Skip to content

Commit 381c5e0

Browse files
committed
docs: document remaining cli helpers
1 parent e254346 commit 381c5e0

18 files changed

Lines changed: 67 additions & 0 deletions

src/cli/banner-config-lite.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,16 @@
1+
// Lightweight banner config reader kept out of the full CLI import path.
12
import { createConfigIO } from "../config/config.js";
23
import type { TaglineMode } from "./tagline.js";
34

5+
/** Parse a persisted CLI banner tagline mode. */
46
export function parseTaglineMode(value: unknown): TaglineMode | undefined {
57
if (value === "random" || value === "default" || value === "off") {
68
return value;
79
}
810
return undefined;
911
}
1012

13+
/** Read the banner tagline mode without pulling in full CLI command registration. */
1114
export function readCliBannerTaglineMode(
1215
env: NodeJS.ProcessEnv = process.env,
1316
): TaglineMode | undefined {

src/cli/banner.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
// CLI banner formatter and one-shot emitter.
12
import { visibleWidth } from "../../packages/terminal-core/src/ansi.js";
23
import {
34
decorativeEmoji,
@@ -23,6 +24,7 @@ type BannerOptions = TaglineOptions & {
2324

2425
let bannerEmitted = false;
2526

27+
// Use grapheme segmentation so decorative emoji and block art split without corrupting clusters.
2628
const graphemeSegmenter =
2729
typeof Intl !== "undefined" && "Segmenter" in Intl
2830
? new Intl.Segmenter(undefined, { granularity: "grapheme" })
@@ -61,6 +63,7 @@ function resolveEmojiOptions(options: BannerOptions): DecorativeEmojiOptions {
6163
};
6264
}
6365

66+
/** Format the compact one-line CLI banner, wrapping tagline when terminal width requires it. */
6467
export function formatCliBannerLine(version: string, options: BannerOptions = {}): string {
6568
const commit =
6669
options.commit ?? resolveCommitHash({ env: options.env, moduleUrl: import.meta.url });
@@ -129,6 +132,7 @@ function formatCliBannerArtLines(options: BannerOptions): string[] {
129132
return [...LOBSTER_ASCII_BODY, centerText(title, width), " "];
130133
}
131134

135+
/** Format the large decorative OpenClaw banner art. */
132136
export function formatCliBannerArt(options: BannerOptions = {}): string {
133137
const rich = options.richTty ?? isRich();
134138
const lines = formatCliBannerArtLines(options);
@@ -169,6 +173,7 @@ export function formatCliBannerArt(options: BannerOptions = {}): string {
169173
return colored.join("\n");
170174
}
171175

176+
/** Emit the CLI banner once for interactive, non-JSON, non-version invocations. */
172177
export function emitCliBanner(version: string, options: BannerOptions = {}) {
173178
if (bannerEmitted) {
174179
return;
@@ -189,6 +194,7 @@ export function emitCliBanner(version: string, options: BannerOptions = {}) {
189194
bannerEmitted = true;
190195
}
191196

197+
/** Return whether the current process already emitted the CLI banner. */
192198
export function hasEmittedCliBanner(): boolean {
193199
return bannerEmitted;
194200
}

src/cli/cron-cli.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1 +1,3 @@
1+
// Public CLI barrel for cron subcommand registration.
2+
/** Register cron job CLI subcommands on the root program. */
13
export { registerCronCli } from "./cron-cli/register.js";

src/cli/cron-cli/schedule-options.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
// Shared schedule option resolver for cron create/edit commands.
12
import { normalizeOptionalString } from "@openclaw/normalization-core/string-coerce";
23
import type { CronSchedule } from "../../cron/types.js";
34
import { parseAt, parseCronStaggerMs, parseDurationMs } from "./shared.js";
@@ -23,11 +24,13 @@ type NormalizedScheduleOptions = {
2324
tz: string | undefined;
2425
};
2526

27+
/** Normalized schedule edit request, including patch-only updates for cron metadata. */
2628
export type CronEditScheduleRequest =
2729
| { kind: "direct"; schedule: CronSchedule }
2830
| { kind: "patch-existing-cron"; staggerMs: number | undefined; tz: string | undefined }
2931
| { kind: "none" };
3032

33+
/** Resolve explicit `--at`, `--every`, or `--cron` options for cron creation. */
3134
export function resolveCronCreateSchedule(options: ScheduleOptionInput): CronSchedule {
3235
const normalized = normalizeScheduleOptions(options);
3336
const chosen = countChosenSchedules(normalized);
@@ -41,6 +44,7 @@ export function resolveCronCreateSchedule(options: ScheduleOptionInput): CronSch
4144
return schedule;
4245
}
4346

47+
/** Resolve cron creation schedule from either a positional shorthand or explicit flags. */
4448
export function resolveCronCreateScheduleFromArgs(
4549
options: ScheduleOptionInput & PositionalScheduleInput,
4650
): CronSchedule {
@@ -65,6 +69,7 @@ export function resolveCronCreateScheduleFromArgs(
6569
});
6670
}
6771

72+
/** Resolve a cron edit request, allowing at most one direct schedule replacement. */
6873
export function resolveCronEditScheduleRequest(
6974
options: ScheduleOptionInput,
7075
): CronEditScheduleRequest {
@@ -87,6 +92,7 @@ export function resolveCronEditScheduleRequest(
8792
return { kind: "none" };
8893
}
8994

95+
/** Apply `--tz`, `--stagger`, or `--exact` metadata changes to an existing cron schedule. */
9096
export function applyExistingCronSchedulePatch(
9197
existingSchedule: CronSchedule,
9298
request: Extract<CronEditScheduleRequest, { kind: "patch-existing-cron" }>,

src/cli/daemon-cli/launchd-recovery.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
// macOS LaunchAgent recovery helper for daemon lifecycle commands.
12
import { launchAgentPlistExists, repairLaunchAgentBootstrap } from "../../daemon/launchd.js";
23

34
const LAUNCH_AGENT_RECOVERY_MESSAGE =
@@ -11,6 +12,7 @@ type LaunchAgentRecoveryResult = {
1112
message: string;
1213
};
1314

15+
/** Re-bootstrap an installed but unloaded LaunchAgent after a daemon start/restart command. */
1416
export async function recoverInstalledLaunchAgent(params: {
1517
result: LaunchAgentRecoveryAction;
1618
env?: Record<string, string | undefined>;
@@ -37,4 +39,5 @@ export async function recoverInstalledLaunchAgent(params: {
3739
};
3840
}
3941

42+
/** User-facing recovery message for successful LaunchAgent bootstrap repair. */
4043
export { LAUNCH_AGENT_RECOVERY_MESSAGE };

src/cli/deps.types.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
// Shared dependency surface for CLI send commands.
12
import type { CliOutboundSendSource } from "./outbound-send-mapping.js";
23

4+
/** CLI dependency bag currently used by outbound send command plumbing. */
35
export type CliDeps = CliOutboundSendSource;

src/cli/node-cli.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1 +1,3 @@
1+
// Public CLI barrel for node subcommand registration.
2+
/** Register node/device CLI subcommands on the root program. */
13
export { registerNodeCli } from "./node-cli/register.js";

src/cli/nodes-camera.ts

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
// Camera payload validation and artifact writers for node media commands.
12
import * as fs from "node:fs/promises";
23
import * as path from "node:path";
34
import { fetchWithSsrFGuard } from "../infra/net/fetch-guard.js";
@@ -15,8 +16,10 @@ import {
1516
const MAX_CAMERA_URL_DOWNLOAD_BYTES = 250 * 1024 * 1024;
1617
const MAX_CAMERA_BASE64_BYTES = MAX_CAMERA_URL_DOWNLOAD_BYTES;
1718

19+
/** Camera orientation accepted by node camera commands. */
1820
export type CameraFacing = "front" | "back";
1921

22+
/** Validated still-image payload from `nodes camera snap`. */
2023
export type CameraSnapPayload = {
2124
format: string;
2225
base64?: string;
@@ -25,6 +28,7 @@ export type CameraSnapPayload = {
2528
height: number;
2629
};
2730

31+
/** Validated video payload from `nodes camera clip`. */
2832
export type CameraClipPayload = {
2933
format: string;
3034
base64?: string;
@@ -33,6 +37,7 @@ export type CameraClipPayload = {
3337
hasAudio: boolean;
3438
};
3539

40+
/** Validate and normalize an unknown camera still-image payload. */
3641
export function parseCameraSnapPayload(value: unknown): CameraSnapPayload {
3742
const obj = asRecord(value);
3843
const format = asString(obj.format);
@@ -46,6 +51,7 @@ export function parseCameraSnapPayload(value: unknown): CameraSnapPayload {
4651
return { format, ...(base64 ? { base64 } : {}), ...(url ? { url } : {}), width, height };
4752
}
4853

54+
/** Validate and normalize an unknown camera clip payload. */
4955
export function parseCameraClipPayload(value: unknown): CameraClipPayload {
5056
const obj = asRecord(value);
5157
const format = asString(obj.format);
@@ -59,6 +65,7 @@ export function parseCameraClipPayload(value: unknown): CameraClipPayload {
5965
return { format, ...(base64 ? { base64 } : {}), ...(url ? { url } : {}), durationMs, hasAudio };
6066
}
6167

68+
/** Build a deterministic temp path for a camera artifact. */
6269
export function cameraTempPath(opts: {
6370
kind: "snap" | "clip";
6471
facing?: CameraFacing;
@@ -76,6 +83,7 @@ export function cameraTempPath(opts: {
7683
return path.join(tmpDir, `${cliName}-camera-${opts.kind}${facingPart}-${id}${ext}`);
7784
}
7885

86+
/** Download a node-hosted media URL to disk after HTTPS, host, redirect, and size checks. */
7987
export async function writeUrlToFile(
8088
filePath: string,
8189
url: string,
@@ -95,6 +103,7 @@ export async function writeUrlToFile(
95103
);
96104
}
97105

106+
// The node host is allowed even when private because the RPC response supplied its remote IP.
98107
const policy = {
99108
allowPrivateNetwork: true,
100109
allowedHostnames: [expectedHost],
@@ -184,6 +193,7 @@ function estimateDecodedBase64Bytes(base64: string): number {
184193
return Math.floor((normalized.length * 3) / 4) - padding;
185194
}
186195

196+
/** Decode a base64 media payload to disk with preflight and post-decode size checks. */
187197
export async function writeBase64ToFile(
188198
filePath: string,
189199
base64: string,
@@ -201,6 +211,7 @@ export async function writeBase64ToFile(
201211
return { path: filePath, bytes: buf.length };
202212
}
203213

214+
/** Require the node remote IP needed to validate URL-backed camera payloads. */
204215
export function requireNodeRemoteIp(remoteIp?: string): string {
205216
const normalized = remoteIp?.trim();
206217
if (!normalized) {
@@ -209,6 +220,7 @@ export function requireNodeRemoteIp(remoteIp?: string): string {
209220
return normalized;
210221
}
211222

223+
/** Write either a URL-backed or base64-backed camera payload to disk. */
212224
export async function writeCameraPayloadToFile(params: {
213225
filePath: string;
214226
payload: { url?: string; base64?: string };
@@ -228,6 +240,7 @@ export async function writeCameraPayloadToFile(params: {
228240
throw new Error(params.invalidPayloadMessage ?? "invalid camera payload");
229241
}
230242

243+
/** Write a camera clip payload to a generated temp file and return its path. */
231244
export async function writeCameraClipPayloadToFile(params: {
232245
payload: CameraClipPayload;
233246
facing: CameraFacing;

src/cli/nodes-screen.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,9 @@
1+
// Screen-recording payload helpers for node media commands.
12
import * as path from "node:path";
23
import { writeBase64ToFile } from "./nodes-camera.js";
34
import { asRecord, asString, resolveTempPathParts } from "./nodes-media-utils.js";
45

6+
/** Validated payload returned by `nodes screen record` RPC calls. */
57
export type ScreenRecordPayload = {
68
format: string;
79
base64: string;
@@ -11,6 +13,7 @@ export type ScreenRecordPayload = {
1113
hasAudio?: boolean;
1214
};
1315

16+
/** Validate and normalize an unknown screen-record payload. */
1417
export function parseScreenRecordPayload(value: unknown): ScreenRecordPayload {
1518
const obj = asRecord(value);
1619
const format = asString(obj.format);
@@ -28,11 +31,13 @@ export function parseScreenRecordPayload(value: unknown): ScreenRecordPayload {
2831
};
2932
}
3033

34+
/** Build the temp output path for a screen recording artifact. */
3135
export function screenRecordTempPath(opts: { ext: string; tmpDir?: string; id?: string }) {
3236
const { tmpDir, id, ext } = resolveTempPathParts(opts);
3337
return path.join(tmpDir, `openclaw-screen-record-${id}${ext}`);
3438
}
3539

40+
/** Decode and write a screen recording payload to disk. */
3641
export async function writeScreenRecordToFile(
3742
filePath: string,
3843
base64: string,

src/cli/plugins-config.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1 +1,3 @@
1+
// Public CLI barrel for plugin config mutations.
2+
/** Toggle plugin enablement inside an OpenClaw config object. */
13
export { setPluginEnabledInConfig } from "../plugins/toggle-config.js";

0 commit comments

Comments
 (0)