@rimori/react-client 0.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 (139) hide show
  1. package/.prettierignore +35 -0
  2. package/LICENSE +201 -0
  3. package/README copy.md +1216 -0
  4. package/README.md +1 -0
  5. package/dist/components/MarkdownEditor.d.ts +8 -0
  6. package/dist/components/MarkdownEditor.js +48 -0
  7. package/dist/components/Spinner.d.ts +8 -0
  8. package/dist/components/Spinner.js +4 -0
  9. package/dist/components/ai/Assistant.d.ts +9 -0
  10. package/dist/components/ai/Assistant.js +58 -0
  11. package/dist/components/ai/Avatar.d.ts +14 -0
  12. package/dist/components/ai/Avatar.js +59 -0
  13. package/dist/components/ai/EmbeddedAssistent/AudioInputField.d.ts +7 -0
  14. package/dist/components/ai/EmbeddedAssistent/AudioInputField.js +37 -0
  15. package/dist/components/ai/EmbeddedAssistent/CircleAudioAvatar.d.ts +8 -0
  16. package/dist/components/ai/EmbeddedAssistent/CircleAudioAvatar.js +79 -0
  17. package/dist/components/ai/EmbeddedAssistent/TTS/MessageSender.d.ts +19 -0
  18. package/dist/components/ai/EmbeddedAssistent/TTS/MessageSender.js +91 -0
  19. package/dist/components/ai/EmbeddedAssistent/TTS/Player.d.ts +27 -0
  20. package/dist/components/ai/EmbeddedAssistent/TTS/Player.js +185 -0
  21. package/dist/components/ai/EmbeddedAssistent/VoiceRecoder.d.ts +11 -0
  22. package/dist/components/ai/EmbeddedAssistent/VoiceRecoder.js +95 -0
  23. package/dist/components/ai/utils.d.ts +6 -0
  24. package/dist/components/ai/utils.js +13 -0
  25. package/dist/components/audio/Playbutton.d.ts +15 -0
  26. package/dist/components/audio/Playbutton.js +80 -0
  27. package/dist/components/components/ContextMenu.d.ts +10 -0
  28. package/dist/components/components/ContextMenu.js +135 -0
  29. package/dist/hooks/I18nHooks.d.ts +11 -0
  30. package/dist/hooks/I18nHooks.js +25 -0
  31. package/dist/hooks/UseChatHook.d.ts +10 -0
  32. package/dist/hooks/UseChatHook.js +29 -0
  33. package/dist/providers/PluginProvider.d.ts +11 -0
  34. package/dist/providers/PluginProvider.js +142 -0
  35. package/dist/react-client/plugin/ThemeSetter.d.ts +2 -0
  36. package/dist/react-client/plugin/ThemeSetter.js +19 -0
  37. package/dist/react-client/src/components/ContextMenu.d.ts +10 -0
  38. package/dist/react-client/src/components/ContextMenu.js +135 -0
  39. package/dist/react-client/src/components/MarkdownEditor.d.ts +8 -0
  40. package/dist/react-client/src/components/MarkdownEditor.js +48 -0
  41. package/dist/react-client/src/components/Spinner.d.ts +8 -0
  42. package/dist/react-client/src/components/Spinner.js +4 -0
  43. package/dist/react-client/src/components/ai/Assistant.d.ts +9 -0
  44. package/dist/react-client/src/components/ai/Assistant.js +58 -0
  45. package/dist/react-client/src/components/ai/Avatar.d.ts +14 -0
  46. package/dist/react-client/src/components/ai/Avatar.js +59 -0
  47. package/dist/react-client/src/components/ai/EmbeddedAssistent/AudioInputField.d.ts +7 -0
  48. package/dist/react-client/src/components/ai/EmbeddedAssistent/AudioInputField.js +37 -0
  49. package/dist/react-client/src/components/ai/EmbeddedAssistent/CircleAudioAvatar.d.ts +8 -0
  50. package/dist/react-client/src/components/ai/EmbeddedAssistent/CircleAudioAvatar.js +79 -0
  51. package/dist/react-client/src/components/ai/EmbeddedAssistent/TTS/MessageSender.d.ts +19 -0
  52. package/dist/react-client/src/components/ai/EmbeddedAssistent/TTS/MessageSender.js +91 -0
  53. package/dist/react-client/src/components/ai/EmbeddedAssistent/TTS/Player.d.ts +27 -0
  54. package/dist/react-client/src/components/ai/EmbeddedAssistent/TTS/Player.js +185 -0
  55. package/dist/react-client/src/components/ai/EmbeddedAssistent/VoiceRecoder.d.ts +11 -0
  56. package/dist/react-client/src/components/ai/EmbeddedAssistent/VoiceRecoder.js +95 -0
  57. package/dist/react-client/src/components/ai/utils.d.ts +6 -0
  58. package/dist/react-client/src/components/ai/utils.js +13 -0
  59. package/dist/react-client/src/components/audio/Playbutton.d.ts +15 -0
  60. package/dist/react-client/src/components/audio/Playbutton.js +82 -0
  61. package/dist/react-client/src/components/components/ContextMenu.d.ts +10 -0
  62. package/dist/react-client/src/components/components/ContextMenu.js +135 -0
  63. package/dist/react-client/src/hooks/I18nHooks.d.ts +11 -0
  64. package/dist/react-client/src/hooks/I18nHooks.js +25 -0
  65. package/dist/react-client/src/hooks/UseChatHook.d.ts +10 -0
  66. package/dist/react-client/src/hooks/UseChatHook.js +29 -0
  67. package/dist/react-client/src/plugin/ThemeSetter.d.ts +2 -0
  68. package/dist/react-client/src/plugin/ThemeSetter.js +19 -0
  69. package/dist/react-client/src/providers/PluginProvider.d.ts +12 -0
  70. package/dist/react-client/src/providers/PluginProvider.js +142 -0
  71. package/dist/react-client/src/utils/FullscreenUtils.d.ts +2 -0
  72. package/dist/react-client/src/utils/FullscreenUtils.js +23 -0
  73. package/dist/react-client/src/utils/PluginUtils.d.ts +2 -0
  74. package/dist/react-client/src/utils/PluginUtils.js +23 -0
  75. package/dist/rimori-client/src/cli/types/DatabaseTypes.d.ts +103 -0
  76. package/dist/rimori-client/src/cli/types/DatabaseTypes.js +2 -0
  77. package/dist/rimori-client/src/controller/AIController.d.ts +15 -0
  78. package/dist/rimori-client/src/controller/AIController.js +255 -0
  79. package/dist/rimori-client/src/controller/AccomplishmentController.d.ts +38 -0
  80. package/dist/rimori-client/src/controller/AccomplishmentController.js +112 -0
  81. package/dist/rimori-client/src/controller/AudioController.d.ts +37 -0
  82. package/dist/rimori-client/src/controller/AudioController.js +68 -0
  83. package/dist/rimori-client/src/controller/ExerciseController.d.ts +54 -0
  84. package/dist/rimori-client/src/controller/ExerciseController.js +74 -0
  85. package/dist/rimori-client/src/controller/ObjectController.d.ts +42 -0
  86. package/dist/rimori-client/src/controller/ObjectController.js +76 -0
  87. package/dist/rimori-client/src/controller/SettingsController.d.ts +79 -0
  88. package/dist/rimori-client/src/controller/SettingsController.js +118 -0
  89. package/dist/rimori-client/src/controller/SharedContentController.d.ts +106 -0
  90. package/dist/rimori-client/src/controller/SharedContentController.js +285 -0
  91. package/dist/rimori-client/src/controller/TranslationController.d.ts +38 -0
  92. package/dist/rimori-client/src/controller/TranslationController.js +106 -0
  93. package/dist/rimori-client/src/controller/VoiceController.d.ts +9 -0
  94. package/dist/rimori-client/src/controller/VoiceController.js +37 -0
  95. package/dist/rimori-client/src/fromRimori/EventBus.d.ts +101 -0
  96. package/dist/rimori-client/src/fromRimori/EventBus.js +263 -0
  97. package/dist/rimori-client/src/fromRimori/PluginTypes.d.ts +174 -0
  98. package/dist/rimori-client/src/fromRimori/PluginTypes.js +1 -0
  99. package/dist/rimori-client/src/index.d.ts +11 -0
  100. package/dist/rimori-client/src/index.js +10 -0
  101. package/dist/rimori-client/src/plugin/CommunicationHandler.d.ts +48 -0
  102. package/dist/rimori-client/src/plugin/CommunicationHandler.js +234 -0
  103. package/dist/rimori-client/src/plugin/Logger.d.ts +73 -0
  104. package/dist/rimori-client/src/plugin/Logger.js +308 -0
  105. package/dist/rimori-client/src/plugin/RimoriClient.d.ts +258 -0
  106. package/dist/rimori-client/src/plugin/RimoriClient.js +375 -0
  107. package/dist/rimori-client/src/plugin/StandaloneClient.d.ts +17 -0
  108. package/dist/rimori-client/src/plugin/StandaloneClient.js +115 -0
  109. package/dist/rimori-client/src/utils/difficultyConverter.d.ts +4 -0
  110. package/dist/rimori-client/src/utils/difficultyConverter.js +10 -0
  111. package/dist/rimori-client/src/utils/endpoint.d.ts +2 -0
  112. package/dist/rimori-client/src/utils/endpoint.js +2 -0
  113. package/dist/style.css +110 -0
  114. package/dist/style.css.map +1 -0
  115. package/dist/utils/PluginUtils.d.ts +2 -0
  116. package/dist/utils/PluginUtils.js +23 -0
  117. package/eslint.config.js +53 -0
  118. package/index.ts +6 -0
  119. package/package.json +47 -0
  120. package/prettier.config.js +8 -0
  121. package/src/components/ContextMenu.tsx +177 -0
  122. package/src/components/MarkdownEditor.tsx +144 -0
  123. package/src/components/Spinner.tsx +29 -0
  124. package/src/components/ai/Assistant.tsx +96 -0
  125. package/src/components/ai/Avatar.tsx +99 -0
  126. package/src/components/ai/EmbeddedAssistent/AudioInputField.tsx +73 -0
  127. package/src/components/ai/EmbeddedAssistent/CircleAudioAvatar.tsx +107 -0
  128. package/src/components/ai/EmbeddedAssistent/TTS/MessageSender.ts +96 -0
  129. package/src/components/ai/EmbeddedAssistent/TTS/Player.ts +197 -0
  130. package/src/components/ai/EmbeddedAssistent/VoiceRecoder.tsx +129 -0
  131. package/src/components/ai/utils.ts +21 -0
  132. package/src/components/audio/Playbutton.tsx +126 -0
  133. package/src/hooks/I18nHooks.ts +33 -0
  134. package/src/hooks/UseChatHook.ts +38 -0
  135. package/src/plugin/ThemeSetter.ts +23 -0
  136. package/src/providers/PluginProvider.tsx +197 -0
  137. package/src/style.scss +136 -0
  138. package/src/utils/FullscreenUtils.ts +22 -0
  139. package/tsconfig.json +23 -0
@@ -0,0 +1,285 @@
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
+ export class SharedContentController {
11
+ constructor(supabase, rimoriClient) {
12
+ this.supabase = supabase;
13
+ this.rimoriClient = rimoriClient;
14
+ }
15
+ /**
16
+ * Fetch new shared content for a given content type.
17
+ * @param contentType - The type of content to fetch.
18
+ * @param generatorInstructions - The instructions for the generator. The object needs to have a tool property with a topic and keywords property to let a new unique topic be generated.
19
+ * @param filter - An optional filter to apply to the query.
20
+ * @param options - Optional options.
21
+ * @param options.privateTopic - If the topic should be private and only be visible to the user.
22
+ * @param options.skipDbSave - If true, do not persist a newly generated content to the DB (default false).
23
+ * @param options.alwaysGenerateNew - If true, always generate a new content even if there is already a content with the same filter.
24
+ * @param options.excludeIds - Optional list of shared_content ids to exclude from selection.
25
+ * @returns The new shared content.
26
+ */
27
+ getNewSharedContent(contentType, generatorInstructions,
28
+ //this filter is there if the content should be filtered additionally by a column and value
29
+ filter, options) {
30
+ return __awaiter(this, void 0, void 0, function* () {
31
+ let query = this.supabase
32
+ .from('shared_content')
33
+ .select('*, scc:shared_content_completed(id, state)')
34
+ .eq('content_type', contentType)
35
+ .not('scc.state', 'in', '("completed","ongoing","hidden")')
36
+ .is('deleted_at', null);
37
+ if ((options === null || options === void 0 ? void 0 : options.excludeIds) && options.excludeIds.length > 0) {
38
+ const excludeIds = options.excludeIds.filter((id) => !id.startsWith('internal-temp-id-'));
39
+ // Supabase expects raw PostgREST syntax like '("id1","id2")'.
40
+ const excludeList = `(${excludeIds.map((id) => `"${id}"`).join(',')})`;
41
+ query = query.not('id', 'in', excludeList);
42
+ }
43
+ if (filter) {
44
+ query.contains('data', filter);
45
+ }
46
+ const { data: newAssignments, error } = yield query.limit(30);
47
+ if (error) {
48
+ console.error('error fetching new assignments:', error);
49
+ throw new Error('error fetching new assignments');
50
+ }
51
+ // console.log('newAssignments:', newAssignments);
52
+ if (!(options === null || options === void 0 ? void 0 : options.alwaysGenerateNew) && newAssignments.length > 0) {
53
+ const index = Math.floor(Math.random() * newAssignments.length);
54
+ return newAssignments[index];
55
+ }
56
+ const instructions = yield this.generateNewAssignment(contentType, generatorInstructions, filter);
57
+ console.log('instructions:', instructions);
58
+ //create the shared content object
59
+ const data = {
60
+ id: 'internal-temp-id-' + Math.random().toString(36).substring(2, 15),
61
+ contentType,
62
+ title: instructions.title,
63
+ keywords: instructions.keywords.map(({ text }) => text),
64
+ data: Object.assign(Object.assign(Object.assign({}, instructions), { title: undefined, keywords: undefined }), generatorInstructions.fixedProperties),
65
+ privateTopic: options === null || options === void 0 ? void 0 : options.privateTopic,
66
+ };
67
+ if (options === null || options === void 0 ? void 0 : options.skipDbSave) {
68
+ return data;
69
+ }
70
+ return yield this.createSharedContent(data);
71
+ });
72
+ }
73
+ generateNewAssignment(contentType, generatorInstructions, filter) {
74
+ return __awaiter(this, void 0, void 0, function* () {
75
+ const fullInstructions = yield this.getGeneratorInstructions(contentType, generatorInstructions, filter);
76
+ console.log('fullInstructions:', fullInstructions);
77
+ return yield this.rimoriClient.ai.getObject(fullInstructions);
78
+ });
79
+ }
80
+ getGeneratorInstructions(contentType, generatorInstructions, filter) {
81
+ return __awaiter(this, void 0, void 0, function* () {
82
+ const completedTopics = yield this.getCompletedTopics(contentType, filter);
83
+ generatorInstructions.instructions += `
84
+ The following topics are already taken: ${completedTopics.join(', ')}`;
85
+ generatorInstructions.tool.title = {
86
+ type: 'string',
87
+ description: 'What the topic is about. Short. ',
88
+ };
89
+ generatorInstructions.tool.keywords = {
90
+ type: [{ text: { type: 'string' } }],
91
+ description: 'Keywords around the topic of the assignment.',
92
+ };
93
+ return generatorInstructions;
94
+ });
95
+ }
96
+ getCompletedTopics(contentType, filter) {
97
+ return __awaiter(this, void 0, void 0, function* () {
98
+ const query = this.supabase
99
+ .from('shared_content')
100
+ .select('title, keywords, scc:shared_content_completed(id)')
101
+ .eq('content_type', contentType)
102
+ .not('scc.id', 'is', null)
103
+ .is('deleted_at', null);
104
+ if (filter) {
105
+ query.contains('data', filter);
106
+ }
107
+ const { data: oldAssignments, error } = yield query;
108
+ if (error) {
109
+ console.error('error fetching old assignments:', error);
110
+ return [];
111
+ }
112
+ return oldAssignments.map(({ title, keywords }) => `${title}(${keywords.join(',')})`);
113
+ });
114
+ }
115
+ getSharedContent(contentType, id) {
116
+ return __awaiter(this, void 0, void 0, function* () {
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();
124
+ if (error) {
125
+ console.error('error fetching shared content:', error);
126
+ throw new Error('error fetching shared content');
127
+ }
128
+ return data;
129
+ });
130
+ }
131
+ completeSharedContent(contentType, assignmentId) {
132
+ return __awaiter(this, void 0, void 0, function* () {
133
+ // Idempotent completion: upsert on (id, user_id) so repeated calls don't fail
134
+ const { error } = yield this.supabase
135
+ .from('shared_content_completed')
136
+ .upsert({ content_type: contentType, id: assignmentId }, { onConflict: 'id' });
137
+ if (error) {
138
+ console.error('error completing shared content:', error);
139
+ throw new Error('error completing shared content');
140
+ }
141
+ });
142
+ }
143
+ /**
144
+ * Update state details for a shared content entry in shared_content_completed.
145
+ * Assumes table has columns: state ('completed'|'ongoing'|'hidden'), reaction ('liked'|'disliked'|null), bookmarked boolean.
146
+ * Upserts per (id, content_type, user).
147
+ * @param param
148
+ * @param param.contentType - The content type.
149
+ * @param param.id - The shared content id.
150
+ * @param param.state - The state to set.
151
+ * @param param.reaction - Optional reaction.
152
+ * @param param.bookmarked - Optional bookmark flag.
153
+ */
154
+ updateSharedContentState(_a) {
155
+ return __awaiter(this, arguments, void 0, function* ({ contentType, id, state, reaction, bookmarked, }) {
156
+ const payload = { content_type: contentType, id };
157
+ if (state !== undefined)
158
+ payload.state = state;
159
+ if (reaction !== undefined)
160
+ payload.reaction = reaction;
161
+ if (bookmarked !== undefined)
162
+ payload.bookmarked = bookmarked;
163
+ // Prefer upsert, fall back to insert/update if upsert not allowed
164
+ const { error } = yield this.supabase.from('shared_content_completed').upsert(payload, { onConflict: 'id' });
165
+ if (error) {
166
+ console.error('error updating shared content state:', error);
167
+ throw new Error('error updating shared content state');
168
+ }
169
+ });
170
+ }
171
+ /**
172
+ * Fetch shared content from the database based on optional filters.
173
+ * @param contentType - The type of content to fetch.
174
+ * @param filter - Optional filter to apply to the query.
175
+ * @param limit - Optional limit for the number of results.
176
+ * @returns Array of shared content matching the criteria.
177
+ */
178
+ getSharedContentList(contentType, filter, limit) {
179
+ return __awaiter(this, void 0, void 0, function* () {
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);
186
+ if (filter) {
187
+ query.contains('data', filter);
188
+ }
189
+ const { data, error } = yield query;
190
+ if (error) {
191
+ console.error('error fetching shared content:', error);
192
+ throw new Error('error fetching shared content');
193
+ }
194
+ return data;
195
+ });
196
+ }
197
+ /**
198
+ * Insert new shared content into the database.
199
+ * @param param
200
+ * @param param.contentType - The type of content to insert.
201
+ * @param param.title - The title of the content.
202
+ * @param param.keywords - Keywords associated with the content.
203
+ * @param param.data - The content data to store.
204
+ * @param param.privateTopic - Optional flag to indicate if the topic should be private.
205
+ * @returns The inserted shared content.
206
+ * @throws {Error} if insertion fails.
207
+ */
208
+ createSharedContent(_a) {
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({
213
+ private: privateTopic,
214
+ content_type: contentType,
215
+ title,
216
+ keywords,
217
+ data,
218
+ })
219
+ .select();
220
+ if (error) {
221
+ console.error('error inserting shared content:', error);
222
+ throw new Error('error inserting shared content');
223
+ }
224
+ return newContent[0];
225
+ });
226
+ }
227
+ /**
228
+ * Update existing shared content in the database.
229
+ * @param id - The ID of the content to update.
230
+ * @param updates - The updates to apply to the shared content.
231
+ * @returns The updated shared content.
232
+ * @throws {Error} if update fails.
233
+ */
234
+ updateSharedContent(id, updates) {
235
+ return __awaiter(this, void 0, void 0, function* () {
236
+ const updateData = {};
237
+ if (updates.contentType)
238
+ updateData.content_type = updates.contentType;
239
+ if (updates.title)
240
+ updateData.title = updates.title;
241
+ if (updates.keywords)
242
+ updateData.keywords = updates.keywords;
243
+ if (updates.data)
244
+ updateData.data = updates.data;
245
+ if (updates.privateTopic !== undefined)
246
+ updateData.private = updates.privateTopic;
247
+ const { data: updatedContent, error } = yield this.supabase
248
+ .from('shared_content')
249
+ .update(updateData)
250
+ .eq('id', id)
251
+ .select();
252
+ if (error) {
253
+ console.error('error updating shared content:', error);
254
+ throw new Error('error updating shared content');
255
+ }
256
+ if (!updatedContent || updatedContent.length === 0) {
257
+ throw new Error('shared content not found');
258
+ }
259
+ return updatedContent[0];
260
+ });
261
+ }
262
+ /**
263
+ * Soft delete shared content by setting the deleted_at timestamp.
264
+ * @param id - The ID of the content to delete.
265
+ * @returns The deleted shared content record.
266
+ * @throws {Error} if deletion fails or content not found.
267
+ */
268
+ removeSharedContent(id) {
269
+ return __awaiter(this, void 0, void 0, function* () {
270
+ const { data: deletedContent, error } = yield this.supabase
271
+ .from('shared_content')
272
+ .update({ deleted_at: new Date().toISOString() })
273
+ .eq('id', id)
274
+ .select();
275
+ if (error) {
276
+ console.error('error deleting shared content:', error);
277
+ throw new Error('error deleting shared content');
278
+ }
279
+ if (!deletedContent || deletedContent.length === 0) {
280
+ throw new Error('shared content not found or already deleted');
281
+ }
282
+ return deletedContent[0];
283
+ });
284
+ }
285
+ }
@@ -0,0 +1,38 @@
1
+ import { ThirdPartyModule, TOptions } from 'i18next';
2
+ /**
3
+ * Translator class for handling internationalization
4
+ */
5
+ export declare class Translator {
6
+ private currentLanguage;
7
+ private isInitialized;
8
+ private i18n;
9
+ constructor(initialLanguage: string);
10
+ /**
11
+ * Initialize translator with user's language
12
+ * @param userLanguage - Language code from user info
13
+ */
14
+ initialize(): Promise<void>;
15
+ private getTranslationUrl;
16
+ usePlugin(plugin: ThirdPartyModule): void;
17
+ /**
18
+ * Fetch translations manually from the current domain
19
+ * @param language - Language code to fetch
20
+ * @returns Promise with translation data
21
+ */
22
+ private fetchTranslations;
23
+ /**
24
+ * Get translation for a key
25
+ * @param key - Translation key
26
+ * @param options - Translation options
27
+ * @returns Translated string
28
+ */
29
+ t(key: string, options?: TOptions): string;
30
+ /**
31
+ * Get current language
32
+ */
33
+ getCurrentLanguage(): string;
34
+ /**
35
+ * Check if translator is initialized
36
+ */
37
+ isReady(): boolean;
38
+ }
@@ -0,0 +1,106 @@
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 { createInstance } from 'i18next';
11
+ /**
12
+ * Translator class for handling internationalization
13
+ */
14
+ export class Translator {
15
+ constructor(initialLanguage) {
16
+ this.isInitialized = false;
17
+ this.currentLanguage = initialLanguage;
18
+ }
19
+ /**
20
+ * Initialize translator with user's language
21
+ * @param userLanguage - Language code from user info
22
+ */
23
+ initialize() {
24
+ return __awaiter(this, void 0, void 0, function* () {
25
+ if (this.isInitialized)
26
+ return;
27
+ const translations = yield this.fetchTranslations(this.currentLanguage);
28
+ const instance = createInstance({
29
+ lng: this.currentLanguage,
30
+ resources: {
31
+ [this.currentLanguage]: {
32
+ translation: translations,
33
+ },
34
+ },
35
+ debug: window.location.hostname === 'localhost',
36
+ });
37
+ yield instance.init();
38
+ this.i18n = instance;
39
+ this.isInitialized = true;
40
+ });
41
+ }
42
+ getTranslationUrl(language) {
43
+ // For localhost development, use local- prefix for non-English languages
44
+ if (window.location.hostname === 'localhost') {
45
+ const filename = language !== 'en' ? `local-${language}` : language;
46
+ return `${window.location.origin}/locales/${filename}.json`;
47
+ }
48
+ return `./locales/${language}.json`;
49
+ }
50
+ usePlugin(plugin) {
51
+ if (!this.i18n) {
52
+ throw new Error('Translator is not initialized');
53
+ }
54
+ this.i18n.use(plugin);
55
+ }
56
+ /**
57
+ * Fetch translations manually from the current domain
58
+ * @param language - Language code to fetch
59
+ * @returns Promise with translation data
60
+ */
61
+ fetchTranslations(language) {
62
+ return __awaiter(this, void 0, void 0, function* () {
63
+ try {
64
+ const response = yield fetch(this.getTranslationUrl(language));
65
+ if (!response.ok) {
66
+ throw new Error(`Failed to fetch translations for ${language}`);
67
+ }
68
+ return (yield response.json());
69
+ }
70
+ catch (error) {
71
+ console.warn(`Failed to fetch translations for ${language}:`, error);
72
+ if (language === 'en')
73
+ return {};
74
+ // Fallback to English
75
+ return this.fetchTranslations('en').catch((error) => {
76
+ console.error('Failed to fetch fallback translations:', error);
77
+ return {};
78
+ });
79
+ }
80
+ });
81
+ }
82
+ /**
83
+ * Get translation for a key
84
+ * @param key - Translation key
85
+ * @param options - Translation options
86
+ * @returns Translated string
87
+ */
88
+ t(key, options) {
89
+ if (!this.i18n) {
90
+ throw new Error('Translator is not initialized');
91
+ }
92
+ return this.i18n.t(key, options);
93
+ }
94
+ /**
95
+ * Get current language
96
+ */
97
+ getCurrentLanguage() {
98
+ return this.currentLanguage;
99
+ }
100
+ /**
101
+ * Check if translator is initialized
102
+ */
103
+ isReady() {
104
+ return this.isInitialized;
105
+ }
106
+ }
@@ -0,0 +1,9 @@
1
+ export declare function getSTTResponse(backendUrl: string, audio: Blob, token: string): Promise<string>;
2
+ export declare function getTTSResponse(backendUrl: string, request: TTSRequest, token: string): Promise<Blob>;
3
+ interface TTSRequest {
4
+ input: string;
5
+ voice: string;
6
+ speed: number;
7
+ language?: string;
8
+ }
9
+ export {};
@@ -0,0 +1,37 @@
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
+ export function getSTTResponse(backendUrl, audio, token) {
11
+ return __awaiter(this, void 0, void 0, function* () {
12
+ const formData = new FormData();
13
+ formData.append('file', audio);
14
+ return yield fetch(`${backendUrl}/voice/stt`, {
15
+ method: 'POST',
16
+ headers: { Authorization: `Bearer ${token}` },
17
+ body: formData,
18
+ })
19
+ .then((r) => r.json())
20
+ .then((r) => {
21
+ // console.log("STT response: ", r);
22
+ return r.text;
23
+ });
24
+ });
25
+ }
26
+ export function getTTSResponse(backendUrl, request, token) {
27
+ return __awaiter(this, void 0, void 0, function* () {
28
+ return yield fetch(`${backendUrl}/voice/tts`, {
29
+ method: 'POST',
30
+ headers: {
31
+ 'Content-Type': 'application/json',
32
+ Authorization: `Bearer ${token}`,
33
+ },
34
+ body: JSON.stringify(request),
35
+ }).then((r) => r.blob());
36
+ });
37
+ }
@@ -0,0 +1,101 @@
1
+ export type EventPayload = Record<string, any>;
2
+ /**
3
+ * Interface representing a message sent through the EventBus
4
+ *
5
+ * Debug capabilities:
6
+ * - System-wide debugging: Send an event to "global.system.requestDebug"
7
+ * Example: `EventBus.emit("yourPluginId", "global.system.requestDebug");`
8
+ */
9
+ export interface EventBusMessage<T = EventPayload> {
10
+ timestamp: string;
11
+ eventId: number;
12
+ sender: string;
13
+ topic: string;
14
+ data: T;
15
+ debug: boolean;
16
+ }
17
+ export type EventHandler<T = EventPayload> = (event: EventBusMessage<T>) => void | Promise<void>;
18
+ export interface EventListener {
19
+ off: () => void;
20
+ }
21
+ export declare class EventBusHandler {
22
+ private listeners;
23
+ private responseResolvers;
24
+ private static instance;
25
+ private debugEnabled;
26
+ private evName;
27
+ private constructor();
28
+ static getInstance(name?: string): EventBusHandler;
29
+ private createEvent;
30
+ /**
31
+ * Emits an event to the event bus. Can be a new event or a response to a request.
32
+ * @param sender - The sender of the event.
33
+ * @param topic - The topic of the event.
34
+ * @param data - The data of the event.
35
+ * @param eventId - The event id of the event.
36
+ *
37
+ * The topic format is: **pluginId.area.action**
38
+ *
39
+ * Example topics:
40
+ * - pl1234.card.requestHard
41
+ * - pl1234.card.requestNew
42
+ * - pl1234.card.requestAll
43
+ * - pl1234.card.create
44
+ * - pl1234.card.update
45
+ * - pl1234.card.delete
46
+ * - pl1234.card.triggerBackup
47
+ */
48
+ emit<T = EventPayload>(sender: string, topic: string, data?: T, eventId?: number): void;
49
+ private emitInternal;
50
+ /**
51
+ * Subscribes to an event on the event bus.
52
+ * @param topics - The topic of the event.
53
+ * @param handler - The handler to be called when the event is emitted.
54
+ * @param ignoreSender - The senders to ignore.
55
+ * @returns An EventListener object containing an off() method to unsubscribe the listeners.
56
+ */
57
+ on<T = EventPayload>(topics: string | string[], handler: EventHandler<T>, ignoreSender?: string[]): EventListener;
58
+ /**
59
+ * Subscribes to an event, processes the data and emits a response on the event bus.
60
+ * @param sender - The sender of the event.
61
+ * @param topic - The topic of the event.
62
+ * @param handler - The handler to be called when the event is received. The handler returns the data to be emitted. Can be a static object or a function.
63
+ * @returns An EventListener object containing an off() method to unsubscribe the listeners.
64
+ */
65
+ respond(sender: string, topic: string | string[], handler: EventPayload | ((data: EventBusMessage) => EventPayload | Promise<EventPayload>)): EventListener;
66
+ /**
67
+ * Subscribes to an event on the event bus. The handler will be called once and then removed.
68
+ * @param topic - The topic of the event.
69
+ * @param handler - The handler to be called when the event is emitted.
70
+ */
71
+ once<T = EventPayload>(topic: string, handler: EventHandler<T>): void;
72
+ /**
73
+ * Unsubscribes from an event on the event bus.
74
+ * @param listenerIds - The ids of the listeners to unsubscribe from.
75
+ */
76
+ private off;
77
+ private toArray;
78
+ /**
79
+ * Requests data from the event bus.
80
+ * @param sender - The sender of the event.
81
+ * @param topic - The topic of the event.
82
+ * @param data - The data of the event.
83
+ * @returns A promise that resolves to the event.
84
+ */
85
+ request<T = EventPayload>(sender: string, topic: string, data?: EventPayload): Promise<EventBusMessage<T>>;
86
+ /**
87
+ * Gets the matching handlers for an event.
88
+ * @param topic - The topic of the event.
89
+ * @returns A set of handlers that match the event type.
90
+ */
91
+ private getMatchingHandlers;
92
+ /**
93
+ * Validates the topic of an event.
94
+ * @param topic - The topic of the event.
95
+ * @returns True if the topic is valid, false otherwise.
96
+ */
97
+ private validateTopic;
98
+ private logIfDebug;
99
+ private logAndThrowError;
100
+ }
101
+ export declare const EventBus: EventBusHandler;