using UnityEngine; using UnityEditor; using System.Linq; using LLM.Editor.Core; using LLM.Editor.Data; using LLM.Editor.Helper; using LLM.Editor.Commands; using Newtonsoft.Json.Linq; using System.Threading.Tasks; using System.Collections.Generic; namespace LLM.Editor.Client { /// /// A mock client that simulates an LLM response for testing purposes. /// It now reads from an external JSON file to handle complex, multi-step test cases. /// public class DummyApiClient : ILlmApiClient { [System.Serializable] private class CommandResponse { public List commands; } private static DummyTestCase _activeTestCase; private static int _activeResponseStep; public Task SendPrompt(string prompt, List stagedContext) { var responseSheet = LoadResponseSheet(); if (responseSheet == null) { DisplayError("Could not load DummyResponses.json. Make sure it exists in a Resources folder."); return Task.CompletedTask; } // Find a test case whose trigger phrase is in the user's prompt. _activeTestCase = responseSheet.testCases.FirstOrDefault( c => prompt.ToLower().Contains(c.triggerPhrase.ToLower()) ); if (_activeTestCase != null) { Debug.Log($"[DummyApiClient] Triggered test case for: '{_activeTestCase.triggerPhrase}'"); _activeResponseStep = 0; // Start at the first response ExecuteStep(); } else { // Fallback to a default response if no test case matches. ExecuteCommandsFromJson(GetDefaultResponse()); } return Task.CompletedTask; } public Task SendFollowUp(string detailedContext) { if (_activeTestCase != null) { _activeResponseStep++; // Move to the next response 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."); ExecuteCommandsFromJson(GetDefaultResponse()); } return Task.CompletedTask; } private static void ExecuteStep() { if (_activeTestCase?.responses == null || _activeResponseStep >= _activeTestCase.responses.Count) { Debug.Log("[DummyApiClient] Test case finished or has no more steps."); _activeTestCase = null; // End the test case return; } var jsonResponse = _activeTestCase.responses[_activeResponseStep]; ExecuteCommandsFromJson(jsonResponse); } private static void ExecuteCommandsFromJson(string json) { var commandResponse = json.FromJson(); if (commandResponse?.commands != null) { CommandExecutor.SetQueue(commandResponse.commands); CommandExecutor.ExecuteNextCommand(); } else { DisplayError($"Failed to parse command structure from dummy JSON response: {json}"); } } private static DummyResponseSheet LoadResponseSheet() { TextAsset textAsset; var allMatches = AssetDatabase.FindAssets("t:textasset DummyResponses"); foreach (var match in allMatches) { var path = AssetDatabase.GUIDToAssetPath(match); textAsset = AssetDatabase.LoadAssetAtPath(path); if (textAsset) { return textAsset.text.FromJson(); } } textAsset = Resources.Load($"DummyResponses"); return !textAsset ? null : textAsset.text.FromJson(); } private static void DisplayError(string message) { var errorParams = new DisplayMessageParams { outcome = CommandOutcome.Error, message = $"[Dummy Client Error] {message}" }; var commandData = new CommandData { commandName = nameof(DisplayMessageCommand), jsonData = new JObject(errorParams) }; CommandExecutor.SetQueue(new List { commandData }); CommandExecutor.ExecuteNextCommand(); } private static string GetDefaultResponse() { return @"{ ""commands"": [ { ""commandName"": ""DisplayMessageCommand"", ""jsonData"": { ""outcome"": ""Success"", ""message"": ""[Dummy] No specific test case was triggered by your prompt."" } } ] }"; } } }