Skip to content
34 changes: 33 additions & 1 deletion packages/client-runtime/src/state/threadExecution.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,10 +24,10 @@ import {
deriveLatestThreadRun,
deriveProviderSubagentStatus,
deriveResumableRunId,
formatModelSelectionEffort,
deriveRunlessWorkStartedAt,
deriveThreadActivityRun,
deriveThreadRuntime,
formatModelSelectionEffort,
isBackgroundWorkStopPending,
presentPendingBackgroundWork,
presentProviderGoal,
Expand Down Expand Up @@ -476,6 +476,38 @@ describe("provider-reported model selection", () => {
});

describe("formatModelSelectionEffort", () => {
it("finds the catalog model when the selection names it by display name or alias", () => {
const selection = {
...v2Projection.thread.modelSelection,
model: "GPT-6 Luna",
options: [{ id: "reasoning_effort", value: "medium" }],
};
const models = [
{
slug: "custom:GPT-6 Luna-12",
name: "GPT-6 Luna",
aliases: ["Luna-12"],
isCustom: true,
capabilities: {
optionDescriptors: [
{
id: "reasoning_effort",
label: "Reasoning",
type: "select" as const,
options: [
{ id: "medium", label: "Medium" },
{ id: "high", label: "High" },
],
},
],
},
},
];

expect(formatModelSelectionEffort(selection, models)).toBe("Medium");
expect(formatModelSelectionEffort({ ...selection, model: "Luna-12" }, models)).toBe("Medium");
});

it("labels an old Ultracode effort by the effort it runs at", () => {
const models = [
{
Expand Down
17 changes: 16 additions & 1 deletion packages/client-runtime/src/state/threadExecution.ts
Original file line number Diff line number Diff line change
Expand Up @@ -166,12 +166,27 @@ export const REASONING_EFFORT_OPTION_IDS: ReadonlyArray<string> = [
"thinking_level",
];

function findSelectionCatalogModel(
models: ReadonlyArray<ServerProviderModel>,
model: string,
): ServerProviderModel | undefined {
const name = model.trim().toLowerCase();
return (
models.find((candidate) => candidate.slug === model) ??
models.find(
(candidate) =>
candidate.name.trim().toLowerCase() === name ||
candidate.aliases?.some((alias) => alias.trim().toLowerCase() === name),
)
);
}

export function formatModelSelectionEffort(
selection: ModelSelection,
models: ReadonlyArray<ServerProviderModel> = [],
reportedSelection?: ModelSelection | null,
): string | null {
const caps = models.find((model) => model.slug === selection.model)?.capabilities;
const caps = findSelectionCatalogModel(models, selection.model)?.capabilities;
if (!caps) return null;
const options = withLegacyUltracodeEffort(caps.optionDescriptors, selection.options);
const current = options ? { ...selection, options } : selection;
Expand Down