import Foundation // Public entry point used by both SwiftPM executable and Xcode app target. // Preserves AF_UNIX privacy-host protocol exactly as before. // Headless design: socket-server or stdin JSON-lines mode only. public func runReynaCLIHost(arguments: [String] = CommandLine.arguments) -> Never { if let idx = arguments.firstIndex(of: "--socket") { let nextIdx = idx + 1 guard nextIdx < arguments.count else { fputs("error: --socket requires a path argument\n", stderr) Darwin.exit(2) } let socketPath = arguments[nextIdx] runSocketServer(socketPath: socketPath) } else { runStdinLoop() } } func extractRecoverableId(from data: Data) -> String? { if let obj = try? JSONSerialization.jsonObject(with: data, options: []) as? [String: Any], let id = obj["id"] as? String { return id } guard let str = String(data: data, encoding: .utf8) else { return nil } let pattern = "\"id\"\\s*:\\s*\"([^\"]*)\"" guard let regex = try? NSRegularExpression(pattern: pattern, options: []), let match = regex.firstMatch(in: str, options: [], range: NSRange(str.startIndex..., in: str)), match.numberOfRanges >= 2, let r = Range(match.range(at: 1), in: str) else { return nil } return String(str[r]) } func writeResponse(_ response: Response) { guard let jsonData = try? JSONEncoder().encode(response), let jsonString = String(data: jsonData, encoding: .utf8), let outData = (jsonString + "\n").data(using: .utf8) else { return } FileHandle.standardOutput.write(outData) } func handleLine(_ lineData: Data) { if lineData.isEmpty { return } if let s = String(data: lineData, encoding: .utf8), s.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty { return } if let request = try? JSONDecoder().decode(Request.self, from: lineData) { let response = dispatch(request: request) writeResponse(response) } else { let recoveredId = extractRecoverableId(from: lineData) let err = ErrorPayload(code: "invalid_request", message: "Invalid request JSON") let resp = Response(id: recoveredId ?? "", ok: false, result: nil, error: err) writeResponse(resp) } } func runStdinLoop() -> Never { while let line = readLine() { if line.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty { continue } if let data = line.data(using: .utf8) { handleLine(data) } else { let err = ErrorPayload(code: "invalid_request", message: "Invalid request encoding") let resp = Response(id: "", ok: false, result: nil, error: err) writeResponse(resp) } } Darwin.exit(0) }