mirror of
https://github.com/tinyhumansai/openhuman.git
synced 2026-07-27 21:08:00 +00:00
test(agent-harness): restore TAURI-RUST-4 dedup seam test (#2665)
Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 4.7
parent
fa85d5c44e
commit
1aee7ded8d
@@ -1148,3 +1148,115 @@ fn hard_reject_distinct_args_do_not_trip_repeat() {
|
||||
"6 distinct hard rejects in a row should still trip the no-progress guard"
|
||||
);
|
||||
}
|
||||
|
||||
/// Provider that records the tool-spec names of every `chat()` request
|
||||
/// it sees, then returns the next scripted response.
|
||||
struct CapturingProvider {
|
||||
/// One entry per `chat()` call — the tool-name list extracted from
|
||||
/// `ChatRequest.tools`. `None` if `tools` was `None`.
|
||||
captured: Mutex<Vec<Option<Vec<String>>>>,
|
||||
responses: Mutex<Vec<anyhow::Result<ChatResponse>>>,
|
||||
native_tools: bool,
|
||||
}
|
||||
|
||||
#[async_trait]
|
||||
impl Provider for CapturingProvider {
|
||||
async fn chat_with_system(
|
||||
&self,
|
||||
_system_prompt: Option<&str>,
|
||||
_message: &str,
|
||||
_model: &str,
|
||||
_temperature: f64,
|
||||
) -> Result<String> {
|
||||
Ok("fallback".into())
|
||||
}
|
||||
|
||||
async fn chat(
|
||||
&self,
|
||||
request: ChatRequest<'_>,
|
||||
_model: &str,
|
||||
_temperature: f64,
|
||||
) -> Result<ChatResponse> {
|
||||
let names = request
|
||||
.tools
|
||||
.map(|specs| specs.iter().map(|s| s.name.clone()).collect::<Vec<_>>());
|
||||
self.captured.lock().push(names);
|
||||
let mut guard = self.responses.lock();
|
||||
guard.remove(0)
|
||||
}
|
||||
|
||||
fn capabilities(&self) -> ProviderCapabilities {
|
||||
ProviderCapabilities {
|
||||
native_tool_calling: self.native_tools,
|
||||
vision: false,
|
||||
..ProviderCapabilities::default()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn run_tool_call_loop_dedups_duplicate_tool_names_before_provider_call() {
|
||||
// Provider returns a single final text response — no tool calls —
|
||||
// so the loop terminates after exactly one `chat()` invocation,
|
||||
// and the captured tool list reflects what the fix is supposed to
|
||||
// guard against (no duplicate names reaching the wire).
|
||||
let provider = CapturingProvider {
|
||||
captured: Mutex::new(Vec::new()),
|
||||
responses: Mutex::new(vec![Ok(ChatResponse {
|
||||
text: Some("done".into()),
|
||||
tool_calls: vec![],
|
||||
usage: None,
|
||||
})]),
|
||||
// Native tool-calling on: only when the provider supports native
|
||||
// tools does `run_tool_call_loop` populate `ChatRequest.tools`.
|
||||
native_tools: true,
|
||||
};
|
||||
|
||||
// Registry has `EchoTool` (name = "echo"). `extra_tools` adds a
|
||||
// second tool also named "echo" — the exact collision pattern from
|
||||
// the bug report (a synthesised delegation tool whose
|
||||
// `delegate_name` shadows a same-named skill tool).
|
||||
let registry: Vec<Box<dyn Tool>> = vec![Box::new(EchoTool)];
|
||||
let extra: Vec<Box<dyn Tool>> = vec![Box::new(EchoTool)];
|
||||
|
||||
let mut history = vec![ChatMessage::user("hi")];
|
||||
let result = run_tool_call_loop(
|
||||
&provider,
|
||||
&mut history,
|
||||
®istry,
|
||||
"test-provider",
|
||||
"model",
|
||||
0.0,
|
||||
true,
|
||||
None,
|
||||
"channel",
|
||||
&crate::openhuman::config::MultimodalConfig::default(),
|
||||
2,
|
||||
None,
|
||||
None,
|
||||
&extra,
|
||||
None,
|
||||
None,
|
||||
&crate::openhuman::tools::policy::DefaultToolPolicy,
|
||||
)
|
||||
.await
|
||||
.expect("loop should succeed with deduplicated tool list");
|
||||
assert_eq!(result, "done");
|
||||
|
||||
let captured = provider.captured.lock();
|
||||
assert_eq!(
|
||||
captured.len(),
|
||||
1,
|
||||
"exactly one chat() call expected for a final-only response"
|
||||
);
|
||||
let names = captured[0]
|
||||
.as_ref()
|
||||
.expect("native_tools=true should populate ChatRequest.tools");
|
||||
let echo_count = names.iter().filter(|n| n.as_str() == "echo").count();
|
||||
assert_eq!(
|
||||
echo_count, 1,
|
||||
"duplicate tool names must be dropped before the provider call \
|
||||
(TAURI-RUST-4) — got names={:?}",
|
||||
names
|
||||
);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user