@rool-dev/svelte 0.8.1 → 0.8.2-dev.d82ea25

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.
package/README.md CHANGED
@@ -2,9 +2,7 @@
2
2
 
3
3
  Svelte 5 bindings for Rool Spaces. Adds reactive state to the SDK using `$state` runes.
4
4
 
5
- > **Building a new Rool extension?** Start with [`@rool-dev/extension`](/extension/) it includes a reactive channel and handles hosting for you. This package is for integrating Rool into an existing Svelte application that manages its own auth, routing, and build setup.
6
-
7
- **Requires Svelte 5.** For core concepts (objects, references, AI placeholders, undo/redo), see the [SDK documentation](../sdk/README.md).
5
+ **Requires Svelte 5.** For core concepts (objects, references, AI, WebDAV files, undo/redo), see the [SDK documentation](../sdk/README.md).
8
6
 
9
7
  ## Installation
10
8
 
@@ -15,16 +13,18 @@ npm install @rool-dev/svelte
15
13
  ## Quick Start
16
14
 
17
15
  ```svelte
18
- <script>
19
- import { createRool } from '@rool-dev/svelte';
16
+ <script lang="ts">
17
+ import { createRool, type ReactiveChannel } from '@rool-dev/svelte';
20
18
 
21
19
  const rool = createRool();
22
- rool.init();
20
+ void rool.init();
23
21
 
24
- let channel = $state(null);
22
+ let channel = $state<ReactiveChannel | null>(null);
25
23
  </script>
26
24
 
27
- {#if !rool.authenticated}
25
+ {#if rool.authenticated === null}
26
+ <p>Checking session...</p>
27
+ {:else if !rool.authenticated}
28
28
  <button onclick={() => rool.login('My App')}>Login</button>
29
29
  {:else}
30
30
  <h1>My Spaces</h1>
@@ -50,14 +50,16 @@ The Svelte wrapper adds reactive state on top of the SDK:
50
50
  | Reactive Property | Description |
51
51
  |-------------------|-------------|
52
52
  | `rool.authenticated` | Auth state (`null` = checking, `true`/`false` = known) |
53
+ | `rool.currentUser` | Current user profile after authentication |
53
54
  | `rool.spaces` | List of available spaces |
54
55
  | `rool.spacesLoading` | Whether spaces are loading |
55
56
  | `rool.spacesError` | Error from loading spaces |
56
- | `rool.connectionState` | SSE connection state |
57
+ | `rool.connectionState` | Client SSE connection state |
57
58
  | `rool.userStorage` | User storage (cross-device preferences) |
58
- | `channel.interactions` | Channel interactions (auto-updates) |
59
- | `channel.objectIds` | All object IDs in the space (auto-updates on create/delete) |
60
- | `channel.collections` | Collection names from the schema (auto-updates) |
59
+ | `space.fileTree` | Canonical reactive WebDAV tree for `/`, including `/space` objects and `/rool-drive` user files |
60
+ | `channel.interactions` | Current conversation interactions |
61
+ | `channel.objectPaths` | Object paths derived from `space.fileTree` |
62
+ | `channel.collections` | Collection directories derived from `space.fileTree` |
61
63
  | `channel.conversations` | Conversations in this channel (auto-updates on create/delete/rename) |
62
64
  | `thread.interactions` | Interactions for a specific conversation (auto-updates) |
63
65
  | `watch.objects` | Objects matching a filter (auto-updates) |
@@ -65,6 +67,22 @@ The Svelte wrapper adds reactive state on top of the SDK:
65
67
 
66
68
  Everything else passes through to the SDK directly. See the [SDK documentation](../sdk/README.md) for full API details.
67
69
 
70
+ ### Reactive File Tree
71
+
72
+ Every `ReactiveSpace` owns a canonical reactive WebDAV tree. It is kept current with server `filesChanged`/`filesReset` events and WebDAV `sync-collection`, so it covers both object files and user files without polling.
73
+
74
+ ```ts
75
+ const space = await rool.openSpace(spaceId);
76
+
77
+ space.fileTree.nodes; // ReactiveFileNode[]
78
+ space.fileTree.byPath['/space']; // lookup by machine/WebDAV path
79
+ space.fileTree.childrenOf('/'); // /space and /rool-drive
80
+ space.fileTree.childrenOf('/rool-drive');
81
+ space.fileTree.objectPaths(); // object paths from /space/**/*.json
82
+ ```
83
+
84
+ Use this tree when UI needs to react to both files and objects. Object helpers like `channel.object()`, `channel.watch()`, `channel.objectPaths`, and `channel.collections` are backed by this tree.
85
+
68
86
  ## API
69
87
 
70
88
  ### Lifecycle
@@ -72,7 +90,7 @@ Everything else passes through to the SDK directly. See the [SDK documentation](
72
90
  ```typescript
73
91
  const rool = createRool();
74
92
 
75
- rool.init(); // Process auth callbacks (call on app startup)
93
+ void rool.init(); // Process auth callbacks (call on app startup)
76
94
  rool.login('My App'); // Redirect to login page
77
95
  rool.signup('My App'); // Redirect to signup page
78
96
  rool.verify(token); // Sign in from an email verification link (used by the official Rool app)
@@ -91,6 +109,7 @@ rool.destroy(); // Clean up all resources
91
109
  // rool.spacesError → Error | null
92
110
  // rool.connectionState → 'connected' | 'disconnected' | 'reconnecting'
93
111
  // rool.userStorage → Record<string, unknown>
112
+ // rool.currentUser → CurrentUser | null
94
113
  </script>
95
114
 
96
115
  {#if rool.spacesLoading}
@@ -109,9 +128,10 @@ rool.destroy(); // Clean up all resources
109
128
  Reactive cross-device storage for user preferences. Synced from server on `init()`, then kept up-to-date via SSE.
110
129
 
111
130
  ```svelte
112
- <script>
131
+ <script lang="ts">
132
+ import { createRool } from '@rool-dev/svelte';
113
133
  const rool = createRool();
114
- rool.init();
134
+ void rool.init();
115
135
  </script>
116
136
 
117
137
  <!-- Reactive binding to storage values -->
@@ -122,9 +142,7 @@ Reactive cross-device storage for user preferences. Synced from server on `init(
122
142
  {/if}
123
143
 
124
144
  <!-- Theme toggle -->
125
- <button onclick={() => rool.setUserStorage('theme',
126
- rool.userStorage.theme === 'dark' ? 'light' : 'dark'
127
- )}>
145
+ <button onclick={() => rool.setUserStorage('theme', rool.userStorage.theme === 'dark' ? 'light' : 'dark')}>
128
146
  Toggle theme
129
147
  </button>
130
148
  ```
@@ -161,47 +179,55 @@ space.close();
161
179
 
162
180
  ### ReactiveChannel
163
181
 
164
- `space.openChannel()` returns a `ReactiveChannel` — the SDK's `RoolChannel` with reactive `interactions` and `objectIds`:
182
+ `space.openChannel()` returns a `ReactiveChannel` — the SDK's `RoolChannel` with reactive `interactions`, `objectPaths`, `collections`, `conversations`, and file-tree-backed object helpers:
165
183
 
166
184
  ```svelte
167
- <script>
168
- let space = $state(null);
169
- let channel = $state(null);
185
+ <script lang="ts">
186
+ import { createRool, type ReactiveChannel, type ReactiveSpace } from '@rool-dev/svelte';
187
+
188
+ const rool = createRool();
189
+ void rool.init();
190
+
191
+ let space = $state<ReactiveSpace | null>(null);
192
+ let channel = $state<ReactiveChannel | null>(null);
170
193
 
171
- async function open(spaceId) {
194
+ async function open(spaceId: string) {
172
195
  space = await rool.openSpace(spaceId);
173
196
  channel = await space.openChannel('main');
174
197
  }
175
198
  </script>
176
199
 
177
200
  {#if channel}
178
- <!-- Reactive: updates as AI makes tool calls -->
201
+ <!-- Reactive: updates when the current conversation changes -->
179
202
  {#each channel.interactions as interaction}
180
203
  <div>
181
- <strong>{interaction.operation}</strong>: {interaction.output}
204
+ <strong>{interaction.operation}</strong>: {interaction.output ?? ''}
182
205
  </div>
183
206
  {/each}
184
207
 
185
208
  <!-- All SDK methods work directly -->
186
- <button onclick={() => channel.prompt('Hello')}>Send</button>
209
+ <button onclick={() => void channel.prompt('Hello')}>Send</button>
187
210
  {/if}
188
211
  ```
189
212
 
190
213
  ### Reactive Object
191
214
 
192
- Track a single object by ID with auto-updates:
215
+ Track a single object by machine path with auto-updates:
193
216
 
194
217
  ```svelte
195
- <script>
196
- let channel = $state(null);
197
- let item = $state(null);
218
+ <script lang="ts">
219
+ import { createRool, type ReactiveChannel, type ReactiveObject } from '@rool-dev/svelte';
220
+
221
+ const rool = createRool();
222
+ void rool.init();
198
223
 
199
- let space = $state(null);
224
+ let channel = $state<ReactiveChannel | null>(null);
225
+ let item = $state<ReactiveObject | null>(null);
200
226
 
201
- async function open(spaceId, objectId) {
202
- space = await rool.openSpace(spaceId);
227
+ async function open(spaceId: string, path: string) {
228
+ const space = await rool.openSpace(spaceId);
203
229
  channel = await space.openChannel('main');
204
- item = channel.object(objectId);
230
+ item = channel.object(path); // e.g. '/space/article/welcome.json'
205
231
  }
206
232
  </script>
207
233
 
@@ -209,7 +235,7 @@ Track a single object by ID with auto-updates:
209
235
  {#if item.loading}
210
236
  <p>Loading...</p>
211
237
  {:else if item.data}
212
- <div>{item.data.title}</div>
238
+ <div>{String(item.data.body.title ?? '')}</div>
213
239
  {:else}
214
240
  <p>Object not found</p>
215
241
  {/if}
@@ -233,16 +259,19 @@ item.close() // Stop listening for updates
233
259
  Create auto-updating watches of objects filtered by field values:
234
260
 
235
261
  ```svelte
236
- <script>
237
- let channel = $state(null);
238
- let articles = $state(null);
262
+ <script lang="ts">
263
+ import { createRool, type ReactiveChannel, type ReactiveSpace, type ReactiveWatch } from '@rool-dev/svelte';
239
264
 
240
- let space = $state(null);
265
+ const rool = createRool();
266
+ void rool.init();
241
267
 
242
- async function open(spaceId) {
268
+ let space = $state<ReactiveSpace | null>(null);
269
+ let channel = $state<ReactiveChannel | null>(null);
270
+ let articles = $state<ReactiveWatch | null>(null);
271
+ async function open(spaceId: string) {
243
272
  space = await rool.openSpace(spaceId);
244
273
  channel = await space.openChannel('main');
245
- // Create a reactive watch of all objects where type === 'article'
274
+ // Create a reactive watch of all objects in the 'article' collection
246
275
  articles = channel.watch({ collection: 'article' });
247
276
  }
248
277
  </script>
@@ -252,18 +281,18 @@ Create auto-updating watches of objects filtered by field values:
252
281
  <p>Loading...</p>
253
282
  {:else}
254
283
  {#each articles.objects as article}
255
- <div>{article.title}</div>
284
+ <div>{String(article.body.title ?? '')}</div>
256
285
  {/each}
257
286
  {/if}
258
287
  {/if}
259
288
  ```
260
289
 
261
- Watches automatically re-fetch when objects matching the filter are created, updated, or deleted. Since the SDK caches objects locally, re-fetches are typically instant (no network round-trip).
290
+ Watches automatically re-fetch when matching object files change in `space.fileTree`.
262
291
 
263
292
  **Lifecycle:** Watches are tied to their channel. Closing the channel stops all updates — existing watches will retain their last data but no longer refresh. Calling `channel.watch()` after `close()` throws.
264
293
 
265
294
  ```typescript
266
- // Watch options (same as findObjects, but no AI prompt)
295
+ // Watch options
267
296
  const articles = channel.watch({
268
297
  collection: 'article',
269
298
  where: { status: 'published' },
@@ -282,36 +311,51 @@ articles.close() // Stop listening for updates
282
311
 
283
312
  ### Reactive Channel List
284
313
 
285
- `space.channels` is a reactive `ChannelInfo[]` that auto-updates as channels are created, renamed, or deleted.
314
+ `space.channels` is a reactive `ChannelInfo[]` on an opened `ReactiveSpace`. If you only need a live channel list without managing a `ReactiveSpace`, use `rool.channels(spaceId)` and call `close()` when done.
286
315
 
287
316
  ```svelte
288
- <script>
289
- let space = $state(null);
317
+ <script lang="ts">
318
+ import { createRool, type ReactiveSpace } from '@rool-dev/svelte';
290
319
 
291
- async function open(spaceId) {
320
+ const rool = createRool();
321
+ void rool.init();
322
+
323
+ let space = $state<ReactiveSpace | null>(null);
324
+ async function open(spaceId: string) {
292
325
  space = await rool.openSpace(spaceId);
293
326
  }
294
327
  </script>
295
328
 
296
329
  {#if space}
297
330
  {#each space.channels as ch}
298
- <button onclick={() => space.openChannel(ch.id)}>{ch.name ?? ch.id}</button>
331
+ <button onclick={() => void space.openChannel(ch.id)}>{ch.name ?? ch.id}</button>
299
332
  {/each}
300
333
  {/if}
301
334
  ```
302
335
 
336
+ ```typescript
337
+ const channels = rool.channels(spaceId);
338
+ channels.list; // ChannelInfo[]
339
+ channels.loading; // boolean
340
+ await channels.refresh();
341
+ channels.close();
342
+ ```
343
+
303
344
  ### Reactive Conversation Handle
304
345
 
305
346
  For apps with multiple independent interaction threads (e.g., chat with threads), use `channel.conversation()` to get a handle with reactive interactions:
306
347
 
307
348
  ```svelte
308
- <script>
309
- let channel = $state(null);
310
- let thread = $state(null);
349
+ <script lang="ts">
350
+ import { createRool, type ReactiveChannel, type ReactiveConversationHandle, type ReactiveSpace } from '@rool-dev/svelte';
311
351
 
312
- let space = $state(null);
352
+ const rool = createRool();
353
+ void rool.init();
313
354
 
314
- async function openThread(spaceId, threadId) {
355
+ let space = $state<ReactiveSpace | null>(null);
356
+ let channel = $state<ReactiveChannel | null>(null);
357
+ let thread = $state<ReactiveConversationHandle | null>(null);
358
+ async function openThread(spaceId: string, threadId: string) {
315
359
  space = await rool.openSpace(spaceId);
316
360
  channel = await space.openChannel('main');
317
361
  thread = channel.conversation(threadId);
@@ -323,17 +367,19 @@ For apps with multiple independent interaction threads (e.g., chat with threads)
323
367
  <div>{interaction.output}</div>
324
368
  {/each}
325
369
 
326
- <button onclick={() => thread.prompt('Hello')}>Send</button>
370
+ <button onclick={() => void thread.prompt('Hello')}>Send</button>
327
371
  {/if}
328
372
  ```
329
373
 
330
374
  ```typescript
331
375
  // Reactive state
332
- thread.interactions // $state<Interaction[]> — auto-updates via SSE
376
+ thread.interactions // $state<Interaction[]> — updates from space/channel events
333
377
 
334
- // All conversation-scoped methods
378
+ // Conversation-scoped methods
335
379
  await thread.prompt('Hello')
336
- await thread.createObject({ data: { type: 'note', text: 'Note' } })
380
+ await thread.stop() // Stop this thread's in-flight interaction (false if none)
381
+ await thread.putObject('/space/note/welcome.json', { text: 'Note' })
382
+ await thread.patchObject('/space/note/welcome.json', { data: { text: 'Updated' } })
337
383
  await thread.setSystemInstruction('Respond in haiku')
338
384
  await thread.rename('Research Thread')
339
385
  thread.getInteractions() // Manual read
@@ -343,7 +389,7 @@ thread.getSystemInstruction()
343
389
  thread.close() // Stop listening for updates
344
390
  ```
345
391
 
346
- Conversations are auto-created on first interaction. All conversations share one SSE connection per channel.
392
+ Conversations are auto-created when you first write history or settings. Real-time events are owned by the space subscription; conversation handles subscribe to channel events locally.
347
393
 
348
394
  ### Channel Management
349
395
 
@@ -369,15 +415,18 @@ channel.name
369
415
  channel.role
370
416
  channel.channelId
371
417
 
372
- // Object operations
373
- await channel.getObject(id)
374
- await channel.createObject({ data: { type: 'note', text: 'Hello' } })
375
- await channel.updateObject(id, { data: { text: 'Updated' } })
376
- await channel.deleteObjects([id])
377
- await channel.findObjects({ collection: 'note' })
418
+ // Object operations — addressed by exact machine paths
419
+ const path = '/space/note/welcome.json';
420
+ await channel.getObject(path)
421
+ await channel.putObject(path, { text: 'Hello' })
422
+ await channel.patchObject(path, { data: { text: 'Updated' } })
423
+ await channel.moveObject(path, '/space/note/renamed.json')
424
+ await channel.deleteObjects(['/space/note/renamed.json'])
378
425
 
379
426
  // AI
380
427
  await channel.prompt('Summarize everything')
428
+ await channel.stop() // Stop the in-flight interaction (false if none)
429
+ await channel.stopInteraction(channel.activeLeafId!) // Stop a specific interaction by ID
381
430
 
382
431
  // Schema
383
432
  channel.getSchema()
@@ -385,7 +434,7 @@ await channel.createCollection('article', [
385
434
  { name: 'title', type: { kind: 'string' } },
386
435
  { name: 'status', type: { kind: 'enum', values: ['draft', 'published'] } },
387
436
  ])
388
- await channel.alterCollection('article', [...updatedProps])
437
+ await channel.alterCollection('article', updatedFields)
389
438
  await channel.dropCollection('article')
390
439
 
391
440
  // Undo/Redo
@@ -403,7 +452,7 @@ await channel.renameConversation('Research')
403
452
  // Conversation handles (reactive interactions for specific conversations)
404
453
  const thread = channel.conversation('thread-42');
405
454
  await thread.prompt('Hello'); // Uses thread-42's interaction history
406
- // thread.interactions is reactive $state — auto-updates via SSE
455
+ // thread.interactions is reactive $state — updates from space/channel events
407
456
  thread.close(); // Stop listening when done
408
457
 
409
458
  // Channel admin
@@ -415,17 +464,23 @@ See the [SDK documentation](../sdk/README.md) for complete API details.
415
464
  ### Utilities
416
465
 
417
466
  ```typescript
418
- import { generateId } from '@rool-dev/svelte';
467
+ import { machinePath, machineUri, isObjectPath, generateId } from '@rool-dev/svelte';
468
+
469
+ machinePath('rool-machine:/rool-drive/docs/read%20me.md');
470
+ // '/rool-drive/docs/read me.md'
419
471
 
420
- // Generate a 6-character alphanumeric ID
421
- const id = generateId();
472
+ machineUri('/space/article/welcome.json');
473
+ // 'rool-machine:/space/article/welcome.json'
474
+
475
+ isObjectPath('/space/article/welcome.json'); // true
476
+ generateId(); // 6-character alphanumeric ID
422
477
  ```
423
478
 
424
479
  ## Exported Types
425
480
 
426
481
  ```typescript
427
482
  // Package types
428
- import type { Rool, ReactiveChannel, ReactiveConversationHandle, ReactiveObject, ReactiveWatch, WatchOptions, ReactiveChannelList } from '@rool-dev/svelte';
483
+ import type { Rool, ReactiveSpace, ReactiveChannel, ReactiveConversationHandle, ReactiveObject, ReactiveWatch, WatchOptions, ReactiveChannelList, ReactiveFileTree, ReactiveFileNode, ReactiveFileRoot, ReactiveFileTreeEvent, ReactiveFileTreeSyncResult } from '@rool-dev/svelte';
429
484
 
430
485
  // Re-exported from @rool-dev/sdk
431
486
  import type {
@@ -435,6 +490,7 @@ import type {
435
490
  RoolSpace,
436
491
  RoolSpaceInfo,
437
492
  RoolObject,
493
+ GetObjectsResult,
438
494
  RoolObjectStat,
439
495
  RoolUserRole,
440
496
  ConnectionState,
@@ -443,29 +499,27 @@ import type {
443
499
  ConversationInfo,
444
500
  CurrentUser,
445
501
  Interaction,
446
- FindObjectsOptions,
447
502
  PromptOptions,
448
- CreateObjectOptions,
503
+ PromptAttachment,
449
504
  UpdateObjectOptions,
505
+ MoveObjectOptions,
506
+ CollectionOptions,
450
507
  FieldType,
451
508
  FieldDef,
452
509
  CollectionDef,
453
510
  SpaceSchema,
454
511
  SpaceMember,
455
512
  UserResult,
456
- PublishedExtensionInfo,
457
- PublishExtensionOptions,
458
- ExtensionManifest,
459
- FindExtensionsOptions,
460
-
513
+ SpaceFileStorageUsage,
514
+ RoolSpaceEvents,
515
+ WebDAVDepth,
516
+ WebDAVSyncLevel,
517
+ WebDAVPropName,
518
+ WebDAVResponse,
519
+ WebDAVProps,
461
520
  } from '@rool-dev/svelte';
462
521
  ```
463
522
 
464
- ## Examples
465
-
466
- - [soft-sql](../../examples/soft-sql) — SQL-style natural language queries with live tool call progress
467
- - [flashcards](../../examples/flashcards) — Spaced repetition with AI-generated cards
468
-
469
523
  ## License
470
524
 
471
525
  MIT - see [LICENSE](../../LICENSE) for details.
@@ -1,12 +1,13 @@
1
1
  import type { RoolChannel, RoolSpace, Interaction, RoolObject, ChannelInfo, ConversationInfo, ConversationHandle } from '@rool-dev/sdk';
2
+ import { ReactiveFileTree } from './file-tree.svelte.js';
2
3
  /**
3
4
  * Options for creating a reactive watch.
4
- * Same as FindObjectsOptions but without `prompt` (AI queries are too slow for reactive updates).
5
+ * Structured object filter for reactive updates.
5
6
  */
6
7
  export interface WatchOptions {
7
8
  /** Field requirements for exact matching */
8
9
  where?: Record<string, unknown>;
9
- /** Filter by collection name. Returns objects whose `type` field equals the given name. */
10
+ /** Filter by collection name. */
10
11
  collection?: string;
11
12
  /** Maximum number of objects */
12
13
  limit?: number;
@@ -14,20 +15,15 @@ export interface WatchOptions {
14
15
  order?: 'asc' | 'desc';
15
16
  }
16
17
  /**
17
- * A reactive watch of objects that auto-updates when matching objects change.
18
+ * A reactive watch of objects that auto-updates when matching object files change.
18
19
  */
19
20
  declare class ReactiveWatchImpl {
20
21
  #private;
21
22
  objects: RoolObject[];
22
23
  loading: boolean;
23
- constructor(channel: RoolChannel, options: WatchOptions);
24
- /**
25
- * Re-fetch the watched objects from the channel.
26
- */
24
+ constructor(channel: RoolChannel, fileTree: ReactiveFileTree, options: WatchOptions);
25
+ /** Re-fetch matching objects using the canonical file tree for paths. */
27
26
  refresh(): Promise<void>;
28
- /**
29
- * Stop listening for updates and clean up.
30
- */
31
27
  close(): void;
32
28
  }
33
29
  export type ReactiveWatch = ReactiveWatchImpl;
@@ -38,23 +34,11 @@ declare class ReactiveObjectImpl {
38
34
  #private;
39
35
  data: RoolObject | undefined;
40
36
  loading: boolean;
41
- constructor(channel: RoolChannel, objectId: string);
42
- /**
43
- * Re-fetch the object from the channel.
44
- */
37
+ constructor(channel: RoolChannel, fileTree: ReactiveFileTree, path: string);
45
38
  refresh(): Promise<void>;
46
- /**
47
- * Stop listening for updates and clean up.
48
- */
49
39
  close(): void;
50
40
  }
51
41
  export type ReactiveObject = ReactiveObjectImpl;
52
- /**
53
- * A reactive conversation handle that auto-updates interactions when the
54
- * conversation changes. Wraps the SDK's ConversationHandle with $state.
55
- *
56
- * Call `close()` when done to stop listening for updates.
57
- */
58
42
  declare class ReactiveConversationHandleImpl {
59
43
  #private;
60
44
  interactions: Interaction[];
@@ -67,30 +51,30 @@ declare class ReactiveConversationHandleImpl {
67
51
  getSystemInstruction(): string | undefined;
68
52
  setSystemInstruction(...args: Parameters<ConversationHandle['setSystemInstruction']>): Promise<void>;
69
53
  rename(...args: Parameters<ConversationHandle['rename']>): Promise<void>;
70
- findObjects(...args: Parameters<ConversationHandle['findObjects']>): Promise<{
71
- objects: RoolObject[];
54
+ putObject(...args: Parameters<ConversationHandle['putObject']>): Promise<{
55
+ object: RoolObject;
72
56
  message: string;
73
57
  }>;
74
- createObject(...args: Parameters<ConversationHandle['createObject']>): Promise<{
58
+ patchObject(...args: Parameters<ConversationHandle['patchObject']>): Promise<{
75
59
  object: RoolObject;
76
60
  message: string;
77
61
  }>;
78
- updateObject(...args: Parameters<ConversationHandle['updateObject']>): Promise<{
62
+ moveObject(...args: Parameters<ConversationHandle['moveObject']>): Promise<{
79
63
  object: RoolObject;
80
64
  message: string;
81
65
  }>;
82
66
  deleteObjects(...args: Parameters<ConversationHandle['deleteObjects']>): Promise<void>;
67
+ /** @deprecated Use deleteObjects instead. */
68
+ deletePaths(...args: Parameters<ConversationHandle['deletePaths']>): Promise<void>;
83
69
  prompt(...args: Parameters<ConversationHandle['prompt']>): Promise<{
84
70
  message: string;
85
71
  objects: RoolObject[];
86
72
  }>;
73
+ stop(): Promise<boolean>;
87
74
  createCollection(...args: Parameters<ConversationHandle['createCollection']>): Promise<import("@rool-dev/sdk").CollectionDef>;
88
75
  alterCollection(...args: Parameters<ConversationHandle['alterCollection']>): Promise<import("@rool-dev/sdk").CollectionDef>;
89
76
  dropCollection(...args: Parameters<ConversationHandle['dropCollection']>): Promise<void>;
90
77
  setMetadata(...args: Parameters<ConversationHandle['setMetadata']>): void;
91
- /**
92
- * Stop listening for updates and clean up.
93
- */
94
78
  close(): void;
95
79
  }
96
80
  export type ReactiveConversationHandle = ReactiveConversationHandleImpl;
@@ -101,10 +85,10 @@ export type ReactiveConversationHandle = ReactiveConversationHandleImpl;
101
85
  declare class ReactiveChannelImpl {
102
86
  #private;
103
87
  interactions: Interaction[];
104
- objectIds: string[];
88
+ objectPaths: string[];
105
89
  collections: string[];
106
90
  conversations: ConversationInfo[];
107
- constructor(channel: RoolChannel);
91
+ constructor(channel: RoolChannel, fileTree: ReactiveFileTree);
108
92
  get id(): string;
109
93
  get name(): string;
110
94
  get role(): import("@rool-dev/sdk").RoolUserRole;
@@ -113,30 +97,32 @@ declare class ReactiveChannelImpl {
113
97
  get channelName(): string | null;
114
98
  get isReadOnly(): boolean;
115
99
  get linkAccess(): import("@rool-dev/sdk").LinkAccess;
116
- get extensionUrl(): string | null;
117
- get manifest(): import("@rool-dev/sdk").ExtensionManifest | null;
118
100
  get isClosed(): boolean;
119
101
  close(): void;
120
102
  getObject(...args: Parameters<RoolChannel['getObject']>): Promise<RoolObject | undefined>;
103
+ getObjects(...args: Parameters<RoolChannel['getObjects']>): Promise<import("@rool-dev/sdk").GetObjectsResult>;
121
104
  stat(...args: Parameters<RoolChannel['stat']>): import("@rool-dev/sdk").RoolObjectStat | undefined;
122
- findObjects(...args: Parameters<RoolChannel['findObjects']>): Promise<{
123
- objects: RoolObject[];
105
+ putObject(...args: Parameters<RoolChannel['putObject']>): Promise<{
106
+ object: RoolObject;
124
107
  message: string;
125
108
  }>;
126
- getObjectIds(...args: Parameters<RoolChannel['getObjectIds']>): string[];
127
- createObject(...args: Parameters<RoolChannel['createObject']>): Promise<{
109
+ patchObject(...args: Parameters<RoolChannel['patchObject']>): Promise<{
128
110
  object: RoolObject;
129
111
  message: string;
130
112
  }>;
131
- updateObject(...args: Parameters<RoolChannel['updateObject']>): Promise<{
113
+ moveObject(...args: Parameters<RoolChannel['moveObject']>): Promise<{
132
114
  object: RoolObject;
133
115
  message: string;
134
116
  }>;
135
117
  deleteObjects(...args: Parameters<RoolChannel['deleteObjects']>): Promise<void>;
118
+ /** @deprecated Use deleteObjects instead. */
119
+ deletePaths(...args: Parameters<RoolChannel['deletePaths']>): Promise<void>;
136
120
  prompt(...args: Parameters<RoolChannel['prompt']>): Promise<{
137
121
  message: string;
138
122
  objects: RoolObject[];
139
123
  }>;
124
+ stop(): Promise<boolean>;
125
+ stopInteraction(...args: Parameters<RoolChannel['stopInteraction']>): Promise<boolean>;
140
126
  checkpoint(...args: Parameters<RoolChannel['checkpoint']>): Promise<string>;
141
127
  canUndo(): Promise<boolean>;
142
128
  canRedo(): Promise<boolean>;
@@ -159,45 +145,31 @@ declare class ReactiveChannelImpl {
159
145
  createCollection(...args: Parameters<RoolChannel['createCollection']>): Promise<import("@rool-dev/sdk").CollectionDef>;
160
146
  alterCollection(...args: Parameters<RoolChannel['alterCollection']>): Promise<import("@rool-dev/sdk").CollectionDef>;
161
147
  dropCollection(...args: Parameters<RoolChannel['dropCollection']>): Promise<void>;
162
- uploadMedia(...args: Parameters<RoolChannel['uploadMedia']>): Promise<string>;
163
- fetchMedia(...args: Parameters<RoolChannel['fetchMedia']>): Promise<import("@rool-dev/sdk").MediaResponse>;
164
- deleteMedia(...args: Parameters<RoolChannel['deleteMedia']>): Promise<void>;
165
- listMedia(): Promise<import("@rool-dev/sdk").MediaInfo[]>;
166
148
  fetch(...args: Parameters<RoolChannel['fetch']>): Promise<Response>;
167
149
  rename(...args: Parameters<RoolChannel['rename']>): Promise<void>;
168
150
  conversation(conversationId: string): ReactiveConversationHandle;
169
151
  on(...args: Parameters<RoolChannel['on']>): () => void;
170
152
  off(...args: Parameters<RoolChannel['off']>): void;
171
153
  /**
172
- * Create a reactive object that auto-updates when the object changes.
173
- * Throws if the channel has been closed.
154
+ * Create a reactive object that auto-updates when the object at this path changes.
174
155
  */
175
- object(objectId: string): ReactiveObject;
156
+ object(path: string): ReactiveObject;
176
157
  /**
177
158
  * Create a reactive watch that auto-updates when matching objects change.
178
- * Throws if the channel has been closed.
179
159
  */
180
160
  watch(options: WatchOptions): ReactiveWatch;
181
161
  }
182
- export declare function wrapChannel(channel: RoolChannel): ReactiveChannel;
162
+ export declare function wrapChannel(channel: RoolChannel, fileTree: ReactiveFileTree): ReactiveChannel;
183
163
  export type ReactiveChannel = ReactiveChannelImpl;
184
164
  /**
185
165
  * A reactive list of channels for a space that auto-updates via SSE events.
186
- * Can be constructed with a RoolSpace directly or a Promise<RoolSpace>
187
- * (starts with an empty list and loading=true until the space resolves).
188
166
  */
189
167
  declare class ReactiveChannelListImpl {
190
168
  #private;
191
169
  list: ChannelInfo[];
192
170
  loading: boolean;
193
171
  constructor(spaceOrPromise: RoolSpace | Promise<RoolSpace>);
194
- /**
195
- * Refresh the channel list from the space.
196
- */
197
172
  refresh(): Promise<void>;
198
- /**
199
- * Stop listening for updates and clean up.
200
- */
201
173
  close(): void;
202
174
  }
203
175
  export declare function createChannelList(spaceOrPromise: RoolSpace | Promise<RoolSpace>): ReactiveChannelList;