fix(capabilities): add deepseek-v4-1-flash vision alias; fix(modal): add zed to live catalog providers
This commit is contained in:
1 parent
45d42b8066
commit
8a4f4d9d2c
3 files changed
+89
-2
No files matched your search
@@ -130,7 +130,10 @@ export const MODEL_CAPABILITIES = {
|
|||||||
// DeepSeek API; it previously fell through to the generic *deepseek* pattern, whose
|
// DeepSeek API; it previously fell through to the generic *deepseek* pattern, whose
|
||||||
// 128K/64K limits are kept here. The repeated fields are deliberate: an exact entry
|
// 128K/64K limits are kept here. The repeated fields are deliberate: an exact entry
|
||||||
// short-circuits the pattern table, so a vision-only delta would drop them.
|
// short-circuits the pattern table, so a vision-only delta would drop them.
|
||||||
|
// Some providers (e.g. Kenari) expose this model under the hyphenated ID
|
||||||
|
// "deepseek-v4-1-flash" (dash instead of dot); add it as an alias (#4293).
|
||||||
"deepseek-v4.1-flash": { vision: true, reasoning: true, thinkingFormat: "deepseek", contextWindow: 1000000, maxOutput: 384000 },
|
"deepseek-v4.1-flash": { vision: true, reasoning: true, thinkingFormat: "deepseek", contextWindow: 1000000, maxOutput: 384000 },
|
||||||
|
"deepseek-v4-1-flash": { vision: true, reasoning: true, thinkingFormat: "deepseek", contextWindow: 1000000, maxOutput: 384000 },
|
||||||
"deepseek-flash": { vision: true, reasoning: true, thinkingFormat: "deepseek", contextWindow: 128000, maxOutput: 64000 },
|
"deepseek-flash": { vision: true, reasoning: true, thinkingFormat: "deepseek", contextWindow: 128000, maxOutput: 64000 },
|
||||||
|
|
||||||
// Qwen plain coder/text (no vision) — registry "vision-model" / "coder-model" aliases
|
// Qwen plain coder/text (no vision) — registry "vision-model" / "coder-model" aliases
|
||||||
|
|||||||
@@ -22,7 +22,9 @@ const NO_AUTH_PROVIDER_IDS = Object.keys(FREE_PROVIDERS).filter(id => FREE_PROVI
|
|||||||
|
|
||||||
// Providers with per-account live catalogs via /api/providers/[id]/models.
|
// Providers with per-account live catalogs via /api/providers/[id]/models.
|
||||||
// Static registry stays as fallback when live fetch fails or is empty.
|
// Static registry stays as fallback when live fetch fails or is empty.
|
||||||
const LIVE_CATALOG_PROVIDERS = ["cursor", "cline", "clinepass"];
|
// zed added in #4244: its backend customResolver already returns live models
|
||||||
|
// but the frontend omitted it, hiding Zed entirely from the Combo picker.
|
||||||
|
const LIVE_CATALOG_PROVIDERS = ["cursor", "cline", "clinepass", "zed"];
|
||||||
|
|
||||||
// Fetch a provider's account-scoped catalog for every active connection and merge
|
// Fetch a provider's account-scoped catalog for every active connection and merge
|
||||||
// the results. Entries collapse by model id on purpose: two connections of the
|
// the results. Entries collapse by model id on purpose: two connections of the
|
||||||
@@ -112,10 +114,12 @@ export default function ModelSelectModal({
|
|||||||
const cursorConnectionIds = liveConnectionIdsByProvider.cursor;
|
const cursorConnectionIds = liveConnectionIdsByProvider.cursor;
|
||||||
const clineConnectionIds = liveConnectionIdsByProvider.cline;
|
const clineConnectionIds = liveConnectionIdsByProvider.cline;
|
||||||
const clinepassConnectionIds = liveConnectionIdsByProvider.clinepass;
|
const clinepassConnectionIds = liveConnectionIdsByProvider.clinepass;
|
||||||
|
const zedConnectionIds = liveConnectionIdsByProvider.zed;
|
||||||
|
|
||||||
const cursorModels = useLiveProviderModels(isOpen, cursorConnectionIds, "Cursor");
|
const cursorModels = useLiveProviderModels(isOpen, cursorConnectionIds, "Cursor");
|
||||||
const clineModels = useLiveProviderModels(isOpen, clineConnectionIds, "Cline");
|
const clineModels = useLiveProviderModels(isOpen, clineConnectionIds, "Cline");
|
||||||
const clinepassModels = useLiveProviderModels(isOpen, clinepassConnectionIds, "ClinePass");
|
const clinepassModels = useLiveProviderModels(isOpen, clinepassConnectionIds, "ClinePass");
|
||||||
|
const zedModels = useLiveProviderModels(isOpen, zedConnectionIds, "Zed");
|
||||||
|
|
||||||
const fetchCombos = async () => {
|
const fetchCombos = async () => {
|
||||||
try {
|
try {
|
||||||
@@ -348,7 +352,7 @@ export default function ModelSelectModal({
|
|||||||
hasModels: mergedModels.length > 0,
|
hasModels: mergedModels.length > 0,
|
||||||
};
|
};
|
||||||
} else {
|
} else {
|
||||||
const liveModels = providerId === "cursor" ? cursorModels : providerId === "cline" ? clineModels : providerId === "clinepass" ? clinepassModels : [];
|
const liveModels = providerId === "cursor" ? cursorModels : providerId === "cline" ? clineModels : providerId === "clinepass" ? clinepassModels : providerId === "zed" ? zedModels : [];
|
||||||
const hardcodedModels = liveModels.length > 0
|
const hardcodedModels = liveModels.length > 0
|
||||||
? liveModels
|
? liveModels
|
||||||
: getModelsByProviderId(providerId);
|
: getModelsByProviderId(providerId);
|
||||||
|
|||||||
@@ -0,0 +1,80 @@
|
|||||||
|
/**
|
||||||
|
* Tests for two independent frontend/capabilities fixes:
|
||||||
|
*
|
||||||
|
* #4293 — deepseek-v4-1-flash (hyphen) has vision=false
|
||||||
|
* Kenari exposes the model under the ID "deepseek-v4-1-flash" (dash instead
|
||||||
|
* of dot). The capabilities table only had "deepseek-v4.1-flash" (dot), so
|
||||||
|
* the hyphenated variant fell through to the generic *deepseek* pattern which
|
||||||
|
* has vision:false. Fix: add "deepseek-v4-1-flash" as an alias with the same
|
||||||
|
* vision:true entry.
|
||||||
|
*
|
||||||
|
* #4244 — Zed missing from SelectModelModal LIVE_CATALOG_PROVIDERS
|
||||||
|
* The hardcoded list ["cursor","cline","clinepass"] omitted "zed", so the
|
||||||
|
* Zed provider card was never fetched and never shown in the Combo picker.
|
||||||
|
* Fix: add "zed" to the list (and wire up the corresponding state/hook/ternary).
|
||||||
|
*/
|
||||||
|
|
||||||
|
import { describe, it, expect, beforeAll } from "vitest";
|
||||||
|
import { getCapabilitiesForModel } from "../../open-sse/providers/capabilities.js";
|
||||||
|
|
||||||
|
// ── #4293 deepseek-v4-1-flash vision capability ───────────────────────────
|
||||||
|
|
||||||
|
describe("deepseek-v4-1-flash capabilities (#4293)", () => {
|
||||||
|
it("reports vision:true for the hyphenated deepseek-v4-1-flash id (Kenari variant)", () => {
|
||||||
|
// Any provider that uses the hyphenated id should get vision:true
|
||||||
|
const caps = getCapabilitiesForModel("kenari", "deepseek-v4-1-flash");
|
||||||
|
expect(caps.vision).toBe(true);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("still reports vision:true for the dotted deepseek-v4.1-flash id", () => {
|
||||||
|
const caps = getCapabilitiesForModel("ollama", "deepseek-v4.1-flash");
|
||||||
|
expect(caps.vision).toBe(true);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("still reports reasoning:true for deepseek-v4-1-flash", () => {
|
||||||
|
const caps = getCapabilitiesForModel("kenari", "deepseek-v4-1-flash");
|
||||||
|
expect(caps.reasoning).toBe(true);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("reports the correct contextWindow (1M) for deepseek-v4-1-flash", () => {
|
||||||
|
const caps = getCapabilitiesForModel("kenari", "deepseek-v4-1-flash");
|
||||||
|
expect(caps.contextWindow).toBe(1000000);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
// ── #4244 LIVE_CATALOG_PROVIDERS includes zed ────────────────────────────
|
||||||
|
// ModelSelectModal.js is JSX so we cannot import it in Vitest without a
|
||||||
|
// JSX transform. Read the source text and verify the constant definition
|
||||||
|
// directly — this is reliable and does not require a full React setup.
|
||||||
|
|
||||||
|
import fs from "fs";
|
||||||
|
import path from "path";
|
||||||
|
|
||||||
|
describe("ModelSelectModal LIVE_CATALOG_PROVIDERS includes zed (#4244)", () => {
|
||||||
|
let src;
|
||||||
|
beforeAll(() => {
|
||||||
|
const fileUrl = new URL("../../src/shared/components/ModelSelectModal.js", import.meta.url);
|
||||||
|
src = fs.readFileSync(fileUrl, "utf-8");
|
||||||
|
});
|
||||||
|
|
||||||
|
it("includes zed in LIVE_CATALOG_PROVIDERS", () => {
|
||||||
|
// Match the const definition line and verify zed is present
|
||||||
|
const match = src.match(/const LIVE_CATALOG_PROVIDERS\s*=\s*\[([^\]]+)\]/);
|
||||||
|
expect(match).toBeTruthy();
|
||||||
|
const list = match[1];
|
||||||
|
expect(list).toContain('"zed"');
|
||||||
|
});
|
||||||
|
|
||||||
|
it("still includes cursor, cline, clinepass", () => {
|
||||||
|
const match = src.match(/const LIVE_CATALOG_PROVIDERS\s*=\s*\[([^\]]+)\]/);
|
||||||
|
const list = match[1];
|
||||||
|
expect(list).toContain('"cursor"');
|
||||||
|
expect(list).toContain('"cline"');
|
||||||
|
expect(list).toContain('"clinepass"');
|
||||||
|
});
|
||||||
|
|
||||||
|
it("zedModels hook call is present in the file", () => {
|
||||||
|
expect(src).toContain("zedModels");
|
||||||
|
expect(src).toContain("zedConnectionIds");
|
||||||
|
});
|
||||||
|
});
|
||||||
Reference in new issue
Block a user