Skip to content

Commit cf02238

Browse files
Remove legacy auth and notification handling from tui_app_server (#15414)
## Summary - remove `tui_app_server` handling for legacy app-server notifications - drop the local ChatGPT auth refresh request path from `tui_app_server` - remove the now-unused refresh response helper from local auth loading Split out of #15106 so the `tui_app_server` cleanup can land separately from the larger `codex-exec` app-server migration.
1 parent c23566b commit cf02238

File tree

2 files changed

+0
-217
lines changed

2 files changed

+0
-217
lines changed

codex-rs/tui_app_server/src/app/app_server_adapter.rs

Lines changed: 0 additions & 206 deletions
Original file line numberDiff line numberDiff line change
@@ -16,12 +16,9 @@ use crate::app_event::AppEvent;
1616
use crate::app_server_session::AppServerSession;
1717
use crate::app_server_session::app_server_rate_limit_snapshot_to_core;
1818
use crate::app_server_session::status_account_display_from_auth_mode;
19-
use crate::local_chatgpt_auth::load_local_chatgpt_auth;
2019
use codex_app_server_client::AppServerEvent;
2120
use codex_app_server_protocol::AuthMode;
22-
use codex_app_server_protocol::ChatgptAuthTokensRefreshParams;
2321
use codex_app_server_protocol::JSONRPCErrorError;
24-
use codex_app_server_protocol::RequestId;
2522
use codex_app_server_protocol::ServerNotification;
2623
use 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)]
1185979
fn app_server_web_search_action_to_core(
1186980
action: codex_app_server_protocol::WebSearchAction,

codex-rs/tui_app_server/src/local_chatgpt_auth.rs

Lines changed: 0 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
use std::path::Path;
22

33
use codex_app_server_protocol::AuthMode;
4-
use codex_app_server_protocol::ChatgptAuthTokensRefreshResponse;
54
use codex_core::auth::AuthCredentialsStoreMode;
65
use codex_core::auth::load_auth_dot_json;
76

@@ -12,16 +11,6 @@ pub(crate) struct LocalChatgptAuth {
1211
pub(crate) chatgpt_plan_type: Option<String>,
1312
}
1413

15-
impl LocalChatgptAuth {
16-
pub(crate) fn to_refresh_response(&self) -> ChatgptAuthTokensRefreshResponse {
17-
ChatgptAuthTokensRefreshResponse {
18-
access_token: self.access_token.clone(),
19-
chatgpt_account_id: self.chatgpt_account_id.clone(),
20-
chatgpt_plan_type: self.chatgpt_plan_type.clone(),
21-
}
22-
}
23-
}
24-
2514
pub(crate) fn load_local_chatgpt_auth(
2615
codex_home: &Path,
2716
auth_credentials_store_mode: AuthCredentialsStoreMode,

0 commit comments

Comments
 (0)