refactor(claude-desktop): replace [1M] suffix with supports1m field

inferenceModels entries now emit {name, supports1m: true} objects when
1M is enabled (plain strings otherwise), instead of appending a " [1M]"
suffix to model IDs. Route IDs and upstream model IDs are stored
verbatim; the suffix is rejected on input rather than silently stripped,
and proxy request mapping now requires an exact route_id match.
This commit is contained in:
Jason
2026-05-12 17:40:32 +08:00
parent ea4cdaad27
commit 60a3628360
5 changed files with 99 additions and 103 deletions
@@ -111,6 +111,7 @@ type RouteRowValues = Omit<RouteRow, "rowId">;
const CLAUDE_ROUTE_PREFIX = "claude-";
const ANTHROPIC_CLAUDE_ROUTE_PREFIX = "anthropic/claude-";
const LEGACY_ONE_M_MARKER = "[1m]";
function envString(
settingsConfig: Record<string, unknown> | undefined,
@@ -188,11 +189,10 @@ function initialRouteRows(
function isClaudeSafeRoute(route: string) {
const normalized = route.trim().toLowerCase();
return (
(normalized.startsWith(CLAUDE_ROUTE_PREFIX) &&
normalized.length > CLAUDE_ROUTE_PREFIX.length) ||
(normalized.startsWith(ANTHROPIC_CLAUDE_ROUTE_PREFIX) &&
normalized.length > ANTHROPIC_CLAUDE_ROUTE_PREFIX.length)
if (normalized.includes(LEGACY_ONE_M_MARKER)) return false;
return [CLAUDE_ROUTE_PREFIX, ANTHROPIC_CLAUDE_ROUTE_PREFIX].some(
(prefix) =>
normalized.startsWith(prefix) && normalized.length > prefix.length,
);
}
@@ -825,12 +825,12 @@ export function ClaudeDesktopProviderForm({
<p className="text-xs leading-relaxed text-muted-foreground">
{t("claudeDesktop.routeMapHint", {
defaultValue:
"左侧决定 Claude Desktop 模型菜单里的可见模型 ID,实际写入为 claude-*;右侧填写供应商实际请求模型。",
"左侧决定 Claude Desktop 模型菜单里的可见模型 ID1M 只控制是否向 Claude Desktop 声明支持 1M 上下文,实际请求模型按右侧填写内容发送。",
})}
</p>
</div>
<div className="hidden grid-cols-[1fr_1fr_92px_36px] gap-2 px-1 text-xs font-medium text-muted-foreground md:grid">
<div className="hidden grid-cols-[1fr_1fr_116px_36px] gap-2 px-1 text-xs font-medium text-muted-foreground md:grid">
<span>
{t("claudeDesktop.routeModelLabel", {
defaultValue: "Desktop 显示模型",
@@ -843,7 +843,7 @@ export function ClaudeDesktopProviderForm({
</span>
<span>
{t("claudeDesktop.supports1mLabel", {
defaultValue: "1M",
defaultValue: "声明支持 1M",
})}
</span>
<span />
@@ -851,7 +851,7 @@ export function ClaudeDesktopProviderForm({
{routes.map((route, index) => (
<div
key={route.rowId}
className="grid grid-cols-1 gap-2 md:grid-cols-[1fr_1fr_92px_36px]"
className="grid grid-cols-1 gap-2 md:grid-cols-[1fr_1fr_116px_36px]"
>
<div className="flex">
<span className="inline-flex h-9 items-center rounded-l-md border border-r-0 border-input bg-muted px-3 text-sm text-muted-foreground">
@@ -896,7 +896,9 @@ export function ClaudeDesktopProviderForm({
updateRoute(index, { supports1m: checked === true })
}
/>
1M
{t("claudeDesktop.supports1mShort", {
defaultValue: "1M",
})}
</label>
<Button
type="button"
@@ -975,7 +977,7 @@ export function ClaudeDesktopProviderForm({
{routes.map((route, index) => (
<div
key={route.rowId}
className="grid grid-cols-1 gap-2 md:grid-cols-[1fr_92px_36px]"
className="grid grid-cols-1 gap-2 md:grid-cols-[1fr_116px_36px]"
>
<div className="flex gap-1">
<Input
@@ -1004,7 +1006,9 @@ export function ClaudeDesktopProviderForm({
})
}
/>
1M
{t("claudeDesktop.supports1mShort", {
defaultValue: "1M",
})}
</label>
<Button
type="button"
+4 -3
View File
@@ -181,13 +181,14 @@
"modelMappingOffHint": "Use this when the provider already exposes and accepts claude-* / anthropic/claude-* model IDs through Anthropic Messages. Claude Desktop connects to the provider directly.",
"modelMappingOnHint": "Claude Desktop currently restricts model IDs. If your provider offers non-Claude models, enable this switch and keep local routing running while in use.",
"routeMapTitle": "Model mapping",
"routeMapHint": "The left field controls the Claude Desktop-visible model ID and is written as claude-*. Enter the provider's actual requested model on the right.",
"routeMapHint": "The left field controls the Claude Desktop-visible model ID. 1M only declares 1M context support to Claude Desktop; requested model IDs are sent upstream exactly as entered on the right.",
"routeModelLabel": "Desktop display model",
"upstreamModelLabel": "Requested model",
"supports1mLabel": "1M",
"supports1mLabel": "Declare 1M",
"supports1mShort": "1M",
"directModelListTitle": "Manually specify Claude Desktop models (advanced, optional)",
"directModelListCollapsedHint": "Native Claude model providers usually do not need this. Claude Desktop will fetch /v1/models automatically.",
"directModelListHint": "Only fill this when the provider's /v1/models is unavailable or does not return Claude Desktop-safe claude-* model IDs. Checking 1M writes the [1M] marker after the model ID.",
"directModelListHint": "Only fill this when the provider's /v1/models is unavailable or does not return Claude Desktop-safe claude-* model IDs. Checking 1M declares 1M context support to Claude Desktop.",
"directModelInvalid": "Direct models must use claude-* / anthropic/claude-* model IDs",
"addModel": "Add model",
"addRoute": "Add model",
+4 -3
View File
@@ -181,13 +181,14 @@
"modelMappingOffHint": "プロバイダーが Anthropic Messages で claude-* / anthropic/claude-* のモデル ID を公開し、そのまま受け付ける場合に使います。Claude Desktop はプロバイダーへ直接接続します。",
"modelMappingOnHint": "Claude Desktop は現在モデル ID を制限しています。お使いのプロバイダーが Claude 系列以外のモデルを提供する場合、このスイッチを有効にし、使用中はローカルルーティングを起動したままにしてください。",
"routeMapTitle": "モデルマッピング",
"routeMapHint": "左側は Claude Desktop のモデルメニューに表示されるモデル ID を指定し、claude-* として書き込まれます。右側にはプロバイダーへ実際にリクエストするモデル名を入力してください。",
"routeMapHint": "左側は Claude Desktop のモデルメニューに表示されるモデル ID です。1M は Claude Desktop に 1M コンテキスト対応を宣言するだけで、上流へのリクエストモデル ID は右側の入力どおりに送信されます。",
"routeModelLabel": "Desktop 表示モデル",
"upstreamModelLabel": "リクエストモデル",
"supports1mLabel": "1M",
"supports1mLabel": "1M 対応を宣言",
"supports1mShort": "1M",
"directModelListTitle": "Claude Desktop モデルを手動指定(高度・任意)",
"directModelListCollapsedHint": "ネイティブ Claude モデルのプロバイダーでは通常不要です。Claude Desktop が /v1/models を自動取得します。",
"directModelListHint": "プロバイダーの /v1/models が使えない、または Claude Desktop が認識できる claude-* モデル ID を返さない場合だけ入力してください。1M をオンにするとモデル ID の後ろ[1M] マーカーを書き込みます。",
"directModelListHint": "プロバイダーの /v1/models が使えない、または Claude Desktop が認識できる claude-* モデル ID を返さない場合だけ入力してください。1M をオンにすると Claude Desktop に 1M コンテキスト対応を宣言します。",
"directModelInvalid": "直結モデルは claude-* / anthropic/claude-* のモデル ID を使う必要があります",
"addModel": "モデルを追加",
"addRoute": "モデルを追加",
+4 -3
View File
@@ -181,13 +181,14 @@
"modelMappingOffHint": "适合供应商已经暴露并接受 claude-* / anthropic/claude-* 模型名的 Anthropic Messages API;请求会由 Claude Desktop 直连供应商。",
"modelMappingOnHint": "Claude Desktop 目前对模型 ID 进行了限制,如果您的供应商提供的模型不是 Claude 系列模型,则需要打开本开关,并在使用过程中保持本地路由开启。",
"routeMapTitle": "模型映射",
"routeMapHint": "左侧决定 Claude Desktop 模型菜单里的可见模型 ID,实际写入为 claude-*;右侧填写供应商实际请求模型。",
"routeMapHint": "左侧决定 Claude Desktop 模型菜单里的可见模型 ID1M 只控制是否向 Claude Desktop 声明支持 1M 上下文,实际请求模型按右侧填写内容发送。",
"routeModelLabel": "Desktop 显示模型",
"upstreamModelLabel": "实际请求模型",
"supports1mLabel": "1M",
"supports1mLabel": "声明支持 1M",
"supports1mShort": "1M",
"directModelListTitle": "手动指定 Claude Desktop 模型列表(高级,可选)",
"directModelListCollapsedHint": "原生 Claude 模型供应商通常不用填写,Claude Desktop 会自动读取 /v1/models。",
"directModelListHint": "仅当供应商的 /v1/models 不可用或没有返回 Claude Desktop 可识别的 claude-* 模型名时填写;勾选 1M 会在模型名后写入 [1M] 标记。",
"directModelListHint": "仅当供应商的 /v1/models 不可用或没有返回 Claude Desktop 可识别的 claude-* 模型名时填写;勾选 1M 会向 Claude Desktop 声明支持 1M 上下文。",
"directModelInvalid": "直连模型必须使用 claude-* / anthropic/claude-* 模型名",
"addModel": "添加模型",
"addRoute": "添加模型",