@xbrowser/cli 1.24.0 → 1.24.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-BROEUPL3.js → chunk-5PZXCIDR.js} +31 -4
- package/dist/{chunk-A7RZYSWM.js → chunk-AYNFXG7V.js} +31 -4
- package/dist/{chunk-A3MORKYR.js → chunk-OSZNJT4U.js} +29 -3
- package/dist/cli.js +32 -23
- package/dist/daemon-main.js +5 -4
- package/dist/index.d.ts +12 -0
- package/dist/index.js +32 -23
- package/dist/{plugin-singleton-GJO7EZXB.js → plugin-singleton-GGSBI3EG.js} +1 -1
- package/dist/{server-YVMWMNHD.js → server-KSHSG4TY.js} +1 -1
- package/dist/{server-NPINOVJS.js → server-NXXU3UGI.js} +1 -1
- package/package.json +1 -1
|
@@ -7146,7 +7146,7 @@ function setWSServerCache(browserContext, server) {
|
|
|
7146
7146
|
import {
|
|
7147
7147
|
Core
|
|
7148
7148
|
} from "@dyyz1993/xcli-core";
|
|
7149
|
-
import { resolve as resolve2 } from "path";
|
|
7149
|
+
import { resolve as resolve2, basename, dirname as dirname3 } from "path";
|
|
7150
7150
|
import { existsSync as existsSync6, readdirSync } from "fs";
|
|
7151
7151
|
import { homedir as homedir4 } from "os";
|
|
7152
7152
|
|
|
@@ -7450,6 +7450,8 @@ var XBrowserPluginLoader = class {
|
|
|
7450
7450
|
core;
|
|
7451
7451
|
loader;
|
|
7452
7452
|
options;
|
|
7453
|
+
/** 目录名 → 该插件注册的 site 名(site.name ≠ 目录名时的命令别名兜底) */
|
|
7454
|
+
dirSiteAliases = /* @__PURE__ */ new Map();
|
|
7453
7455
|
constructor(options) {
|
|
7454
7456
|
patchLoginRequired();
|
|
7455
7457
|
this.options = options ?? {};
|
|
@@ -7487,15 +7489,39 @@ var XBrowserPluginLoader = class {
|
|
|
7487
7489
|
getLoadedPlugins() {
|
|
7488
7490
|
return this.loader.getLoadedPlugins();
|
|
7489
7491
|
}
|
|
7492
|
+
/**
|
|
7493
|
+
* 目录名别名兜底(小白用户实测踩坑):`plugin list` 显示目录名,但命令路由
|
|
7494
|
+
* 按 site.name 匹配——两者不一致时(如目录 alibaba-1688、site 名 1688),
|
|
7495
|
+
* 用户按 list 显示的名字敲命令会 "Unknown command"。映射在 scanAndLoad/
|
|
7496
|
+
* loadPlugin 时通过加载前后 site 快照 diff 记录(instance.siteName 返回的是
|
|
7497
|
+
* 插件 id 而非 site 名,不可用)。
|
|
7498
|
+
*/
|
|
7499
|
+
resolveSiteName(name) {
|
|
7500
|
+
if (this.core.loader.getSite(name)) return name;
|
|
7501
|
+
const aliased = this.dirSiteAliases.get(name);
|
|
7502
|
+
if (aliased && this.core.loader.getSite(aliased)) return aliased;
|
|
7503
|
+
return void 0;
|
|
7504
|
+
}
|
|
7505
|
+
/** 记录一次插件加载引入的 site:加载前后快照 diff(同插件可注册多个 site) */
|
|
7506
|
+
recordSiteAliases(pluginDirName, before) {
|
|
7507
|
+
for (const site of this.core.loader.getSites()) {
|
|
7508
|
+
if (!before.has(site.name)) this.dirSiteAliases.set(pluginDirName, site.name);
|
|
7509
|
+
}
|
|
7510
|
+
}
|
|
7490
7511
|
getPluginContract(siteName, commandName) {
|
|
7491
|
-
const
|
|
7512
|
+
const resolved = this.resolveSiteName(siteName);
|
|
7513
|
+
if (!resolved) return void 0;
|
|
7514
|
+
const site = this.core.loader.getSite(resolved);
|
|
7492
7515
|
if (!site) return void 0;
|
|
7493
7516
|
const contract = buildPluginContract(site);
|
|
7494
7517
|
if (!commandName) return contract;
|
|
7495
7518
|
return contract.commands.find((command) => command.name === commandName);
|
|
7496
7519
|
}
|
|
7497
7520
|
async loadPlugin(pluginPath, id) {
|
|
7498
|
-
|
|
7521
|
+
const before = new Set(this.core.loader.getSites().map((s) => s.name));
|
|
7522
|
+
const instance = await this.loader.loadPlugin(pluginPath, id);
|
|
7523
|
+
this.recordSiteAliases(basename(dirname3(pluginPath)), before);
|
|
7524
|
+
return instance;
|
|
7499
7525
|
}
|
|
7500
7526
|
async unloadPlugin(id) {
|
|
7501
7527
|
return this.loader.unloadPlugin(id);
|
|
@@ -8837,7 +8863,8 @@ async function executeChain(input, options) {
|
|
|
8837
8863
|
const cmdArgs = parts.slice(1);
|
|
8838
8864
|
const loader = await getPluginLoader();
|
|
8839
8865
|
const internalLoader = loader.getCore().loader;
|
|
8840
|
-
const
|
|
8866
|
+
const resolvedName = loader.resolveSiteName(cmdName);
|
|
8867
|
+
const site = resolvedName ? internalLoader.getSite(resolvedName) : void 0;
|
|
8841
8868
|
if (site) {
|
|
8842
8869
|
const subCommand = cmdArgs[0];
|
|
8843
8870
|
if (!subCommand) {
|
|
@@ -7045,7 +7045,7 @@ function attachDetectAntiBot(ctx) {
|
|
|
7045
7045
|
import {
|
|
7046
7046
|
Core
|
|
7047
7047
|
} from "@dyyz1993/xcli-core";
|
|
7048
|
-
import { resolve as resolve2 } from "path";
|
|
7048
|
+
import { resolve as resolve2, basename, dirname as dirname3 } from "path";
|
|
7049
7049
|
import { existsSync as existsSync6, readdirSync } from "fs";
|
|
7050
7050
|
import { homedir as homedir5 } from "os";
|
|
7051
7051
|
|
|
@@ -7349,6 +7349,8 @@ var XBrowserPluginLoader = class {
|
|
|
7349
7349
|
core;
|
|
7350
7350
|
loader;
|
|
7351
7351
|
options;
|
|
7352
|
+
/** 目录名 → 该插件注册的 site 名(site.name ≠ 目录名时的命令别名兜底) */
|
|
7353
|
+
dirSiteAliases = /* @__PURE__ */ new Map();
|
|
7352
7354
|
constructor(options) {
|
|
7353
7355
|
patchLoginRequired();
|
|
7354
7356
|
this.options = options ?? {};
|
|
@@ -7386,15 +7388,39 @@ var XBrowserPluginLoader = class {
|
|
|
7386
7388
|
getLoadedPlugins() {
|
|
7387
7389
|
return this.loader.getLoadedPlugins();
|
|
7388
7390
|
}
|
|
7391
|
+
/**
|
|
7392
|
+
* 目录名别名兜底(小白用户实测踩坑):`plugin list` 显示目录名,但命令路由
|
|
7393
|
+
* 按 site.name 匹配——两者不一致时(如目录 alibaba-1688、site 名 1688),
|
|
7394
|
+
* 用户按 list 显示的名字敲命令会 "Unknown command"。映射在 scanAndLoad/
|
|
7395
|
+
* loadPlugin 时通过加载前后 site 快照 diff 记录(instance.siteName 返回的是
|
|
7396
|
+
* 插件 id 而非 site 名,不可用)。
|
|
7397
|
+
*/
|
|
7398
|
+
resolveSiteName(name) {
|
|
7399
|
+
if (this.core.loader.getSite(name)) return name;
|
|
7400
|
+
const aliased = this.dirSiteAliases.get(name);
|
|
7401
|
+
if (aliased && this.core.loader.getSite(aliased)) return aliased;
|
|
7402
|
+
return void 0;
|
|
7403
|
+
}
|
|
7404
|
+
/** 记录一次插件加载引入的 site:加载前后快照 diff(同插件可注册多个 site) */
|
|
7405
|
+
recordSiteAliases(pluginDirName, before) {
|
|
7406
|
+
for (const site of this.core.loader.getSites()) {
|
|
7407
|
+
if (!before.has(site.name)) this.dirSiteAliases.set(pluginDirName, site.name);
|
|
7408
|
+
}
|
|
7409
|
+
}
|
|
7389
7410
|
getPluginContract(siteName, commandName) {
|
|
7390
|
-
const
|
|
7411
|
+
const resolved = this.resolveSiteName(siteName);
|
|
7412
|
+
if (!resolved) return void 0;
|
|
7413
|
+
const site = this.core.loader.getSite(resolved);
|
|
7391
7414
|
if (!site) return void 0;
|
|
7392
7415
|
const contract = buildPluginContract(site);
|
|
7393
7416
|
if (!commandName) return contract;
|
|
7394
7417
|
return contract.commands.find((command) => command.name === commandName);
|
|
7395
7418
|
}
|
|
7396
7419
|
async loadPlugin(pluginPath, id) {
|
|
7397
|
-
|
|
7420
|
+
const before = new Set(this.core.loader.getSites().map((s) => s.name));
|
|
7421
|
+
const instance = await this.loader.loadPlugin(pluginPath, id);
|
|
7422
|
+
this.recordSiteAliases(basename(dirname3(pluginPath)), before);
|
|
7423
|
+
return instance;
|
|
7398
7424
|
}
|
|
7399
7425
|
async unloadPlugin(id) {
|
|
7400
7426
|
return this.loader.unloadPlugin(id);
|
|
@@ -8517,7 +8543,8 @@ async function executeChain(input, options) {
|
|
|
8517
8543
|
const cmdArgs = parts.slice(1);
|
|
8518
8544
|
const loader = await getPluginLoader();
|
|
8519
8545
|
const internalLoader = loader.getCore().loader;
|
|
8520
|
-
const
|
|
8546
|
+
const resolvedName = loader.resolveSiteName(cmdName);
|
|
8547
|
+
const site = resolvedName ? internalLoader.getSite(resolvedName) : void 0;
|
|
8521
8548
|
if (site) {
|
|
8522
8549
|
const subCommand = cmdArgs[0];
|
|
8523
8550
|
if (!subCommand) {
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
import {
|
|
3
3
|
Core
|
|
4
4
|
} from "@dyyz1993/xcli-core";
|
|
5
|
-
import { resolve as resolve2 } from "path";
|
|
5
|
+
import { resolve as resolve2, basename, dirname } from "path";
|
|
6
6
|
import { existsSync as existsSync3, readdirSync } from "fs";
|
|
7
7
|
import { homedir } from "os";
|
|
8
8
|
|
|
@@ -306,6 +306,8 @@ var XBrowserPluginLoader = class {
|
|
|
306
306
|
core;
|
|
307
307
|
loader;
|
|
308
308
|
options;
|
|
309
|
+
/** 目录名 → 该插件注册的 site 名(site.name ≠ 目录名时的命令别名兜底) */
|
|
310
|
+
dirSiteAliases = /* @__PURE__ */ new Map();
|
|
309
311
|
constructor(options) {
|
|
310
312
|
patchLoginRequired();
|
|
311
313
|
this.options = options ?? {};
|
|
@@ -343,15 +345,39 @@ var XBrowserPluginLoader = class {
|
|
|
343
345
|
getLoadedPlugins() {
|
|
344
346
|
return this.loader.getLoadedPlugins();
|
|
345
347
|
}
|
|
348
|
+
/**
|
|
349
|
+
* 目录名别名兜底(小白用户实测踩坑):`plugin list` 显示目录名,但命令路由
|
|
350
|
+
* 按 site.name 匹配——两者不一致时(如目录 alibaba-1688、site 名 1688),
|
|
351
|
+
* 用户按 list 显示的名字敲命令会 "Unknown command"。映射在 scanAndLoad/
|
|
352
|
+
* loadPlugin 时通过加载前后 site 快照 diff 记录(instance.siteName 返回的是
|
|
353
|
+
* 插件 id 而非 site 名,不可用)。
|
|
354
|
+
*/
|
|
355
|
+
resolveSiteName(name) {
|
|
356
|
+
if (this.core.loader.getSite(name)) return name;
|
|
357
|
+
const aliased = this.dirSiteAliases.get(name);
|
|
358
|
+
if (aliased && this.core.loader.getSite(aliased)) return aliased;
|
|
359
|
+
return void 0;
|
|
360
|
+
}
|
|
361
|
+
/** 记录一次插件加载引入的 site:加载前后快照 diff(同插件可注册多个 site) */
|
|
362
|
+
recordSiteAliases(pluginDirName, before) {
|
|
363
|
+
for (const site of this.core.loader.getSites()) {
|
|
364
|
+
if (!before.has(site.name)) this.dirSiteAliases.set(pluginDirName, site.name);
|
|
365
|
+
}
|
|
366
|
+
}
|
|
346
367
|
getPluginContract(siteName, commandName) {
|
|
347
|
-
const
|
|
368
|
+
const resolved = this.resolveSiteName(siteName);
|
|
369
|
+
if (!resolved) return void 0;
|
|
370
|
+
const site = this.core.loader.getSite(resolved);
|
|
348
371
|
if (!site) return void 0;
|
|
349
372
|
const contract = buildPluginContract(site);
|
|
350
373
|
if (!commandName) return contract;
|
|
351
374
|
return contract.commands.find((command) => command.name === commandName);
|
|
352
375
|
}
|
|
353
376
|
async loadPlugin(pluginPath, id) {
|
|
354
|
-
|
|
377
|
+
const before = new Set(this.core.loader.getSites().map((s) => s.name));
|
|
378
|
+
const instance = await this.loader.loadPlugin(pluginPath, id);
|
|
379
|
+
this.recordSiteAliases(basename(dirname(pluginPath)), before);
|
|
380
|
+
return instance;
|
|
355
381
|
}
|
|
356
382
|
async unloadPlugin(id) {
|
|
357
383
|
return this.loader.unloadPlugin(id);
|
package/dist/cli.js
CHANGED
|
@@ -16,7 +16,7 @@ import {
|
|
|
16
16
|
loadHooks,
|
|
17
17
|
parsePluginParams,
|
|
18
18
|
readJsonFile
|
|
19
|
-
} from "./chunk-
|
|
19
|
+
} from "./chunk-AYNFXG7V.js";
|
|
20
20
|
import "./chunk-JKVUFP3G.js";
|
|
21
21
|
import {
|
|
22
22
|
forwardCommandLog,
|
|
@@ -629,6 +629,9 @@ async function installFromMarketplace(pluginsDir, slug, options) {
|
|
|
629
629
|
const realSlug = String(plugin.slug || slug);
|
|
630
630
|
try {
|
|
631
631
|
await downloadAndExtractMarketplaceTarball(baseUrl, realSlug, tmpDir, targetDir);
|
|
632
|
+
} catch (err) {
|
|
633
|
+
safeCleanup5(targetDir);
|
|
634
|
+
throw err;
|
|
632
635
|
} finally {
|
|
633
636
|
safeCleanup5(tmpDir);
|
|
634
637
|
}
|
|
@@ -802,6 +805,7 @@ function ensureIndexFile(plugin, name, targetDir) {
|
|
|
802
805
|
}
|
|
803
806
|
|
|
804
807
|
// src/plugin/installer.ts
|
|
808
|
+
import { safeCleanup as safeCleanup6 } from "@dyyz1993/xcli-core";
|
|
805
809
|
var PluginInstaller = class {
|
|
806
810
|
pluginsDir;
|
|
807
811
|
constructor(pluginsDir) {
|
|
@@ -827,31 +831,29 @@ var PluginInstaller = class {
|
|
|
827
831
|
}
|
|
828
832
|
mkdirSync4(targetDir, { recursive: true });
|
|
829
833
|
const resolvedSource = type === "npm" ? await resolveNpmPackageWithFallback(source) : source;
|
|
834
|
+
const withCleanup = async (fn) => {
|
|
835
|
+
try {
|
|
836
|
+
const r = await fn();
|
|
837
|
+
await this.fixSharedDeps(targetDir);
|
|
838
|
+
ensurePluginDependencies(this.pluginsDir);
|
|
839
|
+
if (!existsSync6(resolve6(targetDir, "index.ts")) && !existsSync6(resolve6(targetDir, "index.js"))) {
|
|
840
|
+
throw new Error("installed package has no index.ts/js entry");
|
|
841
|
+
}
|
|
842
|
+
return r;
|
|
843
|
+
} catch (err) {
|
|
844
|
+
safeCleanup6(targetDir);
|
|
845
|
+
throw err;
|
|
846
|
+
}
|
|
847
|
+
};
|
|
830
848
|
switch (type) {
|
|
831
849
|
case "local":
|
|
832
|
-
return await installFromLocal(source, name, targetDir)
|
|
833
|
-
await this.fixSharedDeps(targetDir);
|
|
834
|
-
ensurePluginDependencies(this.pluginsDir);
|
|
835
|
-
return r;
|
|
836
|
-
});
|
|
850
|
+
return await withCleanup(() => installFromLocal(source, name, targetDir));
|
|
837
851
|
case "npm":
|
|
838
|
-
return await installFromNpm(resolvedSource, name, targetDir)
|
|
839
|
-
await this.fixSharedDeps(targetDir);
|
|
840
|
-
ensurePluginDependencies(this.pluginsDir);
|
|
841
|
-
return r;
|
|
842
|
-
});
|
|
852
|
+
return await withCleanup(() => installFromNpm(resolvedSource, name, targetDir));
|
|
843
853
|
case "git":
|
|
844
|
-
return await installFromGit(source, name, targetDir)
|
|
845
|
-
await this.fixSharedDeps(targetDir);
|
|
846
|
-
ensurePluginDependencies(this.pluginsDir);
|
|
847
|
-
return r;
|
|
848
|
-
});
|
|
854
|
+
return await withCleanup(() => installFromGit(source, name, targetDir));
|
|
849
855
|
case "url":
|
|
850
|
-
return await installFromUrl(source, name, targetDir)
|
|
851
|
-
await this.fixSharedDeps(targetDir);
|
|
852
|
-
ensurePluginDependencies(this.pluginsDir);
|
|
853
|
-
return r;
|
|
854
|
-
});
|
|
856
|
+
return await withCleanup(() => installFromUrl(source, name, targetDir));
|
|
855
857
|
}
|
|
856
858
|
}
|
|
857
859
|
/**
|
|
@@ -5816,7 +5818,14 @@ async function routeCommand(argvIn, stdinCommands) {
|
|
|
5816
5818
|
default: {
|
|
5817
5819
|
const loader = await getPluginLoader();
|
|
5818
5820
|
const internalLoader = loader.getCore().loader;
|
|
5819
|
-
const
|
|
5821
|
+
const resolvedSiteName = loader.resolveSiteName(command);
|
|
5822
|
+
const site = resolvedSiteName ? internalLoader.getSite(resolvedSiteName) : void 0;
|
|
5823
|
+
if (site && resolvedSiteName !== command) {
|
|
5824
|
+
if (mode !== "json" && mode !== "yaml") {
|
|
5825
|
+
process.stderr.write(`\u2139\uFE0F "${command}" \u7684\u547D\u4EE4\u540D\u662F "${resolvedSiteName}"\uFF08\u63D2\u4EF6\u76EE\u5F55\u540D\u4E0E\u7AD9\u70B9\u540D\u4E0D\u4E00\u81F4\uFF0C\u5DF2\u81EA\u52A8\u6620\u5C04\uFF09
|
|
5826
|
+
`);
|
|
5827
|
+
}
|
|
5828
|
+
}
|
|
5820
5829
|
if (!site) {
|
|
5821
5830
|
const globalFlagSet = /* @__PURE__ */ new Set(["--session", "--cdp", "--json", "--yaml", "--help", "-h", "--version", "--output", "-o"]);
|
|
5822
5831
|
const cleanParts = [];
|
|
@@ -6272,7 +6281,7 @@ async function handleRemote(args, options, mode) {
|
|
|
6272
6281
|
}
|
|
6273
6282
|
}
|
|
6274
6283
|
async function startMcpServer() {
|
|
6275
|
-
const { startMcpStdio } = await import("./server-
|
|
6284
|
+
const { startMcpStdio } = await import("./server-KSHSG4TY.js");
|
|
6276
6285
|
startMcpStdio();
|
|
6277
6286
|
}
|
|
6278
6287
|
|
package/dist/daemon-main.js
CHANGED
|
@@ -4,7 +4,7 @@ import {
|
|
|
4
4
|
} from "./chunk-JKVUFP3G.js";
|
|
5
5
|
import {
|
|
6
6
|
getPluginLoader
|
|
7
|
-
} from "./chunk-
|
|
7
|
+
} from "./chunk-OSZNJT4U.js";
|
|
8
8
|
import {
|
|
9
9
|
version
|
|
10
10
|
} from "./chunk-43TEMG4U.js";
|
|
@@ -8098,7 +8098,8 @@ async function executeChain(input, options) {
|
|
|
8098
8098
|
const cmdArgs = parts.slice(1);
|
|
8099
8099
|
const loader = await getPluginLoader();
|
|
8100
8100
|
const internalLoader = loader.getCore().loader;
|
|
8101
|
-
const
|
|
8101
|
+
const resolvedName = loader.resolveSiteName(cmdName);
|
|
8102
|
+
const site = resolvedName ? internalLoader.getSite(resolvedName) : void 0;
|
|
8102
8103
|
if (site) {
|
|
8103
8104
|
const subCommand = cmdArgs[0];
|
|
8104
8105
|
if (!subCommand) {
|
|
@@ -9238,9 +9239,9 @@ function createRPCHandler() {
|
|
|
9238
9239
|
return result;
|
|
9239
9240
|
}
|
|
9240
9241
|
async function handlePluginsReload() {
|
|
9241
|
-
const { resetPluginLoader } = await import("./plugin-singleton-
|
|
9242
|
+
const { resetPluginLoader } = await import("./plugin-singleton-GGSBI3EG.js");
|
|
9242
9243
|
resetPluginLoader();
|
|
9243
|
-
const loader = await import("./plugin-singleton-
|
|
9244
|
+
const loader = await import("./plugin-singleton-GGSBI3EG.js").then((m) => m.getPluginLoader());
|
|
9244
9245
|
const sites = loader.getCore().loader.getSites();
|
|
9245
9246
|
return { ok: true, plugins: sites.length };
|
|
9246
9247
|
}
|
package/dist/index.d.ts
CHANGED
|
@@ -1634,6 +1634,8 @@ declare class XBrowserPluginLoader {
|
|
|
1634
1634
|
private core;
|
|
1635
1635
|
private loader;
|
|
1636
1636
|
private options;
|
|
1637
|
+
/** 目录名 → 该插件注册的 site 名(site.name ≠ 目录名时的命令别名兜底) */
|
|
1638
|
+
private dirSiteAliases;
|
|
1637
1639
|
constructor(options?: PluginLoaderOptions);
|
|
1638
1640
|
getAPI(): XCLIAPI;
|
|
1639
1641
|
/**
|
|
@@ -1644,6 +1646,16 @@ declare class XBrowserPluginLoader {
|
|
|
1644
1646
|
getPlugin(id: string): PluginInstance | undefined;
|
|
1645
1647
|
getPluginStatus(id: string): PluginStatus;
|
|
1646
1648
|
getLoadedPlugins(): PluginInstance[];
|
|
1649
|
+
/**
|
|
1650
|
+
* 目录名别名兜底(小白用户实测踩坑):`plugin list` 显示目录名,但命令路由
|
|
1651
|
+
* 按 site.name 匹配——两者不一致时(如目录 alibaba-1688、site 名 1688),
|
|
1652
|
+
* 用户按 list 显示的名字敲命令会 "Unknown command"。映射在 scanAndLoad/
|
|
1653
|
+
* loadPlugin 时通过加载前后 site 快照 diff 记录(instance.siteName 返回的是
|
|
1654
|
+
* 插件 id 而非 site 名,不可用)。
|
|
1655
|
+
*/
|
|
1656
|
+
resolveSiteName(name: string): string | undefined;
|
|
1657
|
+
/** 记录一次插件加载引入的 site:加载前后快照 diff(同插件可注册多个 site) */
|
|
1658
|
+
private recordSiteAliases;
|
|
1647
1659
|
getPluginContract(siteName: string, commandName?: string): PluginContract | PluginCommandContract | undefined;
|
|
1648
1660
|
loadPlugin(pluginPath: string, id?: string): Promise<PluginInstance>;
|
|
1649
1661
|
unloadPlugin(id: string): Promise<void>;
|
package/dist/index.js
CHANGED
|
@@ -48,7 +48,7 @@ import {
|
|
|
48
48
|
splitCommand,
|
|
49
49
|
waitForAIResponse,
|
|
50
50
|
waitForPage
|
|
51
|
-
} from "./chunk-
|
|
51
|
+
} from "./chunk-5PZXCIDR.js";
|
|
52
52
|
import {
|
|
53
53
|
SessionRecorder
|
|
54
54
|
} from "./chunk-IR6C24P7.js";
|
|
@@ -720,6 +720,9 @@ async function installFromMarketplace(pluginsDir, slug, options) {
|
|
|
720
720
|
const realSlug = String(plugin.slug || slug);
|
|
721
721
|
try {
|
|
722
722
|
await downloadAndExtractMarketplaceTarball(baseUrl, realSlug, tmpDir, targetDir);
|
|
723
|
+
} catch (err) {
|
|
724
|
+
safeCleanup5(targetDir);
|
|
725
|
+
throw err;
|
|
723
726
|
} finally {
|
|
724
727
|
safeCleanup5(tmpDir);
|
|
725
728
|
}
|
|
@@ -893,6 +896,7 @@ function ensureIndexFile(plugin, name, targetDir) {
|
|
|
893
896
|
}
|
|
894
897
|
|
|
895
898
|
// src/plugin/installer.ts
|
|
899
|
+
import { safeCleanup as safeCleanup6 } from "@dyyz1993/xcli-core";
|
|
896
900
|
var PluginInstaller = class {
|
|
897
901
|
pluginsDir;
|
|
898
902
|
constructor(pluginsDir) {
|
|
@@ -918,31 +922,29 @@ var PluginInstaller = class {
|
|
|
918
922
|
}
|
|
919
923
|
mkdirSync4(targetDir, { recursive: true });
|
|
920
924
|
const resolvedSource = type === "npm" ? await resolveNpmPackageWithFallback(source) : source;
|
|
925
|
+
const withCleanup = async (fn) => {
|
|
926
|
+
try {
|
|
927
|
+
const r = await fn();
|
|
928
|
+
await this.fixSharedDeps(targetDir);
|
|
929
|
+
ensurePluginDependencies(this.pluginsDir);
|
|
930
|
+
if (!existsSync6(resolve6(targetDir, "index.ts")) && !existsSync6(resolve6(targetDir, "index.js"))) {
|
|
931
|
+
throw new Error("installed package has no index.ts/js entry");
|
|
932
|
+
}
|
|
933
|
+
return r;
|
|
934
|
+
} catch (err) {
|
|
935
|
+
safeCleanup6(targetDir);
|
|
936
|
+
throw err;
|
|
937
|
+
}
|
|
938
|
+
};
|
|
921
939
|
switch (type) {
|
|
922
940
|
case "local":
|
|
923
|
-
return await installFromLocal(source, name, targetDir)
|
|
924
|
-
await this.fixSharedDeps(targetDir);
|
|
925
|
-
ensurePluginDependencies(this.pluginsDir);
|
|
926
|
-
return r;
|
|
927
|
-
});
|
|
941
|
+
return await withCleanup(() => installFromLocal(source, name, targetDir));
|
|
928
942
|
case "npm":
|
|
929
|
-
return await installFromNpm(resolvedSource, name, targetDir)
|
|
930
|
-
await this.fixSharedDeps(targetDir);
|
|
931
|
-
ensurePluginDependencies(this.pluginsDir);
|
|
932
|
-
return r;
|
|
933
|
-
});
|
|
943
|
+
return await withCleanup(() => installFromNpm(resolvedSource, name, targetDir));
|
|
934
944
|
case "git":
|
|
935
|
-
return await installFromGit(source, name, targetDir)
|
|
936
|
-
await this.fixSharedDeps(targetDir);
|
|
937
|
-
ensurePluginDependencies(this.pluginsDir);
|
|
938
|
-
return r;
|
|
939
|
-
});
|
|
945
|
+
return await withCleanup(() => installFromGit(source, name, targetDir));
|
|
940
946
|
case "url":
|
|
941
|
-
return await installFromUrl(source, name, targetDir)
|
|
942
|
-
await this.fixSharedDeps(targetDir);
|
|
943
|
-
ensurePluginDependencies(this.pluginsDir);
|
|
944
|
-
return r;
|
|
945
|
-
});
|
|
947
|
+
return await withCleanup(() => installFromUrl(source, name, targetDir));
|
|
946
948
|
}
|
|
947
949
|
}
|
|
948
950
|
/**
|
|
@@ -5912,7 +5914,14 @@ async function routeCommand(argvIn, stdinCommands) {
|
|
|
5912
5914
|
default: {
|
|
5913
5915
|
const loader = await getPluginLoader();
|
|
5914
5916
|
const internalLoader = loader.getCore().loader;
|
|
5915
|
-
const
|
|
5917
|
+
const resolvedSiteName = loader.resolveSiteName(command);
|
|
5918
|
+
const site = resolvedSiteName ? internalLoader.getSite(resolvedSiteName) : void 0;
|
|
5919
|
+
if (site && resolvedSiteName !== command) {
|
|
5920
|
+
if (mode !== "json" && mode !== "yaml") {
|
|
5921
|
+
process.stderr.write(`\u2139\uFE0F "${command}" \u7684\u547D\u4EE4\u540D\u662F "${resolvedSiteName}"\uFF08\u63D2\u4EF6\u76EE\u5F55\u540D\u4E0E\u7AD9\u70B9\u540D\u4E0D\u4E00\u81F4\uFF0C\u5DF2\u81EA\u52A8\u6620\u5C04\uFF09
|
|
5922
|
+
`);
|
|
5923
|
+
}
|
|
5924
|
+
}
|
|
5916
5925
|
if (!site) {
|
|
5917
5926
|
const globalFlagSet = /* @__PURE__ */ new Set(["--session", "--cdp", "--json", "--yaml", "--help", "-h", "--version", "--output", "-o"]);
|
|
5918
5927
|
const cleanParts = [];
|
|
@@ -6368,7 +6377,7 @@ async function handleRemote(args, options, mode) {
|
|
|
6368
6377
|
}
|
|
6369
6378
|
}
|
|
6370
6379
|
async function startMcpServer() {
|
|
6371
|
-
const { startMcpStdio } = await import("./server-
|
|
6380
|
+
const { startMcpStdio } = await import("./server-NXXU3UGI.js");
|
|
6372
6381
|
startMcpStdio();
|
|
6373
6382
|
}
|
|
6374
6383
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@xbrowser/cli",
|
|
3
|
-
"version": "1.24.
|
|
3
|
+
"version": "1.24.1",
|
|
4
4
|
"description": "Browser automation CLI for web scraping, headless browsing, SEO analysis, and AI agent workflows. A command-line alternative to Playwright, Puppeteer, and Selenium.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|