// Modified for AGC: bounded preparation, dispatch observation and local selection invalidation.
using System.Collections.Concurrent;
using System.Diagnostics;
using System.Text.Json.Nodes;
namespace DotCraft.Unity;
/// Local Mono Editor connection and target-side execution.
public sealed class UnityAttachService(string cacheRoot, string nativeBootstrapPath) : IAsyncDisposable
{
private static readonly TimeSpan HandshakeTimeout = TimeSpan.FromSeconds(60);
private readonly SemaphoreSlim gate = new(1, 1);
private readonly ConcurrentDictionary owned = new();
private readonly ConcurrentDictionary selected = new(StringComparer.Ordinal);
private readonly ConcurrentDictionary executions = new(StringComparer.Ordinal);
private readonly string clientId = Guid.NewGuid().ToString("N");
private bool disposed;
private string? runtimeIdentity;
private string? extractedNative;
private string CacheRoot => resolvedCacheRoot ?? cacheRoot;
private string? resolvedCacheRoot;
private string NativeBootstrapPath => extractedNative ??=
string.IsNullOrEmpty(nativeBootstrapPath) ? AttachStorage.ExtractNative(CacheRoot) : nativeBootstrapPath;
private string RuntimeIdentity => runtimeIdentity ??= AttachStorage.RuntimeIdentity(NativeBootstrapPath);
/// Creates an Attach client using the shared per-user rendezvous.
public static UnityAttachService CreateDefault() => new(AttachStorage.DefaultRoot, "");
/// Lists running local Unity Editors without attaching.
public object List()
{
var targets = new List