@probelabs/probe 0.6.0-rc130 → 0.6.0-rc132

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;
@@ -46509,9 +46531,49 @@ function validateJsonResponse(response, options = {}) {
46509
46531
  }
46510
46532
  return { isValid: true, parsed };
46511
46533
  } catch (error) {
46534
+ const positionMatch = error.message.match(/position (\d+)/);
46535
+ let errorPosition = positionMatch ? parseInt(positionMatch[1], 10) : null;
46536
+ if (errorPosition === null) {
46537
+ const tokenMatch = error.message.match(/Unexpected token '(.)', /);
46538
+ if (tokenMatch && tokenMatch[1]) {
46539
+ const problematicToken = tokenMatch[1];
46540
+ errorPosition = response.indexOf(problematicToken);
46541
+ }
46542
+ }
46543
+ let enhancedError = error.message;
46544
+ let errorContext = null;
46545
+ if (errorPosition !== null && errorPosition >= 0 && response && response.length > 0) {
46546
+ const contextRadius = 50;
46547
+ const startPos = Math.max(0, errorPosition - contextRadius);
46548
+ const endPos = Math.min(response.length, errorPosition + contextRadius);
46549
+ const beforeError = response.substring(startPos, errorPosition);
46550
+ const atError = response[errorPosition] || "";
46551
+ const afterError = response.substring(errorPosition + 1, endPos);
46552
+ const snippet = beforeError + atError + afterError;
46553
+ const pointerOffset = beforeError.length;
46554
+ const pointer = " ".repeat(pointerOffset) + "^";
46555
+ errorContext = {
46556
+ position: errorPosition,
46557
+ snippet,
46558
+ pointer,
46559
+ beforeError,
46560
+ atError,
46561
+ afterError
46562
+ };
46563
+ enhancedError = `${error.message}
46564
+
46565
+ Error location (position ${errorPosition}):
46566
+ ${snippet}
46567
+ ${pointer} here`;
46568
+ }
46512
46569
  if (debug) {
46513
46570
  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"}`);
46571
+ console.log(`[DEBUG] JSON validation: Error at position: ${errorPosition !== null ? errorPosition : "unknown"}`);
46572
+ if (errorContext) {
46573
+ console.log(`[DEBUG] JSON validation: Error context:
46574
+ ${errorContext.snippet}
46575
+ ${errorContext.pointer}`);
46576
+ }
46515
46577
  if (error.message.includes("Unexpected token")) {
46516
46578
  console.log(`[DEBUG] JSON validation: Likely syntax error - unexpected character`);
46517
46579
  } else if (error.message.includes("Unexpected end")) {
@@ -46520,7 +46582,12 @@ function validateJsonResponse(response, options = {}) {
46520
46582
  console.log(`[DEBUG] JSON validation: Likely unquoted property names`);
46521
46583
  }
46522
46584
  }
46523
- return { isValid: false, error: error.message };
46585
+ return {
46586
+ isValid: false,
46587
+ error: error.message,
46588
+ enhancedError,
46589
+ errorContext
46590
+ };
46524
46591
  }
46525
46592
  }
46526
46593
  function validateXmlResponse(response) {
@@ -46640,7 +46707,16 @@ function isJsonSchemaDefinition(jsonString, options = {}) {
46640
46707
  return false;
46641
46708
  }
46642
46709
  }
46643
- function createJsonCorrectionPrompt(invalidResponse, schema, error, retryCount = 0) {
46710
+ function createJsonCorrectionPrompt(invalidResponse, schema, errorOrValidation, retryCount = 0) {
46711
+ let errorMessage;
46712
+ let enhancedError;
46713
+ if (typeof errorOrValidation === "object" && errorOrValidation !== null) {
46714
+ errorMessage = errorOrValidation.error;
46715
+ enhancedError = errorOrValidation.enhancedError || errorMessage;
46716
+ } else {
46717
+ errorMessage = errorOrValidation;
46718
+ enhancedError = errorMessage;
46719
+ }
46644
46720
  const strengthLevels = [
46645
46721
  {
46646
46722
  prefix: "CRITICAL JSON ERROR:",
@@ -46664,7 +46740,7 @@ function createJsonCorrectionPrompt(invalidResponse, schema, error, retryCount =
46664
46740
 
46665
46741
  ${invalidResponse.substring(0, 500)}${invalidResponse.length > 500 ? "..." : ""}
46666
46742
 
46667
- Error: ${error}
46743
+ Error: ${enhancedError}
46668
46744
 
46669
46745
  ${currentLevel.instruction}
46670
46746
 
@@ -46709,6 +46785,28 @@ ${currentLevel.example}
46709
46785
  Return ONLY the JSON data object/array that follows the schema structure. NO schema definitions, NO explanations, NO markdown formatting.`;
46710
46786
  return prompt;
46711
46787
  }
46788
+ function isMermaidSchema(schema) {
46789
+ if (!schema || typeof schema !== "string") {
46790
+ return false;
46791
+ }
46792
+ const trimmedSchema = schema.trim().toLowerCase();
46793
+ const mermaidIndicators = [
46794
+ trimmedSchema.includes("mermaid"),
46795
+ trimmedSchema.includes("diagram"),
46796
+ trimmedSchema.includes("flowchart"),
46797
+ trimmedSchema.includes("sequence"),
46798
+ trimmedSchema.includes("gantt"),
46799
+ trimmedSchema.includes("pie chart"),
46800
+ trimmedSchema.includes("state diagram"),
46801
+ trimmedSchema.includes("class diagram"),
46802
+ trimmedSchema.includes("entity relationship"),
46803
+ trimmedSchema.includes("user journey"),
46804
+ trimmedSchema.includes("git graph"),
46805
+ trimmedSchema.includes("requirement diagram"),
46806
+ trimmedSchema.includes("c4 context")
46807
+ ];
46808
+ return mermaidIndicators.some((indicator) => indicator);
46809
+ }
46712
46810
  function extractMermaidFromMarkdown(response) {
46713
46811
  if (!response || typeof response !== "string") {
46714
46812
  return { diagrams: [], cleanedResponse: response };
@@ -46729,6 +46827,24 @@ function extractMermaidFromMarkdown(response) {
46729
46827
  }
46730
46828
  return { diagrams, cleanedResponse: response };
46731
46829
  }
46830
+ function replaceMermaidDiagramsInMarkdown(originalResponse, correctedDiagrams) {
46831
+ if (!originalResponse || typeof originalResponse !== "string") {
46832
+ return originalResponse;
46833
+ }
46834
+ if (!correctedDiagrams || correctedDiagrams.length === 0) {
46835
+ return originalResponse;
46836
+ }
46837
+ let modifiedResponse = originalResponse;
46838
+ const sortedDiagrams = [...correctedDiagrams].sort((a, b) => b.startIndex - a.startIndex);
46839
+ for (const diagram of sortedDiagrams) {
46840
+ const attributesStr = diagram.attributes ? ` ${diagram.attributes}` : "";
46841
+ const newCodeBlock = `\`\`\`mermaid${attributesStr}
46842
+ ${diagram.content}
46843
+ \`\`\``;
46844
+ modifiedResponse = modifiedResponse.slice(0, diagram.startIndex) + newCodeBlock + modifiedResponse.slice(diagram.endIndex);
46845
+ }
46846
+ return modifiedResponse;
46847
+ }
46732
46848
  async function validateMermaidDiagram(diagram) {
46733
46849
  if (!diagram || typeof diagram !== "string") {
46734
46850
  return { isValid: false, error: "Empty or invalid diagram input" };
@@ -46795,6 +46911,45 @@ async function validateMermaidResponse(response) {
46795
46911
  errors: errors.length > 0 ? errors : void 0
46796
46912
  };
46797
46913
  }
46914
+ function createMermaidCorrectionPrompt(invalidResponse, schema, errors, diagrams) {
46915
+ let prompt = `Your previous response contains invalid Mermaid diagrams that cannot be parsed. Here's what you returned:
46916
+
46917
+ ${invalidResponse}
46918
+
46919
+ Validation Errors:`;
46920
+ errors.forEach((error, index) => {
46921
+ prompt += `
46922
+ ${index + 1}. ${error}`;
46923
+ });
46924
+ if (diagrams && diagrams.length > 0) {
46925
+ prompt += `
46926
+
46927
+ Diagram Details:`;
46928
+ diagrams.forEach((diagramResult, index) => {
46929
+ if (!diagramResult.isValid) {
46930
+ prompt += `
46931
+
46932
+ Diagram ${index + 1}:`;
46933
+ const diagramContent = diagramResult.content || diagramResult.diagram || "";
46934
+ prompt += `
46935
+ - Content: ${diagramContent.substring(0, 100)}${diagramContent.length > 100 ? "..." : ""}`;
46936
+ prompt += `
46937
+ - Error: ${diagramResult.error}`;
46938
+ if (diagramResult.detailedError && diagramResult.detailedError !== diagramResult.error) {
46939
+ prompt += `
46940
+ - Details: ${diagramResult.detailedError}`;
46941
+ }
46942
+ }
46943
+ });
46944
+ }
46945
+ prompt += `
46946
+
46947
+ Please correct your response to include valid Mermaid diagrams that match this schema:
46948
+ ${schema}
46949
+
46950
+ Ensure all Mermaid diagrams are properly formatted within \`\`\`mermaid code blocks and follow correct Mermaid syntax.`;
46951
+ return prompt;
46952
+ }
46798
46953
  async function tryMaidAutoFix(diagramContent, options = {}) {
46799
46954
  const { debug = false } = options;
46800
46955
  try {
@@ -47104,7 +47259,7 @@ ${fixedContent}
47104
47259
  };
47105
47260
  }
47106
47261
  }
47107
- var HTML_ENTITY_MAP, MermaidFixingAgent;
47262
+ var HTML_ENTITY_MAP, JsonFixingAgent, MermaidFixingAgent;
47108
47263
  var init_schemaUtils = __esm({
47109
47264
  "src/agent/schemaUtils.js"() {
47110
47265
  "use strict";
@@ -47120,6 +47275,156 @@ var init_schemaUtils = __esm({
47120
47275
  // Also handle XML/HTML5 apostrophe entity
47121
47276
  " ": " "
47122
47277
  };
47278
+ JsonFixingAgent = class {
47279
+ constructor(options = {}) {
47280
+ this.ProbeAgent = null;
47281
+ this.options = {
47282
+ sessionId: options.sessionId || `json-fixer-${Date.now()}`,
47283
+ path: options.path || process.cwd(),
47284
+ provider: options.provider,
47285
+ model: options.model,
47286
+ debug: options.debug,
47287
+ tracer: options.tracer,
47288
+ // Set to false since we're only fixing JSON syntax, not implementing code
47289
+ allowEdit: false
47290
+ };
47291
+ }
47292
+ /**
47293
+ * Get the specialized prompt for JSON fixing
47294
+ */
47295
+ getJsonFixingPrompt() {
47296
+ 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.
47297
+
47298
+ CORE RESPONSIBILITIES:
47299
+ - Analyze JSON for syntax errors and structural issues
47300
+ - Fix syntax errors while maintaining the original data's semantic meaning
47301
+ - Ensure JSON follows proper RFC 8259 specification
47302
+ - Handle all JSON structures: objects, arrays, primitives, nested structures
47303
+
47304
+ JSON SYNTAX RULES:
47305
+ 1. **Property names**: Must be enclosed in double quotes
47306
+ 2. **String values**: Must use double quotes (not single quotes)
47307
+ 3. **Numbers**: Can be integers or decimals, no quotes needed
47308
+ 4. **Booleans**: true or false (lowercase, no quotes)
47309
+ 5. **Null**: null (lowercase, no quotes)
47310
+ 6. **Arrays**: Comma-separated values in square brackets [...]
47311
+ 7. **Objects**: Comma-separated key-value pairs in curly braces {...}
47312
+ 8. **No trailing commas**: Last item in array/object must not have a trailing comma
47313
+ 9. **Escape sequences**: Special characters must be escaped (\\n, \\t, \\", \\\\, etc.)
47314
+
47315
+ COMMON ERRORS TO FIX:
47316
+ 1. **Unquoted property names**: {name: "value"} \u2192 {"name": "value"}
47317
+ 2. **Single quotes**: {'key': 'value'} \u2192 {"key": "value"}
47318
+ 3. **Trailing commas**: {"a": 1,} \u2192 {"a": 1}
47319
+ 4. **Unquoted strings**: {key: value} \u2192 {"key": "value"}
47320
+ 5. **Missing commas**: {"a": 1 "b": 2} \u2192 {"a": 1, "b": 2}
47321
+ 6. **Extra commas**: {"a": 1,, "b": 2} \u2192 {"a": 1, "b": 2}
47322
+ 7. **Unclosed brackets/braces**: {"key": "value" \u2192 {"key": "value"}
47323
+ 8. **Invalid escape sequences**: Fix or remove
47324
+ 9. **Comments**: Remove // or /* */ comments (not allowed in JSON)
47325
+ 10. **Undefined values**: Replace undefined with null
47326
+
47327
+ FIXING METHODOLOGY:
47328
+ 1. **Identify the error location** from the error message
47329
+ 2. **Analyze the context** around the error
47330
+ 3. **Apply the appropriate fix** based on JSON syntax rules
47331
+ 4. **Preserve data intent** - never change the meaning of the data
47332
+ 5. **Validate the result** - ensure it's parseable JSON
47333
+
47334
+ CRITICAL RULES:
47335
+ - ALWAYS output only the corrected JSON
47336
+ - NEVER add explanations, comments, or additional text
47337
+ - NEVER wrap in markdown code blocks (no \`\`\`json)
47338
+ - PRESERVE the original data structure and values
47339
+ - FIX only syntax errors, don't modify the data itself
47340
+ - ENSURE the output is valid, parseable JSON
47341
+
47342
+ When presented with broken JSON, analyze it thoroughly and provide the corrected version that maintains the original intent while fixing all syntax issues.`;
47343
+ }
47344
+ /**
47345
+ * Initialize the ProbeAgent if not already done
47346
+ */
47347
+ async initializeAgent() {
47348
+ if (!this.ProbeAgent) {
47349
+ const { ProbeAgent: ProbeAgent2 } = await Promise.resolve().then(() => (init_ProbeAgent(), ProbeAgent_exports));
47350
+ this.ProbeAgent = ProbeAgent2;
47351
+ }
47352
+ if (!this.agent) {
47353
+ this.agent = new this.ProbeAgent({
47354
+ sessionId: this.options.sessionId,
47355
+ customPrompt: this.getJsonFixingPrompt(),
47356
+ path: this.options.path,
47357
+ provider: this.options.provider,
47358
+ model: this.options.model,
47359
+ debug: this.options.debug,
47360
+ tracer: this.options.tracer,
47361
+ allowEdit: this.options.allowEdit,
47362
+ maxIterations: 5,
47363
+ // Allow multiple iterations for JSON fixing
47364
+ disableJsonValidation: true
47365
+ // CRITICAL: Disable JSON validation in nested agent to prevent infinite recursion
47366
+ });
47367
+ }
47368
+ return this.agent;
47369
+ }
47370
+ /**
47371
+ * Fix invalid JSON using the specialized agent
47372
+ * @param {string} invalidJson - The broken JSON string
47373
+ * @param {string} schema - The original schema for context
47374
+ * @param {Object} validationResult - Validation result with error details
47375
+ * @param {number} attemptNumber - Current attempt number (for logging)
47376
+ * @returns {Promise<string>} - The corrected JSON
47377
+ */
47378
+ async fixJson(invalidJson, schema, validationResult, attemptNumber = 1) {
47379
+ await this.initializeAgent();
47380
+ let errorContext = validationResult.error;
47381
+ if (validationResult.enhancedError) {
47382
+ errorContext = validationResult.enhancedError;
47383
+ }
47384
+ const prompt = `Fix the following invalid JSON.
47385
+
47386
+ Error: ${errorContext}
47387
+
47388
+ Invalid JSON:
47389
+ ${invalidJson}
47390
+
47391
+ Expected schema structure:
47392
+ ${schema}
47393
+
47394
+ Provide only the corrected JSON without any markdown formatting or explanations.`;
47395
+ try {
47396
+ if (this.options.debug) {
47397
+ console.log(`[DEBUG] JSON fixing: Attempt ${attemptNumber} to fix JSON with separate agent`);
47398
+ }
47399
+ const result = await this.agent.answer(prompt, []);
47400
+ const cleaned = cleanSchemaResponse(result);
47401
+ if (this.options.debug) {
47402
+ console.log(`[DEBUG] JSON fixing: Agent returned ${cleaned.length} chars`);
47403
+ }
47404
+ return cleaned;
47405
+ } catch (error) {
47406
+ if (this.options.debug) {
47407
+ console.error(`[DEBUG] JSON fixing failed: ${error.message}`);
47408
+ }
47409
+ throw new Error(`Failed to fix JSON: ${error.message}`);
47410
+ }
47411
+ }
47412
+ /**
47413
+ * Get token usage information from the specialized agent
47414
+ * @returns {Object} - Token usage statistics
47415
+ */
47416
+ getTokenUsage() {
47417
+ return this.agent ? this.agent.getTokenUsage() : null;
47418
+ }
47419
+ /**
47420
+ * Cancel any ongoing operations
47421
+ */
47422
+ cancel() {
47423
+ if (this.agent) {
47424
+ this.agent.cancel();
47425
+ }
47426
+ }
47427
+ };
47123
47428
  MermaidFixingAgent = class {
47124
47429
  constructor(options = {}) {
47125
47430
  this.ProbeAgent = null;
@@ -48112,6 +48417,7 @@ var init_ProbeAgent = __esm({
48112
48417
  * @param {number} [options.maxResponseTokens] - Maximum tokens for AI responses
48113
48418
  * @param {number} [options.maxIterations] - Maximum tool iterations (overrides MAX_TOOL_ITERATIONS env var)
48114
48419
  * @param {boolean} [options.disableMermaidValidation=false] - Disable automatic mermaid diagram validation and fixing
48420
+ * @param {boolean} [options.disableJsonValidation=false] - Disable automatic JSON validation and fixing (prevents infinite recursion in JsonFixingAgent)
48115
48421
  * @param {boolean} [options.enableMcp=false] - Enable MCP tool integration
48116
48422
  * @param {string} [options.mcpConfigPath] - Path to MCP configuration file
48117
48423
  * @param {Object} [options.mcpConfig] - MCP configuration object (overrides mcpConfigPath)
@@ -48131,6 +48437,7 @@ var init_ProbeAgent = __esm({
48131
48437
  this.maxResponseTokens = options.maxResponseTokens || parseInt(process.env.MAX_RESPONSE_TOKENS || "0", 10) || null;
48132
48438
  this.maxIterations = options.maxIterations || null;
48133
48439
  this.disableMermaidValidation = !!options.disableMermaidValidation;
48440
+ this.disableJsonValidation = !!options.disableJsonValidation;
48134
48441
  this.storageAdapter = options.storageAdapter || new InMemoryStorageAdapter();
48135
48442
  this.hooks = new HookManager();
48136
48443
  if (options.hooks) {
@@ -48273,7 +48580,7 @@ var init_ProbeAgent = __esm({
48273
48580
  this.initializeMockModel();
48274
48581
  return;
48275
48582
  }
48276
- const anthropicApiKey = process.env.ANTHROPIC_API_KEY;
48583
+ const anthropicApiKey = process.env.ANTHROPIC_API_KEY || process.env.ANTHROPIC_AUTH_TOKEN;
48277
48584
  const openaiApiKey = process.env.OPENAI_API_KEY;
48278
48585
  const googleApiKey = process.env.GOOGLE_GENERATIVE_AI_API_KEY || process.env.GOOGLE_API_KEY;
48279
48586
  const awsAccessKeyId = process.env.AWS_ACCESS_KEY_ID;
@@ -48282,7 +48589,7 @@ var init_ProbeAgent = __esm({
48282
48589
  const awsSessionToken = process.env.AWS_SESSION_TOKEN;
48283
48590
  const awsApiKey = process.env.AWS_BEDROCK_API_KEY;
48284
48591
  const llmBaseUrl = process.env.LLM_BASE_URL;
48285
- const anthropicApiUrl = process.env.ANTHROPIC_API_URL || llmBaseUrl;
48592
+ const anthropicApiUrl = process.env.ANTHROPIC_API_URL || process.env.ANTHROPIC_BASE_URL || llmBaseUrl;
48286
48593
  const openaiApiUrl = process.env.OPENAI_API_URL || llmBaseUrl;
48287
48594
  const googleApiUrl = process.env.GOOGLE_API_URL || llmBaseUrl;
48288
48595
  const awsBedrockBaseUrl = process.env.AWS_BEDROCK_BASE_URL || llmBaseUrl;
@@ -48323,7 +48630,7 @@ var init_ProbeAgent = __esm({
48323
48630
  } else if (awsAccessKeyId && awsSecretAccessKey && awsRegion || awsApiKey) {
48324
48631
  this.initializeBedrockModel(awsAccessKeyId, awsSecretAccessKey, awsRegion, awsSessionToken, awsApiKey, awsBedrockBaseUrl, modelName);
48325
48632
  } else {
48326
- throw new Error("No API key provided. Please set ANTHROPIC_API_KEY, OPENAI_API_KEY, GOOGLE_GENERATIVE_AI_API_KEY (or GOOGLE_API_KEY), AWS credentials (AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY, AWS_REGION), or AWS_BEDROCK_API_KEY environment variables.");
48633
+ throw new Error("No API key provided. Please set ANTHROPIC_API_KEY (or ANTHROPIC_AUTH_TOKEN), OPENAI_API_KEY, GOOGLE_GENERATIVE_AI_API_KEY (or GOOGLE_API_KEY), AWS credentials (AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY, AWS_REGION), or AWS_BEDROCK_API_KEY environment variables.");
48327
48634
  }
48328
48635
  }
48329
48636
  /**
@@ -49345,15 +49652,16 @@ Remember: Use proper XML format with BOTH opening and closing tags:
49345
49652
  <parameter>value</parameter>
49346
49653
  </tool_name>
49347
49654
 
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:
49655
+ IMPORTANT: A schema was provided for the final output format. You have two options:
49350
49656
 
49657
+ Option 1 - Use attempt_completion with your complete answer:
49351
49658
  <attempt_completion>
49352
- [Your response content matching the provided schema format]
49659
+ [Your complete answer here - will be automatically formatted to match the schema]
49353
49660
  </attempt_completion>
49354
49661
 
49355
- Your response must conform to this schema:
49356
- ${options.schema}`;
49662
+ Option 2 - Provide a natural response without any tool, and it will be automatically formatted.
49663
+
49664
+ Do NOT try to format your response as JSON yourself - this will be done automatically.`;
49357
49665
  } else {
49358
49666
  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
49667
 
@@ -49500,6 +49808,10 @@ Convert your previous response content into actual JSON data that follows this s
49500
49808
  console.log(`[DEBUG] JSON validation: Starting validation process for schema response`);
49501
49809
  console.log(`[DEBUG] JSON validation: Response length: ${finalResult.length} chars`);
49502
49810
  }
49811
+ finalResult = cleanSchemaResponse(finalResult);
49812
+ if (this.debug) {
49813
+ console.log(`[DEBUG] JSON validation: After cleaning, length: ${finalResult.length} chars`);
49814
+ }
49503
49815
  if (this.tracer) {
49504
49816
  this.tracer.recordJsonValidationEvent("started", {
49505
49817
  "json_validation.response_length": finalResult.length,
@@ -49511,75 +49823,66 @@ Convert your previous response content into actual JSON data that follows this s
49511
49823
  const maxRetries = 3;
49512
49824
  if (validation.isValid && isJsonSchemaDefinition(finalResult, { debug: this.debug })) {
49513
49825
  if (this.debug) {
49514
- console.log(`[DEBUG] JSON validation: Response is a JSON schema definition instead of data, correcting...`);
49826
+ console.log(`[DEBUG] JSON validation: Response is a JSON schema definition instead of data, needs correction...`);
49515
49827
  }
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;
49828
+ validation = {
49829
+ isValid: false,
49830
+ error: "Response is a JSON schema definition instead of actual data",
49831
+ enhancedError: "Response is a JSON schema definition instead of actual data. Please return data that conforms to the schema, not the schema itself."
49832
+ };
49528
49833
  }
49529
- while (!validation.isValid && retryCount < maxRetries) {
49834
+ if (!validation.isValid) {
49530
49835
  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 ? "..." : ""}`);
49836
+ console.log(`[DEBUG] JSON validation: Starting separate JsonFixingAgent session...`);
49533
49837
  }
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,
49838
+ const { JsonFixingAgent: JsonFixingAgent2 } = await Promise.resolve().then(() => (init_schemaUtils(), schemaUtils_exports));
49839
+ const jsonFixer = new JsonFixingAgent2({
49840
+ path: this.allowedFolders[0],
49841
+ provider: this.clientApiProvider,
49842
+ model: this.model,
49843
+ debug: this.debug,
49844
+ tracer: this.tracer
49845
+ });
49846
+ let currentResult = finalResult;
49847
+ let currentValidation = validation;
49848
+ while (!currentValidation.isValid && retryCount < maxRetries) {
49849
+ if (this.debug) {
49850
+ console.log(`[DEBUG] JSON validation: Validation failed (attempt ${retryCount + 1}/${maxRetries}):`, currentValidation.error);
49851
+ console.log(`[DEBUG] JSON validation: Invalid response sample: ${currentResult.substring(0, 300)}${currentResult.length > 300 ? "..." : ""}`);
49852
+ }
49853
+ try {
49854
+ currentResult = await jsonFixer.fixJson(
49855
+ currentResult,
49548
49856
  options.schema,
49549
- validation.error,
49550
- retryCount
49857
+ currentValidation,
49858
+ retryCount + 1
49551
49859
  );
49860
+ currentValidation = validateJsonResponse(currentResult, { debug: this.debug });
49861
+ retryCount++;
49862
+ if (this.debug) {
49863
+ if (!currentValidation.isValid && retryCount < maxRetries) {
49864
+ console.log(`[DEBUG] JSON validation: Still invalid after correction ${retryCount}, retrying...`);
49865
+ console.log(`[DEBUG] JSON validation: Corrected response sample: ${currentResult.substring(0, 300)}${currentResult.length > 300 ? "..." : ""}`);
49866
+ } else if (currentValidation.isValid) {
49867
+ console.log(`[DEBUG] JSON validation: Successfully corrected after ${retryCount} attempts with JsonFixingAgent`);
49868
+ }
49869
+ }
49870
+ } catch (error) {
49871
+ if (this.debug) {
49872
+ console.error(`[DEBUG] JSON validation: JsonFixingAgent error on attempt ${retryCount + 1}:`, error.message);
49873
+ }
49874
+ break;
49552
49875
  }
49553
- } catch (error) {
49554
- correctionPrompt = createJsonCorrectionPrompt(
49555
- finalResult,
49556
- options.schema,
49557
- validation.error,
49558
- retryCount
49559
- );
49560
49876
  }
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
- }
49877
+ finalResult = currentResult;
49878
+ validation = currentValidation;
49879
+ if (!validation.isValid && this.debug) {
49880
+ console.log(`[DEBUG] JSON validation: Still invalid after ${maxRetries} correction attempts with JsonFixingAgent:`, validation.error);
49881
+ console.log(`[DEBUG] JSON validation: Final invalid response: ${finalResult.substring(0, 500)}${finalResult.length > 500 ? "..." : ""}`);
49882
+ } else if (validation.isValid && this.debug) {
49883
+ console.log(`[DEBUG] JSON validation: Final validation successful`);
49575
49884
  }
49576
49885
  }
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
49886
  if (this.tracer) {
49584
49887
  this.tracer.recordJsonValidationEvent("completed", {
49585
49888
  "json_validation.success": validation.isValid,
@@ -49827,6 +50130,7 @@ Convert your previous response content into actual JSON data that follows this s
49827
50130
  maxResponseTokens: this.maxResponseTokens,
49828
50131
  maxIterations: this.maxIterations,
49829
50132
  disableMermaidValidation: this.disableMermaidValidation,
50133
+ disableJsonValidation: this.disableJsonValidation,
49830
50134
  enableMcp: !!this.mcpBridge,
49831
50135
  mcpConfig: this.mcpConfig,
49832
50136
  enableBash: this.enableBash,
@@ -49845,11 +50149,44 @@ Convert your previous response content into actual JSON data that follows this s
49845
50149
  }
49846
50150
  /**
49847
50151
  * 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
50152
+ * Strategy: Find the FIRST schema-related message and truncate everything from that point onwards.
50153
+ * This ensures that all schema formatting iterations (IMPORTANT, CRITICAL, corrections, etc.) are removed.
50154
+ * Keeps: system message, user messages, assistant responses, tool results up to the first schema message
49850
50155
  * @private
49851
50156
  */
49852
50157
  _stripInternalMessages(history, keepSystemMessage = true) {
50158
+ let firstSchemaMessageIndex = -1;
50159
+ for (let i = 0; i < history.length; i++) {
50160
+ const message = history[i];
50161
+ if (message.role === "system") {
50162
+ continue;
50163
+ }
50164
+ if (this._isSchemaMessage(message)) {
50165
+ firstSchemaMessageIndex = i;
50166
+ if (this.debug) {
50167
+ console.log(`[DEBUG] Found first schema message at index ${i}, truncating from here`);
50168
+ }
50169
+ break;
50170
+ }
50171
+ }
50172
+ if (firstSchemaMessageIndex === -1) {
50173
+ return this._stripNonSchemaInternalMessages(history, keepSystemMessage);
50174
+ }
50175
+ const truncated = history.slice(0, firstSchemaMessageIndex);
50176
+ const filtered = this._stripNonSchemaInternalMessages(truncated, keepSystemMessage);
50177
+ if (this.debug) {
50178
+ const removedCount = history.length - filtered.length;
50179
+ console.log(`[DEBUG] Truncated at schema message (index ${firstSchemaMessageIndex}) and filtered non-schema internal messages`);
50180
+ console.log(`[DEBUG] Removed ${removedCount} messages total (${history.length} \u2192 ${filtered.length})`);
50181
+ }
50182
+ return filtered;
50183
+ }
50184
+ /**
50185
+ * Strip non-schema internal messages (mermaid fixes, tool reminders, etc.) individually
50186
+ * Used when no schema messages are present in history
50187
+ * @private
50188
+ */
50189
+ _stripNonSchemaInternalMessages(history, keepSystemMessage = true) {
49853
50190
  const filtered = [];
49854
50191
  for (let i = 0; i < history.length; i++) {
49855
50192
  const message = history[i];
@@ -49861,9 +50198,9 @@ Convert your previous response content into actual JSON data that follows this s
49861
50198
  }
49862
50199
  continue;
49863
50200
  }
49864
- if (this._isInternalMessage(message, i, history)) {
50201
+ if (this._isNonSchemaInternalMessage(message)) {
49865
50202
  if (this.debug) {
49866
- console.log(`[DEBUG] Stripping internal message at index ${i}: ${message.role}`);
50203
+ console.log(`[DEBUG] Stripping non-schema internal message at index ${i}: ${message.role}`);
49867
50204
  }
49868
50205
  continue;
49869
50206
  }
@@ -49872,20 +50209,50 @@ Convert your previous response content into actual JSON data that follows this s
49872
50209
  return filtered;
49873
50210
  }
49874
50211
  /**
49875
- * Determine if a message is an internal/temporary message
50212
+ * Check if a message is schema-related (IMPORTANT, CRITICAL, etc.)
49876
50213
  * @private
49877
50214
  */
49878
- _isInternalMessage(message, index, history) {
50215
+ _isSchemaMessage(message) {
49879
50216
  if (message.role !== "user") {
49880
50217
  return false;
49881
50218
  }
49882
50219
  if (!message.content) {
49883
50220
  return false;
49884
50221
  }
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:")) {
50222
+ let content;
50223
+ try {
50224
+ content = typeof message.content === "string" ? message.content : JSON.stringify(message.content);
50225
+ } catch (error) {
50226
+ if (this.debug) {
50227
+ console.log(`[DEBUG] Could not stringify message content in _isSchemaMessage: ${error.message}`);
50228
+ }
50229
+ return false;
50230
+ }
50231
+ 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
50232
  return true;
49888
50233
  }
50234
+ return false;
50235
+ }
50236
+ /**
50237
+ * Check if a message is a non-schema internal message (mermaid, tool reminders, JSON corrections)
50238
+ * @private
50239
+ */
50240
+ _isNonSchemaInternalMessage(message) {
50241
+ if (message.role !== "user") {
50242
+ return false;
50243
+ }
50244
+ if (!message.content) {
50245
+ return false;
50246
+ }
50247
+ let content;
50248
+ try {
50249
+ content = typeof message.content === "string" ? message.content : JSON.stringify(message.content);
50250
+ } catch (error) {
50251
+ if (this.debug) {
50252
+ console.log(`[DEBUG] Could not stringify message content in _isNonSchemaInternalMessage: ${error.message}`);
50253
+ }
50254
+ return false;
50255
+ }
49889
50256
  if (content.includes("Please use one of the available tools") && content.includes("or use attempt_completion") && content.includes("Remember: Use proper XML format")) {
49890
50257
  return true;
49891
50258
  }