Skip to content

Commit 841949e

Browse files
committed
Add requestId to device code auth elicitation requests
1 parent cc193c4 commit 841949e

15 files changed

Lines changed: 230 additions & 202 deletions

src/CodexAcpClient.ts

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -103,6 +103,7 @@ export class CodexAcpClient {
103103
async authenticate(
104104
connection: AcpClientConnection,
105105
authRequest: acp.AuthenticateRequest,
106+
requestId: acp.JsonRpcId,
106107
env: NodeJS.ProcessEnv = process.env,
107108
): Promise<Boolean> {
108109
if (!isCodexAuthRequest(authRequest)) {
@@ -120,7 +121,7 @@ export class CodexAcpClient {
120121
return true;
121122
}
122123
if (env["NO_BROWSER"]) {
123-
return await this.authenticateWithChatGptDeviceCode(connection);
124+
return await this.authenticateWithChatGptDeviceCode(connection, requestId);
124125
} else {
125126
return await this.authenticateWithChatGptBrowser();
126127
}
@@ -152,14 +153,15 @@ export class CodexAcpClient {
152153
return result.success;
153154
}
154155

155-
private async authenticateWithChatGptDeviceCode(connection: AcpClientConnection): Promise<Boolean> {
156+
private async authenticateWithChatGptDeviceCode(connection: AcpClientConnection, requestId: acp.JsonRpcId): Promise<Boolean> {
156157
const loginCompletedPromise = this.awaitNextLoginCompleted();
157158
const loginResponse = await this.codexClient.accountLogin({type: "chatgptDeviceCode"});
158159
if (loginResponse.type == "chatgptDeviceCode") {
159160
const url = loginResponse.verificationUrl;
160161
const userCode = loginResponse.userCode;
161162

162163
await this.requestDeviceCodeAuth(connection, {
164+
requestId,
163165
elicitationId: `chatgpt-login-${crypto.randomUUID()}`,
164166
url,
165167
message: `Follow these steps to sign in with ChatGPT using device code authorization:\n\
@@ -174,15 +176,13 @@ export class CodexAcpClient {
174176

175177
private async requestDeviceCodeAuth(
176178
client: AcpClientConnection,
177-
request: { elicitationId: string; url: string; message: string },
179+
request: { requestId: acp.JsonRpcId, elicitationId: string; url: string; message: string },
178180
): Promise<void> {
179181
const response = await client.request(
180182
acp.methods.client.elicitation.create,
181183
{
182184
mode: "url",
183-
// This should be the authenticate requestId, but this is not exposed by the ACP SDK.
184-
// The elicitation still works, but won't be tied to the authenticate request.
185-
requestId: null,
185+
requestId: request.requestId,
186186
elicitationId: request.elicitationId,
187187
url: request.url,
188188
message: request.message,

src/CodexAcpServer.ts

Lines changed: 31 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -277,15 +277,15 @@ export class CodexAcpServer {
277277
}
278278
}
279279

280-
async checkAuthorization(){
280+
async checkAuthorization(requestId: acp.JsonRpcId){
281281
const authNeeded = await this.runWithProcessCheck(() => this.codexAcpClient.authRequired());
282282
logger.log("Auth requirement checked", {authRequired: authNeeded});
283283
if (authNeeded) {
284284
if (this.defaultAuthRequest) {
285285
logger.log("Authenticating with default auth request...", {
286286
authRequest: this.defaultAuthRequest
287287
});
288-
await this.authenticate(this.defaultAuthRequest)
288+
await this.authenticate(this.defaultAuthRequest, requestId);
289289
logger.log("Authentication completed");
290290
} else {
291291
logger.log("Authentication required but no default auth request provided, return to IDE");
@@ -294,9 +294,12 @@ export class CodexAcpServer {
294294
}
295295
}
296296

297-
async getOrCreateSession(request: acp.NewSessionRequest | acp.ResumeSessionRequest): Promise<[SessionId, LegacySessionModelState, SessionModeState]> {
297+
async getOrCreateSession(
298+
request: acp.NewSessionRequest | acp.ResumeSessionRequest,
299+
requestId: acp.JsonRpcId,
300+
): Promise<[SessionId, LegacySessionModelState, SessionModeState]> {
298301
try {
299-
return await this.tryCreateSession(request);
302+
return await this.tryCreateSession(request, requestId);
300303
} catch (e) {
301304
const error = e instanceof Error ? e : new Error(String(e));
302305
await this.handleError(error);
@@ -375,11 +378,14 @@ export class CodexAcpServer {
375378
return generation;
376379
}
377380

378-
async tryCreateSession(request: acp.NewSessionRequest | acp.ResumeSessionRequest): Promise<[SessionId, LegacySessionModelState, SessionModeState]> {
381+
async tryCreateSession(
382+
request: acp.NewSessionRequest | acp.ResumeSessionRequest,
383+
requestId: acp.JsonRpcId,
384+
): Promise<[SessionId, LegacySessionModelState, SessionModeState]> {
379385
const requestedSessionGeneration = "sessionId" in request
380386
? this.beginSessionOpen(request.sessionId)
381387
: null;
382-
await this.checkAuthorization();
388+
await this.checkAuthorization(requestId);
383389
const requestedMcpServers = request.mcpServers ?? [];
384390
const mcpServerStartupVersion = requestedMcpServers.length > 0
385391
? this.codexAcpClient.getMcpServerStartupVersion()
@@ -504,14 +510,17 @@ export class CodexAcpServer {
504510
return null;
505511
}
506512

507-
async loadSession(params: acp.LoadSessionRequest): Promise<LegacyLoadSessionResponse> {
513+
async loadSession(
514+
params: acp.LoadSessionRequest,
515+
requestId: acp.JsonRpcId,
516+
): Promise<LegacyLoadSessionResponse> {
508517
logger.log("Loading session...", {sessionId: params.sessionId});
509518
const {
510519
sessionId,
511520
modelState,
512521
modeState,
513522
thread,
514-
} = await this.getOrCreateSessionWithHistory(params);
523+
} = await this.getOrCreateSessionWithHistory(params, requestId);
515524

516525
await this.streamThreadHistory(sessionId, thread);
517526

@@ -527,9 +536,12 @@ export class CodexAcpServer {
527536
};
528537
}
529538

530-
async resumeSession(params: acp.ResumeSessionRequest): Promise<LegacyResumeSessionResponse> {
539+
async resumeSession(
540+
params: acp.ResumeSessionRequest,
541+
requestId: acp.JsonRpcId,
542+
): Promise<LegacyResumeSessionResponse> {
531543
logger.log("Resuming session...", {sessionId: params.sessionId});
532-
const [sessionId, modelState, modeState] = await this.getOrCreateSession(params);
544+
const [sessionId, modelState, modeState] = await this.getOrCreateSession(params, requestId);
533545

534546
logger.log("Session resumed", {
535547
sessionId: sessionId,
@@ -543,9 +555,9 @@ export class CodexAcpServer {
543555
};
544556
}
545557

546-
async listSessions(params: acp.ListSessionsRequest): Promise<acp.ListSessionsResponse> {
558+
async listSessions(params: acp.ListSessionsRequest, requestId: acp.JsonRpcId): Promise<acp.ListSessionsResponse> {
547559
logger.log("Listing sessions...", {cwd: params.cwd, cursor: params.cursor});
548-
await this.checkAuthorization();
560+
await this.checkAuthorization(requestId);
549561
const response = await this.runWithProcessCheck(() => this.codexAcpClient.listSessions(params));
550562
return {
551563
...response,
@@ -633,9 +645,10 @@ export class CodexAcpServer {
633645

634646
async newSession(
635647
params: acp.NewSessionRequest,
648+
requestId: acp.JsonRpcId,
636649
): Promise<LegacyNewSessionResponse> {
637650
logger.log("Starting new session...");
638-
const [sessionId, modelState, modeState] = await this.getOrCreateSession(params);
651+
const [sessionId, modelState, modeState] = await this.getOrCreateSession(params, requestId);
639652

640653
logger.log("New session created", {
641654
sessionId: sessionId,
@@ -653,9 +666,10 @@ export class CodexAcpServer {
653666

654667
async authenticate(
655668
_params: acp.AuthenticateRequest,
669+
requestId: acp.JsonRpcId,
656670
): Promise<acp.AuthenticateResponse> {
657671
logger.log("Authenticate request received");
658-
const isAuthenticated = await this.runWithProcessCheck(() => this.codexAcpClient.authenticate(this.connection, _params));
672+
const isAuthenticated = await this.runWithProcessCheck(() => this.codexAcpClient.authenticate(this.connection, _params, requestId));
659673
if (!isAuthenticated) {
660674
logger.log("Authenticate request failed");
661675
throw RequestError.invalidParams();
@@ -991,15 +1005,16 @@ export class CodexAcpServer {
9911005
}
9921006

9931007
private async getOrCreateSessionWithHistory(
994-
request: acp.LoadSessionRequest
1008+
request: acp.LoadSessionRequest,
1009+
requestId: acp.JsonRpcId,
9951010
): Promise<{
9961011
sessionId: SessionId;
9971012
modelState: LegacySessionModelState;
9981013
modeState: SessionModeState;
9991014
thread: Thread;
10001015
}> {
10011016
const requestedSessionGeneration = this.beginSessionOpen(request.sessionId);
1002-
await this.checkAuthorization();
1017+
await this.checkAuthorization(requestId);
10031018
const requestedMcpServers = request.mcpServers ?? [];
10041019
const mcpServerStartupVersion = requestedMcpServers.length > 0
10051020
? this.codexAcpClient.getMcpServerStartupVersion()

0 commit comments

Comments
 (0)