From ffbd02fe8ed9146056442766eb98e5328abbcb6e Mon Sep 17 00:00:00 2001 From: Vincent Koc Date: Tue, 2 Jun 2026 05:52:31 +0200 Subject: [PATCH] fix(agents): preserve null node payloads --- src/agents/tools/nodes-tool-commands.ts | 4 +++- src/agents/tools/nodes-tool.test.ts | 13 +++++++++++++ 2 files changed, 16 insertions(+), 1 deletion(-) diff --git a/src/agents/tools/nodes-tool-commands.ts b/src/agents/tools/nodes-tool-commands.ts index 5d615b530356..85de34c488b4 100644 --- a/src/agents/tools/nodes-tool-commands.ts +++ b/src/agents/tools/nodes-tool-commands.ts @@ -179,5 +179,7 @@ async function invokeNodeCommandPayload(params: { params: params.commandParams ?? {}, idempotencyKey: crypto.randomUUID(), }); - return raw?.payload ?? {}; + return raw && typeof raw === "object" && Object.hasOwn(raw, "payload") + ? raw.payload + : {}; } diff --git a/src/agents/tools/nodes-tool.test.ts b/src/agents/tools/nodes-tool.test.ts index 9c46e0ebd6ef..9a2cf4949da0 100644 --- a/src/agents/tools/nodes-tool.test.ts +++ b/src/agents/tools/nodes-tool.test.ts @@ -462,6 +462,19 @@ describe("createNodesTool screen_record duration guardrails", () => { }); }); + it("preserves explicit null location_get payloads from node.invoke", async () => { + gatewayMocks.callGatewayTool.mockResolvedValue({ payload: null }); + const tool = createNodesTool(); + + const result = await tool.execute("call-location-null", { + action: "location_get", + node: "macbook", + }); + + expect(result.details).toBeNull(); + expect(result.content).toEqual([{ type: "text", text: "null" }]); + }); + it("uses operator.pairing plus operator.admin to approve exec-capable node pair requests", async () => { mockNodePairApproveFlow({ requiredApproveScopes: ["operator.pairing", "operator.admin"],