hangman: add retry + log validation failures for word generation
Lint / Shell (shellcheck) (push) Successful in 9s
Lint / JS (eslint) (push) Successful in 7s
Lint / Python (ruff) (push) Successful in 5s
Lint / Python deps (pip-audit) (push) Failing after 42s
Lint / Secret scan (gitleaks) (push) Successful in 7s

Silent failures (word too long/short, has hyphens, empty hint) are now
logged as warnings showing the actual word/hint returned. Retry up to
2 times before giving up, matching riddle's behavior.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-04-26 15:19:58 -04:00
parent 0a486c2176
commit 6eb435010d
+33 -31
View File
@@ -1390,37 +1390,39 @@ async def _generate_hangman_word() -> dict | None:
'Format: {"word": "example", "hint": "short category or hint"}' 'Format: {"word": "example", "hint": "short category or hint"}'
) )
user_msg = "Pick a common English word between 5 and 8 letters (lowercase letters only, no hyphens or spaces) and give a short hint." user_msg = "Pick a common English word between 5 and 8 letters (lowercase letters only, no hyphens or spaces) and give a short hint."
try: for attempt in range(2):
timeout = aiohttp.ClientTimeout(total=60) try:
async with aiohttp.ClientSession(timeout=timeout) as session: timeout = aiohttp.ClientTimeout(total=60)
async with session.post( async with aiohttp.ClientSession(timeout=timeout) as session:
f"{OLLAMA_URL}/api/chat", async with session.post(
json={ f"{OLLAMA_URL}/api/chat",
"model": ASK_MODEL, json={
"stream": False, "model": ASK_MODEL,
"messages": [ "stream": False,
{"role": "system", "content": system_msg}, "messages": [
{"role": "user", "content": user_msg}, {"role": "system", "content": system_msg},
], {"role": "user", "content": user_msg},
}, ],
) as response: },
data = await response.json() ) as response:
text = data.get("message", {}).get("content", "").strip() data = await response.json()
if "```" in text: text = data.get("message", {}).get("content", "").strip()
text = re.sub(r"```[a-z]*\n?", "", text).strip() if "```" in text:
m = re.search(r"\{[^{}]+\}", text, re.DOTALL) text = re.sub(r"```[a-z]*\n?", "", text).strip()
candidate = m.group(0) if m else text m = re.search(r"\{[^{}]+\}", text, re.DOTALL)
try: candidate = m.group(0) if m else text
parsed = json.loads(candidate) try:
except json.JSONDecodeError: parsed = json.loads(candidate)
logger.warning("hangman: JSON parse failed, raw: %.200s", text) except json.JSONDecodeError:
parsed = {} logger.warning("hangman: JSON parse failed (attempt %d), raw: %.200s", attempt + 1, text)
word = parsed.get("word", "").lower().strip() parsed = {}
hint = parsed.get("hint", "").strip() word = parsed.get("word", "").lower().strip()
if word.isalpha() and 5 <= len(word) <= 8 and hint: hint = parsed.get("hint", "").strip()
return {"word": word, "hint": hint} if word.isalpha() and 5 <= len(word) <= 8 and hint:
except Exception as e: return {"word": word, "hint": hint}
logger.error(f"hangman word generation error: {e}", exc_info=True) logger.warning("hangman: validation failed (attempt %d): word=%r hint=%r", attempt + 1, word, hint)
except Exception as e:
logger.error(f"hangman word generation error (attempt {attempt + 1}): {e}", exc_info=True)
return None return None