fix(agents): recover bare tool names to their unique prefixed tool

Models prompted with bare names such as write_file hit 'Tool not advertised'
even though sandbox-fs__write_file was available. Ambiguous matches still
fail.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
john
2026-09-23 14:25:12 +08:00
parent c44c7f04be
commit 52dd6697c6
+36 -1
View File
@@ -309,10 +309,15 @@ pub(crate) fn recover_mangled_tool_name<'a>(
let owner_mangled = owner.map(|o| format!("{o}.{name}"));
let owner_prefixed = owner.map(|o| format!("{o}__{name}"));
// Models prompted with bare tool names ("write_file") drop the extension
// prefix entirely; recover only when exactly one extension owns that tool.
let bare_tool = name.split_once("__").map(|(_, tool)| tool);
let matches = stripped == name
|| separator_mangled.as_deref() == Some(stripped)
|| owner_mangled.as_deref() == Some(stripped)
|| owner_prefixed.as_deref() == Some(stripped);
|| owner_prefixed.as_deref() == Some(stripped)
|| bare_tool == Some(stripped);
if name == emitted || !matches {
continue;
}
@@ -3805,6 +3810,36 @@ mod tests {
);
}
#[test]
fn test_recover_mangled_tool_name_bare_tool_without_extension_prefix() {
let tools = [
("sandbox-fs__write_file", None),
("sandbox-fs__read_file", None),
("developer__shell", None),
];
assert_eq!(
recover_mangled_tool_name("write_file", tools.iter().copied()).as_deref(),
Some("sandbox-fs__write_file")
);
assert_eq!(
recover_mangled_tool_name("functions.read_file", tools.iter().copied()).as_deref(),
Some("sandbox-fs__read_file")
);
assert_eq!(
recover_mangled_tool_name("edit_file", tools.iter().copied()),
None
);
let ambiguous = [
("sandbox-fs__write_file", None),
("other__write_file", None),
];
assert_eq!(
recover_mangled_tool_name("write_file", ambiguous.iter().copied()),
None
);
}
#[test]
fn test_recover_mangled_tool_name_non_extension_manager_tools() {
// recipe__final_output and platform__manage_schedule are appended by