Spaces:
Configuration error
Configuration error
| import type { Command } from "commander"; | |
| import { danger } from "../../globals.js"; | |
| import { defaultRuntime } from "../../runtime.js"; | |
| import type { BrowserParentOpts } from "../browser-cli-shared.js"; | |
| import { callBrowserAct, requireRef, resolveBrowserActionContext } from "./shared.js"; | |
| export function registerBrowserElementCommands( | |
| browser: Command, | |
| parentOpts: (cmd: Command) => BrowserParentOpts, | |
| ) { | |
| browser | |
| .command("click") | |
| .description("Click an element by ref from snapshot") | |
| .argument("<ref>", "Ref id from snapshot") | |
| .option("--target-id <id>", "CDP target id (or unique prefix)") | |
| .option("--double", "Double click", false) | |
| .option("--button <left|right|middle>", "Mouse button to use") | |
| .option("--modifiers <list>", "Comma-separated modifiers (Shift,Alt,Meta)") | |
| .action(async (ref: string | undefined, opts, cmd) => { | |
| const { parent, profile } = resolveBrowserActionContext(cmd, parentOpts); | |
| const refValue = requireRef(ref); | |
| if (!refValue) return; | |
| const modifiers = opts.modifiers | |
| ? String(opts.modifiers) | |
| .split(",") | |
| .map((v: string) => v.trim()) | |
| .filter(Boolean) | |
| : undefined; | |
| try { | |
| const result = await callBrowserAct<{ url?: string }>({ | |
| parent, | |
| profile, | |
| body: { | |
| kind: "click", | |
| ref: refValue, | |
| targetId: opts.targetId?.trim() || undefined, | |
| doubleClick: Boolean(opts.double), | |
| button: opts.button?.trim() || undefined, | |
| modifiers, | |
| }, | |
| }); | |
| if (parent?.json) { | |
| defaultRuntime.log(JSON.stringify(result, null, 2)); | |
| return; | |
| } | |
| const suffix = result.url ? ` on ${result.url}` : ""; | |
| defaultRuntime.log(`clicked ref ${refValue}${suffix}`); | |
| } catch (err) { | |
| defaultRuntime.error(danger(String(err))); | |
| defaultRuntime.exit(1); | |
| } | |
| }); | |
| browser | |
| .command("type") | |
| .description("Type into an element by ref from snapshot") | |
| .argument("<ref>", "Ref id from snapshot") | |
| .argument("<text>", "Text to type") | |
| .option("--submit", "Press Enter after typing", false) | |
| .option("--slowly", "Type slowly (human-like)", false) | |
| .option("--target-id <id>", "CDP target id (or unique prefix)") | |
| .action(async (ref: string | undefined, text: string, opts, cmd) => { | |
| const { parent, profile } = resolveBrowserActionContext(cmd, parentOpts); | |
| const refValue = requireRef(ref); | |
| if (!refValue) return; | |
| try { | |
| const result = await callBrowserAct({ | |
| parent, | |
| profile, | |
| body: { | |
| kind: "type", | |
| ref: refValue, | |
| text, | |
| submit: Boolean(opts.submit), | |
| slowly: Boolean(opts.slowly), | |
| targetId: opts.targetId?.trim() || undefined, | |
| }, | |
| }); | |
| if (parent?.json) { | |
| defaultRuntime.log(JSON.stringify(result, null, 2)); | |
| return; | |
| } | |
| defaultRuntime.log(`typed into ref ${refValue}`); | |
| } catch (err) { | |
| defaultRuntime.error(danger(String(err))); | |
| defaultRuntime.exit(1); | |
| } | |
| }); | |
| browser | |
| .command("press") | |
| .description("Press a key") | |
| .argument("<key>", "Key to press (e.g. Enter)") | |
| .option("--target-id <id>", "CDP target id (or unique prefix)") | |
| .action(async (key: string, opts, cmd) => { | |
| const { parent, profile } = resolveBrowserActionContext(cmd, parentOpts); | |
| try { | |
| const result = await callBrowserAct({ | |
| parent, | |
| profile, | |
| body: { kind: "press", key, targetId: opts.targetId?.trim() || undefined }, | |
| }); | |
| if (parent?.json) { | |
| defaultRuntime.log(JSON.stringify(result, null, 2)); | |
| return; | |
| } | |
| defaultRuntime.log(`pressed ${key}`); | |
| } catch (err) { | |
| defaultRuntime.error(danger(String(err))); | |
| defaultRuntime.exit(1); | |
| } | |
| }); | |
| browser | |
| .command("hover") | |
| .description("Hover an element by ai ref") | |
| .argument("<ref>", "Ref id from snapshot") | |
| .option("--target-id <id>", "CDP target id (or unique prefix)") | |
| .action(async (ref: string, opts, cmd) => { | |
| const { parent, profile } = resolveBrowserActionContext(cmd, parentOpts); | |
| try { | |
| const result = await callBrowserAct({ | |
| parent, | |
| profile, | |
| body: { kind: "hover", ref, targetId: opts.targetId?.trim() || undefined }, | |
| }); | |
| if (parent?.json) { | |
| defaultRuntime.log(JSON.stringify(result, null, 2)); | |
| return; | |
| } | |
| defaultRuntime.log(`hovered ref ${ref}`); | |
| } catch (err) { | |
| defaultRuntime.error(danger(String(err))); | |
| defaultRuntime.exit(1); | |
| } | |
| }); | |
| browser | |
| .command("scrollintoview") | |
| .description("Scroll an element into view by ref from snapshot") | |
| .argument("<ref>", "Ref id from snapshot") | |
| .option("--target-id <id>", "CDP target id (or unique prefix)") | |
| .option("--timeout-ms <ms>", "How long to wait for scroll (default: 20000)", (v: string) => | |
| Number(v), | |
| ) | |
| .action(async (ref: string | undefined, opts, cmd) => { | |
| const { parent, profile } = resolveBrowserActionContext(cmd, parentOpts); | |
| const refValue = requireRef(ref); | |
| if (!refValue) return; | |
| try { | |
| const result = await callBrowserAct({ | |
| parent, | |
| profile, | |
| body: { | |
| kind: "scrollIntoView", | |
| ref: refValue, | |
| targetId: opts.targetId?.trim() || undefined, | |
| timeoutMs: Number.isFinite(opts.timeoutMs) ? opts.timeoutMs : undefined, | |
| }, | |
| timeoutMs: Number.isFinite(opts.timeoutMs) ? opts.timeoutMs : undefined, | |
| }); | |
| if (parent?.json) { | |
| defaultRuntime.log(JSON.stringify(result, null, 2)); | |
| return; | |
| } | |
| defaultRuntime.log(`scrolled into view: ${refValue}`); | |
| } catch (err) { | |
| defaultRuntime.error(danger(String(err))); | |
| defaultRuntime.exit(1); | |
| } | |
| }); | |
| browser | |
| .command("drag") | |
| .description("Drag from one ref to another") | |
| .argument("<startRef>", "Start ref id") | |
| .argument("<endRef>", "End ref id") | |
| .option("--target-id <id>", "CDP target id (or unique prefix)") | |
| .action(async (startRef: string, endRef: string, opts, cmd) => { | |
| const { parent, profile } = resolveBrowserActionContext(cmd, parentOpts); | |
| try { | |
| const result = await callBrowserAct({ | |
| parent, | |
| profile, | |
| body: { | |
| kind: "drag", | |
| startRef, | |
| endRef, | |
| targetId: opts.targetId?.trim() || undefined, | |
| }, | |
| }); | |
| if (parent?.json) { | |
| defaultRuntime.log(JSON.stringify(result, null, 2)); | |
| return; | |
| } | |
| defaultRuntime.log(`dragged ${startRef} → ${endRef}`); | |
| } catch (err) { | |
| defaultRuntime.error(danger(String(err))); | |
| defaultRuntime.exit(1); | |
| } | |
| }); | |
| browser | |
| .command("select") | |
| .description("Select option(s) in a select element") | |
| .argument("<ref>", "Ref id from snapshot") | |
| .argument("<values...>", "Option values to select") | |
| .option("--target-id <id>", "CDP target id (or unique prefix)") | |
| .action(async (ref: string, values: string[], opts, cmd) => { | |
| const { parent, profile } = resolveBrowserActionContext(cmd, parentOpts); | |
| try { | |
| const result = await callBrowserAct({ | |
| parent, | |
| profile, | |
| body: { | |
| kind: "select", | |
| ref, | |
| values, | |
| targetId: opts.targetId?.trim() || undefined, | |
| }, | |
| }); | |
| if (parent?.json) { | |
| defaultRuntime.log(JSON.stringify(result, null, 2)); | |
| return; | |
| } | |
| defaultRuntime.log(`selected ${values.join(", ")}`); | |
| } catch (err) { | |
| defaultRuntime.error(danger(String(err))); | |
| defaultRuntime.exit(1); | |
| } | |
| }); | |
| } | |