Skip to content

Commit 5b1400d

Browse files
fix multiple auth listeners
1 parent 41d2c3c commit 5b1400d

2 files changed

Lines changed: 38 additions & 7 deletions

File tree

src/CodexAcpClient.ts

Lines changed: 37 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import * as acp from "@agentclientprotocol/sdk";
44
import {type McpServer, RequestError} from "@agentclientprotocol/sdk";
55
import type {ApprovalHandler, CodexAppServerClient} from "./CodexAppServerClient";
66
import open from "open";
7+
import type {Disposable} from "vscode-jsonrpc";
78
import type {
89
ClientInfo,
910
ReasoningEffort,
@@ -40,6 +41,8 @@ export class CodexAcpClient {
4041
private readonly config: JsonObject;
4142
private readonly modelProvider: string | null;
4243
private gatewayConfig: GatewayConfig | null;
44+
private pendingLoginCompleted: Promise<AccountLoginCompletedNotification> | null = null;
45+
private pendingAccountUpdated: Promise<AccountUpdatedNotification> | null = null;
4346

4447

4548
constructor(codexClient: CodexAppServerClient, codexConfig?: JsonObject, modelProvider?: string) {
@@ -393,17 +396,44 @@ export class CodexAcpClient {
393396
}
394397

395398
private async awaitNextLoginCompleted(): Promise<AccountLoginCompletedNotification> {
396-
return await new Promise((resolve) => {
397-
this.codexClient.connection.onNotification("account/login/completed", (event: AccountLoginCompletedNotification) => {
398-
resolve(event);
399-
});
400-
});
399+
if (this.pendingLoginCompleted !== null) {
400+
return await this.pendingLoginCompleted;
401+
}
402+
this.pendingLoginCompleted = this.awaitSingleNotification(
403+
"account/login/completed",
404+
(event: AccountLoginCompletedNotification) => event,
405+
);
406+
try {
407+
return await this.pendingLoginCompleted;
408+
} finally {
409+
this.pendingLoginCompleted = null;
410+
}
401411
}
402412

403413
private async awaitNextAccountUpdated(): Promise<AccountUpdatedNotification> {
414+
if (this.pendingAccountUpdated !== null) {
415+
return await this.pendingAccountUpdated;
416+
}
417+
this.pendingAccountUpdated = this.awaitSingleNotification(
418+
"account/updated",
419+
(event: AccountUpdatedNotification) => event,
420+
);
421+
try {
422+
return await this.pendingAccountUpdated;
423+
} finally {
424+
this.pendingAccountUpdated = null;
425+
}
426+
}
427+
428+
private async awaitSingleNotification<T>(
429+
method: "account/login/completed" | "account/updated",
430+
mapEvent: (event: T) => T,
431+
): Promise<T> {
404432
return await new Promise((resolve) => {
405-
this.codexClient.connection.onNotification("account/updated", (event: AccountUpdatedNotification) => {
406-
resolve(event);
433+
let disposable: Disposable | undefined;
434+
disposable = this.codexClient.connection.onNotification(method, (event: T) => {
435+
disposable?.dispose();
436+
resolve(mapEvent(event));
407437
});
408438
});
409439
}

src/__tests__/CodexACPAgent/CodexAcpClient.test.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -135,6 +135,7 @@ describe('ACP server test', { timeout: 40_000 }, () => {
135135
expect(transportMethods).toEqual([
136136
"account/login/start",
137137
"account/read",
138+
"account/updated",
138139
"thread/start",
139140
"model/list",
140141
"thread/started",

0 commit comments

Comments
 (0)