@probelabs/probe 0.6.0-rc131 → 0.6.0-rc133
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.d.ts +1 -1
- package/build/agent/ProbeAgent.js +188 -93
- package/build/agent/index.js +454 -90
- package/build/agent/schemaUtils.js +282 -33
- package/cjs/agent/ProbeAgent.cjs +780 -302
- package/cjs/index.cjs +780 -302
- package/package.json +1 -1
- package/src/agent/ProbeAgent.d.ts +1 -1
- package/src/agent/ProbeAgent.js +188 -93
- package/src/agent/schemaUtils.js +282 -33
package/build/agent/index.js
CHANGED
|
@@ -46421,6 +46421,28 @@ var init_out = __esm({
|
|
|
46421
46421
|
});
|
|
46422
46422
|
|
|
46423
46423
|
// src/agent/schemaUtils.js
|
|
46424
|
+
var schemaUtils_exports = {};
|
|
46425
|
+
__export(schemaUtils_exports, {
|
|
46426
|
+
JsonFixingAgent: () => JsonFixingAgent,
|
|
46427
|
+
MermaidFixingAgent: () => MermaidFixingAgent,
|
|
46428
|
+
cleanSchemaResponse: () => cleanSchemaResponse,
|
|
46429
|
+
createJsonCorrectionPrompt: () => createJsonCorrectionPrompt,
|
|
46430
|
+
createMermaidCorrectionPrompt: () => createMermaidCorrectionPrompt,
|
|
46431
|
+
createSchemaDefinitionCorrectionPrompt: () => createSchemaDefinitionCorrectionPrompt,
|
|
46432
|
+
decodeHtmlEntities: () => decodeHtmlEntities,
|
|
46433
|
+
extractMermaidFromMarkdown: () => extractMermaidFromMarkdown,
|
|
46434
|
+
isJsonSchema: () => isJsonSchema,
|
|
46435
|
+
isJsonSchemaDefinition: () => isJsonSchemaDefinition,
|
|
46436
|
+
isMermaidSchema: () => isMermaidSchema,
|
|
46437
|
+
processSchemaResponse: () => processSchemaResponse,
|
|
46438
|
+
replaceMermaidDiagramsInMarkdown: () => replaceMermaidDiagramsInMarkdown,
|
|
46439
|
+
tryMaidAutoFix: () => tryMaidAutoFix,
|
|
46440
|
+
validateAndFixMermaidResponse: () => validateAndFixMermaidResponse,
|
|
46441
|
+
validateJsonResponse: () => validateJsonResponse,
|
|
46442
|
+
validateMermaidDiagram: () => validateMermaidDiagram,
|
|
46443
|
+
validateMermaidResponse: () => validateMermaidResponse,
|
|
46444
|
+
validateXmlResponse: () => validateXmlResponse
|
|
46445
|
+
});
|
|
46424
46446
|
function decodeHtmlEntities(text) {
|
|
46425
46447
|
if (!text || typeof text !== "string") {
|
|
46426
46448
|
return text;
|
|
@@ -46476,19 +46498,16 @@ function cleanSchemaResponse(response) {
|
|
|
46476
46498
|
return trimmed.substring(startIndex, endIndex);
|
|
46477
46499
|
}
|
|
46478
46500
|
}
|
|
46479
|
-
|
|
46480
|
-
|
|
46481
|
-
|
|
46482
|
-
);
|
|
46483
|
-
const
|
|
46484
|
-
|
|
46485
|
-
|
|
46486
|
-
|
|
46487
|
-
if (
|
|
46488
|
-
|
|
46489
|
-
if (beforeFirstBracket === "" || beforeFirstBracket.match(/^```\w*$/) || beforeFirstBracket.split("\n").length <= 2) {
|
|
46490
|
-
return trimmed.substring(firstBracket, lastBracket + 1);
|
|
46491
|
-
}
|
|
46501
|
+
let cleaned = trimmed;
|
|
46502
|
+
cleaned = cleaned.replace(/^```(?:json)?\s*\n?/i, "");
|
|
46503
|
+
cleaned = cleaned.replace(/\n?```\s*$/, "");
|
|
46504
|
+
cleaned = cleaned.trim();
|
|
46505
|
+
const firstChar = cleaned[0];
|
|
46506
|
+
const lastChar = cleaned[cleaned.length - 1];
|
|
46507
|
+
const isJsonObject = firstChar === "{" && lastChar === "}";
|
|
46508
|
+
const isJsonArray = firstChar === "[" && lastChar === "]";
|
|
46509
|
+
if (isJsonObject || isJsonArray) {
|
|
46510
|
+
return cleaned;
|
|
46492
46511
|
}
|
|
46493
46512
|
return response;
|
|
46494
46513
|
}
|
|
@@ -46509,9 +46528,49 @@ function validateJsonResponse(response, options = {}) {
|
|
|
46509
46528
|
}
|
|
46510
46529
|
return { isValid: true, parsed };
|
|
46511
46530
|
} catch (error) {
|
|
46531
|
+
const positionMatch = error.message.match(/position (\d+)/);
|
|
46532
|
+
let errorPosition = positionMatch ? parseInt(positionMatch[1], 10) : null;
|
|
46533
|
+
if (errorPosition === null) {
|
|
46534
|
+
const tokenMatch = error.message.match(/Unexpected token '(.)', /);
|
|
46535
|
+
if (tokenMatch && tokenMatch[1]) {
|
|
46536
|
+
const problematicToken = tokenMatch[1];
|
|
46537
|
+
errorPosition = response.indexOf(problematicToken);
|
|
46538
|
+
}
|
|
46539
|
+
}
|
|
46540
|
+
let enhancedError = error.message;
|
|
46541
|
+
let errorContext = null;
|
|
46542
|
+
if (errorPosition !== null && errorPosition >= 0 && response && response.length > 0) {
|
|
46543
|
+
const contextRadius = 50;
|
|
46544
|
+
const startPos = Math.max(0, errorPosition - contextRadius);
|
|
46545
|
+
const endPos = Math.min(response.length, errorPosition + contextRadius);
|
|
46546
|
+
const beforeError = response.substring(startPos, errorPosition);
|
|
46547
|
+
const atError = response[errorPosition] || "";
|
|
46548
|
+
const afterError = response.substring(errorPosition + 1, endPos);
|
|
46549
|
+
const snippet = beforeError + atError + afterError;
|
|
46550
|
+
const pointerOffset = beforeError.length;
|
|
46551
|
+
const pointer = " ".repeat(pointerOffset) + "^";
|
|
46552
|
+
errorContext = {
|
|
46553
|
+
position: errorPosition,
|
|
46554
|
+
snippet,
|
|
46555
|
+
pointer,
|
|
46556
|
+
beforeError,
|
|
46557
|
+
atError,
|
|
46558
|
+
afterError
|
|
46559
|
+
};
|
|
46560
|
+
enhancedError = `${error.message}
|
|
46561
|
+
|
|
46562
|
+
Error location (position ${errorPosition}):
|
|
46563
|
+
${snippet}
|
|
46564
|
+
${pointer} here`;
|
|
46565
|
+
}
|
|
46512
46566
|
if (debug) {
|
|
46513
46567
|
console.log(`[DEBUG] JSON validation: Parse failed with error: ${error.message}`);
|
|
46514
|
-
console.log(`[DEBUG] JSON validation: Error at position: ${
|
|
46568
|
+
console.log(`[DEBUG] JSON validation: Error at position: ${errorPosition !== null ? errorPosition : "unknown"}`);
|
|
46569
|
+
if (errorContext) {
|
|
46570
|
+
console.log(`[DEBUG] JSON validation: Error context:
|
|
46571
|
+
${errorContext.snippet}
|
|
46572
|
+
${errorContext.pointer}`);
|
|
46573
|
+
}
|
|
46515
46574
|
if (error.message.includes("Unexpected token")) {
|
|
46516
46575
|
console.log(`[DEBUG] JSON validation: Likely syntax error - unexpected character`);
|
|
46517
46576
|
} else if (error.message.includes("Unexpected end")) {
|
|
@@ -46520,7 +46579,12 @@ function validateJsonResponse(response, options = {}) {
|
|
|
46520
46579
|
console.log(`[DEBUG] JSON validation: Likely unquoted property names`);
|
|
46521
46580
|
}
|
|
46522
46581
|
}
|
|
46523
|
-
return {
|
|
46582
|
+
return {
|
|
46583
|
+
isValid: false,
|
|
46584
|
+
error: error.message,
|
|
46585
|
+
enhancedError,
|
|
46586
|
+
errorContext
|
|
46587
|
+
};
|
|
46524
46588
|
}
|
|
46525
46589
|
}
|
|
46526
46590
|
function validateXmlResponse(response) {
|
|
@@ -46640,7 +46704,16 @@ function isJsonSchemaDefinition(jsonString, options = {}) {
|
|
|
46640
46704
|
return false;
|
|
46641
46705
|
}
|
|
46642
46706
|
}
|
|
46643
|
-
function createJsonCorrectionPrompt(invalidResponse, schema,
|
|
46707
|
+
function createJsonCorrectionPrompt(invalidResponse, schema, errorOrValidation, retryCount = 0) {
|
|
46708
|
+
let errorMessage;
|
|
46709
|
+
let enhancedError;
|
|
46710
|
+
if (typeof errorOrValidation === "object" && errorOrValidation !== null) {
|
|
46711
|
+
errorMessage = errorOrValidation.error;
|
|
46712
|
+
enhancedError = errorOrValidation.enhancedError || errorMessage;
|
|
46713
|
+
} else {
|
|
46714
|
+
errorMessage = errorOrValidation;
|
|
46715
|
+
enhancedError = errorMessage;
|
|
46716
|
+
}
|
|
46644
46717
|
const strengthLevels = [
|
|
46645
46718
|
{
|
|
46646
46719
|
prefix: "CRITICAL JSON ERROR:",
|
|
@@ -46664,7 +46737,7 @@ function createJsonCorrectionPrompt(invalidResponse, schema, error, retryCount =
|
|
|
46664
46737
|
|
|
46665
46738
|
${invalidResponse.substring(0, 500)}${invalidResponse.length > 500 ? "..." : ""}
|
|
46666
46739
|
|
|
46667
|
-
Error: ${
|
|
46740
|
+
Error: ${enhancedError}
|
|
46668
46741
|
|
|
46669
46742
|
${currentLevel.instruction}
|
|
46670
46743
|
|
|
@@ -46709,6 +46782,28 @@ ${currentLevel.example}
|
|
|
46709
46782
|
Return ONLY the JSON data object/array that follows the schema structure. NO schema definitions, NO explanations, NO markdown formatting.`;
|
|
46710
46783
|
return prompt;
|
|
46711
46784
|
}
|
|
46785
|
+
function isMermaidSchema(schema) {
|
|
46786
|
+
if (!schema || typeof schema !== "string") {
|
|
46787
|
+
return false;
|
|
46788
|
+
}
|
|
46789
|
+
const trimmedSchema = schema.trim().toLowerCase();
|
|
46790
|
+
const mermaidIndicators = [
|
|
46791
|
+
trimmedSchema.includes("mermaid"),
|
|
46792
|
+
trimmedSchema.includes("diagram"),
|
|
46793
|
+
trimmedSchema.includes("flowchart"),
|
|
46794
|
+
trimmedSchema.includes("sequence"),
|
|
46795
|
+
trimmedSchema.includes("gantt"),
|
|
46796
|
+
trimmedSchema.includes("pie chart"),
|
|
46797
|
+
trimmedSchema.includes("state diagram"),
|
|
46798
|
+
trimmedSchema.includes("class diagram"),
|
|
46799
|
+
trimmedSchema.includes("entity relationship"),
|
|
46800
|
+
trimmedSchema.includes("user journey"),
|
|
46801
|
+
trimmedSchema.includes("git graph"),
|
|
46802
|
+
trimmedSchema.includes("requirement diagram"),
|
|
46803
|
+
trimmedSchema.includes("c4 context")
|
|
46804
|
+
];
|
|
46805
|
+
return mermaidIndicators.some((indicator) => indicator);
|
|
46806
|
+
}
|
|
46712
46807
|
function extractMermaidFromMarkdown(response) {
|
|
46713
46808
|
if (!response || typeof response !== "string") {
|
|
46714
46809
|
return { diagrams: [], cleanedResponse: response };
|
|
@@ -46729,6 +46824,24 @@ function extractMermaidFromMarkdown(response) {
|
|
|
46729
46824
|
}
|
|
46730
46825
|
return { diagrams, cleanedResponse: response };
|
|
46731
46826
|
}
|
|
46827
|
+
function replaceMermaidDiagramsInMarkdown(originalResponse, correctedDiagrams) {
|
|
46828
|
+
if (!originalResponse || typeof originalResponse !== "string") {
|
|
46829
|
+
return originalResponse;
|
|
46830
|
+
}
|
|
46831
|
+
if (!correctedDiagrams || correctedDiagrams.length === 0) {
|
|
46832
|
+
return originalResponse;
|
|
46833
|
+
}
|
|
46834
|
+
let modifiedResponse = originalResponse;
|
|
46835
|
+
const sortedDiagrams = [...correctedDiagrams].sort((a, b) => b.startIndex - a.startIndex);
|
|
46836
|
+
for (const diagram of sortedDiagrams) {
|
|
46837
|
+
const attributesStr = diagram.attributes ? ` ${diagram.attributes}` : "";
|
|
46838
|
+
const newCodeBlock = `\`\`\`mermaid${attributesStr}
|
|
46839
|
+
${diagram.content}
|
|
46840
|
+
\`\`\``;
|
|
46841
|
+
modifiedResponse = modifiedResponse.slice(0, diagram.startIndex) + newCodeBlock + modifiedResponse.slice(diagram.endIndex);
|
|
46842
|
+
}
|
|
46843
|
+
return modifiedResponse;
|
|
46844
|
+
}
|
|
46732
46845
|
async function validateMermaidDiagram(diagram) {
|
|
46733
46846
|
if (!diagram || typeof diagram !== "string") {
|
|
46734
46847
|
return { isValid: false, error: "Empty or invalid diagram input" };
|
|
@@ -46795,6 +46908,45 @@ async function validateMermaidResponse(response) {
|
|
|
46795
46908
|
errors: errors.length > 0 ? errors : void 0
|
|
46796
46909
|
};
|
|
46797
46910
|
}
|
|
46911
|
+
function createMermaidCorrectionPrompt(invalidResponse, schema, errors, diagrams) {
|
|
46912
|
+
let prompt = `Your previous response contains invalid Mermaid diagrams that cannot be parsed. Here's what you returned:
|
|
46913
|
+
|
|
46914
|
+
${invalidResponse}
|
|
46915
|
+
|
|
46916
|
+
Validation Errors:`;
|
|
46917
|
+
errors.forEach((error, index) => {
|
|
46918
|
+
prompt += `
|
|
46919
|
+
${index + 1}. ${error}`;
|
|
46920
|
+
});
|
|
46921
|
+
if (diagrams && diagrams.length > 0) {
|
|
46922
|
+
prompt += `
|
|
46923
|
+
|
|
46924
|
+
Diagram Details:`;
|
|
46925
|
+
diagrams.forEach((diagramResult, index) => {
|
|
46926
|
+
if (!diagramResult.isValid) {
|
|
46927
|
+
prompt += `
|
|
46928
|
+
|
|
46929
|
+
Diagram ${index + 1}:`;
|
|
46930
|
+
const diagramContent = diagramResult.content || diagramResult.diagram || "";
|
|
46931
|
+
prompt += `
|
|
46932
|
+
- Content: ${diagramContent.substring(0, 100)}${diagramContent.length > 100 ? "..." : ""}`;
|
|
46933
|
+
prompt += `
|
|
46934
|
+
- Error: ${diagramResult.error}`;
|
|
46935
|
+
if (diagramResult.detailedError && diagramResult.detailedError !== diagramResult.error) {
|
|
46936
|
+
prompt += `
|
|
46937
|
+
- Details: ${diagramResult.detailedError}`;
|
|
46938
|
+
}
|
|
46939
|
+
}
|
|
46940
|
+
});
|
|
46941
|
+
}
|
|
46942
|
+
prompt += `
|
|
46943
|
+
|
|
46944
|
+
Please correct your response to include valid Mermaid diagrams that match this schema:
|
|
46945
|
+
${schema}
|
|
46946
|
+
|
|
46947
|
+
Ensure all Mermaid diagrams are properly formatted within \`\`\`mermaid code blocks and follow correct Mermaid syntax.`;
|
|
46948
|
+
return prompt;
|
|
46949
|
+
}
|
|
46798
46950
|
async function tryMaidAutoFix(diagramContent, options = {}) {
|
|
46799
46951
|
const { debug = false } = options;
|
|
46800
46952
|
try {
|
|
@@ -47104,7 +47256,7 @@ ${fixedContent}
|
|
|
47104
47256
|
};
|
|
47105
47257
|
}
|
|
47106
47258
|
}
|
|
47107
|
-
var HTML_ENTITY_MAP, MermaidFixingAgent;
|
|
47259
|
+
var HTML_ENTITY_MAP, JsonFixingAgent, MermaidFixingAgent;
|
|
47108
47260
|
var init_schemaUtils = __esm({
|
|
47109
47261
|
"src/agent/schemaUtils.js"() {
|
|
47110
47262
|
"use strict";
|
|
@@ -47120,6 +47272,156 @@ var init_schemaUtils = __esm({
|
|
|
47120
47272
|
// Also handle XML/HTML5 apostrophe entity
|
|
47121
47273
|
" ": " "
|
|
47122
47274
|
};
|
|
47275
|
+
JsonFixingAgent = class {
|
|
47276
|
+
constructor(options = {}) {
|
|
47277
|
+
this.ProbeAgent = null;
|
|
47278
|
+
this.options = {
|
|
47279
|
+
sessionId: options.sessionId || `json-fixer-${Date.now()}`,
|
|
47280
|
+
path: options.path || process.cwd(),
|
|
47281
|
+
provider: options.provider,
|
|
47282
|
+
model: options.model,
|
|
47283
|
+
debug: options.debug,
|
|
47284
|
+
tracer: options.tracer,
|
|
47285
|
+
// Set to false since we're only fixing JSON syntax, not implementing code
|
|
47286
|
+
allowEdit: false
|
|
47287
|
+
};
|
|
47288
|
+
}
|
|
47289
|
+
/**
|
|
47290
|
+
* Get the specialized prompt for JSON fixing
|
|
47291
|
+
*/
|
|
47292
|
+
getJsonFixingPrompt() {
|
|
47293
|
+
return `You are a world-class JSON syntax correction specialist. Your expertise lies in analyzing and fixing JSON syntax errors while preserving the original data structure and intent.
|
|
47294
|
+
|
|
47295
|
+
CORE RESPONSIBILITIES:
|
|
47296
|
+
- Analyze JSON for syntax errors and structural issues
|
|
47297
|
+
- Fix syntax errors while maintaining the original data's semantic meaning
|
|
47298
|
+
- Ensure JSON follows proper RFC 8259 specification
|
|
47299
|
+
- Handle all JSON structures: objects, arrays, primitives, nested structures
|
|
47300
|
+
|
|
47301
|
+
JSON SYNTAX RULES:
|
|
47302
|
+
1. **Property names**: Must be enclosed in double quotes
|
|
47303
|
+
2. **String values**: Must use double quotes (not single quotes)
|
|
47304
|
+
3. **Numbers**: Can be integers or decimals, no quotes needed
|
|
47305
|
+
4. **Booleans**: true or false (lowercase, no quotes)
|
|
47306
|
+
5. **Null**: null (lowercase, no quotes)
|
|
47307
|
+
6. **Arrays**: Comma-separated values in square brackets [...]
|
|
47308
|
+
7. **Objects**: Comma-separated key-value pairs in curly braces {...}
|
|
47309
|
+
8. **No trailing commas**: Last item in array/object must not have a trailing comma
|
|
47310
|
+
9. **Escape sequences**: Special characters must be escaped (\\n, \\t, \\", \\\\, etc.)
|
|
47311
|
+
|
|
47312
|
+
COMMON ERRORS TO FIX:
|
|
47313
|
+
1. **Unquoted property names**: {name: "value"} \u2192 {"name": "value"}
|
|
47314
|
+
2. **Single quotes**: {'key': 'value'} \u2192 {"key": "value"}
|
|
47315
|
+
3. **Trailing commas**: {"a": 1,} \u2192 {"a": 1}
|
|
47316
|
+
4. **Unquoted strings**: {key: value} \u2192 {"key": "value"}
|
|
47317
|
+
5. **Missing commas**: {"a": 1 "b": 2} \u2192 {"a": 1, "b": 2}
|
|
47318
|
+
6. **Extra commas**: {"a": 1,, "b": 2} \u2192 {"a": 1, "b": 2}
|
|
47319
|
+
7. **Unclosed brackets/braces**: {"key": "value" \u2192 {"key": "value"}
|
|
47320
|
+
8. **Invalid escape sequences**: Fix or remove
|
|
47321
|
+
9. **Comments**: Remove // or /* */ comments (not allowed in JSON)
|
|
47322
|
+
10. **Undefined values**: Replace undefined with null
|
|
47323
|
+
|
|
47324
|
+
FIXING METHODOLOGY:
|
|
47325
|
+
1. **Identify the error location** from the error message
|
|
47326
|
+
2. **Analyze the context** around the error
|
|
47327
|
+
3. **Apply the appropriate fix** based on JSON syntax rules
|
|
47328
|
+
4. **Preserve data intent** - never change the meaning of the data
|
|
47329
|
+
5. **Validate the result** - ensure it's parseable JSON
|
|
47330
|
+
|
|
47331
|
+
CRITICAL RULES:
|
|
47332
|
+
- ALWAYS output only the corrected JSON
|
|
47333
|
+
- NEVER add explanations, comments, or additional text
|
|
47334
|
+
- NEVER wrap in markdown code blocks (no \`\`\`json)
|
|
47335
|
+
- PRESERVE the original data structure and values
|
|
47336
|
+
- FIX only syntax errors, don't modify the data itself
|
|
47337
|
+
- ENSURE the output is valid, parseable JSON
|
|
47338
|
+
|
|
47339
|
+
When presented with broken JSON, analyze it thoroughly and provide the corrected version that maintains the original intent while fixing all syntax issues.`;
|
|
47340
|
+
}
|
|
47341
|
+
/**
|
|
47342
|
+
* Initialize the ProbeAgent if not already done
|
|
47343
|
+
*/
|
|
47344
|
+
async initializeAgent() {
|
|
47345
|
+
if (!this.ProbeAgent) {
|
|
47346
|
+
const { ProbeAgent: ProbeAgent2 } = await Promise.resolve().then(() => (init_ProbeAgent(), ProbeAgent_exports));
|
|
47347
|
+
this.ProbeAgent = ProbeAgent2;
|
|
47348
|
+
}
|
|
47349
|
+
if (!this.agent) {
|
|
47350
|
+
this.agent = new this.ProbeAgent({
|
|
47351
|
+
sessionId: this.options.sessionId,
|
|
47352
|
+
customPrompt: this.getJsonFixingPrompt(),
|
|
47353
|
+
path: this.options.path,
|
|
47354
|
+
provider: this.options.provider,
|
|
47355
|
+
model: this.options.model,
|
|
47356
|
+
debug: this.options.debug,
|
|
47357
|
+
tracer: this.options.tracer,
|
|
47358
|
+
allowEdit: this.options.allowEdit,
|
|
47359
|
+
maxIterations: 5,
|
|
47360
|
+
// Allow multiple iterations for JSON fixing
|
|
47361
|
+
disableJsonValidation: true
|
|
47362
|
+
// CRITICAL: Disable JSON validation in nested agent to prevent infinite recursion
|
|
47363
|
+
});
|
|
47364
|
+
}
|
|
47365
|
+
return this.agent;
|
|
47366
|
+
}
|
|
47367
|
+
/**
|
|
47368
|
+
* Fix invalid JSON using the specialized agent
|
|
47369
|
+
* @param {string} invalidJson - The broken JSON string
|
|
47370
|
+
* @param {string} schema - The original schema for context
|
|
47371
|
+
* @param {Object} validationResult - Validation result with error details
|
|
47372
|
+
* @param {number} attemptNumber - Current attempt number (for logging)
|
|
47373
|
+
* @returns {Promise<string>} - The corrected JSON
|
|
47374
|
+
*/
|
|
47375
|
+
async fixJson(invalidJson, schema, validationResult, attemptNumber = 1) {
|
|
47376
|
+
await this.initializeAgent();
|
|
47377
|
+
let errorContext = validationResult.error;
|
|
47378
|
+
if (validationResult.enhancedError) {
|
|
47379
|
+
errorContext = validationResult.enhancedError;
|
|
47380
|
+
}
|
|
47381
|
+
const prompt = `Fix the following invalid JSON.
|
|
47382
|
+
|
|
47383
|
+
Error: ${errorContext}
|
|
47384
|
+
|
|
47385
|
+
Invalid JSON:
|
|
47386
|
+
${invalidJson}
|
|
47387
|
+
|
|
47388
|
+
Expected schema structure:
|
|
47389
|
+
${schema}
|
|
47390
|
+
|
|
47391
|
+
Provide only the corrected JSON without any markdown formatting or explanations.`;
|
|
47392
|
+
try {
|
|
47393
|
+
if (this.options.debug) {
|
|
47394
|
+
console.log(`[DEBUG] JSON fixing: Attempt ${attemptNumber} to fix JSON with separate agent`);
|
|
47395
|
+
}
|
|
47396
|
+
const result = await this.agent.answer(prompt, []);
|
|
47397
|
+
const cleaned = cleanSchemaResponse(result);
|
|
47398
|
+
if (this.options.debug) {
|
|
47399
|
+
console.log(`[DEBUG] JSON fixing: Agent returned ${cleaned.length} chars`);
|
|
47400
|
+
}
|
|
47401
|
+
return cleaned;
|
|
47402
|
+
} catch (error) {
|
|
47403
|
+
if (this.options.debug) {
|
|
47404
|
+
console.error(`[DEBUG] JSON fixing failed: ${error.message}`);
|
|
47405
|
+
}
|
|
47406
|
+
throw new Error(`Failed to fix JSON: ${error.message}`);
|
|
47407
|
+
}
|
|
47408
|
+
}
|
|
47409
|
+
/**
|
|
47410
|
+
* Get token usage information from the specialized agent
|
|
47411
|
+
* @returns {Object} - Token usage statistics
|
|
47412
|
+
*/
|
|
47413
|
+
getTokenUsage() {
|
|
47414
|
+
return this.agent ? this.agent.getTokenUsage() : null;
|
|
47415
|
+
}
|
|
47416
|
+
/**
|
|
47417
|
+
* Cancel any ongoing operations
|
|
47418
|
+
*/
|
|
47419
|
+
cancel() {
|
|
47420
|
+
if (this.agent) {
|
|
47421
|
+
this.agent.cancel();
|
|
47422
|
+
}
|
|
47423
|
+
}
|
|
47424
|
+
};
|
|
47123
47425
|
MermaidFixingAgent = class {
|
|
47124
47426
|
constructor(options = {}) {
|
|
47125
47427
|
this.ProbeAgent = null;
|
|
@@ -48112,6 +48414,7 @@ var init_ProbeAgent = __esm({
|
|
|
48112
48414
|
* @param {number} [options.maxResponseTokens] - Maximum tokens for AI responses
|
|
48113
48415
|
* @param {number} [options.maxIterations] - Maximum tool iterations (overrides MAX_TOOL_ITERATIONS env var)
|
|
48114
48416
|
* @param {boolean} [options.disableMermaidValidation=false] - Disable automatic mermaid diagram validation and fixing
|
|
48417
|
+
* @param {boolean} [options.disableJsonValidation=false] - Disable automatic JSON validation and fixing (prevents infinite recursion in JsonFixingAgent)
|
|
48115
48418
|
* @param {boolean} [options.enableMcp=false] - Enable MCP tool integration
|
|
48116
48419
|
* @param {string} [options.mcpConfigPath] - Path to MCP configuration file
|
|
48117
48420
|
* @param {Object} [options.mcpConfig] - MCP configuration object (overrides mcpConfigPath)
|
|
@@ -48131,6 +48434,7 @@ var init_ProbeAgent = __esm({
|
|
|
48131
48434
|
this.maxResponseTokens = options.maxResponseTokens || parseInt(process.env.MAX_RESPONSE_TOKENS || "0", 10) || null;
|
|
48132
48435
|
this.maxIterations = options.maxIterations || null;
|
|
48133
48436
|
this.disableMermaidValidation = !!options.disableMermaidValidation;
|
|
48437
|
+
this.disableJsonValidation = !!options.disableJsonValidation;
|
|
48134
48438
|
this.storageAdapter = options.storageAdapter || new InMemoryStorageAdapter();
|
|
48135
48439
|
this.hooks = new HookManager();
|
|
48136
48440
|
if (options.hooks) {
|
|
@@ -49345,15 +49649,16 @@ Remember: Use proper XML format with BOTH opening and closing tags:
|
|
|
49345
49649
|
<parameter>value</parameter>
|
|
49346
49650
|
</tool_name>
|
|
49347
49651
|
|
|
49348
|
-
IMPORTANT: A schema was provided
|
|
49349
|
-
Use attempt_completion with your response directly inside the tags:
|
|
49652
|
+
IMPORTANT: A schema was provided for the final output format. You have two options:
|
|
49350
49653
|
|
|
49654
|
+
Option 1 - Use attempt_completion with your complete answer:
|
|
49351
49655
|
<attempt_completion>
|
|
49352
|
-
[Your
|
|
49656
|
+
[Your complete answer here - will be automatically formatted to match the schema]
|
|
49353
49657
|
</attempt_completion>
|
|
49354
49658
|
|
|
49355
|
-
|
|
49356
|
-
|
|
49659
|
+
Option 2 - Provide a natural response without any tool, and it will be automatically formatted.
|
|
49660
|
+
|
|
49661
|
+
Do NOT try to format your response as JSON yourself - this will be done automatically.`;
|
|
49357
49662
|
} else {
|
|
49358
49663
|
reminderContent = `Please use one of the available tools to help answer the question, or use attempt_completion if you have enough information to provide a final answer.
|
|
49359
49664
|
|
|
@@ -49500,6 +49805,10 @@ Convert your previous response content into actual JSON data that follows this s
|
|
|
49500
49805
|
console.log(`[DEBUG] JSON validation: Starting validation process for schema response`);
|
|
49501
49806
|
console.log(`[DEBUG] JSON validation: Response length: ${finalResult.length} chars`);
|
|
49502
49807
|
}
|
|
49808
|
+
finalResult = cleanSchemaResponse(finalResult);
|
|
49809
|
+
if (this.debug) {
|
|
49810
|
+
console.log(`[DEBUG] JSON validation: After cleaning, length: ${finalResult.length} chars`);
|
|
49811
|
+
}
|
|
49503
49812
|
if (this.tracer) {
|
|
49504
49813
|
this.tracer.recordJsonValidationEvent("started", {
|
|
49505
49814
|
"json_validation.response_length": finalResult.length,
|
|
@@ -49511,75 +49820,66 @@ Convert your previous response content into actual JSON data that follows this s
|
|
|
49511
49820
|
const maxRetries = 3;
|
|
49512
49821
|
if (validation.isValid && isJsonSchemaDefinition(finalResult, { debug: this.debug })) {
|
|
49513
49822
|
if (this.debug) {
|
|
49514
|
-
console.log(`[DEBUG] JSON validation: Response is a JSON schema definition instead of data,
|
|
49823
|
+
console.log(`[DEBUG] JSON validation: Response is a JSON schema definition instead of data, needs correction...`);
|
|
49515
49824
|
}
|
|
49516
|
-
|
|
49517
|
-
|
|
49518
|
-
|
|
49519
|
-
|
|
49520
|
-
|
|
49521
|
-
finalResult = await this.answer(schemaDefinitionPrompt, [], {
|
|
49522
|
-
...options,
|
|
49523
|
-
_schemaFormatted: true
|
|
49524
|
-
});
|
|
49525
|
-
finalResult = cleanSchemaResponse(finalResult);
|
|
49526
|
-
validation = validateJsonResponse(finalResult);
|
|
49527
|
-
retryCount = 1;
|
|
49825
|
+
validation = {
|
|
49826
|
+
isValid: false,
|
|
49827
|
+
error: "Response is a JSON schema definition instead of actual data",
|
|
49828
|
+
enhancedError: "Response is a JSON schema definition instead of actual data. Please return data that conforms to the schema, not the schema itself."
|
|
49829
|
+
};
|
|
49528
49830
|
}
|
|
49529
|
-
|
|
49831
|
+
if (!validation.isValid) {
|
|
49530
49832
|
if (this.debug) {
|
|
49531
|
-
console.log(`[DEBUG] JSON validation:
|
|
49532
|
-
console.log(`[DEBUG] JSON validation: Invalid response sample: ${finalResult.substring(0, 300)}${finalResult.length > 300 ? "..." : ""}`);
|
|
49833
|
+
console.log(`[DEBUG] JSON validation: Starting separate JsonFixingAgent session...`);
|
|
49533
49834
|
}
|
|
49534
|
-
|
|
49535
|
-
|
|
49536
|
-
|
|
49537
|
-
|
|
49538
|
-
|
|
49539
|
-
|
|
49540
|
-
|
|
49541
|
-
|
|
49542
|
-
|
|
49543
|
-
|
|
49544
|
-
|
|
49545
|
-
|
|
49546
|
-
|
|
49547
|
-
|
|
49835
|
+
const { JsonFixingAgent: JsonFixingAgent2 } = await Promise.resolve().then(() => (init_schemaUtils(), schemaUtils_exports));
|
|
49836
|
+
const jsonFixer = new JsonFixingAgent2({
|
|
49837
|
+
path: this.allowedFolders[0],
|
|
49838
|
+
provider: this.clientApiProvider,
|
|
49839
|
+
model: this.model,
|
|
49840
|
+
debug: this.debug,
|
|
49841
|
+
tracer: this.tracer
|
|
49842
|
+
});
|
|
49843
|
+
let currentResult = finalResult;
|
|
49844
|
+
let currentValidation = validation;
|
|
49845
|
+
while (!currentValidation.isValid && retryCount < maxRetries) {
|
|
49846
|
+
if (this.debug) {
|
|
49847
|
+
console.log(`[DEBUG] JSON validation: Validation failed (attempt ${retryCount + 1}/${maxRetries}):`, currentValidation.error);
|
|
49848
|
+
console.log(`[DEBUG] JSON validation: Invalid response sample: ${currentResult.substring(0, 300)}${currentResult.length > 300 ? "..." : ""}`);
|
|
49849
|
+
}
|
|
49850
|
+
try {
|
|
49851
|
+
currentResult = await jsonFixer.fixJson(
|
|
49852
|
+
currentResult,
|
|
49548
49853
|
options.schema,
|
|
49549
|
-
|
|
49550
|
-
retryCount
|
|
49854
|
+
currentValidation,
|
|
49855
|
+
retryCount + 1
|
|
49551
49856
|
);
|
|
49857
|
+
currentValidation = validateJsonResponse(currentResult, { debug: this.debug });
|
|
49858
|
+
retryCount++;
|
|
49859
|
+
if (this.debug) {
|
|
49860
|
+
if (!currentValidation.isValid && retryCount < maxRetries) {
|
|
49861
|
+
console.log(`[DEBUG] JSON validation: Still invalid after correction ${retryCount}, retrying...`);
|
|
49862
|
+
console.log(`[DEBUG] JSON validation: Corrected response sample: ${currentResult.substring(0, 300)}${currentResult.length > 300 ? "..." : ""}`);
|
|
49863
|
+
} else if (currentValidation.isValid) {
|
|
49864
|
+
console.log(`[DEBUG] JSON validation: Successfully corrected after ${retryCount} attempts with JsonFixingAgent`);
|
|
49865
|
+
}
|
|
49866
|
+
}
|
|
49867
|
+
} catch (error) {
|
|
49868
|
+
if (this.debug) {
|
|
49869
|
+
console.error(`[DEBUG] JSON validation: JsonFixingAgent error on attempt ${retryCount + 1}:`, error.message);
|
|
49870
|
+
}
|
|
49871
|
+
break;
|
|
49552
49872
|
}
|
|
49553
|
-
} catch (error) {
|
|
49554
|
-
correctionPrompt = createJsonCorrectionPrompt(
|
|
49555
|
-
finalResult,
|
|
49556
|
-
options.schema,
|
|
49557
|
-
validation.error,
|
|
49558
|
-
retryCount
|
|
49559
|
-
);
|
|
49560
49873
|
}
|
|
49561
|
-
finalResult =
|
|
49562
|
-
|
|
49563
|
-
|
|
49564
|
-
|
|
49565
|
-
|
|
49566
|
-
|
|
49567
|
-
|
|
49568
|
-
if (this.debug) {
|
|
49569
|
-
if (!validation.isValid && retryCount < maxRetries) {
|
|
49570
|
-
console.log(`[DEBUG] JSON validation: Still invalid after correction ${retryCount}, retrying...`);
|
|
49571
|
-
console.log(`[DEBUG] JSON validation: Corrected response sample: ${finalResult.substring(0, 300)}${finalResult.length > 300 ? "..." : ""}`);
|
|
49572
|
-
} else if (validation.isValid) {
|
|
49573
|
-
console.log(`[DEBUG] JSON validation: Successfully corrected after ${retryCount} attempts`);
|
|
49574
|
-
}
|
|
49874
|
+
finalResult = currentResult;
|
|
49875
|
+
validation = currentValidation;
|
|
49876
|
+
if (!validation.isValid && this.debug) {
|
|
49877
|
+
console.log(`[DEBUG] JSON validation: Still invalid after ${maxRetries} correction attempts with JsonFixingAgent:`, validation.error);
|
|
49878
|
+
console.log(`[DEBUG] JSON validation: Final invalid response: ${finalResult.substring(0, 500)}${finalResult.length > 500 ? "..." : ""}`);
|
|
49879
|
+
} else if (validation.isValid && this.debug) {
|
|
49880
|
+
console.log(`[DEBUG] JSON validation: Final validation successful`);
|
|
49575
49881
|
}
|
|
49576
49882
|
}
|
|
49577
|
-
if (!validation.isValid && this.debug) {
|
|
49578
|
-
console.log(`[DEBUG] JSON validation: Still invalid after ${maxRetries} correction attempts:`, validation.error);
|
|
49579
|
-
console.log(`[DEBUG] JSON validation: Final invalid response: ${finalResult.substring(0, 500)}${finalResult.length > 500 ? "..." : ""}`);
|
|
49580
|
-
} else if (validation.isValid && this.debug) {
|
|
49581
|
-
console.log(`[DEBUG] JSON validation: Final validation successful`);
|
|
49582
|
-
}
|
|
49583
49883
|
if (this.tracer) {
|
|
49584
49884
|
this.tracer.recordJsonValidationEvent("completed", {
|
|
49585
49885
|
"json_validation.success": validation.isValid,
|
|
@@ -49827,6 +50127,7 @@ Convert your previous response content into actual JSON data that follows this s
|
|
|
49827
50127
|
maxResponseTokens: this.maxResponseTokens,
|
|
49828
50128
|
maxIterations: this.maxIterations,
|
|
49829
50129
|
disableMermaidValidation: this.disableMermaidValidation,
|
|
50130
|
+
disableJsonValidation: this.disableJsonValidation,
|
|
49830
50131
|
enableMcp: !!this.mcpBridge,
|
|
49831
50132
|
mcpConfig: this.mcpConfig,
|
|
49832
50133
|
enableBash: this.enableBash,
|
|
@@ -49845,11 +50146,44 @@ Convert your previous response content into actual JSON data that follows this s
|
|
|
49845
50146
|
}
|
|
49846
50147
|
/**
|
|
49847
50148
|
* Internal method to strip internal/temporary messages from history
|
|
49848
|
-
*
|
|
49849
|
-
*
|
|
50149
|
+
* Strategy: Find the FIRST schema-related message and truncate everything from that point onwards.
|
|
50150
|
+
* This ensures that all schema formatting iterations (IMPORTANT, CRITICAL, corrections, etc.) are removed.
|
|
50151
|
+
* Keeps: system message, user messages, assistant responses, tool results up to the first schema message
|
|
49850
50152
|
* @private
|
|
49851
50153
|
*/
|
|
49852
50154
|
_stripInternalMessages(history, keepSystemMessage = true) {
|
|
50155
|
+
let firstSchemaMessageIndex = -1;
|
|
50156
|
+
for (let i = 0; i < history.length; i++) {
|
|
50157
|
+
const message = history[i];
|
|
50158
|
+
if (message.role === "system") {
|
|
50159
|
+
continue;
|
|
50160
|
+
}
|
|
50161
|
+
if (this._isSchemaMessage(message)) {
|
|
50162
|
+
firstSchemaMessageIndex = i;
|
|
50163
|
+
if (this.debug) {
|
|
50164
|
+
console.log(`[DEBUG] Found first schema message at index ${i}, truncating from here`);
|
|
50165
|
+
}
|
|
50166
|
+
break;
|
|
50167
|
+
}
|
|
50168
|
+
}
|
|
50169
|
+
if (firstSchemaMessageIndex === -1) {
|
|
50170
|
+
return this._stripNonSchemaInternalMessages(history, keepSystemMessage);
|
|
50171
|
+
}
|
|
50172
|
+
const truncated = history.slice(0, firstSchemaMessageIndex);
|
|
50173
|
+
const filtered = this._stripNonSchemaInternalMessages(truncated, keepSystemMessage);
|
|
50174
|
+
if (this.debug) {
|
|
50175
|
+
const removedCount = history.length - filtered.length;
|
|
50176
|
+
console.log(`[DEBUG] Truncated at schema message (index ${firstSchemaMessageIndex}) and filtered non-schema internal messages`);
|
|
50177
|
+
console.log(`[DEBUG] Removed ${removedCount} messages total (${history.length} \u2192 ${filtered.length})`);
|
|
50178
|
+
}
|
|
50179
|
+
return filtered;
|
|
50180
|
+
}
|
|
50181
|
+
/**
|
|
50182
|
+
* Strip non-schema internal messages (mermaid fixes, tool reminders, etc.) individually
|
|
50183
|
+
* Used when no schema messages are present in history
|
|
50184
|
+
* @private
|
|
50185
|
+
*/
|
|
50186
|
+
_stripNonSchemaInternalMessages(history, keepSystemMessage = true) {
|
|
49853
50187
|
const filtered = [];
|
|
49854
50188
|
for (let i = 0; i < history.length; i++) {
|
|
49855
50189
|
const message = history[i];
|
|
@@ -49861,9 +50195,9 @@ Convert your previous response content into actual JSON data that follows this s
|
|
|
49861
50195
|
}
|
|
49862
50196
|
continue;
|
|
49863
50197
|
}
|
|
49864
|
-
if (this.
|
|
50198
|
+
if (this._isNonSchemaInternalMessage(message)) {
|
|
49865
50199
|
if (this.debug) {
|
|
49866
|
-
console.log(`[DEBUG] Stripping internal message at index ${i}: ${message.role}`);
|
|
50200
|
+
console.log(`[DEBUG] Stripping non-schema internal message at index ${i}: ${message.role}`);
|
|
49867
50201
|
}
|
|
49868
50202
|
continue;
|
|
49869
50203
|
}
|
|
@@ -49872,20 +50206,50 @@ Convert your previous response content into actual JSON data that follows this s
|
|
|
49872
50206
|
return filtered;
|
|
49873
50207
|
}
|
|
49874
50208
|
/**
|
|
49875
|
-
*
|
|
50209
|
+
* Check if a message is schema-related (IMPORTANT, CRITICAL, etc.)
|
|
49876
50210
|
* @private
|
|
49877
50211
|
*/
|
|
49878
|
-
|
|
50212
|
+
_isSchemaMessage(message) {
|
|
49879
50213
|
if (message.role !== "user") {
|
|
49880
50214
|
return false;
|
|
49881
50215
|
}
|
|
49882
50216
|
if (!message.content) {
|
|
49883
50217
|
return false;
|
|
49884
50218
|
}
|
|
49885
|
-
|
|
49886
|
-
|
|
50219
|
+
let content;
|
|
50220
|
+
try {
|
|
50221
|
+
content = typeof message.content === "string" ? message.content : JSON.stringify(message.content);
|
|
50222
|
+
} catch (error) {
|
|
50223
|
+
if (this.debug) {
|
|
50224
|
+
console.log(`[DEBUG] Could not stringify message content in _isSchemaMessage: ${error.message}`);
|
|
50225
|
+
}
|
|
50226
|
+
return false;
|
|
50227
|
+
}
|
|
50228
|
+
if (content.includes("IMPORTANT: A schema was provided") || content.includes("You MUST respond with data that matches this schema") || content.includes("Your response must conform to this schema:") || content.includes("CRITICAL: You MUST respond with ONLY valid JSON DATA") || content.includes("Schema to follow (this is just the structure")) {
|
|
49887
50229
|
return true;
|
|
49888
50230
|
}
|
|
50231
|
+
return false;
|
|
50232
|
+
}
|
|
50233
|
+
/**
|
|
50234
|
+
* Check if a message is a non-schema internal message (mermaid, tool reminders, JSON corrections)
|
|
50235
|
+
* @private
|
|
50236
|
+
*/
|
|
50237
|
+
_isNonSchemaInternalMessage(message) {
|
|
50238
|
+
if (message.role !== "user") {
|
|
50239
|
+
return false;
|
|
50240
|
+
}
|
|
50241
|
+
if (!message.content) {
|
|
50242
|
+
return false;
|
|
50243
|
+
}
|
|
50244
|
+
let content;
|
|
50245
|
+
try {
|
|
50246
|
+
content = typeof message.content === "string" ? message.content : JSON.stringify(message.content);
|
|
50247
|
+
} catch (error) {
|
|
50248
|
+
if (this.debug) {
|
|
50249
|
+
console.log(`[DEBUG] Could not stringify message content in _isNonSchemaInternalMessage: ${error.message}`);
|
|
50250
|
+
}
|
|
50251
|
+
return false;
|
|
50252
|
+
}
|
|
49889
50253
|
if (content.includes("Please use one of the available tools") && content.includes("or use attempt_completion") && content.includes("Remember: Use proper XML format")) {
|
|
49890
50254
|
return true;
|
|
49891
50255
|
}
|