"""TTS input normalisation. Claude speaks in markdown/backticks; MeloTTS's Korean normaliser crashes on a bare backtick (``KeyError: '`'``), which used to take down the whole voice turn. normalize_for_speech() must strip formatting and above all guarantee no backtick reaches the synthesiser.""" from wsai.backends.melo import normalize_for_speech def test_backticks_are_always_removed(): # The exact crash trigger: inline code, a fenced block, and a stray backtick. reply = "`ls -la` 를 써봐. 예시:\n```python\nprint('hi')\n```\n그리고 ` 이건 홀로 남은 백틱" out = normalize_for_speech(reply) assert "`" not in out # the character that crashes MeloTTS is gone assert "ls -la" in out # inner words are kept, just unwrapped assert "print('hi')" in out # fenced code content survives as spoken text def test_markdown_structure_flattened(): reply = "# 제목\n- 첫째 항목\n- 둘째 항목\n**굵게** 그리고 _기울임_\n> 인용문" out = normalize_for_speech(reply) assert "#" not in out assert "**" not in out and "_" not in out assert not out.lstrip().startswith(("-", ">")) assert "첫째 항목" in out and "굵게" in out and "인용문" in out def test_links_reduced_to_label(): out = normalize_for_speech("자세히는 [문서](https://example.com/docs) 참고해") assert "문서" in out assert "http" not in out and "]" not in out and "(" not in out def test_plain_text_is_left_intact(): plain = "안녕, 지금 화면 잘 보고 있어. 뭐 도와줄까?" assert normalize_for_speech(plain) == plain def test_empty_is_safe(): assert normalize_for_speech("") == ""