Skip to content

Comments

Port mtrix DiscordClient class to mindtrace#205

Merged
vik-rant merged 26 commits intodevfrom
feature/discord-clean
Oct 29, 2025
Merged

Port mtrix DiscordClient class to mindtrace#205
vik-rant merged 26 commits intodevfrom
feature/discord-clean

Conversation

@JeremyWurbs
Copy link
Contributor

@JeremyWurbs JeremyWurbs commented Sep 29, 2025

This PR ports the old DiscordClient class from mtrix. It also updates the client to utilize slash commands.

DiscordClient Usage

First, create your own Discord server and bot, and add the bot to your server. You can find a comprehensive guide on how to do this here. The process should only take 5 minutes. Place the bot's API key in your config.ini file at [MINDTRACE_API_KEYS][DISCORD], set the associated MINDTRACE_API_KEYS__DISCORD environment variable, or directly pass the token into the following command.

To run the integration tests, also place the same (or an additional bot key) at [MINDTRACE_TESTING_API_KEYS][DISCORD].

Then test the above with the associated DiscordClient bot sample:

$ uv run mindtrace/services/samples/discord/custom_bot_client.py

If the bot successfully launches, you will get the following message:

% uv run python mindtrace/services/mindtrace/services/samples/discord/custom_bot_implementation.py
No token provided via --token.
The bot will attempt to use MINDTRACE_API_KEYS__DISCORD from Mindtrace config.
Registering slash commands...
Registered 4 slash commands
Starting Discord bot...
Syncing 4 commands...
Successfully synced 4 command(s)

In any chat or DM the bot has access to, type slash / to list the bot commands:
Screenshot 2025-09-29 at 18 03 45

If the bot has the requisite permissions, all of the example commands should work. Commands with extra inputs will display them as separate input boxes:
Screenshot 2025-09-29 at 18 05 30

Custom handlers are also supported. Refer to the example code for a custom handler for DMs:

from mindtrace.services.discord.discord_client import DiscordEventHandler

class CustomEventHandler(DiscordEventHandler):
    """Custom event handler for demonstration."""
    
    async def handle(self, event_type: DiscordEventType, **kwargs):
        """Handle Discord events with custom logic."""
        if event_type == DiscordEventType.MESSAGE:
            message = kwargs.get('message')
            if message and "hello" in message.content.lower():
                await message.channel.send("Hello there! 👋")
Screenshot 2025-09-29 at 17 59 29

DiscordService class

The above sample uses the DiscordClient class, which derives from the Mindtrace class. There is a separate DiscordService class derived from the mindtrace Service class with associated functionality. You can run the associated sample with:

$ uv run mindtrace/services/samples/discord/custom_bot_service.py

Screenshot 2025-09-30 at 11 00 01

Running the Discord bot as a Service enables using the bot's slash commands through the generated connection manager's discord_execute command:

from mindtrace.services.samples.discord.custom_bot_service import CustomDiscordService

cm = CustomDiscordService.launch()  # launches both the DiscordClient and a separate FastAPI app
result = cm.discord_execute(content="/roll 20")
print(f"Result: {result.response}")  # Result: You rolled a 12 (1-20)

Note the following arguments are always provided by Discord when calling the bot through Discord. If your slash command uses them (e.g. for some guild commands), you will have to pass them in through the the above command as well: author_id, channel_id, guild_id, message_id.

Docs & Testing

Unit tests, integration tests and samples have been provided. Run the discord test suite with

ds test: tests/unit/mindtrace/services/discord \
tests/unit/mindtrace/services/samples/discord \
tests/integration/mindtrace/services/test_discord_service_integration.py \
tests/integration/mindtrace/services/test_discord_samples_integration.py

All tests should pass.

The two samples can be run with:

$ uv run mindtrace/services/samples/discord/custom_bot_client.py
$ uv run mindtrace/services/samples/discord/custom_bot_service.py

After running either sample above, you should be able to use and communicate with the bot on the associated Discord server.

Jeremy Wurbs added 9 commits September 26, 2025 10:33
- Add BaseDiscordClient with slash command support
- Implement Discord bot with modern slash commands and legacy prefix support
- Add comprehensive unit tests for Discord service
- Add discord_bot_example.py sample implementation
- Update services pyproject.toml with discord.py dependency
- Support for event handling, command registration, and permissions
- Clean implementation without sensitive tokens in history
- Use config.get() instead of config[] to handle missing keys gracefully
- All unit tests now pass (18/18)
- Update test imports from mindtrace.services.sample to mindtrace.services.samples
- Move test_echo_service.py to correct samples directory
The Discord implementation now includes:
- Modern slash command support with auto-completion
- Backward compatibility with prefix commands
- Comprehensive unit tests
- Clean integration with Mindtrace Service patterns
- Proper configuration management via CoreConfig
@JeremyWurbs JeremyWurbs self-assigned this Sep 29, 2025
@JeremyWurbs JeremyWurbs added the mindtrace-services Issues raised from services module in mindtrace package label Sep 29, 2025
Jeremy Wurbs and others added 17 commits October 1, 2025 14:17
…asses

- Rename BaseDiscordClient to DiscordClient (extends Mindtrace)
- Create new DiscordService class (extends Service) that wraps DiscordClient
- Separate concerns: DiscordClient handles core bot logic, DiscordService provides HTTP API
- Update all imports, tests, and examples to use new class names
- Fix endpoint paths to use dot notation for ConnectionManager compatibility
- Use POST requests consistently across all endpoints for Service pattern compatibility
- Add comprehensive integration tests for DiscordService HTTP endpoints
- Create example files: custom_bot_client.py and custom_bot_service.py
- Fix NaN latency handling in bot status responses
- All integration tests now pass

Breaking changes:
- BaseDiscordClient renamed to DiscordClient
- Service-specific methods moved from DiscordClient to DiscordService
- Endpoint paths changed from slashes to dots (e.g., /discord/status -> /discord.status)
- All endpoints now use POST requests instead of mixed GET/POST

This refactoring provides better separation of concerns and allows using Discord
functionality either as a standalone Mindtrace client or as a full HTTP service.
- Add execute_command method to DiscordService for programmatic command execution
- Make DiscordCommandInput parameters optional with reasonable defaults
- Implement parameter parsing from command content strings (e.g., "/roll 20" → sides=20)
- Add Discord parameter type to Python type mapping for proper conversion
- Create minimal mock interactions without fake Discord server data
- Add warning logging for missing required parameters
- Update example script to demonstrate optional parameters and proper cleanup
- Support exposing AI models and shared logic through both Discord and HTTP interfaces

This enables the same functionality to be accessed via Discord slash commands
or HTTP API calls, perfect for AI models, shared business logic, and web UIs.
@vik-rant vik-rant merged commit 551131f into dev Oct 29, 2025
4 checks passed
@vik-rant vik-rant deleted the feature/discord-clean branch November 14, 2025 13:30
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

mindtrace-services Issues raised from services module in mindtrace package

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants