fix(foundry): preserve bearer auth intent

This commit is contained in:
Vincent Koc
2026-06-11 00:48:42 +09:00
parent 6b0f718b9a
commit 72bfc5e9bf
4 changed files with 18 additions and 2 deletions

View File

@@ -606,6 +606,8 @@ export interface Model<TApi extends Api = Api> {
/** Provider-specific request/runtime parameters passed through to provider plugins. */
params?: Record<string, unknown>;
headers?: Record<string, string>;
/** Sends runtime credentials as Authorization: Bearer instead of provider-specific key headers. */
authHeader?: boolean;
/** Compatibility overrides for OpenAI-compatible APIs. If not set, auto-detected from baseUrl. */
compat?: TApi extends "openai-completions"
? OpenAICompletionsCompat

View File

@@ -669,6 +669,7 @@ function applyConfiguredProviderOverrides(params: {
...(resolvedParams ? { params: resolvedParams } : {}),
...(requestTimeoutMs !== undefined ? { requestTimeoutMs } : {}),
headers: passthroughRequestConfig.headers,
...(providerConfig.authHeader !== undefined ? { authHeader: providerConfig.authHeader } : {}),
};
}
const resolvedParams = mergeModelParams(
@@ -760,6 +761,9 @@ function applyConfiguredProviderOverrides(params: {
...(resolvedParams ? { params: resolvedParams } : {}),
...(requestTimeoutMs !== undefined ? { requestTimeoutMs } : {}),
headers: requestConfig.headers,
...(providerConfig.authHeader !== undefined
? { authHeader: providerConfig.authHeader }
: {}),
compat: resolvedCompat,
mediaInput: mergeModelMediaInput(
discoveredModel.mediaInput,
@@ -1143,6 +1147,9 @@ function resolveConfiguredFallbackModel(params: {
...(resolvedParams ? { params: resolvedParams } : {}),
...(requestTimeoutMs !== undefined ? { requestTimeoutMs } : {}),
headers: requestConfig.headers,
...(providerConfig?.authHeader !== undefined
? { authHeader: providerConfig.authHeader }
: {}),
compat: fallbackCompat,
mediaInput: fallbackMediaInput,
} as Model,

View File

@@ -87,8 +87,8 @@ describe("Anthropic provider", () => {
const model = makeAnthropicModel({
provider: "microsoft-foundry",
baseUrl: "https://example.services.ai.azure.com/anthropic",
authHeader: true,
headers: {
Authorization: "Bearer entra-access-token",
"x-api-key": "stale-resource-key",
},
});

View File

@@ -266,6 +266,13 @@ function hasBearerAuthorizationHeader(headers?: Record<string, string>): boolean
);
}
function usesFoundryBearerAuth(model: Model<"anthropic-messages">): boolean {
return (
model.provider === "microsoft-foundry" &&
(model.authHeader === true || hasBearerAuthorizationHeader(model.headers))
);
}
function omitFoundryBearerCredentialHeaders(
headers?: Record<string, string>,
): Record<string, string> | undefined {
@@ -988,7 +995,7 @@ function createClient(
return { client, isOAuthToken: false };
}
if (model.provider === "microsoft-foundry" && hasBearerAuthorizationHeader(model.headers)) {
if (usesFoundryBearerAuth(model)) {
const client = new Anthropic({
apiKey: null,
authToken: apiKey,