@rimori/client 1.4.0 → 1.4.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +77 -71
- package/dist/cli/scripts/init/dev-registration.d.ts +1 -1
- package/dist/cli/scripts/init/dev-registration.js +4 -4
- package/dist/cli/scripts/init/main.js +1 -1
- package/dist/cli/scripts/init/package-setup.d.ts +1 -1
- package/dist/cli/scripts/init/package-setup.js +3 -3
- package/dist/cli/scripts/init/router-transformer.js +19 -12
- package/dist/cli/scripts/init/vite-config.d.ts +2 -2
- package/dist/cli/scripts/init/vite-config.js +2 -2
- package/dist/cli/scripts/release/release-config-upload.js +9 -9
- package/dist/cli/scripts/release/release-db-update.d.ts +1 -1
- package/dist/cli/scripts/release/release-db-update.js +9 -9
- package/dist/cli/scripts/release/release-file-upload.js +1 -1
- package/dist/cli/scripts/release/release.js +2 -2
- package/dist/components/CRUDModal.d.ts +1 -1
- package/dist/components/CRUDModal.js +3 -3
- package/dist/components/MarkdownEditor.js +16 -16
- package/dist/components/Spinner.js +2 -2
- package/dist/components/ai/Assistant.js +7 -8
- package/dist/components/ai/Avatar.d.ts +2 -2
- package/dist/components/ai/Avatar.js +10 -5
- package/dist/components/ai/EmbeddedAssistent/AudioInputField.js +5 -6
- package/dist/components/ai/EmbeddedAssistent/CircleAudioAvatar.d.ts +1 -1
- package/dist/components/ai/EmbeddedAssistent/CircleAudioAvatar.js +1 -2
- package/dist/components/ai/EmbeddedAssistent/TTS/MessageSender.d.ts +1 -2
- package/dist/components/ai/EmbeddedAssistent/TTS/MessageSender.js +4 -2
- package/dist/components/ai/EmbeddedAssistent/VoiceRecoder.js +2 -3
- package/dist/components/audio/Playbutton.js +10 -7
- package/dist/components/components/ContextMenu.d.ts +1 -1
- package/dist/components/components/ContextMenu.js +19 -16
- package/dist/components.d.ts +10 -10
- package/dist/components.js +10 -10
- package/dist/core/controller/AIController.d.ts +2 -2
- package/dist/core/controller/AIController.js +12 -12
- package/dist/core/controller/ExerciseController.d.ts +2 -2
- package/dist/core/controller/ExerciseController.js +2 -2
- package/dist/core/controller/ObjectController.js +5 -5
- package/dist/core/controller/SettingsController.d.ts +22 -7
- package/dist/core/controller/SettingsController.js +73 -8
- package/dist/core/controller/SharedContentController.d.ts +3 -3
- package/dist/core/controller/SharedContentController.js +38 -20
- package/dist/core/controller/VoiceController.js +6 -4
- package/dist/core/core.d.ts +15 -15
- package/dist/core/core.js +7 -7
- package/dist/fromRimori/EventBus.js +23 -23
- package/dist/fromRimori/PluginTypes.d.ts +4 -4
- package/dist/hooks/UseChatHook.d.ts +3 -3
- package/dist/hooks/UseChatHook.js +9 -3
- package/dist/index.d.ts +10 -10
- package/dist/index.js +9 -9
- package/dist/plugin/AccomplishmentHandler.d.ts +5 -5
- package/dist/plugin/AccomplishmentHandler.js +31 -27
- package/dist/plugin/AudioController.d.ts +1 -1
- package/dist/plugin/AudioController.js +6 -6
- package/dist/plugin/Logger.js +15 -13
- package/dist/plugin/PluginController.d.ts +7 -1
- package/dist/plugin/PluginController.js +32 -27
- package/dist/plugin/RimoriClient.d.ts +17 -18
- package/dist/plugin/RimoriClient.js +31 -31
- package/dist/plugin/StandaloneClient.d.ts +1 -1
- package/dist/plugin/StandaloneClient.js +35 -16
- package/dist/plugin/ThemeSetter.js +4 -4
- package/dist/providers/PluginProvider.js +44 -14
- package/dist/utils/Language.js +57 -57
- package/dist/utils/PluginUtils.js +3 -3
- package/dist/utils/difficultyConverter.d.ts +1 -1
- package/dist/utils/difficultyConverter.js +1 -1
- package/dist/utils/endpoint.js +2 -2
- package/dist/worker/WorkerSetup.d.ts +1 -1
- package/dist/worker/WorkerSetup.js +6 -6
- package/example/docs/devdocs.md +50 -40
- package/example/docs/overview.md +1 -1
- package/example/docs/userdocs.md +4 -1
- package/example/rimori.config.ts +51 -49
- package/example/worker/vite.config.ts +3 -3
- package/example/worker/worker.ts +2 -2
- package/package.json +14 -8
- package/prettier.config.js +1 -1
- package/src/cli/scripts/init/dev-registration.ts +5 -8
- package/src/cli/scripts/init/env-setup.ts +1 -1
- package/src/cli/scripts/init/file-operations.ts +1 -1
- package/src/cli/scripts/init/html-cleaner.ts +2 -5
- package/src/cli/scripts/init/main.ts +16 -13
- package/src/cli/scripts/init/package-setup.ts +11 -15
- package/src/cli/scripts/init/router-transformer.ts +40 -37
- package/src/cli/scripts/init/tailwind-config.ts +17 -26
- package/src/cli/scripts/init/vite-config.ts +3 -3
- package/src/cli/scripts/release/release-config-upload.ts +11 -11
- package/src/cli/scripts/release/release-db-update.ts +12 -12
- package/src/cli/scripts/release/release-file-upload.ts +2 -2
- package/src/cli/scripts/release/release.ts +4 -4
- package/src/cli/types/DatabaseTypes.ts +2 -10
- package/src/components/CRUDModal.tsx +64 -48
- package/src/components/MarkdownEditor.tsx +58 -27
- package/src/components/Spinner.tsx +24 -17
- package/src/components/ai/Assistant.tsx +70 -70
- package/src/components/ai/Avatar.tsx +17 -14
- package/src/components/ai/EmbeddedAssistent/AudioInputField.tsx +63 -54
- package/src/components/ai/EmbeddedAssistent/CircleAudioAvatar.tsx +14 -5
- package/src/components/ai/EmbeddedAssistent/TTS/MessageSender.ts +75 -74
- package/src/components/ai/EmbeddedAssistent/TTS/Player.ts +3 -4
- package/src/components/ai/EmbeddedAssistent/VoiceRecoder.tsx +109 -94
- package/src/components/ai/utils.ts +4 -4
- package/src/components/audio/Playbutton.tsx +101 -93
- package/src/components/components/ContextMenu.tsx +47 -35
- package/src/components.ts +10 -10
- package/src/core/controller/AIController.ts +29 -19
- package/src/core/controller/ExerciseController.ts +16 -23
- package/src/core/controller/ObjectController.ts +15 -10
- package/src/core/controller/SettingsController.ts +89 -16
- package/src/core/controller/SharedContentController.ts +80 -44
- package/src/core/controller/VoiceController.ts +10 -8
- package/src/core/core.ts +15 -16
- package/src/fromRimori/EventBus.ts +76 -47
- package/src/fromRimori/PluginTypes.ts +26 -17
- package/src/fromRimori/readme.md +2 -2
- package/src/hooks/UseChatHook.ts +25 -15
- package/src/index.ts +10 -10
- package/src/plugin/AccomplishmentHandler.ts +53 -35
- package/src/plugin/AudioController.ts +18 -12
- package/src/plugin/Logger.ts +28 -21
- package/src/plugin/PluginController.ts +60 -44
- package/src/plugin/RimoriClient.ts +102 -72
- package/src/plugin/StandaloneClient.ts +51 -24
- package/src/plugin/ThemeSetter.ts +5 -5
- package/src/providers/PluginProvider.tsx +90 -36
- package/src/style.scss +3 -3
- package/src/utils/Language.ts +58 -58
- package/src/utils/PluginUtils.ts +16 -20
- package/src/utils/difficultyConverter.ts +2 -2
- package/src/utils/endpoint.ts +3 -2
- package/src/worker/WorkerSetup.ts +8 -9
- package/tsconfig.json +2 -4
|
@@ -1,6 +1,7 @@
|
|
|
1
|
-
import { SupabaseClient } from
|
|
2
|
-
import { LanguageLevel } from
|
|
3
|
-
import { Language } from
|
|
1
|
+
import { SupabaseClient } from '@supabase/supabase-js';
|
|
2
|
+
import { LanguageLevel } from '../../utils/difficultyConverter';
|
|
3
|
+
import { Language } from '../../utils/Language';
|
|
4
|
+
import { Guild } from '../core';
|
|
4
5
|
|
|
5
6
|
export interface Buddy {
|
|
6
7
|
id: string;
|
|
@@ -37,45 +38,117 @@ export interface UserInfo {
|
|
|
37
38
|
context_menu_on_select: boolean;
|
|
38
39
|
user_name?: string;
|
|
39
40
|
/**
|
|
40
|
-
* ISO 3166-1 alpha-2 country code of user's location (exposed to plugins)
|
|
41
|
+
* ISO 3166-1 alpha-2 country code of user's target location (exposed to plugins)
|
|
41
42
|
*/
|
|
42
|
-
|
|
43
|
+
target_country: string;
|
|
43
44
|
/**
|
|
44
45
|
* Optional: nearest big city (>100,000) near user's location
|
|
45
46
|
*/
|
|
46
|
-
|
|
47
|
+
target_city?: string;
|
|
47
48
|
}
|
|
48
49
|
|
|
49
50
|
export class SettingsController {
|
|
50
51
|
private pluginId: string;
|
|
51
52
|
private supabase: SupabaseClient;
|
|
53
|
+
private guild: Guild;
|
|
52
54
|
|
|
53
|
-
constructor(supabase: SupabaseClient, pluginId: string) {
|
|
55
|
+
constructor(supabase: SupabaseClient, pluginId: string, guild: Guild) {
|
|
54
56
|
this.supabase = supabase;
|
|
55
57
|
this.pluginId = pluginId;
|
|
58
|
+
this.guild = guild;
|
|
56
59
|
}
|
|
57
60
|
|
|
61
|
+
/**
|
|
62
|
+
* Fetches settings based on guild configuration.
|
|
63
|
+
* If guild doesn't allow user settings, fetches guild-level settings.
|
|
64
|
+
* Otherwise, fetches user-specific settings.
|
|
65
|
+
* @returns The settings object or null if not found.
|
|
66
|
+
*/
|
|
58
67
|
private async fetchSettings(): Promise<any | null> {
|
|
59
|
-
const
|
|
68
|
+
const isGuildSetting = !this.guild.allowUserPluginSettings;
|
|
60
69
|
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
70
|
+
const { data } = await this.supabase
|
|
71
|
+
.from('plugin_settings')
|
|
72
|
+
.select('*')
|
|
73
|
+
.eq('plugin_id', this.pluginId)
|
|
74
|
+
.eq('guild_id', this.guild.id)
|
|
75
|
+
.eq('is_guild_setting', isGuildSetting)
|
|
76
|
+
.maybeSingle();
|
|
64
77
|
|
|
65
|
-
return data
|
|
78
|
+
return data?.settings ?? null;
|
|
66
79
|
}
|
|
67
80
|
|
|
81
|
+
/**
|
|
82
|
+
* Sets settings for the plugin.
|
|
83
|
+
* Automatically saves as guild settings if guild doesn't allow user settings,
|
|
84
|
+
* otherwise saves as user-specific settings.
|
|
85
|
+
* @param settings - The settings object to save.
|
|
86
|
+
* @throws {Error} if RLS blocks the operation.
|
|
87
|
+
*/
|
|
68
88
|
public async setSettings(settings: any): Promise<void> {
|
|
69
|
-
|
|
89
|
+
const isGuildSetting = !this.guild.allowUserPluginSettings;
|
|
90
|
+
|
|
91
|
+
const payload: any = {
|
|
92
|
+
plugin_id: this.pluginId,
|
|
93
|
+
settings,
|
|
94
|
+
guild_id: this.guild.id,
|
|
95
|
+
is_guild_setting: isGuildSetting,
|
|
96
|
+
};
|
|
97
|
+
|
|
98
|
+
if (isGuildSetting) {
|
|
99
|
+
payload.user_id = null;
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
// Try UPDATE first (safe with RLS). If nothing updated, INSERT.
|
|
103
|
+
const updateQuery = this.supabase
|
|
104
|
+
.from('plugin_settings')
|
|
105
|
+
.update({ settings })
|
|
106
|
+
.eq('plugin_id', this.pluginId)
|
|
107
|
+
.eq('guild_id', this.guild.id)
|
|
108
|
+
.eq('is_guild_setting', isGuildSetting);
|
|
109
|
+
|
|
110
|
+
const { data: updatedRows, error: updateError } = await (isGuildSetting
|
|
111
|
+
? updateQuery.is('user_id', null).select('id')
|
|
112
|
+
: updateQuery.select('id'));
|
|
113
|
+
|
|
114
|
+
if (updateError) {
|
|
115
|
+
if (updateError.code === '42501' || updateError.message?.includes('policy')) {
|
|
116
|
+
throw new Error(`Cannot set ${isGuildSetting ? 'guild' : 'user'} settings: Permission denied.`);
|
|
117
|
+
}
|
|
118
|
+
// proceed to try insert in case of other issues
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
if (updatedRows && updatedRows.length > 0) {
|
|
122
|
+
return; // updated successfully
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
// No row updated -> INSERT
|
|
126
|
+
const { error: insertError } = await this.supabase.from('plugin_settings').insert(payload);
|
|
127
|
+
|
|
128
|
+
if (insertError) {
|
|
129
|
+
// In case of race condition (duplicate), try one more UPDATE
|
|
130
|
+
if (insertError.code === '23505' /* unique_violation */) {
|
|
131
|
+
const retry = this.supabase
|
|
132
|
+
.from('plugin_settings')
|
|
133
|
+
.update({ settings })
|
|
134
|
+
.eq('plugin_id', this.pluginId)
|
|
135
|
+
.eq('guild_id', this.guild.id)
|
|
136
|
+
.eq('is_guild_setting', isGuildSetting);
|
|
137
|
+
const { error: retryError } = await (isGuildSetting ? retry.is('user_id', null) : retry);
|
|
138
|
+
if (!retryError) return;
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
throw insertError;
|
|
142
|
+
}
|
|
70
143
|
}
|
|
71
144
|
|
|
72
145
|
/**
|
|
73
146
|
* Get the settings for the plugin. T can be any type of settings, UserSettings or SystemSettings.
|
|
74
147
|
* @param defaultSettings The default settings to use if no settings are found.
|
|
75
|
-
* @returns The settings for the plugin.
|
|
148
|
+
* @returns The settings for the plugin.
|
|
76
149
|
*/
|
|
77
150
|
public async getSettings<T extends object>(defaultSettings: T): Promise<T> {
|
|
78
|
-
const storedSettings = await this.fetchSettings() as T | null;
|
|
151
|
+
const storedSettings = (await this.fetchSettings()) as T | null;
|
|
79
152
|
|
|
80
153
|
if (!storedSettings) {
|
|
81
154
|
await this.setSettings(defaultSettings);
|
|
@@ -88,7 +161,7 @@ export class SettingsController {
|
|
|
88
161
|
|
|
89
162
|
if (storedKeys.length !== defaultKeys.length) {
|
|
90
163
|
const validStoredSettings = Object.fromEntries(
|
|
91
|
-
Object.entries(storedSettings).filter(([key]) => defaultKeys.includes(key))
|
|
164
|
+
Object.entries(storedSettings).filter(([key]) => defaultKeys.includes(key)),
|
|
92
165
|
);
|
|
93
166
|
const mergedSettings = { ...defaultSettings, ...validStoredSettings } as T;
|
|
94
167
|
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
import { SupabaseClient } from '@supabase/supabase-js';
|
|
2
|
-
import { RimoriClient } from
|
|
3
|
-
import { ObjectRequest } from
|
|
2
|
+
import { RimoriClient } from '../../plugin/RimoriClient';
|
|
3
|
+
import { ObjectRequest } from './ObjectController';
|
|
4
4
|
|
|
5
5
|
export interface SharedContentObjectRequest extends ObjectRequest {
|
|
6
|
-
fixedProperties?: Record<string, string | number | boolean
|
|
6
|
+
fixedProperties?: Record<string, string | number | boolean>;
|
|
7
7
|
}
|
|
8
8
|
|
|
9
|
-
export type SharedContentFilter = Record<string, string | number | boolean
|
|
9
|
+
export type SharedContentFilter = Record<string, string | number | boolean>;
|
|
10
10
|
|
|
11
11
|
export class SharedContentController {
|
|
12
12
|
private supabase: SupabaseClient;
|
|
@@ -34,10 +34,11 @@ export class SharedContentController {
|
|
|
34
34
|
generatorInstructions: SharedContentObjectRequest,
|
|
35
35
|
//this filter is there if the content should be filtered additionally by a column and value
|
|
36
36
|
filter?: SharedContentFilter,
|
|
37
|
-
options?: { privateTopic?: boolean
|
|
37
|
+
options?: { privateTopic?: boolean; skipDbSave?: boolean; alwaysGenerateNew?: boolean; excludeIds?: string[] },
|
|
38
38
|
): Promise<SharedContent<T>> {
|
|
39
|
-
let query = this.supabase
|
|
40
|
-
.
|
|
39
|
+
let query = this.supabase
|
|
40
|
+
.from('shared_content')
|
|
41
|
+
.select('*, scc:shared_content_completed(id, state)')
|
|
41
42
|
.eq('content_type', contentType)
|
|
42
43
|
.not('scc.state', 'in', '("completed","ongoing","hidden")')
|
|
43
44
|
.is('deleted_at', null);
|
|
@@ -62,7 +63,7 @@ export class SharedContentController {
|
|
|
62
63
|
|
|
63
64
|
// console.log('newAssignments:', newAssignments);
|
|
64
65
|
|
|
65
|
-
if (!
|
|
66
|
+
if (!options?.alwaysGenerateNew && newAssignments.length > 0) {
|
|
66
67
|
const index = Math.floor(Math.random() * newAssignments.length);
|
|
67
68
|
return newAssignments[index];
|
|
68
69
|
}
|
|
@@ -73,13 +74,13 @@ export class SharedContentController {
|
|
|
73
74
|
|
|
74
75
|
//create the shared content object
|
|
75
76
|
const data: SharedContent<T> = {
|
|
76
|
-
id:
|
|
77
|
+
id: 'internal-temp-id-' + Math.random().toString(36).substring(2, 15),
|
|
77
78
|
contentType,
|
|
78
79
|
title: instructions.title,
|
|
79
80
|
keywords: instructions.keywords.map(({ text }: { text: string }) => text),
|
|
80
81
|
data: { ...instructions, title: undefined, keywords: undefined, ...generatorInstructions.fixedProperties },
|
|
81
82
|
privateTopic: options?.privateTopic,
|
|
82
|
-
}
|
|
83
|
+
};
|
|
83
84
|
|
|
84
85
|
if (options?.skipDbSave) {
|
|
85
86
|
return data;
|
|
@@ -88,7 +89,11 @@ export class SharedContentController {
|
|
|
88
89
|
return await this.createSharedContent(data);
|
|
89
90
|
}
|
|
90
91
|
|
|
91
|
-
private async generateNewAssignment(
|
|
92
|
+
private async generateNewAssignment(
|
|
93
|
+
contentType: string,
|
|
94
|
+
generatorInstructions: SharedContentObjectRequest,
|
|
95
|
+
filter?: SharedContentFilter,
|
|
96
|
+
): Promise<any> {
|
|
92
97
|
const fullInstructions = await this.getGeneratorInstructions(contentType, generatorInstructions, filter);
|
|
93
98
|
|
|
94
99
|
console.log('fullInstructions:', fullInstructions);
|
|
@@ -96,29 +101,34 @@ export class SharedContentController {
|
|
|
96
101
|
return await this.rimoriClient.ai.getObject(fullInstructions);
|
|
97
102
|
}
|
|
98
103
|
|
|
99
|
-
private async getGeneratorInstructions(
|
|
104
|
+
private async getGeneratorInstructions(
|
|
105
|
+
contentType: string,
|
|
106
|
+
generatorInstructions: ObjectRequest,
|
|
107
|
+
filter?: SharedContentFilter,
|
|
108
|
+
): Promise<ObjectRequest> {
|
|
100
109
|
const completedTopics = await this.getCompletedTopics(contentType, filter);
|
|
101
110
|
|
|
102
111
|
generatorInstructions.instructions += `
|
|
103
112
|
The following topics are already taken: ${completedTopics.join(', ')}`;
|
|
104
113
|
|
|
105
114
|
generatorInstructions.tool.title = {
|
|
106
|
-
type:
|
|
107
|
-
description:
|
|
108
|
-
}
|
|
115
|
+
type: 'string',
|
|
116
|
+
description: 'What the topic is about. Short. ',
|
|
117
|
+
};
|
|
109
118
|
generatorInstructions.tool.keywords = {
|
|
110
|
-
type: [{ text: { type:
|
|
111
|
-
description:
|
|
112
|
-
}
|
|
119
|
+
type: [{ text: { type: 'string' } }],
|
|
120
|
+
description: 'Keywords around the topic of the assignment.',
|
|
121
|
+
};
|
|
113
122
|
return generatorInstructions;
|
|
114
123
|
}
|
|
115
124
|
|
|
116
125
|
private async getCompletedTopics(contentType: string, filter?: SharedContentFilter): Promise<string[]> {
|
|
117
|
-
const query = this.supabase
|
|
118
|
-
.
|
|
126
|
+
const query = this.supabase
|
|
127
|
+
.from('shared_content')
|
|
128
|
+
.select('title, keywords, scc:shared_content_completed(id)')
|
|
119
129
|
.eq('content_type', contentType)
|
|
120
130
|
.not('scc.id', 'is', null)
|
|
121
|
-
.is('deleted_at', null)
|
|
131
|
+
.is('deleted_at', null);
|
|
122
132
|
|
|
123
133
|
if (filter) {
|
|
124
134
|
query.contains('data', filter);
|
|
@@ -134,7 +144,13 @@ export class SharedContentController {
|
|
|
134
144
|
}
|
|
135
145
|
|
|
136
146
|
public async getSharedContent<T>(contentType: string, id: string): Promise<SharedContent<T>> {
|
|
137
|
-
const { data, error } = await this.supabase
|
|
147
|
+
const { data, error } = await this.supabase
|
|
148
|
+
.from('shared_content')
|
|
149
|
+
.select()
|
|
150
|
+
.eq('content_type', contentType)
|
|
151
|
+
.eq('id', id)
|
|
152
|
+
.is('deleted_at', null)
|
|
153
|
+
.single();
|
|
138
154
|
if (error) {
|
|
139
155
|
console.error('error fetching shared content:', error);
|
|
140
156
|
throw new Error('error fetching shared content');
|
|
@@ -145,7 +161,7 @@ export class SharedContentController {
|
|
|
145
161
|
public async completeSharedContent(contentType: string, assignmentId: string) {
|
|
146
162
|
// Idempotent completion: upsert on (id, user_id) so repeated calls don't fail
|
|
147
163
|
const { error } = await this.supabase
|
|
148
|
-
.from(
|
|
164
|
+
.from('shared_content_completed')
|
|
149
165
|
.upsert({ content_type: contentType, id: assignmentId } as any, { onConflict: 'id' });
|
|
150
166
|
|
|
151
167
|
if (error) {
|
|
@@ -172,11 +188,11 @@ export class SharedContentController {
|
|
|
172
188
|
reaction,
|
|
173
189
|
bookmarked,
|
|
174
190
|
}: {
|
|
175
|
-
contentType: string
|
|
176
|
-
id: string
|
|
177
|
-
state?: 'completed' | 'ongoing' | 'hidden'
|
|
178
|
-
reaction?: 'liked' | 'disliked' | null
|
|
179
|
-
bookmarked?: boolean
|
|
191
|
+
contentType: string;
|
|
192
|
+
id: string;
|
|
193
|
+
state?: 'completed' | 'ongoing' | 'hidden';
|
|
194
|
+
reaction?: 'liked' | 'disliked' | null;
|
|
195
|
+
bookmarked?: boolean;
|
|
180
196
|
}): Promise<void> {
|
|
181
197
|
const payload: Record<string, unknown> = { content_type: contentType, id };
|
|
182
198
|
if (state !== undefined) payload.state = state;
|
|
@@ -184,9 +200,7 @@ export class SharedContentController {
|
|
|
184
200
|
if (bookmarked !== undefined) payload.bookmarked = bookmarked;
|
|
185
201
|
|
|
186
202
|
// Prefer upsert, fall back to insert/update if upsert not allowed
|
|
187
|
-
const { error } = await this.supabase
|
|
188
|
-
.from('shared_content_completed')
|
|
189
|
-
.upsert(payload as any, { onConflict: 'id' });
|
|
203
|
+
const { error } = await this.supabase.from('shared_content_completed').upsert(payload as any, { onConflict: 'id' });
|
|
190
204
|
|
|
191
205
|
if (error) {
|
|
192
206
|
console.error('error updating shared content state:', error);
|
|
@@ -201,8 +215,17 @@ export class SharedContentController {
|
|
|
201
215
|
* @param limit - Optional limit for the number of results.
|
|
202
216
|
* @returns Array of shared content matching the criteria.
|
|
203
217
|
*/
|
|
204
|
-
public async getSharedContentList<T>(
|
|
205
|
-
|
|
218
|
+
public async getSharedContentList<T>(
|
|
219
|
+
contentType: string,
|
|
220
|
+
filter?: SharedContentFilter,
|
|
221
|
+
limit?: number,
|
|
222
|
+
): Promise<SharedContent<T>[]> {
|
|
223
|
+
const query = this.supabase
|
|
224
|
+
.from('shared_content')
|
|
225
|
+
.select('*')
|
|
226
|
+
.eq('content_type', contentType)
|
|
227
|
+
.is('deleted_at', null)
|
|
228
|
+
.limit(limit ?? 30);
|
|
206
229
|
|
|
207
230
|
if (filter) {
|
|
208
231
|
query.contains('data', filter);
|
|
@@ -229,14 +252,23 @@ export class SharedContentController {
|
|
|
229
252
|
* @returns The inserted shared content.
|
|
230
253
|
* @throws {Error} if insertion fails.
|
|
231
254
|
*/
|
|
232
|
-
public async createSharedContent<T>({
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
}
|
|
255
|
+
public async createSharedContent<T>({
|
|
256
|
+
contentType,
|
|
257
|
+
title,
|
|
258
|
+
keywords,
|
|
259
|
+
data,
|
|
260
|
+
privateTopic,
|
|
261
|
+
}: Omit<SharedContent<T>, 'id'>): Promise<SharedContent<T>> {
|
|
262
|
+
const { data: newContent, error } = await this.supabase
|
|
263
|
+
.from('shared_content')
|
|
264
|
+
.insert({
|
|
265
|
+
private: privateTopic,
|
|
266
|
+
content_type: contentType,
|
|
267
|
+
title,
|
|
268
|
+
keywords,
|
|
269
|
+
data,
|
|
270
|
+
})
|
|
271
|
+
.select();
|
|
240
272
|
|
|
241
273
|
if (error) {
|
|
242
274
|
console.error('error inserting shared content:', error);
|
|
@@ -262,7 +294,11 @@ export class SharedContentController {
|
|
|
262
294
|
if (updates.data) updateData.data = updates.data;
|
|
263
295
|
if (updates.privateTopic !== undefined) updateData.private = updates.privateTopic;
|
|
264
296
|
|
|
265
|
-
const { data: updatedContent, error } = await this.supabase
|
|
297
|
+
const { data: updatedContent, error } = await this.supabase
|
|
298
|
+
.from('shared_content')
|
|
299
|
+
.update(updateData)
|
|
300
|
+
.eq('id', id)
|
|
301
|
+
.select();
|
|
266
302
|
|
|
267
303
|
if (error) {
|
|
268
304
|
console.error('error updating shared content:', error);
|
|
@@ -284,7 +320,7 @@ export class SharedContentController {
|
|
|
284
320
|
*/
|
|
285
321
|
public async removeSharedContent(id: string): Promise<SharedContent<any>> {
|
|
286
322
|
const { data: deletedContent, error } = await this.supabase
|
|
287
|
-
.from(
|
|
323
|
+
.from('shared_content')
|
|
288
324
|
.update({ deleted_at: new Date().toISOString() })
|
|
289
325
|
.eq('id', id)
|
|
290
326
|
.select();
|
|
@@ -324,4 +360,4 @@ export interface SharedContent<T> {
|
|
|
324
360
|
|
|
325
361
|
/** Whether this content should only be visible to the creator. Defaults to false if not specified */
|
|
326
362
|
privateTopic?: boolean;
|
|
327
|
-
}
|
|
363
|
+
}
|
|
@@ -4,12 +4,14 @@ export async function getSTTResponse(backendUrl: string, audio: Blob, token: str
|
|
|
4
4
|
|
|
5
5
|
return await fetch(`${backendUrl}/voice/stt`, {
|
|
6
6
|
method: 'POST',
|
|
7
|
-
headers: {
|
|
7
|
+
headers: { Authorization: `Bearer ${token}` },
|
|
8
8
|
body: formData,
|
|
9
|
-
})
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
9
|
+
})
|
|
10
|
+
.then((r) => r.json())
|
|
11
|
+
.then((r) => {
|
|
12
|
+
// console.log("STT response: ", r);
|
|
13
|
+
return r.text;
|
|
14
|
+
});
|
|
13
15
|
}
|
|
14
16
|
|
|
15
17
|
export async function getTTSResponse(backendUrl: string, request: TTSRequest, token: string) {
|
|
@@ -17,10 +19,10 @@ export async function getTTSResponse(backendUrl: string, request: TTSRequest, to
|
|
|
17
19
|
method: 'POST',
|
|
18
20
|
headers: {
|
|
19
21
|
'Content-Type': 'application/json',
|
|
20
|
-
|
|
22
|
+
Authorization: `Bearer ${token}`,
|
|
21
23
|
},
|
|
22
24
|
body: JSON.stringify(request),
|
|
23
|
-
}).then(r => r.blob());
|
|
25
|
+
}).then((r) => r.blob());
|
|
24
26
|
}
|
|
25
27
|
|
|
26
28
|
interface TTSRequest {
|
|
@@ -28,4 +30,4 @@ interface TTSRequest {
|
|
|
28
30
|
voice: string;
|
|
29
31
|
speed: number;
|
|
30
32
|
language?: string;
|
|
31
|
-
}
|
|
33
|
+
}
|
package/src/core/core.ts
CHANGED
|
@@ -1,17 +1,16 @@
|
|
|
1
1
|
// Core functionality exports
|
|
2
|
-
export * from
|
|
3
|
-
export * from
|
|
4
|
-
export * from
|
|
5
|
-
export * from
|
|
6
|
-
export * from
|
|
7
|
-
export * from
|
|
8
|
-
export * from
|
|
9
|
-
export { EventBusMessage } from
|
|
10
|
-
export { Buddy, UserInfo } from
|
|
11
|
-
export { SharedContent } from
|
|
12
|
-
export { Exercise, TriggerAction } from
|
|
13
|
-
export { Message, OnLLMResponse, ToolInvocation } from
|
|
14
|
-
export { MacroAccomplishmentPayload, MicroAccomplishmentPayload } from
|
|
15
|
-
export { Tool } from
|
|
16
|
-
export { SharedContentObjectRequest } from
|
|
17
|
-
|
|
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';
|
|
9
|
+
export { EventBusMessage } from '../fromRimori/EventBus';
|
|
10
|
+
export { Buddy, UserInfo } from './controller/SettingsController';
|
|
11
|
+
export { SharedContent } from './controller/SharedContentController';
|
|
12
|
+
export { Exercise, TriggerAction } from './controller/ExerciseController';
|
|
13
|
+
export { Message, OnLLMResponse, ToolInvocation } from './controller/AIController';
|
|
14
|
+
export { MacroAccomplishmentPayload, MicroAccomplishmentPayload } from '../plugin/AccomplishmentHandler';
|
|
15
|
+
export { Tool } from '../fromRimori/PluginTypes';
|
|
16
|
+
export { SharedContentObjectRequest } from './controller/SharedContentController';
|