@rimori/client 1.1.10 → 1.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (171) hide show
  1. package/README.md +189 -63
  2. package/dist/cli/scripts/init/dev-registration.d.ts +35 -0
  3. package/dist/cli/scripts/init/dev-registration.js +174 -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 +160 -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/LoggerExample.d.ts +6 -0
  31. package/dist/components/LoggerExample.js +79 -0
  32. package/dist/components/ai/Assistant.js +5 -5
  33. package/dist/components/ai/Avatar.d.ts +3 -2
  34. package/dist/components/ai/Avatar.js +11 -6
  35. package/dist/components/ai/EmbeddedAssistent/CircleAudioAvatar.js +1 -1
  36. package/dist/components/ai/EmbeddedAssistent/VoiceRecoder.d.ts +1 -0
  37. package/dist/components/ai/EmbeddedAssistent/VoiceRecoder.js +48 -33
  38. package/dist/components/ai/utils.js +0 -1
  39. package/dist/components/audio/Playbutton.js +4 -4
  40. package/dist/{core → components}/components/ContextMenu.js +50 -11
  41. package/dist/components.d.ts +5 -5
  42. package/dist/components.js +5 -5
  43. package/dist/core/controller/AIController.d.ts +15 -0
  44. package/dist/core/controller/AIController.js +253 -0
  45. package/dist/core/controller/AudioController.d.ts +0 -0
  46. package/dist/core/controller/AudioController.js +1 -0
  47. package/dist/{controller → core/controller}/ObjectController.d.ts +10 -2
  48. package/dist/{controller → core/controller}/ObjectController.js +8 -8
  49. package/dist/{controller → core/controller}/SettingsController.d.ts +28 -4
  50. package/dist/{controller → core/controller}/SettingsController.js +0 -25
  51. package/dist/{controller → core/controller}/SharedContentController.d.ts +31 -3
  52. package/dist/{controller → core/controller}/SharedContentController.js +77 -26
  53. package/dist/core/controller/VoiceController.d.ts +9 -0
  54. package/dist/{controller → core/controller}/VoiceController.js +11 -4
  55. package/dist/core/core.d.ts +14 -0
  56. package/dist/core/core.js +8 -0
  57. package/dist/{plugin/fromRimori → fromRimori}/EventBus.d.ts +3 -3
  58. package/dist/{plugin/fromRimori → fromRimori}/EventBus.js +26 -9
  59. package/dist/fromRimori/PluginTypes.d.ts +174 -0
  60. package/dist/hooks/UseChatHook.d.ts +2 -1
  61. package/dist/hooks/UseChatHook.js +6 -4
  62. package/dist/hooks/UseLogger.d.ts +30 -0
  63. package/dist/hooks/UseLogger.js +122 -0
  64. package/dist/index.d.ts +6 -3
  65. package/dist/index.js +5 -3
  66. package/dist/plugin/AccomplishmentHandler.d.ts +1 -1
  67. package/dist/plugin/AccomplishmentHandler.js +1 -1
  68. package/dist/plugin/AudioController.d.ts +37 -0
  69. package/dist/plugin/AudioController.js +68 -0
  70. package/dist/plugin/Logger.d.ts +68 -0
  71. package/dist/plugin/Logger.js +256 -0
  72. package/dist/plugin/LoggerExample.d.ts +16 -0
  73. package/dist/plugin/LoggerExample.js +140 -0
  74. package/dist/plugin/PluginController.d.ts +30 -5
  75. package/dist/plugin/PluginController.js +182 -53
  76. package/dist/plugin/RimoriClient.d.ts +68 -21
  77. package/dist/plugin/RimoriClient.js +88 -41
  78. package/dist/plugin/StandaloneClient.d.ts +1 -0
  79. package/dist/plugin/StandaloneClient.js +24 -10
  80. package/dist/plugin/ThemeSetter.d.ts +2 -1
  81. package/dist/plugin/ThemeSetter.js +13 -7
  82. package/dist/providers/PluginProvider.d.ts +4 -1
  83. package/dist/providers/PluginProvider.js +39 -13
  84. package/dist/utils/Language.d.ts +2 -1
  85. package/dist/utils/Language.js +4 -2
  86. package/dist/utils/audioFormats.d.ts +26 -0
  87. package/dist/utils/audioFormats.js +67 -0
  88. package/dist/utils/difficultyConverter.js +1 -1
  89. package/dist/utils/endpoint.d.ts +2 -0
  90. package/dist/utils/endpoint.js +2 -0
  91. package/dist/worker/WorkerSetup.d.ts +3 -2
  92. package/dist/worker/WorkerSetup.js +22 -65
  93. package/example/docs/devdocs.md +231 -0
  94. package/example/docs/overview.md +29 -0
  95. package/example/docs/userdocs.md +123 -0
  96. package/example/rimori.config.ts +89 -0
  97. package/example/worker/vite.config.ts +23 -0
  98. package/example/worker/worker.ts +11 -0
  99. package/package.json +16 -9
  100. package/src/cli/scripts/init/dev-registration.ts +192 -0
  101. package/src/cli/scripts/init/env-setup.ts +44 -0
  102. package/src/cli/scripts/init/file-operations.ts +58 -0
  103. package/src/cli/scripts/init/html-cleaner.ts +48 -0
  104. package/src/cli/scripts/init/main.ts +172 -0
  105. package/src/cli/scripts/init/package-setup.ts +117 -0
  106. package/src/cli/scripts/init/router-transformer.ts +329 -0
  107. package/src/cli/scripts/init/tailwind-config.ts +75 -0
  108. package/src/cli/scripts/init/vite-config.ts +73 -0
  109. package/src/cli/scripts/release/release-config-upload.ts +114 -0
  110. package/src/cli/scripts/release/release-db-update.ts +97 -0
  111. package/src/cli/scripts/release/release-file-upload.ts +138 -0
  112. package/src/cli/scripts/release/release.ts +69 -0
  113. package/src/cli/types/DatabaseTypes.ts +117 -0
  114. package/src/components/ai/Assistant.tsx +5 -5
  115. package/src/components/ai/Avatar.tsx +25 -8
  116. package/src/components/ai/EmbeddedAssistent/CircleAudioAvatar.tsx +1 -1
  117. package/src/components/ai/EmbeddedAssistent/VoiceRecoder.tsx +50 -35
  118. package/src/components/ai/utils.ts +0 -2
  119. package/src/components/audio/Playbutton.tsx +4 -4
  120. package/src/{core → components}/components/ContextMenu.tsx +56 -12
  121. package/src/components.ts +6 -6
  122. package/src/core/controller/AIController.ts +283 -0
  123. package/src/core/controller/ObjectController.ts +115 -0
  124. package/src/{controller → core/controller}/SettingsController.ts +29 -29
  125. package/src/{controller → core/controller}/SharedContentController.ts +91 -29
  126. package/src/core/controller/VoiceController.ts +31 -0
  127. package/src/core/core.ts +16 -0
  128. package/src/{plugin/fromRimori → fromRimori}/EventBus.ts +29 -11
  129. package/src/fromRimori/PluginTypes.ts +205 -0
  130. package/src/hooks/UseChatHook.ts +8 -5
  131. package/src/index.ts +6 -3
  132. package/src/plugin/AccomplishmentHandler.ts +1 -1
  133. package/src/plugin/AudioController.ts +58 -0
  134. package/src/plugin/Logger.ts +324 -0
  135. package/src/plugin/PluginController.ts +203 -63
  136. package/src/plugin/RimoriClient.ts +127 -55
  137. package/src/plugin/StandaloneClient.ts +30 -11
  138. package/src/plugin/ThemeSetter.ts +16 -9
  139. package/src/providers/PluginProvider.tsx +46 -13
  140. package/src/utils/Language.ts +4 -2
  141. package/src/utils/difficultyConverter.ts +3 -3
  142. package/src/utils/endpoint.ts +2 -0
  143. package/src/worker/WorkerSetup.ts +13 -60
  144. package/dist/components/PluginController.d.ts +0 -21
  145. package/dist/components/PluginController.js +0 -116
  146. package/dist/controller/AIController.d.ts +0 -23
  147. package/dist/controller/AIController.js +0 -93
  148. package/dist/controller/SidePluginController.d.ts +0 -3
  149. package/dist/controller/SidePluginController.js +0 -31
  150. package/dist/controller/VoiceController.d.ts +0 -10
  151. package/dist/core.d.ts +0 -7
  152. package/dist/core.js +0 -7
  153. package/dist/plugin/ContextMenu.d.ts +0 -17
  154. package/dist/plugin/ContextMenu.js +0 -45
  155. package/dist/plugin/fromRimori/PluginTypes.d.ts +0 -48
  156. package/dist/plugin/fromRimori/SupabaseHandler.d.ts +0 -13
  157. package/dist/plugin/fromRimori/SupabaseHandler.js +0 -55
  158. package/dist/providers/PluginController.d.ts +0 -21
  159. package/dist/providers/PluginController.js +0 -116
  160. package/dist/types/Actions.d.ts +0 -4
  161. package/dist/types/Actions.js +0 -1
  162. package/src/controller/AIController.ts +0 -112
  163. package/src/controller/ObjectController.ts +0 -107
  164. package/src/controller/SidePluginController.ts +0 -25
  165. package/src/controller/VoiceController.ts +0 -26
  166. package/src/core.ts +0 -8
  167. package/src/plugin/fromRimori/PluginTypes.ts +0 -64
  168. package/src/types/Actions.ts +0 -6
  169. /package/dist/{core → components}/components/ContextMenu.d.ts +0 -0
  170. /package/dist/{plugin/fromRimori → fromRimori}/PluginTypes.js +0 -0
  171. /package/src/{plugin/fromRimori → fromRimori}/readme.md +0 -0
@@ -0,0 +1,103 @@
1
+ /**
2
+ * Supported database column data types for table schema definitions.
3
+ */
4
+ type DbColumnType = 'decimal' | 'integer' | 'text' | 'boolean' | 'json' | 'timestamp' | 'uuid';
5
+ /**
6
+ * Foreign key relationship configuration with cascade delete support.
7
+ * Defines a relationship where the source record is deleted when the destination record is deleted.
8
+ */
9
+ interface ForeignKeyRelation {
10
+ /** The target table that this column references */
11
+ references_table: string;
12
+ /** The target column in the referenced table (defaults to 'id') */
13
+ references_column?: string;
14
+ /** Whether to cascade delete when the referenced record is deleted */
15
+ on_delete_cascade: boolean;
16
+ }
17
+ /**
18
+ * Database column definition with support for types, constraints, and relationships.
19
+ */
20
+ export interface DbColumnDefinition {
21
+ /** The data type of the column */
22
+ type: DbColumnType;
23
+ /** Human-readable description of the column's purpose */
24
+ description: string;
25
+ /** Whether the column can contain null values */
26
+ nullable?: boolean;
27
+ /** Whether the column has a unique constraint */
28
+ unique?: boolean;
29
+ /** Default value for the column. can also use sql functions like now(), auth.uid() or gen_random_uuid() */
30
+ default_value?: string | number | boolean;
31
+ /** Array of allowed values for enumerated columns */
32
+ /** Foreign key relationship configuration */
33
+ foreign_key?: ForeignKeyRelation;
34
+ /** The name of the column before it was renamed. */
35
+ old_name?: string;
36
+ /** Whether the column is deprecated. The column gets renamed to column_name_old. To fully remove the column, first set deprecated to true and then after a release, remove the column from the table definition. */
37
+ deprecated?: boolean;
38
+ /** Whether the column is a primary key */
39
+ /** Restrictions for the column. If the column is restricted, the permission is further restricted. E.g. if the column is restricted to user, then the user can only read the column if they have the right permission.
40
+ * Example: Denying users to update the column, but allowing the moderator to update the column.
41
+ */
42
+ restrict?: {
43
+ /** Restrictions for the user */
44
+ user: Partial<Omit<DbPermissionDefinition, 'delete'>>;
45
+ /** Restrictions for the moderator */
46
+ moderator?: Partial<Omit<DbPermissionDefinition, 'delete'>>;
47
+ };
48
+ }
49
+ /**
50
+ * Base table structure that all database tables inherit.
51
+ * Includes standard audit fields for tracking creation and ownership.
52
+ */
53
+ interface BaseTableStructure {
54
+ /** Unique identifier for the record */
55
+ id: DbColumnDefinition;
56
+ /** Timestamp when the record was created */
57
+ created_at: DbColumnDefinition;
58
+ /** ID of the user who created the record */
59
+ created_by: DbColumnDefinition;
60
+ }
61
+ /**
62
+ * Complete database table schema definition.
63
+ * Defines the structure, constraints, and relationships for a database table.
64
+ */
65
+ export interface DbTableDefinition {
66
+ /** Name of the database table */
67
+ table_name: string;
68
+ /** Description of the table's purpose and usage */
69
+ description: string;
70
+ /** Permissions for the table */
71
+ permissions: {
72
+ user: DbPermissionDefinition;
73
+ moderator?: DbPermissionDefinition;
74
+ };
75
+ /** Column definitions for the table */
76
+ columns: {
77
+ [column_name: string]: DbColumnDefinition;
78
+ };
79
+ }
80
+ /**
81
+ * Permission definition for a database table.
82
+ * NONE means the action is not allowed.
83
+ * OWN means only do the action on your own records.
84
+ * ALL means do the action on all records.
85
+ *
86
+ * Defines the permissions for a database table.
87
+ */
88
+ export type DbPermission = "NONE" | "OWN" | "ALL";
89
+ /**
90
+ * Permission definition for a database table.
91
+ * Defines the permissions for a database table.
92
+ */
93
+ export interface DbPermissionDefinition {
94
+ read: DbPermission;
95
+ insert: DbPermission;
96
+ update: DbPermission;
97
+ delete: DbPermission;
98
+ }
99
+ /**
100
+ * Full table definition that includes automatically generated fields.
101
+ */
102
+ export type FullTable<T extends Record<string, DbColumnDefinition>> = T & BaseTableStructure;
103
+ export {};
@@ -0,0 +1,2 @@
1
+ // Database table structure definitions
2
+ export {};
@@ -0,0 +1,6 @@
1
+ import React from 'react';
2
+ /**
3
+ * Example component demonstrating Logger usage in a React component.
4
+ * Shows how console methods are automatically captured by the Logger.
5
+ */
6
+ export declare const LoggerExample: React.FC;
@@ -0,0 +1,79 @@
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 { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
11
+ import { useState } from 'react';
12
+ import { useLogging, useLogger } from '../hooks/UseLogger';
13
+ /**
14
+ * Example component demonstrating Logger usage in a React component.
15
+ * Shows how console methods are automatically captured by the Logger.
16
+ */
17
+ export const LoggerExample = () => {
18
+ const [logMessage, setLogMessage] = useState('Hello from Logger Example');
19
+ const [logData, setLogData] = useState('{"key": "value"}');
20
+ // Initialize the logger - this overrides console methods globally
21
+ const logger = useLogger(process.env.NODE_ENV === 'production');
22
+ // Get logging utilities
23
+ const { sendAllLogs, getStats, clearLogs, exportLogs, sendLogsByLevel } = useLogging(process.env.NODE_ENV === 'production');
24
+ const handleConsoleLog = () => {
25
+ // This will be automatically captured by the Logger
26
+ console.log(logMessage, logData ? JSON.parse(logData) : '');
27
+ };
28
+ const handleConsoleInfo = () => {
29
+ // This will be automatically captured by the Logger
30
+ console.info(logMessage, logData ? JSON.parse(logData) : '');
31
+ };
32
+ const handleConsoleWarn = () => {
33
+ // This will be automatically captured by the Logger and include screenshot + mouse position
34
+ console.warn(logMessage, logData ? JSON.parse(logData) : '');
35
+ };
36
+ const handleConsoleError = () => {
37
+ // This will be automatically captured by the Logger and include screenshot + mouse position
38
+ console.error(logMessage, logData ? JSON.parse(logData) : '');
39
+ };
40
+ const handleConsoleDebug = () => {
41
+ // This will be automatically captured by the Logger
42
+ console.debug(logMessage, logData ? JSON.parse(logData) : '');
43
+ };
44
+ const handleSendLogs = () => __awaiter(void 0, void 0, void 0, function* () {
45
+ yield sendAllLogs();
46
+ alert('Logs sent to Rimori!');
47
+ });
48
+ const handleGetStats = () => {
49
+ const stats = getStats();
50
+ alert(`Log Statistics:\nTotal: ${stats.total}\nDebug: ${stats.byLevel.debug}\nInfo: ${stats.byLevel.info}\nWarn: ${stats.byLevel.warn}\nError: ${stats.byLevel.error}`);
51
+ };
52
+ const handleClearLogs = () => {
53
+ clearLogs();
54
+ alert('Logs cleared!');
55
+ };
56
+ const handleExportLogs = () => {
57
+ const exportedLogs = exportLogs();
58
+ const blob = new Blob([exportedLogs], { type: 'application/json' });
59
+ const url = URL.createObjectURL(blob);
60
+ const a = document.createElement('a');
61
+ a.href = url;
62
+ a.download = 'rimori-logs.json';
63
+ a.click();
64
+ URL.revokeObjectURL(url);
65
+ };
66
+ const handleSendErrorLogs = () => __awaiter(void 0, void 0, void 0, function* () {
67
+ yield sendLogsByLevel('error');
68
+ alert('Error logs sent to Rimori!');
69
+ });
70
+ const handleTriggerError = () => {
71
+ // This will trigger an unhandled error that the logger will catch via console.error override
72
+ throw new Error('This is a test error for the logger');
73
+ };
74
+ const handleTriggerPromiseRejection = () => {
75
+ // This will trigger an unhandled promise rejection that the logger will catch
76
+ Promise.reject(new Error('This is a test promise rejection'));
77
+ };
78
+ return (_jsxs("div", { style: { padding: '20px', maxWidth: '800px' }, children: [_jsx("h2", { children: "Logger Example - Console Override Demo" }), _jsxs("div", { style: { marginBottom: '20px', padding: '15px', backgroundColor: '#e3f2fd', borderRadius: '5px' }, children: [_jsx("h4", { children: "\uD83C\uDFAF Key Feature: Console Methods Override" }), _jsxs("p", { children: ["The Logger automatically overrides ", _jsx("code", { children: "console.log" }), ", ", _jsx("code", { children: "console.info" }), ",", _jsx("code", { children: "console.warn" }), ", ", _jsx("code", { children: "console.error" }), ", and ", _jsx("code", { children: "console.debug" }), " globally. All console calls are automatically captured and stored with context information."] })] }), _jsx("div", { style: { marginBottom: '20px' }, children: _jsxs("label", { children: ["Log Message:", _jsx("input", { type: "text", value: logMessage, onChange: (e) => setLogMessage(e.target.value), placeholder: "Enter log message", style: { width: '100%', marginTop: '5px' } })] }) }), _jsx("div", { style: { marginBottom: '20px' }, children: _jsxs("label", { children: ["Log Data (JSON):", _jsx("textarea", { value: logData, onChange: (e) => setLogData(e.target.value), placeholder: '{"key": "value"}', style: { width: '100%', height: '60px', marginTop: '5px' } })] }) }), _jsxs("div", { style: { marginBottom: '20px' }, children: [_jsx("h3", { children: "Console Method Calls (Automatically Captured)" }), _jsx("button", { onClick: handleConsoleLog, style: { margin: '5px' }, children: "console.log()" }), _jsx("button", { onClick: handleConsoleInfo, style: { margin: '5px' }, children: "console.info()" }), _jsx("button", { onClick: handleConsoleWarn, style: { margin: '5px', backgroundColor: '#ff9800' }, children: "console.warn() \uD83D\uDCF8" }), _jsx("button", { onClick: handleConsoleError, style: { margin: '5px', backgroundColor: '#f44336' }, children: "console.error() \uD83D\uDCF8" }), _jsx("button", { onClick: handleConsoleDebug, style: { margin: '5px' }, children: "console.debug()" })] }), _jsxs("div", { style: { marginBottom: '20px' }, children: [_jsx("h3", { children: "Log Management" }), _jsx("button", { onClick: handleSendLogs, style: { margin: '5px' }, children: "Send All Logs to Rimori" }), _jsx("button", { onClick: handleSendErrorLogs, style: { margin: '5px', backgroundColor: '#f44336' }, children: "Send Error Logs Only" }), _jsx("button", { onClick: handleGetStats, style: { margin: '5px' }, children: "Get Log Statistics" }), _jsx("button", { onClick: handleClearLogs, style: { margin: '5px' }, children: "Clear Logs" }), _jsx("button", { onClick: handleExportLogs, style: { margin: '5px' }, children: "Export Logs (JSON)" })] }), _jsxs("div", { style: { marginBottom: '20px' }, children: [_jsx("h3", { children: "Test Error Handling" }), _jsx("button", { onClick: handleTriggerError, style: { margin: '5px', backgroundColor: '#ff6b6b' }, children: "Trigger Unhandled Error" }), _jsx("button", { onClick: handleTriggerPromiseRejection, style: { margin: '5px', backgroundColor: '#ff6b6b' }, children: "Trigger Promise Rejection" })] }), _jsxs("div", { style: { marginTop: '30px', padding: '15px', backgroundColor: '#f5f5f5', borderRadius: '5px' }, children: [_jsx("h4", { children: "\uD83D\uDCCB How It Works:" }), _jsxs("ul", { children: [_jsxs("li", { children: [_jsx("strong", { children: "Automatic Capture:" }), " All console calls are automatically captured by the Logger"] }), _jsxs("li", { children: [_jsx("strong", { children: "No Manual Logging:" }), " Just use ", _jsx("code", { children: "console.log()" }), " as usual - no need to call Logger methods"] }), _jsxs("li", { children: [_jsx("strong", { children: "Production Filtering:" }), " In production, only warnings and errors show in console, but all are stored"] }), _jsxs("li", { children: [_jsx("strong", { children: "Screenshot Capture:" }), " Errors and warnings automatically capture screenshots + mouse position"] }), _jsxs("li", { children: [_jsx("strong", { children: "Browser Context:" }), " Each log includes URL, user agent, screen resolution, etc."] }), _jsxs("li", { children: [_jsx("strong", { children: "Rimori Integration:" }), " Logs can be sent to Rimori for centralized logging"] })] }), _jsx("h4", { children: "\uD83C\uDFAF Screenshot & Mouse Position:" }), _jsxs("p", { children: ["When you call ", _jsx("code", { children: "console.warn()" }), " or ", _jsx("code", { children: "console.error()" }), ", the Logger automatically:"] }), _jsxs("ul", { children: [_jsx("li", { children: "Captures a screenshot of the current page (if html2canvas is available)" }), _jsx("li", { children: "Records the current mouse position (x, y coordinates)" }), _jsx("li", { children: "Includes timestamp for both screenshot and mouse position" })] })] }), _jsxs("div", { style: { marginTop: '20px', padding: '15px', backgroundColor: '#fff3e0', borderRadius: '5px' }, children: [_jsx("h4", { children: "\uD83D\uDD27 Setup Required:" }), _jsx("p", { children: "To enable screenshot capture, include html2canvas in your plugin:" }), _jsx("pre", { style: { backgroundColor: '#f5f5f5', padding: '10px', borderRadius: '3px' }, children: `<script src="https://html2canvas.hertzen.com/dist/html2canvas.min.js"></script>` })] })] }));
79
+ };
@@ -5,12 +5,12 @@ import { AudioInputField } from './EmbeddedAssistent/AudioInputField';
5
5
  import { MessageSender } from './EmbeddedAssistent/TTS/MessageSender';
6
6
  import Markdown from 'react-markdown';
7
7
  import { useChat } from '../../hooks/UseChatHook';
8
- import { usePlugin } from '../../components';
8
+ import { useRimori } from '../../components';
9
9
  import { getFirstMessages } from './utils';
10
10
  export function AssistantChat({ avatarImageUrl, voiceId, onComplete, autoStartConversation }) {
11
11
  var _a;
12
12
  const [oralCommunication, setOralCommunication] = React.useState(true);
13
- const { llm, event } = usePlugin();
13
+ const { ai: llm, event } = useRimori();
14
14
  const sender = useMemo(() => new MessageSender(llm.getVoice, voiceId), []);
15
15
  const { messages, append, isLoading, setMessages } = useChat();
16
16
  const lastAssistantMessage = (_a = [...messages].filter((m) => m.role === 'assistant').pop()) === null || _a === void 0 ? void 0 : _a.content;
@@ -37,15 +37,15 @@ export function AssistantChat({ avatarImageUrl, voiceId, onComplete, autoStartCo
37
37
  const lastMessage = messages[messages.length - 1];
38
38
  useEffect(() => {
39
39
  console.log("lastMessage", lastMessage);
40
- const toolInvocations = lastMessage === null || lastMessage === void 0 ? void 0 : lastMessage.toolInvocations;
40
+ const toolInvocations = lastMessage === null || lastMessage === void 0 ? void 0 : lastMessage.toolCalls;
41
41
  if (toolInvocations && toolInvocations.length > 0) {
42
42
  console.log("toolInvocations", toolInvocations);
43
43
  onComplete(toolInvocations[0].args);
44
44
  }
45
45
  }, [lastMessage]);
46
- if ((lastMessage === null || lastMessage === void 0 ? void 0 : lastMessage.toolInvocations) && lastMessage.toolInvocations.length > 0) {
46
+ if ((lastMessage === null || lastMessage === void 0 ? void 0 : lastMessage.toolCalls) && lastMessage.toolCalls.length > 0) {
47
47
  console.log("lastMessage test2", lastMessage);
48
- const args = lastMessage.toolInvocations[0].args;
48
+ const args = lastMessage.toolCalls[0].args;
49
49
  const success = args.explanationUnderstood === "TRUE" || args.studentKnowsTopic === "TRUE";
50
50
  return _jsxs("div", { className: "px-5 pt-5 overflow-y-auto text-center", style: { height: "478px" }, children: [_jsx("h1", { className: 'text-center mt-5 mb-5', children: success ? "Great job!" : "You failed" }), _jsx("p", { children: args.improvementHints })] });
51
51
  }
@@ -1,4 +1,4 @@
1
- import { Tool } from '../../controller/AIController';
1
+ import { Tool } from '../../fromRimori/PluginTypes';
2
2
  import { FirstMessages } from './utils';
3
3
  interface Props {
4
4
  voiceId: any;
@@ -8,6 +8,7 @@ interface Props {
8
8
  isDarkTheme?: boolean;
9
9
  children?: React.ReactNode;
10
10
  autoStartConversation?: FirstMessages;
11
+ className?: string;
11
12
  }
12
- export declare function Avatar({ avatarImageUrl, voiceId, agentTools, autoStartConversation, children, isDarkTheme, circleSize }: Props): import("react/jsx-runtime").JSX.Element;
13
+ export declare function Avatar({ avatarImageUrl, voiceId, agentTools, autoStartConversation, children, isDarkTheme, circleSize, className }: Props): import("react/jsx-runtime").JSX.Element;
13
14
  export {};
@@ -4,13 +4,13 @@ import { VoiceRecorder } from './EmbeddedAssistent/VoiceRecoder';
4
4
  import { MessageSender } from './EmbeddedAssistent/TTS/MessageSender';
5
5
  import { CircleAudioAvatar } from './EmbeddedAssistent/CircleAudioAvatar';
6
6
  import { useChat } from '../../hooks/UseChatHook';
7
- import { usePlugin } from '../../components';
7
+ import { useRimori } from '../../components';
8
8
  import { getFirstMessages } from './utils';
9
- export function Avatar({ avatarImageUrl, voiceId, agentTools, autoStartConversation, children, isDarkTheme = false, circleSize = "300px" }) {
10
- const { llm, event } = usePlugin();
9
+ export function Avatar({ avatarImageUrl, voiceId, agentTools, autoStartConversation, children, isDarkTheme = false, circleSize = "300px", className }) {
10
+ const { ai, event } = useRimori();
11
11
  const [agentReplying, setAgentReplying] = useState(false);
12
12
  const [isProcessingMessage, setIsProcessingMessage] = useState(false);
13
- const sender = useMemo(() => new MessageSender(llm.getVoice, voiceId), []);
13
+ const sender = useMemo(() => new MessageSender(ai.getVoice, voiceId), [voiceId]);
14
14
  const { messages, append, isLoading, lastMessage, setMessages } = useChat(agentTools);
15
15
  useEffect(() => {
16
16
  console.log("messages", messages);
@@ -33,13 +33,18 @@ export function Avatar({ avatarImageUrl, voiceId, agentTools, autoStartConversat
33
33
  else if (autoStartConversation.userMessage) {
34
34
  append([{ role: 'user', content: autoStartConversation.userMessage, id: messages.length.toString() }]);
35
35
  }
36
- }, []);
36
+ }, [autoStartConversation]);
37
37
  useEffect(() => {
38
38
  if ((lastMessage === null || lastMessage === void 0 ? void 0 : lastMessage.role) === 'assistant') {
39
39
  sender.handleNewText(lastMessage.content, isLoading);
40
+ if (lastMessage.toolCalls) {
41
+ console.log("unlocking mic", lastMessage);
42
+ setAgentReplying(false);
43
+ setIsProcessingMessage(false);
44
+ }
40
45
  }
41
46
  }, [lastMessage, isLoading]);
42
- return (_jsxs("div", { className: 'pb-8', children: [_jsx(CircleAudioAvatar, { width: circleSize, className: 'mx-auto', imageUrl: avatarImageUrl, isDarkTheme: isDarkTheme }), children, _jsx(VoiceRecorder, { iconSize: '300', disabled: agentReplying, loading: isProcessingMessage, onVoiceRecorded: (message) => {
47
+ return (_jsxs("div", { className: `md:pb-8 ${className || ''}`, children: [_jsx(CircleAudioAvatar, { width: circleSize, className: 'mx-auto', imageUrl: avatarImageUrl, isDarkTheme: isDarkTheme }), children, _jsx(VoiceRecorder, { iconSize: '30', className: 'w-16 h-16 shadow-lg rounded-full bg-gray-400 dark:bg-gray-800', disabled: agentReplying, loading: isProcessingMessage, enablePushToTalk: true, onVoiceRecorded: (message) => {
43
48
  setAgentReplying(true);
44
49
  append([{ role: 'user', content: "Message(" + Math.floor((messages.length + 1) / 2) + "): " + message, id: messages.length.toString() }]);
45
50
  }, onRecordingStatusChange: (running) => !running && setIsProcessingMessage(true) })] }));
@@ -1,6 +1,6 @@
1
1
  import { jsx as _jsx } from "react/jsx-runtime";
2
2
  import { useEffect, useRef } from 'react';
3
- import { EventBus } from '../../../plugin/fromRimori/EventBus';
3
+ import { EventBus } from '../../../fromRimori/EventBus';
4
4
  export function CircleAudioAvatar({ imageUrl, className, isDarkTheme = false, width = "150px" }) {
5
5
  const canvasRef = useRef(null);
6
6
  const currentLoudnessRef = useRef(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
  }
@@ -8,48 +8,61 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
8
8
  });
9
9
  };
10
10
  import { jsx as _jsx } from "react/jsx-runtime";
11
- import { useState, useRef, forwardRef, useImperativeHandle, useEffect } from 'react';
11
+ import { useRimori } from '../../../components';
12
12
  import { FaMicrophone, FaSpinner } from 'react-icons/fa6';
13
- import { usePlugin } from '../../../components';
14
- export const VoiceRecorder = forwardRef(({ onVoiceRecorded, iconSize, className, disabled, loading, onRecordingStatusChange }, ref) => {
13
+ import { AudioController } from '../../../plugin/AudioController';
14
+ import { useState, useRef, forwardRef, useImperativeHandle, useEffect } from 'react';
15
+ export const VoiceRecorder = forwardRef(({ onVoiceRecorded, iconSize, className, disabled, loading, onRecordingStatusChange, enablePushToTalk = false }, ref) => {
15
16
  const [isRecording, setIsRecording] = useState(false);
16
- const mediaRecorderRef = useRef(null);
17
- const audioChunksRef = useRef([]);
18
- const mediaStreamRef = useRef(null);
19
- const { llm } = usePlugin();
17
+ const [internalIsProcessing, setInternalIsProcessing] = useState(false);
18
+ const audioControllerRef = useRef(null);
19
+ const { ai, plugin } = useRimori();
20
20
  // Ref for latest onVoiceRecorded callback
21
21
  const onVoiceRecordedRef = useRef(onVoiceRecorded);
22
22
  useEffect(() => {
23
23
  onVoiceRecordedRef.current = onVoiceRecorded;
24
24
  }, [onVoiceRecorded]);
25
25
  const startRecording = () => __awaiter(void 0, void 0, void 0, function* () {
26
- const stream = yield navigator.mediaDevices.getUserMedia({ audio: true });
27
- mediaStreamRef.current = stream;
28
- const mediaRecorder = new MediaRecorder(stream);
29
- mediaRecorderRef.current = mediaRecorder;
30
- mediaRecorder.ondataavailable = (event) => {
31
- audioChunksRef.current.push(event.data);
32
- };
33
- mediaRecorder.onstop = () => __awaiter(void 0, void 0, void 0, function* () {
34
- const audioBlob = new Blob(audioChunksRef.current);
35
- audioChunksRef.current = [];
36
- onVoiceRecordedRef.current(yield llm.getTextFromVoice(audioBlob));
37
- });
38
- mediaRecorder.start();
39
- setIsRecording(true);
40
- onRecordingStatusChange(true);
26
+ try {
27
+ if (!audioControllerRef.current) {
28
+ audioControllerRef.current = new AudioController(plugin.pluginId);
29
+ }
30
+ yield audioControllerRef.current.startRecording();
31
+ setIsRecording(true);
32
+ onRecordingStatusChange(true);
33
+ }
34
+ catch (error) {
35
+ console.error('Failed to start recording:', error);
36
+ // Handle permission denied or other errors
37
+ }
41
38
  });
42
- const stopRecording = () => {
43
- if (mediaRecorderRef.current) {
44
- mediaRecorderRef.current.stop();
39
+ const stopRecording = () => __awaiter(void 0, void 0, void 0, function* () {
40
+ try {
41
+ if (audioControllerRef.current && isRecording) {
42
+ const audioResult = yield audioControllerRef.current.stopRecording();
43
+ // console.log("audioResult: ", audioResult);
44
+ setInternalIsProcessing(true);
45
+ // Play the recorded audio from the Blob
46
+ // const blobUrl = URL.createObjectURL(audioResult.recording);
47
+ // const audioRef = new Audio(blobUrl);
48
+ // audioRef.onended = () => URL.revokeObjectURL(blobUrl);
49
+ // audioRef.play().catch((e) => console.error('Playback error:', e));
50
+ // console.log("audioBlob: ", audioResult.recording);
51
+ const text = yield ai.getTextFromVoice(audioResult.recording);
52
+ // console.log("stt result", text);
53
+ // throw new Error("test");
54
+ setInternalIsProcessing(false);
55
+ onVoiceRecordedRef.current(text);
56
+ }
57
+ }
58
+ catch (error) {
59
+ console.error('Failed to stop recording:', error);
60
+ }
61
+ finally {
45
62
  setIsRecording(false);
46
63
  onRecordingStatusChange(false);
47
64
  }
48
- if (mediaStreamRef.current) {
49
- mediaStreamRef.current.getTracks().forEach(track => track.stop());
50
- mediaStreamRef.current = null;
51
- }
52
- };
65
+ });
53
66
  useImperativeHandle(ref, () => ({
54
67
  startRecording,
55
68
  stopRecording,
@@ -57,6 +70,8 @@ export const VoiceRecorder = forwardRef(({ onVoiceRecorded, iconSize, className,
57
70
  // push to talk feature
58
71
  const spacePressedRef = useRef(false);
59
72
  useEffect(() => {
73
+ if (!enablePushToTalk)
74
+ return;
60
75
  const handleKeyDown = (event) => __awaiter(void 0, void 0, void 0, function* () {
61
76
  if (event.code === 'Space' && !spacePressedRef.current) {
62
77
  spacePressedRef.current = true;
@@ -75,7 +90,7 @@ export const VoiceRecorder = forwardRef(({ onVoiceRecorded, iconSize, className,
75
90
  window.removeEventListener('keydown', handleKeyDown);
76
91
  window.removeEventListener('keyup', handleKeyUp);
77
92
  };
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" : "") }) }));
93
+ }, [enablePushToTalk]);
94
+ 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" }) :
95
+ _jsx(FaMicrophone, { size: iconSize, className: (isRecording ? "text-red-600" : "") }) }));
81
96
  });
@@ -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
  }
@@ -10,9 +10,9 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
10
10
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
11
11
  import { useState, useEffect } from 'react';
12
12
  import { FaPlayCircle, FaStopCircle } from "react-icons/fa";
13
- import { usePlugin } from "../../providers/PluginProvider";
13
+ import { useRimori } 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 } = useRimori();
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,23 +1,48 @@
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([]);
7
7
  const [position, setPosition] = useState({ x: 0, y: 0 });
8
8
  const [openOnTextSelect, setOpenOnTextSelect] = useState(false);
9
+ const [menuWidth, setMenuWidth] = useState(0);
9
10
  const menuRef = useRef(null);
11
+ const isMobile = window.innerWidth < 768;
12
+ /**
13
+ * Calculates position for mobile context menu based on selected text bounds.
14
+ * Centers the menu horizontally over the selected text and positions it 30px below the text's end.
15
+ * @param selectedText - The currently selected text
16
+ * @param menuWidth - The width of the menu to center properly
17
+ * @returns Position object with x and y coordinates
18
+ */
19
+ const calculateMobilePosition = (selectedText, menuWidth = 0) => {
20
+ const selection = window.getSelection();
21
+ if (!selection || !selectedText) {
22
+ return { x: 0, y: 0, text: selectedText };
23
+ }
24
+ const range = selection.getRangeAt(0);
25
+ const rect = range.getBoundingClientRect();
26
+ // Center horizontally over the selected text, accounting for menu width
27
+ const centerX = rect.left + (rect.width / 2) - (menuWidth / 2);
28
+ // Position 12px below where the text ends vertically
29
+ const textEndY = rect.bottom + 12;
30
+ return { x: centerX, y: textEndY, text: selectedText };
31
+ };
10
32
  useEffect(() => {
11
- client.plugin.getInstalled().then(plugins => {
12
- setActions(plugins.flatMap(p => p.context_menu_actions).filter(Boolean));
13
- });
14
- client.plugin.getUserInfo().then((userInfo) => {
15
- setOpenOnTextSelect(userInfo.context_menu_on_select);
16
- });
33
+ const actions = client.plugin.getPluginInfo().installedPlugins.flatMap(p => p.context_menu_actions).filter(Boolean);
34
+ setActions(actions);
35
+ setOpenOnTextSelect(client.plugin.getUserInfo().context_menu_on_select);
17
36
  EventBus.on("global.contextMenu.createActions", ({ data }) => {
18
37
  setActions([...data.actions, ...actions]);
19
38
  });
20
39
  }, []);
40
+ // Update menu width when menu is rendered
41
+ useEffect(() => {
42
+ if (isOpen && menuRef.current) {
43
+ setMenuWidth(menuRef.current.offsetWidth);
44
+ }
45
+ }, [isOpen, actions]);
21
46
  useEffect(() => {
22
47
  // Track mouse position globally
23
48
  const handleMouseMove = (e) => {
@@ -25,7 +50,12 @@ const ContextMenu = ({ client }) => {
25
50
  const selectedText = (_a = window.getSelection()) === null || _a === void 0 ? void 0 : _a.toString().trim();
26
51
  if (isOpen && selectedText === position.text)
27
52
  return;
28
- setPosition({ x: e.clientX, y: e.clientY, text: selectedText });
53
+ if (isMobile && selectedText) {
54
+ setPosition(calculateMobilePosition(selectedText, menuWidth));
55
+ }
56
+ else {
57
+ setPosition({ x: e.clientX, y: e.clientY, text: selectedText });
58
+ }
29
59
  };
30
60
  const handleMouseUp = (e) => {
31
61
  var _a, _b;
@@ -51,20 +81,29 @@ const ContextMenu = ({ client }) => {
51
81
  if (e.button === 2) {
52
82
  e.preventDefault();
53
83
  }
54
- setPosition({ x: e.clientX, y: e.clientY, text: selectedText });
84
+ if (isMobile) {
85
+ setPosition(calculateMobilePosition(selectedText, menuWidth));
86
+ }
87
+ else {
88
+ setPosition({ x: e.clientX, y: e.clientY, text: selectedText });
89
+ }
55
90
  setIsOpen(true);
56
91
  }
57
92
  else {
58
93
  setIsOpen(false);
59
94
  }
60
95
  };
61
- // Add selectionchange listener to close menu if selection is cleared
96
+ // Add selectionchange listener to close menu if selection is cleared and update position for mobile
62
97
  const handleSelectionChange = () => {
63
98
  var _a;
64
99
  const selectedText = (_a = window.getSelection()) === null || _a === void 0 ? void 0 : _a.toString().trim();
65
100
  if (!selectedText && isOpen) {
66
101
  setIsOpen(false);
67
102
  }
103
+ else if (selectedText && isOpen && isMobile) {
104
+ // Update position in real-time as text selection changes on mobile
105
+ setPosition(calculateMobilePosition(selectedText, menuWidth));
106
+ }
68
107
  };
69
108
  document.addEventListener("mouseup", handleMouseUp);
70
109
  window.addEventListener("mousemove", handleMouseMove);
@@ -84,7 +123,7 @@ const ContextMenu = ({ client }) => {
84
123
  var _a;
85
124
  setIsOpen(false);
86
125
  (_a = window.getSelection()) === null || _a === void 0 ? void 0 : _a.removeAllRanges();
87
- client.event.emitSidebarAction(action.pluginId, action.actionKey, position.text);
126
+ client.event.emitSidebarAction(action.plugin_id, action.action_key, position.text);
88
127
  } }, index))) }));
89
128
  };
90
129
  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>;