@vforsh/argus 0.1.21 → 0.1.23

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.
Files changed (47) hide show
  1. package/dist/.tsbuildinfo +1 -1
  2. package/dist/argus.js +488 -121
  3. package/dist/bin.js +2 -0
  4. package/dist/bin.js.map +1 -1
  5. package/dist/cli/register/evalCommands.d.ts.map +1 -1
  6. package/dist/cli/register/evalCommands.js +1 -0
  7. package/dist/cli/register/evalCommands.js.map +1 -1
  8. package/dist/cli/register/logsCommands.d.ts.map +1 -1
  9. package/dist/cli/register/logsCommands.js +15 -4
  10. package/dist/cli/register/logsCommands.js.map +1 -1
  11. package/dist/commands/eval.d.ts.map +1 -1
  12. package/dist/commands/eval.js +2 -0
  13. package/dist/commands/eval.js.map +1 -1
  14. package/dist/commands/evalBundle.d.ts +2 -1
  15. package/dist/commands/evalBundle.d.ts.map +1 -1
  16. package/dist/commands/evalBundle.js +28 -9
  17. package/dist/commands/evalBundle.js.map +1 -1
  18. package/dist/commands/evalPolling.d.ts +1 -0
  19. package/dist/commands/evalPolling.d.ts.map +1 -1
  20. package/dist/commands/evalPolling.js +1 -0
  21. package/dist/commands/evalPolling.js.map +1 -1
  22. package/dist/commands/evalShared.d.ts +2 -0
  23. package/dist/commands/evalShared.d.ts.map +1 -1
  24. package/dist/commands/evalShared.js +14 -5
  25. package/dist/commands/evalShared.js.map +1 -1
  26. package/dist/commands/evalUntil.d.ts.map +1 -1
  27. package/dist/commands/evalUntil.js +1 -0
  28. package/dist/commands/evalUntil.js.map +1 -1
  29. package/dist/commands/logs.d.ts +6 -0
  30. package/dist/commands/logs.d.ts.map +1 -1
  31. package/dist/commands/logs.js +5 -0
  32. package/dist/commands/logs.js.map +1 -1
  33. package/dist/eval/evalClient.d.ts +1 -0
  34. package/dist/eval/evalClient.d.ts.map +1 -1
  35. package/dist/eval/evalClient.js +2 -0
  36. package/dist/eval/evalClient.js.map +1 -1
  37. package/dist/index.d.ts +1 -1
  38. package/dist/index.d.ts.map +1 -1
  39. package/dist/output/io.d.ts +4 -0
  40. package/dist/output/io.d.ts.map +1 -1
  41. package/dist/output/io.js +19 -1
  42. package/dist/output/io.js.map +1 -1
  43. package/dist/skill/argus/SKILL.md +16 -0
  44. package/dist/skill/argus/reference/EVAL.md +35 -2
  45. package/dist/skill/argus/reference/INSPECT.md +3 -0
  46. package/dist/skill/argus/reference/PLUGINS.md +16 -2
  47. package/package.json +4 -4
package/dist/argus.js CHANGED
@@ -5,29 +5,15 @@ var __getProtoOf = Object.getPrototypeOf;
5
5
  var __defProp = Object.defineProperty;
6
6
  var __getOwnPropNames = Object.getOwnPropertyNames;
7
7
  var __hasOwnProp = Object.prototype.hasOwnProperty;
8
- function __accessProp(key) {
9
- return this[key];
10
- }
11
- var __toESMCache_node;
12
- var __toESMCache_esm;
13
8
  var __toESM = (mod, isNodeMode, target) => {
14
- var canCache = mod != null && typeof mod === "object";
15
- if (canCache) {
16
- var cache = isNodeMode ? __toESMCache_node ??= new WeakMap : __toESMCache_esm ??= new WeakMap;
17
- var cached = cache.get(mod);
18
- if (cached)
19
- return cached;
20
- }
21
9
  target = mod != null ? __create(__getProtoOf(mod)) : {};
22
10
  const to = isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target;
23
11
  for (let key of __getOwnPropNames(mod))
24
12
  if (!__hasOwnProp.call(to, key))
25
13
  __defProp(to, key, {
26
- get: __accessProp.bind(mod, key),
14
+ get: () => mod[key],
27
15
  enumerable: true
28
16
  });
29
- if (canCache)
30
- cache.set(mod, to);
31
17
  return to;
32
18
  };
33
19
  var __commonJS = (cb, mod) => () => (mod || cb((mod = { exports: {} }).exports, mod), mod.exports);
@@ -2144,7 +2130,7 @@ var {
2144
2130
  // package.json
2145
2131
  var package_default = {
2146
2132
  name: "@vforsh/argus",
2147
- version: "0.1.21",
2133
+ version: "0.1.23",
2148
2134
  repository: {
2149
2135
  type: "git",
2150
2136
  url: "git+https://github.com/vforsh/argus.git",
@@ -2170,9 +2156,9 @@ var package_default = {
2170
2156
  access: "public"
2171
2157
  },
2172
2158
  dependencies: {
2173
- "@vforsh/argus-core": "workspace:*",
2174
- "@vforsh/argus-plugin-api": "workspace:*",
2175
- "@vforsh/argus-watcher": "workspace:*",
2159
+ "@vforsh/argus-core": "^0.1.11",
2160
+ "@vforsh/argus-plugin-api": "^0.1.4",
2161
+ "@vforsh/argus-watcher": "^0.1.16",
2176
2162
  commander: "14.0.2",
2177
2163
  esbuild: "0.25.12",
2178
2164
  prettier: "3.7.4"
@@ -2270,6 +2256,7 @@ ${examples.map((example) => ` $ ${example}`).join(`
2270
2256
  `;
2271
2257
 
2272
2258
  // ../argus-core/dist/protocol/logs.js
2259
+ var LOG_LEVELS = ["log", "info", "warning", "error", "debug", "exception"];
2273
2260
  var formatLogLevelTag = (level) => {
2274
2261
  switch (level) {
2275
2262
  case "log":
@@ -3205,12 +3192,29 @@ var extractErrorMessage = async (response) => {
3205
3192
  var ensureTrailingNewline = (value) => value.endsWith(`
3206
3193
  `) ? value : `${value}
3207
3194
  `;
3195
+ var configureMachineSafeConsole = (argv) => {
3196
+ if (!argv.includes("--json") && !argv.includes("--json-full")) {
3197
+ return;
3198
+ }
3199
+ const writeConsoleError = console.error.bind(console);
3200
+ console.log = writeConsoleError;
3201
+ console.info = writeConsoleError;
3202
+ console.debug = writeConsoleError;
3203
+ };
3208
3204
  var createOutput = (options) => {
3209
3205
  const json = options.json === true;
3206
+ let wroteJsonDocument = false;
3210
3207
  const writeJsonLine = (value) => {
3211
3208
  process.stdout.write(JSON.stringify(value) + `
3212
3209
  `);
3213
3210
  };
3211
+ const writeJson = (value) => {
3212
+ if (wroteJsonDocument) {
3213
+ throw new Error("Attempted to write more than one JSON document to stdout");
3214
+ }
3215
+ wroteJsonDocument = true;
3216
+ writeJsonLine(value);
3217
+ };
3214
3218
  const writeHuman = (text) => {
3215
3219
  const line = ensureTrailingNewline(text);
3216
3220
  if (json) {
@@ -3224,7 +3228,7 @@ var createOutput = (options) => {
3224
3228
  };
3225
3229
  return {
3226
3230
  json,
3227
- writeJson: writeJsonLine,
3231
+ writeJson,
3228
3232
  writeJsonLine,
3229
3233
  writeHuman,
3230
3234
  writeWarn
@@ -6119,8 +6123,15 @@ var route2 = defineJsonRoute({
6119
6123
  }
6120
6124
  });
6121
6125
 
6122
- // ../argus-watcher/dist/http/routes/getTail.js
6126
+ // ../argus-watcher/dist/http/routes/getLogCursor.js
6123
6127
  var route3 = defineJsonRoute({
6128
+ method: "GET",
6129
+ path: "/logs/cursor",
6130
+ handle: ({ ctx }) => ({ ok: true, cursor: ctx.buffer.getCursor() })
6131
+ });
6132
+
6133
+ // ../argus-watcher/dist/http/routes/getTail.js
6134
+ var route4 = defineJsonRoute({
6124
6135
  method: "GET",
6125
6136
  path: "/tail",
6126
6137
  handle: async ({ res, url, ctx }) => {
@@ -6460,7 +6471,7 @@ var hasTruthyFlag = (searchParams, key) => {
6460
6471
  var optionalClampNumber = (value, min) => value == null ? undefined : clampNumber(value, undefined, min);
6461
6472
 
6462
6473
  // ../argus-watcher/dist/http/routes/getNet.js
6463
- var route4 = defineJsonRoute({
6474
+ var route5 = defineJsonRoute({
6464
6475
  method: "GET",
6465
6476
  path: "/net",
6466
6477
  handle: ({ res, url, ctx }) => {
@@ -6479,7 +6490,7 @@ var route4 = defineJsonRoute({
6479
6490
  });
6480
6491
 
6481
6492
  // ../argus-watcher/dist/http/routes/getNetRequests.js
6482
- var route5 = defineJsonRoute({
6493
+ var route6 = defineJsonRoute({
6483
6494
  method: "GET",
6484
6495
  path: "/net/requests",
6485
6496
  handle: ({ res, url, ctx }) => {
@@ -6533,7 +6544,7 @@ var parsePositiveInt2 = (value) => {
6533
6544
  };
6534
6545
 
6535
6546
  // ../argus-watcher/dist/http/routes/getNetRequest.js
6536
- var route6 = defineJsonRoute({
6547
+ var route7 = defineJsonRoute({
6537
6548
  method: "GET",
6538
6549
  path: "/net/request",
6539
6550
  handle: ({ res, url, ctx }) => {
@@ -6617,7 +6628,7 @@ var createNetBodyError = (message, code) => {
6617
6628
  var capitalizePart = (part) => `${part.slice(0, 1).toUpperCase()}${part.slice(1)}`;
6618
6629
 
6619
6630
  // ../argus-watcher/dist/http/routes/getNetRequestBody.js
6620
- var route7 = defineJsonRoute({
6631
+ var route8 = defineJsonRoute({
6621
6632
  method: "GET",
6622
6633
  path: "/net/request/body",
6623
6634
  handle: async ({ res, url, ctx }) => {
@@ -6687,7 +6698,7 @@ var resolveBodySessionId = (ctx, frameId, storedSessionId) => {
6687
6698
  };
6688
6699
 
6689
6700
  // ../argus-watcher/dist/http/routes/getNetTail.js
6690
- var route8 = defineJsonRoute({
6701
+ var route9 = defineJsonRoute({
6691
6702
  method: "GET",
6692
6703
  path: "/net/tail",
6693
6704
  handle: async ({ res, url, ctx }) => {
@@ -6723,7 +6734,7 @@ var pollNetBuffer = async (buffer, after, filters, limit, timeoutMs) => {
6723
6734
  var delay2 = (timeoutMs) => new Promise((resolve) => setTimeout(resolve, timeoutMs));
6724
6735
 
6725
6736
  // ../argus-watcher/dist/http/routes/getNetWebSockets.js
6726
- var route9 = defineJsonRoute({
6737
+ var route10 = defineJsonRoute({
6727
6738
  method: "GET",
6728
6739
  path: "/net/ws",
6729
6740
  handle: ({ res, url, ctx }) => {
@@ -6742,7 +6753,7 @@ var route9 = defineJsonRoute({
6742
6753
  });
6743
6754
 
6744
6755
  // ../argus-watcher/dist/http/routes/getNetWebSocketConnection.js
6745
- var route10 = defineJsonRoute({
6756
+ var route11 = defineJsonRoute({
6746
6757
  method: "GET",
6747
6758
  path: "/net/ws/connection",
6748
6759
  handle: ({ res, url, ctx }) => {
@@ -6764,7 +6775,7 @@ var route10 = defineJsonRoute({
6764
6775
  });
6765
6776
 
6766
6777
  // ../argus-watcher/dist/http/routes/getNetSse.js
6767
- var route11 = defineJsonRoute({
6778
+ var route12 = defineJsonRoute({
6768
6779
  method: "GET",
6769
6780
  path: "/net/sse",
6770
6781
  handle: ({ res, url, ctx }) => {
@@ -6783,7 +6794,7 @@ var route11 = defineJsonRoute({
6783
6794
  });
6784
6795
 
6785
6796
  // ../argus-watcher/dist/http/routes/postNetClear.js
6786
- var route12 = defineJsonRoute({
6797
+ var route13 = defineJsonRoute({
6787
6798
  method: "POST",
6788
6799
  path: "/net/clear",
6789
6800
  handle: ({ res, ctx }) => {
@@ -7268,7 +7279,7 @@ var normalizeStorageEntries = (entries) => entries.filter((entry) => typeof entr
7268
7279
  }));
7269
7280
 
7270
7281
  // ../argus-watcher/dist/http/routes/getAuthCookies.js
7271
- var route13 = defineJsonRoute({
7282
+ var route14 = defineJsonRoute({
7272
7283
  method: "GET",
7273
7284
  path: "/auth/cookies",
7274
7285
  handle: ({ res, url, ctx }) => {
@@ -7283,7 +7294,7 @@ var route13 = defineJsonRoute({
7283
7294
  });
7284
7295
 
7285
7296
  // ../argus-watcher/dist/http/routes/getAuthState.js
7286
- var route14 = defineJsonRoute({
7297
+ var route15 = defineJsonRoute({
7287
7298
  method: "GET",
7288
7299
  path: "/auth/state",
7289
7300
  handle: ({ res, url, ctx }) => {
@@ -7473,7 +7484,7 @@ var applyAuthStateToSession = async (input) => hydrateAuthState({
7473
7484
  });
7474
7485
 
7475
7486
  // ../argus-watcher/dist/http/routes/postAuthStateLoad.js
7476
- var route15 = defineJsonRoute({
7487
+ var route16 = defineJsonRoute({
7477
7488
  method: "POST",
7478
7489
  path: "/auth/state/load",
7479
7490
  parseBody: true,
@@ -7591,14 +7602,311 @@ var expandRemoteObjectViaGetProperties = async (record2, cdp) => {
7591
7602
  return out;
7592
7603
  };
7593
7604
 
7605
+ // ../argus-watcher/dist/cdp/scenarioBridge.js
7606
+ import { randomUUID } from "node:crypto";
7607
+ var SCENARIO_ACTION_TIMEOUT_MS = 30000;
7608
+ var DEFAULT_LOG_LIMIT = 500;
7609
+ var MAX_LOG_LIMIT = 5000;
7610
+ var installScenarioBridge = async (session, expression, args, services, timeoutMs) => {
7611
+ const token = randomUUID();
7612
+ const suffix = token.replaceAll("-", "");
7613
+ const bindingName = `__argusScenarioSend_${suffix}`;
7614
+ const responseName = `__argusScenarioReceive_${suffix}`;
7615
+ const off = session.onEvent("Runtime.bindingCalled", (rawEvent, meta) => {
7616
+ const { name, payload, executionContextId } = rawEvent;
7617
+ if (name !== bindingName || typeof payload !== "string" || typeof executionContextId !== "number" || !Number.isInteger(executionContextId)) {
7618
+ return;
7619
+ }
7620
+ const request = parseBridgeRequest(payload, token);
7621
+ if (!request) {
7622
+ return;
7623
+ }
7624
+ respondToBridgeRequest(session, responseName, request, services, executionContextId, meta, timeoutMs);
7625
+ });
7626
+ try {
7627
+ await session.sendAndWait("Runtime.addBinding", { name: bindingName }, { timeoutMs });
7628
+ } catch (error) {
7629
+ off();
7630
+ throw error;
7631
+ }
7632
+ let disposed = false;
7633
+ return {
7634
+ expression: buildScenarioExpression(expression, { bindingName, responseName, token, args: args ?? {} }),
7635
+ dispose: async () => {
7636
+ if (disposed)
7637
+ return;
7638
+ disposed = true;
7639
+ off();
7640
+ try {
7641
+ await session.sendAndWait("Runtime.removeBinding", { name: bindingName }, { timeoutMs });
7642
+ } catch {}
7643
+ }
7644
+ };
7645
+ };
7646
+ var parseBridgeRequest = (payload, token) => {
7647
+ try {
7648
+ const parsed = JSON.parse(payload);
7649
+ if (typeof parsed !== "object" || parsed == null || Array.isArray(parsed)) {
7650
+ return null;
7651
+ }
7652
+ const { token: requestToken, id, action, payload: requestPayload } = parsed;
7653
+ if (requestToken !== token || typeof id !== "number" || !Number.isInteger(id) || id < 1 || typeof action !== "string") {
7654
+ return null;
7655
+ }
7656
+ return { token: requestToken, id, action, payload: requestPayload };
7657
+ } catch {
7658
+ return null;
7659
+ }
7660
+ };
7661
+ var respondToBridgeRequest = async (session, responseName, request, services, executionContextId, meta, timeoutMs) => {
7662
+ let response;
7663
+ try {
7664
+ response = { id: request.id, ok: true, result: await handleBridgeRequest(request, services) };
7665
+ } catch (error) {
7666
+ response = { id: request.id, ok: false, error: formatError3(error) };
7667
+ }
7668
+ try {
7669
+ await sendBridgeResponse(session, responseName, response, executionContextId, meta, timeoutMs);
7670
+ } catch {}
7671
+ };
7672
+ var handleBridgeRequest = async (request, services) => {
7673
+ switch (request.action) {
7674
+ case "screenshot": {
7675
+ const options = parseScreenshotOptions(request.payload);
7676
+ return services.screenshotter.capture(options);
7677
+ }
7678
+ case "checkpoint": {
7679
+ const payload = requireRecord(request.payload, "checkpoint payload");
7680
+ const name = parseCheckpointName(payload.name);
7681
+ const options = parseScreenshotOptions(payload.options);
7682
+ const fileName = name.endsWith(".png") ? name : `${name}.png`;
7683
+ return services.screenshotter.capture({ ...options, outFile: `scenarios/checkpoints/${fileName}` });
7684
+ }
7685
+ case "logs.cursor":
7686
+ return { cursor: services.buffer.getCursor() };
7687
+ case "logs.read":
7688
+ return readScenarioLogs(services.buffer, request.payload);
7689
+ default:
7690
+ throw new Error(`Unsupported scenario action: ${request.action}`);
7691
+ }
7692
+ };
7693
+ var parseScreenshotOptions = (value) => {
7694
+ if (value == null)
7695
+ return {};
7696
+ const record2 = requireRecord(value, "screenshot options");
7697
+ const selector = record2.selector;
7698
+ const clip = record2.clip;
7699
+ if (selector != null && (typeof selector !== "string" || !selector.trim())) {
7700
+ throw new Error("selector must be a non-empty string");
7701
+ }
7702
+ if (selector != null && clip != null) {
7703
+ throw new Error("selector and clip are mutually exclusive");
7704
+ }
7705
+ return {
7706
+ selector: typeof selector === "string" ? selector : undefined,
7707
+ clip: clip == null ? undefined : parseClip(clip)
7708
+ };
7709
+ };
7710
+ var parseClip = (value) => {
7711
+ const clip = requireRecord(value, "clip");
7712
+ const { x, y, width, height } = clip;
7713
+ if (!isFiniteNumber2(x) || !isFiniteNumber2(y) || !isFiniteNumber2(width) || !isFiniteNumber2(height)) {
7714
+ throw new Error("clip.x, clip.y, clip.width, and clip.height must be finite numbers");
7715
+ }
7716
+ if (width <= 0 || height <= 0) {
7717
+ throw new Error("clip.width and clip.height must be greater than 0");
7718
+ }
7719
+ return { x, y, width, height };
7720
+ };
7721
+ var isFiniteNumber2 = (value) => typeof value === "number" && Number.isFinite(value);
7722
+ var parseCheckpointName = (value) => {
7723
+ if (typeof value !== "string" || !/^[A-Za-z0-9][A-Za-z0-9._-]{0,99}$/.test(value)) {
7724
+ throw new Error("checkpoint name must be 1-100 characters using letters, numbers, dot, underscore, or dash");
7725
+ }
7726
+ return value;
7727
+ };
7728
+ var readScenarioLogs = (buffer, value) => {
7729
+ const payload = requireRecord(value, "logs.read payload");
7730
+ const cursor = payload.cursor;
7731
+ if (typeof cursor !== "number" || !Number.isInteger(cursor) || cursor < 0) {
7732
+ throw new Error("log cursor must be a non-negative integer");
7733
+ }
7734
+ const { filters, limit } = parseLogOptions(payload.options);
7735
+ const endCursor = buffer.getCursor();
7736
+ const events = buffer.listAfter(cursor, filters, limit);
7737
+ let nextCursor = endCursor;
7738
+ if (events.length === limit) {
7739
+ nextCursor = events[events.length - 1]?.id ?? cursor;
7740
+ }
7741
+ return { events, nextCursor };
7742
+ };
7743
+ var parseLogOptions = (value) => {
7744
+ if (value == null)
7745
+ return { filters: {}, limit: DEFAULT_LOG_LIMIT };
7746
+ const options = requireRecord(value, "log options");
7747
+ const levels = parseLogLevels(options.levels);
7748
+ const matchCase = parseLogMatchCase(options.matchCase);
7749
+ const match = compileLogMatch(options.match, matchCase);
7750
+ const source = parseLogSource(options.source);
7751
+ const limit = parseLogLimit(options.limit);
7752
+ return {
7753
+ filters: { levels, match, source },
7754
+ limit
7755
+ };
7756
+ };
7757
+ var parseLogLevels = (value) => {
7758
+ if (value == null)
7759
+ return;
7760
+ if (Array.isArray(value) && value.every(isLogLevel))
7761
+ return value;
7762
+ throw new Error(`levels must contain only: ${LOG_LEVELS.join(", ")}`);
7763
+ };
7764
+ var isLogLevel = (value) => typeof value === "string" && LOG_LEVELS.includes(value);
7765
+ var parseLogMatchCase = (value) => {
7766
+ if (value == null || value === "sensitive")
7767
+ return "sensitive";
7768
+ if (value === "insensitive")
7769
+ return value;
7770
+ throw new Error("matchCase must be sensitive or insensitive");
7771
+ };
7772
+ var compileLogMatch = (value, matchCase) => {
7773
+ if (value == null)
7774
+ return;
7775
+ const patterns = Array.isArray(value) ? value : [value];
7776
+ if (patterns.length === 0)
7777
+ return;
7778
+ if (!patterns.every(isNonEmptyString)) {
7779
+ throw new Error("match must be a non-empty string or array of non-empty strings");
7780
+ }
7781
+ try {
7782
+ return patterns.map((pattern) => new RegExp(pattern, matchCase === "insensitive" ? "i" : undefined));
7783
+ } catch (error) {
7784
+ throw new Error(`invalid log match expression: ${formatError3(error)}`);
7785
+ }
7786
+ };
7787
+ var isNonEmptyString = (value) => typeof value === "string" && value.length > 0;
7788
+ var parseLogSource = (value) => {
7789
+ if (value == null)
7790
+ return;
7791
+ if (typeof value === "string" && value.trim())
7792
+ return value;
7793
+ throw new Error("source must be a non-empty string");
7794
+ };
7795
+ var parseLogLimit = (value) => {
7796
+ const limit = value ?? DEFAULT_LOG_LIMIT;
7797
+ if (typeof limit === "number" && Number.isInteger(limit) && limit >= 1 && limit <= MAX_LOG_LIMIT)
7798
+ return limit;
7799
+ throw new Error(`limit must be an integer from 1 to ${MAX_LOG_LIMIT}`);
7800
+ };
7801
+ var requireRecord = (value, label) => {
7802
+ if (typeof value !== "object" || value == null || Array.isArray(value)) {
7803
+ throw new Error(`${label} must be an object`);
7804
+ }
7805
+ return value;
7806
+ };
7807
+ var sendBridgeResponse = async (session, responseName, response, executionContextId, meta, timeoutMs) => {
7808
+ await session.sendAndWait("Runtime.evaluate", {
7809
+ expression: `globalThis[${JSON.stringify(responseName)}]?.(${JSON.stringify(response)})`,
7810
+ contextId: executionContextId,
7811
+ returnByValue: true,
7812
+ silent: true
7813
+ }, { timeoutMs, sessionId: meta.sessionId ?? undefined });
7814
+ };
7815
+ var buildScenarioExpression = (expression, options) => `(async () => {
7816
+ const __argusBridge = (() => {
7817
+ const send = globalThis[${JSON.stringify(options.bindingName)}];
7818
+ if (typeof send !== 'function') throw new Error('Argus scenario bridge is unavailable');
7819
+ const pending = new Map();
7820
+ let nextId = 1;
7821
+ const receiveName = ${JSON.stringify(options.responseName)};
7822
+ Object.defineProperty(globalThis, receiveName, {
7823
+ configurable: true,
7824
+ value: (message) => {
7825
+ const entry = pending.get(message?.id);
7826
+ if (!entry) return;
7827
+ pending.delete(message.id);
7828
+ clearTimeout(entry.timeout);
7829
+ if (message.ok) entry.resolve(message.result);
7830
+ else entry.reject(new Error(message.error));
7831
+ },
7832
+ });
7833
+ const request = (action, payload) => new Promise((resolve, reject) => {
7834
+ const id = nextId++;
7835
+ const timeout = setTimeout(() => {
7836
+ pending.delete(id);
7837
+ reject(new Error('Argus scenario action timed out after ${SCENARIO_ACTION_TIMEOUT_MS}ms: ' + action));
7838
+ }, ${SCENARIO_ACTION_TIMEOUT_MS});
7839
+ pending.set(id, { resolve, reject, timeout });
7840
+ try {
7841
+ send(JSON.stringify({ token: ${JSON.stringify(options.token)}, id, action, payload }));
7842
+ } catch (error) {
7843
+ clearTimeout(timeout);
7844
+ pending.delete(id);
7845
+ reject(error);
7846
+ }
7847
+ });
7848
+ const logs = Object.freeze({
7849
+ cursor: async () => (await request('logs.cursor')).cursor,
7850
+ read: (cursor, logOptions) => request('logs.read', { cursor, options: logOptions }),
7851
+ session: async () => {
7852
+ let cursor = (await request('logs.cursor')).cursor;
7853
+ return Object.freeze({
7854
+ get cursor() { return cursor; },
7855
+ async read(logOptions) {
7856
+ const result = await request('logs.read', { cursor, options: logOptions });
7857
+ cursor = result.nextCursor;
7858
+ return result;
7859
+ },
7860
+ });
7861
+ },
7862
+ });
7863
+ const context = Object.freeze({
7864
+ args: Object.freeze(${JSON.stringify(options.args)}),
7865
+ screenshot: (screenshotOptions) => request('screenshot', screenshotOptions),
7866
+ checkpoint: (name, screenshotOptions) => request('checkpoint', { name, options: screenshotOptions }),
7867
+ logs,
7868
+ });
7869
+ return {
7870
+ context,
7871
+ dispose() {
7872
+ delete globalThis[receiveName];
7873
+ for (const entry of pending.values()) {
7874
+ clearTimeout(entry.timeout);
7875
+ entry.reject(new Error('Argus scenario finished before the action completed'));
7876
+ }
7877
+ pending.clear();
7878
+ },
7879
+ };
7880
+ })();
7881
+ const __argusScenarioContext = __argusBridge.context;
7882
+ try {
7883
+ return await (${expression}
7884
+ );
7885
+ } finally {
7886
+ __argusBridge.dispose();
7887
+ }
7888
+ })()`;
7889
+ var formatError3 = (error) => error instanceof Error ? error.message : String(error);
7890
+
7594
7891
  // ../argus-watcher/dist/cdp/eval.js
7595
7892
  var evaluateExpression = async (session, options) => {
7596
7893
  const args = hasEvalArgs(options.args) ? options.args : undefined;
7597
7894
  if (args) {
7598
7895
  await installEvalArgs(session, args, options.timeoutMs);
7599
7896
  }
7897
+ let scenarioBridge;
7600
7898
  try {
7601
- const recordResult = await evaluateAndAwaitRecord(session, options);
7899
+ if (options.scenario) {
7900
+ if (!options.scenarioServices) {
7901
+ throw new Error("Scenario host services are unavailable");
7902
+ }
7903
+ scenarioBridge = await installScenarioBridge(session, options.expression, args, options.scenarioServices, options.timeoutMs);
7904
+ }
7905
+ const recordResult = await evaluateAndAwaitRecord(session, {
7906
+ ...options,
7907
+ expression: scenarioBridge?.expression ?? options.expression,
7908
+ replMode: scenarioBridge ? false : options.replMode
7909
+ });
7602
7910
  if (recordResult.exception)
7603
7911
  return recordResult.response;
7604
7912
  const record2 = recordResult.record;
@@ -7610,6 +7918,7 @@ var evaluateExpression = async (session, options) => {
7610
7918
  exception: null
7611
7919
  };
7612
7920
  } finally {
7921
+ await scenarioBridge?.dispose();
7613
7922
  if (args) {
7614
7923
  await restoreEvalArgs(session, options.timeoutMs);
7615
7924
  }
@@ -7712,7 +8021,7 @@ var shouldMaterializeByValue = (record2) => {
7712
8021
  };
7713
8022
 
7714
8023
  // ../argus-watcher/dist/http/routes/postEval.js
7715
- var route16 = defineJsonRoute({
8024
+ var route17 = defineJsonRoute({
7716
8025
  method: "POST",
7717
8026
  path: "/eval",
7718
8027
  parseBody: true,
@@ -7729,7 +8038,12 @@ var route16 = defineJsonRoute({
7729
8038
  awaitPromise: normalizeBoolean(payload.awaitPromise, true),
7730
8039
  replMode: normalizeBoolean(payload.replMode, true),
7731
8040
  returnByValue: normalizeBoolean(payload.returnByValue, true),
7732
- timeoutMs: normalizeTimeout(payload.timeoutMs)
8041
+ timeoutMs: normalizeTimeout(payload.timeoutMs),
8042
+ scenario: normalizeBoolean(payload.scenario, false),
8043
+ scenarioServices: {
8044
+ buffer: ctx.buffer,
8045
+ screenshotter: ctx.screenshotter
8046
+ }
7733
8047
  })
7734
8048
  });
7735
8049
  var normalizeEvalArgs = (args) => {
@@ -7746,7 +8060,7 @@ var normalizeEvalArgs = (args) => {
7746
8060
  };
7747
8061
 
7748
8062
  // ../argus-watcher/dist/http/routes/postTraceStart.js
7749
- var route17 = defineJsonRoute({
8063
+ var route18 = defineJsonRoute({
7750
8064
  method: "POST",
7751
8065
  path: "/trace/start",
7752
8066
  parseBody: true,
@@ -7755,7 +8069,7 @@ var route17 = defineJsonRoute({
7755
8069
  });
7756
8070
 
7757
8071
  // ../argus-watcher/dist/http/routes/postTraceStop.js
7758
- var route18 = defineJsonRoute({
8072
+ var route19 = defineJsonRoute({
7759
8073
  method: "POST",
7760
8074
  path: "/trace/stop",
7761
8075
  parseBody: true,
@@ -7851,7 +8165,7 @@ var validateClip = (clip) => {
7851
8165
  };
7852
8166
 
7853
8167
  // ../argus-watcher/dist/http/routes/postScreenshot.js
7854
- var route19 = defineJsonRoute({
8168
+ var route20 = defineJsonRoute({
7855
8169
  method: "POST",
7856
8170
  path: "/screenshot",
7857
8171
  parseBody: true,
@@ -8363,7 +8677,7 @@ var countNodes = (nodes) => {
8363
8677
  };
8364
8678
 
8365
8679
  // ../argus-watcher/dist/http/routes/postSnapshot.js
8366
- var route20 = defineJsonRoute({
8680
+ var route21 = defineJsonRoute({
8367
8681
  method: "POST",
8368
8682
  path: "/snapshot",
8369
8683
  parseBody: true,
@@ -8540,7 +8854,7 @@ var locateRoutes = [
8540
8854
  ];
8541
8855
 
8542
8856
  // ../argus-watcher/dist/http/routes/postCodeList.js
8543
- var route21 = defineJsonRoute({
8857
+ var route22 = defineJsonRoute({
8544
8858
  method: "POST",
8545
8859
  path: "/code/list",
8546
8860
  parseBody: true,
@@ -8555,7 +8869,7 @@ var route21 = defineJsonRoute({
8555
8869
  });
8556
8870
 
8557
8871
  // ../argus-watcher/dist/http/routes/postCodeRead.js
8558
- var route22 = defineJsonRoute({
8872
+ var route23 = defineJsonRoute({
8559
8873
  method: "POST",
8560
8874
  path: "/code/read",
8561
8875
  parseBody: true,
@@ -8580,7 +8894,7 @@ var route22 = defineJsonRoute({
8580
8894
  });
8581
8895
 
8582
8896
  // ../argus-watcher/dist/http/routes/postCodeGrep.js
8583
- var route23 = defineJsonRoute({
8897
+ var route24 = defineJsonRoute({
8584
8898
  method: "POST",
8585
8899
  path: "/code/grep",
8586
8900
  parseBody: true,
@@ -8601,7 +8915,7 @@ var route23 = defineJsonRoute({
8601
8915
  });
8602
8916
 
8603
8917
  // ../argus-watcher/dist/http/routes/postCodeEdit.js
8604
- var route24 = defineJsonRoute({
8918
+ var route25 = defineJsonRoute({
8605
8919
  method: "POST",
8606
8920
  path: "/code/edit",
8607
8921
  parseBody: true,
@@ -8958,7 +9272,7 @@ var fillResolvedNodes = async (session, handles, value) => {
8958
9272
  return handles.length;
8959
9273
  };
8960
9274
  // ../argus-watcher/dist/http/routes/postDomTree.js
8961
- var route25 = defineJsonRoute({
9275
+ var route26 = defineJsonRoute({
8962
9276
  method: "POST",
8963
9277
  path: "/dom/tree",
8964
9278
  parseBody: true,
@@ -8981,7 +9295,7 @@ var route25 = defineJsonRoute({
8981
9295
  });
8982
9296
 
8983
9297
  // ../argus-watcher/dist/http/routes/postDomInfo.js
8984
- var route26 = defineJsonRoute({
9298
+ var route27 = defineJsonRoute({
8985
9299
  method: "POST",
8986
9300
  path: "/dom/info",
8987
9301
  parseBody: true,
@@ -9266,7 +9580,7 @@ var defineDomTargetRoute = (input) => defineJsonRoute({
9266
9580
  });
9267
9581
 
9268
9582
  // ../argus-watcher/dist/http/routes/postDomHover.js
9269
- var route27 = defineDomTargetRoute({
9583
+ var route28 = defineDomTargetRoute({
9270
9584
  path: "/dom/hover",
9271
9585
  endpoint: "dom/hover",
9272
9586
  action: "hover",
@@ -9277,7 +9591,7 @@ var route27 = defineDomTargetRoute({
9277
9591
  });
9278
9592
 
9279
9593
  // ../argus-watcher/dist/http/routes/postDomClick.js
9280
- var route28 = defineJsonRoute({
9594
+ var route29 = defineJsonRoute({
9281
9595
  method: "POST",
9282
9596
  path: "/dom/click",
9283
9597
  bodySchema: domClickRequestSchema,
@@ -9325,7 +9639,7 @@ var route28 = defineJsonRoute({
9325
9639
  });
9326
9640
 
9327
9641
  // ../argus-watcher/dist/http/routes/postDomDrag.js
9328
- var route29 = defineJsonRoute({
9642
+ var route30 = defineJsonRoute({
9329
9643
  method: "POST",
9330
9644
  path: "/dom/drag",
9331
9645
  bodySchema: domDragRequestSchema,
@@ -9542,7 +9856,7 @@ var dispatchKeydown = async (session, options) => {
9542
9856
  };
9543
9857
 
9544
9858
  // ../argus-watcher/dist/http/routes/postDomKeydown.js
9545
- var route30 = defineJsonRoute({
9859
+ var route31 = defineJsonRoute({
9546
9860
  method: "POST",
9547
9861
  path: "/dom/keydown",
9548
9862
  parseBody: true,
@@ -9592,7 +9906,7 @@ var route30 = defineJsonRoute({
9592
9906
 
9593
9907
  // ../argus-watcher/dist/http/routes/postDomAdd.js
9594
9908
  var validPositions = ["beforebegin", "afterbegin", "beforeend", "afterend"];
9595
- var route31 = defineJsonRoute({
9909
+ var route32 = defineJsonRoute({
9596
9910
  method: "POST",
9597
9911
  path: "/dom/add",
9598
9912
  parseBody: true,
@@ -9681,7 +9995,7 @@ var selectDomAddNodeIds = (allNodeIds, options) => {
9681
9995
  };
9682
9996
 
9683
9997
  // ../argus-watcher/dist/http/routes/postDomRemove.js
9684
- var route32 = defineJsonRoute({
9998
+ var route33 = defineJsonRoute({
9685
9999
  method: "POST",
9686
10000
  path: "/dom/remove",
9687
10001
  parseBody: true,
@@ -9703,7 +10017,7 @@ var route32 = defineJsonRoute({
9703
10017
 
9704
10018
  // ../argus-watcher/dist/http/routes/postDomModify.js
9705
10019
  var validTypes = ["attr", "class", "style", "text", "html"];
9706
- var route33 = defineJsonRoute({
10020
+ var route34 = defineJsonRoute({
9707
10021
  method: "POST",
9708
10022
  path: "/dom/modify",
9709
10023
  parseBody: true,
@@ -9734,7 +10048,7 @@ var route33 = defineJsonRoute({
9734
10048
  });
9735
10049
 
9736
10050
  // ../argus-watcher/dist/http/routes/postDomSetFile.js
9737
- var route34 = defineJsonRoute({
10051
+ var route35 = defineJsonRoute({
9738
10052
  method: "POST",
9739
10053
  path: "/dom/set-file",
9740
10054
  parseBody: true,
@@ -9772,7 +10086,7 @@ var route34 = defineJsonRoute({
9772
10086
  });
9773
10087
 
9774
10088
  // ../argus-watcher/dist/http/routes/postDomFocus.js
9775
- var route35 = defineDomTargetRoute({
10089
+ var route36 = defineDomTargetRoute({
9776
10090
  path: "/dom/focus",
9777
10091
  endpoint: "dom/focus",
9778
10092
  action: "focus",
@@ -9783,7 +10097,7 @@ var route35 = defineDomTargetRoute({
9783
10097
  });
9784
10098
 
9785
10099
  // ../argus-watcher/dist/http/routes/postDomFill.js
9786
- var route36 = defineDomTargetRoute({
10100
+ var route37 = defineDomTargetRoute({
9787
10101
  path: "/dom/fill",
9788
10102
  endpoint: "dom/fill",
9789
10103
  action: "fill",
@@ -9804,7 +10118,7 @@ var route36 = defineDomTargetRoute({
9804
10118
  });
9805
10119
 
9806
10120
  // ../argus-watcher/dist/http/routes/postDomScroll.js
9807
- var route37 = defineJsonRoute({
10121
+ var route38 = defineJsonRoute({
9808
10122
  method: "POST",
9809
10123
  path: "/dom/scroll",
9810
10124
  parseBody: true,
@@ -9863,7 +10177,7 @@ var getViewportSize = async (session) => {
9863
10177
  };
9864
10178
 
9865
10179
  // ../argus-watcher/dist/http/routes/postDomScrollTo.js
9866
- var route38 = defineJsonRoute({
10180
+ var route39 = defineJsonRoute({
9867
10181
  method: "POST",
9868
10182
  path: "/dom/scroll-to",
9869
10183
  parseBody: true,
@@ -9910,7 +10224,7 @@ var route38 = defineJsonRoute({
9910
10224
  });
9911
10225
 
9912
10226
  // ../argus-watcher/dist/http/routes/getEmulation.js
9913
- var route39 = defineJsonRoute({
10227
+ var route40 = defineJsonRoute({
9914
10228
  method: "GET",
9915
10229
  path: "/emulation",
9916
10230
  endpoint: "emulation",
@@ -9919,7 +10233,7 @@ var route39 = defineJsonRoute({
9919
10233
 
9920
10234
  // ../argus-watcher/dist/http/routes/postEmulation.js
9921
10235
  var validActions = ["set", "clear"];
9922
- var route40 = defineJsonRoute({
10236
+ var route41 = defineJsonRoute({
9923
10237
  method: "POST",
9924
10238
  path: "/emulation",
9925
10239
  parseBody: true,
@@ -9978,7 +10292,7 @@ function validateEmulationRequest(payload) {
9978
10292
  }
9979
10293
 
9980
10294
  // ../argus-watcher/dist/http/routes/getThrottle.js
9981
- var route41 = defineJsonRoute({
10295
+ var route42 = defineJsonRoute({
9982
10296
  method: "GET",
9983
10297
  path: "/throttle",
9984
10298
  endpoint: "throttle",
@@ -9987,7 +10301,7 @@ var route41 = defineJsonRoute({
9987
10301
 
9988
10302
  // ../argus-watcher/dist/http/routes/postThrottle.js
9989
10303
  var validActions2 = ["set", "clear"];
9990
- var route42 = defineJsonRoute({
10304
+ var route43 = defineJsonRoute({
9991
10305
  method: "POST",
9992
10306
  path: "/throttle",
9993
10307
  parseBody: true,
@@ -10015,7 +10329,7 @@ var route42 = defineJsonRoute({
10015
10329
  });
10016
10330
 
10017
10331
  // ../argus-watcher/dist/http/routes/getDialog.js
10018
- var route43 = defineJsonRoute({
10332
+ var route44 = defineJsonRoute({
10019
10333
  method: "GET",
10020
10334
  path: "/dialog",
10021
10335
  endpoint: "dialog/status",
@@ -10023,7 +10337,7 @@ var route43 = defineJsonRoute({
10023
10337
  });
10024
10338
 
10025
10339
  // ../argus-watcher/dist/http/routes/postDialog.js
10026
- var route44 = defineJsonRoute({
10340
+ var route45 = defineJsonRoute({
10027
10341
  method: "POST",
10028
10342
  path: "/dialog",
10029
10343
  parseBody: true,
@@ -10062,7 +10376,7 @@ var route44 = defineJsonRoute({
10062
10376
  });
10063
10377
 
10064
10378
  // ../argus-watcher/dist/http/routes/postVisibility.js
10065
- var route45 = defineJsonRoute({
10379
+ var route46 = defineJsonRoute({
10066
10380
  method: "POST",
10067
10381
  path: "/visibility",
10068
10382
  parseBody: true,
@@ -10179,7 +10493,7 @@ function validateStoragePayload(payload) {
10179
10493
  }
10180
10494
 
10181
10495
  // ../argus-watcher/dist/http/routes/postReload.js
10182
- var route46 = defineJsonRoute({
10496
+ var route47 = defineJsonRoute({
10183
10497
  method: "POST",
10184
10498
  path: "/reload",
10185
10499
  parseBody: true,
@@ -10193,7 +10507,7 @@ var route46 = defineJsonRoute({
10193
10507
  });
10194
10508
 
10195
10509
  // ../argus-watcher/dist/http/routes/postShutdown.js
10196
- var route47 = defineJsonRoute({
10510
+ var route48 = defineJsonRoute({
10197
10511
  method: "POST",
10198
10512
  path: "/shutdown",
10199
10513
  endpoint: "shutdown",
@@ -10208,7 +10522,7 @@ var route47 = defineJsonRoute({
10208
10522
  });
10209
10523
 
10210
10524
  // ../argus-watcher/dist/http/routes/getExtensionTabs.js
10211
- var route48 = defineJsonRoute({
10525
+ var route49 = defineJsonRoute({
10212
10526
  method: "GET",
10213
10527
  path: "/tabs",
10214
10528
  extensionOnly: true,
@@ -10229,7 +10543,7 @@ var route48 = defineJsonRoute({
10229
10543
  });
10230
10544
 
10231
10545
  // ../argus-watcher/dist/http/routes/getExtensionDiagnostics.js
10232
- var route49 = defineJsonRoute({
10546
+ var route50 = defineJsonRoute({
10233
10547
  method: "GET",
10234
10548
  path: "/extension/diagnostics",
10235
10549
  extensionOnly: true,
@@ -10243,7 +10557,7 @@ var route49 = defineJsonRoute({
10243
10557
  });
10244
10558
 
10245
10559
  // ../argus-watcher/dist/http/routes/getTargets.js
10246
- var route50 = defineJsonRoute({
10560
+ var route51 = defineJsonRoute({
10247
10561
  method: "GET",
10248
10562
  path: "/targets",
10249
10563
  extensionOnly: true,
@@ -10258,7 +10572,7 @@ var route50 = defineJsonRoute({
10258
10572
  });
10259
10573
 
10260
10574
  // ../argus-watcher/dist/http/routes/postAttach.js
10261
- var route51 = defineJsonRoute({
10575
+ var route52 = defineJsonRoute({
10262
10576
  method: "POST",
10263
10577
  path: "/attach",
10264
10578
  parseBody: true,
@@ -10281,7 +10595,7 @@ var route51 = defineJsonRoute({
10281
10595
  });
10282
10596
 
10283
10597
  // ../argus-watcher/dist/http/routes/postDetach.js
10284
- var route52 = defineJsonRoute({
10598
+ var route53 = defineJsonRoute({
10285
10599
  method: "POST",
10286
10600
  path: "/detach",
10287
10601
  parseBody: true,
@@ -10306,8 +10620,8 @@ var route52 = defineJsonRoute({
10306
10620
  // ../argus-watcher/dist/http/routes/index.js
10307
10621
  var watcherRoutes = [
10308
10622
  route,
10309
- route2,
10310
10623
  route3,
10624
+ route2,
10311
10625
  route4,
10312
10626
  route5,
10313
10627
  route6,
@@ -10317,22 +10631,22 @@ var watcherRoutes = [
10317
10631
  route10,
10318
10632
  route11,
10319
10633
  route12,
10320
- ...netMockRoutes,
10321
10634
  route13,
10635
+ ...netMockRoutes,
10636
+ route14,
10322
10637
  cookieGetRoute,
10323
10638
  cookieSetRoute,
10324
10639
  cookieDeleteRoute,
10325
10640
  cookieClearRoute,
10326
- route14,
10327
10641
  route15,
10328
10642
  route16,
10329
10643
  route17,
10330
10644
  route18,
10331
- ...recordRoutes,
10332
10645
  route19,
10646
+ ...recordRoutes,
10333
10647
  route20,
10334
- ...locateRoutes,
10335
10648
  route21,
10649
+ ...locateRoutes,
10336
10650
  route22,
10337
10651
  route23,
10338
10652
  route24,
@@ -10357,18 +10671,19 @@ var watcherRoutes = [
10357
10671
  route43,
10358
10672
  route44,
10359
10673
  route45,
10360
- ...storageRoutes,
10361
10674
  route46,
10675
+ ...storageRoutes,
10362
10676
  route47,
10363
10677
  route48,
10364
10678
  route49,
10365
10679
  route50,
10366
10680
  route51,
10367
- route52
10681
+ route52,
10682
+ route53
10368
10683
  ];
10369
10684
 
10370
10685
  // ../argus-watcher/dist/http/router.js
10371
- var routes = new Map(watcherRoutes.map((route53) => [`${route53.method} ${route53.path}`, route53]));
10686
+ var routes = new Map(watcherRoutes.map((route54) => [`${route54.method} ${route54.path}`, route54]));
10372
10687
  var dispatch = (req, res, url, ctx) => {
10373
10688
  const entry = routes.get(`${req.method} ${url.pathname}`);
10374
10689
  if (!entry || entry.extensionOnly && !ctx.sourceHandle) {
@@ -11055,6 +11370,9 @@ class LogBuffer {
11055
11370
  const filtered = this.events.filter((event) => event.id > after && matchesFilters(event, filters));
11056
11371
  return filtered.slice(0, limit);
11057
11372
  }
11373
+ getCursor() {
11374
+ return this.nextId - 1;
11375
+ }
11058
11376
  waitForAfter(after, filters, limit, timeoutMs) {
11059
11377
  const immediate = this.listAfter(after, filters, limit);
11060
11378
  if (immediate.length > 0) {
@@ -15140,8 +15458,8 @@ var startCdpWatcher = (options) => {
15140
15458
  await connectOnce();
15141
15459
  backoffMs = 1000;
15142
15460
  } catch (error) {
15143
- const reason = `connect_failed: ${formatError3(error)}`;
15144
- options.onLog(createSystemLog(`CDP connection failed: ${formatError3(error)}`));
15461
+ const reason = `connect_failed: ${formatError4(error)}`;
15462
+ options.onLog(createSystemLog(`CDP connection failed: ${formatError4(error)}`));
15145
15463
  options.onStatus({ attached: false, target: null, reason });
15146
15464
  options.onDetach?.(reason);
15147
15465
  await delay4(backoffMs);
@@ -15218,7 +15536,7 @@ var createSystemLog = (message) => ({
15218
15536
  pageTitle: null,
15219
15537
  source: "system"
15220
15538
  });
15221
- var formatError3 = (error) => {
15539
+ var formatError4 = (error) => {
15222
15540
  if (!error) {
15223
15541
  return "Unknown error";
15224
15542
  }
@@ -19851,6 +20169,10 @@ var appendRepeatedParams = (params, key, values) => {
19851
20169
  };
19852
20170
 
19853
20171
  // dist/commands/logs.js
20172
+ var runLogCursor = defineWatcherCommand({
20173
+ build: () => ({ path: "/logs/cursor", timeoutMs: 5000 }),
20174
+ formatHuman: (response, { output }) => output.writeHuman(String(response.cursor))
20175
+ });
19854
20176
  var runLogs = defineWatcherCommand({
19855
20177
  isJson: (options) => options.jsonFull === true,
19856
20178
  build: (_args, options, output) => buildLogsPlan(options, output),
@@ -19980,6 +20302,16 @@ var logsCommands = [
19980
20302
  await runLogs(id, options);
19981
20303
  },
19982
20304
  subcommands: [
20305
+ {
20306
+ name: "cursor",
20307
+ description: "Return the current log cursor without downloading events",
20308
+ arguments: [{ flags: "[id]", description: "Watcher id to query" }],
20309
+ options: [{ flags: "--json", description: "Output one JSON document for automation" }],
20310
+ examples: ["argus logs cursor app", "argus logs cursor app --json"],
20311
+ action: async (id, options, command) => {
20312
+ await runLogCursor(id, command.optsWithGlobals?.() ?? options);
20313
+ }
20314
+ },
19983
20315
  {
19984
20316
  name: "tail",
19985
20317
  description: "Stream logs via long-polling",
@@ -19998,10 +20330,11 @@ var logsCommands = [
19998
20330
  "argus logs tail app --json",
19999
20331
  "argus logs tail app --json-full"
20000
20332
  ],
20001
- action: async (id, options) => {
20002
- if (!validateLogsOptions(options))
20333
+ action: async (id, options, command) => {
20334
+ const resolvedOptions = command.optsWithGlobals?.() ?? options;
20335
+ if (!validateLogsOptions(resolvedOptions))
20003
20336
  return;
20004
- await runTail(id, options);
20337
+ await runTail(id, resolvedOptions);
20005
20338
  }
20006
20339
  }
20007
20340
  ]
@@ -20030,7 +20363,8 @@ var evalOnce = async (input) => {
20030
20363
  awaitPromise: input.awaitPromise,
20031
20364
  replMode: input.replMode,
20032
20365
  returnByValue: input.returnByValue,
20033
- timeoutMs: input.timeoutMs
20366
+ timeoutMs: input.timeoutMs,
20367
+ scenario: input.scenario
20034
20368
  };
20035
20369
  const requestTimeoutMs = input.timeoutMs ? input.timeoutMs + 5000 : DEFAULT_EVAL_REQUEST_TIMEOUT_MS;
20036
20370
  let response;
@@ -20088,7 +20422,8 @@ var evalWithRetries = async (input) => {
20088
20422
  replMode: input.replMode,
20089
20423
  returnByValue: input.returnByValue,
20090
20424
  timeoutMs: input.timeoutMs,
20091
- failOnException: input.failOnException
20425
+ failOnException: input.failOnException,
20426
+ scenario: input.scenario
20092
20427
  });
20093
20428
  if (outcome.ok) {
20094
20429
  return { ...outcome, attempt };
@@ -20309,6 +20644,10 @@ import path13 from "node:path";
20309
20644
  var esbuildModulePromise;
20310
20645
  var loadEsbuild = () => esbuildModulePromise ??= import("esbuild");
20311
20646
  var RESULT_BINDING = "__argusEvalBundleResult";
20647
+ var LEGACY_RESULT_BINDING = "__argusEvalLegacyResult";
20648
+ var LEGACY_RESULT_EXPORT = "__argusLegacyResult";
20649
+ var VIRTUAL_ENTRY = "argus:eval-entry";
20650
+ var VIRTUAL_NAMESPACE = "argus-eval-entry";
20312
20651
  var bundleEvalEntry = async (entryPath) => {
20313
20652
  let entryPoint;
20314
20653
  try {
@@ -20320,7 +20659,7 @@ var bundleEvalEntry = async (entryPath) => {
20320
20659
  const esbuild = await loadEsbuild();
20321
20660
  const result = await esbuild.build({
20322
20661
  absWorkingDir: process.cwd(),
20323
- entryPoints: [entryPoint],
20662
+ entryPoints: [VIRTUAL_ENTRY],
20324
20663
  bundle: true,
20325
20664
  write: false,
20326
20665
  splitting: false,
@@ -20343,6 +20682,12 @@ var bundleEvalEntry = async (entryPath) => {
20343
20682
  var createPageEvalBundlePlugin = (entryPoint) => ({
20344
20683
  name: "argus-eval-bundle",
20345
20684
  setup(build) {
20685
+ build.onResolve({ filter: /^argus:eval-entry$/ }, () => ({ path: VIRTUAL_ENTRY, namespace: VIRTUAL_NAMESPACE }));
20686
+ build.onLoad({ filter: /.*/, namespace: VIRTUAL_NAMESPACE }, () => ({
20687
+ contents: buildVirtualEntrySource(entryPoint),
20688
+ loader: "js",
20689
+ resolveDir: process.cwd()
20690
+ }));
20346
20691
  build.onResolve({ filter: /^node:/ }, (args) => bundleError(`Node built-in import ${JSON.stringify(args.path)} is not allowed in page eval.`));
20347
20692
  build.onLoad({ filter: /.*/ }, async (args) => {
20348
20693
  if (await realpath(args.path) !== entryPoint) {
@@ -20350,7 +20695,7 @@ var createPageEvalBundlePlugin = (entryPoint) => ({
20350
20695
  }
20351
20696
  const source = await readFile3(args.path, "utf8");
20352
20697
  return {
20353
- contents: captureFinalExpression(source),
20698
+ contents: exposeLegacyResult(source),
20354
20699
  loader: loaderForPath(args.path)
20355
20700
  };
20356
20701
  });
@@ -20362,12 +20707,23 @@ var createPageEvalBundlePlugin = (entryPoint) => ({
20362
20707
  if (outputs.length !== 1) {
20363
20708
  return bundleError(`Bundle produced ${outputs.length} outputs; expected exactly one script.`);
20364
20709
  }
20365
- if (/\bexport\b/.test(outputs[0]?.text ?? "")) {
20366
- return bundleError("Bundled script contains top-level export statements, which page eval cannot run. Remove exports from the entry file (helpers may still export symbols for import).");
20367
- }
20368
20710
  });
20369
20711
  }
20370
20712
  });
20713
+ var buildVirtualEntrySource = (entryPoint) => `
20714
+ import * as __argusEntry from ${JSON.stringify(entryPoint)};
20715
+ const __argusDefault = __argusEntry.default;
20716
+ if (__argusDefault !== undefined && typeof __argusDefault !== 'function') {
20717
+ throw new TypeError('The default export of an Argus scenario must be a function');
20718
+ }
20719
+ ${RESULT_BINDING} = typeof __argusDefault === 'function'
20720
+ ? await __argusDefault(__argusScenarioContext)
20721
+ : __argusEntry.${LEGACY_RESULT_EXPORT};
20722
+ `;
20723
+ var exposeLegacyResult = (source) => `let ${LEGACY_RESULT_BINDING};
20724
+ ${captureFinalExpression(source)}
20725
+ export { ${LEGACY_RESULT_BINDING} as ${LEGACY_RESULT_EXPORT} };
20726
+ `;
20371
20727
  var captureFinalExpression = (source) => {
20372
20728
  const lines = source.split(/\r?\n/);
20373
20729
  const index = findFinalCodeLine(lines);
@@ -20380,7 +20736,7 @@ var captureFinalExpression = (source) => {
20380
20736
  return source;
20381
20737
  }
20382
20738
  const indent = line.match(/^\s*/)?.[0] ?? "";
20383
- lines[index] = `${indent}${RESULT_BINDING} = (${expression});`;
20739
+ lines[index] = `${indent}${LEGACY_RESULT_BINDING} = (${expression});`;
20384
20740
  return lines.join(`
20385
20741
  `);
20386
20742
  };
@@ -20393,7 +20749,7 @@ var findFinalCodeLine = (lines) => {
20393
20749
  }
20394
20750
  return null;
20395
20751
  };
20396
- var isStatementLike = (source) => /^(?:import|export|const|let|var|function|class|if|for|while|switch|try|catch|finally|return|throw|break|continue)\b/.test(source);
20752
+ var isStatementLike = (source) => source === "}" || /^(?:[{}]|import|export|const|let|var|function|class|if|for|while|switch|try|catch|finally|return|throw|break|continue)\b/.test(source);
20397
20753
  var loaderForPath = (filePath) => {
20398
20754
  const extension = path13.extname(filePath).toLowerCase();
20399
20755
  if (extension === ".ts")
@@ -20553,14 +20909,15 @@ var prepareEvalExpression = async (inline, options, output) => {
20553
20909
  if (args == null) {
20554
20910
  return null;
20555
20911
  }
20556
- const resolvedExpression = await resolveExpression(inline, options, output);
20557
- if (resolvedExpression == null) {
20912
+ const resolved = await resolveExpressionSource(inline, options, output);
20913
+ if (resolved == null) {
20558
20914
  return null;
20559
20915
  }
20560
20916
  if (!options.iframe) {
20561
20917
  return {
20562
- expression: resolvedExpression,
20563
- args: hasEvalArgs2(args) ? args : undefined
20918
+ expression: resolved.expression,
20919
+ args: hasEvalArgs2(args) ? args : undefined,
20920
+ scenario: resolved.scenario
20564
20921
  };
20565
20922
  }
20566
20923
  const iframeTimeoutMs = parseDurationFlagMs(options.iframeTimeout, "--iframe-timeout");
@@ -20569,14 +20926,15 @@ var prepareEvalExpression = async (inline, options, output) => {
20569
20926
  return null;
20570
20927
  }
20571
20928
  return {
20572
- expression: wrapForIframeEval(wrapExpressionWithArgs(resolvedExpression, args), {
20929
+ expression: wrapForIframeEval(wrapExpressionWithArgs(resolved.expression, args), {
20573
20930
  selector: options.iframe,
20574
20931
  namespace: options.iframeNamespace ?? "argus",
20575
20932
  timeoutMs: iframeTimeoutMs.value ?? 5000
20576
- })
20933
+ }),
20934
+ scenario: resolved.scenario
20577
20935
  };
20578
20936
  };
20579
- var resolveExpression = async (inline, options, output) => {
20937
+ var resolveExpressionSource = async (inline, options, output) => {
20580
20938
  const wantsStdin = options.stdin === true || inline === "-";
20581
20939
  const hasInline = inline != null && inline !== "-";
20582
20940
  const filePath = options.file;
@@ -20598,6 +20956,7 @@ var resolveExpression = async (inline, options, output) => {
20598
20956
  return null;
20599
20957
  }
20600
20958
  let expression;
20959
+ let scenario;
20601
20960
  if (hasFile) {
20602
20961
  const fileContent = await readFileContent(filePath, options.file, output);
20603
20962
  if (fileContent == null) {
@@ -20618,6 +20977,7 @@ var resolveExpression = async (inline, options, output) => {
20618
20977
  return null;
20619
20978
  }
20620
20979
  expression = bundled.code;
20980
+ scenario = true;
20621
20981
  } else {
20622
20982
  expression = fileContent;
20623
20983
  }
@@ -20643,7 +21003,8 @@ var resolveExpression = async (inline, options, output) => {
20643
21003
  output.writeWarn("Expression is required. Provide an inline expression, --file, or --stdin (or pass - as expression).");
20644
21004
  return null;
20645
21005
  }
20646
- return await prependInjectSource(expression, options.inject, output);
21006
+ const injected = await prependInjectSource(expression, options.inject, output);
21007
+ return injected == null ? null : { expression: injected, scenario };
20647
21008
  };
20648
21009
  var resolveBundleDecision = (options, fileContent) => {
20649
21010
  if (options.noBundle) {
@@ -23601,7 +23962,8 @@ var pollEval = async (input) => {
23601
23962
  returnByValue: input.returnByValue,
23602
23963
  timeoutMs: input.timeoutMs,
23603
23964
  failOnException: input.failOnException,
23604
- retryCount: input.retryCount
23965
+ retryCount: input.retryCount,
23966
+ scenario: input.scenario
23605
23967
  });
23606
23968
  if (!result.ok) {
23607
23969
  return { kind: "eval-error", failure: result };
@@ -23694,7 +24056,8 @@ var runEval = async (id, rawExpression, options) => {
23694
24056
  returnByValue: options.returnByValue ?? true,
23695
24057
  timeoutMs: timeoutMs.value,
23696
24058
  failOnException: options.failOnException ?? true,
23697
- retryCount: retryCount.value
24059
+ retryCount: retryCount.value,
24060
+ scenario: prepared.scenario
23698
24061
  });
23699
24062
  if (!singleResult.ok) {
23700
24063
  emitter.emitError(singleResult);
@@ -23713,6 +24076,7 @@ var runEval = async (id, rawExpression, options) => {
23713
24076
  timeoutMs: timeoutMs.value,
23714
24077
  failOnException: options.failOnException ?? true,
23715
24078
  retryCount: retryCount.value,
24079
+ scenario: prepared.scenario,
23716
24080
  intervalMs: intervalMs.value,
23717
24081
  count: countValue.value,
23718
24082
  onResult: async (response) => {
@@ -23826,6 +24190,7 @@ var runEvalUntil = async (id, rawExpression, options) => {
23826
24190
  timeoutMs: timeoutMs.value,
23827
24191
  failOnException: options.failOnException ?? true,
23828
24192
  retryCount: retryCount.value,
24193
+ scenario: prepared.scenario,
23829
24194
  intervalMs: pollIntervalMs,
23830
24195
  count: countValue.value,
23831
24196
  totalTimeoutMs: totalTimeoutMs.value,
@@ -23976,6 +24341,7 @@ var evalCommands = [
23976
24341
  'argus eval app "window.store.getState()" --inject ./debug-hooks.js',
23977
24342
  "argus eval app --file ./script.js --arg level=10 --arg mode=fast",
23978
24343
  "argus eval app --file ./script.js --args ./args.json",
24344
+ "argus eval app --file ./scenario.ts --arg level=10 --json",
23979
24345
  'argus eval app "document.title" --json --out ./result.json',
23980
24346
  'argus eval app "Date.now()" --interval 500 --count 10 --out ./poll.ndjson',
23981
24347
  'argus eval app "Date.now()" --interval 500 --count 10 --out ./frames.json --rotate',
@@ -49994,7 +50360,7 @@ var runExtensionTabs = async (options) => {
49994
50360
  returnErrorResponse: true
49995
50361
  });
49996
50362
  } catch (error) {
49997
- writeCommandError(output, options, `${resolved.watcher.id}: failed to list extension tabs (${formatError4(error)})`, formatError4(error));
50363
+ writeCommandError(output, options, `${resolved.watcher.id}: failed to list extension tabs (${formatError5(error)})`, formatError5(error));
49998
50364
  process.exitCode = 1;
49999
50365
  return;
50000
50366
  }
@@ -50055,7 +50421,7 @@ var writeCommandError = (output, options, humanMessage, jsonPayload) => {
50055
50421
  }
50056
50422
  output.writeWarn(humanMessage);
50057
50423
  };
50058
- var formatError4 = (error) => error instanceof Error ? error.message : String(error);
50424
+ var formatError5 = (error) => error instanceof Error ? error.message : String(error);
50059
50425
 
50060
50426
  // dist/commands/extension/tabSelection.js
50061
50427
  var parseTabSelector = (options, missingReason) => {
@@ -50100,7 +50466,7 @@ var fetchExtensionTabs = async (watcher, selector) => {
50100
50466
  }
50101
50467
  return { ok: true, tabs: response.tabs };
50102
50468
  } catch (error) {
50103
- return { ok: false, error: `${watcher.id}: failed to list extension tabs (${formatError5(error)})` };
50469
+ return { ok: false, error: `${watcher.id}: failed to list extension tabs (${formatError6(error)})` };
50104
50470
  }
50105
50471
  };
50106
50472
  var hasTabSelector = (options) => Boolean(options.tab != null || options.url || options.title);
@@ -50130,7 +50496,7 @@ var buildTabsQuery2 = (selector) => {
50130
50496
  }
50131
50497
  return query;
50132
50498
  };
50133
- var formatError5 = (error) => error instanceof Error ? error.message : String(error);
50499
+ var formatError6 = (error) => error instanceof Error ? error.message : String(error);
50134
50500
 
50135
50501
  // dist/commands/extension/tabAttach.js
50136
50502
  var WATCHER_POLL_TIMEOUT_MS = 5000;
@@ -50149,7 +50515,7 @@ var attachTab = async (controlWatcher, tab, options = {}) => {
50149
50515
  }
50150
50516
  return { ok: true, tab: response.tab, watcherId: response.watcherId };
50151
50517
  } catch (error) {
50152
- return { ok: false, error: `${controlWatcher.id}: failed to attach tab (${formatError6(error)})` };
50518
+ return { ok: false, error: `${controlWatcher.id}: failed to attach tab (${formatError7(error)})` };
50153
50519
  }
50154
50520
  };
50155
50521
  var waitForTabWatcher = async (controlWatcher, selector, tab, watcherId) => {
@@ -50228,7 +50594,7 @@ var targetMatchesTab = (target, tab) => {
50228
50594
  return Boolean(target.title && target.title === tab.title && target.url === tab.url);
50229
50595
  };
50230
50596
  var delay8 = (ms3) => new Promise((resolve2) => setTimeout(resolve2, ms3));
50231
- var formatError6 = (error) => error instanceof Error ? error.message : String(error);
50597
+ var formatError7 = (error) => error instanceof Error ? error.message : String(error);
50232
50598
 
50233
50599
  // dist/commands/extension/show.js
50234
50600
  var runExtensionShow = async (id, options, config = {}) => {
@@ -50304,7 +50670,7 @@ var showWatcher = async (watcher, tab, output, options) => {
50304
50670
  returnErrorResponse: true
50305
50671
  });
50306
50672
  } catch (error) {
50307
- writeFailure(output, options, `${watcher.id}: failed to show page (${formatError7(error)})`, 1);
50673
+ writeFailure(output, options, `${watcher.id}: failed to show page (${formatError8(error)})`, 1);
50308
50674
  return;
50309
50675
  }
50310
50676
  if (!response.ok) {
@@ -50353,7 +50719,7 @@ var writeFailure = (output, options, error, exitCode, extra = {}) => {
50353
50719
  }
50354
50720
  process.exitCode = exitCode;
50355
50721
  };
50356
- var formatError7 = (error) => error instanceof Error ? error.message : String(error);
50722
+ var formatError8 = (error) => error instanceof Error ? error.message : String(error);
50357
50723
 
50358
50724
  // dist/commands/extension/attach.js
50359
50725
  var runExtensionAttach = async (options) => {
@@ -50577,7 +50943,7 @@ var fetchExtensionTargets = async (watcher) => {
50577
50943
  }
50578
50944
  return { ok: true, targets: response.targets };
50579
50945
  } catch (error) {
50580
- return { ok: false, error: `${watcher.id}: failed to list extension targets (${formatError8(error)})` };
50946
+ return { ok: false, error: `${watcher.id}: failed to list extension targets (${formatError9(error)})` };
50581
50947
  }
50582
50948
  };
50583
50949
  var selectExtensionTarget = async (watcher, target) => {
@@ -50594,7 +50960,7 @@ var selectExtensionTarget = async (watcher, target) => {
50594
50960
  }
50595
50961
  return { ok: true, tab: response.tab, watcherId: response.watcherId };
50596
50962
  } catch (error) {
50597
- return { ok: false, error: `${watcher.id}: failed to select target (${formatError8(error)})` };
50963
+ return { ok: false, error: `${watcher.id}: failed to select target (${formatError9(error)})` };
50598
50964
  }
50599
50965
  };
50600
50966
  var waitForSelectedTarget = async (watcher, target, options = {}) => {
@@ -50740,7 +51106,7 @@ var fetchWatcherStatus = async (watcher) => {
50740
51106
  try {
50741
51107
  return { ok: true, status: await fetchWatcherJson(watcher, { path: "/status", timeoutMs: 1000 }) };
50742
51108
  } catch (error) {
50743
- return { ok: false, error: `${watcher.id}: failed to read status (${formatError8(error)})` };
51109
+ return { ok: false, error: `${watcher.id}: failed to read status (${formatError9(error)})` };
50744
51110
  }
50745
51111
  };
50746
51112
  var statusMatchesTarget = (status, target) => {
@@ -50765,7 +51131,7 @@ var originOf = (url) => {
50765
51131
  };
50766
51132
  var shortenId = (id) => id.length > 18 ? `${id.slice(0, 14)}...` : id;
50767
51133
  var delay9 = (ms3) => new Promise((resolve2) => setTimeout(resolve2, ms3));
50768
- var formatError8 = (error) => error instanceof Error ? error.message : String(error);
51134
+ var formatError9 = (error) => error instanceof Error ? error.message : String(error);
50769
51135
 
50770
51136
  // dist/commands/extension/use.js
50771
51137
  var runExtensionUse = async (options) => {
@@ -50937,7 +51303,7 @@ var inspectNativeHostState = () => {
50937
51303
  issues: configured ? [] : ["Native messaging hosts are not fully configured."]
50938
51304
  };
50939
51305
  } catch (error) {
50940
- return { configured: false, hosts: [], issues: [formatError9(error)] };
51306
+ return { configured: false, hosts: [], issues: [formatError10(error)] };
50941
51307
  }
50942
51308
  };
50943
51309
  var fetchExtensionDiagnostics = async (watcher) => {
@@ -50952,7 +51318,7 @@ var fetchExtensionDiagnostics = async (watcher) => {
50952
51318
  }
50953
51319
  return { ok: false, error: response.error.message };
50954
51320
  } catch (error) {
50955
- return { ok: false, error: `${watcher.id}: failed to read extension diagnostics (${formatError9(error)})` };
51321
+ return { ok: false, error: `${watcher.id}: failed to read extension diagnostics (${formatError10(error)})` };
50956
51322
  }
50957
51323
  };
50958
51324
  var inspectWatcher = async (id, diagnostics) => {
@@ -50995,10 +51361,10 @@ var fetchWatcherStatus2 = async (watcher) => {
50995
51361
  try {
50996
51362
  return { ok: true, status: await fetchWatcherJson(watcher, { path: "/status", timeoutMs: 1000 }) };
50997
51363
  } catch (error) {
50998
- return { ok: false, error: `${watcher.id}: failed to read status (${formatError9(error)})` };
51364
+ return { ok: false, error: `${watcher.id}: failed to read status (${formatError10(error)})` };
50999
51365
  }
51000
51366
  };
51001
- var formatError9 = (error) => error instanceof Error ? error.message : String(error);
51367
+ var formatError10 = (error) => error instanceof Error ? error.message : String(error);
51002
51368
 
51003
51369
  // dist/commands/extension/targets.js
51004
51370
  var runExtensionTargets = async (id, options) => {
@@ -51462,6 +51828,7 @@ var coreCommandDefinitions = [
51462
51828
  var coreProgramRegistrars = [(program2) => defineCommands(program2, coreCommandDefinitions)];
51463
51829
 
51464
51830
  // dist/bin.js
51831
+ configureMachineSafeConsole(process.argv.slice(2));
51465
51832
  var program2 = createProgram();
51466
51833
  for (const registerProgramPart of coreProgramRegistrars) {
51467
51834
  registerProgramPart(program2);