@remodlai/lexiqfs 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,397 @@
1
+ import * as _zenfs_core from '@zenfs/core';
2
+ import { FileSystem, InodeLike, CreationOptions } from '@zenfs/core';
3
+ export * from '@zenfs/core';
4
+ import { Client } from '@libsql/client';
5
+
6
+ /**
7
+ * Default mode values for convenience
8
+ */
9
+ declare const DEFAULT_DIR_MODE: number;
10
+ declare const DEFAULT_FILE_MODE: number;
11
+ /**
12
+ * Configuration options for LibSQLBackend
13
+ */
14
+ interface LibSQLBackendOptions {
15
+ /**
16
+ * URL for the local embedded replica file
17
+ * Example: "file:/project.db" or "file:/agent-workspace.db"
18
+ */
19
+ url?: string;
20
+ /**
21
+ * URL for the remote libsql-server to sync with
22
+ * Example: "http://libsql-server:8080/v1/namespaces/org-123/project"
23
+ */
24
+ syncUrl?: string;
25
+ /**
26
+ * Authentication token for remote sync
27
+ */
28
+ authToken?: string;
29
+ /**
30
+ * Organization ID for multi-tenant isolation
31
+ */
32
+ organizationId: string;
33
+ /**
34
+ * Agent ID (null for project filesystem, string for agent workspace)
35
+ */
36
+ agentId?: string | null;
37
+ /**
38
+ * Sync interval in milliseconds (default: 60000 = 1 minute)
39
+ */
40
+ syncInterval?: number;
41
+ /**
42
+ * Label for this store instance
43
+ */
44
+ label?: string;
45
+ /**
46
+ * Maximum storage size in bytes (for usage reporting)
47
+ */
48
+ maxSize?: number;
49
+ }
50
+ /**
51
+ * Helper to check if mode indicates a directory
52
+ */
53
+ declare function isDirectory(mode: number): boolean;
54
+ /**
55
+ * Helper to check if mode indicates a regular file
56
+ */
57
+ declare function isFile(mode: number): boolean;
58
+ /**
59
+ * File system change event type
60
+ * - 'change': file content modified
61
+ * - 'rename': file created or deleted (Node.js fs.watch convention)
62
+ */
63
+ type FSChangeEventType = 'change' | 'rename';
64
+ /**
65
+ * File system change event payload
66
+ * Uses path (not inode ID) so watch() can match events to watchers
67
+ */
68
+ interface FSChangeEvent {
69
+ eventType: FSChangeEventType;
70
+ path: string;
71
+ timestamp: number;
72
+ }
73
+ /**
74
+ * Callback for file system change events
75
+ */
76
+ type FSChangeCallback = (event: FSChangeEvent) => void;
77
+ /**
78
+ * Get current ISO8601 timestamp
79
+ */
80
+ declare function nowISO(): string;
81
+
82
+ /**
83
+ * LibSQLTransaction - Atomic operations for libSQL-backed ZenFS filesystem
84
+ *
85
+ * This provides path-based storage where:
86
+ * - Keys are file paths (strings like '/src/main.ts')
87
+ * - Values are Uint8Array data (file content)
88
+ *
89
+ * Why path-based instead of inode-based?
90
+ * - libSQL already provides inode-level efficiency (no BLOB copy on UPDATE)
91
+ * - watch() needs paths, not inode IDs
92
+ * - Simpler schema, simpler code
93
+ */
94
+
95
+ /**
96
+ * AsyncTransaction base class compatible with ZenFS
97
+ * Path-based interface for filesystem operations
98
+ */
99
+ declare abstract class AsyncTransactionBase {
100
+ protected asyncDone: Promise<unknown>;
101
+ /**
102
+ * Run an async operation from sync context
103
+ */
104
+ protected async(promise: Promise<unknown>): void;
105
+ abstract keys(): Promise<Iterable<string>>;
106
+ abstract get(path: string, offset: number, end?: number): Promise<Uint8Array | undefined>;
107
+ abstract getSync(path: string, offset: number, end?: number): Uint8Array | undefined;
108
+ abstract set(path: string, data: Uint8Array, offset: number): Promise<void>;
109
+ abstract setSync(path: string, data: Uint8Array, offset: number): void;
110
+ abstract remove(path: string): Promise<void>;
111
+ abstract removeSync(path: string): void;
112
+ }
113
+ /**
114
+ * LibSQLTransaction provides atomic operations using libSQL
115
+ *
116
+ * Path-based storage where:
117
+ * - keys are strings (file paths like '/src/main.ts')
118
+ * - values are Uint8Array (file content)
119
+ *
120
+ * We store these in the 'files' table using path as the primary key.
121
+ */
122
+ declare class LibSQLTransaction extends AsyncTransactionBase {
123
+ readonly store: LibSQLStore;
124
+ private readonly client;
125
+ private readonly organizationId;
126
+ private readonly agentId;
127
+ private readonly onCommit?;
128
+ private cache;
129
+ private pendingWrites;
130
+ private pendingDeletes;
131
+ private committed;
132
+ constructor(store: LibSQLStore, client: Client, organizationId: string, agentId: string | null, onCommit?: ((events: FSChangeEvent[]) => void) | undefined);
133
+ /**
134
+ * Get all keys (file paths) in the store
135
+ */
136
+ keys(): Promise<Iterable<string>>;
137
+ /**
138
+ * Get data for a file path
139
+ *
140
+ * @param path - The file path to look up (e.g., '/src/main.ts')
141
+ * @param offset - Start offset in the data
142
+ * @param end - End offset (exclusive), or undefined for rest of data
143
+ */
144
+ get(path: string, offset: number, end?: number): Promise<Uint8Array | undefined>;
145
+ /**
146
+ * Synchronous get - uses cache only
147
+ * Throws EAGAIN if data not in cache
148
+ */
149
+ getSync(path: string, offset: number, end?: number): Uint8Array | undefined;
150
+ /**
151
+ * Set data for a file path
152
+ *
153
+ * @param path - The file path (e.g., '/src/main.ts')
154
+ * @param data - The data to store
155
+ * @param offset - Offset at which to write (0 for full replacement)
156
+ */
157
+ set(path: string, data: Uint8Array, offset: number): Promise<void>;
158
+ /**
159
+ * Synchronous set - queues for async write
160
+ */
161
+ setSync(path: string, data: Uint8Array, offset: number): void;
162
+ /**
163
+ * Remove a file path from the store
164
+ */
165
+ remove(path: string): Promise<void>;
166
+ /**
167
+ * Synchronous remove - queues for async delete
168
+ */
169
+ removeSync(path: string): void;
170
+ /**
171
+ * Commit all pending changes to the database
172
+ */
173
+ commit(): Promise<void>;
174
+ /**
175
+ * Abort - discard pending changes
176
+ */
177
+ abort(): void;
178
+ /**
179
+ * Slice data according to offset/end
180
+ */
181
+ private sliceData;
182
+ /**
183
+ * Decode base64 string to Uint8Array
184
+ */
185
+ private decodeBase64;
186
+ /**
187
+ * Symbol.asyncDispose for using/await using
188
+ */
189
+ [Symbol.asyncDispose](): Promise<void>;
190
+ /**
191
+ * Symbol.dispose for using
192
+ */
193
+ [Symbol.dispose](): void;
194
+ }
195
+
196
+ /**
197
+ * LibSQLStore - ZenFS Store implementation backed by libSQL
198
+ *
199
+ * This implements the ZenFS Store interface using libSQL as the storage backend.
200
+ * It supports both local embedded replicas (SQLite WASM) and remote sync to libsql-server.
201
+ *
202
+ * Key concepts:
203
+ * - Store is a path-based interface (path → Uint8Array)
204
+ * - All operations go through transactions for atomicity
205
+ * - watch() events use paths (not inode IDs) for easy matching
206
+ */
207
+
208
+ /**
209
+ * Usage information for the store
210
+ */
211
+ interface UsageInfo {
212
+ totalSpace: number;
213
+ freeSpace: number;
214
+ }
215
+ /**
216
+ * Store flags for optimization hints
217
+ */
218
+ type StoreFlag = 'partial';
219
+ /**
220
+ * Store interface compatible with ZenFS
221
+ */
222
+ interface Store {
223
+ readonly type?: number;
224
+ readonly name: string;
225
+ readonly label?: string;
226
+ readonly uuid?: string;
227
+ readonly flags?: readonly StoreFlag[];
228
+ sync(): Promise<void>;
229
+ transaction(): LibSQLTransaction;
230
+ usage?(): UsageInfo;
231
+ }
232
+ /**
233
+ * LibSQLStore implements the ZenFS Store interface
234
+ *
235
+ * Architecture:
236
+ * - Uses @libsql/client for database operations
237
+ * - Supports embedded replicas (local SQLite) with remote sync
238
+ * - All read/write operations go through transactions
239
+ * - Implements the simple key-value interface expected by StoreFS
240
+ */
241
+ declare class LibSQLStore implements Store {
242
+ readonly type = 1819505011;
243
+ readonly name = "libsqlfs";
244
+ readonly label?: string;
245
+ readonly uuid?: string;
246
+ readonly flags: readonly StoreFlag[];
247
+ private readonly client;
248
+ private readonly organizationId;
249
+ private readonly agentId;
250
+ private readonly maxSize;
251
+ private initialized;
252
+ private eventEmitter;
253
+ constructor(client: Client, options: LibSQLBackendOptions);
254
+ /**
255
+ * Initialize the database schema if needed
256
+ */
257
+ initialize(): Promise<void>;
258
+ /**
259
+ * Sync the embedded replica with the remote server
260
+ * For libSQL embedded replicas, this triggers a sync operation
261
+ */
262
+ sync(): Promise<void>;
263
+ /**
264
+ * Create a new transaction for atomic operations
265
+ *
266
+ * ZenFS StoreFS uses transactions for all operations:
267
+ * - tx.get(id, offset, end) - read data
268
+ * - tx.set(id, data, offset) - write data
269
+ * - tx.remove(id) - delete data
270
+ * - tx.commit() - persist changes
271
+ */
272
+ transaction(): LibSQLTransaction;
273
+ /**
274
+ * Handle events from committed transactions
275
+ */
276
+ private handleCommitEvents;
277
+ /**
278
+ * Subscribe to file change events
279
+ * @returns Unsubscribe function
280
+ */
281
+ onFileChange(callback: FSChangeCallback): () => void;
282
+ /**
283
+ * Get storage usage information
284
+ */
285
+ usage(): UsageInfo;
286
+ /**
287
+ * Get the libSQL client (for advanced operations)
288
+ */
289
+ getClient(): Client;
290
+ /**
291
+ * Get organization ID
292
+ */
293
+ getOrganizationId(): string;
294
+ /**
295
+ * Get agent ID
296
+ */
297
+ getAgentId(): string | null;
298
+ /**
299
+ * Check if a root directory exists
300
+ */
301
+ hasRoot(): Promise<boolean>;
302
+ /**
303
+ * Create root directory if it doesn't exist
304
+ * Called by StoreFS during initialization
305
+ */
306
+ ensureRoot(): Promise<void>;
307
+ /**
308
+ * Close the store and release resources
309
+ */
310
+ close(): Promise<void>;
311
+ /**
312
+ * Text search using FTS5 with fuzzy fallback
313
+ *
314
+ * Search strategy:
315
+ * 1. FTS5 MATCH for fast, indexed word matching
316
+ * 2. Fuzzy fallback (fuzzy_damlev) for typo tolerance if no results
317
+ *
318
+ * @param query - Search query string
319
+ * @param options - Search options
320
+ * @returns Array of search matches with line information
321
+ */
322
+ textSearch(query: string, options?: {
323
+ folders?: string[];
324
+ includes?: string[];
325
+ excludes?: string[];
326
+ caseSensitive?: boolean;
327
+ isRegex?: boolean;
328
+ resultLimit?: number;
329
+ fuzzyThreshold?: number;
330
+ }): Promise<{
331
+ matches: Array<{
332
+ path: string;
333
+ lineNumber: number;
334
+ lineContent: string;
335
+ matchStart: number;
336
+ matchEnd: number;
337
+ }>;
338
+ truncated: boolean;
339
+ }>;
340
+ }
341
+
342
+ declare const LibSQLFS_base: _zenfs_core.Mixin<typeof FileSystem, _zenfs_core.AsyncMixin>;
343
+ /**
344
+ * LibSQLFS — ZenFS v2.4.4 FileSystem backed by libSQL path-based storage.
345
+ *
346
+ * Extends Async(FileSystem): only async methods implemented here.
347
+ * Async() provides all *Sync methods via _sync (InMemory instance).
348
+ * ready() triggers crossCopy which preloads libSQL data into _sync.
349
+ */
350
+ declare class LibSQLFS extends LibSQLFS_base {
351
+ _sync: _zenfs_core.StoreFS<_zenfs_core.InMemoryStore>;
352
+ private client;
353
+ private organizationId;
354
+ private agentId;
355
+ readonly label?: string;
356
+ constructor(client: Client, options: LibSQLBackendOptions);
357
+ /**
358
+ * Initialize schema and seed root directory.
359
+ * Called before ready(), which triggers Async() crossCopy.
360
+ */
361
+ private initialize;
362
+ /**
363
+ * Override ready() to run initialize(), then let Async() crossCopy.
364
+ */
365
+ ready(): Promise<void>;
366
+ rename(oldPath: string, newPath: string): Promise<void>;
367
+ stat(path: string): Promise<InodeLike>;
368
+ touch(path: string, metadata: Partial<InodeLike>): Promise<void>;
369
+ createFile(path: string, options: CreationOptions): Promise<InodeLike>;
370
+ unlink(path: string): Promise<void>;
371
+ rmdir(path: string): Promise<void>;
372
+ mkdir(path: string, options: CreationOptions): Promise<InodeLike>;
373
+ readdir(path: string): Promise<string[]>;
374
+ link(_target: string, _link: string): Promise<void>;
375
+ sync(): Promise<void>;
376
+ read(path: string, buffer: Uint8Array, start: number, end: number): Promise<void>;
377
+ write(path: string, buffer: Uint8Array, offset: number): Promise<void>;
378
+ }
379
+ /**
380
+ * Backend interface compatible with ZenFS configure()
381
+ */
382
+ interface Backend<FS = unknown, TOptions = object> {
383
+ name: string;
384
+ options: Record<string, {
385
+ type: string | readonly string[];
386
+ required: boolean;
387
+ }>;
388
+ create(options: TOptions): FS | Promise<FS>;
389
+ isAvailable?(config: TOptions): boolean | Promise<boolean>;
390
+ }
391
+ declare const LibSQLBackend: Backend<LibSQLFS, LibSQLBackendOptions>;
392
+ declare function createLibSQLStore(options: LibSQLBackendOptions): Promise<LibSQLStore>;
393
+ declare function forkTemplate(serverUrl: string, templateNamespace: string, targetNamespace: string, authToken?: string): Promise<boolean>;
394
+ declare function namespaceExists(serverUrl: string, namespace: string, authToken?: string): Promise<boolean>;
395
+ declare function createNamespace(serverUrl: string, namespace: string, authToken?: string): Promise<boolean>;
396
+
397
+ export { AsyncTransactionBase, DEFAULT_DIR_MODE, DEFAULT_FILE_MODE, type FSChangeCallback, type FSChangeEvent, type FSChangeEventType, LibSQLBackend as LibSQL, LibSQLBackend, type LibSQLBackendOptions, LibSQLStore, LibSQLTransaction, createLibSQLStore, createNamespace, forkTemplate, isDirectory, isFile, namespaceExists, nowISO };