@rimori/client 2.5.7 → 2.5.8-next.1
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/dist/cli/types/DatabaseTypes.d.ts +3 -3
- package/dist/controller/ObjectController.d.ts +2 -2
- package/dist/controller/ObjectController.js +55 -26
- package/dist/index.d.ts +1 -1
- package/dist/plugin/module/AIModule.d.ts +6 -0
- package/dist/plugin/module/AIModule.js +11 -1
- package/dist/plugin/module/SharedContentController.d.ts +2 -1
- package/dist/utils/difficultyConverter.d.ts +8 -0
- package/dist/utils/difficultyConverter.js +10 -0
- package/package.json +1 -1
|
@@ -89,8 +89,8 @@ export interface DbNormalTableDefinition {
|
|
|
89
89
|
* Shared content table schema definition.
|
|
90
90
|
* Defines the structure for community-shared content tables with automatic columns and verification.
|
|
91
91
|
* Table naming: {pluginId}_sc_{table_name}
|
|
92
|
-
* Automatic columns: title (text), keywords (text[]),
|
|
93
|
-
* Hardcoded permissions: read ALL public+own, insert/update/delete OWN
|
|
92
|
+
* Automatic columns: title (text), keywords (text[]), content_status (text: featured/community/unverified), embedding (vector)
|
|
93
|
+
* Hardcoded permissions: read ALL public verified (community/featured) + own, insert/update/delete OWN
|
|
94
94
|
*/
|
|
95
95
|
export interface DbSharedContentTableDefinition {
|
|
96
96
|
/** Type discriminator for shared content tables */
|
|
@@ -101,7 +101,7 @@ export interface DbSharedContentTableDefinition {
|
|
|
101
101
|
description: string;
|
|
102
102
|
/** AI prompt for generating content. Supports placeholders like {{topic}}, {{level}}, etc. */
|
|
103
103
|
instructions: string;
|
|
104
|
-
/** Optional AI prompt to verify content quality
|
|
104
|
+
/** Optional AI prompt to verify content quality and set content_status to 'community' */
|
|
105
105
|
verification_prompt: string;
|
|
106
106
|
/** Column definitions for the table (excluding auto-generated columns) */
|
|
107
107
|
columns: {
|
|
@@ -37,6 +37,6 @@ export interface ObjectRequest {
|
|
|
37
37
|
instructions: string;
|
|
38
38
|
}
|
|
39
39
|
export declare function generateObject<T = any>(backendUrl: string, request: ObjectRequest, token: string): Promise<T>;
|
|
40
|
-
export type
|
|
41
|
-
export declare function streamObject(backendUrl: string, request: ObjectRequest,
|
|
40
|
+
export type OnStreamedObjectResult<T = any> = (result: T, isLoading: boolean) => void;
|
|
41
|
+
export declare function streamObject<T = any>(backendUrl: string, request: ObjectRequest, onResult: OnStreamedObjectResult<T>, token: string): Promise<void>;
|
|
42
42
|
export {};
|
|
@@ -21,56 +21,85 @@ export function generateObject(backendUrl, request, token) {
|
|
|
21
21
|
}).then((response) => response.json());
|
|
22
22
|
});
|
|
23
23
|
}
|
|
24
|
-
|
|
24
|
+
const tryParseJson = (value) => {
|
|
25
|
+
try {
|
|
26
|
+
return JSON.parse(value);
|
|
27
|
+
}
|
|
28
|
+
catch (_a) {
|
|
29
|
+
return null;
|
|
30
|
+
}
|
|
31
|
+
};
|
|
32
|
+
const mergeStreamObject = (base, patch) => {
|
|
33
|
+
if (Array.isArray(patch)) {
|
|
34
|
+
return patch.map((item, index) => mergeStreamObject(base === null || base === void 0 ? void 0 : base[index], item));
|
|
35
|
+
}
|
|
36
|
+
if (patch && typeof patch === 'object') {
|
|
37
|
+
const result = base && typeof base === 'object' && !Array.isArray(base) ? Object.assign({}, base) : {};
|
|
38
|
+
for (const [key, value] of Object.entries(patch)) {
|
|
39
|
+
result[key] = mergeStreamObject(result[key], value);
|
|
40
|
+
}
|
|
41
|
+
return result;
|
|
42
|
+
}
|
|
43
|
+
return patch;
|
|
44
|
+
};
|
|
45
|
+
const applyStreamChunk = (current, chunk) => {
|
|
46
|
+
if (!chunk || typeof chunk !== 'object') {
|
|
47
|
+
return { next: current, updated: false };
|
|
48
|
+
}
|
|
49
|
+
if (chunk.object && typeof chunk.object === 'object') {
|
|
50
|
+
return { next: chunk.object, updated: true };
|
|
51
|
+
}
|
|
52
|
+
if (chunk.delta && typeof chunk.delta === 'object') {
|
|
53
|
+
return { next: mergeStreamObject(current, chunk.delta), updated: true };
|
|
54
|
+
}
|
|
55
|
+
if (chunk.value && typeof chunk.value === 'object') {
|
|
56
|
+
return { next: mergeStreamObject(current, chunk.value), updated: true };
|
|
57
|
+
}
|
|
58
|
+
return { next: current, updated: false };
|
|
59
|
+
};
|
|
60
|
+
export function streamObject(backendUrl, request, onResult, token) {
|
|
25
61
|
return __awaiter(this, void 0, void 0, function* () {
|
|
26
|
-
const messageId = Math.random().toString(36).substring(3);
|
|
27
62
|
const response = yield fetch(`${backendUrl}/ai/llm-object`, {
|
|
28
63
|
method: 'POST',
|
|
29
64
|
body: JSON.stringify({
|
|
30
65
|
stream: true,
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
66
|
+
tool: request.tool,
|
|
67
|
+
behaviour: request.behaviour,
|
|
68
|
+
instructions: request.instructions,
|
|
34
69
|
}),
|
|
35
70
|
headers: { Authorization: `Bearer ${token}`, 'Content-Type': 'application/json' },
|
|
36
71
|
});
|
|
72
|
+
if (!response.ok) {
|
|
73
|
+
console.error('Failed to stream object:', response.status, response.statusText);
|
|
74
|
+
return;
|
|
75
|
+
}
|
|
37
76
|
if (!response.body) {
|
|
38
77
|
console.error('No response body.');
|
|
39
78
|
return;
|
|
40
79
|
}
|
|
41
80
|
const reader = response.body.getReader();
|
|
42
81
|
const decoder = new TextDecoder('utf-8');
|
|
43
|
-
let content = '';
|
|
44
82
|
let done = false;
|
|
45
|
-
|
|
83
|
+
let currentObject = {};
|
|
46
84
|
while (!done) {
|
|
47
|
-
const { value } = yield reader.read();
|
|
85
|
+
const { value, done: readerDone } = yield reader.read();
|
|
48
86
|
if (value) {
|
|
49
87
|
const chunk = decoder.decode(value, { stream: true });
|
|
50
|
-
const lines = chunk.split('\n').filter((line) => line.trim()
|
|
88
|
+
const lines = chunk.split('\n').filter((line) => line.trim());
|
|
51
89
|
for (const line of lines) {
|
|
52
|
-
const
|
|
53
|
-
|
|
54
|
-
// console.log("data: ", { line, data, command });
|
|
55
|
-
if (command === '0') {
|
|
56
|
-
content += data;
|
|
57
|
-
// console.log("AI response:", content);
|
|
58
|
-
//content \n\n should be real line break when message is displayed
|
|
59
|
-
onResponse(messageId, content.replace(/\\n/g, '\n').replace(/\\+"/g, '"'), false);
|
|
60
|
-
}
|
|
61
|
-
else if (command === 'd') {
|
|
62
|
-
// console.log("AI usage:", JSON.parse(line.substring(2)));
|
|
90
|
+
const dataStr = line.substring(5).trim();
|
|
91
|
+
if (dataStr === '[DONE]') {
|
|
63
92
|
done = true;
|
|
64
93
|
break;
|
|
65
94
|
}
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
// console.log("tools", tools);
|
|
69
|
-
toolInvocations.push(JSON.parse(line.substring(2)));
|
|
70
|
-
}
|
|
95
|
+
currentObject = JSON.parse(dataStr);
|
|
96
|
+
onResult(currentObject, true);
|
|
71
97
|
}
|
|
72
98
|
}
|
|
99
|
+
if (readerDone) {
|
|
100
|
+
done = true;
|
|
101
|
+
}
|
|
73
102
|
}
|
|
74
|
-
|
|
103
|
+
onResult(currentObject, false);
|
|
75
104
|
});
|
|
76
105
|
}
|
package/dist/index.d.ts
CHANGED
|
@@ -9,7 +9,7 @@ export { setupWorker } from './worker/WorkerSetup';
|
|
|
9
9
|
export { AudioController } from './controller/AudioController';
|
|
10
10
|
export { Translator } from './controller/TranslationController';
|
|
11
11
|
export type { TOptions } from 'i18next';
|
|
12
|
-
export type { SharedContent, BasicSharedContent } from './plugin/module/SharedContentController';
|
|
12
|
+
export type { SharedContent, BasicSharedContent, ContentStatus } from './plugin/module/SharedContentController';
|
|
13
13
|
export type { Exercise } from './plugin/module/ExerciseModule';
|
|
14
14
|
export type { UserInfo, Language, UserRole } from './controller/SettingsController';
|
|
15
15
|
export type { Message, ToolInvocation } from './controller/AIController';
|
|
@@ -46,4 +46,10 @@ export declare class AIModule {
|
|
|
46
46
|
* @returns The generated object.
|
|
47
47
|
*/
|
|
48
48
|
getObject<T = any>(request: ObjectRequest): Promise<T>;
|
|
49
|
+
/**
|
|
50
|
+
* Generate a streamed structured object from a request using AI.
|
|
51
|
+
* @param request The object generation request.
|
|
52
|
+
* @param onResult Callback for each result chunk.
|
|
53
|
+
*/
|
|
54
|
+
getStreamedObject<T = any>(request: ObjectRequest, onResult: (result: T, isLoading: boolean) => void): Promise<void>;
|
|
49
55
|
}
|
|
@@ -8,7 +8,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
|
|
|
8
8
|
});
|
|
9
9
|
};
|
|
10
10
|
import { generateText, streamChatGPT } from '../../controller/AIController';
|
|
11
|
-
import { generateObject } from '../../controller/ObjectController';
|
|
11
|
+
import { generateObject, streamObject } from '../../controller/ObjectController';
|
|
12
12
|
import { getSTTResponse, getTTSResponse } from '../../controller/VoiceController';
|
|
13
13
|
/**
|
|
14
14
|
* Controller for AI-related operations.
|
|
@@ -78,4 +78,14 @@ export class AIModule {
|
|
|
78
78
|
return generateObject(this.backendUrl, request, this.token);
|
|
79
79
|
});
|
|
80
80
|
}
|
|
81
|
+
/**
|
|
82
|
+
* Generate a streamed structured object from a request using AI.
|
|
83
|
+
* @param request The object generation request.
|
|
84
|
+
* @param onResult Callback for each result chunk.
|
|
85
|
+
*/
|
|
86
|
+
getStreamedObject(request, onResult) {
|
|
87
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
88
|
+
return streamObject(this.backendUrl, request, onResult, this.token);
|
|
89
|
+
});
|
|
90
|
+
}
|
|
81
91
|
}
|
|
@@ -2,11 +2,12 @@ import { ObjectTool } from '../../fromRimori/PluginTypes';
|
|
|
2
2
|
import { SupabaseClient } from '../CommunicationHandler';
|
|
3
3
|
import { RimoriClient } from '../RimoriClient';
|
|
4
4
|
export type SharedContent<T> = BasicSharedContent & T;
|
|
5
|
+
export type ContentStatus = 'featured' | 'community' | 'unverified';
|
|
5
6
|
export interface BasicSharedContent {
|
|
6
7
|
id: string;
|
|
7
8
|
title: string;
|
|
8
9
|
keywords: string[];
|
|
9
|
-
|
|
10
|
+
content_status: ContentStatus;
|
|
10
11
|
created_by: string;
|
|
11
12
|
created_at: string;
|
|
12
13
|
guild_id: string | null;
|
|
@@ -2,3 +2,11 @@ export type LanguageLevel = 'Pre-A1' | 'A1' | 'A2' | 'B1' | 'B2' | 'C1' | 'C2' |
|
|
|
2
2
|
export declare function getDifficultyLevel(difficulty: LanguageLevel): number;
|
|
3
3
|
export declare function getDifficultyLabel(difficulty: number): LanguageLevel;
|
|
4
4
|
export declare function getNeighborDifficultyLevel(difficulty: LanguageLevel, difficultyAdjustment: number): LanguageLevel;
|
|
5
|
+
/**
|
|
6
|
+
* Compares two LanguageLevel values to determine their relative order.
|
|
7
|
+
* Returns:
|
|
8
|
+
* - negative number if level1 < level2
|
|
9
|
+
* - 0 if level1 === level2
|
|
10
|
+
* - positive number if level1 > level2
|
|
11
|
+
*/
|
|
12
|
+
export declare function compareLanguageLevels(level1: LanguageLevel, level2: LanguageLevel): number;
|
|
@@ -8,3 +8,13 @@ export function getDifficultyLabel(difficulty) {
|
|
|
8
8
|
export function getNeighborDifficultyLevel(difficulty, difficultyAdjustment) {
|
|
9
9
|
return getDifficultyLabel(getDifficultyLevel(difficulty) + difficultyAdjustment - 1);
|
|
10
10
|
}
|
|
11
|
+
/**
|
|
12
|
+
* Compares two LanguageLevel values to determine their relative order.
|
|
13
|
+
* Returns:
|
|
14
|
+
* - negative number if level1 < level2
|
|
15
|
+
* - 0 if level1 === level2
|
|
16
|
+
* - positive number if level1 > level2
|
|
17
|
+
*/
|
|
18
|
+
export function compareLanguageLevels(level1, level2) {
|
|
19
|
+
return getDifficultyLevel(level1) - getDifficultyLevel(level2);
|
|
20
|
+
}
|