Sebas Tin angelegt und Synology Chat connected
This commit is contained in:
@@ -0,0 +1,22 @@
|
||||
use thiserror::Error;
|
||||
|
||||
#[derive(Debug, Error)]
|
||||
pub enum NazarickError {
|
||||
#[error("IO error: {0}")]
|
||||
Io(#[from] std::io::Error),
|
||||
|
||||
#[error("Config error: {0}")]
|
||||
Config(String),
|
||||
|
||||
#[error("Agent error: {0}")]
|
||||
Agent(String),
|
||||
|
||||
#[error("Memory error: {0}")]
|
||||
Memory(String),
|
||||
|
||||
#[error("Skill error: {0}")]
|
||||
Skill(String),
|
||||
|
||||
#[error("Api error: {0}")]
|
||||
Api(String),
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
use crate::types::AgentId;
|
||||
|
||||
#[derive(Debug, Clone, PartialEq)]
|
||||
pub enum Permission {
|
||||
// LLM
|
||||
LlmAccess,
|
||||
// Image
|
||||
ImageGeneration,
|
||||
// Skills
|
||||
SkillFileRead,
|
||||
SkillFileWrite,
|
||||
SkillWebSearch,
|
||||
// Channels
|
||||
ChannelSynology,
|
||||
ChannelWebUi,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct AgentPermissions {
|
||||
pub agent_id: AgentId,
|
||||
pub allowed: Vec<Permission>,
|
||||
}
|
||||
|
||||
impl AgentPermissions {
|
||||
pub fn new(agent_id: AgentId, allowed: Vec<Permission>) -> Self {
|
||||
Self { agent_id, allowed }
|
||||
}
|
||||
|
||||
pub fn has(&self, permission: &Permission) -> bool {
|
||||
self.allowed.contains(permission)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,60 @@
|
||||
use crate::types::Result;
|
||||
use crate::error::NazarickError;
|
||||
|
||||
/// Verantwortlich für das Zusammensetzen des System-Prompts.
|
||||
/// Liest soul_core.md und soul_personality.md und kombiniert
|
||||
/// sie in der richtigen Reihenfolge.
|
||||
///
|
||||
/// Reihenfolge ist bewusst gewählt:
|
||||
/// 1. soul_core.md IMMER zuerst — Kernregeln haben höchste Priorität
|
||||
/// 2. soul_personality.md danach — Ton und Stil
|
||||
/// So kann soul_personality niemals soul_core überschreiben.
|
||||
pub struct PromptBuilder {
|
||||
/// Pfad zu soul_core.md — unveränderliche Kernregeln
|
||||
soul_core_path: String,
|
||||
/// Pfad zu soul_personality.md — entwickelbarer Persönlichkeitsteil
|
||||
soul_personality_path: String,
|
||||
}
|
||||
|
||||
impl PromptBuilder {
|
||||
/// Erstellt einen neuen PromptBuilder mit den angegebenen Dateipfaden.
|
||||
pub fn new(
|
||||
soul_core_path: impl Into<String>,
|
||||
soul_personality_path: impl Into<String>,
|
||||
) -> Self {
|
||||
Self {
|
||||
soul_core_path: soul_core_path.into(),
|
||||
soul_personality_path: soul_personality_path.into(),
|
||||
}
|
||||
}
|
||||
|
||||
/// Liest beide soul-Dateien und kombiniert sie zum finalen System-Prompt.
|
||||
/// Fehlt soul_personality.md wird nur soul_core.md verwendet —
|
||||
/// das System bleibt funktionsfähig auch ohne Persönlichkeitsdatei.
|
||||
pub fn build(&self) -> Result<String> {
|
||||
// soul_core.md ist Pflicht — ohne Kernregeln kein Start
|
||||
let core = std::fs::read_to_string(&self.soul_core_path)
|
||||
.map_err(|e| NazarickError::Config(
|
||||
format!("soul_core.md nicht gefunden unter '{}': {}",
|
||||
self.soul_core_path, e)
|
||||
))?;
|
||||
|
||||
// soul_personality.md ist optional — graceful fallback
|
||||
let personality = match std::fs::read_to_string(&self.soul_personality_path) {
|
||||
Ok(content) => content,
|
||||
Err(_) => {
|
||||
// Kein Fehler — leere Persönlichkeit ist valid beim ersten Start
|
||||
String::new()
|
||||
}
|
||||
};
|
||||
|
||||
// Zusammensetzen: Core immer zuerst
|
||||
let system_prompt = if personality.is_empty() {
|
||||
core
|
||||
} else {
|
||||
format!("{}\n\n---\n\n{}", core, personality)
|
||||
};
|
||||
|
||||
Ok(system_prompt)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
use crate::types::{AgentId, SkillId, MemoryId, Result};
|
||||
|
||||
pub trait Agent: Send + Sync {
|
||||
fn id(&self) -> AgentId;
|
||||
fn name(&self) -> &str;
|
||||
}
|
||||
|
||||
pub trait Skill: Send + Sync {
|
||||
fn id(&self) -> &SkillId;
|
||||
fn name(&self) -> &str;
|
||||
}
|
||||
|
||||
pub trait MemoryStore: Send + Sync {
|
||||
fn store(&self, content: &str) -> Result<MemoryId>;
|
||||
fn retrieve(&self, id: &MemoryId) -> Result<Option<String>>;
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
use uuid::Uuid;
|
||||
use crate::error::NazarickError;
|
||||
|
||||
pub type Result<T> = std::result::Result<T, NazarickError>;
|
||||
pub type AgentId = Uuid;
|
||||
pub type SkillId = String;
|
||||
pub type MemoryId = Uuid;
|
||||
@@ -0,0 +1,50 @@
|
||||
use crate::types::AgentId;
|
||||
|
||||
/// Trackt den Ressourcenverbrauch eines einzelnen Agenten.
|
||||
/// Wird vom Hauptprozess (nazarick) pro Agent geführt und
|
||||
/// ermöglicht späteres Monitoring, Limits und Kostenberechnung.
|
||||
#[derive(Debug, Clone, Default)]
|
||||
pub struct UsageRecord {
|
||||
/// Eindeutige ID des Agenten dem dieser Record gehört
|
||||
pub agent_id: AgentId,
|
||||
/// Anzahl der Token die als Input an die LLM API gesendet wurden
|
||||
pub tokens_input: u64,
|
||||
/// Anzahl der Token die als Output von der LLM API empfangen wurden
|
||||
pub tokens_output: u64,
|
||||
/// Anzahl der Bildgenerierungs-Anfragen (ComfyUI)
|
||||
pub image_requests: u64,
|
||||
/// Gesamtanzahl aller API-Aufrufe (LLM + Bild)
|
||||
pub api_calls: u64,
|
||||
}
|
||||
|
||||
impl UsageRecord {
|
||||
/// Erstellt einen neuen leeren UsageRecord für den angegebenen Agenten.
|
||||
/// Alle Zähler starten bei 0.
|
||||
pub fn new(agent_id: AgentId) -> Self {
|
||||
Self {
|
||||
agent_id,
|
||||
..Default::default()
|
||||
}
|
||||
}
|
||||
|
||||
/// Registriert einen LLM API-Aufruf mit den entsprechenden Token-Zahlen.
|
||||
/// Input und Output werden separat gezählt da sie unterschiedliche
|
||||
/// Kosten haben können (z.B. bei Mistral API).
|
||||
pub fn add_tokens(&mut self, input: u64, output: u64) {
|
||||
self.tokens_input += input;
|
||||
self.tokens_output += output;
|
||||
self.api_calls += 1;
|
||||
}
|
||||
|
||||
/// Registriert eine Bildgenerierungs-Anfrage (z.B. ComfyUI).
|
||||
pub fn add_image_request(&mut self) {
|
||||
self.image_requests += 1;
|
||||
self.api_calls += 1;
|
||||
}
|
||||
|
||||
/// Gibt die Gesamtanzahl der Token zurück (Input + Output).
|
||||
/// Nützlich für schnelle Übersichten ohne Input/Output zu trennen.
|
||||
pub fn total_tokens(&self) -> u64 {
|
||||
self.tokens_input + self.tokens_output
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user