Merge origin/master (v0.5.81) into gitea/new_feature
Resolve conflicts: - streamingHandler.js: merge buildStreamErrorBytes onAbortTerminal + local shouldPersistRequestDetail & streamStatusForContent - capabilities.js: preserve server-injected user-asserted caps and models.dev catalog lookup; wire CommandCode /alpha/generate caps inside resolve() - commandcode.js (services/usage): adopt upstream whoami + billing credits/subscriptions with 5h/weekly rate windows and plan caps - openai-to-commandcode.js: merge toNativeImageBlock (data-URI & http(s) support) and assistant reasoning_content preservation - commandcode-to-openai.js: adopt upstream mid-stream error throw for clean retry and abortion - tests: sync commandcode test suite and exclude .next from vitest config
This commit is contained in:
@@ -116,6 +116,16 @@ export const MODEL_CAPABILITIES = {
|
||||
// DeepSeek's first V4 model with image input; text limits match V4-Flash.
|
||||
"deepseek-v4-flash-vision-exp": { vision: true, reasoning: true, thinkingFormat: "deepseek", contextWindow: 1000000, maxOutput: 384000 },
|
||||
|
||||
// DeepSeek V4.1-Flash is natively multimodal — models.dev lists
|
||||
// opencode-go/deepseek-v4.1-flash with modalities.input ["text","image"] — and upstream
|
||||
// the retired v4-flash / vision-exp ids route to it, so the live V4.1 ids carry the
|
||||
// same image capability as the exp id above. "deepseek-flash" is the GA id on the
|
||||
// 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
|
||||
// short-circuits the pattern table, so a vision-only delta would drop them.
|
||||
"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 },
|
||||
|
||||
// Qwen plain coder/text (no vision) — registry "vision-model" / "coder-model" aliases
|
||||
"vision-model": { vision: true, reasoning: true, thinkingFormat: "qwen", contextWindow: 1000000 },
|
||||
"coder-model": { reasoning: true, thinkingFormat: "qwen", contextWindow: 1000000 },
|
||||
@@ -131,6 +141,8 @@ export const MODEL_CAPABILITIES = {
|
||||
// via OpenAI Responses input_image; reasoning supports up to xhigh.
|
||||
"muse-spark-1.2-contributor-free": { vision: true, reasoning: true, thinkingFormat: "openai", contextWindow: 1048576, maxOutput: 131072 },
|
||||
"muse-spark-1.3-contributor-free": { vision: true, reasoning: true, thinkingFormat: "openai", contextWindow: 1048576, maxOutput: 131072 },
|
||||
// OpenCode Free Union Alpha — multimodal (text+vision), 262K context, 131K max output
|
||||
"union-alpha": { vision: true, contextWindow: 262144, maxOutput: 131072 },
|
||||
};
|
||||
|
||||
const KIRO_GPT_5_6_CAPABILITIES = { vision: true, reasoning: true, search: true, thinkingFormat: "openai", contextWindow: 272000, maxOutput: 128000 };
|
||||
@@ -214,6 +226,13 @@ export const PROVIDER_CAPABILITIES = {
|
||||
// contract). maxOutput 128000 per the server's product-config payload.
|
||||
"deepseek-v4.1-flash": { vision: true, reasoning: true, thinkingFormat: "openai", thinkingCanDisable: true, contextWindow: 1000000, maxOutput: 128000 },
|
||||
},
|
||||
// CodeBuddy intl — same gateway catalog as CN, so deepseek-v4.1-flash mirrors
|
||||
// the codebuddy-cn entry (the openai-style reasoning_effort format matters:
|
||||
// the generic *deepseek-v4* pattern would otherwise pick the vendor-native
|
||||
// "deepseek" thinking shape, which the CodeBuddy gateway does not accept).
|
||||
"codebuddy-intl": {
|
||||
"deepseek-v4.1-flash": { vision: true, reasoning: true, thinkingFormat: "openai", thinkingCanDisable: true, contextWindow: 1000000, maxOutput: 128000 },
|
||||
},
|
||||
// Qoder — upstream exposes opaque internal ids (dfmodel, kmodel, …); the
|
||||
// registry `name` is display-only and capability lookup matches on the raw
|
||||
// id, so every qoder model would fall through to DEFAULT_CAPABILITIES
|
||||
@@ -251,6 +270,16 @@ export const PROVIDER_CAPABILITIES = {
|
||||
"laguna-s-2.1": { reasoning: true, thinkingFormat: "openai", contextWindow: 1000000, maxOutput: 32000 },
|
||||
"laguna-xs-2.1": { reasoning: true, thinkingFormat: "openai", contextWindow: 200000, maxOutput: 32000 },
|
||||
},
|
||||
// Ollama Cloud — the generic *deepseek-v4* pattern misses the vision badge
|
||||
// the library page publishes for this model (text+image in, 1M context).
|
||||
// ponytail: thinkingFormat stays "deepseek" to preserve today's body shape;
|
||||
// Ollama's native toggle is the top-level `think` field (bool or
|
||||
// low/medium/high/max), which no format in thinkingUnified.js emits yet —
|
||||
// openai-to-ollama.js drops it. Wire a "think" format when thinking on
|
||||
// Ollama Cloud is actually needed.
|
||||
"ollama": {
|
||||
"deepseek-v4.1-flash:cloud": { vision: true, reasoning: true, thinkingFormat: "deepseek", contextWindow: 1000000, maxOutput: 384000 },
|
||||
},
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -349,7 +378,11 @@ export const PATTERN_CAPABILITIES = [
|
||||
{ pattern: "*glm*", caps: { reasoning: true, thinkingFormat: "zai", contextWindow: 200000 } },
|
||||
|
||||
// ── DeepSeek (thinking.enabled + reasoning_effort; r1 = thinking-only) ─
|
||||
{ pattern: "*deepseek-v4*", caps: { reasoning: true, thinkingFormat: "deepseek", contextWindow: 1000000, maxOutput: 384000 } },
|
||||
// v4.1+ has real image input (probed live on Alibaba MaaS: correct color
|
||||
// read from a PNG). v4-pro / v4-flash-0731 accept image blocks but ignore
|
||||
// them (answered "Unknown"), so vision stays scoped to v4.* dotted releases.
|
||||
{ pattern: "*deepseek-v4.*", caps: { vision: true, reasoning: true, thinkingFormat: "deepseek", thinkingEffortSupported: true, contextWindow: 1000000, maxOutput: 128000 } },
|
||||
{ pattern: "*deepseek-v4*", caps: { reasoning: true, thinkingFormat: "deepseek", thinkingEffortSupported: true, contextWindow: 1000000, maxOutput: 384000 } },
|
||||
{ pattern: "*reasoner*", caps: { reasoning: true, thinkingFormat: "deepseek", thinkingCanDisable: false, contextWindow: 128000 } },
|
||||
{ pattern: "*deepseek-r*", caps: { reasoning: true, thinkingFormat: "deepseek", thinkingCanDisable: false, contextWindow: 128000 } },
|
||||
{ pattern: "*deepseek-chat*", caps: { contextWindow: 128000 } },
|
||||
@@ -425,6 +458,7 @@ const MODALITY_KEYS = ["vision", "pdf", "audioInput", "videoInput"];
|
||||
// globalThis, which IS shared across server bundles in the same process.
|
||||
// Same reason the browser bundle is safe: it never calls a setter, so the slots
|
||||
// stay empty and every consumer below short-circuits.
|
||||
let catalogSource = null;
|
||||
const SOURCE_SLOTS = (globalThis.__9R_CAPABILITY_SOURCES ||= {
|
||||
catalog: null, // { getModalities, getLimits } — synced models.dev catalog
|
||||
userCaps: null, // (provider, model) => asserted caps — dashboard toggles
|
||||
@@ -432,10 +466,20 @@ const SOURCE_SLOTS = (globalThis.__9R_CAPABILITY_SOURCES ||= {
|
||||
|
||||
/**
|
||||
* Install the synced catalog reader (server only).
|
||||
* @param {{ getModalities: Function, getLimits: Function } | null} source
|
||||
* @param {{ getModalities: (provider: string, model: string) => object|null,
|
||||
* getLimits: (provider: string, model: string) => object|null } | null} source
|
||||
*/
|
||||
export function setCatalogSource(source) {
|
||||
catalogSource = source || null;
|
||||
SOURCE_SLOTS.catalog = source || null;
|
||||
if (typeof globalThis !== "undefined") globalThis.__9rCatalogSource = source || null;
|
||||
}
|
||||
|
||||
function getCatalogSource() {
|
||||
if (catalogSource) return catalogSource;
|
||||
if (SOURCE_SLOTS.catalog) return (catalogSource = SOURCE_SLOTS.catalog);
|
||||
if (typeof globalThis === "undefined") return null;
|
||||
return (catalogSource = globalThis.__9rCatalogSource || null);
|
||||
}
|
||||
|
||||
// Capabilities the user asserted per provider+model (dashboard "Add/Edit Model"
|
||||
@@ -478,16 +522,17 @@ function applyUserCaps(result, provider, model) {
|
||||
// flips when an outside source positively declares support.
|
||||
function refine(base, provider, model) {
|
||||
const result = { ...DEFAULT_CAPABILITIES, ...base };
|
||||
const catalogSource = SOURCE_SLOTS.catalog;
|
||||
if (catalogSource) {
|
||||
const modalities = catalogSource.getModalities(model);
|
||||
|
||||
const source = getCatalogSource();
|
||||
if (source) {
|
||||
const modalities = source.getModalities(provider, model);
|
||||
if (modalities) {
|
||||
for (const key of MODALITY_KEYS) {
|
||||
if (modalities[key] === true) result[key] = true;
|
||||
}
|
||||
}
|
||||
|
||||
const limits = catalogSource.getLimits(provider, model);
|
||||
const limits = source.getLimits(provider, model);
|
||||
if (limits) {
|
||||
if (limits.contextWindow > 0) result.contextWindow = limits.contextWindow;
|
||||
if (limits.maxOutput > 0) result.maxOutput = limits.maxOutput;
|
||||
@@ -499,12 +544,67 @@ function refine(base, provider, model) {
|
||||
return result;
|
||||
}
|
||||
|
||||
// Mirrors Command Code CLI `isKnownTextOnlyModel` (no image input). New models
|
||||
// default to vision; only this denylist stays text-only.
|
||||
const COMMANDCODE_TEXT_ONLY = new Set([
|
||||
"deepseek/deepseek-v4-pro",
|
||||
"deepseek/deepseek-v4-flash",
|
||||
"deepseek/deepseek-v4-flash-fast",
|
||||
"zai-org/glm-5.3",
|
||||
"zai-org/glm-5.2",
|
||||
"zai-org/glm-5.2-fast",
|
||||
"zai-org/glm-5.1",
|
||||
"zai-org/glm-5",
|
||||
"minimaxai/minimax-m2.7",
|
||||
"minimax/minimax-m2.7-free",
|
||||
"minimaxai/minimax-m2.5",
|
||||
"xiaomi/mimo-v2.5-pro",
|
||||
"qwen/qwen3.6-max-preview",
|
||||
"qwen/qwen3.7-max",
|
||||
"meituan/longcat-2.0:free",
|
||||
"stepfun/step-3.5-flash",
|
||||
"tencent/hy4-preview",
|
||||
"tencent/hy3",
|
||||
"tencent/hy3-paid",
|
||||
"nvidia/nemotron-3-ultra-550b-a55b",
|
||||
"poolside/laguna-s-2.1-free",
|
||||
"inclusionai/ling-3.0-flash-free",
|
||||
"inclusionai/ling-3.0-flash-sante:free",
|
||||
]);
|
||||
|
||||
function isCommandCodeTextOnly(model) {
|
||||
const key = String(model || "").toLowerCase();
|
||||
if (COMMANDCODE_TEXT_ONLY.has(key)) return true;
|
||||
for (const id of COMMANDCODE_TEXT_ONLY) {
|
||||
const base = id.includes("/") ? id.slice(id.lastIndexOf("/") + 1) : id;
|
||||
if (key === base || key.endsWith("/" + base)) return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
export function getCapabilitiesForModel(provider, model) {
|
||||
if (!model) return { ...DEFAULT_CAPABILITIES };
|
||||
|
||||
// Canonical exact lookup strips vendor prefix: "anthropic/claude-opus-4.7" -> "claude-opus-4.7".
|
||||
const baseModel = model.includes("/") ? model.split("/").pop() : model;
|
||||
const resolve = () => {
|
||||
// CommandCode wire is /alpha/generate for every model. Family patterns
|
||||
// (deepseek-v4 → thinkingFormat:deepseek, vision:false) must not win here.
|
||||
if (provider === "commandcode" || provider === "cmc") {
|
||||
const providerCaps = PROVIDER_CAPABILITIES.commandcode;
|
||||
if (providerCaps?.[model]) return { ...DEFAULT_CAPABILITIES, ...providerCaps[model] };
|
||||
if (providerCaps?.[baseModel]) return { ...DEFAULT_CAPABILITIES, ...providerCaps[baseModel] };
|
||||
return {
|
||||
...DEFAULT_CAPABILITIES,
|
||||
reasoning: true,
|
||||
thinkingFormat: "commandcode",
|
||||
thinkingEffortSupported: true,
|
||||
vision: !isCommandCodeTextOnly(model),
|
||||
contextWindow: 1000000,
|
||||
maxOutput: 384000,
|
||||
};
|
||||
}
|
||||
|
||||
// 1. Provider-specific override
|
||||
if (provider) {
|
||||
const providerCaps = PROVIDER_CAPABILITIES[provider];
|
||||
|
||||
@@ -13,6 +13,11 @@ export const CATALOG_FILE = path.join(DATA_DIR, "model-catalog.json");
|
||||
// Trimmed upstream catalog, read by the add-models skill (not by the router).
|
||||
export const CATALOG_RAW_FILE = path.join(DATA_DIR, "model-catalog-raw.json");
|
||||
|
||||
// Schema of the file this module reads. The writer stamps it; a file carrying an
|
||||
// older value predates provider-scoped modality keys, and its flat keys are not
|
||||
// looked up here, so the sync rebuilds it instead of asking upstream for a 304.
|
||||
export const CATALOG_VERSION = 2;
|
||||
|
||||
const EMPTY = { models: {}, providers: {} };
|
||||
let cache = EMPTY;
|
||||
let cachedMtime = -1;
|
||||
@@ -45,14 +50,19 @@ function load() {
|
||||
return cache;
|
||||
}
|
||||
|
||||
// Modality is a property of the model itself — any gateway serving it inherits
|
||||
// the same image/video/pdf support, so this is keyed by model id alone.
|
||||
export function getCatalogModalities(model) {
|
||||
return load().models[baseId(model)] || null;
|
||||
// Modalities are recorded per gateway upstream, and gateways disagree about the
|
||||
// same weights — some do not proxy images at all — so the key is provider +
|
||||
// model, in the local provider id space, exactly like the limits below. Keying
|
||||
// by model id alone made short ids collide across vendors: "auto", "free" and
|
||||
// "efficient" are router modes in one catalog and model names in another, and a
|
||||
// request to the router mode inherited a stranger's vision.
|
||||
export function getCatalogModalities(provider, model) {
|
||||
if (!provider) return null;
|
||||
return load().models[`${provider}:${baseId(model)}`] || null;
|
||||
}
|
||||
|
||||
// Context and output limits are a property of the gateway, not the model: each
|
||||
// one truncates differently, so these stay keyed by provider + model.
|
||||
// Context and output limits are a property of the gateway too: each one
|
||||
// truncates differently, so these stay keyed by provider + model.
|
||||
export function getCatalogLimits(provider, model) {
|
||||
const byProvider = provider && load().providers[provider];
|
||||
if (!byProvider) return null;
|
||||
|
||||
@@ -111,6 +111,8 @@ export const MODEL_PRICING = {
|
||||
"deepseek-v3.2-chat": { input: 0.14, output: 0.28, cached: 0.0028, reasoning: 0.28, cache_creation: 0.14 },
|
||||
"deepseek-v3.2-reasoner": { input: 0.14, output: 0.28, cached: 0.0028, reasoning: 0.28, cache_creation: 0.14 },
|
||||
"deepseek-v4-flash": { input: 0.14, output: 0.28, cached: 0.0028, reasoning: 0.28, cache_creation: 0.14 },
|
||||
"deepseek-v4.1-flash": { input: 0.14, output: 0.28, cached: 0.0028, reasoning: 0.28, cache_creation: 0.14 },
|
||||
"deepseek-flash": { input: 0.14, output: 0.28, cached: 0.0028, reasoning: 0.28, cache_creation: 0.14 },
|
||||
"deepseek-v4-pro": { input: 0.435, output: 0.87, cached: 0.003625, reasoning: 0.87, cache_creation: 0.435 },
|
||||
|
||||
// === GLM ===
|
||||
|
||||
@@ -58,7 +58,9 @@ export default {
|
||||
{ id: "kimi-k2.5", name: "Kimi-K2.5" },
|
||||
{ id: "hy3-preview", name: "Hy3 Preview" },
|
||||
{ id: "deepseek-v4-pro", name: "DeepSeek-V4-Pro" },
|
||||
{ id: "deepseek-v4-flash", name: "DeepSeek-V4-Flash" },
|
||||
// deepseek-v4-flash replaced server-side by deepseek-v4.1-flash (same
|
||||
// catalog as CN; the old endpoint still answers 200 but the list is the contract).
|
||||
{ id: "deepseek-v4.1-flash", name: "DeepSeek-V4.1-Flash" },
|
||||
{ id: "deepseek-v3-2-volc", name: "DeepSeek-V3.2" },
|
||||
],
|
||||
oauth: {
|
||||
|
||||
@@ -65,6 +65,9 @@ export default {
|
||||
{ id: "gpt-5.4-mini-review", name: "GPT 5.4 Mini Review", upstreamModelId: "gpt-5.4-mini", quotaFamily: "review" },
|
||||
{ id: "gpt-5.3-codex-spark", name: "GPT 5.3 Codex Spark" },
|
||||
{ id: "gpt-5.3-codex-spark-review", name: "GPT 5.3 Codex Spark Review", upstreamModelId: "gpt-5.3-codex-spark", quotaFamily: "review" },
|
||||
// Codex CLI's auto-review virtual model. Unlike the "-review" variants above it is not derived
|
||||
// from a base model, so it is forwarded verbatim instead of having "-review" stripped (#1398).
|
||||
{ id: "codex-auto-review", name: "Codex Auto Review", upstreamModelId: "codex-auto-review", quotaFamily: "review" },
|
||||
{ id: "gpt-image-2.5", name: "GPT Image 2.5", capabilities: ["text2img","edit","multiImage"], params: ["size","quality","background","image_detail","output_format"], kind: "image" },
|
||||
{ id: "gpt-image-2.5-flare", name: "GPT Image 2.5 Flare", capabilities: ["text2img","edit","multiImage"], params: ["size","quality","background","image_detail","output_format"], kind: "image" },
|
||||
{ id: "gpt-image-2.5-sunburst", name: "GPT Image 2.5 Sunburst", capabilities: ["text2img","edit","multiImage"], params: ["size","quality","background","image_detail","output_format"], kind: "image" },
|
||||
|
||||
@@ -74,4 +74,8 @@ export default {
|
||||
{ id: "claude-opus-4-7", name: "Claude Opus 4.7" },
|
||||
{ id: "claude-haiku-4-5", name: "Claude Haiku 4.5" },
|
||||
],
|
||||
features: {
|
||||
usage: true,
|
||||
usageApikey: true,
|
||||
},
|
||||
};
|
||||
|
||||
@@ -59,6 +59,7 @@ export default {
|
||||
{ id: "deepseek-v4-pro", name: "DeepSeek V4 Pro" },
|
||||
{ id: "deepseek-v4-pro-max", name: "DeepSeek V4 Pro Max", upstreamModelId: "deepseek-v4-pro" },
|
||||
{ id: "deepseek-v4-pro-none", name: "DeepSeek V4 Pro No Thinking", upstreamModelId: "deepseek-v4-pro" },
|
||||
{ id: "deepseek-v4.1-flash", name: "DeepSeek V4.1 Flash" },
|
||||
{ id: "deepseek-v4-flash", name: "DeepSeek V4 Flash" },
|
||||
{ id: "deepseek-v4-flash-vision-exp", name: "DeepSeek V4 Flash Vision (Exp)" },
|
||||
{ id: "deepseek-chat", name: "DeepSeek V3.2 Chat" },
|
||||
|
||||
@@ -30,6 +30,7 @@ export default {
|
||||
{ id: "glm-4.7-flash", name: "GLM 4.7 Flash" },
|
||||
{ id: "qwen3.5", name: "Qwen3.5" },
|
||||
{ id: "minimax-m3", name: "MiniMax M3" },
|
||||
{ id: "deepseek-v4.1-flash:cloud", name: "DeepSeek V4.1 Flash" },
|
||||
],
|
||||
serviceKinds: ["llm", "webFetch"],
|
||||
fetchConfig: {
|
||||
|
||||
@@ -13,7 +13,7 @@ export default {
|
||||
textIcon: "OC",
|
||||
website: "https://opencode.ai/auth",
|
||||
notice: {
|
||||
text: "OpenCode Go subscription: $5/mo (then 0/mo). Access to Kimi, GLM, Qwen, MiMo, MiniMax models.",
|
||||
text: "OpenCode Go subscription: $5/mo (then 10/mo). Access to Kimi, GLM, Qwen, MiMo, MiniMax models.",
|
||||
apiKeyUrl: "https://opencode.ai/auth",
|
||||
},
|
||||
},
|
||||
|
||||
@@ -17,13 +17,17 @@ export default {
|
||||
headers: {
|
||||
"x-opencode-client": "desktop",
|
||||
},
|
||||
forceStream: true,
|
||||
noAuth: true,
|
||||
quirks: {
|
||||
forceAutoToolChoiceModels: ["muse-spark-1.3-contributor-free"],
|
||||
},
|
||||
},
|
||||
models: [
|
||||
// Muse Spark models are served by /zen/v1/responses; the rest stay on
|
||||
// /chat/completions, so the format is declared per-model, not per-provider.
|
||||
// Endpoint formats differ per model, so declare non-chat models explicitly.
|
||||
{ id: "muse-spark-1.2-contributor-free", name: "Muse Spark 1.2 Contributor Free", targetFormat: "openai-responses" },
|
||||
{ id: "muse-spark-1.3-contributor-free", name: "Muse Spark 1.3 Contributor Free", targetFormat: "openai-responses" },
|
||||
{ id: "union-alpha", name: "Union Alpha Free", targetFormat: "claude" },
|
||||
],
|
||||
modelsFetcher: { url: "https://opencode.ai/zen/v1/models", type: "opencode-free" },
|
||||
passthroughModels: true,
|
||||
|
||||
@@ -1,10 +1,9 @@
|
||||
// Zed provider — RSA keypair callback auth (NOT standard OAuth).
|
||||
export default {
|
||||
id: "zed",
|
||||
priority: 10,
|
||||
priority: 999,
|
||||
alias: "zd",
|
||||
uiAlias: "zd",
|
||||
hidden: true,
|
||||
display: {
|
||||
name: "Zed",
|
||||
icon: "code",
|
||||
|
||||
@@ -62,8 +62,17 @@ const ANTHROPIC_BETA_BASE = [
|
||||
const ANTHROPIC_BETA_HEAVY_AGENT = ["advanced-tool-use-2025-11-20", "effort-2025-11-24"];
|
||||
|
||||
// Heavy-agent beta flags are gated to opus/sonnet — cheaper models don't need them.
|
||||
export function selectAnthropicBeta(model = "") {
|
||||
const flags = [...ANTHROPIC_BETA_BASE];
|
||||
// `redact-thinking` asks Anthropic to return signature-only thinking blocks, which
|
||||
// is right for clients that never render thinking but blanks the summaries a
|
||||
// client explicitly requested with `thinking.display: "summarized"`.
|
||||
const ANTHROPIC_BETA_REDACT_THINKING = "redact-thinking-2026-02-12";
|
||||
|
||||
export function wantsThinkingSummaries(body) {
|
||||
return body?.thinking?.display === "summarized";
|
||||
}
|
||||
|
||||
export function selectAnthropicBeta(model = "", body = null) {
|
||||
const flags = ANTHROPIC_BETA_BASE.filter((flag) => flag !== ANTHROPIC_BETA_REDACT_THINKING || !wantsThinkingSummaries(body));
|
||||
if (/^claude-(opus|sonnet)/.test(model)) flags.push(...ANTHROPIC_BETA_HEAVY_AGENT);
|
||||
return flags.join(",");
|
||||
}
|
||||
|
||||
@@ -26,6 +26,7 @@ const FORMAT_LEVELS = {
|
||||
qwen: L.base,
|
||||
kimi: L.levelMax,
|
||||
deepseek: L.hiMax,
|
||||
commandcode: ["none", "low", "medium", "high", "xhigh", "max"],
|
||||
minimax: L.onOff,
|
||||
hunyuan: L.base,
|
||||
step: L.base,
|
||||
@@ -40,6 +41,10 @@ const PATTERN_THINKING = [
|
||||
{ provider: "codex", pattern: "*gpt-5.6-terra*", levels: [...CODEX_GPT_5_6_LEVELS, "ultra"] },
|
||||
{ provider: "codex", pattern: "*gpt-5.6-luna*", levels: CODEX_GPT_5_6_LEVELS },
|
||||
{ pattern: "*codex*", levels: ["low", "medium", "high", "xhigh"] }, // codex cannot disable thinking
|
||||
// DeepSeek v4.* (Alibaba MaaS, probed live): effort low|medium|high|xhigh|max
|
||||
// all 200 via output_config.effort; "none" is a 400 on the anthropic route
|
||||
// (disable thinking instead). none kept for the picker = disable.
|
||||
{ pattern: "*deepseek-v4.*", levels: ["none", "low", "medium", "high", "xhigh", "max"] },
|
||||
// codebuddy-cn per-model effort sets — the server's product-config payload
|
||||
// publishes `reasoning.supportedEfforts` per model. NOTE: the chat endpoint
|
||||
// accepts any level you send (probed none/minimal/low/medium/high/xhigh/max
|
||||
@@ -52,6 +57,8 @@ const PATTERN_THINKING = [
|
||||
{ provider: "codebuddy-cn", pattern: "deepseek-v4*", levels: ["low", "high", "xhigh"] },
|
||||
{ provider: "codebuddy-cn", pattern: "hy3*", levels: ["low", "high"] },
|
||||
{ provider: "codebuddy-cn", pattern: "hy4*", levels: ["high"] },
|
||||
// codebuddy-intl rides the same gateway catalog, so its deepseek levels match.
|
||||
{ provider: "codebuddy-intl", pattern: "deepseek-v4*", levels: ["low", "high", "xhigh"] },
|
||||
];
|
||||
|
||||
// The generic level set used when a model's thinking format is unknown. Exported
|
||||
|
||||
Reference in New Issue
Block a user