XFE Git
XFE Studio Git
Git 首页 全局搜索
XFE 主站 文档 NuGet

XFE.SpaceEngineers.AgentBridge

【SpaceEngineer】AI调试插件

公开
关注 0 Fork 0 Star 0
UTF-8
using System.Diagnostics;
using System.Text.Json;

namespace XFE.SeAgent.Cli;

public sealed record AgentEndpoint(string Version, int ProtocolVersion, string PipeName, int Pid, DateTimeOffset StartTimeUtc, string ExecutablePath, DateTimeOffset CreatedUtc);
public sealed record ProcessIdentity(string ExecutablePath, DateTimeOffset StartTimeUtc);

public interface IProcessInspector
{
    ProcessIdentity? Inspect(int pid);
}

public sealed class LocalProcessInspector : IProcessInspector
{
    public ProcessIdentity? Inspect(int pid)
    {
        try
        {
            using var process = Process.GetProcessById(pid);
            if (process.HasExited || process.MainModule?.FileName is not string executable) return null;
            return new(executable, new DateTimeOffset(process.StartTime.ToUniversalTime()));
        }
        catch (ArgumentException) { return null; }
        catch (InvalidOperationException) { return null; }
        catch (System.ComponentModel.Win32Exception) { return null; }
    }
}

public sealed class EndpointDiscovery(IProcessInspector? inspector = null)
{
    private readonly IProcessInspector inspector = inspector ?? new LocalProcessInspector();
    private static readonly JsonSerializerOptions Json = new(JsonSerializerDefaults.Web);
    public static string DefaultDirectory => Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), "XFE", "SpaceEngineersAgent", "endpoints");

    public IReadOnlyList<AgentEndpoint> Discover(string? directory = null)
    {
        directory ??= DefaultDirectory;
        if (!Directory.Exists(directory)) return [];
        var found = new List<AgentEndpoint>();
        foreach (string file in Directory.EnumerateFiles(directory, "*.json").Take(1024))
        {
            try
            {
                if (new FileInfo(file).Length > 65536) continue;
                var endpoint = JsonSerializer.Deserialize<AgentEndpoint>(File.ReadAllText(file), Json);
                if (endpoint == null || endpoint.ProtocolVersion != 1 || endpoint.Pid <= 0 || string.IsNullOrWhiteSpace(endpoint.Version) || endpoint.PipeName != "XFE.SE.Agent." + endpoint.Pid ||
                    !Path.IsPathFullyQualified(endpoint.ExecutablePath) || Path.GetFileNameWithoutExtension(file) != endpoint.Pid.ToString(System.Globalization.CultureInfo.InvariantCulture)) continue;
                var process = inspector.Inspect(endpoint.Pid);
                if (process == null || process.StartTimeUtc.UtcTicks != endpoint.StartTimeUtc.UtcTicks || !Path.GetFullPath(process.ExecutablePath).Equals(Path.GetFullPath(endpoint.ExecutablePath), StringComparison.OrdinalIgnoreCase)) continue;
                found.Add(endpoint);
            }
            catch (Exception ex) when (ex is IOException or UnauthorizedAccessException or JsonException or ArgumentException) { }
        }
        return found.OrderBy(item => item.Pid).ToArray();
    }
}