zeitzeuge 0.3.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/LICENSE +21 -0
- package/README.md +212 -0
- package/dist/analysis/agent.d.ts +19 -0
- package/dist/analysis/agent.d.ts.map +1 -0
- package/dist/analysis/parser.d.ts +3 -0
- package/dist/analysis/parser.d.ts.map +1 -0
- package/dist/analysis/prompts.d.ts +2 -0
- package/dist/analysis/prompts.d.ts.map +1 -0
- package/dist/browser/capture.d.ts +14 -0
- package/dist/browser/capture.d.ts.map +1 -0
- package/dist/browser/launch.d.ts +6 -0
- package/dist/browser/launch.d.ts.map +1 -0
- package/dist/browser/runtime-trace.d.ts +52 -0
- package/dist/browser/runtime-trace.d.ts.map +1 -0
- package/dist/browser/trace.d.ts +8 -0
- package/dist/browser/trace.d.ts.map +1 -0
- package/dist/cli.d.ts +3 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +1695 -0
- package/dist/models/init.d.ts +3 -0
- package/dist/models/init.d.ts.map +1 -0
- package/dist/output/report.d.ts +38 -0
- package/dist/output/report.d.ts.map +1 -0
- package/dist/output/terminal.d.ts +31 -0
- package/dist/output/terminal.d.ts.map +1 -0
- package/dist/sandbox/workspace.d.ts +33 -0
- package/dist/sandbox/workspace.d.ts.map +1 -0
- package/dist/schema.d.ts +64 -0
- package/dist/schema.d.ts.map +1 -0
- package/dist/types.d.ts +245 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/vitest/classify.d.ts +19 -0
- package/dist/vitest/classify.d.ts.map +1 -0
- package/dist/vitest/heap-profile-parser.d.ts +12 -0
- package/dist/vitest/heap-profile-parser.d.ts.map +1 -0
- package/dist/vitest/index.d.ts +17 -0
- package/dist/vitest/index.d.ts.map +1 -0
- package/dist/vitest/index.js +1616 -0
- package/dist/vitest/plugin.d.ts +17 -0
- package/dist/vitest/plugin.d.ts.map +1 -0
- package/dist/vitest/profile-parser.d.ts +13 -0
- package/dist/vitest/profile-parser.d.ts.map +1 -0
- package/dist/vitest/prompts.d.ts +10 -0
- package/dist/vitest/prompts.d.ts.map +1 -0
- package/dist/vitest/reporter.d.ts +79 -0
- package/dist/vitest/reporter.d.ts.map +1 -0
- package/dist/vitest/types.d.ts +231 -0
- package/dist/vitest/types.d.ts.map +1 -0
- package/dist/vitest/workspace.d.ts +25 -0
- package/dist/vitest/workspace.d.ts.map +1 -0
- package/package.json +76 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"init.d.ts","sourceRoot":"","sources":["../../src/models/init.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,6CAA6C,CAAC;AAEjF,wBAAgB,SAAS,IAAI,aAAa,CAyBzC"}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import type { Finding, HeapSummary, TraceResult } from '../types.js';
|
|
2
|
+
import type { TestFileTiming, CorrelatedProfile } from '../vitest/types.js';
|
|
3
|
+
export interface ReportOptions {
|
|
4
|
+
url: string;
|
|
5
|
+
version: string;
|
|
6
|
+
findings: Finding[];
|
|
7
|
+
heapSummary: HeapSummary;
|
|
8
|
+
trace: TraceResult;
|
|
9
|
+
}
|
|
10
|
+
export interface TestReportOptions {
|
|
11
|
+
version: string;
|
|
12
|
+
findings: Finding[];
|
|
13
|
+
testTiming: TestFileTiming[];
|
|
14
|
+
profiles: CorrelatedProfile[];
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* Generate a Markdown performance report and write it to disk.
|
|
18
|
+
* Returns the absolute path of the written file.
|
|
19
|
+
*/
|
|
20
|
+
export declare function writeReport(outputPath: string, options: ReportOptions): string;
|
|
21
|
+
/**
|
|
22
|
+
* Generate the full Markdown report string.
|
|
23
|
+
*
|
|
24
|
+
* The report is focused on actionable findings — what's wrong and how
|
|
25
|
+
* to fix it. Raw metrics are kept to a one-line health snapshot so
|
|
26
|
+
* the reader can jump straight to the issues that matter.
|
|
27
|
+
*/
|
|
28
|
+
export declare function generateMarkdown(options: ReportOptions): string;
|
|
29
|
+
/**
|
|
30
|
+
* Generate a Markdown report for Vitest test performance and write it to disk.
|
|
31
|
+
* Returns the absolute path of the written file.
|
|
32
|
+
*/
|
|
33
|
+
export declare function writeTestReport(outputPath: string, options: TestReportOptions): string;
|
|
34
|
+
/**
|
|
35
|
+
* Generate the full Markdown report string for Vitest test performance.
|
|
36
|
+
*/
|
|
37
|
+
export declare function generateTestMarkdown(options: TestReportOptions): string;
|
|
38
|
+
//# sourceMappingURL=report.d.ts.map
|
|
@@ -0,0 +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;AAmC5E,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;CAC/B;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,CA+G/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,CAkHvE"}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { type Ora } from 'ora';
|
|
2
|
+
import type { Finding, HeapSummary, TraceResult } from '../types.js';
|
|
3
|
+
/**
|
|
4
|
+
* Print the zeitzeuge header with version and target URL.
|
|
5
|
+
*/
|
|
6
|
+
export declare function printHeader(url: string, version: string): void;
|
|
7
|
+
/**
|
|
8
|
+
* Create and start a spinner with the given text.
|
|
9
|
+
*/
|
|
10
|
+
export declare function createSpinner(text: string): Ora;
|
|
11
|
+
/**
|
|
12
|
+
* Print all findings to the terminal with formatting.
|
|
13
|
+
*/
|
|
14
|
+
export declare function printFindings(findings: Finding[]): void;
|
|
15
|
+
/**
|
|
16
|
+
* Print capture info summary (heap + trace).
|
|
17
|
+
*/
|
|
18
|
+
export declare function printCaptureInfo(heapSummary: HeapSummary, trace: TraceResult): void;
|
|
19
|
+
/**
|
|
20
|
+
* Print snapshot metadata summary (legacy, kept for compatibility).
|
|
21
|
+
*/
|
|
22
|
+
export declare function printSnapshotInfo(summary: HeapSummary): void;
|
|
23
|
+
/**
|
|
24
|
+
* Print an error message to stderr.
|
|
25
|
+
*/
|
|
26
|
+
export declare function printError(err: unknown): void;
|
|
27
|
+
/**
|
|
28
|
+
* Format bytes into a human-readable string.
|
|
29
|
+
*/
|
|
30
|
+
export declare function formatBytes(bytes: number): string;
|
|
31
|
+
//# sourceMappingURL=terminal.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"terminal.d.ts","sourceRoot":"","sources":["../../src/output/terminal.ts"],"names":[],"mappings":"AACA,OAAY,EAAE,KAAK,GAAG,EAAE,MAAM,KAAK,CAAC;AACpC,OAAO,KAAK,EAAE,OAAO,EAAE,WAAW,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAkCrE;;GAEG;AACH,wBAAgB,WAAW,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,IAAI,CAU9D;AAED;;GAEG;AACH,wBAAgB,aAAa,CAAC,IAAI,EAAE,MAAM,GAAG,GAAG,CAE/C;AAED;;GAEG;AACH,wBAAgB,aAAa,CAAC,QAAQ,EAAE,OAAO,EAAE,GAAG,IAAI,CAoEvD;AAED;;GAEG;AACH,wBAAgB,gBAAgB,CAAC,WAAW,EAAE,WAAW,EAAE,KAAK,EAAE,WAAW,GAAG,IAAI,CASnF;AAED;;GAEG;AACH,wBAAgB,iBAAiB,CAAC,OAAO,EAAE,WAAW,GAAG,IAAI,CAQ5D;AAED;;GAEG;AACH,wBAAgB,UAAU,CAAC,GAAG,EAAE,OAAO,GAAG,IAAI,CAG7C;AAED;;GAEG;AACH,wBAAgB,WAAW,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAIjD"}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { type BackendProtocol } from 'deepagents';
|
|
2
|
+
import type { HeapSummary, TraceResult, NetworkRequest } from '../types.js';
|
|
3
|
+
export interface WorkspaceOptions {
|
|
4
|
+
heapSummary: HeapSummary;
|
|
5
|
+
traceResult: TraceResult;
|
|
6
|
+
url: string;
|
|
7
|
+
/** Maximum total size of stored asset content in bytes. Default: 10 MB */
|
|
8
|
+
maxAssetSize?: number;
|
|
9
|
+
}
|
|
10
|
+
export interface WorkspaceResult {
|
|
11
|
+
/** Backend for use with createDeepAgent */
|
|
12
|
+
backend: BackendProtocol;
|
|
13
|
+
/** Clean up the temporary directory when done */
|
|
14
|
+
cleanup: () => void;
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* Create a workspace populated with heap snapshot data, trace data,
|
|
18
|
+
* and actual network asset content.
|
|
19
|
+
*
|
|
20
|
+
* Uses FilesystemBackend with virtualMode so the agent's absolute paths
|
|
21
|
+
* (e.g. /heap/summary.json) map to files inside the temp directory.
|
|
22
|
+
* This avoids the VfsSandbox shell-command path issues where absolute
|
|
23
|
+
* paths resolve against the real filesystem instead of the workspace.
|
|
24
|
+
*/
|
|
25
|
+
export declare function createWorkspace(options: WorkspaceOptions): Promise<WorkspaceResult>;
|
|
26
|
+
/**
|
|
27
|
+
* Map a network request to its workspace path based on resource type.
|
|
28
|
+
*
|
|
29
|
+
* Returns virtual absolute paths (e.g. /scripts/app.js) that the
|
|
30
|
+
* FilesystemBackend with virtualMode maps to the temp directory.
|
|
31
|
+
*/
|
|
32
|
+
export declare function getAssetPath(req: NetworkRequest): string;
|
|
33
|
+
//# sourceMappingURL=workspace.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"workspace.d.ts","sourceRoot":"","sources":["../../src/sandbox/workspace.ts"],"names":[],"mappings":"AAAA,OAAO,EAAqB,KAAK,eAAe,EAAE,MAAM,YAAY,CAAC;AAIrE,OAAO,KAAK,EAAE,WAAW,EAAE,WAAW,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAE5E,MAAM,WAAW,gBAAgB;IAC/B,WAAW,EAAE,WAAW,CAAC;IACzB,WAAW,EAAE,WAAW,CAAC;IACzB,GAAG,EAAE,MAAM,CAAC;IACZ,0EAA0E;IAC1E,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB;AAED,MAAM,WAAW,eAAe;IAC9B,2CAA2C;IAC3C,OAAO,EAAE,eAAe,CAAC;IACzB,iDAAiD;IACjD,OAAO,EAAE,MAAM,IAAI,CAAC;CACrB;AAED;;;;;;;;GAQG;AACH,wBAAsB,eAAe,CAAC,OAAO,EAAE,gBAAgB,GAAG,OAAO,CAAC,eAAe,CAAC,CAkKzF;AAED;;;;;GAKG;AACH,wBAAgB,YAAY,CAAC,GAAG,EAAE,cAAc,GAAG,MAAM,CAqBxD"}
|
package/dist/schema.d.ts
ADDED
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
/**
|
|
3
|
+
* All finding categories — shared between page-load and test-performance analysis.
|
|
4
|
+
*
|
|
5
|
+
* NOTE: We intentionally use `z.string()` instead of `z.enum()` in the Zod
|
|
6
|
+
* schema below. When `z.enum()` is used with `providerStrategy()`, certain
|
|
7
|
+
* LLM providers (e.g. Anthropic) may emit the structured response in a single
|
|
8
|
+
* turn without exploring the workspace first, resulting in empty findings.
|
|
9
|
+
* Using `z.string()` with a `.describe()` hint keeps the schema flexible for
|
|
10
|
+
* the API while the TypeScript `Finding` type still enforces the union at
|
|
11
|
+
* compile time.
|
|
12
|
+
*/
|
|
13
|
+
export declare const ALL_CATEGORIES: readonly ["memory-leak", "large-retained-object", "detached-dom", "render-blocking", "long-task", "unused-code", "waterfall-bottleneck", "large-asset", "frame-blocking-function", "listener-leak", "gc-pressure", "slow-test", "expensive-setup", "hot-function", "unnecessary-computation", "import-overhead", "dependency-bottleneck", "algorithm", "serialization", "allocation", "event-handling", "blocking-io", "other"];
|
|
14
|
+
export declare const FindingSchema: z.ZodObject<{
|
|
15
|
+
severity: z.ZodEnum<{
|
|
16
|
+
critical: "critical";
|
|
17
|
+
warning: "warning";
|
|
18
|
+
info: "info";
|
|
19
|
+
}>;
|
|
20
|
+
title: z.ZodString;
|
|
21
|
+
description: z.ZodString;
|
|
22
|
+
category: z.ZodString;
|
|
23
|
+
resourceUrl: z.ZodOptional<z.ZodString>;
|
|
24
|
+
workspacePath: z.ZodOptional<z.ZodString>;
|
|
25
|
+
impactMs: z.ZodOptional<z.ZodNumber>;
|
|
26
|
+
retainedSize: z.ZodOptional<z.ZodNumber>;
|
|
27
|
+
retainerPath: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
28
|
+
suggestedFix: z.ZodString;
|
|
29
|
+
testFile: z.ZodOptional<z.ZodString>;
|
|
30
|
+
hotFunction: z.ZodOptional<z.ZodObject<{
|
|
31
|
+
name: z.ZodString;
|
|
32
|
+
scriptUrl: z.ZodString;
|
|
33
|
+
lineNumber: z.ZodNumber;
|
|
34
|
+
selfTime: z.ZodNumber;
|
|
35
|
+
selfPercent: z.ZodNumber;
|
|
36
|
+
}, z.core.$strip>>;
|
|
37
|
+
}, z.core.$strip>;
|
|
38
|
+
export declare const FindingsSchema: z.ZodObject<{
|
|
39
|
+
findings: z.ZodArray<z.ZodObject<{
|
|
40
|
+
severity: z.ZodEnum<{
|
|
41
|
+
critical: "critical";
|
|
42
|
+
warning: "warning";
|
|
43
|
+
info: "info";
|
|
44
|
+
}>;
|
|
45
|
+
title: z.ZodString;
|
|
46
|
+
description: z.ZodString;
|
|
47
|
+
category: z.ZodString;
|
|
48
|
+
resourceUrl: z.ZodOptional<z.ZodString>;
|
|
49
|
+
workspacePath: z.ZodOptional<z.ZodString>;
|
|
50
|
+
impactMs: z.ZodOptional<z.ZodNumber>;
|
|
51
|
+
retainedSize: z.ZodOptional<z.ZodNumber>;
|
|
52
|
+
retainerPath: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
53
|
+
suggestedFix: z.ZodString;
|
|
54
|
+
testFile: z.ZodOptional<z.ZodString>;
|
|
55
|
+
hotFunction: z.ZodOptional<z.ZodObject<{
|
|
56
|
+
name: z.ZodString;
|
|
57
|
+
scriptUrl: z.ZodString;
|
|
58
|
+
lineNumber: z.ZodNumber;
|
|
59
|
+
selfTime: z.ZodNumber;
|
|
60
|
+
selfPercent: z.ZodNumber;
|
|
61
|
+
}, z.core.$strip>>;
|
|
62
|
+
}, z.core.$strip>>;
|
|
63
|
+
}, z.core.$strip>;
|
|
64
|
+
//# sourceMappingURL=schema.d.ts.map
|
|
@@ -0,0 +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;;;;;;;;;;;;;;;;;;;;;;;iBA0BxB,CAAC;AAEH,eAAO,MAAM,cAAc;;;;;;;;;;;;;;;;;;;;;;;;;iBAEzB,CAAC"}
|
package/dist/types.d.ts
ADDED
|
@@ -0,0 +1,245 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
import { FindingSchema } from "./schema";
|
|
3
|
+
/**
|
|
4
|
+
* Shared TypeScript types for zeitzeuge.
|
|
5
|
+
*/
|
|
6
|
+
export type Finding = z.infer<typeof FindingSchema>;
|
|
7
|
+
/** The structured summary produced by the heap snapshot parser. */
|
|
8
|
+
export interface HeapSummary {
|
|
9
|
+
metadata: {
|
|
10
|
+
url: string;
|
|
11
|
+
capturedAt: number;
|
|
12
|
+
totalSize: number;
|
|
13
|
+
nodeCount: number;
|
|
14
|
+
edgeCount: number;
|
|
15
|
+
};
|
|
16
|
+
largestObjects: LargestObject[];
|
|
17
|
+
typeStats: TypeStat[];
|
|
18
|
+
constructorStats: ConstructorStat[];
|
|
19
|
+
detachedNodes: DetachedNodeInfo;
|
|
20
|
+
closureStats: ClosureStats;
|
|
21
|
+
}
|
|
22
|
+
/** A single large object from the heap, sorted by retained size. */
|
|
23
|
+
export interface LargestObject {
|
|
24
|
+
name: string;
|
|
25
|
+
type: string;
|
|
26
|
+
selfSize: number;
|
|
27
|
+
retainedSize: number;
|
|
28
|
+
retainerPath: string[];
|
|
29
|
+
}
|
|
30
|
+
/** Aggregated statistics for a node type (e.g. "object", "closure", "string"). */
|
|
31
|
+
export interface TypeStat {
|
|
32
|
+
type: string;
|
|
33
|
+
count: number;
|
|
34
|
+
totalSize: number;
|
|
35
|
+
avgSize: number;
|
|
36
|
+
}
|
|
37
|
+
/** Aggregated statistics for a constructor (e.g. "Array", "Map", "HTMLDivElement"). */
|
|
38
|
+
export interface ConstructorStat {
|
|
39
|
+
constructor: string;
|
|
40
|
+
count: number;
|
|
41
|
+
totalSize: number;
|
|
42
|
+
avgSize: number;
|
|
43
|
+
}
|
|
44
|
+
/** Information about detached DOM nodes found in the heap. */
|
|
45
|
+
export interface DetachedNodeInfo {
|
|
46
|
+
count: number;
|
|
47
|
+
totalSize: number;
|
|
48
|
+
examples: Array<{
|
|
49
|
+
name: string;
|
|
50
|
+
retainerPath: string[];
|
|
51
|
+
}>;
|
|
52
|
+
}
|
|
53
|
+
/** Statistics about closures retaining scope variables. */
|
|
54
|
+
export interface ClosureStats {
|
|
55
|
+
count: number;
|
|
56
|
+
totalSize: number;
|
|
57
|
+
topClosures: Array<{
|
|
58
|
+
name: string;
|
|
59
|
+
contextSize: number;
|
|
60
|
+
retainerPath: string[];
|
|
61
|
+
}>;
|
|
62
|
+
}
|
|
63
|
+
/** Raw heap snapshot data as captured from CDP. */
|
|
64
|
+
export interface RawSnapshot {
|
|
65
|
+
/** The full JSON string of the V8 heap snapshot. */
|
|
66
|
+
data: string;
|
|
67
|
+
/** Timestamp when the snapshot was captured. */
|
|
68
|
+
capturedAt: number;
|
|
69
|
+
/** The URL that was loaded. */
|
|
70
|
+
url: string;
|
|
71
|
+
}
|
|
72
|
+
/** A network request captured during page load. */
|
|
73
|
+
export interface NetworkRequest {
|
|
74
|
+
requestId: string;
|
|
75
|
+
url: string;
|
|
76
|
+
method: string;
|
|
77
|
+
resourceType: string;
|
|
78
|
+
mimeType: string;
|
|
79
|
+
status: number;
|
|
80
|
+
encodedSize: number;
|
|
81
|
+
decodedSize: number;
|
|
82
|
+
/** Timing in ms relative to navigation start */
|
|
83
|
+
startTime: number;
|
|
84
|
+
endTime: number;
|
|
85
|
+
duration: number;
|
|
86
|
+
isRenderBlocking: boolean;
|
|
87
|
+
/** Actual response body (text-based resources only) */
|
|
88
|
+
responseBody: string | null;
|
|
89
|
+
priority: string;
|
|
90
|
+
initiator: string;
|
|
91
|
+
}
|
|
92
|
+
/** Page load timing metrics. */
|
|
93
|
+
export interface PageMetrics {
|
|
94
|
+
navigationStart: number;
|
|
95
|
+
domContentLoaded: number;
|
|
96
|
+
loadComplete: number;
|
|
97
|
+
firstPaint: number;
|
|
98
|
+
firstContentfulPaint: number;
|
|
99
|
+
largestContentfulPaint: number;
|
|
100
|
+
totalBlockingTime: number;
|
|
101
|
+
longTasks: LongTask[];
|
|
102
|
+
}
|
|
103
|
+
/** A long task detected during page load (> 50ms). */
|
|
104
|
+
export interface LongTask {
|
|
105
|
+
startTime: number;
|
|
106
|
+
duration: number;
|
|
107
|
+
/** Script URL if attributable */
|
|
108
|
+
scriptUrl: string | null;
|
|
109
|
+
}
|
|
110
|
+
/** Result of performance tracing during page load. */
|
|
111
|
+
export interface TraceResult {
|
|
112
|
+
networkRequests: NetworkRequest[];
|
|
113
|
+
metrics: PageMetrics;
|
|
114
|
+
/** Runtime trace summary from Chrome Tracing domain (optional for backwards compat). */
|
|
115
|
+
runtimeTrace?: RuntimeTraceSummary;
|
|
116
|
+
/** Raw Chrome trace events from the Tracing domain — for storage in the workspace. */
|
|
117
|
+
rawTraceEvents?: TraceEvent[];
|
|
118
|
+
}
|
|
119
|
+
/** A single Chrome trace event from the Tracing domain. */
|
|
120
|
+
export interface TraceEvent {
|
|
121
|
+
cat: string;
|
|
122
|
+
name: string;
|
|
123
|
+
ph: string;
|
|
124
|
+
ts: number;
|
|
125
|
+
dur?: number;
|
|
126
|
+
pid: number;
|
|
127
|
+
tid: number;
|
|
128
|
+
args?: {
|
|
129
|
+
name?: string;
|
|
130
|
+
data?: {
|
|
131
|
+
functionName?: string;
|
|
132
|
+
url?: string;
|
|
133
|
+
lineNumber?: number;
|
|
134
|
+
columnNumber?: number;
|
|
135
|
+
type?: string;
|
|
136
|
+
frame?: string;
|
|
137
|
+
stackTrace?: Array<{
|
|
138
|
+
functionName: string;
|
|
139
|
+
url: string;
|
|
140
|
+
lineNumber: number;
|
|
141
|
+
columnNumber: number;
|
|
142
|
+
}>;
|
|
143
|
+
usedHeapSizeBefore?: number;
|
|
144
|
+
usedHeapSizeAfter?: number;
|
|
145
|
+
};
|
|
146
|
+
};
|
|
147
|
+
}
|
|
148
|
+
/** A function call that blocked the main thread. */
|
|
149
|
+
export interface BlockingFunction {
|
|
150
|
+
functionName: string;
|
|
151
|
+
scriptUrl: string;
|
|
152
|
+
lineNumber: number;
|
|
153
|
+
columnNumber: number;
|
|
154
|
+
/** Duration in ms */
|
|
155
|
+
duration: number;
|
|
156
|
+
/** Timestamp in ms relative to navigation start */
|
|
157
|
+
startTime: number;
|
|
158
|
+
/** Call stack (caller chain) */
|
|
159
|
+
callStack: Array<{
|
|
160
|
+
functionName: string;
|
|
161
|
+
scriptUrl: string;
|
|
162
|
+
lineNumber: number;
|
|
163
|
+
}>;
|
|
164
|
+
/** Category of work: "scripting" | "layout" | "paint" | "gc" */
|
|
165
|
+
category: string;
|
|
166
|
+
}
|
|
167
|
+
/** Aggregated event listener data. */
|
|
168
|
+
export interface EventListenerInfo {
|
|
169
|
+
eventType: string;
|
|
170
|
+
/** Number of times addEventListener was called for this type */
|
|
171
|
+
addCount: number;
|
|
172
|
+
/** Number of times removeEventListener was called for this type */
|
|
173
|
+
removeCount: number;
|
|
174
|
+
/** Net active listeners (add - remove) */
|
|
175
|
+
activeCount: number;
|
|
176
|
+
/** Scripts that registered listeners */
|
|
177
|
+
sources: Array<{
|
|
178
|
+
scriptUrl: string;
|
|
179
|
+
lineNumber: number;
|
|
180
|
+
count: number;
|
|
181
|
+
}>;
|
|
182
|
+
}
|
|
183
|
+
/** Per-frame time breakdown. */
|
|
184
|
+
export interface FrameBreakdown {
|
|
185
|
+
totalTime: number;
|
|
186
|
+
scripting: number;
|
|
187
|
+
layout: number;
|
|
188
|
+
painting: number;
|
|
189
|
+
gc: number;
|
|
190
|
+
other: number;
|
|
191
|
+
}
|
|
192
|
+
/** GC event detail. */
|
|
193
|
+
export interface GCEvent {
|
|
194
|
+
/** Timestamp in ms relative to navigation start */
|
|
195
|
+
startTime: number;
|
|
196
|
+
/** Duration in ms */
|
|
197
|
+
duration: number;
|
|
198
|
+
/** Type: "MajorGC" or "MinorGC" */
|
|
199
|
+
type: string;
|
|
200
|
+
/** Bytes used before GC, if available */
|
|
201
|
+
usedHeapSizeBefore?: number;
|
|
202
|
+
/** Bytes used after GC, if available */
|
|
203
|
+
usedHeapSizeAfter?: number;
|
|
204
|
+
}
|
|
205
|
+
/** Complete runtime trace summary. */
|
|
206
|
+
export interface RuntimeTraceSummary {
|
|
207
|
+
totalEvents: number;
|
|
208
|
+
mainThreadId: number;
|
|
209
|
+
/** Duration of the trace in ms */
|
|
210
|
+
traceDuration: number;
|
|
211
|
+
/** Frame time breakdown */
|
|
212
|
+
frameBreakdown: FrameBreakdown;
|
|
213
|
+
/** Functions that blocked the main thread > 50ms, sorted by duration */
|
|
214
|
+
blockingFunctions: BlockingFunction[];
|
|
215
|
+
/** Event listener add/remove imbalances */
|
|
216
|
+
eventListeners: EventListenerInfo[];
|
|
217
|
+
/** GC events */
|
|
218
|
+
gcEvents: GCEvent[];
|
|
219
|
+
/** Top repeated event dispatches (possible missing throttle/debounce) */
|
|
220
|
+
frequentEvents: Array<{
|
|
221
|
+
eventType: string;
|
|
222
|
+
count: number;
|
|
223
|
+
totalDuration: number;
|
|
224
|
+
}>;
|
|
225
|
+
}
|
|
226
|
+
/** Handle returned by tracePageLoad — call stop() after page settles. */
|
|
227
|
+
export interface TraceHandle {
|
|
228
|
+
stop(): Promise<TraceResult>;
|
|
229
|
+
}
|
|
230
|
+
/** Combined result of unified page capture (heap + trace). */
|
|
231
|
+
export interface CaptureResult {
|
|
232
|
+
heapSnapshot: RawSnapshot;
|
|
233
|
+
trace: TraceResult;
|
|
234
|
+
}
|
|
235
|
+
/** Options for page capture. */
|
|
236
|
+
export interface CaptureOptions {
|
|
237
|
+
/** Page load timeout in milliseconds. */
|
|
238
|
+
timeout?: number;
|
|
239
|
+
}
|
|
240
|
+
/** Options for browser launch. */
|
|
241
|
+
export interface LaunchOptions {
|
|
242
|
+
/** Run Chrome in headless mode. */
|
|
243
|
+
headless?: boolean;
|
|
244
|
+
}
|
|
245
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Classify script URLs into source categories so the Deep Agent can
|
|
3
|
+
* distinguish application code (what the user cares about) from
|
|
4
|
+
* dependencies, test files, and framework internals.
|
|
5
|
+
*/
|
|
6
|
+
import type { SourceCategory } from './types.js';
|
|
7
|
+
/**
|
|
8
|
+
* Classify a script URL (file path or file:// URL) into a source category.
|
|
9
|
+
*
|
|
10
|
+
* @param scriptUrl - The URL or file path from the V8 profile
|
|
11
|
+
* @param projectRoot - The project root directory (absolute path)
|
|
12
|
+
* @param testFiles - Optional set of known test file paths for more accurate classification
|
|
13
|
+
*/
|
|
14
|
+
export declare function classifyScript(scriptUrl: string, projectRoot: string, testFiles?: Set<string>): SourceCategory;
|
|
15
|
+
/**
|
|
16
|
+
* Classify multiple scripts and return a Map of scriptUrl → category.
|
|
17
|
+
*/
|
|
18
|
+
export declare function classifyScripts(scriptUrls: string[], projectRoot: string, testFiles?: Set<string>): Map<string, SourceCategory>;
|
|
19
|
+
//# sourceMappingURL=classify.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"classify.d.ts","sourceRoot":"","sources":["../../src/vitest/classify.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAGH,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAkBjD;;;;;;GAMG;AACH,wBAAgB,cAAc,CAC5B,SAAS,EAAE,MAAM,EACjB,WAAW,EAAE,MAAM,EACnB,SAAS,CAAC,EAAE,GAAG,CAAC,MAAM,CAAC,GACtB,cAAc,CAwDhB;AAED;;GAEG;AACH,wBAAgB,eAAe,CAC7B,UAAU,EAAE,MAAM,EAAE,EACpB,WAAW,EAAE,MAAM,EACnB,SAAS,CAAC,EAAE,GAAG,CAAC,MAAM,CAAC,GACtB,GAAG,CAAC,MAAM,EAAE,cAAc,CAAC,CAM7B"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import type { HeapProfileSummary, V8HeapProfile } from './types.js';
|
|
2
|
+
/**
|
|
3
|
+
* Parse a V8 heap profile (from Node.js `--heap-prof`) into a compact summary.
|
|
4
|
+
*
|
|
5
|
+
* The raw heap profile is a call tree (`head`) plus allocation samples
|
|
6
|
+
* referencing node ids (`samples[].nodeId`). We attribute bytes to the node
|
|
7
|
+
* referenced by each sample (self attribution) and then aggregate:
|
|
8
|
+
* - top functions by allocated bytes
|
|
9
|
+
* - per-script allocated bytes
|
|
10
|
+
*/
|
|
11
|
+
export declare function parseHeapProfile(raw: V8HeapProfile, profilePath: string): HeapProfileSummary;
|
|
12
|
+
//# sourceMappingURL=heap-profile-parser.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"heap-profile-parser.d.ts","sourceRoot":"","sources":["../../src/vitest/heap-profile-parser.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,kBAAkB,EAClB,aAAa,EAId,MAAM,YAAY,CAAC;AAEpB;;;;;;;;GAQG;AACH,wBAAgB,gBAAgB,CAAC,GAAG,EAAE,aAAa,EAAE,WAAW,EAAE,MAAM,GAAG,kBAAkB,CA0E5F"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Public entry point for the zeitzeuge Vitest integration.
|
|
3
|
+
*
|
|
4
|
+
* Usage in vitest.config.ts:
|
|
5
|
+
*
|
|
6
|
+
* ```ts
|
|
7
|
+
* import { defineConfig } from 'vitest/config'
|
|
8
|
+
* import { zeitzeuge } from 'zeitzeuge/vitest'
|
|
9
|
+
*
|
|
10
|
+
* export default defineConfig({
|
|
11
|
+
* plugins: [zeitzeuge()],
|
|
12
|
+
* })
|
|
13
|
+
* ```
|
|
14
|
+
*/
|
|
15
|
+
export { zeitzeuge } from './plugin.js';
|
|
16
|
+
export type { ZeitZeugeVitestOptions, SourceCategory } from './types.js';
|
|
17
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/vitest/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAEH,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AACxC,YAAY,EAAE,sBAAsB,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC"}
|