@probelabs/probe 0.6.0-rc206 → 0.6.0-rc208
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-rc206-aarch64-apple-darwin.tar.gz → probe-v0.6.0-rc208-aarch64-apple-darwin.tar.gz} +0 -0
- package/bin/binaries/probe-v0.6.0-rc208-aarch64-unknown-linux-musl.tar.gz +0 -0
- package/bin/binaries/probe-v0.6.0-rc208-x86_64-apple-darwin.tar.gz +0 -0
- package/bin/binaries/probe-v0.6.0-rc208-x86_64-pc-windows-msvc.zip +0 -0
- package/bin/binaries/probe-v0.6.0-rc208-x86_64-unknown-linux-musl.tar.gz +0 -0
- package/build/agent/ProbeAgent.js +144 -2
- package/build/agent/bashPermissions.js +88 -7
- package/build/agent/index.js +450 -18
- package/build/agent/mcp/client.js +234 -4
- package/build/agent/mcp/config.js +87 -0
- package/build/agent/mcp/xmlBridge.js +15 -5
- package/build/agent/simpleTelemetry.js +26 -0
- package/build/tools/bash.js +5 -3
- package/build/tools/common.js +31 -0
- package/cjs/agent/ProbeAgent.cjs +428 -18
- package/cjs/agent/simpleTelemetry.cjs +22 -0
- package/cjs/index.cjs +450 -18
- package/package.json +1 -1
- package/src/agent/ProbeAgent.js +144 -2
- package/src/agent/bashPermissions.js +88 -7
- package/src/agent/mcp/client.js +234 -4
- package/src/agent/mcp/config.js +87 -0
- package/src/agent/mcp/xmlBridge.js +15 -5
- package/src/agent/simpleTelemetry.js +26 -0
- package/src/tools/bash.js +5 -3
- package/src/tools/common.js +31 -0
- package/bin/binaries/probe-v0.6.0-rc206-aarch64-unknown-linux-musl.tar.gz +0 -0
- package/bin/binaries/probe-v0.6.0-rc206-x86_64-apple-darwin.tar.gz +0 -0
- package/bin/binaries/probe-v0.6.0-rc206-x86_64-pc-windows-msvc.zip +0 -0
- package/bin/binaries/probe-v0.6.0-rc206-x86_64-unknown-linux-musl.tar.gz +0 -0
package/cjs/agent/ProbeAgent.cjs
CHANGED
|
@@ -36006,6 +36006,22 @@ function detectUnrecognizedToolCall(xmlString, validTools) {
|
|
|
36006
36006
|
return toolName;
|
|
36007
36007
|
}
|
|
36008
36008
|
}
|
|
36009
|
+
const allToolNames = [.../* @__PURE__ */ new Set([...knownToolNames, ...validTools])];
|
|
36010
|
+
for (const toolName of allToolNames) {
|
|
36011
|
+
const escapedToolName = toolName.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
36012
|
+
const wrapperPatterns = [
|
|
36013
|
+
new RegExp(`<tool_name>\\s*${escapedToolName}\\s*</tool_name>`, "i"),
|
|
36014
|
+
new RegExp(`<function>\\s*${escapedToolName}\\s*</function>`, "i"),
|
|
36015
|
+
new RegExp(`<name>\\s*${escapedToolName}\\s*</name>`, "i"),
|
|
36016
|
+
// Also check for tool name immediately after api_call or call opening tag
|
|
36017
|
+
new RegExp(`<(?:api_call|call)[^>]*>[\\s\\S]*?<tool_name>\\s*${escapedToolName}`, "i")
|
|
36018
|
+
];
|
|
36019
|
+
for (const pattern of wrapperPatterns) {
|
|
36020
|
+
if (pattern.test(xmlString)) {
|
|
36021
|
+
return `wrapped_tool:${toolName}`;
|
|
36022
|
+
}
|
|
36023
|
+
}
|
|
36024
|
+
}
|
|
36009
36025
|
return null;
|
|
36010
36026
|
}
|
|
36011
36027
|
function parseTargets(targets) {
|
|
@@ -37533,9 +37549,11 @@ var init_bashPermissions = __esm({
|
|
|
37533
37549
|
* @param {boolean} [config.disableDefaultAllow] - Disable default allow list
|
|
37534
37550
|
* @param {boolean} [config.disableDefaultDeny] - Disable default deny list
|
|
37535
37551
|
* @param {boolean} [config.debug] - Enable debug logging
|
|
37552
|
+
* @param {Object} [config.tracer] - Optional tracer for telemetry
|
|
37536
37553
|
*/
|
|
37537
37554
|
constructor(config = {}) {
|
|
37538
37555
|
this.debug = config.debug || false;
|
|
37556
|
+
this.tracer = config.tracer || null;
|
|
37539
37557
|
this.allowPatterns = [];
|
|
37540
37558
|
if (!config.disableDefaultAllow) {
|
|
37541
37559
|
this.allowPatterns.push(...DEFAULT_ALLOW_PATTERNS);
|
|
@@ -37565,6 +37583,24 @@ var init_bashPermissions = __esm({
|
|
|
37565
37583
|
if (this.debug) {
|
|
37566
37584
|
console.log(`[BashPermissions] Total patterns - Allow: ${this.allowPatterns.length}, Deny: ${this.denyPatterns.length}`);
|
|
37567
37585
|
}
|
|
37586
|
+
this.recordBashEvent("permissions.initialized", {
|
|
37587
|
+
allowPatternCount: this.allowPatterns.length,
|
|
37588
|
+
denyPatternCount: this.denyPatterns.length,
|
|
37589
|
+
hasCustomAllowPatterns: !!(config.allow && config.allow.length > 0),
|
|
37590
|
+
hasCustomDenyPatterns: !!(config.deny && config.deny.length > 0),
|
|
37591
|
+
disableDefaultAllow: !!config.disableDefaultAllow,
|
|
37592
|
+
disableDefaultDeny: !!config.disableDefaultDeny
|
|
37593
|
+
});
|
|
37594
|
+
}
|
|
37595
|
+
/**
|
|
37596
|
+
* Record a bash telemetry event if tracer is available
|
|
37597
|
+
* @param {string} eventType - Event type (e.g., 'permission.checked', 'permission.denied')
|
|
37598
|
+
* @param {Object} data - Event data
|
|
37599
|
+
*/
|
|
37600
|
+
recordBashEvent(eventType, data2 = {}) {
|
|
37601
|
+
if (this.tracer && typeof this.tracer.recordBashEvent === "function") {
|
|
37602
|
+
this.tracer.recordBashEvent(eventType, data2);
|
|
37603
|
+
}
|
|
37568
37604
|
}
|
|
37569
37605
|
/**
|
|
37570
37606
|
* Check if a simple command is allowed (complex commands allowed if they match patterns)
|
|
@@ -37573,11 +37609,17 @@ var init_bashPermissions = __esm({
|
|
|
37573
37609
|
*/
|
|
37574
37610
|
check(command) {
|
|
37575
37611
|
if (!command || typeof command !== "string") {
|
|
37576
|
-
|
|
37612
|
+
const result2 = {
|
|
37577
37613
|
allowed: false,
|
|
37578
37614
|
reason: "Invalid or empty command",
|
|
37579
37615
|
command
|
|
37580
37616
|
};
|
|
37617
|
+
this.recordBashEvent("permission.denied", {
|
|
37618
|
+
command: String(command),
|
|
37619
|
+
reason: result2.reason,
|
|
37620
|
+
isComplex: false
|
|
37621
|
+
});
|
|
37622
|
+
return result2;
|
|
37581
37623
|
}
|
|
37582
37624
|
const commandIsComplex = isComplexCommand(command);
|
|
37583
37625
|
if (commandIsComplex) {
|
|
@@ -37585,18 +37627,31 @@ var init_bashPermissions = __esm({
|
|
|
37585
37627
|
}
|
|
37586
37628
|
const parsed = parseCommand(command);
|
|
37587
37629
|
if (parsed.error) {
|
|
37588
|
-
|
|
37630
|
+
const result2 = {
|
|
37589
37631
|
allowed: false,
|
|
37590
37632
|
reason: parsed.error,
|
|
37591
37633
|
command
|
|
37592
37634
|
};
|
|
37635
|
+
this.recordBashEvent("permission.denied", {
|
|
37636
|
+
command,
|
|
37637
|
+
reason: result2.reason,
|
|
37638
|
+
isComplex: false,
|
|
37639
|
+
parseError: true
|
|
37640
|
+
});
|
|
37641
|
+
return result2;
|
|
37593
37642
|
}
|
|
37594
37643
|
if (!parsed.command) {
|
|
37595
|
-
|
|
37644
|
+
const result2 = {
|
|
37596
37645
|
allowed: false,
|
|
37597
37646
|
reason: "No valid command found",
|
|
37598
37647
|
command
|
|
37599
37648
|
};
|
|
37649
|
+
this.recordBashEvent("permission.denied", {
|
|
37650
|
+
command,
|
|
37651
|
+
reason: result2.reason,
|
|
37652
|
+
isComplex: false
|
|
37653
|
+
});
|
|
37654
|
+
return result2;
|
|
37600
37655
|
}
|
|
37601
37656
|
if (this.debug) {
|
|
37602
37657
|
console.log(`[BashPermissions] Checking simple command: "${command}"`);
|
|
@@ -37604,22 +37659,37 @@ var init_bashPermissions = __esm({
|
|
|
37604
37659
|
}
|
|
37605
37660
|
if (matchesAnyPattern(parsed, this.denyPatterns)) {
|
|
37606
37661
|
const matchedPatterns = this.denyPatterns.filter((pattern) => matchesPattern(parsed, pattern));
|
|
37607
|
-
|
|
37662
|
+
const result2 = {
|
|
37608
37663
|
allowed: false,
|
|
37609
37664
|
reason: `Command matches deny pattern: ${matchedPatterns[0]}`,
|
|
37610
37665
|
command,
|
|
37611
37666
|
parsed,
|
|
37612
37667
|
matchedPatterns
|
|
37613
37668
|
};
|
|
37669
|
+
this.recordBashEvent("permission.denied", {
|
|
37670
|
+
command,
|
|
37671
|
+
parsedCommand: parsed.command,
|
|
37672
|
+
reason: "matches_deny_pattern",
|
|
37673
|
+
matchedPattern: matchedPatterns[0],
|
|
37674
|
+
isComplex: false
|
|
37675
|
+
});
|
|
37676
|
+
return result2;
|
|
37614
37677
|
}
|
|
37615
37678
|
if (this.allowPatterns.length > 0) {
|
|
37616
37679
|
if (!matchesAnyPattern(parsed, this.allowPatterns)) {
|
|
37617
|
-
|
|
37680
|
+
const result2 = {
|
|
37618
37681
|
allowed: false,
|
|
37619
37682
|
reason: "Command not in allow list",
|
|
37620
37683
|
command,
|
|
37621
37684
|
parsed
|
|
37622
37685
|
};
|
|
37686
|
+
this.recordBashEvent("permission.denied", {
|
|
37687
|
+
command,
|
|
37688
|
+
parsedCommand: parsed.command,
|
|
37689
|
+
reason: "not_in_allow_list",
|
|
37690
|
+
isComplex: false
|
|
37691
|
+
});
|
|
37692
|
+
return result2;
|
|
37623
37693
|
}
|
|
37624
37694
|
}
|
|
37625
37695
|
const result = {
|
|
@@ -37631,6 +37701,11 @@ var init_bashPermissions = __esm({
|
|
|
37631
37701
|
if (this.debug) {
|
|
37632
37702
|
console.log(`[BashPermissions] ALLOWED - command passed all checks`);
|
|
37633
37703
|
}
|
|
37704
|
+
this.recordBashEvent("permission.allowed", {
|
|
37705
|
+
command,
|
|
37706
|
+
parsedCommand: parsed.command,
|
|
37707
|
+
isComplex: false
|
|
37708
|
+
});
|
|
37634
37709
|
return result;
|
|
37635
37710
|
}
|
|
37636
37711
|
/**
|
|
@@ -37654,13 +37729,20 @@ var init_bashPermissions = __esm({
|
|
|
37654
37729
|
if (this.debug) {
|
|
37655
37730
|
console.log(`[BashPermissions] DENIED - matches complex deny pattern: ${pattern}`);
|
|
37656
37731
|
}
|
|
37657
|
-
|
|
37732
|
+
const result = {
|
|
37658
37733
|
allowed: false,
|
|
37659
37734
|
reason: `Command matches deny pattern: ${pattern}`,
|
|
37660
37735
|
command,
|
|
37661
37736
|
isComplex: true,
|
|
37662
37737
|
matchedPatterns: [pattern]
|
|
37663
37738
|
};
|
|
37739
|
+
this.recordBashEvent("permission.denied", {
|
|
37740
|
+
command,
|
|
37741
|
+
reason: "matches_deny_pattern",
|
|
37742
|
+
matchedPattern: pattern,
|
|
37743
|
+
isComplex: true
|
|
37744
|
+
});
|
|
37745
|
+
return result;
|
|
37664
37746
|
}
|
|
37665
37747
|
}
|
|
37666
37748
|
for (const pattern of complexAllowPatterns) {
|
|
@@ -37668,17 +37750,28 @@ var init_bashPermissions = __esm({
|
|
|
37668
37750
|
if (this.debug) {
|
|
37669
37751
|
console.log(`[BashPermissions] ALLOWED - matches complex allow pattern: ${pattern}`);
|
|
37670
37752
|
}
|
|
37671
|
-
|
|
37753
|
+
const result = {
|
|
37672
37754
|
allowed: true,
|
|
37673
37755
|
command,
|
|
37674
37756
|
isComplex: true,
|
|
37675
37757
|
matchedPattern: pattern
|
|
37676
37758
|
};
|
|
37759
|
+
this.recordBashEvent("permission.allowed", {
|
|
37760
|
+
command,
|
|
37761
|
+
matchedPattern: pattern,
|
|
37762
|
+
isComplex: true
|
|
37763
|
+
});
|
|
37764
|
+
return result;
|
|
37677
37765
|
}
|
|
37678
37766
|
}
|
|
37679
37767
|
if (this.debug) {
|
|
37680
37768
|
console.log(`[BashPermissions] DENIED - no matching complex pattern found`);
|
|
37681
37769
|
}
|
|
37770
|
+
this.recordBashEvent("permission.denied", {
|
|
37771
|
+
command,
|
|
37772
|
+
reason: "no_matching_complex_pattern",
|
|
37773
|
+
isComplex: true
|
|
37774
|
+
});
|
|
37682
37775
|
return {
|
|
37683
37776
|
allowed: false,
|
|
37684
37777
|
reason: 'Complex shell commands require explicit allow patterns (e.g., "cd * && git *")',
|
|
@@ -37977,14 +38070,16 @@ var init_bash = __esm({
|
|
|
37977
38070
|
bashConfig = {},
|
|
37978
38071
|
debug = false,
|
|
37979
38072
|
cwd,
|
|
37980
|
-
allowedFolders = []
|
|
38073
|
+
allowedFolders = [],
|
|
38074
|
+
tracer = null
|
|
37981
38075
|
} = options;
|
|
37982
38076
|
const permissionChecker = new BashPermissionChecker({
|
|
37983
38077
|
allow: bashConfig.allow,
|
|
37984
38078
|
deny: bashConfig.deny,
|
|
37985
38079
|
disableDefaultAllow: bashConfig.disableDefaultAllow,
|
|
37986
38080
|
disableDefaultDeny: bashConfig.disableDefaultDeny,
|
|
37987
|
-
debug
|
|
38081
|
+
debug,
|
|
38082
|
+
tracer
|
|
37988
38083
|
});
|
|
37989
38084
|
const getDefaultWorkingDirectory = () => {
|
|
37990
38085
|
if (bashConfig.workingDirectory) {
|
|
@@ -84601,6 +84696,47 @@ function validateTimeout(value) {
|
|
|
84601
84696
|
if (!Number.isFinite(num) || num < 0) return void 0;
|
|
84602
84697
|
return Math.min(num, MAX_TIMEOUT);
|
|
84603
84698
|
}
|
|
84699
|
+
function validateMethodFilter(serverConfig, serverName = "unknown") {
|
|
84700
|
+
const result = { allowedMethods: null, blockedMethods: null };
|
|
84701
|
+
const debug = process.env.DEBUG === "1" || process.env.DEBUG_MCP === "1";
|
|
84702
|
+
if (serverConfig.allowedMethods && serverConfig.blockedMethods) {
|
|
84703
|
+
console.error(`[MCP WARN] Server '${serverName}' has both allowedMethods and blockedMethods - using allowedMethods only`);
|
|
84704
|
+
}
|
|
84705
|
+
if (serverConfig.allowedMethods) {
|
|
84706
|
+
if (!Array.isArray(serverConfig.allowedMethods)) {
|
|
84707
|
+
console.error(`[MCP WARN] Server '${serverName}' allowedMethods must be an array, ignoring`);
|
|
84708
|
+
} else {
|
|
84709
|
+
const validMethods = serverConfig.allowedMethods.filter((m4) => typeof m4 === "string" && m4.length > 0);
|
|
84710
|
+
if (validMethods.length !== serverConfig.allowedMethods.length) {
|
|
84711
|
+
console.error(`[MCP WARN] Server '${serverName}' allowedMethods contains non-string values, skipping those`);
|
|
84712
|
+
}
|
|
84713
|
+
if (validMethods.length > 0) {
|
|
84714
|
+
result.allowedMethods = validMethods;
|
|
84715
|
+
if (debug) {
|
|
84716
|
+
console.error(`[MCP DEBUG] Server '${serverName}' allowedMethods: ${validMethods.join(", ")}`);
|
|
84717
|
+
}
|
|
84718
|
+
}
|
|
84719
|
+
}
|
|
84720
|
+
return result;
|
|
84721
|
+
}
|
|
84722
|
+
if (serverConfig.blockedMethods) {
|
|
84723
|
+
if (!Array.isArray(serverConfig.blockedMethods)) {
|
|
84724
|
+
console.error(`[MCP WARN] Server '${serverName}' blockedMethods must be an array, ignoring`);
|
|
84725
|
+
} else {
|
|
84726
|
+
const validMethods = serverConfig.blockedMethods.filter((m4) => typeof m4 === "string" && m4.length > 0);
|
|
84727
|
+
if (validMethods.length !== serverConfig.blockedMethods.length) {
|
|
84728
|
+
console.error(`[MCP WARN] Server '${serverName}' blockedMethods contains non-string values, skipping those`);
|
|
84729
|
+
}
|
|
84730
|
+
if (validMethods.length > 0) {
|
|
84731
|
+
result.blockedMethods = validMethods;
|
|
84732
|
+
if (debug) {
|
|
84733
|
+
console.error(`[MCP DEBUG] Server '${serverName}' blockedMethods: ${validMethods.join(", ")}`);
|
|
84734
|
+
}
|
|
84735
|
+
}
|
|
84736
|
+
}
|
|
84737
|
+
}
|
|
84738
|
+
return result;
|
|
84739
|
+
}
|
|
84604
84740
|
function loadMCPConfigurationFromPath(configPath) {
|
|
84605
84741
|
if (!configPath) {
|
|
84606
84742
|
throw new Error("Config path is required");
|
|
@@ -84694,6 +84830,12 @@ function mergeWithEnvironment(config) {
|
|
|
84694
84830
|
console.error(`[MCP WARN] Invalid timeout value for ${normalizedName}: ${value}`);
|
|
84695
84831
|
}
|
|
84696
84832
|
break;
|
|
84833
|
+
case "ALLOWLIST":
|
|
84834
|
+
config.mcpServers[normalizedName].allowedMethods = value.split(",").map((m4) => m4.trim()).filter(Boolean);
|
|
84835
|
+
break;
|
|
84836
|
+
case "BLOCKLIST":
|
|
84837
|
+
config.mcpServers[normalizedName].blockedMethods = value.split(",").map((m4) => m4.trim()).filter(Boolean);
|
|
84838
|
+
break;
|
|
84697
84839
|
}
|
|
84698
84840
|
}
|
|
84699
84841
|
}
|
|
@@ -84744,6 +84886,9 @@ function parseEnabledServers(config) {
|
|
|
84744
84886
|
}
|
|
84745
84887
|
server.timeout = validatedTimeout;
|
|
84746
84888
|
}
|
|
84889
|
+
const methodFilter = validateMethodFilter(serverConfig, name14);
|
|
84890
|
+
server.allowedMethods = methodFilter.allowedMethods;
|
|
84891
|
+
server.blockedMethods = methodFilter.blockedMethods;
|
|
84747
84892
|
servers.push(server);
|
|
84748
84893
|
}
|
|
84749
84894
|
return servers;
|
|
@@ -84781,6 +84926,22 @@ var init_config = __esm({
|
|
|
84781
84926
|
});
|
|
84782
84927
|
|
|
84783
84928
|
// src/agent/mcp/client.js
|
|
84929
|
+
function isMethodAllowed(methodName, allowedMethods, blockedMethods) {
|
|
84930
|
+
const matchesPattern2 = (name14, pattern) => {
|
|
84931
|
+
if (!pattern.includes("*")) {
|
|
84932
|
+
return name14 === pattern;
|
|
84933
|
+
}
|
|
84934
|
+
const regexPattern = pattern.replace(/[.+?^${}()|[\]\\]/g, "\\$&").replace(/\*/g, ".*");
|
|
84935
|
+
return new RegExp(`^${regexPattern}$`).test(name14);
|
|
84936
|
+
};
|
|
84937
|
+
if (allowedMethods && allowedMethods.length > 0) {
|
|
84938
|
+
return allowedMethods.some((pattern) => matchesPattern2(methodName, pattern));
|
|
84939
|
+
}
|
|
84940
|
+
if (blockedMethods && blockedMethods.length > 0) {
|
|
84941
|
+
return !blockedMethods.some((pattern) => matchesPattern2(methodName, pattern));
|
|
84942
|
+
}
|
|
84943
|
+
return true;
|
|
84944
|
+
}
|
|
84784
84945
|
function createTransport(serverConfig) {
|
|
84785
84946
|
const { transport, command, args, url, env } = serverConfig;
|
|
84786
84947
|
switch (transport) {
|
|
@@ -84865,6 +85026,17 @@ var init_client2 = __esm({
|
|
|
84865
85026
|
this.tools = /* @__PURE__ */ new Map();
|
|
84866
85027
|
this.debug = options.debug || process.env.DEBUG_MCP === "1";
|
|
84867
85028
|
this.config = null;
|
|
85029
|
+
this.tracer = options.tracer || null;
|
|
85030
|
+
}
|
|
85031
|
+
/**
|
|
85032
|
+
* Record an MCP telemetry event if tracer is available
|
|
85033
|
+
* @param {string} eventType - Event type (e.g., 'server.connect', 'tool.discovered')
|
|
85034
|
+
* @param {Object} data - Event data
|
|
85035
|
+
*/
|
|
85036
|
+
recordMcpEvent(eventType, data2 = {}) {
|
|
85037
|
+
if (this.tracer && typeof this.tracer.recordMcpEvent === "function") {
|
|
85038
|
+
this.tracer.recordMcpEvent(eventType, data2);
|
|
85039
|
+
}
|
|
84868
85040
|
}
|
|
84869
85041
|
/**
|
|
84870
85042
|
* Initialize MCP clients from configuration
|
|
@@ -84873,10 +85045,20 @@ var init_client2 = __esm({
|
|
|
84873
85045
|
async initialize(config = null) {
|
|
84874
85046
|
this.config = config || loadMCPConfiguration();
|
|
84875
85047
|
const servers = parseEnabledServers(this.config);
|
|
85048
|
+
this.recordMcpEvent("initialization.started", {
|
|
85049
|
+
serverCount: servers.length,
|
|
85050
|
+
serverNames: servers.map((s4) => s4.name)
|
|
85051
|
+
});
|
|
84876
85052
|
console.error(`[MCP INFO] Found ${servers.length} enabled MCP server${servers.length !== 1 ? "s" : ""}`);
|
|
84877
85053
|
if (servers.length === 0) {
|
|
84878
85054
|
console.error("[MCP INFO] No MCP servers configured or enabled");
|
|
84879
85055
|
console.error("[MCP INFO] 0 MCP tools available");
|
|
85056
|
+
this.recordMcpEvent("initialization.completed", {
|
|
85057
|
+
connected: 0,
|
|
85058
|
+
total: 0,
|
|
85059
|
+
toolCount: 0,
|
|
85060
|
+
tools: []
|
|
85061
|
+
});
|
|
84880
85062
|
return {
|
|
84881
85063
|
connected: 0,
|
|
84882
85064
|
total: 0,
|
|
@@ -84913,10 +85095,17 @@ var init_client2 = __esm({
|
|
|
84913
85095
|
console.error(`[MCP DEBUG] - ${toolName}`);
|
|
84914
85096
|
});
|
|
84915
85097
|
}
|
|
85098
|
+
const toolNames = Array.from(this.tools.keys());
|
|
85099
|
+
this.recordMcpEvent("initialization.completed", {
|
|
85100
|
+
connected: connectedCount,
|
|
85101
|
+
total: servers.length,
|
|
85102
|
+
toolCount: this.tools.size,
|
|
85103
|
+
tools: toolNames
|
|
85104
|
+
});
|
|
84916
85105
|
return {
|
|
84917
85106
|
connected: connectedCount,
|
|
84918
85107
|
total: servers.length,
|
|
84919
|
-
tools:
|
|
85108
|
+
tools: toolNames
|
|
84920
85109
|
};
|
|
84921
85110
|
}
|
|
84922
85111
|
/**
|
|
@@ -84925,6 +85114,12 @@ var init_client2 = __esm({
|
|
|
84925
85114
|
*/
|
|
84926
85115
|
async connectToServer(serverConfig) {
|
|
84927
85116
|
const { name: name14 } = serverConfig;
|
|
85117
|
+
this.recordMcpEvent("server.connecting", {
|
|
85118
|
+
serverName: name14,
|
|
85119
|
+
transport: serverConfig.transport,
|
|
85120
|
+
hasAllowedMethods: !!(serverConfig.allowedMethods && serverConfig.allowedMethods.length > 0),
|
|
85121
|
+
hasBlockedMethods: !!(serverConfig.blockedMethods && serverConfig.blockedMethods.length > 0)
|
|
85122
|
+
});
|
|
84928
85123
|
try {
|
|
84929
85124
|
if (this.debug) {
|
|
84930
85125
|
console.error(`[MCP DEBUG] Connecting to ${name14} via ${serverConfig.transport}...`);
|
|
@@ -84946,27 +85141,92 @@ var init_client2 = __esm({
|
|
|
84946
85141
|
config: serverConfig
|
|
84947
85142
|
});
|
|
84948
85143
|
const toolsResponse = await client.listTools();
|
|
84949
|
-
const
|
|
85144
|
+
const totalToolCount = toolsResponse?.tools?.length || 0;
|
|
85145
|
+
let registeredCount = 0;
|
|
85146
|
+
let filteredCount = 0;
|
|
85147
|
+
const registeredTools = [];
|
|
85148
|
+
const filteredTools = [];
|
|
84950
85149
|
if (toolsResponse && toolsResponse.tools) {
|
|
85150
|
+
const { allowedMethods, blockedMethods } = serverConfig;
|
|
85151
|
+
const allToolNames = toolsResponse.tools.map((t4) => t4.name);
|
|
85152
|
+
this.recordMcpEvent("tools.discovered", {
|
|
85153
|
+
serverName: name14,
|
|
85154
|
+
toolCount: totalToolCount,
|
|
85155
|
+
tools: allToolNames
|
|
85156
|
+
});
|
|
84951
85157
|
for (const tool4 of toolsResponse.tools) {
|
|
85158
|
+
if (!isMethodAllowed(tool4.name, allowedMethods, blockedMethods)) {
|
|
85159
|
+
filteredCount++;
|
|
85160
|
+
filteredTools.push(tool4.name);
|
|
85161
|
+
if (this.debug) {
|
|
85162
|
+
console.error(`[MCP DEBUG] Filtered out tool: ${tool4.name} (not allowed by method filter)`);
|
|
85163
|
+
}
|
|
85164
|
+
continue;
|
|
85165
|
+
}
|
|
84952
85166
|
const qualifiedName = `${name14}_${tool4.name}`;
|
|
84953
85167
|
this.tools.set(qualifiedName, {
|
|
84954
85168
|
...tool4,
|
|
84955
85169
|
serverName: name14,
|
|
84956
85170
|
originalName: tool4.name
|
|
84957
85171
|
});
|
|
85172
|
+
registeredCount++;
|
|
85173
|
+
registeredTools.push(qualifiedName);
|
|
84958
85174
|
if (this.debug) {
|
|
84959
85175
|
console.error(`[MCP DEBUG] Registered tool: ${qualifiedName}`);
|
|
84960
85176
|
}
|
|
84961
85177
|
}
|
|
85178
|
+
if (filteredCount > 0) {
|
|
85179
|
+
this.recordMcpEvent("tools.filtered", {
|
|
85180
|
+
serverName: name14,
|
|
85181
|
+
filteredCount,
|
|
85182
|
+
filteredTools,
|
|
85183
|
+
allowedMethods: allowedMethods || [],
|
|
85184
|
+
blockedMethods: blockedMethods || []
|
|
85185
|
+
});
|
|
85186
|
+
}
|
|
85187
|
+
if (allowedMethods && allowedMethods.length > 0) {
|
|
85188
|
+
const unmatchedPatterns = allowedMethods.filter((pattern) => {
|
|
85189
|
+
return !allToolNames.some((toolName) => isMethodAllowed(toolName, [pattern], null));
|
|
85190
|
+
});
|
|
85191
|
+
if (unmatchedPatterns.length > 0) {
|
|
85192
|
+
console.error(`[MCP WARN] Server '${name14}': The following allowedMethods patterns did not match any tools: ${unmatchedPatterns.join(", ")}`);
|
|
85193
|
+
console.error(`[MCP WARN] Available methods from '${name14}': ${allToolNames.join(", ")}`);
|
|
85194
|
+
}
|
|
85195
|
+
}
|
|
85196
|
+
if (blockedMethods && blockedMethods.length > 0) {
|
|
85197
|
+
const unmatchedPatterns = blockedMethods.filter((pattern) => {
|
|
85198
|
+
return !allToolNames.some((toolName) => !isMethodAllowed(toolName, null, [pattern]));
|
|
85199
|
+
});
|
|
85200
|
+
if (unmatchedPatterns.length > 0) {
|
|
85201
|
+
console.error(`[MCP WARN] Server '${name14}': The following blockedMethods patterns did not match any tools: ${unmatchedPatterns.join(", ")}`);
|
|
85202
|
+
console.error(`[MCP WARN] Available methods from '${name14}': ${allToolNames.join(", ")}`);
|
|
85203
|
+
}
|
|
85204
|
+
}
|
|
84962
85205
|
}
|
|
84963
|
-
|
|
85206
|
+
if (filteredCount > 0) {
|
|
85207
|
+
console.error(`[MCP INFO] Connected to ${name14}: ${registeredCount} tool${registeredCount !== 1 ? "s" : ""} loaded (${filteredCount} filtered out)`);
|
|
85208
|
+
} else {
|
|
85209
|
+
console.error(`[MCP INFO] Connected to ${name14}: ${registeredCount} tool${registeredCount !== 1 ? "s" : ""} loaded`);
|
|
85210
|
+
}
|
|
85211
|
+
this.recordMcpEvent("server.connected", {
|
|
85212
|
+
serverName: name14,
|
|
85213
|
+
transport: serverConfig.transport,
|
|
85214
|
+
totalToolCount,
|
|
85215
|
+
registeredCount,
|
|
85216
|
+
filteredCount,
|
|
85217
|
+
registeredTools
|
|
85218
|
+
});
|
|
84964
85219
|
return true;
|
|
84965
85220
|
} catch (error2) {
|
|
84966
85221
|
console.error(`[MCP ERROR] Error connecting to ${name14}:`, error2.message);
|
|
84967
85222
|
if (this.debug) {
|
|
84968
85223
|
console.error(`[MCP DEBUG] Full error details:`, error2);
|
|
84969
85224
|
}
|
|
85225
|
+
this.recordMcpEvent("server.connection_failed", {
|
|
85226
|
+
serverName: name14,
|
|
85227
|
+
transport: serverConfig.transport,
|
|
85228
|
+
error: error2.message
|
|
85229
|
+
});
|
|
84970
85230
|
return false;
|
|
84971
85231
|
}
|
|
84972
85232
|
}
|
|
@@ -84978,12 +85238,27 @@ var init_client2 = __esm({
|
|
|
84978
85238
|
async callTool(toolName, args) {
|
|
84979
85239
|
const tool4 = this.tools.get(toolName);
|
|
84980
85240
|
if (!tool4) {
|
|
85241
|
+
this.recordMcpEvent("tool.call_failed", {
|
|
85242
|
+
toolName,
|
|
85243
|
+
error: "Unknown tool"
|
|
85244
|
+
});
|
|
84981
85245
|
throw new Error(`Unknown tool: ${toolName}`);
|
|
84982
85246
|
}
|
|
84983
85247
|
const clientInfo = this.clients.get(tool4.serverName);
|
|
84984
85248
|
if (!clientInfo) {
|
|
85249
|
+
this.recordMcpEvent("tool.call_failed", {
|
|
85250
|
+
toolName,
|
|
85251
|
+
serverName: tool4.serverName,
|
|
85252
|
+
error: "Server not connected"
|
|
85253
|
+
});
|
|
84985
85254
|
throw new Error(`Server ${tool4.serverName} not connected`);
|
|
84986
85255
|
}
|
|
85256
|
+
const startTime = Date.now();
|
|
85257
|
+
this.recordMcpEvent("tool.call_started", {
|
|
85258
|
+
toolName,
|
|
85259
|
+
serverName: tool4.serverName,
|
|
85260
|
+
originalToolName: tool4.originalName
|
|
85261
|
+
});
|
|
84987
85262
|
try {
|
|
84988
85263
|
if (this.debug) {
|
|
84989
85264
|
console.error(`[MCP DEBUG] Calling ${toolName} with args:`, JSON.stringify(args, null, 2));
|
|
@@ -85003,15 +85278,31 @@ var init_client2 = __esm({
|
|
|
85003
85278
|
}),
|
|
85004
85279
|
timeoutPromise
|
|
85005
85280
|
]);
|
|
85281
|
+
const durationMs = Date.now() - startTime;
|
|
85006
85282
|
if (this.debug) {
|
|
85007
85283
|
console.error(`[MCP DEBUG] Tool ${toolName} executed successfully`);
|
|
85008
85284
|
}
|
|
85285
|
+
this.recordMcpEvent("tool.call_completed", {
|
|
85286
|
+
toolName,
|
|
85287
|
+
serverName: tool4.serverName,
|
|
85288
|
+
originalToolName: tool4.originalName,
|
|
85289
|
+
durationMs
|
|
85290
|
+
});
|
|
85009
85291
|
return result;
|
|
85010
85292
|
} catch (error2) {
|
|
85293
|
+
const durationMs = Date.now() - startTime;
|
|
85011
85294
|
console.error(`[MCP ERROR] Error calling tool ${toolName}:`, error2.message);
|
|
85012
85295
|
if (this.debug) {
|
|
85013
85296
|
console.error(`[MCP DEBUG] Full error details:`, error2);
|
|
85014
85297
|
}
|
|
85298
|
+
this.recordMcpEvent("tool.call_failed", {
|
|
85299
|
+
toolName,
|
|
85300
|
+
serverName: tool4.serverName,
|
|
85301
|
+
originalToolName: tool4.originalName,
|
|
85302
|
+
error: error2.message,
|
|
85303
|
+
durationMs,
|
|
85304
|
+
isTimeout: error2.message.includes("timeout")
|
|
85305
|
+
});
|
|
85015
85306
|
throw error2;
|
|
85016
85307
|
}
|
|
85017
85308
|
}
|
|
@@ -85056,12 +85347,17 @@ var init_client2 = __esm({
|
|
|
85056
85347
|
*/
|
|
85057
85348
|
async disconnect() {
|
|
85058
85349
|
const disconnectPromises = [];
|
|
85350
|
+
const serverNames = Array.from(this.clients.keys());
|
|
85059
85351
|
if (this.clients.size === 0) {
|
|
85060
85352
|
if (this.debug) {
|
|
85061
85353
|
console.error("[MCP DEBUG] No MCP clients to disconnect");
|
|
85062
85354
|
}
|
|
85063
85355
|
return;
|
|
85064
85356
|
}
|
|
85357
|
+
this.recordMcpEvent("disconnection.started", {
|
|
85358
|
+
serverCount: this.clients.size,
|
|
85359
|
+
serverNames
|
|
85360
|
+
});
|
|
85065
85361
|
if (this.debug) {
|
|
85066
85362
|
console.error(`[MCP DEBUG] Disconnecting from ${this.clients.size} MCP server${this.clients.size !== 1 ? "s" : ""}...`);
|
|
85067
85363
|
}
|
|
@@ -85071,14 +85367,25 @@ var init_client2 = __esm({
|
|
|
85071
85367
|
if (this.debug) {
|
|
85072
85368
|
console.error(`[MCP DEBUG] Disconnected from ${name14}`);
|
|
85073
85369
|
}
|
|
85370
|
+
this.recordMcpEvent("server.disconnected", {
|
|
85371
|
+
serverName: name14
|
|
85372
|
+
});
|
|
85074
85373
|
}).catch((error2) => {
|
|
85075
85374
|
console.error(`[MCP ERROR] Error disconnecting from ${name14}:`, error2.message);
|
|
85375
|
+
this.recordMcpEvent("server.disconnect_failed", {
|
|
85376
|
+
serverName: name14,
|
|
85377
|
+
error: error2.message
|
|
85378
|
+
});
|
|
85076
85379
|
})
|
|
85077
85380
|
);
|
|
85078
85381
|
}
|
|
85079
85382
|
await Promise.all(disconnectPromises);
|
|
85080
85383
|
this.clients.clear();
|
|
85081
85384
|
this.tools.clear();
|
|
85385
|
+
this.recordMcpEvent("disconnection.completed", {
|
|
85386
|
+
serverCount: serverNames.length,
|
|
85387
|
+
serverNames
|
|
85388
|
+
});
|
|
85082
85389
|
if (this.debug) {
|
|
85083
85390
|
console.error("[MCP DEBUG] All MCP connections closed");
|
|
85084
85391
|
}
|
|
@@ -85222,6 +85529,7 @@ var init_xmlBridge = __esm({
|
|
|
85222
85529
|
MCPXmlBridge = class {
|
|
85223
85530
|
constructor(options = {}) {
|
|
85224
85531
|
this.debug = options.debug || false;
|
|
85532
|
+
this.tracer = options.tracer || null;
|
|
85225
85533
|
this.mcpTools = {};
|
|
85226
85534
|
this.mcpManager = null;
|
|
85227
85535
|
this.xmlDefinitions = {};
|
|
@@ -85264,7 +85572,7 @@ var init_xmlBridge = __esm({
|
|
|
85264
85572
|
if (this.debug) {
|
|
85265
85573
|
console.error("[MCP DEBUG] Initializing MCP client manager...");
|
|
85266
85574
|
}
|
|
85267
|
-
this.mcpManager = new MCPClientManager({ debug: this.debug });
|
|
85575
|
+
this.mcpManager = new MCPClientManager({ debug: this.debug, tracer: this.tracer });
|
|
85268
85576
|
const result = await this.mcpManager.initialize(mcpConfigs);
|
|
85269
85577
|
const vercelTools = this.mcpManager.getVercelTools();
|
|
85270
85578
|
this.mcpTools = vercelTools;
|
|
@@ -85288,11 +85596,15 @@ var init_xmlBridge = __esm({
|
|
|
85288
85596
|
}
|
|
85289
85597
|
}
|
|
85290
85598
|
/**
|
|
85291
|
-
* Get
|
|
85599
|
+
* Get XML tool definitions for inclusion in system prompt
|
|
85600
|
+
* @param {Array<string>|null} filterToolNames - Optional list of tool names to include (if null, include all)
|
|
85292
85601
|
* @returns {string} Combined XML tool definitions
|
|
85293
85602
|
*/
|
|
85294
|
-
getXmlToolDefinitions() {
|
|
85295
|
-
|
|
85603
|
+
getXmlToolDefinitions(filterToolNames = null) {
|
|
85604
|
+
if (filterToolNames === null) {
|
|
85605
|
+
return Object.values(this.xmlDefinitions).join("\n\n");
|
|
85606
|
+
}
|
|
85607
|
+
return Object.entries(this.xmlDefinitions).filter(([name14]) => filterToolNames.includes(name14)).map(([, def]) => def).join("\n\n");
|
|
85296
85608
|
}
|
|
85297
85609
|
/**
|
|
85298
85610
|
* Get list of MCP tool names
|
|
@@ -95379,6 +95691,27 @@ __export(ProbeAgent_exports, {
|
|
|
95379
95691
|
ProbeAgent: () => ProbeAgent
|
|
95380
95692
|
});
|
|
95381
95693
|
module.exports = __toCommonJS(ProbeAgent_exports);
|
|
95694
|
+
function extractWrappedToolName(wrappedToolError) {
|
|
95695
|
+
if (!wrappedToolError || typeof wrappedToolError !== "string") {
|
|
95696
|
+
return "unknown";
|
|
95697
|
+
}
|
|
95698
|
+
const colonIndex = wrappedToolError.indexOf(":");
|
|
95699
|
+
return colonIndex !== -1 ? wrappedToolError.slice(colonIndex + 1) : "unknown";
|
|
95700
|
+
}
|
|
95701
|
+
function isWrappedToolError(error2) {
|
|
95702
|
+
return error2 && typeof error2 === "string" && error2.startsWith("wrapped_tool:");
|
|
95703
|
+
}
|
|
95704
|
+
function createWrappedToolErrorMessage(wrappedToolName) {
|
|
95705
|
+
return `Your response contained an incorrectly formatted tool call (${wrappedToolName} wrapped in XML tags). This cannot be used.
|
|
95706
|
+
|
|
95707
|
+
Please use the CORRECT format:
|
|
95708
|
+
|
|
95709
|
+
<${wrappedToolName}>
|
|
95710
|
+
Your content here
|
|
95711
|
+
</${wrappedToolName}>
|
|
95712
|
+
|
|
95713
|
+
Do NOT wrap in other tags like <api_call>, <tool_name>, <function>, etc.`;
|
|
95714
|
+
}
|
|
95382
95715
|
var import_dotenv2, import_anthropic2, import_openai2, import_google2, import_ai5, import_crypto9, import_events4, import_fs14, import_promises6, import_path17, MAX_TOOL_ITERATIONS, MAX_HISTORY_MESSAGES, MAX_IMAGE_FILE_SIZE, ProbeAgent;
|
|
95383
95716
|
var init_ProbeAgent = __esm({
|
|
95384
95717
|
"src/agent/ProbeAgent.js"() {
|
|
@@ -97388,6 +97721,9 @@ You are working with a repository located at: ${searchDirectory}
|
|
|
97388
97721
|
console.log(`[DEBUG] Schema provided, using extended iteration limit: ${maxIterations} (base: ${baseMaxIterations})`);
|
|
97389
97722
|
}
|
|
97390
97723
|
}
|
|
97724
|
+
let lastFormatErrorType = null;
|
|
97725
|
+
let sameFormatErrorCount = 0;
|
|
97726
|
+
const MAX_REPEATED_FORMAT_ERRORS = 3;
|
|
97391
97727
|
while (currentIteration < maxIterations && !completionAttempted) {
|
|
97392
97728
|
currentIteration++;
|
|
97393
97729
|
if (this.cancelled) throw new Error("Request was cancelled by the user");
|
|
@@ -97586,7 +97922,22 @@ You are working with a repository located at: ${searchDirectory}
|
|
|
97586
97922
|
(msg) => msg.role === "assistant" && msg.content && !(this.mcpBridge ? parseHybridXmlToolCall(msg.content, validTools, this.mcpBridge) : parseXmlToolCallWithThinking(msg.content, validTools))
|
|
97587
97923
|
);
|
|
97588
97924
|
if (lastAssistantMessage) {
|
|
97589
|
-
|
|
97925
|
+
const prevContent = lastAssistantMessage.content;
|
|
97926
|
+
const wrappedToolError = detectUnrecognizedToolCall(prevContent, validTools);
|
|
97927
|
+
if (isWrappedToolError(wrappedToolError)) {
|
|
97928
|
+
const wrappedToolName = extractWrappedToolName(wrappedToolError);
|
|
97929
|
+
if (this.debug) {
|
|
97930
|
+
console.log(`[DEBUG] Previous response contains wrapped tool '${wrappedToolName}' - rejecting for __PREVIOUS_RESPONSE__`);
|
|
97931
|
+
}
|
|
97932
|
+
currentMessages.push({ role: "assistant", content: assistantResponseContent });
|
|
97933
|
+
currentMessages.push({
|
|
97934
|
+
role: "user",
|
|
97935
|
+
content: createWrappedToolErrorMessage(wrappedToolName)
|
|
97936
|
+
});
|
|
97937
|
+
completionAttempted = false;
|
|
97938
|
+
continue;
|
|
97939
|
+
}
|
|
97940
|
+
finalResult = prevContent;
|
|
97590
97941
|
if (this.debug) console.log(`[DEBUG] Using previous response as completion: ${finalResult.substring(0, 100)}...`);
|
|
97591
97942
|
} else {
|
|
97592
97943
|
finalResult = "Error: No previous response found to use as completion.";
|
|
@@ -97857,7 +98208,33 @@ ${errorXml}
|
|
|
97857
98208
|
currentMessages.push({ role: "assistant", content: assistantResponseContent });
|
|
97858
98209
|
const unrecognizedTool = detectUnrecognizedToolCall(assistantResponseContent, validTools);
|
|
97859
98210
|
let reminderContent;
|
|
97860
|
-
if (unrecognizedTool) {
|
|
98211
|
+
if (isWrappedToolError(unrecognizedTool)) {
|
|
98212
|
+
const wrappedToolName = extractWrappedToolName(unrecognizedTool);
|
|
98213
|
+
if (this.debug) {
|
|
98214
|
+
console.log(`[DEBUG] Detected wrapped tool '${wrappedToolName}' in assistant response - wrong XML format.`);
|
|
98215
|
+
}
|
|
98216
|
+
const toolError = new ParameterError(
|
|
98217
|
+
`Tool '${wrappedToolName}' found but in WRONG FORMAT - do not wrap tools in other XML tags.`,
|
|
98218
|
+
{
|
|
98219
|
+
suggestion: `Use the tool tag DIRECTLY without any wrapper:
|
|
98220
|
+
|
|
98221
|
+
CORRECT FORMAT:
|
|
98222
|
+
<${wrappedToolName}>
|
|
98223
|
+
<param>value</param>
|
|
98224
|
+
</${wrappedToolName}>
|
|
98225
|
+
|
|
98226
|
+
WRONG (what you did - do not wrap in other tags):
|
|
98227
|
+
<api_call><tool_name>${wrappedToolName}</tool_name>...</api_call>
|
|
98228
|
+
<function>${wrappedToolName}</function>
|
|
98229
|
+
<call name="${wrappedToolName}">...</call>
|
|
98230
|
+
|
|
98231
|
+
Remove ALL wrapper tags and use <${wrappedToolName}> directly as the outermost tag.`
|
|
98232
|
+
}
|
|
98233
|
+
);
|
|
98234
|
+
reminderContent = `<tool_result>
|
|
98235
|
+
${formatErrorForAI(toolError)}
|
|
98236
|
+
</tool_result>`;
|
|
98237
|
+
} else if (unrecognizedTool) {
|
|
97861
98238
|
if (this.debug) {
|
|
97862
98239
|
console.log(`[DEBUG] Detected unrecognized tool '${unrecognizedTool}' in assistant response.`);
|
|
97863
98240
|
}
|
|
@@ -97868,6 +98245,20 @@ ${errorXml}
|
|
|
97868
98245
|
${formatErrorForAI(toolError)}
|
|
97869
98246
|
</tool_result>`;
|
|
97870
98247
|
} else {
|
|
98248
|
+
if (currentIteration >= maxIterations) {
|
|
98249
|
+
let cleanedResponse = assistantResponseContent;
|
|
98250
|
+
cleanedResponse = cleanedResponse.replace(/<thinking>[\s\S]*?<\/thinking>/gi, "").trim();
|
|
98251
|
+
cleanedResponse = cleanedResponse.replace(/<thinking>[\s\S]*$/gi, "").trim();
|
|
98252
|
+
const hasSubstantialContent = cleanedResponse.length > 50 && !cleanedResponse.includes("<api_call>") && !cleanedResponse.includes("<tool_name>") && !cleanedResponse.includes("<function>");
|
|
98253
|
+
if (hasSubstantialContent) {
|
|
98254
|
+
if (this.debug) {
|
|
98255
|
+
console.log(`[DEBUG] Max iterations reached - accepting AI response as final answer (${cleanedResponse.length} chars)`);
|
|
98256
|
+
}
|
|
98257
|
+
finalResult = cleanedResponse;
|
|
98258
|
+
completionAttempted = true;
|
|
98259
|
+
break;
|
|
98260
|
+
}
|
|
98261
|
+
}
|
|
97871
98262
|
reminderContent = `Please use one of the available tools to help answer the question, or use attempt_completion if you have enough information to provide a final answer.
|
|
97872
98263
|
|
|
97873
98264
|
Remember: Use proper XML format with BOTH opening and closing tags:
|
|
@@ -97897,6 +98288,25 @@ Note: <attempt_complete></attempt_complete> reuses your PREVIOUS assistant messa
|
|
|
97897
98288
|
console.log(`[DEBUG] No tool call detected in assistant response. Prompting for tool use.`);
|
|
97898
98289
|
}
|
|
97899
98290
|
}
|
|
98291
|
+
if (unrecognizedTool) {
|
|
98292
|
+
const isWrapped = isWrappedToolError(unrecognizedTool);
|
|
98293
|
+
const errorCategory = isWrapped ? "wrapped_tool" : unrecognizedTool;
|
|
98294
|
+
if (errorCategory === lastFormatErrorType) {
|
|
98295
|
+
sameFormatErrorCount++;
|
|
98296
|
+
if (sameFormatErrorCount >= MAX_REPEATED_FORMAT_ERRORS) {
|
|
98297
|
+
const errorDesc = isWrapped ? "wrapped tool format" : unrecognizedTool;
|
|
98298
|
+
console.error(`[ERROR] Format error category '${errorCategory}' repeated ${sameFormatErrorCount} times. Breaking loop early to prevent infinite iteration.`);
|
|
98299
|
+
finalResult = `Error: Unable to complete request. The AI model repeatedly used incorrect tool call format (${errorDesc}). Please try rephrasing your question or using a different model.`;
|
|
98300
|
+
break;
|
|
98301
|
+
}
|
|
98302
|
+
} else {
|
|
98303
|
+
lastFormatErrorType = errorCategory;
|
|
98304
|
+
sameFormatErrorCount = 1;
|
|
98305
|
+
}
|
|
98306
|
+
} else {
|
|
98307
|
+
lastFormatErrorType = null;
|
|
98308
|
+
sameFormatErrorCount = 0;
|
|
98309
|
+
}
|
|
97900
98310
|
}
|
|
97901
98311
|
if (currentMessages.length > MAX_HISTORY_MESSAGES) {
|
|
97902
98312
|
const messagesBefore = currentMessages.length;
|