Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 15 additions & 0 deletions packages/openai-adapters/src/apis/Azure.ts
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,10 @@ export class AzureApi extends OpenAIApi {
return apiType === "azure-openai" || apiType === "azure";
}

private _isAzureFoundry(apiType?: string): boolean {
return apiType === "azure-foundry";
}

private _getAzureBaseURL(config: z.infer<typeof AzureConfigSchema>): {
baseURL: string;
defaultQuery: Record<string, string>;
Expand All @@ -50,6 +54,17 @@ export class AzureApi extends OpenAIApi {
url.pathname = url.pathname.replace(/\/$/, ""); // Remove trailing slash if present
url.search = ""; // Clear original search params

// Azure AI Foundry (a.k.a. Microsoft Foundry / Azure serverless) uses an
// OpenAI-compatible routing path (`/openai/v1/...`) that the user supplies
// in apiBase. We must NOT append `/openai/deployments/{deployment}` like the
// legacy Azure OpenAI Service path — doing so 404s on Foundry endpoints.
if (this._isAzureFoundry(config.env?.apiType)) {
return {
baseURL: url.toString(),
defaultQuery: queryParams,
};
}

// Default is `azure-openai` in docs, but previously was `azure`
if (this._isAzureOpenAI(config.env?.apiType)) {
if (!config.env?.deployment) {
Expand Down
32 changes: 32 additions & 0 deletions packages/openai-adapters/src/test/main.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -330,6 +330,38 @@ describe("Configuration", () => {
expect((azure as OpenAIApi).openai.apiKey).toBe("sk-xxx");
});

it("should configure Azure AI Foundry client without appending /openai/deployments/{deployment}", () => {
const azure = constructLlmApi({
provider: "azure",
apiKey: "sk-xxx",
apiBase: "https://my-resource.services.ai.azure.com/openai/v1",
env: {
apiType: "azure-foundry",
},
});

// Azure AI Foundry endpoints use the apiBase as-is (OpenAI-compatible
// routing path supplied by the user). Appending /openai/deployments/{deployment}
// would 404 because Foundry does not expose that legacy path.
expect((azure as OpenAIApi).openai.baseURL).toBe(
"https://my-resource.services.ai.azure.com/openai/v1",
);
expect((azure as OpenAIApi).openai.apiKey).toBe("sk-xxx");
});

it("should not require env.deployment or env.apiVersion for Azure AI Foundry", () => {
expect(() =>
constructLlmApi({
provider: "azure",
apiKey: "sk-xxx",
apiBase: "https://my-resource.services.ai.azure.com/openai/v1",
env: {
apiType: "azure-foundry",
},
}),
).not.toThrow();
});

describe("ollama api base", () => {
it('should have correct default API base for "ollama"', () => {
const ollama = constructLlmApi({
Expand Down
Loading