mirror of
https://github.com/openai/codex.git
synced 2026-11-13 06:45:07 +00:00
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
This commit is contained in:
1 parent
9078e32371
commit
3bc49e1721
18 files changed
+195
-25
No files matched your search
@@ -876,6 +876,24 @@
|
|||||||
"description": "If true, include detection under the user's home directory.",
|
"description": "If true, include detection under the user's home directory.",
|
||||||
"type": "boolean"
|
"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": {
|
"migrationSource": {
|
||||||
"description": "Optional migration-source selector. Missing or unrecognized values use the default source.",
|
"description": "Optional migration-source selector. Missing or unrecognized values use the default source.",
|
||||||
"type": [
|
"type": [
|
||||||
|
|||||||
+18
@@ -9577,6 +9577,24 @@
|
|||||||
"description": "If true, include detection under the user's home directory.",
|
"description": "If true, include detection under the user's home directory.",
|
||||||
"type": "boolean"
|
"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": {
|
"migrationSource": {
|
||||||
"description": "Optional migration-source selector. Missing or unrecognized values use the default source.",
|
"description": "Optional migration-source selector. Missing or unrecognized values use the default source.",
|
||||||
"type": [
|
"type": [
|
||||||
|
|||||||
+18
@@ -5755,6 +5755,24 @@
|
|||||||
"description": "If true, include detection under the user's home directory.",
|
"description": "If true, include detection under the user's home directory.",
|
||||||
"type": "boolean"
|
"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": {
|
"migrationSource": {
|
||||||
"description": "Optional migration-source selector. Missing or unrecognized values use the default source.",
|
"description": "Optional migration-source selector. Missing or unrecognized values use the default source.",
|
||||||
"type": [
|
"type": [
|
||||||
|
|||||||
+18
@@ -15,6 +15,24 @@
|
|||||||
"description": "If true, include detection under the user's home directory.",
|
"description": "If true, include detection under the user's home directory.",
|
||||||
"type": "boolean"
|
"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": {
|
"migrationSource": {
|
||||||
"description": "Optional migration-source selector. Missing or unrecognized values use the default source.",
|
"description": "Optional migration-source selector. Missing or unrecognized values use the default source.",
|
||||||
"type": [
|
"type": [
|
||||||
|
|||||||
+8
@@ -11,6 +11,14 @@ includeHome?: boolean,
|
|||||||
* Zero or more working directories to include for repo-scoped detection.
|
* Zero or more working directories to include for repo-scoped detection.
|
||||||
*/
|
*/
|
||||||
cwds?: Array<string> | null,
|
cwds?: Array<string> | 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`
|
* Deprecated field retained for compatibility. This field is ignored; use `migrationSource`
|
||||||
* to select the migration source.
|
* to select the migration source.
|
||||||
|
|||||||
@@ -699,6 +699,12 @@ pub struct ExternalAgentConfigDetectParams {
|
|||||||
/// Zero or more working directories to include for repo-scoped detection.
|
/// Zero or more working directories to include for repo-scoped detection.
|
||||||
#[ts(optional = nullable)]
|
#[ts(optional = nullable)]
|
||||||
pub cwds: Option<Vec<PathBuf>>,
|
pub cwds: Option<Vec<PathBuf>>,
|
||||||
|
/// Maximum age in days for detected sessions. Missing values use the default limit.
|
||||||
|
#[ts(optional = nullable)]
|
||||||
|
pub max_session_age_days: Option<u32>,
|
||||||
|
/// Maximum number of sessions to detect. Missing values use the default limit.
|
||||||
|
#[ts(optional = nullable)]
|
||||||
|
pub max_sessions: Option<u32>,
|
||||||
/// Deprecated field retained for compatibility. This field is ignored; use `migrationSource`
|
/// Deprecated field retained for compatibility. This field is ignored; use `migrationSource`
|
||||||
/// to select the migration source.
|
/// to select the migration source.
|
||||||
#[ts(optional = nullable)]
|
#[ts(optional = nullable)]
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
use std::time::Duration;
|
||||||
|
|
||||||
use crate::config_manager::ConfigManager;
|
use crate::config_manager::ConfigManager;
|
||||||
use crate::error_code::internal_error;
|
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::ExternalAgentConfigImportOutcome as CoreImportOutcome;
|
||||||
use codex_external_agent_migration::ExternalAgentConfigMigrationItemType as CoreMigrationItemType;
|
use codex_external_agent_migration::ExternalAgentConfigMigrationItemType as CoreMigrationItemType;
|
||||||
use codex_external_agent_migration::ExternalAgentConfigService;
|
use codex_external_agent_migration::ExternalAgentConfigService;
|
||||||
|
use codex_external_agent_migration::ExternalAgentSessionImportLimits;
|
||||||
use codex_external_agent_migration::PluginImportOutcome;
|
use codex_external_agent_migration::PluginImportOutcome;
|
||||||
use codex_external_agent_migration::record_import_error;
|
use codex_external_agent_migration::record_import_error;
|
||||||
use codex_external_agent_migration::sessions::ExternalAgentSessionMigration as CoreSessionMigration;
|
use codex_external_agent_migration::sessions::ExternalAgentSessionMigration as CoreSessionMigration;
|
||||||
@@ -119,6 +121,18 @@ impl ExternalAgentConfigRequestProcessor {
|
|||||||
let migration_service = self
|
let migration_service = self
|
||||||
.migration_service
|
.migration_service
|
||||||
.with_migration_source(params.migration_source.as_deref());
|
.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 {
|
let options = ExternalAgentConfigDetectOptions {
|
||||||
include_home: params.include_home,
|
include_home: params.include_home,
|
||||||
include_memory: self.external_agent_memory_import_enabled().await,
|
include_memory: self.external_agent_memory_import_enabled().await,
|
||||||
|
|||||||
@@ -378,9 +378,11 @@ impl ExternalAgentConfigService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if scope.is_home() {
|
if scope.is_home() {
|
||||||
let sessions = self
|
let sessions = self.source.recent_sessions(
|
||||||
.source
|
&self.external_agent_home,
|
||||||
.recent_sessions(&self.external_agent_home, &self.codex_home)?;
|
&self.codex_home,
|
||||||
|
self.session_import_limits,
|
||||||
|
)?;
|
||||||
if !sessions.is_empty() {
|
if !sessions.is_empty() {
|
||||||
items.push(ExternalAgentConfigMigrationItem {
|
items.push(ExternalAgentConfigMigrationItem {
|
||||||
item_type: ExternalAgentConfigMigrationItemType::Sessions,
|
item_type: ExternalAgentConfigMigrationItemType::Sessions,
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
#[cfg(test)]
|
|
||||||
use super::common::SESSION_IMPORT_MAX_COUNT;
|
|
||||||
use super::common::SessionFileCandidate;
|
use super::common::SessionFileCandidate;
|
||||||
use super::common::detect_recent_sessions;
|
use super::common::detect_recent_sessions;
|
||||||
|
use crate::model::ExternalAgentSessionImportLimits;
|
||||||
use crate::sessions::ExternalAgentSessionMigration;
|
use crate::sessions::ExternalAgentSessionMigration;
|
||||||
use std::fs;
|
use std::fs;
|
||||||
use std::io;
|
use std::io;
|
||||||
@@ -10,6 +9,18 @@ use std::path::Path;
|
|||||||
pub fn detect_recent_cla_sessions(
|
pub fn detect_recent_cla_sessions(
|
||||||
external_agent_home: &Path,
|
external_agent_home: &Path,
|
||||||
codex_home: &Path,
|
codex_home: &Path,
|
||||||
|
) -> io::Result<Vec<ExternalAgentSessionMigration>> {
|
||||||
|
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<Vec<ExternalAgentSessionMigration>> {
|
) -> io::Result<Vec<ExternalAgentSessionMigration>> {
|
||||||
let projects_root = external_agent_home.join("projects");
|
let projects_root = external_agent_home.join("projects");
|
||||||
if !projects_root.is_dir() {
|
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)]
|
#[cfg(test)]
|
||||||
@@ -233,7 +246,8 @@ mod tests {
|
|||||||
let timestamp = chrono::Utc::now().to_rfc3339_opts(chrono::SecondsFormat::Secs, true);
|
let timestamp = chrono::Utc::now().to_rfc3339_opts(chrono::SecondsFormat::Secs, true);
|
||||||
let modified_at = SystemTime::now();
|
let modified_at = SystemTime::now();
|
||||||
let mut expected = Vec::new();
|
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 file_name = format!("{index:02}-session.jsonl");
|
||||||
let title = format!("session {index}");
|
let title = format!("session {index}");
|
||||||
let path = write_session(
|
let path = write_session(
|
||||||
@@ -275,7 +289,7 @@ mod tests {
|
|||||||
}
|
}
|
||||||
|
|
||||||
let changed_at = SystemTime::now()
|
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() {
|
for (index, session) in all_sessions.iter().enumerate() {
|
||||||
let title = session.title.as_deref().expect("session title");
|
let title = session.title.as_deref().expect("session title");
|
||||||
std::fs::write(
|
std::fs::write(
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
use crate::model::ExternalAgentSessionImportLimits;
|
||||||
use crate::sessions::ExternalAgentSessionMigration;
|
use crate::sessions::ExternalAgentSessionMigration;
|
||||||
use crate::sessions::ledger::load_import_ledger;
|
use crate::sessions::ledger::load_import_ledger;
|
||||||
use crate::sessions::ledger::save_import_ledger;
|
use crate::sessions::ledger::save_import_ledger;
|
||||||
@@ -9,10 +10,6 @@ use std::fs;
|
|||||||
use std::io;
|
use std::io;
|
||||||
use std::path::Path;
|
use std::path::Path;
|
||||||
use std::path::PathBuf;
|
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(super) struct SessionFileCandidate {
|
||||||
pub path: PathBuf,
|
pub path: PathBuf,
|
||||||
@@ -23,11 +20,12 @@ pub(super) fn detect_recent_sessions(
|
|||||||
codex_home: &Path,
|
codex_home: &Path,
|
||||||
candidates: impl IntoIterator<Item = SessionFileCandidate>,
|
candidates: impl IntoIterator<Item = SessionFileCandidate>,
|
||||||
require_existing_cwd: bool,
|
require_existing_cwd: bool,
|
||||||
|
limits: ExternalAgentSessionImportLimits,
|
||||||
) -> io::Result<Vec<ExternalAgentSessionMigration>> {
|
) -> io::Result<Vec<ExternalAgentSessionMigration>> {
|
||||||
let now = now_unix_seconds();
|
let now = now_unix_seconds();
|
||||||
let mut ledger = load_import_ledger(codex_home)?;
|
let mut ledger = load_import_ledger(codex_home)?;
|
||||||
let source_states = ledger.source_states();
|
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 {
|
for candidate in candidates {
|
||||||
let Ok(metadata) = fs::metadata(&candidate.path) else {
|
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 {
|
let Ok(modified_at) = modified_at.duration_since(std::time::UNIX_EPOCH) else {
|
||||||
continue;
|
continue;
|
||||||
};
|
};
|
||||||
if (modified_at.as_secs() as i64)
|
if (modified_at.as_secs() as i64) < now.saturating_sub(limits.max_age.as_secs() as i64) {
|
||||||
< now.saturating_sub(SESSION_IMPORT_MAX_AGE.as_secs() as i64)
|
|
||||||
{
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
let Ok(modified_at_nanos) = i64::try_from(modified_at.as_nanos()) else {
|
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.path,
|
||||||
candidate.fallback_cwd,
|
candidate.fallback_cwd,
|
||||||
));
|
));
|
||||||
if recent.len() > SESSION_IMPORT_MAX_COUNT {
|
if recent.len() > limits.max_sessions {
|
||||||
recent.pop();
|
recent.pop();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
#[cfg(test)]
|
|
||||||
use super::common::SESSION_IMPORT_MAX_COUNT;
|
|
||||||
use super::common::SessionFileCandidate;
|
use super::common::SessionFileCandidate;
|
||||||
use super::common::detect_recent_sessions;
|
use super::common::detect_recent_sessions;
|
||||||
|
use crate::model::ExternalAgentSessionImportLimits;
|
||||||
use crate::sessions::ExternalAgentSessionMigration;
|
use crate::sessions::ExternalAgentSessionMigration;
|
||||||
use std::fs;
|
use std::fs;
|
||||||
use std::io;
|
use std::io;
|
||||||
@@ -11,6 +10,18 @@ use std::path::PathBuf;
|
|||||||
pub fn detect_recent_cur_sessions(
|
pub fn detect_recent_cur_sessions(
|
||||||
external_agent_home: &Path,
|
external_agent_home: &Path,
|
||||||
codex_home: &Path,
|
codex_home: &Path,
|
||||||
|
) -> io::Result<Vec<ExternalAgentSessionMigration>> {
|
||||||
|
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<Vec<ExternalAgentSessionMigration>> {
|
) -> io::Result<Vec<ExternalAgentSessionMigration>> {
|
||||||
let projects_root = external_agent_home.join("projects");
|
let projects_root = external_agent_home.join("projects");
|
||||||
if !projects_root.is_dir() {
|
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<PathBuf> {
|
fn cur_transcript_files(transcripts_root: &Path) -> Vec<PathBuf> {
|
||||||
|
|||||||
@@ -171,7 +171,8 @@ fn detects_cur_sessions_in_batches_and_redetects_modified_imports() {
|
|||||||
let encoded_project = encode_project_path(&project_root);
|
let encoded_project = encode_project_path(&project_root);
|
||||||
let modified_at = SystemTime::now();
|
let modified_at = SystemTime::now();
|
||||||
let mut expected = Vec::new();
|
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 session_id = format!("session-{index:02}");
|
||||||
let title = format!("request {index}");
|
let title = format!("request {index}");
|
||||||
let path = write_transcript(&external_agent_home, &encoded_project, &session_id, &title);
|
let path = write_transcript(&external_agent_home, &encoded_project, &session_id, &title);
|
||||||
|
|||||||
@@ -4,6 +4,8 @@ mod connectors_cla;
|
|||||||
mod cur;
|
mod cur;
|
||||||
|
|
||||||
pub use cla::detect_recent_cla_sessions;
|
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::ImportedSessionConnectorAttribution;
|
||||||
pub use connectors_cla::detect_imported_cla_session_connectors;
|
pub use connectors_cla::detect_imported_cla_session_connectors;
|
||||||
pub use cur::detect_recent_cur_sessions;
|
pub use cur::detect_recent_cur_sessions;
|
||||||
|
pub(crate) use cur::detect_recent_cur_sessions_with_limits;
|
||||||
@@ -64,6 +64,7 @@ pub use service::ExternalAgentConfigImportSuccess;
|
|||||||
pub use service::ExternalAgentConfigMigrationItem;
|
pub use service::ExternalAgentConfigMigrationItem;
|
||||||
pub use service::ExternalAgentConfigMigrationItemType;
|
pub use service::ExternalAgentConfigMigrationItemType;
|
||||||
pub use service::ExternalAgentConfigService;
|
pub use service::ExternalAgentConfigService;
|
||||||
|
pub use service::ExternalAgentSessionImportLimits;
|
||||||
pub use service::MigrationDetails;
|
pub use service::MigrationDetails;
|
||||||
pub use service::NamedMigration;
|
pub use service::NamedMigration;
|
||||||
pub use service::PendingPluginImport;
|
pub use service::PendingPluginImport;
|
||||||
|
|||||||
@@ -2,8 +2,9 @@ use crate::ClaSource;
|
|||||||
use crate::CurSource;
|
use crate::CurSource;
|
||||||
use crate::RewriteProfile;
|
use crate::RewriteProfile;
|
||||||
use crate::detect::plugins;
|
use crate::detect::plugins;
|
||||||
use crate::detect::sessions::detect_recent_cla_sessions;
|
use crate::detect::sessions::detect_recent_cla_sessions_with_limits;
|
||||||
use crate::detect::sessions::detect_recent_cur_sessions;
|
use crate::detect::sessions::detect_recent_cur_sessions_with_limits;
|
||||||
|
use crate::model::ExternalAgentSessionImportLimits;
|
||||||
use crate::sessions::ExternalAgentSessionMigration;
|
use crate::sessions::ExternalAgentSessionMigration;
|
||||||
use crate::sessions::SessionMetadataMode;
|
use crate::sessions::SessionMetadataMode;
|
||||||
use serde_json::Value as JsonValue;
|
use serde_json::Value as JsonValue;
|
||||||
@@ -122,10 +123,15 @@ impl ExternalAgentSource {
|
|||||||
self,
|
self,
|
||||||
external_agent_home: &Path,
|
external_agent_home: &Path,
|
||||||
codex_home: &Path,
|
codex_home: &Path,
|
||||||
|
limits: ExternalAgentSessionImportLimits,
|
||||||
) -> io::Result<Vec<ExternalAgentSessionMigration>> {
|
) -> io::Result<Vec<ExternalAgentSessionMigration>> {
|
||||||
match self {
|
match self {
|
||||||
Self::Cla => detect_recent_cla_sessions(external_agent_home, codex_home),
|
Self::Cla => {
|
||||||
Self::Cur => detect_recent_cur_sessions(external_agent_home, codex_home),
|
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)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,27 @@
|
|||||||
use crate::sessions::ExternalAgentSessionMigration;
|
use crate::sessions::ExternalAgentSessionMigration;
|
||||||
use std::path::PathBuf;
|
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)]
|
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||||
pub struct ExternalAgentConfigDetectOptions {
|
pub struct ExternalAgentConfigDetectOptions {
|
||||||
|
|||||||
@@ -13,6 +13,7 @@ pub use crate::model::ExternalAgentConfigImportRawError;
|
|||||||
pub use crate::model::ExternalAgentConfigImportSuccess;
|
pub use crate::model::ExternalAgentConfigImportSuccess;
|
||||||
pub use crate::model::ExternalAgentConfigMigrationItem;
|
pub use crate::model::ExternalAgentConfigMigrationItem;
|
||||||
pub use crate::model::ExternalAgentConfigMigrationItemType;
|
pub use crate::model::ExternalAgentConfigMigrationItemType;
|
||||||
|
pub use crate::model::ExternalAgentSessionImportLimits;
|
||||||
pub use crate::model::MigrationDetails;
|
pub use crate::model::MigrationDetails;
|
||||||
pub use crate::model::NamedMigration;
|
pub use crate::model::NamedMigration;
|
||||||
pub use crate::model::PendingPluginImport;
|
pub use crate::model::PendingPluginImport;
|
||||||
@@ -64,6 +65,7 @@ pub struct ExternalAgentConfigService {
|
|||||||
pub(crate) external_agent_home: PathBuf,
|
pub(crate) external_agent_home: PathBuf,
|
||||||
pub(crate) analytics_events_client: Option<AnalyticsEventsClient>,
|
pub(crate) analytics_events_client: Option<AnalyticsEventsClient>,
|
||||||
pub(crate) source: ExternalAgentSource,
|
pub(crate) source: ExternalAgentSource,
|
||||||
|
pub(crate) session_import_limits: ExternalAgentSessionImportLimits,
|
||||||
state_db: Option<StateDbHandle>,
|
state_db: Option<StateDbHandle>,
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -82,6 +84,7 @@ impl ExternalAgentConfigService {
|
|||||||
external_agent_home,
|
external_agent_home,
|
||||||
analytics_events_client: Some(analytics_events_client),
|
analytics_events_client: Some(analytics_events_client),
|
||||||
source,
|
source,
|
||||||
|
session_import_limits: ExternalAgentSessionImportLimits::default(),
|
||||||
state_db,
|
state_db,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -96,10 +99,17 @@ impl ExternalAgentConfigService {
|
|||||||
external_agent_home,
|
external_agent_home,
|
||||||
analytics_events_client: self.analytics_events_client.clone(),
|
analytics_events_client: self.analytics_events_client.clone(),
|
||||||
source,
|
source,
|
||||||
|
session_import_limits: self.session_import_limits,
|
||||||
state_db: self.state_db.clone(),
|
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 {
|
pub fn session_metadata_mode(&self) -> SessionMetadataMode {
|
||||||
self.source.session_metadata_mode()
|
self.source.session_metadata_mode()
|
||||||
}
|
}
|
||||||
@@ -122,6 +132,7 @@ impl ExternalAgentConfigService {
|
|||||||
external_agent_home,
|
external_agent_home,
|
||||||
analytics_events_client: None,
|
analytics_events_client: None,
|
||||||
source,
|
source,
|
||||||
|
session_import_limits: ExternalAgentSessionImportLimits::default(),
|
||||||
state_db: None,
|
state_db: None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -274,6 +274,8 @@ pub(crate) async fn handle_external_agent_config_migration_prompt(
|
|||||||
.external_agent_config_detect(ExternalAgentConfigDetectParams {
|
.external_agent_config_detect(ExternalAgentConfigDetectParams {
|
||||||
include_home: true,
|
include_home: true,
|
||||||
cwds: Some(vec![cwd.clone()]),
|
cwds: Some(vec![cwd.clone()]),
|
||||||
|
max_session_age_days: None,
|
||||||
|
max_sessions: None,
|
||||||
source: None,
|
source: None,
|
||||||
migration_source: Some(source.migration_source().to_string()),
|
migration_source: Some(source.migration_source().to_string()),
|
||||||
})
|
})
|
||||||
|
|||||||
Reference in new issue
Block a user