@rool-dev/extension 0.3.7 → 0.3.8-dev.368b058
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 +21 -8
- package/dist/cli/build-pipeline.js +1 -1
- package/dist/cli/dev.js +1 -1
- package/dist/cli/init.js +1 -1
- package/dist/dev/DevHostController.d.ts +5 -0
- package/dist/dev/DevHostController.d.ts.map +1 -1
- package/dist/dev/DevHostController.js +22 -1
- package/dist/dev/HostShell.svelte +11 -8
- package/dist/dev/HostShell.svelte.d.ts +1 -8
- package/dist/dev/HostShell.svelte.d.ts.map +1 -1
- package/dist/dev/Sidebar.svelte +14 -1
- package/dist/dev/Sidebar.svelte.d.ts +1 -0
- package/dist/dev/Sidebar.svelte.d.ts.map +1 -1
- package/dist/dev/app.css +1 -0
- package/dist/dev/host-shell.js +280 -72
- package/dist/dev/host-shell.js.map +1 -1
- package/dist/host.d.ts +9 -0
- package/dist/host.d.ts.map +1 -1
- package/dist/host.js +28 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/protocol.d.ts +10 -0
- package/dist/protocol.d.ts.map +1 -1
- package/dist/reactive.svelte.d.ts +68 -37
- package/dist/reactive.svelte.d.ts.map +1 -1
- package/dist/reactive.svelte.js +388 -103
- package/dist/types.d.ts +4 -0
- package/dist/types.d.ts.map +1 -1
- package/package.json +2 -2
- package/dist/client.d.ts +0 -139
- package/dist/client.d.ts.map +0 -1
- package/dist/client.js +0 -360
package/dist/reactive.svelte.js
CHANGED
|
@@ -1,10 +1,17 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
2
|
+
* Extension channel — bridge client with Svelte 5 reactivity.
|
|
3
3
|
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
-
* The underlying transport is the postMessage bridge, not the SDK.
|
|
4
|
+
* Handles the postMessage bridge to the host and provides reactive $state
|
|
5
|
+
* properties, matching the @rool-dev/svelte ReactiveChannel API.
|
|
7
6
|
*/
|
|
7
|
+
import { isBridgeMessage } from './protocol.js';
|
|
8
|
+
// ---------------------------------------------------------------------------
|
|
9
|
+
// Helpers
|
|
10
|
+
// ---------------------------------------------------------------------------
|
|
11
|
+
let _nextId = 0;
|
|
12
|
+
function nextRequestId() {
|
|
13
|
+
return `req-${++_nextId}-${Date.now().toString(36)}`;
|
|
14
|
+
}
|
|
8
15
|
// ---------------------------------------------------------------------------
|
|
9
16
|
// ReactiveWatch
|
|
10
17
|
// ---------------------------------------------------------------------------
|
|
@@ -157,128 +164,341 @@ class ReactiveObjectImpl {
|
|
|
157
164
|
}
|
|
158
165
|
}
|
|
159
166
|
// ---------------------------------------------------------------------------
|
|
167
|
+
// Color scheme helper
|
|
168
|
+
// ---------------------------------------------------------------------------
|
|
169
|
+
function applyColorScheme(scheme) {
|
|
170
|
+
document.documentElement.classList.toggle('dark', scheme === 'dark');
|
|
171
|
+
}
|
|
172
|
+
// ---------------------------------------------------------------------------
|
|
160
173
|
// ReactiveChannel
|
|
161
174
|
// ---------------------------------------------------------------------------
|
|
162
175
|
class ReactiveChannelImpl {
|
|
163
|
-
|
|
176
|
+
_pending = new Map();
|
|
177
|
+
_listeners = new Map();
|
|
178
|
+
_schema;
|
|
179
|
+
_metadata;
|
|
180
|
+
#unsubscribers = [];
|
|
164
181
|
#closed = false;
|
|
182
|
+
// Metadata from handshake
|
|
183
|
+
channelId;
|
|
184
|
+
spaceId;
|
|
185
|
+
spaceName;
|
|
186
|
+
role;
|
|
187
|
+
linkAccess;
|
|
188
|
+
userId;
|
|
189
|
+
/** Current user info (id, name, email). */
|
|
190
|
+
user;
|
|
165
191
|
// Reactive state
|
|
166
192
|
interactions = $state([]);
|
|
167
193
|
objectIds = $state([]);
|
|
168
194
|
collections = $state([]);
|
|
169
195
|
conversations = $state([]);
|
|
170
|
-
|
|
171
|
-
constructor(
|
|
172
|
-
this
|
|
196
|
+
colorScheme = $state('light');
|
|
197
|
+
constructor(init) {
|
|
198
|
+
this.channelId = init.channelId;
|
|
199
|
+
this.spaceId = init.spaceId;
|
|
200
|
+
this.spaceName = init.spaceName;
|
|
201
|
+
this.role = init.role;
|
|
202
|
+
this.linkAccess = init.linkAccess;
|
|
203
|
+
this.userId = init.userId;
|
|
204
|
+
this.user = init.user;
|
|
205
|
+
this._schema = init.schema;
|
|
206
|
+
this._metadata = init.metadata;
|
|
207
|
+
this.colorScheme = init.colorScheme ?? 'light';
|
|
208
|
+
applyColorScheme(this.colorScheme);
|
|
209
|
+
window.addEventListener('message', this._onMessage);
|
|
173
210
|
// Load initial data
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
this.collections = Object.keys(
|
|
211
|
+
this.getInteractions().then((list) => { this.interactions = list; });
|
|
212
|
+
this._call('getObjectIds').then((ids) => { this.objectIds = ids; });
|
|
213
|
+
this.getConversations().then((list) => { this.conversations = list; });
|
|
214
|
+
this.collections = Object.keys(this._schema);
|
|
178
215
|
// Subscribe to channel updates → refresh interactions
|
|
179
216
|
const onChannelUpdated = () => {
|
|
180
|
-
|
|
217
|
+
this.getInteractions().then((list) => { this.interactions = list; });
|
|
181
218
|
};
|
|
182
|
-
|
|
183
|
-
this.#unsubscribers.push(() =>
|
|
219
|
+
this.on('channelUpdated', onChannelUpdated);
|
|
220
|
+
this.#unsubscribers.push(() => this.off('channelUpdated', onChannelUpdated));
|
|
184
221
|
// Subscribe to conversation updates → refresh conversations
|
|
185
222
|
const onConversationUpdated = () => {
|
|
186
|
-
|
|
223
|
+
this.getConversations().then((list) => { this.conversations = list; });
|
|
187
224
|
};
|
|
188
|
-
|
|
189
|
-
this.#unsubscribers.push(() =>
|
|
225
|
+
this.on('conversationUpdated', onConversationUpdated);
|
|
226
|
+
this.#unsubscribers.push(() => this.off('conversationUpdated', onConversationUpdated));
|
|
190
227
|
// Subscribe to object events → refresh objectIds
|
|
191
228
|
const refreshObjectIds = () => {
|
|
192
|
-
|
|
229
|
+
this._call('getObjectIds').then((ids) => { this.objectIds = ids; });
|
|
193
230
|
};
|
|
194
|
-
|
|
195
|
-
this.#unsubscribers.push(() =>
|
|
196
|
-
|
|
197
|
-
this.#unsubscribers.push(() =>
|
|
231
|
+
this.on('objectCreated', refreshObjectIds);
|
|
232
|
+
this.#unsubscribers.push(() => this.off('objectCreated', refreshObjectIds));
|
|
233
|
+
this.on('objectDeleted', refreshObjectIds);
|
|
234
|
+
this.#unsubscribers.push(() => this.off('objectDeleted', refreshObjectIds));
|
|
198
235
|
// Subscribe to schema updates → refresh collections
|
|
199
236
|
const onSchemaUpdated = () => {
|
|
200
|
-
this.collections = Object.keys(
|
|
237
|
+
this.collections = Object.keys(this._schema);
|
|
201
238
|
};
|
|
202
|
-
|
|
203
|
-
this.#unsubscribers.push(() =>
|
|
239
|
+
this.on('schemaUpdated', onSchemaUpdated);
|
|
240
|
+
this.#unsubscribers.push(() => this.off('schemaUpdated', onSchemaUpdated));
|
|
204
241
|
// Full resets
|
|
205
242
|
const onReset = () => {
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
this.collections = Object.keys(
|
|
243
|
+
this.getInteractions().then((list) => { this.interactions = list; });
|
|
244
|
+
this._call('getObjectIds').then((ids) => { this.objectIds = ids; });
|
|
245
|
+
this.getConversations().then((list) => { this.conversations = list; });
|
|
246
|
+
this.collections = Object.keys(this._schema);
|
|
210
247
|
};
|
|
211
|
-
|
|
212
|
-
this.#unsubscribers.push(() =>
|
|
248
|
+
this.on('reset', onReset);
|
|
249
|
+
this.#unsubscribers.push(() => this.off('reset', onReset));
|
|
250
|
+
}
|
|
251
|
+
get isReadOnly() {
|
|
252
|
+
return this.role === 'viewer';
|
|
253
|
+
}
|
|
254
|
+
// ---------------------------------------------------------------------------
|
|
255
|
+
// Event emitter
|
|
256
|
+
// ---------------------------------------------------------------------------
|
|
257
|
+
on(event, callback) {
|
|
258
|
+
let set = this._listeners.get(event);
|
|
259
|
+
if (!set) {
|
|
260
|
+
set = new Set();
|
|
261
|
+
this._listeners.set(event, set);
|
|
262
|
+
}
|
|
263
|
+
set.add(callback);
|
|
264
|
+
}
|
|
265
|
+
off(event, callback) {
|
|
266
|
+
this._listeners.get(event)?.delete(callback);
|
|
267
|
+
}
|
|
268
|
+
_emit(event, data) {
|
|
269
|
+
const set = this._listeners.get(event);
|
|
270
|
+
if (set) {
|
|
271
|
+
for (const cb of set) {
|
|
272
|
+
try {
|
|
273
|
+
cb(data);
|
|
274
|
+
}
|
|
275
|
+
catch (e) {
|
|
276
|
+
console.error(`[Channel] Error in ${event} listener:`, e);
|
|
277
|
+
}
|
|
278
|
+
}
|
|
279
|
+
}
|
|
280
|
+
}
|
|
281
|
+
// ---------------------------------------------------------------------------
|
|
282
|
+
// postMessage transport
|
|
283
|
+
// ---------------------------------------------------------------------------
|
|
284
|
+
_call(method, ...args) {
|
|
285
|
+
return this._callScoped(method, args);
|
|
286
|
+
}
|
|
287
|
+
/**
|
|
288
|
+
* Send a bridge request, optionally scoped to a conversation.
|
|
289
|
+
* @internal
|
|
290
|
+
*/
|
|
291
|
+
_callScoped(method, args, conversationId) {
|
|
292
|
+
return new Promise((resolve, reject) => {
|
|
293
|
+
const id = nextRequestId();
|
|
294
|
+
this._pending.set(id, { resolve, reject });
|
|
295
|
+
const msg = { type: 'rool:request', id, method, args };
|
|
296
|
+
if (conversationId !== undefined)
|
|
297
|
+
msg.conversationId = conversationId;
|
|
298
|
+
window.parent.postMessage(msg, '*');
|
|
299
|
+
});
|
|
213
300
|
}
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
301
|
+
_onMessage = (event) => {
|
|
302
|
+
if (!isBridgeMessage(event.data))
|
|
303
|
+
return;
|
|
304
|
+
if (event.data.type === 'rool:response') {
|
|
305
|
+
const msg = event.data;
|
|
306
|
+
const pending = this._pending.get(msg.id);
|
|
307
|
+
if (pending) {
|
|
308
|
+
this._pending.delete(msg.id);
|
|
309
|
+
if (msg.error) {
|
|
310
|
+
pending.reject(new Error(msg.error));
|
|
311
|
+
}
|
|
312
|
+
else {
|
|
313
|
+
pending.resolve(msg.result);
|
|
314
|
+
}
|
|
315
|
+
}
|
|
316
|
+
return;
|
|
317
|
+
}
|
|
318
|
+
if (event.data.type === 'rool:event') {
|
|
319
|
+
const msg = event.data;
|
|
320
|
+
// Update local caches before emitting so listeners see fresh data
|
|
321
|
+
if (msg.name === 'colorSchemeChanged') {
|
|
322
|
+
const { colorScheme } = msg.data;
|
|
323
|
+
this.colorScheme = colorScheme;
|
|
324
|
+
applyColorScheme(colorScheme);
|
|
325
|
+
}
|
|
326
|
+
else if (msg.name === 'metadataUpdated') {
|
|
327
|
+
const payload = msg.data;
|
|
328
|
+
this._metadata = payload.metadata;
|
|
329
|
+
}
|
|
330
|
+
else if (msg.name === 'schemaUpdated') {
|
|
331
|
+
const payload = msg.data;
|
|
332
|
+
this._schema = payload.schema;
|
|
333
|
+
}
|
|
334
|
+
else if (msg.name === 'reset') {
|
|
335
|
+
// Full reload happened on the host — refresh cached schema and metadata
|
|
336
|
+
Promise.all([
|
|
337
|
+
this._call('getSchema'),
|
|
338
|
+
this._call('getAllMetadata'),
|
|
339
|
+
]).then(([schema, metadata]) => {
|
|
340
|
+
this._schema = schema;
|
|
341
|
+
this._metadata = metadata;
|
|
342
|
+
});
|
|
343
|
+
}
|
|
344
|
+
this._emit(msg.name, msg.data);
|
|
345
|
+
return;
|
|
346
|
+
}
|
|
347
|
+
};
|
|
348
|
+
// ---------------------------------------------------------------------------
|
|
222
349
|
// Object operations
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
setSystemInstruction(instruction) { return this.#channel.setSystemInstruction(instruction); }
|
|
247
|
-
getConversations() { return this.#channel.getConversations(); }
|
|
248
|
-
deleteConversation(conversationId) { return this.#channel.deleteConversation(conversationId); }
|
|
249
|
-
renameConversation(name) { return this.#channel.renameConversation(name); }
|
|
350
|
+
// ---------------------------------------------------------------------------
|
|
351
|
+
async getObject(objectId) {
|
|
352
|
+
return this._call('getObject', objectId);
|
|
353
|
+
}
|
|
354
|
+
async stat(objectId) {
|
|
355
|
+
return this._call('stat', objectId);
|
|
356
|
+
}
|
|
357
|
+
async findObjects(options) {
|
|
358
|
+
return this._call('findObjects', options);
|
|
359
|
+
}
|
|
360
|
+
async getObjectIds(options) {
|
|
361
|
+
return this._call('getObjectIds', options);
|
|
362
|
+
}
|
|
363
|
+
async createObject(options) {
|
|
364
|
+
return this._call('createObject', options);
|
|
365
|
+
}
|
|
366
|
+
async updateObject(objectId, options) {
|
|
367
|
+
return this._call('updateObject', objectId, options);
|
|
368
|
+
}
|
|
369
|
+
async deleteObjects(objectIds) {
|
|
370
|
+
await this._call('deleteObjects', objectIds);
|
|
371
|
+
}
|
|
372
|
+
// ---------------------------------------------------------------------------
|
|
250
373
|
// Schema
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
374
|
+
// ---------------------------------------------------------------------------
|
|
375
|
+
getSchema() {
|
|
376
|
+
return this._schema;
|
|
377
|
+
}
|
|
378
|
+
async createCollection(name, fields) {
|
|
379
|
+
const result = await this._call('createCollection', name, fields);
|
|
380
|
+
this._schema[name] = result;
|
|
381
|
+
return result;
|
|
382
|
+
}
|
|
383
|
+
async alterCollection(name, fields) {
|
|
384
|
+
const result = await this._call('alterCollection', name, fields);
|
|
385
|
+
this._schema[name] = result;
|
|
386
|
+
return result;
|
|
387
|
+
}
|
|
388
|
+
async dropCollection(name) {
|
|
389
|
+
await this._call('dropCollection', name);
|
|
390
|
+
delete this._schema[name];
|
|
391
|
+
}
|
|
392
|
+
// ---------------------------------------------------------------------------
|
|
393
|
+
// Interactions & system instruction
|
|
394
|
+
// ---------------------------------------------------------------------------
|
|
395
|
+
async getInteractions() {
|
|
396
|
+
return this._call('getInteractions');
|
|
397
|
+
}
|
|
398
|
+
async getTree() {
|
|
399
|
+
return this._call('getTree');
|
|
400
|
+
}
|
|
401
|
+
async getActiveLeafId() {
|
|
402
|
+
return this._call('getActiveLeafId');
|
|
403
|
+
}
|
|
404
|
+
async setActiveLeaf(interactionId) {
|
|
405
|
+
await this._call('setActiveLeaf', interactionId);
|
|
406
|
+
}
|
|
407
|
+
async getSystemInstruction() {
|
|
408
|
+
return this._call('getSystemInstruction');
|
|
409
|
+
}
|
|
410
|
+
async setSystemInstruction(instruction) {
|
|
411
|
+
await this._call('setSystemInstruction', instruction);
|
|
412
|
+
}
|
|
413
|
+
async getConversations() {
|
|
414
|
+
return this._call('getConversations');
|
|
415
|
+
}
|
|
416
|
+
async deleteConversation(conversationId) {
|
|
417
|
+
await this._call('deleteConversation', conversationId);
|
|
418
|
+
}
|
|
419
|
+
async renameConversation(name) {
|
|
420
|
+
await this._call('renameConversation', name);
|
|
421
|
+
}
|
|
422
|
+
// ---------------------------------------------------------------------------
|
|
255
423
|
// Conversations
|
|
424
|
+
// ---------------------------------------------------------------------------
|
|
425
|
+
/**
|
|
426
|
+
* Get a reactive handle for a specific conversation within this channel.
|
|
427
|
+
* Scopes AI and mutation operations to that conversation's interaction history.
|
|
428
|
+
* Conversations are auto-created on first interaction.
|
|
429
|
+
*/
|
|
256
430
|
conversation(conversationId) {
|
|
257
431
|
if (this.#closed)
|
|
258
432
|
throw new Error('Cannot create reactive conversation: channel is closed');
|
|
259
|
-
return new ReactiveConversationHandleImpl(this
|
|
433
|
+
return new ReactiveConversationHandleImpl(this, conversationId);
|
|
434
|
+
}
|
|
435
|
+
// ---------------------------------------------------------------------------
|
|
436
|
+
// Metadata
|
|
437
|
+
// ---------------------------------------------------------------------------
|
|
438
|
+
async setMetadata(key, value) {
|
|
439
|
+
await this._call('setMetadata', key, value);
|
|
440
|
+
this._metadata[key] = value;
|
|
441
|
+
}
|
|
442
|
+
getMetadata(key) {
|
|
443
|
+
return this._metadata[key];
|
|
444
|
+
}
|
|
445
|
+
getAllMetadata() {
|
|
446
|
+
return { ...this._metadata };
|
|
447
|
+
}
|
|
448
|
+
// ---------------------------------------------------------------------------
|
|
449
|
+
// AI
|
|
450
|
+
// ---------------------------------------------------------------------------
|
|
451
|
+
async prompt(text, options) {
|
|
452
|
+
return this._call('prompt', text, options);
|
|
453
|
+
}
|
|
454
|
+
// ---------------------------------------------------------------------------
|
|
455
|
+
// Undo/redo
|
|
456
|
+
// ---------------------------------------------------------------------------
|
|
457
|
+
async checkpoint(label) {
|
|
458
|
+
return this._call('checkpoint', label);
|
|
459
|
+
}
|
|
460
|
+
async canUndo() {
|
|
461
|
+
return this._call('canUndo');
|
|
462
|
+
}
|
|
463
|
+
async canRedo() {
|
|
464
|
+
return this._call('canRedo');
|
|
465
|
+
}
|
|
466
|
+
async undo() {
|
|
467
|
+
return this._call('undo');
|
|
468
|
+
}
|
|
469
|
+
async redo() {
|
|
470
|
+
return this._call('redo');
|
|
471
|
+
}
|
|
472
|
+
async clearHistory() {
|
|
473
|
+
await this._call('clearHistory');
|
|
260
474
|
}
|
|
261
|
-
//
|
|
262
|
-
on(...args) { return this.#channel.on(...args); }
|
|
263
|
-
off(...args) { return this.#channel.off(...args); }
|
|
475
|
+
// ---------------------------------------------------------------------------
|
|
264
476
|
// Reactive primitives
|
|
477
|
+
// ---------------------------------------------------------------------------
|
|
265
478
|
object(objectId) {
|
|
266
479
|
if (this.#closed)
|
|
267
480
|
throw new Error('Cannot create reactive object: channel is closed');
|
|
268
|
-
return new ReactiveObjectImpl(this
|
|
481
|
+
return new ReactiveObjectImpl(this, objectId);
|
|
269
482
|
}
|
|
270
483
|
watch(options) {
|
|
271
484
|
if (this.#closed)
|
|
272
485
|
throw new Error('Cannot create reactive watch: channel is closed');
|
|
273
|
-
return new ReactiveWatchImpl(this
|
|
486
|
+
return new ReactiveWatchImpl(this, options);
|
|
274
487
|
}
|
|
488
|
+
// ---------------------------------------------------------------------------
|
|
275
489
|
// Cleanup
|
|
490
|
+
// ---------------------------------------------------------------------------
|
|
276
491
|
destroy() {
|
|
277
492
|
this.#closed = true;
|
|
278
493
|
for (const unsub of this.#unsubscribers)
|
|
279
494
|
unsub();
|
|
280
495
|
this.#unsubscribers.length = 0;
|
|
281
|
-
this
|
|
496
|
+
window.removeEventListener('message', this._onMessage);
|
|
497
|
+
for (const { reject } of this._pending.values()) {
|
|
498
|
+
reject(new Error('Channel destroyed'));
|
|
499
|
+
}
|
|
500
|
+
this._pending.clear();
|
|
501
|
+
this._listeners.clear();
|
|
282
502
|
}
|
|
283
503
|
}
|
|
284
504
|
// ---------------------------------------------------------------------------
|
|
@@ -286,56 +506,91 @@ class ReactiveChannelImpl {
|
|
|
286
506
|
// ---------------------------------------------------------------------------
|
|
287
507
|
/**
|
|
288
508
|
* A reactive conversation handle for the extension bridge.
|
|
289
|
-
*
|
|
290
|
-
*
|
|
509
|
+
* Scopes AI and mutation operations to a specific conversation's
|
|
510
|
+
* interaction history, while sharing the channel's bridge connection.
|
|
291
511
|
*
|
|
292
512
|
* Call `close()` when done to stop listening for updates.
|
|
293
513
|
*/
|
|
294
514
|
class ReactiveConversationHandleImpl {
|
|
295
|
-
#
|
|
515
|
+
#channel;
|
|
296
516
|
#conversationId;
|
|
297
517
|
#unsubscribers = [];
|
|
298
518
|
// Reactive state
|
|
299
519
|
interactions = $state([]);
|
|
300
520
|
constructor(channel, conversationId) {
|
|
521
|
+
this.#channel = channel;
|
|
301
522
|
this.#conversationId = conversationId;
|
|
302
|
-
this.#handle = channel.conversation(conversationId);
|
|
303
523
|
// Initial load
|
|
304
|
-
this
|
|
524
|
+
this.getInteractions().then((list) => { this.interactions = list; });
|
|
305
525
|
// Listen for updates to this conversation
|
|
306
526
|
const onConversationUpdated = ({ conversationId: cid }) => {
|
|
307
527
|
if (cid === this.#conversationId) {
|
|
308
|
-
this
|
|
528
|
+
this.getInteractions().then((list) => { this.interactions = list; });
|
|
309
529
|
}
|
|
310
530
|
};
|
|
311
531
|
channel.on('conversationUpdated', onConversationUpdated);
|
|
312
532
|
this.#unsubscribers.push(() => channel.off('conversationUpdated', onConversationUpdated));
|
|
313
533
|
// Handle full resets
|
|
314
534
|
const onReset = () => {
|
|
315
|
-
this
|
|
535
|
+
this.getInteractions().then((list) => { this.interactions = list; });
|
|
316
536
|
};
|
|
317
537
|
channel.on('reset', onReset);
|
|
318
538
|
this.#unsubscribers.push(() => channel.off('reset', onReset));
|
|
319
539
|
}
|
|
320
540
|
get conversationId() { return this.#conversationId; }
|
|
321
541
|
// Conversation history
|
|
322
|
-
getInteractions() {
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
542
|
+
async getInteractions() {
|
|
543
|
+
return this.#channel._callScoped('getInteractions', [], this.#conversationId);
|
|
544
|
+
}
|
|
545
|
+
async getTree() {
|
|
546
|
+
return this.#channel._callScoped('getTree', [], this.#conversationId);
|
|
547
|
+
}
|
|
548
|
+
async getActiveLeafId() {
|
|
549
|
+
return this.#channel._callScoped('getActiveLeafId', [], this.#conversationId);
|
|
550
|
+
}
|
|
551
|
+
async setActiveLeaf(interactionId) {
|
|
552
|
+
await this.#channel._callScoped('setActiveLeaf', [interactionId], this.#conversationId);
|
|
553
|
+
}
|
|
554
|
+
async getSystemInstruction() {
|
|
555
|
+
return this.#channel._callScoped('getSystemInstruction', [], this.#conversationId);
|
|
556
|
+
}
|
|
557
|
+
async setSystemInstruction(instruction) {
|
|
558
|
+
await this.#channel._callScoped('setSystemInstruction', [instruction], this.#conversationId);
|
|
559
|
+
}
|
|
560
|
+
async rename(name) {
|
|
561
|
+
await this.#channel._callScoped('renameConversation', [name], this.#conversationId);
|
|
562
|
+
}
|
|
326
563
|
// Object operations
|
|
327
|
-
findObjects(options) {
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
564
|
+
async findObjects(options) {
|
|
565
|
+
return this.#channel._callScoped('findObjects', [options], this.#conversationId);
|
|
566
|
+
}
|
|
567
|
+
async createObject(options) {
|
|
568
|
+
return this.#channel._callScoped('createObject', [options], this.#conversationId);
|
|
569
|
+
}
|
|
570
|
+
async updateObject(objectId, options) {
|
|
571
|
+
return this.#channel._callScoped('updateObject', [objectId, options], this.#conversationId);
|
|
572
|
+
}
|
|
573
|
+
async deleteObjects(objectIds) {
|
|
574
|
+
await this.#channel._callScoped('deleteObjects', [objectIds], this.#conversationId);
|
|
575
|
+
}
|
|
331
576
|
// AI
|
|
332
|
-
prompt(text, options) {
|
|
577
|
+
async prompt(text, options) {
|
|
578
|
+
return this.#channel._callScoped('prompt', [text, options], this.#conversationId);
|
|
579
|
+
}
|
|
333
580
|
// Schema
|
|
334
|
-
createCollection(name, fields) {
|
|
335
|
-
|
|
336
|
-
|
|
581
|
+
async createCollection(name, fields) {
|
|
582
|
+
return this.#channel._callScoped('createCollection', [name, fields], this.#conversationId);
|
|
583
|
+
}
|
|
584
|
+
async alterCollection(name, fields) {
|
|
585
|
+
return this.#channel._callScoped('alterCollection', [name, fields], this.#conversationId);
|
|
586
|
+
}
|
|
587
|
+
async dropCollection(name) {
|
|
588
|
+
await this.#channel._callScoped('dropCollection', [name], this.#conversationId);
|
|
589
|
+
}
|
|
337
590
|
// Metadata
|
|
338
|
-
setMetadata(key, value) {
|
|
591
|
+
async setMetadata(key, value) {
|
|
592
|
+
await this.#channel._callScoped('setMetadata', [key, value], this.#conversationId);
|
|
593
|
+
}
|
|
339
594
|
/**
|
|
340
595
|
* Stop listening for updates and clean up.
|
|
341
596
|
*/
|
|
@@ -346,17 +601,47 @@ class ReactiveConversationHandleImpl {
|
|
|
346
601
|
}
|
|
347
602
|
}
|
|
348
603
|
// ---------------------------------------------------------------------------
|
|
349
|
-
// initExtension
|
|
604
|
+
// initExtension
|
|
350
605
|
// ---------------------------------------------------------------------------
|
|
351
|
-
import { initExtension as initBridge } from './client.js';
|
|
352
606
|
/**
|
|
353
607
|
* Initialize the extension and return a reactive channel.
|
|
354
608
|
*
|
|
355
609
|
* Sends `rool:ready` to the host, waits for the handshake, and returns
|
|
356
610
|
* a reactive channel with $state properties (interactions, objectIds)
|
|
357
611
|
* and reactive primitives (object(), watch()).
|
|
612
|
+
*
|
|
613
|
+
* If the extension is opened directly (not in an iframe), redirects to the Rool
|
|
614
|
+
* console with `?openExtension={extensionId}` so the user can install or navigate to it.
|
|
615
|
+
*
|
|
616
|
+
* @param timeout - How long to wait for the handshake (ms). Default: 10000.
|
|
358
617
|
*/
|
|
359
|
-
export
|
|
360
|
-
|
|
361
|
-
|
|
618
|
+
export function initExtension(timeout = 10000) {
|
|
619
|
+
// Deep link: if not in an iframe, redirect to the Rool console
|
|
620
|
+
if (window.self === window.top) {
|
|
621
|
+
const host = window.location.hostname;
|
|
622
|
+
const dot = host.indexOf('.');
|
|
623
|
+
if (dot > 0) {
|
|
624
|
+
const extensionId = host.slice(0, dot);
|
|
625
|
+
const domain = host.slice(dot + 1);
|
|
626
|
+
window.location.href = `https://${domain}/?openExtension=${extensionId}`;
|
|
627
|
+
}
|
|
628
|
+
// Never resolve — the redirect will unload the page
|
|
629
|
+
return new Promise(() => { });
|
|
630
|
+
}
|
|
631
|
+
return new Promise((resolve, reject) => {
|
|
632
|
+
const timer = setTimeout(() => {
|
|
633
|
+
window.removeEventListener('message', onMessage);
|
|
634
|
+
reject(new Error('Extension handshake timed out — is this running inside a Rool host?'));
|
|
635
|
+
}, timeout);
|
|
636
|
+
function onMessage(event) {
|
|
637
|
+
if (!isBridgeMessage(event.data) || event.data.type !== 'rool:init')
|
|
638
|
+
return;
|
|
639
|
+
clearTimeout(timer);
|
|
640
|
+
window.removeEventListener('message', onMessage);
|
|
641
|
+
resolve(new ReactiveChannelImpl(event.data));
|
|
642
|
+
}
|
|
643
|
+
window.addEventListener('message', onMessage);
|
|
644
|
+
// Signal to the host that we're ready
|
|
645
|
+
window.parent.postMessage({ type: 'rool:ready' }, '*');
|
|
646
|
+
});
|
|
362
647
|
}
|
package/dist/types.d.ts
CHANGED
|
@@ -50,6 +50,8 @@ export interface ToolCall {
|
|
|
50
50
|
export type InteractionStatus = 'pending' | 'streaming' | 'done' | 'error';
|
|
51
51
|
export interface Interaction {
|
|
52
52
|
id: string;
|
|
53
|
+
/** Parent interaction in the conversation tree. null = root message. */
|
|
54
|
+
parentId: string | null;
|
|
53
55
|
timestamp: number;
|
|
54
56
|
userId: string;
|
|
55
57
|
userName?: string | null;
|
|
@@ -69,6 +71,8 @@ export interface PromptOptions {
|
|
|
69
71
|
effort?: PromptEffort;
|
|
70
72
|
ephemeral?: boolean;
|
|
71
73
|
readOnly?: boolean;
|
|
74
|
+
/** Parent interaction in the conversation tree. Omit to auto-continue from the active leaf. */
|
|
75
|
+
parentInteractionId?: string | null;
|
|
72
76
|
}
|
|
73
77
|
export interface FindObjectsOptions {
|
|
74
78
|
where?: Record<string, unknown>;
|
package/dist/types.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAIH,MAAM,WAAW,UAAU;IACzB,EAAE,EAAE,MAAM,CAAC;IACX,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;CACxB;AAED,MAAM,WAAW,cAAc;IAC7B,UAAU,EAAE,MAAM,CAAC;IACnB,UAAU,EAAE,MAAM,CAAC;IACnB,cAAc,EAAE,MAAM,GAAG,IAAI,CAAC;CAC/B;AAID,MAAM,MAAM,SAAS,GACjB;IAAE,IAAI,EAAE,QAAQ,CAAA;CAAE,GAClB;IAAE,IAAI,EAAE,QAAQ,CAAA;CAAE,GAClB;IAAE,IAAI,EAAE,SAAS,CAAA;CAAE,GACnB;IAAE,IAAI,EAAE,OAAO,CAAC;IAAC,KAAK,CAAC,EAAE,SAAS,CAAA;CAAE,GACpC;IAAE,IAAI,EAAE,OAAO,CAAC;IAAC,KAAK,EAAE,SAAS,CAAA;CAAE,GACnC;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,EAAE,CAAA;CAAE,GAClC;IAAE,IAAI,EAAE,SAAS,CAAC;IAAC,KAAK,EAAE,MAAM,GAAG,MAAM,GAAG,OAAO,CAAA;CAAE,GACrD;IAAE,IAAI,EAAE,KAAK,CAAA;CAAE,CAAC;AAEpB,MAAM,WAAW,QAAQ;IACvB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,SAAS,CAAC;CACjB;AAED,MAAM,WAAW,aAAa;IAC5B,MAAM,EAAE,QAAQ,EAAE,CAAC;CACpB;AAED,MAAM,MAAM,WAAW,GAAG,MAAM,CAAC,MAAM,EAAE,aAAa,CAAC,CAAC;AAIxD,MAAM,WAAW,QAAQ;IACvB,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,OAAO,CAAC;IACf,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,MAAM,iBAAiB,GAAG,SAAS,GAAG,WAAW,GAAG,MAAM,GAAG,OAAO,CAAC;AAE3E,MAAM,WAAW,WAAW;IAC1B,EAAE,EAAE,MAAM,CAAC;IACX,SAAS,EAAE,MAAM,CAAC;IAClB,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,SAAS,EAAE,QAAQ,GAAG,cAAc,GAAG,cAAc,GAAG,eAAe,CAAC;IACxE,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB,MAAM,EAAE,iBAAiB,CAAC;IAC1B,EAAE,EAAE,OAAO,CAAC;IACZ,iBAAiB,EAAE,MAAM,EAAE,CAAC;IAC5B,SAAS,EAAE,QAAQ,EAAE,CAAC;IACtB,WAAW,CAAC,EAAE,MAAM,EAAE,CAAC;CACxB;AAID,MAAM,MAAM,YAAY,GAAG,OAAO,GAAG,UAAU,GAAG,WAAW,GAAG,UAAU,CAAC;AAE3E,MAAM,WAAW,aAAa;IAC5B,SAAS,CAAC,EAAE,MAAM,EAAE,CAAC;IACrB,cAAc,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACzC,MAAM,CAAC,EAAE,YAAY,CAAC;IACtB,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,QAAQ,CAAC,EAAE,OAAO,CAAC;
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@rool-dev/extension",
|
|
3
|
-
"version": "0.3.
|
|
3
|
+
"version": "0.3.8-dev.368b058",
|
|
4
4
|
"description": "Svelte-first extension SDK for Rool — reactive channel over iframe bridge",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"svelte": "./dist/index.js",
|
|
@@ -57,7 +57,7 @@
|
|
|
57
57
|
"archiver": "^7.0.1",
|
|
58
58
|
"tailwindcss": "^4.2.2",
|
|
59
59
|
"vite": "^8.0.0",
|
|
60
|
-
"@rool-dev/sdk": "0.3.
|
|
60
|
+
"@rool-dev/sdk": "0.3.8-dev.368b058"
|
|
61
61
|
},
|
|
62
62
|
"devDependencies": {
|
|
63
63
|
"@sveltejs/package": "^2.5.7",
|