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); } }}
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