@smythos/sre 1.6.14 → 1.7.5

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.
Files changed (115) hide show
  1. package/CHANGELOG +15 -0
  2. package/dist/index.js +66 -58
  3. package/dist/index.js.map +1 -1
  4. package/dist/types/Components/APIEndpoint.class.d.ts +2 -8
  5. package/dist/types/Components/Component.class.d.ts +9 -0
  6. package/dist/types/Components/Triggers/Gmail.trigger.d.ts +0 -17
  7. package/dist/types/Components/Triggers/JobScheduler.trigger.d.ts +10 -0
  8. package/dist/types/Components/Triggers/Trigger.class.d.ts +11 -0
  9. package/dist/types/Components/index.d.ts +6 -0
  10. package/dist/types/Core/Connector.class.d.ts +1 -0
  11. package/dist/types/Core/ConnectorsService.d.ts +2 -0
  12. package/dist/types/Core/HookService.d.ts +1 -1
  13. package/dist/types/helpers/BinaryInput.helper.d.ts +1 -1
  14. package/dist/types/helpers/Conversation.helper.d.ts +2 -0
  15. package/dist/types/helpers/Crypto.helper.d.ts +8 -0
  16. package/dist/types/helpers/LocalCache.helper.d.ts +18 -0
  17. package/dist/types/helpers/TemplateString.helper.d.ts +2 -1
  18. package/dist/types/index.d.ts +13 -0
  19. package/dist/types/subsystems/AgentManager/Agent.class.d.ts +4 -2
  20. package/dist/types/subsystems/AgentManager/AgentData.service/AgentDataConnector.d.ts +13 -0
  21. package/dist/types/subsystems/AgentManager/AgentData.service/connectors/NullAgentData.class.d.ts +1 -4
  22. package/dist/types/subsystems/AgentManager/Scheduler.service/Job.class.d.ts +29 -6
  23. package/dist/types/subsystems/AgentManager/Scheduler.service/SchedulerConnector.d.ts +11 -3
  24. package/dist/types/subsystems/AgentManager/Scheduler.service/connectors/LocalScheduler.class.d.ts +31 -7
  25. package/dist/types/subsystems/IO/VectorDB.service/VectorDBConnector.d.ts +4 -4
  26. package/dist/types/subsystems/IO/VectorDB.service/connectors/MilvusVectorDB.class.d.ts +2 -2
  27. package/dist/types/subsystems/IO/VectorDB.service/connectors/PineconeVectorDB.class.d.ts +2 -2
  28. package/dist/types/subsystems/IO/VectorDB.service/connectors/RAMVecrtorDB.class.d.ts +2 -2
  29. package/dist/types/subsystems/IO/VectorDB.service/embed/BaseEmbedding.d.ts +16 -9
  30. package/dist/types/subsystems/IO/VectorDB.service/embed/index.d.ts +4 -1
  31. package/dist/types/subsystems/LLMManager/LLM.inference.d.ts +36 -2
  32. package/dist/types/subsystems/LLMManager/LLM.service/connectors/Perplexity.class.d.ts +2 -5
  33. package/dist/types/subsystems/LLMManager/LLM.service/connectors/openai/OpenAIConnector.class.d.ts +3 -6
  34. package/dist/types/subsystems/LLMManager/LLM.service/connectors/openai/apiInterfaces/ResponsesApiInterface.d.ts +7 -0
  35. package/dist/types/subsystems/LLMManager/LLM.service/connectors/xAI.class.d.ts +2 -5
  36. package/dist/types/types/Agent.types.d.ts +1 -0
  37. package/dist/types/types/LLM.types.d.ts +56 -36
  38. package/dist/types/types/SRE.types.d.ts +4 -1
  39. package/dist/types/types/VectorDB.types.d.ts +6 -3
  40. package/dist/types/utils/string.utils.d.ts +0 -4
  41. package/package.json +6 -2
  42. package/src/Components/APICall/OAuth.helper.ts +30 -35
  43. package/src/Components/APIEndpoint.class.ts +25 -6
  44. package/src/Components/Classifier.class.ts +8 -2
  45. package/src/Components/Component.class.ts +11 -0
  46. package/src/Components/GenAILLM.class.ts +11 -7
  47. package/src/Components/LLMAssistant.class.ts +12 -3
  48. package/src/Components/ScrapflyWebScrape.class.ts +8 -1
  49. package/src/Components/TavilyWebSearch.class.ts +4 -1
  50. package/src/Components/Triggers/Gmail.trigger.ts +282 -0
  51. package/src/Components/Triggers/JobScheduler.trigger.ts +45 -0
  52. package/src/Components/Triggers/README.md +3 -0
  53. package/src/Components/Triggers/Trigger.class.ts +101 -0
  54. package/src/Components/Triggers/WhatsApp.trigger.ts +219 -0
  55. package/src/Components/index.ts +8 -0
  56. package/src/Core/AgentProcess.helper.ts +4 -6
  57. package/src/Core/Connector.class.ts +11 -3
  58. package/src/Core/ConnectorsService.ts +5 -0
  59. package/src/Core/ExternalEventsReceiver.ts +317 -0
  60. package/src/Core/HookService.ts +20 -6
  61. package/src/Core/SmythRuntime.class.ts +20 -2
  62. package/src/Core/SystemEvents.ts +17 -0
  63. package/src/Core/boot.ts +2 -0
  64. package/src/helpers/BinaryInput.helper.ts +8 -8
  65. package/src/helpers/Conversation.helper.ts +46 -12
  66. package/src/helpers/Crypto.helper.ts +28 -0
  67. package/src/helpers/LocalCache.helper.ts +18 -0
  68. package/src/helpers/TemplateString.helper.ts +20 -9
  69. package/src/index.ts +13 -0
  70. package/src/index.ts.bak +13 -0
  71. package/src/subsystems/AGENTS.md +594 -0
  72. package/src/subsystems/AgentManager/Agent.class.ts +73 -21
  73. package/src/subsystems/AgentManager/AgentData.service/AgentDataConnector.ts +30 -6
  74. package/src/subsystems/AgentManager/AgentData.service/connectors/NullAgentData.class.ts +2 -2
  75. package/src/subsystems/AgentManager/AgentLogger.class.ts +1 -1
  76. package/src/subsystems/AgentManager/AgentRuntime.class.ts +34 -5
  77. package/src/subsystems/AgentManager/Scheduler.service/Job.class.ts +414 -0
  78. package/src/subsystems/AgentManager/Scheduler.service/Schedule.class.ts +200 -0
  79. package/src/subsystems/AgentManager/Scheduler.service/SchedulerConnector.ts +200 -0
  80. package/src/subsystems/AgentManager/Scheduler.service/connectors/LocalScheduler.class.ts +767 -0
  81. package/src/subsystems/AgentManager/Scheduler.service/index.ts +11 -0
  82. package/src/subsystems/IO/VectorDB.service/VectorDBConnector.ts +15 -4
  83. package/src/subsystems/IO/VectorDB.service/connectors/MilvusVectorDB.class.ts +32 -11
  84. package/src/subsystems/IO/VectorDB.service/connectors/PineconeVectorDB.class.ts +27 -10
  85. package/src/subsystems/IO/VectorDB.service/connectors/RAMVecrtorDB.class.ts +25 -9
  86. package/src/subsystems/IO/VectorDB.service/embed/BaseEmbedding.ts +182 -12
  87. package/src/subsystems/IO/VectorDB.service/embed/GoogleEmbedding.ts +1 -1
  88. package/src/subsystems/IO/VectorDB.service/embed/OpenAIEmbedding.ts +1 -1
  89. package/src/subsystems/IO/VectorDB.service/embed/index.ts +12 -2
  90. package/src/subsystems/LLMManager/LLM.inference.ts +76 -17
  91. package/src/subsystems/LLMManager/LLM.service/LLMCredentials.helper.ts +61 -2
  92. package/src/subsystems/LLMManager/LLM.service/connectors/Anthropic.class.ts +3 -0
  93. package/src/subsystems/LLMManager/LLM.service/connectors/Bedrock.class.ts +3 -1
  94. package/src/subsystems/LLMManager/LLM.service/connectors/Echo.class.ts +5 -1
  95. package/src/subsystems/LLMManager/LLM.service/connectors/GoogleAI.class.ts +247 -56
  96. package/src/subsystems/LLMManager/LLM.service/connectors/Groq.class.ts +3 -0
  97. package/src/subsystems/LLMManager/LLM.service/connectors/Ollama.class.ts +28 -21
  98. package/src/subsystems/LLMManager/LLM.service/connectors/Perplexity.class.ts +3 -0
  99. package/src/subsystems/LLMManager/LLM.service/connectors/VertexAI.class.ts +121 -33
  100. package/src/subsystems/LLMManager/LLM.service/connectors/openai/OpenAIConnector.class.ts +38 -27
  101. package/src/subsystems/LLMManager/LLM.service/connectors/openai/apiInterfaces/ChatCompletionsApiInterface.ts +3 -2
  102. package/src/subsystems/LLMManager/LLM.service/connectors/openai/apiInterfaces/ResponsesApiInterface.ts +117 -20
  103. package/src/subsystems/LLMManager/LLM.service/connectors/xAI.class.ts +3 -0
  104. package/src/subsystems/LLMManager/ModelsProvider.service/ModelsProviderConnector.ts +3 -8
  105. package/src/subsystems/LLMManager/ModelsProvider.service/connectors/JSONModelsProvider.class.ts +4 -1
  106. package/src/subsystems/MemoryManager/Cache.service/connectors/RedisCache.class.ts +12 -0
  107. package/src/subsystems/MemoryManager/LLMContext.ts +3 -8
  108. package/src/subsystems/MemoryManager/RuntimeContext.ts +10 -9
  109. package/src/subsystems/Security/Credentials/Credentials.class.ts +1 -0
  110. package/src/subsystems/Security/Credentials/ManagedOAuth2Credentials.class.ts +106 -0
  111. package/src/types/Agent.types.ts +1 -0
  112. package/src/types/LLM.types.ts +68 -40
  113. package/src/types/SRE.types.ts +3 -0
  114. package/src/types/VectorDB.types.ts +7 -3
  115. package/src/utils/string.utils.ts +193 -191
@@ -15,7 +15,7 @@ import { IModelsProviderRequest, ModelsProviderConnector } from './ModelsProvide
15
15
 
16
16
  const console = Logger('LLMInference');
17
17
 
18
- type TPromptParams = { query?: string; contextWindow?: any[]; files?: any[]; params: TLLMParams };
18
+ type TPromptParams = { query?: string; contextWindow?: any[]; files?: any[]; params: TLLMParams; onFallback?: (data: any) => void };
19
19
 
20
20
  export class LLMInference {
21
21
  private model: string | TLLMModel;
@@ -52,12 +52,11 @@ export class LLMInference {
52
52
 
53
53
  public static user(candidate: AccessCandidate): any {}
54
54
 
55
-
56
55
  public get connector(): LLMConnector {
57
56
  return this.llmConnector;
58
57
  }
59
58
 
60
- public async prompt({ query, contextWindow, files, params }: TPromptParams, isInFallback: boolean = false) {
59
+ public async prompt({ query, contextWindow, files, params, onFallback = () => {} }: TPromptParams, isInFallback: boolean = false) {
61
60
  let messages = contextWindow || [];
62
61
 
63
62
  if (query) {
@@ -71,6 +70,11 @@ export class LLMInference {
71
70
  params.messages = messages;
72
71
  params.files = files;
73
72
 
73
+ // If a fallback model is used, trigger the onFallback callback to notify the caller.
74
+ if (isInFallback && typeof onFallback === 'function') {
75
+ onFallback({ model: this.model });
76
+ }
77
+
74
78
  try {
75
79
  let response: TLLMChatResponse = await this.llmConnector.requester(AccessCandidate.agent(params.agentId)).request(params);
76
80
 
@@ -89,8 +93,9 @@ export class LLMInference {
89
93
  // Attempt fallback for custom models (only if not already in fallback)
90
94
  if (!isInFallback) {
91
95
  try {
92
- const fallbackResult = await this.executeFallback('prompt', { query, contextWindow, files, params });
93
-
96
+ const fallbackParams = await this.getSafeFallbackParams(params);
97
+ const fallbackResult = await this.executeFallback('prompt', { query, contextWindow, files, params: fallbackParams, onFallback });
98
+
94
99
  // If fallback succeeded, return the result
95
100
  if (fallbackResult !== null) {
96
101
  return fallbackResult;
@@ -107,7 +112,7 @@ export class LLMInference {
107
112
  }
108
113
  }
109
114
 
110
- public async promptStream({ query, contextWindow, files, params }: TPromptParams, isInFallback: boolean = false) {
115
+ public async promptStream({ query, contextWindow, files, params, onFallback = () => {} }: TPromptParams, isInFallback: boolean = false) {
111
116
  let messages = contextWindow || [];
112
117
 
113
118
  if (query) {
@@ -121,14 +126,26 @@ export class LLMInference {
121
126
  params.messages = messages;
122
127
  params.files = files;
123
128
 
129
+ // If a fallback model is used, trigger the onFallback callback to notify the caller.
130
+ if (isInFallback && typeof onFallback === 'function') {
131
+ onFallback({ model: this.model });
132
+ }
133
+
124
134
  try {
125
135
  return await this.llmConnector.user(AccessCandidate.agent(params.agentId)).streamRequest(params);
126
136
  } catch (error) {
127
137
  // Attempt fallback for custom models (only if not already in fallback)
128
138
  if (!isInFallback) {
129
139
  try {
130
- const fallbackResult = await this.executeFallback('promptStream', { query, contextWindow, files, params });
131
-
140
+ const fallbackParams = await this.getSafeFallbackParams(params);
141
+ const fallbackResult = await this.executeFallback('promptStream', {
142
+ query,
143
+ contextWindow,
144
+ files,
145
+ params: fallbackParams,
146
+ onFallback,
147
+ });
148
+
132
149
  // If fallback succeeded, return the result
133
150
  if (fallbackResult !== null) {
134
151
  return fallbackResult;
@@ -151,38 +168,80 @@ export class LLMInference {
151
168
  }
152
169
  }
153
170
 
171
+ /**
172
+ * Creates a safe, minimal set of parameters when switching to a fallback LLM provider.
173
+ *
174
+ * **Why this exists:**
175
+ * Model settings persist in the component's configuration data, even when you switch models.
176
+ * This can cause issues when fallback models run with settings the user can't see or track.
177
+ *
178
+ * **Real-world scenario:**
179
+ * 1. User configures a GPT-5 model and sets `reasoning_effort: "high"`
180
+ * 2. This setting gets saved to the component's configuration
181
+ * 3. User switches to a custom model (e.g., for cost savings)
182
+ * 4. The UI now shows custom model options - GPT-5 options are hidden
183
+ * 5. **BUT**: `reasoning_effort: "high"` is STILL in the config data!
184
+ * 6. Custom model has GPT-5 as its fallback
185
+ * 7. Primary custom model fails → automatically switches to GPT-5 fallback
186
+ * 8. GPT-5 fallback runs with the hidden `reasoning_effort: "high"` setting
187
+ * 9. `reasoning_effort: "high"` requires a high `max_tokens` value
188
+ * 10. If `max_tokens` is too low → the request fails
189
+ *
190
+ * **The impact:**
191
+ * Users can't track response quality properly because they don't know what configuration
192
+ * the fallback model is using. The UI doesn't show fallback model settings, so users have
193
+ * no visibility into how responses are being generated.
194
+ *
195
+ * **What this function does:**
196
+ * Strips out provider-specific settings when falling back, using only universal parameters.
197
+ * This ensures predictable behavior. (Note: A more robust solution would be showing fallback
198
+ * configuration in the UI, but for now this handles it at the parameter level.)
199
+ *
200
+ * @param params - The full set of LLM parameters from the original request
201
+ * @returns A filtered parameter object with only provider-agnostic, safe parameters
202
+ */
203
+ private async getSafeFallbackParams(params: TLLMParams): Promise<TLLMParams> {
204
+ const fallbackParams = {
205
+ agentId: params.agentId,
206
+ model: params.model,
207
+ maxContextWindowLength: params.maxContextWindowLength,
208
+ maxTokens: params.maxTokens,
209
+ messages: params.messages,
210
+ passthrough: params.passthrough,
211
+ useContextWindow: params.useContextWindow,
212
+ };
213
+
214
+ return fallbackParams;
215
+ }
154
216
 
155
217
  /**
156
218
  * Executes fallback logic for custom models when the primary model fails.
157
219
  * This method checks if a fallback model is configured and invokes the appropriate LLM method.
158
220
  * Prevents infinite loops by passing a flag to indicate we're in a fallback attempt.
159
- *
221
+ *
160
222
  * @param methodName - The name of the method being called ('prompt' or 'promptStream')
161
223
  * @param args - The original arguments passed to the method
162
224
  * @returns The result from the fallback execution, or null if fallback should not be attempted
163
225
  */
164
- private async executeFallback(
165
- methodName: 'prompt' | 'promptStream',
166
- args: TPromptParams
167
- ): Promise<any> {
226
+ private async executeFallback(methodName: 'prompt' | 'promptStream', args: TPromptParams): Promise<any> {
168
227
  const isCustomModel = await this.modelProviderReq.isUserCustomLLM(this.model);
169
228
  const fallbackModel = await this.modelProviderReq.getFallbackLLM(this.model);
170
-
229
+
171
230
  // Only execute fallback if it's a custom model with a configured fallback
172
231
  if (!isCustomModel || !fallbackModel) {
173
232
  return null;
174
233
  }
175
234
 
176
235
  console.info(`Attempting fallback from ${this.model} to ${fallbackModel}`);
177
-
236
+
178
237
  // Mutate the model and connector to use fallback
179
238
  this.model = fallbackModel;
180
-
239
+
181
240
  const llmProvider = await this.modelProviderReq.getProvider(fallbackModel);
182
241
  if (llmProvider) {
183
242
  this.llmConnector = ConnectorService.getLLMConnector(llmProvider);
184
243
  }
185
-
244
+
186
245
  // Call the appropriate method with isInFallback=true to prevent further fallbacks
187
246
  if (methodName === 'prompt') {
188
247
  return await this.prompt(args, true);
@@ -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 passed directly
15
- return credentialsMode;
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 new Promise((resolve) => setTimeout(resolve, 50));
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