@probelabs/probe 0.6.0-rc284 → 0.6.0-rc286
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-rc286-aarch64-apple-darwin.tar.gz +0 -0
- package/bin/binaries/{probe-v0.6.0-rc284-aarch64-unknown-linux-musl.tar.gz → probe-v0.6.0-rc286-aarch64-unknown-linux-musl.tar.gz} +0 -0
- package/bin/binaries/probe-v0.6.0-rc286-x86_64-apple-darwin.tar.gz +0 -0
- package/bin/binaries/probe-v0.6.0-rc286-x86_64-pc-windows-msvc.zip +0 -0
- package/bin/binaries/probe-v0.6.0-rc286-x86_64-unknown-linux-musl.tar.gz +0 -0
- package/build/agent/ProbeAgent.d.ts +1 -1
- package/build/agent/ProbeAgent.js +353 -489
- package/build/agent/contextCompactor.js +17 -10
- package/build/agent/index.js +325 -719
- 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/downloader.js +5 -1
- 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 +10 -8
- package/cjs/agent/ProbeAgent.cjs +316 -775
- package/cjs/index.cjs +317 -831
- package/package.json +1 -1
- package/src/agent/ProbeAgent.d.ts +1 -1
- package/src/agent/ProbeAgent.js +353 -489
- 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/downloader.js +5 -1
- 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 +10 -8
- package/bin/binaries/probe-v0.6.0-rc284-aarch64-apple-darwin.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
|
@@ -24981,7 +24981,11 @@ async function extractBinary(assetPath, outputDir) {
|
|
|
24981
24981
|
if (process.env.DEBUG === "1" || process.env.VERBOSE === "1") {
|
|
24982
24982
|
console.log(`Extracting zip to ${extractDir}...`);
|
|
24983
24983
|
}
|
|
24984
|
-
|
|
24984
|
+
if (isWindows) {
|
|
24985
|
+
await exec(`powershell -NoProfile -Command "Expand-Archive -Path '${assetPath}' -DestinationPath '${extractDir}' -Force"`);
|
|
24986
|
+
} else {
|
|
24987
|
+
await exec(`unzip -q "${assetPath}" -d "${extractDir}"`);
|
|
24988
|
+
}
|
|
24985
24989
|
} else {
|
|
24986
24990
|
if (process.env.DEBUG === "1" || process.env.VERBOSE === "1") {
|
|
24987
24991
|
console.log(`Copying binary directly to ${binaryPath}`);
|
|
@@ -26629,7 +26633,7 @@ Instructions:
|
|
|
26629
26633
|
- Format as a structured list if multiple items found
|
|
26630
26634
|
- If nothing relevant is found in this chunk, respond with "No relevant items found in this chunk."
|
|
26631
26635
|
- Do NOT summarize the code - extract the specific information requested
|
|
26632
|
-
- When done,
|
|
26636
|
+
- When done, provide your final answer directly.`;
|
|
26633
26637
|
try {
|
|
26634
26638
|
const result = await delegate({
|
|
26635
26639
|
task,
|
|
@@ -26691,7 +26695,7 @@ async function aggregateResults(chunkResults2, aggregation, extractionPrompt, op
|
|
|
26691
26695
|
${stripResultTags(r.result)}`).join("\n\n");
|
|
26692
26696
|
const completionNote = `
|
|
26693
26697
|
|
|
26694
|
-
When done,
|
|
26698
|
+
When done, provide your final answer directly.`;
|
|
26695
26699
|
const aggregationPrompts = {
|
|
26696
26700
|
summarize: `Synthesize these analyses into a comprehensive summary. Combine related findings, remove redundancy, and present a coherent overview.
|
|
26697
26701
|
|
|
@@ -26785,7 +26789,7 @@ For example, if looking for customer data:
|
|
|
26785
26789
|
STEP 3: CREATE THE FINAL PLAN
|
|
26786
26790
|
Based on your experiments, output the BEST search strategy.
|
|
26787
26791
|
|
|
26788
|
-
|
|
26792
|
+
Provide your answer in this EXACT format:
|
|
26789
26793
|
|
|
26790
26794
|
SEARCH_QUERY: <the query that WORKED in your experiments - use OR for multiple terms>
|
|
26791
26795
|
AGGREGATION: <summarize | list_unique | count | group_by>
|
|
@@ -26851,7 +26855,7 @@ Your answer should:
|
|
|
26851
26855
|
|
|
26852
26856
|
Format your response as a well-structured document that fully answers: "${question}"
|
|
26853
26857
|
|
|
26854
|
-
When done,
|
|
26858
|
+
When done, provide your final answer directly.`;
|
|
26855
26859
|
try {
|
|
26856
26860
|
const result = await delegate({
|
|
26857
26861
|
task: synthesisTask,
|
|
@@ -27030,6 +27034,34 @@ function createMessagePreview(message, charsPerSide = 200) {
|
|
|
27030
27034
|
const end = message.substring(message.length - charsPerSide);
|
|
27031
27035
|
return `${start}...${end}`;
|
|
27032
27036
|
}
|
|
27037
|
+
function detectStuckResponse(response) {
|
|
27038
|
+
if (!response || typeof response !== "string") {
|
|
27039
|
+
return false;
|
|
27040
|
+
}
|
|
27041
|
+
const stuckPatterns = [
|
|
27042
|
+
/\bi\s+cannot\s+proceed\b/i,
|
|
27043
|
+
/\bi\s+can['']t\s+(?:proceed|continue|move\s+forward)\b/i,
|
|
27044
|
+
/\bunable\s+to\s+(?:proceed|continue|complete)\b/i,
|
|
27045
|
+
/\bblocked\b.*\b(?:proceed|continue)\b/i,
|
|
27046
|
+
/\bneed\s+(?:the|an?)\s+\w+(?:\s+\w+)?\s+to\s+(?:proceed|continue)\b/i,
|
|
27047
|
+
/\brequire[sd]?\s+(?:the|an?)\s+\w+\b.*\bto\s+(?:proceed|continue)\b/i,
|
|
27048
|
+
/\bmissing\s+(?:required|necessary|essential)\b/i,
|
|
27049
|
+
/\bdeadlock\b/i,
|
|
27050
|
+
/\bwe\s+are\s+in\s+a\s+loop\b/i,
|
|
27051
|
+
/\bstuck\s+in\s+a\s+loop\b/i,
|
|
27052
|
+
/\bi\s+(?:have|['']ve)\s+(?:explained|stated|mentioned)\s+(?:this|the\s+situation|it)\s+(?:multiple|several)\s+times\b/i,
|
|
27053
|
+
/\bi\s+(?:cannot|can['']t|could\s+not|couldn['']t)\s+(?:find|locate|get|retrieve|obtain)\s+(?:the|this|that|an?)\b/i,
|
|
27054
|
+
/\bno\s+way\s+to\s+(?:find|get|obtain|retrieve)\b/i,
|
|
27055
|
+
/\bi\s+(?:have|['']ve)\s+exhausted\s+(?:all|my)\s+(?:available\s+)?(?:options|methods|approaches)\b/i,
|
|
27056
|
+
/\bneither\s+of\s+these\s+methods\b/i
|
|
27057
|
+
];
|
|
27058
|
+
for (const pattern of stuckPatterns) {
|
|
27059
|
+
if (pattern.test(response)) {
|
|
27060
|
+
return true;
|
|
27061
|
+
}
|
|
27062
|
+
}
|
|
27063
|
+
return false;
|
|
27064
|
+
}
|
|
27033
27065
|
function parseTargets(targets) {
|
|
27034
27066
|
if (!targets || typeof targets !== "string") {
|
|
27035
27067
|
return [];
|
|
@@ -27540,7 +27572,7 @@ var init_vercel = __esm({
|
|
|
27540
27572
|
if (debug) {
|
|
27541
27573
|
console.error(`[DEDUP] Blocked duplicate search: "${searchQuery}" (path: "${searchPath}")`);
|
|
27542
27574
|
}
|
|
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
|
|
27575
|
+
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
27576
|
}
|
|
27545
27577
|
previousSearches.add(searchKey);
|
|
27546
27578
|
paginationCounts.set(searchKey, 0);
|
|
@@ -27551,7 +27583,7 @@ var init_vercel = __esm({
|
|
|
27551
27583
|
if (debug) {
|
|
27552
27584
|
console.error(`[DEDUP] Blocked excessive pagination (page ${pageCount}/${MAX_PAGES_PER_QUERY}): "${searchQuery}" in "${searchPath}"`);
|
|
27553
27585
|
}
|
|
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
|
|
27586
|
+
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
27587
|
}
|
|
27556
27588
|
}
|
|
27557
27589
|
try {
|
|
@@ -27590,7 +27622,7 @@ var init_vercel = __esm({
|
|
|
27590
27622
|
bashConfig: null,
|
|
27591
27623
|
architectureFileName: options.architectureFileName || null,
|
|
27592
27624
|
promptType: "code-searcher",
|
|
27593
|
-
allowedTools: ["search", "extract", "listFiles"
|
|
27625
|
+
allowedTools: ["search", "extract", "listFiles"],
|
|
27594
27626
|
searchDelegate: false,
|
|
27595
27627
|
schema: CODE_SEARCH_SCHEMA,
|
|
27596
27628
|
parentAbortSignal: options.parentAbortSignal || null
|
|
@@ -27761,14 +27793,15 @@ var init_vercel = __esm({
|
|
|
27761
27793
|
const parsedTargets = parseTargets(targets);
|
|
27762
27794
|
extractFiles = parsedTargets.map((target) => resolveTargetPath(target, effectiveCwd));
|
|
27763
27795
|
if (options.allowedFolders && options.allowedFolders.length > 0) {
|
|
27796
|
+
const { join: pathJoin, sep: pathSep } = await import("path");
|
|
27764
27797
|
extractFiles = extractFiles.map((target) => {
|
|
27765
27798
|
const { filePart, suffix } = splitTargetSuffix(target);
|
|
27766
27799
|
if ((0, import_fs4.existsSync)(filePart)) return target;
|
|
27767
|
-
const cwdPrefix = effectiveCwd.endsWith(
|
|
27800
|
+
const cwdPrefix = effectiveCwd.endsWith(pathSep) ? effectiveCwd : effectiveCwd + pathSep;
|
|
27768
27801
|
const relativePart = filePart.startsWith(cwdPrefix) ? filePart.slice(cwdPrefix.length) : null;
|
|
27769
27802
|
if (relativePart) {
|
|
27770
27803
|
for (const folder of options.allowedFolders) {
|
|
27771
|
-
const candidate = folder
|
|
27804
|
+
const candidate = pathJoin(folder, relativePart);
|
|
27772
27805
|
if ((0, import_fs4.existsSync)(candidate)) {
|
|
27773
27806
|
if (debug) console.error(`[extract] Auto-fixed path: ${filePart} \u2192 ${candidate}`);
|
|
27774
27807
|
return candidate + suffix;
|
|
@@ -27776,11 +27809,12 @@ var init_vercel = __esm({
|
|
|
27776
27809
|
}
|
|
27777
27810
|
}
|
|
27778
27811
|
for (const folder of options.allowedFolders) {
|
|
27779
|
-
const folderPrefix = folder.endsWith(
|
|
27780
|
-
const
|
|
27812
|
+
const folderPrefix = folder.endsWith(pathSep) ? folder : folder + pathSep;
|
|
27813
|
+
const sepEscaped = pathSep === "\\" ? "\\\\" : pathSep;
|
|
27814
|
+
const wsParent = folderPrefix.replace(new RegExp("[^" + sepEscaped + "]+" + sepEscaped + "$"), "");
|
|
27781
27815
|
if (filePart.startsWith(wsParent)) {
|
|
27782
27816
|
const tail = filePart.slice(wsParent.length);
|
|
27783
|
-
const candidate = folderPrefix
|
|
27817
|
+
const candidate = pathJoin(folderPrefix, tail);
|
|
27784
27818
|
if (candidate !== filePart && (0, import_fs4.existsSync)(candidate)) {
|
|
27785
27819
|
if (debug) console.error(`[extract] Auto-fixed path via workspace: ${filePart} \u2192 ${candidate}`);
|
|
27786
27820
|
return candidate + suffix;
|
|
@@ -49650,7 +49684,7 @@ For each pending/in_progress task, either:
|
|
|
49650
49684
|
- Complete it: call task tool with action="complete", id="task-X"
|
|
49651
49685
|
- Cancel it: call task tool with action="update", id="task-X", status="cancelled"
|
|
49652
49686
|
|
|
49653
|
-
After all tasks are resolved,
|
|
49687
|
+
After all tasks are resolved, provide your final answer.`;
|
|
49654
49688
|
}
|
|
49655
49689
|
function createTaskTool(options = {}) {
|
|
49656
49690
|
const { taskManager, tracer, debug = false } = options;
|
|
@@ -49900,13 +49934,13 @@ Tasks = logical units of work, not files or steps.
|
|
|
49900
49934
|
|
|
49901
49935
|
1. **Plan**: Call task tool with action="create" and a tasks array up front
|
|
49902
49936
|
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
|
|
49937
|
+
3. **Finish**: All tasks must be "completed" or "cancelled" before providing your final answer.
|
|
49904
49938
|
|
|
49905
49939
|
## Rules
|
|
49906
49940
|
|
|
49907
49941
|
- Dependencies are enforced: a task cannot start until its dependencies are completed
|
|
49908
49942
|
- Circular dependencies are rejected
|
|
49909
|
-
-
|
|
49943
|
+
- Completion is blocked while tasks remain unresolved
|
|
49910
49944
|
`;
|
|
49911
49945
|
}
|
|
49912
49946
|
});
|
|
@@ -86773,68 +86807,9 @@ var require_ajv = __commonJS({
|
|
|
86773
86807
|
});
|
|
86774
86808
|
|
|
86775
86809
|
// 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
86810
|
function generateSchemaInstructions(schema, options = {}) {
|
|
86836
86811
|
const { debug = false } = options;
|
|
86837
|
-
let instructions = "\n\nIMPORTANT: When you provide your final answer
|
|
86812
|
+
let instructions = "\n\nIMPORTANT: When you provide your final answer, you MUST format it as valid JSON matching this schema:\n\n";
|
|
86838
86813
|
try {
|
|
86839
86814
|
const parsedSchema = typeof schema === "string" ? JSON.parse(schema) : schema;
|
|
86840
86815
|
instructions += `${JSON.stringify(parsedSchema, null, 2)}
|
|
@@ -86848,7 +86823,7 @@ function generateSchemaInstructions(schema, options = {}) {
|
|
|
86848
86823
|
|
|
86849
86824
|
`;
|
|
86850
86825
|
}
|
|
86851
|
-
instructions += "Your response
|
|
86826
|
+
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
86827
|
return instructions;
|
|
86853
86828
|
}
|
|
86854
86829
|
function enforceNoAdditionalProperties(schema) {
|
|
@@ -87345,65 +87320,6 @@ function tryExtractValidJsonPrefix(response, options = {}) {
|
|
|
87345
87320
|
return null;
|
|
87346
87321
|
}
|
|
87347
87322
|
}
|
|
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
87323
|
function isJsonSchema(schema) {
|
|
87408
87324
|
if (!schema || typeof schema !== "string") {
|
|
87409
87325
|
return false;
|
|
@@ -87545,18 +87461,18 @@ function createJsonCorrectionPrompt(invalidResponse, schema, errorOrValidation,
|
|
|
87545
87461
|
const strengthLevels = [
|
|
87546
87462
|
{
|
|
87547
87463
|
prefix: "CRITICAL JSON ERROR:",
|
|
87548
|
-
instruction: "You MUST fix this and respond
|
|
87549
|
-
emphasis: "
|
|
87464
|
+
instruction: "You MUST fix this and respond with ONLY valid JSON.",
|
|
87465
|
+
emphasis: "Respond with ONLY the corrected JSON. No explanatory text, no markdown, no code blocks."
|
|
87550
87466
|
},
|
|
87551
87467
|
{
|
|
87552
87468
|
prefix: "URGENT - JSON PARSING FAILED:",
|
|
87553
|
-
instruction: "This is your second chance.
|
|
87554
|
-
emphasis: "ABSOLUTELY NO explanatory text or formatting.
|
|
87469
|
+
instruction: "This is your second chance. Respond with valid JSON that can be parsed by JSON.parse().",
|
|
87470
|
+
emphasis: "ABSOLUTELY NO explanatory text or formatting. Respond with ONLY raw JSON."
|
|
87555
87471
|
},
|
|
87556
87472
|
{
|
|
87557
87473
|
prefix: "FINAL ATTEMPT - CRITICAL JSON ERROR:",
|
|
87558
|
-
instruction: "This is the final retry. You MUST
|
|
87559
|
-
emphasis: 'CORRECT:
|
|
87474
|
+
instruction: "This is the final retry. You MUST respond with ONLY raw JSON.",
|
|
87475
|
+
emphasis: 'CORRECT: {"key": "value"}\nWRONG: Here is the JSON: {"key": "value"}\nWRONG: ```json{"key": "value"}```'
|
|
87560
87476
|
}
|
|
87561
87477
|
];
|
|
87562
87478
|
const level = Math.min(retryCount, strengthLevels.length - 1);
|
|
@@ -87610,28 +87526,6 @@ ${currentLevel.example}
|
|
|
87610
87526
|
Return ONLY the JSON data object/array that follows the schema structure. NO schema definitions, NO explanations, NO markdown formatting.`;
|
|
87611
87527
|
return prompt;
|
|
87612
87528
|
}
|
|
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
87529
|
function extractMermaidFromJson(response) {
|
|
87636
87530
|
if (!response || typeof response !== "string") {
|
|
87637
87531
|
return { diagrams: [], jsonPaths: [], parsedJson: null };
|
|
@@ -87763,28 +87657,6 @@ ${modifiedJsonString}
|
|
|
87763
87657
|
}
|
|
87764
87658
|
return modifiedJsonString;
|
|
87765
87659
|
}
|
|
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
87660
|
function replaceSingleMermaidDiagramInResponse(response, originalDiagram, newContent) {
|
|
87789
87661
|
if (!originalDiagram) {
|
|
87790
87662
|
return response;
|
|
@@ -87869,45 +87741,6 @@ async function validateMermaidResponse(response) {
|
|
|
87869
87741
|
errors: errors.length > 0 ? errors : void 0
|
|
87870
87742
|
};
|
|
87871
87743
|
}
|
|
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
87744
|
async function tryMaidAutoFix(diagramContent, options = {}) {
|
|
87912
87745
|
const { debug = false } = options;
|
|
87913
87746
|
try {
|
|
@@ -88217,7 +88050,7 @@ async function validateAndFixMermaidResponse(response, options = {}) {
|
|
|
88217
88050
|
};
|
|
88218
88051
|
}
|
|
88219
88052
|
}
|
|
88220
|
-
var import_ajv, HTML_ENTITY_MAP, sessionIdCounter,
|
|
88053
|
+
var import_ajv, HTML_ENTITY_MAP, sessionIdCounter, MermaidFixingAgent;
|
|
88221
88054
|
var init_schemaUtils = __esm({
|
|
88222
88055
|
"src/agent/schemaUtils.js"() {
|
|
88223
88056
|
"use strict";
|
|
@@ -88235,172 +88068,6 @@ var init_schemaUtils = __esm({
|
|
|
88235
88068
|
" ": " "
|
|
88236
88069
|
};
|
|
88237
88070
|
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
88071
|
MermaidFixingAgent = class {
|
|
88405
88072
|
constructor(options = {}) {
|
|
88406
88073
|
this.ProbeAgent = null;
|
|
@@ -88644,7 +88311,7 @@ When reviewing code:
|
|
|
88644
88311
|
"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
88312
|
"engineer": `You are a senior engineer focused on software architecture and design.
|
|
88646
88313
|
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
|
|
88314
|
+
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
88315
|
|
|
88649
88316
|
# Tone and Style
|
|
88650
88317
|
- Be concise and direct. Explain your approach briefly before implementing, then let the code speak for itself.
|
|
@@ -88667,7 +88334,7 @@ If the solution is clear, you can jump to implementation right away. If not, ask
|
|
|
88667
88334
|
When the request has **multiple distinct goals** (e.g. "Fix bug A AND add feature B"), use the task tool to track them:
|
|
88668
88335
|
- Call the task tool with action="create" and a tasks array. Each task must have an "id" field.
|
|
88669
88336
|
- Update task status to "in_progress" when starting and "completed" when done.
|
|
88670
|
-
- All tasks must be completed or cancelled before
|
|
88337
|
+
- All tasks must be completed or cancelled before providing your final answer.
|
|
88671
88338
|
- Stay flexible \u2014 add, remove, or reorganize tasks as your understanding changes.
|
|
88672
88339
|
|
|
88673
88340
|
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.
|
|
@@ -97895,14 +97562,6 @@ var init_FallbackManager = __esm({
|
|
|
97895
97562
|
});
|
|
97896
97563
|
|
|
97897
97564
|
// src/agent/contextCompactor.js
|
|
97898
|
-
var contextCompactor_exports = {};
|
|
97899
|
-
__export(contextCompactor_exports, {
|
|
97900
|
-
calculateCompactionStats: () => calculateCompactionStats,
|
|
97901
|
-
compactMessages: () => compactMessages,
|
|
97902
|
-
handleContextLimitError: () => handleContextLimitError,
|
|
97903
|
-
identifyMessageSegments: () => identifyMessageSegments,
|
|
97904
|
-
isContextLimitError: () => isContextLimitError
|
|
97905
|
-
});
|
|
97906
97565
|
function isContextLimitError(error40) {
|
|
97907
97566
|
if (!error40) return false;
|
|
97908
97567
|
const errorMessage = (typeof error40 === "string" ? error40 : error40?.message || "").toLowerCase();
|
|
@@ -97924,9 +97583,15 @@ function messageContainsCompletion(msg) {
|
|
|
97924
97583
|
}
|
|
97925
97584
|
if (Array.isArray(msg.content)) {
|
|
97926
97585
|
if (msg.content.some((p) => p.type === "tool-call" && p.toolName === "attempt_completion")) return true;
|
|
97586
|
+
const hasToolCalls = msg.content.some((p) => p.type === "tool-call");
|
|
97587
|
+
const hasText = msg.content.some((p) => p.type === "text" && p.text?.trim());
|
|
97588
|
+
if (!hasToolCalls && hasText) return true;
|
|
97927
97589
|
}
|
|
97928
97590
|
const text = typeof msg.content === "string" ? msg.content : "";
|
|
97929
|
-
|
|
97591
|
+
if (text.includes("attempt_completion")) return true;
|
|
97592
|
+
const hasNoToolCalls = !Array.isArray(msg.toolInvocations) && !Array.isArray(msg.tool_calls);
|
|
97593
|
+
if (hasNoToolCalls && text.trim().length > 0) return true;
|
|
97594
|
+
return false;
|
|
97930
97595
|
}
|
|
97931
97596
|
function identifyMessageSegments(messages) {
|
|
97932
97597
|
const segments = [];
|
|
@@ -99696,8 +99361,8 @@ function debugTruncate(s, limit = 200) {
|
|
|
99696
99361
|
function debugLogToolResults(toolResults) {
|
|
99697
99362
|
if (!toolResults || toolResults.length === 0) return;
|
|
99698
99363
|
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
|
|
99364
|
+
const argsStr = tr.args != null ? JSON.stringify(tr.args) : "<no args>";
|
|
99365
|
+
const resultStr = tr.result != null ? typeof tr.result === "string" ? tr.result : JSON.stringify(tr.result) : "<no result>";
|
|
99701
99366
|
console.log(`[DEBUG] tool: ${tr.toolName} | args: ${debugTruncate(argsStr)} | result: ${debugTruncate(resultStr)}`);
|
|
99702
99367
|
}
|
|
99703
99368
|
}
|
|
@@ -99803,7 +99468,7 @@ var init_ProbeAgent = __esm({
|
|
|
99803
99468
|
* @param {Array<Object>} [options.fallback.providers] - List of provider configurations for custom fallback
|
|
99804
99469
|
* @param {boolean} [options.fallback.stopOnSuccess=true] - Stop on first success
|
|
99805
99470
|
* @param {number} [options.fallback.maxTotalAttempts=10] - Maximum total attempts across all providers
|
|
99806
|
-
* @param {string} [options.completionPrompt] - Custom prompt to run after
|
|
99471
|
+
* @param {string} [options.completionPrompt] - Custom prompt to run after completion for validation/review (runs before mermaid/JSON validation)
|
|
99807
99472
|
* @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
99473
|
* @param {number} [options.requestTimeout] - Timeout in ms for AI requests (default: 120000 or REQUEST_TIMEOUT env var). Used to abort hung requests.
|
|
99809
99474
|
* @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 +100620,11 @@ var init_ProbeAgent = __esm({
|
|
|
100955
100620
|
* - Delegate tool param injection
|
|
100956
100621
|
*
|
|
100957
100622
|
* @param {Object} options - Options from the answer() call
|
|
100958
|
-
* @param {Function} onComplete - Callback when attempt_completion is called (receives result string)
|
|
100959
100623
|
* @param {Object} context - Execution context { maxIterations, currentMessages }
|
|
100960
100624
|
* @returns {Object} Tools object for streamText()
|
|
100961
100625
|
* @private
|
|
100962
100626
|
*/
|
|
100963
|
-
_buildNativeTools(options,
|
|
100627
|
+
_buildNativeTools(options, context = {}) {
|
|
100964
100628
|
const { maxIterations = 30 } = context;
|
|
100965
100629
|
const nativeTools = {};
|
|
100966
100630
|
const isToolAllowed = (toolName) => this.allowedTools.isEnabled(toolName);
|
|
@@ -101110,16 +100774,6 @@ var init_ProbeAgent = __esm({
|
|
|
101110
100774
|
});
|
|
101111
100775
|
};
|
|
101112
100776
|
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
100777
|
return nativeTools;
|
|
101124
100778
|
}
|
|
101125
100779
|
for (const [toolName, toolImpl] of Object.entries(this.toolImplementations)) {
|
|
@@ -101130,28 +100784,6 @@ var init_ProbeAgent = __esm({
|
|
|
101130
100784
|
nativeTools[toolName] = wrapTool(toolName, schema, description, toolImpl.execute);
|
|
101131
100785
|
}
|
|
101132
100786
|
}
|
|
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
100787
|
if (this.mcpBridge && !options._disableTools) {
|
|
101156
100788
|
const mcpTools = this.mcpBridge.getVercelTools(this._filterMcpTools(this.mcpBridge.getToolNames()));
|
|
101157
100789
|
for (const [name15, mcpTool] of Object.entries(mcpTools)) {
|
|
@@ -102035,7 +101667,7 @@ Follow these instructions carefully:
|
|
|
102035
101667
|
2. Use the available tools step-by-step to fulfill the request.
|
|
102036
101668
|
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
101669
|
4. Ensure to get really deep and understand the full picture before answering.
|
|
102038
|
-
5. Once the task is fully completed,
|
|
101670
|
+
5. Once the task is fully completed, provide your final answer directly as text.
|
|
102039
101671
|
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
101672
|
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
101673
|
7. When modifying files, choose the appropriate tool:
|
|
@@ -102213,7 +101845,7 @@ You are working with a workspace. Available paths: ${workspaceDesc}
|
|
|
102213
101845
|
});
|
|
102214
101846
|
const systemMessage = await this.getSystemMessage();
|
|
102215
101847
|
let userMessage = { role: "user", content: message.trim() };
|
|
102216
|
-
if (options.schema && !options._schemaFormatted) {
|
|
101848
|
+
if (options.schema && !options._schemaFormatted && !options._disableTools) {
|
|
102217
101849
|
const schemaInstructions = generateSchemaInstructions(options.schema, { debug: this.debug });
|
|
102218
101850
|
userMessage.content = message.trim() + schemaInstructions;
|
|
102219
101851
|
}
|
|
@@ -102245,8 +101877,17 @@ You are working with a workspace. Available paths: ${workspaceDesc}
|
|
|
102245
101877
|
userMessage
|
|
102246
101878
|
];
|
|
102247
101879
|
}
|
|
101880
|
+
if (this.history.length > 0) {
|
|
101881
|
+
const compacted = compactMessages(currentMessages, { keepLastSegment: true, minSegmentsToKeep: 1 });
|
|
101882
|
+
if (compacted.length < currentMessages.length) {
|
|
101883
|
+
const stats = calculateCompactionStats(currentMessages, compacted);
|
|
101884
|
+
if (this.debug) {
|
|
101885
|
+
console.log(`[DEBUG] Proactive history compaction: ${currentMessages.length} \u2192 ${compacted.length} messages (${stats.reductionPercent}% reduction, ~${stats.tokensSaved} tokens saved)`);
|
|
101886
|
+
}
|
|
101887
|
+
currentMessages = compacted;
|
|
101888
|
+
}
|
|
101889
|
+
}
|
|
102248
101890
|
let currentIteration = 0;
|
|
102249
|
-
let completionAttempted = false;
|
|
102250
101891
|
let finalResult = "I was unable to complete your request due to reaching the maximum number of tool iterations.";
|
|
102251
101892
|
const baseMaxIterations = options._maxIterationsOverride || this.maxIterations || MAX_TOOL_ITERATIONS;
|
|
102252
101893
|
const maxIterations = options._maxIterationsOverride ? baseMaxIterations : options.schema ? baseMaxIterations + 4 : baseMaxIterations;
|
|
@@ -102362,12 +102003,8 @@ You are working with a workspace. Available paths: ${workspaceDesc}
|
|
|
102362
102003
|
console.log(`[DEBUG] Schema provided, using extended iteration limit: ${maxIterations} (base: ${baseMaxIterations})`);
|
|
102363
102004
|
}
|
|
102364
102005
|
}
|
|
102365
|
-
let completionResult = null;
|
|
102366
102006
|
const toolContext = { maxIterations, currentIteration: 0, currentMessages };
|
|
102367
|
-
const tools2 = this._buildNativeTools(options,
|
|
102368
|
-
completionResult = result;
|
|
102369
|
-
completionAttempted = true;
|
|
102370
|
-
}, toolContext);
|
|
102007
|
+
const tools2 = this._buildNativeTools(options, toolContext);
|
|
102371
102008
|
if (this.debug) {
|
|
102372
102009
|
const toolNames = Object.keys(tools2);
|
|
102373
102010
|
console.log(`[DEBUG] Agent tools registered (${toolNames.length}): ${toolNames.join(", ")}`);
|
|
@@ -102381,6 +102018,8 @@ You are working with a workspace. Available paths: ${workspaceDesc}
|
|
|
102381
102018
|
maxResponseTokens = 32e3;
|
|
102382
102019
|
}
|
|
102383
102020
|
}
|
|
102021
|
+
let completionPromptInjected = false;
|
|
102022
|
+
let preCompletionResult = null;
|
|
102384
102023
|
let compactionAttempted = false;
|
|
102385
102024
|
while (true) {
|
|
102386
102025
|
try {
|
|
@@ -102389,19 +102028,103 @@ You are working with a workspace. Available paths: ${workspaceDesc}
|
|
|
102389
102028
|
model: this.provider ? this.provider(this.model) : this.model,
|
|
102390
102029
|
messages: messagesForAI,
|
|
102391
102030
|
tools: tools2,
|
|
102392
|
-
stopWhen: (
|
|
102031
|
+
stopWhen: ({ steps }) => {
|
|
102032
|
+
if (steps.length >= maxIterations) return true;
|
|
102033
|
+
const lastStep = steps[steps.length - 1];
|
|
102034
|
+
const modelWantsToStop = lastStep?.finishReason === "stop" && (!lastStep?.toolCalls || lastStep.toolCalls.length === 0);
|
|
102035
|
+
if (modelWantsToStop) {
|
|
102036
|
+
if (this.enableTasks && this.taskManager?.hasIncompleteTasks()) {
|
|
102037
|
+
const highIterationCount = steps.length > maxIterations * 0.7;
|
|
102038
|
+
if (!highIterationCount) return false;
|
|
102039
|
+
}
|
|
102040
|
+
if (this.completionPrompt && !options._completionPromptProcessed && !completionPromptInjected) {
|
|
102041
|
+
preCompletionResult = lastStep.text || null;
|
|
102042
|
+
return false;
|
|
102043
|
+
}
|
|
102044
|
+
}
|
|
102045
|
+
let trailingNoTool = 0;
|
|
102046
|
+
for (let i = steps.length - 1; i >= 0; i--) {
|
|
102047
|
+
if (!steps[i].toolCalls?.length) trailingNoTool++;
|
|
102048
|
+
else break;
|
|
102049
|
+
}
|
|
102050
|
+
if (trailingNoTool >= 5) return true;
|
|
102051
|
+
if (trailingNoTool >= 3) {
|
|
102052
|
+
const recentTexts = steps.slice(-3).map((s) => s.text);
|
|
102053
|
+
if (recentTexts.every((t) => t && t === recentTexts[0])) return true;
|
|
102054
|
+
if (recentTexts.every((t) => detectStuckResponse(t))) return true;
|
|
102055
|
+
}
|
|
102056
|
+
return false;
|
|
102057
|
+
},
|
|
102058
|
+
prepareStep: ({ steps, stepNumber }) => {
|
|
102059
|
+
if (stepNumber === maxIterations - 1) {
|
|
102060
|
+
return {
|
|
102061
|
+
toolChoice: "none"
|
|
102062
|
+
};
|
|
102063
|
+
}
|
|
102064
|
+
const lastStep = steps[steps.length - 1];
|
|
102065
|
+
const modelJustStopped = lastStep?.finishReason === "stop" && (!lastStep?.toolCalls || lastStep.toolCalls.length === 0);
|
|
102066
|
+
if (modelJustStopped) {
|
|
102067
|
+
if (this.enableTasks && this.taskManager?.hasIncompleteTasks()) {
|
|
102068
|
+
const taskSummary = this.taskManager.getTaskSummary();
|
|
102069
|
+
const blockedMessage = createTaskCompletionBlockedMessage(taskSummary);
|
|
102070
|
+
return {
|
|
102071
|
+
userMessage: blockedMessage
|
|
102072
|
+
};
|
|
102073
|
+
}
|
|
102074
|
+
if (this.completionPrompt && !options._completionPromptProcessed && !completionPromptInjected) {
|
|
102075
|
+
completionPromptInjected = true;
|
|
102076
|
+
const resultToReview = lastStep.text || preCompletionResult || "";
|
|
102077
|
+
if (this.debug) {
|
|
102078
|
+
console.log("[DEBUG] Injecting completion prompt into main loop via prepareStep...");
|
|
102079
|
+
}
|
|
102080
|
+
if (this.tracer) {
|
|
102081
|
+
this.tracer.recordEvent("completion_prompt.started", {
|
|
102082
|
+
"completion_prompt.original_result_length": resultToReview.length
|
|
102083
|
+
});
|
|
102084
|
+
}
|
|
102085
|
+
const completionPromptMessage = `${this.completionPrompt}
|
|
102086
|
+
|
|
102087
|
+
Here is the result to review:
|
|
102088
|
+
<result>
|
|
102089
|
+
${resultToReview}
|
|
102090
|
+
</result>
|
|
102091
|
+
|
|
102092
|
+
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).`;
|
|
102093
|
+
return {
|
|
102094
|
+
userMessage: completionPromptMessage
|
|
102095
|
+
};
|
|
102096
|
+
}
|
|
102097
|
+
}
|
|
102098
|
+
return void 0;
|
|
102099
|
+
},
|
|
102393
102100
|
maxTokens: maxResponseTokens,
|
|
102394
102101
|
temperature: 0.3,
|
|
102395
|
-
onStepFinish: (
|
|
102102
|
+
onStepFinish: (stepResult) => {
|
|
102103
|
+
const { toolResults, toolCalls, text, reasoningText, finishReason, usage } = stepResult;
|
|
102396
102104
|
currentIteration++;
|
|
102397
102105
|
toolContext.currentIteration = currentIteration;
|
|
102398
102106
|
if (this.tracer) {
|
|
102399
|
-
|
|
102107
|
+
const stepEvent = {
|
|
102400
102108
|
"iteration": currentIteration,
|
|
102401
102109
|
"max_iterations": maxIterations,
|
|
102402
102110
|
"finish_reason": finishReason,
|
|
102403
102111
|
"has_tool_calls": !!(toolResults && toolResults.length > 0)
|
|
102404
|
-
}
|
|
102112
|
+
};
|
|
102113
|
+
if (text) {
|
|
102114
|
+
stepEvent["ai.text"] = text.substring(0, 1e4);
|
|
102115
|
+
stepEvent["ai.text.length"] = text.length;
|
|
102116
|
+
}
|
|
102117
|
+
if (reasoningText) {
|
|
102118
|
+
stepEvent["ai.reasoning"] = reasoningText.substring(0, 1e4);
|
|
102119
|
+
stepEvent["ai.reasoning.length"] = reasoningText.length;
|
|
102120
|
+
}
|
|
102121
|
+
if (toolCalls && toolCalls.length > 0) {
|
|
102122
|
+
stepEvent["ai.tool_calls"] = toolCalls.map((tc) => ({
|
|
102123
|
+
name: tc.toolName,
|
|
102124
|
+
args: JSON.stringify(tc.args || {}).substring(0, 2e3)
|
|
102125
|
+
}));
|
|
102126
|
+
}
|
|
102127
|
+
this.tracer.addEvent("iteration.step", stepEvent);
|
|
102405
102128
|
}
|
|
102406
102129
|
if (usage) {
|
|
102407
102130
|
this.tokenCounter.recordUsage(usage);
|
|
@@ -102411,10 +102134,32 @@ You are working with a workspace. Available paths: ${workspaceDesc}
|
|
|
102411
102134
|
}
|
|
102412
102135
|
if (this.debug) {
|
|
102413
102136
|
console.log(`[DEBUG] Step ${currentIteration}/${maxIterations} finished (reason: ${finishReason}, tools: ${toolResults?.length || 0})`);
|
|
102137
|
+
if (text) {
|
|
102138
|
+
console.log(`[DEBUG] model text: ${debugTruncate(text)}`);
|
|
102139
|
+
}
|
|
102140
|
+
if (reasoningText) {
|
|
102141
|
+
console.log(`[DEBUG] reasoning: ${debugTruncate(reasoningText)}`);
|
|
102142
|
+
}
|
|
102414
102143
|
debugLogToolResults(toolResults);
|
|
102415
102144
|
}
|
|
102416
102145
|
}
|
|
102417
102146
|
};
|
|
102147
|
+
const hasActiveTools = Object.keys(tools2).length > 0;
|
|
102148
|
+
if (options.schema && !hasActiveTools) {
|
|
102149
|
+
try {
|
|
102150
|
+
const parsedSchema = typeof options.schema === "string" ? JSON.parse(options.schema) : options.schema;
|
|
102151
|
+
if (isJsonSchema(options.schema)) {
|
|
102152
|
+
streamOptions.output = import_ai6.Output.object({ schema: (0, import_ai6.jsonSchema)(parsedSchema) });
|
|
102153
|
+
if (this.debug) {
|
|
102154
|
+
console.log(`[DEBUG] Native JSON schema output enabled (no active tools)`);
|
|
102155
|
+
}
|
|
102156
|
+
}
|
|
102157
|
+
} catch (e) {
|
|
102158
|
+
if (this.debug) {
|
|
102159
|
+
console.log(`[DEBUG] Failed to set native JSON schema output: ${e.message}`);
|
|
102160
|
+
}
|
|
102161
|
+
}
|
|
102162
|
+
}
|
|
102418
102163
|
const providerOpts = this._buildThinkingProviderOptions(maxResponseTokens);
|
|
102419
102164
|
if (providerOpts) {
|
|
102420
102165
|
streamOptions.providerOptions = providerOpts;
|
|
@@ -102424,7 +102169,7 @@ You are working with a workspace. Available paths: ${workspaceDesc}
|
|
|
102424
102169
|
const finalText = await result.text;
|
|
102425
102170
|
if (this.debug) {
|
|
102426
102171
|
const steps = await result.steps;
|
|
102427
|
-
console.log(`[DEBUG] streamText completed: ${steps?.length || 0} steps, finalText=${finalText?.length || 0} chars
|
|
102172
|
+
console.log(`[DEBUG] streamText completed: ${steps?.length || 0} steps, finalText=${finalText?.length || 0} chars`);
|
|
102428
102173
|
}
|
|
102429
102174
|
const usage = await result.usage;
|
|
102430
102175
|
if (usage) {
|
|
@@ -102448,18 +102193,24 @@ You are working with a workspace. Available paths: ${workspaceDesc}
|
|
|
102448
102193
|
} else {
|
|
102449
102194
|
aiResult = await executeAIRequest();
|
|
102450
102195
|
}
|
|
102451
|
-
if (
|
|
102452
|
-
|
|
102453
|
-
|
|
102454
|
-
|
|
102455
|
-
|
|
102456
|
-
|
|
102457
|
-
|
|
102196
|
+
if (options.schema && streamOptions.output) {
|
|
102197
|
+
try {
|
|
102198
|
+
const outputObject = await aiResult.result.output;
|
|
102199
|
+
if (outputObject) {
|
|
102200
|
+
finalResult = JSON.stringify(outputObject);
|
|
102201
|
+
} else if (aiResult.finalText) {
|
|
102202
|
+
finalResult = aiResult.finalText;
|
|
102203
|
+
}
|
|
102204
|
+
} catch (e) {
|
|
102205
|
+
if (this.debug) {
|
|
102206
|
+
console.log(`[DEBUG] Native JSON output failed, falling back to text: ${e.message}`);
|
|
102207
|
+
}
|
|
102208
|
+
if (aiResult.finalText) {
|
|
102209
|
+
finalResult = aiResult.finalText;
|
|
102458
102210
|
}
|
|
102459
102211
|
}
|
|
102460
102212
|
} else if (aiResult.finalText) {
|
|
102461
102213
|
finalResult = aiResult.finalText;
|
|
102462
|
-
completionAttempted = true;
|
|
102463
102214
|
}
|
|
102464
102215
|
const resultMessages = await aiResult.result.response?.messages;
|
|
102465
102216
|
if (resultMessages) {
|
|
@@ -102467,6 +102218,75 @@ You are working with a workspace. Available paths: ${workspaceDesc}
|
|
|
102467
102218
|
currentMessages.push(msg);
|
|
102468
102219
|
}
|
|
102469
102220
|
}
|
|
102221
|
+
if (this.completionPrompt && !options._completionPromptProcessed && !completionPromptInjected && finalResult) {
|
|
102222
|
+
completionPromptInjected = true;
|
|
102223
|
+
preCompletionResult = finalResult;
|
|
102224
|
+
if (this.debug) {
|
|
102225
|
+
console.log("[DEBUG] Injecting completion prompt as post-streamText follow-up pass...");
|
|
102226
|
+
}
|
|
102227
|
+
if (this.tracer) {
|
|
102228
|
+
this.tracer.recordEvent("completion_prompt.started", {
|
|
102229
|
+
"completion_prompt.original_result_length": finalResult.length
|
|
102230
|
+
});
|
|
102231
|
+
}
|
|
102232
|
+
const completionPromptMessage = `${this.completionPrompt}
|
|
102233
|
+
|
|
102234
|
+
Here is the result to review:
|
|
102235
|
+
<result>
|
|
102236
|
+
${finalResult}
|
|
102237
|
+
</result>
|
|
102238
|
+
|
|
102239
|
+
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).`;
|
|
102240
|
+
currentMessages.push({ role: "user", content: completionPromptMessage });
|
|
102241
|
+
const completionMaxIterations = 5;
|
|
102242
|
+
const completionStreamOptions = {
|
|
102243
|
+
model: this.provider ? this.provider(this.model) : this.model,
|
|
102244
|
+
messages: this.prepareMessagesWithImages(currentMessages),
|
|
102245
|
+
tools: tools2,
|
|
102246
|
+
stopWhen: (0, import_ai6.stepCountIs)(completionMaxIterations),
|
|
102247
|
+
maxTokens: maxResponseTokens,
|
|
102248
|
+
temperature: 0.3,
|
|
102249
|
+
onStepFinish: ({ toolResults, text, finishReason, usage }) => {
|
|
102250
|
+
if (usage) {
|
|
102251
|
+
this.tokenCounter.recordUsage(usage);
|
|
102252
|
+
}
|
|
102253
|
+
if (options.onStream && text) {
|
|
102254
|
+
options.onStream(text);
|
|
102255
|
+
}
|
|
102256
|
+
if (this.debug) {
|
|
102257
|
+
console.log(`[DEBUG] Completion prompt step finished (reason: ${finishReason}, tools: ${toolResults?.length || 0})`);
|
|
102258
|
+
}
|
|
102259
|
+
}
|
|
102260
|
+
};
|
|
102261
|
+
const providerOpts2 = this._buildThinkingProviderOptions(maxResponseTokens);
|
|
102262
|
+
if (providerOpts2) {
|
|
102263
|
+
completionStreamOptions.providerOptions = providerOpts2;
|
|
102264
|
+
}
|
|
102265
|
+
try {
|
|
102266
|
+
const cpResult = await this.streamTextWithRetryAndFallback(completionStreamOptions);
|
|
102267
|
+
const cpFinalText = await cpResult.text;
|
|
102268
|
+
const cpUsage = await cpResult.usage;
|
|
102269
|
+
if (cpUsage) {
|
|
102270
|
+
this.tokenCounter.recordUsage(cpUsage, cpResult.experimental_providerMetadata);
|
|
102271
|
+
}
|
|
102272
|
+
const cpMessages = await cpResult.response?.messages;
|
|
102273
|
+
if (cpMessages) {
|
|
102274
|
+
for (const msg of cpMessages) {
|
|
102275
|
+
currentMessages.push(msg);
|
|
102276
|
+
}
|
|
102277
|
+
}
|
|
102278
|
+
if (cpFinalText && cpFinalText.trim().length > 0) {
|
|
102279
|
+
finalResult = cpFinalText;
|
|
102280
|
+
}
|
|
102281
|
+
if (this.debug) {
|
|
102282
|
+
console.log(`[DEBUG] Completion prompt follow-up produced ${cpFinalText?.length || 0} chars (using ${cpFinalText && cpFinalText.trim().length > 0 ? "updated" : "original"} result)`);
|
|
102283
|
+
}
|
|
102284
|
+
} catch (cpError) {
|
|
102285
|
+
if (this.debug) {
|
|
102286
|
+
console.log(`[DEBUG] Completion prompt follow-up failed: ${cpError.message}, keeping original result`);
|
|
102287
|
+
}
|
|
102288
|
+
}
|
|
102289
|
+
}
|
|
102470
102290
|
break;
|
|
102471
102291
|
} catch (error40) {
|
|
102472
102292
|
if (!compactionAttempted && handleContextLimitError) {
|
|
@@ -102496,17 +102316,13 @@ You are working with a workspace. Available paths: ${workspaceDesc}
|
|
|
102496
102316
|
continue;
|
|
102497
102317
|
}
|
|
102498
102318
|
}
|
|
102499
|
-
if (completionResult) {
|
|
102500
|
-
finalResult = completionResult;
|
|
102501
|
-
break;
|
|
102502
|
-
}
|
|
102503
102319
|
console.error(`Error during streamText:`, error40);
|
|
102504
102320
|
finalResult = `Error: Failed to get response from AI model. ${error40.message}`;
|
|
102505
102321
|
throw new Error(finalResult);
|
|
102506
102322
|
}
|
|
102507
102323
|
}
|
|
102508
|
-
if (currentIteration >= maxIterations
|
|
102509
|
-
console.warn(`[WARN] Max tool iterations (${maxIterations}) reached for session ${this.sessionId}
|
|
102324
|
+
if (currentIteration >= maxIterations) {
|
|
102325
|
+
console.warn(`[WARN] Max tool iterations (${maxIterations}) reached for session ${this.sessionId}.`);
|
|
102510
102326
|
}
|
|
102511
102327
|
this.history = currentMessages.map((msg) => ({ ...msg }));
|
|
102512
102328
|
if (this.history.length > MAX_HISTORY_MESSAGES) {
|
|
@@ -102529,279 +102345,17 @@ You are working with a workspace. Available paths: ${workspaceDesc}
|
|
|
102529
102345
|
} catch (error40) {
|
|
102530
102346
|
console.error(`[ERROR] Failed to save messages to storage:`, error40);
|
|
102531
102347
|
}
|
|
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
|
-
}
|
|
102348
|
+
if (completionPromptInjected && this.tracer) {
|
|
102349
|
+
this.tracer.recordEvent("completion_prompt.completed", {
|
|
102350
|
+
"completion_prompt.final_result_length": finalResult?.length || 0,
|
|
102351
|
+
"completion_prompt.used_original": preCompletionResult && finalResult === preCompletionResult
|
|
102352
|
+
});
|
|
102621
102353
|
}
|
|
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) {
|
|
102354
|
+
if (options.schema && !options._schemaFormatted && !options._skipValidation) {
|
|
102801
102355
|
try {
|
|
102802
102356
|
if (!this.disableMermaidValidation) {
|
|
102803
102357
|
if (this.debug) {
|
|
102804
|
-
console.log(`[DEBUG] Mermaid validation: Validating
|
|
102358
|
+
console.log(`[DEBUG] Mermaid validation: Validating result BEFORE schema cleaning...`);
|
|
102805
102359
|
}
|
|
102806
102360
|
const mermaidValidation = await validateAndFixMermaidResponse(finalResult, {
|
|
102807
102361
|
debug: this.debug,
|
|
@@ -102813,55 +102367,51 @@ Convert your previous response content into actual JSON data that follows this s
|
|
|
102813
102367
|
if (mermaidValidation.wasFixed) {
|
|
102814
102368
|
finalResult = mermaidValidation.fixedResponse;
|
|
102815
102369
|
if (this.debug) {
|
|
102816
|
-
console.log(`[DEBUG] Mermaid validation:
|
|
102370
|
+
console.log(`[DEBUG] Mermaid validation: Diagrams fixed`);
|
|
102817
102371
|
if (mermaidValidation.performanceMetrics) {
|
|
102818
102372
|
console.log(`[DEBUG] Mermaid validation: Fixed in ${mermaidValidation.performanceMetrics.totalTimeMs}ms`);
|
|
102819
102373
|
}
|
|
102820
102374
|
}
|
|
102821
102375
|
} else if (this.debug) {
|
|
102822
|
-
console.log(`[DEBUG] Mermaid validation:
|
|
102376
|
+
console.log(`[DEBUG] Mermaid validation: Completed (no fixes needed)`);
|
|
102823
102377
|
}
|
|
102824
102378
|
} else if (this.debug) {
|
|
102825
|
-
console.log(`[DEBUG] Mermaid validation: Skipped
|
|
102379
|
+
console.log(`[DEBUG] Mermaid validation: Skipped due to disableMermaidValidation option`);
|
|
102826
102380
|
}
|
|
102827
102381
|
finalResult = cleanSchemaResponse(finalResult);
|
|
102828
102382
|
if (isJsonSchema(options.schema)) {
|
|
102829
102383
|
if (this.debug) {
|
|
102830
|
-
console.log(`[DEBUG] JSON validation: Starting validation process
|
|
102384
|
+
console.log(`[DEBUG] JSON validation: Starting validation process`);
|
|
102831
102385
|
console.log(`[DEBUG] JSON validation: Response length: ${finalResult.length} chars`);
|
|
102832
102386
|
}
|
|
102833
102387
|
if (this.tracer) {
|
|
102834
|
-
this.tracer.recordJsonValidationEvent("
|
|
102388
|
+
this.tracer.recordJsonValidationEvent("started", {
|
|
102835
102389
|
"json_validation.response_length": finalResult.length,
|
|
102836
|
-
"json_validation.schema_type": "JSON"
|
|
102837
|
-
"json_validation.context": "attempt_completion"
|
|
102390
|
+
"json_validation.schema_type": "JSON"
|
|
102838
102391
|
});
|
|
102839
102392
|
}
|
|
102840
|
-
let validation = validateJsonResponse(finalResult, { debug: this.debug });
|
|
102393
|
+
let validation = validateJsonResponse(finalResult, { debug: this.debug, schema: options.schema });
|
|
102841
102394
|
let retryCount = 0;
|
|
102842
102395
|
const maxRetries = 3;
|
|
102843
102396
|
if (validation.isValid && isJsonSchemaDefinition(finalResult, { debug: this.debug })) {
|
|
102844
102397
|
if (this.debug) {
|
|
102845
|
-
console.log(`[DEBUG] JSON validation:
|
|
102398
|
+
console.log(`[DEBUG] JSON validation: Response is a JSON schema definition instead of data, correcting...`);
|
|
102846
102399
|
}
|
|
102847
102400
|
const schemaDefinitionPrompt = createSchemaDefinitionCorrectionPrompt(
|
|
102848
102401
|
finalResult,
|
|
102849
102402
|
options.schema,
|
|
102850
102403
|
0
|
|
102851
102404
|
);
|
|
102852
|
-
const { schema: _unusedSchema1, ...schemaDefCorrectionOptions } = options;
|
|
102853
102405
|
finalResult = await this.answer(schemaDefinitionPrompt, [], {
|
|
102854
|
-
...
|
|
102406
|
+
...options,
|
|
102855
102407
|
_schemaFormatted: true,
|
|
102856
102408
|
_skipValidation: true,
|
|
102857
|
-
|
|
102409
|
+
_disableTools: true,
|
|
102858
102410
|
_completionPromptProcessed: true,
|
|
102859
|
-
// Prevent cascading completion prompts in retry calls
|
|
102860
102411
|
_maxIterationsOverride: 3
|
|
102861
|
-
// Correction should complete in 1-2 iterations (issue #447)
|
|
102862
102412
|
});
|
|
102863
102413
|
finalResult = cleanSchemaResponse(finalResult);
|
|
102864
|
-
validation = validateJsonResponse(finalResult);
|
|
102414
|
+
validation = validateJsonResponse(finalResult, { debug: this.debug, schema: options.schema });
|
|
102865
102415
|
retryCount = 1;
|
|
102866
102416
|
}
|
|
102867
102417
|
if (!validation.isValid) {
|
|
@@ -102871,20 +102421,16 @@ Convert your previous response content into actual JSON data that follows this s
|
|
|
102871
102421
|
console.log(`[DEBUG] JSON validation: Auto-wrapped plain text for simple schema`);
|
|
102872
102422
|
}
|
|
102873
102423
|
finalResult = autoWrapped;
|
|
102874
|
-
validation = validateJsonResponse(finalResult, { debug: this.debug });
|
|
102424
|
+
validation = validateJsonResponse(finalResult, { debug: this.debug, schema: options.schema });
|
|
102875
102425
|
}
|
|
102876
102426
|
}
|
|
102877
102427
|
while (!validation.isValid && retryCount < maxRetries) {
|
|
102878
102428
|
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 ? "..." : ""}`);
|
|
102429
|
+
console.log(`[DEBUG] JSON validation: Validation failed (attempt ${retryCount + 1}/${maxRetries}):`, validation.error);
|
|
102881
102430
|
}
|
|
102882
102431
|
let correctionPrompt;
|
|
102883
102432
|
try {
|
|
102884
102433
|
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
102434
|
correctionPrompt = createSchemaDefinitionCorrectionPrompt(
|
|
102889
102435
|
finalResult,
|
|
102890
102436
|
options.schema,
|
|
@@ -102906,47 +102452,43 @@ Convert your previous response content into actual JSON data that follows this s
|
|
|
102906
102452
|
retryCount
|
|
102907
102453
|
);
|
|
102908
102454
|
}
|
|
102909
|
-
const { schema: _unusedSchema2, ...correctionOptions } = options;
|
|
102910
102455
|
finalResult = await this.answer(correctionPrompt, [], {
|
|
102911
|
-
...
|
|
102456
|
+
...options,
|
|
102912
102457
|
_schemaFormatted: true,
|
|
102913
102458
|
_skipValidation: true,
|
|
102914
|
-
// Skip validation in recursive correction calls to prevent loops
|
|
102915
102459
|
_disableTools: true,
|
|
102916
|
-
// Only allow attempt_completion - prevent AI from using search/query tools
|
|
102917
102460
|
_completionPromptProcessed: true,
|
|
102918
|
-
// Prevent cascading completion prompts in retry calls
|
|
102919
102461
|
_maxIterationsOverride: 3
|
|
102920
|
-
// Correction should complete in 1-2 iterations (issue #447)
|
|
102921
102462
|
});
|
|
102922
102463
|
finalResult = cleanSchemaResponse(finalResult);
|
|
102923
|
-
validation = validateJsonResponse(finalResult, { debug: this.debug });
|
|
102464
|
+
validation = validateJsonResponse(finalResult, { debug: this.debug, schema: options.schema });
|
|
102924
102465
|
retryCount++;
|
|
102925
102466
|
if (this.debug) {
|
|
102926
102467
|
if (validation.isValid) {
|
|
102927
|
-
console.log(`[DEBUG] JSON validation:
|
|
102468
|
+
console.log(`[DEBUG] JSON validation: Correction successful on attempt ${retryCount}`);
|
|
102928
102469
|
} else {
|
|
102929
|
-
console.log(`[DEBUG] JSON validation:
|
|
102470
|
+
console.log(`[DEBUG] JSON validation: Correction failed on attempt ${retryCount}: ${validation.error}`);
|
|
102930
102471
|
}
|
|
102931
102472
|
}
|
|
102932
102473
|
}
|
|
102933
102474
|
if (this.tracer) {
|
|
102934
|
-
this.tracer.recordJsonValidationEvent("
|
|
102475
|
+
this.tracer.recordJsonValidationEvent("completed", {
|
|
102935
102476
|
"json_validation.success": validation.isValid,
|
|
102936
102477
|
"json_validation.retry_count": retryCount,
|
|
102937
|
-
"json_validation.
|
|
102478
|
+
"json_validation.max_retries": maxRetries,
|
|
102479
|
+
"json_validation.final_response_length": finalResult.length,
|
|
102480
|
+
"json_validation.error": validation.isValid ? null : validation.error
|
|
102938
102481
|
});
|
|
102939
102482
|
}
|
|
102940
102483
|
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 ? "..." : ""}`);
|
|
102484
|
+
console.log(`[DEBUG] JSON validation: Failed after ${maxRetries} attempts: ${validation.error}`);
|
|
102943
102485
|
} else if (validation.isValid && this.debug) {
|
|
102944
|
-
console.log(`[DEBUG] JSON validation:
|
|
102486
|
+
console.log(`[DEBUG] JSON validation: Final validation successful`);
|
|
102945
102487
|
}
|
|
102946
102488
|
}
|
|
102947
102489
|
} catch (error40) {
|
|
102948
102490
|
if (this.debug) {
|
|
102949
|
-
console.log(`[DEBUG]
|
|
102491
|
+
console.log(`[DEBUG] Schema validation/cleanup failed: ${error40.message}`);
|
|
102950
102492
|
}
|
|
102951
102493
|
}
|
|
102952
102494
|
}
|
|
@@ -103045,7 +102587,6 @@ Convert your previous response content into actual JSON data that follows this s
|
|
|
103045
102587
|
* @returns {Object} Compaction statistics
|
|
103046
102588
|
*/
|
|
103047
102589
|
async compactHistory(options = {}) {
|
|
103048
|
-
const { compactMessages: compactMessages2, calculateCompactionStats: calculateCompactionStats2 } = await Promise.resolve().then(() => (init_contextCompactor(), contextCompactor_exports));
|
|
103049
102590
|
if (this.history.length === 0) {
|
|
103050
102591
|
if (this.debug) {
|
|
103051
102592
|
console.log(`[DEBUG] No history to compact for session ${this.sessionId}`);
|
|
@@ -103060,8 +102601,8 @@ Convert your previous response content into actual JSON data that follows this s
|
|
|
103060
102601
|
tokensSaved: 0
|
|
103061
102602
|
};
|
|
103062
102603
|
}
|
|
103063
|
-
const compactedMessages =
|
|
103064
|
-
const stats =
|
|
102604
|
+
const compactedMessages = compactMessages(this.history, options);
|
|
102605
|
+
const stats = calculateCompactionStats(this.history, compactedMessages);
|
|
103065
102606
|
this.history = compactedMessages;
|
|
103066
102607
|
try {
|
|
103067
102608
|
await this.storageAdapter.clearHistory(this.sessionId);
|