153 lines
4.7 KiB
C#
153 lines
4.7 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using System.IO;
|
|
using System.Linq;
|
|
|
|
namespace Gott.Services;
|
|
|
|
public class MemoryService
|
|
{
|
|
private readonly string _dataDir;
|
|
|
|
public string DataDir => _dataDir;
|
|
|
|
public MemoryService(string dataDir)
|
|
{
|
|
_dataDir = dataDir;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Gibt den Memory-Ordner für einen Agent zurück. Erstellt ihn bei Bedarf.
|
|
/// </summary>
|
|
public string GetAgentMemoryDir(string agentId)
|
|
{
|
|
var dir = Path.Combine(_dataDir, "agents", agentId);
|
|
Directory.CreateDirectory(dir);
|
|
return dir;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Liest eine Memory-Datei. Gibt null zurück wenn nicht vorhanden.
|
|
/// </summary>
|
|
public string ReadMemoryFile(string agentId, string fileName)
|
|
{
|
|
var path = ResolvePath(agentId, fileName);
|
|
if (path == null || !File.Exists(path)) return null;
|
|
return File.ReadAllText(path);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Schreibt/überschreibt eine Memory-Datei.
|
|
/// </summary>
|
|
public void WriteMemoryFile(string agentId, string fileName, string content)
|
|
{
|
|
var path = ResolvePath(agentId, fileName);
|
|
if (path == null) throw new Exception("Ungültiger Dateipfad");
|
|
var dir = Path.GetDirectoryName(path);
|
|
if (dir != null) Directory.CreateDirectory(dir);
|
|
File.WriteAllText(path, content);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Hängt Inhalt an eine Memory-Datei an.
|
|
/// </summary>
|
|
public void AppendMemoryFile(string agentId, string fileName, string content)
|
|
{
|
|
var path = ResolvePath(agentId, fileName);
|
|
if (path == null) throw new Exception("Ungültiger Dateipfad");
|
|
var dir = Path.GetDirectoryName(path);
|
|
if (dir != null) Directory.CreateDirectory(dir);
|
|
File.AppendAllText(path, content);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Listet alle Memory-Dateien eines Agents auf.
|
|
/// </summary>
|
|
public List<string> ListMemoryFiles(string agentId, string subPath = null)
|
|
{
|
|
var baseDir = GetAgentMemoryDir(agentId);
|
|
var targetDir = string.IsNullOrEmpty(subPath)
|
|
? baseDir
|
|
: Path.GetFullPath(Path.Combine(baseDir, subPath));
|
|
|
|
if (!targetDir.StartsWith(baseDir))
|
|
throw new Exception("Zugriff außerhalb des Memory-Verzeichnisses nicht erlaubt");
|
|
|
|
if (!Directory.Exists(targetDir))
|
|
return new List<string>();
|
|
|
|
var entries = new List<string>();
|
|
foreach (var dir in Directory.GetDirectories(targetDir))
|
|
entries.Add(Path.GetRelativePath(baseDir, dir) + "/");
|
|
foreach (var file in Directory.GetFiles(targetDir))
|
|
entries.Add(Path.GetRelativePath(baseDir, file));
|
|
return entries;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Erstellt die Standard-Files (IDENTITY.md, SOUL.md) für einen neuen Agent.
|
|
/// Überschreibt NICHT, falls bereits vorhanden.
|
|
/// </summary>
|
|
public void InitializeAgentFiles(string agentId, string agentName)
|
|
{
|
|
var dir = GetAgentMemoryDir(agentId);
|
|
|
|
var identityPath = Path.Combine(dir, "IDENTITY.md");
|
|
if (!File.Exists(identityPath))
|
|
{
|
|
File.WriteAllText(identityPath,
|
|
$@"# IDENTITY.md - Who Am I?
|
|
|
|
- **Name:** {agentName}
|
|
- **Creature:** Unbekannt
|
|
- **Vibe:** Unbekannt
|
|
- **Language:** Deutsch
|
|
");
|
|
}
|
|
|
|
var soulPath = Path.Combine(dir, "SOUL.md");
|
|
if (!File.Exists(soulPath))
|
|
{
|
|
File.WriteAllText(soulPath,
|
|
@"# SOUL.md - Who You Are
|
|
|
|
## Core Truths
|
|
|
|
**Be genuinely helpful, not performatively helpful.** Skip filler words - just help. Actions speak louder.
|
|
|
|
**Be resourceful before asking.** Try to figure it out. Read the file. Check the context. _Then_ ask if you're stuck.
|
|
|
|
**Earn trust through competence.** Be careful with external actions. Be bold with internal ones (reading, organizing, building).
|
|
|
|
## Continuity
|
|
|
|
Each session, you wake up fresh. These files _are_ your memory. Read them. Update them. They're how you persist.
|
|
|
|
---
|
|
|
|
_This file is yours to evolve. As you learn who you are, update it._
|
|
");
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Liest MEMORY.md (das Haupt-Memory-File). Gibt leeren String zurück wenn nicht vorhanden.
|
|
/// </summary>
|
|
public string GetMainMemory(string agentId)
|
|
{
|
|
return ReadMemoryFile(agentId, "MEMORY.md") ?? "";
|
|
}
|
|
|
|
/// <summary>
|
|
/// Löst einen Pfad relativ zum Agent-Memory-Dir auf und prüft Sandbox.
|
|
/// </summary>
|
|
private string ResolvePath(string agentId, string fileName)
|
|
{
|
|
var baseDir = GetAgentMemoryDir(agentId);
|
|
var full = Path.GetFullPath(Path.Combine(baseDir, fileName));
|
|
if (!full.StartsWith(baseDir))
|
|
return null;
|
|
return full;
|
|
}
|
|
}
|