Add per-model generation settings to the model selector

Each text and vision harness setting now carries the generation settings
its model takes (temperature, sampling limits, penalties, seed, reasoning
effort), edited in a modal under the model pick so the harness block stays
short. Nothing is set by default, so models keep their provider's own
values until a super admin or admin changes them.

A setting is only offered and only sent when the catalog says the model
takes it: OpenRouter's supported_parameters is now stored on
harness_models and refreshed by the hourly sync. Other providers list no
parameters, so their models get them all.
This commit is contained in:
2026-10-22 04:52:55 +01:00
parent fe502b38fe
commit c2553a4746
25 changed files with 644 additions and 13 deletions
@@ -30,6 +30,22 @@ function isSame({ a, b }: { a: HarnessFormValue; b?: HarnessFormValue }) {
(a.provider_id ?? null) == (b!.provider_id ?? null) &&
a.fallback == b!.fallback &&
a.enabled == b!.enabled &&
(a.voice || "") == (b!.voice || "")
(a.voice || "") == (b!.voice || "") &&
paramsKey({ params: a.params }) == paramsKey({ params: b!.params })
);
}
/**
* The generation settings as one comparable string.
*/
export function paramsKey({
params,
}: {
params?: Record<string, number | string>;
}) {
const entries = Object.entries(params || {}).sort(([a], [b]) =>
a.localeCompare(b),
);
return JSON.stringify(entries);
}
@@ -1,3 +1,4 @@
import { harnessParametersFromOptions } from "@/src/dict/harness-parameter-dict";
import type {
HarnessOverview,
HarnessSettingsFormObject,
@@ -26,6 +27,9 @@ export default function toHarnessForm({
typeof harness.options.voice == "string"
? harness.options.voice
: undefined,
params: harnessParametersFromOptions({
options: harness.options,
}),
},
]),
);