import type { Command } from "commander"; import { randomIdempotencyKey } from "../../gateway/call.js"; import { defaultRuntime } from "../../runtime.js"; import { getNodesTheme, runNodesCommand } from "./cli-utils.js"; import { callGatewayCli, nodesCallOpts, resolveNodeId } from "./rpc.js"; import type { NodesRpcOpts } from "./types.js"; export function registerNodesNotifyCommand(nodes: Command) { nodesCallOpts( nodes .command("notify") .description("Send a local notification on a node (mac only)") .requiredOption("--node ", "Node id, name, or IP") .option("--title ", "Notification title") .option("--body ", "Notification body") .option("--sound ", "Notification sound") .option("--priority ", "Notification priority") .option("--delivery ", "Delivery mode", "system") .option("--invoke-timeout ", "Node invoke timeout in ms (default 15000)", "15000") .action(async (opts: NodesRpcOpts) => { await runNodesCommand("notify", async () => { const nodeId = await resolveNodeId(opts, String(opts.node ?? "")); const title = String(opts.title ?? "").trim(); const body = String(opts.body ?? "").trim(); if (!title && !body) { throw new Error("missing --title or --body"); } const invokeTimeout = opts.invokeTimeout ? Number.parseInt(String(opts.invokeTimeout), 10) : undefined; const invokeParams: Record = { nodeId, command: "system.notify", params: { title, body, sound: opts.sound, priority: opts.priority, delivery: opts.delivery, }, idempotencyKey: String(opts.idempotencyKey ?? randomIdempotencyKey()), }; if (typeof invokeTimeout === "number" && Number.isFinite(invokeTimeout)) { invokeParams.timeoutMs = invokeTimeout; } const result = await callGatewayCli("node.invoke", opts, invokeParams); if (opts.json) { defaultRuntime.log(JSON.stringify(result, null, 2)); return; } const { ok } = getNodesTheme(); defaultRuntime.log(ok("notify ok")); }); }), ); }