feat: dispatch queued user messages from thread idle

This commit is contained in:
Edward Frazer
2026-06-16 06:14:24 +00:00
parent 19d58dfe9a
commit 2aa714e273
18 changed files with 780 additions and 13 deletions
+7 -1
View File
@@ -59,8 +59,14 @@ where
executor_skill_provider,
thread_store: _thread_store,
} = dependencies;
let mut builder = ExtensionRegistryBuilder::<Config>::with_event_sink(event_sink);
let mut builder = ExtensionRegistryBuilder::<Config>::with_event_sink(Arc::clone(&event_sink));
if let Some(state_db) = state_db {
let queue_service = Arc::new(codex_queue_extension::QueuedItemService::new(
Arc::clone(&state_db),
thread_manager.clone(),
Arc::clone(&event_sink),
));
codex_queue_extension::install(&mut builder, queue_service);
codex_goal_extension::install_with_backend(
&mut builder,
state_db,
@@ -63,18 +63,11 @@ impl ThreadGoalRequestProcessor {
.map(|()| None)
}
pub(crate) async fn emit_resume_goal_snapshot_and_continue(
&self,
thread_id: ThreadId,
thread: &CodexThread,
) {
pub(crate) async fn emit_resume_goal_snapshot(&self, thread_id: ThreadId) {
if !self.config.features.enabled(Feature::Goals) {
return;
}
self.emit_thread_goal_snapshot(thread_id).await;
// App-server owns resume response and snapshot ordering, so wait until
// those are sent before letting extensions react to the idle thread.
thread.emit_thread_idle_lifecycle_if_idle().await;
}
pub(crate) async fn pending_resume_goal_state(
@@ -698,9 +698,7 @@ pub(super) async fn handle_pending_thread_resume_request(
.await;
// App-server owns resume response and snapshot ordering, so wait until
// replay completes before letting extensions react to the idle thread.
if pending.emit_thread_goal_update {
conversation.emit_thread_idle_lifecycle_if_idle().await;
}
conversation.emit_thread_idle_lifecycle_if_idle().await;
}
pub(super) async fn send_thread_goal_snapshot_notification(
@@ -2814,8 +2814,11 @@ impl ThreadRequestProcessor {
.await;
}
self.thread_goal_processor
.emit_resume_goal_snapshot_and_continue(thread_id, codex_thread.as_ref())
.emit_resume_goal_snapshot(thread_id)
.await;
// App-server owns resume response and snapshot ordering, so wait until
// those are sent before letting extensions react to the idle thread.
codex_thread.emit_thread_idle_lifecycle_if_idle().await;
}
Err(err) => {
let error = internal_error(format!("error resuming thread: {err}"));