✨ 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:
@@ -159,8 +159,59 @@ impl AgentLoop {
|
||||
let _guard = span.enter();
|
||||
info!("Agent loop started (interactive)");
|
||||
|
||||
// ── Identity & memory injection on startup ─────────────────────
|
||||
let (agent_name, agent_role, user_name, user_role) = {
|
||||
let memory = self.memory.lock().await;
|
||||
let (l0, _) = memory.identity_get().unwrap_or_default();
|
||||
if !l0.is_empty() && !self.config.identity.agent_name.is_empty() {
|
||||
(
|
||||
self.config.identity.agent_name.clone(),
|
||||
self.config.identity.agent_role.clone(),
|
||||
self.config.identity.user_name.clone(),
|
||||
self.config.identity.user_role.clone(),
|
||||
)
|
||||
} else if !l0.is_empty() {
|
||||
// Parse from L0: "name: X\nrole: Y\nuser: Z (W)\n"
|
||||
let mut parts = l0.lines().filter_map(|l| l.split_once(": ").map(|(_, v)| v.to_string())).collect::<Vec<_>>();
|
||||
(
|
||||
parts.get(0).cloned().unwrap_or_default(),
|
||||
parts.get(1).cloned().unwrap_or_default(),
|
||||
parts.get(2).and_then(|u| u.split_once(" (").map(|(n, _)| n.to_string())).unwrap_or_default(),
|
||||
parts.get(2).and_then(|u| u.split_once(" (").and_then(|(_, r)| r.trim_end_matches(')').to_string().into())).unwrap_or_default(),
|
||||
)
|
||||
} else {
|
||||
(String::new(), String::new(), String::new(), String::new())
|
||||
}
|
||||
};
|
||||
|
||||
// Build system prompt with identity + dialogue memory
|
||||
let mut system_prompt = self.config.system_prompt.clone();
|
||||
if !agent_name.is_empty() {
|
||||
system_prompt = format!(
|
||||
"{}\n\n## Your Identity\n- Name: {}\n- Role: {}\n- You are speaking to: {} ({})\n\n## Memory\nYou have a verbatim dialogue log with your user. Use everything from past conversations as context when answering.",
|
||||
system_prompt,
|
||||
agent_name,
|
||||
if agent_role.is_empty() { "AI Assistant" } else { &agent_role },
|
||||
if user_name.is_empty() { "the User" } else { &user_name },
|
||||
if user_role.is_empty() { "User" } else { &user_role },
|
||||
);
|
||||
}
|
||||
|
||||
// Inject recent dialogue from verbatim memory
|
||||
{
|
||||
let memory = self.memory.lock().await;
|
||||
if let Ok(dialogue) = memory.dialogue_read(8000).await {
|
||||
if !dialogue.is_empty() {
|
||||
system_prompt = format!(
|
||||
"{}\n\n## Past Conversations (Verbatim Memory)\n{}\n---\nContinue the conversation naturally.",
|
||||
system_prompt, dialogue
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let mut messages: Vec<Message> =
|
||||
vec![Message::new(MessageRole::System, &self.config.system_prompt)];
|
||||
vec![Message::new(MessageRole::System, &system_prompt)];
|
||||
|
||||
loop {
|
||||
// 1. Read user input
|
||||
@@ -174,19 +225,26 @@ impl AgentLoop {
|
||||
|
||||
// 3. Sanitize
|
||||
let clean_input = self.sanitizer.sanitize_input(&user_input, &gyandoot_security::sanitizer::SanitizerConfig::default());
|
||||
messages.push(Message::new(MessageRole::User, clean_input));
|
||||
messages.push(Message::new(MessageRole::User, clean_input.clone()));
|
||||
|
||||
// 4. Run the core turn (LLM + tool execution)
|
||||
let new_messages = self.execute_turn(messages).await?;
|
||||
messages = new_messages;
|
||||
|
||||
// 5. Store conversation turn in memory
|
||||
// 5. Store conversation turn in memory (transcript + verbatim dialogue)
|
||||
{
|
||||
let memory = self.memory.lock().await;
|
||||
// Daily transcript
|
||||
memory
|
||||
.transcript_append("user", &user_input)
|
||||
.await
|
||||
.unwrap_or_else(|e| warn!("Failed to store user message: {e}"));
|
||||
// Verbatim dialogue — word by word, line by line
|
||||
memory
|
||||
.dialogue_append("user", &user_input)
|
||||
.await
|
||||
.unwrap_or_else(|e| warn!("Failed to store user dialogue: {e}"));
|
||||
|
||||
// Store last assistant response
|
||||
if let Some(last) = messages.last() {
|
||||
if last.role == MessageRole::Assistant {
|
||||
@@ -194,6 +252,10 @@ impl AgentLoop {
|
||||
.transcript_append("assistant", &last.content)
|
||||
.await
|
||||
.unwrap_or_else(|e| warn!("Failed to store assistant message: {e}"));
|
||||
memory
|
||||
.dialogue_append("assistant", &last.content)
|
||||
.await
|
||||
.unwrap_or_else(|e| warn!("Failed to store assistant dialogue: {e}"));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user