@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.
- package/build/agent/ProbeAgent.d.ts +1 -1
- package/build/agent/ProbeAgent.js +192 -96
- package/build/agent/index.js +447 -80
- package/build/agent/schemaUtils.js +260 -11
- package/cjs/agent/ProbeAgent.cjs +773 -292
- package/cjs/index.cjs +773 -292
- package/package.json +1 -1
- package/src/agent/ProbeAgent.d.ts +1 -1
- package/src/agent/ProbeAgent.js +192 -96
- package/src/agent/schemaUtils.js +260 -11
|
@@ -117,7 +117,7 @@ export interface AnswerOptions {
|
|
|
117
117
|
export interface CloneOptions {
|
|
118
118
|
/** Session ID for the cloned agent (defaults to new UUID) */
|
|
119
119
|
sessionId?: string;
|
|
120
|
-
/** Remove internal messages (schema reminders, mermaid fixes, etc.) */
|
|
120
|
+
/** Remove internal messages (schema reminders, schema formatting prompts, mermaid fixes, etc.) */
|
|
121
121
|
stripInternalMessages?: boolean;
|
|
122
122
|
/** Keep the system message in cloned history */
|
|
123
123
|
keepSystemMessage?: boolean;
|
|
@@ -78,6 +78,7 @@ export class ProbeAgent {
|
|
|
78
78
|
* @param {number} [options.maxResponseTokens] - Maximum tokens for AI responses
|
|
79
79
|
* @param {number} [options.maxIterations] - Maximum tool iterations (overrides MAX_TOOL_ITERATIONS env var)
|
|
80
80
|
* @param {boolean} [options.disableMermaidValidation=false] - Disable automatic mermaid diagram validation and fixing
|
|
81
|
+
* @param {boolean} [options.disableJsonValidation=false] - Disable automatic JSON validation and fixing (prevents infinite recursion in JsonFixingAgent)
|
|
81
82
|
* @param {boolean} [options.enableMcp=false] - Enable MCP tool integration
|
|
82
83
|
* @param {string} [options.mcpConfigPath] - Path to MCP configuration file
|
|
83
84
|
* @param {Object} [options.mcpConfig] - MCP configuration object (overrides mcpConfigPath)
|
|
@@ -98,6 +99,7 @@ export class ProbeAgent {
|
|
|
98
99
|
this.maxResponseTokens = options.maxResponseTokens || parseInt(process.env.MAX_RESPONSE_TOKENS || '0', 10) || null;
|
|
99
100
|
this.maxIterations = options.maxIterations || null;
|
|
100
101
|
this.disableMermaidValidation = !!options.disableMermaidValidation;
|
|
102
|
+
this.disableJsonValidation = !!options.disableJsonValidation;
|
|
101
103
|
|
|
102
104
|
// Storage adapter (defaults to in-memory)
|
|
103
105
|
this.storageAdapter = options.storageAdapter || new InMemoryStorageAdapter();
|
|
@@ -302,7 +304,8 @@ export class ProbeAgent {
|
|
|
302
304
|
}
|
|
303
305
|
|
|
304
306
|
// Get API keys from environment variables
|
|
305
|
-
|
|
307
|
+
// Support both ANTHROPIC_API_KEY and ANTHROPIC_AUTH_TOKEN (used by Z.AI)
|
|
308
|
+
const anthropicApiKey = process.env.ANTHROPIC_API_KEY || process.env.ANTHROPIC_AUTH_TOKEN;
|
|
306
309
|
const openaiApiKey = process.env.OPENAI_API_KEY;
|
|
307
310
|
// Support both GOOGLE_GENERATIVE_AI_API_KEY (official) and GOOGLE_API_KEY (legacy)
|
|
308
311
|
const googleApiKey = process.env.GOOGLE_GENERATIVE_AI_API_KEY || process.env.GOOGLE_API_KEY;
|
|
@@ -314,7 +317,7 @@ export class ProbeAgent {
|
|
|
314
317
|
|
|
315
318
|
// Get custom API URLs if provided
|
|
316
319
|
const llmBaseUrl = process.env.LLM_BASE_URL;
|
|
317
|
-
const anthropicApiUrl = process.env.ANTHROPIC_API_URL || llmBaseUrl;
|
|
320
|
+
const anthropicApiUrl = process.env.ANTHROPIC_API_URL || process.env.ANTHROPIC_BASE_URL || llmBaseUrl;
|
|
318
321
|
const openaiApiUrl = process.env.OPENAI_API_URL || llmBaseUrl;
|
|
319
322
|
const googleApiUrl = process.env.GOOGLE_API_URL || llmBaseUrl;
|
|
320
323
|
const awsBedrockBaseUrl = process.env.AWS_BEDROCK_BASE_URL || llmBaseUrl;
|
|
@@ -364,7 +367,7 @@ export class ProbeAgent {
|
|
|
364
367
|
} else if ((awsAccessKeyId && awsSecretAccessKey && awsRegion) || awsApiKey) {
|
|
365
368
|
this.initializeBedrockModel(awsAccessKeyId, awsSecretAccessKey, awsRegion, awsSessionToken, awsApiKey, awsBedrockBaseUrl, modelName);
|
|
366
369
|
} else {
|
|
367
|
-
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.');
|
|
370
|
+
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.');
|
|
368
371
|
}
|
|
369
372
|
}
|
|
370
373
|
|
|
@@ -1610,7 +1613,8 @@ When troubleshooting:
|
|
|
1610
1613
|
// Build appropriate reminder message based on whether schema is provided
|
|
1611
1614
|
let reminderContent;
|
|
1612
1615
|
if (options.schema) { // Apply for ANY schema, not just JSON schemas
|
|
1613
|
-
// When schema is provided,
|
|
1616
|
+
// When schema is provided, AI should either use tools OR provide natural response
|
|
1617
|
+
// Schema formatting will happen automatically afterward
|
|
1614
1618
|
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.
|
|
1615
1619
|
|
|
1616
1620
|
Remember: Use proper XML format with BOTH opening and closing tags:
|
|
@@ -1619,15 +1623,16 @@ Remember: Use proper XML format with BOTH opening and closing tags:
|
|
|
1619
1623
|
<parameter>value</parameter>
|
|
1620
1624
|
</tool_name>
|
|
1621
1625
|
|
|
1622
|
-
IMPORTANT: A schema was provided
|
|
1623
|
-
Use attempt_completion with your response directly inside the tags:
|
|
1626
|
+
IMPORTANT: A schema was provided for the final output format. You have two options:
|
|
1624
1627
|
|
|
1628
|
+
Option 1 - Use attempt_completion with your complete answer:
|
|
1625
1629
|
<attempt_completion>
|
|
1626
|
-
[Your
|
|
1630
|
+
[Your complete answer here - will be automatically formatted to match the schema]
|
|
1627
1631
|
</attempt_completion>
|
|
1628
1632
|
|
|
1629
|
-
|
|
1630
|
-
|
|
1633
|
+
Option 2 - Provide a natural response without any tool, and it will be automatically formatted.
|
|
1634
|
+
|
|
1635
|
+
Do NOT try to format your response as JSON yourself - this will be done automatically.`;
|
|
1631
1636
|
} else {
|
|
1632
1637
|
// Standard reminder without schema
|
|
1633
1638
|
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.
|
|
@@ -1807,7 +1812,14 @@ Convert your previous response content into actual JSON data that follows this s
|
|
|
1807
1812
|
console.log(`[DEBUG] JSON validation: Starting validation process for schema response`);
|
|
1808
1813
|
console.log(`[DEBUG] JSON validation: Response length: ${finalResult.length} chars`);
|
|
1809
1814
|
}
|
|
1810
|
-
|
|
1815
|
+
|
|
1816
|
+
// Clean the response first to extract JSON from markdown/code blocks
|
|
1817
|
+
finalResult = cleanSchemaResponse(finalResult);
|
|
1818
|
+
|
|
1819
|
+
if (this.debug) {
|
|
1820
|
+
console.log(`[DEBUG] JSON validation: After cleaning, length: ${finalResult.length} chars`);
|
|
1821
|
+
}
|
|
1822
|
+
|
|
1811
1823
|
// Record JSON validation start in telemetry
|
|
1812
1824
|
if (this.tracer) {
|
|
1813
1825
|
this.tracer.recordJsonValidationEvent('started', {
|
|
@@ -1815,96 +1827,90 @@ Convert your previous response content into actual JSON data that follows this s
|
|
|
1815
1827
|
'json_validation.schema_type': 'JSON'
|
|
1816
1828
|
});
|
|
1817
1829
|
}
|
|
1818
|
-
|
|
1830
|
+
|
|
1819
1831
|
let validation = validateJsonResponse(finalResult, { debug: this.debug });
|
|
1820
1832
|
let retryCount = 0;
|
|
1821
1833
|
const maxRetries = 3;
|
|
1822
|
-
|
|
1834
|
+
|
|
1823
1835
|
// First check if the response is valid JSON but is actually a schema definition
|
|
1824
1836
|
if (validation.isValid && isJsonSchemaDefinition(finalResult, { debug: this.debug })) {
|
|
1825
1837
|
if (this.debug) {
|
|
1826
|
-
console.log(`[DEBUG] JSON validation: Response is a JSON schema definition instead of data,
|
|
1838
|
+
console.log(`[DEBUG] JSON validation: Response is a JSON schema definition instead of data, needs correction...`);
|
|
1827
1839
|
}
|
|
1828
|
-
|
|
1829
|
-
|
|
1830
|
-
|
|
1831
|
-
|
|
1832
|
-
|
|
1833
|
-
|
|
1834
|
-
);
|
|
1835
|
-
|
|
1836
|
-
finalResult = await this.answer(schemaDefinitionPrompt, [], {
|
|
1837
|
-
...options,
|
|
1838
|
-
_schemaFormatted: true
|
|
1839
|
-
});
|
|
1840
|
-
finalResult = cleanSchemaResponse(finalResult);
|
|
1841
|
-
validation = validateJsonResponse(finalResult);
|
|
1842
|
-
retryCount = 1; // Start at 1 since we already did one correction
|
|
1840
|
+
// Mark as invalid so it goes through the fixing process
|
|
1841
|
+
validation = {
|
|
1842
|
+
isValid: false,
|
|
1843
|
+
error: 'Response is a JSON schema definition instead of actual data',
|
|
1844
|
+
enhancedError: 'Response is a JSON schema definition instead of actual data. Please return data that conforms to the schema, not the schema itself.'
|
|
1845
|
+
};
|
|
1843
1846
|
}
|
|
1844
|
-
|
|
1845
|
-
|
|
1847
|
+
|
|
1848
|
+
// Use separate JsonFixingAgent for JSON corrections (isolates session like Mermaid fixing)
|
|
1849
|
+
if (!validation.isValid) {
|
|
1846
1850
|
if (this.debug) {
|
|
1847
|
-
console.log(`[DEBUG] JSON validation:
|
|
1848
|
-
console.log(`[DEBUG] JSON validation: Invalid response sample: ${finalResult.substring(0, 300)}${finalResult.length > 300 ? '...' : ''}`);
|
|
1851
|
+
console.log(`[DEBUG] JSON validation: Starting separate JsonFixingAgent session...`);
|
|
1849
1852
|
}
|
|
1850
|
-
|
|
1851
|
-
|
|
1852
|
-
|
|
1853
|
-
|
|
1854
|
-
|
|
1855
|
-
|
|
1856
|
-
|
|
1857
|
-
|
|
1858
|
-
|
|
1859
|
-
|
|
1853
|
+
|
|
1854
|
+
const { JsonFixingAgent } = await import('./schemaUtils.js');
|
|
1855
|
+
const jsonFixer = new JsonFixingAgent({
|
|
1856
|
+
path: this.allowedFolders[0],
|
|
1857
|
+
provider: this.clientApiProvider,
|
|
1858
|
+
model: this.model,
|
|
1859
|
+
debug: this.debug,
|
|
1860
|
+
tracer: this.tracer
|
|
1861
|
+
});
|
|
1862
|
+
|
|
1863
|
+
let currentResult = finalResult;
|
|
1864
|
+
let currentValidation = validation;
|
|
1865
|
+
|
|
1866
|
+
while (!currentValidation.isValid && retryCount < maxRetries) {
|
|
1867
|
+
if (this.debug) {
|
|
1868
|
+
console.log(`[DEBUG] JSON validation: Validation failed (attempt ${retryCount + 1}/${maxRetries}):`, currentValidation.error);
|
|
1869
|
+
console.log(`[DEBUG] JSON validation: Invalid response sample: ${currentResult.substring(0, 300)}${currentResult.length > 300 ? '...' : ''}`);
|
|
1870
|
+
}
|
|
1871
|
+
|
|
1872
|
+
try {
|
|
1873
|
+
// Use specialized JsonFixingAgent to fix the JSON in a separate session
|
|
1874
|
+
currentResult = await jsonFixer.fixJson(
|
|
1875
|
+
currentResult,
|
|
1860
1876
|
options.schema,
|
|
1861
|
-
|
|
1862
|
-
|
|
1863
|
-
} else {
|
|
1864
|
-
correctionPrompt = createJsonCorrectionPrompt(
|
|
1865
|
-
finalResult,
|
|
1866
|
-
options.schema,
|
|
1867
|
-
validation.error,
|
|
1868
|
-
retryCount
|
|
1877
|
+
currentValidation,
|
|
1878
|
+
retryCount + 1
|
|
1869
1879
|
);
|
|
1880
|
+
|
|
1881
|
+
// Validate the corrected response
|
|
1882
|
+
currentValidation = validateJsonResponse(currentResult, { debug: this.debug });
|
|
1883
|
+
retryCount++;
|
|
1884
|
+
|
|
1885
|
+
if (this.debug) {
|
|
1886
|
+
if (!currentValidation.isValid && retryCount < maxRetries) {
|
|
1887
|
+
console.log(`[DEBUG] JSON validation: Still invalid after correction ${retryCount}, retrying...`);
|
|
1888
|
+
console.log(`[DEBUG] JSON validation: Corrected response sample: ${currentResult.substring(0, 300)}${currentResult.length > 300 ? '...' : ''}`);
|
|
1889
|
+
} else if (currentValidation.isValid) {
|
|
1890
|
+
console.log(`[DEBUG] JSON validation: Successfully corrected after ${retryCount} attempts with JsonFixingAgent`);
|
|
1891
|
+
}
|
|
1892
|
+
}
|
|
1893
|
+
} catch (error) {
|
|
1894
|
+
if (this.debug) {
|
|
1895
|
+
console.error(`[DEBUG] JSON validation: JsonFixingAgent error on attempt ${retryCount + 1}:`, error.message);
|
|
1896
|
+
}
|
|
1897
|
+
// If JsonFixingAgent fails, break out of loop
|
|
1898
|
+
break;
|
|
1870
1899
|
}
|
|
1871
|
-
} catch (error) {
|
|
1872
|
-
// If we can't parse to check if it's a schema definition, use regular correction
|
|
1873
|
-
correctionPrompt = createJsonCorrectionPrompt(
|
|
1874
|
-
finalResult,
|
|
1875
|
-
options.schema,
|
|
1876
|
-
validation.error,
|
|
1877
|
-
retryCount
|
|
1878
|
-
);
|
|
1879
1900
|
}
|
|
1880
|
-
|
|
1881
|
-
|
|
1882
|
-
|
|
1883
|
-
|
|
1884
|
-
|
|
1885
|
-
|
|
1886
|
-
|
|
1887
|
-
|
|
1888
|
-
|
|
1889
|
-
|
|
1890
|
-
|
|
1891
|
-
if (this.debug) {
|
|
1892
|
-
if (!validation.isValid && retryCount < maxRetries) {
|
|
1893
|
-
console.log(`[DEBUG] JSON validation: Still invalid after correction ${retryCount}, retrying...`);
|
|
1894
|
-
console.log(`[DEBUG] JSON validation: Corrected response sample: ${finalResult.substring(0, 300)}${finalResult.length > 300 ? '...' : ''}`);
|
|
1895
|
-
} else if (validation.isValid) {
|
|
1896
|
-
console.log(`[DEBUG] JSON validation: Successfully corrected after ${retryCount} attempts`);
|
|
1897
|
-
}
|
|
1901
|
+
|
|
1902
|
+
// Update finalResult with the fixed version
|
|
1903
|
+
finalResult = currentResult;
|
|
1904
|
+
validation = currentValidation;
|
|
1905
|
+
|
|
1906
|
+
if (!validation.isValid && this.debug) {
|
|
1907
|
+
console.log(`[DEBUG] JSON validation: Still invalid after ${maxRetries} correction attempts with JsonFixingAgent:`, validation.error);
|
|
1908
|
+
console.log(`[DEBUG] JSON validation: Final invalid response: ${finalResult.substring(0, 500)}${finalResult.length > 500 ? '...' : ''}`);
|
|
1909
|
+
} else if (validation.isValid && this.debug) {
|
|
1910
|
+
console.log(`[DEBUG] JSON validation: Final validation successful`);
|
|
1898
1911
|
}
|
|
1899
1912
|
}
|
|
1900
1913
|
|
|
1901
|
-
if (!validation.isValid && this.debug) {
|
|
1902
|
-
console.log(`[DEBUG] JSON validation: Still invalid after ${maxRetries} correction attempts:`, validation.error);
|
|
1903
|
-
console.log(`[DEBUG] JSON validation: Final invalid response: ${finalResult.substring(0, 500)}${finalResult.length > 500 ? '...' : ''}`);
|
|
1904
|
-
} else if (validation.isValid && this.debug) {
|
|
1905
|
-
console.log(`[DEBUG] JSON validation: Final validation successful`);
|
|
1906
|
-
}
|
|
1907
|
-
|
|
1908
1914
|
// Record JSON validation completion in telemetry
|
|
1909
1915
|
if (this.tracer) {
|
|
1910
1916
|
this.tracer.recordJsonValidationEvent('completed', {
|
|
@@ -2208,6 +2214,7 @@ Convert your previous response content into actual JSON data that follows this s
|
|
|
2208
2214
|
maxResponseTokens: this.maxResponseTokens,
|
|
2209
2215
|
maxIterations: this.maxIterations,
|
|
2210
2216
|
disableMermaidValidation: this.disableMermaidValidation,
|
|
2217
|
+
disableJsonValidation: this.disableJsonValidation,
|
|
2211
2218
|
enableMcp: !!this.mcpBridge,
|
|
2212
2219
|
mcpConfig: this.mcpConfig,
|
|
2213
2220
|
enableBash: this.enableBash,
|
|
@@ -2231,11 +2238,60 @@ Convert your previous response content into actual JSON data that follows this s
|
|
|
2231
2238
|
|
|
2232
2239
|
/**
|
|
2233
2240
|
* Internal method to strip internal/temporary messages from history
|
|
2234
|
-
*
|
|
2235
|
-
*
|
|
2241
|
+
* Strategy: Find the FIRST schema-related message and truncate everything from that point onwards.
|
|
2242
|
+
* This ensures that all schema formatting iterations (IMPORTANT, CRITICAL, corrections, etc.) are removed.
|
|
2243
|
+
* Keeps: system message, user messages, assistant responses, tool results up to the first schema message
|
|
2236
2244
|
* @private
|
|
2237
2245
|
*/
|
|
2238
2246
|
_stripInternalMessages(history, keepSystemMessage = true) {
|
|
2247
|
+
// Find the first schema-related message index
|
|
2248
|
+
let firstSchemaMessageIndex = -1;
|
|
2249
|
+
|
|
2250
|
+
for (let i = 0; i < history.length; i++) {
|
|
2251
|
+
const message = history[i];
|
|
2252
|
+
|
|
2253
|
+
// Skip system messages
|
|
2254
|
+
if (message.role === 'system') {
|
|
2255
|
+
continue;
|
|
2256
|
+
}
|
|
2257
|
+
|
|
2258
|
+
// Check if this is a schema-related message
|
|
2259
|
+
if (this._isSchemaMessage(message)) {
|
|
2260
|
+
firstSchemaMessageIndex = i;
|
|
2261
|
+
if (this.debug) {
|
|
2262
|
+
console.log(`[DEBUG] Found first schema message at index ${i}, truncating from here`);
|
|
2263
|
+
}
|
|
2264
|
+
break;
|
|
2265
|
+
}
|
|
2266
|
+
}
|
|
2267
|
+
|
|
2268
|
+
// If no schema message found, try to find other internal messages and remove them individually
|
|
2269
|
+
if (firstSchemaMessageIndex === -1) {
|
|
2270
|
+
return this._stripNonSchemaInternalMessages(history, keepSystemMessage);
|
|
2271
|
+
}
|
|
2272
|
+
|
|
2273
|
+
// Truncate at the first schema message, then also filter non-schema internal messages
|
|
2274
|
+
// from the remaining history before the schema
|
|
2275
|
+
const truncated = history.slice(0, firstSchemaMessageIndex);
|
|
2276
|
+
|
|
2277
|
+
// Now filter non-schema internal messages from the truncated history
|
|
2278
|
+
const filtered = this._stripNonSchemaInternalMessages(truncated, keepSystemMessage);
|
|
2279
|
+
|
|
2280
|
+
if (this.debug) {
|
|
2281
|
+
const removedCount = history.length - filtered.length;
|
|
2282
|
+
console.log(`[DEBUG] Truncated at schema message (index ${firstSchemaMessageIndex}) and filtered non-schema internal messages`);
|
|
2283
|
+
console.log(`[DEBUG] Removed ${removedCount} messages total (${history.length} → ${filtered.length})`);
|
|
2284
|
+
}
|
|
2285
|
+
|
|
2286
|
+
return filtered;
|
|
2287
|
+
}
|
|
2288
|
+
|
|
2289
|
+
/**
|
|
2290
|
+
* Strip non-schema internal messages (mermaid fixes, tool reminders, etc.) individually
|
|
2291
|
+
* Used when no schema messages are present in history
|
|
2292
|
+
* @private
|
|
2293
|
+
*/
|
|
2294
|
+
_stripNonSchemaInternalMessages(history, keepSystemMessage = true) {
|
|
2239
2295
|
const filtered = [];
|
|
2240
2296
|
|
|
2241
2297
|
for (let i = 0; i < history.length; i++) {
|
|
@@ -2251,10 +2307,10 @@ Convert your previous response content into actual JSON data that follows this s
|
|
|
2251
2307
|
continue;
|
|
2252
2308
|
}
|
|
2253
2309
|
|
|
2254
|
-
// Check if this is
|
|
2255
|
-
if (this.
|
|
2310
|
+
// Check if this is a non-schema internal message (mermaid, tool reminders)
|
|
2311
|
+
if (this._isNonSchemaInternalMessage(message)) {
|
|
2256
2312
|
if (this.debug) {
|
|
2257
|
-
console.log(`[DEBUG] Stripping internal message at index ${i}: ${message.role}`);
|
|
2313
|
+
console.log(`[DEBUG] Stripping non-schema internal message at index ${i}: ${message.role}`);
|
|
2258
2314
|
}
|
|
2259
2315
|
continue;
|
|
2260
2316
|
}
|
|
@@ -2267,30 +2323,69 @@ Convert your previous response content into actual JSON data that follows this s
|
|
|
2267
2323
|
}
|
|
2268
2324
|
|
|
2269
2325
|
/**
|
|
2270
|
-
*
|
|
2326
|
+
* Check if a message is schema-related (IMPORTANT, CRITICAL, etc.)
|
|
2271
2327
|
* @private
|
|
2272
2328
|
*/
|
|
2273
|
-
|
|
2329
|
+
_isSchemaMessage(message) {
|
|
2274
2330
|
if (message.role !== 'user') {
|
|
2275
|
-
return false;
|
|
2331
|
+
return false;
|
|
2276
2332
|
}
|
|
2277
2333
|
|
|
2278
|
-
// Handle null/undefined content
|
|
2279
2334
|
if (!message.content) {
|
|
2280
2335
|
return false;
|
|
2281
2336
|
}
|
|
2282
2337
|
|
|
2283
|
-
|
|
2284
|
-
|
|
2285
|
-
|
|
2338
|
+
let content;
|
|
2339
|
+
try {
|
|
2340
|
+
content = typeof message.content === 'string'
|
|
2341
|
+
? message.content
|
|
2342
|
+
: JSON.stringify(message.content);
|
|
2343
|
+
} catch (error) {
|
|
2344
|
+
// If content cannot be stringified (e.g., circular reference), skip this message
|
|
2345
|
+
if (this.debug) {
|
|
2346
|
+
console.log(`[DEBUG] Could not stringify message content in _isSchemaMessage: ${error.message}`);
|
|
2347
|
+
}
|
|
2348
|
+
return false;
|
|
2349
|
+
}
|
|
2286
2350
|
|
|
2287
2351
|
// Schema reminder messages
|
|
2288
2352
|
if (content.includes('IMPORTANT: A schema was provided') ||
|
|
2289
2353
|
content.includes('You MUST respond with data that matches this schema') ||
|
|
2290
|
-
content.includes('Your response must conform to this schema:')
|
|
2354
|
+
content.includes('Your response must conform to this schema:') ||
|
|
2355
|
+
content.includes('CRITICAL: You MUST respond with ONLY valid JSON DATA') ||
|
|
2356
|
+
content.includes('Schema to follow (this is just the structure')) {
|
|
2291
2357
|
return true;
|
|
2292
2358
|
}
|
|
2293
2359
|
|
|
2360
|
+
return false;
|
|
2361
|
+
}
|
|
2362
|
+
|
|
2363
|
+
/**
|
|
2364
|
+
* Check if a message is a non-schema internal message (mermaid, tool reminders, JSON corrections)
|
|
2365
|
+
* @private
|
|
2366
|
+
*/
|
|
2367
|
+
_isNonSchemaInternalMessage(message) {
|
|
2368
|
+
if (message.role !== 'user') {
|
|
2369
|
+
return false;
|
|
2370
|
+
}
|
|
2371
|
+
|
|
2372
|
+
if (!message.content) {
|
|
2373
|
+
return false;
|
|
2374
|
+
}
|
|
2375
|
+
|
|
2376
|
+
let content;
|
|
2377
|
+
try {
|
|
2378
|
+
content = typeof message.content === 'string'
|
|
2379
|
+
? message.content
|
|
2380
|
+
: JSON.stringify(message.content);
|
|
2381
|
+
} catch (error) {
|
|
2382
|
+
// If content cannot be stringified (e.g., circular reference), skip this message
|
|
2383
|
+
if (this.debug) {
|
|
2384
|
+
console.log(`[DEBUG] Could not stringify message content in _isNonSchemaInternalMessage: ${error.message}`);
|
|
2385
|
+
}
|
|
2386
|
+
return false;
|
|
2387
|
+
}
|
|
2388
|
+
|
|
2294
2389
|
// Tool use reminder messages
|
|
2295
2390
|
if (content.includes('Please use one of the available tools') &&
|
|
2296
2391
|
content.includes('or use attempt_completion') &&
|
|
@@ -2321,6 +2416,7 @@ Convert your previous response content into actual JSON data that follows this s
|
|
|
2321
2416
|
return false;
|
|
2322
2417
|
}
|
|
2323
2418
|
|
|
2419
|
+
|
|
2324
2420
|
/**
|
|
2325
2421
|
* Clean up resources (including MCP connections)
|
|
2326
2422
|
*/
|