AI: a dead Assistants API must not disable the whole AI cog
CI / compile (pull_request) Successful in 8s
CI / unit (pull_request) Successful in 29s
CI / integration (pull_request) Successful in 39s
build / build (push) Successful in 4m29s
CI / compile (push) Successful in 5s
CI / unit (push) Successful in 22s
CI / integration (push) Successful in 27s

Field report from both instances: "Command modele_ai is not found", and on
restart the extension fails outright:

  ai_commands.py:129 in cog_load
    thread = await OPENAICLIENT.beta.threads.create()
  openai.NotFoundError: Error code: 404
  -> ExtensionFailed: Extension 'ai_commands' raised an error

The personal-assistants bootstrap calls the OpenAI Assistants API (beta
threads/runs), a legacy surface that now answers 404. That exception
propagated out of cog_load, so discord.py failed the whole extension - and
with it EVERY AI command: $gadaj_teraz, $modele_ai and the conversation
handler. The bot kept running (bot.py loads each extension defensively), it
simply had no AI at all.

cog_load already had the right instinct - it skips the bootstrap cleanly
when OPENAICLIENT is None, so a Claude-only deployment works - but it
guarded against the client being ABSENT, not against the call FAILING.

Move the bootstrap into _start_personal_assistants() and treat any failure
there as non-fatal: log what was lost and carry on. Personal assistants are
one optional feature; the rest of the cog works fine on Claude and Ollama
and must not go down with them.

Not unit-tested on purpose: exercising cog_load needs stubs for openai,
tiktoken and a tasks.loop complete enough to answer is_running(), at which
point the test exercises the stubs rather than the code. Verified against
the running cluster instead.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit was merged in pull request #27.
This commit is contained in:
2026-08-27 16:12:03 +02:00
parent fdc1fa1817
commit 9b6666dc9c
+19
View File
@@ -114,6 +114,25 @@ class Events(commands.Cog):
"OPENAICLIENT niedostępny - osobiści asystenci (OpenAI Assistants API) wyłączeni" "OPENAICLIENT niedostępny - osobiści asystenci (OpenAI Assistants API) wyłączeni"
) )
return return
# The bootstrap below must NEVER take the cog down with it. It calls the
# OpenAI Assistants API (beta threads/runs), which is a legacy surface -
# it now answers 404, and that exception propagated out of cog_load,
# failed the whole extension, and took EVERY AI command with it
# ($gadaj_teraz, $modele_ai, the conversation handler). Personal
# assistants are one optional feature; losing them must not disable the
# AI cog, which otherwise works fine on Claude and Ollama.
try:
await self._start_personal_assistants()
except Exception as exc: # pylint: disable=broad-exception-caught
self.logger.warning(
"Osobiści asystenci (OpenAI Assistants API) wyłączeni - %s: %s. "
"Reszta AI (rozmowy, $gadaj_teraz, $modele_ai) działa normalnie.",
type(exc).__name__, exc,
)
async def _start_personal_assistants(self):
"""Bootstrap the per-user OpenAI Assistants threads. Optional feature:
callers must treat a failure here as non-fatal (see cog_load)."""
for superfryta_id, superfryta in SPECJALNE_ZIEMNIACZKI.items(): for superfryta_id, superfryta in SPECJALNE_ZIEMNIACZKI.items():
if superfryta[4] != "": if superfryta[4] != "":