fix(providers): update SenseNova Token Plan support (#6330)

Reconstructed onto release/v3.8.47 to drop unrelated main-drift (deps/electron/proxy
files belong to #6620, not this PR); the author's constants/registry/snapshot deltas
were re-applied cleanly onto the release tip.

Co-authored-by: diegosouzapw <8016841+diegosouzapw@users.noreply.github.com>
This commit is contained in:
Xiangzhe
2026-07-11 05:05:46 +08:00
committed by GitHub
parent f79302ccd9
commit 48df80e4a5
5 changed files with 58 additions and 17 deletions

View File

@@ -0,0 +1 @@
- **fix(providers):** update SenseNova Token Plan support — register the token-plan model ids/constants and adjust the SenseNova registry so token-plan accounts route correctly (#6330 — thanks @xz-dev).

View File

@@ -108,6 +108,7 @@ export const PROVIDER_MAX_TOKENS: Record<string, number> = {
openai: 16384, // GPT-4/4o standard
anthropic: 65536, // Claude models
gemini: 65536, // Gemini Studio
sensenova: 65536, // SenseNova Token Plan rejects MaxTokens outside [1, 65536]
};
export const DEFAULT_PROVIDER_MAX_TOKENS = 32000;

View File

@@ -5,23 +5,37 @@ export const sensenovaProvider: RegistryEntry = {
alias: "sensenova",
format: "openai",
executor: "default",
baseUrl: "https://api.sensenova.cn/v1/chat/completions",
baseUrl: "https://token.sensenova.cn/v1/chat/completions",
authType: "apikey",
authHeader: "bearer",
// Sweep 2026-06-19: refreshed against the official SenseCore compatible-mode catalog.
// V6.5-Pro is the heavyweight flagship; the 6.7 generation so far ships only flash-lite.
// Note the casing split: V6.5 models are PascalCase-dotted, 6.7 is lowercase-dotted.
// SenseNova Token Plan (validated 2026-07-06): the Token Plan endpoint is
// OpenAI-compatible but enforces max_tokens in [1, 65536]. Its /models list
// also currently advertises sensenova-u1-fast, but chat completions return
// 404 "model is not found" for that model; U1 Fast belongs to image flows.
models: [
{ id: "SenseNova-V6.5-Pro", name: "SenseNova V6.5 Pro", contextLength: 131072 },
{ id: "SenseNova-V6.5-Turbo", name: "SenseNova V6.5 Turbo", contextLength: 131072 },
{ id: "sensenova-6.7-flash-lite", name: "SenseNova 6.7 Flash-Lite" },
// DeepSeek V4 Flash is served on SenseNova's free Token Plan (9router#2233).
{ id: "deepseek-v4-flash", name: "DeepSeek V4 Flash" },
{ id: "SenseChat-5", name: "SenseChat 5", contextLength: 131072 },
{ id: "SenseChat-5-Cantonese", name: "SenseChat 5 Cantonese", contextLength: 32768 },
{ id: "SenseChat-Turbo", name: "SenseChat Turbo", contextLength: 4096 },
{ id: "SenseChat-Vision", name: "SenseChat Vision", contextLength: 4096 },
{ id: "SenseChat-Character", name: "SenseChat Character", contextLength: 8192 },
{ id: "sensechat", name: "SenseChat" },
{
id: "sensenova-6.7-flash-lite",
name: "SenseNova 6.7 Flash-Lite",
contextLength: 262144,
maxOutputTokens: 65536,
supportsVision: true,
toolCalling: true,
},
{
id: "deepseek-v4-flash",
name: "DeepSeek V4 Flash",
contextLength: 1048576,
maxOutputTokens: 65536,
supportsReasoning: true,
interleavedField: "reasoning_content",
},
{
id: "glm-5.2",
name: "GLM 5.2",
contextLength: 1048576,
maxOutputTokens: 65536,
supportsReasoning: true,
interleavedField: "reasoning_content",
},
],
};

View File

@@ -3706,8 +3706,8 @@
}
},
"url": {
"nonStream": "https://api.sensenova.cn/v1/chat/completions",
"stream": "https://api.sensenova.cn/v1/chat/completions"
"nonStream": "https://token.sensenova.cn/v1/chat/completions",
"stream": "https://token.sensenova.cn/v1/chat/completions"
}
},
"siliconflow": {

View File

@@ -0,0 +1,25 @@
import test from "node:test";
import assert from "node:assert/strict";
import { PROVIDER_MAX_TOKENS } from "../../open-sse/config/constants.ts";
import { getModelsByProviderId } from "../../open-sse/config/providerModels.ts";
test("SenseNova Token Plan catalog exposes only supported chat models with 64K output", () => {
const models = getModelsByProviderId("sensenova");
const ids = new Set(models.map((model) => model.id));
assert.ok(ids.has("sensenova-6.7-flash-lite"));
assert.ok(ids.has("deepseek-v4-flash"));
assert.ok(ids.has("glm-5.2"));
assert.equal(ids.has("sensenova-u1-fast"), false, "U1 Fast is not a chat-completions model");
for (const model of models) {
assert.equal(
model.maxOutputTokens,
65536,
`${model.id} should use Token Plan's 64K output cap`
);
}
assert.equal(PROVIDER_MAX_TOKENS.sensenova, 65536);
});