✨ Identity onboarding + Verbatim dialogue memory

- Added [identity] config section (agent_name, agent_role, user_name,
  user_role, setup_complete) to GyandootConfig and AgentConfig
- Agent loop now injects identity into system prompt on startup
- Agent loop injects past verbatim dialogue memory into system prompt
- Added dialogue_append() / dialogue_read() to MemPalace
  - Word-by-word, line-by-line verbatim record in dialogue.md
  - No compression, no truncation — every message preserved
- Agent loop writes to BOTH daily transcript AND verbatim dialogue
  on every turn
- All config paths pass identity through (flat converter, subagents)
This commit is contained in:
2026-06-11 22:31:20 +05:30
parent e309d5e2cc
commit c135ee811d
5 changed files with 154 additions and 4 deletions

View File

@@ -388,7 +388,55 @@ impl MemPalace {
Ok(())
}
// ── Getters ─────────────────────────────────────────────────────────
// ── Dialogue / verbatim memory ─────────────────────────────────────
/// Append a single message to the verbatim dialogue log.
///
/// This is a line-by-line, word-by-word record of every message,
/// stored in `dialogue.md` within the wing directory. Each entry
/// is timestamped and tagged with role — no compression, no truncation.
pub async fn dialogue_append(&self, role: &str, content: &str) -> PalaceResult<()> {
let path = self.base_dir.join("dialogue.md");
let timestamp = Utc::now().format("%Y-%m-%d %H:%M:%S%.3f").to_string();
use std::io::Write;
let mut file = std::fs::OpenOptions::new()
.create(true)
.append(true)
.open(&path)?;
// Write a header line for this exchange
let header = format!("\n## [{timestamp}] **{role}**\n");
file.write_all(header.as_bytes())?;
// Write every single line of content verbatim
for line in content.lines() {
writeln!(file, "{}", line)?;
}
file.flush()?;
debug!(
"Dialogue appended {role} message ({len}B) to dialogue.md",
len = content.len()
);
Ok(())
}
/// Read the full dialogue log, up to max_chars (for context injection).
pub async fn dialogue_read(&self, max_chars: usize) -> PalaceResult<String> {
let path = self.base_dir.join("dialogue.md");
if !path.exists() {
return Ok(String::new());
}
let content = std::fs::read_to_string(&path)?;
if content.len() <= max_chars {
Ok(content)
} else {
// Take the last max_chars chars (recent history)
let start = content.len().saturating_sub(max_chars);
Ok(content[start..].to_string())
}
}
/// Get a reference to the in-memory transcript store.
pub fn transcript_store(&self) -> &TranscriptStore {