Studio: persist new sampling keys through settings sanitizer

Codex P1: the runtime store added frequencyPenalty, seed, stop,
serviceTier, parallelToolCalls but the save/load path went through
sanitizeInferenceParams, which only whitelisted the older numeric set
plus systemPrompt / trustRemoteCode. The new keys were silently
stripped on save and dropped on reload.

Extend the whitelist:
- frequencyPenalty added to the numeric finite-number set.
- seed: integer or explicit null (null = "no seed field on the wire").
- stop: string array, capped at 4 entries per OpenAI's limit.
- serviceTier: nullable enum (auto/default/flex/priority/scale).
- parallelToolCalls: boolean.
This commit is contained in:
Daniel Han 2026-05-23 16:37:51 +00:00
commit ffda6bbc71

View file

@ -40,10 +40,21 @@ const NUMERIC_INFERENCE_FIELDS = [
"minP",
"repetitionPenalty",
"presencePenalty",
"frequencyPenalty",
"maxSeqLength",
"maxTokens",
] as const satisfies readonly (keyof PersistedInferenceParams)[];
// `seed` is numeric but nullable (null = "no seed field on the wire") so
// it can't go through the NUMERIC_INFERENCE_FIELDS Finite-number filter.
const VALID_SERVICE_TIERS = new Set([
"auto",
"default",
"flex",
"priority",
"scale",
]);
const CHAT_PRESET_SOURCES = new Set<string>([
"builtin-default",
"custom",
@ -140,6 +151,29 @@ function sanitizeInferenceParams(
if (typeof value.trustRemoteCode === "boolean") {
params.trustRemoteCode = value.trustRemoteCode;
}
// seed: nullable integer (null = no seed on the wire).
if (value.seed === null) {
params.seed = null;
} else if (typeof value.seed === "number" && Number.isInteger(value.seed)) {
params.seed = value.seed;
}
// stop: capped string array per OpenAI's max-4 rule.
if (Array.isArray(value.stop)) {
const stops = value.stop.filter((s): s is string => typeof s === "string");
if (stops.length > 0) params.stop = stops.slice(0, 4);
}
// serviceTier: nullable enum string.
if (value.serviceTier === null) {
params.serviceTier = null;
} else if (
typeof value.serviceTier === "string" &&
VALID_SERVICE_TIERS.has(value.serviceTier)
) {
params.serviceTier = value.serviceTier as PersistedInferenceParams["serviceTier"];
}
if (typeof value.parallelToolCalls === "boolean") {
params.parallelToolCalls = value.parallelToolCalls;
}
return hasKeys(params) ? params : undefined;
}