@xbrowser/cli 0.14.0 → 0.14.2

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/cli.js CHANGED
@@ -18,20 +18,6 @@ import {
18
18
  saveSessionDiskMeta,
19
19
  setActivePage
20
20
  } from "./chunk-2ONMTDLK.js";
21
- import {
22
- PluginMetadataParser
23
- } from "./chunk-HINTG75P.js";
24
- import {
25
- NPM_REGISTRY_URL,
26
- NPM_SCOPE,
27
- ensureProxyFetch,
28
- getConfigValue,
29
- getMarketplaceUrl,
30
- loadConfig,
31
- readJsonFile,
32
- resolveNpmPackageWithFallback,
33
- setConfigValue
34
- } from "./chunk-FF5WHQHN.js";
35
21
  import {
36
22
  forwardCommandLog,
37
23
  forwardNetworkAnalyze,
@@ -395,15 +381,15 @@ var clickCommand = registerCommand({
395
381
  let detectedNewPage;
396
382
  let cleanup;
397
383
  if (ctx.browserContext?.on) {
398
- const pagePromise = new Promise((resolve15) => {
384
+ const pagePromise = new Promise((resolve16) => {
399
385
  const timer = setTimeout(() => {
400
386
  ctx.browserContext.off("page", handler);
401
- resolve15(void 0);
387
+ resolve16(void 0);
402
388
  }, 3e3);
403
389
  const handler = (page2) => {
404
390
  clearTimeout(timer);
405
391
  ctx.browserContext.off("page", handler);
406
- resolve15(page2);
392
+ resolve16(page2);
407
393
  };
408
394
  ctx.browserContext.on("page", handler);
409
395
  });
@@ -1161,7 +1147,7 @@ var consoleCheckCommand = registerCommand({
1161
1147
  await page.goto(p.url, { waitUntil: "domcontentloaded" });
1162
1148
  }
1163
1149
  const messages = await page.evaluate((args) => {
1164
- return new Promise((resolve15) => {
1150
+ return new Promise((resolve16) => {
1165
1151
  const collected = [];
1166
1152
  const originalConsole = {
1167
1153
  log: console.log,
@@ -1228,7 +1214,7 @@ ${a.stack || ""}`;
1228
1214
  console.warn = originalConsole.warn;
1229
1215
  console.error = originalConsole.error;
1230
1216
  console.info = originalConsole.info;
1231
- resolve15(collected);
1217
+ resolve16(collected);
1232
1218
  }, args.duration);
1233
1219
  });
1234
1220
  }, { duration: p.duration });
@@ -1640,7 +1626,7 @@ async function executeAction(page, action) {
1640
1626
  if (action.selector) {
1641
1627
  await page.waitForSelector(action.selector, { timeout: 3e4 });
1642
1628
  } else if (action.milliseconds) {
1643
- await new Promise((resolve15) => setTimeout(resolve15, action.milliseconds));
1629
+ await new Promise((resolve16) => setTimeout(resolve16, action.milliseconds));
1644
1630
  } else {
1645
1631
  throw new Error("wait action requires either milliseconds or selector");
1646
1632
  }
@@ -1723,8 +1709,8 @@ var actionsCommand = registerCommand({
1723
1709
  results.push(result);
1724
1710
  }
1725
1711
  })();
1726
- const timeoutPromise = new Promise((resolve15) => {
1727
- setTimeout(resolve15, timeoutMs);
1712
+ const timeoutPromise = new Promise((resolve16) => {
1713
+ setTimeout(resolve16, timeoutMs);
1728
1714
  });
1729
1715
  await Promise.race([executionPromise, timeoutPromise]);
1730
1716
  const title = await ctx.page.title();
@@ -2398,11 +2384,11 @@ async function navigateForMap(page, url, timeout = 15e3) {
2398
2384
  }
2399
2385
  async function extractPageLinks(page, baseUrl) {
2400
2386
  await navigateForMap(page, baseUrl);
2401
- await new Promise((resolve15) => setTimeout(resolve15, 2e3));
2387
+ await new Promise((resolve16) => setTimeout(resolve16, 2e3));
2402
2388
  await page.evaluate(() => {
2403
2389
  window.scrollTo(0, document.body.scrollHeight);
2404
2390
  });
2405
- await new Promise((resolve15) => setTimeout(resolve15, 1e3));
2391
+ await new Promise((resolve16) => setTimeout(resolve16, 1e3));
2406
2392
  const origin = new URL(baseUrl).origin;
2407
2393
  const rawLinks = await page.evaluate((evalOrigin) => {
2408
2394
  return Array.from(document.querySelectorAll("a[href]")).map((a) => {
@@ -4232,25 +4218,25 @@ aria snapshot\uFF1A
4232
4218
  async function analyzeWithLLM(ariaSnapshot) {
4233
4219
  const piBin = process.env.PI_CLI_PATH || "pi";
4234
4220
  const prompt = LLM_PROMPT.replace("{snapshot}", ariaSnapshot.slice(0, 4e3));
4235
- return new Promise((resolve15) => {
4221
+ return new Promise((resolve16) => {
4236
4222
  execFile(
4237
4223
  piBin,
4238
4224
  ["--provider", LLM_PROVIDER, "--model", LLM_MODEL, prompt],
4239
4225
  { timeout: LLM_TIMEOUT_MS, maxBuffer: 1024 * 1024 },
4240
4226
  (err, stdout, _stderr) => {
4241
4227
  if (err) {
4242
- resolve15(null);
4228
+ resolve16(null);
4243
4229
  return;
4244
4230
  }
4245
4231
  const output = (stdout || "").trim();
4246
4232
  if (!output) {
4247
- resolve15(null);
4233
+ resolve16(null);
4248
4234
  return;
4249
4235
  }
4250
4236
  try {
4251
4237
  const parsed = parse(output);
4252
4238
  if (!parsed || typeof parsed !== "object") {
4253
- resolve15(null);
4239
+ resolve16(null);
4254
4240
  return;
4255
4241
  }
4256
4242
  const elements = {};
@@ -4265,9 +4251,9 @@ async function analyzeWithLLM(ariaSnapshot) {
4265
4251
  };
4266
4252
  }
4267
4253
  }
4268
- resolve15(Object.keys(elements).length > 0 ? elements : null);
4254
+ resolve16(Object.keys(elements).length > 0 ? elements : null);
4269
4255
  } catch {
4270
- resolve15(null);
4256
+ resolve16(null);
4271
4257
  }
4272
4258
  }
4273
4259
  );
@@ -4820,11 +4806,11 @@ function resolveScriptContent(params) {
4820
4806
  async function readStdin() {
4821
4807
  const { createReadStream } = await import("fs");
4822
4808
  const { createInterface: createInterface2 } = await import("readline");
4823
- return new Promise((resolve15, reject) => {
4809
+ return new Promise((resolve16, reject) => {
4824
4810
  const lines = [];
4825
4811
  const rl = createInterface2({ input: createReadStream("/dev/stdin") });
4826
4812
  rl.on("line", (line) => lines.push(line));
4827
- rl.on("close", () => resolve15(lines.join("\n")));
4813
+ rl.on("close", () => resolve16(lines.join("\n")));
4828
4814
  rl.on("error", reject);
4829
4815
  });
4830
4816
  }
@@ -5562,12 +5548,95 @@ var promoCommand = registerCommand({
5562
5548
  import {
5563
5549
  Core
5564
5550
  } from "@dyyz1993/xcli-core";
5565
- import { resolve as resolve7 } from "path";
5566
- import { existsSync as existsSync4, readdirSync } from "fs";
5551
+ import { resolve as resolve8 } from "path";
5552
+ import { existsSync as existsSync5, readdirSync } from "fs";
5567
5553
  import { homedir as homedir2 } from "os";
5568
5554
 
5555
+ // src/plugin/metadata-parser.ts
5556
+ import { existsSync as existsSync3 } from "fs";
5557
+ import { resolve as resolve7 } from "path";
5558
+
5559
+ // src/utils/json-file.ts
5560
+ import { readFileSync as readFileSync9, writeFileSync as writeFileSync3 } from "fs";
5561
+ function readJsonFile(filePath, defaultValue) {
5562
+ try {
5563
+ const content = readFileSync9(filePath, "utf-8");
5564
+ return JSON.parse(content);
5565
+ } catch {
5566
+ return defaultValue;
5567
+ }
5568
+ }
5569
+
5570
+ // src/plugin/metadata-parser.ts
5571
+ var PluginMetadataParser = class {
5572
+ static XBROWSER_KEYWORDS = ["xbrowser", "xbrowser-plugin"];
5573
+ static parseFromPackageJson(pluginPath) {
5574
+ const packageJsonPath = resolve7(pluginPath, "package.json");
5575
+ if (!existsSync3(packageJsonPath)) {
5576
+ return null;
5577
+ }
5578
+ const packageJson = readJsonFile(packageJsonPath, null);
5579
+ if (!packageJson) return null;
5580
+ if (!packageJson.xbrowser) {
5581
+ return null;
5582
+ }
5583
+ const xbrowser = packageJson.xbrowser;
5584
+ const metadata = {
5585
+ id: xbrowser.id || packageJson.name,
5586
+ name: xbrowser.name || packageJson.name,
5587
+ description: xbrowser.description || packageJson.description || "",
5588
+ version: xbrowser.version || packageJson.version || "1.0.0",
5589
+ author: xbrowser.author || this.extractAuthor(packageJson.author),
5590
+ homepage: xbrowser.homepage || packageJson.homepage,
5591
+ commands: xbrowser.commands,
5592
+ sites: xbrowser.sites,
5593
+ tags: xbrowser.tags,
5594
+ screenshot: xbrowser.screenshot,
5595
+ license: xbrowser.license || packageJson.license
5596
+ };
5597
+ return metadata;
5598
+ }
5599
+ static isXBrowserPlugin(packageJson) {
5600
+ if (packageJson.xbrowser) {
5601
+ return true;
5602
+ }
5603
+ const keywords = packageJson.keywords;
5604
+ if (!keywords) return false;
5605
+ return this.XBROWSER_KEYWORDS.some((kw) => keywords.includes(kw));
5606
+ }
5607
+ static fromNPMResult(result) {
5608
+ const author = typeof result.author === "string" ? result.author : result.author?.name || "Unknown";
5609
+ return {
5610
+ id: result.name,
5611
+ name: result.name.replace(/^xbrowser-plugin-/, "").replace(/^@[^/]+\//, ""),
5612
+ description: result.description || "",
5613
+ version: result.version,
5614
+ author,
5615
+ homepage: result.homepage || result.links?.homepage,
5616
+ tags: result.keywords,
5617
+ license: ""
5618
+ };
5619
+ }
5620
+ static extractAuthor(author) {
5621
+ if (typeof author === "string") return author;
5622
+ if (typeof author === "object" && author !== null) {
5623
+ const authorObj = author;
5624
+ return authorObj.name || "Unknown";
5625
+ }
5626
+ return "Unknown";
5627
+ }
5628
+ static validateMetadata(metadata) {
5629
+ const errors = [];
5630
+ if (!metadata.id) errors.push("id is required");
5631
+ if (!metadata.name) errors.push("name is required");
5632
+ if (!metadata.description) errors.push("description is required");
5633
+ if (!metadata.version) errors.push("version is required");
5634
+ return errors;
5635
+ }
5636
+ };
5637
+
5569
5638
  // src/plugin/ensure-deps.ts
5570
- import { existsSync as existsSync3, mkdirSync as mkdirSync2, writeFileSync as writeFileSync3 } from "fs";
5639
+ import { existsSync as existsSync4, mkdirSync as mkdirSync2, writeFileSync as writeFileSync4 } from "fs";
5571
5640
  import { join as join2 } from "path";
5572
5641
  import { execSync as execSync6 } from "child_process";
5573
5642
  var SHARED_PLUGIN_DEPENDENCIES = {
@@ -5576,11 +5645,11 @@ var SHARED_PLUGIN_DEPENDENCIES = {
5576
5645
  };
5577
5646
  function ensurePluginDependencies(pluginsDir) {
5578
5647
  const zodPath = join2(pluginsDir, "node_modules", "zod");
5579
- if (existsSync3(zodPath)) return;
5648
+ if (existsSync4(zodPath)) return;
5580
5649
  mkdirSync2(pluginsDir, { recursive: true });
5581
5650
  const pkgPath = join2(pluginsDir, "package.json");
5582
5651
  let pkg2 = {};
5583
- if (existsSync3(pkgPath)) {
5652
+ if (existsSync4(pkgPath)) {
5584
5653
  try {
5585
5654
  pkg2 = readJsonFile(pkgPath, {});
5586
5655
  } catch {
@@ -5594,11 +5663,11 @@ function ensurePluginDependencies(pluginsDir) {
5594
5663
  needsInstall = true;
5595
5664
  }
5596
5665
  }
5597
- if (!needsInstall && existsSync3(join2(pluginsDir, "node_modules"))) return;
5666
+ if (!needsInstall && existsSync4(join2(pluginsDir, "node_modules"))) return;
5598
5667
  pkg2.dependencies = existingDeps;
5599
5668
  pkg2.private = true;
5600
5669
  pkg2.description = pkg2.description || "xbrowser plugins \u2014 shared dependencies";
5601
- writeFileSync3(pkgPath, JSON.stringify(pkg2, null, 2) + "\n", "utf-8");
5670
+ writeFileSync4(pkgPath, JSON.stringify(pkg2, null, 2) + "\n", "utf-8");
5602
5671
  try {
5603
5672
  execSync6("npm install --production --no-package-lock --no-fund --no-audit", {
5604
5673
  cwd: pluginsDir,
@@ -5628,7 +5697,7 @@ var XBrowserPluginLoader = class {
5628
5697
  envPrefix: "XBROWSER",
5629
5698
  pluginDirs: [
5630
5699
  ...DEFAULT_PLUGIN_DIRS,
5631
- resolve7(cwd, ".xcli/plugins")
5700
+ resolve8(cwd, ".xcli/plugins")
5632
5701
  ]
5633
5702
  };
5634
5703
  this.core = new Core(coreConfig);
@@ -5667,31 +5736,31 @@ var XBrowserPluginLoader = class {
5667
5736
  }
5668
5737
  async scanAndLoad() {
5669
5738
  const cwd = this.options.cwd || process.cwd();
5670
- const globalDir = this.options.globalDir || resolve7(homedir2(), ".xbrowser/plugins");
5739
+ const globalDir = this.options.globalDir || resolve8(homedir2(), ".xbrowser/plugins");
5671
5740
  ensurePluginDependencies(globalDir);
5672
5741
  const dirs = [
5673
- resolve7(cwd, ".xcli/plugins"),
5674
- resolve7(cwd, "../.xcli/plugins"),
5675
- this.options.userDir || resolve7(homedir2(), ".xcli/plugins"),
5742
+ resolve8(cwd, ".xcli/plugins"),
5743
+ resolve8(cwd, "../.xcli/plugins"),
5744
+ this.options.userDir || resolve8(homedir2(), ".xcli/plugins"),
5676
5745
  globalDir
5677
5746
  ];
5678
5747
  const loaded = [];
5679
5748
  const seen = /* @__PURE__ */ new Set();
5680
5749
  for (const dir of dirs) {
5681
- if (!existsSync4(dir)) continue;
5750
+ if (!existsSync5(dir)) continue;
5682
5751
  const entries = readdirSync(dir, { withFileTypes: true });
5683
5752
  for (const entry of entries) {
5684
5753
  if (!entry.isDirectory()) continue;
5685
5754
  if (seen.has(entry.name)) continue;
5686
5755
  seen.add(entry.name);
5687
- const pluginDir = resolve7(dir, entry.name);
5688
- let indexPath = resolve7(pluginDir, "index.js");
5689
- if (!existsSync4(indexPath)) {
5690
- indexPath = resolve7(pluginDir, "index.ts");
5756
+ const pluginDir = resolve8(dir, entry.name);
5757
+ let indexPath = resolve8(pluginDir, "index.js");
5758
+ if (!existsSync5(indexPath)) {
5759
+ indexPath = resolve8(pluginDir, "index.ts");
5691
5760
  }
5692
- if (!existsSync4(indexPath)) continue;
5761
+ if (!existsSync5(indexPath)) continue;
5693
5762
  try {
5694
- if (!existsSync4(resolve7(pluginDir, "package.json"))) {
5763
+ if (!existsSync5(resolve8(pluginDir, "package.json"))) {
5695
5764
  console.warn(`\u26A0\uFE0F Plugin "${entry.name}" has no package.json. Use "xbrowser create ${entry.name} --template static" for proper structure.`);
5696
5765
  } else {
5697
5766
  const metadata = PluginMetadataParser.parseFromPackageJson(pluginDir);
@@ -5708,22 +5777,6 @@ var XBrowserPluginLoader = class {
5708
5777
  }
5709
5778
  }
5710
5779
  }
5711
- try {
5712
- const { default: setupMarketplace } = await import("./marketplace-W545W4FR.js");
5713
- setupMarketplace(this.loader.getAPI());
5714
- } catch (err) {
5715
- if (process.env.XBROWSER_DEBUG) {
5716
- console.warn(`\u26A0\uFE0F Built-in marketplace plugin load failed: ${err instanceof Error ? err.message : String(err)}`);
5717
- }
5718
- }
5719
- try {
5720
- const { default: setupAdmin } = await import("./admin-RPJJ5CAF.js");
5721
- setupAdmin(this.loader.getAPI());
5722
- } catch (err) {
5723
- if (process.env.XBROWSER_DEBUG) {
5724
- console.warn(`\u26A0\uFE0F Built-in admin plugin load failed: ${err instanceof Error ? err.message : String(err)}`);
5725
- }
5726
- }
5727
5780
  return loaded;
5728
5781
  }
5729
5782
  async unload() {
@@ -6124,7 +6177,7 @@ var TipsManager = class {
6124
6177
  }
6125
6178
  }
6126
6179
  debounce() {
6127
- return new Promise((resolve15) => setTimeout(resolve15, DEBOUNCE_MS));
6180
+ return new Promise((resolve16) => setTimeout(resolve16, DEBOUNCE_MS));
6128
6181
  }
6129
6182
  formatTips(tips) {
6130
6183
  return tips.map((tip) => {
@@ -6151,6 +6204,24 @@ function getTipsManager() {
6151
6204
  return globalTipsManager;
6152
6205
  }
6153
6206
 
6207
+ // src/hooks/loader.ts
6208
+ var builtinHooks = {
6209
+ screenshot: () => import("./screenshot-MB6R7RSS.js").then((m) => m.screenshotHook)
6210
+ };
6211
+ async function loadHooks() {
6212
+ const names = process.env.XBROWSER_HOOKS;
6213
+ if (!names) return [];
6214
+ const hooks = [];
6215
+ for (const name of names.split(",")) {
6216
+ const trimmed = name.trim();
6217
+ const factory = builtinHooks[trimmed];
6218
+ if (factory) {
6219
+ hooks.push(await factory());
6220
+ }
6221
+ }
6222
+ return hooks;
6223
+ }
6224
+
6154
6225
  // src/executor.ts
6155
6226
  import { homedir as homedir3 } from "os";
6156
6227
  import { join as join3 } from "path";
@@ -6310,9 +6381,22 @@ async function executeCommand(commandName, params, sessionName = "default", extr
6310
6381
  }
6311
6382
  }
6312
6383
  try {
6384
+ const hooks = await loadHooks();
6385
+ if (hooks.length > 0 && session?.page) {
6386
+ await Promise.all(hooks.map((h) => h.onBeforeCommand?.({ page: session.page, command: commandName, params })));
6387
+ }
6313
6388
  const raw = await command.handler(params, ctx);
6314
6389
  const end = Date.now();
6315
6390
  const duration = end - start;
6391
+ let hookOutputs;
6392
+ if (hooks.length > 0 && session?.page) {
6393
+ const outputs = [];
6394
+ for (const h of hooks) {
6395
+ const output = await h.onAfterCommand?.({ page: session.page, command: commandName, params, result: raw, duration });
6396
+ if (output) outputs.push({ _hook: h.name, ...output });
6397
+ }
6398
+ if (outputs.length > 0) hookOutputs = outputs;
6399
+ }
6316
6400
  if (session && isCommandResult(raw)) {
6317
6401
  const resultData = raw.data;
6318
6402
  const convUrl = resultData?.conversationUrl;
@@ -6360,9 +6444,9 @@ async function executeCommand(commandName, params, sessionName = "default", extr
6360
6444
  timestamp: start
6361
6445
  });
6362
6446
  if (isSuccess) {
6363
- return { ...ok25(raw.data, merged.length > 0 ? merged : raw.tips), duration };
6447
+ return { ...ok25(raw.data, merged.length > 0 ? merged : raw.tips), duration, ...hookOutputs ? { hookOutputs } : {} };
6364
6448
  }
6365
- return { success: false, data: raw.data, message: raw.message, tips: merged.length > 0 ? merged : raw.tips || [], duration };
6449
+ return { success: false, data: raw.data, message: raw.message, tips: merged.length > 0 ? merged : raw.tips || [], duration, ...hookOutputs ? { hookOutputs } : {} };
6366
6450
  }
6367
6451
  recordArchive(session?.id, sessionName, {
6368
6452
  step: 0,
@@ -6373,7 +6457,7 @@ async function executeCommand(commandName, params, sessionName = "default", extr
6373
6457
  duration,
6374
6458
  timestamp: start
6375
6459
  });
6376
- return { ...ok25(raw, smartTips), duration };
6460
+ return { ...ok25(raw, smartTips), duration, ...hookOutputs ? { hookOutputs } : {} };
6377
6461
  } catch (err) {
6378
6462
  const end = Date.now();
6379
6463
  const duration = end - start;
@@ -6768,6 +6852,68 @@ var sessionKillBuiltin = {
6768
6852
  }
6769
6853
  };
6770
6854
 
6855
+ // src/config.ts
6856
+ import { existsSync as existsSync6, mkdirSync as mkdirSync3, writeFileSync as writeFileSync5 } from "fs";
6857
+ import { join as join4 } from "path";
6858
+ import { homedir as homedir4, tmpdir } from "os";
6859
+ function getConfigFile() {
6860
+ return join4(homedir4() || tmpdir(), ".xbrowser", "config.json");
6861
+ }
6862
+ function loadConfig() {
6863
+ const configFile = getConfigFile();
6864
+ if (!existsSync6(configFile)) return {};
6865
+ return readJsonFile(configFile, {});
6866
+ }
6867
+ function saveConfig(config) {
6868
+ const dir = join4(homedir4() || tmpdir(), ".xbrowser");
6869
+ const configFile = getConfigFile();
6870
+ if (!existsSync6(dir)) mkdirSync3(dir, { recursive: true });
6871
+ writeFileSync5(configFile, JSON.stringify(config, null, 2), "utf-8");
6872
+ }
6873
+ function getConfigValue(key) {
6874
+ return loadConfig()[key];
6875
+ }
6876
+ function setConfigValue(key, value) {
6877
+ const config = loadConfig();
6878
+ config[key] = value;
6879
+ saveConfig(config);
6880
+ }
6881
+ var DEFAULT_MARKETPLACE_URL = "https://marketplace.xbrowser.dev";
6882
+ var NPM_REGISTRY_URL = "https://registry.npmjs.org";
6883
+ var NPM_SCOPE = "@xbrowser/";
6884
+ function getMarketplaceUrl() {
6885
+ return process.env.XBROWSER_MARKETPLACE_URL || getConfigValue("marketplaceUrl") || DEFAULT_MARKETPLACE_URL;
6886
+ }
6887
+ function resolveNpmPackageName(name) {
6888
+ if (name.startsWith("@")) return name;
6889
+ return `${NPM_SCOPE}${name}`;
6890
+ }
6891
+ var NPM_NAME_ALIASES = {
6892
+ "1688": "alibaba-1688"
6893
+ };
6894
+ function generateNpmCandidates(name) {
6895
+ if (name.startsWith("@")) return [name];
6896
+ const resolved = NPM_NAME_ALIASES[name] ?? name;
6897
+ return [
6898
+ `${NPM_SCOPE}xbrowser-plugin-${resolved}`,
6899
+ `${NPM_SCOPE}${resolved}`,
6900
+ `xbrowser-plugin-${resolved}`
6901
+ ];
6902
+ }
6903
+ async function resolveNpmPackageWithFallback(name) {
6904
+ const candidates = generateNpmCandidates(name);
6905
+ for (const candidate of candidates) {
6906
+ try {
6907
+ const encoded = encodeURIComponent(candidate);
6908
+ const res = await fetch(`${NPM_REGISTRY_URL}/${encoded}`);
6909
+ if (res.ok) return candidate;
6910
+ } catch {
6911
+ continue;
6912
+ }
6913
+ }
6914
+ return resolveNpmPackageName(name);
6915
+ }
6916
+
6771
6917
  // src/builtins/config.ts
6772
6918
  var configBuiltin = {
6773
6919
  name: "config",
@@ -6830,32 +6976,78 @@ var configBuiltin = {
6830
6976
 
6831
6977
  // src/plugin/installer.ts
6832
6978
  import {
6833
- existsSync as existsSync11,
6979
+ existsSync as existsSync13,
6834
6980
  readdirSync as readdirSync3,
6835
- mkdirSync as mkdirSync7,
6981
+ mkdirSync as mkdirSync8,
6836
6982
  rmSync as rmSync7
6837
6983
  } from "fs";
6838
- import { resolve as resolve14, basename as basename2 } from "path";
6839
- import { homedir as homedir4 } from "os";
6984
+ import { resolve as resolve15, basename as basename2 } from "path";
6985
+ import { homedir as homedir5 } from "os";
6840
6986
 
6841
6987
  // src/plugin/install-sources/local.ts
6842
- import { existsSync as existsSync6, cpSync as cpSync2, rmSync as rmSync2 } from "fs";
6843
- import { resolve as resolve9 } from "path";
6988
+ import { existsSync as existsSync8, cpSync as cpSync2, rmSync as rmSync2 } from "fs";
6989
+ import { resolve as resolve10 } from "path";
6844
6990
 
6845
6991
  // src/plugin/install-utils.ts
6846
6992
  import {
6847
- existsSync as existsSync5,
6993
+ existsSync as existsSync7,
6848
6994
  readdirSync as readdirSync2,
6849
6995
  cpSync,
6850
6996
  rmSync,
6851
- mkdirSync as mkdirSync3,
6852
- readFileSync as readFileSync9,
6997
+ mkdirSync as mkdirSync4,
6998
+ readFileSync as readFileSync10,
6853
6999
  createWriteStream
6854
7000
  } from "fs";
6855
- import { resolve as resolve8 } from "path";
7001
+ import { resolve as resolve9 } from "path";
6856
7002
  import { execSync as execSync7 } from "child_process";
6857
7003
  import { pipeline } from "stream/promises";
6858
7004
  import { Readable } from "stream";
7005
+
7006
+ // src/utils/proxy-fetch.ts
7007
+ var patched = false;
7008
+ async function ensureProxyFetch() {
7009
+ if (patched) return;
7010
+ patched = true;
7011
+ if (process.env.https_proxy && !process.env.HTTPS_PROXY) {
7012
+ process.env.HTTPS_PROXY = process.env.https_proxy;
7013
+ }
7014
+ if (process.env.http_proxy && !process.env.HTTP_PROXY) {
7015
+ process.env.HTTP_PROXY = process.env.http_proxy;
7016
+ }
7017
+ if (process.env.all_proxy && !process.env.ALL_PROXY) {
7018
+ process.env.ALL_PROXY = process.env.all_proxy;
7019
+ }
7020
+ 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;
7021
+ if (!proxyUrl) return;
7022
+ try {
7023
+ const undici = await import("undici");
7024
+ const EnvHttpProxyAgent = undici.EnvHttpProxyAgent;
7025
+ const uFetch = undici.fetch;
7026
+ const UFormData = undici.FormData;
7027
+ if (EnvHttpProxyAgent && uFetch && UFormData) {
7028
+ const agent = new EnvHttpProxyAgent();
7029
+ globalThis.fetch = ((input, init) => {
7030
+ const url = typeof input === "string" ? input : input instanceof URL ? input.href : input.url;
7031
+ const body = init?.body;
7032
+ if (body instanceof globalThis.FormData && !(body instanceof UFormData)) {
7033
+ const ufd = new UFormData();
7034
+ body.forEach((value, key) => {
7035
+ if (value instanceof Blob) {
7036
+ ufd.append(key, value, value.name || "file");
7037
+ } else {
7038
+ ufd.append(key, value);
7039
+ }
7040
+ });
7041
+ return uFetch(url, { ...init, body: ufd, dispatcher: agent });
7042
+ }
7043
+ return uFetch(url, { ...init, dispatcher: agent });
7044
+ });
7045
+ }
7046
+ } catch {
7047
+ }
7048
+ }
7049
+
7050
+ // src/plugin/install-utils.ts
6859
7051
  async function downloadToFile(url, destPath) {
6860
7052
  await ensureProxyFetch();
6861
7053
  if (url.startsWith("file://")) {
@@ -6874,7 +7066,7 @@ async function downloadToFile(url, destPath) {
6874
7066
  await pipeline(nodeStream, createWriteStream(destPath));
6875
7067
  }
6876
7068
  function extractTarGz(tarballPath, targetDir) {
6877
- mkdirSync3(targetDir, { recursive: true });
7069
+ mkdirSync4(targetDir, { recursive: true });
6878
7070
  execSync7(`tar -xzf "${tarballPath}" -C "${targetDir}"`, { stdio: "pipe" });
6879
7071
  }
6880
7072
  function flattenPackageRoot(targetDir) {
@@ -6882,11 +7074,11 @@ function flattenPackageRoot(targetDir) {
6882
7074
  const dirs = entries.filter((e) => e.isDirectory());
6883
7075
  const files = entries.filter((e) => !e.isDirectory());
6884
7076
  if (dirs.length === 1 && files.length === 0) {
6885
- const pkgDir = resolve8(targetDir, dirs[0].name);
7077
+ const pkgDir = resolve9(targetDir, dirs[0].name);
6886
7078
  const items = readdirSync2(pkgDir);
6887
7079
  for (const item of items) {
6888
- const src = resolve8(pkgDir, item);
6889
- const dst = resolve8(targetDir, item);
7080
+ const src = resolve9(pkgDir, item);
7081
+ const dst = resolve9(targetDir, item);
6890
7082
  cpSync(src, dst, { recursive: true, force: true });
6891
7083
  }
6892
7084
  rmSync(pkgDir, { recursive: true, force: true });
@@ -6894,19 +7086,19 @@ function flattenPackageRoot(targetDir) {
6894
7086
  }
6895
7087
  async function verifyPlugin(dir) {
6896
7088
  const warnings = [];
6897
- const indexPath = resolve8(dir, "index.ts");
6898
- if (!existsSync5(indexPath)) {
6899
- const indexJs = resolve8(dir, "index.js");
6900
- if (!existsSync5(indexJs)) {
7089
+ const indexPath = resolve9(dir, "index.ts");
7090
+ if (!existsSync7(indexPath)) {
7091
+ const indexJs = resolve9(dir, "index.js");
7092
+ if (!existsSync7(indexJs)) {
6901
7093
  return { valid: false, error: "No index.ts or index.js entry point found", warnings };
6902
7094
  }
6903
7095
  }
6904
- const pkgPath = resolve8(dir, "package.json");
6905
- if (!existsSync5(pkgPath)) {
7096
+ const pkgPath = resolve9(dir, "package.json");
7097
+ if (!existsSync7(pkgPath)) {
6906
7098
  warnings.push("No package.json found");
6907
7099
  } else {
6908
7100
  try {
6909
- const pkg2 = JSON.parse(readFileSync9(pkgPath, "utf-8"));
7101
+ const pkg2 = JSON.parse(readFileSync10(pkgPath, "utf-8"));
6910
7102
  if (!pkg2.xbrowser) {
6911
7103
  warnings.push("No xbrowser metadata in package.json");
6912
7104
  }
@@ -6925,8 +7117,8 @@ function safeCleanup(dir) {
6925
7117
 
6926
7118
  // src/plugin/install-sources/local.ts
6927
7119
  async function installFromLocal(source, name, targetDir) {
6928
- const srcPath = resolve9(source);
6929
- if (!existsSync6(srcPath)) {
7120
+ const srcPath = resolve10(source);
7121
+ if (!existsSync8(srcPath)) {
6930
7122
  throw new Error(`Local path does not exist: ${srcPath}`);
6931
7123
  }
6932
7124
  const tmpTarget = `${targetDir}-tmp-${Date.now()}`;
@@ -6939,7 +7131,7 @@ async function installFromLocal(source, name, targetDir) {
6939
7131
  safeCleanup(tmpTarget);
6940
7132
  throw new Error(`Invalid plugin: ${verify.error}`);
6941
7133
  }
6942
- if (existsSync6(targetDir)) {
7134
+ if (existsSync8(targetDir)) {
6943
7135
  rmSync2(targetDir, { recursive: true, force: true });
6944
7136
  }
6945
7137
  cpSync2(tmpTarget, targetDir, { recursive: true, force: true });
@@ -6959,9 +7151,9 @@ async function installFromLocal(source, name, targetDir) {
6959
7151
  }
6960
7152
 
6961
7153
  // src/plugin/install-sources/npm.ts
6962
- import { existsSync as existsSync7, mkdirSync as mkdirSync4, readFileSync as readFileSync10, writeFileSync as writeFileSync4, rmSync as rmSync3, cpSync as cpSync3 } from "fs";
6963
- import { resolve as resolve10, join as join4 } from "path";
6964
- import { tmpdir } from "os";
7154
+ import { existsSync as existsSync9, mkdirSync as mkdirSync5, readFileSync as readFileSync11, writeFileSync as writeFileSync6, rmSync as rmSync3, cpSync as cpSync3 } from "fs";
7155
+ import { resolve as resolve11, join as join5 } from "path";
7156
+ import { tmpdir as tmpdir2 } from "os";
6965
7157
  async function installFromNpm(packageName, name, targetDir) {
6966
7158
  await ensureProxyFetch();
6967
7159
  const encodedName = encodeURIComponent(packageName);
@@ -6979,13 +7171,13 @@ async function installFromNpm(packageName, name, targetDir) {
6979
7171
  throw new Error(`No tarball URL for ${packageName}@${latestVersion}`);
6980
7172
  }
6981
7173
  const tarballUrl = versionMeta.dist.tarball;
6982
- const tmpDir = join4(tmpdir(), `xbrowser-npm-${Date.now()}`);
6983
- mkdirSync4(tmpDir, { recursive: true });
7174
+ const tmpDir = join5(tmpdir2(), `xbrowser-npm-${Date.now()}`);
7175
+ mkdirSync5(tmpDir, { recursive: true });
6984
7176
  let warnings = [];
6985
7177
  try {
6986
- const tarballPath = join4(tmpDir, `${name}.tgz`);
7178
+ const tarballPath = join5(tmpDir, `${name}.tgz`);
6987
7179
  await downloadToFile(tarballUrl, tarballPath);
6988
- const extractDir = join4(tmpDir, "extracted");
7180
+ const extractDir = join5(tmpDir, "extracted");
6989
7181
  extractTarGz(tarballPath, extractDir);
6990
7182
  flattenPackageRoot(extractDir);
6991
7183
  const verify = await verifyPlugin(extractDir);
@@ -6993,16 +7185,16 @@ async function installFromNpm(packageName, name, targetDir) {
6993
7185
  if (!verify.valid) {
6994
7186
  throw new Error(`Invalid npm plugin: ${verify.error}`);
6995
7187
  }
6996
- if (existsSync7(targetDir)) {
7188
+ if (existsSync9(targetDir)) {
6997
7189
  rmSync3(targetDir, { recursive: true, force: true });
6998
7190
  }
6999
7191
  cpSync3(extractDir, targetDir, { recursive: true, force: true });
7000
- const pkgPath = resolve10(targetDir, "package.json");
7001
- if (existsSync7(pkgPath)) {
7002
- const pkg2 = JSON.parse(readFileSync10(pkgPath, "utf-8"));
7192
+ const pkgPath = resolve11(targetDir, "package.json");
7193
+ if (existsSync9(pkgPath)) {
7194
+ const pkg2 = JSON.parse(readFileSync11(pkgPath, "utf-8"));
7003
7195
  if (!pkg2._npmSource) {
7004
7196
  pkg2._npmSource = { name: packageName, version: latestVersion };
7005
- writeFileSync4(pkgPath, JSON.stringify(pkg2, null, 2));
7197
+ writeFileSync6(pkgPath, JSON.stringify(pkg2, null, 2));
7006
7198
  }
7007
7199
  }
7008
7200
  } finally {
@@ -7019,12 +7211,12 @@ async function installFromNpm(packageName, name, targetDir) {
7019
7211
  }
7020
7212
 
7021
7213
  // src/plugin/install-sources/git.ts
7022
- import { existsSync as existsSync8, readFileSync as readFileSync11, writeFileSync as writeFileSync5, rmSync as rmSync4, cpSync as cpSync4 } from "fs";
7023
- import { resolve as resolve11, join as join5 } from "path";
7024
- import { tmpdir as tmpdir2 } from "os";
7214
+ import { existsSync as existsSync10, readFileSync as readFileSync12, writeFileSync as writeFileSync7, rmSync as rmSync4, cpSync as cpSync4 } from "fs";
7215
+ import { resolve as resolve12, join as join6 } from "path";
7216
+ import { tmpdir as tmpdir3 } from "os";
7025
7217
  import { execSync as execSync8 } from "child_process";
7026
7218
  async function installFromGit(gitUrl, name, targetDir) {
7027
- const tmpDir = join5(tmpdir2(), `xbrowser-git-${Date.now()}`);
7219
+ const tmpDir = join6(tmpdir3(), `xbrowser-git-${Date.now()}`);
7028
7220
  let warnings = [];
7029
7221
  try {
7030
7222
  execSync8(`git clone --depth 1 "${gitUrl}" "${tmpDir}"`, { stdio: "pipe" });
@@ -7033,17 +7225,17 @@ async function installFromGit(gitUrl, name, targetDir) {
7033
7225
  if (!verify.valid) {
7034
7226
  throw new Error(`Invalid git plugin: ${verify.error}`);
7035
7227
  }
7036
- if (existsSync8(targetDir)) {
7228
+ if (existsSync10(targetDir)) {
7037
7229
  rmSync4(targetDir, { recursive: true, force: true });
7038
7230
  }
7039
7231
  cpSync4(tmpDir, targetDir, { recursive: true, force: true });
7040
- rmSync4(resolve11(targetDir, ".git"), { recursive: true, force: true });
7041
- const pkgPath = resolve11(targetDir, "package.json");
7042
- if (existsSync8(pkgPath)) {
7043
- const pkg2 = JSON.parse(readFileSync11(pkgPath, "utf-8"));
7232
+ rmSync4(resolve12(targetDir, ".git"), { recursive: true, force: true });
7233
+ const pkgPath = resolve12(targetDir, "package.json");
7234
+ if (existsSync10(pkgPath)) {
7235
+ const pkg2 = JSON.parse(readFileSync12(pkgPath, "utf-8"));
7044
7236
  if (!pkg2._gitSource) {
7045
7237
  pkg2._gitSource = { url: gitUrl };
7046
- writeFileSync5(pkgPath, JSON.stringify(pkg2, null, 2));
7238
+ writeFileSync7(pkgPath, JSON.stringify(pkg2, null, 2));
7047
7239
  }
7048
7240
  }
7049
7241
  } finally {
@@ -7060,18 +7252,18 @@ async function installFromGit(gitUrl, name, targetDir) {
7060
7252
  }
7061
7253
 
7062
7254
  // src/plugin/install-sources/url.ts
7063
- import { existsSync as existsSync9, readFileSync as readFileSync12, writeFileSync as writeFileSync6, mkdirSync as mkdirSync5, rmSync as rmSync5, cpSync as cpSync5 } from "fs";
7064
- import { resolve as resolve12, join as join6, basename } from "path";
7065
- import { tmpdir as tmpdir3 } from "os";
7255
+ import { existsSync as existsSync11, readFileSync as readFileSync13, writeFileSync as writeFileSync8, mkdirSync as mkdirSync6, rmSync as rmSync5, cpSync as cpSync5 } from "fs";
7256
+ import { resolve as resolve13, join as join7, basename } from "path";
7257
+ import { tmpdir as tmpdir4 } from "os";
7066
7258
  async function installFromUrl(url, name, targetDir) {
7067
- const tmpDir = join6(tmpdir3(), `xbrowser-url-${Date.now()}`);
7068
- mkdirSync5(tmpDir, { recursive: true });
7259
+ const tmpDir = join7(tmpdir4(), `xbrowser-url-${Date.now()}`);
7260
+ mkdirSync6(tmpDir, { recursive: true });
7069
7261
  let warnings = [];
7070
7262
  try {
7071
7263
  const fileName = basename(new URL(url).pathname) || "plugin.tar.gz";
7072
- const tarballPath = join6(tmpDir, fileName);
7264
+ const tarballPath = join7(tmpDir, fileName);
7073
7265
  await downloadToFile(url, tarballPath);
7074
- const extractDir = join6(tmpDir, "extracted");
7266
+ const extractDir = join7(tmpDir, "extracted");
7075
7267
  extractTarGz(tarballPath, extractDir);
7076
7268
  flattenPackageRoot(extractDir);
7077
7269
  const verify = await verifyPlugin(extractDir);
@@ -7079,16 +7271,16 @@ async function installFromUrl(url, name, targetDir) {
7079
7271
  if (!verify.valid) {
7080
7272
  throw new Error(`Invalid plugin from URL: ${verify.error}`);
7081
7273
  }
7082
- if (existsSync9(targetDir)) {
7274
+ if (existsSync11(targetDir)) {
7083
7275
  rmSync5(targetDir, { recursive: true, force: true });
7084
7276
  }
7085
7277
  cpSync5(extractDir, targetDir, { recursive: true, force: true });
7086
- const pkgPath = resolve12(targetDir, "package.json");
7087
- if (existsSync9(pkgPath)) {
7088
- const pkg2 = JSON.parse(readFileSync12(pkgPath, "utf-8"));
7278
+ const pkgPath = resolve13(targetDir, "package.json");
7279
+ if (existsSync11(pkgPath)) {
7280
+ const pkg2 = JSON.parse(readFileSync13(pkgPath, "utf-8"));
7089
7281
  if (!pkg2._urlSource) {
7090
7282
  pkg2._urlSource = { url };
7091
- writeFileSync6(pkgPath, JSON.stringify(pkg2, null, 2));
7283
+ writeFileSync8(pkgPath, JSON.stringify(pkg2, null, 2));
7092
7284
  }
7093
7285
  }
7094
7286
  } finally {
@@ -7106,15 +7298,15 @@ async function installFromUrl(url, name, targetDir) {
7106
7298
 
7107
7299
  // src/plugin/install-sources/marketplace.ts
7108
7300
  import {
7109
- existsSync as existsSync10,
7110
- mkdirSync as mkdirSync6,
7111
- writeFileSync as writeFileSync7,
7112
- readFileSync as readFileSync13,
7301
+ existsSync as existsSync12,
7302
+ mkdirSync as mkdirSync7,
7303
+ writeFileSync as writeFileSync9,
7304
+ readFileSync as readFileSync14,
7113
7305
  rmSync as rmSync6,
7114
7306
  cpSync as cpSync6
7115
7307
  } from "fs";
7116
- import { resolve as resolve13, join as join7, dirname as dirname2 } from "path";
7117
- import { tmpdir as tmpdir4 } from "os";
7308
+ import { resolve as resolve14, join as join8, dirname as dirname2 } from "path";
7309
+ import { tmpdir as tmpdir5 } from "os";
7118
7310
  import { gunzipSync } from "zlib";
7119
7311
  async function installFromMarketplace(pluginsDir, slug, options) {
7120
7312
  await ensureProxyFetch();
@@ -7130,13 +7322,13 @@ async function installFromMarketplace(pluginsDir, slug, options) {
7130
7322
  }
7131
7323
  const plugin = detailData.data;
7132
7324
  const name = options?.name || String(plugin.slug || slug);
7133
- const targetDir = resolve13(pluginsDir, name);
7134
- if (existsSync10(targetDir) && !options?.force) {
7325
+ const targetDir = resolve14(pluginsDir, name);
7326
+ if (existsSync12(targetDir) && !options?.force) {
7135
7327
  throw new Error(`Plugin "${name}" already exists. Use --force to overwrite.`);
7136
7328
  }
7137
- mkdirSync6(targetDir, { recursive: true });
7138
- const tmpDir = join7(tmpdir4(), `xbrowser-marketplace-${Date.now()}`);
7139
- mkdirSync6(tmpDir, { recursive: true });
7329
+ mkdirSync7(targetDir, { recursive: true });
7330
+ const tmpDir = join8(tmpdir5(), `xbrowser-marketplace-${Date.now()}`);
7331
+ mkdirSync7(tmpDir, { recursive: true });
7140
7332
  const realSlug = String(plugin.slug || slug);
7141
7333
  try {
7142
7334
  await downloadAndExtractMarketplaceTarball(baseUrl, realSlug, tmpDir, targetDir);
@@ -7166,14 +7358,14 @@ function isManifestArray(data) {
7166
7358
  return Array.isArray(data) && data.length > 0 && typeof data[0].path === "string" && typeof data[0].content === "string";
7167
7359
  }
7168
7360
  function extractManifestToDir(manifest, targetDir) {
7169
- if (existsSync10(targetDir)) {
7361
+ if (existsSync12(targetDir)) {
7170
7362
  rmSync6(targetDir, { recursive: true, force: true });
7171
7363
  }
7172
- mkdirSync6(targetDir, { recursive: true });
7364
+ mkdirSync7(targetDir, { recursive: true });
7173
7365
  for (const file of manifest) {
7174
- const filePath = resolve13(targetDir, file.path);
7175
- mkdirSync6(dirname2(filePath), { recursive: true });
7176
- writeFileSync7(filePath, Buffer.from(file.content, "base64"));
7366
+ const filePath = resolve14(targetDir, file.path);
7367
+ mkdirSync7(dirname2(filePath), { recursive: true });
7368
+ writeFileSync9(filePath, Buffer.from(file.content, "base64"));
7177
7369
  }
7178
7370
  }
7179
7371
  function tryParseAsGzippedManifest(buffer) {
@@ -7198,18 +7390,18 @@ async function downloadAndExtractMarketplaceTarball(baseUrl, slug, tmpDir, targe
7198
7390
  }
7199
7391
  if (tarballRes.status === 302 || tarballRes.headers.get("location")) {
7200
7392
  const redirectUrl = tarballRes.headers.get("location");
7201
- const tarballPath = join7(tmpDir, `${slug}.tar.gz`);
7393
+ const tarballPath = join8(tmpDir, `${slug}.tar.gz`);
7202
7394
  await downloadToFile(redirectUrl, tarballPath);
7203
- const buffer = readFileSync13(tarballPath);
7395
+ const buffer = readFileSync14(tarballPath);
7204
7396
  const manifest = tryParseAsGzippedManifest(buffer);
7205
7397
  if (manifest) {
7206
7398
  extractManifestToDir(manifest, targetDir);
7207
7399
  return;
7208
7400
  }
7209
- const extractDir = join7(tmpDir, "extracted");
7401
+ const extractDir = join8(tmpDir, "extracted");
7210
7402
  extractTarGz(tarballPath, extractDir);
7211
7403
  flattenPackageRoot(extractDir);
7212
- if (existsSync10(targetDir)) {
7404
+ if (existsSync12(targetDir)) {
7213
7405
  rmSync6(targetDir, { recursive: true, force: true });
7214
7406
  }
7215
7407
  cpSync6(extractDir, targetDir, { recursive: true, force: true });
@@ -7220,13 +7412,13 @@ async function downloadAndExtractMarketplaceTarball(baseUrl, slug, tmpDir, targe
7220
7412
  extractManifestToDir(manifest, targetDir);
7221
7413
  return;
7222
7414
  }
7223
- const tarballPath = join7(tmpDir, `${slug}.tar.gz`);
7224
- writeFileSync7(tarballPath, buffer);
7415
+ const tarballPath = join8(tmpDir, `${slug}.tar.gz`);
7416
+ writeFileSync9(tarballPath, buffer);
7225
7417
  try {
7226
- const extractDir = join7(tmpDir, "extracted");
7418
+ const extractDir = join8(tmpDir, "extracted");
7227
7419
  extractTarGz(tarballPath, extractDir);
7228
7420
  flattenPackageRoot(extractDir);
7229
- if (existsSync10(targetDir)) {
7421
+ if (existsSync12(targetDir)) {
7230
7422
  rmSync6(targetDir, { recursive: true, force: true });
7231
7423
  }
7232
7424
  cpSync6(extractDir, targetDir, { recursive: true, force: true });
@@ -7261,25 +7453,25 @@ function writeMarketplacePackageJson(plugin, slug, name, baseUrl, targetDir) {
7261
7453
  url: baseUrl
7262
7454
  }
7263
7455
  };
7264
- const pkgPath = resolve13(targetDir, "package.json");
7265
- if (!existsSync10(pkgPath)) {
7266
- writeFileSync7(pkgPath, JSON.stringify(packageJson, null, 2));
7456
+ const pkgPath = resolve14(targetDir, "package.json");
7457
+ if (!existsSync12(pkgPath)) {
7458
+ writeFileSync9(pkgPath, JSON.stringify(packageJson, null, 2));
7267
7459
  } else {
7268
7460
  try {
7269
- const existing = JSON.parse(readFileSync13(pkgPath, "utf-8"));
7461
+ const existing = JSON.parse(readFileSync14(pkgPath, "utf-8"));
7270
7462
  const merged = {
7271
7463
  ...existing,
7272
7464
  xbrowser: { ...existing.xbrowser, ...packageJson.xbrowser },
7273
7465
  _marketplace: packageJson._marketplace
7274
7466
  };
7275
- writeFileSync7(pkgPath, JSON.stringify(merged, null, 2));
7467
+ writeFileSync9(pkgPath, JSON.stringify(merged, null, 2));
7276
7468
  } catch {
7277
- writeFileSync7(pkgPath, JSON.stringify(packageJson, null, 2));
7469
+ writeFileSync9(pkgPath, JSON.stringify(packageJson, null, 2));
7278
7470
  }
7279
7471
  }
7280
7472
  }
7281
7473
  function ensureIndexFile(plugin, name, targetDir) {
7282
- if (!existsSync10(resolve13(targetDir, "index.ts")) && !existsSync10(resolve13(targetDir, "index.js"))) {
7474
+ if (!existsSync12(resolve14(targetDir, "index.ts")) && !existsSync12(resolve14(targetDir, "index.js"))) {
7283
7475
  const commands = plugin.commands || [];
7284
7476
  const commandHandlers = commands.length > 0 ? commands.map((cmd) => {
7285
7477
  return [
@@ -7294,8 +7486,8 @@ function ensureIndexFile(plugin, name, targetDir) {
7294
7486
  ` handler: async () => ({ data: { message: 'Hello from ${name}!' }, tips: [] }),`,
7295
7487
  ` });`
7296
7488
  ].join("\n");
7297
- writeFileSync7(
7298
- resolve13(targetDir, "index.ts"),
7489
+ writeFileSync9(
7490
+ resolve14(targetDir, "index.ts"),
7299
7491
  [
7300
7492
  `import type { XCLIAPI } from '@dyyz1993/xcli-core';`,
7301
7493
  ``,
@@ -7316,7 +7508,7 @@ function ensureIndexFile(plugin, name, targetDir) {
7316
7508
  var PluginInstaller = class {
7317
7509
  pluginsDir;
7318
7510
  constructor(pluginsDir) {
7319
- this.pluginsDir = pluginsDir || resolve14(homedir4(), ".xbrowser/plugins");
7511
+ this.pluginsDir = pluginsDir || resolve15(homedir5(), ".xbrowser/plugins");
7320
7512
  }
7321
7513
  getPluginsDir() {
7322
7514
  return this.pluginsDir;
@@ -7332,11 +7524,11 @@ var PluginInstaller = class {
7332
7524
  async install(source, options) {
7333
7525
  const type = this.detectSourceType(source);
7334
7526
  const name = options?.name || this.deriveName(source, type);
7335
- const targetDir = resolve14(this.pluginsDir, name);
7336
- if (existsSync11(targetDir) && !options?.force) {
7527
+ const targetDir = resolve15(this.pluginsDir, name);
7528
+ if (existsSync13(targetDir) && !options?.force) {
7337
7529
  throw new Error(`Plugin "${name}" already exists. Use --force to overwrite.`);
7338
7530
  }
7339
- mkdirSync7(targetDir, { recursive: true });
7531
+ mkdirSync8(targetDir, { recursive: true });
7340
7532
  const resolvedSource = type === "npm" ? await resolveNpmPackageWithFallback(source) : source;
7341
7533
  switch (type) {
7342
7534
  case "local":
@@ -7393,8 +7585,8 @@ var PluginInstaller = class {
7393
7585
  * @throws If the plugin is not installed.
7394
7586
  */
7395
7587
  async uninstall(name) {
7396
- const targetDir = resolve14(this.pluginsDir, name);
7397
- if (!existsSync11(targetDir)) {
7588
+ const targetDir = resolve15(this.pluginsDir, name);
7589
+ if (!existsSync13(targetDir)) {
7398
7590
  throw new Error(`Plugin "${name}" not found`);
7399
7591
  }
7400
7592
  rmSync7(targetDir, { recursive: true, force: true });
@@ -7405,18 +7597,18 @@ var PluginInstaller = class {
7405
7597
  * @returns Array of installed plugin information.
7406
7598
  */
7407
7599
  async list(_options) {
7408
- if (!existsSync11(this.pluginsDir)) return [];
7600
+ if (!existsSync13(this.pluginsDir)) return [];
7409
7601
  const entries = readdirSync3(this.pluginsDir, { withFileTypes: true });
7410
7602
  const plugins = [];
7411
7603
  for (const entry of entries) {
7412
7604
  if (!entry.isDirectory()) continue;
7413
- const pluginPath = resolve14(this.pluginsDir, entry.name);
7414
- const indexPath = resolve14(pluginPath, "index.ts");
7415
- const indexJsPath = resolve14(pluginPath, "index.js");
7416
- if (!existsSync11(indexPath) && !existsSync11(indexJsPath)) continue;
7605
+ const pluginPath = resolve15(this.pluginsDir, entry.name);
7606
+ const indexPath = resolve15(pluginPath, "index.ts");
7607
+ const indexJsPath = resolve15(pluginPath, "index.js");
7608
+ if (!existsSync13(indexPath) && !existsSync13(indexJsPath)) continue;
7417
7609
  const metadata = PluginMetadataParser.parseFromPackageJson(pluginPath);
7418
7610
  let source = "local";
7419
- const pkg2 = readJsonFile(resolve14(pluginPath, "package.json"), {});
7611
+ const pkg2 = readJsonFile(resolve15(pluginPath, "package.json"), {});
7420
7612
  if (pkg2._marketplace) source = "marketplace";
7421
7613
  else if (pkg2._npmSource) source = "npm";
7422
7614
  else if (pkg2._gitSource) source = "git";
@@ -7440,10 +7632,10 @@ var PluginInstaller = class {
7440
7632
  }
7441
7633
  if (source.startsWith("file://")) {
7442
7634
  const filePath = decodeURIComponent(new URL(source).pathname);
7443
- if (existsSync11(filePath)) return "url";
7635
+ if (existsSync13(filePath)) return "url";
7444
7636
  }
7445
7637
  if (source.endsWith(".git") || source.includes("github.com/")) return "git";
7446
- if (existsSync11(resolve14(source))) return "local";
7638
+ if (existsSync13(resolve15(source))) return "local";
7447
7639
  return "npm";
7448
7640
  }
7449
7641
  deriveName(source, type) {
@@ -7519,10 +7711,6 @@ function handlePluginHelp() {
7519
7711
  " uninstall <name> Uninstall a plugin",
7520
7712
  " list [--json] List installed plugins",
7521
7713
  " reload <name> Reload a plugin",
7522
- " publish [--registry <url>] [--dry-run] Publish plugin to marketplace",
7523
- " login [--token <api-key>] [--registry <url>] Login to marketplace",
7524
- " whoami Show current logged-in user",
7525
- " logout Logout from marketplace",
7526
7714
  "",
7527
7715
  "Examples:",
7528
7716
  " xbrowser plugin search scraper",
@@ -7530,12 +7718,7 @@ function handlePluginHelp() {
7530
7718
  " xbrowser plugin install ./my-plugin",
7531
7719
  " xbrowser plugin uninstall my-plugin",
7532
7720
  " xbrowser plugin list",
7533
- " xbrowser plugin reload my-plugin",
7534
- " xbrowser plugin publish",
7535
- " xbrowser plugin publish --dry-run",
7536
- " xbrowser plugin login --token my-api-key",
7537
- " xbrowser plugin whoami",
7538
- " xbrowser plugin logout"
7721
+ " xbrowser plugin reload my-plugin"
7539
7722
  ].join("\n");
7540
7723
  }
7541
7724
  var pluginInstallBuiltin = {
@@ -7837,76 +8020,60 @@ var NPMSearcher = class {
7837
8020
  }
7838
8021
  };
7839
8022
 
7840
- // src/plugin/marketplace-search.ts
7841
- var MarketplaceSearcher = class {
7842
- static getBaseUrl() {
7843
- return getMarketplaceUrl();
7844
- }
7845
- static async search(options = {}) {
7846
- await ensureProxyFetch();
7847
- const { query = "", tag, site, limit = 20 } = options;
7848
- const baseUrl = this.getBaseUrl();
7849
- const params = new URLSearchParams();
7850
- if (query) params.set("q", query);
7851
- if (tag) params.set("tag", tag);
7852
- if (site) params.set("site", site);
7853
- params.set("limit", String(limit));
7854
- const url = `${baseUrl}/api/plugins/search?${params.toString()}`;
7855
- try {
7856
- const response = await fetch(url);
7857
- if (!response.ok) {
7858
- return [];
7859
- }
7860
- const data = await response.json();
7861
- if (!data.success || !data.data?.items) {
7862
- return [];
7863
- }
7864
- return data.data.items.map((item) => this.parseMarketplacePlugin(item));
7865
- } catch {
7866
- return [];
7867
- }
7868
- }
7869
- static async getPluginDetail(slug) {
7870
- await ensureProxyFetch();
7871
- const baseUrl = this.getBaseUrl();
7872
- const url = `${baseUrl}/api/plugins/${slug}`;
7873
- try {
7874
- const response = await fetch(url);
7875
- if (!response.ok) return null;
7876
- const data = await response.json();
7877
- if (!data.success || !data.data) return null;
7878
- return this.parseMarketplacePlugin(data.data);
7879
- } catch {
7880
- return null;
7881
- }
7882
- }
7883
- static parseMarketplacePlugin(item) {
7884
- return {
8023
+ // src/builtins/plugin-search.ts
8024
+ async function searchFromMarketplacePlugin(options, loader) {
8025
+ const sites = loader.getCore().loader.getSites();
8026
+ const marketplaceSite = sites.find((s) => s.name === "marketplace");
8027
+ if (!marketplaceSite) return [];
8028
+ const searchCmd = marketplaceSite.getCommand("search");
8029
+ if (!searchCmd) return [];
8030
+ try {
8031
+ const result = await searchCmd.handler(
8032
+ {
8033
+ query: options.query,
8034
+ tag: options.tag,
8035
+ site: options.site,
8036
+ limit: options.limit
8037
+ },
8038
+ {}
8039
+ );
8040
+ const items = extractItems(result);
8041
+ return items.map((item) => ({
7885
8042
  source: "marketplace",
7886
- slug: String(item.slug || ""),
7887
8043
  name: String(item.name || ""),
7888
8044
  version: String(item.version || "latest"),
7889
8045
  description: String(item.description || ""),
7890
- author: String(item.authorName || "Unknown"),
7891
- homepage: typeof item.homepageUrl === "string" ? item.homepageUrl : void 0,
7892
- repository: typeof item.repositoryUrl === "string" ? item.repositoryUrl : void 0,
7893
- keywords: Array.isArray(item.tags) ? item.tags.map(String) : [],
8046
+ author: String(item.author || ""),
8047
+ homepage: typeof item.homepage === "string" ? item.homepage : void 0,
7894
8048
  tags: Array.isArray(item.tags) ? item.tags.map(String) : [],
7895
- sites: Array.isArray(item.siteUrls) ? item.siteUrls.map(String) : [],
7896
- commands: Array.isArray(item.commands) ? item.commands.map(String) : [],
7897
- downloads: typeof item.downloadCount === "number" ? item.downloadCount : 0,
7898
- license: typeof item.license === "string" ? item.license : void 0
7899
- };
8049
+ downloads: typeof item.downloads === "number" ? item.downloads : 0,
8050
+ slug: String(item.slug || ""),
8051
+ commands: Array.isArray(item.commands) ? item.commands.map(String) : []
8052
+ }));
8053
+ } catch {
8054
+ return [];
7900
8055
  }
7901
- };
7902
-
7903
- // src/builtins/plugin-search.ts
8056
+ }
8057
+ function extractItems(result) {
8058
+ if (!result || typeof result !== "object") return [];
8059
+ const r = result;
8060
+ if ("data" in r) {
8061
+ const data = r.data;
8062
+ if (data && "items" in data && Array.isArray(data.items)) {
8063
+ return data.items;
8064
+ }
8065
+ }
8066
+ if ("items" in r && Array.isArray(r.items)) {
8067
+ return r.items;
8068
+ }
8069
+ return [];
8070
+ }
7904
8071
  var pluginSearchBuiltin = {
7905
8072
  name: "plugin search",
7906
8073
  description: "Search for xbrowser plugins on npm registry and marketplace",
7907
8074
  help: {
7908
8075
  usage: "xbrowser plugin search <query> [options]",
7909
- description: "Search npm registry and marketplace for xbrowser-compatible plugins",
8076
+ description: "Search npm registry and installed plugin search providers for xbrowser-compatible plugins",
7910
8077
  options: [
7911
8078
  { name: "--tag <tag>", description: "Filter by plugin tag" },
7912
8079
  { name: "--site <site>", description: "Filter by target site" },
@@ -7928,26 +8095,24 @@ var pluginSearchBuiltin = {
7928
8095
  limit: options["limit"] ? Number.parseInt(String(options["limit"])) : 20
7929
8096
  };
7930
8097
  console.log(
7931
- `Searching npm registry and marketplace for xbrowser plugins...${query ? ` (query: "${query}")` : ""}`
8098
+ `Searching for xbrowser plugins...${query ? ` (query: "${query}")` : ""}`
7932
8099
  );
7933
- const [npmSettled, marketplaceSettled] = await Promise.allSettled([
8100
+ const loader = await getPluginLoader();
8101
+ const [npmSettled, pluginSettled] = await Promise.allSettled([
7934
8102
  NPMSearcher.search(searchOptions),
7935
- MarketplaceSearcher.search(searchOptions)
8103
+ searchFromMarketplacePlugin(searchOptions, loader)
7936
8104
  ]);
7937
8105
  const npmResults = npmSettled.status === "fulfilled" ? npmSettled.value : [];
7938
- const marketplaceResults = marketplaceSettled.status === "fulfilled" ? marketplaceSettled.value : [];
8106
+ const pluginResults = pluginSettled.status === "fulfilled" ? pluginSettled.value : [];
7939
8107
  if (npmSettled.status === "rejected") {
7940
8108
  console.warn(`Warning: npm search failed: ${npmSettled.reason}`);
7941
8109
  }
7942
- if (marketplaceSettled.status === "rejected") {
7943
- console.warn(`Warning: marketplace search failed: ${marketplaceSettled.reason}`);
7944
- }
7945
- const total = npmResults.length + marketplaceResults.length;
8110
+ const total = npmResults.length + pluginResults.length;
7946
8111
  if (total === 0) {
7947
8112
  console.log("No plugins found.");
7948
8113
  return;
7949
8114
  }
7950
- console.log(`Found ${total} plugin(s) (npm: ${npmResults.length}, marketplace: ${marketplaceResults.length}):
8115
+ console.log(`Found ${total} plugin(s) (npm: ${npmResults.length}, plugins: ${pluginResults.length}):
7951
8116
  `);
7952
8117
  if (npmResults.length > 0) {
7953
8118
  console.log("--- npm ---\n");
@@ -7971,14 +8136,14 @@ var pluginSearchBuiltin = {
7971
8136
  console.log("");
7972
8137
  });
7973
8138
  }
7974
- if (marketplaceResults.length > 0) {
8139
+ if (pluginResults.length > 0) {
7975
8140
  console.log("--- marketplace ---\n");
7976
- marketplaceResults.forEach((result, idx) => {
8141
+ pluginResults.forEach((result, idx) => {
7977
8142
  console.log(`${idx + 1}. ${result.name} [marketplace]`);
7978
8143
  console.log(` ${result.description}`);
7979
8144
  console.log(` Version: ${result.version}`);
7980
- console.log(` Author: ${result.author}`);
7981
- console.log(` Downloads: ${result.downloads}`);
8145
+ if (result.author) console.log(` Author: ${result.author}`);
8146
+ if (result.downloads) console.log(` Downloads: ${result.downloads}`);
7982
8147
  if (result.tags && result.tags.length > 0) {
7983
8148
  console.log(` Tags: ${result.tags.join(", ")}`);
7984
8149
  }
@@ -7988,7 +8153,9 @@ var pluginSearchBuiltin = {
7988
8153
  if (result.homepage) {
7989
8154
  console.log(` Homepage: ${result.homepage}`);
7990
8155
  }
7991
- console.log(` Install: xbrowser plugin install ${result.slug} --from-marketplace`);
8156
+ if (result.slug) {
8157
+ console.log(` Install: xbrowser plugin install ${result.slug} --from-marketplace`);
8158
+ }
7992
8159
  console.log("");
7993
8160
  });
7994
8161
  }
@@ -8758,15 +8925,15 @@ async function handleBrowserCommand(command, args, options, sessionName, mode, c
8758
8925
  }
8759
8926
 
8760
8927
  // src/cli/session-routes.ts
8761
- import { homedir as homedir5 } from "os";
8762
- import { join as join9 } from "path";
8928
+ import { homedir as homedir6 } from "os";
8929
+ import { join as join10 } from "path";
8763
8930
  import { readdirSync as readdirSync4, rmSync as rmSync8 } from "fs";
8764
8931
  function cleanSessionFiles() {
8765
- const dir = join9(homedir5(), ".xbrowser", "sessions");
8932
+ const dir = join10(homedir6(), ".xbrowser", "sessions");
8766
8933
  let count = 0;
8767
8934
  try {
8768
8935
  for (const entry of readdirSync4(dir, { withFileTypes: true })) {
8769
- const p = join9(dir, entry.name);
8936
+ const p = join10(dir, entry.name);
8770
8937
  rmSync8(p, { recursive: true, force: true });
8771
8938
  count++;
8772
8939
  }
@@ -8869,6 +9036,67 @@ function applyRegistryOverride(options) {
8869
9036
  process.env.XBROWSER_MARKETPLACE_URL = registry2;
8870
9037
  }
8871
9038
  }
9039
+ function extractItems2(result) {
9040
+ if (!result || typeof result !== "object") return [];
9041
+ const r = result;
9042
+ if ("data" in r) {
9043
+ const data = r.data;
9044
+ if (data && "items" in data && Array.isArray(data.items)) {
9045
+ return data.items;
9046
+ }
9047
+ }
9048
+ if ("items" in r && Array.isArray(r.items)) {
9049
+ return r.items;
9050
+ }
9051
+ return [];
9052
+ }
9053
+ async function searchFromMarketplacePlugin2(options, loader) {
9054
+ const sites = loader.getCore().loader.getSites();
9055
+ const marketplaceSite = sites.find((s) => s.name === "marketplace");
9056
+ if (!marketplaceSite) return [];
9057
+ const searchCmd = marketplaceSite.getCommand("search");
9058
+ if (!searchCmd) return [];
9059
+ try {
9060
+ const result = await searchCmd.handler(
9061
+ {
9062
+ query: options.query,
9063
+ tag: options.tag,
9064
+ site: options.site,
9065
+ limit: options.limit
9066
+ },
9067
+ {}
9068
+ );
9069
+ const items = extractItems2(result);
9070
+ return items.map((item) => ({ ...item, source: "marketplace" }));
9071
+ } catch {
9072
+ return [];
9073
+ }
9074
+ }
9075
+ async function infoFromMarketplacePlugin(slug, loader) {
9076
+ const sites = loader.getCore().loader.getSites();
9077
+ const marketplaceSite = sites.find((s) => s.name === "marketplace");
9078
+ if (!marketplaceSite) return null;
9079
+ const infoCmd = marketplaceSite.getCommand("info");
9080
+ if (!infoCmd) return null;
9081
+ try {
9082
+ const result = await infoCmd.handler({ slug }, {});
9083
+ if (!result || typeof result !== "object") return null;
9084
+ const r = result;
9085
+ let plugin = null;
9086
+ if ("data" in r) {
9087
+ const data = r.data;
9088
+ plugin = data?.plugin || null;
9089
+ }
9090
+ if (!plugin && "plugin" in r) {
9091
+ plugin = r.plugin;
9092
+ }
9093
+ if (plugin && plugin.name) {
9094
+ return { ...plugin, source: "marketplace" };
9095
+ }
9096
+ } catch {
9097
+ }
9098
+ return null;
9099
+ }
8872
9100
  async function handleSearch(args, options, mode) {
8873
9101
  const query = args[0] || "";
8874
9102
  applyRegistryOverride(options);
@@ -8876,11 +9104,10 @@ async function handleSearch(args, options, mode) {
8876
9104
  const searchLimit = options.limit ? Number(options.limit) : 20;
8877
9105
  const searchOpts = { query, tag: options.tag, site: options.site, limit: searchLimit };
8878
9106
  const results = [];
8879
- const marketplaceResults = await MarketplaceSearcher.search(searchOpts);
8880
- for (const r of marketplaceResults) {
8881
- results.push({ ...r, source: "marketplace" });
8882
- }
8883
- if (marketplaceResults.length === 0) {
9107
+ const loader = await getPluginLoader();
9108
+ const pluginResults = await searchFromMarketplacePlugin2(searchOpts, loader);
9109
+ results.push(...pluginResults);
9110
+ if (pluginResults.length === 0) {
8884
9111
  try {
8885
9112
  const npmResults = await NPMSearcher.search(searchOpts);
8886
9113
  for (const r of npmResults) {
@@ -8913,12 +9140,11 @@ async function handlePluginInfo(args, options, mode) {
8913
9140
  if (!slug) outputError("Usage: xbrowser plugin info <slug>");
8914
9141
  applyRegistryOverride(options);
8915
9142
  await ensureProxyFetch();
8916
- const marketplaceUrl = getMarketplaceUrl();
9143
+ const loader = await getPluginLoader();
8917
9144
  try {
8918
- const resp = await fetch(`${marketplaceUrl}/api/plugins/${slug}`);
8919
- if (resp.ok) {
8920
- const raw = await resp.json();
8921
- const d = raw.data || raw;
9145
+ const pluginInfo = await infoFromMarketplacePlugin(slug, loader);
9146
+ if (pluginInfo) {
9147
+ const d = pluginInfo;
8922
9148
  if (mode === "json") {
8923
9149
  outputResult({ source: "marketplace", ...d }, mode);
8924
9150
  return;
@@ -8926,12 +9152,11 @@ async function handlePluginInfo(args, options, mode) {
8926
9152
  console.log(`\u540D\u79F0: ${d.name || ""}`);
8927
9153
  console.log(`\u7248\u672C: ${d.version || ""}`);
8928
9154
  console.log(`\u63CF\u8FF0: ${d.description || ""}`);
8929
- console.log(`\u4F5C\u8005: ${d.authorName || d.author || ""}`);
8930
- console.log(`\u72B6\u6001: ${d.status || ""}`);
9155
+ console.log(`\u4F5C\u8005: ${d.author || ""}`);
8931
9156
  console.log(`\u547D\u4EE4: ${(d.commands || []).join(", ")}`);
8932
- console.log(`\u4E0B\u8F7D\u91CF: ${d.downloadCount || 0}`);
9157
+ console.log(`\u4E0B\u8F7D\u91CF: ${d.downloads || 0}`);
8933
9158
  console.log(`\u6807\u7B7E: ${(d.tags || []).join(", ")}`);
8934
- console.log(`\u7F51\u7AD9: ${(d.siteUrls || []).join(", ")}`);
9159
+ console.log(`\u7F51\u7AD9: ${(d.sites || []).join(", ")}`);
8935
9160
  return;
8936
9161
  }
8937
9162
  } catch {
@@ -9434,7 +9659,7 @@ async function handleFilter(args, _mode) {
9434
9659
 
9435
9660
  // src/stdin.ts
9436
9661
  import { createInterface } from "readline";
9437
- import { readFileSync as readFileSync14 } from "fs";
9662
+ import { readFileSync as readFileSync15 } from "fs";
9438
9663
  async function readStdin2() {
9439
9664
  if (process.stdin.isTTY) return [];
9440
9665
  const lines = [];
@@ -9448,7 +9673,7 @@ async function readStdin2() {
9448
9673
  return lines;
9449
9674
  }
9450
9675
  function readCommandFile(filePath) {
9451
- const content = readFileSync14(filePath, "utf-8");
9676
+ const content = readFileSync15(filePath, "utf-8");
9452
9677
  return content.split("\n").map((line) => line.trim()).filter((line) => line && !line.startsWith("#"));
9453
9678
  }
9454
9679
 
@@ -9880,24 +10105,6 @@ Commands:
9880
10105
  viewer [--name <n>] [--selector <sel>] Generate viewer URL
9881
10106
  help Show this help
9882
10107
  --version, -v Show version
9883
-
9884
- Marketplace & Admin:
9885
- marketplace publish [--dry-run] Publish plugin to marketplace
9886
- marketplace login [--token <key>] Login to marketplace
9887
- marketplace register Register developer account
9888
- marketplace whoami Show current user
9889
- marketplace logout Logout from marketplace
9890
- admin pending List pending plugins (admin only)
9891
- admin approve <slug> Approve a plugin (admin only)
9892
- admin reject <slug> [--reason] Reject a plugin (admin only)
9893
- admin feature <slug> Toggle featured (admin only)
9894
- admin remove <slug> Remove a plugin (admin only)
9895
- admin stats Dashboard stats (admin only)
9896
- admin inventory Plugin inventory (admin only)
9897
- admin list [--status <status>] List all plugins (admin only)
9898
- admin bulk-approve <slugs...> Bulk approve (admin only)
9899
- admin cleanup Reset data (admin only)
9900
-
9901
10108
  Plugin Commands:
9902
10109
  Installed plugins provide additional commands.
9903
10110
  Use 'xbrowser plugin list' to see installed plugins and their commands.
@@ -10260,19 +10467,19 @@ function headersToObject(headers) {
10260
10467
  return result;
10261
10468
  }
10262
10469
  function readBody(req) {
10263
- return new Promise((resolve15, reject) => {
10470
+ return new Promise((resolve16, reject) => {
10264
10471
  const chunks = [];
10265
10472
  req.on("data", (chunk) => chunks.push(chunk));
10266
10473
  req.on("end", () => {
10267
10474
  const raw = Buffer.concat(chunks).toString("utf-8");
10268
10475
  if (!raw) {
10269
- resolve15(null);
10476
+ resolve16(null);
10270
10477
  return;
10271
10478
  }
10272
10479
  try {
10273
- resolve15(JSON.parse(raw));
10480
+ resolve16(JSON.parse(raw));
10274
10481
  } catch {
10275
- resolve15(null);
10482
+ resolve16(null);
10276
10483
  }
10277
10484
  });
10278
10485
  req.on("error", reject);
@@ -10317,7 +10524,7 @@ var HTTPServer = class {
10317
10524
  res.end(JSON.stringify({ error: "INTERNAL_ERROR", message, statusCode: 500 }));
10318
10525
  });
10319
10526
  });
10320
- return new Promise((resolve15, reject) => {
10527
+ return new Promise((resolve16, reject) => {
10321
10528
  const server = this.server;
10322
10529
  server.on("error", (err) => {
10323
10530
  this.server = null;
@@ -10329,7 +10536,7 @@ var HTTPServer = class {
10329
10536
  this.port = addr.port;
10330
10537
  }
10331
10538
  console.log(`HTTP server listening on http://${this.host}:${this.port}`);
10332
- resolve15({ port: this.port, host: this.host });
10539
+ resolve16({ port: this.port, host: this.host });
10333
10540
  });
10334
10541
  });
10335
10542
  }
@@ -10340,13 +10547,13 @@ var HTTPServer = class {
10340
10547
  */
10341
10548
  async stop() {
10342
10549
  if (!this.server) return;
10343
- return new Promise((resolve15, reject) => {
10550
+ return new Promise((resolve16, reject) => {
10344
10551
  this.server.close((err) => {
10345
10552
  if (err) {
10346
10553
  reject(err);
10347
10554
  } else {
10348
10555
  this.server = null;
10349
- resolve15();
10556
+ resolve16();
10350
10557
  }
10351
10558
  });
10352
10559
  });