Spaces:
Sleeping
Sleeping
feat: complete Ever-Brain engine, MCP server, CLI evb mcp command, Dockerfile and release workflow
61b1da1 Download packages/cli/src/services/cache-service.ts from projectsorg/ever-brain: direct link, hf CLI and curl.
- Browser
- Download file 3.9 kB
-
https://huggingface.co/spaces/projectsorg/ever-brain/resolve/main/packages/cli/src/services/cache-service.ts
- Command line
-
hf download hf://spaces/projectsorg/ever-brain/packages/cli/src/services/cache-service.ts
-
curl -L -o cache-service.ts https://huggingface.co/spaces/projectsorg/ever-brain/resolve/main/packages/cli/src/services/cache-service.ts
3.9 kB
| import fs from 'node:fs'; | |
| import path from 'node:path'; | |
| import crypto from 'node:crypto'; | |
| import { isBinaryOrIgnoredFile } from '@ever-brain/api/utils/binary-filter.js'; | |
| import { projectConfigManager } from '../config/project-config.js'; | |
| export interface LocalModifications { | |
| modified: string[]; | |
| added: string[]; | |
| deleted: string[]; | |
| isDirty: boolean; | |
| } | |
| export function computeSha256(content: string): string { | |
| return crypto.createHash('sha256').update(content, 'utf8').digest('hex'); | |
| } | |
| export function normalizePosixPath(filePath: string): string { | |
| return filePath.replace(/\\/g, '/').replace(/^\/+/, ''); | |
| } | |
| export class CacheService { | |
| readCachedFile(workspaceRoot: string, relativePath: string): string | null { | |
| const cleanPath = normalizePosixPath(relativePath); | |
| const fullPath = path.join(projectConfigManager.getCacheDirPath(workspaceRoot), cleanPath); | |
| if (!fs.existsSync(fullPath)) { | |
| return null; | |
| } | |
| return fs.readFileSync(fullPath, 'utf8'); | |
| } | |
| writeCachedFile(workspaceRoot: string, relativePath: string, content: string): void { | |
| const cleanPath = normalizePosixPath(relativePath); | |
| const fullPath = path.join(projectConfigManager.getCacheDirPath(workspaceRoot), cleanPath); | |
| const dirName = path.dirname(fullPath); | |
| if (!fs.existsSync(dirName)) { | |
| fs.mkdirSync(dirName, { recursive: true }); | |
| } | |
| fs.writeFileSync(fullPath, content, 'utf8'); | |
| } | |
| deleteCachedFile(workspaceRoot: string, relativePath: string): void { | |
| const cleanPath = normalizePosixPath(relativePath); | |
| const fullPath = path.join(projectConfigManager.getCacheDirPath(workspaceRoot), cleanPath); | |
| if (fs.existsSync(fullPath)) { | |
| fs.unlinkSync(fullPath); | |
| } | |
| } | |
| listCachedFiles(workspaceRoot: string): string[] { | |
| const cacheDir = projectConfigManager.getCacheDirPath(workspaceRoot); | |
| if (!fs.existsSync(cacheDir)) { | |
| return []; | |
| } | |
| const results: string[] = []; | |
| const walk = (currentDir: string) => { | |
| const entries = fs.readdirSync(currentDir, { withFileTypes: true }); | |
| for (const entry of entries) { | |
| const fullPath = path.join(currentDir, entry.name); | |
| if (entry.isDirectory()) { | |
| walk(fullPath); | |
| } else if (entry.isFile()) { | |
| const relPath = normalizePosixPath(path.relative(cacheDir, fullPath)); | |
| if (!isBinaryOrIgnoredFile(relPath)) { | |
| results.push(relPath); | |
| } | |
| } | |
| } | |
| }; | |
| walk(cacheDir); | |
| return results.sort(); | |
| } | |
| computeDirtyState(workspaceRoot: string): LocalModifications { | |
| const state = projectConfigManager.readState(workspaceRoot); | |
| const baselineFiles = state?.files || {}; | |
| const localFiles = this.listCachedFiles(workspaceRoot); | |
| const localFileSet = new Set(localFiles); | |
| const baselineFileSet = new Set(Object.keys(baselineFiles)); | |
| const modified: string[] = []; | |
| const added: string[] = []; | |
| const deleted: string[] = []; | |
| // Check existing local files for additions and modifications | |
| for (const file of localFiles) { | |
| const content = this.readCachedFile(workspaceRoot, file); | |
| if (content === null) continue; | |
| const currentHash = computeSha256(content); | |
| if (!baselineFileSet.has(file)) { | |
| added.push(file); | |
| } else { | |
| const baselineHash = baselineFiles[file]; | |
| if (currentHash !== baselineHash) { | |
| modified.push(file); | |
| } | |
| } | |
| } | |
| // Check for deleted baseline files | |
| for (const baselineFile of Object.keys(baselineFiles)) { | |
| if (!localFileSet.has(baselineFile)) { | |
| deleted.push(baselineFile); | |
| } | |
| } | |
| return { | |
| modified: modified.sort(), | |
| added: added.sort(), | |
| deleted: deleted.sort(), | |
| isDirty: modified.length > 0 || added.length > 0 || deleted.length > 0, | |
| }; | |
| } | |
| } | |
| export const cacheService = new CacheService(); | |