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
package/dist/utils/fs.js
ADDED
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* File system utilities for temporary file management
|
|
3
|
+
*/
|
|
4
|
+
import { writeFile, rm, readFile, mkdir } from "node:fs/promises";
|
|
5
|
+
import { tmpdir } from "node:os";
|
|
6
|
+
import { join, dirname } from "node:path";
|
|
7
|
+
import { randomUUID } from "node:crypto";
|
|
8
|
+
import { gunzipSync, gzipSync } from "node:zlib";
|
|
9
|
+
import { isGzip } from "./limits.js";
|
|
10
|
+
/**
|
|
11
|
+
* Generate a unique temporary file path
|
|
12
|
+
*/
|
|
13
|
+
export function getTempPath(prefix = "pprof", ext = ".pb.gz") {
|
|
14
|
+
return join(tmpdir(), `${prefix}-${randomUUID()}${ext}`);
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* Write data to a temporary file and return the path
|
|
18
|
+
*/
|
|
19
|
+
export async function writeToTemp(data, prefix = "pprof", ext = ".pb.gz") {
|
|
20
|
+
const tempPath = getTempPath(prefix, ext);
|
|
21
|
+
await writeFile(tempPath, data);
|
|
22
|
+
return tempPath;
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* Safely remove a file (ignores errors)
|
|
26
|
+
*/
|
|
27
|
+
export async function safeRemove(path) {
|
|
28
|
+
try {
|
|
29
|
+
await rm(path, { force: true });
|
|
30
|
+
}
|
|
31
|
+
catch {
|
|
32
|
+
// Ignore removal errors
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* Execute a function with a temporary file, ensuring cleanup
|
|
37
|
+
*/
|
|
38
|
+
export async function withTempFile(data, fn, prefix = "pprof", ext = ".pb.gz") {
|
|
39
|
+
const tempPath = await writeToTemp(data, prefix, ext);
|
|
40
|
+
try {
|
|
41
|
+
return await fn(tempPath);
|
|
42
|
+
}
|
|
43
|
+
finally {
|
|
44
|
+
await safeRemove(tempPath);
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* Read and decompress a gzipped file
|
|
49
|
+
*/
|
|
50
|
+
export async function readGzipFile(path, maxOutputBytes) {
|
|
51
|
+
const data = await readFile(path);
|
|
52
|
+
return decompressIfNeeded(data, maxOutputBytes);
|
|
53
|
+
}
|
|
54
|
+
/**
|
|
55
|
+
* Decompress data if gzipped
|
|
56
|
+
*/
|
|
57
|
+
export function decompressIfNeeded(data, maxOutputBytes) {
|
|
58
|
+
if (isGzip(data)) {
|
|
59
|
+
if (maxOutputBytes) {
|
|
60
|
+
return gunzipSync(data, { maxOutputLength: maxOutputBytes });
|
|
61
|
+
}
|
|
62
|
+
return gunzipSync(data);
|
|
63
|
+
}
|
|
64
|
+
return Buffer.from(data);
|
|
65
|
+
}
|
|
66
|
+
/**
|
|
67
|
+
* Compress data with gzip
|
|
68
|
+
*/
|
|
69
|
+
export function compressGzip(data) {
|
|
70
|
+
return gzipSync(data);
|
|
71
|
+
}
|
|
72
|
+
/**
|
|
73
|
+
* Pick a profile file extension based on compression
|
|
74
|
+
*/
|
|
75
|
+
export function getProfileExtension(data) {
|
|
76
|
+
return isGzip(data) ? ".pb.gz" : ".pb";
|
|
77
|
+
}
|
|
78
|
+
/**
|
|
79
|
+
* Ensure directory exists
|
|
80
|
+
*/
|
|
81
|
+
export async function ensureDir(path) {
|
|
82
|
+
const dir = dirname(path);
|
|
83
|
+
await mkdir(dir, { recursive: true });
|
|
84
|
+
}
|
|
85
|
+
/**
|
|
86
|
+
* Convert base64 to Buffer
|
|
87
|
+
*/
|
|
88
|
+
export function base64ToBuffer(base64) {
|
|
89
|
+
return Buffer.from(base64, "base64");
|
|
90
|
+
}
|
|
91
|
+
/**
|
|
92
|
+
* Convert Buffer to base64
|
|
93
|
+
*/
|
|
94
|
+
export function bufferToBase64(buffer) {
|
|
95
|
+
return Buffer.from(buffer).toString("base64");
|
|
96
|
+
}
|
|
97
|
+
/**
|
|
98
|
+
* Load profile from path or base64
|
|
99
|
+
*/
|
|
100
|
+
export async function loadProfile(input, encoding = "path") {
|
|
101
|
+
if (encoding === "base64") {
|
|
102
|
+
return base64ToBuffer(input);
|
|
103
|
+
}
|
|
104
|
+
return readFile(input);
|
|
105
|
+
}
|
|
106
|
+
//# sourceMappingURL=fs.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"fs.js","sourceRoot":"","sources":["../../src/utils/fs.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Utilities module exports
|
|
3
|
+
*/
|
|
4
|
+
export { logger, setLogLevel, type LogLevel, } from "./logger.js";
|
|
5
|
+
export { DEFAULT_LIMITS, resolveLimits, checkSizeLimit, checkCharLimit, formatBytes, formatDuration, withTimeout, isGzip, validateProfileExtension, } from "./limits.js";
|
|
6
|
+
export { getTempPath, writeToTemp, safeRemove, withTempFile, readGzipFile, decompressIfNeeded, compressGzip, getProfileExtension, ensureDir, base64ToBuffer, bufferToBase64, loadProfile, } from "./fs.js";
|
|
7
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/utils/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EACL,MAAM,EACN,WAAW,EACX,KAAK,QAAQ,GACd,MAAM,aAAa,CAAC;AAErB,OAAO,EACL,cAAc,EACd,aAAa,EACb,cAAc,EACd,cAAc,EACd,WAAW,EACX,cAAc,EACd,WAAW,EACX,MAAM,EACN,wBAAwB,GACzB,MAAM,aAAa,CAAC;AAErB,OAAO,EACL,WAAW,EACX,WAAW,EACX,UAAU,EACV,YAAY,EACZ,YAAY,EACZ,kBAAkB,EAClB,YAAY,EACZ,mBAAmB,EACnB,SAAS,EACT,cAAc,EACd,cAAc,EACd,WAAW,GACZ,MAAM,SAAS,CAAC"}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Utilities module exports
|
|
3
|
+
*/
|
|
4
|
+
export { logger, setLogLevel, } from "./logger.js";
|
|
5
|
+
export { DEFAULT_LIMITS, resolveLimits, checkSizeLimit, checkCharLimit, formatBytes, formatDuration, withTimeout, isGzip, validateProfileExtension, } from "./limits.js";
|
|
6
|
+
export { getTempPath, writeToTemp, safeRemove, withTempFile, readGzipFile, decompressIfNeeded, compressGzip, getProfileExtension, ensureDir, base64ToBuffer, bufferToBase64, loadProfile, } from "./fs.js";
|
|
7
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/utils/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EACL,MAAM,EACN,WAAW,GAEZ,MAAM,aAAa,CAAC;AAErB,OAAO,EACL,cAAc,EACd,aAAa,EACb,cAAc,EACd,cAAc,EACd,WAAW,EACX,cAAc,EACd,WAAW,EACX,MAAM,EACN,wBAAwB,GACzB,MAAM,aAAa,CAAC;AAErB,OAAO,EACL,WAAW,EACX,WAAW,EACX,UAAU,EACV,YAAY,EACZ,YAAY,EACZ,kBAAkB,EAClB,YAAY,EACZ,mBAAmB,EACnB,SAAS,EACT,cAAc,EACd,cAAc,EACd,WAAW,GACZ,MAAM,SAAS,CAAC"}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Resource limits and validation
|
|
3
|
+
*/
|
|
4
|
+
import type { ResourceLimits } from "../types.js";
|
|
5
|
+
export declare const DEFAULT_LIMITS: Required<ResourceLimits>;
|
|
6
|
+
/**
|
|
7
|
+
* Merge user limits with defaults
|
|
8
|
+
*/
|
|
9
|
+
export declare function resolveLimits(userLimits?: ResourceLimits): Required<ResourceLimits>;
|
|
10
|
+
/**
|
|
11
|
+
* Check if a buffer exceeds size limit
|
|
12
|
+
*/
|
|
13
|
+
export declare function checkSizeLimit(data: Uint8Array | Buffer, maxBytes: number, label?: string): void;
|
|
14
|
+
/**
|
|
15
|
+
* Check if content exceeds character limit
|
|
16
|
+
*/
|
|
17
|
+
export declare function checkCharLimit(content: string, maxChars: number, label?: string): void;
|
|
18
|
+
/**
|
|
19
|
+
* Format bytes to human-readable string
|
|
20
|
+
*/
|
|
21
|
+
export declare function formatBytes(bytes: number): string;
|
|
22
|
+
/**
|
|
23
|
+
* Format duration in milliseconds
|
|
24
|
+
*/
|
|
25
|
+
export declare function formatDuration(ms: number): string;
|
|
26
|
+
/**
|
|
27
|
+
* Create a timeout promise
|
|
28
|
+
*/
|
|
29
|
+
export declare function withTimeout<T>(promise: Promise<T>, ms: number, message?: string): Promise<T>;
|
|
30
|
+
/**
|
|
31
|
+
* Gzip magic number check
|
|
32
|
+
*/
|
|
33
|
+
export declare function isGzip(data: Uint8Array | Buffer): boolean;
|
|
34
|
+
/**
|
|
35
|
+
* Validate profile file extension
|
|
36
|
+
*/
|
|
37
|
+
export declare function validateProfileExtension(filename: string): void;
|
|
38
|
+
//# sourceMappingURL=limits.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"limits.d.ts","sourceRoot":"","sources":["../../src/utils/limits.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAGlD,eAAO,MAAM,cAAc,EAAE,QAAQ,CAAC,cAAc,CAMnD,CAAC;AAEF;;GAEG;AACH,wBAAgB,aAAa,CAAC,UAAU,CAAC,EAAE,cAAc,GAAG,QAAQ,CAAC,cAAc,CAAC,CAKnF;AAED;;GAEG;AACH,wBAAgB,cAAc,CAC5B,IAAI,EAAE,UAAU,GAAG,MAAM,EACzB,QAAQ,EAAE,MAAM,EAChB,KAAK,GAAE,MAAe,GACrB,IAAI,CAMN;AAED;;GAEG;AACH,wBAAgB,cAAc,CAC5B,OAAO,EAAE,MAAM,EACf,QAAQ,EAAE,MAAM,EAChB,KAAK,GAAE,MAAkB,GACxB,IAAI,CAMN;AAED;;GAEG;AACH,wBAAgB,WAAW,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAKjD;AAED;;GAEG;AACH,wBAAgB,cAAc,CAAC,EAAE,EAAE,MAAM,GAAG,MAAM,CAIjD;AAED;;GAEG;AACH,wBAAgB,WAAW,CAAC,CAAC,EAC3B,OAAO,EAAE,OAAO,CAAC,CAAC,CAAC,EACnB,EAAE,EAAE,MAAM,EACV,OAAO,GAAE,MAA8B,GACtC,OAAO,CAAC,CAAC,CAAC,CAOZ;AAED;;GAEG;AACH,wBAAgB,MAAM,CAAC,IAAI,EAAE,UAAU,GAAG,MAAM,GAAG,OAAO,CAEzD;AAED;;GAEG;AACH,wBAAgB,wBAAwB,CAAC,QAAQ,EAAE,MAAM,GAAG,IAAI,CAU/D"}
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Resource limits and validation
|
|
3
|
+
*/
|
|
4
|
+
// Default limits
|
|
5
|
+
export const DEFAULT_LIMITS = {
|
|
6
|
+
maxProfileBytes: 50 * 1024 * 1024, // 50MB compressed
|
|
7
|
+
maxDecompressedBytes: 200 * 1024 * 1024, // 200MB uncompressed
|
|
8
|
+
maxMarkdownChars: 200_000, // 200k chars
|
|
9
|
+
maxSourceLinesPerFile: 50, // lines per source snippet
|
|
10
|
+
timeoutMs: 60_000, // 60 seconds
|
|
11
|
+
};
|
|
12
|
+
/**
|
|
13
|
+
* Merge user limits with defaults
|
|
14
|
+
*/
|
|
15
|
+
export function resolveLimits(userLimits) {
|
|
16
|
+
return {
|
|
17
|
+
...DEFAULT_LIMITS,
|
|
18
|
+
...userLimits,
|
|
19
|
+
};
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* Check if a buffer exceeds size limit
|
|
23
|
+
*/
|
|
24
|
+
export function checkSizeLimit(data, maxBytes, label = "file") {
|
|
25
|
+
if (data.length > maxBytes) {
|
|
26
|
+
throw new Error(`${label} size (${formatBytes(data.length)}) exceeds limit (${formatBytes(maxBytes)})`);
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* Check if content exceeds character limit
|
|
31
|
+
*/
|
|
32
|
+
export function checkCharLimit(content, maxChars, label = "content") {
|
|
33
|
+
if (content.length > maxChars) {
|
|
34
|
+
throw new Error(`${label} length (${content.length} chars) exceeds limit (${maxChars} chars)`);
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* Format bytes to human-readable string
|
|
39
|
+
*/
|
|
40
|
+
export function formatBytes(bytes) {
|
|
41
|
+
if (bytes < 1024)
|
|
42
|
+
return `${bytes} B`;
|
|
43
|
+
if (bytes < 1024 * 1024)
|
|
44
|
+
return `${(bytes / 1024).toFixed(1)} KB`;
|
|
45
|
+
if (bytes < 1024 * 1024 * 1024)
|
|
46
|
+
return `${(bytes / (1024 * 1024)).toFixed(1)} MB`;
|
|
47
|
+
return `${(bytes / (1024 * 1024 * 1024)).toFixed(1)} GB`;
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* Format duration in milliseconds
|
|
51
|
+
*/
|
|
52
|
+
export function formatDuration(ms) {
|
|
53
|
+
if (ms < 1000)
|
|
54
|
+
return `${Math.round(ms)}ms`;
|
|
55
|
+
if (ms < 60_000)
|
|
56
|
+
return `${(ms / 1000).toFixed(1)}s`;
|
|
57
|
+
return `${(ms / 60_000).toFixed(1)}m`;
|
|
58
|
+
}
|
|
59
|
+
/**
|
|
60
|
+
* Create a timeout promise
|
|
61
|
+
*/
|
|
62
|
+
export function withTimeout(promise, ms, message = "Operation timed out") {
|
|
63
|
+
return Promise.race([
|
|
64
|
+
promise,
|
|
65
|
+
new Promise((_, reject) => {
|
|
66
|
+
setTimeout(() => reject(new Error(`${message} after ${formatDuration(ms)}`)), ms);
|
|
67
|
+
}),
|
|
68
|
+
]);
|
|
69
|
+
}
|
|
70
|
+
/**
|
|
71
|
+
* Gzip magic number check
|
|
72
|
+
*/
|
|
73
|
+
export function isGzip(data) {
|
|
74
|
+
return data.length >= 2 && data[0] === 0x1f && data[1] === 0x8b;
|
|
75
|
+
}
|
|
76
|
+
/**
|
|
77
|
+
* Validate profile file extension
|
|
78
|
+
*/
|
|
79
|
+
export function validateProfileExtension(filename) {
|
|
80
|
+
const validExtensions = [".pb.gz", ".pprof", ".pb"];
|
|
81
|
+
const hasValidExt = validExtensions.some((ext) => filename.toLowerCase().endsWith(ext));
|
|
82
|
+
if (!hasValidExt) {
|
|
83
|
+
throw new Error(`Invalid profile file extension. Expected: ${validExtensions.join(", ")}`);
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
//# sourceMappingURL=limits.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"limits.js","sourceRoot":"","sources":["../../src/utils/limits.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Simple structured logger for observability
|
|
3
|
+
*/
|
|
4
|
+
export type LogLevel = "debug" | "info" | "warn" | "error";
|
|
5
|
+
export declare function setLogLevel(level: LogLevel): void;
|
|
6
|
+
export declare const logger: {
|
|
7
|
+
debug: (message: string, meta?: Record<string, unknown>) => void;
|
|
8
|
+
info: (message: string, meta?: Record<string, unknown>) => void;
|
|
9
|
+
warn: (message: string, meta?: Record<string, unknown>) => void;
|
|
10
|
+
error: (message: string, meta?: Record<string, unknown>) => void;
|
|
11
|
+
/** Log with timing measurement */
|
|
12
|
+
time: <T>(label: string, fn: () => T) => T;
|
|
13
|
+
/** Create a child logger with default metadata */
|
|
14
|
+
child: (defaultMeta: Record<string, unknown>) => {
|
|
15
|
+
debug: (message: string, meta?: Record<string, unknown>) => void;
|
|
16
|
+
info: (message: string, meta?: Record<string, unknown>) => void;
|
|
17
|
+
warn: (message: string, meta?: Record<string, unknown>) => void;
|
|
18
|
+
error: (message: string, meta?: Record<string, unknown>) => void;
|
|
19
|
+
};
|
|
20
|
+
};
|
|
21
|
+
//# sourceMappingURL=logger.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"logger.d.ts","sourceRoot":"","sources":["../../src/utils/logger.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,MAAM,MAAM,QAAQ,GAAG,OAAO,GAAG,MAAM,GAAG,MAAM,GAAG,OAAO,CAAC;AAkB3D,wBAAgB,WAAW,CAAC,KAAK,EAAE,QAAQ,GAAG,IAAI,CAEjD;AAuCD,eAAO,MAAM,MAAM;qBACA,MAAM,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC;oBACvC,MAAM,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC;oBACtC,MAAM,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC;qBACrC,MAAM,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC;IAEvD,kCAAkC;WAC3B,CAAC,SAAS,MAAM,MAAM,MAAM,CAAC,KAAG,CAAC;IAqBxC,kDAAkD;yBAC7B,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC;yBACzB,MAAM,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC;wBAEvC,MAAM,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC;wBAEtC,MAAM,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC;yBAErC,MAAM,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC;;CAG1D,CAAC"}
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Simple structured logger for observability
|
|
3
|
+
*/
|
|
4
|
+
const LOG_LEVELS = {
|
|
5
|
+
debug: 0,
|
|
6
|
+
info: 1,
|
|
7
|
+
warn: 2,
|
|
8
|
+
error: 3,
|
|
9
|
+
};
|
|
10
|
+
let currentLevel = process.env.LOG_LEVEL || "info";
|
|
11
|
+
export function setLogLevel(level) {
|
|
12
|
+
currentLevel = level;
|
|
13
|
+
}
|
|
14
|
+
function shouldLog(level) {
|
|
15
|
+
return LOG_LEVELS[level] >= LOG_LEVELS[currentLevel];
|
|
16
|
+
}
|
|
17
|
+
function formatLog(entry) {
|
|
18
|
+
if (process.env.LOG_FORMAT === "json") {
|
|
19
|
+
return JSON.stringify(entry);
|
|
20
|
+
}
|
|
21
|
+
const { level, message, timestamp, ...rest } = entry;
|
|
22
|
+
const extras = Object.keys(rest).length > 0
|
|
23
|
+
? ` ${JSON.stringify(rest)}`
|
|
24
|
+
: "";
|
|
25
|
+
return `[${timestamp}] ${level.toUpperCase()}: ${message}${extras}`;
|
|
26
|
+
}
|
|
27
|
+
function log(level, message, meta) {
|
|
28
|
+
if (!shouldLog(level))
|
|
29
|
+
return;
|
|
30
|
+
const entry = {
|
|
31
|
+
level,
|
|
32
|
+
message,
|
|
33
|
+
timestamp: new Date().toISOString(),
|
|
34
|
+
...meta,
|
|
35
|
+
};
|
|
36
|
+
const output = formatLog(entry);
|
|
37
|
+
if (level === "error") {
|
|
38
|
+
console.error(output);
|
|
39
|
+
}
|
|
40
|
+
else if (level === "warn") {
|
|
41
|
+
console.warn(output);
|
|
42
|
+
}
|
|
43
|
+
else {
|
|
44
|
+
console.log(output);
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
export const logger = {
|
|
48
|
+
debug: (message, meta) => log("debug", message, meta),
|
|
49
|
+
info: (message, meta) => log("info", message, meta),
|
|
50
|
+
warn: (message, meta) => log("warn", message, meta),
|
|
51
|
+
error: (message, meta) => log("error", message, meta),
|
|
52
|
+
/** Log with timing measurement */
|
|
53
|
+
time: (label, fn) => {
|
|
54
|
+
const start = performance.now();
|
|
55
|
+
try {
|
|
56
|
+
const result = fn();
|
|
57
|
+
if (result instanceof Promise) {
|
|
58
|
+
return result.then((r) => {
|
|
59
|
+
log("debug", `${label} completed`, { durationMs: Math.round(performance.now() - start) });
|
|
60
|
+
return r;
|
|
61
|
+
}).catch((e) => {
|
|
62
|
+
log("error", `${label} failed`, { durationMs: Math.round(performance.now() - start), error: String(e) });
|
|
63
|
+
throw e;
|
|
64
|
+
});
|
|
65
|
+
}
|
|
66
|
+
log("debug", `${label} completed`, { durationMs: Math.round(performance.now() - start) });
|
|
67
|
+
return result;
|
|
68
|
+
}
|
|
69
|
+
catch (e) {
|
|
70
|
+
log("error", `${label} failed`, { durationMs: Math.round(performance.now() - start), error: String(e) });
|
|
71
|
+
throw e;
|
|
72
|
+
}
|
|
73
|
+
},
|
|
74
|
+
/** Create a child logger with default metadata */
|
|
75
|
+
child: (defaultMeta) => ({
|
|
76
|
+
debug: (message, meta) => log("debug", message, { ...defaultMeta, ...meta }),
|
|
77
|
+
info: (message, meta) => log("info", message, { ...defaultMeta, ...meta }),
|
|
78
|
+
warn: (message, meta) => log("warn", message, { ...defaultMeta, ...meta }),
|
|
79
|
+
error: (message, meta) => log("error", message, { ...defaultMeta, ...meta }),
|
|
80
|
+
}),
|
|
81
|
+
};
|
|
82
|
+
//# sourceMappingURL=logger.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"logger.js","sourceRoot":"","sources":["../../src/utils/logger.ts"],"names":[],"mappings":"AAAA;;GAEG;AAWH,MAAM,UAAU,GAA6B;IAC3C,KAAK,EAAE,CAAC;IACR,IAAI,EAAE,CAAC;IACP,IAAI,EAAE,CAAC;IACP,KAAK,EAAE,CAAC;CACT,CAAC;AAEF,IAAI,YAAY,GAAc,OAAO,CAAC,GAAG,CAAC,SAAsB,IAAI,MAAM,CAAC;AAE3E,MAAM,UAAU,WAAW,CAAC,KAAe;IACzC,YAAY,GAAG,KAAK,CAAC;AACvB,CAAC;AAED,SAAS,SAAS,CAAC,KAAe;IAChC,OAAO,UAAU,CAAC,KAAK,CAAC,IAAI,UAAU,CAAC,YAAY,CAAC,CAAC;AACvD,CAAC;AAED,SAAS,SAAS,CAAC,KAAe;IAChC,IAAI,OAAO,CAAC,GAAG,CAAC,UAAU,KAAK,MAAM,EAAE,CAAC;QACtC,OAAO,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC;IAC/B,CAAC;IAED,MAAM,EAAE,KAAK,EAAE,OAAO,EAAE,SAAS,EAAE,GAAG,IAAI,EAAE,GAAG,KAAK,CAAC;IACrD,MAAM,MAAM,GAAG,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,MAAM,GAAG,CAAC;QACzC,CAAC,CAAC,IAAI,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,EAAE;QAC5B,CAAC,CAAC,EAAE,CAAC;IACP,OAAO,IAAI,SAAS,KAAK,KAAK,CAAC,WAAW,EAAE,KAAK,OAAO,GAAG,MAAM,EAAE,CAAC;AACtE,CAAC;AAED,SAAS,GAAG,CAAC,KAAe,EAAE,OAAe,EAAE,IAA8B;IAC3E,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC;QAAE,OAAO;IAE9B,MAAM,KAAK,GAAa;QACtB,KAAK;QACL,OAAO;QACP,SAAS,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;QACnC,GAAG,IAAI;KACR,CAAC;IAEF,MAAM,MAAM,GAAG,SAAS,CAAC,KAAK,CAAC,CAAC;IAEhC,IAAI,KAAK,KAAK,OAAO,EAAE,CAAC;QACtB,OAAO,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC;IACxB,CAAC;SAAM,IAAI,KAAK,KAAK,MAAM,EAAE,CAAC;QAC5B,OAAO,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;IACvB,CAAC;SAAM,CAAC;QACN,OAAO,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;IACtB,CAAC;AACH,CAAC;AAED,MAAM,CAAC,MAAM,MAAM,GAAG;IACpB,KAAK,EAAE,CAAC,OAAe,EAAE,IAA8B,EAAE,EAAE,CAAC,GAAG,CAAC,OAAO,EAAE,OAAO,EAAE,IAAI,CAAC;IACvF,IAAI,EAAE,CAAC,OAAe,EAAE,IAA8B,EAAE,EAAE,CAAC,GAAG,CAAC,MAAM,EAAE,OAAO,EAAE,IAAI,CAAC;IACrF,IAAI,EAAE,CAAC,OAAe,EAAE,IAA8B,EAAE,EAAE,CAAC,GAAG,CAAC,MAAM,EAAE,OAAO,EAAE,IAAI,CAAC;IACrF,KAAK,EAAE,CAAC,OAAe,EAAE,IAA8B,EAAE,EAAE,CAAC,GAAG,CAAC,OAAO,EAAE,OAAO,EAAE,IAAI,CAAC;IAEvF,kCAAkC;IAClC,IAAI,EAAE,CAAI,KAAa,EAAE,EAAW,EAAK,EAAE;QACzC,MAAM,KAAK,GAAG,WAAW,CAAC,GAAG,EAAE,CAAC;QAChC,IAAI,CAAC;YACH,MAAM,MAAM,GAAG,EAAE,EAAE,CAAC;YACpB,IAAI,MAAM,YAAY,OAAO,EAAE,CAAC;gBAC9B,OAAO,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE;oBACvB,GAAG,CAAC,OAAO,EAAE,GAAG,KAAK,YAAY,EAAE,EAAE,UAAU,EAAE,IAAI,CAAC,KAAK,CAAC,WAAW,CAAC,GAAG,EAAE,GAAG,KAAK,CAAC,EAAE,CAAC,CAAC;oBAC1F,OAAO,CAAC,CAAC;gBACX,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,EAAE;oBACb,GAAG,CAAC,OAAO,EAAE,GAAG,KAAK,SAAS,EAAE,EAAE,UAAU,EAAE,IAAI,CAAC,KAAK,CAAC,WAAW,CAAC,GAAG,EAAE,GAAG,KAAK,CAAC,EAAE,KAAK,EAAE,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;oBACzG,MAAM,CAAC,CAAC;gBACV,CAAC,CAAM,CAAC;YACV,CAAC;YACD,GAAG,CAAC,OAAO,EAAE,GAAG,KAAK,YAAY,EAAE,EAAE,UAAU,EAAE,IAAI,CAAC,KAAK,CAAC,WAAW,CAAC,GAAG,EAAE,GAAG,KAAK,CAAC,EAAE,CAAC,CAAC;YAC1F,OAAO,MAAM,CAAC;QAChB,CAAC;QAAC,OAAO,CAAC,EAAE,CAAC;YACX,GAAG,CAAC,OAAO,EAAE,GAAG,KAAK,SAAS,EAAE,EAAE,UAAU,EAAE,IAAI,CAAC,KAAK,CAAC,WAAW,CAAC,GAAG,EAAE,GAAG,KAAK,CAAC,EAAE,KAAK,EAAE,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;YACzG,MAAM,CAAC,CAAC;QACV,CAAC;IACH,CAAC;IAED,kDAAkD;IAClD,KAAK,EAAE,CAAC,WAAoC,EAAE,EAAE,CAAC,CAAC;QAChD,KAAK,EAAE,CAAC,OAAe,EAAE,IAA8B,EAAE,EAAE,CACzD,GAAG,CAAC,OAAO,EAAE,OAAO,EAAE,EAAE,GAAG,WAAW,EAAE,GAAG,IAAI,EAAE,CAAC;QACpD,IAAI,EAAE,CAAC,OAAe,EAAE,IAA8B,EAAE,EAAE,CACxD,GAAG,CAAC,MAAM,EAAE,OAAO,EAAE,EAAE,GAAG,WAAW,EAAE,GAAG,IAAI,EAAE,CAAC;QACnD,IAAI,EAAE,CAAC,OAAe,EAAE,IAA8B,EAAE,EAAE,CACxD,GAAG,CAAC,MAAM,EAAE,OAAO,EAAE,EAAE,GAAG,WAAW,EAAE,GAAG,IAAI,EAAE,CAAC;QACnD,KAAK,EAAE,CAAC,OAAe,EAAE,IAA8B,EAAE,EAAE,CACzD,GAAG,CAAC,OAAO,EAAE,OAAO,EAAE,EAAE,GAAG,WAAW,EAAE,GAAG,IAAI,EAAE,CAAC;KACrD,CAAC;CACH,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,11 +1,75 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "perf-skill",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"description": "",
|
|
5
|
-
"
|
|
3
|
+
"version": "0.2.1",
|
|
4
|
+
"description": "AI Skill for pprof profile analysis - convert .pb.gz to Markdown and generate structured performance recommendations",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "dist/index.js",
|
|
7
|
+
"types": "dist/index.d.ts",
|
|
8
|
+
"bin": {
|
|
9
|
+
"perf-skill": "dist/cli/main.js"
|
|
10
|
+
},
|
|
11
|
+
"exports": {
|
|
12
|
+
".": {
|
|
13
|
+
"types": "./dist/index.d.ts",
|
|
14
|
+
"import": "./dist/index.js"
|
|
15
|
+
}
|
|
16
|
+
},
|
|
17
|
+
"engines": {
|
|
18
|
+
"node": ">=20"
|
|
19
|
+
},
|
|
6
20
|
"scripts": {
|
|
7
|
-
"
|
|
21
|
+
"build": "tsc",
|
|
22
|
+
"dev": "tsc --watch",
|
|
23
|
+
"start": "node dist/server/http.js",
|
|
24
|
+
"cli": "node --import tsx src/cli/main.ts",
|
|
25
|
+
"test": "node --test --import tsx 'test/**/*.test.ts'",
|
|
26
|
+
"lint": "eslint src --ext .ts",
|
|
27
|
+
"clean": "rm -rf dist",
|
|
28
|
+
"update-prompts": "node --import tsx scripts/update-prompt-fixtures.ts",
|
|
29
|
+
"prepublishOnly": "npm run build"
|
|
30
|
+
},
|
|
31
|
+
"keywords": [
|
|
32
|
+
"pprof",
|
|
33
|
+
"profiling",
|
|
34
|
+
"performance",
|
|
35
|
+
"ai",
|
|
36
|
+
"llm",
|
|
37
|
+
"markdown",
|
|
38
|
+
"cpu",
|
|
39
|
+
"memory",
|
|
40
|
+
"heap",
|
|
41
|
+
"analysis"
|
|
42
|
+
],
|
|
43
|
+
"author": "unadlib",
|
|
44
|
+
"repository": {
|
|
45
|
+
"type": "git",
|
|
46
|
+
"url": "https://github.com/skillsland/perf-skill.git"
|
|
47
|
+
},
|
|
48
|
+
"license": "MIT",
|
|
49
|
+
"dependencies": {
|
|
50
|
+
"@datadog/pprof": "^5.13.2",
|
|
51
|
+
"@fastify/cors": "^11.2.0",
|
|
52
|
+
"@fastify/helmet": "^13.0.2",
|
|
53
|
+
"@fastify/multipart": "^9.4.0",
|
|
54
|
+
"@fastify/rate-limit": "^10.3.0",
|
|
55
|
+
"commander": "^14.0.3",
|
|
56
|
+
"fastify": "^5.7.3",
|
|
57
|
+
"openai": "^6.17.0",
|
|
58
|
+
"pprof-format": "^2.2.1",
|
|
59
|
+
"pprof-to-md": "^0.2.0",
|
|
60
|
+
"zod": "^4.3.6"
|
|
61
|
+
},
|
|
62
|
+
"devDependencies": {
|
|
63
|
+
"@types/node": "^25.2.0",
|
|
64
|
+
"@typescript-eslint/eslint-plugin": "^8.54.0",
|
|
65
|
+
"@typescript-eslint/parser": "^8.54.0",
|
|
66
|
+
"eslint": "^9.39.2",
|
|
67
|
+
"tsx": "^4.21.0",
|
|
68
|
+
"typescript": "^5.9.3"
|
|
8
69
|
},
|
|
9
|
-
"
|
|
10
|
-
|
|
70
|
+
"files": [
|
|
71
|
+
"dist",
|
|
72
|
+
"SKILL.md",
|
|
73
|
+
"README.md"
|
|
74
|
+
]
|
|
11
75
|
}
|