@probelabs/probe 0.6.0-rc178 → 0.6.0-rc187
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/build/agent/ProbeAgent.d.ts +15 -0
- package/build/agent/ProbeAgent.js +50 -23
- package/build/agent/bashCommandUtils.js +63 -0
- package/build/agent/bashExecutor.js +34 -19
- package/build/agent/bashPermissions.js +74 -13
- package/build/agent/index.js +232 -67
- package/build/agent/schemaUtils.js +7 -6
- package/build/delegate.js +10 -4
- package/build/tools/vercel.js +6 -2
- package/cjs/agent/ProbeAgent.cjs +2842 -1870
- package/cjs/index.cjs +2842 -1870
- package/package.json +1 -1
- package/src/agent/ProbeAgent.d.ts +15 -0
- package/src/agent/ProbeAgent.js +50 -23
- package/src/agent/bashCommandUtils.js +63 -0
- package/src/agent/bashExecutor.js +34 -19
- package/src/agent/bashPermissions.js +74 -13
- package/src/agent/index.js +3 -3
- package/src/agent/schemaUtils.js +7 -6
- package/src/delegate.js +10 -4
- package/src/tools/vercel.js +6 -2
package/build/agent/index.js
CHANGED
|
@@ -3513,7 +3513,9 @@ async function delegate({
|
|
|
3513
3513
|
parentSessionId = null,
|
|
3514
3514
|
path: path9 = null,
|
|
3515
3515
|
provider = null,
|
|
3516
|
-
model = null
|
|
3516
|
+
model = null,
|
|
3517
|
+
enableBash = false,
|
|
3518
|
+
bashConfig = null
|
|
3517
3519
|
}) {
|
|
3518
3520
|
if (!task || typeof task !== "string") {
|
|
3519
3521
|
throw new Error("Task parameter is required and must be a string");
|
|
@@ -3555,7 +3557,11 @@ async function delegate({
|
|
|
3555
3557
|
// Inherit from parent
|
|
3556
3558
|
provider,
|
|
3557
3559
|
// Inherit from parent
|
|
3558
|
-
model
|
|
3560
|
+
model,
|
|
3561
|
+
// Inherit from parent
|
|
3562
|
+
enableBash,
|
|
3563
|
+
// Inherit from parent
|
|
3564
|
+
bashConfig
|
|
3559
3565
|
// Inherit from parent
|
|
3560
3566
|
});
|
|
3561
3567
|
if (debug) {
|
|
@@ -8455,7 +8461,7 @@ var init_vercel = __esm({
|
|
|
8455
8461
|
});
|
|
8456
8462
|
};
|
|
8457
8463
|
delegateTool = (options = {}) => {
|
|
8458
|
-
const { debug = false, timeout = 300, cwd, allowedFolders } = options;
|
|
8464
|
+
const { debug = false, timeout = 300, cwd, allowedFolders, enableBash = false, bashConfig } = options;
|
|
8459
8465
|
return tool({
|
|
8460
8466
|
name: "delegate",
|
|
8461
8467
|
description: delegateDescription,
|
|
@@ -8505,7 +8511,9 @@ var init_vercel = __esm({
|
|
|
8505
8511
|
path: effectivePath,
|
|
8506
8512
|
provider,
|
|
8507
8513
|
model,
|
|
8508
|
-
tracer
|
|
8514
|
+
tracer,
|
|
8515
|
+
enableBash,
|
|
8516
|
+
bashConfig
|
|
8509
8517
|
});
|
|
8510
8518
|
return result;
|
|
8511
8519
|
}
|
|
@@ -9136,6 +9144,46 @@ function isComplexCommand(command) {
|
|
|
9136
9144
|
const result = parseSimpleCommand(command);
|
|
9137
9145
|
return result.isComplex;
|
|
9138
9146
|
}
|
|
9147
|
+
function isComplexPattern(pattern) {
|
|
9148
|
+
if (!pattern || typeof pattern !== "string") return false;
|
|
9149
|
+
const operatorPatterns = [
|
|
9150
|
+
/\|/,
|
|
9151
|
+
// Pipes
|
|
9152
|
+
/&&/,
|
|
9153
|
+
// Logical AND
|
|
9154
|
+
/\|\|/,
|
|
9155
|
+
// Logical OR
|
|
9156
|
+
/;/,
|
|
9157
|
+
// Command separator
|
|
9158
|
+
/&$/,
|
|
9159
|
+
// Background execution
|
|
9160
|
+
/\$\(/,
|
|
9161
|
+
// Command substitution $()
|
|
9162
|
+
/`/,
|
|
9163
|
+
// Command substitution ``
|
|
9164
|
+
/>/,
|
|
9165
|
+
// Redirection >
|
|
9166
|
+
/</
|
|
9167
|
+
// Redirection <
|
|
9168
|
+
];
|
|
9169
|
+
return operatorPatterns.some((p) => p.test(pattern));
|
|
9170
|
+
}
|
|
9171
|
+
function globToRegex(pattern) {
|
|
9172
|
+
let escaped = pattern.replace(/[.+?^${}()|[\]\\]/g, "\\$&");
|
|
9173
|
+
escaped = escaped.replace(/\*/g, ".*?");
|
|
9174
|
+
return new RegExp("^" + escaped + "$", "i");
|
|
9175
|
+
}
|
|
9176
|
+
function matchesComplexPattern(command, pattern) {
|
|
9177
|
+
if (!command || !pattern) return false;
|
|
9178
|
+
const normalizedCommand = command.trim().replace(/\s+/g, " ");
|
|
9179
|
+
const normalizedPattern = pattern.trim().replace(/\s+/g, " ");
|
|
9180
|
+
try {
|
|
9181
|
+
const regex = globToRegex(normalizedPattern);
|
|
9182
|
+
return regex.test(normalizedCommand);
|
|
9183
|
+
} catch (e) {
|
|
9184
|
+
return normalizedCommand === normalizedPattern;
|
|
9185
|
+
}
|
|
9186
|
+
}
|
|
9139
9187
|
function parseCommand(command) {
|
|
9140
9188
|
const result = parseSimpleCommand(command);
|
|
9141
9189
|
if (!result.success) {
|
|
@@ -9250,7 +9298,7 @@ var init_bashPermissions = __esm({
|
|
|
9250
9298
|
}
|
|
9251
9299
|
}
|
|
9252
9300
|
/**
|
|
9253
|
-
* Check if a simple command is allowed (
|
|
9301
|
+
* Check if a simple command is allowed (complex commands allowed if they match patterns)
|
|
9254
9302
|
* @param {string} command - Command to check
|
|
9255
9303
|
* @returns {Object} Permission result
|
|
9256
9304
|
*/
|
|
@@ -9262,13 +9310,9 @@ var init_bashPermissions = __esm({
|
|
|
9262
9310
|
command
|
|
9263
9311
|
};
|
|
9264
9312
|
}
|
|
9265
|
-
|
|
9266
|
-
|
|
9267
|
-
|
|
9268
|
-
reason: "Complex shell commands with pipes, operators, or redirections are not supported for security reasons",
|
|
9269
|
-
command,
|
|
9270
|
-
isComplex: true
|
|
9271
|
-
};
|
|
9313
|
+
const commandIsComplex = isComplexCommand(command);
|
|
9314
|
+
if (commandIsComplex) {
|
|
9315
|
+
return this._checkComplexCommand(command);
|
|
9272
9316
|
}
|
|
9273
9317
|
const parsed = parseCommand(command);
|
|
9274
9318
|
if (parsed.error) {
|
|
@@ -9320,6 +9364,59 @@ var init_bashPermissions = __esm({
|
|
|
9320
9364
|
}
|
|
9321
9365
|
return result;
|
|
9322
9366
|
}
|
|
9367
|
+
/**
|
|
9368
|
+
* Check a complex command against complex patterns in allow/deny lists
|
|
9369
|
+
* @private
|
|
9370
|
+
* @param {string} command - Complex command to check
|
|
9371
|
+
* @returns {Object} Permission result
|
|
9372
|
+
*/
|
|
9373
|
+
_checkComplexCommand(command) {
|
|
9374
|
+
if (this.debug) {
|
|
9375
|
+
console.log(`[BashPermissions] Checking complex command: "${command}"`);
|
|
9376
|
+
}
|
|
9377
|
+
const complexAllowPatterns = this.allowPatterns.filter((p) => isComplexPattern(p));
|
|
9378
|
+
const complexDenyPatterns = this.denyPatterns.filter((p) => isComplexPattern(p));
|
|
9379
|
+
if (this.debug) {
|
|
9380
|
+
console.log(`[BashPermissions] Complex allow patterns: ${complexAllowPatterns.length}`);
|
|
9381
|
+
console.log(`[BashPermissions] Complex deny patterns: ${complexDenyPatterns.length}`);
|
|
9382
|
+
}
|
|
9383
|
+
for (const pattern of complexDenyPatterns) {
|
|
9384
|
+
if (matchesComplexPattern(command, pattern)) {
|
|
9385
|
+
if (this.debug) {
|
|
9386
|
+
console.log(`[BashPermissions] DENIED - matches complex deny pattern: ${pattern}`);
|
|
9387
|
+
}
|
|
9388
|
+
return {
|
|
9389
|
+
allowed: false,
|
|
9390
|
+
reason: `Command matches deny pattern: ${pattern}`,
|
|
9391
|
+
command,
|
|
9392
|
+
isComplex: true,
|
|
9393
|
+
matchedPatterns: [pattern]
|
|
9394
|
+
};
|
|
9395
|
+
}
|
|
9396
|
+
}
|
|
9397
|
+
for (const pattern of complexAllowPatterns) {
|
|
9398
|
+
if (matchesComplexPattern(command, pattern)) {
|
|
9399
|
+
if (this.debug) {
|
|
9400
|
+
console.log(`[BashPermissions] ALLOWED - matches complex allow pattern: ${pattern}`);
|
|
9401
|
+
}
|
|
9402
|
+
return {
|
|
9403
|
+
allowed: true,
|
|
9404
|
+
command,
|
|
9405
|
+
isComplex: true,
|
|
9406
|
+
matchedPattern: pattern
|
|
9407
|
+
};
|
|
9408
|
+
}
|
|
9409
|
+
}
|
|
9410
|
+
if (this.debug) {
|
|
9411
|
+
console.log(`[BashPermissions] DENIED - no matching complex pattern found`);
|
|
9412
|
+
}
|
|
9413
|
+
return {
|
|
9414
|
+
allowed: false,
|
|
9415
|
+
reason: 'Complex shell commands require explicit allow patterns (e.g., "cd * && git *")',
|
|
9416
|
+
command,
|
|
9417
|
+
isComplex: true
|
|
9418
|
+
};
|
|
9419
|
+
}
|
|
9323
9420
|
/**
|
|
9324
9421
|
* Get configuration summary
|
|
9325
9422
|
* @returns {Object} Configuration info
|
|
@@ -9378,28 +9475,40 @@ async function executeBashCommand(command, options = {}) {
|
|
|
9378
9475
|
...process.env,
|
|
9379
9476
|
...env
|
|
9380
9477
|
};
|
|
9381
|
-
const
|
|
9382
|
-
|
|
9383
|
-
|
|
9384
|
-
|
|
9385
|
-
|
|
9386
|
-
|
|
9387
|
-
|
|
9388
|
-
|
|
9389
|
-
|
|
9390
|
-
|
|
9391
|
-
|
|
9392
|
-
|
|
9393
|
-
|
|
9478
|
+
const isComplex = isComplexCommand(command);
|
|
9479
|
+
let cmd, cmdArgs, useShell;
|
|
9480
|
+
if (isComplex) {
|
|
9481
|
+
cmd = "sh";
|
|
9482
|
+
cmdArgs = ["-c", command];
|
|
9483
|
+
useShell = false;
|
|
9484
|
+
if (debug) {
|
|
9485
|
+
console.log(`[BashExecutor] Complex command - using sh -c`);
|
|
9486
|
+
}
|
|
9487
|
+
} else {
|
|
9488
|
+
const args = parseCommandForExecution(command);
|
|
9489
|
+
if (!args || args.length === 0) {
|
|
9490
|
+
resolve6({
|
|
9491
|
+
success: false,
|
|
9492
|
+
error: "Failed to parse command",
|
|
9493
|
+
stdout: "",
|
|
9494
|
+
stderr: "",
|
|
9495
|
+
exitCode: 1,
|
|
9496
|
+
command,
|
|
9497
|
+
workingDirectory: cwd,
|
|
9498
|
+
duration: Date.now() - startTime
|
|
9499
|
+
});
|
|
9500
|
+
return;
|
|
9501
|
+
}
|
|
9502
|
+
[cmd, ...cmdArgs] = args;
|
|
9503
|
+
useShell = false;
|
|
9394
9504
|
}
|
|
9395
|
-
const [cmd, ...cmdArgs] = args;
|
|
9396
9505
|
const child = spawn2(cmd, cmdArgs, {
|
|
9397
9506
|
cwd,
|
|
9398
9507
|
env: processEnv,
|
|
9399
9508
|
stdio: ["ignore", "pipe", "pipe"],
|
|
9400
9509
|
// stdin ignored, capture stdout/stderr
|
|
9401
|
-
shell:
|
|
9402
|
-
//
|
|
9510
|
+
shell: useShell,
|
|
9511
|
+
// false for security
|
|
9403
9512
|
windowsHide: true
|
|
9404
9513
|
});
|
|
9405
9514
|
let stdout = "";
|
|
@@ -23000,6 +23109,16 @@ var init_regexp_parser = __esm({
|
|
|
23000
23109
|
case "!":
|
|
23001
23110
|
type = "NegativeLookahead";
|
|
23002
23111
|
break;
|
|
23112
|
+
case "<": {
|
|
23113
|
+
switch (this.popChar()) {
|
|
23114
|
+
case "=":
|
|
23115
|
+
type = "Lookbehind";
|
|
23116
|
+
break;
|
|
23117
|
+
case "!":
|
|
23118
|
+
type = "NegativeLookbehind";
|
|
23119
|
+
}
|
|
23120
|
+
break;
|
|
23121
|
+
}
|
|
23003
23122
|
}
|
|
23004
23123
|
ASSERT_EXISTS(type);
|
|
23005
23124
|
const disjunction = this.disjunction();
|
|
@@ -23491,9 +23610,9 @@ var init_regexp_parser = __esm({
|
|
|
23491
23610
|
default:
|
|
23492
23611
|
return false;
|
|
23493
23612
|
}
|
|
23494
|
-
// '(?=' or '(?!'
|
|
23613
|
+
// '(?=' or '(?!' or `(?<=` or `(?<!`
|
|
23495
23614
|
case "(":
|
|
23496
|
-
return this.peekChar(1) === "?" && (this.peekChar(2) === "=" || this.peekChar(2) === "!");
|
|
23615
|
+
return this.peekChar(1) === "?" && (this.peekChar(2) === "=" || this.peekChar(2) === "!" || this.peekChar(2) === "<" && (this.peekChar(3) === "=" || this.peekChar(3) === "!"));
|
|
23497
23616
|
default:
|
|
23498
23617
|
return false;
|
|
23499
23618
|
}
|
|
@@ -23618,6 +23737,12 @@ var init_base_regexp_visitor = __esm({
|
|
|
23618
23737
|
case "NegativeLookahead":
|
|
23619
23738
|
this.visitNegativeLookahead(node);
|
|
23620
23739
|
break;
|
|
23740
|
+
case "Lookbehind":
|
|
23741
|
+
this.visitLookbehind(node);
|
|
23742
|
+
break;
|
|
23743
|
+
case "NegativeLookbehind":
|
|
23744
|
+
this.visitNegativeLookbehind(node);
|
|
23745
|
+
break;
|
|
23621
23746
|
case "Character":
|
|
23622
23747
|
this.visitCharacter(node);
|
|
23623
23748
|
break;
|
|
@@ -23657,6 +23782,10 @@ var init_base_regexp_visitor = __esm({
|
|
|
23657
23782
|
}
|
|
23658
23783
|
visitNegativeLookahead(node) {
|
|
23659
23784
|
}
|
|
23785
|
+
visitLookbehind(node) {
|
|
23786
|
+
}
|
|
23787
|
+
visitNegativeLookbehind(node) {
|
|
23788
|
+
}
|
|
23660
23789
|
// atoms
|
|
23661
23790
|
visitCharacter(node) {
|
|
23662
23791
|
}
|
|
@@ -23750,6 +23879,8 @@ function firstCharOptimizedIndices(ast, result, ignoreCase) {
|
|
|
23750
23879
|
// assertions do not affect potential starting codes
|
|
23751
23880
|
case "Lookahead":
|
|
23752
23881
|
case "NegativeLookahead":
|
|
23882
|
+
case "Lookbehind":
|
|
23883
|
+
case "NegativeLookbehind":
|
|
23753
23884
|
case "StartAnchor":
|
|
23754
23885
|
case "WordBoundary":
|
|
23755
23886
|
case "NonWordBoundary":
|
|
@@ -23894,6 +24025,12 @@ var init_reg_exp = __esm({
|
|
|
23894
24025
|
case "NegativeLookahead":
|
|
23895
24026
|
this.visitNegativeLookahead(node);
|
|
23896
24027
|
return;
|
|
24028
|
+
case "Lookbehind":
|
|
24029
|
+
this.visitLookbehind(node);
|
|
24030
|
+
return;
|
|
24031
|
+
case "NegativeLookbehind":
|
|
24032
|
+
this.visitNegativeLookbehind(node);
|
|
24033
|
+
return;
|
|
23897
24034
|
}
|
|
23898
24035
|
super.visitChildren(node);
|
|
23899
24036
|
}
|
|
@@ -24333,24 +24470,27 @@ function findUnreachablePatterns(tokenTypes) {
|
|
|
24333
24470
|
}
|
|
24334
24471
|
return result;
|
|
24335
24472
|
}, []);
|
|
24336
|
-
forEach_default(tokenTypes, (
|
|
24337
|
-
forEach_default(canBeTested, ({ str, idx, tokenType }) => {
|
|
24338
|
-
if (
|
|
24339
|
-
const msg = `Token: ->${
|
|
24340
|
-
Because it appears AFTER the Token Type ->${
|
|
24473
|
+
forEach_default(tokenTypes, (aTokType, aIdx) => {
|
|
24474
|
+
forEach_default(canBeTested, ({ str: bStr, idx: bIdx, tokenType: bTokType }) => {
|
|
24475
|
+
if (aIdx < bIdx && tryToMatchStrToPattern(bStr, aTokType.PATTERN)) {
|
|
24476
|
+
const msg = `Token: ->${bTokType.name}<- can never be matched.
|
|
24477
|
+
Because it appears AFTER the Token Type ->${aTokType.name}<-in the lexer's definition.
|
|
24341
24478
|
See https://chevrotain.io/docs/guide/resolving_lexer_errors.html#UNREACHABLE`;
|
|
24342
24479
|
errors.push({
|
|
24343
24480
|
message: msg,
|
|
24344
24481
|
type: LexerDefinitionErrorType.UNREACHABLE_PATTERN,
|
|
24345
|
-
tokenTypes: [
|
|
24482
|
+
tokenTypes: [aTokType, bTokType]
|
|
24346
24483
|
});
|
|
24347
24484
|
}
|
|
24348
24485
|
});
|
|
24349
24486
|
});
|
|
24350
24487
|
return errors;
|
|
24351
24488
|
}
|
|
24352
|
-
function
|
|
24489
|
+
function tryToMatchStrToPattern(str, pattern) {
|
|
24353
24490
|
if (isRegExp_default(pattern)) {
|
|
24491
|
+
if (usesLookAheadOrBehind(pattern)) {
|
|
24492
|
+
return false;
|
|
24493
|
+
}
|
|
24354
24494
|
const regExpArray = pattern.exec(str);
|
|
24355
24495
|
return regExpArray !== null && regExpArray.index === 0;
|
|
24356
24496
|
} else if (isFunction_default(pattern)) {
|
|
@@ -24381,6 +24521,9 @@ function noMetaChar(regExp) {
|
|
|
24381
24521
|
];
|
|
24382
24522
|
return find_default(metaChars, (char) => regExp.source.indexOf(char) !== -1) === void 0;
|
|
24383
24523
|
}
|
|
24524
|
+
function usesLookAheadOrBehind(regExp) {
|
|
24525
|
+
return /(\(\?=)|(\(\?!)|(\(\?<=)|(\(\?<!)/.test(regExp.source);
|
|
24526
|
+
}
|
|
24384
24527
|
function addStartOfInput(pattern) {
|
|
24385
24528
|
const flags = pattern.ignoreCase ? "i" : "";
|
|
24386
24529
|
return new RegExp(`^(?:${pattern.source})`, flags);
|
|
@@ -24728,7 +24871,7 @@ var init_lexer_errors_public = __esm({
|
|
|
24728
24871
|
buildUnableToPopLexerModeMessage(token) {
|
|
24729
24872
|
return `Unable to pop Lexer Mode after encountering Token ->${token.image}<- The Mode Stack is empty`;
|
|
24730
24873
|
},
|
|
24731
|
-
buildUnexpectedCharactersMessage(fullText, startOffset, length, line, column) {
|
|
24874
|
+
buildUnexpectedCharactersMessage(fullText, startOffset, length, line, column, mode) {
|
|
24732
24875
|
return `unexpected character: ->${fullText.charAt(startOffset)}<- at offset: ${startOffset}, skipped ${length} characters.`;
|
|
24733
24876
|
}
|
|
24734
24877
|
};
|
|
@@ -25169,7 +25312,7 @@ var init_lexer_public = __esm({
|
|
|
25169
25312
|
}
|
|
25170
25313
|
errLength = offset - errorStartOffset;
|
|
25171
25314
|
column = this.computeNewColumn(column, errLength);
|
|
25172
|
-
msg = this.config.errorMessageProvider.buildUnexpectedCharactersMessage(orgText, errorStartOffset, errLength, errorLine, errorColumn);
|
|
25315
|
+
msg = this.config.errorMessageProvider.buildUnexpectedCharactersMessage(orgText, errorStartOffset, errLength, errorLine, errorColumn, last_default(modeStack));
|
|
25173
25316
|
errors.push({
|
|
25174
25317
|
offset: errorStartOffset,
|
|
25175
25318
|
line: errorLine,
|
|
@@ -25282,7 +25425,7 @@ var init_lexer_public = __esm({
|
|
|
25282
25425
|
return regExpArray !== null ? regExpArray[0] : null;
|
|
25283
25426
|
}
|
|
25284
25427
|
};
|
|
25285
|
-
Lexer.SKIPPED = "This marks a skipped Token pattern, this means each token identified by it
|
|
25428
|
+
Lexer.SKIPPED = "This marks a skipped Token pattern, this means each token identified by it will be consumed and then thrown into oblivion, this can be used to for example to completely ignore whitespace.";
|
|
25286
25429
|
Lexer.NA = /NOT_APPLICABLE/;
|
|
25287
25430
|
}
|
|
25288
25431
|
});
|
|
@@ -54963,18 +55106,18 @@ function createJsonCorrectionPrompt(invalidResponse, schema, errorOrValidation,
|
|
|
54963
55106
|
const strengthLevels = [
|
|
54964
55107
|
{
|
|
54965
55108
|
prefix: "CRITICAL JSON ERROR:",
|
|
54966
|
-
instruction: "You MUST fix this and
|
|
54967
|
-
emphasis: "
|
|
55109
|
+
instruction: "You MUST fix this and respond using attempt_completion with ONLY valid JSON as the result.",
|
|
55110
|
+
emphasis: "Use attempt_completion with ONLY the corrected JSON in the result field. No explanatory text, no markdown, no code blocks."
|
|
54968
55111
|
},
|
|
54969
55112
|
{
|
|
54970
55113
|
prefix: "URGENT - JSON PARSING FAILED:",
|
|
54971
|
-
instruction: "This is your second chance.
|
|
54972
|
-
emphasis: "ABSOLUTELY NO explanatory text
|
|
55114
|
+
instruction: "This is your second chance. Use attempt_completion with valid JSON that can be parsed by JSON.parse().",
|
|
55115
|
+
emphasis: "ABSOLUTELY NO explanatory text or formatting. Use attempt_completion with ONLY raw JSON in the result."
|
|
54973
55116
|
},
|
|
54974
55117
|
{
|
|
54975
55118
|
prefix: "FINAL ATTEMPT - CRITICAL JSON ERROR:",
|
|
54976
|
-
instruction: "This is the final retry. You MUST
|
|
54977
|
-
emphasis: '
|
|
55119
|
+
instruction: "This is the final retry. You MUST use attempt_completion with ONLY raw JSON in the result field.",
|
|
55120
|
+
emphasis: 'CORRECT: <attempt_completion><result>{"key": "value"}</result></attempt_completion>\nWRONG: Here is the JSON: {"key": "value"}\nWRONG: ```json{"key": "value"}```'
|
|
54978
55121
|
}
|
|
54979
55122
|
];
|
|
54980
55123
|
const level = Math.min(retryCount, strengthLevels.length - 1);
|
|
@@ -60988,24 +61131,31 @@ You are working with a repository located at: ${searchDirectory}
|
|
|
60988
61131
|
console.log(`[DEBUG] Assistant response (${assistantResponseContent.length} chars): ${assistantPreview}`);
|
|
60989
61132
|
}
|
|
60990
61133
|
const validTools = [];
|
|
60991
|
-
if (
|
|
60992
|
-
|
|
60993
|
-
|
|
60994
|
-
|
|
60995
|
-
|
|
60996
|
-
|
|
60997
|
-
|
|
60998
|
-
|
|
60999
|
-
|
|
61000
|
-
|
|
61001
|
-
|
|
61002
|
-
validTools.push("
|
|
61003
|
-
|
|
61004
|
-
|
|
61005
|
-
|
|
61134
|
+
if (options._disableTools) {
|
|
61135
|
+
validTools.push("attempt_completion");
|
|
61136
|
+
if (this.debug) {
|
|
61137
|
+
console.log(`[DEBUG] Tools disabled for this call - only attempt_completion allowed`);
|
|
61138
|
+
}
|
|
61139
|
+
} else {
|
|
61140
|
+
if (this.allowedTools.isEnabled("search")) validTools.push("search");
|
|
61141
|
+
if (this.allowedTools.isEnabled("query")) validTools.push("query");
|
|
61142
|
+
if (this.allowedTools.isEnabled("extract")) validTools.push("extract");
|
|
61143
|
+
if (this.allowedTools.isEnabled("listFiles")) validTools.push("listFiles");
|
|
61144
|
+
if (this.allowedTools.isEnabled("searchFiles")) validTools.push("searchFiles");
|
|
61145
|
+
if (this.allowedTools.isEnabled("readImage")) validTools.push("readImage");
|
|
61146
|
+
if (this.allowedTools.isEnabled("attempt_completion")) validTools.push("attempt_completion");
|
|
61147
|
+
if (this.allowEdit && this.allowedTools.isEnabled("implement")) {
|
|
61148
|
+
validTools.push("implement", "edit", "create");
|
|
61149
|
+
}
|
|
61150
|
+
if (this.enableBash && this.allowedTools.isEnabled("bash")) {
|
|
61151
|
+
validTools.push("bash");
|
|
61152
|
+
}
|
|
61153
|
+
if (this.enableDelegate && this.allowedTools.isEnabled("delegate")) {
|
|
61154
|
+
validTools.push("delegate");
|
|
61155
|
+
}
|
|
61006
61156
|
}
|
|
61007
61157
|
const nativeTools = validTools;
|
|
61008
|
-
const parsedTool = this.mcpBridge ? parseHybridXmlToolCall(assistantResponseContent, nativeTools, this.mcpBridge) : parseXmlToolCallWithThinking(assistantResponseContent, validTools);
|
|
61158
|
+
const parsedTool = this.mcpBridge && !options._disableTools ? parseHybridXmlToolCall(assistantResponseContent, nativeTools, this.mcpBridge) : parseXmlToolCallWithThinking(assistantResponseContent, validTools);
|
|
61009
61159
|
if (parsedTool) {
|
|
61010
61160
|
const { toolName, params } = parsedTool;
|
|
61011
61161
|
if (this.debug) console.log(`[DEBUG] Parsed tool call: ${toolName} with params:`, params);
|
|
@@ -61086,10 +61236,23 @@ ${toolResultContent}
|
|
|
61086
61236
|
}
|
|
61087
61237
|
} else if (this.toolImplementations[toolName]) {
|
|
61088
61238
|
try {
|
|
61239
|
+
let resolvedWorkingDirectory = this.allowedFolders && this.allowedFolders[0] || process.cwd();
|
|
61240
|
+
if (params.workingDirectory) {
|
|
61241
|
+
const requestedDir = resolve4(params.workingDirectory);
|
|
61242
|
+
const isWithinAllowed = !this.allowedFolders || this.allowedFolders.length === 0 || this.allowedFolders.some((folder) => {
|
|
61243
|
+
const resolvedFolder = resolve4(folder);
|
|
61244
|
+
return requestedDir === resolvedFolder || requestedDir.startsWith(resolvedFolder + sep3);
|
|
61245
|
+
});
|
|
61246
|
+
if (isWithinAllowed) {
|
|
61247
|
+
resolvedWorkingDirectory = requestedDir;
|
|
61248
|
+
} else if (this.debug) {
|
|
61249
|
+
console.error(`[DEBUG] Rejected workingDirectory "${params.workingDirectory}" - not within allowed folders`);
|
|
61250
|
+
}
|
|
61251
|
+
}
|
|
61089
61252
|
const toolParams = {
|
|
61090
61253
|
...params,
|
|
61091
61254
|
sessionId: this.sessionId,
|
|
61092
|
-
workingDirectory:
|
|
61255
|
+
workingDirectory: resolvedWorkingDirectory
|
|
61093
61256
|
};
|
|
61094
61257
|
if (this.debug) {
|
|
61095
61258
|
console.error(`
|
|
@@ -61604,8 +61767,10 @@ Convert your previous response content into actual JSON data that follows this s
|
|
|
61604
61767
|
finalResult = await this.answer(correctionPrompt, [], {
|
|
61605
61768
|
...options,
|
|
61606
61769
|
_schemaFormatted: true,
|
|
61607
|
-
_skipValidation: true
|
|
61770
|
+
_skipValidation: true,
|
|
61608
61771
|
// Skip validation in recursive correction calls to prevent loops
|
|
61772
|
+
_disableTools: true
|
|
61773
|
+
// Only allow attempt_completion - prevent AI from using search/query tools
|
|
61609
61774
|
});
|
|
61610
61775
|
finalResult = cleanSchemaResponse(finalResult);
|
|
61611
61776
|
validation = validateJsonResponse(finalResult, { debug: this.debug });
|
|
@@ -63084,7 +63249,7 @@ Please reformat your previous response to match this schema exactly. Only return
|
|
|
63084
63249
|
if (!validation.isValid) {
|
|
63085
63250
|
const correctionPrompt = createJsonCorrectionPrompt(result, schema, validation.error);
|
|
63086
63251
|
try {
|
|
63087
|
-
result = await agent.answer(correctionPrompt, [], { schema, _schemaFormatted: true });
|
|
63252
|
+
result = await agent.answer(correctionPrompt, [], { schema, _schemaFormatted: true, _disableTools: true });
|
|
63088
63253
|
result = cleanSchemaResponse(result);
|
|
63089
63254
|
const finalValidation = validateJsonResponse(result);
|
|
63090
63255
|
if (!finalValidation.isValid && args.debug) {
|
|
@@ -63370,11 +63535,11 @@ Please reformat your previous response to match this schema exactly. Only return
|
|
|
63370
63535
|
if (appTracer) {
|
|
63371
63536
|
result = await appTracer.withSpan(
|
|
63372
63537
|
"agent.json_correction",
|
|
63373
|
-
() => agent.answer(correctionPrompt, [], { schema, _schemaFormatted: true }),
|
|
63538
|
+
() => agent.answer(correctionPrompt, [], { schema, _schemaFormatted: true, _disableTools: true }),
|
|
63374
63539
|
{ "original_error": validation.error }
|
|
63375
63540
|
);
|
|
63376
63541
|
} else {
|
|
63377
|
-
result = await agent.answer(correctionPrompt, [], { schema, _schemaFormatted: true });
|
|
63542
|
+
result = await agent.answer(correctionPrompt, [], { schema, _schemaFormatted: true, _disableTools: true });
|
|
63378
63543
|
}
|
|
63379
63544
|
result = cleanSchemaResponse(result);
|
|
63380
63545
|
const finalValidation = validateJsonResponse(result);
|
|
@@ -787,21 +787,22 @@ export function createJsonCorrectionPrompt(invalidResponse, schema, errorOrValid
|
|
|
787
787
|
}
|
|
788
788
|
|
|
789
789
|
// Create increasingly stronger prompts based on retry attempt
|
|
790
|
+
// These prompts explicitly instruct the AI to use attempt_completion with the JSON result
|
|
790
791
|
const strengthLevels = [
|
|
791
792
|
{
|
|
792
793
|
prefix: "CRITICAL JSON ERROR:",
|
|
793
|
-
instruction: "You MUST fix this and
|
|
794
|
-
emphasis: "
|
|
794
|
+
instruction: "You MUST fix this and respond using attempt_completion with ONLY valid JSON as the result.",
|
|
795
|
+
emphasis: "Use attempt_completion with ONLY the corrected JSON in the result field. No explanatory text, no markdown, no code blocks."
|
|
795
796
|
},
|
|
796
797
|
{
|
|
797
798
|
prefix: "URGENT - JSON PARSING FAILED:",
|
|
798
|
-
instruction: "This is your second chance.
|
|
799
|
-
emphasis: "ABSOLUTELY NO explanatory text
|
|
799
|
+
instruction: "This is your second chance. Use attempt_completion with valid JSON that can be parsed by JSON.parse().",
|
|
800
|
+
emphasis: "ABSOLUTELY NO explanatory text or formatting. Use attempt_completion with ONLY raw JSON in the result."
|
|
800
801
|
},
|
|
801
802
|
{
|
|
802
803
|
prefix: "FINAL ATTEMPT - CRITICAL JSON ERROR:",
|
|
803
|
-
instruction: "This is the final retry. You MUST
|
|
804
|
-
emphasis: "
|
|
804
|
+
instruction: "This is the final retry. You MUST use attempt_completion with ONLY raw JSON in the result field.",
|
|
805
|
+
emphasis: "CORRECT: <attempt_completion><result>{\"key\": \"value\"}</result></attempt_completion>\nWRONG: Here is the JSON: {\"key\": \"value\"}\nWRONG: ```json{\"key\": \"value\"}```"
|
|
805
806
|
}
|
|
806
807
|
];
|
|
807
808
|
|
package/build/delegate.js
CHANGED
|
@@ -176,6 +176,8 @@ const delegationManager = new DelegationManager();
|
|
|
176
176
|
* @param {string} [options.provider] - AI provider (inherited from parent)
|
|
177
177
|
* @param {string} [options.model] - AI model (inherited from parent)
|
|
178
178
|
* @param {Object} [options.tracer=null] - Telemetry tracer instance
|
|
179
|
+
* @param {boolean} [options.enableBash=false] - Enable bash tool (inherited from parent)
|
|
180
|
+
* @param {Object} [options.bashConfig] - Bash configuration (inherited from parent)
|
|
179
181
|
* @returns {Promise<string>} The response from the delegate agent
|
|
180
182
|
*/
|
|
181
183
|
export async function delegate({
|
|
@@ -188,7 +190,9 @@ export async function delegate({
|
|
|
188
190
|
parentSessionId = null,
|
|
189
191
|
path = null,
|
|
190
192
|
provider = null,
|
|
191
|
-
model = null
|
|
193
|
+
model = null,
|
|
194
|
+
enableBash = false,
|
|
195
|
+
bashConfig = null
|
|
192
196
|
}) {
|
|
193
197
|
if (!task || typeof task !== 'string') {
|
|
194
198
|
throw new Error('Task parameter is required and must be a string');
|
|
@@ -234,9 +238,11 @@ export async function delegate({
|
|
|
234
238
|
maxIterations: remainingIterations,
|
|
235
239
|
debug,
|
|
236
240
|
tracer,
|
|
237
|
-
path,
|
|
238
|
-
provider,
|
|
239
|
-
model // Inherit from parent
|
|
241
|
+
path, // Inherit from parent
|
|
242
|
+
provider, // Inherit from parent
|
|
243
|
+
model, // Inherit from parent
|
|
244
|
+
enableBash, // Inherit from parent
|
|
245
|
+
bashConfig // Inherit from parent
|
|
240
246
|
});
|
|
241
247
|
|
|
242
248
|
if (debug) {
|
package/build/tools/vercel.js
CHANGED
|
@@ -239,10 +239,12 @@ export const extractTool = (options = {}) => {
|
|
|
239
239
|
* @param {number} [options.timeout=300] - Default timeout in seconds
|
|
240
240
|
* @param {string} [options.cwd] - Working directory to use if not specified in call
|
|
241
241
|
* @param {string[]} [options.allowedFolders] - Allowed folders for workspace isolation
|
|
242
|
+
* @param {boolean} [options.enableBash=false] - Enable bash tool for sub-agents
|
|
243
|
+
* @param {Object} [options.bashConfig] - Bash configuration (allow/deny patterns)
|
|
242
244
|
* @returns {Object} Configured delegate tool
|
|
243
245
|
*/
|
|
244
246
|
export const delegateTool = (options = {}) => {
|
|
245
|
-
const { debug = false, timeout = 300, cwd, allowedFolders } = options;
|
|
247
|
+
const { debug = false, timeout = 300, cwd, allowedFolders, enableBash = false, bashConfig } = options;
|
|
246
248
|
|
|
247
249
|
return tool({
|
|
248
250
|
name: 'delegate',
|
|
@@ -309,7 +311,9 @@ export const delegateTool = (options = {}) => {
|
|
|
309
311
|
path: effectivePath,
|
|
310
312
|
provider,
|
|
311
313
|
model,
|
|
312
|
-
tracer
|
|
314
|
+
tracer,
|
|
315
|
+
enableBash,
|
|
316
|
+
bashConfig
|
|
313
317
|
});
|
|
314
318
|
|
|
315
319
|
return result;
|