mirror of
https://github.com/anomalyco/opencode.git
synced 2026-11-13 01:31:22 +03:00
fix(core): stop sending API key metadata as request body (#53546)
Co-authored-by: neriousy <filip@anoma.ly>
This commit is contained in:
committed by
GitHub
Unverified
parent
34cf183c4c
commit
6273bd7924
@@ -198,7 +198,7 @@ const resolveCatalogModel = Effect.fn("ModelResolver.resolveCatalogModel")(funct
|
||||
credential?: Credential.Value,
|
||||
dependencies?: Dependencies,
|
||||
) {
|
||||
const resolved = prepareRuntimeModel(model, credential)
|
||||
const resolved = prepareRuntimeModel(model)
|
||||
const configuration = credential?.type === "key" ? credential.configuration : undefined
|
||||
const configured = { ...resolved.settings, ...credential?.metadata, ...configuration }
|
||||
if (Provider.isAISDK(resolved.package)) {
|
||||
@@ -256,15 +256,9 @@ const resolveCatalogModel = Effect.fn("ModelResolver.resolveCatalogModel")(funct
|
||||
})
|
||||
})
|
||||
|
||||
function prepareRuntimeModel(model: RuntimeInfo, credential: Credential.Value | undefined) {
|
||||
if (model.settings?.apiKey !== "" && (credential?.type !== "key" || credential.metadata === undefined)) return model
|
||||
return {
|
||||
...model,
|
||||
...(model.settings?.apiKey === "" ? { settings: Struct.omit(model.settings, ["apiKey"]) } : {}),
|
||||
...(credential?.type === "key" && credential.metadata !== undefined
|
||||
? { body: Provider.mergeOverlay(model.body, credential.metadata) }
|
||||
: {}),
|
||||
}
|
||||
function prepareRuntimeModel(model: RuntimeInfo) {
|
||||
if (model.settings?.apiKey !== "") return model
|
||||
return { ...model, settings: Struct.omit(model.settings, ["apiKey"]) }
|
||||
}
|
||||
|
||||
function validateProviderVariables(
|
||||
|
||||
@@ -487,11 +487,12 @@ function expandResourceName(baseURL: string, resourceName: string) {
|
||||
.replaceAll("${AZURE_COGNITIVE_SERVICES_RESOURCE_NAME}", resourceName)
|
||||
}
|
||||
|
||||
// The Azure CLI method stores the resource as credential metadata, the API key method as its form answer.
|
||||
// The Azure CLI method stores the resource as credential metadata, the API key method as its form answer. API keys
|
||||
// imported from V1 keep their connect-form answer as metadata.
|
||||
function credentialResource(credential: Credential.Value | undefined) {
|
||||
const resource =
|
||||
credential?.type === "key"
|
||||
? credential.configuration?.resourceName
|
||||
? (credential.configuration?.resourceName ?? credential.metadata?.resourceName)
|
||||
: credential?.methodID === methodID
|
||||
? credential.metadata?.resourceName
|
||||
: undefined
|
||||
|
||||
@@ -710,7 +710,7 @@ describe("ModelResolver", () => {
|
||||
|
||||
it.effect("prefers stored credentials over configured auth", () =>
|
||||
Effect.gen(function* () {
|
||||
const credential = Credential.Key.make({ type: "key", key: "stored-secret", metadata: { tenant: "work" } })
|
||||
const credential = Credential.Key.make({ type: "key", key: "stored-secret" })
|
||||
const resolved = yield* ModelResolver.fromCatalogModel(
|
||||
model(Provider.aisdk("@ai-sdk/openai"), {
|
||||
settings: { apiKey: "configured-secret", baseURL: "https://openai.example/v1" },
|
||||
@@ -728,7 +728,25 @@ describe("ModelResolver", () => {
|
||||
})
|
||||
|
||||
expect(headers.authorization).toBe("Bearer stored-secret")
|
||||
expect(resolved.route.defaults.http?.body).toEqual({ tenant: "work" })
|
||||
}),
|
||||
)
|
||||
|
||||
it.effect("does not project API key metadata into the request body", () =>
|
||||
Effect.gen(function* () {
|
||||
// V1 auth.json stored connect-form answers as API key metadata, and the legacy import preserves them there.
|
||||
const resolved = yield* ModelResolver.fromCatalogModel(
|
||||
model(Provider.aisdk("@ai-sdk/azure"), {
|
||||
providerID: Provider.ID.azure,
|
||||
modelID: "responses-deployment",
|
||||
settings: { apiVersion: "2025-01-01-preview" },
|
||||
headers: {},
|
||||
body: {},
|
||||
}),
|
||||
Credential.Key.make({ type: "key", key: "secret", metadata: { resourceName: "migrated-resource" } }),
|
||||
)
|
||||
|
||||
expect(resolved.route.endpoint.baseURL).toBe("https://migrated-resource.openai.azure.com/openai/v1")
|
||||
expect(resolved.route.defaults.http?.body).toEqual({})
|
||||
}),
|
||||
)
|
||||
|
||||
|
||||
@@ -574,9 +574,15 @@ describe("AzurePlugin resource name", () => {
|
||||
name: "prefers the connection's resource over configuration, as requests do",
|
||||
env: { AZURE_RESOURCE_NAME: "from-env" },
|
||||
settings: { resourceName: "from-config" },
|
||||
connection: true,
|
||||
credential: keyCredential(),
|
||||
expected: "test-resource",
|
||||
},
|
||||
{
|
||||
name: "reads the resource of an API key imported from V1",
|
||||
env: { AZURE_RESOURCE_NAME: "from-env" },
|
||||
credential: Credential.Key.make({ type: "key", key: "secret", metadata: { resourceName: "imported-resource" } }),
|
||||
expected: "imported-resource",
|
||||
},
|
||||
]
|
||||
|
||||
cases.forEach((item) =>
|
||||
@@ -586,7 +592,7 @@ describe("AzurePlugin resource name", () => {
|
||||
yield* seedProvider(item.settings)
|
||||
const providers = yield* Provider.Service
|
||||
yield* providers.transform((editor) => editor.update(Provider.ID.openai, () => {}))
|
||||
if (item.connection) yield* connect(keyCredential())
|
||||
if (item.credential) yield* connect(item.credential)
|
||||
yield* addPlugin()
|
||||
|
||||
expect(required(yield* providers.get(Provider.ID.azure)).settings?.resourceName).toBe(item.expected)
|
||||
|
||||
Reference in New Issue
Block a user