Core: update shared gateway models

This commit is contained in:
Mariano Belinky
2026-02-02 12:58:16 +00:00
parent ff6114599e
commit 37eaca719a
6 changed files with 31 additions and 14 deletions

View File

@@ -360,11 +360,12 @@ actor GatewayConnection {
await client.shutdown()
}
self.lastSnapshot = nil
let resolvedSessionBox = self.sessionBox ?? Self.buildSessionBox(url: url)
self.client = GatewayChannelActor(
url: url,
token: token,
password: password,
session: self.sessionBox,
session: resolvedSessionBox,
pushHandler: { [weak self] push in
await self?.handle(push: push)
})
@@ -380,6 +381,21 @@ actor GatewayConnection {
private static func defaultConfigProvider() async throws -> Config {
try await GatewayEndpointStore.shared.requireConfig()
}
private static func buildSessionBox(url: URL) -> WebSocketSessionBox? {
guard url.scheme?.lowercased() == "wss" else { return nil }
let host = url.host ?? "gateway"
let port = url.port ?? 443
let stableID = "\(host):\(port)"
let stored = GatewayTLSStore.loadFingerprint(stableID: stableID)
let params = GatewayTLSParams(
required: true,
expectedFingerprint: stored,
allowTOFU: true,
storeKey: stableID)
let session = GatewayTLSPinningSession(params: params)
return WebSocketSessionBox(session: session)
}
}
// MARK: - Typed gateway API

View File

@@ -428,9 +428,7 @@ public actor GatewayChannelActor {
guard let self else { return }
await self.watchTicks()
}
if let pushHandler = self.pushHandler {
Task { await pushHandler(.snapshot(ok)) }
}
await self.pushHandler?(.snapshot(ok))
}
private func listen() {

View File

@@ -16,7 +16,6 @@ public actor GatewayNodeSession {
private let logger = Logger(subsystem: "ai.openclaw", category: "node.gateway")
private let decoder = JSONDecoder()
private let encoder = JSONEncoder()
private static let defaultInvokeTimeoutMs = 30_000
private var channel: GatewayChannelActor?
private var activeURL: URL?
private var activeToken: String?
@@ -36,8 +35,8 @@ public actor GatewayNodeSession {
) async -> BridgeInvokeResponse {
let timeoutLogger = Logger(subsystem: "ai.openclaw", category: "node.gateway")
let timeout: Int = {
if let timeoutMs { return max(0, timeoutMs) }
return Self.defaultInvokeTimeoutMs
guard let timeoutMs else { return 0 }
return max(0, timeoutMs)
}()
guard timeout > 0 else {
return await onInvoke(request)
@@ -154,8 +153,10 @@ public actor GatewayNodeSession {
do {
try await channel.connect()
_ = await self.waitForSnapshot(timeoutMs: 500)
await self.notifyConnectedIfNeeded()
let snapshotReady = await self.waitForSnapshot(timeoutMs: 500)
if snapshotReady {
await self.notifyConnectedIfNeeded()
}
} catch {
await onDisconnected(error.localizedDescription)
throw error

View File

@@ -73,6 +73,11 @@ public final class GatewayTLSPinningSession: NSObject, WebSocketSessioning, URLS
if let expected {
if fingerprint == expected {
completionHandler(.useCredential, URLCredential(trust: trust))
} else if params.allowTOFU {
if let storeKey = params.storeKey {
GatewayTLSStore.saveFingerprint(fingerprint, stableID: storeKey)
}
completionHandler(.useCredential, URLCredential(trust: trust))
} else {
completionHandler(.cancelAuthenticationChallenge, nil)
}

View File

@@ -454,7 +454,7 @@ export function createNodesTool(options?: {
invokeParams = JSON.parse(invokeParamsJson);
} catch (err) {
const message = err instanceof Error ? err.message : String(err);
throw new Error(`invokeParamsJson must be valid JSON: ${message}`);
throw new Error(`invokeParamsJson must be valid JSON: ${message}`, { cause: err });
}
}
const invokeTimeoutMs = parseTimeoutMs(params.invokeTimeoutMs);

View File

@@ -187,10 +187,7 @@ export const handlePTTCommand: CommandHandler = async (params, allowTextCommands
params: invokeParams,
config: cfg,
});
const payload =
res.payload && typeof res.payload === "object"
? (res.payload as Record<string, unknown>)
: {};
const payload = res.payload && typeof res.payload === "object" ? res.payload : {};
const lines = [`PTT ${actionKey}${nodeId}`];
if (typeof payload.status === "string") {