UNPKG

@visulima/error

Version:

Error with more than just a message, stacktrace parsing.

278 lines (270 loc) 8.31 kB
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 };