@probelabs/probe 0.6.0-rc108 → 0.6.0-rc112
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/index.js +26320 -4708
- package/build/agent/schemaUtils.js +269 -789
- package/build/agent/xmlParsingUtils.js +54 -2
- package/build/tools/common.js +30 -15
- package/cjs/agent/ProbeAgent.cjs +26037 -4425
- package/cjs/index.cjs +26041 -4429
- package/package.json +2 -1
- package/src/agent/schemaUtils.js +269 -789
- package/src/agent/xmlParsingUtils.js +54 -2
- package/src/tools/common.js +30 -15
|
@@ -5,11 +5,39 @@
|
|
|
5
5
|
|
|
6
6
|
/**
|
|
7
7
|
* Remove thinking tags and their content from XML string
|
|
8
|
+
* Handles both closed and unclosed thinking tags
|
|
8
9
|
* @param {string} xmlString - The XML string to clean
|
|
9
10
|
* @returns {string} - Cleaned XML string without thinking tags
|
|
10
11
|
*/
|
|
11
12
|
export function removeThinkingTags(xmlString) {
|
|
12
|
-
|
|
13
|
+
let result = xmlString;
|
|
14
|
+
|
|
15
|
+
// Remove all properly closed thinking tags first
|
|
16
|
+
result = result.replace(/<thinking>[\s\S]*?<\/thinking>/g, '');
|
|
17
|
+
|
|
18
|
+
// Handle unclosed thinking tags
|
|
19
|
+
// Find any remaining <thinking> tag (which means it's unclosed)
|
|
20
|
+
const thinkingIndex = result.indexOf('<thinking>');
|
|
21
|
+
if (thinkingIndex !== -1) {
|
|
22
|
+
// Check if there's a tool tag after the thinking tag
|
|
23
|
+
// We want to preserve tool tags even if they're after unclosed thinking
|
|
24
|
+
const afterThinking = result.substring(thinkingIndex + '<thinking>'.length);
|
|
25
|
+
|
|
26
|
+
// Look for any tool tags in the remaining content
|
|
27
|
+
const toolPattern = /<(search|query|extract|listFiles|searchFiles|implement|attempt_completion|attempt_complete)>/;
|
|
28
|
+
const toolMatch = afterThinking.match(toolPattern);
|
|
29
|
+
|
|
30
|
+
if (toolMatch) {
|
|
31
|
+
// Found a tool tag - remove thinking tag and its content up to the tool tag
|
|
32
|
+
const toolStart = thinkingIndex + '<thinking>'.length + toolMatch.index;
|
|
33
|
+
result = result.substring(0, thinkingIndex) + result.substring(toolStart);
|
|
34
|
+
} else {
|
|
35
|
+
// No tool tag found - remove everything from <thinking> onwards
|
|
36
|
+
result = result.substring(0, thinkingIndex);
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
return result.trim();
|
|
13
41
|
}
|
|
14
42
|
|
|
15
43
|
/**
|
|
@@ -29,6 +57,30 @@ export function extractThinkingContent(xmlString) {
|
|
|
29
57
|
* @returns {Object|null} - Standardized attempt_completion result or null
|
|
30
58
|
*/
|
|
31
59
|
export function checkAttemptCompleteRecovery(cleanedXmlString, validTools = []) {
|
|
60
|
+
// Check for <attempt_completion> with content (with or without closing tag)
|
|
61
|
+
// This handles: "<attempt_completion>content" or "<attempt_completion>content</attempt_completion>"
|
|
62
|
+
const attemptCompletionMatch = cleanedXmlString.match(/<attempt_completion>([\s\S]*?)(?:<\/attempt_completion>|$)/);
|
|
63
|
+
if (attemptCompletionMatch) {
|
|
64
|
+
const content = attemptCompletionMatch[1].trim();
|
|
65
|
+
const hasClosingTag = cleanedXmlString.includes('</attempt_completion>');
|
|
66
|
+
|
|
67
|
+
if (content) {
|
|
68
|
+
// If there's content after the tag, use it as the result
|
|
69
|
+
return {
|
|
70
|
+
toolName: 'attempt_completion',
|
|
71
|
+
params: { result: content }
|
|
72
|
+
};
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
// If the tag exists but is empty:
|
|
76
|
+
// - With closing tag (e.g., "<attempt_completion></attempt_completion>"): use empty string
|
|
77
|
+
// - Without closing tag (e.g., "<attempt_completion>"): use previous response
|
|
78
|
+
return {
|
|
79
|
+
toolName: 'attempt_completion',
|
|
80
|
+
params: { result: hasClosingTag ? '' : '__PREVIOUS_RESPONSE__' }
|
|
81
|
+
};
|
|
82
|
+
}
|
|
83
|
+
|
|
32
84
|
// Enhanced recovery logic for attempt_complete shorthand
|
|
33
85
|
const attemptCompletePatterns = [
|
|
34
86
|
// Standard shorthand with optional whitespace
|
|
@@ -61,7 +113,7 @@ export function checkAttemptCompleteRecovery(cleanedXmlString, validTools = [])
|
|
|
61
113
|
if (cleanedXmlString.includes('<attempt_complete') && !hasOtherToolTags(cleanedXmlString, validTools)) {
|
|
62
114
|
// This handles malformed cases where attempt_complete appears but is broken
|
|
63
115
|
return {
|
|
64
|
-
toolName: 'attempt_completion',
|
|
116
|
+
toolName: 'attempt_completion',
|
|
65
117
|
params: { result: '__PREVIOUS_RESPONSE__' }
|
|
66
118
|
};
|
|
67
119
|
}
|
package/src/tools/common.js
CHANGED
|
@@ -364,47 +364,62 @@ export function parseXmlToolCall(xmlString, validTools = DEFAULT_VALID_TOOLS) {
|
|
|
364
364
|
for (const toolName of validTools) {
|
|
365
365
|
const openTag = `<${toolName}>`;
|
|
366
366
|
const closeTag = `</${toolName}>`;
|
|
367
|
-
|
|
367
|
+
|
|
368
368
|
const openIndex = xmlString.indexOf(openTag);
|
|
369
369
|
if (openIndex === -1) {
|
|
370
370
|
continue; // Tool not found, try next tool
|
|
371
371
|
}
|
|
372
|
-
|
|
373
|
-
|
|
372
|
+
|
|
373
|
+
let closeIndex = xmlString.indexOf(closeTag, openIndex + openTag.length);
|
|
374
|
+
let hasClosingTag = closeIndex !== -1;
|
|
375
|
+
|
|
376
|
+
// If no closing tag found, use content until end of string
|
|
377
|
+
// This makes the parser more resilient to AI formatting errors
|
|
374
378
|
if (closeIndex === -1) {
|
|
375
|
-
|
|
379
|
+
closeIndex = xmlString.length;
|
|
376
380
|
}
|
|
377
|
-
|
|
378
|
-
// Extract the content between tags
|
|
381
|
+
|
|
382
|
+
// Extract the content between tags (or until end if no closing tag)
|
|
379
383
|
const innerContent = xmlString.substring(
|
|
380
|
-
openIndex + openTag.length,
|
|
384
|
+
openIndex + openTag.length,
|
|
381
385
|
closeIndex
|
|
382
386
|
);
|
|
383
|
-
|
|
387
|
+
|
|
384
388
|
const params = {};
|
|
385
389
|
|
|
386
390
|
// Parse parameters using string-based approach for better safety
|
|
387
391
|
// Common parameter names to look for (can be extended as needed)
|
|
388
392
|
// Note: includes both camelCase and underscore_case variants to handle inconsistencies
|
|
389
|
-
const commonParams = ['query', 'file_path', 'line', 'end_line', 'path', 'recursive', 'includeHidden',
|
|
393
|
+
const commonParams = ['query', 'file_path', 'line', 'end_line', 'path', 'recursive', 'includeHidden',
|
|
390
394
|
'max_results', 'maxResults', 'result', 'command', 'description', 'task', 'param', 'pattern',
|
|
391
395
|
'allow_tests', 'exact', 'maxTokens', 'language', 'input_content',
|
|
392
396
|
'context_lines', 'format', 'directory', 'autoCommits', 'files', 'targets'];
|
|
393
|
-
|
|
397
|
+
|
|
394
398
|
for (const paramName of commonParams) {
|
|
395
399
|
const paramOpenTag = `<${paramName}>`;
|
|
396
400
|
const paramCloseTag = `</${paramName}>`;
|
|
397
|
-
|
|
401
|
+
|
|
398
402
|
const paramOpenIndex = innerContent.indexOf(paramOpenTag);
|
|
399
403
|
if (paramOpenIndex === -1) {
|
|
400
404
|
continue; // Parameter not found
|
|
401
405
|
}
|
|
402
|
-
|
|
403
|
-
|
|
406
|
+
|
|
407
|
+
let paramCloseIndex = innerContent.indexOf(paramCloseTag, paramOpenIndex + paramOpenTag.length);
|
|
408
|
+
|
|
409
|
+
// Handle unclosed parameter tags - use content until next tag or end of content
|
|
404
410
|
if (paramCloseIndex === -1) {
|
|
405
|
-
|
|
411
|
+
// Find the next opening tag after this parameter
|
|
412
|
+
let nextTagIndex = innerContent.length;
|
|
413
|
+
for (const nextParam of commonParams) {
|
|
414
|
+
const nextOpenTag = `<${nextParam}>`;
|
|
415
|
+
const nextIndex = innerContent.indexOf(nextOpenTag, paramOpenIndex + paramOpenTag.length);
|
|
416
|
+
if (nextIndex !== -1 && nextIndex < nextTagIndex) {
|
|
417
|
+
nextTagIndex = nextIndex;
|
|
418
|
+
}
|
|
419
|
+
}
|
|
420
|
+
paramCloseIndex = nextTagIndex;
|
|
406
421
|
}
|
|
407
|
-
|
|
422
|
+
|
|
408
423
|
let paramValue = innerContent.substring(
|
|
409
424
|
paramOpenIndex + paramOpenTag.length,
|
|
410
425
|
paramCloseIndex
|