Run models on sensible generation defaults out of the box

A fresh install had no generation settings until someone set one, so every
model ran on whatever its provider happened to use. Each harness now has a
default (text 0.3 temperature, vision 0.2, image the provider's own), shown
in the model settings modal so what a model runs on is never a guess.

The defaults are only sent to a model whose catalog lists the field, so a
provider that says nothing about its models still gets no parameter it
might reject; anything saved on a harness or bot wins over the default.
This commit is contained in:
2026-10-22 04:56:10 +01:00
parent c2553a4746
commit 8edff8988a
6 changed files with 150 additions and 13 deletions
@@ -1,12 +1,20 @@
import {
HarnessParameterHarnesses,
harnessParameterValue,
HarnessParameters,
modelTakesParameter,
type HarnessParameterKey,
} from "@/src/dict/harness-parameter-dict";
import type { HarnessKind } from "@/src/dict/harness-dict";
import type { HarnessModelOption } from "@/src/types";
import HarnessParameterControl from "./harness-parameter-control";
type Props = {
id: string;
/**
* The harness the settings are for: its default fills an empty one.
*/
harness: HarnessKind;
/**
* The model whose settings these are: only what it takes is shown.
*/
@@ -18,10 +26,14 @@ type Props = {
/**
* The generation settings the picked model takes: temperature, sampling
* limits, penalties, seed and reasoning effort. A model whose provider
* lists no parameters (anything but OpenRouter) gets them all.
* lists no parameters (anything but OpenRouter) gets them all. An empty
* one shows the value it actually runs on (the harness's default). A model
* whose provider lists nothing gets the app's default in its box, but the
* call only sends a default to a model that advertises the field.
*/
export default function HarnessParameterFields({
id,
harness,
model,
params,
onChange,
@@ -42,7 +54,13 @@ export default function HarnessParameterFields({
key={parameter.key}
id={`${id}-${parameter.key}`}
parameter={parameter}
value={params?.[parameter.key]}
value={
harnessParameterValue({
harness: harness as (typeof HarnessParameterHarnesses)[number],
params,
key: parameter.key,
}).value
}
onChange={(value) => {
const next = { ...params };
@@ -3,12 +3,23 @@ import Modal from "@moduletrace/twui/elements/Modal";
import H2 from "@moduletrace/twui/layout/H2";
import Span from "@moduletrace/twui/layout/Span";
import Stack from "@moduletrace/twui/layout/Stack";
import { HarnessParameters } from "@/src/dict/harness-parameter-dict";
import {
HarnessParameterHarnesses,
harnessParameterValue,
HarnessParameterKeys,
HarnessParameters,
type HarnessParameterKey,
} from "@/src/dict/harness-parameter-dict";
import type { HarnessKind } from "@/src/dict/harness-dict";
import type { HarnessModelOption } from "@/src/types";
import HarnessParameterFields from "./harness-parameter-fields";
type Props = {
id: string;
/**
* The harness the settings are for: its default fills an empty one.
*/
harness: HarnessKind;
/**
* The model the settings are for: only what it takes is offered.
*/
@@ -24,13 +35,27 @@ type Props = {
*/
export default function HarnessParameterModal({
id,
harness,
model,
params,
onChange,
}: Props) {
const [open, setOpen] = useState(false);
/**
* Nothing saved yet: every value shown is the app's default for it.
*/
const using_defaults = !Object.entries(params || {}).some(
([key, value]) =>
value !== undefined &&
value !== "" &&
HarnessParameterKeys.includes(key as HarnessParameterKey),
);
const set = HarnessParameters.flatMap((parameter) => {
const value = params?.[parameter.key];
const { value } = harnessParameterValue({
harness: harness as (typeof HarnessParameterHarnesses)[number],
params,
key: parameter.key,
});
if (value === undefined || value === "") return [];
@@ -52,7 +77,7 @@ export default function HarnessParameterModal({
</Span>
<Span className="text-xs leading-4 text-ink-secondary">
{set.length
? set.join(" · ")
? `${using_defaults ? "Default: " : ""}${set.join(" · ")}`
: "Temperature, reasoning effort, sampling limits"}
</Span>
</Stack>
@@ -70,14 +95,16 @@ export default function HarnessParameterModal({
{model.name} settings
</H2>
<Span className="text-[13px] leading-[18px] text-ink-secondary">
How this model answers. Empty leaves the provider's own
default; a lower temperature keeps a bot literal and
repeatable.
How this model answers. The filled-in values are what it
runs on now (the app's default for this harness, else the
provider's own); a lower temperature keeps a bot literal
and repeatable.
</Span>
</Stack>
<Stack className="w-full gap-4! items-stretch">
<HarnessParameterFields
id={id}
harness={harness}
model={model}
params={params}
onChange={onChange}
@@ -93,6 +93,7 @@ export default function HarnessSettingGroup({ harness, value, onChange }: Props)
{shows_params && params_model ? (
<HarnessParameterModal
id={id}
harness={harness.harness}
model={params_model}
params={value.params}
onChange={(params) => onChange({ ...value, params })}