perf-skill 0.0.1 → 0.2.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 +414 -0
- package/SKILL.md +238 -0
- package/dist/cli/main.d.ts +6 -0
- package/dist/cli/main.d.ts.map +1 -0
- package/dist/cli/main.js +353 -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
package/dist/cli/main.js
ADDED
|
@@ -0,0 +1,353 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* perf-skill CLI - Analyze pprof profiles with AI assistance
|
|
4
|
+
*/
|
|
5
|
+
import { Command } from "commander";
|
|
6
|
+
import { writeFile } from "node:fs/promises";
|
|
7
|
+
import { join, parse, resolve } from "node:path";
|
|
8
|
+
import { analyze, diff } from "../index.js";
|
|
9
|
+
import { parseDurationInput, runCpuProfile } from "../profile/runner.js";
|
|
10
|
+
import { setLogLevel } from "../utils/logger.js";
|
|
11
|
+
import { validateProfileExtension } from "../utils/limits.js";
|
|
12
|
+
import { buildAnalyzeOptions, buildConvertOptions, buildDiffOptions, } from "./options.js";
|
|
13
|
+
const program = new Command();
|
|
14
|
+
program
|
|
15
|
+
.name("perf-skill")
|
|
16
|
+
.description("Analyze pprof profiles with AI-powered recommendations")
|
|
17
|
+
.version("1.0.0");
|
|
18
|
+
function parseOptionalInt(value) {
|
|
19
|
+
if (value === undefined)
|
|
20
|
+
return undefined;
|
|
21
|
+
const parsed = Number.parseInt(value, 10);
|
|
22
|
+
return Number.isFinite(parsed) ? parsed : undefined;
|
|
23
|
+
}
|
|
24
|
+
function deriveSiblingPath(basePath, suffix, defaultExt) {
|
|
25
|
+
const parsed = parse(basePath);
|
|
26
|
+
const ext = parsed.ext || defaultExt;
|
|
27
|
+
const name = parsed.ext ? parsed.name : parsed.base;
|
|
28
|
+
const filename = `${name}.${suffix}${ext}`;
|
|
29
|
+
return parsed.dir ? join(parsed.dir, filename) : filename;
|
|
30
|
+
}
|
|
31
|
+
async function executeAnalyze(profilePath, opts) {
|
|
32
|
+
if (opts.verbose) {
|
|
33
|
+
setLogLevel("debug");
|
|
34
|
+
}
|
|
35
|
+
const resolvedPath = resolve(profilePath);
|
|
36
|
+
validateProfileExtension(resolvedPath);
|
|
37
|
+
const options = buildAnalyzeOptions(opts);
|
|
38
|
+
if (opts.llmProvider || opts.llmModel) {
|
|
39
|
+
options.llm = {
|
|
40
|
+
provider: opts.llmProvider ?? "openai",
|
|
41
|
+
model: opts.llmModel || "gpt-5.2",
|
|
42
|
+
};
|
|
43
|
+
}
|
|
44
|
+
console.log(`Analyzing ${profilePath}...`);
|
|
45
|
+
const result = await analyze(resolvedPath, options);
|
|
46
|
+
if (opts.output) {
|
|
47
|
+
await writeFile(opts.output, result.markdown, "utf-8");
|
|
48
|
+
console.log(`Markdown saved to ${opts.output}`);
|
|
49
|
+
}
|
|
50
|
+
else {
|
|
51
|
+
console.log("\n" + result.markdown);
|
|
52
|
+
}
|
|
53
|
+
if (opts.json) {
|
|
54
|
+
const jsonResult = {
|
|
55
|
+
profileMeta: result.profileMeta,
|
|
56
|
+
hotspots: result.hotspots,
|
|
57
|
+
recommendations: result.recommendations,
|
|
58
|
+
nextSteps: result.nextSteps,
|
|
59
|
+
metrics: result.metrics,
|
|
60
|
+
};
|
|
61
|
+
await writeFile(opts.json, JSON.stringify(jsonResult, null, 2), "utf-8");
|
|
62
|
+
console.log(`JSON saved to ${opts.json}`);
|
|
63
|
+
}
|
|
64
|
+
if (opts.output) {
|
|
65
|
+
console.log(`\nFound ${result.hotspots.length} hotspots`);
|
|
66
|
+
if (result.recommendations) {
|
|
67
|
+
console.log(`Generated ${result.recommendations.length} recommendations`);
|
|
68
|
+
}
|
|
69
|
+
if (result.metrics) {
|
|
70
|
+
console.log(`Processing time: ${result.metrics.totalMs.toFixed(0)}ms`);
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
// Analyze command (default)
|
|
75
|
+
program
|
|
76
|
+
.command("analyze", { isDefault: true })
|
|
77
|
+
.description("Analyze a single pprof profile")
|
|
78
|
+
.argument("<profile>", "Path to pprof profile (.pb.gz)")
|
|
79
|
+
.option("-f, --format <format>", "Output format: summary, detailed, adaptive", "adaptive")
|
|
80
|
+
.option("-t, --type <type>", "Profile type: cpu, heap, auto", "auto")
|
|
81
|
+
.option("-o, --output <file>", "Output markdown file")
|
|
82
|
+
.option("-j, --json <file>", "Output JSON results file")
|
|
83
|
+
.option("-s, --source-dir <path>", "Source directory for code context")
|
|
84
|
+
.option("--no-source", "Disable source code inclusion")
|
|
85
|
+
.option("--max-hotspots <n>", "Maximum hotspots to show", "10")
|
|
86
|
+
.option("-m, --mode <mode>", "Mode: convert-only, analyze", "analyze")
|
|
87
|
+
.option("--llm-provider <provider>", "LLM provider: openai, azure-openai, anthropic, custom")
|
|
88
|
+
.option("--llm-model <model>", "LLM model name")
|
|
89
|
+
.option("--service <name>", "Service name for context")
|
|
90
|
+
.option("--scenario <desc>", "Scenario description")
|
|
91
|
+
.option("--slo <target>", "Target SLO")
|
|
92
|
+
.option("--no-redact", "Disable redaction of sensitive information")
|
|
93
|
+
.option("-v, --verbose", "Enable verbose logging")
|
|
94
|
+
.action(async (profilePath, opts) => {
|
|
95
|
+
try {
|
|
96
|
+
await executeAnalyze(profilePath, opts);
|
|
97
|
+
}
|
|
98
|
+
catch (error) {
|
|
99
|
+
console.error("Error:", error instanceof Error ? error.message : error);
|
|
100
|
+
process.exit(1);
|
|
101
|
+
}
|
|
102
|
+
});
|
|
103
|
+
// Run command (profile + analyze)
|
|
104
|
+
program
|
|
105
|
+
.command("run")
|
|
106
|
+
.description("Profile a Node entry file and analyze the resulting CPU profile")
|
|
107
|
+
.argument("<entry>", "Entry file to run (js/mjs/cjs)")
|
|
108
|
+
.argument("[entryArgs...]", "Arguments passed to the entry file")
|
|
109
|
+
.option("-d, --duration <duration>", "CPU profile duration (e.g. 10s, 5000ms)", "10s")
|
|
110
|
+
.option("--profile-out <file>", "Profile output file", "cpu.pb.gz")
|
|
111
|
+
.option("--heap", "Also capture a heap profile")
|
|
112
|
+
.option("--heap-profile-out <file>", "Heap profile output file", "heap.pb.gz")
|
|
113
|
+
.option("--heap-interval-bytes <n>", "Heap sampling interval in bytes")
|
|
114
|
+
.option("--heap-stack-depth <n>", "Heap sampling stack depth")
|
|
115
|
+
.option("--heap-output <file>", "Heap markdown output file")
|
|
116
|
+
.option("--heap-json <file>", "Heap JSON output file")
|
|
117
|
+
.option("-f, --format <format>", "Output format: summary, detailed, adaptive", "adaptive")
|
|
118
|
+
.option("-t, --type <type>", "Profile type: cpu, heap, auto", "auto")
|
|
119
|
+
.option("-o, --output <file>", "Output markdown file")
|
|
120
|
+
.option("-j, --json <file>", "Output JSON results file")
|
|
121
|
+
.option("-s, --source-dir <path>", "Source directory for code context")
|
|
122
|
+
.option("--no-source", "Disable source code inclusion")
|
|
123
|
+
.option("--max-hotspots <n>", "Maximum hotspots to show", "10")
|
|
124
|
+
.option("-m, --mode <mode>", "Mode: convert-only, analyze", "analyze")
|
|
125
|
+
.option("--llm-provider <provider>", "LLM provider: openai, azure-openai, anthropic, custom")
|
|
126
|
+
.option("--llm-model <model>", "LLM model name")
|
|
127
|
+
.option("--service <name>", "Service name for context")
|
|
128
|
+
.option("--scenario <desc>", "Scenario description")
|
|
129
|
+
.option("--slo <target>", "Target SLO")
|
|
130
|
+
.option("--no-redact", "Disable redaction of sensitive information")
|
|
131
|
+
.option("-v, --verbose", "Enable verbose logging")
|
|
132
|
+
.action(async (entryPath, entryArgs, opts) => {
|
|
133
|
+
try {
|
|
134
|
+
if (opts.verbose) {
|
|
135
|
+
setLogLevel("debug");
|
|
136
|
+
}
|
|
137
|
+
const durationMs = parseDurationInput(opts.duration);
|
|
138
|
+
const profilePath = resolve(opts.profileOut);
|
|
139
|
+
const heapEnabled = Boolean(opts.heap);
|
|
140
|
+
const heapIntervalBytes = parseOptionalInt(opts.heapIntervalBytes);
|
|
141
|
+
const heapStackDepth = parseOptionalInt(opts.heapStackDepth);
|
|
142
|
+
const cpuOutput = opts.output ?? (heapEnabled ? "cpu.md" : undefined);
|
|
143
|
+
const cpuJson = opts.json;
|
|
144
|
+
const heapOutput = heapEnabled
|
|
145
|
+
? opts.heapOutput ?? (opts.output ? deriveSiblingPath(opts.output, "heap", ".md") : "heap.md")
|
|
146
|
+
: undefined;
|
|
147
|
+
const heapJson = heapEnabled
|
|
148
|
+
? opts.heapJson ?? (cpuJson ? deriveSiblingPath(cpuJson, "heap", ".json") : undefined)
|
|
149
|
+
: undefined;
|
|
150
|
+
console.log(`Profiling ${entryPath} for ${opts.duration}...`);
|
|
151
|
+
const { heapProfilePath } = await runCpuProfile({
|
|
152
|
+
entryPath,
|
|
153
|
+
entryArgs,
|
|
154
|
+
durationMs,
|
|
155
|
+
outPath: profilePath,
|
|
156
|
+
enableHeap: heapEnabled,
|
|
157
|
+
heapOutPath: heapEnabled ? resolve(opts.heapProfileOut) : undefined,
|
|
158
|
+
heapIntervalBytes,
|
|
159
|
+
heapStackDepth,
|
|
160
|
+
});
|
|
161
|
+
await executeAnalyze(profilePath, { ...opts, output: cpuOutput, json: cpuJson, type: "cpu" });
|
|
162
|
+
if (heapEnabled && heapProfilePath) {
|
|
163
|
+
await executeAnalyze(heapProfilePath, { ...opts, output: heapOutput, json: heapJson, type: "heap" });
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
catch (error) {
|
|
167
|
+
console.error("Error:", error instanceof Error ? error.message : error);
|
|
168
|
+
process.exit(1);
|
|
169
|
+
}
|
|
170
|
+
});
|
|
171
|
+
// Profile-only command
|
|
172
|
+
program
|
|
173
|
+
.command("profile")
|
|
174
|
+
.description("Generate a CPU profile for a Node entry file")
|
|
175
|
+
.argument("<entry>", "Entry file to run (js/mjs/cjs)")
|
|
176
|
+
.argument("[entryArgs...]", "Arguments passed to the entry file")
|
|
177
|
+
.option("-d, --duration <duration>", "CPU profile duration (e.g. 10s, 5000ms)", "10s")
|
|
178
|
+
.option("-o, --output <file>", "Profile output file", "cpu.pb.gz")
|
|
179
|
+
.option("--heap", "Also capture a heap profile")
|
|
180
|
+
.option("--heap-profile-out <file>", "Heap profile output file", "heap.pb.gz")
|
|
181
|
+
.option("--heap-interval-bytes <n>", "Heap sampling interval in bytes")
|
|
182
|
+
.option("--heap-stack-depth <n>", "Heap sampling stack depth")
|
|
183
|
+
.option("-v, --verbose", "Enable verbose logging")
|
|
184
|
+
.action(async (entryPath, entryArgs, opts) => {
|
|
185
|
+
if (opts.verbose) {
|
|
186
|
+
setLogLevel("debug");
|
|
187
|
+
}
|
|
188
|
+
try {
|
|
189
|
+
const durationMs = parseDurationInput(opts.duration);
|
|
190
|
+
const profilePath = resolve(opts.output);
|
|
191
|
+
const heapEnabled = Boolean(opts.heap);
|
|
192
|
+
const heapIntervalBytes = parseOptionalInt(opts.heapIntervalBytes);
|
|
193
|
+
const heapStackDepth = parseOptionalInt(opts.heapStackDepth);
|
|
194
|
+
console.log(`Profiling ${entryPath} for ${opts.duration}...`);
|
|
195
|
+
const { heapProfilePath } = await runCpuProfile({
|
|
196
|
+
entryPath,
|
|
197
|
+
entryArgs,
|
|
198
|
+
durationMs,
|
|
199
|
+
outPath: profilePath,
|
|
200
|
+
enableHeap: heapEnabled,
|
|
201
|
+
heapOutPath: heapEnabled ? resolve(opts.heapProfileOut) : undefined,
|
|
202
|
+
heapIntervalBytes,
|
|
203
|
+
heapStackDepth,
|
|
204
|
+
});
|
|
205
|
+
console.log(`Profile saved to ${profilePath}`);
|
|
206
|
+
if (heapEnabled && heapProfilePath) {
|
|
207
|
+
console.log(`Heap profile saved to ${heapProfilePath}`);
|
|
208
|
+
}
|
|
209
|
+
}
|
|
210
|
+
catch (error) {
|
|
211
|
+
console.error("Error:", error instanceof Error ? error.message : error);
|
|
212
|
+
process.exit(1);
|
|
213
|
+
}
|
|
214
|
+
});
|
|
215
|
+
// Diff command
|
|
216
|
+
program
|
|
217
|
+
.command("diff")
|
|
218
|
+
.description("Compare two pprof profiles")
|
|
219
|
+
.argument("<base>", "Path to base profile (.pb.gz)")
|
|
220
|
+
.argument("<current>", "Path to current profile (.pb.gz)")
|
|
221
|
+
.option("-f, --format <format>", "Output format: diff-summary, diff-detailed, diff-adaptive", "diff-adaptive")
|
|
222
|
+
.option("-o, --output <file>", "Output markdown file")
|
|
223
|
+
.option("-j, --json <file>", "Output JSON results file")
|
|
224
|
+
.option("-n, --normalize <mode>", "Normalize mode: none, scale-to-base-total, per-second", "scale-to-base-total")
|
|
225
|
+
.option("--max-regressions <n>", "Maximum regressions to show", "10")
|
|
226
|
+
.option("--max-improvements <n>", "Maximum improvements to show", "5")
|
|
227
|
+
.option("--max-decompressed-bytes <n>", "Maximum decompressed profile size in bytes")
|
|
228
|
+
.option("-m, --mode <mode>", "Mode: convert-only, analyze", "convert-only")
|
|
229
|
+
.option("--llm-provider <provider>", "LLM provider for analysis")
|
|
230
|
+
.option("--llm-model <model>", "LLM model name")
|
|
231
|
+
.option("--service <name>", "Service name for context")
|
|
232
|
+
.option("--changes <desc>", "Recent changes description")
|
|
233
|
+
.option("-v, --verbose", "Enable verbose logging")
|
|
234
|
+
.action(async (basePath, currentPath, opts) => {
|
|
235
|
+
if (opts.verbose) {
|
|
236
|
+
setLogLevel("debug");
|
|
237
|
+
}
|
|
238
|
+
try {
|
|
239
|
+
const resolvedBase = resolve(basePath);
|
|
240
|
+
const resolvedCurrent = resolve(currentPath);
|
|
241
|
+
validateProfileExtension(resolvedBase);
|
|
242
|
+
validateProfileExtension(resolvedCurrent);
|
|
243
|
+
const options = buildDiffOptions(opts);
|
|
244
|
+
console.log(`Comparing ${basePath} vs ${currentPath}...`);
|
|
245
|
+
const result = await diff(resolvedBase, resolvedCurrent, options);
|
|
246
|
+
// Output markdown
|
|
247
|
+
if (opts.output) {
|
|
248
|
+
await writeFile(opts.output, result.markdown, "utf-8");
|
|
249
|
+
console.log(`Markdown saved to ${opts.output}`);
|
|
250
|
+
}
|
|
251
|
+
else {
|
|
252
|
+
console.log("\n" + result.markdown);
|
|
253
|
+
}
|
|
254
|
+
// Output JSON
|
|
255
|
+
if (opts.json) {
|
|
256
|
+
const jsonResult = {
|
|
257
|
+
baseMeta: result.baseMeta,
|
|
258
|
+
currentMeta: result.currentMeta,
|
|
259
|
+
regressions: result.regressions,
|
|
260
|
+
improvements: result.improvements,
|
|
261
|
+
summary: result.summary,
|
|
262
|
+
recommendations: result.recommendations,
|
|
263
|
+
metrics: result.metrics,
|
|
264
|
+
};
|
|
265
|
+
await writeFile(opts.json, JSON.stringify(jsonResult, null, 2), "utf-8");
|
|
266
|
+
console.log(`JSON saved to ${opts.json}`);
|
|
267
|
+
}
|
|
268
|
+
// Print summary to stderr if outputting to file
|
|
269
|
+
if (opts.output) {
|
|
270
|
+
console.log(`\nFound ${result.regressions.length} regressions, ${result.improvements.length} improvements`);
|
|
271
|
+
}
|
|
272
|
+
}
|
|
273
|
+
catch (error) {
|
|
274
|
+
console.error("Error:", error instanceof Error ? error.message : error);
|
|
275
|
+
process.exit(1);
|
|
276
|
+
}
|
|
277
|
+
});
|
|
278
|
+
// Convert command (no LLM)
|
|
279
|
+
program
|
|
280
|
+
.command("convert")
|
|
281
|
+
.description("Convert pprof profile to markdown (no AI analysis)")
|
|
282
|
+
.argument("<profile>", "Path to pprof profile (.pb.gz)")
|
|
283
|
+
.option("-f, --format <format>", "Output format: summary, detailed, adaptive", "adaptive")
|
|
284
|
+
.option("-t, --type <type>", "Profile type: cpu, heap, auto", "auto")
|
|
285
|
+
.option("-o, --output <file>", "Output markdown file")
|
|
286
|
+
.option("-s, --source-dir <path>", "Source directory for code context")
|
|
287
|
+
.option("--no-source", "Disable source code inclusion")
|
|
288
|
+
.option("--max-hotspots <n>", "Maximum hotspots to show", "10")
|
|
289
|
+
.option("--no-redact", "Disable redaction of sensitive information")
|
|
290
|
+
.option("-v, --verbose", "Enable verbose logging")
|
|
291
|
+
.action(async (profilePath, opts) => {
|
|
292
|
+
if (opts.verbose) {
|
|
293
|
+
setLogLevel("debug");
|
|
294
|
+
}
|
|
295
|
+
try {
|
|
296
|
+
const resolvedPath = resolve(profilePath);
|
|
297
|
+
validateProfileExtension(resolvedPath);
|
|
298
|
+
const options = buildConvertOptions(opts);
|
|
299
|
+
console.log(`Converting ${profilePath}...`);
|
|
300
|
+
const result = await analyze(resolvedPath, options);
|
|
301
|
+
if (opts.output) {
|
|
302
|
+
await writeFile(opts.output, result.markdown, "utf-8");
|
|
303
|
+
console.log(`Markdown saved to ${opts.output}`);
|
|
304
|
+
}
|
|
305
|
+
else {
|
|
306
|
+
console.log("\n" + result.markdown);
|
|
307
|
+
}
|
|
308
|
+
}
|
|
309
|
+
catch (error) {
|
|
310
|
+
console.error("Error:", error instanceof Error ? error.message : error);
|
|
311
|
+
process.exit(1);
|
|
312
|
+
}
|
|
313
|
+
});
|
|
314
|
+
// Server command
|
|
315
|
+
program
|
|
316
|
+
.command("server")
|
|
317
|
+
.description("Start HTTP API server")
|
|
318
|
+
.option("-p, --port <port>", "Port to listen on", "3000")
|
|
319
|
+
.option("-h, --host <host>", "Host to bind to", "0.0.0.0")
|
|
320
|
+
.option("--cors", "Enable CORS")
|
|
321
|
+
.option("--no-cors", "Disable CORS")
|
|
322
|
+
.option("--cors-origin <origin>", "CORS origin(s), comma-separated or '*'")
|
|
323
|
+
.option("--helmet", "Enable helmet security headers")
|
|
324
|
+
.option("--no-helmet", "Disable helmet security headers")
|
|
325
|
+
.option("--rate-limit", "Enable rate limiting")
|
|
326
|
+
.option("--no-rate-limit", "Disable rate limiting")
|
|
327
|
+
.option("--rate-limit-max <n>", "Rate limit max requests per window")
|
|
328
|
+
.option("--rate-limit-window-ms <ms>", "Rate limit window in ms")
|
|
329
|
+
.option("-v, --verbose", "Enable verbose logging")
|
|
330
|
+
.action(async (opts) => {
|
|
331
|
+
if (opts.verbose) {
|
|
332
|
+
setLogLevel("debug");
|
|
333
|
+
}
|
|
334
|
+
try {
|
|
335
|
+
const { startServer } = await import("../server/http.js");
|
|
336
|
+
await startServer({
|
|
337
|
+
port: parseInt(opts.port, 10),
|
|
338
|
+
host: opts.host,
|
|
339
|
+
enableCors: opts.cors,
|
|
340
|
+
corsOrigin: opts.corsOrigin,
|
|
341
|
+
enableHelmet: opts.helmet,
|
|
342
|
+
enableRateLimit: opts.rateLimit,
|
|
343
|
+
rateLimitMax: opts.rateLimitMax ? parseInt(opts.rateLimitMax, 10) : undefined,
|
|
344
|
+
rateLimitWindowMs: opts.rateLimitWindowMs ? parseInt(opts.rateLimitWindowMs, 10) : undefined,
|
|
345
|
+
});
|
|
346
|
+
}
|
|
347
|
+
catch (error) {
|
|
348
|
+
console.error("Error:", error instanceof Error ? error.message : error);
|
|
349
|
+
process.exit(1);
|
|
350
|
+
}
|
|
351
|
+
});
|
|
352
|
+
program.parse();
|
|
353
|
+
//# sourceMappingURL=main.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"main.js","sourceRoot":"","sources":["../../src/cli/main.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* CLI option builders (pure helpers for testing)
|
|
3
|
+
*/
|
|
4
|
+
import type { AnalyzeOptions, DiffOptions, LLMConfig } from "../types.js";
|
|
5
|
+
export interface AnalyzeCommandOptions {
|
|
6
|
+
format: AnalyzeOptions["format"];
|
|
7
|
+
type: AnalyzeOptions["profileType"];
|
|
8
|
+
maxHotspots: string;
|
|
9
|
+
sourceDir?: string;
|
|
10
|
+
source?: boolean;
|
|
11
|
+
mode: AnalyzeOptions["mode"];
|
|
12
|
+
redact: boolean;
|
|
13
|
+
service?: string;
|
|
14
|
+
scenario?: string;
|
|
15
|
+
slo?: string;
|
|
16
|
+
llmProvider?: LLMConfig["provider"];
|
|
17
|
+
llmModel?: string;
|
|
18
|
+
}
|
|
19
|
+
export interface ConvertCommandOptions {
|
|
20
|
+
format: AnalyzeOptions["format"];
|
|
21
|
+
type: AnalyzeOptions["profileType"];
|
|
22
|
+
maxHotspots: string;
|
|
23
|
+
sourceDir?: string;
|
|
24
|
+
source?: boolean;
|
|
25
|
+
redact: boolean;
|
|
26
|
+
}
|
|
27
|
+
export interface DiffCommandOptions {
|
|
28
|
+
format: DiffOptions["format"];
|
|
29
|
+
normalize: DiffOptions["normalize"];
|
|
30
|
+
maxRegressions: string;
|
|
31
|
+
maxImprovements: string;
|
|
32
|
+
maxDecompressedBytes?: string;
|
|
33
|
+
}
|
|
34
|
+
export declare function buildAnalyzeOptions(opts: AnalyzeCommandOptions): AnalyzeOptions;
|
|
35
|
+
export declare function buildConvertOptions(opts: ConvertCommandOptions): AnalyzeOptions;
|
|
36
|
+
export declare function buildDiffOptions(opts: DiffCommandOptions): DiffOptions;
|
|
37
|
+
//# sourceMappingURL=options.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"options.d.ts","sourceRoot":"","sources":["../../src/cli/options.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,KAAK,EAAE,cAAc,EAAE,WAAW,EAAE,SAAS,EAAkB,MAAM,aAAa,CAAC;AAE1F,MAAM,WAAW,qBAAqB;IACpC,MAAM,EAAE,cAAc,CAAC,QAAQ,CAAC,CAAC;IACjC,IAAI,EAAE,cAAc,CAAC,aAAa,CAAC,CAAC;IACpC,WAAW,EAAE,MAAM,CAAC;IACpB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,IAAI,EAAE,cAAc,CAAC,MAAM,CAAC,CAAC;IAC7B,MAAM,EAAE,OAAO,CAAC;IAChB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,WAAW,CAAC,EAAE,SAAS,CAAC,UAAU,CAAC,CAAC;IACpC,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,qBAAqB;IACpC,MAAM,EAAE,cAAc,CAAC,QAAQ,CAAC,CAAC;IACjC,IAAI,EAAE,cAAc,CAAC,aAAa,CAAC,CAAC;IACpC,WAAW,EAAE,MAAM,CAAC;IACpB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,MAAM,EAAE,OAAO,CAAC;CACjB;AAED,MAAM,WAAW,kBAAkB;IACjC,MAAM,EAAE,WAAW,CAAC,QAAQ,CAAC,CAAC;IAC9B,SAAS,EAAE,WAAW,CAAC,WAAW,CAAC,CAAC;IACpC,cAAc,EAAE,MAAM,CAAC;IACvB,eAAe,EAAE,MAAM,CAAC;IACxB,oBAAoB,CAAC,EAAE,MAAM,CAAC;CAC/B;AAgBD,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,qBAAqB,GAAG,cAAc,CAe/E;AAED,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,qBAAqB,GAAG,cAAc,CAU/E;AAED,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,kBAAkB,GAAG,WAAW,CAStE"}
|
|
@@ -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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"}
|