#!/usr/bin/env node import { Command } from 'commander'; import { ensureDaemonRunning } from './auto-daemon.js'; import { safeStringify, VisionLClient } from '@visionl/core'; const DEFAULT_PORT = 9527; const program = new Command(); program.name('visionl').version('0.1.0'); program.option('-p, --port ', 'daemon port', String(DEFAULT_PORT)); program.option('--pretty', 'human-readable output'); function getClient(): Promise { const opts = program.opts<{ port: string }>(); const port = parseInt(opts.port, 10) || DEFAULT_PORT; return ensureDaemonRunning(port); } function print(result: unknown): void { const opts = program.opts<{ pretty: boolean }>(); if (opts.pretty) { console.log(JSON.stringify(result, null, 2)); } else { console.log(safeStringify(result)); } } // health — check daemon health program.command('health') .description('Check daemon health') .action(async () => { const client = await getClient(); const ok = await client.health(); print({ ok }); }); // pages — page management program.command('open ') .description('Open a URL in a new page') .option('-a, --alias ', 'Page alias') .option('-p, --profile ', 'Browser profile') .action(async (url: string, options: { alias?: string; profile?: string }) => { const client = await getClient(); const result = await client.openPage(url, options.alias, options.profile); print(result); }); program.command('list') .description('List all open pages') .action(async () => { const client = await getClient(); const result = await client.listPages(); print(result); }); program.command('get ') .description('Get page info by ID or alias') .action(async (id: string) => { const client = await getClient(); const result = await client.getPage(id); print(result); }); program.command('kill ') .description('Close a page by ID or alias') .action(async (id: string) => { const client = await getClient(); const result = await client.killPage(id); print(result); }); // navigation — page interactions program.command('navigate ') .description('Navigate an existing page to a URL') .action(async (id: string, url: string) => { const client = await getClient(); const result = await client.navigate(id, url); print(result); }); program.command('click ') .description('Click an element on a page') .action(async (id: string, selector: string) => { const client = await getClient(); const result = await client.click(id, selector); print(result); }); program.command('type ') .description('Type text into an element') .action(async (id: string, selector: string, text: string) => { const client = await getClient(); const result = await client.type(id, selector, text); print(result); }); program.command('scroll ') .description('Scroll on a page') .option('-y, --delta-y ', 'Vertical scroll delta', '0') .option('-b, --to-bottom', 'Scroll to bottom') .action(async (id: string, options: { deltaY: string; toBottom?: boolean }) => { const client = await getClient(); const result = await client.scroll(id, { deltaY: parseInt(options.deltaY, 10) || undefined, toBottom: options.toBottom, }); print(result); }); program.command('eval ') .description('Evaluate JavaScript on a page') .action(async (id: string, code: string) => { const client = await getClient(); const result = await client.eval(id, code); print(result); }); program.command('wait ') .description('Wait for selector or duration on a page') .option('-s, --selector ', 'Wait for CSS selector') .option('-m, --ms ', 'Wait time in milliseconds') .action(async (id: string, options: { selector?: string; ms?: string }) => { const client = await getClient(); const result = await client.wait(id, { selector: options.selector, ms: options.ms ? parseInt(options.ms, 10) : undefined, }); print(result); }); // content — page content retrieval program.command('screenshot ') .description('Take a screenshot of a page (returns base64)') .action(async (id: string) => { const client = await getClient(); const result = await client.screenshot(id); print(result); }); program.command('text ') .description('Get the text content of a page') .action(async (id: string) => { const client = await getClient(); const result = await client.text(id); print(result); }); program.command('html ') .description('Get the HTML source of a page') .action(async (id: string) => { const client = await getClient(); const result = await client.html(id); print(result); }); // profiles program.command('profiles') .description('List available fingerprint profiles') .action(async () => { const client = await getClient(); const result = await client.getProfiles(); print(result); }); program.parse();