Files
nazarick-private/crates/skills/src/skills/personality.rs
T
Sithies 18b666f45d
CI / check (push) Successful in 4m11s
CI / test (push) Successful in 3m57s
CI / clippy (push) Has been cancelled
added Tokens, openrouter, memory system
2026-03-21 19:59:07 +01:00

155 lines
5.3 KiB
Rust

// crates/skills/src/skills/personality.rs
use std::sync::Arc;
use async_trait::async_trait;
use anyhow::Result;
use tracing::info;
use nazarick_core::agent::traits::{Skill, SkillInput, SkillOutput};
use nazarick_core::agent::context::AgentContext;
use nazarick_core::agent::skill_registry::SkillMeta;
pub struct PersonalitySkill;
impl PersonalitySkill {
fn path(agent_id: &str) -> String {
format!("crates/{}/config/soul_personality.md", agent_id)
}
fn do_update(path: &str, field: &str, value: &str) -> Result<()> {
let content = std::fs::read_to_string(path)?;
let section_header = format!("## {}", field);
let new_section = format!("## {}\n{}", field, value);
let updated = if content.contains(&section_header) {
let mut result = String::new();
let mut in_section = false;
for line in content.lines() {
if line.trim_start().starts_with("## ") && line.contains(field) {
result.push_str(&new_section);
result.push('\n');
in_section = true;
} else if line.trim_start().starts_with("## ") && in_section {
in_section = false;
result.push_str(line);
result.push('\n');
} else if !in_section {
result.push_str(line);
result.push('\n');
}
}
result
} else {
format!("{}\n{}\n", content.trim_end(), new_section)
};
std::fs::write(path, updated)?;
info!(path = %path, field = %field, "Persönlichkeit aktualisiert");
Ok(())
}
fn do_remove(path: &str, field: &str) -> Result<()> {
let content = std::fs::read_to_string(path)?;
if !content.contains(&format!("## {}", field)) {
return Ok(());
}
let mut result = String::new();
let mut in_section = false;
for line in content.lines() {
if line.trim_start().starts_with("## ") && line.contains(field) {
in_section = true;
} else if line.trim_start().starts_with("## ") && in_section {
in_section = false;
result.push_str(line);
result.push('\n');
} else if !in_section {
result.push_str(line);
result.push('\n');
}
}
std::fs::write(path, result.trim_end())?;
info!(path = %path, field = %field, "Persönlichkeits-Abschnitt entfernt");
Ok(())
}
}
#[async_trait]
impl Skill for PersonalitySkill {
fn summary(&self) -> &str {
"Liest und schreibt den PERSONALITY [MUTABLE] Block — speichert dauerhaft Eigenschaften wie Ton, Stil oder Präferenzen des Herrn"
}
fn details(&self) -> &str {
"Verwaltet Persönlichkeitswerte in soul_personality.md.
## update — Wert setzen oder überschreiben
action: update, field: <name>, value: <wert>
## remove — Wert entfernen
action: remove, field: <name>"
}
fn tool_definition(&self) -> serde_json::Value {
serde_json::json!({
"type": "function",
"function": {
"name": "personality",
"description": self.summary(),
"parameters": {
"type": "object",
"properties": {
"action": {
"type": "string",
"enum": ["update", "remove"],
"description": "update = setzen/überschreiben, remove = entfernen"
},
"field": {
"type": "string",
"description": "Name des Persönlichkeitswerts, z.B. 'Ton', 'Stil'"
},
"value": {
"type": "string",
"description": "Neuer Wert — nur bei action=update nötig"
}
},
"required": ["action", "field"]
}
}
})
}
async fn execute(&self, input: SkillInput, ctx: AgentContext) -> Result<SkillOutput> {
let path = Self::path(&ctx.agent_id);
let action = input.get("action").unwrap_or("update");
let field = match input.get("field") {
Some(f) => f,
None => return Ok(SkillOutput::err("Parameter 'field' fehlt")),
};
match action {
"update" => {
let value = match input.get("value") {
Some(v) => v,
None => return Ok(SkillOutput::err("Parameter 'value' fehlt bei action=update")),
};
Self::do_update(&path, field, value)?;
Ok(SkillOutput::ok(format!("'{}' gesetzt auf '{}'", field, value)))
}
"remove" => {
Self::do_remove(&path, field)?;
Ok(SkillOutput::ok(format!("'{}' entfernt", field)))
}
unknown => Ok(SkillOutput::err(format!(
"Unbekannte Action '{}'. Erlaubt: update, remove", unknown
)))
}
}
}
inventory::submit!(SkillMeta {
name: "personality",
allowed: &["all"],
awaits_result: false,
skill: || Arc::new(PersonalitySkill),
});