Preserve thread lifecycle input compatibility

This commit is contained in:
Eric Traut
2026-05-27 12:55:39 -07:00
parent 3177d69fa7
commit 12143a14c5
7 changed files with 83 additions and 20 deletions
+7 -5
View File
@@ -176,11 +176,13 @@ impl CodexThread {
.thread_lifecycle_contributors()
{
contributor
.on_thread_resume(codex_extension_api::ThreadResumeInput {
thread_settings: &thread_settings,
session_store: &self.codex.session.services.session_extension_data,
thread_store: &self.codex.session.services.thread_extension_data,
})
.on_thread_resume_with_settings(
codex_extension_api::ThreadResumeWithSettingsInput {
thread_settings: &thread_settings,
session_store: &self.codex.session.services.session_extension_data,
thread_store: &self.codex.session.services.thread_extension_data,
},
)
.await;
}
}
+8 -6
View File
@@ -108,7 +108,7 @@ async fn notify_thread_idle(session: &Session) {
let thread_settings = thread_settings_snapshot(session).await;
for contributor in session.services.extensions.thread_lifecycle_contributors() {
contributor
.on_thread_idle(codex_extension_api::ThreadIdleInput {
.on_thread_idle_with_settings(codex_extension_api::ThreadIdleWithSettingsInput {
thread_settings: &thread_settings,
session_store: &session.services.session_extension_data,
thread_store: &session.services.thread_extension_data,
@@ -144,11 +144,13 @@ async fn next_idle_turn_candidate(session: &Session) -> Option<IdleTurnCandidate
.enumerate()
{
let Some(request) = contributor
.request_thread_idle_turn(codex_extension_api::ThreadIdleInput {
thread_settings: &thread_settings,
session_store: &session.services.session_extension_data,
thread_store: &session.services.thread_extension_data,
})
.request_thread_idle_turn_with_settings(
codex_extension_api::ThreadIdleWithSettingsInput {
thread_settings: &thread_settings,
session_store: &session.services.session_extension_data,
thread_store: &session.services.thread_extension_data,
},
)
.await
else {
continue;
@@ -22,7 +22,9 @@ pub use prompt::PromptSlot;
pub use thread_lifecycle::ThreadIdleInput;
pub use thread_lifecycle::ThreadIdleRequest;
pub use thread_lifecycle::ThreadIdleTurnStartInput;
pub use thread_lifecycle::ThreadIdleWithSettingsInput;
pub use thread_lifecycle::ThreadResumeInput;
pub use thread_lifecycle::ThreadResumeWithSettingsInput;
pub use thread_lifecycle::ThreadStartInput;
pub use thread_lifecycle::ThreadStopInput;
pub use tool_lifecycle::ToolCallOutcome;
@@ -58,9 +60,21 @@ pub trait ThreadLifecycleContributor<C: Sync>: Send + Sync {
/// Called after the host constructs a runtime from persisted history.
async fn on_thread_resume(&self, _input: ThreadResumeInput<'_>) {}
/// Called after the host constructs a runtime from persisted history, with
/// a snapshot of host-owned thread settings.
async fn on_thread_resume_with_settings(&self, input: ThreadResumeWithSettingsInput<'_>) {
self.on_thread_resume(input.without_settings()).await;
}
/// Called after the host has drained immediately pending thread work.
async fn on_thread_idle(&self, _input: ThreadIdleInput<'_>) {}
/// Called after the host has drained immediately pending thread work, with
/// a snapshot of host-owned thread settings.
async fn on_thread_idle_with_settings(&self, input: ThreadIdleWithSettingsInput<'_>) {
self.on_thread_idle(input.without_settings()).await;
}
/// Called before the host drops the thread runtime and thread-scoped store.
async fn on_thread_stop(&self, _input: ThreadStopInput<'_>) {}
}
@@ -87,6 +101,15 @@ pub trait ThreadIdleTurnContributor: Send + Sync {
Box::pin(std::future::ready(None))
}
/// Returns one hidden prompt body to start an idle turn, with a snapshot of
/// host-owned thread settings.
fn request_thread_idle_turn_with_settings<'a>(
&'a self,
input: ThreadIdleWithSettingsInput<'a>,
) -> ThreadIdleTurnRequestFuture<'a> {
self.request_thread_idle_turn(input.without_settings())
}
/// Confirms that the idle-turn request is still current immediately before
/// the host starts the turn.
fn should_start_thread_idle_turn<'a>(
@@ -13,6 +13,14 @@ pub struct ThreadStartInput<'a, C> {
/// Input supplied when the host resumes an existing thread.
pub struct ThreadResumeInput<'a> {
/// Store scoped to the host session runtime.
pub session_store: &'a ExtensionData,
/// Store scoped to this thread runtime.
pub thread_store: &'a ExtensionData,
}
/// Settings-aware input supplied when the host resumes an existing thread.
pub struct ThreadResumeWithSettingsInput<'a> {
/// Current host-owned thread settings at resume time.
pub thread_settings: &'a ThreadSettingsSnapshot,
/// Store scoped to the host session runtime.
@@ -21,8 +29,25 @@ pub struct ThreadResumeInput<'a> {
pub thread_store: &'a ExtensionData,
}
impl<'a> ThreadResumeWithSettingsInput<'a> {
pub fn without_settings(&self) -> ThreadResumeInput<'a> {
ThreadResumeInput {
session_store: self.session_store,
thread_store: self.thread_store,
}
}
}
/// Input supplied when the host has no immediately pending thread work.
pub struct ThreadIdleInput<'a> {
/// Store scoped to the host session runtime.
pub session_store: &'a ExtensionData,
/// Store scoped to this thread runtime.
pub thread_store: &'a ExtensionData,
}
/// Settings-aware input supplied when the host has no immediately pending thread work.
pub struct ThreadIdleWithSettingsInput<'a> {
/// Current host-owned thread settings for the idle thread.
pub thread_settings: &'a ThreadSettingsSnapshot,
/// Store scoped to the host session runtime.
@@ -31,6 +56,15 @@ pub struct ThreadIdleInput<'a> {
pub thread_store: &'a ExtensionData,
}
impl<'a> ThreadIdleWithSettingsInput<'a> {
pub fn without_settings(&self) -> ThreadIdleInput<'a> {
ThreadIdleInput {
session_store: self.session_store,
thread_store: self.thread_store,
}
}
}
/// Extension request to start a new idle turn.
pub struct ThreadIdleRequest {
/// Hidden prompt body that the host wraps as extension-owned context.
+2
View File
@@ -34,8 +34,10 @@ pub use contributors::ThreadIdleTurnContributor;
pub use contributors::ThreadIdleTurnRequestFuture;
pub use contributors::ThreadIdleTurnStartFuture;
pub use contributors::ThreadIdleTurnStartInput;
pub use contributors::ThreadIdleWithSettingsInput;
pub use contributors::ThreadLifecycleContributor;
pub use contributors::ThreadResumeInput;
pub use contributors::ThreadResumeWithSettingsInput;
pub use contributors::ThreadStartInput;
pub use contributors::ThreadStopInput;
pub use contributors::TokenUsageContributor;
+5 -5
View File
@@ -7,13 +7,13 @@ use codex_extension_api::ConfigContributor;
use codex_extension_api::ExtensionData;
use codex_extension_api::ExtensionEventSink;
use codex_extension_api::ExtensionRegistryBuilder;
use codex_extension_api::ThreadIdleInput;
use codex_extension_api::ThreadIdleTurnContributor;
use codex_extension_api::ThreadIdleTurnRequestFuture;
use codex_extension_api::ThreadIdleTurnStartFuture;
use codex_extension_api::ThreadIdleTurnStartInput;
use codex_extension_api::ThreadIdleWithSettingsInput;
use codex_extension_api::ThreadLifecycleContributor;
use codex_extension_api::ThreadResumeInput;
use codex_extension_api::ThreadResumeWithSettingsInput;
use codex_extension_api::ThreadStartInput;
use codex_extension_api::TokenUsageContributor;
use codex_extension_api::ToolCallOutcome;
@@ -118,7 +118,7 @@ where
runtime.set_enabled(enabled);
}
async fn on_thread_resume(&self, input: ThreadResumeInput<'_>) {
async fn on_thread_resume_with_settings(&self, input: ThreadResumeWithSettingsInput<'_>) {
let Some(runtime) = goal_runtime_handle(input.thread_store) else {
return;
};
@@ -136,9 +136,9 @@ impl<C> ThreadIdleTurnContributor for GoalExtension<C>
where
C: Send + Sync + 'static,
{
fn request_thread_idle_turn<'a>(
fn request_thread_idle_turn_with_settings<'a>(
&'a self,
input: ThreadIdleInput<'a>,
input: ThreadIdleWithSettingsInput<'a>,
) -> ThreadIdleTurnRequestFuture<'a> {
Box::pin(async move {
let runtime = goal_runtime_handle(input.thread_store)?;
@@ -8,10 +8,10 @@ use codex_extension_api::ExtensionData;
use codex_extension_api::ExtensionEventSink;
use codex_extension_api::ExtensionRegistryBuilder;
use codex_extension_api::FunctionCallError;
use codex_extension_api::ThreadIdleInput;
use codex_extension_api::ThreadIdleRequest;
use codex_extension_api::ThreadIdleTurnStartInput;
use codex_extension_api::ThreadResumeInput;
use codex_extension_api::ThreadIdleWithSettingsInput;
use codex_extension_api::ThreadResumeWithSettingsInput;
use codex_extension_api::ThreadStartInput;
use codex_extension_api::ToolCall;
use codex_extension_api::ToolCallOutcome;
@@ -1272,7 +1272,7 @@ impl GoalExtensionHarness {
let thread_settings = thread_settings(mode);
for contributor in self.registry.thread_lifecycle_contributors() {
contributor
.on_thread_resume(ThreadResumeInput {
.on_thread_resume_with_settings(ThreadResumeWithSettingsInput {
thread_settings: &thread_settings,
session_store: &self.session_store,
thread_store: &self.thread_store,
@@ -1319,7 +1319,7 @@ impl GoalExtensionHarness {
let thread_settings = thread_settings(mode);
for contributor in self.registry.thread_idle_turn_contributors() {
if let Some(request) = contributor
.request_thread_idle_turn(ThreadIdleInput {
.request_thread_idle_turn_with_settings(ThreadIdleWithSettingsInput {
thread_settings: &thread_settings,
session_store: &self.session_store,
thread_store: &self.thread_store,