fix(mac): make rpc parsing tolerate stray stdout

This commit is contained in:
Peter Steinberger
2025-12-09 05:01:50 +01:00
parent f0860ec145
commit b04f04776b

View File

@@ -105,9 +105,7 @@ actor AgentRPC {
stdinHandle.write(data)
stdinHandle.write(Data([0x0A]))
let line = try await nextLine()
let parsed = try JSONSerialization.jsonObject(with: Data(line.utf8)) as? [String: Any]
guard let parsed else { throw RpcError(message: "invalid JSON") }
let parsed = try await self.nextJSONObject()
if let ok = parsed["ok"] as? Bool, let type = parsed["type"] as? String, type == "result" {
if ok {
@@ -147,10 +145,9 @@ actor AgentRPC {
stdinHandle.write(data)
stdinHandle.write(Data([0x0A]))
let line = try await nextLine()
let parsed = try JSONSerialization.jsonObject(with: Data(line.utf8)) as? [String: Any]
if let ok = parsed?["ok"] as? Bool, ok { return (true, nil) }
return (false, parsed?["error"] as? String ?? "rpc status failed: \(line)")
let parsed = try await self.nextJSONObject()
if let ok = parsed["ok"] as? Bool, ok { return (true, nil) }
return (false, parsed["error"] as? String ?? "rpc status failed: \(parsed)")
} catch {
self.logger.error("rpc status failed: \(error.localizedDescription, privacy: .public)")
await self.stop()
@@ -287,6 +284,25 @@ actor AgentRPC {
}
}
/// Read the next line that successfully parses as JSON. Non-JSON lines (e.g., stray stdout logs)
/// are skipped to keep the RPC bridge resilient to accidental prints.
private func nextJSONObject(maxSkips: Int = 30) async throws -> [String: Any] {
var skipped = 0
while true {
let line = try await self.nextLine()
guard let data = line.data(using: .utf8),
let obj = try? JSONSerialization.jsonObject(with: data) as? [String: Any]
else {
skipped += 1
if skipped >= maxSkips {
throw RpcError(message: "rpc returned non-JSON output: \(line)")
}
continue
}
return obj
}
}
private func parseHeartbeatEvent(from line: String) -> HeartbeatEvent? {
guard let data = line.data(using: .utf8) else { return nil }
guard