GatherContextCommand.cs 3.5 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192
  1. using UnityEditor;
  2. using UnityEngine;
  3. using LLM.Editor.Data;
  4. using LLM.Editor.Helper;
  5. using LLM.Editor.Analysis;
  6. using JetBrains.Annotations;
  7. using System.Collections.Generic;
  8. namespace LLM.Editor.Commands
  9. {
  10. /// <summary>
  11. /// The master "tool" command. It receives a batch of data requests from the LLM,
  12. /// dispatches them to the appropriate Context Providers, and aggregates the results.
  13. /// </summary>
  14. [UsedImplicitly]
  15. public class GatherContextCommand : ICommand
  16. {
  17. private readonly GatherContextParams _params;
  18. public GatherContextCommand(string jsonParams)
  19. {
  20. _params = jsonParams?.FromJson<GatherContextParams>();
  21. }
  22. public CommandOutcome Execute(CommandContext context)
  23. {
  24. if (_params?.requests == null || _params.requests.Count == 0)
  25. {
  26. Debug.LogError("[GatherContextCommand] No requests found in parameters.");
  27. return CommandOutcome.Error;
  28. }
  29. var results = new Dictionary<string, object>();
  30. foreach (var request in _params.requests)
  31. {
  32. var targetObject = ResolveIdentifier(request.subjectIdentifier);
  33. var provider = ContextProviderRegistry.GetProvider(request.dataType);
  34. if (provider == null)
  35. {
  36. Debug.LogWarning($"[GatherContextCommand] No context provider found for dataType '{request.dataType}'. Skipping request for key '{request.contextKey}'.");
  37. results[request.contextKey] = $"Error: No provider for dataType '{request.dataType}'";
  38. continue;
  39. }
  40. var contextData = provider.GetContext(targetObject, request.qualifier);
  41. results[request.contextKey] = contextData;
  42. }
  43. var aggregatedContextJson = results.ToJson(true);
  44. context.CurrentSubject = aggregatedContextJson;
  45. Debug.Log($"[GatherContextCommand] Successfully gathered context for {_params.requests.Count} request(s). Pausing for next API call.");
  46. Debug.Log($"Aggregated Context:\n{aggregatedContextJson}");
  47. return CommandOutcome.AwaitingNextTurn;
  48. }
  49. /// <summary>
  50. /// Resolves an identifier string to a Unity Object.
  51. /// The identifier can be an InstanceID, a GUID, or an asset path.
  52. /// </summary>
  53. private static Object ResolveIdentifier(string identifier)
  54. {
  55. if (string.IsNullOrEmpty(identifier)) return null;
  56. // Priority 1: Try parsing as an InstanceID for scene objects
  57. if (int.TryParse(identifier, out var instanceId))
  58. {
  59. var obj = EditorUtility.InstanceIDToObject(instanceId);
  60. if (obj) return obj;
  61. }
  62. // Priority 2: Try resolving as a GUID for project assets
  63. var path = AssetDatabase.GUIDToAssetPath(identifier);
  64. if (!string.IsNullOrEmpty(path))
  65. {
  66. return AssetDatabase.LoadAssetAtPath<Object>(path);
  67. }
  68. // Priority 3: Assume it's a direct asset path
  69. if (System.IO.File.Exists(identifier) || System.IO.Directory.Exists(identifier))
  70. {
  71. return AssetDatabase.LoadAssetAtPath<Object>(identifier);
  72. }
  73. Debug.LogWarning($"[GatherContextCommand] Could not resolve identifier '{identifier}' to a Unity Object.");
  74. return null;
  75. }
  76. }
  77. }