zeitzeuge 0.5.1 → 0.6.0
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/analysis/agent.d.ts +16 -3
- package/dist/analysis/agent.d.ts.map +1 -1
- package/dist/analysis/prompts.d.ts +1 -1
- package/dist/analysis/prompts.d.ts.map +1 -1
- package/dist/cli.js +291 -46
- package/dist/output/report.d.ts.map +1 -1
- package/dist/schema.d.ts +22 -0
- package/dist/schema.d.ts.map +1 -1
- package/dist/vitest/index.js +405 -55
- package/dist/vitest/profile-parser.d.ts.map +1 -1
- package/dist/vitest/prompts.d.ts +1 -1
- package/dist/vitest/prompts.d.ts.map +1 -1
- package/dist/vitest/reporter.d.ts.map +1 -1
- package/dist/vitest/types.d.ts +14 -0
- package/dist/vitest/types.d.ts.map +1 -1
- package/dist/vitest/workspace.d.ts.map +1 -1
- package/package.json +1 -1
package/dist/analysis/agent.d.ts
CHANGED
|
@@ -1,17 +1,30 @@
|
|
|
1
1
|
import { type BackendProtocol } from 'deepagents';
|
|
2
2
|
import type { BaseChatModel } from '@langchain/core/language_models/chat_models';
|
|
3
3
|
import type { Ora } from 'ora';
|
|
4
|
-
import type { Finding } from '../types.js';
|
|
4
|
+
import type { Finding, HeapSummary, TraceResult } from '../types.js';
|
|
5
|
+
import type { PerformanceMetrics } from '../vitest/metrics.js';
|
|
6
|
+
/** Context for building a dynamic page-load user message. */
|
|
7
|
+
export interface PageLoadContext {
|
|
8
|
+
url: string;
|
|
9
|
+
heapSummary: HeapSummary;
|
|
10
|
+
traceResult: TraceResult;
|
|
11
|
+
}
|
|
5
12
|
/**
|
|
6
13
|
* Analyze performance data using a Deep Agent that explores
|
|
7
14
|
* the workspace containing heap + trace data + source files.
|
|
8
15
|
*/
|
|
9
|
-
export declare function analyze(model: BaseChatModel, backend: BackendProtocol, spinner: Ora): Promise<Finding[]>;
|
|
16
|
+
export declare function analyze(model: BaseChatModel, backend: BackendProtocol, spinner: Ora, context?: PageLoadContext): Promise<Finding[]>;
|
|
17
|
+
/** Context for building a dynamic Vitest user message. */
|
|
18
|
+
export interface VitestAnalysisContext {
|
|
19
|
+
metrics: PerformanceMetrics;
|
|
20
|
+
hasHeapProfiles: boolean;
|
|
21
|
+
hasListenerTracking: boolean;
|
|
22
|
+
}
|
|
10
23
|
/**
|
|
11
24
|
* Analyze Vitest test performance data using a Deep Agent that explores
|
|
12
25
|
* the workspace containing CPU profiles + test timing + source files.
|
|
13
26
|
*/
|
|
14
|
-
export declare function analyzeTestPerformance(model: BaseChatModel, backend: BackendProtocol, spinner: Ora): Promise<Finding[]>;
|
|
27
|
+
export declare function analyzeTestPerformance(model: BaseChatModel, backend: BackendProtocol, spinner: Ora, context?: VitestAnalysisContext): Promise<Finding[]>;
|
|
15
28
|
/**
|
|
16
29
|
* Format bytes into a human-readable string.
|
|
17
30
|
* Kept for backwards compatibility with existing imports.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"agent.d.ts","sourceRoot":"","sources":["../../src/analysis/agent.ts"],"names":[],"mappings":"AAAA,OAAO,EAEL,KAAK,eAAe,EAGrB,MAAM,YAAY,CAAC;AAEpB,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,6CAA6C,CAAC;AACjF,OAAO,KAAK,EAAE,GAAG,EAAE,MAAM,KAAK,CAAC;AAM/B,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,aAAa,CAAC;
|
|
1
|
+
{"version":3,"file":"agent.d.ts","sourceRoot":"","sources":["../../src/analysis/agent.ts"],"names":[],"mappings":"AAAA,OAAO,EAEL,KAAK,eAAe,EAGrB,MAAM,YAAY,CAAC;AAEpB,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,6CAA6C,CAAC;AACjF,OAAO,KAAK,EAAE,GAAG,EAAE,MAAM,KAAK,CAAC;AAM/B,OAAO,KAAK,EAAE,OAAO,EAAE,WAAW,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AACrE,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,sBAAsB,CAAC;AAwC/D,6DAA6D;AAC7D,MAAM,WAAW,eAAe;IAC9B,GAAG,EAAE,MAAM,CAAC;IACZ,WAAW,EAAE,WAAW,CAAC;IACzB,WAAW,EAAE,WAAW,CAAC;CAC1B;AA6DD;;;GAGG;AACH,wBAAsB,OAAO,CAC3B,KAAK,EAAE,aAAa,EACpB,OAAO,EAAE,eAAe,EACxB,OAAO,EAAE,GAAG,EACZ,OAAO,CAAC,EAAE,eAAe,GACxB,OAAO,CAAC,OAAO,EAAE,CAAC,CAwBpB;AAED,0DAA0D;AAC1D,MAAM,WAAW,qBAAqB;IACpC,OAAO,EAAE,kBAAkB,CAAC;IAC5B,eAAe,EAAE,OAAO,CAAC;IACzB,mBAAmB,EAAE,OAAO,CAAC;CAC9B;AAkDD;;;GAGG;AACH,wBAAsB,sBAAsB,CAC1C,KAAK,EAAE,aAAa,EACpB,OAAO,EAAE,eAAe,EACxB,OAAO,EAAE,GAAG,EACZ,OAAO,CAAC,EAAE,qBAAqB,GAC9B,OAAO,CAAC,OAAO,EAAE,CAAC,CAwBpB;AAED;;;GAGG;AACH,wBAAgB,WAAW,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAIjD"}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
export declare const SYSTEM_PROMPT = "You are an expert web performance engineer. You have access to a virtual filesystem workspace containing captured data from a real page load: heap snapshot, network trace, and Chrome runtime trace.\n\n## Workspace structure\n\n- /heap/summary.json \u2014 Parsed V8 heap snapshot: largest objects, type stats, constructor stats, detached DOM nodes, closure stats\n- /trace/summary.json \u2014 Page load metrics: timing, long tasks, render-blocking resources, resource breakdown\n- /trace/network-waterfall.json \u2014 Every network request with timing, size, priority, render-blocking status\n- /trace/asset-manifest.json \u2014 Index of all assets with paths to stored files\n- /trace/runtime/summary.json \u2014 Runtime trace overview: frame breakdown (scripting/layout/paint/GC), blocking function count, listener imbalances, GC stats\n- /trace/runtime/blocking-functions.json \u2014 Functions that blocked the main thread > 50ms, with script URL, line number, call stack, and duration\n- /trace/runtime/event-listeners.json \u2014 Event listener add/remove counts per event type, with source locations\n- /trace/runtime/frame-breakdown.json \u2014 Time spent in scripting vs layout vs paint vs GC\n- /trace/runtime/raw-events.json \u2014 Full Chrome trace events (large file \u2014 read to investigate specific function calls, layouts, GC, and event dispatches)\n- /scripts/*.js \u2014 Actual JavaScript source files captured during page load\n- /styles/*.css \u2014 Actual CSS source files\n- /html/document.html \u2014 The HTML document\n\n## Your workflow\n\n1. Read /heap/summary.json, /trace/summary.json, AND /trace/runtime/summary.json first for the big picture\n2. Identify the highest-impact issues from all datasets\n3. For each issue, dive into the relevant source files to understand the root cause\n4. Provide specific, code-level fixes\n\n## What to look for\n\n### Memory issues (from heap data)\n- Memory leaks: unbounded arrays, maps, caches that grow without bound\n- Detached DOM nodes: DOM elements removed from the document but still referenced\n- Large retained objects: single objects or trees retaining disproportionate memory\n- Closure leaks: closures capturing variables they no longer need\n\n### Page-load issues (from trace + source code)\n- Render-blocking scripts: <script> in <head> without async/defer \u2014 read the script to judge if it must be synchronous\n- Render-blocking CSS: large stylesheets blocking first paint\n- Long tasks (> 50ms): identify the function/module causing the block by reading the source\n- Large bundles: scripts > 100KB \u2014 search for unused imports or code that could be lazy-loaded\n- Sequential waterfalls: resources chained sequentially that could load in parallel\n\n### Runtime issues (from Chrome trace)\n- Frame-blocking functions: read /trace/runtime/blocking-functions.json first, then inspect the actual script source at the reported line number to understand what the function does and how to optimize it\n- Event listener leaks: check /trace/runtime/event-listeners.json for event types where addCount >> removeCount, then grep the scripts for those addEventListener calls\n- GC pressure: high GC pause counts or duration suggest excessive short-lived object creation \u2014 look for hot loops creating objects\n- Layout thrashing: forced synchronous layouts caused by reading layout properties (offsetHeight, getBoundingClientRect) after DOM writes\n\n## Output guidelines\n\n- Report 3\u20137 findings, ordered by impact (mix of memory, page-load, and runtime if all have issues)\n- Be specific \u2014 name actual files, functions, object constructors, and retention paths\n- Provide concrete code fixes, not generic advice\n- If heap, trace, and runtime all look healthy, say so \u2014 don't manufacture issues";
|
|
1
|
+
export declare const SYSTEM_PROMPT = "You are an expert web performance engineer. You have access to a virtual filesystem workspace containing captured data from a real page load: heap snapshot, network trace, and Chrome runtime trace.\n\n## Workspace structure\n\n- /heap/summary.json \u2014 Parsed V8 heap snapshot: largest objects, type stats, constructor stats, detached DOM nodes, closure stats\n- /trace/summary.json \u2014 Page load metrics: timing, long tasks, render-blocking resources, resource breakdown\n- /trace/network-waterfall.json \u2014 Every network request with timing, size, priority, render-blocking status\n- /trace/asset-manifest.json \u2014 Index of all assets with paths to stored files\n- /trace/runtime/summary.json \u2014 Runtime trace overview: frame breakdown (scripting/layout/paint/GC), blocking function count, listener imbalances, GC stats\n- /trace/runtime/blocking-functions.json \u2014 Functions that blocked the main thread > 50ms, with script URL, line number, call stack, and duration\n- /trace/runtime/event-listeners.json \u2014 Event listener add/remove counts per event type, with source locations\n- /trace/runtime/frame-breakdown.json \u2014 Time spent in scripting vs layout vs paint vs GC\n- /trace/runtime/raw-events.json \u2014 Full Chrome trace events (large file \u2014 read to investigate specific function calls, layouts, GC, and event dispatches)\n- /scripts/*.js \u2014 Actual JavaScript source files captured during page load\n- /styles/*.css \u2014 Actual CSS source files\n- /html/document.html \u2014 The HTML document\n\n## Your workflow\n\n1. Read /heap/summary.json, /trace/summary.json, AND /trace/runtime/summary.json first for the big picture\n2. Identify the highest-impact issues from all datasets\n3. For each issue, dive into the relevant source files to understand the root cause\n4. Provide specific, code-level fixes\n\n## What to look for\n\n### Memory issues (from heap data)\n- Memory leaks: unbounded arrays, maps, caches that grow without bound\n- Detached DOM nodes: DOM elements removed from the document but still referenced\n- Large retained objects: single objects or trees retaining disproportionate memory\n- Closure leaks: closures capturing variables they no longer need\n\n### Page-load issues (from trace + source code)\n- Render-blocking scripts: <script> in <head> without async/defer \u2014 read the script to judge if it must be synchronous\n- Render-blocking CSS: large stylesheets blocking first paint\n- Long tasks (> 50ms): identify the function/module causing the block by reading the source\n- Large bundles: scripts > 100KB \u2014 search for unused imports or code that could be lazy-loaded\n- Sequential waterfalls: resources chained sequentially that could load in parallel\n\n### Runtime issues (from Chrome trace)\n- Frame-blocking functions: read /trace/runtime/blocking-functions.json first, then inspect the actual script source at the reported line number to understand what the function does and how to optimize it\n- Event listener leaks: check /trace/runtime/event-listeners.json for event types where addCount >> removeCount, then grep the scripts for those addEventListener calls\n- GC pressure: high GC pause counts or duration suggest excessive short-lived object creation \u2014 look for hot loops creating objects\n- Layout thrashing: forced synchronous layouts caused by reading layout properties (offsetHeight, getBoundingClientRect) after DOM writes\n\n## Severity classification\n\nAssign severity based on measured impact \u2014 do NOT guess:\n\n- **critical** \u2014 A blocking function >500ms, retained heap object >5MB,\n render-blocking resource >200KB, listener addCount > 10\u00D7 removeCount,\n or GC pauses totalling >500ms\n- **warning** \u2014 A blocking function 100\u2013500ms, retained heap object 1\u20135MB,\n render-blocking resource 50\u2013200KB, listener addCount > 2\u00D7 removeCount,\n or GC pauses totalling 100\u2013500ms\n- **info** \u2014 Blocking function 50\u2013100ms, retained object <1MB, minor\n optimisation opportunities, or observations about dependency usage\n\nAlways base severity on the actual numbers from the captured data \u2014 never inflate.\n\n## Verification rules\n\nThese rules are mandatory for every finding:\n\n1. **ALWAYS read the source file** in /scripts/, /styles/, or /html/ and\n verify the code BEFORE suggesting a fix. Never suggest a fix for code\n you have not read.\n2. **Never guess at line numbers** \u2014 confirm by reading the file. If the\n trace reports a line number but the source doesn't match, say so.\n3. Each `suggestedFix` MUST reference the actual current code and describe\n what to change. Include a before/after snippet from the real source.\n4. If the heap summary, trace summary, and runtime summary all show healthy\n numbers, state that the page is well-optimised \u2014 do NOT manufacture\n findings.\n5. Never report a finding based solely on a URL or resource name \u2014 always\n read the actual content to confirm the issue.\n\n## Cross-referencing data\n\n- When a script appears in BOTH /trace/runtime/blocking-functions.json (CPU)\n AND /heap/summary.json (memory), mention both dimensions in the finding.\n- Check /trace/runtime/event-listeners.json for listener imbalances and\n cross-reference with the actual addEventListener calls in /scripts/.\n- Use /trace/network-waterfall.json to identify sequential chains, then read\n the initiating script to confirm the dependency.\n- When GC pauses are significant, cross-reference with heap data to identify\n which constructors or allocation patterns are responsible.\n\n## Estimating impactMs\n\nEvery finding should include an `impactMs` estimate when possible:\n\n- For render-blocking resources: impactMs \u2248 the resource's load duration\n (from the network waterfall) that could be deferred.\n- For blocking functions: impactMs \u2248 the function's duration minus 50ms\n (the long-task threshold).\n- For memory issues: impactMs may not apply \u2014 use `retainedSize` instead.\n- If you cannot reasonably estimate the savings, omit impactMs rather than\n guessing.\n\n## Output guidelines\n\n- Report 3\u20137 findings, ordered by impact (mix of memory, page-load, and runtime if all have issues)\n- Be specific \u2014 name actual files, functions, object constructors, and retention paths\n- Provide concrete code fixes, not generic advice\n- If heap, trace, and runtime all look healthy, say so \u2014 don't manufacture issues\n\n## Structured output fields\n\nFor each finding, fill in as many fields as applicable:\n\n- `sourceFile` \u2014 the workspace path (e.g. /scripts/app.js) or resource URL\n where the issue occurs. Always set this when you can identify the file.\n- `lineNumber` \u2014 the 1-based line number in the source file. Only set after\n verifying by reading the file.\n- `confidence` \u2014 `high` if you read the source and confirmed the issue,\n `medium` if the profiling data strongly suggests it but you couldn't fully\n verify, `low` if inferred from patterns.\n- `estimatedSavingsMs` \u2014 your estimate of time saved if the fix is applied.\n- `beforeCode` \u2014 a snippet of the CURRENT problematic code, copied from the\n source file you read. Keep it focused (5\u201315 lines).\n- `afterCode` \u2014 the IMPROVED code snippet showing the fix. Must be a drop-in\n replacement for `beforeCode`.\n- `impactMs` \u2014 the current measured cost (e.g. blocking function duration,\n resource load time).";
|
|
2
2
|
//# sourceMappingURL=prompts.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"prompts.d.ts","sourceRoot":"","sources":["../../src/analysis/prompts.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,aAAa,
|
|
1
|
+
{"version":3,"file":"prompts.d.ts","sourceRoot":"","sources":["../../src/analysis/prompts.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,aAAa,i1OA4HH,CAAC"}
|
package/dist/cli.js
CHANGED
|
@@ -59,12 +59,86 @@ var SYSTEM_PROMPT = `You are an expert web performance engineer. You have access
|
|
|
59
59
|
- GC pressure: high GC pause counts or duration suggest excessive short-lived object creation — look for hot loops creating objects
|
|
60
60
|
- Layout thrashing: forced synchronous layouts caused by reading layout properties (offsetHeight, getBoundingClientRect) after DOM writes
|
|
61
61
|
|
|
62
|
+
## Severity classification
|
|
63
|
+
|
|
64
|
+
Assign severity based on measured impact — do NOT guess:
|
|
65
|
+
|
|
66
|
+
- **critical** — A blocking function >500ms, retained heap object >5MB,
|
|
67
|
+
render-blocking resource >200KB, listener addCount > 10× removeCount,
|
|
68
|
+
or GC pauses totalling >500ms
|
|
69
|
+
- **warning** — A blocking function 100–500ms, retained heap object 1–5MB,
|
|
70
|
+
render-blocking resource 50–200KB, listener addCount > 2× removeCount,
|
|
71
|
+
or GC pauses totalling 100–500ms
|
|
72
|
+
- **info** — Blocking function 50–100ms, retained object <1MB, minor
|
|
73
|
+
optimisation opportunities, or observations about dependency usage
|
|
74
|
+
|
|
75
|
+
Always base severity on the actual numbers from the captured data — never inflate.
|
|
76
|
+
|
|
77
|
+
## Verification rules
|
|
78
|
+
|
|
79
|
+
These rules are mandatory for every finding:
|
|
80
|
+
|
|
81
|
+
1. **ALWAYS read the source file** in /scripts/, /styles/, or /html/ and
|
|
82
|
+
verify the code BEFORE suggesting a fix. Never suggest a fix for code
|
|
83
|
+
you have not read.
|
|
84
|
+
2. **Never guess at line numbers** — confirm by reading the file. If the
|
|
85
|
+
trace reports a line number but the source doesn't match, say so.
|
|
86
|
+
3. Each \`suggestedFix\` MUST reference the actual current code and describe
|
|
87
|
+
what to change. Include a before/after snippet from the real source.
|
|
88
|
+
4. If the heap summary, trace summary, and runtime summary all show healthy
|
|
89
|
+
numbers, state that the page is well-optimised — do NOT manufacture
|
|
90
|
+
findings.
|
|
91
|
+
5. Never report a finding based solely on a URL or resource name — always
|
|
92
|
+
read the actual content to confirm the issue.
|
|
93
|
+
|
|
94
|
+
## Cross-referencing data
|
|
95
|
+
|
|
96
|
+
- When a script appears in BOTH /trace/runtime/blocking-functions.json (CPU)
|
|
97
|
+
AND /heap/summary.json (memory), mention both dimensions in the finding.
|
|
98
|
+
- Check /trace/runtime/event-listeners.json for listener imbalances and
|
|
99
|
+
cross-reference with the actual addEventListener calls in /scripts/.
|
|
100
|
+
- Use /trace/network-waterfall.json to identify sequential chains, then read
|
|
101
|
+
the initiating script to confirm the dependency.
|
|
102
|
+
- When GC pauses are significant, cross-reference with heap data to identify
|
|
103
|
+
which constructors or allocation patterns are responsible.
|
|
104
|
+
|
|
105
|
+
## Estimating impactMs
|
|
106
|
+
|
|
107
|
+
Every finding should include an \`impactMs\` estimate when possible:
|
|
108
|
+
|
|
109
|
+
- For render-blocking resources: impactMs ≈ the resource's load duration
|
|
110
|
+
(from the network waterfall) that could be deferred.
|
|
111
|
+
- For blocking functions: impactMs ≈ the function's duration minus 50ms
|
|
112
|
+
(the long-task threshold).
|
|
113
|
+
- For memory issues: impactMs may not apply — use \`retainedSize\` instead.
|
|
114
|
+
- If you cannot reasonably estimate the savings, omit impactMs rather than
|
|
115
|
+
guessing.
|
|
116
|
+
|
|
62
117
|
## Output guidelines
|
|
63
118
|
|
|
64
119
|
- Report 3–7 findings, ordered by impact (mix of memory, page-load, and runtime if all have issues)
|
|
65
120
|
- Be specific — name actual files, functions, object constructors, and retention paths
|
|
66
121
|
- Provide concrete code fixes, not generic advice
|
|
67
|
-
- If heap, trace, and runtime all look healthy, say so — don't manufacture issues
|
|
122
|
+
- If heap, trace, and runtime all look healthy, say so — don't manufacture issues
|
|
123
|
+
|
|
124
|
+
## Structured output fields
|
|
125
|
+
|
|
126
|
+
For each finding, fill in as many fields as applicable:
|
|
127
|
+
|
|
128
|
+
- \`sourceFile\` — the workspace path (e.g. /scripts/app.js) or resource URL
|
|
129
|
+
where the issue occurs. Always set this when you can identify the file.
|
|
130
|
+
- \`lineNumber\` — the 1-based line number in the source file. Only set after
|
|
131
|
+
verifying by reading the file.
|
|
132
|
+
- \`confidence\` — \`high\` if you read the source and confirmed the issue,
|
|
133
|
+
\`medium\` if the profiling data strongly suggests it but you couldn't fully
|
|
134
|
+
verify, \`low\` if inferred from patterns.
|
|
135
|
+
- \`estimatedSavingsMs\` — your estimate of time saved if the fix is applied.
|
|
136
|
+
- \`beforeCode\` — a snippet of the CURRENT problematic code, copied from the
|
|
137
|
+
source file you read. Keep it focused (5–15 lines).
|
|
138
|
+
- \`afterCode\` — the IMPROVED code snippet showing the fix. Must be a drop-in
|
|
139
|
+
replacement for \`beforeCode\`.
|
|
140
|
+
- \`impactMs\` — the current measured cost (e.g. blocking function duration,
|
|
141
|
+
resource load time).`;
|
|
68
142
|
|
|
69
143
|
// src/vitest/prompts.ts
|
|
70
144
|
var VITEST_SYSTEM_PROMPT = `You are an expert in JavaScript/TypeScript performance optimization.
|
|
@@ -105,7 +179,9 @@ Every hot function and script in the workspace has a \`sourceCategory\` field:
|
|
|
105
179
|
- /heap-profiles/index.json — (optional) Manifest mapping test files to heap profiles
|
|
106
180
|
- /heap-profiles/<file>.json — (optional) Heap profile summary: allocation hotspots,
|
|
107
181
|
per-script allocated bytes (with sourceCategory)
|
|
108
|
-
- /hot-functions/application.json — **START HERE**: Hot functions from application code only
|
|
182
|
+
- /hot-functions/application.json — **START HERE**: Hot functions from application code only.
|
|
183
|
+
Each entry includes a \`sourceSnippet\` (lines around the hot line) and \`workspacePath\`
|
|
184
|
+
(path to the full source file in the workspace) when source code is available.
|
|
109
185
|
- /hot-functions/dependencies.json — Hot functions from third-party dependencies
|
|
110
186
|
- /hot-functions/global.json — All hot functions across all categories
|
|
111
187
|
- /scripts/application.json — Per-script time breakdown for application code
|
|
@@ -113,8 +189,11 @@ Every hot function and script in the workspace has a \`sourceCategory\` field:
|
|
|
113
189
|
- /listener-tracking.json — (optional) Event listener tracking data captured from
|
|
114
190
|
worker processes. Contains per-event-type add/remove counts for EventTarget and
|
|
115
191
|
EventEmitter, plus exceedances where listener counts exceeded maxListeners.
|
|
116
|
-
- /
|
|
117
|
-
|
|
192
|
+
- /src/index.json — Mapping of source files to their hot functions (quick overview
|
|
193
|
+
of which files matter and what bottlenecks they contain)
|
|
194
|
+
- /tests/<relative-path> — Test source files (directory structure preserved)
|
|
195
|
+
- /src/<relative-path> — Application and dependency source files referenced by
|
|
196
|
+
hot functions (directory structure preserved from the project root)
|
|
118
197
|
|
|
119
198
|
## Your workflow
|
|
120
199
|
|
|
@@ -159,6 +238,9 @@ Every hot function and script in the workspace has a \`sourceCategory\` field:
|
|
|
159
238
|
- When allocation hotspots match CPU hotspots, prioritize fixes there first
|
|
160
239
|
|
|
161
240
|
### Call chain analysis
|
|
241
|
+
- Each hot function includes a \`callerChain\` field — the chain of callers
|
|
242
|
+
from the hot function up toward the entry point. Use this to understand
|
|
243
|
+
WHY a function is hot and which application-level call triggers it.
|
|
162
244
|
- Trace expensive call trees to find which APPLICATION function triggers them
|
|
163
245
|
- Follow the call tree from application entry points down to the hot leaf functions
|
|
164
246
|
- Identify which application-level design decisions lead to the bottleneck
|
|
@@ -208,6 +290,63 @@ Each finding MUST use one of these exact category values:
|
|
|
208
290
|
Prefer more specific categories (algorithm, serialization, allocation, event-handling)
|
|
209
291
|
over generic ones (hot-function, other) when the root cause is clear.
|
|
210
292
|
|
|
293
|
+
## Severity classification
|
|
294
|
+
|
|
295
|
+
Assign severity based on measured impact — do NOT guess:
|
|
296
|
+
|
|
297
|
+
- **critical** — A single function consuming >15% self-time, listener exceedances
|
|
298
|
+
(count exceeding maxListeners), or GC overhead >10% of total profile duration
|
|
299
|
+
- **warning** — A function consuming 5–15% self-time, listener add/remove imbalance
|
|
300
|
+
where addCount > 2× removeCount, or GC overhead between 5–10%
|
|
301
|
+
- **info** — A function consuming <5% self-time, minor inefficiencies,
|
|
302
|
+
dependency observations, or small optimisation opportunities
|
|
303
|
+
|
|
304
|
+
Always base severity on the actual numbers from the profiling data — never inflate.
|
|
305
|
+
|
|
306
|
+
## Verification rules
|
|
307
|
+
|
|
308
|
+
These rules are mandatory for every finding:
|
|
309
|
+
|
|
310
|
+
1. **ALWAYS read the source file** in /src/ or /tests/ and verify the code
|
|
311
|
+
BEFORE suggesting a fix. Never suggest a fix for code you have not read.
|
|
312
|
+
2. **Never guess at line numbers** — confirm by reading the file. If the profile
|
|
313
|
+
reports line 42 but the source at line 42 doesn't match, say so.
|
|
314
|
+
3. Each \`suggestedFix\` MUST reference the actual current code and describe
|
|
315
|
+
what to change. Include a before/after snippet from the real source.
|
|
316
|
+
4. If /hot-functions/application.json is empty or every function is <1%
|
|
317
|
+
self-time, state that the application code is efficient — do NOT
|
|
318
|
+
manufacture findings.
|
|
319
|
+
5. Never report a finding based solely on a function name — always read the
|
|
320
|
+
implementation to confirm the issue exists.
|
|
321
|
+
|
|
322
|
+
## Cross-referencing data
|
|
323
|
+
|
|
324
|
+
- When a function appears in BOTH /hot-functions/ (CPU hotspot) AND
|
|
325
|
+
/heap-profiles/ (allocation hotspot), prioritise it and mention both
|
|
326
|
+
dimensions in the finding.
|
|
327
|
+
- Cross-reference /hot-functions/ data with /heap-profiles/ when both are
|
|
328
|
+
present to find functions that are expensive in both CPU and memory.
|
|
329
|
+
- Check whether hot dependency calls originate from application code by
|
|
330
|
+
tracing the call tree in /profiles/.
|
|
331
|
+
- When /listener-tracking.json is present, cross-reference exceedance stack
|
|
332
|
+
traces with the source code in /src/ to pinpoint the registration site.
|
|
333
|
+
- /metrics/current.json contains pre-computed aggregate metrics (suite totals,
|
|
334
|
+
CPU category breakdown, top hot functions). Use it for the big-picture
|
|
335
|
+
numbers when sizing impact.
|
|
336
|
+
|
|
337
|
+
## Estimating impactMs
|
|
338
|
+
|
|
339
|
+
Every finding should include an \`impactMs\` estimate when possible:
|
|
340
|
+
|
|
341
|
+
- Use the hot function's \`selfTime\` as the baseline cost.
|
|
342
|
+
- Estimate what fraction of that cost the fix would eliminate
|
|
343
|
+
(e.g. an O(n²) → O(n) fix on data of size 1000 might eliminate ~99%).
|
|
344
|
+
- impactMs = selfTime × estimated fraction eliminated.
|
|
345
|
+
- Example: a function with selfTime 200ms in a 1000ms run, where an
|
|
346
|
+
algorithm fix would remove ~80% of the work → impactMs ≈ 160.
|
|
347
|
+
- If you cannot reasonably estimate the savings, omit impactMs rather than
|
|
348
|
+
guessing.
|
|
349
|
+
|
|
211
350
|
## Output guidelines
|
|
212
351
|
|
|
213
352
|
- Report 3–7 findings, ordered by impact ON THE APPLICATION CODE
|
|
@@ -218,7 +357,28 @@ over generic ones (hot-function, other) when the root cause is clear.
|
|
|
218
357
|
- When reporting a dependency bottleneck, explain what application code is
|
|
219
358
|
calling it and how the developer can reduce that cost
|
|
220
359
|
- If the application code is already efficient, say so — don't force findings
|
|
221
|
-
about test infrastructure just to fill the report
|
|
360
|
+
about test infrastructure just to fill the report
|
|
361
|
+
|
|
362
|
+
## Structured output fields
|
|
363
|
+
|
|
364
|
+
For each finding, fill in as many fields as applicable:
|
|
365
|
+
|
|
366
|
+
- \`sourceFile\` — the workspace path (e.g. /src/utils/parser.ts) or original
|
|
367
|
+
file path where the issue occurs. Always set this when you can identify
|
|
368
|
+
the file.
|
|
369
|
+
- \`lineNumber\` — the 1-based line number in the source file. Only set after
|
|
370
|
+
verifying by reading the file.
|
|
371
|
+
- \`confidence\` — \`high\` if you read the source and confirmed the issue,
|
|
372
|
+
\`medium\` if the profiling data strongly suggests it but you couldn't fully
|
|
373
|
+
verify, \`low\` if inferred from patterns.
|
|
374
|
+
- \`estimatedSavingsMs\` — your estimate of time saved if the fix is applied.
|
|
375
|
+
- \`beforeCode\` — a snippet of the CURRENT problematic code, copied from the
|
|
376
|
+
source file you read. Keep it focused (5–15 lines).
|
|
377
|
+
- \`afterCode\` — the IMPROVED code snippet showing the fix. Must be a drop-in
|
|
378
|
+
replacement for \`beforeCode\`.
|
|
379
|
+
- \`affectedTests\` — list of test names that exercise this code path and would
|
|
380
|
+
benefit from the fix.
|
|
381
|
+
- \`impactMs\` — the current measured cost (e.g. selfTime of the hot function).`;
|
|
222
382
|
|
|
223
383
|
// src/schema.ts
|
|
224
384
|
import { z } from "zod";
|
|
@@ -256,11 +416,18 @@ var init_schema = __esm(() => {
|
|
|
256
416
|
category: z.string().describe(`Category of the performance issue. Use one of: ${ALL_CATEGORIES.join(", ")}`),
|
|
257
417
|
resourceUrl: z.string().optional().describe("URL of the resource involved"),
|
|
258
418
|
workspacePath: z.string().optional().describe("Path in the VFS workspace"),
|
|
259
|
-
impactMs: z.number().optional().describe("
|
|
419
|
+
impactMs: z.number().optional().describe("Estimated current cost in ms (e.g. selfTime of the hot function)"),
|
|
420
|
+
estimatedSavingsMs: z.number().optional().describe("Estimated time savings in ms if the fix is applied. Computed as impactMs × fraction eliminated by the fix."),
|
|
421
|
+
confidence: z.enum(["high", "medium", "low"]).optional().describe("How confident you are in this finding. high = verified in source code, medium = strong signal but partial verification, low = inferred from data patterns"),
|
|
260
422
|
retainedSize: z.number().optional().describe("Retained heap size in bytes"),
|
|
261
423
|
retainerPath: z.array(z.string()).optional().describe("Object retention path in the heap"),
|
|
424
|
+
sourceFile: z.string().optional().describe("Primary source file where the issue occurs (workspace path or original path)"),
|
|
425
|
+
lineNumber: z.number().optional().describe("Line number in the source file where the issue occurs (1-based)"),
|
|
262
426
|
suggestedFix: z.string().describe("Code snippet or guidance to fix the issue"),
|
|
427
|
+
beforeCode: z.string().optional().describe("The current problematic code snippet from the source file"),
|
|
428
|
+
afterCode: z.string().optional().describe("The improved code snippet that fixes the issue"),
|
|
263
429
|
testFile: z.string().optional().describe("Test file path (for test performance findings)"),
|
|
430
|
+
affectedTests: z.array(z.string()).optional().describe("Test names that would benefit from this fix (for test performance findings)"),
|
|
264
431
|
hotFunction: z.object({
|
|
265
432
|
name: z.string(),
|
|
266
433
|
scriptUrl: z.string(),
|
|
@@ -362,32 +529,46 @@ async function invokeWithTodoStreaming(agent, userMessage, spinner) {
|
|
|
362
529
|
}
|
|
363
530
|
return lastValues;
|
|
364
531
|
}
|
|
365
|
-
|
|
532
|
+
function buildPageLoadUserMessage(ctx) {
|
|
533
|
+
const { url, heapSummary, traceResult } = ctx;
|
|
534
|
+
const m = traceResult.metrics;
|
|
535
|
+
const reqCount = traceResult.networkRequests.length;
|
|
536
|
+
const renderBlocking = traceResult.networkRequests.filter((r) => r.isRenderBlocking).length;
|
|
537
|
+
const totalTransfer = traceResult.networkRequests.reduce((s, r) => s + r.encodedSize, 0);
|
|
538
|
+
const hasRuntime = !!traceResult.runtimeTrace;
|
|
539
|
+
const lines = [
|
|
540
|
+
"Analyze the frontend performance data in this workspace.",
|
|
541
|
+
"",
|
|
542
|
+
`URL: ${url}`,
|
|
543
|
+
`Page load: ${Math.round(m.loadComplete)}ms | FCP: ${Math.round(m.firstContentfulPaint)}ms | LCP: ${Math.round(m.largestContentfulPaint)}ms | TBT: ${Math.round(m.totalBlockingTime)}ms`,
|
|
544
|
+
`Heap: ${formatBytes(heapSummary.metadata.totalSize)} total, ${heapSummary.metadata.nodeCount.toLocaleString()} nodes, ${heapSummary.detachedNodes.count} detached DOM nodes`,
|
|
545
|
+
`Network: ${reqCount} requests, ${formatBytes(totalTransfer)} transferred, ${renderBlocking} render-blocking`,
|
|
546
|
+
`Long tasks: ${m.longTasks.length}`
|
|
547
|
+
];
|
|
548
|
+
if (hasRuntime) {
|
|
549
|
+
const rt = traceResult.runtimeTrace;
|
|
550
|
+
lines.push(`Runtime trace: ${rt.blockingFunctions.length} blocking functions, ${rt.gcEvents.length} GC events (${Math.round(rt.gcEvents.reduce((s, e) => s + e.duration, 0))}ms total)`);
|
|
551
|
+
}
|
|
552
|
+
lines.push("", "Available data:", "- /heap/summary.json — parsed heap snapshot", "- /trace/summary.json — page load metrics", "- /trace/network-waterfall.json — request timing and sizes", "- /trace/asset-manifest.json — index of stored assets");
|
|
553
|
+
if (hasRuntime) {
|
|
554
|
+
lines.push("- /trace/runtime/summary.json — runtime trace overview", "- /trace/runtime/blocking-functions.json — main thread blocking functions", "- /trace/runtime/event-listeners.json — listener add/remove counts", "- /trace/runtime/frame-breakdown.json — scripting vs layout vs paint vs GC", "- /trace/runtime/raw-events.json — full Chrome trace events");
|
|
555
|
+
}
|
|
556
|
+
lines.push("- /scripts/ — JavaScript source files", "- /styles/ — CSS source files", "- /html/document.html — page markup", "", "Explore the workspace, read source files to verify root causes, and provide code-level fixes.");
|
|
557
|
+
return lines.join(`
|
|
558
|
+
`);
|
|
559
|
+
}
|
|
560
|
+
async function analyze(model, backend, spinner, context) {
|
|
366
561
|
const agent = createDeepAgent({
|
|
367
562
|
model,
|
|
368
563
|
systemPrompt: SYSTEM_PROMPT,
|
|
369
564
|
backend,
|
|
370
565
|
responseFormat: providerStrategy(FindingsSchema)
|
|
371
566
|
});
|
|
372
|
-
const userMessage = [
|
|
567
|
+
const userMessage = context ? buildPageLoadUserMessage(context) : [
|
|
373
568
|
"Analyze the frontend performance data in this workspace.",
|
|
374
569
|
"",
|
|
375
|
-
"The workspace contains heap snapshot data, page-load trace data, and Chrome runtime trace data.",
|
|
376
|
-
"",
|
|
377
570
|
"Start by reading /heap/summary.json, /trace/summary.json, and /trace/runtime/summary.json",
|
|
378
|
-
"to understand the overall picture
|
|
379
|
-
"",
|
|
380
|
-
"- /trace/network-waterfall.json for request timing",
|
|
381
|
-
"- /trace/runtime/blocking-functions.json for function-level main thread blocking",
|
|
382
|
-
"- /trace/runtime/event-listeners.json for listener add/remove imbalances",
|
|
383
|
-
"- /trace/runtime/frame-breakdown.json for frame breakdown (scripting vs layout vs paint vs GC)",
|
|
384
|
-
"- /scripts/ for the actual JavaScript source code",
|
|
385
|
-
"- /styles/ for CSS source",
|
|
386
|
-
"- /html/document.html for the page markup",
|
|
387
|
-
"",
|
|
388
|
-
"Look for memory issues (from the heap data), page-load issues (from the network trace),",
|
|
389
|
-
"and runtime issues (from the Chrome trace — blocking functions, listener leaks, GC pressure).",
|
|
390
|
-
"When you find a problem, read the actual source file to provide a specific, code-level fix."
|
|
571
|
+
"to understand the overall picture, then explore source files to verify root causes."
|
|
391
572
|
].join(`
|
|
392
573
|
`);
|
|
393
574
|
const result = await invokeWithTodoStreaming(agent, userMessage, spinner);
|
|
@@ -397,36 +578,44 @@ async function analyze(model, backend, spinner) {
|
|
|
397
578
|
}
|
|
398
579
|
return findings;
|
|
399
580
|
}
|
|
400
|
-
|
|
581
|
+
function buildVitestUserMessage(ctx) {
|
|
582
|
+
const { metrics, hasHeapProfiles, hasListenerTracking } = ctx;
|
|
583
|
+
const lines = [
|
|
584
|
+
"Analyze the performance of the APPLICATION CODE being tested in this Vitest workspace.",
|
|
585
|
+
"",
|
|
586
|
+
`Test suite: ${metrics.suite.totalTests} tests, total duration ${metrics.suite.totalDuration}ms`,
|
|
587
|
+
`CPU breakdown: application ${metrics.cpu.applicationPercent}%, dependencies ${metrics.cpu.dependencyPercent}%, GC ${metrics.cpu.gcPercentage}%, idle ${metrics.cpu.idlePercentage}%`,
|
|
588
|
+
`Slowest file: ${metrics.suite.slowestFile} (${metrics.suite.slowestFileDuration}ms)`,
|
|
589
|
+
`Slowest test: ${metrics.suite.slowestTestName} (${metrics.suite.slowestTestDuration}ms)`,
|
|
590
|
+
"",
|
|
591
|
+
"Available data:",
|
|
592
|
+
"- /hot-functions/application.json — application-level CPU hotspots",
|
|
593
|
+
"- /scripts/application.json — per-file CPU time for application code",
|
|
594
|
+
"- /hot-functions/dependencies.json — dependency CPU hotspots",
|
|
595
|
+
"- /scripts/dependencies.json — per-file CPU time for dependencies"
|
|
596
|
+
];
|
|
597
|
+
if (hasListenerTracking) {
|
|
598
|
+
lines.push("- /listener-tracking.json — event listener add/remove patterns and exceedances");
|
|
599
|
+
}
|
|
600
|
+
if (hasHeapProfiles) {
|
|
601
|
+
lines.push("- /heap-profiles/index.json — heap profile manifest", "- /heap-profiles/<file>.json — per-file allocation hotspots");
|
|
602
|
+
}
|
|
603
|
+
lines.push("- /summary.json — overall test run summary", "- /timing/overview.json — per-file test durations", "- /timing/slow-tests.json — tests exceeding the slow threshold", "- /profiles/ — full CPU profile summaries with call trees", "- /metrics/current.json — pre-computed aggregate metrics", "- /src/ and /tests/ — source files", "", "Focus findings on the APPLICATION code — what can the developer change in their own", "codebase to improve performance? Read source files to verify root causes before suggesting fixes.");
|
|
604
|
+
return lines.join(`
|
|
605
|
+
`);
|
|
606
|
+
}
|
|
607
|
+
async function analyzeTestPerformance(model, backend, spinner, context) {
|
|
401
608
|
const agent = createDeepAgent({
|
|
402
609
|
model,
|
|
403
610
|
systemPrompt: VITEST_SYSTEM_PROMPT,
|
|
404
611
|
backend,
|
|
405
612
|
responseFormat: providerStrategy(FindingsSchema)
|
|
406
613
|
});
|
|
407
|
-
const userMessage = [
|
|
614
|
+
const userMessage = context ? buildVitestUserMessage(context) : [
|
|
408
615
|
"Analyze the performance of the APPLICATION CODE being tested in this Vitest workspace.",
|
|
409
616
|
"",
|
|
410
|
-
"
|
|
411
|
-
"
|
|
412
|
-
"2. Read /scripts/application.json — per-file CPU time for application source files",
|
|
413
|
-
"3. Read /hot-functions/dependencies.json — expensive dependency calls",
|
|
414
|
-
"4. If present, read /heap-profiles/index.json and /heap-profiles/<file>.json for allocation hotspots",
|
|
415
|
-
"5. If present, read /listener-tracking.json — event listener add/remove patterns",
|
|
416
|
-
" from worker processes. Look for exceedances (too many listeners on a single target)",
|
|
417
|
-
" and add/remove imbalances (listeners registered but never cleaned up).",
|
|
418
|
-
"6. Read /summary.json and /timing/overview.json for the big picture",
|
|
419
|
-
"7. Read CPU profiles in /profiles/ for detailed call trees",
|
|
420
|
-
"8. Read source files in /src/ and /tests/ to understand root causes and propose code-level fixes",
|
|
421
|
-
"",
|
|
422
|
-
"Focus findings on the APPLICATION code — what can the developer change in their own codebase",
|
|
423
|
-
"to improve performance? Dependency bottlenecks are worth reporting if the developer can",
|
|
424
|
-
"reduce how they call the dependency or choose an alternative.",
|
|
425
|
-
"",
|
|
426
|
-
"If /listener-tracking.json is present, analyze exceedances and imbalances.",
|
|
427
|
-
"For listener exceedances (e.g. AbortSignal with 15 abort listeners when max is 10),",
|
|
428
|
-
"use the stack trace to identify the code adding listeners and suggest proper cleanup",
|
|
429
|
-
"(e.g. AbortController, removeEventListener, { once: true })."
|
|
617
|
+
"Start with /hot-functions/application.json, then explore source files to verify",
|
|
618
|
+
"root causes and provide code-level fixes."
|
|
430
619
|
].join(`
|
|
431
620
|
`);
|
|
432
621
|
const result = await invokeWithTodoStreaming(agent, userMessage, spinner);
|
|
@@ -1898,16 +2087,40 @@ function generateMarkdown(options) {
|
|
|
1898
2087
|
sections.push(`## ${emoji} ${f.title}`);
|
|
1899
2088
|
sections.push("");
|
|
1900
2089
|
const context = [`**${categoryLabel}**`];
|
|
2090
|
+
if (f.confidence)
|
|
2091
|
+
context.push(`confidence: ${f.confidence}`);
|
|
1901
2092
|
if (f.impactMs != null)
|
|
1902
2093
|
context.push(`${f.impactMs.toFixed(0)}ms impact`);
|
|
2094
|
+
if (f.estimatedSavingsMs != null)
|
|
2095
|
+
context.push(`~${f.estimatedSavingsMs.toFixed(0)}ms savings`);
|
|
1903
2096
|
if (f.retainedSize != null)
|
|
1904
2097
|
context.push(`${formatBytes2(f.retainedSize)} retained`);
|
|
2098
|
+
if (f.sourceFile)
|
|
2099
|
+
context.push(`\`${f.sourceFile}${f.lineNumber != null ? `:${f.lineNumber}` : ""}\``);
|
|
1905
2100
|
if (f.resourceUrl)
|
|
1906
2101
|
context.push(`\`${f.resourceUrl}\``);
|
|
1907
2102
|
sections.push(context.join(" · "));
|
|
1908
2103
|
sections.push("");
|
|
1909
2104
|
sections.push(f.description);
|
|
1910
2105
|
sections.push("");
|
|
2106
|
+
if (f.beforeCode || f.afterCode) {
|
|
2107
|
+
if (f.beforeCode) {
|
|
2108
|
+
sections.push(`### Before`);
|
|
2109
|
+
sections.push("");
|
|
2110
|
+
sections.push("```js");
|
|
2111
|
+
sections.push(f.beforeCode);
|
|
2112
|
+
sections.push("```");
|
|
2113
|
+
sections.push("");
|
|
2114
|
+
}
|
|
2115
|
+
if (f.afterCode) {
|
|
2116
|
+
sections.push(`### After`);
|
|
2117
|
+
sections.push("");
|
|
2118
|
+
sections.push("```js");
|
|
2119
|
+
sections.push(f.afterCode);
|
|
2120
|
+
sections.push("```");
|
|
2121
|
+
sections.push("");
|
|
2122
|
+
}
|
|
2123
|
+
}
|
|
1911
2124
|
if (f.suggestedFix) {
|
|
1912
2125
|
sections.push(`### How to fix`);
|
|
1913
2126
|
sections.push("");
|
|
@@ -2043,19 +2256,47 @@ function generateTestMarkdown(options) {
|
|
|
2043
2256
|
sections.push(`## ${emoji} ${f.title}`);
|
|
2044
2257
|
sections.push("");
|
|
2045
2258
|
const context = [`**${categoryLabel}**`];
|
|
2259
|
+
if (f.confidence)
|
|
2260
|
+
context.push(`confidence: ${f.confidence}`);
|
|
2046
2261
|
if (f.impactMs != null)
|
|
2047
2262
|
context.push(`${f.impactMs.toFixed(0)}ms impact`);
|
|
2263
|
+
if (f.estimatedSavingsMs != null)
|
|
2264
|
+
context.push(`~${f.estimatedSavingsMs.toFixed(0)}ms savings`);
|
|
2048
2265
|
if (f.testFile)
|
|
2049
2266
|
context.push(`\`${f.testFile}\``);
|
|
2050
2267
|
if (f.hotFunction) {
|
|
2051
2268
|
context.push(`\`${f.hotFunction.name}\` (${f.hotFunction.selfTime.toFixed(0)}ms, ${f.hotFunction.selfPercent.toFixed(1)}%)`);
|
|
2052
2269
|
}
|
|
2270
|
+
if (f.sourceFile)
|
|
2271
|
+
context.push(`\`${f.sourceFile}${f.lineNumber != null ? `:${f.lineNumber}` : ""}\``);
|
|
2053
2272
|
if (f.resourceUrl)
|
|
2054
2273
|
context.push(`\`${f.resourceUrl}\``);
|
|
2055
2274
|
sections.push(context.join(" · "));
|
|
2056
2275
|
sections.push("");
|
|
2276
|
+
if (f.affectedTests && f.affectedTests.length > 0) {
|
|
2277
|
+
sections.push(`**Affected tests:** ${f.affectedTests.map((t) => `\`${t}\``).join(", ")}`);
|
|
2278
|
+
sections.push("");
|
|
2279
|
+
}
|
|
2057
2280
|
sections.push(f.description);
|
|
2058
2281
|
sections.push("");
|
|
2282
|
+
if (f.beforeCode || f.afterCode) {
|
|
2283
|
+
if (f.beforeCode) {
|
|
2284
|
+
sections.push(`### Before`);
|
|
2285
|
+
sections.push("");
|
|
2286
|
+
sections.push("```ts");
|
|
2287
|
+
sections.push(f.beforeCode);
|
|
2288
|
+
sections.push("```");
|
|
2289
|
+
sections.push("");
|
|
2290
|
+
}
|
|
2291
|
+
if (f.afterCode) {
|
|
2292
|
+
sections.push(`### After`);
|
|
2293
|
+
sections.push("");
|
|
2294
|
+
sections.push("```ts");
|
|
2295
|
+
sections.push(f.afterCode);
|
|
2296
|
+
sections.push("```");
|
|
2297
|
+
sections.push("");
|
|
2298
|
+
}
|
|
2299
|
+
}
|
|
2059
2300
|
if (f.suggestedFix) {
|
|
2060
2301
|
sections.push(`### How to fix`);
|
|
2061
2302
|
sections.push("");
|
|
@@ -2207,7 +2448,11 @@ async function main() {
|
|
|
2207
2448
|
const agentSpinner = createSpinner("Analyzing...");
|
|
2208
2449
|
let findings;
|
|
2209
2450
|
try {
|
|
2210
|
-
findings = await analyze(model, workspace.backend, agentSpinner
|
|
2451
|
+
findings = await analyze(model, workspace.backend, agentSpinner, {
|
|
2452
|
+
url,
|
|
2453
|
+
heapSummary,
|
|
2454
|
+
traceResult: captureResult.trace
|
|
2455
|
+
});
|
|
2211
2456
|
agentSpinner.succeed(`Analysis complete — ${findings.length} findings`);
|
|
2212
2457
|
} catch (err) {
|
|
2213
2458
|
agentSpinner.fail(`Analysis failed: ${err instanceof Error ? err.message : "Unknown error"}`);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"report.d.ts","sourceRoot":"","sources":["../../src/output/report.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,OAAO,EAAE,WAAW,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AACrE,OAAO,KAAK,EAAE,cAAc,EAAE,iBAAiB,EAAE,MAAM,oBAAoB,CAAC;AAC5E,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,sBAAsB,CAAC;AAoC/D,MAAM,WAAW,aAAa;IAC5B,GAAG,EAAE,MAAM,CAAC;IACZ,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,OAAO,EAAE,CAAC;IACpB,WAAW,EAAE,WAAW,CAAC;IACzB,KAAK,EAAE,WAAW,CAAC;CACpB;AAED,MAAM,WAAW,iBAAiB;IAChC,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,OAAO,EAAE,CAAC;IACpB,UAAU,EAAE,cAAc,EAAE,CAAC;IAC7B,QAAQ,EAAE,iBAAiB,EAAE,CAAC;IAC9B,OAAO,CAAC,EAAE,kBAAkB,CAAC;CAC9B;AAED;;;GAGG;AACH,wBAAgB,WAAW,CAAC,UAAU,EAAE,MAAM,EAAE,OAAO,EAAE,aAAa,GAAG,MAAM,CAI9E;AAED;;;;;;GAMG;AACH,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,aAAa,GAAG,MAAM,
|
|
1
|
+
{"version":3,"file":"report.d.ts","sourceRoot":"","sources":["../../src/output/report.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,OAAO,EAAE,WAAW,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AACrE,OAAO,KAAK,EAAE,cAAc,EAAE,iBAAiB,EAAE,MAAM,oBAAoB,CAAC;AAC5E,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,sBAAsB,CAAC;AAoC/D,MAAM,WAAW,aAAa;IAC5B,GAAG,EAAE,MAAM,CAAC;IACZ,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,OAAO,EAAE,CAAC;IACpB,WAAW,EAAE,WAAW,CAAC;IACzB,KAAK,EAAE,WAAW,CAAC;CACpB;AAED,MAAM,WAAW,iBAAiB;IAChC,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,OAAO,EAAE,CAAC;IACpB,UAAU,EAAE,cAAc,EAAE,CAAC;IAC7B,QAAQ,EAAE,iBAAiB,EAAE,CAAC;IAC9B,OAAO,CAAC,EAAE,kBAAkB,CAAC;CAC9B;AAED;;;GAGG;AACH,wBAAgB,WAAW,CAAC,UAAU,EAAE,MAAM,EAAE,OAAO,EAAE,aAAa,GAAG,MAAM,CAI9E;AAED;;;;;;GAMG;AACH,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,aAAa,GAAG,MAAM,CAwI/D;AAID;;;GAGG;AACH,wBAAgB,eAAe,CAAC,UAAU,EAAE,MAAM,EAAE,OAAO,EAAE,iBAAiB,GAAG,MAAM,CAItF;AAED;;GAEG;AACH,wBAAgB,oBAAoB,CAAC,OAAO,EAAE,iBAAiB,GAAG,MAAM,CAoPvE"}
|
package/dist/schema.d.ts
CHANGED
|
@@ -23,10 +23,21 @@ export declare const FindingSchema: z.ZodObject<{
|
|
|
23
23
|
resourceUrl: z.ZodOptional<z.ZodString>;
|
|
24
24
|
workspacePath: z.ZodOptional<z.ZodString>;
|
|
25
25
|
impactMs: z.ZodOptional<z.ZodNumber>;
|
|
26
|
+
estimatedSavingsMs: z.ZodOptional<z.ZodNumber>;
|
|
27
|
+
confidence: z.ZodOptional<z.ZodEnum<{
|
|
28
|
+
low: "low";
|
|
29
|
+
medium: "medium";
|
|
30
|
+
high: "high";
|
|
31
|
+
}>>;
|
|
26
32
|
retainedSize: z.ZodOptional<z.ZodNumber>;
|
|
27
33
|
retainerPath: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
34
|
+
sourceFile: z.ZodOptional<z.ZodString>;
|
|
35
|
+
lineNumber: z.ZodOptional<z.ZodNumber>;
|
|
28
36
|
suggestedFix: z.ZodString;
|
|
37
|
+
beforeCode: z.ZodOptional<z.ZodString>;
|
|
38
|
+
afterCode: z.ZodOptional<z.ZodString>;
|
|
29
39
|
testFile: z.ZodOptional<z.ZodString>;
|
|
40
|
+
affectedTests: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
30
41
|
hotFunction: z.ZodOptional<z.ZodObject<{
|
|
31
42
|
name: z.ZodString;
|
|
32
43
|
scriptUrl: z.ZodString;
|
|
@@ -48,10 +59,21 @@ export declare const FindingsSchema: z.ZodObject<{
|
|
|
48
59
|
resourceUrl: z.ZodOptional<z.ZodString>;
|
|
49
60
|
workspacePath: z.ZodOptional<z.ZodString>;
|
|
50
61
|
impactMs: z.ZodOptional<z.ZodNumber>;
|
|
62
|
+
estimatedSavingsMs: z.ZodOptional<z.ZodNumber>;
|
|
63
|
+
confidence: z.ZodOptional<z.ZodEnum<{
|
|
64
|
+
low: "low";
|
|
65
|
+
medium: "medium";
|
|
66
|
+
high: "high";
|
|
67
|
+
}>>;
|
|
51
68
|
retainedSize: z.ZodOptional<z.ZodNumber>;
|
|
52
69
|
retainerPath: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
70
|
+
sourceFile: z.ZodOptional<z.ZodString>;
|
|
71
|
+
lineNumber: z.ZodOptional<z.ZodNumber>;
|
|
53
72
|
suggestedFix: z.ZodString;
|
|
73
|
+
beforeCode: z.ZodOptional<z.ZodString>;
|
|
74
|
+
afterCode: z.ZodOptional<z.ZodString>;
|
|
54
75
|
testFile: z.ZodOptional<z.ZodString>;
|
|
76
|
+
affectedTests: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
55
77
|
hotFunction: z.ZodOptional<z.ZodObject<{
|
|
56
78
|
name: z.ZodString;
|
|
57
79
|
scriptUrl: z.ZodString;
|
package/dist/schema.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"schema.d.ts","sourceRoot":"","sources":["../src/schema.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB;;;;;;;;;;GAUG;AACH,eAAO,MAAM,cAAc,iaA2BjB,CAAC;AAEX,eAAO,MAAM,aAAa
|
|
1
|
+
{"version":3,"file":"schema.d.ts","sourceRoot":"","sources":["../src/schema.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB;;;;;;;;;;GAUG;AACH,eAAO,MAAM,cAAc,iaA2BjB,CAAC;AAEX,eAAO,MAAM,aAAa;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBAwDxB,CAAC;AAEH,eAAO,MAAM,cAAc;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBAEzB,CAAC"}
|