From aaee77fb4701ee257e7b439ce8a795fd9aa6144d Mon Sep 17 00:00:00 2001 From: "Jace Medlin (AIM Consulting Addison Group)" Date: Wed, 29 Apr 2026 02:29:31 -0500 Subject: [PATCH 1/6] No longer hardcoding models Co-authored-by: Copilot --- apps/promptions-chat/.env.example | 3 +++ apps/promptions-chat/src/services/ChatService.ts | 12 ++++++++++-- apps/promptions-chat/src/vite-env.d.ts | 3 +++ 3 files changed, 16 insertions(+), 2 deletions(-) diff --git a/apps/promptions-chat/.env.example b/apps/promptions-chat/.env.example index 19d97c9..6a4c82e 100644 --- a/apps/promptions-chat/.env.example +++ b/apps/promptions-chat/.env.example @@ -1,2 +1,5 @@ # Copy this file to .env and add your OpenAI API key VITE_OPENAI_API_KEY=your_openai_api_key_here +VITE_OPENAI_BASE_URL=your_openai_base_url_here +VITE_OPENAI_API_VERSION=2024-12-01-preview +VITE_OPENAI_MODEL=gpt-4.1-mini diff --git a/apps/promptions-chat/src/services/ChatService.ts b/apps/promptions-chat/src/services/ChatService.ts index a60c3f4..8fc9845 100644 --- a/apps/promptions-chat/src/services/ChatService.ts +++ b/apps/promptions-chat/src/services/ChatService.ts @@ -7,6 +7,7 @@ interface ChatMessage { export class ChatService { private client: OpenAI; + private model: string; constructor() { // In a real application, you'd want to handle the API key more securely @@ -19,8 +20,15 @@ export class ChatService { ); } + const baseURL = import.meta.env.VITE_OPENAI_BASE_URL || process.env.OPENAI_BASE_URL; + const apiVersion = import.meta.env.VITE_OPENAI_API_VERSION || process.env.OPENAI_API_VERSION; + this.model = import.meta.env.VITE_OPENAI_MODEL || process.env.OPENAI_MODEL || "gpt-4.1"; + this.client = new OpenAI({ apiKey, + ...(baseURL ? { baseURL } : {}), + ...(apiVersion ? { defaultQuery: { "api-version": apiVersion } } : {}), + ...(baseURL ? { defaultHeaders: { "api-key": apiKey } } : {}), dangerouslyAllowBrowser: true, // Only for demo purposes - use a backend in production }); } @@ -35,7 +43,7 @@ export class ChatService { try { const stream = await this.client.chat.completions.create( { - model: "gpt-4.1", + model: this.model, messages: messages as OpenAI.Chat.Completions.ChatCompletionMessageParam[], stream: true, temperature: 0.7, @@ -64,7 +72,7 @@ export class ChatService { async sendMessage(messages: ChatMessage[]): Promise { try { const response = await this.client.chat.completions.create({ - model: "gpt-3.5-turbo", + model: this.model, messages: messages as OpenAI.Chat.Completions.ChatCompletionMessageParam[], temperature: 0.7, max_tokens: 1000, diff --git a/apps/promptions-chat/src/vite-env.d.ts b/apps/promptions-chat/src/vite-env.d.ts index c8d8de6..e7a0439 100644 --- a/apps/promptions-chat/src/vite-env.d.ts +++ b/apps/promptions-chat/src/vite-env.d.ts @@ -2,6 +2,9 @@ interface ImportMetaEnv { readonly VITE_OPENAI_API_KEY: string; + readonly VITE_OPENAI_BASE_URL?: string; + readonly VITE_OPENAI_API_VERSION?: string; + readonly VITE_OPENAI_MODEL?: string; // more env variables... } From 5fbf623a5ecbbb1068dc28ebd310e045ffb23b1d Mon Sep 17 00:00:00 2001 From: Jack Williams <4489219+jack-williams@users.noreply.github.com> Date: Thu, 30 Apr 2026 11:28:54 +0200 Subject: [PATCH 2/6] Apply suggestion from @Copilot Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> Signed-off-by: Jack Williams <4489219+jack-williams@users.noreply.github.com> --- apps/promptions-chat/.env.example | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/apps/promptions-chat/.env.example b/apps/promptions-chat/.env.example index 6a4c82e..2789988 100644 --- a/apps/promptions-chat/.env.example +++ b/apps/promptions-chat/.env.example @@ -1,5 +1,9 @@ # Copy this file to .env and add your OpenAI API key VITE_OPENAI_API_KEY=your_openai_api_key_here +# Optional: only set for Azure or other custom OpenAI-compatible endpoints. +# Omit for standard OpenAI API usage. VITE_OPENAI_BASE_URL=your_openai_base_url_here +# Optional: API version is typically Azure-specific/custom-endpoint specific. +# Omit for standard OpenAI API usage. VITE_OPENAI_API_VERSION=2024-12-01-preview VITE_OPENAI_MODEL=gpt-4.1-mini From 5f5327bf2fd884d83a0dd019f0dab8d48cd34129 Mon Sep 17 00:00:00 2001 From: Jack Williams Date: Thu, 30 Apr 2026 12:17:17 +0200 Subject: [PATCH 3/6] Use AzureOpenAI client for Azure endpoints Replace manual headers/defaultQuery hacks on the base OpenAI client with the dedicated AzureOpenAI client when a baseURL is configured. This avoids sending the API key twice (once via apiKey -> Authorization, once via defaultHeaders.api-key) and uses the SDK's supported Azure auth path. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- .../src/services/ChatService.ts | 20 +++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) diff --git a/apps/promptions-chat/src/services/ChatService.ts b/apps/promptions-chat/src/services/ChatService.ts index 8fc9845..fc5bc1a 100644 --- a/apps/promptions-chat/src/services/ChatService.ts +++ b/apps/promptions-chat/src/services/ChatService.ts @@ -1,4 +1,4 @@ -import OpenAI from "openai"; +import OpenAI, { AzureOpenAI } from "openai"; interface ChatMessage { role: "user" | "assistant" | "system"; @@ -24,13 +24,17 @@ export class ChatService { const apiVersion = import.meta.env.VITE_OPENAI_API_VERSION || process.env.OPENAI_API_VERSION; this.model = import.meta.env.VITE_OPENAI_MODEL || process.env.OPENAI_MODEL || "gpt-4.1"; - this.client = new OpenAI({ - apiKey, - ...(baseURL ? { baseURL } : {}), - ...(apiVersion ? { defaultQuery: { "api-version": apiVersion } } : {}), - ...(baseURL ? { defaultHeaders: { "api-key": apiKey } } : {}), - dangerouslyAllowBrowser: true, // Only for demo purposes - use a backend in production - }); + this.client = baseURL + ? new AzureOpenAI({ + apiKey, + endpoint: baseURL, + apiVersion, + dangerouslyAllowBrowser: true, // Only for demo purposes - use a backend in production + }) + : new OpenAI({ + apiKey, + dangerouslyAllowBrowser: true, // Only for demo purposes - use a backend in production + }); } async streamChat( From 07920a3d8a582c32c847c4fecddb6320d0ef3415 Mon Sep 17 00:00:00 2001 From: Jack Williams Date: Thu, 30 Apr 2026 12:22:15 +0200 Subject: [PATCH 4/6] Remove process.env fallbacks in ChatService Vite's vite.config.ts defines process.env as {}, so process.env.OPENAI_* references were inlined as undefined at build time and never did anything. Drop the dead fallbacks and read configuration only from import.meta.env.VITE_OPENAI_*, which is the supported way to surface env vars to a Vite client bundle. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- apps/promptions-chat/src/services/ChatService.ts | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/apps/promptions-chat/src/services/ChatService.ts b/apps/promptions-chat/src/services/ChatService.ts index fc5bc1a..e0bcc43 100644 --- a/apps/promptions-chat/src/services/ChatService.ts +++ b/apps/promptions-chat/src/services/ChatService.ts @@ -12,7 +12,7 @@ export class ChatService { constructor() { // In a real application, you'd want to handle the API key more securely // For development, you can set VITE_OPENAI_API_KEY in your .env file - const apiKey = import.meta.env.VITE_OPENAI_API_KEY || process.env.OPENAI_API_KEY; + const apiKey = import.meta.env.VITE_OPENAI_API_KEY; if (!apiKey) { throw new Error( @@ -20,9 +20,9 @@ export class ChatService { ); } - const baseURL = import.meta.env.VITE_OPENAI_BASE_URL || process.env.OPENAI_BASE_URL; - const apiVersion = import.meta.env.VITE_OPENAI_API_VERSION || process.env.OPENAI_API_VERSION; - this.model = import.meta.env.VITE_OPENAI_MODEL || process.env.OPENAI_MODEL || "gpt-4.1"; + const baseURL = import.meta.env.VITE_OPENAI_BASE_URL; + const apiVersion = import.meta.env.VITE_OPENAI_API_VERSION; + this.model = import.meta.env.VITE_OPENAI_MODEL || "gpt-4.1"; this.client = baseURL ? new AzureOpenAI({ From e73bd12725a8b3b1e7c999e648be524a2d3701f1 Mon Sep 17 00:00:00 2001 From: Jack Williams Date: Thu, 30 Apr 2026 12:29:49 +0200 Subject: [PATCH 5/6] Document optional VITE_OPENAI_* config and tidy .env.example Comment out optional VITE_OPENAI_BASE_URL / _API_VERSION / _MODEL placeholders in .env.example so a copied file does not silently activate the Azure OpenAI client with a bogus endpoint, and align the example model with the code default (gpt-4.1). Add an Optional configuration section to the README documenting the new env vars used by the chat app. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- README.md | 12 ++++++++++++ apps/promptions-chat/.env.example | 7 ++++--- 2 files changed, 16 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index a315c52..8aee176 100644 --- a/README.md +++ b/README.md @@ -122,6 +122,18 @@ $env:VITE_OPENAI_API_KEY="your_openai_api_key_here" ; yarn workspace @promptions $env:VITE_OPENAI_API_KEY="your_openai_api_key_here" ; yarn workspace @promptions/promptions-image dev ``` +#### Optional configuration (chat app) + +The chat app reads these additional `VITE_*` variables from `apps/promptions-chat/.env`. They're all optional — leave them unset to use the standard OpenAI API. + +| Variable | Description | Default | +| ------------------------- | ----------------------------------------------------------------------------------- | --------- | +| `VITE_OPENAI_MODEL` | Model used for chat completions. | `gpt-4.1` | +| `VITE_OPENAI_BASE_URL` | Custom endpoint. Set this to use Azure OpenAI or another OpenAI-compatible service. | _(unset)_ | +| `VITE_OPENAI_API_VERSION` | API version. Required when `VITE_OPENAI_BASE_URL` points at Azure OpenAI. | _(unset)_ | + +When `VITE_OPENAI_BASE_URL` is set, the app uses the Azure OpenAI client; otherwise it uses the standard OpenAI client. + Start the dev servers: - Chat application (http://localhost:3003): diff --git a/apps/promptions-chat/.env.example b/apps/promptions-chat/.env.example index 2789988..0195cd5 100644 --- a/apps/promptions-chat/.env.example +++ b/apps/promptions-chat/.env.example @@ -2,8 +2,9 @@ VITE_OPENAI_API_KEY=your_openai_api_key_here # Optional: only set for Azure or other custom OpenAI-compatible endpoints. # Omit for standard OpenAI API usage. -VITE_OPENAI_BASE_URL=your_openai_base_url_here +# VITE_OPENAI_BASE_URL=https://your-resource.openai.azure.com # Optional: API version is typically Azure-specific/custom-endpoint specific. # Omit for standard OpenAI API usage. -VITE_OPENAI_API_VERSION=2024-12-01-preview -VITE_OPENAI_MODEL=gpt-4.1-mini +# VITE_OPENAI_API_VERSION=2024-12-01-preview +# Optional: override the model used for chat completions (defaults to gpt-4.1). +# VITE_OPENAI_MODEL=gpt-4.1 From 40085f1270ddd8ccb4ca8bc2dff83de2f093903a Mon Sep 17 00:00:00 2001 From: Jack Williams Date: Thu, 30 Apr 2026 12:34:42 +0200 Subject: [PATCH 6/6] Port chat-app config changes to image app Apply the same fixes to apps/promptions-image: - Drop the dead process.env.OPENAI_API_KEY fallback (Vite defines process.env as {} so it never resolved). - Read optional VITE_OPENAI_BASE_URL / _API_VERSION / _MODEL from import.meta.env, with the same AzureOpenAI client switch when a base URL is configured. - Use the configured chat model in streamChat instead of the hardcoded gpt-4.1. - Mirror the .env.example layout (commented-out optional vars) so copying it does not silently activate the Azure path with a placeholder URL. - Update vite-env.d.ts with the new optional types. Generalize the README Optional configuration section to cover both apps. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- README.md | 8 +++--- apps/promptions-image/.env.example | 9 +++++++ .../src/services/ImageService.ts | 26 ++++++++++++++----- apps/promptions-image/src/vite-env.d.ts | 23 +++++++++------- 4 files changed, 45 insertions(+), 21 deletions(-) diff --git a/README.md b/README.md index 8aee176..a0a8c9a 100644 --- a/README.md +++ b/README.md @@ -122,17 +122,17 @@ $env:VITE_OPENAI_API_KEY="your_openai_api_key_here" ; yarn workspace @promptions $env:VITE_OPENAI_API_KEY="your_openai_api_key_here" ; yarn workspace @promptions/promptions-image dev ``` -#### Optional configuration (chat app) +#### Optional configuration -The chat app reads these additional `VITE_*` variables from `apps/promptions-chat/.env`. They're all optional — leave them unset to use the standard OpenAI API. +Both apps read these additional `VITE_*` variables from their respective `.env` files. They're all optional — leave them unset to use the standard OpenAI API. | Variable | Description | Default | | ------------------------- | ----------------------------------------------------------------------------------- | --------- | -| `VITE_OPENAI_MODEL` | Model used for chat completions. | `gpt-4.1` | +| `VITE_OPENAI_MODEL` | Chat model used for completions. The image-generation model is selected in the UI. | `gpt-4.1` | | `VITE_OPENAI_BASE_URL` | Custom endpoint. Set this to use Azure OpenAI or another OpenAI-compatible service. | _(unset)_ | | `VITE_OPENAI_API_VERSION` | API version. Required when `VITE_OPENAI_BASE_URL` points at Azure OpenAI. | _(unset)_ | -When `VITE_OPENAI_BASE_URL` is set, the app uses the Azure OpenAI client; otherwise it uses the standard OpenAI client. +When `VITE_OPENAI_BASE_URL` is set, the apps use the Azure OpenAI client; otherwise they use the standard OpenAI client. Start the dev servers: diff --git a/apps/promptions-image/.env.example b/apps/promptions-image/.env.example index 19d97c9..0cbf61f 100644 --- a/apps/promptions-image/.env.example +++ b/apps/promptions-image/.env.example @@ -1,2 +1,11 @@ # Copy this file to .env and add your OpenAI API key VITE_OPENAI_API_KEY=your_openai_api_key_here +# Optional: only set for Azure or other custom OpenAI-compatible endpoints. +# Omit for standard OpenAI API usage. +# VITE_OPENAI_BASE_URL=https://your-resource.openai.azure.com +# Optional: API version is typically Azure-specific/custom-endpoint specific. +# Omit for standard OpenAI API usage. +# VITE_OPENAI_API_VERSION=2024-12-01-preview +# Optional: override the chat model used for prompt-related completions (defaults to gpt-4.1). +# The image generation model itself is selected in the UI. +# VITE_OPENAI_MODEL=gpt-4.1 diff --git a/apps/promptions-image/src/services/ImageService.ts b/apps/promptions-image/src/services/ImageService.ts index 533e32f..142958e 100644 --- a/apps/promptions-image/src/services/ImageService.ts +++ b/apps/promptions-image/src/services/ImageService.ts @@ -1,11 +1,12 @@ -import OpenAI from "openai"; +import OpenAI, { AzureOpenAI } from "openai"; import { ImageGenerationParams, GeneratedImage } from "../types"; export class ImageService { private client: OpenAI; + private chatModel: string; constructor() { - const apiKey = import.meta.env.VITE_OPENAI_API_KEY || process.env.OPENAI_API_KEY; + const apiKey = import.meta.env.VITE_OPENAI_API_KEY; if (!apiKey) { throw new Error( @@ -13,10 +14,21 @@ export class ImageService { ); } - this.client = new OpenAI({ - apiKey, - dangerouslyAllowBrowser: true, // Only for demo purposes - use a backend in production - }); + const baseURL = import.meta.env.VITE_OPENAI_BASE_URL; + const apiVersion = import.meta.env.VITE_OPENAI_API_VERSION; + this.chatModel = import.meta.env.VITE_OPENAI_MODEL || "gpt-4.1"; + + this.client = baseURL + ? new AzureOpenAI({ + apiKey, + endpoint: baseURL, + apiVersion, + dangerouslyAllowBrowser: true, // Only for demo purposes - use a backend in production + }) + : new OpenAI({ + apiKey, + dangerouslyAllowBrowser: true, // Only for demo purposes - use a backend in production + }); } async generateImage(params: ImageGenerationParams, options?: { signal?: AbortSignal }): Promise { @@ -61,7 +73,7 @@ export class ImageService { try { const stream = await this.client.chat.completions.create( { - model: "gpt-4.1", + model: this.chatModel, messages: messages as OpenAI.Chat.Completions.ChatCompletionMessageParam[], stream: true, temperature: 0.7, diff --git a/apps/promptions-image/src/vite-env.d.ts b/apps/promptions-image/src/vite-env.d.ts index c8d8de6..f77a8c0 100644 --- a/apps/promptions-image/src/vite-env.d.ts +++ b/apps/promptions-image/src/vite-env.d.ts @@ -1,10 +1,13 @@ -/// - -interface ImportMetaEnv { - readonly VITE_OPENAI_API_KEY: string; - // more env variables... -} - -interface ImportMeta { - readonly env: ImportMetaEnv; -} +/// + +interface ImportMetaEnv { + readonly VITE_OPENAI_API_KEY: string; + readonly VITE_OPENAI_BASE_URL?: string; + readonly VITE_OPENAI_API_VERSION?: string; + readonly VITE_OPENAI_MODEL?: string; + // more env variables... +} + +interface ImportMeta { + readonly env: ImportMetaEnv; +}