diff --git a/crates/tui/src/core/engine/tests.rs b/crates/tui/src/core/engine/tests.rs index 00a82681..d6177f8b 100644 --- a/crates/tui/src/core/engine/tests.rs +++ b/crates/tui/src/core/engine/tests.rs @@ -635,10 +635,7 @@ fn turn_metadata_skips_tool_result_messages() { // The earlier real user message receives the turn_meta prefix. let real_user = messages.first().expect("first user message"); assert_eq!(real_user.role, "user"); - let ContentBlock::Text { text, .. } = real_user - .content - .first() - .expect("user text content") + let ContentBlock::Text { text, .. } = real_user.content.first().expect("user text content") else { panic!("expected Text block on real user message"); }; diff --git a/npm/deepseek-tui/scripts/install.js b/npm/deepseek-tui/scripts/install.js index 52e0219e..9bfd1795 100644 --- a/npm/deepseek-tui/scripts/install.js +++ b/npm/deepseek-tui/scripts/install.js @@ -778,12 +778,26 @@ async function downloadText(url) { stallMs: downloadStallMs(), }); const response = result.response; - const chunks = []; response.setEncoding("utf8"); - for await (const chunk of response) { - chunks.push(chunk); - } - return chunks.join(""); + // NOTE: do NOT use `for await (const chunk of response)` here. + // `httpRequest` attaches a `data` listener on the response to re-arm + // the stall timer, which puts the stream in flowing mode. The async + // iterator expects paused mode and will silently miss every chunk — + // this manifested as an empty checksum manifest in the npm wrapper + // smoke test ("Checksum manifest is missing "). Subscribing + // to `data` events directly stacks alongside the stall listener and + // both fire per chunk, so we collect the body correctly without + // disturbing the stall detection. + return new Promise((resolve, reject) => { + const chunks = []; + response.on("data", (chunk) => { + chunks.push(chunk); + }); + response.on("end", () => { + resolve(chunks.join("")); + }); + response.on("error", reject); + }); }); }