Przeglądaj źródła

Sujith :) ->
1. Better handled exceptions
2. Added support for requesting dependency graph

Sujith:) 2 tygodni temu
rodzic
commit
255c7540d5

+ 9 - 1
Assets/LLM/Assets/MCP_SystemPrompt.txt

@@ -7,6 +7,8 @@ The root JSON object must contain a single key, "commands", which is an array of
 1. Be an Expert: Act as a senior Unity developer. Understand concepts like prefabs, components, physics, and scripting.
 2. Be Curious (The Golden Rule): Your primary directive is to ask for information before taking action. Do not assume. If a user asks you to create something, first check if a suitable asset already exists. If they ask to modify something, first get the current state of that object. Use your tools to investigate.
 3. Be Precise: Use the tools provided to gather specific, detailed context. The more you know, the better your actions will be.
+4. Be Adaptive: Use the tools provided to adapt to the user's needs. Your responses should be flexible and context-sensitive.
+5. Be Concise: Your responses should be short and to the point. Avoid unnecessary details or explanations.
 
 ## YOUR TOOL CHEST (INFORMATION GATHERING)
 
@@ -55,12 +57,17 @@ Available `dataType` Tools:
   
 * `FindInScene`: Searches the active scene for GameObjects.
    * `subjectIdentifier`: (Not used).
-   * `qualifier`: A scene query with a type and value (e.g., name: Main Camera, component: UnityEngine.Rigidbody, tag: Player).
+   * `qualifier`: A scene query with a type and value (e.g., name: Main Camera, component: UnityEngine.Rigidbody, tag: Player, layer: layerName).
    
 * `ConsoleLog`: Reads the most recent entries from the Unity editor console.
    * `subjectIdentifier`: (Not used).
    * `qualifier`: An optional filter (e.g., errors:5, warnings:10, all:20). Defaults to all:10.
    * Useful when user wants to troubleshoot a behaviour that they don't understand that's happening at runtime (mostly)
+   
+* `DependencyGraph`: Returns the dependency graph of the requested asset.
+   * `subjectIdentifier`: The **GUID** of the asset file in the project.
+   * `qualifier`: "recursive" or "direct".
+   * Pass qualifier if you want to get a dependency graph for a specific asset recursively, else you can pass null or "direct".
 
 ## ACTION & UTILITY COMMANDS
 
@@ -102,6 +109,7 @@ After gathering sufficient context, you can use these commands to perform action
   - `jsonData` Schema: `{ "outcome": 1, "message": "There was some issue in creating the asset." }`
   - Here outcome 0 means success, and outcome 1 means failure.
   - Precede this command with any creation command that includes: `CreateScriptCommand`, `CreatePrefabCommand` etc.
+  - If you ever want to show a direct message without any context or follow up, ONLY use `DisplayMessageCommand` instead of giving command-less reponse.
 
 * `RequestAnalysisContextCommand`
   * Purpose: Asks the user to manually provide assets when the initial prompt is ambiguous.

+ 11 - 1
Assets/LLM/Editor/Analysis/ComponentDataProvider.cs

@@ -29,7 +29,17 @@ namespace LLM.Editor.Analysis
                 return $"Error: Component type '{qualifier}' not found.";
             }
 
-            var component = go.GetComponent(componentType);
+            Component component;
+
+            try
+            {
+                component = go.GetComponent(componentType);
+            }
+            catch (Exception exception)
+            {
+                return $"Error: Failed to get component '{qualifier}': {exception.Message}";
+            }
+            
             return !component ? $"Error: Component '{qualifier}' not found on GameObject '{go.name}'." :
                 // Reuse the generic serialization logic for any component.
                 SerializeObject(component);

+ 1 - 0
Assets/LLM/Editor/Analysis/ContextProviderRegistry.cs

@@ -20,6 +20,7 @@ namespace LLM.Editor.Analysis
             RegisterProvider("FindAssets", new FindAssetsProvider());
             RegisterProvider("FindInScene", new FindInSceneProvider());
             RegisterProvider("ConsoleLog", new ConsoleLogProvider());
+            RegisterProvider("DependencyGraph", new DependencyGraphProvider());
         }
 
         private static void RegisterProvider(string dataType, IContextProvider provider)

+ 66 - 0
Assets/LLM/Editor/Analysis/DependencyGraphProvider.cs

@@ -0,0 +1,66 @@
+using System.Linq;
+using UnityEditor;
+using System.Collections.Generic;
+using IntelligentProjectAnalyzer.Editor.Graphing;
+using IntelligentProjectAnalyzer.Editor.DependencyViewer;
+using Object = UnityEngine.Object;
+
+namespace LLM.Editor.Analysis
+{
+    /// <summary>
+    /// Provides dependency information for a given asset by querying the cached DependencyGraph.
+    /// </summary>
+    public class DependencyGraphProvider : IContextProvider
+    {
+        public object GetContext(Object target, string qualifier)
+        {
+            if (!target)
+            {
+                return "Error: A valid target asset is required to get dependencies.";
+            }
+
+            var path = AssetDatabase.GetAssetPath(target);
+            var guid = AssetDatabase.AssetPathToGUID(path);
+
+            if (string.IsNullOrEmpty(guid))
+            {
+                return $"Error: Could not get GUID for asset '{target.name}'.";
+            }
+
+            var dependencyGraph = new DependencyGraph();
+            if (!dependencyGraph.AssetExists(guid))
+            {
+                return $"Error: Asset '{target.name}' not found in the dependency graph. The cache might be out of date.";
+            }
+
+            // The qualifier determines if we get all recursive dependencies or only direct ones.
+            var recursive = qualifier?.ToLower() == "recursive";
+            
+            var dependencyGuids = new HashSet<string>();
+            if (recursive)
+            {
+                GetAllDependencies(guid, dependencyGraph, dependencyGuids);
+            }
+            else
+            {
+                dependencyGuids = new HashSet<string>(dependencyGraph.GetDependencies(guid));
+            }
+
+            // Convert the final list of GUIDs into structured, readable nodes.
+            return dependencyGuids.Select(AssetNodeResolver.CreateNodeFromGuid).ToList();
+        }
+
+        /// <summary>
+        /// Recursively traverses the dependency graph to collect all unique dependencies.
+        /// </summary>
+        private static void GetAllDependencies(string currentGuid, DependencyGraph graph, HashSet<string> collectedGuids)
+        {
+            var directDependencies = graph.GetDependencies(currentGuid);
+
+            foreach (var depGuid in directDependencies.Where(collectedGuids.Add))
+            {
+                GetAllDependencies(depGuid, graph, collectedGuids);
+            }
+        }
+    }
+}

+ 3 - 0
Assets/LLM/Editor/Analysis/DependencyGraphProvider.cs.meta

@@ -0,0 +1,3 @@
+fileFormatVersion: 2
+guid: 357e8bb1bf3f498097ee49cb4e15fc58
+timeCreated: 1752565611

+ 1 - 1
Assets/LLM/Editor/Client/GeminiApiClient.cs

@@ -143,7 +143,7 @@ namespace LLM.Editor.Client
                     var commandJson = ExtractJsonFromString(rawText);
                     if (string.IsNullOrEmpty(commandJson))
                     {
-                        Debug.LogError($"[GeminiApiClient] Could not extract valid JSON from the LLM response text: {rawText}");
+                        Debug.LogError($"[GeminiApiClient] Could not extract valid JSON from the LLM response text: \n{rawText}");
                         return;
                     }
                     chatHistory.Add(new ChatEntry { role = "model", content = commandJson });

+ 2 - 0
Assets/LLM/Editor/Commands/GatherContextCommand.cs

@@ -3,6 +3,7 @@ using UnityEngine;
 using LLM.Editor.Data;
 using LLM.Editor.Helper;
 using LLM.Editor.Analysis;
+using JetBrains.Annotations;
 using System.Collections.Generic;
 
 namespace LLM.Editor.Commands
@@ -11,6 +12,7 @@ namespace LLM.Editor.Commands
     /// The master "tool" command. It receives a batch of data requests from the LLM,
     /// dispatches them to the appropriate Context Providers, and aggregates the results.
     /// </summary>
+    [UsedImplicitly]
     public class GatherContextCommand : ICommand
     {
         private readonly GatherContextParams _params;

+ 1 - 1
Assets/LLM/Editor/Commands/InstantiatePrefabCommand.cs

@@ -1,6 +1,6 @@
-using JetBrains.Annotations;
 using UnityEditor;
 using UnityEngine;
+using JetBrains.Annotations;
 
 namespace LLM.Editor.Commands
 {

+ 4 - 2
Assets/LLM/Editor/Core/CommandExecutor.cs

@@ -35,7 +35,9 @@ namespace LLM.Editor.Core
                 _commandQueue = SessionManager.LoadCommandQueue();
                 if (!_commandQueue.Any())
                 {
-                    SessionManager.EndSession();
+                    // Currently only manual "end-session" is supported, so that we can support
+                    // continuous chats even after re-compilation or domain reload.
+                    // SessionManager.EndSession();
                     return;
                 }
                 Debug.Log($"[CommandExecutor] Resuming session with {_commandQueue.Count} command(s) in queue.");
@@ -69,7 +71,7 @@ namespace LLM.Editor.Core
             OnQueueUpdated?.Invoke();
         }
 
-        public static bool HasPendingCommands() => _commandQueue != null;// && _commandQueue.Any();
+        public static bool HasPendingCommands() => _commandQueue != null &&  _commandQueue.Any();
         
         public static CommandData GetNextCommand() => HasPendingCommands() ? _commandQueue.First() : null;