@atelierai/uco 1.0.8 → 1.0.10

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 (35) hide show
  1. package/CHANGELOG.md +32 -8
  2. package/package.json +2 -2
  3. package/vendor/plugin/com.atelierai.unity.copilot/CHANGELOG.md +4 -4
  4. package/vendor/plugin/com.atelierai.unity.copilot/Editor/Scripts/API/Tool/ToolGroups.SetEnabled.cs +92 -92
  5. package/vendor/plugin/com.atelierai.unity.copilot/Editor/Scripts/CopilotServerManager.cs +0 -147
  6. package/vendor/plugin/com.atelierai.unity.copilot/Editor/Scripts/Startup.Editor.cs +16 -0
  7. package/vendor/plugin/com.atelierai.unity.copilot/Editor/Scripts/UI/Window/MainWindowEditor.CopilotServer.cs +3 -3
  8. package/vendor/plugin/com.atelierai.unity.copilot/Editor/Scripts/Utils/ToolGroupRegistry.cs +461 -460
  9. package/vendor/plugin/com.atelierai.unity.copilot/Editor/UI/uss/CopilotPromptsWindow.uss +11 -11
  10. package/vendor/plugin/com.atelierai.unity.copilot/Editor/UI/uss/CopilotResourcesWindow.uss +16 -16
  11. package/vendor/plugin/com.atelierai.unity.copilot/Editor/UI/uss/CopilotToolsWindow.uss +36 -36
  12. package/vendor/plugin/com.atelierai.unity.copilot/Editor/UI/uss/MainWindow.uss +183 -183
  13. package/vendor/plugin/com.atelierai.unity.copilot/Editor/UI/uss/common/{_mcp-list-window.uss → _copilot-list-window.uss} +18 -18
  14. package/vendor/plugin/com.atelierai.unity.copilot/Editor/UI/uss/common/_list-view.uss +77 -77
  15. package/vendor/plugin/com.atelierai.unity.copilot/Editor/UI/uxml/CopilotPromptsWindow.uxml +18 -18
  16. package/vendor/plugin/com.atelierai.unity.copilot/Editor/UI/uxml/CopilotResourcesWindow.uxml +18 -18
  17. package/vendor/plugin/com.atelierai.unity.copilot/Editor/UI/uxml/CopilotToolsWindow.uxml +18 -18
  18. package/vendor/plugin/com.atelierai.unity.copilot/Editor/UI/uxml/MainWindow.uxml +115 -115
  19. package/vendor/plugin/com.atelierai.unity.copilot/Plugins/ReflectorNet.dll +0 -0
  20. package/vendor/plugin/com.atelierai.unity.copilot/Plugins/Uco.Framework.Common.dll +0 -0
  21. package/vendor/plugin/com.atelierai.unity.copilot/Plugins/Uco.Framework.dll +0 -0
  22. package/vendor/plugin/com.atelierai.unity.copilot/README.md +88 -88
  23. package/vendor/plugin/com.atelierai.unity.copilot/Runtime/Unity/Logs/BufferedFileLogStorage.cs +208 -207
  24. package/vendor/plugin/com.atelierai.unity.copilot/Runtime/Unity/Logs/FileLogStorage.cs +3 -1
  25. package/vendor/plugin/com.atelierai.unity.copilot/Runtime/Unity/Logs/UnityLogCollector.cs +282 -280
  26. package/vendor/plugin/com.atelierai.unity.copilot/Runtime/UnityCopilotPlugin.cs +1 -1
  27. package/vendor/plugin/com.atelierai.unity.copilot/Tests/Editor/DependencyResolver/NuGetExtractorDevelopmentDependencyTests.cs +148 -148
  28. package/vendor/plugin/com.atelierai.unity.copilot/Tests/Editor/DependencyResolver/NuGetExtractorFlatLayoutTests.cs +166 -166
  29. package/vendor/plugin/com.atelierai.unity.copilot/Tests/Editor/DependencyResolver/NuGetInstallManifestTests.cs +436 -436
  30. package/vendor/plugin/com.atelierai.unity.copilot/Tests/Editor/DependencyResolver/NuGetLegacyMigrationTests.cs +1 -1
  31. package/vendor/plugin/com.atelierai.unity.copilot/Tests/Editor/DependencyResolver/NuGetPackageInstallerStaleVersionCleanupTests.cs +200 -200
  32. package/vendor/plugin/com.atelierai.unity.copilot/Tests/Editor/Environment/EnvironmentUtilsTests.cs +1 -1
  33. package/vendor/plugin/com.atelierai.unity.copilot/Tests/Editor/Tool/GameObject/TestJsonSchema.cs +199 -199
  34. package/vendor/plugin/com.atelierai.unity.copilot/package.json +1 -1
  35. /package/vendor/plugin/com.atelierai.unity.copilot/Editor/UI/uss/common/{_mcp-list-window.uss.meta → _copilot-list-window.uss.meta} +0 -0
package/CHANGELOG.md CHANGED
@@ -1,5 +1,29 @@
1
1
  # Changelog
2
2
 
3
+ ## 1.0.10 - 2026-09-19
4
+
5
+ - Vendored plugin refreshed to **1.0.8** — fixes an editor-native crash on
6
+ domain reload (UmaViewer issue uco-domain-reload-crash-20260919, 2/2
7
+ reproducible during script recompile). The plugin no longer defines a
8
+ finalizer: the historical one ran the full teardown (token cancellation
9
+ with synchronous Task continuations and ExecutionContext restores) on the
10
+ GC finalizer thread during domain unload, which mono cannot execute.
11
+ Assembly-reload/unload/quit cleanup now disposes the plugin instance
12
+ deterministically on the safe background-thread path. Ten other
13
+ same-pattern finalizers (request DTOs, log storage/collector) removed with
14
+ it. Framework tests 831x2; 2022.3 gate unchanged.
15
+
16
+
17
+ ## 1.0.9 - 2026-09-19
18
+
19
+ - Vendored plugin refreshed to **1.0.7**: the complete legacy-naming sweep —
20
+ dead config-builder helpers removed (the last code producing
21
+ agent-config-shaped JSON), internal docs rewritten to the current
22
+ architecture, package/UI naming cleaned end to end, and a live prefs-key
23
+ bug fixed (the tool-group flag now reads the key its own migration writes).
24
+ Framework tests 831x2, 2022.3 gate 857/858 unchanged.
25
+
26
+
3
27
  ## 1.0.8 - 2026-09-19
4
28
 
5
29
  - Vendored plugin refreshed to **1.0.6**: the C# source's internal type and
@@ -14,10 +38,10 @@
14
38
  ## 1.0.7 - 2026-09-19
15
39
 
16
40
  - **Legacy agent-config writing removed.** uco no longer writes or
17
- reconciles server entries into agent-client config files (`.mcp.json`,
41
+ reconciles server entries into agent-client config files
18
42
  Cursor, codex toml, …) — those entries pointed at a protocol surface the
19
43
  bridge has never spoken and never worked; they only surfaced as dead
20
- entries in agent tooling. `uco setup-mcp` and `uco login` are gone.
44
+ entries in agent tooling. The legacy setup and login commands are gone.
21
45
  Existing entries in your projects are left untouched; delete them at will.
22
46
  - **Legacy naming surface scrubbed end to end.** The bridge speaks plain
23
47
  REST (`/api/*`) plus a raw-WebSocket plugin hub — nothing else — and the
@@ -34,7 +58,7 @@
34
58
 
35
59
  ## 1.0.6 - 2026-09-19
36
60
 
37
- - Agent MCP configs (`.mcp.json` and friends) written by `uco setup-mcp` /
61
+ - Agent-client config files written by the legacy setup command /
38
62
  `uco update` now dial `127.0.0.1` even when the project config's host says
39
63
  `localhost` — third-party agent clients (Claude Code, codex) run on Node
40
64
  runtimes that resolve `localhost` to `::1`, which per-process proxy rules
@@ -54,8 +78,8 @@
54
78
  (Node's fetch may resolve `localhost` to ::1, which proxy rules matching
55
79
  node.exe commonly hijack), and a dead bridge behind such a proxy still
56
80
  classifies as `connection-refused` instead of an opaque `fetch failed`.
57
- `uco open --start-server` handoff health checks and generated MCP configs
58
- (`.mcp.json`) use `127.0.0.1` as well.
81
+ `uco open --start-server` handoff health checks and generated agent configs use
82
+ `127.0.0.1` as well.
59
83
  - Legacy `.cocli-skill.json` markers refresh in place again (a pre-rename
60
84
  install was refused by its own ownership marker; the marker file itself
61
85
  no longer counts as unmanaged).
@@ -68,7 +92,7 @@
68
92
 
69
93
  ## 1.0.4 - 2026-09-17
70
94
 
71
- - Server startup banner says "uco bridge" (was "Node MCP Server"); help
95
+ - Server startup banner says "uco bridge"; help
72
96
  endpoint header updated to match.
73
97
  - Vendored plugin refreshed to **1.0.4**: the in-editor updater now
74
98
  detects embedded installs (uco install) and directs the user to the
@@ -81,7 +105,7 @@
81
105
  bridge discovery now finds the published **@atelierai/uco** npm package
82
106
  (plus legacy `uco`/`cocli` layouts as fallbacks).
83
107
  - Help text and skill templates say "uco bridge server" instead of
84
- "Unity-MCP server"; the uco-setup recovery skill now documents how to
108
+ the legacy server name; the uco-setup recovery skill now documents how to
85
109
  bring the bridge up (`uco open --start-server true`, plugin auto-start,
86
110
  manual spawn with the exact CLI arguments).
87
111
 
@@ -90,7 +114,7 @@
90
114
  - Product naming unified to **Unity Copilot** (no hyphen) across docs and
91
115
  skill templates.
92
116
  - Vendored plugin refreshed to **1.0.2**: one menu tree (Tools ▸ Unity
93
- Copilot), the "AI Game Developer" leftovers and the dead MCP Inspector
117
+ Copilot), the "AI Game Developer" leftovers and the dead legacy inspector
94
118
  item removed.
95
119
  - `uco init` interactive agent selection now renders a checkbox list
96
120
  (space toggles, arrows move, enter confirms) on a TTY; non-TTY keeps the
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@atelierai/uco",
3
- "version": "1.0.8",
4
- "description": "uco — Unity Copilot CLI. Drive Unity Editor (and runtime game builds) from any AI agent via plain HTTP. No MCP protocol on the wire.",
3
+ "version": "1.0.10",
4
+ "description": "uco — Unity Copilot CLI. Drive Unity Editor (and runtime game builds) from any AI agent via plain HTTP.",
5
5
  "type": "module",
6
6
  "bin": {
7
7
  "uco": "./bin/uco.mjs",
@@ -22,7 +22,7 @@ detects the embedded layout and directs the user to run
22
22
  Discovery now probes @atelierai/uco, then the legacy uco and cocli layouts,
23
23
  project-local and npm-global.
24
24
  - Token env overrides route straight to the local token (no mode routing);
25
- UNITY_MCP_CLOUD_URL is gone, --url/UNITY_MCP_HOST keep working.
25
+ the cloud URL variable is gone; --url and the host variable keep working.
26
26
 
27
27
  ## [1.0.2] - 2026-09-15 — one menu tree, one name: Unity Copilot
28
28
 
@@ -32,9 +32,9 @@ detects the embedded layout and directs the user to run
32
32
  - The leftover "AI Game Developer" menu tree (NuGet resolver items) is
33
33
  merged into **Tools ▸ Unity Copilot**; the stray root-level
34
34
  "Generate Tools Manifest" item moves under it too.
35
- - Removed the dead **Launch MCP Inspector** item and the legacy
36
- `Commands/` folder (`start_mcp_inspector.bat`, `copy_readme.bat`) — the
37
- bridge speaks plain REST, there is no MCP endpoint to inspect.
35
+ - Removed the dead **legacy inspector** menu item and the legacy
36
+ `Commands/` folder (`start_legacy_inspector.bat`, `copy_readme.bat`) — the
37
+ bridge speaks plain REST, with no endpoint of that kind to inspect.
38
38
  - Team update kill-switch asset renamed to
39
39
  `ProjectSettings/Copilot-UpdateSettings.asset` (the old
40
40
  AI-Game-Developer-named file is no longer read; the toggle resets to
@@ -1,92 +1,92 @@
1
- /*
2
- * Design inspired by MCP for Unity (CoplayDev/unity-mcp), Copyright (c) Coplay Inc., MIT License.
3
- */
4
-
5
- /*
6
- ┌──────────────────────────────────────────────────────────────────┐
7
- │ Author: Ivan Murzak (https://github.com/IvanMurzak) │
8
- │ Repository: GitHub (https://github.com/IvanMurzak/Unity-MCP) │
9
- │ Copyright (c) 2025 Ivan Murzak │
10
- │ Licensed under the Apache License, Version 2.0. │
11
- │ See the LICENSE file in the project root for more information. │
12
- └──────────────────────────────────────────────────────────────────┘
13
- */
14
-
15
- #nullable enable
16
- using System;
17
- using System.ComponentModel;
18
- using AIGD;
19
- using com.AtelierAI.Uco.Framework;
20
- using com.IvanMurzak.ReflectorNet.Utils;
21
- using com.AtelierAI.Unity.Copilot.Editor.Utils;
22
-
23
- namespace com.AtelierAI.Unity.Copilot.Editor.API
24
- {
25
- public partial class Tool_ToolGroups
26
- {
27
- public const string ToolsSetGroupEnabledId = "tools-set-group-enabled";
28
-
29
- [UcoTool
30
- (
31
- ToolsSetGroupEnabledId,
32
- Title = "Tools / Set Group Enabled",
33
- DestructiveHint = true
34
- )]
35
- [UcoSkillDescription("Enable or disable an uco tool group at runtime, persisting the choice to EditorPrefs. " +
36
- "Use this together with 'tools-list-groups' to keep the LLM tool-list lean: turn off niche groups " +
37
- "(physics, profiler, vfx) until you need them. " +
38
- "NOTE: currently a soft hint — disabled tools remain callable; enforcement requires hooking the request pipeline.")]
39
- [UcoSkillBody("Toggle a logical tool group. " +
40
- "Groups are declared on `Tool_*` partial-class roots via `[ToolGroupAttribute(\"name\")]`. " +
41
- "This tool only updates the registry + EditorPrefs; it does not modify the upstream NuGet package " +
42
- "or hook `IRunTool.RunCallTool`, so toggling is informational only at the moment.\n\n" +
43
- "## Inputs\n\n" +
44
- "- `group` — group name (case-sensitive). Use `tools-list-groups` to discover valid names.\n" +
45
- "- `enabled` — true to enable the group, false to disable.\n\n" +
46
- "## Persistence\n\n" +
47
- "Stored under EditorPrefs key `UnityMcp.ToolGroups.Enabled` as a pipe-separated " +
48
- "`group=0|group=1` string. Stale entries (for groups that no longer exist) are ignored on load.")]
49
- [Description("Enable or disable an uco tool group at runtime, persisting the choice to EditorPrefs. " +
50
- "Soft hint only — disabled tools remain callable through the upstream request pipeline.")]
51
- public ToolGroupResult SetGroupEnabled
52
- (
53
- [Description("Group name. Use 'tools-list-groups' to discover valid group names.")]
54
- string group,
55
- [Description("True to enable the group, false to disable it.")]
56
- bool enabled
57
- )
58
- {
59
- if (string.IsNullOrWhiteSpace(group))
60
- throw new ArgumentException(Error.GroupNameIsEmpty(), nameof(group));
61
-
62
- return MainThread.Instance.Run(() =>
63
- {
64
- var canonicalGroup = ToolGroupRegistry.ResolveCanonicalGroup(group);
65
- if (canonicalGroup == null)
66
- throw new ArgumentException(Error.UnknownGroup(group), nameof(group));
67
-
68
- var previous = ToolGroupRegistry.IsGroupEnabled(canonicalGroup);
69
- if (previous != enabled)
70
- ToolGroupRegistry.SetGroupEnabled(canonicalGroup, enabled);
71
-
72
- var tools = ToolGroupRegistry.ToolsInGroup(canonicalGroup);
73
- var aliases = ToolGroupRegistry.AliasesForGroup(canonicalGroup);
74
- var aliasesArray = new string[aliases.Count];
75
- for (var i = 0; i < aliases.Count; i++) aliasesArray[i] = aliases[i];
76
-
77
- return new ToolGroupResult
78
- {
79
- Group = canonicalGroup,
80
- Enabled = enabled,
81
- RequestedEnabled = enabled,
82
- EffectiveEnabled = ToolGroupRegistry.IsGroupEffectivelyEnabled(canonicalGroup),
83
- Aliases = aliasesArray,
84
- PreviousEnabled = previous,
85
- Changed = previous != enabled,
86
- ToolCount = tools.Count,
87
- Note = SoftHintNote
88
- };
89
- });
90
- }
91
- }
92
- }
1
+ /*
2
+ * Design inspired by MCP for Unity (CoplayDev/unity-mcp), Copyright (c) Coplay Inc., MIT License.
3
+ */
4
+
5
+ /*
6
+ ┌──────────────────────────────────────────────────────────────────┐
7
+ │ Author: Ivan Murzak (https://github.com/IvanMurzak) │
8
+ │ Repository: GitHub (https://github.com/IvanMurzak/Unity-MCP) │
9
+ │ Copyright (c) 2025 Ivan Murzak │
10
+ │ Licensed under the Apache License, Version 2.0. │
11
+ │ See the LICENSE file in the project root for more information. │
12
+ └──────────────────────────────────────────────────────────────────┘
13
+ */
14
+
15
+ #nullable enable
16
+ using System;
17
+ using System.ComponentModel;
18
+ using AIGD;
19
+ using com.AtelierAI.Uco.Framework;
20
+ using com.IvanMurzak.ReflectorNet.Utils;
21
+ using com.AtelierAI.Unity.Copilot.Editor.Utils;
22
+
23
+ namespace com.AtelierAI.Unity.Copilot.Editor.API
24
+ {
25
+ public partial class Tool_ToolGroups
26
+ {
27
+ public const string ToolsSetGroupEnabledId = "tools-set-group-enabled";
28
+
29
+ [UcoTool
30
+ (
31
+ ToolsSetGroupEnabledId,
32
+ Title = "Tools / Set Group Enabled",
33
+ DestructiveHint = true
34
+ )]
35
+ [UcoSkillDescription("Enable or disable an uco tool group at runtime, persisting the choice to EditorPrefs. " +
36
+ "Use this together with 'tools-list-groups' to keep the LLM tool-list lean: turn off niche groups " +
37
+ "(physics, profiler, vfx) until you need them. " +
38
+ "NOTE: currently a soft hint — disabled tools remain callable; enforcement requires hooking the request pipeline.")]
39
+ [UcoSkillBody("Toggle a logical tool group. " +
40
+ "Groups are declared on `Tool_*` partial-class roots via `[ToolGroupAttribute(\"name\")]`. " +
41
+ "This tool only updates the registry + EditorPrefs; it does not modify the upstream NuGet package " +
42
+ "or hook `IRunTool.RunCallTool`, so toggling is informational only at the moment.\n\n" +
43
+ "## Inputs\n\n" +
44
+ "- `group` — group name (case-sensitive). Use `tools-list-groups` to discover valid names.\n" +
45
+ "- `enabled` — true to enable the group, false to disable.\n\n" +
46
+ "## Persistence\n\n" +
47
+ "Stored under the product EditorPrefs key `<prefix>.ToolGroups.Enabled` as a pipe-separated " +
48
+ "`group=0|group=1` string. Stale entries (for groups that no longer exist) are ignored on load.")]
49
+ [Description("Enable or disable an uco tool group at runtime, persisting the choice to EditorPrefs. " +
50
+ "Soft hint only — disabled tools remain callable through the upstream request pipeline.")]
51
+ public ToolGroupResult SetGroupEnabled
52
+ (
53
+ [Description("Group name. Use 'tools-list-groups' to discover valid group names.")]
54
+ string group,
55
+ [Description("True to enable the group, false to disable it.")]
56
+ bool enabled
57
+ )
58
+ {
59
+ if (string.IsNullOrWhiteSpace(group))
60
+ throw new ArgumentException(Error.GroupNameIsEmpty(), nameof(group));
61
+
62
+ return MainThread.Instance.Run(() =>
63
+ {
64
+ var canonicalGroup = ToolGroupRegistry.ResolveCanonicalGroup(group);
65
+ if (canonicalGroup == null)
66
+ throw new ArgumentException(Error.UnknownGroup(group), nameof(group));
67
+
68
+ var previous = ToolGroupRegistry.IsGroupEnabled(canonicalGroup);
69
+ if (previous != enabled)
70
+ ToolGroupRegistry.SetGroupEnabled(canonicalGroup, enabled);
71
+
72
+ var tools = ToolGroupRegistry.ToolsInGroup(canonicalGroup);
73
+ var aliases = ToolGroupRegistry.AliasesForGroup(canonicalGroup);
74
+ var aliasesArray = new string[aliases.Count];
75
+ for (var i = 0; i < aliases.Count; i++) aliasesArray[i] = aliases[i];
76
+
77
+ return new ToolGroupResult
78
+ {
79
+ Group = canonicalGroup,
80
+ Enabled = enabled,
81
+ RequestedEnabled = enabled,
82
+ EffectiveEnabled = ToolGroupRegistry.IsGroupEffectivelyEnabled(canonicalGroup),
83
+ Aliases = aliasesArray,
84
+ PreviousEnabled = previous,
85
+ Changed = previous != enabled,
86
+ ToolCount = tools.Count,
87
+ Note = SoftHintNote
88
+ };
89
+ });
90
+ }
91
+ }
92
+ }
@@ -222,153 +222,6 @@ namespace com.AtelierAI.Unity.Copilot.Editor
222
222
 
223
223
  #endregion // Node Server Discovery
224
224
 
225
- #region Client Configuration
226
-
227
- /// <summary>
228
- /// Generates a JSON configuration for stdio transport.
229
- /// <code>
230
- /// {
231
- /// "mcpServers": {
232
- /// "Unity ProjectName": {
233
- /// "type": "...", // optional, only if provided
234
- /// "command": "node",
235
- /// "args": ["path/to/bin/server.mjs", "--port", "...", "--plugin-timeout-ms", "...", "--authorization", "..." /*, "--token", "..." if auth required */]
236
- /// }
237
- /// }
238
- /// }
239
- /// </code>
240
- /// </summary>
241
- public static JsonNode RawJsonConfigurationStdio(
242
- int port,
243
- string bodyPath = "mcpServers",
244
- int timeoutMs = Consts.Hub.DefaultTimeoutMs,
245
- string? type = null)
246
- {
247
- var pathSegments = BodyPathSegments(bodyPath);
248
-
249
- // Build innermost content first
250
- var serverConfig = new JsonObject();
251
-
252
- if (type != null)
253
- serverConfig["type"] = type;
254
-
255
- // The AI agent launches the Node.js Uco server via the node runtime.
256
- // When the entry script cannot be resolved right now, fall back to the
257
- // documented project-local install location so the generated config is
258
- // still a valid, copy-pasteable starting point.
259
- var serverEntry = ResolveNodeServerEntry()
260
- ?? Path.Combine("node_modules", NodeServerPackageNames[0], NodeServerEntryRelativePath);
261
-
262
- serverConfig["command"] = ResolveNodeExecutable().Replace('\\', '/');
263
-
264
- var args = new JsonArray
265
- {
266
- serverEntry.Replace('\\', '/'),
267
- "--port",
268
- port.ToString(),
269
- "--plugin-timeout-ms",
270
- timeoutMs.ToString(),
271
- "--authorization",
272
- UnityCopilotPluginEditor.AuthOption.ToString()
273
- };
274
-
275
- var authRequired = UnityCopilotPluginEditor.AuthOption == AuthOption.required;
276
- if (authRequired && !string.IsNullOrEmpty(UnityCopilotPluginEditor.Token))
277
- {
278
- args.Add("--token");
279
- args.Add(UnityCopilotPluginEditor.Token);
280
- }
281
-
282
- serverConfig["args"] = args;
283
-
284
- var innerContent = new JsonObject
285
- {
286
- ["ai-game-developer"] = serverConfig
287
- };
288
-
289
- // Build nested structure from innermost to outermost
290
- var result = innerContent;
291
- for (int i = pathSegments.Length - 1; i >= 0; i--)
292
- {
293
- result = new JsonObject { [pathSegments[i]] = result };
294
- }
295
-
296
- return result;
297
- }
298
-
299
- /// <summary>
300
- /// Generates a JSON configuration for HTTP transport.
301
- /// <code>
302
- /// {
303
- /// "mcpServers": {
304
- /// "Unity ProjectName": {
305
- /// "type": "...", // optional, only if provided
306
- /// "url": "http://localhost:port",
307
- /// "headers": { // only if token is provided
308
- /// "Authorization": "Bearer token"
309
- /// }
310
- /// }
311
- /// }
312
- /// }
313
- /// </code>
314
- /// </summary>
315
- public static JsonNode RawJsonConfigurationHttp(
316
- string url,
317
- string bodyPath = "mcpServers",
318
- string? type = null)
319
- {
320
- // ── Safe-defaults advisory ────────────────────────────────────────────────
321
- // If the URL targets a remote host over plain HTTP and the user has not opted in
322
- // to insecure remote HTTP, log a single warning. We deliberately do NOT throw or
323
- // rewrite the URL here — the configurators are expected to produce *some* output
324
- // even when the configuration is sub-optimal, so the user can see what was
325
- // generated and decide. The dialog/UI gate handles refusal at start time.
326
- if (SafeDefaultsGuard.IsInsecureRemoteHttpUrl(url) &&
327
- !UnityCopilotPluginEditor.AllowInsecureRemoteHttp)
328
- {
329
- _logger.LogWarning(
330
- "Generating AI agent client config for plain-HTTP remote URL '{url}' without " +
331
- "AllowInsecureRemoteHttp. The token (if any) and tool payloads will be " +
332
- "sent unencrypted. Either switch to https:// or enable 'Allow Insecure " +
333
- "Remote HTTP' in the Game Developer window to silence this warning.",
334
- url);
335
- }
336
-
337
- var pathSegments = BodyPathSegments(bodyPath);
338
-
339
- // Build innermost content first
340
- var serverConfig = new JsonObject();
341
-
342
- if (type != null)
343
- serverConfig["type"] = type;
344
-
345
- serverConfig["url"] = url;
346
-
347
- var authRequired = UnityCopilotPluginEditor.AuthOption == AuthOption.required;
348
- if (authRequired && !string.IsNullOrEmpty(UnityCopilotPluginEditor.Token))
349
- {
350
- serverConfig["headers"] = new JsonObject
351
- {
352
- ["Authorization"] = $"Bearer {UnityCopilotPluginEditor.Token}"
353
- };
354
- }
355
-
356
- var innerContent = new JsonObject
357
- {
358
- ["ai-game-developer"] = serverConfig
359
- };
360
-
361
- // Build nested structure from innermost to outermost
362
- var result = innerContent;
363
- for (int i = pathSegments.Length - 1; i >= 0; i--)
364
- {
365
- result = new JsonObject { [pathSegments[i]] = result };
366
- }
367
-
368
- return result;
369
- }
370
-
371
- #endregion // Client Configuration
372
225
 
373
226
  #region Process Lifecycle
374
227
 
@@ -84,6 +84,22 @@ namespace com.AtelierAI.Unity.Copilot.Editor
84
84
  nameof(Startup), callerName, e.Message);
85
85
  }
86
86
  }
87
+
88
+ // Deterministic teardown on reload/unload/quit: dispose the plugin
89
+ // instance on a background thread (the safe context for the token
90
+ // cancellation callbacks — same reasoning as
91
+ // DisposeUcoPluginInstance). Without this, the instance survived
92
+ // domain unload undisposed and relied on GC finalization — the
93
+ // crash path fixed in uco-domain-reload-crash-20260919.
94
+ try
95
+ {
96
+ plugin.DisposeUcoPluginInstance();
97
+ }
98
+ catch (System.Exception e)
99
+ {
100
+ _logger.LogWarning(e, "{class} {method}: Exception during plugin disposal (non-blocking): {message}",
101
+ nameof(Startup), callerName, e.Message);
102
+ }
87
103
  }
88
104
 
89
105
  try
@@ -28,10 +28,10 @@ namespace com.AtelierAI.Unity.Copilot.Editor.UI
28
28
  private void SetupServerSection(VisualElement root)
29
29
  {
30
30
  var btnStartStop = root.Q<Button>("btnStartStopServer") ?? throw new InvalidOperationException("Server start/stop button not found.");
31
- var statusCircle = root.Q<VisualElement>("mcpServerStatusCircle") ?? throw new InvalidOperationException("Server status circle not found.");
32
- var statusLabel = root.Q<Label>("mcpServerLabel") ?? throw new InvalidOperationException("Server status label not found.");
31
+ var statusCircle = root.Q<VisualElement>("serverStatusCircle") ?? throw new InvalidOperationException("Server status circle not found.");
32
+ var statusLabel = root.Q<Label>("serverLabel") ?? throw new InvalidOperationException("Server status label not found.");
33
33
 
34
- var timelinePointServer = root.Q<VisualElement>("TimelinePointMcpServer");
34
+ var timelinePointServer = root.Q<VisualElement>("TimelinePointServer");
35
35
  if (timelinePointServer != null)
36
36
  timelinePointServer.tooltip = Tooltip_ServerTimelineLabel;
37
37
  statusCircle.tooltip = Tooltip_ServerTimelineLabel;