Skip to content

Commit 24e00b6

Browse files
committed
fix: respect custom OpenRouter URL for all API operations
- Use configured openRouterBaseUrl in image generation instead of hardcoded URL - Dynamically include custom OpenRouter domain in CSP headers - Pass baseUrl to webview hooks for model endpoints fetching - Update useOpenRouterModelProviders hook to use custom baseUrl Fixes #8947
1 parent 4a096e1 commit 24e00b6

File tree

4 files changed

+39
-17
lines changed

4 files changed

+39
-17
lines changed

src/api/providers/openrouter.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -304,7 +304,8 @@ export class OpenRouterHandler extends BaseProvider implements SingleCompletionH
304304
}
305305

306306
try {
307-
const response = await fetch("https://openrouter.ai/api/v1/chat/completions", {
307+
const baseURL = this.options.openRouterBaseUrl || "https://openrouter.ai/api/v1"
308+
const response = await fetch(`${baseURL}/chat/completions`, {
308309
method: "POST",
309310
headers: {
310311
Authorization: `Bearer ${apiKey}`,

src/core/webview/ClineProvider.ts

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -785,7 +785,7 @@ export class ClineProvider
785785
webviewView.webview.html =
786786
this.contextProxy.extensionMode === vscode.ExtensionMode.Development
787787
? await this.getHMRHtmlContent(webviewView.webview)
788-
: this.getHtmlContent(webviewView.webview)
788+
: await this.getHtmlContent(webviewView.webview)
789789

790790
// Sets up an event listener to listen for messages passed from the webview view context
791791
// and executes code based on the message that is received.
@@ -1019,6 +1019,12 @@ export class ClineProvider
10191019

10201020
const nonce = getNonce()
10211021

1022+
// Get the OpenRouter base URL from configuration
1023+
const { apiConfiguration } = await this.getState()
1024+
const openRouterBaseUrl = apiConfiguration.openRouterBaseUrl || "https://openrouter.ai"
1025+
// Extract the domain for CSP
1026+
const openRouterDomain = openRouterBaseUrl.match(/^(https?:\/\/[^\/]+)/)?.[1] || "https://openrouter.ai"
1027+
10221028
const stylesUri = getUri(webview, this.contextProxy.extensionUri, [
10231029
"webview-ui",
10241030
"build",
@@ -1055,7 +1061,7 @@ export class ClineProvider
10551061
`img-src ${webview.cspSource} https://storage.googleapis.com https://img.clerk.com data:`,
10561062
`media-src ${webview.cspSource}`,
10571063
`script-src 'unsafe-eval' ${webview.cspSource} https://* https://*.posthog.com http://${localServerUrl} http://0.0.0.0:${localPort} 'nonce-${nonce}'`,
1058-
`connect-src ${webview.cspSource} https://* https://*.posthog.com ws://${localServerUrl} ws://0.0.0.0:${localPort} http://${localServerUrl} http://0.0.0.0:${localPort}`,
1064+
`connect-src ${webview.cspSource} ${openRouterDomain} https://* https://*.posthog.com ws://${localServerUrl} ws://0.0.0.0:${localPort} http://${localServerUrl} http://0.0.0.0:${localPort}`,
10591065
]
10601066

10611067
return /*html*/ `
@@ -1094,7 +1100,7 @@ export class ClineProvider
10941100
* @returns A template string literal containing the HTML that should be
10951101
* rendered within the webview panel
10961102
*/
1097-
private getHtmlContent(webview: vscode.Webview): string {
1103+
private async getHtmlContent(webview: vscode.Webview): Promise<string> {
10981104
// Get the local path to main script run in the webview,
10991105
// then convert it to a uri we can use in the webview.
11001106

@@ -1129,6 +1135,12 @@ export class ClineProvider
11291135
*/
11301136
const nonce = getNonce()
11311137

1138+
// Get the OpenRouter base URL from configuration
1139+
const { apiConfiguration } = await this.getState()
1140+
const openRouterBaseUrl = apiConfiguration.openRouterBaseUrl || "https://openrouter.ai"
1141+
// Extract the domain for CSP
1142+
const openRouterDomain = openRouterBaseUrl.match(/^(https?:\/\/[^\/]+)/)?.[1] || "https://openrouter.ai"
1143+
11321144
// Tip: Install the es6-string-html VS Code extension to enable code highlighting below
11331145
return /*html*/ `
11341146
<!DOCTYPE html>
@@ -1137,7 +1149,7 @@ export class ClineProvider
11371149
<meta charset="utf-8">
11381150
<meta name="viewport" content="width=device-width,initial-scale=1,shrink-to-fit=no">
11391151
<meta name="theme-color" content="#000000">
1140-
<meta http-equiv="Content-Security-Policy" content="default-src 'none'; font-src ${webview.cspSource} data:; style-src ${webview.cspSource} 'unsafe-inline'; img-src ${webview.cspSource} https://storage.googleapis.com https://img.clerk.com data:; media-src ${webview.cspSource}; script-src ${webview.cspSource} 'wasm-unsafe-eval' 'nonce-${nonce}' https://us-assets.i.posthog.com 'strict-dynamic'; connect-src ${webview.cspSource} https://openrouter.ai https://api.requesty.ai https://us.i.posthog.com https://us-assets.i.posthog.com;">
1152+
<meta http-equiv="Content-Security-Policy" content="default-src 'none'; font-src ${webview.cspSource} data:; style-src ${webview.cspSource} 'unsafe-inline'; img-src ${webview.cspSource} https://storage.googleapis.com https://img.clerk.com data:; media-src ${webview.cspSource}; script-src ${webview.cspSource} 'wasm-unsafe-eval' 'nonce-${nonce}' https://us-assets.i.posthog.com 'strict-dynamic'; connect-src ${webview.cspSource} ${openRouterDomain} https://api.requesty.ai https://us.i.posthog.com https://us-assets.i.posthog.com;">
11411153
<link rel="stylesheet" type="text/css" href="${stylesUri}">
11421154
<link href="${codiconsUri}" rel="stylesheet" />
11431155
<script nonce="${nonce}">

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

Lines changed: 11 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -192,13 +192,17 @@ const ApiOptions = ({
192192

193193
const { data: routerModels, refetch: refetchRouterModels } = useRouterModels()
194194

195-
const { data: openRouterModelProviders } = useOpenRouterModelProviders(apiConfiguration?.openRouterModelId, {
196-
enabled:
197-
!!apiConfiguration?.openRouterModelId &&
198-
routerModels?.openrouter &&
199-
Object.keys(routerModels.openrouter).length > 1 &&
200-
apiConfiguration.openRouterModelId in routerModels.openrouter,
201-
})
195+
const { data: openRouterModelProviders } = useOpenRouterModelProviders(
196+
apiConfiguration?.openRouterModelId,
197+
apiConfiguration?.openRouterBaseUrl,
198+
{
199+
enabled:
200+
!!apiConfiguration?.openRouterModelId &&
201+
routerModels?.openrouter &&
202+
Object.keys(routerModels.openrouter).length > 1 &&
203+
apiConfiguration.openRouterModelId in routerModels.openrouter,
204+
},
205+
)
202206

203207
// Update `apiModelId` whenever `selectedModelId` changes.
204208
useEffect(() => {

webview-ui/src/components/ui/hooks/useOpenRouterModelProviders.ts

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -43,11 +43,12 @@ type OpenRouterModelProvider = ModelInfo & {
4343
label: string
4444
}
4545

46-
async function getOpenRouterProvidersForModel(modelId: string) {
46+
async function getOpenRouterProvidersForModel(modelId: string, baseUrl?: string) {
4747
const models: Record<string, OpenRouterModelProvider> = {}
4848

4949
try {
50-
const response = await axios.get(`https://openrouter.ai/api/v1/models/${modelId}/endpoints`)
50+
const apiBaseUrl = baseUrl || "https://openrouter.ai/api/v1"
51+
const response = await axios.get(`${apiBaseUrl}/models/${modelId}/endpoints`)
5152
const result = openRouterEndpointsSchema.safeParse(response.data)
5253

5354
if (!result.success) {
@@ -100,9 +101,13 @@ type UseOpenRouterModelProvidersOptions = Omit<
100101
"queryKey" | "queryFn"
101102
>
102103

103-
export const useOpenRouterModelProviders = (modelId?: string, options?: UseOpenRouterModelProvidersOptions) =>
104+
export const useOpenRouterModelProviders = (
105+
modelId?: string,
106+
baseUrl?: string,
107+
options?: UseOpenRouterModelProvidersOptions,
108+
) =>
104109
useQuery<Record<string, OpenRouterModelProvider>>({
105-
queryKey: ["openrouter-model-providers", modelId],
106-
queryFn: () => (modelId ? getOpenRouterProvidersForModel(modelId) : {}),
110+
queryKey: ["openrouter-model-providers", modelId, baseUrl],
111+
queryFn: () => (modelId ? getOpenRouterProvidersForModel(modelId, baseUrl) : {}),
107112
...options,
108113
})

0 commit comments

Comments
 (0)