From 3bc49e1721ef0453d695950dc67bd2f0616c4883 Mon Sep 17 00:00:00 2001 From: charlesgong-openai Date: Tue, 21 Jul 2026 02:50:37 +0000 Subject: [PATCH] Make external session detection limits configurable (#34449) ## What changed - Add `maxSessionAgeDays` and `maxSessions` to the external-agent config detection request. - Apply the requested limits when discovering sessions from supported migration sources. - Preserve the existing defaults of a 30-day maximum age and 50 sessions when either option is omitted. GitOrigin-RevId: 46376e94b64f1f61d8776e34d82cdd2cdeb36ca0 --- .../schema/json/ClientRequest.json | 18 ++++++++++++++ .../codex_app_server_protocol.schemas.json | 18 ++++++++++++++ .../codex_app_server_protocol.v2.schemas.json | 18 ++++++++++++++ .../v2/ExternalAgentConfigDetectParams.json | 18 ++++++++++++++ .../v2/ExternalAgentConfigDetectParams.ts | 8 +++++++ .../src/protocol/v2/config.rs | 6 +++++ .../src/external_agent_migration/processor.rs | 14 +++++++++++ .../src/detect/mod.rs | 8 ++++--- .../src/detect/sessions/cla.rs | 24 +++++++++++++++---- .../src/detect/sessions/common.rs | 14 ++++------- .../src/detect/sessions/cur.rs | 19 ++++++++++++--- .../src/detect/sessions/cur_tests.rs | 3 ++- .../src/detect/sessions/mod.rs | 2 ++ codex-rs/external-agent-migration/src/lib.rs | 1 + .../src/migration_source.rs | 14 +++++++---- .../external-agent-migration/src/model.rs | 22 +++++++++++++++++ .../external-agent-migration/src/service.rs | 11 +++++++++ .../external_agent_config_migration_flow.rs | 2 ++ 18 files changed, 195 insertions(+), 25 deletions(-) diff --git a/codex-rs/app-server-protocol/schema/json/ClientRequest.json b/codex-rs/app-server-protocol/schema/json/ClientRequest.json index 996f9ea93c..e64e14daec 100644 --- a/codex-rs/app-server-protocol/schema/json/ClientRequest.json +++ b/codex-rs/app-server-protocol/schema/json/ClientRequest.json @@ -876,6 +876,24 @@ "description": "If true, include detection under the user's home directory.", "type": "boolean" }, + "maxSessionAgeDays": { + "description": "Maximum age in days for detected sessions. Missing values use the default limit.", + "format": "uint32", + "minimum": 0.0, + "type": [ + "integer", + "null" + ] + }, + "maxSessions": { + "description": "Maximum number of sessions to detect. Missing values use the default limit.", + "format": "uint32", + "minimum": 0.0, + "type": [ + "integer", + "null" + ] + }, "migrationSource": { "description": "Optional migration-source selector. Missing or unrecognized values use the default source.", "type": [ diff --git a/codex-rs/app-server-protocol/schema/json/codex_app_server_protocol.schemas.json b/codex-rs/app-server-protocol/schema/json/codex_app_server_protocol.schemas.json index 78348e6a43..4b3aff4263 100644 --- a/codex-rs/app-server-protocol/schema/json/codex_app_server_protocol.schemas.json +++ b/codex-rs/app-server-protocol/schema/json/codex_app_server_protocol.schemas.json @@ -9577,6 +9577,24 @@ "description": "If true, include detection under the user's home directory.", "type": "boolean" }, + "maxSessionAgeDays": { + "description": "Maximum age in days for detected sessions. Missing values use the default limit.", + "format": "uint32", + "minimum": 0.0, + "type": [ + "integer", + "null" + ] + }, + "maxSessions": { + "description": "Maximum number of sessions to detect. Missing values use the default limit.", + "format": "uint32", + "minimum": 0.0, + "type": [ + "integer", + "null" + ] + }, "migrationSource": { "description": "Optional migration-source selector. Missing or unrecognized values use the default source.", "type": [ diff --git a/codex-rs/app-server-protocol/schema/json/codex_app_server_protocol.v2.schemas.json b/codex-rs/app-server-protocol/schema/json/codex_app_server_protocol.v2.schemas.json index e0cfbc1d9f..bfbab0c94b 100644 --- a/codex-rs/app-server-protocol/schema/json/codex_app_server_protocol.v2.schemas.json +++ b/codex-rs/app-server-protocol/schema/json/codex_app_server_protocol.v2.schemas.json @@ -5755,6 +5755,24 @@ "description": "If true, include detection under the user's home directory.", "type": "boolean" }, + "maxSessionAgeDays": { + "description": "Maximum age in days for detected sessions. Missing values use the default limit.", + "format": "uint32", + "minimum": 0.0, + "type": [ + "integer", + "null" + ] + }, + "maxSessions": { + "description": "Maximum number of sessions to detect. Missing values use the default limit.", + "format": "uint32", + "minimum": 0.0, + "type": [ + "integer", + "null" + ] + }, "migrationSource": { "description": "Optional migration-source selector. Missing or unrecognized values use the default source.", "type": [ diff --git a/codex-rs/app-server-protocol/schema/json/v2/ExternalAgentConfigDetectParams.json b/codex-rs/app-server-protocol/schema/json/v2/ExternalAgentConfigDetectParams.json index 20e1639ccd..f226823ead 100644 --- a/codex-rs/app-server-protocol/schema/json/v2/ExternalAgentConfigDetectParams.json +++ b/codex-rs/app-server-protocol/schema/json/v2/ExternalAgentConfigDetectParams.json @@ -15,6 +15,24 @@ "description": "If true, include detection under the user's home directory.", "type": "boolean" }, + "maxSessionAgeDays": { + "description": "Maximum age in days for detected sessions. Missing values use the default limit.", + "format": "uint32", + "minimum": 0.0, + "type": [ + "integer", + "null" + ] + }, + "maxSessions": { + "description": "Maximum number of sessions to detect. Missing values use the default limit.", + "format": "uint32", + "minimum": 0.0, + "type": [ + "integer", + "null" + ] + }, "migrationSource": { "description": "Optional migration-source selector. Missing or unrecognized values use the default source.", "type": [ diff --git a/codex-rs/app-server-protocol/schema/typescript/v2/ExternalAgentConfigDetectParams.ts b/codex-rs/app-server-protocol/schema/typescript/v2/ExternalAgentConfigDetectParams.ts index 5d43fb4402..b6abb7e929 100644 --- a/codex-rs/app-server-protocol/schema/typescript/v2/ExternalAgentConfigDetectParams.ts +++ b/codex-rs/app-server-protocol/schema/typescript/v2/ExternalAgentConfigDetectParams.ts @@ -11,6 +11,14 @@ includeHome?: boolean, * Zero or more working directories to include for repo-scoped detection. */ cwds?: Array | null, +/** + * Maximum age in days for detected sessions. Missing values use the default limit. + */ +maxSessionAgeDays?: number | null, +/** + * Maximum number of sessions to detect. Missing values use the default limit. + */ +maxSessions?: number | null, /** * Deprecated field retained for compatibility. This field is ignored; use `migrationSource` * to select the migration source. diff --git a/codex-rs/app-server-protocol/src/protocol/v2/config.rs b/codex-rs/app-server-protocol/src/protocol/v2/config.rs index 035e837f3d..10791c4ed9 100644 --- a/codex-rs/app-server-protocol/src/protocol/v2/config.rs +++ b/codex-rs/app-server-protocol/src/protocol/v2/config.rs @@ -699,6 +699,12 @@ pub struct ExternalAgentConfigDetectParams { /// Zero or more working directories to include for repo-scoped detection. #[ts(optional = nullable)] pub cwds: Option>, + /// Maximum age in days for detected sessions. Missing values use the default limit. + #[ts(optional = nullable)] + pub max_session_age_days: Option, + /// Maximum number of sessions to detect. Missing values use the default limit. + #[ts(optional = nullable)] + pub max_sessions: Option, /// Deprecated field retained for compatibility. This field is ignored; use `migrationSource` /// to select the migration source. #[ts(optional = nullable)] diff --git a/codex-rs/app-server/src/external_agent_migration/processor.rs b/codex-rs/app-server/src/external_agent_migration/processor.rs index 8ad8a44bd3..3fcfb4b4cf 100644 --- a/codex-rs/app-server/src/external_agent_migration/processor.rs +++ b/codex-rs/app-server/src/external_agent_migration/processor.rs @@ -1,4 +1,5 @@ use std::sync::Arc; +use std::time::Duration; use crate::config_manager::ConfigManager; use crate::error_code::internal_error; @@ -30,6 +31,7 @@ use codex_external_agent_migration::ExternalAgentConfigImportItemResult as CoreI use codex_external_agent_migration::ExternalAgentConfigImportOutcome as CoreImportOutcome; use codex_external_agent_migration::ExternalAgentConfigMigrationItemType as CoreMigrationItemType; use codex_external_agent_migration::ExternalAgentConfigService; +use codex_external_agent_migration::ExternalAgentSessionImportLimits; use codex_external_agent_migration::PluginImportOutcome; use codex_external_agent_migration::record_import_error; use codex_external_agent_migration::sessions::ExternalAgentSessionMigration as CoreSessionMigration; @@ -119,6 +121,18 @@ impl ExternalAgentConfigRequestProcessor { let migration_service = self .migration_service .with_migration_source(params.migration_source.as_deref()); + let default_session_import_limits = ExternalAgentSessionImportLimits::default(); + let migration_service = + migration_service.with_session_import_limits(ExternalAgentSessionImportLimits { + max_age: params + .max_session_age_days + .map(|days| Duration::from_secs(u64::from(days) * 24 * 60 * 60)) + .unwrap_or(default_session_import_limits.max_age), + max_sessions: params + .max_sessions + .map(|max_sessions| max_sessions as usize) + .unwrap_or(default_session_import_limits.max_sessions), + }); let options = ExternalAgentConfigDetectOptions { include_home: params.include_home, include_memory: self.external_agent_memory_import_enabled().await, diff --git a/codex-rs/external-agent-migration/src/detect/mod.rs b/codex-rs/external-agent-migration/src/detect/mod.rs index fd6162c3d9..9ca6b2851d 100644 --- a/codex-rs/external-agent-migration/src/detect/mod.rs +++ b/codex-rs/external-agent-migration/src/detect/mod.rs @@ -378,9 +378,11 @@ impl ExternalAgentConfigService { } if scope.is_home() { - let sessions = self - .source - .recent_sessions(&self.external_agent_home, &self.codex_home)?; + let sessions = self.source.recent_sessions( + &self.external_agent_home, + &self.codex_home, + self.session_import_limits, + )?; if !sessions.is_empty() { items.push(ExternalAgentConfigMigrationItem { item_type: ExternalAgentConfigMigrationItemType::Sessions, diff --git a/codex-rs/external-agent-migration/src/detect/sessions/cla.rs b/codex-rs/external-agent-migration/src/detect/sessions/cla.rs index 6b6b0be48d..7087c2cdee 100644 --- a/codex-rs/external-agent-migration/src/detect/sessions/cla.rs +++ b/codex-rs/external-agent-migration/src/detect/sessions/cla.rs @@ -1,7 +1,6 @@ -#[cfg(test)] -use super::common::SESSION_IMPORT_MAX_COUNT; use super::common::SessionFileCandidate; use super::common::detect_recent_sessions; +use crate::model::ExternalAgentSessionImportLimits; use crate::sessions::ExternalAgentSessionMigration; use std::fs; use std::io; @@ -10,6 +9,18 @@ use std::path::Path; pub fn detect_recent_cla_sessions( external_agent_home: &Path, codex_home: &Path, +) -> io::Result> { + detect_recent_cla_sessions_with_limits( + external_agent_home, + codex_home, + ExternalAgentSessionImportLimits::default(), + ) +} + +pub(crate) fn detect_recent_cla_sessions_with_limits( + external_agent_home: &Path, + codex_home: &Path, + limits: ExternalAgentSessionImportLimits, ) -> io::Result> { let projects_root = external_agent_home.join("projects"); if !projects_root.is_dir() { @@ -42,7 +53,9 @@ pub fn detect_recent_cla_sessions( }); } } - detect_recent_sessions(codex_home, candidates, /*require_existing_cwd*/ true) + detect_recent_sessions( + codex_home, candidates, /*require_existing_cwd*/ true, limits, + ) } #[cfg(test)] @@ -233,7 +246,8 @@ mod tests { let timestamp = chrono::Utc::now().to_rfc3339_opts(chrono::SecondsFormat::Secs, true); let modified_at = SystemTime::now(); let mut expected = Vec::new(); - for index in 0..=SESSION_IMPORT_MAX_COUNT { + let default_limits = ExternalAgentSessionImportLimits::default(); + for index in 0..=default_limits.max_sessions { let file_name = format!("{index:02}-session.jsonl"); let title = format!("session {index}"); let path = write_session( @@ -275,7 +289,7 @@ mod tests { } let changed_at = SystemTime::now() - + Duration::from_secs(/*secs*/ SESSION_IMPORT_MAX_COUNT as u64 + 1); + + Duration::from_secs(/*secs*/ default_limits.max_sessions as u64 + 1); for (index, session) in all_sessions.iter().enumerate() { let title = session.title.as_deref().expect("session title"); std::fs::write( diff --git a/codex-rs/external-agent-migration/src/detect/sessions/common.rs b/codex-rs/external-agent-migration/src/detect/sessions/common.rs index 6cad8ec32d..dadcb3b022 100644 --- a/codex-rs/external-agent-migration/src/detect/sessions/common.rs +++ b/codex-rs/external-agent-migration/src/detect/sessions/common.rs @@ -1,3 +1,4 @@ +use crate::model::ExternalAgentSessionImportLimits; use crate::sessions::ExternalAgentSessionMigration; use crate::sessions::ledger::load_import_ledger; use crate::sessions::ledger::save_import_ledger; @@ -9,10 +10,6 @@ use std::fs; use std::io; use std::path::Path; use std::path::PathBuf; -use std::time::Duration; - -pub(super) const SESSION_IMPORT_MAX_COUNT: usize = 50; -const SESSION_IMPORT_MAX_AGE: Duration = Duration::from_secs(30 * 24 * 60 * 60); pub(super) struct SessionFileCandidate { pub path: PathBuf, @@ -23,11 +20,12 @@ pub(super) fn detect_recent_sessions( codex_home: &Path, candidates: impl IntoIterator, require_existing_cwd: bool, + limits: ExternalAgentSessionImportLimits, ) -> io::Result> { let now = now_unix_seconds(); let mut ledger = load_import_ledger(codex_home)?; let source_states = ledger.source_states(); - let mut recent = BinaryHeap::with_capacity(SESSION_IMPORT_MAX_COUNT + 1); + let mut recent = BinaryHeap::new(); for candidate in candidates { let Ok(metadata) = fs::metadata(&candidate.path) else { @@ -39,9 +37,7 @@ pub(super) fn detect_recent_sessions( let Ok(modified_at) = modified_at.duration_since(std::time::UNIX_EPOCH) else { continue; }; - if (modified_at.as_secs() as i64) - < now.saturating_sub(SESSION_IMPORT_MAX_AGE.as_secs() as i64) - { + if (modified_at.as_secs() as i64) < now.saturating_sub(limits.max_age.as_secs() as i64) { continue; } let Ok(modified_at_nanos) = i64::try_from(modified_at.as_nanos()) else { @@ -62,7 +58,7 @@ pub(super) fn detect_recent_sessions( candidate.path, candidate.fallback_cwd, )); - if recent.len() > SESSION_IMPORT_MAX_COUNT { + if recent.len() > limits.max_sessions { recent.pop(); } } diff --git a/codex-rs/external-agent-migration/src/detect/sessions/cur.rs b/codex-rs/external-agent-migration/src/detect/sessions/cur.rs index bf9a6c6425..68595648f7 100644 --- a/codex-rs/external-agent-migration/src/detect/sessions/cur.rs +++ b/codex-rs/external-agent-migration/src/detect/sessions/cur.rs @@ -1,7 +1,6 @@ -#[cfg(test)] -use super::common::SESSION_IMPORT_MAX_COUNT; use super::common::SessionFileCandidate; use super::common::detect_recent_sessions; +use crate::model::ExternalAgentSessionImportLimits; use crate::sessions::ExternalAgentSessionMigration; use std::fs; use std::io; @@ -11,6 +10,18 @@ use std::path::PathBuf; pub fn detect_recent_cur_sessions( external_agent_home: &Path, codex_home: &Path, +) -> io::Result> { + detect_recent_cur_sessions_with_limits( + external_agent_home, + codex_home, + ExternalAgentSessionImportLimits::default(), + ) +} + +pub(crate) fn detect_recent_cur_sessions_with_limits( + external_agent_home: &Path, + codex_home: &Path, + limits: ExternalAgentSessionImportLimits, ) -> io::Result> { let projects_root = external_agent_home.join("projects"); if !projects_root.is_dir() { @@ -34,7 +45,9 @@ pub fn detect_recent_cur_sessions( }); } } - detect_recent_sessions(codex_home, candidates, /*require_existing_cwd*/ false) + detect_recent_sessions( + codex_home, candidates, /*require_existing_cwd*/ false, limits, + ) } fn cur_transcript_files(transcripts_root: &Path) -> Vec { diff --git a/codex-rs/external-agent-migration/src/detect/sessions/cur_tests.rs b/codex-rs/external-agent-migration/src/detect/sessions/cur_tests.rs index 44ffdb7aa3..f9f4bb443c 100644 --- a/codex-rs/external-agent-migration/src/detect/sessions/cur_tests.rs +++ b/codex-rs/external-agent-migration/src/detect/sessions/cur_tests.rs @@ -171,7 +171,8 @@ fn detects_cur_sessions_in_batches_and_redetects_modified_imports() { let encoded_project = encode_project_path(&project_root); let modified_at = SystemTime::now(); let mut expected = Vec::new(); - for index in 0..=SESSION_IMPORT_MAX_COUNT { + let default_limits = ExternalAgentSessionImportLimits::default(); + for index in 0..=default_limits.max_sessions { let session_id = format!("session-{index:02}"); let title = format!("request {index}"); let path = write_transcript(&external_agent_home, &encoded_project, &session_id, &title); diff --git a/codex-rs/external-agent-migration/src/detect/sessions/mod.rs b/codex-rs/external-agent-migration/src/detect/sessions/mod.rs index 773ce3e792..a825c94857 100644 --- a/codex-rs/external-agent-migration/src/detect/sessions/mod.rs +++ b/codex-rs/external-agent-migration/src/detect/sessions/mod.rs @@ -4,6 +4,8 @@ mod connectors_cla; mod cur; pub use cla::detect_recent_cla_sessions; +pub(crate) use cla::detect_recent_cla_sessions_with_limits; pub use connectors_cla::ImportedSessionConnectorAttribution; pub use connectors_cla::detect_imported_cla_session_connectors; pub use cur::detect_recent_cur_sessions; +pub(crate) use cur::detect_recent_cur_sessions_with_limits; diff --git a/codex-rs/external-agent-migration/src/lib.rs b/codex-rs/external-agent-migration/src/lib.rs index 403df2853b..8c012c835b 100644 --- a/codex-rs/external-agent-migration/src/lib.rs +++ b/codex-rs/external-agent-migration/src/lib.rs @@ -64,6 +64,7 @@ pub use service::ExternalAgentConfigImportSuccess; pub use service::ExternalAgentConfigMigrationItem; pub use service::ExternalAgentConfigMigrationItemType; pub use service::ExternalAgentConfigService; +pub use service::ExternalAgentSessionImportLimits; pub use service::MigrationDetails; pub use service::NamedMigration; pub use service::PendingPluginImport; diff --git a/codex-rs/external-agent-migration/src/migration_source.rs b/codex-rs/external-agent-migration/src/migration_source.rs index cd56c3929b..ae4d9fb241 100644 --- a/codex-rs/external-agent-migration/src/migration_source.rs +++ b/codex-rs/external-agent-migration/src/migration_source.rs @@ -2,8 +2,9 @@ use crate::ClaSource; use crate::CurSource; use crate::RewriteProfile; use crate::detect::plugins; -use crate::detect::sessions::detect_recent_cla_sessions; -use crate::detect::sessions::detect_recent_cur_sessions; +use crate::detect::sessions::detect_recent_cla_sessions_with_limits; +use crate::detect::sessions::detect_recent_cur_sessions_with_limits; +use crate::model::ExternalAgentSessionImportLimits; use crate::sessions::ExternalAgentSessionMigration; use crate::sessions::SessionMetadataMode; use serde_json::Value as JsonValue; @@ -122,10 +123,15 @@ impl ExternalAgentSource { self, external_agent_home: &Path, codex_home: &Path, + limits: ExternalAgentSessionImportLimits, ) -> io::Result> { match self { - Self::Cla => detect_recent_cla_sessions(external_agent_home, codex_home), - Self::Cur => detect_recent_cur_sessions(external_agent_home, codex_home), + Self::Cla => { + detect_recent_cla_sessions_with_limits(external_agent_home, codex_home, limits) + } + Self::Cur => { + detect_recent_cur_sessions_with_limits(external_agent_home, codex_home, limits) + } } } diff --git a/codex-rs/external-agent-migration/src/model.rs b/codex-rs/external-agent-migration/src/model.rs index 255823eb38..555d0b0e89 100644 --- a/codex-rs/external-agent-migration/src/model.rs +++ b/codex-rs/external-agent-migration/src/model.rs @@ -1,5 +1,27 @@ use crate::sessions::ExternalAgentSessionMigration; use std::path::PathBuf; +use std::time::Duration; + +const DEFAULT_SESSION_IMPORT_MAX_AGE: Duration = Duration::from_secs(30 * 24 * 60 * 60); +const DEFAULT_SESSION_IMPORT_MAX_COUNT: usize = 50; + +/// Bounds session discovery for an external-agent import. +#[derive(Debug, Clone, Copy, PartialEq, Eq)] +pub struct ExternalAgentSessionImportLimits { + /// Oldest source-session modification age that remains eligible. + pub max_age: Duration, + /// Maximum number of eligible sessions returned by detection. + pub max_sessions: usize, +} + +impl Default for ExternalAgentSessionImportLimits { + fn default() -> Self { + Self { + max_age: DEFAULT_SESSION_IMPORT_MAX_AGE, + max_sessions: DEFAULT_SESSION_IMPORT_MAX_COUNT, + } + } +} #[derive(Debug, Clone, PartialEq, Eq)] pub struct ExternalAgentConfigDetectOptions { diff --git a/codex-rs/external-agent-migration/src/service.rs b/codex-rs/external-agent-migration/src/service.rs index 9246202180..e798db2667 100644 --- a/codex-rs/external-agent-migration/src/service.rs +++ b/codex-rs/external-agent-migration/src/service.rs @@ -13,6 +13,7 @@ pub use crate::model::ExternalAgentConfigImportRawError; pub use crate::model::ExternalAgentConfigImportSuccess; pub use crate::model::ExternalAgentConfigMigrationItem; pub use crate::model::ExternalAgentConfigMigrationItemType; +pub use crate::model::ExternalAgentSessionImportLimits; pub use crate::model::MigrationDetails; pub use crate::model::NamedMigration; pub use crate::model::PendingPluginImport; @@ -64,6 +65,7 @@ pub struct ExternalAgentConfigService { pub(crate) external_agent_home: PathBuf, pub(crate) analytics_events_client: Option, pub(crate) source: ExternalAgentSource, + pub(crate) session_import_limits: ExternalAgentSessionImportLimits, state_db: Option, } @@ -82,6 +84,7 @@ impl ExternalAgentConfigService { external_agent_home, analytics_events_client: Some(analytics_events_client), source, + session_import_limits: ExternalAgentSessionImportLimits::default(), state_db, } } @@ -96,10 +99,17 @@ impl ExternalAgentConfigService { external_agent_home, analytics_events_client: self.analytics_events_client.clone(), source, + session_import_limits: self.session_import_limits, state_db: self.state_db.clone(), } } + pub fn with_session_import_limits(&self, limits: ExternalAgentSessionImportLimits) -> Self { + let mut service = self.clone(); + service.session_import_limits = limits; + service + } + pub fn session_metadata_mode(&self) -> SessionMetadataMode { self.source.session_metadata_mode() } @@ -122,6 +132,7 @@ impl ExternalAgentConfigService { external_agent_home, analytics_events_client: None, source, + session_import_limits: ExternalAgentSessionImportLimits::default(), state_db: None, } } diff --git a/codex-rs/tui/src/external_agent_config_migration_flow.rs b/codex-rs/tui/src/external_agent_config_migration_flow.rs index 24d078f16b..c802664f41 100644 --- a/codex-rs/tui/src/external_agent_config_migration_flow.rs +++ b/codex-rs/tui/src/external_agent_config_migration_flow.rs @@ -274,6 +274,8 @@ pub(crate) async fn handle_external_agent_config_migration_prompt( .external_agent_config_detect(ExternalAgentConfigDetectParams { include_home: true, cwds: Some(vec![cwd.clone()]), + max_session_age_days: None, + max_sessions: None, source: None, migration_source: Some(source.migration_source().to_string()), })