@runflow-ai/sdk 1.0.17 → 1.0.19
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/README.md +14 -4
- package/dist/core/agent.d.ts +5 -30
- package/dist/core/agent.d.ts.map +1 -1
- package/dist/core/agent.js +259 -472
- package/dist/core/agent.js.map +1 -1
- package/dist/core/context.d.ts.map +1 -1
- package/dist/core/context.js +1 -11
- package/dist/core/context.js.map +1 -1
- package/dist/core/helpers/agent-context.d.ts +23 -0
- package/dist/core/helpers/agent-context.d.ts.map +1 -0
- package/dist/core/helpers/agent-context.js +90 -0
- package/dist/core/helpers/agent-context.js.map +1 -0
- package/dist/core/helpers/agent-memory.d.ts +17 -0
- package/dist/core/helpers/agent-memory.d.ts.map +1 -0
- package/dist/core/helpers/agent-memory.js +194 -0
- package/dist/core/helpers/agent-memory.js.map +1 -0
- package/dist/core/helpers/agent-rag.d.ts +22 -0
- package/dist/core/helpers/agent-rag.d.ts.map +1 -0
- package/dist/core/helpers/agent-rag.js +216 -0
- package/dist/core/helpers/agent-rag.js.map +1 -0
- package/dist/core/helpers/agent-utils.d.ts +13 -0
- package/dist/core/helpers/agent-utils.d.ts.map +1 -0
- package/dist/core/helpers/agent-utils.js +35 -0
- package/dist/core/helpers/agent-utils.js.map +1 -0
- package/dist/core/logger.d.ts +22 -0
- package/dist/core/logger.d.ts.map +1 -0
- package/dist/core/logger.js +91 -0
- package/dist/core/logger.js.map +1 -0
- package/dist/core/performance-logger.d.ts +45 -0
- package/dist/core/performance-logger.d.ts.map +1 -0
- package/dist/core/performance-logger.js +140 -0
- package/dist/core/performance-logger.js.map +1 -0
- package/dist/observability/trace-collector.d.ts.map +1 -1
- package/dist/observability/trace-collector.js +0 -16
- package/dist/observability/trace-collector.js.map +1 -1
- package/dist/types/all-types.d.ts +11 -3
- package/dist/types/all-types.d.ts.map +1 -1
- package/package.json +3 -1
package/dist/core/agent.js
CHANGED
|
@@ -4,14 +4,42 @@ exports.Agent = void 0;
|
|
|
4
4
|
const trace_collector_1 = require("../observability/trace-collector");
|
|
5
5
|
const api_client_1 = require("./api-client");
|
|
6
6
|
const context_1 = require("./context");
|
|
7
|
+
const logger_1 = require("./logger");
|
|
8
|
+
const performance_logger_1 = require("./performance-logger");
|
|
9
|
+
const agent_memory_1 = require("./helpers/agent-memory");
|
|
10
|
+
const agent_rag_1 = require("./helpers/agent-rag");
|
|
11
|
+
const agent_context_1 = require("./helpers/agent-context");
|
|
12
|
+
const agent_utils_1 = require("./helpers/agent-utils");
|
|
7
13
|
// ============================================================================
|
|
8
14
|
// AGENT CLASS
|
|
9
15
|
// ============================================================================
|
|
10
16
|
class Agent {
|
|
11
17
|
constructor(config) {
|
|
12
18
|
this.config = config;
|
|
13
|
-
// Configurar
|
|
14
|
-
this.
|
|
19
|
+
// Configurar logger
|
|
20
|
+
this.logger = (0, logger_1.createLogger)({
|
|
21
|
+
name: `agent:${config.name}`,
|
|
22
|
+
level: this.resolveLogLevel(config.debug),
|
|
23
|
+
enabled: config.debug !== false,
|
|
24
|
+
});
|
|
25
|
+
// ============================================================================
|
|
26
|
+
// AUTO-CREATE RAG TOOLS (Agentic RAG)
|
|
27
|
+
// ============================================================================
|
|
28
|
+
// Se RAG configurado, criar tools automaticamente
|
|
29
|
+
// LLM decide quando buscar (não busca sempre)
|
|
30
|
+
if (config.rag) {
|
|
31
|
+
this.logger.debug('RAG configuration detected, creating tools');
|
|
32
|
+
const ragTools = (0, agent_rag_1.createRAGTools)(config.rag, this.logger);
|
|
33
|
+
this.config.tools = {
|
|
34
|
+
...ragTools,
|
|
35
|
+
...config.tools,
|
|
36
|
+
};
|
|
37
|
+
// Injetar searchPrompt nas instructions (orienta quando buscar)
|
|
38
|
+
if (config.rag.searchPrompt) {
|
|
39
|
+
this.config.instructions += `\n\n${config.rag.searchPrompt}`;
|
|
40
|
+
this.logger.debug('Search prompt injected into instructions');
|
|
41
|
+
}
|
|
42
|
+
}
|
|
15
43
|
// Auto-initialize API client if not in execution context
|
|
16
44
|
if (!this.apiClient) {
|
|
17
45
|
this.apiClient = (0, api_client_1.createRunflowAPIClient)();
|
|
@@ -21,32 +49,34 @@ class Agent {
|
|
|
21
49
|
batchSize: 1, // Flush imediatamente após cada trace
|
|
22
50
|
flushInterval: 1000,
|
|
23
51
|
});
|
|
24
|
-
console.log('🔍 [SDK Agent] Trace collector initialized in constructor with projectId:', projectId);
|
|
25
52
|
}
|
|
26
53
|
}
|
|
27
54
|
// Injetar API client (feito pela execution engine)
|
|
28
55
|
_setAPIClient(apiClient) {
|
|
29
|
-
this.apiClient = apiClient;
|
|
30
|
-
// Use agentId from environment or config name as fallback
|
|
31
56
|
const projectId = process.env.RUNFLOW_AGENT_ID || this.config.name.toLowerCase().replace(/\s+/g, '-');
|
|
57
|
+
this.logger.debug('Setting API client', { projectId });
|
|
58
|
+
this.apiClient = apiClient;
|
|
32
59
|
this.traceCollector = (0, trace_collector_1.createTraceCollector)(apiClient, projectId, {
|
|
33
60
|
batchSize: 1, // Flush imediatamente após cada trace
|
|
34
61
|
flushInterval: 1000,
|
|
35
62
|
});
|
|
36
|
-
console.log('🔍 [SDK Agent] Trace collector initialized via _setAPIClient with projectId:', projectId);
|
|
37
63
|
}
|
|
38
64
|
// Geração simples (aceita string ou array de messages)
|
|
39
65
|
async generate(input) {
|
|
40
66
|
const isMessagesArray = Array.isArray(input);
|
|
41
|
-
console.log('💬 [SDK Agent] Generate called with', isMessagesArray ? `${input.length} messages` : `prompt length: ${input.length}`);
|
|
42
67
|
if (!this.apiClient) {
|
|
43
|
-
|
|
68
|
+
this.logger.error('API client not initialized');
|
|
44
69
|
throw new Error('Agent not initialized. API client not set.');
|
|
45
70
|
}
|
|
46
|
-
console.log('🌐 [SDK Agent] Calling chat API...');
|
|
47
71
|
const messages = isMessagesArray
|
|
48
72
|
? input
|
|
49
73
|
: [{ role: 'user', content: input }];
|
|
74
|
+
this.logger.debug('Starting generation', {
|
|
75
|
+
messagesCount: messages.length,
|
|
76
|
+
isMessagesArray,
|
|
77
|
+
provider: this.config.model.provider,
|
|
78
|
+
model: this.config.model.model
|
|
79
|
+
});
|
|
50
80
|
const chatRequest = {
|
|
51
81
|
projectId: '', // Será injetado pela engine
|
|
52
82
|
provider: this.config.model.provider,
|
|
@@ -61,22 +91,32 @@ class Agent {
|
|
|
61
91
|
stop: this.config.modelConfig?.stop,
|
|
62
92
|
seed: this.config.modelConfig?.seed,
|
|
63
93
|
};
|
|
64
|
-
console.log('📡 [SDK Agent] Chat request:', JSON.stringify(chatRequest, null, 2));
|
|
65
94
|
try {
|
|
66
95
|
const response = await this.apiClient.chat(chatRequest);
|
|
67
|
-
|
|
96
|
+
this.logger.debug('Generation completed', {
|
|
97
|
+
responseLength: response.text?.length || 0,
|
|
98
|
+
usage: response.usage
|
|
99
|
+
});
|
|
68
100
|
return { text: response.text };
|
|
69
101
|
}
|
|
70
102
|
catch (error) {
|
|
71
|
-
|
|
103
|
+
this.logger.error('Chat API failed', {
|
|
104
|
+
error: error instanceof Error ? error.message : 'Unknown error'
|
|
105
|
+
});
|
|
72
106
|
throw error;
|
|
73
107
|
}
|
|
74
108
|
}
|
|
75
109
|
// Geração com streaming
|
|
76
110
|
async generateStream(prompt) {
|
|
77
111
|
if (!this.apiClient) {
|
|
112
|
+
this.logger.error('API client not initialized for streaming');
|
|
78
113
|
throw new Error('Agent not initialized. API client not set.');
|
|
79
114
|
}
|
|
115
|
+
this.logger.debug('Starting stream generation', {
|
|
116
|
+
promptLength: prompt.length,
|
|
117
|
+
provider: this.config.model.provider,
|
|
118
|
+
model: this.config.model.model
|
|
119
|
+
});
|
|
80
120
|
const stream = this.apiClient.chatStream({
|
|
81
121
|
projectId: '',
|
|
82
122
|
provider: this.config.model.provider,
|
|
@@ -91,26 +131,38 @@ class Agent {
|
|
|
91
131
|
stop: this.config.modelConfig?.stop,
|
|
92
132
|
seed: this.config.modelConfig?.seed,
|
|
93
133
|
});
|
|
94
|
-
return
|
|
134
|
+
return (0, agent_utils_1.processStreamChunks)(stream, this.logger);
|
|
95
135
|
}
|
|
96
136
|
// Geração com tools (implementa loop de tool calling)
|
|
97
137
|
async generateWithTools(input) {
|
|
98
138
|
if (!this.apiClient) {
|
|
139
|
+
this.logger.error('API client not initialized for tool generation');
|
|
99
140
|
throw new Error('Agent not initialized. API client not set.');
|
|
100
141
|
}
|
|
101
142
|
if (!this.config.tools || Object.keys(this.config.tools).length === 0) {
|
|
143
|
+
this.logger.debug('No tools configured, falling back to simple generation');
|
|
102
144
|
return this.generate(input);
|
|
103
145
|
}
|
|
104
146
|
const isMessagesArray = Array.isArray(input);
|
|
105
147
|
let messages = isMessagesArray
|
|
106
148
|
? [...input]
|
|
107
149
|
: [{ role: 'user', content: input }];
|
|
150
|
+
this.logger.debug('Starting generation with tools', {
|
|
151
|
+
messagesCount: messages.length,
|
|
152
|
+
toolsCount: Object.keys(this.config.tools).length,
|
|
153
|
+
toolNames: Object.keys(this.config.tools)
|
|
154
|
+
});
|
|
108
155
|
const maxIterations = this.config.maxToolIterations || 10; // Prevenir loops infinitos
|
|
109
156
|
let iteration = 0;
|
|
110
157
|
while (iteration < maxIterations) {
|
|
111
158
|
iteration++;
|
|
112
|
-
|
|
159
|
+
this.logger.debug('Tool calling iteration', {
|
|
160
|
+
iteration,
|
|
161
|
+
maxIterations,
|
|
162
|
+
messagesCount: messages.length
|
|
163
|
+
});
|
|
113
164
|
// 🔍 Trace: LLM Call
|
|
165
|
+
performance_logger_1.performanceLogger.start(`llm.call.${iteration}`);
|
|
114
166
|
const llmStartTime = Date.now();
|
|
115
167
|
const llmSpan = this.traceCollector?.startSpan('llm_call', {
|
|
116
168
|
provider: this.config.model.provider,
|
|
@@ -119,16 +171,12 @@ class Agent {
|
|
|
119
171
|
hasTools: true,
|
|
120
172
|
toolsCount: Object.keys(this.config.tools).length,
|
|
121
173
|
});
|
|
122
|
-
// 🔍 Input do trace
|
|
174
|
+
// 🔍 Input do trace
|
|
123
175
|
const llmInput = {
|
|
124
176
|
messagesCount: messages.length,
|
|
125
177
|
temperature: this.config.modelConfig?.temperature,
|
|
126
178
|
maxTokens: this.config.modelConfig?.maxTokens,
|
|
127
179
|
};
|
|
128
|
-
if (this.debugConfig.logLLMCalls || this.debugConfig.logMessages) {
|
|
129
|
-
llmInput.messages = messages;
|
|
130
|
-
llmInput.instructions = this.config.instructions;
|
|
131
|
-
}
|
|
132
180
|
llmSpan?.setInput(llmInput);
|
|
133
181
|
const chatRequest = {
|
|
134
182
|
projectId: '', // Será injetado pela engine
|
|
@@ -146,17 +194,26 @@ class Agent {
|
|
|
146
194
|
seed: this.config.modelConfig?.seed,
|
|
147
195
|
};
|
|
148
196
|
const response = await this.apiClient.chat(chatRequest);
|
|
149
|
-
|
|
197
|
+
performance_logger_1.performanceLogger.end(`llm.call.${iteration}`, {
|
|
198
|
+
iteration,
|
|
199
|
+
hasToolCalls: !!response.toolCalls && response.toolCalls.length > 0,
|
|
200
|
+
toolCallsCount: response.toolCalls?.length || 0,
|
|
201
|
+
promptTokens: response.usage?.promptTokens,
|
|
202
|
+
completionTokens: response.usage?.completionTokens
|
|
203
|
+
});
|
|
204
|
+
this.logger.debug('LLM response received', {
|
|
205
|
+
iteration,
|
|
206
|
+
responseLength: response.text?.length || 0,
|
|
207
|
+
hasToolCalls: !!response.toolCalls && response.toolCalls.length > 0,
|
|
208
|
+
toolCallsCount: response.toolCalls?.length || 0,
|
|
209
|
+
usage: response.usage
|
|
210
|
+
});
|
|
211
|
+
// 🔍 Output do trace
|
|
150
212
|
const llmOutput = {
|
|
151
213
|
responseLength: response.text?.length || 0,
|
|
152
214
|
hasToolCalls: !!response.toolCalls && response.toolCalls.length > 0,
|
|
153
215
|
toolCallsCount: response.toolCalls?.length || 0,
|
|
154
216
|
};
|
|
155
|
-
if (this.debugConfig.logLLMCalls) {
|
|
156
|
-
llmOutput.responseText = response.text;
|
|
157
|
-
llmOutput.toolCalls = response.toolCalls;
|
|
158
|
-
llmOutput.usage = response.usage;
|
|
159
|
-
}
|
|
160
217
|
llmSpan?.setOutput(llmOutput);
|
|
161
218
|
llmSpan?.setMetadata({
|
|
162
219
|
provider: this.config.model.provider,
|
|
@@ -180,10 +237,12 @@ class Agent {
|
|
|
180
237
|
llmSpan?.finish();
|
|
181
238
|
// Se não há tool calls, retornar resposta final
|
|
182
239
|
if (!response.toolCalls || response.toolCalls.length === 0) {
|
|
183
|
-
|
|
240
|
+
this.logger.info('Generation completed without tool calls', {
|
|
241
|
+
iteration,
|
|
242
|
+
responseLength: response.text?.length || 0
|
|
243
|
+
});
|
|
184
244
|
return { text: response.text };
|
|
185
245
|
}
|
|
186
|
-
console.log(`🛠️ [SDK Agent] Processing ${response.toolCalls.length} tool call(s)`);
|
|
187
246
|
// Adicionar mensagem do assistente com tool calls
|
|
188
247
|
messages.push({
|
|
189
248
|
role: 'assistant',
|
|
@@ -193,6 +252,11 @@ class Agent {
|
|
|
193
252
|
// Executar cada tool call
|
|
194
253
|
for (const toolCall of response.toolCalls) {
|
|
195
254
|
const toolName = toolCall.name;
|
|
255
|
+
this.logger.debug('Processing tool call', {
|
|
256
|
+
toolName,
|
|
257
|
+
toolCallId: toolCall.id,
|
|
258
|
+
iteration
|
|
259
|
+
});
|
|
196
260
|
// Buscar tool por ID (pode estar com nome diferente da key no config)
|
|
197
261
|
let tool = this.config.tools[toolName];
|
|
198
262
|
// Se não encontrou, buscar por ID da tool
|
|
@@ -203,8 +267,10 @@ class Agent {
|
|
|
203
267
|
}
|
|
204
268
|
}
|
|
205
269
|
if (!tool) {
|
|
206
|
-
|
|
207
|
-
|
|
270
|
+
this.logger.warn('Tool not found', {
|
|
271
|
+
toolName,
|
|
272
|
+
availableTools: Object.keys(this.config.tools)
|
|
273
|
+
});
|
|
208
274
|
// Adicionar mensagem de erro
|
|
209
275
|
messages.push({
|
|
210
276
|
role: 'tool',
|
|
@@ -215,7 +281,6 @@ class Agent {
|
|
|
215
281
|
continue;
|
|
216
282
|
}
|
|
217
283
|
try {
|
|
218
|
-
console.log(`🔧 [SDK Agent] Executing tool: ${toolName}`);
|
|
219
284
|
// 🔍 Iniciar trace da tool execution
|
|
220
285
|
const toolStartTime = Date.now();
|
|
221
286
|
const toolSpan = this.traceCollector?.startSpan('tool_call', {
|
|
@@ -230,20 +295,28 @@ class Agent {
|
|
|
230
295
|
}
|
|
231
296
|
// 🔍 Input sempre vai completo para o trace
|
|
232
297
|
toolSpan?.setInput(args);
|
|
233
|
-
// Executar tool
|
|
234
|
-
const toolResult = await
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
298
|
+
// Executar tool com performance tracking
|
|
299
|
+
const toolResult = await performance_logger_1.performanceLogger.measure(`tool.${toolName}`, async () => {
|
|
300
|
+
return await tool.execute(args, {
|
|
301
|
+
runflowAPI: this.apiClient,
|
|
302
|
+
projectId: process.env.RUNFLOW_AGENT_ID || '',
|
|
303
|
+
companyId: process.env.RUNFLOW_TENANT_ID || '',
|
|
304
|
+
});
|
|
305
|
+
}, { toolId: tool.id, iteration });
|
|
240
306
|
// 🔍 Output sempre vai completo para o trace
|
|
241
307
|
const toolEndTime = Date.now();
|
|
308
|
+
const processingTimeMs = toolEndTime - toolStartTime;
|
|
309
|
+
this.logger.info('Tool execution completed', {
|
|
310
|
+
toolName,
|
|
311
|
+
toolId: tool.id,
|
|
312
|
+
processingTimeMs,
|
|
313
|
+
iteration
|
|
314
|
+
});
|
|
242
315
|
toolSpan?.setOutput(toolResult);
|
|
243
316
|
toolSpan?.setMetadata({
|
|
244
317
|
toolName,
|
|
245
318
|
toolId: tool.id,
|
|
246
|
-
processingTimeMs
|
|
319
|
+
processingTimeMs,
|
|
247
320
|
success: true,
|
|
248
321
|
});
|
|
249
322
|
toolSpan?.finish();
|
|
@@ -256,7 +329,12 @@ class Agent {
|
|
|
256
329
|
});
|
|
257
330
|
}
|
|
258
331
|
catch (error) {
|
|
259
|
-
|
|
332
|
+
this.logger.error('Tool execution failed', {
|
|
333
|
+
toolName,
|
|
334
|
+
toolId: tool.id,
|
|
335
|
+
error: error instanceof Error ? error.message : 'Unknown error',
|
|
336
|
+
iteration
|
|
337
|
+
});
|
|
260
338
|
// 🔍 Registrar erro no trace (se existe)
|
|
261
339
|
const toolSpan = this.traceCollector?.startSpan('tool_call', {
|
|
262
340
|
toolName,
|
|
@@ -284,30 +362,26 @@ class Agent {
|
|
|
284
362
|
}
|
|
285
363
|
}
|
|
286
364
|
// Se chegou aqui, atingiu o limite de iterações
|
|
287
|
-
|
|
365
|
+
this.logger.warn('Max tool calling iterations reached', {
|
|
366
|
+
maxIterations,
|
|
367
|
+
finalMessagesCount: messages.length
|
|
368
|
+
});
|
|
288
369
|
return { text: 'Maximum tool calling iterations reached. Please try again.' };
|
|
289
370
|
}
|
|
290
371
|
// Processamento principal (chamado pela execution engine)
|
|
291
372
|
async process(input, context) {
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
hasTools: !!(this.config.tools && Object.keys(this.config.tools).length > 0),
|
|
373
|
+
const processStartTime = Date.now();
|
|
374
|
+
performance_logger_1.performanceLogger.start('agent.process');
|
|
375
|
+
this.logger.info('Agent processing started', {
|
|
376
|
+
agentName: this.config.name,
|
|
377
|
+
messageLength: input.message?.length || 0,
|
|
378
|
+
sessionId: input.sessionId,
|
|
379
|
+
companyId: input.companyId
|
|
300
380
|
});
|
|
301
381
|
// Configurar API client com contexto
|
|
302
382
|
if (context?.apiClient) {
|
|
303
|
-
console.log('🔗 [SDK Agent] Using injected API client from context');
|
|
304
383
|
this._setAPIClient(context.apiClient);
|
|
305
384
|
}
|
|
306
|
-
else {
|
|
307
|
-
console.log('🔗 [SDK Agent] Using auto-configured API client');
|
|
308
|
-
// this.apiClient já foi inicializado no constructor
|
|
309
|
-
}
|
|
310
|
-
console.log('🌐 [SDK Agent] API Client configured:', !!this.apiClient);
|
|
311
385
|
// ============================================================================
|
|
312
386
|
// RESOLVER EXECUTION CONTEXT (prioridade: input > state > env > inferência)
|
|
313
387
|
// ============================================================================
|
|
@@ -315,27 +389,26 @@ class Agent {
|
|
|
315
389
|
const executionId = input.executionId
|
|
316
390
|
|| state.executionId
|
|
317
391
|
|| process.env.RUNFLOW_EXECUTION_ID
|
|
318
|
-
||
|
|
392
|
+
|| (0, agent_context_1.generateExecutionId)();
|
|
319
393
|
const threadId = input.threadId
|
|
320
394
|
|| state.threadId
|
|
321
395
|
|| process.env.RUNFLOW_THREAD_ID
|
|
322
|
-
||
|
|
396
|
+
|| (0, agent_context_1.generateThreadId)(input, this.logger);
|
|
323
397
|
const entityType = input.entityType
|
|
324
398
|
|| state.entityType
|
|
325
|
-
||
|
|
399
|
+
|| (0, agent_context_1.inferEntityType)(input, this.logger);
|
|
326
400
|
const entityValue = input.entityValue
|
|
327
401
|
|| state.entityValue
|
|
328
|
-
||
|
|
402
|
+
|| (0, agent_context_1.inferEntityValue)(input, this.logger);
|
|
329
403
|
const userId = input.userId
|
|
330
404
|
|| state.userId
|
|
331
|
-
||
|
|
332
|
-
|
|
405
|
+
|| (0, agent_context_1.inferUserId)(input, this.logger);
|
|
406
|
+
this.logger.debug('Execution context resolved', {
|
|
333
407
|
executionId,
|
|
334
408
|
threadId,
|
|
335
409
|
entityType,
|
|
336
|
-
entityValue
|
|
337
|
-
userId
|
|
338
|
-
source: input.threadId ? 'input' : state.threadId ? 'state' : 'inferred',
|
|
410
|
+
entityValue,
|
|
411
|
+
userId
|
|
339
412
|
});
|
|
340
413
|
// Configurar trace collector com contexto
|
|
341
414
|
if (this.traceCollector) {
|
|
@@ -384,6 +457,10 @@ class Agent {
|
|
|
384
457
|
span?.setInput(input);
|
|
385
458
|
// Se tem multi-agents, usar supervisor pattern
|
|
386
459
|
if (this.config.agents && Object.keys(this.config.agents).length > 0) {
|
|
460
|
+
this.logger.debug('Multi-agent configuration detected, delegating to supervisor', {
|
|
461
|
+
agentsCount: Object.keys(this.config.agents).length,
|
|
462
|
+
agentNames: Object.keys(this.config.agents)
|
|
463
|
+
});
|
|
387
464
|
return this.processMultiAgent(input, context);
|
|
388
465
|
}
|
|
389
466
|
// Memory management se configurado
|
|
@@ -393,48 +470,35 @@ class Agent {
|
|
|
393
470
|
// Prioridade 1: Custom memoryKey (override completo)
|
|
394
471
|
if (this.config.memory.memoryKey) {
|
|
395
472
|
memoryId = this.config.memory.memoryKey;
|
|
396
|
-
console.log('🧠 [SDK Agent] Loading memory with custom key:', memoryId);
|
|
397
473
|
}
|
|
398
474
|
// Prioridade 2: entityType + entityValue (do identify())
|
|
399
475
|
else if (entityType && entityValue) {
|
|
400
476
|
memoryId = `${entityType}:${entityValue}`;
|
|
401
|
-
console.log('🧠 [SDK Agent] Loading memory for entity:', memoryId);
|
|
402
477
|
}
|
|
403
478
|
// Prioridade 3: sessionId (backward compatibility)
|
|
404
479
|
else if (input.sessionId) {
|
|
405
480
|
memoryId = `session:${input.sessionId}`;
|
|
406
|
-
console.log('🧠 [SDK Agent] Loading memory for session (fallback):', memoryId);
|
|
407
481
|
}
|
|
408
482
|
if (memoryId) {
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
const ragData = await this.performRAG(input.message);
|
|
418
|
-
if (ragData) {
|
|
419
|
-
ragContext = ragData;
|
|
420
|
-
console.log('🔍 [SDK Agent] RAG context found:', ragData.substring(0, 100) + '...');
|
|
421
|
-
}
|
|
422
|
-
else {
|
|
423
|
-
console.log('🔍 [SDK Agent] No RAG context found');
|
|
483
|
+
this.logger.debug('Loading memory', {
|
|
484
|
+
memoryId,
|
|
485
|
+
memoryType: this.config.memory.type
|
|
486
|
+
});
|
|
487
|
+
const memoryLoadTime = await performance_logger_1.performanceLogger.measure('memory.load', async () => {
|
|
488
|
+
return await (0, agent_memory_1.loadMemory)(memoryId, this.apiClient, this.config.memory, this.traceCollector, this.logger);
|
|
489
|
+
}, { memoryId, memoryType: this.config.memory.type });
|
|
490
|
+
memoryMessages = memoryLoadTime;
|
|
424
491
|
}
|
|
425
492
|
}
|
|
493
|
+
// ============================================================================
|
|
494
|
+
// RAG agora é TOOL - LLM decide quando buscar
|
|
495
|
+
// ============================================================================
|
|
496
|
+
// REMOVIDO: performRAG() automático
|
|
497
|
+
// Agora: RAG tools criadas no constructor, LLM chama quando necessário
|
|
426
498
|
// Construir messages para LLM
|
|
427
499
|
let messages = [];
|
|
428
|
-
// 1. Adicionar RAG context como system message (se houver)
|
|
429
|
-
if (ragContext) {
|
|
430
|
-
messages.push({
|
|
431
|
-
role: 'system',
|
|
432
|
-
content: `Relevant context from knowledge base:\n\n${ragContext}`
|
|
433
|
-
});
|
|
434
|
-
}
|
|
435
500
|
// 2. Se tem messages[] no input, adicionar como contexto
|
|
436
501
|
if (input.messages && input.messages.length > 0) {
|
|
437
|
-
console.log('💬 [SDK Agent] Using provided messages as context:', input.messages.length);
|
|
438
502
|
const inputMessages = input.messages.map(msg => ({
|
|
439
503
|
role: msg.role,
|
|
440
504
|
content: msg.content // Pode ser string ou array multimodal
|
|
@@ -443,49 +507,85 @@ class Agent {
|
|
|
443
507
|
}
|
|
444
508
|
// 3. Adicionar historical messages da memória
|
|
445
509
|
if (memoryMessages.length > 0) {
|
|
446
|
-
console.log('🧠 [SDK Agent] Adding memory messages:', memoryMessages.length);
|
|
447
510
|
messages.push(...memoryMessages);
|
|
448
511
|
}
|
|
449
512
|
// 4. Adicionar mensagem atual do usuário
|
|
450
513
|
messages.push({ role: 'user', content: input.message });
|
|
451
|
-
console.log('📝 [SDK Agent] Final messages for LLM:', messages.length);
|
|
452
|
-
console.log('🤖 [SDK Agent] Calling LLM...');
|
|
453
514
|
// Processar com ou sem tools
|
|
454
|
-
const
|
|
515
|
+
const hasTools = this.config.tools && Object.keys(this.config.tools).length > 0;
|
|
516
|
+
this.logger.debug('Processing messages', {
|
|
517
|
+
messagesCount: messages.length,
|
|
518
|
+
hasTools,
|
|
519
|
+
toolsCount: hasTools ? Object.keys(this.config.tools).length : 0
|
|
520
|
+
});
|
|
521
|
+
performance_logger_1.performanceLogger.start('llm.processing');
|
|
522
|
+
const result = hasTools
|
|
455
523
|
? await this.generateWithTools(messages)
|
|
456
524
|
: await this.generate(messages);
|
|
457
|
-
|
|
525
|
+
const llmProcessingTime = performance_logger_1.performanceLogger.end('llm.processing', {
|
|
526
|
+
hasTools,
|
|
527
|
+
messagesCount: messages.length
|
|
528
|
+
});
|
|
458
529
|
// Salvar na memória se configurado
|
|
530
|
+
let memorySaveTime = 0;
|
|
459
531
|
if (this.config.memory && memoryId) {
|
|
460
|
-
|
|
461
|
-
await
|
|
462
|
-
|
|
532
|
+
this.logger.debug('Saving to memory', { memoryId });
|
|
533
|
+
await performance_logger_1.performanceLogger.measure('memory.save', async () => {
|
|
534
|
+
await (0, agent_memory_1.saveToMemory)(memoryId, input.message, result.text, this.apiClient, this.config.memory, this.config.model, this.traceCollector, this.logger);
|
|
535
|
+
}, { memoryId });
|
|
536
|
+
memorySaveTime = Date.now() - processStartTime - llmProcessingTime;
|
|
463
537
|
}
|
|
464
538
|
const output = {
|
|
465
539
|
message: result.text,
|
|
466
540
|
metadata: {
|
|
467
541
|
model: this.config.model.model,
|
|
468
542
|
provider: this.config.model.provider,
|
|
469
|
-
ragUsed:
|
|
543
|
+
ragUsed: false, // Agora detectado via toolCalls
|
|
470
544
|
memoryUsed: memoryMessages.length > 0,
|
|
471
545
|
sessionId: input.sessionId,
|
|
472
546
|
},
|
|
473
547
|
};
|
|
474
|
-
console.log('📤 [SDK Agent] Final output:', JSON.stringify(output, null, 2));
|
|
475
548
|
// Finalizar trace com métricas de performance
|
|
476
|
-
const
|
|
477
|
-
|
|
549
|
+
const processingTimeMs = Date.now() - processStartTime;
|
|
550
|
+
// Performance summary (se ativado)
|
|
551
|
+
if (performance_logger_1.performanceLogger.isEnabled()) {
|
|
552
|
+
const memoryLoadTime = memoryMessages.length > 0 ?
|
|
553
|
+
(processStartTime + 100) : 0; // Estimativa se não medido diretamente
|
|
554
|
+
performance_logger_1.performanceLogger.summary('agent.process', {
|
|
555
|
+
'context_resolution': 5, // Tempo mínimo de setup
|
|
556
|
+
'memory_load': memoryLoadTime,
|
|
557
|
+
'llm_processing': llmProcessingTime,
|
|
558
|
+
'memory_save': memorySaveTime,
|
|
559
|
+
}, processingTimeMs);
|
|
560
|
+
}
|
|
561
|
+
performance_logger_1.performanceLogger.end('agent.process', {
|
|
562
|
+
agentName: this.config.name,
|
|
563
|
+
responseLength: result.text?.length || 0,
|
|
564
|
+
memoryUsed: memoryMessages.length > 0,
|
|
565
|
+
toolsUsed: (0, agent_utils_1.getUsedTools)(this.config.tools).length,
|
|
566
|
+
executionId,
|
|
567
|
+
threadId
|
|
568
|
+
});
|
|
569
|
+
this.logger.info('Agent processing completed', {
|
|
570
|
+
agentName: this.config.name,
|
|
571
|
+
processingTimeMs,
|
|
572
|
+
responseLength: result.text?.length || 0,
|
|
573
|
+
memoryUsed: memoryMessages.length > 0,
|
|
574
|
+
toolsUsed: (0, agent_utils_1.getUsedTools)(this.config.tools),
|
|
575
|
+
executionId,
|
|
576
|
+
threadId
|
|
577
|
+
});
|
|
478
578
|
span?.setOutput(output);
|
|
479
579
|
span?.setMetadata({
|
|
480
580
|
// Feature usage atualizado
|
|
481
|
-
ragUsed:
|
|
581
|
+
ragUsed: false, // Agora detectado via tool calls
|
|
482
582
|
memoryUsed: memoryMessages.length > 0,
|
|
483
|
-
toolsUsed:
|
|
583
|
+
toolsUsed: (0, agent_utils_1.getUsedTools)(this.config.tools),
|
|
484
584
|
// Performance metrics
|
|
485
585
|
processingTimeMs,
|
|
486
586
|
// Quality metrics
|
|
487
587
|
confidence: 0.9, // Placeholder - pode ser calculado baseado no contexto
|
|
488
|
-
reasoning:
|
|
588
|
+
reasoning: 'Direct LLM response',
|
|
489
589
|
});
|
|
490
590
|
// Adicionar custos se disponível (placeholder - será implementado quando tivermos dados reais)
|
|
491
591
|
span?.setCosts({
|
|
@@ -505,17 +605,19 @@ class Agent {
|
|
|
505
605
|
span?.finish();
|
|
506
606
|
// Forçar flush dos traces pendentes
|
|
507
607
|
if (this.traceCollector) {
|
|
508
|
-
console.log('🚀 [SDK Agent] Forcing trace flush...');
|
|
509
608
|
await this.traceCollector.flush();
|
|
510
609
|
}
|
|
511
|
-
console.log('🎉 [SDK Agent] Process completed successfully');
|
|
512
610
|
return output;
|
|
513
611
|
}
|
|
514
612
|
// Multi-agent processing (supervisor pattern)
|
|
515
613
|
async processMultiAgent(input, context) {
|
|
614
|
+
this.logger.debug('Starting multi-agent processing with supervisor pattern');
|
|
516
615
|
// Criar supervisor automático
|
|
517
616
|
const supervisor = this.createSupervisor();
|
|
518
617
|
// Supervisor decide qual agent usar
|
|
618
|
+
this.logger.debug('Supervisor analyzing agent selection', {
|
|
619
|
+
availableAgents: Object.keys(this.config.agents)
|
|
620
|
+
});
|
|
519
621
|
const decision = await supervisor.generate(`
|
|
520
622
|
Available agents:
|
|
521
623
|
${Object.entries(this.config.agents).map(([name, config]) => `- ${name}: ${config.instructions}`).join('\n')}
|
|
@@ -527,12 +629,19 @@ Which agent should handle this? Respond with just the agent name.
|
|
|
527
629
|
const selectedAgentName = decision.text.trim();
|
|
528
630
|
const selectedAgentConfig = this.config.agents[selectedAgentName];
|
|
529
631
|
if (!selectedAgentConfig) {
|
|
530
|
-
// Fallback para primeiro agent
|
|
531
632
|
const firstAgentName = Object.keys(this.config.agents)[0];
|
|
633
|
+
this.logger.warn('Supervisor selected invalid agent, using fallback', {
|
|
634
|
+
selectedAgentName,
|
|
635
|
+
fallbackAgentName: firstAgentName
|
|
636
|
+
});
|
|
637
|
+
// Fallback para primeiro agent
|
|
532
638
|
const firstAgentConfig = this.config.agents[firstAgentName];
|
|
533
639
|
const agent = new Agent(firstAgentConfig);
|
|
534
640
|
return agent.process(input, context);
|
|
535
641
|
}
|
|
642
|
+
this.logger.info('Supervisor selected agent', {
|
|
643
|
+
selectedAgentName
|
|
644
|
+
});
|
|
536
645
|
// Executar agent selecionado
|
|
537
646
|
const selectedAgent = new Agent(selectedAgentConfig);
|
|
538
647
|
return selectedAgent.process(input, context);
|
|
@@ -545,76 +654,27 @@ Which agent should handle this? Respond with just the agent name.
|
|
|
545
654
|
model: this.config.model, // Mesmo modelo do agent principal
|
|
546
655
|
});
|
|
547
656
|
}
|
|
548
|
-
//
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
657
|
+
// ============================================================================
|
|
658
|
+
// LOGGER CONFIGURATION
|
|
659
|
+
// ============================================================================
|
|
660
|
+
/**
|
|
661
|
+
* Resolve o nível de log baseado na configuração de debug
|
|
662
|
+
*/
|
|
663
|
+
resolveLogLevel(debug) {
|
|
664
|
+
// Se debug é false, desativar logs
|
|
665
|
+
if (debug === false) {
|
|
666
|
+
return 'silent';
|
|
552
667
|
}
|
|
553
|
-
//
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
operation: 'vector_search',
|
|
557
|
-
vectorStore: this.config.rag.vectorStore,
|
|
558
|
-
k: this.config.rag.k || 5,
|
|
559
|
-
threshold: this.config.rag.threshold || 0.7,
|
|
560
|
-
});
|
|
561
|
-
ragSpan?.setInput({ query });
|
|
562
|
-
try {
|
|
563
|
-
const searchResults = await this.apiClient.vectorSearch(query, {
|
|
564
|
-
vectorStore: this.config.rag.vectorStore,
|
|
565
|
-
k: this.config.rag.k || 5,
|
|
566
|
-
threshold: this.config.rag.threshold || 0.7,
|
|
567
|
-
});
|
|
568
|
-
if (searchResults.results.length === 0) {
|
|
569
|
-
ragSpan?.setOutput({ resultsCount: 0, hasResults: false });
|
|
570
|
-
ragSpan?.setMetadata({
|
|
571
|
-
operation: 'vector_search',
|
|
572
|
-
vectorStore: this.config.rag.vectorStore,
|
|
573
|
-
resultsCount: 0,
|
|
574
|
-
processingTimeMs: Date.now() - ragStartTime,
|
|
575
|
-
success: true,
|
|
576
|
-
});
|
|
577
|
-
ragSpan?.finish();
|
|
578
|
-
return null;
|
|
579
|
-
}
|
|
580
|
-
const context = searchResults.results
|
|
581
|
-
.map((result) => result.content)
|
|
582
|
-
.join('\n\n');
|
|
583
|
-
// 🔍 Finalizar trace (com dados completos se debug ativado)
|
|
584
|
-
const ragOutput = {
|
|
585
|
-
resultsCount: searchResults.results.length,
|
|
586
|
-
hasResults: true,
|
|
587
|
-
contextLength: context.length,
|
|
588
|
-
};
|
|
589
|
-
if (this.debugConfig.logRAG) {
|
|
590
|
-
ragOutput.results = searchResults.results;
|
|
591
|
-
ragOutput.contextGenerated = context;
|
|
592
|
-
}
|
|
593
|
-
ragSpan?.setOutput(ragOutput);
|
|
594
|
-
ragSpan?.setMetadata({
|
|
595
|
-
operation: 'vector_search',
|
|
596
|
-
vectorStore: this.config.rag.vectorStore,
|
|
597
|
-
resultsCount: searchResults.results.length,
|
|
598
|
-
k: this.config.rag.k || 5,
|
|
599
|
-
threshold: this.config.rag.threshold || 0.7,
|
|
600
|
-
processingTimeMs: Date.now() - ragStartTime,
|
|
601
|
-
success: true,
|
|
602
|
-
});
|
|
603
|
-
ragSpan?.finish();
|
|
604
|
-
return context;
|
|
668
|
+
// Se debug é true, usar debug level
|
|
669
|
+
if (debug === true) {
|
|
670
|
+
return 'debug';
|
|
605
671
|
}
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
operation: 'vector_search',
|
|
610
|
-
vectorStore: this.config.rag.vectorStore,
|
|
611
|
-
success: false,
|
|
612
|
-
error: error instanceof Error ? error.message : 'Unknown error',
|
|
613
|
-
processingTimeMs: Date.now() - ragStartTime,
|
|
614
|
-
});
|
|
615
|
-
ragSpan?.finish();
|
|
616
|
-
return null;
|
|
672
|
+
// Se debug é objeto com level, usar o nível especificado
|
|
673
|
+
if (typeof debug === 'object' && debug.level) {
|
|
674
|
+
return debug.level;
|
|
617
675
|
}
|
|
676
|
+
// Default: info em produção, debug em desenvolvimento
|
|
677
|
+
return process.env.NODE_ENV === 'production' ? 'info' : 'debug';
|
|
618
678
|
}
|
|
619
679
|
// Getters
|
|
620
680
|
get name() {
|
|
@@ -632,293 +692,19 @@ Which agent should handle this? Respond with just the agent name.
|
|
|
632
692
|
get isMultiAgent() {
|
|
633
693
|
return !!(this.config.agents && Object.keys(this.config.agents).length > 0);
|
|
634
694
|
}
|
|
635
|
-
// Obter tools utilizadas (para traces)
|
|
636
|
-
getUsedTools() {
|
|
637
|
-
if (!this.config.tools)
|
|
638
|
-
return [];
|
|
639
|
-
return Object.keys(this.config.tools);
|
|
640
|
-
}
|
|
641
|
-
// ============================================================================
|
|
642
|
-
// DEBUG HELPERS
|
|
643
|
-
// ============================================================================
|
|
644
|
-
/**
|
|
645
|
-
* Resolver configuração de debug
|
|
646
|
-
*/
|
|
647
|
-
resolveDebugConfig(debug) {
|
|
648
|
-
// Verificar variável de ambiente
|
|
649
|
-
const envDebug = process.env.RUNFLOW_DEBUG === 'true' || process.env.RUNFLOW_LOG_LEVEL === 'verbose';
|
|
650
|
-
if (debug === true || envDebug) {
|
|
651
|
-
// Debug simples = todos logs ativados
|
|
652
|
-
return {
|
|
653
|
-
enabled: true,
|
|
654
|
-
logMessages: true,
|
|
655
|
-
logLLMCalls: true,
|
|
656
|
-
logToolCalls: true,
|
|
657
|
-
logRAG: true,
|
|
658
|
-
logMemory: true,
|
|
659
|
-
truncateAt: undefined,
|
|
660
|
-
};
|
|
661
|
-
}
|
|
662
|
-
else if (typeof debug === 'object' && debug.enabled) {
|
|
663
|
-
// Debug customizado
|
|
664
|
-
return {
|
|
665
|
-
enabled: true,
|
|
666
|
-
logMessages: debug.logMessages !== false,
|
|
667
|
-
logLLMCalls: debug.logLLMCalls !== false,
|
|
668
|
-
logToolCalls: debug.logToolCalls !== false,
|
|
669
|
-
logRAG: debug.logRAG !== false,
|
|
670
|
-
logMemory: debug.logMemory !== false,
|
|
671
|
-
truncateAt: debug.truncateAt,
|
|
672
|
-
};
|
|
673
|
-
}
|
|
674
|
-
return { enabled: false };
|
|
675
|
-
}
|
|
676
|
-
// ============================================================================
|
|
677
|
-
// CONTEXT RESOLUTION HELPERS
|
|
678
|
-
// ============================================================================
|
|
679
|
-
/**
|
|
680
|
-
* Generate unique execution ID
|
|
681
|
-
*/
|
|
682
|
-
generateExecutionId() {
|
|
683
|
-
return `exec_${Date.now()}_${Math.random().toString(36).substring(2, 8)}`;
|
|
684
|
-
}
|
|
685
|
-
/**
|
|
686
|
-
* Generate threadId based on input (fallback quando não fornecido)
|
|
687
|
-
*/
|
|
688
|
-
generateThreadId(input) {
|
|
689
|
-
const companyId = input.companyId || 'default';
|
|
690
|
-
// Se tem sessionId, usar como thread
|
|
691
|
-
if (input.sessionId) {
|
|
692
|
-
return `session_${companyId}_${input.sessionId}`;
|
|
693
|
-
}
|
|
694
|
-
// Fallback: gerar único
|
|
695
|
-
return `thread_${companyId}_${Date.now()}_${Math.random().toString(36).substring(2, 8)}`;
|
|
696
|
-
}
|
|
697
|
-
/**
|
|
698
|
-
* Infer entityType from input metadata
|
|
699
|
-
*/
|
|
700
|
-
inferEntityType(input) {
|
|
701
|
-
if (input.metadata?.phone)
|
|
702
|
-
return 'phone';
|
|
703
|
-
if (input.metadata?.email)
|
|
704
|
-
return 'email';
|
|
705
|
-
if (input.metadata?.contactId)
|
|
706
|
-
return 'hubspot_contact';
|
|
707
|
-
if (input.sessionId)
|
|
708
|
-
return 'session';
|
|
709
|
-
return 'session'; // Default
|
|
710
|
-
}
|
|
711
|
-
/**
|
|
712
|
-
* Infer entityValue from input metadata
|
|
713
|
-
*/
|
|
714
|
-
inferEntityValue(input) {
|
|
715
|
-
if (input.metadata?.phone)
|
|
716
|
-
return input.metadata.phone;
|
|
717
|
-
if (input.metadata?.email)
|
|
718
|
-
return input.metadata.email;
|
|
719
|
-
if (input.metadata?.contactId)
|
|
720
|
-
return input.metadata.contactId;
|
|
721
|
-
if (input.sessionId)
|
|
722
|
-
return input.sessionId;
|
|
723
|
-
return null;
|
|
724
|
-
}
|
|
725
|
-
/**
|
|
726
|
-
* Infer userId from input metadata
|
|
727
|
-
*/
|
|
728
|
-
inferUserId(input) {
|
|
729
|
-
if (input.metadata?.phone)
|
|
730
|
-
return input.metadata.phone;
|
|
731
|
-
if (input.metadata?.email)
|
|
732
|
-
return input.metadata.email;
|
|
733
|
-
if (input.metadata?.contactId)
|
|
734
|
-
return input.metadata.contactId;
|
|
735
|
-
return null;
|
|
736
|
-
}
|
|
737
|
-
// ============================================================================
|
|
738
|
-
// MEMORY MANAGEMENT
|
|
739
|
-
// ============================================================================
|
|
740
|
-
// Carregar memória da entidade (retorna array de messages)
|
|
741
|
-
async loadMemory(memoryId) {
|
|
742
|
-
if (!this.apiClient || !this.config.memory) {
|
|
743
|
-
return [];
|
|
744
|
-
}
|
|
745
|
-
// 🔍 Trace: Memory Load
|
|
746
|
-
const memoryLoadStartTime = Date.now();
|
|
747
|
-
const memoryLoadSpan = this.traceCollector?.startSpan('memory_operation', {
|
|
748
|
-
operation: 'load',
|
|
749
|
-
memoryId,
|
|
750
|
-
memoryType: this.config.memory.type,
|
|
751
|
-
});
|
|
752
|
-
try {
|
|
753
|
-
const memoryData = await this.apiClient.memory.get(memoryId);
|
|
754
|
-
if (!memoryData.messages || memoryData.messages.length === 0) {
|
|
755
|
-
memoryLoadSpan?.setOutput({ messagesCount: 0, hasHistory: false });
|
|
756
|
-
memoryLoadSpan?.setMetadata({
|
|
757
|
-
operation: 'load',
|
|
758
|
-
memoryId,
|
|
759
|
-
messagesCount: 0,
|
|
760
|
-
processingTimeMs: Date.now() - memoryLoadStartTime,
|
|
761
|
-
success: true,
|
|
762
|
-
});
|
|
763
|
-
memoryLoadSpan?.finish();
|
|
764
|
-
return [];
|
|
765
|
-
}
|
|
766
|
-
// Aplicar configurações de memória
|
|
767
|
-
let messages = memoryData.messages;
|
|
768
|
-
// Limitar por número de turnos
|
|
769
|
-
if (this.config.memory.maxTurns) {
|
|
770
|
-
messages = messages.slice(-this.config.memory.maxTurns * 2); // user + assistant = 2 messages per turn
|
|
771
|
-
}
|
|
772
|
-
// Limitar por tokens (aproximado)
|
|
773
|
-
if (this.config.memory.maxTokens) {
|
|
774
|
-
let totalTokens = 0;
|
|
775
|
-
const filteredMessages = [];
|
|
776
|
-
for (let i = messages.length - 1; i >= 0; i--) {
|
|
777
|
-
const messageTokens = Math.ceil(messages[i].content.length / 4);
|
|
778
|
-
if (totalTokens + messageTokens <= this.config.memory.maxTokens) {
|
|
779
|
-
filteredMessages.unshift(messages[i]);
|
|
780
|
-
totalTokens += messageTokens;
|
|
781
|
-
}
|
|
782
|
-
else {
|
|
783
|
-
break;
|
|
784
|
-
}
|
|
785
|
-
}
|
|
786
|
-
messages = filteredMessages;
|
|
787
|
-
}
|
|
788
|
-
// Retornar messages como array (formato nativo do LLM)
|
|
789
|
-
const result = messages.map((msg) => ({
|
|
790
|
-
role: msg.role,
|
|
791
|
-
content: msg.content,
|
|
792
|
-
}));
|
|
793
|
-
// 🔍 Finalizar trace (com dados completos se debug ativado)
|
|
794
|
-
const memoryOutput = {
|
|
795
|
-
messagesCount: messages.length,
|
|
796
|
-
hasHistory: result.length > 0,
|
|
797
|
-
};
|
|
798
|
-
if (this.debugConfig.logMemory) {
|
|
799
|
-
memoryOutput.messages = result;
|
|
800
|
-
}
|
|
801
|
-
memoryLoadSpan?.setOutput(memoryOutput);
|
|
802
|
-
memoryLoadSpan?.setMetadata({
|
|
803
|
-
operation: 'load',
|
|
804
|
-
memoryId,
|
|
805
|
-
messagesCount: messages.length,
|
|
806
|
-
maxTurns: this.config.memory.maxTurns,
|
|
807
|
-
processingTimeMs: Date.now() - memoryLoadStartTime,
|
|
808
|
-
success: true,
|
|
809
|
-
});
|
|
810
|
-
memoryLoadSpan?.finish();
|
|
811
|
-
return result;
|
|
812
|
-
}
|
|
813
|
-
catch (error) {
|
|
814
|
-
console.error('Failed to load memory:', error);
|
|
815
|
-
// 🔍 Trace de erro
|
|
816
|
-
memoryLoadSpan?.setMetadata({
|
|
817
|
-
operation: 'load',
|
|
818
|
-
memoryId,
|
|
819
|
-
success: false,
|
|
820
|
-
error: error instanceof Error ? error.message : 'Unknown error',
|
|
821
|
-
processingTimeMs: Date.now() - memoryLoadStartTime,
|
|
822
|
-
});
|
|
823
|
-
memoryLoadSpan?.finish();
|
|
824
|
-
return [];
|
|
825
|
-
}
|
|
826
|
-
}
|
|
827
|
-
// Salvar na memória
|
|
828
|
-
async saveToMemory(memoryId, userMessage, assistantMessage) {
|
|
829
|
-
if (!this.apiClient || !this.config.memory) {
|
|
830
|
-
return;
|
|
831
|
-
}
|
|
832
|
-
// 🔍 Trace: Memory Save
|
|
833
|
-
const memorySaveStartTime = Date.now();
|
|
834
|
-
const memorySaveSpan = this.traceCollector?.startSpan('memory_operation', {
|
|
835
|
-
operation: 'save',
|
|
836
|
-
memoryId,
|
|
837
|
-
memoryType: this.config.memory.type,
|
|
838
|
-
});
|
|
839
|
-
try {
|
|
840
|
-
// Adicionar mensagem do usuário
|
|
841
|
-
await this.apiClient.memory.append(memoryId, {
|
|
842
|
-
role: 'user',
|
|
843
|
-
content: userMessage,
|
|
844
|
-
timestamp: new Date(),
|
|
845
|
-
});
|
|
846
|
-
// Adicionar resposta do assistant
|
|
847
|
-
await this.apiClient.memory.append(memoryId, {
|
|
848
|
-
role: 'assistant',
|
|
849
|
-
content: assistantMessage,
|
|
850
|
-
timestamp: new Date(),
|
|
851
|
-
metadata: {
|
|
852
|
-
model: this.config.model.model,
|
|
853
|
-
},
|
|
854
|
-
});
|
|
855
|
-
// Resumir se necessário
|
|
856
|
-
let summarized = false;
|
|
857
|
-
if (this.config.memory.summarizeAfter) {
|
|
858
|
-
const currentMemory = await this.apiClient.memory.get(memoryId);
|
|
859
|
-
if (currentMemory.messages.length >= this.config.memory.summarizeAfter) {
|
|
860
|
-
await this.apiClient.memory.summarize(memoryId);
|
|
861
|
-
summarized = true;
|
|
862
|
-
}
|
|
863
|
-
}
|
|
864
|
-
// 🔍 Finalizar trace (com dados completos se debug ativado)
|
|
865
|
-
const memorySaveOutput = {
|
|
866
|
-
messagesSaved: 2,
|
|
867
|
-
summarized,
|
|
868
|
-
};
|
|
869
|
-
if (this.debugConfig.logMemory) {
|
|
870
|
-
memorySaveOutput.userMessage = userMessage;
|
|
871
|
-
memorySaveOutput.assistantMessage = assistantMessage;
|
|
872
|
-
}
|
|
873
|
-
memorySaveSpan?.setOutput(memorySaveOutput);
|
|
874
|
-
memorySaveSpan?.setMetadata({
|
|
875
|
-
operation: 'save',
|
|
876
|
-
memoryId,
|
|
877
|
-
messagesSaved: 2,
|
|
878
|
-
summarized,
|
|
879
|
-
summarizeAfter: this.config.memory.summarizeAfter,
|
|
880
|
-
processingTimeMs: Date.now() - memorySaveStartTime,
|
|
881
|
-
success: true,
|
|
882
|
-
});
|
|
883
|
-
memorySaveSpan?.finish();
|
|
884
|
-
}
|
|
885
|
-
catch (error) {
|
|
886
|
-
console.error('Failed to save to memory:', error);
|
|
887
|
-
// 🔍 Trace de erro
|
|
888
|
-
memorySaveSpan?.setMetadata({
|
|
889
|
-
operation: 'save',
|
|
890
|
-
memoryId,
|
|
891
|
-
success: false,
|
|
892
|
-
error: error instanceof Error ? error.message : 'Unknown error',
|
|
893
|
-
processingTimeMs: Date.now() - memorySaveStartTime,
|
|
894
|
-
});
|
|
895
|
-
memorySaveSpan?.finish();
|
|
896
|
-
}
|
|
897
|
-
}
|
|
898
|
-
// Processar stream chunks (helper)
|
|
899
|
-
async *processStreamChunks(stream) {
|
|
900
|
-
for await (const chunk of stream) {
|
|
901
|
-
if (chunk.type === 'content') {
|
|
902
|
-
yield { text: chunk.content || '', done: false };
|
|
903
|
-
}
|
|
904
|
-
else if (chunk.type === 'done') {
|
|
905
|
-
yield { text: '', done: true };
|
|
906
|
-
break;
|
|
907
|
-
}
|
|
908
|
-
else if (chunk.type === 'error') {
|
|
909
|
-
throw new Error(chunk.error || 'Streaming error');
|
|
910
|
-
}
|
|
911
|
-
}
|
|
912
|
-
}
|
|
913
695
|
// Streaming com memória
|
|
914
696
|
async processStream(input, context) {
|
|
697
|
+
this.logger.debug('Starting stream processing', {
|
|
698
|
+
messageLength: input.message?.length || 0,
|
|
699
|
+
sessionId: input.sessionId
|
|
700
|
+
});
|
|
915
701
|
if (context?.apiClient) {
|
|
916
702
|
this.apiClient = context.apiClient;
|
|
917
703
|
}
|
|
918
704
|
// Resolver entity context
|
|
919
705
|
const state = context_1.Runflow.getState();
|
|
920
|
-
const entityType = input.entityType || state.entityType ||
|
|
921
|
-
const entityValue = input.entityValue || state.entityValue ||
|
|
706
|
+
const entityType = input.entityType || state.entityType || (0, agent_context_1.inferEntityType)(input, this.logger);
|
|
707
|
+
const entityValue = input.entityValue || state.entityValue || (0, agent_context_1.inferEntityValue)(input, this.logger);
|
|
922
708
|
// Resolver memoryId com mesma prioridade do process()
|
|
923
709
|
let memoryId = null;
|
|
924
710
|
if (this.config.memory) {
|
|
@@ -938,25 +724,16 @@ Which agent should handle this? Respond with just the agent name.
|
|
|
938
724
|
// Carregar memória se configurado
|
|
939
725
|
let memoryMessages = [];
|
|
940
726
|
if (this.config.memory && memoryId) {
|
|
941
|
-
|
|
942
|
-
|
|
943
|
-
// RAG automático se configurado
|
|
944
|
-
let ragContext = '';
|
|
945
|
-
if (this.config.rag?.autoSearch) {
|
|
946
|
-
const ragData = await this.performRAG(input.message);
|
|
947
|
-
if (ragData) {
|
|
948
|
-
ragContext = ragData;
|
|
949
|
-
}
|
|
727
|
+
this.logger.debug('Loading memory for streaming', { memoryId });
|
|
728
|
+
memoryMessages = await (0, agent_memory_1.loadMemory)(memoryId, this.apiClient, this.config.memory, this.traceCollector, this.logger);
|
|
950
729
|
}
|
|
730
|
+
// ============================================================================
|
|
731
|
+
// RAG agora é TOOL - LLM decide quando buscar
|
|
732
|
+
// ============================================================================
|
|
733
|
+
// REMOVIDO: performRAG() automático
|
|
734
|
+
// Agora: RAG tools criadas no constructor, LLM chama quando necessário
|
|
951
735
|
// Construir messages para streaming
|
|
952
736
|
let messages = [];
|
|
953
|
-
// Adicionar RAG context
|
|
954
|
-
if (ragContext) {
|
|
955
|
-
messages.push({
|
|
956
|
-
role: 'system',
|
|
957
|
-
content: `Relevant context from knowledge base:\n\n${ragContext}`
|
|
958
|
-
});
|
|
959
|
-
}
|
|
960
737
|
// Adicionar memory messages
|
|
961
738
|
if (memoryMessages.length > 0) {
|
|
962
739
|
messages.push(...memoryMessages);
|
|
@@ -984,6 +761,11 @@ Which agent should handle this? Respond with just the agent name.
|
|
|
984
761
|
});
|
|
985
762
|
// Criar async generator
|
|
986
763
|
const self = this;
|
|
764
|
+
const logger = this.logger;
|
|
765
|
+
const apiClient = this.apiClient;
|
|
766
|
+
const memoryConfig = this.config.memory;
|
|
767
|
+
const modelConfig = this.config.model;
|
|
768
|
+
const traceCollector = this.traceCollector;
|
|
987
769
|
return (async function* () {
|
|
988
770
|
let fullResponse = '';
|
|
989
771
|
for await (const chunk of stream) {
|
|
@@ -993,13 +775,18 @@ Which agent should handle this? Respond with just the agent name.
|
|
|
993
775
|
}
|
|
994
776
|
else if (chunk.type === 'done') {
|
|
995
777
|
// Salvar na memória quando streaming terminar
|
|
996
|
-
if (
|
|
997
|
-
|
|
778
|
+
if (memoryConfig && memoryId && apiClient) {
|
|
779
|
+
logger.debug('Saving stream response to memory', { memoryId });
|
|
780
|
+
await (0, agent_memory_1.saveToMemory)(memoryId, input.message, fullResponse, apiClient, memoryConfig, modelConfig, traceCollector, logger);
|
|
998
781
|
}
|
|
782
|
+
logger.info('Stream processing completed', {
|
|
783
|
+
responseLength: fullResponse.length
|
|
784
|
+
});
|
|
999
785
|
yield { text: '', done: true };
|
|
1000
786
|
break;
|
|
1001
787
|
}
|
|
1002
788
|
else if (chunk.type === 'error') {
|
|
789
|
+
logger.error('Streaming error', { error: chunk.error });
|
|
1003
790
|
throw new Error(chunk.error || 'Streaming error');
|
|
1004
791
|
}
|
|
1005
792
|
}
|