Skip to content

feat: add MiniMax as chatbot provider integration#2480

Open
octo-patch wants to merge 1 commit intoEvolutionAPI:mainfrom
octo-patch:feature/add-minimax-provider
Open

feat: add MiniMax as chatbot provider integration#2480
octo-patch wants to merge 1 commit intoEvolutionAPI:mainfrom
octo-patch:feature/add-minimax-provider

Conversation

@octo-patch
Copy link

@octo-patch octo-patch commented Mar 20, 2026

Summary

  • Add MiniMax AI as a new chatbot provider integration, following the existing provider pattern (OpenAI, Dify, Flowise, etc.)
  • Uses MiniMax's OpenAI-compatible API (https://api.minimax.io/v1) via the OpenAI SDK
  • Supports MiniMax M2.5 and M2.5-highspeed models for chat completion
  • Includes credential management (create/list/delete API keys per instance)
  • Strips <think>...</think> tags from MiniMax M2.5 reasoning model responses
  • Manages conversation history with configurable session settings

Changes

  • 15 files changed, 1565 additions
  • New provider module: src/api/integrations/chatbot/minimax/ (controller, service, router, DTO, schema)
  • Prisma schemas: MinimaxCreds, MinimaxBot, MinimaxSetting models (both PostgreSQL and MySQL)
  • Environment config: MINIMAX_ENABLED toggle
  • Wired into server module, chatbot controller, chatbot router, and schema exports
  • 35 unit tests covering DTOs, schemas, think-tag stripping, conversation history, config defaults

Architecture

Follows the same pattern as existing chatbot providers:

  • MinimaxService extends BaseChatbotService<MinimaxBot, MinimaxSetting>
  • MinimaxController extends BaseChatbotController<MinimaxBot, MinimaxDto>
  • MinimaxRouter extends RouterBroker with full CRUD + credentials + settings + sessions endpoints
  • Prisma models mirror the OpenAI provider structure with MiniMax-specific fields

Test plan

  • All 35 unit tests pass (npx jest test/minimax.test.ts)
  • ESLint passes with no errors
  • TypeScript build succeeds (npm run build)
  • Manual testing: create MiniMax credentials, create bot, send message via WhatsApp

MiniMax API

  • Base URL: https://api.minimax.io/v1
  • Models: MiniMax-M2.5, MiniMax-M2.5-highspeed (204K context)
  • Authentication: API key via OpenAI SDK
  • MiniMax Platform

Summary by Sourcery

Add MiniMax as a new chatbot provider integration using an OpenAI-compatible API, including full CRUD endpoints, session handling, and configuration toggles.

New Features:

  • Introduce MiniMax chatbot provider with chat completion support via OpenAI-compatible API and MiniMax M2.5 models.
  • Expose MiniMax-specific REST endpoints for bots, settings, sessions, and model listing under the chatbot router.
  • Add credential management for MiniMax API keys scoped per instance, including create, list, and delete operations.

Enhancements:

  • Wire MiniMax into the existing chatbot architecture, controller orchestration, and environment configuration with a feature flag.
  • Persist MiniMax bot configuration and settings in Prisma schemas for both MySQL and PostgreSQL, mirroring other chatbot providers.
  • Handle MiniMax conversation history and reasoning output by managing session context and stripping think tags from responses.

Documentation:

  • Document MiniMax as a supported integration in the README with model and capability information.

Tests:

  • Add unit tests covering MiniMax DTOs, validation schemas, response post-processing, configuration defaults, and conversation history behavior.

Add MiniMax AI as a new chatbot provider alongside OpenAI, Dify, Flowise,
and others. MiniMax uses the OpenAI-compatible API at api.minimax.io/v1
and supports M2.5 and M2.5-highspeed models for chat completions.

Changes:
- New minimax chatbot integration (service, controller, router, DTOs, schemas)
- Prisma schema models for MinimaxCreds, MinimaxBot, MinimaxSetting (both PostgreSQL and MySQL)
- Environment configuration (MINIMAX_ENABLED)
- Registration in chatbot router, controller, and server module
- Think tag stripping for MiniMax M2.5 responses
- 35 unit and integration tests
- README documentation
@sourcery-ai
Copy link
Contributor

sourcery-ai bot commented Mar 20, 2026

Reviewer's Guide

Adds a new MiniMax chatbot provider integration wired through the existing chatbot integration architecture, including service/controller/router layers, Prisma models, configuration flag, validation schemas, DTOs, and tests for conversation handling, think-tag stripping, and credentials/settings management.

Sequence diagram for MiniMax chat message processing and think tag stripping

sequenceDiagram
  actor User
  participant WhatsAppClient as WhatsApp_instance
  participant ChatbotController
  participant MinimaxController
  participant MinimaxService
  participant PrismaRepository
  participant MiniMaxAPI as MiniMax_API

  User->>WhatsAppClient: send message content
  WhatsAppClient->>ChatbotController: inbound message event
  ChatbotController->>MinimaxController: emit(eventData)
  MinimaxController->>PrismaRepository: find minimaxBot and settings
  MinimaxController->>PrismaRepository: find integrationSession
  MinimaxController->>MinimaxService: process(instance, remoteJid, minimaxBot, session, settings, content, pushName, msg)

  alt keyword_finish_matched
    MinimaxService->>PrismaRepository: update or delete integrationSession
    MinimaxService->>MiniMaxAPI: sendTelemetry /minimax/session/finish
    MinimaxService-->>MinimaxController: return
  else new_session
    MinimaxService->>PrismaRepository: createNewSession
    MinimaxService->>MinimaxService: initNewSession(..., content)
    MinimaxService->>MiniMaxAPI: sendTelemetry /minimax/session/start
    MinimaxService-->>MinimaxController: return
  else existing_session
    MinimaxService->>PrismaRepository: ensure minimaxCreds
    MinimaxService->>MinimaxService: sendMessageToBot(...)
    MinimaxService->>PrismaRepository: load conversation history
    MinimaxService->>MiniMaxAPI: chat.completions.create(model, messages)
    MiniMaxAPI-->>MinimaxService: completion with content including <think> tags
    MinimaxService->>MinimaxService: strip <think>...</think> from content
    MinimaxService->>PrismaRepository: update conversation history in session.context
    MinimaxService-->>WhatsAppClient: sendMessageWhatsApp(cleaned_content)
    MinimaxService->>PrismaRepository: update session status opened
  end
Loading

ER diagram for MiniMax Prisma models and relations

erDiagram
  Instance {
    string id PK
    string name
  }

  MinimaxCreds {
    string id PK
    string name
    string apiKey
    string instanceId FK
  }

  MinimaxBot {
    string id PK
    boolean enabled
    string description
    string model
    json systemMessages
    json assistantMessages
    json userMessages
    int maxTokens
    string minimaxCredsId FK
    string instanceId FK
  }

  MinimaxSetting {
    string id PK
    int expire
    string keywordFinish
    int delayMessage
    string unknownMessage
    boolean listeningFromMe
    boolean stopBotFromMe
    boolean keepOpen
    int debounceTime
    json ignoreJids
    boolean splitMessages
    float timePerChar
    string minimaxCredsId FK
    string minimaxIdFallback FK
    string instanceId FK
  }

  IntegrationSession {
    string id PK
    string remoteJid
    string botId FK
    string status
    json context
  }

  Instance ||--o{ MinimaxCreds : has
  Instance ||--o{ MinimaxBot : has
  Instance ||--o{ MinimaxSetting : has

  MinimaxCreds ||--o{ MinimaxBot : used_by
  MinimaxCreds ||--o{ MinimaxSetting : used_by

  MinimaxBot ||--o{ IntegrationSession : has

  MinimaxBot ||--|| MinimaxSetting : fallback_for
  MinimaxSetting }o--|| MinimaxBot : minimaxIdFallback
Loading

Class diagram for MiniMax chatbot provider integration

classDiagram
  class BaseChatbotService {
  }

  class MinimaxService {
    - OpenAI client
    + MinimaxService(waMonitor, prismaRepository, configService)
    + process(instance, remoteJid, minimaxBot, session, settings, content, pushName, msg) void
    - initClient(apiKey) OpenAI
    - getBotType() string
    - sendMessageToBot(instance, session, settings, minimaxBot, remoteJid, pushName, content, msg) void
    - processChatCompletionMessage(instance, minimaxBot, remoteJid, content) string
  }

  class BaseChatbotController {
  }

  class MinimaxController {
    - MinimaxService minimaxService
    - PrismaRepository prismaRepository
    - WAMonitoringService waMonitor
    - Logger logger
    - boolean integrationEnabled
    - any botRepository
    - any settingsRepository
    - any sessionRepository
    - any credsRepository
    - map~string,object~ userMessageDebounce
    + MinimaxController(minimaxService, prismaRepository, waMonitor)
    + createBot(instance, data) any
    + processBot(instance, remoteJid, bot, session, settings, content, pushName, msg) void
    + createMinimaxCreds(instance, data) any
    + findMinimaxCreds(instance) any
    + deleteCreds(instance, minimaxCredsId) any
    + settings(instance, data) any
    + getModels(instance) any
    - getFallbackBotId(settings) string
    - getFallbackFieldName() string
    - getIntegrationType() string
    - getAdditionalBotData(data) map~string,any~
    - getAdditionalUpdateFields(data) map~string,any~
    - validateNoDuplicatesOnUpdate(botId, instanceId, data) void
  }

  class RouterBroker {
  }

  class MinimaxRouter {
    + MinimaxRouter(guards)
    + Router router
  }

  class MinimaxCredsDto {
    string name
    string apiKey
  }

  class BaseChatbotDto {
    boolean enabled
    string description
    string triggerType
    string triggerOperator
    string triggerValue
    integer expire
    string keywordFinish
    integer delayMessage
    string unknownMessage
    boolean listeningFromMe
    boolean stopBotFromMe
    boolean keepOpen
    integer debounceTime
    string[] ignoreJids
  }

  class MinimaxDto {
    string minimaxCredsId
    string model
    string[] systemMessages
    string[] assistantMessages
    string[] userMessages
    integer maxTokens
  }

  class BaseChatbotSettingDto {
    string minimaxCredsId
    integer expire
    string keywordFinish
    integer delayMessage
    string unknownMessage
    boolean listeningFromMe
    boolean stopBotFromMe
    boolean keepOpen
    integer debounceTime
    string[] ignoreJids
  }

  class MinimaxSettingDto {
    string minimaxCredsId
    string minimaxIdFallback
  }

  class MinimaxBot {
    string id
    boolean enabled
    string description
    string model
    any systemMessages
    any assistantMessages
    any userMessages
    integer maxTokens
    string minimaxCredsId
    string instanceId
  }

  class MinimaxSetting {
    string id
    integer expire
    string keywordFinish
    integer delayMessage
    string unknownMessage
    boolean listeningFromMe
    boolean stopBotFromMe
    boolean keepOpen
    integer debounceTime
    any ignoreJids
    boolean splitMessages
    number timePerChar
    string minimaxCredsId
    string minimaxIdFallback
    string instanceId
  }

  class MinimaxCreds {
    string id
    string name
    string apiKey
    string instanceId
  }

  BaseChatbotService <|-- MinimaxService
  BaseChatbotController <|-- MinimaxController
  RouterBroker <|-- MinimaxRouter

  MinimaxDto --|> BaseChatbotDto
  MinimaxSettingDto --|> BaseChatbotSettingDto

  MinimaxController --> MinimaxService
  MinimaxController --> MinimaxBot
  MinimaxController --> MinimaxSetting
  MinimaxController --> MinimaxCreds

  MinimaxService --> MinimaxBot
  MinimaxService --> MinimaxSetting
  MinimaxService --> MinimaxCreds
Loading

File-Level Changes

Change Details Files
Introduce MiniMax chatbot provider service built on the OpenAI SDK against MiniMax's OpenAI-compatible API, including conversation history, session lifecycle, and think-tag stripping.
  • Implement MinimaxService extending BaseChatbotService with OpenAI client initialized against https://api.minimax.io/v1
  • Load MiniMax credentials from Prisma, initialize client per instance, and handle missing creds errors
  • Implement process flow for starting, resuming, and closing sessions based on keyword finish and settings flags
  • Build chat completion request with system/assistant/user seed messages plus persisted conversation history, including WhatsApp presence updates
  • Strip ... sections from MiniMax responses and persist truncated rolling history back to IntegrationSession context
src/api/integrations/chatbot/minimax/services/minimax.service.ts
Add MiniMax chatbot controller that plugs into the base controller abstraction and manages bots, settings, and credentials with MiniMax-specific validation and defaults.
  • Extend BaseChatbotController to create MinimaxController with repositories bound to minimaxBot/minimaxSetting/minimaxCreds
  • Implement MiniMax-specific bot creation/update validation to prevent duplicate model+maxTokens per instance and ensure model is provided
  • Override settings handler to wire MiniMax credentials, fallback bot id, and default values, returning normalized fallbackId
  • Expose CRUD endpoints for MiniMax credentials with instance scoping, uniqueness checks on apiKey and name, and delete safeguards
  • Provide static getModels endpoint returning supported MiniMax M2.5 models
src/api/integrations/chatbot/minimax/controllers/minimax.controller.ts
Expose MiniMax HTTP API surface under the chatbot integration namespace with full bot, settings, sessions, status, models, and credentials endpoints.
  • Create MinimaxRouter wired to minimaxController, composing guards, validation, and DTO mapping via RouterBroker.dataValidate
  • Implement routes for creds create/list/delete, bot create/find/fetch/update/delete, settings set/fetch, status change, sessions fetch, ignoreJid, and getModels
  • Mount MinimaxRouter under /minimax within the ChatbotRouter so it is accessible via /chatbot/minimax/* paths
src/api/integrations/chatbot/minimax/routes/minimax.router.ts
src/api/integrations/chatbot/chatbot.router.ts
Define MiniMax validation schemas and DTOs aligned with the base chatbot contracts and provider-specific fields.
  • Add JSON schemas for MiniMax bot, creds, settings, status, and ignoreJid with required fields and non-empty constraints
  • Register MiniMax schemas in the global chatbot validation export so they can be referenced by validate.schema
  • Create DTOs for MinimaxCreds, Minimax bot config (extending BaseChatbotDto), and Minimax settings (extending BaseChatbotSettingDto)
src/api/integrations/chatbot/minimax/validate/minimax.schema.ts
src/api/integrations/chatbot/minimax/dto/minimax.dto.ts
src/api/integrations/chatbot/chatbot.schema.ts
Wire MiniMax into server bootstrap, environment configuration, documentation, and persistence layer.
  • Add MINIMAX type and MINIMAX key on Env plus configuration mapping from MINIMAX_ENABLED in ConfigService
  • Instantiate MinimaxService and MinimaxController in server.module and emit ChatbotController events to minimaxController
  • Document MiniMax integration and models in README and .env example
  • Introduce Prisma models (MySQL and PostgreSQL) for MinimaxCreds, MinimaxBot, and MinimaxSetting mirroring existing provider structures
src/config/env.config.ts
src/api/server.module.ts
src/api/integrations/chatbot/chatbot.controller.ts
src/api/integrations/chatbot/chatbot.router.ts
src/api/integrations/chatbot/chatbot.schema.ts
README.md
.env.example
prisma/mysql-schema.prisma
prisma/postgresql-schema.prisma
Add automated tests for MiniMax provider behavior, including DTO/schema validation, conversation/session handling, and think-tag stripping.
  • Create Jest test suite for MiniMax integration (35 tests) covering DTOs, schemas, think-tag removal behavior, config defaults, and conversation history persistence
  • Integrate tests into existing Jest setup ensuring they run with npx jest test/minimax.test.ts
test/minimax.test.ts

Tips and commands

Interacting with Sourcery

  • Trigger a new review: Comment @sourcery-ai review on the pull request.
  • Continue discussions: Reply directly to Sourcery's review comments.
  • Generate a GitHub issue from a review comment: Ask Sourcery to create an
    issue from a review comment by replying to it. You can also reply to a
    review comment with @sourcery-ai issue to create an issue from it.
  • Generate a pull request title: Write @sourcery-ai anywhere in the pull
    request title to generate a title at any time. You can also comment
    @sourcery-ai title on the pull request to (re-)generate the title at any time.
  • Generate a pull request summary: Write @sourcery-ai summary anywhere in
    the pull request body to generate a PR summary at any time exactly where you
    want it. You can also comment @sourcery-ai summary on the pull request to
    (re-)generate the summary at any time.
  • Generate reviewer's guide: Comment @sourcery-ai guide on the pull
    request to (re-)generate the reviewer's guide at any time.
  • Resolve all Sourcery comments: Comment @sourcery-ai resolve on the
    pull request to resolve all Sourcery comments. Useful if you've already
    addressed all the comments and don't want to see them anymore.
  • Dismiss all Sourcery reviews: Comment @sourcery-ai dismiss on the pull
    request to dismiss all existing Sourcery reviews. Especially useful if you
    want to start fresh with a new review - don't forget to comment
    @sourcery-ai review to trigger a new review!

Customizing Your Experience

Access your dashboard to:

  • Enable or disable review features such as the Sourcery-generated pull request
    summary, the reviewer's guide, and others.
  • Change the review language.
  • Add, remove or edit custom review instructions.
  • Adjust other review settings.

Getting Help

Copy link
Contributor

@sourcery-ai sourcery-ai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hey - I've found 3 issues, and left some high level feedback:

  • In MinimaxController.settings, the mapping between DTO fields and Prisma fields looks inconsistent (minimaxIdFallback is assigned from data.fallbackId and you return fallbackId while the DTO/schema expose minimaxIdFallback), which likely makes the fallback bot ID impossible to set or read correctly; consider aligning the property names end-to-end (DTO, schema, settingsData, and response).
  • In MinimaxService.processChatCompletionMessage, completions.choices[0].message.content is assumed to be a string but the OpenAI SDK can return structured content; it would be safer to normalize this value (handle null and array-of-parts) before using replace and saving it into history.
  • Error handling across the new MiniMax code often assumes error has a .message (e.g., error.message || JSON.stringify(error)); to avoid runtime issues and improve observability, consider narrowing error to Error (or checking instanceof Error) before accessing .message and falling back cleanly otherwise.
Prompt for AI Agents
Please address the comments from this code review:

## Overall Comments
- In `MinimaxController.settings`, the mapping between DTO fields and Prisma fields looks inconsistent (`minimaxIdFallback` is assigned from `data.fallbackId` and you return `fallbackId` while the DTO/schema expose `minimaxIdFallback`), which likely makes the fallback bot ID impossible to set or read correctly; consider aligning the property names end-to-end (DTO, schema, settingsData, and response).
- In `MinimaxService.processChatCompletionMessage`, `completions.choices[0].message.content` is assumed to be a string but the OpenAI SDK can return structured content; it would be safer to normalize this value (handle `null` and array-of-parts) before using `replace` and saving it into history.
- Error handling across the new MiniMax code often assumes `error` has a `.message` (e.g., `error.message || JSON.stringify(error)`); to avoid runtime issues and improve observability, consider narrowing `error` to `Error` (or checking `instanceof Error`) before accessing `.message` and falling back cleanly otherwise.

## Individual Comments

### Comment 1
<location path="src/api/integrations/chatbot/minimax/services/minimax.service.ts" line_range="105-114" />
<code_context>
+      this.initClient(creds.apiKey);
+
+      // Handle keyword finish
+      const keywordFinish = settings?.keywordFinish || '';
+      const normalizedContent = content.toLowerCase().trim();
+      if (keywordFinish.length > 0 && normalizedContent === keywordFinish.toLowerCase()) {
+        if (settings?.keepOpen) {
+          await this.prismaRepository.integrationSession.update({
+            where: { id: session.id },
+            data: { status: 'closed' },
+          });
+        } else {
+          await this.prismaRepository.integrationSession.delete({
+            where: { id: session.id },
+          });
</code_context>
<issue_to_address>
**issue (bug_risk):** Guard against `session` being null/undefined when handling keyword-based session finish.

In this branch you access `session.id` before checking `!session`. On a first message (or when loading the session fails), `session` can be `undefined`, causing a runtime error. Please either return early when `!session` or move the `!session` handling before any use of `session.id`.
</issue_to_address>

### Comment 2
<location path="src/api/integrations/chatbot/minimax/controllers/minimax.controller.ts" line_range="296" />
<code_context>
+        ignoreJids: data.ignoreJids,
+        splitMessages: data.splitMessages,
+        timePerChar: data.timePerChar,
+        minimaxIdFallback: data.fallbackId,
+        MinimaxCreds: data.minimaxCredsId
+          ? {
</code_context>
<issue_to_address>
**issue (bug_risk):** Fallback ID field name in settings doesn’t match DTO/schema, so it will never be persisted.

Here you read `data.fallbackId`, but both `MinimaxSettingDto` and `minimaxSettingSchema` use `minimaxIdFallback`. As a result, the fallback ID will always persist as `undefined`. Please either read from `data.minimaxIdFallback` or rename the DTO/schema field to `fallbackId` so the value is stored correctly.
</issue_to_address>

### Comment 3
<location path="README.md" line_range="73-74" />
<code_context>
   - Integrate your Evolution API with OpenAI for AI capabilities, including audio-to-text conversion, available across all Evolution integrations.

+- [MiniMax](https://www.minimaxi.com/):
+  - Integrate your Evolution API with MiniMax AI for chat completion capabilities using MiniMax M2.5 and M2.5-highspeed models via OpenAI-compatible API.
+
 - Amazon S3 / Minio:
</code_context>
<issue_to_address>
**nitpick (typo):** Consider adding the article "an" before "OpenAI-compatible API" for grammatical correctness.

You could instead write: "…models via an OpenAI-compatible API." to fix the grammar while preserving the meaning.

```suggestion
- [MiniMax](https://www.minimaxi.com/):
  - Integrate your Evolution API with MiniMax AI for chat completion capabilities using MiniMax M2.5 and M2.5-highspeed models via an OpenAI-compatible API.
```
</issue_to_address>

Sourcery is free for open source - if you like our reviews please consider sharing them ✨
Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.

Comment on lines +105 to +114
const keywordFinish = settings?.keywordFinish || '';
const normalizedContent = content.toLowerCase().trim();
if (keywordFinish.length > 0 && normalizedContent === keywordFinish.toLowerCase()) {
if (settings?.keepOpen) {
await this.prismaRepository.integrationSession.update({
where: { id: session.id },
data: { status: 'closed' },
});
} else {
await this.prismaRepository.integrationSession.delete({
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

issue (bug_risk): Guard against session being null/undefined when handling keyword-based session finish.

In this branch you access session.id before checking !session. On a first message (or when loading the session fails), session can be undefined, causing a runtime error. Please either return early when !session or move the !session handling before any use of session.id.

ignoreJids: data.ignoreJids,
splitMessages: data.splitMessages,
timePerChar: data.timePerChar,
minimaxIdFallback: data.fallbackId,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

issue (bug_risk): Fallback ID field name in settings doesn’t match DTO/schema, so it will never be persisted.

Here you read data.fallbackId, but both MinimaxSettingDto and minimaxSettingSchema use minimaxIdFallback. As a result, the fallback ID will always persist as undefined. Please either read from data.minimaxIdFallback or rename the DTO/schema field to fallbackId so the value is stored correctly.

Comment on lines +73 to +74
- [MiniMax](https://www.minimaxi.com/):
- Integrate your Evolution API with MiniMax AI for chat completion capabilities using MiniMax M2.5 and M2.5-highspeed models via OpenAI-compatible API.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nitpick (typo): Consider adding the article "an" before "OpenAI-compatible API" for grammatical correctness.

You could instead write: "…models via an OpenAI-compatible API." to fix the grammar while preserving the meaning.

Suggested change
- [MiniMax](https://www.minimaxi.com/):
- Integrate your Evolution API with MiniMax AI for chat completion capabilities using MiniMax M2.5 and M2.5-highspeed models via OpenAI-compatible API.
- [MiniMax](https://www.minimaxi.com/):
- Integrate your Evolution API with MiniMax AI for chat completion capabilities using MiniMax M2.5 and M2.5-highspeed models via an OpenAI-compatible API.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant