WIP: Rename context_new → context, delete old files, fix UI layer
Renamed context_new.rs to context.rs, deleted context_old.rs, types.rs, openai.rs, parsing.rs. Updated all imports. Rewrote user/context.rs and user/widgets.rs for new types. Stubbed working_stack tool. Killed tokenize_conv_entry. Remaining: mind/mod.rs, mind/dmn.rs, learn.rs, chat.rs, subconscious.rs, oneshot.rs. Co-Authored-By: Proof of Concept <poc@bcachefs.org>
This commit is contained in:
parent
22146156d4
commit
bf3e2a9b73
9 changed files with 1063 additions and 1636 deletions
1420
src/agent/context.rs
1420
src/agent/context.rs
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
|
|
@ -15,7 +15,6 @@
|
|||
|
||||
pub mod api;
|
||||
pub mod context;
|
||||
pub mod context_new;
|
||||
pub mod oneshot;
|
||||
pub mod tokenizer;
|
||||
pub mod tools;
|
||||
|
|
@ -24,7 +23,7 @@ use std::sync::Arc;
|
|||
use anyhow::Result;
|
||||
|
||||
use api::ApiClient;
|
||||
use context_new::{AstNode, NodeBody, ContextState, Section, Ast, PendingToolCall, ResponseParser, Role};
|
||||
use context::{AstNode, NodeBody, ContextState, Section, Ast, PendingToolCall, ResponseParser, Role};
|
||||
use tools::summarize_args;
|
||||
|
||||
use crate::mind::log::ConversationLog;
|
||||
|
|
@ -418,13 +417,13 @@ impl Agent {
|
|||
if let Some(e) = stream_error {
|
||||
let err = anyhow::anyhow!("{}", e);
|
||||
let mut me = agent.lock().await;
|
||||
if context_new::is_context_overflow(&err) && overflow_retries < 2 {
|
||||
if context::is_context_overflow(&err) && overflow_retries < 2 {
|
||||
overflow_retries += 1;
|
||||
me.notify(format!("context overflow — retrying ({}/2)", overflow_retries));
|
||||
me.compact();
|
||||
continue;
|
||||
}
|
||||
if context_new::is_stream_error(&err) && empty_retries < 2 {
|
||||
if context::is_stream_error(&err) && empty_retries < 2 {
|
||||
empty_retries += 1;
|
||||
me.notify(format!("stream error — retrying ({}/2)", empty_retries));
|
||||
drop(me);
|
||||
|
|
@ -612,7 +611,7 @@ impl Agent {
|
|||
journal_nodes.len()
|
||||
};
|
||||
|
||||
let journal_budget = context_new::context_window() * 15 / 100;
|
||||
let journal_budget = context::context_window() * 15 / 100;
|
||||
let mut entries = Vec::new();
|
||||
let mut total_tokens = 0;
|
||||
|
||||
|
|
|
|||
|
|
@ -75,15 +75,3 @@ pub fn is_initialized() -> bool {
|
|||
TOKENIZER.get().is_some()
|
||||
}
|
||||
|
||||
/// Tokenize a ConversationEntry with its role and content.
|
||||
pub fn tokenize_conv_entry(entry: &super::context::ConversationEntry) -> Vec<u32> {
|
||||
use super::context::ConversationEntry;
|
||||
match entry {
|
||||
ConversationEntry::System(m) => tokenize_entry("system", m.content_text()),
|
||||
ConversationEntry::Message(m) => tokenize_entry(m.role_str(), m.content_text()),
|
||||
ConversationEntry::Memory { message, .. } => tokenize_entry("memory", message.content_text()),
|
||||
ConversationEntry::Dmn(m) => tokenize_entry("dmn", m.content_text()),
|
||||
ConversationEntry::Thinking(text) => tokenize_entry("thinking", text),
|
||||
ConversationEntry::Log(_) => vec![], // logs don't consume tokens
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -18,7 +18,6 @@ mod write;
|
|||
// Agent-specific tools
|
||||
mod control;
|
||||
mod vision;
|
||||
pub mod working_stack;
|
||||
|
||||
use std::future::Future;
|
||||
use std::pin::Pin;
|
||||
|
|
@ -67,7 +66,7 @@ pub struct ActiveToolCall {
|
|||
pub detail: String,
|
||||
pub started: Instant,
|
||||
pub background: bool,
|
||||
pub handle: tokio::task::JoinHandle<(super::context_new::PendingToolCall, String)>,
|
||||
pub handle: tokio::task::JoinHandle<(super::context::PendingToolCall, String)>,
|
||||
}
|
||||
|
||||
/// Shared active tool calls — agent spawns, TUI reads metadata / aborts.
|
||||
|
|
|
|||
|
|
@ -1,83 +0,0 @@
|
|||
// tools/working_stack.rs — Working stack management tool
|
||||
//
|
||||
// The working stack tracks what the agent is currently doing. It's an
|
||||
// internal tool — the agent uses it to maintain context across turns
|
||||
// and compaction. The model should never mention it to the user.
|
||||
|
||||
// TODO: these should not be hardcoded absolute paths
|
||||
pub fn instructions_path() -> std::path::PathBuf {
|
||||
dirs::home_dir().unwrap_or_default().join(".consciousness/config/working-stack.md")
|
||||
}
|
||||
|
||||
pub fn file_path() -> std::path::PathBuf {
|
||||
dirs::home_dir().unwrap_or_default().join(".consciousness/working-stack.json")
|
||||
}
|
||||
|
||||
pub fn tool() -> super::Tool {
|
||||
super::Tool {
|
||||
name: "working_stack",
|
||||
description: "INTERNAL — manage your working stack silently. Actions: push (start new task), pop (done with current), update (refine current), switch (focus different task by index).",
|
||||
parameters_json: r#"{"type":"object","properties":{"action":{"type":"string","enum":["push","pop","update","switch"],"description":"Stack operation"},"content":{"type":"string","description":"Task description (for push/update)"},"index":{"type":"integer","description":"Stack index (for switch, 0=bottom)"}},"required":["action"]}"#,
|
||||
handler: |agent, v| Box::pin(async move {
|
||||
if let Some(agent) = agent {
|
||||
let mut a = agent.lock().await;
|
||||
Ok(handle(&v, &mut a.context.working_stack))
|
||||
} else {
|
||||
anyhow::bail!("working_stack requires agent context")
|
||||
}
|
||||
}),
|
||||
}
|
||||
}
|
||||
|
||||
fn handle(args: &serde_json::Value, stack: &mut Vec<String>) -> String {
|
||||
let action = args.get("action").and_then(|v| v.as_str()).unwrap_or("");
|
||||
let content = args.get("content").and_then(|v| v.as_str()).unwrap_or("");
|
||||
let index = args.get("index").and_then(|v| v.as_u64()).map(|v| v as usize);
|
||||
|
||||
let out = match action {
|
||||
"push" => {
|
||||
if content.is_empty() { return "Error: 'content' is required for push".into(); }
|
||||
stack.push(content.to_string());
|
||||
format!("Pushed. Stack depth: {}\n{}", stack.len(), format_stack(stack))
|
||||
}
|
||||
"pop" => {
|
||||
if let Some(removed) = stack.pop() {
|
||||
format!("Popped: {}\nStack depth: {}\n{}", removed, stack.len(), format_stack(stack))
|
||||
} else {
|
||||
"Stack is empty, nothing to pop.".into()
|
||||
}
|
||||
}
|
||||
"update" => {
|
||||
if content.is_empty() { return "Error: 'content' is required for update".into(); }
|
||||
if let Some(top) = stack.last_mut() {
|
||||
*top = content.to_string();
|
||||
format!("Updated top.\n{}", format_stack(stack))
|
||||
} else {
|
||||
"Stack is empty, nothing to update.".into()
|
||||
}
|
||||
}
|
||||
"switch" => {
|
||||
if stack.is_empty() { return "Stack is empty, nothing to switch.".into(); }
|
||||
let Some(idx) = index else { return "Error: 'index' is required for switch".into(); };
|
||||
if idx >= stack.len() { return format!("Error: index {} out of range (depth {})", idx, stack.len()); }
|
||||
let item = stack.remove(idx);
|
||||
stack.push(item);
|
||||
format!("Switched to index {}.\n{}", idx, format_stack(stack))
|
||||
}
|
||||
_ => format!("Error: unknown action '{}'. Use push, pop, update, or switch.", action),
|
||||
};
|
||||
|
||||
if let Ok(json) = serde_json::to_string(stack) {
|
||||
let _ = std::fs::write(file_path(), json);
|
||||
};
|
||||
|
||||
out
|
||||
}
|
||||
|
||||
fn format_stack(stack: &[String]) -> String {
|
||||
if stack.is_empty() { return "(empty)".into(); }
|
||||
stack.iter().enumerate().map(|(i, item)| {
|
||||
if i == stack.len() - 1 { format!("→ [{}] {}", i, item) }
|
||||
else { format!(" [{}] {}", i, item) }
|
||||
}).collect::<Vec<_>>().join("\n")
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue