@probelabs/probe 0.6.0-rc239 → 0.6.0-rc241
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-rc241-aarch64-apple-darwin.tar.gz +0 -0
- package/bin/binaries/{probe-v0.6.0-rc239-aarch64-unknown-linux-musl.tar.gz → probe-v0.6.0-rc241-aarch64-unknown-linux-musl.tar.gz} +0 -0
- package/bin/binaries/probe-v0.6.0-rc241-x86_64-apple-darwin.tar.gz +0 -0
- package/bin/binaries/probe-v0.6.0-rc241-x86_64-pc-windows-msvc.zip +0 -0
- package/bin/binaries/probe-v0.6.0-rc241-x86_64-unknown-linux-musl.tar.gz +0 -0
- package/build/agent/ProbeAgent.js +20 -2
- package/build/agent/dsl/validator.js +99 -8
- package/build/agent/index.js +213 -22
- package/build/agent/probeTool.js +9 -0
- package/build/agent/schemaUtils.js +34 -10
- package/build/agent/tools.js +9 -0
- package/build/index.js +5 -1
- package/build/tools/common.js +6 -0
- package/build/tools/executePlan.js +136 -2
- package/build/tools/index.js +3 -2
- package/cjs/agent/ProbeAgent.cjs +213 -22
- package/cjs/index.cjs +219 -19
- package/package.json +1 -1
- package/src/agent/ProbeAgent.js +20 -2
- package/src/agent/dsl/validator.js +99 -8
- package/src/agent/probeTool.js +9 -0
- package/src/agent/schemaUtils.js +34 -10
- package/src/agent/tools.js +9 -0
- package/src/index.js +5 -1
- package/src/tools/common.js +6 -0
- package/src/tools/executePlan.js +136 -2
- package/src/tools/index.js +3 -2
- package/bin/binaries/probe-v0.6.0-rc239-aarch64-apple-darwin.tar.gz +0 -0
- package/bin/binaries/probe-v0.6.0-rc239-x86_64-apple-darwin.tar.gz +0 -0
- package/bin/binaries/probe-v0.6.0-rc239-x86_64-pc-windows-msvc.zip +0 -0
- package/bin/binaries/probe-v0.6.0-rc239-x86_64-unknown-linux-musl.tar.gz +0 -0
package/cjs/index.cjs
CHANGED
|
@@ -38518,7 +38518,7 @@ function resolveTargetPath(target, cwd) {
|
|
|
38518
38518
|
}
|
|
38519
38519
|
return filePart + suffix;
|
|
38520
38520
|
}
|
|
38521
|
-
var import_path6, searchSchema, querySchema, extractSchema, delegateSchema, listSkillsSchema, useSkillSchema, bashSchema, analyzeAllSchema, executePlanSchema, attemptCompletionSchema, searchToolDefinition, queryToolDefinition, extractToolDefinition, delegateToolDefinition, attemptCompletionToolDefinition, analyzeAllToolDefinition, bashToolDefinition, googleSearchToolDefinition, urlContextToolDefinition, searchDescription, queryDescription, extractDescription, delegateDescription, bashDescription, analyzeAllDescription, DEFAULT_VALID_TOOLS;
|
|
38521
|
+
var import_path6, searchSchema, querySchema, extractSchema, delegateSchema, listSkillsSchema, useSkillSchema, bashSchema, analyzeAllSchema, executePlanSchema, cleanupExecutePlanSchema, attemptCompletionSchema, searchToolDefinition, queryToolDefinition, extractToolDefinition, delegateToolDefinition, attemptCompletionToolDefinition, analyzeAllToolDefinition, bashToolDefinition, googleSearchToolDefinition, urlContextToolDefinition, searchDescription, queryDescription, extractDescription, delegateDescription, bashDescription, analyzeAllDescription, DEFAULT_VALID_TOOLS;
|
|
38522
38522
|
var init_common2 = __esm({
|
|
38523
38523
|
"src/tools/common.js"() {
|
|
38524
38524
|
"use strict";
|
|
@@ -38567,6 +38567,10 @@ var init_common2 = __esm({
|
|
|
38567
38567
|
code: external_exports.string().min(1).describe("JavaScript DSL code to execute. All function calls look synchronous \u2014 do NOT use async/await. Use map(items, fn) for batch operations. Use LLM(instruction, data) for AI processing."),
|
|
38568
38568
|
description: external_exports.string().optional().describe("Human-readable description of what this plan does, for logging.")
|
|
38569
38569
|
});
|
|
38570
|
+
cleanupExecutePlanSchema = external_exports.object({
|
|
38571
|
+
clearOutputBuffer: external_exports.boolean().optional().default(true).describe("Clear the output buffer from previous execute_plan calls"),
|
|
38572
|
+
clearSessionStore: external_exports.boolean().optional().default(false).describe("Clear the session store (persisted data across execute_plan calls)")
|
|
38573
|
+
});
|
|
38570
38574
|
attemptCompletionSchema = {
|
|
38571
38575
|
// Custom validation that requires result parameter but allows direct XML response
|
|
38572
38576
|
safeParse: (params) => {
|
|
@@ -38915,6 +38919,7 @@ Capabilities:
|
|
|
38915
38919
|
"delegate",
|
|
38916
38920
|
"analyze_all",
|
|
38917
38921
|
"execute_plan",
|
|
38922
|
+
"cleanup_execute_plan",
|
|
38918
38923
|
"listSkills",
|
|
38919
38924
|
"useSkill",
|
|
38920
38925
|
"listFiles",
|
|
@@ -39560,6 +39565,9 @@ function createTools(configOptions) {
|
|
|
39560
39565
|
}
|
|
39561
39566
|
if (configOptions.enableExecutePlan && isToolAllowed("execute_plan")) {
|
|
39562
39567
|
tools2.executePlanTool = createExecutePlanTool(configOptions);
|
|
39568
|
+
if (isToolAllowed("cleanup_execute_plan")) {
|
|
39569
|
+
tools2.cleanupExecutePlanTool = createCleanupExecutePlanTool(configOptions);
|
|
39570
|
+
}
|
|
39563
39571
|
} else if (isToolAllowed("analyze_all")) {
|
|
39564
39572
|
tools2.analyzeAllTool = analyzeAllTool(configOptions);
|
|
39565
39573
|
}
|
|
@@ -46478,6 +46486,13 @@ function createWrappedTools(baseTools) {
|
|
|
46478
46486
|
baseTools.executePlanTool.execute
|
|
46479
46487
|
);
|
|
46480
46488
|
}
|
|
46489
|
+
if (baseTools.cleanupExecutePlanTool) {
|
|
46490
|
+
wrappedTools.cleanupExecutePlanToolInstance = wrapToolWithEmitter(
|
|
46491
|
+
baseTools.cleanupExecutePlanTool,
|
|
46492
|
+
"cleanup_execute_plan",
|
|
46493
|
+
baseTools.cleanupExecutePlanTool.execute
|
|
46494
|
+
);
|
|
46495
|
+
}
|
|
46481
46496
|
if (baseTools.bashTool) {
|
|
46482
46497
|
wrappedTools.bashToolInstance = wrapToolWithEmitter(
|
|
46483
46498
|
baseTools.bashTool,
|
|
@@ -83956,15 +83971,31 @@ function isSimpleTextWrapperSchema(schema) {
|
|
|
83956
83971
|
return null;
|
|
83957
83972
|
}
|
|
83958
83973
|
const trimmed = schema.trim();
|
|
83959
|
-
|
|
83960
|
-
|
|
83961
|
-
|
|
83962
|
-
|
|
83963
|
-
|
|
83964
|
-
|
|
83965
|
-
|
|
83966
|
-
|
|
83974
|
+
try {
|
|
83975
|
+
const parsed = JSON.parse(trimmed);
|
|
83976
|
+
if (typeof parsed !== "object" || parsed === null) {
|
|
83977
|
+
} else {
|
|
83978
|
+
const keys2 = Object.keys(parsed);
|
|
83979
|
+
if (keys2.length === 1 && parsed[keys2[0]] === "string") {
|
|
83980
|
+
return { fieldName: keys2[0] };
|
|
83981
|
+
}
|
|
83982
|
+
if (parsed.type === "object" && parsed.properties) {
|
|
83983
|
+
const propKeys = Object.keys(parsed.properties);
|
|
83984
|
+
if (propKeys.length === 1) {
|
|
83985
|
+
const prop = parsed.properties[propKeys[0]];
|
|
83986
|
+
if (prop && prop.type === "string") {
|
|
83987
|
+
return { fieldName: propKeys[0] };
|
|
83988
|
+
}
|
|
83989
|
+
}
|
|
83990
|
+
}
|
|
83991
|
+
return null;
|
|
83967
83992
|
}
|
|
83993
|
+
} catch {
|
|
83994
|
+
}
|
|
83995
|
+
const simplePattern = /^\{\s*["']?(\w+)["']?\s*:\s*["']?string["']?\s*\}$/i;
|
|
83996
|
+
const match2 = trimmed.match(simplePattern);
|
|
83997
|
+
if (match2) {
|
|
83998
|
+
return { fieldName: match2[1] };
|
|
83968
83999
|
}
|
|
83969
84000
|
return null;
|
|
83970
84001
|
}
|
|
@@ -96826,6 +96857,9 @@ var init_ProbeAgent = __esm({
|
|
|
96826
96857
|
}
|
|
96827
96858
|
if (this.enableExecutePlan && wrappedTools.executePlanToolInstance && isToolAllowed("execute_plan")) {
|
|
96828
96859
|
this.toolImplementations.execute_plan = wrappedTools.executePlanToolInstance;
|
|
96860
|
+
if (wrappedTools.cleanupExecutePlanToolInstance && isToolAllowed("cleanup_execute_plan")) {
|
|
96861
|
+
this.toolImplementations.cleanup_execute_plan = wrappedTools.cleanupExecutePlanToolInstance;
|
|
96862
|
+
}
|
|
96829
96863
|
} else if (wrappedTools.analyzeAllToolInstance && isToolAllowed("analyze_all")) {
|
|
96830
96864
|
this.toolImplementations.analyze_all = wrappedTools.analyzeAllToolInstance;
|
|
96831
96865
|
}
|
|
@@ -98199,6 +98233,10 @@ Workspace: ${this.allowedFolders.join(", ")}`;
|
|
|
98199
98233
|
if (this.enableBash && isToolAllowed("bash")) dslFunctions.push("bash");
|
|
98200
98234
|
toolDefinitions += `${getExecutePlanToolDefinition(dslFunctions)}
|
|
98201
98235
|
`;
|
|
98236
|
+
if (isToolAllowed("cleanup_execute_plan")) {
|
|
98237
|
+
toolDefinitions += `${getCleanupExecutePlanToolDefinition()}
|
|
98238
|
+
`;
|
|
98239
|
+
}
|
|
98202
98240
|
} else if (isToolAllowed("analyze_all")) {
|
|
98203
98241
|
toolDefinitions += `${analyzeAllToolDefinition}
|
|
98204
98242
|
`;
|
|
@@ -98274,6 +98312,9 @@ The configuration is loaded from src/config.js lines 15-25 which contains the da
|
|
|
98274
98312
|
}
|
|
98275
98313
|
if (this.enableExecutePlan && isToolAllowed("execute_plan")) {
|
|
98276
98314
|
availableToolsList += '- execute_plan: Execute a DSL program to orchestrate tool calls. ALWAYS use this for: questions containing "all"/"every"/"comprehensive"/"complete inventory", multi-topic analysis, open-ended discovery questions, or any task requiring full codebase coverage.\n';
|
|
98315
|
+
if (isToolAllowed("cleanup_execute_plan")) {
|
|
98316
|
+
availableToolsList += "- cleanup_execute_plan: Clean up output buffer and session store from previous execute_plan calls.\n";
|
|
98317
|
+
}
|
|
98277
98318
|
} else if (isToolAllowed("analyze_all")) {
|
|
98278
98319
|
availableToolsList += "- analyze_all: Process ALL data matching a query using map-reduce (for aggregate questions needing 100% coverage).\n";
|
|
98279
98320
|
}
|
|
@@ -98500,7 +98541,7 @@ You are working with a workspace. Available paths: ${workspaceDesc}
|
|
|
98500
98541
|
}
|
|
98501
98542
|
try {
|
|
98502
98543
|
const oldHistoryLength = this.history.length;
|
|
98503
|
-
if (this._outputBuffer) {
|
|
98544
|
+
if (this._outputBuffer && !options?._schemaFormatted) {
|
|
98504
98545
|
this._outputBuffer.items = [];
|
|
98505
98546
|
}
|
|
98506
98547
|
if (this.enableTasks) {
|
|
@@ -98860,6 +98901,9 @@ You are working with a workspace. Available paths: ${workspaceDesc}
|
|
|
98860
98901
|
}
|
|
98861
98902
|
if (this.enableExecutePlan && this.allowedTools.isEnabled("execute_plan")) {
|
|
98862
98903
|
validTools.push("execute_plan");
|
|
98904
|
+
if (this.allowedTools.isEnabled("cleanup_execute_plan")) {
|
|
98905
|
+
validTools.push("cleanup_execute_plan");
|
|
98906
|
+
}
|
|
98863
98907
|
} else if (this.allowedTools.isEnabled("analyze_all")) {
|
|
98864
98908
|
validTools.push("analyze_all");
|
|
98865
98909
|
}
|
|
@@ -112340,6 +112384,50 @@ var init_walk = __esm({
|
|
|
112340
112384
|
});
|
|
112341
112385
|
|
|
112342
112386
|
// src/agent/dsl/validator.js
|
|
112387
|
+
function offsetToLineColumn(code, offset2) {
|
|
112388
|
+
const lines = code.split("\n");
|
|
112389
|
+
let pos = 0;
|
|
112390
|
+
for (let i5 = 0; i5 < lines.length; i5++) {
|
|
112391
|
+
const lineLength = lines[i5].length + 1;
|
|
112392
|
+
if (pos + lineLength > offset2) {
|
|
112393
|
+
return { line: i5 + 1, column: offset2 - pos + 1 };
|
|
112394
|
+
}
|
|
112395
|
+
pos += lineLength;
|
|
112396
|
+
}
|
|
112397
|
+
return { line: lines.length, column: 1 };
|
|
112398
|
+
}
|
|
112399
|
+
function generateErrorSnippet(code, line, column, contextLines = 2) {
|
|
112400
|
+
const lines = code.split("\n");
|
|
112401
|
+
const startLine = Math.max(0, line - 1 - contextLines);
|
|
112402
|
+
const endLine = Math.min(lines.length, line + contextLines);
|
|
112403
|
+
const snippetLines = [];
|
|
112404
|
+
const lineNumWidth = String(endLine).length;
|
|
112405
|
+
for (let i5 = startLine; i5 < endLine; i5++) {
|
|
112406
|
+
const lineNum = String(i5 + 1).padStart(lineNumWidth, " ");
|
|
112407
|
+
const marker15 = i5 + 1 === line ? ">" : " ";
|
|
112408
|
+
snippetLines.push(`${marker15} ${lineNum} | ${lines[i5]}`);
|
|
112409
|
+
if (i5 + 1 === line) {
|
|
112410
|
+
const padding = " ".repeat(lineNumWidth + 4);
|
|
112411
|
+
const arrow = " ".repeat(Math.max(0, column - 1)) + "^";
|
|
112412
|
+
snippetLines.push(`${padding}${arrow}`);
|
|
112413
|
+
}
|
|
112414
|
+
}
|
|
112415
|
+
return snippetLines.join("\n");
|
|
112416
|
+
}
|
|
112417
|
+
function formatErrorWithSnippet(message, code, offset2 = -1, line = 0, column = 0) {
|
|
112418
|
+
if (offset2 >= 0) {
|
|
112419
|
+
const loc = offsetToLineColumn(code, offset2);
|
|
112420
|
+
line = loc.line;
|
|
112421
|
+
column = loc.column;
|
|
112422
|
+
}
|
|
112423
|
+
if (line <= 0) {
|
|
112424
|
+
return message;
|
|
112425
|
+
}
|
|
112426
|
+
const snippet = generateErrorSnippet(code, line, column);
|
|
112427
|
+
return `${message}
|
|
112428
|
+
|
|
112429
|
+
${snippet}`;
|
|
112430
|
+
}
|
|
112343
112431
|
function validateDSL(code) {
|
|
112344
112432
|
const errors = [];
|
|
112345
112433
|
let ast;
|
|
@@ -112347,40 +112435,54 @@ function validateDSL(code) {
|
|
|
112347
112435
|
ast = parse8(code, {
|
|
112348
112436
|
ecmaVersion: 2022,
|
|
112349
112437
|
sourceType: "script",
|
|
112350
|
-
allowReturnOutsideFunction: true
|
|
112438
|
+
allowReturnOutsideFunction: true,
|
|
112439
|
+
locations: true
|
|
112440
|
+
// Enable location tracking for better error messages
|
|
112351
112441
|
});
|
|
112352
112442
|
} catch (e5) {
|
|
112353
|
-
|
|
112443
|
+
const line = e5.loc?.line || 0;
|
|
112444
|
+
const column = e5.loc?.column ? e5.loc.column + 1 : 0;
|
|
112445
|
+
const formattedError = formatErrorWithSnippet(
|
|
112446
|
+
`Syntax error: ${e5.message}`,
|
|
112447
|
+
code,
|
|
112448
|
+
-1,
|
|
112449
|
+
line,
|
|
112450
|
+
column
|
|
112451
|
+
);
|
|
112452
|
+
return { valid: false, errors: [formattedError] };
|
|
112354
112453
|
}
|
|
112454
|
+
const addError = (message, position) => {
|
|
112455
|
+
errors.push(formatErrorWithSnippet(message, code, position));
|
|
112456
|
+
};
|
|
112355
112457
|
full(ast, (node) => {
|
|
112356
112458
|
if (!ALLOWED_NODE_TYPES.has(node.type)) {
|
|
112357
|
-
|
|
112459
|
+
addError(`Blocked node type: ${node.type}`, node.start);
|
|
112358
112460
|
return;
|
|
112359
112461
|
}
|
|
112360
112462
|
if ((node.type === "ArrowFunctionExpression" || node.type === "FunctionExpression") && node.async) {
|
|
112361
|
-
|
|
112463
|
+
addError(`Async functions are not allowed. Write synchronous code \u2014 the runtime handles async.`, node.start);
|
|
112362
112464
|
}
|
|
112363
112465
|
if (node.type === "FunctionExpression" && node.generator) {
|
|
112364
|
-
|
|
112466
|
+
addError(`Generator functions are not allowed`, node.start);
|
|
112365
112467
|
}
|
|
112366
112468
|
if (node.type === "Identifier" && BLOCKED_IDENTIFIERS.has(node.name)) {
|
|
112367
|
-
|
|
112469
|
+
addError(`Blocked identifier: '${node.name}'`, node.start);
|
|
112368
112470
|
}
|
|
112369
112471
|
if (node.type === "MemberExpression" && !node.computed) {
|
|
112370
112472
|
if (node.property.type === "Identifier" && BLOCKED_PROPERTIES.has(node.property.name)) {
|
|
112371
|
-
|
|
112473
|
+
addError(`Blocked property access: '.${node.property.name}'`, node.property.start);
|
|
112372
112474
|
}
|
|
112373
112475
|
}
|
|
112374
112476
|
if (node.type === "MemberExpression" && node.computed) {
|
|
112375
112477
|
if (node.property.type === "Literal" && typeof node.property.value === "string") {
|
|
112376
112478
|
if (BLOCKED_PROPERTIES.has(node.property.value) || BLOCKED_IDENTIFIERS.has(node.property.value)) {
|
|
112377
|
-
|
|
112479
|
+
addError(`Blocked computed property access: '["${node.property.value}"]'`, node.property.start);
|
|
112378
112480
|
}
|
|
112379
112481
|
}
|
|
112380
112482
|
}
|
|
112381
112483
|
if (node.type === "VariableDeclarator" && node.id.type === "Identifier") {
|
|
112382
112484
|
if (BLOCKED_IDENTIFIERS.has(node.id.name)) {
|
|
112383
|
-
|
|
112485
|
+
addError(`Cannot declare variable with blocked name: '${node.id.name}'`, node.id.start);
|
|
112384
112486
|
}
|
|
112385
112487
|
}
|
|
112386
112488
|
});
|
|
@@ -113011,10 +113113,32 @@ var init_runtime = __esm({
|
|
|
113011
113113
|
});
|
|
113012
113114
|
|
|
113013
113115
|
// src/tools/executePlan.js
|
|
113116
|
+
function decodeHtmlEntities2(str) {
|
|
113117
|
+
const entities = {
|
|
113118
|
+
"&": "&",
|
|
113119
|
+
"<": "<",
|
|
113120
|
+
">": ">",
|
|
113121
|
+
""": '"',
|
|
113122
|
+
"'": "'",
|
|
113123
|
+
"'": "'",
|
|
113124
|
+
"'": "'"
|
|
113125
|
+
};
|
|
113126
|
+
let result = str.replace(/&(?:amp|lt|gt|quot|apos|#39|#x27);/gi, (match2) => {
|
|
113127
|
+
return entities[match2.toLowerCase()] || match2;
|
|
113128
|
+
});
|
|
113129
|
+
result = result.replace(/&#(\d+);/g, (match2, dec) => {
|
|
113130
|
+
return String.fromCharCode(parseInt(dec, 10));
|
|
113131
|
+
});
|
|
113132
|
+
result = result.replace(/&#x([0-9a-f]+);/gi, (match2, hex) => {
|
|
113133
|
+
return String.fromCharCode(parseInt(hex, 16));
|
|
113134
|
+
});
|
|
113135
|
+
return result;
|
|
113136
|
+
}
|
|
113014
113137
|
function stripCodeWrapping(code) {
|
|
113015
113138
|
let s5 = String(code || "");
|
|
113016
113139
|
s5 = s5.replace(/^```(?:javascript|js)?\n?/gm, "").replace(/```$/gm, "");
|
|
113017
113140
|
s5 = s5.replace(/<\/?(?:execute_plan|code)>/g, "");
|
|
113141
|
+
s5 = decodeHtmlEntities2(s5);
|
|
113018
113142
|
return s5.trim();
|
|
113019
113143
|
}
|
|
113020
113144
|
function buildToolImplementations(configOptions) {
|
|
@@ -113266,6 +113390,14 @@ Logs: ${result.logs.join(" | ")}` : "";
|
|
|
113266
113390
|
"dsl.error": lastError.substring(0, 1e3)
|
|
113267
113391
|
});
|
|
113268
113392
|
}
|
|
113393
|
+
if (outputBuffer && outputBuffer.items && outputBuffer.items.length > 0) {
|
|
113394
|
+
const clearedChars = outputBuffer.items.reduce((sum, item) => sum + item.length, 0);
|
|
113395
|
+
outputBuffer.items = [];
|
|
113396
|
+
planSpan?.addEvent?.("dsl.auto_cleanup", {
|
|
113397
|
+
"cleanup.chars_cleared": clearedChars,
|
|
113398
|
+
"cleanup.reason": "all_retries_exhausted"
|
|
113399
|
+
});
|
|
113400
|
+
}
|
|
113269
113401
|
finalOutput = `Plan execution failed after ${maxRetries} retries.
|
|
113270
113402
|
|
|
113271
113403
|
Last error: ${lastError}`;
|
|
@@ -113278,6 +113410,9 @@ Last error: ${lastError}`;
|
|
|
113278
113410
|
planSpan?.end?.();
|
|
113279
113411
|
return finalOutput;
|
|
113280
113412
|
} catch (e5) {
|
|
113413
|
+
if (outputBuffer && outputBuffer.items && outputBuffer.items.length > 0) {
|
|
113414
|
+
outputBuffer.items = [];
|
|
113415
|
+
}
|
|
113281
113416
|
planSpan?.setStatus?.("ERROR");
|
|
113282
113417
|
planSpan?.addEvent?.("exception", {
|
|
113283
113418
|
"exception.message": e5.message,
|
|
@@ -113721,6 +113856,62 @@ output(table);
|
|
|
113721
113856
|
return "Generated table with " + results.length + " items.";
|
|
113722
113857
|
\`\`\``;
|
|
113723
113858
|
}
|
|
113859
|
+
function createCleanupExecutePlanTool(options) {
|
|
113860
|
+
const { outputBuffer, sessionStore, tracer } = options;
|
|
113861
|
+
return (0, import_ai6.tool)({
|
|
113862
|
+
description: "Clean up output buffer and session store from previous execute_plan calls. Use this when a previous execute_plan failed and left stale data, or before starting a fresh analysis.",
|
|
113863
|
+
parameters: cleanupExecutePlanSchema,
|
|
113864
|
+
execute: async ({ clearOutputBuffer = true, clearSessionStore = false }) => {
|
|
113865
|
+
const span = tracer?.createToolSpan?.("cleanup_execute_plan", {
|
|
113866
|
+
"cleanup.clear_output_buffer": clearOutputBuffer,
|
|
113867
|
+
"cleanup.clear_session_store": clearSessionStore
|
|
113868
|
+
}) || null;
|
|
113869
|
+
const results = [];
|
|
113870
|
+
try {
|
|
113871
|
+
if (clearOutputBuffer && outputBuffer) {
|
|
113872
|
+
const itemCount = outputBuffer.items?.length || 0;
|
|
113873
|
+
const charCount = outputBuffer.items?.reduce((sum, item) => sum + item.length, 0) || 0;
|
|
113874
|
+
outputBuffer.items = [];
|
|
113875
|
+
results.push(`Output buffer cleared (${itemCount} items, ${charCount} chars)`);
|
|
113876
|
+
}
|
|
113877
|
+
if (clearSessionStore && sessionStore) {
|
|
113878
|
+
const keyCount = Object.keys(sessionStore).length;
|
|
113879
|
+
for (const key of Object.keys(sessionStore)) {
|
|
113880
|
+
delete sessionStore[key];
|
|
113881
|
+
}
|
|
113882
|
+
results.push(`Session store cleared (${keyCount} keys)`);
|
|
113883
|
+
}
|
|
113884
|
+
const output = results.length > 0 ? `Cleanup complete:
|
|
113885
|
+
- ${results.join("\n- ")}` : "Nothing to clean up";
|
|
113886
|
+
span?.setAttributes?.({
|
|
113887
|
+
"cleanup.result": output,
|
|
113888
|
+
"cleanup.success": true
|
|
113889
|
+
});
|
|
113890
|
+
span?.setStatus?.("OK");
|
|
113891
|
+
span?.end?.();
|
|
113892
|
+
return output;
|
|
113893
|
+
} catch (e5) {
|
|
113894
|
+
span?.setStatus?.("ERROR");
|
|
113895
|
+
span?.addEvent?.("exception", { "exception.message": e5.message });
|
|
113896
|
+
span?.end?.();
|
|
113897
|
+
return `Cleanup failed: ${e5.message}`;
|
|
113898
|
+
}
|
|
113899
|
+
}
|
|
113900
|
+
});
|
|
113901
|
+
}
|
|
113902
|
+
function getCleanupExecutePlanToolDefinition() {
|
|
113903
|
+
return `## cleanup_execute_plan
|
|
113904
|
+
Description: Clean up output buffer and session store from previous execute_plan calls. Use when a previous execute_plan failed and left stale data, or before starting a fresh analysis.
|
|
113905
|
+
|
|
113906
|
+
Parameters:
|
|
113907
|
+
- clearOutputBuffer: (optional, default: true) Clear the output buffer from previous execute_plan calls
|
|
113908
|
+
- clearSessionStore: (optional, default: false) Clear the session store (persisted data across execute_plan calls)
|
|
113909
|
+
|
|
113910
|
+
Example:
|
|
113911
|
+
<cleanup_execute_plan>
|
|
113912
|
+
<clearOutputBuffer>true</clearOutputBuffer>
|
|
113913
|
+
</cleanup_execute_plan>`;
|
|
113914
|
+
}
|
|
113724
113915
|
var import_ai6;
|
|
113725
113916
|
var init_executePlan = __esm({
|
|
113726
113917
|
"src/tools/executePlan.js"() {
|
|
@@ -113879,6 +114070,8 @@ __export(tools_exports, {
|
|
|
113879
114070
|
bashTool: () => bashTool,
|
|
113880
114071
|
bashToolDefinition: () => bashToolDefinition,
|
|
113881
114072
|
buildToolTagPattern: () => buildToolTagPattern,
|
|
114073
|
+
cleanupExecutePlanSchema: () => cleanupExecutePlanSchema,
|
|
114074
|
+
createCleanupExecutePlanTool: () => createCleanupExecutePlanTool,
|
|
113882
114075
|
createDescription: () => createDescription,
|
|
113883
114076
|
createExecutePlanTool: () => createExecutePlanTool,
|
|
113884
114077
|
createExtractTool: () => createExtractTool,
|
|
@@ -113898,6 +114091,7 @@ __export(tools_exports, {
|
|
|
113898
114091
|
executePlanSchema: () => executePlanSchema,
|
|
113899
114092
|
extractSchema: () => extractSchema,
|
|
113900
114093
|
extractTool: () => extractTool,
|
|
114094
|
+
getCleanupExecutePlanToolDefinition: () => getCleanupExecutePlanToolDefinition,
|
|
113901
114095
|
getExecutePlanToolDefinition: () => getExecutePlanToolDefinition,
|
|
113902
114096
|
parseAndResolvePaths: () => parseAndResolvePaths,
|
|
113903
114097
|
querySchema: () => querySchema,
|
|
@@ -114522,6 +114716,8 @@ __export(index_exports, {
|
|
|
114522
114716
|
bashSchema: () => bashSchema,
|
|
114523
114717
|
bashTool: () => bashTool,
|
|
114524
114718
|
bashToolDefinition: () => bashToolDefinition,
|
|
114719
|
+
cleanupExecutePlanSchema: () => cleanupExecutePlanSchema,
|
|
114720
|
+
createCleanupExecutePlanTool: () => createCleanupExecutePlanTool,
|
|
114525
114721
|
createExecutePlanTool: () => createExecutePlanTool,
|
|
114526
114722
|
createSchema: () => createSchema,
|
|
114527
114723
|
createTaskTool: () => createTaskTool,
|
|
@@ -114540,6 +114736,7 @@ __export(index_exports, {
|
|
|
114540
114736
|
extractTool: () => extractTool,
|
|
114541
114737
|
extractToolDefinition: () => extractToolDefinition,
|
|
114542
114738
|
getBinaryPath: () => getBinaryPath,
|
|
114739
|
+
getCleanupExecutePlanToolDefinition: () => getCleanupExecutePlanToolDefinition,
|
|
114543
114740
|
getExecutePlanToolDefinition: () => getExecutePlanToolDefinition,
|
|
114544
114741
|
googleSearchToolDefinition: () => googleSearchToolDefinition,
|
|
114545
114742
|
grep: () => grep,
|
|
@@ -114612,6 +114809,8 @@ init_index();
|
|
|
114612
114809
|
bashSchema,
|
|
114613
114810
|
bashTool,
|
|
114614
114811
|
bashToolDefinition,
|
|
114812
|
+
cleanupExecutePlanSchema,
|
|
114813
|
+
createCleanupExecutePlanTool,
|
|
114615
114814
|
createExecutePlanTool,
|
|
114616
114815
|
createSchema,
|
|
114617
114816
|
createTaskTool,
|
|
@@ -114630,6 +114829,7 @@ init_index();
|
|
|
114630
114829
|
extractTool,
|
|
114631
114830
|
extractToolDefinition,
|
|
114632
114831
|
getBinaryPath,
|
|
114832
|
+
getCleanupExecutePlanToolDefinition,
|
|
114633
114833
|
getExecutePlanToolDefinition,
|
|
114634
114834
|
googleSearchToolDefinition,
|
|
114635
114835
|
grep,
|
package/package.json
CHANGED
package/src/agent/ProbeAgent.js
CHANGED
|
@@ -49,6 +49,7 @@ import {
|
|
|
49
49
|
delegateToolDefinition,
|
|
50
50
|
analyzeAllToolDefinition,
|
|
51
51
|
getExecutePlanToolDefinition,
|
|
52
|
+
getCleanupExecutePlanToolDefinition,
|
|
52
53
|
bashToolDefinition,
|
|
53
54
|
listFilesToolDefinition,
|
|
54
55
|
searchFilesToolDefinition,
|
|
@@ -870,6 +871,10 @@ export class ProbeAgent {
|
|
|
870
871
|
}
|
|
871
872
|
if (this.enableExecutePlan && wrappedTools.executePlanToolInstance && isToolAllowed('execute_plan')) {
|
|
872
873
|
this.toolImplementations.execute_plan = wrappedTools.executePlanToolInstance;
|
|
874
|
+
// cleanup_execute_plan is enabled together with execute_plan
|
|
875
|
+
if (wrappedTools.cleanupExecutePlanToolInstance && isToolAllowed('cleanup_execute_plan')) {
|
|
876
|
+
this.toolImplementations.cleanup_execute_plan = wrappedTools.cleanupExecutePlanToolInstance;
|
|
877
|
+
}
|
|
873
878
|
} else if (wrappedTools.analyzeAllToolInstance && isToolAllowed('analyze_all')) {
|
|
874
879
|
// analyze_all is fallback when execute_plan is not enabled
|
|
875
880
|
this.toolImplementations.analyze_all = wrappedTools.analyzeAllToolInstance;
|
|
@@ -2582,6 +2587,10 @@ ${extractGuidance}
|
|
|
2582
2587
|
if (isToolAllowed('listFiles')) dslFunctions.push('listFiles');
|
|
2583
2588
|
if (this.enableBash && isToolAllowed('bash')) dslFunctions.push('bash');
|
|
2584
2589
|
toolDefinitions += `${getExecutePlanToolDefinition(dslFunctions)}\n`;
|
|
2590
|
+
// cleanup_execute_plan is enabled together with execute_plan
|
|
2591
|
+
if (isToolAllowed('cleanup_execute_plan')) {
|
|
2592
|
+
toolDefinitions += `${getCleanupExecutePlanToolDefinition()}\n`;
|
|
2593
|
+
}
|
|
2585
2594
|
} else if (isToolAllowed('analyze_all')) {
|
|
2586
2595
|
// Fallback: only register analyze_all if execute_plan is not available
|
|
2587
2596
|
toolDefinitions += `${analyzeAllToolDefinition}\n`;
|
|
@@ -2661,6 +2670,9 @@ The configuration is loaded from src/config.js lines 15-25 which contains the da
|
|
|
2661
2670
|
}
|
|
2662
2671
|
if (this.enableExecutePlan && isToolAllowed('execute_plan')) {
|
|
2663
2672
|
availableToolsList += '- execute_plan: Execute a DSL program to orchestrate tool calls. ALWAYS use this for: questions containing "all"/"every"/"comprehensive"/"complete inventory", multi-topic analysis, open-ended discovery questions, or any task requiring full codebase coverage.\n';
|
|
2673
|
+
if (isToolAllowed('cleanup_execute_plan')) {
|
|
2674
|
+
availableToolsList += '- cleanup_execute_plan: Clean up output buffer and session store from previous execute_plan calls.\n';
|
|
2675
|
+
}
|
|
2664
2676
|
} else if (isToolAllowed('analyze_all')) {
|
|
2665
2677
|
availableToolsList += '- analyze_all: Process ALL data matching a query using map-reduce (for aggregate questions needing 100% coverage).\n';
|
|
2666
2678
|
}
|
|
@@ -2891,8 +2903,10 @@ Follow these instructions carefully:
|
|
|
2891
2903
|
// Track initial history length for storage
|
|
2892
2904
|
const oldHistoryLength = this.history.length;
|
|
2893
2905
|
|
|
2894
|
-
// Reset output buffer for this answer() call
|
|
2895
|
-
|
|
2906
|
+
// Reset output buffer for this answer() call — but NOT during schema correction recursion
|
|
2907
|
+
// When _schemaFormatted is true, this is a recursive call to fix JSON formatting,
|
|
2908
|
+
// and we must preserve the output buffer so the parent call can append it
|
|
2909
|
+
if (this._outputBuffer && !options?._schemaFormatted) {
|
|
2896
2910
|
this._outputBuffer.items = [];
|
|
2897
2911
|
}
|
|
2898
2912
|
|
|
@@ -3411,6 +3425,10 @@ Follow these instructions carefully:
|
|
|
3411
3425
|
// Execute Plan tool (requires enableExecutePlan flag, supersedes analyze_all)
|
|
3412
3426
|
if (this.enableExecutePlan && this.allowedTools.isEnabled('execute_plan')) {
|
|
3413
3427
|
validTools.push('execute_plan');
|
|
3428
|
+
// cleanup_execute_plan is enabled together with execute_plan
|
|
3429
|
+
if (this.allowedTools.isEnabled('cleanup_execute_plan')) {
|
|
3430
|
+
validTools.push('cleanup_execute_plan');
|
|
3431
|
+
}
|
|
3414
3432
|
} else if (this.allowedTools.isEnabled('analyze_all')) {
|
|
3415
3433
|
validTools.push('analyze_all');
|
|
3416
3434
|
}
|
|
@@ -9,6 +9,81 @@
|
|
|
9
9
|
import * as acorn from 'acorn';
|
|
10
10
|
import * as walk from 'acorn-walk';
|
|
11
11
|
|
|
12
|
+
/**
|
|
13
|
+
* Convert a character offset to line and column numbers.
|
|
14
|
+
* @param {string} code - The source code
|
|
15
|
+
* @param {number} offset - Character offset
|
|
16
|
+
* @returns {{ line: number, column: number }}
|
|
17
|
+
*/
|
|
18
|
+
function offsetToLineColumn(code, offset) {
|
|
19
|
+
const lines = code.split('\n');
|
|
20
|
+
let pos = 0;
|
|
21
|
+
for (let i = 0; i < lines.length; i++) {
|
|
22
|
+
const lineLength = lines[i].length + 1; // +1 for newline
|
|
23
|
+
if (pos + lineLength > offset) {
|
|
24
|
+
return { line: i + 1, column: offset - pos + 1 };
|
|
25
|
+
}
|
|
26
|
+
pos += lineLength;
|
|
27
|
+
}
|
|
28
|
+
return { line: lines.length, column: 1 };
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* Generate a code snippet with an arrow pointing to the error location.
|
|
33
|
+
* @param {string} code - The source code
|
|
34
|
+
* @param {number} line - Line number (1-based)
|
|
35
|
+
* @param {number} column - Column number (1-based)
|
|
36
|
+
* @param {number} contextLines - Number of lines to show before/after (default: 2)
|
|
37
|
+
* @returns {string}
|
|
38
|
+
*/
|
|
39
|
+
function generateErrorSnippet(code, line, column, contextLines = 2) {
|
|
40
|
+
const lines = code.split('\n');
|
|
41
|
+
const startLine = Math.max(0, line - 1 - contextLines);
|
|
42
|
+
const endLine = Math.min(lines.length, line + contextLines);
|
|
43
|
+
|
|
44
|
+
const snippetLines = [];
|
|
45
|
+
const lineNumWidth = String(endLine).length;
|
|
46
|
+
|
|
47
|
+
for (let i = startLine; i < endLine; i++) {
|
|
48
|
+
const lineNum = String(i + 1).padStart(lineNumWidth, ' ');
|
|
49
|
+
const marker = (i + 1 === line) ? '>' : ' ';
|
|
50
|
+
snippetLines.push(`${marker} ${lineNum} | ${lines[i]}`);
|
|
51
|
+
|
|
52
|
+
// Add arrow line for the error line
|
|
53
|
+
if (i + 1 === line) {
|
|
54
|
+
const padding = ' '.repeat(lineNumWidth + 4); // " 123 | " prefix
|
|
55
|
+
const arrow = ' '.repeat(Math.max(0, column - 1)) + '^';
|
|
56
|
+
snippetLines.push(`${padding}${arrow}`);
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
return snippetLines.join('\n');
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
/**
|
|
64
|
+
* Format an error message with code snippet.
|
|
65
|
+
* @param {string} message - The error message
|
|
66
|
+
* @param {string} code - The source code
|
|
67
|
+
* @param {number} offset - Character offset (optional, use -1 if line/column provided)
|
|
68
|
+
* @param {number} line - Line number (optional)
|
|
69
|
+
* @param {number} column - Column number (optional)
|
|
70
|
+
* @returns {string}
|
|
71
|
+
*/
|
|
72
|
+
function formatErrorWithSnippet(message, code, offset = -1, line = 0, column = 0) {
|
|
73
|
+
if (offset >= 0) {
|
|
74
|
+
const loc = offsetToLineColumn(code, offset);
|
|
75
|
+
line = loc.line;
|
|
76
|
+
column = loc.column;
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
if (line <= 0) {
|
|
80
|
+
return message;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
const snippet = generateErrorSnippet(code, line, column);
|
|
84
|
+
return `${message}\n\n${snippet}`;
|
|
85
|
+
}
|
|
86
|
+
|
|
12
87
|
// Node types the LLM is allowed to generate
|
|
13
88
|
const ALLOWED_NODE_TYPES = new Set([
|
|
14
89
|
'Program',
|
|
@@ -102,16 +177,32 @@ export function validateDSL(code) {
|
|
|
102
177
|
ecmaVersion: 2022,
|
|
103
178
|
sourceType: 'script',
|
|
104
179
|
allowReturnOutsideFunction: true,
|
|
180
|
+
locations: true, // Enable location tracking for better error messages
|
|
105
181
|
});
|
|
106
182
|
} catch (e) {
|
|
107
|
-
|
|
183
|
+
// Acorn errors have loc property with line/column
|
|
184
|
+
const line = e.loc?.line || 0;
|
|
185
|
+
const column = e.loc?.column ? e.loc.column + 1 : 0; // Acorn column is 0-based
|
|
186
|
+
const formattedError = formatErrorWithSnippet(
|
|
187
|
+
`Syntax error: ${e.message}`,
|
|
188
|
+
code,
|
|
189
|
+
-1,
|
|
190
|
+
line,
|
|
191
|
+
column
|
|
192
|
+
);
|
|
193
|
+
return { valid: false, errors: [formattedError] };
|
|
108
194
|
}
|
|
109
195
|
|
|
196
|
+
// Helper to add error with code snippet
|
|
197
|
+
const addError = (message, position) => {
|
|
198
|
+
errors.push(formatErrorWithSnippet(message, code, position));
|
|
199
|
+
};
|
|
200
|
+
|
|
110
201
|
// Step 2: Walk every node and validate
|
|
111
202
|
walk.full(ast, (node) => {
|
|
112
203
|
// Check node type against whitelist
|
|
113
204
|
if (!ALLOWED_NODE_TYPES.has(node.type)) {
|
|
114
|
-
|
|
205
|
+
addError(`Blocked node type: ${node.type}`, node.start);
|
|
115
206
|
return;
|
|
116
207
|
}
|
|
117
208
|
|
|
@@ -121,7 +212,7 @@ export function validateDSL(code) {
|
|
|
121
212
|
node.type === 'FunctionExpression') &&
|
|
122
213
|
node.async
|
|
123
214
|
) {
|
|
124
|
-
|
|
215
|
+
addError(`Async functions are not allowed. Write synchronous code — the runtime handles async.`, node.start);
|
|
125
216
|
}
|
|
126
217
|
|
|
127
218
|
// Block generator functions
|
|
@@ -129,19 +220,19 @@ export function validateDSL(code) {
|
|
|
129
220
|
(node.type === 'FunctionExpression') &&
|
|
130
221
|
node.generator
|
|
131
222
|
) {
|
|
132
|
-
|
|
223
|
+
addError(`Generator functions are not allowed`, node.start);
|
|
133
224
|
}
|
|
134
225
|
|
|
135
226
|
|
|
136
227
|
// Check identifiers against blocklist
|
|
137
228
|
if (node.type === 'Identifier' && BLOCKED_IDENTIFIERS.has(node.name)) {
|
|
138
|
-
|
|
229
|
+
addError(`Blocked identifier: '${node.name}'`, node.start);
|
|
139
230
|
}
|
|
140
231
|
|
|
141
232
|
// Check member expressions for blocked properties
|
|
142
233
|
if (node.type === 'MemberExpression' && !node.computed) {
|
|
143
234
|
if (node.property.type === 'Identifier' && BLOCKED_PROPERTIES.has(node.property.name)) {
|
|
144
|
-
|
|
235
|
+
addError(`Blocked property access: '.${node.property.name}'`, node.property.start);
|
|
145
236
|
}
|
|
146
237
|
}
|
|
147
238
|
|
|
@@ -149,7 +240,7 @@ export function validateDSL(code) {
|
|
|
149
240
|
if (node.type === 'MemberExpression' && node.computed) {
|
|
150
241
|
if (node.property.type === 'Literal' && typeof node.property.value === 'string') {
|
|
151
242
|
if (BLOCKED_PROPERTIES.has(node.property.value) || BLOCKED_IDENTIFIERS.has(node.property.value)) {
|
|
152
|
-
|
|
243
|
+
addError(`Blocked computed property access: '["${node.property.value}"]'`, node.property.start);
|
|
153
244
|
}
|
|
154
245
|
}
|
|
155
246
|
}
|
|
@@ -157,7 +248,7 @@ export function validateDSL(code) {
|
|
|
157
248
|
// Block variable declarations named with blocked identifiers
|
|
158
249
|
if (node.type === 'VariableDeclarator' && node.id.type === 'Identifier') {
|
|
159
250
|
if (BLOCKED_IDENTIFIERS.has(node.id.name)) {
|
|
160
|
-
|
|
251
|
+
addError(`Cannot declare variable with blocked name: '${node.id.name}'`, node.id.start);
|
|
161
252
|
}
|
|
162
253
|
}
|
|
163
254
|
});
|