@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 +83 -41
- package/dist/cli.js.map +1 -1
- package/dist/index.cjs +83 -41
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +24 -0
- package/dist/index.d.ts +24 -0
- package/dist/index.js +83 -41
- package/dist/index.js.map +1 -1
- package/package.json +7 -7
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
2746
|
-
|
|
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
|
|
2753
|
-
|
|
2754
|
-
|
|
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
|
-
|
|
2762
|
-
|
|
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
|
-
|
|
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(
|
|
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 {};
|