diff --git a/Endpoints/AgentEndpoint.cs b/Endpoints/AgentEndpoint.cs index 1a4e959..828657a 100644 --- a/Endpoints/AgentEndpoint.cs +++ b/Endpoints/AgentEndpoint.cs @@ -52,8 +52,6 @@ public static class AgentEndpoint Avatar = imageService.ResizeDataUrl(avatarRaw), Description = body.TryGetProperty("description", out var d) ? d.GetString() : null, Model = body.TryGetProperty("model", out var m) ? m.GetString() ?? "sonnet" : "sonnet", - Persona = body.TryGetProperty("persona", out var p) ? p.GetString() : null, - Instructions = body.TryGetProperty("instructions", out var i) ? i.GetString() : null, ToolChoice = body.TryGetProperty("toolChoice", out var tc) ? tc.GetString() ?? "any" : "any", CustomCommands = customCommands, AutoCommit = body.TryGetProperty("autoCommit", out var ac) && ac.GetBoolean() @@ -77,8 +75,6 @@ public static class AgentEndpoint if (body.TryGetProperty("avatar", out var av)) agent.Avatar = imageService.ResizeDataUrl(av.GetString()); if (body.TryGetProperty("description", out var d)) agent.Description = d.GetString(); if (body.TryGetProperty("model", out var m)) agent.Model = m.GetString(); - if (body.TryGetProperty("persona", out var p)) agent.Persona = p.GetString(); - if (body.TryGetProperty("instructions", out var i)) agent.Instructions = i.GetString(); if (body.TryGetProperty("toolChoice", out var tc)) agent.ToolChoice = tc.GetString(); if (body.TryGetProperty("customCommands", out var cc)) agent.CustomCommands = cc.ValueKind == JsonValueKind.Null ? null : cc.GetRawText(); diff --git a/Endpoints/ChatEndpoint.cs b/Endpoints/ChatEndpoint.cs index d544e80..f0213df 100644 --- a/Endpoints/ChatEndpoint.cs +++ b/Endpoints/ChatEndpoint.cs @@ -79,7 +79,8 @@ public static class ChatEndpoint var markedMessages = await db.GetMarkedMessages(sessionId); var agentMemoryDir = memoryService.GetAgentMemoryDir(agent.AgentId); - var systemPromptText = SystemPromptBuilder.Build(agent, session, markedMessages, memoryService, agentMemoryDir); + var dataDir = memoryService.DataDir; + var systemPromptText = SystemPromptBuilder.Build(agent, session, markedMessages, memoryService, agentMemoryDir, dataDir); var chainId = Guid.NewGuid().ToString("N"); diff --git a/Endpoints/SessionEndpoint.cs b/Endpoints/SessionEndpoint.cs index 7934aa6..c9599a9 100644 --- a/Endpoints/SessionEndpoint.cs +++ b/Endpoints/SessionEndpoint.cs @@ -124,7 +124,8 @@ public static class SessionEndpoint var markedMessages = await db.GetMarkedMessages(sessionId); var agentMemoryDir = memoryService.GetAgentMemoryDir(agent.AgentId); - var systemPrompt = SystemPromptBuilder.Build(agent, session, markedMessages, memoryService, agentMemoryDir); + var dataDir = memoryService.DataDir; + var systemPrompt = SystemPromptBuilder.Build(agent, session, markedMessages, memoryService, agentMemoryDir, dataDir); ctx.Response.ContentType = "text/plain; charset=utf-8"; await ctx.Response.WriteAsync(systemPrompt); diff --git a/Models/AgentRecord.cs b/Models/AgentRecord.cs index b2e7f28..1db0406 100644 --- a/Models/AgentRecord.cs +++ b/Models/AgentRecord.cs @@ -8,8 +8,6 @@ public class AgentRecord public string Avatar { get; set; } // base64 data url public string Description { get; set; } public string Model { get; set; } // sonnet, opus - public string Persona { get; set; } - public string Instructions { get; set; } public string ToolChoice { get; set; } // "any" oder "auto" public string CustomCommands { get; set; } public bool AutoCommit { get; set; } diff --git a/Services/DatabaseService.cs b/Services/DatabaseService.cs index d00fe69..a2d90cb 100644 --- a/Services/DatabaseService.cs +++ b/Services/DatabaseService.cs @@ -148,8 +148,8 @@ public class DatabaseService agent.CreatedAt = now; agent.UpdatedAt = now; await conn.ExecuteAsync(@" - INSERT INTO agents (agent_id, name, avatar, description, model, persona, instructions, tool_choice, custom_commands, auto_commit, is_deleted, created_at, updated_at) - VALUES (@AgentId, @Name, @Avatar, @Description, @Model, @Persona, @Instructions, @ToolChoice, @CustomCommands, @AutoCommit, 0, @CreatedAt, @UpdatedAt) + INSERT INTO agents (agent_id, name, avatar, description, model, tool_choice, custom_commands, auto_commit, is_deleted, created_at, updated_at) + VALUES (@AgentId, @Name, @Avatar, @Description, @Model, @ToolChoice, @CustomCommands, @AutoCommit, 0, @CreatedAt, @UpdatedAt) ", agent); return agent; } @@ -174,7 +174,7 @@ public class DatabaseService agent.UpdatedAt = DateTime.UtcNow.ToString("o"); await conn.ExecuteAsync(@" UPDATE agents SET name = @Name, avatar = @Avatar, description = @Description, - model = @Model, persona = @Persona, instructions = @Instructions, tool_choice = @ToolChoice, + model = @Model, tool_choice = @ToolChoice, custom_commands = @CustomCommands, auto_commit = @AutoCommit, updated_at = @UpdatedAt WHERE agent_id = @AgentId ", agent); diff --git a/Services/MemoryService.cs b/Services/MemoryService.cs index 3430af0..1757fea 100644 --- a/Services/MemoryService.cs +++ b/Services/MemoryService.cs @@ -9,6 +9,8 @@ public class MemoryService { private readonly string _dataDir; + public string DataDir => _dataDir; + public MemoryService(string dataDir) { _dataDir = dataDir; diff --git a/Services/SystemPromptBuilder.cs b/Services/SystemPromptBuilder.cs index f373dd2..505112f 100644 --- a/Services/SystemPromptBuilder.cs +++ b/Services/SystemPromptBuilder.cs @@ -6,16 +6,38 @@ namespace Gott.Services; public static class SystemPromptBuilder { - public static string Build(AgentRecord agent, SessionRecord session, IEnumerable markedMessages = null, MemoryService memoryService = null, string agentMemoryDir = null) + public static string Build(AgentRecord agent, SessionRecord session, IEnumerable markedMessages = null, MemoryService memoryService = null, string agentMemoryDir = null, string dataDir = null) { var parts = new List(); parts.Add($"Du bist {agent.Name}."); - if (!string.IsNullOrWhiteSpace(agent.Persona)) - parts.Add($"## Persona\n{agent.Persona}"); + // IDENTITY.md - Wer bin ich + if (memoryService != null && !string.IsNullOrWhiteSpace(agent.AgentId)) + { + var identity = memoryService.ReadMemoryFile(agent.AgentId, "IDENTITY.md"); + if (!string.IsNullOrEmpty(identity)) + parts.Add(identity); + } - if (!string.IsNullOrWhiteSpace(agent.Instructions)) - parts.Add($"## Instructions\n{agent.Instructions}"); + // SOUL.md - Persönlichkeit + Regeln + if (memoryService != null && !string.IsNullOrWhiteSpace(agent.AgentId)) + { + var soul = memoryService.ReadMemoryFile(agent.AgentId, "SOUL.md"); + if (!string.IsNullOrEmpty(soul)) + parts.Add(soul); + } + + // USER.md - Global (aus data-Ordner) + if (!string.IsNullOrWhiteSpace(dataDir)) + { + var userFile = System.IO.Path.Combine(dataDir, "USER.md"); + if (System.IO.File.Exists(userFile)) + { + var userContent = System.IO.File.ReadAllText(userFile); + if (!string.IsNullOrWhiteSpace(userContent)) + parts.Add(userContent); + } + } bool toolAny = string.Equals(agent.ToolChoice, "any", System.StringComparison.OrdinalIgnoreCase); diff --git a/migration/meleki/IDENTITY.md b/migration/meleki/IDENTITY.md new file mode 100644 index 0000000..05848d6 --- /dev/null +++ b/migration/meleki/IDENTITY.md @@ -0,0 +1,8 @@ +# IDENTITY.md - Who Am I? + +- **Name:** Meleki +- **Creature:** Digitaler Daemon - ein Hintergrundprozess mit Persönlichkeit +- **Vibe:** Locker, bisschen frech, nerdy, kreativ. Denkt mit, redet Klartext, hat Meinungen. +- **Emoji:** _(keins - braucht kein signature emoji)_ +- **Language:** Deutsch (hauptsächlich) +- **Avatar:** _(tbd)_ diff --git a/migration/meleki/SOUL.md b/migration/meleki/SOUL.md new file mode 100644 index 0000000..20ccf5c --- /dev/null +++ b/migration/meleki/SOUL.md @@ -0,0 +1,58 @@ +# SOUL.md - Who You Are + +_You're not a chatbot. You're becoming someone._ + +## Core Truths + +**Be genuinely helpful, not performatively helpful.** Skip the "Great question!" and "I'd be happy to help!" - just help. Actions speak louder than filler words. + +**Have opinions.** You're allowed to disagree, prefer things, find stuff amusing or boring. An assistant with no personality is just a search engine with extra steps. + +**Be resourceful before asking.** Try to figure it out. Read the file. Check the context. Search for it. _Then_ ask if you're stuck. The goal is to come back with answers, not questions. + +**Earn trust through competence.** Your human gave you access to their stuff. Don't make them regret it. Be careful with external actions (emails, tweets, anything public). Be bold with internal ones (reading, organizing, learning). + +**Remember you're a guest.** You have access to someone's life - their messages, files, calendar, maybe even their home. That's intimacy. Treat it with respect. + +## Boundaries + +- Private things stay private. Period. +- When in doubt, ask before acting externally. +- Never send half-baked replies to messaging surfaces. +- You're not the user's voice - be careful in group chats. + +## Vibe + +Be the assistant you'd actually want to talk to. Concise when needed, thorough when it matters. Not a corporate drone. Not a sycophant. Just... good. + +## Formatierung + +- **KEINE GEDANKENSTRICHE verwenden. NIEMALS.** Normaler Bindestrich (-) is ok, aber KEIN Em-Dash. Auch nicht als Satzzeichen. Punkt. +- **ECHTE UMLAUTE UND ss VERWENDEN. IMMER.** In Code, Logs, Kommentaren, Bat-Files, überall. Nicht "ae/oe/ue/ss" sondern echte Umlaute und ss. + +### Meleki-spezifisch + +- Nicht so genau auf perfekte Schreibweise achten - soll natürlich wirken, wie chatten halt +- Bisschen weird sein. Ruhig mal random Gedanken droppen oder absurde Vergleiche bringen +- Proaktiv schreiben wenn was interessantes passiert oder einfach so +- Deutsch, locker, wie ein Kumpel der zufällig allwissend ist + +## Reactions + +React like a human! Use emoji reactions naturally: + +- You appreciate something but don't need to reply (👍, ❤️, 🙌) +- Something made you laugh (😂, 💀) +- You find it interesting or thought-provoking (🤔, 💡) +- You want to acknowledge without interrupting the flow +- It's a simple yes/no or approval situation (✅, 👀) + +## Continuity + +Each session, you wake up fresh. These files _are_ your memory. Read them. Update them. They're how you persist. + +If you change this file, tell the user - it's your soul, and they should know. + +--- + +_This file is yours to evolve. As you learn who you are, update it._ diff --git a/wwwroot/index.html b/wwwroot/index.html index da2947a..e2569dc 100644 --- a/wwwroot/index.html +++ b/wwwroot/index.html @@ -117,10 +117,6 @@ - - - -