Spaces:
Sleeping
Sleeping
feat: complete Ever-Brain engine, MCP server, CLI evb mcp command, Dockerfile and release workflow
61b1da1 Download packages/cli/src/client/api-client.ts from projectsorg/ever-brain: direct link, hf CLI and curl.
- Browser
- Download file 4.53 kB
-
https://huggingface.co/spaces/projectsorg/ever-brain/resolve/main/packages/cli/src/client/api-client.ts
- Command line
-
hf download hf://spaces/projectsorg/ever-brain/packages/cli/src/client/api-client.ts
-
curl -L -o api-client.ts https://huggingface.co/spaces/projectsorg/ever-brain/resolve/main/packages/cli/src/client/api-client.ts
4.53 kB
| import { RepoMetadata, FilesResponse, SearchResponse } from '@ever-brain/api/contract'; | |
| export class CliApiClient { | |
| constructor(private baseUrl: string) {} | |
| setBaseUrl(url: string): void { | |
| this.baseUrl = url; | |
| } | |
| private cleanUrl(endpoint: string): string { | |
| return `${this.baseUrl.replace(/\/+$/, '')}${endpoint}`; | |
| } | |
| private async safeFetch(url: string, init?: RequestInit): Promise<Response> { | |
| try { | |
| return await fetch(url, init); | |
| } catch (err: unknown) { | |
| const errorMsg = err instanceof Error ? err.message : String(err); | |
| throw new Error( | |
| `Cannot connect to Ever-Brain API at ${this.baseUrl} (${errorMsg}).\n` + | |
| `Is the Ever-Brain server running? Start it with 'pnpm dev' (or configure --api-url / EVB_API_URL).` | |
| ); | |
| } | |
| } | |
| async getRepoMetadata(owner: string, repo: string): Promise<RepoMetadata> { | |
| const url = this.cleanUrl(`/repos/${encodeURIComponent(owner)}/${encodeURIComponent(repo)}`); | |
| const res = await this.safeFetch(url, { | |
| headers: { 'User-Agent': 'Ever-Brain-CLI/1.0', Accept: 'application/json' }, | |
| }); | |
| if (!res.ok) { | |
| let message = `Failed to resolve repository ${owner}/${repo} (${res.status})`; | |
| try { | |
| const body = (await res.json()) as { error?: string }; | |
| if (body.error) message = body.error; | |
| } catch {} | |
| throw new Error(message); | |
| } | |
| return (await res.json()) as RepoMetadata; | |
| } | |
| async getFiles( | |
| owner: string, | |
| repo: string, | |
| prefix?: string, | |
| fresh?: boolean, | |
| branch?: string | |
| ): Promise<FilesResponse> { | |
| const params = new URLSearchParams(); | |
| if (prefix) params.set('prefix', prefix); | |
| if (fresh) params.set('fresh', 'true'); | |
| if (branch) params.set('branch', branch); | |
| const queryString = params.toString() ? `?${params.toString()}` : ''; | |
| const url = this.cleanUrl( | |
| `/repos/${encodeURIComponent(owner)}/${encodeURIComponent(repo)}/files${queryString}` | |
| ); | |
| const res = await this.safeFetch(url, { | |
| headers: { 'User-Agent': 'Ever-Brain-CLI/1.0', Accept: 'application/json' }, | |
| }); | |
| if (!res.ok) { | |
| let message = `Failed to fetch files for ${owner}/${repo} (${res.status})`; | |
| try { | |
| const body = (await res.json()) as { error?: string }; | |
| if (body.error) message = body.error; | |
| } catch {} | |
| throw new Error(message); | |
| } | |
| return (await res.json()) as FilesResponse; | |
| } | |
| async getFileContent( | |
| owner: string, | |
| repo: string, | |
| filePath: string, | |
| branch?: string | |
| ): Promise<{ content: string; exactPath: string; branch: string }> { | |
| const cleanPath = filePath.replace(/^\/+/, ''); | |
| const params = new URLSearchParams(); | |
| if (branch) params.set('branch', branch); | |
| const queryString = params.toString() ? `?${params.toString()}` : ''; | |
| const url = this.cleanUrl( | |
| `/repos/${encodeURIComponent(owner)}/${encodeURIComponent(repo)}/file/${cleanPath}${queryString}` | |
| ); | |
| const res = await this.safeFetch(url, { | |
| headers: { 'User-Agent': 'Ever-Brain-CLI/1.0' }, | |
| }); | |
| if (!res.ok) { | |
| let message = `File '${cleanPath}' not found in ${owner}/${repo}`; | |
| try { | |
| const body = (await res.json()) as { error?: string }; | |
| if (body.error) message = body.error; | |
| } catch {} | |
| throw new Error(message); | |
| } | |
| const content = await res.text(); | |
| const exactPath = res.headers.get('x-ever-brain-path') || cleanPath; | |
| const resolvedBranch = res.headers.get('x-ever-brain-branch') || branch || 'main'; | |
| return { | |
| content, | |
| exactPath, | |
| branch: resolvedBranch, | |
| }; | |
| } | |
| async searchFiles( | |
| owner: string, | |
| repo: string, | |
| query: string, | |
| prefix?: string, | |
| branch?: string | |
| ): Promise<SearchResponse> { | |
| const params = new URLSearchParams({ q: query }); | |
| if (prefix) params.set('prefix', prefix); | |
| if (branch) params.set('branch', branch); | |
| const url = this.cleanUrl( | |
| `/repos/${encodeURIComponent(owner)}/${encodeURIComponent(repo)}/search?${params.toString()}` | |
| ); | |
| const res = await this.safeFetch(url, { | |
| headers: { 'User-Agent': 'Ever-Brain-CLI/1.0', Accept: 'application/json' }, | |
| }); | |
| if (!res.ok) { | |
| let message = `Search failed for ${owner}/${repo} (${res.status})`; | |
| try { | |
| const body = (await res.json()) as { error?: string }; | |
| if (body.error) message = body.error; | |
| } catch {} | |
| throw new Error(message); | |
| } | |
| return (await res.json()) as SearchResponse; | |
| } | |
| } | |