File size: 3,196 Bytes
fc93158
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
import type { Command } from "commander";
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";

type NodesPushOpts = NodesRpcOpts & {
  node?: string;
  title?: string;
  body?: string;
  environment?: string;
};

function normalizeEnvironment(value: unknown): "sandbox" | "production" | null {
  if (typeof value !== "string") {
    return null;
  }
  const normalized = value.trim().toLowerCase();
  if (normalized === "sandbox" || normalized === "production") {
    return normalized;
  }
  return null;
}

export function registerNodesPushCommand(nodes: Command) {
  nodesCallOpts(
    nodes
      .command("push")
      .description("Send an APNs test push to an iOS node")
      .requiredOption("--node <idOrNameOrIp>", "Node id, name, or IP")
      .option("--title <text>", "Push title", "OpenClaw")
      .option("--body <text>", "Push body")
      .option("--environment <sandbox|production>", "Override APNs environment")
      .action(async (opts: NodesPushOpts) => {
        await runNodesCommand("push", async () => {
          const nodeId = await resolveNodeId(opts, String(opts.node ?? ""));
          const title = String(opts.title ?? "").trim() || "OpenClaw";
          const body = String(opts.body ?? "").trim() || `Push test for node ${nodeId}`;
          const environment = normalizeEnvironment(opts.environment);
          if (opts.environment && !environment) {
            throw new Error("invalid --environment (use sandbox|production)");
          }

          const params: Record<string, unknown> = {
            nodeId,
            title,
            body,
          };
          if (environment) {
            params.environment = environment;
          }

          const result = await callGatewayCli("push.test", opts, params);
          if (opts.json) {
            defaultRuntime.log(JSON.stringify(result, null, 2));
            return;
          }

          const parsed =
            typeof result === "object" && result !== null
              ? (result as {
                  ok?: unknown;
                  status?: unknown;
                  reason?: unknown;
                  environment?: unknown;
                })
              : {};
          const ok = parsed.ok === true;
          const status = typeof parsed.status === "number" ? parsed.status : 0;
          const reason =
            typeof parsed.reason === "string" && parsed.reason.trim().length > 0
              ? parsed.reason.trim()
              : undefined;
          const env =
            typeof parsed.environment === "string" && parsed.environment.trim().length > 0
              ? parsed.environment.trim()
              : "unknown";
          const { ok: okLabel, error: errorLabel } = getNodesTheme();
          const label = ok ? okLabel : errorLabel;
          defaultRuntime.log(label(`push.test status=${status} ok=${ok} env=${env}`));
          if (reason) {
            defaultRuntime.log(`reason: ${reason}`);
          }
        });
      }),
    { timeoutMs: 25_000 },
  );
}