Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions changelog.d/fixes/6330-sensenova-token-plan.md
Original file line number Diff line number Diff line change
@@ -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).
1 change: 1 addition & 0 deletions open-sse/config/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
44 changes: 29 additions & 15 deletions open-sse/config/providers/registry/sensenova/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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",
},
],
};
4 changes: 2 additions & 2 deletions tests/snapshots/provider/translate-path.json
Original file line number Diff line number Diff line change
Expand Up @@ -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": {
Expand Down
25 changes: 25 additions & 0 deletions tests/unit/sensenova-provider.test.ts
Original file line number Diff line number Diff line change
@@ -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);
});
Loading