@vforsh/argus 0.1.9 → 0.1.11

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 (117) hide show
  1. package/dist/.tsbuildinfo +1 -1
  2. package/dist/argus.js +1562 -1230
  3. package/dist/bin.js +2 -0
  4. package/dist/bin.js.map +1 -1
  5. package/dist/cdp/sendCdpCommand.d.ts +11 -0
  6. package/dist/cdp/sendCdpCommand.d.ts.map +1 -0
  7. package/dist/cdp/sendCdpCommand.js +103 -0
  8. package/dist/cdp/sendCdpCommand.js.map +1 -0
  9. package/dist/cli/program.js +1 -1
  10. package/dist/cli/program.js.map +1 -1
  11. package/dist/cli/register/registerAuth.d.ts +3 -0
  12. package/dist/cli/register/registerAuth.d.ts.map +1 -0
  13. package/dist/cli/register/registerAuth.js +29 -0
  14. package/dist/cli/register/registerAuth.js.map +1 -0
  15. package/dist/commands/auth.d.ts +22 -0
  16. package/dist/commands/auth.d.ts.map +1 -0
  17. package/dist/commands/auth.js +168 -0
  18. package/dist/commands/auth.js.map +1 -0
  19. package/dist/commands/chrome.d.ts.map +1 -1
  20. package/dist/commands/chrome.js +1 -99
  21. package/dist/commands/chrome.js.map +1 -1
  22. package/dist/commands/chromeStart.d.ts.map +1 -1
  23. package/dist/commands/chromeStart.js +14 -44
  24. package/dist/commands/chromeStart.js.map +1 -1
  25. package/dist/commands/list.d.ts.map +1 -1
  26. package/dist/commands/list.js +3 -5
  27. package/dist/commands/list.js.map +1 -1
  28. package/dist/commands/logs.d.ts.map +1 -1
  29. package/dist/commands/logs.js +10 -57
  30. package/dist/commands/logs.js.map +1 -1
  31. package/dist/commands/net.d.ts.map +1 -1
  32. package/dist/commands/net.js +8 -22
  33. package/dist/commands/net.js.map +1 -1
  34. package/dist/commands/netTail.d.ts.map +1 -1
  35. package/dist/commands/netTail.js +11 -25
  36. package/dist/commands/netTail.js.map +1 -1
  37. package/dist/commands/page.d.ts.map +1 -1
  38. package/dist/commands/page.js +1 -99
  39. package/dist/commands/page.js.map +1 -1
  40. package/dist/commands/start.d.ts.map +1 -1
  41. package/dist/commands/start.js +7 -46
  42. package/dist/commands/start.js.map +1 -1
  43. package/dist/commands/startShared.d.ts +32 -0
  44. package/dist/commands/startShared.d.ts.map +1 -0
  45. package/dist/commands/startShared.js +74 -0
  46. package/dist/commands/startShared.js.map +1 -0
  47. package/dist/commands/tail.d.ts.map +1 -1
  48. package/dist/commands/tail.js +8 -43
  49. package/dist/commands/tail.js.map +1 -1
  50. package/dist/commands/trace.d.ts.map +1 -1
  51. package/dist/commands/trace.js +7 -9
  52. package/dist/commands/trace.js.map +1 -1
  53. package/dist/commands/watcherNativeHost.d.ts.map +1 -1
  54. package/dist/commands/watcherNativeHost.js +1 -0
  55. package/dist/commands/watcherNativeHost.js.map +1 -1
  56. package/dist/commands/watcherStart.d.ts.map +1 -1
  57. package/dist/commands/watcherStart.js +11 -51
  58. package/dist/commands/watcherStart.js.map +1 -1
  59. package/dist/eval/evalClient.js +5 -14
  60. package/dist/eval/evalClient.js.map +1 -1
  61. package/dist/httpClient.d.ts +1 -12
  62. package/dist/httpClient.d.ts.map +1 -1
  63. package/dist/httpClient.js +1 -84
  64. package/dist/httpClient.js.map +1 -1
  65. package/dist/runtime-code/strings.js +9 -1
  66. package/dist/runtime-code/strings.js.map +1 -1
  67. package/dist/watchers/queryParams.d.ts +34 -0
  68. package/dist/watchers/queryParams.d.ts.map +1 -0
  69. package/dist/watchers/queryParams.js +80 -0
  70. package/dist/watchers/queryParams.js.map +1 -0
  71. package/dist/watchers/requestWatcher.d.ts +3 -0
  72. package/dist/watchers/requestWatcher.d.ts.map +1 -1
  73. package/dist/watchers/requestWatcher.js +15 -9
  74. package/dist/watchers/requestWatcher.js.map +1 -1
  75. package/dist/watchers/resolveWatcher.js +2 -3
  76. package/dist/watchers/resolveWatcher.js.map +1 -1
  77. package/package.json +3 -2
  78. package/dist/commands/contexts.d.ts +0 -7
  79. package/dist/commands/contexts.d.ts.map +0 -1
  80. package/dist/commands/contexts.js +0 -54
  81. package/dist/commands/contexts.js.map +0 -1
  82. package/dist/commands/domDiff.d.ts +0 -43
  83. package/dist/commands/domDiff.d.ts.map +0 -1
  84. package/dist/commands/domDiff.js +0 -279
  85. package/dist/commands/domDiff.js.map +0 -1
  86. package/dist/commands/domSubmit.d.ts +0 -10
  87. package/dist/commands/domSubmit.d.ts.map +0 -1
  88. package/dist/commands/domSubmit.js +0 -78
  89. package/dist/commands/domSubmit.js.map +0 -1
  90. package/dist/commands/extension/attach.d.ts +0 -8
  91. package/dist/commands/extension/attach.d.ts.map +0 -1
  92. package/dist/commands/extension/attach.js +0 -171
  93. package/dist/commands/extension/attach.js.map +0 -1
  94. package/dist/commands/extension/detach.d.ts +0 -6
  95. package/dist/commands/extension/detach.d.ts.map +0 -1
  96. package/dist/commands/extension/detach.js +0 -132
  97. package/dist/commands/extension/detach.js.map +0 -1
  98. package/dist/commands/extension/targets.d.ts +0 -13
  99. package/dist/commands/extension/targets.d.ts.map +0 -1
  100. package/dist/commands/extension/targets.js +0 -77
  101. package/dist/commands/extension/targets.js.map +0 -1
  102. package/dist/commands/frames.d.ts +0 -7
  103. package/dist/commands/frames.d.ts.map +0 -1
  104. package/dist/commands/frames.js +0 -90
  105. package/dist/commands/frames.js.map +0 -1
  106. package/dist/frame/frameSelector.d.ts +0 -14
  107. package/dist/frame/frameSelector.d.ts.map +0 -1
  108. package/dist/frame/frameSelector.js +0 -31
  109. package/dist/frame/frameSelector.js.map +0 -1
  110. package/dist/output/domDiff.d.ts +0 -14
  111. package/dist/output/domDiff.d.ts.map +0 -1
  112. package/dist/output/domDiff.js +0 -151
  113. package/dist/output/domDiff.js.map +0 -1
  114. package/dist/throttle/networkPresets.d.ts +0 -6
  115. package/dist/throttle/networkPresets.d.ts.map +0 -1
  116. package/dist/throttle/networkPresets.js +0 -24
  117. package/dist/throttle/networkPresets.js.map +0 -1
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);
@@ -2145,7 +2131,7 @@ var {
2145
2131
  // dist/cli/program.js
2146
2132
  function createProgram() {
2147
2133
  const program2 = new Command;
2148
- program2.name("argus").description("Argus CLI for local watcher servers").version("0.1.0").configureOutput({
2134
+ program2.name("argus").description("Argus CLI for local watcher servers").version("0.1.11").configureOutput({
2149
2135
  outputError: (str, write) => write(str)
2150
2136
  }).showSuggestionAfterError(true).exitOverride((error) => {
2151
2137
  if (error.code === "commander.helpDisplayed" || error.code === "commander.version") {
@@ -2595,38 +2581,32 @@ var findTextPatternMatch = (line, pattern) => {
2595
2581
  length: Math.max(1, matched[0]?.length ?? 0)
2596
2582
  };
2597
2583
  };
2598
- // dist/registry.js
2599
- var loadRegistry = async () => {
2600
- const { registry: registry2, warnings } = await readRegistry();
2601
- for (const warning of warnings) {
2602
- console.error(warning);
2584
+ // ../argus-core/dist/auth/cookies.js
2585
+ var TRACKING_COOKIE_PATTERNS = [/^_ga/i, /^_gid$/i, /^_ym/i, /^_fbp$/i, /^_hj/i, /^amplitude/i, /^mp_/i];
2586
+ var normalizeCookieDomainFilter = (domain) => {
2587
+ if (!domain) {
2588
+ return null;
2603
2589
  }
2604
- return registry2;
2590
+ const normalized = normalizeCookieDomain(domain);
2591
+ return normalized || null;
2605
2592
  };
2606
- var pruneRegistry = async (ttlMs = DEFAULT_TTL_MS) => {
2607
- return updateRegistry((registry2) => {
2608
- const { registry: pruned } = pruneStaleWatchers(registry2, Date.now(), ttlMs);
2609
- return pruned;
2610
- });
2611
- };
2612
- var removeWatcherAndPersist = async (id) => {
2613
- return updateRegistry((registry2) => removeWatcherEntry(registry2, id));
2593
+ var matchesCookieDomain = (cookieDomain, domain) => {
2594
+ if (!domain) {
2595
+ return true;
2596
+ }
2597
+ const normalizedDomain = normalizeCookieDomain(cookieDomain);
2598
+ return normalizedDomain === domain || normalizedDomain.endsWith(`.${domain}`);
2614
2599
  };
2615
- var removeWatchersAndPersist = async (ids) => {
2616
- if (ids.length === 0) {
2617
- const { registry: registry2 } = await readRegistry();
2618
- return registry2;
2600
+ var getOriginHost = (origin) => {
2601
+ try {
2602
+ return new URL(origin).hostname;
2603
+ } catch {
2604
+ return null;
2619
2605
  }
2620
- return updateRegistry((registry2) => {
2621
- let next = registry2;
2622
- for (const id of ids) {
2623
- next = removeWatcherEntry(next, id);
2624
- }
2625
- return next;
2626
- });
2627
2606
  };
2628
-
2629
- // dist/httpClient.js
2607
+ var isTrackingCookieName = (name) => TRACKING_COOKIE_PATTERNS.some((pattern) => pattern.test(name));
2608
+ var normalizeCookieDomain = (domain) => domain.trim().toLowerCase().replace(/^\./, "");
2609
+ // ../argus-core/dist/http/fetch.js
2630
2610
  var fetchJson = async (url, options = {}) => {
2631
2611
  const controller = new AbortController;
2632
2612
  const timeoutMs = options.timeoutMs ?? 5000;
@@ -2656,24 +2636,6 @@ var fetchJson = async (url, options = {}) => {
2656
2636
  clearTimeout(timer);
2657
2637
  }
2658
2638
  };
2659
- var isAbortError = (error) => {
2660
- if (!error || typeof error !== "object" || !("name" in error)) {
2661
- return false;
2662
- }
2663
- return error.name === "AbortError";
2664
- };
2665
- var extractErrorMessage = async (response) => {
2666
- try {
2667
- const body = await response.json();
2668
- if (body && typeof body === "object" && "error" in body) {
2669
- const error = body.error;
2670
- if (error && typeof error === "object" && "message" in error) {
2671
- return error.message;
2672
- }
2673
- }
2674
- } catch {}
2675
- return null;
2676
- };
2677
2639
  var fetchText = async (url, options = {}) => {
2678
2640
  const controller = new AbortController;
2679
2641
  const timeoutMs = options.timeoutMs ?? 5000;
@@ -2699,50 +2661,53 @@ var fetchText = async (url, options = {}) => {
2699
2661
  clearTimeout(timer);
2700
2662
  }
2701
2663
  };
2702
-
2703
- // dist/cli/parse.js
2704
- var formatError = (error) => {
2705
- if (!error) {
2706
- return "unknown error";
2707
- }
2708
- if (error instanceof Error) {
2709
- return error.message;
2664
+ var isAbortError = (error) => {
2665
+ if (!error || typeof error !== "object" || !("name" in error)) {
2666
+ return false;
2710
2667
  }
2711
- return String(error);
2668
+ return error.name === "AbortError";
2712
2669
  };
2713
- var parseNumber = (value) => {
2714
- if (!value) {
2715
- return;
2716
- }
2717
- const parsed = Number(value);
2718
- if (!Number.isFinite(parsed)) {
2719
- return;
2720
- }
2721
- return parsed;
2670
+ var extractErrorMessage = async (response) => {
2671
+ try {
2672
+ const body = await response.json();
2673
+ if (body && typeof body === "object" && "error" in body) {
2674
+ const error = body.error;
2675
+ if (error && typeof error === "object" && "message" in error) {
2676
+ return error.message;
2677
+ }
2678
+ }
2679
+ } catch {}
2680
+ return null;
2722
2681
  };
2723
- var parsePositiveInt = (value, options) => {
2724
- if (value === undefined) {
2725
- return;
2726
- }
2727
- const parsed = Number(value);
2728
- if (!Number.isFinite(parsed) || !Number.isInteger(parsed)) {
2729
- return;
2730
- }
2731
- const min = options?.allowZero ? 0 : 1;
2732
- if (parsed < min) {
2733
- return;
2682
+ // dist/registry.js
2683
+ var loadRegistry = async () => {
2684
+ const { registry: registry2, warnings } = await readRegistry();
2685
+ for (const warning of warnings) {
2686
+ console.error(warning);
2734
2687
  }
2735
- return parsed;
2688
+ return registry2;
2736
2689
  };
2737
- var normalizeQueryValue = (value) => {
2738
- if (value == null) {
2739
- return;
2740
- }
2741
- const trimmed = value.trim();
2742
- if (!trimmed) {
2743
- return;
2690
+ var pruneRegistry = async (ttlMs = DEFAULT_TTL_MS) => {
2691
+ return updateRegistry((registry2) => {
2692
+ const { registry: pruned } = pruneStaleWatchers(registry2, Date.now(), ttlMs);
2693
+ return pruned;
2694
+ });
2695
+ };
2696
+ var removeWatcherAndPersist = async (id) => {
2697
+ return updateRegistry((registry2) => removeWatcherEntry(registry2, id));
2698
+ };
2699
+ var removeWatchersAndPersist = async (ids) => {
2700
+ if (ids.length === 0) {
2701
+ const { registry: registry2 } = await readRegistry();
2702
+ return registry2;
2744
2703
  }
2745
- return trimmed;
2704
+ return updateRegistry((registry2) => {
2705
+ let next = registry2;
2706
+ for (const id of ids) {
2707
+ next = removeWatcherEntry(next, id);
2708
+ }
2709
+ return next;
2710
+ });
2746
2711
  };
2747
2712
 
2748
2713
  // dist/output/format.js
@@ -2836,6 +2801,162 @@ var createOutput = (options) => {
2836
2801
  writeWarn
2837
2802
  };
2838
2803
  };
2804
+ // dist/cli/parse.js
2805
+ var formatError = (error) => {
2806
+ if (!error) {
2807
+ return "unknown error";
2808
+ }
2809
+ if (error instanceof Error) {
2810
+ return error.message;
2811
+ }
2812
+ return String(error);
2813
+ };
2814
+ var parseNumber = (value) => {
2815
+ if (!value) {
2816
+ return;
2817
+ }
2818
+ const parsed = Number(value);
2819
+ if (!Number.isFinite(parsed)) {
2820
+ return;
2821
+ }
2822
+ return parsed;
2823
+ };
2824
+ var parsePositiveInt = (value, options) => {
2825
+ if (value === undefined) {
2826
+ return;
2827
+ }
2828
+ const parsed = Number(value);
2829
+ if (!Number.isFinite(parsed) || !Number.isInteger(parsed)) {
2830
+ return;
2831
+ }
2832
+ const min = options?.allowZero ? 0 : 1;
2833
+ if (parsed < min) {
2834
+ return;
2835
+ }
2836
+ return parsed;
2837
+ };
2838
+ var normalizeQueryValue = (value) => {
2839
+ if (value == null) {
2840
+ return;
2841
+ }
2842
+ const trimmed = value.trim();
2843
+ if (!trimmed) {
2844
+ return;
2845
+ }
2846
+ return trimmed;
2847
+ };
2848
+
2849
+ // dist/watchers/resolveWatcher.js
2850
+ var resolveWatcher = async (input) => {
2851
+ let registry2;
2852
+ try {
2853
+ registry2 = await pruneRegistry();
2854
+ } catch (error) {
2855
+ return { ok: false, error: `Failed to load registry: ${error instanceof Error ? error.message : error}`, exitCode: 1 };
2856
+ }
2857
+ const watchers = Object.values(registry2.watchers);
2858
+ if (input.id) {
2859
+ const watcher = registry2.watchers[input.id];
2860
+ if (!watcher) {
2861
+ return { ok: false, error: `Watcher not found: ${input.id}`, exitCode: 2, candidates: watchers };
2862
+ }
2863
+ return { ok: true, watcher, registry: registry2 };
2864
+ }
2865
+ if (watchers.length === 0) {
2866
+ return { ok: false, error: "Watcher id required.", exitCode: 2 };
2867
+ }
2868
+ const cwd = process.cwd();
2869
+ const cwdMatches = watchers.filter((watcher) => watcher.cwd === cwd);
2870
+ if (cwdMatches.length === 1) {
2871
+ return { ok: true, watcher: cwdMatches[0], registry: registry2 };
2872
+ }
2873
+ if (cwdMatches.length > 1) {
2874
+ return { ok: false, error: "Watcher id required.", exitCode: 2, candidates: cwdMatches };
2875
+ }
2876
+ const reachability = await Promise.all(watchers.map(async (watcher) => ({
2877
+ watcher,
2878
+ status: await checkWatcherStatus(watcher)
2879
+ })));
2880
+ const reachable = reachability.filter((entry) => entry.status.ok);
2881
+ if (reachable.length === 1) {
2882
+ return { ok: true, watcher: reachable[0].watcher, registry: registry2 };
2883
+ }
2884
+ return { ok: false, error: "Watcher id required.", exitCode: 2, candidates: watchers };
2885
+ };
2886
+ var checkWatcherStatus = async (watcher) => {
2887
+ try {
2888
+ const status = await fetchWatcherJson(watcher, { path: "/status", timeoutMs: 1500 });
2889
+ return { ok: true, status };
2890
+ } catch (error) {
2891
+ return { ok: false, error: error instanceof Error ? error.message : String(error) };
2892
+ }
2893
+ };
2894
+
2895
+ // dist/watchers/requestWatcher.js
2896
+ var buildWatcherUrl = (watcher, path4, query) => {
2897
+ const qs = query?.toString();
2898
+ return `http://${watcher.host}:${watcher.port}${path4}${qs ? `?${qs}` : ""}`;
2899
+ };
2900
+ var formatWatcherTransportError = (watcher, error) => `${watcher.id}: failed to reach watcher (${formatError(error)})`;
2901
+ async function fetchWatcherJson(watcher, input) {
2902
+ return fetchJson(buildWatcherUrl(watcher, input.path, input.query), {
2903
+ method: input.method,
2904
+ body: input.body,
2905
+ timeoutMs: input.timeoutMs,
2906
+ returnErrorResponse: input.returnErrorResponse
2907
+ });
2908
+ }
2909
+ async function requestWatcherJson(input) {
2910
+ const resolved = await resolveWatcher({ id: input.id });
2911
+ if (!resolved.ok) {
2912
+ return {
2913
+ ok: false,
2914
+ exitCode: resolved.exitCode,
2915
+ message: resolved.error,
2916
+ candidates: resolved.candidates
2917
+ };
2918
+ }
2919
+ const { watcher } = resolved;
2920
+ try {
2921
+ const data = await fetchWatcherJson(watcher, input);
2922
+ return { ok: true, watcher, data };
2923
+ } catch (error) {
2924
+ return {
2925
+ ok: false,
2926
+ watcher,
2927
+ exitCode: 1,
2928
+ message: formatWatcherTransportError(watcher, error)
2929
+ };
2930
+ }
2931
+ }
2932
+ async function resolveWatcherOrExit(input, output) {
2933
+ const resolved = await resolveWatcher(input);
2934
+ if (!resolved.ok) {
2935
+ writeResolveError(resolved, output);
2936
+ return null;
2937
+ }
2938
+ return { watcher: resolved.watcher };
2939
+ }
2940
+ function writeRequestError(result, output) {
2941
+ output.writeWarn(result.message);
2942
+ if (result.candidates && result.candidates.length > 0) {
2943
+ for (const watcher of result.candidates) {
2944
+ output.writeWarn(formatWatcherLine(watcher));
2945
+ }
2946
+ output.writeWarn("Hint: run `argus list` to see all watchers.");
2947
+ }
2948
+ process.exitCode = result.exitCode;
2949
+ }
2950
+ function writeResolveError(resolved, output) {
2951
+ output.writeWarn(resolved.error);
2952
+ if (resolved.candidates && resolved.candidates.length > 0) {
2953
+ for (const watcher of resolved.candidates) {
2954
+ output.writeWarn(formatWatcherLine(watcher));
2955
+ }
2956
+ output.writeWarn("Hint: run `argus list` to see all watchers.");
2957
+ }
2958
+ process.exitCode = resolved.exitCode;
2959
+ }
2839
2960
 
2840
2961
  // dist/commands/chrome.js
2841
2962
  import { execFile } from "node:child_process";
@@ -2895,6 +3016,102 @@ var resolveCdpEndpoint = async (options) => {
2895
3016
  return { ok: true, host: "127.0.0.1", port: 9222 };
2896
3017
  };
2897
3018
 
3019
+ // dist/cdp/sendCdpCommand.js
3020
+ var getWebSocketCtor = () => {
3021
+ const ctor = globalThis.WebSocket;
3022
+ return ctor ?? null;
3023
+ };
3024
+ var toMessageText = (data) => {
3025
+ if (typeof data === "string") {
3026
+ return data;
3027
+ }
3028
+ if (data instanceof ArrayBuffer) {
3029
+ return Buffer.from(data).toString("utf8");
3030
+ }
3031
+ if (Buffer.isBuffer(data)) {
3032
+ return data.toString("utf8");
3033
+ }
3034
+ return null;
3035
+ };
3036
+ var sendCdpCommand = async (wsUrl, payload, timeoutMs = 5000) => {
3037
+ const WebSocketConstructor = getWebSocketCtor();
3038
+ if (!WebSocketConstructor) {
3039
+ throw new Error("WebSocket unavailable. Node 18+ required.");
3040
+ }
3041
+ const ws = new WebSocketConstructor(wsUrl);
3042
+ const requestId = payload.id;
3043
+ await new Promise((resolve, reject) => {
3044
+ let settled = false;
3045
+ const timer = setTimeout(() => {
3046
+ if (!settled) {
3047
+ settled = true;
3048
+ try {
3049
+ ws.close();
3050
+ } catch {}
3051
+ reject(new Error(`CDP command timed out after ${timeoutMs}ms`));
3052
+ }
3053
+ }, timeoutMs);
3054
+ const cleanup = () => {
3055
+ clearTimeout(timer);
3056
+ ws.removeEventListener?.("open", onOpen);
3057
+ ws.removeEventListener?.("message", onMessage);
3058
+ ws.removeEventListener?.("error", onError);
3059
+ ws.removeEventListener?.("close", onClose);
3060
+ };
3061
+ const finish = (error) => {
3062
+ if (settled) {
3063
+ return;
3064
+ }
3065
+ settled = true;
3066
+ cleanup();
3067
+ try {
3068
+ ws.close();
3069
+ } catch {}
3070
+ if (error) {
3071
+ reject(error);
3072
+ return;
3073
+ }
3074
+ resolve();
3075
+ };
3076
+ const onOpen = () => {
3077
+ try {
3078
+ ws.send(JSON.stringify(payload));
3079
+ } catch (error) {
3080
+ finish(error instanceof Error ? error : new Error(String(error)));
3081
+ }
3082
+ };
3083
+ const onMessage = (event) => {
3084
+ const text = toMessageText(event.data);
3085
+ if (!text) {
3086
+ return;
3087
+ }
3088
+ try {
3089
+ const message = JSON.parse(text);
3090
+ if (message.id !== requestId) {
3091
+ return;
3092
+ }
3093
+ if (message.error?.message) {
3094
+ finish(new Error(message.error.message));
3095
+ return;
3096
+ }
3097
+ finish();
3098
+ } catch (error) {
3099
+ finish(error instanceof Error ? error : new Error(String(error)));
3100
+ }
3101
+ };
3102
+ const onError = () => {
3103
+ finish(new Error("WebSocket error"));
3104
+ };
3105
+ const onClose = () => {
3106
+ finish(new Error("WebSocket closed before response"));
3107
+ };
3108
+ ws.addEventListener("open", onOpen);
3109
+ ws.addEventListener("message", onMessage);
3110
+ ws.addEventListener("error", onError);
3111
+ ws.addEventListener("close", onClose);
3112
+ });
3113
+ };
3114
+
2898
3115
  // dist/cdp/selectTarget.js
2899
3116
  var normalizeFilter = (value) => {
2900
3117
  if (!value) {
@@ -2983,53 +3200,6 @@ var readLineOnce = async () => {
2983
3200
  });
2984
3201
  };
2985
3202
 
2986
- // dist/watchers/resolveWatcher.js
2987
- var resolveWatcher = async (input) => {
2988
- let registry2;
2989
- try {
2990
- registry2 = await pruneRegistry();
2991
- } catch (error) {
2992
- return { ok: false, error: `Failed to load registry: ${error instanceof Error ? error.message : error}`, exitCode: 1 };
2993
- }
2994
- const watchers = Object.values(registry2.watchers);
2995
- if (input.id) {
2996
- const watcher = registry2.watchers[input.id];
2997
- if (!watcher) {
2998
- return { ok: false, error: `Watcher not found: ${input.id}`, exitCode: 2, candidates: watchers };
2999
- }
3000
- return { ok: true, watcher, registry: registry2 };
3001
- }
3002
- if (watchers.length === 0) {
3003
- return { ok: false, error: "Watcher id required.", exitCode: 2 };
3004
- }
3005
- const cwd = process.cwd();
3006
- const cwdMatches = watchers.filter((watcher) => watcher.cwd === cwd);
3007
- if (cwdMatches.length === 1) {
3008
- return { ok: true, watcher: cwdMatches[0], registry: registry2 };
3009
- }
3010
- if (cwdMatches.length > 1) {
3011
- return { ok: false, error: "Watcher id required.", exitCode: 2, candidates: cwdMatches };
3012
- }
3013
- const reachability = await Promise.all(watchers.map(async (watcher) => ({
3014
- watcher,
3015
- status: await checkWatcherStatus(watcher)
3016
- })));
3017
- const reachable = reachability.filter((entry) => entry.status.ok);
3018
- if (reachable.length === 1) {
3019
- return { ok: true, watcher: reachable[0].watcher, registry: registry2 };
3020
- }
3021
- return { ok: false, error: "Watcher id required.", exitCode: 2, candidates: watchers };
3022
- };
3023
- var checkWatcherStatus = async (watcher) => {
3024
- const url = `http://${watcher.host}:${watcher.port}/status`;
3025
- try {
3026
- const status = await fetchJson(url, { timeoutMs: 1500 });
3027
- return { ok: true, status };
3028
- } catch (error) {
3029
- return { ok: false, error: error instanceof Error ? error.message : String(error) };
3030
- }
3031
- };
3032
-
3033
3203
  // dist/commands/chrome.js
3034
3204
  var normalizeUrl = (url) => {
3035
3205
  if (url.startsWith("http://") || url.startsWith("https://")) {
@@ -3037,100 +3207,6 @@ var normalizeUrl = (url) => {
3037
3207
  }
3038
3208
  return `http://${url}`;
3039
3209
  };
3040
- var getWebSocketCtor = () => {
3041
- const ctor = globalThis.WebSocket;
3042
- return ctor ?? null;
3043
- };
3044
- var toMessageText = (data) => {
3045
- if (typeof data === "string") {
3046
- return data;
3047
- }
3048
- if (data instanceof ArrayBuffer) {
3049
- return Buffer.from(data).toString("utf8");
3050
- }
3051
- if (Buffer.isBuffer(data)) {
3052
- return data.toString("utf8");
3053
- }
3054
- return null;
3055
- };
3056
- var sendCdpCommand = async (wsUrl, payload, timeoutMs = 5000) => {
3057
- const WebSocketConstructor = getWebSocketCtor();
3058
- if (!WebSocketConstructor) {
3059
- throw new Error("WebSocket unavailable. Node 18+ required.");
3060
- }
3061
- const ws = new WebSocketConstructor(wsUrl);
3062
- const requestId = payload.id;
3063
- await new Promise((resolve, reject) => {
3064
- let settled = false;
3065
- const timer = setTimeout(() => {
3066
- if (!settled) {
3067
- settled = true;
3068
- try {
3069
- ws.close();
3070
- } catch {}
3071
- reject(new Error(`CDP command timed out after ${timeoutMs}ms`));
3072
- }
3073
- }, timeoutMs);
3074
- const cleanup = () => {
3075
- clearTimeout(timer);
3076
- ws.removeEventListener?.("open", onOpen);
3077
- ws.removeEventListener?.("message", onMessage);
3078
- ws.removeEventListener?.("error", onError);
3079
- ws.removeEventListener?.("close", onClose);
3080
- };
3081
- const finish = (error) => {
3082
- if (settled) {
3083
- return;
3084
- }
3085
- settled = true;
3086
- cleanup();
3087
- try {
3088
- ws.close();
3089
- } catch {}
3090
- if (error) {
3091
- reject(error);
3092
- } else {
3093
- resolve();
3094
- }
3095
- };
3096
- const onOpen = () => {
3097
- try {
3098
- ws.send(JSON.stringify(payload));
3099
- } catch (error) {
3100
- finish(error instanceof Error ? error : new Error(String(error)));
3101
- }
3102
- };
3103
- const onMessage = (event) => {
3104
- const text = toMessageText(event.data);
3105
- if (!text) {
3106
- return;
3107
- }
3108
- try {
3109
- const message = JSON.parse(text);
3110
- if (message.id !== requestId) {
3111
- return;
3112
- }
3113
- if (message.error?.message) {
3114
- finish(new Error(message.error.message));
3115
- return;
3116
- }
3117
- finish();
3118
- } catch (error) {
3119
- finish(error instanceof Error ? error : new Error(String(error)));
3120
- }
3121
- };
3122
- const onError = () => {
3123
- finish(new Error("WebSocket error"));
3124
- };
3125
- const onClose = () => {
3126
- finish(new Error("WebSocket closed before response"));
3127
- };
3128
- ws.addEventListener("open", onOpen);
3129
- ws.addEventListener("message", onMessage);
3130
- ws.addEventListener("error", onError);
3131
- ws.addEventListener("close", onClose);
3132
- });
3133
- };
3134
3210
  var runChromeVersion = async (options) => {
3135
3211
  const output = createOutput(options);
3136
3212
  const endpoint = await resolveCdpEndpoint(options);
@@ -3579,12 +3655,11 @@ var listWatchers = async (options, output) => {
3579
3655
  return [];
3580
3656
  const results = [];
3581
3657
  for (const watcher of watchers) {
3582
- const url = `http://${watcher.host}:${watcher.port}/status`;
3583
3658
  try {
3584
- const status = await fetchJson(url, { timeoutMs: 2000 });
3659
+ const status = await fetchWatcherJson(watcher, { path: "/status", timeoutMs: 2000 });
3585
3660
  results.push({ watcher, status });
3586
3661
  } catch (error) {
3587
- output.writeWarn(`${watcher.id}: failed to reach watcher (${formatError(error)})`);
3662
+ output.writeWarn(formatWatcherTransportError(watcher, error));
3588
3663
  results.push({ watcher });
3589
3664
  }
3590
3665
  }
@@ -3593,11 +3668,6 @@ var listWatchers = async (options, output) => {
3593
3668
 
3594
3669
  // dist/commands/start.js
3595
3670
  import { rmSync as rmSync2 } from "node:fs";
3596
- import fs7 from "node:fs/promises";
3597
-
3598
- // ../argus-watcher/dist/index.js
3599
- import os3 from "node:os";
3600
- import path7 from "node:path";
3601
3671
 
3602
3672
  // ../../node_modules/.bun/emittery@1.2.0/node_modules/emittery/maps.js
3603
3673
  var anyMap = new WeakMap;
@@ -4045,6 +4115,72 @@ Object.defineProperty(Emittery, "listenerRemoved", {
4045
4115
  configurable: false
4046
4116
  });
4047
4117
 
4118
+ // ../argus-watcher/dist/registry/registry.js
4119
+ var resolveUniqueWatcherId = async (id) => {
4120
+ const { registry: registry2 } = await readRegistry();
4121
+ const staleIds = [];
4122
+ const isIdAvailable = (candidate) => {
4123
+ const existing = registry2.watchers[candidate];
4124
+ if (!existing) {
4125
+ return true;
4126
+ }
4127
+ if (existing.pid == null || !isProcessAlive(existing.pid)) {
4128
+ staleIds.push(candidate);
4129
+ return true;
4130
+ }
4131
+ return false;
4132
+ };
4133
+ let resolvedId = id;
4134
+ if (!isIdAvailable(id)) {
4135
+ let suffix = 2;
4136
+ while (!isIdAvailable(`${id}-${suffix}`)) {
4137
+ suffix++;
4138
+ }
4139
+ resolvedId = `${id}-${suffix}`;
4140
+ }
4141
+ if (staleIds.length > 0) {
4142
+ await updateRegistry((reg) => {
4143
+ let next = reg;
4144
+ for (const staleId of staleIds) {
4145
+ next = removeWatcherEntry(next, staleId);
4146
+ }
4147
+ return next;
4148
+ });
4149
+ }
4150
+ return resolvedId;
4151
+ };
4152
+ var isProcessAlive = (pid) => {
4153
+ try {
4154
+ process.kill(pid, 0);
4155
+ return true;
4156
+ } catch {
4157
+ return false;
4158
+ }
4159
+ };
4160
+ var announceWatcher = async (watcher) => {
4161
+ await updateRegistry((registry2) => setWatcherEntry(registry2, watcher));
4162
+ };
4163
+ var updateWatcherHeartbeat = async (watcher) => {
4164
+ await announceWatcher(watcher);
4165
+ };
4166
+ var removeWatcher = async (id) => {
4167
+ await updateRegistry((registry2) => removeWatcherEntry(registry2, id));
4168
+ };
4169
+ var startRegistryHeartbeat = (getWatcher, intervalMs = 15000) => {
4170
+ const timer = setInterval(() => {
4171
+ const watcher = getWatcher();
4172
+ watcher.updatedAt = Date.now();
4173
+ updateWatcherHeartbeat(watcher);
4174
+ }, intervalMs);
4175
+ return {
4176
+ stop: () => clearInterval(timer)
4177
+ };
4178
+ };
4179
+
4180
+ // ../argus-watcher/dist/startWatcherRuntime.js
4181
+ import os3 from "node:os";
4182
+ import path7 from "node:path";
4183
+
4048
4184
  // ../argus-watcher/dist/buffer/LogBuffer.js
4049
4185
  class LogBuffer {
4050
4186
  maxSize;
@@ -4156,6 +4292,10 @@ class NetBuffer {
4156
4292
  const filtered = this.events.filter((event) => event.id > after && matchesFilters2(event, filters));
4157
4293
  return filtered.slice(0, limit);
4158
4294
  }
4295
+ list(filters, limit = this.maxSize) {
4296
+ const filtered = this.events.filter((event) => matchesFilters2(event, filters));
4297
+ return filtered.slice(0, limit);
4298
+ }
4159
4299
  waitForAfter(after, filters, limit, timeoutMs) {
4160
4300
  const immediate = this.listAfter(after, filters, limit);
4161
4301
  if (immediate.length > 0) {
@@ -4501,6 +4641,77 @@ var handle5 = async (_req, res, url, ctx) => {
4501
4641
  respondJson(res, response);
4502
4642
  };
4503
4643
 
4644
+ // ../argus-watcher/dist/cdp/auth.js
4645
+ var inspectAuthCookies = async (session, options) => {
4646
+ const [origin, cookies2] = await Promise.all([capturePageOrigin(session), readCookies(session, options.includeValues === true)]);
4647
+ const normalizedDomain = normalizeCookieDomainFilter(options.domain);
4648
+ return {
4649
+ ok: true,
4650
+ origin,
4651
+ cookies: cookies2.filter((cookie) => matchesCookieDomain(cookie.domain, normalizedDomain))
4652
+ };
4653
+ };
4654
+ var readCookies = async (session, includeValues) => {
4655
+ const payload = await session.sendAndWait("Network.getCookies", {}, { timeoutMs: 5000 });
4656
+ const cookies2 = payload.cookies ?? [];
4657
+ return cookies2.map((cookie) => normalizeCookie(cookie, includeValues)).sort(compareCookies);
4658
+ };
4659
+ var normalizeCookie = (cookie, includeValues) => {
4660
+ const value = cookie.value ?? null;
4661
+ return {
4662
+ name: cookie.name ?? "",
4663
+ domain: cookie.domain ?? "",
4664
+ path: cookie.path ?? "/",
4665
+ value: includeValues ? value : undefined,
4666
+ valuePreview: value != null ? previewSecret(value) : null,
4667
+ secure: cookie.secure === true,
4668
+ httpOnly: cookie.httpOnly === true,
4669
+ session: cookie.session === true,
4670
+ expires: typeof cookie.expires === "number" && Number.isFinite(cookie.expires) ? cookie.expires : null,
4671
+ sameSite: cookie.sameSite ?? null
4672
+ };
4673
+ };
4674
+ var capturePageOrigin = async (session) => {
4675
+ const payload = await session.sendAndWait("Runtime.evaluate", {
4676
+ expression: `(() => {
4677
+ try {
4678
+ return new URL(location.href).origin
4679
+ } catch {
4680
+ throw new Error('Cannot determine origin: page is on a non-http URL (e.g., about:blank)')
4681
+ }
4682
+ })()`,
4683
+ awaitPromise: false,
4684
+ returnByValue: true
4685
+ }, { timeoutMs: 5000 });
4686
+ if (payload.exceptionDetails) {
4687
+ throw new Error(payload.exceptionDetails.exception?.description ?? payload.exceptionDetails.text ?? "Failed to inspect page auth cookies");
4688
+ }
4689
+ return String(payload.result?.value ?? "");
4690
+ };
4691
+ var previewSecret = (value) => {
4692
+ if (value.length <= 8) {
4693
+ return "*".repeat(value.length);
4694
+ }
4695
+ return `${value.slice(0, 4)}...${value.slice(-4)}`;
4696
+ };
4697
+ var compareCookies = (a, b) => a.domain.localeCompare(b.domain) || a.path.localeCompare(b.path) || a.name.localeCompare(b.name);
4698
+
4699
+ // ../argus-watcher/dist/http/routes/getAuthCookies.js
4700
+ var handle6 = async (_req, res, url, ctx) => {
4701
+ const domain = normalizeQueryValue2(url.searchParams.get("domain"));
4702
+ const includeValues = url.searchParams.get("includeValues") === "true";
4703
+ emitRequest(ctx, res, "auth/cookies", { domain, includeValues });
4704
+ try {
4705
+ const response = await inspectAuthCookies(ctx.cdpSession, {
4706
+ domain: domain ?? undefined,
4707
+ includeValues
4708
+ });
4709
+ respondJson(res, response);
4710
+ } catch (error) {
4711
+ respondError(res, error);
4712
+ }
4713
+ };
4714
+
4504
4715
  // ../argus-watcher/dist/cdp/remoteObject.js
4505
4716
  var serializeRemoteObjects = async (values, cdp) => {
4506
4717
  if (!cdp) {
@@ -4667,7 +4878,7 @@ var shouldMaterializeByValue = (record) => {
4667
4878
  };
4668
4879
 
4669
4880
  // ../argus-watcher/dist/http/routes/postEval.js
4670
- var handle6 = async (req, res, _url, ctx) => {
4881
+ var handle7 = async (req, res, _url, ctx) => {
4671
4882
  const payload = await readJsonBody(req, res);
4672
4883
  if (!payload) {
4673
4884
  return;
@@ -4691,7 +4902,7 @@ var handle6 = async (req, res, _url, ctx) => {
4691
4902
  };
4692
4903
 
4693
4904
  // ../argus-watcher/dist/http/routes/postTraceStart.js
4694
- var handle7 = async (req, res, _url, ctx) => {
4905
+ var handle8 = async (req, res, _url, ctx) => {
4695
4906
  const payload = await readJsonBody(req, res);
4696
4907
  if (!payload) {
4697
4908
  return;
@@ -4706,7 +4917,7 @@ var handle7 = async (req, res, _url, ctx) => {
4706
4917
  };
4707
4918
 
4708
4919
  // ../argus-watcher/dist/http/routes/postTraceStop.js
4709
- var handle8 = async (req, res, _url, ctx) => {
4920
+ var handle9 = async (req, res, _url, ctx) => {
4710
4921
  const payload = await readJsonBody(req, res);
4711
4922
  if (!payload) {
4712
4923
  return;
@@ -4721,7 +4932,7 @@ var handle8 = async (req, res, _url, ctx) => {
4721
4932
  };
4722
4933
 
4723
4934
  // ../argus-watcher/dist/http/routes/postScreenshot.js
4724
- var handle9 = async (req, res, _url, ctx) => {
4935
+ var handle10 = async (req, res, _url, ctx) => {
4725
4936
  const payload = await readJsonBody(req, res);
4726
4937
  if (!payload) {
4727
4938
  return;
@@ -4976,7 +5187,7 @@ var countNodes = (nodes) => {
4976
5187
  };
4977
5188
 
4978
5189
  // ../argus-watcher/dist/http/routes/postSnapshot.js
4979
- var handle10 = async (req, res, _url, ctx) => {
5190
+ var handle11 = async (req, res, _url, ctx) => {
4980
5191
  const payload = await readJsonBody(req, res);
4981
5192
  if (!payload) {
4982
5193
  return;
@@ -5001,7 +5212,7 @@ var handle10 = async (req, res, _url, ctx) => {
5001
5212
  };
5002
5213
 
5003
5214
  // ../argus-watcher/dist/http/routes/postCodeList.js
5004
- var handle11 = async (req, res, _url, ctx) => {
5215
+ var handle12 = async (req, res, _url, ctx) => {
5005
5216
  const payload = await readJsonBody(req, res);
5006
5217
  if (!payload) {
5007
5218
  return;
@@ -5019,7 +5230,7 @@ var handle11 = async (req, res, _url, ctx) => {
5019
5230
  };
5020
5231
 
5021
5232
  // ../argus-watcher/dist/http/routes/postCodeRead.js
5022
- var handle12 = async (req, res, _url, ctx) => {
5233
+ var handle13 = async (req, res, _url, ctx) => {
5023
5234
  const payload = await readJsonBody(req, res);
5024
5235
  if (!payload) {
5025
5236
  return;
@@ -5047,7 +5258,7 @@ var handle12 = async (req, res, _url, ctx) => {
5047
5258
  };
5048
5259
 
5049
5260
  // ../argus-watcher/dist/http/routes/postCodeGrep.js
5050
- var handle13 = async (req, res, _url, ctx) => {
5261
+ var handle14 = async (req, res, _url, ctx) => {
5051
5262
  const payload = await readJsonBody(req, res);
5052
5263
  if (!payload) {
5053
5264
  return;
@@ -5070,6 +5281,33 @@ var handle13 = async (req, res, _url, ctx) => {
5070
5281
  }
5071
5282
  };
5072
5283
 
5284
+ // ../argus-watcher/dist/http/routes/domSelectorRoute.js
5285
+ var readDomSelectorPayload = async (req, res) => {
5286
+ const payload = await readJsonBody(req, res);
5287
+ if (!payload) {
5288
+ return null;
5289
+ }
5290
+ if (!payload.selector || typeof payload.selector !== "string") {
5291
+ respondInvalidBody(res, "selector is required");
5292
+ return null;
5293
+ }
5294
+ const all = payload.all ?? false;
5295
+ if (typeof all !== "boolean") {
5296
+ respondInvalidBody(res, "all must be a boolean");
5297
+ return null;
5298
+ }
5299
+ return { payload, all };
5300
+ };
5301
+ var respondMultipleMatches = (res, matches, action) => {
5302
+ respondJson(res, {
5303
+ ok: false,
5304
+ error: {
5305
+ message: `Selector matched ${matches} elements; pass all=true to ${action} all matches`,
5306
+ code: "multiple_matches"
5307
+ }
5308
+ }, 400);
5309
+ };
5310
+
5073
5311
  // ../argus-watcher/dist/cdp/text-filter.js
5074
5312
  var filterNodesByText = async (session, nodeIds, text) => {
5075
5313
  const pattern = parseTextPattern(text);
@@ -5505,18 +5743,12 @@ var fillResolvedNodes = async (session, nodeIds, value) => {
5505
5743
  return nodeIds.length;
5506
5744
  };
5507
5745
  // ../argus-watcher/dist/http/routes/postDomTree.js
5508
- var handle14 = async (req, res, _url, ctx) => {
5509
- const payload = await readJsonBody(req, res);
5510
- if (!payload) {
5746
+ var handle15 = async (req, res, _url, ctx) => {
5747
+ const parsed = await readDomSelectorPayload(req, res);
5748
+ if (!parsed) {
5511
5749
  return;
5512
5750
  }
5513
- if (!payload.selector || typeof payload.selector !== "string") {
5514
- return respondInvalidBody(res, "selector is required");
5515
- }
5516
- const all = payload.all ?? false;
5517
- if (typeof all !== "boolean") {
5518
- return respondInvalidBody(res, "all must be a boolean");
5519
- }
5751
+ const { payload, all } = parsed;
5520
5752
  emitRequest(ctx, res, "dom/tree");
5521
5753
  try {
5522
5754
  const response = await fetchDomSubtreeBySelector(ctx.cdpSession, {
@@ -5527,13 +5759,7 @@ var handle14 = async (req, res, _url, ctx) => {
5527
5759
  text: payload.text
5528
5760
  });
5529
5761
  if (!all && response.matches > 1) {
5530
- return respondJson(res, {
5531
- ok: false,
5532
- error: {
5533
- message: `Selector matched ${response.matches} elements; pass all=true to return all matches`,
5534
- code: "multiple_matches"
5535
- }
5536
- }, 400);
5762
+ return respondMultipleMatches(res, response.matches, "return");
5537
5763
  }
5538
5764
  respondJson(res, response);
5539
5765
  } catch (error) {
@@ -5542,18 +5768,12 @@ var handle14 = async (req, res, _url, ctx) => {
5542
5768
  };
5543
5769
 
5544
5770
  // ../argus-watcher/dist/http/routes/postDomInfo.js
5545
- var handle15 = async (req, res, _url, ctx) => {
5546
- const payload = await readJsonBody(req, res);
5547
- if (!payload) {
5771
+ var handle16 = async (req, res, _url, ctx) => {
5772
+ const parsed = await readDomSelectorPayload(req, res);
5773
+ if (!parsed) {
5548
5774
  return;
5549
5775
  }
5550
- if (!payload.selector || typeof payload.selector !== "string") {
5551
- return respondInvalidBody(res, "selector is required");
5552
- }
5553
- const all = payload.all ?? false;
5554
- if (typeof all !== "boolean") {
5555
- return respondInvalidBody(res, "all must be a boolean");
5556
- }
5776
+ const { payload, all } = parsed;
5557
5777
  emitRequest(ctx, res, "dom/info");
5558
5778
  try {
5559
5779
  const response = await fetchDomInfoBySelector(ctx.cdpSession, {
@@ -5563,13 +5783,7 @@ var handle15 = async (req, res, _url, ctx) => {
5563
5783
  text: payload.text
5564
5784
  });
5565
5785
  if (!all && response.matches > 1) {
5566
- return respondJson(res, {
5567
- ok: false,
5568
- error: {
5569
- message: `Selector matched ${response.matches} elements; pass all=true to return all matches`,
5570
- code: "multiple_matches"
5571
- }
5572
- }, 400);
5786
+ return respondMultipleMatches(res, response.matches, "return");
5573
5787
  }
5574
5788
  respondJson(res, response);
5575
5789
  } catch (error) {
@@ -5767,29 +5981,17 @@ var createNotInteractableError = (message) => {
5767
5981
  };
5768
5982
 
5769
5983
  // ../argus-watcher/dist/http/routes/postDomHover.js
5770
- var handle16 = async (req, res, _url, ctx) => {
5771
- const payload = await readJsonBody(req, res);
5772
- if (!payload) {
5984
+ var handle17 = async (req, res, _url, ctx) => {
5985
+ const parsed = await readDomSelectorPayload(req, res);
5986
+ if (!parsed) {
5773
5987
  return;
5774
5988
  }
5775
- if (!payload.selector || typeof payload.selector !== "string") {
5776
- return respondInvalidBody(res, "selector is required");
5777
- }
5778
- const all = payload.all ?? false;
5779
- if (typeof all !== "boolean") {
5780
- return respondInvalidBody(res, "all must be a boolean");
5781
- }
5989
+ const { payload, all } = parsed;
5782
5990
  emitRequest(ctx, res, "dom/hover");
5783
5991
  try {
5784
5992
  const { allNodeIds, nodeIds } = await resolveDomSelectorMatches(ctx.cdpSession, payload.selector, all, payload.text);
5785
5993
  if (!all && allNodeIds.length > 1) {
5786
- return respondJson(res, {
5787
- ok: false,
5788
- error: {
5789
- message: `Selector matched ${allNodeIds.length} elements; pass all=true to hover all matches`,
5790
- code: "multiple_matches"
5791
- }
5792
- }, 400);
5994
+ return respondMultipleMatches(res, allNodeIds.length, "hover");
5793
5995
  }
5794
5996
  if (allNodeIds.length === 0) {
5795
5997
  const response2 = { ok: true, matches: 0, hovered: 0 };
@@ -5804,7 +6006,7 @@ var handle16 = async (req, res, _url, ctx) => {
5804
6006
  };
5805
6007
 
5806
6008
  // ../argus-watcher/dist/http/routes/postDomClick.js
5807
- var handle17 = async (req, res, _url, ctx) => {
6009
+ var handle18 = async (req, res, _url, ctx) => {
5808
6010
  const payload = await readJsonBody(req, res);
5809
6011
  if (!payload) {
5810
6012
  return;
@@ -5852,13 +6054,7 @@ var handle17 = async (req, res, _url, ctx) => {
5852
6054
  nodeIds = result.nodeIds;
5853
6055
  }
5854
6056
  if (!all && allNodeIds.length > 1) {
5855
- return respondJson(res, {
5856
- ok: false,
5857
- error: {
5858
- message: `Selector matched ${allNodeIds.length} elements; pass all=true to click all matches`,
5859
- code: "multiple_matches"
5860
- }
5861
- }, 400);
6057
+ return respondMultipleMatches(res, allNodeIds.length, "click");
5862
6058
  }
5863
6059
  if (allNodeIds.length === 0) {
5864
6060
  const response2 = { ok: true, matches: 0, clicked: 0 };
@@ -5998,7 +6194,7 @@ var dispatchKeydown = async (session, options) => {
5998
6194
  };
5999
6195
 
6000
6196
  // ../argus-watcher/dist/http/routes/postDomKeydown.js
6001
- var handle18 = async (req, res, _url, ctx) => {
6197
+ var handle19 = async (req, res, _url, ctx) => {
6002
6198
  const payload = await readJsonBody(req, res);
6003
6199
  if (!payload) {
6004
6200
  return;
@@ -6030,7 +6226,7 @@ var handle18 = async (req, res, _url, ctx) => {
6030
6226
  };
6031
6227
 
6032
6228
  // ../argus-watcher/dist/http/routes/postDomAdd.js
6033
- var handle19 = async (req, res, _url, ctx) => {
6229
+ var handle20 = async (req, res, _url, ctx) => {
6034
6230
  const payload = await readJsonBody(req, res);
6035
6231
  if (!payload) {
6036
6232
  return;
@@ -6123,18 +6319,12 @@ var selectDomAddNodeIds = (allNodeIds, options) => {
6123
6319
  };
6124
6320
 
6125
6321
  // ../argus-watcher/dist/http/routes/postDomRemove.js
6126
- var handle20 = async (req, res, _url, ctx) => {
6127
- const payload = await readJsonBody(req, res);
6128
- if (!payload) {
6322
+ var handle21 = async (req, res, _url, ctx) => {
6323
+ const parsed = await readDomSelectorPayload(req, res);
6324
+ if (!parsed) {
6129
6325
  return;
6130
6326
  }
6131
- if (!payload.selector || typeof payload.selector !== "string") {
6132
- return respondInvalidBody(res, "selector is required");
6133
- }
6134
- const all = payload.all ?? false;
6135
- if (typeof all !== "boolean") {
6136
- return respondInvalidBody(res, "all must be a boolean");
6137
- }
6327
+ const { payload, all } = parsed;
6138
6328
  emitRequest(ctx, res, "dom/remove");
6139
6329
  try {
6140
6330
  const { allNodeIds, removedCount } = await removeElements(ctx.cdpSession, {
@@ -6143,13 +6333,7 @@ var handle20 = async (req, res, _url, ctx) => {
6143
6333
  text: payload.text
6144
6334
  });
6145
6335
  if (!all && allNodeIds.length > 1) {
6146
- return respondJson(res, {
6147
- ok: false,
6148
- error: {
6149
- message: `Selector matched ${allNodeIds.length} elements; pass all=true to remove all matches`,
6150
- code: "multiple_matches"
6151
- }
6152
- }, 400);
6336
+ return respondMultipleMatches(res, allNodeIds.length, "remove");
6153
6337
  }
6154
6338
  const response = { ok: true, matches: allNodeIds.length, removed: removedCount };
6155
6339
  respondJson(res, response);
@@ -6159,7 +6343,7 @@ var handle20 = async (req, res, _url, ctx) => {
6159
6343
  };
6160
6344
 
6161
6345
  // ../argus-watcher/dist/http/routes/postDomModify.js
6162
- var handle21 = async (req, res, _url, ctx) => {
6346
+ var handle22 = async (req, res, _url, ctx) => {
6163
6347
  const payload = await readJsonBody(req, res);
6164
6348
  if (!payload) {
6165
6349
  return;
@@ -6201,7 +6385,7 @@ var handle21 = async (req, res, _url, ctx) => {
6201
6385
  };
6202
6386
 
6203
6387
  // ../argus-watcher/dist/http/routes/postDomSetFile.js
6204
- var handle22 = async (req, res, _url, ctx) => {
6388
+ var handle23 = async (req, res, _url, ctx) => {
6205
6389
  const payload = await readJsonBody(req, res);
6206
6390
  if (!payload) {
6207
6391
  return;
@@ -6254,29 +6438,17 @@ var handle22 = async (req, res, _url, ctx) => {
6254
6438
  };
6255
6439
 
6256
6440
  // ../argus-watcher/dist/http/routes/postDomFocus.js
6257
- var handle23 = async (req, res, _url, ctx) => {
6258
- const payload = await readJsonBody(req, res);
6259
- if (!payload) {
6441
+ var handle24 = async (req, res, _url, ctx) => {
6442
+ const parsed = await readDomSelectorPayload(req, res);
6443
+ if (!parsed) {
6260
6444
  return;
6261
6445
  }
6262
- if (!payload.selector || typeof payload.selector !== "string") {
6263
- return respondInvalidBody(res, "selector is required");
6264
- }
6265
- const all = payload.all ?? false;
6266
- if (typeof all !== "boolean") {
6267
- return respondInvalidBody(res, "all must be a boolean");
6268
- }
6446
+ const { payload, all } = parsed;
6269
6447
  emitRequest(ctx, res, "dom/focus");
6270
6448
  try {
6271
6449
  const { allNodeIds, nodeIds } = await resolveDomSelectorMatches(ctx.cdpSession, payload.selector, all, payload.text);
6272
6450
  if (!all && allNodeIds.length > 1) {
6273
- return respondJson(res, {
6274
- ok: false,
6275
- error: {
6276
- message: `Selector matched ${allNodeIds.length} elements; pass all=true to focus all matches`,
6277
- code: "multiple_matches"
6278
- }
6279
- }, 400);
6451
+ return respondMultipleMatches(res, allNodeIds.length, "focus");
6280
6452
  }
6281
6453
  if (allNodeIds.length === 0) {
6282
6454
  const response2 = { ok: true, matches: 0, focused: 0 };
@@ -6291,7 +6463,7 @@ var handle23 = async (req, res, _url, ctx) => {
6291
6463
  };
6292
6464
 
6293
6465
  // ../argus-watcher/dist/http/routes/postDomFill.js
6294
- var handle24 = async (req, res, _url, ctx) => {
6466
+ var handle25 = async (req, res, _url, ctx) => {
6295
6467
  const payload = await readJsonBody(req, res);
6296
6468
  if (!payload) {
6297
6469
  return;
@@ -6344,7 +6516,7 @@ var handle24 = async (req, res, _url, ctx) => {
6344
6516
  };
6345
6517
 
6346
6518
  // ../argus-watcher/dist/http/routes/postDomScroll.js
6347
- var handle25 = async (req, res, _url, ctx) => {
6519
+ var handle26 = async (req, res, _url, ctx) => {
6348
6520
  const payload = await readJsonBody(req, res);
6349
6521
  if (!payload) {
6350
6522
  return;
@@ -6413,7 +6585,7 @@ var getViewportSize = async (session) => {
6413
6585
  };
6414
6586
 
6415
6587
  // ../argus-watcher/dist/http/routes/postDomScrollTo.js
6416
- var handle26 = async (req, res, _url, ctx) => {
6588
+ var handle27 = async (req, res, _url, ctx) => {
6417
6589
  const payload = await readJsonBody(req, res);
6418
6590
  if (!payload) {
6419
6591
  return;
@@ -6472,14 +6644,14 @@ var handle26 = async (req, res, _url, ctx) => {
6472
6644
  };
6473
6645
 
6474
6646
  // ../argus-watcher/dist/http/routes/getEmulation.js
6475
- var handle27 = (_req, res, _url, ctx) => {
6647
+ var handle28 = (_req, res, _url, ctx) => {
6476
6648
  emitRequest(ctx, res, "emulation");
6477
6649
  const status = ctx.emulationController.getStatus({ attached: ctx.getCdpStatus().attached });
6478
6650
  respondJson(res, status);
6479
6651
  };
6480
6652
 
6481
6653
  // ../argus-watcher/dist/http/routes/postEmulation.js
6482
- var handle28 = async (req, res, _url, ctx) => {
6654
+ var handle29 = async (req, res, _url, ctx) => {
6483
6655
  const payload = await readJsonBody(req, res);
6484
6656
  if (!payload) {
6485
6657
  return;
@@ -6542,14 +6714,14 @@ var handle28 = async (req, res, _url, ctx) => {
6542
6714
  };
6543
6715
 
6544
6716
  // ../argus-watcher/dist/http/routes/getThrottle.js
6545
- var handle29 = (_req, res, _url, ctx) => {
6717
+ var handle30 = (_req, res, _url, ctx) => {
6546
6718
  emitRequest(ctx, res, "throttle");
6547
6719
  const status = ctx.throttleController.getStatus({ attached: ctx.getCdpStatus().attached });
6548
6720
  respondJson(res, status);
6549
6721
  };
6550
6722
 
6551
6723
  // ../argus-watcher/dist/http/routes/postThrottle.js
6552
- var handle30 = async (req, res, _url, ctx) => {
6724
+ var handle31 = async (req, res, _url, ctx) => {
6553
6725
  const payload = await readJsonBody(req, res);
6554
6726
  if (!payload) {
6555
6727
  return;
@@ -6647,7 +6819,7 @@ var buildActionCode = (action, key, value) => {
6647
6819
  };
6648
6820
 
6649
6821
  // ../argus-watcher/dist/http/routes/postStorageLocal.js
6650
- var handle31 = async (req, res, _url, ctx) => {
6822
+ var handle32 = async (req, res, _url, ctx) => {
6651
6823
  const payload = await readJsonBody(req, res);
6652
6824
  if (!payload) {
6653
6825
  return;
@@ -6672,14 +6844,14 @@ var handle31 = async (req, res, _url, ctx) => {
6672
6844
  };
6673
6845
 
6674
6846
  // ../argus-watcher/dist/http/routes/postReload.js
6675
- var handle32 = async (req, res, _url, ctx) => {
6847
+ var handle33 = async (req, res, _url, ctx) => {
6676
6848
  const payload = await readJsonBody(req, res);
6677
6849
  if (!payload) {
6678
6850
  return;
6679
6851
  }
6680
6852
  emitRequest(ctx, res, "reload");
6681
6853
  try {
6682
- await ctx.cdpSession.sendAndWait("Page.reload", {
6854
+ await ctx.pageCdpSession.sendAndWait("Page.reload", {
6683
6855
  ignoreCache: payload.ignoreCache ?? false
6684
6856
  });
6685
6857
  const response = { ok: true };
@@ -6690,7 +6862,7 @@ var handle32 = async (req, res, _url, ctx) => {
6690
6862
  };
6691
6863
 
6692
6864
  // ../argus-watcher/dist/http/routes/postShutdown.js
6693
- var handle33 = (_req, res, _url, ctx) => {
6865
+ var handle34 = (_req, res, _url, ctx) => {
6694
6866
  emitRequest(ctx, res, "shutdown");
6695
6867
  const response = { ok: true };
6696
6868
  respondJson(res, response);
@@ -6702,7 +6874,7 @@ var handle33 = (_req, res, _url, ctx) => {
6702
6874
  };
6703
6875
 
6704
6876
  // ../argus-watcher/dist/http/routes/getTargets.js
6705
- var handle34 = async (_req, res, _url, ctx) => {
6877
+ var handle35 = async (_req, res, _url, ctx) => {
6706
6878
  if (!ctx.sourceHandle?.listTargets) {
6707
6879
  return respondJson(res, { ok: false, error: { message: "Not available", code: "not_available" } }, 400);
6708
6880
  }
@@ -6716,7 +6888,7 @@ var handle34 = async (_req, res, _url, ctx) => {
6716
6888
  };
6717
6889
 
6718
6890
  // ../argus-watcher/dist/http/routes/postAttach.js
6719
- var handle35 = async (req, res, _url, ctx) => {
6891
+ var handle36 = async (req, res, _url, ctx) => {
6720
6892
  if (!ctx.sourceHandle?.attachTarget) {
6721
6893
  return respondJson(res, { ok: false, error: { message: "Not available", code: "not_available" } }, 400);
6722
6894
  }
@@ -6738,7 +6910,7 @@ var handle35 = async (req, res, _url, ctx) => {
6738
6910
  };
6739
6911
 
6740
6912
  // ../argus-watcher/dist/http/routes/postDetach.js
6741
- var handle36 = async (req, res, _url, ctx) => {
6913
+ var handle37 = async (req, res, _url, ctx) => {
6742
6914
  if (!ctx.sourceHandle?.detachTarget) {
6743
6915
  return respondJson(res, { ok: false, error: { message: "Not available", code: "not_available" } }, 400);
6744
6916
  }
@@ -6766,37 +6938,38 @@ var routes = {
6766
6938
  "GET /tail": { handler: handle3 },
6767
6939
  "GET /net": { handler: handle4 },
6768
6940
  "GET /net/tail": { handler: handle5 },
6769
- "POST /eval": { handler: handle6 },
6770
- "POST /trace/start": { handler: handle7 },
6771
- "POST /trace/stop": { handler: handle8 },
6772
- "POST /screenshot": { handler: handle9 },
6773
- "POST /snapshot": { handler: handle10 },
6774
- "POST /code/list": { handler: handle11 },
6775
- "POST /code/read": { handler: handle12 },
6776
- "POST /code/grep": { handler: handle13 },
6777
- "POST /dom/tree": { handler: handle14 },
6778
- "POST /dom/info": { handler: handle15 },
6779
- "POST /dom/hover": { handler: handle16 },
6780
- "POST /dom/click": { handler: handle17 },
6781
- "POST /dom/keydown": { handler: handle18 },
6782
- "POST /dom/add": { handler: handle19 },
6783
- "POST /dom/remove": { handler: handle20 },
6784
- "POST /dom/modify": { handler: handle21 },
6785
- "POST /dom/set-file": { handler: handle22 },
6786
- "POST /dom/focus": { handler: handle23 },
6787
- "POST /dom/fill": { handler: handle24 },
6788
- "POST /dom/scroll": { handler: handle25 },
6789
- "POST /dom/scroll-to": { handler: handle26 },
6790
- "GET /emulation": { handler: handle27 },
6791
- "POST /emulation": { handler: handle28 },
6792
- "GET /throttle": { handler: handle29 },
6793
- "POST /throttle": { handler: handle30 },
6794
- "POST /storage/local": { handler: handle31 },
6795
- "POST /reload": { handler: handle32 },
6796
- "POST /shutdown": { handler: handle33 },
6797
- "GET /targets": { handler: handle34, extensionOnly: true },
6798
- "POST /attach": { handler: handle35, extensionOnly: true },
6799
- "POST /detach": { handler: handle36, extensionOnly: true }
6941
+ "GET /auth/cookies": { handler: handle6 },
6942
+ "POST /eval": { handler: handle7 },
6943
+ "POST /trace/start": { handler: handle8 },
6944
+ "POST /trace/stop": { handler: handle9 },
6945
+ "POST /screenshot": { handler: handle10 },
6946
+ "POST /snapshot": { handler: handle11 },
6947
+ "POST /code/list": { handler: handle12 },
6948
+ "POST /code/read": { handler: handle13 },
6949
+ "POST /code/grep": { handler: handle14 },
6950
+ "POST /dom/tree": { handler: handle15 },
6951
+ "POST /dom/info": { handler: handle16 },
6952
+ "POST /dom/hover": { handler: handle17 },
6953
+ "POST /dom/click": { handler: handle18 },
6954
+ "POST /dom/keydown": { handler: handle19 },
6955
+ "POST /dom/add": { handler: handle20 },
6956
+ "POST /dom/remove": { handler: handle21 },
6957
+ "POST /dom/modify": { handler: handle22 },
6958
+ "POST /dom/set-file": { handler: handle23 },
6959
+ "POST /dom/focus": { handler: handle24 },
6960
+ "POST /dom/fill": { handler: handle25 },
6961
+ "POST /dom/scroll": { handler: handle26 },
6962
+ "POST /dom/scroll-to": { handler: handle27 },
6963
+ "GET /emulation": { handler: handle28 },
6964
+ "POST /emulation": { handler: handle29 },
6965
+ "GET /throttle": { handler: handle30 },
6966
+ "POST /throttle": { handler: handle31 },
6967
+ "POST /storage/local": { handler: handle32 },
6968
+ "POST /reload": { handler: handle33 },
6969
+ "POST /shutdown": { handler: handle34 },
6970
+ "GET /targets": { handler: handle35, extensionOnly: true },
6971
+ "POST /attach": { handler: handle36, extensionOnly: true },
6972
+ "POST /detach": { handler: handle37, extensionOnly: true }
6800
6973
  };
6801
6974
  var dispatch = (req, res, url, ctx) => {
6802
6975
  const entry = routes[`${req.method} ${url.pathname}`];
@@ -6833,68 +7006,6 @@ var startHttpServer = async (options) => {
6833
7006
  };
6834
7007
  };
6835
7008
 
6836
- // ../argus-watcher/dist/registry/registry.js
6837
- var resolveUniqueWatcherId = async (id) => {
6838
- const { registry: registry2 } = await readRegistry();
6839
- const staleIds = [];
6840
- const isIdAvailable = (candidate) => {
6841
- const existing = registry2.watchers[candidate];
6842
- if (!existing) {
6843
- return true;
6844
- }
6845
- if (existing.pid == null || !isProcessAlive(existing.pid)) {
6846
- staleIds.push(candidate);
6847
- return true;
6848
- }
6849
- return false;
6850
- };
6851
- let resolvedId = id;
6852
- if (!isIdAvailable(id)) {
6853
- let suffix = 2;
6854
- while (!isIdAvailable(`${id}-${suffix}`)) {
6855
- suffix++;
6856
- }
6857
- resolvedId = `${id}-${suffix}`;
6858
- }
6859
- if (staleIds.length > 0) {
6860
- await updateRegistry((reg) => {
6861
- let next = reg;
6862
- for (const staleId of staleIds) {
6863
- next = removeWatcherEntry(next, staleId);
6864
- }
6865
- return next;
6866
- });
6867
- }
6868
- return resolvedId;
6869
- };
6870
- var isProcessAlive = (pid) => {
6871
- try {
6872
- process.kill(pid, 0);
6873
- return true;
6874
- } catch {
6875
- return false;
6876
- }
6877
- };
6878
- var announceWatcher = async (watcher) => {
6879
- await updateRegistry((registry2) => setWatcherEntry(registry2, watcher));
6880
- };
6881
- var updateWatcherHeartbeat = async (watcher) => {
6882
- await announceWatcher(watcher);
6883
- };
6884
- var removeWatcher = async (id) => {
6885
- await updateRegistry((registry2) => removeWatcherEntry(registry2, id));
6886
- };
6887
- var startRegistryHeartbeat = (getWatcher, intervalMs = 15000) => {
6888
- const timer = setInterval(() => {
6889
- const watcher = getWatcher();
6890
- watcher.updatedAt = Date.now();
6891
- updateWatcherHeartbeat(watcher);
6892
- }, intervalMs);
6893
- return {
6894
- stop: () => clearInterval(timer)
6895
- };
6896
- };
6897
-
6898
7009
  // ../argus-watcher/dist/fileLogs/WatcherFileLogger.js
6899
7010
  import fs3 from "node:fs";
6900
7011
  import fsPromises from "node:fs/promises";
@@ -7198,6 +7309,17 @@ var compileRule = (pattern) => {
7198
7309
 
7199
7310
  // ../argus-watcher/dist/cdp/redaction.js
7200
7311
  var SENSITIVE_KEYS = new Set(["token", "access_token", "auth", "authorization", "code", "password", "pass"]);
7312
+ var AUTH_HEADER_NAMES = new Set([
7313
+ "authorization",
7314
+ "cookie",
7315
+ "x-api-key",
7316
+ "x-auth-token",
7317
+ "x-csrf-token",
7318
+ "x-csrftoken",
7319
+ "x-xsrf-token",
7320
+ "csrf-token",
7321
+ "xsrf-token"
7322
+ ]);
7201
7323
  var redactUrl = (value) => {
7202
7324
  if (!value) {
7203
7325
  return value;
@@ -7229,6 +7351,76 @@ var redactUrl = (value) => {
7229
7351
  url.search = search ? `?${search}` : "";
7230
7352
  return url.toString();
7231
7353
  };
7354
+ var pickCapturedAuthHeaders = (headers) => {
7355
+ if (!headers) {
7356
+ return;
7357
+ }
7358
+ const captured = {};
7359
+ for (const [name, rawValue] of Object.entries(headers)) {
7360
+ const normalizedName = name.trim().toLowerCase();
7361
+ if (!normalizedName || !AUTH_HEADER_NAMES.has(normalizedName)) {
7362
+ continue;
7363
+ }
7364
+ const value = normalizeHeaderValue(rawValue);
7365
+ if (!value) {
7366
+ continue;
7367
+ }
7368
+ captured[normalizedName] = redactHeaderValue(normalizedName, value);
7369
+ }
7370
+ return Object.keys(captured).length > 0 ? captured : undefined;
7371
+ };
7372
+ var mergeCapturedAuthHeaders = (current, incoming) => {
7373
+ if (!current) {
7374
+ return incoming;
7375
+ }
7376
+ if (!incoming) {
7377
+ return current;
7378
+ }
7379
+ return { ...current, ...incoming };
7380
+ };
7381
+ var normalizeHeaderValue = (value) => {
7382
+ if (typeof value === "string") {
7383
+ const trimmed = value.trim();
7384
+ return trimmed || null;
7385
+ }
7386
+ if (typeof value === "number" || typeof value === "boolean") {
7387
+ return String(value);
7388
+ }
7389
+ if (Array.isArray(value)) {
7390
+ const joined = value.map((item) => normalizeHeaderValue(item)).filter((item) => Boolean(item)).join(", ");
7391
+ return joined || null;
7392
+ }
7393
+ return null;
7394
+ };
7395
+ var redactHeaderValue = (name, value) => {
7396
+ if (name === "authorization") {
7397
+ return redactAuthorizationHeader(value);
7398
+ }
7399
+ if (name === "cookie") {
7400
+ return redactCookieHeader(value);
7401
+ }
7402
+ return redactToken(value);
7403
+ };
7404
+ var redactAuthorizationHeader = (value) => {
7405
+ const match = value.match(/^([A-Za-z]+)\s+(.+)$/);
7406
+ if (!match) {
7407
+ return redactToken(value);
7408
+ }
7409
+ return `${match[1]} ${redactToken(match[2])}`;
7410
+ };
7411
+ var redactCookieHeader = (value) => {
7412
+ const parts = value.split(";").map((entry) => entry.trim()).filter(Boolean).map((entry) => {
7413
+ const [name] = entry.split("=");
7414
+ return name ? `${name}=<redacted>` : null;
7415
+ }).filter((entry) => Boolean(entry));
7416
+ return parts.join("; ");
7417
+ };
7418
+ var redactToken = (value) => {
7419
+ if (value.length <= 8) {
7420
+ return "*".repeat(value.length);
7421
+ }
7422
+ return `${value.slice(0, 4)}...${value.slice(-4)}`;
7423
+ };
7232
7424
 
7233
7425
  // ../argus-watcher/dist/cdp/networkCapture.js
7234
7426
  var createNetworkCapture = (options) => {
@@ -7242,6 +7434,7 @@ var createNetworkCapture = (options) => {
7242
7434
  requestId,
7243
7435
  url: "",
7244
7436
  method: "GET",
7437
+ requestHeaders: undefined,
7245
7438
  resourceType: null,
7246
7439
  status: null,
7247
7440
  encodedDataLength: null,
@@ -7264,6 +7457,7 @@ var createNetworkCapture = (options) => {
7264
7457
  requestId: record.requestId,
7265
7458
  url: redactUrl(record.url),
7266
7459
  method: record.method,
7460
+ requestHeaders: record.requestHeaders,
7267
7461
  resourceType: record.resourceType,
7268
7462
  status: record.status,
7269
7463
  encodedDataLength: record.encodedDataLength,
@@ -7281,9 +7475,19 @@ var createNetworkCapture = (options) => {
7281
7475
  const entry = getOrCreate(requestId);
7282
7476
  entry.url = payload.request?.url ?? entry.url;
7283
7477
  entry.method = payload.request?.method ?? entry.method;
7478
+ entry.requestHeaders = mergeCapturedAuthHeaders(entry.requestHeaders, pickCapturedAuthHeaders(payload.request?.headers));
7284
7479
  entry.resourceType = payload.type ?? entry.resourceType;
7285
7480
  entry.startTime = typeof payload.timestamp === "number" ? payload.timestamp : entry.startTime;
7286
7481
  });
7482
+ options.session.onEvent("Network.requestWillBeSentExtraInfo", (params) => {
7483
+ const payload = params;
7484
+ const requestId = payload.requestId;
7485
+ if (!requestId) {
7486
+ return;
7487
+ }
7488
+ const entry = getOrCreate(requestId);
7489
+ entry.requestHeaders = mergeCapturedAuthHeaders(entry.requestHeaders, pickCapturedAuthHeaders(payload.headers));
7490
+ });
7287
7491
  options.session.onEvent("Network.responseReceived", (params) => {
7288
7492
  const payload = params;
7289
7493
  const requestId = payload.requestId;
@@ -7292,6 +7496,7 @@ var createNetworkCapture = (options) => {
7292
7496
  }
7293
7497
  const entry = getOrCreate(requestId);
7294
7498
  entry.status = typeof payload.response?.status === "number" ? payload.response.status : entry.status;
7499
+ entry.requestHeaders = mergeCapturedAuthHeaders(entry.requestHeaders, pickCapturedAuthHeaders(payload.response?.requestHeaders));
7295
7500
  entry.resourceType = payload.type ?? entry.resourceType;
7296
7501
  });
7297
7502
  options.session.onEvent("Network.loadingFinished", (params) => {
@@ -9735,7 +9940,7 @@ class SessionManager {
9735
9940
  const enabledDomains = new Set;
9736
9941
  const tabHandlers = new Map;
9737
9942
  this.eventHandlers.set(tabId, tabHandlers);
9738
- const handle37 = {
9943
+ const handle38 = {
9739
9944
  isAttached: () => this.sessions.has(tabId),
9740
9945
  sendAndWait: async (method, params, options) => {
9741
9946
  if (!this.sessions.has(tabId)) {
@@ -9780,7 +9985,7 @@ class SessionManager {
9780
9985
  attachedAt: Date.now(),
9781
9986
  topFrameId: message.topFrameId ?? null,
9782
9987
  frames: message.frames ?? [],
9783
- handle: handle37,
9988
+ handle: handle38,
9784
9989
  enabledDomains
9785
9990
  };
9786
9991
  this.sessions.set(tabId, session);
@@ -9850,6 +10055,8 @@ class SessionManager {
9850
10055
  var createEmptyFrameState = () => ({
9851
10056
  topFrameId: null,
9852
10057
  requestedFrameId: null,
10058
+ requestedFrameHint: null,
10059
+ requestedFrameDetached: false,
9853
10060
  activeFrameId: null,
9854
10061
  activeAttachedAt: null,
9855
10062
  frames: new Map,
@@ -9948,12 +10155,113 @@ var parseExecutionContext = (params) => {
9948
10155
  isDefault: record.context.auxData?.isDefault === true
9949
10156
  };
9950
10157
  };
9951
- var resolveRequestedFrameId = (state, requestedFrameId) => {
10158
+ var createRequestedFrameHint = (frame) => {
10159
+ if (!frame) {
10160
+ return null;
10161
+ }
10162
+ return {
10163
+ url: frame.url || null,
10164
+ title: frame.title?.trim() || null
10165
+ };
10166
+ };
10167
+ var resolveRequestedFrameId = (state, requestedFrameId, requestedFrameHint) => {
9952
10168
  if (!requestedFrameId) {
9953
10169
  return null;
9954
10170
  }
9955
- return state.frames.has(requestedFrameId) ? requestedFrameId : null;
10171
+ if (state.frames.has(requestedFrameId)) {
10172
+ return requestedFrameId;
10173
+ }
10174
+ if (!requestedFrameHint) {
10175
+ return null;
10176
+ }
10177
+ const urlMatch = requestedFrameHint.url == null ? null : findSingleMatchingFrameId(state, (frame) => frame.url === requestedFrameHint.url);
10178
+ if (urlMatch) {
10179
+ return urlMatch;
10180
+ }
10181
+ if (requestedFrameHint.url != null || !requestedFrameHint.title) {
10182
+ return null;
10183
+ }
10184
+ return findSingleMatchingFrameId(state, (frame) => frame.title?.trim() === requestedFrameHint.title);
10185
+ };
10186
+ var resolveRequestedTarget = (state) => {
10187
+ if (state.requestedFrameId == null) {
10188
+ return { kind: "page" };
10189
+ }
10190
+ const nextFrameId = resolveRequestedFrameId(state, state.requestedFrameId, state.requestedFrameHint);
10191
+ if (nextFrameId) {
10192
+ return { kind: "frame", frameId: nextFrameId };
10193
+ }
10194
+ return state.requestedFrameDetached ? { kind: "page" } : { kind: "pending" };
10195
+ };
10196
+ var findSingleMatchingFrameId = (state, predicate) => {
10197
+ let matchId = null;
10198
+ for (const frame of state.frames.values()) {
10199
+ if (!predicate(frame)) {
10200
+ continue;
10201
+ }
10202
+ if (matchId) {
10203
+ return null;
10204
+ }
10205
+ matchId = frame.frameId;
10206
+ }
10207
+ return matchId;
10208
+ };
10209
+
10210
+ // ../argus-watcher/dist/sources/extension-delegating-session.js
10211
+ var createDelegatingSession = (options) => {
10212
+ const subscriptions = new Set;
10213
+ const rebindSubscriptions = () => {
10214
+ for (const subscription of subscriptions) {
10215
+ subscription.unbind();
10216
+ const currentSession = options.getCurrentSession();
10217
+ if (!currentSession) {
10218
+ continue;
10219
+ }
10220
+ subscription.off = currentSession.handle.onEvent(subscription.method, subscription.handler);
10221
+ }
10222
+ };
10223
+ const disposeSubscriptions = () => {
10224
+ for (const subscription of subscriptions) {
10225
+ subscription.unbind();
10226
+ }
10227
+ subscriptions.clear();
10228
+ };
10229
+ const controller = {
10230
+ rebind: rebindSubscriptions,
10231
+ dispose: disposeSubscriptions
10232
+ };
10233
+ const session = {
10234
+ isAttached: () => options.getCurrentSession()?.handle.isAttached() ?? false,
10235
+ sendAndWait: async (method, params, commandOptions) => {
10236
+ const currentSession = options.requireCurrentSession();
10237
+ const targetContext = options.getTargetContext();
10238
+ const nextParams = options.mapParams ? options.mapParams(method, params) : params;
10239
+ const nextOptions = targetContext.kind === "frame" && targetContext.sessionId ? { ...commandOptions ?? {}, sessionId: targetContext.sessionId } : commandOptions;
10240
+ return currentSession.handle.sendAndWait(method, nextParams, nextOptions);
10241
+ },
10242
+ onEvent: (method, handler) => {
10243
+ const subscription = createDelegatingEventSubscription(method, handler);
10244
+ subscriptions.add(subscription);
10245
+ controller.rebind();
10246
+ return () => {
10247
+ subscription.unbind();
10248
+ subscriptions.delete(subscription);
10249
+ };
10250
+ },
10251
+ getTargetContext: options.getTargetContext
10252
+ };
10253
+ controller.rebind();
10254
+ return { session, controller };
9956
10255
  };
10256
+ var createDelegatingEventSubscription = (method, handler) => ({
10257
+ method,
10258
+ handler,
10259
+ off: null,
10260
+ unbind() {
10261
+ this.off?.();
10262
+ this.off = null;
10263
+ }
10264
+ });
9957
10265
 
9958
10266
  // ../argus-watcher/dist/sources/extension-log-events.js
9959
10267
  var toConsoleEvent2 = (params, session, config) => {
@@ -10054,6 +10362,103 @@ var applyStripPrefixes = (file, prefixes) => {
10054
10362
  return file;
10055
10363
  };
10056
10364
 
10365
+ // ../argus-watcher/dist/sources/extension-session-events.js
10366
+ var registerExtensionSessionEventHandlers = ({ session, events, ignoreMatcher, stripUrlPrefixes: stripUrlPrefixes2, getOrCreateFrameState, reconcileTargetSelection, removeFrame, refreshFrameTitle, emitTargetChanged, setCurrentSession }) => {
10367
+ session.handle.onEvent("Runtime.executionContextCreated", (params, meta) => {
10368
+ const context = parseExecutionContext(params);
10369
+ if (!context?.isDefault || !context.frameId) {
10370
+ return;
10371
+ }
10372
+ const state = getOrCreateFrameState(session.tabId);
10373
+ state.executionContexts.set(context.frameId, context.id);
10374
+ const frame = state.frames.get(context.frameId);
10375
+ if (frame) {
10376
+ frame.sessionId = meta.sessionId ?? null;
10377
+ }
10378
+ refreshFrameTitle(session, context.frameId, context.id);
10379
+ reconcileTargetSelection(session);
10380
+ });
10381
+ session.handle.onEvent("Runtime.executionContextsCleared", () => {
10382
+ const state = getOrCreateFrameState(session.tabId);
10383
+ state.executionContexts.clear();
10384
+ state.pendingTitleLoads.clear();
10385
+ });
10386
+ session.handle.onEvent("Runtime.executionContextDestroyed", (params) => {
10387
+ const record = params;
10388
+ if (record.executionContextId == null) {
10389
+ return;
10390
+ }
10391
+ const state = getOrCreateFrameState(session.tabId);
10392
+ for (const [frameId, contextId] of state.executionContexts.entries()) {
10393
+ if (contextId === record.executionContextId) {
10394
+ state.executionContexts.delete(frameId);
10395
+ state.pendingTitleLoads.delete(frameId);
10396
+ }
10397
+ }
10398
+ });
10399
+ session.handle.onEvent("Page.frameNavigated", (params, meta) => {
10400
+ const frame = parseFrame(params);
10401
+ if (!frame) {
10402
+ return;
10403
+ }
10404
+ const state = getOrCreateFrameState(session.tabId);
10405
+ state.frames.set(frame.frameId, frame);
10406
+ frame.sessionId = meta.sessionId ?? null;
10407
+ if (!frame.parentFrameId) {
10408
+ if (!meta.sessionId) {
10409
+ state.topFrameId = frame.frameId;
10410
+ session.url = frame.url;
10411
+ } else if (state.topFrameId == null) {
10412
+ state.topFrameId = frame.parentFrameId;
10413
+ }
10414
+ } else if (state.executionContexts.has(frame.frameId)) {
10415
+ refreshFrameTitle(session, frame.frameId);
10416
+ }
10417
+ setCurrentSession(session);
10418
+ if (!frame.parentFrameId && !meta.sessionId) {
10419
+ events.onPageNavigation?.({ url: frame.url, title: session.title ?? null });
10420
+ }
10421
+ if (reconcileTargetSelection(session)) {
10422
+ return;
10423
+ }
10424
+ if (!frame.parentFrameId && state.activeFrameId == null || state.activeFrameId === frame.frameId) {
10425
+ emitTargetChanged(session);
10426
+ }
10427
+ });
10428
+ session.handle.onEvent("Page.frameAttached", (params, meta) => {
10429
+ const record = params;
10430
+ if (!record.frameId) {
10431
+ return;
10432
+ }
10433
+ const state = getOrCreateFrameState(session.tabId);
10434
+ state.frames.set(record.frameId, {
10435
+ frameId: record.frameId,
10436
+ parentFrameId: record.parentFrameId ?? state.topFrameId ?? null,
10437
+ url: "",
10438
+ title: null,
10439
+ sessionId: meta.sessionId ?? null
10440
+ });
10441
+ reconcileTargetSelection(session);
10442
+ });
10443
+ session.handle.onEvent("Page.frameDetached", (params) => {
10444
+ const record = params;
10445
+ if (!record.frameId) {
10446
+ return;
10447
+ }
10448
+ removeFrame(session.tabId, record.frameId);
10449
+ reconcileTargetSelection(session);
10450
+ });
10451
+ session.handle.onEvent("Page.domContentEventFired", () => {
10452
+ events.onPageLoad?.();
10453
+ });
10454
+ session.handle.onEvent("Runtime.consoleAPICalled", (params) => {
10455
+ events.onLog(toConsoleEvent2(params, session, { ignoreMatcher, stripUrlPrefixes: stripUrlPrefixes2 }));
10456
+ });
10457
+ session.handle.onEvent("Runtime.exceptionThrown", (params) => {
10458
+ events.onLog(toExceptionEvent2(params, session, { ignoreMatcher, stripUrlPrefixes: stripUrlPrefixes2 }));
10459
+ });
10460
+ };
10461
+
10057
10462
  // ../argus-watcher/dist/sources/extension-source.js
10058
10463
  var createExtensionSource = (options) => {
10059
10464
  const { events, ignoreMatcher, stripUrlPrefixes: stripUrlPrefixes2, watcherId, watcherHost, watcherPort } = options;
@@ -10067,6 +10472,7 @@ var createExtensionSource = (options) => {
10067
10472
  let currentSession = null;
10068
10473
  let stopping = false;
10069
10474
  const frameStateByTabId = new Map;
10475
+ const delegatingSessions = new Set;
10070
10476
  const getCurrentExtensionSession = () => {
10071
10477
  if (!currentSession) {
10072
10478
  throw createNotAttachedError();
@@ -10077,6 +10483,7 @@ var createExtensionSource = (options) => {
10077
10483
  onAttach: (session) => {
10078
10484
  console.error(`[ExtensionSource] Tab attached: ${session.tabId} - ${session.url}`);
10079
10485
  currentSession = session;
10486
+ rebindDelegatingSessions();
10080
10487
  seedFrameState(session);
10081
10488
  bootstrapAttachedSession(session);
10082
10489
  },
@@ -10085,6 +10492,7 @@ var createExtensionSource = (options) => {
10085
10492
  if (currentSession?.tabId === tabId) {
10086
10493
  currentSession = null;
10087
10494
  }
10495
+ rebindDelegatingSessions();
10088
10496
  frameStateByTabId.delete(tabId);
10089
10497
  emitStatus(null, reason);
10090
10498
  events.onDetach?.(reason);
@@ -10093,13 +10501,16 @@ var createExtensionSource = (options) => {
10093
10501
  onTargetSelected: (tabId, frameId) => {
10094
10502
  const session = currentSession;
10095
10503
  if (!session || session.tabId !== tabId) {
10096
- getOrCreateFrameState(tabId).requestedFrameId = frameId;
10504
+ const state = getOrCreateFrameState(tabId);
10505
+ setRequestedTargetSelection(state, frameId);
10097
10506
  return;
10098
10507
  }
10099
10508
  requestTargetSelection(session, frameId);
10100
10509
  }
10101
10510
  });
10102
- const proxySession = createDelegatingSession({
10511
+ const { session: proxySession, controller: proxyController } = createDelegatingSession({
10512
+ getCurrentSession: () => currentSession,
10513
+ requireCurrentSession: getCurrentExtensionSession,
10103
10514
  getTargetContext: () => getCurrentTargetContext() ?? { kind: "page" },
10104
10515
  mapParams: (method, params) => {
10105
10516
  const targetContext = getCurrentTargetContext();
@@ -10115,9 +10526,13 @@ var createExtensionSource = (options) => {
10115
10526
  };
10116
10527
  }
10117
10528
  });
10118
- const pageSession = createDelegatingSession({
10529
+ delegatingSessions.add(proxyController);
10530
+ const { session: pageSession, controller: pageController } = createDelegatingSession({
10531
+ getCurrentSession: () => currentSession,
10532
+ requireCurrentSession: getCurrentExtensionSession,
10119
10533
  getTargetContext: () => ({ kind: "page" })
10120
10534
  });
10535
+ delegatingSessions.add(pageController);
10121
10536
  messaging.start();
10122
10537
  sendHostInfo();
10123
10538
  messaging.onDisconnect(() => {
@@ -10129,6 +10544,7 @@ var createExtensionSource = (options) => {
10129
10544
  });
10130
10545
  const stop = async () => {
10131
10546
  stopping = true;
10547
+ disposeDelegatingSessions();
10132
10548
  messaging.stop();
10133
10549
  };
10134
10550
  const listTargets = async () => {
@@ -10151,7 +10567,8 @@ var createExtensionSource = (options) => {
10151
10567
  const target = parseExtensionTargetId(targetId);
10152
10568
  const session = currentSession;
10153
10569
  if (!session || session.tabId !== target.tabId) {
10154
- getOrCreateFrameState(target.tabId).requestedFrameId = target.frameId;
10570
+ const state = getOrCreateFrameState(target.tabId);
10571
+ setRequestedTargetSelection(state, target.frameId);
10155
10572
  sessionManager.attachTab(target.tabId);
10156
10573
  return;
10157
10574
  }
@@ -10184,9 +10601,33 @@ var createExtensionSource = (options) => {
10184
10601
  pid: hostInfo.watcherPid
10185
10602
  });
10186
10603
  }
10604
+ function rebindDelegatingSessions() {
10605
+ for (const controller of delegatingSessions) {
10606
+ controller.rebind();
10607
+ }
10608
+ }
10609
+ function disposeDelegatingSessions() {
10610
+ for (const controller of delegatingSessions) {
10611
+ controller.dispose();
10612
+ }
10613
+ delegatingSessions.clear();
10614
+ }
10187
10615
  async function bootstrapAttachedSession(session) {
10188
10616
  try {
10189
- registerSessionEventHandlers(session);
10617
+ registerExtensionSessionEventHandlers({
10618
+ session,
10619
+ events,
10620
+ ignoreMatcher,
10621
+ stripUrlPrefixes: stripUrlPrefixes2,
10622
+ getOrCreateFrameState,
10623
+ reconcileTargetSelection,
10624
+ removeFrame,
10625
+ refreshFrameTitle,
10626
+ emitTargetChanged,
10627
+ setCurrentSession: (nextSession) => {
10628
+ currentSession = nextSession;
10629
+ }
10630
+ });
10190
10631
  await enableBootstrapDomains(session);
10191
10632
  await refreshFrameTree(session);
10192
10633
  if (currentSession?.tabId !== session.tabId) {
@@ -10209,101 +10650,6 @@ var createExtensionSource = (options) => {
10209
10650
  await session.handle.sendAndWait("Runtime.enable");
10210
10651
  await session.handle.sendAndWait("Page.enable");
10211
10652
  }
10212
- function registerSessionEventHandlers(session) {
10213
- session.handle.onEvent("Runtime.executionContextCreated", (params, meta) => {
10214
- const context = parseExecutionContext(params);
10215
- if (!context?.isDefault || !context.frameId) {
10216
- return;
10217
- }
10218
- const state = getOrCreateFrameState(session.tabId);
10219
- state.executionContexts.set(context.frameId, context.id);
10220
- const frame = state.frames.get(context.frameId);
10221
- if (frame) {
10222
- frame.sessionId = meta.sessionId ?? null;
10223
- }
10224
- refreshFrameTitle(session, context.frameId, context.id);
10225
- reconcileTargetSelection(session);
10226
- });
10227
- session.handle.onEvent("Runtime.executionContextsCleared", () => {
10228
- const state = getOrCreateFrameState(session.tabId);
10229
- state.executionContexts.clear();
10230
- state.pendingTitleLoads.clear();
10231
- });
10232
- session.handle.onEvent("Runtime.executionContextDestroyed", (params) => {
10233
- const record = params;
10234
- if (record.executionContextId == null) {
10235
- return;
10236
- }
10237
- const state = getOrCreateFrameState(session.tabId);
10238
- for (const [frameId, contextId] of state.executionContexts.entries()) {
10239
- if (contextId === record.executionContextId) {
10240
- state.executionContexts.delete(frameId);
10241
- state.pendingTitleLoads.delete(frameId);
10242
- }
10243
- }
10244
- });
10245
- session.handle.onEvent("Page.frameNavigated", (params, meta) => {
10246
- const frame = parseFrame(params);
10247
- if (!frame) {
10248
- return;
10249
- }
10250
- const state = getOrCreateFrameState(session.tabId);
10251
- state.frames.set(frame.frameId, frame);
10252
- frame.sessionId = meta.sessionId ?? null;
10253
- if (!frame.parentFrameId) {
10254
- if (!meta.sessionId) {
10255
- state.topFrameId = frame.frameId;
10256
- session.url = frame.url;
10257
- } else if (state.topFrameId == null) {
10258
- state.topFrameId = frame.parentFrameId;
10259
- }
10260
- } else if (state.executionContexts.has(frame.frameId)) {
10261
- refreshFrameTitle(session, frame.frameId);
10262
- }
10263
- currentSession = session;
10264
- if (!frame.parentFrameId && !meta.sessionId) {
10265
- events.onPageNavigation?.({ url: frame.url, title: session.title ?? null });
10266
- }
10267
- if (reconcileTargetSelection(session)) {
10268
- return;
10269
- }
10270
- if (!frame.parentFrameId && state.activeFrameId == null || state.activeFrameId === frame.frameId) {
10271
- emitTargetChanged(session);
10272
- }
10273
- });
10274
- session.handle.onEvent("Page.frameAttached", (params, meta) => {
10275
- const record = params;
10276
- if (!record.frameId) {
10277
- return;
10278
- }
10279
- const state = getOrCreateFrameState(session.tabId);
10280
- state.frames.set(record.frameId, {
10281
- frameId: record.frameId,
10282
- parentFrameId: record.parentFrameId ?? state.topFrameId ?? null,
10283
- url: "",
10284
- title: null,
10285
- sessionId: meta.sessionId ?? null
10286
- });
10287
- reconcileTargetSelection(session);
10288
- });
10289
- session.handle.onEvent("Page.frameDetached", (params) => {
10290
- const record = params;
10291
- if (!record.frameId) {
10292
- return;
10293
- }
10294
- removeFrame(session.tabId, record.frameId);
10295
- reconcileTargetSelection(session);
10296
- });
10297
- session.handle.onEvent("Page.domContentEventFired", () => {
10298
- events.onPageLoad?.();
10299
- });
10300
- session.handle.onEvent("Runtime.consoleAPICalled", (params) => {
10301
- events.onLog(toConsoleEvent2(params, session, { ignoreMatcher, stripUrlPrefixes: stripUrlPrefixes2 }));
10302
- });
10303
- session.handle.onEvent("Runtime.exceptionThrown", (params) => {
10304
- events.onLog(toExceptionEvent2(params, session, { ignoreMatcher, stripUrlPrefixes: stripUrlPrefixes2 }));
10305
- });
10306
- }
10307
10653
  function getCurrentTargetContext() {
10308
10654
  const session = currentSession;
10309
10655
  if (!session) {
@@ -10390,30 +10736,47 @@ var createExtensionSource = (options) => {
10390
10736
  }
10391
10737
  function requestTargetSelection(session, frameId) {
10392
10738
  const state = getOrCreateFrameState(session.tabId);
10393
- state.requestedFrameId = frameId;
10739
+ setRequestedTargetSelection(state, frameId);
10394
10740
  reconcileTargetSelection(session);
10395
10741
  }
10742
+ function setRequestedTargetSelection(state, frameId) {
10743
+ const frame = frameId ? state.frames.get(frameId) : null;
10744
+ state.requestedFrameId = frameId;
10745
+ state.requestedFrameHint = createRequestedFrameHint(frame);
10746
+ state.requestedFrameDetached = false;
10747
+ }
10396
10748
  function reconcileTargetSelection(session) {
10397
10749
  const state = getOrCreateFrameState(session.tabId);
10398
- const nextActiveFrameId = resolveRequestedFrameId(state, state.requestedFrameId);
10399
- if (state.requestedFrameId == null) {
10400
- if (state.activeFrameId == null) {
10401
- if (state.activeAttachedAt == null) {
10402
- state.activeAttachedAt = Date.now();
10403
- emitTargetChanged(session);
10404
- return true;
10405
- }
10406
- return false;
10407
- }
10408
- state.activeFrameId = null;
10409
- state.activeAttachedAt = Date.now();
10410
- emitTargetChanged(session);
10411
- return true;
10750
+ const resolution = resolveRequestedTarget(state);
10751
+ if (resolution.kind === "page") {
10752
+ state.requestedFrameDetached = false;
10753
+ return activatePageTarget(session, state);
10412
10754
  }
10413
- if (nextActiveFrameId == null || state.activeFrameId === nextActiveFrameId) {
10755
+ if (resolution.kind === "pending") {
10414
10756
  return false;
10415
10757
  }
10416
- state.activeFrameId = nextActiveFrameId;
10758
+ state.requestedFrameDetached = false;
10759
+ if (state.activeFrameId === resolution.frameId) {
10760
+ return false;
10761
+ }
10762
+ return activateFrameTarget(session, state, resolution.frameId);
10763
+ }
10764
+ function activatePageTarget(session, state) {
10765
+ if (state.activeFrameId == null) {
10766
+ if (state.activeAttachedAt == null) {
10767
+ state.activeAttachedAt = Date.now();
10768
+ emitTargetChanged(session);
10769
+ return true;
10770
+ }
10771
+ return false;
10772
+ }
10773
+ state.activeFrameId = null;
10774
+ state.activeAttachedAt = Date.now();
10775
+ emitTargetChanged(session);
10776
+ return true;
10777
+ }
10778
+ function activateFrameTarget(session, state, frameId) {
10779
+ state.activeFrameId = frameId;
10417
10780
  state.activeAttachedAt = Date.now();
10418
10781
  emitTargetChanged(session);
10419
10782
  return true;
@@ -10430,8 +10793,10 @@ var createExtensionSource = (options) => {
10430
10793
  for (const childId of childIds) {
10431
10794
  removeFrame(tabId, childId);
10432
10795
  }
10433
- if (state.requestedFrameId === frameId) {
10434
- state.requestedFrameId = null;
10796
+ if (state.activeFrameId === frameId) {
10797
+ state.requestedFrameDetached = state.requestedFrameId === frameId;
10798
+ state.activeFrameId = null;
10799
+ state.activeAttachedAt = null;
10435
10800
  }
10436
10801
  state.frames.delete(frameId);
10437
10802
  state.executionContexts.delete(frameId);
@@ -10471,25 +10836,6 @@ var createExtensionSource = (options) => {
10471
10836
  state.pendingTitleLoads.delete(frameId);
10472
10837
  }
10473
10838
  }
10474
- function createDelegatingSession(config) {
10475
- return {
10476
- isAttached: () => currentSession?.handle.isAttached() ?? false,
10477
- sendAndWait: async (method, params, options2) => {
10478
- const session = getCurrentExtensionSession();
10479
- const targetContext = config.getTargetContext();
10480
- const nextParams = config.mapParams ? config.mapParams(method, params) : params;
10481
- const nextOptions = targetContext.kind === "frame" && targetContext.sessionId ? { ...options2 ?? {}, sessionId: targetContext.sessionId } : options2;
10482
- return session.handle.sendAndWait(method, nextParams, nextOptions);
10483
- },
10484
- onEvent: (method, handler) => {
10485
- if (!currentSession) {
10486
- return () => {};
10487
- }
10488
- return currentSession.handle.onEvent(method, handler);
10489
- },
10490
- getTargetContext: config.getTargetContext
10491
- };
10492
- }
10493
10839
  };
10494
10840
  var tabToTarget = (tab) => ({
10495
10841
  id: formatPageTargetId(tab.tabId),
@@ -10500,62 +10846,15 @@ var tabToTarget = (tab) => ({
10500
10846
  attached: tab.attached
10501
10847
  });
10502
10848
 
10503
- // ../argus-watcher/dist/index.js
10504
- var startWatcher = async (options) => {
10505
- if (!options.id) {
10506
- throw new Error("Watcher id is required");
10507
- }
10508
- const watcherId = await resolveUniqueWatcherId(options.id);
10509
- const sourceMode = options.source ?? "cdp";
10510
- const host = options.host ?? "127.0.0.1";
10511
- const port = options.port ?? 0;
10512
- const chrome = options.chrome ?? { host: "127.0.0.1", port: 9222 };
10513
- const bufferSize = options.bufferSize ?? 50000;
10514
- const netBufferSize = options.bufferSize ?? 50000;
10515
- const startedAt = Date.now();
10516
- const ignoreMatcher = buildIgnoreMatcher(options.ignoreList);
10517
- const stripUrlPrefixes2 = options.location?.stripUrlPrefixes;
10518
- const artifactsBaseDir = resolveArtifactsBaseDir(options.artifacts?.base, watcherId);
10519
- const logsEnabled = options.artifacts?.logs?.enabled === true;
10520
- const logsDir = path7.join(artifactsBaseDir, "logs");
10521
- const includeTimestamps = options.artifacts?.logs?.includeTimestamps ?? false;
10522
- const maxFiles = resolveMaxFiles(options.artifacts?.logs?.maxFiles);
10523
- const netEnabled = sourceMode === "cdp" && options.net?.enabled === true;
10524
- const pageConsoleLogging = options.pageConsoleLogging ?? "minimal";
10525
- const events = new Emittery;
10526
- const buffer = new LogBuffer(bufferSize);
10527
- const netBuffer = netEnabled ? new NetBuffer(netBufferSize) : null;
10849
+ // ../argus-watcher/dist/startWatcherRuntime.js
10850
+ var createWatcherHandle = async (options, watcherId) => {
10851
+ const setup = normalizeWatcherSetup(options, watcherId);
10852
+ const { sourceMode, host, port, chrome, artifactsBaseDir, pageConsoleLogging, ignoreMatcher, stripUrlPrefixes: stripUrlPrefixes2, events, buffer, netBuffer, record, fileLogger, sessionHandle, emulationController, throttleController } = setup;
10528
10853
  let closing = false;
10529
10854
  let readyForShutdown = false;
10530
10855
  let shutdownRequested = false;
10531
10856
  let closeOnce = null;
10532
10857
  let cdpStatus = { attached: false, target: null };
10533
- const fileLogger = logsEnabled ? new WatcherFileLogger({
10534
- watcherId,
10535
- startedAt,
10536
- logsDir,
10537
- chrome: sourceMode === "cdp" ? chrome : undefined,
10538
- match: options.match,
10539
- maxFiles,
10540
- includeTimestamps,
10541
- buildFilename: options.artifacts?.logs?.buildFilename
10542
- }) : null;
10543
- const record = {
10544
- id: watcherId,
10545
- host,
10546
- port,
10547
- pid: process.pid,
10548
- cwd: process.cwd(),
10549
- startedAt,
10550
- updatedAt: Date.now(),
10551
- match: sourceMode === "cdp" ? options.match : undefined,
10552
- chrome: sourceMode === "cdp" ? chrome : undefined,
10553
- includeTimestamps,
10554
- source: sourceMode
10555
- };
10556
- const sessionHandle = createCdpSessionHandle();
10557
- const emulationController = createEmulationController();
10558
- const throttleController = createThrottleController();
10559
10858
  const logToPageConsole = (message) => {
10560
10859
  if (pageConsoleLogging === "none") {
10561
10860
  return;
@@ -10672,6 +10971,37 @@ var startWatcher = async (options) => {
10672
10971
  console.warn(`[Watcher] Failed to run inject script for watcher ${record.id}: ${formatError4(error)}`);
10673
10972
  }
10674
10973
  };
10974
+ const handleSourceLog = (event) => {
10975
+ buffer.add(event);
10976
+ fileLogger?.writeEvent(event);
10977
+ };
10978
+ const handlePageNavigation = (info) => {
10979
+ fileLogger?.rotate(info);
10980
+ onIndicatorNavigation(getIndicatorSession(), info);
10981
+ runtimeEditor?.reset();
10982
+ };
10983
+ const handlePageIntl = (info) => {
10984
+ fileLogger?.setPageIntl(info);
10985
+ };
10986
+ const handleSourceAttach = async (session, target) => {
10987
+ runtimeEditor?.rebind();
10988
+ await emulationController.onAttach(session);
10989
+ await throttleController.onAttach(session);
10990
+ await networkCapture?.onAttached();
10991
+ onIndicatorAttach(session, target);
10992
+ await maybeInjectOnAttach(session, target);
10993
+ };
10994
+ const handleTargetChanged = (session, target) => {
10995
+ onIndicatorAttach(session, target);
10996
+ };
10997
+ const handleSourceDetach = (reason) => {
10998
+ runtimeEditor?.rebind();
10999
+ networkCapture?.onDetached();
11000
+ indicatorController?.onDetach();
11001
+ if (reason != null) {
11002
+ traceRecorder.onDetached(reason);
11003
+ }
11004
+ };
10675
11005
  let sourceHandle;
10676
11006
  let networkCapture = null;
10677
11007
  let traceRecorder;
@@ -10680,33 +11010,15 @@ var startWatcher = async (options) => {
10680
11010
  if (sourceMode === "extension") {
10681
11011
  sourceHandle = createExtensionSource({
10682
11012
  events: {
10683
- onLog: (event) => {
10684
- buffer.add(event);
10685
- fileLogger?.writeEvent(event);
10686
- },
11013
+ onLog: handleSourceLog,
10687
11014
  onStatus: updateCdpStatus,
10688
- onPageNavigation: (info) => {
10689
- fileLogger?.rotate(info);
10690
- onIndicatorNavigation(getIndicatorSession(), info);
10691
- runtimeEditor?.reset();
10692
- },
11015
+ onPageNavigation: handlePageNavigation,
10693
11016
  onPageLoad: onIndicatorLoad,
10694
- onPageIntl: (info) => {
10695
- fileLogger?.setPageIntl(info);
10696
- },
10697
- onAttach: async (session, target) => {
10698
- runtimeEditor?.rebind();
10699
- await emulationController.onAttach(session);
10700
- await throttleController.onAttach(session);
10701
- onIndicatorAttach(session, target);
10702
- await maybeInjectOnAttach(session, target);
10703
- },
10704
- onTargetChanged: (session, target) => {
10705
- onIndicatorAttach(session, target);
10706
- },
11017
+ onPageIntl: handlePageIntl,
11018
+ onAttach: handleSourceAttach,
11019
+ onTargetChanged: handleTargetChanged,
10707
11020
  onDetach: () => {
10708
- runtimeEditor?.rebind();
10709
- indicatorController?.onDetach();
11021
+ handleSourceDetach();
10710
11022
  }
10711
11023
  },
10712
11024
  watcherId,
@@ -10715,6 +11027,7 @@ var startWatcher = async (options) => {
10715
11027
  ignoreMatcher: ignoreMatcher ? (url) => ignoreMatcher.matches(url) : null,
10716
11028
  stripUrlPrefixes: stripUrlPrefixes2
10717
11029
  });
11030
+ networkCapture = netBuffer ? createNetworkCapture({ session: sourceHandle.pageSession ?? sourceHandle.session, buffer: netBuffer }) : null;
10718
11031
  traceRecorder = createTraceRecorder({ session: sourceHandle.session, artifactsDir: artifactsBaseDir });
10719
11032
  screenshotter = createScreenshotter({ session: sourceHandle.session, artifactsDir: artifactsBaseDir });
10720
11033
  runtimeEditor = createRuntimeEditor(sourceHandle.session);
@@ -10728,33 +11041,14 @@ var startWatcher = async (options) => {
10728
11041
  match: options.match,
10729
11042
  sessionHandle,
10730
11043
  events: {
10731
- onLog: (event) => {
10732
- buffer.add(event);
10733
- fileLogger?.writeEvent(event);
10734
- },
11044
+ onLog: handleSourceLog,
10735
11045
  onStatus: updateCdpStatus,
10736
- onPageNavigation: (info) => {
10737
- fileLogger?.rotate(info);
10738
- onIndicatorNavigation(sessionHandle.session, info);
10739
- runtimeEditor?.reset();
10740
- },
11046
+ onPageNavigation: handlePageNavigation,
10741
11047
  onPageLoad: onIndicatorLoad,
10742
- onPageIntl: (info) => {
10743
- fileLogger?.setPageIntl(info);
10744
- },
10745
- onAttach: async (session, target) => {
10746
- runtimeEditor?.rebind();
10747
- await emulationController.onAttach(session);
10748
- await throttleController.onAttach(session);
10749
- await networkCapture?.onAttached();
10750
- onIndicatorAttach(session, target);
10751
- await maybeInjectOnAttach(session, target);
10752
- },
11048
+ onPageIntl: handlePageIntl,
11049
+ onAttach: handleSourceAttach,
10753
11050
  onDetach: (reason) => {
10754
- runtimeEditor?.rebind();
10755
- networkCapture?.onDetached();
10756
- traceRecorder.onDetached(reason);
10757
- indicatorController?.onDetach();
11051
+ handleSourceDetach(reason);
10758
11052
  }
10759
11053
  },
10760
11054
  watcherId,
@@ -10769,6 +11063,7 @@ var startWatcher = async (options) => {
10769
11063
  netBuffer,
10770
11064
  getWatcher: () => record,
10771
11065
  getCdpStatus: () => cdpStatus,
11066
+ pageCdpSession: sourceHandle.pageSession ?? sourceHandle.session,
10772
11067
  cdpSession: sourceHandle.session,
10773
11068
  traceRecorder,
10774
11069
  screenshotter,
@@ -10831,6 +11126,71 @@ var startWatcher = async (options) => {
10831
11126
  }
10832
11127
  };
10833
11128
  };
11129
+ var normalizeWatcherSetup = (options, watcherId) => {
11130
+ const sourceMode = options.source ?? "cdp";
11131
+ const host = options.host ?? "127.0.0.1";
11132
+ const port = options.port ?? 0;
11133
+ const chrome = options.chrome ?? { host: "127.0.0.1", port: 9222 };
11134
+ const bufferSize = options.bufferSize ?? 50000;
11135
+ const startedAt = Date.now();
11136
+ const ignoreMatcher = buildIgnoreMatcher(options.ignoreList);
11137
+ const stripUrlPrefixes2 = options.location?.stripUrlPrefixes;
11138
+ const artifactsBaseDir = resolveArtifactsBaseDir(options.artifacts?.base, watcherId);
11139
+ const logsEnabled = options.artifacts?.logs?.enabled === true;
11140
+ const logsDir = path7.join(artifactsBaseDir, "logs");
11141
+ const includeTimestamps = options.artifacts?.logs?.includeTimestamps ?? false;
11142
+ const maxFiles = resolveMaxFiles(options.artifacts?.logs?.maxFiles);
11143
+ const netEnabled = options.net?.enabled === true;
11144
+ const pageConsoleLogging = options.pageConsoleLogging ?? "minimal";
11145
+ const events = new Emittery;
11146
+ const buffer = new LogBuffer(bufferSize);
11147
+ const netBuffer = netEnabled ? new NetBuffer(bufferSize) : null;
11148
+ const fileLogger = logsEnabled ? new WatcherFileLogger({
11149
+ watcherId,
11150
+ startedAt,
11151
+ logsDir,
11152
+ chrome: sourceMode === "cdp" ? chrome : undefined,
11153
+ match: options.match,
11154
+ maxFiles,
11155
+ includeTimestamps,
11156
+ buildFilename: options.artifacts?.logs?.buildFilename
11157
+ }) : null;
11158
+ const record = {
11159
+ id: watcherId,
11160
+ host,
11161
+ port,
11162
+ pid: process.pid,
11163
+ cwd: process.cwd(),
11164
+ startedAt,
11165
+ updatedAt: Date.now(),
11166
+ match: sourceMode === "cdp" ? options.match : undefined,
11167
+ chrome: sourceMode === "cdp" ? chrome : undefined,
11168
+ includeTimestamps,
11169
+ source: sourceMode
11170
+ };
11171
+ return {
11172
+ sourceMode,
11173
+ host,
11174
+ port,
11175
+ chrome,
11176
+ watcherId,
11177
+ startedAt,
11178
+ artifactsBaseDir,
11179
+ includeTimestamps,
11180
+ netEnabled,
11181
+ pageConsoleLogging,
11182
+ ignoreMatcher,
11183
+ stripUrlPrefixes: stripUrlPrefixes2,
11184
+ events,
11185
+ buffer,
11186
+ netBuffer,
11187
+ record,
11188
+ fileLogger,
11189
+ sessionHandle: createCdpSessionHandle(),
11190
+ emulationController: createEmulationController(),
11191
+ throttleController: createThrottleController()
11192
+ };
11193
+ };
10834
11194
  var resolveArtifactsBaseDir = (base, watcherId) => {
10835
11195
  if (base !== undefined && base !== null) {
10836
11196
  if (typeof base !== "string" || base.trim() === "") {
@@ -10871,11 +11231,20 @@ var formatError4 = (error) => {
10871
11231
  return String(error);
10872
11232
  };
10873
11233
 
11234
+ // ../argus-watcher/dist/index.js
11235
+ var startWatcher = async (options) => {
11236
+ if (!options.id) {
11237
+ throw new Error("Watcher id is required");
11238
+ }
11239
+ const watcherId = await resolveUniqueWatcherId(options.id);
11240
+ return createWatcherHandle(options, watcherId);
11241
+ };
11242
+
10874
11243
  // dist/commands/chromeStart.js
10875
11244
  import { spawn } from "node:child_process";
10876
11245
  import { copyFileSync, cpSync, existsSync as existsSync2, mkdtempSync, mkdirSync, readFileSync, rmSync, statSync, writeFileSync } from "node:fs";
10877
- import { homedir, tmpdir } from "node:os";
10878
- import path8 from "node:path";
11246
+ import { homedir as homedir2, tmpdir } from "node:os";
11247
+ import path9 from "node:path";
10879
11248
 
10880
11249
  // dist/utils/chromeBin.js
10881
11250
  import { existsSync } from "node:fs";
@@ -10958,6 +11327,80 @@ var getCdpPort = async () => {
10958
11327
  return getEphemeralPort();
10959
11328
  };
10960
11329
 
11330
+ // dist/commands/startShared.js
11331
+ import fs7 from "node:fs/promises";
11332
+
11333
+ // dist/utils/paths.js
11334
+ import { homedir } from "node:os";
11335
+ import path8 from "node:path";
11336
+ var resolvePath = (input) => {
11337
+ const expanded = input.startsWith("~/") || input === "~" ? path8.join(homedir(), input.slice(1)) : input;
11338
+ return path8.resolve(expanded);
11339
+ };
11340
+
11341
+ // dist/commands/startShared.js
11342
+ var resolveInjectScript = async (inject, output) => {
11343
+ if (!inject) {
11344
+ return;
11345
+ }
11346
+ const resolvedPath = resolvePath(inject.file);
11347
+ let script;
11348
+ try {
11349
+ script = await fs7.readFile(resolvedPath, "utf8");
11350
+ } catch (error) {
11351
+ output.writeWarn(`Failed to read inject script at ${resolvedPath}: ${error instanceof Error ? error.message : String(error)}. Skipping injection.`);
11352
+ return;
11353
+ }
11354
+ if (script.trim() === "") {
11355
+ output.writeWarn(`Inject script at ${resolvedPath} is empty. Skipping injection.`);
11356
+ return;
11357
+ }
11358
+ return { script, exposeArgus: inject.exposeArgus };
11359
+ };
11360
+ var normalizeHttpUrl2 = (value) => {
11361
+ if (!value) {
11362
+ return null;
11363
+ }
11364
+ if (value.startsWith("http://") || value.startsWith("https://")) {
11365
+ return value;
11366
+ }
11367
+ return `http://${value}`;
11368
+ };
11369
+ var buildWatcherMatch = (options) => {
11370
+ const match = {};
11371
+ const url = options.url?.trim();
11372
+ if (url) {
11373
+ match.url = url;
11374
+ }
11375
+ const type = options.type?.trim();
11376
+ if (type) {
11377
+ match.type = type;
11378
+ }
11379
+ const origin = options.origin?.trim();
11380
+ if (origin) {
11381
+ match.origin = origin;
11382
+ }
11383
+ const targetId = options.target?.trim();
11384
+ if (targetId) {
11385
+ match.targetId = targetId;
11386
+ }
11387
+ const parent = options.parent?.trim();
11388
+ if (parent) {
11389
+ match.parent = parent;
11390
+ }
11391
+ return Object.keys(match).length > 0 ? match : undefined;
11392
+ };
11393
+ var registerTerminationHandlers = (terminate) => {
11394
+ const handleTermination = () => {
11395
+ terminate().then(() => process.exit(0));
11396
+ };
11397
+ process.on("SIGINT", handleTermination);
11398
+ process.on("SIGTERM", handleTermination);
11399
+ };
11400
+ var waitForever = async () => {
11401
+ await new Promise(() => {});
11402
+ };
11403
+
10961
11404
  // dist/commands/chromeStart.js
10962
11405
  var delay2 = (ms) => new Promise((resolve2) => setTimeout(resolve2, ms));
10963
11406
  var resolveChromeUserDataDir = () => {
@@ -10970,13 +11413,13 @@ var resolveChromeUserDataDir = () => {
10970
11413
  const platform = process.platform;
10971
11414
  if (platform === "darwin") {
10972
11415
  const candidates = [
10973
- path8.join(homedir(), "Library/Application Support/Google/Chrome"),
10974
- path8.join(homedir(), "Library/Application Support/Chromium")
11416
+ path9.join(homedir2(), "Library/Application Support/Google/Chrome"),
11417
+ path9.join(homedir2(), "Library/Application Support/Chromium")
10975
11418
  ];
10976
11419
  return candidates.find((candidate) => existsSync2(candidate)) ?? null;
10977
11420
  }
10978
11421
  if (platform === "linux") {
10979
- const candidates = [path8.join(homedir(), ".config/google-chrome"), path8.join(homedir(), ".config/chromium")];
11422
+ const candidates = [path9.join(homedir2(), ".config/google-chrome"), path9.join(homedir2(), ".config/chromium")];
10980
11423
  return candidates.find((candidate) => existsSync2(candidate)) ?? null;
10981
11424
  }
10982
11425
  if (platform === "win32") {
@@ -10984,21 +11427,21 @@ var resolveChromeUserDataDir = () => {
10984
11427
  if (!base) {
10985
11428
  return null;
10986
11429
  }
10987
- const candidates = [path8.join(base, "Google/Chrome/User Data"), path8.join(base, "Chromium/User Data")];
11430
+ const candidates = [path9.join(base, "Google/Chrome/User Data"), path9.join(base, "Chromium/User Data")];
10988
11431
  return candidates.find((candidate) => existsSync2(candidate)) ?? null;
10989
11432
  }
10990
11433
  return null;
10991
11434
  };
10992
11435
  var copyDefaultProfile = (sourceDir) => {
10993
- const destRoot = mkdtempSync(path8.join(tmpdir(), "argus-chrome-profile-"));
11436
+ const destRoot = mkdtempSync(path9.join(tmpdir(), "argus-chrome-profile-"));
10994
11437
  mkdirSync(destRoot, { recursive: true });
10995
11438
  const entries = ["Default", "Local State", "First Run", "Last Version"];
10996
11439
  for (const entry of entries) {
10997
- const source = path8.join(sourceDir, entry);
11440
+ const source = path9.join(sourceDir, entry);
10998
11441
  if (!existsSync2(source)) {
10999
11442
  continue;
11000
11443
  }
11001
- const dest = path8.join(destRoot, entry);
11444
+ const dest = path9.join(destRoot, entry);
11002
11445
  if (entry === "Default") {
11003
11446
  cpSync(source, dest, { recursive: true });
11004
11447
  } else {
@@ -11019,8 +11462,8 @@ var stripExtensionsFromPrefs = (prefsPath) => {
11019
11462
  } catch {}
11020
11463
  };
11021
11464
  var copyDefaultProfileLite = (sourceDir) => {
11022
- const destRoot = mkdtempSync(path8.join(tmpdir(), "argus-chrome-profile-lite-"));
11023
- const defaultDir = path8.join(destRoot, "Default");
11465
+ const destRoot = mkdtempSync(path9.join(tmpdir(), "argus-chrome-profile-lite-"));
11466
+ const defaultDir = path9.join(destRoot, "Default");
11024
11467
  mkdirSync(defaultDir, { recursive: true });
11025
11468
  const copyIfExists = (source, dest) => {
11026
11469
  if (!existsSync2(source)) {
@@ -11028,20 +11471,20 @@ var copyDefaultProfileLite = (sourceDir) => {
11028
11471
  }
11029
11472
  copyFileSync(source, dest);
11030
11473
  };
11031
- copyIfExists(path8.join(sourceDir, "Local State"), path8.join(destRoot, "Local State"));
11032
- copyIfExists(path8.join(sourceDir, "Default", "Cookies"), path8.join(defaultDir, "Cookies"));
11033
- copyIfExists(path8.join(sourceDir, "Default", "Cookies-journal"), path8.join(defaultDir, "Cookies-journal"));
11034
- copyIfExists(path8.join(sourceDir, "Default", "Login Data"), path8.join(defaultDir, "Login Data"));
11035
- copyIfExists(path8.join(sourceDir, "Default", "Login Data-journal"), path8.join(defaultDir, "Login Data-journal"));
11036
- copyIfExists(path8.join(sourceDir, "Default", "Preferences"), path8.join(defaultDir, "Preferences"));
11037
- copyIfExists(path8.join(sourceDir, "Default", "Secure Preferences"), path8.join(defaultDir, "Secure Preferences"));
11038
- stripExtensionsFromPrefs(path8.join(defaultDir, "Preferences"));
11039
- stripExtensionsFromPrefs(path8.join(defaultDir, "Secure Preferences"));
11474
+ copyIfExists(path9.join(sourceDir, "Local State"), path9.join(destRoot, "Local State"));
11475
+ copyIfExists(path9.join(sourceDir, "Default", "Cookies"), path9.join(defaultDir, "Cookies"));
11476
+ copyIfExists(path9.join(sourceDir, "Default", "Cookies-journal"), path9.join(defaultDir, "Cookies-journal"));
11477
+ copyIfExists(path9.join(sourceDir, "Default", "Login Data"), path9.join(defaultDir, "Login Data"));
11478
+ copyIfExists(path9.join(sourceDir, "Default", "Login Data-journal"), path9.join(defaultDir, "Login Data-journal"));
11479
+ copyIfExists(path9.join(sourceDir, "Default", "Preferences"), path9.join(defaultDir, "Preferences"));
11480
+ copyIfExists(path9.join(sourceDir, "Default", "Secure Preferences"), path9.join(defaultDir, "Secure Preferences"));
11481
+ stripExtensionsFromPrefs(path9.join(defaultDir, "Preferences"));
11482
+ stripExtensionsFromPrefs(path9.join(defaultDir, "Secure Preferences"));
11040
11483
  return destRoot;
11041
11484
  };
11042
11485
  var copyDefaultProfileMedium = (sourceDir) => {
11043
11486
  const destRoot = copyDefaultProfileLite(sourceDir);
11044
- const defaultDir = path8.join(destRoot, "Default");
11487
+ const defaultDir = path9.join(destRoot, "Default");
11045
11488
  const copyPathIfExists = (source, dest) => {
11046
11489
  if (!existsSync2(source)) {
11047
11490
  return;
@@ -11053,9 +11496,9 @@ var copyDefaultProfileMedium = (sourceDir) => {
11053
11496
  }
11054
11497
  copyFileSync(source, dest);
11055
11498
  };
11056
- copyPathIfExists(path8.join(sourceDir, "Default", "History"), path8.join(defaultDir, "History"));
11057
- copyPathIfExists(path8.join(sourceDir, "Default", "Local Storage"), path8.join(defaultDir, "Local Storage"));
11058
- copyPathIfExists(path8.join(sourceDir, "Default", "IndexedDB"), path8.join(defaultDir, "IndexedDB"));
11499
+ copyPathIfExists(path9.join(sourceDir, "Default", "History"), path9.join(defaultDir, "History"));
11500
+ copyPathIfExists(path9.join(sourceDir, "Default", "Local Storage"), path9.join(defaultDir, "Local Storage"));
11501
+ copyPathIfExists(path9.join(sourceDir, "Default", "IndexedDB"), path9.join(defaultDir, "IndexedDB"));
11059
11502
  return destRoot;
11060
11503
  };
11061
11504
  var waitForCdpReady = async (host, port, chrome) => {
@@ -11079,35 +11522,11 @@ var waitForCdpReady = async (host, port, chrome) => {
11079
11522
  }
11080
11523
  return { ready: false, error: lastError ?? "Timed out waiting for CDP." };
11081
11524
  };
11082
- var sendBrowserClose = (wsUrl, timeoutMs = 3000) => new Promise((resolve2) => {
11083
- const ws = new WebSocket(wsUrl);
11084
- const timer = setTimeout(() => {
11085
- try {
11086
- ws.close();
11087
- } catch {}
11088
- resolve2();
11089
- }, timeoutMs);
11090
- ws.addEventListener("open", () => {
11091
- try {
11092
- ws.send(JSON.stringify({ id: 1, method: "Browser.close" }));
11093
- } catch {}
11094
- });
11095
- ws.addEventListener("message", () => {
11096
- clearTimeout(timer);
11097
- try {
11098
- ws.close();
11099
- } catch {}
11100
- resolve2();
11101
- });
11102
- ws.addEventListener("error", () => {
11103
- clearTimeout(timer);
11104
- resolve2();
11105
- });
11106
- ws.addEventListener("close", () => {
11107
- clearTimeout(timer);
11108
- resolve2();
11109
- });
11110
- });
11525
+ var sendBrowserClose = async (wsUrl, timeoutMs = 3000) => {
11526
+ try {
11527
+ await sendCdpCommand(wsUrl, { id: 1, method: "Browser.close" }, timeoutMs);
11528
+ } catch {}
11529
+ };
11111
11530
  var normalizeProfile = (profile) => {
11112
11531
  if (!profile) {
11113
11532
  return "default-lite";
@@ -11148,7 +11567,7 @@ var launchChrome = async (options) => {
11148
11567
  const cdpPort = await getCdpPort();
11149
11568
  const cdpHost = "127.0.0.1";
11150
11569
  if (!userDataDir) {
11151
- userDataDir = mkdtempSync(path8.join(tmpdir(), "argus-chrome-"));
11570
+ userDataDir = mkdtempSync(path9.join(tmpdir(), "argus-chrome-"));
11152
11571
  }
11153
11572
  const cleanupDir = () => {
11154
11573
  if (userDataDir) {
@@ -11248,12 +11667,9 @@ var runChromeStart = async (options) => {
11248
11667
  process.exitCode = 2;
11249
11668
  return;
11250
11669
  }
11251
- startupUrl = watcher.match.url;
11252
- if (!startupUrl.startsWith("http://") && !startupUrl.startsWith("https://")) {
11253
- startupUrl = `http://${startupUrl}`;
11254
- }
11670
+ startupUrl = normalizeHttpUrl2(watcher.match.url);
11255
11671
  } else if (options.url) {
11256
- startupUrl = options.url;
11672
+ startupUrl = normalizeHttpUrl2(options.url);
11257
11673
  }
11258
11674
  let result;
11259
11675
  try {
@@ -11268,12 +11684,7 @@ var runChromeStart = async (options) => {
11268
11684
  process.exitCode = 1;
11269
11685
  return;
11270
11686
  }
11271
- process.on("SIGINT", () => {
11272
- result.closeGracefully().then(() => process.exit(0));
11273
- });
11274
- process.on("SIGTERM", () => {
11275
- result.closeGracefully().then(() => process.exit(0));
11276
- });
11687
+ registerTerminationHandlers(() => result.closeGracefully());
11277
11688
  result.chrome.on("exit", () => {
11278
11689
  if (result.userDataDir) {
11279
11690
  try {
@@ -11300,36 +11711,10 @@ var runChromeStart = async (options) => {
11300
11711
  output.writeHuman(` url=${info.startupUrl}`);
11301
11712
  }
11302
11713
  }
11303
- await new Promise(() => {});
11304
- };
11305
-
11306
- // dist/utils/paths.js
11307
- import { homedir as homedir2 } from "node:os";
11308
- import path9 from "node:path";
11309
- var resolvePath = (input) => {
11310
- const expanded = input.startsWith("~/") || input === "~" ? path9.join(homedir2(), input.slice(1)) : input;
11311
- return path9.resolve(expanded);
11714
+ await waitForever();
11312
11715
  };
11313
11716
 
11314
11717
  // dist/commands/start.js
11315
- var resolveInjectScript = async (inject, output) => {
11316
- if (!inject) {
11317
- return null;
11318
- }
11319
- const resolvedPath = resolvePath(inject.file);
11320
- let script;
11321
- try {
11322
- script = await fs7.readFile(resolvedPath, "utf8");
11323
- } catch (error) {
11324
- output.writeWarn(`Failed to read inject script at ${resolvedPath}: ${error instanceof Error ? error.message : String(error)}. Skipping injection.`);
11325
- return null;
11326
- }
11327
- if (script.trim() === "") {
11328
- output.writeWarn(`Inject script at ${resolvedPath} is empty. Skipping injection.`);
11329
- return null;
11330
- }
11331
- return { script, exposeArgus: inject.exposeArgus };
11332
- };
11333
11718
  var runStart = async (options) => {
11334
11719
  const output = createOutput(options);
11335
11720
  if (!options.id || options.id.trim() === "") {
@@ -11338,13 +11723,7 @@ var runStart = async (options) => {
11338
11723
  return;
11339
11724
  }
11340
11725
  const watcherId = options.id.trim();
11341
- let chromeUrl = null;
11342
- if (options.url) {
11343
- chromeUrl = options.url;
11344
- if (!chromeUrl.startsWith("http://") && !chromeUrl.startsWith("https://")) {
11345
- chromeUrl = `http://${chromeUrl}`;
11346
- }
11347
- }
11726
+ const chromeUrl = normalizeHttpUrl2(options.url);
11348
11727
  const hasTargeting = options.url?.trim() || options.target?.trim() || options.origin?.trim() || options.type?.trim();
11349
11728
  if (!hasTargeting) {
11350
11729
  output.writeWarn("At least one targeting option is required: --url, --target, --origin, or --type.");
@@ -11373,17 +11752,7 @@ var runStart = async (options) => {
11373
11752
  if (!options.json) {
11374
11753
  output.writeHuman("Attaching watcher...");
11375
11754
  }
11376
- const match = {};
11377
- if (options.url?.trim())
11378
- match.url = options.url.trim();
11379
- if (options.type?.trim())
11380
- match.type = options.type.trim();
11381
- if (options.origin?.trim())
11382
- match.origin = options.origin.trim();
11383
- if (options.target?.trim())
11384
- match.targetId = options.target.trim();
11385
- if (options.parent?.trim())
11386
- match.parent = options.parent.trim();
11755
+ const match = buildWatcherMatch(options);
11387
11756
  let artifactsBaseDir;
11388
11757
  if (options.artifacts != null) {
11389
11758
  const trimmed = options.artifacts.trim();
@@ -11396,15 +11765,16 @@ var runStart = async (options) => {
11396
11765
  artifactsBaseDir = resolvePath(trimmed);
11397
11766
  }
11398
11767
  const inject = await resolveInjectScript(options.inject, output);
11399
- let handle37;
11768
+ let handle38;
11400
11769
  try {
11401
- handle37 = await startWatcher({
11770
+ handle38 = await startWatcher({
11402
11771
  id: watcherId,
11403
11772
  source: "cdp",
11404
- match: Object.keys(match).length > 0 ? match : undefined,
11773
+ match,
11405
11774
  chrome: { host: chrome.cdpHost, port: chrome.cdpPort },
11406
11775
  host: "127.0.0.1",
11407
11776
  port: 0,
11777
+ net: { enabled: true },
11408
11778
  pageIndicator: options.pageIndicator === false ? { enabled: false } : { enabled: true },
11409
11779
  artifacts: artifactsBaseDir ? { base: artifactsBaseDir } : undefined,
11410
11780
  pageConsoleLogging: options.pageConsoleLogging,
@@ -11418,39 +11788,34 @@ var runStart = async (options) => {
11418
11788
  }
11419
11789
  const shutdown = async () => {
11420
11790
  try {
11421
- await handle37.close();
11791
+ await handle38.close();
11422
11792
  } catch {}
11423
11793
  await chrome.closeGracefully();
11424
11794
  };
11425
- process.on("SIGINT", () => {
11426
- shutdown().then(() => process.exit(0));
11427
- });
11428
- process.on("SIGTERM", () => {
11429
- shutdown().then(() => process.exit(0));
11430
- });
11795
+ registerTerminationHandlers(shutdown);
11431
11796
  chrome.chrome.on("exit", () => {
11432
11797
  if (chrome.userDataDir) {
11433
11798
  try {
11434
11799
  rmSync2(chrome.userDataDir, { recursive: true, force: true });
11435
11800
  } catch {}
11436
11801
  }
11437
- handle37.close().then(() => process.exit(0));
11802
+ handle38.close().then(() => process.exit(0));
11438
11803
  });
11439
- handle37.events.on("cdpAttached", ({ target }) => {
11804
+ handle38.events.on("cdpAttached", ({ target }) => {
11440
11805
  const typeInfo = target?.type ? ` (type: ${target.type})` : "";
11441
11806
  output.writeHuman(`[${watcherId}] CDP attached: ${target?.title} (${target?.url})${typeInfo}`);
11442
11807
  });
11443
- handle37.events.on("cdpDetached", ({ reason, target }) => {
11808
+ handle38.events.on("cdpDetached", ({ reason, target }) => {
11444
11809
  output.writeHuman(`[${watcherId}] CDP detached: ${reason} (last target: ${target?.title})`);
11445
11810
  });
11446
11811
  const result = {
11447
- id: handle37.watcher.id,
11812
+ id: handle38.watcher.id,
11448
11813
  chromePid: chrome.chrome.pid,
11449
11814
  cdpHost: chrome.cdpHost,
11450
11815
  cdpPort: chrome.cdpPort,
11451
- watcherHost: handle37.watcher.host,
11452
- watcherPort: handle37.watcher.port,
11453
- watcherPid: handle37.watcher.pid
11816
+ watcherHost: handle38.watcher.host,
11817
+ watcherPort: handle38.watcher.port,
11818
+ watcherPid: handle38.watcher.pid
11454
11819
  };
11455
11820
  if (options.json) {
11456
11821
  output.writeJson(result);
@@ -11480,7 +11845,7 @@ Stopping...`);
11480
11845
  }
11481
11846
  });
11482
11847
  }
11483
- await new Promise(() => {});
11848
+ await waitForever();
11484
11849
  };
11485
11850
 
11486
11851
  // dist/commands/doctor.js
@@ -11609,66 +11974,6 @@ var formatStatus = (status) => {
11609
11974
  return "WARN";
11610
11975
  };
11611
11976
 
11612
- // dist/watchers/requestWatcher.js
11613
- async function requestWatcherJson(input) {
11614
- const resolved = await resolveWatcher({ id: input.id });
11615
- if (!resolved.ok) {
11616
- return {
11617
- ok: false,
11618
- exitCode: resolved.exitCode,
11619
- message: resolved.error,
11620
- candidates: resolved.candidates
11621
- };
11622
- }
11623
- const { watcher } = resolved;
11624
- const qs = input.query?.toString();
11625
- const url = `http://${watcher.host}:${watcher.port}${input.path}${qs ? `?${qs}` : ""}`;
11626
- try {
11627
- const data = await fetchJson(url, {
11628
- method: input.method,
11629
- body: input.body,
11630
- timeoutMs: input.timeoutMs,
11631
- returnErrorResponse: input.returnErrorResponse
11632
- });
11633
- return { ok: true, watcher, data };
11634
- } catch (error) {
11635
- return {
11636
- ok: false,
11637
- watcher,
11638
- exitCode: 1,
11639
- message: `${watcher.id}: failed to reach watcher (${formatError(error)})`
11640
- };
11641
- }
11642
- }
11643
- async function resolveWatcherOrExit(input, output) {
11644
- const resolved = await resolveWatcher(input);
11645
- if (!resolved.ok) {
11646
- writeResolveError(resolved, output);
11647
- return null;
11648
- }
11649
- return { watcher: resolved.watcher };
11650
- }
11651
- function writeRequestError(result, output) {
11652
- output.writeWarn(result.message);
11653
- if (result.candidates && result.candidates.length > 0) {
11654
- for (const watcher of result.candidates) {
11655
- output.writeWarn(formatWatcherLine(watcher));
11656
- }
11657
- output.writeWarn("Hint: run `argus list` to see all watchers.");
11658
- }
11659
- process.exitCode = result.exitCode;
11660
- }
11661
- function writeResolveError(resolved, output) {
11662
- output.writeWarn(resolved.error);
11663
- if (resolved.candidates && resolved.candidates.length > 0) {
11664
- for (const watcher of resolved.candidates) {
11665
- output.writeWarn(formatWatcherLine(watcher));
11666
- }
11667
- output.writeWarn("Hint: run `argus list` to see all watchers.");
11668
- }
11669
- process.exitCode = resolved.exitCode;
11670
- }
11671
-
11672
11977
  // dist/commands/reload.js
11673
11978
  var runReload = async (id, options) => {
11674
11979
  const output = createOutput(options);
@@ -12169,30 +12474,11 @@ Examples:
12169
12474
 
12170
12475
  // dist/commands/watcherStart.js
12171
12476
  import crypto2 from "node:crypto";
12172
- import fs9 from "node:fs/promises";
12173
12477
  var isValidPort = (port) => Number.isFinite(port) && port >= 1 && port <= 65535;
12174
12478
  var parsePort2 = (value) => {
12175
12479
  const port = typeof value === "string" ? parseInt(value, 10) : value;
12176
12480
  return isValidPort(port) ? port : null;
12177
12481
  };
12178
- var resolveInjectScript2 = async (inject, output) => {
12179
- if (!inject) {
12180
- return null;
12181
- }
12182
- const resolvedPath = resolvePath(inject.file);
12183
- let script;
12184
- try {
12185
- script = await fs9.readFile(resolvedPath, "utf8");
12186
- } catch (error) {
12187
- output.writeWarn(`Failed to read inject script at ${resolvedPath}: ${error instanceof Error ? error.message : String(error)}. Skipping injection.`);
12188
- return null;
12189
- }
12190
- if (script.trim() === "") {
12191
- output.writeWarn(`Inject script at ${resolvedPath} is empty. Skipping injection.`);
12192
- return null;
12193
- }
12194
- return { script, exposeArgus: inject.exposeArgus };
12195
- };
12196
12482
  var runWatcherStart = async (options) => {
12197
12483
  const output = createOutput(options);
12198
12484
  const sourceMode = options.source ?? "cdp";
@@ -12243,7 +12529,6 @@ var runWatcherStart = async (options) => {
12243
12529
  }
12244
12530
  }
12245
12531
  const watcherId = options.id?.trim() || generateWatcherId();
12246
- const matchUrl = options.url?.trim();
12247
12532
  let artifactsBaseDir;
12248
12533
  if (options.artifacts != null) {
12249
12534
  const trimmed = options.artifacts.trim();
@@ -12254,32 +12539,18 @@ var runWatcherStart = async (options) => {
12254
12539
  }
12255
12540
  artifactsBaseDir = resolvePath(trimmed);
12256
12541
  }
12257
- const inject = await resolveInjectScript2(options.inject, output);
12258
- const match = {};
12259
- if (matchUrl) {
12260
- match.url = matchUrl;
12261
- }
12262
- if (options.type?.trim()) {
12263
- match.type = options.type.trim();
12264
- }
12265
- if (options.origin?.trim()) {
12266
- match.origin = options.origin.trim();
12267
- }
12268
- if (options.target?.trim()) {
12269
- match.targetId = options.target.trim();
12270
- }
12271
- if (options.parent?.trim()) {
12272
- match.parent = options.parent.trim();
12273
- }
12274
- let handle37;
12542
+ const inject = await resolveInjectScript(options.inject, output);
12543
+ const match = sourceMode === "cdp" ? buildWatcherMatch(options) : undefined;
12544
+ let handle38;
12275
12545
  try {
12276
- handle37 = await startWatcher({
12546
+ handle38 = await startWatcher({
12277
12547
  id: watcherId,
12278
12548
  source: sourceMode,
12279
- match: sourceMode === "cdp" && Object.keys(match).length > 0 ? match : undefined,
12549
+ match,
12280
12550
  chrome: sourceMode === "cdp" ? { host: chromeHost, port: chromePort } : undefined,
12281
12551
  host: "127.0.0.1",
12282
12552
  port: 0,
12553
+ net: { enabled: true },
12283
12554
  pageIndicator: options.pageIndicator === false ? { enabled: false } : { enabled: true },
12284
12555
  artifacts: artifactsBaseDir ? { base: artifactsBaseDir } : undefined,
12285
12556
  pageConsoleLogging: options.pageConsoleLogging,
@@ -12291,37 +12562,32 @@ var runWatcherStart = async (options) => {
12291
12562
  return;
12292
12563
  }
12293
12564
  const result = {
12294
- id: handle37.watcher.id,
12295
- host: handle37.watcher.host,
12296
- port: handle37.watcher.port,
12297
- pid: handle37.watcher.pid,
12565
+ id: handle38.watcher.id,
12566
+ host: handle38.watcher.host,
12567
+ port: handle38.watcher.port,
12568
+ pid: handle38.watcher.pid,
12298
12569
  source: sourceMode,
12299
- matchUrl: match.url,
12300
- matchType: match.type,
12301
- matchOrigin: match.origin,
12302
- matchTarget: match.targetId,
12303
- matchParent: match.parent,
12570
+ matchUrl: match?.url,
12571
+ matchType: match?.type,
12572
+ matchOrigin: match?.origin,
12573
+ matchTarget: match?.targetId,
12574
+ matchParent: match?.parent,
12304
12575
  chromeHost,
12305
12576
  chromePort,
12306
12577
  artifactsBaseDir
12307
12578
  };
12308
12579
  const cleanup = async () => {
12309
12580
  try {
12310
- await handle37.close();
12581
+ await handle38.close();
12311
12582
  } catch {}
12312
12583
  };
12313
- process.on("SIGINT", () => {
12314
- cleanup().then(() => process.exit(0));
12315
- });
12316
- process.on("SIGTERM", () => {
12317
- cleanup().then(() => process.exit(0));
12318
- });
12319
- handle37.events.on("cdpAttached", ({ target }) => {
12584
+ registerTerminationHandlers(cleanup);
12585
+ handle38.events.on("cdpAttached", ({ target }) => {
12320
12586
  const typeInfo = target?.type ? ` (type: ${target.type})` : "";
12321
- output.writeHuman(`[${handle37.watcher.id}] CDP attached: ${target?.title} (${target?.url})${typeInfo}`);
12587
+ output.writeHuman(`[${handle38.watcher.id}] CDP attached: ${target?.title} (${target?.url})${typeInfo}`);
12322
12588
  });
12323
- handle37.events.on("cdpDetached", ({ reason, target }) => {
12324
- output.writeHuman(`[${handle37.watcher.id}] CDP detached: ${reason} (last target: ${target?.title})`);
12589
+ handle38.events.on("cdpDetached", ({ reason, target }) => {
12590
+ output.writeHuman(`[${handle38.watcher.id}] CDP detached: ${reason} (last target: ${target?.title})`);
12325
12591
  });
12326
12592
  if (options.json) {
12327
12593
  output.writeJson(result);
@@ -12353,7 +12619,7 @@ var runWatcherStart = async (options) => {
12353
12619
  output.writeHuman(` artifacts=${result.artifactsBaseDir}`);
12354
12620
  }
12355
12621
  }
12356
- await new Promise(() => {});
12622
+ await waitForever();
12357
12623
  };
12358
12624
  var generateWatcherId = () => crypto2.randomBytes(3).toString("hex");
12359
12625
 
@@ -12533,23 +12799,24 @@ var checkWatcherReachable = async (watcher) => {
12533
12799
  // dist/commands/watcherNativeHost.js
12534
12800
  var runWatcherNativeHost = async (options) => {
12535
12801
  const watcherId = options.id?.trim() || "extension";
12536
- let handle37;
12802
+ let handle38;
12537
12803
  try {
12538
- handle37 = await startWatcher({
12804
+ handle38 = await startWatcher({
12539
12805
  id: watcherId,
12540
12806
  source: "extension",
12541
12807
  host: "127.0.0.1",
12542
12808
  port: 0,
12809
+ net: { enabled: true },
12543
12810
  pageIndicator: { enabled: true }
12544
12811
  });
12545
12812
  } catch (error) {
12546
12813
  console.error(`Failed to start watcher: ${error instanceof Error ? error.message : error}`);
12547
12814
  process.exit(1);
12548
12815
  }
12549
- console.error(`[NativeHost] Watcher started: id=${handle37.watcher.id} port=${handle37.watcher.port}`);
12816
+ console.error(`[NativeHost] Watcher started: id=${handle38.watcher.id} port=${handle38.watcher.port}`);
12550
12817
  const cleanup = async () => {
12551
12818
  try {
12552
- await handle37.close();
12819
+ await handle38.close();
12553
12820
  } catch {}
12554
12821
  };
12555
12822
  process.on("SIGINT", () => {
@@ -12688,100 +12955,6 @@ var parseParamsString = (value) => {
12688
12955
  var isHttpUrl = (url) => {
12689
12956
  return url.startsWith("http://") || url.startsWith("https://");
12690
12957
  };
12691
- var getWebSocketCtor2 = () => {
12692
- const ctor = globalThis.WebSocket;
12693
- return ctor ?? null;
12694
- };
12695
- var toMessageText2 = (data) => {
12696
- if (typeof data === "string") {
12697
- return data;
12698
- }
12699
- if (data instanceof ArrayBuffer) {
12700
- return Buffer.from(data).toString("utf8");
12701
- }
12702
- if (Buffer.isBuffer(data)) {
12703
- return data.toString("utf8");
12704
- }
12705
- return null;
12706
- };
12707
- var sendCdpCommand2 = async (wsUrl, payload, timeoutMs = 5000) => {
12708
- const WebSocketConstructor = getWebSocketCtor2();
12709
- if (!WebSocketConstructor) {
12710
- throw new Error("WebSocket unavailable. Node 18+ required.");
12711
- }
12712
- const ws = new WebSocketConstructor(wsUrl);
12713
- const requestId = payload.id;
12714
- await new Promise((resolve2, reject) => {
12715
- let settled = false;
12716
- const timer = setTimeout(() => {
12717
- if (!settled) {
12718
- settled = true;
12719
- try {
12720
- ws.close();
12721
- } catch {}
12722
- reject(new Error(`CDP command timed out after ${timeoutMs}ms`));
12723
- }
12724
- }, timeoutMs);
12725
- const cleanup = () => {
12726
- clearTimeout(timer);
12727
- ws.removeEventListener?.("open", onOpen);
12728
- ws.removeEventListener?.("message", onMessage);
12729
- ws.removeEventListener?.("error", onError);
12730
- ws.removeEventListener?.("close", onClose);
12731
- };
12732
- const finish = (error) => {
12733
- if (settled) {
12734
- return;
12735
- }
12736
- settled = true;
12737
- cleanup();
12738
- try {
12739
- ws.close();
12740
- } catch {}
12741
- if (error) {
12742
- reject(error);
12743
- } else {
12744
- resolve2();
12745
- }
12746
- };
12747
- const onOpen = () => {
12748
- try {
12749
- ws.send(JSON.stringify(payload));
12750
- } catch (error) {
12751
- finish(error instanceof Error ? error : new Error(String(error)));
12752
- }
12753
- };
12754
- const onMessage = (event) => {
12755
- const text = toMessageText2(event.data);
12756
- if (!text) {
12757
- return;
12758
- }
12759
- try {
12760
- const message = JSON.parse(text);
12761
- if (message.id !== requestId) {
12762
- return;
12763
- }
12764
- if (message.error?.message) {
12765
- finish(new Error(message.error.message));
12766
- return;
12767
- }
12768
- finish();
12769
- } catch (error) {
12770
- finish(error instanceof Error ? error : new Error(String(error)));
12771
- }
12772
- };
12773
- const onError = () => {
12774
- finish(new Error("WebSocket error"));
12775
- };
12776
- const onClose = () => {
12777
- finish(new Error("WebSocket closed before response"));
12778
- };
12779
- ws.addEventListener("open", onOpen);
12780
- ws.addEventListener("message", onMessage);
12781
- ws.addEventListener("error", onError);
12782
- ws.addEventListener("close", onClose);
12783
- });
12784
- };
12785
12958
  var runPageReload = async (options) => {
12786
12959
  const output = createOutput(options);
12787
12960
  const hasParamFlag = (options.param?.length ?? 0) > 0;
@@ -12885,7 +13058,7 @@ var reloadTarget = async (target, context) => {
12885
13058
  }
12886
13059
  if (!context.hasParamFlag && !context.hasParamsFlag) {
12887
13060
  try {
12888
- await sendCdpCommand2(target.webSocketDebuggerUrl, { id: 1, method: "Page.reload" });
13061
+ await sendCdpCommand(target.webSocketDebuggerUrl, { id: 1, method: "Page.reload" });
12889
13062
  } catch (error) {
12890
13063
  output.writeWarn(`Failed to reload target ${target.id}: ${error instanceof Error ? error.message : error}`);
12891
13064
  process.exitCode = 1;
@@ -12941,7 +13114,7 @@ var reloadTarget = async (target, context) => {
12941
13114
  }
12942
13115
  const nextUrl = parsedUrl.toString();
12943
13116
  try {
12944
- await sendCdpCommand2(target.webSocketDebuggerUrl, { id: 1, method: "Page.navigate", params: { url: nextUrl } });
13117
+ await sendCdpCommand(target.webSocketDebuggerUrl, { id: 1, method: "Page.navigate", params: { url: nextUrl } });
12945
13118
  } catch (error) {
12946
13119
  output.writeWarn(`Failed to navigate target ${target.id}: ${error instanceof Error ? error.message : error}`);
12947
13120
  process.exitCode = 1;
@@ -13341,10 +13514,8 @@ var parseDurationMs = (value) => {
13341
13514
  return amount * multiplier;
13342
13515
  };
13343
13516
 
13344
- // dist/commands/logs.js
13345
- var runLogs = async (id, options) => {
13346
- const output = createOutput(options);
13347
- const params = new URLSearchParams;
13517
+ // dist/watchers/queryParams.js
13518
+ var appendAfterLimitParams = (params, options) => {
13348
13519
  const after = parseNumber(options.after);
13349
13520
  if (after != null) {
13350
13521
  params.set("after", String(after));
@@ -13353,19 +13524,38 @@ var runLogs = async (id, options) => {
13353
13524
  if (limit != null) {
13354
13525
  params.set("limit", String(limit));
13355
13526
  }
13527
+ };
13528
+ var appendSinceParam = (params, since) => {
13529
+ const resolved = resolveSinceTimestamp(since);
13530
+ if (resolved.error) {
13531
+ return resolved;
13532
+ }
13533
+ if (resolved.sinceTs == null) {
13534
+ return {};
13535
+ }
13536
+ params.set("sinceTs", String(resolved.sinceTs));
13537
+ return {};
13538
+ };
13539
+ var resolveSinceTimestamp = (since) => {
13540
+ if (!since) {
13541
+ return { sinceTs: null };
13542
+ }
13543
+ const duration = parseDurationMs(since);
13544
+ if (!duration) {
13545
+ return { sinceTs: null, error: `Invalid --since value: ${since}` };
13546
+ }
13547
+ return { sinceTs: Date.now() - duration };
13548
+ };
13549
+ var appendLogFilterParams = (params, options) => {
13356
13550
  if (options.levels) {
13357
13551
  params.set("levels", options.levels);
13358
13552
  }
13359
- const normalizedMatch = normalizeMatch(options.match);
13553
+ const normalizedMatch = normalizeMatchPatterns2(options.match);
13360
13554
  if (normalizedMatch.error) {
13361
- output.writeWarn(normalizedMatch.error);
13362
- process.exitCode = 2;
13363
- return;
13555
+ return normalizedMatch;
13364
13556
  }
13365
- if (normalizedMatch.match) {
13366
- for (const pattern of normalizedMatch.match) {
13367
- params.append("match", pattern);
13368
- }
13557
+ for (const pattern of normalizedMatch.patterns) {
13558
+ params.append("match", pattern);
13369
13559
  }
13370
13560
  const matchCase = resolveMatchCase2(options);
13371
13561
  if (matchCase) {
@@ -13375,14 +13565,50 @@ var runLogs = async (id, options) => {
13375
13565
  if (source) {
13376
13566
  params.set("source", source);
13377
13567
  }
13378
- if (options.since) {
13379
- const duration = parseDurationMs(options.since);
13380
- if (!duration) {
13381
- output.writeWarn(`Invalid --since value: ${options.since}`);
13382
- process.exitCode = 2;
13383
- return;
13384
- }
13385
- params.set("sinceTs", String(Date.now() - duration));
13568
+ return {};
13569
+ };
13570
+ var appendNetFilterParams = (params, options) => {
13571
+ const grep = normalizeQueryValue(options.grep);
13572
+ if (grep) {
13573
+ params.set("grep", grep);
13574
+ }
13575
+ };
13576
+ var normalizeMatchPatterns2 = (match) => {
13577
+ if (!match || match.length === 0) {
13578
+ return { patterns: [] };
13579
+ }
13580
+ const patterns = match.map((value) => value.trim());
13581
+ if (patterns.some((value) => value.length === 0)) {
13582
+ return { patterns: [], error: "Invalid --match value: empty pattern." };
13583
+ }
13584
+ return { patterns };
13585
+ };
13586
+ var resolveMatchCase2 = (options) => {
13587
+ if (options.caseSensitive) {
13588
+ return "sensitive";
13589
+ }
13590
+ if (options.ignoreCase) {
13591
+ return "insensitive";
13592
+ }
13593
+ return;
13594
+ };
13595
+
13596
+ // dist/commands/logs.js
13597
+ var runLogs = async (id, options) => {
13598
+ const output = createOutput(options);
13599
+ const params = new URLSearchParams;
13600
+ appendAfterLimitParams(params, options);
13601
+ const filters = appendLogFilterParams(params, options);
13602
+ if (filters.error) {
13603
+ output.writeWarn(filters.error);
13604
+ process.exitCode = 2;
13605
+ return;
13606
+ }
13607
+ const since = appendSinceParam(params, options.since);
13608
+ if (since.error) {
13609
+ output.writeWarn(since.error);
13610
+ process.exitCode = 2;
13611
+ return;
13386
13612
  }
13387
13613
  const result = await requestWatcherJson({
13388
13614
  id,
@@ -13409,26 +13635,6 @@ var runLogs = async (id, options) => {
13409
13635
  }));
13410
13636
  }
13411
13637
  };
13412
- var normalizeMatch = (match) => {
13413
- if (!match || match.length === 0) {
13414
- return {};
13415
- }
13416
- const normalized = match.map((value) => value.trim());
13417
- const invalid = normalized.find((value) => value.length === 0);
13418
- if (invalid != null) {
13419
- return { error: "Invalid --match value: empty pattern." };
13420
- }
13421
- return { match: normalized };
13422
- };
13423
- var resolveMatchCase2 = (options) => {
13424
- if (options.caseSensitive) {
13425
- return "sensitive";
13426
- }
13427
- if (options.ignoreCase) {
13428
- return "insensitive";
13429
- }
13430
- return;
13431
- };
13432
13638
 
13433
13639
  // dist/commands/tail.js
13434
13640
  var runTail = async (id, options) => {
@@ -13453,34 +13659,18 @@ var runTail = async (id, options) => {
13453
13659
  if (limit != null) {
13454
13660
  params.set("limit", String(limit));
13455
13661
  }
13456
- if (options.levels) {
13457
- params.set("levels", options.levels);
13458
- }
13459
- const normalizedMatch = normalizeMatch2(options.match);
13460
- if (normalizedMatch.error) {
13461
- output.writeWarn(normalizedMatch.error);
13662
+ const filters = appendLogFilterParams(params, options);
13663
+ if (filters.error) {
13664
+ output.writeWarn(filters.error);
13462
13665
  process.exitCode = 2;
13463
13666
  return;
13464
13667
  }
13465
- if (normalizedMatch.match) {
13466
- for (const pattern of normalizedMatch.match) {
13467
- params.append("match", pattern);
13468
- }
13469
- }
13470
- const matchCase = resolveMatchCase3(options);
13471
- if (matchCase) {
13472
- params.set("matchCase", matchCase);
13473
- }
13474
- const source = normalizeQueryValue(options.source);
13475
- if (source) {
13476
- params.set("source", source);
13477
- }
13478
- const url = `http://${watcher.host}:${watcher.port}/tail?${params.toString()}`;
13668
+ const url = buildWatcherUrl(watcher, "/tail", params);
13479
13669
  let response;
13480
13670
  try {
13481
13671
  response = await fetchJson(url, { timeoutMs: timeoutMs + 5000 });
13482
13672
  } catch (error) {
13483
- output.writeWarn(`${watcher.id}: failed to reach watcher (${formatError(error)})`);
13673
+ output.writeWarn(formatWatcherTransportError(watcher, error));
13484
13674
  process.exitCode = 1;
13485
13675
  return;
13486
13676
  }
@@ -13503,26 +13693,6 @@ var runTail = async (id, options) => {
13503
13693
  after = response.nextAfter;
13504
13694
  }
13505
13695
  };
13506
- var normalizeMatch2 = (match) => {
13507
- if (!match || match.length === 0) {
13508
- return {};
13509
- }
13510
- const normalized = match.map((value) => value.trim());
13511
- const invalid = normalized.find((value) => value.length === 0);
13512
- if (invalid != null) {
13513
- return { error: "Invalid --match value: empty pattern." };
13514
- }
13515
- return { match: normalized };
13516
- };
13517
- var resolveMatchCase3 = (options) => {
13518
- if (options.caseSensitive) {
13519
- return "sensitive";
13520
- }
13521
- if (options.ignoreCase) {
13522
- return "insensitive";
13523
- }
13524
- return;
13525
- };
13526
13696
 
13527
13697
  // dist/cli/register/registerLogs.js
13528
13698
  function registerLogs(program2) {
@@ -13572,26 +13742,13 @@ Examples:
13572
13742
  var runNet = async (id, options) => {
13573
13743
  const output = createOutput(options);
13574
13744
  const params = new URLSearchParams;
13575
- const after = parseNumber(options.after);
13576
- if (after != null) {
13577
- params.set("after", String(after));
13578
- }
13579
- const limit = parseNumber(options.limit);
13580
- if (limit != null) {
13581
- params.set("limit", String(limit));
13582
- }
13583
- if (options.since) {
13584
- const duration = parseDurationMs(options.since);
13585
- if (!duration) {
13586
- output.writeWarn(`Invalid --since value: ${options.since}`);
13587
- process.exitCode = 2;
13588
- return;
13589
- }
13590
- params.set("sinceTs", String(Date.now() - duration));
13591
- }
13592
- const grep = normalizeQueryValue(options.grep);
13593
- if (grep) {
13594
- params.set("grep", grep);
13745
+ appendAfterLimitParams(params, options);
13746
+ appendNetFilterParams(params, options);
13747
+ const since = appendSinceParam(params, options.since);
13748
+ if (since.error) {
13749
+ output.writeWarn(since.error);
13750
+ process.exitCode = 2;
13751
+ return;
13595
13752
  }
13596
13753
  const result = await requestWatcherJson({
13597
13754
  id,
@@ -13622,14 +13779,12 @@ var runNetTail = async (id, options) => {
13622
13779
  let after = parseNumber(options.after) ?? 0;
13623
13780
  const timeoutMs = parseNumber(options.timeout) ?? 25000;
13624
13781
  const limit = parseNumber(options.limit);
13625
- const sinceTsResult = resolveSinceTs(options.since);
13626
- if (sinceTsResult.error) {
13627
- output.writeWarn(sinceTsResult.error);
13782
+ const since = resolveSinceTimestamp(options.since);
13783
+ if (since.error) {
13784
+ output.writeWarn(since.error);
13628
13785
  process.exitCode = 2;
13629
13786
  return;
13630
13787
  }
13631
- const sinceTs = sinceTsResult.value;
13632
- const grep = normalizeQueryValue(options.grep);
13633
13788
  let running = true;
13634
13789
  const stop = () => {
13635
13790
  running = false;
@@ -13643,18 +13798,16 @@ var runNetTail = async (id, options) => {
13643
13798
  if (limit != null) {
13644
13799
  params.set("limit", String(limit));
13645
13800
  }
13646
- if (sinceTs != null) {
13647
- params.set("sinceTs", String(sinceTs));
13648
- }
13649
- if (grep) {
13650
- params.set("grep", grep);
13801
+ if (since.sinceTs != null) {
13802
+ params.set("sinceTs", String(since.sinceTs));
13651
13803
  }
13652
- const url = `http://${watcher.host}:${watcher.port}/net/tail?${params.toString()}`;
13804
+ appendNetFilterParams(params, options);
13805
+ const url = buildWatcherUrl(watcher, "/net/tail", params);
13653
13806
  let response;
13654
13807
  try {
13655
13808
  response = await fetchJson(url, { timeoutMs: timeoutMs + 5000 });
13656
13809
  } catch (error) {
13657
- output.writeWarn(`${watcher.id}: failed to reach watcher (${formatError(error)})`);
13810
+ output.writeWarn(formatWatcherTransportError(watcher, error));
13658
13811
  process.exitCode = 1;
13659
13812
  return;
13660
13813
  }
@@ -13670,16 +13823,6 @@ var runNetTail = async (id, options) => {
13670
13823
  after = response.nextAfter;
13671
13824
  }
13672
13825
  };
13673
- var resolveSinceTs = (value) => {
13674
- if (!value) {
13675
- return { value: null };
13676
- }
13677
- const duration = parseDurationMs(value);
13678
- if (!duration) {
13679
- return { value: null, error: `Invalid --since value: ${value}` };
13680
- }
13681
- return { value: Date.now() - duration };
13682
- };
13683
13826
 
13684
13827
  // dist/cli/register/registerNet.js
13685
13828
  function registerNet(program2) {
@@ -13701,9 +13844,197 @@ Examples:
13701
13844
  });
13702
13845
  }
13703
13846
 
13847
+ // dist/commands/auth.js
13848
+ import { writeFile } from "node:fs/promises";
13849
+ var COOKIE_EXPORT_FORMATS = new Set(["netscape", "json", "header"]);
13850
+ var runAuthCookies = async (id, options) => {
13851
+ const output = createOutput(options);
13852
+ const includeValues = options.showValues === true;
13853
+ const response = await fetchAuthCookies(id, { domain: options.domain, includeValues }, output);
13854
+ if (!response) {
13855
+ return;
13856
+ }
13857
+ const cookies2 = filterCookies(response.origin, response.cookies, options);
13858
+ if (options.json) {
13859
+ output.writeJson({ ...response, cookies: cookies2 });
13860
+ return;
13861
+ }
13862
+ if (cookies2.length === 0) {
13863
+ output.writeHuman("No cookies matched.");
13864
+ return;
13865
+ }
13866
+ for (const cookie of cookies2) {
13867
+ output.writeHuman(formatCookieLine(cookie, includeValues));
13868
+ }
13869
+ };
13870
+ var runAuthExportCookies = async (id, options) => {
13871
+ const output = createOutput({});
13872
+ const format = normalizeExportFormat(options.format);
13873
+ if (!format) {
13874
+ output.writeWarn(`Invalid --format value: ${options.format}. Expected one of: netscape, json, header.`);
13875
+ process.exitCode = 2;
13876
+ return;
13877
+ }
13878
+ const response = await fetchAuthCookies(id, { domain: options.domain, includeValues: true }, output);
13879
+ if (!response) {
13880
+ return;
13881
+ }
13882
+ const serialized = serializeCookies(filterCookies(response.origin, response.cookies, options), format);
13883
+ await writeOutput(serialized, options.out);
13884
+ };
13885
+ var fetchAuthCookies = async (id, input, output) => {
13886
+ const result = await requestWatcherJson({
13887
+ id,
13888
+ path: "/auth/cookies",
13889
+ query: buildCookieQuery(input),
13890
+ timeoutMs: 1e4
13891
+ });
13892
+ if (!result.ok) {
13893
+ writeRequestError(result, output);
13894
+ return null;
13895
+ }
13896
+ return result.data;
13897
+ };
13898
+ var buildCookieQuery = (input) => {
13899
+ const params = new URLSearchParams;
13900
+ if (input.domain?.trim()) {
13901
+ params.set("domain", input.domain.trim());
13902
+ }
13903
+ if (input.includeValues) {
13904
+ params.set("includeValues", "true");
13905
+ }
13906
+ return params;
13907
+ };
13908
+ var filterCookies = (origin, cookies2, options) => {
13909
+ const originHost = options.forOrigin ? getOriginHost(origin) : null;
13910
+ return cookies2.filter((cookie) => matchesCookieFilters(cookie, originHost, options));
13911
+ };
13912
+ var matchesCookieFilters = (cookie, originHost, options) => {
13913
+ if (options.sessionOnly && !cookie.session) {
13914
+ return false;
13915
+ }
13916
+ if (options.httpOnly && !cookie.httpOnly) {
13917
+ return false;
13918
+ }
13919
+ if (options.secure && !cookie.secure) {
13920
+ return false;
13921
+ }
13922
+ if (originHost && !matchesCookieDomain(cookie.domain, originHost)) {
13923
+ return false;
13924
+ }
13925
+ if (options.excludeTracking && isTrackingCookieName(cookie.name)) {
13926
+ return false;
13927
+ }
13928
+ return true;
13929
+ };
13930
+ var formatCookieLine = (cookie, showValues) => {
13931
+ const flags = [formatExpiryFlag(cookie), cookie.httpOnly ? "httpOnly" : null, cookie.secure ? "secure" : null, formatSameSiteFlag(cookie)].filter(Boolean).join(",");
13932
+ const value = resolveCookieValue(cookie, showValues);
13933
+ const flagSuffix = flags ? ` [${flags}]` : "";
13934
+ const valueSuffix = value ? ` ${value}` : "";
13935
+ return `${cookie.name} ${cookie.domain}${cookie.path}${flagSuffix}${valueSuffix}`.trim();
13936
+ };
13937
+ var formatExpiryFlag = (cookie) => {
13938
+ if (cookie.session) {
13939
+ return "session";
13940
+ }
13941
+ if (cookie.expires != null) {
13942
+ return `exp=${Math.trunc(cookie.expires)}`;
13943
+ }
13944
+ return null;
13945
+ };
13946
+ var formatSameSiteFlag = (cookie) => {
13947
+ if (!cookie.sameSite) {
13948
+ return null;
13949
+ }
13950
+ return `sameSite=${cookie.sameSite}`;
13951
+ };
13952
+ var resolveCookieValue = (cookie, showValues) => {
13953
+ if (showValues && cookie.value != null) {
13954
+ return cookie.value;
13955
+ }
13956
+ return cookie.valuePreview ?? "";
13957
+ };
13958
+ var normalizeExportFormat = (format) => {
13959
+ if (!format)
13960
+ return "netscape";
13961
+ if (!COOKIE_EXPORT_FORMATS.has(format)) {
13962
+ return null;
13963
+ }
13964
+ switch (format) {
13965
+ case "netscape":
13966
+ case "json":
13967
+ case "header":
13968
+ return format;
13969
+ default:
13970
+ return null;
13971
+ }
13972
+ };
13973
+ var formatCookiesAsNetscape = (cookies2) => {
13974
+ const lines = ["# Netscape HTTP Cookie File", "# This file was generated by Argus.", ""];
13975
+ for (const cookie of cookies2) {
13976
+ lines.push([
13977
+ formatNetscapeDomain(cookie),
13978
+ cookie.domain.startsWith(".") ? "TRUE" : "FALSE",
13979
+ cookie.path,
13980
+ cookie.secure ? "TRUE" : "FALSE",
13981
+ String(cookie.session ? 0 : Math.max(0, Math.trunc(cookie.expires ?? 0))),
13982
+ cookie.name,
13983
+ cookie.value ?? ""
13984
+ ].join("\t"));
13985
+ }
13986
+ return lines.join(`
13987
+ `);
13988
+ };
13989
+ var formatNetscapeDomain = (cookie) => cookie.httpOnly ? `#HttpOnly_${cookie.domain}` : cookie.domain;
13990
+ var formatCookiesAsHeader = (cookies2) => `Cookie: ${cookies2.map((cookie) => `${cookie.name}=${cookie.value ?? ""}`).join("; ")}`;
13991
+ var serializeCookies = (cookies2, format) => {
13992
+ switch (format) {
13993
+ case "netscape":
13994
+ return formatCookiesAsNetscape(cookies2);
13995
+ case "json":
13996
+ return JSON.stringify(cookies2, null, 2);
13997
+ case "header":
13998
+ return formatCookiesAsHeader(cookies2);
13999
+ }
14000
+ };
14001
+ var writeOutput = async (content, outPath) => {
14002
+ const withTrailingNewline = content.endsWith(`
14003
+ `) ? content : `${content}
14004
+ `;
14005
+ if (outPath) {
14006
+ await writeFile(outPath, withTrailingNewline, "utf8");
14007
+ return;
14008
+ }
14009
+ process.stdout.write(withTrailingNewline);
14010
+ };
14011
+
14012
+ // dist/cli/register/registerAuth.js
14013
+ function registerAuth(program2) {
14014
+ const auth = program2.command("auth").description("List and export browser auth cookies");
14015
+ addCookieScopeOptions(auth.command("cookies"), "Only include first-party cookies for the attached page origin").argument("[id]", "Watcher id").description("List cookies for the attached page").option("--domain <domain>", "Filter cookies by domain suffix").option("--session-only", "Show only session cookies").option("--http-only", "Show only HttpOnly cookies").option("--secure", "Show only Secure cookies").option("--show-values", "Reveal raw cookie values instead of previews").option("--json", "Output JSON for automation").addHelpText("after", `
14016
+ Examples:
14017
+ $ argus auth cookies app
14018
+ $ argus auth cookies app --for-origin --exclude-tracking
14019
+ $ argus auth cookies app --domain example.com
14020
+ $ argus auth cookies app --session-only --show-values
14021
+ `).action(async (id, options) => {
14022
+ await runAuthCookies(id, options);
14023
+ });
14024
+ addCookieScopeOptions(auth.command("export-cookies"), "Only include first-party cookies for the attached page origin").argument("[id]", "Watcher id").description("Export cookies for companion CLIs and HTTP clients").option("--format <format>", "Export format: netscape (default), json, or header").option("--domain <domain>", "Filter cookies by domain suffix").option("--out <path>", "Write the export to a file instead of stdout").addHelpText("after", `
14025
+ Examples:
14026
+ $ argus auth export-cookies app --format netscape
14027
+ $ argus auth export-cookies app --for-origin --exclude-tracking
14028
+ $ argus auth export-cookies app --format header
14029
+ $ argus auth export-cookies app --out cookies.txt
14030
+ `).action(async (id, options) => {
14031
+ await runAuthExportCookies(id, options);
14032
+ });
14033
+ }
14034
+ var addCookieScopeOptions = (command, forOriginDescription) => command.option("--for-origin", forOriginDescription).option("--exclude-tracking", "Hide common analytics/tracking cookies such as _ga and _ym");
14035
+
13704
14036
  // dist/eval/evalClient.js
13705
14037
  var evalOnce = async (input) => {
13706
- const url = `http://${input.watcher.host}:${input.watcher.port}/eval`;
13707
14038
  const body = {
13708
14039
  expression: input.expression,
13709
14040
  awaitPromise: input.awaitPromise,
@@ -13713,7 +14044,8 @@ var evalOnce = async (input) => {
13713
14044
  };
13714
14045
  let response;
13715
14046
  try {
13716
- response = await fetchJson(url, {
14047
+ response = await fetchWatcherJson(input.watcher, {
14048
+ path: "/eval",
13717
14049
  method: "POST",
13718
14050
  body,
13719
14051
  timeoutMs: input.timeoutMs ? input.timeoutMs + 5000 : 1e4
@@ -13722,7 +14054,7 @@ var evalOnce = async (input) => {
13722
14054
  return {
13723
14055
  ok: false,
13724
14056
  kind: "transport",
13725
- error: `${input.watcher.id}: failed to reach watcher (${formatError5(error)})`
14057
+ error: formatWatcherTransportError(input.watcher, error)
13726
14058
  };
13727
14059
  }
13728
14060
  if (response.exception && input.failOnException) {
@@ -13759,19 +14091,10 @@ var evalWithRetries = async (input) => {
13759
14091
  return {
13760
14092
  ok: false,
13761
14093
  kind: "transport",
13762
- error: `${input.watcher.id}: failed to reach watcher (unknown error)`,
14094
+ error: formatWatcherTransportError(input.watcher, "unknown error"),
13763
14095
  attempt
13764
14096
  };
13765
14097
  };
13766
- var formatError5 = (error) => {
13767
- if (!error) {
13768
- return "unknown error";
13769
- }
13770
- if (error instanceof Error) {
13771
- return error.message;
13772
- }
13773
- return String(error);
13774
- };
13775
14098
 
13776
14099
  // dist/commands/evalShared.js
13777
14100
  import { readFile } from "node:fs/promises";
@@ -14211,7 +14534,7 @@ var parseTotalTimeout = (value) => {
14211
14534
  };
14212
14535
 
14213
14536
  // dist/commands/iframeHelper.js
14214
- import * as fs10 from "node:fs/promises";
14537
+ import * as fs9 from "node:fs/promises";
14215
14538
  var runIframeHelper = async (options) => {
14216
14539
  const script = generateIframeHelperScript({
14217
14540
  log: options.log ?? true,
@@ -14219,7 +14542,7 @@ var runIframeHelper = async (options) => {
14219
14542
  namespace: options.namespace ?? "argus"
14220
14543
  });
14221
14544
  if (options.out) {
14222
- await fs10.writeFile(options.out, script, "utf-8");
14545
+ await fs9.writeFile(options.out, script, "utf-8");
14223
14546
  console.error(`Written to ${options.out}`);
14224
14547
  } else {
14225
14548
  process.stdout.write(script);
@@ -14986,7 +15309,7 @@ var runDomRemove = async (id, options) => {
14986
15309
  };
14987
15310
 
14988
15311
  // dist/commands/domSetFile.js
14989
- import fs11 from "node:fs";
15312
+ import fs10 from "node:fs";
14990
15313
  var runDomSetFile = async (id, options) => {
14991
15314
  const output = createOutput(options);
14992
15315
  if (!options.selector || options.selector.trim() === "") {
@@ -15002,7 +15325,7 @@ var runDomSetFile = async (id, options) => {
15002
15325
  const files = [];
15003
15326
  for (const f of options.file) {
15004
15327
  const absolute = resolvePath(f);
15005
- if (!fs11.existsSync(absolute)) {
15328
+ if (!fs10.existsSync(absolute)) {
15006
15329
  output.writeWarn(`File not found: ${absolute}`);
15007
15330
  process.exitCode = 2;
15008
15331
  return;
@@ -16499,9 +16822,9 @@ var runTraceStop = async (id, options) => {
16499
16822
  output.writeHuman(`Trace saved: ${stop.outFile} (${stop.eventCount} events, ${formatDurationMs(stop.durationMs)})`);
16500
16823
  };
16501
16824
  var runTraceStartInternal = async (watcher, options, output) => {
16502
- const url = `http://${watcher.host}:${watcher.port}/trace/start`;
16503
16825
  try {
16504
- const response = await fetchJson(url, {
16826
+ const response = await fetchWatcherJson(watcher, {
16827
+ path: "/trace/start",
16505
16828
  method: "POST",
16506
16829
  body: {
16507
16830
  outFile: options.out,
@@ -16512,22 +16835,22 @@ var runTraceStartInternal = async (watcher, options, output) => {
16512
16835
  });
16513
16836
  return response;
16514
16837
  } catch (error) {
16515
- output.writeWarn(`${watcher.id}: failed to reach watcher (${formatError(error)})`);
16838
+ output.writeWarn(formatWatcherTransportError(watcher, error));
16516
16839
  process.exitCode = 1;
16517
16840
  return null;
16518
16841
  }
16519
16842
  };
16520
16843
  var runTraceStopInternal = async (watcher, options, output) => {
16521
- const url = `http://${watcher.host}:${watcher.port}/trace/stop`;
16522
16844
  try {
16523
- const response = await fetchJson(url, {
16845
+ const response = await fetchWatcherJson(watcher, {
16846
+ path: "/trace/stop",
16524
16847
  method: "POST",
16525
16848
  body: { traceId: options.traceId, outFile: options.outFile },
16526
16849
  timeoutMs: 20000
16527
16850
  });
16528
16851
  return response;
16529
16852
  } catch (error) {
16530
- output.writeWarn(`${watcher.id}: failed to reach watcher (${formatError(error)})`);
16853
+ output.writeWarn(formatWatcherTransportError(watcher, error));
16531
16854
  process.exitCode = 1;
16532
16855
  return null;
16533
16856
  }
@@ -16576,7 +16899,7 @@ function resolveActionOptions(options, command) {
16576
16899
  }
16577
16900
 
16578
16901
  // dist/commands/configInit.js
16579
- import fs12 from "node:fs/promises";
16902
+ import fs11 from "node:fs/promises";
16580
16903
  import path11 from "node:path";
16581
16904
  import { fileURLToPath, pathToFileURL } from "node:url";
16582
16905
  var DEFAULT_CONFIG_PATH = ".argus/config.json";
@@ -16610,7 +16933,7 @@ var resolveConfigPath = (cwd, targetPath) => {
16610
16933
  var ensureParentDir2 = async (filePath) => {
16611
16934
  const dir = path11.dirname(filePath);
16612
16935
  try {
16613
- await fs12.mkdir(dir, { recursive: true });
16936
+ await fs11.mkdir(dir, { recursive: true });
16614
16937
  return true;
16615
16938
  } catch (error) {
16616
16939
  console.error(`Failed to create config directory ${dir}: ${error instanceof Error ? error.message : String(error)}`);
@@ -16620,7 +16943,7 @@ var ensureParentDir2 = async (filePath) => {
16620
16943
  };
16621
16944
  var writeConfigFile = async (filePath, contents, force) => {
16622
16945
  try {
16623
- await fs12.writeFile(filePath, contents, { encoding: "utf8", flag: force ? "w" : "wx" });
16946
+ await fs11.writeFile(filePath, contents, { encoding: "utf8", flag: force ? "w" : "wx" });
16624
16947
  return true;
16625
16948
  } catch (error) {
16626
16949
  if (error.code === "EEXIST") {
@@ -16635,7 +16958,7 @@ var writeConfigFile = async (filePath, contents, force) => {
16635
16958
  };
16636
16959
  var ensureSchemaFile = async (schemaPath) => {
16637
16960
  try {
16638
- const stats = await fs12.stat(schemaPath);
16961
+ const stats = await fs11.stat(schemaPath);
16639
16962
  if (!stats.isFile()) {
16640
16963
  console.error(`Schema path is not a file: ${schemaPath}`);
16641
16964
  process.exitCode = 2;
@@ -16688,11 +17011,11 @@ Examples:
16688
17011
  }
16689
17012
 
16690
17013
  // dist/commands/extension/setup.js
16691
- import fs14 from "node:fs";
17014
+ import fs13 from "node:fs";
16692
17015
  import { execSync as execSync2 } from "node:child_process";
16693
17016
 
16694
17017
  // dist/commands/extension/nativeHost.js
16695
- import fs13 from "node:fs";
17018
+ import fs12 from "node:fs";
16696
17019
  import path12 from "node:path";
16697
17020
  import os4 from "node:os";
16698
17021
  import { execSync } from "node:child_process";
@@ -16726,7 +17049,7 @@ var findArgusExecutable = () => {
16726
17049
  try {
16727
17050
  const npmGlobalPrefix = execSync("npm config get prefix", { encoding: "utf8" }).trim();
16728
17051
  const globalBinPath = path12.join(npmGlobalPrefix, "bin", "argus");
16729
- if (fs13.existsSync(globalBinPath)) {
17052
+ if (fs12.existsSync(globalBinPath)) {
16730
17053
  return globalBinPath;
16731
17054
  }
16732
17055
  } catch {}
@@ -16739,7 +17062,7 @@ var findArgusExecutable = () => {
16739
17062
  throw new Error("Could not find argus executable. Please install argus globally (npm install -g @vforsh/argus) or ensure it is in your PATH.");
16740
17063
  };
16741
17064
  var findNodePath = () => {
16742
- return fs13.realpathSync(process.execPath);
17065
+ return fs12.realpathSync(process.execPath);
16743
17066
  };
16744
17067
  var createManifest = (extensionId, executablePath) => {
16745
17068
  return {
@@ -16757,12 +17080,12 @@ var createWrapperScript = (platform, executablePath) => {
16757
17080
  const script = `#!/bin/bash
16758
17081
  exec "${nodePath}" "${executablePath}" watcher native-host
16759
17082
  `;
16760
- fs13.writeFileSync(wrapperPath, script, { mode: 493 });
17083
+ fs12.writeFileSync(wrapperPath, script, { mode: 493 });
16761
17084
  return wrapperPath;
16762
17085
  };
16763
17086
  var readManifest = (manifestPath) => {
16764
17087
  try {
16765
- const content = fs13.readFileSync(manifestPath, "utf8");
17088
+ const content = fs12.readFileSync(manifestPath, "utf8");
16766
17089
  return JSON.parse(content);
16767
17090
  } catch {
16768
17091
  return null;
@@ -16770,7 +17093,7 @@ var readManifest = (manifestPath) => {
16770
17093
  };
16771
17094
  var isWrapperExecutable = (wrapperPath) => {
16772
17095
  try {
16773
- fs13.accessSync(wrapperPath, fs13.constants.X_OK);
17096
+ fs12.accessSync(wrapperPath, fs12.constants.X_OK);
16774
17097
  return true;
16775
17098
  } catch {
16776
17099
  return false;
@@ -16803,7 +17126,7 @@ var runExtensionSetup = async (options) => {
16803
17126
  const manifestDir = getManifestDir(platform);
16804
17127
  const manifestPath = getManifestPath(platform);
16805
17128
  const wrapperPath = getWrapperPath(platform);
16806
- fs14.mkdirSync(manifestDir, { recursive: true });
17129
+ fs13.mkdirSync(manifestDir, { recursive: true });
16807
17130
  let executablePath;
16808
17131
  try {
16809
17132
  executablePath = findArgusExecutable();
@@ -16818,7 +17141,7 @@ var runExtensionSetup = async (options) => {
16818
17141
  }
16819
17142
  createWrapperScript(platform, executablePath);
16820
17143
  const manifest = createManifest(extensionId, wrapperPath);
16821
- fs14.writeFileSync(manifestPath, JSON.stringify(manifest, null, 2));
17144
+ fs13.writeFileSync(manifestPath, JSON.stringify(manifest, null, 2));
16822
17145
  if (platform === "win32") {
16823
17146
  const regKey = `HKCU\\Software\\Google\\Chrome\\NativeMessagingHosts\\${HOST_NAME}`;
16824
17147
  try {
@@ -16859,7 +17182,7 @@ var runExtensionSetup = async (options) => {
16859
17182
  };
16860
17183
 
16861
17184
  // dist/commands/extension/remove.js
16862
- import fs15 from "node:fs";
17185
+ import fs14 from "node:fs";
16863
17186
  import { execSync as execSync3 } from "node:child_process";
16864
17187
  var runExtensionRemove = async (options) => {
16865
17188
  const output = createOutput(options);
@@ -16879,12 +17202,12 @@ var runExtensionRemove = async (options) => {
16879
17202
  const wrapperPath = getWrapperPath(platform);
16880
17203
  let manifestRemoved = false;
16881
17204
  let wrapperRemoved = false;
16882
- if (fs15.existsSync(manifestPath)) {
16883
- fs15.unlinkSync(manifestPath);
17205
+ if (fs14.existsSync(manifestPath)) {
17206
+ fs14.unlinkSync(manifestPath);
16884
17207
  manifestRemoved = true;
16885
17208
  }
16886
- if (fs15.existsSync(wrapperPath)) {
16887
- fs15.unlinkSync(wrapperPath);
17209
+ if (fs14.existsSync(wrapperPath)) {
17210
+ fs14.unlinkSync(wrapperPath);
16888
17211
  wrapperRemoved = true;
16889
17212
  }
16890
17213
  if (platform === "win32") {
@@ -16923,7 +17246,7 @@ var runExtensionRemove = async (options) => {
16923
17246
  };
16924
17247
 
16925
17248
  // dist/commands/extension/status.js
16926
- import fs16 from "node:fs";
17249
+ import fs15 from "node:fs";
16927
17250
  var runExtensionStatus = async (options) => {
16928
17251
  const output = createOutput(options);
16929
17252
  let platform;
@@ -16940,8 +17263,8 @@ var runExtensionStatus = async (options) => {
16940
17263
  }
16941
17264
  const manifestPath = getManifestPath(platform);
16942
17265
  const wrapperPath = getWrapperPath(platform);
16943
- const manifestExists = fs16.existsSync(manifestPath);
16944
- const wrapperExists = fs16.existsSync(wrapperPath);
17266
+ const manifestExists = fs15.existsSync(manifestPath);
17267
+ const wrapperExists = fs15.existsSync(wrapperPath);
16945
17268
  const wrapperExecutable = wrapperExists && isWrapperExecutable(wrapperPath);
16946
17269
  let manifest = null;
16947
17270
  let manifestValid = false;
@@ -17001,7 +17324,7 @@ var runExtensionStatus = async (options) => {
17001
17324
  };
17002
17325
 
17003
17326
  // dist/commands/extension/info.js
17004
- import fs17 from "node:fs";
17327
+ import fs16 from "node:fs";
17005
17328
  var runExtensionInfo = async (options) => {
17006
17329
  const output = createOutput(options);
17007
17330
  let platform;
@@ -17018,8 +17341,8 @@ var runExtensionInfo = async (options) => {
17018
17341
  }
17019
17342
  const manifestPath = getManifestPath(platform);
17020
17343
  const wrapperPath = getWrapperPath(platform);
17021
- const manifestExists = fs17.existsSync(manifestPath);
17022
- const wrapperExists = fs17.existsSync(wrapperPath);
17344
+ const manifestExists = fs16.existsSync(manifestPath);
17345
+ const wrapperExists = fs16.existsSync(wrapperPath);
17023
17346
  let extensionId = null;
17024
17347
  let argusPath = null;
17025
17348
  if (manifestExists) {
@@ -27338,7 +27661,7 @@ function hr2(a2, t, e) {
27338
27661
  }
27339
27662
  return t;
27340
27663
  }
27341
- var fs18 = hr2;
27664
+ var fs17 = hr2;
27342
27665
  function cr2(a2, t) {
27343
27666
  return t === false ? false : a2.charAt(t) === "/" && a2.charAt(t + 1) === "/" ? ls(a2, t) : t;
27344
27667
  }
@@ -27346,7 +27669,7 @@ var ds = cr2;
27346
27669
  function lr2(a2, t) {
27347
27670
  let e = null, s = t;
27348
27671
  for (;s !== e; )
27349
- e = s, s = cs(a2, s), s = ps(a2, s), s = ds(a2, s), s = fs18(a2, s);
27672
+ e = s, s = cs(a2, s), s = ps(a2, s), s = ds(a2, s), s = fs17(a2, s);
27350
27673
  return s;
27351
27674
  }
27352
27675
  var ms = lr2;
@@ -29346,13 +29669,13 @@ function kc({ node: e, parent: t }) {
29346
29669
  let r = /^[fx]?(?:describe|it|test)$/u;
29347
29670
  return t.type === "TaggedTemplateExpression" && t.quasi === e && t.tag.type === "MemberExpression" && t.tag.property.type === "Identifier" && t.tag.property.name === "each" && (t.tag.object.type === "Identifier" && r.test(t.tag.object.name) || t.tag.object.type === "MemberExpression" && t.tag.object.property.type === "Identifier" && (t.tag.object.property.name === "only" || t.tag.object.property.name === "skip") && t.tag.object.object.type === "Identifier" && r.test(t.tag.object.object.name));
29348
29671
  }
29349
- var fs19 = [(e, t) => e.type === "ObjectExpression" && t === "properties", (e, t) => e.type === "CallExpression" && e.callee.type === "Identifier" && e.callee.name === "Component" && t === "arguments", (e, t) => e.type === "Decorator" && t === "expression"];
29672
+ var fs18 = [(e, t) => e.type === "ObjectExpression" && t === "properties", (e, t) => e.type === "CallExpression" && e.callee.type === "Identifier" && e.callee.name === "Component" && t === "arguments", (e, t) => e.type === "Decorator" && t === "expression"];
29350
29673
  function oo2(e) {
29351
29674
  let t = (n) => n.type === "TemplateLiteral", r = (n, s) => Oe3(n) && !n.computed && n.key.type === "Identifier" && n.key.name === "styles" && s === "value";
29352
- return e.match(t, (n, s) => q3(n) && s === "elements", r, ...fs19) || e.match(t, r, ...fs19);
29675
+ return e.match(t, (n, s) => q3(n) && s === "elements", r, ...fs18) || e.match(t, r, ...fs18);
29353
29676
  }
29354
29677
  function ys2(e) {
29355
- return e.match((t) => t.type === "TemplateLiteral", (t, r) => Oe3(t) && !t.computed && t.key.type === "Identifier" && t.key.name === "template" && r === "value", ...fs19);
29678
+ return e.match((t) => t.type === "TemplateLiteral", (t, r) => Oe3(t) && !t.computed && t.key.type === "Identifier" && t.key.name === "template" && r === "value", ...fs18);
29356
29679
  }
29357
29680
  function Ds2(e, t) {
29358
29681
  return T3(e, x2.Block | x2.Leading, ({ value: r }) => r === ` ${t} `);
@@ -33259,7 +33582,7 @@ var ft4 = w4((gx, Mi3) => {
33259
33582
  ct4.default = ct4;
33260
33583
  });
33261
33584
  var fe3 = w4((wx, zi3) => {
33262
- var Bi3 = Me4(), Ui3 = ft4(), Fc2 = ut4(), { isClean: Fi3, my: $i3 } = Ht4(), fs20, Wi3, Gi3, ps3;
33585
+ var Bi3 = Me4(), Ui3 = ft4(), Fc2 = ut4(), { isClean: Fi3, my: $i3 } = Ht4(), fs19, Wi3, Gi3, ps3;
33263
33586
  function Yi3(t) {
33264
33587
  return t.map((e) => (e.nodes && (e.nodes = Yi3(e.nodes)), delete e.source, e));
33265
33588
  }
@@ -33358,7 +33681,7 @@ var fe3 = w4((wx, zi3) => {
33358
33681
  } else if (e.selector || e.selectors)
33359
33682
  e = [new ps3(e)];
33360
33683
  else if (e.name)
33361
- e = [new fs20(e)];
33684
+ e = [new fs19(e)];
33362
33685
  else if (e.text)
33363
33686
  e = [new Bi3(e)];
33364
33687
  else
@@ -33460,7 +33783,7 @@ var fe3 = w4((wx, zi3) => {
33460
33783
  ps3 = t;
33461
33784
  };
33462
33785
  z3.registerAtRule = (t) => {
33463
- fs20 = t;
33786
+ fs19 = t;
33464
33787
  };
33465
33788
  z3.registerRoot = (t) => {
33466
33789
  Gi3 = t;
@@ -33468,7 +33791,7 @@ var fe3 = w4((wx, zi3) => {
33468
33791
  zi3.exports = z3;
33469
33792
  z3.default = z3;
33470
33793
  z3.rebuild = (t) => {
33471
- t.type === "atrule" ? Object.setPrototypeOf(t, fs20.prototype) : t.type === "rule" ? Object.setPrototypeOf(t, ps3.prototype) : t.type === "decl" ? Object.setPrototypeOf(t, Ui3.prototype) : t.type === "comment" ? Object.setPrototypeOf(t, Bi3.prototype) : t.type === "root" && Object.setPrototypeOf(t, Gi3.prototype), t[$i3] = true, t.nodes && t.nodes.forEach((e) => {
33794
+ t.type === "atrule" ? Object.setPrototypeOf(t, fs19.prototype) : t.type === "rule" ? Object.setPrototypeOf(t, ps3.prototype) : t.type === "decl" ? Object.setPrototypeOf(t, Ui3.prototype) : t.type === "comment" ? Object.setPrototypeOf(t, Bi3.prototype) : t.type === "root" && Object.setPrototypeOf(t, Gi3.prototype), t[$i3] = true, t.nodes && t.nodes.forEach((e) => {
33472
33795
  z3.rebuild(e);
33473
33796
  });
33474
33797
  };
@@ -38432,7 +38755,7 @@ var readQuotedLiteral = (source, startIndex, startLineNumber, quote) => {
38432
38755
  return { value: null, nextIndex: index, lineNumber, startLineNumber };
38433
38756
  };
38434
38757
  var classifyCodeString = (value, includeAll) => {
38435
- if (/[\u0000-\u001f]/.test(value)) {
38758
+ if (hasControlChars(value)) {
38436
38759
  return null;
38437
38760
  }
38438
38761
  const kind = detectInterestingKind(value);
@@ -38456,6 +38779,14 @@ var detectInterestingKind = (value) => {
38456
38779
  }
38457
38780
  return null;
38458
38781
  };
38782
+ var hasControlChars = (value) => {
38783
+ for (let index = 0;index < value.length; index += 1) {
38784
+ if (value.charCodeAt(index) < 32) {
38785
+ return true;
38786
+ }
38787
+ }
38788
+ return false;
38789
+ };
38459
38790
  var rankCodeStrings = (matches) => matches.map((match) => ({
38460
38791
  ...match,
38461
38792
  score: scoreCodeString(match)
@@ -39007,6 +39338,7 @@ registerWatcher(program2);
39007
39338
  registerPage(program2);
39008
39339
  registerLogs(program2);
39009
39340
  registerNet(program2);
39341
+ registerAuth(program2);
39010
39342
  registerEval(program2);
39011
39343
  registerCode(program2);
39012
39344
  registerDom(program2);