/** * Client for the backend's workspace file API (see internal/files and the * WebSocket/CLI references in docs/). All functions throw an Error carrying * the server's message when the request fails. * * @example * const { entries } = await listFiles(); // workspace root * const { content } = await readFile(entries[0].path); * await writeFile("notes.txt", "hello"); */ /** One file matched by the recursive search. */ export interface FileHit { name: string; /** Absolute path, usable in further API calls. */ path: string; /** Path relative to the workspace root, with forward slashes. */ relPath: string; } /** One Claude Code skill discovered on disk. */ export interface Skill { name: string; description: string; path: string; source: "project" | "user"; } /** One child of a listed directory. */ export interface FileEntry { name: string; path: string; isDir: boolean; size: number; } async function requestJSON(input: string, init?: RequestInit): Promise { const response = await fetch(input, init); const payload = (await response.json()) as T & { error?: string }; if (!response.ok) { throw new Error( payload.error ?? `request failed with status ${response.status}`, ); } return payload; } /** listFiles returns the entries of a directory (workspace root when omitted). */ export function listFiles( path?: string, ): Promise<{ path: string; entries: FileEntry[] }> { const query = path ? `?path=${encodeURIComponent(path)}` : ""; return requestJSON(`/api/files${query}`); } /** * searchFiles returns the workspace files whose relative path contains the * query (case-insensitive), recursively, at most `limit` of them. */ export function searchFiles( query: string, limit = 50, ): Promise<{ root: string; files: FileHit[] }> { return requestJSON( `/api/files/search?q=${encodeURIComponent(query)}&limit=${limit}`, ); } /** listSkills returns the skills of the project and of the user. */ export function listSkills(): Promise<{ skills: Skill[] }> { return requestJSON("/api/skills"); } /** rawFileUrl is the URL streaming a file's bytes (images, downloads). */ export function rawFileUrl(path: string): string { return `/api/raw?path=${encodeURIComponent(path)}`; } /** readFile returns a text file's content. */ export function readFile( path: string, ): Promise<{ path: string; content: string }> { return requestJSON(`/api/file?path=${encodeURIComponent(path)}`); } /** writeFile saves content to a file, creating parent directories as needed. */ export async function writeFile(path: string, content: string): Promise { await requestJSON(`/api/file?path=${encodeURIComponent(path)}`, { method: "PUT", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ content }), }); }