feat: add group name functionality to models

- Introduced a new `group_name` field in the model configuration to allow for custom provider-group display names.
- Updated the `CursorModelCards`, `CursorModelEditor`, and `CursorSettingsPage` components to support group settings.
- Enhanced the UI to include group settings options, allowing users to modify group names and associated configurations.
- Added localization strings for new group settings features in both English and Chinese.
- Implemented a database migration to add the `group_name` column to the model configurations.
This commit is contained in:
leookun
2026-08-30 23:28:05 +08:00
parent 76baa3b0e7
commit e7a1cca4c6
32 changed files with 1950 additions and 137 deletions
+1
View File
@@ -185,6 +185,7 @@ function createModel({ hash, order, name, type, url, modelId, endpoint = "/v1/re
model_hash: hash,
sort_order: order,
display_name: name,
group_name: null,
type,
base_url: url,
use_full_url: false,
@@ -32,6 +32,7 @@ type CursorModelCardsProps = {
onTestPluginModel: (model: PluginModelDescriptor) => void;
onPluginSettings: (model: PluginModelDescriptor) => void;
onReorder: (modelHashes: string[]) => void;
onGroupSettings: (group: CursorModelGroup) => void;
};
type ModelGridProps = Omit<CursorModelCardsProps, "grouping" | "pluginModels" | "onTestPluginModel" | "onPluginSettings"> & {
@@ -60,6 +61,7 @@ export function CursorModelCards(props: CursorModelCardsProps) {
key={group.key}
label={group.label}
icon={group.icon}
onSettings={props.grouping === "provider" ? () => props.onGroupSettings(group) : undefined}
>
{group.models.map((model) => <ModelListRow
key={model.model_hash}
@@ -107,25 +109,37 @@ function pluginGroups(models: PluginModelDescriptor[]) {
return groups;
}
function CollapsibleGroup({ label, icon, iconSrc, children }: {
function CollapsibleGroup({ label, icon, iconSrc, onSettings, children }: {
label: string;
icon?: IconifyIcon;
iconSrc?: string;
onSettings?: () => void;
children: ReactNode;
}) {
const [open, setOpen] = useState(true);
return <Card className={styles.groupCard}>
<button
type="button"
className={styles.groupToggle}
aria-expanded={open}
onClick={() => setOpen((current) => !current)}
>
{icon && <Icon icon={icon} size="1.1em" />}
{iconSrc && <Icon src={iconSrc} size="1.1em" />}
<span className={styles.groupLabel}>{label}</span>
<Icon icon={open ? chevronDownIcon : chevronRightIcon} size="1em" />
</button>
<div className={styles.groupHeader}>
<button
type="button"
className={styles.groupToggle}
aria-expanded={open}
onClick={() => setOpen((current) => !current)}
>
{icon && <Icon icon={icon} size="1.1em" />}
{iconSrc && <Icon src={iconSrc} size="1.1em" />}
<span className={styles.groupLabel}>{label}</span>
</button>
{onSettings && <button type="button" className={styles.groupSettings} onClick={onSettings}>{t("分组设置")}</button>}
<button
type="button"
className={styles.groupChevron}
tabIndex={-1}
aria-hidden="true"
onClick={() => setOpen((current) => !current)}
>
<Icon icon={open ? chevronDownIcon : chevronRightIcon} size="1em" />
</button>
</div>
{open && <div className={styles.modelList}>{children}</div>}
</Card>;
}
@@ -273,8 +287,9 @@ function ModelGrid({
}
function providerGroup(model: Model) {
const label = providerDomain(model.base_url);
return { key: label, label, icon: flatColorOrganizationIcon };
const key = providerDomain(model.base_url);
const label = model.group_name?.trim() || key;
return { key, label, icon: flatColorOrganizationIcon };
}
function providerDomain(baseUrl: string) {
@@ -24,6 +24,7 @@ export const emptyCursorModelDraft = (): CursorModelDraft => ({
model: {
sort_order: 0,
display_name: "",
group_name: null,
type: "openai",
base_url: "",
use_full_url: false,
@@ -73,8 +73,34 @@
.groupCard {
padding: 4px 12px 8px;
}
.groupHeader {
display: flex;
align-items: center;
gap: 8px;
}
.groupSettings {
padding: 4px 2px;
color: var(--vscode-descriptionForeground);
background: none;
border: none;
font-size: type.$font-size-xs;
white-space: nowrap;
cursor: pointer;
&:hover { color: var(--vscode-foreground); }
}
.groupChevron {
display: flex;
align-items: center;
padding: 4px 0;
color: var(--vscode-foreground);
background: none;
border: none;
cursor: pointer;
}
.groupToggle {
width: 100%;
flex: 1;
min-width: 0;
display: flex;
align-items: center;
gap: 8px;
@@ -2,13 +2,14 @@ import { useCallback, useEffect, useRef, useState } from "react";
import { useNavigate } from "react-router-dom";
import { api, configuredPluginModels, type Model, type ModelInput } from "../../shared/api";
import { CursorCaGate, CursorCaProvider, CursorModelGate, CursorModelProvider } from "./CursorGates";
import { CursorModelCards, cursorModelGroups, type CursorModelGrouping } from "./CursorModelCards";
import { CursorModelCards, cursorModelGroups, type CursorModelGroup, type CursorModelGrouping } from "./CursorModelCards";
import { CursorModelEditor, emptyCursorModelDraft, type CursorModelDraft } from "./CursorModelEditor";
import { CursorModelTestResult, type CursorModelTestState } from "./CursorModelTestResult";
import styles from "./CursorSettings.module.scss";
import { PageContent } from "../../shell/layout/PageContent";
import { LegacyModelImport } from "./LegacyModelImport";
import { ConfirmDialog } from "../../shared/ui/ConfirmDialog";
import { FormField, SecretTextInput, TextInput } from "../../shared/ui/FormControls";
import controls from "../../shared/ui/Controls.module.scss";
import { Icon } from "../../shared/ui/Icon";
import { Modal } from "../../shared/ui/Modal";
@@ -34,6 +35,11 @@ export function CursorSettingsPage() {
const [savingAndTesting, setSavingAndTesting] = useState(false);
const [batchTesting, setBatchTesting] = useState(false);
const [grouping, setGrouping] = useState<CursorModelGrouping>("flat");
const [settingsGroup, setSettingsGroup] = useState<CursorModelGroup | null>(null);
const [groupNameDraft, setGroupNameDraft] = useState("");
const [groupBaseUrlDraft, setGroupBaseUrlDraft] = useState("");
const [groupApiKeyDraft, setGroupApiKeyDraft] = useState("");
const [groupSettingsBusy, setGroupSettingsBusy] = useState(false);
const activeModelTests = useRef(new Map<string, { testId: string; controller: AbortController; cancelling: boolean }>());
const caReady = cursorHarness?.ca === "ready";
const pluginModels = configuredPluginModels(plugins);
@@ -208,6 +214,39 @@ export function CursorSettingsPage() {
}]);
if (created) message(t("模型已复制"));
};
const openGroupSettings = (group: CursorModelGroup) => {
setGroupNameDraft(group.models.find((model) => model.group_name?.trim())?.group_name?.trim() ?? "");
setGroupBaseUrlDraft(sharedValue(group.models.map((model) => model.base_url)) ?? "");
setGroupApiKeyDraft(sharedValue(group.models.map((model) => model.api_key)) ?? "");
setSettingsGroup(group);
};
const saveGroupSettings = async () => {
if (!settingsGroup) return;
const group_name = groupNameDraft.trim() || null;
const base_url = groupBaseUrlDraft.trim();
const api_key = groupApiKeyDraft.trim();
setGroupSettingsBusy(true);
try {
for (const model of settingsGroup.models) {
const input: ModelInput = {
...modelInput(model),
group_name,
...(base_url ? { base_url } : {}),
...(api_key ? { api_key } : {}),
};
if (input.group_name === (model.group_name ?? null)
&& input.base_url === model.base_url
&& input.api_key === model.api_key) continue;
await api.updateModel(model.model_hash, input);
}
await appStore.refresh();
setSettingsGroup(null);
} catch (cause) {
message(errorText(cause));
} finally {
setGroupSettingsBusy(false);
}
};
const reorderModels = useCallback(async (modelHashes: string[]) => {
if (!await appStore.reorderCursorModels(modelHashes)) {
message(appStore.getSnapshot().error || t("排序失败"));
@@ -228,6 +267,7 @@ export function CursorSettingsPage() {
onTestPluginModel={(model) => void testModel({ model_hash: model.id, display_name: model.displayName })}
onPluginSettings={() => navigate("/plugins")}
onReorder={reorderModels}
onGroupSettings={openGroupSettings}
/>;
const refreshCa = async () => {
@@ -274,6 +314,19 @@ export function CursorSettingsPage() {
<ConfirmDialog open={caCommand !== null} title={t("安装本地 CA")} cancelLabel={t("关闭")} confirmLabel={t("打开终端")} onCancel={() => setCaCommand(null)} onConfirm={openCaTerminal}>
<div className={styles.editor}><strong>{t("需要授权安装证书")}</strong><span>{t("安装命令已自动复制。点击“打开终端”,将命令粘贴到终端中执行,并按提示输入密码。")}</span><pre className={styles.command}>{caCommand}</pre></div>
</ConfirmDialog>
<Modal open={settingsGroup !== null} title={t("分组设置")} busy={groupSettingsBusy || cursorBusy} onClose={() => setSettingsGroup(null)} onSubmit={() => void saveGroupSettings()} submitLabel={t("保存")}>
{settingsGroup && <div className={styles.editor}>
<FormField label={t("分组名称")} hint={t("应用于该分组下的全部模型,并作为 Cursor 模型选择器中的徽章标签;清空则恢复显示服务器域名。")}>
<TextInput placeholder={settingsGroup.key} value={groupNameDraft} onChange={(event) => setGroupNameDraft(event.target.value)} />
</FormField>
<FormField label={t("服务器地址")} hint={t("修改后应用于该分组下的全部模型;留空保持各模型现有配置不变。")}>
<TextInput placeholder={t("留空保持不变")} value={groupBaseUrlDraft} onChange={(event) => setGroupBaseUrlDraft(event.target.value)} />
</FormField>
<FormField label="API Key" hint={t("修改后应用于该分组下的全部模型;留空保持各模型现有配置不变。")}>
<SecretTextInput placeholder={t("留空保持不变")} autoComplete="off" value={groupApiKeyDraft} onChange={(event) => setGroupApiKeyDraft(event.target.value)} />
</FormField>
</div>}
</Modal>
<ConfirmDialog open={deleting !== null} title={t("删除模型")} cancelLabel={t("取消")} confirmLabel={t("删除")} onCancel={() => setDeleting(null)} onConfirm={() => { if (deleting) void appStore.deleteModel(deleting.model_hash); setDeleting(null); }}><p>{t("确定删除这个模型吗?")}</p></ConfirmDialog>
</>;
}
@@ -283,6 +336,13 @@ function modelInput(model: Model): ModelInput {
return input;
}
/** 组内所有模型取值一致时返回该值,否则返回 null(表单留空表示保持不变)。 */
function sharedValue(values: string[]): string | null {
const [first, ...rest] = values;
if (first === undefined) return null;
return rest.every((value) => value === first) ? first : null;
}
function draftInput(draft: CursorModelDraft): ModelInput {
const model = {
...draft.model,
+189 -104
View File
@@ -33,7 +33,7 @@
"refs": [
{
"file": "features/models/CursorModelEditor.tsx",
"line": 151,
"line": 152,
"column": 40
}
]
@@ -106,12 +106,12 @@
"refs": [
{
"file": "features/models/CursorModelCards.tsx",
"line": 151,
"line": 165,
"column": 64
},
{
"file": "features/models/CursorModelCards.tsx",
"line": 265,
"line": 279,
"column": 70
},
{
@@ -141,7 +141,7 @@
"refs": [
{
"file": "features/models/CursorSettingsPage.tsx",
"line": 142,
"line": 148,
"column": 27
}
]
@@ -205,12 +205,12 @@
"refs": [
{
"file": "features/models/CursorModelEditor.tsx",
"line": 181,
"line": 182,
"column": 16
},
{
"file": "features/models/CursorSettingsPage.tsx",
"line": 296,
"line": 356,
"column": 73
}
]
@@ -249,7 +249,7 @@
"refs": [
{
"file": "features/models/CursorSettingsPage.tsx",
"line": 307,
"line": 367,
"column": 89
}
]
@@ -447,12 +447,12 @@
"refs": [
{
"file": "features/models/CursorModelEditor.tsx",
"line": 168,
"line": 169,
"column": 16
},
{
"file": "features/models/CursorSettingsPage.tsx",
"line": 306,
"line": 366,
"column": 36
}
]
@@ -476,7 +476,7 @@
"refs": [
{
"file": "features/models/CursorSettingsPage.tsx",
"line": 264,
"line": 304,
"column": 211
}
]
@@ -512,7 +512,7 @@
"refs": [
{
"file": "features/models/CursorModelEditor.tsx",
"line": 153,
"line": 154,
"column": 286
}
]
@@ -524,12 +524,12 @@
"refs": [
{
"file": "features/models/CursorModelEditor.tsx",
"line": 142,
"line": 143,
"column": 59
},
{
"file": "features/models/CursorModelEditor.tsx",
"line": 142,
"line": 143,
"column": 124
}
]
@@ -546,17 +546,17 @@
},
{
"file": "features/models/CursorSettingsPage.tsx",
"line": 267,
"line": 307,
"column": 51
},
{
"file": "features/models/CursorSettingsPage.tsx",
"line": 267,
"line": 307,
"column": 130
},
{
"file": "features/models/CursorSettingsPage.tsx",
"line": 269,
"line": 309,
"column": 74
}
]
@@ -679,7 +679,7 @@
"refs": [
{
"file": "features/models/CursorSettingsPage.tsx",
"line": 277,
"line": 330,
"column": 52
}
]
@@ -778,17 +778,17 @@
"refs": [
{
"file": "features/models/CursorModelEditor.tsx",
"line": 157,
"line": 158,
"column": 49
},
{
"file": "features/models/CursorModelEditor.tsx",
"line": 159,
"line": 160,
"column": 50
},
{
"file": "features/models/CursorModelEditor.tsx",
"line": 162,
"line": 163,
"column": 50
}
]
@@ -802,7 +802,7 @@
"refs": [
{
"file": "features/models/CursorSettingsPage.tsx",
"line": 300,
"line": 360,
"column": 89
}
]
@@ -838,7 +838,7 @@
"refs": [
{
"file": "features/models/CursorSettingsPage.tsx",
"line": 262,
"line": 302,
"column": 134
}
]
@@ -902,7 +902,7 @@
"refs": [
{
"file": "features/models/CursorModelEditor.tsx",
"line": 153,
"line": 154,
"column": 42
}
]
@@ -952,12 +952,12 @@
"refs": [
{
"file": "features/models/CursorModelEditor.tsx",
"line": 164,
"line": 165,
"column": 27
},
{
"file": "features/models/CursorSettingsPage.tsx",
"line": 299,
"line": 359,
"column": 186
}
]
@@ -986,7 +986,7 @@
},
{
"file": "features/models/CursorSettingsPage.tsx",
"line": 277,
"line": 330,
"column": 76
},
{
@@ -1079,7 +1079,7 @@
"refs": [
{
"file": "features/models/CursorModelEditor.tsx",
"line": 154,
"line": 155,
"column": 42
}
]
@@ -1093,7 +1093,7 @@
"refs": [
{
"file": "features/models/CursorSettingsPage.tsx",
"line": 313,
"line": 373,
"column": 70
}
]
@@ -1167,17 +1167,17 @@
"refs": [
{
"file": "features/models/CursorModelCards.tsx",
"line": 153,
"line": 167,
"column": 96
},
{
"file": "features/models/CursorModelCards.tsx",
"line": 267,
"line": 281,
"column": 102
},
{
"file": "features/models/CursorSettingsPage.tsx",
"line": 277,
"line": 330,
"column": 99
},
{
@@ -1216,6 +1216,23 @@
}
]
},
"3260348163d03b8e": {
"source": "留空保持不变",
"kind": "text",
"placeholders": [],
"refs": [
{
"file": "features/models/CursorSettingsPage.tsx",
"line": 323,
"column": 35
},
{
"file": "features/models/CursorSettingsPage.tsx",
"line": 326,
"column": 41
}
]
},
"32896fdaaaa4c106": {
"source": "账号已保存,模型目录已同步。",
"kind": "text",
@@ -1269,7 +1286,7 @@
"refs": [
{
"file": "features/models/CursorSettingsPage.tsx",
"line": 298,
"line": 358,
"column": 123
}
]
@@ -1505,7 +1522,7 @@
"refs": [
{
"file": "features/models/CursorSettingsPage.tsx",
"line": 264,
"line": 304,
"column": 197
}
]
@@ -1517,7 +1534,7 @@
"refs": [
{
"file": "features/models/CursorSettingsPage.tsx",
"line": 274,
"line": 314,
"column": 80
},
{
@@ -1630,7 +1647,7 @@
"refs": [
{
"file": "features/models/CursorSettingsPage.tsx",
"line": 151,
"line": 157,
"column": 27
}
]
@@ -1754,12 +1771,12 @@
"refs": [
{
"file": "features/models/CursorModelEditor.tsx",
"line": 157,
"line": 158,
"column": 25
},
{
"file": "features/models/CursorSettingsPage.tsx",
"line": 299,
"line": 359,
"column": 34
}
]
@@ -1771,22 +1788,22 @@
"refs": [
{
"file": "features/models/CursorModelCards.tsx",
"line": 150,
"line": 164,
"column": 86
},
{
"file": "features/models/CursorModelCards.tsx",
"line": 173,
"line": 187,
"column": 86
},
{
"file": "features/models/CursorModelCards.tsx",
"line": 264,
"line": 278,
"column": 92
},
{
"file": "features/models/CursorSettingsPage.tsx",
"line": 269,
"line": 309,
"column": 703
}
]
@@ -1834,7 +1851,7 @@
"refs": [
{
"file": "features/models/CursorModelEditor.tsx",
"line": 148,
"line": 149,
"column": 145
}
]
@@ -1875,7 +1892,7 @@
"refs": [
{
"file": "features/models/CursorModelEditor.tsx",
"line": 206,
"line": 207,
"column": 41
}
]
@@ -1933,7 +1950,7 @@
"refs": [
{
"file": "features/models/CursorSettingsPage.tsx",
"line": 188,
"line": 194,
"column": 13
}
]
@@ -1993,7 +2010,7 @@
"refs": [
{
"file": "features/models/CursorSettingsPage.tsx",
"line": 213,
"line": 252,
"column": 47
}
]
@@ -2017,7 +2034,7 @@
"refs": [
{
"file": "features/models/CursorSettingsPage.tsx",
"line": 267,
"line": 307,
"column": 63
}
]
@@ -2029,17 +2046,17 @@
"refs": [
{
"file": "features/models/CursorModelEditor.tsx",
"line": 159,
"line": 160,
"column": 27
},
{
"file": "features/models/CursorModelEditor.tsx",
"line": 162,
"line": 163,
"column": 27
},
{
"file": "features/models/CursorSettingsPage.tsx",
"line": 299,
"line": 359,
"column": 83
}
]
@@ -2063,7 +2080,7 @@
"refs": [
{
"file": "features/models/CursorModelEditor.tsx",
"line": 155,
"line": 156,
"column": 69
}
]
@@ -2140,7 +2157,7 @@
"refs": [
{
"file": "features/models/CursorSettingsPage.tsx",
"line": 263,
"line": 303,
"column": 122
}
]
@@ -2314,12 +2331,12 @@
"refs": [
{
"file": "features/models/CursorModelCards.tsx",
"line": 152,
"line": 166,
"column": 64
},
{
"file": "features/models/CursorModelCards.tsx",
"line": 266,
"line": 280,
"column": 70
},
{
@@ -2336,7 +2353,7 @@
"refs": [
{
"file": "shared/api.ts",
"line": 486,
"line": 488,
"column": 43
}
]
@@ -2499,17 +2516,17 @@
"refs": [
{
"file": "features/models/CursorModelCards.tsx",
"line": 150,
"line": 164,
"column": 98
},
{
"file": "features/models/CursorModelCards.tsx",
"line": 173,
"line": 187,
"column": 98
},
{
"file": "features/models/CursorModelCards.tsx",
"line": 264,
"line": 278,
"column": 104
}
]
@@ -2586,7 +2603,7 @@
"refs": [
{
"file": "features/models/CursorSettingsPage.tsx",
"line": 261,
"line": 301,
"column": 103
}
]
@@ -2663,7 +2680,7 @@
"refs": [
{
"file": "shared/api.ts",
"line": 481,
"line": 483,
"column": 43
}
]
@@ -2711,12 +2728,12 @@
"refs": [
{
"file": "features/models/CursorModelEditor.tsx",
"line": 175,
"line": 176,
"column": 16
},
{
"file": "features/models/CursorSettingsPage.tsx",
"line": 294,
"line": 354,
"column": 67
}
]
@@ -2817,7 +2834,7 @@
"refs": [
{
"file": "shared/api.ts",
"line": 418,
"line": 420,
"column": 21
}
]
@@ -2844,7 +2861,7 @@
"refs": [
{
"file": "features/models/CursorSettingsPage.tsx",
"line": 186,
"line": 192,
"column": 11
}
]
@@ -2871,7 +2888,7 @@
"refs": [
{
"file": "features/models/CursorModelEditor.tsx",
"line": 153,
"line": 154,
"column": 298
}
]
@@ -2987,7 +3004,7 @@
"refs": [
{
"file": "features/models/CursorModelEditor.tsx",
"line": 148,
"line": 149,
"column": 115
}
]
@@ -3086,7 +3103,7 @@
"refs": [
{
"file": "features/models/CursorModelEditor.tsx",
"line": 142,
"line": 143,
"column": 76
}
]
@@ -3124,7 +3141,7 @@
"refs": [
{
"file": "features/models/CursorSettingsPage.tsx",
"line": 314,
"line": 374,
"column": 87
}
]
@@ -3208,7 +3225,7 @@
"refs": [
{
"file": "features/models/CursorSettingsPage.tsx",
"line": 277,
"line": 330,
"column": 250
}
]
@@ -3314,12 +3331,12 @@
},
{
"file": "features/models/CursorModelEditor.tsx",
"line": 163,
"line": 164,
"column": 27
},
{
"file": "features/models/CursorModelEditor.tsx",
"line": 163,
"line": 164,
"column": 58
}
]
@@ -3479,7 +3496,7 @@
"refs": [
{
"file": "features/models/CursorSettingsPage.tsx",
"line": 197,
"line": 203,
"column": 22
}
]
@@ -3532,9 +3549,14 @@
"refs": [
{
"file": "features/models/CursorSettingsPage.tsx",
"line": 269,
"line": 309,
"column": 432
},
{
"file": "features/models/CursorSettingsPage.tsx",
"line": 317,
"column": 193
},
{
"file": "features/settings/ProxySettingsCard.tsx",
"line": 33,
@@ -3616,7 +3638,7 @@
"refs": [
{
"file": "features/models/CursorSettingsPage.tsx",
"line": 125,
"line": 131,
"column": 15
}
]
@@ -3671,7 +3693,7 @@
"refs": [
{
"file": "features/models/CursorSettingsPage.tsx",
"line": 269,
"line": 309,
"column": 715
}
]
@@ -3705,7 +3727,7 @@
"refs": [
{
"file": "features/models/CursorModelEditor.tsx",
"line": 149,
"line": 150,
"column": 61
}
]
@@ -3717,12 +3739,12 @@
"refs": [
{
"file": "features/models/CursorModelCards.tsx",
"line": 246,
"line": 260,
"column": 113
},
{
"file": "features/models/CursorModelCards.tsx",
"line": 246,
"line": 260,
"column": 131
}
]
@@ -3744,7 +3766,7 @@
},
{
"file": "features/models/CursorModelEditor.tsx",
"line": 154,
"line": 155,
"column": 25
}
]
@@ -3780,7 +3802,7 @@
"refs": [
{
"file": "features/models/CursorModelEditor.tsx",
"line": 155,
"line": 156,
"column": 118
}
]
@@ -3915,6 +3937,23 @@
}
]
},
"b2617bf9ae663752": {
"source": "分组设置",
"kind": "text",
"placeholders": [],
"refs": [
{
"file": "features/models/CursorModelCards.tsx",
"line": 132,
"column": 99
},
{
"file": "features/models/CursorSettingsPage.tsx",
"line": 317,
"column": 49
}
]
},
"b4411558b932266f": {
"source": "上游类型",
"kind": "text",
@@ -4049,7 +4088,7 @@
"refs": [
{
"file": "features/models/CursorSettingsPage.tsx",
"line": 274,
"line": 314,
"column": 103
}
]
@@ -4107,7 +4146,7 @@
"refs": [
{
"file": "features/models/CursorModelEditor.tsx",
"line": 154,
"line": 155,
"column": 99
}
]
@@ -4134,7 +4173,7 @@
"refs": [
{
"file": "features/models/CursorSettingsPage.tsx",
"line": 189,
"line": 195,
"column": 13
}
]
@@ -4192,6 +4231,23 @@
}
]
},
"be961dc60ab610da": {
"source": "修改后应用于该分组下的全部模型;留空保持各模型现有配置不变。",
"kind": "text",
"placeholders": [],
"refs": [
{
"file": "features/models/CursorSettingsPage.tsx",
"line": 322,
"column": 45
},
{
"file": "features/models/CursorSettingsPage.tsx",
"line": 325,
"column": 42
}
]
},
"bf57afd709694b55": {
"source": "概览时间范围",
"kind": "text",
@@ -4292,7 +4348,7 @@
"refs": [
{
"file": "features/models/CursorSettingsPage.tsx",
"line": 269,
"line": 309,
"column": 62
}
]
@@ -4304,12 +4360,12 @@
"refs": [
{
"file": "features/models/CursorModelEditor.tsx",
"line": 160,
"line": 161,
"column": 27
},
{
"file": "features/models/CursorModelEditor.tsx",
"line": 160,
"line": 161,
"column": 58
}
]
@@ -4386,7 +4442,7 @@
},
{
"file": "features/models/CursorModelEditor.tsx",
"line": 153,
"line": 154,
"column": 25
}
]
@@ -4468,7 +4524,7 @@
"refs": [
{
"file": "features/models/CursorModelEditor.tsx",
"line": 164,
"line": 165,
"column": 50
}
]
@@ -4533,8 +4589,13 @@
"refs": [
{
"file": "features/models/CursorModelEditor.tsx",
"line": 148,
"line": 149,
"column": 70
},
{
"file": "features/models/CursorSettingsPage.tsx",
"line": 322,
"column": 27
}
]
},
@@ -4545,7 +4606,7 @@
"refs": [
{
"file": "features/models/CursorSettingsPage.tsx",
"line": 269,
"line": 309,
"column": 675
},
{
@@ -4598,17 +4659,17 @@
"refs": [
{
"file": "features/models/CursorModelEditor.tsx",
"line": 157,
"line": 158,
"column": 121
},
{
"file": "features/models/CursorModelEditor.tsx",
"line": 159,
"line": 160,
"column": 122
},
{
"file": "features/models/CursorModelEditor.tsx",
"line": 162,
"line": 163,
"column": 122
}
]
@@ -4620,7 +4681,7 @@
"refs": [
{
"file": "features/models/CursorModelEditor.tsx",
"line": 164,
"line": 165,
"column": 137
}
]
@@ -4639,6 +4700,18 @@
}
]
},
"d7e266bdc8064193": {
"source": "分组名称",
"kind": "text",
"placeholders": [],
"refs": [
{
"file": "features/models/CursorSettingsPage.tsx",
"line": 319,
"column": 27
}
]
},
"d86fa42c3848c680": {
"source": "使用系统代理",
"kind": "text",
@@ -4675,7 +4748,7 @@
"refs": [
{
"file": "features/models/CursorSettingsPage.tsx",
"line": 275,
"line": 315,
"column": 47
}
]
@@ -4699,12 +4772,12 @@
"refs": [
{
"file": "features/models/CursorModelEditor.tsx",
"line": 110,
"line": 111,
"column": 88
},
{
"file": "features/models/CursorModelEditor.tsx",
"line": 155,
"line": 156,
"column": 54
}
]
@@ -4793,7 +4866,7 @@
"refs": [
{
"file": "features/models/CursorModelCards.tsx",
"line": 174,
"line": 188,
"column": 64
},
{
@@ -4918,7 +4991,7 @@
"refs": [
{
"file": "features/models/CursorSettingsPage.tsx",
"line": 209,
"line": 215,
"column": 26
}
]
@@ -5004,7 +5077,7 @@
"refs": [
{
"file": "features/models/CursorModelEditor.tsx",
"line": 148,
"line": 149,
"column": 54
}
]
@@ -5086,12 +5159,12 @@
"refs": [
{
"file": "features/models/CursorModelEditor.tsx",
"line": 141,
"line": 142,
"column": 25
},
{
"file": "features/models/CursorModelEditor.tsx",
"line": 141,
"line": 142,
"column": 55
}
]
@@ -5156,6 +5229,18 @@
}
]
},
"eb4a3db23661fb52": {
"source": "应用于该分组下的全部模型,并作为 Cursor 模型选择器中的徽章标签;清空则恢复显示服务器域名。",
"kind": "text",
"placeholders": [],
"refs": [
{
"file": "features/models/CursorSettingsPage.tsx",
"line": 319,
"column": 44
}
]
},
"eb77492c9f76a7e1": {
"source": "安装命令已自动复制。点击“打开终端”,将命令粘贴到终端中执行,并按提示输入密码。",
"kind": "text",
@@ -5163,7 +5248,7 @@
"refs": [
{
"file": "features/models/CursorSettingsPage.tsx",
"line": 275,
"line": 315,
"column": 77
}
]
@@ -5192,7 +5277,7 @@
},
{
"file": "features/models/CursorSettingsPage.tsx",
"line": 260,
"line": 300,
"column": 69
}
]
@@ -5204,7 +5289,7 @@
"refs": [
{
"file": "features/models/CursorSettingsPage.tsx",
"line": 274,
"line": 314,
"column": 53
}
]
+5
View File
@@ -79,6 +79,7 @@
"2f9daa828907b93f": "Delete",
"2fe5a8d0eee9f14c": "Invalid",
"303c30f301514250": "Search resources",
"3260348163d03b8e": "Leave blank to keep unchanged",
"32896fdaaaa4c106": "Account saved and the model catalog is synced.",
"346ff60e6c7c5181": "Reading…",
"36f33adaf0942634": "Confirm",
@@ -270,6 +271,7 @@
"b06325c5660f0c29": "Direct",
"b16c3b2ecedd6fe1": "Cursor integration is active. Add a model configuration to use a BYOK model.",
"b254ff315d861346": "Try initializing again",
"b2617bf9ae663752": "Group settings",
"b4411558b932266f": "Provider type",
"b4c9e08870d41aa2": "Initialize the plugin runtime first",
"b502b1d414664337": "Prompt: {tokens}",
@@ -290,6 +292,7 @@
"bb7efdcb6af6e805": "Default dark",
"bda62ce1d5e4ace9": "Tell us why",
"bda74b5674b6a57d": "Initialize plugins",
"be961dc60ab610da": "Applies to every model in this group when changed; leave blank to keep each model's current configuration.",
"bf57afd709694b55": "Overview time range",
"bfc01caf9fe0c841": "Cache hit rate {rate}",
"c0b3fbff51ccc40b": "Done",
@@ -322,6 +325,7 @@
"d60669bb26a22f5d": "Leave blank to use the default",
"d6b1f203680f5496": "Leave blank to use adaptive thinking",
"d766536c18e8e990": "Plugin runtime {version} is installed and ready to use.",
"d7e266bdc8064193": "Group name",
"d86fa42c3848c680": "Use system proxy",
"d8c47e9776cf1082": "Main menu",
"da521d1c1cbd36af": "Authorization is required to install the certificate",
@@ -361,6 +365,7 @@
"ea26b760e930a7ca": "Call observability",
"eb11e2df1d8ae387": "Provider URL",
"eb1be07f2ca6e506": "Estimated using Claude Opus 4.7 pricing.",
"eb4a3db23661fb52": "Applies to every model in this group and is used as the badge label in Cursor's model picker; clear it to fall back to the server domain.",
"eb77492c9f76a7e1": "The install command has been copied. Click “Open terminal”, paste it into the terminal, and enter your password when prompted.",
"eba54690937bc532": "Manage accounts",
"ed31fbb483ee1b0a": "Actions",
+5
View File
@@ -79,6 +79,7 @@
"2f9daa828907b93f": "删除",
"2fe5a8d0eee9f14c": "已失效",
"303c30f301514250": "搜索资源",
"3260348163d03b8e": "留空保持不变",
"32896fdaaaa4c106": "账号已保存,模型目录已同步。",
"346ff60e6c7c5181": "读取中…",
"36f33adaf0942634": "确认",
@@ -270,6 +271,7 @@
"b06325c5660f0c29": "直连",
"b16c3b2ecedd6fe1": "Cursor 接管已生效;添加模型配置后即可使用 BYOK 模型。",
"b254ff315d861346": "请重试初始化",
"b2617bf9ae663752": "分组设置",
"b4411558b932266f": "上游类型",
"b4c9e08870d41aa2": "需要先初始化插件运行时",
"b502b1d414664337": "提示词:{tokens}",
@@ -290,6 +292,7 @@
"bb7efdcb6af6e805": "默认暗色",
"bda62ce1d5e4ace9": "可以告诉我们原因",
"bda74b5674b6a57d": "初始化插件",
"be961dc60ab610da": "修改后应用于该分组下的全部模型;留空保持各模型现有配置不变。",
"bf57afd709694b55": "概览时间范围",
"bfc01caf9fe0c841": "缓存命中率 {rate}",
"c0b3fbff51ccc40b": "完成",
@@ -322,6 +325,7 @@
"d60669bb26a22f5d": "留空使用默认值",
"d6b1f203680f5496": "留空使用 adaptive thinking",
"d766536c18e8e990": "插件运行时 {version} 已安装,可以开始使用插件。",
"d7e266bdc8064193": "分组名称",
"d86fa42c3848c680": "使用系统代理",
"d8c47e9776cf1082": "主菜单",
"da521d1c1cbd36af": "需要授权安装证书",
@@ -361,6 +365,7 @@
"ea26b760e930a7ca": "调用观测",
"eb11e2df1d8ae387": "上游地址",
"eb1be07f2ca6e506": "按 Claude Opus 4.7 价格估算。",
"eb4a3db23661fb52": "应用于该分组下的全部模型,并作为 Cursor 模型选择器中的徽章标签;清空则恢复显示服务器域名。",
"eb77492c9f76a7e1": "安装命令已自动复制。点击“打开终端”,将命令粘贴到终端中执行,并按提示输入密码。",
"eba54690937bc532": "账号管理",
"ed31fbb483ee1b0a": "操作",
+2
View File
@@ -7,6 +7,7 @@ export interface Model {
model_hash: string;
sort_order: number;
display_name: string;
group_name: string | null;
type: ModelType;
base_url: string;
use_full_url: boolean;
@@ -33,6 +34,7 @@ export interface Model {
export interface ModelInput {
sort_order: number;
display_name: string;
group_name: string | null;
type: ModelType;
base_url: string;
use_full_url: boolean;