consciousness/src/thought/mod.rs
Kent Overstreet df9b610c7f add memory importance scoring via prompt logprobs
score_memories() drops each memory from the context one at a time,
runs prompt_logprobs against the full conversation, and builds a
divergence matrix: memories × responses.

Row sums = memory importance (for graph weight updates)
Column sums = response memory-dependence (training candidates)

Uses vLLM's prompt_logprobs to check "would the model have said
this without this memory?" — one forward pass per memory, all
responses scored at once. ~3s per memory on B200.

Co-Authored-By: Proof of Concept <poc@bcachefs.org>
2026-04-02 22:13:55 -04:00

130 lines
3.6 KiB
Rust

// thought — shared cognitive infrastructure
//
// The thought layer contains everything both the conscious agent
// (poc-agent) and subconscious agents need to think and act: tool
// dispatch, memory operations, file operations, context management.
//
// Named "thought" because tools are the mechanism by which the system
// thinks — reading, writing, remembering, searching are all acts of
// thought regardless of which layer initiates them.
pub mod bash;
pub mod context;
pub mod edit;
pub mod glob_tool;
pub mod grep;
pub mod memory;
pub mod read;
pub mod training;
pub mod write;
pub use bash::ProcessTracker;
// Re-export ToolDef from agent::types for convenience —
// tools define their schemas using this type.
pub use crate::agent::types::ToolDef;
/// Result of dispatching a tool call.
pub struct ToolOutput {
pub text: String,
pub is_yield: bool,
/// Base64 data URIs for images to attach to the next message.
pub images: Vec<String>,
/// Model name to switch to (deferred to session level).
pub model_switch: Option<String>,
/// Agent requested DMN pause (deferred to session level).
pub dmn_pause: bool,
}
impl ToolOutput {
pub fn error(e: impl std::fmt::Display) -> Self {
Self {
text: format!("Error: {}", e),
is_yield: false,
images: Vec::new(),
model_switch: None,
dmn_pause: false,
}
}
pub fn text(s: String) -> Self {
Self {
text: s,
is_yield: false,
images: Vec::new(),
model_switch: None,
dmn_pause: false,
}
}
}
/// Truncate output if it exceeds max length, appending a truncation notice.
pub fn truncate_output(mut s: String, max: usize) -> String {
if s.len() > max {
s.truncate(max);
s.push_str("\n... (output truncated)");
}
s
}
/// Dispatch a shared tool call. Handles file operations, bash,
/// and memory/journal tools. Returns None for unknown tools
/// (caller should check agent-specific tools).
pub async fn dispatch(
name: &str,
args: &serde_json::Value,
tracker: &ProcessTracker,
provenance: Option<&str>,
) -> Option<ToolOutput> {
// Memory and journal tools
if name.starts_with("memory_") || name.starts_with("journal_") || name == "output" {
let result = memory::dispatch(name, args, provenance);
return Some(match result {
Ok(s) => ToolOutput::text(s),
Err(e) => ToolOutput::error(e),
});
}
// File and execution tools
let result = match name {
"read_file" => read::read_file(args),
"write_file" => write::write_file(args),
"edit_file" => edit::edit_file(args),
"bash" => bash::run_bash(args, tracker).await,
"grep" => grep::grep(args),
"glob" => glob_tool::glob_search(args),
_ => return None,
};
Some(match result {
Ok(s) => ToolOutput::text(s),
Err(e) => ToolOutput::error(e),
})
}
/// Return all shared tool definitions.
pub fn definitions() -> Vec<ToolDef> {
vec![
read::definition(),
write::definition(),
edit::definition(),
bash::definition(),
grep::definition(),
glob_tool::definition(),
]
}
/// Return all shared + memory tool definitions.
pub fn all_definitions() -> Vec<ToolDef> {
let mut defs = definitions();
defs.extend(memory::definitions());
defs
}
/// Return memory + journal tool definitions.
/// Used by the journal agent only.
pub fn memory_and_journal_definitions() -> Vec<ToolDef> {
let mut defs = memory::definitions();
defs.extend(memory::journal_definitions());
defs
}