@smythos/sre 1.7.18 → 1.7.40
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/index.js +120 -82
- package/dist/index.js.map +1 -1
- package/dist/types/Components/DataSourceIndexer.class.d.ts +4 -12
- package/dist/types/Components/GenAILLM.class.d.ts +5 -5
- package/dist/types/Components/RAG/DataSourceCleaner.class.d.ts +37 -0
- package/dist/types/Components/RAG/DataSourceComponent.class.d.ts +30 -0
- package/dist/types/Components/RAG/DataSourceIndexer.class.d.ts +14 -0
- package/dist/types/Components/RAG/DataSourceLookup.class.d.ts +36 -0
- package/dist/types/Components/index.d.ts +3 -3
- package/dist/types/helpers/Conversation.helper.d.ts +3 -0
- package/dist/types/index.d.ts +3 -3
- package/dist/types/subsystems/IO/VectorDB.service/connectors/MilvusVectorDB.class.d.ts +1 -0
- package/dist/types/subsystems/IO/VectorDB.service/connectors/PineconeVectorDB.class.d.ts +11 -4
- package/dist/types/subsystems/IO/VectorDB.service/embed/index.d.ts +5 -0
- package/dist/types/subsystems/LLMManager/LLM.inference.d.ts +10 -3
- package/dist/types/subsystems/LLMManager/LLM.service/connectors/GoogleAI.class.d.ts +4 -2
- package/dist/types/subsystems/LLMManager/ModelsProvider.service/connectors/JSONModelsProvider.class.d.ts +35 -0
- package/dist/types/subsystems/Security/Account.service/AccountConnector.d.ts +2 -2
- package/dist/types/subsystems/Security/ManagedVault.service/connectors/SecretManagerManagedVault.d.ts +10 -0
- package/dist/types/subsystems/Security/Vault.service/connectors/SecretsManager.class.d.ts +6 -2
- package/dist/types/types/LLM.types.d.ts +2 -0
- package/dist/types/types/VectorDB.types.d.ts +4 -0
- package/dist/types/utils/array.utils.d.ts +4 -0
- package/dist/types/utils/string.utils.d.ts +1 -0
- package/package.json +3 -3
- package/src/Components/APIEndpoint.class.ts +1 -6
- package/src/Components/Component.class.ts +14 -1
- package/src/Components/DataSourceIndexer.class.ts +148 -34
- package/src/Components/GenAILLM.class.ts +21 -11
- package/src/Components/RAG/DataSourceCleaner.class.ts +178 -0
- package/src/Components/RAG/DataSourceComponent.class.ts +111 -0
- package/src/Components/RAG/DataSourceIndexer.class.ts +254 -0
- package/src/Components/{DataSourceLookup.class.ts → RAG/DataSourceLookup.class.ts} +92 -3
- package/src/Components/ServerlessCode.class.ts +1 -4
- package/src/Components/index.ts +3 -3
- package/src/helpers/AWSLambdaCode.helper.ts +40 -45
- package/src/helpers/Conversation.helper.ts +14 -10
- package/src/helpers/S3Cache.helper.ts +2 -1
- package/src/index.ts +212 -212
- package/src/index.ts.bak +212 -212
- package/src/subsystems/IO/NKV.service/connectors/NKVRedis.class.ts +3 -1
- package/src/subsystems/IO/VectorDB.service/connectors/MilvusVectorDB.class.ts +145 -19
- package/src/subsystems/IO/VectorDB.service/connectors/PineconeVectorDB.class.ts +56 -22
- package/src/subsystems/IO/VectorDB.service/embed/GoogleEmbedding.ts +1 -0
- package/src/subsystems/IO/VectorDB.service/embed/OpenAIEmbedding.ts +2 -1
- package/src/subsystems/IO/VectorDB.service/embed/index.ts +18 -0
- package/src/subsystems/LLMManager/LLM.inference.ts +63 -47
- package/src/subsystems/LLMManager/LLM.service/connectors/Anthropic.class.ts +35 -10
- package/src/subsystems/LLMManager/LLM.service/connectors/Bedrock.class.ts +12 -4
- package/src/subsystems/LLMManager/LLM.service/connectors/Echo.class.ts +4 -4
- package/src/subsystems/LLMManager/LLM.service/connectors/GoogleAI.class.ts +105 -23
- package/src/subsystems/LLMManager/LLM.service/connectors/Groq.class.ts +17 -5
- package/src/subsystems/LLMManager/LLM.service/connectors/Ollama.class.ts +18 -3
- package/src/subsystems/LLMManager/LLM.service/connectors/Perplexity.class.ts +14 -5
- package/src/subsystems/LLMManager/LLM.service/connectors/VertexAI.class.ts +6 -4
- package/src/subsystems/LLMManager/LLM.service/connectors/openai/apiInterfaces/ChatCompletionsApiInterface.ts +5 -5
- package/src/subsystems/LLMManager/LLM.service/connectors/openai/apiInterfaces/ResponsesApiInterface.ts +8 -3
- package/src/subsystems/LLMManager/LLM.service/connectors/xAI.class.ts +9 -8
- package/src/subsystems/LLMManager/ModelsProvider.service/connectors/JSONModelsProvider.class.ts +126 -28
- package/src/subsystems/ObservabilityManager/Telemetry.service/connectors/OTel/OTel.class.ts +38 -6
- package/src/subsystems/Security/Account.service/AccountConnector.ts +3 -3
- package/src/subsystems/Security/ManagedVault.service/connectors/SecretManagerManagedVault.ts +111 -48
- package/src/subsystems/Security/Vault.service/connectors/SecretsManager.class.ts +41 -66
- package/src/types/LLM.types.ts +5 -0
- package/src/types/VectorDB.types.ts +4 -0
- package/src/utils/array.utils.ts +11 -0
- package/src/utils/base64.utils.ts +1 -1
- package/src/utils/string.utils.ts +3 -192
- package/src/Components/DataSourceCleaner.class.ts +0 -92
|
@@ -13,14 +13,30 @@ import { TLLMChatResponse, TLLMMessageRole, TLLMModel, TLLMParams } from '@sre/t
|
|
|
13
13
|
import { LLMConnector } from './LLM.service/LLMConnector';
|
|
14
14
|
import { IModelsProviderRequest, ModelsProviderConnector } from './ModelsProvider.service/ModelsProviderConnector';
|
|
15
15
|
|
|
16
|
-
const
|
|
16
|
+
const logger = Logger('LLMInference');
|
|
17
17
|
|
|
18
18
|
type TPromptParams = { query?: string; contextWindow?: any[]; files?: any[]; params: TLLMParams; onFallback?: (data: any) => void };
|
|
19
19
|
|
|
20
20
|
export class LLMInference {
|
|
21
|
-
private
|
|
22
|
-
|
|
23
|
-
|
|
21
|
+
private _model: string | TLLMModel;
|
|
22
|
+
public get model() {
|
|
23
|
+
return this._model;
|
|
24
|
+
}
|
|
25
|
+
public get modelId() {
|
|
26
|
+
return typeof this._model === 'string' ? this._model : this._model?.modelId;
|
|
27
|
+
}
|
|
28
|
+
private _llmConnector: LLMConnector;
|
|
29
|
+
public get llmConnector() {
|
|
30
|
+
return this._llmConnector;
|
|
31
|
+
}
|
|
32
|
+
private _modelProviderReq: IModelsProviderRequest;
|
|
33
|
+
public get modelProviderReq() {
|
|
34
|
+
return this._modelProviderReq;
|
|
35
|
+
}
|
|
36
|
+
private _llmProviderName: string;
|
|
37
|
+
public get llmProviderName() {
|
|
38
|
+
return this._llmProviderName;
|
|
39
|
+
}
|
|
24
40
|
public teamId?: string;
|
|
25
41
|
|
|
26
42
|
public static async getInstance(model: string | TLLMModel, candidate: AccessCandidate) {
|
|
@@ -34,18 +50,18 @@ export class LLMInference {
|
|
|
34
50
|
const llmInference = new LLMInference();
|
|
35
51
|
llmInference.teamId = teamId;
|
|
36
52
|
|
|
37
|
-
llmInference.
|
|
53
|
+
llmInference._modelProviderReq = modelsProvider.requester(candidate);
|
|
38
54
|
|
|
39
|
-
|
|
40
|
-
if (
|
|
41
|
-
llmInference.
|
|
55
|
+
llmInference._llmProviderName = await llmInference._modelProviderReq.getProvider(model);
|
|
56
|
+
if (llmInference._llmProviderName) {
|
|
57
|
+
llmInference._llmConnector = ConnectorService.getLLMConnector(llmInference._llmProviderName);
|
|
42
58
|
}
|
|
43
59
|
|
|
44
|
-
if (!llmInference.
|
|
45
|
-
|
|
60
|
+
if (!llmInference._llmConnector) {
|
|
61
|
+
logger.warn(`Model ${model} unavailable for team ${teamId}`);
|
|
46
62
|
}
|
|
47
63
|
|
|
48
|
-
llmInference.
|
|
64
|
+
llmInference._model = model;
|
|
49
65
|
|
|
50
66
|
return llmInference;
|
|
51
67
|
}
|
|
@@ -53,32 +69,32 @@ export class LLMInference {
|
|
|
53
69
|
public static user(candidate: AccessCandidate): any {}
|
|
54
70
|
|
|
55
71
|
public get connector(): LLMConnector {
|
|
56
|
-
return this.
|
|
72
|
+
return this._llmConnector;
|
|
57
73
|
}
|
|
58
74
|
|
|
59
75
|
public async prompt({ query, contextWindow, files, params, onFallback = () => {} }: TPromptParams, isInFallback: boolean = false) {
|
|
60
76
|
let messages = contextWindow || [];
|
|
61
77
|
|
|
62
78
|
if (query) {
|
|
63
|
-
const content = this.
|
|
79
|
+
const content = this._llmConnector.enhancePrompt(query, params);
|
|
64
80
|
messages.push({ role: TLLMMessageRole.User, content });
|
|
65
81
|
}
|
|
66
82
|
|
|
67
83
|
// Reset the model, since the fallback model may change — especially when using user custom models.
|
|
68
|
-
params.model = this.
|
|
84
|
+
params.model = this._model;
|
|
69
85
|
|
|
70
86
|
params.messages = messages;
|
|
71
87
|
params.files = files;
|
|
72
88
|
|
|
73
89
|
// If a fallback model is used, trigger the onFallback callback to notify the caller.
|
|
74
90
|
if (isInFallback && typeof onFallback === 'function') {
|
|
75
|
-
onFallback({ model: this.
|
|
91
|
+
onFallback({ model: this._model });
|
|
76
92
|
}
|
|
77
93
|
|
|
78
94
|
try {
|
|
79
|
-
let response: TLLMChatResponse = await this.
|
|
95
|
+
let response: TLLMChatResponse = await this._llmConnector.requester(AccessCandidate.agent(params.agentId)).request(params);
|
|
80
96
|
|
|
81
|
-
const result = this.
|
|
97
|
+
const result = this._llmConnector.postProcess(response?.content);
|
|
82
98
|
if (result.error) {
|
|
83
99
|
// If the model stopped before completing the response, this is usually due to output token limit reached.
|
|
84
100
|
if (response.finishReason !== 'stop') {
|
|
@@ -102,12 +118,12 @@ export class LLMInference {
|
|
|
102
118
|
}
|
|
103
119
|
} catch (fallbackError) {
|
|
104
120
|
// If fallback also failed, log it but continue to throw original error
|
|
105
|
-
|
|
121
|
+
logger.warn('Fallback also failed:', fallbackError);
|
|
106
122
|
}
|
|
107
123
|
}
|
|
108
124
|
|
|
109
125
|
// If fallback was not attempted or failed, throw the original error
|
|
110
|
-
|
|
126
|
+
logger.error('Error in chatRequest: ', error);
|
|
111
127
|
throw error;
|
|
112
128
|
}
|
|
113
129
|
}
|
|
@@ -116,23 +132,23 @@ export class LLMInference {
|
|
|
116
132
|
let messages = contextWindow || [];
|
|
117
133
|
|
|
118
134
|
if (query) {
|
|
119
|
-
const content = this.
|
|
135
|
+
const content = this._llmConnector.enhancePrompt(query, params);
|
|
120
136
|
messages.push({ role: TLLMMessageRole.User, content });
|
|
121
137
|
}
|
|
122
138
|
|
|
123
139
|
// Reset the model, since the fallback model may change — especially when using user custom models.
|
|
124
|
-
params.model = this.
|
|
140
|
+
params.model = this._model;
|
|
125
141
|
|
|
126
142
|
params.messages = messages;
|
|
127
143
|
params.files = files;
|
|
128
144
|
|
|
129
145
|
// If a fallback model is used, trigger the onFallback callback to notify the caller.
|
|
130
146
|
if (isInFallback && typeof onFallback === 'function') {
|
|
131
|
-
onFallback({ model: this.
|
|
147
|
+
onFallback({ model: this._model });
|
|
132
148
|
}
|
|
133
149
|
|
|
134
150
|
try {
|
|
135
|
-
return await this.
|
|
151
|
+
return await this._llmConnector.user(AccessCandidate.agent(params.agentId)).streamRequest(params);
|
|
136
152
|
} catch (error) {
|
|
137
153
|
// Attempt fallback for custom models (only if not already in fallback)
|
|
138
154
|
if (!isInFallback) {
|
|
@@ -152,12 +168,12 @@ export class LLMInference {
|
|
|
152
168
|
}
|
|
153
169
|
} catch (fallbackError) {
|
|
154
170
|
// If fallback also failed, log it but continue to return error emitter
|
|
155
|
-
|
|
171
|
+
logger.warn('Fallback also failed:', fallbackError);
|
|
156
172
|
}
|
|
157
173
|
}
|
|
158
174
|
|
|
159
175
|
// If fallback was not attempted or failed, return error emitter
|
|
160
|
-
|
|
176
|
+
logger.error('Error in streamRequest:', error);
|
|
161
177
|
|
|
162
178
|
const dummyEmitter = new EventEmitter();
|
|
163
179
|
process.nextTick(() => {
|
|
@@ -224,22 +240,22 @@ export class LLMInference {
|
|
|
224
240
|
* @returns The result from the fallback execution, or null if fallback should not be attempted
|
|
225
241
|
*/
|
|
226
242
|
private async executeFallback(methodName: 'prompt' | 'promptStream', args: TPromptParams): Promise<any> {
|
|
227
|
-
const isCustomModel = await this.
|
|
228
|
-
const fallbackModel = await this.
|
|
243
|
+
const isCustomModel = await this._modelProviderReq.isUserCustomLLM(this._model);
|
|
244
|
+
const fallbackModel = await this._modelProviderReq.getFallbackLLM(this._model);
|
|
229
245
|
|
|
230
246
|
// Only execute fallback if it's a custom model with a configured fallback
|
|
231
247
|
if (!isCustomModel || !fallbackModel) {
|
|
232
248
|
return null;
|
|
233
249
|
}
|
|
234
250
|
|
|
235
|
-
|
|
251
|
+
logger.info(`Attempting fallback from ${this._model} to ${fallbackModel}`);
|
|
236
252
|
|
|
237
253
|
// Mutate the model and connector to use fallback
|
|
238
|
-
this.
|
|
254
|
+
this._model = fallbackModel;
|
|
239
255
|
|
|
240
|
-
const llmProvider = await this.
|
|
256
|
+
const llmProvider = await this._modelProviderReq.getProvider(fallbackModel);
|
|
241
257
|
if (llmProvider) {
|
|
242
|
-
this.
|
|
258
|
+
this._llmConnector = ConnectorService.getLLMConnector(llmProvider);
|
|
243
259
|
}
|
|
244
260
|
|
|
245
261
|
// Call the appropriate method with isInFallback=true to prevent further fallbacks
|
|
@@ -252,13 +268,13 @@ export class LLMInference {
|
|
|
252
268
|
|
|
253
269
|
public async imageGenRequest({ query, files, params }: TPromptParams) {
|
|
254
270
|
params.prompt = query;
|
|
255
|
-
return this.
|
|
271
|
+
return this._llmConnector.user(AccessCandidate.agent(params.agentId)).imageGenRequest(params);
|
|
256
272
|
}
|
|
257
273
|
|
|
258
274
|
public async imageEditRequest({ query, files, params }: TPromptParams) {
|
|
259
275
|
params.prompt = query;
|
|
260
276
|
params.files = files;
|
|
261
|
-
return this.
|
|
277
|
+
return this._llmConnector.user(AccessCandidate.agent(params.agentId)).imageEditRequest(params);
|
|
262
278
|
}
|
|
263
279
|
|
|
264
280
|
//@deprecated
|
|
@@ -269,11 +285,11 @@ export class LLMInference {
|
|
|
269
285
|
throw new Error('Input messages are required.');
|
|
270
286
|
}
|
|
271
287
|
|
|
272
|
-
const model = params.model || this.
|
|
288
|
+
const model = params.model || this._model;
|
|
273
289
|
|
|
274
|
-
return await this.
|
|
290
|
+
return await this._llmConnector.user(AccessCandidate.agent(agentId)).streamRequest({ ...params, model });
|
|
275
291
|
} catch (error) {
|
|
276
|
-
|
|
292
|
+
logger.error('Error in streamRequest:', error);
|
|
277
293
|
|
|
278
294
|
const dummyEmitter = new EventEmitter();
|
|
279
295
|
process.nextTick(() => {
|
|
@@ -306,11 +322,11 @@ export class LLMInference {
|
|
|
306
322
|
//FIXME we need to update the connector multimediaStreamRequest in order to ignore prompt param if not provided
|
|
307
323
|
const userMessage = Array.isArray(params.messages) ? params.messages.pop() : {};
|
|
308
324
|
const prompt = userMessage?.content || '';
|
|
309
|
-
const model = params.model || this.
|
|
325
|
+
const model = params.model || this._model;
|
|
310
326
|
|
|
311
|
-
return await this.
|
|
327
|
+
return await this._llmConnector.user(AccessCandidate.agent(agentId)).multimodalStreamRequest(prompt, { ...params, model });
|
|
312
328
|
} catch (error: any) {
|
|
313
|
-
|
|
329
|
+
logger.error('Error in multimodalRequest: ', error);
|
|
314
330
|
|
|
315
331
|
throw error;
|
|
316
332
|
}
|
|
@@ -337,12 +353,12 @@ export class LLMInference {
|
|
|
337
353
|
params.files = _files;
|
|
338
354
|
|
|
339
355
|
try {
|
|
340
|
-
prompt = this.
|
|
341
|
-
const model = params.model || this.
|
|
356
|
+
prompt = this._llmConnector.enhancePrompt(prompt, config);
|
|
357
|
+
const model = params.model || this._model;
|
|
342
358
|
|
|
343
|
-
return await this.
|
|
359
|
+
return await this._llmConnector.user(AccessCandidate.agent(agentId)).multimodalStreamRequest(prompt, { ...params, model });
|
|
344
360
|
} catch (error: any) {
|
|
345
|
-
|
|
361
|
+
logger.error('Error in multimodalRequest: ', error);
|
|
346
362
|
|
|
347
363
|
throw error;
|
|
348
364
|
}
|
|
@@ -376,7 +392,7 @@ export class LLMInference {
|
|
|
376
392
|
|
|
377
393
|
//#region get max model context
|
|
378
394
|
|
|
379
|
-
const modelInfo = await this.
|
|
395
|
+
const modelInfo = await this._modelProviderReq.getModelInfo(this._model, true);
|
|
380
396
|
let maxModelContext = modelInfo?.tokens;
|
|
381
397
|
let maxModelOutputTokens = modelInfo?.completionTokens || modelInfo?.tokens;
|
|
382
398
|
// const isStandardLLM = LLMRegistry.isStandardLLM(this.model);
|
|
@@ -399,10 +415,10 @@ export class LLMInference {
|
|
|
399
415
|
}
|
|
400
416
|
|
|
401
417
|
if (maxInputContext <= 0) {
|
|
402
|
-
|
|
418
|
+
logger.warn('Max input context is 0, returning empty context window, This usually indicates a wrong model configuration');
|
|
403
419
|
}
|
|
404
420
|
|
|
405
|
-
|
|
421
|
+
logger.debug(
|
|
406
422
|
`Context Window Configuration: Max Input Tokens: ${maxInputContext}, Max Output Tokens: ${maxOutputContext}, Max Model Tokens: ${maxModelContext}`
|
|
407
423
|
);
|
|
408
424
|
const systemMessage = { role: 'system', content: systemPrompt };
|
|
@@ -473,7 +489,7 @@ function countTokens(content: any, model: 'gpt-4o' | 'gpt-4o-mini' = 'gpt-4o') {
|
|
|
473
489
|
const tokens = encodeChat([{ role: 'user', content: _stringifiedContent } as ChatMessage], model);
|
|
474
490
|
return tokens.length;
|
|
475
491
|
} catch (error) {
|
|
476
|
-
|
|
492
|
+
logger.warn('Error in countTokens: ', error);
|
|
477
493
|
return 0;
|
|
478
494
|
}
|
|
479
495
|
}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import EventEmitter from 'events';
|
|
2
2
|
import Anthropic from '@anthropic-ai/sdk';
|
|
3
|
+
import type { MessageStreamEvents } from '@anthropic-ai/sdk/lib/MessageStream';
|
|
3
4
|
|
|
4
5
|
import { JSON_RESPONSE_INSTRUCTION, BUILT_IN_MODEL_PREFIX } from '@sre/constants';
|
|
5
6
|
import { BinaryInput } from '@sre/helpers/BinaryInput.helper';
|
|
@@ -35,6 +36,26 @@ const LEGACY_THINKING_MODELS = ['smythos/claude-3.7-sonnet-thinking', 'claude-3.
|
|
|
35
36
|
|
|
36
37
|
// Type aliases
|
|
37
38
|
type AnthropicMessageParams = Anthropic.MessageCreateParamsNonStreaming | Anthropic.Messages.MessageStreamParams;
|
|
39
|
+
type AnthropicStreamEventType = keyof MessageStreamEvents;
|
|
40
|
+
|
|
41
|
+
// Event names automatically validated against MessageStreamEvents type
|
|
42
|
+
// TypeScript will error if any events are missing or incorrect
|
|
43
|
+
// This ensures we always use the correct event names as defined by Anthropic SDK
|
|
44
|
+
const AnthropicStreamEvent = {
|
|
45
|
+
connect: 'connect',
|
|
46
|
+
streamEvent: 'streamEvent',
|
|
47
|
+
text: 'text',
|
|
48
|
+
citation: 'citation',
|
|
49
|
+
inputJson: 'inputJson',
|
|
50
|
+
thinking: 'thinking',
|
|
51
|
+
signature: 'signature',
|
|
52
|
+
message: 'message',
|
|
53
|
+
contentBlock: 'contentBlock',
|
|
54
|
+
finalMessage: 'finalMessage',
|
|
55
|
+
error: 'error',
|
|
56
|
+
abort: 'abort',
|
|
57
|
+
end: 'end',
|
|
58
|
+
} satisfies Record<keyof MessageStreamEvents, AnthropicStreamEventType>;
|
|
38
59
|
|
|
39
60
|
// TODO [Forhad]: implement proper typing
|
|
40
61
|
|
|
@@ -132,34 +153,38 @@ export class AnthropicConnector extends LLMConnector {
|
|
|
132
153
|
const needsPrefillInjection = this.hasPrefillText(body.messages);
|
|
133
154
|
let prefillInjected = false;
|
|
134
155
|
|
|
135
|
-
stream.on(
|
|
156
|
+
stream.on(AnthropicStreamEvent.streamEvent, (event: any) => {
|
|
136
157
|
if (event.message?.usage) {
|
|
137
158
|
//console.log('usage', event.message?.usage);
|
|
138
159
|
}
|
|
139
160
|
});
|
|
140
161
|
|
|
141
|
-
stream.on(
|
|
162
|
+
stream.on(AnthropicStreamEvent.error, (error) => {
|
|
142
163
|
//console.log('error', error);
|
|
143
164
|
|
|
144
|
-
emitter.emit(
|
|
165
|
+
emitter.emit(TLLMEvent.Error, error);
|
|
145
166
|
});
|
|
146
167
|
|
|
147
|
-
stream.on(
|
|
168
|
+
stream.on(AnthropicStreamEvent.message, (message) => {
|
|
169
|
+
emitter.emit(TLLMEvent.Data, message);
|
|
170
|
+
});
|
|
171
|
+
|
|
172
|
+
stream.on(AnthropicStreamEvent.text, (text: string) => {
|
|
148
173
|
// Inject prefill text only once at the very beginning if needed
|
|
149
174
|
if (needsPrefillInjection && !prefillInjected) {
|
|
150
175
|
text = `${PREFILL_TEXT_FOR_JSON_RESPONSE}${text}`;
|
|
151
176
|
prefillInjected = true;
|
|
152
177
|
}
|
|
153
178
|
|
|
154
|
-
emitter.emit(
|
|
179
|
+
emitter.emit(TLLMEvent.Content, text);
|
|
155
180
|
});
|
|
156
181
|
|
|
157
|
-
stream.on(
|
|
182
|
+
stream.on(AnthropicStreamEvent.thinking, (thinking) => {
|
|
158
183
|
// Handle thinking blocks during streaming
|
|
159
|
-
emitter.emit(
|
|
184
|
+
emitter.emit(TLLMEvent.Thinking, thinking);
|
|
160
185
|
});
|
|
161
186
|
|
|
162
|
-
stream.on(
|
|
187
|
+
stream.on(AnthropicStreamEvent.finalMessage, (finalMessage) => {
|
|
163
188
|
let finishReason = 'stop';
|
|
164
189
|
// Preserve thinking blocks for subsequent tool interactions
|
|
165
190
|
thinkingBlocks = finalMessage.content.filter((block) => block.type === 'thinking' || block.type === 'redacted_thinking');
|
|
@@ -197,12 +222,12 @@ export class AnthropicConnector extends LLMConnector {
|
|
|
197
222
|
usage_data.push(reportedUsage);
|
|
198
223
|
}
|
|
199
224
|
if (finishReason !== 'stop' && finishReason !== 'end_turn') {
|
|
200
|
-
emitter.emit(
|
|
225
|
+
emitter.emit(TLLMEvent.Interrupted, finishReason);
|
|
201
226
|
}
|
|
202
227
|
|
|
203
228
|
//only emit end event after processing the final message
|
|
204
229
|
setTimeout(() => {
|
|
205
|
-
emitter.emit(
|
|
230
|
+
emitter.emit(TLLMEvent.End, toolsData, usage_data, finishReason);
|
|
206
231
|
}, 100);
|
|
207
232
|
});
|
|
208
233
|
|
|
@@ -126,14 +126,14 @@ export class BedrockConnector extends LLMConnector {
|
|
|
126
126
|
// Handle message start
|
|
127
127
|
if (chunk.messageStart) {
|
|
128
128
|
currentMessage.role = chunk.messageStart.role || '';
|
|
129
|
-
emitter.emit(
|
|
129
|
+
emitter.emit(TLLMEvent.Data, { role: currentMessage.role });
|
|
130
130
|
}
|
|
131
131
|
|
|
132
132
|
// Handle content deltas
|
|
133
133
|
if (chunk.contentBlockDelta?.delta?.text) {
|
|
134
134
|
currentMessage.content += chunk.contentBlockDelta.delta.text;
|
|
135
|
-
emitter.emit(
|
|
136
|
-
emitter.emit(
|
|
135
|
+
emitter.emit(TLLMEvent.Data, chunk.contentBlockDelta.delta.text);
|
|
136
|
+
emitter.emit(TLLMEvent.Content, chunk.contentBlockDelta.delta.text, currentMessage.role);
|
|
137
137
|
}
|
|
138
138
|
|
|
139
139
|
// Handle tool use start
|
|
@@ -175,10 +175,18 @@ export class BedrockConnector extends LLMConnector {
|
|
|
175
175
|
|
|
176
176
|
// Handle message completion
|
|
177
177
|
if (chunk.messageStop) {
|
|
178
|
+
const finishReason = chunk.messageStop.stopReason || 'stop';
|
|
179
|
+
|
|
178
180
|
if (currentMessage.toolCalls.length > 0) {
|
|
179
181
|
emitter.emit(TLLMEvent.ToolInfo, currentMessage.toolCalls);
|
|
180
182
|
}
|
|
181
|
-
|
|
183
|
+
|
|
184
|
+
// Emit interrupted event if finishReason is not 'stop'
|
|
185
|
+
if (finishReason !== 'stop' && finishReason !== 'end_turn') {
|
|
186
|
+
emitter.emit(TLLMEvent.Interrupted, finishReason);
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
emitter.emit(TLLMEvent.End, currentMessage.toolCalls, [], finishReason);
|
|
182
190
|
}
|
|
183
191
|
|
|
184
192
|
if (chunk?.metadata?.usage) {
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { JSONContent } from '@sre/helpers/JsonContent.helper';
|
|
2
2
|
import { LLMConnector } from '../LLMConnector';
|
|
3
3
|
import EventEmitter from 'events';
|
|
4
|
-
import { APIKeySource, ILLMRequestFuncParams, TLLMChatResponse, TLLMPreparedParams } from '@sre/types/LLM.types';
|
|
4
|
+
import { APIKeySource, ILLMRequestFuncParams, TLLMChatResponse, TLLMEvent, TLLMPreparedParams } from '@sre/types/LLM.types';
|
|
5
5
|
import { Logger } from '@sre/helpers/Log.helper';
|
|
6
6
|
import { delay } from '@sre/utils/index';
|
|
7
7
|
import { hookAsync } from '@sre/Core/HookService';
|
|
@@ -54,13 +54,13 @@ export class EchoConnector extends LLMConnector {
|
|
|
54
54
|
const isLastChunk = i === chunks.length - 1;
|
|
55
55
|
// Add space between chunks except for the last one to avoid trailing space in file URLs
|
|
56
56
|
const delta = { content: chunks[i] + (isLastChunk ? '' : ' ') };
|
|
57
|
-
emitter.emit(
|
|
58
|
-
emitter.emit(
|
|
57
|
+
emitter.emit(TLLMEvent.Data, delta);
|
|
58
|
+
emitter.emit(TLLMEvent.Content, delta.content);
|
|
59
59
|
}
|
|
60
60
|
|
|
61
61
|
// Emit end event after all chunks are processed
|
|
62
62
|
setTimeout(() => {
|
|
63
|
-
emitter.emit(
|
|
63
|
+
emitter.emit(TLLMEvent.End, [], [], 'stop'); // Empty arrays for toolsData and usage_data, with finishReason
|
|
64
64
|
}, 100);
|
|
65
65
|
})();
|
|
66
66
|
|