mirror of
https://github.com/openai/codex.git
synced 2026-11-13 06:45:07 +00:00
Support asynchronous command hooks (#37533)
## Why Hook configurations can mark command handlers as asynchronous, but Codex previously skipped those handlers outside `SessionEnd`. ## What changed - Run asynchronous command hooks in the background with a per-session concurrency limit, while keeping `SessionEnd` hooks synchronous. - Prevent asynchronous hooks from blocking, stopping, rewriting, or otherwise controlling the operation that launched them. - Deliver warnings and additional context at safe turn boundaries: inject results into an active turn after sampling, or buffer them ahead of the next user prompt when the session is idle. - Preserve in-flight hooks across configuration reloads, scope spilled output to the thread, and abort outstanding work during session shutdown. ## Testing Add unit and integration coverage for background scheduling, concurrency, output parsing, active and idle result delivery, configuration reloads, and shutdown cleanup. GitOrigin-RevId: 8094552e4afe7b47b09a61bb575bb20f4e491d8d
This commit is contained in:
1 parent
61a3dd4387
commit
6f647caa9b
29 files changed
+1514
-429
No files matched your search
@@ -21,6 +21,7 @@ use codex_protocol::config_types::ServiceTier;
|
||||
use codex_protocol::mcp::ClientMcpExtensions;
|
||||
use codex_protocol::permissions::FileSystemPath;
|
||||
use codex_protocol::permissions::FileSystemSpecialPath;
|
||||
use codex_protocol::protocol::HookCompletedEvent;
|
||||
use codex_protocol::protocol::MultiAgentVersion;
|
||||
use codex_protocol::protocol::ThreadHistoryMode;
|
||||
use codex_protocol::protocol::ThreadSource;
|
||||
@@ -55,6 +56,7 @@ pub(crate) struct Session {
|
||||
pub(super) mcp_prewarm_task: std::sync::Mutex<Option<JoinHandle<()>>>,
|
||||
pub(crate) conversation: Arc<RealtimeConversationManager>,
|
||||
pub(crate) active_turn: Mutex<Option<ActiveTurn>>,
|
||||
pub(crate) async_hook_results: async_channel::Receiver<HookCompletedEvent>,
|
||||
pub(crate) pending_user_message_admissions:
|
||||
crate::user_message_admission::PendingUserMessageAdmissions,
|
||||
pub(crate) input_queue: InputQueue,
|
||||
@@ -1169,12 +1171,13 @@ impl Session {
|
||||
(None, None)
|
||||
};
|
||||
|
||||
let hooks = build_hooks_for_config(
|
||||
let hooks_config = build_hooks_config(
|
||||
&config,
|
||||
plugins_manager.as_ref(),
|
||||
resolved_environments.single_local_environment(),
|
||||
)
|
||||
.await;
|
||||
let (hooks, async_hook_results) = Hooks::new(hooks_config, thread_id);
|
||||
for warning in hooks.startup_warnings() {
|
||||
post_session_configured_events.push(Event {
|
||||
id: INITIAL_SUBMIT_ID.to_owned(),
|
||||
@@ -1320,6 +1323,7 @@ impl Session {
|
||||
mcp_prewarm_task: std::sync::Mutex::new(None),
|
||||
conversation: Arc::new(RealtimeConversationManager::new()),
|
||||
active_turn: Mutex::new(None),
|
||||
async_hook_results,
|
||||
pending_user_message_admissions: Default::default(),
|
||||
input_queue: InputQueue::new(),
|
||||
guardian_review_session: GuardianReviewSessionManager::default(),
|
||||
|
||||
Reference in new issue
Block a user