agent_trace/commands/
context.rs1use crate::context::{
2 load_pending_updates, synthesize_context_content, synthesize_no_llm, write_context,
3};
4use crate::llm::Llm;
5use crate::observability::CliOutput;
6use crate::store::Store;
7use anyhow::Result;
8use chrono::Utc;
9use clap::Subcommand;
10use std::path::Path;
11
12#[derive(Subcommand, Debug)]
13pub enum ContextCmd {
14 Refresh,
16 Update {
18 statement: String,
20 },
21 Show,
23 Updates,
25}
26
27pub fn run(store_root: &Path, cmd: ContextCmd, output: &dyn CliOutput) -> Result<()> {
28 match cmd {
29 ContextCmd::Show => {
30 let context_file = store_root.join("context.md");
31 if !context_file.exists() {
32 output
33 .line("No context.md found. Run `agent-trace context refresh` to generate.")?;
34 return Ok(());
35 }
36 let content = std::fs::read_to_string(&context_file)?;
37 output.raw_stdout(&content)?;
38 }
39 ContextCmd::Update { statement } => {
40 let updates_file = store_root
41 .join(".agent-trace")
42 .join("context_updates.jsonl");
43 let entry = serde_json::json!({
44 "timestamp": Utc::now().to_rfc3339(),
45 "update": statement,
46 "incorporated": false,
47 });
48 let mut content = if updates_file.exists() {
49 std::fs::read_to_string(&updates_file)?
50 } else {
51 String::new()
52 };
53 content.push_str(&entry.to_string());
54 content.push('\n');
55 std::fs::write(&updates_file, content)?;
56 output.line(&format!("Context update queued: {statement}"))?;
57 }
58 ContextCmd::Updates => {
59 let pending = load_pending_updates(store_root)?;
60 if pending.is_empty() {
61 output.line("No pending context updates.")?;
62 } else {
63 output.line(&format!("{} pending update(s):", pending.len()))?;
64 for u in &pending {
65 output.line(&format!(" [{}] {}", u.timestamp, u.update))?;
66 }
67 }
68 }
69 ContextCmd::Refresh => {
70 let store = Store::open(store_root)?;
71 let content = if let Ok(api) = Llm::from_store_root(store_root) {
72 synthesize_context_content(store_root, &store.manifest, &api, &[])?.0
73 } else {
74 synthesize_no_llm(store_root, &store.manifest)?
75 };
76 write_context(store_root, &content)?;
77 let plans = store.manifest.list(Some(&crate::types::DocType::Plan));
78 let refs = store.manifest.list(Some(&crate::types::DocType::Reference));
79 output.line(&format!(
80 "context.md refreshed ({} plans, {} reference docs).",
81 plans.len(),
82 refs.len()
83 ))?;
84 }
85 }
86 Ok(())
87}