Codex Handbook
memories/write/src/start.rs 79 lines
use crate::extensions::seed_extension_instructions;use crate::guard;use crate::memory_root;use crate::metrics::MEMORY_STARTUP;use crate::phase1;use crate::phase2;use crate::runtime::MemoryStartupContext;use codex_core::CodexThread;use codex_core::ThreadManager;use codex_core::config::Config;use codex_features::Feature;use codex_login::AuthManager;use codex_protocol::ThreadId;use codex_protocol::protocol::SessionSource;use std::sync::Arc;use tracing::warn;/// Starts the asynchronous startup memory pipeline for an eligible root session.////// The pipeline is skipped for ephemeral sessions, disabled feature flags, and/// subagent sessions.pub fn start_memories_startup_task(    thread_manager: Arc<ThreadManager>,    auth_manager: Arc<AuthManager>,    thread_id: ThreadId,    thread: Arc<CodexThread>,    config: Arc<Config>,    source: &SessionSource,) {    if config.ephemeral        || !config.features.enabled(Feature::MemoryTool)        || source.is_non_root_agent()    {        return;    }    let context = Arc::new(MemoryStartupContext::new(        thread_manager,        Arc::clone(&auth_manager),        thread_id,        thread,        config.as_ref(),        source.clone(),    ));    if context.state_db().is_none() {        warn!("state db unavailable for memories startup pipeline; skipping");        return;    }    tokio::spawn(async move {        let root = memory_root(&config.codex_home);        if let Err(err) = tokio::fs::create_dir_all(&root).await {            warn!("failed creating memories root: {err}");            return;        }        if let Err(err) = seed_extension_instructions(&root).await {            warn!("failed seeding memory extension instructions: {err}");        }        // Clean memories to make preserve DB size. This does not consume tokens so can be        // done before the quota check.        phase1::prune(context.as_ref(), &config).await;        if !guard::rate_limits_ok(&auth_manager, &config).await {            context.counter(                MEMORY_STARTUP,                /*inc*/ 1,                &[("status", "skipped_rate_limit")],            );            return;        }        // Run phase 1.        phase1::run(Arc::clone(&context), Arc::clone(&config)).await;        // Run phase 2.        phase2::run(context, config).await;    });}