mirror of
https://github.com/pchuan98/codex.git
synced 2026-07-01 00:31:56 +08:00
d5ec93f379
## Why Config loading should not create or write-authorize the memories root just because memory support exists. Memory startup is the code path that actually materializes that tree. ## What - Stop creating the memories root during Config load and remove it from legacy workspace-write projections. - Grant the memories root read access only when the memories feature and use_memories are enabled. - Create the memories root inside memories startup before seeding extension instructions. - Update config and startup tests around the ownership boundary. ## Tests - just fmt - just fix -p codex-core - just fix -p codex-memories-write - just test -p codex-core memory_tool_makes_memories_root_readable_without_creating_or_widening_writes workspace_write_includes_configured_writable_root_once_without_memories_root permission_profile_override_keeps_memories_root_out_of_legacy_projection permissions_profiles_allow_direct_write_roots_outside_workspace_root default_permissions_profile_populates_runtime_sandbox_policy - just test -p codex-memories-write memories_startup_creates_memory_root Note: a broader just test -p codex-core run is not clean in this sandbox; it hit missing test_stdio_server plus seatbelt, realtime, and environment-sensitive failures. The changed config tests above pass.
80 lines
2.3 KiB
Rust
80 lines
2.3 KiB
Rust
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;
|
|
});
|
|
}
|