feat: add Chrome extension browser relay
This commit is contained in:
97
src/cli/browser-cli-extension.ts
Normal file
97
src/cli/browser-cli-extension.ts
Normal file
@@ -0,0 +1,97 @@
|
||||
import fs from "node:fs";
|
||||
import path from "node:path";
|
||||
import { fileURLToPath } from "node:url";
|
||||
|
||||
import type { Command } from "commander";
|
||||
|
||||
import { STATE_DIR_CLAWDBOT } from "../config/paths.js";
|
||||
import { danger } from "../globals.js";
|
||||
import { defaultRuntime } from "../runtime.js";
|
||||
import { movePathToTrash } from "../browser/trash.js";
|
||||
|
||||
function bundledExtensionRootDir() {
|
||||
const here = path.dirname(fileURLToPath(import.meta.url));
|
||||
return path.resolve(here, "../../assets/chrome-extension");
|
||||
}
|
||||
|
||||
function installedExtensionRootDir() {
|
||||
return path.join(STATE_DIR_CLAWDBOT, "browser", "chrome-extension");
|
||||
}
|
||||
|
||||
function hasManifest(dir: string) {
|
||||
return fs.existsSync(path.join(dir, "manifest.json"));
|
||||
}
|
||||
|
||||
export async function installChromeExtension(opts?: {
|
||||
stateDir?: string;
|
||||
sourceDir?: string;
|
||||
}): Promise<{ path: string }> {
|
||||
const src = opts?.sourceDir ?? bundledExtensionRootDir();
|
||||
if (!hasManifest(src)) {
|
||||
throw new Error("Bundled Chrome extension is missing. Reinstall Clawdbot and try again.");
|
||||
}
|
||||
|
||||
const stateDir = opts?.stateDir ?? STATE_DIR_CLAWDBOT;
|
||||
const dest = path.join(stateDir, "browser", "chrome-extension");
|
||||
fs.mkdirSync(path.dirname(dest), { recursive: true });
|
||||
|
||||
if (fs.existsSync(dest)) {
|
||||
await movePathToTrash(dest).catch(() => {
|
||||
const backup = `${dest}.old-${Date.now()}`;
|
||||
fs.renameSync(dest, backup);
|
||||
});
|
||||
}
|
||||
|
||||
await fs.promises.cp(src, dest, { recursive: true });
|
||||
if (!hasManifest(dest)) {
|
||||
throw new Error("Chrome extension install failed (manifest.json missing). Try again.");
|
||||
}
|
||||
|
||||
return { path: dest };
|
||||
}
|
||||
|
||||
export function registerBrowserExtensionCommands(
|
||||
browser: Command,
|
||||
parentOpts: (cmd: Command) => { json?: boolean },
|
||||
) {
|
||||
const ext = browser.command("extension").description("Chrome extension helpers");
|
||||
|
||||
ext
|
||||
.command("install")
|
||||
.description("Install the Chrome extension to a stable local path")
|
||||
.action(async (_opts, cmd) => {
|
||||
const parent = parentOpts(cmd);
|
||||
let installed: { path: string };
|
||||
try {
|
||||
installed = await installChromeExtension();
|
||||
} catch (err) {
|
||||
defaultRuntime.error(danger(String(err)));
|
||||
defaultRuntime.exit(1);
|
||||
}
|
||||
|
||||
if (parent?.json) {
|
||||
defaultRuntime.log(JSON.stringify({ ok: true, path: installed.path }, null, 2));
|
||||
return;
|
||||
}
|
||||
defaultRuntime.log(installed.path);
|
||||
});
|
||||
|
||||
ext
|
||||
.command("path")
|
||||
.description("Print the path to the installed Chrome extension (load unpacked)")
|
||||
.action((_opts, cmd) => {
|
||||
const parent = parentOpts(cmd);
|
||||
const dir = installedExtensionRootDir();
|
||||
if (!hasManifest(dir)) {
|
||||
defaultRuntime.error(
|
||||
danger('Chrome extension is not installed. Run: "clawdbot browser extension install"'),
|
||||
);
|
||||
defaultRuntime.exit(1);
|
||||
}
|
||||
if (parent?.json) {
|
||||
defaultRuntime.log(JSON.stringify({ path: dir }, null, 2));
|
||||
return;
|
||||
}
|
||||
defaultRuntime.log(dir);
|
||||
});
|
||||
}
|
||||
Reference in New Issue
Block a user