mirror of
https://github.com/nexu-io/open-design.git
synced 2026-09-20 06:15:06 +08:00
441ab84b0b
* fix(web): hide an od-card whose JSON does not parse A closed `<od-card>…</od-card>` block whose payload fails to parse was painted to the user as prose — Markdown and all, so `user_profile` came out italic. A tail comma, a missing `summary`, a misspelled `type`: the model writes all three, and each one put raw protocol markup on screen. Product ruling (user, 2026-09-18): "od-card 如果 json 不对, 就不显示, 不然用户会觉得是乱码...还不如不显示". The block is now dropped instead. The drop lives in the web render helper `splitShellCards`, not in the shared `splitOnOdCards` parser: that parser is a lossless split whose other callers (`chat-protocol-context` Markdown skip-ranges, daemon `memory-verify`) read spans of the original text and need every character back. Both chat surfaces — shell narration (`SayBlock`) and prose (`AssistantMessage`) — already route through `splitShellCards`. "Malformed" and "still streaming" stay separate states: dropping needs a matched close tag, so a card mid-flight is still withheld and can still complete into a real card. A fenced code block quoting the protocol is still user prose, and a valid card still renders as `OdCardView`. Refs OPEND-2745 * fix(web): classify Markdown over the text a dropped card leaves behind Dropping a malformed block without recomputing the Markdown context opened a second leak of exactly the kind this change exists to close. `codeRanges` was still derived from the raw input, so markup inside a payload the user never sees kept voting: a payload carrying an unclosed ``` fence on its own line marked everything after it as code, the next perfectly valid card was skipped by `rangeContains`, and the tail `appendText` emitted that valid card as raw `<od-card …>` markup. Markdown context is now classified over the text that will actually be rendered — the prose retained so far in the current render plus the unconsumed suffix — and positions are mapped into that view. Recomputing from the suffix alone would be wrong in the other direction. A dropped block is a hole in one continuous render, not a break in it: the prose before and after it is handed to Markdown as a single string, so the prose before the drop must keep its say over what follows. Judged on the suffix alone, a ``` that sits mid-line in the real render becomes a line-leading fence that hides everything below it — the same leak again. A rendered card, by contrast, really does end the render, so that branch keeps resetting as before. Refs OPEND-2745