Repository navigation
fix(parser): read tag attributes from raw text, not rich HTML - #227
Open
HuanyuMark wants to merge 3 commits into
Open
HuanyuMark wants to merge 3 commits into
HuanyuMark wants to merge 3 commits into
Conversation
Why: BDS tag attribute values are opaque, but the parser read richText, which serialises a KaTeX subtree as outerHTML. A payload containing two dollar signs was rendered as inline math, so MCP arguments arrived as span markup instead of the original text. A failed render could delete the payload outright: katexToMarkdown returned an empty string when a .katex element had neither an annotation nor a math child, and both callers replaced the subtree with that empty string. Fix: parse tags and attributes from rawText, where KaTeX collapses back to dollar-delimited source, and keep richText only for the overlay visible text. marked has no KaTeX plugin and needs the renderer markup, so feeding it rawText would show literal delimiters instead of formulas. Also make katexToMarkdown fall back to MathML text and then to element text rather than returning empty. Impact: attribute values now survive dollar signs. This does NOT fix backslash-slash collapsing, bare-URL autolinking, or ampersand entity round-trips. Those are rewritten by the Markdown renderer before the DOM exists and need pre-render stream capture. Verified: build:chrome passes. Full unit suite 146 files and 2212 tests pass. The new test fails without the katexToMarkdown change, reporting an empty extraction, and passes with it. Manual check: an MCP start_process call whose args command wraps a letter in dollar signs now delivers them literally to the server instead of KaTeX span markup. Refs: bug report on BDS tag attribute values destroyed by the Markdown render pipeline
为什么:`<BDS:...>` 的属性值是模型写的原始 payload,但插件此前只能从渲染后的 DOM 里反向重建。marked 在渲染阶段就按 CommonMark 规则吃掉了 `\/` 这类转义 (`\/` -> `/`),DOM 里已无据可依,parseBdsMessage 拿到的是被改写的参数, MCP 的 args 会静默截断。PR EdgeTypE#227 把解析源从 richText 换成 rawText,绕过了 KaTeX,但 rawText 同样是 DOM 派生物,绕不过 CommonMark。 修复:fetch-patch 在读取 completion 流的 token usage 时,本来就已经把完整 SSE 响应读进 buffer。现在从同一个 buffer 里按 APPEND 操作重建回复原文, 经 bds:raw-reply 事件交给 content script,按会话缓存。message-processor 在解析标签时优先使用这份原文;缓存未命中(历史消息、刷新后重放)则退回 原有 rawText 路径,行为不变。 影响/权衡: - 只覆盖当前会话刚生成的回复。历史消息仍然走 DOM 重建,`\/` 依旧会丢, 这是 API 不提供原始 markdown 的限制,不是本改动能修的。 - 缓存按会话保存最近 5 条,仅最新一条 assistant 消息会消费,避免多消息 场景下错位。 - 缓存到达时机在流结束之后,因此它参与 stateData.hash 计算;否则已 settle 的消息不会用更好的来源重新解析。 - 裸 URL -> autolink 与 `&` -> `&` 不受影响,仍由 link-artifacts 和 HTML 实体解码兜底。 验证: - 新增 src/injected/reply-text.test.js(7 项),覆盖 APPEND 拼接、首帧 fragment、反斜杠保留、message_id 提取、非目标字段忽略、非 JSON 容错、 空输入。 - 红->绿:先跑出 Cannot find module,实现后 7/7 通过。 - 全量:147 文件 / 2219 测试通过(基线 2212 + 新增 7)。 - 构建:npm build.js 成功,dist-chrome 的 injected.js 与 content.js 均包含 bds:raw-reply。 - 真实流取证:用 Playwright 拦截 chat.deepseek.com 的 completion 响应, 确认服务端原样返回 `D:\/test`,反斜杠在 SSE 层完好。 Refs: EdgeTypE#227
Update @playwright/test to 1.64.1 to support Ubuntu 26.04 in GitHub Actions. Verified: 147 files / 2219 tests passed.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Why: BDS tag attribute values are opaque, but the parser read richText, which serialises a KaTeX subtree as outerHTML. A payload containing two dollar signs was rendered as inline math, so MCP arguments arrived as span markup instead of the original text. A failed render could delete the payload outright: katexToMarkdown returned an empty string when a .katex element had neither an annotation nor a math child, and both callers replaced the subtree with that empty string.
Fix: parse tags and attributes from rawText, where KaTeX collapses back to dollar-delimited source, and keep richText only for the overlay visible text. marked has no KaTeX plugin and needs the renderer markup, so feeding it rawText would show literal delimiters instead of formulas. Also make katexToMarkdown fall back to MathML text and then to element text rather than returning empty.
Impact: attribute values now survive dollar signs. This does NOT fix backslash-slash collapsing, bare-URL autolinking, or ampersand entity round-trips. Those are rewritten by the Markdown renderer before the DOM exists and need pre-render stream capture.
Verified: build:chrome passes. Full unit suite 146 files and 2212 tests pass. The new test fails without the katexToMarkdown change, reporting an empty extraction, and passes with it. Manual check: an MCP start_process call whose args command wraps a letter in dollar signs now delivers them literally to the server instead of KaTeX span markup.
Refs: bug report on BDS tag attribute values destroyed by the Markdown render pipeline
Update: Preserve streamed text for
\/escapesThe original commit fixed
$...$payload deletion caused by KaTeX. However,rawText(reconstructed from DOM) still loses CommonMark escapes like\/→/.The new commit (
4e948b2) intercepts the raw SSE stream infetch-patch.jsand usesextractReplyTextFromSseto rebuild the original text before the renderer touches it. This ensures tag attributes are parsed from the exact bytes the model wrote.src/injected/reply-text.jsand its 7 tests.bridge.js(bds:raw-replyevent) keyed by session.message-processor.svelte.jsprioritizes the cached stream text; falls back to DOM-reconstructedrawTextfor history messages.Note: This does NOT cover history messages loaded from the API (original markdown is not stored by DeepSeek).