diff --git a/src/plugin/messages-transform.test.ts b/src/plugin/messages-transform.test.ts index 57ca0eece..e0b881a9a 100644 --- a/src/plugin/messages-transform.test.ts +++ b/src/plugin/messages-transform.test.ts @@ -419,7 +419,48 @@ describe("createMessagesTransformHandler", () => { }) }) - it("#given models that still allow assistant prefill or missing model metadata #when messages transform runs #then it keeps the assistant tail unchanged", async () => { + it("#given any Anthropic Claude history ends with an assistant tail #when messages transform runs #then it appends a synthetic user recovery turn", async () => { + //#given + const messages: TestMessage[] = [ + { + info: { + id: "msg_user_any_anthropic", + role: "user", + sessionID: "ses_any_anthropic_prefill", + agent: "sisyphus", + model: { providerID: "anthropic", modelID: "claude-sonnet-4-5" }, + }, + parts: [{ type: "text", text: "continue" }], + }, + { + info: { + id: "msg_assistant_any_anthropic", + role: "assistant", + sessionID: "ses_any_anthropic_prefill", + }, + parts: [{ type: "text", text: "done" }], + }, + ] + + //#when + await runHandler(makeHooks({}), messages) + + //#then + expect(messages).toHaveLength(3) + expect(messages.at(-1)?.info).toMatchObject({ + role: "user", + sessionID: "ses_any_anthropic_prefill", + agent: "sisyphus", + model: { providerID: "anthropic", modelID: "claude-sonnet-4-5" }, + }) + expect(messages.at(-1)?.parts[0]).toMatchObject({ + type: "text", + text: "[internal] Continue from the previous assistant state.", + synthetic: true, + }) + }) + + it("#given non-Anthropic models or missing model metadata #when messages transform runs #then it keeps the assistant tail unchanged", async () => { //#given const scenarios: Array<{ name: string; userInfo: TestMessage["info"] }> = [ { @@ -429,13 +470,6 @@ describe("createMessagesTransformHandler", () => { model: { providerID: "openai", modelID: "gpt-5.4" }, }, }, - { - name: "anthropic allowed", - userInfo: { - role: "user", - model: { providerID: "anthropic", modelID: "claude-sonnet-4-5" }, - }, - }, { name: "missing model", userInfo: { role: "user" }, diff --git a/src/plugin/messages-transform.ts b/src/plugin/messages-transform.ts index d49d53f44..58e87a152 100644 --- a/src/plugin/messages-transform.ts +++ b/src/plugin/messages-transform.ts @@ -9,12 +9,6 @@ const ASSISTANT_PREFILL_UNSUPPORTED_PROVIDERS = new Set([ "anthropic", "google-vertex-anthropic", ]) -const ASSISTANT_PREFILL_UNSUPPORTED_MODEL_PREFIXES = [ - "claude-opus-4-7", - "claude-opus-4-6", - "claude-sonnet-4-6", - "claude-mythos", -] type MessageWithParts = { info: Message @@ -101,8 +95,7 @@ function shouldRepairAssistantPrefillForModel(model: ModelIdentifier | undefined return false } - const modelID = normalizeModelID(model.modelID.toLowerCase()) - return ASSISTANT_PREFILL_UNSUPPORTED_MODEL_PREFIXES.some((prefix) => modelID.startsWith(prefix)) + return normalizeModelID(model.modelID.toLowerCase()).startsWith("claude-") } function isCompactionContinuationPart(part: unknown): boolean {