@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.
Files changed (38) hide show
  1. package/README.md +14 -4
  2. package/dist/core/agent.d.ts +5 -30
  3. package/dist/core/agent.d.ts.map +1 -1
  4. package/dist/core/agent.js +259 -472
  5. package/dist/core/agent.js.map +1 -1
  6. package/dist/core/context.d.ts.map +1 -1
  7. package/dist/core/context.js +1 -11
  8. package/dist/core/context.js.map +1 -1
  9. package/dist/core/helpers/agent-context.d.ts +23 -0
  10. package/dist/core/helpers/agent-context.d.ts.map +1 -0
  11. package/dist/core/helpers/agent-context.js +90 -0
  12. package/dist/core/helpers/agent-context.js.map +1 -0
  13. package/dist/core/helpers/agent-memory.d.ts +17 -0
  14. package/dist/core/helpers/agent-memory.d.ts.map +1 -0
  15. package/dist/core/helpers/agent-memory.js +194 -0
  16. package/dist/core/helpers/agent-memory.js.map +1 -0
  17. package/dist/core/helpers/agent-rag.d.ts +22 -0
  18. package/dist/core/helpers/agent-rag.d.ts.map +1 -0
  19. package/dist/core/helpers/agent-rag.js +216 -0
  20. package/dist/core/helpers/agent-rag.js.map +1 -0
  21. package/dist/core/helpers/agent-utils.d.ts +13 -0
  22. package/dist/core/helpers/agent-utils.d.ts.map +1 -0
  23. package/dist/core/helpers/agent-utils.js +35 -0
  24. package/dist/core/helpers/agent-utils.js.map +1 -0
  25. package/dist/core/logger.d.ts +22 -0
  26. package/dist/core/logger.d.ts.map +1 -0
  27. package/dist/core/logger.js +91 -0
  28. package/dist/core/logger.js.map +1 -0
  29. package/dist/core/performance-logger.d.ts +45 -0
  30. package/dist/core/performance-logger.d.ts.map +1 -0
  31. package/dist/core/performance-logger.js +140 -0
  32. package/dist/core/performance-logger.js.map +1 -0
  33. package/dist/observability/trace-collector.d.ts.map +1 -1
  34. package/dist/observability/trace-collector.js +0 -16
  35. package/dist/observability/trace-collector.js.map +1 -1
  36. package/dist/types/all-types.d.ts +11 -3
  37. package/dist/types/all-types.d.ts.map +1 -1
  38. package/package.json +3 -1
@@ -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 debug
14
- this.debugConfig = this.resolveDebugConfig(config.debug);
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
- console.error('❌ [SDK Agent] API client not initialized!');
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
- console.log(' [SDK Agent] Chat response received:', response);
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
- console.error('❌ [SDK Agent] Chat API failed:', error);
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 this.processStreamChunks(stream);
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
- console.log(`🔄 [SDK Agent] Tool calling iteration ${iteration}/${maxIterations}`);
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 (detalhado se debug ativado)
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
- // 🔍 Output do trace (detalhado se debug ativado)
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
- console.log(' [SDK Agent] No tool calls - returning final response');
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
- console.error(`❌ [SDK Agent] Tool not found: ${toolName}`);
207
- console.error(` Available tools:`, Object.keys(this.config.tools));
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 tool.execute(args, {
235
- runflowAPI: this.apiClient,
236
- projectId: process.env.RUNFLOW_AGENT_ID || '',
237
- companyId: process.env.RUNFLOW_TENANT_ID || '',
238
- });
239
- console.log(`✅ [SDK Agent] Tool executed successfully: ${toolName}`, toolResult);
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: toolEndTime - toolStartTime,
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
- console.error(`❌ [SDK Agent] Tool execution failed: ${toolName}`, error);
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
- console.warn('⚠️ [SDK Agent] Max tool calling iterations reached');
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
- console.log('🤖 [SDK Agent] Starting process...');
293
- console.log('📥 [SDK Agent] Input:', JSON.stringify(input, null, 2));
294
- console.log('🔧 [SDK Agent] Config:', {
295
- name: this.config.name,
296
- model: this.config.model,
297
- hasMemory: !!this.config.memory,
298
- hasRAG: !!this.config.rag,
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
- || this.generateExecutionId();
392
+ || (0, agent_context_1.generateExecutionId)();
319
393
  const threadId = input.threadId
320
394
  || state.threadId
321
395
  || process.env.RUNFLOW_THREAD_ID
322
- || this.generateThreadId(input);
396
+ || (0, agent_context_1.generateThreadId)(input, this.logger);
323
397
  const entityType = input.entityType
324
398
  || state.entityType
325
- || this.inferEntityType(input);
399
+ || (0, agent_context_1.inferEntityType)(input, this.logger);
326
400
  const entityValue = input.entityValue
327
401
  || state.entityValue
328
- || this.inferEntityValue(input);
402
+ || (0, agent_context_1.inferEntityValue)(input, this.logger);
329
403
  const userId = input.userId
330
404
  || state.userId
331
- || this.inferUserId(input);
332
- console.log('🔍 [SDK Agent] Execution Context:', {
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: entityValue || '(none)',
337
- userId: userId || '(none)',
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
- memoryMessages = await this.loadMemory(memoryId);
410
- console.log('🧠 [SDK Agent] Memory loaded:', memoryMessages.length > 0 ? `${memoryMessages.length} messages` : 'No history');
411
- }
412
- }
413
- // RAG automático se configurado
414
- let ragContext = '';
415
- if (this.config.rag?.autoSearch) {
416
- console.log('🔍 [SDK Agent] Performing RAG search for:', input.message);
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 result = this.config.tools && Object.keys(this.config.tools).length > 0
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
- console.log('✅ [SDK Agent] LLM response received:', result.text.substring(0, 100) + '...');
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
- console.log('💾 [SDK Agent] Saving to memory:', memoryId);
461
- await this.saveToMemory(memoryId, input.message, result.text);
462
- console.log('💾 [SDK Agent] Memory saved');
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: !!ragContext,
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 executionEndTime = Date.now();
477
- const processingTimeMs = executionEndTime - executionStartTime;
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: !!ragContext,
581
+ ragUsed: false, // Agora detectado via tool calls
482
582
  memoryUsed: memoryMessages.length > 0,
483
- toolsUsed: this.getUsedTools(),
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: ragContext ? 'Used RAG context for enhanced response' : 'Direct LLM response',
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
- // RAG automático
549
- async performRAG(query) {
550
- if (!this.config.rag || !this.apiClient) {
551
- return null;
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
- // 🔍 Trace: RAG Search
554
- const ragStartTime = Date.now();
555
- const ragSpan = this.traceCollector?.startSpan('rag_search', {
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
- catch (error) {
607
- console.error('RAG search failed:', error);
608
- ragSpan?.setMetadata({
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 || this.inferEntityType(input);
921
- const entityValue = input.entityValue || state.entityValue || this.inferEntityValue(input);
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
- memoryMessages = await this.loadMemory(memoryId);
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 (self.config.memory && memoryId) {
997
- await self.saveToMemory(memoryId, input.message, fullResponse);
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
  }