diff --git a/apps/ai-game-creator-shell/scripts/start-dev-server.mjs b/apps/ai-game-creator-shell/scripts/start-dev-server.mjs index 9a4914dcb..f1f76ff31 100644 --- a/apps/ai-game-creator-shell/scripts/start-dev-server.mjs +++ b/apps/ai-game-creator-shell/scripts/start-dev-server.mjs @@ -92,6 +92,8 @@ const child = spawn( { cwd: appRoot, stdio: 'inherit', + // Node 18.20+/20+/24 on Windows rejects spawning .cmd (npm.cmd) without a shell (EINVAL). + shell: true, }, ); diff --git a/server-rs/crates/platform-llm/src/lib.rs b/server-rs/crates/platform-llm/src/lib.rs index 0744e522a..fa7fde1bd 100644 --- a/server-rs/crates/platform-llm/src/lib.rs +++ b/server-rs/crates/platform-llm/src/lib.rs @@ -1838,10 +1838,9 @@ fn parse_anthropic_sse_event(data: &str) -> Result, Ll .and_then(serde_json::Value::as_str) .map(str::to_string), })), - "message_stop" => Ok(Some(ParsedStreamEvent { - delta_text: None, - finish_reason: Some("stop".to_string()), - })), + // message_stop 只是流终止信号;真正的 stop_reason 已由 message_delta 提供, + // 这里不要伪造 finish_reason,否则会覆盖掉 end_turn 等真实值。 + "message_stop" => Ok(None), "error" => { let message = parsed .get("error") @@ -2640,7 +2639,8 @@ mod tests { body: concat!( "data: {\"type\":\"content_block_delta\",\"delta\":{\"type\":\"text_delta\",\"text\":\"你\"}}\n\n", "data: {\"type\":\"content_block_delta\",\"delta\":{\"type\":\"text_delta\",\"text\":\"好\"}}\n\n", - "data: {\"type\":\"message_delta\",\"delta\":{\"stop_reason\":\"end_turn\"}}\n\n" + "data: {\"type\":\"message_delta\",\"delta\":{\"stop_reason\":\"end_turn\"}}\n\n", + "data: {\"type\":\"message_stop\"}\n\n" ) .to_string(), extra_headers: vec![("x-request-id", "req_anthropic_stream_01")],