perf-skill 0.0.1 → 0.2.1
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 +404 -0
- package/SKILL.md +238 -0
- package/dist/cli/init.d.ts +29 -0
- package/dist/cli/init.d.ts.map +1 -0
- package/dist/cli/init.js +139 -0
- package/dist/cli/init.js.map +1 -0
- package/dist/cli/main.d.ts +6 -0
- package/dist/cli/main.d.ts.map +1 -0
- package/dist/cli/main.js +389 -0
- package/dist/cli/main.js.map +1 -0
- package/dist/cli/options.d.ts +37 -0
- package/dist/cli/options.d.ts.map +1 -0
- package/dist/cli/options.js +54 -0
- package/dist/cli/options.js.map +1 -0
- package/dist/convert/converter.d.ts +39 -0
- package/dist/convert/converter.d.ts.map +1 -0
- package/dist/convert/converter.js +99 -0
- package/dist/convert/converter.js.map +1 -0
- package/dist/convert/extract.d.ts +32 -0
- package/dist/convert/extract.d.ts.map +1 -0
- package/dist/convert/extract.js +235 -0
- package/dist/convert/extract.js.map +1 -0
- package/dist/convert/index.d.ts +7 -0
- package/dist/convert/index.d.ts.map +1 -0
- package/dist/convert/index.js +7 -0
- package/dist/convert/index.js.map +1 -0
- package/dist/convert/sanitize.d.ts +60 -0
- package/dist/convert/sanitize.d.ts.map +1 -0
- package/dist/convert/sanitize.js +169 -0
- package/dist/convert/sanitize.js.map +1 -0
- package/dist/diff/engine.d.ts +76 -0
- package/dist/diff/engine.d.ts.map +1 -0
- package/dist/diff/engine.js +386 -0
- package/dist/diff/engine.js.map +1 -0
- package/dist/diff/index.d.ts +6 -0
- package/dist/diff/index.d.ts.map +1 -0
- package/dist/diff/index.js +6 -0
- package/dist/diff/index.js.map +1 -0
- package/dist/diff/markdown.d.ts +16 -0
- package/dist/diff/markdown.d.ts.map +1 -0
- package/dist/diff/markdown.js +342 -0
- package/dist/diff/markdown.js.map +1 -0
- package/dist/index.d.ts +52 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +247 -0
- package/dist/index.js.map +1 -0
- package/dist/llm/client.d.ts +39 -0
- package/dist/llm/client.d.ts.map +1 -0
- package/dist/llm/client.js +270 -0
- package/dist/llm/client.js.map +1 -0
- package/dist/llm/index.d.ts +8 -0
- package/dist/llm/index.d.ts.map +1 -0
- package/dist/llm/index.js +8 -0
- package/dist/llm/index.js.map +1 -0
- package/dist/llm/prompt.d.ts +32 -0
- package/dist/llm/prompt.d.ts.map +1 -0
- package/dist/llm/prompt.js +146 -0
- package/dist/llm/prompt.js.map +1 -0
- package/dist/llm/schema.d.ts +150 -0
- package/dist/llm/schema.d.ts.map +1 -0
- package/dist/llm/schema.js +131 -0
- package/dist/llm/schema.js.map +1 -0
- package/dist/llm/validate.d.ts +33 -0
- package/dist/llm/validate.d.ts.map +1 -0
- package/dist/llm/validate.js +241 -0
- package/dist/llm/validate.js.map +1 -0
- package/dist/profile/duration.d.ts +2 -0
- package/dist/profile/duration.d.ts.map +1 -0
- package/dist/profile/duration.js +24 -0
- package/dist/profile/duration.js.map +1 -0
- package/dist/profile/preload.d.ts +2 -0
- package/dist/profile/preload.d.ts.map +1 -0
- package/dist/profile/preload.js +100 -0
- package/dist/profile/preload.js.map +1 -0
- package/dist/profile/runner.d.ts +22 -0
- package/dist/profile/runner.d.ts.map +1 -0
- package/dist/profile/runner.js +88 -0
- package/dist/profile/runner.js.map +1 -0
- package/dist/server/http.d.ts +27 -0
- package/dist/server/http.d.ts.map +1 -0
- package/dist/server/http.js +285 -0
- package/dist/server/http.js.map +1 -0
- package/dist/server/utils.d.ts +15 -0
- package/dist/server/utils.d.ts.map +1 -0
- package/dist/server/utils.js +71 -0
- package/dist/server/utils.js.map +1 -0
- package/dist/skill/handler.d.ts +77 -0
- package/dist/skill/handler.d.ts.map +1 -0
- package/dist/skill/handler.js +91 -0
- package/dist/skill/handler.js.map +1 -0
- package/dist/skill/index.d.ts +6 -0
- package/dist/skill/index.d.ts.map +1 -0
- package/dist/skill/index.js +6 -0
- package/dist/skill/index.js.map +1 -0
- package/dist/skill/manifest.d.ts +17 -0
- package/dist/skill/manifest.d.ts.map +1 -0
- package/dist/skill/manifest.js +231 -0
- package/dist/skill/manifest.js.map +1 -0
- package/dist/types.d.ts +260 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +5 -0
- package/dist/types.js.map +1 -0
- package/dist/utils/fs.d.ts +52 -0
- package/dist/utils/fs.d.ts.map +1 -0
- package/dist/utils/fs.js +106 -0
- package/dist/utils/fs.js.map +1 -0
- package/dist/utils/index.d.ts +7 -0
- package/dist/utils/index.d.ts.map +1 -0
- package/dist/utils/index.js +7 -0
- package/dist/utils/index.js.map +1 -0
- package/dist/utils/limits.d.ts +38 -0
- package/dist/utils/limits.d.ts.map +1 -0
- package/dist/utils/limits.js +86 -0
- package/dist/utils/limits.js.map +1 -0
- package/dist/utils/logger.d.ts +21 -0
- package/dist/utils/logger.d.ts.map +1 -0
- package/dist/utils/logger.js +82 -0
- package/dist/utils/logger.js.map +1 -0
- package/package.json +70 -6
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* CLI option builders (pure helpers for testing)
|
|
3
|
+
*/
|
|
4
|
+
function parseOptionalInt(value) {
|
|
5
|
+
if (value === undefined)
|
|
6
|
+
return undefined;
|
|
7
|
+
const parsed = parseInt(value, 10);
|
|
8
|
+
return Number.isFinite(parsed) ? parsed : undefined;
|
|
9
|
+
}
|
|
10
|
+
function buildLimits(opts) {
|
|
11
|
+
const maxDecompressedBytes = parseOptionalInt(opts.maxDecompressedBytes);
|
|
12
|
+
if (maxDecompressedBytes === undefined) {
|
|
13
|
+
return undefined;
|
|
14
|
+
}
|
|
15
|
+
return { maxDecompressedBytes };
|
|
16
|
+
}
|
|
17
|
+
export function buildAnalyzeOptions(opts) {
|
|
18
|
+
return {
|
|
19
|
+
format: opts.format,
|
|
20
|
+
profileType: opts.type,
|
|
21
|
+
maxHotspots: parseInt(opts.maxHotspots, 10),
|
|
22
|
+
sourceDir: opts.sourceDir,
|
|
23
|
+
includeSource: opts.source,
|
|
24
|
+
mode: opts.mode,
|
|
25
|
+
redact: opts.redact,
|
|
26
|
+
context: {
|
|
27
|
+
serviceName: opts.service,
|
|
28
|
+
scenario: opts.scenario,
|
|
29
|
+
targetSLO: opts.slo,
|
|
30
|
+
},
|
|
31
|
+
};
|
|
32
|
+
}
|
|
33
|
+
export function buildConvertOptions(opts) {
|
|
34
|
+
return {
|
|
35
|
+
format: opts.format,
|
|
36
|
+
profileType: opts.type,
|
|
37
|
+
maxHotspots: parseInt(opts.maxHotspots, 10),
|
|
38
|
+
sourceDir: opts.sourceDir,
|
|
39
|
+
includeSource: opts.source,
|
|
40
|
+
mode: "convert-only",
|
|
41
|
+
redact: opts.redact,
|
|
42
|
+
};
|
|
43
|
+
}
|
|
44
|
+
export function buildDiffOptions(opts) {
|
|
45
|
+
const limits = buildLimits(opts);
|
|
46
|
+
return {
|
|
47
|
+
format: opts.format,
|
|
48
|
+
normalize: opts.normalize,
|
|
49
|
+
maxRegressions: parseInt(opts.maxRegressions, 10),
|
|
50
|
+
maxImprovements: parseInt(opts.maxImprovements, 10),
|
|
51
|
+
limits,
|
|
52
|
+
};
|
|
53
|
+
}
|
|
54
|
+
//# sourceMappingURL=options.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"options.js","sourceRoot":"","sources":["../../src/cli/options.ts"],"names":[],"mappings":"AAAA;;GAEG;AAoCH,SAAS,gBAAgB,CAAC,KAAc;IACtC,IAAI,KAAK,KAAK,SAAS;QAAE,OAAO,SAAS,CAAC;IAC1C,MAAM,MAAM,GAAG,QAAQ,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC;IACnC,OAAO,MAAM,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,SAAS,CAAC;AACtD,CAAC;AAED,SAAS,WAAW,CAAC,IAAuC;IAC1D,MAAM,oBAAoB,GAAG,gBAAgB,CAAC,IAAI,CAAC,oBAAoB,CAAC,CAAC;IACzE,IAAI,oBAAoB,KAAK,SAAS,EAAE,CAAC;QACvC,OAAO,SAAS,CAAC;IACnB,CAAC;IACD,OAAO,EAAE,oBAAoB,EAAE,CAAC;AAClC,CAAC;AAED,MAAM,UAAU,mBAAmB,CAAC,IAA2B;IAC7D,OAAO;QACL,MAAM,EAAE,IAAI,CAAC,MAAM;QACnB,WAAW,EAAE,IAAI,CAAC,IAAI;QACtB,WAAW,EAAE,QAAQ,CAAC,IAAI,CAAC,WAAW,EAAE,EAAE,CAAC;QAC3C,SAAS,EAAE,IAAI,CAAC,SAAS;QACzB,aAAa,EAAE,IAAI,CAAC,MAAM;QAC1B,IAAI,EAAE,IAAI,CAAC,IAAI;QACf,MAAM,EAAE,IAAI,CAAC,MAAM;QACnB,OAAO,EAAE;YACP,WAAW,EAAE,IAAI,CAAC,OAAO;YACzB,QAAQ,EAAE,IAAI,CAAC,QAAQ;YACvB,SAAS,EAAE,IAAI,CAAC,GAAG;SACpB;KACF,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,mBAAmB,CAAC,IAA2B;IAC7D,OAAO;QACL,MAAM,EAAE,IAAI,CAAC,MAAM;QACnB,WAAW,EAAE,IAAI,CAAC,IAAI;QACtB,WAAW,EAAE,QAAQ,CAAC,IAAI,CAAC,WAAW,EAAE,EAAE,CAAC;QAC3C,SAAS,EAAE,IAAI,CAAC,SAAS;QACzB,aAAa,EAAE,IAAI,CAAC,MAAM;QAC1B,IAAI,EAAE,cAAc;QACpB,MAAM,EAAE,IAAI,CAAC,MAAM;KACpB,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,gBAAgB,CAAC,IAAwB;IACvD,MAAM,MAAM,GAAG,WAAW,CAAC,IAAI,CAAC,CAAC;IACjC,OAAO;QACL,MAAM,EAAE,IAAI,CAAC,MAAM;QACnB,SAAS,EAAE,IAAI,CAAC,SAAS;QACzB,cAAc,EAAE,QAAQ,CAAC,IAAI,CAAC,cAAc,EAAE,EAAE,CAAC;QACjD,eAAe,EAAE,QAAQ,CAAC,IAAI,CAAC,eAAe,EAAE,EAAE,CAAC;QACnD,MAAM;KACP,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Core converter module - wraps pprof-to-md library
|
|
3
|
+
*/
|
|
4
|
+
import type { ConvertOptions, ProfileMeta } from "../types.js";
|
|
5
|
+
import { type SanitizeOptions } from "./sanitize.js";
|
|
6
|
+
import type { Hotspot } from "../types.js";
|
|
7
|
+
export interface ConvertResult {
|
|
8
|
+
/** Generated markdown */
|
|
9
|
+
markdown: string;
|
|
10
|
+
/** Original markdown before sanitization */
|
|
11
|
+
rawMarkdown: string;
|
|
12
|
+
/** Extracted hotspots */
|
|
13
|
+
hotspots: Hotspot[];
|
|
14
|
+
/** Profile metadata */
|
|
15
|
+
meta?: ProfileMeta;
|
|
16
|
+
/** Processing time in ms */
|
|
17
|
+
durationMs: number;
|
|
18
|
+
}
|
|
19
|
+
export interface FullConvertOptions extends ConvertOptions {
|
|
20
|
+
/** Maximum profile size in bytes */
|
|
21
|
+
maxProfileBytes?: number;
|
|
22
|
+
/** Maximum markdown output characters */
|
|
23
|
+
maxMarkdownChars?: number;
|
|
24
|
+
/** Sanitization options */
|
|
25
|
+
sanitize?: SanitizeOptions;
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* Convert a pprof profile buffer to markdown
|
|
29
|
+
*/
|
|
30
|
+
export declare function convertProfileToMarkdown(profileBytes: Uint8Array | Buffer, options?: FullConvertOptions): Promise<ConvertResult>;
|
|
31
|
+
/**
|
|
32
|
+
* Convert profile from file path
|
|
33
|
+
*/
|
|
34
|
+
export declare function convertProfileFromPath(profilePath: string, options?: FullConvertOptions): Promise<ConvertResult>;
|
|
35
|
+
/**
|
|
36
|
+
* Convert profile from base64 string
|
|
37
|
+
*/
|
|
38
|
+
export declare function convertProfileFromBase64(base64: string, options?: FullConvertOptions): Promise<ConvertResult>;
|
|
39
|
+
//# sourceMappingURL=converter.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"converter.d.ts","sourceRoot":"","sources":["../../src/convert/converter.ts"],"names":[],"mappings":"AAAA;;GAEG;AAGH,OAAO,KAAK,EAAE,cAAc,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAI/D,OAAO,EAAoB,KAAK,eAAe,EAAE,MAAM,eAAe,CAAC;AAEvE,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,aAAa,CAAC;AAE3C,MAAM,WAAW,aAAa;IAC5B,yBAAyB;IACzB,QAAQ,EAAE,MAAM,CAAC;IACjB,4CAA4C;IAC5C,WAAW,EAAE,MAAM,CAAC;IACpB,yBAAyB;IACzB,QAAQ,EAAE,OAAO,EAAE,CAAC;IACpB,uBAAuB;IACvB,IAAI,CAAC,EAAE,WAAW,CAAC;IACnB,4BAA4B;IAC5B,UAAU,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,kBAAmB,SAAQ,cAAc;IACxD,oCAAoC;IACpC,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,yCAAyC;IACzC,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,2BAA2B;IAC3B,QAAQ,CAAC,EAAE,eAAe,CAAC;CAC5B;AAED;;GAEG;AACH,wBAAsB,wBAAwB,CAC5C,YAAY,EAAE,UAAU,GAAG,MAAM,EACjC,OAAO,GAAE,kBAAuB,GAC/B,OAAO,CAAC,aAAa,CAAC,CAwFxB;AAED;;GAEG;AACH,wBAAsB,sBAAsB,CAC1C,WAAW,EAAE,MAAM,EACnB,OAAO,GAAE,kBAAuB,GAC/B,OAAO,CAAC,aAAa,CAAC,CAIxB;AAED;;GAEG;AACH,wBAAsB,wBAAwB,CAC5C,MAAM,EAAE,MAAM,EACd,OAAO,GAAE,kBAAuB,GAC/B,OAAO,CAAC,aAAa,CAAC,CAGxB"}
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Core converter module - wraps pprof-to-md library
|
|
3
|
+
*/
|
|
4
|
+
import { convert as pprofToMd } from "pprof-to-md";
|
|
5
|
+
import { getProfileExtension, withTempFile } from "../utils/fs.js";
|
|
6
|
+
import { logger } from "../utils/logger.js";
|
|
7
|
+
import { checkSizeLimit, resolveLimits } from "../utils/limits.js";
|
|
8
|
+
import { sanitizeMarkdown } from "./sanitize.js";
|
|
9
|
+
import { extractHotspots, extractProfileMeta } from "./extract.js";
|
|
10
|
+
/**
|
|
11
|
+
* Convert a pprof profile buffer to markdown
|
|
12
|
+
*/
|
|
13
|
+
export async function convertProfileToMarkdown(profileBytes, options = {}) {
|
|
14
|
+
const startTime = performance.now();
|
|
15
|
+
const limits = resolveLimits(options);
|
|
16
|
+
// Check input size
|
|
17
|
+
checkSizeLimit(profileBytes, limits.maxProfileBytes, "Profile");
|
|
18
|
+
logger.debug("Converting profile to markdown", {
|
|
19
|
+
profileBytes: profileBytes.length,
|
|
20
|
+
format: options.format ?? "adaptive",
|
|
21
|
+
profileType: options.profileType ?? "auto",
|
|
22
|
+
});
|
|
23
|
+
const pprofProfileType = options.profileType === "auto" ? undefined : options.profileType;
|
|
24
|
+
const tempExt = getProfileExtension(profileBytes);
|
|
25
|
+
// Convert using pprof-to-md (requires file path)
|
|
26
|
+
const rawMarkdown = await withTempFile(profileBytes, async (tempPath) => {
|
|
27
|
+
// pprof-to-md convert function
|
|
28
|
+
const md = await Promise.resolve(pprofToMd(tempPath, {
|
|
29
|
+
format: options.format ?? "adaptive",
|
|
30
|
+
profileType: pprofProfileType,
|
|
31
|
+
maxHotspots: options.maxHotspots ?? 10,
|
|
32
|
+
sourceDir: options.sourceDir,
|
|
33
|
+
includeSource: options.includeSource !== false,
|
|
34
|
+
}));
|
|
35
|
+
return md;
|
|
36
|
+
}, "pprof", tempExt);
|
|
37
|
+
logger.debug("Raw markdown generated", { chars: rawMarkdown.length });
|
|
38
|
+
// Check if markdown exceeds limit and needs format downgrade
|
|
39
|
+
let markdown = rawMarkdown;
|
|
40
|
+
let usedFormat = options.format ?? "adaptive";
|
|
41
|
+
if (rawMarkdown.length > limits.maxMarkdownChars) {
|
|
42
|
+
logger.info("Markdown exceeds limit, downgrading to summary format", {
|
|
43
|
+
chars: rawMarkdown.length,
|
|
44
|
+
limit: limits.maxMarkdownChars,
|
|
45
|
+
});
|
|
46
|
+
// Retry with summary format and fewer hotspots
|
|
47
|
+
markdown = await withTempFile(profileBytes, async (tempPath) => {
|
|
48
|
+
const md = await Promise.resolve(pprofToMd(tempPath, {
|
|
49
|
+
format: "summary",
|
|
50
|
+
profileType: pprofProfileType,
|
|
51
|
+
maxHotspots: Math.min(options.maxHotspots ?? 10, 10),
|
|
52
|
+
sourceDir: options.sourceDir,
|
|
53
|
+
includeSource: false, // Disable source for smaller output
|
|
54
|
+
}));
|
|
55
|
+
return md;
|
|
56
|
+
}, "pprof", tempExt);
|
|
57
|
+
usedFormat = "summary";
|
|
58
|
+
}
|
|
59
|
+
// Extract metadata and hotspots from markdown
|
|
60
|
+
const meta = extractProfileMeta(markdown);
|
|
61
|
+
const hotspots = extractHotspots(markdown);
|
|
62
|
+
// Sanitize markdown
|
|
63
|
+
const sanitizedMarkdown = sanitizeMarkdown(markdown, {
|
|
64
|
+
...options.sanitize,
|
|
65
|
+
maxChars: limits.maxMarkdownChars,
|
|
66
|
+
maxSourceLines: limits.maxSourceLinesPerFile,
|
|
67
|
+
baseDir: options.sourceDir,
|
|
68
|
+
});
|
|
69
|
+
const durationMs = performance.now() - startTime;
|
|
70
|
+
logger.info("Profile conversion complete", {
|
|
71
|
+
durationMs: Math.round(durationMs),
|
|
72
|
+
format: usedFormat,
|
|
73
|
+
hotspotsFound: hotspots.length,
|
|
74
|
+
outputChars: sanitizedMarkdown.length,
|
|
75
|
+
});
|
|
76
|
+
return {
|
|
77
|
+
markdown: sanitizedMarkdown,
|
|
78
|
+
rawMarkdown,
|
|
79
|
+
hotspots,
|
|
80
|
+
meta,
|
|
81
|
+
durationMs,
|
|
82
|
+
};
|
|
83
|
+
}
|
|
84
|
+
/**
|
|
85
|
+
* Convert profile from file path
|
|
86
|
+
*/
|
|
87
|
+
export async function convertProfileFromPath(profilePath, options = {}) {
|
|
88
|
+
const { readFile } = await import("node:fs/promises");
|
|
89
|
+
const profileBytes = await readFile(profilePath);
|
|
90
|
+
return convertProfileToMarkdown(profileBytes, options);
|
|
91
|
+
}
|
|
92
|
+
/**
|
|
93
|
+
* Convert profile from base64 string
|
|
94
|
+
*/
|
|
95
|
+
export async function convertProfileFromBase64(base64, options = {}) {
|
|
96
|
+
const buffer = Buffer.from(base64, "base64");
|
|
97
|
+
return convertProfileToMarkdown(buffer, options);
|
|
98
|
+
}
|
|
99
|
+
//# sourceMappingURL=converter.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"converter.js","sourceRoot":"","sources":["../../src/convert/converter.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Extract structured data from pprof-to-md markdown output
|
|
3
|
+
*
|
|
4
|
+
* Best-effort parsing - falls back gracefully when format doesn't match
|
|
5
|
+
*/
|
|
6
|
+
import type { Hotspot, ProfileMeta } from "../types.js";
|
|
7
|
+
/**
|
|
8
|
+
* Extract profile metadata from markdown
|
|
9
|
+
*/
|
|
10
|
+
export declare function extractProfileMeta(markdown: string): ProfileMeta | undefined;
|
|
11
|
+
/**
|
|
12
|
+
* Extract hotspots from markdown
|
|
13
|
+
* Handles both table format and list format
|
|
14
|
+
*/
|
|
15
|
+
export declare function extractHotspots(markdown: string): Hotspot[];
|
|
16
|
+
/**
|
|
17
|
+
* Extract call path for a function from detailed section
|
|
18
|
+
*/
|
|
19
|
+
export declare function extractCallPath(markdown: string, functionName: string): string[] | undefined;
|
|
20
|
+
/**
|
|
21
|
+
* Extract callers of a function
|
|
22
|
+
*/
|
|
23
|
+
export declare function extractCallers(markdown: string, functionName: string): string[] | undefined;
|
|
24
|
+
/**
|
|
25
|
+
* Extract callees of a function
|
|
26
|
+
*/
|
|
27
|
+
export declare function extractCallees(markdown: string, functionName: string): string[] | undefined;
|
|
28
|
+
/**
|
|
29
|
+
* Enrich hotspots with additional context from markdown
|
|
30
|
+
*/
|
|
31
|
+
export declare function enrichHotspots(hotspots: Hotspot[], markdown: string): Hotspot[];
|
|
32
|
+
//# sourceMappingURL=extract.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"extract.d.ts","sourceRoot":"","sources":["../../src/convert/extract.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,EAAE,OAAO,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAExD;;GAEG;AACH,wBAAgB,kBAAkB,CAAC,QAAQ,EAAE,MAAM,GAAG,WAAW,GAAG,SAAS,CAuC5E;AAED;;;GAGG;AACH,wBAAgB,eAAe,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,EAAE,CAS3D;AAyHD;;GAEG;AACH,wBAAgB,eAAe,CAC7B,QAAQ,EAAE,MAAM,EAChB,YAAY,EAAE,MAAM,GACnB,MAAM,EAAE,GAAG,SAAS,CAsBtB;AAED;;GAEG;AACH,wBAAgB,cAAc,CAC5B,QAAQ,EAAE,MAAM,EAChB,YAAY,EAAE,MAAM,GACnB,MAAM,EAAE,GAAG,SAAS,CAmBtB;AAED;;GAEG;AACH,wBAAgB,cAAc,CAC5B,QAAQ,EAAE,MAAM,EAChB,YAAY,EAAE,MAAM,GACnB,MAAM,EAAE,GAAG,SAAS,CAmBtB;AAED;;GAEG;AACH,wBAAgB,cAAc,CAC5B,QAAQ,EAAE,OAAO,EAAE,EACnB,QAAQ,EAAE,MAAM,GACf,OAAO,EAAE,CAOX"}
|
|
@@ -0,0 +1,235 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Extract structured data from pprof-to-md markdown output
|
|
3
|
+
*
|
|
4
|
+
* Best-effort parsing - falls back gracefully when format doesn't match
|
|
5
|
+
*/
|
|
6
|
+
/**
|
|
7
|
+
* Extract profile metadata from markdown
|
|
8
|
+
*/
|
|
9
|
+
export function extractProfileMeta(markdown) {
|
|
10
|
+
const meta = {};
|
|
11
|
+
const normalized = markdown.replace(/\*\*/g, "");
|
|
12
|
+
// Try to extract profile type from header
|
|
13
|
+
// e.g., "# PPROF Analysis: CPU" or "# PPROF Analysis: Heap"
|
|
14
|
+
const typeMatch = normalized.match(/# PPROF Analysis:\s*(CPU|Heap)/i);
|
|
15
|
+
if (typeMatch) {
|
|
16
|
+
meta.type = typeMatch[1].toLowerCase();
|
|
17
|
+
}
|
|
18
|
+
// Extract duration
|
|
19
|
+
// e.g., "**Duration:** 30s" or "Duration: 30.5s"
|
|
20
|
+
const durationMatch = normalized.match(/Duration:\s*([\d.]+)\s*s/i);
|
|
21
|
+
if (durationMatch) {
|
|
22
|
+
meta.durationSec = parseFloat(durationMatch[1]);
|
|
23
|
+
}
|
|
24
|
+
// Extract samples
|
|
25
|
+
// e.g., "**Samples:** 45,231" or "Samples: 45231"
|
|
26
|
+
const samplesMatch = normalized.match(/Samples:\s*([\d,]+)/i);
|
|
27
|
+
if (samplesMatch) {
|
|
28
|
+
meta.samples = parseInt(samplesMatch[1].replace(/,/g, ""), 10);
|
|
29
|
+
}
|
|
30
|
+
// Extract sample type
|
|
31
|
+
// e.g., "Sample Type: cpu" or "Type: alloc_space"
|
|
32
|
+
const sampleTypeMatch = normalized.match(/Sample Type:\s*(\w+)/i);
|
|
33
|
+
if (sampleTypeMatch) {
|
|
34
|
+
meta.sampleType = sampleTypeMatch[1];
|
|
35
|
+
}
|
|
36
|
+
// Extract unit
|
|
37
|
+
const unitMatch = normalized.match(/Unit:\s*(\w+)/i);
|
|
38
|
+
if (unitMatch) {
|
|
39
|
+
meta.unit = unitMatch[1];
|
|
40
|
+
}
|
|
41
|
+
return Object.keys(meta).length > 0 ? meta : undefined;
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* Extract hotspots from markdown
|
|
45
|
+
* Handles both table format and list format
|
|
46
|
+
*/
|
|
47
|
+
export function extractHotspots(markdown) {
|
|
48
|
+
// Try table format first (more structured)
|
|
49
|
+
const tableHotspots = extractHotspotsFromTable(markdown);
|
|
50
|
+
if (tableHotspots.length > 0) {
|
|
51
|
+
return tableHotspots;
|
|
52
|
+
}
|
|
53
|
+
// Fall back to list format
|
|
54
|
+
return extractHotspotsFromList(markdown);
|
|
55
|
+
}
|
|
56
|
+
/**
|
|
57
|
+
* Extract hotspots from markdown table
|
|
58
|
+
*
|
|
59
|
+
* Expected format:
|
|
60
|
+
* | Rank | Function | Self% | Cum% | Location |
|
|
61
|
+
* |------|----------|-------|------|----------|
|
|
62
|
+
* | 1 | `JSON.parse` | 23.4% | 23.4% | `<native>` |
|
|
63
|
+
*/
|
|
64
|
+
function extractHotspotsFromTable(markdown) {
|
|
65
|
+
const hotspots = [];
|
|
66
|
+
// Find hotspots section
|
|
67
|
+
const hotspotsSection = extractSection(markdown, /##?\s*(?:Top\s+)?Hotspots?/i);
|
|
68
|
+
if (!hotspotsSection) {
|
|
69
|
+
return hotspots;
|
|
70
|
+
}
|
|
71
|
+
// Match table rows
|
|
72
|
+
const tableRowPattern = /\|\s*(\d+)\s*\|\s*`?([^|`]+)`?\s*\|\s*([\d.]+)%?\s*\|\s*([\d.]+)%?\s*\|\s*`?([^|`]*)`?\s*\|/g;
|
|
73
|
+
let match;
|
|
74
|
+
while ((match = tableRowPattern.exec(hotspotsSection)) !== null) {
|
|
75
|
+
const [, rank, func, selfPct, cumPct, location] = match;
|
|
76
|
+
hotspots.push({
|
|
77
|
+
rank: parseInt(rank, 10),
|
|
78
|
+
function: func.trim(),
|
|
79
|
+
selfPct: parseFloat(selfPct),
|
|
80
|
+
cumPct: parseFloat(cumPct),
|
|
81
|
+
location: location?.trim() || undefined,
|
|
82
|
+
});
|
|
83
|
+
}
|
|
84
|
+
return hotspots;
|
|
85
|
+
}
|
|
86
|
+
/**
|
|
87
|
+
* Extract hotspots from markdown list
|
|
88
|
+
*
|
|
89
|
+
* Expected format:
|
|
90
|
+
* 1. `JSON.parse` (**23.4%**) → [Details](#json-parse)
|
|
91
|
+
* 2. `processRequest` (**15.2%**) → [Details](#processrequest)
|
|
92
|
+
*/
|
|
93
|
+
function extractHotspotsFromList(markdown) {
|
|
94
|
+
const hotspots = [];
|
|
95
|
+
// Find hotspots section
|
|
96
|
+
const hotspotsSection = extractSection(markdown, /##?\s*(?:Top\s+)?Hotspots?/i);
|
|
97
|
+
if (!hotspotsSection) {
|
|
98
|
+
return hotspots;
|
|
99
|
+
}
|
|
100
|
+
// Match list items with various formats
|
|
101
|
+
const listPatterns = [
|
|
102
|
+
// Format: 1. `func` (**23.4%**) → [Details](#anchor)
|
|
103
|
+
/(\d+)\.\s*`([^`]+)`\s*\(\*?\*?([\d.]+)%?\*?\*?\)/g,
|
|
104
|
+
// Format: 1. func (23.4%) - location
|
|
105
|
+
/(\d+)\.\s*([^\(]+)\s*\(([\d.]+)%?\)/g,
|
|
106
|
+
// Format: - **func** - 23.4%
|
|
107
|
+
/-\s*\*\*([^*]+)\*\*\s*-?\s*([\d.]+)%/g,
|
|
108
|
+
];
|
|
109
|
+
for (const pattern of listPatterns) {
|
|
110
|
+
let match;
|
|
111
|
+
while ((match = pattern.exec(hotspotsSection)) !== null) {
|
|
112
|
+
if (pattern.source.startsWith("(\\d+)")) {
|
|
113
|
+
const [, rank, func, pct] = match;
|
|
114
|
+
hotspots.push({
|
|
115
|
+
rank: parseInt(rank, 10),
|
|
116
|
+
function: func.trim(),
|
|
117
|
+
selfPct: parseFloat(pct),
|
|
118
|
+
});
|
|
119
|
+
}
|
|
120
|
+
else {
|
|
121
|
+
const [, func, pct] = match;
|
|
122
|
+
hotspots.push({
|
|
123
|
+
rank: hotspots.length + 1,
|
|
124
|
+
function: func.trim(),
|
|
125
|
+
selfPct: parseFloat(pct),
|
|
126
|
+
});
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
if (hotspots.length > 0)
|
|
130
|
+
break;
|
|
131
|
+
}
|
|
132
|
+
return hotspots;
|
|
133
|
+
}
|
|
134
|
+
/**
|
|
135
|
+
* Extract a section from markdown by heading pattern
|
|
136
|
+
*/
|
|
137
|
+
function extractSection(markdown, headingPattern) {
|
|
138
|
+
const lines = markdown.split("\n");
|
|
139
|
+
let inSection = false;
|
|
140
|
+
let sectionLines = [];
|
|
141
|
+
let sectionLevel = 0;
|
|
142
|
+
for (const line of lines) {
|
|
143
|
+
// Check for section start
|
|
144
|
+
if (!inSection && headingPattern.test(line)) {
|
|
145
|
+
inSection = true;
|
|
146
|
+
sectionLevel = (line.match(/^#+/) || [""])[0].length;
|
|
147
|
+
sectionLines.push(line);
|
|
148
|
+
continue;
|
|
149
|
+
}
|
|
150
|
+
// Check for section end (next heading of same or higher level)
|
|
151
|
+
if (inSection) {
|
|
152
|
+
const headingMatch = line.match(/^(#+)\s/);
|
|
153
|
+
if (headingMatch && headingMatch[1].length <= sectionLevel) {
|
|
154
|
+
break;
|
|
155
|
+
}
|
|
156
|
+
sectionLines.push(line);
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
return sectionLines.length > 0 ? sectionLines.join("\n") : null;
|
|
160
|
+
}
|
|
161
|
+
/**
|
|
162
|
+
* Extract call path for a function from detailed section
|
|
163
|
+
*/
|
|
164
|
+
export function extractCallPath(markdown, functionName) {
|
|
165
|
+
// Look for call path in function details section
|
|
166
|
+
// Format: **Call path:** `handleHTTP` → `processRequest` → `parseBody` → `JSON.parse`
|
|
167
|
+
const escapedName = escapeRegex(functionName);
|
|
168
|
+
const section = extractSection(markdown, new RegExp(`###?\\s*\`?${escapedName}\`?`, "i"));
|
|
169
|
+
if (!section)
|
|
170
|
+
return undefined;
|
|
171
|
+
const normalized = section.replace(/\*\*/g, "");
|
|
172
|
+
const pathMatch = normalized.match(/Call path:\s*([^\n]+)/i);
|
|
173
|
+
if (!pathMatch)
|
|
174
|
+
return undefined;
|
|
175
|
+
// Parse path (split by → or ->)
|
|
176
|
+
const path = pathMatch[1]
|
|
177
|
+
.split(/\s*(?:→|->)\s*/)
|
|
178
|
+
.map((p) => p.replace(/`/g, "").trim())
|
|
179
|
+
.filter(Boolean);
|
|
180
|
+
return path.length > 0 ? path : undefined;
|
|
181
|
+
}
|
|
182
|
+
/**
|
|
183
|
+
* Extract callers of a function
|
|
184
|
+
*/
|
|
185
|
+
export function extractCallers(markdown, functionName) {
|
|
186
|
+
const escapedName = escapeRegex(functionName);
|
|
187
|
+
const section = extractSection(markdown, new RegExp(`###?\\s*\`?${escapedName}\`?`, "i"));
|
|
188
|
+
if (!section)
|
|
189
|
+
return undefined;
|
|
190
|
+
const normalized = section.replace(/\*\*/g, "");
|
|
191
|
+
const callersMatch = normalized.match(/Callers?:\s*([^\n]+)/i);
|
|
192
|
+
if (!callersMatch)
|
|
193
|
+
return undefined;
|
|
194
|
+
const callers = callersMatch[1]
|
|
195
|
+
.split(/[,;]/)
|
|
196
|
+
.map((c) => c.replace(/`/g, "").trim())
|
|
197
|
+
.filter(Boolean);
|
|
198
|
+
return callers.length > 0 ? callers : undefined;
|
|
199
|
+
}
|
|
200
|
+
/**
|
|
201
|
+
* Extract callees of a function
|
|
202
|
+
*/
|
|
203
|
+
export function extractCallees(markdown, functionName) {
|
|
204
|
+
const escapedName = escapeRegex(functionName);
|
|
205
|
+
const section = extractSection(markdown, new RegExp(`###?\\s*\`?${escapedName}\`?`, "i"));
|
|
206
|
+
if (!section)
|
|
207
|
+
return undefined;
|
|
208
|
+
const normalized = section.replace(/\*\*/g, "");
|
|
209
|
+
const calleesMatch = normalized.match(/Callees?:\s*([^\n]+)/i);
|
|
210
|
+
if (!calleesMatch)
|
|
211
|
+
return undefined;
|
|
212
|
+
const callees = calleesMatch[1]
|
|
213
|
+
.split(/[,;]/)
|
|
214
|
+
.map((c) => c.replace(/`/g, "").trim())
|
|
215
|
+
.filter(Boolean);
|
|
216
|
+
return callees.length > 0 ? callees : undefined;
|
|
217
|
+
}
|
|
218
|
+
/**
|
|
219
|
+
* Enrich hotspots with additional context from markdown
|
|
220
|
+
*/
|
|
221
|
+
export function enrichHotspots(hotspots, markdown) {
|
|
222
|
+
return hotspots.map((hotspot) => ({
|
|
223
|
+
...hotspot,
|
|
224
|
+
callPath: hotspot.callPath || extractCallPath(markdown, hotspot.function),
|
|
225
|
+
callers: hotspot.callers || extractCallers(markdown, hotspot.function),
|
|
226
|
+
callees: hotspot.callees || extractCallees(markdown, hotspot.function),
|
|
227
|
+
}));
|
|
228
|
+
}
|
|
229
|
+
/**
|
|
230
|
+
* Escape special regex characters in a string
|
|
231
|
+
*/
|
|
232
|
+
function escapeRegex(str) {
|
|
233
|
+
return str.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
234
|
+
}
|
|
235
|
+
//# sourceMappingURL=extract.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"extract.js","sourceRoot":"","sources":["../../src/convert/extract.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Convert module exports
|
|
3
|
+
*/
|
|
4
|
+
export { convertProfileToMarkdown, convertProfileFromPath, convertProfileFromBase64, type ConvertResult, type FullConvertOptions, } from "./converter.js";
|
|
5
|
+
export { sanitizeMarkdown, redactSecrets, normalizePaths, truncateSourceBlocks, truncateContent, cleanForLLM, generateSlug, type SanitizeOptions, } from "./sanitize.js";
|
|
6
|
+
export { extractProfileMeta, extractHotspots, extractCallPath, extractCallers, extractCallees, enrichHotspots, } from "./extract.js";
|
|
7
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/convert/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EACL,wBAAwB,EACxB,sBAAsB,EACtB,wBAAwB,EACxB,KAAK,aAAa,EAClB,KAAK,kBAAkB,GACxB,MAAM,gBAAgB,CAAC;AAExB,OAAO,EACL,gBAAgB,EAChB,aAAa,EACb,cAAc,EACd,oBAAoB,EACpB,eAAe,EACf,WAAW,EACX,YAAY,EACZ,KAAK,eAAe,GACrB,MAAM,eAAe,CAAC;AAEvB,OAAO,EACL,kBAAkB,EAClB,eAAe,EACf,eAAe,EACf,cAAc,EACd,cAAc,EACd,cAAc,GACf,MAAM,cAAc,CAAC"}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Convert module exports
|
|
3
|
+
*/
|
|
4
|
+
export { convertProfileToMarkdown, convertProfileFromPath, convertProfileFromBase64, } from "./converter.js";
|
|
5
|
+
export { sanitizeMarkdown, redactSecrets, normalizePaths, truncateSourceBlocks, truncateContent, cleanForLLM, generateSlug, } from "./sanitize.js";
|
|
6
|
+
export { extractProfileMeta, extractHotspots, extractCallPath, extractCallers, extractCallees, enrichHotspots, } from "./extract.js";
|
|
7
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/convert/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EACL,wBAAwB,EACxB,sBAAsB,EACtB,wBAAwB,GAGzB,MAAM,gBAAgB,CAAC;AAExB,OAAO,EACL,gBAAgB,EAChB,aAAa,EACb,cAAc,EACd,oBAAoB,EACpB,eAAe,EACf,WAAW,EACX,YAAY,GAEb,MAAM,eAAe,CAAC;AAEvB,OAAO,EACL,kBAAkB,EAClB,eAAe,EACf,eAAe,EACf,cAAc,EACd,cAAc,EACd,cAAc,GACf,MAAM,cAAc,CAAC"}
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Markdown sanitization and post-processing
|
|
3
|
+
*
|
|
4
|
+
* Handles:
|
|
5
|
+
* - Truncation to stay within token limits
|
|
6
|
+
* - Path redaction/normalization
|
|
7
|
+
* - Secret masking
|
|
8
|
+
* - Anchor stabilization
|
|
9
|
+
*/
|
|
10
|
+
export interface SanitizeOptions {
|
|
11
|
+
/** Maximum total characters */
|
|
12
|
+
maxChars?: number;
|
|
13
|
+
/** Maximum lines per source code block */
|
|
14
|
+
maxSourceLines?: number;
|
|
15
|
+
/** Base directory for path normalization */
|
|
16
|
+
baseDir?: string;
|
|
17
|
+
/** Redact sensitive patterns */
|
|
18
|
+
redactSecrets?: boolean;
|
|
19
|
+
/** Replace absolute paths with relative */
|
|
20
|
+
normalizePaths?: boolean;
|
|
21
|
+
/** Custom patterns to redact */
|
|
22
|
+
customRedactPatterns?: RegExp[];
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* Sanitize markdown content
|
|
26
|
+
*/
|
|
27
|
+
export declare function sanitizeMarkdown(markdown: string, options?: SanitizeOptions): string;
|
|
28
|
+
/**
|
|
29
|
+
* Redact sensitive information
|
|
30
|
+
*/
|
|
31
|
+
export declare function redactSecrets(content: string, customPatterns?: RegExp[]): string;
|
|
32
|
+
/**
|
|
33
|
+
* Convert absolute paths to relative paths
|
|
34
|
+
*/
|
|
35
|
+
export declare function normalizePaths(content: string, baseDir: string): string;
|
|
36
|
+
/**
|
|
37
|
+
* Truncate source code blocks to max lines
|
|
38
|
+
*/
|
|
39
|
+
export declare function truncateSourceBlocks(content: string, maxLines: number): string;
|
|
40
|
+
/**
|
|
41
|
+
* Truncate content to max characters, preserving structure
|
|
42
|
+
*/
|
|
43
|
+
export declare function truncateContent(content: string, maxChars: number): string;
|
|
44
|
+
/**
|
|
45
|
+
* Stabilize anchors for consistent cross-referencing
|
|
46
|
+
*/
|
|
47
|
+
export declare function stabilizeAnchors(content: string): string;
|
|
48
|
+
/**
|
|
49
|
+
* Generate a URL-safe slug from a string
|
|
50
|
+
*/
|
|
51
|
+
export declare function generateSlug(input: string): string;
|
|
52
|
+
/**
|
|
53
|
+
* Strip ANSI escape codes
|
|
54
|
+
*/
|
|
55
|
+
export declare function stripAnsi(content: string): string;
|
|
56
|
+
/**
|
|
57
|
+
* Clean up markdown for LLM consumption
|
|
58
|
+
*/
|
|
59
|
+
export declare function cleanForLLM(markdown: string): string;
|
|
60
|
+
//# sourceMappingURL=sanitize.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sanitize.d.ts","sourceRoot":"","sources":["../../src/convert/sanitize.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAIH,MAAM,WAAW,eAAe;IAC9B,+BAA+B;IAC/B,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,0CAA0C;IAC1C,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,4CAA4C;IAC5C,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,gCAAgC;IAChC,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB,2CAA2C;IAC3C,cAAc,CAAC,EAAE,OAAO,CAAC;IACzB,gCAAgC;IAChC,oBAAoB,CAAC,EAAE,MAAM,EAAE,CAAC;CACjC;AAgBD;;GAEG;AACH,wBAAgB,gBAAgB,CAC9B,QAAQ,EAAE,MAAM,EAChB,OAAO,GAAE,eAAoB,GAC5B,MAAM,CA2BR;AAED;;GAEG;AACH,wBAAgB,aAAa,CAC3B,OAAO,EAAE,MAAM,EACf,cAAc,GAAE,MAAM,EAAO,GAC5B,MAAM,CAUR;AAED;;GAEG;AACH,wBAAgB,cAAc,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,MAAM,CAkBvE;AAED;;GAEG;AACH,wBAAgB,oBAAoB,CAClC,OAAO,EAAE,MAAM,EACf,QAAQ,EAAE,MAAM,GACf,MAAM,CAcR;AAED;;GAEG;AACH,wBAAgB,eAAe,CAAC,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,MAAM,CA6BzE;AAED;;GAEG;AACH,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAQxD;AAED;;GAEG;AACH,wBAAgB,YAAY,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAQlD;AASD;;GAEG;AACH,wBAAgB,SAAS,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAGjD;AAED;;GAEG;AACH,wBAAgB,WAAW,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,CAapD"}
|