@rimori/client 2.5.32 → 2.5.33
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/scripts/init/dev-registration.js +118 -136
- package/dist/cli/scripts/init/main.js +116 -127
- package/dist/cli/scripts/init/package-setup.js +15 -2
- package/dist/cli/scripts/release/detect-translation-languages.js +24 -35
- package/dist/cli/scripts/release/release-config-upload.js +87 -100
- package/dist/cli/scripts/release/release-db-update.js +70 -81
- package/dist/cli/scripts/release/release-file-upload.js +75 -91
- package/dist/cli/scripts/release/release-prompts-upload.js +60 -72
- package/dist/cli/scripts/release/release.js +20 -31
- package/dist/controller/AccomplishmentController.js +12 -12
- package/dist/controller/AudioController.js +15 -33
- package/dist/controller/TranslationController.js +108 -118
- package/dist/fromRimori/EventBus.js +20 -31
- package/dist/plugin/CommunicationHandler.js +73 -81
- package/dist/plugin/Logger.js +71 -83
- package/dist/plugin/RimoriClient.js +31 -31
- package/dist/plugin/StandaloneClient.js +81 -98
- package/dist/plugin/TTS/ChunkedAudioPlayer.js +31 -41
- package/dist/plugin/TTS/MessageSender.js +28 -37
- package/dist/plugin/module/AIModule.js +215 -237
- package/dist/plugin/module/DbModule.js +22 -31
- package/dist/plugin/module/EventModule.js +23 -32
- package/dist/plugin/module/ExerciseModule.js +42 -56
- package/dist/plugin/module/PluginModule.js +97 -106
- package/dist/plugin/module/SharedContentController.js +170 -207
- package/dist/plugin/module/StorageModule.js +18 -29
- package/dist/worker/WorkerSetup.js +23 -34
- package/package.json +1 -1
|
@@ -1,32 +1,12 @@
|
|
|
1
|
-
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
2
|
-
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
3
|
-
return new (P || (P = Promise))(function (resolve, reject) {
|
|
4
|
-
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
5
|
-
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
6
|
-
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
7
|
-
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
8
|
-
});
|
|
9
|
-
};
|
|
10
1
|
/**
|
|
11
2
|
* Controller for AI-related operations.
|
|
12
3
|
* Provides access to text generation, voice synthesis, and object generation.
|
|
13
4
|
*/
|
|
14
5
|
export class AIModule {
|
|
6
|
+
controller;
|
|
7
|
+
sessionTokenId = null;
|
|
8
|
+
onRateLimitedCb;
|
|
15
9
|
constructor(controller) {
|
|
16
|
-
this.sessionTokenId = null;
|
|
17
|
-
/** Exercise session management. */
|
|
18
|
-
this.session = {
|
|
19
|
-
/** Returns the current exercise session token ID (null if no active session). */
|
|
20
|
-
get: () => this.sessionTokenId,
|
|
21
|
-
/** Sets the session token ID. */
|
|
22
|
-
set: (id) => {
|
|
23
|
-
this.sessionTokenId = id;
|
|
24
|
-
},
|
|
25
|
-
/** Clears the stored session token. */
|
|
26
|
-
clear: () => {
|
|
27
|
-
this.sessionTokenId = null;
|
|
28
|
-
},
|
|
29
|
-
};
|
|
30
10
|
this.controller = controller;
|
|
31
11
|
}
|
|
32
12
|
/**
|
|
@@ -43,6 +23,19 @@ export class AIModule {
|
|
|
43
23
|
}
|
|
44
24
|
return name;
|
|
45
25
|
}
|
|
26
|
+
/** Exercise session management. */
|
|
27
|
+
session = {
|
|
28
|
+
/** Returns the current exercise session token ID (null if no active session). */
|
|
29
|
+
get: () => this.sessionTokenId,
|
|
30
|
+
/** Sets the session token ID. */
|
|
31
|
+
set: (id) => {
|
|
32
|
+
this.sessionTokenId = id;
|
|
33
|
+
},
|
|
34
|
+
/** Clears the stored session token. */
|
|
35
|
+
clear: () => {
|
|
36
|
+
this.sessionTokenId = null;
|
|
37
|
+
},
|
|
38
|
+
};
|
|
46
39
|
/** Registers a callback invoked whenever a 429 rate-limit response is received. */
|
|
47
40
|
setOnRateLimited(cb) {
|
|
48
41
|
this.onRateLimitedCb = cb;
|
|
@@ -56,18 +49,16 @@ export class AIModule {
|
|
|
56
49
|
* @param params.variables Variables for the server-side prompt template.
|
|
57
50
|
* @returns The generated text.
|
|
58
51
|
*/
|
|
59
|
-
getText(params) {
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
variables,
|
|
68
|
-
});
|
|
69
|
-
return result;
|
|
52
|
+
async getText(params) {
|
|
53
|
+
const { messages, tools, cache = false, prompt, variables } = params;
|
|
54
|
+
const { result } = await this.streamObject({
|
|
55
|
+
cache,
|
|
56
|
+
tools,
|
|
57
|
+
messages,
|
|
58
|
+
prompt,
|
|
59
|
+
variables,
|
|
70
60
|
});
|
|
61
|
+
return result;
|
|
71
62
|
}
|
|
72
63
|
/**
|
|
73
64
|
* Stream text generation from messages using AI.
|
|
@@ -78,21 +69,19 @@ export class AIModule {
|
|
|
78
69
|
* @param params.prompt Server-side prompt name (e.g. 'writing.analysis').
|
|
79
70
|
* @param params.variables Variables for the server-side prompt template.
|
|
80
71
|
*/
|
|
81
|
-
getStreamedText(params) {
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
onResult: ({ result }) => onMessage(messageId, result, false),
|
|
92
|
-
});
|
|
93
|
-
onMessage(messageId, result, true);
|
|
94
|
-
return result;
|
|
72
|
+
async getStreamedText(params) {
|
|
73
|
+
const { messages, onMessage, tools, cache = false, prompt, variables, } = params;
|
|
74
|
+
const messageId = Math.random().toString(36).substring(3);
|
|
75
|
+
const { result } = await this.streamObject({
|
|
76
|
+
cache,
|
|
77
|
+
tools,
|
|
78
|
+
messages,
|
|
79
|
+
prompt,
|
|
80
|
+
variables,
|
|
81
|
+
onResult: ({ result }) => onMessage(messageId, result, false),
|
|
95
82
|
});
|
|
83
|
+
onMessage(messageId, result, true);
|
|
84
|
+
return result;
|
|
96
85
|
}
|
|
97
86
|
/**
|
|
98
87
|
* Generate voice audio from text using AI.
|
|
@@ -108,26 +97,23 @@ export class AIModule {
|
|
|
108
97
|
* from the TTS backend while keeping the caller's workflow intact.
|
|
109
98
|
* A warning is logged to the console in this case.
|
|
110
99
|
*/
|
|
111
|
-
getVoice(
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
}),
|
|
129
|
-
}).then((r) => r.blob());
|
|
130
|
-
});
|
|
100
|
+
async getVoice(text, voice = 'alloy', speed = 1, language, cache = false, instructions) {
|
|
101
|
+
if (!text.trim().length) {
|
|
102
|
+
console.warn('[rimori-client] getVoice called with empty text — skipping TTS request and returning empty Blob.');
|
|
103
|
+
return new Blob([], { type: 'audio/mpeg' });
|
|
104
|
+
}
|
|
105
|
+
return await this.controller.fetchBackend('/voice/tts', {
|
|
106
|
+
method: 'POST',
|
|
107
|
+
body: JSON.stringify({
|
|
108
|
+
input: text,
|
|
109
|
+
voice,
|
|
110
|
+
speed,
|
|
111
|
+
language,
|
|
112
|
+
cache,
|
|
113
|
+
instructions,
|
|
114
|
+
session_token_id: this.sessionTokenId ?? undefined,
|
|
115
|
+
}),
|
|
116
|
+
}).then((r) => r.blob());
|
|
131
117
|
}
|
|
132
118
|
/**
|
|
133
119
|
* Convert voice audio to text using AI.
|
|
@@ -135,25 +121,23 @@ export class AIModule {
|
|
|
135
121
|
* @param language Optional language for the voice.
|
|
136
122
|
* @returns The transcribed text.
|
|
137
123
|
*/
|
|
138
|
-
getTextFromVoice(file, language) {
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
return r.text;
|
|
156
|
-
});
|
|
124
|
+
async getTextFromVoice(file, language) {
|
|
125
|
+
const formData = new FormData();
|
|
126
|
+
formData.append('file', file);
|
|
127
|
+
if (language) {
|
|
128
|
+
formData.append('language', language.code);
|
|
129
|
+
}
|
|
130
|
+
if (this.sessionTokenId) {
|
|
131
|
+
formData.append('session_token_id', this.sessionTokenId);
|
|
132
|
+
}
|
|
133
|
+
return await this.controller.fetchBackend('/voice/stt', {
|
|
134
|
+
method: 'POST',
|
|
135
|
+
body: formData,
|
|
136
|
+
})
|
|
137
|
+
.then((r) => r.json())
|
|
138
|
+
.then((r) => {
|
|
139
|
+
// console.log("STT response: ", r);
|
|
140
|
+
return r.text;
|
|
157
141
|
});
|
|
158
142
|
}
|
|
159
143
|
/**
|
|
@@ -164,16 +148,14 @@ export class AIModule {
|
|
|
164
148
|
* @param request.variables Variables for the server-side prompt template.
|
|
165
149
|
* @returns The generated object.
|
|
166
150
|
*/
|
|
167
|
-
getObject(params) {
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
variables,
|
|
176
|
-
});
|
|
151
|
+
async getObject(params) {
|
|
152
|
+
const { cache = false, tools = [], prompt, variables } = params;
|
|
153
|
+
return await this.streamObject({
|
|
154
|
+
messages: [],
|
|
155
|
+
cache,
|
|
156
|
+
tools,
|
|
157
|
+
prompt,
|
|
158
|
+
variables,
|
|
177
159
|
});
|
|
178
160
|
}
|
|
179
161
|
/**
|
|
@@ -184,162 +166,158 @@ export class AIModule {
|
|
|
184
166
|
* @param request.prompt Server-side prompt name (e.g. 'writing.analysis').
|
|
185
167
|
* @param request.variables Variables for the server-side prompt template.
|
|
186
168
|
*/
|
|
187
|
-
getStreamedObject(params) {
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
variables,
|
|
197
|
-
});
|
|
169
|
+
async getStreamedObject(params) {
|
|
170
|
+
const { onResult, cache = false, tools = [], prompt, variables } = params;
|
|
171
|
+
return await this.streamObject({
|
|
172
|
+
messages: [],
|
|
173
|
+
onResult,
|
|
174
|
+
cache,
|
|
175
|
+
tools,
|
|
176
|
+
prompt,
|
|
177
|
+
variables,
|
|
198
178
|
});
|
|
199
179
|
}
|
|
200
|
-
streamObject(params) {
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
}
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
}
|
|
226
|
-
throw new Error(`Failed to stream object: ${response.status} ${response.statusText}`);
|
|
180
|
+
async streamObject(params) {
|
|
181
|
+
const { messages, onResult = () => null, cache = false, tools = [], prompt, variables, } = params;
|
|
182
|
+
const chatMessages = messages.map((message, index) => ({
|
|
183
|
+
...message,
|
|
184
|
+
id: `${index + 1}`,
|
|
185
|
+
}));
|
|
186
|
+
const payload = {
|
|
187
|
+
cache,
|
|
188
|
+
tools,
|
|
189
|
+
stream: true,
|
|
190
|
+
messages: chatMessages,
|
|
191
|
+
session_token_id: this.sessionTokenId ?? undefined,
|
|
192
|
+
};
|
|
193
|
+
if (prompt) {
|
|
194
|
+
payload.prompt = { name: this.resolvePromptName(prompt), variables: variables ?? {} };
|
|
195
|
+
}
|
|
196
|
+
const response = await this.controller.fetchBackend('/ai/llm', {
|
|
197
|
+
method: 'POST',
|
|
198
|
+
body: JSON.stringify(payload),
|
|
199
|
+
});
|
|
200
|
+
if (!response.ok) {
|
|
201
|
+
if (response.status === 429) {
|
|
202
|
+
const body = await response.json().catch(() => ({}));
|
|
203
|
+
const remaining = body.exercises_remaining ?? 0;
|
|
204
|
+
this.onRateLimitedCb?.(remaining);
|
|
205
|
+
throw new Error(`Rate limit exceeded: ${body.error ?? 'Daily exercise limit reached'}. exercises_remaining: ${remaining}`);
|
|
227
206
|
}
|
|
228
|
-
|
|
229
|
-
|
|
207
|
+
throw new Error(`Failed to stream object: ${response.status} ${response.statusText}`);
|
|
208
|
+
}
|
|
209
|
+
if (!response.body) {
|
|
210
|
+
throw new Error('No response body.');
|
|
211
|
+
}
|
|
212
|
+
const reader = response.body.getReader();
|
|
213
|
+
const decoder = new TextDecoder('utf-8');
|
|
214
|
+
let currentObject = {};
|
|
215
|
+
// Buffer for SSE lines that are split across network chunks.
|
|
216
|
+
// TCP/IP does not guarantee that each `read()` call delivers a complete
|
|
217
|
+
// logical line. For example, the `token:` line carrying the session token
|
|
218
|
+
// may arrive as two separate chunks:
|
|
219
|
+
// chunk 1 → `token: {"token_id":`
|
|
220
|
+
// chunk 2 → `"abc123"}\n`
|
|
221
|
+
// Without buffering, `JSON.parse` would throw on the partial line and the
|
|
222
|
+
// session token would be silently discarded, causing the next LLM call to
|
|
223
|
+
// start without a session (triggering an unnecessary extra round-trip via
|
|
224
|
+
// `session.ensure()`). By keeping the incomplete tail in `lineBuffer` and
|
|
225
|
+
// prepending it to the next chunk we always process whole lines.
|
|
226
|
+
let lineBuffer = '';
|
|
227
|
+
let isLoading = true;
|
|
228
|
+
while (isLoading) {
|
|
229
|
+
//wait 50ms to not overload the CPU
|
|
230
|
+
await new Promise((resolve) => setTimeout(resolve, 30));
|
|
231
|
+
const { value, done: readerDone } = await reader.read();
|
|
232
|
+
if (readerDone) {
|
|
233
|
+
isLoading = false;
|
|
234
|
+
onResult(currentObject, false);
|
|
235
|
+
return currentObject;
|
|
230
236
|
}
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
//
|
|
236
|
-
//
|
|
237
|
-
// may
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
yield new Promise((resolve) => setTimeout(resolve, 30));
|
|
250
|
-
const { value, done: readerDone } = yield reader.read();
|
|
251
|
-
if (readerDone) {
|
|
252
|
-
isLoading = false;
|
|
253
|
-
onResult(currentObject, false);
|
|
254
|
-
return currentObject;
|
|
255
|
-
}
|
|
256
|
-
//the check needs to be behind readerDone because in closed connections the value is undefined
|
|
257
|
-
if (!value)
|
|
258
|
-
continue;
|
|
259
|
-
const chunk = decoder.decode(value, { stream: true });
|
|
260
|
-
// Prepend any incomplete line left over from the previous chunk, then
|
|
261
|
-
// split on newlines. `parts.pop()` removes (and saves) the last element
|
|
262
|
-
// which may be an incomplete line if the chunk did not end with '\n'.
|
|
263
|
-
const combined = lineBuffer + chunk;
|
|
264
|
-
const parts = combined.split('\n');
|
|
265
|
-
lineBuffer = (_e = parts.pop()) !== null && _e !== void 0 ? _e : '';
|
|
266
|
-
const lines = parts.filter((line) => line.trim());
|
|
267
|
-
for (const line of lines) {
|
|
268
|
-
// Handle token: line (session token issued by backend on first AI call)
|
|
269
|
-
if (line.startsWith('token:')) {
|
|
270
|
-
try {
|
|
271
|
-
const tokenData = JSON.parse(line.slice(6).trim());
|
|
272
|
-
if (tokenData.token_id) {
|
|
273
|
-
this.sessionTokenId = tokenData.token_id;
|
|
274
|
-
}
|
|
275
|
-
}
|
|
276
|
-
catch (_f) {
|
|
277
|
-
console.error('Failed to parse token: line', line);
|
|
278
|
-
}
|
|
279
|
-
continue;
|
|
280
|
-
}
|
|
281
|
-
// Handle debug: line (prompt resolution debug info, dev/local only)
|
|
282
|
-
if (line.startsWith('debug:')) {
|
|
283
|
-
try {
|
|
284
|
-
const debug = JSON.parse(line.slice(6).trim());
|
|
285
|
-
console.group(`[Rimori Prompt] ${debug.promptName}`);
|
|
286
|
-
console.log('System prompt:\n', debug.system);
|
|
287
|
-
console.log('User prompt:\n', debug.user);
|
|
288
|
-
console.log('Variables:', debug.variables);
|
|
289
|
-
console.groupEnd();
|
|
290
|
-
}
|
|
291
|
-
catch (_g) {
|
|
292
|
-
// Ignore malformed debug lines
|
|
237
|
+
//the check needs to be behind readerDone because in closed connections the value is undefined
|
|
238
|
+
if (!value)
|
|
239
|
+
continue;
|
|
240
|
+
const chunk = decoder.decode(value, { stream: true });
|
|
241
|
+
// Prepend any incomplete line left over from the previous chunk, then
|
|
242
|
+
// split on newlines. `parts.pop()` removes (and saves) the last element
|
|
243
|
+
// which may be an incomplete line if the chunk did not end with '\n'.
|
|
244
|
+
const combined = lineBuffer + chunk;
|
|
245
|
+
const parts = combined.split('\n');
|
|
246
|
+
lineBuffer = parts.pop() ?? '';
|
|
247
|
+
const lines = parts.filter((line) => line.trim());
|
|
248
|
+
for (const line of lines) {
|
|
249
|
+
// Handle token: line (session token issued by backend on first AI call)
|
|
250
|
+
if (line.startsWith('token:')) {
|
|
251
|
+
try {
|
|
252
|
+
const tokenData = JSON.parse(line.slice(6).trim());
|
|
253
|
+
if (tokenData.token_id) {
|
|
254
|
+
this.sessionTokenId = tokenData.token_id;
|
|
293
255
|
}
|
|
294
|
-
continue;
|
|
295
256
|
}
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
if (dataStr === '[DONE]') {
|
|
299
|
-
isLoading = false;
|
|
300
|
-
onResult(currentObject, false);
|
|
301
|
-
return currentObject;
|
|
257
|
+
catch {
|
|
258
|
+
console.error('Failed to parse token: line', line);
|
|
302
259
|
}
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
260
|
+
continue;
|
|
261
|
+
}
|
|
262
|
+
// Handle debug: line (prompt resolution debug info, dev/local only)
|
|
263
|
+
if (line.startsWith('debug:')) {
|
|
264
|
+
try {
|
|
265
|
+
const debug = JSON.parse(line.slice(6).trim());
|
|
266
|
+
console.group(`[Rimori Prompt] ${debug.promptName}`);
|
|
267
|
+
console.log('System prompt:\n', debug.system);
|
|
268
|
+
console.log('User prompt:\n', debug.user);
|
|
269
|
+
console.log('Variables:', debug.variables);
|
|
270
|
+
console.groupEnd();
|
|
306
271
|
}
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
const tool = tools.find((tool) => tool.name === toolName);
|
|
310
|
-
if (tool && tool.execute) {
|
|
311
|
-
const result = yield tool.execute(args);
|
|
312
|
-
// Send the result to the backend
|
|
313
|
-
yield this.sendToolResult(toolCallId, result);
|
|
314
|
-
}
|
|
315
|
-
else if (tool && !tool.execute) {
|
|
316
|
-
console.error('Tool found but has no execute function:', toolName);
|
|
317
|
-
}
|
|
318
|
-
else {
|
|
319
|
-
console.error('Tool not found:', toolName);
|
|
320
|
-
}
|
|
272
|
+
catch {
|
|
273
|
+
// Ignore malformed debug lines
|
|
321
274
|
}
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
275
|
+
continue;
|
|
276
|
+
}
|
|
277
|
+
const command = line.substring(0, 5);
|
|
278
|
+
const dataStr = line.substring(5).trim();
|
|
279
|
+
if (dataStr === '[DONE]') {
|
|
280
|
+
isLoading = false;
|
|
281
|
+
onResult(currentObject, false);
|
|
282
|
+
return currentObject;
|
|
283
|
+
}
|
|
284
|
+
if (command === 'data:') {
|
|
285
|
+
currentObject = JSON.parse(dataStr);
|
|
286
|
+
onResult(currentObject, true);
|
|
287
|
+
}
|
|
288
|
+
else if (command === 'tool:') {
|
|
289
|
+
const { toolCallId, toolName, args } = JSON.parse(dataStr);
|
|
290
|
+
const tool = tools.find((tool) => tool.name === toolName);
|
|
291
|
+
if (tool && tool.execute) {
|
|
292
|
+
const result = await tool.execute(args);
|
|
293
|
+
// Send the result to the backend
|
|
294
|
+
await this.sendToolResult(toolCallId, result);
|
|
325
295
|
}
|
|
326
|
-
else if (
|
|
327
|
-
|
|
296
|
+
else if (tool && !tool.execute) {
|
|
297
|
+
console.error('Tool found but has no execute function:', toolName);
|
|
328
298
|
}
|
|
329
299
|
else {
|
|
330
|
-
console.error('
|
|
300
|
+
console.error('Tool not found:', toolName);
|
|
331
301
|
}
|
|
332
302
|
}
|
|
303
|
+
else if (command === 'error') {
|
|
304
|
+
//error has 5 letters + the colon so we need to remove one character of the data string to get the error message
|
|
305
|
+
console.error('Error:', dataStr.substring(1));
|
|
306
|
+
}
|
|
307
|
+
else if (command === 'info:') {
|
|
308
|
+
//ignore info messages
|
|
309
|
+
}
|
|
310
|
+
else {
|
|
311
|
+
console.error('Unknown stream data:', line);
|
|
312
|
+
}
|
|
333
313
|
}
|
|
334
|
-
|
|
335
|
-
|
|
314
|
+
}
|
|
315
|
+
return currentObject;
|
|
336
316
|
}
|
|
337
|
-
sendToolResult(toolCallId, result) {
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
body: JSON.stringify({ toolCallId, result: result !== null && result !== void 0 ? result : '[DONE]' }),
|
|
342
|
-
});
|
|
317
|
+
async sendToolResult(toolCallId, result) {
|
|
318
|
+
await this.controller.fetchBackend('/ai/llm/tool_result', {
|
|
319
|
+
method: 'POST',
|
|
320
|
+
body: JSON.stringify({ toolCallId, result: result ?? '[DONE]' }),
|
|
343
321
|
});
|
|
344
322
|
}
|
|
345
323
|
}
|
|
@@ -1,13 +1,8 @@
|
|
|
1
|
-
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
2
|
-
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
3
|
-
return new (P || (P = Promise))(function (resolve, reject) {
|
|
4
|
-
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
5
|
-
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
6
|
-
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
7
|
-
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
8
|
-
});
|
|
9
|
-
};
|
|
10
1
|
export class DbModule {
|
|
2
|
+
supabase;
|
|
3
|
+
communicationHandler;
|
|
4
|
+
tablePrefix;
|
|
5
|
+
schema;
|
|
11
6
|
constructor(supabase, communicationHandler, info) {
|
|
12
7
|
this.supabase = supabase;
|
|
13
8
|
this.communicationHandler = communicationHandler;
|
|
@@ -63,18 +58,16 @@ export class DbModule {
|
|
|
63
58
|
* @param entryId The UUID of the entry to update
|
|
64
59
|
* @param publicity The desired publicity level
|
|
65
60
|
*/
|
|
66
|
-
setPublicity(table, entryId, publicity) {
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
}),
|
|
77
|
-
});
|
|
61
|
+
async setPublicity(table, entryId, publicity) {
|
|
62
|
+
const tableName = this.getTableName(table);
|
|
63
|
+
await this.communicationHandler.fetchBackend('/db-entry/publicity', {
|
|
64
|
+
method: 'POST',
|
|
65
|
+
body: JSON.stringify({
|
|
66
|
+
table_name: tableName,
|
|
67
|
+
schema: this.schema,
|
|
68
|
+
entry_id: entryId,
|
|
69
|
+
publicity,
|
|
70
|
+
}),
|
|
78
71
|
});
|
|
79
72
|
}
|
|
80
73
|
/**
|
|
@@ -83,16 +76,14 @@ export class DbModule {
|
|
|
83
76
|
* @param params Search parameters
|
|
84
77
|
* @returns Matching rows sorted by similarity
|
|
85
78
|
*/
|
|
86
|
-
vectorSearch(params) {
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
body: JSON.stringify(params),
|
|
91
|
-
});
|
|
92
|
-
if (!response.ok) {
|
|
93
|
-
throw new Error(`Vector search failed: ${response.statusText}`);
|
|
94
|
-
}
|
|
95
|
-
return yield response.json();
|
|
79
|
+
async vectorSearch(params) {
|
|
80
|
+
const response = await this.communicationHandler.fetchBackend('/plugin-search/vector-search', {
|
|
81
|
+
method: 'POST',
|
|
82
|
+
body: JSON.stringify(params),
|
|
96
83
|
});
|
|
84
|
+
if (!response.ok) {
|
|
85
|
+
throw new Error(`Vector search failed: ${response.statusText}`);
|
|
86
|
+
}
|
|
87
|
+
return await response.json();
|
|
97
88
|
}
|
|
98
89
|
}
|