@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,258 @@
1
+ import { PostgrestQueryBuilder } from '@supabase/postgrest-js';
2
+ import { GenericSchema } from '@supabase/supabase-js/dist/module/lib/types';
3
+ import { Message, OnLLMResponse } from '../controller/AIController';
4
+ import { ObjectRequest } from '../controller/ObjectController';
5
+ import { UserInfo } from '../controller/SettingsController';
6
+ import { SharedContent, SharedContentFilter, SharedContentObjectRequest } from '../controller/SharedContentController';
7
+ import { CreateExerciseParams } from '../controller/ExerciseController';
8
+ import { EventBusMessage, EventHandler, EventPayload } from '../fromRimori/EventBus';
9
+ import { ActivePlugin, MainPanelAction, Plugin, Tool } from '../fromRimori/PluginTypes';
10
+ import { AccomplishmentPayload } from '../controller/AccomplishmentController';
11
+ import { Translator } from '../controller/TranslationController';
12
+ export declare class RimoriClient {
13
+ private static instance;
14
+ private superbase;
15
+ private pluginController;
16
+ private settingsController;
17
+ private sharedContentController;
18
+ private exerciseController;
19
+ private accomplishmentHandler;
20
+ private rimoriInfo;
21
+ private translator;
22
+ private constructor();
23
+ get plugin(): {
24
+ pluginId: string;
25
+ /**
26
+ * Set the settings for the plugin.
27
+ * @param settings The settings to set.
28
+ */
29
+ setSettings: (settings: any) => Promise<void>;
30
+ /**
31
+ * Get the settings for the plugin. T can be any type of settings, UserSettings or SystemSettings.
32
+ * @param defaultSettings The default settings to use if no settings are found.
33
+ * @param genericSettings The type of settings to get.
34
+ * @returns The settings for the plugin.
35
+ */
36
+ getSettings: <T extends object>(defaultSettings: T) => Promise<T>;
37
+ getUserInfo: () => UserInfo;
38
+ /**
39
+ * Retrieves information about plugins, including:
40
+ * - All installed plugins
41
+ * - The currently active plugin in the main panel
42
+ * - The currently active plugin in the side panel
43
+ */
44
+ getPluginInfo: () => {
45
+ /**
46
+ * All installed plugins.
47
+ */
48
+ installedPlugins: Plugin[];
49
+ /**
50
+ * The plugin that is loaded in the main panel.
51
+ */
52
+ mainPanelPlugin?: ActivePlugin;
53
+ /**
54
+ * The plugin that is loaded in the side panel.
55
+ */
56
+ sidePanelPlugin?: ActivePlugin;
57
+ };
58
+ /**
59
+ * Get the translator for the plugin.
60
+ * @returns The translator for the plugin.
61
+ */
62
+ getTranslator: () => Promise<Translator>;
63
+ };
64
+ get db(): {
65
+ from: (relation: string) => PostgrestQueryBuilder<GenericSchema, any, any>;
66
+ /**
67
+ * The table prefix for of database tables of the plugin.
68
+ */
69
+ tablePrefix: string;
70
+ /**
71
+ * Get the table name for a given plugin table.
72
+ * Internally all tables are prefixed with the plugin id. This function is used to get the correct table name for a given public table.
73
+ * @param table The plugin table name to get the full table name for.
74
+ * @returns The full table name.
75
+ */
76
+ getTableName: (table: string) => string;
77
+ };
78
+ event: {
79
+ /**
80
+ * Emit an event to Rimori or a plugin.
81
+ * The topic schema is:
82
+ * {pluginId}.{eventId}
83
+ * Check out the event bus documentation for more information.
84
+ * For triggering events from Rimori like context menu actions use the "global" keyword.
85
+ * @param topic The topic to emit the event on.
86
+ * @param data The data to emit.
87
+ * @param eventId The event id.
88
+ */
89
+ emit: (topic: string, data?: any, eventId?: number) => void;
90
+ /**
91
+ * Request an event.
92
+ * @param topic The topic to request the event on.
93
+ * @param data The data to request.
94
+ * @returns The response from the event.
95
+ */
96
+ request: <T>(topic: string, data?: any) => Promise<EventBusMessage<T>>;
97
+ /**
98
+ * Subscribe to an event.
99
+ * @param topic The topic to subscribe to.
100
+ * @param callback The callback to call when the event is emitted.
101
+ * @returns An EventListener object containing an off() method to unsubscribe the listeners.
102
+ */
103
+ on: <T = EventPayload>(topic: string | string[], callback: EventHandler<T>) => import("../fromRimori/EventBus").EventListener;
104
+ /**
105
+ * Subscribe to an event once.
106
+ * @param topic The topic to subscribe to.
107
+ * @param callback The callback to call when the event is emitted.
108
+ */
109
+ once: <T = EventPayload>(topic: string, callback: EventHandler<T>) => void;
110
+ /**
111
+ * Respond to an event.
112
+ * @param topic The topic to respond to.
113
+ * @param data The data to respond with.
114
+ */
115
+ respond: <T = EventPayload>(topic: string | string[], data: EventPayload | ((data: EventBusMessage<T>) => EventPayload | Promise<EventPayload>)) => void;
116
+ /**
117
+ * Emit an accomplishment.
118
+ * @param payload The payload to emit.
119
+ */
120
+ emitAccomplishment: (payload: AccomplishmentPayload) => void;
121
+ /**
122
+ * Subscribe to an accomplishment.
123
+ * @param accomplishmentTopic The topic to subscribe to.
124
+ * @param callback The callback to call when the accomplishment is emitted.
125
+ */
126
+ onAccomplishment: (accomplishmentTopic: string, callback: (payload: EventBusMessage<AccomplishmentPayload>) => void) => void;
127
+ /**
128
+ * Trigger an action that opens the sidebar and triggers an action in the designated plugin.
129
+ * @param pluginId The id of the plugin to trigger the action for.
130
+ * @param actionKey The key of the action to trigger.
131
+ * @param text Optional text to be used for the action like for example text that the translator would look up.
132
+ */
133
+ emitSidebarAction: (pluginId: string, actionKey: string, text?: string) => void;
134
+ onMainPanelAction: (callback: (data: MainPanelAction) => void, actionsToListen?: string[]) => void;
135
+ };
136
+ navigation: {
137
+ toDashboard: () => void;
138
+ };
139
+ /**
140
+ * Get a query parameter value that was passed via MessageChannel
141
+ * @param key The query parameter key
142
+ * @returns The query parameter value or null if not found
143
+ */
144
+ getQueryParam(key: string): string | null;
145
+ static getInstance(pluginId?: string): Promise<RimoriClient>;
146
+ ai: {
147
+ getText: (messages: Message[], tools?: Tool[]) => Promise<string>;
148
+ getSteamedText: (messages: Message[], onMessage: OnLLMResponse, tools?: Tool[]) => Promise<void>;
149
+ getVoice: (text: string, voice?: string, speed?: number, language?: string) => Promise<Blob>;
150
+ getTextFromVoice: (file: Blob) => Promise<string>;
151
+ getObject: <T = any>(request: ObjectRequest) => Promise<T>;
152
+ };
153
+ runtime: {
154
+ fetchBackend: (url: string, options: RequestInit) => Promise<Response>;
155
+ };
156
+ community: {
157
+ /**
158
+ * Shared content is a way to share completable content with other users using this plugin.
159
+ * Typical examples are assignments, exercises, stories, etc.
160
+ * Users generate new shared content items and others can complete the content too.
161
+ */
162
+ sharedContent: {
163
+ /**
164
+ * Get one dedicated shared content item by id. It does not matter if it is completed or not.
165
+ * @param contentType The type of shared content to get. E.g. assignments, exercises, etc.
166
+ * @param id The id of the shared content item.
167
+ * @returns The shared content item.
168
+ */
169
+ get: <T = any>(contentType: string, id: string) => Promise<SharedContent<T>>;
170
+ /**
171
+ * Get a list of shared content items.
172
+ * @param contentType The type of shared content to get. E.g. assignments, exercises, etc.
173
+ * @param filter The optional additional filter for checking new shared content based on a column and value. This is useful if the aditional information stored on the shared content is used to further narrow down the kind of shared content wanted to be received. E.g. only adjective grammar exercises.
174
+ * @param limit The optional limit for the number of results.
175
+ * @returns The list of shared content items.
176
+ */
177
+ getList: <T = any>(contentType: string, filter?: SharedContentFilter, limit?: number) => Promise<SharedContent<T>[]>;
178
+ /**
179
+ * Get new shared content.
180
+ * @param contentType The type of shared content to fetch. E.g. assignments, exercises, etc.
181
+ * @param generatorInstructions The instructions for the creation of new shared content. The object will automatically be extended with a tool property with a topic and keywords property to let a new unique topic be generated.
182
+ * @param filter The optional additional filter for checking new shared content based on a column and value. This is useful if the aditional information stored on the shared content is used to further narrow down the kind of shared content wanted to be received. E.g. only adjective grammar exercises.
183
+ * @param options An optional object with options for the new shared content.
184
+ * @param options.privateTopic An optional flag to indicate if the topic should be private and only be visible to the user. This is useful if the topic is not meant to be shared with other users. Like for personal topics or if the content is based on the personal study goal.
185
+ * @param options.skipDbSave An optional flag to indicate if the new shared content should not be saved to the database. This is useful if the new shared content is not meant to be saved to the database.
186
+ * @param options.alwaysGenerateNew An optional flag to indicate if the new shared content should always be generated even if there is already a content with the same filter. This is useful if the new shared content is not meant to be saved to the database.
187
+ * @param options.excludeIds An optional list of ids to exclude from the selection. This is useful if the new shared content is not meant to be saved to the database.
188
+ * @returns The new shared content.
189
+ */
190
+ getNew: <T = any>(contentType: string, generatorInstructions: SharedContentObjectRequest, filter?: SharedContentFilter, options?: {
191
+ privateTopic?: boolean;
192
+ skipDbSave?: boolean;
193
+ alwaysGenerateNew?: boolean;
194
+ excludeIds?: string[];
195
+ }) => Promise<SharedContent<T>>;
196
+ /**
197
+ * Create a new shared content item.
198
+ * @param content The content to create.
199
+ * @returns The new shared content item.
200
+ */
201
+ create: <T = any>(content: Omit<SharedContent<T>, "id">) => Promise<SharedContent<T>>;
202
+ /**
203
+ * Update a shared content item.
204
+ * @param id The id of the shared content item to update.
205
+ * @param content The content to update.
206
+ * @returns The updated shared content item.
207
+ */
208
+ update: <T = any>(id: string, content: Partial<SharedContent<T>>) => Promise<SharedContent<T>>;
209
+ /**
210
+ * Complete a shared content item.
211
+ * @param contentType The type of shared content to complete. E.g. assignments, exercises, etc.
212
+ * @param assignmentId The id of the shared content item to complete.
213
+ */
214
+ complete: (contentType: string, assignmentId: string) => Promise<void>;
215
+ /**
216
+ /**
217
+ * Update the state of a shared content item for a specific user.
218
+ * Useful for marking content as completed, ongoing, hidden, liked, disliked, or bookmarked.
219
+ */
220
+ updateState: (params: {
221
+ contentType: string;
222
+ id: string;
223
+ state?: "completed" | "ongoing" | "hidden";
224
+ reaction?: "liked" | "disliked" | null;
225
+ bookmarked?: boolean;
226
+ }) => Promise<void>;
227
+ /**
228
+ * Remove a shared content item.
229
+ * @param id The id of the shared content item to remove.
230
+ * @returns The removed shared content item.
231
+ */
232
+ remove: (id: string) => Promise<SharedContent<any>>;
233
+ };
234
+ };
235
+ exercise: {
236
+ /**
237
+ * Fetches weekly exercises from the weekly_exercises view.
238
+ * Shows exercises for the current week that haven't expired.
239
+ * @returns Array of exercise objects.
240
+ */
241
+ view: () => Promise<import("../controller/ExerciseController").Exercise[]>;
242
+ /**
243
+ * Creates a new exercise via the backend API.
244
+ * @param params Exercise creation parameters.
245
+ * @returns Created exercise object.
246
+ */
247
+ add: (params: CreateExerciseParams) => Promise<import("../controller/ExerciseController").Exercise>;
248
+ /**
249
+ * Deletes an exercise via the backend API.
250
+ * @param id The exercise ID to delete.
251
+ * @returns Success status.
252
+ */
253
+ delete: (id: string) => Promise<{
254
+ success: boolean;
255
+ message: string;
256
+ }>;
257
+ };
258
+ }
@@ -0,0 +1,375 @@
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 { generateText, streamChatGPT } from '../controller/AIController';
11
+ import { generateObject } from '../controller/ObjectController';
12
+ import { SettingsController } from '../controller/SettingsController';
13
+ import { SharedContentController, } from '../controller/SharedContentController';
14
+ import { getSTTResponse, getTTSResponse } from '../controller/VoiceController';
15
+ import { ExerciseController } from '../controller/ExerciseController';
16
+ import { EventBus } from '../fromRimori/EventBus';
17
+ import { AccomplishmentController } from '../controller/AccomplishmentController';
18
+ import { RimoriCommunicationHandler } from './CommunicationHandler';
19
+ import { Translator } from '../controller/TranslationController';
20
+ import { Logger } from './Logger';
21
+ export class RimoriClient {
22
+ constructor(controller, supabase, info) {
23
+ this.event = {
24
+ /**
25
+ * Emit an event to Rimori or a plugin.
26
+ * The topic schema is:
27
+ * {pluginId}.{eventId}
28
+ * Check out the event bus documentation for more information.
29
+ * For triggering events from Rimori like context menu actions use the "global" keyword.
30
+ * @param topic The topic to emit the event on.
31
+ * @param data The data to emit.
32
+ * @param eventId The event id.
33
+ */
34
+ emit: (topic, data, eventId) => {
35
+ const globalTopic = this.pluginController.getGlobalEventTopic(topic);
36
+ EventBus.emit(this.plugin.pluginId, globalTopic, data, eventId);
37
+ },
38
+ /**
39
+ * Request an event.
40
+ * @param topic The topic to request the event on.
41
+ * @param data The data to request.
42
+ * @returns The response from the event.
43
+ */
44
+ request: (topic, data) => {
45
+ const globalTopic = this.pluginController.getGlobalEventTopic(topic);
46
+ return EventBus.request(this.plugin.pluginId, globalTopic, data);
47
+ },
48
+ /**
49
+ * Subscribe to an event.
50
+ * @param topic The topic to subscribe to.
51
+ * @param callback The callback to call when the event is emitted.
52
+ * @returns An EventListener object containing an off() method to unsubscribe the listeners.
53
+ */
54
+ on: (topic, callback) => {
55
+ const topics = Array.isArray(topic) ? topic : [topic];
56
+ return EventBus.on(topics.map((t) => this.pluginController.getGlobalEventTopic(t)), callback);
57
+ },
58
+ /**
59
+ * Subscribe to an event once.
60
+ * @param topic The topic to subscribe to.
61
+ * @param callback The callback to call when the event is emitted.
62
+ */
63
+ once: (topic, callback) => {
64
+ EventBus.once(this.pluginController.getGlobalEventTopic(topic), callback);
65
+ },
66
+ /**
67
+ * Respond to an event.
68
+ * @param topic The topic to respond to.
69
+ * @param data The data to respond with.
70
+ */
71
+ respond: (topic, data) => {
72
+ const topics = Array.isArray(topic) ? topic : [topic];
73
+ EventBus.respond(this.plugin.pluginId, topics.map((t) => this.pluginController.getGlobalEventTopic(t)), data);
74
+ },
75
+ /**
76
+ * Emit an accomplishment.
77
+ * @param payload The payload to emit.
78
+ */
79
+ emitAccomplishment: (payload) => {
80
+ this.accomplishmentHandler.emitAccomplishment(payload);
81
+ },
82
+ /**
83
+ * Subscribe to an accomplishment.
84
+ * @param accomplishmentTopic The topic to subscribe to.
85
+ * @param callback The callback to call when the accomplishment is emitted.
86
+ */
87
+ onAccomplishment: (accomplishmentTopic, callback) => {
88
+ this.accomplishmentHandler.subscribe(accomplishmentTopic, callback);
89
+ },
90
+ /**
91
+ * Trigger an action that opens the sidebar and triggers an action in the designated plugin.
92
+ * @param pluginId The id of the plugin to trigger the action for.
93
+ * @param actionKey The key of the action to trigger.
94
+ * @param text Optional text to be used for the action like for example text that the translator would look up.
95
+ */
96
+ emitSidebarAction: (pluginId, actionKey, text) => {
97
+ this.event.emit('global.sidebar.triggerAction', { plugin_id: pluginId, action_key: actionKey, text });
98
+ },
99
+ onMainPanelAction: (callback, actionsToListen = []) => {
100
+ // this needs to be a emit and on because the main panel action is triggered by the user and not by the plugin
101
+ this.event.emit('action.requestMain');
102
+ this.event.on('action.requestMain', ({ data }) => {
103
+ if (actionsToListen.includes(data.action)) {
104
+ callback(data);
105
+ }
106
+ });
107
+ },
108
+ };
109
+ this.navigation = {
110
+ toDashboard: () => {
111
+ this.event.emit('global.navigation.triggerToDashboard');
112
+ },
113
+ };
114
+ this.ai = {
115
+ getText: (messages, tools) => __awaiter(this, void 0, void 0, function* () {
116
+ const token = yield this.pluginController.getToken();
117
+ return generateText(this.pluginController.getBackendUrl(), messages, tools || [], token).then(({ messages }) => messages[0].content[0].text);
118
+ }),
119
+ getSteamedText: (messages, onMessage, tools) => __awaiter(this, void 0, void 0, function* () {
120
+ const token = yield this.pluginController.getToken();
121
+ streamChatGPT(this.pluginController.getBackendUrl(), messages, tools || [], onMessage, token);
122
+ }),
123
+ getVoice: (text_1, ...args_1) => __awaiter(this, [text_1, ...args_1], void 0, function* (text, voice = 'alloy', speed = 1, language) {
124
+ const token = yield this.pluginController.getToken();
125
+ return getTTSResponse(this.pluginController.getBackendUrl(), { input: text, voice, speed, language }, token);
126
+ }),
127
+ getTextFromVoice: (file) => __awaiter(this, void 0, void 0, function* () {
128
+ const token = yield this.pluginController.getToken();
129
+ return getSTTResponse(this.pluginController.getBackendUrl(), file, token);
130
+ }),
131
+ getObject: (request) => __awaiter(this, void 0, void 0, function* () {
132
+ const token = yield this.pluginController.getToken();
133
+ return generateObject(this.pluginController.getBackendUrl(), request, token);
134
+ }),
135
+ // getSteamedObject: this.generateObjectStream,
136
+ };
137
+ this.runtime = {
138
+ fetchBackend: (url, options) => __awaiter(this, void 0, void 0, function* () {
139
+ const token = yield this.pluginController.getToken();
140
+ return fetch(this.pluginController.getBackendUrl() + url, Object.assign(Object.assign({}, options), { headers: Object.assign(Object.assign({}, options.headers), { Authorization: `Bearer ${token}` }) }));
141
+ }),
142
+ };
143
+ this.community = {
144
+ /**
145
+ * Shared content is a way to share completable content with other users using this plugin.
146
+ * Typical examples are assignments, exercises, stories, etc.
147
+ * Users generate new shared content items and others can complete the content too.
148
+ */
149
+ sharedContent: {
150
+ /**
151
+ * Get one dedicated shared content item by id. It does not matter if it is completed or not.
152
+ * @param contentType The type of shared content to get. E.g. assignments, exercises, etc.
153
+ * @param id The id of the shared content item.
154
+ * @returns The shared content item.
155
+ */
156
+ get: (contentType, id) => __awaiter(this, void 0, void 0, function* () {
157
+ return yield this.sharedContentController.getSharedContent(contentType, id);
158
+ }),
159
+ /**
160
+ * Get a list of shared content items.
161
+ * @param contentType The type of shared content to get. E.g. assignments, exercises, etc.
162
+ * @param filter The optional additional filter for checking new shared content based on a column and value. This is useful if the aditional information stored on the shared content is used to further narrow down the kind of shared content wanted to be received. E.g. only adjective grammar exercises.
163
+ * @param limit The optional limit for the number of results.
164
+ * @returns The list of shared content items.
165
+ */
166
+ getList: (contentType, filter, limit) => __awaiter(this, void 0, void 0, function* () {
167
+ return yield this.sharedContentController.getSharedContentList(contentType, filter, limit);
168
+ }),
169
+ /**
170
+ * Get new shared content.
171
+ * @param contentType The type of shared content to fetch. E.g. assignments, exercises, etc.
172
+ * @param generatorInstructions The instructions for the creation of new shared content. The object will automatically be extended with a tool property with a topic and keywords property to let a new unique topic be generated.
173
+ * @param filter The optional additional filter for checking new shared content based on a column and value. This is useful if the aditional information stored on the shared content is used to further narrow down the kind of shared content wanted to be received. E.g. only adjective grammar exercises.
174
+ * @param options An optional object with options for the new shared content.
175
+ * @param options.privateTopic An optional flag to indicate if the topic should be private and only be visible to the user. This is useful if the topic is not meant to be shared with other users. Like for personal topics or if the content is based on the personal study goal.
176
+ * @param options.skipDbSave An optional flag to indicate if the new shared content should not be saved to the database. This is useful if the new shared content is not meant to be saved to the database.
177
+ * @param options.alwaysGenerateNew An optional flag to indicate if the new shared content should always be generated even if there is already a content with the same filter. This is useful if the new shared content is not meant to be saved to the database.
178
+ * @param options.excludeIds An optional list of ids to exclude from the selection. This is useful if the new shared content is not meant to be saved to the database.
179
+ * @returns The new shared content.
180
+ */
181
+ getNew: (contentType, generatorInstructions, filter, options) => __awaiter(this, void 0, void 0, function* () {
182
+ return yield this.sharedContentController.getNewSharedContent(contentType, generatorInstructions, filter, options);
183
+ }),
184
+ /**
185
+ * Create a new shared content item.
186
+ * @param content The content to create.
187
+ * @returns The new shared content item.
188
+ */
189
+ create: (content) => __awaiter(this, void 0, void 0, function* () {
190
+ return yield this.sharedContentController.createSharedContent(content);
191
+ }),
192
+ /**
193
+ * Update a shared content item.
194
+ * @param id The id of the shared content item to update.
195
+ * @param content The content to update.
196
+ * @returns The updated shared content item.
197
+ */
198
+ update: (id, content) => __awaiter(this, void 0, void 0, function* () {
199
+ return yield this.sharedContentController.updateSharedContent(id, content);
200
+ }),
201
+ /**
202
+ * Complete a shared content item.
203
+ * @param contentType The type of shared content to complete. E.g. assignments, exercises, etc.
204
+ * @param assignmentId The id of the shared content item to complete.
205
+ */
206
+ complete: (contentType, assignmentId) => __awaiter(this, void 0, void 0, function* () {
207
+ return yield this.sharedContentController.completeSharedContent(contentType, assignmentId);
208
+ }),
209
+ /**
210
+ /**
211
+ * Update the state of a shared content item for a specific user.
212
+ * Useful for marking content as completed, ongoing, hidden, liked, disliked, or bookmarked.
213
+ */
214
+ updateState: (params) => __awaiter(this, void 0, void 0, function* () {
215
+ return yield this.sharedContentController.updateSharedContentState(params);
216
+ }),
217
+ /**
218
+ * Remove a shared content item.
219
+ * @param id The id of the shared content item to remove.
220
+ * @returns The removed shared content item.
221
+ */
222
+ remove: (id) => __awaiter(this, void 0, void 0, function* () {
223
+ return yield this.sharedContentController.removeSharedContent(id);
224
+ }),
225
+ },
226
+ };
227
+ this.exercise = {
228
+ /**
229
+ * Fetches weekly exercises from the weekly_exercises view.
230
+ * Shows exercises for the current week that haven't expired.
231
+ * @returns Array of exercise objects.
232
+ */
233
+ view: () => __awaiter(this, void 0, void 0, function* () {
234
+ return this.exerciseController.viewWeeklyExercises();
235
+ }),
236
+ /**
237
+ * Creates a new exercise via the backend API.
238
+ * @param params Exercise creation parameters.
239
+ * @returns Created exercise object.
240
+ */
241
+ add: (params) => __awaiter(this, void 0, void 0, function* () {
242
+ const token = yield this.pluginController.getToken();
243
+ const backendUrl = this.pluginController.getBackendUrl();
244
+ return this.exerciseController.addExercise(token, backendUrl, params);
245
+ }),
246
+ /**
247
+ * Deletes an exercise via the backend API.
248
+ * @param id The exercise ID to delete.
249
+ * @returns Success status.
250
+ */
251
+ delete: (id) => __awaiter(this, void 0, void 0, function* () {
252
+ const token = yield this.pluginController.getToken();
253
+ const backendUrl = this.pluginController.getBackendUrl();
254
+ return this.exerciseController.deleteExercise(token, backendUrl, id);
255
+ }),
256
+ };
257
+ this.rimoriInfo = info;
258
+ this.superbase = supabase;
259
+ this.pluginController = controller;
260
+ this.exerciseController = new ExerciseController(supabase);
261
+ this.accomplishmentHandler = new AccomplishmentController(info.pluginId);
262
+ this.settingsController = new SettingsController(supabase, info.pluginId, info.guild);
263
+ this.sharedContentController = new SharedContentController(supabase, this);
264
+ this.translator = new Translator(info.profile.mother_tongue.code);
265
+ //only init logger in workers and on main plugin pages
266
+ if (this.getQueryParam('applicationMode') !== 'sidebar') {
267
+ Logger.getInstance(this);
268
+ }
269
+ }
270
+ get plugin() {
271
+ return {
272
+ pluginId: this.rimoriInfo.pluginId,
273
+ /**
274
+ * Set the settings for the plugin.
275
+ * @param settings The settings to set.
276
+ */
277
+ setSettings: (settings) => __awaiter(this, void 0, void 0, function* () {
278
+ yield this.settingsController.setSettings(settings);
279
+ }),
280
+ /**
281
+ * Get the settings for the plugin. T can be any type of settings, UserSettings or SystemSettings.
282
+ * @param defaultSettings The default settings to use if no settings are found.
283
+ * @param genericSettings The type of settings to get.
284
+ * @returns The settings for the plugin.
285
+ */
286
+ getSettings: (defaultSettings) => __awaiter(this, void 0, void 0, function* () {
287
+ return yield this.settingsController.getSettings(defaultSettings);
288
+ }),
289
+ getUserInfo: () => {
290
+ return this.rimoriInfo.profile;
291
+ },
292
+ /**
293
+ * Retrieves information about plugins, including:
294
+ * - All installed plugins
295
+ * - The currently active plugin in the main panel
296
+ * - The currently active plugin in the side panel
297
+ */
298
+ getPluginInfo: () => {
299
+ return {
300
+ installedPlugins: this.rimoriInfo.installedPlugins,
301
+ mainPanelPlugin: this.rimoriInfo.mainPanelPlugin,
302
+ sidePanelPlugin: this.rimoriInfo.sidePanelPlugin,
303
+ };
304
+ },
305
+ /**
306
+ * Get the translator for the plugin.
307
+ * @returns The translator for the plugin.
308
+ */
309
+ getTranslator: () => __awaiter(this, void 0, void 0, function* () {
310
+ yield this.translator.initialize();
311
+ return this.translator;
312
+ }),
313
+ };
314
+ }
315
+ get db() {
316
+ return {
317
+ // private from<
318
+ // TableName extends string & keyof GenericSchema['Tables'],
319
+ // Table extends GenericSchema['Tables'][TableName],
320
+ // >(relation: TableName): PostgrestQueryBuilder<GenericSchema, Table, TableName>;
321
+ // private from<ViewName extends string & keyof GenericSchema['Views'], View extends GenericSchema['Views'][ViewName]>(
322
+ // relation: ViewName,
323
+ // ): PostgrestQueryBuilder<GenericSchema, View, ViewName>;
324
+ from: (relation) => {
325
+ return this.superbase.from(this.db.getTableName(relation));
326
+ },
327
+ // storage: this.superbase.storage,
328
+ // functions: this.superbase.functions,
329
+ /**
330
+ * The table prefix for of database tables of the plugin.
331
+ */
332
+ tablePrefix: this.rimoriInfo.tablePrefix,
333
+ /**
334
+ * Get the table name for a given plugin table.
335
+ * Internally all tables are prefixed with the plugin id. This function is used to get the correct table name for a given public table.
336
+ * @param table The plugin table name to get the full table name for.
337
+ * @returns The full table name.
338
+ */
339
+ getTableName: (table) => {
340
+ if (/[A-Z]/.test(table)) {
341
+ throw new Error('Table name cannot include uppercase letters. Please use snake_case for table names.');
342
+ }
343
+ if (table.startsWith('global_')) {
344
+ return table.replace('global_', '');
345
+ }
346
+ return this.db.tablePrefix + '_' + table;
347
+ },
348
+ };
349
+ }
350
+ /**
351
+ * Get a query parameter value that was passed via MessageChannel
352
+ * @param key The query parameter key
353
+ * @returns The query parameter value or null if not found
354
+ */
355
+ getQueryParam(key) {
356
+ return this.pluginController.getQueryParam(key);
357
+ }
358
+ static getInstance(pluginId) {
359
+ return __awaiter(this, void 0, void 0, function* () {
360
+ if (!RimoriClient.instance) {
361
+ if (!pluginId)
362
+ throw new Error('Plugin ID is required');
363
+ const controller = new RimoriCommunicationHandler(pluginId, false);
364
+ if (typeof WorkerGlobalScope === 'undefined') {
365
+ // In standalone mode, use URL fallback. In iframe mode, theme will be set after MessageChannel init
366
+ // setTheme();
367
+ // await StandaloneClient.initListeners(pluginId);
368
+ }
369
+ const client = yield controller.getClient();
370
+ RimoriClient.instance = new RimoriClient(controller, client.supabase, client.info);
371
+ }
372
+ return RimoriClient.instance;
373
+ });
374
+ }
375
+ }
@@ -0,0 +1,17 @@
1
+ import { SupabaseClient } from '@supabase/supabase-js';
2
+ export interface StandaloneConfig {
3
+ url: string;
4
+ key: string;
5
+ backendUrl?: string;
6
+ }
7
+ export declare class StandaloneClient {
8
+ private static instance;
9
+ private config;
10
+ private supabase;
11
+ private constructor();
12
+ static getInstance(): Promise<StandaloneClient>;
13
+ getClient(): Promise<SupabaseClient>;
14
+ needsLogin(): Promise<boolean>;
15
+ login(email: string, password: string): Promise<boolean>;
16
+ static initListeners(pluginId: string): Promise<void>;
17
+ }