Spaces:
Paused
Paused
File size: 4,687 Bytes
c1243f9 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 | import type { Command } from "commander";
import fs from "node:fs";
import path from "node:path";
import { fileURLToPath } from "node:url";
import { movePathToTrash } from "../browser/trash.js";
import { resolveStateDir } from "../config/paths.js";
import { danger, info } from "../globals.js";
import { copyToClipboard } from "../infra/clipboard.js";
import { defaultRuntime } from "../runtime.js";
import { formatDocsLink } from "../terminal/links.js";
import { theme } from "../terminal/theme.js";
import { shortenHomePath } from "../utils.js";
import { formatCliCommand } from "./command-format.js";
export function resolveBundledExtensionRootDir(
here = path.dirname(fileURLToPath(import.meta.url)),
) {
let current = here;
while (true) {
const candidate = path.join(current, "assets", "chrome-extension");
if (hasManifest(candidate)) {
return candidate;
}
const parent = path.dirname(current);
if (parent === current) {
break;
}
current = parent;
}
return path.resolve(here, "../../assets/chrome-extension");
}
function installedExtensionRootDir() {
return path.join(resolveStateDir(), "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 ?? resolveBundledExtensionRootDir();
if (!hasManifest(src)) {
throw new Error("Bundled Chrome extension is missing. Reinstall OpenClaw and try again.");
}
const stateDir = opts?.stateDir ?? resolveStateDir();
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;
}
const displayPath = shortenHomePath(installed.path);
defaultRuntime.log(displayPath);
const copied = await copyToClipboard(installed.path).catch(() => false);
defaultRuntime.error(
info(
[
copied ? "Copied to clipboard." : "Copy to clipboard unavailable.",
"Next:",
`- Chrome → chrome://extensions → enable “Developer mode”`,
`- “Load unpacked” → select: ${displayPath}`,
`- Pin “OpenClaw Browser Relay”, then click it on the tab (badge shows ON)`,
"",
`${theme.muted("Docs:")} ${formatDocsLink("/tools/chrome-extension", "docs.openclaw.ai/tools/chrome-extension")}`,
].join("\n"),
),
);
});
ext
.command("path")
.description("Print the path to the installed Chrome extension (load unpacked)")
.action(async (_opts, cmd) => {
const parent = parentOpts(cmd);
const dir = installedExtensionRootDir();
if (!hasManifest(dir)) {
defaultRuntime.error(
danger(
[
`Chrome extension is not installed. Run: "${formatCliCommand("openclaw browser extension install")}"`,
`Docs: ${formatDocsLink("/tools/chrome-extension", "docs.openclaw.ai/tools/chrome-extension")}`,
].join("\n"),
),
);
defaultRuntime.exit(1);
}
if (parent?.json) {
defaultRuntime.log(JSON.stringify({ path: dir }, null, 2));
return;
}
const displayPath = shortenHomePath(dir);
defaultRuntime.log(displayPath);
const copied = await copyToClipboard(dir).catch(() => false);
if (copied) {
defaultRuntime.error(info("Copied to clipboard."));
}
});
}
|