Skip to content

fix(voice): keep link text when the url has parentheses - #8121

Open
ANDROIDHASSAN wants to merge 3 commits into
livekit:mainfrom
ANDROIDHASSAN:fix/markdown-link-parens
Open

ANDROIDHASSAN wants to merge 3 commits into
livekit:mainfrom
ANDROIDHASSAN:fix/markdown-link-parens

Conversation

@ANDROIDHASSAN

@ANDROIDHASSAN ANDROIDHASSAN commented Oct 25, 2026 •

Copy link
Copy Markdown
Contributor

Problem

filter_markdown cuts a link or image destination at its first ). LLMs often cite Wikipedia URLs like .../Python_(language), so

read [Python](https://en.wikipedia.org/wiki/Python_(language)) first

reaches TTS as read Python) first. For ![the logo](img_(1).png) here it gives the logo.png) here. When the alt or link text contains a space, the pending-link check has the same problem: it treats the link as finished after the inner ).

Fix

The destination may now contain one level of balanced parentheses, as CommonMark allows. A backslash-escaped paren (\(, \)) is read as one destination character and opens no group, so [guide](https://example.com/a\(b) is still stripped to guide, as on main. The change is in the image and link patterns and in _PENDING_LINK. The alternatives (\\., [^()\\] and \() never overlap, so the patterns still run in linear time. 20k-character inputs of (, \, \( or plain text after [a]( finish in under 3 ms.

Tests

test_link_text_kept runs a plain link, a Wikipedia-style link, an image with multi-word alt text, and a link and an image whose destination holds an escaped \(. Each case uses the suite's _outputs helper (from #8510), so every chunk size must give exactly the expected text.

  • On main: both paren cases fail, e.g. {'the logo.png) here'} != {'the logo here'} and {'read Python) first'} != {'read Python first'}.
  • The escaped-paren cases pass on main and guard against reading \( as a group (they failed on this PR's first commit).
  • With only _PENDING_LINK reverted: the image case fails (![the logo](img_(1).png) here passes through unchanged at chunk size 1).
  • After merging main: uv run pytest --unit --audio_eot -q: 6235 passed, 4 skipped. ruff format, ruff check and make type-check are clean.

Scope

  • Only one level of nesting. Deeper nesting is rare in URLs and would need a recursive pattern.
  • Unbalanced [a](b(c) is no longer stripped to a. It is left as is, which matches CommonMark: it is not a link there either.

The link and image patterns stopped the destination at the first ')', so
[Python](https://en.wikipedia.org/wiki/Python_(language)) reached TTS as
'Python)'. Allow one level of balanced parentheses in the destination, as
CommonMark does, in both the strip patterns and the pending-link check.
@ANDROIDHASSAN
ANDROIDHASSAN requested a review from a team as a code owner October 25, 2026 10:08
@chatgpt-codex-connector

Copy link
Copy Markdown

Codex Review Summary

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
📝 Code Review 🔄 Running since 2026-10-25T10:08:44.073606Z 64e74ff PR opened
ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

devin-ai-integration[bot]

This comment was marked as resolved.

The balanced-paren destination read \( as opening a group, so [guide](a\(b) was no longer stripped and the pending check held it to the end of the stream. Match \. as one url char, as CommonMark does.
…arens

# Conflicts:
#	tests/test_transcription_filter.py

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant