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.
Files changed (120) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +404 -0
  3. package/SKILL.md +238 -0
  4. package/dist/cli/init.d.ts +29 -0
  5. package/dist/cli/init.d.ts.map +1 -0
  6. package/dist/cli/init.js +139 -0
  7. package/dist/cli/init.js.map +1 -0
  8. package/dist/cli/main.d.ts +6 -0
  9. package/dist/cli/main.d.ts.map +1 -0
  10. package/dist/cli/main.js +389 -0
  11. package/dist/cli/main.js.map +1 -0
  12. package/dist/cli/options.d.ts +37 -0
  13. package/dist/cli/options.d.ts.map +1 -0
  14. package/dist/cli/options.js +54 -0
  15. package/dist/cli/options.js.map +1 -0
  16. package/dist/convert/converter.d.ts +39 -0
  17. package/dist/convert/converter.d.ts.map +1 -0
  18. package/dist/convert/converter.js +99 -0
  19. package/dist/convert/converter.js.map +1 -0
  20. package/dist/convert/extract.d.ts +32 -0
  21. package/dist/convert/extract.d.ts.map +1 -0
  22. package/dist/convert/extract.js +235 -0
  23. package/dist/convert/extract.js.map +1 -0
  24. package/dist/convert/index.d.ts +7 -0
  25. package/dist/convert/index.d.ts.map +1 -0
  26. package/dist/convert/index.js +7 -0
  27. package/dist/convert/index.js.map +1 -0
  28. package/dist/convert/sanitize.d.ts +60 -0
  29. package/dist/convert/sanitize.d.ts.map +1 -0
  30. package/dist/convert/sanitize.js +169 -0
  31. package/dist/convert/sanitize.js.map +1 -0
  32. package/dist/diff/engine.d.ts +76 -0
  33. package/dist/diff/engine.d.ts.map +1 -0
  34. package/dist/diff/engine.js +386 -0
  35. package/dist/diff/engine.js.map +1 -0
  36. package/dist/diff/index.d.ts +6 -0
  37. package/dist/diff/index.d.ts.map +1 -0
  38. package/dist/diff/index.js +6 -0
  39. package/dist/diff/index.js.map +1 -0
  40. package/dist/diff/markdown.d.ts +16 -0
  41. package/dist/diff/markdown.d.ts.map +1 -0
  42. package/dist/diff/markdown.js +342 -0
  43. package/dist/diff/markdown.js.map +1 -0
  44. package/dist/index.d.ts +52 -0
  45. package/dist/index.d.ts.map +1 -0
  46. package/dist/index.js +247 -0
  47. package/dist/index.js.map +1 -0
  48. package/dist/llm/client.d.ts +39 -0
  49. package/dist/llm/client.d.ts.map +1 -0
  50. package/dist/llm/client.js +270 -0
  51. package/dist/llm/client.js.map +1 -0
  52. package/dist/llm/index.d.ts +8 -0
  53. package/dist/llm/index.d.ts.map +1 -0
  54. package/dist/llm/index.js +8 -0
  55. package/dist/llm/index.js.map +1 -0
  56. package/dist/llm/prompt.d.ts +32 -0
  57. package/dist/llm/prompt.d.ts.map +1 -0
  58. package/dist/llm/prompt.js +146 -0
  59. package/dist/llm/prompt.js.map +1 -0
  60. package/dist/llm/schema.d.ts +150 -0
  61. package/dist/llm/schema.d.ts.map +1 -0
  62. package/dist/llm/schema.js +131 -0
  63. package/dist/llm/schema.js.map +1 -0
  64. package/dist/llm/validate.d.ts +33 -0
  65. package/dist/llm/validate.d.ts.map +1 -0
  66. package/dist/llm/validate.js +241 -0
  67. package/dist/llm/validate.js.map +1 -0
  68. package/dist/profile/duration.d.ts +2 -0
  69. package/dist/profile/duration.d.ts.map +1 -0
  70. package/dist/profile/duration.js +24 -0
  71. package/dist/profile/duration.js.map +1 -0
  72. package/dist/profile/preload.d.ts +2 -0
  73. package/dist/profile/preload.d.ts.map +1 -0
  74. package/dist/profile/preload.js +100 -0
  75. package/dist/profile/preload.js.map +1 -0
  76. package/dist/profile/runner.d.ts +22 -0
  77. package/dist/profile/runner.d.ts.map +1 -0
  78. package/dist/profile/runner.js +88 -0
  79. package/dist/profile/runner.js.map +1 -0
  80. package/dist/server/http.d.ts +27 -0
  81. package/dist/server/http.d.ts.map +1 -0
  82. package/dist/server/http.js +285 -0
  83. package/dist/server/http.js.map +1 -0
  84. package/dist/server/utils.d.ts +15 -0
  85. package/dist/server/utils.d.ts.map +1 -0
  86. package/dist/server/utils.js +71 -0
  87. package/dist/server/utils.js.map +1 -0
  88. package/dist/skill/handler.d.ts +77 -0
  89. package/dist/skill/handler.d.ts.map +1 -0
  90. package/dist/skill/handler.js +91 -0
  91. package/dist/skill/handler.js.map +1 -0
  92. package/dist/skill/index.d.ts +6 -0
  93. package/dist/skill/index.d.ts.map +1 -0
  94. package/dist/skill/index.js +6 -0
  95. package/dist/skill/index.js.map +1 -0
  96. package/dist/skill/manifest.d.ts +17 -0
  97. package/dist/skill/manifest.d.ts.map +1 -0
  98. package/dist/skill/manifest.js +231 -0
  99. package/dist/skill/manifest.js.map +1 -0
  100. package/dist/types.d.ts +260 -0
  101. package/dist/types.d.ts.map +1 -0
  102. package/dist/types.js +5 -0
  103. package/dist/types.js.map +1 -0
  104. package/dist/utils/fs.d.ts +52 -0
  105. package/dist/utils/fs.d.ts.map +1 -0
  106. package/dist/utils/fs.js +106 -0
  107. package/dist/utils/fs.js.map +1 -0
  108. package/dist/utils/index.d.ts +7 -0
  109. package/dist/utils/index.d.ts.map +1 -0
  110. package/dist/utils/index.js +7 -0
  111. package/dist/utils/index.js.map +1 -0
  112. package/dist/utils/limits.d.ts +38 -0
  113. package/dist/utils/limits.d.ts.map +1 -0
  114. package/dist/utils/limits.js +86 -0
  115. package/dist/utils/limits.js.map +1 -0
  116. package/dist/utils/logger.d.ts +21 -0
  117. package/dist/utils/logger.d.ts.map +1 -0
  118. package/dist/utils/logger.js +82 -0
  119. package/dist/utils/logger.js.map +1 -0
  120. 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"}