Skip to content

Commit 6611564

Browse files
committed
Add the option to use a custom Host header for openai-compatible
1 parent 06e0fc6 commit 6611564

File tree

21 files changed

+74
-6
lines changed

21 files changed

+74
-6
lines changed

src/api/providers/openai.ts

Lines changed: 23 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -55,10 +55,20 @@ export class OpenAiHandler extends BaseProvider implements SingleCompletionHandl
5555
baseURL,
5656
apiKey,
5757
apiVersion: this.options.azureApiVersion || azureOpenAiDefaultApiVersion,
58-
defaultHeaders,
58+
defaultHeaders: {
59+
...defaultHeaders,
60+
...(this.options.openAiHostHeader ? { Host: this.options.openAiHostHeader } : {}),
61+
},
5962
})
6063
} else {
61-
this.client = new OpenAI({ baseURL, apiKey, defaultHeaders })
64+
this.client = new OpenAI({
65+
baseURL,
66+
apiKey,
67+
defaultHeaders: {
68+
...defaultHeaders,
69+
...(this.options.openAiHostHeader ? { Host: this.options.openAiHostHeader } : {}),
70+
},
71+
})
6272
}
6373
}
6474

@@ -328,7 +338,7 @@ export class OpenAiHandler extends BaseProvider implements SingleCompletionHandl
328338
}
329339
}
330340

331-
export async function getOpenAiModels(baseUrl?: string, apiKey?: string) {
341+
export async function getOpenAiModels(baseUrl?: string, apiKey?: string, hostHeader?: string) {
332342
try {
333343
if (!baseUrl) {
334344
return []
@@ -339,9 +349,18 @@ export async function getOpenAiModels(baseUrl?: string, apiKey?: string) {
339349
}
340350

341351
const config: Record<string, any> = {}
352+
const headers: Record<string, string> = {}
342353

343354
if (apiKey) {
344-
config["headers"] = { Authorization: `Bearer ${apiKey}` }
355+
headers["Authorization"] = `Bearer ${apiKey}`
356+
}
357+
358+
if (hostHeader) {
359+
headers["Host"] = hostHeader
360+
}
361+
362+
if (Object.keys(headers).length > 0) {
363+
config["headers"] = headers
345364
}
346365

347366
const response = await axios.get(`${baseUrl}/models`, config)

src/core/webview/webviewMessageHandler.ts

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -423,7 +423,11 @@ export const webviewMessageHandler = async (provider: ClineProvider, message: We
423423
break
424424
case "refreshOpenAiModels":
425425
if (message?.values?.baseUrl && message?.values?.apiKey) {
426-
const openAiModels = await getOpenAiModels(message?.values?.baseUrl, message?.values?.apiKey)
426+
const openAiModels = await getOpenAiModels(
427+
message?.values?.baseUrl,
428+
message?.values?.apiKey,
429+
message?.values?.hostHeader,
430+
)
427431
provider.postMessageToWebview({ type: "openAiModels", openAiModels })
428432
}
429433

src/exports/roo-code.d.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,7 @@ type ProviderSettings = {
8686
vertexRegion?: string | undefined
8787
openAiBaseUrl?: string | undefined
8888
openAiApiKey?: string | undefined
89+
openAiHostHeader?: string | undefined
8990
openAiR1FormatEnabled?: boolean | undefined
9091
openAiModelId?: string | undefined
9192
openAiCustomModelInfo?:

src/exports/types.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,7 @@ type ProviderSettings = {
8787
vertexRegion?: string | undefined
8888
openAiBaseUrl?: string | undefined
8989
openAiApiKey?: string | undefined
90+
openAiHostHeader?: string | undefined
9091
openAiR1FormatEnabled?: boolean | undefined
9192
openAiModelId?: string | undefined
9293
openAiCustomModelInfo?:

src/schemas/index.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -338,6 +338,7 @@ export const providerSettingsSchema = z.object({
338338
// OpenAI
339339
openAiBaseUrl: z.string().optional(),
340340
openAiApiKey: z.string().optional(),
341+
openAiHostHeader: z.string().optional(),
341342
openAiR1FormatEnabled: z.boolean().optional(),
342343
openAiModelId: z.string().optional(),
343344
openAiCustomModelInfo: modelInfoSchema.nullish(),
@@ -431,6 +432,7 @@ const providerSettingsRecord: ProviderSettingsRecord = {
431432
// OpenAI
432433
openAiBaseUrl: undefined,
433434
openAiApiKey: undefined,
435+
openAiHostHeader: undefined,
434436
openAiR1FormatEnabled: undefined,
435437
openAiModelId: undefined,
436438
openAiCustomModelInfo: undefined,

webview-ui/src/components/settings/ApiOptions.tsx

Lines changed: 27 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -103,6 +103,7 @@ const ApiOptions = ({
103103
const [anthropicBaseUrlSelected, setAnthropicBaseUrlSelected] = useState(!!apiConfiguration?.anthropicBaseUrl)
104104
const [azureApiVersionSelected, setAzureApiVersionSelected] = useState(!!apiConfiguration?.azureApiVersion)
105105
const [openRouterBaseUrlSelected, setOpenRouterBaseUrlSelected] = useState(!!apiConfiguration?.openRouterBaseUrl)
106+
const [openAiHostHeaderSelected, setOpenAiHostHeaderSelected] = useState(!!apiConfiguration?.openAiHostHeader)
106107
const [googleGeminiBaseUrlSelected, setGoogleGeminiBaseUrlSelected] = useState(
107108
!!apiConfiguration?.googleGeminiBaseUrl,
108109
)
@@ -145,7 +146,11 @@ const ApiOptions = ({
145146
} else if (selectedProvider === "openai") {
146147
vscode.postMessage({
147148
type: "refreshOpenAiModels",
148-
values: { baseUrl: apiConfiguration?.openAiBaseUrl, apiKey: apiConfiguration?.openAiApiKey },
149+
values: {
150+
baseUrl: apiConfiguration?.openAiBaseUrl,
151+
apiKey: apiConfiguration?.openAiApiKey,
152+
hostHeader: apiConfiguration?.openAiHostHeader,
153+
},
149154
})
150155
} else if (selectedProvider === "ollama") {
151156
vscode.postMessage({ type: "requestOllamaModels", text: apiConfiguration?.ollamaBaseUrl })
@@ -764,6 +769,27 @@ const ApiOptions = ({
764769
className="w-full">
765770
<label className="block font-medium mb-1">{t("settings:providers.openAiApiKey")}</label>
766771
</VSCodeTextField>
772+
<div>
773+
<Checkbox
774+
checked={openAiHostHeaderSelected}
775+
onChange={(checked: boolean) => {
776+
setOpenAiHostHeaderSelected(checked)
777+
778+
if (!checked) {
779+
setApiConfigurationField("openAiHostHeader", "")
780+
}
781+
}}>
782+
{t("settings:providers.useHostHeader")}
783+
</Checkbox>
784+
{openAiHostHeaderSelected && (
785+
<VSCodeTextField
786+
value={apiConfiguration?.openAiHostHeader || ""}
787+
onInput={handleInputChange("openAiHostHeader")}
788+
placeholder="custom-api-hostname.example.com"
789+
className="w-full mt-1"
790+
/>
791+
)}
792+
</div>
767793
<ModelPicker
768794
apiConfiguration={apiConfiguration}
769795
setApiConfigurationField={setApiConfigurationField}

webview-ui/src/i18n/locales/ca/settings.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -105,6 +105,7 @@
105105
"awsCustomArnDesc": "Assegureu-vos que la regió a l'ARN coincideix amb la regió d'AWS seleccionada anteriorment.",
106106
"apiKeyStorageNotice": "Les claus API s'emmagatzemen de forma segura a l'Emmagatzematge Secret de VSCode",
107107
"useCustomBaseUrl": "Utilitzar URL base personalitzada",
108+
"useHostHeader": "Utilitzar capçalera Host personalitzada",
108109
"openRouterTransformsText": "Comprimir prompts i cadenes de missatges a la mida del context (<a>Transformacions d'OpenRouter</a>)",
109110
"model": "Model",
110111
"getOpenRouterApiKey": "Obtenir clau API d'OpenRouter",

webview-ui/src/i18n/locales/de/settings.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -109,6 +109,7 @@
109109
"glamaApiKey": "Glama API-Schlüssel",
110110
"getGlamaApiKey": "Glama API-Schlüssel erhalten",
111111
"useCustomBaseUrl": "Benutzerdefinierte Basis-URL verwenden",
112+
"useHostHeader": "Benutzerdefinierten Host-Header verwenden",
112113
"requestyApiKey": "Requesty API-Schlüssel",
113114
"getRequestyApiKey": "Requesty API-Schlüssel erhalten",
114115
"openRouterTransformsText": "Prompts und Nachrichtenketten auf Kontextgröße komprimieren (<a>OpenRouter Transformationen</a>)",

webview-ui/src/i18n/locales/en/settings.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -109,6 +109,7 @@
109109
"glamaApiKey": "Glama API Key",
110110
"getGlamaApiKey": "Get Glama API Key",
111111
"useCustomBaseUrl": "Use custom base URL",
112+
"useHostHeader": "Use custom Host header",
112113
"requestyApiKey": "Requesty API Key",
113114
"getRequestyApiKey": "Get Requesty API Key",
114115
"openRouterTransformsText": "Compress prompts and message chains to the context size (<a>OpenRouter Transforms</a>)",

webview-ui/src/i18n/locales/es/settings.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -109,6 +109,7 @@
109109
"glamaApiKey": "Clave API de Glama",
110110
"getGlamaApiKey": "Obtener clave API de Glama",
111111
"useCustomBaseUrl": "Usar URL base personalizada",
112+
"useHostHeader": "Usar encabezado Host personalizado",
112113
"requestyApiKey": "Clave API de Requesty",
113114
"getRequestyApiKey": "Obtener clave API de Requesty",
114115
"openRouterTransformsText": "Comprimir prompts y cadenas de mensajes al tamaño del contexto (<a>Transformaciones de OpenRouter</a>)",

0 commit comments

Comments
 (0)