Skip to content

Commit 03cc362

Browse files
committed
Resolve turn interruption only on close cancellation
1 parent 3ecdaed commit 03cc362

2 files changed

Lines changed: 28 additions & 9 deletions

File tree

src/CodexAcpServer.ts

Lines changed: 15 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1193,9 +1193,7 @@ export class CodexAcpServer {
11931193
if (!turn) {
11941194
return;
11951195
}
1196-
void this.interruptPromptTurn(turn, "Cancel").catch((err) => {
1197-
logger.error("Prompt request cancellation failed to interrupt turn", err);
1198-
});
1196+
void this.requestTurnInterrupt(turn, "Cancel");
11991197
};
12001198

12011199
if (signal.aborted) {
@@ -1223,6 +1221,20 @@ export class CodexAcpServer {
12231221
threadId: turn.threadId,
12241222
turnId: turn.turnId,
12251223
});
1224+
try {
1225+
await this.requestTurnInterrupt(turn, requestName);
1226+
} finally {
1227+
this.codexAcpClient.resolveTurnInterrupted({
1228+
threadId: turn.threadId,
1229+
turnId: turn.turnId,
1230+
});
1231+
}
1232+
}
1233+
1234+
private async requestTurnInterrupt(
1235+
turn: { threadId: string, turnId: string },
1236+
requestName: "Cancel" | "Close",
1237+
): Promise<void> {
12261238
try {
12271239
await this.runWithProcessCheck(() => this.codexAcpClient.turnInterrupt({
12281240
threadId: turn.threadId,
@@ -1234,11 +1246,6 @@ export class CodexAcpServer {
12341246
});
12351247
} catch (err) {
12361248
logger.error(`${requestName} - turnInterrupt failed`, err);
1237-
} finally {
1238-
this.codexAcpClient.resolveTurnInterrupted({
1239-
threadId: turn.threadId,
1240-
turnId: turn.turnId,
1241-
});
12421249
}
12431250
}
12441251

src/__tests__/CodexACPAgent/CodexAcpClient.test.ts

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -971,8 +971,9 @@ describe('ACP server test', { timeout: 40_000 }, () => {
971971
const turnCompleted = deferred<TurnCompletedNotification>();
972972
vi.spyOn(mockFixture.getCodexAppServerClient(), "awaitTurnCompleted")
973973
.mockReturnValue(turnCompleted.promise);
974+
const turnInterrupt = deferred<void>();
974975
const turnInterruptSpy = vi.spyOn(mockFixture.getCodexAcpClient(), "turnInterrupt")
975-
.mockResolvedValue();
976+
.mockReturnValue(turnInterrupt.promise);
976977
const controller = new AbortController();
977978

978979
const promptPromise = mockFixture.getCodexAcpAgent().prompt({
@@ -992,11 +993,22 @@ describe('ACP server test', { timeout: 40_000 }, () => {
992993
});
993994
});
994995

996+
mockFixture.sendServerNotification({
997+
method: "item/agentMessage/delta",
998+
params: {
999+
threadId: "session-id",
1000+
turnId: "turn-id",
1001+
itemId: "tail-item",
1002+
delta: "tail output",
1003+
},
1004+
});
9951005
turnCompleted.resolve({
9961006
threadId: "session-id",
9971007
turn: createTurn("turn-id", "completed"),
9981008
});
9991009
await expect(promptPromise).resolves.toMatchObject({stopReason: "end_turn"});
1010+
expect(mockFixture.getAcpConnectionDump([])).toContain("tail output");
1011+
turnInterrupt.resolve(undefined);
10001012
});
10011013

10021014
it('interrupts a late-started turn after the ACP prompt request is cancelled', async () => {

0 commit comments

Comments
 (0)