修复: 协议层与体验缺陷六件
- temperature 按模型适配,仅收 1 的模型不再 400 - 流式 error 帧不再被 choices 必填整帧丢弃 - 只读缓存写后失效 - git diff 中文截断撞 UTF-8 边界 panic - 非视觉模型纯图片直接拒绝 - 全局快捷键补输入焦点守卫
This commit is contained in:
@@ -51,7 +51,7 @@
|
||||
|
||||
use serde::Deserialize;
|
||||
use serde_json::Value;
|
||||
use tauri::{AppHandle, Emitter, State};
|
||||
use tauri::{AppHandle, State};
|
||||
|
||||
use crate::state::AppState;
|
||||
|
||||
|
||||
@@ -102,6 +102,9 @@ pub(crate) enum StreamResult {
|
||||
usage: df_ai::provider::TokenUsage,
|
||||
/// DeepSeek thinking 模式推理内容(需回传到下一轮请求)
|
||||
reasoning_content: Option<String>,
|
||||
/// 流因 provider max_tokens 上限截断(finish_reason=length / stop_reason=max_tokens)。
|
||||
/// true=文本/tool_calls 可能不完整,调用方据此标记该轮产出截断,不冒充正常完成。
|
||||
truncated_by_max_tokens: bool,
|
||||
},
|
||||
/// 流中途断(MidStream chunk Err / idle timeout / provider stream-error / 有 partial_text
|
||||
/// 但流尽未收到 finished)。已 emit 过 AiTextDelta(前端 currentText 已累积),
|
||||
@@ -282,6 +285,9 @@ pub(crate) async fn stream_llm(
|
||||
let mut finished_received = false;
|
||||
let mut stopped = false;
|
||||
let mut final_usage: Option<df_ai::provider::TokenUsage> = None;
|
||||
// max_tokens 截断标志跨帧 OR 累积(openai finish_reason=length / anthropic
|
||||
// stop_reason=max_tokens 的帧先于终态帧到达),Complete 随旗标带出供上层标记截断。
|
||||
let mut truncated_by_max_tokens = false;
|
||||
// DeepSeek thinking 模式推理内容累积(多轮需回传)
|
||||
let mut reasoning_content_acc: Option<String> = None;
|
||||
// per-conv delta 合批累加器。pending_delta 累积未 flush 的文本,
|
||||
@@ -419,6 +425,9 @@ pub(crate) async fn stream_llm(
|
||||
if let Some(u) = &chunk.usage {
|
||||
final_usage = Some(u.clone());
|
||||
}
|
||||
if chunk.truncated_by_max_tokens {
|
||||
truncated_by_max_tokens = true;
|
||||
}
|
||||
if let Some(ref rc) = chunk.reasoning_content {
|
||||
reasoning_content_acc.get_or_insert_with(String::new).push_str(rc);
|
||||
}
|
||||
@@ -540,6 +549,7 @@ pub(crate) async fn stream_llm(
|
||||
tool_calls: tool_calls_acc,
|
||||
usage: final_usage.unwrap_or_default(),
|
||||
reasoning_content: reasoning_content_acc,
|
||||
truncated_by_max_tokens,
|
||||
};
|
||||
}
|
||||
|
||||
@@ -573,6 +583,7 @@ pub(crate) async fn stream_llm(
|
||||
tool_calls: tool_calls_acc,
|
||||
usage: final_usage.unwrap_or_default(),
|
||||
reasoning_content: reasoning_content_acc,
|
||||
truncated_by_max_tokens,
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -156,9 +156,13 @@ async fn run_git_diff(working_dir: &str, staged: bool) -> serde_json::Value {
|
||||
let mut patch_args = vec!["diff"];
|
||||
if staged { patch_args.push("--cached"); }
|
||||
let patch_raw = exec_git_exit(working_dir, &patch_args).await.0;
|
||||
// 截断到 8000 字符(防大体量 diff)
|
||||
// 截断到 8000 字符(防大体量 diff);中文字节切片撞 UTF-8 边界会 panic,回退到字符边界
|
||||
let patch_truncated = if patch_raw.len() > 8000 {
|
||||
format!("{}\n... (diff 截断,共 {} 字符)", &patch_raw[..8000], patch_raw.len())
|
||||
let mut end = 8000;
|
||||
while !patch_raw.is_char_boundary(end) {
|
||||
end -= 1;
|
||||
}
|
||||
format!("{}\n... (diff 截断,共 {} 字符)", &patch_raw[..end], patch_raw.len())
|
||||
} else {
|
||||
patch_raw
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user