@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/cli.js CHANGED
@@ -2333,6 +2333,7 @@ function createManifestCommand() {
2333
2333
 
2334
2334
  // src/instrument/hooks.ts
2335
2335
  import { resolve as resolve5 } from "path";
2336
+ import { serialize } from "@agent-scope/core";
2336
2337
  import { getBrowserEntryScript as getBrowserEntryScript2 } from "@agent-scope/playwright";
2337
2338
  import { Command as Cmd } from "commander";
2338
2339
  import { chromium as chromium2 } from "playwright";
@@ -2374,26 +2375,7 @@ function buildHookInstrumentationScript() {
2374
2375
  // Walk fiber tree and collect hook data per component
2375
2376
  var components = [];
2376
2377
 
2377
- function serializeValue(v) {
2378
- if (v === null) return null;
2379
- if (v === undefined) return undefined;
2380
- var t = typeof v;
2381
- if (t === "string" || t === "number" || t === "boolean") return v;
2382
- if (t === "function") return "[function " + (v.name || "anonymous") + "]";
2383
- if (Array.isArray(v)) {
2384
- try { return v.map(serializeValue); } catch(e) { return "[Array]"; }
2385
- }
2386
- if (t === "object") {
2387
- try {
2388
- var keys = Object.keys(v).slice(0, 5);
2389
- var out = {};
2390
- for (var k of keys) { out[k] = serializeValue(v[k]); }
2391
- if (Object.keys(v).length > 5) out["..."] = "(truncated)";
2392
- return out;
2393
- } catch(e) { return "[Object]"; }
2394
- }
2395
- return String(v);
2396
- }
2378
+ var serializeValue = __SCOPE_SERIALIZE_VALUE__;
2397
2379
 
2398
2380
  // Hook node classifiers (mirrors hooks-extractor.ts logic)
2399
2381
  var HookLayout = 0b00100;
@@ -2614,7 +2596,10 @@ async function runHooksProfiling(componentName, filePath, props) {
2614
2596
  if (renderError !== null) {
2615
2597
  throw new Error(`Component render error: ${renderError}`);
2616
2598
  }
2617
- const instrumentScript = buildHookInstrumentationScript();
2599
+ const instrumentScript = buildHookInstrumentationScript().replace(
2600
+ "__SCOPE_SERIALIZE_VALUE__",
2601
+ serialize.toString()
2602
+ );
2618
2603
  const raw = await page.evaluate(instrumentScript);
2619
2604
  const result = raw;
2620
2605
  if (result.error) {
@@ -2816,44 +2801,79 @@ function buildProfilingCollectScript() {
2816
2801
  `;
2817
2802
  }
2818
2803
  async function replayInteraction(page, steps) {
2819
- for (const step of steps) {
2804
+ let executed = 0;
2805
+ const skippedInteractions = [];
2806
+ const skip = (index, step, reason) => {
2807
+ skippedInteractions.push({ index, action: step.action, target: step.target, reason });
2808
+ };
2809
+ for (const [index, step] of steps.entries()) {
2820
2810
  switch (step.action) {
2821
2811
  case "click":
2822
- if (step.target) {
2823
- await page.click(step.target, { timeout: 5e3 }).catch(() => {
2824
- process.stderr.write(` \u26A0 click target "${step.target}" not found, skipping
2812
+ if (!step.target) {
2813
+ skip(index, step, "missing_target");
2814
+ break;
2815
+ }
2816
+ try {
2817
+ await page.click(step.target, { timeout: 5e3 });
2818
+ executed++;
2819
+ } catch {
2820
+ process.stderr.write(` \u26A0 click target "${step.target}" not found, skipping
2825
2821
  `);
2826
- });
2822
+ skip(index, step, "not_found");
2827
2823
  }
2828
2824
  break;
2829
2825
  case "fill":
2830
- if (step.target && step.value !== void 0) {
2831
- await page.fill(step.target, step.value, { timeout: 5e3 }).catch(() => {
2832
- process.stderr.write(` \u26A0 fill target "${step.target}" not found, skipping
2826
+ if (!step.target) {
2827
+ skip(index, step, "missing_target");
2828
+ break;
2829
+ }
2830
+ if (step.value === void 0) {
2831
+ skip(index, step, "missing_value");
2832
+ break;
2833
+ }
2834
+ try {
2835
+ await page.fill(step.target, step.value, { timeout: 5e3 });
2836
+ executed++;
2837
+ } catch {
2838
+ process.stderr.write(` \u26A0 fill target "${step.target}" not found, skipping
2833
2839
  `);
2834
- });
2840
+ skip(index, step, "not_found");
2835
2841
  }
2836
2842
  break;
2837
2843
  case "hover":
2838
- if (step.target) {
2839
- await page.hover(step.target, { timeout: 5e3 }).catch(() => {
2840
- process.stderr.write(` \u26A0 hover target "${step.target}" not found, skipping
2844
+ if (!step.target) {
2845
+ skip(index, step, "missing_target");
2846
+ break;
2847
+ }
2848
+ try {
2849
+ await page.hover(step.target, { timeout: 5e3 });
2850
+ executed++;
2851
+ } catch {
2852
+ process.stderr.write(` \u26A0 hover target "${step.target}" not found, skipping
2841
2853
  `);
2842
- });
2854
+ skip(index, step, "not_found");
2843
2855
  }
2844
2856
  break;
2845
2857
  case "press":
2846
- if (step.value) {
2847
- await page.keyboard.press(step.value);
2858
+ if (!step.value) {
2859
+ skip(index, step, "missing_value");
2860
+ break;
2848
2861
  }
2862
+ await page.keyboard.press(step.value);
2863
+ executed++;
2849
2864
  break;
2850
2865
  case "wait":
2851
2866
  await page.waitForTimeout(step.delay ?? 500);
2867
+ executed++;
2868
+ break;
2869
+ default:
2870
+ skip(index, step, "unsupported");
2852
2871
  break;
2853
2872
  }
2854
2873
  }
2874
+ return { executed, skippedInteractions };
2855
2875
  }
2856
- function analyzeProfileFlags(totalRenders, wastedRenders, timing, layoutShifts) {
2876
+ function analyzeProfileFlags(totalRenders, wastedRenders, timing, layoutShifts, profileValidity) {
2857
2877
  const flags = /* @__PURE__ */ new Set();
2858
2878
  if (wastedRenders !== null && wastedRenders > 0 && wastedRenders / Math.max(1, totalRenders) > 0.3) {
2859
2879
  flags.add("WASTED_RENDER");
@@ -2864,7 +2884,7 @@ function analyzeProfileFlags(totalRenders, wastedRenders, timing, layoutShifts)
2864
2884
  if (layoutShifts.cumulativeScore > 0.1) {
2865
2885
  flags.add("LAYOUT_SHIFT_DETECTED");
2866
2886
  }
2867
- if (timing.js > 100) {
2887
+ if (profileValidity === "interaction" && timing.js > 100) {
2868
2888
  flags.add("SLOW_INTERACTION");
2869
2889
  }
2870
2890
  return [...flags];
@@ -2903,13 +2923,18 @@ async function runInteractionProfile(componentName, filePath, props, interaction
2903
2923
  throw new Error(`Profiling setup failed: ${setupData.error}`);
2904
2924
  }
2905
2925
  const jsStart = Date.now();
2926
+ let executedInteractions = 0;
2927
+ let skippedInteractions = [];
2906
2928
  if (interaction.length > 0) {
2907
2929
  process.stderr.write(` Replaying ${interaction.length} interaction step(s)\u2026
2908
2930
  `);
2909
- await replayInteraction(page, interaction);
2931
+ const replayResult = await replayInteraction(page, interaction);
2932
+ executedInteractions = replayResult.executed;
2933
+ skippedInteractions = replayResult.skippedInteractions;
2910
2934
  await page.waitForTimeout(300);
2911
2935
  }
2912
2936
  const jsDuration = Date.now() - jsStart;
2937
+ const profileValidity = interaction.length === 0 ? "no_interaction_requested" : executedInteractions === 0 ? "setup_only" : "interaction";
2913
2938
  const collected = await page.evaluate(buildProfilingCollectScript());
2914
2939
  const profileData = collected;
2915
2940
  if (profileData.error) {
@@ -2927,7 +2952,13 @@ async function runInteractionProfile(componentName, filePath, props, interaction
2927
2952
  const totalRenders = profileData.commitCount ?? 0;
2928
2953
  const uniqueComponents = profileData.uniqueComponents ?? 0;
2929
2954
  const wastedRenders = profileData.wastedRenders ?? null;
2930
- const flags = analyzeProfileFlags(totalRenders, wastedRenders, timing, layoutShifts);
2955
+ const flags = analyzeProfileFlags(
2956
+ totalRenders,
2957
+ wastedRenders,
2958
+ timing,
2959
+ layoutShifts,
2960
+ profileValidity
2961
+ );
2931
2962
  return {
2932
2963
  component: componentName,
2933
2964
  totalRenders,
@@ -2941,7 +2972,17 @@ async function runInteractionProfile(componentName, filePath, props, interaction
2941
2972
  timing,
2942
2973
  layoutShifts,
2943
2974
  flags,
2944
- interaction
2975
+ interaction,
2976
+ interactionSteps: {
2977
+ attempted: interaction.length,
2978
+ executed: executedInteractions,
2979
+ skipped: skippedInteractions.length
2980
+ },
2981
+ interactionStepsAttempted: interaction.length,
2982
+ interactionStepsExecuted: executedInteractions,
2983
+ interactionStepsSkipped: skippedInteractions.length,
2984
+ skippedInteractions,
2985
+ profileValidity
2945
2986
  };
2946
2987
  } finally {
2947
2988
  await browser.close();
@@ -3047,6 +3088,7 @@ function flattenSerializedValue(sv) {
3047
3088
  case "string":
3048
3089
  case "number":
3049
3090
  case "boolean":
3091
+ case "date":
3050
3092
  return v.value;
3051
3093
  case "object": {
3052
3094
  if (!Array.isArray(v.entries)) return {};