@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/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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
2824
|
-
|
|
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
|
|
2831
|
-
|
|
2832
|
-
|
|
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
|
-
|
|
2840
|
-
|
|
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
|
-
|
|
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(
|
|
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 {};
|