using System.Text; using NucleicBroker; // nucleic-brokerd (docs/WINDOWS_PORT.md §2.3): child of nucleic-hostd, NDJSON JSON-RPC 2.0 // over stdio. Exits when stdin closes (hostd died or shut down); on Windows the Job Object // hostd assigns kills us anyway — this is the graceful path. // // stdout carries ONLY protocol lines (the OutboundWriter is its single writer); every // diagnostic goes to stderr, which hostd logs. Console.OutputEncoding = Encoding.UTF8; IWslc wslc = #if USE_WSLC // Create(), not `new`: it configures COM security first, and that MUST precede the process's // first COM call (docs/WINDOWS_PORT.md §13.2). Constructing the facade directly compiles fine // and silently loses session recovery to a 0x80070542 that reads as "not found". NucleicBroker.Wslc.WslcFacade.Create(); #else new UnavailableWslc(); #endif IAiProvider ai = new UnavailableAiProvider(); var stdout = new StreamWriter(Console.OpenStandardOutput(), new UTF8Encoding(false)) { AutoFlush = false }; var outbound = new OutboundWriter(stdout); var service = new BrokerService(wslc, ai, outbound); using var stdin = new StreamReader(Console.OpenStandardInput(), Encoding.UTF8); var inFlight = new List(); for (string? line; (line = await stdin.ReadLineAsync()) is not null;) { if (line.Length == 0) continue; // Requests run concurrently (a long image.pull must not block container.list); the // outbound writer serializes their responses. Track them so shutdown can drain. inFlight.Add(service.HandleLineAsync(line)); inFlight.RemoveAll(t => t.IsCompleted); } await Task.WhenAll(inFlight).ConfigureAwait(false); await outbound.CompleteAsync().ConfigureAwait(false);