clawbr 0.0.42 → 0.0.43

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -86,34 +86,37 @@ export class GenerateCommand extends CommandRunner {
86
86
  const spinner = json ? null : ora(sourceImageData ? "Generating image from source..." : "Generating image...").start();
87
87
  try {
88
88
  let imageBuffer;
89
+ let modelUsed;
89
90
  // Determine models to try
90
91
  const primaryModel = model || getPrimaryModel(aiProvider);
91
- const fallbackModels = getFallbackModels(aiProvider);
92
+ // If the user explicitly specified a model, disable fallbacks so we
93
+ // honour their choice strictly and fail fast if it doesn't work.
94
+ const fallbackModels = model ? [] : getFallbackModels(aiProvider);
92
95
  // Pass aspect ratio and image size to generation
93
96
  const imageConfig = {};
94
97
  if (aspectRatio) imageConfig.aspectRatio = aspectRatio;
95
98
  if (imageSize) imageConfig.imageSize = imageSize;
96
99
  if (aiProvider === "openrouter") {
97
- imageBuffer = await this.generateWithFallback(prompt, size, apiKey, "openrouter", {
100
+ ({ buffer: imageBuffer, modelUsed } = await this.generateWithFallback(prompt, size, apiKey, "openrouter", {
98
101
  primary: primaryModel,
99
102
  fallbacks: fallbackModels
100
- }, spinner, sourceImageData, imageConfig);
103
+ }, spinner, sourceImageData, imageConfig));
101
104
  } else if (aiProvider === "openai") {
102
105
  if (sourceImageData) {
103
106
  throw new Error("OpenAI does not support image-to-image generation. Use OpenRouter with a model that supports reference images.");
104
107
  }
105
- imageBuffer = await this.generateWithFallback(prompt, size, apiKey, "openai", {
108
+ ({ buffer: imageBuffer, modelUsed } = await this.generateWithFallback(prompt, size, apiKey, "openai", {
106
109
  primary: primaryModel,
107
110
  fallbacks: fallbackModels
108
- }, spinner);
111
+ }, spinner));
109
112
  } else if (aiProvider === "google") {
110
113
  if (sourceImageData) {
111
114
  throw new Error("Google Imagen does not support image-to-image generation. Use OpenRouter with a model that supports reference images.");
112
115
  }
113
- imageBuffer = await this.generateWithFallback(prompt, size, apiKey, "google", {
116
+ ({ buffer: imageBuffer, modelUsed } = await this.generateWithFallback(prompt, size, apiKey, "google", {
114
117
  primary: primaryModel,
115
118
  fallbacks: fallbackModels
116
- }, spinner);
119
+ }, spinner));
117
120
  } else {
118
121
  if (spinner) spinner.fail();
119
122
  throw new Error(`Unsupported AI provider: ${aiProvider}`);
@@ -135,7 +138,8 @@ export class GenerateCommand extends CommandRunner {
135
138
  prompt,
136
139
  output: outputPath,
137
140
  size,
138
- provider: aiProvider
141
+ provider: aiProvider,
142
+ modelUsed
139
143
  }, null, 2));
140
144
  } else {
141
145
  console.log("\nšŸŽØ Image Generation Complete!");
@@ -180,7 +184,10 @@ export class GenerateCommand extends CommandRunner {
180
184
  // Only show fallback message if we had to fall back
181
185
  spinner.info(`Successfully generated with fallback model: ${model}`);
182
186
  }
183
- return imageBuffer;
187
+ return {
188
+ buffer: imageBuffer,
189
+ modelUsed: model
190
+ };
184
191
  } catch (error) {
185
192
  lastError = error;
186
193
  // If this wasn't the last model, log the failure and try the next one
@@ -310,7 +317,11 @@ export class GenerateCommand extends CommandRunner {
310
317
  const imageUrl = result.choices[0].message.images[0].image_url.url;
311
318
  // If it's a URL, fetch it
312
319
  if (imageUrl.startsWith("http")) {
313
- const imgRes = await fetch(imageUrl);
320
+ const imgRes = await fetch(imageUrl, {
321
+ headers: {
322
+ "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/124.0.0.0 Safari/537.36"
323
+ }
324
+ });
314
325
  const arrayBuffer = await imgRes.arrayBuffer();
315
326
  return Buffer.from(arrayBuffer);
316
327
  }
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/commands/generate.command.ts"],"sourcesContent":["import { Command, CommandRunner, Option } from \"nest-commander\";\nimport { writeFileSync } from \"fs\";\nimport ora from \"ora\";\nimport fetch from \"node-fetch\";\nimport { resolve } from \"path\";\nimport { generateImage } from \"ai\";\nimport { createOpenAI } from \"@ai-sdk/openai\";\nimport { createGoogleGenerativeAI } from \"@ai-sdk/google\";\nimport { loadCredentials } from \"../utils/credentials.js\";\nimport { resolveImageToDataUri, validateImageInput } from \"../utils/image.js\";\nimport { requireOnboarding } from \"../utils/config.js\";\nimport {\n getProviderModels,\n getModelById,\n isValidModel,\n getPrimaryModel,\n getFallbackModels,\n supportsReferenceImage,\n formatModelList,\n} from \"../config/image-models.js\";\n\ninterface GenerateCommandOptions {\n prompt?: string;\n output?: string;\n size?: string;\n sourceImage?: string;\n model?: string;\n aspectRatio?: string;\n imageSize?: string;\n json?: boolean;\n}\n\n@Command({\n name: \"generate\",\n description: \"Generate an image using AI with smart model fallback\",\n arguments: \"\",\n options: { isDefault: false },\n})\nexport class GenerateCommand extends CommandRunner {\n async run(inputs: string[], options: GenerateCommandOptions): Promise<void> {\n await requireOnboarding();\n const {\n prompt,\n output,\n size = \"1024x1024\",\n sourceImage,\n model,\n aspectRatio,\n imageSize,\n json = false,\n } = options;\n\n // ─────────────────────────────────────────────────────────────────────\n // Validation\n // ─────────────────────────────────────────────────────────────────────\n if (!prompt) {\n throw new Error(\n '--prompt is required. Example: clawbr generate --prompt \"a robot building software\" --output \"./robot.png\"'\n );\n }\n\n if (!output) {\n throw new Error(\n '--output is required. Example: clawbr generate --prompt \"...\" --output \"./image.png\"'\n );\n }\n\n // Validate source image if provided\n if (sourceImage) {\n const validation = validateImageInput(sourceImage);\n if (!validation.valid) {\n throw new Error(validation.error);\n }\n }\n\n // Validate size\n const validSizes = [\"256x256\", \"512x512\", \"1024x1024\", \"1792x1024\", \"1024x1792\"];\n if (!validSizes.includes(size)) {\n throw new Error(`Invalid size. Must be one of: ${validSizes.join(\", \")}`);\n }\n\n // ─────────────────────────────────────────────────────────────────────\n // Load Credentials\n // ─────────────────────────────────────────────────────────────────────\n const credentials = loadCredentials();\n\n if (!credentials) {\n throw new Error(\"Credentials not found. Run 'clawbr onboard' first to set up your account.\");\n }\n\n const { aiProvider, apiKeys } = credentials;\n const apiKey = apiKeys[aiProvider as keyof typeof apiKeys];\n\n if (!apiKey) {\n throw new Error(\n `No API key found for provider '${aiProvider}'. Run 'clawbr onboard' to configure.`\n );\n }\n\n // ─────────────────────────────────────────────────────────────────────\n // Validate model if provided\n // ─────────────────────────────────────────────────────────────────────\n if (model && !isValidModel(aiProvider, model)) {\n const availableModels = formatModelList(aiProvider);\n throw new Error(\n `Invalid model '${model}' for provider '${aiProvider}'.\\n\\nAvailable models:\\n${availableModels}`\n );\n }\n\n // ─────────────────────────────────────────────────────────────────────\n // Check reference image support\n // ─────────────────────────────────────────────────────────────────────\n if (sourceImage && model && !supportsReferenceImage(aiProvider, model)) {\n const modelInfo = getModelById(aiProvider, model);\n throw new Error(\n `Model '${modelInfo?.name || model}' does not support reference images.\\n\\n` +\n `For reference image support with ${aiProvider}, use one of:\\n` +\n getProviderModels(aiProvider)\n .filter((m) => m.supportsReferenceImage)\n .map((m) => ` • ${m.id}`)\n .join(\"\\n\")\n );\n }\n\n // ─────────────────────────────────────────────────────────────────────\n // Prepare source image if provided\n // ─────────────────────────────────────────────────────────────────────\n const sourceImageData = sourceImage ? await resolveImageToDataUri(sourceImage) : undefined;\n\n // ─────────────────────────────────────────────────────────────────────\n // Generate Image with Smart Fallback\n // ─────────────────────────────────────────────────────────────────────\n const spinner = json\n ? null\n : ora(sourceImageData ? \"Generating image from source...\" : \"Generating image...\").start();\n\n try {\n let imageBuffer: Buffer;\n\n // Determine models to try\n const primaryModel = model || getPrimaryModel(aiProvider);\n const fallbackModels = getFallbackModels(aiProvider);\n\n // Pass aspect ratio and image size to generation\n const imageConfig: { aspectRatio?: string; imageSize?: string } = {};\n if (aspectRatio) imageConfig.aspectRatio = aspectRatio;\n if (imageSize) imageConfig.imageSize = imageSize;\n\n if (aiProvider === \"openrouter\") {\n imageBuffer = await this.generateWithFallback(\n prompt,\n size,\n apiKey,\n \"openrouter\",\n { primary: primaryModel, fallbacks: fallbackModels },\n spinner,\n sourceImageData,\n imageConfig\n );\n } else if (aiProvider === \"openai\") {\n if (sourceImageData) {\n throw new Error(\n \"OpenAI does not support image-to-image generation. Use OpenRouter with a model that supports reference images.\"\n );\n }\n imageBuffer = await this.generateWithFallback(\n prompt,\n size,\n apiKey,\n \"openai\",\n { primary: primaryModel, fallbacks: fallbackModels },\n spinner\n );\n } else if (aiProvider === \"google\") {\n if (sourceImageData) {\n throw new Error(\n \"Google Imagen does not support image-to-image generation. Use OpenRouter with a model that supports reference images.\"\n );\n }\n imageBuffer = await this.generateWithFallback(\n prompt,\n size,\n apiKey,\n \"google\",\n { primary: primaryModel, fallbacks: fallbackModels },\n spinner\n );\n } else {\n if (spinner) spinner.fail();\n throw new Error(`Unsupported AI provider: ${aiProvider}`);\n }\n\n // ─────────────────────────────────────────────────────────────────────\n // Save Image\n // ─────────────────────────────────────────────────────────────────────\n const outputPath = resolve(output);\n writeFileSync(outputPath, imageBuffer);\n\n if (spinner) {\n spinner.succeed(`Image generated and saved to: ${outputPath}`);\n }\n\n // ─────────────────────────────────────────────────────────────────────\n // Output\n // ─────────────────────────────────────────────────────────────────────\n if (json) {\n console.log(\n JSON.stringify(\n {\n success: true,\n prompt,\n output: outputPath,\n size,\n provider: aiProvider,\n },\n null,\n 2\n )\n );\n } else {\n console.log(\"\\nšŸŽØ Image Generation Complete!\");\n console.log(\"─────────────────────────────────────\");\n console.log(`Prompt: ${prompt}`);\n console.log(`Size: ${size}`);\n if (sourceImageData) {\n console.log(`Source Image: ${sourceImage}`);\n }\n console.log(`Output: ${outputPath}`);\n console.log(`Provider: ${aiProvider}`);\n if (model) {\n console.log(`Model: ${model}`);\n }\n console.log(\"─────────────────────────────────────\\n\");\n }\n } catch (error) {\n if (spinner && spinner.isSpinning) {\n spinner.fail(\"Image generation failed\");\n }\n throw error;\n }\n }\n\n /**\n * Generate image with smart fallback chain\n * Tries primary model first, then falls back to alternatives if it fails\n */\n private async generateWithFallback(\n prompt: string,\n size: string,\n apiKey: string,\n provider: \"openrouter\" | \"openai\" | \"google\",\n config: { primary: string | null; fallbacks: string[] },\n spinner: {\n text: string;\n info: (msg: string) => void;\n warn: (msg: string) => void;\n isSpinning?: boolean;\n } | null,\n sourceImageData?: string,\n imageConfig?: { aspectRatio?: string; imageSize?: string }\n ): Promise<Buffer> {\n const modelsToTry = [config.primary, ...config.fallbacks].filter(\n (model): model is string => model !== null\n );\n\n let lastError: Error | null = null;\n\n for (let i = 0; i < modelsToTry.length; i++) {\n const model = modelsToTry[i];\n\n try {\n if (spinner) {\n const modelName = model.split(\"/\").pop() || model;\n spinner.text = `Generating image with ${modelName}... (attempt ${i + 1}/${modelsToTry.length})`;\n }\n\n const imageBuffer = await this.generateWithModel(\n prompt,\n size,\n apiKey,\n provider,\n model,\n sourceImageData,\n imageConfig\n );\n\n if (spinner && i > 0) {\n // Only show fallback message if we had to fall back\n spinner.info(`Successfully generated with fallback model: ${model}`);\n }\n\n return imageBuffer;\n } catch (error) {\n lastError = error as Error;\n\n // If this wasn't the last model, log the failure and try the next one\n if (i < modelsToTry.length - 1) {\n if (spinner) {\n spinner.warn(`Model ${model} failed, trying fallback...`);\n } else {\n console.warn(`Model ${model} failed: ${lastError.message}`);\n }\n continue;\n }\n }\n }\n\n // If we get here, all models failed\n throw new Error(\n `All models failed to generate image. Last error: ${lastError?.message || \"Unknown error\"}`\n );\n }\n\n /**\n * get the model configuration for the AI SDK\n */\n private getImageModel(provider: string, apiKey: string, model: string) {\n if (provider === \"openai\") {\n const openai = createOpenAI({ apiKey });\n return openai.image(model);\n } else if (provider === \"google\") {\n const google = createGoogleGenerativeAI({ apiKey });\n return google.image(model);\n }\n throw new Error(`Provider ${provider} not supported via AI SDK`);\n }\n\n /**\n * Generate image using a specific model\n */\n private async generateWithModel(\n prompt: string,\n size: string,\n apiKey: string,\n provider: \"openrouter\" | \"openai\" | \"google\",\n model: string,\n sourceImageData?: string,\n imageConfig?: { aspectRatio?: string; imageSize?: string }\n ): Promise<Buffer> {\n // ─────────────────────────────────────────────────────────────────────\n // OPENROUTER (Via Fetch / Chat Completions)\n // ─────────────────────────────────────────────────────────────────────\n if (provider === \"openrouter\") {\n // Calculate aspect ratio from size if not provided\n let aspectRatio = imageConfig?.aspectRatio || \"1:1\";\n if (!imageConfig?.aspectRatio) {\n const [width, height] = size.split(\"x\").map(Number);\n if (width && height) {\n const gcd = (a: number, b: number): number => (b === 0 ? a : gcd(b, a % b));\n const divisor = gcd(width, height);\n const calculated = `${width / divisor}:${height / divisor}`;\n\n // Map calculated ratio to supported OpenRouter ratios\n const supportedRatios: Record<string, string> = {\n \"1:1\": \"1:1\",\n \"2:3\": \"2:3\",\n \"3:2\": \"3:2\",\n \"3:4\": \"3:4\",\n \"4:3\": \"4:3\",\n \"4:5\": \"4:5\",\n \"5:4\": \"5:4\",\n \"9:16\": \"9:16\",\n \"16:9\": \"16:9\",\n \"21:9\": \"21:9\",\n // Common unsupported ratios mapped to closest supported\n \"7:4\": \"16:9\", // 1792x1024\n \"4:7\": \"9:16\", // 1024x1792\n \"64:27\": \"21:9\", // ultrawide variants\n };\n\n aspectRatio = supportedRatios[calculated] || \"1:1\";\n }\n }\n\n // Build messages array\n let content: Array<{ type: string; text?: string; image_url?: { url: string } }> | string;\n if (sourceImageData) {\n // Image-to-image generation: include source image in content\n content = [\n {\n type: \"text\",\n text: prompt,\n },\n {\n type: \"image_url\",\n image_url: {\n url: sourceImageData,\n },\n },\n ];\n } else {\n // Text-to-image generation: just the prompt\n content = prompt;\n }\n\n const response = await fetch(\"https://openrouter.ai/api/v1/chat/completions\", {\n method: \"POST\",\n headers: {\n Authorization: `Bearer ${apiKey}`,\n \"Content-Type\": \"application/json\",\n \"HTTP-Referer\": \"https://clawbr.bricks-studio.ai\",\n \"X-Title\": \"clawbr CLI\",\n },\n body: JSON.stringify({\n model: model,\n messages: [\n {\n role: \"user\",\n content: content,\n },\n ],\n // Specific to Gemini/OpenRouter multimodal\n modalities: [\"image\", \"text\"],\n ...(aspectRatio || imageConfig?.imageSize\n ? {\n image_config: {\n ...(aspectRatio ? { aspect_ratio: aspectRatio } : {}),\n ...(imageConfig?.imageSize ? { image_size: imageConfig.imageSize } : {}),\n },\n }\n : {}),\n }),\n });\n\n if (!response.ok) {\n const text = await response.text();\n throw new Error(`OpenRouter API error: ${text}`);\n }\n\n const result = (await response.json()) as any;\n\n if (result.choices?.[0]?.message?.images?.[0]?.image_url?.url) {\n const imageUrl = result.choices[0].message.images[0].image_url.url;\n\n // If it's a URL, fetch it\n if (imageUrl.startsWith(\"http\")) {\n const imgRes = await fetch(imageUrl);\n const arrayBuffer = await imgRes.arrayBuffer();\n return Buffer.from(arrayBuffer);\n }\n\n // If it's base64 data URI\n if (imageUrl.startsWith(\"data:image\")) {\n const base64Data = imageUrl.split(\",\")[1];\n return Buffer.from(base64Data, \"base64\");\n }\n\n throw new Error(\"Unknown image URL format\");\n }\n\n throw new Error(\"No image generated from OpenRouter response\");\n }\n\n // ─────────────────────────────────────────────────────────────────────\n // OPENAI / GOOGLE (Via AI SDK)\n // ─────────────────────────────────────────────────────────────────────\n const imageModel = this.getImageModel(provider, apiKey, model);\n\n // Pass size as string directly as per SDK requirements.\n // We cast to 'any' to avoid strict template literal validation errors\n // since we know validSizes allows specifically \"1024x1024\" etc.\n const { image } = await generateImage({\n model: imageModel,\n prompt,\n n: 1,\n size: size as any,\n });\n\n // The image object from 'ai' SDK contains the base64 string\n return Buffer.from(image.base64, \"base64\");\n }\n\n @Option({\n flags: \"-p, --prompt <text>\",\n description: \"Text description of the image to generate\",\n })\n parsePrompt(val: string): string {\n return val;\n }\n\n @Option({\n flags: \"-o, --output <path>\",\n description: \"Path where the generated image will be saved\",\n })\n parseOutput(val: string): string {\n return val;\n }\n\n @Option({\n flags: \"-s, --size <size>\",\n description: \"Image size (256x256, 512x512, 1024x1024, 1792x1024, 1024x1792)\",\n })\n parseSize(val: string): string {\n return val;\n }\n\n @Option({\n flags: \"--source-image <path>\",\n description: \"Path to source image or URL (for image-to-image generation, OpenRouter only)\",\n })\n parseSourceImage(val: string): string {\n return val;\n }\n\n @Option({\n flags: \"-m, --model <modelId>\",\n description:\n \"Specific model to use (provider-dependent). Use model ID from your provider's list. Note: Not all models support reference images (--source-image).\",\n })\n parseModel(val: string): string {\n return val;\n }\n\n @Option({\n flags: \"--aspect-ratio <ratio>\",\n description:\n \"Aspect ratio for generated image (OpenRouter only). Supported: 1:1, 2:3, 3:2, 3:4, 4:3, 4:5, 5:4, 9:16, 16:9, 21:9\",\n })\n parseAspectRatio(val: string): string {\n return val;\n }\n\n @Option({\n flags: \"--image-size <size>\",\n description:\n \"Image resolution size (OpenRouter only). Supported: 1K (standard), 2K (higher), 4K (highest)\",\n })\n parseImageSize(val: string): string {\n return val;\n }\n\n @Option({\n flags: \"--json\",\n description: \"Output result in JSON format\",\n })\n parseJson(): boolean {\n return true;\n }\n}\n"],"names":["Command","CommandRunner","Option","writeFileSync","ora","fetch","resolve","generateImage","createOpenAI","createGoogleGenerativeAI","loadCredentials","resolveImageToDataUri","validateImageInput","requireOnboarding","getProviderModels","getModelById","isValidModel","getPrimaryModel","getFallbackModels","supportsReferenceImage","formatModelList","GenerateCommand","run","inputs","options","prompt","output","size","sourceImage","model","aspectRatio","imageSize","json","Error","validation","valid","error","validSizes","includes","join","credentials","aiProvider","apiKeys","apiKey","availableModels","modelInfo","name","filter","m","map","id","sourceImageData","undefined","spinner","start","imageBuffer","primaryModel","fallbackModels","imageConfig","generateWithFallback","primary","fallbacks","fail","outputPath","succeed","console","log","JSON","stringify","success","provider","isSpinning","config","modelsToTry","lastError","i","length","modelName","split","pop","text","generateWithModel","info","warn","message","getImageModel","openai","image","google","width","height","Number","gcd","a","b","divisor","calculated","supportedRatios","content","type","image_url","url","response","method","headers","Authorization","body","messages","role","modalities","image_config","aspect_ratio","image_size","ok","result","choices","images","imageUrl","startsWith","imgRes","arrayBuffer","Buffer","from","base64Data","imageModel","n","base64","parsePrompt","val","parseOutput","parseSize","parseSourceImage","parseModel","parseAspectRatio","parseImageSize","parseJson","flags","description","arguments","isDefault"],"mappings":"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"}
1
+ {"version":3,"sources":["../../src/commands/generate.command.ts"],"sourcesContent":["import { Command, CommandRunner, Option } from \"nest-commander\";\nimport { writeFileSync } from \"fs\";\nimport ora from \"ora\";\nimport fetch from \"node-fetch\";\nimport { resolve } from \"path\";\nimport { generateImage } from \"ai\";\nimport { createOpenAI } from \"@ai-sdk/openai\";\nimport { createGoogleGenerativeAI } from \"@ai-sdk/google\";\nimport { loadCredentials } from \"../utils/credentials.js\";\nimport { resolveImageToDataUri, validateImageInput } from \"../utils/image.js\";\nimport { requireOnboarding } from \"../utils/config.js\";\nimport {\n getProviderModels,\n getModelById,\n isValidModel,\n getPrimaryModel,\n getFallbackModels,\n supportsReferenceImage,\n formatModelList,\n} from \"../config/image-models.js\";\n\ninterface GenerateCommandOptions {\n prompt?: string;\n output?: string;\n size?: string;\n sourceImage?: string;\n model?: string;\n aspectRatio?: string;\n imageSize?: string;\n json?: boolean;\n}\n\n@Command({\n name: \"generate\",\n description: \"Generate an image using AI with smart model fallback\",\n arguments: \"\",\n options: { isDefault: false },\n})\nexport class GenerateCommand extends CommandRunner {\n async run(inputs: string[], options: GenerateCommandOptions): Promise<void> {\n await requireOnboarding();\n const {\n prompt,\n output,\n size = \"1024x1024\",\n sourceImage,\n model,\n aspectRatio,\n imageSize,\n json = false,\n } = options;\n\n // ─────────────────────────────────────────────────────────────────────\n // Validation\n // ─────────────────────────────────────────────────────────────────────\n if (!prompt) {\n throw new Error(\n '--prompt is required. Example: clawbr generate --prompt \"a robot building software\" --output \"./robot.png\"'\n );\n }\n\n if (!output) {\n throw new Error(\n '--output is required. Example: clawbr generate --prompt \"...\" --output \"./image.png\"'\n );\n }\n\n // Validate source image if provided\n if (sourceImage) {\n const validation = validateImageInput(sourceImage);\n if (!validation.valid) {\n throw new Error(validation.error);\n }\n }\n\n // Validate size\n const validSizes = [\"256x256\", \"512x512\", \"1024x1024\", \"1792x1024\", \"1024x1792\"];\n if (!validSizes.includes(size)) {\n throw new Error(`Invalid size. Must be one of: ${validSizes.join(\", \")}`);\n }\n\n // ─────────────────────────────────────────────────────────────────────\n // Load Credentials\n // ─────────────────────────────────────────────────────────────────────\n const credentials = loadCredentials();\n\n if (!credentials) {\n throw new Error(\"Credentials not found. Run 'clawbr onboard' first to set up your account.\");\n }\n\n const { aiProvider, apiKeys } = credentials;\n const apiKey = apiKeys[aiProvider as keyof typeof apiKeys];\n\n if (!apiKey) {\n throw new Error(\n `No API key found for provider '${aiProvider}'. Run 'clawbr onboard' to configure.`\n );\n }\n\n // ─────────────────────────────────────────────────────────────────────\n // Validate model if provided\n // ─────────────────────────────────────────────────────────────────────\n if (model && !isValidModel(aiProvider, model)) {\n const availableModels = formatModelList(aiProvider);\n throw new Error(\n `Invalid model '${model}' for provider '${aiProvider}'.\\n\\nAvailable models:\\n${availableModels}`\n );\n }\n\n // ─────────────────────────────────────────────────────────────────────\n // Check reference image support\n // ─────────────────────────────────────────────────────────────────────\n if (sourceImage && model && !supportsReferenceImage(aiProvider, model)) {\n const modelInfo = getModelById(aiProvider, model);\n throw new Error(\n `Model '${modelInfo?.name || model}' does not support reference images.\\n\\n` +\n `For reference image support with ${aiProvider}, use one of:\\n` +\n getProviderModels(aiProvider)\n .filter((m) => m.supportsReferenceImage)\n .map((m) => ` • ${m.id}`)\n .join(\"\\n\")\n );\n }\n\n // ─────────────────────────────────────────────────────────────────────\n // Prepare source image if provided\n // ─────────────────────────────────────────────────────────────────────\n const sourceImageData = sourceImage ? await resolveImageToDataUri(sourceImage) : undefined;\n\n // ─────────────────────────────────────────────────────────────────────\n // Generate Image with Smart Fallback\n // ─────────────────────────────────────────────────────────────────────\n const spinner = json\n ? null\n : ora(sourceImageData ? \"Generating image from source...\" : \"Generating image...\").start();\n\n try {\n let imageBuffer: Buffer;\n let modelUsed: string;\n\n // Determine models to try\n const primaryModel = model || getPrimaryModel(aiProvider);\n // If the user explicitly specified a model, disable fallbacks so we\n // honour their choice strictly and fail fast if it doesn't work.\n const fallbackModels = model ? [] : getFallbackModels(aiProvider);\n\n // Pass aspect ratio and image size to generation\n const imageConfig: { aspectRatio?: string; imageSize?: string } = {};\n if (aspectRatio) imageConfig.aspectRatio = aspectRatio;\n if (imageSize) imageConfig.imageSize = imageSize;\n\n if (aiProvider === \"openrouter\") {\n ({ buffer: imageBuffer, modelUsed } = await this.generateWithFallback(\n prompt,\n size,\n apiKey,\n \"openrouter\",\n { primary: primaryModel, fallbacks: fallbackModels },\n spinner,\n sourceImageData,\n imageConfig\n ));\n } else if (aiProvider === \"openai\") {\n if (sourceImageData) {\n throw new Error(\n \"OpenAI does not support image-to-image generation. Use OpenRouter with a model that supports reference images.\"\n );\n }\n ({ buffer: imageBuffer, modelUsed } = await this.generateWithFallback(\n prompt,\n size,\n apiKey,\n \"openai\",\n { primary: primaryModel, fallbacks: fallbackModels },\n spinner\n ));\n } else if (aiProvider === \"google\") {\n if (sourceImageData) {\n throw new Error(\n \"Google Imagen does not support image-to-image generation. Use OpenRouter with a model that supports reference images.\"\n );\n }\n ({ buffer: imageBuffer, modelUsed } = await this.generateWithFallback(\n prompt,\n size,\n apiKey,\n \"google\",\n { primary: primaryModel, fallbacks: fallbackModels },\n spinner\n ));\n } else {\n if (spinner) spinner.fail();\n throw new Error(`Unsupported AI provider: ${aiProvider}`);\n }\n\n // ─────────────────────────────────────────────────────────────────────\n // Save Image\n // ─────────────────────────────────────────────────────────────────────\n const outputPath = resolve(output);\n writeFileSync(outputPath, imageBuffer);\n\n if (spinner) {\n spinner.succeed(`Image generated and saved to: ${outputPath}`);\n }\n\n // ─────────────────────────────────────────────────────────────────────\n // Output\n // ─────────────────────────────────────────────────────────────────────\n if (json) {\n console.log(\n JSON.stringify(\n {\n success: true,\n prompt,\n output: outputPath,\n size,\n provider: aiProvider,\n modelUsed,\n },\n null,\n 2\n )\n );\n } else {\n console.log(\"\\nšŸŽØ Image Generation Complete!\");\n console.log(\"─────────────────────────────────────\");\n console.log(`Prompt: ${prompt}`);\n console.log(`Size: ${size}`);\n if (sourceImageData) {\n console.log(`Source Image: ${sourceImage}`);\n }\n console.log(`Output: ${outputPath}`);\n console.log(`Provider: ${aiProvider}`);\n if (model) {\n console.log(`Model: ${model}`);\n }\n console.log(\"─────────────────────────────────────\\n\");\n }\n } catch (error) {\n if (spinner && spinner.isSpinning) {\n spinner.fail(\"Image generation failed\");\n }\n throw error;\n }\n }\n\n /**\n * Generate image with smart fallback chain\n * Tries primary model first, then falls back to alternatives if it fails\n */\n private async generateWithFallback(\n prompt: string,\n size: string,\n apiKey: string,\n provider: \"openrouter\" | \"openai\" | \"google\",\n config: { primary: string | null; fallbacks: string[] },\n spinner: {\n text: string;\n info: (msg: string) => void;\n warn: (msg: string) => void;\n isSpinning?: boolean;\n } | null,\n sourceImageData?: string,\n imageConfig?: { aspectRatio?: string; imageSize?: string }\n ): Promise<{ buffer: Buffer; modelUsed: string }> {\n const modelsToTry = [config.primary, ...config.fallbacks].filter(\n (model): model is string => model !== null\n );\n\n let lastError: Error | null = null;\n\n for (let i = 0; i < modelsToTry.length; i++) {\n const model = modelsToTry[i];\n\n try {\n if (spinner) {\n const modelName = model.split(\"/\").pop() || model;\n spinner.text = `Generating image with ${modelName}... (attempt ${i + 1}/${modelsToTry.length})`;\n }\n\n const imageBuffer = await this.generateWithModel(\n prompt,\n size,\n apiKey,\n provider,\n model,\n sourceImageData,\n imageConfig\n );\n\n if (spinner && i > 0) {\n // Only show fallback message if we had to fall back\n spinner.info(`Successfully generated with fallback model: ${model}`);\n }\n\n return { buffer: imageBuffer, modelUsed: model };\n } catch (error) {\n lastError = error as Error;\n\n // If this wasn't the last model, log the failure and try the next one\n if (i < modelsToTry.length - 1) {\n if (spinner) {\n spinner.warn(`Model ${model} failed, trying fallback...`);\n } else {\n console.warn(`Model ${model} failed: ${lastError.message}`);\n }\n continue;\n }\n }\n }\n\n // If we get here, all models failed\n throw new Error(\n `All models failed to generate image. Last error: ${lastError?.message || \"Unknown error\"}`\n );\n }\n\n /**\n * get the model configuration for the AI SDK\n */\n private getImageModel(provider: string, apiKey: string, model: string) {\n if (provider === \"openai\") {\n const openai = createOpenAI({ apiKey });\n return openai.image(model);\n } else if (provider === \"google\") {\n const google = createGoogleGenerativeAI({ apiKey });\n return google.image(model);\n }\n throw new Error(`Provider ${provider} not supported via AI SDK`);\n }\n\n /**\n * Generate image using a specific model\n */\n private async generateWithModel(\n prompt: string,\n size: string,\n apiKey: string,\n provider: \"openrouter\" | \"openai\" | \"google\",\n model: string,\n sourceImageData?: string,\n imageConfig?: { aspectRatio?: string; imageSize?: string }\n ): Promise<Buffer> {\n // ─────────────────────────────────────────────────────────────────────\n // OPENROUTER (Via Fetch / Chat Completions)\n // ─────────────────────────────────────────────────────────────────────\n if (provider === \"openrouter\") {\n // Calculate aspect ratio from size if not provided\n let aspectRatio = imageConfig?.aspectRatio || \"1:1\";\n if (!imageConfig?.aspectRatio) {\n const [width, height] = size.split(\"x\").map(Number);\n if (width && height) {\n const gcd = (a: number, b: number): number => (b === 0 ? a : gcd(b, a % b));\n const divisor = gcd(width, height);\n const calculated = `${width / divisor}:${height / divisor}`;\n\n // Map calculated ratio to supported OpenRouter ratios\n const supportedRatios: Record<string, string> = {\n \"1:1\": \"1:1\",\n \"2:3\": \"2:3\",\n \"3:2\": \"3:2\",\n \"3:4\": \"3:4\",\n \"4:3\": \"4:3\",\n \"4:5\": \"4:5\",\n \"5:4\": \"5:4\",\n \"9:16\": \"9:16\",\n \"16:9\": \"16:9\",\n \"21:9\": \"21:9\",\n // Common unsupported ratios mapped to closest supported\n \"7:4\": \"16:9\", // 1792x1024\n \"4:7\": \"9:16\", // 1024x1792\n \"64:27\": \"21:9\", // ultrawide variants\n };\n\n aspectRatio = supportedRatios[calculated] || \"1:1\";\n }\n }\n\n // Build messages array\n let content: Array<{ type: string; text?: string; image_url?: { url: string } }> | string;\n if (sourceImageData) {\n // Image-to-image generation: include source image in content\n content = [\n {\n type: \"text\",\n text: prompt,\n },\n {\n type: \"image_url\",\n image_url: {\n url: sourceImageData,\n },\n },\n ];\n } else {\n // Text-to-image generation: just the prompt\n content = prompt;\n }\n\n const response = await fetch(\"https://openrouter.ai/api/v1/chat/completions\", {\n method: \"POST\",\n headers: {\n Authorization: `Bearer ${apiKey}`,\n \"Content-Type\": \"application/json\",\n \"HTTP-Referer\": \"https://clawbr.bricks-studio.ai\",\n \"X-Title\": \"clawbr CLI\",\n },\n body: JSON.stringify({\n model: model,\n messages: [\n {\n role: \"user\",\n content: content,\n },\n ],\n // Specific to Gemini/OpenRouter multimodal\n modalities: [\"image\", \"text\"],\n ...(aspectRatio || imageConfig?.imageSize\n ? {\n image_config: {\n ...(aspectRatio ? { aspect_ratio: aspectRatio } : {}),\n ...(imageConfig?.imageSize ? { image_size: imageConfig.imageSize } : {}),\n },\n }\n : {}),\n }),\n });\n\n if (!response.ok) {\n const text = await response.text();\n throw new Error(`OpenRouter API error: ${text}`);\n }\n\n const result = (await response.json()) as any;\n\n if (result.choices?.[0]?.message?.images?.[0]?.image_url?.url) {\n const imageUrl = result.choices[0].message.images[0].image_url.url;\n\n // If it's a URL, fetch it\n if (imageUrl.startsWith(\"http\")) {\n const imgRes = await fetch(imageUrl, {\n headers: {\n \"User-Agent\":\n \"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/124.0.0.0 Safari/537.36\",\n },\n });\n const arrayBuffer = await imgRes.arrayBuffer();\n return Buffer.from(arrayBuffer);\n }\n\n // If it's base64 data URI\n if (imageUrl.startsWith(\"data:image\")) {\n const base64Data = imageUrl.split(\",\")[1];\n return Buffer.from(base64Data, \"base64\");\n }\n\n throw new Error(\"Unknown image URL format\");\n }\n\n throw new Error(\"No image generated from OpenRouter response\");\n }\n\n // ─────────────────────────────────────────────────────────────────────\n // OPENAI / GOOGLE (Via AI SDK)\n // ─────────────────────────────────────────────────────────────────────\n const imageModel = this.getImageModel(provider, apiKey, model);\n\n // Pass size as string directly as per SDK requirements.\n // We cast to 'any' to avoid strict template literal validation errors\n // since we know validSizes allows specifically \"1024x1024\" etc.\n const { image } = await generateImage({\n model: imageModel,\n prompt,\n n: 1,\n size: size as any,\n });\n\n // The image object from 'ai' SDK contains the base64 string\n return Buffer.from(image.base64, \"base64\");\n }\n\n @Option({\n flags: \"-p, --prompt <text>\",\n description: \"Text description of the image to generate\",\n })\n parsePrompt(val: string): string {\n return val;\n }\n\n @Option({\n flags: \"-o, --output <path>\",\n description: \"Path where the generated image will be saved\",\n })\n parseOutput(val: string): string {\n return val;\n }\n\n @Option({\n flags: \"-s, --size <size>\",\n description: \"Image size (256x256, 512x512, 1024x1024, 1792x1024, 1024x1792)\",\n })\n parseSize(val: string): string {\n return val;\n }\n\n @Option({\n flags: \"--source-image <path>\",\n description: \"Path to source image or URL (for image-to-image generation, OpenRouter only)\",\n })\n parseSourceImage(val: string): string {\n return val;\n }\n\n @Option({\n flags: \"-m, --model <modelId>\",\n description:\n \"Specific model to use (provider-dependent). Use model ID from your provider's list. Note: Not all models support reference images (--source-image).\",\n })\n parseModel(val: string): string {\n return val;\n }\n\n @Option({\n flags: \"--aspect-ratio <ratio>\",\n description:\n \"Aspect ratio for generated image (OpenRouter only). Supported: 1:1, 2:3, 3:2, 3:4, 4:3, 4:5, 5:4, 9:16, 16:9, 21:9\",\n })\n parseAspectRatio(val: string): string {\n return val;\n }\n\n @Option({\n flags: \"--image-size <size>\",\n description:\n \"Image resolution size (OpenRouter only). Supported: 1K (standard), 2K (higher), 4K (highest)\",\n })\n parseImageSize(val: string): string {\n return val;\n }\n\n @Option({\n flags: \"--json\",\n description: \"Output result in JSON format\",\n })\n parseJson(): boolean {\n return true;\n }\n}\n"],"names":["Command","CommandRunner","Option","writeFileSync","ora","fetch","resolve","generateImage","createOpenAI","createGoogleGenerativeAI","loadCredentials","resolveImageToDataUri","validateImageInput","requireOnboarding","getProviderModels","getModelById","isValidModel","getPrimaryModel","getFallbackModels","supportsReferenceImage","formatModelList","GenerateCommand","run","inputs","options","prompt","output","size","sourceImage","model","aspectRatio","imageSize","json","Error","validation","valid","error","validSizes","includes","join","credentials","aiProvider","apiKeys","apiKey","availableModels","modelInfo","name","filter","m","map","id","sourceImageData","undefined","spinner","start","imageBuffer","modelUsed","primaryModel","fallbackModels","imageConfig","buffer","generateWithFallback","primary","fallbacks","fail","outputPath","succeed","console","log","JSON","stringify","success","provider","isSpinning","config","modelsToTry","lastError","i","length","modelName","split","pop","text","generateWithModel","info","warn","message","getImageModel","openai","image","google","width","height","Number","gcd","a","b","divisor","calculated","supportedRatios","content","type","image_url","url","response","method","headers","Authorization","body","messages","role","modalities","image_config","aspect_ratio","image_size","ok","result","choices","images","imageUrl","startsWith","imgRes","arrayBuffer","Buffer","from","base64Data","imageModel","n","base64","parsePrompt","val","parseOutput","parseSize","parseSourceImage","parseModel","parseAspectRatio","parseImageSize","parseJson","flags","description","arguments","isDefault"],"mappings":"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"}
package/dist/version.js CHANGED
@@ -1,4 +1,4 @@
1
1
  // This file is auto-generated. Do not edit manually.
2
- export const CLAWBR_VERSION = "0.0.42";
2
+ export const CLAWBR_VERSION = "0.0.43";
3
3
 
4
4
  //# sourceMappingURL=version.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/version.ts"],"sourcesContent":["// This file is auto-generated. Do not edit manually.\nexport const CLAWBR_VERSION = \"0.0.42\";\n"],"names":["CLAWBR_VERSION"],"mappings":"AAAA,qDAAqD;AACrD,OAAO,MAAMA,iBAAiB,SAAS"}
1
+ {"version":3,"sources":["../src/version.ts"],"sourcesContent":["// This file is auto-generated. Do not edit manually.\nexport const CLAWBR_VERSION = \"0.0.43\";\n"],"names":["CLAWBR_VERSION"],"mappings":"AAAA,qDAAqD;AACrD,OAAO,MAAMA,iBAAiB,SAAS"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "clawbr",
3
- "version": "0.0.42",
3
+ "version": "0.0.43",
4
4
  "description": "Official CLI for clawbr - Tumblr for AI agents. Full social interaction: post, like, comment, quote, and browse feeds.",
5
5
  "type": "module",
6
6
  "bin": {