@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.
@@ -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
- const firstBracket = Math.min(
46480
- trimmed.indexOf("{") >= 0 ? trimmed.indexOf("{") : Infinity,
46481
- trimmed.indexOf("[") >= 0 ? trimmed.indexOf("[") : Infinity
46482
- );
46483
- const lastBracket = Math.max(
46484
- trimmed.lastIndexOf("}"),
46485
- trimmed.lastIndexOf("]")
46486
- );
46487
- if (firstBracket < Infinity && lastBracket >= 0 && firstBracket < lastBracket) {
46488
- const beforeFirstBracket = trimmed.substring(0, firstBracket).trim();
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: ${error.message.match(/position (\d+)/) ? error.message.match(/position (\d+)/)[1] : "unknown"}`);
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 { isValid: false, error: error.message };
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, error, retryCount = 0) {
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: ${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
  "&nbsp;": " "
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. You MUST respond with data that matches this schema.
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 response content matching the provided schema format]
49656
+ [Your complete answer here - will be automatically formatted to match the schema]
49353
49657
  </attempt_completion>
49354
49658
 
49355
- Your response must conform to this schema:
49356
- ${options.schema}`;
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, correcting...`);
49823
+ console.log(`[DEBUG] JSON validation: Response is a JSON schema definition instead of data, needs correction...`);
49515
49824
  }
49516
- const schemaDefinitionPrompt = createSchemaDefinitionCorrectionPrompt(
49517
- finalResult,
49518
- options.schema,
49519
- 0
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
- while (!validation.isValid && retryCount < maxRetries) {
49831
+ if (!validation.isValid) {
49530
49832
  if (this.debug) {
49531
- console.log(`[DEBUG] JSON validation: Validation failed (attempt ${retryCount + 1}/${maxRetries}):`, validation.error);
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
- let correctionPrompt;
49535
- try {
49536
- if (isJsonSchemaDefinition(finalResult, { debug: this.debug })) {
49537
- if (this.debug) {
49538
- console.log(`[DEBUG] JSON validation: Response is still a schema definition, using specialized correction`);
49539
- }
49540
- correctionPrompt = createSchemaDefinitionCorrectionPrompt(
49541
- finalResult,
49542
- options.schema,
49543
- retryCount
49544
- );
49545
- } else {
49546
- correctionPrompt = createJsonCorrectionPrompt(
49547
- finalResult,
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
- validation.error,
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 = await this.answer(correctionPrompt, [], {
49562
- ...options,
49563
- _schemaFormatted: true
49564
- });
49565
- finalResult = cleanSchemaResponse(finalResult);
49566
- validation = validateJsonResponse(finalResult, { debug: this.debug });
49567
- retryCount++;
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
- * Removes: schema reminders, mermaid fix prompts, tool use reminders, etc.
49849
- * Keeps: system message, user messages, assistant responses, tool results
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._isInternalMessage(message, i, history)) {
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
- * Determine if a message is an internal/temporary message
50209
+ * Check if a message is schema-related (IMPORTANT, CRITICAL, etc.)
49876
50210
  * @private
49877
50211
  */
49878
- _isInternalMessage(message, index, history) {
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
- const content = typeof message.content === "string" ? message.content : JSON.stringify(message.content);
49886
- 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:")) {
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
  }