@rimori/client 1.3.1 → 1.4.3

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 (148) hide show
  1. package/.prettierignore +35 -0
  2. package/README.md +77 -71
  3. package/dist/cli/scripts/init/dev-registration.d.ts +1 -1
  4. package/dist/cli/scripts/init/dev-registration.js +4 -4
  5. package/dist/cli/scripts/init/main.js +1 -1
  6. package/dist/cli/scripts/init/package-setup.d.ts +1 -1
  7. package/dist/cli/scripts/init/package-setup.js +3 -3
  8. package/dist/cli/scripts/init/router-transformer.js +19 -12
  9. package/dist/cli/scripts/init/vite-config.d.ts +2 -2
  10. package/dist/cli/scripts/init/vite-config.js +2 -2
  11. package/dist/cli/scripts/release/release-config-upload.js +9 -9
  12. package/dist/cli/scripts/release/release-db-update.d.ts +1 -1
  13. package/dist/cli/scripts/release/release-db-update.js +9 -9
  14. package/dist/cli/scripts/release/release-file-upload.js +2 -2
  15. package/dist/cli/scripts/release/release.js +2 -2
  16. package/dist/cli/types/DatabaseTypes.d.ts +2 -2
  17. package/dist/components/CRUDModal.d.ts +1 -1
  18. package/dist/components/CRUDModal.js +3 -3
  19. package/dist/components/MarkdownEditor.js +16 -16
  20. package/dist/components/Spinner.js +2 -2
  21. package/dist/components/ai/Assistant.js +7 -8
  22. package/dist/components/ai/Avatar.d.ts +2 -2
  23. package/dist/components/ai/Avatar.js +14 -7
  24. package/dist/components/ai/EmbeddedAssistent/AudioInputField.js +5 -6
  25. package/dist/components/ai/EmbeddedAssistent/CircleAudioAvatar.d.ts +1 -1
  26. package/dist/components/ai/EmbeddedAssistent/CircleAudioAvatar.js +1 -2
  27. package/dist/components/ai/EmbeddedAssistent/TTS/MessageSender.d.ts +1 -2
  28. package/dist/components/ai/EmbeddedAssistent/TTS/MessageSender.js +4 -2
  29. package/dist/components/ai/EmbeddedAssistent/TTS/Player.js +1 -1
  30. package/dist/components/ai/EmbeddedAssistent/VoiceRecoder.js +2 -3
  31. package/dist/components/audio/Playbutton.js +10 -7
  32. package/dist/components/components/ContextMenu.d.ts +1 -1
  33. package/dist/components/components/ContextMenu.js +19 -16
  34. package/dist/components.d.ts +10 -10
  35. package/dist/components.js +10 -10
  36. package/dist/core/controller/AIController.d.ts +2 -2
  37. package/dist/core/controller/AIController.js +20 -18
  38. package/dist/core/controller/ExerciseController.d.ts +52 -0
  39. package/dist/core/controller/ExerciseController.js +73 -0
  40. package/dist/core/controller/ObjectController.js +5 -5
  41. package/dist/core/controller/SettingsController.d.ts +22 -7
  42. package/dist/core/controller/SettingsController.js +73 -8
  43. package/dist/core/controller/SharedContentController.d.ts +3 -3
  44. package/dist/core/controller/SharedContentController.js +38 -20
  45. package/dist/core/controller/VoiceController.js +6 -4
  46. package/dist/core/core.d.ts +15 -14
  47. package/dist/core/core.js +7 -7
  48. package/dist/fromRimori/EventBus.js +23 -23
  49. package/dist/fromRimori/PluginTypes.d.ts +4 -4
  50. package/dist/hooks/UseChatHook.d.ts +3 -3
  51. package/dist/hooks/UseChatHook.js +9 -3
  52. package/dist/index.d.ts +10 -10
  53. package/dist/index.js +9 -9
  54. package/dist/plugin/AccomplishmentHandler.d.ts +5 -5
  55. package/dist/plugin/AccomplishmentHandler.js +31 -27
  56. package/dist/plugin/AudioController.d.ts +1 -1
  57. package/dist/plugin/AudioController.js +6 -6
  58. package/dist/plugin/Logger.d.ts +5 -0
  59. package/dist/plugin/Logger.js +65 -13
  60. package/dist/plugin/PluginController.d.ts +7 -1
  61. package/dist/plugin/PluginController.js +32 -27
  62. package/dist/plugin/RimoriClient.d.ts +39 -14
  63. package/dist/plugin/RimoriClient.js +60 -31
  64. package/dist/plugin/StandaloneClient.d.ts +1 -1
  65. package/dist/plugin/StandaloneClient.js +35 -16
  66. package/dist/plugin/ThemeSetter.js +4 -4
  67. package/dist/providers/PluginProvider.js +44 -14
  68. package/dist/utils/Language.js +57 -57
  69. package/dist/utils/PluginUtils.js +3 -3
  70. package/dist/utils/difficultyConverter.d.ts +1 -1
  71. package/dist/utils/difficultyConverter.js +1 -1
  72. package/dist/utils/endpoint.js +2 -2
  73. package/dist/worker/WorkerSetup.d.ts +1 -1
  74. package/dist/worker/WorkerSetup.js +6 -6
  75. package/eslint.config.js +53 -0
  76. package/example/docs/devdocs.md +50 -40
  77. package/example/docs/overview.md +1 -1
  78. package/example/docs/userdocs.md +4 -1
  79. package/example/rimori.config.ts +51 -49
  80. package/example/worker/vite.config.ts +3 -3
  81. package/example/worker/worker.ts +2 -2
  82. package/package.json +17 -4
  83. package/prettier.config.js +8 -0
  84. package/src/cli/scripts/init/dev-registration.ts +5 -8
  85. package/src/cli/scripts/init/env-setup.ts +1 -1
  86. package/src/cli/scripts/init/file-operations.ts +1 -1
  87. package/src/cli/scripts/init/html-cleaner.ts +2 -5
  88. package/src/cli/scripts/init/main.ts +16 -13
  89. package/src/cli/scripts/init/package-setup.ts +11 -15
  90. package/src/cli/scripts/init/router-transformer.ts +40 -37
  91. package/src/cli/scripts/init/tailwind-config.ts +17 -26
  92. package/src/cli/scripts/init/vite-config.ts +3 -3
  93. package/src/cli/scripts/release/release-config-upload.ts +11 -11
  94. package/src/cli/scripts/release/release-db-update.ts +12 -12
  95. package/src/cli/scripts/release/release-file-upload.ts +3 -3
  96. package/src/cli/scripts/release/release.ts +4 -4
  97. package/src/cli/types/DatabaseTypes.ts +7 -8
  98. package/src/components/CRUDModal.tsx +64 -48
  99. package/src/components/MarkdownEditor.tsx +58 -27
  100. package/src/components/Spinner.tsx +24 -17
  101. package/src/components/ai/Assistant.tsx +70 -70
  102. package/src/components/ai/Avatar.tsx +20 -16
  103. package/src/components/ai/EmbeddedAssistent/AudioInputField.tsx +63 -54
  104. package/src/components/ai/EmbeddedAssistent/CircleAudioAvatar.tsx +14 -5
  105. package/src/components/ai/EmbeddedAssistent/TTS/MessageSender.ts +75 -74
  106. package/src/components/ai/EmbeddedAssistent/TTS/Player.ts +177 -178
  107. package/src/components/ai/EmbeddedAssistent/VoiceRecoder.tsx +109 -94
  108. package/src/components/ai/utils.ts +4 -4
  109. package/src/components/audio/Playbutton.tsx +101 -93
  110. package/src/components/components/ContextMenu.tsx +47 -35
  111. package/src/components.ts +10 -10
  112. package/src/core/controller/AIController.ts +62 -50
  113. package/src/core/controller/ExerciseController.ts +98 -0
  114. package/src/core/controller/ObjectController.ts +15 -10
  115. package/src/core/controller/SettingsController.ts +89 -16
  116. package/src/core/controller/SharedContentController.ts +80 -44
  117. package/src/core/controller/VoiceController.ts +10 -8
  118. package/src/core/core.ts +15 -15
  119. package/src/fromRimori/EventBus.ts +76 -47
  120. package/src/fromRimori/PluginTypes.ts +26 -17
  121. package/src/fromRimori/readme.md +2 -2
  122. package/src/hooks/UseChatHook.ts +25 -15
  123. package/src/index.ts +10 -10
  124. package/src/plugin/AccomplishmentHandler.ts +53 -35
  125. package/src/plugin/AudioController.ts +18 -12
  126. package/src/plugin/Logger.ts +77 -19
  127. package/src/plugin/PluginController.ts +60 -44
  128. package/src/plugin/RimoriClient.ts +133 -69
  129. package/src/plugin/StandaloneClient.ts +51 -24
  130. package/src/plugin/ThemeSetter.ts +5 -5
  131. package/src/providers/PluginProvider.tsx +90 -36
  132. package/src/style.scss +3 -3
  133. package/src/utils/Language.ts +58 -58
  134. package/src/utils/PluginUtils.ts +16 -20
  135. package/src/utils/difficultyConverter.ts +2 -2
  136. package/src/utils/endpoint.ts +3 -2
  137. package/src/worker/WorkerSetup.ts +8 -9
  138. package/tsconfig.json +2 -4
  139. package/dist/components/LoggerExample.d.ts +0 -6
  140. package/dist/components/LoggerExample.js +0 -79
  141. package/dist/core/controller/AudioController.d.ts +0 -0
  142. package/dist/core/controller/AudioController.js +0 -1
  143. package/dist/hooks/UseLogger.d.ts +0 -30
  144. package/dist/hooks/UseLogger.js +0 -122
  145. package/dist/plugin/LoggerExample.d.ts +0 -16
  146. package/dist/plugin/LoggerExample.js +0 -140
  147. package/dist/utils/audioFormats.d.ts +0 -26
  148. package/dist/utils/audioFormats.js +0 -67
@@ -8,22 +8,87 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
8
8
  });
9
9
  };
10
10
  export class SettingsController {
11
- constructor(supabase, pluginId) {
11
+ constructor(supabase, pluginId, guild) {
12
12
  this.supabase = supabase;
13
13
  this.pluginId = pluginId;
14
+ this.guild = guild;
14
15
  }
16
+ /**
17
+ * Fetches settings based on guild configuration.
18
+ * If guild doesn't allow user settings, fetches guild-level settings.
19
+ * Otherwise, fetches user-specific settings.
20
+ * @returns The settings object or null if not found.
21
+ */
15
22
  fetchSettings() {
16
23
  return __awaiter(this, void 0, void 0, function* () {
17
- const { data } = yield this.supabase.from("plugin_settings").select("*").eq("plugin_id", this.pluginId);
18
- if (!data || data.length === 0) {
19
- return null;
20
- }
21
- return data[0].settings;
24
+ var _a;
25
+ const isGuildSetting = !this.guild.allowUserPluginSettings;
26
+ const { data } = yield this.supabase
27
+ .from('plugin_settings')
28
+ .select('*')
29
+ .eq('plugin_id', this.pluginId)
30
+ .eq('guild_id', this.guild.id)
31
+ .eq('is_guild_setting', isGuildSetting)
32
+ .maybeSingle();
33
+ return (_a = data === null || data === void 0 ? void 0 : data.settings) !== null && _a !== void 0 ? _a : null;
22
34
  });
23
35
  }
36
+ /**
37
+ * Sets settings for the plugin.
38
+ * Automatically saves as guild settings if guild doesn't allow user settings,
39
+ * otherwise saves as user-specific settings.
40
+ * @param settings - The settings object to save.
41
+ * @throws {Error} if RLS blocks the operation.
42
+ */
24
43
  setSettings(settings) {
25
44
  return __awaiter(this, void 0, void 0, function* () {
26
- yield this.supabase.from("plugin_settings").upsert({ plugin_id: this.pluginId, settings });
45
+ var _a;
46
+ const isGuildSetting = !this.guild.allowUserPluginSettings;
47
+ const payload = {
48
+ plugin_id: this.pluginId,
49
+ settings,
50
+ guild_id: this.guild.id,
51
+ is_guild_setting: isGuildSetting,
52
+ };
53
+ if (isGuildSetting) {
54
+ payload.user_id = null;
55
+ }
56
+ // Try UPDATE first (safe with RLS). If nothing updated, INSERT.
57
+ const updateQuery = this.supabase
58
+ .from('plugin_settings')
59
+ .update({ settings })
60
+ .eq('plugin_id', this.pluginId)
61
+ .eq('guild_id', this.guild.id)
62
+ .eq('is_guild_setting', isGuildSetting);
63
+ const { data: updatedRows, error: updateError } = yield (isGuildSetting
64
+ ? updateQuery.is('user_id', null).select('id')
65
+ : updateQuery.select('id'));
66
+ if (updateError) {
67
+ if (updateError.code === '42501' || ((_a = updateError.message) === null || _a === void 0 ? void 0 : _a.includes('policy'))) {
68
+ throw new Error(`Cannot set ${isGuildSetting ? 'guild' : 'user'} settings: Permission denied.`);
69
+ }
70
+ // proceed to try insert in case of other issues
71
+ }
72
+ if (updatedRows && updatedRows.length > 0) {
73
+ return; // updated successfully
74
+ }
75
+ // No row updated -> INSERT
76
+ const { error: insertError } = yield this.supabase.from('plugin_settings').insert(payload);
77
+ if (insertError) {
78
+ // In case of race condition (duplicate), try one more UPDATE
79
+ if (insertError.code === '23505' /* unique_violation */) {
80
+ const retry = this.supabase
81
+ .from('plugin_settings')
82
+ .update({ settings })
83
+ .eq('plugin_id', this.pluginId)
84
+ .eq('guild_id', this.guild.id)
85
+ .eq('is_guild_setting', isGuildSetting);
86
+ const { error: retryError } = yield (isGuildSetting ? retry.is('user_id', null) : retry);
87
+ if (!retryError)
88
+ return;
89
+ }
90
+ throw insertError;
91
+ }
27
92
  });
28
93
  }
29
94
  /**
@@ -33,7 +98,7 @@ export class SettingsController {
33
98
  */
34
99
  getSettings(defaultSettings) {
35
100
  return __awaiter(this, void 0, void 0, function* () {
36
- const storedSettings = yield this.fetchSettings();
101
+ const storedSettings = (yield this.fetchSettings());
37
102
  if (!storedSettings) {
38
103
  yield this.setSettings(defaultSettings);
39
104
  return defaultSettings;
@@ -1,6 +1,6 @@
1
1
  import { SupabaseClient } from '@supabase/supabase-js';
2
- import { RimoriClient } from "../../plugin/RimoriClient";
3
- import { ObjectRequest } from "./ObjectController";
2
+ import { RimoriClient } from '../../plugin/RimoriClient';
3
+ import { ObjectRequest } from './ObjectController';
4
4
  export interface SharedContentObjectRequest extends ObjectRequest {
5
5
  fixedProperties?: Record<string, string | number | boolean>;
6
6
  }
@@ -69,7 +69,7 @@ export declare class SharedContentController {
69
69
  * @returns The inserted shared content.
70
70
  * @throws {Error} if insertion fails.
71
71
  */
72
- createSharedContent<T>({ contentType, title, keywords, data, privateTopic }: Omit<SharedContent<T>, 'id'>): Promise<SharedContent<T>>;
72
+ createSharedContent<T>({ contentType, title, keywords, data, privateTopic, }: Omit<SharedContent<T>, 'id'>): Promise<SharedContent<T>>;
73
73
  /**
74
74
  * Update existing shared content in the database.
75
75
  * @param id - The ID of the content to update.
@@ -28,8 +28,9 @@ export class SharedContentController {
28
28
  //this filter is there if the content should be filtered additionally by a column and value
29
29
  filter, options) {
30
30
  return __awaiter(this, void 0, void 0, function* () {
31
- let query = this.supabase.from("shared_content")
32
- .select("*, scc:shared_content_completed(id, state)")
31
+ let query = this.supabase
32
+ .from('shared_content')
33
+ .select('*, scc:shared_content_completed(id, state)')
33
34
  .eq('content_type', contentType)
34
35
  .not('scc.state', 'in', '("completed","ongoing","hidden")')
35
36
  .is('deleted_at', null);
@@ -56,7 +57,7 @@ export class SharedContentController {
56
57
  console.log('instructions:', instructions);
57
58
  //create the shared content object
58
59
  const data = {
59
- id: "internal-temp-id-" + Math.random().toString(36).substring(2, 15),
60
+ id: 'internal-temp-id-' + Math.random().toString(36).substring(2, 15),
60
61
  contentType,
61
62
  title: instructions.title,
62
63
  keywords: instructions.keywords.map(({ text }) => text),
@@ -82,20 +83,21 @@ export class SharedContentController {
82
83
  generatorInstructions.instructions += `
83
84
  The following topics are already taken: ${completedTopics.join(', ')}`;
84
85
  generatorInstructions.tool.title = {
85
- type: "string",
86
- description: "What the topic is about. Short. ",
86
+ type: 'string',
87
+ description: 'What the topic is about. Short. ',
87
88
  };
88
89
  generatorInstructions.tool.keywords = {
89
- type: [{ text: { type: "string" } }],
90
- description: "Keywords around the topic of the assignment.",
90
+ type: [{ text: { type: 'string' } }],
91
+ description: 'Keywords around the topic of the assignment.',
91
92
  };
92
93
  return generatorInstructions;
93
94
  });
94
95
  }
95
96
  getCompletedTopics(contentType, filter) {
96
97
  return __awaiter(this, void 0, void 0, function* () {
97
- const query = this.supabase.from("shared_content")
98
- .select("title, keywords, scc:shared_content_completed(id)")
98
+ const query = this.supabase
99
+ .from('shared_content')
100
+ .select('title, keywords, scc:shared_content_completed(id)')
99
101
  .eq('content_type', contentType)
100
102
  .not('scc.id', 'is', null)
101
103
  .is('deleted_at', null);
@@ -112,7 +114,13 @@ export class SharedContentController {
112
114
  }
113
115
  getSharedContent(contentType, id) {
114
116
  return __awaiter(this, void 0, void 0, function* () {
115
- const { data, error } = yield this.supabase.from("shared_content").select().eq('content_type', contentType).eq('id', id).is('deleted_at', null).single();
117
+ const { data, error } = yield this.supabase
118
+ .from('shared_content')
119
+ .select()
120
+ .eq('content_type', contentType)
121
+ .eq('id', id)
122
+ .is('deleted_at', null)
123
+ .single();
116
124
  if (error) {
117
125
  console.error('error fetching shared content:', error);
118
126
  throw new Error('error fetching shared content');
@@ -124,7 +132,7 @@ export class SharedContentController {
124
132
  return __awaiter(this, void 0, void 0, function* () {
125
133
  // Idempotent completion: upsert on (id, user_id) so repeated calls don't fail
126
134
  const { error } = yield this.supabase
127
- .from("shared_content_completed")
135
+ .from('shared_content_completed')
128
136
  .upsert({ content_type: contentType, id: assignmentId }, { onConflict: 'id' });
129
137
  if (error) {
130
138
  console.error('error completing shared content:', error);
@@ -153,9 +161,7 @@ export class SharedContentController {
153
161
  if (bookmarked !== undefined)
154
162
  payload.bookmarked = bookmarked;
155
163
  // Prefer upsert, fall back to insert/update if upsert not allowed
156
- const { error } = yield this.supabase
157
- .from('shared_content_completed')
158
- .upsert(payload, { onConflict: 'id' });
164
+ const { error } = yield this.supabase.from('shared_content_completed').upsert(payload, { onConflict: 'id' });
159
165
  if (error) {
160
166
  console.error('error updating shared content state:', error);
161
167
  throw new Error('error updating shared content state');
@@ -171,7 +177,12 @@ export class SharedContentController {
171
177
  */
172
178
  getSharedContentList(contentType, filter, limit) {
173
179
  return __awaiter(this, void 0, void 0, function* () {
174
- const query = this.supabase.from("shared_content").select("*").eq('content_type', contentType).is('deleted_at', null).limit(limit !== null && limit !== void 0 ? limit : 30);
180
+ const query = this.supabase
181
+ .from('shared_content')
182
+ .select('*')
183
+ .eq('content_type', contentType)
184
+ .is('deleted_at', null)
185
+ .limit(limit !== null && limit !== void 0 ? limit : 30);
175
186
  if (filter) {
176
187
  query.contains('data', filter);
177
188
  }
@@ -195,14 +206,17 @@ export class SharedContentController {
195
206
  * @throws {Error} if insertion fails.
196
207
  */
197
208
  createSharedContent(_a) {
198
- return __awaiter(this, arguments, void 0, function* ({ contentType, title, keywords, data, privateTopic }) {
199
- const { data: newContent, error } = yield this.supabase.from("shared_content").insert({
209
+ return __awaiter(this, arguments, void 0, function* ({ contentType, title, keywords, data, privateTopic, }) {
210
+ const { data: newContent, error } = yield this.supabase
211
+ .from('shared_content')
212
+ .insert({
200
213
  private: privateTopic,
201
214
  content_type: contentType,
202
215
  title,
203
216
  keywords,
204
217
  data,
205
- }).select();
218
+ })
219
+ .select();
206
220
  if (error) {
207
221
  console.error('error inserting shared content:', error);
208
222
  throw new Error('error inserting shared content');
@@ -230,7 +244,11 @@ export class SharedContentController {
230
244
  updateData.data = updates.data;
231
245
  if (updates.privateTopic !== undefined)
232
246
  updateData.private = updates.privateTopic;
233
- const { data: updatedContent, error } = yield this.supabase.from("shared_content").update(updateData).eq('id', id).select();
247
+ const { data: updatedContent, error } = yield this.supabase
248
+ .from('shared_content')
249
+ .update(updateData)
250
+ .eq('id', id)
251
+ .select();
234
252
  if (error) {
235
253
  console.error('error updating shared content:', error);
236
254
  throw new Error('error updating shared content');
@@ -250,7 +268,7 @@ export class SharedContentController {
250
268
  removeSharedContent(id) {
251
269
  return __awaiter(this, void 0, void 0, function* () {
252
270
  const { data: deletedContent, error } = yield this.supabase
253
- .from("shared_content")
271
+ .from('shared_content')
254
272
  .update({ deleted_at: new Date().toISOString() })
255
273
  .eq('id', id)
256
274
  .select();
@@ -13,9 +13,11 @@ export function getSTTResponse(backendUrl, audio, token) {
13
13
  formData.append('file', audio);
14
14
  return yield fetch(`${backendUrl}/voice/stt`, {
15
15
  method: 'POST',
16
- headers: { 'Authorization': `Bearer ${token}` },
16
+ headers: { Authorization: `Bearer ${token}` },
17
17
  body: formData,
18
- }).then(r => r.json()).then(r => {
18
+ })
19
+ .then((r) => r.json())
20
+ .then((r) => {
19
21
  // console.log("STT response: ", r);
20
22
  return r.text;
21
23
  });
@@ -27,9 +29,9 @@ export function getTTSResponse(backendUrl, request, token) {
27
29
  method: 'POST',
28
30
  headers: {
29
31
  'Content-Type': 'application/json',
30
- 'Authorization': `Bearer ${token}`
32
+ Authorization: `Bearer ${token}`,
31
33
  },
32
34
  body: JSON.stringify(request),
33
- }).then(r => r.blob());
35
+ }).then((r) => r.blob());
34
36
  });
35
37
  }
@@ -1,14 +1,15 @@
1
- export * from "../fromRimori/PluginTypes";
2
- export * from "../plugin/PluginController";
3
- export * from "../plugin/RimoriClient";
4
- export * from "../utils/difficultyConverter";
5
- export * from "../utils/Language";
6
- export * from "../utils/PluginUtils";
7
- export * from "../worker/WorkerSetup";
8
- export { EventBusMessage } from "../fromRimori/EventBus";
9
- export { Buddy, UserInfo } from "./controller/SettingsController";
10
- export { SharedContent } from "./controller/SharedContentController";
11
- export { Message, OnLLMResponse, ToolInvocation } from "./controller/AIController";
12
- export { MacroAccomplishmentPayload, MicroAccomplishmentPayload } from "../plugin/AccomplishmentHandler";
13
- export { Tool } from "../fromRimori/PluginTypes";
14
- export { SharedContentObjectRequest } from "./controller/SharedContentController";
1
+ export * from '../fromRimori/PluginTypes';
2
+ export * from '../plugin/PluginController';
3
+ export * from '../plugin/RimoriClient';
4
+ export * from '../utils/difficultyConverter';
5
+ export * from '../utils/Language';
6
+ export * from '../utils/PluginUtils';
7
+ export * from '../worker/WorkerSetup';
8
+ export { EventBusMessage } from '../fromRimori/EventBus';
9
+ export { Buddy, UserInfo } from './controller/SettingsController';
10
+ export { SharedContent } from './controller/SharedContentController';
11
+ export { Exercise, TriggerAction } from './controller/ExerciseController';
12
+ export { Message, OnLLMResponse, ToolInvocation } from './controller/AIController';
13
+ export { MacroAccomplishmentPayload, MicroAccomplishmentPayload } from '../plugin/AccomplishmentHandler';
14
+ export { Tool } from '../fromRimori/PluginTypes';
15
+ export { SharedContentObjectRequest } from './controller/SharedContentController';
package/dist/core/core.js CHANGED
@@ -1,8 +1,8 @@
1
1
  // Core functionality exports
2
- export * from "../fromRimori/PluginTypes";
3
- export * from "../plugin/PluginController";
4
- export * from "../plugin/RimoriClient";
5
- export * from "../utils/difficultyConverter";
6
- export * from "../utils/Language";
7
- export * from "../utils/PluginUtils";
8
- export * from "../worker/WorkerSetup";
2
+ export * from '../fromRimori/PluginTypes';
3
+ export * from '../plugin/PluginController';
4
+ export * from '../plugin/RimoriClient';
5
+ export * from '../utils/difficultyConverter';
6
+ export * from '../utils/Language';
7
+ export * from '../utils/PluginUtils';
8
+ export * from '../worker/WorkerSetup';
@@ -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;
@@ -67,7 +67,7 @@ export class EventBusHandler {
67
67
  }
68
68
  const event = this.createEvent(sender, topic, data, eventId);
69
69
  const handlers = this.getMatchingHandlers(event.topic);
70
- handlers.forEach(handler => {
70
+ handlers.forEach((handler) => {
71
71
  if (handler.ignoreSender && handler.ignoreSender.includes(sender)) {
72
72
  // console.log("ignore event as its in the ignoreSender list", { event, ignoreList: handler.ignoreSender });
73
73
  return;
@@ -93,7 +93,7 @@ export class EventBusHandler {
93
93
  * @returns An EventListener object containing an off() method to unsubscribe the listeners.
94
94
  */
95
95
  on(topics, handler, ignoreSender = []) {
96
- const ids = this.toArray(topics).map(topic => {
96
+ const ids = this.toArray(topics).map((topic) => {
97
97
  this.logIfDebug(`Subscribing to ` + topic, { ignoreSender });
98
98
  if (!this.validateTopic(topic)) {
99
99
  this.logAndThrowError(true, `Invalid topic: ` + topic);
@@ -109,7 +109,7 @@ export class EventBusHandler {
109
109
  return btoa(JSON.stringify({ topic, id }));
110
110
  });
111
111
  return {
112
- off: () => this.off(ids)
112
+ off: () => this.off(ids),
113
113
  };
114
114
  }
115
115
  /**
@@ -121,10 +121,10 @@ export class EventBusHandler {
121
121
  */
122
122
  respond(sender, topic, handler) {
123
123
  const topics = Array.isArray(topic) ? topic : [topic];
124
- const listeners = topics.map(topic => {
124
+ const listeners = topics.map((topic) => {
125
125
  const blackListedEventIds = [];
126
126
  //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
127
- const finalIgnoreSender = !topic.startsWith("self.") ? [sender] : [];
127
+ const finalIgnoreSender = !topic.startsWith('self.') ? [sender] : [];
128
128
  const listener = this.on(topic, (data) => __awaiter(this, void 0, void 0, function* () {
129
129
  if (blackListedEventIds.includes(data.eventId)) {
130
130
  // console.log("BLACKLISTED EVENT ID", data.eventId);
@@ -134,16 +134,16 @@ export class EventBusHandler {
134
134
  if (blackListedEventIds.length > 20) {
135
135
  blackListedEventIds.shift();
136
136
  }
137
- const response = typeof handler === "function" ? yield handler(data) : handler;
137
+ const response = typeof handler === 'function' ? yield handler(data) : handler;
138
138
  this.emit(sender, topic, response, data.eventId);
139
139
  }), finalIgnoreSender);
140
- this.logIfDebug(`Added respond listener ` + sender + " to topic " + topic, { listener, sender });
140
+ this.logIfDebug(`Added respond listener ` + sender + ' to topic ' + topic, { listener, sender });
141
141
  return {
142
- off: () => listener.off()
142
+ off: () => listener.off(),
143
143
  };
144
144
  });
145
145
  return {
146
- off: () => listeners.forEach(listener => listener.off())
146
+ off: () => listeners.forEach((listener) => listener.off()),
147
147
  };
148
148
  }
149
149
  /**
@@ -169,10 +169,10 @@ export class EventBusHandler {
169
169
  * @param listenerIds - The ids of the listeners to unsubscribe from.
170
170
  */
171
171
  off(listenerIds) {
172
- this.toArray(listenerIds).forEach(fullId => {
172
+ this.toArray(listenerIds).forEach((fullId) => {
173
173
  const { topic, id } = JSON.parse(atob(fullId));
174
174
  const listeners = this.listeners.get(topic) || new Set();
175
- listeners.forEach(listener => {
175
+ listeners.forEach((listener) => {
176
176
  if (listener.id === Number(id)) {
177
177
  listeners.delete(listener);
178
178
  this.logIfDebug(`Removed listener ` + fullId, { topic, listenerId: id });
@@ -197,7 +197,7 @@ export class EventBusHandler {
197
197
  }
198
198
  const event = this.createEvent(sender, topic, data || {});
199
199
  this.logIfDebug(`Requesting data from ` + topic, { event });
200
- return new Promise(resolve => {
200
+ return new Promise((resolve) => {
201
201
  this.responseResolvers.set(event.eventId, (value) => resolve(value));
202
202
  this.emitInternal(sender, topic, data || {}, event.eventId, true);
203
203
  });
@@ -212,7 +212,7 @@ export class EventBusHandler {
212
212
  const exact = this.listeners.get(topic) || new Set();
213
213
  // Find wildcard matches
214
214
  const wildcard = [...this.listeners.entries()]
215
- .filter(([key]) => key.endsWith("*") && topic.startsWith(key.slice(0, -1)))
215
+ .filter(([key]) => key.endsWith('*') && topic.startsWith(key.slice(0, -1)))
216
216
  .flatMap(([_, handlers]) => [...handlers]);
217
217
  return new Set([...exact, ...wildcard]);
218
218
  }
@@ -223,27 +223,27 @@ export class EventBusHandler {
223
223
  */
224
224
  validateTopic(topic) {
225
225
  // Split event type into parts
226
- const parts = topic.split(".");
226
+ const parts = topic.split('.');
227
227
  const [plugin, area, action] = parts;
228
228
  if (parts.length !== 3) {
229
- if (parts.length === 1 && plugin === "*") {
229
+ if (parts.length === 1 && plugin === '*') {
230
230
  return true;
231
231
  }
232
- if (parts.length === 2 && plugin !== "*" && area === "*") {
232
+ if (parts.length === 2 && plugin !== '*' && area === '*') {
233
233
  return true;
234
234
  }
235
235
  this.logAndThrowError(false, `Event type must have 3 parts separated by dots. Received: ` + topic);
236
236
  return false;
237
237
  }
238
- if (action === "*") {
238
+ if (action === '*') {
239
239
  return true;
240
240
  }
241
241
  // Validate action part
242
- const validActions = ["request", "create", "update", "delete", "trigger"];
243
- if (validActions.some(a => action.startsWith(a))) {
242
+ const validActions = ['request', 'create', 'update', 'delete', 'trigger'];
243
+ if (validActions.some((a) => action.startsWith(a))) {
244
244
  return true;
245
245
  }
246
- this.logAndThrowError(false, `Invalid event topic name. The action: ` + action + ". Must be or start with one of: " + validActions.join(", "));
246
+ this.logAndThrowError(false, `Invalid event topic name. The action: ` + action + '. Must be or start with one of: ' + validActions.join(', '));
247
247
  return false;
248
248
  }
249
249
  logIfDebug(...args) {
@@ -3,7 +3,7 @@ export type Plugin<T extends {} = {}> = Omit<RimoriPluginConfig<T>, 'context_men
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;
@@ -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
  }
@@ -1,6 +1,6 @@
1
- import React from "react";
2
- import { Tool } from "../fromRimori/PluginTypes";
3
- import { Message } from "../core/controller/AIController";
1
+ import React from 'react';
2
+ import { Tool } from '../fromRimori/PluginTypes';
3
+ import { Message } from '../core/controller/AIController';
4
4
  export declare function useChat(tools?: Tool[]): {
5
5
  messages: Message[];
6
6
  append: (appendMessages: Message[]) => void;
@@ -1,5 +1,5 @@
1
- import React from "react";
2
- import { useRimori } from "../providers/PluginProvider";
1
+ import React from 'react';
2
+ import { useRimori } from '../providers/PluginProvider';
3
3
  export function useChat(tools) {
4
4
  const [messages, setMessages] = React.useState([]);
5
5
  const [isLoading, setIsLoading] = React.useState(false);
@@ -19,5 +19,11 @@ export function useChat(tools) {
19
19
  }
20
20
  }, tools);
21
21
  };
22
- return { messages, append, isLoading, setMessages, lastMessage: messages[messages.length - 1] };
22
+ return {
23
+ messages,
24
+ append,
25
+ isLoading,
26
+ setMessages,
27
+ lastMessage: messages[messages.length - 1],
28
+ };
23
29
  }
package/dist/index.d.ts CHANGED
@@ -1,11 +1,11 @@
1
1
  export * from './components';
2
- export * from "./hooks/UseChatHook";
3
- export * from "./plugin/PluginController";
4
- export * from "./providers/PluginProvider";
5
- export * from "./cli/types/DatabaseTypes";
6
- export * from "./utils/difficultyConverter";
7
- export * from "./utils/PluginUtils";
8
- export * from "./utils/Language";
9
- export * from "./fromRimori/PluginTypes";
10
- export { FirstMessages } from "./components/ai/utils";
11
- export { AudioController } from "./plugin/AudioController";
2
+ export * from './hooks/UseChatHook';
3
+ export * from './plugin/PluginController';
4
+ export * from './providers/PluginProvider';
5
+ export * from './cli/types/DatabaseTypes';
6
+ export * from './utils/difficultyConverter';
7
+ export * from './utils/PluginUtils';
8
+ export * from './utils/Language';
9
+ export * from './fromRimori/PluginTypes';
10
+ export { FirstMessages } from './components/ai/utils';
11
+ export { AudioController } from './plugin/AudioController';
package/dist/index.js CHANGED
@@ -1,11 +1,11 @@
1
1
  // Re-export everything
2
2
  export * from './components';
3
- export * from "./hooks/UseChatHook";
4
- export * from "./plugin/PluginController";
5
- export * from "./providers/PluginProvider";
6
- export * from "./cli/types/DatabaseTypes";
7
- export * from "./utils/difficultyConverter";
8
- export * from "./utils/PluginUtils";
9
- export * from "./utils/Language";
10
- export * from "./fromRimori/PluginTypes";
11
- export { AudioController } from "./plugin/AudioController";
3
+ export * from './hooks/UseChatHook';
4
+ export * from './plugin/PluginController';
5
+ export * from './providers/PluginProvider';
6
+ export * from './cli/types/DatabaseTypes';
7
+ export * from './utils/difficultyConverter';
8
+ export * from './utils/PluginUtils';
9
+ export * from './utils/Language';
10
+ export * from './fromRimori/PluginTypes';
11
+ export { AudioController } from './plugin/AudioController';
@@ -1,8 +1,8 @@
1
- import { EventBusMessage } from "../fromRimori/EventBus";
1
+ import { EventBusMessage } from '../fromRimori/EventBus';
2
2
  export type AccomplishmentMessage = EventBusMessage<MicroAccomplishmentPayload>;
3
3
  export declare const skillCategories: readonly ["reading", "listening", "speaking", "writing", "learning", "community"];
4
4
  interface BaseAccomplishmentPayload {
5
- type: "micro" | "macro";
5
+ type: 'micro' | 'macro';
6
6
  skillCategory: (typeof skillCategories)[number];
7
7
  accomplishmentKeyword: string;
8
8
  description: string;
@@ -13,10 +13,10 @@ interface BaseAccomplishmentPayload {
13
13
  }[];
14
14
  }
15
15
  export interface MicroAccomplishmentPayload extends BaseAccomplishmentPayload {
16
- type: "micro";
16
+ type: 'micro';
17
17
  }
18
18
  export interface MacroAccomplishmentPayload extends BaseAccomplishmentPayload {
19
- type: "macro";
19
+ type: 'macro';
20
20
  errorRatio: number;
21
21
  durationMinutes: number;
22
22
  }
@@ -24,7 +24,7 @@ export type AccomplishmentPayload = MicroAccomplishmentPayload | MacroAccomplish
24
24
  export declare class AccomplishmentHandler {
25
25
  private pluginId;
26
26
  constructor(pluginId: string);
27
- emitAccomplishment(payload: Omit<AccomplishmentPayload, "type">): void;
27
+ emitAccomplishment(payload: Omit<AccomplishmentPayload, 'type'>): void;
28
28
  private validateAccomplishment;
29
29
  private sanitizeAccomplishment;
30
30
  private getDecoupledTopic;