feat: per-call LLM timing, speaker ID, cancel captures on leave

- llm.py: log each Ollama call's caller + total/load/prompt/gen durations
  so a slow voice turn is attributable to a specific internal call
  (router/enrichment/digest/main); a RELOAD marker flags cold reloads.
- voice.ts: track in-flight Opus captures and abort them on session
  destroy(); drop any utterance that finishes after the user left, so no
  trailing post-leave VAD turns are reported.
- userbot.ts: show the speaker's Discord user ID on each transcript line
  (answered and dropped) so it's clear whose audio produced the turn.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
javis-bot
2026-06-14 00:38:26 +09:00
parent 5c11c5f7e8
commit 44ebfeafa8
4 changed files with 83 additions and 3 deletions

View File

@@ -53,6 +53,14 @@ test("formatTurnMessage reports a dropped turn with only the listening stage", (
expect(msg).not.toContain("🔊 TTS");
});
test("formatTurnMessage shows the speaker user ID when provided", () => {
const answered = formatTurnMessage({ user: "12345", transcript: "안녕", reply: "하이" });
expect(answered).toContain("👤 12345");
const dropped = formatTurnMessage({ user: "67890", transcript: "", reply: "", note: "음성 아님(VAD 차단)" });
expect(dropped).toContain("👤 67890");
expect(dropped).toContain("❌ 음성 아님(VAD 차단)");
});
test("formatTurnMessage falls back to the plain line when no timing is present", () => {
const msg = formatTurnMessage({ transcript: "안녕", reply: "하이" });
expect(msg).toBe('🎤 들음 → 🗣️ "안녕"\n🤖 답변: 하이');