@xbrowser/cli 0.14.0 → 0.14.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{chunk-VUJDJCIN.js → chunk-ITKPSIP7.js} +93 -4
- package/dist/cli.js +512 -305
- package/dist/daemon-main.js +172 -80
- package/dist/{human-interaction-QPHNDD76.js → human-interaction-W753RVJB.js} +1 -2
- package/dist/index.d.ts +7 -68
- package/dist/index.js +407 -271
- package/dist/screenshot-CWAWMXVA.js +28 -0
- package/dist/screenshot-MB6R7RSS.js +26 -0
- package/package.json +1 -1
- package/dist/admin-6UTU2RZ2.js +0 -281
- package/dist/admin-MDGF4CET.js +0 -285
- package/dist/admin-RPJJ5CAF.js +0 -282
- package/dist/chunk-43VX3TYN.js +0 -83
- package/dist/chunk-DESA2KMG.js +0 -77
- package/dist/chunk-FF5WHQHN.js +0 -135
- package/dist/chunk-HINTG75P.js +0 -77
- package/dist/chunk-KTSQU4QT.js +0 -29
- package/dist/chunk-M7CMBPCA.js +0 -100
- package/dist/chunk-NFGO7J2I.js +0 -29
- package/dist/chunk-OLB6UJ25.js +0 -438
- package/dist/chunk-VEKPHQBR.js +0 -47
- package/dist/chunk-YEN2ODUI.js +0 -14
- package/dist/marketplace-FCVN5OTZ.js +0 -706
- package/dist/marketplace-FPT5YLKB.js +0 -351
- package/dist/marketplace-W545W4FR.js +0 -706
package/dist/index.js
CHANGED
|
@@ -1,9 +1,3 @@
|
|
|
1
|
-
import {
|
|
2
|
-
CaptchaDetector,
|
|
3
|
-
HumanInteractionManager,
|
|
4
|
-
ScreencastCapturer,
|
|
5
|
-
WebhookNotifier
|
|
6
|
-
} from "./chunk-VUJDJCIN.js";
|
|
7
1
|
import {
|
|
8
2
|
generateBashScript,
|
|
9
3
|
generateJSScript,
|
|
@@ -52,24 +46,6 @@ import {
|
|
|
52
46
|
networkAnomalyRule,
|
|
53
47
|
pageLifecycleRule
|
|
54
48
|
} from "./chunk-ZZ2TFWIV.js";
|
|
55
|
-
import {
|
|
56
|
-
PluginMetadataParser,
|
|
57
|
-
createTarball
|
|
58
|
-
} from "./chunk-OLB6UJ25.js";
|
|
59
|
-
import {
|
|
60
|
-
ensureProxyFetch
|
|
61
|
-
} from "./chunk-VEKPHQBR.js";
|
|
62
|
-
import {
|
|
63
|
-
NPM_REGISTRY_URL,
|
|
64
|
-
NPM_SCOPE,
|
|
65
|
-
getCaptchaConfig,
|
|
66
|
-
getConfigValue,
|
|
67
|
-
getMarketplaceUrl,
|
|
68
|
-
loadConfig,
|
|
69
|
-
readJsonFile,
|
|
70
|
-
resolveNpmPackageWithFallback,
|
|
71
|
-
setConfigValue
|
|
72
|
-
} from "./chunk-M7CMBPCA.js";
|
|
73
49
|
import {
|
|
74
50
|
forwardCommandLog,
|
|
75
51
|
forwardNetworkAnalyze,
|
|
@@ -99,6 +75,21 @@ import {
|
|
|
99
75
|
startDaemonProcess,
|
|
100
76
|
stopDaemonProcess
|
|
101
77
|
} from "./chunk-ATFTAKMN.js";
|
|
78
|
+
import {
|
|
79
|
+
CaptchaDetector,
|
|
80
|
+
HumanInteractionManager,
|
|
81
|
+
NPM_REGISTRY_URL,
|
|
82
|
+
NPM_SCOPE,
|
|
83
|
+
ScreencastCapturer,
|
|
84
|
+
WebhookNotifier,
|
|
85
|
+
getCaptchaConfig,
|
|
86
|
+
getConfigValue,
|
|
87
|
+
getMarketplaceUrl,
|
|
88
|
+
loadConfig,
|
|
89
|
+
readJsonFile,
|
|
90
|
+
resolveNpmPackageWithFallback,
|
|
91
|
+
setConfigValue
|
|
92
|
+
} from "./chunk-ITKPSIP7.js";
|
|
102
93
|
import {
|
|
103
94
|
__require
|
|
104
95
|
} from "./chunk-3RG5ZIWI.js";
|
|
@@ -436,15 +427,15 @@ var clickCommand = registerCommand({
|
|
|
436
427
|
let detectedNewPage;
|
|
437
428
|
let cleanup;
|
|
438
429
|
if (ctx.browserContext?.on) {
|
|
439
|
-
const pagePromise = new Promise((
|
|
430
|
+
const pagePromise = new Promise((resolve16) => {
|
|
440
431
|
const timer = setTimeout(() => {
|
|
441
432
|
ctx.browserContext.off("page", handler);
|
|
442
|
-
|
|
433
|
+
resolve16(void 0);
|
|
443
434
|
}, 3e3);
|
|
444
435
|
const handler = (page2) => {
|
|
445
436
|
clearTimeout(timer);
|
|
446
437
|
ctx.browserContext.off("page", handler);
|
|
447
|
-
|
|
438
|
+
resolve16(page2);
|
|
448
439
|
};
|
|
449
440
|
ctx.browserContext.on("page", handler);
|
|
450
441
|
});
|
|
@@ -1202,7 +1193,7 @@ var consoleCheckCommand = registerCommand({
|
|
|
1202
1193
|
await page.goto(p.url, { waitUntil: "domcontentloaded" });
|
|
1203
1194
|
}
|
|
1204
1195
|
const messages = await page.evaluate((args) => {
|
|
1205
|
-
return new Promise((
|
|
1196
|
+
return new Promise((resolve16) => {
|
|
1206
1197
|
const collected = [];
|
|
1207
1198
|
const originalConsole = {
|
|
1208
1199
|
log: console.log,
|
|
@@ -1269,7 +1260,7 @@ ${a.stack || ""}`;
|
|
|
1269
1260
|
console.warn = originalConsole.warn;
|
|
1270
1261
|
console.error = originalConsole.error;
|
|
1271
1262
|
console.info = originalConsole.info;
|
|
1272
|
-
|
|
1263
|
+
resolve16(collected);
|
|
1273
1264
|
}, args.duration);
|
|
1274
1265
|
});
|
|
1275
1266
|
}, { duration: p.duration });
|
|
@@ -1681,7 +1672,7 @@ async function executeAction(page, action) {
|
|
|
1681
1672
|
if (action.selector) {
|
|
1682
1673
|
await page.waitForSelector(action.selector, { timeout: 3e4 });
|
|
1683
1674
|
} else if (action.milliseconds) {
|
|
1684
|
-
await new Promise((
|
|
1675
|
+
await new Promise((resolve16) => setTimeout(resolve16, action.milliseconds));
|
|
1685
1676
|
} else {
|
|
1686
1677
|
throw new Error("wait action requires either milliseconds or selector");
|
|
1687
1678
|
}
|
|
@@ -1764,8 +1755,8 @@ var actionsCommand = registerCommand({
|
|
|
1764
1755
|
results.push(result);
|
|
1765
1756
|
}
|
|
1766
1757
|
})();
|
|
1767
|
-
const timeoutPromise = new Promise((
|
|
1768
|
-
setTimeout(
|
|
1758
|
+
const timeoutPromise = new Promise((resolve16) => {
|
|
1759
|
+
setTimeout(resolve16, timeoutMs);
|
|
1769
1760
|
});
|
|
1770
1761
|
await Promise.race([executionPromise, timeoutPromise]);
|
|
1771
1762
|
const title = await ctx.page.title();
|
|
@@ -2439,11 +2430,11 @@ async function navigateForMap(page, url, timeout = 15e3) {
|
|
|
2439
2430
|
}
|
|
2440
2431
|
async function extractPageLinks(page, baseUrl) {
|
|
2441
2432
|
await navigateForMap(page, baseUrl);
|
|
2442
|
-
await new Promise((
|
|
2433
|
+
await new Promise((resolve16) => setTimeout(resolve16, 2e3));
|
|
2443
2434
|
await page.evaluate(() => {
|
|
2444
2435
|
window.scrollTo(0, document.body.scrollHeight);
|
|
2445
2436
|
});
|
|
2446
|
-
await new Promise((
|
|
2437
|
+
await new Promise((resolve16) => setTimeout(resolve16, 1e3));
|
|
2447
2438
|
const origin = new URL(baseUrl).origin;
|
|
2448
2439
|
const rawLinks = await page.evaluate((evalOrigin) => {
|
|
2449
2440
|
return Array.from(document.querySelectorAll("a[href]")).map((a) => {
|
|
@@ -4550,25 +4541,25 @@ aria snapshot\uFF1A
|
|
|
4550
4541
|
async function analyzeWithLLM(ariaSnapshot) {
|
|
4551
4542
|
const piBin = process.env.PI_CLI_PATH || "pi";
|
|
4552
4543
|
const prompt = LLM_PROMPT.replace("{snapshot}", ariaSnapshot.slice(0, 4e3));
|
|
4553
|
-
return new Promise((
|
|
4544
|
+
return new Promise((resolve16) => {
|
|
4554
4545
|
execFile(
|
|
4555
4546
|
piBin,
|
|
4556
4547
|
["--provider", LLM_PROVIDER, "--model", LLM_MODEL, prompt],
|
|
4557
4548
|
{ timeout: LLM_TIMEOUT_MS, maxBuffer: 1024 * 1024 },
|
|
4558
4549
|
(err, stdout, _stderr) => {
|
|
4559
4550
|
if (err) {
|
|
4560
|
-
|
|
4551
|
+
resolve16(null);
|
|
4561
4552
|
return;
|
|
4562
4553
|
}
|
|
4563
4554
|
const output = (stdout || "").trim();
|
|
4564
4555
|
if (!output) {
|
|
4565
|
-
|
|
4556
|
+
resolve16(null);
|
|
4566
4557
|
return;
|
|
4567
4558
|
}
|
|
4568
4559
|
try {
|
|
4569
4560
|
const parsed = parse(output);
|
|
4570
4561
|
if (!parsed || typeof parsed !== "object") {
|
|
4571
|
-
|
|
4562
|
+
resolve16(null);
|
|
4572
4563
|
return;
|
|
4573
4564
|
}
|
|
4574
4565
|
const elements = {};
|
|
@@ -4583,9 +4574,9 @@ async function analyzeWithLLM(ariaSnapshot) {
|
|
|
4583
4574
|
};
|
|
4584
4575
|
}
|
|
4585
4576
|
}
|
|
4586
|
-
|
|
4577
|
+
resolve16(Object.keys(elements).length > 0 ? elements : null);
|
|
4587
4578
|
} catch {
|
|
4588
|
-
|
|
4579
|
+
resolve16(null);
|
|
4589
4580
|
}
|
|
4590
4581
|
}
|
|
4591
4582
|
);
|
|
@@ -5138,11 +5129,11 @@ function resolveScriptContent(params) {
|
|
|
5138
5129
|
async function readStdin() {
|
|
5139
5130
|
const { createReadStream } = await import("fs");
|
|
5140
5131
|
const { createInterface: createInterface2 } = await import("readline");
|
|
5141
|
-
return new Promise((
|
|
5132
|
+
return new Promise((resolve16, reject) => {
|
|
5142
5133
|
const lines = [];
|
|
5143
5134
|
const rl = createInterface2({ input: createReadStream("/dev/stdin") });
|
|
5144
5135
|
rl.on("line", (line) => lines.push(line));
|
|
5145
|
-
rl.on("close", () =>
|
|
5136
|
+
rl.on("close", () => resolve16(lines.join("\n")));
|
|
5146
5137
|
rl.on("error", reject);
|
|
5147
5138
|
});
|
|
5148
5139
|
}
|
|
@@ -5880,12 +5871,82 @@ var promoCommand = registerCommand({
|
|
|
5880
5871
|
import {
|
|
5881
5872
|
Core
|
|
5882
5873
|
} from "@dyyz1993/xcli-core";
|
|
5883
|
-
import { resolve as
|
|
5884
|
-
import { existsSync as
|
|
5874
|
+
import { resolve as resolve8 } from "path";
|
|
5875
|
+
import { existsSync as existsSync5, readdirSync } from "fs";
|
|
5885
5876
|
import { homedir as homedir2 } from "os";
|
|
5886
5877
|
|
|
5878
|
+
// src/plugin/metadata-parser.ts
|
|
5879
|
+
import { existsSync as existsSync3 } from "fs";
|
|
5880
|
+
import { resolve as resolve7 } from "path";
|
|
5881
|
+
var PluginMetadataParser = class {
|
|
5882
|
+
static XBROWSER_KEYWORDS = ["xbrowser", "xbrowser-plugin"];
|
|
5883
|
+
static parseFromPackageJson(pluginPath) {
|
|
5884
|
+
const packageJsonPath = resolve7(pluginPath, "package.json");
|
|
5885
|
+
if (!existsSync3(packageJsonPath)) {
|
|
5886
|
+
return null;
|
|
5887
|
+
}
|
|
5888
|
+
const packageJson = readJsonFile(packageJsonPath, null);
|
|
5889
|
+
if (!packageJson) return null;
|
|
5890
|
+
if (!packageJson.xbrowser) {
|
|
5891
|
+
return null;
|
|
5892
|
+
}
|
|
5893
|
+
const xbrowser = packageJson.xbrowser;
|
|
5894
|
+
const metadata = {
|
|
5895
|
+
id: xbrowser.id || packageJson.name,
|
|
5896
|
+
name: xbrowser.name || packageJson.name,
|
|
5897
|
+
description: xbrowser.description || packageJson.description || "",
|
|
5898
|
+
version: xbrowser.version || packageJson.version || "1.0.0",
|
|
5899
|
+
author: xbrowser.author || this.extractAuthor(packageJson.author),
|
|
5900
|
+
homepage: xbrowser.homepage || packageJson.homepage,
|
|
5901
|
+
commands: xbrowser.commands,
|
|
5902
|
+
sites: xbrowser.sites,
|
|
5903
|
+
tags: xbrowser.tags,
|
|
5904
|
+
screenshot: xbrowser.screenshot,
|
|
5905
|
+
license: xbrowser.license || packageJson.license
|
|
5906
|
+
};
|
|
5907
|
+
return metadata;
|
|
5908
|
+
}
|
|
5909
|
+
static isXBrowserPlugin(packageJson) {
|
|
5910
|
+
if (packageJson.xbrowser) {
|
|
5911
|
+
return true;
|
|
5912
|
+
}
|
|
5913
|
+
const keywords = packageJson.keywords;
|
|
5914
|
+
if (!keywords) return false;
|
|
5915
|
+
return this.XBROWSER_KEYWORDS.some((kw) => keywords.includes(kw));
|
|
5916
|
+
}
|
|
5917
|
+
static fromNPMResult(result) {
|
|
5918
|
+
const author = typeof result.author === "string" ? result.author : result.author?.name || "Unknown";
|
|
5919
|
+
return {
|
|
5920
|
+
id: result.name,
|
|
5921
|
+
name: result.name.replace(/^xbrowser-plugin-/, "").replace(/^@[^/]+\//, ""),
|
|
5922
|
+
description: result.description || "",
|
|
5923
|
+
version: result.version,
|
|
5924
|
+
author,
|
|
5925
|
+
homepage: result.homepage || result.links?.homepage,
|
|
5926
|
+
tags: result.keywords,
|
|
5927
|
+
license: ""
|
|
5928
|
+
};
|
|
5929
|
+
}
|
|
5930
|
+
static extractAuthor(author) {
|
|
5931
|
+
if (typeof author === "string") return author;
|
|
5932
|
+
if (typeof author === "object" && author !== null) {
|
|
5933
|
+
const authorObj = author;
|
|
5934
|
+
return authorObj.name || "Unknown";
|
|
5935
|
+
}
|
|
5936
|
+
return "Unknown";
|
|
5937
|
+
}
|
|
5938
|
+
static validateMetadata(metadata) {
|
|
5939
|
+
const errors = [];
|
|
5940
|
+
if (!metadata.id) errors.push("id is required");
|
|
5941
|
+
if (!metadata.name) errors.push("name is required");
|
|
5942
|
+
if (!metadata.description) errors.push("description is required");
|
|
5943
|
+
if (!metadata.version) errors.push("version is required");
|
|
5944
|
+
return errors;
|
|
5945
|
+
}
|
|
5946
|
+
};
|
|
5947
|
+
|
|
5887
5948
|
// src/plugin/ensure-deps.ts
|
|
5888
|
-
import { existsSync as
|
|
5949
|
+
import { existsSync as existsSync4, mkdirSync as mkdirSync2, writeFileSync as writeFileSync3 } from "fs";
|
|
5889
5950
|
import { join as join2 } from "path";
|
|
5890
5951
|
import { execSync as execSync6 } from "child_process";
|
|
5891
5952
|
var SHARED_PLUGIN_DEPENDENCIES = {
|
|
@@ -5894,11 +5955,11 @@ var SHARED_PLUGIN_DEPENDENCIES = {
|
|
|
5894
5955
|
};
|
|
5895
5956
|
function ensurePluginDependencies(pluginsDir) {
|
|
5896
5957
|
const zodPath = join2(pluginsDir, "node_modules", "zod");
|
|
5897
|
-
if (
|
|
5958
|
+
if (existsSync4(zodPath)) return;
|
|
5898
5959
|
mkdirSync2(pluginsDir, { recursive: true });
|
|
5899
5960
|
const pkgPath = join2(pluginsDir, "package.json");
|
|
5900
5961
|
let pkg2 = {};
|
|
5901
|
-
if (
|
|
5962
|
+
if (existsSync4(pkgPath)) {
|
|
5902
5963
|
try {
|
|
5903
5964
|
pkg2 = readJsonFile(pkgPath, {});
|
|
5904
5965
|
} catch {
|
|
@@ -5912,7 +5973,7 @@ function ensurePluginDependencies(pluginsDir) {
|
|
|
5912
5973
|
needsInstall = true;
|
|
5913
5974
|
}
|
|
5914
5975
|
}
|
|
5915
|
-
if (!needsInstall &&
|
|
5976
|
+
if (!needsInstall && existsSync4(join2(pluginsDir, "node_modules"))) return;
|
|
5916
5977
|
pkg2.dependencies = existingDeps;
|
|
5917
5978
|
pkg2.private = true;
|
|
5918
5979
|
pkg2.description = pkg2.description || "xbrowser plugins \u2014 shared dependencies";
|
|
@@ -5946,7 +6007,7 @@ var XBrowserPluginLoader = class {
|
|
|
5946
6007
|
envPrefix: "XBROWSER",
|
|
5947
6008
|
pluginDirs: [
|
|
5948
6009
|
...DEFAULT_PLUGIN_DIRS,
|
|
5949
|
-
|
|
6010
|
+
resolve8(cwd, ".xcli/plugins")
|
|
5950
6011
|
]
|
|
5951
6012
|
};
|
|
5952
6013
|
this.core = new Core(coreConfig);
|
|
@@ -5985,31 +6046,31 @@ var XBrowserPluginLoader = class {
|
|
|
5985
6046
|
}
|
|
5986
6047
|
async scanAndLoad() {
|
|
5987
6048
|
const cwd = this.options.cwd || process.cwd();
|
|
5988
|
-
const globalDir = this.options.globalDir ||
|
|
6049
|
+
const globalDir = this.options.globalDir || resolve8(homedir2(), ".xbrowser/plugins");
|
|
5989
6050
|
ensurePluginDependencies(globalDir);
|
|
5990
6051
|
const dirs = [
|
|
5991
|
-
|
|
5992
|
-
|
|
5993
|
-
this.options.userDir ||
|
|
6052
|
+
resolve8(cwd, ".xcli/plugins"),
|
|
6053
|
+
resolve8(cwd, "../.xcli/plugins"),
|
|
6054
|
+
this.options.userDir || resolve8(homedir2(), ".xcli/plugins"),
|
|
5994
6055
|
globalDir
|
|
5995
6056
|
];
|
|
5996
6057
|
const loaded = [];
|
|
5997
6058
|
const seen = /* @__PURE__ */ new Set();
|
|
5998
6059
|
for (const dir of dirs) {
|
|
5999
|
-
if (!
|
|
6060
|
+
if (!existsSync5(dir)) continue;
|
|
6000
6061
|
const entries = readdirSync(dir, { withFileTypes: true });
|
|
6001
6062
|
for (const entry of entries) {
|
|
6002
6063
|
if (!entry.isDirectory()) continue;
|
|
6003
6064
|
if (seen.has(entry.name)) continue;
|
|
6004
6065
|
seen.add(entry.name);
|
|
6005
|
-
const pluginDir =
|
|
6006
|
-
let indexPath =
|
|
6007
|
-
if (!
|
|
6008
|
-
indexPath =
|
|
6066
|
+
const pluginDir = resolve8(dir, entry.name);
|
|
6067
|
+
let indexPath = resolve8(pluginDir, "index.js");
|
|
6068
|
+
if (!existsSync5(indexPath)) {
|
|
6069
|
+
indexPath = resolve8(pluginDir, "index.ts");
|
|
6009
6070
|
}
|
|
6010
|
-
if (!
|
|
6071
|
+
if (!existsSync5(indexPath)) continue;
|
|
6011
6072
|
try {
|
|
6012
|
-
if (!
|
|
6073
|
+
if (!existsSync5(resolve8(pluginDir, "package.json"))) {
|
|
6013
6074
|
console.warn(`\u26A0\uFE0F Plugin "${entry.name}" has no package.json. Use "xbrowser create ${entry.name} --template static" for proper structure.`);
|
|
6014
6075
|
} else {
|
|
6015
6076
|
const metadata = PluginMetadataParser.parseFromPackageJson(pluginDir);
|
|
@@ -6026,22 +6087,6 @@ var XBrowserPluginLoader = class {
|
|
|
6026
6087
|
}
|
|
6027
6088
|
}
|
|
6028
6089
|
}
|
|
6029
|
-
try {
|
|
6030
|
-
const { default: setupMarketplace } = await import("./marketplace-FPT5YLKB.js");
|
|
6031
|
-
setupMarketplace(this.loader.getAPI());
|
|
6032
|
-
} catch (err) {
|
|
6033
|
-
if (process.env.XBROWSER_DEBUG) {
|
|
6034
|
-
console.warn(`\u26A0\uFE0F Built-in marketplace plugin load failed: ${err instanceof Error ? err.message : String(err)}`);
|
|
6035
|
-
}
|
|
6036
|
-
}
|
|
6037
|
-
try {
|
|
6038
|
-
const { default: setupAdmin } = await import("./admin-MDGF4CET.js");
|
|
6039
|
-
setupAdmin(this.loader.getAPI());
|
|
6040
|
-
} catch (err) {
|
|
6041
|
-
if (process.env.XBROWSER_DEBUG) {
|
|
6042
|
-
console.warn(`\u26A0\uFE0F Built-in admin plugin load failed: ${err instanceof Error ? err.message : String(err)}`);
|
|
6043
|
-
}
|
|
6044
|
-
}
|
|
6045
6090
|
return loaded;
|
|
6046
6091
|
}
|
|
6047
6092
|
async unload() {
|
|
@@ -6442,7 +6487,7 @@ var TipsManager = class {
|
|
|
6442
6487
|
}
|
|
6443
6488
|
}
|
|
6444
6489
|
debounce() {
|
|
6445
|
-
return new Promise((
|
|
6490
|
+
return new Promise((resolve16) => setTimeout(resolve16, DEBOUNCE_MS));
|
|
6446
6491
|
}
|
|
6447
6492
|
formatTips(tips) {
|
|
6448
6493
|
return tips.map((tip) => {
|
|
@@ -6469,6 +6514,24 @@ function getTipsManager() {
|
|
|
6469
6514
|
return globalTipsManager;
|
|
6470
6515
|
}
|
|
6471
6516
|
|
|
6517
|
+
// src/hooks/loader.ts
|
|
6518
|
+
var builtinHooks = {
|
|
6519
|
+
screenshot: () => import("./screenshot-CWAWMXVA.js").then((m) => m.screenshotHook)
|
|
6520
|
+
};
|
|
6521
|
+
async function loadHooks() {
|
|
6522
|
+
const names = process.env.XBROWSER_HOOKS;
|
|
6523
|
+
if (!names) return [];
|
|
6524
|
+
const hooks = [];
|
|
6525
|
+
for (const name of names.split(",")) {
|
|
6526
|
+
const trimmed = name.trim();
|
|
6527
|
+
const factory = builtinHooks[trimmed];
|
|
6528
|
+
if (factory) {
|
|
6529
|
+
hooks.push(await factory());
|
|
6530
|
+
}
|
|
6531
|
+
}
|
|
6532
|
+
return hooks;
|
|
6533
|
+
}
|
|
6534
|
+
|
|
6472
6535
|
// src/executor.ts
|
|
6473
6536
|
import { homedir as homedir3 } from "os";
|
|
6474
6537
|
import { join as join3 } from "path";
|
|
@@ -6631,9 +6694,22 @@ async function executeCommand(commandName, params, sessionName = "default", extr
|
|
|
6631
6694
|
}
|
|
6632
6695
|
}
|
|
6633
6696
|
try {
|
|
6697
|
+
const hooks = await loadHooks();
|
|
6698
|
+
if (hooks.length > 0 && session?.page) {
|
|
6699
|
+
await Promise.all(hooks.map((h) => h.onBeforeCommand?.({ page: session.page, command: commandName, params })));
|
|
6700
|
+
}
|
|
6634
6701
|
const raw = await command.handler(params, ctx);
|
|
6635
6702
|
const end = Date.now();
|
|
6636
6703
|
const duration = end - start;
|
|
6704
|
+
let hookOutputs;
|
|
6705
|
+
if (hooks.length > 0 && session?.page) {
|
|
6706
|
+
const outputs = [];
|
|
6707
|
+
for (const h of hooks) {
|
|
6708
|
+
const output = await h.onAfterCommand?.({ page: session.page, command: commandName, params, result: raw, duration });
|
|
6709
|
+
if (output) outputs.push({ _hook: h.name, ...output });
|
|
6710
|
+
}
|
|
6711
|
+
if (outputs.length > 0) hookOutputs = outputs;
|
|
6712
|
+
}
|
|
6637
6713
|
if (session && isCommandResult(raw)) {
|
|
6638
6714
|
const resultData = raw.data;
|
|
6639
6715
|
const convUrl = resultData?.conversationUrl;
|
|
@@ -6681,9 +6757,9 @@ async function executeCommand(commandName, params, sessionName = "default", extr
|
|
|
6681
6757
|
timestamp: start
|
|
6682
6758
|
});
|
|
6683
6759
|
if (isSuccess) {
|
|
6684
|
-
return { ...ok25(raw.data, merged.length > 0 ? merged : raw.tips), duration };
|
|
6760
|
+
return { ...ok25(raw.data, merged.length > 0 ? merged : raw.tips), duration, ...hookOutputs ? { hookOutputs } : {} };
|
|
6685
6761
|
}
|
|
6686
|
-
return { success: false, data: raw.data, message: raw.message, tips: merged.length > 0 ? merged : raw.tips || [], duration };
|
|
6762
|
+
return { success: false, data: raw.data, message: raw.message, tips: merged.length > 0 ? merged : raw.tips || [], duration, ...hookOutputs ? { hookOutputs } : {} };
|
|
6687
6763
|
}
|
|
6688
6764
|
recordArchive(session?.id, sessionName, {
|
|
6689
6765
|
step: 0,
|
|
@@ -6694,7 +6770,7 @@ async function executeCommand(commandName, params, sessionName = "default", extr
|
|
|
6694
6770
|
duration,
|
|
6695
6771
|
timestamp: start
|
|
6696
6772
|
});
|
|
6697
|
-
return { ...ok25(raw, smartTips), duration };
|
|
6773
|
+
return { ...ok25(raw, smartTips), duration, ...hookOutputs ? { hookOutputs } : {} };
|
|
6698
6774
|
} catch (err) {
|
|
6699
6775
|
const end = Date.now();
|
|
6700
6776
|
const duration = end - start;
|
|
@@ -6965,7 +7041,7 @@ function attachWaitForHuman(ctx, getOrCreateWSServer) {
|
|
|
6965
7041
|
if (!ctx.page) {
|
|
6966
7042
|
throw new Error("waitForHuman requires an active page");
|
|
6967
7043
|
}
|
|
6968
|
-
const { HumanInteractionManager: HumanInteractionManager2 } = await import("./human-interaction-
|
|
7044
|
+
const { HumanInteractionManager: HumanInteractionManager2 } = await import("./human-interaction-W753RVJB.js");
|
|
6969
7045
|
const wsServer2 = await getOrCreateWSServer(ctx.browserContext);
|
|
6970
7046
|
const manager = new HumanInteractionManager2(wsServer2, ctx.page);
|
|
6971
7047
|
return manager.waitForHuman(options);
|
|
@@ -7209,21 +7285,21 @@ var configBuiltin = {
|
|
|
7209
7285
|
|
|
7210
7286
|
// src/plugin/installer.ts
|
|
7211
7287
|
import {
|
|
7212
|
-
existsSync as
|
|
7288
|
+
existsSync as existsSync12,
|
|
7213
7289
|
readdirSync as readdirSync3,
|
|
7214
7290
|
mkdirSync as mkdirSync7,
|
|
7215
7291
|
rmSync as rmSync7
|
|
7216
7292
|
} from "fs";
|
|
7217
|
-
import { resolve as
|
|
7293
|
+
import { resolve as resolve15, basename as basename2 } from "path";
|
|
7218
7294
|
import { homedir as homedir4 } from "os";
|
|
7219
7295
|
|
|
7220
7296
|
// src/plugin/install-sources/local.ts
|
|
7221
|
-
import { existsSync as
|
|
7222
|
-
import { resolve as
|
|
7297
|
+
import { existsSync as existsSync7, cpSync as cpSync2, rmSync as rmSync2 } from "fs";
|
|
7298
|
+
import { resolve as resolve10 } from "path";
|
|
7223
7299
|
|
|
7224
7300
|
// src/plugin/install-utils.ts
|
|
7225
7301
|
import {
|
|
7226
|
-
existsSync as
|
|
7302
|
+
existsSync as existsSync6,
|
|
7227
7303
|
readdirSync as readdirSync2,
|
|
7228
7304
|
cpSync,
|
|
7229
7305
|
rmSync,
|
|
@@ -7231,10 +7307,56 @@ import {
|
|
|
7231
7307
|
readFileSync as readFileSync9,
|
|
7232
7308
|
createWriteStream
|
|
7233
7309
|
} from "fs";
|
|
7234
|
-
import { resolve as
|
|
7310
|
+
import { resolve as resolve9 } from "path";
|
|
7235
7311
|
import { execSync as execSync7 } from "child_process";
|
|
7236
7312
|
import { pipeline } from "stream/promises";
|
|
7237
7313
|
import { Readable } from "stream";
|
|
7314
|
+
|
|
7315
|
+
// src/utils/proxy-fetch.ts
|
|
7316
|
+
var patched = false;
|
|
7317
|
+
async function ensureProxyFetch() {
|
|
7318
|
+
if (patched) return;
|
|
7319
|
+
patched = true;
|
|
7320
|
+
if (process.env.https_proxy && !process.env.HTTPS_PROXY) {
|
|
7321
|
+
process.env.HTTPS_PROXY = process.env.https_proxy;
|
|
7322
|
+
}
|
|
7323
|
+
if (process.env.http_proxy && !process.env.HTTP_PROXY) {
|
|
7324
|
+
process.env.HTTP_PROXY = process.env.http_proxy;
|
|
7325
|
+
}
|
|
7326
|
+
if (process.env.all_proxy && !process.env.ALL_PROXY) {
|
|
7327
|
+
process.env.ALL_PROXY = process.env.all_proxy;
|
|
7328
|
+
}
|
|
7329
|
+
const proxyUrl = process.env.https_proxy || process.env.HTTPS_PROXY || process.env.http_proxy || process.env.HTTP_PROXY || process.env.all_proxy || process.env.ALL_PROXY;
|
|
7330
|
+
if (!proxyUrl) return;
|
|
7331
|
+
try {
|
|
7332
|
+
const undici = await import("undici");
|
|
7333
|
+
const EnvHttpProxyAgent = undici.EnvHttpProxyAgent;
|
|
7334
|
+
const uFetch = undici.fetch;
|
|
7335
|
+
const UFormData = undici.FormData;
|
|
7336
|
+
if (EnvHttpProxyAgent && uFetch && UFormData) {
|
|
7337
|
+
const agent = new EnvHttpProxyAgent();
|
|
7338
|
+
globalThis.fetch = ((input, init) => {
|
|
7339
|
+
const url = typeof input === "string" ? input : input instanceof URL ? input.href : input.url;
|
|
7340
|
+
const body = init?.body;
|
|
7341
|
+
if (body instanceof globalThis.FormData && !(body instanceof UFormData)) {
|
|
7342
|
+
const ufd = new UFormData();
|
|
7343
|
+
body.forEach((value, key) => {
|
|
7344
|
+
if (value instanceof Blob) {
|
|
7345
|
+
ufd.append(key, value, value.name || "file");
|
|
7346
|
+
} else {
|
|
7347
|
+
ufd.append(key, value);
|
|
7348
|
+
}
|
|
7349
|
+
});
|
|
7350
|
+
return uFetch(url, { ...init, body: ufd, dispatcher: agent });
|
|
7351
|
+
}
|
|
7352
|
+
return uFetch(url, { ...init, dispatcher: agent });
|
|
7353
|
+
});
|
|
7354
|
+
}
|
|
7355
|
+
} catch {
|
|
7356
|
+
}
|
|
7357
|
+
}
|
|
7358
|
+
|
|
7359
|
+
// src/plugin/install-utils.ts
|
|
7238
7360
|
async function downloadToFile(url, destPath) {
|
|
7239
7361
|
await ensureProxyFetch();
|
|
7240
7362
|
if (url.startsWith("file://")) {
|
|
@@ -7261,11 +7383,11 @@ function flattenPackageRoot(targetDir) {
|
|
|
7261
7383
|
const dirs = entries.filter((e) => e.isDirectory());
|
|
7262
7384
|
const files = entries.filter((e) => !e.isDirectory());
|
|
7263
7385
|
if (dirs.length === 1 && files.length === 0) {
|
|
7264
|
-
const pkgDir =
|
|
7386
|
+
const pkgDir = resolve9(targetDir, dirs[0].name);
|
|
7265
7387
|
const items = readdirSync2(pkgDir);
|
|
7266
7388
|
for (const item of items) {
|
|
7267
|
-
const src =
|
|
7268
|
-
const dst =
|
|
7389
|
+
const src = resolve9(pkgDir, item);
|
|
7390
|
+
const dst = resolve9(targetDir, item);
|
|
7269
7391
|
cpSync(src, dst, { recursive: true, force: true });
|
|
7270
7392
|
}
|
|
7271
7393
|
rmSync(pkgDir, { recursive: true, force: true });
|
|
@@ -7273,15 +7395,15 @@ function flattenPackageRoot(targetDir) {
|
|
|
7273
7395
|
}
|
|
7274
7396
|
async function verifyPlugin(dir) {
|
|
7275
7397
|
const warnings = [];
|
|
7276
|
-
const indexPath =
|
|
7277
|
-
if (!
|
|
7278
|
-
const indexJs =
|
|
7279
|
-
if (!
|
|
7398
|
+
const indexPath = resolve9(dir, "index.ts");
|
|
7399
|
+
if (!existsSync6(indexPath)) {
|
|
7400
|
+
const indexJs = resolve9(dir, "index.js");
|
|
7401
|
+
if (!existsSync6(indexJs)) {
|
|
7280
7402
|
return { valid: false, error: "No index.ts or index.js entry point found", warnings };
|
|
7281
7403
|
}
|
|
7282
7404
|
}
|
|
7283
|
-
const pkgPath =
|
|
7284
|
-
if (!
|
|
7405
|
+
const pkgPath = resolve9(dir, "package.json");
|
|
7406
|
+
if (!existsSync6(pkgPath)) {
|
|
7285
7407
|
warnings.push("No package.json found");
|
|
7286
7408
|
} else {
|
|
7287
7409
|
try {
|
|
@@ -7304,8 +7426,8 @@ function safeCleanup(dir) {
|
|
|
7304
7426
|
|
|
7305
7427
|
// src/plugin/install-sources/local.ts
|
|
7306
7428
|
async function installFromLocal(source, name, targetDir) {
|
|
7307
|
-
const srcPath =
|
|
7308
|
-
if (!
|
|
7429
|
+
const srcPath = resolve10(source);
|
|
7430
|
+
if (!existsSync7(srcPath)) {
|
|
7309
7431
|
throw new Error(`Local path does not exist: ${srcPath}`);
|
|
7310
7432
|
}
|
|
7311
7433
|
const tmpTarget = `${targetDir}-tmp-${Date.now()}`;
|
|
@@ -7318,7 +7440,7 @@ async function installFromLocal(source, name, targetDir) {
|
|
|
7318
7440
|
safeCleanup(tmpTarget);
|
|
7319
7441
|
throw new Error(`Invalid plugin: ${verify.error}`);
|
|
7320
7442
|
}
|
|
7321
|
-
if (
|
|
7443
|
+
if (existsSync7(targetDir)) {
|
|
7322
7444
|
rmSync2(targetDir, { recursive: true, force: true });
|
|
7323
7445
|
}
|
|
7324
7446
|
cpSync2(tmpTarget, targetDir, { recursive: true, force: true });
|
|
@@ -7338,8 +7460,8 @@ async function installFromLocal(source, name, targetDir) {
|
|
|
7338
7460
|
}
|
|
7339
7461
|
|
|
7340
7462
|
// src/plugin/install-sources/npm.ts
|
|
7341
|
-
import { existsSync as
|
|
7342
|
-
import { resolve as
|
|
7463
|
+
import { existsSync as existsSync8, mkdirSync as mkdirSync4, readFileSync as readFileSync10, writeFileSync as writeFileSync4, rmSync as rmSync3, cpSync as cpSync3 } from "fs";
|
|
7464
|
+
import { resolve as resolve11, join as join4 } from "path";
|
|
7343
7465
|
import { tmpdir } from "os";
|
|
7344
7466
|
async function installFromNpm(packageName, name, targetDir) {
|
|
7345
7467
|
await ensureProxyFetch();
|
|
@@ -7372,12 +7494,12 @@ async function installFromNpm(packageName, name, targetDir) {
|
|
|
7372
7494
|
if (!verify.valid) {
|
|
7373
7495
|
throw new Error(`Invalid npm plugin: ${verify.error}`);
|
|
7374
7496
|
}
|
|
7375
|
-
if (
|
|
7497
|
+
if (existsSync8(targetDir)) {
|
|
7376
7498
|
rmSync3(targetDir, { recursive: true, force: true });
|
|
7377
7499
|
}
|
|
7378
7500
|
cpSync3(extractDir, targetDir, { recursive: true, force: true });
|
|
7379
|
-
const pkgPath =
|
|
7380
|
-
if (
|
|
7501
|
+
const pkgPath = resolve11(targetDir, "package.json");
|
|
7502
|
+
if (existsSync8(pkgPath)) {
|
|
7381
7503
|
const pkg2 = JSON.parse(readFileSync10(pkgPath, "utf-8"));
|
|
7382
7504
|
if (!pkg2._npmSource) {
|
|
7383
7505
|
pkg2._npmSource = { name: packageName, version: latestVersion };
|
|
@@ -7398,8 +7520,8 @@ async function installFromNpm(packageName, name, targetDir) {
|
|
|
7398
7520
|
}
|
|
7399
7521
|
|
|
7400
7522
|
// src/plugin/install-sources/git.ts
|
|
7401
|
-
import { existsSync as
|
|
7402
|
-
import { resolve as
|
|
7523
|
+
import { existsSync as existsSync9, readFileSync as readFileSync11, writeFileSync as writeFileSync5, rmSync as rmSync4, cpSync as cpSync4 } from "fs";
|
|
7524
|
+
import { resolve as resolve12, join as join5 } from "path";
|
|
7403
7525
|
import { tmpdir as tmpdir2 } from "os";
|
|
7404
7526
|
import { execSync as execSync8 } from "child_process";
|
|
7405
7527
|
async function installFromGit(gitUrl, name, targetDir) {
|
|
@@ -7412,13 +7534,13 @@ async function installFromGit(gitUrl, name, targetDir) {
|
|
|
7412
7534
|
if (!verify.valid) {
|
|
7413
7535
|
throw new Error(`Invalid git plugin: ${verify.error}`);
|
|
7414
7536
|
}
|
|
7415
|
-
if (
|
|
7537
|
+
if (existsSync9(targetDir)) {
|
|
7416
7538
|
rmSync4(targetDir, { recursive: true, force: true });
|
|
7417
7539
|
}
|
|
7418
7540
|
cpSync4(tmpDir, targetDir, { recursive: true, force: true });
|
|
7419
|
-
rmSync4(
|
|
7420
|
-
const pkgPath =
|
|
7421
|
-
if (
|
|
7541
|
+
rmSync4(resolve12(targetDir, ".git"), { recursive: true, force: true });
|
|
7542
|
+
const pkgPath = resolve12(targetDir, "package.json");
|
|
7543
|
+
if (existsSync9(pkgPath)) {
|
|
7422
7544
|
const pkg2 = JSON.parse(readFileSync11(pkgPath, "utf-8"));
|
|
7423
7545
|
if (!pkg2._gitSource) {
|
|
7424
7546
|
pkg2._gitSource = { url: gitUrl };
|
|
@@ -7439,8 +7561,8 @@ async function installFromGit(gitUrl, name, targetDir) {
|
|
|
7439
7561
|
}
|
|
7440
7562
|
|
|
7441
7563
|
// src/plugin/install-sources/url.ts
|
|
7442
|
-
import { existsSync as
|
|
7443
|
-
import { resolve as
|
|
7564
|
+
import { existsSync as existsSync10, readFileSync as readFileSync12, writeFileSync as writeFileSync6, mkdirSync as mkdirSync5, rmSync as rmSync5, cpSync as cpSync5 } from "fs";
|
|
7565
|
+
import { resolve as resolve13, join as join6, basename } from "path";
|
|
7444
7566
|
import { tmpdir as tmpdir3 } from "os";
|
|
7445
7567
|
async function installFromUrl(url, name, targetDir) {
|
|
7446
7568
|
const tmpDir = join6(tmpdir3(), `xbrowser-url-${Date.now()}`);
|
|
@@ -7458,12 +7580,12 @@ async function installFromUrl(url, name, targetDir) {
|
|
|
7458
7580
|
if (!verify.valid) {
|
|
7459
7581
|
throw new Error(`Invalid plugin from URL: ${verify.error}`);
|
|
7460
7582
|
}
|
|
7461
|
-
if (
|
|
7583
|
+
if (existsSync10(targetDir)) {
|
|
7462
7584
|
rmSync5(targetDir, { recursive: true, force: true });
|
|
7463
7585
|
}
|
|
7464
7586
|
cpSync5(extractDir, targetDir, { recursive: true, force: true });
|
|
7465
|
-
const pkgPath =
|
|
7466
|
-
if (
|
|
7587
|
+
const pkgPath = resolve13(targetDir, "package.json");
|
|
7588
|
+
if (existsSync10(pkgPath)) {
|
|
7467
7589
|
const pkg2 = JSON.parse(readFileSync12(pkgPath, "utf-8"));
|
|
7468
7590
|
if (!pkg2._urlSource) {
|
|
7469
7591
|
pkg2._urlSource = { url };
|
|
@@ -7485,14 +7607,14 @@ async function installFromUrl(url, name, targetDir) {
|
|
|
7485
7607
|
|
|
7486
7608
|
// src/plugin/install-sources/marketplace.ts
|
|
7487
7609
|
import {
|
|
7488
|
-
existsSync as
|
|
7610
|
+
existsSync as existsSync11,
|
|
7489
7611
|
mkdirSync as mkdirSync6,
|
|
7490
7612
|
writeFileSync as writeFileSync7,
|
|
7491
7613
|
readFileSync as readFileSync13,
|
|
7492
7614
|
rmSync as rmSync6,
|
|
7493
7615
|
cpSync as cpSync6
|
|
7494
7616
|
} from "fs";
|
|
7495
|
-
import { resolve as
|
|
7617
|
+
import { resolve as resolve14, join as join7, dirname as dirname2 } from "path";
|
|
7496
7618
|
import { tmpdir as tmpdir4 } from "os";
|
|
7497
7619
|
import { gunzipSync } from "zlib";
|
|
7498
7620
|
async function installFromMarketplace(pluginsDir, slug, options) {
|
|
@@ -7509,8 +7631,8 @@ async function installFromMarketplace(pluginsDir, slug, options) {
|
|
|
7509
7631
|
}
|
|
7510
7632
|
const plugin = detailData.data;
|
|
7511
7633
|
const name = options?.name || String(plugin.slug || slug);
|
|
7512
|
-
const targetDir =
|
|
7513
|
-
if (
|
|
7634
|
+
const targetDir = resolve14(pluginsDir, name);
|
|
7635
|
+
if (existsSync11(targetDir) && !options?.force) {
|
|
7514
7636
|
throw new Error(`Plugin "${name}" already exists. Use --force to overwrite.`);
|
|
7515
7637
|
}
|
|
7516
7638
|
mkdirSync6(targetDir, { recursive: true });
|
|
@@ -7545,12 +7667,12 @@ function isManifestArray(data) {
|
|
|
7545
7667
|
return Array.isArray(data) && data.length > 0 && typeof data[0].path === "string" && typeof data[0].content === "string";
|
|
7546
7668
|
}
|
|
7547
7669
|
function extractManifestToDir(manifest, targetDir) {
|
|
7548
|
-
if (
|
|
7670
|
+
if (existsSync11(targetDir)) {
|
|
7549
7671
|
rmSync6(targetDir, { recursive: true, force: true });
|
|
7550
7672
|
}
|
|
7551
7673
|
mkdirSync6(targetDir, { recursive: true });
|
|
7552
7674
|
for (const file of manifest) {
|
|
7553
|
-
const filePath =
|
|
7675
|
+
const filePath = resolve14(targetDir, file.path);
|
|
7554
7676
|
mkdirSync6(dirname2(filePath), { recursive: true });
|
|
7555
7677
|
writeFileSync7(filePath, Buffer.from(file.content, "base64"));
|
|
7556
7678
|
}
|
|
@@ -7588,7 +7710,7 @@ async function downloadAndExtractMarketplaceTarball(baseUrl, slug, tmpDir, targe
|
|
|
7588
7710
|
const extractDir = join7(tmpDir, "extracted");
|
|
7589
7711
|
extractTarGz(tarballPath, extractDir);
|
|
7590
7712
|
flattenPackageRoot(extractDir);
|
|
7591
|
-
if (
|
|
7713
|
+
if (existsSync11(targetDir)) {
|
|
7592
7714
|
rmSync6(targetDir, { recursive: true, force: true });
|
|
7593
7715
|
}
|
|
7594
7716
|
cpSync6(extractDir, targetDir, { recursive: true, force: true });
|
|
@@ -7605,7 +7727,7 @@ async function downloadAndExtractMarketplaceTarball(baseUrl, slug, tmpDir, targe
|
|
|
7605
7727
|
const extractDir = join7(tmpDir, "extracted");
|
|
7606
7728
|
extractTarGz(tarballPath, extractDir);
|
|
7607
7729
|
flattenPackageRoot(extractDir);
|
|
7608
|
-
if (
|
|
7730
|
+
if (existsSync11(targetDir)) {
|
|
7609
7731
|
rmSync6(targetDir, { recursive: true, force: true });
|
|
7610
7732
|
}
|
|
7611
7733
|
cpSync6(extractDir, targetDir, { recursive: true, force: true });
|
|
@@ -7640,8 +7762,8 @@ function writeMarketplacePackageJson(plugin, slug, name, baseUrl, targetDir) {
|
|
|
7640
7762
|
url: baseUrl
|
|
7641
7763
|
}
|
|
7642
7764
|
};
|
|
7643
|
-
const pkgPath =
|
|
7644
|
-
if (!
|
|
7765
|
+
const pkgPath = resolve14(targetDir, "package.json");
|
|
7766
|
+
if (!existsSync11(pkgPath)) {
|
|
7645
7767
|
writeFileSync7(pkgPath, JSON.stringify(packageJson, null, 2));
|
|
7646
7768
|
} else {
|
|
7647
7769
|
try {
|
|
@@ -7658,7 +7780,7 @@ function writeMarketplacePackageJson(plugin, slug, name, baseUrl, targetDir) {
|
|
|
7658
7780
|
}
|
|
7659
7781
|
}
|
|
7660
7782
|
function ensureIndexFile(plugin, name, targetDir) {
|
|
7661
|
-
if (!
|
|
7783
|
+
if (!existsSync11(resolve14(targetDir, "index.ts")) && !existsSync11(resolve14(targetDir, "index.js"))) {
|
|
7662
7784
|
const commands = plugin.commands || [];
|
|
7663
7785
|
const commandHandlers = commands.length > 0 ? commands.map((cmd) => {
|
|
7664
7786
|
return [
|
|
@@ -7674,7 +7796,7 @@ function ensureIndexFile(plugin, name, targetDir) {
|
|
|
7674
7796
|
` });`
|
|
7675
7797
|
].join("\n");
|
|
7676
7798
|
writeFileSync7(
|
|
7677
|
-
|
|
7799
|
+
resolve14(targetDir, "index.ts"),
|
|
7678
7800
|
[
|
|
7679
7801
|
`import type { XCLIAPI } from '@dyyz1993/xcli-core';`,
|
|
7680
7802
|
``,
|
|
@@ -7695,7 +7817,7 @@ function ensureIndexFile(plugin, name, targetDir) {
|
|
|
7695
7817
|
var PluginInstaller = class {
|
|
7696
7818
|
pluginsDir;
|
|
7697
7819
|
constructor(pluginsDir) {
|
|
7698
|
-
this.pluginsDir = pluginsDir ||
|
|
7820
|
+
this.pluginsDir = pluginsDir || resolve15(homedir4(), ".xbrowser/plugins");
|
|
7699
7821
|
}
|
|
7700
7822
|
getPluginsDir() {
|
|
7701
7823
|
return this.pluginsDir;
|
|
@@ -7711,8 +7833,8 @@ var PluginInstaller = class {
|
|
|
7711
7833
|
async install(source, options) {
|
|
7712
7834
|
const type = this.detectSourceType(source);
|
|
7713
7835
|
const name = options?.name || this.deriveName(source, type);
|
|
7714
|
-
const targetDir =
|
|
7715
|
-
if (
|
|
7836
|
+
const targetDir = resolve15(this.pluginsDir, name);
|
|
7837
|
+
if (existsSync12(targetDir) && !options?.force) {
|
|
7716
7838
|
throw new Error(`Plugin "${name}" already exists. Use --force to overwrite.`);
|
|
7717
7839
|
}
|
|
7718
7840
|
mkdirSync7(targetDir, { recursive: true });
|
|
@@ -7772,8 +7894,8 @@ var PluginInstaller = class {
|
|
|
7772
7894
|
* @throws If the plugin is not installed.
|
|
7773
7895
|
*/
|
|
7774
7896
|
async uninstall(name) {
|
|
7775
|
-
const targetDir =
|
|
7776
|
-
if (!
|
|
7897
|
+
const targetDir = resolve15(this.pluginsDir, name);
|
|
7898
|
+
if (!existsSync12(targetDir)) {
|
|
7777
7899
|
throw new Error(`Plugin "${name}" not found`);
|
|
7778
7900
|
}
|
|
7779
7901
|
rmSync7(targetDir, { recursive: true, force: true });
|
|
@@ -7784,18 +7906,18 @@ var PluginInstaller = class {
|
|
|
7784
7906
|
* @returns Array of installed plugin information.
|
|
7785
7907
|
*/
|
|
7786
7908
|
async list(_options) {
|
|
7787
|
-
if (!
|
|
7909
|
+
if (!existsSync12(this.pluginsDir)) return [];
|
|
7788
7910
|
const entries = readdirSync3(this.pluginsDir, { withFileTypes: true });
|
|
7789
7911
|
const plugins = [];
|
|
7790
7912
|
for (const entry of entries) {
|
|
7791
7913
|
if (!entry.isDirectory()) continue;
|
|
7792
|
-
const pluginPath =
|
|
7793
|
-
const indexPath =
|
|
7794
|
-
const indexJsPath =
|
|
7795
|
-
if (!
|
|
7914
|
+
const pluginPath = resolve15(this.pluginsDir, entry.name);
|
|
7915
|
+
const indexPath = resolve15(pluginPath, "index.ts");
|
|
7916
|
+
const indexJsPath = resolve15(pluginPath, "index.js");
|
|
7917
|
+
if (!existsSync12(indexPath) && !existsSync12(indexJsPath)) continue;
|
|
7796
7918
|
const metadata = PluginMetadataParser.parseFromPackageJson(pluginPath);
|
|
7797
7919
|
let source = "local";
|
|
7798
|
-
const pkg2 = readJsonFile(
|
|
7920
|
+
const pkg2 = readJsonFile(resolve15(pluginPath, "package.json"), {});
|
|
7799
7921
|
if (pkg2._marketplace) source = "marketplace";
|
|
7800
7922
|
else if (pkg2._npmSource) source = "npm";
|
|
7801
7923
|
else if (pkg2._gitSource) source = "git";
|
|
@@ -7819,10 +7941,10 @@ var PluginInstaller = class {
|
|
|
7819
7941
|
}
|
|
7820
7942
|
if (source.startsWith("file://")) {
|
|
7821
7943
|
const filePath = decodeURIComponent(new URL(source).pathname);
|
|
7822
|
-
if (
|
|
7944
|
+
if (existsSync12(filePath)) return "url";
|
|
7823
7945
|
}
|
|
7824
7946
|
if (source.endsWith(".git") || source.includes("github.com/")) return "git";
|
|
7825
|
-
if (
|
|
7947
|
+
if (existsSync12(resolve15(source))) return "local";
|
|
7826
7948
|
return "npm";
|
|
7827
7949
|
}
|
|
7828
7950
|
deriveName(source, type) {
|
|
@@ -7898,10 +8020,6 @@ function handlePluginHelp() {
|
|
|
7898
8020
|
" uninstall <name> Uninstall a plugin",
|
|
7899
8021
|
" list [--json] List installed plugins",
|
|
7900
8022
|
" reload <name> Reload a plugin",
|
|
7901
|
-
" publish [--registry <url>] [--dry-run] Publish plugin to marketplace",
|
|
7902
|
-
" login [--token <api-key>] [--registry <url>] Login to marketplace",
|
|
7903
|
-
" whoami Show current logged-in user",
|
|
7904
|
-
" logout Logout from marketplace",
|
|
7905
8023
|
"",
|
|
7906
8024
|
"Examples:",
|
|
7907
8025
|
" xbrowser plugin search scraper",
|
|
@@ -7909,12 +8027,7 @@ function handlePluginHelp() {
|
|
|
7909
8027
|
" xbrowser plugin install ./my-plugin",
|
|
7910
8028
|
" xbrowser plugin uninstall my-plugin",
|
|
7911
8029
|
" xbrowser plugin list",
|
|
7912
|
-
" xbrowser plugin reload my-plugin"
|
|
7913
|
-
" xbrowser plugin publish",
|
|
7914
|
-
" xbrowser plugin publish --dry-run",
|
|
7915
|
-
" xbrowser plugin login --token my-api-key",
|
|
7916
|
-
" xbrowser plugin whoami",
|
|
7917
|
-
" xbrowser plugin logout"
|
|
8030
|
+
" xbrowser plugin reload my-plugin"
|
|
7918
8031
|
].join("\n");
|
|
7919
8032
|
}
|
|
7920
8033
|
var pluginInstallBuiltin = {
|
|
@@ -8216,76 +8329,60 @@ var NPMSearcher = class {
|
|
|
8216
8329
|
}
|
|
8217
8330
|
};
|
|
8218
8331
|
|
|
8219
|
-
// src/plugin
|
|
8220
|
-
|
|
8221
|
-
|
|
8222
|
-
|
|
8223
|
-
|
|
8224
|
-
|
|
8225
|
-
|
|
8226
|
-
|
|
8227
|
-
const
|
|
8228
|
-
|
|
8229
|
-
|
|
8230
|
-
|
|
8231
|
-
|
|
8232
|
-
|
|
8233
|
-
|
|
8234
|
-
|
|
8235
|
-
|
|
8236
|
-
|
|
8237
|
-
|
|
8238
|
-
}
|
|
8239
|
-
const data = await response.json();
|
|
8240
|
-
if (!data.success || !data.data?.items) {
|
|
8241
|
-
return [];
|
|
8242
|
-
}
|
|
8243
|
-
return data.data.items.map((item) => this.parseMarketplacePlugin(item));
|
|
8244
|
-
} catch {
|
|
8245
|
-
return [];
|
|
8246
|
-
}
|
|
8247
|
-
}
|
|
8248
|
-
static async getPluginDetail(slug) {
|
|
8249
|
-
await ensureProxyFetch();
|
|
8250
|
-
const baseUrl = this.getBaseUrl();
|
|
8251
|
-
const url = `${baseUrl}/api/plugins/${slug}`;
|
|
8252
|
-
try {
|
|
8253
|
-
const response = await fetch(url);
|
|
8254
|
-
if (!response.ok) return null;
|
|
8255
|
-
const data = await response.json();
|
|
8256
|
-
if (!data.success || !data.data) return null;
|
|
8257
|
-
return this.parseMarketplacePlugin(data.data);
|
|
8258
|
-
} catch {
|
|
8259
|
-
return null;
|
|
8260
|
-
}
|
|
8261
|
-
}
|
|
8262
|
-
static parseMarketplacePlugin(item) {
|
|
8263
|
-
return {
|
|
8332
|
+
// src/builtins/plugin-search.ts
|
|
8333
|
+
async function searchFromMarketplacePlugin(options, loader) {
|
|
8334
|
+
const sites = loader.getCore().loader.getSites();
|
|
8335
|
+
const marketplaceSite = sites.find((s) => s.name === "marketplace");
|
|
8336
|
+
if (!marketplaceSite) return [];
|
|
8337
|
+
const searchCmd = marketplaceSite.getCommand("search");
|
|
8338
|
+
if (!searchCmd) return [];
|
|
8339
|
+
try {
|
|
8340
|
+
const result = await searchCmd.handler(
|
|
8341
|
+
{
|
|
8342
|
+
query: options.query,
|
|
8343
|
+
tag: options.tag,
|
|
8344
|
+
site: options.site,
|
|
8345
|
+
limit: options.limit
|
|
8346
|
+
},
|
|
8347
|
+
{}
|
|
8348
|
+
);
|
|
8349
|
+
const items = extractItems(result);
|
|
8350
|
+
return items.map((item) => ({
|
|
8264
8351
|
source: "marketplace",
|
|
8265
|
-
slug: String(item.slug || ""),
|
|
8266
8352
|
name: String(item.name || ""),
|
|
8267
8353
|
version: String(item.version || "latest"),
|
|
8268
8354
|
description: String(item.description || ""),
|
|
8269
|
-
author: String(item.
|
|
8270
|
-
homepage: typeof item.
|
|
8271
|
-
repository: typeof item.repositoryUrl === "string" ? item.repositoryUrl : void 0,
|
|
8272
|
-
keywords: Array.isArray(item.tags) ? item.tags.map(String) : [],
|
|
8355
|
+
author: String(item.author || ""),
|
|
8356
|
+
homepage: typeof item.homepage === "string" ? item.homepage : void 0,
|
|
8273
8357
|
tags: Array.isArray(item.tags) ? item.tags.map(String) : [],
|
|
8274
|
-
|
|
8275
|
-
|
|
8276
|
-
|
|
8277
|
-
|
|
8278
|
-
|
|
8358
|
+
downloads: typeof item.downloads === "number" ? item.downloads : 0,
|
|
8359
|
+
slug: String(item.slug || ""),
|
|
8360
|
+
commands: Array.isArray(item.commands) ? item.commands.map(String) : []
|
|
8361
|
+
}));
|
|
8362
|
+
} catch {
|
|
8363
|
+
return [];
|
|
8279
8364
|
}
|
|
8280
|
-
}
|
|
8281
|
-
|
|
8282
|
-
|
|
8365
|
+
}
|
|
8366
|
+
function extractItems(result) {
|
|
8367
|
+
if (!result || typeof result !== "object") return [];
|
|
8368
|
+
const r = result;
|
|
8369
|
+
if ("data" in r) {
|
|
8370
|
+
const data = r.data;
|
|
8371
|
+
if (data && "items" in data && Array.isArray(data.items)) {
|
|
8372
|
+
return data.items;
|
|
8373
|
+
}
|
|
8374
|
+
}
|
|
8375
|
+
if ("items" in r && Array.isArray(r.items)) {
|
|
8376
|
+
return r.items;
|
|
8377
|
+
}
|
|
8378
|
+
return [];
|
|
8379
|
+
}
|
|
8283
8380
|
var pluginSearchBuiltin = {
|
|
8284
8381
|
name: "plugin search",
|
|
8285
8382
|
description: "Search for xbrowser plugins on npm registry and marketplace",
|
|
8286
8383
|
help: {
|
|
8287
8384
|
usage: "xbrowser plugin search <query> [options]",
|
|
8288
|
-
description: "Search npm registry and
|
|
8385
|
+
description: "Search npm registry and installed plugin search providers for xbrowser-compatible plugins",
|
|
8289
8386
|
options: [
|
|
8290
8387
|
{ name: "--tag <tag>", description: "Filter by plugin tag" },
|
|
8291
8388
|
{ name: "--site <site>", description: "Filter by target site" },
|
|
@@ -8307,26 +8404,24 @@ var pluginSearchBuiltin = {
|
|
|
8307
8404
|
limit: options["limit"] ? Number.parseInt(String(options["limit"])) : 20
|
|
8308
8405
|
};
|
|
8309
8406
|
console.log(
|
|
8310
|
-
`Searching
|
|
8407
|
+
`Searching for xbrowser plugins...${query ? ` (query: "${query}")` : ""}`
|
|
8311
8408
|
);
|
|
8312
|
-
const
|
|
8409
|
+
const loader = await getPluginLoader();
|
|
8410
|
+
const [npmSettled, pluginSettled] = await Promise.allSettled([
|
|
8313
8411
|
NPMSearcher.search(searchOptions),
|
|
8314
|
-
|
|
8412
|
+
searchFromMarketplacePlugin(searchOptions, loader)
|
|
8315
8413
|
]);
|
|
8316
8414
|
const npmResults = npmSettled.status === "fulfilled" ? npmSettled.value : [];
|
|
8317
|
-
const
|
|
8415
|
+
const pluginResults = pluginSettled.status === "fulfilled" ? pluginSettled.value : [];
|
|
8318
8416
|
if (npmSettled.status === "rejected") {
|
|
8319
8417
|
console.warn(`Warning: npm search failed: ${npmSettled.reason}`);
|
|
8320
8418
|
}
|
|
8321
|
-
|
|
8322
|
-
console.warn(`Warning: marketplace search failed: ${marketplaceSettled.reason}`);
|
|
8323
|
-
}
|
|
8324
|
-
const total = npmResults.length + marketplaceResults.length;
|
|
8419
|
+
const total = npmResults.length + pluginResults.length;
|
|
8325
8420
|
if (total === 0) {
|
|
8326
8421
|
console.log("No plugins found.");
|
|
8327
8422
|
return;
|
|
8328
8423
|
}
|
|
8329
|
-
console.log(`Found ${total} plugin(s) (npm: ${npmResults.length},
|
|
8424
|
+
console.log(`Found ${total} plugin(s) (npm: ${npmResults.length}, plugins: ${pluginResults.length}):
|
|
8330
8425
|
`);
|
|
8331
8426
|
if (npmResults.length > 0) {
|
|
8332
8427
|
console.log("--- npm ---\n");
|
|
@@ -8350,14 +8445,14 @@ var pluginSearchBuiltin = {
|
|
|
8350
8445
|
console.log("");
|
|
8351
8446
|
});
|
|
8352
8447
|
}
|
|
8353
|
-
if (
|
|
8448
|
+
if (pluginResults.length > 0) {
|
|
8354
8449
|
console.log("--- marketplace ---\n");
|
|
8355
|
-
|
|
8450
|
+
pluginResults.forEach((result, idx) => {
|
|
8356
8451
|
console.log(`${idx + 1}. ${result.name} [marketplace]`);
|
|
8357
8452
|
console.log(` ${result.description}`);
|
|
8358
8453
|
console.log(` Version: ${result.version}`);
|
|
8359
|
-
console.log(` Author: ${result.author}`);
|
|
8360
|
-
console.log(` Downloads: ${result.downloads}`);
|
|
8454
|
+
if (result.author) console.log(` Author: ${result.author}`);
|
|
8455
|
+
if (result.downloads) console.log(` Downloads: ${result.downloads}`);
|
|
8361
8456
|
if (result.tags && result.tags.length > 0) {
|
|
8362
8457
|
console.log(` Tags: ${result.tags.join(", ")}`);
|
|
8363
8458
|
}
|
|
@@ -8367,7 +8462,9 @@ var pluginSearchBuiltin = {
|
|
|
8367
8462
|
if (result.homepage) {
|
|
8368
8463
|
console.log(` Homepage: ${result.homepage}`);
|
|
8369
8464
|
}
|
|
8370
|
-
|
|
8465
|
+
if (result.slug) {
|
|
8466
|
+
console.log(` Install: xbrowser plugin install ${result.slug} --from-marketplace`);
|
|
8467
|
+
}
|
|
8371
8468
|
console.log("");
|
|
8372
8469
|
});
|
|
8373
8470
|
}
|
|
@@ -9253,6 +9350,67 @@ function applyRegistryOverride(options) {
|
|
|
9253
9350
|
process.env.XBROWSER_MARKETPLACE_URL = registry2;
|
|
9254
9351
|
}
|
|
9255
9352
|
}
|
|
9353
|
+
function extractItems2(result) {
|
|
9354
|
+
if (!result || typeof result !== "object") return [];
|
|
9355
|
+
const r = result;
|
|
9356
|
+
if ("data" in r) {
|
|
9357
|
+
const data = r.data;
|
|
9358
|
+
if (data && "items" in data && Array.isArray(data.items)) {
|
|
9359
|
+
return data.items;
|
|
9360
|
+
}
|
|
9361
|
+
}
|
|
9362
|
+
if ("items" in r && Array.isArray(r.items)) {
|
|
9363
|
+
return r.items;
|
|
9364
|
+
}
|
|
9365
|
+
return [];
|
|
9366
|
+
}
|
|
9367
|
+
async function searchFromMarketplacePlugin2(options, loader) {
|
|
9368
|
+
const sites = loader.getCore().loader.getSites();
|
|
9369
|
+
const marketplaceSite = sites.find((s) => s.name === "marketplace");
|
|
9370
|
+
if (!marketplaceSite) return [];
|
|
9371
|
+
const searchCmd = marketplaceSite.getCommand("search");
|
|
9372
|
+
if (!searchCmd) return [];
|
|
9373
|
+
try {
|
|
9374
|
+
const result = await searchCmd.handler(
|
|
9375
|
+
{
|
|
9376
|
+
query: options.query,
|
|
9377
|
+
tag: options.tag,
|
|
9378
|
+
site: options.site,
|
|
9379
|
+
limit: options.limit
|
|
9380
|
+
},
|
|
9381
|
+
{}
|
|
9382
|
+
);
|
|
9383
|
+
const items = extractItems2(result);
|
|
9384
|
+
return items.map((item) => ({ ...item, source: "marketplace" }));
|
|
9385
|
+
} catch {
|
|
9386
|
+
return [];
|
|
9387
|
+
}
|
|
9388
|
+
}
|
|
9389
|
+
async function infoFromMarketplacePlugin(slug, loader) {
|
|
9390
|
+
const sites = loader.getCore().loader.getSites();
|
|
9391
|
+
const marketplaceSite = sites.find((s) => s.name === "marketplace");
|
|
9392
|
+
if (!marketplaceSite) return null;
|
|
9393
|
+
const infoCmd = marketplaceSite.getCommand("info");
|
|
9394
|
+
if (!infoCmd) return null;
|
|
9395
|
+
try {
|
|
9396
|
+
const result = await infoCmd.handler({ slug }, {});
|
|
9397
|
+
if (!result || typeof result !== "object") return null;
|
|
9398
|
+
const r = result;
|
|
9399
|
+
let plugin = null;
|
|
9400
|
+
if ("data" in r) {
|
|
9401
|
+
const data = r.data;
|
|
9402
|
+
plugin = data?.plugin || null;
|
|
9403
|
+
}
|
|
9404
|
+
if (!plugin && "plugin" in r) {
|
|
9405
|
+
plugin = r.plugin;
|
|
9406
|
+
}
|
|
9407
|
+
if (plugin && plugin.name) {
|
|
9408
|
+
return { ...plugin, source: "marketplace" };
|
|
9409
|
+
}
|
|
9410
|
+
} catch {
|
|
9411
|
+
}
|
|
9412
|
+
return null;
|
|
9413
|
+
}
|
|
9256
9414
|
async function handleSearch(args, options, mode) {
|
|
9257
9415
|
const query = args[0] || "";
|
|
9258
9416
|
applyRegistryOverride(options);
|
|
@@ -9260,11 +9418,10 @@ async function handleSearch(args, options, mode) {
|
|
|
9260
9418
|
const searchLimit = options.limit ? Number(options.limit) : 20;
|
|
9261
9419
|
const searchOpts = { query, tag: options.tag, site: options.site, limit: searchLimit };
|
|
9262
9420
|
const results = [];
|
|
9263
|
-
const
|
|
9264
|
-
|
|
9265
|
-
|
|
9266
|
-
|
|
9267
|
-
if (marketplaceResults.length === 0) {
|
|
9421
|
+
const loader = await getPluginLoader();
|
|
9422
|
+
const pluginResults = await searchFromMarketplacePlugin2(searchOpts, loader);
|
|
9423
|
+
results.push(...pluginResults);
|
|
9424
|
+
if (pluginResults.length === 0) {
|
|
9268
9425
|
try {
|
|
9269
9426
|
const npmResults = await NPMSearcher.search(searchOpts);
|
|
9270
9427
|
for (const r of npmResults) {
|
|
@@ -9297,12 +9454,11 @@ async function handlePluginInfo(args, options, mode) {
|
|
|
9297
9454
|
if (!slug) outputError("Usage: xbrowser plugin info <slug>");
|
|
9298
9455
|
applyRegistryOverride(options);
|
|
9299
9456
|
await ensureProxyFetch();
|
|
9300
|
-
const
|
|
9457
|
+
const loader = await getPluginLoader();
|
|
9301
9458
|
try {
|
|
9302
|
-
const
|
|
9303
|
-
if (
|
|
9304
|
-
const
|
|
9305
|
-
const d = raw.data || raw;
|
|
9459
|
+
const pluginInfo = await infoFromMarketplacePlugin(slug, loader);
|
|
9460
|
+
if (pluginInfo) {
|
|
9461
|
+
const d = pluginInfo;
|
|
9306
9462
|
if (mode === "json") {
|
|
9307
9463
|
outputResult({ source: "marketplace", ...d }, mode);
|
|
9308
9464
|
return;
|
|
@@ -9310,12 +9466,11 @@ async function handlePluginInfo(args, options, mode) {
|
|
|
9310
9466
|
console.log(`\u540D\u79F0: ${d.name || ""}`);
|
|
9311
9467
|
console.log(`\u7248\u672C: ${d.version || ""}`);
|
|
9312
9468
|
console.log(`\u63CF\u8FF0: ${d.description || ""}`);
|
|
9313
|
-
console.log(`\u4F5C\u8005: ${d.
|
|
9314
|
-
console.log(`\u72B6\u6001: ${d.status || ""}`);
|
|
9469
|
+
console.log(`\u4F5C\u8005: ${d.author || ""}`);
|
|
9315
9470
|
console.log(`\u547D\u4EE4: ${(d.commands || []).join(", ")}`);
|
|
9316
|
-
console.log(`\u4E0B\u8F7D\u91CF: ${d.
|
|
9471
|
+
console.log(`\u4E0B\u8F7D\u91CF: ${d.downloads || 0}`);
|
|
9317
9472
|
console.log(`\u6807\u7B7E: ${(d.tags || []).join(", ")}`);
|
|
9318
|
-
console.log(`\u7F51\u7AD9: ${(d.
|
|
9473
|
+
console.log(`\u7F51\u7AD9: ${(d.sites || []).join(", ")}`);
|
|
9319
9474
|
return;
|
|
9320
9475
|
}
|
|
9321
9476
|
} catch {
|
|
@@ -10264,24 +10419,6 @@ Commands:
|
|
|
10264
10419
|
viewer [--name <n>] [--selector <sel>] Generate viewer URL
|
|
10265
10420
|
help Show this help
|
|
10266
10421
|
--version, -v Show version
|
|
10267
|
-
|
|
10268
|
-
Marketplace & Admin:
|
|
10269
|
-
marketplace publish [--dry-run] Publish plugin to marketplace
|
|
10270
|
-
marketplace login [--token <key>] Login to marketplace
|
|
10271
|
-
marketplace register Register developer account
|
|
10272
|
-
marketplace whoami Show current user
|
|
10273
|
-
marketplace logout Logout from marketplace
|
|
10274
|
-
admin pending List pending plugins (admin only)
|
|
10275
|
-
admin approve <slug> Approve a plugin (admin only)
|
|
10276
|
-
admin reject <slug> [--reason] Reject a plugin (admin only)
|
|
10277
|
-
admin feature <slug> Toggle featured (admin only)
|
|
10278
|
-
admin remove <slug> Remove a plugin (admin only)
|
|
10279
|
-
admin stats Dashboard stats (admin only)
|
|
10280
|
-
admin inventory Plugin inventory (admin only)
|
|
10281
|
-
admin list [--status <status>] List all plugins (admin only)
|
|
10282
|
-
admin bulk-approve <slugs...> Bulk approve (admin only)
|
|
10283
|
-
admin cleanup Reset data (admin only)
|
|
10284
|
-
|
|
10285
10422
|
Plugin Commands:
|
|
10286
10423
|
Installed plugins provide additional commands.
|
|
10287
10424
|
Use 'xbrowser plugin list' to see installed plugins and their commands.
|
|
@@ -10644,19 +10781,19 @@ function headersToObject(headers) {
|
|
|
10644
10781
|
return result;
|
|
10645
10782
|
}
|
|
10646
10783
|
function readBody(req) {
|
|
10647
|
-
return new Promise((
|
|
10784
|
+
return new Promise((resolve16, reject) => {
|
|
10648
10785
|
const chunks = [];
|
|
10649
10786
|
req.on("data", (chunk) => chunks.push(chunk));
|
|
10650
10787
|
req.on("end", () => {
|
|
10651
10788
|
const raw = Buffer.concat(chunks).toString("utf-8");
|
|
10652
10789
|
if (!raw) {
|
|
10653
|
-
|
|
10790
|
+
resolve16(null);
|
|
10654
10791
|
return;
|
|
10655
10792
|
}
|
|
10656
10793
|
try {
|
|
10657
|
-
|
|
10794
|
+
resolve16(JSON.parse(raw));
|
|
10658
10795
|
} catch {
|
|
10659
|
-
|
|
10796
|
+
resolve16(null);
|
|
10660
10797
|
}
|
|
10661
10798
|
});
|
|
10662
10799
|
req.on("error", reject);
|
|
@@ -10701,7 +10838,7 @@ var HTTPServer = class {
|
|
|
10701
10838
|
res.end(JSON.stringify({ error: "INTERNAL_ERROR", message, statusCode: 500 }));
|
|
10702
10839
|
});
|
|
10703
10840
|
});
|
|
10704
|
-
return new Promise((
|
|
10841
|
+
return new Promise((resolve16, reject) => {
|
|
10705
10842
|
const server = this.server;
|
|
10706
10843
|
server.on("error", (err) => {
|
|
10707
10844
|
this.server = null;
|
|
@@ -10713,7 +10850,7 @@ var HTTPServer = class {
|
|
|
10713
10850
|
this.port = addr.port;
|
|
10714
10851
|
}
|
|
10715
10852
|
console.log(`HTTP server listening on http://${this.host}:${this.port}`);
|
|
10716
|
-
|
|
10853
|
+
resolve16({ port: this.port, host: this.host });
|
|
10717
10854
|
});
|
|
10718
10855
|
});
|
|
10719
10856
|
}
|
|
@@ -10724,13 +10861,13 @@ var HTTPServer = class {
|
|
|
10724
10861
|
*/
|
|
10725
10862
|
async stop() {
|
|
10726
10863
|
if (!this.server) return;
|
|
10727
|
-
return new Promise((
|
|
10864
|
+
return new Promise((resolve16, reject) => {
|
|
10728
10865
|
this.server.close((err) => {
|
|
10729
10866
|
if (err) {
|
|
10730
10867
|
reject(err);
|
|
10731
10868
|
} else {
|
|
10732
10869
|
this.server = null;
|
|
10733
|
-
|
|
10870
|
+
resolve16();
|
|
10734
10871
|
}
|
|
10735
10872
|
});
|
|
10736
10873
|
});
|
|
@@ -12404,8 +12541,8 @@ var WSServer = class extends EventEmitter {
|
|
|
12404
12541
|
case "file_list": {
|
|
12405
12542
|
try {
|
|
12406
12543
|
const { readdirSync: readdirSync5, statSync } = await import("fs");
|
|
12407
|
-
const { join: join11, resolve:
|
|
12408
|
-
const targetPath =
|
|
12544
|
+
const { join: join11, resolve: resolve16 } = await import("path");
|
|
12545
|
+
const targetPath = resolve16(msg.path);
|
|
12409
12546
|
const entries = readdirSync5(targetPath);
|
|
12410
12547
|
const files = entries.map((name) => {
|
|
12411
12548
|
try {
|
|
@@ -12424,8 +12561,8 @@ var WSServer = class extends EventEmitter {
|
|
|
12424
12561
|
case "file_download": {
|
|
12425
12562
|
try {
|
|
12426
12563
|
const { readFileSync: readFileSync16 } = await import("fs");
|
|
12427
|
-
const { resolve:
|
|
12428
|
-
const targetPath =
|
|
12564
|
+
const { resolve: resolve16, basename: basename3 } = await import("path");
|
|
12565
|
+
const targetPath = resolve16(msg.path);
|
|
12429
12566
|
const data = readFileSync16(targetPath);
|
|
12430
12567
|
const base64 = data.toString("base64");
|
|
12431
12568
|
const ext = targetPath.split(".").pop()?.toLowerCase() || "";
|
|
@@ -12531,7 +12668,7 @@ var WSServer = class extends EventEmitter {
|
|
|
12531
12668
|
this.isRunning = false;
|
|
12532
12669
|
return;
|
|
12533
12670
|
}
|
|
12534
|
-
return new Promise((
|
|
12671
|
+
return new Promise((resolve16, reject) => {
|
|
12535
12672
|
this.wsServer.close((err) => {
|
|
12536
12673
|
if (err) {
|
|
12537
12674
|
reject(err);
|
|
@@ -12539,7 +12676,7 @@ var WSServer = class extends EventEmitter {
|
|
|
12539
12676
|
this.wsServer = null;
|
|
12540
12677
|
this.isRunning = false;
|
|
12541
12678
|
this.emit("stopped");
|
|
12542
|
-
|
|
12679
|
+
resolve16();
|
|
12543
12680
|
}
|
|
12544
12681
|
});
|
|
12545
12682
|
});
|
|
@@ -13720,7 +13857,7 @@ var DataCollector = class {
|
|
|
13720
13857
|
return context;
|
|
13721
13858
|
}
|
|
13722
13859
|
sleep(ms) {
|
|
13723
|
-
return new Promise((
|
|
13860
|
+
return new Promise((resolve16) => setTimeout(resolve16, ms));
|
|
13724
13861
|
}
|
|
13725
13862
|
async exportResults(outputPath, format = "json") {
|
|
13726
13863
|
switch (format) {
|
|
@@ -13783,7 +13920,6 @@ export {
|
|
|
13783
13920
|
createCDPInterceptor,
|
|
13784
13921
|
createRuleEngine,
|
|
13785
13922
|
createSession,
|
|
13786
|
-
createTarball,
|
|
13787
13923
|
destroyBrowser,
|
|
13788
13924
|
destroyBrowser as destroySessionManager,
|
|
13789
13925
|
domMutationRule,
|