Skip to content

Commit 782985c

Browse files
committed
feat: reapply fork changes onto rust-v0.144.0
1 parent 946322c commit 782985c

41 files changed

Lines changed: 1658 additions & 198 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

codex-rs/Cargo.lock

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

codex-rs/app-server-protocol/src/protocol/v2/account.rs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -484,6 +484,13 @@ pub struct GetAccountParams {
484484
/// themselves and call `account/login/start` with `chatgptAuthTokens`.
485485
#[serde(default, skip_serializing_if = "std::ops::Not::not")]
486486
pub refresh_token: bool,
487+
488+
/// When `true`, reloads the auth snapshot from storage before returning.
489+
///
490+
/// This keeps long-lived clients in sync with `auth.json` updates without
491+
/// requiring a full app-server restart.
492+
#[serde(default, skip_serializing_if = "std::ops::Not::not")]
493+
pub reload_auth_from_storage: bool,
487494
}
488495

489496
#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, JsonSchema, TS)]

codex-rs/app-server/src/request_processors.rs

Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
use crate::auth_mode::auth_mode_to_api;
12
use crate::bespoke_event_handling::apply_bespoke_event_handling;
23
use crate::command_exec::CommandExecManager;
34
use crate::command_exec::StartCommandExecParams;
@@ -380,6 +381,7 @@ use codex_git_utils::git_diff_to_remote;
380381
use codex_git_utils::resolve_root_git_project_for_trust;
381382
use codex_login::AuthManager;
382383
use codex_login::CODEX_OPEN_APP_URL;
384+
use codex_login::AuthReloadStatus;
383385
use codex_login::CodexAuth;
384386
use codex_login::LoginSuccessPage;
385387
use codex_login::LoginSuccessPageBrand;
@@ -495,6 +497,81 @@ use uuid::Uuid;
495497
#[cfg(test)]
496498
use codex_app_server_protocol::ServerRequest;
497499

500+
async fn reload_auth_from_storage_if_idle(
501+
auth_manager: &Arc<AuthManager>,
502+
thread_manager: &Arc<ThreadManager>,
503+
config_manager: &ConfigManager,
504+
outgoing: &OutgoingMessageSender,
505+
thread_watch_manager: &ThreadWatchManager,
506+
chatgpt_base_url: &str,
507+
reason: &str,
508+
) {
509+
if *thread_watch_manager.subscribe_running_turn_count().borrow() != 0 {
510+
return;
511+
}
512+
513+
let status = auth_manager.reload_with_status().await;
514+
match handle_auth_reload_status(
515+
status,
516+
auth_manager,
517+
thread_manager,
518+
config_manager,
519+
outgoing,
520+
chatgpt_base_url,
521+
reason,
522+
)
523+
.await
524+
{
525+
AuthReloadStatus::Reloaded { .. } => {}
526+
AuthReloadStatus::Failed => {
527+
warn!("failed to reload auth from storage before {reason}");
528+
}
529+
}
530+
}
531+
532+
async fn handle_auth_reload_status(
533+
status: AuthReloadStatus,
534+
auth_manager: &Arc<AuthManager>,
535+
thread_manager: &Arc<ThreadManager>,
536+
config_manager: &ConfigManager,
537+
outgoing: &OutgoingMessageSender,
538+
chatgpt_base_url: &str,
539+
reason: &str,
540+
) -> AuthReloadStatus {
541+
match status {
542+
AuthReloadStatus::Reloaded { changed } => {
543+
if changed {
544+
let invalidated_thread_count =
545+
thread_manager.invalidate_model_transport_caches().await;
546+
info!(
547+
"auth reloaded from storage before {reason}; invalidated model transport caches for {invalidated_thread_count} tracked thread(s)"
548+
);
549+
config_manager.replace_cloud_config_bundle_loader(
550+
Arc::clone(auth_manager),
551+
chatgpt_base_url.to_string(),
552+
);
553+
config_manager
554+
.sync_default_client_residency_requirement()
555+
.await;
556+
let auth = auth_manager.auth_cached();
557+
outgoing
558+
.send_server_notification(ServerNotification::AccountUpdated(
559+
AccountUpdatedNotification {
560+
auth_mode: auth
561+
.as_ref()
562+
.map(CodexAuth::api_auth_mode)
563+
.map(auth_mode_to_api),
564+
plan_type: auth.as_ref().and_then(CodexAuth::account_plan_type),
565+
},
566+
))
567+
.await;
568+
}
569+
AuthReloadStatus::Reloaded { changed }
570+
}
571+
AuthReloadStatus::Failed => AuthReloadStatus::Failed,
572+
}
573+
}
574+
498575
mod account_processor;
499576
mod apps_processor;
500577
mod catalog_processor;

codex-rs/app-server/src/request_processors/account_processor.rs

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -900,6 +900,26 @@ impl AccountRequestProcessor {
900900
) -> Result<GetAccountResponse, JSONRPCErrorError> {
901901
let do_refresh = params.refresh_token;
902902

903+
if params.reload_auth_from_storage {
904+
let status = self.auth_manager.reload_with_status().await;
905+
match handle_auth_reload_status(
906+
status,
907+
&self.auth_manager,
908+
&self.thread_manager,
909+
&self.config_manager,
910+
&self.outgoing,
911+
&self.config.chatgpt_base_url,
912+
"account/get",
913+
)
914+
.await
915+
{
916+
AuthReloadStatus::Reloaded { .. } => {}
917+
AuthReloadStatus::Failed => {
918+
return Err(internal_error("failed to reload auth from storage"));
919+
}
920+
}
921+
}
922+
903923
self.refresh_token_if_requested(do_refresh).await;
904924

905925
let provider = create_model_provider(

codex-rs/app-server/src/request_processors/thread_processor.rs

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -936,6 +936,17 @@ impl ThreadRequestProcessor {
936936
supports_openai_form_elicitation: bool,
937937
request_context: RequestContext,
938938
) -> Result<(), JSONRPCErrorError> {
939+
reload_auth_from_storage_if_idle(
940+
&self.auth_manager,
941+
&self.thread_manager,
942+
&self.config_manager,
943+
&self.outgoing,
944+
&self.thread_watch_manager,
945+
&self.config.chatgpt_base_url,
946+
"thread/start",
947+
)
948+
.await;
949+
939950
let ThreadStartParams {
940951
model,
941952
model_provider,
@@ -2669,6 +2680,17 @@ impl ThreadRequestProcessor {
26692680
app_server_client_version: Option<String>,
26702681
supports_openai_form_elicitation: bool,
26712682
) -> Result<(), JSONRPCErrorError> {
2683+
reload_auth_from_storage_if_idle(
2684+
&self.auth_manager,
2685+
&self.thread_manager,
2686+
&self.config_manager,
2687+
&self.outgoing,
2688+
&self.thread_watch_manager,
2689+
&self.config.chatgpt_base_url,
2690+
"thread/resume",
2691+
)
2692+
.await;
2693+
26722694
if let Ok(thread_id) = ThreadId::from_string(&params.thread_id)
26732695
&& self
26742696
.pending_thread_unloads

codex-rs/app-server/src/request_processors/turn_processor.rs

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -447,6 +447,17 @@ impl TurnRequestProcessor {
447447
app_server_client_version: Option<String>,
448448
supports_openai_form_elicitation: bool,
449449
) -> Result<TurnStartResponse, JSONRPCErrorError> {
450+
reload_auth_from_storage_if_idle(
451+
&self.auth_manager,
452+
&self.thread_manager,
453+
&self.config_manager,
454+
&self.outgoing,
455+
&self.thread_watch_manager,
456+
&self.config.chatgpt_base_url,
457+
"turn/start",
458+
)
459+
.await;
460+
450461
let (thread_id, thread) =
451462
self.load_thread(&params.thread_id)
452463
.await

codex-rs/config/src/types.rs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -765,6 +765,14 @@ pub struct Tui {
765765
#[serde(default)]
766766
pub keymap: TuiKeymap,
767767

768+
/// Optional synthetic user-turn prompt injected after a turn fails with
769+
/// `UsageLimitExceeded`.
770+
///
771+
/// When unset, Codex uses the built-in default recovery prompt.
772+
/// When set to an empty string, Codex disables this automatic recovery turn.
773+
#[serde(default)]
774+
pub usage_limit_resume_prompt: Option<String>,
775+
768776
/// Startup tooltip availability NUX state persisted by the TUI.
769777
#[serde(default)]
770778
pub model_availability_nux: ModelAvailabilityNuxConfig,

codex-rs/core/config.schema.json

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3285,6 +3285,11 @@
32853285
"description": "Syntax highlighting theme name (kebab-case).\n\nWhen set, overrides automatic light/dark theme detection. Use `/theme` in the TUI or see `$CODEX_HOME/themes` for custom themes.",
32863286
"type": "string"
32873287
},
3288+
"usage_limit_resume_prompt": {
3289+
"default": null,
3290+
"description": "Optional synthetic user-turn prompt injected after a turn fails with `UsageLimitExceeded`.\n\nWhen unset, Codex uses the built-in default recovery prompt. When set to an empty string, Codex disables this automatic recovery turn.",
3291+
"type": "string"
3292+
},
32883293
"vim_mode_default": {
32893294
"default": false,
32903295
"description": "Start the composer in Vim mode (`Normal`) by default. Defaults to `false`.",

codex-rs/core/src/client.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -505,6 +505,10 @@ impl ModelClient {
505505
.unwrap_or_else(std::sync::PoisonError::into_inner) = websocket_session;
506506
}
507507

508+
pub(crate) fn invalidate_cached_transport_state(&self) {
509+
self.store_cached_websocket_session(WebsocketSession::default());
510+
}
511+
508512
pub(crate) fn force_http_fallback(
509513
&self,
510514
session_telemetry: &SessionTelemetry,

codex-rs/core/src/codex_thread.rs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -211,6 +211,14 @@ impl CodexThread {
211211
self.codex.shutdown_and_wait().await
212212
}
213213

214+
pub(crate) fn invalidate_model_transport_cache(&self) {
215+
self.codex
216+
.session
217+
.services
218+
.model_client
219+
.invalidate_cached_transport_state();
220+
}
221+
214222
/// Wait until the underlying session loop has terminated.
215223
pub async fn wait_until_terminated(&self) {
216224
self.codex.session_loop_termination.clone().await;

0 commit comments

Comments
 (0)