Address code review feedback: Improve URL normalization and remove duplication

Co-authored-by: Siumauricio <47042324+Siumauricio@users.noreply.github.com>
This commit is contained in:
copilot-swe-agent[bot]
2025-12-20 06:48:47 +00:00
parent 2f9987970a
commit 136edfd4c5
3 changed files with 25 additions and 18 deletions

View File

@@ -60,4 +60,12 @@ describe("Azure OpenAI URL Normalization", () => {
// Should only strip trailing /v1, not /v1 in the middle
expect(result).toBe("https://workspacename.openai.azure.com/v1/something");
});
it("should handle edge case with multiple trailing /v1", () => {
const input = "https://workspacename.openai.azure.com/openai/v1/v1";
const result = normalizeAzureUrl(input);
// Should only strip the last /v1
expect(result).toBe("https://workspacename.openai.azure.com/openai/v1");
});
});

View File

@@ -61,6 +61,18 @@ export const aiRouter = createTRPCRouter({
let response = null;
let apiUrl = input.apiUrl;
// Validate API key for providers that require it
if (
providerName !== "ollama" &&
providerName !== "gemini" &&
!input.apiKey
) {
throw new TRPCError({
code: "BAD_REQUEST",
message: "API key must contain at least 1 character(s)",
});
}
switch (providerName) {
case "ollama":
response = await fetch(`${apiUrl}/api/tags`, { headers });
@@ -76,11 +88,6 @@ export const aiRouter = createTRPCRouter({
// Normalize the URL to remove trailing /openai/v1 or /v1
apiUrl = normalizeAzureUrl(apiUrl);
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`,
@@ -88,11 +95,6 @@ export const aiRouter = createTRPCRouter({
);
break;
default:
if (!input.apiKey)
throw new TRPCError({
code: "BAD_REQUEST",
message: "API key must contain at least 1 character(s)",
});
response = await fetch(`${apiUrl}/models`, { headers });
}

View File

@@ -13,14 +13,11 @@ import { createOllama } from "ai-sdk-ollama";
* to avoid duplicate paths in the final URL (e.g., /v1/v1/chat/completions)
*/
export function normalizeAzureUrl(url: string): string {
let normalized = url;
// Remove trailing /openai/v1 if present
normalized = normalized.replace(/\/openai\/v1\/?$/, "");
// Remove trailing /v1 if present
normalized = normalized.replace(/\/v1\/?$/, "");
// Remove trailing slash
normalized = normalized.replace(/\/$/, "");
return normalized;
// Use a single regex to handle all variations in one pass
// This matches: /openai/v1 or /v1 at the end, with optional trailing slash
let normalized = url.replace(/\/(?:openai\/v1|v1)\/?$/, "");
// Remove any remaining trailing slash
return normalized.replace(/\/$/, "");
}
export function getProviderName(apiUrl: string) {