@rimori/client 1.4.10 → 2.1.0

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.
Files changed (136) hide show
  1. package/README.md +140 -1171
  2. package/dist/{core/controller → controller}/AIController.d.ts +1 -1
  3. package/dist/{core/controller → controller}/AIController.js +2 -2
  4. package/dist/{plugin/AccomplishmentHandler.d.ts → controller/AccomplishmentController.d.ts} +1 -1
  5. package/dist/{plugin/AccomplishmentHandler.js → controller/AccomplishmentController.js} +1 -1
  6. package/dist/{core/controller → controller}/ExerciseController.d.ts +8 -6
  7. package/dist/{core/controller → controller}/ExerciseController.js +10 -9
  8. package/dist/{core/controller → controller}/ObjectController.d.ts +1 -1
  9. package/dist/{core/controller → controller}/ObjectController.js +1 -1
  10. package/dist/{core/controller → controller}/SettingsController.d.ts +2 -2
  11. package/dist/{core/controller → controller}/SharedContentController.d.ts +1 -1
  12. package/dist/{core/controller → controller}/VoiceController.d.ts +1 -1
  13. package/dist/index.d.ts +14 -8
  14. package/dist/index.js +7 -7
  15. package/dist/plugin/{PluginController.d.ts → CommunicationHandler.d.ts} +4 -7
  16. package/dist/plugin/{PluginController.js → CommunicationHandler.js} +19 -27
  17. package/dist/plugin/RimoriClient.d.ts +67 -68
  18. package/dist/plugin/RimoriClient.js +101 -43
  19. package/dist/worker/WorkerSetup.js +3 -3
  20. package/example/docs/devdocs.md +1 -1
  21. package/package.json +5 -26
  22. package/src/{core/controller → controller}/AIController.ts +3 -3
  23. package/src/{plugin/AccomplishmentHandler.ts → controller/AccomplishmentController.ts} +1 -1
  24. package/src/{core/controller → controller}/ExerciseController.ts +14 -11
  25. package/src/{core/controller → controller}/ObjectController.ts +2 -2
  26. package/src/{core/controller → controller}/SettingsController.ts +2 -2
  27. package/src/{core/controller → controller}/SharedContentController.ts +1 -1
  28. package/src/{core/controller → controller}/VoiceController.ts +2 -2
  29. package/src/fromRimori/readme.md +1 -1
  30. package/src/index.ts +14 -8
  31. package/src/plugin/{PluginController.ts → CommunicationHandler.ts} +24 -36
  32. package/src/plugin/RimoriClient.ts +127 -118
  33. package/src/worker/WorkerSetup.ts +6 -4
  34. package/tsconfig.json +5 -2
  35. package/dist/cli/scripts/release/release-translation-upload.d.ts +0 -6
  36. package/dist/cli/scripts/release/release-translation-upload.js +0 -87
  37. package/dist/components/CRUDModal.d.ts +0 -17
  38. package/dist/components/CRUDModal.js +0 -24
  39. package/dist/components/MarkdownEditor.d.ts +0 -8
  40. package/dist/components/MarkdownEditor.js +0 -48
  41. package/dist/components/Spinner.d.ts +0 -8
  42. package/dist/components/Spinner.js +0 -4
  43. package/dist/components/ai/Assistant.d.ts +0 -9
  44. package/dist/components/ai/Assistant.js +0 -58
  45. package/dist/components/ai/Avatar.d.ts +0 -14
  46. package/dist/components/ai/Avatar.js +0 -59
  47. package/dist/components/ai/EmbeddedAssistent/AudioInputField.d.ts +0 -7
  48. package/dist/components/ai/EmbeddedAssistent/AudioInputField.js +0 -37
  49. package/dist/components/ai/EmbeddedAssistent/CircleAudioAvatar.d.ts +0 -8
  50. package/dist/components/ai/EmbeddedAssistent/CircleAudioAvatar.js +0 -79
  51. package/dist/components/ai/EmbeddedAssistent/TTS/MessageSender.d.ts +0 -19
  52. package/dist/components/ai/EmbeddedAssistent/TTS/MessageSender.js +0 -91
  53. package/dist/components/ai/EmbeddedAssistent/TTS/Player.d.ts +0 -27
  54. package/dist/components/ai/EmbeddedAssistent/TTS/Player.js +0 -185
  55. package/dist/components/ai/EmbeddedAssistent/VoiceRecoder.d.ts +0 -11
  56. package/dist/components/ai/EmbeddedAssistent/VoiceRecoder.js +0 -95
  57. package/dist/components/ai/utils.d.ts +0 -6
  58. package/dist/components/ai/utils.js +0 -13
  59. package/dist/components/audio/Playbutton.d.ts +0 -15
  60. package/dist/components/audio/Playbutton.js +0 -80
  61. package/dist/components/components/ContextMenu.d.ts +0 -10
  62. package/dist/components/components/ContextMenu.js +0 -135
  63. package/dist/components.d.ts +0 -10
  64. package/dist/components.js +0 -11
  65. package/dist/core/controller/EnhancedUserInfo.d.ts +0 -0
  66. package/dist/core/controller/EnhancedUserInfo.js +0 -1
  67. package/dist/core/core.d.ts +0 -14
  68. package/dist/core/core.js +0 -7
  69. package/dist/hooks/I18nHooks.d.ts +0 -11
  70. package/dist/hooks/I18nHooks.js +0 -25
  71. package/dist/hooks/UseChatHook.d.ts +0 -10
  72. package/dist/hooks/UseChatHook.js +0 -29
  73. package/dist/i18n/I18nHooks.d.ts +0 -11
  74. package/dist/i18n/I18nHooks.js +0 -25
  75. package/dist/i18n/Translator.d.ts +0 -43
  76. package/dist/i18n/Translator.js +0 -118
  77. package/dist/i18n/config.d.ts +0 -7
  78. package/dist/i18n/config.js +0 -20
  79. package/dist/i18n/createI18nInstance.d.ts +0 -7
  80. package/dist/i18n/createI18nInstance.js +0 -31
  81. package/dist/i18n/hooks.d.ts +0 -11
  82. package/dist/i18n/hooks.js +0 -25
  83. package/dist/i18n/index.d.ts +0 -4
  84. package/dist/i18n/index.js +0 -4
  85. package/dist/i18n/types.d.ts +0 -7
  86. package/dist/i18n/types.js +0 -1
  87. package/dist/i18n/useRimoriI18n.d.ts +0 -11
  88. package/dist/i18n/useRimoriI18n.js +0 -41
  89. package/dist/plugin/ThemeSetter.d.ts +0 -2
  90. package/dist/plugin/ThemeSetter.js +0 -19
  91. package/dist/plugin/Translator.d.ts +0 -38
  92. package/dist/plugin/Translator.js +0 -101
  93. package/dist/providers/PluginProvider.d.ts +0 -12
  94. package/dist/providers/PluginProvider.js +0 -152
  95. package/dist/style.css +0 -110
  96. package/dist/style.css.map +0 -1
  97. package/dist/utils/Language.d.ts +0 -67
  98. package/dist/utils/Language.js +0 -69
  99. package/dist/utils/LanguageClass.d.ts +0 -36
  100. package/dist/utils/LanguageClass.example.d.ts +0 -0
  101. package/dist/utils/LanguageClass.example.js +0 -1
  102. package/dist/utils/LanguageClass.js +0 -50
  103. package/dist/utils/LanguageClass.test.d.ts +0 -0
  104. package/dist/utils/LanguageClass.test.js +0 -1
  105. package/dist/utils/PluginUtils.d.ts +0 -2
  106. package/dist/utils/PluginUtils.js +0 -23
  107. package/src/components/CRUDModal.tsx +0 -75
  108. package/src/components/MarkdownEditor.tsx +0 -144
  109. package/src/components/Spinner.tsx +0 -29
  110. package/src/components/ai/Assistant.tsx +0 -96
  111. package/src/components/ai/Avatar.tsx +0 -99
  112. package/src/components/ai/EmbeddedAssistent/AudioInputField.tsx +0 -73
  113. package/src/components/ai/EmbeddedAssistent/CircleAudioAvatar.tsx +0 -107
  114. package/src/components/ai/EmbeddedAssistent/TTS/MessageSender.ts +0 -96
  115. package/src/components/ai/EmbeddedAssistent/TTS/Player.ts +0 -197
  116. package/src/components/ai/EmbeddedAssistent/VoiceRecoder.tsx +0 -129
  117. package/src/components/ai/utils.ts +0 -21
  118. package/src/components/audio/Playbutton.tsx +0 -126
  119. package/src/components/components/ContextMenu.tsx +0 -179
  120. package/src/components.ts +0 -11
  121. package/src/core/core.ts +0 -15
  122. package/src/hooks/I18nHooks.ts +0 -33
  123. package/src/hooks/UseChatHook.ts +0 -38
  124. package/src/plugin/ThemeSetter.ts +0 -23
  125. package/src/providers/PluginProvider.tsx +0 -209
  126. package/src/style.scss +0 -136
  127. package/src/utils/PluginUtils.ts +0 -22
  128. /package/dist/{plugin → controller}/AudioController.d.ts +0 -0
  129. /package/dist/{plugin → controller}/AudioController.js +0 -0
  130. /package/dist/{core/controller → controller}/SettingsController.js +0 -0
  131. /package/dist/{core/controller → controller}/SharedContentController.js +0 -0
  132. /package/dist/{plugin → controller}/TranslationController.d.ts +0 -0
  133. /package/dist/{plugin → controller}/TranslationController.js +0 -0
  134. /package/dist/{core/controller → controller}/VoiceController.js +0 -0
  135. /package/src/{plugin → controller}/AudioController.ts +0 -0
  136. /package/src/{plugin → controller}/TranslationController.ts +0 -0
@@ -7,17 +7,19 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
7
7
  step((generator = generator.apply(thisArg, _arguments || [])).next());
8
8
  });
9
9
  };
10
- import { generateText, streamChatGPT } from '../core/controller/AIController';
11
- import { generateObject } from '../core/controller/ObjectController';
12
- import { SettingsController } from '../core/controller/SettingsController';
13
- import { SharedContentController, } from '../core/controller/SharedContentController';
14
- import { getSTTResponse, getTTSResponse } from '../core/controller/VoiceController';
15
- import { ExerciseController } from '../core/controller/ExerciseController';
10
+ import { generateText, streamChatGPT } from '../controller/AIController';
11
+ import { generateObject } from '../controller/ObjectController';
12
+ import { SettingsController } from '../controller/SettingsController';
13
+ import { SharedContentController, } from '../controller/SharedContentController';
14
+ import { getSTTResponse, getTTSResponse } from '../controller/VoiceController';
15
+ import { ExerciseController } from '../controller/ExerciseController';
16
16
  import { EventBus } from '../fromRimori/EventBus';
17
- import { AccomplishmentHandler } from './AccomplishmentHandler';
18
- import { Translator } from './TranslationController';
17
+ import { AccomplishmentController } from '../controller/AccomplishmentController';
18
+ import { RimoriCommunicationHandler } from './CommunicationHandler';
19
+ import { Translator } from '../controller/TranslationController';
20
+ import { Logger } from './Logger';
19
21
  export class RimoriClient {
20
- constructor(supabase, info, pluginController) {
22
+ constructor(controller, supabase, info) {
21
23
  this.event = {
22
24
  /**
23
25
  * Emit an event to Rimori or a plugin.
@@ -94,10 +96,14 @@ export class RimoriClient {
94
96
  emitSidebarAction: (pluginId, actionKey, text) => {
95
97
  this.event.emit('global.sidebar.triggerAction', { plugin_id: pluginId, action_key: actionKey, text });
96
98
  },
97
- onMainPanelAction: (callback) => {
99
+ onMainPanelAction: (callback, actionsToListen = []) => {
98
100
  // this needs to be a emit and on because the main panel action is triggered by the user and not by the plugin
99
101
  this.event.emit('action.requestMain');
100
- this.event.on('action.requestMain', ({ data }) => callback(data));
102
+ this.event.on('action.requestMain', ({ data }) => {
103
+ if (actionsToListen.includes(data.action)) {
104
+ callback(data);
105
+ }
106
+ });
101
107
  },
102
108
  };
103
109
  this.navigation = {
@@ -233,7 +239,9 @@ export class RimoriClient {
233
239
  * @returns Created exercise object.
234
240
  */
235
241
  add: (params) => __awaiter(this, void 0, void 0, function* () {
236
- return this.exerciseController.addExercise(params);
242
+ const token = yield this.pluginController.getToken();
243
+ const backendUrl = this.pluginController.getBackendUrl();
244
+ return this.exerciseController.addExercise(token, backendUrl, params);
237
245
  }),
238
246
  /**
239
247
  * Deletes an exercise via the backend API.
@@ -241,37 +249,52 @@ export class RimoriClient {
241
249
  * @returns Success status.
242
250
  */
243
251
  delete: (id) => __awaiter(this, void 0, void 0, function* () {
244
- return this.exerciseController.deleteExercise(id);
252
+ const token = yield this.pluginController.getToken();
253
+ const backendUrl = this.pluginController.getBackendUrl();
254
+ return this.exerciseController.deleteExercise(token, backendUrl, id);
245
255
  }),
246
256
  };
247
257
  this.rimoriInfo = info;
248
258
  this.superbase = supabase;
249
- this.pluginController = pluginController;
259
+ this.pluginController = controller;
260
+ this.exerciseController = new ExerciseController(supabase);
261
+ this.accomplishmentHandler = new AccomplishmentController(info.pluginId);
250
262
  this.settingsController = new SettingsController(supabase, info.pluginId, info.guild);
251
- this.sharedContentController = new SharedContentController(this.superbase, this);
252
- this.exerciseController = new ExerciseController(supabase, pluginController);
253
- this.accomplishmentHandler = new AccomplishmentHandler(info.pluginId);
263
+ this.sharedContentController = new SharedContentController(supabase, this);
254
264
  this.translator = new Translator(info.profile.mother_tongue.code);
255
- this.from = this.from.bind(this);
256
- this.getTableName = this.getTableName.bind(this);
257
- this.db = {
258
- from: this.from,
259
- // storage: this.superbase.storage,
260
- // functions: this.superbase.functions,
261
- tablePrefix: info.tablePrefix,
262
- getTableName: this.getTableName,
263
- };
264
- this.plugin = {
265
- pluginId: info.pluginId,
265
+ //only init logger in workers and on main plugin pages
266
+ if (this.getQueryParam('applicationMode') !== 'sidebar') {
267
+ Logger.getInstance(this);
268
+ }
269
+ }
270
+ get plugin() {
271
+ return {
272
+ pluginId: this.rimoriInfo.pluginId,
273
+ /**
274
+ * Set the settings for the plugin.
275
+ * @param settings The settings to set.
276
+ */
266
277
  setSettings: (settings) => __awaiter(this, void 0, void 0, function* () {
267
278
  yield this.settingsController.setSettings(settings);
268
279
  }),
280
+ /**
281
+ * Get the settings for the plugin. T can be any type of settings, UserSettings or SystemSettings.
282
+ * @param defaultSettings The default settings to use if no settings are found.
283
+ * @param genericSettings The type of settings to get.
284
+ * @returns The settings for the plugin.
285
+ */
269
286
  getSettings: (defaultSettings) => __awaiter(this, void 0, void 0, function* () {
270
287
  return yield this.settingsController.getSettings(defaultSettings);
271
288
  }),
272
289
  getUserInfo: () => {
273
290
  return this.rimoriInfo.profile;
274
291
  },
292
+ /**
293
+ * Retrieves information about plugins, including:
294
+ * - All installed plugins
295
+ * - The currently active plugin in the main panel
296
+ * - The currently active plugin in the side panel
297
+ */
275
298
  getPluginInfo: () => {
276
299
  return {
277
300
  installedPlugins: this.rimoriInfo.installedPlugins,
@@ -279,12 +302,51 @@ export class RimoriClient {
279
302
  sidePanelPlugin: this.rimoriInfo.sidePanelPlugin,
280
303
  };
281
304
  },
305
+ /**
306
+ * Get the translator for the plugin.
307
+ * @returns The translator for the plugin.
308
+ */
282
309
  getTranslator: () => __awaiter(this, void 0, void 0, function* () {
283
310
  yield this.translator.initialize();
284
311
  return this.translator;
285
312
  }),
286
313
  };
287
314
  }
315
+ get db() {
316
+ return {
317
+ // private from<
318
+ // TableName extends string & keyof GenericSchema['Tables'],
319
+ // Table extends GenericSchema['Tables'][TableName],
320
+ // >(relation: TableName): PostgrestQueryBuilder<GenericSchema, Table, TableName>;
321
+ // private from<ViewName extends string & keyof GenericSchema['Views'], View extends GenericSchema['Views'][ViewName]>(
322
+ // relation: ViewName,
323
+ // ): PostgrestQueryBuilder<GenericSchema, View, ViewName>;
324
+ from: (relation) => {
325
+ return this.superbase.from(this.db.getTableName(relation));
326
+ },
327
+ // storage: this.superbase.storage,
328
+ // functions: this.superbase.functions,
329
+ /**
330
+ * The table prefix for of database tables of the plugin.
331
+ */
332
+ tablePrefix: this.rimoriInfo.tablePrefix,
333
+ /**
334
+ * Get the table name for a given plugin table.
335
+ * Internally all tables are prefixed with the plugin id. This function is used to get the correct table name for a given public table.
336
+ * @param table The plugin table name to get the full table name for.
337
+ * @returns The full table name.
338
+ */
339
+ getTableName: (table) => {
340
+ if (/[A-Z]/.test(table)) {
341
+ throw new Error('Table name cannot include uppercase letters. Please use snake_case for table names.');
342
+ }
343
+ if (table.startsWith('global_')) {
344
+ return table.replace('global_', '');
345
+ }
346
+ return this.db.tablePrefix + '_' + table;
347
+ },
348
+ };
349
+ }
288
350
  /**
289
351
  * Get a query parameter value that was passed via MessageChannel
290
352
  * @param key The query parameter key
@@ -293,25 +355,21 @@ export class RimoriClient {
293
355
  getQueryParam(key) {
294
356
  return this.pluginController.getQueryParam(key);
295
357
  }
296
- static getInstance(pluginController) {
358
+ static getInstance(pluginId) {
297
359
  return __awaiter(this, void 0, void 0, function* () {
298
360
  if (!RimoriClient.instance) {
299
- const client = yield pluginController.getClient();
300
- RimoriClient.instance = new RimoriClient(client.supabase, client.info, pluginController);
361
+ if (!pluginId)
362
+ throw new Error('Plugin ID is required');
363
+ const controller = new RimoriCommunicationHandler(pluginId, false);
364
+ if (typeof WorkerGlobalScope === 'undefined') {
365
+ // In standalone mode, use URL fallback. In iframe mode, theme will be set after MessageChannel init
366
+ // setTheme();
367
+ // await StandaloneClient.initListeners(pluginId);
368
+ }
369
+ const client = yield controller.getClient();
370
+ RimoriClient.instance = new RimoriClient(controller, client.supabase, client.info);
301
371
  }
302
372
  return RimoriClient.instance;
303
373
  });
304
374
  }
305
- from(relation) {
306
- return this.superbase.from(this.getTableName(relation));
307
- }
308
- getTableName(table) {
309
- if (/[A-Z]/.test(table)) {
310
- throw new Error('Table name cannot include uppercase letters. Please use snake_case for table names.');
311
- }
312
- if (table.startsWith('global_')) {
313
- return table.replace('global_', '');
314
- }
315
- return this.db.tablePrefix + '_' + table;
316
- }
317
375
  }
@@ -7,8 +7,8 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
7
7
  step((generator = generator.apply(thisArg, _arguments || [])).next());
8
8
  });
9
9
  };
10
+ import { RimoriClient } from '../plugin/RimoriClient';
10
11
  import { EventBusHandler } from '../fromRimori/EventBus';
11
- import { PluginController } from '../plugin/PluginController';
12
12
  /**
13
13
  * Sets up the web worker for the plugin to be able receive and send messages to Rimori.
14
14
  * @param pluginId - The id of the plugin to setup the worker for.
@@ -28,10 +28,10 @@ export function setupWorker(pluginId, init) {
28
28
  // Assign the mock to globalThis.
29
29
  Object.assign(globalThis, { window: mockWindow });
30
30
  EventBusHandler.getInstance('Worker EventBus');
31
- const rimoriClient = yield PluginController.getInstance(pluginId);
31
+ const rimoriClient = yield RimoriClient.getInstance(pluginId);
32
32
  console.debug('[Worker] RimoriClient initialized.');
33
33
  yield init(rimoriClient);
34
34
  console.debug('[Worker] Worker initialized.');
35
- self.postMessage({ type: 'rimori:acknowledged', pluginId: pluginId });
35
+ rimoriClient.event.emit('self.rimori.triggerInitFinished');
36
36
  });
37
37
  }
@@ -42,7 +42,7 @@ plugin.event.emit('pl123456789.flashcard.createLangCard', {
42
42
 
43
43
  ```javascript
44
44
  // Request word translation
45
- const translation = await plugin.event.request('pl123456789.lookup.requestBasic', {
45
+ const translation = await plugin.event.request('pl123456789.lookup.request', {
46
46
  word: 'laufen',
47
47
  language: 'de', // optional
48
48
  });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@rimori/client",
3
- "version": "1.4.10",
3
+ "version": "2.1.0",
4
4
  "main": "dist/index.js",
5
5
  "types": "dist/index.d.ts",
6
6
  "bin": {
@@ -11,39 +11,20 @@
11
11
  "exports": {
12
12
  ".": {
13
13
  "types": "./dist/index.d.ts",
14
+ "import": "./dist/index.js",
14
15
  "default": "./dist/index.js"
15
- },
16
- "./core": {
17
- "types": "./dist/core/core.d.ts",
18
- "default": "./dist/core/core.js"
19
- },
20
- "./components": {
21
- "types": "./dist/components.d.ts",
22
- "default": "./dist/components.js"
23
16
  }
24
17
  },
25
18
  "scripts": {
26
- "build": "tsc && sass src/style.scss:dist/style.css",
19
+ "build": "tsc",
27
20
  "dev": "tsc -w --preserveWatchOutput",
28
- "css-dev": "sass --watch src/style.scss:dist/style.css",
29
21
  "lint": "eslint . --fix",
30
22
  "format": "prettier --write ."
31
23
  },
32
- "peerDependencies": {
33
- "react": "^18.0.0",
34
- "react-dom": "^18.0.0"
35
- },
36
24
  "dependencies": {
37
25
  "@supabase/supabase-js": "2.49.4",
38
- "@tiptap/react": "2.10.3",
39
- "@tiptap/starter-kit": "2.10.3",
40
26
  "dotenv": "16.5.0",
41
- "html2canvas": "1.4.1",
42
- "i18next": "^25.6.0",
43
- "prettier": "^3.6.2",
44
- "react-icons": "5.4.0",
45
- "react-markdown": "10.1.0",
46
- "tiptap-markdown": "0.8.10"
27
+ "i18next": "^25.6.0"
47
28
  },
48
29
  "devDependencies": {
49
30
  "@eslint/js": "^9.37.0",
@@ -51,10 +32,8 @@
51
32
  "eslint-plugin-prettier": "^5.5.4",
52
33
  "eslint-plugin-react-hooks": "^7.0.0",
53
34
  "eslint-plugin-react-refresh": "^0.4.23",
54
- "form-data": "^4.0.2",
55
35
  "globals": "^16.4.0",
56
- "node-fetch": "^3.3.2",
57
- "sass": "^1.82.0",
36
+ "prettier": "^3.6.2",
58
37
  "typescript": "^5.7.2",
59
38
  "typescript-eslint": "^8.46.0"
60
39
  }
@@ -1,4 +1,4 @@
1
- import { Tool } from '../../fromRimori/PluginTypes';
1
+ import { Tool } from '../fromRimori/PluginTypes';
2
2
 
3
3
  export interface ToolInvocation {
4
4
  toolCallId: string;
@@ -38,7 +38,7 @@ export async function streamChatGPT(
38
38
  token: string,
39
39
  ) {
40
40
  const messageId = Math.random().toString(36).substring(3);
41
- let currentMessages: Message[] = [...messages];
41
+ const currentMessages: Message[] = [...messages];
42
42
 
43
43
  console.log('Starting streamChatGPT with:', {
44
44
  messageId,
@@ -71,7 +71,7 @@ export async function streamChatGPT(
71
71
 
72
72
  let content = '';
73
73
  let done = false;
74
- let toolInvocations: { toolCallId: string; toolName: string; args: any }[] = [];
74
+ const toolInvocations: { toolCallId: string; toolName: string; args: any }[] = [];
75
75
  let currentTextId = '';
76
76
  let isToolCallMode = false;
77
77
  let buffer = ''; // Buffer for incomplete chunks
@@ -36,7 +36,7 @@ export interface MacroAccomplishmentPayload extends BaseAccomplishmentPayload {
36
36
 
37
37
  export type AccomplishmentPayload = MicroAccomplishmentPayload | MacroAccomplishmentPayload;
38
38
 
39
- export class AccomplishmentHandler {
39
+ export class AccomplishmentController {
40
40
  private pluginId: string;
41
41
 
42
42
  public constructor(pluginId: string) {
@@ -1,5 +1,4 @@
1
1
  import { SupabaseClient } from '@supabase/supabase-js';
2
- import { PluginController } from '../../plugin/PluginController';
3
2
 
4
3
  export type TriggerAction = { action_key: string } & Record<string, string | number | boolean>;
5
4
 
@@ -28,11 +27,9 @@ export interface Exercise {
28
27
 
29
28
  export class ExerciseController {
30
29
  private supabase: SupabaseClient;
31
- private pluginController: PluginController;
32
30
 
33
- constructor(supabase: SupabaseClient, pluginController: PluginController) {
31
+ constructor(supabase: SupabaseClient) {
34
32
  this.supabase = supabase;
35
- this.pluginController = pluginController;
36
33
  }
37
34
 
38
35
  /**
@@ -52,12 +49,13 @@ export class ExerciseController {
52
49
 
53
50
  /**
54
51
  * Creates a new exercise via the backend API.
52
+ * @param token The token to use for authentication.
53
+ * @param backendUrl The URL of the backend API.
55
54
  * @param params Exercise creation parameters.
56
55
  * @returns Created exercise object.
57
56
  */
58
- public async addExercise(params: CreateExerciseParams): Promise<Exercise> {
59
- const token = await this.pluginController.getToken();
60
- const response = await fetch(`${this.pluginController.getBackendUrl()}/exercises`, {
57
+ public async addExercise(token: string, backendUrl: string, params: CreateExerciseParams): Promise<Exercise> {
58
+ const response = await fetch(`${backendUrl}/exercises`, {
61
59
  method: 'POST',
62
60
  headers: {
63
61
  'Content-Type': 'application/json',
@@ -76,12 +74,17 @@ export class ExerciseController {
76
74
 
77
75
  /**
78
76
  * Deletes an exercise via the backend API.
79
- * @param id The exercise ID to delete.
77
+ * @param token The token to use for authentication.
78
+ * @param backendUrl The URL of the backend API.
79
+ * @param exerciseId The exercise ID to delete.
80
80
  * @returns Success status.
81
81
  */
82
- public async deleteExercise(id: string): Promise<{ success: boolean; message: string }> {
83
- const token = await this.pluginController.getToken();
84
- const response = await fetch(`${this.pluginController.getBackendUrl()}/exercises/${id}`, {
82
+ public async deleteExercise(
83
+ token: string,
84
+ backendUrl: string,
85
+ id: string,
86
+ ): Promise<{ success: boolean; message: string }> {
87
+ const response = await fetch(`${backendUrl}/exercises/${id}`, {
85
88
  method: 'DELETE',
86
89
  headers: {
87
90
  Authorization: `Bearer ${token}`,
@@ -41,7 +41,7 @@ export interface ObjectRequest {
41
41
  instructions: string;
42
42
  }
43
43
 
44
- export async function generateObject(backendUrl: string, request: ObjectRequest, token: string) {
44
+ export async function generateObject<T = any>(backendUrl: string, request: ObjectRequest, token: string): Promise<T> {
45
45
  return await fetch(`${backendUrl}/ai/llm-object`, {
46
46
  method: 'POST',
47
47
  body: JSON.stringify({
@@ -85,7 +85,7 @@ export async function streamObject(
85
85
 
86
86
  let content = '';
87
87
  let done = false;
88
- let toolInvocations: any[] = [];
88
+ const toolInvocations: any[] = [];
89
89
  while (!done) {
90
90
  const { value } = await reader.read();
91
91
 
@@ -1,6 +1,6 @@
1
1
  import { SupabaseClient } from '@supabase/supabase-js';
2
- import { LanguageLevel } from '../../utils/difficultyConverter';
3
- import { Guild } from '../core';
2
+ import { LanguageLevel } from '../utils/difficultyConverter';
3
+ import { Guild } from '../plugin/CommunicationHandler';
4
4
 
5
5
  export interface Buddy {
6
6
  id: string;
@@ -1,5 +1,5 @@
1
1
  import { SupabaseClient } from '@supabase/supabase-js';
2
- import { RimoriClient } from '../../plugin/RimoriClient';
2
+ import { RimoriClient } from '../plugin/RimoriClient';
3
3
  import { ObjectRequest } from './ObjectController';
4
4
 
5
5
  export interface SharedContentObjectRequest extends ObjectRequest {
@@ -1,4 +1,4 @@
1
- export async function getSTTResponse(backendUrl: string, audio: Blob, token: string) {
1
+ export async function getSTTResponse(backendUrl: string, audio: Blob, token: string): Promise<string> {
2
2
  const formData = new FormData();
3
3
  formData.append('file', audio);
4
4
 
@@ -14,7 +14,7 @@ export async function getSTTResponse(backendUrl: string, audio: Blob, token: str
14
14
  });
15
15
  }
16
16
 
17
- export async function getTTSResponse(backendUrl: string, request: TTSRequest, token: string) {
17
+ export async function getTTSResponse(backendUrl: string, request: TTSRequest, token: string): Promise<Blob> {
18
18
  return await fetch(`${backendUrl}/voice/tts`, {
19
19
  method: 'POST',
20
20
  headers: {
@@ -1,2 +1,2 @@
1
- Files inside this folder are copied from Rimori and should not be changed.
1
+ Files inside this folder are copied from Rimori main repository and should not be changed.
2
2
  If change is needed adapt it in Rimori and copy the file then over.
package/src/index.ts CHANGED
@@ -1,12 +1,18 @@
1
1
  // Re-export everything
2
- export * from './components';
3
- export * from './hooks/UseChatHook';
4
- export * from './plugin/PluginController';
5
- export * from './providers/PluginProvider';
2
+ export * from './plugin/CommunicationHandler';
6
3
  export * from './cli/types/DatabaseTypes';
7
4
  export * from './utils/difficultyConverter';
8
- export * from './utils/PluginUtils';
9
5
  export * from './fromRimori/PluginTypes';
10
- export { FirstMessages } from './components/ai/utils';
11
- export { AudioController } from './plugin/AudioController';
12
- export { useTranslation } from './hooks/I18nHooks';
6
+ export * from './fromRimori/EventBus';
7
+ export * from './plugin/RimoriClient';
8
+ export * from './plugin/StandaloneClient';
9
+ export { setupWorker } from './worker/WorkerSetup';
10
+ export { AudioController } from './controller/AudioController';
11
+ export { Translator } from './controller/TranslationController';
12
+ export type { TOptions } from 'i18next';
13
+ export type { SharedContent, SharedContentObjectRequest } from './controller/SharedContentController';
14
+ export type { Exercise } from './controller/ExerciseController';
15
+ export type { UserInfo, Language } from './controller/SettingsController';
16
+ export type { Message, ToolInvocation } from './controller/AIController';
17
+ export type { TriggerAction } from './controller/ExerciseController';
18
+ export type { MacroAccomplishmentPayload, MicroAccomplishmentPayload } from './controller/AccomplishmentController';
@@ -1,11 +1,7 @@
1
1
  import { createClient, SupabaseClient } from '@supabase/supabase-js';
2
- import { UserInfo } from '../core/controller/SettingsController';
2
+ import { UserInfo } from '../controller/SettingsController';
3
3
  import { EventBus, EventBusMessage } from '../fromRimori/EventBus';
4
4
  import { ActivePlugin, Plugin } from '../fromRimori/PluginTypes';
5
- import { RimoriClient } from './RimoriClient';
6
- import { StandaloneClient } from './StandaloneClient';
7
- import { setTheme } from './ThemeSetter';
8
- import { Logger } from './Logger';
9
5
 
10
6
  // Add declaration for WorkerGlobalScope
11
7
  declare const WorkerGlobalScope: any;
@@ -31,35 +27,26 @@ export interface RimoriInfo {
31
27
  sidePanelPlugin?: ActivePlugin;
32
28
  }
33
29
 
34
- export class PluginController {
35
- private static client: RimoriClient;
36
- private static instance: PluginController;
30
+ export class RimoriCommunicationHandler {
37
31
  private port: MessagePort | null = null;
38
32
  private queryParams: Record<string, string> = {};
39
33
  private supabase: SupabaseClient | null = null;
40
34
  private rimoriInfo: RimoriInfo | null = null;
41
35
  private pluginId: string;
42
- private isMessageChannelReady: boolean = false;
36
+ private isMessageChannelReady = false;
43
37
  private pendingRequests: Array<() => void> = [];
44
38
 
45
- private constructor(pluginId: string, standalone: boolean) {
39
+ public constructor(pluginId: string, standalone: boolean) {
46
40
  this.pluginId = pluginId;
47
41
  this.getClient = this.getClient.bind(this);
48
42
 
49
- if (typeof WorkerGlobalScope === 'undefined') {
50
- // In standalone mode, use URL fallback. In iframe mode, theme will be set after MessageChannel init
51
- if (standalone) {
52
- setTheme();
53
- }
54
- }
55
-
56
43
  //no need to forward messages to parent in standalone mode or worker context
57
44
  if (standalone) return;
58
45
 
59
46
  this.initMessageChannel(typeof WorkerGlobalScope !== 'undefined');
60
47
  }
61
48
 
62
- private initMessageChannel(worker: boolean = false) {
49
+ private initMessageChannel(worker = false): void {
63
50
  const listener = (event: MessageEvent) => {
64
51
  console.log('[PluginController] window message', { origin: event.origin, data: event.data });
65
52
  const { type, pluginId, queryParams, rimoriInfo } = event.data || {};
@@ -104,8 +91,9 @@ export class PluginController {
104
91
 
105
92
  // Set theme from MessageChannel query params
106
93
  if (!worker) {
107
- const theme = this.queryParams['rm_theme'];
108
- setTheme(theme);
94
+ // const theme = this.queryParams['rm_theme'];
95
+ // setTheme(theme);
96
+ // console.log('TODO: set theme from MessageChannel query params');
109
97
  }
110
98
 
111
99
  // Forward plugin events to parent (only after MessageChannel is ready)
@@ -128,9 +116,12 @@ export class PluginController {
128
116
  window.addEventListener('message', listener);
129
117
  }
130
118
  this.sendHello(worker);
119
+ EventBus.on('self.rimori.triggerInitFinished', () => {
120
+ this.sendFinishedInit(worker);
121
+ });
131
122
  }
132
123
 
133
- private sendHello(isWorker: boolean = false) {
124
+ private sendHello(isWorker = false): void {
134
125
  try {
135
126
  const payload = { type: 'rimori:hello', pluginId: this.pluginId };
136
127
  if (isWorker) {
@@ -143,20 +134,17 @@ export class PluginController {
143
134
  }
144
135
  }
145
136
 
146
- public static async getInstance(pluginId: string, standalone = false): Promise<RimoriClient> {
147
- if (!PluginController.instance) {
148
- if (standalone) {
149
- await StandaloneClient.initListeners(pluginId);
150
- }
151
- PluginController.instance = new PluginController(pluginId, standalone);
152
- PluginController.client = await RimoriClient.getInstance(PluginController.instance);
153
-
154
- //only init logger in workers and on main plugin pages
155
- if (PluginController.instance.getQueryParam('applicationMode') !== 'sidebar') {
156
- Logger.getInstance(PluginController.client);
137
+ private sendFinishedInit(isWorker = false): void {
138
+ try {
139
+ const payload = { type: 'rimori:acknowledged', pluginId: this.pluginId };
140
+ if (isWorker) {
141
+ self.postMessage(payload);
142
+ } else {
143
+ window.parent.postMessage(payload, '*');
157
144
  }
145
+ } catch (e) {
146
+ console.error('[PluginController] Error sending finished init:', e);
158
147
  }
159
- return PluginController.client;
160
148
  }
161
149
 
162
150
  public getQueryParam(key: string): string | null {
@@ -261,7 +249,7 @@ export class PluginController {
261
249
  * @returns The Supabase URL.
262
250
  * @deprecated All endpoints should use the backend URL instead.
263
251
  */
264
- public getSupabaseUrl() {
252
+ public getSupabaseUrl(): string {
265
253
  if (!this.rimoriInfo) {
266
254
  throw new Error('Supabase info not found');
267
255
  }
@@ -269,14 +257,14 @@ export class PluginController {
269
257
  return this.rimoriInfo.url;
270
258
  }
271
259
 
272
- public getBackendUrl() {
260
+ public getBackendUrl(): string {
273
261
  if (!this.rimoriInfo) {
274
262
  throw new Error('Rimori info not found');
275
263
  }
276
264
  return this.rimoriInfo.backendUrl;
277
265
  }
278
266
 
279
- public getGlobalEventTopic(preliminaryTopic: string) {
267
+ public getGlobalEventTopic(preliminaryTopic: string): string {
280
268
  if (preliminaryTopic.startsWith('global.')) {
281
269
  return preliminaryTopic;
282
270
  }