Files
openclaw/src/cli/webhooks-cli.ts
Peter Steinberger 0b8aabe864 docs: document auth profile failure policy contract (#89613)
* docs: document markdown marker renderer

* docs: document rendered markdown chunking

* docs: document markdown text chunking

* docs: document shared text chunking

* docs: document plugin text chunking exports

* docs: document avatar policy constants

* docs: document node match candidates

* docs: document scoped expiring id cache

* docs: document runtime import normalization

* docs: document string sample summaries

* docs: document session usage timeseries types

* docs: document session usage response types

* docs: document manifest frontmatter shapes

* docs: document channel route input metadata

* docs: document pair loop guard settings

* docs: document migration config patch helpers

* docs: document api provider registry

* docs: document tool call repair payloads

* docs: document plugin tool payload helpers

* docs: document lazy promise loader

* docs: document store writer queue state

* docs: document thread binding lifecycle

* docs: document concurrency helper contract

* docs: document gateway client info contract

* docs: document delivery context contracts

* docs: document secret ref defaults contract

* docs: document command gating contract

* docs: document avatar policy contract

* docs: document node match policy

* docs: document message channel normalization

* docs: document boolean parsing contract

* docs: document zod parse helpers

* docs: document direct dm guard policy

* docs: document fixed window limiter contract

* docs: document node presence event contract

* docs: document secret normalization contract

* docs: document progress draft line removal

* docs: document usage formatting contracts

* docs: document agent run status contract

* docs: document runtime import helpers

* docs: document provider utility ownership

* docs: document invalid config helpers

* docs: document json compat parser

* docs: document channel config metadata ownership

* docs: document channel logging helpers

* docs: document sender identity validation ownership

* docs: document string sampling helper

* docs: document global singleton helpers

* docs: document transcript tool helpers

* docs: document exec safe-bin normalization

* docs: document reaction level resolver

* docs: document account snapshot redaction boundary

* docs: document messaging target helpers

* docs: document thread binding messages

* docs: document conversation binding context

* docs: document conversation resolution helper

* docs: document owner display secret retention

* docs: document provider request config types

* docs: document skills config types

* docs: document memory config types

* docs: document imessage config types

* docs: document crestodian config types

* docs: document tools config policies

* docs: document shared config base types

* docs: document channel config contracts

* docs: document openclaw config state types

* docs: document model config contracts

* docs: document shared agent config types

* docs: document agent defaults config types

* docs: document secret input contracts

* docs: document auth config contracts

* docs: document gateway config contracts

* docs: document tool call stream repair contracts

* docs: document memory host facades

* docs: document llm core contracts

* docs: document markdown core contracts

* docs: document gateway connect error contracts

* docs: document gateway protocol primitives

* docs: document gateway frame schemas

* docs: document gateway device schemas

* docs: document gateway environment schemas

* docs: document gateway push schemas

* docs: document gateway plugin schemas

* docs: document gateway artifact schemas

* docs: document gateway command schemas

* docs: document gateway task schemas

* docs: document gateway exec approval schemas

* docs: document gateway secret schemas

* docs: document gateway config schemas

* docs: document gateway snapshot schemas

* docs: document gateway chat schemas

* docs: document gateway wizard schemas

* docs: document gateway node schemas

* docs: document gateway plugin approval schemas

* docs: document gateway talk schemas

* docs: document gateway agent schemas

* docs: document gateway session schemas

* docs: document gateway cron schemas

* docs: document gateway agent model skill schemas

* docs: document gateway skill proposal tool schemas

* docs: document gateway protocol registry

* docs: document gateway channel status schemas

* docs: document gateway schema regression tests

* docs: document gateway schema barrel

* docs: document gateway validator tests

* docs: document gateway primitive push tests

* docs: document gateway contract tests

* docs: document native protocol guard

* docs: document channel schema tests

* docs: document gateway protocol smoke tests

* docs: document gateway protocol entrypoint

* docs: document gateway protocol type exports

* docs: document gateway error codes

* docs: document protocol schema registry

* docs: document talk audio codec

* docs: document talk activation names

* docs: document talk consult questions

* docs: document talk consult tool

* docs: document talk run control contracts

* docs: document talk run control adapter

* docs: document talkback consult queue

* docs: document talk consult transcript guard

* docs: document talk fast context runtime

* docs: document forced talk consult coordinator

* docs: document talk output activity tracker

* docs: document talk event metrics

* docs: document talk diagnostics

* docs: document talk observability hook

* docs: document talk provider resolver

* docs: document talk provider registry

* docs: document talk runtime primitives

* docs: document talk consult controller logs

* docs: document channel identity helpers

* docs: document channel account allowlist helpers

* docs: document channel metadata draft controls

* docs: document channel ingress policy

* docs: document channel sender access gates

* docs: document channel catalog message contracts

* docs: document channel account plugin helpers

* docs: document configured binding helpers

* docs: document channel acp approval config helpers

* docs: document channel bundled config write helpers

* docs: document channel plugin utility contracts

* docs: document channel config access helpers

* docs: document channel message action helpers

* docs: document channel outbound runtime helpers

* docs: document channel pairing promotion helpers

* docs: document channel registry helpers

* docs: document channel setup wizard helpers

* docs: document channel lifecycle status helpers

* docs: document channel target thread helpers

* docs: document channel session binding helpers

* docs: document channel package module probes

* docs: document channel setup wizard contracts

* docs: document channel plugin API barrels

* docs: document channel contract test helpers

* docs: document channel core helpers

* docs: document small core facades

* docs: document provider runtime helpers

* docs: document persistence and realtime helpers

* docs: document mcp and state helpers

* docs: document tool planner contracts

* docs: document music generation runtime

* docs: document crestodian command flow

* docs: document utility helpers

* docs: document node host helpers

* docs: document transcript contracts

* docs: document trajectory export contracts

* docs: document image generation contracts

* docs: document routing helper contracts

* docs: document session helper contracts

* docs: document video generation contracts

* docs: document model catalog contracts

* docs: document proxy capture contracts

* docs: document status rendering contracts

* docs: document test helper contracts

* docs: document wizard setup contracts

* docs: document process contracts

* docs: document memory host sdk contracts

* docs: document tts contracts

* docs: document secrets runtime contracts

* docs: document shared helper contracts

* docs: document hook runtime contracts

* docs: document security audit contracts

* docs: document flow contracts

* docs: document media understanding contracts

* docs: document tui contracts

* docs: document logging contracts

* docs: document llm contracts

* docs: document cron contracts

* docs: document daemon contracts

* docs: document task contracts

* docs: document acp contracts

* docs: document test utility contracts

* docs: document skill contracts

* docs: document config contracts

* docs: document outbound infra contracts

* docs: document command analysis contracts

* docs: document provider usage infra contracts

* docs: document file safety infra contracts

* docs: document exec approval infra contracts

* docs: document gateway runtime infra contracts

* docs: document infra utility contracts

* docs: document infra queue storage contracts

* docs: document heartbeat infra contracts

* docs: document remaining infra contracts

* docs: document gateway auth contracts

* docs: document gateway display helpers

* docs: document gateway http helpers

* docs: document gateway node helpers

* docs: document gateway mcp helpers

* docs: document gateway support helpers

* docs: document gateway server runtime helpers

* docs: document gateway runtime bootstrap helpers

* docs: document gateway session events

* docs: document gateway utility helpers

* docs: document gateway talk helpers

* docs: document gateway helper contracts

* docs: document gateway server method helpers

* docs: document gateway server auth helpers

* docs: document gateway server tests

* docs: document gateway test helpers

* docs: document gateway node tests

* docs: document gateway channel tests

* docs: document gateway session tests

* docs: document gateway server startup tests

* docs: document gateway tool test helpers

* docs: document gateway server test helpers

* docs: document gateway server method tests

* docs: document remaining gateway tests

* docs: document plugin sdk public subpaths

* docs: document plugin sdk runtime helpers

* docs: document plugin sdk memory provider helpers

* docs: document plugin sdk runtime facades

* docs: document plugin sdk command approval helpers

* docs: document plugin sdk runtime types

* docs: document plugin sdk browser account helpers

* docs: document plugin sdk media memory helpers

* docs: document plugin sdk core tests

* docs: document plugin sdk contract helpers

* docs: document plugin sdk test helpers

* docs: document remaining plugin sdk tests

* docs: document cli utility helpers

* docs: document cli runtime helpers

* docs: document cli command registration helpers

* docs: document node cli helpers

* docs: document cli program registration

* docs: document message cli registration

* docs: document daemon cli helpers

* docs: document cli route parsers
2026-06-03 15:20:39 -07:00

197 lines
7.4 KiB
TypeScript

// Webhook CLI registrations, currently Gmail Pub/Sub setup and service runner commands.
import { normalizeOptionalString } from "@openclaw/normalization-core/string-coerce";
import type { Command } from "commander";
import { formatDocsLink } from "../../packages/terminal-core/src/links.js";
import { theme } from "../../packages/terminal-core/src/theme.js";
import { danger } from "../globals.js";
import {
type GmailRunOptions,
type GmailSetupOptions,
runGmailService,
runGmailSetup,
} from "../hooks/gmail-ops.js";
import {
DEFAULT_GMAIL_LABEL,
DEFAULT_GMAIL_MAX_BYTES,
DEFAULT_GMAIL_RENEW_MINUTES,
DEFAULT_GMAIL_SERVE_BIND,
DEFAULT_GMAIL_SERVE_PATH,
DEFAULT_GMAIL_SERVE_PORT,
DEFAULT_GMAIL_SUBSCRIPTION,
DEFAULT_GMAIL_TOPIC,
} from "../hooks/gmail.js";
import { parseStrictPositiveInteger } from "../infra/parse-finite-number.js";
import { defaultRuntime } from "../runtime.js";
import { formatCliCommand } from "./command-format.js";
/** Register webhook-related subcommands on the root Commander program. */
export function registerWebhooksCli(program: Command) {
const webhooks = program
.command("webhooks")
.description("Webhook helpers and integrations")
.addHelpText(
"after",
() =>
`\n${theme.muted("Docs:")} ${formatDocsLink("/cli/webhooks", "docs.openclaw.ai/cli/webhooks")}\n`,
);
const gmail = webhooks.command("gmail").description("Gmail Pub/Sub hooks (via gogcli)");
gmail
.command("setup")
.description("Configure Gmail watch + Pub/Sub + OpenClaw hooks")
.requiredOption("--account <email>", "Gmail account to watch")
.option("--project <id>", "GCP project id (OAuth client owner)")
.option("--topic <name>", "Pub/Sub topic name", DEFAULT_GMAIL_TOPIC)
.option("--subscription <name>", "Pub/Sub subscription name", DEFAULT_GMAIL_SUBSCRIPTION)
.option("--label <label>", "Gmail label to watch", DEFAULT_GMAIL_LABEL)
.option("--hook-url <url>", "OpenClaw hook URL")
.option("--hook-token <token>", "OpenClaw hook token")
.option("--push-token <token>", "Push token for gog watch serve")
.option("--bind <host>", "gog watch serve bind host", DEFAULT_GMAIL_SERVE_BIND)
.option("--port <port>", "gog watch serve port", String(DEFAULT_GMAIL_SERVE_PORT))
.option("--path <path>", "gog watch serve path", DEFAULT_GMAIL_SERVE_PATH)
.option("--include-body", "Include email body snippets", true)
.option("--max-bytes <n>", "Max bytes for body snippets", String(DEFAULT_GMAIL_MAX_BYTES))
.option(
"--renew-minutes <n>",
"Renew watch every N minutes",
String(DEFAULT_GMAIL_RENEW_MINUTES),
)
.option("--tailscale <mode>", "Expose push endpoint via tailscale (funnel|serve|off)", "funnel")
.option("--tailscale-path <path>", "Path for tailscale serve/funnel")
.option(
"--tailscale-target <target>",
"Tailscale serve/funnel target (port, host:port, or URL)",
)
.option("--push-endpoint <url>", "Explicit Pub/Sub push endpoint")
.option("--json", "Output JSON summary", false)
.action(async (opts) => {
try {
const parsed = parseGmailSetupOptions(opts);
await runGmailSetup(parsed);
} catch (err) {
defaultRuntime.error(danger(String(err)));
defaultRuntime.exit(1);
}
});
gmail
.command("run")
.description("Run gog watch serve + auto-renew loop")
.option("--account <email>", "Gmail account to watch")
.option("--topic <topic>", "Pub/Sub topic path (projects/.../topics/..)")
.option("--subscription <name>", "Pub/Sub subscription name")
.option("--label <label>", "Gmail label to watch")
.option("--hook-url <url>", "OpenClaw hook URL")
.option("--hook-token <token>", "OpenClaw hook token")
.option("--push-token <token>", "Push token for gog watch serve")
.option("--bind <host>", "gog watch serve bind host")
.option("--port <port>", "gog watch serve port")
.option("--path <path>", "gog watch serve path")
.option("--include-body", "Include email body snippets")
.option("--max-bytes <n>", "Max bytes for body snippets")
.option("--renew-minutes <n>", "Renew watch every N minutes")
.option("--tailscale <mode>", "Expose push endpoint via tailscale (funnel|serve|off)")
.option("--tailscale-path <path>", "Path for tailscale serve/funnel")
.option(
"--tailscale-target <target>",
"Tailscale serve/funnel target (port, host:port, or URL)",
)
.action(async (opts) => {
try {
const parsed = parseGmailRunOptions(opts);
await runGmailService(parsed);
} catch (err) {
defaultRuntime.error(danger(String(err)));
defaultRuntime.exit(1);
}
});
}
function parseGmailSetupOptions(raw: Record<string, unknown>): GmailSetupOptions {
const accountRaw = raw.account;
const account = normalizeOptionalString(accountRaw) ?? "";
if (!account) {
throw new Error(
`--account is required. Example: ${formatCliCommand("openclaw webhooks gmail setup --account default")}.`,
);
}
const common = parseGmailCommonOptions(raw);
return {
account,
project: normalizeOptionalString(raw.project),
...gmailOptionsFromCommon(common),
pushEndpoint: normalizeOptionalString(raw.pushEndpoint),
json: Boolean(raw.json),
};
}
function parseGmailRunOptions(raw: Record<string, unknown>): GmailRunOptions {
const common = parseGmailCommonOptions(raw);
return {
account: normalizeOptionalString(raw.account),
...gmailOptionsFromCommon(common),
};
}
function parseGmailCommonOptions(raw: Record<string, unknown>) {
return {
topic: normalizeOptionalString(raw.topic),
subscription: normalizeOptionalString(raw.subscription),
label: normalizeOptionalString(raw.label),
hookUrl: normalizeOptionalString(raw.hookUrl),
hookToken: normalizeOptionalString(raw.hookToken),
pushToken: normalizeOptionalString(raw.pushToken),
bind: normalizeOptionalString(raw.bind),
port: numberOption(raw.port, "--port"),
path: normalizeOptionalString(raw.path),
includeBody: booleanOption(raw.includeBody),
maxBytes: numberOption(raw.maxBytes, "--max-bytes"),
renewEveryMinutes: numberOption(raw.renewMinutes, "--renew-minutes"),
tailscaleRaw: normalizeOptionalString(raw.tailscale),
tailscalePath: normalizeOptionalString(raw.tailscalePath),
tailscaleTarget: normalizeOptionalString(raw.tailscaleTarget),
};
}
function gmailOptionsFromCommon(
common: ReturnType<typeof parseGmailCommonOptions>,
): Omit<GmailRunOptions, "account"> {
return {
topic: common.topic,
subscription: common.subscription,
label: common.label,
hookUrl: common.hookUrl,
hookToken: common.hookToken,
pushToken: common.pushToken,
bind: common.bind,
port: common.port,
path: common.path,
includeBody: common.includeBody,
maxBytes: common.maxBytes,
renewEveryMinutes: common.renewEveryMinutes,
tailscale: common.tailscaleRaw as GmailRunOptions["tailscale"],
tailscalePath: common.tailscalePath,
tailscaleTarget: common.tailscaleTarget,
};
}
function numberOption(value: unknown, label: string): number | undefined {
if (value === undefined || value === null) {
return undefined;
}
const n = parseStrictPositiveInteger(value);
if (n === undefined) {
throw new Error(`${label} must be a positive integer.`);
}
return n;
}
function booleanOption(value: unknown): boolean | undefined {
if (value === undefined || value === null) {
return undefined;
}
return Boolean(value);
}