@atelierai/uco 1.0.7 → 1.0.8

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (87) hide show
  1. package/CHANGELOG.md +11 -0
  2. package/package.json +1 -1
  3. package/vendor/plugin/com.atelierai.unity.copilot/Editor/DependencyResolver/NuGetConfig.cs +132 -132
  4. package/vendor/plugin/com.atelierai.unity.copilot/Editor/DependencyResolver/NuGetDependencyResolver.cs +237 -237
  5. package/vendor/plugin/com.atelierai.unity.copilot/Editor/DependencyResolver/NuGetDownloader.cs +82 -82
  6. package/vendor/plugin/com.atelierai.unity.copilot/Editor/Scripts/API/Resource/MenuItems.cs +247 -247
  7. package/vendor/plugin/com.atelierai.unity.copilot/Editor/Scripts/API/Resource/ToolGroups.cs +153 -153
  8. package/vendor/plugin/com.atelierai.unity.copilot/Editor/Scripts/API/SystemTool/Skills.Create.SkillBody.cs +155 -155
  9. package/vendor/plugin/com.atelierai.unity.copilot/Editor/Scripts/API/Tool/Console.GetLogs.cs +95 -95
  10. package/vendor/plugin/com.atelierai.unity.copilot/Editor/Scripts/API/Tool/Docs.HttpFetcher.cs +139 -139
  11. package/vendor/plugin/com.atelierai.unity.copilot/Editor/Scripts/API/Tool/Instance.ListAll.cs +72 -72
  12. package/vendor/plugin/com.atelierai.unity.copilot/Editor/Scripts/API/Tool/PathReadHelper.cs +106 -106
  13. package/vendor/plugin/com.atelierai.unity.copilot/Editor/Scripts/API/Tool/Script.Validate.cs +252 -252
  14. package/vendor/plugin/com.atelierai.unity.copilot/Editor/Scripts/API/Tool/Tests/TestResultCollector.cs +537 -537
  15. package/vendor/plugin/com.atelierai.unity.copilot/Editor/Scripts/API/Tool/Tests.cs +400 -400
  16. package/vendor/plugin/com.atelierai.unity.copilot/Editor/Scripts/Branding/ProductInfo.cs +62 -62
  17. package/vendor/plugin/com.atelierai.unity.copilot/Editor/Scripts/CopilotServerManager.cs +1034 -1034
  18. package/vendor/plugin/com.atelierai.unity.copilot/Editor/Scripts/Skills/Skill_InitialSetup.cs +197 -197
  19. package/vendor/plugin/com.atelierai.unity.copilot/Editor/Scripts/Startup.Editor.cs +201 -201
  20. package/vendor/plugin/com.atelierai.unity.copilot/Editor/Scripts/Startup.cs +67 -67
  21. package/vendor/plugin/com.atelierai.unity.copilot/Editor/Scripts/UI/Window/CopilotListWindowBase.cs +393 -393
  22. package/vendor/plugin/com.atelierai.unity.copilot/Editor/Scripts/UI/Window/CopilotWindowBase.cs +113 -113
  23. package/vendor/plugin/com.atelierai.unity.copilot/Editor/Scripts/UI/Window/MainWindowEditor.Connection.cs +3 -3
  24. package/vendor/plugin/com.atelierai.unity.copilot/Editor/Scripts/UI/Window/MainWindowEditor.CopilotFeatures.cs +195 -195
  25. package/vendor/plugin/com.atelierai.unity.copilot/Editor/Scripts/UI/Window/MainWindowEditor.CopilotServer.cs +20 -20
  26. package/vendor/plugin/com.atelierai.unity.copilot/Editor/Scripts/UI/Window/MainWindowEditor.CreateGUI.cs +354 -354
  27. package/vendor/plugin/com.atelierai.unity.copilot/Editor/Scripts/UI/Window/MainWindowEditor.cs +78 -78
  28. package/vendor/plugin/com.atelierai.unity.copilot/Editor/Scripts/UI/Window/MainWindowInitializer.cs +47 -47
  29. package/vendor/plugin/com.atelierai.unity.copilot/Editor/Scripts/UI/Window/SerializationCheckWindow.cs +190 -190
  30. package/vendor/plugin/com.atelierai.unity.copilot/Editor/Scripts/UnityCopilotPluginEditor.Build.cs +91 -91
  31. package/vendor/plugin/com.atelierai.unity.copilot/Editor/Scripts/UnityCopilotPluginEditor.Config.cs +298 -298
  32. package/vendor/plugin/com.atelierai.unity.copilot/Editor/Scripts/UnityCopilotPluginEditor.Static.cs +296 -296
  33. package/vendor/plugin/com.atelierai.unity.copilot/Editor/Scripts/UnityCopilotPluginEditor.cs +69 -69
  34. package/vendor/plugin/com.atelierai.unity.copilot/Editor/Scripts/Utils/PackageUtils.cs +168 -168
  35. package/vendor/plugin/com.atelierai.unity.copilot/Editor/Scripts/Utils/PrefsKeyMigration.cs +119 -119
  36. package/vendor/plugin/com.atelierai.unity.copilot/Editor/Scripts/Utils/SafeDefaultsGuard.cs +180 -180
  37. package/vendor/plugin/com.atelierai.unity.copilot/Editor/Scripts/Utils/ScriptUtils.cs +229 -229
  38. package/vendor/plugin/com.atelierai.unity.copilot/Editor/Scripts/Utils/ToolsManifestGenerator.cs +200 -200
  39. package/vendor/plugin/com.atelierai.unity.copilot/Editor/Scripts/Utils/UnityAuthoringAdapters.cs +1467 -1467
  40. package/vendor/plugin/com.atelierai.unity.copilot/Editor/Scripts/Utils/UnityAuthoringSafetyReloadGuard.cs +65 -65
  41. package/vendor/plugin/com.atelierai.unity.copilot/Editor/Scripts/Utils/UnityCopilotUpdateProjectSettings.cs +66 -66
  42. package/vendor/plugin/com.atelierai.unity.copilot/Plugins/ReflectorNet.dll +0 -0
  43. package/vendor/plugin/com.atelierai.unity.copilot/Plugins/Uco.Framework.Common.dll +0 -0
  44. package/vendor/plugin/com.atelierai.unity.copilot/Plugins/Uco.Framework.dll +0 -0
  45. package/vendor/plugin/com.atelierai.unity.copilot/Runtime/Converter/Json/Structures/EntityIdConverter.cs +120 -120
  46. package/vendor/plugin/com.atelierai.unity.copilot/Runtime/Data/GameObjectMetadata.cs +110 -110
  47. package/vendor/plugin/com.atelierai.unity.copilot/Runtime/Data/GameObjectMetadata.pre-Unity.6.5.cs +110 -110
  48. package/vendor/plugin/com.atelierai.unity.copilot/Runtime/Unity/Logs/FileLogStorage.cs +547 -547
  49. package/vendor/plugin/com.atelierai.unity.copilot/Runtime/UnityCopilotPlugin.Build.cs +243 -243
  50. package/vendor/plugin/com.atelierai.unity.copilot/Runtime/UnityCopilotPlugin.Config.cs +3 -3
  51. package/vendor/plugin/com.atelierai.unity.copilot/Runtime/UnityCopilotPlugin.cs +295 -295
  52. package/vendor/plugin/com.atelierai.unity.copilot/Runtime/UnityCopilotPluginBuilder.cs +105 -105
  53. package/vendor/plugin/com.atelierai.unity.copilot/Runtime/UnityCopilotPluginRuntime.Static.cs +155 -155
  54. package/vendor/plugin/com.atelierai.unity.copilot/Runtime/UnityCopilotPluginRuntime.cs +59 -59
  55. package/vendor/plugin/com.atelierai.unity.copilot/Runtime/Utils/EnvironmentUtils.cs +11 -11
  56. package/vendor/plugin/com.atelierai.unity.copilot/Tests/Editor/AtomicApi/AtomicApiTestFixtures.cs +99 -99
  57. package/vendor/plugin/com.atelierai.unity.copilot/Tests/Editor/AtomicApi/TryModifyAtTests.cs +227 -227
  58. package/vendor/plugin/com.atelierai.unity.copilot/Tests/Editor/AuthoringSafetyPilotTests.cs +1050 -1050
  59. package/vendor/plugin/com.atelierai.unity.copilot/Tests/Editor/DependencyResolver/NuGetLegacyMigrationTests.cs +304 -304
  60. package/vendor/plugin/com.atelierai.unity.copilot/Tests/Editor/Environment/EnvironmentUtilsTests.cs +1 -1
  61. package/vendor/plugin/com.atelierai.unity.copilot/Tests/Editor/ReflectionConverter/BlacklistTypeTests.cs +416 -416
  62. package/vendor/plugin/com.atelierai.unity.copilot/Tests/Editor/ReflectionConverter/DataFieldScriptableObjectPopulationTests.cs +172 -172
  63. package/vendor/plugin/com.atelierai.unity.copilot/Tests/Editor/ReflectionConverter/DataFieldScriptableObjectPopulationTests.pre-Unity.6.5.cs +169 -169
  64. package/vendor/plugin/com.atelierai.unity.copilot/Tests/Editor/ReflectionConverter/DataPopulationTests.cs +182 -182
  65. package/vendor/plugin/com.atelierai.unity.copilot/Tests/Editor/ReflectionConverter/DataPopulationTests.pre-Unity.6.5.cs +179 -179
  66. package/vendor/plugin/com.atelierai.unity.copilot/Tests/Editor/ReflectionConverter/DataPropertyPopulationTests.cs +175 -175
  67. package/vendor/plugin/com.atelierai.unity.copilot/Tests/Editor/ReflectionConverter/DataPropertyPopulationTests.pre-Unity.6.5.cs +174 -174
  68. package/vendor/plugin/com.atelierai.unity.copilot/Tests/Editor/ReflectionConverter/DataPropertyScriptableObjectPopulationTests.cs +171 -171
  69. package/vendor/plugin/com.atelierai.unity.copilot/Tests/Editor/ReflectionConverter/DataPropertyScriptableObjectPopulationTests.pre-Unity.6.5.cs +170 -170
  70. package/vendor/plugin/com.atelierai.unity.copilot/Tests/Editor/Tool/Assets/AssetsCreateFolderTests.cs +243 -243
  71. package/vendor/plugin/com.atelierai.unity.copilot/Tests/Editor/Tool/Assets/AssetsMaterialTests.cs +101 -101
  72. package/vendor/plugin/com.atelierai.unity.copilot/Tests/Editor/Tool/Assets/AssetsPrefabCreateTests.cs +348 -348
  73. package/vendor/plugin/com.atelierai.unity.copilot/Tests/Editor/Tool/Assets/AssetsPrefabCreateTests.pre-Unity.6.5.cs +348 -348
  74. package/vendor/plugin/com.atelierai.unity.copilot/Tests/Editor/Tool/Assets/AssetsShaderTests.cs +194 -194
  75. package/vendor/plugin/com.atelierai.unity.copilot/Tests/Editor/Tool/PathBasedToolTests.cs +573 -573
  76. package/vendor/plugin/com.atelierai.unity.copilot/Tests/Editor/Tool/PathBasedToolTests.pre-Unity.6.5.cs +513 -513
  77. package/vendor/plugin/com.atelierai.unity.copilot/Tests/Editor/Tool/Screenshot/ScreenshotCameraTests.cs +154 -154
  78. package/vendor/plugin/com.atelierai.unity.copilot/Tests/Editor/Tool/Screenshot/ScreenshotCameraTests.pre-Unity.6.5.cs +154 -154
  79. package/vendor/plugin/com.atelierai.unity.copilot/Tests/Editor/Tool/Screenshot/ScreenshotGameViewTests.cs +164 -164
  80. package/vendor/plugin/com.atelierai.unity.copilot/Tests/Editor/Tool/Screenshot/ScreenshotSceneViewTests.cs +155 -155
  81. package/vendor/plugin/com.atelierai.unity.copilot/Tests/Editor/Tool/ToolParameterTests.cs +56 -56
  82. package/vendor/plugin/com.atelierai.unity.copilot/Tests/Editor/Tool/ToolThreadSafetyTests.cs +651 -651
  83. package/vendor/plugin/com.atelierai.unity.copilot/Tests/Editor/Tool/ToolThreadSafetyTests.pre-Unity.6.5.cs +651 -651
  84. package/vendor/plugin/com.atelierai.unity.copilot/Tests/Editor/ToolBatchExecutionIntegrationTests.cs +407 -407
  85. package/vendor/plugin/com.atelierai.unity.copilot/Tests/Editor/{McpPluginTests.cs → UcoPluginTests.cs} +105 -105
  86. package/vendor/plugin/com.atelierai.unity.copilot/package.json +1 -1
  87. /package/vendor/plugin/com.atelierai.unity.copilot/Tests/Editor/{McpPluginTests.cs.meta → UcoPluginTests.cs.meta} +0 -0
@@ -1,69 +1,69 @@
1
- /*
2
- ┌──────────────────────────────────────────────────────────────────┐
3
- │ Author: Ivan Murzak (https://github.com/IvanMurzak) │
4
- │ Repository: GitHub (https://github.com/IvanMurzak/Unity-MCP) │
5
- │ Copyright (c) 2025 Ivan Murzak │
6
- │ Licensed under the Apache License, Version 2.0. │
7
- │ See the LICENSE file in the project root for more information. │
8
- └──────────────────────────────────────────────────────────────────┘
9
- */
10
-
11
- #nullable enable
12
- using com.AtelierAI.Unity.Copilot.Runtime.Utils;
13
-
14
- namespace com.AtelierAI.Unity.Copilot
15
- {
16
- /// <summary>
17
- /// Editor-only singleton that owns the persistent MCP connection used
18
- /// by Unity Editor tooling (Copilot window, configurators, etc.).
19
- /// Lives in the Editor assembly — not accessible from Runtime code.
20
- /// </summary>
21
- public partial class UnityCopilotPluginEditor : UnityCopilotPlugin
22
- {
23
- /// <summary>
24
- /// Captures runtime overrides (env vars / CLI flags) that were layered on top of the
25
- /// on-disk config during construction. Used by <see cref="Save"/> to round-trip the
26
- /// disk-baseline values to disk while keeping the runtime overrides on the in-memory
27
- /// config — runtime-only overrides MUST NOT leak into the persisted JSON.
28
- /// </summary>
29
- internal EnvironmentUtils.OverrideRecord RuntimeOverrides { get; private set; }
30
- = new EnvironmentUtils.OverrideRecord();
31
-
32
- protected UnityCopilotPluginEditor() : base()
33
- {
34
- var config = GetOrCreateConfig(out var wasCreated);
35
- unityConnectionConfig = config;
36
- ApplyLogLevel(unityConnectionConfig.LogLevel);
37
- // Layered loader: disk values are already on `config`; env vars and CLI flags
38
- // are applied here as runtime overrides. The OverrideRecord captures the
39
- // disk-baseline values so Save() can persist them without leaking the overrides.
40
- RuntimeOverrides = EnvironmentUtils.ApplyEnvironmentOverrides(unityConnectionConfig);
41
- if (wasCreated)
42
- Save();
43
- IncrementSingletonCount();
44
- }
45
-
46
- public void Validate()
47
- {
48
- var changed = false;
49
- var data = unityConnectionConfig ??= new UnityConnectionConfig();
50
-
51
- if (string.IsNullOrEmpty(data.LocalHost))
52
- {
53
- data.LocalHost = UnityConnectionConfig.DefaultHost;
54
- changed = true;
55
- }
56
-
57
- // Data was changed during validation, need to notify subscribers
58
- if (changed)
59
- NotifyChanged(data);
60
- }
61
-
62
- public override void Dispose()
63
- {
64
- DecrementSingletonCount();
65
- base.Dispose();
66
- DisposeMcpPluginInstance();
67
- }
68
- }
69
- }
1
+ /*
2
+ ┌──────────────────────────────────────────────────────────────────┐
3
+ │ Author: Ivan Murzak (https://github.com/IvanMurzak) │
4
+ │ Repository: GitHub (https://github.com/IvanMurzak/Unity-MCP) │
5
+ │ Copyright (c) 2025 Ivan Murzak │
6
+ │ Licensed under the Apache License, Version 2.0. │
7
+ │ See the LICENSE file in the project root for more information. │
8
+ └──────────────────────────────────────────────────────────────────┘
9
+ */
10
+
11
+ #nullable enable
12
+ using com.AtelierAI.Unity.Copilot.Runtime.Utils;
13
+
14
+ namespace com.AtelierAI.Unity.Copilot
15
+ {
16
+ /// <summary>
17
+ /// Editor-only singleton that owns the persistent Uco connection used
18
+ /// by Unity Editor tooling (Copilot window, configurators, etc.).
19
+ /// Lives in the Editor assembly — not accessible from Runtime code.
20
+ /// </summary>
21
+ public partial class UnityCopilotPluginEditor : UnityCopilotPlugin
22
+ {
23
+ /// <summary>
24
+ /// Captures runtime overrides (env vars / CLI flags) that were layered on top of the
25
+ /// on-disk config during construction. Used by <see cref="Save"/> to round-trip the
26
+ /// disk-baseline values to disk while keeping the runtime overrides on the in-memory
27
+ /// config — runtime-only overrides MUST NOT leak into the persisted JSON.
28
+ /// </summary>
29
+ internal EnvironmentUtils.OverrideRecord RuntimeOverrides { get; private set; }
30
+ = new EnvironmentUtils.OverrideRecord();
31
+
32
+ protected UnityCopilotPluginEditor() : base()
33
+ {
34
+ var config = GetOrCreateConfig(out var wasCreated);
35
+ unityConnectionConfig = config;
36
+ ApplyLogLevel(unityConnectionConfig.LogLevel);
37
+ // Layered loader: disk values are already on `config`; env vars and CLI flags
38
+ // are applied here as runtime overrides. The OverrideRecord captures the
39
+ // disk-baseline values so Save() can persist them without leaking the overrides.
40
+ RuntimeOverrides = EnvironmentUtils.ApplyEnvironmentOverrides(unityConnectionConfig);
41
+ if (wasCreated)
42
+ Save();
43
+ IncrementSingletonCount();
44
+ }
45
+
46
+ public void Validate()
47
+ {
48
+ var changed = false;
49
+ var data = unityConnectionConfig ??= new UnityConnectionConfig();
50
+
51
+ if (string.IsNullOrEmpty(data.LocalHost))
52
+ {
53
+ data.LocalHost = UnityConnectionConfig.DefaultHost;
54
+ changed = true;
55
+ }
56
+
57
+ // Data was changed during validation, need to notify subscribers
58
+ if (changed)
59
+ NotifyChanged(data);
60
+ }
61
+
62
+ public override void Dispose()
63
+ {
64
+ DecrementSingletonCount();
65
+ base.Dispose();
66
+ DisposeUcoPluginInstance();
67
+ }
68
+ }
69
+ }
@@ -1,168 +1,168 @@
1
- /*
2
- ┌──────────────────────────────────────────────────────────────────┐
3
- │ Author: Ivan Murzak (https://github.com/IvanMurzak) │
4
- │ Repository: GitHub (https://github.com/IvanMurzak/Unity-MCP) │
5
- │ Copyright (c) 2025 Ivan Murzak │
6
- │ Licensed under the Apache License, Version 2.0. │
7
- │ See the LICENSE file in the project root for more information. │
8
- └──────────────────────────────────────────────────────────────────┘
9
- */
10
-
11
- #nullable enable
12
- using System.Collections.Generic;
13
- using System.Linq;
14
- using com.AtelierAI.Uco.Framework.Common.Model;
15
- using UnityEditor;
16
-
17
- namespace com.AtelierAI.Unity.Copilot.Editor.Utils
18
- {
19
- /// <summary>
20
- /// Utility class for handling package operations that may trigger domain reloads.
21
- /// Uses SessionState to persist notification data across domain reloads.
22
- /// </summary>
23
- public static class PackageUtils
24
- {
25
- private const string PendingNotificationKeysKey = "MCP_PendingPackageNotificationKeys";
26
- private const string NotificationDataSeparator = "<MCP_PKG_SEP>";
27
-
28
- private static bool _processPendingScheduled = false;
29
-
30
- public static void Init()
31
- {
32
- // Process any pending notifications after domain reload
33
- ScheduleProcessPendingNotifications();
34
- }
35
-
36
- private static void ScheduleProcessPendingNotifications()
37
- {
38
- if (_processPendingScheduled)
39
- return;
40
-
41
- _processPendingScheduled = true;
42
- EditorApplication.update += ProcessPendingNotificationsOnce;
43
- }
44
-
45
- private static void ProcessPendingNotificationsOnce()
46
- {
47
- EditorApplication.update -= ProcessPendingNotificationsOnce;
48
-
49
- if (!_processPendingScheduled)
50
- return;
51
-
52
- _processPendingScheduled = false;
53
- ProcessPendingNotifications();
54
- }
55
-
56
- /// <summary>
57
- /// Schedules a notification to be sent after Unity domain reload completes.
58
- /// Uses SessionState to persist across domain reloads.
59
- /// </summary>
60
- /// <param name="requestId">The request ID to track</param>
61
- /// <param name="packageIdentifier">The package identifier that was operated on</param>
62
- /// <param name="operationType">The type of operation performed (Add, Remove)</param>
63
- /// <param name="expectedResult">Whether the operation was expected to succeed before domain reload</param>
64
- public static void SchedulePostDomainReloadNotification(string requestId, string packageIdentifier, string operationType, bool expectedResult)
65
- {
66
- var notificationKey = $"MCP_PendingPackageNotification_{requestId}";
67
- var notificationData = $"{requestId}{NotificationDataSeparator}{packageIdentifier}{NotificationDataSeparator}{operationType}{NotificationDataSeparator}{expectedResult}";
68
-
69
- // Store the notification data
70
- SessionState.SetString(notificationKey, notificationData);
71
-
72
- // Add to the key list
73
- var existingKeys = SessionState.GetString(PendingNotificationKeysKey, string.Empty);
74
- var keyList = string.IsNullOrEmpty(existingKeys)
75
- ? new List<string>()
76
- : existingKeys.Split(',').Where(k => !string.IsNullOrEmpty(k)).ToList();
77
-
78
- if (!keyList.Contains(notificationKey))
79
- {
80
- keyList.Add(notificationKey);
81
- SessionState.SetString(PendingNotificationKeysKey, string.Join(",", keyList));
82
- }
83
- }
84
-
85
- /// <summary>
86
- /// Called by InitializeOnLoad to process any pending notifications after domain reload.
87
- /// </summary>
88
- public static void ProcessPendingNotifications()
89
- {
90
- // Get the list of pending notification keys from SessionState
91
- var pendingKeys = SessionState.GetString(PendingNotificationKeysKey, string.Empty);
92
- if (string.IsNullOrEmpty(pendingKeys))
93
- return;
94
-
95
- var keys = pendingKeys.Split(',').Where(k => !string.IsNullOrEmpty(k)).ToList();
96
- if (keys.Count == 0)
97
- return;
98
-
99
- var processedKeys = new List<string>();
100
-
101
- foreach (var key in keys)
102
- {
103
- var notificationData = SessionState.GetString(key, string.Empty);
104
- if (string.IsNullOrEmpty(notificationData))
105
- {
106
- processedKeys.Add(key);
107
- continue;
108
- }
109
-
110
- var parts = notificationData.Split(NotificationDataSeparator);
111
- if (parts.Length != 4)
112
- {
113
- processedKeys.Add(key);
114
- continue;
115
- }
116
-
117
- var requestId = parts[0];
118
- var packageIdentifier = parts[1];
119
- var operationType = parts[2];
120
- var expectedResult = bool.Parse(parts[3]);
121
-
122
- // Check for compilation errors after package operation
123
- var hasCompilationErrors = ScriptUtils.HasCompilationErrors();
124
-
125
- ResponseCallTool response;
126
- if (hasCompilationErrors)
127
- {
128
- var errorDetails = ScriptUtils.GetCompilationErrorDetails();
129
- var message = $"[Warning] Package {operationType} completed: {packageIdentifier}, but compilation errors occurred after domain reload. Details:\n{errorDetails}";
130
- response = ResponseCallTool.Success(message).SetRequestID(requestId);
131
- }
132
- else if (expectedResult)
133
- {
134
- var message = $"[Success] Package {operationType} completed: {packageIdentifier}. Domain reload finished successfully.";
135
- response = ResponseCallTool.Success(message).SetRequestID(requestId);
136
- }
137
- else
138
- {
139
- var message = $"[Error] Package {operationType} failed: {packageIdentifier}";
140
- response = ResponseCallTool.Error(message).SetRequestID(requestId);
141
- }
142
-
143
- // Send notification and mark for cleanup
144
- _ = UnityCopilotPluginEditor.NotifyToolRequestCompleted(new RequestToolCompletedData
145
- {
146
- RequestId = requestId,
147
- Result = response
148
- });
149
- processedKeys.Add(key);
150
- }
151
-
152
- // Clean up processed keys
153
- foreach (var key in processedKeys)
154
- SessionState.EraseString(key);
155
-
156
- // Update the key list
157
- var remainingKeys = keys.Except(processedKeys).ToList();
158
- if (remainingKeys.Count > 0)
159
- {
160
- SessionState.SetString(PendingNotificationKeysKey, string.Join(",", remainingKeys));
161
- }
162
- else
163
- {
164
- SessionState.EraseString(PendingNotificationKeysKey);
165
- }
166
- }
167
- }
168
- }
1
+ /*
2
+ ┌──────────────────────────────────────────────────────────────────┐
3
+ │ Author: Ivan Murzak (https://github.com/IvanMurzak) │
4
+ │ Repository: GitHub (https://github.com/IvanMurzak/Unity-MCP) │
5
+ │ Copyright (c) 2025 Ivan Murzak │
6
+ │ Licensed under the Apache License, Version 2.0. │
7
+ │ See the LICENSE file in the project root for more information. │
8
+ └──────────────────────────────────────────────────────────────────┘
9
+ */
10
+
11
+ #nullable enable
12
+ using System.Collections.Generic;
13
+ using System.Linq;
14
+ using com.AtelierAI.Uco.Framework.Common.Model;
15
+ using UnityEditor;
16
+
17
+ namespace com.AtelierAI.Unity.Copilot.Editor.Utils
18
+ {
19
+ /// <summary>
20
+ /// Utility class for handling package operations that may trigger domain reloads.
21
+ /// Uses SessionState to persist notification data across domain reloads.
22
+ /// </summary>
23
+ public static class PackageUtils
24
+ {
25
+ private const string PendingNotificationKeysKey = "UCO_PendingPackageNotificationKeys";
26
+ private const string NotificationDataSeparator = "<UCO_PKG_SEP>";
27
+
28
+ private static bool _processPendingScheduled = false;
29
+
30
+ public static void Init()
31
+ {
32
+ // Process any pending notifications after domain reload
33
+ ScheduleProcessPendingNotifications();
34
+ }
35
+
36
+ private static void ScheduleProcessPendingNotifications()
37
+ {
38
+ if (_processPendingScheduled)
39
+ return;
40
+
41
+ _processPendingScheduled = true;
42
+ EditorApplication.update += ProcessPendingNotificationsOnce;
43
+ }
44
+
45
+ private static void ProcessPendingNotificationsOnce()
46
+ {
47
+ EditorApplication.update -= ProcessPendingNotificationsOnce;
48
+
49
+ if (!_processPendingScheduled)
50
+ return;
51
+
52
+ _processPendingScheduled = false;
53
+ ProcessPendingNotifications();
54
+ }
55
+
56
+ /// <summary>
57
+ /// Schedules a notification to be sent after Unity domain reload completes.
58
+ /// Uses SessionState to persist across domain reloads.
59
+ /// </summary>
60
+ /// <param name="requestId">The request ID to track</param>
61
+ /// <param name="packageIdentifier">The package identifier that was operated on</param>
62
+ /// <param name="operationType">The type of operation performed (Add, Remove)</param>
63
+ /// <param name="expectedResult">Whether the operation was expected to succeed before domain reload</param>
64
+ public static void SchedulePostDomainReloadNotification(string requestId, string packageIdentifier, string operationType, bool expectedResult)
65
+ {
66
+ var notificationKey = $"UCO_PendingPackageNotification_{requestId}";
67
+ var notificationData = $"{requestId}{NotificationDataSeparator}{packageIdentifier}{NotificationDataSeparator}{operationType}{NotificationDataSeparator}{expectedResult}";
68
+
69
+ // Store the notification data
70
+ SessionState.SetString(notificationKey, notificationData);
71
+
72
+ // Add to the key list
73
+ var existingKeys = SessionState.GetString(PendingNotificationKeysKey, string.Empty);
74
+ var keyList = string.IsNullOrEmpty(existingKeys)
75
+ ? new List<string>()
76
+ : existingKeys.Split(',').Where(k => !string.IsNullOrEmpty(k)).ToList();
77
+
78
+ if (!keyList.Contains(notificationKey))
79
+ {
80
+ keyList.Add(notificationKey);
81
+ SessionState.SetString(PendingNotificationKeysKey, string.Join(",", keyList));
82
+ }
83
+ }
84
+
85
+ /// <summary>
86
+ /// Called by InitializeOnLoad to process any pending notifications after domain reload.
87
+ /// </summary>
88
+ public static void ProcessPendingNotifications()
89
+ {
90
+ // Get the list of pending notification keys from SessionState
91
+ var pendingKeys = SessionState.GetString(PendingNotificationKeysKey, string.Empty);
92
+ if (string.IsNullOrEmpty(pendingKeys))
93
+ return;
94
+
95
+ var keys = pendingKeys.Split(',').Where(k => !string.IsNullOrEmpty(k)).ToList();
96
+ if (keys.Count == 0)
97
+ return;
98
+
99
+ var processedKeys = new List<string>();
100
+
101
+ foreach (var key in keys)
102
+ {
103
+ var notificationData = SessionState.GetString(key, string.Empty);
104
+ if (string.IsNullOrEmpty(notificationData))
105
+ {
106
+ processedKeys.Add(key);
107
+ continue;
108
+ }
109
+
110
+ var parts = notificationData.Split(NotificationDataSeparator);
111
+ if (parts.Length != 4)
112
+ {
113
+ processedKeys.Add(key);
114
+ continue;
115
+ }
116
+
117
+ var requestId = parts[0];
118
+ var packageIdentifier = parts[1];
119
+ var operationType = parts[2];
120
+ var expectedResult = bool.Parse(parts[3]);
121
+
122
+ // Check for compilation errors after package operation
123
+ var hasCompilationErrors = ScriptUtils.HasCompilationErrors();
124
+
125
+ ResponseCallTool response;
126
+ if (hasCompilationErrors)
127
+ {
128
+ var errorDetails = ScriptUtils.GetCompilationErrorDetails();
129
+ var message = $"[Warning] Package {operationType} completed: {packageIdentifier}, but compilation errors occurred after domain reload. Details:\n{errorDetails}";
130
+ response = ResponseCallTool.Success(message).SetRequestID(requestId);
131
+ }
132
+ else if (expectedResult)
133
+ {
134
+ var message = $"[Success] Package {operationType} completed: {packageIdentifier}. Domain reload finished successfully.";
135
+ response = ResponseCallTool.Success(message).SetRequestID(requestId);
136
+ }
137
+ else
138
+ {
139
+ var message = $"[Error] Package {operationType} failed: {packageIdentifier}";
140
+ response = ResponseCallTool.Error(message).SetRequestID(requestId);
141
+ }
142
+
143
+ // Send notification and mark for cleanup
144
+ _ = UnityCopilotPluginEditor.NotifyToolRequestCompleted(new RequestToolCompletedData
145
+ {
146
+ RequestId = requestId,
147
+ Result = response
148
+ });
149
+ processedKeys.Add(key);
150
+ }
151
+
152
+ // Clean up processed keys
153
+ foreach (var key in processedKeys)
154
+ SessionState.EraseString(key);
155
+
156
+ // Update the key list
157
+ var remainingKeys = keys.Except(processedKeys).ToList();
158
+ if (remainingKeys.Count > 0)
159
+ {
160
+ SessionState.SetString(PendingNotificationKeysKey, string.Join(",", remainingKeys));
161
+ }
162
+ else
163
+ {
164
+ SessionState.EraseString(PendingNotificationKeysKey);
165
+ }
166
+ }
167
+ }
168
+ }