using System;
using System.Linq;
using UnityEngine;
using LLM.Editor.Core;
using LLM.Editor.Data;
using System.Threading;
using LLM.Editor.Commands;
using System.Threading.Tasks;
using System.Collections.Generic;
using LLM.Editor.Tests.Integration;
namespace LLM.Editor.Client
{
///
/// A mock client that simulates an LLM response for testing purposes.
/// It now discovers and runs test cases from C# classes that implement IDummyTestCase.
///
public class DummyApiClient : ILlmApiClient
{
private static List _testCases;
private static bool _testCasesLoaded;
private IDummyTestCase _activeTestCase;
private int _activeResponseStep;
public static List GetTestCases()
{
if (!_testCasesLoaded)
{
DiscoverTestCases();
}
return _testCases;
}
private static void DiscoverTestCases()
{
_testCases = new List();
var testCaseType = typeof(IDummyTestCase);
var assemblies = AppDomain.CurrentDomain.GetAssemblies();
foreach (var assembly in assemblies)
{
try
{
var types = assembly.GetTypes();
foreach (var type in types)
{
if (testCaseType.IsAssignableFrom(type) && !type.IsInterface && !type.IsAbstract)
{
var instance = (IDummyTestCase)Activator.CreateInstance(type);
_testCases.Add(instance);
}
}
}
catch (Exception e)
{
Debug.LogWarning($"[DummyApiClient] Could not inspect assembly {assembly.FullName} for test cases: {e.Message}");
}
}
_testCases = _testCases.OrderBy(tc => tc.TriggerPhrase).ToList();
_testCasesLoaded = true;
Debug.Log($"[DummyApiClient] Discovered {_testCases.Count} C# test cases.");
}
public Task Initialize()
{
// Dummy client needs no async initialization.
return Task.FromResult(true);
}
public async Task SendPrompt(string prompt, List stagedContext, CancellationToken cancellationToken = default)
{
if (!_testCasesLoaded) DiscoverTestCases();
_activeTestCase = _testCases.FirstOrDefault(
c => prompt.Equals(c.TriggerPhrase, StringComparison.Ordinal)
);
// Simulate network delay
await Task.Delay(500, cancellationToken);
if (cancellationToken.IsCancellationRequested) return;
if (_activeTestCase != null)
{
Debug.Log($"[DummyApiClient] Triggered test case for: '{_activeTestCase.TriggerPhrase}'");
_activeResponseStep = 0;
ExecuteStep();
}
else
{
DisplayError("No test case was triggered by your prompt.");
}
}
public async Task SendFollowUp(string detailedContext, CancellationToken cancellationToken = default)
{
// Simulate network delay
await Task.Delay(500, cancellationToken);
if (cancellationToken.IsCancellationRequested) return;
if (_activeTestCase != null)
{
_activeResponseStep++;
Debug.Log($"[DummyApiClient] Executing follow-up step #{_activeResponseStep + 1} for test case: '{_activeTestCase.TriggerPhrase}'");
ExecuteStep();
}
else
{
Debug.LogWarning("[DummyApiClient] Received a follow-up call, but no active test case was found.");
DisplayError("No active test case for follow-up.");
}
}
public string GetAuthToken()
{
return "dummy-token";
}
private void ExecuteStep()
{
var commandSteps = _activeTestCase?.GetCommandSteps();
if (commandSteps == null || _activeResponseStep >= commandSteps.Count)
{
Debug.Log("[DummyApiClient] Test case finished or has no more steps.");
_activeTestCase = null; // End the test case
return;
}
var commands = commandSteps[_activeResponseStep];
CommandExecutor.SetQueue(commands, _activeTestCase.TriggerPhrase);
}
private void DisplayError(string message)
{
var commandData = new CommandData
{
commandName = nameof(DisplayMessageCommand),
jsonData = new Newtonsoft.Json.Linq.JObject
{
["outcome"] = "Error",
["message"] = $"[Dummy Client Error] {message}"
}
};
CommandExecutor.SetQueue(new List { commandData }, "Error");
}
}
}