@rool-dev/sdk 0.10.2-dev.47747e3 → 0.10.2-dev.550002
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 +36 -163
- package/dist/channel.d.ts +41 -129
- package/dist/channel.d.ts.map +1 -1
- package/dist/channel.js +233 -394
- package/dist/channel.js.map +1 -1
- package/dist/client.d.ts +3 -55
- package/dist/client.d.ts.map +1 -1
- package/dist/client.js +7 -93
- package/dist/client.js.map +1 -1
- package/dist/graphql.d.ts +4 -46
- package/dist/graphql.d.ts.map +1 -1
- package/dist/graphql.js +13 -223
- package/dist/graphql.js.map +1 -1
- package/dist/index.d.ts +3 -6
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -4
- package/dist/index.js.map +1 -1
- package/dist/path.d.ts +6 -0
- package/dist/path.d.ts.map +1 -0
- package/dist/path.js +47 -0
- package/dist/path.js.map +1 -0
- package/dist/rest.d.ts +9 -0
- package/dist/rest.d.ts.map +1 -1
- package/dist/rest.js +48 -1
- package/dist/rest.js.map +1 -1
- package/dist/space.d.ts +4 -14
- package/dist/space.d.ts.map +1 -1
- package/dist/space.js +30 -50
- package/dist/space.js.map +1 -1
- package/dist/subscription.d.ts.map +1 -1
- package/dist/subscription.js +18 -26
- package/dist/subscription.js.map +1 -1
- package/dist/types.d.ts +36 -212
- package/dist/types.d.ts.map +1 -1
- package/dist/webdav.d.ts +31 -21
- package/dist/webdav.d.ts.map +1 -1
- package/dist/webdav.js +70 -58
- package/dist/webdav.js.map +1 -1
- package/package.json +2 -1
- package/dist/apps.d.ts +0 -30
- package/dist/apps.d.ts.map +0 -1
- package/dist/apps.js +0 -81
- package/dist/apps.js.map +0 -1
- package/dist/locations.d.ts +0 -34
- package/dist/locations.d.ts.map +0 -1
- package/dist/locations.js +0 -90
- package/dist/locations.js.map +0 -1
- package/dist/machine.d.ts +0 -16
- package/dist/machine.d.ts.map +0 -1
- package/dist/machine.js +0 -51
- package/dist/machine.js.map +0 -1
package/README.md
CHANGED
|
@@ -2,8 +2,6 @@
|
|
|
2
2
|
|
|
3
3
|
The TypeScript SDK for Rool, a persistent and collaborative environment for organizing objects.
|
|
4
4
|
|
|
5
|
-
> **Building a new Rool extension?** Start with [`@rool-dev/extension`](/extension/) — it handles hosting, dev server, and gives you a reactive Svelte channel out of the box. This SDK is for advanced use cases: integrating Rool into an existing application, building Node.js scripts, or working outside the extension sandbox.
|
|
6
|
-
|
|
7
5
|
The SDK manages authentication, real-time synchronization, and per-space file storage. Core primitives:
|
|
8
6
|
|
|
9
7
|
- **Spaces** — Containers for objects, schema, metadata, channels, and files
|
|
@@ -65,10 +63,9 @@ const { message, objects } = await channel.prompt(
|
|
|
65
63
|
console.log(message); // AI explains what it did
|
|
66
64
|
console.log(`Modified ${objects.length} objects`);
|
|
67
65
|
|
|
68
|
-
//
|
|
69
|
-
const
|
|
70
|
-
|
|
71
|
-
});
|
|
66
|
+
// Read an object by location
|
|
67
|
+
const loadedEarth = await channel.getObject(earth.location);
|
|
68
|
+
console.log(loadedEarth?.body.name);
|
|
72
69
|
|
|
73
70
|
// Clean up
|
|
74
71
|
channel.close();
|
|
@@ -229,7 +226,7 @@ References are just data — no special API is needed to create or remove them.
|
|
|
229
226
|
#### Location helpers
|
|
230
227
|
|
|
231
228
|
```typescript
|
|
232
|
-
import { loc, parseLocation, normalizeLocation
|
|
229
|
+
import { loc, parseLocation, normalizeLocation } from '@rool-dev/sdk';
|
|
233
230
|
|
|
234
231
|
loc('article', 'welcome'); // '/space/article/welcome.json'
|
|
235
232
|
parseLocation('/space/article/welcome.json'); // { collection: 'article', basename: 'welcome' }
|
|
@@ -237,9 +234,6 @@ parseLocation('/space/article/welcome.json'); // { collection: 'article', basena
|
|
|
237
234
|
// normalizeLocation accepts canonical or short form and returns canonical
|
|
238
235
|
normalizeLocation('article/welcome'); // '/space/article/welcome.json'
|
|
239
236
|
normalizeLocation('/space/article/welcome.json'); // unchanged
|
|
240
|
-
|
|
241
|
-
// 6-char random basename — same generator the SDK uses by default
|
|
242
|
-
generateBasename(); // e.g., 'X7kQ9p'
|
|
243
237
|
```
|
|
244
238
|
|
|
245
239
|
SDK methods that accept a location (`getObject`, `updateObject`, `deleteObjects`, `moveObject`, etc.) accept either form and normalize internally. SDK return values always use the canonical full form.
|
|
@@ -320,24 +314,24 @@ await channel.createObject('article', {
|
|
|
320
314
|
|
|
321
315
|
### Real-time Sync
|
|
322
316
|
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
- `local_user` — This client made the change
|
|
326
|
-
- `remote_user` — Another user/client made the change
|
|
327
|
-
- `remote_agent` — AI agent made the change
|
|
328
|
-
- `system` — Resync after error
|
|
317
|
+
Object and file reactivity is WebDAV-based. Listen for space-level file change notifications, then reconcile with `webdav.syncCollection()` using your sync token. This covers both object files under `/space` and user files under `/rool-drive`.
|
|
329
318
|
|
|
330
319
|
```typescript
|
|
331
|
-
|
|
332
|
-
channel.on('objectUpdated', ({ location, object, source }) => {
|
|
333
|
-
renderObject(location, object);
|
|
334
|
-
if (source === 'remote_agent') {
|
|
335
|
-
doLayout(); // AI might have added content
|
|
336
|
-
}
|
|
337
|
-
});
|
|
320
|
+
let token: string | null = null;
|
|
338
321
|
|
|
339
|
-
|
|
340
|
-
|
|
322
|
+
async function syncFiles() {
|
|
323
|
+
const result = await space.webdav.syncCollection('/', {
|
|
324
|
+
token,
|
|
325
|
+
level: 'infinite',
|
|
326
|
+
props: ['displayname', 'getetag', 'getlastmodified', 'resourcetype'],
|
|
327
|
+
});
|
|
328
|
+
token = result.token;
|
|
329
|
+
updateFileTree(result.responses);
|
|
330
|
+
}
|
|
331
|
+
|
|
332
|
+
space.on('filesChanged', syncFiles);
|
|
333
|
+
space.on('filesReset', () => { token = null; syncFiles(); });
|
|
334
|
+
await syncFiles();
|
|
341
335
|
```
|
|
342
336
|
|
|
343
337
|
### Locations & Basenames
|
|
@@ -358,7 +352,7 @@ await channel.createObject('article',
|
|
|
358
352
|
|
|
359
353
|
```typescript
|
|
360
354
|
// Fire-and-forget: create and reference without waiting
|
|
361
|
-
const basename =
|
|
355
|
+
const basename = 'idea-seed';
|
|
362
356
|
const location = loc('note', basename);
|
|
363
357
|
|
|
364
358
|
channel.createObject('note', { text: '{{expand this idea}}' }, { basename });
|
|
@@ -574,7 +568,7 @@ await space.addUser(user.id, 'editor');
|
|
|
574
568
|
| `owner` | Full control, can delete space and manage all users |
|
|
575
569
|
| `admin` | All editor capabilities, plus can manage users (except other admins/owners) |
|
|
576
570
|
| `editor` | Can create, modify, move, and delete objects |
|
|
577
|
-
| `viewer` | Read-only access (can query with `prompt` and
|
|
571
|
+
| `viewer` | Read-only access (can query with `prompt` and read objects/files) |
|
|
578
572
|
|
|
579
573
|
### Space Collaboration Methods
|
|
580
574
|
|
|
@@ -621,18 +615,9 @@ When a user accesses a space via URL, they're granted the corresponding role (`v
|
|
|
621
615
|
|
|
622
616
|
### Real-time Collaboration
|
|
623
617
|
|
|
624
|
-
When multiple users have a space open, changes
|
|
625
|
-
|
|
626
|
-
```typescript
|
|
627
|
-
channel.on('objectUpdated', ({ location, object, source }) => {
|
|
628
|
-
if (source === 'remote_user') {
|
|
629
|
-
// Another user made this change
|
|
630
|
-
showCollaboratorActivity(object);
|
|
631
|
-
}
|
|
632
|
-
});
|
|
633
|
-
```
|
|
618
|
+
When multiple users have a space open, object and file changes are announced by `space.on('filesChanged')` and reconciled through WebDAV `syncCollection()`. Channel/conversation state still emits channel events; filesystem state does not use channel object events.
|
|
634
619
|
|
|
635
|
-
See [Real-time Sync](#real-time-sync) for
|
|
620
|
+
See [Real-time Sync](#real-time-sync) for a WebDAV sync-token example.
|
|
636
621
|
|
|
637
622
|
## RoolClient API
|
|
638
623
|
|
|
@@ -663,8 +648,6 @@ const client = new RoolClient({
|
|
|
663
648
|
| `duplicateSpace(sourceSpaceId, name): Promise<RoolSpace>` | Duplicate an existing space. Returns a handle to the new space. |
|
|
664
649
|
| `deleteSpace(id): Promise<void>` | Permanently delete a space (cannot be undone) |
|
|
665
650
|
| `importArchive(name, archive): Promise<RoolSpace>` | Import from a zip archive, creating a new space |
|
|
666
|
-
| `webdav(spaceId): RoolWebDAV` | Open a WebDAV client for a space's file storage |
|
|
667
|
-
| `getSpaceStorageUsage(spaceId): Promise<SpaceFileStorageUsage>` | Get WebDAV quota usage for a space |
|
|
668
651
|
|
|
669
652
|
### Channel Management
|
|
670
653
|
|
|
@@ -673,7 +656,6 @@ Manage channels on the `RoolSpace` handle:
|
|
|
673
656
|
| Method | Description |
|
|
674
657
|
|--------|-------------|
|
|
675
658
|
| `space.channels: ChannelInfo[]` | Live channel list (auto-updates via SSE) |
|
|
676
|
-
| `space.getChannels(): ChannelInfo[]` | List channels (deprecated — use `space.channels` instead) |
|
|
677
659
|
| `space.renameChannel(channelId, name): Promise<void>` | Rename a channel |
|
|
678
660
|
| `space.deleteChannel(channelId): Promise<void>` | Delete a channel and its interaction history |
|
|
679
661
|
| `channel.rename(name): Promise<void>` | Rename the current open channel |
|
|
@@ -717,39 +699,11 @@ client.on('userStorageChanged', ({ key, value, source }) => {
|
|
|
717
699
|
});
|
|
718
700
|
```
|
|
719
701
|
|
|
720
|
-
### Extensions
|
|
721
|
-
|
|
722
|
-
Manage and publish extensions. See [`@rool-dev/extension`](/extension/) for building extensions.
|
|
723
|
-
|
|
724
|
-
There are two distinct domains: your **personal library** (extensions you've created or installed) and the **published extensions** (extensions discoverable by all users). Each has its own return type.
|
|
725
|
-
|
|
726
|
-
#### Your Library (`ExtensionInfo`)
|
|
727
|
-
|
|
728
|
-
Manage extensions you own. Each `ExtensionInfo` includes `published` (whether it's listed in the marketplace) and `marketplaceExtensionId` (non-null if you installed it from someone else's listing, null if you authored it).
|
|
729
|
-
|
|
730
|
-
| Method | Description |
|
|
731
|
-
|--------|-------------|
|
|
732
|
-
| `uploadExtension(extensionId, options): Promise<ExtensionInfo>` | Upload or update an extension (`options.bundle`: zip with `index.html` and `manifest.json`) |
|
|
733
|
-
| `listExtensions(): Promise<ExtensionInfo[]>` | List your extensions |
|
|
734
|
-
| `getExtensionInfo(extensionId): Promise<ExtensionInfo \| null>` | Get info for a specific extension |
|
|
735
|
-
| `deleteExtension(extensionId): Promise<void>` | Delete an extension permanently (removes files and DB row) |
|
|
736
|
-
|
|
737
|
-
#### Marketplace (`PublishedExtensionInfo`)
|
|
738
|
-
|
|
739
|
-
Discover and install extensions published by other users.
|
|
740
|
-
|
|
741
|
-
| Method | Description |
|
|
742
|
-
|--------|-------------|
|
|
743
|
-
| `findExtensions(options?): Promise<PublishedExtensionInfo[]>` | Search the marketplace. Options: `query` (semantic search string), `limit` (default 20, max 100). Omit `query` to browse all. |
|
|
744
|
-
| `publishToPublic(extensionId): Promise<void>` | Publish one of your extensions to the marketplace |
|
|
745
|
-
| `unpublishFromPublic(extensionId): Promise<void>` | Remove from the marketplace (keeps the extension in your library) |
|
|
746
|
-
|
|
747
702
|
### Utilities
|
|
748
703
|
|
|
749
704
|
| Method | Description |
|
|
750
705
|
|--------|-------------|
|
|
751
|
-
| `RoolClient.
|
|
752
|
-
| `RoolClient.generateId(): string` | Same as `generateBasename()`; retained for callers minting non-object IDs (interactions, conversations, channels). |
|
|
706
|
+
| `RoolClient.generateId(): string` | Generate a unique 6-character alphanumeric ID. |
|
|
753
707
|
| `destroy(): void` | Clean up resources |
|
|
754
708
|
|
|
755
709
|
### Client Events
|
|
@@ -811,10 +765,8 @@ A space handle with a live SSE subscription. Extends `EventEmitter`. Manages use
|
|
|
811
765
|
| `addUser(userId, role): Promise<void>` | Add user to space |
|
|
812
766
|
| `removeUser(userId): Promise<void>` | Remove user from space |
|
|
813
767
|
| `setLinkAccess(linkAccess): Promise<void>` | Set URL sharing level |
|
|
814
|
-
| `getChannels(): ChannelInfo[]` | List channels (deprecated — use `channels` property instead) |
|
|
815
768
|
| `renameChannel(channelId, name): Promise<void>` | Rename a channel |
|
|
816
769
|
| `deleteChannel(channelId): Promise<void>` | Delete a channel |
|
|
817
|
-
| `installExtension(extensionId, channelId): Promise<string>` | Install an extension into a channel of this space. If you own it, wires it directly. If it's a marketplace extension, copies and builds a new extension in your library. Returns the channel ID. |
|
|
818
770
|
| `exportArchive(): Promise<Blob>` | Export space as zip archive |
|
|
819
771
|
| `getStorageUsage(): Promise<SpaceFileStorageUsage>` | Get WebDAV quota usage for this space |
|
|
820
772
|
| `fetchMachineResource(resource): Promise<Response>` | Fetch a resolved file `MachineResource` through this space |
|
|
@@ -824,7 +776,7 @@ A space handle with a live SSE subscription. Extends `EventEmitter`. Manages use
|
|
|
824
776
|
|
|
825
777
|
```typescript
|
|
826
778
|
space.on('channelCreated', (channel: ChannelInfo) => void) // New channel added
|
|
827
|
-
space.on('channelUpdated', (channel: ChannelInfo) => void) // Channel metadata changed
|
|
779
|
+
space.on('channelUpdated', (channel: ChannelInfo) => void) // Channel metadata changed
|
|
828
780
|
space.on('channelDeleted', (channelId: string) => void) // Channel removed
|
|
829
781
|
space.on('filesChanged', ({ source, timestamp }) => void) // WebDAV file storage changed; call webdav.syncCollection()
|
|
830
782
|
space.on('connectionStateChanged', (state: 'connected' | 'disconnected' | 'reconnecting') => void)
|
|
@@ -845,9 +797,6 @@ A channel is a named context within a space. All object operations, AI prompts,
|
|
|
845
797
|
| `userId: string` | Current user's ID |
|
|
846
798
|
| `channelId: string` | Channel ID (read-only, fixed at open time) |
|
|
847
799
|
| `isReadOnly: boolean` | True if viewer role |
|
|
848
|
-
| `extensionUrl: string \| null` | URL of the installed extension, or null if this is a plain channel |
|
|
849
|
-
| `extensionId: string \| null` | ID of the installed extension, or null if this is a plain channel |
|
|
850
|
-
| `manifest: ExtensionManifest \| null` | Extension manifest snapshot (name, icon, collections, etc.), or null |
|
|
851
800
|
|
|
852
801
|
### Lifecycle
|
|
853
802
|
|
|
@@ -867,8 +816,6 @@ All methods that accept a location accept either the canonical form or the short
|
|
|
867
816
|
|--------|-------------|
|
|
868
817
|
| `getObject(location): Promise<RoolObject \| undefined>` | Get an object, or undefined if not found. |
|
|
869
818
|
| `stat(location): RoolObjectStat \| undefined` | Get audit info for an object: when it was last modified, by whom, and where (channel/conversation/interaction). Sync read from local cache. |
|
|
870
|
-
| `findObjects(options): Promise<{ objects, message }>` | Find objects using structured filters and/or natural language. Results sorted by modifiedAt (desc by default). |
|
|
871
|
-
| `getObjectLocations(options?): string[]` | Get all object locations. Sorted by modifiedAt (desc by default). Options: `{ limit?, order? }`. |
|
|
872
819
|
| `createObject(collection, body, options?): Promise<{ object, message }>` | Create a new object in `collection`. The SDK mints a random basename unless you pass `options.basename`. |
|
|
873
820
|
| `updateObject(location, options): Promise<{ object, message }>` | Update an existing object's body. |
|
|
874
821
|
| `moveObject(from, to, options?): Promise<{ object, message }>` | Rename or relocate an object. See [Moving and Renaming](#moving-and-renaming). |
|
|
@@ -961,59 +908,6 @@ await channel.moveObject(from, to, {
|
|
|
961
908
|
| `ephemeral` | If true, the operation won't be recorded in interaction history. |
|
|
962
909
|
| `parentInteractionId` | Conversation tree parent. Omit to auto-continue; pass `null` for a new root. |
|
|
963
910
|
|
|
964
|
-
#### findObjects
|
|
965
|
-
|
|
966
|
-
Find objects using structured filters and/or natural language.
|
|
967
|
-
|
|
968
|
-
- **`where` only** — exact-match filtering, no AI, no credits.
|
|
969
|
-
- **`collection` only** — filter by collection name, no AI, no credits.
|
|
970
|
-
- **`prompt` only** — AI-powered semantic query over all objects.
|
|
971
|
-
- **`where` + `prompt`** — `where` (and `locations`) narrow the data set first, then the AI queries within the constrained set.
|
|
972
|
-
|
|
973
|
-
| Option | Description |
|
|
974
|
-
|--------|-------------|
|
|
975
|
-
| `where` | Exact-match body-field filter (e.g. `{ status: 'published' }`). Values must match literally — no operators or `{{placeholders}}`. When combined with `prompt`, constrains which objects the AI can see. |
|
|
976
|
-
| `collection` | Filter by collection name. |
|
|
977
|
-
| `prompt` | Natural language query. Triggers AI evaluation (uses credits). |
|
|
978
|
-
| `limit` | Maximum number of results. |
|
|
979
|
-
| `locations` | Scope to specific object locations. Constrains the candidate set in both structured and AI queries. |
|
|
980
|
-
| `order` | Sort order by modifiedAt: `'asc'` or `'desc'` (default: `'desc'`). |
|
|
981
|
-
| `ephemeral` | If true, the query won't be recorded in interaction history. Useful for responsive search. |
|
|
982
|
-
|
|
983
|
-
**Examples:**
|
|
984
|
-
|
|
985
|
-
```typescript
|
|
986
|
-
// Filter by collection (no AI, no credits)
|
|
987
|
-
const { objects } = await channel.findObjects({
|
|
988
|
-
collection: 'article'
|
|
989
|
-
});
|
|
990
|
-
|
|
991
|
-
// Exact field matching (no AI, no credits)
|
|
992
|
-
const { objects } = await channel.findObjects({
|
|
993
|
-
where: { status: 'published' }
|
|
994
|
-
});
|
|
995
|
-
|
|
996
|
-
// Combine collection and field filters
|
|
997
|
-
const { objects } = await channel.findObjects({
|
|
998
|
-
collection: 'article',
|
|
999
|
-
where: { status: 'published' }
|
|
1000
|
-
});
|
|
1001
|
-
|
|
1002
|
-
// Pure natural language query (AI interprets)
|
|
1003
|
-
const { objects, message } = await channel.findObjects({
|
|
1004
|
-
prompt: 'articles about space exploration published this year'
|
|
1005
|
-
});
|
|
1006
|
-
|
|
1007
|
-
// Combined: collection + where narrow the data, prompt queries within it
|
|
1008
|
-
const { objects } = await channel.findObjects({
|
|
1009
|
-
collection: 'article',
|
|
1010
|
-
prompt: 'that discuss climate solutions positively',
|
|
1011
|
-
limit: 10
|
|
1012
|
-
});
|
|
1013
|
-
```
|
|
1014
|
-
|
|
1015
|
-
When `where` or `locations` are provided with a `prompt`, the AI only sees the filtered subset — not the full space. The returned `message` explains the query result.
|
|
1016
|
-
|
|
1017
911
|
### Undo/Redo
|
|
1018
912
|
|
|
1019
913
|
| Method | Description |
|
|
@@ -1041,12 +935,13 @@ Store arbitrary data alongside the space without it being part of an object's bo
|
|
|
1041
935
|
|
|
1042
936
|
Every space has authenticated file storage. WebDAV is the SDK surface for that storage: paths are relative to the space root and collection operations use WebDAV collection semantics. Human/AI file links use `rool-machine:/rool-drive/...`; resolve those links with `resolveMachineResource()` and fetch file resources with `space.fetchMachineResource(resource)`.
|
|
1043
937
|
|
|
1044
|
-
|
|
938
|
+
Open a space, then use `space.webdav`.
|
|
1045
939
|
|
|
1046
940
|
```typescript
|
|
1047
941
|
import { resolveMachineResource } from '@rool-dev/sdk';
|
|
1048
942
|
|
|
1049
|
-
const
|
|
943
|
+
const space = await client.openSpace('space-id');
|
|
944
|
+
const webdav = space.webdav;
|
|
1050
945
|
|
|
1051
946
|
await webdav.mkcol('docs');
|
|
1052
947
|
await webdav.put('docs/readme.md', '# Hello', {
|
|
@@ -1091,8 +986,6 @@ Paths are space-relative (`docs/readme.md`, not `/docs/readme.md`). WebDAV metho
|
|
|
1091
986
|
|
|
1092
987
|
| Method | Description |
|
|
1093
988
|
|--------|-------------|
|
|
1094
|
-
| `client.webdav(spaceId)` | Create a WebDAV client for a space |
|
|
1095
|
-
| `client.getSpaceStorageUsage(spaceId)` | Get WebDAV quota usage for a space |
|
|
1096
989
|
| `space.webdav` | WebDAV client for an open space |
|
|
1097
990
|
| `space.getStorageUsage()` | Get WebDAV quota usage for an open space |
|
|
1098
991
|
| `webdav.getStorageUsage()` | Get WebDAV quota usage through the WebDAV client |
|
|
@@ -1225,37 +1118,23 @@ The archive bundles `data.json` (objects, metadata, and channels) together with
|
|
|
1225
1118
|
|
|
1226
1119
|
### Channel Events
|
|
1227
1120
|
|
|
1228
|
-
|
|
1121
|
+
Channel events are for channel/conversation state. Object and file reactivity goes through `space.on('filesChanged' | 'filesReset')` plus WebDAV `syncCollection()`.
|
|
1229
1122
|
|
|
1230
1123
|
```typescript
|
|
1231
|
-
//
|
|
1232
|
-
// - 'local_user': This client made the change
|
|
1233
|
-
// - 'remote_user': Another user/client made the change
|
|
1234
|
-
// - 'remote_agent': AI agent made the change
|
|
1235
|
-
// - 'system': Resync after error
|
|
1236
|
-
|
|
1237
|
-
// Object events — payload includes the full RoolObject
|
|
1238
|
-
channel.on('objectCreated', ({ location, object, source }) => void)
|
|
1239
|
-
channel.on('objectUpdated', ({ location, object, source }) => void)
|
|
1240
|
-
channel.on('objectDeleted', ({ location, source }) => void)
|
|
1241
|
-
channel.on('objectMoved', ({ from, to, object, source }) => void)
|
|
1242
|
-
|
|
1243
|
-
// Space metadata
|
|
1244
|
-
channel.on('metadataUpdated', ({ metadata, source }) => void)
|
|
1245
|
-
|
|
1246
|
-
// Collection schema changed
|
|
1247
|
-
channel.on('schemaUpdated', ({ schema, source }) => void)
|
|
1248
|
-
|
|
1249
|
-
// Channel metadata updated (name, extensionUrl)
|
|
1124
|
+
// Channel metadata updated
|
|
1250
1125
|
channel.on('channelUpdated', ({ channelId, source }) => void)
|
|
1251
1126
|
|
|
1252
1127
|
// Conversation interaction history updated
|
|
1253
1128
|
channel.on('conversationUpdated', ({ conversationId, channelId, source }) => void)
|
|
1254
1129
|
|
|
1130
|
+
// Space metadata / schema compatibility events
|
|
1131
|
+
channel.on('metadataUpdated', ({ metadata, source }) => void)
|
|
1132
|
+
channel.on('schemaUpdated', ({ schema, source }) => void)
|
|
1133
|
+
|
|
1255
1134
|
// Full state replacement (undo/redo, resync after error)
|
|
1256
1135
|
channel.on('reset', ({ source }) => void)
|
|
1257
1136
|
|
|
1258
|
-
// Sync error occurred
|
|
1137
|
+
// Sync error occurred
|
|
1259
1138
|
channel.on('syncError', (error: Error) => void)
|
|
1260
1139
|
```
|
|
1261
1140
|
|
|
@@ -1386,13 +1265,10 @@ interface Channel {
|
|
|
1386
1265
|
createdAt: number; // Timestamp when channel was created
|
|
1387
1266
|
createdBy: string; // User ID who created the channel
|
|
1388
1267
|
createdByName?: string; // Display name at time of creation
|
|
1389
|
-
extensionUrl?: string; // URL of installed extension (set by installExtension)
|
|
1390
|
-
extensionId?: string; // ID of installed extension (user_extensions.extension_id)
|
|
1391
|
-
manifest?: ExtensionManifest; // Extension manifest snapshot (set when extension is wired)
|
|
1392
1268
|
conversations: Record<string, Conversation>; // Keyed by conversation ID
|
|
1393
1269
|
}
|
|
1394
1270
|
|
|
1395
|
-
// Channel summary info (
|
|
1271
|
+
// Channel summary info (used by space.channels)
|
|
1396
1272
|
interface ChannelInfo {
|
|
1397
1273
|
id: string;
|
|
1398
1274
|
name: string | null;
|
|
@@ -1400,9 +1276,6 @@ interface ChannelInfo {
|
|
|
1400
1276
|
createdBy: string;
|
|
1401
1277
|
createdByName: string | null;
|
|
1402
1278
|
interactionCount: number;
|
|
1403
|
-
extensionUrl: string | null; // URL of installed extension, or null
|
|
1404
|
-
extensionId: string | null; // ID of installed extension, or null
|
|
1405
|
-
manifest: ExtensionManifest | null; // Extension manifest snapshot, or null
|
|
1406
1279
|
}
|
|
1407
1280
|
```
|
|
1408
1281
|
|
package/dist/channel.d.ts
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import { EventEmitter } from './event-emitter.js';
|
|
2
2
|
import type { GraphQLClient } from './graphql.js';
|
|
3
3
|
import type { RestClient } from './rest.js';
|
|
4
|
-
import type
|
|
4
|
+
import { type RoolWebDAV } from './webdav.js';
|
|
5
5
|
import type { Logger } from './logger.js';
|
|
6
|
-
import type { RoolObject, RoolObjectStat, ChannelEvents, RoolUserRole, PromptOptions,
|
|
6
|
+
import type { RoolObject, GetObjectsResult, RoolObjectStat, ChannelEvents, RoolUserRole, PromptOptions, UpdateObjectOptions, MoveObjectOptions, ChannelEvent, Interaction, Channel, ConversationInfo, LinkAccess, SpaceSchema, CollectionDef, FieldDef, CollectionOptions } from './types.js';
|
|
7
7
|
export declare function generateEntityId(): string;
|
|
8
8
|
export interface ChannelConfig {
|
|
9
9
|
id: string;
|
|
@@ -12,9 +12,7 @@ export interface ChannelConfig {
|
|
|
12
12
|
linkAccess: LinkAccess;
|
|
13
13
|
/** Current user's ID (for identifying own interactions) */
|
|
14
14
|
userId: string;
|
|
15
|
-
/** Object
|
|
16
|
-
objectLocations: string[];
|
|
17
|
-
/** Object stats keyed by location */
|
|
15
|
+
/** Object stats keyed by path */
|
|
18
16
|
objectStats: Record<string, RoolObjectStat>;
|
|
19
17
|
/** Collection schema */
|
|
20
18
|
schema: SpaceSchema;
|
|
@@ -37,10 +35,10 @@ export interface ChannelConfig {
|
|
|
37
35
|
* at open time and cannot be changed. To use a different channel,
|
|
38
36
|
* open a second one.
|
|
39
37
|
*
|
|
40
|
-
* Objects are addressed by
|
|
41
|
-
* Only schema, metadata,
|
|
42
|
-
*
|
|
43
|
-
*
|
|
38
|
+
* Objects are addressed by machine path (`/space/.../*.json`).
|
|
39
|
+
* Only schema, metadata, object stats, and the channel's own history are cached
|
|
40
|
+
* locally. Object bodies are fetched on demand. Object/file reactivity is
|
|
41
|
+
* exposed at the space level via WebDAV sync notifications.
|
|
44
42
|
*/
|
|
45
43
|
export declare class RoolChannel extends EventEmitter<ChannelEvents> {
|
|
46
44
|
private _id;
|
|
@@ -59,12 +57,8 @@ export declare class RoolChannel extends EventEmitter<ChannelEvents> {
|
|
|
59
57
|
private _meta;
|
|
60
58
|
private _schema;
|
|
61
59
|
private _channel;
|
|
62
|
-
private _objectLocations;
|
|
63
60
|
private _objectStats;
|
|
64
61
|
private _activeLeaves;
|
|
65
|
-
private _pendingMutations;
|
|
66
|
-
private _objectResolvers;
|
|
67
|
-
private _objectBuffer;
|
|
68
62
|
constructor(config: ChannelConfig);
|
|
69
63
|
/**
|
|
70
64
|
* Handle an event from the shared space subscription.
|
|
@@ -80,7 +74,6 @@ export declare class RoolChannel extends EventEmitter<ChannelEvents> {
|
|
|
80
74
|
_applyResyncData(data: {
|
|
81
75
|
meta: Record<string, unknown>;
|
|
82
76
|
schema: SpaceSchema;
|
|
83
|
-
objectLocations: string[];
|
|
84
77
|
objectStats: Record<string, RoolObjectStat>;
|
|
85
78
|
channel: Channel | undefined;
|
|
86
79
|
}): void;
|
|
@@ -105,18 +98,6 @@ export declare class RoolChannel extends EventEmitter<ChannelEvents> {
|
|
|
105
98
|
*/
|
|
106
99
|
get conversationId(): string;
|
|
107
100
|
get isReadOnly(): boolean;
|
|
108
|
-
/**
|
|
109
|
-
* Get the extension URL if this channel was created via installExtension, or null.
|
|
110
|
-
*/
|
|
111
|
-
get extensionUrl(): string | null;
|
|
112
|
-
/**
|
|
113
|
-
* Get the extension ID if this channel has an installed extension, or null.
|
|
114
|
-
*/
|
|
115
|
-
get extensionId(): string | null;
|
|
116
|
-
/**
|
|
117
|
-
* Get the extension manifest if this channel has an installed extension, or null.
|
|
118
|
-
*/
|
|
119
|
-
get manifest(): ExtensionManifest | null;
|
|
120
101
|
/**
|
|
121
102
|
* Get the active branch of the current conversation as a flat array (root → leaf).
|
|
122
103
|
* Walks from the active leaf up through parentId pointers.
|
|
@@ -178,83 +159,35 @@ export declare class RoolChannel extends EventEmitter<ChannelEvents> {
|
|
|
178
159
|
redo(): Promise<boolean>;
|
|
179
160
|
/** Clear the space's checkpoint history. */
|
|
180
161
|
clearHistory(): Promise<void>;
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
*/
|
|
192
|
-
stat(location: string): RoolObjectStat | undefined;
|
|
193
|
-
/**
|
|
194
|
-
* Find objects using structured filters and/or natural language.
|
|
195
|
-
*/
|
|
196
|
-
findObjects(options: FindObjectsOptions): Promise<{
|
|
197
|
-
objects: RoolObject[];
|
|
198
|
-
message: string;
|
|
199
|
-
}>;
|
|
200
|
-
/** @internal */
|
|
201
|
-
_findObjectsImpl(options: FindObjectsOptions, conversationId: string): Promise<{
|
|
202
|
-
objects: RoolObject[];
|
|
203
|
-
message: string;
|
|
204
|
-
}>;
|
|
205
|
-
/**
|
|
206
|
-
* Get all object locations (sync, from local cache).
|
|
207
|
-
* The list is loaded on open and kept current via SSE events.
|
|
208
|
-
*/
|
|
209
|
-
getObjectLocations(options?: {
|
|
210
|
-
limit?: number;
|
|
211
|
-
order?: 'asc' | 'desc';
|
|
212
|
-
}): string[];
|
|
213
|
-
/**
|
|
214
|
-
* Create a new object in the given collection.
|
|
215
|
-
*
|
|
216
|
-
* @param collection - The collection (must exist in the schema)
|
|
217
|
-
* @param body - Object body fields. Use `{{placeholder}}` for AI-generated content.
|
|
218
|
-
* Fields prefixed with `_` are hidden from AI.
|
|
219
|
-
* @param options.basename - Specific basename to use. If omitted, the SDK generates a random one.
|
|
220
|
-
* @param options.ephemeral - If true, the operation won't be recorded in interaction history.
|
|
221
|
-
* @returns The created object and a status message.
|
|
222
|
-
*/
|
|
223
|
-
createObject(collection: string, body: Record<string, unknown>, options?: CreateObjectOptions): Promise<{
|
|
162
|
+
private davHeaders;
|
|
163
|
+
private readObject;
|
|
164
|
+
/** Get an object JSON file by machine path. Fetches from the server on each call. */
|
|
165
|
+
getObject(path: string): Promise<RoolObject | undefined>;
|
|
166
|
+
/** Get object JSON files by machine path in bulk. Duplicate paths are fetched once. */
|
|
167
|
+
getObjects(paths: string[]): Promise<GetObjectsResult>;
|
|
168
|
+
/** Get an object's cached audit information. */
|
|
169
|
+
stat(path: string): RoolObjectStat | undefined;
|
|
170
|
+
/** Create or replace an object JSON file at an exact machine path. */
|
|
171
|
+
putObject(path: string, body: Record<string, unknown>): Promise<{
|
|
224
172
|
object: RoolObject;
|
|
225
173
|
message: string;
|
|
226
174
|
}>;
|
|
227
175
|
/** @internal */
|
|
228
|
-
|
|
176
|
+
_putObjectImpl(path: string, body: Record<string, unknown>, conversationId: string): Promise<{
|
|
229
177
|
object: RoolObject;
|
|
230
178
|
message: string;
|
|
231
179
|
}>;
|
|
232
|
-
/**
|
|
233
|
-
|
|
234
|
-
*
|
|
235
|
-
* @param location - The object's location (canonical or short form)
|
|
236
|
-
* @param options.data - Fields to add or update. Pass `null` to delete a field. Use `{{placeholder}}` for AI-generated content.
|
|
237
|
-
* @param options.prompt - AI prompt to drive the update.
|
|
238
|
-
* @param options.ephemeral - If true, the operation won't be recorded in interaction history.
|
|
239
|
-
*/
|
|
240
|
-
updateObject(location: string, options: UpdateObjectOptions): Promise<{
|
|
180
|
+
/** Patch an existing object. Null or undefined deletes a field. */
|
|
181
|
+
patchObject(path: string, options: UpdateObjectOptions): Promise<{
|
|
241
182
|
object: RoolObject;
|
|
242
183
|
message: string;
|
|
243
184
|
}>;
|
|
244
185
|
/** @internal */
|
|
245
|
-
|
|
186
|
+
_patchObjectImpl(path: string, options: UpdateObjectOptions, conversationId: string): Promise<{
|
|
246
187
|
object: RoolObject;
|
|
247
188
|
message: string;
|
|
248
189
|
}>;
|
|
249
|
-
/**
|
|
250
|
-
* Move (rename or relocate) an object to a new location.
|
|
251
|
-
* Use this to rename, change collection, or atomically rewrite the body.
|
|
252
|
-
*
|
|
253
|
-
* @param from - Current location
|
|
254
|
-
* @param to - New location
|
|
255
|
-
* @param options.body - Replace the body atomically as part of the move.
|
|
256
|
-
* @param options.ephemeral - If true, the operation won't be recorded in interaction history.
|
|
257
|
-
*/
|
|
190
|
+
/** Move an object JSON file to a new machine path, optionally replacing its body. */
|
|
258
191
|
moveObject(from: string, to: string, options?: MoveObjectOptions): Promise<{
|
|
259
192
|
object: RoolObject;
|
|
260
193
|
message: string;
|
|
@@ -264,23 +197,22 @@ export declare class RoolChannel extends EventEmitter<ChannelEvents> {
|
|
|
264
197
|
object: RoolObject;
|
|
265
198
|
message: string;
|
|
266
199
|
}>;
|
|
267
|
-
/**
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
deleteObjects(locations: string[]): Promise<void>;
|
|
200
|
+
/** Delete object JSON files by machine path. */
|
|
201
|
+
deleteObjects(paths: string[]): Promise<void>;
|
|
202
|
+
/** @deprecated Use deleteObjects instead. */
|
|
203
|
+
deletePaths(paths: string[]): Promise<void>;
|
|
272
204
|
/** @internal */
|
|
273
|
-
_deleteObjectsImpl(
|
|
205
|
+
_deleteObjectsImpl(paths: string[], conversationId: string): Promise<void>;
|
|
274
206
|
/** Get the current schema for this space. */
|
|
275
207
|
getSchema(): SpaceSchema;
|
|
276
208
|
/** Create a new collection schema. */
|
|
277
|
-
createCollection(name: string, fields: FieldDef[]): Promise<CollectionDef>;
|
|
209
|
+
createCollection(name: string, fields: FieldDef[] | CollectionDef, options?: CollectionOptions): Promise<CollectionDef>;
|
|
278
210
|
/** @internal */
|
|
279
|
-
_createCollectionImpl(name: string, fields: FieldDef[], conversationId: string): Promise<CollectionDef>;
|
|
211
|
+
_createCollectionImpl(name: string, fields: FieldDef[] | CollectionDef, options: CollectionOptions | undefined, conversationId: string): Promise<CollectionDef>;
|
|
280
212
|
/** Alter an existing collection schema, replacing its field definitions. */
|
|
281
|
-
alterCollection(name: string, fields: FieldDef[]): Promise<CollectionDef>;
|
|
213
|
+
alterCollection(name: string, fields: FieldDef[] | CollectionDef, options?: CollectionOptions): Promise<CollectionDef>;
|
|
282
214
|
/** @internal */
|
|
283
|
-
_alterCollectionImpl(name: string, fields: FieldDef[], conversationId: string): Promise<CollectionDef>;
|
|
215
|
+
_alterCollectionImpl(name: string, fields: FieldDef[] | CollectionDef, options: CollectionOptions | undefined, conversationId: string): Promise<CollectionDef>;
|
|
284
216
|
/** Drop a collection schema. */
|
|
285
217
|
dropCollection(name: string): Promise<void>;
|
|
286
218
|
/** @internal */
|
|
@@ -334,28 +266,11 @@ export declare class RoolChannel extends EventEmitter<ChannelEvents> {
|
|
|
334
266
|
}): Promise<Response>;
|
|
335
267
|
private uploadAttachment;
|
|
336
268
|
private ensureCollection;
|
|
337
|
-
/**
|
|
338
|
-
* Register a collector that resolves when the object arrives via SSE.
|
|
339
|
-
* @internal
|
|
340
|
-
*/
|
|
341
|
-
private _collectObject;
|
|
342
|
-
/** @internal */
|
|
343
|
-
private _cancelCollector;
|
|
344
|
-
/** @internal */
|
|
345
|
-
private _deliverObject;
|
|
346
269
|
/**
|
|
347
270
|
* Handle a channel event from the subscription.
|
|
348
271
|
* @internal
|
|
349
272
|
*/
|
|
350
273
|
private handleChannelEvent;
|
|
351
|
-
/** @internal */
|
|
352
|
-
private _handleObjectCreated;
|
|
353
|
-
/** @internal */
|
|
354
|
-
private _handleObjectUpdated;
|
|
355
|
-
/** @internal */
|
|
356
|
-
private _handleObjectDeleted;
|
|
357
|
-
/** @internal */
|
|
358
|
-
private _handleObjectMoved;
|
|
359
274
|
}
|
|
360
275
|
/**
|
|
361
276
|
* A lightweight handle for a specific conversation within a channel.
|
|
@@ -382,18 +297,13 @@ export declare class ConversationHandle {
|
|
|
382
297
|
setSystemInstruction(instruction: string | null): Promise<void>;
|
|
383
298
|
/** Rename this conversation. */
|
|
384
299
|
rename(name: string): Promise<void>;
|
|
385
|
-
/**
|
|
386
|
-
|
|
387
|
-
objects: RoolObject[];
|
|
388
|
-
message: string;
|
|
389
|
-
}>;
|
|
390
|
-
/** Create a new object. */
|
|
391
|
-
createObject(collection: string, body: Record<string, unknown>, options?: CreateObjectOptions): Promise<{
|
|
300
|
+
/** Create or replace an object JSON file. */
|
|
301
|
+
putObject(path: string, body: Record<string, unknown>): Promise<{
|
|
392
302
|
object: RoolObject;
|
|
393
303
|
message: string;
|
|
394
304
|
}>;
|
|
395
|
-
/**
|
|
396
|
-
|
|
305
|
+
/** Patch an existing object JSON file. */
|
|
306
|
+
patchObject(path: string, options: UpdateObjectOptions): Promise<{
|
|
397
307
|
object: RoolObject;
|
|
398
308
|
message: string;
|
|
399
309
|
}>;
|
|
@@ -402,17 +312,19 @@ export declare class ConversationHandle {
|
|
|
402
312
|
object: RoolObject;
|
|
403
313
|
message: string;
|
|
404
314
|
}>;
|
|
405
|
-
/** Delete
|
|
406
|
-
deleteObjects(
|
|
315
|
+
/** Delete object JSON files by path. */
|
|
316
|
+
deleteObjects(paths: string[]): Promise<void>;
|
|
317
|
+
/** @deprecated Use deleteObjects instead. */
|
|
318
|
+
deletePaths(paths: string[]): Promise<void>;
|
|
407
319
|
/** Send a prompt to the AI agent, scoped to this conversation's history. */
|
|
408
320
|
prompt(text: string, options?: PromptOptions): Promise<{
|
|
409
321
|
message: string;
|
|
410
322
|
objects: RoolObject[];
|
|
411
323
|
}>;
|
|
412
324
|
/** Create a new collection schema. */
|
|
413
|
-
createCollection(name: string, fields: FieldDef[]): Promise<CollectionDef>;
|
|
325
|
+
createCollection(name: string, fields: FieldDef[] | CollectionDef, options?: CollectionOptions): Promise<CollectionDef>;
|
|
414
326
|
/** Alter an existing collection schema. */
|
|
415
|
-
alterCollection(name: string, fields: FieldDef[]): Promise<CollectionDef>;
|
|
327
|
+
alterCollection(name: string, fields: FieldDef[] | CollectionDef, options?: CollectionOptions): Promise<CollectionDef>;
|
|
416
328
|
/** Drop a collection schema. */
|
|
417
329
|
dropCollection(name: string): Promise<void>;
|
|
418
330
|
setMetadata(key: string, value: unknown): void;
|