fix(runner): select qualified ACP model alias
This commit is contained in:
parent
f5af8b2482
commit
cbfb4f1bef
|
|
@ -24,7 +24,7 @@ describe("ACPX qualified model verification", () => {
|
|||
expect(setModel).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it("selects Claude's canonical model and normalizes its ACP selector", async () => {
|
||||
it("accepts and normalizes Claude's qualified ACP selector", async () => {
|
||||
const setModel = vi.fn(async () => undefined);
|
||||
const getStatus = vi.fn(async () => ({
|
||||
models: {
|
||||
|
|
@ -33,6 +33,34 @@ describe("ACPX qualified model verification", () => {
|
|||
},
|
||||
}));
|
||||
|
||||
await expect(
|
||||
requireVerifiedAcpxModel(
|
||||
{ getStatus, setModel },
|
||||
resolveQualifiedAcpxProfile("claude", "claude-sonnet-5"),
|
||||
),
|
||||
).resolves.toMatchObject({
|
||||
models: {
|
||||
currentModelId: "claude-sonnet-5",
|
||||
availableModelIds: ["default", "claude-sonnet-5", "opus"],
|
||||
},
|
||||
});
|
||||
expect(setModel).not.toHaveBeenCalled();
|
||||
expect(getStatus).toHaveBeenCalledTimes(1);
|
||||
});
|
||||
|
||||
it("selects Claude's profile-pinned ACP selector from a stale default", async () => {
|
||||
let selected = false;
|
||||
const setModel = vi.fn(async (model: string) => {
|
||||
expect(model).toBe("sonnet");
|
||||
selected = true;
|
||||
});
|
||||
const getStatus = vi.fn(async () => ({
|
||||
models: {
|
||||
currentModelId: selected ? "sonnet" : "default",
|
||||
availableModelIds: ["default", "sonnet", "opus"],
|
||||
},
|
||||
}));
|
||||
|
||||
await expect(
|
||||
requireVerifiedAcpxModel(
|
||||
{ getStatus, setModel },
|
||||
|
|
@ -45,7 +73,7 @@ describe("ACPX qualified model verification", () => {
|
|||
},
|
||||
});
|
||||
expect(setModel).toHaveBeenCalledTimes(1);
|
||||
expect(setModel).toHaveBeenCalledWith("claude-sonnet-5");
|
||||
expect(setModel).toHaveBeenCalledWith("sonnet");
|
||||
expect(getStatus).toHaveBeenCalledTimes(2);
|
||||
});
|
||||
|
||||
|
|
|
|||
|
|
@ -28,24 +28,26 @@ export async function requireVerifiedAcpxModel(
|
|||
);
|
||||
}
|
||||
const requestedModel = profile.qualificationModel;
|
||||
const providerModel = profile.reportedModelId;
|
||||
let status = await control.getStatus();
|
||||
const mustSelectCanonical =
|
||||
profile.reportedModelId !== requestedModel ||
|
||||
status.models?.currentModelId !== requestedModel;
|
||||
if (mustSelectCanonical) {
|
||||
if (status.models?.currentModelId !== providerModel) {
|
||||
if (!control.setModel) {
|
||||
throw acpxModelVerificationError(
|
||||
"ACPX_MODEL_SELECTION_UNAVAILABLE",
|
||||
"ACPX agent cannot verify its canonical model through ACP config options",
|
||||
"ACPX agent cannot verify its qualified model through ACP config options",
|
||||
);
|
||||
}
|
||||
await control.setModel(requestedModel);
|
||||
// The caller-facing model is already pinned by resolveQualifiedAcpxProfile.
|
||||
// Select the immutable ACP-facing identifier from that same profile: some
|
||||
// providers expose a stable selector (for example Claude's `sonnet`) while
|
||||
// Paperclip publishes the canonical model name after verification.
|
||||
await control.setModel(providerModel);
|
||||
status = await control.getStatus();
|
||||
}
|
||||
if (status.models?.currentModelId !== profile.reportedModelId) {
|
||||
if (status.models?.currentModelId !== providerModel) {
|
||||
throw acpxModelVerificationError(
|
||||
"ACPX_EFFECTIVE_MODEL_MISMATCH",
|
||||
`ACPX effective model mismatch: requested ${requestedModel}, expected ACP selector ${profile.reportedModelId}, received ${status.models?.currentModelId ?? "unverified"}`,
|
||||
`ACPX effective model mismatch: requested ${requestedModel}, expected ACP selector ${providerModel}, received ${status.models?.currentModelId ?? "unverified"}`,
|
||||
);
|
||||
}
|
||||
return normalizeQualifiedModelStatus(status, profile);
|
||||
|
|
|
|||
Loading…
Reference in New Issue