ScenarioSystem/ScenarioXml.cscsharp

Documentation

Lilith (Version 3)

Version 3 Lilith agent library. Entry point: Lilith.cs with partials under Boot/, Chat/, Ollama/, and SystemPrompt/.

Build the solution or run python ../Build-v3.py from this tree.

using System.Xml.Linq;namespace Lilith.Agent.ScenarioSystem;internal sealed record ScenarioXml(    string Id,    string Title,    bool RunOnBoot,    IReadOnlyList<ScenarioStepXml> Steps);internal abstract record ScenarioStepXml(string Kind);/// <summary>Chat step — same idea as TestManager &lt;Step&gt; prompts.</summary>internal sealed record ChatStepXml(string Prompt, string? ExpectContains, string? ExpectEquals) : ScenarioStepXml("chat");internal static class ScenarioXmlParser{    public static ScenarioXml Parse(string xml)    {        var doc = XDocument.Parse(xml);        var root = doc.Root ?? throw new InvalidOperationException("Scenario XML missing root element.");        if (!string.Equals(root.Name.LocalName, "Scenario", StringComparison.OrdinalIgnoreCase))            throw new InvalidOperationException("Scenario XML root must be <Scenario>.");        string id = root.Attribute("id")?.Value?.Trim() ?? "";        string title = root.Attribute("title")?.Value?.Trim() ?? id;        bool runOnBoot = string.Equals(root.Attribute("run_on")?.Value, "boot", StringComparison.OrdinalIgnoreCase);        if (string.IsNullOrWhiteSpace(id))            throw new InvalidOperationException("<Scenario> requires id attribute.");        var steps = new List<ScenarioStepXml>();        foreach (var el in root.Elements())        {            if (!el.Name.LocalName.Equals("Step", StringComparison.OrdinalIgnoreCase))                throw new InvalidOperationException($"Scenario XML only supports <Step> elements (found <{el.Name}>).");            string prompt = el.Value.Trim();            if (string.IsNullOrWhiteSpace(prompt))                throw new InvalidOperationException("<Step> must not be empty.");            steps.Add(new ChatStepXml(                prompt,                el.Attribute("expect_contains")?.Value?.Trim(),                el.Attribute("expect_equals")?.Value?.Trim()));        }        if (steps.Count == 0)            throw new InvalidOperationException("Scenario has no steps.");        return new ScenarioXml(id, title, runOnBoot, steps);    }}