Skip to content

feat(ai): add MiniMax image generation - #59929

Merged
rekram1-node merged 3 commits into
devfrom
minimax-images
Oct 28, 2026
Merged

rekram1-node merged 3 commits into
devfrom
minimax-images

Conversation

@rekram1-node

@rekram1-node rekram1-node commented Oct 28, 2026 •

Copy link
Copy Markdown
Contributor

I added an image route for MiniMax, so image-01 and image-01-live can be used through @opencode/ai. Before this the MiniMax provider only had chat, messages and responses.

Change

 providers/minimax.ts
   configure()
     messages / chat / responses
+    image(modelID)        -> protocols/minimax-images.ts
+providers/minimax/images.ts   # `model` entrypoint for models.dev
 core/src/provider.ts
+  "@opencode/ai/providers/minimax/images"

It posts to POST {baseURL}/image_generation (default https://api.minimax.io/v1; baseURL: "https://api.minimax.cn/v1" for the China platform) with Bearer auth from MINIMAX_API_KEY.

How the shared fields map:

aspect + resolution
  preset aspect (1:1 16:9 4:3 3:2 2:3 3:4 9:16 21:9) and no resolution or 1K
    -> aspect_ratio
  else if image-01
    -> width/height via ImageSizing.exact (512-2048, steps of 8), closest-size error if it can't fit
  else (image-01-live takes no width/height, and no 21:9 preset)
    -> closest-size error naming the nearest preset
n        -> n (1-9)
images   -> subject_reference [{ type: "character", image_file }] (one image, URL or data URL)

It asks for response_format: "base64" by default so the bytes come back inline. responseFormat: "url" still works if you want the 24h links. promptOptimizer, seed and any other native field pass through. Native aspect_ratio/width/height together with shared aspect/resolution fails, same as OpenAI's size. MiniMax returns errors as HTTP 200 with base_resp.status_code. Those now map to typed errors: 1002 rate limit, 1004/2049 auth, 1008 quota, 1026 content policy, 2013 invalid request.

Out of scope

models.dev doesn't list any MiniMax image models yet, so opencode won't offer them until it does. The catalog needs image-01 / image-01-live with type: "image" under minimax / minimax-cn, with an API entry whose opencode package is @opencode/ai/providers/minimax/images. I opened that as anomalyco/models.dev#11860.

Verification

  • bun typecheck and bun run typecheck:tsc in packages/ai, bun typecheck in packages/core
  • bun run test in packages/ai: 1955 pass, 0 fail. That includes new unit tests for request building, sizing, the closest-size errors and status code mapping
  • New recorded cassettes (RECORD=true, about $0.01): text to image at 512x512 and a subject reference generation. The returned dimensions are asserted
  • Live checks: an invalid width came back as InvalidRequest (2013) and a bad key as Authentication (1004). image-01-live rejects width/height and aspect_ratio: "21:9", which is why it only gets the other presets
  • bun run script/test.ts test/provider.test.ts test/aisdk-native.test.ts test/variant.test.ts in packages/core

Visual

<svg xmlns="http://www.w3.org/2000/svg" width="240" height="72" viewBox="0 0 240 72" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
  <rect x="48" y="12" width="64" height="36" rx="4" opacity="0.9">
    <animate attributeName="width" values="64;48;27;64" keyTimes="0;0.33;0.66;1" dur="4.5s" repeatCount="indefinite"/>
    <animate attributeName="height" values="36;48;48;36" keyTimes="0;0.33;0.66;1" dur="4.5s" repeatCount="indefinite"/>
    <animate attributeName="x" values="48;56;66.5;48" keyTimes="0;0.33;0.66;1" dur="4.5s" repeatCount="indefinite"/>
    <animate attributeName="y" values="12;6;6;12" keyTimes="0;0.33;0.66;1" dur="4.5s" repeatCount="indefinite"/>
  </rect>
  <circle cx="80" cy="26" r="4" opacity="0.6"/>
  <path d="M60 44 L72 32 L80 40 L86 35 L100 44" opacity="0.6"/>
  <g font-family="ui-monospace, monospace" font-size="10" fill="currentColor" stroke="none">
    <text x="136" y="24" opacity="0.5">image-01</text>
    <text x="136" y="42" opacity="0.9">16:9
      <animate attributeName="opacity" values="0.9;0;0;0.9" keyTimes="0;0.3;0.97;1" dur="4.5s" repeatCount="indefinite"/>
    </text>
    <text x="136" y="42" opacity="0">1:1
      <animate attributeName="opacity" values="0;0;0.9;0;0" keyTimes="0;0.3;0.33;0.63;1" dur="4.5s" repeatCount="indefinite"/>
    </text>
    <text x="136" y="42" opacity="0">9:16
      <animate attributeName="opacity" values="0;0;0.9;0;0" keyTimes="0;0.63;0.66;0.97;1" dur="4.5s" repeatCount="indefinite"/>
    </text>
  </g>
</svg>

Added by the opencode bot (AI-generated).

Public API: adds MiniMax image generation (MiniMax.image, imageModel, the @opencode/ai/providers/minimax/images export); backwards compatible

@opencodejr opencodejr Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Looks sound. I ran the new MiniMax image tests, the recorded cassettes, the export and entrypoint tests and the existing MiniMax tests (all pass), plus typecheck:tsc in packages/ai and packages/core. I also drove the minimax/images entrypoint against a local mock server: image-01-live sent the expected aspect_ratio/response_format/seed body with Bearer auth to {baseURL}/image_generation, and 16:9 at 2K failed with the closest-preset error. The structure matches the Alibaba and Z.ai image providers. No concerns.

Public API, all backwards compatible:

  • adds MiniMax.configure().image(modelID, providerOptions?) and MiniMax.image
  • adds MiniMax.imageModel and the MiniMaxImageOptions type
  • adds the @opencode/ai/providers/minimax/images package export, also registered as a built-in in core
  • MiniMax.model only got an internal refactor; its signature and behaviour are unchanged.

@opencodejr opencodejr Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

The new commit looks good, and my earlier review left nothing open. The China host (api.minimax.cn/v1) now matches the minimax-cn base URLs in the models.dev snapshot. Dropping 21:9 for image-01-live behaves as intended: against a local mock, a 21:9 request on image-01-live fails with a closest-size error naming 16:9, and image-01 still sends aspect_ratio: "21:9". The MiniMax image tests and typecheck:tsc in packages/ai pass. The public API is unchanged from the previous review: new MiniMax.image/imageModel and the @opencode/ai/providers/minimax/images export, all backwards compatible.

@opencodejr opencodejr Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

The new commit looks good, and my earlier reviews left nothing open. The base64 default is sent unless responseFormat (or a native response_format) overrides it. The new unit test covers this, and the recorded cassettes still pass now that they rely on the default. MiniMax image tests and typecheck:tsc in packages/ai pass. The public API is otherwise unchanged from my earlier reviews: this adds MiniMax.image/imageModel and the @opencode/ai/providers/minimax/images export, all backwards compatible. The only difference is that the new responseFormat option now defaults to base64.

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

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant