Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 0 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@
"dev": "tsc --watch",
"dev:cmd": "./dev-cli.js",
"test": "jest",
"test:icon-batch": "bash scripts/test-icon-batch.sh",
"lint": "eslint src/**/*.ts",
"clean": "rm -rf dist bundle"
},
Expand Down
2 changes: 1 addition & 1 deletion src/commands/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ export default class ConfigCommand extends Command {
await this.showConfig();
}

// If no flags provided, show help
// If no flags provided, show the current configuration
if (Object.keys(flags).length === 0) {
await this.showConfig();
}
Expand Down
20 changes: 19 additions & 1 deletion src/commands/feature-graphic.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { Command, Flags } from "@oclif/core";
import { Command, Errors, Flags } from "@oclif/core";
import fs from "fs-extra";
import chalk from "chalk";
import { OpenAIService } from "../services/openai.js";
Expand Down Expand Up @@ -223,6 +223,19 @@ export default class FeatureGraphicCommand extends Command {

// Prompt-only mode
if (flags["prompt-only"]) {
// Provider-specific validation (so the preview matches generation mode).
if (provider === "banana") {
if (bananaVariant === "banana-2" && requestedN !== 1) {
this.error(chalk.red("banana-2 only supports -n 1"));
}
if (bananaVariant === "banana" && !flags.pro && requestedN !== 1) {
this.error(chalk.red("Banana normal only supports -n 1"));
}
this.resolveBananaQuality(qualityInput);
} else {
this.resolveOpenAIQuality(qualityInput);
}

const styleInput = flags.style?.trim();
const styleNormalized = styleInput?.toLowerCase();
const availableStyles = StyleTemplates.getAvailableStyles().map((s) =>
Expand Down Expand Up @@ -380,6 +393,11 @@ export default class FeatureGraphicCommand extends Command {
});
}
} catch (error) {
// Errors raised via this.error() above are already user-facing CLI
// errors; re-throw them as-is instead of double-wrapping the message.
if (error instanceof Errors.CLIError) {
throw error;
}
this.error(
chalk.red(
`Failed to generate feature graphic: ${(error as Error).message}`
Expand Down
17 changes: 13 additions & 4 deletions src/commands/icon.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { Command, Flags } from "@oclif/core";
import { Command, Errors, Flags } from "@oclif/core";
import chalk from "chalk";
import { OpenAIService } from "../services/openai.js";
import { GeminiService } from "../services/gemini.js";
Expand Down Expand Up @@ -111,13 +111,14 @@ export default class IconCommand extends Command {
// === Advanced Options ===
background: Flags.string({
char: "b",
description: "Background: transparent, opaque, auto (GPT-Image-1 only)",
description:
"Background: transparent, opaque, auto (OpenAI only; transparent not supported by gpt-image-2)",
default: "auto",
options: ["transparent", "opaque", "auto"],
}),
"output-format": Flags.string({
char: "f",
description: "Output format: png, jpeg, webp (GPT-Image-1 only)",
description: "Output format: png, jpeg, webp (OpenAI only)",
default: "png",
options: ["png", "jpeg", "webp"],
}),
Expand All @@ -133,7 +134,7 @@ export default class IconCommand extends Command {
hidden: true,
}),
moderation: Flags.string({
description: "Content filtering: low, auto (GPT-Image-1 only)",
description: "Content filtering: low, auto (OpenAI only)",
default: "auto",
options: ["low", "auto"],
}),
Expand Down Expand Up @@ -307,6 +308,9 @@ export default class IconCommand extends Command {
if (requestedN !== 1) {
this.error(chalk.red("banana-2 only supports -n 1"));
}
// Generation mode resolves banana quality for banana-2 too; run the
// same validation here so the preview matches real behavior.
this.resolveBananaQuality(qualityInput);
} else if (!flags.pro) {
if (requestedN !== 1) {
this.error(chalk.red("Banana normal only supports -n 1"));
Expand Down Expand Up @@ -507,6 +511,11 @@ export default class IconCommand extends Command {
});
}
} catch (error) {
// Errors raised via this.error() above are already user-facing CLI
// errors; re-throw them as-is instead of double-wrapping the message.
if (error instanceof Errors.CLIError) {
throw error;
}
this.error(
chalk.red(`Failed to generate icon: ${(error as Error).message}`)
);
Expand Down
5 changes: 4 additions & 1 deletion src/services/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,10 @@ export class ConfigService {

static async getConfig(): Promise<ConfigData> {
try {
await fs.ensureFile(this.configPath);
// Read-only: don't create the config file as a side effect.
if (!(await fs.pathExists(this.configPath))) {
return {};
}
const config = await fs.readJSON(this.configPath);
return config;
} catch {
Expand Down
5 changes: 1 addition & 4 deletions src/services/openai.ts
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,6 @@ export class OpenAIService {
outputFormat = "png",
numImages = 1,
moderation = "auto",
rawPrompt = false,
} = options;

// Validate model-specific parameters
Expand All @@ -60,14 +59,12 @@ export class OpenAIService {
moderation
);

const finalPrompt = rawPrompt ? prompt : prompt;

const resolvedModelId = this.resolveOpenAIImageModelId(model);

// Build request parameters based on model
const requestParams: ImageGenerateParams = {
model: resolvedModelId,
prompt: finalPrompt,
prompt,
n: numImages,
size: (options.size ?? this.FIXED_SIZE) as any,
};
Expand Down
2 changes: 2 additions & 0 deletions webpack.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,9 @@ export default {
// Keep these as external dependencies
'@oclif/core': '@oclif/core',
'@oclif/plugin-help': '@oclif/plugin-help',
'@google/genai': '@google/genai',
'openai': 'openai',
'mime': 'mime',
'fs-extra': 'fs-extra',
'chalk': 'chalk',
'sharp': 'sharp',
Expand Down