mirror of
https://github.com/openai/codex.git
synced 2026-11-06 20:20:34 +00:00
Move agent message board cleanup into the app server (#59167)
## What changed Move permanent agent message board deletion from `codex-core` into the app server's thread-store cleanup callback. Keep board cleanup active when the board feature is disabled, and run it before optional Guardian evidence-board cleanup. Remove the message board extension dependency from `codex-core` and retain `codex-message-board` only as a development dependency. Update the core test harness to install the app server's cleanup callback. GitOrigin-RevId: 61813bbdcd8b57073b8c249e1f771e3fb0ea061e
This commit is contained in:
@@ -3,11 +3,13 @@
|
||||
//! The extension owns backend construction, storage and tool registration. This adapter
|
||||
//! selects configuration and supplies host capabilities. It never starts or restores
|
||||
//! recipients during lookup. Notifications use ordinary agent-message scheduling.
|
||||
//! Permanent board deletion uses the thread store's existing host cleanup callback.
|
||||
|
||||
use chrono::DateTime;
|
||||
use chrono::Utc;
|
||||
use codex_agent_message_board_client::RemoteAgentMessageBoard;
|
||||
use codex_agent_message_board_extension::BoardBackend;
|
||||
use codex_agent_message_board_extension::local_board_options;
|
||||
use codex_core::CodexThread;
|
||||
use codex_core::MULTI_AGENT_V2_NAMESPACE_DESCRIPTION;
|
||||
use codex_core::ThreadManager;
|
||||
@@ -15,6 +17,7 @@ use codex_core::config::Config;
|
||||
use codex_extension_api::ExtensionRegistryBuilder;
|
||||
use codex_extension_api::ThreadStartInput;
|
||||
use codex_features::Feature;
|
||||
use codex_message_board::LocalAgentMessageBoard;
|
||||
use codex_message_board::LocalBoardConnection;
|
||||
use codex_message_board::MessageBoardHost;
|
||||
use codex_message_board::NotificationDelivery;
|
||||
@@ -27,6 +30,9 @@ use codex_protocol::error::CodexErrorDetails;
|
||||
use codex_protocol::error::Result;
|
||||
use codex_protocol::protocol::InterAgentCommunication;
|
||||
use codex_protocol::protocol::Op;
|
||||
use codex_state::SqliteConfig;
|
||||
use codex_thread_store::ThreadStoreError;
|
||||
use codex_thread_store::ThreadStoreResult;
|
||||
use futures::future::BoxFuture;
|
||||
use std::sync::Arc;
|
||||
use std::sync::Weak;
|
||||
@@ -98,6 +104,24 @@ pub fn install_agent_message_board(
|
||||
);
|
||||
}
|
||||
|
||||
/// Removes persisted agent-board data through the thread store's deletion callback.
|
||||
/// Cleanup also applies when the board feature is currently disabled.
|
||||
pub async fn delete_agent_message_boards(
|
||||
sqlite: &SqliteConfig,
|
||||
thread_ids: &[ThreadId],
|
||||
) -> ThreadStoreResult<()> {
|
||||
let boards = thread_ids
|
||||
.iter()
|
||||
.copied()
|
||||
.map(Into::into)
|
||||
.collect::<Vec<_>>();
|
||||
LocalAgentMessageBoard::delete_boards(sqlite, &local_board_options(), &boards)
|
||||
.await
|
||||
.map_err(|err| ThreadStoreError::Internal {
|
||||
message: format!("failed to delete agent message boards: {err}"),
|
||||
})
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
struct LocalBoardHost {
|
||||
manager: Weak<ThreadManager>,
|
||||
|
||||
@@ -96,6 +96,7 @@ fn is_unsupported_untrusted_approval_policy_error(err: &std::io::Error) -> bool
|
||||
}
|
||||
|
||||
mod agent_message_board;
|
||||
pub use agent_message_board::delete_agent_message_boards;
|
||||
pub use agent_message_board::install_agent_message_board;
|
||||
|
||||
mod analytics_utils;
|
||||
|
||||
@@ -319,22 +319,27 @@ impl MessageProcessor {
|
||||
// The thread store is intentionally process-scoped. Config reloads can
|
||||
// affect per-thread behavior, but they must not move newly started,
|
||||
// resumed, or forked threads to a different persistence backend/root.
|
||||
let mut thread_store = ThreadStoreBuilder::from_config(config.as_ref(), state_db.clone());
|
||||
if config.features.enabled(Feature::GuardianV3) {
|
||||
let sqlite = config.sqlite_config().clone();
|
||||
thread_store = thread_store.with_additional_cleanup(move |thread_ids| {
|
||||
let sqlite = config.sqlite_config().clone();
|
||||
let guardian_v3_enabled = config.features.enabled(Feature::GuardianV3);
|
||||
let thread_store = ThreadStoreBuilder::from_config(config.as_ref(), state_db.clone())
|
||||
.with_additional_cleanup(move |thread_ids| {
|
||||
let sqlite = sqlite.clone();
|
||||
Box::pin(async move {
|
||||
let boards = thread_ids.into_iter().map(Into::into).collect::<Vec<_>>();
|
||||
codex_guardian_v3::delete_local_boards(&sqlite, &boards)
|
||||
.await
|
||||
.map_err(|err| ThreadStoreError::Internal {
|
||||
message: format!("failed to delete Guardian evidence boards: {err}"),
|
||||
})
|
||||
crate::delete_agent_message_boards(&sqlite, &thread_ids).await?;
|
||||
if guardian_v3_enabled {
|
||||
let boards = thread_ids.into_iter().map(Into::into).collect::<Vec<_>>();
|
||||
codex_guardian_v3::delete_local_boards(&sqlite, &boards)
|
||||
.await
|
||||
.map_err(|err| ThreadStoreError::Internal {
|
||||
message: format!(
|
||||
"failed to delete Guardian evidence boards: {err}"
|
||||
),
|
||||
})?;
|
||||
}
|
||||
Ok(())
|
||||
})
|
||||
});
|
||||
}
|
||||
let thread_store = thread_store.build();
|
||||
})
|
||||
.build();
|
||||
// Queue persistence requires SQLite, so in-memory thread stores and
|
||||
// app servers without a state database do not have a queue backend.
|
||||
let queue_store: Option<Arc<dyn QueueStore>> = match &config.experimental_thread_store {
|
||||
|
||||
Reference in New Issue
Block a user