From 9e863fe18175a18247f134f94a975358e2f5dea5 Mon Sep 17 00:00:00 2001 From: Ajax Davis Date: Thu, 4 Dec 2025 13:22:23 +1000 Subject: [PATCH] fix: make OPENAI_API_KEY optional for playground to allow client-provided keys MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Make OPENAI_API_KEY optional in env validation - Move OpenAI client initialization from module level to runtime - Accept API key from client UI (Settings sidebar) or server env - Return clear error message if no API key is provided - Fixes Vercel build failure due to missing env var at build time 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude --- apps/playground/src/app/api/chat/route.ts | 24 ++++++++++++++++++----- apps/playground/src/env.ts | 4 ++-- 2 files changed, 21 insertions(+), 7 deletions(-) diff --git a/apps/playground/src/app/api/chat/route.ts b/apps/playground/src/app/api/chat/route.ts index 390aa4f..5f390ce 100644 --- a/apps/playground/src/app/api/chat/route.ts +++ b/apps/playground/src/app/api/chat/route.ts @@ -10,11 +10,6 @@ export const runtime = 'nodejs'; export const dynamic = 'force-dynamic'; export const maxDuration = 60; -// Initialize OpenAI provider -const openai = createOpenAI({ - apiKey: env.OPENAI_API_KEY, -}); - // Add conversation state tracking (in-memory for MVP) // biome-ignore lint/suspicious/noExplicitAny: Tool types from AI SDK are complex const conversationStates = new Map }>(); @@ -35,6 +30,25 @@ export async function POST(request: NextRequest) { console.log(`🔑 Conversation ID: ${conversationId}`); console.log(`🔐 Client env vars: ${Object.keys(clientEnv).length} keys`); + // Initialize OpenAI with client-provided or server API key + const apiKey = clientEnv.OPENAI_API_KEY || env.OPENAI_API_KEY; + if (!apiKey) { + return new Response( + JSON.stringify({ + success: false, + error: 'OPENAI_API_KEY is required. Please add it in the Settings sidebar.', + }), + { + status: 400, + headers: { 'Content-Type': 'application/json' }, + } + ); + } + + const openai = createOpenAI({ + apiKey, + }); + // Get or create conversation state if (!conversationStates.has(conversationId)) { console.log('✨ Creating new conversation state'); diff --git a/apps/playground/src/env.ts b/apps/playground/src/env.ts index 5734390..549852c 100644 --- a/apps/playground/src/env.ts +++ b/apps/playground/src/env.ts @@ -2,6 +2,6 @@ import { createEnv } from '@tpmjs/env'; import { z } from 'zod'; export const env = createEnv({ - // Server-only - OPENAI_API_KEY: z.string().min(1), + // Server-only (optional for playground - can be provided by client UI) + OPENAI_API_KEY: z.string().min(1).optional(), });