@visulima/error
Version:
Error with more than just a message, stacktrace parsing.
278 lines (270 loc) • 8.31 kB
JavaScript
import { createRequire as __cjs_createRequire } from "node:module";
const __cjs_require = __cjs_createRequire(import.meta.url);
const __cjs_getProcess = typeof globalThis !== "undefined" && typeof globalThis.process !== "undefined" ? globalThis.process : process;
const __cjs_getBuiltinModule = (module) => {
// Check if we're in Node.js and version supports getBuiltinModule
if (typeof __cjs_getProcess !== "undefined" && __cjs_getProcess.versions && __cjs_getProcess.versions.node) {
const [major, minor] = __cjs_getProcess.versions.node.split(".").map(Number);
// Node.js 20.16.0+ and 22.3.0+
if (major > 22 || (major === 22 && minor >= 3) || (major === 20 && minor >= 16)) {
return __cjs_getProcess.getBuiltinModule(module);
}
}
// Fallback to createRequire
return __cjs_require(module);
};
const {
createHash
} = __cjs_getBuiltinModule("node:crypto");
const {
existsSync,
readFileSync,
mkdirSync,
writeFileSync
} = __cjs_getBuiltinModule("node:fs");
const {
tmpdir
} = __cjs_getBuiltinModule("node:os");
import { generateText } from 'ai';
import aiPrompt from '../solution/ai/ai-prompt.js';
import aiSolutionResponse from './aiSolutionResponse-CJBMLS9t.js';
const DRIVE_LETTER_START_RE = /^[A-Z]:\//i;
const normalizeWindowsPath = (input = "") => {
if (!input) {
return input;
}
return input.replaceAll("\\", "/").replace(DRIVE_LETTER_START_RE, (r) => r.toUpperCase());
};
const UNC_REGEX = /^[/\\]{2}/;
const IS_ABSOLUTE_RE = /^[/\\](?![/\\])|^[/\\]{2}(?!\.)|^[A-Z]:[/\\]/i;
const DRIVE_LETTER_RE = /^[A-Z]:$/i;
const normalizeString = (path2, allowAboveRoot) => {
let result = "";
let lastSegmentLength = 0;
let lastSlash = -1;
let dots = 0;
let char;
for (let index = 0; index <= path2.length; ++index) {
if (index < path2.length) {
char = path2[index];
} else if (char === "/") {
break;
} else {
char = "/";
}
if (char === "/") {
if (lastSlash === index - 1 || dots === 1) ;
else if (dots === 2) {
if (result.length < 2 || lastSegmentLength !== 2 || !result.endsWith(".") || result.at(-2) !== ".") {
if (result.length > 2) {
const lastSlashIndex = result.lastIndexOf("/");
if (lastSlashIndex === -1) {
result = "";
lastSegmentLength = 0;
} else {
result = result.slice(0, lastSlashIndex);
lastSegmentLength = result.length - 1 - result.lastIndexOf("/");
}
lastSlash = index;
dots = 0;
continue;
} else if (result.length > 0) {
result = "";
lastSegmentLength = 0;
lastSlash = index;
dots = 0;
continue;
}
}
if (allowAboveRoot) {
result += result.length > 0 ? "/.." : "..";
lastSegmentLength = 2;
}
} else {
if (result.length > 0) {
result += `/${path2.slice(lastSlash + 1, index)}`;
} else {
result = path2.slice(lastSlash + 1, index);
}
lastSegmentLength = index - lastSlash - 1;
}
lastSlash = index;
dots = 0;
} else if (char === "." && dots !== -1) {
++dots;
} else {
dots = -1;
}
}
return result;
};
const isAbsolute = (path2) => IS_ABSOLUTE_RE.test(path2);
const normalize = function(path2) {
if (path2.length === 0) {
return ".";
}
path2 = normalizeWindowsPath(path2);
const isUNCPath = UNC_REGEX.exec(path2);
const isPathAbsolute = isAbsolute(path2);
const trailingSeparator = path2.at(-1) === "/";
path2 = normalizeString(path2, !isPathAbsolute);
if (path2.length === 0) {
if (isPathAbsolute) {
return "/";
}
return trailingSeparator ? "./" : ".";
}
if (trailingSeparator) {
path2 += "/";
}
if (DRIVE_LETTER_RE.test(path2)) {
path2 += "/";
}
if (isUNCPath) {
if (!isPathAbsolute) {
return `//./${path2}`;
}
return `//${path2}`;
}
return isPathAbsolute && !isAbsolute(path2) ? `/${path2}` : path2;
};
const join = (...segments) => {
let path2 = "";
for (const seg of segments) {
if (!seg) {
continue;
}
if (path2.length > 0) {
const pathTrailing = path2[path2.length - 1] === "/";
const segLeading = seg[0] === "/";
const both = pathTrailing && segLeading;
if (both) {
path2 += seg.slice(1);
} else {
path2 += pathTrailing || segLeading ? seg : `/${seg}`;
}
} else {
path2 += seg;
}
}
return normalize(path2);
};
const DEFAULT_HEADER = "## Ai Generated Solution";
const DEFAULT_ERROR_MESSAGE = "Creation of a AI solution failed.";
const generateCacheKey = (error, file, temperature) => {
const keyData = {
error: {
message: error.message,
name: error.name,
stack: error.stack
},
file: {
file: file.file,
language: file.language,
line: file.line,
snippet: file.snippet
},
temperature
};
return createHash("sha256").update(JSON.stringify(keyData)).digest("hex");
};
const getCacheDirectory = (directory) => {
if (directory) {
return directory;
}
return join(tmpdir(), "visulima-error-cache");
};
const ensureCacheDirectory = (cacheDirectory) => {
if (!existsSync(cacheDirectory)) {
mkdirSync(cacheDirectory, { recursive: true });
}
};
const getCacheFilePath = (cacheDirectory, key) => join(cacheDirectory, `${key}.json`);
const readFromCache = (cacheFilePath, ttl) => {
try {
if (!existsSync(cacheFilePath)) {
return void 0;
}
const cacheContent = readFileSync(cacheFilePath, "utf8");
const cacheEntry = JSON.parse(cacheContent);
const now = Date.now();
if (now - cacheEntry.timestamp > ttl) {
return void 0;
}
return cacheEntry.solution;
} catch {
return void 0;
}
};
const writeToCache = (cacheFilePath, solution, ttl) => {
try {
const cacheEntry = {
solution,
timestamp: Date.now(),
ttl
};
writeFileSync(cacheFilePath, JSON.stringify(cacheEntry, null, 2), "utf8");
} catch {
}
};
const aiFinder = (model, options) => {
return {
handle: async (error, file) => {
const cacheOptions = options?.cache;
const temperature = options?.temperature ?? 0;
const ttl = cacheOptions?.ttl ?? 24 * 60 * 60 * 1e3;
const cacheDirectory = getCacheDirectory(cacheOptions?.directory);
if (cacheOptions?.enabled !== false) {
const cacheKey = generateCacheKey(error, file, temperature);
const cacheFilePath = getCacheFilePath(cacheDirectory, cacheKey);
const cachedSolution = readFromCache(cacheFilePath, ttl);
if (cachedSolution) {
return cachedSolution;
}
ensureCacheDirectory(cacheDirectory);
}
const content = aiPrompt({ applicationType: void 0, error, file });
try {
const result = await generateText({
model,
prompt: content,
temperature
});
const messageContent = result.text;
let solution;
if (messageContent) {
solution = {
body: aiSolutionResponse(messageContent),
header: DEFAULT_HEADER
};
} else {
solution = {
body: aiSolutionResponse(DEFAULT_ERROR_MESSAGE),
header: DEFAULT_HEADER
};
}
if (cacheOptions?.enabled !== false) {
const cacheKey = generateCacheKey(error, file, temperature);
const cacheFilePath = getCacheFilePath(cacheDirectory, cacheKey);
writeToCache(cacheFilePath, solution, ttl);
}
return solution;
} catch (error_) {
console.error(error_);
const solution = {
body: aiSolutionResponse(DEFAULT_ERROR_MESSAGE),
header: DEFAULT_HEADER
};
if (cacheOptions?.enabled !== false) {
const cacheKey = generateCacheKey(error, file, temperature);
const cacheFilePath = getCacheFilePath(cacheDirectory, cacheKey);
writeToCache(cacheFilePath, solution, ttl);
}
return solution;
}
},
name: "AI SDK",
priority: 99
};
};
export { aiFinder as default };