UNPKG

openclaw

Version:

Multi-channel AI gateway with extensible messaging integrations

154 lines (153 loc) 7.7 kB
import { l as normalizeOptionalString } from "./string-coerce-CIXf7egm.js"; import { r as defaultRuntime } from "./runtime-CF2WjnNZ.js"; import { n as getRuntimeConfig } from "./io.runtime-B9iJRs3w.js"; import { m as shortenHomePath } from "./utils-P__uGsPB.js"; import { n as inheritOptionFromParent } from "./command-options-BDuSHeWG.js"; import { t as danger } from "./globals-CTaGxEqj.js"; import "./string-coerce-runtime-GQa0ehRA.js"; import { t as writeExternalFileWithinOutputRoot } from "./output-files-pxc2L0xy.js"; import "./core-api-zb8NP8I7.js"; import { a as parseBrowserPositiveIntegerOption, i as parseBrowserNonNegativeIntegerValue, n as callBrowserRequest, o as parseBrowserPositiveIntegerValue, t as BROWSER_TAB_REFERENCE_HELP } from "./browser-cli-shared-Co4TmZyV.js"; import path from "node:path"; import fs from "node:fs/promises"; //#region extensions/browser/src/cli/browser-cli-inspect.ts /** * Browser CLI inspection commands for screenshots and snapshots. */ function parseOptionalIntegerOption(value, label, opts) { if (value === void 0) return; const parsed = opts.min === 0 ? parseBrowserNonNegativeIntegerValue(value) : parseBrowserPositiveIntegerValue(value); if (parsed === void 0 || parsed < opts.min) { defaultRuntime.error(danger(`Invalid ${label}: must be an integer >= ${opts.min}`)); defaultRuntime.exit(1); return; } return parsed; } function parseBrowserChoiceOption(value, label, choices) { if (choices.includes(value)) return value; defaultRuntime.error(danger(`Invalid ${label}: expected ${choices.join(" or ")}`)); defaultRuntime.exit(1); } function resolveBrowserInspectTimeout(command, parent, value) { const timeout = command.getOptionValueSource("timeout") === "cli" ? value : inheritOptionFromParent(command, "timeout", "cli"); if (timeout === void 0) return { parent }; const timeoutMs = parseBrowserPositiveIntegerOption(timeout, "--timeout"); return { parent: { ...parent, timeout: String(timeoutMs) }, timeoutMs }; } /** Registers Browser screenshot and snapshot commands. */ function registerBrowserInspectCommands(browser, parentOpts) { browser.command("screenshot").description("Capture a screenshot (prints the saved path)").argument("[targetId]", BROWSER_TAB_REFERENCE_HELP).option("--full-page", "Capture full scrollable page", false).option("--ref <ref>", "ARIA ref from ai snapshot").option("--element <selector>", "CSS selector for element screenshot").option("--labels", "Overlay role refs on the screenshot (works with --full-page, --ref, and --element)", false).option("--type <png|jpeg>", "Output type (default: png)", "png").option("--timeout <ms>", "Timeout in ms").action(async (targetId, opts, cmd) => { const parent = parentOpts(cmd); const profile = parent?.browserProfile; const type = parseBrowserChoiceOption(opts.type, "--type", ["png", "jpeg"]); if (type === void 0) return; try { const request = resolveBrowserInspectTimeout(cmd, parent, opts.timeout); const result = await callBrowserRequest(request.parent, { method: "POST", path: "/screenshot", query: profile ? { profile } : void 0, body: { targetId: normalizeOptionalString(targetId), fullPage: Boolean(opts.fullPage), ref: normalizeOptionalString(opts.ref), element: normalizeOptionalString(opts.element), labels: Boolean(opts.labels), type, ...request.timeoutMs === void 0 ? {} : { timeoutMs: request.timeoutMs } } }); if (parent?.json) { defaultRuntime.writeJson(result); return; } defaultRuntime.log(shortenHomePath(result.path)); } catch (err) { defaultRuntime.error(danger(String(err))); defaultRuntime.exit(1); } }); browser.command("snapshot").description("Capture a snapshot (default: ai; aria is the accessibility tree)").option("--format <aria|ai>", "Snapshot format (default: ai)", "ai").option("--target-id <id>", BROWSER_TAB_REFERENCE_HELP).option("--limit <n>", "Max nodes (default: 500/800)").option("--mode <efficient>", "Snapshot preset (efficient)").option("--efficient", "Use the efficient snapshot preset", false).option("--interactive", "Role snapshot: interactive elements only", false).option("--compact", "Role snapshot: compact output", false).option("--depth <n>", "Role snapshot: max depth").option("--selector <sel>", "Role snapshot: scope to CSS selector").option("--frame <sel>", "Role snapshot: scope to an iframe selector").option("--labels", "Include label overlay screenshot with annotations", false).option("--urls", "Append discovered link URLs to AI snapshots", false).option("--out <path>", "Write snapshot to a file").option("--timeout <ms>", "Timeout in ms").action(async (opts, cmd) => { const parent = parentOpts(cmd); const profile = parent?.browserProfile; const format = parseBrowserChoiceOption(opts.format, "--format", ["aria", "ai"]); if (format === void 0) return; const explicitMode = opts.mode === void 0 ? void 0 : parseBrowserChoiceOption(opts.mode, "--mode", ["efficient"]); if (opts.mode !== void 0 && explicitMode === void 0) return; const configMode = !(cmd.getOptionValueSource("format") === "cli") && format === "ai" && getRuntimeConfig().browser?.snapshotDefaults?.mode === "efficient" ? "efficient" : void 0; const mode = opts.efficient === true || explicitMode === "efficient" ? "efficient" : configMode; const limit = parseOptionalIntegerOption(opts.limit, "--limit", { min: 1 }); const depth = parseOptionalIntegerOption(opts.depth, "--depth", { min: 0 }); if (opts.limit !== void 0 && limit === void 0 || opts.depth !== void 0 && depth === void 0) return; try { const request = resolveBrowserInspectTimeout(cmd, parent, opts.timeout); const query = { format, targetId: normalizeOptionalString(opts.targetId), limit, interactive: opts.interactive ? true : void 0, compact: opts.compact ? true : void 0, depth, selector: normalizeOptionalString(opts.selector), frame: normalizeOptionalString(opts.frame), labels: opts.labels ? true : void 0, urls: opts.urls ? true : void 0, mode, profile, ...request.timeoutMs === void 0 ? {} : { timeoutMs: request.timeoutMs } }; const result = await callBrowserRequest(request.parent, { method: "GET", path: "/snapshot", query }); if (opts.out) { const payload = result.format === "ai" ? result.snapshot : JSON.stringify(result, null, 2); await writeExternalFileWithinOutputRoot({ path: path.resolve(opts.out), write: async (tempPath) => { await fs.writeFile(tempPath, payload, "utf8"); } }); if (parent?.json) defaultRuntime.writeJson({ ok: true, out: opts.out, ...result.format === "ai" && result.imagePath ? { imagePath: result.imagePath } : {} }); else { defaultRuntime.log(shortenHomePath(opts.out)); if (result.format === "ai" && result.imagePath) defaultRuntime.log(shortenHomePath(result.imagePath)); } return; } if (parent?.json) { defaultRuntime.writeJson(result); return; } if (result.format === "ai") { defaultRuntime.log(result.snapshot); if (result.imagePath) defaultRuntime.log(shortenHomePath(result.imagePath)); return; } const nodes = "nodes" in result ? result.nodes : []; defaultRuntime.log(nodes.map((n) => { const indent = " ".repeat(Math.min(20, n.depth)); const name = n.name ? ` "${n.name}"` : ""; const value = n.value ? ` = "${n.value}"` : ""; return `${indent}- ${n.role}${name}${value}`; }).join("\n")); } catch (err) { defaultRuntime.error(danger(String(err))); defaultRuntime.exit(1); } }); } //#endregion export { registerBrowserInspectCommands };