Build: fix RPC sendable params and CLI imports

This commit is contained in:
Peter Steinberger
2025-12-09 03:33:16 +01:00
parent a8b26570e0
commit c568284f1b
4 changed files with 17 additions and 10 deletions

View File

@@ -1,6 +1,10 @@
import Foundation
import OSLog
struct ControlRequestParams: @unchecked Sendable {
let raw: [String: AnyHashable]
}
actor AgentRPC {
static let shared = AgentRPC()
@@ -173,13 +177,13 @@ actor AgentRPC {
}
}
func controlRequest(method: String, params: [String: Any]? = nil) async throws -> Data {
func controlRequest(method: String, params: ControlRequestParams? = nil) async throws -> Data {
if self.process?.isRunning != true {
try await self.start()
}
let id = UUID().uuidString
var frame: [String: Any] = ["type": "control-request", "id": id, "method": method]
if let params { frame["params"] = params }
if let params { frame["params"] = params.raw }
let data = try JSONSerialization.data(withJSONObject: frame)
guard let stdinHandle else { throw RpcError(message: "stdin missing") }
return try await withCheckedThrowingContinuation { (cont: CheckedContinuation<Data, Error>) in

View File

@@ -71,6 +71,7 @@ final class ControlChannel: ObservableObject {
enum ConnectionState: Equatable {
case disconnected
case connecting
case connected
case degraded(String)
}
@@ -87,6 +88,7 @@ final class ControlChannel: ObservableObject {
func configure() async {
do {
self.state = .connecting
try await AgentRPC.shared.start()
self.state = .connected
} catch {
@@ -96,11 +98,11 @@ final class ControlChannel: ObservableObject {
func configure(mode: Mode) async throws {
// Mode is retained for API compatibility; transport is always stdio now.
try await self.configure()
await self.configure()
}
func health(timeout: TimeInterval? = nil) async throws -> Data {
let params = timeout.map { ["timeoutMs": Int($0 * 1000)] }
let params = timeout.map { ControlRequestParams(raw: ["timeoutMs": AnyHashable(Int($0 * 1000))]) }
do {
let start = Date()
let payload = try await AgentRPC.shared.controlRequest(method: "health", params: params)
@@ -120,7 +122,7 @@ final class ControlChannel: ObservableObject {
return try? JSONDecoder().decode(ControlHeartbeatEvent.self, from: data)
}
func request(method: String, params: [String: Any]? = nil) async throws -> Data {
func request(method: String, params: ControlRequestParams? = nil) async throws -> Data {
do {
let data = try await AgentRPC.shared.controlRequest(method: method, params: params)
self.state = .connected
@@ -132,7 +134,9 @@ final class ControlChannel: ObservableObject {
}
func sendSystemEvent(_ text: String) async throws {
_ = try await self.request(method: "system-event", params: ["text": text])
_ = try await self.request(
method: "system-event",
params: ControlRequestParams(raw: ["text": AnyHashable(text)]))
}
}

View File

@@ -79,14 +79,14 @@ struct VoiceWakeChimeCatalog {
private static let discoveredSoundMap: [String: URL] = {
var map: [String: URL] = [:]
for root in self.searchRoots {
for root in Self.searchRoots {
guard let contents = try? FileManager.default.contentsOfDirectory(
at: root,
includingPropertiesForKeys: nil,
options: [.skipsHiddenFiles])
else { continue }
for url in contents where self.allowedExtensions.contains(url.pathExtension.lowercased()) {
for url in contents where Self.allowedExtensions.contains(url.pathExtension.lowercased()) {
let name = url.deletingPathExtension().lastPathComponent
// Preserve the first match in priority order.
if map[name] == nil {

View File

@@ -12,7 +12,6 @@ import {
getLastHeartbeatEvent,
onHeartbeatEvent,
} from "../infra/heartbeat-events.js";
import { onAgentEvent } from "../infra/agent-events.js";
import { getResolvedLoggerSettings } from "../logging.js";
import {
loginWeb,
@@ -35,8 +34,8 @@ import {
} from "../webchat/server.js";
import { createDefaultDeps, logWebSelfId } from "./deps.js";
import { onAgentEvent } from "../infra/agent-events.js";
import { enqueueSystemEvent } from "../infra/system-events.js";
import {
enqueueSystemEvent,
listSystemPresence,
updateSystemPresence,
} from "../infra/system-presence.js";