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
13 changes: 13 additions & 0 deletions web/public/locales/en/translation.json
Original file line number Diff line number Diff line change
Expand Up @@ -408,6 +408,9 @@
"updateTitle": "Update Model",
"createDescription": "Add a new model to the system",
"updateDescription": "Update the model information",
"confirmUpdateTitle": "Confirm model config update",
"confirmUpdateDescription": "Review these changes before saving. Existing fields that this form does not manage will be preserved.",
"confirmUpdate": "Confirm Update",
"modelName": "Model Name",
"modelNamePlaceholder": "Enter model name",
"ownerPlaceholder": "Enter owner, optional",
Expand Down Expand Up @@ -445,10 +448,20 @@
"recordClaudeLongContextDescription": "Track an extra summary bucket only when the model is Claude and input tokens are greater than 200,000.",
"disableResolutionFuzzyMatch": "Disable Resolution Fuzzy Match",
"disableResolutionFuzzyMatchDescription": "Require conditional prices to match resolution exactly. When disabled, common size formats can fall back to normalized resolution tiers.",
"timeoutConfig": "Timeout Config",
"create": "Create",
"update": "Update",
"submitting": "Submitting...",
"modelNameUpdateDisabled": "Model name cannot be modified in update mode",
"changeSummary": {
"field": "Field",
"before": "Current",
"after": "After Update",
"unset": "Not Set",
"none": "None",
"configured": "Configured",
"changed": "Changed"
},
"config": {
"title": "Model Display Config",
"description": "Configure descriptive display fields for the model",
Expand Down
13 changes: 13 additions & 0 deletions web/public/locales/zh/translation.json
Original file line number Diff line number Diff line change
Expand Up @@ -397,6 +397,9 @@
"updateTitle": "更新模型",
"createDescription": "向系统添加新模型",
"updateDescription": "更新模型信息",
"confirmUpdateTitle": "确认更新模型配置",
"confirmUpdateDescription": "保存前请确认下列变化。未在表单中管理的已有字段会保留。",
"confirmUpdate": "确认更新",
"modelName": "模型名称",
"modelNamePlaceholder": "输入模型名称",
"ownerPlaceholder": "输入所有者,可留空",
Expand Down Expand Up @@ -434,10 +437,20 @@
"recordClaudeLongContextDescription": "仅当模型为 Claude 且输入 Token 大于 200,000 时,记录额外的长上下文汇总桶。",
"disableResolutionFuzzyMatch": "禁用分辨率模糊匹配",
"disableResolutionFuzzyMatchDescription": "要求条件价格中的分辨率完全匹配。关闭时,常见尺寸格式可回退匹配到归一化后的分辨率档位。",
"timeoutConfig": "超时配置",
"create": "创建",
"update": "更新",
"submitting": "提交中...",
"modelNameUpdateDisabled": "模型名称在更新模式下不可修改",
"changeSummary": {
"field": "字段",
"before": "当前配置",
"after": "更新后",
"unset": "未设置",
"none": "无",
"configured": "已配置",
"changed": "已变化"
},
"config": {
"title": "模型展示配置",
"description": "配置模型的展示说明字段",
Expand Down
29 changes: 20 additions & 9 deletions web/src/feature/model/components/BuiltinModelsDialog.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ interface BuiltinModelsDialogProps {
onOpenChange: (open: boolean) => void;
existingModels: ModelConfig[];
onCreateFromBuiltin: (model: ModelConfig) => void;
onEditFromBuiltin: (model: ModelConfig) => void;
onEditFromBuiltin: (builtinModel: ModelConfig, existingModel: ModelConfig) => void;
}

interface BuiltinModelRow {
Expand Down Expand Up @@ -102,13 +102,18 @@ export function BuiltinModelsDialog({
const [selectedModels, setSelectedModels] = useState<Set<string>>(new Set());
const [showExistingModels, setShowExistingModels] = useState(false);
const [isSaving, setIsSaving] = useState(false);
const [savingRowKey, setSavingRowKey] = useState<string | null>(null);
const [savingRowKeys, setSavingRowKeys] = useState<Set<string>>(new Set());

const existingModelSet = useMemo(
() => new Set(existingModels.map((model) => model.model)),
[existingModels]
);

const existingModelMap = useMemo(
() => new Map(existingModels.map((model) => [model.model, model])),
[existingModels]
);

const channelTypeOptions = useMemo(() => {
return Object.keys(channelBuiltinModels || {})
.map(Number)
Expand Down Expand Up @@ -292,7 +297,7 @@ export function BuiltinModelsDialog({

const handleAddBuiltin = async (row: BuiltinModelRow) => {
const rowKey = getBuiltinModelRowKey(row);
setSavingRowKey(rowKey);
setSavingRowKeys((prev) => new Set(prev).add(rowKey));

try {
await modelApi.saveModels([toModelSaveRequest(row.model)]);
Expand All @@ -306,7 +311,11 @@ export function BuiltinModelsDialog({
} catch (error) {
toast.error(error instanceof Error ? error.message : t("model.builtin.importFailed"));
} finally {
setSavingRowKey(null);
setSavingRowKeys((prev) => {
const next = new Set(prev);
next.delete(rowKey);
return next;
});
}
};

Expand Down Expand Up @@ -444,8 +453,10 @@ export function BuiltinModelsDialog({
const model = row.model;
const rowKey = getBuiltinModelRowKey(row);
const exists = existingModelSet.has(model.model);
const existingModel = existingModelMap.get(model.model);
const selected = selectedModels.has(rowKey);
const disabled = !isRowSelectable(row);
const rowSaving = savingRowKeys.has(rowKey);
const configBadges = [
model.config?.vision && "vision",
model.config?.tool_choice && "tool",
Expand Down Expand Up @@ -499,7 +510,9 @@ export function BuiltinModelsDialog({
className="h-7 px-2 text-xs"
onClick={(event) => {
event.stopPropagation();
onEditFromBuiltin(model);
if (existingModel) {
onEditFromBuiltin(model, existingModel);
}
}}
>
{t("model.builtin.editFromThis")}
Expand All @@ -522,15 +535,13 @@ export function BuiltinModelsDialog({
type="button"
size="sm"
className="h-7 px-2 text-xs"
disabled={savingRowKey === rowKey}
disabled={rowSaving}
onClick={(event) => {
event.stopPropagation();
void handleAddBuiltin(row);
}}
>
{savingRowKey === rowKey
? t("model.builtin.importing")
: t("model.builtin.add")}
{rowSaving ? t("model.builtin.importing") : t("model.builtin.add")}
</Button>
</>
)}
Expand Down
4 changes: 3 additions & 1 deletion web/src/feature/model/components/ModelDialog.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ interface ModelDialogProps {
onOpenChange: (open: boolean) => void
mode: 'create' | 'update'
model?: ModelConfig | null
baseModelConfig?: ModelConfig | null
preserveModelNameOnCreate?: boolean
}

Expand All @@ -31,6 +32,7 @@ export function ModelDialog({
onOpenChange,
mode = 'create',
model = null,
baseModelConfig = model,
preserveModelNameOnCreate = false
}: ModelDialogProps) {
const { t } = useTranslation()
Expand Down Expand Up @@ -80,7 +82,7 @@ export function ModelDialog({
<ModelForm
mode={mode}
defaultValues={defaultValues}
baseModelConfig={model}
baseModelConfig={baseModelConfig}
onSuccess={() => onOpenChange(false)}
/>
</motion.div>
Expand Down
Loading
Loading