diff --git a/src/acp-agent.ts b/src/acp-agent.ts index d3c72d33..7ad9554c 100644 --- a/src/acp-agent.ts +++ b/src/acp-agent.ts @@ -5042,7 +5042,9 @@ export class ClaudeAcpAgent { const goalCommandFailed = message.is_error || message.stop_reason === "refusal" || - ("result" in message && message.result.includes("Please run /login")); + ("result" in message && + message.is_error && + message.result.includes("Please run /login")); if (goalCommandFailed) { await this.publishGoal(params.sessionId, pendingGoalUpdate.previous ?? null); } @@ -5406,7 +5408,7 @@ export class ClaudeAcpAgent { switch (message.subtype) { case "success": { - if (message.result.includes("Please run /login")) { + if (message.is_error && message.result.includes("Please run /login")) { await failActiveWithSessionFailure( "auth_required", RequestError.authRequired(), diff --git a/src/tests/acp-agent.test.ts b/src/tests/acp-agent.test.ts index a0d48239..cae687b0 100644 --- a/src/tests/acp-agent.test.ts +++ b/src/tests/acp-agent.test.ts @@ -7439,6 +7439,35 @@ describe("stop reason propagation", () => { expect(logged.join("\n")).not.toContain("cannot fail active turn"); }); + it("does not treat a successful answer mentioning /login as auth_required", async () => { + const updates: SessionNotification[] = []; + const agent = new ClaudeAcpAgent( + { + sessionUpdate: async (update: SessionNotification) => { + updates.push(update); + }, + } as unknown as AcpClient, + { log: () => {}, error: () => {} }, + ); + (agent as any).clientCapabilities = airSessionFailureCapabilities; + const answer = "A normal answer can quote: Please run /login."; + injectSession(agent, [ + createAssistantError(undefined, answer), + createResultMessage({ + subtype: "success", + stop_reason: "end_turn", + is_error: false, + result: answer, + }), + { type: "system", subtype: "session_state_changed", state: "idle" }, + ]); + + await expect( + agent.prompt({ sessionId: "test-session", prompt: [{ type: "text", text: "test" }] }), + ).resolves.toMatchObject({ stopReason: "end_turn" }); + expect(sessionFailuresFromUpdates(updates)).toEqual([]); + }); + it("republishes the signed-out state after a real model answer cleared the last one", async () => { const updates: SessionNotification[] = []; const agent = new ClaudeAcpAgent(