Skip to content

Commit 3d0cb83

Browse files
committed
Add requestId to device code auth elicitation requests
1 parent 45a0c85 commit 3d0cb83

15 files changed

Lines changed: 228 additions & 200 deletions

src/CodexAcpClient.ts

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,7 @@ export class CodexAcpClient {
9797
async authenticate(
9898
connection: AcpClientConnection,
9999
authRequest: acp.AuthenticateRequest,
100+
requestId: acp.JsonRpcId,
100101
env: NodeJS.ProcessEnv = process.env,
101102
): Promise<Boolean> {
102103
if (!isCodexAuthRequest(authRequest)) {
@@ -114,7 +115,7 @@ export class CodexAcpClient {
114115
return true;
115116
}
116117
if (env["NO_BROWSER"]) {
117-
return await this.authenticateWithChatGptDeviceCode(connection);
118+
return await this.authenticateWithChatGptDeviceCode(connection, requestId);
118119
} else {
119120
return await this.authenticateWithChatGptBrowser();
120121
}
@@ -146,14 +147,15 @@ export class CodexAcpClient {
146147
return result.success;
147148
}
148149

149-
private async authenticateWithChatGptDeviceCode(connection: AcpClientConnection): Promise<Boolean> {
150+
private async authenticateWithChatGptDeviceCode(connection: AcpClientConnection, requestId: acp.JsonRpcId): Promise<Boolean> {
150151
const loginCompletedPromise = this.awaitNextLoginCompleted();
151152
const loginResponse = await this.codexClient.accountLogin({type: "chatgptDeviceCode"});
152153
if (loginResponse.type == "chatgptDeviceCode") {
153154
const url = loginResponse.verificationUrl;
154155
const userCode = loginResponse.userCode;
155156

156157
await this.requestDeviceCodeAuth(connection, {
158+
requestId,
157159
elicitationId: `chatgpt-login-${crypto.randomUUID()}`,
158160
url,
159161
message: `Follow these steps to sign in with ChatGPT using device code authorization:\n\
@@ -168,15 +170,13 @@ export class CodexAcpClient {
168170

169171
private async requestDeviceCodeAuth(
170172
client: AcpClientConnection,
171-
request: { elicitationId: string; url: string; message: string },
173+
request: { requestId: acp.JsonRpcId, elicitationId: string; url: string; message: string },
172174
): Promise<void> {
173175
const response = await client.request(
174176
acp.methods.client.elicitation.create,
175177
{
176178
mode: "url",
177-
// This should be the authenticate requestId, but this is not exposed by the ACP SDK.
178-
// The elicitation still works, but won't be tied to the authenticate request.
179-
requestId: null,
179+
requestId: request.requestId,
180180
elicitationId: request.elicitationId,
181181
url: request.url,
182182
message: request.message,

src/CodexAcpServer.ts

Lines changed: 31 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -247,15 +247,15 @@ export class CodexAcpServer {
247247
}
248248
}
249249

250-
async checkAuthorization(){
250+
async checkAuthorization(requestId: acp.JsonRpcId){
251251
const authNeeded = await this.runWithProcessCheck(() => this.codexAcpClient.authRequired());
252252
logger.log("Auth requirement checked", {authRequired: authNeeded});
253253
if (authNeeded) {
254254
if (this.defaultAuthRequest) {
255255
logger.log("Authenticating with default auth request...", {
256256
authRequest: this.defaultAuthRequest
257257
});
258-
await this.authenticate(this.defaultAuthRequest)
258+
await this.authenticate(this.defaultAuthRequest, requestId);
259259
logger.log("Authentication completed");
260260
} else {
261261
logger.log("Authentication required but no default auth request provided, return to IDE");
@@ -264,9 +264,12 @@ export class CodexAcpServer {
264264
}
265265
}
266266

267-
async getOrCreateSession(request: acp.NewSessionRequest | acp.ResumeSessionRequest): Promise<[SessionId, LegacySessionModelState, SessionModeState]> {
267+
async getOrCreateSession(
268+
request: acp.NewSessionRequest | acp.ResumeSessionRequest,
269+
requestId: acp.JsonRpcId,
270+
): Promise<[SessionId, LegacySessionModelState, SessionModeState]> {
268271
try {
269-
return await this.tryCreateSession(request);
272+
return await this.tryCreateSession(request, requestId);
270273
} catch (e) {
271274
const error = e instanceof Error ? e : new Error(String(e));
272275
await this.handleError(error);
@@ -345,11 +348,14 @@ export class CodexAcpServer {
345348
return generation;
346349
}
347350

348-
async tryCreateSession(request: acp.NewSessionRequest | acp.ResumeSessionRequest): Promise<[SessionId, LegacySessionModelState, SessionModeState]> {
351+
async tryCreateSession(
352+
request: acp.NewSessionRequest | acp.ResumeSessionRequest,
353+
requestId: acp.JsonRpcId,
354+
): Promise<[SessionId, LegacySessionModelState, SessionModeState]> {
349355
const requestedSessionGeneration = "sessionId" in request
350356
? this.beginSessionOpen(request.sessionId)
351357
: null;
352-
await this.checkAuthorization();
358+
await this.checkAuthorization(requestId);
353359
const requestedMcpServers = request.mcpServers ?? [];
354360
const mcpServerStartupVersion = requestedMcpServers.length > 0
355361
? this.codexAcpClient.getMcpServerStartupVersion()
@@ -467,14 +473,17 @@ export class CodexAcpServer {
467473
return null;
468474
}
469475

470-
async loadSession(params: acp.LoadSessionRequest): Promise<LegacyLoadSessionResponse> {
476+
async loadSession(
477+
params: acp.LoadSessionRequest,
478+
requestId: acp.JsonRpcId,
479+
): Promise<LegacyLoadSessionResponse> {
471480
logger.log("Loading session...", {sessionId: params.sessionId});
472481
const {
473482
sessionId,
474483
modelState,
475484
modeState,
476485
thread,
477-
} = await this.getOrCreateSessionWithHistory(params);
486+
} = await this.getOrCreateSessionWithHistory(params, requestId);
478487

479488
await this.streamThreadHistory(sessionId, thread);
480489

@@ -490,9 +499,12 @@ export class CodexAcpServer {
490499
};
491500
}
492501

493-
async resumeSession(params: acp.ResumeSessionRequest): Promise<LegacyResumeSessionResponse> {
502+
async resumeSession(
503+
params: acp.ResumeSessionRequest,
504+
requestId: acp.JsonRpcId,
505+
): Promise<LegacyResumeSessionResponse> {
494506
logger.log("Resuming session...", {sessionId: params.sessionId});
495-
const [sessionId, modelState, modeState] = await this.getOrCreateSession(params);
507+
const [sessionId, modelState, modeState] = await this.getOrCreateSession(params, requestId);
496508

497509
logger.log("Session resumed", {
498510
sessionId: sessionId,
@@ -506,9 +518,9 @@ export class CodexAcpServer {
506518
};
507519
}
508520

509-
async listSessions(params: acp.ListSessionsRequest): Promise<acp.ListSessionsResponse> {
521+
async listSessions(params: acp.ListSessionsRequest, requestId: acp.JsonRpcId): Promise<acp.ListSessionsResponse> {
510522
logger.log("Listing sessions...", {cwd: params.cwd, cursor: params.cursor});
511-
await this.checkAuthorization();
523+
await this.checkAuthorization(requestId);
512524
const response = await this.runWithProcessCheck(() => this.codexAcpClient.listSessions(params));
513525
return {
514526
...response,
@@ -596,9 +608,10 @@ export class CodexAcpServer {
596608

597609
async newSession(
598610
params: acp.NewSessionRequest,
611+
requestId: acp.JsonRpcId,
599612
): Promise<LegacyNewSessionResponse> {
600613
logger.log("Starting new session...");
601-
const [sessionId, modelState, modeState] = await this.getOrCreateSession(params);
614+
const [sessionId, modelState, modeState] = await this.getOrCreateSession(params, requestId);
602615

603616
logger.log("New session created", {
604617
sessionId: sessionId,
@@ -616,9 +629,10 @@ export class CodexAcpServer {
616629

617630
async authenticate(
618631
_params: acp.AuthenticateRequest,
632+
requestId: acp.JsonRpcId,
619633
): Promise<acp.AuthenticateResponse> {
620634
logger.log("Authenticate request received");
621-
const isAuthenticated = await this.runWithProcessCheck(() => this.codexAcpClient.authenticate(this.connection, _params));
635+
const isAuthenticated = await this.runWithProcessCheck(() => this.codexAcpClient.authenticate(this.connection, _params, requestId));
622636
if (!isAuthenticated) {
623637
logger.log("Authenticate request failed");
624638
throw RequestError.invalidParams();
@@ -876,15 +890,16 @@ export class CodexAcpServer {
876890
}
877891

878892
private async getOrCreateSessionWithHistory(
879-
request: acp.LoadSessionRequest
893+
request: acp.LoadSessionRequest,
894+
requestId: acp.JsonRpcId,
880895
): Promise<{
881896
sessionId: SessionId;
882897
modelState: LegacySessionModelState;
883898
modeState: SessionModeState;
884899
thread: Thread;
885900
}> {
886901
const requestedSessionGeneration = this.beginSessionOpen(request.sessionId);
887-
await this.checkAuthorization();
902+
await this.checkAuthorization(requestId);
888903
const requestedMcpServers = request.mcpServers ?? [];
889904
const mcpServerStartupVersion = requestedMcpServers.length > 0
890905
? this.codexAcpClient.getMcpServerStartupVersion()

0 commit comments

Comments
 (0)