huskies: merge 670_refactor_hoist_chat_history_persistence_into_a_shared_module_replaces_658

This commit is contained in:
dave
2026-04-27 20:05:12 +00:00
parent 615e1c7f73
commit 63d5a500de
6 changed files with 208 additions and 136 deletions
@@ -1,5 +1,5 @@
//! Matrix conversation history — per-room message history for LLM context.
use crate::slog;
use crate::chat::history::{load_chat_history, save_chat_history};
use matrix_sdk::ruma::OwnedRoomId;
use serde::{Deserialize, Serialize};
use std::collections::HashMap;
@@ -44,32 +44,13 @@ pub struct RoomConversation {
/// event-handler tasks without blocking the sync loop.
pub type ConversationHistory = Arc<TokioMutex<HashMap<OwnedRoomId, RoomConversation>>>;
/// On-disk format for persisted conversation history. Room IDs are stored as
/// strings because `OwnedRoomId` does not implement `Serialize` as a map key.
#[derive(Serialize, Deserialize)]
pub(super) struct PersistedHistory {
pub rooms: HashMap<String, RoomConversation>,
}
/// Path to the persisted conversation history file relative to project root.
pub(super) const HISTORY_FILE: &str = ".huskies/matrix_history.json";
/// Load conversation history from disk, returning an empty map on any error.
pub fn load_history(project_root: &std::path::Path) -> HashMap<OwnedRoomId, RoomConversation> {
let path = project_root.join(HISTORY_FILE);
let data = match std::fs::read_to_string(&path) {
Ok(d) => d,
Err(_) => return HashMap::new(),
};
let persisted: PersistedHistory = match serde_json::from_str(&data) {
Ok(p) => p,
Err(e) => {
slog!("[matrix-bot] Failed to parse history file: {e}");
return HashMap::new();
}
};
persisted
.rooms
let string_map = load_chat_history(project_root, HISTORY_FILE, "matrix-bot");
string_map
.into_iter()
.filter_map(|(k, v)| k.parse::<OwnedRoomId>().ok().map(|room_id| (room_id, v)))
.collect()
@@ -80,21 +61,11 @@ pub fn save_history(
project_root: &std::path::Path,
history: &HashMap<OwnedRoomId, RoomConversation>,
) {
let persisted = PersistedHistory {
rooms: history
.iter()
.map(|(k, v)| (k.to_string(), v.clone()))
.collect(),
};
let path = project_root.join(HISTORY_FILE);
match serde_json::to_string_pretty(&persisted) {
Ok(json) => {
if let Err(e) = std::fs::write(&path, json) {
slog!("[matrix-bot] Failed to write history file: {e}");
}
}
Err(e) => slog!("[matrix-bot] Failed to serialise history: {e}"),
}
let string_map: HashMap<String, RoomConversation> = history
.iter()
.map(|(k, v)| (k.to_string(), v.clone()))
.collect();
save_chat_history(project_root, HISTORY_FILE, "matrix-bot", &string_map);
}
// ---------------------------------------------------------------------------