diff --git a/codex-rs/core/src/session/session.rs b/codex-rs/core/src/session/session.rs index 692f4ad00..c9e1807fe 100644 --- a/codex-rs/core/src/session/session.rs +++ b/codex-rs/core/src/session/session.rs @@ -966,6 +966,8 @@ impl Session { for contributor in extensions.thread_lifecycle_contributors() { contributor.on_thread_start(codex_extension_api::ThreadStartInput { config: config.as_ref(), + session_source: &session_configuration.session_source, + persistent_thread_state_available: state_db_ctx.is_some(), session_store: &session_extension_data, thread_store: &thread_extension_data, }).await; diff --git a/codex-rs/ext/extension-api/src/contributors/thread_lifecycle.rs b/codex-rs/ext/extension-api/src/contributors/thread_lifecycle.rs index 07c7e7fa8..5fbd1562d 100644 --- a/codex-rs/ext/extension-api/src/contributors/thread_lifecycle.rs +++ b/codex-rs/ext/extension-api/src/contributors/thread_lifecycle.rs @@ -1,9 +1,14 @@ use crate::ExtensionData; +use codex_protocol::protocol::SessionSource; /// Input supplied when the host starts a runtime for a thread. pub struct ThreadStartInput<'a, C> { /// Host configuration visible at thread start. pub config: &'a C, + /// Source that created the session for this thread. + pub session_source: &'a SessionSource, + /// Whether persistent thread-scoped state is available for this thread. + pub persistent_thread_state_available: bool, /// Store scoped to the host session runtime. pub session_store: &'a ExtensionData, /// Store scoped to this thread runtime. diff --git a/codex-rs/ext/goal/tests/goal_extension_backend.rs b/codex-rs/ext/goal/tests/goal_extension_backend.rs index 584f7362b..7dbdd2e24 100644 --- a/codex-rs/ext/goal/tests/goal_extension_backend.rs +++ b/codex-rs/ext/goal/tests/goal_extension_backend.rs @@ -889,10 +889,13 @@ async fn installed_tools( let registry = builder.build(); let session_store = ExtensionData::new("session-1"); let thread_store = ExtensionData::new(thread_id.to_string()); + let session_source = SessionSource::Cli; for contributor in registry.thread_lifecycle_contributors() { contributor .on_thread_start(ThreadStartInput { config: &(), + session_source: &session_source, + persistent_thread_state_available: true, session_store: &session_store, thread_store: &thread_store, }) @@ -930,10 +933,13 @@ impl GoalExtensionHarness { let registry = builder.build(); let session_store = ExtensionData::new("session-1"); let thread_store = ExtensionData::new(thread_id.to_string()); + let session_source = SessionSource::Cli; for contributor in registry.thread_lifecycle_contributors() { contributor .on_thread_start(ThreadStartInput { config: &(), + session_source: &session_source, + persistent_thread_state_available: true, session_store: &session_store, thread_store: &thread_store, })