mcard-js
Version:
MCard - Content-addressable storage with cryptographic hashing, handle resolution, and vector search for Node.js and browsers
60 lines • 2.15 kB
JavaScript
/**
* Lean runtime executor.
*
* Executes Lean 4 code via the lean CLI with source caching.
*/
import * as fs from 'fs';
import * as path from 'path';
import * as util from 'util';
import { execFile, parseOutput } from './base.js';
const writeFile = util.promisify(fs.writeFile);
// Lean source caching for performance
let leanCacheDir = null;
const leanSourceCache = new Map();
function ensureLeanCacheDir() {
if (!leanCacheDir) {
leanCacheDir = path.resolve(process.cwd(), '.lean_cache');
if (!fs.existsSync(leanCacheDir)) {
fs.mkdirSync(leanCacheDir, { recursive: true });
}
}
return leanCacheDir;
}
async function getCachedLeanSource(code) {
const crypto = await import('crypto');
const hash = crypto.createHash('sha256').update(code).digest('hex');
if (leanSourceCache.has(hash)) {
return leanSourceCache.get(hash);
}
const cacheDir = ensureLeanCacheDir();
const filePath = path.join(cacheDir, `${hash}.lean`);
if (!fs.existsSync(filePath)) {
await writeFile(filePath, code);
}
leanSourceCache.set(hash, filePath);
return filePath;
}
export class LeanRuntime {
async execute(code, context, config) {
const contextStr = typeof context === 'string' ? context : JSON.stringify(context);
const sourcePath = await getCachedLeanSource(code);
// Use elan to run the stable Lean toolchain if elan is available
const os = await import('os');
const elanPath = path.join(os.homedir(), '.elan', 'bin', 'elan');
let stdout;
if (fs.existsSync(elanPath)) {
// Use 'elan run' to ensure correct toolchain is used
const result = await execFile(elanPath, [
'run', 'leanprover/lean4:v4.25.2', 'lean', '--run', sourcePath, contextStr
]);
stdout = result.stdout;
}
else {
// Fallback to system lean
const result = await execFile('lean', ['--run', sourcePath, contextStr]);
stdout = result.stdout;
}
return parseOutput(stdout);
}
}
//# sourceMappingURL=lean.js.map