feat: Memory-System mit persistenten Markdown-Dateien pro Agent

- MemoryService: Verwaltet data/agents/{agentId}/ Verzeichnisse
  - MEMORY.md als Haupt-Memory-File
  - memory/ Unterordner für Tages-Logs und thematische Notizen
  - Sandbox-Prüfung verhindert Zugriff außerhalb des Agent-Dirs

- Memory-Tools für den Agent:
  - memory_read: Liest Memory-Dateien
  - memory_write: Schreibt/überschreibt oder hängt an (append)
  - memory_list: Listet alle Memory-Dateien auf

- SystemPromptBuilder: Memory-Abschnitt mit Regeln und aktuellem
  MEMORY.md-Inhalt wird in den System-Prompt injiziert

- ToolService/AnthropicService: Memory-Tools werden automatisch
  eingebunden wenn MemoryService und AgentId verfügbar sind

- TODO.md: Embedding-basierte Suche und Subagents als Features
This commit is contained in:
Meleki committed 2026-03-01 13:27:08 +01:00
1 parent 875229964c
commit d913557173
8 files changed
+250 -14

No files matched your search

+4 -4
View File
@@ -23,7 +23,7 @@ public static class ChatEndpoint
app.MapPost("/api/chat", HandleChat);
}
private static async Task HandleChat(HttpRequest req, HttpResponse res, IHttpClientFactory httpFactory, IConfiguration config, ToolService toolService, DatabaseService db, StreamingTracker streamingTracker, CancellationToken cancellationToken)
private static async Task HandleChat(HttpRequest req, HttpResponse res, IHttpClientFactory httpFactory, IConfiguration config, ToolService toolService, DatabaseService db, StreamingTracker streamingTracker, MemoryService memoryService, CancellationToken cancellationToken)
{
var body = await JsonSerializer.DeserializeAsync<ChatRequest>(req.Body);
if (body == null || body.Messages == null || body.Messages.Count == 0)
@@ -78,7 +78,7 @@ public static class ChatEndpoint
res.Headers["Connection"] = "keep-alive";
var markedMessages = await db.GetMarkedMessages(sessionId);
var systemPromptText = SystemPromptBuilder.Build(agent, session, markedMessages);
var systemPromptText = SystemPromptBuilder.Build(agent, session, markedMessages, memoryService);
var chainId = Guid.NewGuid().ToString("N");
@@ -155,11 +155,11 @@ public static class ChatEndpoint
var maxIterations = config.GetValue<int>("MaxIterations", 100);
var toolChoice = agent.ToolChoice ?? "any";
var anthropic = new AnthropicService(httpFactory, token, toolService, db);
var anthropic = new AnthropicService(httpFactory, token, toolService, db, memoryService);
streamingTracker.Start(sessionId, chainId);
try
{
await anthropic.StreamChat(res, modelId, systemPrompt, messages, chainId, workspace, sessionId, maxIterations: maxIterations, toolChoice: toolChoice, cancellationToken: cancellationToken);
await anthropic.StreamChat(res, modelId, systemPrompt, messages, chainId, workspace, sessionId, agentId: agent.AgentId, maxIterations: maxIterations, toolChoice: toolChoice, cancellationToken: cancellationToken);
}
finally
{
+2 -2
View File
@@ -91,7 +91,7 @@ public static class SessionEndpoint
ctx.Response.StatusCode = 204;
}
private static async Task HandleSystemPrompt(HttpContext ctx, DatabaseService db)
private static async Task HandleSystemPrompt(HttpContext ctx, DatabaseService db, MemoryService memoryService)
{
var sessionId = ctx.Request.RouteValues["sessionId"]?.ToString();
if (string.IsNullOrEmpty(sessionId))
@@ -123,7 +123,7 @@ public static class SessionEndpoint
}
var markedMessages = await db.GetMarkedMessages(sessionId);
var systemPrompt = SystemPromptBuilder.Build(agent, session, markedMessages);
var systemPrompt = SystemPromptBuilder.Build(agent, session, markedMessages, memoryService);
ctx.Response.ContentType = "text/plain; charset=utf-8";
await ctx.Response.WriteAsync(systemPrompt);