Skip to content

Commit 227b2dc

Browse files
authorization: support auth via api-key & chat-gpt oauth
1 parent 968d72f commit 227b2dc

6 files changed

Lines changed: 308 additions & 12 deletions

File tree

package-lock.json

Lines changed: 180 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@
3535
"dependencies": {
3636
"@agentclientprotocol/sdk": "^0.5.1",
3737
"diff": "^8.0.2",
38+
"open": "^11.0.0",
3839
"vscode-jsonrpc": "^8.2.1"
3940
}
4041
}

src/CodexACPAgent.ts

Lines changed: 45 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,9 @@ import type {MessageConnection} from "vscode-jsonrpc/node";
33
import {CodexClient} from "./CodexClient";
44
import {CodexEventHandler} from "./CodexEventHandler";
55
import type {JsonValue} from "./app-server/serde_json/JsonValue";
6+
import {CodexAuthMethods, type CodexAuthRequest, isCodexAuthRequest} from "./CodexAuthMethod";
7+
import {RequestError} from "@agentclientprotocol/sdk";
8+
69

710
export interface SessionState {
811
sessionId: string,
@@ -11,42 +14,63 @@ export interface SessionState {
1114
}
1215

1316
export class CodexACPAgent implements acp.Agent {
17+
private readonly name: string = "codex-appserver-acp";
18+
private readonly version: string = "0.1.0";
19+
private readonly title: string = "Codex ACP";
20+
1421
private readonly codexClient: CodexClient;
1522
private readonly connection: acp.AgentSideConnection;
1623
private readonly config: JsonObject | null;
1724
private readonly modelProvider: string | null;
25+
private readonly defaultAuthRequest: CodexAuthRequest | null;
1826

1927
private readonly sessions: Map<string, SessionState>;
2028

21-
constructor(connection: acp.AgentSideConnection, codexConnection: MessageConnection, codexConfig?: JsonObject, modelProvider?: string) {
29+
constructor(
30+
connection: acp.AgentSideConnection,
31+
codexConnection: MessageConnection,
32+
codexConfig?: JsonObject,
33+
modelProvider?: string,
34+
defaultAuthRequest?: CodexAuthRequest,
35+
) {
2236
this.sessions = new Map();
2337
this.codexClient = new CodexClient(codexConnection);
2438
this.connection = connection;
2539
this.config = codexConfig ?? null;
2640
this.modelProvider = modelProvider ?? null;
41+
this.defaultAuthRequest = defaultAuthRequest ?? null;
2742
}
2843

2944
async initialize(
3045
_params: acp.InitializeRequest,
3146
): Promise<acp.InitializeResponse> {
3247
await this.codexClient.initialize({
3348
clientInfo: {
34-
name: _params.clientInfo?.name ?? "CodexACPAgent",
35-
version: _params.clientInfo?.version ?? "0.1.0",
36-
title: _params.clientInfo?.title ?? "Codex ACP"
49+
name: _params.clientInfo?.name ?? this.name,
50+
version: _params.clientInfo?.version ?? this.version,
51+
title: _params.clientInfo?.title ?? this.title,
3752
}
3853
});
3954
return {
4055
protocolVersion: acp.PROTOCOL_VERSION,
4156
agentCapabilities: {
4257
loadSession: false,
4358
},
59+
authMethods: CodexAuthMethods,
4460
};
4561
}
4662

4763
async newSession(
4864
_params: acp.NewSessionRequest,
4965
): Promise<acp.NewSessionResponse> {
66+
if (!await this.codexClient.loginStatus()) {
67+
if (this.defaultAuthRequest) {
68+
await this.authenticate(this.defaultAuthRequest)
69+
} else {
70+
throw RequestError.authRequired();
71+
}
72+
}
73+
5074
const threadStartResponse = await this.codexClient.threadStart({
5175
config: this.config,
5276
modelProvider: this.modelProvider,
@@ -72,9 +96,23 @@ export class CodexACPAgent implements acp.Agent {
7296

7397
async authenticate(
7498
_params: acp.AuthenticateRequest,
75-
): Promise<acp.AuthenticateResponse | void> {
76-
//TODO
77-
return {};
99+
): Promise<acp.AuthenticateResponse> {
100+
if (!isCodexAuthRequest(_params)) {
101+
throw RequestError.invalidRequest();
102+
}
103+
let authResult: Boolean;
104+
switch (_params.methodId) {
105+
case "api-key":
106+
authResult = await this.codexClient.loginWithApiKey(_params._meta.apiKey);
107+
break;
108+
case "chat-gpt":
109+
authResult = await this.codexClient.loginWithChatGpt();
110+
break;
111+
}
112+
if (!authResult) {
113+
throw RequestError.invalidParams();
114+
}
115+
return { };
78116
}
79117

80118
async setSessionMode(

0 commit comments

Comments
 (0)