@vforsh/argus 0.2.0 → 0.3.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/.tsbuildinfo +1 -1
- package/dist/argus.js +260 -139
- package/dist/cli/register/evalCommands.d.ts.map +1 -1
- package/dist/cli/register/evalCommands.js +13 -2
- package/dist/cli/register/evalCommands.js.map +1 -1
- package/dist/cli/register/fillCommand.d.ts.map +1 -1
- package/dist/cli/register/fillCommand.js +8 -1
- package/dist/cli/register/fillCommand.js.map +1 -1
- package/dist/commands/domFill.d.ts +1 -0
- package/dist/commands/domFill.d.ts.map +1 -1
- package/dist/commands/domFill.js.map +1 -1
- package/dist/commands/evalPolling.d.ts +13 -23
- package/dist/commands/evalPolling.d.ts.map +1 -1
- package/dist/commands/evalPolling.js +38 -51
- package/dist/commands/evalPolling.js.map +1 -1
- package/dist/commands/extension/doctor.js +9 -0
- package/dist/commands/extension/doctor.js.map +1 -1
- package/dist/commands/extension/targetSelection.d.ts +2 -0
- package/dist/commands/extension/targetSelection.d.ts.map +1 -1
- package/dist/commands/extension/targetSelection.js +2 -2
- package/dist/commands/extension/targetSelection.js.map +1 -1
- package/dist/extension/dist/background/service-worker.js +4 -1
- package/dist/extension/dist/background/service-worker.js.map +2 -2
- package/dist/extension/manifest.json +1 -1
- package/dist/skill/argus/SKILL.md +7 -0
- package/dist/skill/argus/reference/EXTENSION.md +8 -0
- package/package.json +5 -4
package/dist/argus.js
CHANGED
|
@@ -2130,7 +2130,7 @@ var {
|
|
|
2130
2130
|
// package.json
|
|
2131
2131
|
var package_default = {
|
|
2132
2132
|
name: "@vforsh/argus",
|
|
2133
|
-
version: "0.
|
|
2133
|
+
version: "0.3.1",
|
|
2134
2134
|
repository: {
|
|
2135
2135
|
type: "git",
|
|
2136
2136
|
url: "git+https://github.com/vforsh/argus.git",
|
|
@@ -2156,9 +2156,10 @@ var package_default = {
|
|
|
2156
2156
|
access: "public"
|
|
2157
2157
|
},
|
|
2158
2158
|
dependencies: {
|
|
2159
|
-
"@vforsh/argus-
|
|
2160
|
-
"@vforsh/argus-
|
|
2161
|
-
"@vforsh/argus-
|
|
2159
|
+
"@vforsh/argus-client": "^0.3.0",
|
|
2160
|
+
"@vforsh/argus-core": "^0.3.0",
|
|
2161
|
+
"@vforsh/argus-plugin-api": "^0.3.0",
|
|
2162
|
+
"@vforsh/argus-watcher": "^0.3.1",
|
|
2162
2163
|
commander: "14.0.2",
|
|
2163
2164
|
esbuild: "0.25.12",
|
|
2164
2165
|
prettier: "3.7.4"
|
|
@@ -3116,6 +3117,15 @@ var expectNullableWatcherSource = (value, source) => {
|
|
|
3116
3117
|
throw new Error(`Invalid ${source}: expected "cdp", "extension", or null`);
|
|
3117
3118
|
};
|
|
3118
3119
|
// ../argus-core/dist/http/fetch.js
|
|
3120
|
+
class HttpResponseError extends Error {
|
|
3121
|
+
status;
|
|
3122
|
+
isHttpResponseError = true;
|
|
3123
|
+
constructor(message, status) {
|
|
3124
|
+
super(message);
|
|
3125
|
+
this.name = "HttpResponseError";
|
|
3126
|
+
this.status = status;
|
|
3127
|
+
}
|
|
3128
|
+
}
|
|
3119
3129
|
var fetchJson = async (url, options = {}) => {
|
|
3120
3130
|
const controller = new AbortController;
|
|
3121
3131
|
const timeoutMs = options.timeoutMs ?? 5000;
|
|
@@ -3133,7 +3143,7 @@ var fetchJson = async (url, options = {}) => {
|
|
|
3133
3143
|
return await response.json();
|
|
3134
3144
|
}
|
|
3135
3145
|
const errorMessage = await extractErrorMessage(response);
|
|
3136
|
-
throw new
|
|
3146
|
+
throw new HttpResponseError(errorMessage ?? `Request failed (${response.status} ${response.statusText})`, response.status);
|
|
3137
3147
|
}
|
|
3138
3148
|
return await response.json();
|
|
3139
3149
|
} catch (error) {
|
|
@@ -3158,7 +3168,7 @@ var fetchText = async (url, options = {}) => {
|
|
|
3158
3168
|
headers: body ? { "Content-Type": "application/json" } : undefined
|
|
3159
3169
|
});
|
|
3160
3170
|
if (!response.ok) {
|
|
3161
|
-
throw new
|
|
3171
|
+
throw new HttpResponseError(`Request failed (${response.status} ${response.statusText})`, response.status);
|
|
3162
3172
|
}
|
|
3163
3173
|
return await response.text();
|
|
3164
3174
|
} catch (error) {
|
|
@@ -8192,9 +8202,6 @@ var formatError3 = (error) => error instanceof Error ? error.message : String(er
|
|
|
8192
8202
|
// ../argus-watcher/dist/cdp/eval.js
|
|
8193
8203
|
var evaluateExpression = async (session, options) => {
|
|
8194
8204
|
const args = hasEvalArgs(options.args) ? options.args : undefined;
|
|
8195
|
-
if (args) {
|
|
8196
|
-
await installEvalArgs(session, args, options.timeoutMs);
|
|
8197
|
-
}
|
|
8198
8205
|
let scenarioBridge;
|
|
8199
8206
|
try {
|
|
8200
8207
|
if (options.scenario) {
|
|
@@ -8205,12 +8212,23 @@ var evaluateExpression = async (session, options) => {
|
|
|
8205
8212
|
}
|
|
8206
8213
|
const recordResult = await evaluateAndAwaitRecord(session, {
|
|
8207
8214
|
...options,
|
|
8208
|
-
expression: scenarioBridge?.expression ?? options.expression,
|
|
8215
|
+
expression: wrapExpressionWithArgs(scenarioBridge?.expression ?? options.expression, args),
|
|
8209
8216
|
replMode: scenarioBridge ? false : options.replMode
|
|
8210
8217
|
});
|
|
8211
8218
|
if (recordResult.exception)
|
|
8212
8219
|
return recordResult.response;
|
|
8213
8220
|
const record2 = recordResult.record;
|
|
8221
|
+
if (options.jsonValue) {
|
|
8222
|
+
const jsonResult = await materializeJsonValue(session, record2, options);
|
|
8223
|
+
if (!jsonResult.ok)
|
|
8224
|
+
return jsonResult.response;
|
|
8225
|
+
return {
|
|
8226
|
+
ok: true,
|
|
8227
|
+
result: jsonResult.json,
|
|
8228
|
+
type: record2?.type ?? null,
|
|
8229
|
+
exception: null
|
|
8230
|
+
};
|
|
8231
|
+
}
|
|
8214
8232
|
const value = await materializeRemoteObject(session, record2, options);
|
|
8215
8233
|
return {
|
|
8216
8234
|
ok: true,
|
|
@@ -8220,12 +8238,16 @@ var evaluateExpression = async (session, options) => {
|
|
|
8220
8238
|
};
|
|
8221
8239
|
} finally {
|
|
8222
8240
|
await scenarioBridge?.dispose();
|
|
8223
|
-
if (args) {
|
|
8224
|
-
await restoreEvalArgs(session, options.timeoutMs);
|
|
8225
|
-
}
|
|
8226
8241
|
}
|
|
8227
8242
|
};
|
|
8228
8243
|
var hasEvalArgs = (args) => args != null && Object.keys(args).length > 0;
|
|
8244
|
+
var wrapExpressionWithArgs = (expression, args) => {
|
|
8245
|
+
if (!args)
|
|
8246
|
+
return expression;
|
|
8247
|
+
return `{ const args = Object.freeze(${JSON.stringify(args)});
|
|
8248
|
+
${expression}
|
|
8249
|
+
}`;
|
|
8250
|
+
};
|
|
8229
8251
|
var evaluateAndAwaitRecord = async (session, options) => {
|
|
8230
8252
|
const payload = await evaluateRawExpression(session, options);
|
|
8231
8253
|
if (payload.exceptionDetails) {
|
|
@@ -8250,42 +8272,6 @@ var formatExceptionResponse = (payload) => ({
|
|
|
8250
8272
|
details: payload.exceptionDetails?.exception ?? null
|
|
8251
8273
|
}
|
|
8252
8274
|
});
|
|
8253
|
-
var EVAL_ARGS_STATE_KEY = "__argusEvalArgsPreviousDescriptor__";
|
|
8254
|
-
var installEvalArgs = async (session, args, timeoutMs) => {
|
|
8255
|
-
const payload = JSON.stringify(args);
|
|
8256
|
-
await sendInternalEval(session, `(() => {
|
|
8257
|
-
const previous = Object.getOwnPropertyDescriptor(globalThis, 'args');
|
|
8258
|
-
Object.defineProperty(globalThis, ${JSON.stringify(EVAL_ARGS_STATE_KEY)}, { value: previous, configurable: true });
|
|
8259
|
-
Object.defineProperty(globalThis, 'args', { value: Object.freeze(${payload}), configurable: true });
|
|
8260
|
-
})()`, timeoutMs);
|
|
8261
|
-
};
|
|
8262
|
-
var restoreEvalArgs = async (session, timeoutMs) => {
|
|
8263
|
-
await sendInternalEval(session, `(() => {
|
|
8264
|
-
const stateKey = ${JSON.stringify(EVAL_ARGS_STATE_KEY)};
|
|
8265
|
-
const previous = Object.getOwnPropertyDescriptor(globalThis, stateKey)?.value;
|
|
8266
|
-
delete globalThis[stateKey];
|
|
8267
|
-
delete globalThis.args;
|
|
8268
|
-
if (previous) Object.defineProperty(globalThis, 'args', previous);
|
|
8269
|
-
})()`, timeoutMs);
|
|
8270
|
-
};
|
|
8271
|
-
var sendInternalEval = async (session, expression, timeoutMs) => {
|
|
8272
|
-
const payload = await session.sendAndWait("Runtime.evaluate", {
|
|
8273
|
-
expression,
|
|
8274
|
-
replMode: false,
|
|
8275
|
-
awaitPromise: true,
|
|
8276
|
-
returnByValue: true
|
|
8277
|
-
}, { timeoutMs });
|
|
8278
|
-
if (payload.exceptionDetails) {
|
|
8279
|
-
throw new Error(formatInternalEvalError(payload.exceptionDetails));
|
|
8280
|
-
}
|
|
8281
|
-
};
|
|
8282
|
-
var formatInternalEvalError = (exceptionDetails) => {
|
|
8283
|
-
const exception = exceptionDetails.exception;
|
|
8284
|
-
if (exception != null && typeof exception === "object" && "description" in exception && typeof exception.description === "string") {
|
|
8285
|
-
return exception.description;
|
|
8286
|
-
}
|
|
8287
|
-
return exceptionDetails.text ?? "Failed to prepare eval args";
|
|
8288
|
-
};
|
|
8289
8275
|
var evaluateRawExpression = async (session, options) => await session.sendAndWait("Runtime.evaluate", {
|
|
8290
8276
|
expression: options.expression,
|
|
8291
8277
|
replMode: options.replMode ?? true,
|
|
@@ -8296,6 +8282,25 @@ var awaitPromiseResult = async (session, promiseObjectId, timeoutMs) => await se
|
|
|
8296
8282
|
promiseObjectId,
|
|
8297
8283
|
returnByValue: false
|
|
8298
8284
|
}, { timeoutMs });
|
|
8285
|
+
var EMPTY_JSON_ENVELOPE = "{}";
|
|
8286
|
+
var materializeJsonValue = async (session, record2, options) => {
|
|
8287
|
+
if (!record2) {
|
|
8288
|
+
return { ok: true, json: EMPTY_JSON_ENVELOPE };
|
|
8289
|
+
}
|
|
8290
|
+
if (!record2.objectId) {
|
|
8291
|
+
return { ok: true, json: JSON.stringify({ v: record2.value }) ?? EMPTY_JSON_ENVELOPE };
|
|
8292
|
+
}
|
|
8293
|
+
const payload = await session.sendAndWait("Runtime.callFunctionOn", {
|
|
8294
|
+
objectId: record2.objectId,
|
|
8295
|
+
functionDeclaration: "function () { return JSON.stringify({ v: this }) }",
|
|
8296
|
+
returnByValue: true
|
|
8297
|
+
}, { timeoutMs: options.timeoutMs });
|
|
8298
|
+
if (payload.exceptionDetails) {
|
|
8299
|
+
return { ok: false, response: formatExceptionResponse(payload) };
|
|
8300
|
+
}
|
|
8301
|
+
const json = payload.result?.value;
|
|
8302
|
+
return { ok: true, json: typeof json === "string" ? json : EMPTY_JSON_ENVELOPE };
|
|
8303
|
+
};
|
|
8299
8304
|
var materializeRemoteObject = async (session, record2, options) => {
|
|
8300
8305
|
if (!record2) {
|
|
8301
8306
|
return null;
|
|
@@ -8339,6 +8344,7 @@ var route18 = defineJsonRoute({
|
|
|
8339
8344
|
awaitPromise: normalizeBoolean(payload.awaitPromise, true),
|
|
8340
8345
|
replMode: normalizeBoolean(payload.replMode, true),
|
|
8341
8346
|
returnByValue: normalizeBoolean(payload.returnByValue, true),
|
|
8347
|
+
jsonValue: normalizeBoolean(payload.jsonValue, false),
|
|
8342
8348
|
timeoutMs: normalizeTimeout(payload.timeoutMs),
|
|
8343
8349
|
scenario: normalizeBoolean(payload.scenario, false),
|
|
8344
8350
|
scenarioServices: {
|
|
@@ -8539,7 +8545,7 @@ var filterNodesByText = async (session, nodeIds, text) => {
|
|
|
8539
8545
|
|
|
8540
8546
|
// ../argus-watcher/dist/cdp/dom/selector.js
|
|
8541
8547
|
var getDomRootId = async (session) => {
|
|
8542
|
-
const targetContext = session.getTargetContext?.();
|
|
8548
|
+
const targetContext = session.getReadyTargetContext ? await session.getReadyTargetContext() : session.getTargetContext?.();
|
|
8543
8549
|
if (targetContext?.kind === "frame") {
|
|
8544
8550
|
return getFrameDomRootId(session, targetContext);
|
|
8545
8551
|
}
|
|
@@ -8624,6 +8630,18 @@ var describeNodeByBackendId = async (session, backendNodeId) => {
|
|
|
8624
8630
|
});
|
|
8625
8631
|
return described.node ?? null;
|
|
8626
8632
|
};
|
|
8633
|
+
var resolveNodeIdByBackendId = async (session, backendNodeId) => {
|
|
8634
|
+
const describedNode = await describeNodeByBackendId(session, backendNodeId);
|
|
8635
|
+
if (describedNode?.nodeId) {
|
|
8636
|
+
return describedNode.nodeId;
|
|
8637
|
+
}
|
|
8638
|
+
await getDomRootId(session);
|
|
8639
|
+
const pushed = await session.sendAndWait("DOM.pushNodesByBackendIdsToFrontend", {
|
|
8640
|
+
backendNodeIds: [backendNodeId]
|
|
8641
|
+
});
|
|
8642
|
+
const nodeId = pushed.nodeIds?.[0];
|
|
8643
|
+
return typeof nodeId === "number" && nodeId > 0 ? nodeId : null;
|
|
8644
|
+
};
|
|
8627
8645
|
var toDomNodeDescriptor = (handle) => {
|
|
8628
8646
|
if (handle.nodeId != null) {
|
|
8629
8647
|
return { nodeId: handle.nodeId };
|
|
@@ -9024,7 +9042,39 @@ var locateByLabel = async (session, elementRefs, request) => {
|
|
|
9024
9042
|
}
|
|
9025
9043
|
return matchesText(element.name, request.label, request.exact ?? false);
|
|
9026
9044
|
});
|
|
9027
|
-
return buildLocateResponse(session, request.all ?? false, matches);
|
|
9045
|
+
return buildLocateResponse(session, request.all ?? false, await removeCompositeLabelWrappers(session, matches));
|
|
9046
|
+
};
|
|
9047
|
+
var NATIVE_LABELABLE_TAGS = new Set(["button", "input", "select", "textarea"]);
|
|
9048
|
+
var removeCompositeLabelWrappers = async (session, matches) => {
|
|
9049
|
+
if (matches.length < 2)
|
|
9050
|
+
return matches;
|
|
9051
|
+
const candidates = await Promise.all(matches.map(async (match) => {
|
|
9052
|
+
const [node, nodeId] = await Promise.all([
|
|
9053
|
+
describeNodeByBackendId(session, match.backendNodeId),
|
|
9054
|
+
resolveNodeIdByBackendId(session, match.backendNodeId)
|
|
9055
|
+
]);
|
|
9056
|
+
const tag = node ? (node.localName ?? node.nodeName).toLowerCase() : "";
|
|
9057
|
+
return { match, nodeId, native: NATIVE_LABELABLE_TAGS.has(tag) };
|
|
9058
|
+
}));
|
|
9059
|
+
const nativeCandidates = candidates.filter((candidate) => candidate.native && candidate.nodeId != null);
|
|
9060
|
+
if (nativeCandidates.length === 0)
|
|
9061
|
+
return matches;
|
|
9062
|
+
const kept = [];
|
|
9063
|
+
for (const candidate of candidates) {
|
|
9064
|
+
if (candidate.native || candidate.nodeId == null) {
|
|
9065
|
+
kept.push(candidate.match);
|
|
9066
|
+
continue;
|
|
9067
|
+
}
|
|
9068
|
+
const descendants = await session.sendAndWait("DOM.querySelectorAll", {
|
|
9069
|
+
nodeId: candidate.nodeId,
|
|
9070
|
+
selector: "button,input,select,textarea"
|
|
9071
|
+
});
|
|
9072
|
+
const descendantIds = new Set(descendants.nodeIds ?? []);
|
|
9073
|
+
const wrapsMatchedNative = nativeCandidates.some((native) => native.nodeId != null && descendantIds.has(native.nodeId) && normalizeText(native.match.role) === normalizeText(candidate.match.role) && normalizeText(native.match.name) === normalizeText(candidate.match.name));
|
|
9074
|
+
if (!wrapsMatchedNative)
|
|
9075
|
+
kept.push(candidate.match);
|
|
9076
|
+
}
|
|
9077
|
+
return kept;
|
|
9028
9078
|
};
|
|
9029
9079
|
var buildLocateResponse = async (session, all, matches) => {
|
|
9030
9080
|
const selected = all ? matches : matches.slice(0, 1);
|
|
@@ -9535,8 +9585,8 @@ var setFileOnResolvedNodes = async (session, nodeIds, files) => {
|
|
|
9535
9585
|
// ../argus-watcher/dist/cdp/dom/fill.js
|
|
9536
9586
|
var FILL_FUNCTION = `function(value) {
|
|
9537
9587
|
var el = this;
|
|
9588
|
+
el.focus();
|
|
9538
9589
|
if (el.isContentEditable) {
|
|
9539
|
-
el.focus();
|
|
9540
9590
|
el.textContent = value;
|
|
9541
9591
|
el.dispatchEvent(new Event('input', { bubbles: true }));
|
|
9542
9592
|
el.dispatchEvent(new Event('change', { bubbles: true }));
|
|
@@ -13842,7 +13892,7 @@ import fs7 from "node:fs/promises";
|
|
|
13842
13892
|
// ../argus-watcher/dist/cdp/visualCapture.js
|
|
13843
13893
|
var createVisualCapturePlan = async (session, pageSession, request) => {
|
|
13844
13894
|
const subject = resolveVisualCaptureSubject(request);
|
|
13845
|
-
const targetContext = session.getTargetContext?.();
|
|
13895
|
+
const targetContext = session.getReadyTargetContext ? await session.getReadyTargetContext() : session.getTargetContext?.();
|
|
13846
13896
|
if (targetContext?.kind === "frame" && pageSession) {
|
|
13847
13897
|
return createFrameCapturePlan({
|
|
13848
13898
|
frameSession: session,
|
|
@@ -16244,7 +16294,6 @@ var createEmptyFrameState = () => ({
|
|
|
16244
16294
|
topFrameId: null,
|
|
16245
16295
|
requestedFrameId: null,
|
|
16246
16296
|
requestedFrameHint: null,
|
|
16247
|
-
requestedFrameDetached: false,
|
|
16248
16297
|
activeFrameId: null,
|
|
16249
16298
|
activeAttachedAt: null,
|
|
16250
16299
|
frames: new Map,
|
|
@@ -16373,7 +16422,7 @@ var resolveRequestedTarget = (state2) => {
|
|
|
16373
16422
|
if (nextFrameId) {
|
|
16374
16423
|
return { kind: "frame", frameId: nextFrameId };
|
|
16375
16424
|
}
|
|
16376
|
-
return
|
|
16425
|
+
return { kind: "pending" };
|
|
16377
16426
|
};
|
|
16378
16427
|
var resolveSelectedFrameCommandState = (state2) => {
|
|
16379
16428
|
if (state2.requestedFrameId == null) {
|
|
@@ -16414,7 +16463,7 @@ var buildFrameTargetContext = (state2, frameId) => ({
|
|
|
16414
16463
|
var findSingleMatchingFrameId = (state2, predicate) => {
|
|
16415
16464
|
let matchId = null;
|
|
16416
16465
|
for (const frame of state2.frames.values()) {
|
|
16417
|
-
if (!predicate(frame)) {
|
|
16466
|
+
if (frame.frameId === state2.topFrameId || !predicate(frame)) {
|
|
16418
16467
|
continue;
|
|
16419
16468
|
}
|
|
16420
16469
|
if (matchId) {
|
|
@@ -16504,7 +16553,8 @@ var createDelegatingSession = (options) => {
|
|
|
16504
16553
|
subscriptions.delete(subscription);
|
|
16505
16554
|
};
|
|
16506
16555
|
},
|
|
16507
|
-
getTargetContext: options.getTargetContext
|
|
16556
|
+
getTargetContext: options.getTargetContext,
|
|
16557
|
+
getReadyTargetContext: options.getReadyTargetContext
|
|
16508
16558
|
};
|
|
16509
16559
|
controller.rebind();
|
|
16510
16560
|
return { session, controller };
|
|
@@ -17034,31 +17084,54 @@ var seedExtensionFrameState = (session, state2) => {
|
|
|
17034
17084
|
return state2;
|
|
17035
17085
|
};
|
|
17036
17086
|
var getSelectedExtensionTarget = (session, state2) => {
|
|
17037
|
-
|
|
17087
|
+
const frameId = state2?.requestedFrameId ?? state2?.activeFrameId;
|
|
17088
|
+
if (!state2 || !frameId) {
|
|
17038
17089
|
return buildPageTarget(session, { attached: true });
|
|
17039
17090
|
}
|
|
17040
|
-
const frame = state2.frames.get(
|
|
17091
|
+
const frame = state2.frames.get(frameId);
|
|
17041
17092
|
if (frame) {
|
|
17042
17093
|
return frameToTarget(session.tabId, frame, { attached: true, faviconUrl: session.faviconUrl, topFrameId: state2.topFrameId });
|
|
17043
17094
|
}
|
|
17044
17095
|
return buildSelectedIframeFallbackTarget(session, state2);
|
|
17045
17096
|
};
|
|
17046
17097
|
var setRequestedTargetSelection = (state2, frameId) => {
|
|
17098
|
+
if (state2.requestedFrameId !== frameId) {
|
|
17099
|
+
state2.activeAttachedAt = null;
|
|
17100
|
+
}
|
|
17101
|
+
const previousHint = state2.requestedFrameId === frameId ? state2.requestedFrameHint : null;
|
|
17047
17102
|
state2.requestedFrameId = frameId;
|
|
17048
|
-
state2.requestedFrameHint = frameId ? createRequestedFrameHint(state2.frames.get(frameId)) : null;
|
|
17049
|
-
|
|
17103
|
+
state2.requestedFrameHint = frameId ? createRequestedFrameHint(state2.frames.get(frameId)) ?? previousHint : null;
|
|
17104
|
+
};
|
|
17105
|
+
var listExtensionTargets = (session, state2) => {
|
|
17106
|
+
if (!state2) {
|
|
17107
|
+
return [buildPageTarget(session, { attached: true })];
|
|
17108
|
+
}
|
|
17109
|
+
const selected = getSelectedExtensionTarget(session, state2);
|
|
17110
|
+
selected.targetReady = isSelectedTargetReady(state2);
|
|
17111
|
+
const targets = [buildPageTarget(session, { attached: false }), ...buildFrameTargets(state2, session.tabId, null, session.faviconUrl)];
|
|
17112
|
+
const selectedIndex = targets.findIndex((target) => target.id === selected.id);
|
|
17113
|
+
if (selectedIndex < 0) {
|
|
17114
|
+
targets.push(selected);
|
|
17115
|
+
} else {
|
|
17116
|
+
targets[selectedIndex] = selected;
|
|
17117
|
+
}
|
|
17118
|
+
return targets;
|
|
17050
17119
|
};
|
|
17051
17120
|
var reconcileExtensionTargetSelection = (session, state2, onTargetChanged) => {
|
|
17052
17121
|
const resolution = resolveRequestedTarget(state2);
|
|
17053
17122
|
if (resolution.kind === "page") {
|
|
17054
|
-
state2.requestedFrameDetached = false;
|
|
17055
17123
|
return activatePageTarget(state2, onTargetChanged);
|
|
17056
17124
|
}
|
|
17057
17125
|
if (resolution.kind === "pending") {
|
|
17058
|
-
|
|
17126
|
+
if (state2.activeFrameId == null && state2.activeAttachedAt != null) {
|
|
17127
|
+
return false;
|
|
17128
|
+
}
|
|
17129
|
+
state2.activeFrameId = null;
|
|
17130
|
+
state2.activeAttachedAt = Date.now();
|
|
17131
|
+
onTargetChanged();
|
|
17132
|
+
return true;
|
|
17059
17133
|
}
|
|
17060
17134
|
syncRequestedFrameSelection(state2, resolution.frameId);
|
|
17061
|
-
state2.requestedFrameDetached = false;
|
|
17062
17135
|
if (state2.activeFrameId === resolution.frameId) {
|
|
17063
17136
|
return false;
|
|
17064
17137
|
}
|
|
@@ -17075,7 +17148,6 @@ var removeExtensionFrame = (state2, frameId) => {
|
|
|
17075
17148
|
removeExtensionFrame(state2, childId);
|
|
17076
17149
|
}
|
|
17077
17150
|
if (state2.activeFrameId === frameId) {
|
|
17078
|
-
state2.requestedFrameDetached = state2.requestedFrameId === frameId;
|
|
17079
17151
|
state2.activeFrameId = null;
|
|
17080
17152
|
state2.activeAttachedAt = null;
|
|
17081
17153
|
}
|
|
@@ -17146,7 +17218,7 @@ var syncRequestedFrameSelection = (state2, frameId) => {
|
|
|
17146
17218
|
};
|
|
17147
17219
|
var buildSelectedIframeFallbackTarget = (session, state2) => {
|
|
17148
17220
|
const hint = state2.requestedFrameHint;
|
|
17149
|
-
const frameId = state2.activeFrameId;
|
|
17221
|
+
const frameId = state2.requestedFrameId ?? state2.activeFrameId;
|
|
17150
17222
|
if (!frameId) {
|
|
17151
17223
|
return buildPageTarget(session, { attached: true });
|
|
17152
17224
|
}
|
|
@@ -17157,7 +17229,8 @@ var buildSelectedIframeFallbackTarget = (session, state2) => {
|
|
|
17157
17229
|
type: "iframe",
|
|
17158
17230
|
parentId: formatPageTargetId(session.tabId),
|
|
17159
17231
|
faviconUrl: session.faviconUrl,
|
|
17160
|
-
attached: true
|
|
17232
|
+
attached: true,
|
|
17233
|
+
targetReady: false
|
|
17161
17234
|
};
|
|
17162
17235
|
};
|
|
17163
17236
|
|
|
@@ -17223,6 +17296,10 @@ var createExtensionSource = (options) => {
|
|
|
17223
17296
|
getCurrentSession: () => currentSession,
|
|
17224
17297
|
requireCurrentSession: getCurrentExtensionSession,
|
|
17225
17298
|
getTargetContext: () => getCurrentTargetContext() ?? { kind: "page" },
|
|
17299
|
+
getReadyTargetContext: async () => {
|
|
17300
|
+
const context = getCurrentTargetContext() ?? { kind: "page" };
|
|
17301
|
+
return context.kind === "frame" ? targetRecovery.waitForSelectedFrameCommandTarget() : context;
|
|
17302
|
+
},
|
|
17226
17303
|
prepareCommand: async ({ method, params, targetContext }) => {
|
|
17227
17304
|
if (targetContext.kind !== "frame") {
|
|
17228
17305
|
return;
|
|
@@ -17268,16 +17345,7 @@ var createExtensionSource = (options) => {
|
|
|
17268
17345
|
if (!session) {
|
|
17269
17346
|
return [];
|
|
17270
17347
|
}
|
|
17271
|
-
|
|
17272
|
-
if (!state2 || state2.frames.size === 0) {
|
|
17273
|
-
return [buildPageTarget(session, { attached: true })];
|
|
17274
|
-
}
|
|
17275
|
-
const activeFrameId = state2.activeFrameId;
|
|
17276
|
-
const targets = [buildPageTarget(session, { attached: activeFrameId == null })];
|
|
17277
|
-
for (const frame of buildFrameTargets(state2, session.tabId, activeFrameId, session.faviconUrl)) {
|
|
17278
|
-
targets.push(frame);
|
|
17279
|
-
}
|
|
17280
|
-
return targets;
|
|
17348
|
+
return listExtensionTargets(session, frameStateByTabId.get(session.tabId));
|
|
17281
17349
|
};
|
|
17282
17350
|
const attachTarget = async (targetId) => {
|
|
17283
17351
|
const target = parseExtensionTargetId(targetId);
|
|
@@ -17415,10 +17483,11 @@ var createExtensionSource = (options) => {
|
|
|
17415
17483
|
return null;
|
|
17416
17484
|
}
|
|
17417
17485
|
const state2 = frameStateByTabId.get(session.tabId);
|
|
17418
|
-
|
|
17486
|
+
const frameId = state2?.requestedFrameId ?? state2?.activeFrameId;
|
|
17487
|
+
if (!state2 || !frameId) {
|
|
17419
17488
|
return { kind: "page" };
|
|
17420
17489
|
}
|
|
17421
|
-
return buildFrameTargetContext(state2,
|
|
17490
|
+
return buildFrameTargetContext(state2, frameId);
|
|
17422
17491
|
}
|
|
17423
17492
|
function getOrCreateFrameState(tabId) {
|
|
17424
17493
|
const existing = frameStateByTabId.get(tabId);
|
|
@@ -21159,7 +21228,7 @@ var prepareEvalExpression = async (inline, options, output) => {
|
|
|
21159
21228
|
return null;
|
|
21160
21229
|
}
|
|
21161
21230
|
return {
|
|
21162
|
-
expression: wrapForIframeEval(
|
|
21231
|
+
expression: wrapForIframeEval(wrapExpressionWithArgs2(resolved.expression, args), {
|
|
21163
21232
|
selector: options.iframe,
|
|
21164
21233
|
namespace: options.iframeNamespace ?? "argus",
|
|
21165
21234
|
timeoutMs: iframeTimeoutMs.value ?? 5000
|
|
@@ -21331,16 +21400,13 @@ var parseCount = (value) => {
|
|
|
21331
21400
|
}
|
|
21332
21401
|
return { value: parsed };
|
|
21333
21402
|
};
|
|
21334
|
-
var
|
|
21403
|
+
var wrapExpressionWithArgs2 = (source, args) => {
|
|
21335
21404
|
if (!hasEvalArgs2(args)) {
|
|
21336
21405
|
return source;
|
|
21337
21406
|
}
|
|
21338
21407
|
return `const args = Object.freeze(${JSON.stringify(args)});
|
|
21339
21408
|
${source}`;
|
|
21340
21409
|
};
|
|
21341
|
-
var sleep5 = async (durationMs) => {
|
|
21342
|
-
await new Promise((resolve2) => setTimeout(resolve2, durationMs));
|
|
21343
|
-
};
|
|
21344
21410
|
var formatException = (response) => {
|
|
21345
21411
|
if (!response.exception) {
|
|
21346
21412
|
return "";
|
|
@@ -24167,60 +24233,89 @@ var authCommands = [
|
|
|
24167
24233
|
]
|
|
24168
24234
|
}
|
|
24169
24235
|
];
|
|
24170
|
-
|
|
24171
|
-
// dist/commands/evalPolling.js
|
|
24236
|
+
// ../argus-client/dist/eval/pollEval.js
|
|
24172
24237
|
var pollEval = async (input) => {
|
|
24173
|
-
|
|
24174
|
-
|
|
24175
|
-
|
|
24176
|
-
|
|
24177
|
-
|
|
24178
|
-
|
|
24179
|
-
|
|
24180
|
-
const startTime = Date.now();
|
|
24181
|
-
let iteration = 0;
|
|
24182
|
-
while (running) {
|
|
24183
|
-
if (input.totalTimeoutMs != null) {
|
|
24184
|
-
const elapsed = Date.now() - startTime;
|
|
24185
|
-
if (elapsed >= input.totalTimeoutMs) {
|
|
24186
|
-
return { kind: "timeout", elapsedMs: elapsed };
|
|
24187
|
-
}
|
|
24188
|
-
}
|
|
24189
|
-
iteration += 1;
|
|
24190
|
-
const result = await evalWithRetries({
|
|
24191
|
-
watcher: input.watcher,
|
|
24192
|
-
expression: input.expression,
|
|
24193
|
-
args: input.args,
|
|
24194
|
-
awaitPromise: input.awaitPromise,
|
|
24195
|
-
returnByValue: input.returnByValue,
|
|
24196
|
-
timeoutMs: input.timeoutMs,
|
|
24197
|
-
failOnException: input.failOnException,
|
|
24198
|
-
retryCount: input.retryCount,
|
|
24199
|
-
scenario: input.scenario
|
|
24200
|
-
});
|
|
24201
|
-
if (!result.ok) {
|
|
24202
|
-
return { kind: "eval-error", failure: result };
|
|
24238
|
+
const startTime = Date.now();
|
|
24239
|
+
let iteration = 0;
|
|
24240
|
+
while (!input.signal?.aborted) {
|
|
24241
|
+
if (input.totalTimeoutMs != null) {
|
|
24242
|
+
const elapsedMs = Date.now() - startTime;
|
|
24243
|
+
if (elapsedMs >= input.totalTimeoutMs) {
|
|
24244
|
+
return { kind: "timeout", elapsedMs };
|
|
24203
24245
|
}
|
|
24204
|
-
|
|
24205
|
-
|
|
24206
|
-
|
|
24207
|
-
|
|
24208
|
-
|
|
24209
|
-
|
|
24210
|
-
|
|
24211
|
-
|
|
24212
|
-
|
|
24213
|
-
|
|
24246
|
+
}
|
|
24247
|
+
iteration += 1;
|
|
24248
|
+
const result = await input.runEval(iteration);
|
|
24249
|
+
if (!result.ok) {
|
|
24250
|
+
return { kind: "eval-error", failure: result.failure };
|
|
24251
|
+
}
|
|
24252
|
+
const context = { response: result.response, iteration, attempt: result.attempt };
|
|
24253
|
+
await input.onResult?.(result.response, context);
|
|
24254
|
+
const decision = input.shouldStop?.(context);
|
|
24255
|
+
if (decision) {
|
|
24256
|
+
if (!decision.ok) {
|
|
24257
|
+
return { kind: "condition-error", error: decision.error };
|
|
24214
24258
|
}
|
|
24215
|
-
if (
|
|
24216
|
-
return { kind: "
|
|
24259
|
+
if (decision.matched) {
|
|
24260
|
+
return { kind: "matched", response: result.response, iteration, attempt: result.attempt };
|
|
24217
24261
|
}
|
|
24218
|
-
await sleep5(input.intervalMs);
|
|
24219
24262
|
}
|
|
24220
|
-
|
|
24263
|
+
if (input.count != null && iteration >= input.count) {
|
|
24264
|
+
return { kind: "exhausted", iterations: iteration };
|
|
24265
|
+
}
|
|
24266
|
+
await sleep5(input.intervalMs, input.signal);
|
|
24267
|
+
}
|
|
24268
|
+
return { kind: "interrupted" };
|
|
24269
|
+
};
|
|
24270
|
+
var sleep5 = async (durationMs, signal) => {
|
|
24271
|
+
if (signal?.aborted) {
|
|
24272
|
+
return;
|
|
24273
|
+
}
|
|
24274
|
+
await new Promise((resolve2) => {
|
|
24275
|
+
const finish = () => {
|
|
24276
|
+
clearTimeout(timer);
|
|
24277
|
+
signal?.removeEventListener("abort", finish);
|
|
24278
|
+
resolve2();
|
|
24279
|
+
};
|
|
24280
|
+
const timer = setTimeout(finish, durationMs);
|
|
24281
|
+
signal?.addEventListener("abort", finish, { once: true });
|
|
24282
|
+
});
|
|
24283
|
+
};
|
|
24284
|
+
// dist/commands/evalPolling.js
|
|
24285
|
+
var pollEval2 = async (input) => {
|
|
24286
|
+
const controller = new AbortController;
|
|
24287
|
+
const abort = () => controller.abort();
|
|
24288
|
+
process.on("SIGINT", abort);
|
|
24289
|
+
process.on("SIGTERM", abort);
|
|
24290
|
+
try {
|
|
24291
|
+
return await pollEval({
|
|
24292
|
+
intervalMs: input.intervalMs,
|
|
24293
|
+
count: input.count,
|
|
24294
|
+
totalTimeoutMs: input.totalTimeoutMs,
|
|
24295
|
+
signal: controller.signal,
|
|
24296
|
+
shouldStop: input.shouldStop,
|
|
24297
|
+
onResult: input.onResult,
|
|
24298
|
+
runEval: async () => {
|
|
24299
|
+
const result = await evalWithRetries({
|
|
24300
|
+
watcher: input.watcher,
|
|
24301
|
+
expression: input.expression,
|
|
24302
|
+
args: input.args,
|
|
24303
|
+
awaitPromise: input.awaitPromise,
|
|
24304
|
+
returnByValue: input.returnByValue,
|
|
24305
|
+
timeoutMs: input.timeoutMs,
|
|
24306
|
+
failOnException: input.failOnException,
|
|
24307
|
+
retryCount: input.retryCount,
|
|
24308
|
+
scenario: input.scenario
|
|
24309
|
+
});
|
|
24310
|
+
if (!result.ok) {
|
|
24311
|
+
return { ok: false, failure: result, attempt: result.attempt };
|
|
24312
|
+
}
|
|
24313
|
+
return { ok: true, response: result.response, attempt: result.attempt };
|
|
24314
|
+
}
|
|
24315
|
+
});
|
|
24221
24316
|
} finally {
|
|
24222
|
-
process.off("SIGINT",
|
|
24223
|
-
process.off("SIGTERM",
|
|
24317
|
+
process.off("SIGINT", abort);
|
|
24318
|
+
process.off("SIGTERM", abort);
|
|
24224
24319
|
}
|
|
24225
24320
|
};
|
|
24226
24321
|
|
|
@@ -24300,7 +24395,7 @@ var runEval = async (id, rawExpression, options) => {
|
|
|
24300
24395
|
await emitter.emitSuccess(singleResult.response, false);
|
|
24301
24396
|
return;
|
|
24302
24397
|
}
|
|
24303
|
-
const pollResult = await
|
|
24398
|
+
const pollResult = await pollEval2({
|
|
24304
24399
|
watcher,
|
|
24305
24400
|
expression: prepared.expression,
|
|
24306
24401
|
args: prepared.args,
|
|
@@ -24414,7 +24509,7 @@ var runEvalUntil = async (id, rawExpression, options) => {
|
|
|
24414
24509
|
if (!resolved)
|
|
24415
24510
|
return;
|
|
24416
24511
|
const { watcher } = resolved;
|
|
24417
|
-
const pollResult = await
|
|
24512
|
+
const pollResult = await pollEval2({
|
|
24418
24513
|
watcher,
|
|
24419
24514
|
expression: prepared.expression,
|
|
24420
24515
|
args: prepared.args,
|
|
@@ -24537,6 +24632,7 @@ var sharedEvalHeadOptions = (timeoutDescription) => [
|
|
|
24537
24632
|
{ flags: "-q, --silent", description: "Suppress success output; only emit output on error" }
|
|
24538
24633
|
];
|
|
24539
24634
|
var sharedEvalTailOptions = [
|
|
24635
|
+
{ flags: "--expression <js>", description: "Expression to evaluate (alternative to the positional expression)" },
|
|
24540
24636
|
{ flags: "-f, --file <path>", description: "Read expression from a file" },
|
|
24541
24637
|
{ flags: "--bundle", description: "Bundle --file and its resolved imports into one script before eval" },
|
|
24542
24638
|
{ flags: "--no-bundle", description: "Read --file as-is (skip bundling and auto-bundle)" },
|
|
@@ -24589,7 +24685,12 @@ var evalCommands = [
|
|
|
24589
24685
|
'argus eval app "document.title" --iframe "iframe" --iframe-timeout 10000'
|
|
24590
24686
|
],
|
|
24591
24687
|
action: async (id, expression, options) => {
|
|
24592
|
-
|
|
24688
|
+
if (expression != null && options.expression != null) {
|
|
24689
|
+
console.error("Provide either a positional expression or --expression, not both.");
|
|
24690
|
+
process.exitCode = 2;
|
|
24691
|
+
return;
|
|
24692
|
+
}
|
|
24693
|
+
await runEval(id, expression ?? options.expression, {
|
|
24593
24694
|
json: options.json,
|
|
24594
24695
|
await: options.await,
|
|
24595
24696
|
timeout: options.timeout,
|
|
@@ -24667,7 +24768,12 @@ var evalCommands = [
|
|
|
24667
24768
|
"argus wait app --file ./ready.js --args ./args.json --out ./ready.json"
|
|
24668
24769
|
],
|
|
24669
24770
|
action: async (id, expression, options) => {
|
|
24670
|
-
|
|
24771
|
+
if (expression != null && options.expression != null) {
|
|
24772
|
+
console.error("Provide either a positional expression or --expression, not both.");
|
|
24773
|
+
process.exitCode = 2;
|
|
24774
|
+
return;
|
|
24775
|
+
}
|
|
24776
|
+
await runEvalUntil(id, expression ?? options.expression, {
|
|
24671
24777
|
json: options.json,
|
|
24672
24778
|
await: options.await,
|
|
24673
24779
|
timeout: options.timeout,
|
|
@@ -48325,6 +48431,7 @@ var fillCommand = {
|
|
|
48325
48431
|
{ flags: "--testid <id>", description: `Shorthand for --selector "[data-testid='<id>']"` },
|
|
48326
48432
|
{ flags: "--ref <elementRef>", description: "Stable element ref from snapshot/locate output" },
|
|
48327
48433
|
{ flags: "--name <attr>", description: 'Shorthand for --selector "[name=<attr>]"' },
|
|
48434
|
+
{ flags: "--value <text>", description: "Value to fill (alternative to the positional value)" },
|
|
48328
48435
|
{ flags: "--value-file <path>", description: "Read value from a file" },
|
|
48329
48436
|
{ flags: "--value-stdin", description: 'Read value from stdin (also triggered by "-" as value arg)' },
|
|
48330
48437
|
{ flags: "--all", description: "Allow multiple matches (default: error if >1 match)" },
|
|
@@ -48337,6 +48444,7 @@ var fillCommand = {
|
|
|
48337
48444
|
'argus fill app --testid "username" "Bob"',
|
|
48338
48445
|
'argus fill app --ref e7 "Bob"',
|
|
48339
48446
|
'argus fill app --name "title" "Hello"',
|
|
48447
|
+
'argus fill app --selector "#username" --value "Bob"',
|
|
48340
48448
|
'argus fill app --selector "textarea" "New content"',
|
|
48341
48449
|
'argus fill app --selector "input[type=text]" --all "reset"',
|
|
48342
48450
|
'argus fill app --selector "#desc" --value-file ./description.txt',
|
|
@@ -48344,6 +48452,11 @@ var fillCommand = {
|
|
|
48344
48452
|
'argus fill app --selector "#input" - < value.txt'
|
|
48345
48453
|
],
|
|
48346
48454
|
action: async (id, value, options) => {
|
|
48455
|
+
if (value != null && options.value != null) {
|
|
48456
|
+
console.error("Provide either a positional value or --value, not both.");
|
|
48457
|
+
process.exitCode = 2;
|
|
48458
|
+
return;
|
|
48459
|
+
}
|
|
48347
48460
|
if (options.name && (options.testid || options.ref)) {
|
|
48348
48461
|
console.error("Cannot use --name with --testid or --ref.");
|
|
48349
48462
|
process.exitCode = 2;
|
|
@@ -48351,7 +48464,7 @@ var fillCommand = {
|
|
|
48351
48464
|
}
|
|
48352
48465
|
if (!resolveTestId(options))
|
|
48353
48466
|
return;
|
|
48354
|
-
await runDomFill(id, value, options);
|
|
48467
|
+
await runDomFill(id, value ?? options.value, options);
|
|
48355
48468
|
}
|
|
48356
48469
|
};
|
|
48357
48470
|
|
|
@@ -51244,7 +51357,7 @@ var resolveExtensionTarget = (targets, options) => {
|
|
|
51244
51357
|
};
|
|
51245
51358
|
var hasExtensionTargetSelector = (options) => Boolean(options.page === true || options.iframe || options.iframeUrl || options.iframeTitle);
|
|
51246
51359
|
var formatExtensionTargetLine = (target) => {
|
|
51247
|
-
const state2 = target.attached ? "attached" : "available";
|
|
51360
|
+
const state2 = target.targetReady === false ? "pending" : target.attached ? "attached" : "available";
|
|
51248
51361
|
const type = target.type ?? "target";
|
|
51249
51362
|
const title = target.title || "(untitled)";
|
|
51250
51363
|
const parent = target.parentId ? ` [parent: ${shortenId(target.parentId)}]` : "";
|
|
@@ -51317,7 +51430,7 @@ var scoreIframeTarget = (target, page) => {
|
|
|
51317
51430
|
var renderTargetNode = (target, prefix, isLast, childrenByParent, output, isRoot = false) => {
|
|
51318
51431
|
const connector = targetTreeConnector(isRoot, isLast);
|
|
51319
51432
|
const childPrefix = targetTreeChildPrefix(prefix, isRoot, isLast);
|
|
51320
|
-
const state2 = target.attached ? " attached" : "";
|
|
51433
|
+
const state2 = target.targetReady === false ? " pending" : target.attached ? " attached" : "";
|
|
51321
51434
|
output.writeHuman(`${prefix}${connector}${target.title || "(untitled)"} (${target.type ?? "target"}, ${shortenId(target.id)}${state2})`);
|
|
51322
51435
|
output.writeHuman(`${childPrefix}${target.url}`);
|
|
51323
51436
|
const children = childrenByParent.get(target.id) ?? [];
|
|
@@ -51574,6 +51687,14 @@ var inspectWatcher = async (id, diagnostics) => {
|
|
|
51574
51687
|
}
|
|
51575
51688
|
if (!bridge) {
|
|
51576
51689
|
issues.push(`Watcher ${resolved.watcher.id} is not present in extension diagnostics.`);
|
|
51690
|
+
} else if (!bridge.connected) {
|
|
51691
|
+
issues.push(`Watcher ${resolved.watcher.id} native bridge is disconnected.`);
|
|
51692
|
+
}
|
|
51693
|
+
if (status.ok && !status.status.attached) {
|
|
51694
|
+
issues.push(`Watcher ${resolved.watcher.id} has no debugger-attached target.`);
|
|
51695
|
+
}
|
|
51696
|
+
if (status.ok && status.status.targetReady === false) {
|
|
51697
|
+
issues.push(`Watcher ${resolved.watcher.id} selected target is not ready for commands.`);
|
|
51577
51698
|
}
|
|
51578
51699
|
if (status.ok && status.status.attached && !selectedTarget) {
|
|
51579
51700
|
issues.push(`Watcher ${resolved.watcher.id} is attached, but no selected target was reported by /targets.`);
|