修复: 命名空间上限与网络域解析兜底

- 命名空间超容单条拒绝,上限不变式恢复
- usage 部分字段缺失致整帧内容蒸发,补缺省兜底
- tool_call 缺 id 致整批丢弃,对齐流式 fallback 口径
- 视觉模型判定改词素尾,deepseek-v3 不再误判
- 并行分支 panic 任务对账补齐为失败结果
- plan 执行器死代码清理,实况注释校正
This commit is contained in:
lxy
2026-10-03 17:57:33 +08:00
parent 3e3c6f4d0f
commit 8e09112d59
8 changed files with 259 additions and 19 deletions
+28
View File
@@ -310,7 +310,15 @@ impl OpenAICompatProvider {
.into_iter()
.enumerate()
.map(|(i, c)| {
let missing_id = c.id.is_empty();
let id = tool_call_id_or_fallback(&c.id, i, "gen_tool");
if missing_id {
tracing::warn!(
function = %c.function.name,
fallback_id = %id,
"[OpenAI] 同步响应 tool_call 缺/空 id,已生成 fallback id(防结果路由串号)"
);
}
ToolCall::new(id, c.function.name, c.function.arguments)
})
.collect()
@@ -1293,6 +1301,26 @@ mod tests {
assert_eq!(ids.len(), unique.len(), "id 应全部唯一,实际 {:?}", ids);
}
/// 同步响应 tool_call 缺 id/arguments 字段:serde default 兜底(空串/空串),
/// 缺 id 经 parse_tool_calls 生成 fallback。旧行为:id 必填,单条缺字段令整个
/// 响应 serde 失败 → complete 报"响应解析失败"整批丢弃。
#[test]
fn openai_sync_tool_call_missing_fields_default_instead_of_failing() {
let calls: Vec<OpenAiToolCallResp> = serde_json::from_str(
r#"[{"type":"function","function":{"name":"list_dir"}}]"#,
)
.expect("缺 id/arguments 的 tool_call 应可反序列化,不再整响应解析失败");
let parsed = OpenAICompatProvider::parse_tool_calls(calls);
assert_eq!(parsed.len(), 1);
assert!(
parsed[0].id.starts_with("gen_tool_"),
"缺 id → fallback id, got: {}",
parsed[0].id
);
assert_eq!(parsed[0].function.name, "list_dir");
assert_eq!(parsed[0].function.arguments, "", "缺 arguments 缺省空串");
}
/// CR-空 id 流式:SSE chunk 携带 `"id":""`(SenseNova 兼容缺陷)→ ToolCallDelta.id
/// 转为 `gen_stream_{n}` fallback(n 取自全局计数器,跨轮跨 assistant 递增,非 None),
/// 保证下游 accumulate_tool_calls 写入 draft.id 非空。chunk 完全无 id 字段(None)保持