Imported from x4dr/Okysa (
AGENTS.md). Install upstream withnpx skills add x4dr/Okysa. Copyright stays with the author.
Okysa Agent Guide
This document provides essential information for agentic coding agents working in the Okysa repository.
Project Overview
Okysa (formerly NossiBot) is a Discord bot built with discord.py and Python 3.14+. It features a dice roller, reminder system, and integration with local tools and services.
Environment & Commands
Setup
The project uses uv for dependency management.
- Install dependencies:
uv syncoruv pip install -e . - Python Version: 3.14 or higher (enforced in
pyproject.toml). - Development dependencies:
pytest,pytest-asyncio,pytest-cov,pre-commit. - Local gamepack development: If you need an editable local copy of GamePack (located at
../GamePack), setUV_SOURCE_GAMEPACK='{path = "../GamePack", editable = true}'in your environment or.envfile. Without this, the git dependency from GitHub is used.
Build & Lint
- Formatting:
black .(Strict adherence to Black is required) - Linting:
flake8 - Pre-commit:
pre-commit run --all-files(Runs black, flake8, and various checks)
Testing
Tests are located in the tests/ directory and use pytest.
- Run all tests:
pytest - Run a single test file:
pytest tests/test_roll.py - Run a specific test:
pytest tests/test_base.py::test_message_prep - Run with coverage:
pytest --cov=. --cov-report=text - Async tests: All async tests should use
@pytest.mark.asyncio. - Filtering warnings: Pytest is configured to ignore certain DeprecationWarnings in
pyproject.toml.
Code Style Guidelines
Imports
Organize imports into three groups separated by a single blank line:
- Standard library imports (e.g.,
import os,import json) - Third-party library imports (e.g.,
import discord,from aiohttp import ClientSession) - Local application imports (e.g.,
from Golconda.Storage import evilsingleton)
Order & Loading:
- Imports ALWAYS come first.
- Loading
dotenvhappens after imports in the main entry point (Okysa.py). - Always use absolute imports from the project root. For example, use
from Commands.Base import invokeinstead offrom .Base import invoke.
Environment Variables
NEVER access environment variables (e.g., os.getenv, os.environ) at the module level (top-level).
- This is mandatory because
load_dotenv()runs after imports. - Modules that access environment variables at the top level will fail to see the correct values.
- Access them only within functions or class methods that are called at runtime.
Formatting
- Use Black for all Python files.
- Line length is standard (88 chars as per Black).
- Use double quotes for strings where possible, unless single quotes avoid escaping.
- Indentation is 4 spaces (standard PEP 8).
Types & Type Hinting
- Provide type hints for all function arguments and return types.
- Example:
def handle_input(data: str) -> bool: - Use
|for unions (Python 3.10+ style):discord.Client | None. - Use
list[]anddict[]instead ofList[]andDict[](Python 3.9+ style).
Naming Conventions
- Classes:
PascalCase(e.g.,RollModal,Storage) - Functions & Variables:
snake_case(e.g.,evilsingleton(),on_message) - Constants:
UPPER_SNAKE_CASE(e.g.,DEFAULT_INTENTS) - Modules:
PascalCaseorsnake_case(existing modules usePascalCaselikeGolcondaandCommands, but file names are mixed).
Error Handling
- Use specific exception types. Do not use bare
except:. - Define custom exceptions in
Golconda/RollInterface.pyor similar utility modules when needed (e.g.,AuthorError). - Use
try...exceptblocks in interaction handlers to provide user-friendly error messages via Discord.
Architecture & Patterns
Global State & Storage
- The Evil Singleton: Access the global state and storage via
Golconda.Storage.evilsingleton(). - Initialization: Storage is initialized in
Okysa.pyviaGolconda.Storage.setup(client). - Configuration: Use
evilsingleton().load_conf(user, key)andsave_conffor persistent user/guild settings. - Database: Uses SQLite for persistent storage (e.g.,
remind.db,chatlogs).
Discord Bot Patterns
- Slash Commands: Use
discord.app_commands. Commands are registered inCommands/__init__.py. - UI Components: Use
discord.ui.Viewanddiscord.ui.Modalfor interactive elements. - Events: Main event handlers are in
Okysa.py(e.g.,on_message,on_ready,on_raw_message_edit). - Routing: Message-based commands (prefixed with
?) are routed viaGolconda.Routing.main_route. - Intents:
message_contentintent is enabled.
Module Structure
Commands/: Contains modular command definitions. Each file should have aregister(tree)function.Golconda/: Core logic, storage, scheduling, and utility functions.Storage.py: Handles persistent data and theevilsingleton.Routing.py: Handles command routing for non-slash commands.Scheduling.py: Handles periodic tasks.
Data/: Static data files used by the bot.
Testing Patterns
Fixtures
- Use fixtures defined in
tests/conftest.py:mock_user: A mockeddiscord.User.mock_channel: A mockeddiscord.TextChannel.mock_message: A mockeddiscord.Message.mock_interaction: A mockeddiscord.Interaction.mock_singleton: A mockedStorageinstance.
Mocking & Async
- Use
unittest.mock.patchandAsyncMockto isolate units of work. - Example:
@pytest.mark.asyncio async def test_feature(mock_message): with patch("module.under.test.evilsingleton") as mock_evil: await function_to_test(mock_message) mock_message.reply.assert_called_once()
Development Workflow
- Analyze: Check
Okysa.pyfor event flow andGolconda/for core logic. - Implement: Add features or fixes following PEP 8 and Black.
- Test: Write a corresponding test in
tests/and ensure it passes. - Lint: Run
blackandflake8before submitting changes. - Verify: Run
pre-commit run --all-filesas a final check. - LSP & Standards: Ensure all LSP errors are resolved and code follows project standards.
- Git Operations: Only stage relevant files (
git add). DO NOT create commits or push to remote repositories. Commits and pushes are strictly for human contributors.
Key Dependencies
discord-py >= 2.4.0aiohttp == 3.10.11uvloop >= 0.21.0(used for the event loop on Linux)gamepack: A local dependency (parent directory).
Note: This file is intended for agentic consumption. Be concise, idiomatic, and respect the "evilsingleton" pattern where established.