@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.
- package/build/agent/ProbeAgent.js +159 -14
- package/build/agent/index.js +1529 -241
- package/build/agent/probeTool.js +125 -24
- package/build/agent/schemaUtils.js +1 -1
- package/build/agent/tokenCounter.js +7 -7
- package/build/index.js +4 -0
- package/cjs/agent/ProbeAgent.cjs +1546 -258
- package/cjs/index.cjs +1338 -46
- package/package.json +2 -2
- package/src/agent/ProbeAgent.js +159 -14
- package/src/agent/probeTool.js +125 -24
- package/src/agent/schemaUtils.js +1 -1
- package/src/agent/tokenCounter.js +7 -7
- package/src/index.js +4 -0
|
@@ -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
|
-
|
|
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
|
|
695
|
+
const mcpToolNames = this.mcpBridge.getToolNames();
|
|
696
|
+
const mcpToolCount = mcpToolNames.length;
|
|
634
697
|
if (mcpToolCount > 0) {
|
|
635
698
|
if (this.debug) {
|
|
636
|
-
console.
|
|
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.
|
|
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
|
-
|
|
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
|
-
|
|
1207
|
+
|
|
1208
|
+
// Log MCP tool result in debug mode
|
|
1127
1209
|
if (this.debug) {
|
|
1128
|
-
|
|
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
|
-
|
|
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
|
|
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
|