fix(macos): return paired-node Codex catalogs without native supervision (#126811)

* fix(macos): route Codex catalog to plugin worker

* fix(macos): freeze Codex catalog ownership per invoke

---------

Co-authored-by: Josh Lehman <550978+jalehman@users.noreply.github.com>
This commit is contained in:
Vitor Cepeda Lopes
2026-08-25 00:24:27 +01:00
committed by GitHub
parent 9abfc1b4a3
commit b71a09fd8a
2 changed files with 37 additions and 7 deletions
@@ -305,7 +305,15 @@ actor MacNodeRuntime {
}
private func handleCodexThreadInvoke(_ req: BridgeInvokeRequest) async throws -> BridgeInvokeResponse {
guard self.codexThreadCatalogEnabled() else {
// Freeze native ownership before awaiting worker support so one invocation cannot switch owners.
let nativeCatalogEnabled = self.codexThreadCatalogEnabled()
if !nativeCatalogEnabled,
let nodeHostWorker,
await nodeHostWorker.supports(req.command)
{
return await nodeHostWorker.invoke(req)
}
guard nativeCatalogEnabled else {
return Self.errorResponse(
req,
code: .unavailable,
@@ -2,6 +2,7 @@ import Darwin
import Foundation
import OpenClawKit
import OpenClawProtocol
import os
import Testing
@testable import OpenClaw
@@ -211,12 +212,33 @@ struct MacNodeHostWorkerTests {
}
@Test(arguments: [
(
MacNodeCodexThreadCatalogContract.listCommand,
"UNAVAILABLE: Codex session catalog is disabled"),
(
MacNodeCodexThreadCatalogContract.turnsCommand,
"UNAVAILABLE: Codex session catalog is disabled"),
MacNodeCodexThreadCatalogContract.listCommand,
MacNodeCodexThreadCatalogContract.turnsCommand,
])
func `worker owns Codex catalog commands when native catalog is disabled`(command: String) async {
let worker = StubMacNodeHostWorker(commands: [command])
let nativeCatalogEnabledReads = OSAllocatedUnfairLock(initialState: 0)
let runtime = MacNodeRuntime(
nodeHostWorker: worker,
codexThreadCatalogEnabled: {
nativeCatalogEnabledReads.withLock {
$0 += 1
return false
}
})
let response = await runtime.handleInvoke(BridgeInvokeRequest(
id: "worker-codex-catalog",
command: command,
paramsJSON: #"{"limit":1}"#))
#expect(response.ok)
#expect(response.payloadJSON == #"{"owner":"cli"}"#)
#expect(await worker.invokedCommands() == [command])
#expect(nativeCatalogEnabledReads.withLock { $0 } == 1)
}
@Test(arguments: [
(
MacNodeClaudeSessionCatalogContract.listCommand,
"UNAVAILABLE: Claude session catalog is disabled"),