fix(voice): stop backtick TTS crash and actually count error turns
Claude replies with markdown/backticks by default; MeloTTS's Korean text
normaliser has no entry for '`' and dies with KeyError: '`', so any reply
mentioning a command/code block crashed the whole voice turn (500 on
/api/voice-turn). Fix at the shared synth() choke point with
normalize_for_speech(), which flattens code fences/inline code/links/markdown
and guarantees no backtick reaches the worker — covering both the dashboard
voice turn and the Discord speak() bridge. Also add a PERSONA line asking the
model to avoid markdown (belt-and-suspenders; the code strip is the real fix).
errors_total never moved for turn-level failures: it was only bumped by
log("error") events, and the dashboard voice path calls turn.finish(error=...)
without logging. Emit one error-level log event from Turn.finish() when a turn
ends in error, so both the server counter and the browser SSE mirror stay
consistent, guarded to count at most once. Drop the now-redundant pipeline
log("error") to avoid double counting and remove the dead _publish stub.
Verified: raw backtick -> worker KeyError '`' reproduced; after fix real
MeloTTS synth of a backtick+fenced reply succeeds; /api/voice-turn returns 200
with a wav body on a backtick reply and errors_total stays 0, and an induced
synth failure returns 500 with errors_total incrementing to exactly 1. Full
suite 18 passed.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
@@ -94,8 +94,9 @@ class Pipeline:
|
||||
async with turn.step("응답(TTS/전송)"):
|
||||
await self._emit(reply)
|
||||
except Exception as exc:
|
||||
# finish() records the error and emits the single error-level log
|
||||
# event that bumps errors_total, so don't log the same failure twice.
|
||||
turn.finish(error=f"{type(exc).__name__}: {exc}")
|
||||
self.monitor.log("error", f"대화 #{turn.id} 실패: {exc}")
|
||||
raise
|
||||
else:
|
||||
turn.finish()
|
||||
|
||||
Reference in New Issue
Block a user