@rimori/client 1.1.10 → 1.3.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.
- package/README.md +189 -63
- package/dist/cli/scripts/init/dev-registration.d.ts +35 -0
- package/dist/cli/scripts/init/dev-registration.js +174 -0
- package/dist/cli/scripts/init/env-setup.d.ts +9 -0
- package/dist/cli/scripts/init/env-setup.js +43 -0
- package/dist/cli/scripts/init/file-operations.d.ts +4 -0
- package/dist/cli/scripts/init/file-operations.js +51 -0
- package/dist/cli/scripts/init/html-cleaner.d.ts +4 -0
- package/dist/cli/scripts/init/html-cleaner.js +38 -0
- package/dist/cli/scripts/init/main.d.ts +2 -0
- package/dist/cli/scripts/init/main.js +160 -0
- package/dist/cli/scripts/init/package-setup.d.ts +32 -0
- package/dist/cli/scripts/init/package-setup.js +75 -0
- package/dist/cli/scripts/init/router-transformer.d.ts +6 -0
- package/dist/cli/scripts/init/router-transformer.js +254 -0
- package/dist/cli/scripts/init/tailwind-config.d.ts +4 -0
- package/dist/cli/scripts/init/tailwind-config.js +56 -0
- package/dist/cli/scripts/init/vite-config.d.ts +20 -0
- package/dist/cli/scripts/init/vite-config.js +54 -0
- package/dist/cli/scripts/release/release-config-upload.d.ts +7 -0
- package/dist/cli/scripts/release/release-config-upload.js +116 -0
- package/dist/cli/scripts/release/release-db-update.d.ts +6 -0
- package/dist/cli/scripts/release/release-db-update.js +100 -0
- package/dist/cli/scripts/release/release-file-upload.d.ts +6 -0
- package/dist/cli/scripts/release/release-file-upload.js +136 -0
- package/dist/cli/scripts/release/release.d.ts +23 -0
- package/dist/cli/scripts/release/release.js +70 -0
- package/dist/cli/types/DatabaseTypes.d.ts +103 -0
- package/dist/cli/types/DatabaseTypes.js +2 -0
- package/dist/components/LoggerExample.d.ts +6 -0
- package/dist/components/LoggerExample.js +79 -0
- package/dist/components/ai/Assistant.js +5 -5
- package/dist/components/ai/Avatar.d.ts +3 -2
- package/dist/components/ai/Avatar.js +11 -6
- package/dist/components/ai/EmbeddedAssistent/CircleAudioAvatar.js +1 -1
- package/dist/components/ai/EmbeddedAssistent/VoiceRecoder.d.ts +1 -0
- package/dist/components/ai/EmbeddedAssistent/VoiceRecoder.js +48 -33
- package/dist/components/ai/utils.js +0 -1
- package/dist/components/audio/Playbutton.js +4 -4
- package/dist/{core → components}/components/ContextMenu.js +50 -11
- package/dist/components.d.ts +5 -5
- package/dist/components.js +5 -5
- package/dist/core/controller/AIController.d.ts +15 -0
- package/dist/core/controller/AIController.js +253 -0
- package/dist/core/controller/AudioController.d.ts +0 -0
- package/dist/core/controller/AudioController.js +1 -0
- package/dist/{controller → core/controller}/ObjectController.d.ts +10 -2
- package/dist/{controller → core/controller}/ObjectController.js +8 -8
- package/dist/{controller → core/controller}/SettingsController.d.ts +28 -4
- package/dist/{controller → core/controller}/SettingsController.js +0 -25
- package/dist/{controller → core/controller}/SharedContentController.d.ts +31 -3
- package/dist/{controller → core/controller}/SharedContentController.js +77 -26
- package/dist/core/controller/VoiceController.d.ts +9 -0
- package/dist/{controller → core/controller}/VoiceController.js +11 -4
- package/dist/core/core.d.ts +14 -0
- package/dist/core/core.js +8 -0
- package/dist/{plugin/fromRimori → fromRimori}/EventBus.d.ts +3 -3
- package/dist/{plugin/fromRimori → fromRimori}/EventBus.js +26 -9
- package/dist/fromRimori/PluginTypes.d.ts +174 -0
- package/dist/hooks/UseChatHook.d.ts +2 -1
- package/dist/hooks/UseChatHook.js +6 -4
- package/dist/hooks/UseLogger.d.ts +30 -0
- package/dist/hooks/UseLogger.js +122 -0
- package/dist/index.d.ts +6 -3
- package/dist/index.js +5 -3
- package/dist/plugin/AccomplishmentHandler.d.ts +1 -1
- package/dist/plugin/AccomplishmentHandler.js +1 -1
- package/dist/plugin/AudioController.d.ts +37 -0
- package/dist/plugin/AudioController.js +68 -0
- package/dist/plugin/Logger.d.ts +68 -0
- package/dist/plugin/Logger.js +256 -0
- package/dist/plugin/LoggerExample.d.ts +16 -0
- package/dist/plugin/LoggerExample.js +140 -0
- package/dist/plugin/PluginController.d.ts +30 -5
- package/dist/plugin/PluginController.js +182 -53
- package/dist/plugin/RimoriClient.d.ts +68 -21
- package/dist/plugin/RimoriClient.js +88 -41
- package/dist/plugin/StandaloneClient.d.ts +1 -0
- package/dist/plugin/StandaloneClient.js +24 -10
- package/dist/plugin/ThemeSetter.d.ts +2 -1
- package/dist/plugin/ThemeSetter.js +13 -7
- package/dist/providers/PluginProvider.d.ts +4 -1
- package/dist/providers/PluginProvider.js +39 -13
- package/dist/utils/Language.d.ts +2 -1
- package/dist/utils/Language.js +4 -2
- package/dist/utils/audioFormats.d.ts +26 -0
- package/dist/utils/audioFormats.js +67 -0
- package/dist/utils/difficultyConverter.js +1 -1
- package/dist/utils/endpoint.d.ts +2 -0
- package/dist/utils/endpoint.js +2 -0
- package/dist/worker/WorkerSetup.d.ts +3 -2
- package/dist/worker/WorkerSetup.js +22 -65
- package/example/docs/devdocs.md +231 -0
- package/example/docs/overview.md +29 -0
- package/example/docs/userdocs.md +123 -0
- package/example/rimori.config.ts +89 -0
- package/example/worker/vite.config.ts +23 -0
- package/example/worker/worker.ts +11 -0
- package/package.json +16 -9
- package/src/cli/scripts/init/dev-registration.ts +192 -0
- package/src/cli/scripts/init/env-setup.ts +44 -0
- package/src/cli/scripts/init/file-operations.ts +58 -0
- package/src/cli/scripts/init/html-cleaner.ts +48 -0
- package/src/cli/scripts/init/main.ts +172 -0
- package/src/cli/scripts/init/package-setup.ts +117 -0
- package/src/cli/scripts/init/router-transformer.ts +329 -0
- package/src/cli/scripts/init/tailwind-config.ts +75 -0
- package/src/cli/scripts/init/vite-config.ts +73 -0
- package/src/cli/scripts/release/release-config-upload.ts +114 -0
- package/src/cli/scripts/release/release-db-update.ts +97 -0
- package/src/cli/scripts/release/release-file-upload.ts +138 -0
- package/src/cli/scripts/release/release.ts +69 -0
- package/src/cli/types/DatabaseTypes.ts +117 -0
- package/src/components/ai/Assistant.tsx +5 -5
- package/src/components/ai/Avatar.tsx +25 -8
- package/src/components/ai/EmbeddedAssistent/CircleAudioAvatar.tsx +1 -1
- package/src/components/ai/EmbeddedAssistent/VoiceRecoder.tsx +50 -35
- package/src/components/ai/utils.ts +0 -2
- package/src/components/audio/Playbutton.tsx +4 -4
- package/src/{core → components}/components/ContextMenu.tsx +56 -12
- package/src/components.ts +6 -6
- package/src/core/controller/AIController.ts +283 -0
- package/src/core/controller/ObjectController.ts +115 -0
- package/src/{controller → core/controller}/SettingsController.ts +29 -29
- package/src/{controller → core/controller}/SharedContentController.ts +91 -29
- package/src/core/controller/VoiceController.ts +31 -0
- package/src/core/core.ts +16 -0
- package/src/{plugin/fromRimori → fromRimori}/EventBus.ts +29 -11
- package/src/fromRimori/PluginTypes.ts +205 -0
- package/src/hooks/UseChatHook.ts +8 -5
- package/src/index.ts +6 -3
- package/src/plugin/AccomplishmentHandler.ts +1 -1
- package/src/plugin/AudioController.ts +58 -0
- package/src/plugin/Logger.ts +324 -0
- package/src/plugin/PluginController.ts +203 -63
- package/src/plugin/RimoriClient.ts +127 -55
- package/src/plugin/StandaloneClient.ts +30 -11
- package/src/plugin/ThemeSetter.ts +16 -9
- package/src/providers/PluginProvider.tsx +46 -13
- package/src/utils/Language.ts +4 -2
- package/src/utils/difficultyConverter.ts +3 -3
- package/src/utils/endpoint.ts +2 -0
- package/src/worker/WorkerSetup.ts +13 -60
- package/dist/components/PluginController.d.ts +0 -21
- package/dist/components/PluginController.js +0 -116
- package/dist/controller/AIController.d.ts +0 -23
- package/dist/controller/AIController.js +0 -93
- package/dist/controller/SidePluginController.d.ts +0 -3
- package/dist/controller/SidePluginController.js +0 -31
- package/dist/controller/VoiceController.d.ts +0 -10
- package/dist/core.d.ts +0 -7
- package/dist/core.js +0 -7
- package/dist/plugin/ContextMenu.d.ts +0 -17
- package/dist/plugin/ContextMenu.js +0 -45
- package/dist/plugin/fromRimori/PluginTypes.d.ts +0 -48
- package/dist/plugin/fromRimori/SupabaseHandler.d.ts +0 -13
- package/dist/plugin/fromRimori/SupabaseHandler.js +0 -55
- package/dist/providers/PluginController.d.ts +0 -21
- package/dist/providers/PluginController.js +0 -116
- package/dist/types/Actions.d.ts +0 -4
- package/dist/types/Actions.js +0 -1
- package/src/controller/AIController.ts +0 -112
- package/src/controller/ObjectController.ts +0 -107
- package/src/controller/SidePluginController.ts +0 -25
- package/src/controller/VoiceController.ts +0 -26
- package/src/core.ts +0 -8
- package/src/plugin/fromRimori/PluginTypes.ts +0 -64
- package/src/types/Actions.ts +0 -6
- /package/dist/{core → components}/components/ContextMenu.d.ts +0 -0
- /package/dist/{plugin/fromRimori → fromRimori}/PluginTypes.js +0 -0
- /package/src/{plugin/fromRimori → fromRimori}/readme.md +0 -0
|
@@ -7,16 +7,15 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
|
|
|
7
7
|
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
8
8
|
});
|
|
9
9
|
};
|
|
10
|
-
import { generateText, streamChatGPT } from "../controller/AIController";
|
|
11
|
-
import { generateObject
|
|
12
|
-
import { SettingsController } from "../controller/SettingsController";
|
|
13
|
-
import { SharedContentController } from "../controller/SharedContentController";
|
|
14
|
-
import {
|
|
15
|
-
import {
|
|
10
|
+
import { generateText, streamChatGPT } from "../core/controller/AIController";
|
|
11
|
+
import { generateObject } from "../core/controller/ObjectController";
|
|
12
|
+
import { SettingsController } from "../core/controller/SettingsController";
|
|
13
|
+
import { SharedContentController } from "../core/controller/SharedContentController";
|
|
14
|
+
import { getSTTResponse, getTTSResponse } from "../core/controller/VoiceController";
|
|
15
|
+
import { EventBus } from "../fromRimori/EventBus";
|
|
16
16
|
import { AccomplishmentHandler } from "./AccomplishmentHandler";
|
|
17
|
-
import { EventBus } from "./fromRimori/EventBus";
|
|
18
17
|
export class RimoriClient {
|
|
19
|
-
constructor(
|
|
18
|
+
constructor(supabase, info, pluginController) {
|
|
20
19
|
this.event = {
|
|
21
20
|
/**
|
|
22
21
|
* Emit an event to Rimori or a plugin.
|
|
@@ -46,11 +45,11 @@ export class RimoriClient {
|
|
|
46
45
|
* Subscribe to an event.
|
|
47
46
|
* @param topic The topic to subscribe to.
|
|
48
47
|
* @param callback The callback to call when the event is emitted.
|
|
49
|
-
* @returns
|
|
48
|
+
* @returns An EventListener object containing an off() method to unsubscribe the listeners.
|
|
50
49
|
*/
|
|
51
50
|
on: (topic, callback) => {
|
|
52
51
|
const topics = Array.isArray(topic) ? topic : [topic];
|
|
53
|
-
return topics.map(
|
|
52
|
+
return EventBus.on(topics.map(t => this.pluginController.getGlobalEventTopic(t)), callback);
|
|
54
53
|
},
|
|
55
54
|
/**
|
|
56
55
|
* Subscribe to an event once.
|
|
@@ -66,7 +65,8 @@ export class RimoriClient {
|
|
|
66
65
|
* @param data The data to respond with.
|
|
67
66
|
*/
|
|
68
67
|
respond: (topic, data) => {
|
|
69
|
-
|
|
68
|
+
const topics = Array.isArray(topic) ? topic : [topic];
|
|
69
|
+
EventBus.respond(this.plugin.pluginId, topics.map(t => this.pluginController.getGlobalEventTopic(t)), data);
|
|
70
70
|
},
|
|
71
71
|
/**
|
|
72
72
|
* Emit an accomplishment.
|
|
@@ -90,31 +90,48 @@ export class RimoriClient {
|
|
|
90
90
|
* @param text Optional text to be used for the action like for example text that the translator would look up.
|
|
91
91
|
*/
|
|
92
92
|
emitSidebarAction: (pluginId, actionKey, text) => {
|
|
93
|
-
this.event.emit("global.sidebar.triggerAction", { pluginId, actionKey, text });
|
|
93
|
+
this.event.emit("global.sidebar.triggerAction", { plugin_id: pluginId, action_key: actionKey, text });
|
|
94
|
+
},
|
|
95
|
+
onMainPanelAction: (callback) => {
|
|
96
|
+
// this needs to be a emit and on because the main panel action is triggered by the user and not by the plugin
|
|
97
|
+
this.event.emit("action.requestMain");
|
|
98
|
+
this.event.on("action.requestMain", ({ data }) => callback(data));
|
|
94
99
|
}
|
|
95
100
|
};
|
|
96
|
-
this.
|
|
101
|
+
this.navigation = {
|
|
102
|
+
toDashboard: () => {
|
|
103
|
+
this.event.emit("global.navigation.triggerToDashboard");
|
|
104
|
+
}
|
|
105
|
+
};
|
|
106
|
+
this.ai = {
|
|
97
107
|
getText: (messages, tools) => __awaiter(this, void 0, void 0, function* () {
|
|
98
108
|
const token = yield this.pluginController.getToken();
|
|
99
|
-
return generateText(this.
|
|
109
|
+
return generateText(this.pluginController.getBackendUrl(), messages, tools || [], token).then(({ messages }) => messages[0].content[0].text);
|
|
100
110
|
}),
|
|
101
111
|
getSteamedText: (messages, onMessage, tools) => __awaiter(this, void 0, void 0, function* () {
|
|
102
112
|
const token = yield this.pluginController.getToken();
|
|
103
|
-
streamChatGPT(this.
|
|
113
|
+
streamChatGPT(this.pluginController.getBackendUrl(), messages, tools || [], onMessage, token);
|
|
104
114
|
}),
|
|
105
115
|
getVoice: (text_1, ...args_1) => __awaiter(this, [text_1, ...args_1], void 0, function* (text, voice = "alloy", speed = 1, language) {
|
|
106
116
|
const token = yield this.pluginController.getToken();
|
|
107
|
-
return getTTSResponse(this.
|
|
117
|
+
return getTTSResponse(this.pluginController.getBackendUrl(), { input: text, voice, speed, language }, token);
|
|
118
|
+
}),
|
|
119
|
+
getTextFromVoice: (file) => __awaiter(this, void 0, void 0, function* () {
|
|
120
|
+
const token = yield this.pluginController.getToken();
|
|
121
|
+
return getSTTResponse(this.pluginController.getBackendUrl(), file, token);
|
|
108
122
|
}),
|
|
109
|
-
getTextFromVoice: (file) => {
|
|
110
|
-
return getSTTResponse(this.superbase, file);
|
|
111
|
-
},
|
|
112
123
|
getObject: (request) => __awaiter(this, void 0, void 0, function* () {
|
|
113
124
|
const token = yield this.pluginController.getToken();
|
|
114
|
-
return
|
|
125
|
+
return generateObject(this.pluginController.getBackendUrl(), request, token);
|
|
115
126
|
}),
|
|
116
127
|
// getSteamedObject: this.generateObjectStream,
|
|
117
128
|
};
|
|
129
|
+
this.runtime = {
|
|
130
|
+
fetchBackend: (url, options) => __awaiter(this, void 0, void 0, function* () {
|
|
131
|
+
const token = yield this.pluginController.getToken();
|
|
132
|
+
return fetch(this.pluginController.getBackendUrl() + url, Object.assign(Object.assign({}, options), { headers: Object.assign(Object.assign({}, options.headers), { 'Authorization': `Bearer ${token}` }) }));
|
|
133
|
+
})
|
|
134
|
+
};
|
|
118
135
|
this.community = {
|
|
119
136
|
/**
|
|
120
137
|
* Shared content is a way to share completable content with other users using this plugin.
|
|
@@ -146,11 +163,15 @@ export class RimoriClient {
|
|
|
146
163
|
* @param contentType The type of shared content to fetch. E.g. assignments, exercises, etc.
|
|
147
164
|
* @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.
|
|
148
165
|
* @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.
|
|
149
|
-
* @param
|
|
166
|
+
* @param options An optional object with options for the new shared content.
|
|
167
|
+
* @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.
|
|
168
|
+
* @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.
|
|
169
|
+
* @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.
|
|
170
|
+
* @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.
|
|
150
171
|
* @returns The new shared content.
|
|
151
172
|
*/
|
|
152
|
-
getNew: (contentType, generatorInstructions, filter,
|
|
153
|
-
return yield this.sharedContentController.getNewSharedContent(contentType, generatorInstructions, filter,
|
|
173
|
+
getNew: (contentType, generatorInstructions, filter, options) => __awaiter(this, void 0, void 0, function* () {
|
|
174
|
+
return yield this.sharedContentController.getNewSharedContent(contentType, generatorInstructions, filter, options);
|
|
154
175
|
}),
|
|
155
176
|
/**
|
|
156
177
|
* Create a new shared content item.
|
|
@@ -177,6 +198,14 @@ export class RimoriClient {
|
|
|
177
198
|
complete: (contentType, assignmentId) => __awaiter(this, void 0, void 0, function* () {
|
|
178
199
|
return yield this.sharedContentController.completeSharedContent(contentType, assignmentId);
|
|
179
200
|
}),
|
|
201
|
+
/**
|
|
202
|
+
/**
|
|
203
|
+
* Update the state of a shared content item for a specific user.
|
|
204
|
+
* Useful for marking content as completed, ongoing, hidden, liked, disliked, or bookmarked.
|
|
205
|
+
*/
|
|
206
|
+
updateState: (params) => __awaiter(this, void 0, void 0, function* () {
|
|
207
|
+
return yield this.sharedContentController.updateSharedContentState(params);
|
|
208
|
+
}),
|
|
180
209
|
/**
|
|
181
210
|
* Remove a shared content item.
|
|
182
211
|
* @param id The id of the shared content item to remove.
|
|
@@ -187,41 +216,53 @@ export class RimoriClient {
|
|
|
187
216
|
})
|
|
188
217
|
}
|
|
189
218
|
};
|
|
190
|
-
this.
|
|
191
|
-
this.
|
|
192
|
-
this.
|
|
219
|
+
this.rimoriInfo = info;
|
|
220
|
+
this.superbase = supabase;
|
|
221
|
+
this.pluginController = pluginController;
|
|
222
|
+
this.settingsController = new SettingsController(supabase, info.pluginId);
|
|
193
223
|
this.sharedContentController = new SharedContentController(this.superbase, this);
|
|
194
|
-
this.
|
|
195
|
-
this.accomplishmentHandler = new AccomplishmentHandler(options.pluginId);
|
|
224
|
+
this.accomplishmentHandler = new AccomplishmentHandler(info.pluginId);
|
|
196
225
|
this.from = this.from.bind(this);
|
|
197
226
|
this.db = {
|
|
198
227
|
from: this.from,
|
|
199
|
-
storage: this.superbase.storage,
|
|
228
|
+
// storage: this.superbase.storage,
|
|
200
229
|
// functions: this.superbase.functions,
|
|
201
|
-
tablePrefix:
|
|
230
|
+
tablePrefix: info.tablePrefix,
|
|
202
231
|
getTableName: this.getTableName.bind(this),
|
|
203
232
|
};
|
|
204
233
|
this.plugin = {
|
|
205
|
-
pluginId:
|
|
234
|
+
pluginId: info.pluginId,
|
|
206
235
|
setSettings: (settings) => __awaiter(this, void 0, void 0, function* () {
|
|
207
236
|
yield this.settingsController.setSettings(settings);
|
|
208
237
|
}),
|
|
209
238
|
getSettings: (defaultSettings) => __awaiter(this, void 0, void 0, function* () {
|
|
210
239
|
return yield this.settingsController.getSettings(defaultSettings);
|
|
211
240
|
}),
|
|
212
|
-
|
|
213
|
-
return
|
|
214
|
-
}
|
|
215
|
-
|
|
216
|
-
return
|
|
217
|
-
|
|
241
|
+
getUserInfo: () => {
|
|
242
|
+
return this.rimoriInfo.profile;
|
|
243
|
+
},
|
|
244
|
+
getPluginInfo: () => {
|
|
245
|
+
return {
|
|
246
|
+
installedPlugins: this.rimoriInfo.installedPlugins,
|
|
247
|
+
mainPanelPlugin: this.rimoriInfo.mainPanelPlugin,
|
|
248
|
+
sidePanelPlugin: this.rimoriInfo.sidePanelPlugin,
|
|
249
|
+
};
|
|
250
|
+
}
|
|
218
251
|
};
|
|
219
252
|
}
|
|
253
|
+
/**
|
|
254
|
+
* Get a query parameter value that was passed via MessageChannel
|
|
255
|
+
* @param key The query parameter key
|
|
256
|
+
* @returns The query parameter value or null if not found
|
|
257
|
+
*/
|
|
258
|
+
getQueryParam(key) {
|
|
259
|
+
return this.pluginController.getQueryParam(key);
|
|
260
|
+
}
|
|
220
261
|
static getInstance(pluginController) {
|
|
221
262
|
return __awaiter(this, void 0, void 0, function* () {
|
|
222
263
|
if (!RimoriClient.instance) {
|
|
223
|
-
const
|
|
224
|
-
RimoriClient.instance = new RimoriClient(
|
|
264
|
+
const client = yield pluginController.getClient();
|
|
265
|
+
RimoriClient.instance = new RimoriClient(client.supabase, client.info, pluginController);
|
|
225
266
|
}
|
|
226
267
|
return RimoriClient.instance;
|
|
227
268
|
});
|
|
@@ -229,7 +270,13 @@ export class RimoriClient {
|
|
|
229
270
|
from(relation) {
|
|
230
271
|
return this.superbase.from(this.getTableName(relation));
|
|
231
272
|
}
|
|
232
|
-
getTableName(
|
|
233
|
-
|
|
273
|
+
getTableName(table) {
|
|
274
|
+
if (/[A-Z]/.test(table)) {
|
|
275
|
+
throw new Error("Table name cannot include uppercase letters. Please use snake_case for table names.");
|
|
276
|
+
}
|
|
277
|
+
if (table.startsWith("global_")) {
|
|
278
|
+
return table.replace("global_", "");
|
|
279
|
+
}
|
|
280
|
+
return this.db.tablePrefix + "_" + table;
|
|
234
281
|
}
|
|
235
282
|
}
|
|
@@ -7,8 +7,9 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
|
|
|
7
7
|
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
8
8
|
});
|
|
9
9
|
};
|
|
10
|
-
import { EventBus } from "./fromRimori/EventBus";
|
|
11
10
|
import { createClient } from "@supabase/supabase-js";
|
|
11
|
+
import { EventBus } from "../fromRimori/EventBus";
|
|
12
|
+
import { DEFAULT_ANON_KEY, DEFAULT_ENDPOINT } from "../utils/endpoint";
|
|
12
13
|
export class StandaloneClient {
|
|
13
14
|
constructor(config) {
|
|
14
15
|
this.supabase = createClient(config.url, config.key);
|
|
@@ -17,14 +18,14 @@ export class StandaloneClient {
|
|
|
17
18
|
static getInstance() {
|
|
18
19
|
return __awaiter(this, void 0, void 0, function* () {
|
|
19
20
|
if (!StandaloneClient.instance) {
|
|
20
|
-
const config = yield fetch("
|
|
21
|
+
const config = yield fetch("https://app.rimori.se/config.json").then(res => res.json()).catch(err => {
|
|
21
22
|
console.warn("Error fetching config.json, using default values", err);
|
|
22
|
-
return {
|
|
23
|
-
SUPABASE_URL: "https://pheptqdoqsdnadgoihvr.supabase.co",
|
|
24
|
-
SUPABASE_ANON_KEY: "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJzdXBhYmFzZSIsInJlZiI6InBoZXB0cWRvcXNkbmFkZ29paHZyIiwicm9sZSI6ImFub24iLCJpYXQiOjE3MzE2OTY2ODcsImV4cCI6MjA0NzI3MjY4N30.4GPFAXTF8685FaXISdAPNCIM-H3RGLo8GbyhQpu1mP0",
|
|
25
|
-
};
|
|
26
23
|
});
|
|
27
|
-
StandaloneClient.instance = new StandaloneClient({
|
|
24
|
+
StandaloneClient.instance = new StandaloneClient({
|
|
25
|
+
url: (config === null || config === void 0 ? void 0 : config.SUPABASE_URL) || DEFAULT_ENDPOINT,
|
|
26
|
+
key: (config === null || config === void 0 ? void 0 : config.SUPABASE_ANON_KEY) || DEFAULT_ANON_KEY,
|
|
27
|
+
backendUrl: (config === null || config === void 0 ? void 0 : config.BACKEND_URL) || 'https://api.rimori.se',
|
|
28
|
+
});
|
|
28
29
|
}
|
|
29
30
|
return StandaloneClient.instance;
|
|
30
31
|
});
|
|
@@ -61,15 +62,28 @@ export class StandaloneClient {
|
|
|
61
62
|
var _a;
|
|
62
63
|
const session = yield supabase.auth.getSession();
|
|
63
64
|
console.log("session", session);
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
65
|
+
// Call the NestJS backend endpoint instead of the Supabase edge function
|
|
66
|
+
const response = yield fetch(`${config.backendUrl}/plugin/token`, {
|
|
67
|
+
method: 'POST',
|
|
68
|
+
headers: {
|
|
69
|
+
'Content-Type': 'application/json',
|
|
70
|
+
'Authorization': `Bearer ${(_a = session.data.session) === null || _a === void 0 ? void 0 : _a.access_token}`
|
|
71
|
+
},
|
|
72
|
+
body: JSON.stringify({
|
|
73
|
+
pluginId: pluginId
|
|
74
|
+
})
|
|
75
|
+
});
|
|
76
|
+
if (!response.ok) {
|
|
77
|
+
const errorText = yield response.text();
|
|
78
|
+
throw new Error(`Failed to get plugin token. ${response.status}: ${errorText}`);
|
|
67
79
|
}
|
|
80
|
+
const data = yield response.json();
|
|
68
81
|
return {
|
|
69
82
|
token: data.token,
|
|
70
83
|
pluginId: pluginId,
|
|
71
84
|
url: config.url,
|
|
72
85
|
key: config.key,
|
|
86
|
+
backendUrl: config.backendUrl,
|
|
73
87
|
tablePrefix: pluginId,
|
|
74
88
|
expiration: new Date(Date.now() + 1000 * 60 * 60 * 1.5), // 1.5 hours
|
|
75
89
|
};
|
|
@@ -1 +1,2 @@
|
|
|
1
|
-
export declare function setTheme(): void;
|
|
1
|
+
export declare function setTheme(theme?: string | null): void;
|
|
2
|
+
export declare function isDarkTheme(theme?: string | null): boolean;
|
|
@@ -1,13 +1,19 @@
|
|
|
1
|
-
export function setTheme() {
|
|
2
|
-
const urlParams = new URLSearchParams(window.location.search);
|
|
3
|
-
let theme = urlParams.get('theme');
|
|
4
|
-
if (!theme || theme === 'system') {
|
|
5
|
-
theme = window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light';
|
|
6
|
-
}
|
|
1
|
+
export function setTheme(theme) {
|
|
7
2
|
document.documentElement.classList.add("dark:text-gray-200");
|
|
8
|
-
if (theme
|
|
3
|
+
if (isDarkTheme(theme)) {
|
|
9
4
|
document.documentElement.setAttribute("data-theme", "dark");
|
|
10
5
|
document.documentElement.classList.add('dark', "dark:bg-gray-950");
|
|
11
6
|
document.documentElement.style.background = "hsl(var(--background))";
|
|
12
7
|
}
|
|
13
8
|
}
|
|
9
|
+
export function isDarkTheme(theme) {
|
|
10
|
+
// If no theme provided, try to get from URL as fallback (for standalone mode)
|
|
11
|
+
if (!theme) {
|
|
12
|
+
const urlParams = new URLSearchParams(window.location.search);
|
|
13
|
+
theme = urlParams.get('theme');
|
|
14
|
+
}
|
|
15
|
+
if (!theme || theme === 'system') {
|
|
16
|
+
return window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches;
|
|
17
|
+
}
|
|
18
|
+
return theme === 'dark';
|
|
19
|
+
}
|
|
@@ -3,7 +3,10 @@ import { RimoriClient } from '../plugin/RimoriClient';
|
|
|
3
3
|
interface PluginProviderProps {
|
|
4
4
|
children: ReactNode;
|
|
5
5
|
pluginId: string;
|
|
6
|
+
settings?: {
|
|
7
|
+
disableContextMenu?: boolean;
|
|
8
|
+
};
|
|
6
9
|
}
|
|
7
10
|
export declare const PluginProvider: React.FC<PluginProviderProps>;
|
|
8
|
-
export declare const
|
|
11
|
+
export declare const useRimori: () => RimoriClient;
|
|
9
12
|
export {};
|
|
@@ -10,34 +10,47 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
|
|
|
10
10
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
11
11
|
import { createContext, useContext, useEffect, useState } from 'react';
|
|
12
12
|
import { PluginController } from '../plugin/PluginController';
|
|
13
|
-
import { EventBusHandler } from '../
|
|
14
|
-
import ContextMenu from '../
|
|
13
|
+
import { EventBusHandler } from '../fromRimori/EventBus';
|
|
14
|
+
import ContextMenu from '../components/components/ContextMenu';
|
|
15
15
|
import { StandaloneClient } from '../plugin/StandaloneClient';
|
|
16
16
|
const PluginContext = createContext(null);
|
|
17
|
-
export const PluginProvider = ({ children, pluginId }) => {
|
|
17
|
+
export const PluginProvider = ({ children, pluginId, settings }) => {
|
|
18
18
|
const [plugin, setPlugin] = useState(null);
|
|
19
19
|
const [standaloneClient, setStandaloneClient] = useState(false);
|
|
20
|
+
const [applicationMode, setApplicationMode] = useState(null);
|
|
21
|
+
const [theme, setTheme] = useState(null);
|
|
22
|
+
const isSidebar = applicationMode === "sidebar";
|
|
23
|
+
const isSettings = applicationMode === "settings";
|
|
20
24
|
useEffect(() => {
|
|
21
25
|
initEventBus(pluginId);
|
|
22
|
-
|
|
26
|
+
// Check if we're in an iframe context - if not, we're standalone
|
|
27
|
+
const standaloneDetected = window === window.parent;
|
|
23
28
|
if (standaloneDetected && !standaloneClient) {
|
|
24
29
|
StandaloneClient.getInstance().then(client => {
|
|
25
30
|
client.needsLogin().then((needLogin) => setStandaloneClient(needLogin ? client : true));
|
|
26
31
|
});
|
|
27
32
|
}
|
|
28
33
|
if ((!standaloneDetected && !plugin) || (standaloneDetected && standaloneClient === true)) {
|
|
29
|
-
PluginController.getInstance(pluginId, standaloneDetected).then(
|
|
34
|
+
PluginController.getInstance(pluginId, standaloneDetected).then(client => {
|
|
35
|
+
setPlugin(client);
|
|
36
|
+
// Get applicationMode and theme from MessageChannel query params
|
|
37
|
+
if (!standaloneDetected) {
|
|
38
|
+
const mode = client.getQueryParam("applicationMode");
|
|
39
|
+
const themeParam = client.getQueryParam("rm_theme");
|
|
40
|
+
setApplicationMode(mode);
|
|
41
|
+
setTheme(themeParam);
|
|
42
|
+
}
|
|
43
|
+
});
|
|
30
44
|
}
|
|
31
45
|
}, [pluginId, standaloneClient]);
|
|
32
46
|
//route change
|
|
33
47
|
useEffect(() => {
|
|
34
48
|
if (!plugin)
|
|
35
49
|
return;
|
|
36
|
-
const url = new URL(window.location.href);
|
|
37
50
|
//sidebar pages should not report url changes
|
|
38
|
-
if (
|
|
51
|
+
if (isSidebar)
|
|
39
52
|
return;
|
|
40
|
-
let lastHash =
|
|
53
|
+
let lastHash = window.location.hash;
|
|
41
54
|
const emitUrlChange = (url) => plugin.event.emit('session.triggerUrlChange', { url });
|
|
42
55
|
const interval = setInterval(() => {
|
|
43
56
|
if (lastHash === window.location.hash)
|
|
@@ -66,18 +79,31 @@ export const PluginProvider = ({ children, pluginId }) => {
|
|
|
66
79
|
if (!plugin) {
|
|
67
80
|
return "";
|
|
68
81
|
}
|
|
69
|
-
return (_jsxs(PluginContext.Provider, { value: plugin, children: [_jsx(ContextMenu, { client: plugin }), children] }));
|
|
82
|
+
return (_jsxs(PluginContext.Provider, { value: plugin, children: [!(settings === null || settings === void 0 ? void 0 : settings.disableContextMenu) && !isSidebar && !isSettings && _jsx(ContextMenu, { client: plugin }), children] }));
|
|
70
83
|
};
|
|
71
|
-
export const
|
|
84
|
+
export const useRimori = () => {
|
|
72
85
|
const context = useContext(PluginContext);
|
|
73
86
|
if (context === null) {
|
|
74
|
-
throw new Error('
|
|
87
|
+
throw new Error('useRimori must be used within an PluginProvider');
|
|
75
88
|
}
|
|
76
89
|
return context;
|
|
77
90
|
};
|
|
78
|
-
function
|
|
91
|
+
function getUrlParam(name) {
|
|
92
|
+
// First try to get from URL hash query params (for compatibility)
|
|
93
|
+
const hashParts = window.location.hash.split('?');
|
|
94
|
+
if (hashParts.length > 1) {
|
|
95
|
+
const hashParams = new URLSearchParams(hashParts[1]);
|
|
96
|
+
const hashValue = hashParams.get(name);
|
|
97
|
+
if (hashValue)
|
|
98
|
+
return hashValue;
|
|
99
|
+
}
|
|
100
|
+
// Fallback to regular URL search params
|
|
79
101
|
const url = new URL(window.location.href);
|
|
80
|
-
|
|
102
|
+
return url.searchParams.get(name);
|
|
103
|
+
}
|
|
104
|
+
function initEventBus(pluginId) {
|
|
105
|
+
// For now, use URL fallback for EventBus naming - this will be updated once MessageChannel is ready
|
|
106
|
+
const isSidebar = getUrlParam("applicationMode") === "sidebar";
|
|
81
107
|
EventBusHandler.getInstance("Plugin EventBus " + pluginId + " " + (isSidebar ? "sidebar" : "main"));
|
|
82
108
|
}
|
|
83
109
|
function StandaloneAuth({ onLogin }) {
|
package/dist/utils/Language.d.ts
CHANGED
|
@@ -61,6 +61,7 @@ export type Language = keyof typeof languageKeys;
|
|
|
61
61
|
/**
|
|
62
62
|
* Get the language name from the language code
|
|
63
63
|
* @param languageCode The code of the language
|
|
64
|
+
* @param capitalize Whether to capitalize the first letter of the language name
|
|
64
65
|
* @returns The language name
|
|
65
66
|
*/
|
|
66
|
-
export declare function getLanguageName(languageCode: Language): string;
|
|
67
|
+
export declare function getLanguageName(languageCode: Language, capitalize?: boolean): string;
|
package/dist/utils/Language.js
CHANGED
|
@@ -60,8 +60,10 @@ export const languageKeys = {
|
|
|
60
60
|
/**
|
|
61
61
|
* Get the language name from the language code
|
|
62
62
|
* @param languageCode The code of the language
|
|
63
|
+
* @param capitalize Whether to capitalize the first letter of the language name
|
|
63
64
|
* @returns The language name
|
|
64
65
|
*/
|
|
65
|
-
export function getLanguageName(languageCode) {
|
|
66
|
-
|
|
66
|
+
export function getLanguageName(languageCode, capitalize = false) {
|
|
67
|
+
const lang = languageKeys[languageCode];
|
|
68
|
+
return capitalize ? lang.charAt(0).toUpperCase() + lang.slice(1) : lang;
|
|
67
69
|
}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Maps audio MIME types to their corresponding file extensions
|
|
3
|
+
* OpenAI supports: mp3, mp4, mpeg, mpga, m4a, wav, webm
|
|
4
|
+
*/
|
|
5
|
+
export declare const AUDIO_MIME_TO_EXTENSION: Record<string, string>;
|
|
6
|
+
/**
|
|
7
|
+
* OpenAI supported audio formats for STT API
|
|
8
|
+
*/
|
|
9
|
+
export declare const OPENAI_SUPPORTED_FORMATS: string[];
|
|
10
|
+
/**
|
|
11
|
+
* Determines the appropriate file extension for an audio MIME type
|
|
12
|
+
* @param mimeType - The MIME type of the audio
|
|
13
|
+
* @returns The file extension (without dot) or null if unsupported
|
|
14
|
+
*/
|
|
15
|
+
export declare function getAudioFormatFromMimeType(mimeType: string): string | null;
|
|
16
|
+
/**
|
|
17
|
+
* Checks if an audio MIME type is supported by OpenAI
|
|
18
|
+
* @param mimeType - The MIME type to check
|
|
19
|
+
* @returns True if supported, false otherwise
|
|
20
|
+
*/
|
|
21
|
+
export declare function isAudioFormatSupported(mimeType: string): boolean;
|
|
22
|
+
/**
|
|
23
|
+
* Gets a human-readable list of supported audio formats
|
|
24
|
+
* @returns Formatted string of supported formats
|
|
25
|
+
*/
|
|
26
|
+
export declare function getSupportedFormatsList(): string;
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Maps audio MIME types to their corresponding file extensions
|
|
3
|
+
* OpenAI supports: mp3, mp4, mpeg, mpga, m4a, wav, webm
|
|
4
|
+
*/
|
|
5
|
+
export const AUDIO_MIME_TO_EXTENSION = {
|
|
6
|
+
'audio/mpeg': 'mp3',
|
|
7
|
+
'audio/mp3': 'mp3',
|
|
8
|
+
'audio/mp4': 'mp4',
|
|
9
|
+
'audio/m4a': 'm4a',
|
|
10
|
+
'audio/wav': 'wav',
|
|
11
|
+
'audio/wave': 'wav',
|
|
12
|
+
'audio/x-wav': 'wav',
|
|
13
|
+
'audio/webm': 'webm',
|
|
14
|
+
'audio/ogg': 'webm', // Convert ogg to webm for OpenAI compatibility
|
|
15
|
+
'audio/aac': 'm4a', // Convert aac to m4a for OpenAI compatibility
|
|
16
|
+
'audio/x-aac': 'm4a',
|
|
17
|
+
'audio/3gpp': 'mp4', // Convert 3gpp to mp4
|
|
18
|
+
'audio/3gpp2': 'mp4',
|
|
19
|
+
'audio/amr': 'mp4', // Convert amr to mp4
|
|
20
|
+
'audio/amr-wb': 'mp4',
|
|
21
|
+
'audio/flac': 'wav', // Convert flac to wav
|
|
22
|
+
'audio/x-flac': 'wav',
|
|
23
|
+
'audio/opus': 'webm', // Convert opus to webm
|
|
24
|
+
'audio/x-opus': 'webm',
|
|
25
|
+
};
|
|
26
|
+
/**
|
|
27
|
+
* OpenAI supported audio formats for STT API
|
|
28
|
+
*/
|
|
29
|
+
export const OPENAI_SUPPORTED_FORMATS = ['mp3', 'mp4', 'mpeg', 'mpga', 'm4a', 'wav', 'webm'];
|
|
30
|
+
/**
|
|
31
|
+
* Determines the appropriate file extension for an audio MIME type
|
|
32
|
+
* @param mimeType - The MIME type of the audio
|
|
33
|
+
* @returns The file extension (without dot) or null if unsupported
|
|
34
|
+
*/
|
|
35
|
+
export function getAudioFormatFromMimeType(mimeType) {
|
|
36
|
+
const normalizedMimeType = mimeType.toLowerCase();
|
|
37
|
+
// Try to get format from MIME type mapping first
|
|
38
|
+
let format = AUDIO_MIME_TO_EXTENSION[normalizedMimeType];
|
|
39
|
+
// If no mapping found, try to extract from MIME type
|
|
40
|
+
if (!format && normalizedMimeType.includes('audio/')) {
|
|
41
|
+
format = normalizedMimeType.replace('audio/', '');
|
|
42
|
+
}
|
|
43
|
+
// Handle special cases
|
|
44
|
+
if (format === 'mpeg') {
|
|
45
|
+
format = 'mp3'; // OpenAI expects mp3, not mpeg
|
|
46
|
+
}
|
|
47
|
+
// Validate the format
|
|
48
|
+
if (!format || !OPENAI_SUPPORTED_FORMATS.includes(format)) {
|
|
49
|
+
return null;
|
|
50
|
+
}
|
|
51
|
+
return format;
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
54
|
+
* Checks if an audio MIME type is supported by OpenAI
|
|
55
|
+
* @param mimeType - The MIME type to check
|
|
56
|
+
* @returns True if supported, false otherwise
|
|
57
|
+
*/
|
|
58
|
+
export function isAudioFormatSupported(mimeType) {
|
|
59
|
+
return getAudioFormatFromMimeType(mimeType) !== null;
|
|
60
|
+
}
|
|
61
|
+
/**
|
|
62
|
+
* Gets a human-readable list of supported audio formats
|
|
63
|
+
* @returns Formatted string of supported formats
|
|
64
|
+
*/
|
|
65
|
+
export function getSupportedFormatsList() {
|
|
66
|
+
return OPENAI_SUPPORTED_FORMATS.join(', ');
|
|
67
|
+
}
|
|
@@ -6,5 +6,5 @@ export function getDifficultyLabel(difficulty) {
|
|
|
6
6
|
return codes[difficulty];
|
|
7
7
|
}
|
|
8
8
|
export function getNeighborDifficultyLevel(difficulty, difficultyAdjustment) {
|
|
9
|
-
return getDifficultyLabel(getDifficultyLevel(difficulty) + difficultyAdjustment);
|
|
9
|
+
return getDifficultyLabel(getDifficultyLevel(difficulty) + difficultyAdjustment - 1);
|
|
10
10
|
}
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
export declare const DEFAULT_ENDPOINT = "https://pheptqdoqsdnadgoihvr.supabase.co";
|
|
2
|
+
export declare const DEFAULT_ANON_KEY = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJzdXBhYmFzZSIsInJlZiI6InBoZXB0cWRvcXNkbmFkZ29paHZyIiwicm9sZSI6ImFub24iLCJpYXQiOjE3MzE2OTY2ODcsImV4cCI6MjA0NzI3MjY4N30.4GPFAXTF8685FaXISdAPNCIM-H3RGLo8GbyhQpu1mP0";
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
export const DEFAULT_ENDPOINT = "https://pheptqdoqsdnadgoihvr.supabase.co";
|
|
2
|
+
export const DEFAULT_ANON_KEY = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJzdXBhYmFzZSIsInJlZiI6InBoZXB0cWRvcXNkbmFkZ29paHZyIiwicm9sZSI6ImFub24iLCJpYXQiOjE3MzE2OTY2ODcsImV4cCI6MjA0NzI3MjY4N30.4GPFAXTF8685FaXISdAPNCIM-H3RGLo8GbyhQpu1mP0";
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { RimoriClient } from "../plugin/RimoriClient";
|
|
2
2
|
/**
|
|
3
3
|
* Sets up the web worker for the plugin to be able receive and send messages to Rimori.
|
|
4
|
-
* @param
|
|
4
|
+
* @param pluginId - The id of the plugin to setup the worker for.
|
|
5
|
+
* @param init - The function containing the initialization logic.
|
|
5
6
|
*/
|
|
6
|
-
export declare function setupWorker(init: (
|
|
7
|
+
export declare function setupWorker(pluginId: string, init: (client: RimoriClient) => void | Promise<void>): Promise<void>;
|