From 6b2142eb0036bbb98fa21a1b44e69d3142e0eb6b Mon Sep 17 00:00:00 2001 From: Dotta Date: Tue, 10 Nov 2026 03:50:33 -0600 Subject: [PATCH] Revert "fix(runner): name an ACP agent's rejection of an unadvertised model" This reverts commit 35aff22dd3e7971547370029a6e4a6d0ee3fd5ac. --- .../drivers/acpx/model-verification.test.ts | 28 ------------------- .../src/drivers/acpx/model-verification.ts | 25 +---------------- 2 files changed, 1 insertion(+), 52 deletions(-) diff --git a/packages/paperclip-runner/src/drivers/acpx/model-verification.test.ts b/packages/paperclip-runner/src/drivers/acpx/model-verification.test.ts index d816bf7fe67..6c36e3a0774 100644 --- a/packages/paperclip-runner/src/drivers/acpx/model-verification.test.ts +++ b/packages/paperclip-runner/src/drivers/acpx/model-verification.test.ts @@ -2,7 +2,6 @@ import { describe, expect, it, vi } from "vitest"; import { resolveQualifiedAcpxProfile } from "./qualified-profiles.js"; import { requireVerifiedAcpxModel } from "./model-verification.js"; -import { acpxSidecarErrorCode } from "../../cli/acpx-sidecar-input.js"; describe("ACPX requested model verification", () => { it.each(["claude", "codex", "pi", "grok", "cursor", "copilot"] as const)("selects and verifies an unlisted model unchanged with %s", async agent => { @@ -30,33 +29,6 @@ describe("ACPX requested model verification", () => { expect(getStatus).toHaveBeenCalledTimes(1); }); - it.each(["claude", "codex", "pi", "grok", "cursor", "copilot"] as const)("names an ACP rejection of an unadvertised model as an unsupported model with %s", async agent => { - const model = "chaos-missing-model-abc12345"; - // claude-agent-acp 0.73.0 answers session/set_config_option for an unknown model with this - // JSON-RPC error; ACPX wraps it as below (live probe, 2026-11-10). - const acp = Object.assign(new Error("Internal error"), { - code: -32603, data: { details: `Invalid value for config option model: ${model}` }, - }); - const wrapped = new Error(`Failed session/set_config_option for model "${model}": Invalid value for config option model: ${model} (ACP -32603, adapter reported "Internal error")`, { cause: acp }); - const getStatus = vi.fn(async () => ({ models: { currentModelId: "default", availableModelIds: ["default", "opus", "sonnet"] } })); - const setModel = vi.fn(async () => { throw wrapped; }); - const failure = await requireVerifiedAcpxModel({ getStatus, setModel }, resolveQualifiedAcpxProfile(agent, model)) - .then(() => null, (error: unknown) => error as Error & { code?: unknown; retryable?: unknown }); - expect(failure).toMatchObject({ code: "ACP_MODEL_UNSUPPORTED", retryable: false }); - expect(failure?.cause).toBe(wrapped); - expect(acpxSidecarErrorCode(failure!)).toBe("ACP_MODEL_UNSUPPORTED"); - }); - - it("keeps a transport failure or an advertised model's rejection unchanged", async () => { - const acp = Object.assign(new Error("Internal error"), { code: -32603, data: { details: "busy" } }); - for (const [rejected, available] of [[new Error("socket closed"), ["default"]], [acp, ["default", "listed-model"]]] as const) { - const getStatus = vi.fn(async () => ({ models: { currentModelId: "default", availableModelIds: [...available] } })); - const setModel = vi.fn(async () => { throw rejected; }); - await expect(requireVerifiedAcpxModel({ getStatus, setModel }, resolveQualifiedAcpxProfile("claude", "listed-model"))) - .rejects.toBe(rejected); - } - }); - it("accepts an exact model already reported by the provider", async () => { const getStatus = vi.fn(async () => ({ models: { diff --git a/packages/paperclip-runner/src/drivers/acpx/model-verification.ts b/packages/paperclip-runner/src/drivers/acpx/model-verification.ts index 1b0afdd4a8e..337d2612c77 100644 --- a/packages/paperclip-runner/src/drivers/acpx/model-verification.ts +++ b/packages/paperclip-runner/src/drivers/acpx/model-verification.ts @@ -38,22 +38,7 @@ export async function requireVerifiedAcpxModel( ); } // Catalogs may be incomplete. Let the provider accept or reject the exact ID. - try { - await control.setModel(providerModel); - } catch (error) { - // The provider answered the selection of a model it does not advertise with - // an ACP error: it rejected that model. Name it as such so the task asks the - // user to choose a model. Transport failures and an advertised model's - // rejection keep their original error. - const advertised = status.models?.availableModelIds ?? []; - if (!advertised.includes(providerModel) && acpErrorResponse(error)) { - throw Object.assign( - new Error(`ACP agent rejected the requested model ${requestedModel}`, { cause: error }), - { code: "ACP_MODEL_UNSUPPORTED", retryable: false }, - ); - } - throw error; - } + await control.setModel(providerModel); status = await control.getStatus(); } if (status.models?.currentModelId !== providerModel) { @@ -65,14 +50,6 @@ export async function requireVerifiedAcpxModel( return normalizeVerifiedModelStatus(status, profile); } -/** A JSON-RPC error response from the ACP agent, found on the error or its causes. */ -function acpErrorResponse(error: unknown, depth = 0): boolean { - if (!error || typeof error !== "object" || depth > 5) return false; - const entry = error as Record; - if (typeof entry.code === "number" && Number.isInteger(entry.code) && typeof entry.message === "string") return true; - return ["acp", "cause", "error"].some(key => acpErrorResponse(entry[key], depth + 1)); -} - function acpxModelVerificationError(code: string, message: string): Error { return Object.assign(new Error(message), { code }); }