Implement Skills feature: filesystem-based skills with agent assignment

- Add SkillService: scans data/skills/ directory, parses _meta.json and SKILL.md frontmatter
- Add SkillEndpoint: REST API for listing skills and managing agent-skill assignments
- Add agent_skills DB table for agent-to-skill mapping (only relation in DB, skills live on filesystem)
- Extend SystemPromptBuilder: inject assigned skills' SKILL.md content into system prompt
- Extend ChatEndpoint + SessionEndpoint: load agent skills and pass to prompt builder
- Frontend: skill checkboxes in agent form, API functions for skill management
- Add form.css styling for skill list items
This commit is contained in:
Meleki committed 2026-03-01 17:22:14 +01:00
1 parent b18dc78651
commit cf6caea2dc
11 files changed
+454 -6

No files matched your search

+25 -1
View File
@@ -6,7 +6,7 @@ namespace Gott.Services;
public static class SystemPromptBuilder
{
public static string Build(AgentRecord agent, SessionRecord session, IEnumerable<MessageRecord> markedMessages = null, MemoryService memoryService = null, string agentMemoryDir = null, string dataDir = null)
public static string Build(AgentRecord agent, SessionRecord session, IEnumerable<MessageRecord> markedMessages = null, MemoryService memoryService = null, string agentMemoryDir = null, string dataDir = null, IEnumerable<string> skillSlugs = null, SkillService skillService = null)
{
var parts = new List<string>();
@@ -69,6 +69,30 @@ Wenn der User auf eine bestimmte Zeile in einer Datei verweist (z.B. `[Datei: fo
if (!string.IsNullOrWhiteSpace(session.Context))
parts.Add($"## Kontext\n{session.Context}");
// Skills
if (skillSlugs != null && skillService != null)
{
var skillParts = new List<string>();
foreach (var slug in skillSlugs)
{
var skillPrompt = skillService.GetSkillPrompt(slug);
if (string.IsNullOrEmpty(skillPrompt)) continue;
var skill = skillService.GetSkill(slug);
var header = skill != null ? $"### {skill.Name}" : $"### {slug}";
if (skill?.Version != null) header += $" (v{skill.Version})";
header += $"\nPfad: `{skill?.Path ?? slug}`";
skillParts.Add($"{header}\n\n{skillPrompt}");
}
if (skillParts.Count > 0)
{
var skillSection = "## Skills\nDu hast folgende Skills zur Verfügung. Nutze sie über das `execute`-Tool wenn der User etwas anfragt, das ein Skill abdeckt.\n\n"
+ string.Join("\n\n---\n\n", skillParts);
parts.Add(skillSection);
}
}
// Memory-System
if (agent.UseMemory && memoryService != null && !string.IsNullOrWhiteSpace(agent.AgentId))
{