use std::collections::HashSet;
use serde_json::Value;
use crate::tape::entries::TapeEntry;
pub fn collect_active_decisions(entries: &[TapeEntry]) -> Vec<String> {
let mut decisions: Vec<String> = Vec::new();
let mut revoked: HashSet<String> = HashSet::new();
for entry in entries {
if entry.kind == "decision_revoked"
&& let Some(text) = entry.payload.get("text").and_then(|v| v.as_str())
{
revoked.insert(text.to_string());
}
}
for entry in entries {
if entry.kind == "decision"
&& let Some(text) = entry.payload.get("text").and_then(|v| v.as_str())
&& !revoked.contains(text)
&& !text.is_empty()
{
decisions.push(text.to_string());
}
}
decisions
}
pub fn inject_decisions_into_system_prompt(messages: &mut Vec<Value>, decisions: &[String]) {
if decisions.is_empty() {
return;
}
let mut block = String::from("\n\nActive decisions:");
for (i, decision) in decisions.iter().enumerate() {
block.push_str(&format!("\n{}. {}", i + 1, decision));
}
let mut last_system_idx = None;
for (i, msg) in messages.iter().enumerate() {
if msg.get("role").and_then(|r| r.as_str()) == Some("system") {
last_system_idx = Some(i);
}
}
if let Some(idx) = last_system_idx {
if let Some(obj) = messages[idx].as_object_mut() {
let existing = obj.get("content").and_then(|c| c.as_str()).unwrap_or("");
let new_content = format!("{}{}", existing, block);
obj.insert("content".to_owned(), Value::String(new_content));
}
} else {
messages.insert(
0,
serde_json::json!({"role": "system", "content": block.trim_start()}),
);
}
}