@@ -16,12 +16,9 @@ use crate::app_event::AppEvent;
1616use crate :: app_server_session:: AppServerSession ;
1717use crate :: app_server_session:: app_server_rate_limit_snapshot_to_core;
1818use crate :: app_server_session:: status_account_display_from_auth_mode;
19- use crate :: local_chatgpt_auth:: load_local_chatgpt_auth;
2019use codex_app_server_client:: AppServerEvent ;
2120use codex_app_server_protocol:: AuthMode ;
22- use codex_app_server_protocol:: ChatgptAuthTokensRefreshParams ;
2321use codex_app_server_protocol:: JSONRPCErrorError ;
24- use codex_app_server_protocol:: RequestId ;
2522use codex_app_server_protocol:: ServerNotification ;
2623use codex_app_server_protocol:: ServerRequest ;
2724#[ cfg( test) ]
@@ -129,15 +126,6 @@ impl App {
129126 tracing:: debug!( "ignoring legacy app-server notification in tui_app_server" ) ;
130127 }
131128 AppServerEvent :: ServerRequest ( request) => {
132- if let ServerRequest :: ChatgptAuthTokensRefresh { request_id, params } = request {
133- self . handle_chatgpt_auth_tokens_refresh_request (
134- app_server_client,
135- request_id,
136- params,
137- )
138- . await ;
139- return ;
140- }
141129 self . handle_server_request_event ( app_server_client, request)
142130 . await ;
143131 }
@@ -256,71 +244,6 @@ impl App {
256244 tracing:: warn!( "failed to enqueue app-server request: {err}" ) ;
257245 }
258246 }
259-
260- async fn handle_chatgpt_auth_tokens_refresh_request (
261- & mut self ,
262- app_server_client : & AppServerSession ,
263- request_id : RequestId ,
264- params : ChatgptAuthTokensRefreshParams ,
265- ) {
266- let config = self . config . clone ( ) ;
267- let result = tokio:: task:: spawn_blocking ( move || {
268- resolve_chatgpt_auth_tokens_refresh_response (
269- & config. codex_home ,
270- config. cli_auth_credentials_store_mode ,
271- config. forced_chatgpt_workspace_id . as_deref ( ) ,
272- & params,
273- )
274- } )
275- . await ;
276-
277- match result {
278- Ok ( Ok ( response) ) => {
279- let response = serde_json:: to_value ( response) . map_err ( |err| {
280- format ! ( "failed to serialize chatgpt auth refresh response: {err}" )
281- } ) ;
282- match response {
283- Ok ( response) => {
284- if let Err ( err) = app_server_client
285- . resolve_server_request ( request_id, response)
286- . await
287- {
288- tracing:: warn!( "failed to resolve chatgpt auth refresh request: {err}" ) ;
289- }
290- }
291- Err ( err) => {
292- self . chat_widget . add_error_message ( err. clone ( ) ) ;
293- if let Err ( reject_err) = self
294- . reject_app_server_request ( app_server_client, request_id, err)
295- . await
296- {
297- tracing:: warn!( "{reject_err}" ) ;
298- }
299- }
300- }
301- }
302- Ok ( Err ( err) ) => {
303- self . chat_widget . add_error_message ( err. clone ( ) ) ;
304- if let Err ( reject_err) = self
305- . reject_app_server_request ( app_server_client, request_id, err)
306- . await
307- {
308- tracing:: warn!( "{reject_err}" ) ;
309- }
310- }
311- Err ( err) => {
312- let message = format ! ( "chatgpt auth refresh task failed: {err}" ) ;
313- self . chat_widget . add_error_message ( message. clone ( ) ) ;
314- if let Err ( reject_err) = self
315- . reject_app_server_request ( app_server_client, request_id, message)
316- . await
317- {
318- tracing:: warn!( "{reject_err}" ) ;
319- }
320- }
321- }
322- }
323-
324247 async fn reject_app_server_request (
325248 & self ,
326249 app_server_client : & AppServerSession ,
@@ -482,28 +405,6 @@ fn server_notification_thread_target(
482405 }
483406}
484407
485- fn resolve_chatgpt_auth_tokens_refresh_response (
486- codex_home : & std:: path:: Path ,
487- auth_credentials_store_mode : codex_core:: auth:: AuthCredentialsStoreMode ,
488- forced_chatgpt_workspace_id : Option < & str > ,
489- params : & ChatgptAuthTokensRefreshParams ,
490- ) -> Result < codex_app_server_protocol:: ChatgptAuthTokensRefreshResponse , String > {
491- let auth = load_local_chatgpt_auth (
492- codex_home,
493- auth_credentials_store_mode,
494- forced_chatgpt_workspace_id,
495- ) ?;
496- if let Some ( previous_account_id) = params. previous_account_id . as_deref ( )
497- && previous_account_id != auth. chatgpt_account_id
498- {
499- return Err ( format ! (
500- "local ChatGPT auth refresh account mismatch: expected `{previous_account_id}`, got `{}`" ,
501- auth. chatgpt_account_id
502- ) ) ;
503- }
504- Ok ( auth. to_refresh_response ( ) )
505- }
506-
507408#[ cfg( test) ]
508409/// Convert a `Thread` snapshot into a flat sequence of protocol `Event`s
509410/// suitable for replaying into the TUI event store.
@@ -1074,113 +975,6 @@ fn split_command_string(command: &str) -> Vec<String> {
1074975 }
1075976}
1076977
1077- #[ cfg( test) ]
1078- mod refresh_tests {
1079- use super :: * ;
1080-
1081- use base64:: Engine ;
1082- use chrono:: Utc ;
1083- use codex_app_server_protocol:: AuthMode ;
1084- use codex_core:: auth:: AuthCredentialsStoreMode ;
1085- use codex_core:: auth:: AuthDotJson ;
1086- use codex_core:: auth:: save_auth;
1087- use codex_core:: token_data:: TokenData ;
1088- use pretty_assertions:: assert_eq;
1089- use serde:: Serialize ;
1090- use serde_json:: json;
1091- use tempfile:: TempDir ;
1092-
1093- fn fake_jwt ( account_id : & str , plan_type : & str ) -> String {
1094- #[ derive( Serialize ) ]
1095- struct Header {
1096- alg : & ' static str ,
1097- typ : & ' static str ,
1098- }
1099-
1100- let header = Header {
1101- alg : "none" ,
1102- typ : "JWT" ,
1103- } ;
1104- let payload = json ! ( {
1105- "email" : "user@example.com" ,
1106- "https://api.openai.com/auth" : {
1107- "chatgpt_account_id" : account_id,
1108- "chatgpt_plan_type" : plan_type,
1109- } ,
1110- } ) ;
1111- let encode = |bytes : & [ u8 ] | base64:: engine:: general_purpose:: URL_SAFE_NO_PAD . encode ( bytes) ;
1112- let header_b64 = encode ( & serde_json:: to_vec ( & header) . expect ( "serialize header" ) ) ;
1113- let payload_b64 = encode ( & serde_json:: to_vec ( & payload) . expect ( "serialize payload" ) ) ;
1114- let signature_b64 = encode ( b"sig" ) ;
1115- format ! ( "{header_b64}.{payload_b64}.{signature_b64}" )
1116- }
1117-
1118- fn write_chatgpt_auth ( codex_home : & std:: path:: Path ) {
1119- let id_token = fake_jwt ( "workspace-1" , "business" ) ;
1120- let access_token = fake_jwt ( "workspace-1" , "business" ) ;
1121- save_auth (
1122- codex_home,
1123- & AuthDotJson {
1124- auth_mode : Some ( AuthMode :: Chatgpt ) ,
1125- openai_api_key : None ,
1126- tokens : Some ( TokenData {
1127- id_token : codex_core:: token_data:: parse_chatgpt_jwt_claims ( & id_token)
1128- . expect ( "id token should parse" ) ,
1129- access_token,
1130- refresh_token : "refresh-token" . to_string ( ) ,
1131- account_id : Some ( "workspace-1" . to_string ( ) ) ,
1132- } ) ,
1133- last_refresh : Some ( Utc :: now ( ) ) ,
1134- } ,
1135- AuthCredentialsStoreMode :: File ,
1136- )
1137- . expect ( "chatgpt auth should save" ) ;
1138- }
1139-
1140- #[ test]
1141- fn refresh_request_uses_local_chatgpt_auth ( ) {
1142- let codex_home = TempDir :: new ( ) . expect ( "tempdir" ) ;
1143- write_chatgpt_auth ( codex_home. path ( ) ) ;
1144-
1145- let response = resolve_chatgpt_auth_tokens_refresh_response (
1146- codex_home. path ( ) ,
1147- AuthCredentialsStoreMode :: File ,
1148- Some ( "workspace-1" ) ,
1149- & ChatgptAuthTokensRefreshParams {
1150- reason : codex_app_server_protocol:: ChatgptAuthTokensRefreshReason :: Unauthorized ,
1151- previous_account_id : Some ( "workspace-1" . to_string ( ) ) ,
1152- } ,
1153- )
1154- . expect ( "refresh response should resolve" ) ;
1155-
1156- assert_eq ! ( response. chatgpt_account_id, "workspace-1" ) ;
1157- assert_eq ! ( response. chatgpt_plan_type. as_deref( ) , Some ( "business" ) ) ;
1158- assert ! ( !response. access_token. is_empty( ) ) ;
1159- }
1160-
1161- #[ test]
1162- fn refresh_request_rejects_account_mismatch ( ) {
1163- let codex_home = TempDir :: new ( ) . expect ( "tempdir" ) ;
1164- write_chatgpt_auth ( codex_home. path ( ) ) ;
1165-
1166- let err = resolve_chatgpt_auth_tokens_refresh_response (
1167- codex_home. path ( ) ,
1168- AuthCredentialsStoreMode :: File ,
1169- Some ( "workspace-1" ) ,
1170- & ChatgptAuthTokensRefreshParams {
1171- reason : codex_app_server_protocol:: ChatgptAuthTokensRefreshReason :: Unauthorized ,
1172- previous_account_id : Some ( "workspace-2" . to_string ( ) ) ,
1173- } ,
1174- )
1175- . expect_err ( "mismatched account should fail" ) ;
1176-
1177- assert_eq ! (
1178- err,
1179- "local ChatGPT auth refresh account mismatch: expected `workspace-2`, got `workspace-1`"
1180- ) ;
1181- }
1182- }
1183-
1184978#[ cfg( test) ]
1185979fn app_server_web_search_action_to_core (
1186980 action : codex_app_server_protocol:: WebSearchAction ,
0 commit comments