nandi/oripublic Fork 0
76d62ac0da1600e1c208017584c3fa22e54feaa3
Commits
Clone
git clone https://git.rickub.com/nandi/ori.git
git clone ssh://git@rickub.com/nandi/ori.git

Host key fingerprint (ed25519): SHA256:iycHnxEyq0Q7uyVpB7JlznP0G7JrTPXLYRcAU5CSLhc — verify it before your first connect.

forked from bots-garden/ori

api.ts · 93 lines · 2.7 KBTypeScript Blame HistoryRaw
✨ Workspace panel, selectors, previews, desktop app, sandbox template, resizable file tree, light/dark theme 76d62ac k33g yesterday1/**
2 * Client for the backend's workspace file API (see internal/files and the
3 * WebSocket/CLI references in docs/). All functions throw an Error carrying
4 * the server's message when the request fails.
5 *
6 * @example
7 * const { entries } = await listFiles(); // workspace root
8 * const { content } = await readFile(entries[0].path);
9 * await writeFile("notes.txt", "hello");
10 */
11
12/** One file matched by the recursive search. */
13export interface FileHit {
14 name: string;
15 /** Absolute path, usable in further API calls. */
16 path: string;
17 /** Path relative to the workspace root, with forward slashes. */
18 relPath: string;
19}
20
21/** One Claude Code skill discovered on disk. */
22export interface Skill {
23 name: string;
24 description: string;
25 path: string;
26 source: "project" | "user";
27}
28
29/** One child of a listed directory. */
30export interface FileEntry {
31 name: string;
32 path: string;
33 isDir: boolean;
34 size: number;
35}
36
37async function requestJSON<T>(input: string, init?: RequestInit): Promise<T> {
38 const response = await fetch(input, init);
39 const payload = (await response.json()) as T & { error?: string };
40 if (!response.ok) {
41 throw new Error(
42 payload.error ?? `request failed with status ${response.status}`,
43 );
44 }
45 return payload;
46}
47
48/** listFiles returns the entries of a directory (workspace root when omitted). */
49export function listFiles(
50 path?: string,
51): Promise<{ path: string; entries: FileEntry[] }> {
52 const query = path ? `?path=${encodeURIComponent(path)}` : "";
53 return requestJSON(`/api/files${query}`);
54}
55
56/**
57 * searchFiles returns the workspace files whose relative path contains the
58 * query (case-insensitive), recursively, at most `limit` of them.
59 */
60export function searchFiles(
61 query: string,
62 limit = 50,
63): Promise<{ root: string; files: FileHit[] }> {
64 return requestJSON(
65 `/api/files/search?q=${encodeURIComponent(query)}&limit=${limit}`,
66 );
67}
68
69/** listSkills returns the skills of the project and of the user. */
70export function listSkills(): Promise<{ skills: Skill[] }> {
71 return requestJSON("/api/skills");
72}
73
74/** rawFileUrl is the URL streaming a file's bytes (images, downloads). */
75export function rawFileUrl(path: string): string {
76 return `/api/raw?path=${encodeURIComponent(path)}`;
77}
78
79/** readFile returns a text file's content. */
80export function readFile(
81 path: string,
82): Promise<{ path: string; content: string }> {
83 return requestJSON(`/api/file?path=${encodeURIComponent(path)}`);
84}
85
86/** writeFile saves content to a file, creating parent directories as needed. */
87export async function writeFile(path: string, content: string): Promise<void> {
88 await requestJSON(`/api/file?path=${encodeURIComponent(path)}`, {
89 method: "PUT",
90 headers: { "Content-Type": "application/json" },
91 body: JSON.stringify({ content }),
92 });
93}