@rimori/client 2.2.0-next.3 → 2.2.0-next.5

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.
@@ -92,18 +92,18 @@ jobs:
92
92
  # Uses OIDC token automatically (no NODE_AUTH_TOKEN needed)
93
93
  # Requires npm 11.5.1+ and id-token: write permission (already set)
94
94
 
95
- - name: Commit version bump
96
- run: |
97
- git config --local user.email "action@github.com"
98
- git config --local user.name "GitHub Action"
99
- git add package.json
100
- git commit -m "chore: bump @rimori/client to ${{ steps.version.outputs.new_version }} [skip ci]"
101
- git push
102
-
103
95
  - name: Output published version
104
96
  run: |
105
97
  echo "✅ Published @rimori/client@${{ steps.version.outputs.new_version }} to npm with @next tag"
106
98
 
99
+ - name: Create git tag
100
+ run: |
101
+ git config --local user.email "action@github.com"
102
+ git config --local user.name "GitHub Action"
103
+ git tag "v${{ steps.version.outputs.new_version }}" -m "Pre-release v${{ steps.version.outputs.new_version }}"
104
+ git push origin "v${{ steps.version.outputs.new_version }}"
105
+ echo "🏷️ Created and pushed tag v${{ steps.version.outputs.new_version }}"
106
+
107
107
  - name: Notify Slack
108
108
  if: always()
109
109
  uses: slackapi/slack-github-action@v1.24.0
@@ -12,18 +12,18 @@ export class EventBusHandler {
12
12
  this.listeners = new Map();
13
13
  this.responseResolvers = new Map();
14
14
  this.debugEnabled = false;
15
- this.evName = "";
15
+ this.evName = '';
16
16
  //private constructor
17
17
  }
18
18
  static getInstance(name) {
19
19
  if (!EventBusHandler.instance) {
20
20
  EventBusHandler.instance = new EventBusHandler();
21
- EventBusHandler.instance.on("global.system.requestDebug", () => {
21
+ EventBusHandler.instance.on('global.system.requestDebug', () => {
22
22
  EventBusHandler.instance.debugEnabled = true;
23
23
  console.log(`[${EventBusHandler.instance.evName}] Debug mode enabled. Make sure debugging messages are enabled in the browser console.`);
24
24
  });
25
25
  }
26
- if (name && EventBusHandler.instance.evName === "") {
26
+ if (name && EventBusHandler.instance.evName === '') {
27
27
  EventBusHandler.instance.evName = name;
28
28
  }
29
29
  return EventBusHandler.instance;
@@ -79,9 +79,7 @@ export class EventBusHandler {
79
79
  this.logAndThrowError(false, `No handlers found for topic: ` + topic);
80
80
  }
81
81
  // If it's a response to a request
82
- if (eventId &&
83
- this.responseResolvers.has(eventId) &&
84
- !skipResponseTrigger) {
82
+ if (eventId && this.responseResolvers.has(eventId) && !skipResponseTrigger) {
85
83
  // console.log("[Rimori] Resolving response to request: " + eventId, event.data);
86
84
  this.responseResolvers.get(eventId)(event);
87
85
  this.responseResolvers.delete(eventId);
@@ -108,7 +106,7 @@ export class EventBusHandler {
108
106
  const blackListedEventIds = [];
109
107
  const eventHandler = (data) => {
110
108
  if (blackListedEventIds.some((item) => item.eventId === data.eventId && item.sender === data.sender)) {
111
- console.log("BLACKLISTED EVENT ID", data.eventId, data);
109
+ console.log('BLACKLISTED EVENT ID', data.eventId, data);
112
110
  return;
113
111
  }
114
112
  blackListedEventIds.push({
@@ -120,9 +118,7 @@ export class EventBusHandler {
120
118
  }
121
119
  return handler(data);
122
120
  };
123
- this.listeners
124
- .get(topic)
125
- .add({ id, handler: eventHandler, ignoreSender });
121
+ this.listeners.get(topic).add({ id, handler: eventHandler, ignoreSender });
126
122
  this.logIfDebug(`Subscribed to ` + topic, {
127
123
  listenerId: id,
128
124
  ignoreSender,
@@ -145,7 +141,7 @@ export class EventBusHandler {
145
141
  const listeners = topics.map((topic) => {
146
142
  const blackListedEventIds = [];
147
143
  //To allow event communication inside the same plugin the sender needs to be ignored but the events still need to be checked for the same event just reaching the subscriber to prevent infinite loops
148
- const finalIgnoreSender = !topic.startsWith("self.") ? [sender] : [];
144
+ const finalIgnoreSender = !topic.startsWith('self.') ? [sender] : [];
149
145
  const listener = this.on(topic, (data) => __awaiter(this, void 0, void 0, function* () {
150
146
  if (blackListedEventIds.includes(data.eventId)) {
151
147
  // console.log("BLACKLISTED EVENT ID", data.eventId);
@@ -155,10 +151,10 @@ export class EventBusHandler {
155
151
  if (blackListedEventIds.length > 100) {
156
152
  blackListedEventIds.shift();
157
153
  }
158
- const response = typeof handler === "function" ? yield handler(data) : handler;
154
+ const response = typeof handler === 'function' ? yield handler(data) : handler;
159
155
  this.emit(sender, topic, response, data.eventId);
160
156
  }), finalIgnoreSender);
161
- this.logIfDebug(`Added respond listener ` + sender + " to topic " + topic, { listener, sender });
157
+ this.logIfDebug(`Added respond listener ` + sender + ' to topic ' + topic, { listener, sender });
162
158
  return {
163
159
  off: () => listener.off(),
164
160
  };
@@ -177,7 +173,7 @@ export class EventBusHandler {
177
173
  this.logAndThrowError(false, `Invalid topic: ` + topic);
178
174
  return;
179
175
  }
180
- let listener;
176
+ let listener = undefined;
181
177
  const wrapper = (event) => {
182
178
  handler(event);
183
179
  listener === null || listener === void 0 ? void 0 : listener.off();
@@ -236,7 +232,7 @@ export class EventBusHandler {
236
232
  const exact = this.listeners.get(topic) || new Set();
237
233
  // Find wildcard matches
238
234
  const wildcard = [...this.listeners.entries()]
239
- .filter(([key]) => key.endsWith("*") && topic.startsWith(key.slice(0, -1)))
235
+ .filter(([key]) => key.endsWith('*') && topic.startsWith(key.slice(0, -1)))
240
236
  .flatMap(([_, handlers]) => [...handlers]);
241
237
  return new Set([...exact, ...wildcard]);
242
238
  }
@@ -247,30 +243,27 @@ export class EventBusHandler {
247
243
  */
248
244
  validateTopic(topic) {
249
245
  // Split event type into parts
250
- const parts = topic.split(".");
246
+ const parts = topic.split('.');
251
247
  const [plugin, area, action] = parts;
252
248
  if (parts.length !== 3) {
253
- if (parts.length === 1 && plugin === "*") {
249
+ if (parts.length === 1 && plugin === '*') {
254
250
  return true;
255
251
  }
256
- if (parts.length === 2 && plugin !== "*" && area === "*") {
252
+ if (parts.length === 2 && plugin !== '*' && area === '*') {
257
253
  return true;
258
254
  }
259
255
  this.logAndThrowError(false, `Event type must have 3 parts separated by dots. Received: ` + topic);
260
256
  return false;
261
257
  }
262
- if (action === "*") {
258
+ if (action === '*') {
263
259
  return true;
264
260
  }
265
261
  // Validate action part
266
- const validActions = ["request", "create", "update", "delete", "trigger"];
262
+ const validActions = ['request', 'create', 'update', 'delete', 'trigger'];
267
263
  if (validActions.some((a) => action.startsWith(a))) {
268
264
  return true;
269
265
  }
270
- this.logAndThrowError(false, `Invalid event topic name. The action: ` +
271
- action +
272
- ". Must be or start with one of: " +
273
- validActions.join(", "));
266
+ this.logAndThrowError(false, `Invalid event topic name. The action: ` + action + '. Must be or start with one of: ' + validActions.join(', '));
274
267
  return false;
275
268
  }
276
269
  logIfDebug(...args) {
@@ -1,9 +1,9 @@
1
- export type Plugin<T extends {} = {}> = Omit<RimoriPluginConfig<T>, 'context_menu_actions'> & {
1
+ export type Plugin<T extends object = object> = Omit<RimoriPluginConfig<T>, 'context_menu_actions'> & {
2
2
  version: string;
3
3
  endpoint: string;
4
4
  assetEndpoint: string;
5
5
  context_menu_actions: MenuEntry[];
6
- release_channel: "alpha" | "beta" | "stable";
6
+ release_channel: 'alpha' | 'beta' | 'stable';
7
7
  };
8
8
  export type ActivePlugin = Plugin<{
9
9
  active?: boolean;
@@ -14,7 +14,7 @@ export interface PluginPage {
14
14
  url: string;
15
15
  show: boolean;
16
16
  description: string;
17
- root: "vocabulary" | "grammar" | "reading" | "listening" | "watching" | "writing" | "speaking" | "other" | "community";
17
+ root: 'vocabulary' | 'grammar' | 'reading' | 'listening' | 'watching' | 'writing' | 'speaking' | 'other' | 'community';
18
18
  action?: {
19
19
  key: string;
20
20
  parameters: ObjectTool;
@@ -46,7 +46,7 @@ export interface ContextMenuAction {
46
46
  * Rimori plugin structure representing the complete configuration
47
47
  * of a Rimori plugin with all metadata and configuration options.
48
48
  */
49
- export interface RimoriPluginConfig<T extends {} = {}> {
49
+ export interface RimoriPluginConfig<T extends object = object> {
50
50
  id: string;
51
51
  /**
52
52
  * Basic information about the plugin including branding and core details.
@@ -79,7 +79,7 @@ export interface RimoriPluginConfig<T extends {} = {}> {
79
79
  /**
80
80
  * Context menu actions that the plugin registers to appear in right-click menus throughout the application.
81
81
  */
82
- context_menu_actions: Omit<MenuEntry, "plugin_id">[];
82
+ context_menu_actions: Omit<MenuEntry, 'plugin_id'>[];
83
83
  /**
84
84
  * Documentation paths for different types of plugin documentation.
85
85
  */
@@ -107,7 +107,7 @@ export interface Tool {
107
107
  parameters: {
108
108
  name: string;
109
109
  description: string;
110
- type: "string" | "number" | "boolean";
110
+ type: 'string' | 'number' | 'boolean';
111
111
  }[];
112
112
  execute?: (args: Record<string, any>) => Promise<unknown> | unknown | void;
113
113
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@rimori/client",
3
- "version": "2.2.0-next.3",
3
+ "version": "2.2.0-next.5",
4
4
  "main": "dist/index.js",
5
5
  "types": "dist/index.d.ts",
6
6
  "repository": {
@@ -23,9 +23,7 @@ export interface EventBusMessage<T = EventPayload> {
23
23
  debug: boolean;
24
24
  }
25
25
 
26
- export type EventHandler<T = EventPayload> = (
27
- event: EventBusMessage<T>
28
- ) => void | Promise<void>;
26
+ export type EventHandler<T = EventPayload> = (event: EventBusMessage<T>) => void | Promise<void>;
29
27
 
30
28
  interface Listeners<T = EventPayload> {
31
29
  id: number;
@@ -39,13 +37,10 @@ export interface EventListener {
39
37
 
40
38
  export class EventBusHandler {
41
39
  private listeners: Map<string, Set<Listeners<EventPayload>>> = new Map();
42
- private responseResolvers: Map<
43
- number,
44
- (value: EventBusMessage<unknown>) => void
45
- > = new Map();
40
+ private responseResolvers: Map<number, (value: EventBusMessage<unknown>) => void> = new Map();
46
41
  private static instance: EventBusHandler | null = null;
47
- private debugEnabled: boolean = false;
48
- private evName: string = "";
42
+ private debugEnabled = false;
43
+ private evName = '';
49
44
 
50
45
  private constructor() {
51
46
  //private constructor
@@ -55,27 +50,22 @@ export class EventBusHandler {
55
50
  if (!EventBusHandler.instance) {
56
51
  EventBusHandler.instance = new EventBusHandler();
57
52
 
58
- EventBusHandler.instance.on("global.system.requestDebug", () => {
53
+ EventBusHandler.instance.on('global.system.requestDebug', () => {
59
54
  EventBusHandler.instance!.debugEnabled = true;
60
55
  console.log(
61
56
  `[${
62
57
  EventBusHandler.instance!.evName
63
- }] Debug mode enabled. Make sure debugging messages are enabled in the browser console.`
58
+ }] Debug mode enabled. Make sure debugging messages are enabled in the browser console.`,
64
59
  );
65
60
  });
66
61
  }
67
- if (name && EventBusHandler.instance.evName === "") {
62
+ if (name && EventBusHandler.instance.evName === '') {
68
63
  EventBusHandler.instance.evName = name;
69
64
  }
70
65
  return EventBusHandler.instance;
71
66
  }
72
67
 
73
- private createEvent(
74
- sender: string,
75
- topic: string,
76
- data: EventPayload,
77
- eventId?: number
78
- ): EventBusMessage {
68
+ private createEvent(sender: string, topic: string, data: EventPayload, eventId?: number): EventBusMessage {
79
69
  const generatedEventId = eventId || Math.floor(Math.random() * 10000000000);
80
70
 
81
71
  return {
@@ -106,12 +96,7 @@ export class EventBusHandler {
106
96
  * - pl1234.card.delete
107
97
  * - pl1234.card.triggerBackup
108
98
  */
109
- public emit<T = EventPayload>(
110
- sender: string,
111
- topic: string,
112
- data?: T,
113
- eventId?: number
114
- ): void {
99
+ public emit<T = EventPayload>(sender: string, topic: string, data?: T, eventId?: number): void {
115
100
  this.emitInternal(sender, topic, data || {}, eventId);
116
101
  }
117
102
 
@@ -120,7 +105,7 @@ export class EventBusHandler {
120
105
  topic: string,
121
106
  data: EventPayload,
122
107
  eventId?: number,
123
- skipResponseTrigger = false
108
+ skipResponseTrigger = false,
124
109
  ): void {
125
110
  if (!this.validateTopic(topic)) {
126
111
  this.logAndThrowError(false, `Invalid topic: ` + topic);
@@ -143,11 +128,7 @@ export class EventBusHandler {
143
128
  }
144
129
 
145
130
  // If it's a response to a request
146
- if (
147
- eventId &&
148
- this.responseResolvers.has(eventId) &&
149
- !skipResponseTrigger
150
- ) {
131
+ if (eventId && this.responseResolvers.has(eventId) && !skipResponseTrigger) {
151
132
  // console.log("[Rimori] Resolving response to request: " + eventId, event.data);
152
133
  this.responseResolvers.get(eventId)!(event);
153
134
  this.responseResolvers.delete(eventId);
@@ -164,7 +145,7 @@ export class EventBusHandler {
164
145
  public on<T = EventPayload>(
165
146
  topics: string | string[],
166
147
  handler: EventHandler<T>,
167
- ignoreSender: string[] = []
148
+ ignoreSender: string[] = [],
168
149
  ): EventListener {
169
150
  const ids = this.toArray(topics).map((topic) => {
170
151
  this.logIfDebug(`Subscribing to ` + topic, { ignoreSender });
@@ -180,13 +161,8 @@ export class EventBusHandler {
180
161
  // To prevent infinite loops and processing the same eventId multiple times
181
162
  const blackListedEventIds: { eventId: number; sender: string }[] = [];
182
163
  const eventHandler = (data: EventBusMessage) => {
183
- if (
184
- blackListedEventIds.some(
185
- (item) =>
186
- item.eventId === data.eventId && item.sender === data.sender
187
- )
188
- ) {
189
- console.log("BLACKLISTED EVENT ID", data.eventId, data);
164
+ if (blackListedEventIds.some((item) => item.eventId === data.eventId && item.sender === data.sender)) {
165
+ console.log('BLACKLISTED EVENT ID', data.eventId, data);
190
166
  return;
191
167
  }
192
168
  blackListedEventIds.push({
@@ -199,9 +175,7 @@ export class EventBusHandler {
199
175
  return (handler as unknown as EventHandler<EventPayload>)(data);
200
176
  };
201
177
 
202
- this.listeners
203
- .get(topic)!
204
- .add({ id, handler: eventHandler, ignoreSender });
178
+ this.listeners.get(topic)!.add({ id, handler: eventHandler, ignoreSender });
205
179
 
206
180
  this.logIfDebug(`Subscribed to ` + topic, {
207
181
  listenerId: id,
@@ -226,15 +200,13 @@ export class EventBusHandler {
226
200
  public respond(
227
201
  sender: string,
228
202
  topic: string | string[],
229
- handler:
230
- | EventPayload
231
- | ((data: EventBusMessage) => EventPayload | Promise<EventPayload>)
203
+ handler: EventPayload | ((data: EventBusMessage) => EventPayload | Promise<EventPayload>),
232
204
  ): EventListener {
233
205
  const topics = Array.isArray(topic) ? topic : [topic];
234
206
  const listeners = topics.map((topic) => {
235
207
  const blackListedEventIds: number[] = [];
236
208
  //To allow event communication inside the same plugin the sender needs to be ignored but the events still need to be checked for the same event just reaching the subscriber to prevent infinite loops
237
- const finalIgnoreSender = !topic.startsWith("self.") ? [sender] : [];
209
+ const finalIgnoreSender = !topic.startsWith('self.') ? [sender] : [];
238
210
 
239
211
  const listener = this.on(
240
212
  topic,
@@ -247,17 +219,13 @@ export class EventBusHandler {
247
219
  if (blackListedEventIds.length > 100) {
248
220
  blackListedEventIds.shift();
249
221
  }
250
- const response =
251
- typeof handler === "function" ? await handler(data) : handler;
222
+ const response = typeof handler === 'function' ? await handler(data) : handler;
252
223
  this.emit(sender, topic, response, data.eventId);
253
224
  },
254
- finalIgnoreSender
225
+ finalIgnoreSender,
255
226
  );
256
227
 
257
- this.logIfDebug(
258
- `Added respond listener ` + sender + " to topic " + topic,
259
- { listener, sender }
260
- );
228
+ this.logIfDebug(`Added respond listener ` + sender + ' to topic ' + topic, { listener, sender });
261
229
  return {
262
230
  off: () => listener.off(),
263
231
  };
@@ -278,7 +246,7 @@ export class EventBusHandler {
278
246
  return;
279
247
  }
280
248
 
281
- let listener: EventListener | undefined;
249
+ let listener: EventListener | undefined = undefined;
282
250
  const wrapper = (event: EventBusMessage<T>) => {
283
251
  handler(event);
284
252
  listener?.off();
@@ -324,7 +292,7 @@ export class EventBusHandler {
324
292
  public async request<T = EventPayload>(
325
293
  sender: string,
326
294
  topic: string,
327
- data?: EventPayload
295
+ data?: EventPayload,
328
296
  ): Promise<EventBusMessage<T>> {
329
297
  if (!this.validateTopic(topic)) {
330
298
  this.logAndThrowError(true, `Invalid topic: ` + topic);
@@ -335,10 +303,8 @@ export class EventBusHandler {
335
303
  this.logIfDebug(`Requesting data from ` + topic, { event });
336
304
 
337
305
  return new Promise<EventBusMessage<T>>((resolve) => {
338
- this.responseResolvers.set(
339
- event.eventId,
340
- (value: EventBusMessage<unknown>) =>
341
- resolve(value as EventBusMessage<T>)
306
+ this.responseResolvers.set(event.eventId, (value: EventBusMessage<unknown>) =>
307
+ resolve(value as EventBusMessage<T>),
342
308
  );
343
309
  this.emitInternal(sender, topic, data || {}, event.eventId, true);
344
310
  });
@@ -354,9 +320,7 @@ export class EventBusHandler {
354
320
 
355
321
  // Find wildcard matches
356
322
  const wildcard = [...this.listeners.entries()]
357
- .filter(
358
- ([key]) => key.endsWith("*") && topic.startsWith(key.slice(0, -1))
359
- )
323
+ .filter(([key]) => key.endsWith('*') && topic.startsWith(key.slice(0, -1)))
360
324
  .flatMap(([_, handlers]) => [...handlers]);
361
325
  return new Set([...exact, ...wildcard]);
362
326
  }
@@ -368,29 +332,26 @@ export class EventBusHandler {
368
332
  */
369
333
  private validateTopic(topic: string): boolean {
370
334
  // Split event type into parts
371
- const parts = topic.split(".");
335
+ const parts = topic.split('.');
372
336
  const [plugin, area, action] = parts;
373
337
 
374
338
  if (parts.length !== 3) {
375
- if (parts.length === 1 && plugin === "*") {
339
+ if (parts.length === 1 && plugin === '*') {
376
340
  return true;
377
341
  }
378
- if (parts.length === 2 && plugin !== "*" && area === "*") {
342
+ if (parts.length === 2 && plugin !== '*' && area === '*') {
379
343
  return true;
380
344
  }
381
- this.logAndThrowError(
382
- false,
383
- `Event type must have 3 parts separated by dots. Received: ` + topic
384
- );
345
+ this.logAndThrowError(false, `Event type must have 3 parts separated by dots. Received: ` + topic);
385
346
  return false;
386
347
  }
387
348
 
388
- if (action === "*") {
349
+ if (action === '*') {
389
350
  return true;
390
351
  }
391
352
 
392
353
  // Validate action part
393
- const validActions = ["request", "create", "update", "delete", "trigger"];
354
+ const validActions = ['request', 'create', 'update', 'delete', 'trigger'];
394
355
 
395
356
  if (validActions.some((a) => action.startsWith(a))) {
396
357
  return true;
@@ -398,10 +359,7 @@ export class EventBusHandler {
398
359
 
399
360
  this.logAndThrowError(
400
361
  false,
401
- `Invalid event topic name. The action: ` +
402
- action +
403
- ". Must be or start with one of: " +
404
- validActions.join(", ")
362
+ `Invalid event topic name. The action: ` + action + '. Must be or start with one of: ' + validActions.join(', '),
405
363
  );
406
364
  return false;
407
365
  }
@@ -412,10 +370,7 @@ export class EventBusHandler {
412
370
  }
413
371
  }
414
372
 
415
- private logAndThrowError(
416
- throwError: boolean,
417
- ...args: (string | EventPayload)[]
418
- ) {
373
+ private logAndThrowError(throwError: boolean, ...args: (string | EventPayload)[]) {
419
374
  const message = `[${this.evName}] ` + args[0];
420
375
  console.error(message, ...args.slice(1));
421
376
  if (throwError) {
@@ -1,13 +1,13 @@
1
1
  // whole configuration of a plugin (from the database)
2
- export type Plugin<T extends {} = {}> = Omit<RimoriPluginConfig<T>, 'context_menu_actions'> & {
2
+ export type Plugin<T extends object = object> = Omit<RimoriPluginConfig<T>, 'context_menu_actions'> & {
3
3
  version: string;
4
4
  endpoint: string;
5
5
  assetEndpoint: string;
6
6
  context_menu_actions: MenuEntry[];
7
- release_channel: "alpha" | "beta" | "stable";
8
- }
7
+ release_channel: 'alpha' | 'beta' | 'stable';
8
+ };
9
9
 
10
- export type ActivePlugin = Plugin<{ active?: boolean }>
10
+ export type ActivePlugin = Plugin<{ active?: boolean }>;
11
11
 
12
12
  // browsable page of a plugin
13
13
  export interface PluginPage {
@@ -17,13 +17,22 @@ export interface PluginPage {
17
17
  // Whether the page should be shown in the navbar
18
18
  show: boolean;
19
19
  description: string;
20
- root: "vocabulary" | "grammar" | "reading" | "listening" | "watching" | "writing" | "speaking" | "other" | "community";
20
+ root:
21
+ | 'vocabulary'
22
+ | 'grammar'
23
+ | 'reading'
24
+ | 'listening'
25
+ | 'watching'
26
+ | 'writing'
27
+ | 'speaking'
28
+ | 'other'
29
+ | 'community';
21
30
  // The actions that can be triggered in the plugin
22
31
  // The key is the action key. The other entries are additional properties needed when triggering the action
23
32
  action?: {
24
33
  key: string;
25
34
  parameters: ObjectTool;
26
- }
35
+ };
27
36
  }
28
37
 
29
38
  // a sidebar page of a plugin
@@ -65,14 +74,14 @@ export interface ContextMenuAction {
65
74
  // id of the plugin that the action belongs to
66
75
  plugin_id: string;
67
76
  // key of the action. Used to know which action to trigger when clicking on the context menu
68
- action_key: string
77
+ action_key: string;
69
78
  }
70
79
 
71
80
  /**
72
81
  * Rimori plugin structure representing the complete configuration
73
82
  * of a Rimori plugin with all metadata and configuration options.
74
83
  */
75
- export interface RimoriPluginConfig<T extends {} = {}> {
84
+ export interface RimoriPluginConfig<T extends object = object> {
76
85
  id: string;
77
86
  /**
78
87
  * Basic information about the plugin including branding and core details.
@@ -86,7 +95,7 @@ export interface RimoriPluginConfig<T extends {} = {}> {
86
95
  logo: string;
87
96
  /** Optional website URL for the plugin's homepage or link to plugins owner for contributions */
88
97
  website?: string;
89
- }
98
+ };
90
99
  /**
91
100
  * Configuration for different types of pages.
92
101
  */
@@ -101,11 +110,11 @@ export interface RimoriPluginConfig<T extends {} = {}> {
101
110
  settings?: string;
102
111
  /** Optional array of event topics the plugin pages can listen to for cross-plugin communication */
103
112
  topics?: string[];
104
- }
113
+ };
105
114
  /**
106
115
  * Context menu actions that the plugin registers to appear in right-click menus throughout the application.
107
116
  */
108
- context_menu_actions: Omit<MenuEntry, "plugin_id">[];
117
+ context_menu_actions: Omit<MenuEntry, 'plugin_id'>[];
109
118
  /**
110
119
  * Documentation paths for different types of plugin documentation.
111
120
  */
@@ -116,7 +125,7 @@ export interface RimoriPluginConfig<T extends {} = {}> {
116
125
  user_path: string;
117
126
  /** Path to developer documentation for plugin development */
118
127
  developer_path: string;
119
- }
128
+ };
120
129
  /**
121
130
  * Configuration for the plugin's web worker if it uses background processing or exposes actions to other plugins.
122
131
  */
@@ -136,7 +145,7 @@ export interface Tool {
136
145
  parameters: {
137
146
  name: string;
138
147
  description: string;
139
- type: "string" | "number" | "boolean";
148
+ type: 'string' | 'number' | 'boolean';
140
149
  }[];
141
150
  execute?: (args: Record<string, any>) => Promise<unknown> | unknown | void;
142
151
  }
@@ -145,7 +154,7 @@ export interface Tool {
145
154
  * The tool definition structure is used for LLM function calling and plugin action parameters.
146
155
  * It defines the schema for tools that can be used by Language Learning Models (LLMs)
147
156
  * and plugin actions.
148
- *
157
+ *
149
158
  * @example
150
159
  * ```typescript
151
160
  * const flashcardTool: Tool = {
@@ -155,13 +164,13 @@ export interface Tool {
155
164
  * description: 'Number of flashcards to practice'
156
165
  * },
157
166
  * deck: {
158
- * type: 'string',
167
+ * type: 'string',
159
168
  * enum: ['latest', 'random', 'oldest', 'mix', 'best_known'],
160
169
  * description: 'Type of deck to practice'
161
170
  * }
162
171
  * };
163
172
  * ```
164
- *
173
+ *
165
174
  */
166
175
  export type ObjectTool = {
167
176
  [key: string]: ToolParameter;
@@ -188,15 +197,15 @@ interface ToolParameter {
188
197
  * Supports primitive types, nested objects for complex data structures,
189
198
  * and arrays of objects for collections. The tuple notation [{}] indicates
190
199
  * arrays of objects with a specific structure.
191
- *
200
+ *
192
201
  * @example Primitive: 'string' | 'number' | 'boolean'
193
202
  * @example Nested object: { name: { type: 'string' }, age: { type: 'number' } }
194
203
  * @example Array of objects: [{ id: { type: 'string' }, value: { type: 'number' } }]
195
204
  */
196
205
  type ToolParameterType =
197
206
  | PrimitiveType
198
- | { [key: string]: ToolParameter } // for nested objects
199
- | [{ [key: string]: ToolParameter }]; // for arrays of objects (notice the tuple type)
207
+ | { [key: string]: ToolParameter } // for nested objects
208
+ | [{ [key: string]: ToolParameter }]; // for arrays of objects (notice the tuple type)
200
209
 
201
210
  /**
202
211
  * Primitive data types supported by the LLM tool system.