Route requests only with parameters ZDR endpoints declare, and list them
The gpt-5.6 family's zero-data-retention endpoints declare max_completion_tokens, so sending max_tokens under require_parameters excluded every ZDR route and returned HTTP 404 for the whole family. The cap is retired: the strict schema, the finish_reason check and the 64 KiB read cap already bound the response. The model fields now offer the provider's public ZDR catalog filtered by the exact conditions completions are routed under (live endpoint, strict structured outputs), fetched server-side, cached for an hour, and served at GET /api/models; the inputs stay free text so an unlisted model remains usable when the catalog is unreachable.
This commit is contained in:
@@ -8,7 +8,14 @@ import type {
|
||||
State,
|
||||
} from "./api";
|
||||
import { categoryPath, request } from "./api";
|
||||
import { DateField, Empty, ErrorMessage, Field, Modal } from "./ui";
|
||||
import {
|
||||
DateField,
|
||||
Empty,
|
||||
ErrorMessage,
|
||||
Field,
|
||||
Modal,
|
||||
ModelOptions,
|
||||
} from "./ui";
|
||||
export function Classification({
|
||||
state,
|
||||
acceptState,
|
||||
@@ -292,12 +299,7 @@ export function Classification({
|
||||
onChange={(e) => setModel(e.target.value)}
|
||||
list="model-options"
|
||||
/>
|
||||
<datalist id="model-options">
|
||||
<option value={state.settings.model} />
|
||||
<option value="gpt-4.1-mini" />
|
||||
<option value="gpt-4.1" />
|
||||
<option value="gpt-4o-mini" />
|
||||
</datalist>
|
||||
<ModelOptions id="model-options" />
|
||||
</Field>
|
||||
<fieldset className="tag-picker">
|
||||
<legend>Fields to reclassify</legend>
|
||||
|
||||
@@ -9,7 +9,7 @@ import {
|
||||
} from "lucide-react";
|
||||
import type { State } from "./api";
|
||||
import { APIError } from "./api";
|
||||
import { ErrorMessage, Field, Modal } from "./ui";
|
||||
import { ErrorMessage, Field, Modal, ModelOptions } from "./ui";
|
||||
import type { Mutate } from "./ui";
|
||||
export function Settings({ state, mutate }: { state: State; mutate: Mutate }) {
|
||||
const [model, setModel] = useState(state.settings.model);
|
||||
@@ -362,7 +362,9 @@ export function Settings({ state, mutate }: { state: State; mutate: Mutate }) {
|
||||
required
|
||||
value={model}
|
||||
onChange={(e) => setModel(e.target.value)}
|
||||
list="verified-models"
|
||||
/>
|
||||
<ModelOptions id="verified-models" />
|
||||
</Field>
|
||||
<Field
|
||||
label="Private names"
|
||||
|
||||
@@ -61,6 +61,14 @@ export interface Provenance {
|
||||
timestamp?: string;
|
||||
error?: string;
|
||||
}
|
||||
|
||||
// VerifiedModel is a model the server confirmed against the provider's public
|
||||
// catalog: it has a live zero-data-retention endpoint with strict structured
|
||||
// outputs, so classification requests can actually route to it.
|
||||
export interface VerifiedModel {
|
||||
id: string;
|
||||
name: string;
|
||||
}
|
||||
export interface Enrichment {
|
||||
kind: string;
|
||||
merchant_id?: string;
|
||||
|
||||
+23
-1
@@ -8,12 +8,13 @@ import {
|
||||
ChevronLeft,
|
||||
ChevronRight,
|
||||
} from "lucide-react";
|
||||
import type { Dataset, Filter } from "./api";
|
||||
import type { Dataset, Filter, VerifiedModel } from "./api";
|
||||
import {
|
||||
categoryPath,
|
||||
DEFAULT_MONTHS,
|
||||
defaultFilter,
|
||||
monthStart,
|
||||
request,
|
||||
yearStart,
|
||||
} from "./api";
|
||||
export function Modal({
|
||||
@@ -58,6 +59,27 @@ export function Modal({
|
||||
</dialog>
|
||||
);
|
||||
}
|
||||
// ModelOptions loads the server-verified model list once and renders it as a
|
||||
// datalist: the input stays free text so an unlisted model is still usable
|
||||
// when the catalog is unreachable.
|
||||
export function ModelOptions({ id }: { id: string }) {
|
||||
const [models, setModels] = useState<VerifiedModel[]>([]);
|
||||
useEffect(() => {
|
||||
request<VerifiedModel[]>("/api/models")
|
||||
.then(setModels)
|
||||
.catch(() => {});
|
||||
}, []);
|
||||
return (
|
||||
<datalist id={id}>
|
||||
{models.map((m) => (
|
||||
<option key={m.id} value={m.id}>
|
||||
{m.name}
|
||||
</option>
|
||||
))}
|
||||
</datalist>
|
||||
);
|
||||
}
|
||||
|
||||
export function Field({
|
||||
label,
|
||||
children,
|
||||
|
||||
Reference in New Issue
Block a user