mirror of
https://github.com/agentclientprotocol/claude-agent-acp.git
synced 2026-10-27 04:30:59 +00:00
fix: gate login result text on error state (#1103)
## Summary - Fixes #1092 by treating `Please run /login` in a `success` result as auth-required only when the result is actually error-shaped. - Applies the same error-state guard to goal-command failure detection so quoted login text in a normal answer does not roll back the active goal. - Adds a regression test for a successful model answer that mentions `/login` without publishing a session failure. ## Test Plan - [x] `npm run test:run -- src/tests/acp-agent.test.ts -t 'login|auth_required'` - [x] `npm run build` - [x] `npm run check` - [ ] `npm run test:run` (blocked locally by pre-existing root permission-mode assertions: `resolvePermissionMode("bypassPermissions")` and `resolvePermissionMode("bypass")` resolve to `default` when running as root) Signed-off-by: Emre K <110906681+kocaemre@users.noreply.github.com>
This commit is contained in:
@@ -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(),
|
||||
|
||||
@@ -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(
|
||||
|
||||
Reference in New Issue
Block a user