Files
vibe-bot/AGENTS.md
T
2026-08-17 11:35:40 -04:00

3.4 KiB

AGENTS.md

Single Python package vibe_bot: a Discord bot (discord.py, ! prefix) with SQLite RAG chat history, Kokoro TTS, and image gen/edit via OpenAI-compatible APIs. Python 3.13, managed with uv. Everything lives in vibe_bot/.

Commands

  • Setup: uv sync --extra dev — plain uv sync already installs the dev dependency group (ruff, pyright); the dev extra adds black/debugpy/mypy
  • Run bot: uv run python -m vibe_bot.main — this logs the real bot into Discord with the token from .env; don't run it as a smoke test
  • Tests: uv run pytest vibe_bot/tests/ -v; single test: uv run pytest vibe_bot/tests/test_main.py::test_name
  • Checks: uv run ruff check vibe_bot/, uv run mypy vibe_bot/ (strict), uv run pyright vibe_bot/ (strict), uv run black --check vibe_bot/
  • Container: ./build.sh (podman). CI (.gitea/workflows/build-push.yml, Gitea) only builds/pushes the image on main/release — lint and tests are not gated; run them locally

Setup requirements

  • A repo-root .env is required even to run tests: config.py calls load_dotenv() and raises RuntimeError at import time if any required var is missing. Placeholder values suffice for the mocked suite. Never commit it.
  • PortAudio is a required system library (kokoro-tts → sounddevice). Without it, ~60 tests in test_main/test_tts error at import time. On this host: sudo dnf install portaudio (the Containerfile installs portaudio19-dev).
  • TTS needs kokoro-v1.0.onnx and voices-v1.0.bin in the repo root (baked into the container image). The bot runs without them; only !speak degrades.

Test suite gotchas

  • Baseline: everything passes except test_llama_wrapper.py::test_chat_completion_think and ::test_chat_completion_instruct. Those two are unmocked live calls to the real CHAT_ENDPOINT from .env and fail without network access to that API.
  • test_config.py hardcodes sys.path.insert(0, "/var/home/ducoterra/Projects/vibe_discord_bots") (a stale repo path). The test only passes because pytest's cwd fallback finds the package — run tests from the repo root.
  • If uv run <tool> suddenly fails with ModuleNotFoundError or "bad interpreter", the .venv shebangs are stale from a repo move: rm -rf .venv && uv sync --extra dev.

Code map

  • main.py — entrypoint. The bot is created at module import (module-level commands.Bot(...)), bot.run() only under __main__. Custom-bot "commands" (!<bot_name> ...) are matched in on_message against the database, not registered with bot.command.
  • config.py — env loading + import-time validation, voice catalog.
  • database.py — ChatDatabase (embeddings stored as float32 blobs, cosine-similarity RAG, schema auto-migrates on startup) and CustomBotManager.
  • llama_wrapper.py — thin OpenAI-compatible clients for chat / image gen / image edit / embeddings, each with its own endpoint, key, and model.
  • tools.py — get_channel_members is a no-op LangChain @tool stub used only for name/description/schema; the real implementation is get_channel_members_impl(channel), wired into the tool executor in main.py.

Style

  • All four checks (ruff, mypy strict, pyright strict, black) are declared gates and currently pass; keep new code clean under all of them.
  • ruff is a dev dependency (installed via uv add --dev) with config in pyproject.toml; it runs with the default ruleset of the locked version.