@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,201 +1,201 @@
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
- using com.AtelierAI.Unity.Copilot.Editor.Utils;
14
- using com.AtelierAI.Uco.Framework;
15
- using Microsoft.Extensions.Logging;
16
- using UnityEditor;
17
- using UnityEngine;
18
-
19
- namespace com.AtelierAI.Unity.Copilot.Editor
20
- {
21
- public static partial class Startup
22
- {
23
- static void SubscribeOnEditorEvents()
24
- {
25
- Application.unloading += OnApplicationUnloading;
26
- Application.quitting += OnApplicationQuitting;
27
-
28
- AssemblyReloadEvents.beforeAssemblyReload += OnBeforeAssemblyReload;
29
- AssemblyReloadEvents.afterAssemblyReload += OnAfterAssemblyReload;
30
-
31
- // Handle Play mode state changes to ensure reconnection after exiting Play mode
32
- EditorApplication.playModeStateChanged += OnPlayModeStateChanged;
33
- }
34
- static void OnApplicationUnloading() => TryDisconnectAndCleanup(nameof(OnApplicationUnloading));
35
- static void OnApplicationQuitting() => TryDisconnectAndCleanup(nameof(OnApplicationQuitting));
36
- static void OnBeforeAssemblyReload()
37
- {
38
- EditorToolExecutionScheduler.Shared.InvalidateInstance();
39
- EditorOperationOwnerRegistry.InvalidateGeneration();
40
- UnityAuthoringSafetyReloadGuard.InvalidateConfirmationPlans();
41
- TryDisconnectAndCleanup(nameof(OnBeforeAssemblyReload));
42
- }
43
-
44
- /// <summary>
45
- /// Safely disconnects and cleans up the MCP plugin instance.
46
- /// Catches exceptions to prevent blocking Unity's shutdown/reload process.
47
- /// </summary>
48
- /// <param name="callerName">Name of the calling method for logging.</param>
49
- /// <param name="onlyIfConnected">If true, only disconnects when in Connected state.
50
- /// This prevents issues when cancelling in-progress connection attempts during assembly reload.
51
- /// Note: Log collector disposal always occurs regardless of this flag.</param>
52
- static void TryDisconnectAndCleanup(string callerName, bool onlyIfConnected = false)
53
- {
54
- if (!UnityCopilotPluginEditor.HasInstance)
55
- {
56
- _logger.LogDebug("{class} {method} triggered: No UnityCopilotPluginEditor instance to disconnect",
57
- nameof(Startup), callerName);
58
- return;
59
- }
60
-
61
- _logger.LogInformation("{method} triggered", callerName);
62
-
63
- var plugin = UnityCopilotPluginEditor.Instance;
64
- if (plugin.HasMcpPluginInstance)
65
- {
66
- var connectionState = UnityCopilotPluginEditor.ConnectionState.CurrentValue;
67
-
68
- // When onlyIfConnected is true, skip disconnect unless we have an established connection.
69
- // This prevents hanging when cancelling in-progress connection attempts (Connecting/Reconnecting states).
70
- if (onlyIfConnected && connectionState != ConnectionState.Connected)
71
- {
72
- _logger.LogTrace("Skipping {method} - not connected (state: {state})",
73
- nameof(plugin.DisconnectImmediate), connectionState);
74
- }
75
- else
76
- {
77
- try
78
- {
79
- plugin.DisconnectImmediate();
80
- }
81
- catch (System.Exception e)
82
- {
83
- _logger.LogWarning(e, "{class} {method}: Exception during disconnect (non-blocking): {message}",
84
- nameof(Startup), callerName, e.Message);
85
- }
86
- }
87
- }
88
-
89
- try
90
- {
91
- plugin.DisposeLogCollector();
92
- }
93
- catch (System.Exception e)
94
- {
95
- _logger.LogWarning(e, "{class} {method}: Exception during log collector disposal (non-blocking): {message}",
96
- nameof(Startup), callerName, e.Message);
97
- }
98
-
99
- if (UnityCopilotPluginRuntime.HasInstance)
100
- {
101
- try
102
- {
103
- UnityCopilotPluginRuntime.DisposeInstance();
104
- }
105
- catch (System.Exception e)
106
- {
107
- _logger.LogWarning(e, "{class} {method}: Exception during runtime plugin disposal (non-blocking): {message}",
108
- nameof(Startup), callerName, e.Message);
109
- }
110
- }
111
- }
112
- static void OnAfterAssemblyReload()
113
- {
114
- var isCi = EnvironmentUtils.IsCi();
115
- var isBatchMode = EnvironmentUtils.IsBatchMode();
116
- var keepConnected = UnityCopilotPluginEditor.KeepConnected;
117
- // COCli-13: batchmode launches (offline builds, command-line
118
- // automation) skip the connection retry loop unless the
119
- // configuration explicitly keeps the server running — connection
120
- // warnings would otherwise pollute BuildReport output.
121
- var connectionAllowed = keepConnected || (!isCi && !isBatchMode);
122
-
123
- _logger.LogInformation("{method} triggered - BuildAndStart with connectionAllowed: {connectionAllowed} (isCi: {isCi}, isBatchMode: {isBatchMode}, keepConnected: {keepConnected})",
124
- nameof(OnAfterAssemblyReload), connectionAllowed, isCi, isBatchMode, keepConnected);
125
-
126
- UnityCopilotPluginEditor.Instance.BuildMcpPluginIfNeeded();
127
- UnityCopilotPluginEditor.Instance.AddUnityLogCollectorIfNeeded(() => new BufferedFileLogStorage());
128
-
129
- if (connectionAllowed)
130
- UnityCopilotPluginEditor.ConnectIfNeeded();
131
- }
132
-
133
- static void OnPlayModeStateChanged(PlayModeStateChange state)
134
- {
135
- if (!UnityCopilotPluginEditor.HasInstance)
136
- {
137
- _logger.LogDebug("{class} {method} triggered: No UnityCopilotPluginEditor instance available. State: {state}",
138
- nameof(Startup), nameof(OnPlayModeStateChanged), state);
139
- return;
140
- }
141
-
142
- // Log Play mode state changes for debugging
143
- _logger.LogInformation("Play mode state changed: {state}", state);
144
-
145
- switch (state)
146
- {
147
- case PlayModeStateChange.ExitingPlayMode:
148
- // Dispose the runtime plugin instance created by Initialize().Build().
149
- // This handles the no-domain-reload case; TryDisconnectAndCleanup covers the domain-reload case.
150
- _logger.LogTrace("Exiting Play mode - disposing runtime plugin instance if present");
151
- if (UnityCopilotPluginRuntime.HasInstance)
152
- UnityCopilotPluginRuntime.DisposeInstance();
153
- break;
154
-
155
- case PlayModeStateChange.EnteredEditMode:
156
- // Unity has returned to Edit mode - ensure connection is re-established
157
- // if the configuration expects it to be connected
158
- var isCi = EnvironmentUtils.IsCi();
159
- var isBatchMode = EnvironmentUtils.IsBatchMode();
160
- var keepConnected = UnityCopilotPluginEditor.KeepConnected;
161
- _logger.LogTrace("Entered Edit mode - KeepConnected: {keepConnected}, IsCi: {isCi}, IsBatchMode: {isBatchMode}",
162
- keepConnected, isCi, isBatchMode);
163
-
164
- if ((isCi || isBatchMode) && !keepConnected)
165
- {
166
- _logger.LogTrace("Skipping reconnection in CI/batchmode environment (KeepConnected is false)");
167
- break;
168
- }
169
-
170
- _logger.LogTrace("Scheduling reconnection after Play mode exit");
171
-
172
- // Small delay to ensure Unity is fully settled in Edit mode
173
- EditorApplication.delayCall += () =>
174
- {
175
- _logger.LogTrace("Initiating delayed reconnection after Play mode exit");
176
-
177
- UnityCopilotPluginEditor.Instance.BuildMcpPluginIfNeeded();
178
- UnityCopilotPluginEditor.Instance.AddUnityLogCollectorIfNeeded(() => new BufferedFileLogStorage());
179
- UnityCopilotPluginEditor.ConnectIfNeeded();
180
- };
181
-
182
- // No delay, immediate reconnection for the case if Unity Editor in background
183
- // (has no focus)
184
- _logger.LogTrace("Initiating reconnection after Play mode exit");
185
-
186
- UnityCopilotPluginEditor.Instance.BuildMcpPluginIfNeeded();
187
- UnityCopilotPluginEditor.Instance.AddUnityLogCollectorIfNeeded(() => new BufferedFileLogStorage());
188
- UnityCopilotPluginEditor.ConnectIfNeeded();
189
- break;
190
-
191
- case PlayModeStateChange.ExitingEditMode:
192
- _logger.LogTrace("Exiting Edit mode to enter Play mode");
193
- break;
194
-
195
- case PlayModeStateChange.EnteredPlayMode:
196
- _logger.LogTrace("Entered Play mode");
197
- break;
198
- }
199
- }
200
- }
201
- }
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
+ using com.AtelierAI.Unity.Copilot.Editor.Utils;
14
+ using com.AtelierAI.Uco.Framework;
15
+ using Microsoft.Extensions.Logging;
16
+ using UnityEditor;
17
+ using UnityEngine;
18
+
19
+ namespace com.AtelierAI.Unity.Copilot.Editor
20
+ {
21
+ public static partial class Startup
22
+ {
23
+ static void SubscribeOnEditorEvents()
24
+ {
25
+ Application.unloading += OnApplicationUnloading;
26
+ Application.quitting += OnApplicationQuitting;
27
+
28
+ AssemblyReloadEvents.beforeAssemblyReload += OnBeforeAssemblyReload;
29
+ AssemblyReloadEvents.afterAssemblyReload += OnAfterAssemblyReload;
30
+
31
+ // Handle Play mode state changes to ensure reconnection after exiting Play mode
32
+ EditorApplication.playModeStateChanged += OnPlayModeStateChanged;
33
+ }
34
+ static void OnApplicationUnloading() => TryDisconnectAndCleanup(nameof(OnApplicationUnloading));
35
+ static void OnApplicationQuitting() => TryDisconnectAndCleanup(nameof(OnApplicationQuitting));
36
+ static void OnBeforeAssemblyReload()
37
+ {
38
+ EditorToolExecutionScheduler.Shared.InvalidateInstance();
39
+ EditorOperationOwnerRegistry.InvalidateGeneration();
40
+ UnityAuthoringSafetyReloadGuard.InvalidateConfirmationPlans();
41
+ TryDisconnectAndCleanup(nameof(OnBeforeAssemblyReload));
42
+ }
43
+
44
+ /// <summary>
45
+ /// Safely disconnects and cleans up the Uco plugin instance.
46
+ /// Catches exceptions to prevent blocking Unity's shutdown/reload process.
47
+ /// </summary>
48
+ /// <param name="callerName">Name of the calling method for logging.</param>
49
+ /// <param name="onlyIfConnected">If true, only disconnects when in Connected state.
50
+ /// This prevents issues when cancelling in-progress connection attempts during assembly reload.
51
+ /// Note: Log collector disposal always occurs regardless of this flag.</param>
52
+ static void TryDisconnectAndCleanup(string callerName, bool onlyIfConnected = false)
53
+ {
54
+ if (!UnityCopilotPluginEditor.HasInstance)
55
+ {
56
+ _logger.LogDebug("{class} {method} triggered: No UnityCopilotPluginEditor instance to disconnect",
57
+ nameof(Startup), callerName);
58
+ return;
59
+ }
60
+
61
+ _logger.LogInformation("{method} triggered", callerName);
62
+
63
+ var plugin = UnityCopilotPluginEditor.Instance;
64
+ if (plugin.HasUcoPluginInstance)
65
+ {
66
+ var connectionState = UnityCopilotPluginEditor.ConnectionState.CurrentValue;
67
+
68
+ // When onlyIfConnected is true, skip disconnect unless we have an established connection.
69
+ // This prevents hanging when cancelling in-progress connection attempts (Connecting/Reconnecting states).
70
+ if (onlyIfConnected && connectionState != ConnectionState.Connected)
71
+ {
72
+ _logger.LogTrace("Skipping {method} - not connected (state: {state})",
73
+ nameof(plugin.DisconnectImmediate), connectionState);
74
+ }
75
+ else
76
+ {
77
+ try
78
+ {
79
+ plugin.DisconnectImmediate();
80
+ }
81
+ catch (System.Exception e)
82
+ {
83
+ _logger.LogWarning(e, "{class} {method}: Exception during disconnect (non-blocking): {message}",
84
+ nameof(Startup), callerName, e.Message);
85
+ }
86
+ }
87
+ }
88
+
89
+ try
90
+ {
91
+ plugin.DisposeLogCollector();
92
+ }
93
+ catch (System.Exception e)
94
+ {
95
+ _logger.LogWarning(e, "{class} {method}: Exception during log collector disposal (non-blocking): {message}",
96
+ nameof(Startup), callerName, e.Message);
97
+ }
98
+
99
+ if (UnityCopilotPluginRuntime.HasInstance)
100
+ {
101
+ try
102
+ {
103
+ UnityCopilotPluginRuntime.DisposeInstance();
104
+ }
105
+ catch (System.Exception e)
106
+ {
107
+ _logger.LogWarning(e, "{class} {method}: Exception during runtime plugin disposal (non-blocking): {message}",
108
+ nameof(Startup), callerName, e.Message);
109
+ }
110
+ }
111
+ }
112
+ static void OnAfterAssemblyReload()
113
+ {
114
+ var isCi = EnvironmentUtils.IsCi();
115
+ var isBatchMode = EnvironmentUtils.IsBatchMode();
116
+ var keepConnected = UnityCopilotPluginEditor.KeepConnected;
117
+ // COCli-13: batchmode launches (offline builds, command-line
118
+ // automation) skip the connection retry loop unless the
119
+ // configuration explicitly keeps the server running — connection
120
+ // warnings would otherwise pollute BuildReport output.
121
+ var connectionAllowed = keepConnected || (!isCi && !isBatchMode);
122
+
123
+ _logger.LogInformation("{method} triggered - BuildAndStart with connectionAllowed: {connectionAllowed} (isCi: {isCi}, isBatchMode: {isBatchMode}, keepConnected: {keepConnected})",
124
+ nameof(OnAfterAssemblyReload), connectionAllowed, isCi, isBatchMode, keepConnected);
125
+
126
+ UnityCopilotPluginEditor.Instance.BuildUcoPluginIfNeeded();
127
+ UnityCopilotPluginEditor.Instance.AddUnityLogCollectorIfNeeded(() => new BufferedFileLogStorage());
128
+
129
+ if (connectionAllowed)
130
+ UnityCopilotPluginEditor.ConnectIfNeeded();
131
+ }
132
+
133
+ static void OnPlayModeStateChanged(PlayModeStateChange state)
134
+ {
135
+ if (!UnityCopilotPluginEditor.HasInstance)
136
+ {
137
+ _logger.LogDebug("{class} {method} triggered: No UnityCopilotPluginEditor instance available. State: {state}",
138
+ nameof(Startup), nameof(OnPlayModeStateChanged), state);
139
+ return;
140
+ }
141
+
142
+ // Log Play mode state changes for debugging
143
+ _logger.LogInformation("Play mode state changed: {state}", state);
144
+
145
+ switch (state)
146
+ {
147
+ case PlayModeStateChange.ExitingPlayMode:
148
+ // Dispose the runtime plugin instance created by Initialize().Build().
149
+ // This handles the no-domain-reload case; TryDisconnectAndCleanup covers the domain-reload case.
150
+ _logger.LogTrace("Exiting Play mode - disposing runtime plugin instance if present");
151
+ if (UnityCopilotPluginRuntime.HasInstance)
152
+ UnityCopilotPluginRuntime.DisposeInstance();
153
+ break;
154
+
155
+ case PlayModeStateChange.EnteredEditMode:
156
+ // Unity has returned to Edit mode - ensure connection is re-established
157
+ // if the configuration expects it to be connected
158
+ var isCi = EnvironmentUtils.IsCi();
159
+ var isBatchMode = EnvironmentUtils.IsBatchMode();
160
+ var keepConnected = UnityCopilotPluginEditor.KeepConnected;
161
+ _logger.LogTrace("Entered Edit mode - KeepConnected: {keepConnected}, IsCi: {isCi}, IsBatchMode: {isBatchMode}",
162
+ keepConnected, isCi, isBatchMode);
163
+
164
+ if ((isCi || isBatchMode) && !keepConnected)
165
+ {
166
+ _logger.LogTrace("Skipping reconnection in CI/batchmode environment (KeepConnected is false)");
167
+ break;
168
+ }
169
+
170
+ _logger.LogTrace("Scheduling reconnection after Play mode exit");
171
+
172
+ // Small delay to ensure Unity is fully settled in Edit mode
173
+ EditorApplication.delayCall += () =>
174
+ {
175
+ _logger.LogTrace("Initiating delayed reconnection after Play mode exit");
176
+
177
+ UnityCopilotPluginEditor.Instance.BuildUcoPluginIfNeeded();
178
+ UnityCopilotPluginEditor.Instance.AddUnityLogCollectorIfNeeded(() => new BufferedFileLogStorage());
179
+ UnityCopilotPluginEditor.ConnectIfNeeded();
180
+ };
181
+
182
+ // No delay, immediate reconnection for the case if Unity Editor in background
183
+ // (has no focus)
184
+ _logger.LogTrace("Initiating reconnection after Play mode exit");
185
+
186
+ UnityCopilotPluginEditor.Instance.BuildUcoPluginIfNeeded();
187
+ UnityCopilotPluginEditor.Instance.AddUnityLogCollectorIfNeeded(() => new BufferedFileLogStorage());
188
+ UnityCopilotPluginEditor.ConnectIfNeeded();
189
+ break;
190
+
191
+ case PlayModeStateChange.ExitingEditMode:
192
+ _logger.LogTrace("Exiting Edit mode to enter Play mode");
193
+ break;
194
+
195
+ case PlayModeStateChange.EnteredPlayMode:
196
+ _logger.LogTrace("Entered Play mode");
197
+ break;
198
+ }
199
+ }
200
+ }
201
+ }
@@ -1,67 +1,67 @@
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.Editor.UI;
13
- using com.AtelierAI.Unity.Copilot.Editor.Utils;
14
- using com.AtelierAI.Unity.Copilot.Utils;
15
- using Microsoft.Extensions.Logging;
16
- using UnityEditor;
17
- using UnityEngine;
18
- using ILogger = Microsoft.Extensions.Logging.ILogger;
19
-
20
- namespace com.AtelierAI.Unity.Copilot.Editor
21
- {
22
- [InitializeOnLoad]
23
- public static partial class Startup
24
- {
25
- static readonly ILogger _logger = UnityLoggerFactory.LoggerFactory.CreateLogger(nameof(Startup));
26
-
27
- static Startup()
28
- {
29
- if (!UnityProcessGuard.ShouldInitialize(AssetDatabase.IsAssetImportWorkerProcess()))
30
- {
31
- return;
32
- }
33
-
34
- EditorOperationOwners.RegisterAndReconcile();
35
- UnityCopilotPluginEditor.Instance.BuildMcpPluginIfNeeded();
36
- UnityCopilotPluginEditor.Instance.AddUnityLogCollectorIfNeeded(() => new BufferedFileLogStorage());
37
-
38
- // Informational notice — historically the plugin treated a space in the project
39
- // path as a hard error, but in practice the modern startup pipeline (structured
40
- // ProcessStartInfo, JSON/TOML client configs with quoted command strings,
41
- // Path.Combine-based file IO) handles spaces correctly. We keep a one-shot
42
- // warning so users have a breadcrumb if they hit a third-party tool that does
43
- // not tolerate spaces in paths.
44
- if (Application.dataPath.Contains(" "))
45
- Debug.LogWarning("Unity Copilot: project path contains spaces. The plugin will start normally; if any specific workflow misbehaves with this path, please report it so we can fix the underlying issue.");
46
-
47
- SubscribeOnEditorEvents();
48
-
49
- // Initialize sub-systems
50
- API.Tool_Tests.Init();
51
- UpdateChecker.Init();
52
- PackageUtils.Init();
53
- }
54
- }
55
-
56
- /// <summary>
57
- /// Asset Import Workers inherit the main Editor's environment variables but
58
- /// must never create their own MCP plugin/server lifecycle. A worker bridge
59
- /// advertises the same project instance ID, cannot complete normal Editor
60
- /// registration, and can otherwise displace the main Editor connection.
61
- /// </summary>
62
- internal static class UnityProcessGuard
63
- {
64
- internal static bool ShouldInitialize(bool isAssetImportWorkerProcess)
65
- => !isAssetImportWorkerProcess;
66
- }
67
- }
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.Editor.UI;
13
+ using com.AtelierAI.Unity.Copilot.Editor.Utils;
14
+ using com.AtelierAI.Unity.Copilot.Utils;
15
+ using Microsoft.Extensions.Logging;
16
+ using UnityEditor;
17
+ using UnityEngine;
18
+ using ILogger = Microsoft.Extensions.Logging.ILogger;
19
+
20
+ namespace com.AtelierAI.Unity.Copilot.Editor
21
+ {
22
+ [InitializeOnLoad]
23
+ public static partial class Startup
24
+ {
25
+ static readonly ILogger _logger = UnityLoggerFactory.LoggerFactory.CreateLogger(nameof(Startup));
26
+
27
+ static Startup()
28
+ {
29
+ if (!UnityProcessGuard.ShouldInitialize(AssetDatabase.IsAssetImportWorkerProcess()))
30
+ {
31
+ return;
32
+ }
33
+
34
+ EditorOperationOwners.RegisterAndReconcile();
35
+ UnityCopilotPluginEditor.Instance.BuildUcoPluginIfNeeded();
36
+ UnityCopilotPluginEditor.Instance.AddUnityLogCollectorIfNeeded(() => new BufferedFileLogStorage());
37
+
38
+ // Informational notice — historically the plugin treated a space in the project
39
+ // path as a hard error, but in practice the modern startup pipeline (structured
40
+ // ProcessStartInfo, JSON/TOML client configs with quoted command strings,
41
+ // Path.Combine-based file IO) handles spaces correctly. We keep a one-shot
42
+ // warning so users have a breadcrumb if they hit a third-party tool that does
43
+ // not tolerate spaces in paths.
44
+ if (Application.dataPath.Contains(" "))
45
+ Debug.LogWarning("Unity Copilot: project path contains spaces. The plugin will start normally; if any specific workflow misbehaves with this path, please report it so we can fix the underlying issue.");
46
+
47
+ SubscribeOnEditorEvents();
48
+
49
+ // Initialize sub-systems
50
+ API.Tool_Tests.Init();
51
+ UpdateChecker.Init();
52
+ PackageUtils.Init();
53
+ }
54
+ }
55
+
56
+ /// <summary>
57
+ /// Asset Import Workers inherit the main Editor's environment variables but
58
+ /// must never create their own Uco plugin/server lifecycle. A worker bridge
59
+ /// advertises the same project instance ID, cannot complete normal Editor
60
+ /// registration, and can otherwise displace the main Editor connection.
61
+ /// </summary>
62
+ internal static class UnityProcessGuard
63
+ {
64
+ internal static bool ShouldInitialize(bool isAssetImportWorkerProcess)
65
+ => !isAssetImportWorkerProcess;
66
+ }
67
+ }