@rimori/client 1.0.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/dist/CRUDModal.d.ts +16 -0
- package/dist/CRUDModal.js +31 -0
- package/dist/MarkdownEditor.d.ts +8 -0
- package/dist/MarkdownEditor.js +46 -0
- package/dist/audio/Playbutton.d.ts +14 -0
- package/dist/audio/Playbutton.js +73 -0
- package/dist/components/CRUDModal.d.ts +17 -0
- package/dist/components/CRUDModal.js +25 -0
- package/dist/components/MarkdownEditor.d.ts +8 -0
- package/dist/components/MarkdownEditor.js +46 -0
- package/dist/components/Spinner.d.ts +8 -0
- package/dist/components/Spinner.js +5 -0
- package/dist/components/audio/Playbutton.d.ts +15 -0
- package/dist/components/audio/Playbutton.js +78 -0
- package/dist/components/hooks/UseChatHook.d.ts +15 -0
- package/dist/components/hooks/UseChatHook.js +21 -0
- package/dist/controller/AIController.d.ts +22 -0
- package/dist/controller/AIController.js +68 -0
- package/dist/controller/ObjectController.d.ts +34 -0
- package/dist/controller/ObjectController.js +77 -0
- package/dist/controller/SettingsController.d.ts +24 -0
- package/dist/controller/SettingsController.js +72 -0
- package/dist/controller/SharedContentController.d.ts +22 -0
- package/dist/controller/SharedContentController.js +56 -0
- package/dist/controller/VoiceController.d.ts +10 -0
- package/dist/controller/VoiceController.js +28 -0
- package/dist/hooks/UseChatHook.d.ts +9 -0
- package/dist/hooks/UseChatHook.js +21 -0
- package/dist/index.d.ts +14 -0
- package/dist/index.js +14 -0
- package/dist/plugin/AIController copy.d.ts +22 -0
- package/dist/plugin/AIController copy.js +68 -0
- package/dist/plugin/AIController.d.ts +22 -0
- package/dist/plugin/AIController.js +68 -0
- package/dist/plugin/ObjectController.d.ts +34 -0
- package/dist/plugin/ObjectController.js +77 -0
- package/dist/plugin/PluginController.d.ts +29 -0
- package/dist/plugin/PluginController.js +138 -0
- package/dist/plugin/RimoriClient.d.ts +91 -0
- package/dist/plugin/RimoriClient.js +163 -0
- package/dist/plugin/SettingController.d.ts +13 -0
- package/dist/plugin/SettingController.js +55 -0
- package/dist/plugin/ThemeSetter.d.ts +1 -0
- package/dist/plugin/ThemeSetter.js +13 -0
- package/dist/plugin/VoiceController.d.ts +2 -0
- package/dist/plugin/VoiceController.js +27 -0
- package/dist/providers/EventEmitter.d.ts +11 -0
- package/dist/providers/EventEmitter.js +41 -0
- package/dist/providers/EventEmitterContext.d.ts +6 -0
- package/dist/providers/EventEmitterContext.js +19 -0
- package/dist/providers/PluginProvider.d.ts +8 -0
- package/dist/providers/PluginProvider.js +52 -0
- package/dist/style.css +110 -0
- package/dist/style.css.map +1 -0
- package/dist/utils/DifficultyConverter.d.ts +3 -0
- package/dist/utils/DifficultyConverter.js +7 -0
- package/dist/utils/PluginUtils.d.ts +2 -0
- package/dist/utils/PluginUtils.js +23 -0
- package/dist/utils/constants.d.ts +4 -0
- package/dist/utils/constants.js +12 -0
- package/dist/utils/difficultyConverter.d.ts +3 -0
- package/dist/utils/difficultyConverter.js +7 -0
- package/dist/utils/plugin/Client.d.ts +72 -0
- package/dist/utils/plugin/Client.js +118 -0
- package/dist/utils/plugin/PluginController.d.ts +36 -0
- package/dist/utils/plugin/PluginController.js +119 -0
- package/dist/utils/plugin/PluginUtils.d.ts +2 -0
- package/dist/utils/plugin/PluginUtils.js +23 -0
- package/dist/utils/plugin/RimoriClient.d.ts +72 -0
- package/dist/utils/plugin/RimoriClient.js +118 -0
- package/dist/utils/plugin/ThemeSetter.d.ts +1 -0
- package/dist/utils/plugin/ThemeSetter.js +13 -0
- package/dist/utils/plugin/WhereClauseBuilder.d.ts +24 -0
- package/dist/utils/plugin/WhereClauseBuilder.js +79 -0
- package/dist/utils/plugin/providers/EventEmitter.d.ts +11 -0
- package/dist/utils/plugin/providers/EventEmitter.js +41 -0
- package/dist/utils/plugin/providers/EventEmitterContext.d.ts +6 -0
- package/dist/utils/plugin/providers/EventEmitterContext.js +19 -0
- package/dist/utils/plugin/providers/PluginProvider.d.ts +8 -0
- package/dist/utils/plugin/providers/PluginProvider.js +49 -0
- package/package.json +30 -0
- package/src/components/CRUDModal.tsx +61 -0
- package/src/components/MarkdownEditor.tsx +111 -0
- package/src/components/Spinner.tsx +24 -0
- package/src/components/audio/Playbutton.tsx +119 -0
- package/src/controller/AIController.ts +87 -0
- package/src/controller/ObjectController.ts +109 -0
- package/src/controller/SettingsController.ts +87 -0
- package/src/controller/SharedContentController.ts +71 -0
- package/src/controller/VoiceController.ts +26 -0
- package/src/hooks/UseChatHook.ts +25 -0
- package/src/index.ts +14 -0
- package/src/plugin/PluginController.ts +158 -0
- package/src/plugin/RimoriClient.ts +207 -0
- package/src/plugin/ThemeSetter.ts +17 -0
- package/src/providers/EventEmitter.ts +48 -0
- package/src/providers/EventEmitterContext.tsx +27 -0
- package/src/providers/PluginProvider.tsx +68 -0
- package/src/style.scss +136 -0
- package/src/utils/PluginUtils.ts +26 -0
- package/src/utils/constants.ts +18 -0
- package/src/utils/difficultyConverter.ts +11 -0
- package/tsconfig.json +16 -0
|
@@ -0,0 +1,77 @@
|
|
|
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 { env } from "../utils/constants";
|
|
11
|
+
export function generateObject(request, token) {
|
|
12
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
13
|
+
return yield fetch(`${env.SUPABASE_URL}/functions/v1/llm-object`, {
|
|
14
|
+
method: 'POST',
|
|
15
|
+
body: JSON.stringify({
|
|
16
|
+
stream: false,
|
|
17
|
+
tool: request.tool,
|
|
18
|
+
behaviour: request.behaviour,
|
|
19
|
+
instructions: request.instructions,
|
|
20
|
+
}),
|
|
21
|
+
headers: { 'Authorization': `Bearer ${token}` }
|
|
22
|
+
}).then(response => response.json());
|
|
23
|
+
});
|
|
24
|
+
}
|
|
25
|
+
export function streamObject(request, onResponse, token) {
|
|
26
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
27
|
+
const messageId = Math.random().toString(36).substring(3);
|
|
28
|
+
const response = yield fetch(`${env.SUPABASE_URL}/functions/v1/llm-object`, {
|
|
29
|
+
method: 'POST',
|
|
30
|
+
body: JSON.stringify({
|
|
31
|
+
stream: true,
|
|
32
|
+
tools: request.tool,
|
|
33
|
+
systemInstructions: request.behaviour,
|
|
34
|
+
secondaryInstructions: request.instructions,
|
|
35
|
+
}),
|
|
36
|
+
headers: { 'Authorization': `Bearer ${token}` }
|
|
37
|
+
});
|
|
38
|
+
if (!response.body) {
|
|
39
|
+
console.error('No response body.');
|
|
40
|
+
return;
|
|
41
|
+
}
|
|
42
|
+
const reader = response.body.getReader();
|
|
43
|
+
const decoder = new TextDecoder('utf-8');
|
|
44
|
+
let content = "";
|
|
45
|
+
let done = false;
|
|
46
|
+
let toolInvocations = [];
|
|
47
|
+
while (!done) {
|
|
48
|
+
const { value } = yield reader.read();
|
|
49
|
+
if (value) {
|
|
50
|
+
const chunk = decoder.decode(value, { stream: true });
|
|
51
|
+
const lines = chunk.split('\n').filter(line => line.trim() !== '');
|
|
52
|
+
for (const line of lines) {
|
|
53
|
+
const data = line.substring(3, line.length - 1);
|
|
54
|
+
const command = line.substring(0, 1);
|
|
55
|
+
// console.log("data: ", { line, data, command });
|
|
56
|
+
if (command === '0') {
|
|
57
|
+
content += data;
|
|
58
|
+
// console.log("AI response:", content);
|
|
59
|
+
//content \n\n should be real line break when message is displayed
|
|
60
|
+
onResponse(messageId, content.replace(/\\n/g, '\n'), false);
|
|
61
|
+
}
|
|
62
|
+
else if (command === 'd') {
|
|
63
|
+
// console.log("AI usage:", JSON.parse(line.substring(2)));
|
|
64
|
+
done = true;
|
|
65
|
+
break;
|
|
66
|
+
}
|
|
67
|
+
else if (command === '9') {
|
|
68
|
+
// console.log("tool call:", JSON.parse(line.substring(2)));
|
|
69
|
+
// console.log("tools", tools);
|
|
70
|
+
toolInvocations.push(JSON.parse(line.substring(2)));
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
onResponse(messageId, content.replace(/\\n/g, '\n'), true, toolInvocations);
|
|
76
|
+
});
|
|
77
|
+
}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { SupabaseClient } from "@supabase/supabase-js";
|
|
2
|
+
import { LanguageLevel } from "../utils/difficultyConverter";
|
|
3
|
+
export interface UserSettings {
|
|
4
|
+
motherTongue: string;
|
|
5
|
+
languageLevel: LanguageLevel;
|
|
6
|
+
}
|
|
7
|
+
export interface SystemSettings {
|
|
8
|
+
}
|
|
9
|
+
export declare class SettingsController {
|
|
10
|
+
private pluginId;
|
|
11
|
+
private supabase;
|
|
12
|
+
constructor(supabase: SupabaseClient, pluginId: string);
|
|
13
|
+
private getSettingsType;
|
|
14
|
+
private fetchSettings;
|
|
15
|
+
private saveSettings;
|
|
16
|
+
/**
|
|
17
|
+
* Get the settings for the plugin. T can be any type of settings, UserSettings or SystemSettings.
|
|
18
|
+
* @param defaultSettings The default settings to use if no settings are found.
|
|
19
|
+
* @param genericSettings The type of settings to get.
|
|
20
|
+
* @returns The settings for the plugin.
|
|
21
|
+
*/
|
|
22
|
+
getSettings<T extends object>(defaultSettings: T, genericSettings?: "user" | "system"): Promise<T>;
|
|
23
|
+
setSettings(settings: any, genericSettings?: "user" | "system"): Promise<void>;
|
|
24
|
+
}
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
2
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
3
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
4
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
5
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
6
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
7
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
8
|
+
});
|
|
9
|
+
};
|
|
10
|
+
export class SettingsController {
|
|
11
|
+
constructor(supabase, pluginId) {
|
|
12
|
+
this.supabase = supabase;
|
|
13
|
+
this.pluginId = pluginId;
|
|
14
|
+
}
|
|
15
|
+
getSettingsType(genericSettings) {
|
|
16
|
+
return genericSettings || "plugin";
|
|
17
|
+
}
|
|
18
|
+
fetchSettings(type) {
|
|
19
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
20
|
+
const pluginId = type === "plugin" ? this.pluginId : type;
|
|
21
|
+
const { data } = yield this.supabase.from("plugin_settings").select("*").eq("plugin_id", pluginId);
|
|
22
|
+
if (!data || data.length === 0) {
|
|
23
|
+
return null;
|
|
24
|
+
}
|
|
25
|
+
return data[0].settings;
|
|
26
|
+
});
|
|
27
|
+
}
|
|
28
|
+
saveSettings(settings, type) {
|
|
29
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
30
|
+
if (type !== "plugin") {
|
|
31
|
+
throw new Error(`Cannot modify ${type} settings`);
|
|
32
|
+
}
|
|
33
|
+
yield this.supabase.from("plugin_settings").upsert({ plugin_id: this.pluginId, settings });
|
|
34
|
+
});
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* Get the settings for the plugin. T can be any type of settings, UserSettings or SystemSettings.
|
|
38
|
+
* @param defaultSettings The default settings to use if no settings are found.
|
|
39
|
+
* @param genericSettings The type of settings to get.
|
|
40
|
+
* @returns The settings for the plugin.
|
|
41
|
+
*/
|
|
42
|
+
getSettings(defaultSettings, genericSettings) {
|
|
43
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
44
|
+
const type = this.getSettingsType(genericSettings);
|
|
45
|
+
const storedSettings = yield this.fetchSettings(type);
|
|
46
|
+
if (!storedSettings) {
|
|
47
|
+
if (type === "plugin") {
|
|
48
|
+
yield this.saveSettings(defaultSettings, type);
|
|
49
|
+
}
|
|
50
|
+
return defaultSettings;
|
|
51
|
+
}
|
|
52
|
+
// Handle settings migration
|
|
53
|
+
const storedKeys = Object.keys(storedSettings);
|
|
54
|
+
const defaultKeys = Object.keys(defaultSettings);
|
|
55
|
+
if (storedKeys.length !== defaultKeys.length) {
|
|
56
|
+
const validStoredSettings = Object.fromEntries(Object.entries(storedSettings).filter(([key]) => defaultKeys.includes(key)));
|
|
57
|
+
const mergedSettings = Object.assign(Object.assign({}, defaultSettings), validStoredSettings);
|
|
58
|
+
if (type === "plugin") {
|
|
59
|
+
yield this.saveSettings(mergedSettings, type);
|
|
60
|
+
}
|
|
61
|
+
return mergedSettings;
|
|
62
|
+
}
|
|
63
|
+
return storedSettings;
|
|
64
|
+
});
|
|
65
|
+
}
|
|
66
|
+
setSettings(settings, genericSettings) {
|
|
67
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
68
|
+
const type = this.getSettingsType(genericSettings);
|
|
69
|
+
yield this.saveSettings(settings, type);
|
|
70
|
+
});
|
|
71
|
+
}
|
|
72
|
+
}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { ObjectRequest } from "./ObjectController";
|
|
2
|
+
import { RimoriClient } from "../plugin/RimoriClient";
|
|
3
|
+
export interface BasicAssignment {
|
|
4
|
+
id: string;
|
|
5
|
+
createdAt: Date;
|
|
6
|
+
topic: string;
|
|
7
|
+
createdBy: string;
|
|
8
|
+
verified: boolean;
|
|
9
|
+
keywords: any;
|
|
10
|
+
}
|
|
11
|
+
export declare class SharedContentController {
|
|
12
|
+
private rimoriClient;
|
|
13
|
+
constructor(rimoriClient: RimoriClient);
|
|
14
|
+
fetchNewSharedContent<T, R = T & BasicAssignment>(type: string, generatorInstructions: (reservedTopics: string[]) => Promise<ObjectRequest> | ObjectRequest, filter?: {
|
|
15
|
+
column: string;
|
|
16
|
+
value: string | number | boolean;
|
|
17
|
+
}): Promise<R[]>;
|
|
18
|
+
private getReservedTopics;
|
|
19
|
+
private purifyStringArray;
|
|
20
|
+
getSharedContent<T extends BasicAssignment>(type: string, id: string): Promise<T>;
|
|
21
|
+
completeSharedContent(type: string, assignmentId: string): Promise<void>;
|
|
22
|
+
}
|
|
@@ -0,0 +1,56 @@
|
|
|
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 { v4 as uuidv4 } from 'uuid';
|
|
11
|
+
export class SharedContentController {
|
|
12
|
+
constructor(rimoriClient) {
|
|
13
|
+
this.rimoriClient = rimoriClient;
|
|
14
|
+
}
|
|
15
|
+
fetchNewSharedContent(type, generatorInstructions, filter) {
|
|
16
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
17
|
+
const queryParameter = { filter_column: (filter === null || filter === void 0 ? void 0 : filter.column) || null, filter_value: (filter === null || filter === void 0 ? void 0 : filter.value) || null, unread: true };
|
|
18
|
+
const { data: newAssignments } = yield this.rimoriClient.rpc(type + "_entries", queryParameter);
|
|
19
|
+
console.log('newAssignments:', newAssignments);
|
|
20
|
+
if (newAssignments.length > 0) {
|
|
21
|
+
return newAssignments;
|
|
22
|
+
}
|
|
23
|
+
// generate new assignments
|
|
24
|
+
const { data: oldAssignments } = yield this.rimoriClient.rpc(type + "_entries", Object.assign(Object.assign({}, queryParameter), { unread: false }));
|
|
25
|
+
console.log('oldAssignments:', oldAssignments);
|
|
26
|
+
const reservedTopics = this.getReservedTopics(oldAssignments);
|
|
27
|
+
const request = yield generatorInstructions(reservedTopics);
|
|
28
|
+
if (!request.tool.keywords || !request.tool.topic) {
|
|
29
|
+
throw new Error("topic or keywords not found in the request schema");
|
|
30
|
+
}
|
|
31
|
+
const instructions = yield this.rimoriClient.generateObject(request);
|
|
32
|
+
console.log('instructions:', instructions);
|
|
33
|
+
const preparedData = Object.assign(Object.assign({ id: uuidv4() }, instructions), { keywords: this.purifyStringArray(instructions.keywords) });
|
|
34
|
+
return yield this.rimoriClient.from(type).insert(preparedData).then(() => [preparedData]);
|
|
35
|
+
});
|
|
36
|
+
}
|
|
37
|
+
getReservedTopics(oldAssignments) {
|
|
38
|
+
return oldAssignments.map(({ topic, keywords }) => {
|
|
39
|
+
const keywordTexts = this.purifyStringArray(keywords).join(',');
|
|
40
|
+
return `${topic}(${keywordTexts})`;
|
|
41
|
+
});
|
|
42
|
+
}
|
|
43
|
+
purifyStringArray(array) {
|
|
44
|
+
return array.map(({ text }) => text);
|
|
45
|
+
}
|
|
46
|
+
getSharedContent(type, id) {
|
|
47
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
48
|
+
return yield this.rimoriClient.from(type).select().eq('id', id).single();
|
|
49
|
+
});
|
|
50
|
+
}
|
|
51
|
+
completeSharedContent(type, assignmentId) {
|
|
52
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
53
|
+
yield this.rimoriClient.from(type + "_result").insert({ assignment_id: assignmentId });
|
|
54
|
+
});
|
|
55
|
+
}
|
|
56
|
+
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { SupabaseClient } from "@supabase/supabase-js";
|
|
2
|
+
export declare function getSTTResponse(supabase: SupabaseClient, audio: Blob): Promise<any>;
|
|
3
|
+
export declare function getTTSResponse(supabaseUrl: string, request: TTSRequest, token: string): Promise<Blob>;
|
|
4
|
+
interface TTSRequest {
|
|
5
|
+
input: string;
|
|
6
|
+
voice: string;
|
|
7
|
+
speed: number;
|
|
8
|
+
language?: string;
|
|
9
|
+
}
|
|
10
|
+
export {};
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
2
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
3
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
4
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
5
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
6
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
7
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
8
|
+
});
|
|
9
|
+
};
|
|
10
|
+
export function getSTTResponse(supabase, audio) {
|
|
11
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
12
|
+
const formData = new FormData();
|
|
13
|
+
formData.append('file', audio);
|
|
14
|
+
return yield supabase.functions.invoke('speech', { method: 'POST', body: formData }).then((r) => r.text);
|
|
15
|
+
});
|
|
16
|
+
}
|
|
17
|
+
export function getTTSResponse(supabaseUrl, request, token) {
|
|
18
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
19
|
+
return yield fetch(`${supabaseUrl}/functions/v1/speech`, {
|
|
20
|
+
method: 'POST',
|
|
21
|
+
headers: {
|
|
22
|
+
'Content-Type': 'application/json',
|
|
23
|
+
'Authorization': `Bearer ${token}`
|
|
24
|
+
},
|
|
25
|
+
body: JSON.stringify(request),
|
|
26
|
+
}).then(r => r.blob());
|
|
27
|
+
});
|
|
28
|
+
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
import { Tool, Message } from "../controller/AIController";
|
|
3
|
+
export declare function useChat(tools?: Tool[]): {
|
|
4
|
+
messages: Message[];
|
|
5
|
+
append: (appendMessages: Message[]) => void;
|
|
6
|
+
isLoading: boolean;
|
|
7
|
+
setMessages: React.Dispatch<React.SetStateAction<Message[]>>;
|
|
8
|
+
lastMessage: Message | undefined;
|
|
9
|
+
};
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
import { usePlugin } from "../providers/PluginProvider";
|
|
3
|
+
export function useChat(tools) {
|
|
4
|
+
const [messages, setMessages] = React.useState([]);
|
|
5
|
+
const [isLoading, setIsLoading] = React.useState(false);
|
|
6
|
+
const { getAIResponseStream } = usePlugin();
|
|
7
|
+
const append = (appendMessages) => {
|
|
8
|
+
getAIResponseStream([...messages, ...appendMessages], (id, message, finished, toolInvocations) => {
|
|
9
|
+
const lastMessage = messages[messages.length - 1];
|
|
10
|
+
setIsLoading(!finished);
|
|
11
|
+
if ((lastMessage === null || lastMessage === void 0 ? void 0 : lastMessage.id) === id) {
|
|
12
|
+
lastMessage.content = message;
|
|
13
|
+
setMessages([...messages, lastMessage]);
|
|
14
|
+
}
|
|
15
|
+
else {
|
|
16
|
+
setMessages([...messages, ...appendMessages, { id, role: 'assistant', content: message, toolInvocations }]);
|
|
17
|
+
}
|
|
18
|
+
}, tools);
|
|
19
|
+
};
|
|
20
|
+
return { messages, append, isLoading, setMessages, lastMessage: messages[messages.length - 1] };
|
|
21
|
+
}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
export * from "./components/MarkdownEditor";
|
|
2
|
+
export * from "./components/CRUDModal";
|
|
3
|
+
export * from "./plugin/ThemeSetter";
|
|
4
|
+
export * from "./components/audio/Playbutton";
|
|
5
|
+
export * from "./providers/EventEmitterContext";
|
|
6
|
+
export * from "./providers/PluginProvider";
|
|
7
|
+
export * from "./providers/EventEmitter";
|
|
8
|
+
export * from "./components/Spinner";
|
|
9
|
+
export * from "./hooks/UseChatHook";
|
|
10
|
+
export * from "./utils/PluginUtils";
|
|
11
|
+
export * from "./plugin/RimoriClient";
|
|
12
|
+
export * from "./controller/AIController";
|
|
13
|
+
export * from "./controller/SharedContentController";
|
|
14
|
+
export * from "./controller/SettingsController";
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
export * from "./components/MarkdownEditor";
|
|
2
|
+
export * from "./components/CRUDModal";
|
|
3
|
+
export * from "./plugin/ThemeSetter";
|
|
4
|
+
export * from "./components/audio/Playbutton";
|
|
5
|
+
export * from "./providers/EventEmitterContext";
|
|
6
|
+
export * from "./providers/PluginProvider";
|
|
7
|
+
export * from "./providers/EventEmitter";
|
|
8
|
+
export * from "./components/Spinner";
|
|
9
|
+
export * from "./hooks/UseChatHook";
|
|
10
|
+
export * from "./utils/PluginUtils";
|
|
11
|
+
export * from "./plugin/RimoriClient";
|
|
12
|
+
export * from "./controller/AIController";
|
|
13
|
+
export * from "./controller/SharedContentController";
|
|
14
|
+
export * from "./controller/SettingsController";
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
export interface ToolInvocation {
|
|
2
|
+
toolName: string;
|
|
3
|
+
args: Record<string, string>;
|
|
4
|
+
}
|
|
5
|
+
export interface Tool {
|
|
6
|
+
name: string;
|
|
7
|
+
description: string;
|
|
8
|
+
parameters: {
|
|
9
|
+
name: string;
|
|
10
|
+
type: "string" | "number" | "boolean";
|
|
11
|
+
description: string;
|
|
12
|
+
}[];
|
|
13
|
+
}
|
|
14
|
+
export interface Message {
|
|
15
|
+
id: string;
|
|
16
|
+
role: string;
|
|
17
|
+
content: string;
|
|
18
|
+
toolInvocations?: ToolInvocation[];
|
|
19
|
+
}
|
|
20
|
+
export declare function generateText(messages: Message[], tools: Tool[], token: string): Promise<any>;
|
|
21
|
+
export type OnLLMResponse = (id: string, response: string, finished: boolean, toolInvocations?: ToolInvocation[]) => void;
|
|
22
|
+
export declare function streamChatGPT(messages: Message[], tools: Tool[], onResponse: OnLLMResponse, token: string): Promise<void>;
|
|
@@ -0,0 +1,68 @@
|
|
|
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 { env } from "../utils/constants";
|
|
11
|
+
export function generateText(messages, tools, token) {
|
|
12
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
13
|
+
const response = yield fetch(`${env.SUPABASE_URL}/functions/v1/llm`, {
|
|
14
|
+
method: 'POST',
|
|
15
|
+
body: JSON.stringify({ messages, tools }),
|
|
16
|
+
headers: { 'Authorization': `Bearer ${token}` }
|
|
17
|
+
});
|
|
18
|
+
return yield response.json();
|
|
19
|
+
});
|
|
20
|
+
}
|
|
21
|
+
export function streamChatGPT(messages, tools, onResponse, token) {
|
|
22
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
23
|
+
const messageId = Math.random().toString(36).substring(3);
|
|
24
|
+
const response = yield fetch(`${env.SUPABASE_URL}/functions/v1/llm`, {
|
|
25
|
+
method: 'POST',
|
|
26
|
+
body: JSON.stringify({ messages, tools, stream: true }),
|
|
27
|
+
headers: { 'Authorization': `Bearer ${token}` }
|
|
28
|
+
});
|
|
29
|
+
if (!response.body) {
|
|
30
|
+
console.error('No response body.');
|
|
31
|
+
return;
|
|
32
|
+
}
|
|
33
|
+
const reader = response.body.getReader();
|
|
34
|
+
const decoder = new TextDecoder('utf-8');
|
|
35
|
+
let content = "";
|
|
36
|
+
let done = false;
|
|
37
|
+
let toolInvocations = [];
|
|
38
|
+
while (!done) {
|
|
39
|
+
const { value } = yield reader.read();
|
|
40
|
+
if (value) {
|
|
41
|
+
const chunk = decoder.decode(value, { stream: true });
|
|
42
|
+
const lines = chunk.split('\n').filter(line => line.trim() !== '');
|
|
43
|
+
for (const line of lines) {
|
|
44
|
+
const data = line.substring(3, line.length - 1);
|
|
45
|
+
const command = line.substring(0, 1);
|
|
46
|
+
// console.log("data: ", { line, data, command });
|
|
47
|
+
if (command === '0') {
|
|
48
|
+
content += data;
|
|
49
|
+
// console.log("AI response:", content);
|
|
50
|
+
//content \n\n should be real line break when message is displayed
|
|
51
|
+
onResponse(messageId, content.replace(/\\n/g, '\n'), false);
|
|
52
|
+
}
|
|
53
|
+
else if (command === 'd') {
|
|
54
|
+
// console.log("AI usage:", JSON.parse(line.substring(2)));
|
|
55
|
+
done = true;
|
|
56
|
+
break;
|
|
57
|
+
}
|
|
58
|
+
else if (command === '9') {
|
|
59
|
+
// console.log("tool call:", JSON.parse(line.substring(2)));
|
|
60
|
+
// console.log("tools", tools);
|
|
61
|
+
toolInvocations.push(JSON.parse(line.substring(2)));
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
onResponse(messageId, content.replace(/\\n/g, '\n'), true, toolInvocations);
|
|
67
|
+
});
|
|
68
|
+
}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
export interface ToolInvocation {
|
|
2
|
+
toolName: string;
|
|
3
|
+
args: Record<string, string>;
|
|
4
|
+
}
|
|
5
|
+
export interface Tool {
|
|
6
|
+
name: string;
|
|
7
|
+
description: string;
|
|
8
|
+
parameters: {
|
|
9
|
+
name: string;
|
|
10
|
+
type: "string" | "number" | "boolean";
|
|
11
|
+
description: string;
|
|
12
|
+
}[];
|
|
13
|
+
}
|
|
14
|
+
export interface Message {
|
|
15
|
+
id: string;
|
|
16
|
+
role: string;
|
|
17
|
+
content: string;
|
|
18
|
+
toolInvocations?: ToolInvocation[];
|
|
19
|
+
}
|
|
20
|
+
export declare function generateText(messages: Message[], tools: Tool[], token: string): Promise<any>;
|
|
21
|
+
export type OnLLMResponse = (id: string, response: string, finished: boolean, toolInvocations?: ToolInvocation[]) => void;
|
|
22
|
+
export declare function streamChatGPT(messages: Message[], tools: Tool[], onResponse: OnLLMResponse, token: string): Promise<void>;
|
|
@@ -0,0 +1,68 @@
|
|
|
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 { env } from "../utils/constants";
|
|
11
|
+
export function generateText(messages, tools, token) {
|
|
12
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
13
|
+
const response = yield fetch(`${env.SUPABASE_URL}/functions/v1/llm`, {
|
|
14
|
+
method: 'POST',
|
|
15
|
+
body: JSON.stringify({ messages, tools }),
|
|
16
|
+
headers: { 'Authorization': `Bearer ${token}` }
|
|
17
|
+
});
|
|
18
|
+
return yield response.json();
|
|
19
|
+
});
|
|
20
|
+
}
|
|
21
|
+
export function streamChatGPT(messages, tools, onResponse, token) {
|
|
22
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
23
|
+
const messageId = Math.random().toString(36).substring(3);
|
|
24
|
+
const response = yield fetch(`${env.SUPABASE_URL}/functions/v1/llm`, {
|
|
25
|
+
method: 'POST',
|
|
26
|
+
body: JSON.stringify({ messages, tools, stream: true }),
|
|
27
|
+
headers: { 'Authorization': `Bearer ${token}` }
|
|
28
|
+
});
|
|
29
|
+
if (!response.body) {
|
|
30
|
+
console.error('No response body.');
|
|
31
|
+
return;
|
|
32
|
+
}
|
|
33
|
+
const reader = response.body.getReader();
|
|
34
|
+
const decoder = new TextDecoder('utf-8');
|
|
35
|
+
let content = "";
|
|
36
|
+
let done = false;
|
|
37
|
+
let toolInvocations = [];
|
|
38
|
+
while (!done) {
|
|
39
|
+
const { value } = yield reader.read();
|
|
40
|
+
if (value) {
|
|
41
|
+
const chunk = decoder.decode(value, { stream: true });
|
|
42
|
+
const lines = chunk.split('\n').filter(line => line.trim() !== '');
|
|
43
|
+
for (const line of lines) {
|
|
44
|
+
const data = line.substring(3, line.length - 1);
|
|
45
|
+
const command = line.substring(0, 1);
|
|
46
|
+
// console.log("data: ", { line, data, command });
|
|
47
|
+
if (command === '0') {
|
|
48
|
+
content += data;
|
|
49
|
+
// console.log("AI response:", content);
|
|
50
|
+
//content \n\n should be real line break when message is displayed
|
|
51
|
+
onResponse(messageId, content.replace(/\\n/g, '\n'), false);
|
|
52
|
+
}
|
|
53
|
+
else if (command === 'd') {
|
|
54
|
+
// console.log("AI usage:", JSON.parse(line.substring(2)));
|
|
55
|
+
done = true;
|
|
56
|
+
break;
|
|
57
|
+
}
|
|
58
|
+
else if (command === '9') {
|
|
59
|
+
// console.log("tool call:", JSON.parse(line.substring(2)));
|
|
60
|
+
// console.log("tools", tools);
|
|
61
|
+
toolInvocations.push(JSON.parse(line.substring(2)));
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
onResponse(messageId, content.replace(/\\n/g, '\n'), true, toolInvocations);
|
|
67
|
+
});
|
|
68
|
+
}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
type PrimitiveType = 'string' | 'number' | 'boolean';
|
|
2
|
+
type ObjectToolParameterType = PrimitiveType | {
|
|
3
|
+
[key: string]: ObjectToolParameter;
|
|
4
|
+
} | [{
|
|
5
|
+
[key: string]: ObjectToolParameter;
|
|
6
|
+
}];
|
|
7
|
+
interface ObjectToolParameter {
|
|
8
|
+
type: ObjectToolParameterType;
|
|
9
|
+
description?: string;
|
|
10
|
+
enum?: string[];
|
|
11
|
+
}
|
|
12
|
+
export type ObjectTool = {
|
|
13
|
+
[key: string]: ObjectToolParameter;
|
|
14
|
+
};
|
|
15
|
+
export interface ObjectRequest {
|
|
16
|
+
/**
|
|
17
|
+
* The tools that the AI can use.
|
|
18
|
+
*/
|
|
19
|
+
tool: ObjectTool;
|
|
20
|
+
/**
|
|
21
|
+
* High level instructions for the AI to follow. Behaviour, tone, restrictions, etc.
|
|
22
|
+
* Example: "Act like a recipe writer."
|
|
23
|
+
*/
|
|
24
|
+
behaviour?: string;
|
|
25
|
+
/**
|
|
26
|
+
* The specific instruction for the AI to follow.
|
|
27
|
+
* Example: "Generate a recipe using chicken, rice and vegetables."
|
|
28
|
+
*/
|
|
29
|
+
instructions: string;
|
|
30
|
+
}
|
|
31
|
+
export declare function generateObject(request: ObjectRequest, token: string): Promise<any>;
|
|
32
|
+
export type OnLLMResponse = (id: string, response: string, finished: boolean, toolInvocations?: any[]) => void;
|
|
33
|
+
export declare function streamObject(request: ObjectRequest, onResponse: OnLLMResponse, token: string): Promise<void>;
|
|
34
|
+
export {};
|
|
@@ -0,0 +1,77 @@
|
|
|
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 { env } from "../utils/constants";
|
|
11
|
+
export function generateObject(request, token) {
|
|
12
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
13
|
+
return yield fetch(`${env.SUPABASE_URL}/functions/v1/llm-object`, {
|
|
14
|
+
method: 'POST',
|
|
15
|
+
body: JSON.stringify({
|
|
16
|
+
stream: false,
|
|
17
|
+
tool: request.tool,
|
|
18
|
+
behaviour: request.behaviour,
|
|
19
|
+
instructions: request.instructions,
|
|
20
|
+
}),
|
|
21
|
+
headers: { 'Authorization': `Bearer ${token}` }
|
|
22
|
+
}).then(response => response.json());
|
|
23
|
+
});
|
|
24
|
+
}
|
|
25
|
+
export function streamObject(request, onResponse, token) {
|
|
26
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
27
|
+
const messageId = Math.random().toString(36).substring(3);
|
|
28
|
+
const response = yield fetch(`${env.SUPABASE_URL}/functions/v1/llm-object`, {
|
|
29
|
+
method: 'POST',
|
|
30
|
+
body: JSON.stringify({
|
|
31
|
+
stream: true,
|
|
32
|
+
tools: request.tool,
|
|
33
|
+
systemInstructions: request.behaviour,
|
|
34
|
+
secondaryInstructions: request.instructions,
|
|
35
|
+
}),
|
|
36
|
+
headers: { 'Authorization': `Bearer ${token}` }
|
|
37
|
+
});
|
|
38
|
+
if (!response.body) {
|
|
39
|
+
console.error('No response body.');
|
|
40
|
+
return;
|
|
41
|
+
}
|
|
42
|
+
const reader = response.body.getReader();
|
|
43
|
+
const decoder = new TextDecoder('utf-8');
|
|
44
|
+
let content = "";
|
|
45
|
+
let done = false;
|
|
46
|
+
let toolInvocations = [];
|
|
47
|
+
while (!done) {
|
|
48
|
+
const { value } = yield reader.read();
|
|
49
|
+
if (value) {
|
|
50
|
+
const chunk = decoder.decode(value, { stream: true });
|
|
51
|
+
const lines = chunk.split('\n').filter(line => line.trim() !== '');
|
|
52
|
+
for (const line of lines) {
|
|
53
|
+
const data = line.substring(3, line.length - 1);
|
|
54
|
+
const command = line.substring(0, 1);
|
|
55
|
+
// console.log("data: ", { line, data, command });
|
|
56
|
+
if (command === '0') {
|
|
57
|
+
content += data;
|
|
58
|
+
// console.log("AI response:", content);
|
|
59
|
+
//content \n\n should be real line break when message is displayed
|
|
60
|
+
onResponse(messageId, content.replace(/\\n/g, '\n'), false);
|
|
61
|
+
}
|
|
62
|
+
else if (command === 'd') {
|
|
63
|
+
// console.log("AI usage:", JSON.parse(line.substring(2)));
|
|
64
|
+
done = true;
|
|
65
|
+
break;
|
|
66
|
+
}
|
|
67
|
+
else if (command === '9') {
|
|
68
|
+
// console.log("tool call:", JSON.parse(line.substring(2)));
|
|
69
|
+
// console.log("tools", tools);
|
|
70
|
+
toolInvocations.push(JSON.parse(line.substring(2)));
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
onResponse(messageId, content.replace(/\\n/g, '\n'), true, toolInvocations);
|
|
76
|
+
});
|
|
77
|
+
}
|