@smythos/sre 1.6.14 → 1.7.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/CHANGELOG +15 -0
- package/dist/index.js +52 -46
- package/dist/index.js.map +1 -1
- package/dist/types/Components/APIEndpoint.class.d.ts +2 -8
- package/dist/types/Components/Component.class.d.ts +9 -0
- package/dist/types/Components/Triggers/Gmail.trigger.d.ts +0 -17
- package/dist/types/Components/Triggers/JobScheduler.trigger.d.ts +10 -0
- package/dist/types/Components/Triggers/Trigger.class.d.ts +11 -0
- package/dist/types/Components/index.d.ts +6 -0
- package/dist/types/Core/Connector.class.d.ts +1 -0
- package/dist/types/Core/ConnectorsService.d.ts +2 -0
- package/dist/types/Core/HookService.d.ts +1 -1
- package/dist/types/helpers/Conversation.helper.d.ts +2 -0
- package/dist/types/helpers/Crypto.helper.d.ts +8 -0
- package/dist/types/index.d.ts +13 -0
- package/dist/types/subsystems/AgentManager/Agent.class.d.ts +4 -2
- package/dist/types/subsystems/AgentManager/AgentData.service/AgentDataConnector.d.ts +13 -0
- package/dist/types/subsystems/AgentManager/AgentData.service/connectors/NullAgentData.class.d.ts +1 -4
- package/dist/types/subsystems/AgentManager/Scheduler.service/Job.class.d.ts +29 -6
- package/dist/types/subsystems/AgentManager/Scheduler.service/SchedulerConnector.d.ts +11 -3
- package/dist/types/subsystems/AgentManager/Scheduler.service/connectors/LocalScheduler.class.d.ts +31 -7
- package/dist/types/subsystems/LLMManager/LLM.service/connectors/Perplexity.class.d.ts +2 -5
- package/dist/types/subsystems/LLMManager/LLM.service/connectors/openai/OpenAIConnector.class.d.ts +3 -6
- package/dist/types/subsystems/LLMManager/LLM.service/connectors/openai/apiInterfaces/ResponsesApiInterface.d.ts +7 -0
- package/dist/types/subsystems/LLMManager/LLM.service/connectors/xAI.class.d.ts +2 -5
- package/dist/types/types/Agent.types.d.ts +1 -0
- package/dist/types/types/LLM.types.d.ts +2 -5
- package/dist/types/types/SRE.types.d.ts +4 -1
- package/package.json +6 -2
- package/src/Components/APICall/OAuth.helper.ts +30 -35
- package/src/Components/APIEndpoint.class.ts +25 -6
- package/src/Components/Component.class.ts +11 -0
- package/src/Components/Triggers/Gmail.trigger.ts +282 -0
- package/src/Components/Triggers/JobScheduler.trigger.ts +45 -0
- package/src/Components/Triggers/README.md +3 -0
- package/src/Components/Triggers/Trigger.class.ts +101 -0
- package/src/Components/Triggers/WhatsApp.trigger.ts +219 -0
- package/src/Components/index.ts +8 -0
- package/src/Core/AgentProcess.helper.ts +4 -6
- package/src/Core/Connector.class.ts +11 -3
- package/src/Core/ConnectorsService.ts +5 -0
- package/src/Core/ExternalEventsReceiver.ts +317 -0
- package/src/Core/HookService.ts +20 -6
- package/src/Core/SmythRuntime.class.ts +7 -0
- package/src/Core/SystemEvents.ts +17 -0
- package/src/Core/boot.ts +2 -0
- package/src/helpers/Conversation.helper.ts +35 -11
- package/src/helpers/Crypto.helper.ts +28 -0
- package/src/index.ts +208 -195
- package/src/index.ts.bak +208 -195
- package/src/subsystems/AGENTS.md +594 -0
- package/src/subsystems/AgentManager/Agent.class.ts +71 -21
- package/src/subsystems/AgentManager/AgentData.service/AgentDataConnector.ts +24 -1
- package/src/subsystems/AgentManager/AgentData.service/connectors/NullAgentData.class.ts +2 -2
- package/src/subsystems/AgentManager/AgentRuntime.class.ts +34 -5
- package/src/subsystems/AgentManager/Scheduler.service/Job.class.ts +414 -0
- package/src/subsystems/AgentManager/Scheduler.service/Schedule.class.ts +200 -0
- package/src/subsystems/AgentManager/Scheduler.service/SchedulerConnector.ts +200 -0
- package/src/subsystems/AgentManager/Scheduler.service/connectors/LocalScheduler.class.ts +767 -0
- package/src/subsystems/AgentManager/Scheduler.service/index.ts +11 -0
- package/src/subsystems/IO/VectorDB.service/connectors/MilvusVectorDB.class.ts +1 -1
- package/src/subsystems/LLMManager/LLM.service/LLMCredentials.helper.ts +61 -2
- package/src/subsystems/LLMManager/LLM.service/connectors/Anthropic.class.ts +3 -0
- package/src/subsystems/LLMManager/LLM.service/connectors/Bedrock.class.ts +3 -1
- package/src/subsystems/LLMManager/LLM.service/connectors/Echo.class.ts +5 -1
- package/src/subsystems/LLMManager/LLM.service/connectors/GoogleAI.class.ts +247 -56
- package/src/subsystems/LLMManager/LLM.service/connectors/Groq.class.ts +3 -0
- package/src/subsystems/LLMManager/LLM.service/connectors/Ollama.class.ts +28 -21
- package/src/subsystems/LLMManager/LLM.service/connectors/Perplexity.class.ts +3 -0
- package/src/subsystems/LLMManager/LLM.service/connectors/VertexAI.class.ts +121 -33
- package/src/subsystems/LLMManager/LLM.service/connectors/openai/OpenAIConnector.class.ts +38 -27
- package/src/subsystems/LLMManager/LLM.service/connectors/openai/apiInterfaces/ResponsesApiInterface.ts +115 -18
- package/src/subsystems/LLMManager/LLM.service/connectors/xAI.class.ts +3 -0
- package/src/subsystems/LLMManager/ModelsProvider.service/ModelsProviderConnector.ts +1 -6
- package/src/subsystems/MemoryManager/LLMContext.ts +3 -8
- package/src/subsystems/MemoryManager/RuntimeContext.ts +10 -9
- package/src/subsystems/Security/Credentials/Credentials.class.ts +1 -0
- package/src/subsystems/Security/Credentials/ManagedOAuth2Credentials.class.ts +106 -0
- package/src/types/Agent.types.ts +1 -0
- package/src/types/LLM.types.ts +2 -2
- package/src/types/SRE.types.ts +3 -0
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
//==[ SRE: Scheduler ]======================
|
|
2
|
+
|
|
3
|
+
import { ConnectorService, ConnectorServiceProvider } from '@sre/Core/ConnectorsService';
|
|
4
|
+
import { TConnectorService } from '@sre/types/SRE.types';
|
|
5
|
+
import { LocalScheduler } from './connectors/LocalScheduler.class';
|
|
6
|
+
|
|
7
|
+
export class SchedulerService extends ConnectorServiceProvider {
|
|
8
|
+
public register() {
|
|
9
|
+
ConnectorService.register(TConnectorService.Scheduler, 'LocalScheduler', LocalScheduler);
|
|
10
|
+
}
|
|
11
|
+
}
|
|
@@ -205,7 +205,7 @@ export class MilvusVectorDB extends VectorDBConnector {
|
|
|
205
205
|
}
|
|
206
206
|
|
|
207
207
|
const result = await this.client.search({
|
|
208
|
-
|
|
208
|
+
data: _vector as number[],
|
|
209
209
|
collection_name: preparedNs,
|
|
210
210
|
output_fields: ['id', 'text', this.USER_METADATA_KEY, 'namespaceId', 'datasourceId', 'datasourceLabel', 'vector'],
|
|
211
211
|
limit: options.topK || 10,
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { ConnectorService } from '@sre/Core/ConnectorsService';
|
|
2
2
|
import { AccessCandidate } from '@sre/Security/AccessControl/AccessCandidate.class';
|
|
3
3
|
import { TBedrockSettings, TCustomLLMModel, TLLMCredentials, TLLMModel, TVertexAISettings } from '@sre/types/LLM.types';
|
|
4
|
+
import { TemplateString, Match } from '@sre/helpers/TemplateString.helper';
|
|
4
5
|
|
|
5
6
|
export async function getLLMCredentials(candidate: AccessCandidate, modelInfo: TLLMModel | TCustomLLMModel) {
|
|
6
7
|
//create a credentials list that we can iterate over
|
|
@@ -11,8 +12,16 @@ export async function getLLMCredentials(candidate: AccessCandidate, modelInfo: T
|
|
|
11
12
|
|
|
12
13
|
for (let credentialsMode of credentialsList) {
|
|
13
14
|
if (typeof credentialsMode === 'object') {
|
|
14
|
-
//credentials
|
|
15
|
-
|
|
15
|
+
// Resolve key templates for each property in the credentials object
|
|
16
|
+
const resolvedCredentials: any = {};
|
|
17
|
+
|
|
18
|
+
for (const [key, value] of Object.entries(credentialsMode)) {
|
|
19
|
+
// Resolve {{KEY(...)}} templates from vault (supports nested objects)
|
|
20
|
+
resolvedCredentials[key] = await resolveKeyTemplate(value, candidate);
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
//credentials passed directly (resolved from vault templates if any)
|
|
24
|
+
return resolvedCredentials;
|
|
16
25
|
}
|
|
17
26
|
|
|
18
27
|
switch (credentialsMode) {
|
|
@@ -169,3 +178,53 @@ async function getVertexAICredentials(candidate: AccessCandidate, modelInfo: TCu
|
|
|
169
178
|
if (!credentials) return null;
|
|
170
179
|
return { ...credentials, isUserKey: true };
|
|
171
180
|
}
|
|
181
|
+
|
|
182
|
+
/**
|
|
183
|
+
* Creates a vault key processor for the TemplateString helper that works with AccessCandidate
|
|
184
|
+
* @param candidate - The access candidate requesting the credentials
|
|
185
|
+
* @returns A processor function that resolves vault keys using the candidate's permissions
|
|
186
|
+
* @private
|
|
187
|
+
*/
|
|
188
|
+
function createVaultKeyProcessor(candidate: AccessCandidate): (token: string) => Promise<string> {
|
|
189
|
+
return async (token: string) => {
|
|
190
|
+
try {
|
|
191
|
+
const vaultConnector = ConnectorService.getVaultConnector();
|
|
192
|
+
return await vaultConnector.requester(candidate).get(token);
|
|
193
|
+
} catch (error) {
|
|
194
|
+
return '';
|
|
195
|
+
}
|
|
196
|
+
};
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
/**
|
|
200
|
+
* Resolves a vault key template by fetching the value from the vault
|
|
201
|
+
* Uses the TemplateString helper to parse {{KEY(...)}} templates
|
|
202
|
+
* Recursively handles nested objects and arrays
|
|
203
|
+
* @param value - The value to resolve (can be a template string, object, array, or primitive)
|
|
204
|
+
* @param candidate - The access candidate requesting the credentials
|
|
205
|
+
* @returns Promise resolving to the vault value or the original value if not a template
|
|
206
|
+
* @private
|
|
207
|
+
*/
|
|
208
|
+
async function resolveKeyTemplate(value: any, candidate: AccessCandidate): Promise<any> {
|
|
209
|
+
// Handle strings with templates
|
|
210
|
+
if (typeof value === 'string') {
|
|
211
|
+
return await TemplateString(value).process(createVaultKeyProcessor(candidate), Match.fn('KEY')).asyncResult;
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
// Handle arrays recursively
|
|
215
|
+
if (Array.isArray(value)) {
|
|
216
|
+
return await Promise.all(value.map((item) => resolveKeyTemplate(item, candidate)));
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
// Handle nested objects recursively
|
|
220
|
+
if (typeof value === 'object' && value !== null) {
|
|
221
|
+
const resolvedObject: any = {};
|
|
222
|
+
for (const [key, val] of Object.entries(value)) {
|
|
223
|
+
resolvedObject[key] = await resolveKeyTemplate(val, candidate);
|
|
224
|
+
}
|
|
225
|
+
return resolvedObject;
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
// Return primitives as-is
|
|
229
|
+
return value;
|
|
230
|
+
}
|
|
@@ -26,6 +26,7 @@ import { LLMConnector } from '../LLMConnector';
|
|
|
26
26
|
import { SystemEvents } from '@sre/Core/SystemEvents';
|
|
27
27
|
import { SUPPORTED_MIME_TYPES_MAP } from '@sre/constants';
|
|
28
28
|
import { Logger } from '@sre/helpers/Log.helper';
|
|
29
|
+
import { hookAsync } from '@sre/Core/HookService';
|
|
29
30
|
|
|
30
31
|
const logger = Logger('AnthropicConnector');
|
|
31
32
|
|
|
@@ -50,6 +51,7 @@ export class AnthropicConnector extends LLMConnector {
|
|
|
50
51
|
return new Anthropic({ apiKey });
|
|
51
52
|
}
|
|
52
53
|
|
|
54
|
+
@hookAsync('LLMConnector.request')
|
|
53
55
|
protected async request({ acRequest, body, context }: ILLMRequestFuncParams): Promise<TLLMChatResponse> {
|
|
54
56
|
try {
|
|
55
57
|
logger.debug(`request ${this.name}`, acRequest.candidate);
|
|
@@ -113,6 +115,7 @@ export class AnthropicConnector extends LLMConnector {
|
|
|
113
115
|
}
|
|
114
116
|
}
|
|
115
117
|
|
|
118
|
+
@hookAsync('LLMConnector.streamRequest')
|
|
116
119
|
protected async streamRequest({ acRequest, body, context }: ILLMRequestFuncParams): Promise<EventEmitter> {
|
|
117
120
|
try {
|
|
118
121
|
logger.debug(`streamRequest ${this.name}`, acRequest.candidate);
|
|
@@ -31,6 +31,7 @@ import { LLMConnector } from '../LLMConnector';
|
|
|
31
31
|
import { JSONContent } from '@sre/helpers/JsonContent.helper';
|
|
32
32
|
import { SystemEvents } from '@sre/Core/SystemEvents';
|
|
33
33
|
import { Logger } from '@sre/helpers/Log.helper';
|
|
34
|
+
import { hookAsync } from '@sre/Core/HookService';
|
|
34
35
|
|
|
35
36
|
const logger = Logger('BedrockConnector');
|
|
36
37
|
|
|
@@ -51,6 +52,7 @@ export class BedrockConnector extends LLMConnector {
|
|
|
51
52
|
});
|
|
52
53
|
}
|
|
53
54
|
|
|
55
|
+
@hookAsync('LLMConnector.request')
|
|
54
56
|
protected async request({ acRequest, body, context }: ILLMRequestFuncParams): Promise<TLLMChatResponse> {
|
|
55
57
|
try {
|
|
56
58
|
logger.debug(`request ${this.name}`, acRequest.candidate);
|
|
@@ -99,7 +101,7 @@ export class BedrockConnector extends LLMConnector {
|
|
|
99
101
|
throw error?.error || error;
|
|
100
102
|
}
|
|
101
103
|
}
|
|
102
|
-
|
|
104
|
+
@hookAsync('LLMConnector.streamRequest')
|
|
103
105
|
protected async streamRequest({ acRequest, body, context }: ILLMRequestFuncParams): Promise<EventEmitter> {
|
|
104
106
|
const emitter = new EventEmitter();
|
|
105
107
|
|
|
@@ -3,12 +3,15 @@ import { LLMConnector } from '../LLMConnector';
|
|
|
3
3
|
import EventEmitter from 'events';
|
|
4
4
|
import { APIKeySource, ILLMRequestFuncParams, TLLMChatResponse, TLLMPreparedParams } from '@sre/types/LLM.types';
|
|
5
5
|
import { Logger } from '@sre/helpers/Log.helper';
|
|
6
|
+
import { delay } from '@sre/utils/index';
|
|
7
|
+
import { hookAsync } from '@sre/Core/HookService';
|
|
6
8
|
|
|
7
9
|
const logger = Logger('EchoConnector');
|
|
8
10
|
|
|
9
11
|
export class EchoConnector extends LLMConnector {
|
|
10
12
|
public name = 'LLM:Echo';
|
|
11
13
|
|
|
14
|
+
@hookAsync('LLMConnector.request')
|
|
12
15
|
protected async request({ acRequest, body, context }: ILLMRequestFuncParams): Promise<TLLMChatResponse> {
|
|
13
16
|
try {
|
|
14
17
|
logger.debug(`request ${this.name}`, acRequest.candidate);
|
|
@@ -27,6 +30,7 @@ export class EchoConnector extends LLMConnector {
|
|
|
27
30
|
}
|
|
28
31
|
}
|
|
29
32
|
|
|
33
|
+
@hookAsync('LLMConnector.streamRequest')
|
|
30
34
|
protected async streamRequest({ acRequest, body, context }: ILLMRequestFuncParams): Promise<EventEmitter> {
|
|
31
35
|
try {
|
|
32
36
|
logger.debug(`streamRequest ${this.name}`, acRequest.candidate);
|
|
@@ -45,7 +49,7 @@ export class EchoConnector extends LLMConnector {
|
|
|
45
49
|
|
|
46
50
|
for (let i = 0; i < chunks.length; i++) {
|
|
47
51
|
// Simulate network delay
|
|
48
|
-
await
|
|
52
|
+
await delay(10);
|
|
49
53
|
|
|
50
54
|
const isLastChunk = i === chunks.length - 1;
|
|
51
55
|
// Add space between chunks except for the last one to avoid trailing space in file URLs
|
|
@@ -3,12 +3,7 @@ import path from 'path';
|
|
|
3
3
|
import EventEmitter from 'events';
|
|
4
4
|
import fs from 'fs';
|
|
5
5
|
|
|
6
|
-
import {
|
|
7
|
-
GoogleGenAI,
|
|
8
|
-
FunctionCallingConfigMode,
|
|
9
|
-
FileState,
|
|
10
|
-
type GenerateContentResponseUsageMetadata,
|
|
11
|
-
} from '@google/genai/node';
|
|
6
|
+
import { GoogleGenAI, FunctionCallingConfigMode, FileState, type GenerateContentResponseUsageMetadata } from '@google/genai/node';
|
|
12
7
|
|
|
13
8
|
import { JSON_RESPONSE_INSTRUCTION, BUILT_IN_MODEL_PREFIX } from '@sre/constants';
|
|
14
9
|
import { BinaryInput } from '@sre/helpers/BinaryInput.helper';
|
|
@@ -40,6 +35,7 @@ import { SUPPORTED_MIME_TYPES_MAP } from '@sre/constants';
|
|
|
40
35
|
import { Logger } from '@sre/helpers/Log.helper';
|
|
41
36
|
|
|
42
37
|
import { LLMConnector } from '../LLMConnector';
|
|
38
|
+
import { hookAsync } from '@sre/Core/HookService';
|
|
43
39
|
|
|
44
40
|
const logger = Logger('GoogleAIConnector');
|
|
45
41
|
|
|
@@ -90,6 +86,7 @@ export class GoogleAIConnector extends LLMConnector {
|
|
|
90
86
|
return new GoogleGenAI({ apiKey });
|
|
91
87
|
}
|
|
92
88
|
|
|
89
|
+
@hookAsync('LLMConnector.request')
|
|
93
90
|
protected async request({ acRequest, body, context }: ILLMRequestFuncParams): Promise<TLLMChatResponse> {
|
|
94
91
|
try {
|
|
95
92
|
logger.debug(`request ${this.name}`, acRequest.candidate);
|
|
@@ -160,6 +157,7 @@ export class GoogleAIConnector extends LLMConnector {
|
|
|
160
157
|
}
|
|
161
158
|
}
|
|
162
159
|
|
|
160
|
+
@hookAsync('LLMConnector.streamRequest')
|
|
163
161
|
protected async streamRequest({ acRequest, body, context }: ILLMRequestFuncParams): Promise<EventEmitter> {
|
|
164
162
|
logger.debug(`streamRequest ${this.name}`, acRequest.candidate);
|
|
165
163
|
const emitter = new EventEmitter();
|
|
@@ -436,9 +434,10 @@ export class GoogleAIConnector extends LLMConnector {
|
|
|
436
434
|
return body;
|
|
437
435
|
}
|
|
438
436
|
|
|
439
|
-
private normalizePrompt(
|
|
440
|
-
|
|
441
|
-
|
|
437
|
+
private normalizePrompt(prompt: TGoogleAIRequestBody['messages'] | TGoogleAIRequestBody['contents']): {
|
|
438
|
+
contents: any;
|
|
439
|
+
config?: Record<string, any>;
|
|
440
|
+
} {
|
|
442
441
|
if (prompt == null) {
|
|
443
442
|
return { contents: '' };
|
|
444
443
|
}
|
|
@@ -627,87 +626,279 @@ export class GoogleAIConnector extends LLMConnector {
|
|
|
627
626
|
}): TLLMToolResultMessageBlock[] {
|
|
628
627
|
const messageBlocks: TLLMToolResultMessageBlock[] = [];
|
|
629
628
|
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
|
|
629
|
+
const parseFunctionArgs = (args: unknown) => {
|
|
630
|
+
if (typeof args === 'string') {
|
|
631
|
+
try {
|
|
632
|
+
return JSON.parse(args);
|
|
633
|
+
} catch {
|
|
634
|
+
return args;
|
|
635
|
+
}
|
|
636
636
|
}
|
|
637
|
+
return args ?? {};
|
|
638
|
+
};
|
|
639
|
+
|
|
640
|
+
const parseFunctionResponse = (response: unknown): any => {
|
|
641
|
+
if (typeof response === 'string') {
|
|
642
|
+
try {
|
|
643
|
+
const parsed = JSON.parse(response);
|
|
644
|
+
if (typeof parsed === 'string' && parsed !== response) {
|
|
645
|
+
return parseFunctionResponse(parsed);
|
|
646
|
+
}
|
|
647
|
+
return parsed;
|
|
648
|
+
} catch {
|
|
649
|
+
return response;
|
|
650
|
+
}
|
|
651
|
+
}
|
|
652
|
+
return response ?? {};
|
|
653
|
+
};
|
|
637
654
|
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
|
|
655
|
+
if (messageBlock) {
|
|
656
|
+
const content: any[] = [];
|
|
657
|
+
|
|
658
|
+
if (Array.isArray(messageBlock.parts) && messageBlock.parts.length > 0) {
|
|
659
|
+
for (const part of messageBlock.parts) {
|
|
660
|
+
if (!part) continue;
|
|
661
|
+
|
|
662
|
+
if (typeof part.text === 'string' && part.text.trim()) {
|
|
663
|
+
content.push({ text: part.text.trim() });
|
|
664
|
+
continue;
|
|
665
|
+
}
|
|
666
|
+
|
|
667
|
+
if (part.functionCall) {
|
|
668
|
+
content.push({
|
|
643
669
|
functionCall: {
|
|
644
|
-
name:
|
|
645
|
-
args:
|
|
670
|
+
name: part.functionCall.name,
|
|
671
|
+
args: parseFunctionArgs(part.functionCall.args),
|
|
646
672
|
},
|
|
647
|
-
})
|
|
648
|
-
|
|
673
|
+
});
|
|
674
|
+
continue;
|
|
675
|
+
}
|
|
676
|
+
|
|
677
|
+
if (part.functionResponse) {
|
|
678
|
+
content.push({
|
|
679
|
+
functionResponse: {
|
|
680
|
+
name: part.functionResponse.name,
|
|
681
|
+
response: parseFunctionResponse(part.functionResponse.response),
|
|
682
|
+
},
|
|
683
|
+
});
|
|
684
|
+
continue;
|
|
685
|
+
}
|
|
686
|
+
|
|
687
|
+
if ((part as any).inlineData) {
|
|
688
|
+
content.push({ inlineData: (part as any).inlineData });
|
|
689
|
+
}
|
|
690
|
+
}
|
|
691
|
+
} else {
|
|
692
|
+
if (typeof messageBlock.content === 'string' && messageBlock.content.trim()) {
|
|
693
|
+
content.push({ text: messageBlock.content.trim() });
|
|
694
|
+
} else if (Array.isArray(messageBlock.content) && messageBlock.content.length > 0) {
|
|
695
|
+
content.push(...messageBlock.content);
|
|
696
|
+
}
|
|
697
|
+
}
|
|
698
|
+
|
|
699
|
+
const hasFunctionCall = content.some((part) => part.functionCall);
|
|
700
|
+
if (!hasFunctionCall && toolsData.length > 0) {
|
|
701
|
+
toolsData.forEach((toolCall) => {
|
|
702
|
+
content.push({
|
|
703
|
+
functionCall: {
|
|
704
|
+
name: toolCall.name,
|
|
705
|
+
args: parseFunctionArgs(toolCall.arguments),
|
|
706
|
+
},
|
|
707
|
+
});
|
|
708
|
+
});
|
|
709
|
+
}
|
|
710
|
+
|
|
711
|
+
if (content.length > 0) {
|
|
712
|
+
let role = messageBlock.role;
|
|
713
|
+
if (role === TLLMMessageRole.Assistant) {
|
|
714
|
+
role = TLLMMessageRole.Model;
|
|
649
715
|
}
|
|
716
|
+
|
|
717
|
+
messageBlocks.push({
|
|
718
|
+
role,
|
|
719
|
+
parts: content,
|
|
720
|
+
});
|
|
650
721
|
}
|
|
722
|
+
}
|
|
723
|
+
|
|
724
|
+
const functionResponseParts = toolsData
|
|
725
|
+
.filter((toolData) => toolData.result !== undefined)
|
|
726
|
+
.map((toolData) => ({
|
|
727
|
+
functionResponse: {
|
|
728
|
+
name: toolData.name,
|
|
729
|
+
response: parseFunctionResponse(toolData.result),
|
|
730
|
+
},
|
|
731
|
+
}));
|
|
651
732
|
|
|
733
|
+
if (functionResponseParts.length > 0) {
|
|
652
734
|
messageBlocks.push({
|
|
653
|
-
role:
|
|
654
|
-
parts:
|
|
735
|
+
role: TLLMMessageRole.Function,
|
|
736
|
+
parts: functionResponseParts,
|
|
655
737
|
});
|
|
656
738
|
}
|
|
657
739
|
|
|
658
|
-
|
|
659
|
-
(toolData): TLLMToolResultMessageBlock => ({
|
|
660
|
-
role: TLLMMessageRole.User,
|
|
661
|
-
parts: [
|
|
662
|
-
{
|
|
663
|
-
functionResponse: {
|
|
664
|
-
name: toolData.name,
|
|
665
|
-
response: {
|
|
666
|
-
name: toolData.name,
|
|
667
|
-
content: typeof toolData.result === 'string' ? toolData.result : JSON.stringify(toolData.result),
|
|
668
|
-
},
|
|
669
|
-
},
|
|
670
|
-
},
|
|
671
|
-
],
|
|
672
|
-
})
|
|
673
|
-
);
|
|
674
|
-
|
|
675
|
-
return [...messageBlocks, ...transformedToolsData];
|
|
740
|
+
return messageBlocks;
|
|
676
741
|
}
|
|
677
742
|
|
|
678
743
|
public getConsistentMessages(messages: TLLMMessageBlock[]): TLLMMessageBlock[] {
|
|
679
744
|
const _messages = LLMHelper.removeDuplicateUserMessages(messages);
|
|
680
745
|
|
|
681
746
|
return _messages.map((message) => {
|
|
682
|
-
const _message = { ...message };
|
|
683
|
-
|
|
747
|
+
const _message: TLLMMessageBlock = { ...message };
|
|
748
|
+
|
|
749
|
+
const parseFunctionArgs = (args: unknown) => {
|
|
750
|
+
if (typeof args === 'string') {
|
|
751
|
+
try {
|
|
752
|
+
return JSON.parse(args);
|
|
753
|
+
} catch {
|
|
754
|
+
return args;
|
|
755
|
+
}
|
|
756
|
+
}
|
|
757
|
+
|
|
758
|
+
return args ?? {};
|
|
759
|
+
};
|
|
760
|
+
|
|
761
|
+
const parseFunctionResponse = (response: unknown) => {
|
|
762
|
+
if (typeof response === 'string') {
|
|
763
|
+
try {
|
|
764
|
+
return JSON.parse(response);
|
|
765
|
+
} catch {
|
|
766
|
+
return response;
|
|
767
|
+
}
|
|
768
|
+
}
|
|
769
|
+
|
|
770
|
+
return response;
|
|
771
|
+
};
|
|
772
|
+
|
|
773
|
+
const pushTextPart = (parts: any[], text?: string) => {
|
|
774
|
+
const value = typeof text === 'string' && text.trim() ? text : undefined;
|
|
775
|
+
if (value) {
|
|
776
|
+
parts.push({ text: value });
|
|
777
|
+
}
|
|
778
|
+
};
|
|
779
|
+
|
|
780
|
+
const normalizedParts: any[] = [];
|
|
684
781
|
|
|
685
782
|
// Map roles to valid Google AI roles
|
|
686
783
|
switch (_message.role) {
|
|
687
784
|
case TLLMMessageRole.Assistant:
|
|
688
785
|
case TLLMMessageRole.System:
|
|
786
|
+
case TLLMMessageRole.Model:
|
|
689
787
|
_message.role = TLLMMessageRole.Model;
|
|
690
788
|
break;
|
|
789
|
+
case TLLMMessageRole.Function:
|
|
790
|
+
case TLLMMessageRole.Tool:
|
|
791
|
+
_message.role = TLLMMessageRole.Function;
|
|
792
|
+
break;
|
|
691
793
|
case TLLMMessageRole.User:
|
|
692
|
-
// User role is already valid
|
|
693
794
|
break;
|
|
694
795
|
default:
|
|
695
|
-
_message.role = TLLMMessageRole.User;
|
|
796
|
+
_message.role = TLLMMessageRole.User;
|
|
696
797
|
}
|
|
697
798
|
|
|
698
|
-
|
|
799
|
+
if (Array.isArray(message?.parts)) {
|
|
800
|
+
for (const part of message.parts) {
|
|
801
|
+
if (!part) continue;
|
|
802
|
+
|
|
803
|
+
const normalizedPart: any = { ...part };
|
|
804
|
+
|
|
805
|
+
if (typeof normalizedPart.text === 'string') {
|
|
806
|
+
normalizedPart.text = normalizedPart.text.trim() || '...';
|
|
807
|
+
}
|
|
808
|
+
|
|
809
|
+
if (part.functionCall) {
|
|
810
|
+
normalizedPart.functionCall = {
|
|
811
|
+
name: part.functionCall.name,
|
|
812
|
+
args: parseFunctionArgs(part.functionCall.args),
|
|
813
|
+
};
|
|
814
|
+
}
|
|
815
|
+
|
|
816
|
+
if (part.functionResponse) {
|
|
817
|
+
normalizedPart.functionResponse = {
|
|
818
|
+
name: part.functionResponse.name,
|
|
819
|
+
response: parseFunctionResponse(part.functionResponse.response),
|
|
820
|
+
};
|
|
821
|
+
}
|
|
822
|
+
|
|
823
|
+
const hasMeaningfulContent = Object.values(normalizedPart).some((value) => value !== undefined && value !== null && value !== '');
|
|
824
|
+
|
|
825
|
+
if (hasMeaningfulContent) {
|
|
826
|
+
normalizedParts.push(normalizedPart);
|
|
827
|
+
}
|
|
828
|
+
}
|
|
829
|
+
}
|
|
830
|
+
|
|
831
|
+
if (!normalizedParts.length && Array.isArray(message?.content)) {
|
|
832
|
+
for (const contentPart of message.content) {
|
|
833
|
+
if (!contentPart) continue;
|
|
834
|
+
|
|
835
|
+
if (typeof contentPart === 'string') {
|
|
836
|
+
pushTextPart(normalizedParts, contentPart);
|
|
837
|
+
} else if (typeof contentPart === 'object') {
|
|
838
|
+
if ('text' in contentPart && typeof contentPart.text === 'string') {
|
|
839
|
+
pushTextPart(normalizedParts, contentPart.text);
|
|
840
|
+
} else if ('functionCall' in contentPart && (contentPart as any).functionCall) {
|
|
841
|
+
const functionCallPart = (contentPart as any).functionCall;
|
|
842
|
+
normalizedParts.push({
|
|
843
|
+
functionCall: {
|
|
844
|
+
name: functionCallPart.name,
|
|
845
|
+
args: parseFunctionArgs(functionCallPart.args),
|
|
846
|
+
},
|
|
847
|
+
});
|
|
848
|
+
} else if ('functionResponse' in contentPart && (contentPart as any).functionResponse) {
|
|
849
|
+
const functionResponsePart = (contentPart as any).functionResponse;
|
|
850
|
+
normalizedParts.push({
|
|
851
|
+
functionResponse: {
|
|
852
|
+
name: functionResponsePart.name,
|
|
853
|
+
response: parseFunctionResponse(functionResponsePart.response),
|
|
854
|
+
},
|
|
855
|
+
});
|
|
856
|
+
} else {
|
|
857
|
+
const fallbackText = typeof (contentPart as any)?.toString === 'function' ? (contentPart as any).toString() : '';
|
|
858
|
+
if (fallbackText && fallbackText !== '[object Object]') {
|
|
859
|
+
pushTextPart(normalizedParts, fallbackText);
|
|
860
|
+
}
|
|
861
|
+
}
|
|
862
|
+
}
|
|
863
|
+
}
|
|
864
|
+
}
|
|
865
|
+
|
|
866
|
+
if (!normalizedParts.length) {
|
|
867
|
+
if (typeof message?.content === 'string') {
|
|
868
|
+
pushTextPart(normalizedParts, message.content);
|
|
869
|
+
} else if (message?.content && typeof message.content === 'object') {
|
|
870
|
+
if ('text' in (message.content as any)) {
|
|
871
|
+
pushTextPart(normalizedParts, (message.content as any).text);
|
|
872
|
+
} else {
|
|
873
|
+
const fallbackText = typeof (message.content as any)?.toString === 'function' ? (message.content as any).toString() : '';
|
|
874
|
+
if (fallbackText && fallbackText !== '[object Object]') {
|
|
875
|
+
pushTextPart(normalizedParts, fallbackText);
|
|
876
|
+
}
|
|
877
|
+
}
|
|
878
|
+
}
|
|
879
|
+
}
|
|
880
|
+
|
|
881
|
+
if (Array.isArray(message?.tool_calls) && message.tool_calls.length > 0) {
|
|
882
|
+
for (const toolCall of message.tool_calls) {
|
|
883
|
+
if (!toolCall?.function?.name) continue;
|
|
884
|
+
|
|
885
|
+
normalizedParts.push({
|
|
886
|
+
functionCall: {
|
|
887
|
+
name: toolCall.function.name,
|
|
888
|
+
args: parseFunctionArgs(toolCall.function.arguments),
|
|
889
|
+
},
|
|
890
|
+
});
|
|
891
|
+
}
|
|
892
|
+
}
|
|
699
893
|
|
|
700
|
-
if (
|
|
701
|
-
|
|
702
|
-
} else if (Array.isArray(_message?.content)) {
|
|
703
|
-
textContent = _message.content.map((textBlock) => textBlock?.text || '...').join(' ');
|
|
704
|
-
} else if (_message?.content) {
|
|
705
|
-
textContent = (_message.content as string) || '...';
|
|
894
|
+
if (!normalizedParts.length) {
|
|
895
|
+
normalizedParts.push({ text: '...' });
|
|
706
896
|
}
|
|
707
897
|
|
|
708
|
-
_message.parts =
|
|
898
|
+
_message.parts = normalizedParts as any;
|
|
709
899
|
|
|
710
900
|
delete _message.content; // Remove content to avoid error
|
|
901
|
+
delete (_message as any).tool_calls;
|
|
711
902
|
|
|
712
903
|
return _message;
|
|
713
904
|
});
|
|
@@ -20,6 +20,7 @@ import { LLMHelper } from '@sre/LLMManager/LLM.helper';
|
|
|
20
20
|
import { LLMConnector } from '../LLMConnector';
|
|
21
21
|
import { SystemEvents } from '@sre/Core/SystemEvents';
|
|
22
22
|
import { Logger } from '@sre/helpers/Log.helper';
|
|
23
|
+
import { hookAsync } from '@sre/Core/HookService';
|
|
23
24
|
|
|
24
25
|
const logger = Logger('GroqConnector');
|
|
25
26
|
|
|
@@ -50,6 +51,7 @@ export class GroqConnector extends LLMConnector {
|
|
|
50
51
|
return new Groq({ apiKey });
|
|
51
52
|
}
|
|
52
53
|
|
|
54
|
+
@hookAsync('LLMConnector.request')
|
|
53
55
|
protected async request({ acRequest, body, context }: ILLMRequestFuncParams): Promise<TLLMChatResponse> {
|
|
54
56
|
try {
|
|
55
57
|
logger.debug(`request ${this.name}`, acRequest.candidate);
|
|
@@ -95,6 +97,7 @@ export class GroqConnector extends LLMConnector {
|
|
|
95
97
|
}
|
|
96
98
|
}
|
|
97
99
|
|
|
100
|
+
@hookAsync('LLMConnector.streamRequest')
|
|
98
101
|
protected async streamRequest({ acRequest, body, context }: ILLMRequestFuncParams): Promise<EventEmitter> {
|
|
99
102
|
try {
|
|
100
103
|
logger.debug(`streamRequest ${this.name}`, acRequest.candidate);
|