155 lines
5.3 KiB
Rust
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(§ion_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),
|
|
}); |