@probelabs/probe 0.6.0-rc284 → 0.6.0-rc285
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/bin/binaries/{probe-v0.6.0-rc284-aarch64-apple-darwin.tar.gz → probe-v0.6.0-rc285-aarch64-apple-darwin.tar.gz} +0 -0
- package/bin/binaries/probe-v0.6.0-rc285-aarch64-unknown-linux-musl.tar.gz +0 -0
- package/bin/binaries/probe-v0.6.0-rc285-x86_64-apple-darwin.tar.gz +0 -0
- package/bin/binaries/probe-v0.6.0-rc285-x86_64-pc-windows-msvc.zip +0 -0
- package/bin/binaries/probe-v0.6.0-rc285-x86_64-unknown-linux-musl.tar.gz +0 -0
- package/build/agent/ProbeAgent.d.ts +1 -1
- package/build/agent/ProbeAgent.js +333 -486
- package/build/agent/contextCompactor.js +17 -10
- package/build/agent/index.js +301 -702
- package/build/agent/schemaUtils.js +10 -11
- package/build/agent/shared/prompts.js +2 -2
- package/build/agent/tasks/taskTool.js +3 -3
- package/build/agent/tools.js +0 -2
- package/build/index.js +0 -2
- package/build/tools/analyzeAll.js +4 -4
- package/build/tools/common.js +55 -55
- package/build/tools/index.js +0 -1
- package/build/tools/vercel.js +3 -3
- package/cjs/agent/ProbeAgent.cjs +292 -758
- package/cjs/index.cjs +293 -814
- package/package.json +1 -1
- package/src/agent/ProbeAgent.d.ts +1 -1
- package/src/agent/ProbeAgent.js +333 -486
- package/src/agent/contextCompactor.js +17 -10
- package/src/agent/index.js +8 -2
- package/src/agent/schemaUtils.js +10 -11
- package/src/agent/shared/prompts.js +2 -2
- package/src/agent/tasks/taskTool.js +3 -3
- package/src/agent/tools.js +0 -2
- package/src/index.js +0 -2
- package/src/tools/analyzeAll.js +4 -4
- package/src/tools/common.js +55 -55
- package/src/tools/index.js +0 -1
- package/src/tools/vercel.js +3 -3
- package/bin/binaries/probe-v0.6.0-rc284-aarch64-unknown-linux-musl.tar.gz +0 -0
- package/bin/binaries/probe-v0.6.0-rc284-x86_64-apple-darwin.tar.gz +0 -0
- package/bin/binaries/probe-v0.6.0-rc284-x86_64-pc-windows-msvc.zip +0 -0
- package/bin/binaries/probe-v0.6.0-rc284-x86_64-unknown-linux-musl.tar.gz +0 -0
package/cjs/agent/ProbeAgent.cjs
CHANGED
|
@@ -26629,7 +26629,7 @@ Instructions:
|
|
|
26629
26629
|
- Format as a structured list if multiple items found
|
|
26630
26630
|
- If nothing relevant is found in this chunk, respond with "No relevant items found in this chunk."
|
|
26631
26631
|
- Do NOT summarize the code - extract the specific information requested
|
|
26632
|
-
- When done,
|
|
26632
|
+
- When done, provide your final answer directly.`;
|
|
26633
26633
|
try {
|
|
26634
26634
|
const result = await delegate({
|
|
26635
26635
|
task,
|
|
@@ -26691,7 +26691,7 @@ async function aggregateResults(chunkResults2, aggregation, extractionPrompt, op
|
|
|
26691
26691
|
${stripResultTags(r.result)}`).join("\n\n");
|
|
26692
26692
|
const completionNote = `
|
|
26693
26693
|
|
|
26694
|
-
When done,
|
|
26694
|
+
When done, provide your final answer directly.`;
|
|
26695
26695
|
const aggregationPrompts = {
|
|
26696
26696
|
summarize: `Synthesize these analyses into a comprehensive summary. Combine related findings, remove redundancy, and present a coherent overview.
|
|
26697
26697
|
|
|
@@ -26785,7 +26785,7 @@ For example, if looking for customer data:
|
|
|
26785
26785
|
STEP 3: CREATE THE FINAL PLAN
|
|
26786
26786
|
Based on your experiments, output the BEST search strategy.
|
|
26787
26787
|
|
|
26788
|
-
|
|
26788
|
+
Provide your answer in this EXACT format:
|
|
26789
26789
|
|
|
26790
26790
|
SEARCH_QUERY: <the query that WORKED in your experiments - use OR for multiple terms>
|
|
26791
26791
|
AGGREGATION: <summarize | list_unique | count | group_by>
|
|
@@ -26851,7 +26851,7 @@ Your answer should:
|
|
|
26851
26851
|
|
|
26852
26852
|
Format your response as a well-structured document that fully answers: "${question}"
|
|
26853
26853
|
|
|
26854
|
-
When done,
|
|
26854
|
+
When done, provide your final answer directly.`;
|
|
26855
26855
|
try {
|
|
26856
26856
|
const result = await delegate({
|
|
26857
26857
|
task: synthesisTask,
|
|
@@ -27030,6 +27030,34 @@ function createMessagePreview(message, charsPerSide = 200) {
|
|
|
27030
27030
|
const end = message.substring(message.length - charsPerSide);
|
|
27031
27031
|
return `${start}...${end}`;
|
|
27032
27032
|
}
|
|
27033
|
+
function detectStuckResponse(response) {
|
|
27034
|
+
if (!response || typeof response !== "string") {
|
|
27035
|
+
return false;
|
|
27036
|
+
}
|
|
27037
|
+
const stuckPatterns = [
|
|
27038
|
+
/\bi\s+cannot\s+proceed\b/i,
|
|
27039
|
+
/\bi\s+can['']t\s+(?:proceed|continue|move\s+forward)\b/i,
|
|
27040
|
+
/\bunable\s+to\s+(?:proceed|continue|complete)\b/i,
|
|
27041
|
+
/\bblocked\b.*\b(?:proceed|continue)\b/i,
|
|
27042
|
+
/\bneed\s+(?:the|an?)\s+\w+(?:\s+\w+)?\s+to\s+(?:proceed|continue)\b/i,
|
|
27043
|
+
/\brequire[sd]?\s+(?:the|an?)\s+\w+\b.*\bto\s+(?:proceed|continue)\b/i,
|
|
27044
|
+
/\bmissing\s+(?:required|necessary|essential)\b/i,
|
|
27045
|
+
/\bdeadlock\b/i,
|
|
27046
|
+
/\bwe\s+are\s+in\s+a\s+loop\b/i,
|
|
27047
|
+
/\bstuck\s+in\s+a\s+loop\b/i,
|
|
27048
|
+
/\bi\s+(?:have|['']ve)\s+(?:explained|stated|mentioned)\s+(?:this|the\s+situation|it)\s+(?:multiple|several)\s+times\b/i,
|
|
27049
|
+
/\bi\s+(?:cannot|can['']t|could\s+not|couldn['']t)\s+(?:find|locate|get|retrieve|obtain)\s+(?:the|this|that|an?)\b/i,
|
|
27050
|
+
/\bno\s+way\s+to\s+(?:find|get|obtain|retrieve)\b/i,
|
|
27051
|
+
/\bi\s+(?:have|['']ve)\s+exhausted\s+(?:all|my)\s+(?:available\s+)?(?:options|methods|approaches)\b/i,
|
|
27052
|
+
/\bneither\s+of\s+these\s+methods\b/i
|
|
27053
|
+
];
|
|
27054
|
+
for (const pattern of stuckPatterns) {
|
|
27055
|
+
if (pattern.test(response)) {
|
|
27056
|
+
return true;
|
|
27057
|
+
}
|
|
27058
|
+
}
|
|
27059
|
+
return false;
|
|
27060
|
+
}
|
|
27033
27061
|
function parseTargets(targets) {
|
|
27034
27062
|
if (!targets || typeof targets !== "string") {
|
|
27035
27063
|
return [];
|
|
@@ -27540,7 +27568,7 @@ var init_vercel = __esm({
|
|
|
27540
27568
|
if (debug) {
|
|
27541
27569
|
console.error(`[DEDUP] Blocked duplicate search: "${searchQuery}" (path: "${searchPath}")`);
|
|
27542
27570
|
}
|
|
27543
|
-
return "DUPLICATE SEARCH BLOCKED: You already searched for this exact query. Changing the path does NOT give different results \u2014 probe searches recursively. Do NOT repeat the same search. Try a genuinely different keyword, use extract to examine results you already found, or
|
|
27571
|
+
return "DUPLICATE SEARCH BLOCKED: You already searched for this exact query. Changing the path does NOT give different results \u2014 probe searches recursively. Do NOT repeat the same search. Try a genuinely different keyword, use extract to examine results you already found, or provide your final answer if you have enough information.";
|
|
27544
27572
|
}
|
|
27545
27573
|
previousSearches.add(searchKey);
|
|
27546
27574
|
paginationCounts.set(searchKey, 0);
|
|
@@ -27551,7 +27579,7 @@ var init_vercel = __esm({
|
|
|
27551
27579
|
if (debug) {
|
|
27552
27580
|
console.error(`[DEDUP] Blocked excessive pagination (page ${pageCount}/${MAX_PAGES_PER_QUERY}): "${searchQuery}" in "${searchPath}"`);
|
|
27553
27581
|
}
|
|
27554
|
-
return `PAGINATION LIMIT REACHED: You have already retrieved ${MAX_PAGES_PER_QUERY} pages of results for this query. You have enough results \u2014 use extract to examine specific files, or
|
|
27582
|
+
return `PAGINATION LIMIT REACHED: You have already retrieved ${MAX_PAGES_PER_QUERY} pages of results for this query. You have enough results \u2014 use extract to examine specific files, or provide your final answer with your findings.`;
|
|
27555
27583
|
}
|
|
27556
27584
|
}
|
|
27557
27585
|
try {
|
|
@@ -27590,7 +27618,7 @@ var init_vercel = __esm({
|
|
|
27590
27618
|
bashConfig: null,
|
|
27591
27619
|
architectureFileName: options.architectureFileName || null,
|
|
27592
27620
|
promptType: "code-searcher",
|
|
27593
|
-
allowedTools: ["search", "extract", "listFiles"
|
|
27621
|
+
allowedTools: ["search", "extract", "listFiles"],
|
|
27594
27622
|
searchDelegate: false,
|
|
27595
27623
|
schema: CODE_SEARCH_SCHEMA,
|
|
27596
27624
|
parentAbortSignal: options.parentAbortSignal || null
|
|
@@ -49650,7 +49678,7 @@ For each pending/in_progress task, either:
|
|
|
49650
49678
|
- Complete it: call task tool with action="complete", id="task-X"
|
|
49651
49679
|
- Cancel it: call task tool with action="update", id="task-X", status="cancelled"
|
|
49652
49680
|
|
|
49653
|
-
After all tasks are resolved,
|
|
49681
|
+
After all tasks are resolved, provide your final answer.`;
|
|
49654
49682
|
}
|
|
49655
49683
|
function createTaskTool(options = {}) {
|
|
49656
49684
|
const { taskManager, tracer, debug = false } = options;
|
|
@@ -49900,13 +49928,13 @@ Tasks = logical units of work, not files or steps.
|
|
|
49900
49928
|
|
|
49901
49929
|
1. **Plan**: Call task tool with action="create" and a tasks array up front
|
|
49902
49930
|
2. **Execute**: Update status to "in_progress" / "completed" as you work. Add, split, or cancel tasks as you learn more.
|
|
49903
|
-
3. **Finish**: All tasks must be "completed" or "cancelled" before
|
|
49931
|
+
3. **Finish**: All tasks must be "completed" or "cancelled" before providing your final answer.
|
|
49904
49932
|
|
|
49905
49933
|
## Rules
|
|
49906
49934
|
|
|
49907
49935
|
- Dependencies are enforced: a task cannot start until its dependencies are completed
|
|
49908
49936
|
- Circular dependencies are rejected
|
|
49909
|
-
-
|
|
49937
|
+
- Completion is blocked while tasks remain unresolved
|
|
49910
49938
|
`;
|
|
49911
49939
|
}
|
|
49912
49940
|
});
|
|
@@ -86773,68 +86801,9 @@ var require_ajv = __commonJS({
|
|
|
86773
86801
|
});
|
|
86774
86802
|
|
|
86775
86803
|
// src/agent/schemaUtils.js
|
|
86776
|
-
var schemaUtils_exports = {};
|
|
86777
|
-
__export(schemaUtils_exports, {
|
|
86778
|
-
JsonFixingAgent: () => JsonFixingAgent,
|
|
86779
|
-
MermaidFixingAgent: () => MermaidFixingAgent,
|
|
86780
|
-
cleanSchemaResponse: () => cleanSchemaResponse,
|
|
86781
|
-
createJsonCorrectionPrompt: () => createJsonCorrectionPrompt,
|
|
86782
|
-
createMermaidCorrectionPrompt: () => createMermaidCorrectionPrompt,
|
|
86783
|
-
createSchemaDefinitionCorrectionPrompt: () => createSchemaDefinitionCorrectionPrompt,
|
|
86784
|
-
decodeHtmlEntities: () => decodeHtmlEntities2,
|
|
86785
|
-
extractMermaidFromJson: () => extractMermaidFromJson,
|
|
86786
|
-
extractMermaidFromMarkdown: () => extractMermaidFromMarkdown,
|
|
86787
|
-
generateExampleFromSchema: () => generateExampleFromSchema,
|
|
86788
|
-
generateSchemaInstructions: () => generateSchemaInstructions,
|
|
86789
|
-
isJsonSchema: () => isJsonSchema,
|
|
86790
|
-
isJsonSchemaDefinition: () => isJsonSchemaDefinition,
|
|
86791
|
-
isMermaidSchema: () => isMermaidSchema,
|
|
86792
|
-
isSimpleTextWrapperSchema: () => isSimpleTextWrapperSchema,
|
|
86793
|
-
processSchemaResponse: () => processSchemaResponse,
|
|
86794
|
-
replaceMermaidDiagramsInJson: () => replaceMermaidDiagramsInJson,
|
|
86795
|
-
replaceMermaidDiagramsInMarkdown: () => replaceMermaidDiagramsInMarkdown,
|
|
86796
|
-
sanitizeMarkdownEscapesInJson: () => sanitizeMarkdownEscapesInJson,
|
|
86797
|
-
tryAutoWrapForSimpleSchema: () => tryAutoWrapForSimpleSchema,
|
|
86798
|
-
tryExtractValidJsonPrefix: () => tryExtractValidJsonPrefix,
|
|
86799
|
-
tryMaidAutoFix: () => tryMaidAutoFix,
|
|
86800
|
-
validateAndFixMermaidResponse: () => validateAndFixMermaidResponse,
|
|
86801
|
-
validateJsonResponse: () => validateJsonResponse,
|
|
86802
|
-
validateMermaidDiagram: () => validateMermaidDiagram,
|
|
86803
|
-
validateMermaidResponse: () => validateMermaidResponse,
|
|
86804
|
-
validateXmlResponse: () => validateXmlResponse
|
|
86805
|
-
});
|
|
86806
|
-
function generateExampleFromSchema(schema, options = {}) {
|
|
86807
|
-
const { debug = false } = options;
|
|
86808
|
-
try {
|
|
86809
|
-
const parsedSchema = typeof schema === "string" ? JSON.parse(schema) : schema;
|
|
86810
|
-
if (parsedSchema.type !== "object" || !parsedSchema.properties) {
|
|
86811
|
-
return null;
|
|
86812
|
-
}
|
|
86813
|
-
const exampleObj = {};
|
|
86814
|
-
for (const [key, value] of Object.entries(parsedSchema.properties)) {
|
|
86815
|
-
if (value.type === "boolean") {
|
|
86816
|
-
exampleObj[key] = false;
|
|
86817
|
-
} else if (value.type === "number") {
|
|
86818
|
-
exampleObj[key] = 0;
|
|
86819
|
-
} else if (value.type === "string") {
|
|
86820
|
-
exampleObj[key] = value.description || "your answer here";
|
|
86821
|
-
} else if (value.type === "array") {
|
|
86822
|
-
exampleObj[key] = [];
|
|
86823
|
-
} else {
|
|
86824
|
-
exampleObj[key] = {};
|
|
86825
|
-
}
|
|
86826
|
-
}
|
|
86827
|
-
return exampleObj;
|
|
86828
|
-
} catch (e) {
|
|
86829
|
-
if (debug) {
|
|
86830
|
-
console.error("[DEBUG] generateExampleFromSchema: Failed to parse schema:", e.message);
|
|
86831
|
-
}
|
|
86832
|
-
return null;
|
|
86833
|
-
}
|
|
86834
|
-
}
|
|
86835
86804
|
function generateSchemaInstructions(schema, options = {}) {
|
|
86836
86805
|
const { debug = false } = options;
|
|
86837
|
-
let instructions = "\n\nIMPORTANT: When you provide your final answer
|
|
86806
|
+
let instructions = "\n\nIMPORTANT: When you provide your final answer, you MUST format it as valid JSON matching this schema:\n\n";
|
|
86838
86807
|
try {
|
|
86839
86808
|
const parsedSchema = typeof schema === "string" ? JSON.parse(schema) : schema;
|
|
86840
86809
|
instructions += `${JSON.stringify(parsedSchema, null, 2)}
|
|
@@ -86848,7 +86817,7 @@ function generateSchemaInstructions(schema, options = {}) {
|
|
|
86848
86817
|
|
|
86849
86818
|
`;
|
|
86850
86819
|
}
|
|
86851
|
-
instructions += "Your response
|
|
86820
|
+
instructions += "Your final response must be ONLY valid JSON - no plain text, no explanations, no markdown.\n\nIMPORTANT: First complete the requested analysis/task thoroughly, then provide your final answer in the JSON format above.";
|
|
86852
86821
|
return instructions;
|
|
86853
86822
|
}
|
|
86854
86823
|
function enforceNoAdditionalProperties(schema) {
|
|
@@ -87345,65 +87314,6 @@ function tryExtractValidJsonPrefix(response, options = {}) {
|
|
|
87345
87314
|
return null;
|
|
87346
87315
|
}
|
|
87347
87316
|
}
|
|
87348
|
-
function validateXmlResponse(response) {
|
|
87349
|
-
const xmlPattern = /<\/?[\w\s="'.-]+>/g;
|
|
87350
|
-
const tags = response.match(xmlPattern);
|
|
87351
|
-
if (!tags) {
|
|
87352
|
-
return { isValid: false, error: "No XML tags found" };
|
|
87353
|
-
}
|
|
87354
|
-
if (response.includes("<") && response.includes(">")) {
|
|
87355
|
-
return { isValid: true };
|
|
87356
|
-
}
|
|
87357
|
-
return { isValid: false, error: "Invalid XML structure" };
|
|
87358
|
-
}
|
|
87359
|
-
function processSchemaResponse(response, schema, options = {}) {
|
|
87360
|
-
const { validateJson = false, validateXml = false, debug = false } = options;
|
|
87361
|
-
if (debug) {
|
|
87362
|
-
console.log(`[DEBUG] Schema processing: Starting with response length ${response.length}`);
|
|
87363
|
-
console.log(`[DEBUG] Schema processing: Schema type detection...`);
|
|
87364
|
-
if (isJsonSchema(schema)) {
|
|
87365
|
-
console.log(`[DEBUG] Schema processing: Detected JSON schema`);
|
|
87366
|
-
} else {
|
|
87367
|
-
console.log(`[DEBUG] Schema processing: Non-JSON schema detected`);
|
|
87368
|
-
}
|
|
87369
|
-
}
|
|
87370
|
-
const cleanStart = Date.now();
|
|
87371
|
-
const cleaned = cleanSchemaResponse(response);
|
|
87372
|
-
const cleanTime = Date.now() - cleanStart;
|
|
87373
|
-
const result = { cleaned };
|
|
87374
|
-
if (debug) {
|
|
87375
|
-
console.log(`[DEBUG] Schema processing: Cleaning completed in ${cleanTime}ms`);
|
|
87376
|
-
result.debug = {
|
|
87377
|
-
originalLength: response.length,
|
|
87378
|
-
cleanedLength: cleaned.length,
|
|
87379
|
-
wasModified: response !== cleaned,
|
|
87380
|
-
cleaningTimeMs: cleanTime,
|
|
87381
|
-
removedContent: response !== cleaned ? {
|
|
87382
|
-
before: response.substring(0, 100) + (response.length > 100 ? "..." : ""),
|
|
87383
|
-
after: cleaned.substring(0, 100) + (cleaned.length > 100 ? "..." : "")
|
|
87384
|
-
} : null
|
|
87385
|
-
};
|
|
87386
|
-
if (response !== cleaned) {
|
|
87387
|
-
console.log(`[DEBUG] Schema processing: Response was modified during cleaning`);
|
|
87388
|
-
console.log(`[DEBUG] Schema processing: Original length: ${response.length}, cleaned length: ${cleaned.length}`);
|
|
87389
|
-
} else {
|
|
87390
|
-
console.log(`[DEBUG] Schema processing: Response unchanged during cleaning`);
|
|
87391
|
-
}
|
|
87392
|
-
}
|
|
87393
|
-
if (validateJson) {
|
|
87394
|
-
if (debug) {
|
|
87395
|
-
console.log(`[DEBUG] Schema processing: Running JSON validation...`);
|
|
87396
|
-
}
|
|
87397
|
-
result.jsonValidation = validateJsonResponse(cleaned, { debug });
|
|
87398
|
-
}
|
|
87399
|
-
if (validateXml) {
|
|
87400
|
-
if (debug) {
|
|
87401
|
-
console.log(`[DEBUG] Schema processing: Running XML validation...`);
|
|
87402
|
-
}
|
|
87403
|
-
result.xmlValidation = validateXmlResponse(cleaned);
|
|
87404
|
-
}
|
|
87405
|
-
return result;
|
|
87406
|
-
}
|
|
87407
87317
|
function isJsonSchema(schema) {
|
|
87408
87318
|
if (!schema || typeof schema !== "string") {
|
|
87409
87319
|
return false;
|
|
@@ -87545,18 +87455,18 @@ function createJsonCorrectionPrompt(invalidResponse, schema, errorOrValidation,
|
|
|
87545
87455
|
const strengthLevels = [
|
|
87546
87456
|
{
|
|
87547
87457
|
prefix: "CRITICAL JSON ERROR:",
|
|
87548
|
-
instruction: "You MUST fix this and respond
|
|
87549
|
-
emphasis: "
|
|
87458
|
+
instruction: "You MUST fix this and respond with ONLY valid JSON.",
|
|
87459
|
+
emphasis: "Respond with ONLY the corrected JSON. No explanatory text, no markdown, no code blocks."
|
|
87550
87460
|
},
|
|
87551
87461
|
{
|
|
87552
87462
|
prefix: "URGENT - JSON PARSING FAILED:",
|
|
87553
|
-
instruction: "This is your second chance.
|
|
87554
|
-
emphasis: "ABSOLUTELY NO explanatory text or formatting.
|
|
87463
|
+
instruction: "This is your second chance. Respond with valid JSON that can be parsed by JSON.parse().",
|
|
87464
|
+
emphasis: "ABSOLUTELY NO explanatory text or formatting. Respond with ONLY raw JSON."
|
|
87555
87465
|
},
|
|
87556
87466
|
{
|
|
87557
87467
|
prefix: "FINAL ATTEMPT - CRITICAL JSON ERROR:",
|
|
87558
|
-
instruction: "This is the final retry. You MUST
|
|
87559
|
-
emphasis: 'CORRECT:
|
|
87468
|
+
instruction: "This is the final retry. You MUST respond with ONLY raw JSON.",
|
|
87469
|
+
emphasis: 'CORRECT: {"key": "value"}\nWRONG: Here is the JSON: {"key": "value"}\nWRONG: ```json{"key": "value"}```'
|
|
87560
87470
|
}
|
|
87561
87471
|
];
|
|
87562
87472
|
const level = Math.min(retryCount, strengthLevels.length - 1);
|
|
@@ -87610,28 +87520,6 @@ ${currentLevel.example}
|
|
|
87610
87520
|
Return ONLY the JSON data object/array that follows the schema structure. NO schema definitions, NO explanations, NO markdown formatting.`;
|
|
87611
87521
|
return prompt;
|
|
87612
87522
|
}
|
|
87613
|
-
function isMermaidSchema(schema) {
|
|
87614
|
-
if (!schema || typeof schema !== "string") {
|
|
87615
|
-
return false;
|
|
87616
|
-
}
|
|
87617
|
-
const trimmedSchema = schema.trim().toLowerCase();
|
|
87618
|
-
const mermaidIndicators = [
|
|
87619
|
-
trimmedSchema.includes("mermaid"),
|
|
87620
|
-
trimmedSchema.includes("diagram"),
|
|
87621
|
-
trimmedSchema.includes("flowchart"),
|
|
87622
|
-
trimmedSchema.includes("sequence"),
|
|
87623
|
-
trimmedSchema.includes("gantt"),
|
|
87624
|
-
trimmedSchema.includes("pie chart"),
|
|
87625
|
-
trimmedSchema.includes("state diagram"),
|
|
87626
|
-
trimmedSchema.includes("class diagram"),
|
|
87627
|
-
trimmedSchema.includes("entity relationship"),
|
|
87628
|
-
trimmedSchema.includes("user journey"),
|
|
87629
|
-
trimmedSchema.includes("git graph"),
|
|
87630
|
-
trimmedSchema.includes("requirement diagram"),
|
|
87631
|
-
trimmedSchema.includes("c4 context")
|
|
87632
|
-
];
|
|
87633
|
-
return mermaidIndicators.some((indicator) => indicator);
|
|
87634
|
-
}
|
|
87635
87523
|
function extractMermaidFromJson(response) {
|
|
87636
87524
|
if (!response || typeof response !== "string") {
|
|
87637
87525
|
return { diagrams: [], jsonPaths: [], parsedJson: null };
|
|
@@ -87763,28 +87651,6 @@ ${modifiedJsonString}
|
|
|
87763
87651
|
}
|
|
87764
87652
|
return modifiedJsonString;
|
|
87765
87653
|
}
|
|
87766
|
-
function replaceMermaidDiagramsInMarkdown(originalResponse, correctedDiagrams) {
|
|
87767
|
-
if (!originalResponse || typeof originalResponse !== "string") {
|
|
87768
|
-
return originalResponse;
|
|
87769
|
-
}
|
|
87770
|
-
if (!correctedDiagrams || correctedDiagrams.length === 0) {
|
|
87771
|
-
return originalResponse;
|
|
87772
|
-
}
|
|
87773
|
-
const hasJsonDiagrams = correctedDiagrams.some((d) => d.isInJson);
|
|
87774
|
-
if (hasJsonDiagrams) {
|
|
87775
|
-
return replaceMermaidDiagramsInJson(originalResponse, correctedDiagrams);
|
|
87776
|
-
}
|
|
87777
|
-
let modifiedResponse = originalResponse;
|
|
87778
|
-
const sortedDiagrams = [...correctedDiagrams].sort((a, b) => b.startIndex - a.startIndex);
|
|
87779
|
-
for (const diagram of sortedDiagrams) {
|
|
87780
|
-
const attributesStr = diagram.attributes ? ` ${diagram.attributes}` : "";
|
|
87781
|
-
const newCodeBlock = `\`\`\`mermaid${attributesStr}
|
|
87782
|
-
${diagram.content}
|
|
87783
|
-
\`\`\``;
|
|
87784
|
-
modifiedResponse = modifiedResponse.slice(0, diagram.startIndex) + newCodeBlock + modifiedResponse.slice(diagram.endIndex);
|
|
87785
|
-
}
|
|
87786
|
-
return modifiedResponse;
|
|
87787
|
-
}
|
|
87788
87654
|
function replaceSingleMermaidDiagramInResponse(response, originalDiagram, newContent) {
|
|
87789
87655
|
if (!originalDiagram) {
|
|
87790
87656
|
return response;
|
|
@@ -87869,45 +87735,6 @@ async function validateMermaidResponse(response) {
|
|
|
87869
87735
|
errors: errors.length > 0 ? errors : void 0
|
|
87870
87736
|
};
|
|
87871
87737
|
}
|
|
87872
|
-
function createMermaidCorrectionPrompt(invalidResponse, schema, errors, diagrams) {
|
|
87873
|
-
let prompt = `Your previous response contains invalid Mermaid diagrams that cannot be parsed. Here's what you returned:
|
|
87874
|
-
|
|
87875
|
-
${invalidResponse}
|
|
87876
|
-
|
|
87877
|
-
Validation Errors:`;
|
|
87878
|
-
errors.forEach((error40, index) => {
|
|
87879
|
-
prompt += `
|
|
87880
|
-
${index + 1}. ${error40}`;
|
|
87881
|
-
});
|
|
87882
|
-
if (diagrams && diagrams.length > 0) {
|
|
87883
|
-
prompt += `
|
|
87884
|
-
|
|
87885
|
-
Diagram Details:`;
|
|
87886
|
-
diagrams.forEach((diagramResult, index) => {
|
|
87887
|
-
if (!diagramResult.isValid) {
|
|
87888
|
-
prompt += `
|
|
87889
|
-
|
|
87890
|
-
Diagram ${index + 1}:`;
|
|
87891
|
-
const diagramContent = diagramResult.content || diagramResult.diagram || "";
|
|
87892
|
-
prompt += `
|
|
87893
|
-
- Content: ${diagramContent.substring(0, 100)}${diagramContent.length > 100 ? "..." : ""}`;
|
|
87894
|
-
prompt += `
|
|
87895
|
-
- Error: ${diagramResult.error}`;
|
|
87896
|
-
if (diagramResult.detailedError && diagramResult.detailedError !== diagramResult.error) {
|
|
87897
|
-
prompt += `
|
|
87898
|
-
- Details: ${diagramResult.detailedError}`;
|
|
87899
|
-
}
|
|
87900
|
-
}
|
|
87901
|
-
});
|
|
87902
|
-
}
|
|
87903
|
-
prompt += `
|
|
87904
|
-
|
|
87905
|
-
Please correct your response to include valid Mermaid diagrams that match this schema:
|
|
87906
|
-
${schema}
|
|
87907
|
-
|
|
87908
|
-
Ensure all Mermaid diagrams are properly formatted within \`\`\`mermaid code blocks and follow correct Mermaid syntax.`;
|
|
87909
|
-
return prompt;
|
|
87910
|
-
}
|
|
87911
87738
|
async function tryMaidAutoFix(diagramContent, options = {}) {
|
|
87912
87739
|
const { debug = false } = options;
|
|
87913
87740
|
try {
|
|
@@ -88217,7 +88044,7 @@ async function validateAndFixMermaidResponse(response, options = {}) {
|
|
|
88217
88044
|
};
|
|
88218
88045
|
}
|
|
88219
88046
|
}
|
|
88220
|
-
var import_ajv, HTML_ENTITY_MAP, sessionIdCounter,
|
|
88047
|
+
var import_ajv, HTML_ENTITY_MAP, sessionIdCounter, MermaidFixingAgent;
|
|
88221
88048
|
var init_schemaUtils = __esm({
|
|
88222
88049
|
"src/agent/schemaUtils.js"() {
|
|
88223
88050
|
"use strict";
|
|
@@ -88235,172 +88062,6 @@ var init_schemaUtils = __esm({
|
|
|
88235
88062
|
" ": " "
|
|
88236
88063
|
};
|
|
88237
88064
|
sessionIdCounter = 0;
|
|
88238
|
-
JsonFixingAgent = class {
|
|
88239
|
-
constructor(options = {}) {
|
|
88240
|
-
this.ProbeAgent = null;
|
|
88241
|
-
this.options = {
|
|
88242
|
-
sessionId: options.sessionId || `json-fixer-${Date.now()}-${sessionIdCounter++}`,
|
|
88243
|
-
path: options.path || process.cwd(),
|
|
88244
|
-
provider: options.provider,
|
|
88245
|
-
model: options.model,
|
|
88246
|
-
debug: options.debug,
|
|
88247
|
-
tracer: options.tracer,
|
|
88248
|
-
// Set to false since we're only fixing JSON syntax, not implementing code
|
|
88249
|
-
allowEdit: false
|
|
88250
|
-
};
|
|
88251
|
-
}
|
|
88252
|
-
/**
|
|
88253
|
-
* Get the specialized prompt for JSON fixing
|
|
88254
|
-
*/
|
|
88255
|
-
getJsonFixingPrompt() {
|
|
88256
|
-
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.
|
|
88257
|
-
|
|
88258
|
-
CORE RESPONSIBILITIES:
|
|
88259
|
-
- Analyze JSON for syntax errors and structural issues
|
|
88260
|
-
- Fix syntax errors while maintaining the original data's semantic meaning
|
|
88261
|
-
- Ensure JSON follows proper RFC 8259 specification
|
|
88262
|
-
- Handle all JSON structures: objects, arrays, primitives, nested structures
|
|
88263
|
-
|
|
88264
|
-
JSON SYNTAX RULES:
|
|
88265
|
-
1. **Property names**: Must be enclosed in double quotes
|
|
88266
|
-
2. **String values**: Must use double quotes (not single quotes)
|
|
88267
|
-
3. **Numbers**: Can be integers or decimals, no quotes needed
|
|
88268
|
-
4. **Booleans**: true or false (lowercase, no quotes)
|
|
88269
|
-
5. **Null**: null (lowercase, no quotes)
|
|
88270
|
-
6. **Arrays**: Comma-separated values in square brackets [...]
|
|
88271
|
-
7. **Objects**: Comma-separated key-value pairs in curly braces {...}
|
|
88272
|
-
8. **No trailing commas**: Last item in array/object must not have a trailing comma
|
|
88273
|
-
9. **Escape sequences**: Special characters must be escaped (\\n, \\t, \\", \\\\, etc.)
|
|
88274
|
-
|
|
88275
|
-
COMMON ERRORS TO FIX:
|
|
88276
|
-
1. **Unquoted property names**: {name: "value"} \u2192 {"name": "value"}
|
|
88277
|
-
2. **Single quotes**: {'key': 'value'} \u2192 {"key": "value"}
|
|
88278
|
-
3. **Trailing commas**: {"a": 1,} \u2192 {"a": 1}
|
|
88279
|
-
4. **Unquoted strings**: {key: value} \u2192 {"key": "value"}
|
|
88280
|
-
5. **Missing commas**: {"a": 1 "b": 2} \u2192 {"a": 1, "b": 2}
|
|
88281
|
-
6. **Extra commas**: {"a": 1,, "b": 2} \u2192 {"a": 1, "b": 2}
|
|
88282
|
-
7. **Unclosed brackets/braces**: {"key": "value" \u2192 {"key": "value"}
|
|
88283
|
-
8. **Invalid escape sequences**: Fix or remove
|
|
88284
|
-
9. **Comments**: Remove // or /* */ comments (not allowed in JSON)
|
|
88285
|
-
10. **Undefined values**: Replace undefined with null
|
|
88286
|
-
|
|
88287
|
-
FIXING METHODOLOGY:
|
|
88288
|
-
1. **Identify the error location** from the error message
|
|
88289
|
-
2. **Analyze the context** around the error
|
|
88290
|
-
3. **Apply the appropriate fix** based on JSON syntax rules
|
|
88291
|
-
4. **Preserve data intent** - never change the meaning of the data
|
|
88292
|
-
5. **Validate the result** - ensure it's parseable JSON
|
|
88293
|
-
|
|
88294
|
-
CRITICAL RULES:
|
|
88295
|
-
- ALWAYS output only the corrected JSON
|
|
88296
|
-
- NEVER add explanations, comments, or additional text
|
|
88297
|
-
- NEVER wrap in markdown code blocks (no \`\`\`json)
|
|
88298
|
-
- PRESERVE the original data structure and values
|
|
88299
|
-
- FIX only syntax errors, don't modify the data itself
|
|
88300
|
-
- ENSURE the output is valid, parseable JSON
|
|
88301
|
-
|
|
88302
|
-
When presented with broken JSON, analyze it thoroughly and provide the corrected version that maintains the original intent while fixing all syntax issues.`;
|
|
88303
|
-
}
|
|
88304
|
-
/**
|
|
88305
|
-
* Initialize the ProbeAgent if not already done
|
|
88306
|
-
*/
|
|
88307
|
-
async initializeAgent() {
|
|
88308
|
-
if (!this.ProbeAgent) {
|
|
88309
|
-
const { ProbeAgent: ProbeAgent2 } = await Promise.resolve().then(() => (init_ProbeAgent(), ProbeAgent_exports));
|
|
88310
|
-
this.ProbeAgent = ProbeAgent2;
|
|
88311
|
-
}
|
|
88312
|
-
if (!this.agent) {
|
|
88313
|
-
this.agent = new this.ProbeAgent({
|
|
88314
|
-
sessionId: this.options.sessionId,
|
|
88315
|
-
customPrompt: this.getJsonFixingPrompt(),
|
|
88316
|
-
path: this.options.path,
|
|
88317
|
-
provider: this.options.provider,
|
|
88318
|
-
model: this.options.model,
|
|
88319
|
-
debug: this.options.debug,
|
|
88320
|
-
tracer: this.options.tracer,
|
|
88321
|
-
allowEdit: this.options.allowEdit,
|
|
88322
|
-
maxIterations: 5,
|
|
88323
|
-
// Allow multiple iterations for JSON fixing
|
|
88324
|
-
disableJsonValidation: true
|
|
88325
|
-
// CRITICAL: Disable JSON validation in nested agent to prevent infinite recursion
|
|
88326
|
-
});
|
|
88327
|
-
}
|
|
88328
|
-
return this.agent;
|
|
88329
|
-
}
|
|
88330
|
-
/**
|
|
88331
|
-
* Fix invalid JSON using the specialized agent
|
|
88332
|
-
* @param {string} invalidJson - The broken JSON string
|
|
88333
|
-
* @param {string} schema - The original schema for context
|
|
88334
|
-
* @param {Object} validationResult - Validation result with error details
|
|
88335
|
-
* @param {number} attemptNumber - Current attempt number (for logging)
|
|
88336
|
-
* @returns {Promise<string>} - The corrected JSON
|
|
88337
|
-
*/
|
|
88338
|
-
async fixJson(invalidJson, schema, validationResult, attemptNumber = 1) {
|
|
88339
|
-
await this.initializeAgent();
|
|
88340
|
-
let errorContext = validationResult.error;
|
|
88341
|
-
if (validationResult.enhancedError) {
|
|
88342
|
-
errorContext = validationResult.enhancedError;
|
|
88343
|
-
}
|
|
88344
|
-
let schemaErrorDetails = "";
|
|
88345
|
-
if (validationResult.errorSummary) {
|
|
88346
|
-
schemaErrorDetails = `
|
|
88347
|
-
|
|
88348
|
-
Schema Validation Errors:
|
|
88349
|
-
${validationResult.errorSummary}`;
|
|
88350
|
-
} else if (validationResult.schemaErrors && validationResult.schemaErrors.length > 0) {
|
|
88351
|
-
const errors = validationResult.schemaErrors.map((err) => {
|
|
88352
|
-
const path9 = err.instancePath || "(root)";
|
|
88353
|
-
return ` ${path9}: ${err.message}`;
|
|
88354
|
-
}).join("\n");
|
|
88355
|
-
schemaErrorDetails = `
|
|
88356
|
-
|
|
88357
|
-
Schema Validation Errors:
|
|
88358
|
-
${errors}`;
|
|
88359
|
-
}
|
|
88360
|
-
const prompt = `Fix the following invalid JSON.
|
|
88361
|
-
|
|
88362
|
-
Error: ${errorContext}${schemaErrorDetails}
|
|
88363
|
-
|
|
88364
|
-
Invalid JSON:
|
|
88365
|
-
${invalidJson}
|
|
88366
|
-
|
|
88367
|
-
Expected schema structure:
|
|
88368
|
-
${schema}
|
|
88369
|
-
|
|
88370
|
-
${schemaErrorDetails ? "CRITICAL: Pay special attention to the schema validation errors above. The JSON may be syntactically valid but does not conform to the required schema. Make sure to:\n- Include all required fields\n- Use correct data types\n- Remove any additional properties not defined in the schema (if additionalProperties is false)\n- Ensure all values match their schema constraints\n\n" : ""}Provide only the corrected JSON without any markdown formatting or explanations.`;
|
|
88371
|
-
try {
|
|
88372
|
-
if (this.options.debug) {
|
|
88373
|
-
console.log(`[DEBUG] JSON fixing: Attempt ${attemptNumber} to fix JSON with separate agent`);
|
|
88374
|
-
}
|
|
88375
|
-
const result = await this.agent.answer(prompt, []);
|
|
88376
|
-
const cleaned = cleanSchemaResponse(result);
|
|
88377
|
-
if (this.options.debug) {
|
|
88378
|
-
console.log(`[DEBUG] JSON fixing: Agent returned ${cleaned.length} chars`);
|
|
88379
|
-
}
|
|
88380
|
-
return cleaned;
|
|
88381
|
-
} catch (error40) {
|
|
88382
|
-
if (this.options.debug) {
|
|
88383
|
-
console.error(`[DEBUG] JSON fixing failed: ${error40.message}`);
|
|
88384
|
-
}
|
|
88385
|
-
throw new Error(`Failed to fix JSON: ${error40.message}`);
|
|
88386
|
-
}
|
|
88387
|
-
}
|
|
88388
|
-
/**
|
|
88389
|
-
* Get token usage information from the specialized agent
|
|
88390
|
-
* @returns {Object} - Token usage statistics
|
|
88391
|
-
*/
|
|
88392
|
-
getTokenUsage() {
|
|
88393
|
-
return this.agent ? this.agent.getTokenUsage() : null;
|
|
88394
|
-
}
|
|
88395
|
-
/**
|
|
88396
|
-
* Cancel any ongoing operations
|
|
88397
|
-
*/
|
|
88398
|
-
cancel() {
|
|
88399
|
-
if (this.agent) {
|
|
88400
|
-
this.agent.cancel();
|
|
88401
|
-
}
|
|
88402
|
-
}
|
|
88403
|
-
};
|
|
88404
88065
|
MermaidFixingAgent = class {
|
|
88405
88066
|
constructor(options = {}) {
|
|
88406
88067
|
this.ProbeAgent = null;
|
|
@@ -88644,7 +88305,7 @@ When reviewing code:
|
|
|
88644
88305
|
"code-review-template": `You are going to perform code review according to provided user rules. Ensure to review only code provided in diff and latest commit, if provided. However you still need to fully understand how modified code works, and read dependencies if something is not clear.`,
|
|
88645
88306
|
"engineer": `You are a senior engineer focused on software architecture and design.
|
|
88646
88307
|
Before jumping on the task you first analyse the user request in detail, and try to provide an elegant and concise solution.
|
|
88647
|
-
If the solution is clear, you can jump to implementation right away. If not, ask the user a clarification question
|
|
88308
|
+
If the solution is clear, you can jump to implementation right away. If not, ask the user a clarification question with the required details.
|
|
88648
88309
|
|
|
88649
88310
|
# Tone and Style
|
|
88650
88311
|
- Be concise and direct. Explain your approach briefly before implementing, then let the code speak for itself.
|
|
@@ -88667,7 +88328,7 @@ If the solution is clear, you can jump to implementation right away. If not, ask
|
|
|
88667
88328
|
When the request has **multiple distinct goals** (e.g. "Fix bug A AND add feature B"), use the task tool to track them:
|
|
88668
88329
|
- Call the task tool with action="create" and a tasks array. Each task must have an "id" field.
|
|
88669
88330
|
- Update task status to "in_progress" when starting and "completed" when done.
|
|
88670
|
-
- All tasks must be completed or cancelled before
|
|
88331
|
+
- All tasks must be completed or cancelled before providing your final answer.
|
|
88671
88332
|
- Stay flexible \u2014 add, remove, or reorganize tasks as your understanding changes.
|
|
88672
88333
|
|
|
88673
88334
|
Do NOT create tasks for single-goal requests, even complex ones. Multiple internal steps for one goal (search, read, analyze, implement) do not need tasks.
|
|
@@ -97924,9 +97585,15 @@ function messageContainsCompletion(msg) {
|
|
|
97924
97585
|
}
|
|
97925
97586
|
if (Array.isArray(msg.content)) {
|
|
97926
97587
|
if (msg.content.some((p) => p.type === "tool-call" && p.toolName === "attempt_completion")) return true;
|
|
97588
|
+
const hasToolCalls = msg.content.some((p) => p.type === "tool-call");
|
|
97589
|
+
const hasText = msg.content.some((p) => p.type === "text" && p.text?.trim());
|
|
97590
|
+
if (!hasToolCalls && hasText) return true;
|
|
97927
97591
|
}
|
|
97928
97592
|
const text = typeof msg.content === "string" ? msg.content : "";
|
|
97929
|
-
|
|
97593
|
+
if (text.includes("attempt_completion")) return true;
|
|
97594
|
+
const hasNoToolCalls = !Array.isArray(msg.toolInvocations) && !Array.isArray(msg.tool_calls);
|
|
97595
|
+
if (hasNoToolCalls && text.trim().length > 0) return true;
|
|
97596
|
+
return false;
|
|
97930
97597
|
}
|
|
97931
97598
|
function identifyMessageSegments(messages) {
|
|
97932
97599
|
const segments = [];
|
|
@@ -99696,8 +99363,8 @@ function debugTruncate(s, limit = 200) {
|
|
|
99696
99363
|
function debugLogToolResults(toolResults) {
|
|
99697
99364
|
if (!toolResults || toolResults.length === 0) return;
|
|
99698
99365
|
for (const tr of toolResults) {
|
|
99699
|
-
const argsStr = JSON.stringify(tr.args
|
|
99700
|
-
const resultStr = typeof tr.result === "string" ? tr.result : JSON.stringify(tr.result
|
|
99366
|
+
const argsStr = tr.args != null ? JSON.stringify(tr.args) : "<no args>";
|
|
99367
|
+
const resultStr = tr.result != null ? typeof tr.result === "string" ? tr.result : JSON.stringify(tr.result) : "<no result>";
|
|
99701
99368
|
console.log(`[DEBUG] tool: ${tr.toolName} | args: ${debugTruncate(argsStr)} | result: ${debugTruncate(resultStr)}`);
|
|
99702
99369
|
}
|
|
99703
99370
|
}
|
|
@@ -99803,7 +99470,7 @@ var init_ProbeAgent = __esm({
|
|
|
99803
99470
|
* @param {Array<Object>} [options.fallback.providers] - List of provider configurations for custom fallback
|
|
99804
99471
|
* @param {boolean} [options.fallback.stopOnSuccess=true] - Stop on first success
|
|
99805
99472
|
* @param {number} [options.fallback.maxTotalAttempts=10] - Maximum total attempts across all providers
|
|
99806
|
-
* @param {string} [options.completionPrompt] - Custom prompt to run after
|
|
99473
|
+
* @param {string} [options.completionPrompt] - Custom prompt to run after completion for validation/review (runs before mermaid/JSON validation)
|
|
99807
99474
|
* @param {number} [options.maxOutputTokens] - Maximum tokens for tool output before truncation (default: 20000, can also be set via PROBE_MAX_OUTPUT_TOKENS env var)
|
|
99808
99475
|
* @param {number} [options.requestTimeout] - Timeout in ms for AI requests (default: 120000 or REQUEST_TIMEOUT env var). Used to abort hung requests.
|
|
99809
99476
|
* @param {number} [options.maxOperationTimeout] - Maximum timeout in ms for the entire operation including all retries and fallbacks (default: 300000 or MAX_OPERATION_TIMEOUT env var). This is the absolute maximum time for streamTextWithRetryAndFallback.
|
|
@@ -100955,12 +100622,11 @@ var init_ProbeAgent = __esm({
|
|
|
100955
100622
|
* - Delegate tool param injection
|
|
100956
100623
|
*
|
|
100957
100624
|
* @param {Object} options - Options from the answer() call
|
|
100958
|
-
* @param {Function} onComplete - Callback when attempt_completion is called (receives result string)
|
|
100959
100625
|
* @param {Object} context - Execution context { maxIterations, currentMessages }
|
|
100960
100626
|
* @returns {Object} Tools object for streamText()
|
|
100961
100627
|
* @private
|
|
100962
100628
|
*/
|
|
100963
|
-
_buildNativeTools(options,
|
|
100629
|
+
_buildNativeTools(options, context = {}) {
|
|
100964
100630
|
const { maxIterations = 30 } = context;
|
|
100965
100631
|
const nativeTools = {};
|
|
100966
100632
|
const isToolAllowed = (toolName) => this.allowedTools.isEnabled(toolName);
|
|
@@ -101110,16 +100776,6 @@ var init_ProbeAgent = __esm({
|
|
|
101110
100776
|
});
|
|
101111
100777
|
};
|
|
101112
100778
|
if (options._disableTools) {
|
|
101113
|
-
nativeTools.attempt_completion = (0, import_ai6.tool)({
|
|
101114
|
-
description: "Signal task completion and provide the final result to the user",
|
|
101115
|
-
inputSchema: external_exports2.object({
|
|
101116
|
-
result: external_exports2.string().describe("The final result to present to the user")
|
|
101117
|
-
}),
|
|
101118
|
-
execute: async ({ result }) => {
|
|
101119
|
-
onComplete(result);
|
|
101120
|
-
return result;
|
|
101121
|
-
}
|
|
101122
|
-
});
|
|
101123
100779
|
return nativeTools;
|
|
101124
100780
|
}
|
|
101125
100781
|
for (const [toolName, toolImpl] of Object.entries(this.toolImplementations)) {
|
|
@@ -101130,28 +100786,6 @@ var init_ProbeAgent = __esm({
|
|
|
101130
100786
|
nativeTools[toolName] = wrapTool(toolName, schema, description, toolImpl.execute);
|
|
101131
100787
|
}
|
|
101132
100788
|
}
|
|
101133
|
-
nativeTools.attempt_completion = (0, import_ai6.tool)({
|
|
101134
|
-
description: "Signal task completion and provide the final result to the user",
|
|
101135
|
-
inputSchema: external_exports2.object({
|
|
101136
|
-
result: external_exports2.string().describe("The final result to present to the user")
|
|
101137
|
-
}),
|
|
101138
|
-
execute: async ({ result }) => {
|
|
101139
|
-
if (this.enableTasks && this.taskManager && this.taskManager.hasIncompleteTasks()) {
|
|
101140
|
-
const incompleteTasks = this.taskManager.getIncompleteTasks();
|
|
101141
|
-
const highIterationCount = (context.currentIteration || 0) > maxIterations * 0.7;
|
|
101142
|
-
if (!highIterationCount) {
|
|
101143
|
-
const taskSummary = this.taskManager.getTaskSummary();
|
|
101144
|
-
const blockedMessage = createTaskCompletionBlockedMessage(taskSummary);
|
|
101145
|
-
if (this.debug) {
|
|
101146
|
-
console.log("[DEBUG] Task checkpoint: Blocking completion due to incomplete tasks");
|
|
101147
|
-
}
|
|
101148
|
-
return blockedMessage;
|
|
101149
|
-
}
|
|
101150
|
-
}
|
|
101151
|
-
onComplete(result);
|
|
101152
|
-
return result;
|
|
101153
|
-
}
|
|
101154
|
-
});
|
|
101155
100789
|
if (this.mcpBridge && !options._disableTools) {
|
|
101156
100790
|
const mcpTools = this.mcpBridge.getVercelTools(this._filterMcpTools(this.mcpBridge.getToolNames()));
|
|
101157
100791
|
for (const [name15, mcpTool] of Object.entries(mcpTools)) {
|
|
@@ -102035,7 +101669,7 @@ Follow these instructions carefully:
|
|
|
102035
101669
|
2. Use the available tools step-by-step to fulfill the request.
|
|
102036
101670
|
3. You should always prefer the search tool for code-related questions.${this.searchDelegate ? " Ask natural language questions \u2014 the search subagent handles keyword formulation and returns extracted code blocks. Use extract only to expand context or read full files." : " Search handles stemming and case variations automatically \u2014 do NOT try keyword variations manually. Read full files only if really necessary."}
|
|
102037
101671
|
4. Ensure to get really deep and understand the full picture before answering.
|
|
102038
|
-
5. Once the task is fully completed,
|
|
101672
|
+
5. Once the task is fully completed, provide your final answer directly as text.
|
|
102039
101673
|
6. ${this.searchDelegate ? "Ask clear, specific questions when searching. Each search should target a distinct concept or question." : "Prefer concise and focused search queries. Use specific keywords and phrases to narrow down results."}
|
|
102040
101674
|
7. NEVER use bash for code exploration (no grep, cat, find, head, tail, awk, sed) \u2014 always use search and extract tools instead. Bash is only for system operations like building, running tests, or git commands.${this.allowEdit ? `
|
|
102041
101675
|
7. When modifying files, choose the appropriate tool:
|
|
@@ -102213,7 +101847,7 @@ You are working with a workspace. Available paths: ${workspaceDesc}
|
|
|
102213
101847
|
});
|
|
102214
101848
|
const systemMessage = await this.getSystemMessage();
|
|
102215
101849
|
let userMessage = { role: "user", content: message.trim() };
|
|
102216
|
-
if (options.schema && !options._schemaFormatted) {
|
|
101850
|
+
if (options.schema && !options._schemaFormatted && !options._disableTools) {
|
|
102217
101851
|
const schemaInstructions = generateSchemaInstructions(options.schema, { debug: this.debug });
|
|
102218
101852
|
userMessage.content = message.trim() + schemaInstructions;
|
|
102219
101853
|
}
|
|
@@ -102246,7 +101880,6 @@ You are working with a workspace. Available paths: ${workspaceDesc}
|
|
|
102246
101880
|
];
|
|
102247
101881
|
}
|
|
102248
101882
|
let currentIteration = 0;
|
|
102249
|
-
let completionAttempted = false;
|
|
102250
101883
|
let finalResult = "I was unable to complete your request due to reaching the maximum number of tool iterations.";
|
|
102251
101884
|
const baseMaxIterations = options._maxIterationsOverride || this.maxIterations || MAX_TOOL_ITERATIONS;
|
|
102252
101885
|
const maxIterations = options._maxIterationsOverride ? baseMaxIterations : options.schema ? baseMaxIterations + 4 : baseMaxIterations;
|
|
@@ -102362,12 +101995,8 @@ You are working with a workspace. Available paths: ${workspaceDesc}
|
|
|
102362
101995
|
console.log(`[DEBUG] Schema provided, using extended iteration limit: ${maxIterations} (base: ${baseMaxIterations})`);
|
|
102363
101996
|
}
|
|
102364
101997
|
}
|
|
102365
|
-
let completionResult = null;
|
|
102366
101998
|
const toolContext = { maxIterations, currentIteration: 0, currentMessages };
|
|
102367
|
-
const tools2 = this._buildNativeTools(options,
|
|
102368
|
-
completionResult = result;
|
|
102369
|
-
completionAttempted = true;
|
|
102370
|
-
}, toolContext);
|
|
101999
|
+
const tools2 = this._buildNativeTools(options, toolContext);
|
|
102371
102000
|
if (this.debug) {
|
|
102372
102001
|
const toolNames = Object.keys(tools2);
|
|
102373
102002
|
console.log(`[DEBUG] Agent tools registered (${toolNames.length}): ${toolNames.join(", ")}`);
|
|
@@ -102381,6 +102010,8 @@ You are working with a workspace. Available paths: ${workspaceDesc}
|
|
|
102381
102010
|
maxResponseTokens = 32e3;
|
|
102382
102011
|
}
|
|
102383
102012
|
}
|
|
102013
|
+
let completionPromptInjected = false;
|
|
102014
|
+
let preCompletionResult = null;
|
|
102384
102015
|
let compactionAttempted = false;
|
|
102385
102016
|
while (true) {
|
|
102386
102017
|
try {
|
|
@@ -102389,19 +102020,103 @@ You are working with a workspace. Available paths: ${workspaceDesc}
|
|
|
102389
102020
|
model: this.provider ? this.provider(this.model) : this.model,
|
|
102390
102021
|
messages: messagesForAI,
|
|
102391
102022
|
tools: tools2,
|
|
102392
|
-
stopWhen: (
|
|
102023
|
+
stopWhen: ({ steps }) => {
|
|
102024
|
+
if (steps.length >= maxIterations) return true;
|
|
102025
|
+
const lastStep = steps[steps.length - 1];
|
|
102026
|
+
const modelWantsToStop = lastStep?.finishReason === "stop" && (!lastStep?.toolCalls || lastStep.toolCalls.length === 0);
|
|
102027
|
+
if (modelWantsToStop) {
|
|
102028
|
+
if (this.enableTasks && this.taskManager?.hasIncompleteTasks()) {
|
|
102029
|
+
const highIterationCount = steps.length > maxIterations * 0.7;
|
|
102030
|
+
if (!highIterationCount) return false;
|
|
102031
|
+
}
|
|
102032
|
+
if (this.completionPrompt && !options._completionPromptProcessed && !completionPromptInjected) {
|
|
102033
|
+
preCompletionResult = lastStep.text || null;
|
|
102034
|
+
return false;
|
|
102035
|
+
}
|
|
102036
|
+
}
|
|
102037
|
+
let trailingNoTool = 0;
|
|
102038
|
+
for (let i = steps.length - 1; i >= 0; i--) {
|
|
102039
|
+
if (!steps[i].toolCalls?.length) trailingNoTool++;
|
|
102040
|
+
else break;
|
|
102041
|
+
}
|
|
102042
|
+
if (trailingNoTool >= 5) return true;
|
|
102043
|
+
if (trailingNoTool >= 3) {
|
|
102044
|
+
const recentTexts = steps.slice(-3).map((s) => s.text);
|
|
102045
|
+
if (recentTexts.every((t) => t && t === recentTexts[0])) return true;
|
|
102046
|
+
if (recentTexts.every((t) => detectStuckResponse(t))) return true;
|
|
102047
|
+
}
|
|
102048
|
+
return false;
|
|
102049
|
+
},
|
|
102050
|
+
prepareStep: ({ steps, stepNumber }) => {
|
|
102051
|
+
if (stepNumber === maxIterations - 1) {
|
|
102052
|
+
return {
|
|
102053
|
+
toolChoice: "none"
|
|
102054
|
+
};
|
|
102055
|
+
}
|
|
102056
|
+
const lastStep = steps[steps.length - 1];
|
|
102057
|
+
const modelJustStopped = lastStep?.finishReason === "stop" && (!lastStep?.toolCalls || lastStep.toolCalls.length === 0);
|
|
102058
|
+
if (modelJustStopped) {
|
|
102059
|
+
if (this.enableTasks && this.taskManager?.hasIncompleteTasks()) {
|
|
102060
|
+
const taskSummary = this.taskManager.getTaskSummary();
|
|
102061
|
+
const blockedMessage = createTaskCompletionBlockedMessage(taskSummary);
|
|
102062
|
+
return {
|
|
102063
|
+
userMessage: blockedMessage
|
|
102064
|
+
};
|
|
102065
|
+
}
|
|
102066
|
+
if (this.completionPrompt && !options._completionPromptProcessed && !completionPromptInjected) {
|
|
102067
|
+
completionPromptInjected = true;
|
|
102068
|
+
const resultToReview = lastStep.text || preCompletionResult || "";
|
|
102069
|
+
if (this.debug) {
|
|
102070
|
+
console.log("[DEBUG] Injecting completion prompt into main loop via prepareStep...");
|
|
102071
|
+
}
|
|
102072
|
+
if (this.tracer) {
|
|
102073
|
+
this.tracer.recordEvent("completion_prompt.started", {
|
|
102074
|
+
"completion_prompt.original_result_length": resultToReview.length
|
|
102075
|
+
});
|
|
102076
|
+
}
|
|
102077
|
+
const completionPromptMessage = `${this.completionPrompt}
|
|
102078
|
+
|
|
102079
|
+
Here is the result to review:
|
|
102080
|
+
<result>
|
|
102081
|
+
${resultToReview}
|
|
102082
|
+
</result>
|
|
102083
|
+
|
|
102084
|
+
Double-check your response based on the criteria above. If everything looks good, respond with your previous answer exactly as-is. If something needs to be fixed or is missing, do it now, then respond with the COMPLETE updated answer (everything you did in total, not just the fix).`;
|
|
102085
|
+
return {
|
|
102086
|
+
userMessage: completionPromptMessage
|
|
102087
|
+
};
|
|
102088
|
+
}
|
|
102089
|
+
}
|
|
102090
|
+
return void 0;
|
|
102091
|
+
},
|
|
102393
102092
|
maxTokens: maxResponseTokens,
|
|
102394
102093
|
temperature: 0.3,
|
|
102395
|
-
onStepFinish: (
|
|
102094
|
+
onStepFinish: (stepResult) => {
|
|
102095
|
+
const { toolResults, toolCalls, text, reasoningText, finishReason, usage } = stepResult;
|
|
102396
102096
|
currentIteration++;
|
|
102397
102097
|
toolContext.currentIteration = currentIteration;
|
|
102398
102098
|
if (this.tracer) {
|
|
102399
|
-
|
|
102099
|
+
const stepEvent = {
|
|
102400
102100
|
"iteration": currentIteration,
|
|
102401
102101
|
"max_iterations": maxIterations,
|
|
102402
102102
|
"finish_reason": finishReason,
|
|
102403
102103
|
"has_tool_calls": !!(toolResults && toolResults.length > 0)
|
|
102404
|
-
}
|
|
102104
|
+
};
|
|
102105
|
+
if (text) {
|
|
102106
|
+
stepEvent["ai.text"] = text.substring(0, 1e4);
|
|
102107
|
+
stepEvent["ai.text.length"] = text.length;
|
|
102108
|
+
}
|
|
102109
|
+
if (reasoningText) {
|
|
102110
|
+
stepEvent["ai.reasoning"] = reasoningText.substring(0, 1e4);
|
|
102111
|
+
stepEvent["ai.reasoning.length"] = reasoningText.length;
|
|
102112
|
+
}
|
|
102113
|
+
if (toolCalls && toolCalls.length > 0) {
|
|
102114
|
+
stepEvent["ai.tool_calls"] = toolCalls.map((tc) => ({
|
|
102115
|
+
name: tc.toolName,
|
|
102116
|
+
args: JSON.stringify(tc.args || {}).substring(0, 2e3)
|
|
102117
|
+
}));
|
|
102118
|
+
}
|
|
102119
|
+
this.tracer.addEvent("iteration.step", stepEvent);
|
|
102405
102120
|
}
|
|
102406
102121
|
if (usage) {
|
|
102407
102122
|
this.tokenCounter.recordUsage(usage);
|
|
@@ -102411,10 +102126,32 @@ You are working with a workspace. Available paths: ${workspaceDesc}
|
|
|
102411
102126
|
}
|
|
102412
102127
|
if (this.debug) {
|
|
102413
102128
|
console.log(`[DEBUG] Step ${currentIteration}/${maxIterations} finished (reason: ${finishReason}, tools: ${toolResults?.length || 0})`);
|
|
102129
|
+
if (text) {
|
|
102130
|
+
console.log(`[DEBUG] model text: ${debugTruncate(text)}`);
|
|
102131
|
+
}
|
|
102132
|
+
if (reasoningText) {
|
|
102133
|
+
console.log(`[DEBUG] reasoning: ${debugTruncate(reasoningText)}`);
|
|
102134
|
+
}
|
|
102414
102135
|
debugLogToolResults(toolResults);
|
|
102415
102136
|
}
|
|
102416
102137
|
}
|
|
102417
102138
|
};
|
|
102139
|
+
const hasActiveTools = Object.keys(tools2).length > 0;
|
|
102140
|
+
if (options.schema && !hasActiveTools) {
|
|
102141
|
+
try {
|
|
102142
|
+
const parsedSchema = typeof options.schema === "string" ? JSON.parse(options.schema) : options.schema;
|
|
102143
|
+
if (isJsonSchema(options.schema)) {
|
|
102144
|
+
streamOptions.output = import_ai6.Output.object({ schema: (0, import_ai6.jsonSchema)(parsedSchema) });
|
|
102145
|
+
if (this.debug) {
|
|
102146
|
+
console.log(`[DEBUG] Native JSON schema output enabled (no active tools)`);
|
|
102147
|
+
}
|
|
102148
|
+
}
|
|
102149
|
+
} catch (e) {
|
|
102150
|
+
if (this.debug) {
|
|
102151
|
+
console.log(`[DEBUG] Failed to set native JSON schema output: ${e.message}`);
|
|
102152
|
+
}
|
|
102153
|
+
}
|
|
102154
|
+
}
|
|
102418
102155
|
const providerOpts = this._buildThinkingProviderOptions(maxResponseTokens);
|
|
102419
102156
|
if (providerOpts) {
|
|
102420
102157
|
streamOptions.providerOptions = providerOpts;
|
|
@@ -102424,7 +102161,7 @@ You are working with a workspace. Available paths: ${workspaceDesc}
|
|
|
102424
102161
|
const finalText = await result.text;
|
|
102425
102162
|
if (this.debug) {
|
|
102426
102163
|
const steps = await result.steps;
|
|
102427
|
-
console.log(`[DEBUG] streamText completed: ${steps?.length || 0} steps, finalText=${finalText?.length || 0} chars
|
|
102164
|
+
console.log(`[DEBUG] streamText completed: ${steps?.length || 0} steps, finalText=${finalText?.length || 0} chars`);
|
|
102428
102165
|
}
|
|
102429
102166
|
const usage = await result.usage;
|
|
102430
102167
|
if (usage) {
|
|
@@ -102448,18 +102185,24 @@ You are working with a workspace. Available paths: ${workspaceDesc}
|
|
|
102448
102185
|
} else {
|
|
102449
102186
|
aiResult = await executeAIRequest();
|
|
102450
102187
|
}
|
|
102451
|
-
if (
|
|
102452
|
-
|
|
102453
|
-
|
|
102454
|
-
|
|
102455
|
-
|
|
102456
|
-
|
|
102457
|
-
|
|
102188
|
+
if (options.schema && streamOptions.output) {
|
|
102189
|
+
try {
|
|
102190
|
+
const outputObject = await aiResult.result.output;
|
|
102191
|
+
if (outputObject) {
|
|
102192
|
+
finalResult = JSON.stringify(outputObject);
|
|
102193
|
+
} else if (aiResult.finalText) {
|
|
102194
|
+
finalResult = aiResult.finalText;
|
|
102195
|
+
}
|
|
102196
|
+
} catch (e) {
|
|
102197
|
+
if (this.debug) {
|
|
102198
|
+
console.log(`[DEBUG] Native JSON output failed, falling back to text: ${e.message}`);
|
|
102199
|
+
}
|
|
102200
|
+
if (aiResult.finalText) {
|
|
102201
|
+
finalResult = aiResult.finalText;
|
|
102458
102202
|
}
|
|
102459
102203
|
}
|
|
102460
102204
|
} else if (aiResult.finalText) {
|
|
102461
102205
|
finalResult = aiResult.finalText;
|
|
102462
|
-
completionAttempted = true;
|
|
102463
102206
|
}
|
|
102464
102207
|
const resultMessages = await aiResult.result.response?.messages;
|
|
102465
102208
|
if (resultMessages) {
|
|
@@ -102467,6 +102210,75 @@ You are working with a workspace. Available paths: ${workspaceDesc}
|
|
|
102467
102210
|
currentMessages.push(msg);
|
|
102468
102211
|
}
|
|
102469
102212
|
}
|
|
102213
|
+
if (this.completionPrompt && !options._completionPromptProcessed && !completionPromptInjected && finalResult) {
|
|
102214
|
+
completionPromptInjected = true;
|
|
102215
|
+
preCompletionResult = finalResult;
|
|
102216
|
+
if (this.debug) {
|
|
102217
|
+
console.log("[DEBUG] Injecting completion prompt as post-streamText follow-up pass...");
|
|
102218
|
+
}
|
|
102219
|
+
if (this.tracer) {
|
|
102220
|
+
this.tracer.recordEvent("completion_prompt.started", {
|
|
102221
|
+
"completion_prompt.original_result_length": finalResult.length
|
|
102222
|
+
});
|
|
102223
|
+
}
|
|
102224
|
+
const completionPromptMessage = `${this.completionPrompt}
|
|
102225
|
+
|
|
102226
|
+
Here is the result to review:
|
|
102227
|
+
<result>
|
|
102228
|
+
${finalResult}
|
|
102229
|
+
</result>
|
|
102230
|
+
|
|
102231
|
+
Double-check your response based on the criteria above. If everything looks good, respond with your previous answer exactly as-is. If something needs to be fixed or is missing, do it now, then respond with the COMPLETE updated answer (everything you did in total, not just the fix).`;
|
|
102232
|
+
currentMessages.push({ role: "user", content: completionPromptMessage });
|
|
102233
|
+
const completionMaxIterations = 5;
|
|
102234
|
+
const completionStreamOptions = {
|
|
102235
|
+
model: this.provider ? this.provider(this.model) : this.model,
|
|
102236
|
+
messages: this.prepareMessagesWithImages(currentMessages),
|
|
102237
|
+
tools: tools2,
|
|
102238
|
+
stopWhen: (0, import_ai6.stepCountIs)(completionMaxIterations),
|
|
102239
|
+
maxTokens: maxResponseTokens,
|
|
102240
|
+
temperature: 0.3,
|
|
102241
|
+
onStepFinish: ({ toolResults, text, finishReason, usage }) => {
|
|
102242
|
+
if (usage) {
|
|
102243
|
+
this.tokenCounter.recordUsage(usage);
|
|
102244
|
+
}
|
|
102245
|
+
if (options.onStream && text) {
|
|
102246
|
+
options.onStream(text);
|
|
102247
|
+
}
|
|
102248
|
+
if (this.debug) {
|
|
102249
|
+
console.log(`[DEBUG] Completion prompt step finished (reason: ${finishReason}, tools: ${toolResults?.length || 0})`);
|
|
102250
|
+
}
|
|
102251
|
+
}
|
|
102252
|
+
};
|
|
102253
|
+
const providerOpts2 = this._buildThinkingProviderOptions(maxResponseTokens);
|
|
102254
|
+
if (providerOpts2) {
|
|
102255
|
+
completionStreamOptions.providerOptions = providerOpts2;
|
|
102256
|
+
}
|
|
102257
|
+
try {
|
|
102258
|
+
const cpResult = await this.streamTextWithRetryAndFallback(completionStreamOptions);
|
|
102259
|
+
const cpFinalText = await cpResult.text;
|
|
102260
|
+
const cpUsage = await cpResult.usage;
|
|
102261
|
+
if (cpUsage) {
|
|
102262
|
+
this.tokenCounter.recordUsage(cpUsage, cpResult.experimental_providerMetadata);
|
|
102263
|
+
}
|
|
102264
|
+
const cpMessages = await cpResult.response?.messages;
|
|
102265
|
+
if (cpMessages) {
|
|
102266
|
+
for (const msg of cpMessages) {
|
|
102267
|
+
currentMessages.push(msg);
|
|
102268
|
+
}
|
|
102269
|
+
}
|
|
102270
|
+
if (cpFinalText && cpFinalText.trim().length > 0) {
|
|
102271
|
+
finalResult = cpFinalText;
|
|
102272
|
+
}
|
|
102273
|
+
if (this.debug) {
|
|
102274
|
+
console.log(`[DEBUG] Completion prompt follow-up produced ${cpFinalText?.length || 0} chars (using ${cpFinalText && cpFinalText.trim().length > 0 ? "updated" : "original"} result)`);
|
|
102275
|
+
}
|
|
102276
|
+
} catch (cpError) {
|
|
102277
|
+
if (this.debug) {
|
|
102278
|
+
console.log(`[DEBUG] Completion prompt follow-up failed: ${cpError.message}, keeping original result`);
|
|
102279
|
+
}
|
|
102280
|
+
}
|
|
102281
|
+
}
|
|
102470
102282
|
break;
|
|
102471
102283
|
} catch (error40) {
|
|
102472
102284
|
if (!compactionAttempted && handleContextLimitError) {
|
|
@@ -102496,17 +102308,13 @@ You are working with a workspace. Available paths: ${workspaceDesc}
|
|
|
102496
102308
|
continue;
|
|
102497
102309
|
}
|
|
102498
102310
|
}
|
|
102499
|
-
if (completionResult) {
|
|
102500
|
-
finalResult = completionResult;
|
|
102501
|
-
break;
|
|
102502
|
-
}
|
|
102503
102311
|
console.error(`Error during streamText:`, error40);
|
|
102504
102312
|
finalResult = `Error: Failed to get response from AI model. ${error40.message}`;
|
|
102505
102313
|
throw new Error(finalResult);
|
|
102506
102314
|
}
|
|
102507
102315
|
}
|
|
102508
|
-
if (currentIteration >= maxIterations
|
|
102509
|
-
console.warn(`[WARN] Max tool iterations (${maxIterations}) reached for session ${this.sessionId}
|
|
102316
|
+
if (currentIteration >= maxIterations) {
|
|
102317
|
+
console.warn(`[WARN] Max tool iterations (${maxIterations}) reached for session ${this.sessionId}.`);
|
|
102510
102318
|
}
|
|
102511
102319
|
this.history = currentMessages.map((msg) => ({ ...msg }));
|
|
102512
102320
|
if (this.history.length > MAX_HISTORY_MESSAGES) {
|
|
@@ -102529,279 +102337,17 @@ You are working with a workspace. Available paths: ${workspaceDesc}
|
|
|
102529
102337
|
} catch (error40) {
|
|
102530
102338
|
console.error(`[ERROR] Failed to save messages to storage:`, error40);
|
|
102531
102339
|
}
|
|
102532
|
-
if (
|
|
102533
|
-
|
|
102534
|
-
|
|
102535
|
-
|
|
102536
|
-
|
|
102537
|
-
const originalResult = finalResult;
|
|
102538
|
-
if (this.tracer) {
|
|
102539
|
-
this.tracer.recordEvent("completion_prompt.started", {
|
|
102540
|
-
"completion_prompt.original_result_length": finalResult?.length || 0
|
|
102541
|
-
});
|
|
102542
|
-
}
|
|
102543
|
-
const completionPromptMessage = `${this.completionPrompt}
|
|
102544
|
-
|
|
102545
|
-
Here is the result to review:
|
|
102546
|
-
<result>
|
|
102547
|
-
${finalResult}
|
|
102548
|
-
</result>
|
|
102549
|
-
|
|
102550
|
-
Double-check your response based on the criteria above. If everything looks good, respond with your previous answer exactly as-is using attempt_completion. If something needs to be fixed or is missing, do it now, then respond with the COMPLETE updated answer (everything you did in total, not just the fix) using attempt_completion.`;
|
|
102551
|
-
currentMessages.push({ role: "user", content: completionPromptMessage });
|
|
102552
|
-
completionResult = null;
|
|
102553
|
-
completionAttempted = false;
|
|
102554
|
-
const completionMaxIterations = 5;
|
|
102555
|
-
const completionStreamOptions = {
|
|
102556
|
-
model: this.provider ? this.provider(this.model) : this.model,
|
|
102557
|
-
messages: this.prepareMessagesWithImages(currentMessages),
|
|
102558
|
-
tools: tools2,
|
|
102559
|
-
stopWhen: (0, import_ai6.stepCountIs)(completionMaxIterations),
|
|
102560
|
-
maxTokens: maxResponseTokens,
|
|
102561
|
-
temperature: 0.3,
|
|
102562
|
-
onStepFinish: ({ toolResults, text, finishReason, usage }) => {
|
|
102563
|
-
if (usage) {
|
|
102564
|
-
this.tokenCounter.recordUsage(usage);
|
|
102565
|
-
}
|
|
102566
|
-
if (options.onStream && text) {
|
|
102567
|
-
options.onStream(text);
|
|
102568
|
-
}
|
|
102569
|
-
if (this.debug) {
|
|
102570
|
-
console.log(`[DEBUG] Completion prompt step finished (reason: ${finishReason}, tools: ${toolResults?.length || 0})`);
|
|
102571
|
-
debugLogToolResults(toolResults);
|
|
102572
|
-
}
|
|
102573
|
-
}
|
|
102574
|
-
};
|
|
102575
|
-
const providerOpts = this._buildThinkingProviderOptions(maxResponseTokens);
|
|
102576
|
-
if (providerOpts) {
|
|
102577
|
-
completionStreamOptions.providerOptions = providerOpts;
|
|
102578
|
-
}
|
|
102579
|
-
const cpResult = await this.streamTextWithRetryAndFallback(completionStreamOptions);
|
|
102580
|
-
const cpFinalText = await cpResult.text;
|
|
102581
|
-
const cpUsage = await cpResult.usage;
|
|
102582
|
-
if (cpUsage) {
|
|
102583
|
-
this.tokenCounter.recordUsage(cpUsage, cpResult.experimental_providerMetadata);
|
|
102584
|
-
}
|
|
102585
|
-
const cpMessages = await cpResult.response?.messages;
|
|
102586
|
-
if (cpMessages) {
|
|
102587
|
-
for (const msg of cpMessages) {
|
|
102588
|
-
currentMessages.push(msg);
|
|
102589
|
-
}
|
|
102590
|
-
}
|
|
102591
|
-
if (completionResult) {
|
|
102592
|
-
finalResult = completionResult;
|
|
102593
|
-
completionAttempted = true;
|
|
102594
|
-
} else if (cpFinalText && cpFinalText.trim().length > 0) {
|
|
102595
|
-
finalResult = cpFinalText;
|
|
102596
|
-
completionAttempted = true;
|
|
102597
|
-
} else {
|
|
102598
|
-
finalResult = originalResult;
|
|
102599
|
-
completionAttempted = true;
|
|
102600
|
-
if (this.debug) {
|
|
102601
|
-
console.log("[DEBUG] Completion prompt returned empty result, keeping original.");
|
|
102602
|
-
}
|
|
102603
|
-
}
|
|
102604
|
-
if (this.debug) {
|
|
102605
|
-
console.log(`[DEBUG] Completion prompt finished. Final result length: ${finalResult?.length || 0}`);
|
|
102606
|
-
}
|
|
102607
|
-
if (this.tracer) {
|
|
102608
|
-
this.tracer.recordEvent("completion_prompt.completed", {
|
|
102609
|
-
"completion_prompt.final_result_length": finalResult?.length || 0,
|
|
102610
|
-
"completion_prompt.used_original": finalResult === originalResult
|
|
102611
|
-
});
|
|
102612
|
-
}
|
|
102613
|
-
} catch (error40) {
|
|
102614
|
-
console.error("[ERROR] Completion prompt failed:", error40);
|
|
102615
|
-
if (this.tracer) {
|
|
102616
|
-
this.tracer.recordEvent("completion_prompt.error", {
|
|
102617
|
-
"completion_prompt.error": error40.message
|
|
102618
|
-
});
|
|
102619
|
-
}
|
|
102620
|
-
}
|
|
102340
|
+
if (completionPromptInjected && this.tracer) {
|
|
102341
|
+
this.tracer.recordEvent("completion_prompt.completed", {
|
|
102342
|
+
"completion_prompt.final_result_length": finalResult?.length || 0,
|
|
102343
|
+
"completion_prompt.used_original": preCompletionResult && finalResult === preCompletionResult
|
|
102344
|
+
});
|
|
102621
102345
|
}
|
|
102622
|
-
|
|
102623
|
-
if (options.schema && !options._schemaFormatted && !completionAttempted && !reachedMaxIterations) {
|
|
102624
|
-
if (this.debug) {
|
|
102625
|
-
console.log("[DEBUG] Schema provided, applying automatic formatting...");
|
|
102626
|
-
}
|
|
102627
|
-
try {
|
|
102628
|
-
const schemaPrompt = `CRITICAL: You MUST respond with ONLY valid JSON DATA that conforms to this schema structure. DO NOT return the schema definition itself.
|
|
102629
|
-
|
|
102630
|
-
Schema to follow (this is just the structure - provide ACTUAL DATA):
|
|
102631
|
-
${options.schema}
|
|
102632
|
-
|
|
102633
|
-
REQUIREMENTS:
|
|
102634
|
-
- Return ONLY the JSON object/array with REAL DATA that matches the schema structure
|
|
102635
|
-
- DO NOT return the schema definition itself (no "$schema", "$id", "type", "properties", etc.)
|
|
102636
|
-
- NO additional text, explanations, or markdown formatting
|
|
102637
|
-
- NO code blocks or backticks
|
|
102638
|
-
- The JSON must be parseable by JSON.parse()
|
|
102639
|
-
- Fill in actual values that make sense based on your previous response content
|
|
102640
|
-
|
|
102641
|
-
EXAMPLE:
|
|
102642
|
-
If schema defines {type: "object", properties: {name: {type: "string"}, age: {type: "number"}}}
|
|
102643
|
-
Return: {"name": "John Doe", "age": 25}
|
|
102644
|
-
NOT: {"type": "object", "properties": {"name": {"type": "string"}}}
|
|
102645
|
-
|
|
102646
|
-
Convert your previous response content into actual JSON data that follows this schema structure.`;
|
|
102647
|
-
finalResult = await this.answer(schemaPrompt, [], {
|
|
102648
|
-
...options,
|
|
102649
|
-
_schemaFormatted: true,
|
|
102650
|
-
_completionPromptProcessed: true
|
|
102651
|
-
// Prevent cascading completion prompts in retry calls
|
|
102652
|
-
});
|
|
102653
|
-
if (!this.disableMermaidValidation) {
|
|
102654
|
-
try {
|
|
102655
|
-
if (this.debug) {
|
|
102656
|
-
console.log(`[DEBUG] Mermaid validation: Starting enhanced mermaid validation...`);
|
|
102657
|
-
}
|
|
102658
|
-
if (this.tracer) {
|
|
102659
|
-
this.tracer.recordMermaidValidationEvent("schema_processing_started", {
|
|
102660
|
-
"mermaid_validation.context": "schema_processing",
|
|
102661
|
-
"mermaid_validation.response_length": finalResult.length
|
|
102662
|
-
});
|
|
102663
|
-
}
|
|
102664
|
-
const mermaidValidation = await validateAndFixMermaidResponse(finalResult, {
|
|
102665
|
-
debug: this.debug,
|
|
102666
|
-
path: this.workspaceRoot || this.allowedFolders[0],
|
|
102667
|
-
provider: this.clientApiProvider,
|
|
102668
|
-
model: this.model,
|
|
102669
|
-
tracer: this.tracer
|
|
102670
|
-
});
|
|
102671
|
-
if (mermaidValidation.wasFixed) {
|
|
102672
|
-
finalResult = mermaidValidation.fixedResponse;
|
|
102673
|
-
if (this.debug) {
|
|
102674
|
-
console.log(`[DEBUG] Mermaid validation: Diagrams successfully fixed`);
|
|
102675
|
-
if (mermaidValidation.performanceMetrics) {
|
|
102676
|
-
const metrics = mermaidValidation.performanceMetrics;
|
|
102677
|
-
console.log(`[DEBUG] Mermaid validation: Performance - total: ${metrics.totalTimeMs}ms, AI fixing: ${metrics.aiFixingTimeMs}ms`);
|
|
102678
|
-
console.log(`[DEBUG] Mermaid validation: Results - ${metrics.diagramsFixed}/${metrics.diagramsProcessed} diagrams fixed`);
|
|
102679
|
-
}
|
|
102680
|
-
if (mermaidValidation.fixingResults) {
|
|
102681
|
-
mermaidValidation.fixingResults.forEach((fixResult, index) => {
|
|
102682
|
-
if (fixResult.wasFixed) {
|
|
102683
|
-
const method = fixResult.fixedWithHtmlDecoding ? "HTML entity decoding" : "AI correction";
|
|
102684
|
-
const time3 = fixResult.aiFixingTimeMs ? ` in ${fixResult.aiFixingTimeMs}ms` : "";
|
|
102685
|
-
console.log(`[DEBUG] Mermaid validation: Fixed diagram ${fixResult.diagramIndex + 1} with ${method}${time3}`);
|
|
102686
|
-
console.log(`[DEBUG] Mermaid validation: Original error: ${fixResult.originalError}`);
|
|
102687
|
-
} else {
|
|
102688
|
-
console.log(`[DEBUG] Mermaid validation: Failed to fix diagram ${fixResult.diagramIndex + 1}: ${fixResult.fixingError}`);
|
|
102689
|
-
}
|
|
102690
|
-
});
|
|
102691
|
-
}
|
|
102692
|
-
}
|
|
102693
|
-
} else if (this.debug) {
|
|
102694
|
-
console.log(`[DEBUG] Mermaid validation: No fixes needed or fixes unsuccessful`);
|
|
102695
|
-
if (mermaidValidation.diagrams?.length > 0) {
|
|
102696
|
-
console.log(`[DEBUG] Mermaid validation: Found ${mermaidValidation.diagrams.length} diagrams, all valid: ${mermaidValidation.isValid}`);
|
|
102697
|
-
}
|
|
102698
|
-
}
|
|
102699
|
-
} catch (error40) {
|
|
102700
|
-
if (this.debug) {
|
|
102701
|
-
console.log(`[DEBUG] Mermaid validation: Process failed with error: ${error40.message}`);
|
|
102702
|
-
console.log(`[DEBUG] Mermaid validation: Stack trace: ${error40.stack}`);
|
|
102703
|
-
}
|
|
102704
|
-
}
|
|
102705
|
-
} else if (this.debug) {
|
|
102706
|
-
console.log(`[DEBUG] Mermaid validation: Skipped due to disableMermaidValidation option`);
|
|
102707
|
-
}
|
|
102708
|
-
finalResult = cleanSchemaResponse(finalResult);
|
|
102709
|
-
if (isJsonSchema(options.schema)) {
|
|
102710
|
-
if (this.debug) {
|
|
102711
|
-
console.log(`[DEBUG] JSON validation: Starting validation process for schema response`);
|
|
102712
|
-
console.log(`[DEBUG] JSON validation: Cleaned response length: ${finalResult.length} chars`);
|
|
102713
|
-
}
|
|
102714
|
-
if (this.tracer) {
|
|
102715
|
-
this.tracer.recordJsonValidationEvent("started", {
|
|
102716
|
-
"json_validation.response_length": finalResult.length,
|
|
102717
|
-
"json_validation.schema_type": "JSON"
|
|
102718
|
-
});
|
|
102719
|
-
}
|
|
102720
|
-
let validation = validateJsonResponse(finalResult, { debug: this.debug, schema: options.schema });
|
|
102721
|
-
let retryCount = 0;
|
|
102722
|
-
const maxRetries = 3;
|
|
102723
|
-
if (validation.isValid && isJsonSchemaDefinition(finalResult, { debug: this.debug })) {
|
|
102724
|
-
if (this.debug) {
|
|
102725
|
-
console.log(`[DEBUG] JSON validation: Response is a JSON schema definition instead of data, needs correction...`);
|
|
102726
|
-
}
|
|
102727
|
-
validation = {
|
|
102728
|
-
isValid: false,
|
|
102729
|
-
error: "Response is a JSON schema definition instead of actual data",
|
|
102730
|
-
enhancedError: "Response is a JSON schema definition instead of actual data. Please return data that conforms to the schema, not the schema itself."
|
|
102731
|
-
};
|
|
102732
|
-
}
|
|
102733
|
-
if (!validation.isValid) {
|
|
102734
|
-
if (this.debug) {
|
|
102735
|
-
console.log(`[DEBUG] JSON validation: Starting separate JsonFixingAgent session...`);
|
|
102736
|
-
}
|
|
102737
|
-
const { JsonFixingAgent: JsonFixingAgent2 } = await Promise.resolve().then(() => (init_schemaUtils(), schemaUtils_exports));
|
|
102738
|
-
const jsonFixer = new JsonFixingAgent2({
|
|
102739
|
-
path: this.workspaceRoot || this.allowedFolders[0],
|
|
102740
|
-
provider: this.clientApiProvider,
|
|
102741
|
-
model: this.model,
|
|
102742
|
-
debug: this.debug,
|
|
102743
|
-
tracer: this.tracer
|
|
102744
|
-
});
|
|
102745
|
-
let currentResult = finalResult;
|
|
102746
|
-
let currentValidation = validation;
|
|
102747
|
-
while (!currentValidation.isValid && retryCount < maxRetries) {
|
|
102748
|
-
if (this.debug) {
|
|
102749
|
-
console.log(`[DEBUG] JSON validation: Validation failed (attempt ${retryCount + 1}/${maxRetries}):`, currentValidation.error);
|
|
102750
|
-
console.log(`[DEBUG] JSON validation: Invalid response sample: ${currentResult.substring(0, 300)}${currentResult.length > 300 ? "..." : ""}`);
|
|
102751
|
-
}
|
|
102752
|
-
try {
|
|
102753
|
-
currentResult = await jsonFixer.fixJson(
|
|
102754
|
-
currentResult,
|
|
102755
|
-
options.schema,
|
|
102756
|
-
currentValidation,
|
|
102757
|
-
retryCount + 1
|
|
102758
|
-
);
|
|
102759
|
-
currentValidation = validateJsonResponse(currentResult, { debug: this.debug, schema: options.schema });
|
|
102760
|
-
retryCount++;
|
|
102761
|
-
if (this.debug) {
|
|
102762
|
-
if (!currentValidation.isValid && retryCount < maxRetries) {
|
|
102763
|
-
console.log(`[DEBUG] JSON validation: Still invalid after correction ${retryCount}, retrying...`);
|
|
102764
|
-
console.log(`[DEBUG] JSON validation: Corrected response sample: ${currentResult.substring(0, 300)}${currentResult.length > 300 ? "..." : ""}`);
|
|
102765
|
-
} else if (currentValidation.isValid) {
|
|
102766
|
-
console.log(`[DEBUG] JSON validation: Successfully corrected after ${retryCount} attempts with JsonFixingAgent`);
|
|
102767
|
-
}
|
|
102768
|
-
}
|
|
102769
|
-
} catch (error40) {
|
|
102770
|
-
if (this.debug) {
|
|
102771
|
-
console.error(`[DEBUG] JSON validation: JsonFixingAgent error on attempt ${retryCount + 1}:`, error40.message);
|
|
102772
|
-
}
|
|
102773
|
-
break;
|
|
102774
|
-
}
|
|
102775
|
-
}
|
|
102776
|
-
finalResult = currentResult;
|
|
102777
|
-
validation = currentValidation;
|
|
102778
|
-
if (!validation.isValid && this.debug) {
|
|
102779
|
-
console.log(`[DEBUG] JSON validation: Still invalid after ${maxRetries} correction attempts with JsonFixingAgent:`, validation.error);
|
|
102780
|
-
console.log(`[DEBUG] JSON validation: Final invalid response: ${finalResult.substring(0, 500)}${finalResult.length > 500 ? "..." : ""}`);
|
|
102781
|
-
} else if (validation.isValid && this.debug) {
|
|
102782
|
-
console.log(`[DEBUG] JSON validation: Final validation successful`);
|
|
102783
|
-
}
|
|
102784
|
-
}
|
|
102785
|
-
if (this.tracer) {
|
|
102786
|
-
this.tracer.recordJsonValidationEvent("completed", {
|
|
102787
|
-
"json_validation.success": validation.isValid,
|
|
102788
|
-
"json_validation.retry_count": retryCount,
|
|
102789
|
-
"json_validation.max_retries": maxRetries,
|
|
102790
|
-
"json_validation.final_response_length": finalResult.length,
|
|
102791
|
-
"json_validation.error": validation.isValid ? null : validation.error
|
|
102792
|
-
});
|
|
102793
|
-
}
|
|
102794
|
-
}
|
|
102795
|
-
} catch (error40) {
|
|
102796
|
-
console.error("[ERROR] Schema formatting failed:", error40);
|
|
102797
|
-
}
|
|
102798
|
-
} else if (reachedMaxIterations && options.schema && this.debug) {
|
|
102799
|
-
console.log("[DEBUG] Skipping schema formatting due to max iterations reached without completion");
|
|
102800
|
-
} else if (completionAttempted && options.schema && !options._schemaFormatted && !options._skipValidation) {
|
|
102346
|
+
if (options.schema && !options._schemaFormatted && !options._skipValidation) {
|
|
102801
102347
|
try {
|
|
102802
102348
|
if (!this.disableMermaidValidation) {
|
|
102803
102349
|
if (this.debug) {
|
|
102804
|
-
console.log(`[DEBUG] Mermaid validation: Validating
|
|
102350
|
+
console.log(`[DEBUG] Mermaid validation: Validating result BEFORE schema cleaning...`);
|
|
102805
102351
|
}
|
|
102806
102352
|
const mermaidValidation = await validateAndFixMermaidResponse(finalResult, {
|
|
102807
102353
|
debug: this.debug,
|
|
@@ -102813,55 +102359,51 @@ Convert your previous response content into actual JSON data that follows this s
|
|
|
102813
102359
|
if (mermaidValidation.wasFixed) {
|
|
102814
102360
|
finalResult = mermaidValidation.fixedResponse;
|
|
102815
102361
|
if (this.debug) {
|
|
102816
|
-
console.log(`[DEBUG] Mermaid validation:
|
|
102362
|
+
console.log(`[DEBUG] Mermaid validation: Diagrams fixed`);
|
|
102817
102363
|
if (mermaidValidation.performanceMetrics) {
|
|
102818
102364
|
console.log(`[DEBUG] Mermaid validation: Fixed in ${mermaidValidation.performanceMetrics.totalTimeMs}ms`);
|
|
102819
102365
|
}
|
|
102820
102366
|
}
|
|
102821
102367
|
} else if (this.debug) {
|
|
102822
|
-
console.log(`[DEBUG] Mermaid validation:
|
|
102368
|
+
console.log(`[DEBUG] Mermaid validation: Completed (no fixes needed)`);
|
|
102823
102369
|
}
|
|
102824
102370
|
} else if (this.debug) {
|
|
102825
|
-
console.log(`[DEBUG] Mermaid validation: Skipped
|
|
102371
|
+
console.log(`[DEBUG] Mermaid validation: Skipped due to disableMermaidValidation option`);
|
|
102826
102372
|
}
|
|
102827
102373
|
finalResult = cleanSchemaResponse(finalResult);
|
|
102828
102374
|
if (isJsonSchema(options.schema)) {
|
|
102829
102375
|
if (this.debug) {
|
|
102830
|
-
console.log(`[DEBUG] JSON validation: Starting validation process
|
|
102376
|
+
console.log(`[DEBUG] JSON validation: Starting validation process`);
|
|
102831
102377
|
console.log(`[DEBUG] JSON validation: Response length: ${finalResult.length} chars`);
|
|
102832
102378
|
}
|
|
102833
102379
|
if (this.tracer) {
|
|
102834
|
-
this.tracer.recordJsonValidationEvent("
|
|
102380
|
+
this.tracer.recordJsonValidationEvent("started", {
|
|
102835
102381
|
"json_validation.response_length": finalResult.length,
|
|
102836
|
-
"json_validation.schema_type": "JSON"
|
|
102837
|
-
"json_validation.context": "attempt_completion"
|
|
102382
|
+
"json_validation.schema_type": "JSON"
|
|
102838
102383
|
});
|
|
102839
102384
|
}
|
|
102840
|
-
let validation = validateJsonResponse(finalResult, { debug: this.debug });
|
|
102385
|
+
let validation = validateJsonResponse(finalResult, { debug: this.debug, schema: options.schema });
|
|
102841
102386
|
let retryCount = 0;
|
|
102842
102387
|
const maxRetries = 3;
|
|
102843
102388
|
if (validation.isValid && isJsonSchemaDefinition(finalResult, { debug: this.debug })) {
|
|
102844
102389
|
if (this.debug) {
|
|
102845
|
-
console.log(`[DEBUG] JSON validation:
|
|
102390
|
+
console.log(`[DEBUG] JSON validation: Response is a JSON schema definition instead of data, correcting...`);
|
|
102846
102391
|
}
|
|
102847
102392
|
const schemaDefinitionPrompt = createSchemaDefinitionCorrectionPrompt(
|
|
102848
102393
|
finalResult,
|
|
102849
102394
|
options.schema,
|
|
102850
102395
|
0
|
|
102851
102396
|
);
|
|
102852
|
-
const { schema: _unusedSchema1, ...schemaDefCorrectionOptions } = options;
|
|
102853
102397
|
finalResult = await this.answer(schemaDefinitionPrompt, [], {
|
|
102854
|
-
...
|
|
102398
|
+
...options,
|
|
102855
102399
|
_schemaFormatted: true,
|
|
102856
102400
|
_skipValidation: true,
|
|
102857
|
-
|
|
102401
|
+
_disableTools: true,
|
|
102858
102402
|
_completionPromptProcessed: true,
|
|
102859
|
-
// Prevent cascading completion prompts in retry calls
|
|
102860
102403
|
_maxIterationsOverride: 3
|
|
102861
|
-
// Correction should complete in 1-2 iterations (issue #447)
|
|
102862
102404
|
});
|
|
102863
102405
|
finalResult = cleanSchemaResponse(finalResult);
|
|
102864
|
-
validation = validateJsonResponse(finalResult);
|
|
102406
|
+
validation = validateJsonResponse(finalResult, { debug: this.debug, schema: options.schema });
|
|
102865
102407
|
retryCount = 1;
|
|
102866
102408
|
}
|
|
102867
102409
|
if (!validation.isValid) {
|
|
@@ -102871,20 +102413,16 @@ Convert your previous response content into actual JSON data that follows this s
|
|
|
102871
102413
|
console.log(`[DEBUG] JSON validation: Auto-wrapped plain text for simple schema`);
|
|
102872
102414
|
}
|
|
102873
102415
|
finalResult = autoWrapped;
|
|
102874
|
-
validation = validateJsonResponse(finalResult, { debug: this.debug });
|
|
102416
|
+
validation = validateJsonResponse(finalResult, { debug: this.debug, schema: options.schema });
|
|
102875
102417
|
}
|
|
102876
102418
|
}
|
|
102877
102419
|
while (!validation.isValid && retryCount < maxRetries) {
|
|
102878
102420
|
if (this.debug) {
|
|
102879
|
-
console.log(`[DEBUG] JSON validation:
|
|
102880
|
-
console.log(`[DEBUG] JSON validation: Invalid response sample: ${finalResult.substring(0, 300)}${finalResult.length > 300 ? "..." : ""}`);
|
|
102421
|
+
console.log(`[DEBUG] JSON validation: Validation failed (attempt ${retryCount + 1}/${maxRetries}):`, validation.error);
|
|
102881
102422
|
}
|
|
102882
102423
|
let correctionPrompt;
|
|
102883
102424
|
try {
|
|
102884
102425
|
if (isJsonSchemaDefinition(finalResult, { debug: this.debug })) {
|
|
102885
|
-
if (this.debug) {
|
|
102886
|
-
console.log(`[DEBUG] JSON validation: attempt_completion response is still a schema definition, using specialized correction`);
|
|
102887
|
-
}
|
|
102888
102426
|
correctionPrompt = createSchemaDefinitionCorrectionPrompt(
|
|
102889
102427
|
finalResult,
|
|
102890
102428
|
options.schema,
|
|
@@ -102906,47 +102444,43 @@ Convert your previous response content into actual JSON data that follows this s
|
|
|
102906
102444
|
retryCount
|
|
102907
102445
|
);
|
|
102908
102446
|
}
|
|
102909
|
-
const { schema: _unusedSchema2, ...correctionOptions } = options;
|
|
102910
102447
|
finalResult = await this.answer(correctionPrompt, [], {
|
|
102911
|
-
...
|
|
102448
|
+
...options,
|
|
102912
102449
|
_schemaFormatted: true,
|
|
102913
102450
|
_skipValidation: true,
|
|
102914
|
-
// Skip validation in recursive correction calls to prevent loops
|
|
102915
102451
|
_disableTools: true,
|
|
102916
|
-
// Only allow attempt_completion - prevent AI from using search/query tools
|
|
102917
102452
|
_completionPromptProcessed: true,
|
|
102918
|
-
// Prevent cascading completion prompts in retry calls
|
|
102919
102453
|
_maxIterationsOverride: 3
|
|
102920
|
-
// Correction should complete in 1-2 iterations (issue #447)
|
|
102921
102454
|
});
|
|
102922
102455
|
finalResult = cleanSchemaResponse(finalResult);
|
|
102923
|
-
validation = validateJsonResponse(finalResult, { debug: this.debug });
|
|
102456
|
+
validation = validateJsonResponse(finalResult, { debug: this.debug, schema: options.schema });
|
|
102924
102457
|
retryCount++;
|
|
102925
102458
|
if (this.debug) {
|
|
102926
102459
|
if (validation.isValid) {
|
|
102927
|
-
console.log(`[DEBUG] JSON validation:
|
|
102460
|
+
console.log(`[DEBUG] JSON validation: Correction successful on attempt ${retryCount}`);
|
|
102928
102461
|
} else {
|
|
102929
|
-
console.log(`[DEBUG] JSON validation:
|
|
102462
|
+
console.log(`[DEBUG] JSON validation: Correction failed on attempt ${retryCount}: ${validation.error}`);
|
|
102930
102463
|
}
|
|
102931
102464
|
}
|
|
102932
102465
|
}
|
|
102933
102466
|
if (this.tracer) {
|
|
102934
|
-
this.tracer.recordJsonValidationEvent("
|
|
102467
|
+
this.tracer.recordJsonValidationEvent("completed", {
|
|
102935
102468
|
"json_validation.success": validation.isValid,
|
|
102936
102469
|
"json_validation.retry_count": retryCount,
|
|
102937
|
-
"json_validation.
|
|
102470
|
+
"json_validation.max_retries": maxRetries,
|
|
102471
|
+
"json_validation.final_response_length": finalResult.length,
|
|
102472
|
+
"json_validation.error": validation.isValid ? null : validation.error
|
|
102938
102473
|
});
|
|
102939
102474
|
}
|
|
102940
102475
|
if (!validation.isValid && this.debug) {
|
|
102941
|
-
console.log(`[DEBUG] JSON validation:
|
|
102942
|
-
console.log(`[DEBUG] JSON validation: Final attempt_completion response: ${finalResult.substring(0, 500)}${finalResult.length > 500 ? "..." : ""}`);
|
|
102476
|
+
console.log(`[DEBUG] JSON validation: Failed after ${maxRetries} attempts: ${validation.error}`);
|
|
102943
102477
|
} else if (validation.isValid && this.debug) {
|
|
102944
|
-
console.log(`[DEBUG] JSON validation:
|
|
102478
|
+
console.log(`[DEBUG] JSON validation: Final validation successful`);
|
|
102945
102479
|
}
|
|
102946
102480
|
}
|
|
102947
102481
|
} catch (error40) {
|
|
102948
102482
|
if (this.debug) {
|
|
102949
|
-
console.log(`[DEBUG]
|
|
102483
|
+
console.log(`[DEBUG] Schema validation/cleanup failed: ${error40.message}`);
|
|
102950
102484
|
}
|
|
102951
102485
|
}
|
|
102952
102486
|
}
|