Spaces:
Sleeping
Sleeping
feat: complete Ever-Brain engine, MCP server, CLI evb mcp command, Dockerfile and release workflow
61b1da1 Download packages/cli/src/config/project-config.ts from projectsorg/ever-brain: direct link, hf CLI and curl.
- Browser
- Download file 4.51 kB
-
https://huggingface.co/spaces/projectsorg/ever-brain/resolve/main/packages/cli/src/config/project-config.ts
- Command line
-
hf download hf://spaces/projectsorg/ever-brain/packages/cli/src/config/project-config.ts
-
curl -L -o project-config.ts https://huggingface.co/spaces/projectsorg/ever-brain/resolve/main/packages/cli/src/config/project-config.ts
4.51 kB
| import fs from 'node:fs'; | |
| import path from 'node:path'; | |
| import YAML from 'yaml'; | |
| import { | |
| EVB_DIR, | |
| CONFIG_FILE, | |
| STATE_FILE, | |
| CACHE_DIR, | |
| getDefaultApiUrl, | |
| } from './constants.js'; | |
| export interface EverBrainSourceConfig { | |
| repository: string; | |
| branch: string; | |
| api_url?: string; | |
| } | |
| export interface EverBrainProjectConfig { | |
| version: number; | |
| source: EverBrainSourceConfig; | |
| } | |
| export interface EverBrainState { | |
| last_sync: string; | |
| source_revision: string; | |
| cached_files: number; | |
| files: Record<string, string>; // path -> sha256 | |
| } | |
| export class ProjectConfigManager { | |
| findEvbRoot(startDir = process.cwd()): string | null { | |
| let currentDir = path.resolve(startDir); | |
| while (true) { | |
| const evbPath = path.join(currentDir, EVB_DIR); | |
| const configPath = path.join(evbPath, CONFIG_FILE); | |
| if (fs.existsSync(configPath)) { | |
| return currentDir; | |
| } | |
| const parentDir = path.dirname(currentDir); | |
| if (parentDir === currentDir) { | |
| break; | |
| } | |
| currentDir = parentDir; | |
| } | |
| return null; | |
| } | |
| getEvbDirPath(workspaceRoot: string): string { | |
| return path.join(workspaceRoot, EVB_DIR); | |
| } | |
| getConfigFilePath(workspaceRoot: string): string { | |
| return path.join(workspaceRoot, EVB_DIR, CONFIG_FILE); | |
| } | |
| getStateFilePath(workspaceRoot: string): string { | |
| return path.join(workspaceRoot, EVB_DIR, STATE_FILE); | |
| } | |
| getCacheDirPath(workspaceRoot: string): string { | |
| return path.join(workspaceRoot, EVB_DIR, CACHE_DIR); | |
| } | |
| readConfig(workspaceRoot: string): EverBrainProjectConfig { | |
| const configPath = this.getConfigFilePath(workspaceRoot); | |
| if (!fs.existsSync(configPath)) { | |
| throw new Error( | |
| `Ever-Brain configuration not found at '${configPath}'. Run 'evb init' first.` | |
| ); | |
| } | |
| const content = fs.readFileSync(configPath, 'utf8'); | |
| const parsed = YAML.parse(content) as EverBrainProjectConfig; | |
| if (!parsed || !parsed.source || !parsed.source.repository) { | |
| throw new Error(`Invalid Ever-Brain configuration in '${configPath}'.`); | |
| } | |
| return parsed; | |
| } | |
| writeConfig(workspaceRoot: string, config: EverBrainProjectConfig): void { | |
| const evbDir = this.getEvbDirPath(workspaceRoot); | |
| if (!fs.existsSync(evbDir)) { | |
| fs.mkdirSync(evbDir, { recursive: true }); | |
| } | |
| const configPath = this.getConfigFilePath(workspaceRoot); | |
| const yamlStr = YAML.stringify(config); | |
| fs.writeFileSync(configPath, yamlStr, 'utf8'); | |
| } | |
| readState(workspaceRoot: string): EverBrainState | null { | |
| const statePath = this.getStateFilePath(workspaceRoot); | |
| if (!fs.existsSync(statePath)) { | |
| return null; | |
| } | |
| try { | |
| const content = fs.readFileSync(statePath, 'utf8'); | |
| return YAML.parse(content) as EverBrainState; | |
| } catch { | |
| return null; | |
| } | |
| } | |
| writeState(workspaceRoot: string, state: EverBrainState): void { | |
| const evbDir = this.getEvbDirPath(workspaceRoot); | |
| if (!fs.existsSync(evbDir)) { | |
| fs.mkdirSync(evbDir, { recursive: true }); | |
| } | |
| const statePath = this.getStateFilePath(workspaceRoot); | |
| const yamlStr = YAML.stringify(state); | |
| fs.writeFileSync(statePath, yamlStr, 'utf8'); | |
| } | |
| ensureGitignore(workspaceRoot: string): void { | |
| const gitignorePath = path.join(workspaceRoot, '.gitignore'); | |
| const entriesToAdd = [ | |
| `${EVB_DIR}/${CACHE_DIR}/`, | |
| `${EVB_DIR}/${STATE_FILE}`, | |
| `${EVB_DIR}/auth.yaml`, | |
| ]; | |
| let content = ''; | |
| if (fs.existsSync(gitignorePath)) { | |
| content = fs.readFileSync(gitignorePath, 'utf8'); | |
| } | |
| const lines = content.split(/\r?\n/).map((l) => l.trim()); | |
| const missing = entriesToAdd.filter((entry) => !lines.includes(entry)); | |
| if (missing.length > 0) { | |
| const toAppend = (content.endsWith('\n') || content === '' ? '' : '\n') + | |
| `\n# Ever-Brain local cache & state\n` + | |
| missing.join('\n') + | |
| '\n'; | |
| fs.appendFileSync(gitignorePath, toAppend, 'utf8'); | |
| } | |
| } | |
| getApiUrl(workspaceRoot?: string): string { | |
| if (process.env.EVB_API_URL || process.env.EVER_BRAIN_API_URL) { | |
| return process.env.EVB_API_URL || process.env.EVER_BRAIN_API_URL!; | |
| } | |
| if (workspaceRoot) { | |
| try { | |
| const config = this.readConfig(workspaceRoot); | |
| if (config.source.api_url) { | |
| return config.source.api_url; | |
| } | |
| } catch { | |
| // Fall back to default | |
| } | |
| } | |
| return getDefaultApiUrl(); | |
| } | |
| } | |
| export const projectConfigManager = new ProjectConfigManager(); | |