@rool-dev/sdk 0.9.0-dev.f75b2d1 → 0.10.0-dev.97d979e
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 +313 -149
- package/dist/channel.d.ts +86 -158
- package/dist/channel.d.ts.map +1 -1
- package/dist/channel.js +276 -333
- package/dist/channel.js.map +1 -1
- package/dist/client.d.ts +24 -4
- package/dist/client.d.ts.map +1 -1
- package/dist/client.js +35 -3
- package/dist/client.js.map +1 -1
- package/dist/graphql.d.ts +35 -19
- package/dist/graphql.d.ts.map +1 -1
- package/dist/graphql.js +112 -128
- package/dist/graphql.js.map +1 -1
- package/dist/index.d.ts +7 -3
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +5 -1
- package/dist/index.js.map +1 -1
- package/dist/locations.d.ts +34 -0
- package/dist/locations.d.ts.map +1 -0
- package/dist/locations.js +90 -0
- package/dist/locations.js.map +1 -0
- package/dist/machine.d.ts +16 -0
- package/dist/machine.d.ts.map +1 -0
- package/dist/machine.js +51 -0
- package/dist/machine.js.map +1 -0
- package/dist/space.d.ts +13 -2
- package/dist/space.d.ts.map +1 -1
- package/dist/space.js +16 -6
- package/dist/space.js.map +1 -1
- package/dist/subscription.d.ts.map +1 -1
- package/dist/subscription.js +9 -12
- package/dist/subscription.js.map +1 -1
- package/dist/types.d.ts +70 -37
- package/dist/types.d.ts.map +1 -1
- package/dist/webdav.d.ts +15 -11
- package/dist/webdav.d.ts.map +1 -1
- package/dist/webdav.js +30 -35
- package/dist/webdav.js.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -9,7 +9,7 @@ The SDK manages authentication, real-time synchronization, and per-space file st
|
|
|
9
9
|
- **Spaces** — Containers for objects, schema, metadata, channels, and files
|
|
10
10
|
- **Channels** — Named contexts within a space. All object and AI operations go through a channel.
|
|
11
11
|
- **Conversations** — Independent interaction histories within a channel.
|
|
12
|
-
- **Objects** —
|
|
12
|
+
- **Objects** — Records addressed by a **location** path (`/space/<collection>/<basename>.json`). The body holds user-defined fields. References between objects are body fields whose values are location strings.
|
|
13
13
|
- **AI operations** — Create, update, or query objects using natural language and `{{placeholders}}`
|
|
14
14
|
- **File storage** — Every space has WebDAV file storage
|
|
15
15
|
|
|
@@ -43,24 +43,19 @@ await channel.createCollection('body', [
|
|
|
43
43
|
{ name: 'orbits', type: { kind: 'maybe', inner: { kind: 'ref' } } },
|
|
44
44
|
]);
|
|
45
45
|
|
|
46
|
-
// Create objects with AI-generated content using {{placeholders}}
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
name: 'Earth',
|
|
60
|
-
mass: '{{mass in Earth masses}}',
|
|
61
|
-
radius: '{{radius in km}}',
|
|
62
|
-
orbits: sun.id // Reference to the sun object
|
|
63
|
-
}
|
|
46
|
+
// Create objects with AI-generated content using {{placeholders}}.
|
|
47
|
+
// First arg is the collection, second is the body.
|
|
48
|
+
const { object: sun } = await channel.createObject('body', {
|
|
49
|
+
name: 'Sun',
|
|
50
|
+
mass: '{{mass in solar masses}}',
|
|
51
|
+
radius: '{{radius in km}}',
|
|
52
|
+
}, { basename: 'sun' });
|
|
53
|
+
|
|
54
|
+
const { object: earth } = await channel.createObject('body', {
|
|
55
|
+
name: 'Earth',
|
|
56
|
+
mass: '{{mass in Earth masses}}',
|
|
57
|
+
radius: '{{radius in km}}',
|
|
58
|
+
orbits: sun.location, // Reference to the sun via its location
|
|
64
59
|
});
|
|
65
60
|
|
|
66
61
|
// Use the AI agent to work with your data
|
|
@@ -68,7 +63,7 @@ const { message, objects } = await channel.prompt(
|
|
|
68
63
|
'Add the other planets in our solar system, each referencing the Sun'
|
|
69
64
|
);
|
|
70
65
|
console.log(message); // AI explains what it did
|
|
71
|
-
console.log(`
|
|
66
|
+
console.log(`Modified ${objects.length} objects`);
|
|
72
67
|
|
|
73
68
|
// Query with natural language
|
|
74
69
|
const { objects: innerPlanets } = await channel.findObjects({
|
|
@@ -187,52 +182,105 @@ thread.getInteractions(); // Returns the blue branch (root → leaf)
|
|
|
187
182
|
- `prompt()` with no `parentInteractionId` auto-continues from `activeLeafId`
|
|
188
183
|
- `prompt()` with `parentInteractionId: null` starts a new root-level branch
|
|
189
184
|
|
|
190
|
-
### Objects
|
|
185
|
+
### Objects, Locations, and References
|
|
191
186
|
|
|
192
|
-
|
|
187
|
+
Every object lives at a **location** — a path of the form `/space/<collection>/<basename>.json`. The collection is the parent directory, the basename is the filename without `.json`, and together they fully identify the object.
|
|
193
188
|
|
|
194
189
|
```typescript
|
|
195
|
-
{
|
|
190
|
+
{
|
|
191
|
+
location: '/space/article/welcome.json',
|
|
192
|
+
collection: 'article',
|
|
193
|
+
basename: 'welcome',
|
|
194
|
+
body: { title: 'Hello World', status: 'draft' },
|
|
195
|
+
}
|
|
196
196
|
```
|
|
197
197
|
|
|
198
|
-
**
|
|
198
|
+
The **body** holds the user-defined data.
|
|
199
|
+
|
|
200
|
+
**References** between objects are body fields whose values are location strings:
|
|
199
201
|
|
|
200
202
|
```typescript
|
|
201
|
-
// A planet references a star
|
|
202
|
-
{
|
|
203
|
+
// A planet references a star
|
|
204
|
+
{
|
|
205
|
+
location: '/space/body/earth.json',
|
|
206
|
+
collection: 'body',
|
|
207
|
+
basename: 'earth',
|
|
208
|
+
body: { name: 'Earth', orbits: '/space/body/sun.json' },
|
|
209
|
+
}
|
|
203
210
|
|
|
204
211
|
// An array of references
|
|
205
|
-
{
|
|
212
|
+
{
|
|
213
|
+
location: '/space/team/alpha.json',
|
|
214
|
+
collection: 'team',
|
|
215
|
+
basename: 'alpha',
|
|
216
|
+
body: {
|
|
217
|
+
name: 'Alpha',
|
|
218
|
+
members: [
|
|
219
|
+
'/space/user/alice.json',
|
|
220
|
+
'/space/user/bob.json',
|
|
221
|
+
'/space/user/carol.json',
|
|
222
|
+
],
|
|
223
|
+
},
|
|
224
|
+
}
|
|
225
|
+
```
|
|
226
|
+
|
|
227
|
+
References are just data — no special API is needed to create or remove them. Set a field to a location string to create a reference; clear it to remove it.
|
|
228
|
+
|
|
229
|
+
#### Location helpers
|
|
230
|
+
|
|
231
|
+
```typescript
|
|
232
|
+
import { loc, parseLocation, normalizeLocation, generateBasename } from '@rool-dev/sdk';
|
|
233
|
+
|
|
234
|
+
loc('article', 'welcome'); // '/space/article/welcome.json'
|
|
235
|
+
parseLocation('/space/article/welcome.json'); // { collection: 'article', basename: 'welcome' }
|
|
236
|
+
|
|
237
|
+
// normalizeLocation accepts canonical or short form and returns canonical
|
|
238
|
+
normalizeLocation('article/welcome'); // '/space/article/welcome.json'
|
|
239
|
+
normalizeLocation('/space/article/welcome.json'); // unchanged
|
|
240
|
+
|
|
241
|
+
// 6-char random basename — same generator the SDK uses by default
|
|
242
|
+
generateBasename(); // e.g., 'X7kQ9p'
|
|
206
243
|
```
|
|
207
244
|
|
|
208
|
-
|
|
245
|
+
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.
|
|
246
|
+
|
|
247
|
+
#### Machine resource links
|
|
248
|
+
|
|
249
|
+
```typescript
|
|
250
|
+
import { resolveMachineResource } from '@rool-dev/sdk';
|
|
251
|
+
|
|
252
|
+
const objectResource = resolveMachineResource('/space/article/welcome.json');
|
|
253
|
+
// { kind: 'object', path: '/space/article/welcome.json' }
|
|
254
|
+
|
|
255
|
+
const fileResource = resolveMachineResource('/rool-drive/docs/readme.md');
|
|
256
|
+
// { kind: 'file', path: '/rool-drive/docs/readme.md' }
|
|
257
|
+
```
|
|
258
|
+
|
|
259
|
+
`rool-machine:` is the canonical URI scheme for user-visible resources from the Rool machine filesystem. `resolveMachineResource()` accepts either canonical `rool-machine:/...` URIs or bare machine paths such as `/rool-drive/...`, and returns the resource kind plus machine path. Fetch file resources through `space.fetchMachineResource(resource)`.
|
|
209
260
|
|
|
210
261
|
### AI Placeholder Pattern
|
|
211
262
|
|
|
212
|
-
Use `{{description}}` in field values to have AI generate content:
|
|
263
|
+
Use `{{description}}` in body field values to have AI generate content:
|
|
213
264
|
|
|
214
265
|
```typescript
|
|
215
266
|
// Create with AI-generated content
|
|
216
|
-
await channel.createObject({
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
headline: '{{catchy headline about coffee}}',
|
|
220
|
-
body: '{{informative paragraph}}'
|
|
221
|
-
}
|
|
267
|
+
await channel.createObject('article', {
|
|
268
|
+
headline: '{{catchy headline about coffee}}',
|
|
269
|
+
body: '{{informative paragraph}}',
|
|
222
270
|
});
|
|
223
271
|
|
|
224
272
|
// Update existing content with AI
|
|
225
|
-
await channel.updateObject('
|
|
273
|
+
await channel.updateObject('/space/article/welcome.json', {
|
|
226
274
|
prompt: 'Make the body shorter and more casual'
|
|
227
275
|
});
|
|
228
276
|
|
|
229
277
|
// Add new AI-generated field to existing object
|
|
230
|
-
await channel.updateObject('
|
|
278
|
+
await channel.updateObject('/space/article/welcome.json', {
|
|
231
279
|
data: { summary: '{{one-sentence summary}}' }
|
|
232
280
|
});
|
|
233
281
|
```
|
|
234
282
|
|
|
235
|
-
When resolving placeholders, the agent has access to the full
|
|
283
|
+
When resolving placeholders, the agent has access to the full body and the surrounding space context (except for `_`-prefixed fields). Placeholders are instructions, not templates, and do not need to repeat information already present in other fields.
|
|
236
284
|
|
|
237
285
|
Placeholders are resolved by the AI during the mutation and replaced with concrete values. The `{{...}}` syntax is never stored — it only guides the agent while creating or updating the object.
|
|
238
286
|
|
|
@@ -243,7 +291,7 @@ Undo/redo works on **checkpoints**, not individual operations. Call `checkpoint(
|
|
|
243
291
|
```typescript
|
|
244
292
|
// Create a checkpoint before user action
|
|
245
293
|
await channel.checkpoint('Delete object');
|
|
246
|
-
await channel.deleteObjects([
|
|
294
|
+
await channel.deleteObjects([location]);
|
|
247
295
|
|
|
248
296
|
// User can now undo back to the checkpoint
|
|
249
297
|
if (await channel.canUndo()) {
|
|
@@ -260,16 +308,13 @@ Checkpoints are **space-wide**: one shared stack across all channels and users.
|
|
|
260
308
|
|
|
261
309
|
### Hidden Fields
|
|
262
310
|
|
|
263
|
-
|
|
311
|
+
Body fields starting with `_` (e.g., `_ui`, `_cache`) are hidden from AI and ignored by the schema — you can add them to any object regardless of its collection definition. Otherwise they behave like normal fields: they sync in real-time, persist to the server, support undo/redo, and are visible to all users of the space. Use them for UI state, positions, or other data the AI shouldn't see or modify:
|
|
264
312
|
|
|
265
313
|
```typescript
|
|
266
|
-
await channel.createObject({
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
author: "John Doe",
|
|
271
|
-
_ui: { x: 100, y: 200, collapsed: false }
|
|
272
|
-
}
|
|
314
|
+
await channel.createObject('article', {
|
|
315
|
+
title: 'My Article',
|
|
316
|
+
author: 'John Doe',
|
|
317
|
+
_ui: { x: 100, y: 200, collapsed: false }
|
|
273
318
|
});
|
|
274
319
|
```
|
|
275
320
|
|
|
@@ -284,42 +329,50 @@ Events fire for both local and remote changes. The `source` field indicates orig
|
|
|
284
329
|
|
|
285
330
|
```typescript
|
|
286
331
|
// All UI updates happen in one place, regardless of change source
|
|
287
|
-
channel.on('objectUpdated', ({
|
|
288
|
-
renderObject(
|
|
332
|
+
channel.on('objectUpdated', ({ location, object, source }) => {
|
|
333
|
+
renderObject(location, object);
|
|
289
334
|
if (source === 'remote_agent') {
|
|
290
335
|
doLayout(); // AI might have added content
|
|
291
336
|
}
|
|
292
337
|
});
|
|
293
338
|
|
|
294
339
|
// Caller just makes the change - event handler does the UI work
|
|
295
|
-
channel.updateObject(
|
|
340
|
+
channel.updateObject(location, { prompt: 'expand this' });
|
|
296
341
|
```
|
|
297
342
|
|
|
298
|
-
###
|
|
343
|
+
### Locations & Basenames
|
|
299
344
|
|
|
300
|
-
By default, `createObject`
|
|
345
|
+
By default, `createObject` mints a 6-character alphanumeric basename. Provide your own via `options.basename` for meaningful identifiers:
|
|
301
346
|
|
|
302
347
|
```typescript
|
|
303
|
-
await channel.createObject(
|
|
348
|
+
await channel.createObject('article',
|
|
349
|
+
{ title: 'The Meaning of Life' },
|
|
350
|
+
{ basename: 'meaning-of-life' },
|
|
351
|
+
);
|
|
352
|
+
// → location: /space/article/meaning-of-life.json
|
|
304
353
|
```
|
|
305
354
|
|
|
306
|
-
**Why
|
|
307
|
-
- **Fire-and-forget creation** — Know the
|
|
308
|
-
- **Meaningful
|
|
355
|
+
**Why pin a basename?**
|
|
356
|
+
- **Fire-and-forget creation** — Know the location immediately without awaiting the response.
|
|
357
|
+
- **Meaningful identifiers** — Use domain-specific names like `welcome` or `2026-budget` for easier debugging and external references.
|
|
309
358
|
|
|
310
359
|
```typescript
|
|
311
360
|
// Fire-and-forget: create and reference without waiting
|
|
312
|
-
const
|
|
313
|
-
|
|
314
|
-
|
|
361
|
+
const basename = RoolClient.generateBasename();
|
|
362
|
+
const location = loc('note', basename);
|
|
363
|
+
|
|
364
|
+
channel.createObject('note', { text: '{{expand this idea}}' }, { basename });
|
|
365
|
+
channel.updateObject(parentLocation, {
|
|
366
|
+
data: { notes: [...existingNotes, location] },
|
|
367
|
+
}); // Add reference immediately
|
|
315
368
|
```
|
|
316
369
|
|
|
317
|
-
**
|
|
318
|
-
- Must
|
|
319
|
-
-
|
|
320
|
-
-
|
|
370
|
+
**Basename constraints:**
|
|
371
|
+
- Must start with an alphanumeric character.
|
|
372
|
+
- Other characters may be alphanumeric, hyphens (`-`), or underscores (`_`).
|
|
373
|
+
- Must be unique within its collection (throws if the location already exists).
|
|
321
374
|
|
|
322
|
-
Use `
|
|
375
|
+
Use `moveObject` to rename an object or move it to a different collection — see [Moving and Renaming](#moving-and-renaming).
|
|
323
376
|
|
|
324
377
|
## Authentication
|
|
325
378
|
|
|
@@ -366,7 +419,7 @@ if (!authenticated) {
|
|
|
366
419
|
|
|
367
420
|
## AI Agent
|
|
368
421
|
|
|
369
|
-
The `prompt()` method is the primary way to invoke the AI agent. The agent has editor-level capabilities — it can create, modify, and delete objects — but cannot see or modify `_`-prefixed fields.
|
|
422
|
+
The `prompt()` method is the primary way to invoke the AI agent. The agent has editor-level capabilities — it can create, modify, move, and delete objects — but cannot see or modify `_`-prefixed fields.
|
|
370
423
|
|
|
371
424
|
```typescript
|
|
372
425
|
const { message, objects } = await channel.prompt(
|
|
@@ -390,13 +443,13 @@ Returns a message (the AI's response) and the list of objects that were created
|
|
|
390
443
|
|
|
391
444
|
| Option | Description |
|
|
392
445
|
|--------|-------------|
|
|
393
|
-
| `
|
|
446
|
+
| `locations` | Focus the AI on specific objects, identified by location (given primary attention in context). |
|
|
394
447
|
| `responseSchema` | Request structured JSON instead of text summary |
|
|
395
448
|
| `effort` | Effort level: `'QUICK'`, `'STANDARD'` (default), `'REASONING'`, or `'RESEARCH'` |
|
|
396
449
|
| `ephemeral` | If true, don't record in interaction history (useful for tab completion) |
|
|
397
|
-
| `readOnly` | If true, disable mutation tools (create, update, delete). Use for questions. |
|
|
450
|
+
| `readOnly` | If true, disable mutation tools (create, update, move, delete). Use for questions. |
|
|
398
451
|
| `parentInteractionId` | Parent interaction in the conversation tree. Omit to auto-continue from the active leaf. Pass `null` to start a new root-level branch. Pass a specific ID to branch from that point (edit/reroll). |
|
|
399
|
-
| `attachments` | Files to attach (`File`, `Blob`, or `{ data, contentType }`). Stored as authenticated space files; resulting `rool-drive
|
|
452
|
+
| `attachments` | Files to attach (`File`, `Blob`, or `{ data, contentType }`). Stored as authenticated space files; resulting `rool-machine:/rool-drive/...` references are stored on the interaction's `attachments` field for UI rendering. The AI can interpret images (JPEG, PNG, GIF, WebP, SVG), PDFs, text-based files (plain text, Markdown, CSV, HTML, XML, JSON), and DOCX documents. Other file types are uploaded and stored but the AI cannot natively consume their contents, only use shell tools on them. |
|
|
400
453
|
| `signal` | `AbortSignal` to stop the prompt mid-flight. When aborted, the agent loop halts and the streaming response closes. Note that any LLM turn already in flight on Vertex keeps generating server-side and is billed. |
|
|
401
454
|
|
|
402
455
|
### Effort Levels
|
|
@@ -419,7 +472,7 @@ const { objects } = await channel.prompt(
|
|
|
419
472
|
// Work with specific objects
|
|
420
473
|
const result = await channel.prompt(
|
|
421
474
|
"Summarize these articles",
|
|
422
|
-
{
|
|
475
|
+
{ locations: ['/space/article/intro.json', '/space/article/conclusion.json'] }
|
|
423
476
|
);
|
|
424
477
|
|
|
425
478
|
// Quick question without mutations (fast model + read-only)
|
|
@@ -456,7 +509,11 @@ Use `responseSchema` to get structured JSON instead of a text message:
|
|
|
456
509
|
|
|
457
510
|
```typescript
|
|
458
511
|
const { message } = await channel.prompt("Categorize these items", {
|
|
459
|
-
|
|
512
|
+
locations: [
|
|
513
|
+
'/space/item/widget.json',
|
|
514
|
+
'/space/item/gadget.json',
|
|
515
|
+
'/space/item/gizmo.json',
|
|
516
|
+
],
|
|
460
517
|
responseSchema: {
|
|
461
518
|
type: 'object',
|
|
462
519
|
properties: {
|
|
@@ -478,7 +535,7 @@ console.log(result.categories, result.summary);
|
|
|
478
535
|
AI operations automatically receive context:
|
|
479
536
|
- **Interaction history** — Previous interactions and their results from this channel
|
|
480
537
|
- **Recently modified objects** — Objects created or changed recently
|
|
481
|
-
- **Selected objects** — Objects passed via `
|
|
538
|
+
- **Selected objects** — Objects passed via `locations` are given primary focus
|
|
482
539
|
|
|
483
540
|
This context flows automatically — no configuration needed. The AI sees enough history to maintain coherent interactions while respecting the `_`-prefixed field hiding rules.
|
|
484
541
|
|
|
@@ -506,7 +563,7 @@ await space.addUser(user.id, 'editor');
|
|
|
506
563
|
|------|--------------|
|
|
507
564
|
| `owner` | Full control, can delete space and manage all users |
|
|
508
565
|
| `admin` | All editor capabilities, plus can manage users (except other admins/owners) |
|
|
509
|
-
| `editor` | Can create, modify, and delete objects |
|
|
566
|
+
| `editor` | Can create, modify, move, and delete objects |
|
|
510
567
|
| `viewer` | Read-only access (can query with `prompt` and `findObjects`) |
|
|
511
568
|
|
|
512
569
|
### Space Collaboration Methods
|
|
@@ -549,6 +606,7 @@ When a user accesses a space via URL, they're granted the corresponding role (`v
|
|
|
549
606
|
| `currentUser: CurrentUser \| null` | Cached user profile from `initialize()`. Use for sync access to user info (id, email, name, etc.). Returns `null` before `initialize()` is called. |
|
|
550
607
|
| `getCurrentUser(): Promise<CurrentUser>` | Fetch fresh user profile from server (id, email, name, photoUrl, slug, plan, creditsBalance, totalCreditsUsed, createdAt, lastActivity, processedAt, storage) |
|
|
551
608
|
| `updateCurrentUser(input): Promise<CurrentUser>` | Update the current user's profile (`name`, `slug`). Returns the updated user. Slug must be 3–32 chars, start with a letter, and contain only lowercase alphanumeric characters, hyphens, and underscores. |
|
|
609
|
+
| `deleteCurrentUser(): Promise<void>` | Mark the current user's account for deletion (10-minute grace period before irreversible). Logs out the client. |
|
|
552
610
|
| `searchUser(email): Promise<UserResult \| null>` | Find user by exact email address (no partial matching) |
|
|
553
611
|
|
|
554
612
|
### Real-time Collaboration
|
|
@@ -556,7 +614,7 @@ When a user accesses a space via URL, they're granted the corresponding role (`v
|
|
|
556
614
|
When multiple users have a space open, changes sync in real-time. The `source` field in events tells you who made the change:
|
|
557
615
|
|
|
558
616
|
```typescript
|
|
559
|
-
channel.on('objectUpdated', ({
|
|
617
|
+
channel.on('objectUpdated', ({ location, object, source }) => {
|
|
560
618
|
if (source === 'remote_user') {
|
|
561
619
|
// Another user made this change
|
|
562
620
|
showCollaboratorActivity(object);
|
|
@@ -592,9 +650,11 @@ const client = new RoolClient({
|
|
|
592
650
|
| `listSpaces(): Promise<RoolSpaceInfo[]>` | List available spaces |
|
|
593
651
|
| `openSpace(spaceId): Promise<RoolSpace>` | Open a space with live SSE subscription. Caches and reuses open spaces. Call `space.openChannel(channelId)` to get a channel. |
|
|
594
652
|
| `createSpace(name): Promise<RoolSpace>` | Create a new space, returns live handle with SSE subscription |
|
|
653
|
+
| `duplicateSpace(sourceSpaceId, name): Promise<RoolSpace>` | Duplicate an existing space. Returns a handle to the new space. |
|
|
595
654
|
| `deleteSpace(id): Promise<void>` | Permanently delete a space (cannot be undone) |
|
|
596
655
|
| `importArchive(name, archive): Promise<RoolSpace>` | Import from a zip archive, creating a new space |
|
|
597
656
|
| `webdav(spaceId): RoolWebDAV` | Open a WebDAV client for a space's file storage |
|
|
657
|
+
| `getSpaceStorageUsage(spaceId): Promise<SpaceFileStorageUsage>` | Get WebDAV quota usage for a space |
|
|
598
658
|
|
|
599
659
|
### Channel Management
|
|
600
660
|
|
|
@@ -678,7 +738,8 @@ Discover and install extensions published by other users.
|
|
|
678
738
|
|
|
679
739
|
| Method | Description |
|
|
680
740
|
|--------|-------------|
|
|
681
|
-
| `RoolClient.
|
|
741
|
+
| `RoolClient.generateBasename(): string` | Generate a 6-char alphanumeric basename for new object identities. |
|
|
742
|
+
| `RoolClient.generateId(): string` | Same as `generateBasename()`; retained for callers minting non-object IDs (interactions, conversations, channels). |
|
|
682
743
|
| `destroy(): void` | Clean up resources |
|
|
683
744
|
|
|
684
745
|
### Client Events
|
|
@@ -745,6 +806,8 @@ A space handle with a live SSE subscription. Extends `EventEmitter`. Manages use
|
|
|
745
806
|
| `deleteChannel(channelId): Promise<void>` | Delete a channel |
|
|
746
807
|
| `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. |
|
|
747
808
|
| `exportArchive(): Promise<Blob>` | Export space as zip archive |
|
|
809
|
+
| `getStorageUsage(): Promise<SpaceFileStorageUsage>` | Get WebDAV quota usage for this space |
|
|
810
|
+
| `fetchMachineResource(resource): Promise<Response>` | Fetch a resolved file `MachineResource` through this space |
|
|
748
811
|
| `refresh(): Promise<void>` | Refresh space data from server |
|
|
749
812
|
|
|
750
813
|
### Space Events
|
|
@@ -785,49 +848,124 @@ A channel is a named context within a space. All object operations, AI prompts,
|
|
|
785
848
|
|
|
786
849
|
### Object Operations
|
|
787
850
|
|
|
788
|
-
Objects are
|
|
851
|
+
Objects are records addressed by location (`/space/<collection>/<basename>.json`). Every object must belong to a collection — create the collection first (see [Collection Schema](#collection-schema)). The body holds the user-defined fields.
|
|
852
|
+
|
|
853
|
+
All methods that accept a location accept either the canonical form or the short form (`collection/basename`).
|
|
789
854
|
|
|
790
855
|
| Method | Description |
|
|
791
856
|
|--------|-------------|
|
|
792
|
-
| `getObject(
|
|
793
|
-
| `stat(
|
|
794
|
-
| `findObjects(options): Promise<{ objects, message }>` | Find objects using structured filters and natural language. Results sorted by modifiedAt (desc by default). |
|
|
795
|
-
| `
|
|
796
|
-
| `createObject(options): Promise<{ object, message }>` | Create a new object
|
|
797
|
-
| `updateObject(
|
|
798
|
-
| `
|
|
857
|
+
| `getObject(location): Promise<RoolObject \| undefined>` | Get an object, or undefined if not found. |
|
|
858
|
+
| `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. |
|
|
859
|
+
| `findObjects(options): Promise<{ objects, message }>` | Find objects using structured filters and/or natural language. Results sorted by modifiedAt (desc by default). |
|
|
860
|
+
| `getObjectLocations(options?): string[]` | Get all object locations. Sorted by modifiedAt (desc by default). Options: `{ limit?, order? }`. |
|
|
861
|
+
| `createObject(collection, body, options?): Promise<{ object, message }>` | Create a new object in `collection`. The SDK mints a random basename unless you pass `options.basename`. |
|
|
862
|
+
| `updateObject(location, options): Promise<{ object, message }>` | Update an existing object's body. |
|
|
863
|
+
| `moveObject(from, to, options?): Promise<{ object, message }>` | Rename or relocate an object. See [Moving and Renaming](#moving-and-renaming). |
|
|
864
|
+
| `deleteObjects(locations): Promise<void>` | Delete objects by location. Other objects' refs become stale. |
|
|
799
865
|
|
|
800
|
-
#### createObject
|
|
866
|
+
#### createObject
|
|
867
|
+
|
|
868
|
+
```typescript
|
|
869
|
+
// Auto-generated basename
|
|
870
|
+
const { object } = await channel.createObject('article', {
|
|
871
|
+
title: 'Hello',
|
|
872
|
+
body: 'World',
|
|
873
|
+
});
|
|
874
|
+
// → object.location: '/space/article/X7kQ9p.json'
|
|
875
|
+
|
|
876
|
+
// Pinned basename
|
|
877
|
+
await channel.createObject('article',
|
|
878
|
+
{ title: 'Welcome' },
|
|
879
|
+
{ basename: 'welcome' },
|
|
880
|
+
);
|
|
881
|
+
// → location: '/space/article/welcome.json'
|
|
882
|
+
|
|
883
|
+
// AI placeholders
|
|
884
|
+
await channel.createObject('article', {
|
|
885
|
+
headline: '{{catchy headline}}',
|
|
886
|
+
body: '{{long-form intro}}',
|
|
887
|
+
});
|
|
888
|
+
```
|
|
801
889
|
|
|
802
890
|
| Option | Description |
|
|
803
891
|
|--------|-------------|
|
|
804
|
-
| `
|
|
805
|
-
| `ephemeral` | If true, the operation won't be recorded in interaction history.
|
|
892
|
+
| `basename` | Specific basename to use. If omitted, the SDK generates a random 6-char one. |
|
|
893
|
+
| `ephemeral` | If true, the operation won't be recorded in interaction history. |
|
|
894
|
+
| `parentInteractionId` | Conversation tree parent. Omit to auto-continue; pass `null` for a new root. |
|
|
895
|
+
|
|
896
|
+
#### updateObject
|
|
897
|
+
|
|
898
|
+
```typescript
|
|
899
|
+
// Add/update fields
|
|
900
|
+
await channel.updateObject('/space/article/welcome.json', {
|
|
901
|
+
data: { status: 'published' },
|
|
902
|
+
});
|
|
806
903
|
|
|
807
|
-
|
|
904
|
+
// Delete a field (pass null)
|
|
905
|
+
await channel.updateObject('/space/article/welcome.json', {
|
|
906
|
+
data: { draft: null },
|
|
907
|
+
});
|
|
908
|
+
|
|
909
|
+
// AI-driven rewrite
|
|
910
|
+
await channel.updateObject('/space/article/welcome.json', {
|
|
911
|
+
prompt: 'Tighten the intro by 30%.',
|
|
912
|
+
});
|
|
913
|
+
```
|
|
808
914
|
|
|
809
915
|
| Option | Description |
|
|
810
916
|
|--------|-------------|
|
|
811
|
-
| `data` |
|
|
917
|
+
| `data` | Body fields to add, update, or delete. `null` removes the field. Use `{{placeholder}}` for AI-generated content. Fields prefixed with `_` are hidden from AI. |
|
|
812
918
|
| `prompt` | Natural language instruction for AI to modify content. |
|
|
813
|
-
| `ephemeral` | If true, the operation won't be recorded in interaction history.
|
|
919
|
+
| `ephemeral` | If true, the operation won't be recorded in interaction history. |
|
|
920
|
+
| `parentInteractionId` | Conversation tree parent. Omit to auto-continue; pass `null` for a new root. |
|
|
921
|
+
|
|
922
|
+
Use `moveObject` to change an object's location (collection or basename).
|
|
923
|
+
|
|
924
|
+
#### Moving and Renaming
|
|
925
|
+
|
|
926
|
+
`moveObject` is how you rename an object (new basename in the same collection) or move it across collections. Pass `options.body` to atomically rewrite the body as part of the move.
|
|
927
|
+
|
|
928
|
+
```typescript
|
|
929
|
+
// Rename within the same collection
|
|
930
|
+
await channel.moveObject(
|
|
931
|
+
'/space/article/welcome.json',
|
|
932
|
+
'/space/article/hello-world.json',
|
|
933
|
+
);
|
|
934
|
+
|
|
935
|
+
// Move into a different collection
|
|
936
|
+
await channel.moveObject(
|
|
937
|
+
'/space/draft/post-42.json',
|
|
938
|
+
'/space/article/post-42.json',
|
|
939
|
+
);
|
|
940
|
+
|
|
941
|
+
// Move and replace body in one go
|
|
942
|
+
await channel.moveObject(from, to, {
|
|
943
|
+
body: { title: 'Hello, world', status: 'published' },
|
|
944
|
+
});
|
|
945
|
+
```
|
|
946
|
+
|
|
947
|
+
| Option | Description |
|
|
948
|
+
|--------|-------------|
|
|
949
|
+
| `body` | Replace the body atomically as part of the move. If omitted, the body is preserved. |
|
|
950
|
+
| `ephemeral` | If true, the operation won't be recorded in interaction history. |
|
|
951
|
+
| `parentInteractionId` | Conversation tree parent. Omit to auto-continue; pass `null` for a new root. |
|
|
814
952
|
|
|
815
|
-
#### findObjects
|
|
953
|
+
#### findObjects
|
|
816
954
|
|
|
817
955
|
Find objects using structured filters and/or natural language.
|
|
818
956
|
|
|
819
957
|
- **`where` only** — exact-match filtering, no AI, no credits.
|
|
820
|
-
- **`collection` only** — filter by collection name
|
|
958
|
+
- **`collection` only** — filter by collection name, no AI, no credits.
|
|
821
959
|
- **`prompt` only** — AI-powered semantic query over all objects.
|
|
822
|
-
- **`where` + `prompt`** — `where` (and `
|
|
960
|
+
- **`where` + `prompt`** — `where` (and `locations`) narrow the data set first, then the AI queries within the constrained set.
|
|
823
961
|
|
|
824
962
|
| Option | Description |
|
|
825
963
|
|--------|-------------|
|
|
826
|
-
| `where` | Exact-match 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. |
|
|
827
|
-
| `collection` | Filter by collection name.
|
|
964
|
+
| `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. |
|
|
965
|
+
| `collection` | Filter by collection name. |
|
|
828
966
|
| `prompt` | Natural language query. Triggers AI evaluation (uses credits). |
|
|
829
967
|
| `limit` | Maximum number of results. |
|
|
830
|
-
| `
|
|
968
|
+
| `locations` | Scope to specific object locations. Constrains the candidate set in both structured and AI queries. |
|
|
831
969
|
| `order` | Sort order by modifiedAt: `'asc'` or `'desc'` (default: `'desc'`). |
|
|
832
970
|
| `ephemeral` | If true, the query won't be recorded in interaction history. Useful for responsive search. |
|
|
833
971
|
|
|
@@ -863,7 +1001,7 @@ const { objects } = await channel.findObjects({
|
|
|
863
1001
|
});
|
|
864
1002
|
```
|
|
865
1003
|
|
|
866
|
-
When `where` or `
|
|
1004
|
+
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.
|
|
867
1005
|
|
|
868
1006
|
### Undo/Redo
|
|
869
1007
|
|
|
@@ -880,7 +1018,7 @@ See [Checkpoints & Undo/Redo](#checkpoints--undoredo) for semantics.
|
|
|
880
1018
|
|
|
881
1019
|
### Space Metadata
|
|
882
1020
|
|
|
883
|
-
Store arbitrary data alongside the
|
|
1021
|
+
Store arbitrary data alongside the space without it being part of an object's body (e.g., viewport state, user preferences).
|
|
884
1022
|
|
|
885
1023
|
| Method | Description |
|
|
886
1024
|
|--------|-------------|
|
|
@@ -890,11 +1028,13 @@ Store arbitrary data alongside the Space without it being part of the object dat
|
|
|
890
1028
|
|
|
891
1029
|
### Space File Storage
|
|
892
1030
|
|
|
893
|
-
Every space has authenticated file storage. WebDAV is the SDK surface for that storage: paths are relative to the space root
|
|
1031
|
+
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)`.
|
|
894
1032
|
|
|
895
1033
|
Use `client.webdav(spaceId)` when you only have an ID, or `space.webdav` when you already have an open space.
|
|
896
1034
|
|
|
897
1035
|
```typescript
|
|
1036
|
+
import { resolveMachineResource } from '@rool-dev/sdk';
|
|
1037
|
+
|
|
898
1038
|
const webdav = client.webdav('space-id');
|
|
899
1039
|
|
|
900
1040
|
await webdav.mkcol('docs');
|
|
@@ -911,39 +1051,51 @@ const listing = await webdav.propfind('docs/', {
|
|
|
911
1051
|
const file = await webdav.get('docs/readme.md');
|
|
912
1052
|
console.log(await file.text());
|
|
913
1053
|
|
|
914
|
-
const
|
|
915
|
-
|
|
1054
|
+
const resource = resolveMachineResource('/rool-drive/docs/read me.md');
|
|
1055
|
+
if (!resource || resource.kind !== 'file') throw new Error('not a file');
|
|
1056
|
+
const sameFile = await space.fetchMachineResource(resource);
|
|
1057
|
+
|
|
1058
|
+
const usage = await space.getStorageUsage();
|
|
1059
|
+
console.log(usage.usedBytes);
|
|
1060
|
+
console.log(usage.availableBytes); // null means unlimited
|
|
1061
|
+
console.log(usage.limitBytes); // null means unlimited
|
|
916
1062
|
```
|
|
917
1063
|
|
|
918
|
-
Paths are space-relative (`docs/readme.md`, not `/docs/readme.md`).
|
|
1064
|
+
Paths are space-relative (`docs/readme.md`, not `/docs/readme.md`). WebDAV methods accept WebDAV paths only. User-facing file links should use `rool-machine:/rool-drive/...`; resolve either that URI or a bare `/rool-drive/...` machine path with `resolveMachineResource()` and fetch the resulting file resource with `space.fetchMachineResource(resource)`. `PUT` writes an exact path and does not create parent collections; create parents with `mkcol()` first. Helpers preserve WebDAV status semantics: non-success responses throw `WebDAVError` with `status`, `statusText`, and `body`.
|
|
919
1065
|
|
|
920
1066
|
| Method | Description |
|
|
921
1067
|
|--------|-------------|
|
|
922
1068
|
| `client.webdav(spaceId)` | Create a WebDAV client for a space |
|
|
1069
|
+
| `client.getSpaceStorageUsage(spaceId)` | Get WebDAV quota usage for a space |
|
|
923
1070
|
| `space.webdav` | WebDAV client for an open space |
|
|
924
|
-
| `
|
|
925
|
-
| `webdav.
|
|
926
|
-
| `webdav.
|
|
927
|
-
| `webdav.
|
|
928
|
-
| `webdav.
|
|
1071
|
+
| `space.getStorageUsage()` | Get WebDAV quota usage for an open space |
|
|
1072
|
+
| `webdav.getStorageUsage()` | Get WebDAV quota usage through the WebDAV client |
|
|
1073
|
+
| `webdav.path(path)` | Normalize a WebDAV path |
|
|
1074
|
+
| `webdav.propfind(path, options)` | Read properties/list collections; explicit `depth` required |
|
|
1075
|
+
| `webdav.get(path, options?)` / `webdav.head(path)` | Read a file, including optional byte ranges for `get` |
|
|
1076
|
+
| `webdav.put(path, body, options?)` | Write an exact file path; parents must already exist |
|
|
929
1077
|
| `webdav.mkcol(path)` | Create one collection |
|
|
930
1078
|
| `webdav.copy(source, destination, options?)` | Copy a file or collection within the same space |
|
|
931
1079
|
| `webdav.move(source, destination, options?)` | Move a file or collection within the same space |
|
|
932
|
-
| `webdav.delete(
|
|
933
|
-
| `webdav.lock(
|
|
1080
|
+
| `webdav.delete(path, options?)` | Delete a file or collection |
|
|
1081
|
+
| `webdav.lock(path, options)` / `webdav.refreshLock(path, token)` / `webdav.unlock(token)` | WebDAV Class 2 write locks |
|
|
934
1082
|
| `webdav.request(method, path, init?)` | Raw authenticated WebDAV request escape hatch |
|
|
935
1083
|
|
|
1084
|
+
> **Note**: `resolveMachineResource()` returns either a file resource or an object resource. File resources point at user-visible files in the space's WebDAV storage and can be fetched with `space.fetchMachineResource(resource)`. Object resources identify records inside the space. They're not interchangeable.
|
|
1085
|
+
|
|
936
1086
|
#### File references from AI responses
|
|
937
1087
|
|
|
938
|
-
When an agent refers to a user-visible file, the SDK contract is `rool-drive
|
|
1088
|
+
When an agent refers to a user-visible file, the SDK contract is `rool-machine:/rool-drive/path/to/file.ext`. That prefix makes a file reference unambiguous without exposing the authenticated WebDAV URL. In free text, ambiguous characters such as spaces are percent-encoded (`rool-machine:/rool-drive/docs/read%20me.md`).
|
|
939
1089
|
|
|
940
1090
|
```typescript
|
|
941
|
-
const
|
|
1091
|
+
const resource = resolveMachineResource('rool-machine:/rool-drive/docs/readme.md');
|
|
1092
|
+
if (!resource || resource.kind !== 'file') throw new Error('not a file');
|
|
1093
|
+
const response = await space.fetchMachineResource(resource);
|
|
942
1094
|
const blob = await response.blob();
|
|
943
1095
|
img.src = URL.createObjectURL(blob);
|
|
944
1096
|
```
|
|
945
1097
|
|
|
946
|
-
Plain relative strings like `docs/readme.md` are valid WebDAV paths when you already know you are working with file storage. In user text or agent output, use `rool-drive
|
|
1098
|
+
Plain relative strings like `docs/readme.md` are valid WebDAV paths when you already know you are working with file storage. In user text or agent output, use `rool-machine:/rool-drive/docs/readme.md` so clients do not have to guess whether a string is a file.
|
|
947
1099
|
|
|
948
1100
|
### Proxied Fetch
|
|
949
1101
|
|
|
@@ -968,7 +1120,7 @@ const response = await channel.fetch('https://api.example.com/submit', {
|
|
|
968
1120
|
|
|
969
1121
|
### Collection Schema
|
|
970
1122
|
|
|
971
|
-
Collections are the types you use to group objects in a space. Every object
|
|
1123
|
+
Collections are the types you use to group objects in a space. Every object belongs to exactly one collection: the collection is the parent directory of its location, and the server validates the object's body against that collection's definition. Renaming a collection changes the location of every object bound to it; dropping a collection is blocked while any object still lives there.
|
|
972
1124
|
|
|
973
1125
|
Collections make up the schema and are stored in the space data, syncing in real time. The schema is visible to the AI agent so it knows which collections exist and what fields they contain, producing more consistent objects.
|
|
974
1126
|
|
|
@@ -1013,7 +1165,7 @@ await channel.dropCollection('article');
|
|
|
1013
1165
|
| `string` | Text value | `{ kind: 'string' }` |
|
|
1014
1166
|
| `number` | Numeric value | `{ kind: 'number' }` |
|
|
1015
1167
|
| `boolean` | True/false | `{ kind: 'boolean' }` |
|
|
1016
|
-
| `ref` | Reference to another object | `{ kind: 'ref' }` |
|
|
1168
|
+
| `ref` | Reference to another object (location string) | `{ kind: 'ref' }` |
|
|
1017
1169
|
| `enum` | One of a set of values | `{ kind: 'enum', values: ['a', 'b'] }` |
|
|
1018
1170
|
| `literal` | Exact value | `{ kind: 'literal', value: 'fixed' }` |
|
|
1019
1171
|
| `array` | List of values | `{ kind: 'array', inner: { kind: 'string' } }` |
|
|
@@ -1055,10 +1207,11 @@ Semantic events describe what changed. Events fire for both local changes and re
|
|
|
1055
1207
|
// - 'remote_agent': AI agent made the change
|
|
1056
1208
|
// - 'system': Resync after error
|
|
1057
1209
|
|
|
1058
|
-
// Object events
|
|
1059
|
-
channel.on('objectCreated', ({
|
|
1060
|
-
channel.on('objectUpdated', ({
|
|
1061
|
-
channel.on('objectDeleted', ({
|
|
1210
|
+
// Object events — payload includes the full RoolObject
|
|
1211
|
+
channel.on('objectCreated', ({ location, object, source }) => void)
|
|
1212
|
+
channel.on('objectUpdated', ({ location, object, source }) => void)
|
|
1213
|
+
channel.on('objectDeleted', ({ location, source }) => void)
|
|
1214
|
+
channel.on('objectMoved', ({ from, to, object, source }) => void)
|
|
1062
1215
|
|
|
1063
1216
|
// Space metadata
|
|
1064
1217
|
channel.on('metadataUpdated', ({ metadata, source }) => void)
|
|
@@ -1085,7 +1238,7 @@ AI operations may fail due to rate limiting or other transient errors. Check `er
|
|
|
1085
1238
|
|
|
1086
1239
|
```typescript
|
|
1087
1240
|
try {
|
|
1088
|
-
await channel.updateObject(
|
|
1241
|
+
await channel.updateObject(location, { prompt: 'expand this' });
|
|
1089
1242
|
} catch (error) {
|
|
1090
1243
|
if (error.message.includes('temporarily unavailable')) {
|
|
1091
1244
|
showToast('Service busy, please try again in a moment');
|
|
@@ -1119,11 +1272,11 @@ Channel management (listing, renaming, deleting channels) is done via the client
|
|
|
1119
1272
|
|
|
1120
1273
|
The `ai` field in interactions distinguishes AI-generated responses from synthetic confirmations:
|
|
1121
1274
|
- `ai: true` — AI processed this operation (prompt, or createObject/updateObject with placeholders)
|
|
1122
|
-
- `ai: false` — System confirmation only (e.g., "Created object
|
|
1275
|
+
- `ai: false` — System confirmation only (e.g., "Created object /space/note/welcome.json")
|
|
1123
1276
|
|
|
1124
1277
|
### Tool Calls
|
|
1125
1278
|
|
|
1126
|
-
The `toolCalls` array captures what the AI agent did during execution. The `conversationUpdated` event fires when each tool starts and completes. A tool call
|
|
1279
|
+
The `toolCalls` array captures what the AI agent did during execution. The `conversationUpdated` event fires when each tool starts and completes. A tool call with `status: 'running'` has no result; once `status: 'done'`, `result` contains the truncated result string.
|
|
1127
1280
|
|
|
1128
1281
|
## Data Types
|
|
1129
1282
|
|
|
@@ -1157,17 +1310,18 @@ type SpaceSchema = Record<string, CollectionDef>;
|
|
|
1157
1310
|
### Object Data
|
|
1158
1311
|
|
|
1159
1312
|
```typescript
|
|
1160
|
-
//
|
|
1161
|
-
//
|
|
1162
|
-
// Fields prefixed with _ are hidden from AI
|
|
1163
|
-
// References between objects are fields whose values are object IDs
|
|
1313
|
+
// An object addressed by location. References between objects are body
|
|
1314
|
+
// fields whose values are location strings.
|
|
1164
1315
|
interface RoolObject {
|
|
1165
|
-
|
|
1166
|
-
|
|
1316
|
+
location: string; // "/space/<collection>/<basename>.json"
|
|
1317
|
+
collection: string;
|
|
1318
|
+
basename: string;
|
|
1319
|
+
body: Record<string, unknown>;
|
|
1167
1320
|
}
|
|
1168
1321
|
|
|
1169
|
-
// Object stat
|
|
1322
|
+
// Object stat — audit information returned by channel.stat()
|
|
1170
1323
|
interface RoolObjectStat {
|
|
1324
|
+
location: string;
|
|
1171
1325
|
modifiedAt: number;
|
|
1172
1326
|
modifiedBy: string;
|
|
1173
1327
|
modifiedByName: string | null;
|
|
@@ -1230,28 +1384,37 @@ Note: `Channel` and `ChannelInfo` are data types describing the stored channel m
|
|
|
1230
1384
|
### Interaction Types
|
|
1231
1385
|
|
|
1232
1386
|
```typescript
|
|
1233
|
-
|
|
1234
|
-
|
|
1235
|
-
|
|
1236
|
-
|
|
1237
|
-
|
|
1387
|
+
type ToolCall =
|
|
1388
|
+
| {
|
|
1389
|
+
id: string;
|
|
1390
|
+
name: string; // Tool name (e.g., "create_object", "update_object", "search_web")
|
|
1391
|
+
input: unknown; // Arguments passed to the tool
|
|
1392
|
+
status: 'running';
|
|
1393
|
+
}
|
|
1394
|
+
| {
|
|
1395
|
+
id: string;
|
|
1396
|
+
name: string;
|
|
1397
|
+
input: unknown;
|
|
1398
|
+
status: 'done';
|
|
1399
|
+
result: string; // Truncated result
|
|
1400
|
+
};
|
|
1238
1401
|
|
|
1239
1402
|
type InteractionStatus = 'pending' | 'streaming' | 'done' | 'error';
|
|
1240
1403
|
|
|
1241
1404
|
interface Interaction {
|
|
1242
|
-
id: string;
|
|
1243
|
-
parentId: string | null;
|
|
1405
|
+
id: string; // Unique ID for this interaction
|
|
1406
|
+
parentId: string | null; // Parent in conversation tree (null = root)
|
|
1244
1407
|
timestamp: number;
|
|
1245
|
-
userId: string;
|
|
1246
|
-
userName?: string | null;
|
|
1247
|
-
operation: 'prompt' | 'createObject' | 'updateObject' | 'deleteObjects';
|
|
1248
|
-
input: string;
|
|
1249
|
-
output: string | null;
|
|
1250
|
-
status: InteractionStatus;
|
|
1251
|
-
ai: boolean;
|
|
1252
|
-
|
|
1253
|
-
toolCalls: ToolCall[];
|
|
1254
|
-
attachments?: string[];
|
|
1408
|
+
userId: string; // Who performed this interaction
|
|
1409
|
+
userName?: string | null; // Display name at time of interaction
|
|
1410
|
+
operation: 'prompt' | 'createObject' | 'updateObject' | 'moveObject' | 'deleteObjects';
|
|
1411
|
+
input: string; // What the user did: prompt text or action description
|
|
1412
|
+
output: string | null; // AI response or confirmation message (may be partial when streaming)
|
|
1413
|
+
status: InteractionStatus; // Lifecycle status (pending → streaming → done/error)
|
|
1414
|
+
ai: boolean; // Whether AI was invoked (vs synthetic confirmation)
|
|
1415
|
+
modifiedObjectLocations: string[]; // Locations of objects affected by this interaction
|
|
1416
|
+
toolCalls: ToolCall[]; // Tools called during this interaction (for AI prompts)
|
|
1417
|
+
attachments?: string[]; // rool-machine:/rool-drive/... file references attached by the user
|
|
1255
1418
|
}
|
|
1256
1419
|
```
|
|
1257
1420
|
|
|
@@ -1274,13 +1437,14 @@ type ChangeSource = 'local_user' | 'remote_user' | 'remote_agent' | 'system';
|
|
|
1274
1437
|
type PromptEffort = 'QUICK' | 'STANDARD' | 'REASONING' | 'RESEARCH';
|
|
1275
1438
|
|
|
1276
1439
|
interface PromptOptions {
|
|
1277
|
-
|
|
1440
|
+
locations?: string[]; // Scope to specific objects
|
|
1278
1441
|
responseSchema?: Record<string, unknown>;
|
|
1279
|
-
effort?: PromptEffort;
|
|
1280
|
-
ephemeral?: boolean;
|
|
1281
|
-
readOnly?: boolean;
|
|
1282
|
-
parentInteractionId?: string | null;
|
|
1283
|
-
attachments?: Array<File | Blob | { data: string; contentType: string }>;
|
|
1442
|
+
effort?: PromptEffort; // Effort level (default: 'STANDARD')
|
|
1443
|
+
ephemeral?: boolean; // Don't record in interaction history
|
|
1444
|
+
readOnly?: boolean; // Disable mutation tools (default: false)
|
|
1445
|
+
parentInteractionId?: string | null; // Branch from a specific interaction (omit to auto-continue)
|
|
1446
|
+
attachments?: Array<File | Blob | { data: string; contentType: string }>; // Files to attach
|
|
1447
|
+
signal?: AbortSignal; // Cancel an in-flight prompt
|
|
1284
1448
|
}
|
|
1285
1449
|
```
|
|
1286
1450
|
|