fix(deepseek): expose v4 thinking profile in policy surface

This commit is contained in:
Peter Steinberger
2026-05-04 08:12:34 +01:00
parent a5dcf3d300
commit c36f8f1e39
5 changed files with 58 additions and 17 deletions

View File

@@ -1,27 +1,12 @@
import type { ProviderThinkingProfile } from "openclaw/plugin-sdk/plugin-entry";
import { readConfiguredProviderCatalogEntries } from "openclaw/plugin-sdk/provider-catalog-shared";
import { defineSingleProviderPluginEntry } from "openclaw/plugin-sdk/provider-entry";
import { buildProviderReplayFamilyHooks } from "openclaw/plugin-sdk/provider-model-shared";
import { isDeepSeekV4ModelId } from "./models.js";
import { applyDeepSeekConfig, DEEPSEEK_DEFAULT_MODEL_REF } from "./onboard.js";
import { buildDeepSeekProvider } from "./provider-catalog.js";
import { createDeepSeekV4ThinkingWrapper } from "./stream.js";
import { resolveDeepSeekV4ThinkingProfile } from "./thinking.js";
const PROVIDER_ID = "deepseek";
const V4_THINKING_LEVEL_IDS = ["off", "minimal", "low", "medium", "high", "xhigh", "max"] as const;
function buildDeepSeekV4ThinkingLevel(id: (typeof V4_THINKING_LEVEL_IDS)[number]) {
return { id };
}
const DEEPSEEK_V4_THINKING_PROFILE = {
levels: V4_THINKING_LEVEL_IDS.map(buildDeepSeekV4ThinkingLevel),
defaultLevel: "high",
} satisfies ProviderThinkingProfile;
function resolveDeepSeekV4ThinkingProfile(modelId: string): ProviderThinkingProfile | undefined {
return isDeepSeekV4ModelId(modelId) ? DEEPSEEK_V4_THINKING_PROFILE : undefined;
}
export default defineSingleProviderPluginEntry({
id: PROVIDER_ID,

View File

@@ -1,8 +1,37 @@
import type { ModelProviderConfig } from "openclaw/plugin-sdk/provider-model-types";
import { describe, expect, it } from "vitest";
import { normalizeConfig } from "./provider-policy-api.js";
import { normalizeConfig, resolveThinkingProfile } from "./provider-policy-api.js";
describe("deepseek provider-policy-api", () => {
it("advertises max thinking levels for DeepSeek V4 models", () => {
const expectedV4Levels = ["off", "minimal", "low", "medium", "high", "xhigh", "max"];
expect(
resolveThinkingProfile({
provider: "deepseek",
modelId: "deepseek-v4-pro",
})?.levels.map((level) => level.id),
).toEqual(expectedV4Levels);
expect(
resolveThinkingProfile({
provider: "deepseek",
modelId: "deepseek-v4-flash",
})?.defaultLevel,
).toBe("high");
expect(
resolveThinkingProfile({
provider: "deepseek",
modelId: "deepseek-chat",
}),
).toBe(undefined);
expect(
resolveThinkingProfile({
provider: "openrouter",
modelId: "deepseek-v4-pro",
}),
).toBe(null);
});
it("hydrates contextWindow and cost from catalog for known models", () => {
const providerConfig: ModelProviderConfig = {
baseUrl: "https://api.deepseek.com",

View File

@@ -1,6 +1,7 @@
import type { ModelDefinitionConfig } from "openclaw/plugin-sdk/provider-model-shared";
import type { ModelProviderConfig } from "openclaw/plugin-sdk/provider-model-types";
import { DEEPSEEK_MODEL_CATALOG } from "./models.js";
import { resolveDeepSeekV4ThinkingProfile } from "./thinking.js";
type ModelDefinitionDraft = Partial<ModelDefinitionConfig> &
Pick<ModelDefinitionConfig, "id" | "name">;
@@ -95,3 +96,9 @@ export function normalizeConfig(params: {
return { ...providerConfig, models: nextModels as ModelDefinitionConfig[] };
}
export function resolveThinkingProfile(params: { provider: string; modelId: string }) {
return params.provider.trim().toLowerCase() === "deepseek"
? resolveDeepSeekV4ThinkingProfile(params.modelId)
: null;
}

View File

@@ -0,0 +1,19 @@
import type { ProviderThinkingProfile } from "openclaw/plugin-sdk/plugin-entry";
import { isDeepSeekV4ModelId } from "./models.js";
const V4_THINKING_LEVEL_IDS = ["off", "minimal", "low", "medium", "high", "xhigh", "max"] as const;
function buildDeepSeekV4ThinkingLevel(id: (typeof V4_THINKING_LEVEL_IDS)[number]) {
return { id };
}
const DEEPSEEK_V4_THINKING_PROFILE = {
levels: V4_THINKING_LEVEL_IDS.map(buildDeepSeekV4ThinkingLevel),
defaultLevel: "high",
} satisfies ProviderThinkingProfile;
export function resolveDeepSeekV4ThinkingProfile(
modelId: string,
): ProviderThinkingProfile | undefined {
return isDeepSeekV4ModelId(modelId) ? DEEPSEEK_V4_THINKING_PROFILE : undefined;
}