Skip to content

Commit c8a9668

Browse files
committed
feat(design): support OPENAI_BASE_URL for API calls
1 parent a7593d7 commit c8a9668

9 files changed

Lines changed: 33 additions & 18 deletions

File tree

design/src/auth.ts

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ import fs from "fs";
1111
import path from "path";
1212

1313
const CONFIG_PATH = path.join(process.env.HOME || "~", ".gstack", "openai.json");
14+
const DEFAULT_OPENAI_BASE_URL = "https://api.openai.com/v1";
1415

1516
export function resolveApiKey(): string | null {
1617
// 1. Check ~/.gstack/openai.json
@@ -61,3 +62,17 @@ export function requireApiKey(): string {
6162
}
6263
return key;
6364
}
65+
66+
export function resolveOpenAIBaseUrl(): string {
67+
const baseUrl = process.env.OPENAI_BASE_URL?.trim();
68+
if (!baseUrl) {
69+
return DEFAULT_OPENAI_BASE_URL;
70+
}
71+
72+
return baseUrl.replace(/\/+$/, "");
73+
}
74+
75+
export function openaiUrl(endpoint: string): string {
76+
const normalized = endpoint.startsWith("/") ? endpoint : `/${endpoint}`;
77+
return `${resolveOpenAIBaseUrl()}${normalized}`;
78+
}

design/src/check.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
*/
55

66
import fs from "fs";
7-
import { requireApiKey } from "./auth";
7+
import { openaiUrl, requireApiKey } from "./auth";
88

99
export interface CheckResult {
1010
pass: boolean;
@@ -22,7 +22,7 @@ export async function checkMockup(imagePath: string, brief: string): Promise<Che
2222
const timeout = setTimeout(() => controller.abort(), 60_000);
2323

2424
try {
25-
const response = await fetch("https://api.openai.com/v1/chat/completions", {
25+
const response = await fetch(openaiUrl("/chat/completions"), {
2626
method: "POST",
2727
headers: {
2828
"Authorization": `Bearer ${apiKey}`,

design/src/design-to-code.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
*/
66

77
import fs from "fs";
8-
import { requireApiKey } from "./auth";
8+
import { openaiUrl, requireApiKey } from "./auth";
99
import { readDesignConstraints } from "./memory";
1010

1111
export interface DesignToCodeResult {
@@ -37,7 +37,7 @@ export async function generateDesignToCodePrompt(
3737
? `\n\nExisting DESIGN.md (use these as constraints):\n${designConstraints}`
3838
: "";
3939

40-
const response = await fetch("https://api.openai.com/v1/chat/completions", {
40+
const response = await fetch(openaiUrl("/chat/completions"), {
4141
method: "POST",
4242
headers: {
4343
"Authorization": `Bearer ${apiKey}`,

design/src/diff.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
*/
66

77
import fs from "fs";
8-
import { requireApiKey } from "./auth";
8+
import { openaiUrl, requireApiKey } from "./auth";
99

1010
export interface DiffResult {
1111
differences: { area: string; description: string; severity: string }[];
@@ -28,7 +28,7 @@ export async function diffMockups(
2828
const timeout = setTimeout(() => controller.abort(), 60_000);
2929

3030
try {
31-
const response = await fetch("https://api.openai.com/v1/chat/completions", {
31+
const response = await fetch(openaiUrl("/chat/completions"), {
3232
method: "POST",
3333
headers: {
3434
"Authorization": `Bearer ${apiKey}`,

design/src/evolve.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77

88
import fs from "fs";
99
import path from "path";
10-
import { requireApiKey } from "./auth";
10+
import { openaiUrl, requireApiKey } from "./auth";
1111

1212
export interface EvolveOptions {
1313
screenshot: string; // Path to current site screenshot
@@ -55,7 +55,7 @@ export async function evolve(options: EvolveOptions): Promise<void> {
5555
const timeout = setTimeout(() => controller.abort(), 120_000);
5656

5757
try {
58-
const response = await fetch("https://api.openai.com/v1/responses", {
58+
const response = await fetch(openaiUrl("/responses"), {
5959
method: "POST",
6060
headers: {
6161
"Authorization": `Bearer ${apiKey}`,
@@ -113,7 +113,7 @@ async function analyzeScreenshot(apiKey: string, imageBase64: string): Promise<s
113113
const timeout = setTimeout(() => controller.abort(), 30_000);
114114

115115
try {
116-
const response = await fetch("https://api.openai.com/v1/chat/completions", {
116+
const response = await fetch(openaiUrl("/chat/completions"), {
117117
method: "POST",
118118
headers: {
119119
"Authorization": `Bearer ${apiKey}`,

design/src/generate.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44

55
import fs from "fs";
66
import path from "path";
7-
import { requireApiKey } from "./auth";
7+
import { openaiUrl, requireApiKey } from "./auth";
88
import { parseBrief } from "./brief";
99
import { createSession, sessionPath } from "./session";
1010
import { checkMockup } from "./check";
@@ -40,7 +40,7 @@ async function callImageGeneration(
4040
const timeout = setTimeout(() => controller.abort(), 120_000);
4141

4242
try {
43-
const response = await fetch("https://api.openai.com/v1/responses", {
43+
const response = await fetch(openaiUrl("/responses"), {
4444
method: "POST",
4545
headers: {
4646
"Authorization": `Bearer ${apiKey}`,

design/src/iterate.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88

99
import fs from "fs";
1010
import path from "path";
11-
import { requireApiKey } from "./auth";
11+
import { openaiUrl, requireApiKey } from "./auth";
1212
import { readSession, updateSession } from "./session";
1313

1414
export interface IterateOptions {
@@ -85,7 +85,7 @@ async function callWithThreading(
8585
const timeout = setTimeout(() => controller.abort(), 120_000);
8686

8787
try {
88-
const response = await fetch("https://api.openai.com/v1/responses", {
88+
const response = await fetch(openaiUrl("/responses"), {
8989
method: "POST",
9090
headers: {
9191
"Authorization": `Bearer ${apiKey}`,
@@ -133,7 +133,7 @@ async function callFresh(
133133
const timeout = setTimeout(() => controller.abort(), 120_000);
134134

135135
try {
136-
const response = await fetch("https://api.openai.com/v1/responses", {
136+
const response = await fetch(openaiUrl("/responses"), {
137137
method: "POST",
138138
headers: {
139139
"Authorization": `Bearer ${apiKey}`,

design/src/memory.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313

1414
import fs from "fs";
1515
import path from "path";
16-
import { requireApiKey } from "./auth";
16+
import { openaiUrl, requireApiKey } from "./auth";
1717

1818
export interface ExtractedDesign {
1919
colors: { name: string; hex: string; usage: string }[];
@@ -34,7 +34,7 @@ export async function extractDesignLanguage(imagePath: string): Promise<Extracte
3434
const timeout = setTimeout(() => controller.abort(), 60_000);
3535

3636
try {
37-
const response = await fetch("https://api.openai.com/v1/chat/completions", {
37+
const response = await fetch(openaiUrl("/chat/completions"), {
3838
method: "POST",
3939
headers: {
4040
"Authorization": `Bearer ${apiKey}`,

design/src/variants.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66

77
import fs from "fs";
88
import path from "path";
9-
import { requireApiKey } from "./auth";
9+
import { openaiUrl, requireApiKey } from "./auth";
1010
import { parseBrief } from "./brief";
1111

1212
export interface VariantsOptions {
@@ -54,7 +54,7 @@ async function generateVariant(
5454
const timeout = setTimeout(() => controller.abort(), 120_000);
5555

5656
try {
57-
const response = await fetch("https://api.openai.com/v1/responses", {
57+
const response = await fetch(openaiUrl("/responses"), {
5858
method: "POST",
5959
headers: {
6060
"Authorization": `Bearer ${apiKey}`,

0 commit comments

Comments
 (0)