@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/build/agent/index.js
CHANGED
|
@@ -2755,7 +2755,11 @@ async function extractBinary(assetPath, outputDir) {
|
|
|
2755
2755
|
if (process.env.DEBUG === "1" || process.env.VERBOSE === "1") {
|
|
2756
2756
|
console.log(`Extracting zip to ${extractDir}...`);
|
|
2757
2757
|
}
|
|
2758
|
-
|
|
2758
|
+
if (isWindows) {
|
|
2759
|
+
await exec(`powershell -NoProfile -Command "Expand-Archive -Path '${assetPath}' -DestinationPath '${extractDir}' -Force"`);
|
|
2760
|
+
} else {
|
|
2761
|
+
await exec(`unzip -q "${assetPath}" -d "${extractDir}"`);
|
|
2762
|
+
}
|
|
2759
2763
|
} else {
|
|
2760
2764
|
if (process.env.DEBUG === "1" || process.env.VERBOSE === "1") {
|
|
2761
2765
|
console.log(`Copying binary directly to ${binaryPath}`);
|
|
@@ -4393,7 +4397,7 @@ Instructions:
|
|
|
4393
4397
|
- Format as a structured list if multiple items found
|
|
4394
4398
|
- If nothing relevant is found in this chunk, respond with "No relevant items found in this chunk."
|
|
4395
4399
|
- Do NOT summarize the code - extract the specific information requested
|
|
4396
|
-
- When done,
|
|
4400
|
+
- When done, provide your final answer directly.`;
|
|
4397
4401
|
try {
|
|
4398
4402
|
const result = await delegate({
|
|
4399
4403
|
task,
|
|
@@ -4455,7 +4459,7 @@ async function aggregateResults(chunkResults2, aggregation, extractionPrompt, op
|
|
|
4455
4459
|
${stripResultTags(r.result)}`).join("\n\n");
|
|
4456
4460
|
const completionNote = `
|
|
4457
4461
|
|
|
4458
|
-
When done,
|
|
4462
|
+
When done, provide your final answer directly.`;
|
|
4459
4463
|
const aggregationPrompts = {
|
|
4460
4464
|
summarize: `Synthesize these analyses into a comprehensive summary. Combine related findings, remove redundancy, and present a coherent overview.
|
|
4461
4465
|
|
|
@@ -4549,7 +4553,7 @@ For example, if looking for customer data:
|
|
|
4549
4553
|
STEP 3: CREATE THE FINAL PLAN
|
|
4550
4554
|
Based on your experiments, output the BEST search strategy.
|
|
4551
4555
|
|
|
4552
|
-
|
|
4556
|
+
Provide your answer in this EXACT format:
|
|
4553
4557
|
|
|
4554
4558
|
SEARCH_QUERY: <the query that WORKED in your experiments - use OR for multiple terms>
|
|
4555
4559
|
AGGREGATION: <summarize | list_unique | count | group_by>
|
|
@@ -4615,7 +4619,7 @@ Your answer should:
|
|
|
4615
4619
|
|
|
4616
4620
|
Format your response as a well-structured document that fully answers: "${question}"
|
|
4617
4621
|
|
|
4618
|
-
When done,
|
|
4622
|
+
When done, provide your final answer directly.`;
|
|
4619
4623
|
try {
|
|
4620
4624
|
const result = await delegate({
|
|
4621
4625
|
task: synthesisTask,
|
|
@@ -8893,6 +8897,34 @@ function createMessagePreview(message, charsPerSide = 200) {
|
|
|
8893
8897
|
const end = message.substring(message.length - charsPerSide);
|
|
8894
8898
|
return `${start}...${end}`;
|
|
8895
8899
|
}
|
|
8900
|
+
function detectStuckResponse(response) {
|
|
8901
|
+
if (!response || typeof response !== "string") {
|
|
8902
|
+
return false;
|
|
8903
|
+
}
|
|
8904
|
+
const stuckPatterns = [
|
|
8905
|
+
/\bi\s+cannot\s+proceed\b/i,
|
|
8906
|
+
/\bi\s+can['']t\s+(?:proceed|continue|move\s+forward)\b/i,
|
|
8907
|
+
/\bunable\s+to\s+(?:proceed|continue|complete)\b/i,
|
|
8908
|
+
/\bblocked\b.*\b(?:proceed|continue)\b/i,
|
|
8909
|
+
/\bneed\s+(?:the|an?)\s+\w+(?:\s+\w+)?\s+to\s+(?:proceed|continue)\b/i,
|
|
8910
|
+
/\brequire[sd]?\s+(?:the|an?)\s+\w+\b.*\bto\s+(?:proceed|continue)\b/i,
|
|
8911
|
+
/\bmissing\s+(?:required|necessary|essential)\b/i,
|
|
8912
|
+
/\bdeadlock\b/i,
|
|
8913
|
+
/\bwe\s+are\s+in\s+a\s+loop\b/i,
|
|
8914
|
+
/\bstuck\s+in\s+a\s+loop\b/i,
|
|
8915
|
+
/\bi\s+(?:have|['']ve)\s+(?:explained|stated|mentioned)\s+(?:this|the\s+situation|it)\s+(?:multiple|several)\s+times\b/i,
|
|
8916
|
+
/\bi\s+(?:cannot|can['']t|could\s+not|couldn['']t)\s+(?:find|locate|get|retrieve|obtain)\s+(?:the|this|that|an?)\b/i,
|
|
8917
|
+
/\bno\s+way\s+to\s+(?:find|get|obtain|retrieve)\b/i,
|
|
8918
|
+
/\bi\s+(?:have|['']ve)\s+exhausted\s+(?:all|my)\s+(?:available\s+)?(?:options|methods|approaches)\b/i,
|
|
8919
|
+
/\bneither\s+of\s+these\s+methods\b/i
|
|
8920
|
+
];
|
|
8921
|
+
for (const pattern of stuckPatterns) {
|
|
8922
|
+
if (pattern.test(response)) {
|
|
8923
|
+
return true;
|
|
8924
|
+
}
|
|
8925
|
+
}
|
|
8926
|
+
return false;
|
|
8927
|
+
}
|
|
8896
8928
|
function parseTargets(targets) {
|
|
8897
8929
|
if (!targets || typeof targets !== "string") {
|
|
8898
8930
|
return [];
|
|
@@ -9402,7 +9434,7 @@ var init_vercel = __esm({
|
|
|
9402
9434
|
if (debug) {
|
|
9403
9435
|
console.error(`[DEDUP] Blocked duplicate search: "${searchQuery}" (path: "${searchPath}")`);
|
|
9404
9436
|
}
|
|
9405
|
-
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
|
|
9437
|
+
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.";
|
|
9406
9438
|
}
|
|
9407
9439
|
previousSearches.add(searchKey);
|
|
9408
9440
|
paginationCounts.set(searchKey, 0);
|
|
@@ -9413,7 +9445,7 @@ var init_vercel = __esm({
|
|
|
9413
9445
|
if (debug) {
|
|
9414
9446
|
console.error(`[DEDUP] Blocked excessive pagination (page ${pageCount}/${MAX_PAGES_PER_QUERY}): "${searchQuery}" in "${searchPath}"`);
|
|
9415
9447
|
}
|
|
9416
|
-
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
|
|
9448
|
+
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.`;
|
|
9417
9449
|
}
|
|
9418
9450
|
}
|
|
9419
9451
|
try {
|
|
@@ -9452,7 +9484,7 @@ var init_vercel = __esm({
|
|
|
9452
9484
|
bashConfig: null,
|
|
9453
9485
|
architectureFileName: options.architectureFileName || null,
|
|
9454
9486
|
promptType: "code-searcher",
|
|
9455
|
-
allowedTools: ["search", "extract", "listFiles"
|
|
9487
|
+
allowedTools: ["search", "extract", "listFiles"],
|
|
9456
9488
|
searchDelegate: false,
|
|
9457
9489
|
schema: CODE_SEARCH_SCHEMA,
|
|
9458
9490
|
parentAbortSignal: options.parentAbortSignal || null
|
|
@@ -9623,14 +9655,15 @@ var init_vercel = __esm({
|
|
|
9623
9655
|
const parsedTargets = parseTargets(targets);
|
|
9624
9656
|
extractFiles = parsedTargets.map((target) => resolveTargetPath(target, effectiveCwd));
|
|
9625
9657
|
if (options.allowedFolders && options.allowedFolders.length > 0) {
|
|
9658
|
+
const { join: pathJoin, sep: pathSep } = await import("path");
|
|
9626
9659
|
extractFiles = extractFiles.map((target) => {
|
|
9627
9660
|
const { filePart, suffix } = splitTargetSuffix(target);
|
|
9628
9661
|
if (existsSync(filePart)) return target;
|
|
9629
|
-
const cwdPrefix = effectiveCwd.endsWith(
|
|
9662
|
+
const cwdPrefix = effectiveCwd.endsWith(pathSep) ? effectiveCwd : effectiveCwd + pathSep;
|
|
9630
9663
|
const relativePart = filePart.startsWith(cwdPrefix) ? filePart.slice(cwdPrefix.length) : null;
|
|
9631
9664
|
if (relativePart) {
|
|
9632
9665
|
for (const folder of options.allowedFolders) {
|
|
9633
|
-
const candidate = folder
|
|
9666
|
+
const candidate = pathJoin(folder, relativePart);
|
|
9634
9667
|
if (existsSync(candidate)) {
|
|
9635
9668
|
if (debug) console.error(`[extract] Auto-fixed path: ${filePart} \u2192 ${candidate}`);
|
|
9636
9669
|
return candidate + suffix;
|
|
@@ -9638,11 +9671,12 @@ var init_vercel = __esm({
|
|
|
9638
9671
|
}
|
|
9639
9672
|
}
|
|
9640
9673
|
for (const folder of options.allowedFolders) {
|
|
9641
|
-
const folderPrefix = folder.endsWith(
|
|
9642
|
-
const
|
|
9674
|
+
const folderPrefix = folder.endsWith(pathSep) ? folder : folder + pathSep;
|
|
9675
|
+
const sepEscaped = pathSep === "\\" ? "\\\\" : pathSep;
|
|
9676
|
+
const wsParent = folderPrefix.replace(new RegExp("[^" + sepEscaped + "]+" + sepEscaped + "$"), "");
|
|
9643
9677
|
if (filePart.startsWith(wsParent)) {
|
|
9644
9678
|
const tail = filePart.slice(wsParent.length);
|
|
9645
|
-
const candidate = folderPrefix
|
|
9679
|
+
const candidate = pathJoin(folderPrefix, tail);
|
|
9646
9680
|
if (candidate !== filePart && existsSync(candidate)) {
|
|
9647
9681
|
if (debug) console.error(`[extract] Auto-fixed path via workspace: ${filePart} \u2192 ${candidate}`);
|
|
9648
9682
|
return candidate + suffix;
|
|
@@ -31946,7 +31980,7 @@ For each pending/in_progress task, either:
|
|
|
31946
31980
|
- Complete it: call task tool with action="complete", id="task-X"
|
|
31947
31981
|
- Cancel it: call task tool with action="update", id="task-X", status="cancelled"
|
|
31948
31982
|
|
|
31949
|
-
After all tasks are resolved,
|
|
31983
|
+
After all tasks are resolved, provide your final answer.`;
|
|
31950
31984
|
}
|
|
31951
31985
|
function createTaskTool(options = {}) {
|
|
31952
31986
|
const { taskManager, tracer, debug = false } = options;
|
|
@@ -32196,13 +32230,13 @@ Tasks = logical units of work, not files or steps.
|
|
|
32196
32230
|
|
|
32197
32231
|
1. **Plan**: Call task tool with action="create" and a tasks array up front
|
|
32198
32232
|
2. **Execute**: Update status to "in_progress" / "completed" as you work. Add, split, or cancel tasks as you learn more.
|
|
32199
|
-
3. **Finish**: All tasks must be "completed" or "cancelled" before
|
|
32233
|
+
3. **Finish**: All tasks must be "completed" or "cancelled" before providing your final answer.
|
|
32200
32234
|
|
|
32201
32235
|
## Rules
|
|
32202
32236
|
|
|
32203
32237
|
- Dependencies are enforced: a task cannot start until its dependencies are completed
|
|
32204
32238
|
- Circular dependencies are rejected
|
|
32205
|
-
-
|
|
32239
|
+
- Completion is blocked while tasks remain unresolved
|
|
32206
32240
|
`;
|
|
32207
32241
|
}
|
|
32208
32242
|
});
|
|
@@ -69068,68 +69102,9 @@ var require_ajv = __commonJS({
|
|
|
69068
69102
|
});
|
|
69069
69103
|
|
|
69070
69104
|
// src/agent/schemaUtils.js
|
|
69071
|
-
var schemaUtils_exports = {};
|
|
69072
|
-
__export(schemaUtils_exports, {
|
|
69073
|
-
JsonFixingAgent: () => JsonFixingAgent,
|
|
69074
|
-
MermaidFixingAgent: () => MermaidFixingAgent,
|
|
69075
|
-
cleanSchemaResponse: () => cleanSchemaResponse,
|
|
69076
|
-
createJsonCorrectionPrompt: () => createJsonCorrectionPrompt,
|
|
69077
|
-
createMermaidCorrectionPrompt: () => createMermaidCorrectionPrompt,
|
|
69078
|
-
createSchemaDefinitionCorrectionPrompt: () => createSchemaDefinitionCorrectionPrompt,
|
|
69079
|
-
decodeHtmlEntities: () => decodeHtmlEntities2,
|
|
69080
|
-
extractMermaidFromJson: () => extractMermaidFromJson,
|
|
69081
|
-
extractMermaidFromMarkdown: () => extractMermaidFromMarkdown,
|
|
69082
|
-
generateExampleFromSchema: () => generateExampleFromSchema,
|
|
69083
|
-
generateSchemaInstructions: () => generateSchemaInstructions,
|
|
69084
|
-
isJsonSchema: () => isJsonSchema,
|
|
69085
|
-
isJsonSchemaDefinition: () => isJsonSchemaDefinition,
|
|
69086
|
-
isMermaidSchema: () => isMermaidSchema,
|
|
69087
|
-
isSimpleTextWrapperSchema: () => isSimpleTextWrapperSchema,
|
|
69088
|
-
processSchemaResponse: () => processSchemaResponse,
|
|
69089
|
-
replaceMermaidDiagramsInJson: () => replaceMermaidDiagramsInJson,
|
|
69090
|
-
replaceMermaidDiagramsInMarkdown: () => replaceMermaidDiagramsInMarkdown,
|
|
69091
|
-
sanitizeMarkdownEscapesInJson: () => sanitizeMarkdownEscapesInJson,
|
|
69092
|
-
tryAutoWrapForSimpleSchema: () => tryAutoWrapForSimpleSchema,
|
|
69093
|
-
tryExtractValidJsonPrefix: () => tryExtractValidJsonPrefix,
|
|
69094
|
-
tryMaidAutoFix: () => tryMaidAutoFix,
|
|
69095
|
-
validateAndFixMermaidResponse: () => validateAndFixMermaidResponse,
|
|
69096
|
-
validateJsonResponse: () => validateJsonResponse,
|
|
69097
|
-
validateMermaidDiagram: () => validateMermaidDiagram,
|
|
69098
|
-
validateMermaidResponse: () => validateMermaidResponse,
|
|
69099
|
-
validateXmlResponse: () => validateXmlResponse
|
|
69100
|
-
});
|
|
69101
|
-
function generateExampleFromSchema(schema, options = {}) {
|
|
69102
|
-
const { debug = false } = options;
|
|
69103
|
-
try {
|
|
69104
|
-
const parsedSchema = typeof schema === "string" ? JSON.parse(schema) : schema;
|
|
69105
|
-
if (parsedSchema.type !== "object" || !parsedSchema.properties) {
|
|
69106
|
-
return null;
|
|
69107
|
-
}
|
|
69108
|
-
const exampleObj = {};
|
|
69109
|
-
for (const [key, value] of Object.entries(parsedSchema.properties)) {
|
|
69110
|
-
if (value.type === "boolean") {
|
|
69111
|
-
exampleObj[key] = false;
|
|
69112
|
-
} else if (value.type === "number") {
|
|
69113
|
-
exampleObj[key] = 0;
|
|
69114
|
-
} else if (value.type === "string") {
|
|
69115
|
-
exampleObj[key] = value.description || "your answer here";
|
|
69116
|
-
} else if (value.type === "array") {
|
|
69117
|
-
exampleObj[key] = [];
|
|
69118
|
-
} else {
|
|
69119
|
-
exampleObj[key] = {};
|
|
69120
|
-
}
|
|
69121
|
-
}
|
|
69122
|
-
return exampleObj;
|
|
69123
|
-
} catch (e) {
|
|
69124
|
-
if (debug) {
|
|
69125
|
-
console.error("[DEBUG] generateExampleFromSchema: Failed to parse schema:", e.message);
|
|
69126
|
-
}
|
|
69127
|
-
return null;
|
|
69128
|
-
}
|
|
69129
|
-
}
|
|
69130
69105
|
function generateSchemaInstructions(schema, options = {}) {
|
|
69131
69106
|
const { debug = false } = options;
|
|
69132
|
-
let instructions = "\n\nIMPORTANT: When you provide your final answer
|
|
69107
|
+
let instructions = "\n\nIMPORTANT: When you provide your final answer, you MUST format it as valid JSON matching this schema:\n\n";
|
|
69133
69108
|
try {
|
|
69134
69109
|
const parsedSchema = typeof schema === "string" ? JSON.parse(schema) : schema;
|
|
69135
69110
|
instructions += `${JSON.stringify(parsedSchema, null, 2)}
|
|
@@ -69143,7 +69118,7 @@ function generateSchemaInstructions(schema, options = {}) {
|
|
|
69143
69118
|
|
|
69144
69119
|
`;
|
|
69145
69120
|
}
|
|
69146
|
-
instructions += "Your response
|
|
69121
|
+
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.";
|
|
69147
69122
|
return instructions;
|
|
69148
69123
|
}
|
|
69149
69124
|
function enforceNoAdditionalProperties(schema) {
|
|
@@ -69840,18 +69815,18 @@ function createJsonCorrectionPrompt(invalidResponse, schema, errorOrValidation,
|
|
|
69840
69815
|
const strengthLevels = [
|
|
69841
69816
|
{
|
|
69842
69817
|
prefix: "CRITICAL JSON ERROR:",
|
|
69843
|
-
instruction: "You MUST fix this and respond
|
|
69844
|
-
emphasis: "
|
|
69818
|
+
instruction: "You MUST fix this and respond with ONLY valid JSON.",
|
|
69819
|
+
emphasis: "Respond with ONLY the corrected JSON. No explanatory text, no markdown, no code blocks."
|
|
69845
69820
|
},
|
|
69846
69821
|
{
|
|
69847
69822
|
prefix: "URGENT - JSON PARSING FAILED:",
|
|
69848
|
-
instruction: "This is your second chance.
|
|
69849
|
-
emphasis: "ABSOLUTELY NO explanatory text or formatting.
|
|
69823
|
+
instruction: "This is your second chance. Respond with valid JSON that can be parsed by JSON.parse().",
|
|
69824
|
+
emphasis: "ABSOLUTELY NO explanatory text or formatting. Respond with ONLY raw JSON."
|
|
69850
69825
|
},
|
|
69851
69826
|
{
|
|
69852
69827
|
prefix: "FINAL ATTEMPT - CRITICAL JSON ERROR:",
|
|
69853
|
-
instruction: "This is the final retry. You MUST
|
|
69854
|
-
emphasis: 'CORRECT:
|
|
69828
|
+
instruction: "This is the final retry. You MUST respond with ONLY raw JSON.",
|
|
69829
|
+
emphasis: 'CORRECT: {"key": "value"}\nWRONG: Here is the JSON: {"key": "value"}\nWRONG: ```json{"key": "value"}```'
|
|
69855
69830
|
}
|
|
69856
69831
|
];
|
|
69857
69832
|
const level = Math.min(retryCount, strengthLevels.length - 1);
|
|
@@ -69905,28 +69880,6 @@ ${currentLevel.example}
|
|
|
69905
69880
|
Return ONLY the JSON data object/array that follows the schema structure. NO schema definitions, NO explanations, NO markdown formatting.`;
|
|
69906
69881
|
return prompt;
|
|
69907
69882
|
}
|
|
69908
|
-
function isMermaidSchema(schema) {
|
|
69909
|
-
if (!schema || typeof schema !== "string") {
|
|
69910
|
-
return false;
|
|
69911
|
-
}
|
|
69912
|
-
const trimmedSchema = schema.trim().toLowerCase();
|
|
69913
|
-
const mermaidIndicators = [
|
|
69914
|
-
trimmedSchema.includes("mermaid"),
|
|
69915
|
-
trimmedSchema.includes("diagram"),
|
|
69916
|
-
trimmedSchema.includes("flowchart"),
|
|
69917
|
-
trimmedSchema.includes("sequence"),
|
|
69918
|
-
trimmedSchema.includes("gantt"),
|
|
69919
|
-
trimmedSchema.includes("pie chart"),
|
|
69920
|
-
trimmedSchema.includes("state diagram"),
|
|
69921
|
-
trimmedSchema.includes("class diagram"),
|
|
69922
|
-
trimmedSchema.includes("entity relationship"),
|
|
69923
|
-
trimmedSchema.includes("user journey"),
|
|
69924
|
-
trimmedSchema.includes("git graph"),
|
|
69925
|
-
trimmedSchema.includes("requirement diagram"),
|
|
69926
|
-
trimmedSchema.includes("c4 context")
|
|
69927
|
-
];
|
|
69928
|
-
return mermaidIndicators.some((indicator) => indicator);
|
|
69929
|
-
}
|
|
69930
69883
|
function extractMermaidFromJson(response) {
|
|
69931
69884
|
if (!response || typeof response !== "string") {
|
|
69932
69885
|
return { diagrams: [], jsonPaths: [], parsedJson: null };
|
|
@@ -70058,28 +70011,6 @@ ${modifiedJsonString}
|
|
|
70058
70011
|
}
|
|
70059
70012
|
return modifiedJsonString;
|
|
70060
70013
|
}
|
|
70061
|
-
function replaceMermaidDiagramsInMarkdown(originalResponse, correctedDiagrams) {
|
|
70062
|
-
if (!originalResponse || typeof originalResponse !== "string") {
|
|
70063
|
-
return originalResponse;
|
|
70064
|
-
}
|
|
70065
|
-
if (!correctedDiagrams || correctedDiagrams.length === 0) {
|
|
70066
|
-
return originalResponse;
|
|
70067
|
-
}
|
|
70068
|
-
const hasJsonDiagrams = correctedDiagrams.some((d) => d.isInJson);
|
|
70069
|
-
if (hasJsonDiagrams) {
|
|
70070
|
-
return replaceMermaidDiagramsInJson(originalResponse, correctedDiagrams);
|
|
70071
|
-
}
|
|
70072
|
-
let modifiedResponse = originalResponse;
|
|
70073
|
-
const sortedDiagrams = [...correctedDiagrams].sort((a, b) => b.startIndex - a.startIndex);
|
|
70074
|
-
for (const diagram of sortedDiagrams) {
|
|
70075
|
-
const attributesStr = diagram.attributes ? ` ${diagram.attributes}` : "";
|
|
70076
|
-
const newCodeBlock = `\`\`\`mermaid${attributesStr}
|
|
70077
|
-
${diagram.content}
|
|
70078
|
-
\`\`\``;
|
|
70079
|
-
modifiedResponse = modifiedResponse.slice(0, diagram.startIndex) + newCodeBlock + modifiedResponse.slice(diagram.endIndex);
|
|
70080
|
-
}
|
|
70081
|
-
return modifiedResponse;
|
|
70082
|
-
}
|
|
70083
70014
|
function replaceSingleMermaidDiagramInResponse(response, originalDiagram, newContent) {
|
|
70084
70015
|
if (!originalDiagram) {
|
|
70085
70016
|
return response;
|
|
@@ -70164,45 +70095,6 @@ async function validateMermaidResponse(response) {
|
|
|
70164
70095
|
errors: errors.length > 0 ? errors : void 0
|
|
70165
70096
|
};
|
|
70166
70097
|
}
|
|
70167
|
-
function createMermaidCorrectionPrompt(invalidResponse, schema, errors, diagrams) {
|
|
70168
|
-
let prompt = `Your previous response contains invalid Mermaid diagrams that cannot be parsed. Here's what you returned:
|
|
70169
|
-
|
|
70170
|
-
${invalidResponse}
|
|
70171
|
-
|
|
70172
|
-
Validation Errors:`;
|
|
70173
|
-
errors.forEach((error, index) => {
|
|
70174
|
-
prompt += `
|
|
70175
|
-
${index + 1}. ${error}`;
|
|
70176
|
-
});
|
|
70177
|
-
if (diagrams && diagrams.length > 0) {
|
|
70178
|
-
prompt += `
|
|
70179
|
-
|
|
70180
|
-
Diagram Details:`;
|
|
70181
|
-
diagrams.forEach((diagramResult, index) => {
|
|
70182
|
-
if (!diagramResult.isValid) {
|
|
70183
|
-
prompt += `
|
|
70184
|
-
|
|
70185
|
-
Diagram ${index + 1}:`;
|
|
70186
|
-
const diagramContent = diagramResult.content || diagramResult.diagram || "";
|
|
70187
|
-
prompt += `
|
|
70188
|
-
- Content: ${diagramContent.substring(0, 100)}${diagramContent.length > 100 ? "..." : ""}`;
|
|
70189
|
-
prompt += `
|
|
70190
|
-
- Error: ${diagramResult.error}`;
|
|
70191
|
-
if (diagramResult.detailedError && diagramResult.detailedError !== diagramResult.error) {
|
|
70192
|
-
prompt += `
|
|
70193
|
-
- Details: ${diagramResult.detailedError}`;
|
|
70194
|
-
}
|
|
70195
|
-
}
|
|
70196
|
-
});
|
|
70197
|
-
}
|
|
70198
|
-
prompt += `
|
|
70199
|
-
|
|
70200
|
-
Please correct your response to include valid Mermaid diagrams that match this schema:
|
|
70201
|
-
${schema}
|
|
70202
|
-
|
|
70203
|
-
Ensure all Mermaid diagrams are properly formatted within \`\`\`mermaid code blocks and follow correct Mermaid syntax.`;
|
|
70204
|
-
return prompt;
|
|
70205
|
-
}
|
|
70206
70098
|
async function tryMaidAutoFix(diagramContent, options = {}) {
|
|
70207
70099
|
const { debug = false } = options;
|
|
70208
70100
|
try {
|
|
@@ -70512,7 +70404,7 @@ async function validateAndFixMermaidResponse(response, options = {}) {
|
|
|
70512
70404
|
};
|
|
70513
70405
|
}
|
|
70514
70406
|
}
|
|
70515
|
-
var import_ajv, HTML_ENTITY_MAP, sessionIdCounter,
|
|
70407
|
+
var import_ajv, HTML_ENTITY_MAP, sessionIdCounter, MermaidFixingAgent;
|
|
70516
70408
|
var init_schemaUtils = __esm({
|
|
70517
70409
|
"src/agent/schemaUtils.js"() {
|
|
70518
70410
|
"use strict";
|
|
@@ -70530,172 +70422,6 @@ var init_schemaUtils = __esm({
|
|
|
70530
70422
|
" ": " "
|
|
70531
70423
|
};
|
|
70532
70424
|
sessionIdCounter = 0;
|
|
70533
|
-
JsonFixingAgent = class {
|
|
70534
|
-
constructor(options = {}) {
|
|
70535
|
-
this.ProbeAgent = null;
|
|
70536
|
-
this.options = {
|
|
70537
|
-
sessionId: options.sessionId || `json-fixer-${Date.now()}-${sessionIdCounter++}`,
|
|
70538
|
-
path: options.path || process.cwd(),
|
|
70539
|
-
provider: options.provider,
|
|
70540
|
-
model: options.model,
|
|
70541
|
-
debug: options.debug,
|
|
70542
|
-
tracer: options.tracer,
|
|
70543
|
-
// Set to false since we're only fixing JSON syntax, not implementing code
|
|
70544
|
-
allowEdit: false
|
|
70545
|
-
};
|
|
70546
|
-
}
|
|
70547
|
-
/**
|
|
70548
|
-
* Get the specialized prompt for JSON fixing
|
|
70549
|
-
*/
|
|
70550
|
-
getJsonFixingPrompt() {
|
|
70551
|
-
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.
|
|
70552
|
-
|
|
70553
|
-
CORE RESPONSIBILITIES:
|
|
70554
|
-
- Analyze JSON for syntax errors and structural issues
|
|
70555
|
-
- Fix syntax errors while maintaining the original data's semantic meaning
|
|
70556
|
-
- Ensure JSON follows proper RFC 8259 specification
|
|
70557
|
-
- Handle all JSON structures: objects, arrays, primitives, nested structures
|
|
70558
|
-
|
|
70559
|
-
JSON SYNTAX RULES:
|
|
70560
|
-
1. **Property names**: Must be enclosed in double quotes
|
|
70561
|
-
2. **String values**: Must use double quotes (not single quotes)
|
|
70562
|
-
3. **Numbers**: Can be integers or decimals, no quotes needed
|
|
70563
|
-
4. **Booleans**: true or false (lowercase, no quotes)
|
|
70564
|
-
5. **Null**: null (lowercase, no quotes)
|
|
70565
|
-
6. **Arrays**: Comma-separated values in square brackets [...]
|
|
70566
|
-
7. **Objects**: Comma-separated key-value pairs in curly braces {...}
|
|
70567
|
-
8. **No trailing commas**: Last item in array/object must not have a trailing comma
|
|
70568
|
-
9. **Escape sequences**: Special characters must be escaped (\\n, \\t, \\", \\\\, etc.)
|
|
70569
|
-
|
|
70570
|
-
COMMON ERRORS TO FIX:
|
|
70571
|
-
1. **Unquoted property names**: {name: "value"} \u2192 {"name": "value"}
|
|
70572
|
-
2. **Single quotes**: {'key': 'value'} \u2192 {"key": "value"}
|
|
70573
|
-
3. **Trailing commas**: {"a": 1,} \u2192 {"a": 1}
|
|
70574
|
-
4. **Unquoted strings**: {key: value} \u2192 {"key": "value"}
|
|
70575
|
-
5. **Missing commas**: {"a": 1 "b": 2} \u2192 {"a": 1, "b": 2}
|
|
70576
|
-
6. **Extra commas**: {"a": 1,, "b": 2} \u2192 {"a": 1, "b": 2}
|
|
70577
|
-
7. **Unclosed brackets/braces**: {"key": "value" \u2192 {"key": "value"}
|
|
70578
|
-
8. **Invalid escape sequences**: Fix or remove
|
|
70579
|
-
9. **Comments**: Remove // or /* */ comments (not allowed in JSON)
|
|
70580
|
-
10. **Undefined values**: Replace undefined with null
|
|
70581
|
-
|
|
70582
|
-
FIXING METHODOLOGY:
|
|
70583
|
-
1. **Identify the error location** from the error message
|
|
70584
|
-
2. **Analyze the context** around the error
|
|
70585
|
-
3. **Apply the appropriate fix** based on JSON syntax rules
|
|
70586
|
-
4. **Preserve data intent** - never change the meaning of the data
|
|
70587
|
-
5. **Validate the result** - ensure it's parseable JSON
|
|
70588
|
-
|
|
70589
|
-
CRITICAL RULES:
|
|
70590
|
-
- ALWAYS output only the corrected JSON
|
|
70591
|
-
- NEVER add explanations, comments, or additional text
|
|
70592
|
-
- NEVER wrap in markdown code blocks (no \`\`\`json)
|
|
70593
|
-
- PRESERVE the original data structure and values
|
|
70594
|
-
- FIX only syntax errors, don't modify the data itself
|
|
70595
|
-
- ENSURE the output is valid, parseable JSON
|
|
70596
|
-
|
|
70597
|
-
When presented with broken JSON, analyze it thoroughly and provide the corrected version that maintains the original intent while fixing all syntax issues.`;
|
|
70598
|
-
}
|
|
70599
|
-
/**
|
|
70600
|
-
* Initialize the ProbeAgent if not already done
|
|
70601
|
-
*/
|
|
70602
|
-
async initializeAgent() {
|
|
70603
|
-
if (!this.ProbeAgent) {
|
|
70604
|
-
const { ProbeAgent: ProbeAgent2 } = await Promise.resolve().then(() => (init_ProbeAgent(), ProbeAgent_exports));
|
|
70605
|
-
this.ProbeAgent = ProbeAgent2;
|
|
70606
|
-
}
|
|
70607
|
-
if (!this.agent) {
|
|
70608
|
-
this.agent = new this.ProbeAgent({
|
|
70609
|
-
sessionId: this.options.sessionId,
|
|
70610
|
-
customPrompt: this.getJsonFixingPrompt(),
|
|
70611
|
-
path: this.options.path,
|
|
70612
|
-
provider: this.options.provider,
|
|
70613
|
-
model: this.options.model,
|
|
70614
|
-
debug: this.options.debug,
|
|
70615
|
-
tracer: this.options.tracer,
|
|
70616
|
-
allowEdit: this.options.allowEdit,
|
|
70617
|
-
maxIterations: 5,
|
|
70618
|
-
// Allow multiple iterations for JSON fixing
|
|
70619
|
-
disableJsonValidation: true
|
|
70620
|
-
// CRITICAL: Disable JSON validation in nested agent to prevent infinite recursion
|
|
70621
|
-
});
|
|
70622
|
-
}
|
|
70623
|
-
return this.agent;
|
|
70624
|
-
}
|
|
70625
|
-
/**
|
|
70626
|
-
* Fix invalid JSON using the specialized agent
|
|
70627
|
-
* @param {string} invalidJson - The broken JSON string
|
|
70628
|
-
* @param {string} schema - The original schema for context
|
|
70629
|
-
* @param {Object} validationResult - Validation result with error details
|
|
70630
|
-
* @param {number} attemptNumber - Current attempt number (for logging)
|
|
70631
|
-
* @returns {Promise<string>} - The corrected JSON
|
|
70632
|
-
*/
|
|
70633
|
-
async fixJson(invalidJson, schema, validationResult, attemptNumber = 1) {
|
|
70634
|
-
await this.initializeAgent();
|
|
70635
|
-
let errorContext = validationResult.error;
|
|
70636
|
-
if (validationResult.enhancedError) {
|
|
70637
|
-
errorContext = validationResult.enhancedError;
|
|
70638
|
-
}
|
|
70639
|
-
let schemaErrorDetails = "";
|
|
70640
|
-
if (validationResult.errorSummary) {
|
|
70641
|
-
schemaErrorDetails = `
|
|
70642
|
-
|
|
70643
|
-
Schema Validation Errors:
|
|
70644
|
-
${validationResult.errorSummary}`;
|
|
70645
|
-
} else if (validationResult.schemaErrors && validationResult.schemaErrors.length > 0) {
|
|
70646
|
-
const errors = validationResult.schemaErrors.map((err) => {
|
|
70647
|
-
const path9 = err.instancePath || "(root)";
|
|
70648
|
-
return ` ${path9}: ${err.message}`;
|
|
70649
|
-
}).join("\n");
|
|
70650
|
-
schemaErrorDetails = `
|
|
70651
|
-
|
|
70652
|
-
Schema Validation Errors:
|
|
70653
|
-
${errors}`;
|
|
70654
|
-
}
|
|
70655
|
-
const prompt = `Fix the following invalid JSON.
|
|
70656
|
-
|
|
70657
|
-
Error: ${errorContext}${schemaErrorDetails}
|
|
70658
|
-
|
|
70659
|
-
Invalid JSON:
|
|
70660
|
-
${invalidJson}
|
|
70661
|
-
|
|
70662
|
-
Expected schema structure:
|
|
70663
|
-
${schema}
|
|
70664
|
-
|
|
70665
|
-
${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.`;
|
|
70666
|
-
try {
|
|
70667
|
-
if (this.options.debug) {
|
|
70668
|
-
console.log(`[DEBUG] JSON fixing: Attempt ${attemptNumber} to fix JSON with separate agent`);
|
|
70669
|
-
}
|
|
70670
|
-
const result = await this.agent.answer(prompt, []);
|
|
70671
|
-
const cleaned = cleanSchemaResponse(result);
|
|
70672
|
-
if (this.options.debug) {
|
|
70673
|
-
console.log(`[DEBUG] JSON fixing: Agent returned ${cleaned.length} chars`);
|
|
70674
|
-
}
|
|
70675
|
-
return cleaned;
|
|
70676
|
-
} catch (error) {
|
|
70677
|
-
if (this.options.debug) {
|
|
70678
|
-
console.error(`[DEBUG] JSON fixing failed: ${error.message}`);
|
|
70679
|
-
}
|
|
70680
|
-
throw new Error(`Failed to fix JSON: ${error.message}`);
|
|
70681
|
-
}
|
|
70682
|
-
}
|
|
70683
|
-
/**
|
|
70684
|
-
* Get token usage information from the specialized agent
|
|
70685
|
-
* @returns {Object} - Token usage statistics
|
|
70686
|
-
*/
|
|
70687
|
-
getTokenUsage() {
|
|
70688
|
-
return this.agent ? this.agent.getTokenUsage() : null;
|
|
70689
|
-
}
|
|
70690
|
-
/**
|
|
70691
|
-
* Cancel any ongoing operations
|
|
70692
|
-
*/
|
|
70693
|
-
cancel() {
|
|
70694
|
-
if (this.agent) {
|
|
70695
|
-
this.agent.cancel();
|
|
70696
|
-
}
|
|
70697
|
-
}
|
|
70698
|
-
};
|
|
70699
70425
|
MermaidFixingAgent = class {
|
|
70700
70426
|
constructor(options = {}) {
|
|
70701
70427
|
this.ProbeAgent = null;
|
|
@@ -70939,7 +70665,7 @@ When reviewing code:
|
|
|
70939
70665
|
"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.`,
|
|
70940
70666
|
"engineer": `You are a senior engineer focused on software architecture and design.
|
|
70941
70667
|
Before jumping on the task you first analyse the user request in detail, and try to provide an elegant and concise solution.
|
|
70942
|
-
If the solution is clear, you can jump to implementation right away. If not, ask the user a clarification question
|
|
70668
|
+
If the solution is clear, you can jump to implementation right away. If not, ask the user a clarification question with the required details.
|
|
70943
70669
|
|
|
70944
70670
|
# Tone and Style
|
|
70945
70671
|
- Be concise and direct. Explain your approach briefly before implementing, then let the code speak for itself.
|
|
@@ -70962,7 +70688,7 @@ If the solution is clear, you can jump to implementation right away. If not, ask
|
|
|
70962
70688
|
When the request has **multiple distinct goals** (e.g. "Fix bug A AND add feature B"), use the task tool to track them:
|
|
70963
70689
|
- Call the task tool with action="create" and a tasks array. Each task must have an "id" field.
|
|
70964
70690
|
- Update task status to "in_progress" when starting and "completed" when done.
|
|
70965
|
-
- All tasks must be completed or cancelled before
|
|
70691
|
+
- All tasks must be completed or cancelled before providing your final answer.
|
|
70966
70692
|
- Stay flexible \u2014 add, remove, or reorganize tasks as your understanding changes.
|
|
70967
70693
|
|
|
70968
70694
|
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.
|
|
@@ -80190,14 +79916,6 @@ var init_FallbackManager = __esm({
|
|
|
80190
79916
|
});
|
|
80191
79917
|
|
|
80192
79918
|
// src/agent/contextCompactor.js
|
|
80193
|
-
var contextCompactor_exports = {};
|
|
80194
|
-
__export(contextCompactor_exports, {
|
|
80195
|
-
calculateCompactionStats: () => calculateCompactionStats,
|
|
80196
|
-
compactMessages: () => compactMessages,
|
|
80197
|
-
handleContextLimitError: () => handleContextLimitError,
|
|
80198
|
-
identifyMessageSegments: () => identifyMessageSegments,
|
|
80199
|
-
isContextLimitError: () => isContextLimitError
|
|
80200
|
-
});
|
|
80201
79919
|
function isContextLimitError(error) {
|
|
80202
79920
|
if (!error) return false;
|
|
80203
79921
|
const errorMessage = (typeof error === "string" ? error : error?.message || "").toLowerCase();
|
|
@@ -80219,9 +79937,15 @@ function messageContainsCompletion(msg) {
|
|
|
80219
79937
|
}
|
|
80220
79938
|
if (Array.isArray(msg.content)) {
|
|
80221
79939
|
if (msg.content.some((p) => p.type === "tool-call" && p.toolName === "attempt_completion")) return true;
|
|
79940
|
+
const hasToolCalls = msg.content.some((p) => p.type === "tool-call");
|
|
79941
|
+
const hasText = msg.content.some((p) => p.type === "text" && p.text?.trim());
|
|
79942
|
+
if (!hasToolCalls && hasText) return true;
|
|
80222
79943
|
}
|
|
80223
79944
|
const text = typeof msg.content === "string" ? msg.content : "";
|
|
80224
|
-
|
|
79945
|
+
if (text.includes("attempt_completion")) return true;
|
|
79946
|
+
const hasNoToolCalls = !Array.isArray(msg.toolInvocations) && !Array.isArray(msg.tool_calls);
|
|
79947
|
+
if (hasNoToolCalls && text.trim().length > 0) return true;
|
|
79948
|
+
return false;
|
|
80225
79949
|
}
|
|
80226
79950
|
function identifyMessageSegments(messages) {
|
|
80227
79951
|
const segments = [];
|
|
@@ -81988,7 +81712,7 @@ import { createAnthropic as createAnthropic2 } from "@ai-sdk/anthropic";
|
|
|
81988
81712
|
import { createOpenAI as createOpenAI2 } from "@ai-sdk/openai";
|
|
81989
81713
|
import { createGoogleGenerativeAI as createGoogleGenerativeAI2 } from "@ai-sdk/google";
|
|
81990
81714
|
import { createAmazonBedrock as createAmazonBedrock2 } from "@ai-sdk/amazon-bedrock";
|
|
81991
|
-
import { streamText as streamText2, tool as tool5, stepCountIs, jsonSchema } from "ai";
|
|
81715
|
+
import { streamText as streamText2, tool as tool5, stepCountIs, jsonSchema, Output } from "ai";
|
|
81992
81716
|
import { randomUUID as randomUUID5 } from "crypto";
|
|
81993
81717
|
import { EventEmitter as EventEmitter5 } from "events";
|
|
81994
81718
|
import { existsSync as existsSync7 } from "fs";
|
|
@@ -82002,8 +81726,8 @@ function debugTruncate(s, limit = 200) {
|
|
|
82002
81726
|
function debugLogToolResults(toolResults) {
|
|
82003
81727
|
if (!toolResults || toolResults.length === 0) return;
|
|
82004
81728
|
for (const tr of toolResults) {
|
|
82005
|
-
const argsStr = JSON.stringify(tr.args
|
|
82006
|
-
const resultStr = typeof tr.result === "string" ? tr.result : JSON.stringify(tr.result
|
|
81729
|
+
const argsStr = tr.args != null ? JSON.stringify(tr.args) : "<no args>";
|
|
81730
|
+
const resultStr = tr.result != null ? typeof tr.result === "string" ? tr.result : JSON.stringify(tr.result) : "<no result>";
|
|
82007
81731
|
console.log(`[DEBUG] tool: ${tr.toolName} | args: ${debugTruncate(argsStr)} | result: ${debugTruncate(resultStr)}`);
|
|
82008
81732
|
}
|
|
82009
81733
|
}
|
|
@@ -82099,7 +81823,7 @@ var init_ProbeAgent = __esm({
|
|
|
82099
81823
|
* @param {Array<Object>} [options.fallback.providers] - List of provider configurations for custom fallback
|
|
82100
81824
|
* @param {boolean} [options.fallback.stopOnSuccess=true] - Stop on first success
|
|
82101
81825
|
* @param {number} [options.fallback.maxTotalAttempts=10] - Maximum total attempts across all providers
|
|
82102
|
-
* @param {string} [options.completionPrompt] - Custom prompt to run after
|
|
81826
|
+
* @param {string} [options.completionPrompt] - Custom prompt to run after completion for validation/review (runs before mermaid/JSON validation)
|
|
82103
81827
|
* @param {number} [options.maxOutputTokens] - Maximum tokens for tool output before truncation (default: 20000, can also be set via PROBE_MAX_OUTPUT_TOKENS env var)
|
|
82104
81828
|
* @param {number} [options.requestTimeout] - Timeout in ms for AI requests (default: 120000 or REQUEST_TIMEOUT env var). Used to abort hung requests.
|
|
82105
81829
|
* @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.
|
|
@@ -83251,12 +82975,11 @@ var init_ProbeAgent = __esm({
|
|
|
83251
82975
|
* - Delegate tool param injection
|
|
83252
82976
|
*
|
|
83253
82977
|
* @param {Object} options - Options from the answer() call
|
|
83254
|
-
* @param {Function} onComplete - Callback when attempt_completion is called (receives result string)
|
|
83255
82978
|
* @param {Object} context - Execution context { maxIterations, currentMessages }
|
|
83256
82979
|
* @returns {Object} Tools object for streamText()
|
|
83257
82980
|
* @private
|
|
83258
82981
|
*/
|
|
83259
|
-
_buildNativeTools(options,
|
|
82982
|
+
_buildNativeTools(options, context = {}) {
|
|
83260
82983
|
const { maxIterations = 30 } = context;
|
|
83261
82984
|
const nativeTools = {};
|
|
83262
82985
|
const isToolAllowed = (toolName) => this.allowedTools.isEnabled(toolName);
|
|
@@ -83406,16 +83129,6 @@ var init_ProbeAgent = __esm({
|
|
|
83406
83129
|
});
|
|
83407
83130
|
};
|
|
83408
83131
|
if (options._disableTools) {
|
|
83409
|
-
nativeTools.attempt_completion = tool5({
|
|
83410
|
-
description: "Signal task completion and provide the final result to the user",
|
|
83411
|
-
inputSchema: external_exports.object({
|
|
83412
|
-
result: external_exports.string().describe("The final result to present to the user")
|
|
83413
|
-
}),
|
|
83414
|
-
execute: async ({ result }) => {
|
|
83415
|
-
onComplete(result);
|
|
83416
|
-
return result;
|
|
83417
|
-
}
|
|
83418
|
-
});
|
|
83419
83132
|
return nativeTools;
|
|
83420
83133
|
}
|
|
83421
83134
|
for (const [toolName, toolImpl] of Object.entries(this.toolImplementations)) {
|
|
@@ -83426,28 +83139,6 @@ var init_ProbeAgent = __esm({
|
|
|
83426
83139
|
nativeTools[toolName] = wrapTool(toolName, schema, description, toolImpl.execute);
|
|
83427
83140
|
}
|
|
83428
83141
|
}
|
|
83429
|
-
nativeTools.attempt_completion = tool5({
|
|
83430
|
-
description: "Signal task completion and provide the final result to the user",
|
|
83431
|
-
inputSchema: external_exports.object({
|
|
83432
|
-
result: external_exports.string().describe("The final result to present to the user")
|
|
83433
|
-
}),
|
|
83434
|
-
execute: async ({ result }) => {
|
|
83435
|
-
if (this.enableTasks && this.taskManager && this.taskManager.hasIncompleteTasks()) {
|
|
83436
|
-
const incompleteTasks = this.taskManager.getIncompleteTasks();
|
|
83437
|
-
const highIterationCount = (context.currentIteration || 0) > maxIterations * 0.7;
|
|
83438
|
-
if (!highIterationCount) {
|
|
83439
|
-
const taskSummary = this.taskManager.getTaskSummary();
|
|
83440
|
-
const blockedMessage = createTaskCompletionBlockedMessage(taskSummary);
|
|
83441
|
-
if (this.debug) {
|
|
83442
|
-
console.log("[DEBUG] Task checkpoint: Blocking completion due to incomplete tasks");
|
|
83443
|
-
}
|
|
83444
|
-
return blockedMessage;
|
|
83445
|
-
}
|
|
83446
|
-
}
|
|
83447
|
-
onComplete(result);
|
|
83448
|
-
return result;
|
|
83449
|
-
}
|
|
83450
|
-
});
|
|
83451
83142
|
if (this.mcpBridge && !options._disableTools) {
|
|
83452
83143
|
const mcpTools = this.mcpBridge.getVercelTools(this._filterMcpTools(this.mcpBridge.getToolNames()));
|
|
83453
83144
|
for (const [name, mcpTool] of Object.entries(mcpTools)) {
|
|
@@ -84331,7 +84022,7 @@ Follow these instructions carefully:
|
|
|
84331
84022
|
2. Use the available tools step-by-step to fulfill the request.
|
|
84332
84023
|
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."}
|
|
84333
84024
|
4. Ensure to get really deep and understand the full picture before answering.
|
|
84334
|
-
5. Once the task is fully completed,
|
|
84025
|
+
5. Once the task is fully completed, provide your final answer directly as text.
|
|
84335
84026
|
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."}
|
|
84336
84027
|
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 ? `
|
|
84337
84028
|
7. When modifying files, choose the appropriate tool:
|
|
@@ -84509,7 +84200,7 @@ You are working with a workspace. Available paths: ${workspaceDesc}
|
|
|
84509
84200
|
});
|
|
84510
84201
|
const systemMessage = await this.getSystemMessage();
|
|
84511
84202
|
let userMessage = { role: "user", content: message.trim() };
|
|
84512
|
-
if (options.schema && !options._schemaFormatted) {
|
|
84203
|
+
if (options.schema && !options._schemaFormatted && !options._disableTools) {
|
|
84513
84204
|
const schemaInstructions = generateSchemaInstructions(options.schema, { debug: this.debug });
|
|
84514
84205
|
userMessage.content = message.trim() + schemaInstructions;
|
|
84515
84206
|
}
|
|
@@ -84541,8 +84232,17 @@ You are working with a workspace. Available paths: ${workspaceDesc}
|
|
|
84541
84232
|
userMessage
|
|
84542
84233
|
];
|
|
84543
84234
|
}
|
|
84235
|
+
if (this.history.length > 0) {
|
|
84236
|
+
const compacted = compactMessages(currentMessages, { keepLastSegment: true, minSegmentsToKeep: 1 });
|
|
84237
|
+
if (compacted.length < currentMessages.length) {
|
|
84238
|
+
const stats = calculateCompactionStats(currentMessages, compacted);
|
|
84239
|
+
if (this.debug) {
|
|
84240
|
+
console.log(`[DEBUG] Proactive history compaction: ${currentMessages.length} \u2192 ${compacted.length} messages (${stats.reductionPercent}% reduction, ~${stats.tokensSaved} tokens saved)`);
|
|
84241
|
+
}
|
|
84242
|
+
currentMessages = compacted;
|
|
84243
|
+
}
|
|
84244
|
+
}
|
|
84544
84245
|
let currentIteration = 0;
|
|
84545
|
-
let completionAttempted = false;
|
|
84546
84246
|
let finalResult = "I was unable to complete your request due to reaching the maximum number of tool iterations.";
|
|
84547
84247
|
const baseMaxIterations = options._maxIterationsOverride || this.maxIterations || MAX_TOOL_ITERATIONS;
|
|
84548
84248
|
const maxIterations = options._maxIterationsOverride ? baseMaxIterations : options.schema ? baseMaxIterations + 4 : baseMaxIterations;
|
|
@@ -84658,12 +84358,8 @@ You are working with a workspace. Available paths: ${workspaceDesc}
|
|
|
84658
84358
|
console.log(`[DEBUG] Schema provided, using extended iteration limit: ${maxIterations} (base: ${baseMaxIterations})`);
|
|
84659
84359
|
}
|
|
84660
84360
|
}
|
|
84661
|
-
let completionResult = null;
|
|
84662
84361
|
const toolContext = { maxIterations, currentIteration: 0, currentMessages };
|
|
84663
|
-
const tools2 = this._buildNativeTools(options,
|
|
84664
|
-
completionResult = result;
|
|
84665
|
-
completionAttempted = true;
|
|
84666
|
-
}, toolContext);
|
|
84362
|
+
const tools2 = this._buildNativeTools(options, toolContext);
|
|
84667
84363
|
if (this.debug) {
|
|
84668
84364
|
const toolNames = Object.keys(tools2);
|
|
84669
84365
|
console.log(`[DEBUG] Agent tools registered (${toolNames.length}): ${toolNames.join(", ")}`);
|
|
@@ -84677,6 +84373,8 @@ You are working with a workspace. Available paths: ${workspaceDesc}
|
|
|
84677
84373
|
maxResponseTokens = 32e3;
|
|
84678
84374
|
}
|
|
84679
84375
|
}
|
|
84376
|
+
let completionPromptInjected = false;
|
|
84377
|
+
let preCompletionResult = null;
|
|
84680
84378
|
let compactionAttempted = false;
|
|
84681
84379
|
while (true) {
|
|
84682
84380
|
try {
|
|
@@ -84685,19 +84383,103 @@ You are working with a workspace. Available paths: ${workspaceDesc}
|
|
|
84685
84383
|
model: this.provider ? this.provider(this.model) : this.model,
|
|
84686
84384
|
messages: messagesForAI,
|
|
84687
84385
|
tools: tools2,
|
|
84688
|
-
stopWhen:
|
|
84386
|
+
stopWhen: ({ steps }) => {
|
|
84387
|
+
if (steps.length >= maxIterations) return true;
|
|
84388
|
+
const lastStep = steps[steps.length - 1];
|
|
84389
|
+
const modelWantsToStop = lastStep?.finishReason === "stop" && (!lastStep?.toolCalls || lastStep.toolCalls.length === 0);
|
|
84390
|
+
if (modelWantsToStop) {
|
|
84391
|
+
if (this.enableTasks && this.taskManager?.hasIncompleteTasks()) {
|
|
84392
|
+
const highIterationCount = steps.length > maxIterations * 0.7;
|
|
84393
|
+
if (!highIterationCount) return false;
|
|
84394
|
+
}
|
|
84395
|
+
if (this.completionPrompt && !options._completionPromptProcessed && !completionPromptInjected) {
|
|
84396
|
+
preCompletionResult = lastStep.text || null;
|
|
84397
|
+
return false;
|
|
84398
|
+
}
|
|
84399
|
+
}
|
|
84400
|
+
let trailingNoTool = 0;
|
|
84401
|
+
for (let i = steps.length - 1; i >= 0; i--) {
|
|
84402
|
+
if (!steps[i].toolCalls?.length) trailingNoTool++;
|
|
84403
|
+
else break;
|
|
84404
|
+
}
|
|
84405
|
+
if (trailingNoTool >= 5) return true;
|
|
84406
|
+
if (trailingNoTool >= 3) {
|
|
84407
|
+
const recentTexts = steps.slice(-3).map((s) => s.text);
|
|
84408
|
+
if (recentTexts.every((t) => t && t === recentTexts[0])) return true;
|
|
84409
|
+
if (recentTexts.every((t) => detectStuckResponse(t))) return true;
|
|
84410
|
+
}
|
|
84411
|
+
return false;
|
|
84412
|
+
},
|
|
84413
|
+
prepareStep: ({ steps, stepNumber }) => {
|
|
84414
|
+
if (stepNumber === maxIterations - 1) {
|
|
84415
|
+
return {
|
|
84416
|
+
toolChoice: "none"
|
|
84417
|
+
};
|
|
84418
|
+
}
|
|
84419
|
+
const lastStep = steps[steps.length - 1];
|
|
84420
|
+
const modelJustStopped = lastStep?.finishReason === "stop" && (!lastStep?.toolCalls || lastStep.toolCalls.length === 0);
|
|
84421
|
+
if (modelJustStopped) {
|
|
84422
|
+
if (this.enableTasks && this.taskManager?.hasIncompleteTasks()) {
|
|
84423
|
+
const taskSummary = this.taskManager.getTaskSummary();
|
|
84424
|
+
const blockedMessage = createTaskCompletionBlockedMessage(taskSummary);
|
|
84425
|
+
return {
|
|
84426
|
+
userMessage: blockedMessage
|
|
84427
|
+
};
|
|
84428
|
+
}
|
|
84429
|
+
if (this.completionPrompt && !options._completionPromptProcessed && !completionPromptInjected) {
|
|
84430
|
+
completionPromptInjected = true;
|
|
84431
|
+
const resultToReview = lastStep.text || preCompletionResult || "";
|
|
84432
|
+
if (this.debug) {
|
|
84433
|
+
console.log("[DEBUG] Injecting completion prompt into main loop via prepareStep...");
|
|
84434
|
+
}
|
|
84435
|
+
if (this.tracer) {
|
|
84436
|
+
this.tracer.recordEvent("completion_prompt.started", {
|
|
84437
|
+
"completion_prompt.original_result_length": resultToReview.length
|
|
84438
|
+
});
|
|
84439
|
+
}
|
|
84440
|
+
const completionPromptMessage = `${this.completionPrompt}
|
|
84441
|
+
|
|
84442
|
+
Here is the result to review:
|
|
84443
|
+
<result>
|
|
84444
|
+
${resultToReview}
|
|
84445
|
+
</result>
|
|
84446
|
+
|
|
84447
|
+
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).`;
|
|
84448
|
+
return {
|
|
84449
|
+
userMessage: completionPromptMessage
|
|
84450
|
+
};
|
|
84451
|
+
}
|
|
84452
|
+
}
|
|
84453
|
+
return void 0;
|
|
84454
|
+
},
|
|
84689
84455
|
maxTokens: maxResponseTokens,
|
|
84690
84456
|
temperature: 0.3,
|
|
84691
|
-
onStepFinish: (
|
|
84457
|
+
onStepFinish: (stepResult) => {
|
|
84458
|
+
const { toolResults, toolCalls, text, reasoningText, finishReason, usage } = stepResult;
|
|
84692
84459
|
currentIteration++;
|
|
84693
84460
|
toolContext.currentIteration = currentIteration;
|
|
84694
84461
|
if (this.tracer) {
|
|
84695
|
-
|
|
84462
|
+
const stepEvent = {
|
|
84696
84463
|
"iteration": currentIteration,
|
|
84697
84464
|
"max_iterations": maxIterations,
|
|
84698
84465
|
"finish_reason": finishReason,
|
|
84699
84466
|
"has_tool_calls": !!(toolResults && toolResults.length > 0)
|
|
84700
|
-
}
|
|
84467
|
+
};
|
|
84468
|
+
if (text) {
|
|
84469
|
+
stepEvent["ai.text"] = text.substring(0, 1e4);
|
|
84470
|
+
stepEvent["ai.text.length"] = text.length;
|
|
84471
|
+
}
|
|
84472
|
+
if (reasoningText) {
|
|
84473
|
+
stepEvent["ai.reasoning"] = reasoningText.substring(0, 1e4);
|
|
84474
|
+
stepEvent["ai.reasoning.length"] = reasoningText.length;
|
|
84475
|
+
}
|
|
84476
|
+
if (toolCalls && toolCalls.length > 0) {
|
|
84477
|
+
stepEvent["ai.tool_calls"] = toolCalls.map((tc) => ({
|
|
84478
|
+
name: tc.toolName,
|
|
84479
|
+
args: JSON.stringify(tc.args || {}).substring(0, 2e3)
|
|
84480
|
+
}));
|
|
84481
|
+
}
|
|
84482
|
+
this.tracer.addEvent("iteration.step", stepEvent);
|
|
84701
84483
|
}
|
|
84702
84484
|
if (usage) {
|
|
84703
84485
|
this.tokenCounter.recordUsage(usage);
|
|
@@ -84707,10 +84489,32 @@ You are working with a workspace. Available paths: ${workspaceDesc}
|
|
|
84707
84489
|
}
|
|
84708
84490
|
if (this.debug) {
|
|
84709
84491
|
console.log(`[DEBUG] Step ${currentIteration}/${maxIterations} finished (reason: ${finishReason}, tools: ${toolResults?.length || 0})`);
|
|
84492
|
+
if (text) {
|
|
84493
|
+
console.log(`[DEBUG] model text: ${debugTruncate(text)}`);
|
|
84494
|
+
}
|
|
84495
|
+
if (reasoningText) {
|
|
84496
|
+
console.log(`[DEBUG] reasoning: ${debugTruncate(reasoningText)}`);
|
|
84497
|
+
}
|
|
84710
84498
|
debugLogToolResults(toolResults);
|
|
84711
84499
|
}
|
|
84712
84500
|
}
|
|
84713
84501
|
};
|
|
84502
|
+
const hasActiveTools = Object.keys(tools2).length > 0;
|
|
84503
|
+
if (options.schema && !hasActiveTools) {
|
|
84504
|
+
try {
|
|
84505
|
+
const parsedSchema = typeof options.schema === "string" ? JSON.parse(options.schema) : options.schema;
|
|
84506
|
+
if (isJsonSchema(options.schema)) {
|
|
84507
|
+
streamOptions.output = Output.object({ schema: jsonSchema(parsedSchema) });
|
|
84508
|
+
if (this.debug) {
|
|
84509
|
+
console.log(`[DEBUG] Native JSON schema output enabled (no active tools)`);
|
|
84510
|
+
}
|
|
84511
|
+
}
|
|
84512
|
+
} catch (e) {
|
|
84513
|
+
if (this.debug) {
|
|
84514
|
+
console.log(`[DEBUG] Failed to set native JSON schema output: ${e.message}`);
|
|
84515
|
+
}
|
|
84516
|
+
}
|
|
84517
|
+
}
|
|
84714
84518
|
const providerOpts = this._buildThinkingProviderOptions(maxResponseTokens);
|
|
84715
84519
|
if (providerOpts) {
|
|
84716
84520
|
streamOptions.providerOptions = providerOpts;
|
|
@@ -84720,7 +84524,7 @@ You are working with a workspace. Available paths: ${workspaceDesc}
|
|
|
84720
84524
|
const finalText = await result.text;
|
|
84721
84525
|
if (this.debug) {
|
|
84722
84526
|
const steps = await result.steps;
|
|
84723
|
-
console.log(`[DEBUG] streamText completed: ${steps?.length || 0} steps, finalText=${finalText?.length || 0} chars
|
|
84527
|
+
console.log(`[DEBUG] streamText completed: ${steps?.length || 0} steps, finalText=${finalText?.length || 0} chars`);
|
|
84724
84528
|
}
|
|
84725
84529
|
const usage = await result.usage;
|
|
84726
84530
|
if (usage) {
|
|
@@ -84744,18 +84548,24 @@ You are working with a workspace. Available paths: ${workspaceDesc}
|
|
|
84744
84548
|
} else {
|
|
84745
84549
|
aiResult = await executeAIRequest();
|
|
84746
84550
|
}
|
|
84747
|
-
if (
|
|
84748
|
-
|
|
84749
|
-
|
|
84750
|
-
|
|
84751
|
-
|
|
84752
|
-
|
|
84753
|
-
|
|
84551
|
+
if (options.schema && streamOptions.output) {
|
|
84552
|
+
try {
|
|
84553
|
+
const outputObject = await aiResult.result.output;
|
|
84554
|
+
if (outputObject) {
|
|
84555
|
+
finalResult = JSON.stringify(outputObject);
|
|
84556
|
+
} else if (aiResult.finalText) {
|
|
84557
|
+
finalResult = aiResult.finalText;
|
|
84558
|
+
}
|
|
84559
|
+
} catch (e) {
|
|
84560
|
+
if (this.debug) {
|
|
84561
|
+
console.log(`[DEBUG] Native JSON output failed, falling back to text: ${e.message}`);
|
|
84562
|
+
}
|
|
84563
|
+
if (aiResult.finalText) {
|
|
84564
|
+
finalResult = aiResult.finalText;
|
|
84754
84565
|
}
|
|
84755
84566
|
}
|
|
84756
84567
|
} else if (aiResult.finalText) {
|
|
84757
84568
|
finalResult = aiResult.finalText;
|
|
84758
|
-
completionAttempted = true;
|
|
84759
84569
|
}
|
|
84760
84570
|
const resultMessages = await aiResult.result.response?.messages;
|
|
84761
84571
|
if (resultMessages) {
|
|
@@ -84763,6 +84573,75 @@ You are working with a workspace. Available paths: ${workspaceDesc}
|
|
|
84763
84573
|
currentMessages.push(msg);
|
|
84764
84574
|
}
|
|
84765
84575
|
}
|
|
84576
|
+
if (this.completionPrompt && !options._completionPromptProcessed && !completionPromptInjected && finalResult) {
|
|
84577
|
+
completionPromptInjected = true;
|
|
84578
|
+
preCompletionResult = finalResult;
|
|
84579
|
+
if (this.debug) {
|
|
84580
|
+
console.log("[DEBUG] Injecting completion prompt as post-streamText follow-up pass...");
|
|
84581
|
+
}
|
|
84582
|
+
if (this.tracer) {
|
|
84583
|
+
this.tracer.recordEvent("completion_prompt.started", {
|
|
84584
|
+
"completion_prompt.original_result_length": finalResult.length
|
|
84585
|
+
});
|
|
84586
|
+
}
|
|
84587
|
+
const completionPromptMessage = `${this.completionPrompt}
|
|
84588
|
+
|
|
84589
|
+
Here is the result to review:
|
|
84590
|
+
<result>
|
|
84591
|
+
${finalResult}
|
|
84592
|
+
</result>
|
|
84593
|
+
|
|
84594
|
+
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).`;
|
|
84595
|
+
currentMessages.push({ role: "user", content: completionPromptMessage });
|
|
84596
|
+
const completionMaxIterations = 5;
|
|
84597
|
+
const completionStreamOptions = {
|
|
84598
|
+
model: this.provider ? this.provider(this.model) : this.model,
|
|
84599
|
+
messages: this.prepareMessagesWithImages(currentMessages),
|
|
84600
|
+
tools: tools2,
|
|
84601
|
+
stopWhen: stepCountIs(completionMaxIterations),
|
|
84602
|
+
maxTokens: maxResponseTokens,
|
|
84603
|
+
temperature: 0.3,
|
|
84604
|
+
onStepFinish: ({ toolResults, text, finishReason, usage }) => {
|
|
84605
|
+
if (usage) {
|
|
84606
|
+
this.tokenCounter.recordUsage(usage);
|
|
84607
|
+
}
|
|
84608
|
+
if (options.onStream && text) {
|
|
84609
|
+
options.onStream(text);
|
|
84610
|
+
}
|
|
84611
|
+
if (this.debug) {
|
|
84612
|
+
console.log(`[DEBUG] Completion prompt step finished (reason: ${finishReason}, tools: ${toolResults?.length || 0})`);
|
|
84613
|
+
}
|
|
84614
|
+
}
|
|
84615
|
+
};
|
|
84616
|
+
const providerOpts2 = this._buildThinkingProviderOptions(maxResponseTokens);
|
|
84617
|
+
if (providerOpts2) {
|
|
84618
|
+
completionStreamOptions.providerOptions = providerOpts2;
|
|
84619
|
+
}
|
|
84620
|
+
try {
|
|
84621
|
+
const cpResult = await this.streamTextWithRetryAndFallback(completionStreamOptions);
|
|
84622
|
+
const cpFinalText = await cpResult.text;
|
|
84623
|
+
const cpUsage = await cpResult.usage;
|
|
84624
|
+
if (cpUsage) {
|
|
84625
|
+
this.tokenCounter.recordUsage(cpUsage, cpResult.experimental_providerMetadata);
|
|
84626
|
+
}
|
|
84627
|
+
const cpMessages = await cpResult.response?.messages;
|
|
84628
|
+
if (cpMessages) {
|
|
84629
|
+
for (const msg of cpMessages) {
|
|
84630
|
+
currentMessages.push(msg);
|
|
84631
|
+
}
|
|
84632
|
+
}
|
|
84633
|
+
if (cpFinalText && cpFinalText.trim().length > 0) {
|
|
84634
|
+
finalResult = cpFinalText;
|
|
84635
|
+
}
|
|
84636
|
+
if (this.debug) {
|
|
84637
|
+
console.log(`[DEBUG] Completion prompt follow-up produced ${cpFinalText?.length || 0} chars (using ${cpFinalText && cpFinalText.trim().length > 0 ? "updated" : "original"} result)`);
|
|
84638
|
+
}
|
|
84639
|
+
} catch (cpError) {
|
|
84640
|
+
if (this.debug) {
|
|
84641
|
+
console.log(`[DEBUG] Completion prompt follow-up failed: ${cpError.message}, keeping original result`);
|
|
84642
|
+
}
|
|
84643
|
+
}
|
|
84644
|
+
}
|
|
84766
84645
|
break;
|
|
84767
84646
|
} catch (error) {
|
|
84768
84647
|
if (!compactionAttempted && handleContextLimitError) {
|
|
@@ -84792,17 +84671,13 @@ You are working with a workspace. Available paths: ${workspaceDesc}
|
|
|
84792
84671
|
continue;
|
|
84793
84672
|
}
|
|
84794
84673
|
}
|
|
84795
|
-
if (completionResult) {
|
|
84796
|
-
finalResult = completionResult;
|
|
84797
|
-
break;
|
|
84798
|
-
}
|
|
84799
84674
|
console.error(`Error during streamText:`, error);
|
|
84800
84675
|
finalResult = `Error: Failed to get response from AI model. ${error.message}`;
|
|
84801
84676
|
throw new Error(finalResult);
|
|
84802
84677
|
}
|
|
84803
84678
|
}
|
|
84804
|
-
if (currentIteration >= maxIterations
|
|
84805
|
-
console.warn(`[WARN] Max tool iterations (${maxIterations}) reached for session ${this.sessionId}
|
|
84679
|
+
if (currentIteration >= maxIterations) {
|
|
84680
|
+
console.warn(`[WARN] Max tool iterations (${maxIterations}) reached for session ${this.sessionId}.`);
|
|
84806
84681
|
}
|
|
84807
84682
|
this.history = currentMessages.map((msg) => ({ ...msg }));
|
|
84808
84683
|
if (this.history.length > MAX_HISTORY_MESSAGES) {
|
|
@@ -84825,279 +84700,17 @@ You are working with a workspace. Available paths: ${workspaceDesc}
|
|
|
84825
84700
|
} catch (error) {
|
|
84826
84701
|
console.error(`[ERROR] Failed to save messages to storage:`, error);
|
|
84827
84702
|
}
|
|
84828
|
-
if (
|
|
84829
|
-
|
|
84830
|
-
|
|
84831
|
-
|
|
84832
|
-
|
|
84833
|
-
const originalResult = finalResult;
|
|
84834
|
-
if (this.tracer) {
|
|
84835
|
-
this.tracer.recordEvent("completion_prompt.started", {
|
|
84836
|
-
"completion_prompt.original_result_length": finalResult?.length || 0
|
|
84837
|
-
});
|
|
84838
|
-
}
|
|
84839
|
-
const completionPromptMessage = `${this.completionPrompt}
|
|
84840
|
-
|
|
84841
|
-
Here is the result to review:
|
|
84842
|
-
<result>
|
|
84843
|
-
${finalResult}
|
|
84844
|
-
</result>
|
|
84845
|
-
|
|
84846
|
-
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.`;
|
|
84847
|
-
currentMessages.push({ role: "user", content: completionPromptMessage });
|
|
84848
|
-
completionResult = null;
|
|
84849
|
-
completionAttempted = false;
|
|
84850
|
-
const completionMaxIterations = 5;
|
|
84851
|
-
const completionStreamOptions = {
|
|
84852
|
-
model: this.provider ? this.provider(this.model) : this.model,
|
|
84853
|
-
messages: this.prepareMessagesWithImages(currentMessages),
|
|
84854
|
-
tools: tools2,
|
|
84855
|
-
stopWhen: stepCountIs(completionMaxIterations),
|
|
84856
|
-
maxTokens: maxResponseTokens,
|
|
84857
|
-
temperature: 0.3,
|
|
84858
|
-
onStepFinish: ({ toolResults, text, finishReason, usage }) => {
|
|
84859
|
-
if (usage) {
|
|
84860
|
-
this.tokenCounter.recordUsage(usage);
|
|
84861
|
-
}
|
|
84862
|
-
if (options.onStream && text) {
|
|
84863
|
-
options.onStream(text);
|
|
84864
|
-
}
|
|
84865
|
-
if (this.debug) {
|
|
84866
|
-
console.log(`[DEBUG] Completion prompt step finished (reason: ${finishReason}, tools: ${toolResults?.length || 0})`);
|
|
84867
|
-
debugLogToolResults(toolResults);
|
|
84868
|
-
}
|
|
84869
|
-
}
|
|
84870
|
-
};
|
|
84871
|
-
const providerOpts = this._buildThinkingProviderOptions(maxResponseTokens);
|
|
84872
|
-
if (providerOpts) {
|
|
84873
|
-
completionStreamOptions.providerOptions = providerOpts;
|
|
84874
|
-
}
|
|
84875
|
-
const cpResult = await this.streamTextWithRetryAndFallback(completionStreamOptions);
|
|
84876
|
-
const cpFinalText = await cpResult.text;
|
|
84877
|
-
const cpUsage = await cpResult.usage;
|
|
84878
|
-
if (cpUsage) {
|
|
84879
|
-
this.tokenCounter.recordUsage(cpUsage, cpResult.experimental_providerMetadata);
|
|
84880
|
-
}
|
|
84881
|
-
const cpMessages = await cpResult.response?.messages;
|
|
84882
|
-
if (cpMessages) {
|
|
84883
|
-
for (const msg of cpMessages) {
|
|
84884
|
-
currentMessages.push(msg);
|
|
84885
|
-
}
|
|
84886
|
-
}
|
|
84887
|
-
if (completionResult) {
|
|
84888
|
-
finalResult = completionResult;
|
|
84889
|
-
completionAttempted = true;
|
|
84890
|
-
} else if (cpFinalText && cpFinalText.trim().length > 0) {
|
|
84891
|
-
finalResult = cpFinalText;
|
|
84892
|
-
completionAttempted = true;
|
|
84893
|
-
} else {
|
|
84894
|
-
finalResult = originalResult;
|
|
84895
|
-
completionAttempted = true;
|
|
84896
|
-
if (this.debug) {
|
|
84897
|
-
console.log("[DEBUG] Completion prompt returned empty result, keeping original.");
|
|
84898
|
-
}
|
|
84899
|
-
}
|
|
84900
|
-
if (this.debug) {
|
|
84901
|
-
console.log(`[DEBUG] Completion prompt finished. Final result length: ${finalResult?.length || 0}`);
|
|
84902
|
-
}
|
|
84903
|
-
if (this.tracer) {
|
|
84904
|
-
this.tracer.recordEvent("completion_prompt.completed", {
|
|
84905
|
-
"completion_prompt.final_result_length": finalResult?.length || 0,
|
|
84906
|
-
"completion_prompt.used_original": finalResult === originalResult
|
|
84907
|
-
});
|
|
84908
|
-
}
|
|
84909
|
-
} catch (error) {
|
|
84910
|
-
console.error("[ERROR] Completion prompt failed:", error);
|
|
84911
|
-
if (this.tracer) {
|
|
84912
|
-
this.tracer.recordEvent("completion_prompt.error", {
|
|
84913
|
-
"completion_prompt.error": error.message
|
|
84914
|
-
});
|
|
84915
|
-
}
|
|
84916
|
-
}
|
|
84703
|
+
if (completionPromptInjected && this.tracer) {
|
|
84704
|
+
this.tracer.recordEvent("completion_prompt.completed", {
|
|
84705
|
+
"completion_prompt.final_result_length": finalResult?.length || 0,
|
|
84706
|
+
"completion_prompt.used_original": preCompletionResult && finalResult === preCompletionResult
|
|
84707
|
+
});
|
|
84917
84708
|
}
|
|
84918
|
-
|
|
84919
|
-
if (options.schema && !options._schemaFormatted && !completionAttempted && !reachedMaxIterations) {
|
|
84920
|
-
if (this.debug) {
|
|
84921
|
-
console.log("[DEBUG] Schema provided, applying automatic formatting...");
|
|
84922
|
-
}
|
|
84923
|
-
try {
|
|
84924
|
-
const schemaPrompt = `CRITICAL: You MUST respond with ONLY valid JSON DATA that conforms to this schema structure. DO NOT return the schema definition itself.
|
|
84925
|
-
|
|
84926
|
-
Schema to follow (this is just the structure - provide ACTUAL DATA):
|
|
84927
|
-
${options.schema}
|
|
84928
|
-
|
|
84929
|
-
REQUIREMENTS:
|
|
84930
|
-
- Return ONLY the JSON object/array with REAL DATA that matches the schema structure
|
|
84931
|
-
- DO NOT return the schema definition itself (no "$schema", "$id", "type", "properties", etc.)
|
|
84932
|
-
- NO additional text, explanations, or markdown formatting
|
|
84933
|
-
- NO code blocks or backticks
|
|
84934
|
-
- The JSON must be parseable by JSON.parse()
|
|
84935
|
-
- Fill in actual values that make sense based on your previous response content
|
|
84936
|
-
|
|
84937
|
-
EXAMPLE:
|
|
84938
|
-
If schema defines {type: "object", properties: {name: {type: "string"}, age: {type: "number"}}}
|
|
84939
|
-
Return: {"name": "John Doe", "age": 25}
|
|
84940
|
-
NOT: {"type": "object", "properties": {"name": {"type": "string"}}}
|
|
84941
|
-
|
|
84942
|
-
Convert your previous response content into actual JSON data that follows this schema structure.`;
|
|
84943
|
-
finalResult = await this.answer(schemaPrompt, [], {
|
|
84944
|
-
...options,
|
|
84945
|
-
_schemaFormatted: true,
|
|
84946
|
-
_completionPromptProcessed: true
|
|
84947
|
-
// Prevent cascading completion prompts in retry calls
|
|
84948
|
-
});
|
|
84949
|
-
if (!this.disableMermaidValidation) {
|
|
84950
|
-
try {
|
|
84951
|
-
if (this.debug) {
|
|
84952
|
-
console.log(`[DEBUG] Mermaid validation: Starting enhanced mermaid validation...`);
|
|
84953
|
-
}
|
|
84954
|
-
if (this.tracer) {
|
|
84955
|
-
this.tracer.recordMermaidValidationEvent("schema_processing_started", {
|
|
84956
|
-
"mermaid_validation.context": "schema_processing",
|
|
84957
|
-
"mermaid_validation.response_length": finalResult.length
|
|
84958
|
-
});
|
|
84959
|
-
}
|
|
84960
|
-
const mermaidValidation = await validateAndFixMermaidResponse(finalResult, {
|
|
84961
|
-
debug: this.debug,
|
|
84962
|
-
path: this.workspaceRoot || this.allowedFolders[0],
|
|
84963
|
-
provider: this.clientApiProvider,
|
|
84964
|
-
model: this.model,
|
|
84965
|
-
tracer: this.tracer
|
|
84966
|
-
});
|
|
84967
|
-
if (mermaidValidation.wasFixed) {
|
|
84968
|
-
finalResult = mermaidValidation.fixedResponse;
|
|
84969
|
-
if (this.debug) {
|
|
84970
|
-
console.log(`[DEBUG] Mermaid validation: Diagrams successfully fixed`);
|
|
84971
|
-
if (mermaidValidation.performanceMetrics) {
|
|
84972
|
-
const metrics = mermaidValidation.performanceMetrics;
|
|
84973
|
-
console.log(`[DEBUG] Mermaid validation: Performance - total: ${metrics.totalTimeMs}ms, AI fixing: ${metrics.aiFixingTimeMs}ms`);
|
|
84974
|
-
console.log(`[DEBUG] Mermaid validation: Results - ${metrics.diagramsFixed}/${metrics.diagramsProcessed} diagrams fixed`);
|
|
84975
|
-
}
|
|
84976
|
-
if (mermaidValidation.fixingResults) {
|
|
84977
|
-
mermaidValidation.fixingResults.forEach((fixResult, index) => {
|
|
84978
|
-
if (fixResult.wasFixed) {
|
|
84979
|
-
const method = fixResult.fixedWithHtmlDecoding ? "HTML entity decoding" : "AI correction";
|
|
84980
|
-
const time = fixResult.aiFixingTimeMs ? ` in ${fixResult.aiFixingTimeMs}ms` : "";
|
|
84981
|
-
console.log(`[DEBUG] Mermaid validation: Fixed diagram ${fixResult.diagramIndex + 1} with ${method}${time}`);
|
|
84982
|
-
console.log(`[DEBUG] Mermaid validation: Original error: ${fixResult.originalError}`);
|
|
84983
|
-
} else {
|
|
84984
|
-
console.log(`[DEBUG] Mermaid validation: Failed to fix diagram ${fixResult.diagramIndex + 1}: ${fixResult.fixingError}`);
|
|
84985
|
-
}
|
|
84986
|
-
});
|
|
84987
|
-
}
|
|
84988
|
-
}
|
|
84989
|
-
} else if (this.debug) {
|
|
84990
|
-
console.log(`[DEBUG] Mermaid validation: No fixes needed or fixes unsuccessful`);
|
|
84991
|
-
if (mermaidValidation.diagrams?.length > 0) {
|
|
84992
|
-
console.log(`[DEBUG] Mermaid validation: Found ${mermaidValidation.diagrams.length} diagrams, all valid: ${mermaidValidation.isValid}`);
|
|
84993
|
-
}
|
|
84994
|
-
}
|
|
84995
|
-
} catch (error) {
|
|
84996
|
-
if (this.debug) {
|
|
84997
|
-
console.log(`[DEBUG] Mermaid validation: Process failed with error: ${error.message}`);
|
|
84998
|
-
console.log(`[DEBUG] Mermaid validation: Stack trace: ${error.stack}`);
|
|
84999
|
-
}
|
|
85000
|
-
}
|
|
85001
|
-
} else if (this.debug) {
|
|
85002
|
-
console.log(`[DEBUG] Mermaid validation: Skipped due to disableMermaidValidation option`);
|
|
85003
|
-
}
|
|
85004
|
-
finalResult = cleanSchemaResponse(finalResult);
|
|
85005
|
-
if (isJsonSchema(options.schema)) {
|
|
85006
|
-
if (this.debug) {
|
|
85007
|
-
console.log(`[DEBUG] JSON validation: Starting validation process for schema response`);
|
|
85008
|
-
console.log(`[DEBUG] JSON validation: Cleaned response length: ${finalResult.length} chars`);
|
|
85009
|
-
}
|
|
85010
|
-
if (this.tracer) {
|
|
85011
|
-
this.tracer.recordJsonValidationEvent("started", {
|
|
85012
|
-
"json_validation.response_length": finalResult.length,
|
|
85013
|
-
"json_validation.schema_type": "JSON"
|
|
85014
|
-
});
|
|
85015
|
-
}
|
|
85016
|
-
let validation = validateJsonResponse(finalResult, { debug: this.debug, schema: options.schema });
|
|
85017
|
-
let retryCount = 0;
|
|
85018
|
-
const maxRetries = 3;
|
|
85019
|
-
if (validation.isValid && isJsonSchemaDefinition(finalResult, { debug: this.debug })) {
|
|
85020
|
-
if (this.debug) {
|
|
85021
|
-
console.log(`[DEBUG] JSON validation: Response is a JSON schema definition instead of data, needs correction...`);
|
|
85022
|
-
}
|
|
85023
|
-
validation = {
|
|
85024
|
-
isValid: false,
|
|
85025
|
-
error: "Response is a JSON schema definition instead of actual data",
|
|
85026
|
-
enhancedError: "Response is a JSON schema definition instead of actual data. Please return data that conforms to the schema, not the schema itself."
|
|
85027
|
-
};
|
|
85028
|
-
}
|
|
85029
|
-
if (!validation.isValid) {
|
|
85030
|
-
if (this.debug) {
|
|
85031
|
-
console.log(`[DEBUG] JSON validation: Starting separate JsonFixingAgent session...`);
|
|
85032
|
-
}
|
|
85033
|
-
const { JsonFixingAgent: JsonFixingAgent2 } = await Promise.resolve().then(() => (init_schemaUtils(), schemaUtils_exports));
|
|
85034
|
-
const jsonFixer = new JsonFixingAgent2({
|
|
85035
|
-
path: this.workspaceRoot || this.allowedFolders[0],
|
|
85036
|
-
provider: this.clientApiProvider,
|
|
85037
|
-
model: this.model,
|
|
85038
|
-
debug: this.debug,
|
|
85039
|
-
tracer: this.tracer
|
|
85040
|
-
});
|
|
85041
|
-
let currentResult = finalResult;
|
|
85042
|
-
let currentValidation = validation;
|
|
85043
|
-
while (!currentValidation.isValid && retryCount < maxRetries) {
|
|
85044
|
-
if (this.debug) {
|
|
85045
|
-
console.log(`[DEBUG] JSON validation: Validation failed (attempt ${retryCount + 1}/${maxRetries}):`, currentValidation.error);
|
|
85046
|
-
console.log(`[DEBUG] JSON validation: Invalid response sample: ${currentResult.substring(0, 300)}${currentResult.length > 300 ? "..." : ""}`);
|
|
85047
|
-
}
|
|
85048
|
-
try {
|
|
85049
|
-
currentResult = await jsonFixer.fixJson(
|
|
85050
|
-
currentResult,
|
|
85051
|
-
options.schema,
|
|
85052
|
-
currentValidation,
|
|
85053
|
-
retryCount + 1
|
|
85054
|
-
);
|
|
85055
|
-
currentValidation = validateJsonResponse(currentResult, { debug: this.debug, schema: options.schema });
|
|
85056
|
-
retryCount++;
|
|
85057
|
-
if (this.debug) {
|
|
85058
|
-
if (!currentValidation.isValid && retryCount < maxRetries) {
|
|
85059
|
-
console.log(`[DEBUG] JSON validation: Still invalid after correction ${retryCount}, retrying...`);
|
|
85060
|
-
console.log(`[DEBUG] JSON validation: Corrected response sample: ${currentResult.substring(0, 300)}${currentResult.length > 300 ? "..." : ""}`);
|
|
85061
|
-
} else if (currentValidation.isValid) {
|
|
85062
|
-
console.log(`[DEBUG] JSON validation: Successfully corrected after ${retryCount} attempts with JsonFixingAgent`);
|
|
85063
|
-
}
|
|
85064
|
-
}
|
|
85065
|
-
} catch (error) {
|
|
85066
|
-
if (this.debug) {
|
|
85067
|
-
console.error(`[DEBUG] JSON validation: JsonFixingAgent error on attempt ${retryCount + 1}:`, error.message);
|
|
85068
|
-
}
|
|
85069
|
-
break;
|
|
85070
|
-
}
|
|
85071
|
-
}
|
|
85072
|
-
finalResult = currentResult;
|
|
85073
|
-
validation = currentValidation;
|
|
85074
|
-
if (!validation.isValid && this.debug) {
|
|
85075
|
-
console.log(`[DEBUG] JSON validation: Still invalid after ${maxRetries} correction attempts with JsonFixingAgent:`, validation.error);
|
|
85076
|
-
console.log(`[DEBUG] JSON validation: Final invalid response: ${finalResult.substring(0, 500)}${finalResult.length > 500 ? "..." : ""}`);
|
|
85077
|
-
} else if (validation.isValid && this.debug) {
|
|
85078
|
-
console.log(`[DEBUG] JSON validation: Final validation successful`);
|
|
85079
|
-
}
|
|
85080
|
-
}
|
|
85081
|
-
if (this.tracer) {
|
|
85082
|
-
this.tracer.recordJsonValidationEvent("completed", {
|
|
85083
|
-
"json_validation.success": validation.isValid,
|
|
85084
|
-
"json_validation.retry_count": retryCount,
|
|
85085
|
-
"json_validation.max_retries": maxRetries,
|
|
85086
|
-
"json_validation.final_response_length": finalResult.length,
|
|
85087
|
-
"json_validation.error": validation.isValid ? null : validation.error
|
|
85088
|
-
});
|
|
85089
|
-
}
|
|
85090
|
-
}
|
|
85091
|
-
} catch (error) {
|
|
85092
|
-
console.error("[ERROR] Schema formatting failed:", error);
|
|
85093
|
-
}
|
|
85094
|
-
} else if (reachedMaxIterations && options.schema && this.debug) {
|
|
85095
|
-
console.log("[DEBUG] Skipping schema formatting due to max iterations reached without completion");
|
|
85096
|
-
} else if (completionAttempted && options.schema && !options._schemaFormatted && !options._skipValidation) {
|
|
84709
|
+
if (options.schema && !options._schemaFormatted && !options._skipValidation) {
|
|
85097
84710
|
try {
|
|
85098
84711
|
if (!this.disableMermaidValidation) {
|
|
85099
84712
|
if (this.debug) {
|
|
85100
|
-
console.log(`[DEBUG] Mermaid validation: Validating
|
|
84713
|
+
console.log(`[DEBUG] Mermaid validation: Validating result BEFORE schema cleaning...`);
|
|
85101
84714
|
}
|
|
85102
84715
|
const mermaidValidation = await validateAndFixMermaidResponse(finalResult, {
|
|
85103
84716
|
debug: this.debug,
|
|
@@ -85109,55 +84722,51 @@ Convert your previous response content into actual JSON data that follows this s
|
|
|
85109
84722
|
if (mermaidValidation.wasFixed) {
|
|
85110
84723
|
finalResult = mermaidValidation.fixedResponse;
|
|
85111
84724
|
if (this.debug) {
|
|
85112
|
-
console.log(`[DEBUG] Mermaid validation:
|
|
84725
|
+
console.log(`[DEBUG] Mermaid validation: Diagrams fixed`);
|
|
85113
84726
|
if (mermaidValidation.performanceMetrics) {
|
|
85114
84727
|
console.log(`[DEBUG] Mermaid validation: Fixed in ${mermaidValidation.performanceMetrics.totalTimeMs}ms`);
|
|
85115
84728
|
}
|
|
85116
84729
|
}
|
|
85117
84730
|
} else if (this.debug) {
|
|
85118
|
-
console.log(`[DEBUG] Mermaid validation:
|
|
84731
|
+
console.log(`[DEBUG] Mermaid validation: Completed (no fixes needed)`);
|
|
85119
84732
|
}
|
|
85120
84733
|
} else if (this.debug) {
|
|
85121
|
-
console.log(`[DEBUG] Mermaid validation: Skipped
|
|
84734
|
+
console.log(`[DEBUG] Mermaid validation: Skipped due to disableMermaidValidation option`);
|
|
85122
84735
|
}
|
|
85123
84736
|
finalResult = cleanSchemaResponse(finalResult);
|
|
85124
84737
|
if (isJsonSchema(options.schema)) {
|
|
85125
84738
|
if (this.debug) {
|
|
85126
|
-
console.log(`[DEBUG] JSON validation: Starting validation process
|
|
84739
|
+
console.log(`[DEBUG] JSON validation: Starting validation process`);
|
|
85127
84740
|
console.log(`[DEBUG] JSON validation: Response length: ${finalResult.length} chars`);
|
|
85128
84741
|
}
|
|
85129
84742
|
if (this.tracer) {
|
|
85130
|
-
this.tracer.recordJsonValidationEvent("
|
|
84743
|
+
this.tracer.recordJsonValidationEvent("started", {
|
|
85131
84744
|
"json_validation.response_length": finalResult.length,
|
|
85132
|
-
"json_validation.schema_type": "JSON"
|
|
85133
|
-
"json_validation.context": "attempt_completion"
|
|
84745
|
+
"json_validation.schema_type": "JSON"
|
|
85134
84746
|
});
|
|
85135
84747
|
}
|
|
85136
|
-
let validation = validateJsonResponse(finalResult, { debug: this.debug });
|
|
84748
|
+
let validation = validateJsonResponse(finalResult, { debug: this.debug, schema: options.schema });
|
|
85137
84749
|
let retryCount = 0;
|
|
85138
84750
|
const maxRetries = 3;
|
|
85139
84751
|
if (validation.isValid && isJsonSchemaDefinition(finalResult, { debug: this.debug })) {
|
|
85140
84752
|
if (this.debug) {
|
|
85141
|
-
console.log(`[DEBUG] JSON validation:
|
|
84753
|
+
console.log(`[DEBUG] JSON validation: Response is a JSON schema definition instead of data, correcting...`);
|
|
85142
84754
|
}
|
|
85143
84755
|
const schemaDefinitionPrompt = createSchemaDefinitionCorrectionPrompt(
|
|
85144
84756
|
finalResult,
|
|
85145
84757
|
options.schema,
|
|
85146
84758
|
0
|
|
85147
84759
|
);
|
|
85148
|
-
const { schema: _unusedSchema1, ...schemaDefCorrectionOptions } = options;
|
|
85149
84760
|
finalResult = await this.answer(schemaDefinitionPrompt, [], {
|
|
85150
|
-
...
|
|
84761
|
+
...options,
|
|
85151
84762
|
_schemaFormatted: true,
|
|
85152
84763
|
_skipValidation: true,
|
|
85153
|
-
|
|
84764
|
+
_disableTools: true,
|
|
85154
84765
|
_completionPromptProcessed: true,
|
|
85155
|
-
// Prevent cascading completion prompts in retry calls
|
|
85156
84766
|
_maxIterationsOverride: 3
|
|
85157
|
-
// Correction should complete in 1-2 iterations (issue #447)
|
|
85158
84767
|
});
|
|
85159
84768
|
finalResult = cleanSchemaResponse(finalResult);
|
|
85160
|
-
validation = validateJsonResponse(finalResult);
|
|
84769
|
+
validation = validateJsonResponse(finalResult, { debug: this.debug, schema: options.schema });
|
|
85161
84770
|
retryCount = 1;
|
|
85162
84771
|
}
|
|
85163
84772
|
if (!validation.isValid) {
|
|
@@ -85167,20 +84776,16 @@ Convert your previous response content into actual JSON data that follows this s
|
|
|
85167
84776
|
console.log(`[DEBUG] JSON validation: Auto-wrapped plain text for simple schema`);
|
|
85168
84777
|
}
|
|
85169
84778
|
finalResult = autoWrapped;
|
|
85170
|
-
validation = validateJsonResponse(finalResult, { debug: this.debug });
|
|
84779
|
+
validation = validateJsonResponse(finalResult, { debug: this.debug, schema: options.schema });
|
|
85171
84780
|
}
|
|
85172
84781
|
}
|
|
85173
84782
|
while (!validation.isValid && retryCount < maxRetries) {
|
|
85174
84783
|
if (this.debug) {
|
|
85175
|
-
console.log(`[DEBUG] JSON validation:
|
|
85176
|
-
console.log(`[DEBUG] JSON validation: Invalid response sample: ${finalResult.substring(0, 300)}${finalResult.length > 300 ? "..." : ""}`);
|
|
84784
|
+
console.log(`[DEBUG] JSON validation: Validation failed (attempt ${retryCount + 1}/${maxRetries}):`, validation.error);
|
|
85177
84785
|
}
|
|
85178
84786
|
let correctionPrompt;
|
|
85179
84787
|
try {
|
|
85180
84788
|
if (isJsonSchemaDefinition(finalResult, { debug: this.debug })) {
|
|
85181
|
-
if (this.debug) {
|
|
85182
|
-
console.log(`[DEBUG] JSON validation: attempt_completion response is still a schema definition, using specialized correction`);
|
|
85183
|
-
}
|
|
85184
84789
|
correctionPrompt = createSchemaDefinitionCorrectionPrompt(
|
|
85185
84790
|
finalResult,
|
|
85186
84791
|
options.schema,
|
|
@@ -85202,47 +84807,43 @@ Convert your previous response content into actual JSON data that follows this s
|
|
|
85202
84807
|
retryCount
|
|
85203
84808
|
);
|
|
85204
84809
|
}
|
|
85205
|
-
const { schema: _unusedSchema2, ...correctionOptions } = options;
|
|
85206
84810
|
finalResult = await this.answer(correctionPrompt, [], {
|
|
85207
|
-
...
|
|
84811
|
+
...options,
|
|
85208
84812
|
_schemaFormatted: true,
|
|
85209
84813
|
_skipValidation: true,
|
|
85210
|
-
// Skip validation in recursive correction calls to prevent loops
|
|
85211
84814
|
_disableTools: true,
|
|
85212
|
-
// Only allow attempt_completion - prevent AI from using search/query tools
|
|
85213
84815
|
_completionPromptProcessed: true,
|
|
85214
|
-
// Prevent cascading completion prompts in retry calls
|
|
85215
84816
|
_maxIterationsOverride: 3
|
|
85216
|
-
// Correction should complete in 1-2 iterations (issue #447)
|
|
85217
84817
|
});
|
|
85218
84818
|
finalResult = cleanSchemaResponse(finalResult);
|
|
85219
|
-
validation = validateJsonResponse(finalResult, { debug: this.debug });
|
|
84819
|
+
validation = validateJsonResponse(finalResult, { debug: this.debug, schema: options.schema });
|
|
85220
84820
|
retryCount++;
|
|
85221
84821
|
if (this.debug) {
|
|
85222
84822
|
if (validation.isValid) {
|
|
85223
|
-
console.log(`[DEBUG] JSON validation:
|
|
84823
|
+
console.log(`[DEBUG] JSON validation: Correction successful on attempt ${retryCount}`);
|
|
85224
84824
|
} else {
|
|
85225
|
-
console.log(`[DEBUG] JSON validation:
|
|
84825
|
+
console.log(`[DEBUG] JSON validation: Correction failed on attempt ${retryCount}: ${validation.error}`);
|
|
85226
84826
|
}
|
|
85227
84827
|
}
|
|
85228
84828
|
}
|
|
85229
84829
|
if (this.tracer) {
|
|
85230
|
-
this.tracer.recordJsonValidationEvent("
|
|
84830
|
+
this.tracer.recordJsonValidationEvent("completed", {
|
|
85231
84831
|
"json_validation.success": validation.isValid,
|
|
85232
84832
|
"json_validation.retry_count": retryCount,
|
|
85233
|
-
"json_validation.
|
|
84833
|
+
"json_validation.max_retries": maxRetries,
|
|
84834
|
+
"json_validation.final_response_length": finalResult.length,
|
|
84835
|
+
"json_validation.error": validation.isValid ? null : validation.error
|
|
85234
84836
|
});
|
|
85235
84837
|
}
|
|
85236
84838
|
if (!validation.isValid && this.debug) {
|
|
85237
|
-
console.log(`[DEBUG] JSON validation:
|
|
85238
|
-
console.log(`[DEBUG] JSON validation: Final attempt_completion response: ${finalResult.substring(0, 500)}${finalResult.length > 500 ? "..." : ""}`);
|
|
84839
|
+
console.log(`[DEBUG] JSON validation: Failed after ${maxRetries} attempts: ${validation.error}`);
|
|
85239
84840
|
} else if (validation.isValid && this.debug) {
|
|
85240
|
-
console.log(`[DEBUG] JSON validation:
|
|
84841
|
+
console.log(`[DEBUG] JSON validation: Final validation successful`);
|
|
85241
84842
|
}
|
|
85242
84843
|
}
|
|
85243
84844
|
} catch (error) {
|
|
85244
84845
|
if (this.debug) {
|
|
85245
|
-
console.log(`[DEBUG]
|
|
84846
|
+
console.log(`[DEBUG] Schema validation/cleanup failed: ${error.message}`);
|
|
85246
84847
|
}
|
|
85247
84848
|
}
|
|
85248
84849
|
}
|
|
@@ -85341,7 +84942,6 @@ Convert your previous response content into actual JSON data that follows this s
|
|
|
85341
84942
|
* @returns {Object} Compaction statistics
|
|
85342
84943
|
*/
|
|
85343
84944
|
async compactHistory(options = {}) {
|
|
85344
|
-
const { compactMessages: compactMessages2, calculateCompactionStats: calculateCompactionStats2 } = await Promise.resolve().then(() => (init_contextCompactor(), contextCompactor_exports));
|
|
85345
84945
|
if (this.history.length === 0) {
|
|
85346
84946
|
if (this.debug) {
|
|
85347
84947
|
console.log(`[DEBUG] No history to compact for session ${this.sessionId}`);
|
|
@@ -85356,8 +84956,8 @@ Convert your previous response content into actual JSON data that follows this s
|
|
|
85356
84956
|
tokensSaved: 0
|
|
85357
84957
|
};
|
|
85358
84958
|
}
|
|
85359
|
-
const compactedMessages =
|
|
85360
|
-
const stats =
|
|
84959
|
+
const compactedMessages = compactMessages(this.history, options);
|
|
84960
|
+
const stats = calculateCompactionStats(this.history, compactedMessages);
|
|
85361
84961
|
this.history = compactedMessages;
|
|
85362
84962
|
try {
|
|
85363
84963
|
await this.storageAdapter.clearHistory(this.sessionId);
|
|
@@ -86418,7 +86018,9 @@ function parseArgs() {
|
|
|
86418
86018
|
disableDefaultBashAllow: false,
|
|
86419
86019
|
disableDefaultBashDeny: false,
|
|
86420
86020
|
// Native thinking/reasoning effort
|
|
86421
|
-
thinkingEffort: null
|
|
86021
|
+
thinkingEffort: null,
|
|
86022
|
+
// Completion prompt for post-completion validation/review
|
|
86023
|
+
completionPrompt: null
|
|
86422
86024
|
};
|
|
86423
86025
|
for (let i = 0; i < args.length; i++) {
|
|
86424
86026
|
const arg = args[i];
|
|
@@ -86452,6 +86054,8 @@ function parseArgs() {
|
|
|
86452
86054
|
config.architectureFileName = args[++i];
|
|
86453
86055
|
} else if (arg === "--schema" && i + 1 < args.length) {
|
|
86454
86056
|
config.schema = args[++i];
|
|
86057
|
+
} else if (arg === "--completion-prompt" && i + 1 < args.length) {
|
|
86058
|
+
config.completionPrompt = args[++i];
|
|
86455
86059
|
} else if (arg === "--provider" && i + 1 < args.length) {
|
|
86456
86060
|
config.provider = args[++i];
|
|
86457
86061
|
} else if (arg === "--model" && i + 1 < args.length) {
|
|
@@ -86538,6 +86142,7 @@ Options:
|
|
|
86538
86142
|
--system-prompt <text|file> Custom system prompt (text or file path)
|
|
86539
86143
|
--architecture-file <name> Architecture context filename in repo root (defaults to AGENTS.md with CLAUDE.md fallback; ARCHITECTURE.md is always included when present)
|
|
86540
86144
|
--schema <schema|file> Output schema (JSON, XML, any format - text or file path)
|
|
86145
|
+
--completion-prompt <text> Post-completion review prompt (validates/enriches the answer)
|
|
86541
86146
|
--provider <name> Force AI provider: anthropic, openai, google
|
|
86542
86147
|
--model <name> Override model name
|
|
86543
86148
|
--allow-edit Enable code modification capabilities (edit + create tools)
|
|
@@ -87040,7 +86645,8 @@ async function main() {
|
|
|
87040
86645
|
enableTasks: config.enableTasks,
|
|
87041
86646
|
thinkingEffort: config.thinkingEffort,
|
|
87042
86647
|
searchDelegateProvider: config.searchDelegateProvider,
|
|
87043
|
-
searchDelegateModel: config.searchDelegateModel
|
|
86648
|
+
searchDelegateModel: config.searchDelegateModel,
|
|
86649
|
+
completionPrompt: config.completionPrompt
|
|
87044
86650
|
};
|
|
87045
86651
|
const agent = new ProbeAgent(agentConfig2);
|
|
87046
86652
|
await agent.initialize();
|