Normalize default thinking options (#1028)
This commit is contained in:
@@ -71,6 +71,15 @@ export interface AgentSelectOption {
|
|||||||
metadata?: AgentMetadata;
|
metadata?: AgentMetadata;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function normalizeAgentModelDefinition(model: AgentModelDefinition): AgentModelDefinition {
|
||||||
|
const defaultThinkingOptionId =
|
||||||
|
model.defaultThinkingOptionId ?? model.thinkingOptions?.find((option) => option.isDefault)?.id;
|
||||||
|
if (!defaultThinkingOptionId || defaultThinkingOptionId === model.defaultThinkingOptionId) {
|
||||||
|
return model;
|
||||||
|
}
|
||||||
|
return { ...model, defaultThinkingOptionId };
|
||||||
|
}
|
||||||
|
|
||||||
export interface ProviderSnapshotEntry {
|
export interface ProviderSnapshotEntry {
|
||||||
provider: AgentProvider;
|
provider: AgentProvider;
|
||||||
status: ProviderStatus;
|
status: ProviderStatus;
|
||||||
|
|||||||
@@ -755,6 +755,45 @@ describe("model merging", () => {
|
|||||||
]);
|
]);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test("profile thinking option default is normalized onto the model", async () => {
|
||||||
|
const registry = buildProviderRegistry(logger, {
|
||||||
|
providerOverrides: {
|
||||||
|
codex: {
|
||||||
|
models: [
|
||||||
|
{
|
||||||
|
id: "profile-default",
|
||||||
|
label: "Profile Default",
|
||||||
|
isDefault: true,
|
||||||
|
thinkingOptions: [
|
||||||
|
{ id: "off", label: "Off" },
|
||||||
|
{ id: "max", label: "Max", isDefault: true },
|
||||||
|
],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
const models = await registry.codex.fetchModels({
|
||||||
|
cwd: "/tmp/registry-models",
|
||||||
|
force: false,
|
||||||
|
});
|
||||||
|
|
||||||
|
expect(models).toEqual([
|
||||||
|
{
|
||||||
|
provider: "codex",
|
||||||
|
id: "profile-default",
|
||||||
|
label: "Profile Default",
|
||||||
|
isDefault: true,
|
||||||
|
thinkingOptions: [
|
||||||
|
{ id: "off", label: "Off" },
|
||||||
|
{ id: "max", label: "Max", isDefault: true },
|
||||||
|
],
|
||||||
|
defaultThinkingOptionId: "max",
|
||||||
|
},
|
||||||
|
]);
|
||||||
|
});
|
||||||
|
|
||||||
test("additional models append to runtime models", async () => {
|
test("additional models append to runtime models", async () => {
|
||||||
mockState.runtimeModels.set("claude", [
|
mockState.runtimeModels.set("claude", [
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -14,6 +14,7 @@ import type {
|
|||||||
ListPersistedAgentsOptions,
|
ListPersistedAgentsOptions,
|
||||||
PersistedAgentDescriptor,
|
PersistedAgentDescriptor,
|
||||||
} from "./agent-sdk-types.js";
|
} from "./agent-sdk-types.js";
|
||||||
|
import { normalizeAgentModelDefinition } from "./agent-sdk-types.js";
|
||||||
import type { WorkspaceGitService } from "../workspace-git-service.js";
|
import type { WorkspaceGitService } from "../workspace-git-service.js";
|
||||||
import type {
|
import type {
|
||||||
AgentProviderRuntimeSettingsMap,
|
AgentProviderRuntimeSettingsMap,
|
||||||
@@ -263,11 +264,11 @@ function mapPersistedAgentDescriptor(
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
function mapModel(provider: AgentProvider, model: AgentModelDefinition): AgentModelDefinition {
|
function mapModel(
|
||||||
return {
|
provider: AgentProvider,
|
||||||
...model,
|
model: AgentModelDefinition | ProviderProfileModel,
|
||||||
provider,
|
): AgentModelDefinition {
|
||||||
};
|
return normalizeAgentModelDefinition({ ...model, provider });
|
||||||
}
|
}
|
||||||
|
|
||||||
function mergeModels(
|
function mergeModels(
|
||||||
@@ -281,10 +282,7 @@ function mergeModels(
|
|||||||
if (profileModels.length > 0 && options?.profileModelsAreAdditive !== true) {
|
if (profileModels.length > 0 && options?.profileModelsAreAdditive !== true) {
|
||||||
return mergeModelAdditions(
|
return mergeModelAdditions(
|
||||||
provider,
|
provider,
|
||||||
profileModels.map((model) => ({
|
profileModels.map((model) => mapModel(provider, model)),
|
||||||
...model,
|
|
||||||
provider,
|
|
||||||
})),
|
|
||||||
additionalModels,
|
additionalModels,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@@ -305,10 +303,7 @@ function mergeModelAdditions(
|
|||||||
let hasAdditionalDefault = false;
|
let hasAdditionalDefault = false;
|
||||||
|
|
||||||
for (const model of modelAdditions) {
|
for (const model of modelAdditions) {
|
||||||
const additionalModel = {
|
const additionalModel = mapModel(provider, model);
|
||||||
...model,
|
|
||||||
provider,
|
|
||||||
};
|
|
||||||
hasAdditionalDefault ||= additionalModel.isDefault === true;
|
hasAdditionalDefault ||= additionalModel.isDefault === true;
|
||||||
|
|
||||||
const existingIndex = mergedModels.findIndex((candidate) => candidate.id === model.id);
|
const existingIndex = mergedModels.findIndex((candidate) => candidate.id === model.id);
|
||||||
|
|||||||
@@ -38,6 +38,39 @@ describe("provider snapshot message schemas", () => {
|
|||||||
expect(parsed.enabled).toBe(true);
|
expect(parsed.enabled).toBe(true);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test("normalizes thinking option defaults on provider snapshot models", () => {
|
||||||
|
const parsed = ProviderSnapshotEntrySchema.parse({
|
||||||
|
provider: "claude",
|
||||||
|
status: "ready",
|
||||||
|
models: [
|
||||||
|
{
|
||||||
|
provider: "claude",
|
||||||
|
id: "MiniMax-M2.7",
|
||||||
|
label: "MiniMax-M2.7",
|
||||||
|
isDefault: true,
|
||||||
|
thinkingOptions: [
|
||||||
|
{ id: "off", label: "Off" },
|
||||||
|
{ id: "max", label: "Max", isDefault: true },
|
||||||
|
],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
});
|
||||||
|
|
||||||
|
expect(parsed.models).toEqual([
|
||||||
|
{
|
||||||
|
provider: "claude",
|
||||||
|
id: "MiniMax-M2.7",
|
||||||
|
label: "MiniMax-M2.7",
|
||||||
|
isDefault: true,
|
||||||
|
thinkingOptions: [
|
||||||
|
{ id: "off", label: "Off" },
|
||||||
|
{ id: "max", label: "Max", isDefault: true },
|
||||||
|
],
|
||||||
|
defaultThinkingOptionId: "max",
|
||||||
|
},
|
||||||
|
]);
|
||||||
|
});
|
||||||
|
|
||||||
test("defaults missing enabled state in providers snapshot response entries", () => {
|
test("defaults missing enabled state in providers snapshot response entries", () => {
|
||||||
const parsed = GetProvidersSnapshotResponseMessageSchema.parse({
|
const parsed = GetProvidersSnapshotResponseMessageSchema.parse({
|
||||||
type: "get_providers_snapshot_response",
|
type: "get_providers_snapshot_response",
|
||||||
|
|||||||
@@ -3,7 +3,10 @@ import { CLIENT_CAPS } from "./client-capabilities.js";
|
|||||||
import { AGENT_LIFECYCLE_STATUSES } from "./agent-lifecycle.js";
|
import { AGENT_LIFECYCLE_STATUSES } from "./agent-lifecycle.js";
|
||||||
import { MAX_EXPLICIT_AGENT_TITLE_CHARS } from "../server/agent/agent-title-limits.js";
|
import { MAX_EXPLICIT_AGENT_TITLE_CHARS } from "../server/agent/agent-title-limits.js";
|
||||||
import { AgentProviderSchema } from "../server/agent/provider-manifest.js";
|
import { AgentProviderSchema } from "../server/agent/provider-manifest.js";
|
||||||
import { TOOL_CALL_ICON_NAMES } from "../server/agent/agent-sdk-types.js";
|
import {
|
||||||
|
normalizeAgentModelDefinition,
|
||||||
|
TOOL_CALL_ICON_NAMES,
|
||||||
|
} from "../server/agent/agent-sdk-types.js";
|
||||||
import {
|
import {
|
||||||
ChatCreateRequestSchema,
|
ChatCreateRequestSchema,
|
||||||
ChatListRequestSchema,
|
ChatListRequestSchema,
|
||||||
@@ -194,16 +197,18 @@ export const AgentFeatureSchema = z.discriminatedUnion("type", [
|
|||||||
AgentFeatureSelectSchema,
|
AgentFeatureSelectSchema,
|
||||||
]);
|
]);
|
||||||
|
|
||||||
const AgentModelDefinitionSchema: z.ZodType<AgentModelDefinition> = z.object({
|
const AgentModelDefinitionSchema: z.ZodType<AgentModelDefinition> = z
|
||||||
provider: AgentProviderSchema,
|
.object({
|
||||||
id: z.string(),
|
provider: AgentProviderSchema,
|
||||||
label: z.string(),
|
id: z.string(),
|
||||||
description: z.string().optional(),
|
label: z.string(),
|
||||||
isDefault: z.boolean().optional(),
|
description: z.string().optional(),
|
||||||
metadata: z.record(z.unknown()).optional(),
|
isDefault: z.boolean().optional(),
|
||||||
thinkingOptions: z.array(AgentSelectOptionSchema).optional(),
|
metadata: z.record(z.unknown()).optional(),
|
||||||
defaultThinkingOptionId: z.string().optional(),
|
thinkingOptions: z.array(AgentSelectOptionSchema).optional(),
|
||||||
});
|
defaultThinkingOptionId: z.string().optional(),
|
||||||
|
})
|
||||||
|
.transform(normalizeAgentModelDefinition);
|
||||||
|
|
||||||
export const ProviderSnapshotEntrySchema = z.object({
|
export const ProviderSnapshotEntrySchema = z.object({
|
||||||
provider: AgentProviderSchema,
|
provider: AgentProviderSchema,
|
||||||
|
|||||||
Reference in New Issue
Block a user