feat: memories config (#11731)
This commit is contained in:
parent
36541876f4
commit
e00080cea3
9 changed files with 253 additions and 44 deletions
|
|
@ -434,6 +434,43 @@
|
|||
}
|
||||
]
|
||||
},
|
||||
"MemoriesToml": {
|
||||
"additionalProperties": false,
|
||||
"description": "Memories settings loaded from config.toml.",
|
||||
"properties": {
|
||||
"max_raw_memories_for_global": {
|
||||
"description": "Maximum number of recent raw memories retained for global consolidation.",
|
||||
"format": "uint",
|
||||
"minimum": 0.0,
|
||||
"type": "integer"
|
||||
},
|
||||
"max_rollout_age_days": {
|
||||
"description": "Maximum age of the threads used for memories.",
|
||||
"format": "int64",
|
||||
"type": "integer"
|
||||
},
|
||||
"max_rollouts_per_startup": {
|
||||
"description": "Maximum number of rollout candidates processed per pass.",
|
||||
"format": "uint",
|
||||
"minimum": 0.0,
|
||||
"type": "integer"
|
||||
},
|
||||
"min_rollout_idle_hours": {
|
||||
"description": "Minimum idle time between last thread activity and memory creation (hours). > 12h recommended.",
|
||||
"format": "int64",
|
||||
"type": "integer"
|
||||
},
|
||||
"phase_1_model": {
|
||||
"description": "Model used for thread summarisation.",
|
||||
"type": "string"
|
||||
},
|
||||
"phase_2_model": {
|
||||
"description": "Model used for memory consolidation.",
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"type": "object"
|
||||
},
|
||||
"ModeKind": {
|
||||
"description": "Initial collaboration mode to use when the TUI starts.",
|
||||
"enum": [
|
||||
|
|
@ -1481,6 +1518,14 @@
|
|||
"description": "Definition for MCP servers that Codex can reach out to for tool calls.",
|
||||
"type": "object"
|
||||
},
|
||||
"memories": {
|
||||
"allOf": [
|
||||
{
|
||||
"$ref": "#/definitions/MemoriesToml"
|
||||
}
|
||||
],
|
||||
"description": "Memories subsystem settings."
|
||||
},
|
||||
"model": {
|
||||
"description": "Optional override of model selection.",
|
||||
"type": "string"
|
||||
|
|
|
|||
|
|
@ -7,6 +7,8 @@ use crate::config::types::History;
|
|||
use crate::config::types::McpServerConfig;
|
||||
use crate::config::types::McpServerDisabledReason;
|
||||
use crate::config::types::McpServerTransportConfig;
|
||||
use crate::config::types::MemoriesConfig;
|
||||
use crate::config::types::MemoriesToml;
|
||||
use crate::config::types::Notice;
|
||||
use crate::config::types::NotificationMethod;
|
||||
use crate::config::types::Notifications;
|
||||
|
|
@ -289,6 +291,9 @@ pub struct Config {
|
|||
/// Maximum number of agent threads that can be open concurrently.
|
||||
pub agent_max_threads: Option<usize>,
|
||||
|
||||
/// Memories subsystem settings.
|
||||
pub memories: MemoriesConfig,
|
||||
|
||||
/// Directory containing all Codex state (defaults to `~/.codex` but can be
|
||||
/// overridden by the `CODEX_HOME` environment variable).
|
||||
pub codex_home: PathBuf,
|
||||
|
|
@ -1006,6 +1011,9 @@ pub struct ConfigToml {
|
|||
/// Agent-related settings (thread limits, etc.).
|
||||
pub agents: Option<AgentsToml>,
|
||||
|
||||
/// Memories subsystem settings.
|
||||
pub memories: Option<MemoriesToml>,
|
||||
|
||||
/// User-level skill config entries keyed by SKILL.md path.
|
||||
pub skills: Option<SkillsConfig>,
|
||||
|
||||
|
|
@ -1771,6 +1779,7 @@ impl Config {
|
|||
.collect(),
|
||||
tool_output_token_limit: cfg.tool_output_token_limit,
|
||||
agent_max_threads,
|
||||
memories: cfg.memories.unwrap_or_default().into(),
|
||||
codex_home,
|
||||
log_dir,
|
||||
config_layer_stack,
|
||||
|
|
@ -1985,6 +1994,8 @@ mod tests {
|
|||
use crate::config::types::FeedbackConfigToml;
|
||||
use crate::config::types::HistoryPersistence;
|
||||
use crate::config::types::McpServerTransportConfig;
|
||||
use crate::config::types::MemoriesConfig;
|
||||
use crate::config::types::MemoriesToml;
|
||||
use crate::config::types::NotificationMethod;
|
||||
use crate::config::types::Notifications;
|
||||
use crate::config_loader::RequirementSource;
|
||||
|
|
@ -2068,6 +2079,47 @@ persistence = "none"
|
|||
}),
|
||||
history_no_persistence_cfg.history
|
||||
);
|
||||
|
||||
let memories = r#"
|
||||
[memories]
|
||||
max_raw_memories_for_global = 512
|
||||
max_rollout_age_days = 42
|
||||
max_rollouts_per_startup = 9
|
||||
min_rollout_idle_hours = 24
|
||||
phase_1_model = "gpt-5-mini"
|
||||
phase_2_model = "gpt-5"
|
||||
"#;
|
||||
let memories_cfg =
|
||||
toml::from_str::<ConfigToml>(memories).expect("TOML deserialization should succeed");
|
||||
assert_eq!(
|
||||
Some(MemoriesToml {
|
||||
max_raw_memories_for_global: Some(512),
|
||||
max_rollout_age_days: Some(42),
|
||||
max_rollouts_per_startup: Some(9),
|
||||
min_rollout_idle_hours: Some(24),
|
||||
phase_1_model: Some("gpt-5-mini".to_string()),
|
||||
phase_2_model: Some("gpt-5".to_string()),
|
||||
}),
|
||||
memories_cfg.memories
|
||||
);
|
||||
|
||||
let config = Config::load_from_base_config_with_overrides(
|
||||
memories_cfg,
|
||||
ConfigOverrides::default(),
|
||||
tempdir().expect("tempdir").path().to_path_buf(),
|
||||
)
|
||||
.expect("load config from memories settings");
|
||||
assert_eq!(
|
||||
config.memories,
|
||||
MemoriesConfig {
|
||||
max_raw_memories_for_global: 512,
|
||||
max_rollout_age_days: 42,
|
||||
max_rollouts_per_startup: 9,
|
||||
min_rollout_idle_hours: 24,
|
||||
phase_1_model: Some("gpt-5-mini".to_string()),
|
||||
phase_2_model: Some("gpt-5".to_string()),
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
|
@ -4047,6 +4099,7 @@ model_verbosity = "high"
|
|||
project_doc_fallback_filenames: Vec::new(),
|
||||
tool_output_token_limit: None,
|
||||
agent_max_threads: DEFAULT_AGENT_MAX_THREADS,
|
||||
memories: MemoriesConfig::default(),
|
||||
codex_home: fixture.codex_home(),
|
||||
log_dir: fixture.codex_home().join("log"),
|
||||
config_layer_stack: Default::default(),
|
||||
|
|
@ -4156,6 +4209,7 @@ model_verbosity = "high"
|
|||
project_doc_fallback_filenames: Vec::new(),
|
||||
tool_output_token_limit: None,
|
||||
agent_max_threads: DEFAULT_AGENT_MAX_THREADS,
|
||||
memories: MemoriesConfig::default(),
|
||||
codex_home: fixture.codex_home(),
|
||||
log_dir: fixture.codex_home().join("log"),
|
||||
config_layer_stack: Default::default(),
|
||||
|
|
@ -4263,6 +4317,7 @@ model_verbosity = "high"
|
|||
project_doc_fallback_filenames: Vec::new(),
|
||||
tool_output_token_limit: None,
|
||||
agent_max_threads: DEFAULT_AGENT_MAX_THREADS,
|
||||
memories: MemoriesConfig::default(),
|
||||
codex_home: fixture.codex_home(),
|
||||
log_dir: fixture.codex_home().join("log"),
|
||||
config_layer_stack: Default::default(),
|
||||
|
|
@ -4356,6 +4411,7 @@ model_verbosity = "high"
|
|||
project_doc_fallback_filenames: Vec::new(),
|
||||
tool_output_token_limit: None,
|
||||
agent_max_threads: DEFAULT_AGENT_MAX_THREADS,
|
||||
memories: MemoriesConfig::default(),
|
||||
codex_home: fixture.codex_home(),
|
||||
log_dir: fixture.codex_home().join("log"),
|
||||
config_layer_stack: Default::default(),
|
||||
|
|
|
|||
|
|
@ -23,6 +23,10 @@ use serde::Serialize;
|
|||
use serde::de::Error as SerdeError;
|
||||
|
||||
pub const DEFAULT_OTEL_ENVIRONMENT: &str = "dev";
|
||||
pub const DEFAULT_MEMORIES_MAX_ROLLOUTS_PER_STARTUP: usize = 8;
|
||||
pub const DEFAULT_MEMORIES_MAX_ROLLOUT_AGE_DAYS: i64 = 30;
|
||||
pub const DEFAULT_MEMORIES_MIN_ROLLOUT_IDLE_HOURS: i64 = 12;
|
||||
pub const DEFAULT_MEMORIES_MAX_RAW_MEMORIES_FOR_GLOBAL: usize = 1_024;
|
||||
|
||||
#[derive(Serialize, Deserialize, Debug, Clone, Copy, PartialEq, Eq, JsonSchema)]
|
||||
#[serde(rename_all = "kebab-case")]
|
||||
|
|
@ -353,6 +357,74 @@ pub struct FeedbackConfigToml {
|
|||
pub enabled: Option<bool>,
|
||||
}
|
||||
|
||||
/// Memories settings loaded from config.toml.
|
||||
#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Default, JsonSchema)]
|
||||
#[schemars(deny_unknown_fields)]
|
||||
pub struct MemoriesToml {
|
||||
/// Maximum number of recent raw memories retained for global consolidation.
|
||||
pub max_raw_memories_for_global: Option<usize>,
|
||||
/// Maximum age of the threads used for memories.
|
||||
pub max_rollout_age_days: Option<i64>,
|
||||
/// Maximum number of rollout candidates processed per pass.
|
||||
pub max_rollouts_per_startup: Option<usize>,
|
||||
/// Minimum idle time between last thread activity and memory creation (hours). > 12h recommended.
|
||||
pub min_rollout_idle_hours: Option<i64>,
|
||||
/// Model used for thread summarisation.
|
||||
pub phase_1_model: Option<String>,
|
||||
/// Model used for memory consolidation.
|
||||
pub phase_2_model: Option<String>,
|
||||
}
|
||||
|
||||
/// Effective memories settings after defaults are applied.
|
||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||
pub struct MemoriesConfig {
|
||||
pub max_raw_memories_for_global: usize,
|
||||
pub max_rollout_age_days: i64,
|
||||
pub max_rollouts_per_startup: usize,
|
||||
pub min_rollout_idle_hours: i64,
|
||||
pub phase_1_model: Option<String>,
|
||||
pub phase_2_model: Option<String>,
|
||||
}
|
||||
|
||||
impl Default for MemoriesConfig {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
max_raw_memories_for_global: DEFAULT_MEMORIES_MAX_RAW_MEMORIES_FOR_GLOBAL,
|
||||
max_rollout_age_days: DEFAULT_MEMORIES_MAX_ROLLOUT_AGE_DAYS,
|
||||
max_rollouts_per_startup: DEFAULT_MEMORIES_MAX_ROLLOUTS_PER_STARTUP,
|
||||
min_rollout_idle_hours: DEFAULT_MEMORIES_MIN_ROLLOUT_IDLE_HOURS,
|
||||
phase_1_model: None,
|
||||
phase_2_model: None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<MemoriesToml> for MemoriesConfig {
|
||||
fn from(toml: MemoriesToml) -> Self {
|
||||
let defaults = Self::default();
|
||||
Self {
|
||||
max_raw_memories_for_global: toml
|
||||
.max_raw_memories_for_global
|
||||
.unwrap_or(defaults.max_raw_memories_for_global)
|
||||
.min(4096),
|
||||
max_rollout_age_days: toml
|
||||
.max_rollout_age_days
|
||||
.unwrap_or(defaults.max_rollout_age_days)
|
||||
.clamp(0, 90),
|
||||
max_rollouts_per_startup: toml
|
||||
.max_rollouts_per_startup
|
||||
.unwrap_or(defaults.max_rollouts_per_startup)
|
||||
.min(128),
|
||||
min_rollout_idle_hours: toml
|
||||
.min_rollout_idle_hours
|
||||
.unwrap_or(defaults.min_rollout_idle_hours)
|
||||
.clamp(1, 48),
|
||||
phase_1_model: toml.phase_1_model,
|
||||
phase_2_model: toml.phase_2_model,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, JsonSchema)]
|
||||
#[serde(rename_all = "snake_case")]
|
||||
pub enum AppDisabledReason {
|
||||
|
|
|
|||
|
|
@ -25,10 +25,10 @@ mod artifacts {
|
|||
|
||||
/// Phase 1 (startup extraction).
|
||||
mod phase_one {
|
||||
/// Default model used for phase 1.
|
||||
pub(super) const MODEL: &str = "gpt-5.3-codex-spark";
|
||||
/// Prompt used for phase 1.
|
||||
pub(super) const PROMPT: &str = include_str!("../../templates/memories/stage_one_system.md");
|
||||
/// Maximum number of rollout candidates processed per startup pass.
|
||||
pub(super) const MAX_ROLLOUTS_PER_STARTUP: usize = 8;
|
||||
/// Concurrency cap for startup memory extraction and consolidation scheduling.
|
||||
pub(super) const CONCURRENCY_LIMIT: usize = 8;
|
||||
/// Fallback stage-1 rollout truncation limit (tokens) when model metadata
|
||||
|
|
@ -43,10 +43,6 @@ mod phase_one {
|
|||
/// Keeping this below 100% leaves room for system instructions, prompt
|
||||
/// framing, and model output.
|
||||
pub(super) const CONTEXT_WINDOW_PERCENT: i64 = 70;
|
||||
/// Maximum rollout age considered for phase-1 extraction.
|
||||
pub(super) const MAX_ROLLOUT_AGE_DAYS: i64 = 30;
|
||||
/// Minimum rollout idle time required before phase-1 extraction.
|
||||
pub(super) const MIN_ROLLOUT_IDLE_HOURS: i64 = 12;
|
||||
/// Lease duration (seconds) for phase-1 job ownership.
|
||||
pub(super) const JOB_LEASE_SECONDS: i64 = 3_600;
|
||||
/// Backoff delay (seconds) before retrying a failed stage-1 extraction job.
|
||||
|
|
@ -57,8 +53,8 @@ mod phase_one {
|
|||
|
||||
/// Phase 2 (aka `Consolidation`).
|
||||
mod phase_two {
|
||||
/// Maximum number of recent raw memories retained for global consolidation.
|
||||
pub(super) const MAX_RAW_MEMORIES_FOR_GLOBAL: usize = 1_024;
|
||||
/// Default model used for phase 2.
|
||||
pub(super) const MODEL: &str = "gpt-5.3-codex";
|
||||
/// Lease duration (seconds) for phase-2 consolidation job ownership.
|
||||
pub(super) const JOB_LEASE_SECONDS: i64 = 3_600;
|
||||
/// Backoff delay (seconds) before retrying a failed phase-2 consolidation
|
||||
|
|
|
|||
|
|
@ -2,6 +2,8 @@ use crate::Prompt;
|
|||
use crate::RolloutRecorder;
|
||||
use crate::codex::Session;
|
||||
use crate::codex::TurnContext;
|
||||
use crate::config::Config;
|
||||
use crate::config::types::MemoriesConfig;
|
||||
use crate::error::CodexErr;
|
||||
use crate::memories::metrics;
|
||||
use crate::memories::phase_one;
|
||||
|
|
@ -78,9 +80,9 @@ struct StageOneOutput {
|
|||
/// 2) build one stage-1 request context
|
||||
/// 3) run stage-1 extraction jobs in parallel
|
||||
/// 4) emit metrics and logs
|
||||
pub(in crate::memories) async fn run(session: &Arc<Session>) {
|
||||
pub(in crate::memories) async fn run(session: &Arc<Session>, config: &Config) {
|
||||
// 1. Claim startup job.
|
||||
let Some(claimed_candidates) = claim_startup_jobs(session).await else {
|
||||
let Some(claimed_candidates) = claim_startup_jobs(session, &config.memories).await else {
|
||||
return;
|
||||
};
|
||||
if claimed_candidates.is_empty() {
|
||||
|
|
@ -93,7 +95,7 @@ pub(in crate::memories) async fn run(session: &Arc<Session>) {
|
|||
}
|
||||
|
||||
// 2. Build request.
|
||||
let stage_one_context = build_request_context(session).await;
|
||||
let stage_one_context = build_request_context(session, config).await;
|
||||
|
||||
// 3. Run the parallel sampling.
|
||||
let outcomes = run_jobs(session, claimed_candidates, stage_one_context).await;
|
||||
|
|
@ -129,18 +131,22 @@ impl RequestContext {
|
|||
pub(in crate::memories) fn from_turn_context(
|
||||
turn_context: &TurnContext,
|
||||
turn_metadata_header: Option<String>,
|
||||
model_info: ModelInfo,
|
||||
) -> Self {
|
||||
Self {
|
||||
model_info: turn_context.model_info.clone(),
|
||||
model_info,
|
||||
turn_metadata_header,
|
||||
otel_manager: turn_context.otel_manager.clone(),
|
||||
reasoning_effort: turn_context.reasoning_effort,
|
||||
reasoning_summary: turn_context.reasoning_summary,
|
||||
turn_metadata_header,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
async fn claim_startup_jobs(session: &Arc<Session>) -> Option<Vec<codex_state::Stage1JobClaim>> {
|
||||
async fn claim_startup_jobs(
|
||||
session: &Arc<Session>,
|
||||
memories_config: &MemoriesConfig,
|
||||
) -> Option<Vec<codex_state::Stage1JobClaim>> {
|
||||
let Some(state_db) = session.services.state_db.as_deref() else {
|
||||
// This should not happen.
|
||||
warn!("state db unavailable while claiming phase-1 startup jobs; skipping");
|
||||
|
|
@ -157,9 +163,9 @@ async fn claim_startup_jobs(session: &Arc<Session>) -> Option<Vec<codex_state::S
|
|||
session.conversation_id,
|
||||
codex_state::Stage1StartupClaimParams {
|
||||
scan_limit: phase_one::THREAD_SCAN_LIMIT,
|
||||
max_claimed: phase_one::MAX_ROLLOUTS_PER_STARTUP,
|
||||
max_age_days: phase_one::MAX_ROLLOUT_AGE_DAYS,
|
||||
min_rollout_idle_hours: phase_one::MIN_ROLLOUT_IDLE_HOURS,
|
||||
max_claimed: memories_config.max_rollouts_per_startup,
|
||||
max_age_days: memories_config.max_rollout_age_days,
|
||||
min_rollout_idle_hours: memories_config.min_rollout_idle_hours,
|
||||
allowed_sources: allowed_sources.as_slice(),
|
||||
lease_seconds: phase_one::JOB_LEASE_SECONDS,
|
||||
},
|
||||
|
|
@ -179,11 +185,22 @@ async fn claim_startup_jobs(session: &Arc<Session>) -> Option<Vec<codex_state::S
|
|||
}
|
||||
}
|
||||
|
||||
async fn build_request_context(session: &Arc<Session>) -> RequestContext {
|
||||
async fn build_request_context(session: &Arc<Session>, config: &Config) -> RequestContext {
|
||||
let model_name = config
|
||||
.memories
|
||||
.phase_1_model
|
||||
.clone()
|
||||
.unwrap_or(phase_one::MODEL.to_string());
|
||||
let model = session
|
||||
.services
|
||||
.models_manager
|
||||
.get_model_info(&model_name, config)
|
||||
.await;
|
||||
let turn_context = session.new_default_turn().await;
|
||||
RequestContext::from_turn_context(
|
||||
turn_context.as_ref(),
|
||||
turn_context.resolve_turn_metadata_header().await,
|
||||
model,
|
||||
)
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -41,6 +41,7 @@ pub(super) async fn run(session: &Arc<Session>, config: Arc<Config>) {
|
|||
return;
|
||||
};
|
||||
let root = memory_root(&config.codex_home);
|
||||
let max_raw_memories = config.memories.max_raw_memories_for_global;
|
||||
|
||||
// 1. Claim the job.
|
||||
let claim = match job::claim(session, db).await {
|
||||
|
|
@ -64,10 +65,7 @@ pub(super) async fn run(session: &Arc<Session>, config: Arc<Config>) {
|
|||
};
|
||||
|
||||
// 3. Query the memories
|
||||
let raw_memories = match db
|
||||
.list_stage1_outputs_for_global(phase_two::MAX_RAW_MEMORIES_FOR_GLOBAL)
|
||||
.await
|
||||
{
|
||||
let raw_memories = match db.list_stage1_outputs_for_global(max_raw_memories).await {
|
||||
Ok(memories) => memories,
|
||||
Err(err) => {
|
||||
tracing::error!("failed to list stage1 outputs from global: {}", err);
|
||||
|
|
@ -80,13 +78,17 @@ pub(super) async fn run(session: &Arc<Session>, config: Arc<Config>) {
|
|||
// 4. Update the file system by syncing the raw memories with the one extracted from DB at
|
||||
// step 3
|
||||
// [`rollout_summaries/`]
|
||||
if let Err(err) = sync_rollout_summaries_from_memories(&root, &raw_memories).await {
|
||||
if let Err(err) =
|
||||
sync_rollout_summaries_from_memories(&root, &raw_memories, max_raw_memories).await
|
||||
{
|
||||
tracing::error!("failed syncing local memory artifacts for global consolidation: {err}");
|
||||
job::failed(session, db, &claim, "failed_sync_artifacts").await;
|
||||
return;
|
||||
}
|
||||
// [`raw_memories.md`]
|
||||
if let Err(err) = rebuild_raw_memories_file_from_memories(&root, &raw_memories).await {
|
||||
if let Err(err) =
|
||||
rebuild_raw_memories_file_from_memories(&root, &raw_memories, max_raw_memories).await
|
||||
{
|
||||
tracing::error!("failed syncing local memory artifacts for global consolidation: {err}");
|
||||
job::failed(session, db, &claim, "failed_rebuild_raw_memories").await;
|
||||
return;
|
||||
|
|
@ -207,20 +209,19 @@ mod agent {
|
|||
|
||||
pub(super) fn get_config(config: Arc<Config>) -> Option<Config> {
|
||||
let root = memory_root(&config.codex_home);
|
||||
let mut consolidation_config = config.as_ref().clone();
|
||||
let mut agent_config = config.as_ref().clone();
|
||||
|
||||
consolidation_config.cwd = root;
|
||||
agent_config.cwd = root;
|
||||
// Approval policy
|
||||
consolidation_config.permissions.approval_policy =
|
||||
Constrained::allow_only(AskForApproval::Never);
|
||||
agent_config.permissions.approval_policy = Constrained::allow_only(AskForApproval::Never);
|
||||
|
||||
// Sandbox policy
|
||||
let mut writable_roots = Vec::new();
|
||||
match AbsolutePathBuf::from_absolute_path(consolidation_config.codex_home.clone()) {
|
||||
match AbsolutePathBuf::from_absolute_path(agent_config.codex_home.clone()) {
|
||||
Ok(codex_home) => writable_roots.push(codex_home),
|
||||
Err(err) => warn!(
|
||||
"memory phase-2 consolidation could not add codex_home writable root {}: {err}",
|
||||
consolidation_config.codex_home.display()
|
||||
agent_config.codex_home.display()
|
||||
),
|
||||
}
|
||||
// The consolidation agent only needs local codex_home write access and no network.
|
||||
|
|
@ -231,13 +232,21 @@ mod agent {
|
|||
exclude_tmpdir_env_var: false,
|
||||
exclude_slash_tmp: false,
|
||||
};
|
||||
consolidation_config
|
||||
agent_config
|
||||
.permissions
|
||||
.sandbox_policy
|
||||
.set(consolidation_sandbox_policy)
|
||||
.ok()?;
|
||||
|
||||
Some(consolidation_config)
|
||||
agent_config.model = Some(
|
||||
config
|
||||
.memories
|
||||
.phase_2_model
|
||||
.clone()
|
||||
.unwrap_or(phase_two::MODEL.to_string()),
|
||||
);
|
||||
|
||||
Some(agent_config)
|
||||
}
|
||||
|
||||
pub(super) fn get_prompt(config: Arc<Config>) -> Vec<UserInput> {
|
||||
|
|
|
|||
|
|
@ -35,7 +35,7 @@ pub(crate) fn start_memories_startup_task(
|
|||
};
|
||||
|
||||
// Run phase 1.
|
||||
phase1::run(&session).await;
|
||||
phase1::run(&session, &config).await;
|
||||
// Run phase 2.
|
||||
phase2::run(&session, config).await;
|
||||
});
|
||||
|
|
|
|||
|
|
@ -5,7 +5,6 @@ use std::path::Path;
|
|||
use tracing::warn;
|
||||
|
||||
use crate::memories::ensure_layout;
|
||||
use crate::memories::phase_two;
|
||||
use crate::memories::raw_memories_file;
|
||||
use crate::memories::rollout_summaries_dir;
|
||||
|
||||
|
|
@ -15,21 +14,23 @@ use crate::memories::rollout_summaries_dir;
|
|||
pub(super) async fn rebuild_raw_memories_file_from_memories(
|
||||
root: &Path,
|
||||
memories: &[Stage1Output],
|
||||
max_raw_memories_for_global: usize,
|
||||
) -> std::io::Result<()> {
|
||||
ensure_layout(root).await?;
|
||||
rebuild_raw_memories_file(root, memories).await
|
||||
rebuild_raw_memories_file(root, memories, max_raw_memories_for_global).await
|
||||
}
|
||||
|
||||
/// Syncs canonical rollout summary files from DB-backed stage-1 output rows.
|
||||
pub(super) async fn sync_rollout_summaries_from_memories(
|
||||
root: &Path,
|
||||
memories: &[Stage1Output],
|
||||
max_raw_memories_for_global: usize,
|
||||
) -> std::io::Result<()> {
|
||||
ensure_layout(root).await?;
|
||||
|
||||
let retained = memories
|
||||
.iter()
|
||||
.take(phase_two::MAX_RAW_MEMORIES_FOR_GLOBAL)
|
||||
.take(max_raw_memories_for_global)
|
||||
.collect::<Vec<_>>();
|
||||
let keep = retained
|
||||
.iter()
|
||||
|
|
@ -62,10 +63,14 @@ pub(super) async fn sync_rollout_summaries_from_memories(
|
|||
Ok(())
|
||||
}
|
||||
|
||||
async fn rebuild_raw_memories_file(root: &Path, memories: &[Stage1Output]) -> std::io::Result<()> {
|
||||
async fn rebuild_raw_memories_file(
|
||||
root: &Path,
|
||||
memories: &[Stage1Output],
|
||||
max_raw_memories_for_global: usize,
|
||||
) -> std::io::Result<()> {
|
||||
let retained = memories
|
||||
.iter()
|
||||
.take(phase_two::MAX_RAW_MEMORIES_FOR_GLOBAL)
|
||||
.take(max_raw_memories_for_global)
|
||||
.collect::<Vec<_>>();
|
||||
let mut body = String::from("# Raw Memories\n\n");
|
||||
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
use super::storage::rebuild_raw_memories_file_from_memories;
|
||||
use super::storage::sync_rollout_summaries_from_memories;
|
||||
use crate::config::types::DEFAULT_MEMORIES_MAX_RAW_MEMORIES_FOR_GLOBAL;
|
||||
use crate::memories::ensure_layout;
|
||||
use crate::memories::memory_root;
|
||||
use crate::memories::raw_memories_file;
|
||||
|
|
@ -70,12 +71,20 @@ async fn sync_rollout_summaries_and_raw_memories_file_keeps_latest_memories_only
|
|||
generated_at: Utc.timestamp_opt(101, 0).single().expect("timestamp"),
|
||||
}];
|
||||
|
||||
sync_rollout_summaries_from_memories(&root, &memories)
|
||||
.await
|
||||
.expect("sync rollout summaries");
|
||||
rebuild_raw_memories_file_from_memories(&root, &memories)
|
||||
.await
|
||||
.expect("rebuild raw memories");
|
||||
sync_rollout_summaries_from_memories(
|
||||
&root,
|
||||
&memories,
|
||||
DEFAULT_MEMORIES_MAX_RAW_MEMORIES_FOR_GLOBAL,
|
||||
)
|
||||
.await
|
||||
.expect("sync rollout summaries");
|
||||
rebuild_raw_memories_file_from_memories(
|
||||
&root,
|
||||
&memories,
|
||||
DEFAULT_MEMORIES_MAX_RAW_MEMORIES_FOR_GLOBAL,
|
||||
)
|
||||
.await
|
||||
.expect("rebuild raw memories");
|
||||
|
||||
assert!(keep_path.is_file());
|
||||
assert!(!drop_path.exists());
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue