@rool-dev/extension 0.3.7 → 0.3.8-dev.b3f8671

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/dist/client.d.ts DELETED
@@ -1,139 +0,0 @@
1
- /**
2
- * Extension-side bridge client.
3
- *
4
- * `initExtension()` waits for the host handshake, then returns a `Channel`
5
- * that mirrors the RoolChannel API over postMessage.
6
- */
7
- import type { BridgeInit } from './protocol.js';
8
- import type { RoolObject, RoolObjectStat, SpaceSchema, CollectionDef, FieldDef, Interaction, ConversationInfo, PromptOptions, FindObjectsOptions, CreateObjectOptions, UpdateObjectOptions, RoolUserRole, LinkAccess, ChannelEvents } from './types.js';
9
- type EventName = keyof ChannelEvents;
10
- export declare class Channel {
11
- private _pending;
12
- private _listeners;
13
- readonly channelId: string;
14
- readonly spaceId: string;
15
- readonly spaceName: string;
16
- readonly role: RoolUserRole;
17
- readonly linkAccess: LinkAccess;
18
- readonly userId: string;
19
- private _schema;
20
- private _metadata;
21
- constructor(init: BridgeInit);
22
- get isReadOnly(): boolean;
23
- on<E extends EventName>(event: E, callback: (data: ChannelEvents[E]) => void): void;
24
- off<E extends EventName>(event: E, callback: (data: ChannelEvents[E]) => void): void;
25
- private _emit;
26
- private _call;
27
- /**
28
- * Send a bridge request, optionally scoped to a conversation.
29
- * Used internally by Channel (no conversationId) and ConversationHandle.
30
- * @internal
31
- */
32
- _callScoped(method: string, args: unknown[], conversationId?: string): Promise<unknown>;
33
- private _onMessage;
34
- getObject(objectId: string): Promise<RoolObject | undefined>;
35
- stat(objectId: string): Promise<RoolObjectStat | undefined>;
36
- findObjects(options: FindObjectsOptions): Promise<{
37
- objects: RoolObject[];
38
- message: string;
39
- }>;
40
- getObjectIds(options?: {
41
- limit?: number;
42
- order?: 'asc' | 'desc';
43
- }): Promise<string[]>;
44
- createObject(options: CreateObjectOptions): Promise<{
45
- object: RoolObject;
46
- message: string;
47
- }>;
48
- updateObject(objectId: string, options: UpdateObjectOptions): Promise<{
49
- object: RoolObject;
50
- message: string;
51
- }>;
52
- deleteObjects(objectIds: string[]): Promise<void>;
53
- getSchema(): SpaceSchema;
54
- createCollection(name: string, fields: FieldDef[]): Promise<CollectionDef>;
55
- alterCollection(name: string, fields: FieldDef[]): Promise<CollectionDef>;
56
- dropCollection(name: string): Promise<void>;
57
- getInteractions(): Promise<Interaction[]>;
58
- getSystemInstruction(): Promise<string | undefined>;
59
- setSystemInstruction(instruction: string | null): Promise<void>;
60
- getConversations(): Promise<ConversationInfo[]>;
61
- deleteConversation(conversationId: string): Promise<void>;
62
- renameConversation(name: string): Promise<void>;
63
- /**
64
- * Get a handle for a specific conversation within this channel.
65
- * Scopes AI and mutation operations to that conversation's interaction history.
66
- * Conversations are auto-created on first interaction.
67
- */
68
- conversation(conversationId: string): ConversationHandle;
69
- setMetadata(key: string, value: unknown): Promise<void>;
70
- getMetadata(key: string): unknown;
71
- getAllMetadata(): Record<string, unknown>;
72
- prompt(text: string, options?: PromptOptions): Promise<{
73
- message: string;
74
- objects: RoolObject[];
75
- }>;
76
- checkpoint(label?: string): Promise<string>;
77
- canUndo(): Promise<boolean>;
78
- canRedo(): Promise<boolean>;
79
- undo(): Promise<boolean>;
80
- redo(): Promise<boolean>;
81
- clearHistory(): Promise<void>;
82
- destroy(): void;
83
- }
84
- /**
85
- * A conversation handle for the extension bridge.
86
- * Mirrors the SDK's ConversationHandle API over postMessage.
87
- *
88
- * Scopes AI and mutation operations to a specific conversation's
89
- * interaction history, while sharing the channel's bridge connection.
90
- *
91
- * Obtain via `channel.conversation('thread-id')`.
92
- */
93
- export declare class ConversationHandle {
94
- private _channel;
95
- private _conversationId;
96
- /** @internal */
97
- constructor(channel: Channel, conversationId: string);
98
- /** The conversation ID this handle is scoped to. */
99
- get conversationId(): string;
100
- getInteractions(): Promise<Interaction[]>;
101
- getSystemInstruction(): Promise<string | undefined>;
102
- setSystemInstruction(instruction: string | null): Promise<void>;
103
- rename(name: string): Promise<void>;
104
- findObjects(options: FindObjectsOptions): Promise<{
105
- objects: RoolObject[];
106
- message: string;
107
- }>;
108
- createObject(options: CreateObjectOptions): Promise<{
109
- object: RoolObject;
110
- message: string;
111
- }>;
112
- updateObject(objectId: string, options: UpdateObjectOptions): Promise<{
113
- object: RoolObject;
114
- message: string;
115
- }>;
116
- deleteObjects(objectIds: string[]): Promise<void>;
117
- prompt(text: string, options?: PromptOptions): Promise<{
118
- message: string;
119
- objects: RoolObject[];
120
- }>;
121
- createCollection(name: string, fields: FieldDef[]): Promise<CollectionDef>;
122
- alterCollection(name: string, fields: FieldDef[]): Promise<CollectionDef>;
123
- dropCollection(name: string): Promise<void>;
124
- setMetadata(key: string, value: unknown): Promise<void>;
125
- }
126
- /**
127
- * Initialize the extension bridge. Call this once at startup.
128
- *
129
- * Sends `rool:ready` to the host and waits for `rool:init` with channel metadata.
130
- * Returns a `Channel` that mirrors the RoolChannel API over postMessage.
131
- *
132
- * If the extension is opened directly (not in an iframe), redirects to the Rool
133
- * console with `?openExtension={extensionId}` so the user can install or navigate to it.
134
- *
135
- * @param timeout - How long to wait for the handshake (ms). Default: 10000.
136
- */
137
- export declare function initExtension(timeout?: number): Promise<Channel>;
138
- export {};
139
- //# sourceMappingURL=client.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"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"}
package/dist/client.js DELETED
@@ -1,360 +0,0 @@
1
- /**
2
- * Extension-side bridge client.
3
- *
4
- * `initExtension()` waits for the host handshake, then returns a `Channel`
5
- * that mirrors the RoolChannel API over postMessage.
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
- }
15
- // ---------------------------------------------------------------------------
16
- // Channel
17
- // ---------------------------------------------------------------------------
18
- export class Channel {
19
- _pending = new Map();
20
- _listeners = new Map();
21
- // Metadata from handshake
22
- channelId;
23
- spaceId;
24
- spaceName;
25
- role;
26
- linkAccess;
27
- userId;
28
- _schema;
29
- _metadata;
30
- constructor(init) {
31
- this.channelId = init.channelId;
32
- this.spaceId = init.spaceId;
33
- this.spaceName = init.spaceName;
34
- this.role = init.role;
35
- this.linkAccess = init.linkAccess;
36
- this.userId = init.userId;
37
- this._schema = init.schema;
38
- this._metadata = init.metadata;
39
- window.addEventListener('message', this._onMessage);
40
- }
41
- get isReadOnly() {
42
- return this.role === 'viewer';
43
- }
44
- // ---------------------------------------------------------------------------
45
- // Event emitter
46
- // ---------------------------------------------------------------------------
47
- on(event, callback) {
48
- let set = this._listeners.get(event);
49
- if (!set) {
50
- set = new Set();
51
- this._listeners.set(event, set);
52
- }
53
- set.add(callback);
54
- }
55
- off(event, callback) {
56
- this._listeners.get(event)?.delete(callback);
57
- }
58
- _emit(event, data) {
59
- const set = this._listeners.get(event);
60
- if (set) {
61
- for (const cb of set) {
62
- try {
63
- cb(data);
64
- }
65
- catch (e) {
66
- console.error(`[Channel] Error in ${event} listener:`, e);
67
- }
68
- }
69
- }
70
- }
71
- // ---------------------------------------------------------------------------
72
- // postMessage transport
73
- // ---------------------------------------------------------------------------
74
- _call(method, ...args) {
75
- return this._callScoped(method, args);
76
- }
77
- /**
78
- * Send a bridge request, optionally scoped to a conversation.
79
- * Used internally by Channel (no conversationId) and ConversationHandle.
80
- * @internal
81
- */
82
- _callScoped(method, args, conversationId) {
83
- return new Promise((resolve, reject) => {
84
- const id = nextRequestId();
85
- this._pending.set(id, { resolve, reject });
86
- const msg = { type: 'rool:request', id, method, args };
87
- if (conversationId !== undefined)
88
- msg.conversationId = conversationId;
89
- window.parent.postMessage(msg, '*');
90
- });
91
- }
92
- _onMessage = (event) => {
93
- if (!isBridgeMessage(event.data))
94
- return;
95
- if (event.data.type === 'rool:response') {
96
- const msg = event.data;
97
- const pending = this._pending.get(msg.id);
98
- if (pending) {
99
- this._pending.delete(msg.id);
100
- if (msg.error) {
101
- pending.reject(new Error(msg.error));
102
- }
103
- else {
104
- pending.resolve(msg.result);
105
- }
106
- }
107
- return;
108
- }
109
- if (event.data.type === 'rool:event') {
110
- const msg = event.data;
111
- // Update local caches before emitting so listeners see fresh data
112
- if (msg.name === 'metadataUpdated') {
113
- const payload = msg.data;
114
- this._metadata = payload.metadata;
115
- }
116
- else if (msg.name === 'schemaUpdated') {
117
- const payload = msg.data;
118
- this._schema = payload.schema;
119
- }
120
- else if (msg.name === 'reset') {
121
- // Full reload happened on the host — refresh cached schema and metadata
122
- Promise.all([
123
- this._call('getSchema'),
124
- this._call('getAllMetadata'),
125
- ]).then(([schema, metadata]) => {
126
- this._schema = schema;
127
- this._metadata = metadata;
128
- });
129
- }
130
- this._emit(msg.name, msg.data);
131
- return;
132
- }
133
- };
134
- // ---------------------------------------------------------------------------
135
- // Channel API — mirrors RoolChannel
136
- // ---------------------------------------------------------------------------
137
- // Object operations
138
- async getObject(objectId) {
139
- return this._call('getObject', objectId);
140
- }
141
- async stat(objectId) {
142
- return this._call('stat', objectId);
143
- }
144
- async findObjects(options) {
145
- return this._call('findObjects', options);
146
- }
147
- async getObjectIds(options) {
148
- return this._call('getObjectIds', options);
149
- }
150
- async createObject(options) {
151
- return this._call('createObject', options);
152
- }
153
- async updateObject(objectId, options) {
154
- return this._call('updateObject', objectId, options);
155
- }
156
- async deleteObjects(objectIds) {
157
- await this._call('deleteObjects', objectIds);
158
- }
159
- // Schema
160
- getSchema() {
161
- return this._schema;
162
- }
163
- async createCollection(name, fields) {
164
- const result = await this._call('createCollection', name, fields);
165
- this._schema[name] = result;
166
- return result;
167
- }
168
- async alterCollection(name, fields) {
169
- const result = await this._call('alterCollection', name, fields);
170
- this._schema[name] = result;
171
- return result;
172
- }
173
- async dropCollection(name) {
174
- await this._call('dropCollection', name);
175
- delete this._schema[name];
176
- }
177
- // Interactions & system instruction
178
- async getInteractions() {
179
- return this._call('getInteractions');
180
- }
181
- async getSystemInstruction() {
182
- return this._call('getSystemInstruction');
183
- }
184
- async setSystemInstruction(instruction) {
185
- await this._call('setSystemInstruction', instruction);
186
- }
187
- async getConversations() {
188
- return this._call('getConversations');
189
- }
190
- async deleteConversation(conversationId) {
191
- await this._call('deleteConversation', conversationId);
192
- }
193
- async renameConversation(name) {
194
- await this._call('renameConversation', name);
195
- }
196
- // Conversations
197
- /**
198
- * Get a handle for a specific conversation within this channel.
199
- * Scopes AI and mutation operations to that conversation's interaction history.
200
- * Conversations are auto-created on first interaction.
201
- */
202
- conversation(conversationId) {
203
- return new ConversationHandle(this, conversationId);
204
- }
205
- // Metadata
206
- async setMetadata(key, value) {
207
- await this._call('setMetadata', key, value);
208
- this._metadata[key] = value;
209
- }
210
- getMetadata(key) {
211
- return this._metadata[key];
212
- }
213
- getAllMetadata() {
214
- return { ...this._metadata };
215
- }
216
- // AI
217
- async prompt(text, options) {
218
- return this._call('prompt', text, options);
219
- }
220
- // Undo/redo
221
- async checkpoint(label) {
222
- return this._call('checkpoint', label);
223
- }
224
- async canUndo() {
225
- return this._call('canUndo');
226
- }
227
- async canRedo() {
228
- return this._call('canRedo');
229
- }
230
- async undo() {
231
- return this._call('undo');
232
- }
233
- async redo() {
234
- return this._call('redo');
235
- }
236
- async clearHistory() {
237
- await this._call('clearHistory');
238
- }
239
- // Cleanup
240
- destroy() {
241
- window.removeEventListener('message', this._onMessage);
242
- for (const { reject } of this._pending.values()) {
243
- reject(new Error('Channel destroyed'));
244
- }
245
- this._pending.clear();
246
- this._listeners.clear();
247
- }
248
- }
249
- // ---------------------------------------------------------------------------
250
- // ConversationHandle
251
- // ---------------------------------------------------------------------------
252
- /**
253
- * A conversation handle for the extension bridge.
254
- * Mirrors the SDK's ConversationHandle API over postMessage.
255
- *
256
- * Scopes AI and mutation operations to a specific conversation's
257
- * interaction history, while sharing the channel's bridge connection.
258
- *
259
- * Obtain via `channel.conversation('thread-id')`.
260
- */
261
- export class ConversationHandle {
262
- _channel;
263
- _conversationId;
264
- /** @internal */
265
- constructor(channel, conversationId) {
266
- this._channel = channel;
267
- this._conversationId = conversationId;
268
- }
269
- /** The conversation ID this handle is scoped to. */
270
- get conversationId() { return this._conversationId; }
271
- // Conversation history
272
- async getInteractions() {
273
- return this._channel._callScoped('getInteractions', [], this._conversationId);
274
- }
275
- async getSystemInstruction() {
276
- return this._channel._callScoped('getSystemInstruction', [], this._conversationId);
277
- }
278
- async setSystemInstruction(instruction) {
279
- await this._channel._callScoped('setSystemInstruction', [instruction], this._conversationId);
280
- }
281
- async rename(name) {
282
- await this._channel._callScoped('renameConversation', [name], this._conversationId);
283
- }
284
- // Object operations
285
- async findObjects(options) {
286
- return this._channel._callScoped('findObjects', [options], this._conversationId);
287
- }
288
- async createObject(options) {
289
- return this._channel._callScoped('createObject', [options], this._conversationId);
290
- }
291
- async updateObject(objectId, options) {
292
- return this._channel._callScoped('updateObject', [objectId, options], this._conversationId);
293
- }
294
- async deleteObjects(objectIds) {
295
- await this._channel._callScoped('deleteObjects', [objectIds], this._conversationId);
296
- }
297
- // AI
298
- async prompt(text, options) {
299
- return this._channel._callScoped('prompt', [text, options], this._conversationId);
300
- }
301
- // Schema
302
- async createCollection(name, fields) {
303
- return this._channel._callScoped('createCollection', [name, fields], this._conversationId);
304
- }
305
- async alterCollection(name, fields) {
306
- return this._channel._callScoped('alterCollection', [name, fields], this._conversationId);
307
- }
308
- async dropCollection(name) {
309
- await this._channel._callScoped('dropCollection', [name], this._conversationId);
310
- }
311
- // Metadata
312
- async setMetadata(key, value) {
313
- await this._channel._callScoped('setMetadata', [key, value], this._conversationId);
314
- }
315
- }
316
- // ---------------------------------------------------------------------------
317
- // initExtension
318
- // ---------------------------------------------------------------------------
319
- /**
320
- * Initialize the extension bridge. Call this once at startup.
321
- *
322
- * Sends `rool:ready` to the host and waits for `rool:init` with channel metadata.
323
- * Returns a `Channel` that mirrors the RoolChannel API over postMessage.
324
- *
325
- * If the extension is opened directly (not in an iframe), redirects to the Rool
326
- * console with `?openExtension={extensionId}` so the user can install or navigate to it.
327
- *
328
- * @param timeout - How long to wait for the handshake (ms). Default: 10000.
329
- */
330
- export function initExtension(timeout = 10000) {
331
- // Deep link: if not in an iframe, redirect to the Rool console
332
- if (window.self === window.top) {
333
- const host = window.location.hostname;
334
- const dot = host.indexOf('.');
335
- if (dot > 0) {
336
- const extensionId = host.slice(0, dot);
337
- const domain = host.slice(dot + 1);
338
- window.location.href = `https://${domain}/?openExtension=${extensionId}`;
339
- }
340
- // Never resolve — the redirect will unload the page
341
- return new Promise(() => { });
342
- }
343
- return new Promise((resolve, reject) => {
344
- const timer = setTimeout(() => {
345
- window.removeEventListener('message', onMessage);
346
- reject(new Error('Extension handshake timed out — is this running inside a Rool host?'));
347
- }, timeout);
348
- function onMessage(event) {
349
- if (!isBridgeMessage(event.data) || event.data.type !== 'rool:init')
350
- return;
351
- clearTimeout(timer);
352
- window.removeEventListener('message', onMessage);
353
- const channel = new Channel(event.data);
354
- resolve(channel);
355
- }
356
- window.addEventListener('message', onMessage);
357
- // Signal to the host that we're ready
358
- window.parent.postMessage({ type: 'rool:ready' }, '*');
359
- });
360
- }