opensteer 0.9.4 → 0.9.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{chunk-ZRF7WMS3.js → chunk-3I3A5OLB.js} +3 -3
- package/dist/{chunk-ZRF7WMS3.js.map → chunk-3I3A5OLB.js.map} +1 -1
- package/dist/{chunk-GSCQQKZZ.js → chunk-3XBQRZZC.js} +221 -6
- package/dist/chunk-3XBQRZZC.js.map +1 -0
- package/dist/{chunk-GEUHKPC2.js → chunk-BVRIPCWA.js} +878 -572
- package/dist/chunk-BVRIPCWA.js.map +1 -0
- package/dist/chunk-L4NF74KI.js +458 -0
- package/dist/chunk-L4NF74KI.js.map +1 -0
- package/dist/cli/bin.cjs +1313 -494
- package/dist/cli/bin.cjs.map +1 -1
- package/dist/cli/bin.js +235 -108
- package/dist/cli/bin.js.map +1 -1
- package/dist/index.cjs +1152 -647
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +37 -460
- package/dist/index.d.ts +37 -460
- package/dist/index.js +3 -4
- package/dist/local-view/serve-entry.cjs +5354 -4
- package/dist/local-view/serve-entry.cjs.map +1 -1
- package/dist/local-view/serve-entry.js +1 -1
- package/dist/opensteer-UGA6YBRN.js +6 -0
- package/dist/{opensteer-PJI7VUIT.js.map → opensteer-UGA6YBRN.js.map} +1 -1
- package/dist/{session-control-M3JD7ZKA.js → session-control-U3L5H2ZI.js} +3 -3
- package/dist/{session-control-M3JD7ZKA.js.map → session-control-U3L5H2ZI.js.map} +1 -1
- package/package.json +7 -7
- package/skills/opensteer/SKILL.md +134 -94
- package/dist/chunk-GEUHKPC2.js.map +0 -1
- package/dist/chunk-GSCQQKZZ.js.map +0 -1
- package/dist/chunk-HQCMXRBE.js +0 -335
- package/dist/chunk-HQCMXRBE.js.map +0 -1
- package/dist/chunk-KCINASQC.js +0 -3
- package/dist/chunk-KCINASQC.js.map +0 -1
- package/dist/opensteer-PJI7VUIT.js +0 -6
package/dist/cli/bin.cjs
CHANGED
|
@@ -2598,10 +2598,8 @@ var init_cdp_dom_snapshot = __esm({
|
|
|
2598
2598
|
});
|
|
2599
2599
|
|
|
2600
2600
|
// ../browser-core/src/cdp-visual-stability.ts
|
|
2601
|
-
var DEFAULT_VISUAL_STABILITY_SETTLE_MS;
|
|
2602
2601
|
var init_cdp_visual_stability = __esm({
|
|
2603
2602
|
"../browser-core/src/cdp-visual-stability.ts"() {
|
|
2604
|
-
DEFAULT_VISUAL_STABILITY_SETTLE_MS = 750;
|
|
2605
2603
|
}
|
|
2606
2604
|
});
|
|
2607
2605
|
|
|
@@ -6679,7 +6677,7 @@ function assertValidSemanticOperationInput(name, input) {
|
|
|
6679
6677
|
}
|
|
6680
6678
|
);
|
|
6681
6679
|
}
|
|
6682
|
-
var opensteerComputerAnnotationNames, opensteerExposedSemanticOperationNames, opensteerPackageRunnableSemanticOperationNames, snapshotModeSchema, viewportSchema, opensteerBrowserLaunchOptionsSchema, attachBrowserOptionsSchema, opensteerBrowserOptionsSchema, opensteerBrowserContextOptionsSchema, targetByElementSchema2, targetByPersistSchema2, targetBySelectorSchema2, opensteerTargetInputSchema, opensteerResolvedTargetSchema, opensteerActionResultSchema, opensteerSnapshotCounterSchema, opensteerSessionStateSchema, opensteerOpenInputSchema, opensteerPageListInputSchema, opensteerPageListOutputSchema, opensteerPageNewInputSchema, opensteerPageActivateInputSchema, opensteerPageCloseInputSchema, opensteerPageCloseOutputSchema, opensteerPageGotoInputSchema, opensteerPageEvaluateInputSchema, opensteerPageEvaluateOutputSchema, opensteerAddInitScriptInputSchema, opensteerAddInitScriptOutputSchema, opensteerCapturedScriptSchema, opensteerCaptureScriptsInputSchema, opensteerCaptureScriptsOutputSchema, opensteerPageSnapshotInputSchema, opensteerPageSnapshotOutputSchema, opensteerComputerMouseButtonSchema, opensteerComputerKeyModifierSchema, opensteerDomClickInputSchema, opensteerDomHoverInputSchema, opensteerDomInputInputSchema, opensteerDomScrollInputSchema,
|
|
6680
|
+
var opensteerComputerAnnotationNames, opensteerExposedSemanticOperationNames, opensteerPackageRunnableSemanticOperationNames, snapshotModeSchema, viewportSchema, opensteerBrowserLaunchOptionsSchema, attachBrowserOptionsSchema, opensteerBrowserOptionsSchema, opensteerBrowserContextOptionsSchema, targetByElementSchema2, targetByPersistSchema2, targetBySelectorSchema2, opensteerTargetInputSchema, opensteerResolvedTargetSchema, opensteerActionResultSchema, opensteerSnapshotCounterSchema, opensteerSessionStateSchema, opensteerOpenInputSchema, opensteerPageListInputSchema, opensteerPageListOutputSchema, opensteerPageNewInputSchema, opensteerPageActivateInputSchema, opensteerPageCloseInputSchema, opensteerPageCloseOutputSchema, opensteerPageGotoInputSchema, opensteerPageEvaluateInputSchema, opensteerPageEvaluateOutputSchema, opensteerAddInitScriptInputSchema, opensteerAddInitScriptOutputSchema, opensteerCapturedScriptSchema, opensteerCaptureScriptsInputSchema, opensteerCaptureScriptsOutputSchema, opensteerPageSnapshotInputSchema, opensteerPageSnapshotOutputSchema, opensteerComputerMouseButtonSchema, opensteerComputerKeyModifierSchema, opensteerDomClickInputSchema, opensteerDomHoverInputSchema, opensteerDomInputInputSchema, opensteerDomScrollInputSchema, opensteerExtractTemplateSchema, opensteerDomExtractInputSchema, jsonValueSchema2, opensteerDomExtractOutputSchema, opensteerSessionCloseInputSchema, opensteerSessionCloseOutputSchema, opensteerComputerAnnotationSchema, opensteerComputerClickActionSchema, opensteerComputerMoveActionSchema, opensteerComputerScrollActionSchema, opensteerComputerTypeActionSchema, opensteerComputerKeyActionSchema, opensteerComputerDragActionSchema, opensteerComputerScreenshotActionSchema, opensteerComputerWaitActionSchema, opensteerComputerActionSchema, opensteerComputerScreenshotOptionsSchema, opensteerComputerExecuteInputSchema, opensteerComputerTracePointSchema, opensteerComputerTraceEnrichmentSchema, opensteerComputerExecuteTimingSchema, opensteerComputerDisplayScaleSchema, opensteerComputerExecuteOutputSchema, opensteerSemanticOperationSpecificationsBase, exposedSemanticOperationNameSet, opensteerSemanticOperationSpecificationsInternal, opensteerSemanticOperationSpecifications, opensteerSemanticOperationSpecificationMap, semanticRestBasePath, opensteerSemanticRestEndpoints;
|
|
6683
6681
|
var init_semantic = __esm({
|
|
6684
6682
|
"../protocol/src/semantic.ts"() {
|
|
6685
6683
|
init_json2();
|
|
@@ -7261,10 +7259,10 @@ var init_semantic = __esm({
|
|
|
7261
7259
|
required: ["target", "direction", "amount"]
|
|
7262
7260
|
}
|
|
7263
7261
|
);
|
|
7264
|
-
|
|
7262
|
+
opensteerExtractTemplateSchema = objectSchema(
|
|
7265
7263
|
{},
|
|
7266
7264
|
{
|
|
7267
|
-
title: "
|
|
7265
|
+
title: "OpensteerExtractTemplate",
|
|
7268
7266
|
additionalProperties: true
|
|
7269
7267
|
}
|
|
7270
7268
|
);
|
|
@@ -7272,13 +7270,13 @@ var init_semantic = __esm({
|
|
|
7272
7270
|
...objectSchema(
|
|
7273
7271
|
{
|
|
7274
7272
|
persist: stringSchema(),
|
|
7275
|
-
|
|
7273
|
+
template: opensteerExtractTemplateSchema
|
|
7276
7274
|
},
|
|
7277
7275
|
{
|
|
7278
7276
|
title: "OpensteerDomExtractInput"
|
|
7279
7277
|
}
|
|
7280
7278
|
),
|
|
7281
|
-
anyOf: [defineSchema({ required: ["persist"] }), defineSchema({ required: ["
|
|
7279
|
+
anyOf: [defineSchema({ required: ["persist"] }), defineSchema({ required: ["template"] })]
|
|
7282
7280
|
});
|
|
7283
7281
|
jsonValueSchema2 = recordSchema({}, { title: "JsonValueRecord" });
|
|
7284
7282
|
opensteerDomExtractOutputSchema = objectSchema(
|
|
@@ -10413,7 +10411,8 @@ function normalizeOpensteerEngineName(value, source = "engine") {
|
|
|
10413
10411
|
if (normalized === "playwright" || normalized === "abp") {
|
|
10414
10412
|
return normalized;
|
|
10415
10413
|
}
|
|
10416
|
-
throw new
|
|
10414
|
+
throw new OpensteerProtocolError(
|
|
10415
|
+
"invalid-argument",
|
|
10417
10416
|
`${source} must be one of ${OPENSTEER_ENGINE_NAMES.join(", ")}; received "${value}".`
|
|
10418
10417
|
);
|
|
10419
10418
|
}
|
|
@@ -10422,7 +10421,8 @@ function assertSupportedEngineOptions(input) {
|
|
|
10422
10421
|
return;
|
|
10423
10422
|
}
|
|
10424
10423
|
if (typeof input.browser === "object" && input.browser !== null && input.browser.mode === "attach") {
|
|
10425
|
-
throw new
|
|
10424
|
+
throw new OpensteerProtocolError(
|
|
10425
|
+
"invalid-argument",
|
|
10426
10426
|
'ABP engine does not support browser.mode="attach". Use the Playwright engine for attach flows.'
|
|
10427
10427
|
);
|
|
10428
10428
|
}
|
|
@@ -10430,7 +10430,8 @@ function assertSupportedEngineOptions(input) {
|
|
|
10430
10430
|
if (unsupportedContextOptionNames.length === 0) {
|
|
10431
10431
|
return;
|
|
10432
10432
|
}
|
|
10433
|
-
throw new
|
|
10433
|
+
throw new OpensteerProtocolError(
|
|
10434
|
+
"invalid-argument",
|
|
10434
10435
|
`ABP engine does not support ${unsupportedContextOptionNames.join(", ")}. Supported ABP context options: context.viewport.`
|
|
10435
10436
|
);
|
|
10436
10437
|
}
|
|
@@ -10488,6 +10489,7 @@ function stripWindowSizeArgs(args) {
|
|
|
10488
10489
|
var OPENSTEER_ENGINE_NAMES, DEFAULT_OPENSTEER_ENGINE;
|
|
10489
10490
|
var init_engine_selection = __esm({
|
|
10490
10491
|
"../runtime-core/src/internal/engine-selection.ts"() {
|
|
10492
|
+
init_src2();
|
|
10491
10493
|
OPENSTEER_ENGINE_NAMES = ["playwright", "abp"];
|
|
10492
10494
|
DEFAULT_OPENSTEER_ENGINE = "playwright";
|
|
10493
10495
|
}
|
|
@@ -11472,7 +11474,8 @@ function assertProviderSupportsEngine(provider, engine) {
|
|
|
11472
11474
|
return;
|
|
11473
11475
|
}
|
|
11474
11476
|
if (provider === "cloud") {
|
|
11475
|
-
throw new
|
|
11477
|
+
throw new OpensteerProtocolError(
|
|
11478
|
+
"invalid-argument",
|
|
11476
11479
|
"ABP is not supported for provider=cloud. Cloud provider currently requires Playwright."
|
|
11477
11480
|
);
|
|
11478
11481
|
}
|
|
@@ -11482,7 +11485,8 @@ function normalizeOpensteerProviderMode(value, source = "OPENSTEER_PROVIDER") {
|
|
|
11482
11485
|
if (normalized === OPENSTEER_PROVIDER_MODES[0] || normalized === OPENSTEER_PROVIDER_MODES[1]) {
|
|
11483
11486
|
return normalized;
|
|
11484
11487
|
}
|
|
11485
|
-
throw new
|
|
11488
|
+
throw new OpensteerProtocolError(
|
|
11489
|
+
"invalid-argument",
|
|
11486
11490
|
`${source} must be one of ${OPENSTEER_PROVIDER_MODES.join(", ")}; received "${value}".`
|
|
11487
11491
|
);
|
|
11488
11492
|
}
|
|
@@ -11507,6 +11511,7 @@ function resolveOpensteerProvider(input = {}) {
|
|
|
11507
11511
|
var OPENSTEER_PROVIDER_MODES;
|
|
11508
11512
|
var init_config = __esm({
|
|
11509
11513
|
"src/provider/config.ts"() {
|
|
11514
|
+
init_src2();
|
|
11510
11515
|
OPENSTEER_PROVIDER_MODES = ["local", "cloud"];
|
|
11511
11516
|
}
|
|
11512
11517
|
});
|
|
@@ -11968,12 +11973,60 @@ function wrapCloudFetchError(error, input) {
|
|
|
11968
11973
|
wrapped.name = error.name;
|
|
11969
11974
|
return wrapped;
|
|
11970
11975
|
}
|
|
11971
|
-
|
|
11976
|
+
async function createCloudRequestError(response, input) {
|
|
11977
|
+
const payload = await readCloudErrorPayload(response);
|
|
11978
|
+
return new OpensteerCloudRequestError({
|
|
11979
|
+
statusCode: response.status,
|
|
11980
|
+
method: input.method,
|
|
11981
|
+
pathname: input.pathname,
|
|
11982
|
+
url: input.url,
|
|
11983
|
+
message: payload?.error ?? `${input.method} ${input.pathname} failed with ${String(response.status)}.`,
|
|
11984
|
+
...payload?.code === void 0 ? {} : { code: payload.code },
|
|
11985
|
+
...payload?.details === void 0 ? {} : { details: payload.details }
|
|
11986
|
+
});
|
|
11987
|
+
}
|
|
11988
|
+
async function readCloudErrorPayload(response) {
|
|
11989
|
+
try {
|
|
11990
|
+
return asCloudErrorPayload(await response.json());
|
|
11991
|
+
} catch {
|
|
11992
|
+
return void 0;
|
|
11993
|
+
}
|
|
11994
|
+
}
|
|
11995
|
+
function asCloudErrorPayload(value) {
|
|
11996
|
+
if (value === null || typeof value !== "object") {
|
|
11997
|
+
return void 0;
|
|
11998
|
+
}
|
|
11999
|
+
const payload = value;
|
|
12000
|
+
return {
|
|
12001
|
+
...typeof payload.error === "string" ? { error: payload.error } : {},
|
|
12002
|
+
...typeof payload.code === "string" ? { code: payload.code } : {},
|
|
12003
|
+
..."details" in payload ? { details: payload.details } : {}
|
|
12004
|
+
};
|
|
12005
|
+
}
|
|
12006
|
+
var CLOUD_CLOSE_TIMEOUT_MS, CLOUD_CLOSE_POLL_INTERVAL_MS, OpensteerCloudRequestError, OpensteerCloudClient;
|
|
11972
12007
|
var init_client = __esm({
|
|
11973
12008
|
"src/cloud/client.ts"() {
|
|
11974
12009
|
init_profile_sync();
|
|
11975
12010
|
CLOUD_CLOSE_TIMEOUT_MS = 6e4;
|
|
11976
12011
|
CLOUD_CLOSE_POLL_INTERVAL_MS = 250;
|
|
12012
|
+
OpensteerCloudRequestError = class extends Error {
|
|
12013
|
+
statusCode;
|
|
12014
|
+
code;
|
|
12015
|
+
details;
|
|
12016
|
+
method;
|
|
12017
|
+
pathname;
|
|
12018
|
+
url;
|
|
12019
|
+
constructor(args) {
|
|
12020
|
+
super(args.message);
|
|
12021
|
+
this.name = "OpensteerCloudRequestError";
|
|
12022
|
+
this.statusCode = args.statusCode;
|
|
12023
|
+
this.code = args.code;
|
|
12024
|
+
this.details = args.details;
|
|
12025
|
+
this.method = args.method;
|
|
12026
|
+
this.pathname = args.pathname;
|
|
12027
|
+
this.url = args.url;
|
|
12028
|
+
}
|
|
12029
|
+
};
|
|
11977
12030
|
OpensteerCloudClient = class {
|
|
11978
12031
|
constructor(config) {
|
|
11979
12032
|
this.config = config;
|
|
@@ -12149,7 +12202,11 @@ var init_client = __esm({
|
|
|
12149
12202
|
});
|
|
12150
12203
|
}
|
|
12151
12204
|
if (!response.ok) {
|
|
12152
|
-
throw
|
|
12205
|
+
throw await createCloudRequestError(response, {
|
|
12206
|
+
method: init.method,
|
|
12207
|
+
pathname,
|
|
12208
|
+
url
|
|
12209
|
+
});
|
|
12153
12210
|
}
|
|
12154
12211
|
return response;
|
|
12155
12212
|
}
|
|
@@ -12220,7 +12277,7 @@ var init_package = __esm({
|
|
|
12220
12277
|
"../runtime-core/package.json"() {
|
|
12221
12278
|
package_default2 = {
|
|
12222
12279
|
name: "@opensteer/runtime-core",
|
|
12223
|
-
version: "0.2.
|
|
12280
|
+
version: "0.2.5",
|
|
12224
12281
|
description: "Shared semantic runtime for Opensteer local and cloud execution.",
|
|
12225
12282
|
license: "MIT",
|
|
12226
12283
|
type: "module",
|
|
@@ -12372,7 +12429,7 @@ var init_errors3 = __esm({
|
|
|
12372
12429
|
function defaultPolicy() {
|
|
12373
12430
|
return DEFAULT_POLICY;
|
|
12374
12431
|
}
|
|
12375
|
-
var DEFAULT_TIMEOUTS, DEFAULT_SETTLE_DELAYS,
|
|
12432
|
+
var DEFAULT_TIMEOUTS, DEFAULT_SETTLE_DELAYS, DOM_ACTION_VISUAL_STABILITY_PROFILES, DEFAULT_DOM_ACTION_VISUAL_STABILITY_PROFILE, NAVIGATION_VISUAL_STABILITY_PROFILE, NAVIGATION_POST_LOAD_CAPTURE_WINDOW_MS, defaultDomActionSettleObserver, defaultNavigationSettleObserver, DEFAULT_SETTLE_OBSERVERS, defaultTimeoutPolicy, defaultSettlePolicy, defaultRetryPolicy, defaultFallbackPolicy, DEFAULT_POLICY;
|
|
12376
12433
|
var init_defaults = __esm({
|
|
12377
12434
|
"../runtime-core/src/policy/defaults.ts"() {
|
|
12378
12435
|
init_src();
|
|
@@ -12401,21 +12458,6 @@ var init_defaults = __esm({
|
|
|
12401
12458
|
"dom-action": 100,
|
|
12402
12459
|
snapshot: 0
|
|
12403
12460
|
};
|
|
12404
|
-
defaultSnapshotSettleObserver = {
|
|
12405
|
-
async settle(input) {
|
|
12406
|
-
if (input.trigger !== "snapshot") {
|
|
12407
|
-
return false;
|
|
12408
|
-
}
|
|
12409
|
-
await input.engine.waitForVisualStability({
|
|
12410
|
-
pageRef: input.pageRef,
|
|
12411
|
-
...input.remainingMs === void 0 ? {} : { timeoutMs: input.remainingMs },
|
|
12412
|
-
settleMs: DEFAULT_VISUAL_STABILITY_SETTLE_MS,
|
|
12413
|
-
scope: "visible-frames"
|
|
12414
|
-
});
|
|
12415
|
-
return true;
|
|
12416
|
-
}
|
|
12417
|
-
};
|
|
12418
|
-
Object.freeze(defaultSnapshotSettleObserver);
|
|
12419
12461
|
DOM_ACTION_VISUAL_STABILITY_PROFILES = {
|
|
12420
12462
|
"dom.click": { settleMs: 750, scope: "visible-frames", timeoutMs: 7e3 },
|
|
12421
12463
|
"dom.input": { settleMs: 750, scope: "visible-frames", timeoutMs: 7e3 },
|
|
@@ -12468,6 +12510,7 @@ var init_defaults = __esm({
|
|
|
12468
12510
|
return false;
|
|
12469
12511
|
}
|
|
12470
12512
|
try {
|
|
12513
|
+
const startedAt = Date.now();
|
|
12471
12514
|
await input.engine.waitForPostLoadQuiet({
|
|
12472
12515
|
pageRef: input.pageRef,
|
|
12473
12516
|
timeoutMs: effectiveTimeout,
|
|
@@ -12475,9 +12518,13 @@ var init_defaults = __esm({
|
|
|
12475
12518
|
captureWindowMs: Math.min(NAVIGATION_POST_LOAD_CAPTURE_WINDOW_MS, effectiveTimeout),
|
|
12476
12519
|
signal: input.signal
|
|
12477
12520
|
});
|
|
12521
|
+
const visualTimeout = Math.max(0, effectiveTimeout - (Date.now() - startedAt));
|
|
12522
|
+
if (visualTimeout <= 0) {
|
|
12523
|
+
return true;
|
|
12524
|
+
}
|
|
12478
12525
|
await input.engine.waitForVisualStability({
|
|
12479
12526
|
pageRef: input.pageRef,
|
|
12480
|
-
timeoutMs:
|
|
12527
|
+
timeoutMs: visualTimeout,
|
|
12481
12528
|
settleMs: profile.settleMs,
|
|
12482
12529
|
scope: profile.scope
|
|
12483
12530
|
});
|
|
@@ -12489,7 +12536,6 @@ var init_defaults = __esm({
|
|
|
12489
12536
|
};
|
|
12490
12537
|
Object.freeze(defaultNavigationSettleObserver);
|
|
12491
12538
|
DEFAULT_SETTLE_OBSERVERS = Object.freeze([
|
|
12492
|
-
defaultSnapshotSettleObserver,
|
|
12493
12539
|
defaultDomActionSettleObserver,
|
|
12494
12540
|
defaultNavigationSettleObserver
|
|
12495
12541
|
]);
|
|
@@ -12977,6 +13023,9 @@ function buildClauseSelector(node, clause) {
|
|
|
12977
13023
|
if (!clause || typeof clause !== "object") {
|
|
12978
13024
|
return "";
|
|
12979
13025
|
}
|
|
13026
|
+
if (clause.kind === "text") {
|
|
13027
|
+
return "";
|
|
13028
|
+
}
|
|
12980
13029
|
if (clause.kind === "position") {
|
|
12981
13030
|
if (clause.axis === "nthOfType") {
|
|
12982
13031
|
return `:nth-of-type(${Math.max(1, Number(node.position?.nthOfType || 1))})`;
|
|
@@ -13092,7 +13141,7 @@ function resolveExtractedValueInContext(normalizedValue, options) {
|
|
|
13092
13141
|
function stripPositionClauses(nodes) {
|
|
13093
13142
|
return (nodes || []).map((node) => ({
|
|
13094
13143
|
...node,
|
|
13095
|
-
match: (node.match || []).filter((clause) => clause.kind !== "position")
|
|
13144
|
+
match: (node.match || []).filter((clause) => clause.kind !== "position" && clause.kind !== "text")
|
|
13096
13145
|
}));
|
|
13097
13146
|
}
|
|
13098
13147
|
function dedupeSelectors(selectors) {
|
|
@@ -13680,9 +13729,17 @@ function resolveDomPathInScope(index, domPath, scope) {
|
|
|
13680
13729
|
if (!candidates.length) {
|
|
13681
13730
|
return null;
|
|
13682
13731
|
}
|
|
13732
|
+
const lastNode = domPath[domPath.length - 1];
|
|
13733
|
+
const textClauses = lastNode?.match.filter((c) => c.kind === "text") ?? [];
|
|
13683
13734
|
let fallback = null;
|
|
13684
13735
|
for (const selector of candidates) {
|
|
13685
|
-
|
|
13736
|
+
let matches = querySelectorAllInScope(index, selector, scope);
|
|
13737
|
+
if (textClauses.length > 0 && matches.length > 1) {
|
|
13738
|
+
const filtered = matches.filter((node) => matchesTextClauses(node, textClauses));
|
|
13739
|
+
if (filtered.length > 0) {
|
|
13740
|
+
matches = filtered;
|
|
13741
|
+
}
|
|
13742
|
+
}
|
|
13686
13743
|
if (matches.length === 1) {
|
|
13687
13744
|
return {
|
|
13688
13745
|
node: matches[0],
|
|
@@ -13702,6 +13759,10 @@ function resolveDomPathInScope(index, domPath, scope) {
|
|
|
13702
13759
|
}
|
|
13703
13760
|
return fallback;
|
|
13704
13761
|
}
|
|
13762
|
+
function matchesTextClauses(node, clauses) {
|
|
13763
|
+
const text = (node.textContent ?? "").replace(/\s+/g, " ").trim();
|
|
13764
|
+
return clauses.every((clause) => text.includes(clause.value));
|
|
13765
|
+
}
|
|
13705
13766
|
function queryAllDomPathInScope(index, domPath, scope) {
|
|
13706
13767
|
const selectors = buildPathCandidates(domPath);
|
|
13707
13768
|
for (const selector of selectors) {
|
|
@@ -13860,7 +13921,13 @@ function clonePathNode(node) {
|
|
|
13860
13921
|
};
|
|
13861
13922
|
}
|
|
13862
13923
|
function cloneMatchClause(clause) {
|
|
13863
|
-
|
|
13924
|
+
if (clause.kind === "position") {
|
|
13925
|
+
return { kind: "position", axis: clause.axis };
|
|
13926
|
+
}
|
|
13927
|
+
if (clause.kind === "text") {
|
|
13928
|
+
return { kind: "text", value: clause.value };
|
|
13929
|
+
}
|
|
13930
|
+
return {
|
|
13864
13931
|
kind: "attr",
|
|
13865
13932
|
key: clause.key,
|
|
13866
13933
|
...clause.op === void 0 ? {} : { op: clause.op },
|
|
@@ -13915,6 +13982,13 @@ function normalizeMatch(rawMatch, attrs, position, tag) {
|
|
|
13915
13982
|
op,
|
|
13916
13983
|
...value === void 0 ? {} : { value }
|
|
13917
13984
|
});
|
|
13985
|
+
continue;
|
|
13986
|
+
}
|
|
13987
|
+
if (record.kind === "text") {
|
|
13988
|
+
const textValue = typeof record.value === "string" ? record.value.trim() : "";
|
|
13989
|
+
if (textValue) {
|
|
13990
|
+
push({ kind: "text", value: textValue.slice(0, 80) });
|
|
13991
|
+
}
|
|
13918
13992
|
}
|
|
13919
13993
|
}
|
|
13920
13994
|
}
|
|
@@ -14329,7 +14403,7 @@ var init_executor = __esm({
|
|
|
14329
14403
|
init_action_boundary2();
|
|
14330
14404
|
init_policy();
|
|
14331
14405
|
init_bridge();
|
|
14332
|
-
MAX_DOM_ACTION_ATTEMPTS =
|
|
14406
|
+
MAX_DOM_ACTION_ATTEMPTS = 2;
|
|
14333
14407
|
DEFAULT_SCROLL_OPTIONS = {
|
|
14334
14408
|
block: "center",
|
|
14335
14409
|
inline: "center"
|
|
@@ -14816,11 +14890,12 @@ var init_executor = __esm({
|
|
|
14816
14890
|
throw this.createActionabilityError(
|
|
14817
14891
|
operation,
|
|
14818
14892
|
"obscured",
|
|
14819
|
-
`
|
|
14893
|
+
`target is obscured by ${assessment.blockingDescription ?? "another element"} at the click point`,
|
|
14820
14894
|
{
|
|
14821
14895
|
...details,
|
|
14822
14896
|
hitRelation: assessment.relation,
|
|
14823
14897
|
...assessment.ambiguous === void 0 ? {} : { hitAmbiguous: assessment.ambiguous },
|
|
14898
|
+
...assessment.blockingDescription === void 0 ? {} : { blockingDescription: assessment.blockingDescription },
|
|
14824
14899
|
...assessment.canonicalTarget === void 0 ? {} : {
|
|
14825
14900
|
canonicalNodeRef: assessment.canonicalTarget.nodeRef,
|
|
14826
14901
|
canonicalDocumentRef: assessment.canonicalTarget.documentRef,
|
|
@@ -14834,8 +14909,7 @@ var init_executor = __esm({
|
|
|
14834
14909
|
hitMissingFromSnapshot: !resolved.snapshot.nodes.some(
|
|
14835
14910
|
(node) => node.nodeRef === hit.nodeRef
|
|
14836
14911
|
)
|
|
14837
|
-
}
|
|
14838
|
-
true
|
|
14912
|
+
}
|
|
14839
14913
|
);
|
|
14840
14914
|
}
|
|
14841
14915
|
async resolveActionablePointerTarget(session, operation, resolved) {
|
|
@@ -15026,7 +15100,12 @@ var init_runtime = __esm({
|
|
|
15026
15100
|
});
|
|
15027
15101
|
}
|
|
15028
15102
|
async buildPath(input) {
|
|
15029
|
-
return sanitizeReplayElementPath(
|
|
15103
|
+
return sanitizeReplayElementPath(
|
|
15104
|
+
await this.requireBridge().buildReplayPath(
|
|
15105
|
+
input.locator,
|
|
15106
|
+
input.enableTextMatch ? { enableTextMatch: true } : void 0
|
|
15107
|
+
)
|
|
15108
|
+
);
|
|
15030
15109
|
}
|
|
15031
15110
|
async resolveTarget(input) {
|
|
15032
15111
|
return this.withSnapshotSession((session) => this.resolveTargetWithSession(session, input));
|
|
@@ -15246,7 +15325,7 @@ var init_runtime = __esm({
|
|
|
15246
15325
|
if (resolvedByLocator) {
|
|
15247
15326
|
const { snapshot, node } = resolvedByLocator;
|
|
15248
15327
|
const anchor = await this.buildAnchorFromSnapshotNode(session, snapshot, node);
|
|
15249
|
-
const replayPath = await this.tryBuildPathFromNode(snapshot, node);
|
|
15328
|
+
const replayPath = await this.tryBuildPathFromNode(snapshot, node, { enableTextMatch: true });
|
|
15250
15329
|
return this.createResolvedTarget("live", snapshot, node, anchor, {
|
|
15251
15330
|
...target.persist === void 0 ? {} : { persist: target.persist },
|
|
15252
15331
|
...replayPath === void 0 ? {} : { replayPath }
|
|
@@ -15264,11 +15343,12 @@ var init_runtime = __esm({
|
|
|
15264
15343
|
const { snapshot, node } = resolved;
|
|
15265
15344
|
const anchor = await this.buildAnchorFromSnapshotNode(session, snapshot, node);
|
|
15266
15345
|
const writeDescriptor = descriptorWriter ?? ((input) => this.descriptors.write(input));
|
|
15267
|
-
const
|
|
15346
|
+
const enableTextMatch = method !== "extract";
|
|
15347
|
+
const replayPath = await this.tryBuildPathFromNode(snapshot, node, { enableTextMatch });
|
|
15268
15348
|
const descriptor = target.persist === void 0 ? void 0 : await writeDescriptor({
|
|
15269
15349
|
method,
|
|
15270
15350
|
persist: target.persist,
|
|
15271
|
-
path: replayPath ?? await this.buildPathForNode(snapshot, node),
|
|
15351
|
+
path: replayPath ?? await this.buildPathForNode(snapshot, node, { enableTextMatch }),
|
|
15272
15352
|
sourceUrl: snapshot.url
|
|
15273
15353
|
});
|
|
15274
15354
|
return this.createResolvedTarget("selector", snapshot, node, anchor, {
|
|
@@ -15368,7 +15448,7 @@ var init_runtime = __esm({
|
|
|
15368
15448
|
`Unable to resolve structural anchor "${buildPathSelectorHint(anchor)}" in the current session`
|
|
15369
15449
|
);
|
|
15370
15450
|
}
|
|
15371
|
-
const replayPath = await this.tryBuildPathFromNode(context.snapshot, target.node);
|
|
15451
|
+
const replayPath = await this.tryBuildPathFromNode(context.snapshot, target.node, { enableTextMatch: true });
|
|
15372
15452
|
return this.createResolvedTarget(source, context.snapshot, target.node, anchor, {
|
|
15373
15453
|
...persist === void 0 ? {} : { persist },
|
|
15374
15454
|
...replayPath === void 0 ? {} : { replayPath }
|
|
@@ -15539,19 +15619,20 @@ var init_runtime = __esm({
|
|
|
15539
15619
|
}
|
|
15540
15620
|
return this.bridge;
|
|
15541
15621
|
}
|
|
15542
|
-
async buildPathForNode(snapshot, node) {
|
|
15622
|
+
async buildPathForNode(snapshot, node, options) {
|
|
15543
15623
|
if (node.nodeRef === void 0) {
|
|
15544
15624
|
throw new Error(
|
|
15545
15625
|
`snapshot node ${String(node.snapshotNodeId)} does not expose a live node reference`
|
|
15546
15626
|
);
|
|
15547
15627
|
}
|
|
15548
15628
|
return this.buildPath({
|
|
15549
|
-
locator: createNodeLocator(snapshot.documentRef, snapshot.documentEpoch, node.nodeRef)
|
|
15629
|
+
locator: createNodeLocator(snapshot.documentRef, snapshot.documentEpoch, node.nodeRef),
|
|
15630
|
+
...options?.enableTextMatch ? { enableTextMatch: true } : {}
|
|
15550
15631
|
});
|
|
15551
15632
|
}
|
|
15552
|
-
async tryBuildPathFromNode(snapshot, node) {
|
|
15633
|
+
async tryBuildPathFromNode(snapshot, node, options) {
|
|
15553
15634
|
try {
|
|
15554
|
-
return await this.buildPathForNode(snapshot, node);
|
|
15635
|
+
return await this.buildPathForNode(snapshot, node, options);
|
|
15555
15636
|
} catch {
|
|
15556
15637
|
return void 0;
|
|
15557
15638
|
}
|
|
@@ -17121,6 +17202,9 @@ function relaxPathForSingleSample(path24, mode) {
|
|
|
17121
17202
|
}
|
|
17122
17203
|
return !isLast;
|
|
17123
17204
|
}
|
|
17205
|
+
if (clause.kind === "text") {
|
|
17206
|
+
return false;
|
|
17207
|
+
}
|
|
17124
17208
|
const key = String(clause.key || "").trim().toLowerCase();
|
|
17125
17209
|
if (!key || !shouldKeepAttrForSingleSample(key)) {
|
|
17126
17210
|
return false;
|
|
@@ -17223,9 +17307,11 @@ function buildNodeStructure(node) {
|
|
|
17223
17307
|
}
|
|
17224
17308
|
structuralAttrs[key] = value;
|
|
17225
17309
|
}
|
|
17226
|
-
const matchClauses = (node.match || []).map(
|
|
17227
|
-
(clause
|
|
17228
|
-
|
|
17310
|
+
const matchClauses = (node.match || []).map((clause) => {
|
|
17311
|
+
if (clause.kind === "position") return `position:${clause.axis}`;
|
|
17312
|
+
if (clause.kind === "text") return `text:${clause.value}`;
|
|
17313
|
+
return `attr:${String(clause.key || "").trim().toLowerCase()}`;
|
|
17314
|
+
}).sort();
|
|
17229
17315
|
return {
|
|
17230
17316
|
tag,
|
|
17231
17317
|
attrs: structuralAttrs,
|
|
@@ -17631,6 +17717,9 @@ function mergeMatchByMajority(matchLists, attrs, threshold, positionFlags = {
|
|
|
17631
17717
|
});
|
|
17632
17718
|
continue;
|
|
17633
17719
|
}
|
|
17720
|
+
if (clause.kind === "text") {
|
|
17721
|
+
continue;
|
|
17722
|
+
}
|
|
17634
17723
|
if (clause.axis === "nthOfType") {
|
|
17635
17724
|
if (positionFlags.hasNthOfType) {
|
|
17636
17725
|
merged.push({ kind: "position", axis: "nthOfType" });
|
|
@@ -17809,9 +17898,9 @@ var init_extraction_consolidation = __esm({
|
|
|
17809
17898
|
CLUSTER_FALLBACK_PREFIX = "variant";
|
|
17810
17899
|
}
|
|
17811
17900
|
});
|
|
17812
|
-
function
|
|
17813
|
-
if (!
|
|
17814
|
-
throw new Error("Invalid extraction
|
|
17901
|
+
function assertValidOpensteerExtractionTemplateRoot(template) {
|
|
17902
|
+
if (!template || typeof template !== "object" || Array.isArray(template)) {
|
|
17903
|
+
throw new Error("Invalid extraction template: expected a JSON object at the top level.");
|
|
17815
17904
|
}
|
|
17816
17905
|
}
|
|
17817
17906
|
function isPersistedOpensteerExtractionValueNode2(value) {
|
|
@@ -17833,12 +17922,12 @@ function isPersistedOpensteerExtractionArrayNode2(value) {
|
|
|
17833
17922
|
return "$array" in value;
|
|
17834
17923
|
}
|
|
17835
17924
|
async function compileOpensteerExtractionFieldTargets(options) {
|
|
17836
|
-
|
|
17925
|
+
assertValidOpensteerExtractionTemplateRoot(options.template);
|
|
17837
17926
|
const fields = [];
|
|
17838
|
-
await
|
|
17927
|
+
await collectFieldTargetsFromTemplateObject({
|
|
17839
17928
|
dom: options.dom,
|
|
17840
17929
|
pageRef: options.pageRef,
|
|
17841
|
-
value: options.
|
|
17930
|
+
value: options.template,
|
|
17842
17931
|
path: "",
|
|
17843
17932
|
fields,
|
|
17844
17933
|
insideArray: false
|
|
@@ -17890,13 +17979,13 @@ function createOpensteerExtractionDescriptorStore(options) {
|
|
|
17890
17979
|
}
|
|
17891
17980
|
return new MemoryOpensteerExtractionDescriptorStore(namespace);
|
|
17892
17981
|
}
|
|
17893
|
-
async function
|
|
17982
|
+
async function collectFieldTargetsFromTemplateObject(options) {
|
|
17894
17983
|
for (const [key, childValue] of Object.entries(options.value)) {
|
|
17895
17984
|
const normalizedKey = normalizeKey(key);
|
|
17896
17985
|
if (!normalizedKey) {
|
|
17897
17986
|
continue;
|
|
17898
17987
|
}
|
|
17899
|
-
await
|
|
17988
|
+
await collectFieldTargetsFromTemplateValue({
|
|
17900
17989
|
dom: options.dom,
|
|
17901
17990
|
pageRef: options.pageRef,
|
|
17902
17991
|
value: childValue,
|
|
@@ -17906,8 +17995,8 @@ async function collectFieldTargetsFromSchemaObject(options) {
|
|
|
17906
17995
|
});
|
|
17907
17996
|
}
|
|
17908
17997
|
}
|
|
17909
|
-
async function
|
|
17910
|
-
const normalizedField =
|
|
17998
|
+
async function collectFieldTargetsFromTemplateValue(options) {
|
|
17999
|
+
const normalizedField = normalizeTemplateField(options.value);
|
|
17911
18000
|
if (normalizedField !== null) {
|
|
17912
18001
|
options.fields.push(
|
|
17913
18002
|
await compileFieldTarget({
|
|
@@ -17922,12 +18011,12 @@ async function collectFieldTargetsFromSchemaValue(options) {
|
|
|
17922
18011
|
if (Array.isArray(options.value)) {
|
|
17923
18012
|
if (options.insideArray) {
|
|
17924
18013
|
throw new Error(
|
|
17925
|
-
`Nested arrays are not supported in extraction
|
|
18014
|
+
`Nested arrays are not supported in extraction template at "${labelForPath(options.path)}".`
|
|
17926
18015
|
);
|
|
17927
18016
|
}
|
|
17928
18017
|
if (options.value.length === 0) {
|
|
17929
18018
|
throw new Error(
|
|
17930
|
-
`Extraction array "${labelForPath(options.path)}" must include at least one representative item.`
|
|
18019
|
+
`Extraction array "${labelForPath(options.path)}" must include at least one representative template item.`
|
|
17931
18020
|
);
|
|
17932
18021
|
}
|
|
17933
18022
|
for (let index = 0; index < options.value.length; index += 1) {
|
|
@@ -17938,7 +18027,7 @@ async function collectFieldTargetsFromSchemaValue(options) {
|
|
|
17938
18027
|
);
|
|
17939
18028
|
}
|
|
17940
18029
|
const fieldCountBeforeItem = options.fields.length;
|
|
17941
|
-
await
|
|
18030
|
+
await collectFieldTargetsFromTemplateObject({
|
|
17942
18031
|
dom: options.dom,
|
|
17943
18032
|
pageRef: options.pageRef,
|
|
17944
18033
|
value: itemValue,
|
|
@@ -17949,7 +18038,7 @@ async function collectFieldTargetsFromSchemaValue(options) {
|
|
|
17949
18038
|
const itemFields = options.fields.slice(fieldCountBeforeItem);
|
|
17950
18039
|
if (!itemFields.some((field) => !("source" in field))) {
|
|
17951
18040
|
throw new Error(
|
|
17952
|
-
`Extraction array "${labelForPath(options.path)}" item ${String(index)} must include at least one element
|
|
18041
|
+
`Extraction array "${labelForPath(options.path)}" item ${String(index)} must include at least one element number or selector field.`
|
|
17953
18042
|
);
|
|
17954
18043
|
}
|
|
17955
18044
|
}
|
|
@@ -17957,10 +18046,10 @@ async function collectFieldTargetsFromSchemaValue(options) {
|
|
|
17957
18046
|
}
|
|
17958
18047
|
if (!options.value || typeof options.value !== "object") {
|
|
17959
18048
|
throw new Error(
|
|
17960
|
-
`Invalid extraction
|
|
18049
|
+
`Invalid extraction template value at "${labelForPath(options.path)}": expected an object, array, or field descriptor.`
|
|
17961
18050
|
);
|
|
17962
18051
|
}
|
|
17963
|
-
await
|
|
18052
|
+
await collectFieldTargetsFromTemplateObject({
|
|
17964
18053
|
dom: options.dom,
|
|
17965
18054
|
pageRef: options.pageRef,
|
|
17966
18055
|
value: options.value,
|
|
@@ -17992,7 +18081,7 @@ async function compileFieldTarget(options) {
|
|
|
17992
18081
|
path: await resolveSelectorFieldPath({
|
|
17993
18082
|
dom: options.dom,
|
|
17994
18083
|
pageRef: options.pageRef,
|
|
17995
|
-
selector: `[c="${String(options.field.
|
|
18084
|
+
selector: `[c="${String(options.field.c)}"]`
|
|
17996
18085
|
}),
|
|
17997
18086
|
...options.field.attribute === void 0 ? {} : { attribute: options.field.attribute }
|
|
17998
18087
|
};
|
|
@@ -18293,24 +18382,29 @@ function countNonNullLeaves(value) {
|
|
|
18293
18382
|
}
|
|
18294
18383
|
return Object.values(value).reduce((sum, item) => sum + countNonNullLeaves(item), 0);
|
|
18295
18384
|
}
|
|
18296
|
-
function
|
|
18385
|
+
function normalizeTemplateField(value) {
|
|
18386
|
+
if (typeof value === "number") {
|
|
18387
|
+
return {
|
|
18388
|
+
c: normalizeExtractionCounter(value)
|
|
18389
|
+
};
|
|
18390
|
+
}
|
|
18297
18391
|
if (!value || typeof value !== "object" || Array.isArray(value)) {
|
|
18298
18392
|
return null;
|
|
18299
18393
|
}
|
|
18300
18394
|
const raw = value;
|
|
18301
|
-
const
|
|
18395
|
+
const hasCounter = raw.c !== void 0 || raw.element !== void 0;
|
|
18302
18396
|
const hasSelector = raw.selector !== void 0;
|
|
18303
18397
|
const hasSource = raw.source !== void 0;
|
|
18304
|
-
const targetCount = Number(
|
|
18398
|
+
const targetCount = Number(hasCounter) + Number(hasSelector) + Number(hasSource);
|
|
18305
18399
|
if (targetCount === 0) {
|
|
18306
18400
|
return null;
|
|
18307
18401
|
}
|
|
18308
18402
|
if (targetCount !== 1) {
|
|
18309
18403
|
throw new Error(
|
|
18310
|
-
"Extraction field descriptors must specify exactly one of element, selector, or source."
|
|
18404
|
+
"Extraction field descriptors must specify exactly one of c/element, selector, or source."
|
|
18311
18405
|
);
|
|
18312
18406
|
}
|
|
18313
|
-
const attribute = raw.attribute === void 0 ? void 0 : normalizeNonEmptyString2("attribute", raw.attribute);
|
|
18407
|
+
const attribute = raw.attr !== void 0 ? normalizeNonEmptyString2("attr", raw.attr) : raw.attribute === void 0 ? void 0 : normalizeNonEmptyString2("attribute", raw.attribute);
|
|
18314
18408
|
if (hasSource) {
|
|
18315
18409
|
if (raw.source !== "current_url") {
|
|
18316
18410
|
throw new Error(`Unsupported extraction source "${String(raw.source)}".`);
|
|
@@ -18325,17 +18419,20 @@ function normalizeSchemaField(value) {
|
|
|
18325
18419
|
...attribute === void 0 ? {} : { attribute }
|
|
18326
18420
|
};
|
|
18327
18421
|
}
|
|
18328
|
-
const element = Number(raw.element);
|
|
18329
|
-
if (!Number.isInteger(element) || element < 1) {
|
|
18330
|
-
throw new Error(
|
|
18331
|
-
`Extraction field element must be a positive integer, received ${String(raw.element)}.`
|
|
18332
|
-
);
|
|
18333
|
-
}
|
|
18334
18422
|
return {
|
|
18335
|
-
element,
|
|
18423
|
+
c: normalizeExtractionCounter(raw.c ?? raw.element),
|
|
18336
18424
|
...attribute === void 0 ? {} : { attribute }
|
|
18337
18425
|
};
|
|
18338
18426
|
}
|
|
18427
|
+
function normalizeExtractionCounter(value) {
|
|
18428
|
+
const counter = Number(value);
|
|
18429
|
+
if (!Number.isInteger(counter) || counter < 1) {
|
|
18430
|
+
throw new Error(
|
|
18431
|
+
`Extraction element number must be a positive integer, received ${String(value)}.`
|
|
18432
|
+
);
|
|
18433
|
+
}
|
|
18434
|
+
return counter;
|
|
18435
|
+
}
|
|
18339
18436
|
function normalizeNamespace(namespace) {
|
|
18340
18437
|
const normalized = String(namespace ?? "default").trim();
|
|
18341
18438
|
return normalized.length === 0 ? "default" : normalized;
|
|
@@ -18366,7 +18463,7 @@ function parseExtractionDescriptorRecord(record) {
|
|
|
18366
18463
|
kind: "dom-extraction",
|
|
18367
18464
|
persist: raw.persist,
|
|
18368
18465
|
root,
|
|
18369
|
-
...typeof raw.schemaHash === "string" ? {
|
|
18466
|
+
...typeof raw.templateHash === "string" ? { templateHash: raw.templateHash } : typeof raw.schemaHash === "string" ? { templateHash: raw.schemaHash } : {},
|
|
18370
18467
|
...typeof raw.sourceUrl === "string" ? { sourceUrl: raw.sourceUrl } : {}
|
|
18371
18468
|
}
|
|
18372
18469
|
};
|
|
@@ -18475,7 +18572,7 @@ var init_extraction2 = __esm({
|
|
|
18475
18572
|
kind: "dom-extraction",
|
|
18476
18573
|
persist: input.persist,
|
|
18477
18574
|
root: input.root,
|
|
18478
|
-
...input.
|
|
18575
|
+
...input.templateHash === void 0 ? {} : { templateHash: input.templateHash },
|
|
18479
18576
|
...input.sourceUrl === void 0 ? {} : { sourceUrl: input.sourceUrl }
|
|
18480
18577
|
};
|
|
18481
18578
|
const key = persistKey(this.namespace, input.persist);
|
|
@@ -18524,7 +18621,7 @@ var init_extraction2 = __esm({
|
|
|
18524
18621
|
kind: "dom-extraction",
|
|
18525
18622
|
persist: input.persist,
|
|
18526
18623
|
root: input.root,
|
|
18527
|
-
...input.
|
|
18624
|
+
...input.templateHash === void 0 ? {} : { templateHash: input.templateHash },
|
|
18528
18625
|
...input.sourceUrl === void 0 ? {} : { sourceUrl: input.sourceUrl }
|
|
18529
18626
|
};
|
|
18530
18627
|
const key = persistKey(this.namespace, input.persist);
|
|
@@ -18701,19 +18798,260 @@ function truncateValue(value, max) {
|
|
|
18701
18798
|
}
|
|
18702
18799
|
return `${head}${TRUNCATION_SUFFIX}`;
|
|
18703
18800
|
}
|
|
18801
|
+
function takeValueWithinSerializedLengthFromEnd(value, max) {
|
|
18802
|
+
let serializedLength = 0;
|
|
18803
|
+
const chars = [];
|
|
18804
|
+
for (let index = value.length - 1; index >= 0; index -= 1) {
|
|
18805
|
+
const char = value[index];
|
|
18806
|
+
let nextLength = 1;
|
|
18807
|
+
if (char === "&") {
|
|
18808
|
+
nextLength = 5;
|
|
18809
|
+
} else if (char === "<" || char === ">") {
|
|
18810
|
+
nextLength = 4;
|
|
18811
|
+
} else if (char === '"') {
|
|
18812
|
+
nextLength = 6;
|
|
18813
|
+
}
|
|
18814
|
+
if (serializedLength + nextLength > max) {
|
|
18815
|
+
break;
|
|
18816
|
+
}
|
|
18817
|
+
chars.push(char);
|
|
18818
|
+
serializedLength += nextLength;
|
|
18819
|
+
}
|
|
18820
|
+
return chars.reverse().join("");
|
|
18821
|
+
}
|
|
18822
|
+
function truncateValueInMiddle(value, headMax, tailMax, marker = MIDDLE_TRUNCATION_MARKER) {
|
|
18823
|
+
const markerLength = getSerializedLength(marker);
|
|
18824
|
+
const max = headMax + markerLength + tailMax;
|
|
18825
|
+
if (getSerializedLength(value) <= max) {
|
|
18826
|
+
return value;
|
|
18827
|
+
}
|
|
18828
|
+
const head = takeValueWithinSerializedLength(value, headMax).replace(/\s+$/u, "");
|
|
18829
|
+
const tail = takeValueWithinSerializedLengthFromEnd(value, tailMax).replace(/^\s+/u, "");
|
|
18830
|
+
if (head.length === 0) {
|
|
18831
|
+
return tail.length === 0 ? marker : `${marker}${tail}`;
|
|
18832
|
+
}
|
|
18833
|
+
if (tail.length === 0) {
|
|
18834
|
+
return `${head}${marker}`;
|
|
18835
|
+
}
|
|
18836
|
+
return `${head}${marker}${tail}`;
|
|
18837
|
+
}
|
|
18704
18838
|
function getAttrLimit(attr) {
|
|
18705
|
-
if (
|
|
18706
|
-
return
|
|
18839
|
+
if (attr === "srcset") {
|
|
18840
|
+
return SRCSET_ATTR_MAX;
|
|
18707
18841
|
}
|
|
18708
18842
|
if (TEXT_ATTRS.has(attr)) {
|
|
18709
18843
|
return TEXT_ATTR_MAX;
|
|
18710
18844
|
}
|
|
18711
18845
|
return void 0;
|
|
18712
18846
|
}
|
|
18847
|
+
function shouldBoundAttr(attr) {
|
|
18848
|
+
return MIDDLE_TRUNCATED_URL_ATTRS.has(attr) || getAttrLimit(attr) !== void 0;
|
|
18849
|
+
}
|
|
18713
18850
|
function setBoundedAttr(el, attr, value) {
|
|
18851
|
+
if (MIDDLE_TRUNCATED_URL_ATTRS.has(attr)) {
|
|
18852
|
+
el.attr(
|
|
18853
|
+
attr,
|
|
18854
|
+
truncateValueInMiddle(value, MIDDLE_TRUNCATION_HEAD_MAX, MIDDLE_TRUNCATION_TAIL_MAX)
|
|
18855
|
+
);
|
|
18856
|
+
return;
|
|
18857
|
+
}
|
|
18714
18858
|
const limit = getAttrLimit(attr);
|
|
18859
|
+
if (attr === "srcset" && limit !== void 0) {
|
|
18860
|
+
el.attr(attr, truncateSrcsetValue(value, limit));
|
|
18861
|
+
return;
|
|
18862
|
+
}
|
|
18715
18863
|
el.attr(attr, limit === void 0 ? value : truncateValue(value, limit));
|
|
18716
18864
|
}
|
|
18865
|
+
function truncateSrcsetValue(value, max) {
|
|
18866
|
+
if (getSerializedLength(value) <= max) {
|
|
18867
|
+
return value;
|
|
18868
|
+
}
|
|
18869
|
+
const candidates = parseSrcsetCandidates2(value);
|
|
18870
|
+
if (candidates.length === 0) {
|
|
18871
|
+
return truncateValueInMiddle(value, SRCSET_FALLBACK_HEAD_MAX, SRCSET_FALLBACK_TAIL_MAX);
|
|
18872
|
+
}
|
|
18873
|
+
for (const [headMax, tailMax, includeBest] of [
|
|
18874
|
+
[SRCSET_CANDIDATE_HEAD_MAX, SRCSET_CANDIDATE_TAIL_MAX, true],
|
|
18875
|
+
[SRCSET_COMPACT_CANDIDATE_HEAD_MAX, SRCSET_COMPACT_CANDIDATE_TAIL_MAX, true],
|
|
18876
|
+
[SRCSET_COMPACT_CANDIDATE_HEAD_MAX, SRCSET_COMPACT_CANDIDATE_TAIL_MAX, false]
|
|
18877
|
+
]) {
|
|
18878
|
+
const compact = buildTruncatedSrcsetValue(candidates, headMax, tailMax, includeBest);
|
|
18879
|
+
if (getSerializedLength(compact) <= max) {
|
|
18880
|
+
return compact;
|
|
18881
|
+
}
|
|
18882
|
+
}
|
|
18883
|
+
return truncateValueInMiddle(value, SRCSET_FALLBACK_HEAD_MAX, SRCSET_FALLBACK_TAIL_MAX);
|
|
18884
|
+
}
|
|
18885
|
+
function buildTruncatedSrcsetValue(candidates, headMax, tailMax, includeBest) {
|
|
18886
|
+
const kept = getPreferredSrcsetCandidateIndices(candidates, includeBest);
|
|
18887
|
+
const parts = [];
|
|
18888
|
+
let previousIndex;
|
|
18889
|
+
for (const candidateIndex of kept) {
|
|
18890
|
+
if (previousIndex !== void 0 && candidateIndex - previousIndex > 1) {
|
|
18891
|
+
parts.push(MIDDLE_TRUNCATION_MARKER);
|
|
18892
|
+
}
|
|
18893
|
+
parts.push(formatSrcsetCandidate(candidates[candidateIndex], headMax, tailMax));
|
|
18894
|
+
previousIndex = candidateIndex;
|
|
18895
|
+
}
|
|
18896
|
+
return parts.join(", ");
|
|
18897
|
+
}
|
|
18898
|
+
function getPreferredSrcsetCandidateIndices(candidates, includeBest) {
|
|
18899
|
+
if (candidates.length === 0) {
|
|
18900
|
+
return [];
|
|
18901
|
+
}
|
|
18902
|
+
const kept = /* @__PURE__ */ new Set([0, candidates.length - 1]);
|
|
18903
|
+
if (includeBest) {
|
|
18904
|
+
kept.add(pickBestSrcsetCandidateIndex(candidates));
|
|
18905
|
+
}
|
|
18906
|
+
return [...kept].filter((index) => index >= 0 && index < candidates.length).sort((a, b) => a - b);
|
|
18907
|
+
}
|
|
18908
|
+
function pickBestSrcsetCandidateIndex(candidates) {
|
|
18909
|
+
let bestWidthIndex = -1;
|
|
18910
|
+
let bestWidth = -1;
|
|
18911
|
+
let bestDensityIndex = -1;
|
|
18912
|
+
let bestDensity = -1;
|
|
18913
|
+
for (let index = 0; index < candidates.length; index += 1) {
|
|
18914
|
+
const candidate = candidates[index];
|
|
18915
|
+
if (typeof candidate.width === "number" && Number.isFinite(candidate.width) && candidate.width > bestWidth) {
|
|
18916
|
+
bestWidth = candidate.width;
|
|
18917
|
+
bestWidthIndex = index;
|
|
18918
|
+
}
|
|
18919
|
+
if (typeof candidate.density === "number" && Number.isFinite(candidate.density) && candidate.density > bestDensity) {
|
|
18920
|
+
bestDensity = candidate.density;
|
|
18921
|
+
bestDensityIndex = index;
|
|
18922
|
+
}
|
|
18923
|
+
}
|
|
18924
|
+
if (bestWidthIndex >= 0) {
|
|
18925
|
+
return bestWidthIndex;
|
|
18926
|
+
}
|
|
18927
|
+
if (bestDensityIndex >= 0) {
|
|
18928
|
+
return bestDensityIndex;
|
|
18929
|
+
}
|
|
18930
|
+
return candidates.length - 1;
|
|
18931
|
+
}
|
|
18932
|
+
function formatSrcsetCandidate(candidate, headMax, tailMax) {
|
|
18933
|
+
const url = truncateValueInMiddle(candidate.url, headMax, tailMax);
|
|
18934
|
+
return candidate.descriptorText ? `${url} ${candidate.descriptorText}` : url;
|
|
18935
|
+
}
|
|
18936
|
+
function parseSrcsetCandidates2(raw) {
|
|
18937
|
+
const text = raw.trim();
|
|
18938
|
+
if (!text) {
|
|
18939
|
+
return [];
|
|
18940
|
+
}
|
|
18941
|
+
const out = [];
|
|
18942
|
+
let index = 0;
|
|
18943
|
+
while (index < text.length) {
|
|
18944
|
+
index = skipSrcsetSeparators(text, index);
|
|
18945
|
+
if (index >= text.length) {
|
|
18946
|
+
break;
|
|
18947
|
+
}
|
|
18948
|
+
const urlToken = readSrcsetUrlToken(text, index);
|
|
18949
|
+
index = urlToken.nextIndex;
|
|
18950
|
+
const url = urlToken.value.trim();
|
|
18951
|
+
if (!url) {
|
|
18952
|
+
continue;
|
|
18953
|
+
}
|
|
18954
|
+
index = skipSrcsetWhitespace(text, index);
|
|
18955
|
+
const descriptors = [];
|
|
18956
|
+
while (index < text.length && text[index] !== ",") {
|
|
18957
|
+
const descriptorToken = readSrcsetDescriptorToken(text, index);
|
|
18958
|
+
if (!descriptorToken.value) {
|
|
18959
|
+
index = descriptorToken.nextIndex;
|
|
18960
|
+
continue;
|
|
18961
|
+
}
|
|
18962
|
+
descriptors.push(descriptorToken.value);
|
|
18963
|
+
index = descriptorToken.nextIndex;
|
|
18964
|
+
index = skipSrcsetWhitespace(text, index);
|
|
18965
|
+
}
|
|
18966
|
+
if (index < text.length && text[index] === ",") {
|
|
18967
|
+
index += 1;
|
|
18968
|
+
}
|
|
18969
|
+
let width = null;
|
|
18970
|
+
let density = null;
|
|
18971
|
+
for (const descriptor of descriptors) {
|
|
18972
|
+
const token = descriptor.trim().toLowerCase();
|
|
18973
|
+
if (!token) {
|
|
18974
|
+
continue;
|
|
18975
|
+
}
|
|
18976
|
+
const widthMatch = token.match(/^(\d+)w$/);
|
|
18977
|
+
if (widthMatch) {
|
|
18978
|
+
const parsed = Number.parseInt(widthMatch[1], 10);
|
|
18979
|
+
if (Number.isFinite(parsed)) {
|
|
18980
|
+
width = parsed;
|
|
18981
|
+
}
|
|
18982
|
+
continue;
|
|
18983
|
+
}
|
|
18984
|
+
const densityMatch = token.match(/^(\d*\.?\d+)x$/);
|
|
18985
|
+
if (densityMatch) {
|
|
18986
|
+
const parsed = Number.parseFloat(densityMatch[1]);
|
|
18987
|
+
if (Number.isFinite(parsed)) {
|
|
18988
|
+
density = parsed;
|
|
18989
|
+
}
|
|
18990
|
+
}
|
|
18991
|
+
}
|
|
18992
|
+
out.push({
|
|
18993
|
+
url,
|
|
18994
|
+
descriptorText: descriptors.join(" "),
|
|
18995
|
+
width,
|
|
18996
|
+
density
|
|
18997
|
+
});
|
|
18998
|
+
}
|
|
18999
|
+
return out;
|
|
19000
|
+
}
|
|
19001
|
+
function skipSrcsetWhitespace(value, index) {
|
|
19002
|
+
let cursor = index;
|
|
19003
|
+
while (cursor < value.length && /\s/u.test(value[cursor])) {
|
|
19004
|
+
cursor += 1;
|
|
19005
|
+
}
|
|
19006
|
+
return cursor;
|
|
19007
|
+
}
|
|
19008
|
+
function skipSrcsetSeparators(value, index) {
|
|
19009
|
+
let cursor = skipSrcsetWhitespace(value, index);
|
|
19010
|
+
while (cursor < value.length && value[cursor] === ",") {
|
|
19011
|
+
cursor += 1;
|
|
19012
|
+
cursor = skipSrcsetWhitespace(value, cursor);
|
|
19013
|
+
}
|
|
19014
|
+
return cursor;
|
|
19015
|
+
}
|
|
19016
|
+
function readSrcsetUrlToken(value, index) {
|
|
19017
|
+
let cursor = index;
|
|
19018
|
+
let out = "";
|
|
19019
|
+
const isDataUrl = value.slice(index, index + 5).toLowerCase().startsWith("data:");
|
|
19020
|
+
while (cursor < value.length) {
|
|
19021
|
+
const char = value[cursor];
|
|
19022
|
+
if (/\s/u.test(char)) {
|
|
19023
|
+
break;
|
|
19024
|
+
}
|
|
19025
|
+
if (char === "," && !isDataUrl) {
|
|
19026
|
+
break;
|
|
19027
|
+
}
|
|
19028
|
+
out += char;
|
|
19029
|
+
cursor += 1;
|
|
19030
|
+
}
|
|
19031
|
+
if (isDataUrl && out.endsWith(",") && cursor < value.length) {
|
|
19032
|
+
out = out.slice(0, -1);
|
|
19033
|
+
}
|
|
19034
|
+
return {
|
|
19035
|
+
value: out,
|
|
19036
|
+
nextIndex: cursor
|
|
19037
|
+
};
|
|
19038
|
+
}
|
|
19039
|
+
function readSrcsetDescriptorToken(value, index) {
|
|
19040
|
+
let cursor = skipSrcsetWhitespace(value, index);
|
|
19041
|
+
let out = "";
|
|
19042
|
+
while (cursor < value.length) {
|
|
19043
|
+
const char = value[cursor];
|
|
19044
|
+
if (char === "," || /\s/u.test(char)) {
|
|
19045
|
+
break;
|
|
19046
|
+
}
|
|
19047
|
+
out += char;
|
|
19048
|
+
cursor += 1;
|
|
19049
|
+
}
|
|
19050
|
+
return {
|
|
19051
|
+
value: out.trim(),
|
|
19052
|
+
nextIndex: cursor
|
|
19053
|
+
};
|
|
19054
|
+
}
|
|
18717
19055
|
function removeNoise($) {
|
|
18718
19056
|
for (const tag of STRIP_TAGS) {
|
|
18719
19057
|
$(tag).remove();
|
|
@@ -18738,46 +19076,76 @@ function markInlineSelfHiddenFallback($) {
|
|
|
18738
19076
|
});
|
|
18739
19077
|
}
|
|
18740
19078
|
function pruneSelfHiddenNodes($) {
|
|
18741
|
-
const
|
|
18742
|
-
|
|
18743
|
-
nodes.push($(this));
|
|
18744
|
-
});
|
|
18745
|
-
nodes.sort((left, right) => right.parents().length - left.parents().length);
|
|
18746
|
-
for (const el of nodes) {
|
|
18747
|
-
if (!el[0]) {
|
|
19079
|
+
for (const node of getElementsInReverseDocumentOrder($)) {
|
|
19080
|
+
if (node.attribs?.[OPENSTEER_SELF_HIDDEN_ATTR] === void 0) {
|
|
18748
19081
|
continue;
|
|
18749
19082
|
}
|
|
19083
|
+
const el = $(node);
|
|
18750
19084
|
el.contents().each(function removeSelfHiddenText() {
|
|
18751
19085
|
if (this.type === "text") {
|
|
18752
19086
|
$(this).remove();
|
|
18753
19087
|
}
|
|
18754
19088
|
});
|
|
18755
|
-
if (
|
|
19089
|
+
if (!hasElementChildren(node)) {
|
|
18756
19090
|
el.remove();
|
|
18757
19091
|
}
|
|
18758
19092
|
}
|
|
18759
19093
|
}
|
|
18760
|
-
function
|
|
18761
|
-
return
|
|
18762
|
-
return this.type === "text" && $(this).text().trim() !== "";
|
|
18763
|
-
}).length > 0;
|
|
18764
|
-
}
|
|
18765
|
-
function hasTextDeep(el) {
|
|
18766
|
-
return el.text().trim().length > 0;
|
|
19094
|
+
function getChildNodes(node) {
|
|
19095
|
+
return node?.children ?? [];
|
|
18767
19096
|
}
|
|
18768
|
-
function
|
|
18769
|
-
return
|
|
19097
|
+
function isElementLikeNode(node) {
|
|
19098
|
+
return node?.type === "tag" || node?.type === "script" || node?.type === "style";
|
|
18770
19099
|
}
|
|
18771
|
-
function
|
|
18772
|
-
if (
|
|
18773
|
-
|
|
18774
|
-
|
|
19100
|
+
function hasDirectText(node) {
|
|
19101
|
+
if (!node) {
|
|
19102
|
+
return false;
|
|
19103
|
+
}
|
|
19104
|
+
for (const child of getChildNodes(node)) {
|
|
19105
|
+
if (child.type === "text" && (child.data || "").trim() !== "") {
|
|
19106
|
+
return true;
|
|
18775
19107
|
}
|
|
18776
|
-
|
|
18777
|
-
|
|
19108
|
+
}
|
|
19109
|
+
return false;
|
|
19110
|
+
}
|
|
19111
|
+
function hasElementChildren(node) {
|
|
19112
|
+
if (!node) {
|
|
19113
|
+
return false;
|
|
19114
|
+
}
|
|
19115
|
+
for (const child of getChildNodes(node)) {
|
|
19116
|
+
if (isElementLikeNode(child)) {
|
|
19117
|
+
return true;
|
|
18778
19118
|
}
|
|
18779
19119
|
}
|
|
18780
|
-
|
|
19120
|
+
return false;
|
|
19121
|
+
}
|
|
19122
|
+
function hasTextDeepNode(node) {
|
|
19123
|
+
if (!node) {
|
|
19124
|
+
return false;
|
|
19125
|
+
}
|
|
19126
|
+
if (node.type === "text") {
|
|
19127
|
+
return (node.data || "").trim() !== "";
|
|
19128
|
+
}
|
|
19129
|
+
for (const child of getChildNodes(node)) {
|
|
19130
|
+
if (hasTextDeepNode(child)) {
|
|
19131
|
+
return true;
|
|
19132
|
+
}
|
|
19133
|
+
}
|
|
19134
|
+
return false;
|
|
19135
|
+
}
|
|
19136
|
+
function hasActionLabel(attrs) {
|
|
19137
|
+
return typeof attrs["aria-label"] === "string" && attrs["aria-label"].trim() !== "" || typeof attrs["aria-labelledby"] === "string" && attrs["aria-labelledby"].trim() !== "" || typeof attrs["aria-describedby"] === "string" && attrs["aria-describedby"].trim() !== "" || typeof attrs.title === "string" && attrs.title.trim() !== "" || typeof attrs.placeholder === "string" && attrs.placeholder.trim() !== "" || typeof attrs.value === "string" && attrs.value.trim() !== "";
|
|
19138
|
+
}
|
|
19139
|
+
function unwrapActionNode($, el) {
|
|
19140
|
+
if (hasTextDeepNode(el[0])) {
|
|
19141
|
+
if (el.prev().length > 0) {
|
|
19142
|
+
el.before(" ");
|
|
19143
|
+
}
|
|
19144
|
+
if (el.next().length > 0) {
|
|
19145
|
+
el.after(" ");
|
|
19146
|
+
}
|
|
19147
|
+
}
|
|
19148
|
+
el.replaceWith(el.contents());
|
|
18781
19149
|
}
|
|
18782
19150
|
function stripToAttrs(el, keep) {
|
|
18783
19151
|
const attrs = el.attr() || {};
|
|
@@ -18790,7 +19158,7 @@ function stripToAttrs(el, keep) {
|
|
|
18790
19158
|
if (typeof value !== "string") {
|
|
18791
19159
|
continue;
|
|
18792
19160
|
}
|
|
18793
|
-
if (
|
|
19161
|
+
if (shouldBoundAttr(attr)) {
|
|
18794
19162
|
setBoundedAttr(el, attr, value);
|
|
18795
19163
|
}
|
|
18796
19164
|
}
|
|
@@ -18808,6 +19176,9 @@ function restoreBoundedAttr(el, attr, value) {
|
|
|
18808
19176
|
function deduplicateImages(html) {
|
|
18809
19177
|
const seen = /* @__PURE__ */ new Set();
|
|
18810
19178
|
return html.replace(/<img\b([^>]*)>/gi, (full, attrContent) => {
|
|
19179
|
+
if (/\bc\s*=/.test(attrContent)) {
|
|
19180
|
+
return full;
|
|
19181
|
+
}
|
|
18811
19182
|
const srcMatch = attrContent.match(/\bsrc\s*=\s*(["']?)(.*?)\1/);
|
|
18812
19183
|
const srcsetMatch = attrContent.match(/\bsrcset\s*=\s*(["'])(.*?)\1/);
|
|
18813
19184
|
let src = null;
|
|
@@ -18826,59 +19197,155 @@ function deduplicateImages(html) {
|
|
|
18826
19197
|
return full;
|
|
18827
19198
|
});
|
|
18828
19199
|
}
|
|
18829
|
-
function
|
|
18830
|
-
|
|
19200
|
+
function hasAttribute2(node, attr) {
|
|
19201
|
+
return node?.attribs?.[attr] !== void 0;
|
|
19202
|
+
}
|
|
19203
|
+
function hasPictureAncestor(node) {
|
|
19204
|
+
let current = node?.parent;
|
|
19205
|
+
while (current) {
|
|
19206
|
+
if (isElementLikeNode(current) && (current.tagName || "").toLowerCase() === "picture") {
|
|
19207
|
+
return true;
|
|
19208
|
+
}
|
|
19209
|
+
current = current.parent;
|
|
19210
|
+
}
|
|
19211
|
+
return false;
|
|
19212
|
+
}
|
|
19213
|
+
function pictureHasPreservedDescendant(node) {
|
|
19214
|
+
if (!node) {
|
|
19215
|
+
return false;
|
|
19216
|
+
}
|
|
19217
|
+
for (const child of getChildNodes(node)) {
|
|
19218
|
+
if (!isElementLikeNode(child)) {
|
|
19219
|
+
continue;
|
|
19220
|
+
}
|
|
19221
|
+
const tag = (child.tagName || "").toLowerCase();
|
|
19222
|
+
if (tag === "img") {
|
|
19223
|
+
return true;
|
|
19224
|
+
}
|
|
19225
|
+
if (tag === "source" && typeof child.attribs?.src === "string" && child.attribs.src.trim() !== "") {
|
|
19226
|
+
return true;
|
|
19227
|
+
}
|
|
19228
|
+
if (tag === "source" && typeof child.attribs?.srcset === "string" && child.attribs.srcset.trim() !== "") {
|
|
19229
|
+
return true;
|
|
19230
|
+
}
|
|
19231
|
+
if (pictureHasPreservedDescendant(child)) {
|
|
19232
|
+
return true;
|
|
19233
|
+
}
|
|
19234
|
+
}
|
|
19235
|
+
return false;
|
|
19236
|
+
}
|
|
19237
|
+
function isPreservedImageElement(node) {
|
|
19238
|
+
const tag = (node?.tagName || "").toLowerCase();
|
|
18831
19239
|
if (tag === "img") {
|
|
18832
19240
|
return true;
|
|
18833
19241
|
}
|
|
18834
19242
|
if (tag === "picture") {
|
|
18835
|
-
|
|
18836
|
-
const hasSource = el.find("source[src], source[srcset]").length > 0;
|
|
18837
|
-
return hasImg || hasSource;
|
|
19243
|
+
return pictureHasPreservedDescendant(node);
|
|
18838
19244
|
}
|
|
18839
19245
|
if (tag === "source") {
|
|
18840
|
-
const inPicture =
|
|
18841
|
-
const hasSrc =
|
|
19246
|
+
const inPicture = hasPictureAncestor(node);
|
|
19247
|
+
const hasSrc = typeof node?.attribs?.src === "string" && node.attribs.src.trim() !== "" || typeof node?.attribs?.srcset === "string" && node.attribs.srcset.trim() !== "";
|
|
18842
19248
|
return inPicture && hasSrc;
|
|
18843
19249
|
}
|
|
18844
19250
|
return false;
|
|
18845
19251
|
}
|
|
19252
|
+
function getElementsInReverseDocumentOrder($) {
|
|
19253
|
+
return $.root().find("*").toArray().reverse().filter((node) => node.type === "tag");
|
|
19254
|
+
}
|
|
19255
|
+
function getNodeDepth(node) {
|
|
19256
|
+
let depth = 0;
|
|
19257
|
+
let current = node.parent;
|
|
19258
|
+
while (current) {
|
|
19259
|
+
depth++;
|
|
19260
|
+
current = current.parent;
|
|
19261
|
+
}
|
|
19262
|
+
return depth;
|
|
19263
|
+
}
|
|
19264
|
+
function getElementsByDepthDescending($) {
|
|
19265
|
+
const elements = $.root().find("*").toArray().filter((node) => node.type === "tag");
|
|
19266
|
+
const depths = /* @__PURE__ */ new Map();
|
|
19267
|
+
for (const el of elements) {
|
|
19268
|
+
depths.set(el, getNodeDepth(el));
|
|
19269
|
+
}
|
|
19270
|
+
return elements.sort((a, b) => (depths.get(b) ?? 0) - (depths.get(a) ?? 0));
|
|
19271
|
+
}
|
|
18846
19272
|
function flattenExtractionTree($) {
|
|
18847
|
-
const
|
|
18848
|
-
|
|
18849
|
-
|
|
18850
|
-
|
|
18851
|
-
|
|
18852
|
-
|
|
18853
|
-
|
|
18854
|
-
|
|
18855
|
-
|
|
18856
|
-
|
|
18857
|
-
|
|
18858
|
-
|
|
18859
|
-
|
|
18860
|
-
|
|
18861
|
-
|
|
18862
|
-
|
|
18863
|
-
|
|
18864
|
-
|
|
18865
|
-
|
|
18866
|
-
|
|
18867
|
-
|
|
18868
|
-
|
|
18869
|
-
|
|
18870
|
-
|
|
18871
|
-
|
|
18872
|
-
|
|
18873
|
-
|
|
19273
|
+
for (const node of getElementsInReverseDocumentOrder($)) {
|
|
19274
|
+
const el = $(node);
|
|
19275
|
+
const tag = (node.tagName || "").toLowerCase();
|
|
19276
|
+
if (ROOT_TAGS.has(tag) || isBoundaryTag(tag) || isPreservedImageElement(node)) {
|
|
19277
|
+
continue;
|
|
19278
|
+
}
|
|
19279
|
+
if (tag === "a" || hasDirectText(node)) {
|
|
19280
|
+
continue;
|
|
19281
|
+
}
|
|
19282
|
+
if (!hasElementChildren(node)) {
|
|
19283
|
+
el.remove();
|
|
19284
|
+
continue;
|
|
19285
|
+
}
|
|
19286
|
+
el.replaceWith(el.contents());
|
|
19287
|
+
}
|
|
19288
|
+
}
|
|
19289
|
+
function hasMarkedAncestor(el, attr) {
|
|
19290
|
+
let current = el[0]?.parent;
|
|
19291
|
+
while (current) {
|
|
19292
|
+
if (!isElementLikeNode(current)) {
|
|
19293
|
+
return false;
|
|
19294
|
+
}
|
|
19295
|
+
if (current.attribs?.[attr] !== void 0) {
|
|
19296
|
+
return true;
|
|
19297
|
+
}
|
|
19298
|
+
current = current.parent;
|
|
19299
|
+
}
|
|
19300
|
+
return false;
|
|
19301
|
+
}
|
|
19302
|
+
function isIndicatorImage(node) {
|
|
19303
|
+
return (node?.tagName || "").toLowerCase() === "img" && (hasAttribute2(node, "alt") || hasAttribute2(node, "src") || hasAttribute2(node, "srcset"));
|
|
19304
|
+
}
|
|
19305
|
+
function isIndicatorPictureSource(node) {
|
|
19306
|
+
return (node?.tagName || "").toLowerCase() === "source" && hasPictureAncestor(node) && (hasAttribute2(node, "src") || hasAttribute2(node, "srcset"));
|
|
19307
|
+
}
|
|
19308
|
+
function isSemanticIndicator(node) {
|
|
19309
|
+
const tag = (node?.tagName || "").toLowerCase();
|
|
19310
|
+
if (tag === "svg") {
|
|
19311
|
+
return true;
|
|
19312
|
+
}
|
|
19313
|
+
return hasAttribute2(node, "aria-label") || hasAttribute2(node, "title") || hasAttribute2(node, "data-icon") || node?.attribs?.role === "img";
|
|
19314
|
+
}
|
|
19315
|
+
function findIndicatorDescendant(root) {
|
|
19316
|
+
if (!root) {
|
|
19317
|
+
return void 0;
|
|
19318
|
+
}
|
|
19319
|
+
let firstImage;
|
|
19320
|
+
let firstSource;
|
|
19321
|
+
let firstSemantic;
|
|
19322
|
+
const visit = (node) => {
|
|
19323
|
+
if (!isElementLikeNode(node)) {
|
|
19324
|
+
return false;
|
|
19325
|
+
}
|
|
19326
|
+
if (isIndicatorImage(node)) {
|
|
19327
|
+
firstImage = node;
|
|
19328
|
+
return true;
|
|
19329
|
+
}
|
|
19330
|
+
if (firstSource === void 0 && isIndicatorPictureSource(node)) {
|
|
19331
|
+
firstSource = node;
|
|
19332
|
+
}
|
|
19333
|
+
if (firstSemantic === void 0 && isSemanticIndicator(node)) {
|
|
19334
|
+
firstSemantic = node;
|
|
19335
|
+
}
|
|
19336
|
+
for (const child of getChildNodes(node)) {
|
|
19337
|
+
if (visit(child)) {
|
|
19338
|
+
return true;
|
|
18874
19339
|
}
|
|
18875
|
-
|
|
18876
|
-
|
|
18877
|
-
});
|
|
18878
|
-
el.replaceWith(el.contents());
|
|
18879
|
-
});
|
|
19340
|
+
}
|
|
19341
|
+
return false;
|
|
18880
19342
|
};
|
|
18881
|
-
|
|
19343
|
+
for (const child of getChildNodes(root)) {
|
|
19344
|
+
if (visit(child)) {
|
|
19345
|
+
return firstImage;
|
|
19346
|
+
}
|
|
19347
|
+
}
|
|
19348
|
+
return firstImage ?? firstSource ?? firstSemantic;
|
|
18882
19349
|
}
|
|
18883
19350
|
function serializeForExtraction($, root) {
|
|
18884
19351
|
const lines = [];
|
|
@@ -18947,7 +19414,7 @@ function serializeForExtraction($, root) {
|
|
|
18947
19414
|
lines.push(`${" ".repeat(depth)}</${tagName}>`);
|
|
18948
19415
|
}
|
|
18949
19416
|
traverse(root, 0);
|
|
18950
|
-
return lines.join("
|
|
19417
|
+
return lines.map((l) => l.trim()).filter((l) => l.length > 0).join("");
|
|
18951
19418
|
}
|
|
18952
19419
|
function isClickable($, el, context) {
|
|
18953
19420
|
if (context.hasPreMarked) {
|
|
@@ -19039,7 +19506,11 @@ function cleanForExtraction(html) {
|
|
|
19039
19506
|
}
|
|
19040
19507
|
});
|
|
19041
19508
|
flattenExtractionTree($clean);
|
|
19042
|
-
|
|
19509
|
+
const root = $clean.root()[0];
|
|
19510
|
+
if (root === void 0) {
|
|
19511
|
+
return "";
|
|
19512
|
+
}
|
|
19513
|
+
return deduplicateImages(serializeForExtraction($clean, root));
|
|
19043
19514
|
}
|
|
19044
19515
|
function cleanForAction(html) {
|
|
19045
19516
|
if (!html.trim()) {
|
|
@@ -19065,22 +19536,12 @@ function cleanForAction(html) {
|
|
|
19065
19536
|
$(`[${clickableMark}]`).each(function markIndicators() {
|
|
19066
19537
|
const el = $(this);
|
|
19067
19538
|
const wrapperAttrs = el.attr() || {};
|
|
19068
|
-
if (
|
|
19539
|
+
if (hasTextDeepNode(el[0]) || hasActionLabel(wrapperAttrs)) {
|
|
19069
19540
|
return;
|
|
19070
19541
|
}
|
|
19071
|
-
const
|
|
19072
|
-
if (
|
|
19073
|
-
|
|
19074
|
-
return;
|
|
19075
|
-
}
|
|
19076
|
-
const pictureSourceIndicator = el.find("picture source[src], picture source[srcset]").first();
|
|
19077
|
-
if (pictureSourceIndicator.length) {
|
|
19078
|
-
pictureSourceIndicator.attr(indicatorMark, "1");
|
|
19079
|
-
return;
|
|
19080
|
-
}
|
|
19081
|
-
const semanticIndicator = el.find('[aria-label], [title], [data-icon], [role="img"], svg').first();
|
|
19082
|
-
if (semanticIndicator.length) {
|
|
19083
|
-
semanticIndicator.attr(indicatorMark, "1");
|
|
19542
|
+
const indicatorNode = findIndicatorDescendant(el[0]);
|
|
19543
|
+
if (indicatorNode !== void 0) {
|
|
19544
|
+
$(indicatorNode).attr(indicatorMark, "1");
|
|
19084
19545
|
}
|
|
19085
19546
|
});
|
|
19086
19547
|
$(`[${clickableMark}]`).each(function removeEmptyClickable() {
|
|
@@ -19090,7 +19551,7 @@ function cleanForAction(html) {
|
|
|
19090
19551
|
if (NATIVE_INTERACTIVE_TAGS.has(tag) || tag === "a") {
|
|
19091
19552
|
return;
|
|
19092
19553
|
}
|
|
19093
|
-
if (
|
|
19554
|
+
if (hasElementChildren(node) || hasDirectText(node)) {
|
|
19094
19555
|
return;
|
|
19095
19556
|
}
|
|
19096
19557
|
const wrapperAttrs = el.attr() || {};
|
|
@@ -19116,46 +19577,31 @@ function cleanForAction(html) {
|
|
|
19116
19577
|
current = ancestor.parent();
|
|
19117
19578
|
}
|
|
19118
19579
|
});
|
|
19119
|
-
|
|
19120
|
-
|
|
19121
|
-
|
|
19122
|
-
|
|
19123
|
-
|
|
19124
|
-
|
|
19125
|
-
|
|
19126
|
-
|
|
19127
|
-
|
|
19128
|
-
|
|
19129
|
-
|
|
19130
|
-
|
|
19131
|
-
|
|
19132
|
-
const tag = (node.tagName || "").toLowerCase();
|
|
19133
|
-
if (ROOT_TAGS.has(tag) || isBoundaryTag(tag)) {
|
|
19134
|
-
continue;
|
|
19135
|
-
}
|
|
19136
|
-
if (el.attr(clickableMark) !== void 0 || el.attr(indicatorMark) !== void 0) {
|
|
19137
|
-
continue;
|
|
19138
|
-
}
|
|
19139
|
-
const insideClickable = el.parents(`[${clickableMark}]`).length > 0;
|
|
19140
|
-
const preserveBranch = el.attr(branchMark) !== void 0;
|
|
19141
|
-
const hasContent = el.children().length > 0 || hasDirectText($, el);
|
|
19142
|
-
if (insideClickable || preserveBranch) {
|
|
19143
|
-
if (!hasContent) {
|
|
19144
|
-
el.remove();
|
|
19145
|
-
} else {
|
|
19146
|
-
unwrapActionNode($, el);
|
|
19147
|
-
}
|
|
19148
|
-
changed = true;
|
|
19149
|
-
continue;
|
|
19150
|
-
}
|
|
19580
|
+
for (const node of getElementsByDepthDescending($)) {
|
|
19581
|
+
const el = $(node);
|
|
19582
|
+
const tag = (node.tagName || "").toLowerCase();
|
|
19583
|
+
if (ROOT_TAGS.has(tag) || isBoundaryTag(tag)) {
|
|
19584
|
+
continue;
|
|
19585
|
+
}
|
|
19586
|
+
if (el.attr(clickableMark) !== void 0 || el.attr(indicatorMark) !== void 0) {
|
|
19587
|
+
continue;
|
|
19588
|
+
}
|
|
19589
|
+
const insideClickable = hasMarkedAncestor(el, clickableMark);
|
|
19590
|
+
const preserveBranch = el.attr(branchMark) !== void 0;
|
|
19591
|
+
const hasContent = hasElementChildren(node) || hasDirectText(node);
|
|
19592
|
+
if (insideClickable || preserveBranch) {
|
|
19151
19593
|
if (!hasContent) {
|
|
19152
19594
|
el.remove();
|
|
19153
|
-
|
|
19154
|
-
|
|
19595
|
+
} else {
|
|
19596
|
+
unwrapActionNode($, el);
|
|
19155
19597
|
}
|
|
19156
|
-
|
|
19157
|
-
|
|
19598
|
+
continue;
|
|
19599
|
+
}
|
|
19600
|
+
if (!hasContent) {
|
|
19601
|
+
el.remove();
|
|
19602
|
+
continue;
|
|
19158
19603
|
}
|
|
19604
|
+
unwrapActionNode($, el);
|
|
19159
19605
|
}
|
|
19160
19606
|
$.root().find("*").contents().each(function normalizeActionTextNodes() {
|
|
19161
19607
|
if (this.type !== "text") {
|
|
@@ -19235,21 +19681,7 @@ function cleanForAction(html) {
|
|
|
19235
19681
|
OPENSTEER_SPARSE_COUNTER_ATTR
|
|
19236
19682
|
]);
|
|
19237
19683
|
if (clickable) {
|
|
19238
|
-
for (const attr of [
|
|
19239
|
-
"href",
|
|
19240
|
-
"role",
|
|
19241
|
-
"type",
|
|
19242
|
-
"title",
|
|
19243
|
-
"placeholder",
|
|
19244
|
-
"value",
|
|
19245
|
-
"aria-label",
|
|
19246
|
-
"aria-labelledby",
|
|
19247
|
-
"aria-describedby",
|
|
19248
|
-
"aria-expanded",
|
|
19249
|
-
"aria-pressed",
|
|
19250
|
-
"aria-selected",
|
|
19251
|
-
"aria-haspopup"
|
|
19252
|
-
]) {
|
|
19684
|
+
for (const attr of ["href", "role", "type", "title", "placeholder", "value", "aria-label"]) {
|
|
19253
19685
|
keep.add(attr);
|
|
19254
19686
|
}
|
|
19255
19687
|
}
|
|
@@ -19273,16 +19705,25 @@ function cleanForAction(html) {
|
|
|
19273
19705
|
});
|
|
19274
19706
|
return compactHtml(deduplicateImages($.html()));
|
|
19275
19707
|
}
|
|
19276
|
-
var STRIP_TAGS, TEXT_ATTR_MAX,
|
|
19708
|
+
var STRIP_TAGS, TEXT_ATTR_MAX, SRCSET_ATTR_MAX, MIDDLE_TRUNCATED_URL_ATTRS, TEXT_ATTRS, TRUNCATION_SUFFIX, MIDDLE_TRUNCATION_MARKER, MIDDLE_TRUNCATION_HEAD_MAX, MIDDLE_TRUNCATION_TAIL_MAX, SRCSET_CANDIDATE_HEAD_MAX, SRCSET_CANDIDATE_TAIL_MAX, SRCSET_COMPACT_CANDIDATE_HEAD_MAX, SRCSET_COMPACT_CANDIDATE_TAIL_MAX, SRCSET_FALLBACK_HEAD_MAX, SRCSET_FALLBACK_TAIL_MAX, NOISE_SELECTORS, VOID_TAGS2;
|
|
19277
19709
|
var init_cleaner = __esm({
|
|
19278
19710
|
"../runtime-core/src/sdk/snapshot/cleaner.ts"() {
|
|
19279
19711
|
init_constants();
|
|
19280
19712
|
STRIP_TAGS = /* @__PURE__ */ new Set(["script", "style", "noscript", "meta", "link", "template"]);
|
|
19281
19713
|
TEXT_ATTR_MAX = 150;
|
|
19282
|
-
|
|
19283
|
-
|
|
19714
|
+
SRCSET_ATTR_MAX = 160;
|
|
19715
|
+
MIDDLE_TRUNCATED_URL_ATTRS = /* @__PURE__ */ new Set(["href", "src"]);
|
|
19284
19716
|
TEXT_ATTRS = /* @__PURE__ */ new Set(["alt", "title", "aria-label", "placeholder", "value"]);
|
|
19285
|
-
TRUNCATION_SUFFIX = "
|
|
19717
|
+
TRUNCATION_SUFFIX = "...";
|
|
19718
|
+
MIDDLE_TRUNCATION_MARKER = "...";
|
|
19719
|
+
MIDDLE_TRUNCATION_HEAD_MAX = 40;
|
|
19720
|
+
MIDDLE_TRUNCATION_TAIL_MAX = 20;
|
|
19721
|
+
SRCSET_CANDIDATE_HEAD_MAX = 36;
|
|
19722
|
+
SRCSET_CANDIDATE_TAIL_MAX = 12;
|
|
19723
|
+
SRCSET_COMPACT_CANDIDATE_HEAD_MAX = 20;
|
|
19724
|
+
SRCSET_COMPACT_CANDIDATE_TAIL_MAX = 8;
|
|
19725
|
+
SRCSET_FALLBACK_HEAD_MAX = 56;
|
|
19726
|
+
SRCSET_FALLBACK_TAIL_MAX = 20;
|
|
19286
19727
|
NOISE_SELECTORS = [
|
|
19287
19728
|
`[${OPENSTEER_HIDDEN_ATTR}]`,
|
|
19288
19729
|
"[hidden]",
|
|
@@ -19821,9 +20262,9 @@ function renderNode(snapshot, node, nodesById, snapshotsByDocumentRef, snapshotI
|
|
|
19821
20262
|
const snapshotAttributes = normalizeNodeAttributes(node.attributes);
|
|
19822
20263
|
const authoredAttributes = stripInternalSnapshotAttributes(snapshotAttributes);
|
|
19823
20264
|
const attributes = [...authoredAttributes];
|
|
19824
|
-
const subtreeHidden =
|
|
19825
|
-
const selfHidden = !subtreeHidden && (
|
|
19826
|
-
const interactive = !subtreeHidden && !selfHidden && (
|
|
20265
|
+
const subtreeHidden = hasAttribute3(snapshotAttributes, OPENSTEER_HIDDEN_ATTR) || isLikelySubtreeHidden(node);
|
|
20266
|
+
const selfHidden = !subtreeHidden && (hasAttribute3(snapshotAttributes, OPENSTEER_SELF_HIDDEN_ATTR) || isLikelySelfHidden(node, nodesById));
|
|
20267
|
+
const interactive = !subtreeHidden && !selfHidden && (hasAttribute3(snapshotAttributes, OPENSTEER_INTERACTIVE_ATTR) || isLikelyInteractive(tagName, node, authoredAttributes));
|
|
19827
20268
|
if (interactive) {
|
|
19828
20269
|
attributes.push({ name: OPENSTEER_INTERACTIVE_ATTR, value: "1" });
|
|
19829
20270
|
}
|
|
@@ -20141,7 +20582,7 @@ function parseOpacity(value) {
|
|
|
20141
20582
|
const parsed = Number.parseFloat(value);
|
|
20142
20583
|
return Number.isFinite(parsed) ? parsed : Number.NaN;
|
|
20143
20584
|
}
|
|
20144
|
-
function
|
|
20585
|
+
function hasAttribute3(attributes, name) {
|
|
20145
20586
|
const normalizedName = name.toLowerCase();
|
|
20146
20587
|
return attributes.some((attribute) => attribute.name.toLowerCase() === normalizedName);
|
|
20147
20588
|
}
|
|
@@ -23471,12 +23912,12 @@ var init_runtime3 = __esm({
|
|
|
23471
23912
|
async (timeout) => {
|
|
23472
23913
|
let descriptor2;
|
|
23473
23914
|
let data;
|
|
23474
|
-
if (input.
|
|
23475
|
-
|
|
23915
|
+
if (input.template !== void 0) {
|
|
23916
|
+
assertValidOpensteerExtractionTemplateRoot(input.template);
|
|
23476
23917
|
const fieldTargets = await timeout.runStep(
|
|
23477
23918
|
() => compileOpensteerExtractionFieldTargets({
|
|
23478
23919
|
pageRef,
|
|
23479
|
-
|
|
23920
|
+
template: input.template,
|
|
23480
23921
|
dom: this.requireDom()
|
|
23481
23922
|
})
|
|
23482
23923
|
);
|
|
@@ -23508,7 +23949,7 @@ var init_runtime3 = __esm({
|
|
|
23508
23949
|
() => descriptors.write({
|
|
23509
23950
|
persist,
|
|
23510
23951
|
root: payload,
|
|
23511
|
-
|
|
23952
|
+
templateHash: canonicalJsonString(input.template),
|
|
23512
23953
|
sourceUrl: pageInfo.url
|
|
23513
23954
|
})
|
|
23514
23955
|
);
|
|
@@ -23568,7 +24009,7 @@ var init_runtime3 = __esm({
|
|
|
23568
24009
|
artifacts,
|
|
23569
24010
|
data: {
|
|
23570
24011
|
...input.persist === void 0 ? {} : { persist: input.persist },
|
|
23571
|
-
...descriptor?.payload.
|
|
24012
|
+
...descriptor?.payload.templateHash === void 0 ? {} : { templateHash: descriptor.payload.templateHash },
|
|
23572
24013
|
data: output.data
|
|
23573
24014
|
},
|
|
23574
24015
|
context: buildRuntimeTraceContext({
|
|
@@ -29171,8 +29612,29 @@ function assertSupportedCloudBrowserMode(browser) {
|
|
|
29171
29612
|
}
|
|
29172
29613
|
}
|
|
29173
29614
|
function isMissingCloudSessionError(error) {
|
|
29615
|
+
if (error instanceof OpensteerCloudRequestError) {
|
|
29616
|
+
return error.statusCode === 404 && (error.code === void 0 || error.code === "CLOUD_SESSION_NOT_FOUND");
|
|
29617
|
+
}
|
|
29174
29618
|
return error instanceof Error && /\b404\b/.test(error.message);
|
|
29175
29619
|
}
|
|
29620
|
+
function isRecoverableCloudSessionError(error) {
|
|
29621
|
+
if (!(error instanceof OpensteerCloudRequestError)) {
|
|
29622
|
+
return false;
|
|
29623
|
+
}
|
|
29624
|
+
if (error.statusCode === 404) {
|
|
29625
|
+
return error.code === void 0 || error.code === "CLOUD_SESSION_NOT_FOUND";
|
|
29626
|
+
}
|
|
29627
|
+
return error.statusCode === 409 && error.code === "CLOUD_SESSION_STALE";
|
|
29628
|
+
}
|
|
29629
|
+
function isBootstrapRecoveryOperation(operation) {
|
|
29630
|
+
return operation === "session.open" || operation === "instrumentation.route" || operation === "instrumentation.intercept-script";
|
|
29631
|
+
}
|
|
29632
|
+
function isReusableCloudSessionState(session) {
|
|
29633
|
+
if (session.status === "closing" || session.status === "closed" || session.status === "failed") {
|
|
29634
|
+
return false;
|
|
29635
|
+
}
|
|
29636
|
+
return !(typeof session.expiresAt === "number" && session.expiresAt <= Date.now() + CLOUD_SESSION_REUSE_EXPIRY_SKEW_MS);
|
|
29637
|
+
}
|
|
29176
29638
|
function isLoopbackBaseUrl(baseUrl) {
|
|
29177
29639
|
let url;
|
|
29178
29640
|
try {
|
|
@@ -29182,7 +29644,7 @@ function isLoopbackBaseUrl(baseUrl) {
|
|
|
29182
29644
|
}
|
|
29183
29645
|
return url.hostname === "localhost" || url.hostname === "127.0.0.1" || url.hostname === "::1" || url.hostname === "[::1]";
|
|
29184
29646
|
}
|
|
29185
|
-
var TEMPORARY_CLOUD_WORKSPACE_PREFIX, CloudSessionProxy;
|
|
29647
|
+
var TEMPORARY_CLOUD_WORKSPACE_PREFIX, CLOUD_SESSION_REUSE_EXPIRY_SKEW_MS, CloudSessionProxy;
|
|
29186
29648
|
var init_session_proxy = __esm({
|
|
29187
29649
|
"src/cloud/session-proxy.ts"() {
|
|
29188
29650
|
init_src3();
|
|
@@ -29192,8 +29654,10 @@ var init_session_proxy = __esm({
|
|
|
29192
29654
|
init_policy2();
|
|
29193
29655
|
init_semantic_rest_client();
|
|
29194
29656
|
init_automation_client();
|
|
29657
|
+
init_client();
|
|
29195
29658
|
init_workspace_sync();
|
|
29196
29659
|
TEMPORARY_CLOUD_WORKSPACE_PREFIX = "opensteer-cloud-workspace-";
|
|
29660
|
+
CLOUD_SESSION_REUSE_EXPIRY_SKEW_MS = 1e4;
|
|
29197
29661
|
CloudSessionProxy = class {
|
|
29198
29662
|
rootPath;
|
|
29199
29663
|
workspace;
|
|
@@ -29207,6 +29671,8 @@ var init_session_proxy = __esm({
|
|
|
29207
29671
|
automation;
|
|
29208
29672
|
workspaceStore;
|
|
29209
29673
|
syncWorkspaceOnClose = false;
|
|
29674
|
+
liveSessionStateEstablished = false;
|
|
29675
|
+
storedInstrumentation = [];
|
|
29210
29676
|
constructor(cloud, options = {}) {
|
|
29211
29677
|
this.cloud = cloud;
|
|
29212
29678
|
this.workspace = options.workspace;
|
|
@@ -29236,15 +29702,12 @@ var init_session_proxy = __esm({
|
|
|
29236
29702
|
if (this.client === void 0 && this.sessionId === void 0 && persisted !== void 0 && await this.isReusableCloudSession(persisted.sessionId)) {
|
|
29237
29703
|
this.bindClient(persisted);
|
|
29238
29704
|
}
|
|
29239
|
-
|
|
29240
|
-
|
|
29241
|
-
|
|
29242
|
-
|
|
29243
|
-
|
|
29244
|
-
|
|
29245
|
-
};
|
|
29246
|
-
} catch {
|
|
29247
|
-
}
|
|
29705
|
+
const sessionInfo = this.automation ? await this.automation.getSessionInfo().catch(() => void 0) : void 0;
|
|
29706
|
+
if (sessionInfo !== void 0) {
|
|
29707
|
+
return {
|
|
29708
|
+
...sessionInfo,
|
|
29709
|
+
...this.workspace === void 0 ? {} : { workspace: this.workspace }
|
|
29710
|
+
};
|
|
29248
29711
|
}
|
|
29249
29712
|
return {
|
|
29250
29713
|
provider: {
|
|
@@ -29356,12 +29819,26 @@ var init_session_proxy = __esm({
|
|
|
29356
29819
|
return this.invokeSemanticOperation("session.cookies", input);
|
|
29357
29820
|
}
|
|
29358
29821
|
async route(input) {
|
|
29359
|
-
await this.
|
|
29360
|
-
|
|
29822
|
+
const registration = await this.invokeBootstrapInstrumentationOperation(
|
|
29823
|
+
"instrumentation.route",
|
|
29824
|
+
(automation) => automation.route(input)
|
|
29825
|
+
);
|
|
29826
|
+
this.storedInstrumentation.push({
|
|
29827
|
+
kind: "route",
|
|
29828
|
+
input
|
|
29829
|
+
});
|
|
29830
|
+
return registration;
|
|
29361
29831
|
}
|
|
29362
29832
|
async interceptScript(input) {
|
|
29363
|
-
await this.
|
|
29364
|
-
|
|
29833
|
+
const registration = await this.invokeBootstrapInstrumentationOperation(
|
|
29834
|
+
"instrumentation.intercept-script",
|
|
29835
|
+
(automation) => automation.interceptScript(input)
|
|
29836
|
+
);
|
|
29837
|
+
this.storedInstrumentation.push({
|
|
29838
|
+
kind: "intercept-script",
|
|
29839
|
+
input
|
|
29840
|
+
});
|
|
29841
|
+
return registration;
|
|
29365
29842
|
}
|
|
29366
29843
|
async getStorageSnapshot(input = {}) {
|
|
29367
29844
|
return this.invokeSemanticOperation("session.storage", input);
|
|
@@ -29409,6 +29886,8 @@ var init_session_proxy = __esm({
|
|
|
29409
29886
|
this.client = void 0;
|
|
29410
29887
|
this.sessionId = void 0;
|
|
29411
29888
|
this.semanticGrant = void 0;
|
|
29889
|
+
this.liveSessionStateEstablished = false;
|
|
29890
|
+
this.storedInstrumentation.length = 0;
|
|
29412
29891
|
if (this.cleanupRootOnClose) {
|
|
29413
29892
|
await promises.rm(this.rootPath, { recursive: true, force: true }).catch(() => void 0);
|
|
29414
29893
|
}
|
|
@@ -29436,6 +29915,8 @@ var init_session_proxy = __esm({
|
|
|
29436
29915
|
this.automation = void 0;
|
|
29437
29916
|
this.sessionId = void 0;
|
|
29438
29917
|
this.semanticGrant = void 0;
|
|
29918
|
+
this.liveSessionStateEstablished = false;
|
|
29919
|
+
this.storedInstrumentation.length = 0;
|
|
29439
29920
|
if (syncError !== void 0) {
|
|
29440
29921
|
throw syncError;
|
|
29441
29922
|
}
|
|
@@ -29483,6 +29964,7 @@ var init_session_proxy = __esm({
|
|
|
29483
29964
|
};
|
|
29484
29965
|
await this.writePersistedSession(record);
|
|
29485
29966
|
this.bindClient(record, session.initialGrants?.semantic);
|
|
29967
|
+
await this.restoreStoredInstrumentation();
|
|
29486
29968
|
}
|
|
29487
29969
|
async syncWorkspaceToCloud() {
|
|
29488
29970
|
if (this.workspace === void 0) {
|
|
@@ -29494,6 +29976,7 @@ var init_session_proxy = __esm({
|
|
|
29494
29976
|
bindClient(record, initialSemanticGrant) {
|
|
29495
29977
|
this.sessionId = record.sessionId;
|
|
29496
29978
|
this.semanticGrant = initialSemanticGrant?.kind === "semantic" ? initialSemanticGrant : void 0;
|
|
29979
|
+
this.liveSessionStateEstablished = false;
|
|
29497
29980
|
this.client = new OpensteerSemanticRestClient({
|
|
29498
29981
|
getBaseUrl: async () => (await this.ensureSemanticGrant()).url,
|
|
29499
29982
|
getAuthorizationHeader: async () => `Bearer ${(await this.ensureSemanticGrant()).token}`,
|
|
@@ -29501,6 +29984,19 @@ var init_session_proxy = __esm({
|
|
|
29501
29984
|
});
|
|
29502
29985
|
this.automation = new OpensteerCloudAutomationClient(this.cloud, record.sessionId);
|
|
29503
29986
|
}
|
|
29987
|
+
async restoreStoredInstrumentation() {
|
|
29988
|
+
if (this.storedInstrumentation.length === 0) {
|
|
29989
|
+
return;
|
|
29990
|
+
}
|
|
29991
|
+
const automation = this.requireAutomation();
|
|
29992
|
+
for (const registration of this.storedInstrumentation) {
|
|
29993
|
+
if (registration.kind === "route") {
|
|
29994
|
+
await automation.route(registration.input);
|
|
29995
|
+
} else {
|
|
29996
|
+
await automation.interceptScript(registration.input);
|
|
29997
|
+
}
|
|
29998
|
+
}
|
|
29999
|
+
}
|
|
29504
30000
|
async ensureWorkspaceStore() {
|
|
29505
30001
|
if (this.workspaceStore !== void 0) {
|
|
29506
30002
|
return this.workspaceStore;
|
|
@@ -29523,13 +30019,22 @@ var init_session_proxy = __esm({
|
|
|
29523
30019
|
async clearPersistedSession() {
|
|
29524
30020
|
await clearPersistedSessionRecord(this.rootPath, "cloud").catch(() => void 0);
|
|
29525
30021
|
}
|
|
30022
|
+
async invalidateSession() {
|
|
30023
|
+
await this.automation?.close().catch(() => void 0);
|
|
30024
|
+
this.automation = void 0;
|
|
30025
|
+
this.client = void 0;
|
|
30026
|
+
this.sessionId = void 0;
|
|
30027
|
+
this.semanticGrant = void 0;
|
|
30028
|
+
this.liveSessionStateEstablished = false;
|
|
30029
|
+
await this.clearPersistedSession();
|
|
30030
|
+
}
|
|
29526
30031
|
async isReusableCloudSession(sessionId, timeout) {
|
|
29527
30032
|
try {
|
|
29528
30033
|
const session = await this.cloud.getSession(sessionId, {
|
|
29529
30034
|
signal: timeout?.signal,
|
|
29530
30035
|
timeoutMs: timeout?.remainingMs()
|
|
29531
30036
|
});
|
|
29532
|
-
return session
|
|
30037
|
+
return isReusableCloudSessionState(session);
|
|
29533
30038
|
} catch (error) {
|
|
29534
30039
|
if (isMissingCloudSessionError(error)) {
|
|
29535
30040
|
return false;
|
|
@@ -29578,26 +30083,79 @@ var init_session_proxy = __esm({
|
|
|
29578
30083
|
try {
|
|
29579
30084
|
await this.ensureSemanticGrant(true);
|
|
29580
30085
|
return true;
|
|
29581
|
-
} catch {
|
|
30086
|
+
} catch (refreshError) {
|
|
30087
|
+
if (await this.resetStaleSession(refreshError)) {
|
|
30088
|
+
throw refreshError;
|
|
30089
|
+
}
|
|
29582
30090
|
return false;
|
|
29583
30091
|
}
|
|
29584
30092
|
}
|
|
29585
30093
|
async invokeSemanticOperation(operation, input, sessionInit = {}) {
|
|
29586
|
-
return this.
|
|
30094
|
+
return this.runOperationWithSessionRecovery(operation, async (timeout) => {
|
|
29587
30095
|
await this.ensureSession(sessionInit, timeout);
|
|
29588
30096
|
await this.ensureSemanticGrant(false, timeout);
|
|
29589
|
-
|
|
30097
|
+
const output = await this.requireClient().invoke(operation, input, {
|
|
29590
30098
|
signal: timeout.signal,
|
|
29591
30099
|
timeoutMs: timeout.remainingMs()
|
|
29592
30100
|
});
|
|
30101
|
+
this.noteSuccessfulLiveOperation(operation);
|
|
30102
|
+
return output;
|
|
29593
30103
|
});
|
|
29594
30104
|
}
|
|
29595
30105
|
async invokeAutomationOperation(operation, invoke, sessionInit = {}) {
|
|
29596
|
-
return this.
|
|
30106
|
+
return this.runOperationWithSessionRecovery(operation, async (timeout) => {
|
|
29597
30107
|
await this.ensureSession(sessionInit, timeout);
|
|
29598
|
-
|
|
30108
|
+
const output = await invoke(this.requireAutomation());
|
|
30109
|
+
this.noteSuccessfulLiveOperation(operation);
|
|
30110
|
+
return output;
|
|
29599
30111
|
});
|
|
29600
30112
|
}
|
|
30113
|
+
async invokeBootstrapInstrumentationOperation(operation, invoke) {
|
|
30114
|
+
let recovered = false;
|
|
30115
|
+
while (true) {
|
|
30116
|
+
try {
|
|
30117
|
+
await this.ensureSession();
|
|
30118
|
+
return await invoke(this.requireAutomation());
|
|
30119
|
+
} catch (error) {
|
|
30120
|
+
const stale = await this.resetStaleSession(error);
|
|
30121
|
+
if (!stale || recovered || !this.canRecoverWithFreshSession(operation)) {
|
|
30122
|
+
throw error;
|
|
30123
|
+
}
|
|
30124
|
+
recovered = true;
|
|
30125
|
+
}
|
|
30126
|
+
}
|
|
30127
|
+
}
|
|
30128
|
+
async runOperationWithSessionRecovery(operation, invoke) {
|
|
30129
|
+
return this.runOperationWithPolicy(operation, async (timeout) => {
|
|
30130
|
+
let recovered = false;
|
|
30131
|
+
while (true) {
|
|
30132
|
+
try {
|
|
30133
|
+
return await invoke(timeout);
|
|
30134
|
+
} catch (error) {
|
|
30135
|
+
const stale = await this.resetStaleSession(error);
|
|
30136
|
+
if (!stale || recovered || !this.canRecoverWithFreshSession(operation)) {
|
|
30137
|
+
throw error;
|
|
30138
|
+
}
|
|
30139
|
+
recovered = true;
|
|
30140
|
+
}
|
|
30141
|
+
}
|
|
30142
|
+
});
|
|
30143
|
+
}
|
|
30144
|
+
async resetStaleSession(error) {
|
|
30145
|
+
if (!isRecoverableCloudSessionError(error)) {
|
|
30146
|
+
return false;
|
|
30147
|
+
}
|
|
30148
|
+
await this.invalidateSession();
|
|
30149
|
+
return true;
|
|
30150
|
+
}
|
|
30151
|
+
canRecoverWithFreshSession(operation) {
|
|
30152
|
+
return !this.liveSessionStateEstablished && isBootstrapRecoveryOperation(operation);
|
|
30153
|
+
}
|
|
30154
|
+
noteSuccessfulLiveOperation(operation) {
|
|
30155
|
+
if (operation === "session.open" || operation === "page.list" || operation === "page.new" || operation === "page.activate" || operation === "page.close" || operation === "page.goto" || operation === "page.evaluate" || operation === "page.add-init-script" || operation === "page.snapshot" || operation === "dom.click" || operation === "dom.hover" || operation === "dom.input" || operation === "dom.scroll" || operation === "dom.extract" || operation === "network.query" || operation === "network.detail" || operation === "interaction.capture" || operation === "interaction.get" || operation === "interaction.diff" || operation === "interaction.replay" || operation === "scripts.capture" || operation === "artifact.read" || operation === "scripts.beautify" || operation === "scripts.deobfuscate" || operation === "scripts.sandbox" || operation === "captcha.solve" || operation === "session.cookies" || operation === "session.storage" || operation === "session.state" || operation === "session.fetch" || operation === "computer.execute") {
|
|
30156
|
+
this.liveSessionStateEstablished = true;
|
|
30157
|
+
}
|
|
30158
|
+
}
|
|
29601
30159
|
async runOperationWithPolicy(operation, invoke) {
|
|
29602
30160
|
return runWithPolicyTimeout(this.policy.timeout, { operation }, invoke);
|
|
29603
30161
|
}
|
|
@@ -29912,14 +30470,85 @@ var init_session_control = __esm({
|
|
|
29912
30470
|
}
|
|
29913
30471
|
});
|
|
29914
30472
|
|
|
30473
|
+
// src/internal/errors.ts
|
|
30474
|
+
function normalizeThrownOpensteerError2(error, fallbackMessage) {
|
|
30475
|
+
if (isOpensteerProtocolError(error)) {
|
|
30476
|
+
return toOpensteerError(error);
|
|
30477
|
+
}
|
|
30478
|
+
if (isBrowserCoreError(error)) {
|
|
30479
|
+
return createOpensteerError(error.code, error.message, {
|
|
30480
|
+
retriable: error.retriable,
|
|
30481
|
+
...error.details === void 0 ? {} : { details: error.details }
|
|
30482
|
+
});
|
|
30483
|
+
}
|
|
30484
|
+
if (error instanceof OpensteerAttachAmbiguousError) {
|
|
30485
|
+
return createOpensteerError("conflict", error.message, {
|
|
30486
|
+
details: {
|
|
30487
|
+
candidates: error.candidates,
|
|
30488
|
+
code: error.code,
|
|
30489
|
+
name: error.name
|
|
30490
|
+
}
|
|
30491
|
+
});
|
|
30492
|
+
}
|
|
30493
|
+
if (error instanceof Error && "opensteerError" in error && typeof error.opensteerError === "object" && error.opensteerError !== null) {
|
|
30494
|
+
const oe = error.opensteerError;
|
|
30495
|
+
return createOpensteerError(oe.code, oe.message, {
|
|
30496
|
+
retriable: oe.retriable,
|
|
30497
|
+
...oe.capability === void 0 ? {} : { capability: oe.capability },
|
|
30498
|
+
...oe.details === void 0 ? {} : { details: oe.details }
|
|
30499
|
+
});
|
|
30500
|
+
}
|
|
30501
|
+
if (error instanceof Error) {
|
|
30502
|
+
return createOpensteerError("operation-failed", error.message, {
|
|
30503
|
+
details: {
|
|
30504
|
+
name: error.name
|
|
30505
|
+
}
|
|
30506
|
+
});
|
|
30507
|
+
}
|
|
30508
|
+
return createOpensteerError("internal", fallbackMessage, {
|
|
30509
|
+
details: {
|
|
30510
|
+
value: error
|
|
30511
|
+
}
|
|
30512
|
+
});
|
|
30513
|
+
}
|
|
30514
|
+
var init_errors5 = __esm({
|
|
30515
|
+
"src/internal/errors.ts"() {
|
|
30516
|
+
init_src();
|
|
30517
|
+
init_src2();
|
|
30518
|
+
init_cdp_discovery();
|
|
30519
|
+
}
|
|
30520
|
+
});
|
|
30521
|
+
|
|
29915
30522
|
// src/sdk/opensteer.ts
|
|
29916
30523
|
var opensteer_exports = {};
|
|
29917
30524
|
__export(opensteer_exports, {
|
|
29918
30525
|
Opensteer: () => Opensteer
|
|
29919
30526
|
});
|
|
30527
|
+
function createSdkProtocolError(error, fallbackMessage) {
|
|
30528
|
+
const normalized = normalizeThrownOpensteerError2(error, fallbackMessage);
|
|
30529
|
+
return new OpensteerProtocolError(normalized.code, normalized.message, {
|
|
30530
|
+
cause: error,
|
|
30531
|
+
retriable: normalized.retriable,
|
|
30532
|
+
...normalized.capability === void 0 ? {} : { capability: normalized.capability },
|
|
30533
|
+
...normalized.details === void 0 ? {} : { details: normalized.details }
|
|
30534
|
+
});
|
|
30535
|
+
}
|
|
30536
|
+
async function wrapSdkError(operation, fn) {
|
|
30537
|
+
try {
|
|
30538
|
+
return await fn();
|
|
30539
|
+
} catch (error) {
|
|
30540
|
+
if (isOpensteerProtocolError(error)) {
|
|
30541
|
+
throw error;
|
|
30542
|
+
}
|
|
30543
|
+
throw createSdkProtocolError(error, `${operation} failed`);
|
|
30544
|
+
}
|
|
30545
|
+
}
|
|
29920
30546
|
function createUnsupportedBrowserController() {
|
|
29921
30547
|
const fail = async () => {
|
|
29922
|
-
throw new
|
|
30548
|
+
throw new OpensteerProtocolError(
|
|
30549
|
+
"unsupported-operation",
|
|
30550
|
+
"browser.* helpers are only available in local mode."
|
|
30551
|
+
);
|
|
29923
30552
|
};
|
|
29924
30553
|
return {
|
|
29925
30554
|
status: fail,
|
|
@@ -29932,7 +30561,10 @@ function normalizeTargetOptions(input) {
|
|
|
29932
30561
|
const hasElement = input.element !== void 0;
|
|
29933
30562
|
const hasSelector = input.selector !== void 0;
|
|
29934
30563
|
if (hasElement && hasSelector) {
|
|
29935
|
-
throw new
|
|
30564
|
+
throw new OpensteerProtocolError(
|
|
30565
|
+
"invalid-argument",
|
|
30566
|
+
"Specify exactly one of element, selector, or persist."
|
|
30567
|
+
);
|
|
29936
30568
|
}
|
|
29937
30569
|
if (hasElement) {
|
|
29938
30570
|
return {
|
|
@@ -29955,7 +30587,10 @@ function normalizeTargetOptions(input) {
|
|
|
29955
30587
|
};
|
|
29956
30588
|
}
|
|
29957
30589
|
if (input.persist === void 0) {
|
|
29958
|
-
throw new
|
|
30590
|
+
throw new OpensteerProtocolError(
|
|
30591
|
+
"invalid-argument",
|
|
30592
|
+
"Specify exactly one of element, selector, or persist."
|
|
30593
|
+
);
|
|
29959
30594
|
}
|
|
29960
30595
|
return {
|
|
29961
30596
|
target: {
|
|
@@ -30017,8 +30652,10 @@ function delay5(ms) {
|
|
|
30017
30652
|
var SessionCookieJar, Opensteer;
|
|
30018
30653
|
var init_opensteer = __esm({
|
|
30019
30654
|
"src/sdk/opensteer.ts"() {
|
|
30655
|
+
init_src2();
|
|
30020
30656
|
init_browser_manager();
|
|
30021
30657
|
init_env();
|
|
30658
|
+
init_errors5();
|
|
30022
30659
|
init_runtime_resolution();
|
|
30023
30660
|
SessionCookieJar = class {
|
|
30024
30661
|
domain;
|
|
@@ -30049,205 +30686,257 @@ var init_opensteer = __esm({
|
|
|
30049
30686
|
dom;
|
|
30050
30687
|
network;
|
|
30051
30688
|
constructor(options = {}) {
|
|
30052
|
-
|
|
30053
|
-
|
|
30054
|
-
|
|
30055
|
-
|
|
30056
|
-
environment
|
|
30057
|
-
});
|
|
30058
|
-
if (runtimeConfig.provider.mode === "cloud") {
|
|
30059
|
-
this.browserManager = void 0;
|
|
30060
|
-
this.runtime = createOpensteerSemanticRuntime({
|
|
30061
|
-
...provider === void 0 ? {} : { provider },
|
|
30062
|
-
...engineName === void 0 ? {} : { engine: engineName },
|
|
30063
|
-
environment,
|
|
30064
|
-
runtimeOptions
|
|
30065
|
-
});
|
|
30066
|
-
this.browser = createUnsupportedBrowserController();
|
|
30067
|
-
} else {
|
|
30068
|
-
this.browserManager = new OpensteerBrowserManager({
|
|
30069
|
-
...runtimeOptions.rootDir === void 0 ? {} : { rootDir: runtimeOptions.rootDir },
|
|
30070
|
-
...runtimeOptions.rootPath === void 0 ? {} : { rootPath: runtimeOptions.rootPath },
|
|
30071
|
-
...runtimeOptions.workspace === void 0 ? {} : { workspace: runtimeOptions.workspace },
|
|
30072
|
-
...engineName === void 0 ? {} : { engineName },
|
|
30073
|
-
environment,
|
|
30074
|
-
...runtimeOptions.browser === void 0 ? {} : { browser: runtimeOptions.browser },
|
|
30075
|
-
...runtimeOptions.launch === void 0 ? {} : { launch: runtimeOptions.launch },
|
|
30076
|
-
...runtimeOptions.context === void 0 ? {} : { context: runtimeOptions.context }
|
|
30077
|
-
});
|
|
30078
|
-
this.runtime = createOpensteerSemanticRuntime({
|
|
30689
|
+
try {
|
|
30690
|
+
const environment = resolveOpensteerEnvironment(options.rootDir);
|
|
30691
|
+
const { provider, engineName, ...runtimeOptions } = options;
|
|
30692
|
+
const runtimeConfig = resolveOpensteerRuntimeConfig({
|
|
30079
30693
|
...provider === void 0 ? {} : { provider },
|
|
30080
|
-
|
|
30081
|
-
environment,
|
|
30082
|
-
runtimeOptions: {
|
|
30083
|
-
...runtimeOptions,
|
|
30084
|
-
rootPath: this.browserManager.rootPath,
|
|
30085
|
-
cleanupRootOnClose: this.browserManager.cleanupRootOnDisconnect
|
|
30086
|
-
}
|
|
30694
|
+
environment
|
|
30087
30695
|
});
|
|
30088
|
-
|
|
30089
|
-
|
|
30090
|
-
|
|
30091
|
-
|
|
30092
|
-
|
|
30696
|
+
if (runtimeConfig.provider.mode === "cloud") {
|
|
30697
|
+
this.browserManager = void 0;
|
|
30698
|
+
this.runtime = createOpensteerSemanticRuntime({
|
|
30699
|
+
...provider === void 0 ? {} : { provider },
|
|
30700
|
+
...engineName === void 0 ? {} : { engine: engineName },
|
|
30701
|
+
environment,
|
|
30702
|
+
runtimeOptions
|
|
30703
|
+
});
|
|
30704
|
+
this.browser = createUnsupportedBrowserController();
|
|
30705
|
+
} else {
|
|
30706
|
+
this.browserManager = new OpensteerBrowserManager({
|
|
30707
|
+
...runtimeOptions.rootDir === void 0 ? {} : { rootDir: runtimeOptions.rootDir },
|
|
30708
|
+
...runtimeOptions.rootPath === void 0 ? {} : { rootPath: runtimeOptions.rootPath },
|
|
30709
|
+
...runtimeOptions.workspace === void 0 ? {} : { workspace: runtimeOptions.workspace },
|
|
30710
|
+
...engineName === void 0 ? {} : { engineName },
|
|
30711
|
+
environment,
|
|
30712
|
+
...runtimeOptions.browser === void 0 ? {} : { browser: runtimeOptions.browser },
|
|
30713
|
+
...runtimeOptions.launch === void 0 ? {} : { launch: runtimeOptions.launch },
|
|
30714
|
+
...runtimeOptions.context === void 0 ? {} : { context: runtimeOptions.context }
|
|
30715
|
+
});
|
|
30716
|
+
this.runtime = createOpensteerSemanticRuntime({
|
|
30717
|
+
...provider === void 0 ? {} : { provider },
|
|
30718
|
+
...engineName === void 0 ? {} : { engine: engineName },
|
|
30719
|
+
environment,
|
|
30720
|
+
runtimeOptions: {
|
|
30721
|
+
...runtimeOptions,
|
|
30722
|
+
rootPath: this.browserManager.rootPath,
|
|
30723
|
+
cleanupRootOnClose: this.browserManager.cleanupRootOnDisconnect
|
|
30724
|
+
}
|
|
30725
|
+
});
|
|
30726
|
+
this.browser = {
|
|
30727
|
+
status: () => wrapSdkError("browser.status", () => this.browserManager.status()),
|
|
30728
|
+
clone: (input) => wrapSdkError("browser.clone", () => this.browserManager.clonePersistentBrowser(input)),
|
|
30729
|
+
reset: () => wrapSdkError("browser.reset", () => this.browserManager.reset()),
|
|
30730
|
+
delete: () => wrapSdkError("browser.delete", () => this.browserManager.delete())
|
|
30731
|
+
};
|
|
30732
|
+
}
|
|
30733
|
+
this.dom = {
|
|
30734
|
+
click: (input) => this.click(input),
|
|
30735
|
+
hover: (input) => this.hover(input),
|
|
30736
|
+
input: (input) => this.input(input),
|
|
30737
|
+
scroll: (input) => this.scroll(input)
|
|
30738
|
+
};
|
|
30739
|
+
this.network = {
|
|
30740
|
+
query: (input = {}) => wrapSdkError("network.query", () => this.runtime.queryNetwork(input)),
|
|
30741
|
+
detail: (recordId, options2) => wrapSdkError(
|
|
30742
|
+
"network.detail",
|
|
30743
|
+
() => this.runtime.getNetworkDetail({ recordId, ...options2 })
|
|
30744
|
+
)
|
|
30093
30745
|
};
|
|
30746
|
+
} catch (error) {
|
|
30747
|
+
if (isOpensteerProtocolError(error)) {
|
|
30748
|
+
throw error;
|
|
30749
|
+
}
|
|
30750
|
+
throw createSdkProtocolError(error, "Failed to initialize Opensteer");
|
|
30094
30751
|
}
|
|
30095
|
-
this.dom = {
|
|
30096
|
-
click: (input) => this.click(input),
|
|
30097
|
-
hover: (input) => this.hover(input),
|
|
30098
|
-
input: (input) => this.input(input),
|
|
30099
|
-
scroll: (input) => this.scroll(input)
|
|
30100
|
-
};
|
|
30101
|
-
this.network = {
|
|
30102
|
-
query: (input = {}) => this.runtime.queryNetwork(input),
|
|
30103
|
-
detail: (recordId, options2) => this.runtime.getNetworkDetail({ recordId, ...options2 })
|
|
30104
|
-
};
|
|
30105
30752
|
}
|
|
30106
30753
|
async open(input = {}) {
|
|
30107
|
-
return
|
|
30754
|
+
return wrapSdkError(
|
|
30755
|
+
"session.open",
|
|
30756
|
+
() => this.runtime.open(typeof input === "string" ? { url: input } : input)
|
|
30757
|
+
);
|
|
30108
30758
|
}
|
|
30109
30759
|
async info() {
|
|
30110
|
-
return this.runtime.info();
|
|
30760
|
+
return wrapSdkError("session.info", () => this.runtime.info());
|
|
30111
30761
|
}
|
|
30112
30762
|
async listPages(input = {}) {
|
|
30113
|
-
return this.runtime.listPages(input);
|
|
30763
|
+
return wrapSdkError("page.list", () => this.runtime.listPages(input));
|
|
30114
30764
|
}
|
|
30115
30765
|
async newPage(input = {}) {
|
|
30116
|
-
return this.runtime.newPage(input);
|
|
30766
|
+
return wrapSdkError("page.new", () => this.runtime.newPage(input));
|
|
30117
30767
|
}
|
|
30118
30768
|
async activatePage(input) {
|
|
30119
|
-
return this.runtime.activatePage(input);
|
|
30769
|
+
return wrapSdkError("page.activate", () => this.runtime.activatePage(input));
|
|
30120
30770
|
}
|
|
30121
30771
|
async closePage(input = {}) {
|
|
30122
|
-
return this.runtime.closePage(input);
|
|
30772
|
+
return wrapSdkError("page.close", () => this.runtime.closePage(input));
|
|
30123
30773
|
}
|
|
30124
30774
|
async goto(url, options = {}) {
|
|
30125
|
-
return
|
|
30126
|
-
|
|
30127
|
-
|
|
30128
|
-
|
|
30775
|
+
return wrapSdkError(
|
|
30776
|
+
"page.goto",
|
|
30777
|
+
() => this.runtime.goto({
|
|
30778
|
+
url,
|
|
30779
|
+
...options
|
|
30780
|
+
})
|
|
30781
|
+
);
|
|
30129
30782
|
}
|
|
30130
30783
|
async evaluate(input) {
|
|
30131
|
-
|
|
30132
|
-
|
|
30133
|
-
|
|
30134
|
-
|
|
30784
|
+
return wrapSdkError("page.evaluate", async () => {
|
|
30785
|
+
const normalized = typeof input === "string" ? {
|
|
30786
|
+
script: input
|
|
30787
|
+
} : input;
|
|
30788
|
+
return (await this.runtime.evaluate(normalized)).value;
|
|
30789
|
+
});
|
|
30135
30790
|
}
|
|
30136
30791
|
async addInitScript(input) {
|
|
30137
|
-
return
|
|
30138
|
-
|
|
30139
|
-
|
|
30140
|
-
|
|
30792
|
+
return wrapSdkError(
|
|
30793
|
+
"page.addInitScript",
|
|
30794
|
+
() => this.runtime.addInitScript(
|
|
30795
|
+
typeof input === "string" ? {
|
|
30796
|
+
script: input
|
|
30797
|
+
} : input
|
|
30798
|
+
)
|
|
30141
30799
|
);
|
|
30142
30800
|
}
|
|
30143
30801
|
async click(input) {
|
|
30144
|
-
|
|
30145
|
-
|
|
30146
|
-
|
|
30147
|
-
|
|
30148
|
-
|
|
30149
|
-
|
|
30802
|
+
return wrapSdkError("dom.click", () => {
|
|
30803
|
+
const { button, clickCount, modifiers, ...target } = input;
|
|
30804
|
+
return this.runtime.click({
|
|
30805
|
+
...normalizeTargetOptions(target),
|
|
30806
|
+
...button === void 0 ? {} : { button },
|
|
30807
|
+
...clickCount === void 0 ? {} : { clickCount },
|
|
30808
|
+
...modifiers === void 0 ? {} : { modifiers }
|
|
30809
|
+
});
|
|
30150
30810
|
});
|
|
30151
30811
|
}
|
|
30152
30812
|
async hover(input) {
|
|
30153
|
-
return this.runtime.hover(normalizeTargetOptions(input));
|
|
30813
|
+
return wrapSdkError("dom.hover", () => this.runtime.hover(normalizeTargetOptions(input)));
|
|
30154
30814
|
}
|
|
30155
30815
|
async input(input) {
|
|
30156
|
-
return
|
|
30157
|
-
|
|
30158
|
-
|
|
30159
|
-
|
|
30160
|
-
|
|
30816
|
+
return wrapSdkError(
|
|
30817
|
+
"dom.input",
|
|
30818
|
+
() => this.runtime.input({
|
|
30819
|
+
...normalizeTargetOptions(input),
|
|
30820
|
+
text: input.text,
|
|
30821
|
+
...input.pressEnter === void 0 ? {} : { pressEnter: input.pressEnter }
|
|
30822
|
+
})
|
|
30823
|
+
);
|
|
30161
30824
|
}
|
|
30162
30825
|
async scroll(input) {
|
|
30163
|
-
return
|
|
30164
|
-
|
|
30165
|
-
|
|
30166
|
-
|
|
30167
|
-
|
|
30826
|
+
return wrapSdkError(
|
|
30827
|
+
"dom.scroll",
|
|
30828
|
+
() => this.runtime.scroll({
|
|
30829
|
+
...normalizeTargetOptions(input),
|
|
30830
|
+
direction: input.direction,
|
|
30831
|
+
amount: input.amount
|
|
30832
|
+
})
|
|
30833
|
+
);
|
|
30168
30834
|
}
|
|
30169
30835
|
async extract(input) {
|
|
30170
|
-
return (await this.runtime.extract(input)).data;
|
|
30836
|
+
return wrapSdkError("extract", async () => (await this.runtime.extract(input)).data);
|
|
30171
30837
|
}
|
|
30172
30838
|
async waitForPage(input = {}) {
|
|
30173
|
-
|
|
30174
|
-
|
|
30175
|
-
|
|
30176
|
-
|
|
30177
|
-
|
|
30178
|
-
|
|
30179
|
-
|
|
30180
|
-
|
|
30181
|
-
|
|
30182
|
-
|
|
30839
|
+
return wrapSdkError("page.waitForPage", async () => {
|
|
30840
|
+
const baseline = new Set((await this.runtime.listPages()).pages.map((page) => page.pageRef));
|
|
30841
|
+
const timeoutAt = Date.now() + (input.timeoutMs ?? 3e4);
|
|
30842
|
+
const pollIntervalMs = input.pollIntervalMs ?? 100;
|
|
30843
|
+
while (true) {
|
|
30844
|
+
const match = (await this.runtime.listPages()).pages.find((page) => {
|
|
30845
|
+
if (baseline.has(page.pageRef)) {
|
|
30846
|
+
return false;
|
|
30847
|
+
}
|
|
30848
|
+
if (input.openerPageRef !== void 0 && page.openerPageRef !== input.openerPageRef) {
|
|
30849
|
+
return false;
|
|
30850
|
+
}
|
|
30851
|
+
if (input.urlIncludes !== void 0 && !page.url.includes(input.urlIncludes)) {
|
|
30852
|
+
return false;
|
|
30853
|
+
}
|
|
30854
|
+
return true;
|
|
30855
|
+
});
|
|
30856
|
+
if (match !== void 0) {
|
|
30857
|
+
return match;
|
|
30183
30858
|
}
|
|
30184
|
-
if (
|
|
30185
|
-
|
|
30859
|
+
if (Date.now() >= timeoutAt) {
|
|
30860
|
+
throw new OpensteerProtocolError("timeout", "waitForPage timed out");
|
|
30186
30861
|
}
|
|
30187
|
-
|
|
30188
|
-
});
|
|
30189
|
-
if (match !== void 0) {
|
|
30190
|
-
return match;
|
|
30191
|
-
}
|
|
30192
|
-
if (Date.now() >= timeoutAt) {
|
|
30193
|
-
throw new Error("waitForPage timed out");
|
|
30862
|
+
await delay5(pollIntervalMs);
|
|
30194
30863
|
}
|
|
30195
|
-
|
|
30196
|
-
}
|
|
30197
|
-
}
|
|
30198
|
-
async snapshot(mode = "action") {
|
|
30199
|
-
return (await this.runtime.snapshot({ mode })).html;
|
|
30864
|
+
});
|
|
30200
30865
|
}
|
|
30201
30866
|
async cookies(domain) {
|
|
30202
|
-
return
|
|
30203
|
-
|
|
30867
|
+
return wrapSdkError(
|
|
30868
|
+
"session.cookies",
|
|
30869
|
+
async () => new SessionCookieJar(await this.runtime.getCookies(domain === void 0 ? {} : { domain }))
|
|
30204
30870
|
);
|
|
30205
30871
|
}
|
|
30206
30872
|
async storage(domain, type = "local") {
|
|
30207
|
-
|
|
30208
|
-
|
|
30209
|
-
|
|
30210
|
-
|
|
30211
|
-
|
|
30212
|
-
|
|
30213
|
-
|
|
30873
|
+
return wrapSdkError("session.storage", async () => {
|
|
30874
|
+
const snapshot = await this.runtime.getStorageSnapshot(
|
|
30875
|
+
domain === void 0 ? {} : { domain }
|
|
30876
|
+
);
|
|
30877
|
+
const domainSnapshot = pickStorageDomainSnapshot(snapshot, domain);
|
|
30878
|
+
if (domainSnapshot === void 0) {
|
|
30879
|
+
return {};
|
|
30880
|
+
}
|
|
30881
|
+
const entries = type === "local" ? domainSnapshot.localStorage : domainSnapshot.sessionStorage;
|
|
30882
|
+
return Object.fromEntries(entries.map((entry) => [entry.key, entry.value]));
|
|
30883
|
+
});
|
|
30214
30884
|
}
|
|
30215
30885
|
async state(domain) {
|
|
30216
|
-
return
|
|
30886
|
+
return wrapSdkError(
|
|
30887
|
+
"session.state",
|
|
30888
|
+
() => this.runtime.getBrowserState(domain === void 0 ? {} : { domain })
|
|
30889
|
+
);
|
|
30217
30890
|
}
|
|
30218
30891
|
async fetch(url, options = {}) {
|
|
30219
|
-
|
|
30220
|
-
|
|
30221
|
-
|
|
30222
|
-
|
|
30223
|
-
|
|
30224
|
-
|
|
30892
|
+
return wrapSdkError("session.fetch", async () => {
|
|
30893
|
+
const input = buildFetchInput(url, options);
|
|
30894
|
+
const result = await this.runtime.fetch(input);
|
|
30895
|
+
if (result.response === void 0) {
|
|
30896
|
+
throw new OpensteerProtocolError(
|
|
30897
|
+
"operation-failed",
|
|
30898
|
+
result.note ?? `session.fetch did not produce a response for ${url}`
|
|
30899
|
+
);
|
|
30900
|
+
}
|
|
30901
|
+
return toResponse(result.response);
|
|
30902
|
+
});
|
|
30225
30903
|
}
|
|
30226
30904
|
async computerExecute(input) {
|
|
30227
|
-
return this.runtime.computerExecute(input);
|
|
30905
|
+
return wrapSdkError("session.computerExecute", () => this.runtime.computerExecute(input));
|
|
30228
30906
|
}
|
|
30229
30907
|
async route(input) {
|
|
30230
|
-
return
|
|
30908
|
+
return wrapSdkError(
|
|
30909
|
+
"session.route",
|
|
30910
|
+
() => this.requireOwnedInstrumentationRuntime("route").route(input)
|
|
30911
|
+
);
|
|
30231
30912
|
}
|
|
30232
30913
|
async interceptScript(input) {
|
|
30233
|
-
return
|
|
30914
|
+
return wrapSdkError(
|
|
30915
|
+
"session.interceptScript",
|
|
30916
|
+
() => this.requireOwnedInstrumentationRuntime("interceptScript").interceptScript(input)
|
|
30917
|
+
);
|
|
30234
30918
|
}
|
|
30235
30919
|
async close() {
|
|
30236
|
-
|
|
30237
|
-
|
|
30238
|
-
|
|
30239
|
-
|
|
30240
|
-
|
|
30241
|
-
|
|
30920
|
+
return wrapSdkError("session.close", async () => {
|
|
30921
|
+
if (this.browserManager === void 0 || this.browserManager.mode === "temporary") {
|
|
30922
|
+
return this.runtime.close();
|
|
30923
|
+
}
|
|
30924
|
+
const output = await this.runtime.close();
|
|
30925
|
+
await this.browserManager.close();
|
|
30926
|
+
return output;
|
|
30927
|
+
});
|
|
30242
30928
|
}
|
|
30243
30929
|
async disconnect() {
|
|
30244
|
-
|
|
30930
|
+
return wrapSdkError("session.disconnect", () => this.runtime.disconnect());
|
|
30245
30931
|
}
|
|
30246
30932
|
requireOwnedInstrumentationRuntime(method) {
|
|
30247
30933
|
if (typeof this.runtime.route === "function" && typeof this.runtime.interceptScript === "function") {
|
|
30248
30934
|
return this.runtime;
|
|
30249
30935
|
}
|
|
30250
|
-
throw new
|
|
30936
|
+
throw new OpensteerProtocolError(
|
|
30937
|
+
"unsupported-operation",
|
|
30938
|
+
`${method}() is not available for this session runtime.`
|
|
30939
|
+
);
|
|
30251
30940
|
}
|
|
30252
30941
|
};
|
|
30253
30942
|
}
|
|
@@ -30255,7 +30944,7 @@ var init_opensteer = __esm({
|
|
|
30255
30944
|
|
|
30256
30945
|
// package.json
|
|
30257
30946
|
var package_default = {
|
|
30258
|
-
version: "0.9.
|
|
30947
|
+
version: "0.9.6"};
|
|
30259
30948
|
|
|
30260
30949
|
// src/cli/bin.ts
|
|
30261
30950
|
init_browser_manager();
|
|
@@ -30270,6 +30959,110 @@ async function loadCliEnvironment(cwd) {
|
|
|
30270
30959
|
loadEnvironment(cwd);
|
|
30271
30960
|
}
|
|
30272
30961
|
|
|
30962
|
+
// src/cli/errors.ts
|
|
30963
|
+
init_src();
|
|
30964
|
+
init_src2();
|
|
30965
|
+
var CliError = class extends Error {
|
|
30966
|
+
type;
|
|
30967
|
+
usage;
|
|
30968
|
+
constructor(type, message, usage) {
|
|
30969
|
+
super(message);
|
|
30970
|
+
this.name = "CliError";
|
|
30971
|
+
this.type = type;
|
|
30972
|
+
this.usage = usage;
|
|
30973
|
+
}
|
|
30974
|
+
format() {
|
|
30975
|
+
return this.usage === void 0 ? this.message : `${this.message}
|
|
30976
|
+
Usage: ${this.usage}`;
|
|
30977
|
+
}
|
|
30978
|
+
};
|
|
30979
|
+
function isCliError(value) {
|
|
30980
|
+
return value instanceof CliError;
|
|
30981
|
+
}
|
|
30982
|
+
function formatCliErrorOutput(error) {
|
|
30983
|
+
if (isCliError(error)) {
|
|
30984
|
+
return {
|
|
30985
|
+
success: false,
|
|
30986
|
+
error: error.format(),
|
|
30987
|
+
type: error.type
|
|
30988
|
+
};
|
|
30989
|
+
}
|
|
30990
|
+
if (isOpensteerProtocolError(error)) {
|
|
30991
|
+
return {
|
|
30992
|
+
success: false,
|
|
30993
|
+
error: error.message,
|
|
30994
|
+
code: error.code,
|
|
30995
|
+
retriable: error.retriable
|
|
30996
|
+
};
|
|
30997
|
+
}
|
|
30998
|
+
if (isBrowserCoreError(error)) {
|
|
30999
|
+
return {
|
|
31000
|
+
success: false,
|
|
31001
|
+
error: error.message,
|
|
31002
|
+
code: error.code,
|
|
31003
|
+
retriable: error.retriable
|
|
31004
|
+
};
|
|
31005
|
+
}
|
|
31006
|
+
if (error instanceof Error && "opensteerError" in error) {
|
|
31007
|
+
const oe = error.opensteerError;
|
|
31008
|
+
return {
|
|
31009
|
+
success: false,
|
|
31010
|
+
error: oe.message,
|
|
31011
|
+
code: oe.code,
|
|
31012
|
+
retriable: oe.retriable
|
|
31013
|
+
};
|
|
31014
|
+
}
|
|
31015
|
+
if (error instanceof SyntaxError) {
|
|
31016
|
+
return {
|
|
31017
|
+
success: false,
|
|
31018
|
+
error: error.message,
|
|
31019
|
+
type: "invalid_value"
|
|
31020
|
+
};
|
|
31021
|
+
}
|
|
31022
|
+
return {
|
|
31023
|
+
success: false,
|
|
31024
|
+
error: error instanceof Error ? error.message : String(error)
|
|
31025
|
+
};
|
|
31026
|
+
}
|
|
31027
|
+
function emitWarning(warning) {
|
|
31028
|
+
process.stderr.write(`${JSON.stringify({ warning })}
|
|
31029
|
+
`);
|
|
31030
|
+
}
|
|
31031
|
+
var CLI_USAGE_HINTS = {
|
|
31032
|
+
"session.open": "opensteer open <url> [--workspace <id>]",
|
|
31033
|
+
"page.goto": "opensteer goto <url>",
|
|
31034
|
+
"page.evaluate": "opensteer evaluate <script>",
|
|
31035
|
+
"page.add-init-script": "opensteer init-script <script>",
|
|
31036
|
+
"dom.click": "opensteer click <element> --persist <key>",
|
|
31037
|
+
"dom.hover": "opensteer hover <element> --persist <key>",
|
|
31038
|
+
"dom.input": "opensteer input <element> <text> --persist <key>",
|
|
31039
|
+
"dom.scroll": "opensteer scroll <direction> <amount> --persist <key>",
|
|
31040
|
+
"dom.extract": "opensteer extract <template> --persist <key>",
|
|
31041
|
+
"network.detail": "opensteer network detail <recordId>",
|
|
31042
|
+
"session.fetch": "opensteer fetch <url>",
|
|
31043
|
+
"captcha.solve": "opensteer captcha solve --provider <name> --api-key <key>",
|
|
31044
|
+
"scripts.capture": "opensteer scripts capture",
|
|
31045
|
+
"scripts.beautify": "opensteer scripts beautify <artifactId>",
|
|
31046
|
+
"scripts.deobfuscate": "opensteer scripts deobfuscate <artifactId>",
|
|
31047
|
+
"scripts.sandbox": "opensteer scripts sandbox <artifactId>",
|
|
31048
|
+
"interaction.capture": "opensteer interaction capture",
|
|
31049
|
+
"interaction.get": "opensteer interaction get <traceId>",
|
|
31050
|
+
"interaction.replay": "opensteer interaction replay <traceId>",
|
|
31051
|
+
"interaction.diff": "opensteer interaction diff <leftTraceId> <rightTraceId>",
|
|
31052
|
+
"artifact.read": "opensteer artifact read <artifactId>",
|
|
31053
|
+
"computer.click": "opensteer computer click <x> <y>",
|
|
31054
|
+
"computer.type": "opensteer computer type <text>",
|
|
31055
|
+
"computer.key": "opensteer computer key <key>",
|
|
31056
|
+
"computer.scroll": "opensteer computer scroll <x> <y> --dx <n> --dy <n>",
|
|
31057
|
+
"computer.move": "opensteer computer move <x> <y>",
|
|
31058
|
+
"computer.drag": "opensteer computer drag <x1> <y1> <x2> <y2>",
|
|
31059
|
+
"computer.screenshot": "opensteer computer screenshot",
|
|
31060
|
+
exec: "opensteer exec <expression>",
|
|
31061
|
+
record: "opensteer record --url <url> --workspace <id>",
|
|
31062
|
+
"browser.inspect": "opensteer browser inspect <endpoint>",
|
|
31063
|
+
"browser.clone": "opensteer browser clone --source-user-data-dir <path>"
|
|
31064
|
+
};
|
|
31065
|
+
|
|
30273
31066
|
// src/cli/help.ts
|
|
30274
31067
|
function getHelpText() {
|
|
30275
31068
|
return `Opensteer CLI
|
|
@@ -30288,11 +31081,11 @@ Navigation:
|
|
|
30288
31081
|
|
|
30289
31082
|
DOM:
|
|
30290
31083
|
snapshot [action|extraction]
|
|
30291
|
-
click <element> [--button left|middle|right] [--
|
|
30292
|
-
hover <element>
|
|
30293
|
-
input <element> <text>
|
|
30294
|
-
scroll <direction> <amount>
|
|
30295
|
-
extract <
|
|
31084
|
+
click <element> --persist <key> [--button left|middle|right] [--capture-network <label>]
|
|
31085
|
+
hover <element> --persist <key> [--capture-network <label>]
|
|
31086
|
+
input <element> <text> --persist <key> [--press-enter] [--capture-network <label>]
|
|
31087
|
+
scroll <direction> <amount> --persist <key> [--element <n>] [--capture-network <label>]
|
|
31088
|
+
extract <template> --persist <key>
|
|
30296
31089
|
evaluate <script>
|
|
30297
31090
|
init-script <script>
|
|
30298
31091
|
|
|
@@ -30531,7 +31324,7 @@ function parseCommandLine(argv) {
|
|
|
30531
31324
|
const key = token.slice(2, separator === -1 ? void 0 : separator);
|
|
30532
31325
|
const spec = CLI_OPTION_SPECS[key];
|
|
30533
31326
|
if (spec === void 0) {
|
|
30534
|
-
throw new
|
|
31327
|
+
throw new CliError("unknown_option", `Unknown option: --${key}.`);
|
|
30535
31328
|
}
|
|
30536
31329
|
if (separator !== -1) {
|
|
30537
31330
|
rawOptions.set(key, [...rawOptions.get(key) ?? [], token.slice(separator + 1)]);
|
|
@@ -30560,7 +31353,8 @@ function parseCommandLine(argv) {
|
|
|
30560
31353
|
continue;
|
|
30561
31354
|
}
|
|
30562
31355
|
if (next === void 0 || next.startsWith("--")) {
|
|
30563
|
-
throw new
|
|
31356
|
+
throw new CliError(
|
|
31357
|
+
"missing_arguments",
|
|
30564
31358
|
`Option "--${key}" requires a value.${next?.startsWith("--") === true ? ` Use "--${key}=<value>" when the value begins with "--".` : ``}`
|
|
30565
31359
|
);
|
|
30566
31360
|
}
|
|
@@ -30606,10 +31400,14 @@ function parseCommandLine(argv) {
|
|
|
30606
31400
|
const autoLocalView = readOptionalBoolean(rawOptions, "auto");
|
|
30607
31401
|
const noAutoLocalView = readOptionalBoolean(rawOptions, "no-auto");
|
|
30608
31402
|
if (autoLocalView === true && noAutoLocalView === true) {
|
|
30609
|
-
throw new
|
|
31403
|
+
throw new CliError("invalid_option", 'Options "--auto" and "--no-auto" cannot be combined.');
|
|
30610
31404
|
}
|
|
30611
31405
|
if (command[0] !== "view" && (autoLocalView !== void 0 || noAutoLocalView !== void 0)) {
|
|
30612
|
-
throw new
|
|
31406
|
+
throw new CliError(
|
|
31407
|
+
"invalid_option",
|
|
31408
|
+
'Options "--auto" and "--no-auto" are only supported with "view".',
|
|
31409
|
+
"opensteer view --auto"
|
|
31410
|
+
);
|
|
30613
31411
|
}
|
|
30614
31412
|
const global = readOptionalBoolean(rawOptions, "global");
|
|
30615
31413
|
const yes = readOptionalBoolean(rawOptions, "yes");
|
|
@@ -30665,7 +31463,7 @@ function parseKeyValueList(values) {
|
|
|
30665
31463
|
values.map((entry) => {
|
|
30666
31464
|
const separator = entry.indexOf("=");
|
|
30667
31465
|
if (separator <= 0) {
|
|
30668
|
-
throw new
|
|
31466
|
+
throw new CliError("invalid_value", `Expected NAME=VALUE, received "${entry}".`);
|
|
30669
31467
|
}
|
|
30670
31468
|
return [entry.slice(0, separator), entry.slice(separator + 1)];
|
|
30671
31469
|
})
|
|
@@ -30696,7 +31494,7 @@ function readOptionalBoolean(options, name) {
|
|
|
30696
31494
|
if (value === "false") {
|
|
30697
31495
|
return false;
|
|
30698
31496
|
}
|
|
30699
|
-
throw new
|
|
31497
|
+
throw new CliError("invalid_value", `Option "--${name}" must be true or false.`);
|
|
30700
31498
|
}
|
|
30701
31499
|
function readOptionalNumber(options, name) {
|
|
30702
31500
|
const value = readSingle(options, name);
|
|
@@ -30705,13 +31503,20 @@ function readOptionalNumber(options, name) {
|
|
|
30705
31503
|
}
|
|
30706
31504
|
const parsed = Number(value);
|
|
30707
31505
|
if (!Number.isFinite(parsed)) {
|
|
30708
|
-
throw new
|
|
31506
|
+
throw new CliError("invalid_value", `Option "--${name}" must be a number.`);
|
|
30709
31507
|
}
|
|
30710
31508
|
return parsed;
|
|
30711
31509
|
}
|
|
30712
31510
|
function readJsonValue(options, name) {
|
|
30713
31511
|
const value = readSingle(options, name);
|
|
30714
|
-
|
|
31512
|
+
if (value === void 0) {
|
|
31513
|
+
return void 0;
|
|
31514
|
+
}
|
|
31515
|
+
try {
|
|
31516
|
+
return JSON.parse(value);
|
|
31517
|
+
} catch {
|
|
31518
|
+
throw new CliError("invalid_value", `Option "--${name}" contains invalid JSON.`);
|
|
31519
|
+
}
|
|
30715
31520
|
}
|
|
30716
31521
|
function readJsonObject(options, name) {
|
|
30717
31522
|
const parsed = readJsonValue(options, name);
|
|
@@ -30719,7 +31524,7 @@ function readJsonObject(options, name) {
|
|
|
30719
31524
|
return void 0;
|
|
30720
31525
|
}
|
|
30721
31526
|
if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) {
|
|
30722
|
-
throw new
|
|
31527
|
+
throw new CliError("invalid_value", `Option "--${name}" must be a JSON object.`);
|
|
30723
31528
|
}
|
|
30724
31529
|
return parsed;
|
|
30725
31530
|
}
|
|
@@ -30729,7 +31534,7 @@ function readJsonArray(options, name) {
|
|
|
30729
31534
|
return void 0;
|
|
30730
31535
|
}
|
|
30731
31536
|
if (!Array.isArray(parsed)) {
|
|
30732
|
-
throw new
|
|
31537
|
+
throw new CliError("invalid_value", `Option "--${name}" must be a JSON array.`);
|
|
30733
31538
|
}
|
|
30734
31539
|
return parsed;
|
|
30735
31540
|
}
|
|
@@ -30749,7 +31554,7 @@ async function buildOperationInput(operation, parsed, runtime) {
|
|
|
30749
31554
|
case "session.open": {
|
|
30750
31555
|
const url = parsed.rest[0];
|
|
30751
31556
|
if (url === void 0) {
|
|
30752
|
-
throw new
|
|
31557
|
+
throw new CliError("missing_arguments", "open requires a URL.", CLI_USAGE_HINTS[operation]);
|
|
30753
31558
|
}
|
|
30754
31559
|
return {
|
|
30755
31560
|
url,
|
|
@@ -30782,7 +31587,7 @@ async function buildOperationInput(operation, parsed, runtime) {
|
|
|
30782
31587
|
}
|
|
30783
31588
|
case "page.goto": {
|
|
30784
31589
|
if (parsed.rest[0] === void 0) {
|
|
30785
|
-
throw new
|
|
31590
|
+
throw new CliError("missing_arguments", "goto requires a URL.", CLI_USAGE_HINTS[operation]);
|
|
30786
31591
|
}
|
|
30787
31592
|
const captureNetwork = readSingle(parsed.rawOptions, "capture-network");
|
|
30788
31593
|
return {
|
|
@@ -30794,14 +31599,14 @@ async function buildOperationInput(operation, parsed, runtime) {
|
|
|
30794
31599
|
return parsed.rest[0] === void 0 ? {} : { mode: parsed.rest[0] };
|
|
30795
31600
|
case "page.evaluate":
|
|
30796
31601
|
if (parsed.rest[0] === void 0) {
|
|
30797
|
-
throw new
|
|
31602
|
+
throw new CliError("missing_arguments", "evaluate requires a script.", CLI_USAGE_HINTS[operation]);
|
|
30798
31603
|
}
|
|
30799
31604
|
return {
|
|
30800
31605
|
script: joinRest(parsed.rest, 0)
|
|
30801
31606
|
};
|
|
30802
31607
|
case "page.add-init-script":
|
|
30803
31608
|
if (parsed.rest[0] === void 0) {
|
|
30804
|
-
throw new
|
|
31609
|
+
throw new CliError("missing_arguments", "init-script requires a script.", CLI_USAGE_HINTS[operation]);
|
|
30805
31610
|
}
|
|
30806
31611
|
return {
|
|
30807
31612
|
script: joinRest(parsed.rest, 0)
|
|
@@ -30817,7 +31622,7 @@ async function buildOperationInput(operation, parsed, runtime) {
|
|
|
30817
31622
|
return buildElementTargetInput(parsed, "hover");
|
|
30818
31623
|
case "dom.input": {
|
|
30819
31624
|
if (parsed.rest[1] === void 0) {
|
|
30820
|
-
throw new
|
|
31625
|
+
throw new CliError("missing_arguments", "input requires an element number and text.", CLI_USAGE_HINTS[operation]);
|
|
30821
31626
|
}
|
|
30822
31627
|
const pressEnter = readOptionalBoolean(parsed.rawOptions, "press-enter");
|
|
30823
31628
|
return {
|
|
@@ -30842,18 +31647,18 @@ async function buildOperationInput(operation, parsed, runtime) {
|
|
|
30842
31647
|
},
|
|
30843
31648
|
direction,
|
|
30844
31649
|
amount,
|
|
30845
|
-
|
|
31650
|
+
persist,
|
|
30846
31651
|
...captureNetwork === void 0 ? {} : { captureNetwork }
|
|
30847
31652
|
};
|
|
30848
31653
|
}
|
|
30849
31654
|
case "dom.extract": {
|
|
30850
31655
|
if (parsed.rest[0] === void 0) {
|
|
30851
|
-
throw new
|
|
31656
|
+
throw new CliError("missing_arguments", "extract requires a template.", CLI_USAGE_HINTS[operation]);
|
|
30852
31657
|
}
|
|
30853
|
-
const persist =
|
|
31658
|
+
const persist = readPersistKey(parsed, "extract");
|
|
30854
31659
|
return {
|
|
30855
|
-
|
|
30856
|
-
|
|
31660
|
+
persist,
|
|
31661
|
+
template: parseRequiredJsonObjectArgument(joinRest(parsed.rest, 0), "extract template")
|
|
30857
31662
|
};
|
|
30858
31663
|
}
|
|
30859
31664
|
case "network.query": {
|
|
@@ -30884,7 +31689,7 @@ async function buildOperationInput(operation, parsed, runtime) {
|
|
|
30884
31689
|
}
|
|
30885
31690
|
case "network.detail": {
|
|
30886
31691
|
if (parsed.rest[0] === void 0) {
|
|
30887
|
-
throw new
|
|
31692
|
+
throw new CliError("missing_arguments", "network detail requires a record id.", CLI_USAGE_HINTS[operation]);
|
|
30888
31693
|
}
|
|
30889
31694
|
const probeFlag = readOptionalBoolean(parsed.rawOptions, "probe");
|
|
30890
31695
|
return {
|
|
@@ -30895,7 +31700,7 @@ async function buildOperationInput(operation, parsed, runtime) {
|
|
|
30895
31700
|
case "session.fetch": {
|
|
30896
31701
|
const url = parsed.rest[0];
|
|
30897
31702
|
if (url === void 0) {
|
|
30898
|
-
throw new
|
|
31703
|
+
throw new CliError("missing_arguments", "fetch requires a URL.", CLI_USAGE_HINTS[operation]);
|
|
30899
31704
|
}
|
|
30900
31705
|
const bodyJson = readJsonValue(parsed.rawOptions, "body");
|
|
30901
31706
|
const bodyText = readSingle(parsed.rawOptions, "body-text");
|
|
@@ -30903,7 +31708,7 @@ async function buildOperationInput(operation, parsed, runtime) {
|
|
|
30903
31708
|
const query = parseKeyValueList(parsed.rawOptions.get("query"));
|
|
30904
31709
|
const headers = parseKeyValueList(parsed.rawOptions.get("header"));
|
|
30905
31710
|
if (bodyJson !== void 0 && bodyText !== void 0) {
|
|
30906
|
-
throw new
|
|
31711
|
+
throw new CliError("invalid_option", 'Use either "--body" or "--body-text", not both.');
|
|
30907
31712
|
}
|
|
30908
31713
|
const transport = readSingle(parsed.rawOptions, "transport");
|
|
30909
31714
|
const cookies = readOptionalBoolean(parsed.rawOptions, "cookies");
|
|
@@ -30934,7 +31739,7 @@ async function buildOperationInput(operation, parsed, runtime) {
|
|
|
30934
31739
|
const siteKey = readSingle(parsed.rawOptions, "site-key");
|
|
30935
31740
|
const pageUrl = readSingle(parsed.rawOptions, "page-url");
|
|
30936
31741
|
if (provider === void 0 || apiKey === void 0) {
|
|
30937
|
-
throw new
|
|
31742
|
+
throw new CliError("missing_arguments", 'captcha solve requires "--provider" and "--api-key".', CLI_USAGE_HINTS[operation]);
|
|
30938
31743
|
}
|
|
30939
31744
|
return {
|
|
30940
31745
|
provider: readCaptchaProvider(provider),
|
|
@@ -30964,7 +31769,7 @@ async function buildOperationInput(operation, parsed, runtime) {
|
|
|
30964
31769
|
case "scripts.beautify":
|
|
30965
31770
|
case "scripts.deobfuscate": {
|
|
30966
31771
|
if (parsed.rest[0] === void 0) {
|
|
30967
|
-
throw new
|
|
31772
|
+
throw new CliError("missing_arguments", `${parsed.command.join(" ")} requires an artifact id.`, CLI_USAGE_HINTS[operation]);
|
|
30968
31773
|
}
|
|
30969
31774
|
const persist = readOptionalBoolean(parsed.rawOptions, "persist");
|
|
30970
31775
|
return {
|
|
@@ -30974,7 +31779,7 @@ async function buildOperationInput(operation, parsed, runtime) {
|
|
|
30974
31779
|
}
|
|
30975
31780
|
case "scripts.sandbox":
|
|
30976
31781
|
if (parsed.rest[0] === void 0) {
|
|
30977
|
-
throw new
|
|
31782
|
+
throw new CliError("missing_arguments", "scripts sandbox requires an artifact id.", CLI_USAGE_HINTS[operation]);
|
|
30978
31783
|
}
|
|
30979
31784
|
{
|
|
30980
31785
|
const fidelity = readSingle(parsed.rawOptions, "fidelity");
|
|
@@ -31023,14 +31828,14 @@ async function buildOperationInput(operation, parsed, runtime) {
|
|
|
31023
31828
|
case "interaction.get":
|
|
31024
31829
|
case "interaction.replay":
|
|
31025
31830
|
if (parsed.rest[0] === void 0) {
|
|
31026
|
-
throw new
|
|
31831
|
+
throw new CliError("missing_arguments", `${parsed.command.join(" ")} requires a trace id.`, CLI_USAGE_HINTS[operation]);
|
|
31027
31832
|
}
|
|
31028
31833
|
return {
|
|
31029
31834
|
traceId: parsed.rest[0]
|
|
31030
31835
|
};
|
|
31031
31836
|
case "interaction.diff":
|
|
31032
31837
|
if (parsed.rest[0] === void 0 || parsed.rest[1] === void 0) {
|
|
31033
|
-
throw new
|
|
31838
|
+
throw new CliError("missing_arguments", "interaction diff requires two trace ids.", CLI_USAGE_HINTS[operation]);
|
|
31034
31839
|
}
|
|
31035
31840
|
return {
|
|
31036
31841
|
leftTraceId: parsed.rest[0],
|
|
@@ -31038,7 +31843,7 @@ async function buildOperationInput(operation, parsed, runtime) {
|
|
|
31038
31843
|
};
|
|
31039
31844
|
case "artifact.read":
|
|
31040
31845
|
if (parsed.rest[0] === void 0) {
|
|
31041
|
-
throw new
|
|
31846
|
+
throw new CliError("missing_arguments", "artifact read requires an artifact id.", CLI_USAGE_HINTS[operation]);
|
|
31042
31847
|
}
|
|
31043
31848
|
return {
|
|
31044
31849
|
artifactId: parsed.rest[0]
|
|
@@ -31046,7 +31851,8 @@ async function buildOperationInput(operation, parsed, runtime) {
|
|
|
31046
31851
|
case "session.close":
|
|
31047
31852
|
return {};
|
|
31048
31853
|
default:
|
|
31049
|
-
throw new
|
|
31854
|
+
throw new CliError(
|
|
31855
|
+
"unsupported_operation",
|
|
31050
31856
|
`${operation} does not have a direct CLI input shape. Use a supported command or the SDK.`
|
|
31051
31857
|
);
|
|
31052
31858
|
}
|
|
@@ -31063,7 +31869,7 @@ function buildElementTargetInput(parsed, verb) {
|
|
|
31063
31869
|
kind: "element",
|
|
31064
31870
|
element
|
|
31065
31871
|
},
|
|
31066
|
-
|
|
31872
|
+
persist,
|
|
31067
31873
|
...captureNetwork === void 0 ? {} : { captureNetwork }
|
|
31068
31874
|
};
|
|
31069
31875
|
}
|
|
@@ -31093,7 +31899,7 @@ function buildComputerExecuteInput(parsed) {
|
|
|
31093
31899
|
}
|
|
31094
31900
|
case "type":
|
|
31095
31901
|
if (parsed.rest[0] === void 0) {
|
|
31096
|
-
throw new
|
|
31902
|
+
throw new CliError("missing_arguments", "computer type requires text.");
|
|
31097
31903
|
}
|
|
31098
31904
|
return {
|
|
31099
31905
|
action: {
|
|
@@ -31104,7 +31910,7 @@ function buildComputerExecuteInput(parsed) {
|
|
|
31104
31910
|
};
|
|
31105
31911
|
case "key": {
|
|
31106
31912
|
if (parsed.rest[0] === void 0) {
|
|
31107
|
-
throw new
|
|
31913
|
+
throw new CliError("missing_arguments", "computer key requires a key.");
|
|
31108
31914
|
}
|
|
31109
31915
|
const modifiers = readKeyModifiers(readSingle(parsed.rawOptions, "modifiers"));
|
|
31110
31916
|
return {
|
|
@@ -31120,7 +31926,7 @@ function buildComputerExecuteInput(parsed) {
|
|
|
31120
31926
|
const dx = readOptionalNumber(parsed.rawOptions, "dx");
|
|
31121
31927
|
const dy = readOptionalNumber(parsed.rawOptions, "dy");
|
|
31122
31928
|
if (dx === void 0 || dy === void 0) {
|
|
31123
|
-
throw new
|
|
31929
|
+
throw new CliError("missing_arguments", 'computer scroll requires "--dx" and "--dy".');
|
|
31124
31930
|
}
|
|
31125
31931
|
return {
|
|
31126
31932
|
action: {
|
|
@@ -31175,49 +31981,50 @@ function buildComputerExecuteInput(parsed) {
|
|
|
31175
31981
|
}
|
|
31176
31982
|
};
|
|
31177
31983
|
default:
|
|
31178
|
-
throw new
|
|
31984
|
+
throw new CliError("unknown_command", `Unknown computer command: ${parsed.command.join(" ")}`);
|
|
31179
31985
|
}
|
|
31180
31986
|
}
|
|
31181
31987
|
async function resolvePageRefByIndex(runtime, index) {
|
|
31182
31988
|
const pages = (await runtime.listPages({})).pages;
|
|
31183
31989
|
const page = pages[index - 1];
|
|
31184
31990
|
if (page === void 0) {
|
|
31185
|
-
throw new
|
|
31991
|
+
throw new CliError("invalid_value", `tab ${String(index)} does not exist.`);
|
|
31186
31992
|
}
|
|
31187
31993
|
return page.pageRef;
|
|
31188
31994
|
}
|
|
31189
31995
|
function readRequiredPositiveInteger(value, message) {
|
|
31190
31996
|
const parsed = readRequiredNumber(value, message);
|
|
31191
31997
|
if (!Number.isInteger(parsed) || parsed < 1) {
|
|
31192
|
-
throw new
|
|
31998
|
+
throw new CliError("missing_arguments", message);
|
|
31193
31999
|
}
|
|
31194
32000
|
return parsed;
|
|
31195
32001
|
}
|
|
31196
32002
|
function readRequiredNumber(value, message) {
|
|
31197
32003
|
if (value === void 0) {
|
|
31198
|
-
throw new
|
|
32004
|
+
throw new CliError("missing_arguments", message);
|
|
31199
32005
|
}
|
|
31200
32006
|
const parsed = Number(value);
|
|
31201
32007
|
if (!Number.isFinite(parsed)) {
|
|
31202
|
-
throw new
|
|
32008
|
+
throw new CliError("missing_arguments", message);
|
|
31203
32009
|
}
|
|
31204
32010
|
return parsed;
|
|
31205
32011
|
}
|
|
31206
32012
|
function readSingleDirection(value) {
|
|
31207
32013
|
if (value === void 0 || !SCROLL_DIRECTIONS.has(value)) {
|
|
31208
|
-
throw new
|
|
32014
|
+
throw new CliError("missing_arguments", "scroll requires a direction: up, down, left, or right.");
|
|
31209
32015
|
}
|
|
31210
32016
|
return value;
|
|
31211
32017
|
}
|
|
31212
32018
|
function readClickButton(value) {
|
|
31213
32019
|
if (value === void 0 || !CLICK_BUTTONS.has(value)) {
|
|
31214
|
-
throw new
|
|
32020
|
+
throw new CliError("invalid_value", 'Expected "--button" to be one of: left, middle, right.');
|
|
31215
32021
|
}
|
|
31216
32022
|
return value;
|
|
31217
32023
|
}
|
|
31218
32024
|
function readFetchTransport(value) {
|
|
31219
32025
|
if (value === void 0 || !FETCH_TRANSPORTS.has(value)) {
|
|
31220
|
-
throw new
|
|
32026
|
+
throw new CliError(
|
|
32027
|
+
"invalid_value",
|
|
31221
32028
|
'Expected "--transport" to be one of: auto, direct, matched-tls, context, page.'
|
|
31222
32029
|
);
|
|
31223
32030
|
}
|
|
@@ -31225,31 +32032,31 @@ function readFetchTransport(value) {
|
|
|
31225
32032
|
}
|
|
31226
32033
|
function readCaptchaProvider(value) {
|
|
31227
32034
|
if (value === void 0 || !CAPTCHA_PROVIDERS.has(value)) {
|
|
31228
|
-
throw new
|
|
32035
|
+
throw new CliError("invalid_value", 'Expected "--provider" to be one of: 2captcha, capsolver.');
|
|
31229
32036
|
}
|
|
31230
32037
|
return value;
|
|
31231
32038
|
}
|
|
31232
32039
|
function readCaptchaType(value) {
|
|
31233
32040
|
if (value === void 0 || !CAPTCHA_TYPES.has(value)) {
|
|
31234
|
-
throw new
|
|
32041
|
+
throw new CliError("invalid_value", 'Expected "--type" to be one of: recaptcha-v2, hcaptcha, turnstile.');
|
|
31235
32042
|
}
|
|
31236
32043
|
return value;
|
|
31237
32044
|
}
|
|
31238
32045
|
function readSandboxFidelity(value) {
|
|
31239
32046
|
if (value === void 0 || !SANDBOX_FIDELITIES.has(value)) {
|
|
31240
|
-
throw new
|
|
32047
|
+
throw new CliError("invalid_value", 'Expected "--fidelity" to be one of: minimal, standard, full.');
|
|
31241
32048
|
}
|
|
31242
32049
|
return value;
|
|
31243
32050
|
}
|
|
31244
32051
|
function readSandboxClockMode(value) {
|
|
31245
32052
|
if (value === void 0 || !SANDBOX_CLOCK_MODES.has(value)) {
|
|
31246
|
-
throw new
|
|
32053
|
+
throw new CliError("invalid_value", 'Expected "--clock" to be one of: real, manual.');
|
|
31247
32054
|
}
|
|
31248
32055
|
return value;
|
|
31249
32056
|
}
|
|
31250
32057
|
function readScreenshotFormat(value) {
|
|
31251
32058
|
if (value === void 0 || !SCREENSHOT_FORMATS.has(value)) {
|
|
31252
|
-
throw new
|
|
32059
|
+
throw new CliError("invalid_value", 'Expected "--format" to be one of: png, jpeg, webp.');
|
|
31253
32060
|
}
|
|
31254
32061
|
return value;
|
|
31255
32062
|
}
|
|
@@ -31260,7 +32067,7 @@ function readKeyModifiers(value) {
|
|
|
31260
32067
|
}
|
|
31261
32068
|
for (const modifier of modifiers) {
|
|
31262
32069
|
if (!KEY_MODIFIERS.has(modifier)) {
|
|
31263
|
-
throw new
|
|
32070
|
+
throw new CliError("invalid_value", 'Expected "--modifiers" to contain only: Shift, Control, Alt, Meta.');
|
|
31264
32071
|
}
|
|
31265
32072
|
}
|
|
31266
32073
|
return [...new Set(modifiers)];
|
|
@@ -31268,30 +32075,22 @@ function readKeyModifiers(value) {
|
|
|
31268
32075
|
function readPersistKey(parsed, verb) {
|
|
31269
32076
|
const value = readSingle(parsed.rawOptions, "persist");
|
|
31270
32077
|
if (value === void 0) {
|
|
31271
|
-
|
|
31272
|
-
}
|
|
31273
|
-
if (value === "true" || value === "false") {
|
|
31274
|
-
throw new Error(`${verb} requires "--persist <key>" when using --persist.`);
|
|
31275
|
-
}
|
|
31276
|
-
if (verb === "scroll" && readOptionalNumber(parsed.rawOptions, "element") === void 0) {
|
|
31277
|
-
throw new Error('scroll requires "--element <n>" when using "--persist <key>".');
|
|
31278
|
-
}
|
|
31279
|
-
return value;
|
|
31280
|
-
}
|
|
31281
|
-
function readExtractPersistKey(parsed) {
|
|
31282
|
-
const value = readSingle(parsed.rawOptions, "persist");
|
|
31283
|
-
if (value === void 0) {
|
|
31284
|
-
return void 0;
|
|
32078
|
+
throw new CliError("missing_arguments", `${verb} requires "--persist <key>".`);
|
|
31285
32079
|
}
|
|
31286
32080
|
if (value === "true" || value === "false") {
|
|
31287
|
-
throw new
|
|
32081
|
+
throw new CliError("missing_arguments", `${verb} requires "--persist <key>".`);
|
|
31288
32082
|
}
|
|
31289
32083
|
return value;
|
|
31290
32084
|
}
|
|
31291
32085
|
function parseRequiredJsonObjectArgument(value, label) {
|
|
31292
|
-
|
|
32086
|
+
let parsed;
|
|
32087
|
+
try {
|
|
32088
|
+
parsed = JSON.parse(value);
|
|
32089
|
+
} catch {
|
|
32090
|
+
throw new CliError("invalid_value", `${label} contains invalid JSON.`);
|
|
32091
|
+
}
|
|
31293
32092
|
if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) {
|
|
31294
|
-
throw new
|
|
32093
|
+
throw new CliError("invalid_value", `${label} must be a JSON object.`);
|
|
31295
32094
|
}
|
|
31296
32095
|
return parsed;
|
|
31297
32096
|
}
|
|
@@ -34269,7 +35068,7 @@ async function handleViewCommand(parsed, options = {}) {
|
|
|
34269
35068
|
return;
|
|
34270
35069
|
}
|
|
34271
35070
|
if (subcommand !== void 0) {
|
|
34272
|
-
throw new
|
|
35071
|
+
throw new CliError("unknown_command", `Unknown view command: view ${subcommand}`);
|
|
34273
35072
|
}
|
|
34274
35073
|
if (parsed.options.localViewMode !== void 0) {
|
|
34275
35074
|
const preference = await setLocalViewMode(parsed.options.localViewMode);
|
|
@@ -34317,7 +35116,10 @@ async function resolveWorkspaceSessionId(input) {
|
|
|
34317
35116
|
}
|
|
34318
35117
|
function assertNoViewPreferenceFlag(parsed) {
|
|
34319
35118
|
if (parsed.options.localViewMode !== void 0) {
|
|
34320
|
-
throw new
|
|
35119
|
+
throw new CliError(
|
|
35120
|
+
"invalid_option",
|
|
35121
|
+
"View preference flags cannot be combined with this subcommand."
|
|
35122
|
+
);
|
|
34321
35123
|
}
|
|
34322
35124
|
}
|
|
34323
35125
|
function writeViewOutput(parsed, value) {
|
|
@@ -34402,10 +35204,10 @@ async function main() {
|
|
|
34402
35204
|
}
|
|
34403
35205
|
const operation = resolveOperation(parsed.command);
|
|
34404
35206
|
if (!operation) {
|
|
34405
|
-
throw new
|
|
35207
|
+
throw new CliError("unknown_command", `Unknown command: ${parsed.command.join(" ")}`);
|
|
34406
35208
|
}
|
|
34407
35209
|
if (parsed.options.workspace === void 0) {
|
|
34408
|
-
throw new
|
|
35210
|
+
throw new CliError("missing_workspace", 'Stateful commands require "--workspace <id>" or OPENSTEER_WORKSPACE.');
|
|
34409
35211
|
}
|
|
34410
35212
|
const { engineName, provider, runtimeProvider } = resolveCliRuntimeSelection(parsed);
|
|
34411
35213
|
if (operation === "session.close") {
|
|
@@ -34427,24 +35229,39 @@ async function main() {
|
|
|
34427
35229
|
let renderOperation = operation;
|
|
34428
35230
|
try {
|
|
34429
35231
|
const input = await buildOperationInput(operation, parsed, runtime);
|
|
34430
|
-
|
|
35232
|
+
const rawResult = await dispatchSemanticOperation(runtime, operation, input);
|
|
34431
35233
|
if (parsed.command[0] === "tab" && operation !== "page.list") {
|
|
34432
35234
|
renderOperation = "page.list";
|
|
34433
35235
|
result = await runtime.listPages({});
|
|
35236
|
+
} else {
|
|
35237
|
+
result = rawResult;
|
|
35238
|
+
}
|
|
35239
|
+
let warning;
|
|
35240
|
+
if (result !== null && typeof result === "object" && "warning" in result) {
|
|
35241
|
+
const { warning: w, ...rest } = result;
|
|
35242
|
+
if (typeof w === "string") {
|
|
35243
|
+
warning = w;
|
|
35244
|
+
result = rest;
|
|
35245
|
+
}
|
|
34434
35246
|
}
|
|
34435
35247
|
process4__default.default.stdout.write(renderOperationOutput(renderOperation, result, input));
|
|
35248
|
+
if (warning !== void 0) {
|
|
35249
|
+
emitWarning(warning);
|
|
35250
|
+
}
|
|
34436
35251
|
} finally {
|
|
34437
35252
|
await runtime.disconnect().catch(() => void 0);
|
|
34438
35253
|
}
|
|
34439
35254
|
}
|
|
34440
35255
|
async function handleExecCommand(parsed) {
|
|
34441
35256
|
if (parsed.options.workspace === void 0) {
|
|
34442
|
-
throw new
|
|
35257
|
+
throw new CliError("missing_workspace", 'exec requires "--workspace <id>" or OPENSTEER_WORKSPACE.');
|
|
34443
35258
|
}
|
|
34444
35259
|
const expression = parsed.rest.join(" ");
|
|
34445
35260
|
if (!expression) {
|
|
34446
|
-
throw new
|
|
34447
|
-
|
|
35261
|
+
throw new CliError(
|
|
35262
|
+
"missing_arguments",
|
|
35263
|
+
"exec requires an expression.",
|
|
35264
|
+
"opensteer exec <expression>"
|
|
34448
35265
|
);
|
|
34449
35266
|
}
|
|
34450
35267
|
const { engineName, runtimeProvider } = resolveCliRuntimeSelection(parsed);
|
|
@@ -34480,8 +35297,10 @@ async function handleBrowserCommand(parsed) {
|
|
|
34480
35297
|
if (subcommand === "inspect") {
|
|
34481
35298
|
const endpoint = parsed.options.attachEndpoint ?? parsed.rest[0];
|
|
34482
35299
|
if (!endpoint) {
|
|
34483
|
-
throw new
|
|
34484
|
-
|
|
35300
|
+
throw new CliError(
|
|
35301
|
+
"missing_arguments",
|
|
35302
|
+
'browser inspect requires "--attach-endpoint <url>" or a positional endpoint.',
|
|
35303
|
+
"opensteer browser inspect <endpoint>"
|
|
34485
35304
|
);
|
|
34486
35305
|
}
|
|
34487
35306
|
const result = await inspectCdpEndpoint({
|
|
@@ -34494,7 +35313,8 @@ async function handleBrowserCommand(parsed) {
|
|
|
34494
35313
|
return;
|
|
34495
35314
|
}
|
|
34496
35315
|
if (parsed.options.workspace === void 0) {
|
|
34497
|
-
throw new
|
|
35316
|
+
throw new CliError(
|
|
35317
|
+
"missing_workspace",
|
|
34498
35318
|
'Browser workspace commands require "--workspace <id>" or OPENSTEER_WORKSPACE.'
|
|
34499
35319
|
);
|
|
34500
35320
|
}
|
|
@@ -34517,7 +35337,11 @@ async function handleBrowserCommand(parsed) {
|
|
|
34517
35337
|
case "clone": {
|
|
34518
35338
|
const sourceUserDataDir = parsed.options.sourceUserDataDir;
|
|
34519
35339
|
if (!sourceUserDataDir) {
|
|
34520
|
-
throw new
|
|
35340
|
+
throw new CliError(
|
|
35341
|
+
"missing_arguments",
|
|
35342
|
+
'browser clone requires "--source-user-data-dir <path>".',
|
|
35343
|
+
"opensteer browser clone --source-user-data-dir <path>"
|
|
35344
|
+
);
|
|
34521
35345
|
}
|
|
34522
35346
|
const result = await manager.clonePersistentBrowser({
|
|
34523
35347
|
sourceUserDataDir,
|
|
@@ -34540,7 +35364,7 @@ async function handleBrowserCommand(parsed) {
|
|
|
34540
35364
|
return;
|
|
34541
35365
|
}
|
|
34542
35366
|
default:
|
|
34543
|
-
throw new
|
|
35367
|
+
throw new CliError("unknown_command", `Unknown browser command: ${parsed.command.join(" ")}`);
|
|
34544
35368
|
}
|
|
34545
35369
|
}
|
|
34546
35370
|
async function handleCloseCommand(parsed, engineName, providerMode, runtimeProvider) {
|
|
@@ -34573,23 +35397,27 @@ async function handleCloseCommand(parsed, engineName, providerMode, runtimeProvi
|
|
|
34573
35397
|
}
|
|
34574
35398
|
async function handleRecordCommandEntry(parsed) {
|
|
34575
35399
|
if (parsed.options.workspace === void 0) {
|
|
34576
|
-
throw new
|
|
35400
|
+
throw new CliError("missing_workspace", 'record requires "--workspace <id>" or OPENSTEER_WORKSPACE.');
|
|
34577
35401
|
}
|
|
34578
35402
|
const url = parsed.options.url ?? parsed.rest[0];
|
|
34579
35403
|
if (url === void 0) {
|
|
34580
|
-
throw new
|
|
35404
|
+
throw new CliError(
|
|
35405
|
+
"missing_arguments",
|
|
35406
|
+
'record requires "--url <value>" or a positional URL.',
|
|
35407
|
+
"opensteer record --url <url> --workspace <id>"
|
|
35408
|
+
);
|
|
34581
35409
|
}
|
|
34582
35410
|
const provider = resolveCliProvider(parsed);
|
|
34583
35411
|
assertCloudCliOptionsMatchProvider(parsed, provider.mode);
|
|
34584
35412
|
const engineName = resolveCliEngineName(parsed);
|
|
34585
35413
|
if (engineName !== "playwright") {
|
|
34586
|
-
throw new
|
|
35414
|
+
throw new CliError("config_conflict", "record requires engine=playwright.");
|
|
34587
35415
|
}
|
|
34588
35416
|
const rootDir = process4__default.default.cwd();
|
|
34589
35417
|
const recordBrowser = parsed.options.browser;
|
|
34590
35418
|
if (provider.mode === "cloud") {
|
|
34591
35419
|
if (typeof recordBrowser === "object") {
|
|
34592
|
-
throw new
|
|
35420
|
+
throw new CliError("config_conflict", 'record does not support browser.mode="attach".');
|
|
34593
35421
|
}
|
|
34594
35422
|
const runtimeProvider = buildCliRuntimeProvider(parsed, provider.mode);
|
|
34595
35423
|
const runtimeConfig = resolveOpensteerRuntimeConfig({
|
|
@@ -34609,10 +35437,10 @@ async function handleRecordCommandEntry(parsed) {
|
|
|
34609
35437
|
return;
|
|
34610
35438
|
}
|
|
34611
35439
|
if (parsed.options.launch?.headless === true) {
|
|
34612
|
-
throw new
|
|
35440
|
+
throw new CliError("config_conflict", 'record requires a headed browser. Remove "--headless true".');
|
|
34613
35441
|
}
|
|
34614
35442
|
if (typeof recordBrowser === "object") {
|
|
34615
|
-
throw new
|
|
35443
|
+
throw new CliError("config_conflict", 'record does not support browser.mode="attach".');
|
|
34616
35444
|
}
|
|
34617
35445
|
const launch = {
|
|
34618
35446
|
...parsed.options.launch ?? {},
|
|
@@ -34681,7 +35509,7 @@ function resolveCliBootstrapAction(argv) {
|
|
|
34681
35509
|
}
|
|
34682
35510
|
function buildCliBrowserProfile(parsed) {
|
|
34683
35511
|
if (parsed.options.cloudProfileReuseIfActive === true && parsed.options.cloudProfileId === void 0) {
|
|
34684
|
-
throw new
|
|
35512
|
+
throw new CliError("invalid_option", '"--cloud-profile-reuse-if-active" requires "--cloud-profile-id <id>".');
|
|
34685
35513
|
}
|
|
34686
35514
|
return parsed.options.cloudProfileId === void 0 ? void 0 : {
|
|
34687
35515
|
profileId: parsed.options.cloudProfileId,
|
|
@@ -34742,7 +35570,8 @@ function buildCliRuntimeProvider(parsed, providerMode) {
|
|
|
34742
35570
|
}
|
|
34743
35571
|
function assertCloudCliOptionsMatchProvider(parsed, providerMode) {
|
|
34744
35572
|
if (providerMode !== "cloud" && (parsed.options.cloudBaseUrl !== void 0 || parsed.options.cloudApiKey !== void 0 || parsed.options.cloudAppBaseUrl !== void 0 || parsed.options.cloudProfileId !== void 0 || parsed.options.cloudProfileReuseIfActive === true)) {
|
|
34745
|
-
throw new
|
|
35573
|
+
throw new CliError(
|
|
35574
|
+
"config_conflict",
|
|
34746
35575
|
'Cloud-specific options require provider=cloud. Set "--provider cloud" or OPENSTEER_PROVIDER=cloud.'
|
|
34747
35576
|
);
|
|
34748
35577
|
}
|
|
@@ -34776,17 +35605,7 @@ function printVersion() {
|
|
|
34776
35605
|
`);
|
|
34777
35606
|
}
|
|
34778
35607
|
main().catch((error) => {
|
|
34779
|
-
const payload = error
|
|
34780
|
-
error: {
|
|
34781
|
-
name: error.name,
|
|
34782
|
-
message: error.message
|
|
34783
|
-
}
|
|
34784
|
-
} : {
|
|
34785
|
-
error: {
|
|
34786
|
-
name: "Error",
|
|
34787
|
-
message: String(error)
|
|
34788
|
-
}
|
|
34789
|
-
};
|
|
35608
|
+
const payload = formatCliErrorOutput(error);
|
|
34790
35609
|
process4__default.default.stderr.write(`${JSON.stringify(payload)}
|
|
34791
35610
|
`);
|
|
34792
35611
|
process4__default.default.exitCode = 1;
|