Remove find_context_files — identity comes from memory nodes
Deleted the directory-walking CLAUDE.md/POC.md loader. Identity now comes entirely from personality_nodes in the memory graph. Simplified: - assemble_context_message() takes just personality_nodes - Removed config_file_count/memory_file_count tracking - reload_for_model() → reload_context() (no longer model-specific) Co-Authored-By: Kent Overstreet <kent.overstreet@linux.dev> Signed-off-by: Kent Overstreet <kent.overstreet@linux.dev>
This commit is contained in:
parent
e847a313b4
commit
fc978e2f2e
14 changed files with 779 additions and 107 deletions
|
|
@ -579,7 +579,7 @@ impl Agent {
|
|||
}
|
||||
|
||||
pub async fn compact(&self) {
|
||||
match crate::config::reload_for_model(&self.app_config, &self.prompt_file).await {
|
||||
match crate::config::reload_context().await {
|
||||
Ok(personality) => {
|
||||
let mut ctx = self.context.lock().await;
|
||||
// System section (prompt + tools) set by new(), don't touch it
|
||||
|
|
|
|||
|
|
@ -260,9 +260,8 @@ impl AutoAgent {
|
|||
let cli = crate::user::CliArgs::default();
|
||||
let (app, _) = crate::config::load_app(&cli)
|
||||
.map_err(|e| format!("config: {}", e))?;
|
||||
let personality = crate::config::reload_for_model(
|
||||
&app, &app.prompts.other,
|
||||
).await.map_err(|e| format!("config: {}", e))?;
|
||||
let personality = crate::config::reload_context()
|
||||
.await.map_err(|e| format!("config: {}", e))?;
|
||||
|
||||
let agent = Agent::new(
|
||||
client, personality,
|
||||
|
|
|
|||
|
|
@ -383,10 +383,8 @@ pub struct SessionConfig {
|
|||
pub api_key: String,
|
||||
pub model: String,
|
||||
pub prompt_file: String,
|
||||
/// Identity/personality files as (name, content) pairs.
|
||||
/// Identity/personality nodes as (name, content) pairs.
|
||||
pub context_parts: Vec<(String, String)>,
|
||||
pub config_file_count: usize,
|
||||
pub memory_file_count: usize,
|
||||
pub session_dir: PathBuf,
|
||||
pub app: AppConfig,
|
||||
/// Disable background agents (surface, observe, scoring)
|
||||
|
|
@ -407,8 +405,6 @@ pub struct ResolvedModel {
|
|||
impl AppConfig {
|
||||
/// Resolve the active backend and assemble prompts into a SessionConfig.
|
||||
pub async fn resolve(&self, cli: &crate::user::CliArgs) -> Result<SessionConfig> {
|
||||
let cwd = std::env::current_dir().context("Failed to get current directory")?;
|
||||
|
||||
let (api_base, api_key, model, prompt_file);
|
||||
|
||||
if !self.models.is_empty() {
|
||||
|
|
@ -434,9 +430,7 @@ impl AppConfig {
|
|||
}
|
||||
|
||||
let personality_nodes = get().personality_nodes.clone();
|
||||
|
||||
let (context_parts, config_file_count, memory_file_count) =
|
||||
crate::mind::identity::assemble_context_message(&cwd, &prompt_file, self.memory_project.as_deref(), &personality_nodes).await?;
|
||||
let context_parts = crate::mind::identity::personality_nodes(&personality_nodes).await;
|
||||
|
||||
let session_dir = dirs::home_dir()
|
||||
.unwrap_or_else(|| PathBuf::from("."))
|
||||
|
|
@ -450,7 +444,6 @@ impl AppConfig {
|
|||
Ok(SessionConfig {
|
||||
api_base, api_key, model, prompt_file,
|
||||
context_parts,
|
||||
config_file_count, memory_file_count,
|
||||
session_dir,
|
||||
app: self.clone(),
|
||||
no_agents: cli.no_agents,
|
||||
|
|
@ -574,11 +567,10 @@ pub async fn load_session(cli: &crate::user::CliArgs) -> Result<(SessionConfig,
|
|||
Ok((config, figment))
|
||||
}
|
||||
|
||||
/// Re-assemble context for a specific model's prompt file.
|
||||
pub async fn reload_for_model(app: &AppConfig, prompt_file: &str) -> Result<Vec<(String, String)>> {
|
||||
let cwd = std::env::current_dir().context("Failed to get current directory")?;
|
||||
/// Re-assemble context (reload personality nodes).
|
||||
pub async fn reload_context() -> Result<Vec<(String, String)>> {
|
||||
let personality_nodes = get().personality_nodes.clone();
|
||||
let (context_parts, _, _) = crate::mind::identity::assemble_context_message(&cwd, prompt_file, app.memory_project.as_deref(), &personality_nodes).await?;
|
||||
let context_parts = crate::mind::identity::personality_nodes(&personality_nodes).await;
|
||||
Ok(context_parts)
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,60 +1,11 @@
|
|||
// identity.rs — Identity file discovery and context assembly
|
||||
// identity.rs — Identity context assembly
|
||||
//
|
||||
// Discovers and loads the agent's identity: instruction files (CLAUDE.md,
|
||||
// POC.md), memory nodes, and the system prompt.
|
||||
|
||||
use anyhow::Result;
|
||||
use std::path::{Path, PathBuf};
|
||||
// Loads the agent's identity from memory nodes.
|
||||
|
||||
use crate::agent::tools::memory::memory_render;
|
||||
|
||||
/// Walk from cwd to git root collecting instruction files (CLAUDE.md / POC.md).
|
||||
///
|
||||
/// On Anthropic models, loads CLAUDE.md. On other models, prefers POC.md
|
||||
/// (omits Claude-specific RLHF corrections). If only one exists, it's
|
||||
/// always loaded regardless of model.
|
||||
fn find_context_files(cwd: &Path, prompt_file: &str) -> Vec<PathBuf> {
|
||||
let prefer_poc = prompt_file == "POC.md";
|
||||
|
||||
let mut found = Vec::new();
|
||||
let mut dir = Some(cwd);
|
||||
while let Some(d) = dir {
|
||||
for name in ["POC.md", "CLAUDE.md", ".claude/CLAUDE.md"] {
|
||||
let path = d.join(name);
|
||||
if path.exists() {
|
||||
found.push(path);
|
||||
}
|
||||
}
|
||||
if d.join(".git").exists() { break; }
|
||||
dir = d.parent();
|
||||
}
|
||||
|
||||
if let Some(home) = dirs::home_dir() {
|
||||
let global = home.join(".claude/CLAUDE.md");
|
||||
if global.exists() && !found.contains(&global) {
|
||||
found.push(global);
|
||||
}
|
||||
}
|
||||
|
||||
// Filter: when preferring POC.md, skip bare CLAUDE.md (keep .claude/CLAUDE.md).
|
||||
// When preferring CLAUDE.md, skip POC.md entirely.
|
||||
let has_poc = found.iter().any(|p| p.file_name().map_or(false, |n| n == "POC.md"));
|
||||
if !prefer_poc {
|
||||
found.retain(|p| p.file_name().map_or(true, |n| n != "POC.md"));
|
||||
} else if has_poc {
|
||||
found.retain(|p| match p.file_name().and_then(|n| n.to_str()) {
|
||||
Some("CLAUDE.md") => p.parent().and_then(|par| par.file_name())
|
||||
.map_or(true, |n| n == ".claude"),
|
||||
_ => true,
|
||||
});
|
||||
}
|
||||
|
||||
found.reverse(); // global first, project-specific overrides
|
||||
found
|
||||
}
|
||||
|
||||
/// Load memory nodes from the store.
|
||||
async fn load_memory_nodes(keys: &[String]) -> Vec<(String, String)> {
|
||||
pub async fn personality_nodes(keys: &[String]) -> Vec<(String, String)> {
|
||||
let mut memories: Vec<(String, String)> = Vec::new();
|
||||
|
||||
for key in keys {
|
||||
|
|
@ -67,41 +18,3 @@ async fn load_memory_nodes(keys: &[String]) -> Vec<(String, String)> {
|
|||
|
||||
memories
|
||||
}
|
||||
|
||||
/// Context message: instruction files + memory nodes.
|
||||
pub async fn assemble_context_message(cwd: &Path, prompt_file: &str, _memory_project: Option<&Path>, personality_nodes: &[String]) -> Result<(Vec<(String, String)>, usize, usize)> {
|
||||
let mut parts: Vec<(String, String)> = vec![
|
||||
("Preamble".to_string(),
|
||||
"Everything below is already loaded — your identity, instructions, \
|
||||
memory files, and recent journal entries. Read them here in context, \
|
||||
not with tools.\n\n\
|
||||
IMPORTANT: Skip the \"Session startup\" steps from CLAUDE.md. Do NOT \
|
||||
run poc-journal, poc-memory, or read memory files with tools — \
|
||||
poc-agent has already loaded everything into your context. Just read \
|
||||
what's here.".to_string()),
|
||||
];
|
||||
|
||||
let context_files = find_context_files(cwd, prompt_file);
|
||||
let mut config_count = 0;
|
||||
for path in &context_files {
|
||||
if let Ok(content) = std::fs::read_to_string(path) {
|
||||
parts.push((path.display().to_string(), content));
|
||||
config_count += 1;
|
||||
}
|
||||
}
|
||||
|
||||
let memories = load_memory_nodes(personality_nodes).await;
|
||||
let memory_count = memories.len();
|
||||
for (name, content) in memories {
|
||||
parts.push((name, content));
|
||||
}
|
||||
|
||||
if config_count == 0 && memory_count == 0 {
|
||||
parts.push(("Fallback".to_string(),
|
||||
"No identity files found. You are a helpful AI assistant with access to \
|
||||
tools for reading files, writing files, running bash commands, and \
|
||||
searching code.".to_string()));
|
||||
}
|
||||
|
||||
Ok((parts, config_count, memory_count))
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue