Fix Azure OpenAI endpoint double /v1 issue

Co-authored-by: Siumauricio <47042324+Siumauricio@users.noreply.github.com>
This commit is contained in:
copilot-swe-agent[bot]
2025-12-20 06:43:20 +00:00
parent 53f67c6eb2
commit 0af6dc3fc2
2 changed files with 43 additions and 5 deletions

View File

@@ -58,23 +58,43 @@ export const aiRouter = createTRPCRouter({
const providerName = getProviderName(input.apiUrl);
const headers = getProviderHeaders(input.apiUrl, input.apiKey);
let response = null;
let apiUrl = input.apiUrl;
switch (providerName) {
case "ollama":
response = await fetch(`${input.apiUrl}/api/tags`, { headers });
response = await fetch(`${apiUrl}/api/tags`, { headers });
break;
case "gemini":
response = await fetch(
`${input.apiUrl}/models?key=${encodeURIComponent(input.apiKey)}`,
`${apiUrl}/models?key=${encodeURIComponent(input.apiKey)}`,
{ headers: {} },
);
break;
case "azure":
// Azure OpenAI uses deployments endpoint
// Remove trailing /openai/v1 or /v1 if present
apiUrl = apiUrl.replace(/\/openai\/v1\/?$/, "");
apiUrl = apiUrl.replace(/\/v1\/?$/, "");
apiUrl = apiUrl.replace(/\/$/, "");
if (!input.apiKey)
throw new TRPCError({
code: "BAD_REQUEST",
message: "API key must contain at least 1 character(s)",
});
// Azure uses deployments endpoint to list models
response = await fetch(
`${apiUrl}/openai/deployments?api-version=2023-05-15`,
{ headers },
);
break;
default:
if (!input.apiKey)
throw new TRPCError({
code: "BAD_REQUEST",
message: "API key must contain at least 1 character(s)",
});
response = await fetch(`${input.apiUrl}/models`, { headers });
response = await fetch(`${apiUrl}/models`, { headers });
}
if (!response.ok) {

View File

@@ -29,11 +29,22 @@ export function selectAIProvider(config: { apiUrl: string; apiKey: string }) {
apiKey: config.apiKey,
baseURL: config.apiUrl,
});
case "azure":
case "azure": {
// Azure OpenAI endpoints should not include /openai/v1 or /v1 at the end
// The SDK handles the path construction internally
let azureBaseUrl = config.apiUrl;
// Remove trailing /openai/v1 if present
azureBaseUrl = azureBaseUrl.replace(/\/openai\/v1\/?$/, "");
// Remove trailing /v1 if present
azureBaseUrl = azureBaseUrl.replace(/\/v1\/?$/, "");
// Remove trailing slash
azureBaseUrl = azureBaseUrl.replace(/\/$/, "");
return createAzure({
apiKey: config.apiKey,
baseURL: config.apiUrl,
baseURL: azureBaseUrl,
});
}
case "anthropic":
return createAnthropic({
apiKey: config.apiKey,
@@ -91,6 +102,13 @@ export const getProviderHeaders = (
apiUrl: string,
apiKey: string,
): Record<string, string> => {
// Azure OpenAI
if (apiUrl.includes("azure.com")) {
return {
"api-key": apiKey,
};
}
// Anthropic
if (apiUrl.includes("anthropic")) {
return {