feat(models): support object type in extra parameters (#2158)

Add 'object' as a new value type for model extra parameters so users can
configure nested JSON like {"thinking": {"type": "disabled"}} required by
DeepSeek-v4 non-thinking mode (refs #2157).

UI: add 'Object' option to the type dropdown in ExtraArgsEditor; render a
full-width JSON Textarea (resize-y, monospace) with live JSON validation.
On save, JSON is parsed and rejected if not a plain object.

Also make the model edit and add-model popovers scrollable: cap height at
min(70vh, --radix-popover-content-available-height), stop wheel/touchmove
propagation so the dialog's react-remove-scroll lock doesn't swallow
events, and use overscroll-none to avoid the bottom border seam from
rubber-band overscroll.

i18n updated for all 8 locales.

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
Junyan Chin
2026-05-01 20:44:17 +08:00
committed by GitHub
parent b9662250a6
commit 8db55267d8
13 changed files with 184 additions and 57 deletions
@@ -29,15 +29,36 @@ interface ModelsDialogProps {
onOpenChange: (open: boolean) => void;
}
type ExtraArgValue = string | number | boolean | Record<string, unknown>;
function convertExtraArgsToObject(
args: ExtraArg[],
): Record<string, string | number | boolean> {
const obj: Record<string, string | number | boolean> = {};
): Record<string, ExtraArgValue> {
const obj: Record<string, ExtraArgValue> = {};
args.forEach((arg) => {
if (arg.key.trim()) {
if (arg.type === 'number') obj[arg.key] = Number(arg.value);
else if (arg.type === 'boolean') obj[arg.key] = arg.value === 'true';
else obj[arg.key] = arg.value;
if (!arg.key.trim()) return;
if (arg.type === 'number') {
obj[arg.key] = Number(arg.value);
} else if (arg.type === 'boolean') {
obj[arg.key] = arg.value === 'true';
} else if (arg.type === 'object') {
const raw = arg.value.trim() || '{}';
let parsed: unknown;
try {
parsed = JSON.parse(raw);
} catch {
throw new Error(`Invalid JSON for extra parameter "${arg.key}"`);
}
if (
parsed === null ||
typeof parsed !== 'object' ||
Array.isArray(parsed)
) {
throw new Error(`Extra parameter "${arg.key}" must be a JSON object`);
}
obj[arg.key] = parsed as Record<string, unknown>;
} else {
obj[arg.key] = arg.value;
}
});
return obj;