Skip to content

fix(provider): select DeepSeek adapter for Azure deployments - #44179

Open
Shalin-Shah-2002 wants to merge 2 commits into
anomalyco:devfrom
Shalin-Shah-2002:azure-deepseek-adapter
Open

fix(provider): select DeepSeek adapter for Azure deployments#44179
Shalin-Shah-2002 wants to merge 2 commits into
anomalyco:devfrom
Shalin-Shah-2002:azure-deepseek-adapter

Conversation

@Shalin-Shah-2002

Copy link
Copy Markdown

Issue for this PR

Closes#43106

Type of change

  • Bug fix
  • New feature
  • Refactor / code improvement
  • Documentation

What does this PR do?

Azure-hosted DeepSeek-V4-Pro / DeepSeek-V4-Flash deployments currently route through the generic chat or responses adapter in both the V2 provider plugin (packages/core/src/plugin/provider/azure.ts) and the legacy loader (packages/opencode/src/provider/provider.ts). The bundled @ai-sdk/azure provider exposes sdk.deepseek(), which handles DeepSeek Chat Completions semantics — max_tokens, reasoning_effort (low/medium/high/xhigh/max), and reasoning_content across reasoning/tool-call turns. It was never selected, so reasoningEffort: max variants failed with a generic Azure error.

Changes:

  • packages/core/src/plugin/provider/azure.ts and packages/opencode/src/provider/provider.ts: prefer sdk.deepseek(modelID) for deployment names containing deepseek, before the useCompletionUrls/responses routing (the DeepSeek adapter is chat-completions based, so it also applies when completion URLs are used). Explicit routing overrides for non-DeepSeek deployments are unchanged.
  • packages/opencode/src/provider/transform.ts: azure reasoningVariants now emits a max effort variant for deepseek-v4 deployments (mirrors the existing @ai-sdk/openai-compatible behavior), so azure/deepseek-v4-pro:max exists.
  • Tests: adapter selection via the real @ai-sdk/azure SDK (asserting azure.deepseek provider, plus unchanged responses/chat routing for non-DeepSeek models), variant generation, and the V2 plugin selector with a fake SDK.

How did you verify your code works?

  • bun typecheck in packages/core and packages/opencode — clean.
  • bun test test/provider/provider.test.ts test/provider/transform.test.ts in packages/opencode — 518 pass; the single failure (Google Vertex: uses REP endpoint for Gemini continental multi-regions) also fails on clean dev and is unrelated.
  • packages/core/test/plugin/provider-azure.test.ts cannot load in this environment due to a pre-existing circular import (plugin/provider.tsplugin/internal.ts) that fails on clean dev too; the new core tests follow the existing pattern exactly and the core package typechecks.

Screenshots / recordings

N/A

Checklist

  • I have tested my changes locally
  • I have not included unrelated changes in this PR

Azure DeepSeek deployments (deepseek-v4-pro, deepseek-v4-flash) currently
route through the generic chat or responses adapter, so reasoning effort
variants such as max fail and reasoning_content is not preserved across
agentic turns. @ai-sdk/azure exposes a DeepSeek-specific adapter that
handles these semantics, but it was never selected.
Prefer sdk.deepseek() for deployment names containing deepseek in both
the V2 provider plugin and the legacy provider loader, while keeping
explicit routing overrides for non-DeepSeek deployments. Also emit a
max reasoning effort variant for azure deepseek-v4 models.
Closesanomalyco#43106
@github-actions

Copy link
Copy Markdown
Contributor

The following comment was made by an LLM, it may be inaccurate:

Potential Duplicate Found

PR #43135: fix(provider): select Azure DeepSeek adapter
#43135

This appears to be addressing the exact same issue as the current PR #44179. Both PRs are fixing the same problem: selecting the DeepSeek adapter for Azure deployments. Since the current PR also closes issue #43106, PR #43135 likely addresses the same issue or is an earlier attempt at the same fix.

@Enough1122

Copy link
Copy Markdown

AI code review — automated review for reference, author can ignore or act on any point.

Reviewed the full diff (6 files). Overall this is a clean fix with unusually good test coverage — positive path, useCompletionUrls precedence, missing-adapter fallback, and non-DeepSeek routing preservation are all covered. A few points:

1. Confirm the pinned @ai-sdk/azure version actually exposes .deepseek()packages/core/src/plugin/provider/azure.ts:10 and packages/opencode/src/provider/provider.ts:165 are both guarded by sdk.deepseek, which is good for safety, but if the installed Azure provider build has no DeepSeek factory the branch never fires and production behavior stays exactly as today (tests pass via the fake SDK either way). Worth confirming the integration test in packages/opencode/test/provider/provider.test.ts (expect(language.provider).toBe("azure.deepseek")) runs against the real npm package, not a mock — that's what proves this is live rather than inert.

2. Two different predicates for "is DeepSeek" in one PR — the selectors match modelID.toLowerCase().includes("deepseek") (provider.ts:165), while the max reasoning-effort variant matches model.api.id.toLowerCase().includes("deepseek-v4") (packages/opencode/src/provider/transform.ts:946). If intentional (V3 deployments get the adapter but not the max effort), consider a one-line comment on each site noting they deliberately differ — otherwise the next reader will "fix" one to match the other.

3. Duplicated selector logic across packages — the same 4-line guard + comment block now exists verbatim in both packages/core/src/plugin/provider/azure.ts:7-10 and packages/opencode/src/provider/provider.ts:162-165. These copies have drifted before (that's how the fallback order got out of sync historically); consider extracting a shared helper or at least adding a "keep in sync with …" cross-reference comment to both.

4. Minor: duplicate-key safety in variants()transform.ts:945-946: if openaiReasoningEfforts(id, model.release_date) ever returns max itself, push("max") yields a duplicate key that Object.fromEntries silently collapses. Cheap hardening: if (!azureEfforts.includes("max")) azureEfforts.push("max").

None of these block the approach — the fallback test in particular means worst-case behavior degrades to the status quo.

Add cross-package keep-in-sync comments for the duplicated selector and
note why the adapter gate (any deepseek deployment) deliberately differs
from the max-effort variant gate (deepseek-v4 only). Harden the azure
variants push against a duplicate max key.
@Shalin-Shah-2002

Copy link
Copy Markdown
Author

Thanks for the review. Addressed points 2-4 in commit 9926e46; evidence for point 1 below.

1. Real SDK confirmation — the integration test in packages/opencode/test/provider/provider.test.ts does run against the real npm package, not a mock. getLanguageresolveSDK calls createAzure({resourceName, apiKey}) from @ai-sdk/azure and the azure loader calls selectAzureLanguageModel on that real SDK; the assertion language.provider === "azure.deepseek" can only pass if the installed @ai-sdk/azure@3.0.88 actually exposes .deepseek(). I verified this live while debugging: with npm wrongly resolved to @ai-sdk/openai-compatible (no deepseek factory) the test failed with azure.chat; after fixing the test config to @ai-sdk/azure, it passed with azure.deepseek. The d.ts also declares it: packages/opencode/node_modules/@ai-sdk/azure/dist/index.d.ts:28 (deepseek(deploymentId: string): LanguageModelV3), backed by DeepSeekChatLanguageModel with provider: "azure.deepseek".

2. Predicate difference — intentional: adapter selection matches any deepseek deployment (r1/v3/v4 all benefit from the DeepSeek adapter), while the max-effort variant is gated on deepseek-v4 only (only v4 exposes max per the deepseek adapter's reasoningEffort enum). Added comments at both sites noting the deliberate difference.

3. Duplication — added Keep in sync with … cross-references in both files.

4. Duplicate max — hardened: if (…includes("deepseek-v4") && !azureEfforts.includes("max")) azureEfforts.push("max").

Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

bug: Azure DeepSeek V4 never selects the DeepSeek SDK adapter

2 participants

@Shalin-Shah-2002@Enough1122