File size: 3,213 Bytes
f778c12
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
// APNs test-push command for iOS nodes.
import {
  normalizeOptionalLowercaseString,
  normalizeOptionalString,
} from "@openclaw/normalization-core/string-coerce";
import type { Command } from "commander";
import type { PushTestResult } from "../../../packages/gateway-protocol/src/index.js";
import { defaultRuntime } from "../../runtime.js";
import { getNodesTheme, runNodesCommand } from "./cli-utils.js";
import { callNodesGatewayCli, nodesCallOpts, resolveCliNodeId } from "./rpc.js";
import type { NodesRpcOpts } from "./types.js";

/** Register the node push-test command. */
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: NodesRpcOpts & { environment?: string }) => {
        await runNodesCommand("push", async () => {
          const environment = normalizeOptionalLowercaseString(opts.environment);
          if (
            opts.environment !== undefined &&
            environment !== "sandbox" &&
            environment !== "production"
          ) {
            throw new Error("invalid --environment (use sandbox|production)");
          }
          const nodeId = await resolveCliNodeId(opts, normalizeOptionalString(opts.node) ?? "");
          const title = normalizeOptionalString(opts.title) || "OpenClaw";
          const body = normalizeOptionalString(opts.body) || `Push test for node ${nodeId}`;

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

          const result = await callNodesGatewayCli("push.test", opts, params);
          const parsed =
            typeof result === "object" && result !== null
              ? (result as Partial<PushTestResult>)
              : {};
          const ok = parsed.ok === true;
          const status = typeof parsed.status === "number" ? parsed.status : 0;
          const reason =
            typeof parsed.reason === "string" ? normalizeOptionalString(parsed.reason) : undefined;
          const env =
            typeof parsed.environment === "string"
              ? (normalizeOptionalString(parsed.environment) ?? "unknown")
              : "unknown";
          if (opts.json) {
            defaultRuntime.writeJson(result);
          } else {
            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}`);
            }
          }
          if (!ok) {
            // Defer termination so the complete human/JSON result reaches stdout.
            process.exitCode = 1;
          }
        });
      }),
    { timeoutMs: 25_000 },
  );
}