@@ -8,15 +8,15 @@ import { formatOutput, detectOutputFormat } from '../../output/formatter';
88import type { Config } from '../../config/schema' ;
99import type { GlobalFlags } from '../../types/flags' ;
1010import type { ImageRequest , ImageResponse } from '../../types/api' ;
11- import { mkdirSync , existsSync , readFileSync } from 'fs' ;
11+ import { mkdirSync , existsSync , readFileSync , writeFileSync } from 'fs' ;
1212import { join , resolve , extname } from 'path' ;
13+ import { isInteractive } from '../../utils/env' ;
14+ import { promptText , failIfMissing } from '../../utils/prompt' ;
1315
1416const MIME_TYPES : Record < string , string > = {
1517 '.jpg' : 'image/jpeg' , '.jpeg' : 'image/jpeg' ,
1618 '.png' : 'image/png' , '.webp' : 'image/webp' ,
1719} ;
18- import { isInteractive } from '../../utils/env' ;
19- import { promptText , failIfMissing } from '../../utils/prompt' ;
2020
2121export default defineCommand ( {
2222 name : 'image generate' ,
@@ -33,6 +33,7 @@ export default defineCommand({
3333 { flag : '--prompt-optimizer' , description : 'Automatically optimize the prompt before generation for better results.' } ,
3434 { flag : '--aigc-watermark' , description : 'Embed AI-generated content watermark in the output image.' } ,
3535 { flag : '--subject-ref <params>' , description : 'Subject reference for character consistency. Format: type=character,image=path-or-url' } ,
36+ { flag : '--response-format <format>' , description : 'Response format: url (download), base64 (embed). Default: url' } ,
3637 { flag : '--out-dir <dir>' , description : 'Download images to directory' } ,
3738 { flag : '--out-prefix <prefix>' , description : 'Filename prefix (default: image)' } ,
3839 ] ,
@@ -46,6 +47,8 @@ export default defineCommand({
4647 'mmx image generate --prompt "Wide landscape" --width 1920 --height 1080' ,
4748 '# Optimized prompt with watermark' ,
4849 'mmx image generate --prompt "sunset" --prompt-optimizer --aigc-watermark' ,
50+ '# Base64 response (bypasses CDN, useful when image URLs are unreachable)' ,
51+ 'mmx image generate --prompt "A cat" --response-format base64' ,
4952 ] ,
5053 async run ( config : Config , flags : GlobalFlags ) {
5154 let prompt = ( flags . prompt ?? ( flags . _positional as string [ ] | undefined ) ?. [ 0 ] ) as string | undefined ;
@@ -88,6 +91,8 @@ export default defineCommand({
8891 validateSize ( 'height' , height ) ;
8992 }
9093
94+ const responseFormat = ( flags . responseFormat as 'url' | 'base64' | undefined ) || 'url' ;
95+
9196 const body : ImageRequest = {
9297 model : 'image-01' ,
9398 prompt,
@@ -98,6 +103,7 @@ export default defineCommand({
98103 height : height ,
99104 prompt_optimizer : flags . promptOptimizer === true || undefined ,
100105 aigc_watermark : flags . aigcWatermark === true || undefined ,
106+ response_format : responseFormat ,
101107 } ;
102108
103109 if ( flags . subjectRef ) {
@@ -143,8 +149,6 @@ export default defineCommand({
143149 body,
144150 } ) ;
145151
146- const imageUrls = response . data . image_urls || [ ] ;
147-
148152 if ( ! config . quiet ) {
149153 process . stderr . write ( '[Model: image-01]\n' ) ;
150154 }
@@ -155,17 +159,28 @@ export default defineCommand({
155159 const prefix = ( flags . outPrefix as string ) || 'image' ;
156160 const saved : string [ ] = [ ] ;
157161
158- for ( let i = 0 ; i < imageUrls . length ; i ++ ) {
159- const filename = `${ prefix } _${ String ( i + 1 ) . padStart ( 3 , '0' ) } .jpg` ;
160- const destPath = join ( outDir , filename ) ;
161-
162- // Warn if overwriting existing file (but don't block)
163- if ( existsSync ( destPath ) ) {
164- process . stderr . write ( `Warning: overwriting existing file: ${ destPath } \n` ) ;
162+ if ( responseFormat === 'base64' ) {
163+ const images = response . data . image_base64 || [ ] ;
164+ for ( let i = 0 ; i < images . length ; i ++ ) {
165+ const filename = `${ prefix } _${ String ( i + 1 ) . padStart ( 3 , '0' ) } .jpg` ;
166+ const destPath = join ( outDir , filename ) ;
167+ if ( existsSync ( destPath ) ) {
168+ process . stderr . write ( `Warning: overwriting existing file: ${ destPath } \n` ) ;
169+ }
170+ writeFileSync ( destPath , images [ i ] ! , 'base64' ) ;
171+ saved . push ( destPath ) ;
172+ }
173+ } else {
174+ const imageUrls = response . data . image_urls || [ ] ;
175+ for ( let i = 0 ; i < imageUrls . length ; i ++ ) {
176+ const filename = `${ prefix } _${ String ( i + 1 ) . padStart ( 3 , '0' ) } .jpg` ;
177+ const destPath = join ( outDir , filename ) ;
178+ if ( existsSync ( destPath ) ) {
179+ process . stderr . write ( `Warning: overwriting existing file: ${ destPath } \n` ) ;
180+ }
181+ await downloadFile ( imageUrls [ i ] ! , destPath , { quiet : config . quiet } ) ;
182+ saved . push ( destPath ) ;
165183 }
166-
167- await downloadFile ( imageUrls [ i ] ! , destPath , { quiet : config . quiet } ) ;
168- saved . push ( destPath ) ;
169184 }
170185
171186 // --output json is respected even in --quiet mode (JSON is the actual output, not progress)
0 commit comments