feat(browser): add remote-capable profiles
Co-authored-by: James Groat <james@groat.com>
This commit is contained in:
@@ -64,10 +64,12 @@ export function registerBrowserActionInputCommands(
|
||||
.action(async (url: string, opts, cmd) => {
|
||||
const parent = parentOpts(cmd);
|
||||
const baseUrl = resolveBrowserControlUrl(parent?.url);
|
||||
const profile = parent?.profile;
|
||||
try {
|
||||
const result = await browserNavigate(baseUrl, {
|
||||
url,
|
||||
targetId: opts.targetId?.trim() || undefined,
|
||||
profile,
|
||||
});
|
||||
if (parent?.json) {
|
||||
defaultRuntime.log(JSON.stringify(result, null, 2));
|
||||
@@ -89,6 +91,7 @@ export function registerBrowserActionInputCommands(
|
||||
.action(async (width: number, height: number, opts, cmd) => {
|
||||
const parent = parentOpts(cmd);
|
||||
const baseUrl = resolveBrowserControlUrl(parent?.url);
|
||||
const profile = parent?.profile;
|
||||
if (!Number.isFinite(width) || !Number.isFinite(height)) {
|
||||
defaultRuntime.error(danger("width and height must be numbers"));
|
||||
defaultRuntime.exit(1);
|
||||
@@ -100,7 +103,7 @@ export function registerBrowserActionInputCommands(
|
||||
width,
|
||||
height,
|
||||
targetId: opts.targetId?.trim() || undefined,
|
||||
});
|
||||
}, { profile });
|
||||
if (parent?.json) {
|
||||
defaultRuntime.log(JSON.stringify(result, null, 2));
|
||||
return;
|
||||
@@ -123,6 +126,7 @@ export function registerBrowserActionInputCommands(
|
||||
.action(async (ref: string | undefined, opts, cmd) => {
|
||||
const parent = parentOpts(cmd);
|
||||
const baseUrl = resolveBrowserControlUrl(parent?.url);
|
||||
const profile = parent?.profile;
|
||||
const refValue = typeof ref === "string" ? ref.trim() : "";
|
||||
if (!refValue) {
|
||||
defaultRuntime.error(danger("ref is required"));
|
||||
@@ -143,7 +147,7 @@ export function registerBrowserActionInputCommands(
|
||||
doubleClick: Boolean(opts.double),
|
||||
button: opts.button?.trim() || undefined,
|
||||
modifiers,
|
||||
});
|
||||
}, { profile });
|
||||
if (parent?.json) {
|
||||
defaultRuntime.log(JSON.stringify(result, null, 2));
|
||||
return;
|
||||
@@ -167,6 +171,7 @@ export function registerBrowserActionInputCommands(
|
||||
.action(async (ref: string | undefined, text: string, opts, cmd) => {
|
||||
const parent = parentOpts(cmd);
|
||||
const baseUrl = resolveBrowserControlUrl(parent?.url);
|
||||
const profile = parent?.profile;
|
||||
const refValue = typeof ref === "string" ? ref.trim() : "";
|
||||
if (!refValue) {
|
||||
defaultRuntime.error(danger("ref is required"));
|
||||
@@ -181,7 +186,7 @@ export function registerBrowserActionInputCommands(
|
||||
submit: Boolean(opts.submit),
|
||||
slowly: Boolean(opts.slowly),
|
||||
targetId: opts.targetId?.trim() || undefined,
|
||||
});
|
||||
}, { profile });
|
||||
if (parent?.json) {
|
||||
defaultRuntime.log(JSON.stringify(result, null, 2));
|
||||
return;
|
||||
@@ -201,12 +206,13 @@ export function registerBrowserActionInputCommands(
|
||||
.action(async (key: string, opts, cmd) => {
|
||||
const parent = parentOpts(cmd);
|
||||
const baseUrl = resolveBrowserControlUrl(parent?.url);
|
||||
const profile = parent?.profile;
|
||||
try {
|
||||
const result = await browserAct(baseUrl, {
|
||||
kind: "press",
|
||||
key,
|
||||
targetId: opts.targetId?.trim() || undefined,
|
||||
});
|
||||
}, { profile });
|
||||
if (parent?.json) {
|
||||
defaultRuntime.log(JSON.stringify(result, null, 2));
|
||||
return;
|
||||
@@ -226,12 +232,13 @@ export function registerBrowserActionInputCommands(
|
||||
.action(async (ref: string, opts, cmd) => {
|
||||
const parent = parentOpts(cmd);
|
||||
const baseUrl = resolveBrowserControlUrl(parent?.url);
|
||||
const profile = parent?.profile;
|
||||
try {
|
||||
const result = await browserAct(baseUrl, {
|
||||
kind: "hover",
|
||||
ref,
|
||||
targetId: opts.targetId?.trim() || undefined,
|
||||
});
|
||||
}, { profile });
|
||||
if (parent?.json) {
|
||||
defaultRuntime.log(JSON.stringify(result, null, 2));
|
||||
return;
|
||||
@@ -252,13 +259,14 @@ export function registerBrowserActionInputCommands(
|
||||
.action(async (startRef: string, endRef: string, opts, cmd) => {
|
||||
const parent = parentOpts(cmd);
|
||||
const baseUrl = resolveBrowserControlUrl(parent?.url);
|
||||
const profile = parent?.profile;
|
||||
try {
|
||||
const result = await browserAct(baseUrl, {
|
||||
kind: "drag",
|
||||
startRef,
|
||||
endRef,
|
||||
targetId: opts.targetId?.trim() || undefined,
|
||||
});
|
||||
}, { profile });
|
||||
if (parent?.json) {
|
||||
defaultRuntime.log(JSON.stringify(result, null, 2));
|
||||
return;
|
||||
@@ -279,13 +287,14 @@ export function registerBrowserActionInputCommands(
|
||||
.action(async (ref: string, values: string[], opts, cmd) => {
|
||||
const parent = parentOpts(cmd);
|
||||
const baseUrl = resolveBrowserControlUrl(parent?.url);
|
||||
const profile = parent?.profile;
|
||||
try {
|
||||
const result = await browserAct(baseUrl, {
|
||||
kind: "select",
|
||||
ref,
|
||||
values,
|
||||
targetId: opts.targetId?.trim() || undefined,
|
||||
});
|
||||
}, { profile });
|
||||
if (parent?.json) {
|
||||
defaultRuntime.log(JSON.stringify(result, null, 2));
|
||||
return;
|
||||
@@ -313,6 +322,7 @@ export function registerBrowserActionInputCommands(
|
||||
.action(async (paths: string[], opts, cmd) => {
|
||||
const parent = parentOpts(cmd);
|
||||
const baseUrl = resolveBrowserControlUrl(parent?.url);
|
||||
const profile = parent?.profile;
|
||||
try {
|
||||
const result = await browserArmFileChooser(baseUrl, {
|
||||
paths,
|
||||
@@ -323,6 +333,7 @@ export function registerBrowserActionInputCommands(
|
||||
timeoutMs: Number.isFinite(opts.timeoutMs)
|
||||
? opts.timeoutMs
|
||||
: undefined,
|
||||
profile,
|
||||
});
|
||||
if (parent?.json) {
|
||||
defaultRuntime.log(JSON.stringify(result, null, 2));
|
||||
@@ -344,6 +355,7 @@ export function registerBrowserActionInputCommands(
|
||||
.action(async (opts, cmd) => {
|
||||
const parent = parentOpts(cmd);
|
||||
const baseUrl = resolveBrowserControlUrl(parent?.url);
|
||||
const profile = parent?.profile;
|
||||
try {
|
||||
const fields = await readFields({
|
||||
fields: opts.fields,
|
||||
@@ -353,7 +365,7 @@ export function registerBrowserActionInputCommands(
|
||||
kind: "fill",
|
||||
fields,
|
||||
targetId: opts.targetId?.trim() || undefined,
|
||||
});
|
||||
}, { profile });
|
||||
if (parent?.json) {
|
||||
defaultRuntime.log(JSON.stringify(result, null, 2));
|
||||
return;
|
||||
@@ -380,6 +392,7 @@ export function registerBrowserActionInputCommands(
|
||||
.action(async (opts, cmd) => {
|
||||
const parent = parentOpts(cmd);
|
||||
const baseUrl = resolveBrowserControlUrl(parent?.url);
|
||||
const profile = parent?.profile;
|
||||
const accept = opts.accept ? true : opts.dismiss ? false : undefined;
|
||||
if (accept === undefined) {
|
||||
defaultRuntime.error(danger("Specify --accept or --dismiss"));
|
||||
@@ -394,6 +407,7 @@ export function registerBrowserActionInputCommands(
|
||||
timeoutMs: Number.isFinite(opts.timeoutMs)
|
||||
? opts.timeoutMs
|
||||
: undefined,
|
||||
profile,
|
||||
});
|
||||
if (parent?.json) {
|
||||
defaultRuntime.log(JSON.stringify(result, null, 2));
|
||||
@@ -416,6 +430,7 @@ export function registerBrowserActionInputCommands(
|
||||
.action(async (opts, cmd) => {
|
||||
const parent = parentOpts(cmd);
|
||||
const baseUrl = resolveBrowserControlUrl(parent?.url);
|
||||
const profile = parent?.profile;
|
||||
try {
|
||||
const result = await browserAct(baseUrl, {
|
||||
kind: "wait",
|
||||
@@ -423,7 +438,7 @@ export function registerBrowserActionInputCommands(
|
||||
text: opts.text?.trim() || undefined,
|
||||
textGone: opts.textGone?.trim() || undefined,
|
||||
targetId: opts.targetId?.trim() || undefined,
|
||||
});
|
||||
}, { profile });
|
||||
if (parent?.json) {
|
||||
defaultRuntime.log(JSON.stringify(result, null, 2));
|
||||
return;
|
||||
@@ -444,6 +459,7 @@ export function registerBrowserActionInputCommands(
|
||||
.action(async (opts, cmd) => {
|
||||
const parent = parentOpts(cmd);
|
||||
const baseUrl = resolveBrowserControlUrl(parent?.url);
|
||||
const profile = parent?.profile;
|
||||
if (!opts.fn) {
|
||||
defaultRuntime.error(danger("Missing --fn"));
|
||||
defaultRuntime.exit(1);
|
||||
@@ -455,7 +471,7 @@ export function registerBrowserActionInputCommands(
|
||||
fn: opts.fn,
|
||||
ref: opts.ref?.trim() || undefined,
|
||||
targetId: opts.targetId?.trim() || undefined,
|
||||
});
|
||||
}, { profile });
|
||||
if (parent?.json) {
|
||||
defaultRuntime.log(JSON.stringify(result, null, 2));
|
||||
return;
|
||||
|
||||
@@ -20,10 +20,12 @@ export function registerBrowserActionObserveCommands(
|
||||
.action(async (opts, cmd) => {
|
||||
const parent = parentOpts(cmd);
|
||||
const baseUrl = resolveBrowserControlUrl(parent?.url);
|
||||
const profile = parent?.profile;
|
||||
try {
|
||||
const result = await browserConsoleMessages(baseUrl, {
|
||||
level: opts.level?.trim() || undefined,
|
||||
targetId: opts.targetId?.trim() || undefined,
|
||||
profile,
|
||||
});
|
||||
if (parent?.json) {
|
||||
defaultRuntime.log(JSON.stringify(result, null, 2));
|
||||
@@ -43,9 +45,11 @@ export function registerBrowserActionObserveCommands(
|
||||
.action(async (opts, cmd) => {
|
||||
const parent = parentOpts(cmd);
|
||||
const baseUrl = resolveBrowserControlUrl(parent?.url);
|
||||
const profile = parent?.profile;
|
||||
try {
|
||||
const result = await browserPdfSave(baseUrl, {
|
||||
targetId: opts.targetId?.trim() || undefined,
|
||||
profile,
|
||||
});
|
||||
if (parent?.json) {
|
||||
defaultRuntime.log(JSON.stringify(result, null, 2));
|
||||
|
||||
@@ -24,6 +24,7 @@ export function registerBrowserInspectCommands(
|
||||
.action(async (targetId: string | undefined, opts, cmd) => {
|
||||
const parent = parentOpts(cmd);
|
||||
const baseUrl = resolveBrowserControlUrl(parent?.url);
|
||||
const profile = parent?.profile;
|
||||
try {
|
||||
const result = await browserScreenshotAction(baseUrl, {
|
||||
targetId: targetId?.trim() || undefined,
|
||||
@@ -31,6 +32,7 @@ export function registerBrowserInspectCommands(
|
||||
ref: opts.ref?.trim() || undefined,
|
||||
element: opts.element?.trim() || undefined,
|
||||
type: opts.type === "jpeg" ? "jpeg" : "png",
|
||||
profile,
|
||||
});
|
||||
if (parent?.json) {
|
||||
defaultRuntime.log(JSON.stringify(result, null, 2));
|
||||
@@ -57,12 +59,14 @@ export function registerBrowserInspectCommands(
|
||||
.action(async (opts, cmd) => {
|
||||
const parent = parentOpts(cmd);
|
||||
const baseUrl = resolveBrowserControlUrl(parent?.url);
|
||||
const profile = parent?.profile;
|
||||
const format = opts.format === "aria" ? "aria" : "ai";
|
||||
try {
|
||||
const result = await browserSnapshot(baseUrl, {
|
||||
format,
|
||||
targetId: opts.targetId?.trim() || undefined,
|
||||
limit: Number.isFinite(opts.limit) ? opts.limit : undefined,
|
||||
profile,
|
||||
});
|
||||
|
||||
if (opts.out) {
|
||||
|
||||
@@ -2,8 +2,11 @@ import type { Command } from "commander";
|
||||
|
||||
import {
|
||||
browserCloseTab,
|
||||
browserCreateProfile,
|
||||
browserDeleteProfile,
|
||||
browserFocusTab,
|
||||
browserOpenTab,
|
||||
browserProfiles,
|
||||
browserResetProfile,
|
||||
browserStart,
|
||||
browserStatus,
|
||||
@@ -11,7 +14,7 @@ import {
|
||||
browserTabs,
|
||||
resolveBrowserControlUrl,
|
||||
} from "../browser/client.js";
|
||||
import { browserAct } from "../browser/client-actions.js";
|
||||
import { browserAct } from "../browser/client-actions-core.js";
|
||||
import { danger, info } from "../globals.js";
|
||||
import { defaultRuntime } from "../runtime.js";
|
||||
import type { BrowserParentOpts } from "./browser-cli-shared.js";
|
||||
@@ -27,13 +30,16 @@ export function registerBrowserManageCommands(
|
||||
const parent = parentOpts(cmd);
|
||||
const baseUrl = resolveBrowserControlUrl(parent?.url);
|
||||
try {
|
||||
const status = await browserStatus(baseUrl);
|
||||
const status = await browserStatus(baseUrl, {
|
||||
profile: parent?.profile,
|
||||
});
|
||||
if (parent?.json) {
|
||||
defaultRuntime.log(JSON.stringify(status, null, 2));
|
||||
return;
|
||||
}
|
||||
defaultRuntime.log(
|
||||
[
|
||||
`profile: ${status.profile ?? "clawd"}`,
|
||||
`enabled: ${status.enabled}`,
|
||||
`running: ${status.running}`,
|
||||
`controlUrl: ${status.controlUrl}`,
|
||||
@@ -51,18 +57,22 @@ export function registerBrowserManageCommands(
|
||||
|
||||
browser
|
||||
.command("start")
|
||||
.description("Start the clawd browser (no-op if already running)")
|
||||
.description("Start the browser (no-op if already running)")
|
||||
.action(async (_opts, cmd) => {
|
||||
const parent = parentOpts(cmd);
|
||||
const baseUrl = resolveBrowserControlUrl(parent?.url);
|
||||
const profile = parent?.profile;
|
||||
try {
|
||||
await browserStart(baseUrl);
|
||||
const status = await browserStatus(baseUrl);
|
||||
await browserStart(baseUrl, { profile });
|
||||
const status = await browserStatus(baseUrl, { profile });
|
||||
if (parent?.json) {
|
||||
defaultRuntime.log(JSON.stringify(status, null, 2));
|
||||
return;
|
||||
}
|
||||
defaultRuntime.log(info(`🦞 clawd browser running: ${status.running}`));
|
||||
const name = status.profile ?? "clawd";
|
||||
defaultRuntime.log(
|
||||
info(`🦞 browser [${name}] running: ${status.running}`),
|
||||
);
|
||||
} catch (err) {
|
||||
defaultRuntime.error(danger(String(err)));
|
||||
defaultRuntime.exit(1);
|
||||
@@ -71,18 +81,22 @@ export function registerBrowserManageCommands(
|
||||
|
||||
browser
|
||||
.command("stop")
|
||||
.description("Stop the clawd browser (best-effort)")
|
||||
.description("Stop the browser (best-effort)")
|
||||
.action(async (_opts, cmd) => {
|
||||
const parent = parentOpts(cmd);
|
||||
const baseUrl = resolveBrowserControlUrl(parent?.url);
|
||||
const profile = parent?.profile;
|
||||
try {
|
||||
await browserStop(baseUrl);
|
||||
const status = await browserStatus(baseUrl);
|
||||
await browserStop(baseUrl, { profile });
|
||||
const status = await browserStatus(baseUrl, { profile });
|
||||
if (parent?.json) {
|
||||
defaultRuntime.log(JSON.stringify(status, null, 2));
|
||||
return;
|
||||
}
|
||||
defaultRuntime.log(info(`🦞 clawd browser running: ${status.running}`));
|
||||
const name = status.profile ?? "clawd";
|
||||
defaultRuntime.log(
|
||||
info(`🦞 browser [${name}] running: ${status.running}`),
|
||||
);
|
||||
} catch (err) {
|
||||
defaultRuntime.error(danger(String(err)));
|
||||
defaultRuntime.exit(1);
|
||||
@@ -91,24 +105,23 @@ export function registerBrowserManageCommands(
|
||||
|
||||
browser
|
||||
.command("reset-profile")
|
||||
.description("Reset clawd browser profile (moves it to Trash)")
|
||||
.description("Reset browser profile (moves it to Trash)")
|
||||
.action(async (_opts, cmd) => {
|
||||
const parent = parentOpts(cmd);
|
||||
const baseUrl = resolveBrowserControlUrl(parent?.url);
|
||||
const profile = parent?.profile;
|
||||
try {
|
||||
const result = await browserResetProfile(baseUrl);
|
||||
const result = await browserResetProfile(baseUrl, { profile });
|
||||
if (parent?.json) {
|
||||
defaultRuntime.log(JSON.stringify(result, null, 2));
|
||||
return;
|
||||
}
|
||||
if (!result.moved) {
|
||||
defaultRuntime.log(info("🦞 clawd browser profile already missing."));
|
||||
defaultRuntime.log(info(`🦞 browser profile already missing.`));
|
||||
return;
|
||||
}
|
||||
const dest = result.to ?? result.from;
|
||||
defaultRuntime.log(
|
||||
info(`🦞 clawd browser profile moved to Trash (${dest})`),
|
||||
);
|
||||
defaultRuntime.log(info(`🦞 browser profile moved to Trash (${dest})`));
|
||||
} catch (err) {
|
||||
defaultRuntime.error(danger(String(err)));
|
||||
defaultRuntime.exit(1);
|
||||
@@ -121,8 +134,9 @@ export function registerBrowserManageCommands(
|
||||
.action(async (_opts, cmd) => {
|
||||
const parent = parentOpts(cmd);
|
||||
const baseUrl = resolveBrowserControlUrl(parent?.url);
|
||||
const profile = parent?.profile;
|
||||
try {
|
||||
const tabs = await browserTabs(baseUrl);
|
||||
const tabs = await browserTabs(baseUrl, { profile });
|
||||
if (parent?.json) {
|
||||
defaultRuntime.log(JSON.stringify({ tabs }, null, 2));
|
||||
return;
|
||||
@@ -149,11 +163,12 @@ export function registerBrowserManageCommands(
|
||||
.command("open")
|
||||
.description("Open a URL in a new tab")
|
||||
.argument("<url>", "URL to open")
|
||||
.action(async (url: string, cmd) => {
|
||||
.action(async (url: string, _opts, cmd) => {
|
||||
const parent = parentOpts(cmd);
|
||||
const baseUrl = resolveBrowserControlUrl(parent?.url);
|
||||
const profile = parent?.profile;
|
||||
try {
|
||||
const tab = await browserOpenTab(baseUrl, url);
|
||||
const tab = await browserOpenTab(baseUrl, url, { profile });
|
||||
if (parent?.json) {
|
||||
defaultRuntime.log(JSON.stringify(tab, null, 2));
|
||||
return;
|
||||
@@ -169,11 +184,12 @@ export function registerBrowserManageCommands(
|
||||
.command("focus")
|
||||
.description("Focus a tab by target id (or unique prefix)")
|
||||
.argument("<targetId>", "Target id or unique prefix")
|
||||
.action(async (targetId: string, cmd) => {
|
||||
.action(async (targetId: string, _opts, cmd) => {
|
||||
const parent = parentOpts(cmd);
|
||||
const baseUrl = resolveBrowserControlUrl(parent?.url);
|
||||
const profile = parent?.profile;
|
||||
try {
|
||||
await browserFocusTab(baseUrl, targetId);
|
||||
await browserFocusTab(baseUrl, targetId, { profile });
|
||||
if (parent?.json) {
|
||||
defaultRuntime.log(JSON.stringify({ ok: true }, null, 2));
|
||||
return;
|
||||
@@ -189,14 +205,15 @@ export function registerBrowserManageCommands(
|
||||
.command("close")
|
||||
.description("Close a tab (target id optional)")
|
||||
.argument("[targetId]", "Target id or unique prefix (optional)")
|
||||
.action(async (targetId: string | undefined, cmd) => {
|
||||
.action(async (targetId: string | undefined, _opts, cmd) => {
|
||||
const parent = parentOpts(cmd);
|
||||
const baseUrl = resolveBrowserControlUrl(parent?.url);
|
||||
const profile = parent?.profile;
|
||||
try {
|
||||
if (targetId?.trim()) {
|
||||
await browserCloseTab(baseUrl, targetId.trim());
|
||||
await browserCloseTab(baseUrl, targetId.trim(), { profile });
|
||||
} else {
|
||||
await browserAct(baseUrl, { kind: "close" });
|
||||
await browserAct(baseUrl, { kind: "close" }, { profile });
|
||||
}
|
||||
if (parent?.json) {
|
||||
defaultRuntime.log(JSON.stringify({ ok: true }, null, 2));
|
||||
@@ -208,4 +225,102 @@ export function registerBrowserManageCommands(
|
||||
defaultRuntime.exit(1);
|
||||
}
|
||||
});
|
||||
|
||||
// Profile management commands
|
||||
browser
|
||||
.command("profiles")
|
||||
.description("List all browser profiles")
|
||||
.action(async (_opts, cmd) => {
|
||||
const parent = parentOpts(cmd);
|
||||
const baseUrl = resolveBrowserControlUrl(parent?.url);
|
||||
try {
|
||||
const profiles = await browserProfiles(baseUrl);
|
||||
if (parent?.json) {
|
||||
defaultRuntime.log(JSON.stringify({ profiles }, null, 2));
|
||||
return;
|
||||
}
|
||||
if (profiles.length === 0) {
|
||||
defaultRuntime.log("No profiles configured.");
|
||||
return;
|
||||
}
|
||||
defaultRuntime.log(
|
||||
profiles
|
||||
.map((p) => {
|
||||
const status = p.running ? "running" : "stopped";
|
||||
const tabs = p.running ? ` (${p.tabCount} tabs)` : "";
|
||||
const def = p.isDefault ? " [default]" : "";
|
||||
const loc = p.isRemote
|
||||
? `cdpUrl: ${p.cdpUrl}`
|
||||
: `port: ${p.cdpPort}`;
|
||||
const remote = p.isRemote ? " [remote]" : "";
|
||||
return `${p.name}: ${status}${tabs}${def}${remote}\n ${loc}, color: ${p.color}`;
|
||||
})
|
||||
.join("\n"),
|
||||
);
|
||||
} catch (err) {
|
||||
defaultRuntime.error(danger(String(err)));
|
||||
defaultRuntime.exit(1);
|
||||
}
|
||||
});
|
||||
|
||||
browser
|
||||
.command("create-profile")
|
||||
.description("Create a new browser profile")
|
||||
.requiredOption(
|
||||
"--name <name>",
|
||||
"Profile name (lowercase, numbers, hyphens)",
|
||||
)
|
||||
.option("--color <hex>", "Profile color (hex format, e.g. #0066CC)")
|
||||
.option("--cdp-url <url>", "CDP URL for remote Chrome (http/https)")
|
||||
.action(
|
||||
async (opts: { name: string; color?: string; cdpUrl?: string }, cmd) => {
|
||||
const parent = parentOpts(cmd);
|
||||
const baseUrl = resolveBrowserControlUrl(parent?.url);
|
||||
try {
|
||||
const result = await browserCreateProfile(baseUrl, {
|
||||
name: opts.name,
|
||||
color: opts.color,
|
||||
cdpUrl: opts.cdpUrl,
|
||||
});
|
||||
if (parent?.json) {
|
||||
defaultRuntime.log(JSON.stringify(result, null, 2));
|
||||
return;
|
||||
}
|
||||
const loc = result.isRemote
|
||||
? ` cdpUrl: ${result.cdpUrl}`
|
||||
: ` port: ${result.cdpPort}`;
|
||||
defaultRuntime.log(
|
||||
info(
|
||||
`🦞 Created profile "${result.profile}"\n${loc}\n color: ${result.color}`,
|
||||
),
|
||||
);
|
||||
} catch (err) {
|
||||
defaultRuntime.error(danger(String(err)));
|
||||
defaultRuntime.exit(1);
|
||||
}
|
||||
},
|
||||
);
|
||||
|
||||
browser
|
||||
.command("delete-profile")
|
||||
.description("Delete a browser profile")
|
||||
.requiredOption("--name <name>", "Profile name to delete")
|
||||
.action(async (opts: { name: string }, cmd) => {
|
||||
const parent = parentOpts(cmd);
|
||||
const baseUrl = resolveBrowserControlUrl(parent?.url);
|
||||
try {
|
||||
const result = await browserDeleteProfile(baseUrl, opts.name);
|
||||
if (parent?.json) {
|
||||
defaultRuntime.log(JSON.stringify(result, null, 2));
|
||||
return;
|
||||
}
|
||||
const msg = result.deleted
|
||||
? `🦞 Deleted profile "${result.profile}" (user data removed)`
|
||||
: `🦞 Deleted profile "${result.profile}" (no user data found)`;
|
||||
defaultRuntime.log(info(msg));
|
||||
} catch (err) {
|
||||
defaultRuntime.error(danger(String(err)));
|
||||
defaultRuntime.exit(1);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@@ -1 +1 @@
|
||||
export type BrowserParentOpts = { url?: string; json?: boolean };
|
||||
export type BrowserParentOpts = { url?: string; json?: boolean; profile?: string };
|
||||
|
||||
@@ -10,6 +10,7 @@ import {
|
||||
} from "./browser-cli-examples.js";
|
||||
import { registerBrowserInspectCommands } from "./browser-cli-inspect.js";
|
||||
import { registerBrowserManageCommands } from "./browser-cli-manage.js";
|
||||
import type { BrowserParentOpts } from "./browser-cli-shared.js";
|
||||
|
||||
export function registerBrowserCli(program: Command) {
|
||||
const browser = program
|
||||
@@ -19,6 +20,7 @@ export function registerBrowserCli(program: Command) {
|
||||
"--url <url>",
|
||||
"Override browser control URL (default from ~/.clawdis/clawdis.json)",
|
||||
)
|
||||
.option("--profile <name>", "Browser profile name (default from config)")
|
||||
.option("--json", "Output machine-readable JSON", false)
|
||||
.addHelpText(
|
||||
"after",
|
||||
@@ -33,7 +35,7 @@ export function registerBrowserCli(program: Command) {
|
||||
});
|
||||
|
||||
const parentOpts = (cmd: Command) =>
|
||||
cmd.parent?.opts?.() as { url?: string; json?: boolean };
|
||||
cmd.parent?.opts?.() as BrowserParentOpts;
|
||||
|
||||
registerBrowserManageCommands(browser, parentOpts);
|
||||
registerBrowserInspectCommands(browser, parentOpts);
|
||||
|
||||
Reference in New Issue
Block a user