feat(worker): session skill registry (install/update/remove, pinned clone)

This commit is contained in:
Mika Kuns
2026-07-23 16:47:14 +02:00
committed by mika kuns
parent 54cdaf89d5
commit dea2b7db8b
8 changed files with 611 additions and 0 deletions
@@ -0,0 +1,62 @@
namespace ClaudeDo.Worker.Skills;
internal static class SkillFrontmatter
{
public sealed record ParsedFrontmatter(string Name, string Description);
/// <summary>
/// Parses the YAML frontmatter block (between the first two "---" lines) of a SKILL.md
/// file, extracting "name" (required) and "description" (optional). The description may
/// be a folded scalar ("description: >"), whose indented continuation lines are joined
/// with spaces into a single string.
/// </summary>
public static ParsedFrontmatter Parse(string skillMdPath)
{
var lines = File.ReadAllLines(skillMdPath);
if (lines.Length == 0 || lines[0].Trim() != "---")
throw new InvalidOperationException($"'{skillMdPath}' has no YAML frontmatter block.");
string? name = null;
var description = "";
var i = 1;
for (; i < lines.Length; i++)
{
var line = lines[i];
if (line.Trim() == "---") break;
if (line.StartsWith("name:", StringComparison.Ordinal))
{
name = line["name:".Length..].Trim().Trim('"', '\'');
}
else if (line.StartsWith("description:", StringComparison.Ordinal))
{
var rest = line["description:".Length..].Trim();
if (rest == ">" || rest == ">-" || rest == "|" || rest == "|-")
{
var folded = new List<string>();
var j = i + 1;
for (; j < lines.Length; j++)
{
var contLine = lines[j];
if (contLine.Trim() == "---") break;
if (contLine.Length == 0) continue;
if (!char.IsWhiteSpace(contLine[0])) break;
folded.Add(contLine.Trim());
}
description = string.Join(" ", folded);
i = j - 1;
}
else
{
description = rest.Trim('"', '\'');
}
}
}
if (string.IsNullOrWhiteSpace(name))
throw new InvalidOperationException($"'{skillMdPath}' frontmatter is missing required 'name'.");
return new ParsedFrontmatter(name, description);
}
}