@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
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
@@ -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
|
});
|
package/build/agent/index.js
CHANGED
|
@@ -9905,7 +9905,7 @@ function resolveTargetPath(target, cwd) {
|
|
|
9905
9905
|
}
|
|
9906
9906
|
return filePart + suffix;
|
|
9907
9907
|
}
|
|
9908
|
-
var searchSchema, querySchema, extractSchema, delegateSchema, listSkillsSchema, useSkillSchema, bashSchema, analyzeAllSchema, executePlanSchema, attemptCompletionSchema, searchToolDefinition, queryToolDefinition, extractToolDefinition, delegateToolDefinition, attemptCompletionToolDefinition, analyzeAllToolDefinition, bashToolDefinition, googleSearchToolDefinition, urlContextToolDefinition, searchDescription, queryDescription, extractDescription, delegateDescription, analyzeAllDescription, DEFAULT_VALID_TOOLS;
|
|
9908
|
+
var searchSchema, querySchema, extractSchema, delegateSchema, listSkillsSchema, useSkillSchema, bashSchema, analyzeAllSchema, executePlanSchema, cleanupExecutePlanSchema, attemptCompletionSchema, searchToolDefinition, queryToolDefinition, extractToolDefinition, delegateToolDefinition, attemptCompletionToolDefinition, analyzeAllToolDefinition, bashToolDefinition, googleSearchToolDefinition, urlContextToolDefinition, searchDescription, queryDescription, extractDescription, delegateDescription, analyzeAllDescription, DEFAULT_VALID_TOOLS;
|
|
9909
9909
|
var init_common = __esm({
|
|
9910
9910
|
"src/tools/common.js"() {
|
|
9911
9911
|
"use strict";
|
|
@@ -9953,6 +9953,10 @@ var init_common = __esm({
|
|
|
9953
9953
|
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."),
|
|
9954
9954
|
description: external_exports.string().optional().describe("Human-readable description of what this plan does, for logging.")
|
|
9955
9955
|
});
|
|
9956
|
+
cleanupExecutePlanSchema = external_exports.object({
|
|
9957
|
+
clearOutputBuffer: external_exports.boolean().optional().default(true).describe("Clear the output buffer from previous execute_plan calls"),
|
|
9958
|
+
clearSessionStore: external_exports.boolean().optional().default(false).describe("Clear the session store (persisted data across execute_plan calls)")
|
|
9959
|
+
});
|
|
9956
9960
|
attemptCompletionSchema = {
|
|
9957
9961
|
// Custom validation that requires result parameter but allows direct XML response
|
|
9958
9962
|
safeParse: (params) => {
|
|
@@ -10300,6 +10304,7 @@ Capabilities:
|
|
|
10300
10304
|
"delegate",
|
|
10301
10305
|
"analyze_all",
|
|
10302
10306
|
"execute_plan",
|
|
10307
|
+
"cleanup_execute_plan",
|
|
10303
10308
|
"listSkills",
|
|
10304
10309
|
"useSkill",
|
|
10305
10310
|
"listFiles",
|
|
@@ -21476,6 +21481,50 @@ var init_walk = __esm({
|
|
|
21476
21481
|
});
|
|
21477
21482
|
|
|
21478
21483
|
// src/agent/dsl/validator.js
|
|
21484
|
+
function offsetToLineColumn(code, offset2) {
|
|
21485
|
+
const lines = code.split("\n");
|
|
21486
|
+
let pos = 0;
|
|
21487
|
+
for (let i = 0; i < lines.length; i++) {
|
|
21488
|
+
const lineLength = lines[i].length + 1;
|
|
21489
|
+
if (pos + lineLength > offset2) {
|
|
21490
|
+
return { line: i + 1, column: offset2 - pos + 1 };
|
|
21491
|
+
}
|
|
21492
|
+
pos += lineLength;
|
|
21493
|
+
}
|
|
21494
|
+
return { line: lines.length, column: 1 };
|
|
21495
|
+
}
|
|
21496
|
+
function generateErrorSnippet(code, line, column, contextLines = 2) {
|
|
21497
|
+
const lines = code.split("\n");
|
|
21498
|
+
const startLine = Math.max(0, line - 1 - contextLines);
|
|
21499
|
+
const endLine = Math.min(lines.length, line + contextLines);
|
|
21500
|
+
const snippetLines = [];
|
|
21501
|
+
const lineNumWidth = String(endLine).length;
|
|
21502
|
+
for (let i = startLine; i < endLine; i++) {
|
|
21503
|
+
const lineNum = String(i + 1).padStart(lineNumWidth, " ");
|
|
21504
|
+
const marker = i + 1 === line ? ">" : " ";
|
|
21505
|
+
snippetLines.push(`${marker} ${lineNum} | ${lines[i]}`);
|
|
21506
|
+
if (i + 1 === line) {
|
|
21507
|
+
const padding = " ".repeat(lineNumWidth + 4);
|
|
21508
|
+
const arrow = " ".repeat(Math.max(0, column - 1)) + "^";
|
|
21509
|
+
snippetLines.push(`${padding}${arrow}`);
|
|
21510
|
+
}
|
|
21511
|
+
}
|
|
21512
|
+
return snippetLines.join("\n");
|
|
21513
|
+
}
|
|
21514
|
+
function formatErrorWithSnippet(message, code, offset2 = -1, line = 0, column = 0) {
|
|
21515
|
+
if (offset2 >= 0) {
|
|
21516
|
+
const loc = offsetToLineColumn(code, offset2);
|
|
21517
|
+
line = loc.line;
|
|
21518
|
+
column = loc.column;
|
|
21519
|
+
}
|
|
21520
|
+
if (line <= 0) {
|
|
21521
|
+
return message;
|
|
21522
|
+
}
|
|
21523
|
+
const snippet = generateErrorSnippet(code, line, column);
|
|
21524
|
+
return `${message}
|
|
21525
|
+
|
|
21526
|
+
${snippet}`;
|
|
21527
|
+
}
|
|
21479
21528
|
function validateDSL(code) {
|
|
21480
21529
|
const errors = [];
|
|
21481
21530
|
let ast;
|
|
@@ -21483,40 +21532,54 @@ function validateDSL(code) {
|
|
|
21483
21532
|
ast = parse3(code, {
|
|
21484
21533
|
ecmaVersion: 2022,
|
|
21485
21534
|
sourceType: "script",
|
|
21486
|
-
allowReturnOutsideFunction: true
|
|
21535
|
+
allowReturnOutsideFunction: true,
|
|
21536
|
+
locations: true
|
|
21537
|
+
// Enable location tracking for better error messages
|
|
21487
21538
|
});
|
|
21488
21539
|
} catch (e) {
|
|
21489
|
-
|
|
21540
|
+
const line = e.loc?.line || 0;
|
|
21541
|
+
const column = e.loc?.column ? e.loc.column + 1 : 0;
|
|
21542
|
+
const formattedError = formatErrorWithSnippet(
|
|
21543
|
+
`Syntax error: ${e.message}`,
|
|
21544
|
+
code,
|
|
21545
|
+
-1,
|
|
21546
|
+
line,
|
|
21547
|
+
column
|
|
21548
|
+
);
|
|
21549
|
+
return { valid: false, errors: [formattedError] };
|
|
21490
21550
|
}
|
|
21551
|
+
const addError = (message, position) => {
|
|
21552
|
+
errors.push(formatErrorWithSnippet(message, code, position));
|
|
21553
|
+
};
|
|
21491
21554
|
full(ast, (node) => {
|
|
21492
21555
|
if (!ALLOWED_NODE_TYPES.has(node.type)) {
|
|
21493
|
-
|
|
21556
|
+
addError(`Blocked node type: ${node.type}`, node.start);
|
|
21494
21557
|
return;
|
|
21495
21558
|
}
|
|
21496
21559
|
if ((node.type === "ArrowFunctionExpression" || node.type === "FunctionExpression") && node.async) {
|
|
21497
|
-
|
|
21560
|
+
addError(`Async functions are not allowed. Write synchronous code \u2014 the runtime handles async.`, node.start);
|
|
21498
21561
|
}
|
|
21499
21562
|
if (node.type === "FunctionExpression" && node.generator) {
|
|
21500
|
-
|
|
21563
|
+
addError(`Generator functions are not allowed`, node.start);
|
|
21501
21564
|
}
|
|
21502
21565
|
if (node.type === "Identifier" && BLOCKED_IDENTIFIERS.has(node.name)) {
|
|
21503
|
-
|
|
21566
|
+
addError(`Blocked identifier: '${node.name}'`, node.start);
|
|
21504
21567
|
}
|
|
21505
21568
|
if (node.type === "MemberExpression" && !node.computed) {
|
|
21506
21569
|
if (node.property.type === "Identifier" && BLOCKED_PROPERTIES.has(node.property.name)) {
|
|
21507
|
-
|
|
21570
|
+
addError(`Blocked property access: '.${node.property.name}'`, node.property.start);
|
|
21508
21571
|
}
|
|
21509
21572
|
}
|
|
21510
21573
|
if (node.type === "MemberExpression" && node.computed) {
|
|
21511
21574
|
if (node.property.type === "Literal" && typeof node.property.value === "string") {
|
|
21512
21575
|
if (BLOCKED_PROPERTIES.has(node.property.value) || BLOCKED_IDENTIFIERS.has(node.property.value)) {
|
|
21513
|
-
|
|
21576
|
+
addError(`Blocked computed property access: '["${node.property.value}"]'`, node.property.start);
|
|
21514
21577
|
}
|
|
21515
21578
|
}
|
|
21516
21579
|
}
|
|
21517
21580
|
if (node.type === "VariableDeclarator" && node.id.type === "Identifier") {
|
|
21518
21581
|
if (BLOCKED_IDENTIFIERS.has(node.id.name)) {
|
|
21519
|
-
|
|
21582
|
+
addError(`Cannot declare variable with blocked name: '${node.id.name}'`, node.id.start);
|
|
21520
21583
|
}
|
|
21521
21584
|
}
|
|
21522
21585
|
});
|
|
@@ -28831,10 +28894,32 @@ var init_esm5 = __esm({
|
|
|
28831
28894
|
|
|
28832
28895
|
// src/tools/executePlan.js
|
|
28833
28896
|
import { tool as tool4 } from "ai";
|
|
28897
|
+
function decodeHtmlEntities(str) {
|
|
28898
|
+
const entities = {
|
|
28899
|
+
"&": "&",
|
|
28900
|
+
"<": "<",
|
|
28901
|
+
">": ">",
|
|
28902
|
+
""": '"',
|
|
28903
|
+
"'": "'",
|
|
28904
|
+
"'": "'",
|
|
28905
|
+
"'": "'"
|
|
28906
|
+
};
|
|
28907
|
+
let result = str.replace(/&(?:amp|lt|gt|quot|apos|#39|#x27);/gi, (match2) => {
|
|
28908
|
+
return entities[match2.toLowerCase()] || match2;
|
|
28909
|
+
});
|
|
28910
|
+
result = result.replace(/&#(\d+);/g, (match2, dec) => {
|
|
28911
|
+
return String.fromCharCode(parseInt(dec, 10));
|
|
28912
|
+
});
|
|
28913
|
+
result = result.replace(/&#x([0-9a-f]+);/gi, (match2, hex) => {
|
|
28914
|
+
return String.fromCharCode(parseInt(hex, 16));
|
|
28915
|
+
});
|
|
28916
|
+
return result;
|
|
28917
|
+
}
|
|
28834
28918
|
function stripCodeWrapping(code) {
|
|
28835
28919
|
let s = String(code || "");
|
|
28836
28920
|
s = s.replace(/^```(?:javascript|js)?\n?/gm, "").replace(/```$/gm, "");
|
|
28837
28921
|
s = s.replace(/<\/?(?:execute_plan|code)>/g, "");
|
|
28922
|
+
s = decodeHtmlEntities(s);
|
|
28838
28923
|
return s.trim();
|
|
28839
28924
|
}
|
|
28840
28925
|
function buildToolImplementations(configOptions) {
|
|
@@ -29086,6 +29171,14 @@ Logs: ${result.logs.join(" | ")}` : "";
|
|
|
29086
29171
|
"dsl.error": lastError.substring(0, 1e3)
|
|
29087
29172
|
});
|
|
29088
29173
|
}
|
|
29174
|
+
if (outputBuffer && outputBuffer.items && outputBuffer.items.length > 0) {
|
|
29175
|
+
const clearedChars = outputBuffer.items.reduce((sum, item) => sum + item.length, 0);
|
|
29176
|
+
outputBuffer.items = [];
|
|
29177
|
+
planSpan?.addEvent?.("dsl.auto_cleanup", {
|
|
29178
|
+
"cleanup.chars_cleared": clearedChars,
|
|
29179
|
+
"cleanup.reason": "all_retries_exhausted"
|
|
29180
|
+
});
|
|
29181
|
+
}
|
|
29089
29182
|
finalOutput = `Plan execution failed after ${maxRetries} retries.
|
|
29090
29183
|
|
|
29091
29184
|
Last error: ${lastError}`;
|
|
@@ -29098,6 +29191,9 @@ Last error: ${lastError}`;
|
|
|
29098
29191
|
planSpan?.end?.();
|
|
29099
29192
|
return finalOutput;
|
|
29100
29193
|
} catch (e) {
|
|
29194
|
+
if (outputBuffer && outputBuffer.items && outputBuffer.items.length > 0) {
|
|
29195
|
+
outputBuffer.items = [];
|
|
29196
|
+
}
|
|
29101
29197
|
planSpan?.setStatus?.("ERROR");
|
|
29102
29198
|
planSpan?.addEvent?.("exception", {
|
|
29103
29199
|
"exception.message": e.message,
|
|
@@ -29541,6 +29637,62 @@ output(table);
|
|
|
29541
29637
|
return "Generated table with " + results.length + " items.";
|
|
29542
29638
|
\`\`\``;
|
|
29543
29639
|
}
|
|
29640
|
+
function createCleanupExecutePlanTool(options) {
|
|
29641
|
+
const { outputBuffer, sessionStore, tracer } = options;
|
|
29642
|
+
return tool4({
|
|
29643
|
+
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.",
|
|
29644
|
+
parameters: cleanupExecutePlanSchema,
|
|
29645
|
+
execute: async ({ clearOutputBuffer = true, clearSessionStore = false }) => {
|
|
29646
|
+
const span = tracer?.createToolSpan?.("cleanup_execute_plan", {
|
|
29647
|
+
"cleanup.clear_output_buffer": clearOutputBuffer,
|
|
29648
|
+
"cleanup.clear_session_store": clearSessionStore
|
|
29649
|
+
}) || null;
|
|
29650
|
+
const results = [];
|
|
29651
|
+
try {
|
|
29652
|
+
if (clearOutputBuffer && outputBuffer) {
|
|
29653
|
+
const itemCount = outputBuffer.items?.length || 0;
|
|
29654
|
+
const charCount = outputBuffer.items?.reduce((sum, item) => sum + item.length, 0) || 0;
|
|
29655
|
+
outputBuffer.items = [];
|
|
29656
|
+
results.push(`Output buffer cleared (${itemCount} items, ${charCount} chars)`);
|
|
29657
|
+
}
|
|
29658
|
+
if (clearSessionStore && sessionStore) {
|
|
29659
|
+
const keyCount = Object.keys(sessionStore).length;
|
|
29660
|
+
for (const key of Object.keys(sessionStore)) {
|
|
29661
|
+
delete sessionStore[key];
|
|
29662
|
+
}
|
|
29663
|
+
results.push(`Session store cleared (${keyCount} keys)`);
|
|
29664
|
+
}
|
|
29665
|
+
const output = results.length > 0 ? `Cleanup complete:
|
|
29666
|
+
- ${results.join("\n- ")}` : "Nothing to clean up";
|
|
29667
|
+
span?.setAttributes?.({
|
|
29668
|
+
"cleanup.result": output,
|
|
29669
|
+
"cleanup.success": true
|
|
29670
|
+
});
|
|
29671
|
+
span?.setStatus?.("OK");
|
|
29672
|
+
span?.end?.();
|
|
29673
|
+
return output;
|
|
29674
|
+
} catch (e) {
|
|
29675
|
+
span?.setStatus?.("ERROR");
|
|
29676
|
+
span?.addEvent?.("exception", { "exception.message": e.message });
|
|
29677
|
+
span?.end?.();
|
|
29678
|
+
return `Cleanup failed: ${e.message}`;
|
|
29679
|
+
}
|
|
29680
|
+
}
|
|
29681
|
+
});
|
|
29682
|
+
}
|
|
29683
|
+
function getCleanupExecutePlanToolDefinition() {
|
|
29684
|
+
return `## cleanup_execute_plan
|
|
29685
|
+
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.
|
|
29686
|
+
|
|
29687
|
+
Parameters:
|
|
29688
|
+
- clearOutputBuffer: (optional, default: true) Clear the output buffer from previous execute_plan calls
|
|
29689
|
+
- clearSessionStore: (optional, default: false) Clear the session store (persisted data across execute_plan calls)
|
|
29690
|
+
|
|
29691
|
+
Example:
|
|
29692
|
+
<cleanup_execute_plan>
|
|
29693
|
+
<clearOutputBuffer>true</clearOutputBuffer>
|
|
29694
|
+
</cleanup_execute_plan>`;
|
|
29695
|
+
}
|
|
29544
29696
|
var init_executePlan = __esm({
|
|
29545
29697
|
"src/tools/executePlan.js"() {
|
|
29546
29698
|
"use strict";
|
|
@@ -30336,6 +30488,13 @@ function createWrappedTools(baseTools) {
|
|
|
30336
30488
|
baseTools.executePlanTool.execute
|
|
30337
30489
|
);
|
|
30338
30490
|
}
|
|
30491
|
+
if (baseTools.cleanupExecutePlanTool) {
|
|
30492
|
+
wrappedTools.cleanupExecutePlanToolInstance = wrapToolWithEmitter(
|
|
30493
|
+
baseTools.cleanupExecutePlanTool,
|
|
30494
|
+
"cleanup_execute_plan",
|
|
30495
|
+
baseTools.cleanupExecutePlanTool.execute
|
|
30496
|
+
);
|
|
30497
|
+
}
|
|
30339
30498
|
if (baseTools.bashTool) {
|
|
30340
30499
|
wrappedTools.bashToolInstance = wrapToolWithEmitter(
|
|
30341
30500
|
baseTools.bashTool,
|
|
@@ -31245,6 +31404,9 @@ function createTools(configOptions) {
|
|
|
31245
31404
|
}
|
|
31246
31405
|
if (configOptions.enableExecutePlan && isToolAllowed("execute_plan")) {
|
|
31247
31406
|
tools2.executePlanTool = createExecutePlanTool(configOptions);
|
|
31407
|
+
if (isToolAllowed("cleanup_execute_plan")) {
|
|
31408
|
+
tools2.cleanupExecutePlanTool = createCleanupExecutePlanTool(configOptions);
|
|
31409
|
+
}
|
|
31248
31410
|
} else if (isToolAllowed("analyze_all")) {
|
|
31249
31411
|
tools2.analyzeAllTool = analyzeAllTool(configOptions);
|
|
31250
31412
|
}
|
|
@@ -68122,7 +68284,7 @@ __export(schemaUtils_exports, {
|
|
|
68122
68284
|
createJsonCorrectionPrompt: () => createJsonCorrectionPrompt,
|
|
68123
68285
|
createMermaidCorrectionPrompt: () => createMermaidCorrectionPrompt,
|
|
68124
68286
|
createSchemaDefinitionCorrectionPrompt: () => createSchemaDefinitionCorrectionPrompt,
|
|
68125
|
-
decodeHtmlEntities: () =>
|
|
68287
|
+
decodeHtmlEntities: () => decodeHtmlEntities2,
|
|
68126
68288
|
extractMermaidFromJson: () => extractMermaidFromJson,
|
|
68127
68289
|
extractMermaidFromMarkdown: () => extractMermaidFromMarkdown,
|
|
68128
68290
|
generateExampleFromSchema: () => generateExampleFromSchema,
|
|
@@ -68227,7 +68389,7 @@ function enforceNoAdditionalProperties(schema) {
|
|
|
68227
68389
|
applyRecursively(cloned);
|
|
68228
68390
|
return cloned;
|
|
68229
68391
|
}
|
|
68230
|
-
function
|
|
68392
|
+
function decodeHtmlEntities2(text) {
|
|
68231
68393
|
if (!text || typeof text !== "string") {
|
|
68232
68394
|
return text;
|
|
68233
68395
|
}
|
|
@@ -68657,15 +68819,31 @@ function isSimpleTextWrapperSchema(schema) {
|
|
|
68657
68819
|
return null;
|
|
68658
68820
|
}
|
|
68659
68821
|
const trimmed = schema.trim();
|
|
68660
|
-
|
|
68661
|
-
|
|
68662
|
-
|
|
68663
|
-
|
|
68664
|
-
|
|
68665
|
-
|
|
68666
|
-
|
|
68667
|
-
|
|
68822
|
+
try {
|
|
68823
|
+
const parsed = JSON.parse(trimmed);
|
|
68824
|
+
if (typeof parsed !== "object" || parsed === null) {
|
|
68825
|
+
} else {
|
|
68826
|
+
const keys2 = Object.keys(parsed);
|
|
68827
|
+
if (keys2.length === 1 && parsed[keys2[0]] === "string") {
|
|
68828
|
+
return { fieldName: keys2[0] };
|
|
68829
|
+
}
|
|
68830
|
+
if (parsed.type === "object" && parsed.properties) {
|
|
68831
|
+
const propKeys = Object.keys(parsed.properties);
|
|
68832
|
+
if (propKeys.length === 1) {
|
|
68833
|
+
const prop = parsed.properties[propKeys[0]];
|
|
68834
|
+
if (prop && prop.type === "string") {
|
|
68835
|
+
return { fieldName: propKeys[0] };
|
|
68836
|
+
}
|
|
68837
|
+
}
|
|
68838
|
+
}
|
|
68839
|
+
return null;
|
|
68668
68840
|
}
|
|
68841
|
+
} catch {
|
|
68842
|
+
}
|
|
68843
|
+
const simplePattern = /^\{\s*["']?(\w+)["']?\s*:\s*["']?string["']?\s*\}$/i;
|
|
68844
|
+
const match2 = trimmed.match(simplePattern);
|
|
68845
|
+
if (match2) {
|
|
68846
|
+
return { fieldName: match2[1] };
|
|
68669
68847
|
}
|
|
68670
68848
|
return null;
|
|
68671
68849
|
}
|
|
@@ -69654,7 +69832,7 @@ When presented with a broken Mermaid diagram, analyze it thoroughly and provide
|
|
|
69654
69832
|
* @returns {Promise<string>} - The corrected Mermaid diagram
|
|
69655
69833
|
*/
|
|
69656
69834
|
async fixMermaidDiagram(diagramContent, originalErrors = [], diagramInfo = {}) {
|
|
69657
|
-
const decodedContent =
|
|
69835
|
+
const decodedContent = decodeHtmlEntities2(diagramContent);
|
|
69658
69836
|
if (decodedContent !== diagramContent) {
|
|
69659
69837
|
try {
|
|
69660
69838
|
const quickValidation = await validateMermaidDiagram(decodedContent);
|
|
@@ -81528,6 +81706,9 @@ var init_ProbeAgent = __esm({
|
|
|
81528
81706
|
}
|
|
81529
81707
|
if (this.enableExecutePlan && wrappedTools.executePlanToolInstance && isToolAllowed("execute_plan")) {
|
|
81530
81708
|
this.toolImplementations.execute_plan = wrappedTools.executePlanToolInstance;
|
|
81709
|
+
if (wrappedTools.cleanupExecutePlanToolInstance && isToolAllowed("cleanup_execute_plan")) {
|
|
81710
|
+
this.toolImplementations.cleanup_execute_plan = wrappedTools.cleanupExecutePlanToolInstance;
|
|
81711
|
+
}
|
|
81531
81712
|
} else if (wrappedTools.analyzeAllToolInstance && isToolAllowed("analyze_all")) {
|
|
81532
81713
|
this.toolImplementations.analyze_all = wrappedTools.analyzeAllToolInstance;
|
|
81533
81714
|
}
|
|
@@ -82901,6 +83082,10 @@ Workspace: ${this.allowedFolders.join(", ")}`;
|
|
|
82901
83082
|
if (this.enableBash && isToolAllowed("bash")) dslFunctions.push("bash");
|
|
82902
83083
|
toolDefinitions += `${getExecutePlanToolDefinition(dslFunctions)}
|
|
82903
83084
|
`;
|
|
83085
|
+
if (isToolAllowed("cleanup_execute_plan")) {
|
|
83086
|
+
toolDefinitions += `${getCleanupExecutePlanToolDefinition()}
|
|
83087
|
+
`;
|
|
83088
|
+
}
|
|
82904
83089
|
} else if (isToolAllowed("analyze_all")) {
|
|
82905
83090
|
toolDefinitions += `${analyzeAllToolDefinition}
|
|
82906
83091
|
`;
|
|
@@ -82976,6 +83161,9 @@ The configuration is loaded from src/config.js lines 15-25 which contains the da
|
|
|
82976
83161
|
}
|
|
82977
83162
|
if (this.enableExecutePlan && isToolAllowed("execute_plan")) {
|
|
82978
83163
|
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';
|
|
83164
|
+
if (isToolAllowed("cleanup_execute_plan")) {
|
|
83165
|
+
availableToolsList += "- cleanup_execute_plan: Clean up output buffer and session store from previous execute_plan calls.\n";
|
|
83166
|
+
}
|
|
82979
83167
|
} else if (isToolAllowed("analyze_all")) {
|
|
82980
83168
|
availableToolsList += "- analyze_all: Process ALL data matching a query using map-reduce (for aggregate questions needing 100% coverage).\n";
|
|
82981
83169
|
}
|
|
@@ -83202,7 +83390,7 @@ You are working with a workspace. Available paths: ${workspaceDesc}
|
|
|
83202
83390
|
}
|
|
83203
83391
|
try {
|
|
83204
83392
|
const oldHistoryLength = this.history.length;
|
|
83205
|
-
if (this._outputBuffer) {
|
|
83393
|
+
if (this._outputBuffer && !options?._schemaFormatted) {
|
|
83206
83394
|
this._outputBuffer.items = [];
|
|
83207
83395
|
}
|
|
83208
83396
|
if (this.enableTasks) {
|
|
@@ -83562,6 +83750,9 @@ You are working with a workspace. Available paths: ${workspaceDesc}
|
|
|
83562
83750
|
}
|
|
83563
83751
|
if (this.enableExecutePlan && this.allowedTools.isEnabled("execute_plan")) {
|
|
83564
83752
|
validTools.push("execute_plan");
|
|
83753
|
+
if (this.allowedTools.isEnabled("cleanup_execute_plan")) {
|
|
83754
|
+
validTools.push("cleanup_execute_plan");
|
|
83755
|
+
}
|
|
83565
83756
|
} else if (this.allowedTools.isEnabled("analyze_all")) {
|
|
83566
83757
|
validTools.push("analyze_all");
|
|
83567
83758
|
}
|
package/build/agent/probeTool.js
CHANGED
|
@@ -220,6 +220,15 @@ export function createWrappedTools(baseTools) {
|
|
|
220
220
|
);
|
|
221
221
|
}
|
|
222
222
|
|
|
223
|
+
// Wrap cleanup_execute_plan tool
|
|
224
|
+
if (baseTools.cleanupExecutePlanTool) {
|
|
225
|
+
wrappedTools.cleanupExecutePlanToolInstance = wrapToolWithEmitter(
|
|
226
|
+
baseTools.cleanupExecutePlanTool,
|
|
227
|
+
'cleanup_execute_plan',
|
|
228
|
+
baseTools.cleanupExecutePlanTool.execute
|
|
229
|
+
);
|
|
230
|
+
}
|
|
231
|
+
|
|
223
232
|
// Wrap bash tool
|
|
224
233
|
if (baseTools.bashTool) {
|
|
225
234
|
wrappedTools.bashToolInstance = wrapToolWithEmitter(
|