fix(models): normalize trailing @profile parsing across resolver paths

Co-authored-by: Vincent Koc <vincentkoc@ieee.org>
Co-authored-by: Marcus Castro <mcaxtr@gmail.com>
Co-authored-by: Brandon Wise <brandonawise@gmail.com>
This commit is contained in:
Peter Steinberger
2026-02-26 14:31:57 +01:00
parent 00e8e88a7c
commit 4b259ab81b
8 changed files with 208 additions and 14 deletions

View File

@@ -50,6 +50,20 @@ describe("extractModelDirective", () => {
expect(result.rawProfile).toBe("work");
});
it("keeps Cloudflare @cf path segments inside model ids", () => {
const result = extractModelDirective("/model openai/@cf/openai/gpt-oss-20b");
expect(result.hasDirective).toBe(true);
expect(result.rawModel).toBe("openai/@cf/openai/gpt-oss-20b");
expect(result.rawProfile).toBeUndefined();
});
it("allows profile overrides after Cloudflare @cf path segments", () => {
const result = extractModelDirective("/model openai/@cf/openai/gpt-oss-20b@cf:default");
expect(result.hasDirective).toBe(true);
expect(result.rawModel).toBe("openai/@cf/openai/gpt-oss-20b");
expect(result.rawProfile).toBe("cf:default");
});
it("returns no directive for plain text", () => {
const result = extractModelDirective("hello world");
expect(result.hasDirective).toBe(false);

View File

@@ -1,3 +1,4 @@
import { splitTrailingAuthProfile } from "../agents/model-ref-profile.js";
import { escapeRegExp } from "../utils.js";
export function extractModelDirective(
@@ -34,15 +35,9 @@ export function extractModelDirective(
let rawModel = raw;
let rawProfile: string | undefined;
if (raw) {
const atIndex = raw.lastIndexOf("@");
if (atIndex > 0) {
const candidateModel = raw.slice(0, atIndex).trim();
const candidateProfile = raw.slice(atIndex + 1).trim();
if (candidateModel && candidateProfile && !candidateProfile.includes("/")) {
rawModel = candidateModel;
rawProfile = candidateProfile;
}
}
const split = splitTrailingAuthProfile(raw);
rawModel = split.model;
rawProfile = split.profile;
}
const cleaned = match ? body.replace(match[0], " ").replace(/\s+/g, " ").trim() : body.trim();

View File

@@ -172,6 +172,21 @@ describe("/model chat UX", () => {
isDefault: false,
});
});
it("keeps cloudflare @cf model segments for exact selections", () => {
const resolved = resolveModelSelectionForCommand({
command: "/model openai/@cf/openai/gpt-oss-20b",
allowedModelKeys: new Set(["openai/@cf/openai/gpt-oss-20b"]),
allowedModelCatalog: [],
});
expect(resolved.errorText).toBeUndefined();
expect(resolved.modelSelection).toEqual({
provider: "openai",
model: "@cf/openai/gpt-oss-20b",
isDefault: false,
});
});
});
describe("handleDirectiveOnly model persist behavior (fixes #1435)", () => {