Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ All notable public changes to Nexus Unity are documented here.
- Consolidated duplicate internal Ollama-review and serialized-property write helpers.

### Fixed
- `TriggerSafeAssetRefresh` callback is now tracked to prevent callback leaks, duplicate refresh hooks, and memory leaks across assembly reload/shutdown boundaries, with a fail-safe 15-second timeout guard.
- `run_tests` now reports `Submitted` rather than `Success` after Unity accepts its asynchronous request, and `run_tests_wait` now returns rejected submissions immediately instead of polling until timeout.
- Auto Setup now reports a clear refresh-and-retry message if a client is unavailable after the integration list is regenerated, instead of throwing an exception.

Expand Down
38 changes: 34 additions & 4 deletions Editor/MCPServerMethods.Hierarchy.cs
Original file line number Diff line number Diff line change
Expand Up @@ -301,8 +301,27 @@ private static void EnsureParentDirectory(string fullPath)
if (!string.IsNullOrEmpty(directory)) System.IO.Directory.CreateDirectory(directory);
}

private static EditorApplication.CallbackFunction _pendingRefreshCallback;

static MCPServerMethods()
{
AssemblyReloadEvents.beforeAssemblyReload += CleanupPendingRefresh;
EditorApplication.quitting += CleanupPendingRefresh;
}

private static void CleanupPendingRefresh()
{
if (_pendingRefreshCallback != null)
{
EditorApplication.update -= _pendingRefreshCallback;
_pendingRefreshCallback = null;
}
}

private static void TriggerSafeAssetRefresh()
{
CleanupPendingRefresh();

_scriptRefreshBusyUntilUtc = DateTime.UtcNow.AddSeconds(8);

// Scripts trigger domain reload which blocks the HTTP response.
Expand All @@ -314,16 +333,27 @@ private static void TriggerSafeAssetRefresh()
AppNapBypass.ScheduleActivation();
#endif

EditorApplication.CallbackFunction waitForFocus = null;
waitForFocus = () => {
EditorApplication.update -= waitForFocus;
double startTime = EditorApplication.timeSinceStartup;
double timeoutSeconds = 15.0; // Fail-safe fallback timeout

_pendingRefreshCallback = () => {
var cb = _pendingRefreshCallback;
if (cb == null) return;
EditorApplication.update -= cb;
_pendingRefreshCallback = null;

if (EditorApplication.timeSinceStartup - startTime > timeoutSeconds)
{
NexusEditorLog.Warning(NexusLogCategory.Api, "[MCP] TriggerSafeAssetRefresh timed out waiting for OS focus. Refresh aborted.");
return;
}

// Trigger refresh immediately. With App Nap bypassed, this is reliable
// even if the focus-switch (open -a) is still in flight.
AssetDatabase.Refresh();
};

EditorApplication.update += waitForFocus;
EditorApplication.update += _pendingRefreshCallback;
}
}
}
Loading