mirror of
https://github.com/openclaw/openclaw.git
synced 2026-02-19 18:39:20 -05:00
141 lines
4.6 KiB
TypeScript
141 lines
4.6 KiB
TypeScript
import fs from "node:fs";
|
|
import path from "node:path";
|
|
import { fileURLToPath } from "node:url";
|
|
import type { Command } from "commander";
|
|
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);
|
|
return;
|
|
}
|
|
|
|
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."));
|
|
}
|
|
});
|
|
}
|