Merge pull request #397 from kevin9327/fix/duplicate-tool-call-id-hang

fix(conversation): scope completed tool call ids to their round
This commit is contained in:
leokun
2026-09-04 15:46:17 +08:00
committed by GitHub
2 changed files with 156 additions and 0 deletions
+11
View File
@@ -158,6 +158,7 @@ impl ConversationOutput {
let mut streams = BTreeMap::<usize, ToolCallStream>::new();
let mut completions = HashMap::<String, ToolCompletion>::new();
let mut completed = HashSet::<String>::new();
let mut completed_round = None::<ToolRoundId>;
let mut response_text = String::new();
let mut response_thinking = String::new();
let mut active_round = None::<ToolRoundId>;
@@ -425,6 +426,16 @@ impl ConversationOutput {
round_id,
calls: round_calls,
} => {
// `completed` exists so that replaying ExecuteToolRound for a round
// does not dispatch a call this round already committed. Tool call ids
// are only unique *within* a round -- the schema says as much with
// `UNIQUE (round_id, call_id)` -- so an id retained from an earlier
// round would make start_batch skip a fresh call, and tool_round wait
// forever for a result nothing will ever produce.
if completed_round.as_ref() != Some(&round_id) {
completed.clear();
completed_round = Some(round_id.clone());
}
active_round = Some(round_id.clone());
active_tool_calls = round_calls
.iter()