@xbrowser/cli 1.0.2 → 1.0.4

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,25 +21,28 @@ import {
21
21
  resolveLaunchOpts,
22
22
  saveSessionDiskMeta,
23
23
  setActivePage
24
- } from "./chunk-QIK2I3VQ.js";
25
- import "./chunk-PPG4D2EW.js";
26
- import "./chunk-BBMRDUYQ.js";
24
+ } from "./chunk-LRBSUKUZ.js";
25
+ import "./chunk-N2JFPWMI.js";
26
+ import "./chunk-TNEN6VQ2.js";
27
27
  import {
28
28
  getDaemonConfig,
29
29
  getDaemonProcessStatus
30
30
  } from "./chunk-WJRE55TN.js";
31
+ import {
32
+ errMsg
33
+ } from "./chunk-GDKLH7ZY.js";
31
34
  import "./chunk-KFQGP6VL.js";
32
35
 
33
36
  // src/daemon/daemon-main.ts
34
37
  import { writeFileSync as writeFileSync8, mkdirSync as mkdirSync7, appendFileSync } from "fs";
35
- import { join as join8 } from "path";
36
- import { homedir as homedir8 } from "os";
38
+ import { join as join9 } from "path";
39
+ import { homedir as homedir9 } from "os";
37
40
  import { startHttpServer } from "@dyyz1993/xcli-core";
38
41
 
39
42
  // src/daemon/rpc-handlers.ts
40
43
  import { writeFileSync as writeFileSync7, mkdirSync as mkdirSync6, readFileSync as readFileSync6 } from "fs";
41
- import { join as join7 } from "path";
42
- import { homedir as homedir7 } from "os";
44
+ import { join as join8 } from "path";
45
+ import { homedir as homedir8 } from "os";
43
46
  import {
44
47
  createSessionMeta,
45
48
  removeSession
@@ -50,8 +53,8 @@ import {
50
53
  ok as ok25,
51
54
  fail as fail7,
52
55
  isCommandResult,
53
- CompositeStorage,
54
- TipCollector,
56
+ CompositeStorage as CompositeStorage2,
57
+ TipCollector as TipCollector2,
55
58
  normalizeTips as normalizeTips6,
56
59
  configureArchiveStore,
57
60
  appendCommandToArchive,
@@ -169,6 +172,53 @@ function parsePluginParams(args, schema, base = {}) {
169
172
  return result;
170
173
  }
171
174
 
175
+ // src/utils/stub-context.ts
176
+ import { join } from "path";
177
+ import { homedir } from "os";
178
+ import { TipCollector, CompositeStorage } from "@dyyz1993/xcli-core";
179
+ var CONFIG_DIR = join(homedir(), ".xbrowser");
180
+ var NoopSiteInstance = class {
181
+ name = "stub";
182
+ url = "";
183
+ config = { name: "stub" };
184
+ command() {
185
+ return this;
186
+ }
187
+ group() {
188
+ return this;
189
+ }
190
+ login() {
191
+ return this;
192
+ }
193
+ logout() {
194
+ return this;
195
+ }
196
+ async isLoggedIn() {
197
+ return true;
198
+ }
199
+ async requireLogin() {
200
+ }
201
+ getStorage() {
202
+ return new CompositeStorage("stub", CONFIG_DIR, "xbrowser");
203
+ }
204
+ getAllCommands() {
205
+ return [];
206
+ }
207
+ getCommand() {
208
+ return null;
209
+ }
210
+ getOriginalHandler() {
211
+ return void 0;
212
+ }
213
+ async executeLogin() {
214
+ }
215
+ async executeLogout() {
216
+ }
217
+ async restoreLogin() {
218
+ return false;
219
+ }
220
+ };
221
+
172
222
  // src/commands/navigation.ts
173
223
  import { z } from "zod";
174
224
  import { ok } from "@dyyz1993/xcli-core";
@@ -216,7 +266,7 @@ async function detectSsr(page) {
216
266
  try {
217
267
  const result = await page.evaluate((vars) => {
218
268
  for (const varName of vars) {
219
- const value = window[varName];
269
+ const value = Reflect.get(window, varName);
220
270
  if (value != null && typeof value === "object") {
221
271
  const keys = Object.keys(value).slice(0, 10);
222
272
  return { variable: varName, keys };
@@ -932,9 +982,9 @@ var clearLocalStorageCommand = registerCommand({
932
982
  import { z as z9 } from "zod";
933
983
  import { ok as ok9 } from "@dyyz1993/xcli-core";
934
984
  import { writeFileSync, mkdirSync } from "fs";
935
- import { join } from "path";
936
- import { homedir } from "os";
937
- var SCREENSHOTS_DIR = join(homedir(), ".xbrowser", "screenshots");
985
+ import { join as join2 } from "path";
986
+ import { homedir as homedir2 } from "os";
987
+ var SCREENSHOTS_DIR = join2(homedir2(), ".xbrowser", "screenshots");
938
988
  function ensureScreenshotsDir() {
939
989
  mkdirSync(SCREENSHOTS_DIR, { recursive: true });
940
990
  }
@@ -942,7 +992,7 @@ function generateScreenshotPath(format) {
942
992
  const timestamp = Date.now();
943
993
  const random = Math.random().toString(36).slice(2, 8);
944
994
  const ext = format === "jpeg" ? "jpg" : "png";
945
- return join(SCREENSHOTS_DIR, `screenshot-${timestamp}-${random}.${ext}`);
995
+ return join2(SCREENSHOTS_DIR, `screenshot-${timestamp}-${random}.${ext}`);
946
996
  }
947
997
  var screenshotCommand = registerCommand({
948
998
  name: "screenshot",
@@ -1565,7 +1615,7 @@ var healthCheckCommand = registerCommand({
1565
1615
  issues.push({
1566
1616
  severity: "error",
1567
1617
  category: "links",
1568
- message: `Broken link (fetch error): ${href} \u2014 ${err.message || "unknown"}`
1618
+ message: `Broken link (fetch error): ${href} \u2014 ${errMsg(err) || "unknown"}`
1569
1619
  });
1570
1620
  }
1571
1621
  }
@@ -1599,9 +1649,9 @@ var healthCheckCommand = registerCommand({
1599
1649
  import { z as z14 } from "zod";
1600
1650
  import { ok as ok14 } from "@dyyz1993/xcli-core";
1601
1651
  import { writeFileSync as writeFileSync2, mkdirSync as mkdirSync2 } from "fs";
1602
- import { join as join2 } from "path";
1603
- import { homedir as homedir2 } from "os";
1604
- var SCREENSHOTS_DIR2 = join2(homedir2(), ".xbrowser", "screenshots");
1652
+ import { join as join3 } from "path";
1653
+ import { homedir as homedir3 } from "os";
1654
+ var SCREENSHOTS_DIR2 = join3(homedir3(), ".xbrowser", "screenshots");
1605
1655
  function ensureScreenshotsDir2() {
1606
1656
  mkdirSync2(SCREENSHOTS_DIR2, { recursive: true });
1607
1657
  }
@@ -1609,7 +1659,7 @@ function generateScreenshotPath2(format) {
1609
1659
  const timestamp = Date.now();
1610
1660
  const random = Math.random().toString(36).slice(2, 8);
1611
1661
  const ext = format === "jpeg" ? "jpg" : "png";
1612
- return join2(SCREENSHOTS_DIR2, `screenshot-${timestamp}-${random}.${ext}`);
1662
+ return join3(SCREENSHOTS_DIR2, `screenshot-${timestamp}-${random}.${ext}`);
1613
1663
  }
1614
1664
  var waitActionSchema = z14.object({
1615
1665
  type: z14.literal("wait"),
@@ -4111,8 +4161,8 @@ async function resolveRefParams(page, params, selectorKeys, cache, sessionId) {
4111
4161
 
4112
4162
  // src/utils/site-semantics.ts
4113
4163
  import { writeFileSync as writeFileSync3, mkdirSync as mkdirSync3, existsSync, readFileSync } from "fs";
4114
- import { join as join3, dirname } from "path";
4115
- import { homedir as homedir3 } from "os";
4164
+ import { join as join4, dirname } from "path";
4165
+ import { homedir as homedir4 } from "os";
4116
4166
  import { stringify, parse } from "yaml";
4117
4167
  import { execFile } from "child_process";
4118
4168
  var INTERACTIVE_ROLES = /* @__PURE__ */ new Set([
@@ -4189,10 +4239,10 @@ function inferAction(role, label) {
4189
4239
  return {};
4190
4240
  }
4191
4241
  function getSemanticsDir() {
4192
- return join3(homedir3(), ".xbrowser", "site-semantics");
4242
+ return join4(homedir4(), ".xbrowser", "site-semantics");
4193
4243
  }
4194
4244
  function getSemanticsPath(domain) {
4195
- return join3(getSemanticsDir(), `${domain}.yaml`);
4245
+ return join4(getSemanticsDir(), `${domain}.yaml`);
4196
4246
  }
4197
4247
  function extractDomain2(url) {
4198
4248
  try {
@@ -4664,7 +4714,7 @@ async function actOnPage(page, sessionId, input) {
4664
4714
  ref: normalizedRef,
4665
4715
  success: false,
4666
4716
  reason: "browser_error",
4667
- message: error.message,
4717
+ message: errMsg(error),
4668
4718
  stale,
4669
4719
  screenHash: hash,
4670
4720
  target: refMatch?.target
@@ -4748,7 +4798,7 @@ async function waitForPage(page, input) {
4748
4798
  matched: input.selector ? "selector" : input.text ? "text" : input.url ? "url" : input.load ? "load" : input.fn ? "fn" : "screenHashChanged",
4749
4799
  timeout,
4750
4800
  elapsed: Date.now() - startedAt,
4751
- message: error.message
4801
+ message: errMsg(error)
4752
4802
  };
4753
4803
  }
4754
4804
  return {
@@ -5683,11 +5733,11 @@ async function detectWebdriverExposure(page) {
5683
5733
  try {
5684
5734
  const webdriver = await page.evaluate(() => {
5685
5735
  return {
5686
- webdriver: window.navigator && window.navigator instanceof Object ? window.navigator.webdriver : void 0,
5736
+ webdriver: navigator.webdriver,
5687
5737
  webdriverScriptFn: !!window.__webdriver_script_fn,
5688
5738
  webdriverEvaluate: !!window.__webdriver_evaluate,
5689
5739
  chrome: !!window.chrome,
5690
- permissions: window.navigator && window.navigator instanceof Object ? window.navigator.permissions : void 0
5740
+ permissions: navigator.permissions
5691
5741
  };
5692
5742
  }).catch(() => null);
5693
5743
  if (!webdriver) {
@@ -5773,7 +5823,7 @@ import {
5773
5823
  } from "@dyyz1993/xcli-core";
5774
5824
  import { resolve as resolve2 } from "path";
5775
5825
  import { existsSync as existsSync4, readdirSync } from "fs";
5776
- import { homedir as homedir4 } from "os";
5826
+ import { homedir as homedir5 } from "os";
5777
5827
 
5778
5828
  // src/plugin/metadata-parser.ts
5779
5829
  import { existsSync as existsSync2 } from "fs";
@@ -5860,17 +5910,17 @@ var PluginMetadataParser = class {
5860
5910
 
5861
5911
  // src/plugin/ensure-deps.ts
5862
5912
  import { existsSync as existsSync3, mkdirSync as mkdirSync4, writeFileSync as writeFileSync5 } from "fs";
5863
- import { join as join4 } from "path";
5913
+ import { join as join5 } from "path";
5864
5914
  import { execSync } from "child_process";
5865
5915
  var SHARED_PLUGIN_DEPENDENCIES = {
5866
5916
  "zod": "^3.24.0",
5867
5917
  "@dyyz1993/xcli-core": "^0.12.1"
5868
5918
  };
5869
5919
  function ensurePluginDependencies(pluginsDir) {
5870
- const zodPath = join4(pluginsDir, "node_modules", "zod");
5920
+ const zodPath = join5(pluginsDir, "node_modules", "zod");
5871
5921
  if (existsSync3(zodPath)) return;
5872
5922
  mkdirSync4(pluginsDir, { recursive: true });
5873
- const pkgPath = join4(pluginsDir, "package.json");
5923
+ const pkgPath = join5(pluginsDir, "package.json");
5874
5924
  let pkg = {};
5875
5925
  if (existsSync3(pkgPath)) {
5876
5926
  try {
@@ -5886,7 +5936,7 @@ function ensurePluginDependencies(pluginsDir) {
5886
5936
  needsInstall = true;
5887
5937
  }
5888
5938
  }
5889
- if (!needsInstall && existsSync3(join4(pluginsDir, "node_modules"))) return;
5939
+ if (!needsInstall && existsSync3(join5(pluginsDir, "node_modules"))) return;
5890
5940
  pkg.dependencies = existingDeps;
5891
5941
  pkg.private = true;
5892
5942
  pkg.description = pkg.description || "xbrowser plugins \u2014 shared dependencies";
@@ -6047,19 +6097,26 @@ var patched = false;
6047
6097
  function patchLoginRequired() {
6048
6098
  if (patched) return;
6049
6099
  patched = true;
6050
- const proto = SiteInstanceImpl.prototype;
6051
- const original = proto.command;
6052
- proto.command = function(name, cmd) {
6053
- const result = original.call(this, name, cmd);
6100
+ const target = SiteInstanceImpl.prototype;
6101
+ const originalCommand = target.command;
6102
+ const wrapped = function(...args) {
6103
+ const result = originalCommand.apply(this, args);
6104
+ const [name, cmd] = args;
6054
6105
  const loginRequired = cmd.loginRequired;
6055
6106
  if (loginRequired) {
6056
- const entry = this.commands.get(name);
6107
+ const commands = this.commands;
6108
+ const entry = commands?.get(name);
6057
6109
  if (entry) {
6058
6110
  entry.loginRequired = loginRequired;
6059
6111
  }
6060
6112
  }
6061
6113
  return result;
6062
6114
  };
6115
+ Object.defineProperty(target, "command", {
6116
+ value: wrapped,
6117
+ writable: true,
6118
+ configurable: true
6119
+ });
6063
6120
  }
6064
6121
 
6065
6122
  // src/plugin/loader.ts
@@ -6126,12 +6183,12 @@ var XBrowserPluginLoader = class {
6126
6183
  }
6127
6184
  async scanAndLoad() {
6128
6185
  const cwd = this.options.cwd || process.cwd();
6129
- const globalDir = this.options.globalDir || resolve2(homedir4(), ".xbrowser/plugins");
6186
+ const globalDir = this.options.globalDir || resolve2(homedir5(), ".xbrowser/plugins");
6130
6187
  ensurePluginDependencies(globalDir);
6131
6188
  const dirs = [
6132
6189
  resolve2(cwd, ".xcli/plugins"),
6133
6190
  resolve2(cwd, "../.xcli/plugins"),
6134
- this.options.userDir || resolve2(homedir4(), ".xcli/plugins"),
6191
+ this.options.userDir || resolve2(homedir5(), ".xcli/plugins"),
6135
6192
  globalDir
6136
6193
  ];
6137
6194
  const loaded = [];
@@ -6753,15 +6810,14 @@ var HOOK_REGISTRY = {
6753
6810
  recorder: {
6754
6811
  name: "recorder",
6755
6812
  onAfterCommand: async (ctx) => {
6756
- const ctxAny = ctx;
6757
- const logs = ctxAny.__commandLogs || [];
6813
+ const logs = ("__commandLogs" in ctx ? ctx.__commandLogs : void 0) || [];
6758
6814
  logs.push({
6759
6815
  timestamp: Date.now(),
6760
6816
  command: ctx.command,
6761
6817
  params: JSON.parse(JSON.stringify(ctx.params)),
6762
6818
  duration: ctx.duration
6763
6819
  });
6764
- ctxAny.__commandLogs = logs;
6820
+ Reflect.set(ctx, "__commandLogs", logs);
6765
6821
  return void 0;
6766
6822
  }
6767
6823
  }
@@ -6789,15 +6845,15 @@ async function loadHooks() {
6789
6845
  }
6790
6846
 
6791
6847
  // src/executor.ts
6792
- import { homedir as homedir5 } from "os";
6793
- import { join as join5 } from "path";
6848
+ import { homedir as homedir6 } from "os";
6849
+ import { join as join6 } from "path";
6794
6850
  var NAVIGATION_COMMANDS = /* @__PURE__ */ new Set(["goto", "back", "forward", "refresh"]);
6795
6851
  var snapshotHintShown = /* @__PURE__ */ new WeakSet();
6796
- var CONFIG_DIR = join5(homedir5(), ".xbrowser");
6852
+ var CONFIG_DIR2 = join6(homedir6(), ".xbrowser");
6797
6853
  var storageCache = /* @__PURE__ */ new Map();
6798
6854
  function getPluginStorage(pluginName) {
6799
6855
  if (!storageCache.has(pluginName)) {
6800
- storageCache.set(pluginName, new CompositeStorage(pluginName, CONFIG_DIR, "xbrowser"));
6856
+ storageCache.set(pluginName, new CompositeStorage2(pluginName, CONFIG_DIR2, "xbrowser"));
6801
6857
  }
6802
6858
  return storageCache.get(pluginName);
6803
6859
  }
@@ -6805,7 +6861,7 @@ var archiveInitialized = false;
6805
6861
  function ensureArchiveInit() {
6806
6862
  if (!archiveInitialized) {
6807
6863
  try {
6808
- configureArchiveStore({ archiveDir: join5(homedir5(), ".xbrowser", "archives") });
6864
+ configureArchiveStore({ archiveDir: join6(homedir6(), ".xbrowser", "archives") });
6809
6865
  } catch {
6810
6866
  }
6811
6867
  archiveInitialized = true;
@@ -6862,7 +6918,7 @@ async function executeCommand(commandName, params, sessionName = "default", extr
6862
6918
  }
6863
6919
  let targetPageOverride = null;
6864
6920
  if (_target && extraOpts?.cdpEndpoint) {
6865
- const { findTargetPage } = await import("./browser-GITRHHFO.js");
6921
+ const { findTargetPage } = await import("./browser-ITLZZDHJ.js");
6866
6922
  targetPageOverride = await findTargetPage(extraOpts.cdpEndpoint, _target);
6867
6923
  if (!targetPageOverride) {
6868
6924
  return errorResult(`Target "${_target}" not found. Use 'xbrowser targets --cdp ${extraOpts.cdpEndpoint}' to list available pages.`);
@@ -6879,7 +6935,7 @@ async function executeCommand(commandName, params, sessionName = "default", extr
6879
6935
  params = result.data;
6880
6936
  }
6881
6937
  if (command.scope !== "cli" && !process.env.XBROWSER_DAEMON_WORKER) {
6882
- const { forwardExec } = await import("./daemon-client-DRCUMNHK.js");
6938
+ const { forwardExec } = await import("./daemon-client-DIEHGP5B.js");
6883
6939
  const result = await forwardExec(commandName, params, sessionName, extraOpts?.cdpEndpoint);
6884
6940
  if (result) return result;
6885
6941
  }
@@ -6930,9 +6986,9 @@ async function executeCommand(commandName, params, sessionName = "default", extr
6930
6986
  throw new Error(msg);
6931
6987
  },
6932
6988
  config: {},
6933
- site: {},
6989
+ site: new NoopSiteInstance(),
6934
6990
  cliName: "xbrowser",
6935
- tips: new TipCollector()
6991
+ tips: new TipCollector2()
6936
6992
  };
6937
6993
  const start = Date.now();
6938
6994
  if (session) {
@@ -7045,7 +7101,7 @@ async function executeCommand(commandName, params, sessionName = "default", extr
7045
7101
  } catch (err) {
7046
7102
  const end = Date.now();
7047
7103
  const duration = end - start;
7048
- const errorMessage = err.message;
7104
+ const errorMessage = errMsg(err);
7049
7105
  if (session) {
7050
7106
  streamCommandEvent(session.id, {
7051
7107
  sessionId: session.id,
@@ -7158,7 +7214,7 @@ async function executeChain(input, options) {
7158
7214
  config: {},
7159
7215
  site,
7160
7216
  cliName: "xbrowser",
7161
- tips: new TipCollector()
7217
+ tips: new TipCollector2()
7162
7218
  };
7163
7219
  const start2 = Date.now();
7164
7220
  try {
@@ -7245,7 +7301,7 @@ async function executeChain(input, options) {
7245
7301
  }
7246
7302
  } catch (err) {
7247
7303
  const duration2 = Date.now() - start2;
7248
- const errorMessage = err.message;
7304
+ const errorMessage = errMsg(err);
7249
7305
  recordArchive(session.id, sessionName, {
7250
7306
  step: results.length,
7251
7307
  command: `${cmdName} ${subCommand}`,
@@ -7555,7 +7611,7 @@ async function replayEntry(entry, options = {}) {
7555
7611
  size: 0,
7556
7612
  bodyMatch: false,
7557
7613
  duration: 0,
7558
- error: err.message
7614
+ error: errMsg(err)
7559
7615
  }
7560
7616
  };
7561
7617
  }
@@ -7563,9 +7619,9 @@ async function replayEntry(entry, options = {}) {
7563
7619
 
7564
7620
  // src/daemon/feedback-store.ts
7565
7621
  import { readFileSync as readFileSync4, writeFileSync as writeFileSync6, mkdirSync as mkdirSync5 } from "fs";
7566
- import { join as join6 } from "path";
7567
- import { homedir as homedir6 } from "os";
7568
- var FEEDBACK_FILE = join6(homedir6(), ".xbrowser", "feedback.json");
7622
+ import { join as join7 } from "path";
7623
+ import { homedir as homedir7 } from "os";
7624
+ var FEEDBACK_FILE = join7(homedir7(), ".xbrowser", "feedback.json");
7569
7625
  var FeedbackStore = class {
7570
7626
  entries = [];
7571
7627
  constructor() {
@@ -7581,7 +7637,7 @@ var FeedbackStore = class {
7581
7637
  }
7582
7638
  save() {
7583
7639
  try {
7584
- mkdirSync5(join6(homedir6(), ".xbrowser"), { recursive: true });
7640
+ mkdirSync5(join7(homedir7(), ".xbrowser"), { recursive: true });
7585
7641
  writeFileSync6(FEEDBACK_FILE, JSON.stringify(this.entries, null, 2));
7586
7642
  } catch {
7587
7643
  }
@@ -7743,7 +7799,7 @@ var PlaybackEngine = class _PlaybackEngine {
7743
7799
  const content = fs2.readFileSync(filePath, "utf-8");
7744
7800
  const raw = filePath.endsWith(".json") ? JSON.parse(content) : yaml.parse(content);
7745
7801
  let recording;
7746
- const checkpoints = raw.checkpoints || [];
7802
+ const checkpoints = "checkpoints" in raw ? raw.checkpoints : [];
7747
7803
  if (raw.events && raw.events.length > 0) {
7748
7804
  recording = raw;
7749
7805
  } else if (raw.actions && raw.actions.length > 0) {
@@ -7816,7 +7872,7 @@ var PlaybackEngine = class _PlaybackEngine {
7816
7872
  errors.push({
7817
7873
  eventIndex: i,
7818
7874
  event,
7819
- error: err.message
7875
+ error: errMsg(err)
7820
7876
  });
7821
7877
  if (stopOnError) break;
7822
7878
  }
@@ -7880,7 +7936,7 @@ var PlaybackEngine = class _PlaybackEngine {
7880
7936
  // src/daemon/rpc-handlers.ts
7881
7937
  var activeRecorders = /* @__PURE__ */ new Map();
7882
7938
  var replayResumeResolvers = /* @__PURE__ */ new Map();
7883
- var CONFIG_DIR2 = join7(homedir7(), ".xbrowser");
7939
+ var CONFIG_DIR3 = join8(homedir8(), ".xbrowser");
7884
7940
  var RECORDING_INJECT_JS = `
7885
7941
  (function(){
7886
7942
  if(window.__xb_rec) return;
@@ -8237,19 +8293,27 @@ function createRPCHandler() {
8237
8293
  const analyzed = enrichEntries(scored);
8238
8294
  return { session: sessionName, total: entries.length, analyzed };
8239
8295
  }
8296
+ function extractCurlOptions(params) {
8297
+ return {
8298
+ includeHeaders: params.includeHeaders,
8299
+ includeBody: params.includeBody,
8300
+ compressed: params.compressed,
8301
+ insecure: params.insecure
8302
+ };
8303
+ }
8240
8304
  function handleNetworkCurl(params) {
8241
8305
  const sessionName = params.session || "default";
8242
8306
  const id = params.id;
8243
8307
  const entry = networkStore.inspect(sessionName, id);
8244
8308
  if (!entry.capture) return { error: `Entry #${id} not found` };
8245
- return generateCurl(entry.capture, params);
8309
+ return generateCurl(entry.capture, extractCurlOptions(params));
8246
8310
  }
8247
8311
  async function handleNetworkReplay(params) {
8248
8312
  const sessionName = params.session || "default";
8249
8313
  const id = params.id;
8250
8314
  const entry = networkStore.inspect(sessionName, id);
8251
8315
  if (!entry.capture) return { error: `Entry #${id} not found` };
8252
- return await replayEntry(entry.capture, params);
8316
+ return await replayEntry(entry.capture, extractCurlOptions(params));
8253
8317
  }
8254
8318
  function handleNetworkLike(params) {
8255
8319
  const sessionName = params.session || "default";
@@ -8320,9 +8384,9 @@ function createRPCHandler() {
8320
8384
  if (!sess) return { ok: false, error: "No session" };
8321
8385
  try {
8322
8386
  const events = await sess.page.evaluate(() => window.__xb_evts || []);
8323
- const recordingsDir = join7(CONFIG_DIR2, "recordings");
8387
+ const recordingsDir = join8(CONFIG_DIR3, "recordings");
8324
8388
  mkdirSync6(recordingsDir, { recursive: true });
8325
- const outPath = params.path || join7(recordingsDir, `recording-${(/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-")}.json`);
8389
+ const outPath = params.path || join8(recordingsDir, `recording-${(/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-")}.json`);
8326
8390
  writeFileSync7(outPath, JSON.stringify({
8327
8391
  startUrl: sess.page.url(),
8328
8392
  recordedAt: (/* @__PURE__ */ new Date()).toISOString(),
@@ -8330,7 +8394,7 @@ function createRPCHandler() {
8330
8394
  }, null, 2));
8331
8395
  return { ok: true, path: outPath, events: events.length };
8332
8396
  } catch (e) {
8333
- return { ok: false, error: e.message };
8397
+ return { ok: false, error: errMsg(e) };
8334
8398
  }
8335
8399
  }
8336
8400
  function handleCommandLog(params) {
@@ -8363,9 +8427,8 @@ function createRPCHandler() {
8363
8427
  if (session?.page) {
8364
8428
  element = await session.page.evaluate((sel) => {
8365
8429
  const el = document.querySelector(sel);
8366
- const w = window;
8367
- if (!el || typeof w.__xb_describe !== "function") return null;
8368
- return w.__xb_describe(el);
8430
+ if (!el || typeof window.__xb_describe !== "function") return null;
8431
+ return window.__xb_describe(el);
8369
8432
  }, selector);
8370
8433
  }
8371
8434
  } catch {
@@ -8410,7 +8473,7 @@ function createRPCHandler() {
8410
8473
  cdpEndpoint: session.cdpEndpoint
8411
8474
  });
8412
8475
  } catch (e) {
8413
- return { ok: false, error: "Failed to auto-create session: " + e.message };
8476
+ return { ok: false, error: "Failed to auto-create session: " + errMsg(e) };
8414
8477
  }
8415
8478
  }
8416
8479
  try {
@@ -8419,7 +8482,7 @@ function createRPCHandler() {
8419
8482
  activeRecorders.set(sessionName, recorder);
8420
8483
  return { ok: true, session: sessionName, startUrl: url || session.page.url() };
8421
8484
  } catch (e) {
8422
- return { ok: false, error: e.message };
8485
+ return { ok: false, error: errMsg(e) };
8423
8486
  }
8424
8487
  }
8425
8488
  async function handleRecordStop(params) {
@@ -8451,7 +8514,7 @@ function createRPCHandler() {
8451
8514
  };
8452
8515
  } catch (e) {
8453
8516
  activeRecorders.delete(sessionName);
8454
- return { ok: false, error: e.message };
8517
+ return { ok: false, error: errMsg(e) };
8455
8518
  }
8456
8519
  }
8457
8520
  function handleRecordStatus(params) {
@@ -8519,14 +8582,14 @@ function createRPCHandler() {
8519
8582
  const sessionName = params.session || "default";
8520
8583
  const slowMo = params.slowMo || 1;
8521
8584
  if (!file) {
8522
- return { ok: false, success: false, duration: 0, eventsPlayed: 0, totalEvents: 0, errors: [{ eventIndex: -1, event: {}, error: "Missing file parameter" }] };
8585
+ return { ok: false, success: false, duration: 0, eventsPlayed: 0, totalEvents: 0, errors: [{ eventIndex: -1, error: "Missing file parameter" }] };
8523
8586
  }
8524
8587
  const session = findSession(sessionName);
8525
8588
  if (!session) {
8526
- return { ok: false, success: false, duration: 0, eventsPlayed: 0, totalEvents: 0, errors: [{ eventIndex: -1, event: {}, error: "Session not found: " + sessionName }] };
8589
+ return { ok: false, success: false, duration: 0, eventsPlayed: 0, totalEvents: 0, errors: [{ eventIndex: -1, error: "Session not found: " + sessionName }] };
8527
8590
  }
8528
8591
  if (!session.page) {
8529
- return { ok: false, success: false, duration: 0, eventsPlayed: 0, totalEvents: 0, errors: [{ eventIndex: -1, event: {}, error: "Session has no page: " + sessionName }] };
8592
+ return { ok: false, success: false, duration: 0, eventsPlayed: 0, totalEvents: 0, errors: [{ eventIndex: -1, error: "Session has no page: " + sessionName }] };
8530
8593
  }
8531
8594
  let rawContent;
8532
8595
  let parsed;
@@ -8534,12 +8597,12 @@ function createRPCHandler() {
8534
8597
  rawContent = readFileSync6(file, "utf8");
8535
8598
  parsed = JSON.parse(rawContent);
8536
8599
  } catch (e) {
8537
- return { ok: false, success: false, duration: 0, eventsPlayed: 0, totalEvents: 0, errors: [{ eventIndex: -1, event: {}, error: "Failed to read/parse file: " + String(e) }] };
8600
+ return { ok: false, success: false, duration: 0, eventsPlayed: 0, totalEvents: 0, errors: [{ eventIndex: -1, error: "Failed to read/parse file: " + String(e) }] };
8538
8601
  }
8539
8602
  const isNewFormat = Array.isArray(parsed.actions);
8540
8603
  if (isNewFormat) {
8541
8604
  try {
8542
- const { SessionReplayer } = await import("./session-replayer-GLTUICSD.js");
8605
+ const { SessionReplayer } = await import("./session-replayer-MY27H4DX.js");
8543
8606
  const replayer = new SessionReplayer({
8544
8607
  page: session.page,
8545
8608
  stepDelay: slowMo * 500,
@@ -8550,6 +8613,9 @@ function createRPCHandler() {
8550
8613
  console.error(`[replay] Error at step ${action.type}: ${error.message}`);
8551
8614
  }
8552
8615
  });
8616
+ if (!Array.isArray(parsed.actions) || typeof parsed.startUrl !== "string") {
8617
+ return { ok: false, success: false, duration: 0, eventsPlayed: 0, totalEvents: 0, errors: [{ eventIndex: -1, error: "Invalid recording format: missing actions or startUrl" }] };
8618
+ }
8553
8619
  await replayer.load(parsed);
8554
8620
  const startTime = Date.now();
8555
8621
  const result2 = await replayer.run();
@@ -8565,7 +8631,7 @@ function createRPCHandler() {
8565
8631
  } catch (e) {
8566
8632
  const msg = e instanceof Error ? e.message : String(e);
8567
8633
  console.error("[replay] SessionReplayer error:", msg);
8568
- return { ok: false, success: false, duration: 0, eventsPlayed: 0, totalEvents: 0, errors: [{ eventIndex: -1, event: {}, error: "Replay failed: " + msg }] };
8634
+ return { ok: false, success: false, duration: 0, eventsPlayed: 0, totalEvents: 0, errors: [{ eventIndex: -1, error: "Replay failed: " + msg }] };
8569
8635
  }
8570
8636
  }
8571
8637
  const engine = PlaybackEngine.fromFile(session.page, file);
@@ -9117,14 +9183,13 @@ var ElementMonitor = class {
9117
9183
  document.addEventListener("focusin", (e) => {
9118
9184
  const el = e.target;
9119
9185
  if (el.tagName === "INPUT" || el.tagName === "TEXTAREA" || el.contentEditable === "true") {
9120
- const w = window;
9121
- w.__xb_focus_seq = (w.__xb_focus_seq || 0) + 1;
9186
+ window.__xb_focus_seq = (window.__xb_focus_seq || 0) + 1;
9122
9187
  const info = {
9123
9188
  selector: "",
9124
9189
  tag: el.tagName,
9125
9190
  value: el.value || "",
9126
9191
  placeholder: el.placeholder || "",
9127
- seq: w.__xb_focus_seq
9192
+ seq: window.__xb_focus_seq
9128
9193
  };
9129
9194
  if (el.id) info.selector = "#" + el.id;
9130
9195
  else if (el.getAttribute("name")) info.selector = '[name="' + el.getAttribute("name") + '"]';
@@ -9132,7 +9197,7 @@ var ElementMonitor = class {
9132
9197
  if (el.tagName === "INPUT" && el.type === "file") {
9133
9198
  info.isFileInput = true;
9134
9199
  }
9135
- w.__xb_last_focused = info;
9200
+ window.__xb_last_focused = info;
9136
9201
  }
9137
9202
  }, true);
9138
9203
  document.addEventListener("focusout", () => {
@@ -9639,12 +9704,12 @@ var FileListHandler = class {
9639
9704
  const msg = ctx.message;
9640
9705
  try {
9641
9706
  const { readdirSync: readdirSync2, statSync } = await import("fs");
9642
- const { join: join9, resolve: resolve3 } = await import("path");
9707
+ const { join: join10, resolve: resolve3 } = await import("path");
9643
9708
  const targetPath = resolve3(msg.path);
9644
9709
  const entries = readdirSync2(targetPath);
9645
9710
  const files = entries.map((name) => {
9646
9711
  try {
9647
- const stat = statSync(join9(targetPath, name));
9712
+ const stat = statSync(join10(targetPath, name));
9648
9713
  return { name, isDir: stat.isDirectory(), size: stat.size, modified: stat.mtime.toISOString() };
9649
9714
  } catch {
9650
9715
  return { name, isDir: false, size: 0, modified: "" };
@@ -11305,8 +11370,8 @@ connectWS();
11305
11370
  }
11306
11371
 
11307
11372
  // src/daemon/daemon-main.ts
11308
- var CONFIG_DIR3 = join8(homedir8(), ".xbrowser");
11309
- var LOG_FILE = join8(CONFIG_DIR3, "daemon.log");
11373
+ var CONFIG_DIR4 = join9(homedir9(), ".xbrowser");
11374
+ var LOG_FILE = join9(CONFIG_DIR4, "daemon.log");
11310
11375
  function log(msg) {
11311
11376
  const ts = (/* @__PURE__ */ new Date()).toISOString().replace("T", " ").substring(0, 19);
11312
11377
  const line = `[DAEMON ${ts}] ${msg}
@@ -11360,8 +11425,8 @@ async function main() {
11360
11425
  rpcHandler.setPreviewWS(previewWS);
11361
11426
  previewWS.on("screencast-started", (sid) => log(`Preview screencast started: ${sid}`));
11362
11427
  previewWS.on("screencast-stopped", (sid) => log(`Preview screencast stopped: ${sid}`));
11363
- mkdirSync7(CONFIG_DIR3, { recursive: true });
11364
- writeFileSync8(join8(CONFIG_DIR3, "daemon.json"), JSON.stringify({
11428
+ mkdirSync7(CONFIG_DIR4, { recursive: true });
11429
+ writeFileSync8(join9(CONFIG_DIR4, "daemon.json"), JSON.stringify({
11365
11430
  port: daemonPort,
11366
11431
  pid: process.pid,
11367
11432
  startedAt: Date.now()
package/dist/index.d.ts CHANGED
@@ -1928,7 +1928,7 @@ interface PlaybackResult {
1928
1928
  totalEvents: number;
1929
1929
  errors: Array<{
1930
1930
  eventIndex: number;
1931
- event: RecordedEvent;
1931
+ event?: RecordedEvent;
1932
1932
  error: string;
1933
1933
  }>;
1934
1934
  }