revert: remove unnecessary prompt and parser changes from #156 (#169)

The actual fix in #156 was adding chat(ChatRequest) to
ReliableProvider. The prompt changes in instructions.rs and the
bracket tool call parser in parse.rs were added during investigation
but are not needed — the model uses native tool calls when
ReliableProvider properly delegates to the inner provider.
This commit is contained in:
sanil-23
2026-04-01 21:08:23 +05:30
committed by GitHub
parent 3c247a2439
commit 2383d51ea6
2 changed files with 8 additions and 84 deletions
+6 -27
View File
@@ -8,35 +8,14 @@ pub(crate) fn build_tool_instructions(tools_registry: &[Box<dyn Tool>]) -> Strin
instructions.push_str("\n## Tool Use Protocol\n\n");
instructions.push_str("To use a tool, wrap a JSON object in <tool_call></tool_call> tags:\n\n");
instructions.push_str("```\n<tool_call>\n{\"name\": \"tool_name\", \"arguments\": {\"param\": \"value\"}}\n</tool_call>\n```\n\n");
// Explicit anti-hallucination rules
instructions.push_str("### Rules (MUST follow)\n\n");
instructions.push_str(
"1. **ALWAYS use <tool_call> tags** when a task requires a tool. \
NEVER narrate what you would do — emit the actual tags.\n",
"CRITICAL: Output actual <tool_call> tags—never describe steps or give examples.\n\n",
);
instructions.push_str(
"2. **NEVER describe a tool call in prose** (e.g. \"I'll run ls\" or \
\"Let me check the file\") without also emitting the <tool_call> tags. \
If you mention a tool, you must call it.\n",
);
instructions.push_str(
"3. **Use the exact tool names** listed below. \
Do not invent tool names that are not in the list.\n",
);
instructions.push_str("4. You may use **multiple tool calls** in a single response.\n");
instructions.push_str(
"5. After tool execution, results appear in <tool_result> tags. \
Continue reasoning with the results until you can give a final answer.\n",
);
instructions.push_str(
"6. Only respond **without** a tool call when the answer requires \
no tool (e.g. general knowledge, math, or conversation).\n\n",
);
instructions.push_str("### Example\n\n");
instructions.push_str("User: \"what's the date?\"\nCorrect response:\n<tool_call>\n{\"name\":\"shell\",\"arguments\":{\"command\":\"date\"}}\n</tool_call>\n\n");
instructions.push_str("Example: User says \"what's the date?\". You MUST respond with:\n<tool_call>\n{\"name\":\"shell\",\"arguments\":{\"command\":\"date\"}}\n</tool_call>\n\n");
instructions.push_str("You may use multiple tool calls in a single response. ");
instructions.push_str("After tool execution, results appear in <tool_result> tags. ");
instructions
.push_str("Continue reasoning with the results until you can give a final answer.\n\n");
instructions.push_str("### Available Tools\n\n");
for tool in tools_registry {
+2 -57
View File
@@ -82,51 +82,7 @@ pub(crate) fn parse_tool_calls_from_json_value(value: &serde_json::Value) -> Vec
calls
}
/// Parse bracket-style pseudo-syntax emitted by some models:
/// `{tool => "shell", args => { --command "ls" }}`
///
/// Extracts tool name and converts `--key "value"` args into a JSON object.
fn parse_bracket_tool_call(inner: &str) -> Option<ParsedToolCall> {
static BRACKET_TOOL_RE: LazyLock<Regex> = LazyLock::new(|| {
Regex::new(r#"(?s)\{?\s*tool\s*=>\s*"([^"]+)"\s*,\s*args\s*=>\s*\{(.*?)\}\s*\}?"#).unwrap()
});
static ARG_RE: LazyLock<Regex> = LazyLock::new(|| Regex::new(r#"--(\w+)\s+"([^"]*)"#).unwrap());
let cap = BRACKET_TOOL_RE.captures(inner.trim())?;
let name = cap.get(1)?.as_str().to_string();
let args_body = cap.get(2)?.as_str();
let mut args = serde_json::Map::new();
for arg_cap in ARG_RE.captures_iter(args_body) {
let key = arg_cap.get(1)?.as_str().to_string();
let value = arg_cap.get(2)?.as_str().to_string();
args.insert(key, serde_json::Value::String(value));
}
if name.is_empty() {
return None;
}
tracing::debug!(
tool = name.as_str(),
parse_mode = "bracket_syntax",
"[parse] parsed bracket-style tool call"
);
Some(ParsedToolCall {
name,
arguments: serde_json::Value::Object(args),
})
}
const TOOL_CALL_OPEN_TAGS: [&str; 6] = [
"<tool_call>",
"<toolcall>",
"<tool-call>",
"<invoke>",
"[TOOL_CALL]",
"[tool_call]",
];
const TOOL_CALL_OPEN_TAGS: [&str; 4] = ["<tool_call>", "<toolcall>", "<tool-call>", "<invoke>"];
pub(crate) fn find_first_tag<'a>(haystack: &str, tags: &'a [&'a str]) -> Option<(usize, &'a str)> {
tags.iter()
@@ -140,8 +96,6 @@ pub(crate) fn matching_tool_call_close_tag(open_tag: &str) -> Option<&'static st
"<toolcall>" => Some("</toolcall>"),
"<tool-call>" => Some("</tool-call>"),
"<invoke>" => Some("</invoke>"),
"[TOOL_CALL]" => Some("[/TOOL_CALL]"),
"[tool_call]" => Some("[/tool_call]"),
_ => None,
}
}
@@ -422,16 +376,7 @@ pub(crate) fn parse_tool_calls(response: &str) -> (String, Vec<ParsedToolCall>)
}
if !parsed_any {
// Try parsing bracket pseudo-syntax:
// {tool => "name", args => { --key "value" }}
if let Some(call) = parse_bracket_tool_call(inner) {
calls.push(call);
parsed_any = true;
}
}
if !parsed_any {
tracing::warn!("Malformed tool_call body: could not parse tag content as JSON or bracket syntax");
tracing::warn!("Malformed <tool_call> JSON: expected tool-call object in tag body");
}
remaining = &after_open[close_idx + close_tag.len()..];