@xbrowser/cli 1.0.2 → 1.0.3
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/{browser-GITRHHFO.js → browser-5CTOA2WS.js} +3 -3
- package/dist/{browser-R56O3CW6.js → browser-ITLZZDHJ.js} +4 -2
- package/dist/{browser-ZJOZB5CR.js → browser-IUJXXNBT.js} +5 -4
- package/dist/{cdp-driver-BE3FOMRN.js → cdp-driver-4X3DK6PS.js} +19 -5
- package/dist/{cdp-driver-TOPYJIFL.js → cdp-driver-D6WMSMWX.js} +3 -2
- package/dist/{chunk-Q4IGYTKR.js → chunk-6WOSXSCQ.js} +6 -2
- package/dist/{chunk-ZZ2TFWIV.js → chunk-ABXMBNQ6.js} +1 -1
- package/dist/{chunk-JPHCY4TC.js → chunk-AMI64BSD.js} +9 -1
- package/dist/{chunk-CAFNSGYM.js → chunk-DKWR54XQ.js} +24 -8
- package/dist/chunk-GDKLH7ZY.js +8 -0
- package/dist/{chunk-QIK2I3VQ.js → chunk-LRBSUKUZ.js} +7 -4
- package/dist/{chunk-PPG4D2EW.js → chunk-N2JFPWMI.js} +21 -5
- package/dist/{chunk-BBMRDUYQ.js → chunk-TNEN6VQ2.js} +4 -1
- package/dist/{chunk-JPA2ZT2R.js → chunk-TWWOIJM7.js} +7 -4
- package/dist/cli.js +134 -56
- package/dist/{daemon-client-UZZEHHIV.js → daemon-client-3JOKX2L2.js} +2 -1
- package/dist/{daemon-client-DRCUMNHK.js → daemon-client-DIEHGP5B.js} +5 -2
- package/dist/daemon-main.js +122 -57
- package/dist/index.d.ts +1 -1
- package/dist/index.js +140 -65
- package/dist/{launcher-QUJ4M2VS.js → launcher-L2JNDB2H.js} +2 -1
- package/dist/{launcher-YARP45UY.js → launcher-OZXJQPNG.js} +1 -1
- package/dist/{proxy-LV4BJ5RC.js → proxy-C6CK3UH5.js} +1 -1
- package/dist/{session-replayer-GLTUICSD.js → session-replayer-MY27H4DX.js} +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -25,7 +25,7 @@ import {
|
|
|
25
25
|
killAllDaemonProcesses,
|
|
26
26
|
startDaemonProcess,
|
|
27
27
|
stopDaemonProcess
|
|
28
|
-
} from "./chunk-
|
|
28
|
+
} from "./chunk-6WOSXSCQ.js";
|
|
29
29
|
import {
|
|
30
30
|
CaptchaDetector,
|
|
31
31
|
HumanInteractionManager,
|
|
@@ -81,9 +81,12 @@ import {
|
|
|
81
81
|
resolveLaunchOpts,
|
|
82
82
|
saveSessionDiskMeta,
|
|
83
83
|
setActivePage
|
|
84
|
-
} from "./chunk-
|
|
85
|
-
import "./chunk-
|
|
86
|
-
import "./chunk-
|
|
84
|
+
} from "./chunk-TWWOIJM7.js";
|
|
85
|
+
import "./chunk-N2JFPWMI.js";
|
|
86
|
+
import "./chunk-TNEN6VQ2.js";
|
|
87
|
+
import {
|
|
88
|
+
errMsg
|
|
89
|
+
} from "./chunk-GDKLH7ZY.js";
|
|
87
90
|
import {
|
|
88
91
|
CDPInterceptorProxy,
|
|
89
92
|
advise,
|
|
@@ -97,7 +100,7 @@ import {
|
|
|
97
100
|
mouseTrajectoryRule,
|
|
98
101
|
networkAnomalyRule,
|
|
99
102
|
pageLifecycleRule
|
|
100
|
-
} from "./chunk-
|
|
103
|
+
} from "./chunk-ABXMBNQ6.js";
|
|
101
104
|
import {
|
|
102
105
|
__require
|
|
103
106
|
} from "./chunk-KFQGP6VL.js";
|
|
@@ -113,8 +116,8 @@ import {
|
|
|
113
116
|
ok as ok25,
|
|
114
117
|
fail as fail7,
|
|
115
118
|
isCommandResult,
|
|
116
|
-
CompositeStorage,
|
|
117
|
-
TipCollector,
|
|
119
|
+
CompositeStorage as CompositeStorage2,
|
|
120
|
+
TipCollector as TipCollector2,
|
|
118
121
|
normalizeTips as normalizeTips6,
|
|
119
122
|
configureArchiveStore,
|
|
120
123
|
appendCommandToArchive,
|
|
@@ -232,6 +235,67 @@ function parsePluginParams(args, schema, base = {}) {
|
|
|
232
235
|
return result;
|
|
233
236
|
}
|
|
234
237
|
|
|
238
|
+
// src/utils/stub-context.ts
|
|
239
|
+
import { TipCollector, CompositeStorage } from "@dyyz1993/xcli-core";
|
|
240
|
+
var CONFIG_DIR = __require("path").join(__require("os").homedir(), ".xbrowser");
|
|
241
|
+
var NoopSiteInstance = class {
|
|
242
|
+
name = "stub";
|
|
243
|
+
url = "";
|
|
244
|
+
config = { name: "stub" };
|
|
245
|
+
command() {
|
|
246
|
+
return this;
|
|
247
|
+
}
|
|
248
|
+
group() {
|
|
249
|
+
return this;
|
|
250
|
+
}
|
|
251
|
+
login() {
|
|
252
|
+
return this;
|
|
253
|
+
}
|
|
254
|
+
logout() {
|
|
255
|
+
return this;
|
|
256
|
+
}
|
|
257
|
+
async isLoggedIn() {
|
|
258
|
+
return true;
|
|
259
|
+
}
|
|
260
|
+
async requireLogin() {
|
|
261
|
+
}
|
|
262
|
+
getStorage() {
|
|
263
|
+
return new CompositeStorage("stub", CONFIG_DIR, "xbrowser");
|
|
264
|
+
}
|
|
265
|
+
getAllCommands() {
|
|
266
|
+
return [];
|
|
267
|
+
}
|
|
268
|
+
getCommand() {
|
|
269
|
+
return null;
|
|
270
|
+
}
|
|
271
|
+
getOriginalHandler() {
|
|
272
|
+
return void 0;
|
|
273
|
+
}
|
|
274
|
+
async executeLogin() {
|
|
275
|
+
}
|
|
276
|
+
async executeLogout() {
|
|
277
|
+
}
|
|
278
|
+
async restoreLogin() {
|
|
279
|
+
return false;
|
|
280
|
+
}
|
|
281
|
+
};
|
|
282
|
+
function createStubContext(pluginName) {
|
|
283
|
+
return {
|
|
284
|
+
args: [],
|
|
285
|
+
options: {},
|
|
286
|
+
cwd: process.cwd(),
|
|
287
|
+
storage: new CompositeStorage(pluginName, CONFIG_DIR, "xbrowser"),
|
|
288
|
+
output: { mode: "text", showTips: false, color: false, emoji: false },
|
|
289
|
+
error: (msg) => {
|
|
290
|
+
throw new Error(msg);
|
|
291
|
+
},
|
|
292
|
+
config: {},
|
|
293
|
+
site: new NoopSiteInstance(),
|
|
294
|
+
cliName: "xbrowser",
|
|
295
|
+
tips: new TipCollector()
|
|
296
|
+
};
|
|
297
|
+
}
|
|
298
|
+
|
|
235
299
|
// src/commands/navigation.ts
|
|
236
300
|
import { z } from "zod";
|
|
237
301
|
import { ok } from "@dyyz1993/xcli-core";
|
|
@@ -282,7 +346,7 @@ async function detectSsr(page) {
|
|
|
282
346
|
try {
|
|
283
347
|
const result = await page.evaluate((vars) => {
|
|
284
348
|
for (const varName of vars) {
|
|
285
|
-
const value = window
|
|
349
|
+
const value = Reflect.get(window, varName);
|
|
286
350
|
if (value != null && typeof value === "object") {
|
|
287
351
|
const keys = Object.keys(value).slice(0, 10);
|
|
288
352
|
return { variable: varName, keys };
|
|
@@ -1631,7 +1695,7 @@ var healthCheckCommand = registerCommand({
|
|
|
1631
1695
|
issues.push({
|
|
1632
1696
|
severity: "error",
|
|
1633
1697
|
category: "links",
|
|
1634
|
-
message: `Broken link (fetch error): ${href} \u2014 ${err
|
|
1698
|
+
message: `Broken link (fetch error): ${href} \u2014 ${errMsg(err) || "unknown"}`
|
|
1635
1699
|
});
|
|
1636
1700
|
}
|
|
1637
1701
|
}
|
|
@@ -5007,7 +5071,7 @@ async function actOnPage(page, sessionId, input) {
|
|
|
5007
5071
|
ref: normalizedRef,
|
|
5008
5072
|
success: false,
|
|
5009
5073
|
reason: "browser_error",
|
|
5010
|
-
message: error
|
|
5074
|
+
message: errMsg(error),
|
|
5011
5075
|
stale,
|
|
5012
5076
|
screenHash: hash,
|
|
5013
5077
|
target: refMatch?.target
|
|
@@ -5091,7 +5155,7 @@ async function waitForPage(page, input) {
|
|
|
5091
5155
|
matched: input.selector ? "selector" : input.text ? "text" : input.url ? "url" : input.load ? "load" : input.fn ? "fn" : "screenHashChanged",
|
|
5092
5156
|
timeout,
|
|
5093
5157
|
elapsed: Date.now() - startedAt,
|
|
5094
|
-
message: error
|
|
5158
|
+
message: errMsg(error)
|
|
5095
5159
|
};
|
|
5096
5160
|
}
|
|
5097
5161
|
return {
|
|
@@ -6026,11 +6090,11 @@ async function detectWebdriverExposure(page) {
|
|
|
6026
6090
|
try {
|
|
6027
6091
|
const webdriver = await page.evaluate(() => {
|
|
6028
6092
|
return {
|
|
6029
|
-
webdriver:
|
|
6093
|
+
webdriver: navigator.webdriver,
|
|
6030
6094
|
webdriverScriptFn: !!window.__webdriver_script_fn,
|
|
6031
6095
|
webdriverEvaluate: !!window.__webdriver_evaluate,
|
|
6032
6096
|
chrome: !!window.chrome,
|
|
6033
|
-
permissions:
|
|
6097
|
+
permissions: navigator.permissions
|
|
6034
6098
|
};
|
|
6035
6099
|
}).catch(() => null);
|
|
6036
6100
|
if (!webdriver) {
|
|
@@ -6390,19 +6454,26 @@ var patched = false;
|
|
|
6390
6454
|
function patchLoginRequired() {
|
|
6391
6455
|
if (patched) return;
|
|
6392
6456
|
patched = true;
|
|
6393
|
-
const
|
|
6394
|
-
const
|
|
6395
|
-
|
|
6396
|
-
const result =
|
|
6457
|
+
const target = SiteInstanceImpl.prototype;
|
|
6458
|
+
const originalCommand = target.command;
|
|
6459
|
+
const wrapped = function(...args) {
|
|
6460
|
+
const result = originalCommand.apply(this, args);
|
|
6461
|
+
const [name, cmd] = args;
|
|
6397
6462
|
const loginRequired = cmd.loginRequired;
|
|
6398
6463
|
if (loginRequired) {
|
|
6399
|
-
const
|
|
6464
|
+
const commands = this.commands;
|
|
6465
|
+
const entry = commands?.get(name);
|
|
6400
6466
|
if (entry) {
|
|
6401
6467
|
entry.loginRequired = loginRequired;
|
|
6402
6468
|
}
|
|
6403
6469
|
}
|
|
6404
6470
|
return result;
|
|
6405
6471
|
};
|
|
6472
|
+
Object.defineProperty(target, "command", {
|
|
6473
|
+
value: wrapped,
|
|
6474
|
+
writable: true,
|
|
6475
|
+
configurable: true
|
|
6476
|
+
});
|
|
6406
6477
|
}
|
|
6407
6478
|
|
|
6408
6479
|
// src/plugin/loader.ts
|
|
@@ -7096,15 +7167,14 @@ var HOOK_REGISTRY = {
|
|
|
7096
7167
|
recorder: {
|
|
7097
7168
|
name: "recorder",
|
|
7098
7169
|
onAfterCommand: async (ctx) => {
|
|
7099
|
-
const
|
|
7100
|
-
const logs = ctxAny.__commandLogs || [];
|
|
7170
|
+
const logs = ("__commandLogs" in ctx ? ctx.__commandLogs : void 0) || [];
|
|
7101
7171
|
logs.push({
|
|
7102
7172
|
timestamp: Date.now(),
|
|
7103
7173
|
command: ctx.command,
|
|
7104
7174
|
params: JSON.parse(JSON.stringify(ctx.params)),
|
|
7105
7175
|
duration: ctx.duration
|
|
7106
7176
|
});
|
|
7107
|
-
|
|
7177
|
+
Reflect.set(ctx, "__commandLogs", logs);
|
|
7108
7178
|
return void 0;
|
|
7109
7179
|
}
|
|
7110
7180
|
}
|
|
@@ -7136,11 +7206,11 @@ import { homedir as homedir5 } from "os";
|
|
|
7136
7206
|
import { join as join5 } from "path";
|
|
7137
7207
|
var NAVIGATION_COMMANDS = /* @__PURE__ */ new Set(["goto", "back", "forward", "refresh"]);
|
|
7138
7208
|
var snapshotHintShown = /* @__PURE__ */ new WeakSet();
|
|
7139
|
-
var
|
|
7209
|
+
var CONFIG_DIR2 = join5(homedir5(), ".xbrowser");
|
|
7140
7210
|
var storageCache = /* @__PURE__ */ new Map();
|
|
7141
7211
|
function getPluginStorage(pluginName) {
|
|
7142
7212
|
if (!storageCache.has(pluginName)) {
|
|
7143
|
-
storageCache.set(pluginName, new
|
|
7213
|
+
storageCache.set(pluginName, new CompositeStorage2(pluginName, CONFIG_DIR2, "xbrowser"));
|
|
7144
7214
|
}
|
|
7145
7215
|
return storageCache.get(pluginName);
|
|
7146
7216
|
}
|
|
@@ -7208,7 +7278,7 @@ async function executeCommand(commandName, params, sessionName = "default", extr
|
|
|
7208
7278
|
}
|
|
7209
7279
|
let targetPageOverride = null;
|
|
7210
7280
|
if (_target && extraOpts?.cdpEndpoint) {
|
|
7211
|
-
const { findTargetPage } = await import("./browser-
|
|
7281
|
+
const { findTargetPage } = await import("./browser-IUJXXNBT.js");
|
|
7212
7282
|
targetPageOverride = await findTargetPage(extraOpts.cdpEndpoint, _target);
|
|
7213
7283
|
if (!targetPageOverride) {
|
|
7214
7284
|
return errorResult(`Target "${_target}" not found. Use 'xbrowser targets --cdp ${extraOpts.cdpEndpoint}' to list available pages.`);
|
|
@@ -7225,7 +7295,7 @@ async function executeCommand(commandName, params, sessionName = "default", extr
|
|
|
7225
7295
|
params = result.data;
|
|
7226
7296
|
}
|
|
7227
7297
|
if (command.scope !== "cli" && !process.env.XBROWSER_DAEMON_WORKER) {
|
|
7228
|
-
const { forwardExec } = await import("./daemon-client-
|
|
7298
|
+
const { forwardExec } = await import("./daemon-client-3JOKX2L2.js");
|
|
7229
7299
|
const result = await forwardExec(commandName, params, sessionName, extraOpts?.cdpEndpoint);
|
|
7230
7300
|
if (result) return result;
|
|
7231
7301
|
}
|
|
@@ -7276,9 +7346,9 @@ async function executeCommand(commandName, params, sessionName = "default", extr
|
|
|
7276
7346
|
throw new Error(msg);
|
|
7277
7347
|
},
|
|
7278
7348
|
config: {},
|
|
7279
|
-
site:
|
|
7349
|
+
site: new NoopSiteInstance(),
|
|
7280
7350
|
cliName: "xbrowser",
|
|
7281
|
-
tips: new
|
|
7351
|
+
tips: new TipCollector2()
|
|
7282
7352
|
};
|
|
7283
7353
|
const start = Date.now();
|
|
7284
7354
|
if (session) {
|
|
@@ -7391,7 +7461,7 @@ async function executeCommand(commandName, params, sessionName = "default", extr
|
|
|
7391
7461
|
} catch (err) {
|
|
7392
7462
|
const end = Date.now();
|
|
7393
7463
|
const duration = end - start;
|
|
7394
|
-
const errorMessage = err
|
|
7464
|
+
const errorMessage = errMsg(err);
|
|
7395
7465
|
if (session) {
|
|
7396
7466
|
streamCommandEvent(session.id, {
|
|
7397
7467
|
sessionId: session.id,
|
|
@@ -7504,7 +7574,7 @@ async function executeChain(input, options) {
|
|
|
7504
7574
|
config: {},
|
|
7505
7575
|
site,
|
|
7506
7576
|
cliName: "xbrowser",
|
|
7507
|
-
tips: new
|
|
7577
|
+
tips: new TipCollector2()
|
|
7508
7578
|
};
|
|
7509
7579
|
const start2 = Date.now();
|
|
7510
7580
|
try {
|
|
@@ -7591,7 +7661,7 @@ async function executeChain(input, options) {
|
|
|
7591
7661
|
}
|
|
7592
7662
|
} catch (err) {
|
|
7593
7663
|
const duration2 = Date.now() - start2;
|
|
7594
|
-
const errorMessage = err
|
|
7664
|
+
const errorMessage = errMsg(err);
|
|
7595
7665
|
recordArchive(session.id, sessionName, {
|
|
7596
7666
|
step: results.length,
|
|
7597
7667
|
command: `${cmdName} ${subCommand}`,
|
|
@@ -7731,7 +7801,12 @@ var BROWSER_SCOPE = {
|
|
|
7731
7801
|
};
|
|
7732
7802
|
|
|
7733
7803
|
// src/router.ts
|
|
7734
|
-
import { parseArgs, outputFormatter as outputFormatter2, isCommandResult as isCommandResult2, helpGenerator as helpGenerator2, TipCollector as
|
|
7804
|
+
import { parseArgs, outputFormatter as outputFormatter2, isCommandResult as isCommandResult2, helpGenerator as helpGenerator2, TipCollector as TipCollector3, normalizeTips as normalizeTips7, tip as makeTip } from "@dyyz1993/xcli-core";
|
|
7805
|
+
|
|
7806
|
+
// src/utils/zod-internal.ts
|
|
7807
|
+
function asZodSchema(value) {
|
|
7808
|
+
return value;
|
|
7809
|
+
}
|
|
7735
7810
|
|
|
7736
7811
|
// src/session/session-client.ts
|
|
7737
7812
|
function sessionToInfo(s) {
|
|
@@ -8004,7 +8079,8 @@ async function ensureProxyFetch() {
|
|
|
8004
8079
|
const body = init?.body;
|
|
8005
8080
|
if (body instanceof globalThis.FormData && !(body instanceof UFormData)) {
|
|
8006
8081
|
const ufd = new UFormData();
|
|
8007
|
-
|
|
8082
|
+
const domFormData = body;
|
|
8083
|
+
domFormData.forEach((value, key) => {
|
|
8008
8084
|
if (value instanceof Blob) {
|
|
8009
8085
|
ufd.append(key, value, value.name || "file");
|
|
8010
8086
|
} else {
|
|
@@ -8919,7 +8995,7 @@ async function searchFromMarketplacePlugin(options, loader) {
|
|
|
8919
8995
|
site: options.site,
|
|
8920
8996
|
limit: options.limit
|
|
8921
8997
|
},
|
|
8922
|
-
|
|
8998
|
+
createStubContext("marketplace")
|
|
8923
8999
|
);
|
|
8924
9000
|
const items = extractItems(result);
|
|
8925
9001
|
return items.map((item) => ({
|
|
@@ -9700,16 +9776,16 @@ async function handleBrowserCommand(command, args, options, sessionName, mode, c
|
|
|
9700
9776
|
if (cmdDef) {
|
|
9701
9777
|
if (mode === "json") {
|
|
9702
9778
|
const paramsList = [];
|
|
9703
|
-
const schema = cmdDef.parameters;
|
|
9779
|
+
const schema = asZodSchema(cmdDef.parameters);
|
|
9704
9780
|
const shape = schema?.shape ?? schema?._def?.shape;
|
|
9705
9781
|
if (shape) {
|
|
9706
9782
|
for (const [key, value] of Object.entries(shape)) {
|
|
9707
|
-
const fieldSchema = value;
|
|
9783
|
+
const fieldSchema = asZodSchema(value);
|
|
9708
9784
|
const fieldDef = fieldSchema._def;
|
|
9709
9785
|
const description = fieldSchema.description || fieldDef?.description || "";
|
|
9710
9786
|
const typeName = fieldDef?.typeName || "";
|
|
9711
9787
|
const isOptional = typeName === "ZodOptional" || typeof fieldSchema.isOptional === "function" && fieldSchema.isOptional();
|
|
9712
|
-
const innerType = fieldDef?.innerType;
|
|
9788
|
+
const innerType = asZodSchema(fieldDef?.innerType);
|
|
9713
9789
|
const innerTypeName = innerType?._def ? innerType._def.typeName : typeName;
|
|
9714
9790
|
let type = "unknown";
|
|
9715
9791
|
if (innerTypeName === "ZodString" || typeName === "ZodString") type = "string";
|
|
@@ -10119,8 +10195,7 @@ async function buildRuntimePluginInfo() {
|
|
|
10119
10195
|
const cmds = site.getAllCommands();
|
|
10120
10196
|
const commandNames = cmds.map((c) => c.name);
|
|
10121
10197
|
if (commandNames.length === 0) continue;
|
|
10122
|
-
const
|
|
10123
|
-
const hasLoginHandler = typeof anySite.hasLoginCommand === "function" && anySite.hasLoginCommand();
|
|
10198
|
+
const hasLoginHandler = "hasLoginCommand" in site && typeof site.hasLoginCommand === "function" && site.hasLoginCommand();
|
|
10124
10199
|
const configRequiresLogin = !!site.config.requiresLogin;
|
|
10125
10200
|
const hasLogin = hasLoginHandler || configRequiresLogin;
|
|
10126
10201
|
let loggedIn = null;
|
|
@@ -10170,7 +10245,7 @@ async function searchFromMarketplacePlugin2(options, loader) {
|
|
|
10170
10245
|
site: options.site,
|
|
10171
10246
|
limit: options.limit
|
|
10172
10247
|
},
|
|
10173
|
-
|
|
10248
|
+
createStubContext("marketplace")
|
|
10174
10249
|
);
|
|
10175
10250
|
const items = extractItems2(result);
|
|
10176
10251
|
return items.map((item) => ({ ...item, source: "marketplace" }));
|
|
@@ -10185,7 +10260,7 @@ async function infoFromMarketplacePlugin(slug, loader) {
|
|
|
10185
10260
|
const infoCmd = marketplaceSite.getCommand("info");
|
|
10186
10261
|
if (!infoCmd) return null;
|
|
10187
10262
|
try {
|
|
10188
|
-
const result = await infoCmd.handler({ slug },
|
|
10263
|
+
const result = await infoCmd.handler({ slug }, createStubContext("marketplace"));
|
|
10189
10264
|
if (!result || typeof result !== "object") return null;
|
|
10190
10265
|
const r = result;
|
|
10191
10266
|
let plugin = null;
|
|
@@ -10293,7 +10368,7 @@ async function handlePluginInfo(args, options, mode) {
|
|
|
10293
10368
|
}
|
|
10294
10369
|
console.error(`\u63D2\u4EF6 '${slug}' \u672A\u627E\u5230`);
|
|
10295
10370
|
} catch (err) {
|
|
10296
|
-
console.error("\u67E5\u8BE2\u5931\u8D25:", err
|
|
10371
|
+
console.error("\u67E5\u8BE2\u5931\u8D25:", errMsg(err));
|
|
10297
10372
|
}
|
|
10298
10373
|
}
|
|
10299
10374
|
async function handlePluginSchema(args, mode) {
|
|
@@ -10984,9 +11059,9 @@ interface XBPage {
|
|
|
10984
11059
|
}
|
|
10985
11060
|
|
|
10986
11061
|
function ensurePage(ctx: CommandContext): XBPage {
|
|
10987
|
-
const page = (ctx as Record<string, unknown>).page;
|
|
11062
|
+
const page = 'page' in ctx ? (ctx as Record<string, unknown>).page : undefined;
|
|
10988
11063
|
if (!page) throw new Error('No active page. Start a session first.');
|
|
10989
|
-
return page as
|
|
11064
|
+
return page as XBPage;
|
|
10990
11065
|
}
|
|
10991
11066
|
|
|
10992
11067
|
export default createSite({
|
|
@@ -11019,7 +11094,7 @@ async function handleRun(filePath, options) {
|
|
|
11019
11094
|
try {
|
|
11020
11095
|
commands = readCommandFile(filePath);
|
|
11021
11096
|
} catch (e) {
|
|
11022
|
-
outputError(`Failed to read file '${filePath}': ${e
|
|
11097
|
+
outputError(`Failed to read file '${filePath}': ${errMsg(e)}`);
|
|
11023
11098
|
return;
|
|
11024
11099
|
}
|
|
11025
11100
|
if (commands.length === 0) {
|
|
@@ -11375,7 +11450,7 @@ async function handleNetCommand(args, options, mode, sessionName) {
|
|
|
11375
11450
|
outputError(`Unknown net sub-command: ${subCommand}. Use: list, clear, top, log, around, analyze, curl, replay, inspect, like, dislike, export`);
|
|
11376
11451
|
}
|
|
11377
11452
|
} catch (err) {
|
|
11378
|
-
outputError(err
|
|
11453
|
+
outputError(errMsg(err) || "Network command failed");
|
|
11379
11454
|
}
|
|
11380
11455
|
}
|
|
11381
11456
|
|
|
@@ -11900,7 +11975,7 @@ async function createSessionHandler(req) {
|
|
|
11900
11975
|
createdAt: session.createdAt
|
|
11901
11976
|
});
|
|
11902
11977
|
} catch (err) {
|
|
11903
|
-
return errorResponse(500, "INTERNAL_ERROR", err
|
|
11978
|
+
return errorResponse(500, "INTERNAL_ERROR", errMsg(err));
|
|
11904
11979
|
}
|
|
11905
11980
|
}
|
|
11906
11981
|
async function closeSession2(req) {
|
|
@@ -11995,7 +12070,7 @@ async function route(method, url, headers, body) {
|
|
|
11995
12070
|
try {
|
|
11996
12071
|
return await match.route.handler(req);
|
|
11997
12072
|
} catch (err) {
|
|
11998
|
-
return errorResponse(500, "INTERNAL_ERROR", err
|
|
12073
|
+
return errorResponse(500, "INTERNAL_ERROR", errMsg(err));
|
|
11999
12074
|
}
|
|
12000
12075
|
}
|
|
12001
12076
|
async function handleRequest(req, res, validateAuthFn) {
|
|
@@ -12153,8 +12228,9 @@ function showCommandHelp(siteName, cmd, siteConfig, mode) {
|
|
|
12153
12228
|
if (mode === "json") {
|
|
12154
12229
|
const paramsList = [];
|
|
12155
12230
|
if (c.parameters) {
|
|
12156
|
-
const def = c.parameters._def;
|
|
12157
|
-
const
|
|
12231
|
+
const def = asZodSchema(c.parameters)._def;
|
|
12232
|
+
const rawShape = def?.shape;
|
|
12233
|
+
const shape = typeof rawShape === "function" ? rawShape() : rawShape;
|
|
12158
12234
|
if (shape) {
|
|
12159
12235
|
for (const [key, value] of Object.entries(shape)) {
|
|
12160
12236
|
const info = extractZodFieldInfo(value);
|
|
@@ -12381,16 +12457,16 @@ async function routeCommand(argv, stdinCommands) {
|
|
|
12381
12457
|
if (builtinCmd) {
|
|
12382
12458
|
if (mode === "json") {
|
|
12383
12459
|
const paramsList = [];
|
|
12384
|
-
const schema = builtinCmd.parameters;
|
|
12460
|
+
const schema = asZodSchema(builtinCmd.parameters);
|
|
12385
12461
|
const shape = schema?.shape ?? schema?._def?.shape;
|
|
12386
12462
|
if (shape) {
|
|
12387
12463
|
for (const [key, value] of Object.entries(shape)) {
|
|
12388
|
-
const fieldSchema = value;
|
|
12464
|
+
const fieldSchema = asZodSchema(value);
|
|
12389
12465
|
const fieldDef = fieldSchema._def;
|
|
12390
12466
|
const description = fieldSchema.description || fieldDef?.description || "";
|
|
12391
12467
|
const typeName = fieldDef?.typeName || "";
|
|
12392
12468
|
const isOptional = typeName === "ZodOptional" || typeof fieldSchema.isOptional === "function" && fieldSchema.isOptional();
|
|
12393
|
-
const innerType = fieldDef?.innerType;
|
|
12469
|
+
const innerType = asZodSchema(fieldDef?.innerType);
|
|
12394
12470
|
const innerTypeName = innerType?._def ? innerType._def.typeName : typeName;
|
|
12395
12471
|
let type = "unknown";
|
|
12396
12472
|
if (innerTypeName === "ZodString" || typeName === "ZodString") type = "string";
|
|
@@ -12565,7 +12641,7 @@ Run "xbrowser ${command} --help" to see available commands.`
|
|
|
12565
12641
|
const rawPluginArgs = subCmdIdx >= 0 ? argv.slice(subCmdIdx + 1) : [];
|
|
12566
12642
|
const params = parsePluginParams(rawPluginArgs, cmdEntry.parameters);
|
|
12567
12643
|
if (cmdEntry.parameters) {
|
|
12568
|
-
const schemaAny = cmdEntry.parameters;
|
|
12644
|
+
const schemaAny = asZodSchema(cmdEntry.parameters);
|
|
12569
12645
|
const def = schemaAny._def;
|
|
12570
12646
|
const shapeOrFn = def?.shape ?? schemaAny.shape;
|
|
12571
12647
|
const shapeObj = typeof shapeOrFn === "function" ? shapeOrFn() : shapeOrFn;
|
|
@@ -12589,10 +12665,10 @@ Run "xbrowser ${command} ${subCommand} --help" to see available parameters.`
|
|
|
12589
12665
|
}
|
|
12590
12666
|
const needsBrowser = cmdEntry.scope === "page" || cmdEntry.scope === "browser";
|
|
12591
12667
|
if (needsBrowser && !process.env.XBROWSER_DAEMON_WORKER) {
|
|
12592
|
-
const { forwardExec } = await import("./daemon-client-
|
|
12668
|
+
const { forwardExec } = await import("./daemon-client-3JOKX2L2.js");
|
|
12593
12669
|
const userTimeout = typeof params.timeout === "number" && params.timeout > 0 ? params.timeout * 1e3 + 3e4 : void 0;
|
|
12594
12670
|
const result = await forwardExec(`${command}.${subCommand}`, params, sessionName, cdpEndpoint, userTimeout);
|
|
12595
|
-
const resultData = result && typeof result === "object" ? result.data : void 0;
|
|
12671
|
+
const resultData = result && typeof result === "object" && "data" in result ? result.data : void 0;
|
|
12596
12672
|
if (result && result.success === false && resultData?.code === "LOGIN_REQUIRED") {
|
|
12597
12673
|
outputLoginRequired(result, mode);
|
|
12598
12674
|
return;
|
|
@@ -12641,7 +12717,7 @@ Run "xbrowser ${command} ${subCommand} --help" to see available parameters.`
|
|
|
12641
12717
|
waitForHuman: async (_opts) => {
|
|
12642
12718
|
return { solved: false, timedOut: true };
|
|
12643
12719
|
},
|
|
12644
|
-
tips: new
|
|
12720
|
+
tips: new TipCollector3()
|
|
12645
12721
|
};
|
|
12646
12722
|
try {
|
|
12647
12723
|
const cmdStart = Date.now();
|
|
@@ -13084,7 +13160,7 @@ var PlaybackEngine = class _PlaybackEngine {
|
|
|
13084
13160
|
const content = fs4.readFileSync(filePath, "utf-8");
|
|
13085
13161
|
const raw = filePath.endsWith(".json") ? JSON.parse(content) : yaml2.parse(content);
|
|
13086
13162
|
let recording;
|
|
13087
|
-
const checkpoints = raw.checkpoints
|
|
13163
|
+
const checkpoints = "checkpoints" in raw ? raw.checkpoints : [];
|
|
13088
13164
|
if (raw.events && raw.events.length > 0) {
|
|
13089
13165
|
recording = raw;
|
|
13090
13166
|
} else if (raw.actions && raw.actions.length > 0) {
|
|
@@ -13157,7 +13233,7 @@ var PlaybackEngine = class _PlaybackEngine {
|
|
|
13157
13233
|
errors.push({
|
|
13158
13234
|
eventIndex: i,
|
|
13159
13235
|
event,
|
|
13160
|
-
error: err
|
|
13236
|
+
error: errMsg(err)
|
|
13161
13237
|
});
|
|
13162
13238
|
if (stopOnError) break;
|
|
13163
13239
|
}
|
|
@@ -13594,14 +13670,13 @@ var ElementMonitor = class {
|
|
|
13594
13670
|
document.addEventListener("focusin", (e) => {
|
|
13595
13671
|
const el = e.target;
|
|
13596
13672
|
if (el.tagName === "INPUT" || el.tagName === "TEXTAREA" || el.contentEditable === "true") {
|
|
13597
|
-
|
|
13598
|
-
w.__xb_focus_seq = (w.__xb_focus_seq || 0) + 1;
|
|
13673
|
+
window.__xb_focus_seq = (window.__xb_focus_seq || 0) + 1;
|
|
13599
13674
|
const info = {
|
|
13600
13675
|
selector: "",
|
|
13601
13676
|
tag: el.tagName,
|
|
13602
13677
|
value: el.value || "",
|
|
13603
13678
|
placeholder: el.placeholder || "",
|
|
13604
|
-
seq:
|
|
13679
|
+
seq: window.__xb_focus_seq
|
|
13605
13680
|
};
|
|
13606
13681
|
if (el.id) info.selector = "#" + el.id;
|
|
13607
13682
|
else if (el.getAttribute("name")) info.selector = '[name="' + el.getAttribute("name") + '"]';
|
|
@@ -13609,7 +13684,7 @@ var ElementMonitor = class {
|
|
|
13609
13684
|
if (el.tagName === "INPUT" && el.type === "file") {
|
|
13610
13685
|
info.isFileInput = true;
|
|
13611
13686
|
}
|
|
13612
|
-
|
|
13687
|
+
window.__xb_last_focused = info;
|
|
13613
13688
|
}
|
|
13614
13689
|
}, true);
|
|
13615
13690
|
document.addEventListener("focusout", () => {
|
|
@@ -15683,7 +15758,7 @@ var DataCollector = class {
|
|
|
15683
15758
|
return results;
|
|
15684
15759
|
}
|
|
15685
15760
|
async createBrowserContext() {
|
|
15686
|
-
const { launch } = await import("./cdp-driver-
|
|
15761
|
+
const { launch } = await import("./cdp-driver-D6WMSMWX.js");
|
|
15687
15762
|
const { browser } = await launch({
|
|
15688
15763
|
headless: true,
|
|
15689
15764
|
args: ["--no-sandbox", "--disable-setuid-sandbox"]
|
|
@@ -15692,7 +15767,7 @@ var DataCollector = class {
|
|
|
15692
15767
|
userAgent: "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36",
|
|
15693
15768
|
viewport: { width: 1920, height: 1080 }
|
|
15694
15769
|
});
|
|
15695
|
-
context
|
|
15770
|
+
Reflect.set(context, "_browser", browser);
|
|
15696
15771
|
return context;
|
|
15697
15772
|
}
|
|
15698
15773
|
sleep(ms) {
|
|
@@ -15723,7 +15798,7 @@ var DataCollector = class {
|
|
|
15723
15798
|
|
|
15724
15799
|
// src/cdp-interceptor/index.ts
|
|
15725
15800
|
async function createCDPInterceptor(config) {
|
|
15726
|
-
const { CDPInterceptorProxy: CDPInterceptorProxy2 } = await import("./proxy-
|
|
15801
|
+
const { CDPInterceptorProxy: CDPInterceptorProxy2 } = await import("./proxy-C6CK3UH5.js");
|
|
15727
15802
|
const proxy = new CDPInterceptorProxy2(config);
|
|
15728
15803
|
await proxy.start();
|
|
15729
15804
|
return proxy;
|
|
@@ -31,7 +31,7 @@ var SessionReplayer = class {
|
|
|
31
31
|
if (this.opts.page) {
|
|
32
32
|
this.page = this.opts.page;
|
|
33
33
|
} else if (this.opts.cdpUrl) {
|
|
34
|
-
const { launch } = await import("./cdp-driver-
|
|
34
|
+
const { launch } = await import("./cdp-driver-D6WMSMWX.js");
|
|
35
35
|
const { browser } = await launch({ cdpEndpoint: this.opts.cdpUrl });
|
|
36
36
|
let contexts = browser.contexts();
|
|
37
37
|
for (let i = 0; i < 10 && contexts.length === 0; i++) {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@xbrowser/cli",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.3",
|
|
4
4
|
"description": "Browser automation CLI for web scraping, headless browsing, SEO analysis, and AI agent workflows. A command-line alternative to Playwright, Puppeteer, and Selenium.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|