@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,96 +1,96 @@
1
- /*
2
- ┌──────────────────────────────────────────────────────────────────┐
3
- │ Author: Ivan Murzak (https://github.com/IvanMurzak/Unity-MCP) │
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;
13
- using System.ComponentModel;
14
- using com.AtelierAI.Uco.Framework;
15
- using UnityEngine;
16
-
17
- namespace com.AtelierAI.Unity.Copilot.Editor.API
18
- {
19
- public partial class Tool_Console
20
- {
21
- public const string ConsoleGetLogsToolId = "console-get-logs";
22
- [UcoTool
23
- (
24
- ConsoleGetLogsToolId,
25
- Title = "Console / Get Logs",
26
- ReadOnlyHint = true,
27
- IdempotentHint = true
28
- )]
29
- [UcoSkillDescription("Retrieve Unity Editor logs from the MCP plugin's `LogCollector`, " +
30
- "optionally filtered by log type, time window, operation/correlation identity, or source " +
31
- "(product / bridge / tool / unity). Useful for debugging and monitoring Editor activity.")]
32
- [UcoSkillBody("Retrieves Unity Editor logs with attribution and loss accounting.\n\n" +
33
- "## Inputs\n\n" +
34
- "- `maxEntries` (default 100, minimum 1) — caps the size of the returned array.\n" +
35
- "- `logTypeFilter` — Unity `LogType` filter; `null` returns all severities.\n" +
36
- "- `includeStackTrace` (default `false`) — include stack-trace strings in each entry.\n" +
37
- "- `lastMinutes` (default 0) — when non-zero, only logs from the last N minutes are returned.\n" +
38
- "- `correlationId` — only entries emitted inside that tool call's execution window.\n" +
39
- "- `operationId` — only entries attributed to that durable operation.\n" +
40
- "- `source` — one of `product`, `bridge`, `tool`, `unity`.\n" +
41
- "- `sinceUnixMs` — only entries at or after this Unix millisecond boundary.\n\n" +
42
- "## Attribution and loss accounting\n\n" +
43
- "Each entry carries `Source` and, when produced on the main thread inside an owned execution " +
44
- "window, `CorrelationId`/`OperationId`. The response reports `DroppedEntries` (lost to " +
45
- "capacity or storage failures) and `TruncatedEntries` (messages cut at the size limit) so an " +
46
- "empty result is distinguishable from a clean run.\n\n" +
47
- "## Example: new errors for one operation\n\n" +
48
- "`{ \"operationId\": \"<from tests-run>\", \"logTypeFilter\": \"Error\", \"sinceUnixMs\": 1760000000000, \"maxEntries\": 50 }`")]
49
- [Description("Retrieves Unity Editor logs with correlation/source attribution and loss accounting. " +
50
- "Useful for debugging and monitoring Unity Editor activity.")]
51
- public ConsoleLogsQueryResult GetLogs
52
- (
53
- [Description("Maximum number of log entries to return. Minimum: 1. Default: 100")]
54
- int maxEntries = 100,
55
- [Description("Filter by log type. 'null' means All.")]
56
- LogType? logTypeFilter = null,
57
- [Description("Include stack traces in the output. Default: false")]
58
- bool includeStackTrace = false,
59
- [Description("Return logs from the last N minutes. If 0, returns all available logs. Default: 0")]
60
- int lastMinutes = 0,
61
- [Description("Only entries emitted inside this tool call's execution window (correlation identity). Example: 'call-...'.")]
62
- string? correlationId = null,
63
- [Description("Only entries attributed to this durable operation id. Example: the operationId returned by tests-run.")]
64
- string? operationId = null,
65
- [Description("Source classification filter: 'product', 'bridge', 'tool', or 'unity'. 'null' returns all sources.")]
66
- string? source = null,
67
- [Description("Only entries at or after this Unix-epoch millisecond boundary. Record the boundary before an operation, then filter new entries here. Example: 1760000000000.")]
68
- long? sinceUnixMs = null
69
- )
70
- {
71
- // Validate parameters
72
- if (maxEntries < 1)
73
- throw new ArgumentException(Error.InvalidMaxEntries(maxEntries));
74
-
75
- if (!UnityCopilotPluginEditor.HasInstance)
76
- throw new InvalidOperationException("UnityCopilotPluginEditor is not initialized.");
77
-
78
- var logCollector = UnityCopilotPluginEditor.Instance.LogCollector;
79
- if (logCollector == null)
80
- throw new InvalidOperationException("LogCollector is not initialized.");
81
-
82
- var logs = logCollector.QueryDetailed(
83
- maxEntries: maxEntries,
84
- logTypeFilter: logTypeFilter,
85
- includeStackTrace: includeStackTrace,
86
- lastMinutes: lastMinutes,
87
- correlationId: correlationId,
88
- operationId: operationId,
89
- source: source,
90
- sinceUnixMs: sinceUnixMs
91
- );
92
-
93
- return logs;
94
- }
95
- }
1
+ /*
2
+ ┌──────────────────────────────────────────────────────────────────┐
3
+ │ Author: Ivan Murzak (https://github.com/IvanMurzak/Unity-MCP) │
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;
13
+ using System.ComponentModel;
14
+ using com.AtelierAI.Uco.Framework;
15
+ using UnityEngine;
16
+
17
+ namespace com.AtelierAI.Unity.Copilot.Editor.API
18
+ {
19
+ public partial class Tool_Console
20
+ {
21
+ public const string ConsoleGetLogsToolId = "console-get-logs";
22
+ [UcoTool
23
+ (
24
+ ConsoleGetLogsToolId,
25
+ Title = "Console / Get Logs",
26
+ ReadOnlyHint = true,
27
+ IdempotentHint = true
28
+ )]
29
+ [UcoSkillDescription("Retrieve Unity Editor logs from the Uco plugin's `LogCollector`, " +
30
+ "optionally filtered by log type, time window, operation/correlation identity, or source " +
31
+ "(product / bridge / tool / unity). Useful for debugging and monitoring Editor activity.")]
32
+ [UcoSkillBody("Retrieves Unity Editor logs with attribution and loss accounting.\n\n" +
33
+ "## Inputs\n\n" +
34
+ "- `maxEntries` (default 100, minimum 1) — caps the size of the returned array.\n" +
35
+ "- `logTypeFilter` — Unity `LogType` filter; `null` returns all severities.\n" +
36
+ "- `includeStackTrace` (default `false`) — include stack-trace strings in each entry.\n" +
37
+ "- `lastMinutes` (default 0) — when non-zero, only logs from the last N minutes are returned.\n" +
38
+ "- `correlationId` — only entries emitted inside that tool call's execution window.\n" +
39
+ "- `operationId` — only entries attributed to that durable operation.\n" +
40
+ "- `source` — one of `product`, `bridge`, `tool`, `unity`.\n" +
41
+ "- `sinceUnixMs` — only entries at or after this Unix millisecond boundary.\n\n" +
42
+ "## Attribution and loss accounting\n\n" +
43
+ "Each entry carries `Source` and, when produced on the main thread inside an owned execution " +
44
+ "window, `CorrelationId`/`OperationId`. The response reports `DroppedEntries` (lost to " +
45
+ "capacity or storage failures) and `TruncatedEntries` (messages cut at the size limit) so an " +
46
+ "empty result is distinguishable from a clean run.\n\n" +
47
+ "## Example: new errors for one operation\n\n" +
48
+ "`{ \"operationId\": \"<from tests-run>\", \"logTypeFilter\": \"Error\", \"sinceUnixMs\": 1760000000000, \"maxEntries\": 50 }`")]
49
+ [Description("Retrieves Unity Editor logs with correlation/source attribution and loss accounting. " +
50
+ "Useful for debugging and monitoring Unity Editor activity.")]
51
+ public ConsoleLogsQueryResult GetLogs
52
+ (
53
+ [Description("Maximum number of log entries to return. Minimum: 1. Default: 100")]
54
+ int maxEntries = 100,
55
+ [Description("Filter by log type. 'null' means All.")]
56
+ LogType? logTypeFilter = null,
57
+ [Description("Include stack traces in the output. Default: false")]
58
+ bool includeStackTrace = false,
59
+ [Description("Return logs from the last N minutes. If 0, returns all available logs. Default: 0")]
60
+ int lastMinutes = 0,
61
+ [Description("Only entries emitted inside this tool call's execution window (correlation identity). Example: 'call-...'.")]
62
+ string? correlationId = null,
63
+ [Description("Only entries attributed to this durable operation id. Example: the operationId returned by tests-run.")]
64
+ string? operationId = null,
65
+ [Description("Source classification filter: 'product', 'bridge', 'tool', or 'unity'. 'null' returns all sources.")]
66
+ string? source = null,
67
+ [Description("Only entries at or after this Unix-epoch millisecond boundary. Record the boundary before an operation, then filter new entries here. Example: 1760000000000.")]
68
+ long? sinceUnixMs = null
69
+ )
70
+ {
71
+ // Validate parameters
72
+ if (maxEntries < 1)
73
+ throw new ArgumentException(Error.InvalidMaxEntries(maxEntries));
74
+
75
+ if (!UnityCopilotPluginEditor.HasInstance)
76
+ throw new InvalidOperationException("UnityCopilotPluginEditor is not initialized.");
77
+
78
+ var logCollector = UnityCopilotPluginEditor.Instance.LogCollector;
79
+ if (logCollector == null)
80
+ throw new InvalidOperationException("LogCollector is not initialized.");
81
+
82
+ var logs = logCollector.QueryDetailed(
83
+ maxEntries: maxEntries,
84
+ logTypeFilter: logTypeFilter,
85
+ includeStackTrace: includeStackTrace,
86
+ lastMinutes: lastMinutes,
87
+ correlationId: correlationId,
88
+ operationId: operationId,
89
+ source: source,
90
+ sinceUnixMs: sinceUnixMs
91
+ );
92
+
93
+ return logs;
94
+ }
95
+ }
96
96
  }
@@ -1,139 +1,139 @@
1
- /*
2
- * Portions of this file are derived from MCP for Unity (CoplayDev/unity-mcp),
3
- * Copyright (c) Coplay Inc., licensed under the MIT License.
4
- * Original: https://github.com/CoplayDev/unity-mcp/blob/main/Server/src/services/tools/unity_docs.py
5
- */
6
-
7
- /*
8
- ┌──────────────────────────────────────────────────────────────────┐
9
- │ Author: Ivan Murzak (https://github.com/IvanMurzak) │
10
- │ Repository: GitHub (https://github.com/IvanMurzak/Unity-MCP) │
11
- │ Copyright (c) 2025 Ivan Murzak │
12
- │ Licensed under the Apache License, Version 2.0. │
13
- │ See the LICENSE file in the project root for more information. │
14
- └──────────────────────────────────────────────────────────────────┘
15
- */
16
-
17
- #nullable enable
18
- using System;
19
- using System.Collections.Concurrent;
20
- using System.Net;
21
- using System.Net.Http;
22
- using System.Threading;
23
- using System.Threading.Tasks;
24
-
25
- namespace com.AtelierAI.Unity.Copilot.Editor.API
26
- {
27
- public partial class Tool_Docs
28
- {
29
- /// <summary>
30
- /// Small async HTTP wrapper used by the docs-* tools. Holds a single shared
31
- /// <see cref="HttpClient"/>, applies a fixed timeout, follows redirects and
32
- /// caches successful responses in-memory for a short TTL so parallel lookups
33
- /// of the same URL only hit the network once.
34
- /// </summary>
35
- internal static class HttpFetcher
36
- {
37
- // Single shared HttpClient — recommended pattern. .NET pools sockets internally.
38
- private static readonly HttpClient s_client = CreateClient();
39
- private const string UserAgent = "Unity-MCP-Docs/1.0";
40
- private static readonly TimeSpan s_timeout = TimeSpan.FromSeconds(10);
41
- private static readonly TimeSpan s_cacheTtl = TimeSpan.FromSeconds(30);
42
-
43
- private static readonly ConcurrentDictionary<string, CacheEntry> s_cache = new();
44
-
45
- private static HttpClient CreateClient()
46
- {
47
- var handler = new HttpClientHandler
48
- {
49
- AllowAutoRedirect = true,
50
- AutomaticDecompression = DecompressionMethods.GZip | DecompressionMethods.Deflate,
51
- };
52
- var client = new HttpClient(handler)
53
- {
54
- Timeout = TimeSpan.FromSeconds(15) // hard cap; per-call CTS enforces s_timeout earlier.
55
- };
56
- client.DefaultRequestHeaders.UserAgent.ParseAdd(UserAgent);
57
- client.DefaultRequestHeaders.Accept.ParseAdd("text/html,application/xhtml+xml");
58
- return client;
59
- }
60
-
61
- /// <summary>
62
- /// Fetch a URL and return (statusCode, body, finalUrl). On network failure
63
- /// returns (-1, "", url) and sets <paramref name="errorMessage"/>.
64
- /// </summary>
65
- public static async Task<FetchResult> FetchAsync(string url)
66
- {
67
- if (s_cache.TryGetValue(url, out var cached) && cached.ExpiresAt > DateTime.UtcNow)
68
- return new FetchResult(cached.Status, cached.Body, cached.FinalUrl, null);
69
-
70
- using var cts = new CancellationTokenSource(s_timeout);
71
- try
72
- {
73
- using var resp = await s_client.GetAsync(url, HttpCompletionOption.ResponseContentRead, cts.Token).ConfigureAwait(false);
74
- var status = (int)resp.StatusCode;
75
- var body = status == 404
76
- ? string.Empty
77
- : await resp.Content.ReadAsStringAsync().ConfigureAwait(false);
78
- var final = resp.RequestMessage?.RequestUri?.ToString() ?? url;
79
-
80
- // Cache successful + 404 responses (not 5xx — those can be transient)
81
- if (status == 200 || status == 404)
82
- {
83
- s_cache[url] = new CacheEntry(status, body, final, DateTime.UtcNow + s_cacheTtl);
84
- }
85
-
86
- return new FetchResult(status, body, final, null);
87
- }
88
- catch (TaskCanceledException)
89
- {
90
- return new FetchResult(-1, string.Empty, url, $"Timed out after {s_timeout.TotalSeconds:F0}s fetching {url}.");
91
- }
92
- catch (HttpRequestException ex)
93
- {
94
- return new FetchResult(-1, string.Empty, url, $"HTTP error fetching {url}: {ex.Message}");
95
- }
96
- catch (Exception ex)
97
- {
98
- return new FetchResult(-1, string.Empty, url, $"Unexpected error fetching {url}: {ex.Message}");
99
- }
100
- }
101
-
102
- internal readonly struct FetchResult
103
- {
104
- public readonly int Status;
105
- public readonly string Body;
106
- public readonly string FinalUrl;
107
- public readonly string? ErrorMessage;
108
-
109
- public FetchResult(int status, string body, string finalUrl, string? errorMessage)
110
- {
111
- Status = status;
112
- Body = body;
113
- FinalUrl = finalUrl;
114
- ErrorMessage = errorMessage;
115
- }
116
-
117
- public bool IsOk => Status == 200;
118
- public bool IsNotFound => Status == 404;
119
- public bool IsNetworkError => Status == -1;
120
- }
121
-
122
- private readonly struct CacheEntry
123
- {
124
- public readonly int Status;
125
- public readonly string Body;
126
- public readonly string FinalUrl;
127
- public readonly DateTime ExpiresAt;
128
-
129
- public CacheEntry(int status, string body, string finalUrl, DateTime expiresAt)
130
- {
131
- Status = status;
132
- Body = body;
133
- FinalUrl = finalUrl;
134
- ExpiresAt = expiresAt;
135
- }
136
- }
137
- }
138
- }
139
- }
1
+ /*
2
+ * Portions of this file are derived from MCP for Unity (CoplayDev/unity-mcp),
3
+ * Copyright (c) Coplay Inc., licensed under the MIT License.
4
+ * Original: https://github.com/CoplayDev/unity-mcp/blob/main/Server/src/services/tools/unity_docs.py
5
+ */
6
+
7
+ /*
8
+ ┌──────────────────────────────────────────────────────────────────┐
9
+ │ Author: Ivan Murzak (https://github.com/IvanMurzak) │
10
+ │ Repository: GitHub (https://github.com/IvanMurzak/Unity-MCP) │
11
+ │ Copyright (c) 2025 Ivan Murzak │
12
+ │ Licensed under the Apache License, Version 2.0. │
13
+ │ See the LICENSE file in the project root for more information. │
14
+ └──────────────────────────────────────────────────────────────────┘
15
+ */
16
+
17
+ #nullable enable
18
+ using System;
19
+ using System.Collections.Concurrent;
20
+ using System.Net;
21
+ using System.Net.Http;
22
+ using System.Threading;
23
+ using System.Threading.Tasks;
24
+
25
+ namespace com.AtelierAI.Unity.Copilot.Editor.API
26
+ {
27
+ public partial class Tool_Docs
28
+ {
29
+ /// <summary>
30
+ /// Small async HTTP wrapper used by the docs-* tools. Holds a single shared
31
+ /// <see cref="HttpClient"/>, applies a fixed timeout, follows redirects and
32
+ /// caches successful responses in-memory for a short TTL so parallel lookups
33
+ /// of the same URL only hit the network once.
34
+ /// </summary>
35
+ internal static class HttpFetcher
36
+ {
37
+ // Single shared HttpClient — recommended pattern. .NET pools sockets internally.
38
+ private static readonly HttpClient s_client = CreateClient();
39
+ private const string UserAgent = "Unity-Uco-Docs/1.0";
40
+ private static readonly TimeSpan s_timeout = TimeSpan.FromSeconds(10);
41
+ private static readonly TimeSpan s_cacheTtl = TimeSpan.FromSeconds(30);
42
+
43
+ private static readonly ConcurrentDictionary<string, CacheEntry> s_cache = new();
44
+
45
+ private static HttpClient CreateClient()
46
+ {
47
+ var handler = new HttpClientHandler
48
+ {
49
+ AllowAutoRedirect = true,
50
+ AutomaticDecompression = DecompressionMethods.GZip | DecompressionMethods.Deflate,
51
+ };
52
+ var client = new HttpClient(handler)
53
+ {
54
+ Timeout = TimeSpan.FromSeconds(15) // hard cap; per-call CTS enforces s_timeout earlier.
55
+ };
56
+ client.DefaultRequestHeaders.UserAgent.ParseAdd(UserAgent);
57
+ client.DefaultRequestHeaders.Accept.ParseAdd("text/html,application/xhtml+xml");
58
+ return client;
59
+ }
60
+
61
+ /// <summary>
62
+ /// Fetch a URL and return (statusCode, body, finalUrl). On network failure
63
+ /// returns (-1, "", url) and sets <paramref name="errorMessage"/>.
64
+ /// </summary>
65
+ public static async Task<FetchResult> FetchAsync(string url)
66
+ {
67
+ if (s_cache.TryGetValue(url, out var cached) && cached.ExpiresAt > DateTime.UtcNow)
68
+ return new FetchResult(cached.Status, cached.Body, cached.FinalUrl, null);
69
+
70
+ using var cts = new CancellationTokenSource(s_timeout);
71
+ try
72
+ {
73
+ using var resp = await s_client.GetAsync(url, HttpCompletionOption.ResponseContentRead, cts.Token).ConfigureAwait(false);
74
+ var status = (int)resp.StatusCode;
75
+ var body = status == 404
76
+ ? string.Empty
77
+ : await resp.Content.ReadAsStringAsync().ConfigureAwait(false);
78
+ var final = resp.RequestMessage?.RequestUri?.ToString() ?? url;
79
+
80
+ // Cache successful + 404 responses (not 5xx — those can be transient)
81
+ if (status == 200 || status == 404)
82
+ {
83
+ s_cache[url] = new CacheEntry(status, body, final, DateTime.UtcNow + s_cacheTtl);
84
+ }
85
+
86
+ return new FetchResult(status, body, final, null);
87
+ }
88
+ catch (TaskCanceledException)
89
+ {
90
+ return new FetchResult(-1, string.Empty, url, $"Timed out after {s_timeout.TotalSeconds:F0}s fetching {url}.");
91
+ }
92
+ catch (HttpRequestException ex)
93
+ {
94
+ return new FetchResult(-1, string.Empty, url, $"HTTP error fetching {url}: {ex.Message}");
95
+ }
96
+ catch (Exception ex)
97
+ {
98
+ return new FetchResult(-1, string.Empty, url, $"Unexpected error fetching {url}: {ex.Message}");
99
+ }
100
+ }
101
+
102
+ internal readonly struct FetchResult
103
+ {
104
+ public readonly int Status;
105
+ public readonly string Body;
106
+ public readonly string FinalUrl;
107
+ public readonly string? ErrorMessage;
108
+
109
+ public FetchResult(int status, string body, string finalUrl, string? errorMessage)
110
+ {
111
+ Status = status;
112
+ Body = body;
113
+ FinalUrl = finalUrl;
114
+ ErrorMessage = errorMessage;
115
+ }
116
+
117
+ public bool IsOk => Status == 200;
118
+ public bool IsNotFound => Status == 404;
119
+ public bool IsNetworkError => Status == -1;
120
+ }
121
+
122
+ private readonly struct CacheEntry
123
+ {
124
+ public readonly int Status;
125
+ public readonly string Body;
126
+ public readonly string FinalUrl;
127
+ public readonly DateTime ExpiresAt;
128
+
129
+ public CacheEntry(int status, string body, string finalUrl, DateTime expiresAt)
130
+ {
131
+ Status = status;
132
+ Body = body;
133
+ FinalUrl = finalUrl;
134
+ ExpiresAt = expiresAt;
135
+ }
136
+ }
137
+ }
138
+ }
139
+ }
@@ -1,72 +1,72 @@
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.ComponentModel;
17
- using System.Linq;
18
- using com.AtelierAI.Uco.Framework;
19
- using com.IvanMurzak.ReflectorNet.Utils;
20
- using com.AtelierAI.Unity.Copilot.Editor.Utils;
21
-
22
- namespace com.AtelierAI.Unity.Copilot.Editor.API
23
- {
24
- public partial class Tool_Instance
25
- {
26
- public const string InstanceListAllToolId = "instance-list-all";
27
-
28
- [UcoTool
29
- (
30
- InstanceListAllToolId,
31
- Title = "Instance / List All",
32
- ReadOnlyHint = true,
33
- Enabled = false
34
- )]
35
- [UcoSkillDescription("List all Unity Editor instances registered on this machine plus identify the " +
36
- "calling Editor. Each entry carries port, project path, Unity version, PID, instance id and a liveness " +
37
- "flag (verified by checking that the PID is still running).")]
38
- [UcoSkillBody("Soft discovery of every Unity Editor that has registered itself with this machine's " +
39
- "MCP plugin. Each entry includes port, project path, Unity version, PID, stable instance id and an " +
40
- "`IsAlive` flag.\n\n" +
41
- "## Inputs\n\n" +
42
- "- `includeStale` (default `false`) — include rows whose registry file has not been refreshed in over " +
43
- "5 minutes. Useful for diagnosing crashed Editors that did not get a chance to clean up their entry.\n\n" +
44
- "## Behavior\n\n" +
45
- "Reads every `*.json` file under `%TEMP%/unity-mcp-instances/`. The calling Editor's row is marked " +
46
- "with `IsSelf=true`. `IsAlive` is determined by `Process.GetProcessById(pid)`.\n\n" +
47
- "## Limitation\n\n" +
48
- "This is discovery only — you can see which sibling Editors exist, but you cannot route tool calls to " +
49
- "them. Cross-instance routing requires server-side changes in the external NuGet " +
50
- "`com.AtelierAI.Uco.Framework` package and is not yet implemented.")]
51
- [Description("List all Unity Editor instances registered on this machine plus identify the calling Editor.")]
52
- public UnityInstanceListResult ListAll
53
- (
54
- [Description("Include stale entries (Editor exited without cleanup). Default false.")]
55
- bool includeStale = false
56
- )
57
- {
58
- return MainThread.Instance.Run(() =>
59
- {
60
- var entries = UnityInstanceRegistry.List(includeStale: includeStale).ToArray();
61
- var self = entries.FirstOrDefault(e => e.IsSelf);
62
- var currentId = self?.InstanceId
63
- ?? UnityInstanceRegistry.BuildSelfEntry().InstanceId;
64
- return new UnityInstanceListResult
65
- {
66
- Instances = entries,
67
- CurrentInstanceId = currentId,
68
- };
69
- });
70
- }
71
- }
72
- }
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.ComponentModel;
17
+ using System.Linq;
18
+ using com.AtelierAI.Uco.Framework;
19
+ using com.IvanMurzak.ReflectorNet.Utils;
20
+ using com.AtelierAI.Unity.Copilot.Editor.Utils;
21
+
22
+ namespace com.AtelierAI.Unity.Copilot.Editor.API
23
+ {
24
+ public partial class Tool_Instance
25
+ {
26
+ public const string InstanceListAllToolId = "instance-list-all";
27
+
28
+ [UcoTool
29
+ (
30
+ InstanceListAllToolId,
31
+ Title = "Instance / List All",
32
+ ReadOnlyHint = true,
33
+ Enabled = false
34
+ )]
35
+ [UcoSkillDescription("List all Unity Editor instances registered on this machine plus identify the " +
36
+ "calling Editor. Each entry carries port, project path, Unity version, PID, instance id and a liveness " +
37
+ "flag (verified by checking that the PID is still running).")]
38
+ [UcoSkillBody("Soft discovery of every Unity Editor that has registered itself with this machine's " +
39
+ "Uco plugin. Each entry includes port, project path, Unity version, PID, stable instance id and an " +
40
+ "`IsAlive` flag.\n\n" +
41
+ "## Inputs\n\n" +
42
+ "- `includeStale` (default `false`) — include rows whose registry file has not been refreshed in over " +
43
+ "5 minutes. Useful for diagnosing crashed Editors that did not get a chance to clean up their entry.\n\n" +
44
+ "## Behavior\n\n" +
45
+ "Reads every `*.json` file under `%TEMP%/unity-mcp-instances/`. The calling Editor's row is marked " +
46
+ "with `IsSelf=true`. `IsAlive` is determined by `Process.GetProcessById(pid)`.\n\n" +
47
+ "## Limitation\n\n" +
48
+ "This is discovery only — you can see which sibling Editors exist, but you cannot route tool calls to " +
49
+ "them. Cross-instance routing requires server-side changes in the external NuGet " +
50
+ "`com.AtelierAI.Uco.Framework` package and is not yet implemented.")]
51
+ [Description("List all Unity Editor instances registered on this machine plus identify the calling Editor.")]
52
+ public UnityInstanceListResult ListAll
53
+ (
54
+ [Description("Include stale entries (Editor exited without cleanup). Default false.")]
55
+ bool includeStale = false
56
+ )
57
+ {
58
+ return MainThread.Instance.Run(() =>
59
+ {
60
+ var entries = UnityInstanceRegistry.List(includeStale: includeStale).ToArray();
61
+ var self = entries.FirstOrDefault(e => e.IsSelf);
62
+ var currentId = self?.InstanceId
63
+ ?? UnityInstanceRegistry.BuildSelfEntry().InstanceId;
64
+ return new UnityInstanceListResult
65
+ {
66
+ Instances = entries,
67
+ CurrentInstanceId = currentId,
68
+ };
69
+ });
70
+ }
71
+ }
72
+ }