@vforsh/argus 0.1.23 → 0.3.0

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/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.1.23",
2133
+ version: "0.3.0",
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-core": "^0.1.11",
2160
- "@vforsh/argus-plugin-api": "^0.1.4",
2161
- "@vforsh/argus-watcher": "^0.1.16",
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.0",
2162
2163
  commander: "14.0.2",
2163
2164
  esbuild: "0.25.12",
2164
2165
  prettier: "3.7.4"
@@ -2448,7 +2449,7 @@ var optionalPoint = (value, key) => {
2448
2449
  // ../argus-core/dist/protocol/http/auth.js
2449
2450
  var AUTH_STATE_METADATA_SCHEMA_VERSION = 1;
2450
2451
  // ../argus-core/dist/protocol/version.js
2451
- var ARGUS_PROTOCOL_VERSION = 1;
2452
+ var ARGUS_PROTOCOL_VERSION = 2;
2452
2453
  // ../argus-core/dist/registry/registry.js
2453
2454
  import fs2 from "node:fs/promises";
2454
2455
  import path3 from "node:path";
@@ -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 Error(errorMessage ?? `Request failed (${response.status} ${response.statusText})`);
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 Error(`Request failed (${response.status} ${response.statusText})`);
3171
+ throw new HttpResponseError(`Request failed (${response.status} ${response.statusText})`, response.status);
3162
3172
  }
3163
3173
  return await response.text();
3164
3174
  } catch (error) {
@@ -6093,12 +6103,279 @@ var buildStatus = (ctx) => {
6093
6103
  };
6094
6104
  };
6095
6105
 
6106
+ // ../argus-watcher/dist/buffer/LogBuffer.js
6107
+ import { randomUUID } from "node:crypto";
6108
+
6109
+ class LogEpochError extends Error {
6110
+ code;
6111
+ constructor(code, message) {
6112
+ super(message);
6113
+ this.name = "LogEpochError";
6114
+ this.code = code;
6115
+ }
6116
+ }
6117
+ var EPOCH_PREFIX = "argus-log-epoch-v1.";
6118
+
6119
+ class LogBuffer {
6120
+ maxSize;
6121
+ streamId = randomUUID();
6122
+ events = [];
6123
+ nextId = 1;
6124
+ waiters = [];
6125
+ epochWaiters = [];
6126
+ constructor(maxSize) {
6127
+ this.maxSize = maxSize;
6128
+ }
6129
+ add(event) {
6130
+ const entry = {
6131
+ ...event,
6132
+ id: this.nextId++
6133
+ };
6134
+ this.events.push(entry);
6135
+ this.trim();
6136
+ this.flushWaiters();
6137
+ this.flushEpochWaiters();
6138
+ return entry;
6139
+ }
6140
+ listAfter(after, filters, limit) {
6141
+ return this.listAfterPosition(after, filters, limit);
6142
+ }
6143
+ getCursor() {
6144
+ return this.beginLogEpoch();
6145
+ }
6146
+ beginLogEpoch() {
6147
+ return encodeEpoch({ v: 1, s: this.streamId, p: this.currentPosition() });
6148
+ }
6149
+ getEpoch() {
6150
+ return this.beginLogEpoch();
6151
+ }
6152
+ getEpochAt(position) {
6153
+ return encodeEpoch({ v: 1, s: this.streamId, p: position });
6154
+ }
6155
+ listAfterEpoch(epoch, filters, limit) {
6156
+ const position = this.resolveEpoch(epoch);
6157
+ const events = this.listAfterPosition(position, filters, limit);
6158
+ return {
6159
+ events,
6160
+ nextCursor: events.length > 0 ? this.getEpochAt(events[events.length - 1]?.id ?? position) : epoch
6161
+ };
6162
+ }
6163
+ waitForAfter(after, filters, limit, timeoutMs) {
6164
+ const immediate = this.listAfter(after, filters, limit);
6165
+ if (immediate.length > 0) {
6166
+ return Promise.resolve(immediate);
6167
+ }
6168
+ return new Promise((resolve) => {
6169
+ const timer = setTimeout(() => {
6170
+ this.waiters = this.waiters.filter((waiter) => waiter.timer !== timer);
6171
+ resolve([]);
6172
+ }, timeoutMs);
6173
+ this.waiters.push({ after, filters, limit, resolve, timer });
6174
+ });
6175
+ }
6176
+ async waitForAfterEpoch(epoch, filters, limit, timeoutMs) {
6177
+ const position = this.resolveEpoch(epoch);
6178
+ const immediate = this.listAfterPosition(position, filters, limit);
6179
+ if (immediate.length > 0) {
6180
+ return { events: immediate, nextCursor: this.getEpochAt(immediate[immediate.length - 1]?.id ?? position) };
6181
+ }
6182
+ return new Promise((resolve, reject) => {
6183
+ const timer = setTimeout(() => {
6184
+ this.epochWaiters = this.epochWaiters.filter((waiter) => waiter.timer !== timer);
6185
+ resolve({ events: [], nextCursor: epoch });
6186
+ }, timeoutMs);
6187
+ this.epochWaiters.push({ position, filters, limit, resolve, reject, timer });
6188
+ });
6189
+ }
6190
+ getStats() {
6191
+ if (this.events.length === 0) {
6192
+ return { size: this.maxSize, count: 0, minId: null, maxId: null };
6193
+ }
6194
+ return {
6195
+ size: this.maxSize,
6196
+ count: this.events.length,
6197
+ minId: this.events[0]?.id ?? null,
6198
+ maxId: this.events[this.events.length - 1]?.id ?? null
6199
+ };
6200
+ }
6201
+ trim() {
6202
+ if (this.maxSize <= 0) {
6203
+ this.events = [];
6204
+ return;
6205
+ }
6206
+ if (this.events.length <= this.maxSize) {
6207
+ return;
6208
+ }
6209
+ this.events = this.events.slice(this.events.length - this.maxSize);
6210
+ }
6211
+ flushWaiters() {
6212
+ if (this.waiters.length === 0) {
6213
+ return;
6214
+ }
6215
+ const remaining = [];
6216
+ for (const waiter of this.waiters) {
6217
+ const events = this.listAfter(waiter.after, waiter.filters, waiter.limit);
6218
+ if (events.length > 0) {
6219
+ clearTimeout(waiter.timer);
6220
+ waiter.resolve(events);
6221
+ continue;
6222
+ }
6223
+ remaining.push(waiter);
6224
+ }
6225
+ this.waiters = remaining;
6226
+ }
6227
+ flushEpochWaiters() {
6228
+ if (this.epochWaiters.length === 0) {
6229
+ return;
6230
+ }
6231
+ const remaining = [];
6232
+ for (const waiter of this.epochWaiters) {
6233
+ try {
6234
+ this.validatePosition(waiter.position);
6235
+ } catch (error) {
6236
+ clearTimeout(waiter.timer);
6237
+ waiter.reject(error);
6238
+ continue;
6239
+ }
6240
+ const events = this.listAfterPosition(waiter.position, waiter.filters, waiter.limit);
6241
+ if (events.length > 0) {
6242
+ clearTimeout(waiter.timer);
6243
+ waiter.resolve({
6244
+ events,
6245
+ nextCursor: this.getEpochAt(events[events.length - 1]?.id ?? waiter.position)
6246
+ });
6247
+ continue;
6248
+ }
6249
+ remaining.push(waiter);
6250
+ }
6251
+ this.epochWaiters = remaining;
6252
+ }
6253
+ listAfterPosition(position, filters, limit) {
6254
+ return this.events.filter((event) => event.id > position && matchesFilters(event, filters)).slice(0, limit);
6255
+ }
6256
+ resolveEpoch(epoch) {
6257
+ const payload = decodeEpoch(epoch);
6258
+ if (!payload) {
6259
+ throw new LogEpochError("invalid", "Invalid log epoch. Capture a new epoch from the watcher.");
6260
+ }
6261
+ if (payload.s !== this.streamId) {
6262
+ throw new LogEpochError("mismatch", "Log epoch belongs to a different watcher session. Capture a new epoch.");
6263
+ }
6264
+ if (payload.p > this.currentPosition()) {
6265
+ throw new LogEpochError("future", "Log epoch points past the current log stream.");
6266
+ }
6267
+ this.validatePosition(payload.p);
6268
+ return payload.p;
6269
+ }
6270
+ validatePosition(position) {
6271
+ if (this.events.length > 0 && position < (this.events[0]?.id ?? position + 1) - 1) {
6272
+ throw new LogEpochError("evicted", "Log epoch is stale because the ring buffer evicted entries. Capture a new epoch.");
6273
+ }
6274
+ if (this.maxSize === 0 && this.currentPosition() > position) {
6275
+ throw new LogEpochError("evicted", "Log epoch is stale because the ring buffer evicted entries. Capture a new epoch.");
6276
+ }
6277
+ }
6278
+ currentPosition() {
6279
+ return this.nextId - 1;
6280
+ }
6281
+ }
6282
+ var encodeEpoch = (payload) => `${EPOCH_PREFIX}${Buffer.from(JSON.stringify(payload)).toString("base64url")}`;
6283
+ var decodeEpoch = (epoch) => {
6284
+ if (typeof epoch !== "string" || !epoch.startsWith(EPOCH_PREFIX)) {
6285
+ return null;
6286
+ }
6287
+ try {
6288
+ const parsed = JSON.parse(Buffer.from(epoch.slice(EPOCH_PREFIX.length), "base64url").toString("utf8"));
6289
+ if (parsed.v !== 1 || typeof parsed.s !== "string" || !parsed.s || typeof parsed.p !== "number" || !Number.isSafeInteger(parsed.p) || parsed.p < 0) {
6290
+ return null;
6291
+ }
6292
+ return parsed;
6293
+ } catch {
6294
+ return null;
6295
+ }
6296
+ };
6297
+ var matchesFilters = (event, filters) => {
6298
+ if (filters.sinceTs && event.ts < filters.sinceTs) {
6299
+ return false;
6300
+ }
6301
+ if (filters.levels && filters.levels.length > 0 && !filters.levels.includes(event.level)) {
6302
+ return false;
6303
+ }
6304
+ if (filters.source && !event.source.toLowerCase().includes(filters.source.toLowerCase())) {
6305
+ return false;
6306
+ }
6307
+ if (filters.match && filters.match.length > 0) {
6308
+ for (const pattern of filters.match) {
6309
+ if (pattern.test(event.text)) {
6310
+ return true;
6311
+ }
6312
+ }
6313
+ return false;
6314
+ }
6315
+ return true;
6316
+ };
6317
+
6318
+ // ../argus-watcher/dist/http/routes/logEpochQuery.js
6319
+ var parseLogPosition = (url) => {
6320
+ const after = normalizeQueryValue2(url.searchParams.get("after") ?? null);
6321
+ const sinceEpoch = normalizeQueryValue2(url.searchParams.get("sinceEpoch"));
6322
+ if (after && sinceEpoch) {
6323
+ return { error: "Use either after or sinceEpoch, not both." };
6324
+ }
6325
+ if (sinceEpoch) {
6326
+ return { kind: "epoch", epoch: sinceEpoch };
6327
+ }
6328
+ if (after) {
6329
+ return { kind: "epoch", epoch: after };
6330
+ }
6331
+ return { kind: "all" };
6332
+ };
6333
+ var respondLogEpochError = (res, error) => {
6334
+ const status = error.code === "invalid" || error.code === "future" ? 400 : 409;
6335
+ respondJson(res, {
6336
+ ok: false,
6337
+ error: {
6338
+ message: error.message,
6339
+ code: `log_epoch_${error.code}`
6340
+ }
6341
+ }, status);
6342
+ };
6343
+ var listLogsFromPosition = (buffer, position, filters, limit) => {
6344
+ if (position.kind === "epoch") {
6345
+ return buffer.listAfterEpoch(position.epoch, filters, limit);
6346
+ }
6347
+ return createQueryResult(buffer, position, buffer.listAfter(0, filters, limit));
6348
+ };
6349
+ var waitForLogsFromPosition = async (buffer, position, filters, limit, timeoutMs) => {
6350
+ if (position.kind === "epoch") {
6351
+ return buffer.waitForAfterEpoch(position.epoch, filters, limit, timeoutMs);
6352
+ }
6353
+ const events = await buffer.waitForAfter(0, filters, limit, timeoutMs);
6354
+ return createQueryResult(buffer, position, events);
6355
+ };
6356
+ var createQueryResult = (buffer, position, events) => ({
6357
+ events,
6358
+ nextCursor: resolveNextCursor(buffer, position, events)
6359
+ });
6360
+ var resolveNextCursor = (buffer, position, events) => {
6361
+ if (events.length > 0) {
6362
+ return buffer.getEpochAt(events[events.length - 1]?.id ?? 0);
6363
+ }
6364
+ if (position.kind === "epoch") {
6365
+ return position.epoch;
6366
+ }
6367
+ return buffer.getEpoch();
6368
+ };
6369
+
6096
6370
  // ../argus-watcher/dist/http/routes/getLogs.js
6097
6371
  var route2 = defineJsonRoute({
6098
6372
  method: "GET",
6099
6373
  path: "/logs",
6100
6374
  handle: ({ res, url, ctx }) => {
6101
- const after = clampNumber(url.searchParams.get("after"), 0);
6375
+ const position = parseLogPosition(url);
6376
+ if ("error" in position) {
6377
+ return respondLogEpochError(res, new LogEpochError("invalid", position.error));
6378
+ }
6102
6379
  const limit = clampNumber(url.searchParams.get("limit"), 500, 1, 5000);
6103
6380
  const levels = parseLevels(url.searchParams.get("levels"));
6104
6381
  const match = url.searchParams.getAll("match");
@@ -6116,10 +6393,25 @@ var route2 = defineJsonRoute({
6116
6393
  if (compiledMatch.error) {
6117
6394
  return respondInvalidMatch(res, compiledMatch.error);
6118
6395
  }
6119
- emitRequest(ctx, res, "logs", { after, limit, levels, match: matchPatterns.patterns, matchCase, source, sinceTs });
6120
- const events = ctx.buffer.listAfter(after, { levels, match: compiledMatch.match, source, sinceTs }, limit);
6121
- const nextAfter = events.length > 0 ? events[events.length - 1]?.id ?? after : after;
6122
- return { ok: true, events, nextAfter };
6396
+ emitRequest(ctx, res, "logs", {
6397
+ after: position.kind === "epoch" && url.searchParams.has("after") ? position.epoch : undefined,
6398
+ sinceEpoch: position.kind === "epoch" ? position.epoch : undefined,
6399
+ limit,
6400
+ levels,
6401
+ match: matchPatterns.patterns,
6402
+ matchCase,
6403
+ source,
6404
+ sinceTs
6405
+ });
6406
+ try {
6407
+ const result = listLogsFromPosition(ctx.buffer, position, { levels, match: compiledMatch.match, source, sinceTs }, limit);
6408
+ return { ok: true, ...result };
6409
+ } catch (error) {
6410
+ if (error instanceof LogEpochError) {
6411
+ return respondLogEpochError(res, error);
6412
+ }
6413
+ throw error;
6414
+ }
6123
6415
  }
6124
6416
  });
6125
6417
 
@@ -6130,12 +6422,22 @@ var route3 = defineJsonRoute({
6130
6422
  handle: ({ ctx }) => ({ ok: true, cursor: ctx.buffer.getCursor() })
6131
6423
  });
6132
6424
 
6133
- // ../argus-watcher/dist/http/routes/getTail.js
6425
+ // ../argus-watcher/dist/http/routes/getLogEpoch.js
6134
6426
  var route4 = defineJsonRoute({
6427
+ method: "GET",
6428
+ path: "/logs/epoch",
6429
+ handle: ({ ctx }) => ({ ok: true, epoch: ctx.buffer.beginLogEpoch() })
6430
+ });
6431
+
6432
+ // ../argus-watcher/dist/http/routes/getTail.js
6433
+ var route5 = defineJsonRoute({
6135
6434
  method: "GET",
6136
6435
  path: "/tail",
6137
6436
  handle: async ({ res, url, ctx }) => {
6138
- const after = clampNumber(url.searchParams.get("after"), 0);
6437
+ const position = parseLogPosition(url);
6438
+ if ("error" in position) {
6439
+ return respondLogEpochError(res, new LogEpochError("invalid", position.error));
6440
+ }
6139
6441
  const limit = clampNumber(url.searchParams.get("limit"), 500, 1, 5000);
6140
6442
  const timeoutMs = clampNumber(url.searchParams.get("timeoutMs"), 25000, 1000, 120000);
6141
6443
  const levels = parseLevels(url.searchParams.get("levels"));
@@ -6153,10 +6455,25 @@ var route4 = defineJsonRoute({
6153
6455
  if (compiledMatch.error) {
6154
6456
  return respondInvalidMatch(res, compiledMatch.error);
6155
6457
  }
6156
- emitRequest(ctx, res, "tail", { after, limit, levels, match: matchPatterns.patterns, matchCase, source, timeoutMs });
6157
- const events = await ctx.buffer.waitForAfter(after, { levels, match: compiledMatch.match, source }, limit, timeoutMs);
6158
- const nextAfter = events.length > 0 ? events[events.length - 1]?.id ?? after : after;
6159
- return { ok: true, events, nextAfter, timedOut: events.length === 0 };
6458
+ emitRequest(ctx, res, "tail", {
6459
+ after: position.kind === "epoch" ? position.epoch : undefined,
6460
+ sinceEpoch: position.kind === "epoch" ? position.epoch : undefined,
6461
+ limit,
6462
+ levels,
6463
+ match: matchPatterns.patterns,
6464
+ matchCase,
6465
+ source,
6466
+ timeoutMs
6467
+ });
6468
+ try {
6469
+ const result = await waitForLogsFromPosition(ctx.buffer, position, { levels, match: compiledMatch.match, source }, limit, timeoutMs);
6470
+ return { ok: true, ...result, timedOut: result.events.length === 0 };
6471
+ } catch (error) {
6472
+ if (error instanceof LogEpochError) {
6473
+ return respondLogEpochError(res, error);
6474
+ }
6475
+ throw error;
6476
+ }
6160
6477
  }
6161
6478
  });
6162
6479
 
@@ -6471,7 +6788,7 @@ var hasTruthyFlag = (searchParams, key) => {
6471
6788
  var optionalClampNumber = (value, min) => value == null ? undefined : clampNumber(value, undefined, min);
6472
6789
 
6473
6790
  // ../argus-watcher/dist/http/routes/getNet.js
6474
- var route5 = defineJsonRoute({
6791
+ var route6 = defineJsonRoute({
6475
6792
  method: "GET",
6476
6793
  path: "/net",
6477
6794
  handle: ({ res, url, ctx }) => {
@@ -6490,7 +6807,7 @@ var route5 = defineJsonRoute({
6490
6807
  });
6491
6808
 
6492
6809
  // ../argus-watcher/dist/http/routes/getNetRequests.js
6493
- var route6 = defineJsonRoute({
6810
+ var route7 = defineJsonRoute({
6494
6811
  method: "GET",
6495
6812
  path: "/net/requests",
6496
6813
  handle: ({ res, url, ctx }) => {
@@ -6544,7 +6861,7 @@ var parsePositiveInt2 = (value) => {
6544
6861
  };
6545
6862
 
6546
6863
  // ../argus-watcher/dist/http/routes/getNetRequest.js
6547
- var route7 = defineJsonRoute({
6864
+ var route8 = defineJsonRoute({
6548
6865
  method: "GET",
6549
6866
  path: "/net/request",
6550
6867
  handle: ({ res, url, ctx }) => {
@@ -6628,7 +6945,7 @@ var createNetBodyError = (message, code) => {
6628
6945
  var capitalizePart = (part) => `${part.slice(0, 1).toUpperCase()}${part.slice(1)}`;
6629
6946
 
6630
6947
  // ../argus-watcher/dist/http/routes/getNetRequestBody.js
6631
- var route8 = defineJsonRoute({
6948
+ var route9 = defineJsonRoute({
6632
6949
  method: "GET",
6633
6950
  path: "/net/request/body",
6634
6951
  handle: async ({ res, url, ctx }) => {
@@ -6698,7 +7015,7 @@ var resolveBodySessionId = (ctx, frameId, storedSessionId) => {
6698
7015
  };
6699
7016
 
6700
7017
  // ../argus-watcher/dist/http/routes/getNetTail.js
6701
- var route9 = defineJsonRoute({
7018
+ var route10 = defineJsonRoute({
6702
7019
  method: "GET",
6703
7020
  path: "/net/tail",
6704
7021
  handle: async ({ res, url, ctx }) => {
@@ -6734,7 +7051,7 @@ var pollNetBuffer = async (buffer, after, filters, limit, timeoutMs) => {
6734
7051
  var delay2 = (timeoutMs) => new Promise((resolve) => setTimeout(resolve, timeoutMs));
6735
7052
 
6736
7053
  // ../argus-watcher/dist/http/routes/getNetWebSockets.js
6737
- var route10 = defineJsonRoute({
7054
+ var route11 = defineJsonRoute({
6738
7055
  method: "GET",
6739
7056
  path: "/net/ws",
6740
7057
  handle: ({ res, url, ctx }) => {
@@ -6753,7 +7070,7 @@ var route10 = defineJsonRoute({
6753
7070
  });
6754
7071
 
6755
7072
  // ../argus-watcher/dist/http/routes/getNetWebSocketConnection.js
6756
- var route11 = defineJsonRoute({
7073
+ var route12 = defineJsonRoute({
6757
7074
  method: "GET",
6758
7075
  path: "/net/ws/connection",
6759
7076
  handle: ({ res, url, ctx }) => {
@@ -6775,7 +7092,7 @@ var route11 = defineJsonRoute({
6775
7092
  });
6776
7093
 
6777
7094
  // ../argus-watcher/dist/http/routes/getNetSse.js
6778
- var route12 = defineJsonRoute({
7095
+ var route13 = defineJsonRoute({
6779
7096
  method: "GET",
6780
7097
  path: "/net/sse",
6781
7098
  handle: ({ res, url, ctx }) => {
@@ -6794,7 +7111,7 @@ var route12 = defineJsonRoute({
6794
7111
  });
6795
7112
 
6796
7113
  // ../argus-watcher/dist/http/routes/postNetClear.js
6797
- var route13 = defineJsonRoute({
7114
+ var route14 = defineJsonRoute({
6798
7115
  method: "POST",
6799
7116
  path: "/net/clear",
6800
7117
  handle: ({ res, ctx }) => {
@@ -7279,7 +7596,7 @@ var normalizeStorageEntries = (entries) => entries.filter((entry) => typeof entr
7279
7596
  }));
7280
7597
 
7281
7598
  // ../argus-watcher/dist/http/routes/getAuthCookies.js
7282
- var route14 = defineJsonRoute({
7599
+ var route15 = defineJsonRoute({
7283
7600
  method: "GET",
7284
7601
  path: "/auth/cookies",
7285
7602
  handle: ({ res, url, ctx }) => {
@@ -7294,7 +7611,7 @@ var route14 = defineJsonRoute({
7294
7611
  });
7295
7612
 
7296
7613
  // ../argus-watcher/dist/http/routes/getAuthState.js
7297
- var route15 = defineJsonRoute({
7614
+ var route16 = defineJsonRoute({
7298
7615
  method: "GET",
7299
7616
  path: "/auth/state",
7300
7617
  handle: ({ res, url, ctx }) => {
@@ -7484,7 +7801,7 @@ var applyAuthStateToSession = async (input) => hydrateAuthState({
7484
7801
  });
7485
7802
 
7486
7803
  // ../argus-watcher/dist/http/routes/postAuthStateLoad.js
7487
- var route16 = defineJsonRoute({
7804
+ var route17 = defineJsonRoute({
7488
7805
  method: "POST",
7489
7806
  path: "/auth/state/load",
7490
7807
  parseBody: true,
@@ -7603,12 +7920,12 @@ var expandRemoteObjectViaGetProperties = async (record2, cdp) => {
7603
7920
  };
7604
7921
 
7605
7922
  // ../argus-watcher/dist/cdp/scenarioBridge.js
7606
- import { randomUUID } from "node:crypto";
7923
+ import { randomUUID as randomUUID2 } from "node:crypto";
7607
7924
  var SCENARIO_ACTION_TIMEOUT_MS = 30000;
7608
7925
  var DEFAULT_LOG_LIMIT = 500;
7609
7926
  var MAX_LOG_LIMIT = 5000;
7610
7927
  var installScenarioBridge = async (session, expression, args, services, timeoutMs) => {
7611
- const token = randomUUID();
7928
+ const token = randomUUID2();
7612
7929
  const suffix = token.replaceAll("-", "");
7613
7930
  const bindingName = `__argusScenarioSend_${suffix}`;
7614
7931
  const responseName = `__argusScenarioReceive_${suffix}`;
@@ -7728,17 +8045,11 @@ var parseCheckpointName = (value) => {
7728
8045
  var readScenarioLogs = (buffer, value) => {
7729
8046
  const payload = requireRecord(value, "logs.read payload");
7730
8047
  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");
8048
+ if (typeof cursor !== "string" || !cursor.trim()) {
8049
+ throw new Error("log cursor must be a non-empty opaque cursor");
7733
8050
  }
7734
8051
  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 };
8052
+ return buffer.listAfterEpoch(cursor, filters, limit);
7742
8053
  };
7743
8054
  var parseLogOptions = (value) => {
7744
8055
  if (value == null)
@@ -7910,6 +8221,17 @@ var evaluateExpression = async (session, options) => {
7910
8221
  if (recordResult.exception)
7911
8222
  return recordResult.response;
7912
8223
  const record2 = recordResult.record;
8224
+ if (options.jsonValue) {
8225
+ const jsonResult = await materializeJsonValue(session, record2, options);
8226
+ if (!jsonResult.ok)
8227
+ return jsonResult.response;
8228
+ return {
8229
+ ok: true,
8230
+ result: jsonResult.json,
8231
+ type: record2?.type ?? null,
8232
+ exception: null
8233
+ };
8234
+ }
7913
8235
  const value = await materializeRemoteObject(session, record2, options);
7914
8236
  return {
7915
8237
  ok: true,
@@ -7995,6 +8317,25 @@ var awaitPromiseResult = async (session, promiseObjectId, timeoutMs) => await se
7995
8317
  promiseObjectId,
7996
8318
  returnByValue: false
7997
8319
  }, { timeoutMs });
8320
+ var EMPTY_JSON_ENVELOPE = "{}";
8321
+ var materializeJsonValue = async (session, record2, options) => {
8322
+ if (!record2) {
8323
+ return { ok: true, json: EMPTY_JSON_ENVELOPE };
8324
+ }
8325
+ if (!record2.objectId) {
8326
+ return { ok: true, json: JSON.stringify({ v: record2.value }) ?? EMPTY_JSON_ENVELOPE };
8327
+ }
8328
+ const payload = await session.sendAndWait("Runtime.callFunctionOn", {
8329
+ objectId: record2.objectId,
8330
+ functionDeclaration: "function () { return JSON.stringify({ v: this }) }",
8331
+ returnByValue: true
8332
+ }, { timeoutMs: options.timeoutMs });
8333
+ if (payload.exceptionDetails) {
8334
+ return { ok: false, response: formatExceptionResponse(payload) };
8335
+ }
8336
+ const json = payload.result?.value;
8337
+ return { ok: true, json: typeof json === "string" ? json : EMPTY_JSON_ENVELOPE };
8338
+ };
7998
8339
  var materializeRemoteObject = async (session, record2, options) => {
7999
8340
  if (!record2) {
8000
8341
  return null;
@@ -8021,7 +8362,7 @@ var shouldMaterializeByValue = (record2) => {
8021
8362
  };
8022
8363
 
8023
8364
  // ../argus-watcher/dist/http/routes/postEval.js
8024
- var route17 = defineJsonRoute({
8365
+ var route18 = defineJsonRoute({
8025
8366
  method: "POST",
8026
8367
  path: "/eval",
8027
8368
  parseBody: true,
@@ -8038,6 +8379,7 @@ var route17 = defineJsonRoute({
8038
8379
  awaitPromise: normalizeBoolean(payload.awaitPromise, true),
8039
8380
  replMode: normalizeBoolean(payload.replMode, true),
8040
8381
  returnByValue: normalizeBoolean(payload.returnByValue, true),
8382
+ jsonValue: normalizeBoolean(payload.jsonValue, false),
8041
8383
  timeoutMs: normalizeTimeout(payload.timeoutMs),
8042
8384
  scenario: normalizeBoolean(payload.scenario, false),
8043
8385
  scenarioServices: {
@@ -8060,7 +8402,7 @@ var normalizeEvalArgs = (args) => {
8060
8402
  };
8061
8403
 
8062
8404
  // ../argus-watcher/dist/http/routes/postTraceStart.js
8063
- var route18 = defineJsonRoute({
8405
+ var route19 = defineJsonRoute({
8064
8406
  method: "POST",
8065
8407
  path: "/trace/start",
8066
8408
  parseBody: true,
@@ -8069,7 +8411,7 @@ var route18 = defineJsonRoute({
8069
8411
  });
8070
8412
 
8071
8413
  // ../argus-watcher/dist/http/routes/postTraceStop.js
8072
- var route19 = defineJsonRoute({
8414
+ var route20 = defineJsonRoute({
8073
8415
  method: "POST",
8074
8416
  path: "/trace/stop",
8075
8417
  parseBody: true,
@@ -8165,7 +8507,7 @@ var validateClip = (clip) => {
8165
8507
  };
8166
8508
 
8167
8509
  // ../argus-watcher/dist/http/routes/postScreenshot.js
8168
- var route20 = defineJsonRoute({
8510
+ var route21 = defineJsonRoute({
8169
8511
  method: "POST",
8170
8512
  path: "/screenshot",
8171
8513
  parseBody: true,
@@ -8677,7 +9019,7 @@ var countNodes = (nodes) => {
8677
9019
  };
8678
9020
 
8679
9021
  // ../argus-watcher/dist/http/routes/postSnapshot.js
8680
- var route21 = defineJsonRoute({
9022
+ var route22 = defineJsonRoute({
8681
9023
  method: "POST",
8682
9024
  path: "/snapshot",
8683
9025
  parseBody: true,
@@ -8854,7 +9196,7 @@ var locateRoutes = [
8854
9196
  ];
8855
9197
 
8856
9198
  // ../argus-watcher/dist/http/routes/postCodeList.js
8857
- var route22 = defineJsonRoute({
9199
+ var route23 = defineJsonRoute({
8858
9200
  method: "POST",
8859
9201
  path: "/code/list",
8860
9202
  parseBody: true,
@@ -8869,7 +9211,7 @@ var route22 = defineJsonRoute({
8869
9211
  });
8870
9212
 
8871
9213
  // ../argus-watcher/dist/http/routes/postCodeRead.js
8872
- var route23 = defineJsonRoute({
9214
+ var route24 = defineJsonRoute({
8873
9215
  method: "POST",
8874
9216
  path: "/code/read",
8875
9217
  parseBody: true,
@@ -8894,7 +9236,7 @@ var route23 = defineJsonRoute({
8894
9236
  });
8895
9237
 
8896
9238
  // ../argus-watcher/dist/http/routes/postCodeGrep.js
8897
- var route24 = defineJsonRoute({
9239
+ var route25 = defineJsonRoute({
8898
9240
  method: "POST",
8899
9241
  path: "/code/grep",
8900
9242
  parseBody: true,
@@ -8915,7 +9257,7 @@ var route24 = defineJsonRoute({
8915
9257
  });
8916
9258
 
8917
9259
  // ../argus-watcher/dist/http/routes/postCodeEdit.js
8918
- var route25 = defineJsonRoute({
9260
+ var route26 = defineJsonRoute({
8919
9261
  method: "POST",
8920
9262
  path: "/code/edit",
8921
9263
  parseBody: true,
@@ -9272,7 +9614,7 @@ var fillResolvedNodes = async (session, handles, value) => {
9272
9614
  return handles.length;
9273
9615
  };
9274
9616
  // ../argus-watcher/dist/http/routes/postDomTree.js
9275
- var route26 = defineJsonRoute({
9617
+ var route27 = defineJsonRoute({
9276
9618
  method: "POST",
9277
9619
  path: "/dom/tree",
9278
9620
  parseBody: true,
@@ -9295,7 +9637,7 @@ var route26 = defineJsonRoute({
9295
9637
  });
9296
9638
 
9297
9639
  // ../argus-watcher/dist/http/routes/postDomInfo.js
9298
- var route27 = defineJsonRoute({
9640
+ var route28 = defineJsonRoute({
9299
9641
  method: "POST",
9300
9642
  path: "/dom/info",
9301
9643
  parseBody: true,
@@ -9580,7 +9922,7 @@ var defineDomTargetRoute = (input) => defineJsonRoute({
9580
9922
  });
9581
9923
 
9582
9924
  // ../argus-watcher/dist/http/routes/postDomHover.js
9583
- var route28 = defineDomTargetRoute({
9925
+ var route29 = defineDomTargetRoute({
9584
9926
  path: "/dom/hover",
9585
9927
  endpoint: "dom/hover",
9586
9928
  action: "hover",
@@ -9591,7 +9933,7 @@ var route28 = defineDomTargetRoute({
9591
9933
  });
9592
9934
 
9593
9935
  // ../argus-watcher/dist/http/routes/postDomClick.js
9594
- var route29 = defineJsonRoute({
9936
+ var route30 = defineJsonRoute({
9595
9937
  method: "POST",
9596
9938
  path: "/dom/click",
9597
9939
  bodySchema: domClickRequestSchema,
@@ -9639,7 +9981,7 @@ var route29 = defineJsonRoute({
9639
9981
  });
9640
9982
 
9641
9983
  // ../argus-watcher/dist/http/routes/postDomDrag.js
9642
- var route30 = defineJsonRoute({
9984
+ var route31 = defineJsonRoute({
9643
9985
  method: "POST",
9644
9986
  path: "/dom/drag",
9645
9987
  bodySchema: domDragRequestSchema,
@@ -9856,7 +10198,7 @@ var dispatchKeydown = async (session, options) => {
9856
10198
  };
9857
10199
 
9858
10200
  // ../argus-watcher/dist/http/routes/postDomKeydown.js
9859
- var route31 = defineJsonRoute({
10201
+ var route32 = defineJsonRoute({
9860
10202
  method: "POST",
9861
10203
  path: "/dom/keydown",
9862
10204
  parseBody: true,
@@ -9906,7 +10248,7 @@ var route31 = defineJsonRoute({
9906
10248
 
9907
10249
  // ../argus-watcher/dist/http/routes/postDomAdd.js
9908
10250
  var validPositions = ["beforebegin", "afterbegin", "beforeend", "afterend"];
9909
- var route32 = defineJsonRoute({
10251
+ var route33 = defineJsonRoute({
9910
10252
  method: "POST",
9911
10253
  path: "/dom/add",
9912
10254
  parseBody: true,
@@ -9995,7 +10337,7 @@ var selectDomAddNodeIds = (allNodeIds, options) => {
9995
10337
  };
9996
10338
 
9997
10339
  // ../argus-watcher/dist/http/routes/postDomRemove.js
9998
- var route33 = defineJsonRoute({
10340
+ var route34 = defineJsonRoute({
9999
10341
  method: "POST",
10000
10342
  path: "/dom/remove",
10001
10343
  parseBody: true,
@@ -10017,7 +10359,7 @@ var route33 = defineJsonRoute({
10017
10359
 
10018
10360
  // ../argus-watcher/dist/http/routes/postDomModify.js
10019
10361
  var validTypes = ["attr", "class", "style", "text", "html"];
10020
- var route34 = defineJsonRoute({
10362
+ var route35 = defineJsonRoute({
10021
10363
  method: "POST",
10022
10364
  path: "/dom/modify",
10023
10365
  parseBody: true,
@@ -10048,7 +10390,7 @@ var route34 = defineJsonRoute({
10048
10390
  });
10049
10391
 
10050
10392
  // ../argus-watcher/dist/http/routes/postDomSetFile.js
10051
- var route35 = defineJsonRoute({
10393
+ var route36 = defineJsonRoute({
10052
10394
  method: "POST",
10053
10395
  path: "/dom/set-file",
10054
10396
  parseBody: true,
@@ -10086,7 +10428,7 @@ var route35 = defineJsonRoute({
10086
10428
  });
10087
10429
 
10088
10430
  // ../argus-watcher/dist/http/routes/postDomFocus.js
10089
- var route36 = defineDomTargetRoute({
10431
+ var route37 = defineDomTargetRoute({
10090
10432
  path: "/dom/focus",
10091
10433
  endpoint: "dom/focus",
10092
10434
  action: "focus",
@@ -10097,7 +10439,7 @@ var route36 = defineDomTargetRoute({
10097
10439
  });
10098
10440
 
10099
10441
  // ../argus-watcher/dist/http/routes/postDomFill.js
10100
- var route37 = defineDomTargetRoute({
10442
+ var route38 = defineDomTargetRoute({
10101
10443
  path: "/dom/fill",
10102
10444
  endpoint: "dom/fill",
10103
10445
  action: "fill",
@@ -10118,7 +10460,7 @@ var route37 = defineDomTargetRoute({
10118
10460
  });
10119
10461
 
10120
10462
  // ../argus-watcher/dist/http/routes/postDomScroll.js
10121
- var route38 = defineJsonRoute({
10463
+ var route39 = defineJsonRoute({
10122
10464
  method: "POST",
10123
10465
  path: "/dom/scroll",
10124
10466
  parseBody: true,
@@ -10177,7 +10519,7 @@ var getViewportSize = async (session) => {
10177
10519
  };
10178
10520
 
10179
10521
  // ../argus-watcher/dist/http/routes/postDomScrollTo.js
10180
- var route39 = defineJsonRoute({
10522
+ var route40 = defineJsonRoute({
10181
10523
  method: "POST",
10182
10524
  path: "/dom/scroll-to",
10183
10525
  parseBody: true,
@@ -10224,7 +10566,7 @@ var route39 = defineJsonRoute({
10224
10566
  });
10225
10567
 
10226
10568
  // ../argus-watcher/dist/http/routes/getEmulation.js
10227
- var route40 = defineJsonRoute({
10569
+ var route41 = defineJsonRoute({
10228
10570
  method: "GET",
10229
10571
  path: "/emulation",
10230
10572
  endpoint: "emulation",
@@ -10233,7 +10575,7 @@ var route40 = defineJsonRoute({
10233
10575
 
10234
10576
  // ../argus-watcher/dist/http/routes/postEmulation.js
10235
10577
  var validActions = ["set", "clear"];
10236
- var route41 = defineJsonRoute({
10578
+ var route42 = defineJsonRoute({
10237
10579
  method: "POST",
10238
10580
  path: "/emulation",
10239
10581
  parseBody: true,
@@ -10292,7 +10634,7 @@ function validateEmulationRequest(payload) {
10292
10634
  }
10293
10635
 
10294
10636
  // ../argus-watcher/dist/http/routes/getThrottle.js
10295
- var route42 = defineJsonRoute({
10637
+ var route43 = defineJsonRoute({
10296
10638
  method: "GET",
10297
10639
  path: "/throttle",
10298
10640
  endpoint: "throttle",
@@ -10301,7 +10643,7 @@ var route42 = defineJsonRoute({
10301
10643
 
10302
10644
  // ../argus-watcher/dist/http/routes/postThrottle.js
10303
10645
  var validActions2 = ["set", "clear"];
10304
- var route43 = defineJsonRoute({
10646
+ var route44 = defineJsonRoute({
10305
10647
  method: "POST",
10306
10648
  path: "/throttle",
10307
10649
  parseBody: true,
@@ -10329,7 +10671,7 @@ var route43 = defineJsonRoute({
10329
10671
  });
10330
10672
 
10331
10673
  // ../argus-watcher/dist/http/routes/getDialog.js
10332
- var route44 = defineJsonRoute({
10674
+ var route45 = defineJsonRoute({
10333
10675
  method: "GET",
10334
10676
  path: "/dialog",
10335
10677
  endpoint: "dialog/status",
@@ -10337,7 +10679,7 @@ var route44 = defineJsonRoute({
10337
10679
  });
10338
10680
 
10339
10681
  // ../argus-watcher/dist/http/routes/postDialog.js
10340
- var route45 = defineJsonRoute({
10682
+ var route46 = defineJsonRoute({
10341
10683
  method: "POST",
10342
10684
  path: "/dialog",
10343
10685
  parseBody: true,
@@ -10376,7 +10718,7 @@ var route45 = defineJsonRoute({
10376
10718
  });
10377
10719
 
10378
10720
  // ../argus-watcher/dist/http/routes/postVisibility.js
10379
- var route46 = defineJsonRoute({
10721
+ var route47 = defineJsonRoute({
10380
10722
  method: "POST",
10381
10723
  path: "/visibility",
10382
10724
  parseBody: true,
@@ -10493,7 +10835,7 @@ function validateStoragePayload(payload) {
10493
10835
  }
10494
10836
 
10495
10837
  // ../argus-watcher/dist/http/routes/postReload.js
10496
- var route47 = defineJsonRoute({
10838
+ var route48 = defineJsonRoute({
10497
10839
  method: "POST",
10498
10840
  path: "/reload",
10499
10841
  parseBody: true,
@@ -10507,7 +10849,7 @@ var route47 = defineJsonRoute({
10507
10849
  });
10508
10850
 
10509
10851
  // ../argus-watcher/dist/http/routes/postShutdown.js
10510
- var route48 = defineJsonRoute({
10852
+ var route49 = defineJsonRoute({
10511
10853
  method: "POST",
10512
10854
  path: "/shutdown",
10513
10855
  endpoint: "shutdown",
@@ -10522,7 +10864,7 @@ var route48 = defineJsonRoute({
10522
10864
  });
10523
10865
 
10524
10866
  // ../argus-watcher/dist/http/routes/getExtensionTabs.js
10525
- var route49 = defineJsonRoute({
10867
+ var route50 = defineJsonRoute({
10526
10868
  method: "GET",
10527
10869
  path: "/tabs",
10528
10870
  extensionOnly: true,
@@ -10543,7 +10885,7 @@ var route49 = defineJsonRoute({
10543
10885
  });
10544
10886
 
10545
10887
  // ../argus-watcher/dist/http/routes/getExtensionDiagnostics.js
10546
- var route50 = defineJsonRoute({
10888
+ var route51 = defineJsonRoute({
10547
10889
  method: "GET",
10548
10890
  path: "/extension/diagnostics",
10549
10891
  extensionOnly: true,
@@ -10557,7 +10899,7 @@ var route50 = defineJsonRoute({
10557
10899
  });
10558
10900
 
10559
10901
  // ../argus-watcher/dist/http/routes/getTargets.js
10560
- var route51 = defineJsonRoute({
10902
+ var route52 = defineJsonRoute({
10561
10903
  method: "GET",
10562
10904
  path: "/targets",
10563
10905
  extensionOnly: true,
@@ -10572,7 +10914,7 @@ var route51 = defineJsonRoute({
10572
10914
  });
10573
10915
 
10574
10916
  // ../argus-watcher/dist/http/routes/postAttach.js
10575
- var route52 = defineJsonRoute({
10917
+ var route53 = defineJsonRoute({
10576
10918
  method: "POST",
10577
10919
  path: "/attach",
10578
10920
  parseBody: true,
@@ -10595,7 +10937,7 @@ var route52 = defineJsonRoute({
10595
10937
  });
10596
10938
 
10597
10939
  // ../argus-watcher/dist/http/routes/postDetach.js
10598
- var route53 = defineJsonRoute({
10940
+ var route54 = defineJsonRoute({
10599
10941
  method: "POST",
10600
10942
  path: "/detach",
10601
10943
  parseBody: true,
@@ -10621,8 +10963,8 @@ var route53 = defineJsonRoute({
10621
10963
  var watcherRoutes = [
10622
10964
  route,
10623
10965
  route3,
10624
- route2,
10625
10966
  route4,
10967
+ route2,
10626
10968
  route5,
10627
10969
  route6,
10628
10970
  route7,
@@ -10632,22 +10974,22 @@ var watcherRoutes = [
10632
10974
  route11,
10633
10975
  route12,
10634
10976
  route13,
10635
- ...netMockRoutes,
10636
10977
  route14,
10978
+ ...netMockRoutes,
10979
+ route15,
10637
10980
  cookieGetRoute,
10638
10981
  cookieSetRoute,
10639
10982
  cookieDeleteRoute,
10640
10983
  cookieClearRoute,
10641
- route15,
10642
10984
  route16,
10643
10985
  route17,
10644
10986
  route18,
10645
10987
  route19,
10646
- ...recordRoutes,
10647
10988
  route20,
10989
+ ...recordRoutes,
10648
10990
  route21,
10649
- ...locateRoutes,
10650
10991
  route22,
10992
+ ...locateRoutes,
10651
10993
  route23,
10652
10994
  route24,
10653
10995
  route25,
@@ -10672,18 +11014,19 @@ var watcherRoutes = [
10672
11014
  route44,
10673
11015
  route45,
10674
11016
  route46,
10675
- ...storageRoutes,
10676
11017
  route47,
11018
+ ...storageRoutes,
10677
11019
  route48,
10678
11020
  route49,
10679
11021
  route50,
10680
11022
  route51,
10681
11023
  route52,
10682
- route53
11024
+ route53,
11025
+ route54
10683
11026
  ];
10684
11027
 
10685
11028
  // ../argus-watcher/dist/http/router.js
10686
- var routes = new Map(watcherRoutes.map((route54) => [`${route54.method} ${route54.path}`, route54]));
11029
+ var routes = new Map(watcherRoutes.map((route55) => [`${route55.method} ${route55.path}`, route55]));
10687
11030
  var dispatch = (req, res, url, ctx) => {
10688
11031
  const entry = routes.get(`${req.method} ${url.pathname}`);
10689
11032
  if (!entry || entry.extensionOnly && !ctx.sourceHandle) {
@@ -11347,100 +11690,6 @@ var formatWatcherError = (error) => {
11347
11690
  import os3 from "node:os";
11348
11691
  import path7 from "node:path";
11349
11692
 
11350
- // ../argus-watcher/dist/buffer/LogBuffer.js
11351
- class LogBuffer {
11352
- maxSize;
11353
- events = [];
11354
- nextId = 1;
11355
- waiters = [];
11356
- constructor(maxSize) {
11357
- this.maxSize = maxSize;
11358
- }
11359
- add(event) {
11360
- const entry = {
11361
- ...event,
11362
- id: this.nextId++
11363
- };
11364
- this.events.push(entry);
11365
- this.trim();
11366
- this.flushWaiters();
11367
- return entry;
11368
- }
11369
- listAfter(after, filters, limit) {
11370
- const filtered = this.events.filter((event) => event.id > after && matchesFilters(event, filters));
11371
- return filtered.slice(0, limit);
11372
- }
11373
- getCursor() {
11374
- return this.nextId - 1;
11375
- }
11376
- waitForAfter(after, filters, limit, timeoutMs) {
11377
- const immediate = this.listAfter(after, filters, limit);
11378
- if (immediate.length > 0) {
11379
- return Promise.resolve(immediate);
11380
- }
11381
- return new Promise((resolve) => {
11382
- const timer = setTimeout(() => {
11383
- this.waiters = this.waiters.filter((waiter) => waiter.timer !== timer);
11384
- resolve([]);
11385
- }, timeoutMs);
11386
- this.waiters.push({ after, filters, limit, resolve, timer });
11387
- });
11388
- }
11389
- getStats() {
11390
- if (this.events.length === 0) {
11391
- return { size: this.maxSize, count: 0, minId: null, maxId: null };
11392
- }
11393
- return {
11394
- size: this.maxSize,
11395
- count: this.events.length,
11396
- minId: this.events[0]?.id ?? null,
11397
- maxId: this.events[this.events.length - 1]?.id ?? null
11398
- };
11399
- }
11400
- trim() {
11401
- if (this.events.length <= this.maxSize) {
11402
- return;
11403
- }
11404
- this.events = this.events.slice(this.events.length - this.maxSize);
11405
- }
11406
- flushWaiters() {
11407
- if (this.waiters.length === 0) {
11408
- return;
11409
- }
11410
- const remaining = [];
11411
- for (const waiter of this.waiters) {
11412
- const events = this.listAfter(waiter.after, waiter.filters, waiter.limit);
11413
- if (events.length > 0) {
11414
- clearTimeout(waiter.timer);
11415
- waiter.resolve(events);
11416
- continue;
11417
- }
11418
- remaining.push(waiter);
11419
- }
11420
- this.waiters = remaining;
11421
- }
11422
- }
11423
- var matchesFilters = (event, filters) => {
11424
- if (filters.sinceTs && event.ts < filters.sinceTs) {
11425
- return false;
11426
- }
11427
- if (filters.levels && filters.levels.length > 0 && !filters.levels.includes(event.level)) {
11428
- return false;
11429
- }
11430
- if (filters.source && !event.source.toLowerCase().includes(filters.source.toLowerCase())) {
11431
- return false;
11432
- }
11433
- if (filters.match && filters.match.length > 0) {
11434
- for (const pattern of filters.match) {
11435
- if (pattern.test(event.text)) {
11436
- return true;
11437
- }
11438
- }
11439
- return false;
11440
- }
11441
- return true;
11442
- };
11443
-
11444
11693
  // ../argus-watcher/dist/buffer/NetBuffer.js
11445
11694
  class NetBuffer {
11446
11695
  maxSize;
@@ -20030,9 +20279,11 @@ var previewLogEvent = (event) => ({
20030
20279
 
20031
20280
  // dist/watchers/queryParams.js
20032
20281
  var appendAfterLimitParams = (params, options) => {
20033
- const after = parseNumber(options.after);
20034
- if (after != null) {
20035
- params.set("after", String(after));
20282
+ if (options.after?.trim()) {
20283
+ params.set("after", options.after.trim());
20284
+ }
20285
+ if (options.sinceEpoch?.trim()) {
20286
+ params.set("sinceEpoch", options.sinceEpoch.trim());
20036
20287
  }
20037
20288
  const limit = parseNumber(options.limit);
20038
20289
  if (limit != null) {
@@ -20171,7 +20422,11 @@ var appendRepeatedParams = (params, key, values) => {
20171
20422
  // dist/commands/logs.js
20172
20423
  var runLogCursor = defineWatcherCommand({
20173
20424
  build: () => ({ path: "/logs/cursor", timeoutMs: 5000 }),
20174
- formatHuman: (response, { output }) => output.writeHuman(String(response.cursor))
20425
+ formatHuman: (response, { output }) => output.writeHuman(response.cursor)
20426
+ });
20427
+ var runLogEpoch = defineWatcherCommand({
20428
+ build: () => ({ path: "/logs/epoch", timeoutMs: 5000 }),
20429
+ formatHuman: (response, { output }) => output.writeHuman(response.epoch)
20175
20430
  });
20176
20431
  var runLogs = defineWatcherCommand({
20177
20432
  isJson: (options) => options.jsonFull === true,
@@ -20214,7 +20469,14 @@ var runTail = async (id, options) => {
20214
20469
  if (!resolved)
20215
20470
  return;
20216
20471
  const { watcher } = resolved;
20217
- let after = parseNumber(options.after) ?? 0;
20472
+ const afterEpoch = options.after?.trim() || undefined;
20473
+ const sinceEpoch = options.sinceEpoch?.trim() || undefined;
20474
+ if (afterEpoch && sinceEpoch) {
20475
+ output.writeWarn("Use either --after or --since-epoch, not both.");
20476
+ process.exitCode = 2;
20477
+ return;
20478
+ }
20479
+ let position = afterEpoch ?? sinceEpoch;
20218
20480
  const timeoutMs = parseNumber(options.timeout) ?? 25000;
20219
20481
  const limit = parseNumber(options.limit);
20220
20482
  let running = true;
@@ -20225,7 +20487,9 @@ var runTail = async (id, options) => {
20225
20487
  process.on("SIGTERM", stop);
20226
20488
  while (running) {
20227
20489
  const params = new URLSearchParams;
20228
- params.set("after", String(after));
20490
+ if (position) {
20491
+ params.set(sinceEpoch ? "sinceEpoch" : "after", position);
20492
+ }
20229
20493
  params.set("timeoutMs", String(timeoutMs));
20230
20494
  if (limit != null) {
20231
20495
  params.set("limit", String(limit));
@@ -20245,25 +20509,23 @@ var runTail = async (id, options) => {
20245
20509
  process.exitCode = 1;
20246
20510
  return;
20247
20511
  }
20248
- if (response.events.length > 0) {
20249
- for (const event of response.events) {
20250
- if (options.jsonFull) {
20251
- output.writeJsonLine({ watcher: watcher.id, event });
20252
- continue;
20253
- }
20254
- if (options.json) {
20255
- const previewEvent = previewLogEvent(event);
20256
- output.writeJsonLine({ watcher: watcher.id, event: previewEvent });
20257
- continue;
20258
- }
20259
- output.writeHuman(formatLogEvent(event, {
20260
- includeTimestamps: watcher.includeTimestamps
20261
- }));
20262
- }
20512
+ for (const event of response.events) {
20513
+ writeTailEvent(event, watcher, options, output);
20263
20514
  }
20264
- after = response.nextAfter;
20515
+ position = response.nextCursor;
20265
20516
  }
20266
20517
  };
20518
+ var writeTailEvent = (event, watcher, options, output) => {
20519
+ if (options.jsonFull) {
20520
+ output.writeJsonLine({ watcher: watcher.id, event });
20521
+ return;
20522
+ }
20523
+ if (options.json) {
20524
+ output.writeJsonLine({ watcher: watcher.id, event: previewLogEvent(event) });
20525
+ return;
20526
+ }
20527
+ output.writeHuman(formatLogEvent(event, { includeTimestamps: watcher.includeTimestamps }));
20528
+ };
20267
20529
 
20268
20530
  // dist/cli/register/logsCommands.js
20269
20531
  var sharedFilterOptions = [
@@ -20290,7 +20552,8 @@ var logsCommands = [
20290
20552
  options: [
20291
20553
  ...sharedFilterOptions,
20292
20554
  { flags: "--since <duration>", description: "Filter by time window (e.g. 10m, 2h, 30s)" },
20293
- { flags: "--after <id>", description: "Only return events after this id" },
20555
+ { flags: "--after <cursor>", description: "Only return events after this opaque cursor" },
20556
+ { flags: "--since-epoch <epoch>", description: "Only return events after this opaque epoch" },
20294
20557
  { flags: "--limit <count>", description: "Maximum number of events" },
20295
20558
  { flags: "--json", description: "Output bounded JSON preview for automation" },
20296
20559
  { flags: "--json-full", description: "Output full JSON (can be very large)" }
@@ -20302,6 +20565,16 @@ var logsCommands = [
20302
20565
  await runLogs(id, options);
20303
20566
  },
20304
20567
  subcommands: [
20568
+ {
20569
+ name: "epoch",
20570
+ description: "Return an opaque watcher-session log epoch without downloading events",
20571
+ arguments: [{ flags: "[id]", description: "Watcher id to query" }],
20572
+ options: [{ flags: "--json", description: "Output one JSON document for automation" }],
20573
+ examples: ["argus logs epoch app", "argus logs epoch app --json"],
20574
+ action: async (id, options, command) => {
20575
+ await runLogEpoch(id, command.optsWithGlobals?.() ?? options);
20576
+ }
20577
+ },
20305
20578
  {
20306
20579
  name: "cursor",
20307
20580
  description: "Return the current log cursor without downloading events",
@@ -20318,7 +20591,8 @@ var logsCommands = [
20318
20591
  arguments: [{ flags: "[id]", description: "Watcher id to follow" }],
20319
20592
  options: [
20320
20593
  ...sharedFilterOptions,
20321
- { flags: "--after <id>", description: "Start after this event id" },
20594
+ { flags: "--after <cursor>", description: "Start after this opaque cursor" },
20595
+ { flags: "--since-epoch <epoch>", description: "Start after this opaque epoch" },
20322
20596
  { flags: "--limit <count>", description: "Maximum number of events per poll" },
20323
20597
  { flags: "--timeout <ms>", description: "Long-poll timeout in milliseconds" },
20324
20598
  { flags: "--json", description: "Output bounded newline-delimited JSON events" },
@@ -21105,9 +21379,6 @@ var wrapExpressionWithArgs = (source, args) => {
21105
21379
  return `const args = Object.freeze(${JSON.stringify(args)});
21106
21380
  ${source}`;
21107
21381
  };
21108
- var sleep5 = async (durationMs) => {
21109
- await new Promise((resolve2) => setTimeout(resolve2, durationMs));
21110
- };
21111
21382
  var formatException = (response) => {
21112
21383
  if (!response.exception) {
21113
21384
  return "";
@@ -23934,60 +24205,89 @@ var authCommands = [
23934
24205
  ]
23935
24206
  }
23936
24207
  ];
23937
-
23938
- // dist/commands/evalPolling.js
24208
+ // ../argus-client/dist/eval/pollEval.js
23939
24209
  var pollEval = async (input) => {
23940
- let running = true;
23941
- const stop = () => {
23942
- running = false;
23943
- };
23944
- process.on("SIGINT", stop);
23945
- process.on("SIGTERM", stop);
23946
- try {
23947
- const startTime = Date.now();
23948
- let iteration = 0;
23949
- while (running) {
23950
- if (input.totalTimeoutMs != null) {
23951
- const elapsed = Date.now() - startTime;
23952
- if (elapsed >= input.totalTimeoutMs) {
23953
- return { kind: "timeout", elapsedMs: elapsed };
23954
- }
23955
- }
23956
- iteration += 1;
23957
- const result = await evalWithRetries({
23958
- watcher: input.watcher,
23959
- expression: input.expression,
23960
- args: input.args,
23961
- awaitPromise: input.awaitPromise,
23962
- returnByValue: input.returnByValue,
23963
- timeoutMs: input.timeoutMs,
23964
- failOnException: input.failOnException,
23965
- retryCount: input.retryCount,
23966
- scenario: input.scenario
23967
- });
23968
- if (!result.ok) {
23969
- return { kind: "eval-error", failure: result };
24210
+ const startTime = Date.now();
24211
+ let iteration = 0;
24212
+ while (!input.signal?.aborted) {
24213
+ if (input.totalTimeoutMs != null) {
24214
+ const elapsedMs = Date.now() - startTime;
24215
+ if (elapsedMs >= input.totalTimeoutMs) {
24216
+ return { kind: "timeout", elapsedMs };
23970
24217
  }
23971
- const context = { response: result.response, iteration, attempt: result.attempt };
23972
- await input.onResult?.(result.response, context);
23973
- const stopResult = input.shouldStop?.(context);
23974
- if (stopResult) {
23975
- if (!stopResult.ok) {
23976
- return { kind: "condition-error", error: stopResult.error };
23977
- }
23978
- if (stopResult.matched) {
23979
- return { kind: "matched", response: result.response, iteration, attempt: result.attempt };
23980
- }
24218
+ }
24219
+ iteration += 1;
24220
+ const result = await input.runEval(iteration);
24221
+ if (!result.ok) {
24222
+ return { kind: "eval-error", failure: result.failure };
24223
+ }
24224
+ const context = { response: result.response, iteration, attempt: result.attempt };
24225
+ await input.onResult?.(result.response, context);
24226
+ const decision = input.shouldStop?.(context);
24227
+ if (decision) {
24228
+ if (!decision.ok) {
24229
+ return { kind: "condition-error", error: decision.error };
23981
24230
  }
23982
- if (input.count != null && iteration >= input.count) {
23983
- return { kind: "exhausted", iterations: iteration };
24231
+ if (decision.matched) {
24232
+ return { kind: "matched", response: result.response, iteration, attempt: result.attempt };
23984
24233
  }
23985
- await sleep5(input.intervalMs);
23986
24234
  }
23987
- return { kind: "interrupted" };
24235
+ if (input.count != null && iteration >= input.count) {
24236
+ return { kind: "exhausted", iterations: iteration };
24237
+ }
24238
+ await sleep5(input.intervalMs, input.signal);
24239
+ }
24240
+ return { kind: "interrupted" };
24241
+ };
24242
+ var sleep5 = async (durationMs, signal) => {
24243
+ if (signal?.aborted) {
24244
+ return;
24245
+ }
24246
+ await new Promise((resolve2) => {
24247
+ const finish = () => {
24248
+ clearTimeout(timer);
24249
+ signal?.removeEventListener("abort", finish);
24250
+ resolve2();
24251
+ };
24252
+ const timer = setTimeout(finish, durationMs);
24253
+ signal?.addEventListener("abort", finish, { once: true });
24254
+ });
24255
+ };
24256
+ // dist/commands/evalPolling.js
24257
+ var pollEval2 = async (input) => {
24258
+ const controller = new AbortController;
24259
+ const abort = () => controller.abort();
24260
+ process.on("SIGINT", abort);
24261
+ process.on("SIGTERM", abort);
24262
+ try {
24263
+ return await pollEval({
24264
+ intervalMs: input.intervalMs,
24265
+ count: input.count,
24266
+ totalTimeoutMs: input.totalTimeoutMs,
24267
+ signal: controller.signal,
24268
+ shouldStop: input.shouldStop,
24269
+ onResult: input.onResult,
24270
+ runEval: async () => {
24271
+ const result = await evalWithRetries({
24272
+ watcher: input.watcher,
24273
+ expression: input.expression,
24274
+ args: input.args,
24275
+ awaitPromise: input.awaitPromise,
24276
+ returnByValue: input.returnByValue,
24277
+ timeoutMs: input.timeoutMs,
24278
+ failOnException: input.failOnException,
24279
+ retryCount: input.retryCount,
24280
+ scenario: input.scenario
24281
+ });
24282
+ if (!result.ok) {
24283
+ return { ok: false, failure: result, attempt: result.attempt };
24284
+ }
24285
+ return { ok: true, response: result.response, attempt: result.attempt };
24286
+ }
24287
+ });
23988
24288
  } finally {
23989
- process.off("SIGINT", stop);
23990
- process.off("SIGTERM", stop);
24289
+ process.off("SIGINT", abort);
24290
+ process.off("SIGTERM", abort);
23991
24291
  }
23992
24292
  };
23993
24293
 
@@ -24067,7 +24367,7 @@ var runEval = async (id, rawExpression, options) => {
24067
24367
  await emitter.emitSuccess(singleResult.response, false);
24068
24368
  return;
24069
24369
  }
24070
- const pollResult = await pollEval({
24370
+ const pollResult = await pollEval2({
24071
24371
  watcher,
24072
24372
  expression: prepared.expression,
24073
24373
  args: prepared.args,
@@ -24181,7 +24481,7 @@ var runEvalUntil = async (id, rawExpression, options) => {
24181
24481
  if (!resolved)
24182
24482
  return;
24183
24483
  const { watcher } = resolved;
24184
- const pollResult = await pollEval({
24484
+ const pollResult = await pollEval2({
24185
24485
  watcher,
24186
24486
  expression: prepared.expression,
24187
24487
  args: prepared.args,