@agent-scope/cli 1.20.3 → 1.20.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.cjs CHANGED
@@ -11,6 +11,7 @@ var module$1 = require('module');
11
11
  var promises = require('fs/promises');
12
12
  var readline = require('readline');
13
13
  var playwright = require('@agent-scope/playwright');
14
+ var core = require('@agent-scope/core');
14
15
  var playwright$1 = require('playwright');
15
16
  var os = require('os');
16
17
  var http = require('http');
@@ -2302,26 +2303,7 @@ function buildHookInstrumentationScript() {
2302
2303
  // Walk fiber tree and collect hook data per component
2303
2304
  var components = [];
2304
2305
 
2305
- function serializeValue(v) {
2306
- if (v === null) return null;
2307
- if (v === undefined) return undefined;
2308
- var t = typeof v;
2309
- if (t === "string" || t === "number" || t === "boolean") return v;
2310
- if (t === "function") return "[function " + (v.name || "anonymous") + "]";
2311
- if (Array.isArray(v)) {
2312
- try { return v.map(serializeValue); } catch(e) { return "[Array]"; }
2313
- }
2314
- if (t === "object") {
2315
- try {
2316
- var keys = Object.keys(v).slice(0, 5);
2317
- var out = {};
2318
- for (var k of keys) { out[k] = serializeValue(v[k]); }
2319
- if (Object.keys(v).length > 5) out["..."] = "(truncated)";
2320
- return out;
2321
- } catch(e) { return "[Object]"; }
2322
- }
2323
- return String(v);
2324
- }
2306
+ var serializeValue = __SCOPE_SERIALIZE_VALUE__;
2325
2307
 
2326
2308
  // Hook node classifiers (mirrors hooks-extractor.ts logic)
2327
2309
  var HookLayout = 0b00100;
@@ -2542,7 +2524,10 @@ async function runHooksProfiling(componentName, filePath, props) {
2542
2524
  if (renderError !== null) {
2543
2525
  throw new Error(`Component render error: ${renderError}`);
2544
2526
  }
2545
- const instrumentScript = buildHookInstrumentationScript();
2527
+ const instrumentScript = buildHookInstrumentationScript().replace(
2528
+ "__SCOPE_SERIALIZE_VALUE__",
2529
+ core.serialize.toString()
2530
+ );
2546
2531
  const raw = await page.evaluate(instrumentScript);
2547
2532
  const result = raw;
2548
2533
  if (result.error) {
@@ -2738,44 +2723,79 @@ function buildProfilingCollectScript() {
2738
2723
  `;
2739
2724
  }
2740
2725
  async function replayInteraction(page, steps) {
2741
- for (const step of steps) {
2726
+ let executed = 0;
2727
+ const skippedInteractions = [];
2728
+ const skip = (index, step, reason) => {
2729
+ skippedInteractions.push({ index, action: step.action, target: step.target, reason });
2730
+ };
2731
+ for (const [index, step] of steps.entries()) {
2742
2732
  switch (step.action) {
2743
2733
  case "click":
2744
- if (step.target) {
2745
- await page.click(step.target, { timeout: 5e3 }).catch(() => {
2746
- process.stderr.write(` \u26A0 click target "${step.target}" not found, skipping
2734
+ if (!step.target) {
2735
+ skip(index, step, "missing_target");
2736
+ break;
2737
+ }
2738
+ try {
2739
+ await page.click(step.target, { timeout: 5e3 });
2740
+ executed++;
2741
+ } catch {
2742
+ process.stderr.write(` \u26A0 click target "${step.target}" not found, skipping
2747
2743
  `);
2748
- });
2744
+ skip(index, step, "not_found");
2749
2745
  }
2750
2746
  break;
2751
2747
  case "fill":
2752
- if (step.target && step.value !== void 0) {
2753
- await page.fill(step.target, step.value, { timeout: 5e3 }).catch(() => {
2754
- process.stderr.write(` \u26A0 fill target "${step.target}" not found, skipping
2748
+ if (!step.target) {
2749
+ skip(index, step, "missing_target");
2750
+ break;
2751
+ }
2752
+ if (step.value === void 0) {
2753
+ skip(index, step, "missing_value");
2754
+ break;
2755
+ }
2756
+ try {
2757
+ await page.fill(step.target, step.value, { timeout: 5e3 });
2758
+ executed++;
2759
+ } catch {
2760
+ process.stderr.write(` \u26A0 fill target "${step.target}" not found, skipping
2755
2761
  `);
2756
- });
2762
+ skip(index, step, "not_found");
2757
2763
  }
2758
2764
  break;
2759
2765
  case "hover":
2760
- if (step.target) {
2761
- await page.hover(step.target, { timeout: 5e3 }).catch(() => {
2762
- process.stderr.write(` \u26A0 hover target "${step.target}" not found, skipping
2766
+ if (!step.target) {
2767
+ skip(index, step, "missing_target");
2768
+ break;
2769
+ }
2770
+ try {
2771
+ await page.hover(step.target, { timeout: 5e3 });
2772
+ executed++;
2773
+ } catch {
2774
+ process.stderr.write(` \u26A0 hover target "${step.target}" not found, skipping
2763
2775
  `);
2764
- });
2776
+ skip(index, step, "not_found");
2765
2777
  }
2766
2778
  break;
2767
2779
  case "press":
2768
- if (step.value) {
2769
- await page.keyboard.press(step.value);
2780
+ if (!step.value) {
2781
+ skip(index, step, "missing_value");
2782
+ break;
2770
2783
  }
2784
+ await page.keyboard.press(step.value);
2785
+ executed++;
2771
2786
  break;
2772
2787
  case "wait":
2773
2788
  await page.waitForTimeout(step.delay ?? 500);
2789
+ executed++;
2790
+ break;
2791
+ default:
2792
+ skip(index, step, "unsupported");
2774
2793
  break;
2775
2794
  }
2776
2795
  }
2796
+ return { executed, skippedInteractions };
2777
2797
  }
2778
- function analyzeProfileFlags(totalRenders, wastedRenders, timing, layoutShifts) {
2798
+ function analyzeProfileFlags(totalRenders, wastedRenders, timing, layoutShifts, profileValidity) {
2779
2799
  const flags = /* @__PURE__ */ new Set();
2780
2800
  if (wastedRenders !== null && wastedRenders > 0 && wastedRenders / Math.max(1, totalRenders) > 0.3) {
2781
2801
  flags.add("WASTED_RENDER");
@@ -2786,7 +2806,7 @@ function analyzeProfileFlags(totalRenders, wastedRenders, timing, layoutShifts)
2786
2806
  if (layoutShifts.cumulativeScore > 0.1) {
2787
2807
  flags.add("LAYOUT_SHIFT_DETECTED");
2788
2808
  }
2789
- if (timing.js > 100) {
2809
+ if (profileValidity === "interaction" && timing.js > 100) {
2790
2810
  flags.add("SLOW_INTERACTION");
2791
2811
  }
2792
2812
  return [...flags];
@@ -2825,13 +2845,18 @@ async function runInteractionProfile(componentName, filePath, props, interaction
2825
2845
  throw new Error(`Profiling setup failed: ${setupData.error}`);
2826
2846
  }
2827
2847
  const jsStart = Date.now();
2848
+ let executedInteractions = 0;
2849
+ let skippedInteractions = [];
2828
2850
  if (interaction.length > 0) {
2829
2851
  process.stderr.write(` Replaying ${interaction.length} interaction step(s)\u2026
2830
2852
  `);
2831
- await replayInteraction(page, interaction);
2853
+ const replayResult = await replayInteraction(page, interaction);
2854
+ executedInteractions = replayResult.executed;
2855
+ skippedInteractions = replayResult.skippedInteractions;
2832
2856
  await page.waitForTimeout(300);
2833
2857
  }
2834
2858
  const jsDuration = Date.now() - jsStart;
2859
+ const profileValidity = interaction.length === 0 ? "no_interaction_requested" : executedInteractions === 0 ? "setup_only" : "interaction";
2835
2860
  const collected = await page.evaluate(buildProfilingCollectScript());
2836
2861
  const profileData = collected;
2837
2862
  if (profileData.error) {
@@ -2849,7 +2874,13 @@ async function runInteractionProfile(componentName, filePath, props, interaction
2849
2874
  const totalRenders = profileData.commitCount ?? 0;
2850
2875
  const uniqueComponents = profileData.uniqueComponents ?? 0;
2851
2876
  const wastedRenders = profileData.wastedRenders ?? null;
2852
- const flags = analyzeProfileFlags(totalRenders, wastedRenders, timing, layoutShifts);
2877
+ const flags = analyzeProfileFlags(
2878
+ totalRenders,
2879
+ wastedRenders,
2880
+ timing,
2881
+ layoutShifts,
2882
+ profileValidity
2883
+ );
2853
2884
  return {
2854
2885
  component: componentName,
2855
2886
  totalRenders,
@@ -2863,7 +2894,17 @@ async function runInteractionProfile(componentName, filePath, props, interaction
2863
2894
  timing,
2864
2895
  layoutShifts,
2865
2896
  flags,
2866
- interaction
2897
+ interaction,
2898
+ interactionSteps: {
2899
+ attempted: interaction.length,
2900
+ executed: executedInteractions,
2901
+ skipped: skippedInteractions.length
2902
+ },
2903
+ interactionStepsAttempted: interaction.length,
2904
+ interactionStepsExecuted: executedInteractions,
2905
+ interactionStepsSkipped: skippedInteractions.length,
2906
+ skippedInteractions,
2907
+ profileValidity
2867
2908
  };
2868
2909
  } finally {
2869
2910
  await browser.close();
@@ -2963,6 +3004,7 @@ function flattenSerializedValue(sv) {
2963
3004
  case "string":
2964
3005
  case "number":
2965
3006
  case "boolean":
3007
+ case "date":
2966
3008
  return v.value;
2967
3009
  case "object": {
2968
3010
  if (!Array.isArray(v.entries)) return {};