@probelabs/probe 0.6.0-rc67 → 0.6.0-rc69
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 +43 -3
- package/build/agent/index.js +186 -46
- package/build/agent/schemaUtils.js +140 -10
- package/build/agent/tools.js +3 -2
- package/build/tools/common.js +62 -40
- package/cjs/agent/ProbeAgent.cjs +189 -49
- package/cjs/index.cjs +189 -49
- package/package.json +1 -1
- package/src/agent/ProbeAgent.js +43 -3
- package/src/agent/schemaUtils.js +140 -10
- package/src/agent/tools.js +3 -2
- package/src/tools/common.js +62 -40
package/build/tools/common.js
CHANGED
|
@@ -173,52 +173,74 @@ export const searchDescription = 'Search code in the repository using Elasticsea
|
|
|
173
173
|
export const queryDescription = 'Search code using ast-grep structural pattern matching. Use this tool to find specific code structures like functions, classes, or methods.';
|
|
174
174
|
export const extractDescription = 'Extract code blocks from files based on file paths and optional line numbers. Use this tool to see complete context after finding relevant files.';
|
|
175
175
|
|
|
176
|
-
//
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
176
|
+
// Valid tool names that should be parsed as tool calls
|
|
177
|
+
const DEFAULT_VALID_TOOLS = [
|
|
178
|
+
'search',
|
|
179
|
+
'query',
|
|
180
|
+
'extract',
|
|
181
|
+
'listFiles',
|
|
182
|
+
'searchFiles',
|
|
183
|
+
'implement',
|
|
184
|
+
'attempt_completion'
|
|
185
|
+
];
|
|
182
186
|
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
//
|
|
194
|
-
if (
|
|
195
|
-
|
|
196
|
-
} else if (paramValue.toLowerCase() === 'false') {
|
|
197
|
-
paramValue = false;
|
|
198
|
-
} else if (!isNaN(paramValue) && paramValue.trim() !== '') {
|
|
199
|
-
// Check if it's potentially a number (handle integers and floats)
|
|
200
|
-
const num = Number(paramValue);
|
|
201
|
-
if (Number.isFinite(num)) { // Use Number.isFinite to avoid Infinity/NaN
|
|
202
|
-
paramValue = num;
|
|
203
|
-
}
|
|
204
|
-
// Keep as string if not a valid finite number
|
|
187
|
+
// Simple XML parser helper
|
|
188
|
+
export function parseXmlToolCall(xmlString, validTools = DEFAULT_VALID_TOOLS) {
|
|
189
|
+
// Find all potential XML tag matches
|
|
190
|
+
const globalRegex = /<([a-zA-Z0-9_]+)>([\s\S]*?)<\/\1>/g;
|
|
191
|
+
let match;
|
|
192
|
+
|
|
193
|
+
// Look through all matches to find the first valid tool
|
|
194
|
+
while ((match = globalRegex.exec(xmlString)) !== null) {
|
|
195
|
+
const toolName = match[1];
|
|
196
|
+
|
|
197
|
+
// Only parse XML tags that correspond to valid tools
|
|
198
|
+
if (!validTools.includes(toolName)) {
|
|
199
|
+
continue; // Skip non-tool tags and look for the next match
|
|
205
200
|
}
|
|
206
201
|
|
|
207
|
-
|
|
208
|
-
|
|
202
|
+
const innerContent = match[2];
|
|
203
|
+
const params = {};
|
|
204
|
+
|
|
205
|
+
const paramRegex = /<([a-zA-Z0-9_]+)>([\s\S]*?)<\/\1>/g;
|
|
206
|
+
let paramMatch;
|
|
207
|
+
while ((paramMatch = paramRegex.exec(innerContent)) !== null) {
|
|
208
|
+
const paramName = paramMatch[1];
|
|
209
|
+
let paramValue = paramMatch[2].trim();
|
|
210
|
+
|
|
211
|
+
// Basic type inference (can be improved)
|
|
212
|
+
if (paramValue.toLowerCase() === 'true') {
|
|
213
|
+
paramValue = true;
|
|
214
|
+
} else if (paramValue.toLowerCase() === 'false') {
|
|
215
|
+
paramValue = false;
|
|
216
|
+
} else if (!isNaN(paramValue) && paramValue.trim() !== '') {
|
|
217
|
+
// Check if it's potentially a number (handle integers and floats)
|
|
218
|
+
const num = Number(paramValue);
|
|
219
|
+
if (Number.isFinite(num)) { // Use Number.isFinite to avoid Infinity/NaN
|
|
220
|
+
paramValue = num;
|
|
221
|
+
}
|
|
222
|
+
// Keep as string if not a valid finite number
|
|
223
|
+
}
|
|
209
224
|
|
|
210
|
-
|
|
211
|
-
if (toolName === 'attempt_completion') {
|
|
212
|
-
const resultMatch = innerContent.match(/<result>([\s\S]*?)<\/result>/);
|
|
213
|
-
if (resultMatch) {
|
|
214
|
-
params['result'] = resultMatch[1].trim(); // Keep result content as is
|
|
225
|
+
params[paramName] = paramValue;
|
|
215
226
|
}
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
227
|
+
|
|
228
|
+
// Special handling for attempt_completion where result might contain nested XML/code
|
|
229
|
+
if (toolName === 'attempt_completion') {
|
|
230
|
+
const resultMatch = innerContent.match(/<result>([\s\S]*?)<\/result>/);
|
|
231
|
+
if (resultMatch) {
|
|
232
|
+
params['result'] = resultMatch[1].trim(); // Keep result content as is
|
|
233
|
+
}
|
|
234
|
+
const commandMatch = innerContent.match(/<command>([\s\S]*?)<\/command>/);
|
|
235
|
+
if (commandMatch) {
|
|
236
|
+
params['command'] = commandMatch[1].trim();
|
|
237
|
+
}
|
|
219
238
|
}
|
|
220
|
-
}
|
|
221
239
|
|
|
240
|
+
// Return the first valid tool found
|
|
241
|
+
return { toolName, params };
|
|
242
|
+
}
|
|
222
243
|
|
|
223
|
-
|
|
244
|
+
// No valid tool found
|
|
245
|
+
return null;
|
|
224
246
|
}
|
package/cjs/agent/ProbeAgent.cjs
CHANGED
|
@@ -1429,44 +1429,48 @@ var init_extract = __esm({
|
|
|
1429
1429
|
});
|
|
1430
1430
|
|
|
1431
1431
|
// src/tools/common.js
|
|
1432
|
-
function parseXmlToolCall(xmlString) {
|
|
1433
|
-
const
|
|
1434
|
-
|
|
1435
|
-
|
|
1432
|
+
function parseXmlToolCall(xmlString, validTools = DEFAULT_VALID_TOOLS) {
|
|
1433
|
+
const globalRegex = /<([a-zA-Z0-9_]+)>([\s\S]*?)<\/\1>/g;
|
|
1434
|
+
let match;
|
|
1435
|
+
while ((match = globalRegex.exec(xmlString)) !== null) {
|
|
1436
|
+
const toolName = match[1];
|
|
1437
|
+
if (!validTools.includes(toolName)) {
|
|
1438
|
+
continue;
|
|
1439
|
+
}
|
|
1440
|
+
const innerContent = match[2];
|
|
1441
|
+
const params = {};
|
|
1442
|
+
const paramRegex = /<([a-zA-Z0-9_]+)>([\s\S]*?)<\/\1>/g;
|
|
1443
|
+
let paramMatch;
|
|
1444
|
+
while ((paramMatch = paramRegex.exec(innerContent)) !== null) {
|
|
1445
|
+
const paramName = paramMatch[1];
|
|
1446
|
+
let paramValue = paramMatch[2].trim();
|
|
1447
|
+
if (paramValue.toLowerCase() === "true") {
|
|
1448
|
+
paramValue = true;
|
|
1449
|
+
} else if (paramValue.toLowerCase() === "false") {
|
|
1450
|
+
paramValue = false;
|
|
1451
|
+
} else if (!isNaN(paramValue) && paramValue.trim() !== "") {
|
|
1452
|
+
const num = Number(paramValue);
|
|
1453
|
+
if (Number.isFinite(num)) {
|
|
1454
|
+
paramValue = num;
|
|
1455
|
+
}
|
|
1456
|
+
}
|
|
1457
|
+
params[paramName] = paramValue;
|
|
1458
|
+
}
|
|
1459
|
+
if (toolName === "attempt_completion") {
|
|
1460
|
+
const resultMatch = innerContent.match(/<result>([\s\S]*?)<\/result>/);
|
|
1461
|
+
if (resultMatch) {
|
|
1462
|
+
params["result"] = resultMatch[1].trim();
|
|
1463
|
+
}
|
|
1464
|
+
const commandMatch = innerContent.match(/<command>([\s\S]*?)<\/command>/);
|
|
1465
|
+
if (commandMatch) {
|
|
1466
|
+
params["command"] = commandMatch[1].trim();
|
|
1467
|
+
}
|
|
1468
|
+
}
|
|
1469
|
+
return { toolName, params };
|
|
1436
1470
|
}
|
|
1437
|
-
|
|
1438
|
-
const innerContent = toolMatch[2];
|
|
1439
|
-
const params = {};
|
|
1440
|
-
const paramRegex = /<([a-zA-Z0-9_]+)>([\s\S]*?)<\/\1>/g;
|
|
1441
|
-
let paramMatch;
|
|
1442
|
-
while ((paramMatch = paramRegex.exec(innerContent)) !== null) {
|
|
1443
|
-
const paramName = paramMatch[1];
|
|
1444
|
-
let paramValue = paramMatch[2].trim();
|
|
1445
|
-
if (paramValue.toLowerCase() === "true") {
|
|
1446
|
-
paramValue = true;
|
|
1447
|
-
} else if (paramValue.toLowerCase() === "false") {
|
|
1448
|
-
paramValue = false;
|
|
1449
|
-
} else if (!isNaN(paramValue) && paramValue.trim() !== "") {
|
|
1450
|
-
const num = Number(paramValue);
|
|
1451
|
-
if (Number.isFinite(num)) {
|
|
1452
|
-
paramValue = num;
|
|
1453
|
-
}
|
|
1454
|
-
}
|
|
1455
|
-
params[paramName] = paramValue;
|
|
1456
|
-
}
|
|
1457
|
-
if (toolName === "attempt_completion") {
|
|
1458
|
-
const resultMatch = innerContent.match(/<result>([\s\S]*?)<\/result>/);
|
|
1459
|
-
if (resultMatch) {
|
|
1460
|
-
params["result"] = resultMatch[1].trim();
|
|
1461
|
-
}
|
|
1462
|
-
const commandMatch = innerContent.match(/<command>([\s\S]*?)<\/command>/);
|
|
1463
|
-
if (commandMatch) {
|
|
1464
|
-
params["command"] = commandMatch[1].trim();
|
|
1465
|
-
}
|
|
1466
|
-
}
|
|
1467
|
-
return { toolName, params };
|
|
1471
|
+
return null;
|
|
1468
1472
|
}
|
|
1469
|
-
var import_zod, searchSchema, querySchema, extractSchema, attemptCompletionSchema, searchToolDefinition, queryToolDefinition, extractToolDefinition, attemptCompletionToolDefinition, searchDescription, queryDescription, extractDescription;
|
|
1473
|
+
var import_zod, searchSchema, querySchema, extractSchema, attemptCompletionSchema, searchToolDefinition, queryToolDefinition, extractToolDefinition, attemptCompletionToolDefinition, searchDescription, queryDescription, extractDescription, DEFAULT_VALID_TOOLS;
|
|
1470
1474
|
var init_common = __esm({
|
|
1471
1475
|
"src/tools/common.js"() {
|
|
1472
1476
|
"use strict";
|
|
@@ -1625,6 +1629,15 @@ Usage Example:
|
|
|
1625
1629
|
searchDescription = "Search code in the repository using Elasticsearch-like query syntax. Use this tool first for any code-related questions.";
|
|
1626
1630
|
queryDescription = "Search code using ast-grep structural pattern matching. Use this tool to find specific code structures like functions, classes, or methods.";
|
|
1627
1631
|
extractDescription = "Extract code blocks from files based on file paths and optional line numbers. Use this tool to see complete context after finding relevant files.";
|
|
1632
|
+
DEFAULT_VALID_TOOLS = [
|
|
1633
|
+
"search",
|
|
1634
|
+
"query",
|
|
1635
|
+
"extract",
|
|
1636
|
+
"listFiles",
|
|
1637
|
+
"searchFiles",
|
|
1638
|
+
"implement",
|
|
1639
|
+
"attempt_completion"
|
|
1640
|
+
];
|
|
1628
1641
|
}
|
|
1629
1642
|
});
|
|
1630
1643
|
|
|
@@ -2026,11 +2039,11 @@ function createTools(configOptions) {
|
|
|
2026
2039
|
extractTool: extractTool(configOptions)
|
|
2027
2040
|
};
|
|
2028
2041
|
}
|
|
2029
|
-
function parseXmlToolCallWithThinking(xmlString) {
|
|
2042
|
+
function parseXmlToolCallWithThinking(xmlString, validTools) {
|
|
2030
2043
|
const thinkingMatch = xmlString.match(/<thinking>([\s\S]*?)<\/thinking>/);
|
|
2031
2044
|
const thinkingContent = thinkingMatch ? thinkingMatch[1].trim() : null;
|
|
2032
2045
|
const cleanedXmlString = xmlString.replace(/<thinking>[\s\S]*?<\/thinking>/g, "").trim();
|
|
2033
|
-
const parsedTool = parseXmlToolCall(cleanedXmlString);
|
|
2046
|
+
const parsedTool = parseXmlToolCall(cleanedXmlString, validTools);
|
|
2034
2047
|
if (process.env.DEBUG === "1" && thinkingContent) {
|
|
2035
2048
|
console.log(`[DEBUG] AI Thinking Process:
|
|
2036
2049
|
${thinkingContent}`);
|
|
@@ -2305,6 +2318,16 @@ var init_probeTool = __esm({
|
|
|
2305
2318
|
});
|
|
2306
2319
|
|
|
2307
2320
|
// src/agent/schemaUtils.js
|
|
2321
|
+
function decodeHtmlEntities(text) {
|
|
2322
|
+
if (!text || typeof text !== "string") {
|
|
2323
|
+
return text;
|
|
2324
|
+
}
|
|
2325
|
+
let decoded = text;
|
|
2326
|
+
for (const [entity, character] of Object.entries(HTML_ENTITY_MAP)) {
|
|
2327
|
+
decoded = decoded.replace(new RegExp(entity, "g"), character);
|
|
2328
|
+
}
|
|
2329
|
+
return decoded;
|
|
2330
|
+
}
|
|
2308
2331
|
function cleanSchemaResponse(response) {
|
|
2309
2332
|
if (!response || typeof response !== "string") {
|
|
2310
2333
|
return response;
|
|
@@ -2581,9 +2604,65 @@ async function validateAndFixMermaidResponse(response, options = {}) {
|
|
|
2581
2604
|
};
|
|
2582
2605
|
}
|
|
2583
2606
|
if (debug) {
|
|
2584
|
-
console.error("[DEBUG] Invalid Mermaid diagrams detected,
|
|
2607
|
+
console.error("[DEBUG] Invalid Mermaid diagrams detected, trying HTML entity auto-fix first...");
|
|
2585
2608
|
}
|
|
2586
2609
|
try {
|
|
2610
|
+
let fixedResponse = response;
|
|
2611
|
+
const fixingResults = [];
|
|
2612
|
+
let htmlEntityFixesApplied = false;
|
|
2613
|
+
const { diagrams } = extractMermaidFromMarkdown(response);
|
|
2614
|
+
const invalidDiagrams = validation.diagrams.map((result, index) => ({ ...result, originalIndex: index })).filter((result) => !result.isValid).reverse();
|
|
2615
|
+
for (const invalidDiagram of invalidDiagrams) {
|
|
2616
|
+
const originalContent = invalidDiagram.content;
|
|
2617
|
+
const decodedContent = decodeHtmlEntities(originalContent);
|
|
2618
|
+
if (decodedContent !== originalContent) {
|
|
2619
|
+
try {
|
|
2620
|
+
const quickValidation = await validateMermaidDiagram(decodedContent);
|
|
2621
|
+
if (quickValidation.isValid) {
|
|
2622
|
+
const originalDiagram = diagrams[invalidDiagram.originalIndex];
|
|
2623
|
+
const attributesStr = originalDiagram.attributes ? ` ${originalDiagram.attributes}` : "";
|
|
2624
|
+
const newCodeBlock = `\`\`\`mermaid${attributesStr}
|
|
2625
|
+
${decodedContent}
|
|
2626
|
+
\`\`\``;
|
|
2627
|
+
fixedResponse = fixedResponse.slice(0, originalDiagram.startIndex) + newCodeBlock + fixedResponse.slice(originalDiagram.endIndex);
|
|
2628
|
+
fixingResults.push({
|
|
2629
|
+
diagramIndex: invalidDiagram.originalIndex,
|
|
2630
|
+
wasFixed: true,
|
|
2631
|
+
originalContent,
|
|
2632
|
+
fixedContent: decodedContent,
|
|
2633
|
+
originalError: invalidDiagram.error,
|
|
2634
|
+
fixedWithHtmlDecoding: true
|
|
2635
|
+
});
|
|
2636
|
+
htmlEntityFixesApplied = true;
|
|
2637
|
+
if (debug) {
|
|
2638
|
+
console.error(`[DEBUG] Fixed diagram ${invalidDiagram.originalIndex + 1} with HTML entity decoding: ${invalidDiagram.error}`);
|
|
2639
|
+
}
|
|
2640
|
+
}
|
|
2641
|
+
} catch (error) {
|
|
2642
|
+
if (debug) {
|
|
2643
|
+
console.error(`[DEBUG] HTML entity decoding didn't fix diagram ${invalidDiagram.originalIndex + 1}: ${error.message}`);
|
|
2644
|
+
}
|
|
2645
|
+
}
|
|
2646
|
+
}
|
|
2647
|
+
}
|
|
2648
|
+
if (htmlEntityFixesApplied) {
|
|
2649
|
+
const revalidation = await validateMermaidResponse(fixedResponse);
|
|
2650
|
+
if (revalidation.isValid) {
|
|
2651
|
+
if (debug) {
|
|
2652
|
+
console.error("[DEBUG] All diagrams fixed with HTML entity decoding, no AI needed");
|
|
2653
|
+
}
|
|
2654
|
+
return {
|
|
2655
|
+
...revalidation,
|
|
2656
|
+
wasFixed: true,
|
|
2657
|
+
originalResponse: response,
|
|
2658
|
+
fixedResponse,
|
|
2659
|
+
fixingResults
|
|
2660
|
+
};
|
|
2661
|
+
}
|
|
2662
|
+
}
|
|
2663
|
+
if (debug) {
|
|
2664
|
+
console.error("[DEBUG] Some diagrams still invalid after HTML entity decoding, starting AI fixing...");
|
|
2665
|
+
}
|
|
2587
2666
|
const mermaidFixer = new MermaidFixingAgent({
|
|
2588
2667
|
path: path6,
|
|
2589
2668
|
provider,
|
|
@@ -2591,11 +2670,10 @@ async function validateAndFixMermaidResponse(response, options = {}) {
|
|
|
2591
2670
|
debug,
|
|
2592
2671
|
tracer
|
|
2593
2672
|
});
|
|
2594
|
-
|
|
2595
|
-
const
|
|
2596
|
-
const
|
|
2597
|
-
const
|
|
2598
|
-
for (const invalidDiagram of invalidDiagrams) {
|
|
2673
|
+
const { diagrams: updatedDiagrams } = extractMermaidFromMarkdown(fixedResponse);
|
|
2674
|
+
const updatedValidation = await validateMermaidResponse(fixedResponse);
|
|
2675
|
+
const stillInvalidDiagrams = updatedValidation.diagrams.map((result, index) => ({ ...result, originalIndex: index })).filter((result) => !result.isValid).reverse();
|
|
2676
|
+
for (const invalidDiagram of stillInvalidDiagrams) {
|
|
2599
2677
|
try {
|
|
2600
2678
|
const fixedContent = await mermaidFixer.fixMermaidDiagram(
|
|
2601
2679
|
invalidDiagram.content,
|
|
@@ -2603,7 +2681,7 @@ async function validateAndFixMermaidResponse(response, options = {}) {
|
|
|
2603
2681
|
{ diagramType: invalidDiagram.diagramType }
|
|
2604
2682
|
);
|
|
2605
2683
|
if (fixedContent && fixedContent !== invalidDiagram.content) {
|
|
2606
|
-
const originalDiagram =
|
|
2684
|
+
const originalDiagram = updatedDiagrams[invalidDiagram.originalIndex];
|
|
2607
2685
|
const attributesStr = originalDiagram.attributes ? ` ${originalDiagram.attributes}` : "";
|
|
2608
2686
|
const newCodeBlock = `\`\`\`mermaid${attributesStr}
|
|
2609
2687
|
${fixedContent}
|
|
@@ -2664,10 +2742,18 @@ ${fixedContent}
|
|
|
2664
2742
|
};
|
|
2665
2743
|
}
|
|
2666
2744
|
}
|
|
2667
|
-
var MermaidFixingAgent;
|
|
2745
|
+
var HTML_ENTITY_MAP, MermaidFixingAgent;
|
|
2668
2746
|
var init_schemaUtils = __esm({
|
|
2669
2747
|
"src/agent/schemaUtils.js"() {
|
|
2670
2748
|
"use strict";
|
|
2749
|
+
HTML_ENTITY_MAP = {
|
|
2750
|
+
"<": "<",
|
|
2751
|
+
">": ">",
|
|
2752
|
+
"&": "&",
|
|
2753
|
+
""": '"',
|
|
2754
|
+
"'": "'",
|
|
2755
|
+
" ": " "
|
|
2756
|
+
};
|
|
2671
2757
|
MermaidFixingAgent = class {
|
|
2672
2758
|
constructor(options = {}) {
|
|
2673
2759
|
this.ProbeAgent = null;
|
|
@@ -2753,6 +2839,22 @@ When presented with a broken Mermaid diagram, analyze it thoroughly and provide
|
|
|
2753
2839
|
* @returns {Promise<string>} - The corrected Mermaid diagram
|
|
2754
2840
|
*/
|
|
2755
2841
|
async fixMermaidDiagram(diagramContent, originalErrors = [], diagramInfo = {}) {
|
|
2842
|
+
const decodedContent = decodeHtmlEntities(diagramContent);
|
|
2843
|
+
if (decodedContent !== diagramContent) {
|
|
2844
|
+
try {
|
|
2845
|
+
const quickValidation = await validateMermaidDiagram(decodedContent);
|
|
2846
|
+
if (quickValidation.isValid) {
|
|
2847
|
+
if (this.options.debug) {
|
|
2848
|
+
console.error("[DEBUG] Fixed Mermaid diagram with HTML entity decoding only");
|
|
2849
|
+
}
|
|
2850
|
+
return decodedContent;
|
|
2851
|
+
}
|
|
2852
|
+
} catch (error) {
|
|
2853
|
+
if (this.options.debug) {
|
|
2854
|
+
console.error("[DEBUG] HTML entity decoding didn't fully fix diagram, continuing with AI fixing");
|
|
2855
|
+
}
|
|
2856
|
+
}
|
|
2857
|
+
}
|
|
2756
2858
|
await this.initializeAgent();
|
|
2757
2859
|
const errorContext = originalErrors.length > 0 ? `
|
|
2758
2860
|
|
|
@@ -2760,11 +2862,12 @@ Detected errors: ${originalErrors.join(", ")}` : "";
|
|
|
2760
2862
|
const diagramTypeHint = diagramInfo.diagramType ? `
|
|
2761
2863
|
|
|
2762
2864
|
Expected diagram type: ${diagramInfo.diagramType}` : "";
|
|
2865
|
+
const contentToFix = decodedContent !== diagramContent ? decodedContent : diagramContent;
|
|
2763
2866
|
const prompt = `Analyze and fix the following Mermaid diagram.${errorContext}${diagramTypeHint}
|
|
2764
2867
|
|
|
2765
2868
|
Broken Mermaid diagram:
|
|
2766
2869
|
\`\`\`mermaid
|
|
2767
|
-
${
|
|
2870
|
+
${contentToFix}
|
|
2768
2871
|
\`\`\`
|
|
2769
2872
|
|
|
2770
2873
|
Provide only the corrected Mermaid diagram within a mermaid code block. Do not add any explanations or additional text.`;
|
|
@@ -3291,7 +3394,18 @@ You are working with a repository located at: ${searchDirectory}
|
|
|
3291
3394
|
finalResult = `Error: Failed to get response from AI model during iteration ${currentIteration}. ${error.message}`;
|
|
3292
3395
|
throw new Error(finalResult);
|
|
3293
3396
|
}
|
|
3294
|
-
const
|
|
3397
|
+
const validTools = [
|
|
3398
|
+
"search",
|
|
3399
|
+
"query",
|
|
3400
|
+
"extract",
|
|
3401
|
+
"listFiles",
|
|
3402
|
+
"searchFiles",
|
|
3403
|
+
"attempt_completion"
|
|
3404
|
+
];
|
|
3405
|
+
if (this.allowEdit) {
|
|
3406
|
+
validTools.push("implement");
|
|
3407
|
+
}
|
|
3408
|
+
const parsedTool = parseXmlToolCallWithThinking(assistantResponseContent, validTools);
|
|
3295
3409
|
if (parsedTool) {
|
|
3296
3410
|
const { toolName, params } = parsedTool;
|
|
3297
3411
|
if (this.debug) console.log(`[DEBUG] Parsed tool call: ${toolName} with params:`, params);
|
|
@@ -3410,7 +3524,7 @@ Error: Unknown tool '${toolName}'. Available tools: ${Object.keys(this.toolImple
|
|
|
3410
3524
|
}
|
|
3411
3525
|
}
|
|
3412
3526
|
this.tokenCounter.updateHistory(this.history);
|
|
3413
|
-
if (options.schema && !options._schemaFormatted) {
|
|
3527
|
+
if (options.schema && !options._schemaFormatted && !completionAttempted) {
|
|
3414
3528
|
if (this.debug) {
|
|
3415
3529
|
console.log("[DEBUG] Schema provided, applying automatic formatting...");
|
|
3416
3530
|
}
|
|
@@ -3490,6 +3604,32 @@ Convert your previous response content into this JSON format now. Return nothing
|
|
|
3490
3604
|
} catch (error) {
|
|
3491
3605
|
console.error("[ERROR] Schema formatting failed:", error);
|
|
3492
3606
|
}
|
|
3607
|
+
} else if (completionAttempted && options.schema) {
|
|
3608
|
+
try {
|
|
3609
|
+
finalResult = cleanSchemaResponse(finalResult);
|
|
3610
|
+
const mermaidValidation = await validateAndFixMermaidResponse(finalResult, {
|
|
3611
|
+
debug: this.debug,
|
|
3612
|
+
path: this.allowedFolders[0],
|
|
3613
|
+
provider: this.clientApiProvider,
|
|
3614
|
+
model: this.model
|
|
3615
|
+
});
|
|
3616
|
+
if (mermaidValidation.wasFixed) {
|
|
3617
|
+
finalResult = mermaidValidation.fixedResponse;
|
|
3618
|
+
if (this.debug) {
|
|
3619
|
+
console.log(`[DEBUG] Mermaid diagrams fixed in attempt_completion result`);
|
|
3620
|
+
}
|
|
3621
|
+
}
|
|
3622
|
+
if (isJsonSchema(options.schema)) {
|
|
3623
|
+
const validation = validateJsonResponse(finalResult);
|
|
3624
|
+
if (!validation.isValid && this.debug) {
|
|
3625
|
+
console.log(`[DEBUG] attempt_completion result JSON validation failed: ${validation.error}`);
|
|
3626
|
+
}
|
|
3627
|
+
}
|
|
3628
|
+
} catch (error) {
|
|
3629
|
+
if (this.debug) {
|
|
3630
|
+
console.log(`[DEBUG] attempt_completion result cleanup failed: ${error.message}`);
|
|
3631
|
+
}
|
|
3632
|
+
}
|
|
3493
3633
|
}
|
|
3494
3634
|
return finalResult;
|
|
3495
3635
|
} catch (error) {
|