Skip to content

Add MiniMax image generation provider (text-to-image and image-to-image) - #118

Closed
octo-patch wants to merge 1 commit into
lidge-jun:mainfrom
octo-patch:octo/20260730-text-to-image-tool-recvqgSocrkiIr
Closed

Add MiniMax image generation provider (text-to-image and image-to-image)#118
octo-patch wants to merge 1 commit into
lidge-jun:mainfrom
octo-patch:octo/20260730-text-to-image-tool-recvqgSocrkiIr

Conversation

@octo-patch

Copy link
Copy Markdown
Contributor

Reason: Add the MiniMax image-generation provider (text-to-image and image-to-image) to the direct endpoint adapter layer.

Changes

  • New lib/minimaxImageAdapter.ts calls POST /v1/image_generation with a Bearer API key.
    • Models: image-01 (text-to-image) and image-01-live (image-to-image).
    • Attached reference images are mapped to the subject_reference field (character subject, data URL).
    • --size is mapped to the closest supported aspect_ratio (1:1, 16:9, 4:3, 3:2, 2:3, 3:4, 9:16, 21:9); auto defers to the API default.
    • Both url and base64 response formats are parsed into a single base64 payload.
    • Region selects the global (https://api.minimax.io/v1) or China (https://api.minimaxi.com/v1) base URL.
    • base_resp.status_code is mapped to app error codes (auth, rate limit, balance, safety, bad request).
  • lib/providerOptions.ts resolves the minimax provider and validates the model via normalizeMinimaxImageModel (added to lib/imageModels.ts). Web search, reasoning, and size controls are disabled.
  • routes/models.ts exposes a minimax lane (image-01 / image-01-live, key-missing until configured).
  • lib/capabilities.ts, lib/agentSettings.ts, and bin/lib/modelResolver.ts register minimax in their provider/lane lists.
  • routes/keys.ts accepts MINIMAX_API_KEY (env or config) with status, validation, hot-update, and removal.
  • lib/runtimeContext.ts and server.ts load and expose minimaxApiKey.
  • config.ts/config.js add a minimaxProvider block (region, global/CN base URLs, default model, timeout).
  • The classic, multimode, node, edit, and agent generation pipelines dispatch to generateViaMinimax, including the jpeg format group, image-to-image reference handling, and a 1-subject-reference cap (MINIMAX_REF_TOO_MANY) plus MINIMAX_MASK_UNSUPPORTED.
  • routes/auth.ts redacts MINIMAX_API_KEY (and ATLASCLOUD_API_KEY) from the codex child env.
  • CLI (gen/edit/multimode/node) and docs/CLI.md list the minimax lane.
  • New tests/minimax-provider-contract.test.ts covers provider options, key-missing, text-to-image wire shape, subject_reference mapping, CN routing, ref cap, and safety/auth error mapping.
  • Updated tests/models-endpoint-contract.test.ts, tests/cli-model-resolver.test.ts, tests/cli-capabilities-contract.test.js, tests/cli-feature-parity-contract.test.js, and the runtime test inventory for the new lane.

Checks

  • tsc --noEmit -p tsconfig.json (server/lib/routes) — pass
  • tsc --noEmit -p tsconfig.bin.json (bin) — pass
  • node --test tests/minimax-provider-contract.test.ts — pass (9 tests)
  • node --test for models-endpoint, cli-model-resolver, cli-feature-parity, cli-capabilities, atlascloud, gemini-api, image-model, generation-errors, reference-limits, generate route, agent-mode-llm-planner — pass
  • node scripts/classify-tests.mjs --check (test inventory) — pass
  • secret scan of the diff — clean

Wire a direct MiniMax image-generation endpoint adapter alongside the existing
direct OpenAI Responses and Atlas Cloud paths. The adapter calls
POST /v1/image_generation with a Bearer API key, supports image-01 /
image-01-live, maps attached reference images to the subject_reference field
for image-to-image, and parses both url and base64 response formats.

Region selects the global (api.minimax.io/v1) or China (api.minimaxi.com/v1)
base URL. The minimax lane is registered through providerOptions, the model
catalog, capabilities, key management, the classic/multimode/node/edit/agent
pipelines, and the CLI lane resolver. Web search, reasoning, mask, and video
controls are ignored on this provider; image-to-image supports at most one
subject reference.

Adds minimax model validation, runtime-context key fields, env/config wiring,
a provider contract test, and updates the affected lane/provider contract
tests.
@lidge-jun

Copy link
Copy Markdown
Owner

Thanks for this — the MiniMax provider is now on dev via #120, with your commit 521ff85 cherry-picked so authorship is preserved.

I couldn't merge this branch as-is, so I fixed the blockers on top of your work rather than sending it back. What changed:

Key validation was billing the user. Sending {model, prompt} fills in the remaining fields from their defaults, so the probe was a real generation request — every key save or rotation produced an image that was then discarded. MiniMax exposes an OpenAI-compatible GET /v1/models, so validation now uses that, like every other provider here. The validation URL also follows the configured region now; it was pinned to the global host even for cn_zh.

Validation was fail-open. Only 401/1004/2049 were rejected, so a 403, 429, 500, or an unparseable body would store an invalid key. It now requires the documented list shape, and MiniMax reports errors inside 200 bodies so base_resp.status_code is checked too.

The model was being swapped silently. With a reference attached, a user's image-01 was sent as image-01-live while the stored metadata kept the original — and that value is shown in the result metadata and reused for model restore. The official docs have image-01 supporting subject_reference, so there was no reason to swap. Instead, image-01-live without a reference outside China is now rejected locally with a message saying what to do, since that combination is outside the documented range.

The web UI had no MiniMax at all. ui/src didn't mention it, so provider selection and key entry were impossible. The UI build passing wasn't evidence of the opposite — the missing unions just happened to be consistent.

Also fixed: timeouts were misclassified as network failures (AbortSignal.timeout() throws TimeoutError, not AbortError), string safety counters weren't recognised, image downloads had no size cap or content validation, and structure/01-file-function-map.md wasn't refreshed — which is what made CI fast-fail on every matrix leg.

Closing this since the work landed in #120. Appreciate the contribution.

@lidge-jun lidge-jun closed this Aug 4, 2026
dydzm pushed a commit to dydzm/ima2-gen that referenced this pull request Aug 4, 2026
MiniMax provider(lidge-jun#118)를 받기 전에 고쳐야 할 결함들이다.

키 검증이 실제로 이미지를 생성했다. `{model, prompt}`만 보내면 나머지가 기본값으로
채워져서 정상 생성 요청이 되고, 키를 저장하거나 바꿀 때마다 이미지 한 장 값이
나간다. 결과는 그대로 버려진다. MiniMax가 OpenAI 호환 `GET /v1/models`를 제공하므로
다른 provider와 같은 방식으로 바꿨다. 무효 키에 401/1004가 오는 것을 global·CN
양쪽에서 확인했다. 검증 URL도 region을 따라가게 했다 — 전에는 중국 리전 설정에서도
global 호스트를 때렸다.

판정도 뒤집었다. 예전엔 401/1004/2049만 거부해서 403·429·500이나 깨진 JSON이
오면 잘못된 키를 그냥 저장했다. 이제 문서화된 목록 형태를 확인했을 때만 통과시킨다.
MiniMax는 200 안에 오류를 담아 보내기도 해서 `base_resp.status_code`까지 본다.

reference를 붙이면 사용자가 고른 image-01을 image-01-live로 몰래 바꿔 보내면서
히스토리에는 원래 모델을 적었다. 공식 문서상 image-01도 subject_reference를
지원하니 바꿀 이유가 없다. 대신 global 리전에서 image-01-live를 참조 없이 쓰는
조합은 공식 허용 범위 밖이라 로컬에서 막고, 무엇을 하면 되는지 알려준다.

그 밖에:
- `AbortSignal.timeout()`은 TimeoutError를 던지는데 AbortError만 보고 있어서
  타임아웃이 네트워크 실패(502)로 새어 나갔다. 504로 잡는다.
- 안전 차단 카운터를 숫자로만 읽어서, 공식 응답처럼 문자열로 오면 차단을
  upstream 장애로 잘못 보고했다.
- 결과 다운로드에 크기 제한이 없었다. grok 쪽 선례대로 50MB 스트리밍 상한을 두고,
  content-type을 믿는 대신 매직 바이트로 실제 이미지인지 확인한다. 인라인 base64
  경로도 같은 검사를 거친다 — downstream이 미상 MIME을 PNG로 저장하기 때문에
  HTML 오류 페이지가 깨진 .png로 남을 수 있었다.

검증: 어댑터 계약 19건, 키 검증 route 8건 통과. 가드를 되돌리는 ablation에서
해당 케이스만 실패하는 것을 확인했다.
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.

2 participants