From df3ed55d015fefae9e1ae74fb2d79fea2d07c2b2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=BB=9D=E5=B0=98?= <237809796@qq.com> Date: Thu, 1 Oct 2026 02:41:21 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BF=AE=E5=A4=8D:=20=E6=B5=8B=E8=AF=95?= =?UTF-8?q?=E8=BF=9B=E7=A8=8B=20comctl32=20=E5=BB=B6=E8=BF=9F=E5=8A=A0?= =?UTF-8?q?=E8=BD=BD=E4=B8=8E=E6=B5=81=E5=BC=8F=20usage=20=E6=96=AD?= =?UTF-8?q?=E8=A8=80=E5=90=8C=E6=AD=A5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit lib 测试无内嵌窗口清单,GUI 依赖静态绑定 comctl32 缺导出致测试进程启动即崩 改 DELAYLOAD 推迟绑定,测试进程不触碰 GUI 入口;app 端清单选 v6 行为不变 流式 usage 改为 message_start 同帧携带初始快照,断言对齐该语义 --- crates/df-ai/src/anthropic_compat.rs | 6 +++++- crates/df-ai/src/openai_compat.rs | 14 +++++++++++--- src-tauri/build.rs | 9 +++++++++ 3 files changed, 25 insertions(+), 4 deletions(-) diff --git a/crates/df-ai/src/anthropic_compat.rs b/crates/df-ai/src/anthropic_compat.rs index c4da0c1..57bb38a 100644 --- a/crates/df-ai/src/anthropic_compat.rs +++ b/crates/df-ai/src/anthropic_compat.rs @@ -787,9 +787,13 @@ mod tests { let mut acc: Option = None; // 1) message_start:input=42,output=0 + // (6bafdcd 起 usage 同帧挂载:message_start 即带初始快照,中途断连也能拿到真实 usage) let c = apply_anthropic_event(&message_start(42), &mut acc); assert!(!c.finished); - assert!(c.usage.is_none()); + let u0 = c.usage.expect("message_start 应同帧带出初始 usage 快照"); + assert_eq!(u0.prompt_tokens, 42); + assert_eq!(u0.completion_tokens, 0); + assert_eq!(u0.total_tokens, 42); let a = acc.as_ref().expect("message_start 应初始化累加器"); assert_eq!(a.prompt_tokens, 42); assert_eq!(a.completion_tokens, 0); diff --git a/crates/df-ai/src/openai_compat.rs b/crates/df-ai/src/openai_compat.rs index 63e74e2..1dab082 100644 --- a/crates/df-ai/src/openai_compat.rs +++ b/crates/df-ai/src/openai_compat.rs @@ -696,10 +696,14 @@ mod tests { assert_eq!(c.delta, ""); assert!(acc.is_none(), "此 chunk 无 usage 字段,累加器仍为 None"); - // 4) usage-only chunk(choices=[])携带累计 usage → 覆盖累加器 + // 4) usage-only chunk(choices=[])携带累计 usage → 覆盖累加器,并同帧带出快照 + // (6bafdcd 起 usage 与累加器同帧挂载,中途断连也能拿到真实 usage,非仅 [DONE] 带出) let c = apply_openai_sse(&usage_only_chunk(12, 34), &mut acc); assert!(!c.finished); - assert!(c.usage.is_none(), "非 [DONE] chunk 不带出 usage"); + let u = c.usage.expect("usage-only chunk 应同帧带出累积 usage 快照"); + assert_eq!(u.prompt_tokens, 12); + assert_eq!(u.completion_tokens, 34); + assert_eq!(u.total_tokens, 46); let acc = acc.expect("累加器应已被 usage-only chunk 覆盖写入"); assert_eq!(acc.prompt_tokens, 12); assert_eq!(acc.completion_tokens, 34); @@ -712,7 +716,11 @@ mod tests { let mut acc: Option = None; let c = apply_openai_sse(&text_chunk_with_usage("", "stop", 100, 200), &mut acc); assert!(c.finished); - assert!(c.usage.is_none(), "非 [DONE] 不带出 usage,仅覆盖累加器"); + // 6bafdcd 起 usage 与累加器同帧挂载:finish 帧即带快照,下游不必等 [DONE] + let u = c.usage.expect("finish 帧应同帧带出累积 usage 快照"); + assert_eq!(u.prompt_tokens, 100); + assert_eq!(u.completion_tokens, 200); + assert_eq!(u.total_tokens, 300); let acc = acc.expect("末段 chunk 的 usage 应已覆盖累加器"); assert_eq!(acc.prompt_tokens, 100); assert_eq!(acc.completion_tokens, 200); diff --git a/src-tauri/build.rs b/src-tauri/build.rs index 1caf966..2f2dac1 100644 --- a/src-tauri/build.rs +++ b/src-tauri/build.rs @@ -17,4 +17,13 @@ fn main() { println!("cargo:rustc-env=MCP_APP_IDENTIFIER={}", identifier); } } + + // 测试二进制(lib test)没有 tauri 给 bin 内嵌的窗口清单,而 GUI 依赖(tao/muda/tray_icon) + // 会静态导入 comctl32 的 TaskDialogIndirect 等导出(仅存在于 SxS v6 程序集),无清单时 + // 加载器绑定 System32 的 5.82 版(缺这些导出),进程启动即 STATUS_ENTRYPOINT_NOT_FOUND, + // cargo test 全部无法运行。用延迟加载把 comctl32 绑定推迟到首次调用,测试进程从不触碰 + // GUI 入口即永不解析;app 端 bin 自带清单选到 v6,行为不变。不用 /MANIFEST:EMBED 方案是 + // 因为它会与 tauri 内嵌的资源清单产生重复 RT_MANIFEST,链接失败。 + println!("cargo:rustc-link-arg=/DELAYLOAD:comctl32.dll"); + println!("cargo:rustc-link-lib=delayimp"); }