@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
package/README.md
CHANGED
|
@@ -40,11 +40,11 @@ Before initializing your plugin, ensure you have:
|
|
|
40
40
|
|
|
41
41
|
### Initializing a New Plugin
|
|
42
42
|
|
|
43
|
-
Open Lovable and vibe code the look of your plugin.
|
|
43
|
+
Open Lovable and vibe code the look of your plugin.
|
|
44
44
|
|
|
45
45
|
Then connect it to your Github account.
|
|
46
46
|
|
|
47
|
-
Clone the git repository:
|
|
47
|
+
Clone the git repository:
|
|
48
48
|
|
|
49
49
|
```bash
|
|
50
50
|
git clone ...
|
|
@@ -88,6 +88,7 @@ yarn dev
|
|
|
88
88
|
```
|
|
89
89
|
|
|
90
90
|
Rimori client comes pre-configured with:
|
|
91
|
+
|
|
91
92
|
- ✅ **Hot reload** for instant development feedback
|
|
92
93
|
- ✅ **TypeScript support** with full type safety
|
|
93
94
|
- ✅ **TailwindCSS** for modern styling
|
|
@@ -111,7 +112,7 @@ During plugin initialization, convenient release scripts are automatically added
|
|
|
111
112
|
```bash
|
|
112
113
|
# Quick release commands (build + release)
|
|
113
114
|
yarn release:alpha # Build and release to alpha channel
|
|
114
|
-
yarn release:beta # Build and release to beta channel
|
|
115
|
+
yarn release:beta # Build and release to beta channel
|
|
115
116
|
yarn release:stable # Build and release to stable channel
|
|
116
117
|
```
|
|
117
118
|
|
|
@@ -125,7 +126,7 @@ yarn build
|
|
|
125
126
|
|
|
126
127
|
# Then release to different channels
|
|
127
128
|
yarn rimori-release alpha # For alpha testing
|
|
128
|
-
yarn rimori-release beta # For beta releases
|
|
129
|
+
yarn rimori-release beta # For beta releases
|
|
129
130
|
yarn rimori-release stable # For production releases
|
|
130
131
|
```
|
|
131
132
|
|
|
@@ -149,6 +150,7 @@ The `rimori-release` command performs a complete release workflow:
|
|
|
149
150
|
### Automatic Configuration
|
|
150
151
|
|
|
151
152
|
During plugin initialization, the following are automatically configured:
|
|
153
|
+
|
|
152
154
|
- `RIMORI_TOKEN`: Your authentication token (stored in `.env`)
|
|
153
155
|
- `r_id`: Your unique plugin ID (stored in `package.json`)
|
|
154
156
|
- **Release scripts**: `yarn release:alpha`, `yarn release:beta`, `yarn release:stable`
|
|
@@ -166,6 +168,7 @@ If you encounter release issues:
|
|
|
166
168
|
#### Worker Process Errors
|
|
167
169
|
|
|
168
170
|
If you encounter errors like:
|
|
171
|
+
|
|
169
172
|
```
|
|
170
173
|
ReferenceError: process is not defined
|
|
171
174
|
```
|
|
@@ -180,10 +183,11 @@ ReferenceError: process is not defined
|
|
|
180
183
|
- Utility libraries that check for environment variables
|
|
181
184
|
|
|
182
185
|
2. **Verify Rimori Client imports**: Ensure you're importing from `@rimori/client/core` and not from `@rimori/client`:
|
|
186
|
+
|
|
183
187
|
```typescript
|
|
184
188
|
// ✅ Correct - import from rimori client
|
|
185
189
|
import { RimoriClient } from '@rimori/client/core';
|
|
186
|
-
|
|
190
|
+
|
|
187
191
|
// ❌ Incorrect - direct imports that might access process.env directly or through their dependencies
|
|
188
192
|
import { Avatar } from '@rimori/client';
|
|
189
193
|
import { useQuery } from '@tanstack/react-query';
|
|
@@ -195,16 +199,11 @@ ReferenceError: process is not defined
|
|
|
195
199
|
- Routing libraries
|
|
196
200
|
- Any library that checks `process.env.NODE_ENV`
|
|
197
201
|
|
|
198
|
-
|
|
199
202
|
**Solution**: Use only `@rimori/client/core` exports in your worker code. The Rimori client provides all necessary functionality without requiring Node.js globals.
|
|
200
203
|
|
|
201
204
|
**Note**: The worker bundling order is determined by the build system and cannot be controlled. Libraries that access `process.env` will always cause this error in the worker context.
|
|
202
205
|
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
```
|
|
206
|
+
````
|
|
208
207
|
|
|
209
208
|
## Core API - usePlugin Hook
|
|
210
209
|
|
|
@@ -215,13 +214,13 @@ import { useRimori } from "@rimori/client";
|
|
|
215
214
|
|
|
216
215
|
const MyComponent = () => {
|
|
217
216
|
const client = useRimori();
|
|
218
|
-
|
|
217
|
+
|
|
219
218
|
// Access all client features
|
|
220
219
|
const { db, llm, event, community, plugin } = client;
|
|
221
|
-
|
|
220
|
+
|
|
222
221
|
return <div>My Plugin Content</div>;
|
|
223
222
|
};
|
|
224
|
-
|
|
223
|
+
````
|
|
225
224
|
|
|
226
225
|
### Plugin Interface
|
|
227
226
|
|
|
@@ -260,11 +259,11 @@ const FlashcardSettingsComponent = () => {
|
|
|
260
259
|
enableAudioPronunciation: true,
|
|
261
260
|
difficultyAlgorithm: 'spaced-repetition'
|
|
262
261
|
};
|
|
263
|
-
|
|
262
|
+
|
|
264
263
|
const currentSettings = await plugin.getSettings(defaultSettings);
|
|
265
264
|
setSettings(currentSettings);
|
|
266
265
|
};
|
|
267
|
-
|
|
266
|
+
|
|
268
267
|
loadSettings();
|
|
269
268
|
}, []);
|
|
270
269
|
|
|
@@ -278,19 +277,19 @@ const FlashcardSettingsComponent = () => {
|
|
|
278
277
|
<div className="flashcard-settings">
|
|
279
278
|
<label>
|
|
280
279
|
Daily Goal: {settings?.dailyGoal} cards
|
|
281
|
-
<input
|
|
282
|
-
type="range"
|
|
283
|
-
min="5"
|
|
284
|
-
max="100"
|
|
285
|
-
value={settings?.dailyGoal}
|
|
280
|
+
<input
|
|
281
|
+
type="range"
|
|
282
|
+
min="5"
|
|
283
|
+
max="100"
|
|
284
|
+
value={settings?.dailyGoal}
|
|
286
285
|
onChange={(e) => updateSettings({ dailyGoal: parseInt(e.target.value) })}
|
|
287
286
|
/>
|
|
288
287
|
</label>
|
|
289
|
-
|
|
288
|
+
|
|
290
289
|
<label>
|
|
291
290
|
Review Interval:
|
|
292
|
-
<select
|
|
293
|
-
value={settings?.reviewInterval}
|
|
291
|
+
<select
|
|
292
|
+
value={settings?.reviewInterval}
|
|
294
293
|
onChange={(e) => updateSettings({ reviewInterval: e.target.value as any })}
|
|
295
294
|
>
|
|
296
295
|
<option value="easy">Easy (longer intervals)</option>
|
|
@@ -298,10 +297,10 @@ const FlashcardSettingsComponent = () => {
|
|
|
298
297
|
<option value="hard">Hard (shorter intervals)</option>
|
|
299
298
|
</select>
|
|
300
299
|
</label>
|
|
301
|
-
|
|
300
|
+
|
|
302
301
|
<label>
|
|
303
|
-
<input
|
|
304
|
-
type="checkbox"
|
|
302
|
+
<input
|
|
303
|
+
type="checkbox"
|
|
305
304
|
checked={settings?.enableAudioPronunciation}
|
|
306
305
|
onChange={(e) => updateSettings({ enableAudioPronunciation: e.target.checked })}
|
|
307
306
|
/>
|
|
@@ -327,6 +326,7 @@ db.getTableName(table: string): string // Get full table name with prefix
|
|
|
327
326
|
```
|
|
328
327
|
|
|
329
328
|
The `db.from()` method provides access to the complete Supabase PostgREST API, supporting all database operations including:
|
|
329
|
+
|
|
330
330
|
- **CRUD Operations**: `insert()`, `select()`, `update()`, `delete()`, `upsert()`
|
|
331
331
|
- **Filtering**: `eq()`, `neq()`, `gt()`, `gte()`, `lt()`, `lte()`, `like()`, `ilike()`, `is()`, `in()`, `contains()`, `containedBy()`, `rangeLt()`, `rangeGt()`, `rangeGte()`, `rangeLte()`, `rangeAdjacent()`, `overlaps()`, `textSearch()`, `match()`, `not()`, `or()`, `filter()`
|
|
332
332
|
- **Modifiers**: `order()`, `limit()`, `range()`, `single()`, `maybe_single()`, `csv()`, `geojson()`, `explain()`
|
|
@@ -354,7 +354,7 @@ interface StudySession {
|
|
|
354
354
|
|
|
355
355
|
const StudySessionManager = () => {
|
|
356
356
|
const { db } = useRimori();
|
|
357
|
-
|
|
357
|
+
|
|
358
358
|
// Create a new study session
|
|
359
359
|
const createSession = async (session: Omit<StudySession, 'id'>) => {
|
|
360
360
|
const { data, error } = await db
|
|
@@ -362,7 +362,7 @@ const StudySessionManager = () => {
|
|
|
362
362
|
.insert(session)
|
|
363
363
|
.select()
|
|
364
364
|
.single();
|
|
365
|
-
|
|
365
|
+
|
|
366
366
|
if (error) throw error;
|
|
367
367
|
return data;
|
|
368
368
|
};
|
|
@@ -374,7 +374,7 @@ const StudySessionManager = () => {
|
|
|
374
374
|
.select('*')
|
|
375
375
|
.eq('user_id', userId)
|
|
376
376
|
.order('completed_at', { ascending: false });
|
|
377
|
-
|
|
377
|
+
|
|
378
378
|
if (error) throw error;
|
|
379
379
|
return data;
|
|
380
380
|
};
|
|
@@ -387,7 +387,7 @@ const StudySessionManager = () => {
|
|
|
387
387
|
.eq('id', id)
|
|
388
388
|
.select()
|
|
389
389
|
.single();
|
|
390
|
-
|
|
390
|
+
|
|
391
391
|
if (error) throw error;
|
|
392
392
|
return data;
|
|
393
393
|
};
|
|
@@ -405,14 +405,14 @@ const StudySessionManager = () => {
|
|
|
405
405
|
```typescript
|
|
406
406
|
const FileManager = () => {
|
|
407
407
|
const { db } = useRimori();
|
|
408
|
-
|
|
408
|
+
|
|
409
409
|
const uploadFile = async (file: File) => {
|
|
410
410
|
const fileName = `uploads/${Date.now()}-${file.name}`;
|
|
411
|
-
|
|
411
|
+
|
|
412
412
|
const { data, error } = await db.storage
|
|
413
413
|
.from('plugin-files')
|
|
414
414
|
.upload(fileName, file);
|
|
415
|
-
|
|
415
|
+
|
|
416
416
|
if (error) throw error;
|
|
417
417
|
return data;
|
|
418
418
|
};
|
|
@@ -421,7 +421,7 @@ const FileManager = () => {
|
|
|
421
421
|
const { data, error } = await db.storage
|
|
422
422
|
.from('plugin-files')
|
|
423
423
|
.download(filePath);
|
|
424
|
-
|
|
424
|
+
|
|
425
425
|
if (error) throw error;
|
|
426
426
|
return data;
|
|
427
427
|
};
|
|
@@ -464,12 +464,12 @@ const ChatAssistant = () => {
|
|
|
464
464
|
|
|
465
465
|
const sendMessage = () => {
|
|
466
466
|
if (!input.trim()) return;
|
|
467
|
-
|
|
467
|
+
|
|
468
468
|
append([{
|
|
469
469
|
role: 'user',
|
|
470
470
|
content: input
|
|
471
471
|
}]);
|
|
472
|
-
|
|
472
|
+
|
|
473
473
|
setInput('');
|
|
474
474
|
};
|
|
475
475
|
|
|
@@ -483,7 +483,7 @@ const ChatAssistant = () => {
|
|
|
483
483
|
))}
|
|
484
484
|
{isLoading && <div className="message assistant">Thinking...</div>}
|
|
485
485
|
</div>
|
|
486
|
-
|
|
486
|
+
|
|
487
487
|
<div className="input-area">
|
|
488
488
|
<input
|
|
489
489
|
value={input}
|
|
@@ -505,7 +505,7 @@ const ChatAssistant = () => {
|
|
|
505
505
|
```typescript
|
|
506
506
|
const QuizGenerator = () => {
|
|
507
507
|
const { llm } = useRimori();
|
|
508
|
-
|
|
508
|
+
|
|
509
509
|
const generateQuiz = async (topic: string) => {
|
|
510
510
|
const quiz = await llm.getObject({
|
|
511
511
|
schema: {
|
|
@@ -528,7 +528,7 @@ const QuizGenerator = () => {
|
|
|
528
528
|
},
|
|
529
529
|
prompt: `Create a quiz about ${topic} with 5 multiple choice questions.`
|
|
530
530
|
});
|
|
531
|
-
|
|
531
|
+
|
|
532
532
|
return quiz;
|
|
533
533
|
};
|
|
534
534
|
|
|
@@ -541,7 +541,7 @@ const QuizGenerator = () => {
|
|
|
541
541
|
```typescript
|
|
542
542
|
const VoiceAssistant = () => {
|
|
543
543
|
const { llm } = useRimori();
|
|
544
|
-
|
|
544
|
+
|
|
545
545
|
const speakText = async (text: string) => {
|
|
546
546
|
const audioBlob = await llm.getVoice(text, "alloy", 1, "en");
|
|
547
547
|
const audioUrl = URL.createObjectURL(audioBlob);
|
|
@@ -585,7 +585,7 @@ event.emitSidebarAction(pluginId: string, actionKey: string, text?: string): voi
|
|
|
585
585
|
```typescript
|
|
586
586
|
const PluginCommunicator = () => {
|
|
587
587
|
const { event } = useRimori();
|
|
588
|
-
|
|
588
|
+
|
|
589
589
|
useEffect(() => {
|
|
590
590
|
// Listen for messages from other plugins
|
|
591
591
|
const unsubscribe = event.on('flashcards.newCard', (message) => {
|
|
@@ -617,7 +617,7 @@ const PluginCommunicator = () => {
|
|
|
617
617
|
const response = await event.request('flashcards.getStats', {
|
|
618
618
|
timeframe: 'week'
|
|
619
619
|
});
|
|
620
|
-
|
|
620
|
+
|
|
621
621
|
console.log('Flashcard stats:', response.data);
|
|
622
622
|
};
|
|
623
623
|
|
|
@@ -635,7 +635,7 @@ const PluginCommunicator = () => {
|
|
|
635
635
|
```typescript
|
|
636
636
|
const AccomplishmentTracker = () => {
|
|
637
637
|
const { event } = useRimori();
|
|
638
|
-
|
|
638
|
+
|
|
639
639
|
const trackAccomplishment = () => {
|
|
640
640
|
event.emitAccomplishment({
|
|
641
641
|
type: 'study_milestone',
|
|
@@ -666,7 +666,7 @@ const AccomplishmentTracker = () => {
|
|
|
666
666
|
```typescript
|
|
667
667
|
const SidebarIntegration = () => {
|
|
668
668
|
const { event } = useRimori();
|
|
669
|
-
|
|
669
|
+
|
|
670
670
|
const openTranslator = (text: string) => {
|
|
671
671
|
// Trigger translator plugin in sidebar
|
|
672
672
|
event.emitSidebarAction('translator', 'translate', text);
|
|
@@ -745,7 +745,7 @@ const ExerciseManager = () => {
|
|
|
745
745
|
questionCount: exercise.questions.length
|
|
746
746
|
}
|
|
747
747
|
});
|
|
748
|
-
|
|
748
|
+
|
|
749
749
|
return newExercise;
|
|
750
750
|
};
|
|
751
751
|
|
|
@@ -777,7 +777,7 @@ const ExerciseManager = () => {
|
|
|
777
777
|
},
|
|
778
778
|
{ column: 'difficulty', value: 'beginner' }
|
|
779
779
|
);
|
|
780
|
-
|
|
780
|
+
|
|
781
781
|
return aiExercise;
|
|
782
782
|
};
|
|
783
783
|
|
|
@@ -804,6 +804,7 @@ const ExerciseManager = () => {
|
|
|
804
804
|
Pre-built React components for common functionality:
|
|
805
805
|
|
|
806
806
|
### MarkdownEditor
|
|
807
|
+
|
|
807
808
|
Rich text editor with markdown support:
|
|
808
809
|
|
|
809
810
|
```typescript
|
|
@@ -811,7 +812,7 @@ import { MarkdownEditor } from "@rimori/client";
|
|
|
811
812
|
|
|
812
813
|
const EditorExample = () => {
|
|
813
814
|
const [content, setContent] = useState('');
|
|
814
|
-
|
|
815
|
+
|
|
815
816
|
return (
|
|
816
817
|
<MarkdownEditor
|
|
817
818
|
value={content}
|
|
@@ -823,6 +824,7 @@ const EditorExample = () => {
|
|
|
823
824
|
```
|
|
824
825
|
|
|
825
826
|
### CRUDModal
|
|
827
|
+
|
|
826
828
|
Modal component for create/update operations:
|
|
827
829
|
|
|
828
830
|
```typescript
|
|
@@ -831,7 +833,7 @@ import { CRUDModal } from "@rimori/client";
|
|
|
831
833
|
const DataManager = () => {
|
|
832
834
|
const [isOpen, setIsOpen] = useState(false);
|
|
833
835
|
const [editItem, setEditItem] = useState(null);
|
|
834
|
-
|
|
836
|
+
|
|
835
837
|
return (
|
|
836
838
|
<CRUDModal
|
|
837
839
|
isOpen={isOpen}
|
|
@@ -853,6 +855,7 @@ const DataManager = () => {
|
|
|
853
855
|
```
|
|
854
856
|
|
|
855
857
|
### Spinner
|
|
858
|
+
|
|
856
859
|
Loading indicator component:
|
|
857
860
|
|
|
858
861
|
```typescript
|
|
@@ -860,16 +863,17 @@ import { Spinner } from "@rimori/client";
|
|
|
860
863
|
|
|
861
864
|
const LoadingExample = () => {
|
|
862
865
|
const [isLoading, setIsLoading] = useState(true);
|
|
863
|
-
|
|
866
|
+
|
|
864
867
|
if (isLoading) {
|
|
865
868
|
return <Spinner size="large" />;
|
|
866
869
|
}
|
|
867
|
-
|
|
870
|
+
|
|
868
871
|
return <div>Content loaded!</div>;
|
|
869
872
|
};
|
|
870
873
|
```
|
|
871
874
|
|
|
872
875
|
### PlayButton
|
|
876
|
+
|
|
873
877
|
Audio playback component:
|
|
874
878
|
|
|
875
879
|
```typescript
|
|
@@ -894,12 +898,12 @@ import { Avatar, Assistant } from "@rimori/client";
|
|
|
894
898
|
const AIInterface = () => {
|
|
895
899
|
return (
|
|
896
900
|
<div>
|
|
897
|
-
<Avatar
|
|
901
|
+
<Avatar
|
|
898
902
|
name="AI Assistant"
|
|
899
903
|
status="online"
|
|
900
904
|
size="large"
|
|
901
905
|
/>
|
|
902
|
-
|
|
906
|
+
|
|
903
907
|
<Assistant
|
|
904
908
|
onMessage={(message) => console.log('AI message:', message)}
|
|
905
909
|
placeholder="Ask the AI assistant..."
|
|
@@ -912,6 +916,7 @@ const AIInterface = () => {
|
|
|
912
916
|
## Hooks
|
|
913
917
|
|
|
914
918
|
### useChat
|
|
919
|
+
|
|
915
920
|
Manage AI chat conversations:
|
|
916
921
|
|
|
917
922
|
```typescript
|
|
@@ -950,20 +955,22 @@ const ChatExample = () => {
|
|
|
950
955
|
## Utilities
|
|
951
956
|
|
|
952
957
|
### difficultyConverter
|
|
958
|
+
|
|
953
959
|
Convert between different difficulty representations:
|
|
954
960
|
|
|
955
961
|
```typescript
|
|
956
|
-
import { difficultyConverter } from
|
|
962
|
+
import { difficultyConverter } from '@rimori/client';
|
|
957
963
|
|
|
958
964
|
const difficulty = difficultyConverter.toNumber('intermediate'); // Returns: 2
|
|
959
965
|
const difficultyText = difficultyConverter.toString(3); // Returns: 'advanced'
|
|
960
966
|
```
|
|
961
967
|
|
|
962
968
|
### PluginUtils
|
|
969
|
+
|
|
963
970
|
Various utility functions:
|
|
964
971
|
|
|
965
972
|
```typescript
|
|
966
|
-
import { PluginUtils } from
|
|
973
|
+
import { PluginUtils } from '@rimori/client';
|
|
967
974
|
|
|
968
975
|
// Utility functions for common plugin operations
|
|
969
976
|
const utils = PluginUtils.getInstance();
|
|
@@ -971,10 +978,11 @@ const utils = PluginUtils.getInstance();
|
|
|
971
978
|
```
|
|
972
979
|
|
|
973
980
|
### Language Utilities
|
|
981
|
+
|
|
974
982
|
Language detection and processing:
|
|
975
983
|
|
|
976
984
|
```typescript
|
|
977
|
-
import { Language } from
|
|
985
|
+
import { Language } from '@rimori/client';
|
|
978
986
|
|
|
979
987
|
// Language-related utility functions
|
|
980
988
|
const languageCode = Language.detectLanguage(text);
|
|
@@ -986,7 +994,7 @@ const isSupported = Language.isSupported('es');
|
|
|
986
994
|
The package is fully typed with comprehensive TypeScript definitions:
|
|
987
995
|
|
|
988
996
|
```typescript
|
|
989
|
-
import type {
|
|
997
|
+
import type {
|
|
990
998
|
MainPanelAction,
|
|
991
999
|
Message,
|
|
992
1000
|
Tool,
|
|
@@ -994,8 +1002,8 @@ import type {
|
|
|
994
1002
|
AccomplishmentPayload,
|
|
995
1003
|
SharedContent,
|
|
996
1004
|
BasicAssignment,
|
|
997
|
-
UserInfo
|
|
998
|
-
} from
|
|
1005
|
+
UserInfo,
|
|
1006
|
+
} from '@rimori/client';
|
|
999
1007
|
|
|
1000
1008
|
// All interfaces and types are exported for use in your plugin
|
|
1001
1009
|
interface MyPluginData extends SharedContent<any> {
|
|
@@ -1030,12 +1038,12 @@ export interface SharedContent<T> {
|
|
|
1030
1038
|
|
|
1031
1039
|
```typescript
|
|
1032
1040
|
import React, { useState, useEffect } from 'react';
|
|
1033
|
-
import {
|
|
1034
|
-
PluginProvider,
|
|
1035
|
-
usePlugin,
|
|
1036
|
-
MarkdownEditor,
|
|
1041
|
+
import {
|
|
1042
|
+
PluginProvider,
|
|
1043
|
+
usePlugin,
|
|
1044
|
+
MarkdownEditor,
|
|
1037
1045
|
Spinner,
|
|
1038
|
-
useChat
|
|
1046
|
+
useChat
|
|
1039
1047
|
} from '@rimori/client';
|
|
1040
1048
|
import { HashRouter, Route, Routes } from 'react-router-dom';
|
|
1041
1049
|
|
|
@@ -1065,9 +1073,9 @@ const StudyNotesPlugin = () => {
|
|
|
1065
1073
|
content,
|
|
1066
1074
|
created_at: new Date().toISOString()
|
|
1067
1075
|
}).select().single();
|
|
1068
|
-
|
|
1076
|
+
|
|
1069
1077
|
setNotes([data, ...notes]);
|
|
1070
|
-
|
|
1078
|
+
|
|
1071
1079
|
// Share with community
|
|
1072
1080
|
await community.sharedContent.create({
|
|
1073
1081
|
content_type: 'study_notes',
|
|
@@ -1080,7 +1088,7 @@ const StudyNotesPlugin = () => {
|
|
|
1080
1088
|
const summary = await llm.getText([
|
|
1081
1089
|
{ role: 'user', content: `Summarize this study note: ${noteContent}` }
|
|
1082
1090
|
]);
|
|
1083
|
-
|
|
1091
|
+
|
|
1084
1092
|
return summary;
|
|
1085
1093
|
};
|
|
1086
1094
|
|
|
@@ -1089,11 +1097,11 @@ const StudyNotesPlugin = () => {
|
|
|
1089
1097
|
return (
|
|
1090
1098
|
<div className="study-notes-plugin">
|
|
1091
1099
|
<h1>Study Notes</h1>
|
|
1092
|
-
|
|
1100
|
+
|
|
1093
1101
|
<div className="notes-grid">
|
|
1094
1102
|
{notes.map(note => (
|
|
1095
1103
|
<div key={note.id} className="note-card">
|
|
1096
|
-
<MarkdownEditor
|
|
1104
|
+
<MarkdownEditor
|
|
1097
1105
|
value={note.content}
|
|
1098
1106
|
onChange={(content) => {/* Update logic */}}
|
|
1099
1107
|
/>
|
|
@@ -1139,5 +1147,3 @@ export default App;
|
|
|
1139
1147
|
3. **Type Safety**: Use TypeScript interfaces for all data structures
|
|
1140
1148
|
4. **Event Cleanup**: Always unsubscribe from events in useEffect cleanup
|
|
1141
1149
|
5. **Responsive Design**: Use TailwindCSS classes for responsive layouts
|
|
1142
|
-
|
|
1143
|
-
|
|
@@ -24,7 +24,7 @@ export declare function askForPort(): Promise<number>;
|
|
|
24
24
|
* @returns Promise resolving to JWT access token.
|
|
25
25
|
* @throws {Error} if authentication fails.
|
|
26
26
|
*/
|
|
27
|
-
export declare function authenticateWithSupabase({ email, password
|
|
27
|
+
export declare function authenticateWithSupabase({ email, password }: UserCredentials): Promise<string>;
|
|
28
28
|
/**
|
|
29
29
|
* Registers developer and gets plugin credentials from the backend.
|
|
30
30
|
* @param jwtToken - JWT token from Supabase authentication.
|
|
@@ -28,7 +28,7 @@ export function askForCredentials() {
|
|
|
28
28
|
const passwordRl = readline.createInterface({
|
|
29
29
|
input: process.stdin,
|
|
30
30
|
output: process.stdout,
|
|
31
|
-
terminal: false
|
|
31
|
+
terminal: false,
|
|
32
32
|
});
|
|
33
33
|
process.stdout.write('Enter your password: ');
|
|
34
34
|
// Set up stdin for raw input
|
|
@@ -106,7 +106,7 @@ export function askForPort() {
|
|
|
106
106
|
* @throws {Error} if authentication fails.
|
|
107
107
|
*/
|
|
108
108
|
export function authenticateWithSupabase(_a) {
|
|
109
|
-
return __awaiter(this, arguments, void 0, function* ({ email, password
|
|
109
|
+
return __awaiter(this, arguments, void 0, function* ({ email, password }) {
|
|
110
110
|
var _b;
|
|
111
111
|
console.log('🔐 Authenticating with Supabase...');
|
|
112
112
|
// Initialize Supabase client (you may need to adjust the URL and key)
|
|
@@ -145,12 +145,12 @@ export function registerDeveloper(jwtToken, port) {
|
|
|
145
145
|
try {
|
|
146
146
|
const currentFolderName = path.basename(process.cwd());
|
|
147
147
|
const body = { port, pluginName: currentFolderName };
|
|
148
|
-
const backendUrl = process.env.RIMORI_BACKEND_URL ||
|
|
148
|
+
const backendUrl = process.env.RIMORI_BACKEND_URL || 'https://api.rimori.se';
|
|
149
149
|
const response = yield fetch(backendUrl + '/developer/register', {
|
|
150
150
|
method: 'POST',
|
|
151
151
|
headers: {
|
|
152
152
|
'Content-Type': 'application/json',
|
|
153
|
-
|
|
153
|
+
Authorization: `Bearer ${jwtToken}`,
|
|
154
154
|
},
|
|
155
155
|
body: JSON.stringify(body),
|
|
156
156
|
});
|
|
@@ -10,7 +10,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
|
|
|
10
10
|
};
|
|
11
11
|
import * as fs from 'fs';
|
|
12
12
|
import * as path from 'path';
|
|
13
|
-
import { askForCredentials, askForPort, authenticateWithSupabase, registerDeveloper
|
|
13
|
+
import { askForCredentials, askForPort, authenticateWithSupabase, registerDeveloper } from './dev-registration.js';
|
|
14
14
|
import { setupEnvFile, updateGitignore } from './env-setup.js';
|
|
15
15
|
import { copyPluginFiles } from './file-operations.js';
|
|
16
16
|
import { cleanHtmlMetaTags } from './html-cleaner.js';
|
|
@@ -29,4 +29,4 @@ export declare function getRimoriClientVersion(): string;
|
|
|
29
29
|
* @param param.isUpgrade - Whether this is an upgrade operation.
|
|
30
30
|
* @throws {Error} if plugin directory doesn't exist or package.json is missing.
|
|
31
31
|
*/
|
|
32
|
-
export declare function updatePackageJson({ pluginId, port, isUpgrade
|
|
32
|
+
export declare function updatePackageJson({ pluginId, port, isUpgrade }: PackageSetupParams): void;
|
|
@@ -30,7 +30,7 @@ export function getRimoriClientVersion() {
|
|
|
30
30
|
* @param param.isUpgrade - Whether this is an upgrade operation.
|
|
31
31
|
* @throws {Error} if plugin directory doesn't exist or package.json is missing.
|
|
32
32
|
*/
|
|
33
|
-
export function updatePackageJson({ pluginId, port, isUpgrade = false
|
|
33
|
+
export function updatePackageJson({ pluginId, port, isUpgrade = false }) {
|
|
34
34
|
// Get the plugin repo name from the current directory
|
|
35
35
|
const pluginRepoName = path.basename(process.cwd());
|
|
36
36
|
console.log(`Setting up plugin: ${pluginRepoName}`);
|
|
@@ -62,8 +62,8 @@ export function updatePackageJson({ pluginId, port, isUpgrade = false, }) {
|
|
|
62
62
|
if (pluginId) {
|
|
63
63
|
packageJson.r_id = pluginId;
|
|
64
64
|
}
|
|
65
|
-
packageJson.scripts = Object.assign(Object.assign({}, packageJson.scripts), {
|
|
66
|
-
packageJson.dependencies = Object.assign(Object.assign({}, packageJson.dependencies), {
|
|
65
|
+
packageJson.scripts = Object.assign(Object.assign({}, packageJson.scripts), { dev: `vite --port ${port || 3000}`, build: 'yarn run check && vite build', check: 'tsc --project tsconfig.app.json --noEmit --pretty', 'release:alpha': 'yarn build && yarn rimori-release alpha', 'release:beta': 'yarn build && yarn rimori-release beta', 'release:stable': 'yarn build && yarn rimori-release stable', 'dev:worker': 'VITE_MINIFY=false vite build --watch --config worker/vite.config.ts', 'build:worker': 'vite build --config worker/vite.config.ts' });
|
|
66
|
+
packageJson.dependencies = Object.assign(Object.assign({}, packageJson.dependencies), { '@rimori/client': rimoriClientVersion });
|
|
67
67
|
// Write the updated package.json back to file
|
|
68
68
|
try {
|
|
69
69
|
fs.writeFileSync(packageJsonPath, JSON.stringify(packageJson, null, 2), 'utf8');
|