@probelabs/probe 0.6.0-rc116 → 0.6.0-rc118

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.
@@ -188,9 +188,23 @@ export class ProbeAgent {
188
188
  if (this.enableBash && wrappedTools.bashToolInstance) {
189
189
  this.toolImplementations.bash = wrappedTools.bashToolInstance;
190
190
  }
191
-
191
+
192
192
  // Store wrapped tools for ACP system
193
193
  this.wrappedTools = wrappedTools;
194
+
195
+ // Log available tools in debug mode
196
+ if (this.debug) {
197
+ console.error('\n[DEBUG] ========================================');
198
+ console.error('[DEBUG] ProbeAgent Tools Initialized');
199
+ console.error('[DEBUG] Session ID:', this.sessionId);
200
+ console.error('[DEBUG] Available tools:');
201
+ for (const toolName of Object.keys(this.toolImplementations)) {
202
+ console.error(`[DEBUG] - ${toolName}`);
203
+ }
204
+ console.error('[DEBUG] Allowed folders:', this.allowedFolders);
205
+ console.error('[DEBUG] Outline mode:', this.outline);
206
+ console.error('[DEBUG] ========================================\n');
207
+ }
194
208
  }
195
209
 
196
210
  /**
@@ -366,6 +380,9 @@ export class ProbeAgent {
366
380
  async processImageReferences(content) {
367
381
  if (!content) return;
368
382
 
383
+ // First, try to parse listFiles output format to extract directory context
384
+ const listFilesDirectories = this.extractListFilesDirectories(content);
385
+
369
386
  // Enhanced pattern to detect image file mentions in various contexts
370
387
  // Looks for: "image", "file", "screenshot", etc. followed by path-like strings with image extensions
371
388
  const extensionsPattern = `(?:${SUPPORTED_IMAGE_EXTENSIONS.join('|')})`;
@@ -400,10 +417,55 @@ export class ProbeAgent {
400
417
 
401
418
  // Process each found path
402
419
  for (const imagePath of foundPaths) {
403
- await this.loadImageIfValid(imagePath);
420
+ // Try to resolve the path with directory context from listFiles output
421
+ let resolvedPath = imagePath;
422
+
423
+ // If the path is just a filename (no directory separator), try to find it in listFiles directories
424
+ if (!imagePath.includes('/') && !imagePath.includes('\\')) {
425
+ for (const dir of listFilesDirectories) {
426
+ const potentialPath = resolve(dir, imagePath);
427
+ // Check if this file exists by attempting to load it
428
+ const loaded = await this.loadImageIfValid(potentialPath);
429
+ if (loaded) {
430
+ // Successfully loaded with this directory context
431
+ if (this.debug) {
432
+ console.log(`[DEBUG] Resolved ${imagePath} to ${potentialPath} using listFiles context`);
433
+ }
434
+ break; // Found it, no need to try other directories
435
+ }
436
+ }
437
+ } else {
438
+ // Path already has directory info, load as-is
439
+ await this.loadImageIfValid(resolvedPath);
440
+ }
404
441
  }
405
442
  }
406
443
 
444
+ /**
445
+ * Extract directory paths from listFiles tool output
446
+ * @param {string} content - Tool output content
447
+ * @returns {string[]} - Array of directory paths
448
+ */
449
+ extractListFilesDirectories(content) {
450
+ const directories = [];
451
+
452
+ // Pattern to match listFiles output format: "/path/to/directory:" at the start of a line
453
+ const dirPattern = /^([^\n:]+):\s*$/gm;
454
+
455
+ let match;
456
+ while ((match = dirPattern.exec(content)) !== null) {
457
+ const dirPath = match[1].trim();
458
+ if (dirPath && dirPath.length > 0) {
459
+ directories.push(dirPath);
460
+ if (this.debug) {
461
+ console.log(`[DEBUG] Extracted directory context from listFiles: ${dirPath}`);
462
+ }
463
+ }
464
+ }
465
+
466
+ return directories;
467
+ }
468
+
407
469
  /**
408
470
  * Load and cache an image if it's valid and accessible
409
471
  * @param {string} imagePath - Path to the image file
@@ -630,16 +692,23 @@ export class ProbeAgent {
630
692
  this.mcpBridge = new MCPXmlBridge({ debug: this.debug });
631
693
  await this.mcpBridge.initialize(mcpConfig);
632
694
 
633
- const mcpToolCount = this.mcpBridge.getToolNames().length;
695
+ const mcpToolNames = this.mcpBridge.getToolNames();
696
+ const mcpToolCount = mcpToolNames.length;
634
697
  if (mcpToolCount > 0) {
635
698
  if (this.debug) {
636
- console.log(`[DEBUG] Loaded ${mcpToolCount} MCP tools`);
699
+ console.error('\n[DEBUG] ========================================');
700
+ console.error(`[DEBUG] MCP Tools Initialized (${mcpToolCount} tools)`);
701
+ console.error('[DEBUG] Available MCP tools:');
702
+ for (const toolName of mcpToolNames) {
703
+ console.error(`[DEBUG] - ${toolName}`);
704
+ }
705
+ console.error('[DEBUG] ========================================\n');
637
706
  }
638
707
  } else {
639
708
  // For backward compatibility: if no tools were loaded, set bridge to null
640
709
  // This maintains the behavior expected by existing tests
641
710
  if (this.debug) {
642
- console.log('[DEBUG] No MCP tools loaded, setting bridge to null');
711
+ console.error('[DEBUG] No MCP tools loaded, setting bridge to null');
643
712
  }
644
713
  this.mcpBridge = null;
645
714
  }
@@ -1117,34 +1186,74 @@ When troubleshooting:
1117
1186
  if (type === 'mcp' && this.mcpBridge && this.mcpBridge.isMcpTool(toolName)) {
1118
1187
  // Execute MCP tool
1119
1188
  try {
1120
- if (this.debug) console.log(`[DEBUG] Executing MCP tool '${toolName}' with params:`, params);
1189
+ // Log MCP tool execution in debug mode
1190
+ if (this.debug) {
1191
+ console.error(`\n[DEBUG] ========================================`);
1192
+ console.error(`[DEBUG] Executing MCP tool: ${toolName}`);
1193
+ console.error(`[DEBUG] Arguments:`);
1194
+ for (const [key, value] of Object.entries(params)) {
1195
+ const displayValue = typeof value === 'string' && value.length > 100
1196
+ ? value.substring(0, 100) + '...'
1197
+ : value;
1198
+ console.error(`[DEBUG] ${key}: ${JSON.stringify(displayValue)}`);
1199
+ }
1200
+ console.error(`[DEBUG] ========================================\n`);
1201
+ }
1121
1202
 
1122
1203
  // Execute MCP tool through the bridge
1123
1204
  const executionResult = await this.mcpBridge.mcpTools[toolName].execute(params);
1124
1205
 
1125
1206
  const toolResultContent = typeof executionResult === 'string' ? executionResult : JSON.stringify(executionResult, null, 2);
1126
- const preview = createMessagePreview(toolResultContent);
1207
+
1208
+ // Log MCP tool result in debug mode
1127
1209
  if (this.debug) {
1128
- console.log(`[DEBUG] MCP tool '${toolName}' executed successfully. Result preview: ${preview}`);
1210
+ const preview = toolResultContent.length > 500 ? toolResultContent.substring(0, 500) + '...' : toolResultContent;
1211
+ console.error(`[DEBUG] ========================================`);
1212
+ console.error(`[DEBUG] MCP tool '${toolName}' completed successfully`);
1213
+ console.error(`[DEBUG] Result preview:`);
1214
+ console.error(preview);
1215
+ console.error(`[DEBUG] ========================================\n`);
1129
1216
  }
1130
1217
 
1131
1218
  currentMessages.push({ role: 'user', content: `<tool_result>\n${toolResultContent}\n</tool_result>` });
1132
1219
  } catch (error) {
1133
1220
  console.error(`Error executing MCP tool ${toolName}:`, error);
1134
1221
  const toolResultContent = `Error executing MCP tool ${toolName}: ${error.message}`;
1135
- if (this.debug) console.log(`[DEBUG] MCP tool '${toolName}' execution FAILED.`);
1222
+
1223
+ // Log MCP tool error in debug mode
1224
+ if (this.debug) {
1225
+ console.error(`[DEBUG] ========================================`);
1226
+ console.error(`[DEBUG] MCP tool '${toolName}' failed with error:`);
1227
+ console.error(`[DEBUG] ${error.message}`);
1228
+ console.error(`[DEBUG] ========================================\n`);
1229
+ }
1230
+
1136
1231
  currentMessages.push({ role: 'user', content: `<tool_result>\n${toolResultContent}\n</tool_result>` });
1137
1232
  }
1138
1233
  } else if (this.toolImplementations[toolName]) {
1139
1234
  // Execute native tool
1140
1235
  try {
1141
1236
  // Add sessionId and workingDirectory to params for tool execution
1142
- const toolParams = {
1143
- ...params,
1237
+ const toolParams = {
1238
+ ...params,
1144
1239
  sessionId: this.sessionId,
1145
1240
  workingDirectory: (this.allowedFolders && this.allowedFolders[0]) || process.cwd()
1146
1241
  };
1147
-
1242
+
1243
+ // Log tool execution in debug mode
1244
+ if (this.debug) {
1245
+ console.error(`\n[DEBUG] ========================================`);
1246
+ console.error(`[DEBUG] Executing tool: ${toolName}`);
1247
+ console.error(`[DEBUG] Arguments:`);
1248
+ for (const [key, value] of Object.entries(params)) {
1249
+ const displayValue = typeof value === 'string' && value.length > 100
1250
+ ? value.substring(0, 100) + '...'
1251
+ : value;
1252
+ console.error(`[DEBUG] ${key}: ${JSON.stringify(displayValue)}`);
1253
+ }
1254
+ console.error(`[DEBUG] ========================================\n`);
1255
+ }
1256
+
1148
1257
  // Emit tool start event
1149
1258
  this.events.emit('toolCall', {
1150
1259
  timestamp: new Date().toISOString(),
@@ -1196,6 +1305,18 @@ When troubleshooting:
1196
1305
  toolResult = await executeToolCall();
1197
1306
  }
1198
1307
 
1308
+ // Log tool result in debug mode
1309
+ if (this.debug) {
1310
+ const resultPreview = typeof toolResult === 'string'
1311
+ ? (toolResult.length > 500 ? toolResult.substring(0, 500) + '...' : toolResult)
1312
+ : (toolResult ? JSON.stringify(toolResult, null, 2).substring(0, 500) + '...' : 'No Result');
1313
+ console.error(`[DEBUG] ========================================`);
1314
+ console.error(`[DEBUG] Tool '${toolName}' completed successfully`);
1315
+ console.error(`[DEBUG] Result preview:`);
1316
+ console.error(resultPreview);
1317
+ console.error(`[DEBUG] ========================================\n`);
1318
+ }
1319
+
1199
1320
  // Emit tool success event
1200
1321
  this.events.emit('toolCall', {
1201
1322
  timestamp: new Date().toISOString(),
@@ -1206,8 +1327,16 @@ When troubleshooting:
1206
1327
  : (toolResult ? JSON.stringify(toolResult).substring(0, 200) + '...' : 'No Result'),
1207
1328
  status: 'completed'
1208
1329
  });
1209
-
1330
+
1210
1331
  } catch (toolError) {
1332
+ // Log tool error in debug mode
1333
+ if (this.debug) {
1334
+ console.error(`[DEBUG] ========================================`);
1335
+ console.error(`[DEBUG] Tool '${toolName}' failed with error:`);
1336
+ console.error(`[DEBUG] ${toolError.message}`);
1337
+ console.error(`[DEBUG] ========================================\n`);
1338
+ }
1339
+
1211
1340
  // Emit tool error event
1212
1341
  this.events.emit('toolCall', {
1213
1342
  timestamp: new Date().toISOString(),
@@ -1262,7 +1391,23 @@ When troubleshooting:
1262
1391
  }
1263
1392
  }
1264
1393
  } else {
1265
- // No tool call found, add assistant response and ask for tool usage
1394
+ // No tool call found
1395
+ // Special case: If response contains a mermaid code block and no schema was provided,
1396
+ // treat it as a valid completion (for mermaid diagram fixing workflow)
1397
+ const hasMermaidCodeBlock = /```mermaid\s*\n[\s\S]*?\n```/.test(assistantResponseContent);
1398
+ const hasNoSchemaOrTools = !options.schema && validTools.length === 0;
1399
+
1400
+ if (hasMermaidCodeBlock && hasNoSchemaOrTools) {
1401
+ // Accept mermaid code block as final answer for diagram fixing
1402
+ finalResult = assistantResponseContent;
1403
+ completionAttempted = true;
1404
+ if (this.debug) {
1405
+ console.error(`[DEBUG] Accepting mermaid code block as valid completion (no schema, no tools)`);
1406
+ }
1407
+ break;
1408
+ }
1409
+
1410
+ // Add assistant response and ask for tool usage
1266
1411
  currentMessages.push({ role: 'assistant', content: assistantResponseContent });
1267
1412
 
1268
1413
  // Build appropriate reminder message based on whether schema is provided