Skip to content

Commit 58f5215

Browse files
Revert "cleanup: remove ModelId"
This reverts commit 7466a88.
1 parent 7466a88 commit 58f5215

2 files changed

Lines changed: 71 additions & 0 deletions

File tree

src/ModelId.ts

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
import type {ReasoningEffort, ServiceTier} from "./app-server";
2+
import type {Model} from "./app-server/v2";
3+
4+
/**
5+
* ACP Model ID, combining the base model ID, reasoning effort level, and optional service tier.
6+
* @example
7+
* const id = ModelId.fromString("gpt-5.2[high]");
8+
* const fastId = ModelId.fromString("gpt-5.2[high]@fast");
9+
*/
10+
export class ModelId {
11+
private constructor(
12+
public readonly model: string,
13+
public readonly effort: string,
14+
public readonly serviceTier: ServiceTier | null = null
15+
) {}
16+
17+
static fromComponents(model: Model, effort: ReasoningEffort, serviceTier: ServiceTier | null = null): ModelId {
18+
return new ModelId(model.id, effort, serviceTier);
19+
}
20+
21+
static create(modelId: string, effort: ReasoningEffort, serviceTier: ServiceTier | null = null): ModelId {
22+
return new ModelId(modelId, effort, serviceTier);
23+
}
24+
25+
static fromString(modelId: string): ModelId {
26+
const bracketMatch = modelId.match(/^(?<model>[^\[]+)\[(?<effort>[^\]]+)](?:@(?<serviceTier>.+))?$/);
27+
const model = bracketMatch?.groups?.["model"];
28+
const effort = bracketMatch?.groups?.["effort"];
29+
const serviceTier = bracketMatch?.groups?.["serviceTier"] ?? null;
30+
31+
if (!model || !effort) {
32+
throw new Error(`Unsupported format of modelId: ${modelId}. Expected: modelId[effort] or modelId[effort]@fast.`);
33+
}
34+
35+
// The generated app-server ServiceTier type also includes "flex", but ACP model IDs
36+
// only expose Fast variants for now because model/list advertises Fast support.
37+
if (serviceTier !== null && serviceTier !== "fast") {
38+
throw new Error(`Unsupported service tier ${serviceTier} for modelId: ${modelId}.`);
39+
}
40+
41+
return new ModelId(model, effort, serviceTier);
42+
}
43+
44+
toString(): string {
45+
const suffix = this.serviceTier === null ? "" : `@${this.serviceTier}`;
46+
return `${this.model}[${this.effort}]${suffix}`;
47+
}
48+
}

src/__tests__/ModelId.test.ts

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
import {describe, expect, it} from "vitest";
2+
import {ModelId} from "../ModelId";
3+
4+
describe("ModelId", () => {
5+
it("formats and parses normal model IDs", () => {
6+
const modelId = ModelId.create("gpt-5.2", "medium");
7+
8+
expect(modelId.toString()).toBe("gpt-5.2[medium]");
9+
expect(ModelId.fromString("gpt-5.2[medium]")).toEqual(modelId);
10+
});
11+
12+
it("formats and parses fast model IDs", () => {
13+
const modelId = ModelId.create("gpt-5.2", "medium", "fast");
14+
15+
expect(modelId.toString()).toBe("gpt-5.2[medium]@fast");
16+
expect(ModelId.fromString("gpt-5.2[medium]@fast")).toEqual(modelId);
17+
});
18+
19+
it("rejects unknown service tiers", () => {
20+
expect(() => ModelId.fromString("gpt-5.2[medium]@flex"))
21+
.toThrow("Unsupported service tier flex");
22+
});
23+
});

0 commit comments

Comments
 (0)