修复: 上下文流式与工具签名域清债

- tool_signature 归一化补参,合法换参不再误触探索熔断
- SSE 超限截头改对齐事件边界保尾,流不再永久破损
- content_filter 纳入终态判定,无 DONE 流也收敛
- sanitize 占位补头前缀短路只吞 orphan 的盲区消除
- intent 关键词加词边界,history 不再误判
- 恢复重放后重置话题锚点,URL 图 token 地板不被稀释
This commit is contained in:
lxy
2026-10-03 15:35:05 +08:00
parent 499aa49e49
commit c1e5b96d75
10 changed files with 638 additions and 73 deletions
+13 -6
View File
@@ -626,16 +626,23 @@ impl LlmProvider for AnthropicCompatProvider {
error!(%status, %text, "Anthropic API 调用失败(不可重试)");
return AttemptOutcome::Fatal(msg);
}
let resp: AnthropicResponse = match resp.json().await {
Ok(r) => r,
// serde 结构错属 Fatal(重试同败);body 读取中途断连同归 is_decode,可重试。
// body 解析:text 先取再 serde 分层判定:读取中断(text Err,reqwest 归
// is_decode 类,complete 重发幂等安全)可重试;JSON 结构错属 Fatal(响应已
// 完整送达,重试同败)。Response::json 把 serde 错同包成 is_decode,先 text
// 后 from_str 才能区分二者,避免确定性结构错被重试白烧预算。
let text = match resp.text().await {
Ok(t) => t,
Err(e) => {
if e.is_decode() {
return AttemptOutcome::Retryable(format!("响应解码失败(可重试): {}", e));
if is_reqwest_error_retryable(&e) || e.is_decode() {
return AttemptOutcome::Retryable(format!("响应读取失败(可重试): {}", e));
}
return AttemptOutcome::Fatal(format!("响应解析失败: {}", e));
return AttemptOutcome::Fatal(format!("响应读取失败(不可重试): {}", e));
}
};
let resp: AnthropicResponse = match serde_json::from_str(&text) {
Ok(r) => r,
Err(e) => return AttemptOutcome::Fatal(format!("响应解析失败: {}", e)),
};
// content 块中拼接 text,收集 tool_use,累积 thinking
let mut text = String::new();
let mut reasoning = String::new();