Skip to content

Commit b131fc3

Browse files
authored
fix: use raw model names from models/list in model picker fix #430 (#499)
1 parent 8ca3a46 commit b131fc3

2 files changed

Lines changed: 10 additions & 73 deletions

File tree

Lines changed: 8 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -1,43 +1,5 @@
11
import { describe, expect, it } from "vitest";
2-
import { formatModelSlug, parseModelListResponse } from "./modelListResponse";
3-
4-
describe("formatModelSlug", () => {
5-
it("capitalizes plain segments", () => {
6-
expect(formatModelSlug("codex-mini")).toBe("Codex-Mini");
7-
});
8-
9-
it("uppercases known acronyms", () => {
10-
expect(formatModelSlug("gpt-5.3-codex")).toBe("GPT-5.3-Codex");
11-
});
12-
13-
it("leaves version-like segments unchanged", () => {
14-
expect(formatModelSlug("gpt-5.1-codex-max")).toBe("GPT-5.1-Codex-Max");
15-
});
16-
17-
it("handles a version-only slug", () => {
18-
expect(formatModelSlug("gpt-5.2")).toBe("GPT-5.2");
19-
});
20-
it("is case-insensitive for acronym detection", () => {
21-
expect(formatModelSlug("GPT-5.3-codex")).toBe("GPT-5.3-Codex");
22-
expect(formatModelSlug("Gpt-5.3-codex")).toBe("GPT-5.3-Codex");
23-
});
24-
25-
it("returns empty string for non-string input", () => {
26-
expect(formatModelSlug(null)).toBe("");
27-
expect(formatModelSlug(undefined)).toBe("");
28-
expect(formatModelSlug(42)).toBe("");
29-
});
30-
31-
it("returns empty string for blank strings", () => {
32-
expect(formatModelSlug("")).toBe("");
33-
expect(formatModelSlug(" ")).toBe("");
34-
});
35-
36-
it("handles a single segment", () => {
37-
expect(formatModelSlug("codex")).toBe("Codex");
38-
expect(formatModelSlug("gpt")).toBe("GPT");
39-
});
40-
});
2+
import { parseModelListResponse } from "./modelListResponse";
413

424
describe("parseModelListResponse", () => {
435
it("uses displayName when present", () => {
@@ -52,34 +14,34 @@ describe("parseModelListResponse", () => {
5214
expect(model.displayName).toBe("GPT-5.3-Codex-Spark");
5315
});
5416

55-
it("formats the slug when displayName is missing", () => {
17+
it("uses the raw model slug when displayName is missing", () => {
5618
const response = {
5719
result: {
5820
data: [{ id: "m1", model: "gpt-5.3-codex" }],
5921
},
6022
};
6123
const [model] = parseModelListResponse(response);
62-
expect(model.displayName).toBe("GPT-5.3-Codex");
24+
expect(model.displayName).toBe("gpt-5.3-codex");
6325
});
6426

65-
it("formats the slug when displayName is an empty string", () => {
27+
it("uses the raw model slug when displayName is an empty string", () => {
6628
const response = {
6729
result: {
6830
data: [{ id: "m1", model: "gpt-5.1-codex-mini", displayName: "" }],
6931
},
7032
};
7133
const [model] = parseModelListResponse(response);
72-
expect(model.displayName).toBe("GPT-5.1-Codex-Mini");
34+
expect(model.displayName).toBe("gpt-5.1-codex-mini");
7335
});
7436

75-
it("formats the slug when displayName equals the model slug", () => {
37+
it("preserves displayName when it equals the model slug", () => {
7638
const response = {
7739
result: {
7840
data: [{ id: "m1", model: "gpt-5.3-codex", displayName: "gpt-5.3-codex" }],
7941
},
8042
};
8143
const [model] = parseModelListResponse(response);
82-
expect(model.displayName).toBe("GPT-5.3-Codex");
44+
expect(model.displayName).toBe("gpt-5.3-codex");
8345
});
8446

8547
it("preserves displayName when it differs from the slug", () => {
@@ -93,6 +55,6 @@ describe("parseModelListResponse", () => {
9355
};
9456
const models = parseModelListResponse(response);
9557
expect(models[0].displayName).toBe("GPT-5.3-Codex-Spark");
96-
expect(models[1].displayName).toBe("GPT-5.2-Codex");
58+
expect(models[1].displayName).toBe("gpt-5.2-codex");
9759
});
9860
});

src/features/models/utils/modelListResponse.ts

Lines changed: 2 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -1,30 +1,5 @@
11
import type { ModelOption } from "../../../types";
22

3-
const UPPERCASE_SEGMENTS = new Set(["gpt"]);
4-
5-
/**
6-
* Formats a model slug like "gpt-5.3-codex" into "GPT-5.3-Codex".
7-
* Known acronyms are uppercased, version-like segments are left as-is,
8-
* and everything else is capitalized.
9-
*/
10-
export function formatModelSlug(slug: unknown): string {
11-
if (typeof slug !== "string" || !slug.trim()) {
12-
return "";
13-
}
14-
return slug
15-
.split("-")
16-
.map((segment) => {
17-
if (UPPERCASE_SEGMENTS.has(segment.toLowerCase())) {
18-
return segment.toUpperCase();
19-
}
20-
if (/^\d/.test(segment)) {
21-
return segment;
22-
}
23-
return segment.charAt(0).toUpperCase() + segment.slice(1);
24-
})
25-
.join("-");
26-
}
27-
283
export function normalizeEffortValue(value: unknown): string | null {
294
if (typeof value !== "string") {
305
return null;
@@ -108,11 +83,11 @@ export function parseModelListResponse(response: unknown): ModelOption[] {
10883
const record = item as Record<string, unknown>;
10984
const modelSlug = String(record.model ?? record.id ?? "");
11085
const rawDisplayName = String(record.displayName || record.display_name || "");
111-
const hasCustomDisplayName = rawDisplayName !== "" && rawDisplayName !== modelSlug;
86+
const displayName = rawDisplayName.trim().length > 0 ? rawDisplayName : modelSlug;
11287
return {
11388
id: String(record.id ?? record.model ?? ""),
11489
model: modelSlug,
115-
displayName: hasCustomDisplayName ? rawDisplayName : (formatModelSlug(modelSlug) || modelSlug),
90+
displayName,
11691
description: String(record.description ?? ""),
11792
supportedReasoningEfforts: parseReasoningEfforts(record),
11893
defaultReasoningEffort: normalizeEffortValue(

0 commit comments

Comments
 (0)