diff --git a/packages/opencode/src/provider/transform.ts b/packages/opencode/src/provider/transform.ts index 71295ba2b..79892db4c 100644 --- a/packages/opencode/src/provider/transform.ts +++ b/packages/opencode/src/provider/transform.ts @@ -258,7 +258,7 @@ export namespace ProviderTransform { // Remap providerOptions keys from stored providerID to expected SDK key const key = sdkKey(model.api.npm) - if (key && key !== model.providerID) { + if (key && key !== model.providerID && model.api.npm !== "@ai-sdk/azure") { const remap = (opts: Record | undefined) => { if (!opts) return opts if (!(model.providerID in opts)) return opts diff --git a/packages/opencode/test/provider/transform.test.ts b/packages/opencode/test/provider/transform.test.ts index 0f203b930..dcf16c65c 100644 --- a/packages/opencode/test/provider/transform.test.ts +++ b/packages/opencode/test/provider/transform.test.ts @@ -914,6 +914,88 @@ describe("ProviderTransform.message - strip openai metadata when store=false", ( }) }) +describe("ProviderTransform.message - providerOptions key remapping", () => { + const createModel = (providerID: string, npm: string) => + ({ + id: `${providerID}/test-model`, + providerID, + api: { + id: "test-model", + url: "https://api.test.com", + npm, + }, + name: "Test Model", + capabilities: { + temperature: true, + reasoning: false, + attachment: true, + toolcall: true, + input: { text: true, audio: false, image: true, video: false, pdf: true }, + output: { text: true, audio: false, image: false, video: false, pdf: false }, + interleaved: false, + }, + cost: { input: 0.001, output: 0.002, cache: { read: 0.0001, write: 0.0002 } }, + limit: { context: 128000, output: 8192 }, + status: "active", + options: {}, + headers: {}, + }) as any + + test("azure keeps 'azure' key and does not remap to 'openai'", () => { + const model = createModel("azure", "@ai-sdk/azure") + const msgs = [ + { + role: "user", + content: "Hello", + providerOptions: { + azure: { someOption: "value" }, + }, + }, + ] as any[] + + const result = ProviderTransform.message(msgs, model, {}) + + expect(result[0].providerOptions?.azure).toEqual({ someOption: "value" }) + expect(result[0].providerOptions?.openai).toBeUndefined() + }) + + test("openai with github-copilot npm remaps providerID to 'openai'", () => { + const model = createModel("github-copilot", "@ai-sdk/github-copilot") + const msgs = [ + { + role: "user", + content: "Hello", + providerOptions: { + "github-copilot": { someOption: "value" }, + }, + }, + ] as any[] + + const result = ProviderTransform.message(msgs, model, {}) + + expect(result[0].providerOptions?.openai).toEqual({ someOption: "value" }) + expect(result[0].providerOptions?.["github-copilot"]).toBeUndefined() + }) + + test("bedrock remaps providerID to 'bedrock' key", () => { + const model = createModel("my-bedrock", "@ai-sdk/amazon-bedrock") + const msgs = [ + { + role: "user", + content: "Hello", + providerOptions: { + "my-bedrock": { someOption: "value" }, + }, + }, + ] as any[] + + const result = ProviderTransform.message(msgs, model, {}) + + expect(result[0].providerOptions?.bedrock).toEqual({ someOption: "value" }) + expect(result[0].providerOptions?.["my-bedrock"]).toBeUndefined() + }) +}) + describe("ProviderTransform.variants", () => { const createMockModel = (overrides: Partial = {}): any => ({ id: "test/test-model",