WorkspaceTests.cscsharp

Documentation

Version 3 design tests

Automated checks for chat, history, and Kokoro TTS (sanitizer + optional live speech).

Quick run

python src/Version3/DesignTests/run-design-tests.py
python src/Version3/DesignTests/run-design-tests.py --live
.\src\Version3\DesignTests\run-design-tests.ps1 -Live

What runs

| Suite | Needs network | Covers | |-------|----------------|--------| | ChatHistoryStoreTests | No | Same as V1 history XML | | OllamaClientHistoryTests | No | Client save/load | | KokoroTtsSanitizerTests | No | Markdown/emoji/URL stripping for speech | | OllamaLiveTests | Yes (--live) | Ollama chat | | KokoroTtsLiveTests | Yes (--live) | Kokoro model load + SpeakAsync |

First Kokoro live run may download ~320MB of model weights.

Console video (testers)

Record Version 3 console sessions (chat + TTS + history):

python src/TestManager/test_manager.py record v2 chat-tts --build

See src/TestManager/README.md.

All versions

python src/run-all-design-tests.py
python src/run-all-design-tests.py --live
using Xunit;using Agent.Core;using Agent.Core.ToolCalling;using LilithAgent = Lilith.Agent;using System.IO;namespace Agent.Core.DesignTests;public class WorkspaceTests{    [Fact]    public void Workspace_initializes_with_correct_folders()    {        var workspace = new Workspace("C:\\setup", "C:\\output");        Assert.Equal("C:\\setup", workspace.ConfigFolder);        Assert.Equal("C:\\output", workspace.OutputFolder);    }    [Fact]    public void Core_can_attach_and_retrieve_workspace()    {        var core = new Core();        Assert.Null(core.Workspace);        core.UseWorkspace("C:\\setup", "C:\\output");        Assert.NotNull(core.Workspace);        Assert.Equal("C:\\setup", core.Workspace.ConfigFolder);        Assert.Equal("C:\\output", core.Workspace.OutputFolder);    }    [Fact]    public void Workspace_tools_write_read_and_list_files_safely()    {        // 1. Setup temporary workspace directories        string tempConfig = Path.Combine(Path.GetTempPath(), "LilithTestConfig_" + Path.GetRandomFileName());        string tempOutput = Path.Combine(Path.GetTempPath(), "LilithTestOutput_" + Path.GetRandomFileName());        Directory.CreateDirectory(tempConfig);        Directory.CreateDirectory(tempOutput);        try        {            // Create some config files beforehand            File.WriteAllText(Path.Combine(tempConfig, "setup.json"), "{\"settings\": true}");            var workspace = new Workspace(tempConfig, tempOutput);            var lilith = new LilithAgent.Lilith(_ => { }) { Workspace = workspace };            var registry = new ToolRegistry();            lilith.RegisterWorkspaceTools(registry);            // 2. Test write tool            string writeArgs = "{\"path\": \"hello.txt\", \"content\": \"Hello Workspace!\"}";            Assert.True(registry.TryInvoke("write_workspace_file", writeArgs, out string writeResult));            Assert.Contains("Success", writeResult);            string writtenFilePath = Path.Combine(tempOutput, "hello.txt");            Assert.True(File.Exists(writtenFilePath));            Assert.Equal("Hello Workspace!", File.ReadAllText(writtenFilePath));            // 3. Test read tool (from output)            string readOutputArgs = "{\"path\": \"hello.txt\"}";            Assert.True(registry.TryInvoke("read_workspace_file", readOutputArgs, out string readOutputResult));            Assert.Equal("Hello Workspace!", readOutputResult);            // 4. Test read tool (from config)            string readConfigArgs = "{\"path\": \"setup.json\"}";            Assert.True(registry.TryInvoke("read_workspace_file", readConfigArgs, out string readConfigResult));            Assert.Equal("{\"settings\": true}", readConfigResult);            // 5. Test list tool            Assert.True(registry.TryInvoke("list_workspace_files", "{}", out string listResult));            Assert.Contains("setup.json", listResult);            Assert.Contains("hello.txt", listResult);            // 6. Test directory traversal restriction (security check)            string unsafeWriteArgs = "{\"path\": \"../unsafe.txt\", \"content\": \"hacked\"}";            Assert.True(registry.TryInvoke("write_workspace_file", unsafeWriteArgs, out string unsafeWriteResult));            Assert.Contains("Error: Access denied", unsafeWriteResult);            Assert.False(File.Exists(Path.Combine(tempOutput, "../unsafe.txt")));        }        finally        {            // Clean up            if (Directory.Exists(tempConfig)) Directory.Delete(tempConfig, true);            if (Directory.Exists(tempOutput)) Directory.Delete(tempOutput, true);        }    }}