feat(nodes): add device status and info actions

This commit is contained in:
Ayaan Zaidi 2026-02-27 09:25:03 +05:30 committed by Ayaan Zaidi
parent 1f7b3c613d
commit 01f1d355a4
2 changed files with 80 additions and 11 deletions

View File

@ -174,6 +174,71 @@ describe("nodes notifications_list", () => {
});
});
describe("nodes device_status and device_info", () => {
it("invokes device.status and returns payload", async () => {
callGateway.mockImplementation(async ({ method, params }) => {
if (method === "node.list") {
return mockNodeList(["device.status", "device.info"]);
}
if (method === "node.invoke") {
expect(params).toMatchObject({
nodeId: NODE_ID,
command: "device.status",
params: {},
});
return {
payload: {
battery: { state: "charging", lowPowerModeEnabled: false },
},
};
}
return unexpectedGatewayMethod(method);
});
const result = await executeNodes({
action: "device_status",
node: NODE_ID,
});
expect(result.content?.[0]).toMatchObject({
type: "text",
text: expect.stringContaining('"battery"'),
});
});
it("invokes device.info and returns payload", async () => {
callGateway.mockImplementation(async ({ method, params }) => {
if (method === "node.list") {
return mockNodeList(["device.status", "device.info"]);
}
if (method === "node.invoke") {
expect(params).toMatchObject({
nodeId: NODE_ID,
command: "device.info",
params: {},
});
return {
payload: {
systemName: "Android",
appVersion: "1.0.0",
},
};
}
return unexpectedGatewayMethod(method);
});
const result = await executeNodes({
action: "device_info",
node: NODE_ID,
});
expect(result.content?.[0]).toMatchObject({
type: "text",
text: expect.stringContaining('"systemName"'),
});
});
});
describe("nodes run", () => {
it("passes invoke and command timeouts", async () => {
callGateway.mockImplementation(async ({ method, params }) => {

View File

@ -42,6 +42,8 @@ const NODES_TOOL_ACTIONS = [
"screen_record",
"location_get",
"notifications_list",
"device_status",
"device_info",
"run",
"invoke",
] as const;
@ -297,12 +299,23 @@ export function createNodesTool(options?: {
const result: AgentToolResult<unknown> = { content, details };
return await sanitizeToolResultImages(result, "nodes:camera_snap", imageSanitization);
}
case "camera_list": {
case "camera_list":
case "notifications_list":
case "device_status":
case "device_info": {
const node = readStringParam(params, "node", { required: true });
const command =
action === "camera_list"
? "camera.list"
: action === "notifications_list"
? "notifications.list"
: action === "device_status"
? "device.status"
: "device.info";
const payloadRaw = await invokeNodeCommandPayload({
gatewayOpts,
node,
command: "camera.list",
command,
});
const payload =
payloadRaw && typeof payloadRaw === "object" && payloadRaw !== null ? payloadRaw : {};
@ -430,15 +443,6 @@ export function createNodesTool(options?: {
});
return jsonResult(payload);
}
case "notifications_list": {
const node = readStringParam(params, "node", { required: true });
const payload = await invokeNodeCommandPayload({
gatewayOpts,
node,
command: "notifications.list",
});
return jsonResult(payload);
}
case "run": {
const node = readStringParam(params, "node", { required: true });
const nodes = await listNodes(gatewayOpts);