@rimori/client 1.1.10 → 1.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (151) hide show
  1. package/README.md +128 -45
  2. package/dist/cli/scripts/init/dev-registration.d.ts +35 -0
  3. package/dist/cli/scripts/init/dev-registration.js +175 -0
  4. package/dist/cli/scripts/init/env-setup.d.ts +9 -0
  5. package/dist/cli/scripts/init/env-setup.js +43 -0
  6. package/dist/cli/scripts/init/file-operations.d.ts +4 -0
  7. package/dist/cli/scripts/init/file-operations.js +51 -0
  8. package/dist/cli/scripts/init/html-cleaner.d.ts +4 -0
  9. package/dist/cli/scripts/init/html-cleaner.js +38 -0
  10. package/dist/cli/scripts/init/main.d.ts +2 -0
  11. package/dist/cli/scripts/init/main.js +159 -0
  12. package/dist/cli/scripts/init/package-setup.d.ts +32 -0
  13. package/dist/cli/scripts/init/package-setup.js +75 -0
  14. package/dist/cli/scripts/init/router-transformer.d.ts +6 -0
  15. package/dist/cli/scripts/init/router-transformer.js +254 -0
  16. package/dist/cli/scripts/init/tailwind-config.d.ts +4 -0
  17. package/dist/cli/scripts/init/tailwind-config.js +56 -0
  18. package/dist/cli/scripts/init/vite-config.d.ts +20 -0
  19. package/dist/cli/scripts/init/vite-config.js +54 -0
  20. package/dist/cli/scripts/release/release-config-upload.d.ts +7 -0
  21. package/dist/cli/scripts/release/release-config-upload.js +116 -0
  22. package/dist/cli/scripts/release/release-db-update.d.ts +6 -0
  23. package/dist/cli/scripts/release/release-db-update.js +100 -0
  24. package/dist/cli/scripts/release/release-file-upload.d.ts +6 -0
  25. package/dist/cli/scripts/release/release-file-upload.js +136 -0
  26. package/dist/cli/scripts/release/release.d.ts +23 -0
  27. package/dist/cli/scripts/release/release.js +70 -0
  28. package/dist/cli/types/DatabaseTypes.d.ts +103 -0
  29. package/dist/cli/types/DatabaseTypes.js +2 -0
  30. package/dist/components/ai/Assistant.js +4 -4
  31. package/dist/components/ai/Avatar.d.ts +3 -2
  32. package/dist/components/ai/Avatar.js +10 -5
  33. package/dist/components/ai/EmbeddedAssistent/CircleAudioAvatar.js +1 -1
  34. package/dist/components/ai/EmbeddedAssistent/VoiceRecoder.d.ts +1 -0
  35. package/dist/components/ai/EmbeddedAssistent/VoiceRecoder.js +12 -6
  36. package/dist/components/ai/utils.js +0 -1
  37. package/dist/components/audio/Playbutton.js +3 -3
  38. package/dist/{core → components}/components/ContextMenu.js +2 -2
  39. package/dist/components.d.ts +5 -5
  40. package/dist/components.js +5 -5
  41. package/dist/core/controller/AIController.d.ts +15 -0
  42. package/dist/core/controller/AIController.js +120 -0
  43. package/dist/{controller → core/controller}/ObjectController.d.ts +8 -0
  44. package/dist/{controller → core/controller}/SettingsController.d.ts +12 -4
  45. package/dist/{controller → core/controller}/SettingsController.js +0 -25
  46. package/dist/{controller → core/controller}/SharedContentController.d.ts +1 -1
  47. package/dist/{controller → core/controller}/SharedContentController.js +4 -4
  48. package/dist/core/core.d.ts +13 -0
  49. package/dist/core/core.js +8 -0
  50. package/dist/{plugin/fromRimori → fromRimori}/EventBus.d.ts +3 -3
  51. package/dist/{plugin/fromRimori → fromRimori}/EventBus.js +25 -8
  52. package/dist/fromRimori/PluginTypes.d.ts +171 -0
  53. package/dist/hooks/UseChatHook.d.ts +2 -1
  54. package/dist/hooks/UseChatHook.js +3 -3
  55. package/dist/index.d.ts +5 -3
  56. package/dist/index.js +4 -3
  57. package/dist/plugin/AccomplishmentHandler.d.ts +1 -1
  58. package/dist/plugin/AccomplishmentHandler.js +1 -1
  59. package/dist/plugin/PluginController.d.ts +16 -3
  60. package/dist/plugin/PluginController.js +24 -18
  61. package/dist/plugin/RimoriClient.d.ts +16 -11
  62. package/dist/plugin/RimoriClient.js +35 -25
  63. package/dist/plugin/StandaloneClient.js +11 -8
  64. package/dist/plugin/ThemeSetter.d.ts +1 -0
  65. package/dist/plugin/ThemeSetter.js +9 -6
  66. package/dist/providers/PluginProvider.d.ts +3 -0
  67. package/dist/providers/PluginProvider.js +4 -4
  68. package/dist/utils/Language.d.ts +2 -1
  69. package/dist/utils/Language.js +4 -2
  70. package/dist/utils/difficultyConverter.js +1 -1
  71. package/dist/utils/endpoint.d.ts +2 -0
  72. package/dist/utils/endpoint.js +2 -0
  73. package/dist/worker/WorkerSetup.js +3 -1
  74. package/example/docs/devdocs.md +231 -0
  75. package/example/docs/overview.md +29 -0
  76. package/example/docs/userdocs.md +123 -0
  77. package/example/rimori.config.ts +89 -0
  78. package/example/worker/vite.config.ts +23 -0
  79. package/example/worker/worker.ts +11 -0
  80. package/package.json +15 -9
  81. package/src/cli/scripts/init/dev-registration.ts +193 -0
  82. package/src/cli/scripts/init/env-setup.ts +44 -0
  83. package/src/cli/scripts/init/file-operations.ts +58 -0
  84. package/src/cli/scripts/init/html-cleaner.ts +48 -0
  85. package/src/cli/scripts/init/main.ts +171 -0
  86. package/src/cli/scripts/init/package-setup.ts +117 -0
  87. package/src/cli/scripts/init/router-transformer.ts +329 -0
  88. package/src/cli/scripts/init/tailwind-config.ts +75 -0
  89. package/src/cli/scripts/init/vite-config.ts +73 -0
  90. package/src/cli/scripts/release/release-config-upload.ts +114 -0
  91. package/src/cli/scripts/release/release-db-update.ts +97 -0
  92. package/src/cli/scripts/release/release-file-upload.ts +138 -0
  93. package/src/cli/scripts/release/release.ts +69 -0
  94. package/src/cli/types/DatabaseTypes.ts +117 -0
  95. package/src/components/ai/Assistant.tsx +4 -4
  96. package/src/components/ai/Avatar.tsx +24 -7
  97. package/src/components/ai/EmbeddedAssistent/CircleAudioAvatar.tsx +1 -1
  98. package/src/components/ai/EmbeddedAssistent/VoiceRecoder.tsx +16 -8
  99. package/src/components/ai/utils.ts +0 -2
  100. package/src/components/audio/Playbutton.tsx +3 -3
  101. package/src/{core → components}/components/ContextMenu.tsx +3 -3
  102. package/src/components.ts +6 -6
  103. package/src/core/controller/AIController.ts +122 -0
  104. package/src/core/controller/ObjectController.ts +115 -0
  105. package/src/{controller → core/controller}/SettingsController.ts +13 -29
  106. package/src/{controller → core/controller}/SharedContentController.ts +5 -5
  107. package/src/core/core.ts +15 -0
  108. package/src/{plugin/fromRimori → fromRimori}/EventBus.ts +28 -10
  109. package/src/fromRimori/PluginTypes.ts +203 -0
  110. package/src/hooks/UseChatHook.ts +5 -4
  111. package/src/index.ts +5 -3
  112. package/src/plugin/AccomplishmentHandler.ts +1 -1
  113. package/src/plugin/PluginController.ts +35 -23
  114. package/src/plugin/RimoriClient.ts +42 -35
  115. package/src/plugin/StandaloneClient.ts +11 -8
  116. package/src/plugin/ThemeSetter.ts +12 -8
  117. package/src/providers/PluginProvider.tsx +7 -4
  118. package/src/utils/Language.ts +4 -2
  119. package/src/utils/difficultyConverter.ts +3 -3
  120. package/src/utils/endpoint.ts +2 -0
  121. package/src/worker/WorkerSetup.ts +4 -2
  122. package/dist/components/PluginController.d.ts +0 -21
  123. package/dist/components/PluginController.js +0 -116
  124. package/dist/controller/AIController.d.ts +0 -23
  125. package/dist/controller/AIController.js +0 -93
  126. package/dist/controller/SidePluginController.d.ts +0 -3
  127. package/dist/controller/SidePluginController.js +0 -31
  128. package/dist/core.d.ts +0 -7
  129. package/dist/core.js +0 -7
  130. package/dist/plugin/ContextMenu.d.ts +0 -17
  131. package/dist/plugin/ContextMenu.js +0 -45
  132. package/dist/plugin/fromRimori/PluginTypes.d.ts +0 -48
  133. package/dist/plugin/fromRimori/SupabaseHandler.d.ts +0 -13
  134. package/dist/plugin/fromRimori/SupabaseHandler.js +0 -55
  135. package/dist/providers/PluginController.d.ts +0 -21
  136. package/dist/providers/PluginController.js +0 -116
  137. package/dist/types/Actions.d.ts +0 -4
  138. package/dist/types/Actions.js +0 -1
  139. package/src/controller/AIController.ts +0 -112
  140. package/src/controller/ObjectController.ts +0 -107
  141. package/src/controller/SidePluginController.ts +0 -25
  142. package/src/core.ts +0 -8
  143. package/src/plugin/fromRimori/PluginTypes.ts +0 -64
  144. package/src/types/Actions.ts +0 -6
  145. /package/dist/{core → components}/components/ContextMenu.d.ts +0 -0
  146. /package/dist/{controller → core/controller}/ObjectController.js +0 -0
  147. /package/dist/{controller → core/controller}/VoiceController.d.ts +0 -0
  148. /package/dist/{controller → core/controller}/VoiceController.js +0 -0
  149. /package/dist/{plugin/fromRimori → fromRimori}/PluginTypes.js +0 -0
  150. /package/src/{controller → core/controller}/VoiceController.ts +0 -0
  151. /package/src/{plugin/fromRimori → fromRimori}/readme.md +0 -0
@@ -3,6 +3,7 @@ interface Props {
3
3
  className?: string;
4
4
  disabled?: boolean;
5
5
  loading?: boolean;
6
+ enablePushToTalk?: boolean;
6
7
  onRecordingStatusChange: (running: boolean) => void;
7
8
  onVoiceRecorded: (message: string) => void;
8
9
  }
@@ -11,12 +11,13 @@ import { jsx as _jsx } from "react/jsx-runtime";
11
11
  import { useState, useRef, forwardRef, useImperativeHandle, useEffect } from 'react';
12
12
  import { FaMicrophone, FaSpinner } from 'react-icons/fa6';
13
13
  import { usePlugin } from '../../../components';
14
- export const VoiceRecorder = forwardRef(({ onVoiceRecorded, iconSize, className, disabled, loading, onRecordingStatusChange }, ref) => {
14
+ export const VoiceRecorder = forwardRef(({ onVoiceRecorded, iconSize, className, disabled, loading, onRecordingStatusChange, enablePushToTalk = false }, ref) => {
15
15
  const [isRecording, setIsRecording] = useState(false);
16
+ const [internalIsProcessing, setInternalIsProcessing] = useState(false);
16
17
  const mediaRecorderRef = useRef(null);
17
18
  const audioChunksRef = useRef([]);
18
19
  const mediaStreamRef = useRef(null);
19
- const { llm } = usePlugin();
20
+ const { ai: llm } = usePlugin();
20
21
  // Ref for latest onVoiceRecorded callback
21
22
  const onVoiceRecordedRef = useRef(onVoiceRecorded);
22
23
  useEffect(() => {
@@ -33,7 +34,10 @@ export const VoiceRecorder = forwardRef(({ onVoiceRecorded, iconSize, className,
33
34
  mediaRecorder.onstop = () => __awaiter(void 0, void 0, void 0, function* () {
34
35
  const audioBlob = new Blob(audioChunksRef.current);
35
36
  audioChunksRef.current = [];
36
- onVoiceRecordedRef.current(yield llm.getTextFromVoice(audioBlob));
37
+ setInternalIsProcessing(true);
38
+ const text = yield llm.getTextFromVoice(audioBlob);
39
+ setInternalIsProcessing(false);
40
+ onVoiceRecordedRef.current(text);
37
41
  });
38
42
  mediaRecorder.start();
39
43
  setIsRecording(true);
@@ -57,6 +61,8 @@ export const VoiceRecorder = forwardRef(({ onVoiceRecorded, iconSize, className,
57
61
  // push to talk feature
58
62
  const spacePressedRef = useRef(false);
59
63
  useEffect(() => {
64
+ if (!enablePushToTalk)
65
+ return;
60
66
  const handleKeyDown = (event) => __awaiter(void 0, void 0, void 0, function* () {
61
67
  if (event.code === 'Space' && !spacePressedRef.current) {
62
68
  spacePressedRef.current = true;
@@ -75,7 +81,7 @@ export const VoiceRecorder = forwardRef(({ onVoiceRecorded, iconSize, className,
75
81
  window.removeEventListener('keydown', handleKeyDown);
76
82
  window.removeEventListener('keyup', handleKeyUp);
77
83
  };
78
- }, []);
79
- return (_jsx("button", { className: "w-16 h-16 flex text-4xl shadow-lg flex-row justify-center items-center rounded-full mx-auto bg-gray-400 dark:bg-gray-800 pl-[6px] disabled:opacity-50 " + className, onClick: isRecording ? stopRecording : startRecording, disabled: disabled || loading, children: loading ? _jsx(FaSpinner, { className: "animate-spin mr-[6px]" }) :
80
- _jsx(FaMicrophone, { size: iconSize, className: "h-7 w-7 mr-2 " + (isRecording ? "text-red-600" : "") }) }));
84
+ }, [enablePushToTalk]);
85
+ return (_jsx("button", { className: "flex flex-row justify-center items-center rounded-full mx-auto disabled:opacity-50 " + className, onClick: isRecording ? stopRecording : startRecording, disabled: disabled || loading || internalIsProcessing, children: loading || internalIsProcessing ? _jsx(FaSpinner, { className: "animate-spin" }) :
86
+ _jsx(FaMicrophone, { size: iconSize, className: (isRecording ? "text-red-600" : "") }) }));
81
87
  });
@@ -9,6 +9,5 @@ export function getFirstMessages(instructions) {
9
9
  if (instructions.assistantMessage) {
10
10
  messages.push({ id: '3', role: 'assistant', content: instructions.assistantMessage });
11
11
  }
12
- console.log("getFirstMessages", messages);
13
12
  return messages;
14
13
  }
@@ -12,7 +12,7 @@ import { useState, useEffect } from 'react';
12
12
  import { FaPlayCircle, FaStopCircle } from "react-icons/fa";
13
13
  import { usePlugin } from "../../providers/PluginProvider";
14
14
  import { Spinner } from '../Spinner';
15
- import { EventBus } from '../../plugin/fromRimori/EventBus';
15
+ import { EventBus } from '../../fromRimori/EventBus';
16
16
  export const AudioPlayOptions = [0.8, 0.9, 1.0, 1.1, 1.2, 1.5];
17
17
  let isFetchingAudio = false;
18
18
  export const AudioPlayer = ({ text, voice, language, hide, playListenerEvent, initialSpeed = 1.0, playOnMount = false, enableSpeedAdjustment = false, }) => {
@@ -20,7 +20,7 @@ export const AudioPlayer = ({ text, voice, language, hide, playListenerEvent, in
20
20
  const [speed, setSpeed] = useState(initialSpeed);
21
21
  const [isPlaying, setIsPlaying] = useState(false);
22
22
  const [isLoading, setIsLoading] = useState(false);
23
- const { llm } = usePlugin();
23
+ const { ai } = usePlugin();
24
24
  useEffect(() => {
25
25
  if (!playListenerEvent)
26
26
  return;
@@ -35,7 +35,7 @@ export const AudioPlayer = ({ text, voice, language, hide, playListenerEvent, in
35
35
  // Function to generate audio from text using API
36
36
  const generateAudio = () => __awaiter(void 0, void 0, void 0, function* () {
37
37
  setIsLoading(true);
38
- const blob = yield llm.getVoice(text, voice || (language ? "aws_default" : "openai_alloy"), 1, language);
38
+ const blob = yield ai.getVoice(text, voice || (language ? "aws_default" : "openai_alloy"), 1, language);
39
39
  setAudioUrl(URL.createObjectURL(blob));
40
40
  setIsLoading(false);
41
41
  });
@@ -1,6 +1,6 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
2
  import { useState, useEffect, useRef } from "react";
3
- import { EventBus } from "../../plugin/fromRimori/EventBus";
3
+ import { EventBus } from "../../fromRimori/EventBus";
4
4
  const ContextMenu = ({ client }) => {
5
5
  const [isOpen, setIsOpen] = useState(false);
6
6
  const [actions, setActions] = useState([]);
@@ -84,7 +84,7 @@ const ContextMenu = ({ client }) => {
84
84
  var _a;
85
85
  setIsOpen(false);
86
86
  (_a = window.getSelection()) === null || _a === void 0 ? void 0 : _a.removeAllRanges();
87
- client.event.emitSidebarAction(action.pluginId, action.actionKey, position.text);
87
+ client.event.emitSidebarAction(action.plugin_id, action.action_key, position.text);
88
88
  } }, index))) }));
89
89
  };
90
90
  function MenuEntryItem(props) {
@@ -1,10 +1,10 @@
1
- export * from "./components/MarkdownEditor";
1
+ export * from "./components/ai/Assistant";
2
+ export * from "./components/ai/Avatar";
3
+ export * from "./components/ai/EmbeddedAssistent/VoiceRecoder";
4
+ export * from "./components/audio/Playbutton";
2
5
  export * from "./components/CRUDModal";
6
+ export * from "./components/MarkdownEditor";
3
7
  export * from "./components/Spinner";
4
- export * from "./components/audio/Playbutton";
5
8
  export * from "./hooks/UseChatHook";
6
9
  export * from "./plugin/ThemeSetter";
7
10
  export * from "./providers/PluginProvider";
8
- export * from "./components/ai/Avatar";
9
- export * from "./components/ai/Assistant";
10
- export * from "./types/Actions";
@@ -1,11 +1,11 @@
1
1
  // React components and hooks exports
2
- export * from "./components/MarkdownEditor";
2
+ export * from "./components/ai/Assistant";
3
+ export * from "./components/ai/Avatar";
4
+ export * from "./components/ai/EmbeddedAssistent/VoiceRecoder";
5
+ export * from "./components/audio/Playbutton";
3
6
  export * from "./components/CRUDModal";
7
+ export * from "./components/MarkdownEditor";
4
8
  export * from "./components/Spinner";
5
- export * from "./components/audio/Playbutton";
6
9
  export * from "./hooks/UseChatHook";
7
10
  export * from "./plugin/ThemeSetter";
8
11
  export * from "./providers/PluginProvider";
9
- export * from "./components/ai/Avatar";
10
- export * from "./components/ai/Assistant";
11
- export * from "./types/Actions";
@@ -0,0 +1,15 @@
1
+ import { Tool } from "../../fromRimori/PluginTypes";
2
+ export interface ToolInvocation {
3
+ toolCallId: string;
4
+ toolName: string;
5
+ args: Record<string, string>;
6
+ }
7
+ export interface Message {
8
+ id?: string;
9
+ role: "user" | "assistant" | "system";
10
+ content: string;
11
+ toolCalls?: ToolInvocation[];
12
+ }
13
+ export declare function generateText(backendUrl: string, messages: Message[], tools: Tool[], token: string): Promise<any>;
14
+ export type OnLLMResponse = (id: string, response: string, finished: boolean, toolInvocations?: ToolInvocation[]) => void;
15
+ export declare function streamChatGPT(backendUrl: string, messages: Message[], tools: Tool[], onResponse: OnLLMResponse, token: string): Promise<void>;
@@ -0,0 +1,120 @@
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
+ var __rest = (this && this.__rest) || function (s, e) {
11
+ var t = {};
12
+ for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
13
+ t[p] = s[p];
14
+ if (s != null && typeof Object.getOwnPropertySymbols === "function")
15
+ for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
16
+ if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
17
+ t[p[i]] = s[p[i]];
18
+ }
19
+ return t;
20
+ };
21
+ export function generateText(backendUrl, messages, tools, token) {
22
+ return __awaiter(this, void 0, void 0, function* () {
23
+ const response = yield fetch(`${backendUrl}/ai/llm`, {
24
+ method: 'POST',
25
+ body: JSON.stringify({ messages, tools }),
26
+ headers: { 'Authorization': `Bearer ${token}`, 'Content-Type': 'application/json' }
27
+ });
28
+ return yield response.json();
29
+ });
30
+ }
31
+ export function streamChatGPT(backendUrl, messages, tools, onResponse, token) {
32
+ return __awaiter(this, void 0, void 0, function* () {
33
+ const messageId = Math.random().toString(36).substring(3);
34
+ let currentMessages = [...messages];
35
+ while (true) {
36
+ const messagesForApi = currentMessages.map((_a) => {
37
+ var { id } = _a, rest = __rest(_a, ["id"]);
38
+ return rest;
39
+ });
40
+ const response = yield fetch(`${backendUrl}/ai/llm`, {
41
+ method: 'POST',
42
+ body: JSON.stringify({ messages: messagesForApi, tools, stream: true }),
43
+ headers: { 'Authorization': `Bearer ${token}`, 'Content-Type': 'application/json' }
44
+ });
45
+ if (!response.body) {
46
+ console.error('No response body.');
47
+ return;
48
+ }
49
+ const reader = response.body.getReader();
50
+ const decoder = new TextDecoder('utf-8');
51
+ let content = "";
52
+ let done = false;
53
+ let toolInvocations = [];
54
+ let finishReason = "";
55
+ while (!done) {
56
+ const { value, done: readerDone } = yield reader.read();
57
+ if (value) {
58
+ const chunk = decoder.decode(value, { stream: true });
59
+ const lines = chunk.split('\n').filter(line => line.trim() !== '');
60
+ for (const line of lines) {
61
+ const command = line.substring(0, 1);
62
+ if (command === '0') {
63
+ const data = line.substring(3, line.length - 1);
64
+ content += data;
65
+ onResponse(messageId, content.replace(/\\n/g, '\n').replace(/\\+"/g, '"'), false);
66
+ }
67
+ else if (command === 'd' || command === 'e') {
68
+ const eventData = JSON.parse(line.substring(2));
69
+ finishReason = eventData.finishReason;
70
+ done = true;
71
+ break;
72
+ }
73
+ else if (command === '9') {
74
+ const toolInvocation = JSON.parse(line.substring(2));
75
+ toolInvocations.push(toolInvocation);
76
+ }
77
+ }
78
+ }
79
+ if (readerDone) {
80
+ done = true;
81
+ }
82
+ }
83
+ if (content || toolInvocations.length > 0) {
84
+ currentMessages.push({
85
+ id: messageId,
86
+ role: "assistant",
87
+ content: content,
88
+ toolCalls: toolInvocations.length > 0 ? toolInvocations : undefined,
89
+ });
90
+ }
91
+ if (finishReason !== 'tool-calls') {
92
+ onResponse(messageId, content.replace(/\\n/g, '\n'), true, toolInvocations);
93
+ return;
94
+ }
95
+ const toolResults = [];
96
+ for (const toolInvocation of toolInvocations) {
97
+ const tool = tools.find(t => t.name === toolInvocation.toolName);
98
+ if (tool && tool.execute) {
99
+ try {
100
+ const result = yield tool.execute(toolInvocation.args);
101
+ toolResults.push({
102
+ id: Math.random().toString(36).substring(3),
103
+ role: "user",
104
+ content: `Tool '${toolInvocation.toolName}' returned: ${JSON.stringify(result)}`,
105
+ });
106
+ }
107
+ catch (error) {
108
+ console.error(`Error executing tool ${toolInvocation.toolName}:`, error);
109
+ toolResults.push({
110
+ id: Math.random().toString(36).substring(3),
111
+ role: "user",
112
+ content: `Tool '${toolInvocation.toolName}' failed with error: ${error}`,
113
+ });
114
+ }
115
+ }
116
+ }
117
+ currentMessages.push(...toolResults);
118
+ }
119
+ });
120
+ }
@@ -8,7 +8,15 @@ interface ObjectToolParameter {
8
8
  type: ObjectToolParameterType;
9
9
  description?: string;
10
10
  enum?: string[];
11
+ optional?: boolean;
11
12
  }
13
+ /**
14
+ * The tools that the AI can use.
15
+ *
16
+ * The key is the name of the tool.
17
+ * The value is the parameter of the tool.
18
+ *
19
+ */
12
20
  export type ObjectTool = {
13
21
  [key: string]: ObjectToolParameter;
14
22
  };
@@ -1,6 +1,14 @@
1
1
  import { SupabaseClient } from "@supabase/supabase-js";
2
- import { LanguageLevel } from "../utils/difficultyConverter";
3
- import { Language } from "../utils/Language";
2
+ import { LanguageLevel } from "../../utils/difficultyConverter";
3
+ import { Language } from "../../utils/Language";
4
+ export interface Buddy {
5
+ id: string;
6
+ name: string;
7
+ description: string;
8
+ avatarUrl: string;
9
+ voiceId: string;
10
+ aiPersonality: string;
11
+ }
4
12
  export interface UserInfo {
5
13
  skill_level_reading: LanguageLevel;
6
14
  skill_level_writing: LanguageLevel;
@@ -10,13 +18,14 @@ export interface UserInfo {
10
18
  skill_level_understanding: LanguageLevel;
11
19
  goal_longterm: string;
12
20
  goal_weekly: string;
13
- study_buddy: string;
21
+ study_buddy: Buddy;
14
22
  story_genre: string;
15
23
  study_duration: number;
16
24
  mother_tongue: Language;
17
25
  motivation_type: string;
18
26
  onboarding_completed: boolean;
19
27
  context_menu_on_select: boolean;
28
+ user_name?: string;
20
29
  }
21
30
  export declare class SettingsController {
22
31
  private pluginId;
@@ -24,7 +33,6 @@ export declare class SettingsController {
24
33
  constructor(supabase: SupabaseClient, pluginId: string);
25
34
  private fetchSettings;
26
35
  setSettings(settings: any): Promise<void>;
27
- getUserInfo(): Promise<UserInfo>;
28
36
  /**
29
37
  * Get the settings for the plugin. T can be any type of settings, UserSettings or SystemSettings.
30
38
  * @param defaultSettings The default settings to use if no settings are found.
@@ -26,31 +26,6 @@ export class SettingsController {
26
26
  yield this.supabase.from("plugin_settings").upsert({ plugin_id: this.pluginId, settings });
27
27
  });
28
28
  }
29
- getUserInfo() {
30
- return __awaiter(this, void 0, void 0, function* () {
31
- const { data } = yield this.supabase.from("profiles").select("*");
32
- if (!data || data.length === 0) {
33
- return {
34
- mother_tongue: "en",
35
- skill_level_listening: "Pre-A1",
36
- skill_level_reading: "Pre-A1",
37
- skill_level_speaking: "Pre-A1",
38
- skill_level_writing: "Pre-A1",
39
- skill_level_understanding: "Pre-A1",
40
- skill_level_grammar: "Pre-A1",
41
- goal_longterm: "",
42
- goal_weekly: "",
43
- study_buddy: "clarence",
44
- story_genre: "adventure",
45
- study_duration: 30,
46
- motivation_type: "self-motivated",
47
- onboarding_completed: false,
48
- context_menu_on_select: false,
49
- };
50
- }
51
- return data[0].settings;
52
- });
53
- }
54
29
  /**
55
30
  * Get the settings for the plugin. T can be any type of settings, UserSettings or SystemSettings.
56
31
  * @param defaultSettings The default settings to use if no settings are found.
@@ -1,5 +1,5 @@
1
1
  import { SupabaseClient } from '@supabase/supabase-js';
2
- import { RimoriClient } from "../plugin/RimoriClient";
2
+ import { RimoriClient } from "../../plugin/RimoriClient";
3
3
  import { ObjectRequest } from "./ObjectController";
4
4
  export interface SharedContentObjectRequest extends ObjectRequest {
5
5
  fixedProperties?: Record<string, string | number | boolean>;
@@ -46,14 +46,14 @@ export class SharedContentController {
46
46
  // generate new assignments
47
47
  const fullInstructions = yield this.getGeneratorInstructions(contentType, generatorInstructions, filter);
48
48
  console.log('fullInstructions:', fullInstructions);
49
- const instructions = yield this.rimoriClient.llm.getObject(fullInstructions);
49
+ const instructions = yield this.rimoriClient.ai.getObject(fullInstructions);
50
50
  console.log('instructions:', instructions);
51
51
  const { data: newAssignment, error: insertError } = yield this.supabase.from("shared_content").insert({
52
52
  private: privateTopic,
53
53
  content_type: contentType,
54
- topic: instructions.topic,
54
+ title: instructions.title,
55
55
  keywords: instructions.keywords.map(({ text }) => text),
56
- data: Object.assign(Object.assign(Object.assign({}, instructions), { topic: undefined, keywords: undefined }), generatorInstructions.fixedProperties),
56
+ data: Object.assign(Object.assign(Object.assign({}, instructions), { title: undefined, keywords: undefined }), generatorInstructions.fixedProperties),
57
57
  }).select();
58
58
  if (insertError) {
59
59
  console.error('error inserting new assignment:', insertError);
@@ -67,7 +67,7 @@ export class SharedContentController {
67
67
  const completedTopics = yield this.getCompletedTopics(contentType, filter);
68
68
  generatorInstructions.instructions += `
69
69
  The following topics are already taken: ${completedTopics.join(', ')}`;
70
- generatorInstructions.tool.topic = {
70
+ generatorInstructions.tool.title = {
71
71
  type: "string",
72
72
  description: "What the topic is about. Short. ",
73
73
  };
@@ -0,0 +1,13 @@
1
+ export * from "../fromRimori/PluginTypes";
2
+ export * from "../plugin/PluginController";
3
+ export * from "../plugin/RimoriClient";
4
+ export * from "../utils/difficultyConverter";
5
+ export * from "../utils/Language";
6
+ export * from "../utils/PluginUtils";
7
+ export * from "../worker/WorkerSetup";
8
+ export { EventBusMessage } from "../fromRimori/EventBus";
9
+ export { Buddy, UserInfo } from "./controller/SettingsController";
10
+ export { SharedContent } from "./controller/SharedContentController";
11
+ export { Message, OnLLMResponse, ToolInvocation } from "./controller/AIController";
12
+ export { MacroAccomplishmentPayload, MicroAccomplishmentPayload } from "../plugin/AccomplishmentHandler";
13
+ export { Tool } from "../fromRimori/PluginTypes";
@@ -0,0 +1,8 @@
1
+ // Core functionality exports
2
+ export * from "../fromRimori/PluginTypes";
3
+ export * from "../plugin/PluginController";
4
+ export * from "../plugin/RimoriClient";
5
+ export * from "../utils/difficultyConverter";
6
+ export * from "../utils/Language";
7
+ export * from "../utils/PluginUtils";
8
+ export * from "../worker/WorkerSetup";
@@ -52,7 +52,7 @@ export declare class EventBusHandler {
52
52
  * @param topics - The topic of the event.
53
53
  * @param handler - The handler to be called when the event is emitted.
54
54
  * @param ignoreSender - The senders to ignore.
55
- * @returns The ids of the listeners.
55
+ * @returns An EventListener object containing an off() method to unsubscribe the listeners.
56
56
  */
57
57
  on<T = EventPayload>(topics: string | string[], handler: EventHandler<T>, ignoreSender?: string[]): EventListener;
58
58
  /**
@@ -60,9 +60,9 @@ export declare class EventBusHandler {
60
60
  * @param sender - The sender of the event.
61
61
  * @param topic - The topic of the event.
62
62
  * @param handler - The handler to be called when the event is received. The handler returns the data to be emitted. Can be a static object or a function.
63
- * @returns The ids of the listeners.
63
+ * @returns An EventListener object containing an off() method to unsubscribe the listeners.
64
64
  */
65
- respond(sender: string, topic: string, handler: EventPayload | ((data: EventBusMessage) => EventPayload | Promise<EventPayload>)): EventListener;
65
+ respond(sender: string, topic: string | string[], handler: EventPayload | ((data: EventBusMessage) => EventPayload | Promise<EventPayload>)): EventListener;
66
66
  /**
67
67
  * Subscribes to an event on the event bus. The handler will be called once and then removed.
68
68
  * @param topic - The topic of the event.
@@ -90,7 +90,7 @@ export class EventBusHandler {
90
90
  * @param topics - The topic of the event.
91
91
  * @param handler - The handler to be called when the event is emitted.
92
92
  * @param ignoreSender - The senders to ignore.
93
- * @returns The ids of the listeners.
93
+ * @returns An EventListener object containing an off() method to unsubscribe the listeners.
94
94
  */
95
95
  on(topics, handler, ignoreSender = []) {
96
96
  const ids = this.toArray(topics).map(topic => {
@@ -117,16 +117,33 @@ export class EventBusHandler {
117
117
  * @param sender - The sender of the event.
118
118
  * @param topic - The topic of the event.
119
119
  * @param handler - The handler to be called when the event is received. The handler returns the data to be emitted. Can be a static object or a function.
120
- * @returns The ids of the listeners.
120
+ * @returns An EventListener object containing an off() method to unsubscribe the listeners.
121
121
  */
122
122
  respond(sender, topic, handler) {
123
- const listener = this.on(topic, (data) => __awaiter(this, void 0, void 0, function* () {
124
- const response = typeof handler === "function" ? yield handler(data) : handler;
125
- this.emit(sender, topic, response, data.eventId);
126
- }), [sender]);
127
- this.logIfDebug(`Added respond listener ` + sender + " to topic " + topic, { listener, sender });
123
+ const topics = Array.isArray(topic) ? topic : [topic];
124
+ const listeners = topics.map(topic => {
125
+ const blackListedEventIds = [];
126
+ //To allow event communication inside the same plugin the sender needs to be ignored but the events still need to be checked for the same event just reaching the subscriber to prevent infinite loops
127
+ const finalIgnoreSender = !topic.startsWith("self.") ? [sender] : [];
128
+ const listener = this.on(topic, (data) => __awaiter(this, void 0, void 0, function* () {
129
+ if (blackListedEventIds.includes(data.eventId)) {
130
+ // console.log("BLACKLISTED EVENT ID", data.eventId);
131
+ return;
132
+ }
133
+ blackListedEventIds.push(data.eventId);
134
+ if (blackListedEventIds.length > 20) {
135
+ blackListedEventIds.shift();
136
+ }
137
+ const response = typeof handler === "function" ? yield handler(data) : handler;
138
+ this.emit(sender, topic, response, data.eventId);
139
+ }), finalIgnoreSender);
140
+ this.logIfDebug(`Added respond listener ` + sender + " to topic " + topic, { listener, sender });
141
+ return {
142
+ off: () => listener.off()
143
+ };
144
+ });
128
145
  return {
129
- off: () => listener.off()
146
+ off: () => listeners.forEach(listener => listener.off())
130
147
  };
131
148
  }
132
149
  /**