@probelabs/probe 0.6.0-rc131 → 0.6.0-rc133
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/build/agent/ProbeAgent.d.ts +1 -1
- package/build/agent/ProbeAgent.js +188 -93
- package/build/agent/index.js +454 -90
- package/build/agent/schemaUtils.js +282 -33
- package/cjs/agent/ProbeAgent.cjs +780 -302
- package/cjs/index.cjs +780 -302
- package/package.json +1 -1
- package/src/agent/ProbeAgent.d.ts +1 -1
- package/src/agent/ProbeAgent.js +188 -93
- package/src/agent/schemaUtils.js +282 -33
|
@@ -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();
|
|
@@ -1611,7 +1613,8 @@ When troubleshooting:
|
|
|
1611
1613
|
// Build appropriate reminder message based on whether schema is provided
|
|
1612
1614
|
let reminderContent;
|
|
1613
1615
|
if (options.schema) { // Apply for ANY schema, not just JSON schemas
|
|
1614
|
-
// 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
|
|
1615
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.
|
|
1616
1619
|
|
|
1617
1620
|
Remember: Use proper XML format with BOTH opening and closing tags:
|
|
@@ -1620,15 +1623,16 @@ Remember: Use proper XML format with BOTH opening and closing tags:
|
|
|
1620
1623
|
<parameter>value</parameter>
|
|
1621
1624
|
</tool_name>
|
|
1622
1625
|
|
|
1623
|
-
IMPORTANT: A schema was provided
|
|
1624
|
-
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:
|
|
1625
1627
|
|
|
1628
|
+
Option 1 - Use attempt_completion with your complete answer:
|
|
1626
1629
|
<attempt_completion>
|
|
1627
|
-
[Your
|
|
1630
|
+
[Your complete answer here - will be automatically formatted to match the schema]
|
|
1628
1631
|
</attempt_completion>
|
|
1629
1632
|
|
|
1630
|
-
|
|
1631
|
-
|
|
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.`;
|
|
1632
1636
|
} else {
|
|
1633
1637
|
// Standard reminder without schema
|
|
1634
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.
|
|
@@ -1808,7 +1812,14 @@ Convert your previous response content into actual JSON data that follows this s
|
|
|
1808
1812
|
console.log(`[DEBUG] JSON validation: Starting validation process for schema response`);
|
|
1809
1813
|
console.log(`[DEBUG] JSON validation: Response length: ${finalResult.length} chars`);
|
|
1810
1814
|
}
|
|
1811
|
-
|
|
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
|
+
|
|
1812
1823
|
// Record JSON validation start in telemetry
|
|
1813
1824
|
if (this.tracer) {
|
|
1814
1825
|
this.tracer.recordJsonValidationEvent('started', {
|
|
@@ -1816,96 +1827,90 @@ Convert your previous response content into actual JSON data that follows this s
|
|
|
1816
1827
|
'json_validation.schema_type': 'JSON'
|
|
1817
1828
|
});
|
|
1818
1829
|
}
|
|
1819
|
-
|
|
1830
|
+
|
|
1820
1831
|
let validation = validateJsonResponse(finalResult, { debug: this.debug });
|
|
1821
1832
|
let retryCount = 0;
|
|
1822
1833
|
const maxRetries = 3;
|
|
1823
|
-
|
|
1834
|
+
|
|
1824
1835
|
// First check if the response is valid JSON but is actually a schema definition
|
|
1825
1836
|
if (validation.isValid && isJsonSchemaDefinition(finalResult, { debug: this.debug })) {
|
|
1826
1837
|
if (this.debug) {
|
|
1827
|
-
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...`);
|
|
1828
1839
|
}
|
|
1829
|
-
|
|
1830
|
-
|
|
1831
|
-
|
|
1832
|
-
|
|
1833
|
-
|
|
1834
|
-
|
|
1835
|
-
);
|
|
1836
|
-
|
|
1837
|
-
finalResult = await this.answer(schemaDefinitionPrompt, [], {
|
|
1838
|
-
...options,
|
|
1839
|
-
_schemaFormatted: true
|
|
1840
|
-
});
|
|
1841
|
-
finalResult = cleanSchemaResponse(finalResult);
|
|
1842
|
-
validation = validateJsonResponse(finalResult);
|
|
1843
|
-
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
|
+
};
|
|
1844
1846
|
}
|
|
1845
|
-
|
|
1846
|
-
|
|
1847
|
+
|
|
1848
|
+
// Use separate JsonFixingAgent for JSON corrections (isolates session like Mermaid fixing)
|
|
1849
|
+
if (!validation.isValid) {
|
|
1847
1850
|
if (this.debug) {
|
|
1848
|
-
console.log(`[DEBUG] JSON validation:
|
|
1849
|
-
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...`);
|
|
1850
1852
|
}
|
|
1851
|
-
|
|
1852
|
-
|
|
1853
|
-
|
|
1854
|
-
|
|
1855
|
-
|
|
1856
|
-
|
|
1857
|
-
|
|
1858
|
-
|
|
1859
|
-
|
|
1860
|
-
|
|
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,
|
|
1861
1876
|
options.schema,
|
|
1862
|
-
|
|
1863
|
-
|
|
1864
|
-
} else {
|
|
1865
|
-
correctionPrompt = createJsonCorrectionPrompt(
|
|
1866
|
-
finalResult,
|
|
1867
|
-
options.schema,
|
|
1868
|
-
validation.error,
|
|
1869
|
-
retryCount
|
|
1877
|
+
currentValidation,
|
|
1878
|
+
retryCount + 1
|
|
1870
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;
|
|
1871
1899
|
}
|
|
1872
|
-
} catch (error) {
|
|
1873
|
-
// If we can't parse to check if it's a schema definition, use regular correction
|
|
1874
|
-
correctionPrompt = createJsonCorrectionPrompt(
|
|
1875
|
-
finalResult,
|
|
1876
|
-
options.schema,
|
|
1877
|
-
validation.error,
|
|
1878
|
-
retryCount
|
|
1879
|
-
);
|
|
1880
1900
|
}
|
|
1881
|
-
|
|
1882
|
-
|
|
1883
|
-
|
|
1884
|
-
|
|
1885
|
-
|
|
1886
|
-
|
|
1887
|
-
|
|
1888
|
-
|
|
1889
|
-
|
|
1890
|
-
|
|
1891
|
-
|
|
1892
|
-
if (this.debug) {
|
|
1893
|
-
if (!validation.isValid && retryCount < maxRetries) {
|
|
1894
|
-
console.log(`[DEBUG] JSON validation: Still invalid after correction ${retryCount}, retrying...`);
|
|
1895
|
-
console.log(`[DEBUG] JSON validation: Corrected response sample: ${finalResult.substring(0, 300)}${finalResult.length > 300 ? '...' : ''}`);
|
|
1896
|
-
} else if (validation.isValid) {
|
|
1897
|
-
console.log(`[DEBUG] JSON validation: Successfully corrected after ${retryCount} attempts`);
|
|
1898
|
-
}
|
|
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`);
|
|
1899
1911
|
}
|
|
1900
1912
|
}
|
|
1901
1913
|
|
|
1902
|
-
if (!validation.isValid && this.debug) {
|
|
1903
|
-
console.log(`[DEBUG] JSON validation: Still invalid after ${maxRetries} correction attempts:`, validation.error);
|
|
1904
|
-
console.log(`[DEBUG] JSON validation: Final invalid response: ${finalResult.substring(0, 500)}${finalResult.length > 500 ? '...' : ''}`);
|
|
1905
|
-
} else if (validation.isValid && this.debug) {
|
|
1906
|
-
console.log(`[DEBUG] JSON validation: Final validation successful`);
|
|
1907
|
-
}
|
|
1908
|
-
|
|
1909
1914
|
// Record JSON validation completion in telemetry
|
|
1910
1915
|
if (this.tracer) {
|
|
1911
1916
|
this.tracer.recordJsonValidationEvent('completed', {
|
|
@@ -2209,6 +2214,7 @@ Convert your previous response content into actual JSON data that follows this s
|
|
|
2209
2214
|
maxResponseTokens: this.maxResponseTokens,
|
|
2210
2215
|
maxIterations: this.maxIterations,
|
|
2211
2216
|
disableMermaidValidation: this.disableMermaidValidation,
|
|
2217
|
+
disableJsonValidation: this.disableJsonValidation,
|
|
2212
2218
|
enableMcp: !!this.mcpBridge,
|
|
2213
2219
|
mcpConfig: this.mcpConfig,
|
|
2214
2220
|
enableBash: this.enableBash,
|
|
@@ -2232,11 +2238,60 @@ Convert your previous response content into actual JSON data that follows this s
|
|
|
2232
2238
|
|
|
2233
2239
|
/**
|
|
2234
2240
|
* Internal method to strip internal/temporary messages from history
|
|
2235
|
-
*
|
|
2236
|
-
*
|
|
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
|
|
2237
2244
|
* @private
|
|
2238
2245
|
*/
|
|
2239
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) {
|
|
2240
2295
|
const filtered = [];
|
|
2241
2296
|
|
|
2242
2297
|
for (let i = 0; i < history.length; i++) {
|
|
@@ -2252,10 +2307,10 @@ Convert your previous response content into actual JSON data that follows this s
|
|
|
2252
2307
|
continue;
|
|
2253
2308
|
}
|
|
2254
2309
|
|
|
2255
|
-
// Check if this is
|
|
2256
|
-
if (this.
|
|
2310
|
+
// Check if this is a non-schema internal message (mermaid, tool reminders)
|
|
2311
|
+
if (this._isNonSchemaInternalMessage(message)) {
|
|
2257
2312
|
if (this.debug) {
|
|
2258
|
-
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}`);
|
|
2259
2314
|
}
|
|
2260
2315
|
continue;
|
|
2261
2316
|
}
|
|
@@ -2268,30 +2323,69 @@ Convert your previous response content into actual JSON data that follows this s
|
|
|
2268
2323
|
}
|
|
2269
2324
|
|
|
2270
2325
|
/**
|
|
2271
|
-
*
|
|
2326
|
+
* Check if a message is schema-related (IMPORTANT, CRITICAL, etc.)
|
|
2272
2327
|
* @private
|
|
2273
2328
|
*/
|
|
2274
|
-
|
|
2329
|
+
_isSchemaMessage(message) {
|
|
2275
2330
|
if (message.role !== 'user') {
|
|
2276
|
-
return false;
|
|
2331
|
+
return false;
|
|
2277
2332
|
}
|
|
2278
2333
|
|
|
2279
|
-
// Handle null/undefined content
|
|
2280
2334
|
if (!message.content) {
|
|
2281
2335
|
return false;
|
|
2282
2336
|
}
|
|
2283
2337
|
|
|
2284
|
-
|
|
2285
|
-
|
|
2286
|
-
|
|
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
|
+
}
|
|
2287
2350
|
|
|
2288
2351
|
// Schema reminder messages
|
|
2289
2352
|
if (content.includes('IMPORTANT: A schema was provided') ||
|
|
2290
2353
|
content.includes('You MUST respond with data that matches this schema') ||
|
|
2291
|
-
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')) {
|
|
2292
2357
|
return true;
|
|
2293
2358
|
}
|
|
2294
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
|
+
|
|
2295
2389
|
// Tool use reminder messages
|
|
2296
2390
|
if (content.includes('Please use one of the available tools') &&
|
|
2297
2391
|
content.includes('or use attempt_completion') &&
|
|
@@ -2322,6 +2416,7 @@ Convert your previous response content into actual JSON data that follows this s
|
|
|
2322
2416
|
return false;
|
|
2323
2417
|
}
|
|
2324
2418
|
|
|
2419
|
+
|
|
2325
2420
|
/**
|
|
2326
2421
|
* Clean up resources (including MCP connections)
|
|
2327
2422
|
*/
|