@rimori/client 1.0.3 → 1.0.4
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 +51 -0
- package/dist/components/CRUDModal.js +0 -1
- package/dist/components/ai/Assistant.d.ts +9 -0
- package/dist/components/ai/Assistant.js +59 -0
- package/dist/components/ai/Avatar.d.ts +11 -0
- package/dist/components/ai/Avatar.js +39 -0
- package/dist/components/ai/EmbeddedAssistent/AudioInputField.d.ts +7 -0
- package/dist/components/ai/EmbeddedAssistent/AudioInputField.js +38 -0
- package/dist/components/ai/EmbeddedAssistent/CircleAudioAvatar.d.ts +7 -0
- package/dist/components/ai/EmbeddedAssistent/CircleAudioAvatar.js +59 -0
- package/dist/components/ai/EmbeddedAssistent/TTS/MessageSender.d.ts +19 -0
- package/dist/components/ai/EmbeddedAssistent/TTS/MessageSender.js +86 -0
- package/dist/components/ai/EmbeddedAssistent/TTS/Player.d.ts +25 -0
- package/dist/components/ai/EmbeddedAssistent/TTS/Player.js +180 -0
- package/dist/components/ai/EmbeddedAssistent/VoiceRecoder.d.ts +7 -0
- package/dist/components/ai/EmbeddedAssistent/VoiceRecoder.js +45 -0
- package/dist/components/ai/utils.d.ts +6 -0
- package/dist/components/ai/utils.js +14 -0
- package/dist/components/audio/Playbutton.js +4 -5
- package/dist/components/avatar/Assistant.d.ts +9 -0
- package/dist/components/avatar/Assistant.js +59 -0
- package/dist/components/avatar/Avatar.d.ts +12 -0
- package/dist/components/avatar/Avatar.js +42 -0
- package/dist/components/avatar/EmbeddedAssistent/AudioInputField.d.ts +7 -0
- package/dist/components/avatar/EmbeddedAssistent/AudioInputField.js +38 -0
- package/dist/components/avatar/EmbeddedAssistent/CircleAudioAvatar.d.ts +7 -0
- package/dist/components/avatar/EmbeddedAssistent/CircleAudioAvatar.js +59 -0
- package/dist/components/avatar/EmbeddedAssistent/TTS/MessageSender.d.ts +19 -0
- package/dist/components/avatar/EmbeddedAssistent/TTS/MessageSender.js +84 -0
- package/dist/components/avatar/EmbeddedAssistent/TTS/Player.d.ts +25 -0
- package/dist/components/avatar/EmbeddedAssistent/TTS/Player.js +180 -0
- package/dist/components/avatar/EmbeddedAssistent/VoiceRecoder.d.ts +7 -0
- package/dist/components/avatar/EmbeddedAssistent/VoiceRecoder.js +45 -0
- package/dist/components/avatar/utils.d.ts +6 -0
- package/dist/components/avatar/utils.js +14 -0
- package/dist/components.d.ts +9 -0
- package/dist/components.js +10 -0
- package/dist/controller/AIController.d.ts +4 -3
- package/dist/controller/AIController.js +32 -8
- package/dist/controller/ObjectController.d.ts +2 -2
- package/dist/controller/ObjectController.js +4 -5
- package/dist/controller/SettingsController.d.ts +2 -1
- package/dist/controller/SettingsController.js +9 -0
- package/dist/controller/SharedContentController.js +6 -6
- package/dist/core.d.ts +9 -0
- package/dist/core.js +10 -0
- package/dist/hooks/UseChatHook.js +2 -2
- package/dist/index.d.ts +3 -2
- package/dist/index.js +4 -2
- package/dist/plugin/PluginController.d.ts +4 -12
- package/dist/plugin/PluginController.js +43 -70
- package/dist/plugin/RimoriClient.d.ts +85 -32
- package/dist/plugin/RimoriClient.js +98 -77
- package/dist/plugin/fromRimori/EventBus.d.ts +98 -0
- package/dist/plugin/fromRimori/EventBus.js +240 -0
- package/dist/providers/PluginProvider.d.ts +1 -0
- package/dist/providers/PluginProvider.js +10 -12
- package/dist/worker/WorkerSetup.d.ts +6 -0
- package/dist/worker/WorkerSetup.js +79 -0
- package/package.json +16 -3
- package/src/components/CRUDModal.tsx +1 -3
- package/src/components/ai/Assistant.tsx +96 -0
- package/src/components/ai/Avatar.tsx +61 -0
- package/src/components/ai/EmbeddedAssistent/AudioInputField.tsx +64 -0
- package/src/components/ai/EmbeddedAssistent/CircleAudioAvatar.tsx +75 -0
- package/src/components/ai/EmbeddedAssistent/TTS/MessageSender.ts +91 -0
- package/src/components/ai/EmbeddedAssistent/TTS/Player.ts +192 -0
- package/src/components/ai/EmbeddedAssistent/VoiceRecoder.tsx +56 -0
- package/src/components/ai/utils.ts +23 -0
- package/src/components/audio/Playbutton.tsx +4 -5
- package/src/components.ts +10 -0
- package/src/controller/AIController.ts +84 -60
- package/src/controller/ObjectController.ts +4 -6
- package/src/controller/SettingsController.ts +9 -1
- package/src/controller/SharedContentController.ts +6 -6
- package/src/core.ts +10 -0
- package/src/hooks/UseChatHook.ts +2 -2
- package/src/index.ts +4 -2
- package/src/plugin/PluginController.ts +46 -76
- package/src/plugin/RimoriClient.ts +147 -85
- package/src/plugin/fromRimori/EventBus.ts +301 -0
- package/src/plugin/fromRimori/readme.md +2 -0
- package/src/providers/PluginProvider.tsx +12 -14
- package/src/worker/WorkerSetup.ts +80 -0
- package/dist/CRUDModal.d.ts +0 -16
- package/dist/CRUDModal.js +0 -31
- package/dist/MarkdownEditor.d.ts +0 -8
- package/dist/MarkdownEditor.js +0 -46
- package/dist/audio/Playbutton.d.ts +0 -14
- package/dist/audio/Playbutton.js +0 -73
- package/dist/components/hooks/UseChatHook.d.ts +0 -15
- package/dist/components/hooks/UseChatHook.js +0 -21
- package/dist/controller/PluginController.d.ts +0 -14
- package/dist/controller/PluginController.js +0 -30
- package/dist/plugin/AIController copy.d.ts +0 -22
- package/dist/plugin/AIController copy.js +0 -68
- package/dist/plugin/AIController.d.ts +0 -22
- package/dist/plugin/AIController.js +0 -68
- package/dist/plugin/ObjectController.d.ts +0 -34
- package/dist/plugin/ObjectController.js +0 -77
- package/dist/plugin/SettingController.d.ts +0 -13
- package/dist/plugin/SettingController.js +0 -55
- package/dist/plugin/VoiceController.d.ts +0 -2
- package/dist/plugin/VoiceController.js +0 -27
- package/dist/providers/EventEmitter.d.ts +0 -11
- package/dist/providers/EventEmitter.js +0 -41
- package/dist/providers/EventEmitterContext.d.ts +0 -6
- package/dist/providers/EventEmitterContext.js +0 -19
- package/dist/utils/DifficultyConverter.d.ts +0 -3
- package/dist/utils/DifficultyConverter.js +0 -7
- package/dist/utils/constants.d.ts +0 -4
- package/dist/utils/constants.js +0 -12
- package/dist/utils/plugin/Client.d.ts +0 -72
- package/dist/utils/plugin/Client.js +0 -118
- package/dist/utils/plugin/PluginController.d.ts +0 -36
- package/dist/utils/plugin/PluginController.js +0 -119
- package/dist/utils/plugin/PluginUtils.d.ts +0 -2
- package/dist/utils/plugin/PluginUtils.js +0 -23
- package/dist/utils/plugin/RimoriClient.d.ts +0 -72
- package/dist/utils/plugin/RimoriClient.js +0 -118
- package/dist/utils/plugin/ThemeSetter.d.ts +0 -1
- package/dist/utils/plugin/ThemeSetter.js +0 -13
- package/dist/utils/plugin/WhereClauseBuilder.d.ts +0 -24
- package/dist/utils/plugin/WhereClauseBuilder.js +0 -79
- package/dist/utils/plugin/providers/EventEmitter.d.ts +0 -11
- package/dist/utils/plugin/providers/EventEmitter.js +0 -41
- package/dist/utils/plugin/providers/EventEmitterContext.d.ts +0 -6
- package/dist/utils/plugin/providers/EventEmitterContext.js +0 -19
- package/dist/utils/plugin/providers/PluginProvider.d.ts +0 -8
- package/dist/utils/plugin/providers/PluginProvider.js +0 -49
- package/src/providers/EventEmitter.ts +0 -48
- package/src/providers/EventEmitterContext.tsx +0 -27
- package/src/utils/constants.ts +0 -18
|
@@ -1,5 +1,3 @@
|
|
|
1
|
-
import { env } from "../utils/constants";
|
|
2
|
-
|
|
3
1
|
type PrimitiveType = 'string' | 'number' | 'boolean';
|
|
4
2
|
|
|
5
3
|
// This is the type that can appear in the `type` property
|
|
@@ -35,8 +33,8 @@ export interface ObjectRequest {
|
|
|
35
33
|
instructions: string;
|
|
36
34
|
}
|
|
37
35
|
|
|
38
|
-
export async function generateObject(request: ObjectRequest, token: string) {
|
|
39
|
-
return await fetch(`${
|
|
36
|
+
export async function generateObject(supabaseUrl: string, request: ObjectRequest, token: string) {
|
|
37
|
+
return await fetch(`${supabaseUrl}/functions/v1/llm-object`, {
|
|
40
38
|
method: 'POST',
|
|
41
39
|
body: JSON.stringify({
|
|
42
40
|
stream: false,
|
|
@@ -51,9 +49,9 @@ export async function generateObject(request: ObjectRequest, token: string) {
|
|
|
51
49
|
// TODO adjust stream to work with object
|
|
52
50
|
export type OnLLMResponse = (id: string, response: string, finished: boolean, toolInvocations?: any[]) => void;
|
|
53
51
|
|
|
54
|
-
export async function streamObject(request: ObjectRequest, onResponse: OnLLMResponse, token: string) {
|
|
52
|
+
export async function streamObject(supabaseUrl: string, request: ObjectRequest, onResponse: OnLLMResponse, token: string) {
|
|
55
53
|
const messageId = Math.random().toString(36).substring(3);
|
|
56
|
-
const response = await fetch(`${
|
|
54
|
+
const response = await fetch(`${supabaseUrl}/functions/v1/llm-object`, {
|
|
57
55
|
method: 'POST',
|
|
58
56
|
body: JSON.stringify({
|
|
59
57
|
stream: true,
|
|
@@ -3,7 +3,7 @@ import { LanguageLevel } from "../utils/difficultyConverter";
|
|
|
3
3
|
|
|
4
4
|
type SettingsType = "user" | "system" | "plugin";
|
|
5
5
|
|
|
6
|
-
export interface
|
|
6
|
+
export interface UserInfo {
|
|
7
7
|
motherTongue: string;
|
|
8
8
|
languageLevel: LanguageLevel;
|
|
9
9
|
contextMenuOnSelect: boolean;
|
|
@@ -45,6 +45,14 @@ export class SettingsController {
|
|
|
45
45
|
await this.supabase.from("plugin_settings").upsert({ plugin_id: this.pluginId, settings });
|
|
46
46
|
}
|
|
47
47
|
|
|
48
|
+
public async getUserInfo(): Promise<UserInfo> {
|
|
49
|
+
return this.getSettings<UserInfo>({
|
|
50
|
+
motherTongue: "sv",
|
|
51
|
+
languageLevel: "A1",
|
|
52
|
+
contextMenuOnSelect: true,
|
|
53
|
+
}, "user");
|
|
54
|
+
}
|
|
55
|
+
|
|
48
56
|
/**
|
|
49
57
|
* Get the settings for the plugin. T can be any type of settings, UserSettings or SystemSettings.
|
|
50
58
|
* @param defaultSettings The default settings to use if no settings are found.
|
|
@@ -24,14 +24,14 @@ export class SharedContentController {
|
|
|
24
24
|
filter?: { column: string, value: string | number | boolean },
|
|
25
25
|
): Promise<R[]> {
|
|
26
26
|
const queryParameter = { filter_column: filter?.column || null, filter_value: filter?.value || null, unread: true }
|
|
27
|
-
const { data: newAssignments } = await this.rimoriClient.rpc(type + "_entries", queryParameter)
|
|
27
|
+
const { data: newAssignments } = await this.rimoriClient.db.rpc(type + "_entries", queryParameter)
|
|
28
28
|
console.log('newAssignments:', newAssignments);
|
|
29
29
|
|
|
30
30
|
if ((newAssignments as any[]).length > 0) {
|
|
31
31
|
return newAssignments as R[];
|
|
32
32
|
}
|
|
33
33
|
// generate new assignments
|
|
34
|
-
const { data: oldAssignments } = await this.rimoriClient.rpc(type + "_entries", { ...queryParameter, unread: false })
|
|
34
|
+
const { data: oldAssignments } = await this.rimoriClient.db.rpc(type + "_entries", { ...queryParameter, unread: false })
|
|
35
35
|
console.log('oldAssignments:', oldAssignments);
|
|
36
36
|
const reservedTopics = this.getReservedTopics(oldAssignments as BasicAssignment[]);
|
|
37
37
|
|
|
@@ -39,7 +39,7 @@ export class SharedContentController {
|
|
|
39
39
|
if (!request.tool.keywords || !request.tool.topic) {
|
|
40
40
|
throw new Error("topic or keywords not found in the request schema");
|
|
41
41
|
}
|
|
42
|
-
const instructions = await this.rimoriClient.
|
|
42
|
+
const instructions = await this.rimoriClient.llm.getObject(request);
|
|
43
43
|
console.log('instructions:', instructions);
|
|
44
44
|
|
|
45
45
|
const preparedData = {
|
|
@@ -47,7 +47,7 @@ export class SharedContentController {
|
|
|
47
47
|
...instructions,
|
|
48
48
|
keywords: this.purifyStringArray(instructions.keywords),
|
|
49
49
|
};
|
|
50
|
-
return await this.rimoriClient.from(type).insert(preparedData).then(() => [preparedData] as R[]);
|
|
50
|
+
return await this.rimoriClient.db.from(type).insert(preparedData).then(() => [preparedData] as R[]);
|
|
51
51
|
}
|
|
52
52
|
|
|
53
53
|
private getReservedTopics(oldAssignments: BasicAssignment[]) {
|
|
@@ -62,10 +62,10 @@ export class SharedContentController {
|
|
|
62
62
|
}
|
|
63
63
|
|
|
64
64
|
public async getSharedContent<T extends BasicAssignment>(type: string, id: string): Promise<T> {
|
|
65
|
-
return await this.rimoriClient.from(type).select().eq('id', id).single() as unknown as T;
|
|
65
|
+
return await this.rimoriClient.db.from(type).select().eq('id', id).single() as unknown as T;
|
|
66
66
|
}
|
|
67
67
|
|
|
68
68
|
public async completeSharedContent(type: string, assignmentId: string) {
|
|
69
|
-
await this.rimoriClient.from(type + "_result").insert({ assignment_id: assignmentId });
|
|
69
|
+
await this.rimoriClient.db.from(type + "_result").insert({ assignment_id: assignmentId });
|
|
70
70
|
}
|
|
71
71
|
}
|
package/src/core.ts
ADDED
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
// Core functionality exports
|
|
2
|
+
export * from "./controller/AIController";
|
|
3
|
+
export * from "./controller/SharedContentController";
|
|
4
|
+
export * from "./controller/SettingsController";
|
|
5
|
+
export * from "./plugin/RimoriClient";
|
|
6
|
+
export * from "./plugin/PluginController";
|
|
7
|
+
export * from "./utils/difficultyConverter";
|
|
8
|
+
export * from "./utils/PluginUtils";
|
|
9
|
+
export * from "./worker/WorkerSetup";
|
|
10
|
+
export * from "./plugin/fromRimori/EventBus";
|
package/src/hooks/UseChatHook.ts
CHANGED
|
@@ -5,10 +5,10 @@ import { ToolInvocation, Tool, Message } from "../controller/AIController";
|
|
|
5
5
|
export function useChat(tools?: Tool[]) {
|
|
6
6
|
const [messages, setMessages] = React.useState<Message[]>([]);
|
|
7
7
|
const [isLoading, setIsLoading] = React.useState(false);
|
|
8
|
-
const {
|
|
8
|
+
const { llm } = usePlugin();
|
|
9
9
|
|
|
10
10
|
const append = (appendMessages: Message[]) => {
|
|
11
|
-
|
|
11
|
+
llm.getSteamedText([...messages, ...appendMessages], (id, message, finished: boolean, toolInvocations?: ToolInvocation[]) => {
|
|
12
12
|
const lastMessage = messages[messages.length - 1];
|
|
13
13
|
setIsLoading(!finished);
|
|
14
14
|
|
package/src/index.ts
CHANGED
|
@@ -1,3 +1,6 @@
|
|
|
1
|
+
// Re-export everything
|
|
2
|
+
export * from './core';
|
|
3
|
+
export * from './components';
|
|
1
4
|
export * from "./components/MarkdownEditor";
|
|
2
5
|
export * from "./components/CRUDModal";
|
|
3
6
|
export * from "./components/Spinner";
|
|
@@ -8,8 +11,7 @@ export * from "./controller/SettingsController";
|
|
|
8
11
|
export * from "./hooks/UseChatHook";
|
|
9
12
|
export * from "./plugin/RimoriClient";
|
|
10
13
|
export * from "./plugin/ThemeSetter";
|
|
11
|
-
export * from "./providers/EventEmitter";
|
|
12
|
-
export * from "./providers/EventEmitterContext";
|
|
13
14
|
export * from "./providers/PluginProvider";
|
|
14
15
|
export * from "./utils/difficultyConverter";
|
|
15
16
|
export * from "./utils/PluginUtils";
|
|
17
|
+
export * from "./plugin/PluginController";
|
|
@@ -1,6 +1,9 @@
|
|
|
1
|
-
import { Child } from "ibridge-flex";
|
|
2
1
|
import { createClient, SupabaseClient } from '@supabase/supabase-js'
|
|
3
2
|
import { RimoriClient } from "./RimoriClient";
|
|
3
|
+
import { EventBus, EventBusMessage } from './fromRimori/EventBus';
|
|
4
|
+
import { setTheme } from './ThemeSetter';
|
|
5
|
+
|
|
6
|
+
setTheme();
|
|
4
7
|
|
|
5
8
|
interface SupabaseInfo {
|
|
6
9
|
url: string,
|
|
@@ -12,55 +15,43 @@ interface SupabaseInfo {
|
|
|
12
15
|
}
|
|
13
16
|
|
|
14
17
|
export class PluginController {
|
|
15
|
-
private static instance: PluginController;
|
|
16
18
|
private static client: RimoriClient;
|
|
17
|
-
private
|
|
18
|
-
private onceListeners: Map<string, any[]> = new Map();
|
|
19
|
-
private listeners: Map<string, any[]> = new Map();
|
|
19
|
+
private static instance: PluginController;
|
|
20
20
|
private communicationSecret: string | null = null;
|
|
21
|
-
private initialized = false;
|
|
22
21
|
private supabase: SupabaseClient | null = null;
|
|
23
22
|
private supabaseInfo: SupabaseInfo | null = null;
|
|
23
|
+
private pluginId: string;
|
|
24
24
|
|
|
25
|
-
private constructor() {
|
|
26
|
-
|
|
27
|
-
this.
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
25
|
+
private constructor(pluginId: string) {
|
|
26
|
+
this.pluginId = pluginId;
|
|
27
|
+
this.getClient = this.getClient.bind(this);
|
|
28
|
+
|
|
29
|
+
window.addEventListener("message", (event) => {
|
|
30
|
+
// console.log("client: message received", event);
|
|
31
|
+
const { topic, sender, data, eventId } = event.data.event as EventBusMessage;
|
|
32
|
+
|
|
33
|
+
// skip forwarding messages from own plugin
|
|
34
|
+
if (sender === pluginId) return;
|
|
35
|
+
|
|
36
|
+
EventBus.emit(sender, topic, data, eventId);
|
|
34
37
|
});
|
|
35
38
|
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
39
|
+
EventBus.on("*", (event) => {
|
|
40
|
+
// skip messages which are not from the own plugin
|
|
41
|
+
if (event.sender !== this.pluginId) return;
|
|
42
|
+
if (event.topic.startsWith("self.")) return;
|
|
43
|
+
window.parent.postMessage({ event, secret: this.getSecret() }, "*")
|
|
44
|
+
});
|
|
42
45
|
}
|
|
43
46
|
|
|
44
|
-
public static async getInstance(): Promise<RimoriClient> {
|
|
47
|
+
public static async getInstance(sender: string): Promise<RimoriClient> {
|
|
45
48
|
if (!PluginController.instance) {
|
|
46
|
-
PluginController.instance = new PluginController();
|
|
47
|
-
await PluginController.instance
|
|
48
|
-
PluginController.client = await RimoriClient.getInstance(
|
|
49
|
-
PluginController.instance
|
|
50
|
-
);
|
|
49
|
+
PluginController.instance = new PluginController(sender);
|
|
50
|
+
PluginController.client = await RimoriClient.getInstance(PluginController.instance);
|
|
51
51
|
}
|
|
52
52
|
return PluginController.client;
|
|
53
53
|
}
|
|
54
54
|
|
|
55
|
-
async init() {
|
|
56
|
-
if (this.initialized) return;
|
|
57
|
-
|
|
58
|
-
// Wait for the plugin to be ready
|
|
59
|
-
await this.plugin.handshake().then(() => this.initialized = true).catch((error: any) => {
|
|
60
|
-
console.error("Failed to initialize the plugin communication:", error);
|
|
61
|
-
});
|
|
62
|
-
}
|
|
63
|
-
|
|
64
55
|
private getSecret() {
|
|
65
56
|
if (!this.communicationSecret) {
|
|
66
57
|
const secret = new URLSearchParams(window.location.search).get("secret");
|
|
@@ -81,8 +72,8 @@ export class PluginController {
|
|
|
81
72
|
return { supabase: this.supabase, tablePrefix: this.supabaseInfo.tablePrefix, pluginId: this.supabaseInfo.pluginId };
|
|
82
73
|
}
|
|
83
74
|
|
|
84
|
-
|
|
85
|
-
|
|
75
|
+
const {data} = await EventBus.request<SupabaseInfo>(this.pluginId, "global.supabase.requestAccess");
|
|
76
|
+
this.supabaseInfo = data;
|
|
86
77
|
this.supabase = createClient(this.supabaseInfo.url, this.supabaseInfo.key, {
|
|
87
78
|
accessToken: () => Promise.resolve(this.getToken())
|
|
88
79
|
});
|
|
@@ -95,14 +86,14 @@ export class PluginController {
|
|
|
95
86
|
return this.supabaseInfo.token;
|
|
96
87
|
}
|
|
97
88
|
|
|
98
|
-
const
|
|
89
|
+
const {data} = await EventBus.request<{ token: string, expiration: Date }>(this.pluginId, "global.supabase.requestAccess");
|
|
99
90
|
|
|
100
91
|
if (!this.supabaseInfo) {
|
|
101
92
|
throw new Error("Supabase info not found");
|
|
102
93
|
}
|
|
103
94
|
|
|
104
|
-
this.supabaseInfo.token =
|
|
105
|
-
this.supabaseInfo.expiration =
|
|
95
|
+
this.supabaseInfo.token = data.token;
|
|
96
|
+
this.supabaseInfo.expiration = data.expiration;
|
|
106
97
|
|
|
107
98
|
return this.supabaseInfo.token;
|
|
108
99
|
}
|
|
@@ -115,44 +106,23 @@ export class PluginController {
|
|
|
115
106
|
return this.supabaseInfo.url;
|
|
116
107
|
}
|
|
117
108
|
|
|
118
|
-
public
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
// the communication needs to have an id to be able to distinguish between different responses
|
|
123
|
-
private internalEmit(eventName: string, id: number, data?: any) {
|
|
124
|
-
this.init().then(() => this.plugin.emitToParent(eventName, { data, _id: id, secret: this.getSecret() }));
|
|
125
|
-
}
|
|
126
|
-
|
|
127
|
-
public subscribe(eventName: string, callback: (_id: number, data: any) => void) {
|
|
128
|
-
if (!this.listeners.has(eventName)) {
|
|
129
|
-
this.listeners.set(eventName, []);
|
|
109
|
+
public getGlobalEventTopic(preliminaryTopic: string) {
|
|
110
|
+
if (preliminaryTopic.startsWith("global.")) {
|
|
111
|
+
return preliminaryTopic;
|
|
130
112
|
}
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
113
|
+
if (preliminaryTopic.startsWith("self.")) {
|
|
114
|
+
return preliminaryTopic;
|
|
115
|
+
}
|
|
116
|
+
const topicParts = preliminaryTopic.split(".");
|
|
117
|
+
if (topicParts.length === 3) {
|
|
118
|
+
if (![this.supabaseInfo?.pluginId, "global"].includes(topicParts[0])) {
|
|
119
|
+
throw new Error("The event topic must start with the plugin id or 'global'.");
|
|
120
|
+
}
|
|
121
|
+
return preliminaryTopic;
|
|
138
122
|
}
|
|
139
123
|
|
|
140
|
-
this.
|
|
124
|
+
const topicRoot = this.supabaseInfo?.pluginId ?? "global";
|
|
125
|
+
return `${topicRoot}.${preliminaryTopic}`;
|
|
141
126
|
}
|
|
142
127
|
|
|
143
|
-
async request<T>(topic: string, data: any = {}): Promise<T> {
|
|
144
|
-
return await new Promise((resolve) => {
|
|
145
|
-
let triggered = false;
|
|
146
|
-
const id = Math.random();
|
|
147
|
-
|
|
148
|
-
this.internalEmit(topic, id, data);
|
|
149
|
-
|
|
150
|
-
this.subscribe(topic, (_id: number, data: any) => {
|
|
151
|
-
if (triggered || (_id !== id && _id !== 0)) return;
|
|
152
|
-
triggered = true;
|
|
153
|
-
|
|
154
|
-
resolve(data)
|
|
155
|
-
})
|
|
156
|
-
});
|
|
157
|
-
}
|
|
158
128
|
}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { PluginController } from "./PluginController";
|
|
2
2
|
import { SupabaseClient } from "@supabase/supabase-js";
|
|
3
|
+
import { EventBusMessage, EventPayload } from "./fromRimori/EventBus";
|
|
3
4
|
import { SettingsController } from "../controller/SettingsController";
|
|
4
5
|
import { GenericSchema } from "@supabase/supabase-js/dist/module/lib/types";
|
|
5
6
|
import { getSTTResponse, getTTSResponse } from "../controller/VoiceController";
|
|
@@ -8,6 +9,8 @@ import { SharedContentController, BasicAssignment } from "../controller/SharedCo
|
|
|
8
9
|
import { streamChatGPT, Message, Tool, OnLLMResponse, generateText } from "../controller/AIController";
|
|
9
10
|
import { generateObject as generateObjectFunction, ObjectRequest } from "../controller/ObjectController";
|
|
10
11
|
import { getPlugins, Plugin } from "../controller/SidePluginController";
|
|
12
|
+
import { UserInfo } from "../controller/SettingsController";
|
|
13
|
+
import { EventBus, EventHandler } from "./fromRimori/EventBus";
|
|
11
14
|
|
|
12
15
|
interface RimoriClientOptions {
|
|
13
16
|
pluginController: PluginController;
|
|
@@ -16,38 +19,132 @@ interface RimoriClientOptions {
|
|
|
16
19
|
pluginId: string;
|
|
17
20
|
}
|
|
18
21
|
|
|
22
|
+
interface Db {
|
|
23
|
+
from: {
|
|
24
|
+
<TableName extends string & keyof GenericSchema['Tables'], Table extends GenericSchema['Tables'][TableName]>(relation: TableName): PostgrestQueryBuilder<GenericSchema, Table, TableName>;
|
|
25
|
+
<ViewName extends string & keyof GenericSchema['Views'], View extends GenericSchema['Views'][ViewName]>(relation: ViewName): PostgrestQueryBuilder<GenericSchema, View, ViewName>;
|
|
26
|
+
};
|
|
27
|
+
rpc: <Fn extends GenericSchema['Functions'][string], FnName extends string & keyof GenericSchema['Functions']>(functionName: FnName, args?: Fn["Args"], options?: {
|
|
28
|
+
head?: boolean;
|
|
29
|
+
get?: boolean;
|
|
30
|
+
count?: "exact" | "planned" | "estimated";
|
|
31
|
+
}) => PostgrestFilterBuilder<GenericSchema, Fn["Returns"] extends any[] ? Fn["Returns"][number] extends Record<string, unknown> ? Fn["Returns"][number] : never : never, Fn["Returns"], string, null>;
|
|
32
|
+
functions: SupabaseClient["functions"];
|
|
33
|
+
storage: SupabaseClient["storage"];
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
interface PluginInterface {
|
|
37
|
+
pluginId: string;
|
|
38
|
+
tablePrefix: string;
|
|
39
|
+
setSettings: (settings: any) => Promise<void>;
|
|
40
|
+
/**
|
|
41
|
+
* Get the settings for the plugin. T can be any type of settings, UserSettings or SystemSettings.
|
|
42
|
+
* @param defaultSettings The default settings to use if no settings are found.
|
|
43
|
+
* @param genericSettings The type of settings to get.
|
|
44
|
+
* @returns The settings for the plugin.
|
|
45
|
+
*/
|
|
46
|
+
getSettings: <T extends object>(defaultSettings: T) => Promise<T>;
|
|
47
|
+
/**
|
|
48
|
+
* Fetches all installed plugins.
|
|
49
|
+
* @returns A promise that resolves to an array of plugins
|
|
50
|
+
*/
|
|
51
|
+
getInstalled: () => Promise<Plugin[]>;
|
|
52
|
+
getUserInfo: () => Promise<UserInfo>;
|
|
53
|
+
}
|
|
54
|
+
|
|
19
55
|
export class RimoriClient {
|
|
20
56
|
private static instance: RimoriClient;
|
|
21
57
|
private superbase: SupabaseClient;
|
|
22
|
-
private
|
|
23
|
-
public functions: SupabaseClient["functions"];
|
|
24
|
-
public storage: SupabaseClient["storage"];
|
|
25
|
-
public pluginId: string;
|
|
26
|
-
public tablePrefix: string;
|
|
58
|
+
private pluginController: PluginController;
|
|
27
59
|
private settingsController: SettingsController;
|
|
28
60
|
private sharedContentController: SharedContentController;
|
|
61
|
+
private supabaseUrl: string;
|
|
62
|
+
public db: Db;
|
|
63
|
+
public plugin: PluginInterface;
|
|
29
64
|
|
|
30
65
|
private constructor(options: RimoriClientOptions) {
|
|
31
66
|
this.superbase = options.supabase;
|
|
32
|
-
this.
|
|
33
|
-
this.plugin = options.pluginController;
|
|
34
|
-
this.tablePrefix = options.tablePrefix;
|
|
35
|
-
this.storage = this.superbase.storage;
|
|
36
|
-
this.functions = this.superbase.functions;
|
|
67
|
+
this.pluginController = options.pluginController;
|
|
37
68
|
this.settingsController = new SettingsController(options.supabase, options.pluginId);
|
|
38
69
|
this.sharedContentController = new SharedContentController(this);
|
|
70
|
+
this.supabaseUrl = this.pluginController.getSupabaseUrl();
|
|
71
|
+
|
|
39
72
|
this.rpc = this.rpc.bind(this);
|
|
40
73
|
this.from = this.from.bind(this);
|
|
41
|
-
|
|
42
|
-
this.
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
this.
|
|
49
|
-
|
|
50
|
-
|
|
74
|
+
|
|
75
|
+
this.db = {
|
|
76
|
+
rpc: this.rpc,
|
|
77
|
+
from: this.from,
|
|
78
|
+
storage: this.superbase.storage,
|
|
79
|
+
functions: this.superbase.functions,
|
|
80
|
+
}
|
|
81
|
+
this.plugin = {
|
|
82
|
+
pluginId: options.pluginId,
|
|
83
|
+
tablePrefix: options.tablePrefix,
|
|
84
|
+
setSettings: async (settings: any) => {
|
|
85
|
+
await this.settingsController.setSettings(settings);
|
|
86
|
+
},
|
|
87
|
+
getSettings: async <T extends object>(defaultSettings: T): Promise<T> => {
|
|
88
|
+
return await this.settingsController.getSettings<T>(defaultSettings);
|
|
89
|
+
},
|
|
90
|
+
getInstalled: async (): Promise<Plugin[]> => {
|
|
91
|
+
return getPlugins(this.superbase);
|
|
92
|
+
},
|
|
93
|
+
getUserInfo: async (): Promise<UserInfo> => {
|
|
94
|
+
return this.settingsController.getUserInfo();
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
public event = {
|
|
100
|
+
/**
|
|
101
|
+
* Emit an event to Rimori or a plugin.
|
|
102
|
+
* The topic schema is:
|
|
103
|
+
* {pluginId}.{eventId}
|
|
104
|
+
* Check out the event bus documentation for more information.
|
|
105
|
+
* For triggering events from Rimori like context menu actions use the "global" keyword.
|
|
106
|
+
* @param topic The topic to emit the event on.
|
|
107
|
+
* @param data The data to emit.
|
|
108
|
+
* @param eventId The event id.
|
|
109
|
+
*/
|
|
110
|
+
emit: (topic: string, data: any, eventId?: number) => {
|
|
111
|
+
const globalTopic = this.pluginController.getGlobalEventTopic(topic);
|
|
112
|
+
EventBus.emit(this.plugin.pluginId, globalTopic, data, eventId);
|
|
113
|
+
},
|
|
114
|
+
/**
|
|
115
|
+
* Request an event.
|
|
116
|
+
* @param topic The topic to request the event on.
|
|
117
|
+
* @param data The data to request.
|
|
118
|
+
* @returns The response from the event.
|
|
119
|
+
*/
|
|
120
|
+
request: <T>(topic: string, data?: any): Promise<EventBusMessage<T>> => {
|
|
121
|
+
const globalTopic = this.pluginController.getGlobalEventTopic(topic);
|
|
122
|
+
return EventBus.request<T>(this.plugin.pluginId, globalTopic, data);
|
|
123
|
+
},
|
|
124
|
+
/**
|
|
125
|
+
* Subscribe to an event.
|
|
126
|
+
* @param topic The topic to subscribe to.
|
|
127
|
+
* @param callback The callback to call when the event is emitted.
|
|
128
|
+
*/
|
|
129
|
+
on: <T = EventPayload>(topic: string, callback: EventHandler<T>) => {
|
|
130
|
+
EventBus.on<T>(this.pluginController.getGlobalEventTopic(topic), callback);
|
|
131
|
+
},
|
|
132
|
+
/**
|
|
133
|
+
* Subscribe to an event once.
|
|
134
|
+
* @param topic The topic to subscribe to.
|
|
135
|
+
* @param callback The callback to call when the event is emitted.
|
|
136
|
+
*/
|
|
137
|
+
once: <T = EventPayload>(topic: string, callback: EventHandler<T>) => {
|
|
138
|
+
EventBus.once<T>(this.pluginController.getGlobalEventTopic(topic), callback);
|
|
139
|
+
},
|
|
140
|
+
/**
|
|
141
|
+
* Respond to an event.
|
|
142
|
+
* @param topic The topic to respond to.
|
|
143
|
+
* @param data The data to respond with.
|
|
144
|
+
*/
|
|
145
|
+
respond: <T = EventPayload>(topic: string, data: EventPayload | ((data: EventBusMessage<T>) => EventPayload | Promise<EventPayload>)) => {
|
|
146
|
+
EventBus.respond(this.plugin.pluginId, this.pluginController.getGlobalEventTopic(topic), data);
|
|
147
|
+
}
|
|
51
148
|
}
|
|
52
149
|
|
|
53
150
|
public static async getInstance(pluginController: PluginController): Promise<RimoriClient> {
|
|
@@ -58,15 +155,15 @@ export class RimoriClient {
|
|
|
58
155
|
return RimoriClient.instance;
|
|
59
156
|
}
|
|
60
157
|
|
|
61
|
-
|
|
158
|
+
private from<
|
|
62
159
|
TableName extends string & keyof GenericSchema['Tables'],
|
|
63
160
|
Table extends GenericSchema['Tables'][TableName]
|
|
64
161
|
>(relation: TableName): PostgrestQueryBuilder<GenericSchema, Table, TableName>
|
|
65
|
-
|
|
162
|
+
private from<
|
|
66
163
|
ViewName extends string & keyof GenericSchema['Views'],
|
|
67
164
|
View extends GenericSchema['Views'][ViewName]
|
|
68
165
|
>(relation: ViewName): PostgrestQueryBuilder<GenericSchema, View, ViewName>
|
|
69
|
-
|
|
166
|
+
private from(relation: string): PostgrestQueryBuilder<GenericSchema, any, any> {
|
|
70
167
|
return this.superbase.from(this.getTableName(relation));
|
|
71
168
|
}
|
|
72
169
|
|
|
@@ -93,7 +190,7 @@ export class RimoriClient {
|
|
|
93
190
|
* `"estimated"`: Uses exact count for low numbers and planned count for high
|
|
94
191
|
* numbers.
|
|
95
192
|
*/
|
|
96
|
-
rpc<Fn extends GenericSchema['Functions'][string], FnName extends string & keyof GenericSchema['Functions']>(
|
|
193
|
+
private rpc<Fn extends GenericSchema['Functions'][string], FnName extends string & keyof GenericSchema['Functions']>(
|
|
97
194
|
functionName: FnName,
|
|
98
195
|
args: Fn['Args'] = {},
|
|
99
196
|
options: {
|
|
@@ -116,68 +213,33 @@ export class RimoriClient {
|
|
|
116
213
|
}
|
|
117
214
|
|
|
118
215
|
private getTableName(type: string) {
|
|
119
|
-
return this.tablePrefix + "_" + type;
|
|
120
|
-
}
|
|
121
|
-
|
|
122
|
-
public subscribe(eventName: string, callback: (_id: number, data: any) => void) {
|
|
123
|
-
this.plugin.subscribe(eventName, callback);
|
|
124
|
-
}
|
|
125
|
-
|
|
126
|
-
public request<T>(eventName: string, data?: any): Promise<T> {
|
|
127
|
-
return this.plugin.request(eventName, data);
|
|
128
|
-
}
|
|
129
|
-
|
|
130
|
-
public emit(eventName: string, data: any) {
|
|
131
|
-
this.plugin.emit(eventName, data);
|
|
132
|
-
}
|
|
133
|
-
|
|
134
|
-
/**
|
|
135
|
-
* Get the settings for the plugin. T can be any type of settings, UserSettings or SystemSettings.
|
|
136
|
-
* @param defaultSettings The default settings to use if no settings are found.
|
|
137
|
-
* @param genericSettings The type of settings to get.
|
|
138
|
-
* @returns The settings for the plugin.
|
|
139
|
-
*/
|
|
140
|
-
public async getSettings<T extends object>(defaultSettings: T, genericSettings?: "user" | "system"): Promise<T> {
|
|
141
|
-
return this.settingsController.getSettings<T>(defaultSettings, genericSettings);
|
|
142
|
-
}
|
|
143
|
-
|
|
144
|
-
public async setSettings(settings: any, genericSettings?: "user" | "system") {
|
|
145
|
-
await this.settingsController.setSettings(settings, genericSettings);
|
|
146
|
-
}
|
|
147
|
-
|
|
148
|
-
public async getAIResponse(messages: Message[], tools?: Tool[]): Promise<string> {
|
|
149
|
-
const token = await this.plugin.getToken();
|
|
150
|
-
return generateText(messages, tools || [], token).then(response => response.messages[0].content[0].text);
|
|
151
|
-
}
|
|
152
|
-
|
|
153
|
-
public async getAIResponseStream(messages: Message[], onMessage: OnLLMResponse, tools?: Tool[]) {
|
|
154
|
-
const token = await this.plugin.getToken();
|
|
155
|
-
streamChatGPT(messages, tools || [], onMessage, token);
|
|
156
|
-
}
|
|
157
|
-
|
|
158
|
-
public async getVoiceResponse(text: string, voice = "alloy", speed = 1, language?: string): Promise<Blob> {
|
|
159
|
-
return getTTSResponse(
|
|
160
|
-
this.plugin.getSupabaseUrl(),
|
|
161
|
-
{ input: text, voice, speed, language },
|
|
162
|
-
await this.plugin.getToken()
|
|
163
|
-
);
|
|
164
|
-
}
|
|
165
|
-
|
|
166
|
-
public getVoiceToTextResponse(file: Blob): Promise<string> {
|
|
167
|
-
return getSTTResponse(this.superbase, file);
|
|
168
|
-
}
|
|
169
|
-
|
|
170
|
-
/**
|
|
171
|
-
* Fetches all installed plugins.
|
|
172
|
-
* @returns A promise that resolves to an array of plugins
|
|
173
|
-
*/
|
|
174
|
-
public async getPlugins(): Promise<Plugin[]> {
|
|
175
|
-
return getPlugins(this.superbase);
|
|
216
|
+
return this.plugin.tablePrefix + "_" + type;
|
|
176
217
|
}
|
|
177
218
|
|
|
178
|
-
public
|
|
179
|
-
|
|
180
|
-
|
|
219
|
+
public llm = {
|
|
220
|
+
getText: async (messages: Message[], tools?: Tool[]): Promise<string> => {
|
|
221
|
+
const token = await this.pluginController.getToken();
|
|
222
|
+
return generateText(this.supabaseUrl, messages, tools || [], token).then(response => response.messages[0].content[0].text);
|
|
223
|
+
},
|
|
224
|
+
getSteamedText: async (messages: Message[], onMessage: OnLLMResponse, tools?: Tool[]) => {
|
|
225
|
+
const token = await this.pluginController.getToken();
|
|
226
|
+
streamChatGPT(this.supabaseUrl, messages, tools || [], onMessage, token);
|
|
227
|
+
},
|
|
228
|
+
getVoice: async (text: string, voice = "alloy", speed = 1, language?: string): Promise<Blob> => {
|
|
229
|
+
return getTTSResponse(
|
|
230
|
+
this.pluginController.getSupabaseUrl(),
|
|
231
|
+
{ input: text, voice, speed, language },
|
|
232
|
+
await this.pluginController.getToken()
|
|
233
|
+
);
|
|
234
|
+
},
|
|
235
|
+
getTextFromVoice: (file: Blob): Promise<string> => {
|
|
236
|
+
return getSTTResponse(this.superbase, file);
|
|
237
|
+
},
|
|
238
|
+
getObject: async (request: ObjectRequest): Promise<any> => {
|
|
239
|
+
const token = await this.pluginController.getToken();
|
|
240
|
+
return generateObjectFunction(this.pluginController.getSupabaseUrl(), request, token);
|
|
241
|
+
},
|
|
242
|
+
// getSteamedObject: this.generateObjectStream,
|
|
181
243
|
}
|
|
182
244
|
|
|
183
245
|
/**
|
|
@@ -215,6 +277,6 @@ export class RimoriClient {
|
|
|
215
277
|
}
|
|
216
278
|
|
|
217
279
|
public triggerSidebarAction(pluginId: string, actionKey: string, text?: string) {
|
|
218
|
-
this.emit("
|
|
280
|
+
this.event.emit("global.sidebar.triggerAction", { pluginId, actionKey, text });
|
|
219
281
|
}
|
|
220
282
|
}
|