@xbrowser/cli 1.2.2 → 1.3.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.
@@ -21,12 +21,12 @@ import {
21
21
  resolveLaunchOpts,
22
22
  saveSessionDiskMeta,
23
23
  setActivePage
24
- } from "./chunk-SLQR57XZ.js";
25
- import "./chunk-QFROODUU.js";
24
+ } from "./chunk-7OGKQWXE.js";
25
+ import "./chunk-N4PIGZDG.js";
26
26
  import "./chunk-TNEN6VQ2.js";
27
27
  import {
28
28
  getPluginLoader
29
- } from "./chunk-PHBK3TRN.js";
29
+ } from "./chunk-2QQDTXDL.js";
30
30
  import {
31
31
  getDaemonConfig,
32
32
  getDaemonProcessStatus
@@ -54,7 +54,7 @@ import {
54
54
  // src/executor.ts
55
55
  import {
56
56
  ok as ok25,
57
- fail as fail7,
57
+ fail as fail8,
58
58
  isCommandResult,
59
59
  CompositeStorage as CompositeStorage2,
60
60
  TipCollector as TipCollector2,
@@ -224,7 +224,7 @@ var NoopSiteInstance = class {
224
224
 
225
225
  // src/commands/navigation.ts
226
226
  import { z } from "zod";
227
- import { ok } from "@dyyz1993/xcli-core";
227
+ import { ok, fail } from "@dyyz1993/xcli-core";
228
228
 
229
229
  // src/commands/command-registry.ts
230
230
  var registry = /* @__PURE__ */ new Map();
@@ -313,13 +313,19 @@ var gotoCommand = registerCommand({
313
313
  if (/^[\w-]+(\.[\w-]+)+/.test(url) || url.startsWith("localhost")) {
314
314
  url = "https://" + url;
315
315
  } else {
316
- throw new Error(`Invalid URL: "${url}". Expected http(s)://, file://, about:, data:, or a domain name.`);
316
+ return fail(`Invalid URL: "${url}". Expected http(s)://, file://, about:, data:, or a domain name.`);
317
317
  }
318
318
  }
319
- const response = await ctx.page.goto(url, {
320
- waitUntil: p.waitUntil || "domcontentloaded",
321
- ...p.timeout ? { timeout: p.timeout } : {}
322
- });
319
+ let response;
320
+ try {
321
+ response = await ctx.page.goto(url, {
322
+ waitUntil: p.waitUntil || "domcontentloaded",
323
+ ...p.timeout ? { timeout: p.timeout } : {}
324
+ });
325
+ } catch (err) {
326
+ const msg = err instanceof Error ? err.message : String(err);
327
+ return fail(`Navigation failed: ${msg}`);
328
+ }
323
329
  const ssr = await detectSsr(ctx.page);
324
330
  return ok({ url, status: response?.status(), ...ssr ? { ssr } : {} });
325
331
  }
@@ -634,6 +640,22 @@ var checkCommand = registerCommand({
634
640
  return ok2({ selector: p.selector });
635
641
  }
636
642
  });
643
+ var uncheckCommand = registerCommand({
644
+ name: "uncheck",
645
+ description: "Uncheck checkbox or radio",
646
+ scope: "element",
647
+ selectorParams: ["selector"],
648
+ parameters: z2.object({
649
+ selector: z2.string()
650
+ }),
651
+ result: z2.object({
652
+ selector: z2.string()
653
+ }),
654
+ handler: async (p, ctx) => {
655
+ await ctx.page.uncheck(p.selector, { timeout: 1e4 });
656
+ return ok2({ selector: p.selector });
657
+ }
658
+ });
637
659
  var hoverCommand = registerCommand({
638
660
  name: "hover",
639
661
  description: "Hover over element",
@@ -1175,7 +1197,7 @@ var setViewportCommand = registerCommand({
1175
1197
 
1176
1198
  // src/commands/frame.ts
1177
1199
  import { z as z12 } from "zod";
1178
- import { ok as ok12, fail } from "@dyyz1993/xcli-core";
1200
+ import { ok as ok12, fail as fail2 } from "@dyyz1993/xcli-core";
1179
1201
  var framesCommand = registerCommand({
1180
1202
  name: "frames",
1181
1203
  description: "List all frames in the current page",
@@ -1188,7 +1210,9 @@ var framesCommand = registerCommand({
1188
1210
  }))
1189
1211
  }),
1190
1212
  handler: async (_p, ctx) => {
1191
- const frameList = ctx.page.frames().map((frame, index) => ({
1213
+ const discover = ctx.page.discoverFrames;
1214
+ const rawFrames = discover ? await discover.call(ctx.page) : ctx.page.frames();
1215
+ const frameList = rawFrames.map((frame, index) => ({
1192
1216
  index,
1193
1217
  name: frame.name(),
1194
1218
  url: frame.url()
@@ -1210,17 +1234,18 @@ var frameCommand = registerCommand({
1210
1234
  error: z12.string().optional()
1211
1235
  }),
1212
1236
  handler: async (p, ctx) => {
1213
- const allFrames = ctx.page.frames();
1237
+ const discover = ctx.page.discoverFrames;
1238
+ const rawFrames = discover ? await discover.call(ctx.page) : ctx.page.frames();
1214
1239
  let targetFrame;
1215
1240
  if (p.index !== void 0) {
1216
- targetFrame = allFrames[p.index];
1241
+ targetFrame = rawFrames[p.index];
1217
1242
  } else if (p.name !== void 0) {
1218
- targetFrame = allFrames.find((f) => f.name() === p.name);
1243
+ targetFrame = rawFrames.find((f) => f.name() === p.name);
1219
1244
  } else {
1220
- return fail("Must provide index or name");
1245
+ return fail2("Must provide index or name");
1221
1246
  }
1222
1247
  if (!targetFrame) {
1223
- return fail("Frame not found");
1248
+ return fail2("Frame not found");
1224
1249
  }
1225
1250
  return ok12({
1226
1251
  name: targetFrame.name(),
@@ -1866,7 +1891,7 @@ var actionsCommand = registerCommand({
1866
1891
 
1867
1892
  // src/commands/scrape.ts
1868
1893
  import { z as z15 } from "zod";
1869
- import { ok as ok15, fail as fail2 } from "@dyyz1993/xcli-core";
1894
+ import { ok as ok15, fail as fail3 } from "@dyyz1993/xcli-core";
1870
1895
 
1871
1896
  // src/lib/html-to-markdown.ts
1872
1897
  import * as cheerio from "cheerio";
@@ -2382,7 +2407,7 @@ var scrapeCommand = registerCommand({
2382
2407
  }
2383
2408
  }
2384
2409
  }
2385
- return fail2(`Scrape failed after ${maxAttempts} attempt(s): ${lastError?.message ?? "unknown error"}`);
2410
+ return fail3(`Scrape failed after ${maxAttempts} attempt(s): ${lastError?.message ?? "unknown error"}`);
2386
2411
  } finally {
2387
2412
  await closeEphemeralContext(context);
2388
2413
  }
@@ -3446,7 +3471,7 @@ ${errors.map((e) => ` - ${e.engine}: ${e.error}`).join("\n")}`
3446
3471
 
3447
3472
  // src/commands/network.ts
3448
3473
  import { z as z19 } from "zod";
3449
- import { ok as ok19, fail as fail3 } from "@dyyz1993/xcli-core";
3474
+ import { ok as ok19, fail as fail4 } from "@dyyz1993/xcli-core";
3450
3475
  function extractPath2(url) {
3451
3476
  try {
3452
3477
  const u = new URL(url);
@@ -3611,7 +3636,7 @@ var networkCommand = registerCommand({
3611
3636
  };
3612
3637
  if (p.listen) {
3613
3638
  const page2 = ctx.page;
3614
- if (!page2) return fail3("No active page. Use --cdp to connect first.");
3639
+ if (!page2) return fail4("No active page. Use --cdp to connect first.");
3615
3640
  const captures = [];
3616
3641
  const consoleMessages = [];
3617
3642
  const wsCaptures = [];
@@ -3991,7 +4016,7 @@ var ENGINE_KEY_ENUM = z20.enum(ALL_ENGINE_KEYS);
3991
4016
 
3992
4017
  // src/commands/snapshot.ts
3993
4018
  import { z as z21 } from "zod";
3994
- import { ok as ok20, fail as fail4, normalizeTips as normalizeTips3 } from "@dyyz1993/xcli-core";
4019
+ import { ok as ok20, fail as fail5, normalizeTips as normalizeTips3 } from "@dyyz1993/xcli-core";
3995
4020
 
3996
4021
  // src/runtime/ref-store.ts
3997
4022
  var sessions = /* @__PURE__ */ new Map();
@@ -4947,7 +4972,7 @@ var snapshotCommand = registerCommand({
4947
4972
  persistSemantics(url, aria);
4948
4973
  return ok20({ url, title, aria, text, dom }, normalizeTips3(tips));
4949
4974
  }
4950
- return fail4(`Unknown snapshot type: ${p.type}`);
4975
+ return fail5(`Unknown snapshot type: ${p.type}`);
4951
4976
  }
4952
4977
  });
4953
4978
  function persistSemantics(url, aria) {
@@ -5116,7 +5141,7 @@ var waitForCommand = registerCommand({
5116
5141
 
5117
5142
  // src/commands/tab.ts
5118
5143
  import { z as z23 } from "zod";
5119
- import { ok as ok22, fail as fail5 } from "@dyyz1993/xcli-core";
5144
+ import { ok as ok22, fail as fail6 } from "@dyyz1993/xcli-core";
5120
5145
  var TabParams = z23.object({
5121
5146
  subcommand: z23.enum(["list", "new", "close", "switch"]),
5122
5147
  url: z23.string().optional(),
@@ -5143,7 +5168,7 @@ var tabCommand = registerCommand({
5143
5168
  case "switch":
5144
5169
  return handleSwitch(p, pages, ctx);
5145
5170
  default:
5146
- return fail5(`Unknown subcommand: ${p.subcommand}`);
5171
+ return fail6(`Unknown subcommand: ${p.subcommand}`);
5147
5172
  }
5148
5173
  }
5149
5174
  });
@@ -5200,11 +5225,11 @@ async function handleNew(p, _pages, ctx) {
5200
5225
  }
5201
5226
  async function handleClose(p, pages, ctx) {
5202
5227
  if (pages.length <= 1) {
5203
- return fail5("Cannot close the last remaining tab");
5228
+ return fail6("Cannot close the last remaining tab");
5204
5229
  }
5205
5230
  const closeIndex = p.index ?? pages.indexOf(ctx.page);
5206
5231
  if (closeIndex < 0 || closeIndex >= pages.length) {
5207
- return fail5(`Invalid tab index: ${closeIndex}. Valid range: 0-${pages.length - 1}`);
5232
+ return fail6(`Invalid tab index: ${closeIndex}. Valid range: 0-${pages.length - 1}`);
5208
5233
  }
5209
5234
  const pageToClose = pages[closeIndex];
5210
5235
  const isActivePage = pageToClose === ctx.page;
@@ -5227,10 +5252,10 @@ async function handleClose(p, pages, ctx) {
5227
5252
  }
5228
5253
  async function handleSwitch(p, pages, ctx) {
5229
5254
  if (p.index === void 0) {
5230
- return fail5("Parameter --index is required for switch subcommand");
5255
+ return fail6("Parameter --index is required for switch subcommand");
5231
5256
  }
5232
5257
  if (p.index < 0 || p.index >= pages.length) {
5233
- return fail5(`Invalid tab index: ${p.index}. Valid range: 0-${pages.length - 1}`);
5258
+ return fail6(`Invalid tab index: ${p.index}. Valid range: 0-${pages.length - 1}`);
5234
5259
  }
5235
5260
  const targetPage = pages[p.index];
5236
5261
  await targetPage.bringToFront().catch(() => {
@@ -5476,7 +5501,7 @@ registerCommandDefinition("addinitscript", ["script"]);
5476
5501
 
5477
5502
  // src/commands/find.ts
5478
5503
  import { z as z25 } from "zod";
5479
- import { ok as ok24, fail as fail6, normalizeTips as normalizeTips5 } from "@dyyz1993/xcli-core";
5504
+ import { ok as ok24, fail as fail7, normalizeTips as normalizeTips5 } from "@dyyz1993/xcli-core";
5480
5505
  var actionSchema2 = z25.enum(["click", "fill", "type", "select", "hover", "check"]);
5481
5506
  var findCommand = registerCommand({
5482
5507
  name: "find",
@@ -5517,7 +5542,7 @@ var findCommand = registerCommand({
5517
5542
  });
5518
5543
  const count = await locator.count();
5519
5544
  if (count === 0) {
5520
- return fail6(`No element found with ${p.strategy}="${p.value}"`);
5545
+ return fail7(`No element found with ${p.strategy}="${p.value}"`);
5521
5546
  }
5522
5547
  const tips = [];
5523
5548
  const target = selectTarget(locator, p.strategy);
@@ -5529,15 +5554,15 @@ var findCommand = registerCommand({
5529
5554
  await target.click({ timeout: p.timeout, force: true });
5530
5555
  return okWithTips({ matched: count, selector, action: "click" }, tips);
5531
5556
  } else if (actionName === "fill") {
5532
- if (actionValue === void 0) return fail6("find fill requires a value");
5557
+ if (actionValue === void 0) return fail7("find fill requires a value");
5533
5558
  await target.fill(actionValue, { timeout: p.timeout, force: true });
5534
5559
  return okWithTips({ matched: count, selector, action: `fill("${actionValue}")` }, tips);
5535
5560
  } else if (actionName === "type") {
5536
- if (actionValue === void 0) return fail6("find type requires a value");
5561
+ if (actionValue === void 0) return fail7("find type requires a value");
5537
5562
  await target.type(actionValue, { delay: 10, timeout: p.timeout });
5538
5563
  return okWithTips({ matched: count, selector, action: `type("${actionValue}")` }, tips);
5539
5564
  } else if (actionName === "select") {
5540
- if (actionValue === void 0) return fail6("find select requires a value");
5565
+ if (actionValue === void 0) return fail7("find select requires a value");
5541
5566
  await target.selectOption(actionValue);
5542
5567
  return okWithTips({ matched: count, selector, action: `select("${actionValue}")` }, tips);
5543
5568
  } else if (actionName === "hover") {
@@ -6531,7 +6556,7 @@ async function guardCheck(commandName) {
6531
6556
  }
6532
6557
  }
6533
6558
  function errorResult(message) {
6534
- return { ...fail7(message), duration: 0 };
6559
+ return { ...fail8(message), duration: 0 };
6535
6560
  }
6536
6561
  function tipsToMessages(tips) {
6537
6562
  if (!tips || tips.length === 0) return [];
@@ -6564,7 +6589,7 @@ async function executeCommand(commandName, params, sessionName = "default", extr
6564
6589
  }
6565
6590
  let targetPageOverride = null;
6566
6591
  if (_target && extraOpts?.cdpEndpoint) {
6567
- const { findTargetPage } = await import("./browser-CWI6BXYK.js");
6592
+ const { findTargetPage } = await import("./browser-ALV2PLW4.js");
6568
6593
  targetPageOverride = await findTargetPage(extraOpts.cdpEndpoint, _target);
6569
6594
  if (!targetPageOverride) {
6570
6595
  return errorResult(`Target "${_target}" not found. Use 'xbrowser targets --cdp ${extraOpts.cdpEndpoint}' to list available pages.`);
@@ -6768,7 +6793,7 @@ async function executeCommand(commandName, params, sessionName = "default", extr
6768
6793
  duration,
6769
6794
  timestamp: start
6770
6795
  });
6771
- return { ...fail7(errorMessage), duration };
6796
+ return { ...fail8(errorMessage), duration };
6772
6797
  } finally {
6773
6798
  }
6774
6799
  }
@@ -6809,7 +6834,7 @@ async function executeChain(input, options) {
6809
6834
  results.push({
6810
6835
  command: cmdName,
6811
6836
  raw: cmdStr,
6812
- ...fail7(`Plugin "${cmdName}" requires a sub-command`),
6837
+ ...fail8(`Plugin "${cmdName}" requires a sub-command`),
6813
6838
  duration: 0
6814
6839
  });
6815
6840
  if (type === "and") {
@@ -6828,7 +6853,7 @@ async function executeChain(input, options) {
6828
6853
  results.push({
6829
6854
  command: cmdName,
6830
6855
  raw: cmdStr,
6831
- ...fail7(`Unknown command "${subCommand}" for plugin "${cmdName}"`),
6856
+ ...fail8(`Unknown command "${subCommand}" for plugin "${cmdName}"`),
6832
6857
  duration: 0
6833
6858
  });
6834
6859
  if (type === "and") {
@@ -6960,7 +6985,7 @@ async function executeChain(input, options) {
6960
6985
  results.push({
6961
6986
  command: `${cmdName} ${subCommand}`,
6962
6987
  raw: cmdStr,
6963
- ...fail7(errorMessage),
6988
+ ...fail8(errorMessage),
6964
6989
  duration: duration2
6965
6990
  });
6966
6991
  if (type === "and") {
@@ -7863,9 +7888,9 @@ function createRPCHandler() {
7863
7888
  return result;
7864
7889
  }
7865
7890
  async function handlePluginsReload() {
7866
- const { resetPluginLoader } = await import("./plugin-singleton-ZBVTWEYK.js");
7891
+ const { resetPluginLoader } = await import("./plugin-singleton-SYJF6BD6.js");
7867
7892
  resetPluginLoader();
7868
- const loader = await import("./plugin-singleton-ZBVTWEYK.js").then((m) => m.getPluginLoader());
7893
+ const loader = await import("./plugin-singleton-SYJF6BD6.js").then((m) => m.getPluginLoader());
7869
7894
  const sites = loader.getCore().loader.getSites();
7870
7895
  return { ok: true, plugins: sites.length };
7871
7896
  }
@@ -8280,7 +8305,7 @@ function createRPCHandler() {
8280
8305
  const isNewFormat = Array.isArray(parsed.actions);
8281
8306
  if (isNewFormat) {
8282
8307
  try {
8283
- const { SessionReplayer } = await import("./session-replayer-IXLSCF5U.js");
8308
+ const { SessionReplayer } = await import("./session-replayer-JIVFXVUL.js");
8284
8309
  const replayer = new SessionReplayer({
8285
8310
  page: session.page,
8286
8311
  stepDelay: slowMo * 500,
@@ -6,9 +6,10 @@ import * as yaml from "yaml";
6
6
  function extractRecording(filePath) {
7
7
  const content = fs.readFileSync(filePath, "utf-8");
8
8
  const recording = yaml.parse(content);
9
+ const events = recording.actions || recording.events || [];
9
10
  const keyEvents = [];
10
11
  const eventTypes = {};
11
- for (const event of recording.events || []) {
12
+ for (const event of events) {
12
13
  const type = event.type;
13
14
  eventTypes[type] = (eventTypes[type] || 0) + 1;
14
15
  if (["click", "input", "type", "keydown", "keypress", "hover", "hover_enter", "hover_leave"].includes(type)) {
@@ -27,7 +28,7 @@ function extractRecording(filePath) {
27
28
  }
28
29
  return {
29
30
  startUrl: recording.startUrl,
30
- totalEvents: (recording.events || []).length,
31
+ totalEvents: events.length,
31
32
  keyEventsCount: keyEvents.length,
32
33
  eventTypes,
33
34
  operations: keyEvents.map((e, i) => ({
@@ -2,7 +2,7 @@ import {
2
2
  extractAndSave,
3
3
  extractRecording,
4
4
  printExtractSummary
5
- } from "./chunk-L53IDAWK.js";
5
+ } from "./chunk-MJFYLKGL.js";
6
6
  import "./chunk-KFQGP6VL.js";
7
7
  export {
8
8
  extractAndSave,
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  filterRecording,
3
3
  parseExcludeTypes
4
- } from "./chunk-AT4PHAJY.js";
4
+ } from "./chunk-GJAV3QGG.js";
5
5
  import "./chunk-KFQGP6VL.js";
6
6
  export {
7
7
  filterRecording,
@@ -26,9 +26,9 @@ var DEFAULT_EXCLUDE_TYPES = [
26
26
  function filterRecording(inputPath, outputPath, excludeTypes) {
27
27
  const content = fs.readFileSync(inputPath, "utf-8");
28
28
  const recording = yaml.parse(content);
29
- const exclude = excludeTypes || DEFAULT_EXCLUDE_TYPES;
30
- const events = recording.events || [];
29
+ const events = recording.actions || recording.events || [];
31
30
  const originalCount = events.length;
31
+ const exclude = excludeTypes || DEFAULT_EXCLUDE_TYPES;
32
32
  const filteredEvents = events.filter((event) => {
33
33
  return !exclude.includes(event.type);
34
34
  });
package/dist/index.d.ts CHANGED
@@ -1497,6 +1497,16 @@ declare class PluginInstaller {
1497
1497
  * @throws If the plugin already exists without `force`, or if installation fails.
1498
1498
  */
1499
1499
  install(source: string, options?: InstallOptions): Promise<InstalledPlugin>;
1500
+ /**
1501
+ * Fix missing `../shared/` dependencies after installation.
1502
+ *
1503
+ * Some marketplace/npm packages import from `../shared/` (e.g. ssr-detect.js,
1504
+ * ai-chat-base.ts) but the `shared/` directory is not included in the package.
1505
+ * This method scans the installed plugin's index.ts for such imports and
1506
+ * copies the missing files from the local repository's `.xcli/plugins/shared/`
1507
+ * directory (if available).
1508
+ */
1509
+ private fixSharedDeps;
1500
1510
  installFromMarketplace(slug: string, options?: InstallOptions): Promise<InstalledPlugin>;
1501
1511
  installWithMarketplaceFallback(source: string, options?: InstallOptions): Promise<InstalledPlugin>;
1502
1512
  /**