(config: Config, flags: GlobalFlags)
| 49 | 'mmx image generate --prompt "A cat" --response-format base64', |
| 50 | ], |
| 51 | async run(config: Config, flags: GlobalFlags) { |
| 52 | let prompt = (flags.prompt ?? (flags._positional as string[]|undefined)?.[0]) as string | undefined; |
| 53 | |
| 54 | prompt = await promptOrFail({ |
| 55 | value: prompt, |
| 56 | message: 'Enter your image prompt:', |
| 57 | cancelMessage: 'Image generation cancelled.', |
| 58 | flagName: 'prompt', |
| 59 | usageHint: 'mmx image generate --prompt <text>', |
| 60 | nonInteractive: config.nonInteractive, |
| 61 | }); |
| 62 | |
| 63 | // Validate width/height |
| 64 | const width = flags.width as number | undefined; |
| 65 | const height = flags.height as number | undefined; |
| 66 | |
| 67 | if (width !== undefined && height === undefined) { |
| 68 | throw new CLIError('--width requires --height. Both must be specified together.', ExitCode.USAGE); |
| 69 | } |
| 70 | if (height !== undefined && width === undefined) { |
| 71 | throw new CLIError('--height requires --width. Both must be specified together.', ExitCode.USAGE); |
| 72 | } |
| 73 | if (width !== undefined && height !== undefined) { |
| 74 | const validateSize = (name: string, val: number) => { |
| 75 | if (val < 512 || val > 2048) { |
| 76 | throw new CLIError(`--${name} must be between 512 and 2048, got ${val}.`, ExitCode.USAGE); |
| 77 | } |
| 78 | if (val % 8 !== 0) { |
| 79 | throw new CLIError(`--${name} must be a multiple of 8, got ${val}.`, ExitCode.USAGE); |
| 80 | } |
| 81 | }; |
| 82 | validateSize('width', width); |
| 83 | validateSize('height', height); |
| 84 | } |
| 85 | |
| 86 | const outPath = flags.out as string | undefined; |
| 87 | if (outPath && (flags.n as number) > 1) { |
| 88 | throw new CLIError('--out cannot be used with --n > 1. Use --out-dir instead.', ExitCode.USAGE); |
| 89 | } |
| 90 | |
| 91 | const responseFormat = (flags.responseFormat as 'url' | 'base64' | undefined) || 'url'; |
| 92 | |
| 93 | const body: ImageRequest = { |
| 94 | model: 'image-01', |
| 95 | prompt, |
| 96 | aspect_ratio: (width !== undefined && height !== undefined) ? undefined : ((flags.aspectRatio as string) || undefined), |
| 97 | n: (flags.n as number) ?? 1, |
| 98 | seed: flags.seed as number | undefined, |
| 99 | width: width, |
| 100 | height: height, |
| 101 | prompt_optimizer: flags.promptOptimizer === true || undefined, |
| 102 | aigc_watermark: flags.aigcWatermark === true || undefined, |
| 103 | response_format: responseFormat, |
| 104 | }; |
| 105 | |
| 106 | if (flags.subjectRef) { |
| 107 | const refStr = flags.subjectRef as string; |
| 108 | const params = Object.fromEntries( |
nothing calls this directly
no test coverage detected