Skip to content

Add MiniMax image generation support#358

Merged
ModerRAS merged 5 commits into
masterfrom
codex/add-minimax-image-tool
May 31, 2026
Merged

Add MiniMax image generation support#358
ModerRAS merged 5 commits into
masterfrom
codex/add-minimax-image-tool

Conversation

@ModerRAS
Copy link
Copy Markdown
Owner

@ModerRAS ModerRAS commented May 31, 2026

Summary

  • Extend the built-in generate_image tool to call MiniMax /v1/image_generation for image-01 and image-01-live while keeping OpenAI-compatible image generation unchanged.
  • Add MiniMax endpoint normalization, request validation, response/error parsing, local save/send reuse, and admin/help docs for custom gateways and model selection.
  • Include MiniMax image models in the MiniMax channel model list and add tests for endpoint/request/response handling.

Validation

  • dotnet build TelegramSearchBot.sln --configuration Release --no-restore
  • dotnet test TelegramSearchBot.sln --configuration Release --no-build

Summary by CodeRabbit

  • New Features

    • MiniMax image model support (image-01, image-01-live) and selectable per-group or global default
    • Ability to set/choose/clear default image model for chats and admins; selection workflow added
    • Expanded image-generation options (aspect ratio, response format, seed, watermark, style controls) and max images increased to 9
    • API endpoint/address now configurable via LLM channel settings
  • Documentation

    • Updated user guides and README to reflect new models, commands, and configuration flows

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented May 31, 2026

Review Change Stack

Warning

Review limit reached

@ModerRAS, we couldn't start this review because you've reached your PR review rate limit.

More reviews will be available in 48 minutes and 52 seconds. Learn how PR review limits work.

Your organization has run out of usage credits. Purchase more in the billing tab.

⌛ How to resolve this issue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans include higher PR review limits than trial, open-source, and free plans. In all cases, reviews become available again over time. During sustained high-volume PR review activity, CodeRabbit may temporarily slow when the next review becomes available.

Please see our Fair Usage Limits Policy for further information.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 5f1be851-08fe-48b4-aa72-092da2bb2802

📥 Commits

Reviewing files that changed from the base of the PR and between c306998 and cb7b512.

📒 Files selected for processing (2)
  • TelegramSearchBot.Test/Service/Tools/ImageGenerationToolServiceTests.cs
  • TelegramSearchBot/Service/Tools/ImageGenerationToolService.cs
📝 Walkthrough

Walkthrough

This PR integrates MiniMax image generation (models image-01 / image-01-live), adds per-group and default image-model settings, expands the generate_image tool with MiniMax parameters and routing, implements MiniMax request/response handling and validation, updates capability discovery, adds a DB column, updates docs/help/messages, and adds tests.

Changes

MiniMax Image Generation Support

Layer / File(s) Summary
Docs, help text, and manage UI
Docs/Bot_Commands_User_Guide.md, Docs/README_MCP.md, README.md, TelegramSearchBot/Service/Manage/EditLLMConfService.cs, TelegramSearchBot/Controller/Help/HelpController.cs
Updated user/admin documentation and bot messages to describe default vs group image-model configuration, MiniMax examples (image-01 / image-01-live), and distinct MiniMax vs OpenAI-compatible endpoints and parameter notes.
DB: group settings column
TelegramSearchBot.Database/Migrations/*, TelegramSearchBot.Database/Model/Data/GroupSettings.cs
Adds nullable GroupSettings.ImageGenerationModelName via EF Core migration and updates model snapshot and entity.
Model capability detection & discovery API
TelegramSearchBot.Common/Model/AI/ModelWithCapabilities.cs, TelegramSearchBot.LLM/Interface/IModelCapabilityService.cs, TelegramSearchBot.LLM/Service/AI/LLM/ModelCapabilityService.cs, TelegramSearchBot.LLM/Service/AI/LLM/OpenAIResponsesService.cs, TelegramSearchBot.LLM/Service/AI/LLM/OpenAIService.cs, tests
Adds SupportsImageGeneration and known-name heuristic, expands capability inference to recognize image models, special-cases MiniMax enumeration, exposes GetImageGenerationModels, and adds unit tests for capability behavior.
GeneralLLMController: selection UI and Redis flow
TelegramSearchBot/Controller/AI/LLM/GeneralLLMController.cs
Injects image settings/capability services and Redis; implements admin commands for listing/selecting/clearing/viewing group image models and a Redis-backed pending-selection workflow.
ImageGeneration settings and tool contract
TelegramSearchBot/Service/Tools/ImageGenerationToolService.cs
Refactors settings to add default and per-group getters/setters/clear; expands GenerateImage tool signature with MiniMax-specific parameters and increases MaxImageCount.
Routing: MiniMax vs OpenAI and execution
TelegramSearchBot/Service/Tools/ImageGenerationToolService.cs
Branches generation flow to use MiniMax endpoint/request/response path when appropriate (with gateway normalization) or fallback to existing OpenAI-compatible path; updates error messages.
MiniMax request/response builders, extraction, and validation
TelegramSearchBot/Service/Tools/ImageGenerationToolService.cs
Implements MiniMax request body construction and validation, response success checking, image extraction from image_urls/image_base64 and nested shapes, helpers for string-array fields, and MiniMax-specific aspect/size/style normalization and validation.
Image generation MiniMax tests
TelegramSearchBot.Test/Service/Tools/ImageGenerationToolServiceTests.cs
Adds tests covering MiniMax endpoint normalization, request-body variants and validation, error mapping from MiniMax responses, and image extraction (URLs and base64 arrays), plus JSON helper assertions.

Sequence Diagram

sequenceDiagram
  participant User
  participant GeneralLLMController
  participant ModelCapabilityService
  participant ImageGenerationToolService
  participant MiniMaxGateway
  participant Storage

  User->>GeneralLLMController: "选择生图模型" / numeric reply
  GeneralLLMController->>ModelCapabilityService: GetImageGenerationModels()
  ModelCapabilityService-->>GeneralLLMController: model list
  GeneralLLMController->>ImageGenerationToolService: SetGroupModelNameAsync / GenerateImage request
  ImageGenerationToolService->>MiniMaxGateway: POST /v1/image_generation (if MiniMax)
  MiniMaxGateway-->>ImageGenerationToolService: response JSON
  ImageGenerationToolService->>Storage: SaveImageAsync (persist image)
  ImageGenerationToolService-->>GeneralLLMController: result message
  GeneralLLMController-->>User: reply with images/status
Loading

Estimated Code Review Effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Poem

A rabbit hops through image streams so bright,
MiniMax and GPT now paint by moonlight.
Models listed, defaults set, and choices queued,
Requests normalized, responses neatly viewed—
Tests cheer softly as pixels take flight. 🐇✨

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 13.92% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title 'Add MiniMax image generation support' accurately summarizes the main change: extending the generate_image tool to support MiniMax models (image-01 and image-01-live) alongside existing OpenAI-compatible image generation.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch codex/add-minimax-image-tool

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented May 31, 2026

PR Check Report

Summary

Test Results

Platform Status Details
Ubuntu Passed Tests passed, artifacts uploaded
Windows Passed Tests passed, artifacts uploaded

Code Quality

  • Code formatting check
  • Security vulnerability scan
  • Dependency analysis
  • Code coverage collection

Test Artifacts

  • Test results artifacts count: 2
  • Code coverage uploaded to Codecov

Links


This report is auto-generated by GitHub Actions

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@TelegramSearchBot/Service/Tools/ImageGenerationToolService.cs`:
- Around line 237-257: The MiniMax branch still accepts an outputFormat but
never uses it, causing downstream SaveImageAsync to misname payloads; update the
IsMiniMaxImageGeneration/RequestMiniMaxImagesAsync flow to either
propagate/outputFormat into the MiniMax request body or fail fast: when
useMiniMax is true and the provided outputFormat is not supported (e.g., not
provider-default), immediately return or throw an argument/validation error
before calling RequestMiniMaxImagesAsync; alternatively modify
RequestMiniMaxImagesAsync to accept the outputFormat parameter and ensure the
response/meta includes the actual format so SaveImageAsync uses the correct
extension (refer to IsMiniMaxImageGeneration, RequestMiniMaxImagesAsync,
BuildMiniMaxImageGenerationEndpoint, and SaveImageAsync to locate and implement
the change).
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 2f23c56c-43f6-4054-bed1-f8c9cd330fab

📥 Commits

Reviewing files that changed from the base of the PR and between e99fca7 and 925f26a.

📒 Files selected for processing (7)
  • Docs/Bot_Commands_User_Guide.md
  • Docs/README_MCP.md
  • README.md
  • TelegramSearchBot.LLM/Service/AI/LLM/OpenAIService.cs
  • TelegramSearchBot.Test/Service/Tools/ImageGenerationToolServiceTests.cs
  • TelegramSearchBot/Service/Manage/EditLLMConfService.cs
  • TelegramSearchBot/Service/Tools/ImageGenerationToolService.cs

Comment thread TelegramSearchBot/Service/Tools/ImageGenerationToolService.cs
Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (2)
TelegramSearchBot/Service/Tools/ImageGenerationToolService.cs (2)

839-840: ⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Handle data: URLs in image_base64 arrays.

The single-value base64 path already strips data:image/...;base64, prefixes, but array entries skip that normalization and will fail in Convert.FromBase64String. Reuse the same parsing here so compatible gateways can return either raw base64 or data URLs.

🩹 Proposed fix
             foreach (var base64 in GetStringArrayValues(obj, "image_base64")) {
-                yield return new ImageResponseData(base64, null, null);
+                if (TryParseImageDataUrl(base64, out _, out var contentType, out var strippedBase64)) {
+                    yield return new ImageResponseData(strippedBase64, null, contentType);
+                } else {
+                    yield return new ImageResponseData(base64, null, null);
+                }
             }
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@TelegramSearchBot/Service/Tools/ImageGenerationToolService.cs` around lines
839 - 840, The array branch yields ImageResponseData for each string from
GetStringArrayValues("image_base64") but doesn't strip leading
"data:image/...;base64," prefixes like the single-value path does, causing
Convert.FromBase64String to fail; update the loop in ImageGenerationToolService
(the block that creates new ImageResponseData(base64, ...)) to normalize each
entry by detecting and removing the "data:" URI prefix (e.g. "data:*;base64,")
before creating ImageResponseData so both raw base64 and data URLs are
supported—reuse the same parsing/normalization logic used for the single-value
image_base64 handling to ensure consistent behavior.

222-223: ⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Prefer base64 as the default MiniMax response format.

Defaulting MiniMax to url makes the bot download provider-supplied URLs server-side. With custom gateways enabled, that turns a misconfigured or compromised gateway into arbitrary outbound fetches by default. base64 is the safer default and still leaves url available when explicitly requested.

🔒 Proposed mitigation
-        private const string DefaultMiniMaxResponseFormat = "url";
+        private const string DefaultMiniMaxResponseFormat = "base64";
...
-            [BuiltInParameter("MiniMax response format: url or base64. Defaults to url. Leave empty for OpenAI-compatible models.", IsRequired = false)] string minimaxResponseFormat = DefaultMiniMaxResponseFormat,
+            [BuiltInParameter("MiniMax response format: base64 or url. Defaults to base64. Leave empty for OpenAI-compatible models.", IsRequired = false)] string minimaxResponseFormat = DefaultMiniMaxResponseFormat,

Also applies to: 269-270, 299-301

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@TelegramSearchBot/Service/Tools/ImageGenerationToolService.cs` around lines
222 - 223, Change the default MiniMax response format from "url" to the safer
"base64" by updating the DefaultMiniMaxResponseFormat constant in
ImageGenerationToolService (replace "url" with "base64") and update any other
places in this file that set or assume the default MiniMax response format (the
other occurrences referenced in your review) so they use "base64" by default
while leaving "url" available when explicitly requested; ensure any code that
parses or validates the format still accepts both "base64" and "url".
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@TelegramSearchBot/Controller/AI/LLM/GeneralLLMController.cs`:
- Around line 346-370: LoadImageGenerationModelOptionsAsync currently collapses
entries by ModelName and only presents a channel summary, and
SaveImageGenerationModelSelectionAsync persists only the ModelName — change the
option to carry a unique identifier per channel (e.g., composite key like
"{ModelName}#{LLMChannel.Id}/{Provider}" or a separate ChannelId field) by
updating ImageGenerationModelSelectionOption to include that identifier, adjust
LoadImageGenerationModelOptionsAsync to emit one option per unique
channel-identifier (or include the identifier alongside the displayed summary),
and change SaveImageGenerationModelSelectionAsync to persist the identifier(s)
(using GetImageGenerationModelSelectionKey for the key) instead of only
modelName so downstream routing can unambiguously select the correct
gateway/provider; keep the same 50-item and 10-minute limits while ensuring any
UI-facing label remains the human-readable ModelName/channel summary.

---

Outside diff comments:
In `@TelegramSearchBot/Service/Tools/ImageGenerationToolService.cs`:
- Around line 839-840: The array branch yields ImageResponseData for each string
from GetStringArrayValues("image_base64") but doesn't strip leading
"data:image/...;base64," prefixes like the single-value path does, causing
Convert.FromBase64String to fail; update the loop in ImageGenerationToolService
(the block that creates new ImageResponseData(base64, ...)) to normalize each
entry by detecting and removing the "data:" URI prefix (e.g. "data:*;base64,")
before creating ImageResponseData so both raw base64 and data URLs are
supported—reuse the same parsing/normalization logic used for the single-value
image_base64 handling to ensure consistent behavior.
- Around line 222-223: Change the default MiniMax response format from "url" to
the safer "base64" by updating the DefaultMiniMaxResponseFormat constant in
ImageGenerationToolService (replace "url" with "base64") and update any other
places in this file that set or assume the default MiniMax response format (the
other occurrences referenced in your review) so they use "base64" by default
while leaving "url" available when explicitly requested; ensure any code that
parses or validates the format still accepts both "base64" and "url".
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 00efefd4-5322-43b1-b60d-c4327f6ddecd

📥 Commits

Reviewing files that changed from the base of the PR and between 925f26a and c306998.

📒 Files selected for processing (19)
  • Docs/Bot_Commands_User_Guide.md
  • Docs/README_MCP.md
  • README.md
  • TelegramSearchBot.Common/Model/AI/ModelWithCapabilities.cs
  • TelegramSearchBot.Database/Migrations/20260531041305_AddGroupImageGenerationModel.Designer.cs
  • TelegramSearchBot.Database/Migrations/20260531041305_AddGroupImageGenerationModel.cs
  • TelegramSearchBot.Database/Migrations/DataDbContextModelSnapshot.cs
  • TelegramSearchBot.Database/Model/Data/GroupSettings.cs
  • TelegramSearchBot.LLM.Test/Service/AI/LLM/ModelCapabilityServiceTests.cs
  • TelegramSearchBot.LLM.Test/Service/AI/LLM/ModelWithCapabilitiesTests.cs
  • TelegramSearchBot.LLM/Interface/IModelCapabilityService.cs
  • TelegramSearchBot.LLM/Service/AI/LLM/ModelCapabilityService.cs
  • TelegramSearchBot.LLM/Service/AI/LLM/OpenAIResponsesService.cs
  • TelegramSearchBot.LLM/Service/AI/LLM/OpenAIService.cs
  • TelegramSearchBot.Test/Service/Tools/ImageGenerationToolServiceTests.cs
  • TelegramSearchBot/Controller/AI/LLM/GeneralLLMController.cs
  • TelegramSearchBot/Controller/Help/HelpController.cs
  • TelegramSearchBot/Service/Manage/EditLLMConfService.cs
  • TelegramSearchBot/Service/Tools/ImageGenerationToolService.cs
✅ Files skipped from review due to trivial changes (6)
  • TelegramSearchBot.Database/Migrations/20260531041305_AddGroupImageGenerationModel.cs
  • TelegramSearchBot.Database/Migrations/DataDbContextModelSnapshot.cs
  • TelegramSearchBot.Database/Migrations/20260531041305_AddGroupImageGenerationModel.Designer.cs
  • README.md
  • Docs/README_MCP.md
  • Docs/Bot_Commands_User_Guide.md
🚧 Files skipped from review as they are similar to previous changes (1)
  • TelegramSearchBot.Test/Service/Tools/ImageGenerationToolServiceTests.cs

Comment on lines +346 to +370
private async Task<List<ImageGenerationModelSelectionOption>> LoadImageGenerationModelOptionsAsync() {
var models = await _modelCapabilityService.GetImageGenerationModels();
return models
.Where(x => !string.IsNullOrWhiteSpace(x.ModelName) && x.LLMChannel != null)
.GroupBy(x => x.ModelName.Trim(), StringComparer.OrdinalIgnoreCase)
.Select(group => {
var channels = group
.Select(x => $"{x.LLMChannel.Name}#{x.LLMChannel.Id}/{x.LLMChannel.Provider}")
.Distinct(StringComparer.OrdinalIgnoreCase)
.OrderBy(x => x)
.ToList();
var channelSummary = channels.Count <= 3
? string.Join(", ", channels)
: $"{string.Join(", ", channels.Take(3))} 等 {channels.Count} 个渠道";
return new ImageGenerationModelSelectionOption(group.Key, channelSummary);
})
.OrderBy(x => x.ModelName, StringComparer.OrdinalIgnoreCase)
.ToList();
}

private async Task SaveImageGenerationModelSelectionAsync(long chatId, long userId, List<ImageGenerationModelSelectionOption> options) {
var db = _connectionMultiplexer.GetDatabase();
var key = GetImageGenerationModelSelectionKey(chatId, userId);
var modelNames = options.Take(50).Select(x => x.ModelName);
await db.StringSetAsync(key, string.Join('\n', modelNames), TimeSpan.FromMinutes(10));
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major | 🏗️ Heavy lift

Persist the selected channel, not just the model name.

LoadImageGenerationModelOptionsAsync() merges every duplicate into one option keyed only by ModelName, and SaveImageGenerationModelSelectionAsync() stores only that name. If the same model exists on multiple channels, the admin cannot actually choose which gateway/provider backs the setting even though the UI shows per-channel summaries. Store a channel identifier (or another unique composite key) through the pending-selection flow and group settings so downstream routing is unambiguous.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@TelegramSearchBot/Controller/AI/LLM/GeneralLLMController.cs` around lines 346
- 370, LoadImageGenerationModelOptionsAsync currently collapses entries by
ModelName and only presents a channel summary, and
SaveImageGenerationModelSelectionAsync persists only the ModelName — change the
option to carry a unique identifier per channel (e.g., composite key like
"{ModelName}#{LLMChannel.Id}/{Provider}" or a separate ChannelId field) by
updating ImageGenerationModelSelectionOption to include that identifier, adjust
LoadImageGenerationModelOptionsAsync to emit one option per unique
channel-identifier (or include the identifier alongside the displayed summary),
and change SaveImageGenerationModelSelectionAsync to persist the identifier(s)
(using GetImageGenerationModelSelectionKey for the key) instead of only
modelName so downstream routing can unambiguously select the correct
gateway/provider; keep the same 50-item and 10-minute limits while ensuring any
UI-facing label remains the human-readable ModelName/channel summary.

@ModerRAS
Copy link
Copy Markdown
Owner Author

Addressed the MiniMax response-format review items in cb7b512: MiniMax now defaults to base64 and image_base64 array entries can include data URLs. I am intentionally keeping image model selection scoped to model name only: this matches the existing group LLM model setting behavior, while concrete channel/API key/gateway selection remains in the existing ChannelsWithModel routing by channel priority/concurrency. Binding a group setting to a channel id would introduce a second routing model.

@ModerRAS ModerRAS merged commit b853a2e into master May 31, 2026
5 checks passed
@ModerRAS ModerRAS deleted the codex/add-minimax-image-tool branch May 31, 2026 10:08
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