@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
@@ -1,133 +1,108 @@
1
1
  import { PostgrestQueryBuilder } from '@supabase/postgrest-js';
2
2
  import { SupabaseClient } from '@supabase/supabase-js';
3
3
  import { GenericSchema } from '@supabase/supabase-js/dist/module/lib/types';
4
- import { generateText, Message, OnLLMResponse, streamChatGPT } from '../core/controller/AIController';
5
- import { generateObject, ObjectRequest } from '../core/controller/ObjectController';
6
- import { SettingsController, UserInfo } from '../core/controller/SettingsController';
4
+ import { generateText, Message, OnLLMResponse, streamChatGPT } from '../controller/AIController';
5
+ import { generateObject, ObjectRequest } from '../controller/ObjectController';
6
+ import { SettingsController, UserInfo } from '../controller/SettingsController';
7
7
  import {
8
8
  SharedContent,
9
9
  SharedContentController,
10
10
  SharedContentFilter,
11
11
  SharedContentObjectRequest,
12
- } from '../core/controller/SharedContentController';
13
- import { getSTTResponse, getTTSResponse } from '../core/controller/VoiceController';
14
- import { ExerciseController, CreateExerciseParams } from '../core/controller/ExerciseController';
12
+ } from '../controller/SharedContentController';
13
+ import { getSTTResponse, getTTSResponse } from '../controller/VoiceController';
14
+ import { ExerciseController, CreateExerciseParams } from '../controller/ExerciseController';
15
15
  import { EventBus, EventBusMessage, EventHandler, EventPayload } from '../fromRimori/EventBus';
16
16
  import { ActivePlugin, MainPanelAction, Plugin, Tool } from '../fromRimori/PluginTypes';
17
- import { AccomplishmentHandler, AccomplishmentPayload } from './AccomplishmentHandler';
18
- import { PluginController, RimoriInfo } from './PluginController';
19
- import { Translator } from './TranslationController';
17
+ import { AccomplishmentController, AccomplishmentPayload } from '../controller/AccomplishmentController';
18
+ import { RimoriCommunicationHandler, RimoriInfo } from './CommunicationHandler';
19
+ import { Translator } from '../controller/TranslationController';
20
+ import { Logger } from './Logger';
21
+ // import { setTheme } from '../../../react-client/src/plugin/ThemeSetter';
22
+ // import { StandaloneClient } from './StandaloneClient';
20
23
 
21
- interface Db {
22
- from: {
23
- <TableName extends string & keyof GenericSchema['Tables'], Table extends GenericSchema['Tables'][TableName]>(
24
- relation: TableName,
25
- ): PostgrestQueryBuilder<GenericSchema, Table, TableName>;
26
- <ViewName extends string & keyof GenericSchema['Views'], View extends GenericSchema['Views'][ViewName]>(
27
- relation: ViewName,
28
- ): PostgrestQueryBuilder<GenericSchema, View, ViewName>;
29
- };
30
- // storage: SupabaseClient["storage"];
31
-
32
- // functions: SupabaseClient["functions"];
33
- /**
34
- * The table prefix for of database tables of the plugin.
35
- */
36
- tablePrefix: string;
37
- /**
38
- * Get the table name for a given plugin table.
39
- * Internally all tables are prefixed with the plugin id. This function is used to get the correct table name for a given public table.
40
- * @param table The plugin table name to get the full table name for.
41
- * @returns The full table name.
42
- */
43
- getTableName: (table: string) => string;
44
- }
45
-
46
- interface PluginInterface {
47
- pluginId: string;
48
- setSettings: (settings: any) => Promise<void>;
49
- /**
50
- * Get the settings for the plugin. T can be any type of settings, UserSettings or SystemSettings.
51
- * @param defaultSettings The default settings to use if no settings are found.
52
- * @param genericSettings The type of settings to get.
53
- * @returns The settings for the plugin.
54
- */
55
- getSettings: <T extends object>(defaultSettings: T) => Promise<T>;
56
- /**
57
- * Retrieves information about plugins, including:
58
- * - All installed plugins
59
- * - The currently active plugin in the main panel
60
- * - The currently active plugin in the side panel
61
- */
62
- getPluginInfo: () => {
63
- /**
64
- * All installed plugins.
65
- */
66
- installedPlugins: Plugin[];
67
- /**
68
- * The plugin that is loaded in the main panel.
69
- */
70
- mainPanelPlugin?: ActivePlugin;
71
- /**
72
- * The plugin that is loaded in the side panel.
73
- */
74
- sidePanelPlugin?: ActivePlugin;
75
- };
76
- getUserInfo: () => UserInfo;
77
- getTranslator: () => Promise<Translator>;
78
- }
24
+ // Add declaration for WorkerGlobalScope
25
+ declare const WorkerGlobalScope: any;
79
26
 
80
27
  export class RimoriClient {
81
28
  private static instance: RimoriClient;
82
29
  private superbase: SupabaseClient;
83
- private pluginController: PluginController;
30
+ private pluginController: RimoriCommunicationHandler;
84
31
  private settingsController: SettingsController;
85
32
  private sharedContentController: SharedContentController;
86
33
  private exerciseController: ExerciseController;
87
- private accomplishmentHandler: AccomplishmentHandler;
34
+ private accomplishmentHandler: AccomplishmentController;
88
35
  private rimoriInfo: RimoriInfo;
89
36
  private translator: Translator;
90
- public plugin: PluginInterface;
91
- public db: Db;
92
37
 
93
- private constructor(supabase: SupabaseClient, info: RimoriInfo, pluginController: PluginController) {
38
+ private constructor(controller: RimoriCommunicationHandler, supabase: SupabaseClient, info: RimoriInfo) {
94
39
  this.rimoriInfo = info;
95
40
  this.superbase = supabase;
96
- this.pluginController = pluginController;
41
+ this.pluginController = controller;
42
+ this.exerciseController = new ExerciseController(supabase);
43
+ this.accomplishmentHandler = new AccomplishmentController(info.pluginId);
97
44
  this.settingsController = new SettingsController(supabase, info.pluginId, info.guild);
98
- this.sharedContentController = new SharedContentController(this.superbase, this);
99
- this.exerciseController = new ExerciseController(supabase, pluginController);
100
- this.accomplishmentHandler = new AccomplishmentHandler(info.pluginId);
45
+ this.sharedContentController = new SharedContentController(supabase, this);
101
46
  this.translator = new Translator(info.profile.mother_tongue.code);
102
47
 
103
- this.from = this.from.bind(this);
104
- this.getTableName = this.getTableName.bind(this);
48
+ //only init logger in workers and on main plugin pages
49
+ if (this.getQueryParam('applicationMode') !== 'sidebar') {
50
+ Logger.getInstance(this);
51
+ }
52
+ }
105
53
 
106
- this.db = {
107
- from: this.from,
108
- // storage: this.superbase.storage,
109
- // functions: this.superbase.functions,
110
- tablePrefix: info.tablePrefix,
111
- getTableName: this.getTableName,
112
- };
113
- this.plugin = {
114
- pluginId: info.pluginId,
54
+ public get plugin() {
55
+ return {
56
+ pluginId: this.rimoriInfo.pluginId,
57
+ /**
58
+ * Set the settings for the plugin.
59
+ * @param settings The settings to set.
60
+ */
115
61
  setSettings: async (settings: any): Promise<void> => {
116
62
  await this.settingsController.setSettings(settings);
117
63
  },
64
+ /**
65
+ * Get the settings for the plugin. T can be any type of settings, UserSettings or SystemSettings.
66
+ * @param defaultSettings The default settings to use if no settings are found.
67
+ * @param genericSettings The type of settings to get.
68
+ * @returns The settings for the plugin.
69
+ */
118
70
  getSettings: async <T extends object>(defaultSettings: T): Promise<T> => {
119
71
  return await this.settingsController.getSettings<T>(defaultSettings);
120
72
  },
121
73
  getUserInfo: (): UserInfo => {
122
74
  return this.rimoriInfo.profile;
123
75
  },
124
- getPluginInfo: () => {
76
+ /**
77
+ * Retrieves information about plugins, including:
78
+ * - All installed plugins
79
+ * - The currently active plugin in the main panel
80
+ * - The currently active plugin in the side panel
81
+ */
82
+ getPluginInfo: (): {
83
+ /**
84
+ * All installed plugins.
85
+ */
86
+ installedPlugins: Plugin[];
87
+ /**
88
+ * The plugin that is loaded in the main panel.
89
+ */
90
+ mainPanelPlugin?: ActivePlugin;
91
+ /**
92
+ * The plugin that is loaded in the side panel.
93
+ */
94
+ sidePanelPlugin?: ActivePlugin;
95
+ } => {
125
96
  return {
126
97
  installedPlugins: this.rimoriInfo.installedPlugins,
127
98
  mainPanelPlugin: this.rimoriInfo.mainPanelPlugin,
128
99
  sidePanelPlugin: this.rimoriInfo.sidePanelPlugin,
129
100
  };
130
101
  },
102
+ /**
103
+ * Get the translator for the plugin.
104
+ * @returns The translator for the plugin.
105
+ */
131
106
  getTranslator: async (): Promise<Translator> => {
132
107
  await this.translator.initialize();
133
108
  return this.translator;
@@ -135,6 +110,44 @@ export class RimoriClient {
135
110
  };
136
111
  }
137
112
 
113
+ public get db() {
114
+ return {
115
+ // private from<
116
+ // TableName extends string & keyof GenericSchema['Tables'],
117
+ // Table extends GenericSchema['Tables'][TableName],
118
+ // >(relation: TableName): PostgrestQueryBuilder<GenericSchema, Table, TableName>;
119
+ // private from<ViewName extends string & keyof GenericSchema['Views'], View extends GenericSchema['Views'][ViewName]>(
120
+ // relation: ViewName,
121
+ // ): PostgrestQueryBuilder<GenericSchema, View, ViewName>;
122
+ from: <ViewName extends string & keyof GenericSchema['Views'], View extends GenericSchema['Views'][ViewName]>(
123
+ relation: string,
124
+ ): PostgrestQueryBuilder<GenericSchema, View, ViewName> => {
125
+ return this.superbase.from(this.db.getTableName(relation));
126
+ },
127
+ // storage: this.superbase.storage,
128
+ // functions: this.superbase.functions,
129
+ /**
130
+ * The table prefix for of database tables of the plugin.
131
+ */
132
+ tablePrefix: this.rimoriInfo.tablePrefix,
133
+ /**
134
+ * Get the table name for a given plugin table.
135
+ * Internally all tables are prefixed with the plugin id. This function is used to get the correct table name for a given public table.
136
+ * @param table The plugin table name to get the full table name for.
137
+ * @returns The full table name.
138
+ */
139
+ getTableName: (table: string): string => {
140
+ if (/[A-Z]/.test(table)) {
141
+ throw new Error('Table name cannot include uppercase letters. Please use snake_case for table names.');
142
+ }
143
+ if (table.startsWith('global_')) {
144
+ return table.replace('global_', '');
145
+ }
146
+ return this.db.tablePrefix + '_' + table;
147
+ },
148
+ };
149
+ }
150
+
138
151
  public event = {
139
152
  /**
140
153
  * Emit an event to Rimori or a plugin.
@@ -225,15 +238,19 @@ export class RimoriClient {
225
238
  this.event.emit('global.sidebar.triggerAction', { plugin_id: pluginId, action_key: actionKey, text });
226
239
  },
227
240
 
228
- onMainPanelAction: (callback: (data: MainPanelAction) => void) => {
241
+ onMainPanelAction: (callback: (data: MainPanelAction) => void, actionsToListen: string[] = []) => {
229
242
  // this needs to be a emit and on because the main panel action is triggered by the user and not by the plugin
230
243
  this.event.emit('action.requestMain');
231
- this.event.on<MainPanelAction>('action.requestMain', ({ data }) => callback(data));
244
+ this.event.on<MainPanelAction>('action.requestMain', ({ data }) => {
245
+ if (actionsToListen.includes(data.action)) {
246
+ callback(data);
247
+ }
248
+ });
232
249
  },
233
250
  };
234
251
 
235
252
  public navigation = {
236
- toDashboard: () => {
253
+ toDashboard: (): void => {
237
254
  this.event.emit('global.navigation.triggerToDashboard');
238
255
  },
239
256
  };
@@ -247,33 +264,21 @@ export class RimoriClient {
247
264
  return this.pluginController.getQueryParam(key);
248
265
  }
249
266
 
250
- public static async getInstance(pluginController: PluginController): Promise<RimoriClient> {
267
+ public static async getInstance(pluginId?: string): Promise<RimoriClient> {
251
268
  if (!RimoriClient.instance) {
252
- const client = await pluginController.getClient();
253
- RimoriClient.instance = new RimoriClient(client.supabase, client.info, pluginController);
254
- }
255
- return RimoriClient.instance;
256
- }
269
+ if (!pluginId) throw new Error('Plugin ID is required');
257
270
 
258
- private from<
259
- TableName extends string & keyof GenericSchema['Tables'],
260
- Table extends GenericSchema['Tables'][TableName],
261
- >(relation: TableName): PostgrestQueryBuilder<GenericSchema, Table, TableName>;
262
- private from<ViewName extends string & keyof GenericSchema['Views'], View extends GenericSchema['Views'][ViewName]>(
263
- relation: ViewName,
264
- ): PostgrestQueryBuilder<GenericSchema, View, ViewName>;
265
- private from(relation: string): PostgrestQueryBuilder<GenericSchema, any, any> {
266
- return this.superbase.from(this.getTableName(relation));
267
- }
271
+ const controller = new RimoriCommunicationHandler(pluginId, false);
268
272
 
269
- private getTableName(table: string) {
270
- if (/[A-Z]/.test(table)) {
271
- throw new Error('Table name cannot include uppercase letters. Please use snake_case for table names.');
272
- }
273
- if (table.startsWith('global_')) {
274
- return table.replace('global_', '');
273
+ if (typeof WorkerGlobalScope === 'undefined') {
274
+ // In standalone mode, use URL fallback. In iframe mode, theme will be set after MessageChannel init
275
+ // setTheme();
276
+ // await StandaloneClient.initListeners(pluginId);
277
+ }
278
+ const client = await controller.getClient();
279
+ RimoriClient.instance = new RimoriClient(controller, client.supabase, client.info);
275
280
  }
276
- return this.db.tablePrefix + '_' + table;
281
+ return RimoriClient.instance;
277
282
  }
278
283
 
279
284
  public ai = {
@@ -295,9 +300,9 @@ export class RimoriClient {
295
300
  const token = await this.pluginController.getToken();
296
301
  return getSTTResponse(this.pluginController.getBackendUrl(), file, token);
297
302
  },
298
- getObject: async (request: ObjectRequest): Promise<any> => {
303
+ getObject: async <T = any>(request: ObjectRequest): Promise<T> => {
299
304
  const token = await this.pluginController.getToken();
300
- return generateObject(this.pluginController.getBackendUrl(), request, token);
305
+ return generateObject<T>(this.pluginController.getBackendUrl(), request, token);
301
306
  },
302
307
  // getSteamedObject: this.generateObjectStream,
303
308
  };
@@ -436,7 +441,9 @@ export class RimoriClient {
436
441
  * @returns Created exercise object.
437
442
  */
438
443
  add: async (params: CreateExerciseParams) => {
439
- return this.exerciseController.addExercise(params);
444
+ const token = await this.pluginController.getToken();
445
+ const backendUrl = this.pluginController.getBackendUrl();
446
+ return this.exerciseController.addExercise(token, backendUrl, params);
440
447
  },
441
448
 
442
449
  /**
@@ -445,7 +452,9 @@ export class RimoriClient {
445
452
  * @returns Success status.
446
453
  */
447
454
  delete: async (id: string) => {
448
- return this.exerciseController.deleteExercise(id);
455
+ const token = await this.pluginController.getToken();
456
+ const backendUrl = this.pluginController.getBackendUrl();
457
+ return this.exerciseController.deleteExercise(token, backendUrl, id);
449
458
  },
450
459
  };
451
460
  }
@@ -1,13 +1,15 @@
1
1
  import { RimoriClient } from '../plugin/RimoriClient';
2
2
  import { EventBusHandler } from '../fromRimori/EventBus';
3
- import { PluginController } from '../plugin/PluginController';
4
3
 
5
4
  /**
6
5
  * Sets up the web worker for the plugin to be able receive and send messages to Rimori.
7
6
  * @param pluginId - The id of the plugin to setup the worker for.
8
7
  * @param init - The function containing the initialization logic.
9
8
  */
10
- export async function setupWorker(pluginId: string, init: (client: RimoriClient) => void | Promise<void>) {
9
+ export async function setupWorker(
10
+ pluginId: string,
11
+ init: (client: RimoriClient) => void | Promise<void>,
12
+ ): Promise<void> {
11
13
  // Mock of the window object for the worker context to be able to use the PluginController.
12
14
  const mockWindow = {
13
15
  isWorker: true,
@@ -23,11 +25,11 @@ export async function setupWorker(pluginId: string, init: (client: RimoriClient)
23
25
 
24
26
  EventBusHandler.getInstance('Worker EventBus');
25
27
 
26
- const rimoriClient = await PluginController.getInstance(pluginId);
28
+ const rimoriClient = await RimoriClient.getInstance(pluginId);
27
29
  console.debug('[Worker] RimoriClient initialized.');
28
30
 
29
31
  await init(rimoriClient);
30
32
  console.debug('[Worker] Worker initialized.');
31
33
 
32
- self.postMessage({ type: 'rimori:acknowledged', pluginId: pluginId });
34
+ rimoriClient.event.emit('self.rimori.triggerInitFinished');
33
35
  }
package/tsconfig.json CHANGED
@@ -1,6 +1,7 @@
1
1
  {
2
2
  "compilerOptions": {
3
3
  "outDir": "dist",
4
+ "rootDir": "src",
4
5
  "module": "ESNext",
5
6
  "target": "ES6",
6
7
  "declaration": true,
@@ -10,5 +11,7 @@
10
11
  "skipLibCheck": true,
11
12
  "strict": true
12
13
  },
13
- "include": ["src/**/*"]
14
- }
14
+ "include": [
15
+ "src/**/*",
16
+ ]
17
+ }
@@ -1,6 +0,0 @@
1
- import { Config } from './release.js';
2
- /**
3
- * Upload translation files to the release function
4
- * @param config - Configuration object
5
- */
6
- export declare function uploadTranslations(config: Config, release_id: string): Promise<void>;
@@ -1,87 +0,0 @@
1
- var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
2
- function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
3
- return new (P || (P = Promise))(function (resolve, reject) {
4
- function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
5
- function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
6
- function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
7
- step((generator = generator.apply(thisArg, _arguments || [])).next());
8
- });
9
- };
10
- import fs from 'fs';
11
- import path from 'path';
12
- /**
13
- * Upload translation files to the release function
14
- * @param config - Configuration object
15
- */
16
- export function uploadTranslations(config, release_id) {
17
- return __awaiter(this, void 0, void 0, function* () {
18
- const localesPath = './public/locales';
19
- console.log(`📁 Checking for translation files...`);
20
- // Check if locales directory exists
21
- try {
22
- yield fs.promises.access(localesPath);
23
- }
24
- catch (e) {
25
- console.log('⚠️ No locales directory found at public/locales, skipping translation upload');
26
- return;
27
- }
28
- // Read all files in the locales directory
29
- const files = yield fs.promises.readdir(localesPath);
30
- // Filter out local- files and only include .json files
31
- const translationFiles = files.filter(file => file.endsWith('.json') &&
32
- !file.startsWith('local-'));
33
- if (translationFiles.length === 0) {
34
- console.log('⚠️ No translation files found (excluding local- files), skipping translation upload');
35
- return;
36
- }
37
- console.log(`🌐 Found ${translationFiles.length} translation files: ${translationFiles.join(', ')}`);
38
- // Create FormData
39
- const formData = new FormData();
40
- // Add version and release channel data
41
- formData.append('version', config.version);
42
- formData.append('release_channel', config.release_channel);
43
- formData.append('plugin_id', config.plugin_id);
44
- // Create path mapping with ID as key
45
- const pathMapping = {};
46
- try {
47
- // Process each translation file
48
- for (let i = 0; i < translationFiles.length; i++) {
49
- const fileName = translationFiles[i];
50
- const filePath = path.join(localesPath, fileName);
51
- console.log(`📄 Processing ${fileName}...`);
52
- const fileContent = yield fs.promises.readFile(filePath);
53
- const contentType = 'application/json';
54
- // Generate unique ID for this file
55
- const fileId = `file_${i}`;
56
- // Add to path mapping using ID as key
57
- pathMapping[fileId] = fileName;
58
- // Create a Blob with the file content and content type
59
- const blob = new Blob([new Uint8Array(fileContent)], { type: contentType });
60
- // Add file to FormData with ID_filename format
61
- const formFileName = `${fileId}_${fileName}`;
62
- formData.append('files', blob, formFileName);
63
- }
64
- }
65
- catch (error) {
66
- console.error(`❌ Error reading translation files:`, error.message);
67
- throw error;
68
- }
69
- // Add path mapping to FormData
70
- formData.append('path_mapping', JSON.stringify(pathMapping));
71
- // Upload to the release endpoint
72
- const response = yield fetch(`${config.domain}/release/${release_id}/translations`, {
73
- method: 'POST',
74
- headers: { Authorization: `Bearer ${config.token}` },
75
- body: formData,
76
- });
77
- if (response.ok) {
78
- console.log('✅ Translation files uploaded successfully!');
79
- }
80
- else {
81
- const errorText = yield response.text();
82
- console.log('❌ Translation upload failed!');
83
- console.log('Response:', errorText);
84
- throw new Error(`Translation upload failed with status ${response.status}`);
85
- }
86
- });
87
- }
@@ -1,17 +0,0 @@
1
- interface Props {
2
- title: string;
3
- show?: boolean;
4
- className?: string;
5
- closeAble?: boolean;
6
- children: React.ReactNode;
7
- actionbuttons: ActionButton[];
8
- buttonText?: string | React.ReactNode;
9
- onClose?: () => void;
10
- }
11
- interface ActionButton {
12
- text: string;
13
- onClick: () => void;
14
- closeModal?: boolean;
15
- }
16
- export declare function CRUDModal({ actionbuttons, children, title, buttonText, className, closeAble, show, onClose, }: Props): import("react/jsx-runtime").JSX.Element;
17
- export {};
@@ -1,24 +0,0 @@
1
- import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
2
- import { useEffect, useRef } from 'react';
3
- export function CRUDModal({ actionbuttons, children, title, buttonText, className, closeAble = true, show = false, onClose, }) {
4
- const dialogRef = useRef(null);
5
- useEffect(() => {
6
- var _a, _b;
7
- if (show) {
8
- (_a = dialogRef.current) === null || _a === void 0 ? void 0 : _a.showModal();
9
- }
10
- else {
11
- (_b = dialogRef.current) === null || _b === void 0 ? void 0 : _b.close();
12
- }
13
- }, [show]);
14
- const handleClose = () => {
15
- var _a;
16
- (_a = dialogRef.current) === null || _a === void 0 ? void 0 : _a.close();
17
- onClose === null || onClose === void 0 ? void 0 : onClose();
18
- };
19
- return (_jsxs(_Fragment, { children: [!!buttonText && (_jsx("button", { className: className, onClick: () => { var _a; return (_a = dialogRef.current) === null || _a === void 0 ? void 0 : _a.showModal(); }, children: buttonText })), _jsxs("dialog", { ref: dialogRef, className: "bg-gray-400 rounded-lg font-normal", onClose: handleClose, children: [_jsxs("div", { className: "bg-gray-500 text-xl flex flex-row justify-between p-3 items-start font-bold", children: [_jsx("h2", { children: title }), closeAble && _jsx("button", { onClick: handleClose, children: "\u00D7" })] }), _jsx("div", { className: "modal-body p-2", children: children }), _jsx("div", { className: "modal-footer px-2 py-2 flex flex-row gap-2 border-t-2", children: actionbuttons.map(({ onClick, text, closeModal = true }, index) => (_jsx("button", { className: "bg-blue-500 hover:bg-blue-600 dark:border-gray-900 rounded-md py-2 px-4 dark:text-white font-bold", onClick: () => {
20
- if (closeModal)
21
- handleClose();
22
- onClick();
23
- }, children: text }, index))) })] })] }));
24
- }
@@ -1,8 +0,0 @@
1
- interface Props {
2
- content?: string;
3
- editable: boolean;
4
- className?: string;
5
- onUpdate?: (content: string) => void;
6
- }
7
- export declare const MarkdownEditor: (props: Props) => import("react/jsx-runtime").JSX.Element;
8
- export {};
@@ -1,48 +0,0 @@
1
- import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
- import { Markdown } from 'tiptap-markdown';
3
- import StarterKit from '@tiptap/starter-kit';
4
- import { PiCodeBlock } from 'react-icons/pi';
5
- import { TbBlockquote } from 'react-icons/tb';
6
- import { GoListOrdered } from 'react-icons/go';
7
- import { AiOutlineUnorderedList } from 'react-icons/ai';
8
- import { EditorProvider, useCurrentEditor } from '@tiptap/react';
9
- import { LuHeading1, LuHeading2, LuHeading3 } from 'react-icons/lu';
10
- import { FaBold, FaCode, FaItalic, FaParagraph, FaStrikethrough } from 'react-icons/fa';
11
- const EditorButton = ({ action, isActive, label, disabled }) => {
12
- const { editor } = useCurrentEditor();
13
- if (!editor) {
14
- return null;
15
- }
16
- if (action.includes('heading')) {
17
- const level = parseInt(action[action.length - 1]);
18
- return (_jsx("button", { onClick: () => editor.chain().focus().toggleHeading({ level: level }).run(), className: `pl-2 ${isActive ? 'is-active' : ''}`, children: label }));
19
- }
20
- return (_jsx("button", { onClick: () => editor.chain().focus()[action]().run(), disabled: disabled ? !editor.can().chain().focus()[action]().run() : false, className: `pl-2 ${isActive ? 'is-active' : ''}`, children: label }));
21
- };
22
- const MenuBar = () => {
23
- const { editor } = useCurrentEditor();
24
- if (!editor) {
25
- return null;
26
- }
27
- return (_jsxs("div", { className: "bg-gray-400 dark:bg-gray-800 dark:text-white text-lg flex flex-row flex-wrap items-center p-1", children: [_jsx(EditorButton, { action: "toggleBold", isActive: editor.isActive('bold'), label: _jsx(FaBold, {}), disabled: true }), _jsx(EditorButton, { action: "toggleItalic", isActive: editor.isActive('italic'), label: _jsx(FaItalic, {}), disabled: true }), _jsx(EditorButton, { action: "toggleStrike", isActive: editor.isActive('strike'), label: _jsx(FaStrikethrough, {}), disabled: true }), _jsx(EditorButton, { action: "toggleCode", isActive: editor.isActive('code'), label: _jsx(FaCode, {}), disabled: true }), _jsx(EditorButton, { action: "setParagraph", isActive: editor.isActive('paragraph'), label: _jsx(FaParagraph, {}) }), _jsx(EditorButton, { action: "setHeading1", isActive: editor.isActive('heading', { level: 1 }), label: _jsx(LuHeading1, { size: '24px' }) }), _jsx(EditorButton, { action: "setHeading2", isActive: editor.isActive('heading', { level: 2 }), label: _jsx(LuHeading2, { size: '24px' }) }), _jsx(EditorButton, { action: "setHeading3", isActive: editor.isActive('heading', { level: 3 }), label: _jsx(LuHeading3, { size: '24px' }) }), _jsx(EditorButton, { action: "toggleBulletList", isActive: editor.isActive('bulletList'), label: _jsx(AiOutlineUnorderedList, { size: '24px' }) }), _jsx(EditorButton, { action: "toggleOrderedList", isActive: editor.isActive('orderedList'), label: _jsx(GoListOrdered, { size: '24px' }) }), _jsx(EditorButton, { action: "toggleCodeBlock", isActive: editor.isActive('codeBlock'), label: _jsx(PiCodeBlock, { size: '24px' }) }), _jsx(EditorButton, { action: "toggleBlockquote", isActive: editor.isActive('blockquote'), label: _jsx(TbBlockquote, { size: '24px' }) })] }));
28
- };
29
- const extensions = [
30
- StarterKit.configure({
31
- bulletList: {
32
- HTMLAttributes: {
33
- class: 'list-disc list-inside dark:text-white p-1 mt-1 [&_li]:mb-1 [&_p]:inline m-0',
34
- },
35
- },
36
- orderedList: {
37
- HTMLAttributes: {
38
- className: 'list-decimal list-inside dark:text-white p-1 mt-1 [&_li]:mb-1 [&_p]:inline m-0',
39
- },
40
- },
41
- }),
42
- Markdown,
43
- ];
44
- export const MarkdownEditor = (props) => {
45
- return (_jsx("div", { className: 'text-md border border-gray-800 overflow-hidden ' + props.className, style: { borderWidth: props.editable ? 1 : 0 }, children: _jsx(EditorProvider, { slotBefore: props.editable ? _jsx(MenuBar, {}) : null, extensions: extensions, content: props.content, editable: props.editable, onUpdate: (e) => {
46
- props.onUpdate && props.onUpdate(e.editor.storage.markdown.getMarkdown());
47
- } }, (props.editable ? 'editable' : 'readonly') + props.content) }));
48
- };
@@ -1,8 +0,0 @@
1
- import React from 'react';
2
- interface SpinnerProps {
3
- text?: string;
4
- size?: string;
5
- className?: string;
6
- }
7
- export declare const Spinner: React.FC<SpinnerProps>;
8
- export {};
@@ -1,4 +0,0 @@
1
- import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
- export const Spinner = ({ text, className, size = '30px' }) => {
3
- return (_jsxs("div", { className: 'flex items-center space-x-2 ' + className, children: [_jsxs("svg", { style: { width: size, height: size }, className: "animate-spin -ml-1 mr-3 h-5 w-5 text-white", xmlns: "http://www.w3.org/2000/svg", fill: "none", viewBox: "0 0 24 24", children: [_jsx("circle", { className: "opacity-25", cx: "12", cy: "12", r: "10", stroke: "currentColor", strokeWidth: "4" }), _jsx("path", { className: "opacity-75", fill: "currentColor", d: "M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z" })] }), text && _jsx("span", { className: "", children: text })] }));
4
- };
@@ -1,9 +0,0 @@
1
- import { FirstMessages } from './utils';
2
- interface Props {
3
- voiceId: any;
4
- avatarImageUrl: string;
5
- onComplete: (result: any) => void;
6
- autoStartConversation?: FirstMessages;
7
- }
8
- export declare function AssistantChat({ avatarImageUrl, voiceId, onComplete, autoStartConversation }: Props): import("react/jsx-runtime").JSX.Element;
9
- export {};