import { registerRequiredSecret } from "@agent-native/core/secrets"; // ── Image generation provider secrets ──────────────────────────────── // Two providers are supported: Gemini (with style reference matching) // and OpenAI gpt-image-2 (excellent text rendering). Neither is strictly // required — slides work without images. If both are set, Gemini is // preferred (it supports reference images natively). // // This file lives OUTSIDE `server/plugins/` on purpose: Nitro's plugin // auto-discovery expects a defineNitroPlugin-shaped default export and // silently skips files that don't match. Keeping the registration as a // side-effect module imported at the top of `server/plugins/agent-chat.ts` // guarantees the registerRequiredSecret() calls run at boot. registerRequiredSecret({ key: "GEMINI_API_KEY", label: "Gemini API Key", description: "Required for image generation with Gemini. Supports style reference matching and up to 4K resolution.", docsUrl: "https://aistudio.google.com/apikey", scope: "user", kind: "api-key", required: false, validator: async (value) => { if (!value) return true; if (typeof value !== "string" || value.length < 20) { return { ok: false, error: "Key looks too short." }; } try { const res = await fetch( `https://generativelanguage.googleapis.com/v1beta/models?key=${value}`, ); if (res.ok) return true; if (res.status === 400 || res.status === 403) return { ok: false, error: "Gemini rejected this key." }; return { ok: false, error: `Gemini returned ${res.status}.` }; } catch (err: any) { return { ok: false, error: `Could not reach Gemini: ${err?.message ?? err}`, }; } }, }); registerRequiredSecret({ key: "OPENAI_API_KEY", label: "OpenAI API Key", description: "Required for image generation with gpt-image-2. Excellent text rendering and photorealistic output.", docsUrl: "https://platform.openai.com/api-keys", scope: "user", kind: "api-key", required: false, validator: async (value) => { if (!value) return true; if (typeof value !== "string" || value.length < 20) { return { ok: false, error: "Key looks too short." }; } try { const res = await fetch("https://api.openai.com/v1/models", { headers: { Authorization: `Bearer ${value}` }, }); if (res.ok) return true; if (res.status === 401) return { ok: false, error: "OpenAI rejected this key (401)." }; return { ok: false, error: `OpenAI returned ${res.status}.` }; } catch (err: any) { return { ok: false, error: `Could not reach OpenAI: ${err?.message ?? err}`, }; } }, }); registerRequiredSecret({ key: "GOOGLE_API_KEY", label: "Google API Key", description: "Required for image search with Google Custom Search.", docsUrl: "https://console.cloud.google.com/apis/credentials", scope: "user", kind: "api-key", required: false, }); registerRequiredSecret({ key: "GOOGLE_SEARCH_CX", label: "Google Search Engine ID", description: "Required with GOOGLE_API_KEY for image search.", docsUrl: "https://programmablesearchengine.google.com/controlpanel/all", scope: "user", kind: "api-key", required: false, }); registerRequiredSecret({ key: "LOGO_DEV_SECRET_KEY", label: "Logo.dev Search Key", description: "Optional server-side key for company and domain logo search.", docsUrl: "https://www.logo.dev/", scope: "user", kind: "api-key", required: false, }); registerRequiredSecret({ key: "LOGO_DEV_TOKEN", label: "Logo.dev Publishable Token", description: "Optional publishable token for rendering Logo.dev images.", docsUrl: "https://www.logo.dev/", scope: "user", kind: "api-key", required: false, }); registerRequiredSecret({ key: "BRANDFETCH_CLIENT_ID", label: "Brandfetch Client ID", description: "Optional public client ID for Brandfetch logo rendering.", docsUrl: "https://developers.brandfetch.com/", scope: "user", kind: "api-key", required: false, }); registerRequiredSecret({ key: "GOOGLE_CLIENT_ID", label: "Google OAuth Client ID", description: "Required for Google Docs import.", docsUrl: "https://console.cloud.google.com/apis/credentials", scope: "user", kind: "api-key", required: false, }); registerRequiredSecret({ key: "GOOGLE_CLIENT_SECRET", label: "Google OAuth Client Secret", description: "Required for Google Docs import.", docsUrl: "https://console.cloud.google.com/apis/credentials", scope: "user", kind: "api-key", required: false, }); registerRequiredSecret({ key: "GOOGLE_PICKER_API_KEY", label: "Google Picker API Key", description: "Required for the Google Docs picker.", docsUrl: "https://console.cloud.google.com/apis/credentials", scope: "user", kind: "api-key", required: false, }); registerRequiredSecret({ key: "GOOGLE_PICKER_APP_ID", label: "Google Picker App ID", description: "Required for the Google Docs picker.", docsUrl: "https://console.cloud.google.com/apis/credentials", scope: "user", kind: "api-key", required: false, });