forked from kent/consciousness
journal_tail: return typed Vec<JournalEntry>, remove Store::load from agent
- journal_tail returns Vec<JournalEntry> with key, content, created_at - load_startup_journal uses typed API, no more direct Store access - CLI does formatting, hippocampus returns data Co-Authored-By: Proof of Concept <poc@bcachefs.org>
This commit is contained in:
parent
419bb222b5
commit
063cf031d3
4 changed files with 62 additions and 47 deletions
|
|
@ -257,31 +257,46 @@ pub fn memory_query(store: &Store, _provenance: &str, query_str: &str, format: O
|
|||
|
||||
// ── Journal tools ──────────────────────────────────────────────
|
||||
|
||||
pub fn journal_tail(store: &Store, _provenance: &str, count: Option<u64>, level: Option<u64>, format: Option<&str>, after: Option<&str>) -> Result<String> {
|
||||
let count = count.unwrap_or(1);
|
||||
let level = level.unwrap_or(0);
|
||||
let format = format.unwrap_or("full");
|
||||
/// A journal entry with key, content, and timestamp.
|
||||
#[derive(Clone, Debug, serde::Serialize, serde::Deserialize)]
|
||||
pub struct JournalEntry {
|
||||
pub key: String,
|
||||
pub content: String,
|
||||
pub created_at: i64,
|
||||
}
|
||||
|
||||
let type_name = match level {
|
||||
0 => "episodic",
|
||||
1 => "daily",
|
||||
2 => "weekly",
|
||||
3 => "monthly",
|
||||
_ => return Err(anyhow::anyhow!("invalid level: {} (0=journal, 1=daily, 2=weekly, 3=monthly)", level)),
|
||||
/// Get journal entries, sorted by timestamp (newest first).
|
||||
/// level: 0=session, 1=daily, 2=weekly, 3=monthly
|
||||
/// after: only entries after this date (YYYY-MM-DD)
|
||||
pub fn journal_tail(store: &Store, _provenance: &str, count: Option<u64>, level: Option<u64>, after: Option<&str>) -> Result<Vec<JournalEntry>> {
|
||||
let count = count.unwrap_or(10) as usize;
|
||||
let level = level.unwrap_or(0);
|
||||
let node_type = match level {
|
||||
0 => crate::store::NodeType::EpisodicSession,
|
||||
1 => crate::store::NodeType::EpisodicDaily,
|
||||
2 => crate::store::NodeType::EpisodicWeekly,
|
||||
3 => crate::store::NodeType::EpisodicMonthly,
|
||||
_ => return Err(anyhow::anyhow!("invalid level: {}", level)),
|
||||
};
|
||||
|
||||
let mut q = std::format!("all | type:{} | sort:timestamp", type_name);
|
||||
if let Some(date) = after {
|
||||
// Convert date to age in seconds
|
||||
if let Ok(nd) = chrono::NaiveDate::parse_from_str(date, "%Y-%m-%d") {
|
||||
let ts = nd.and_hms_opt(0, 0, 0).unwrap().and_utc().timestamp();
|
||||
let age = chrono::Utc::now().timestamp() - ts;
|
||||
q.push_str(&std::format!(" | age:<{}", age));
|
||||
}
|
||||
}
|
||||
q.push_str(&std::format!(" | limit:{}", count));
|
||||
let after_ts = after.and_then(|date| {
|
||||
chrono::NaiveDate::parse_from_str(date, "%Y-%m-%d").ok()
|
||||
.and_then(|nd| nd.and_hms_opt(0, 0, 0))
|
||||
.map(|dt| dt.and_utc().timestamp())
|
||||
});
|
||||
|
||||
memory_query(store, _provenance, &q, Some(format))
|
||||
let mut entries: Vec<_> = store.nodes.values()
|
||||
.filter(|n| n.node_type == node_type)
|
||||
.filter(|n| after_ts.map(|ts| n.created_at >= ts).unwrap_or(true))
|
||||
.map(|n| JournalEntry {
|
||||
key: n.key.clone(),
|
||||
content: n.content.clone(),
|
||||
created_at: n.created_at,
|
||||
})
|
||||
.collect();
|
||||
entries.sort_by_key(|e| std::cmp::Reverse(e.created_at));
|
||||
entries.truncate(count);
|
||||
Ok(entries)
|
||||
}
|
||||
|
||||
fn level_to_node_type(level: i64) -> crate::store::NodeType {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue