@rimori/client 1.4.0 → 1.4.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (133) hide show
  1. package/README.md +77 -71
  2. package/dist/cli/scripts/init/dev-registration.d.ts +1 -1
  3. package/dist/cli/scripts/init/dev-registration.js +4 -4
  4. package/dist/cli/scripts/init/main.js +1 -1
  5. package/dist/cli/scripts/init/package-setup.d.ts +1 -1
  6. package/dist/cli/scripts/init/package-setup.js +3 -3
  7. package/dist/cli/scripts/init/router-transformer.js +19 -12
  8. package/dist/cli/scripts/init/vite-config.d.ts +2 -2
  9. package/dist/cli/scripts/init/vite-config.js +2 -2
  10. package/dist/cli/scripts/release/release-config-upload.js +9 -9
  11. package/dist/cli/scripts/release/release-db-update.d.ts +1 -1
  12. package/dist/cli/scripts/release/release-db-update.js +9 -9
  13. package/dist/cli/scripts/release/release-file-upload.js +1 -1
  14. package/dist/cli/scripts/release/release.js +2 -2
  15. package/dist/components/CRUDModal.d.ts +1 -1
  16. package/dist/components/CRUDModal.js +3 -3
  17. package/dist/components/MarkdownEditor.js +16 -16
  18. package/dist/components/Spinner.js +2 -2
  19. package/dist/components/ai/Assistant.js +7 -8
  20. package/dist/components/ai/Avatar.d.ts +2 -2
  21. package/dist/components/ai/Avatar.js +10 -5
  22. package/dist/components/ai/EmbeddedAssistent/AudioInputField.js +5 -6
  23. package/dist/components/ai/EmbeddedAssistent/CircleAudioAvatar.d.ts +1 -1
  24. package/dist/components/ai/EmbeddedAssistent/CircleAudioAvatar.js +1 -2
  25. package/dist/components/ai/EmbeddedAssistent/TTS/MessageSender.d.ts +1 -2
  26. package/dist/components/ai/EmbeddedAssistent/TTS/MessageSender.js +4 -2
  27. package/dist/components/ai/EmbeddedAssistent/VoiceRecoder.js +2 -3
  28. package/dist/components/audio/Playbutton.js +10 -7
  29. package/dist/components/components/ContextMenu.d.ts +1 -1
  30. package/dist/components/components/ContextMenu.js +19 -16
  31. package/dist/components.d.ts +10 -10
  32. package/dist/components.js +10 -10
  33. package/dist/core/controller/AIController.d.ts +2 -2
  34. package/dist/core/controller/AIController.js +12 -12
  35. package/dist/core/controller/ExerciseController.d.ts +2 -2
  36. package/dist/core/controller/ExerciseController.js +2 -2
  37. package/dist/core/controller/ObjectController.js +5 -5
  38. package/dist/core/controller/SettingsController.d.ts +22 -7
  39. package/dist/core/controller/SettingsController.js +73 -8
  40. package/dist/core/controller/SharedContentController.d.ts +3 -3
  41. package/dist/core/controller/SharedContentController.js +38 -20
  42. package/dist/core/controller/VoiceController.js +6 -4
  43. package/dist/core/core.d.ts +15 -15
  44. package/dist/core/core.js +7 -7
  45. package/dist/fromRimori/EventBus.js +23 -23
  46. package/dist/fromRimori/PluginTypes.d.ts +4 -4
  47. package/dist/hooks/UseChatHook.d.ts +3 -3
  48. package/dist/hooks/UseChatHook.js +9 -3
  49. package/dist/index.d.ts +10 -10
  50. package/dist/index.js +9 -9
  51. package/dist/plugin/AccomplishmentHandler.d.ts +5 -5
  52. package/dist/plugin/AccomplishmentHandler.js +31 -27
  53. package/dist/plugin/AudioController.d.ts +1 -1
  54. package/dist/plugin/AudioController.js +6 -6
  55. package/dist/plugin/Logger.js +15 -13
  56. package/dist/plugin/PluginController.d.ts +7 -1
  57. package/dist/plugin/PluginController.js +32 -27
  58. package/dist/plugin/RimoriClient.d.ts +17 -18
  59. package/dist/plugin/RimoriClient.js +31 -31
  60. package/dist/plugin/StandaloneClient.d.ts +1 -1
  61. package/dist/plugin/StandaloneClient.js +35 -16
  62. package/dist/plugin/ThemeSetter.js +4 -4
  63. package/dist/providers/PluginProvider.js +44 -14
  64. package/dist/utils/Language.js +57 -57
  65. package/dist/utils/PluginUtils.js +3 -3
  66. package/dist/utils/difficultyConverter.d.ts +1 -1
  67. package/dist/utils/difficultyConverter.js +1 -1
  68. package/dist/utils/endpoint.js +2 -2
  69. package/dist/worker/WorkerSetup.d.ts +1 -1
  70. package/dist/worker/WorkerSetup.js +6 -6
  71. package/example/docs/devdocs.md +50 -40
  72. package/example/docs/overview.md +1 -1
  73. package/example/docs/userdocs.md +4 -1
  74. package/example/rimori.config.ts +51 -49
  75. package/example/worker/vite.config.ts +3 -3
  76. package/example/worker/worker.ts +2 -2
  77. package/package.json +14 -8
  78. package/prettier.config.js +1 -1
  79. package/src/cli/scripts/init/dev-registration.ts +5 -8
  80. package/src/cli/scripts/init/env-setup.ts +1 -1
  81. package/src/cli/scripts/init/file-operations.ts +1 -1
  82. package/src/cli/scripts/init/html-cleaner.ts +2 -5
  83. package/src/cli/scripts/init/main.ts +16 -13
  84. package/src/cli/scripts/init/package-setup.ts +11 -15
  85. package/src/cli/scripts/init/router-transformer.ts +40 -37
  86. package/src/cli/scripts/init/tailwind-config.ts +17 -26
  87. package/src/cli/scripts/init/vite-config.ts +3 -3
  88. package/src/cli/scripts/release/release-config-upload.ts +11 -11
  89. package/src/cli/scripts/release/release-db-update.ts +12 -12
  90. package/src/cli/scripts/release/release-file-upload.ts +2 -2
  91. package/src/cli/scripts/release/release.ts +4 -4
  92. package/src/cli/types/DatabaseTypes.ts +2 -10
  93. package/src/components/CRUDModal.tsx +64 -48
  94. package/src/components/MarkdownEditor.tsx +58 -27
  95. package/src/components/Spinner.tsx +24 -17
  96. package/src/components/ai/Assistant.tsx +70 -70
  97. package/src/components/ai/Avatar.tsx +17 -14
  98. package/src/components/ai/EmbeddedAssistent/AudioInputField.tsx +63 -54
  99. package/src/components/ai/EmbeddedAssistent/CircleAudioAvatar.tsx +14 -5
  100. package/src/components/ai/EmbeddedAssistent/TTS/MessageSender.ts +75 -74
  101. package/src/components/ai/EmbeddedAssistent/TTS/Player.ts +3 -4
  102. package/src/components/ai/EmbeddedAssistent/VoiceRecoder.tsx +109 -94
  103. package/src/components/ai/utils.ts +4 -4
  104. package/src/components/audio/Playbutton.tsx +101 -93
  105. package/src/components/components/ContextMenu.tsx +47 -35
  106. package/src/components.ts +10 -10
  107. package/src/core/controller/AIController.ts +29 -19
  108. package/src/core/controller/ExerciseController.ts +16 -23
  109. package/src/core/controller/ObjectController.ts +15 -10
  110. package/src/core/controller/SettingsController.ts +89 -16
  111. package/src/core/controller/SharedContentController.ts +80 -44
  112. package/src/core/controller/VoiceController.ts +10 -8
  113. package/src/core/core.ts +15 -16
  114. package/src/fromRimori/EventBus.ts +76 -47
  115. package/src/fromRimori/PluginTypes.ts +26 -17
  116. package/src/fromRimori/readme.md +2 -2
  117. package/src/hooks/UseChatHook.ts +25 -15
  118. package/src/index.ts +10 -10
  119. package/src/plugin/AccomplishmentHandler.ts +53 -35
  120. package/src/plugin/AudioController.ts +18 -12
  121. package/src/plugin/Logger.ts +28 -21
  122. package/src/plugin/PluginController.ts +60 -44
  123. package/src/plugin/RimoriClient.ts +102 -72
  124. package/src/plugin/StandaloneClient.ts +51 -24
  125. package/src/plugin/ThemeSetter.ts +5 -5
  126. package/src/providers/PluginProvider.tsx +90 -36
  127. package/src/style.scss +3 -3
  128. package/src/utils/Language.ts +58 -58
  129. package/src/utils/PluginUtils.ts +16 -20
  130. package/src/utils/difficultyConverter.ts +2 -2
  131. package/src/utils/endpoint.ts +3 -2
  132. package/src/worker/WorkerSetup.ts +8 -9
  133. package/tsconfig.json +2 -4
@@ -1,6 +1,7 @@
1
- import { SupabaseClient } from "@supabase/supabase-js";
2
- import { LanguageLevel } from "../../utils/difficultyConverter";
3
- import { Language } from "../../utils/Language";
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
- location_country: string;
43
+ target_country: string;
43
44
  /**
44
45
  * Optional: nearest big city (>100,000) near user's location
45
46
  */
46
- location_city?: string;
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 { data } = await this.supabase.from("plugin_settings").select("*").eq("plugin_id", this.pluginId)
68
+ const isGuildSetting = !this.guild.allowUserPluginSettings;
60
69
 
61
- if (!data || data.length === 0) {
62
- return null;
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[0].settings;
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
- await this.supabase.from("plugin_settings").upsert({ plugin_id: this.pluginId, settings });
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 "../../plugin/RimoriClient";
3
- import { ObjectRequest } from "./ObjectController";
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, skipDbSave?: boolean, alwaysGenerateNew?: boolean, excludeIds?: string[] },
37
+ options?: { privateTopic?: boolean; skipDbSave?: boolean; alwaysGenerateNew?: boolean; excludeIds?: string[] },
38
38
  ): Promise<SharedContent<T>> {
39
- let query = this.supabase.from("shared_content")
40
- .select("*, scc:shared_content_completed(id, state)")
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 (!(options?.alwaysGenerateNew) && newAssignments.length > 0) {
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: "internal-temp-id-" + Math.random().toString(36).substring(2, 15),
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(contentType: string, generatorInstructions: SharedContentObjectRequest, filter?: SharedContentFilter): Promise<any> {
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(contentType: string, generatorInstructions: ObjectRequest, filter?: SharedContentFilter): Promise<ObjectRequest> {
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: "string",
107
- description: "What the topic is about. Short. ",
108
- }
115
+ type: 'string',
116
+ description: 'What the topic is about. Short. ',
117
+ };
109
118
  generatorInstructions.tool.keywords = {
110
- type: [{ text: { type: "string" } }],
111
- description: "Keywords around the topic of the assignment.",
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.from("shared_content")
118
- .select("title, keywords, scc:shared_content_completed(id)")
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.from("shared_content").select().eq('content_type', contentType).eq('id', id).is('deleted_at', null).single();
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("shared_content_completed")
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>(contentType: string, filter?: SharedContentFilter, limit?: number): Promise<SharedContent<T>[]> {
205
- const query = this.supabase.from("shared_content").select("*").eq('content_type', contentType).is('deleted_at', null).limit(limit ?? 30);
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>({ contentType, title, keywords, data, privateTopic }: Omit<SharedContent<T>, 'id'>): Promise<SharedContent<T>> {
233
- const { data: newContent, error } = await this.supabase.from("shared_content").insert({
234
- private: privateTopic,
235
- content_type: contentType,
236
- title,
237
- keywords,
238
- data,
239
- }).select();
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.from("shared_content").update(updateData).eq('id', id).select();
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("shared_content")
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: { 'Authorization': `Bearer ${token}` },
7
+ headers: { Authorization: `Bearer ${token}` },
8
8
  body: formData,
9
- }).then(r => r.json()).then(r => {
10
- // console.log("STT response: ", r);
11
- return r.text;
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
- 'Authorization': `Bearer ${token}`
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 "../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";
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';