@su-record/vibe 2.6.33 → 2.6.35

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.
@@ -97,38 +97,30 @@ vibe gemini status
97
97
 
98
98
  Or check config file: `~/.config/vibe/gemini.json`
99
99
 
100
- #### If Gemini Enabled: Generate UI Image
100
+ #### If Gemini Enabled: Generate UI Image + Code
101
101
 
102
- Use Gemini Image API to generate actual UI mockup:
103
-
104
- **Prompt template for Gemini:**
102
+ ##### A. UI Mockup Image Generation
105
103
 
104
+ ```bash
105
+ node "$(node -p "process.env.APPDATA || require('os').homedir() + '/.config'")/vibe/hooks/scripts/llm-orchestrate.js" gemini image "Modern UI mockup: [UI Description from step 2]. Clean design, [colors/typography if available], mobile-first responsive layout" --output "./ui-preview.png"
106
106
  ```
107
- Generate a modern UI mockup image for:
108
107
 
109
- [UI Description from step 2]
108
+ ##### B. UI Code Generation (from design files)
110
109
 
111
- Style requirements:
112
- - Clean, modern design
113
- - [Colors from design tokens if available]
114
- - [Typography from style guide if available]
115
- - Mobile-first responsive layout
116
- - Include all specified components
110
+ When design files (image/HTML/folder) are provided, use Gemini to generate production-ready component code:
117
111
 
118
- Output: High-quality UI mockup image (1280x720 or similar)
112
+ ```bash
113
+ node "$(node -p "process.env.APPDATA || require('os').homedir() + '/.config'")/vibe/hooks/scripts/llm-orchestrate.js" gemini orchestrate "You are a UI code generator. Analyze the provided design and generate production-ready React TypeScript components with Tailwind CSS. Output complete component code with proper types, responsive layout, and accessibility attributes."
119
114
  ```
120
115
 
121
- **Execution:**
116
+ Pass the design context (file contents, extracted colors, layout structure from step 2) as the user prompt via stdin or arguments.
122
117
 
123
- ```bash
124
- node hooks/scripts/generate-brand-assets.js \
125
- --type "ui-mockup" \
126
- --description "[analyzed UI description]" \
127
- --colors "[extracted colors]" \
128
- --output "./ui-preview.png"
129
- ```
118
+ **When to use each:**
130
119
 
131
- **Output location:** `./ui-preview-{timestamp}.png`
120
+ | Input | Image (Step A) | Code (Step B) |
121
+ | ----- | -------------- | ------------- |
122
+ | Text description | Generate mockup | Skip |
123
+ | Image/HTML/Folder | Generate mockup | Generate component code |
132
124
 
133
125
  #### If Gemini Disabled: ASCII Art Fallback
134
126
 
@@ -959,20 +959,9 @@ Brand:
959
959
 
960
960
  **Manual Generation:**
961
961
  ```bash
962
- node hooks/scripts/generate-brand-assets.js \
963
- --spec ".claude/vibe/specs/my-feature.md" \
964
- --output "./public"
965
-
966
- # Or with explicit values
967
- node hooks/scripts/generate-brand-assets.js \
968
- --name "MyApp" \
969
- --color "#2F6BFF" \
970
- --style "modern minimal" \
971
- --output "./public"
962
+ node "$(node -p "process.env.APPDATA || require('os').homedir() + '/.config'")/vibe/hooks/scripts/llm-orchestrate.js" gemini image "App icon for MyApp, primary color #2F6BFF, square format 1:1, simple recognizable design, works well at small sizes, no text or letters, solid or gradient background, modern minimalist" --output "./public/app-icon.png"
972
963
  ```
973
964
 
974
- **Fallback:** If Gemini Image fails, generates text monogram icon (first letter + primary color).
975
-
976
965
  ---
977
966
 
978
967
  ### 5. Race Code Review (GPT + Gemini) + Auto-Fix (v2.6.9)
@@ -90,11 +90,33 @@ User: 1 hour, disallow, confirm
90
90
  | PDF | `.pdf` | Planning docs, design documents |
91
91
  | Image | `.png`, `.jpg`, `.jpeg`, `.webp` | Wireframes, UI design, screenshots |
92
92
 
93
+ **Image input analysis:**
94
+
95
+ When image files (`.png`, `.jpg`, `.jpeg`, `.webp`) are provided as input, analyze them using the best available method:
96
+
97
+ - **Gemini Enabled**: `llm-orchestrate.js gemini analyze-image` (Gemini 3 Flash - best image recognition)
98
+ - **Gemini Disabled**: Claude Opus Read tool (built-in multimodal, existing behavior)
99
+
100
+ **Gemini enabled - analyze via llm-orchestrate.js:**
101
+
102
+ ```bash
103
+ node "$(node -p "process.env.APPDATA || require('os').homedir() + '/.config'")/vibe/hooks/scripts/llm-orchestrate.js" gemini analyze-image "./designs/login-wireframe.png" "Analyze this UI design image. Identify all UI elements, layout structure, colors, typography, and component hierarchy. Output a structured breakdown."
104
+ ```
105
+
106
+ Parse the JSON result: `{ success: true, analysis: "..." }` → use `analysis` field content.
107
+
108
+ If `success: false`, fall back to Claude Read tool.
109
+
110
+ **Gemini disabled - analyze via Claude Read tool:**
111
+
112
+ Use the Read tool directly on the image file. Claude can read images natively.
113
+
93
114
  **Image input example:**
94
115
  ```
95
116
  /vibe.spec "designs/login-wireframe.png"
96
117
 
97
118
  🖼️ Image analysis: designs/login-wireframe.png
119
+ (via Gemini 3 Flash / Claude Opus)
98
120
 
99
121
  📋 Detected UI elements:
100
122
  - Email input field
@@ -33,7 +33,7 @@ Read and follow `agents/ui-previewer.md` for UI preview generation.
33
33
 
34
34
  Generate UI preview from description or design folder.
35
35
 
36
- - **Gemini enabled**: Actual UI mockup image
36
+ - **Gemini enabled**: UI mockup image + component code generation (via `llm-orchestrate.js` → `gemini-api`)
37
37
  - **Gemini disabled**: ASCII art fallback
38
38
 
39
39
  **Input types:**
@@ -75,10 +75,21 @@ interface ImageGenerationResult {
75
75
  mimeType: string;
76
76
  }
77
77
  /**
78
- * Gemini 이미지 생성 (Nano Banana - gemini-2.5-flash-preview-image-generation)
79
- * API Key 방식만 지원 (이미지 생성은 Google AI Studio API 직접 호출)
78
+ * Gemini Image Generation (Nano Banana - gemini-2.5-flash-image)
79
+ * API Key only (direct Google AI Studio API call for image generation)
80
80
  */
81
81
  export declare function generateImage(prompt: string, options?: ImageGenerationOptions): Promise<ImageGenerationResult>;
82
+ interface ImageAnalysisOptions {
83
+ model?: string;
84
+ maxTokens?: number;
85
+ temperature?: number;
86
+ systemPrompt?: string;
87
+ }
88
+ /**
89
+ * Gemini Image Analysis (이미지 분석 - gemini-3-flash)
90
+ * 이미지 파일을 읽어서 Gemini 멀티모달 API로 분석
91
+ */
92
+ export declare function analyzeImage(imagePath: string, prompt: string, options?: ImageAnalysisOptions): Promise<string>;
82
93
  /**
83
94
  * Vibe Gemini 오케스트레이션 옵션
84
95
  */
@@ -1 +1 @@
1
- {"version":3,"file":"gemini-api.d.ts","sourceRoot":"","sources":["../../src/lib/gemini-api.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"gemini-api.d.ts","sourceRoot":"","sources":["../../src/lib/gemini-api.ts"],"names":[],"mappings":"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"}
@@ -410,8 +410,8 @@ export async function analyzeUI(prompt) {
410
410
  });
411
411
  }
412
412
  /**
413
- * Gemini 이미지 생성 (Nano Banana - gemini-2.5-flash-preview-image-generation)
414
- * API Key 방식만 지원 (이미지 생성은 Google AI Studio API 직접 호출)
413
+ * Gemini Image Generation (Nano Banana - gemini-2.5-flash-image)
414
+ * API Key only (direct Google AI Studio API call for image generation)
415
415
  */
416
416
  export async function generateImage(prompt, options = {}) {
417
417
  const apiKey = getApiKeyFromConfig();
@@ -422,7 +422,7 @@ export async function generateImage(prompt, options = {}) {
422
422
  const [width, height] = size.split('x').map(Number);
423
423
  const aspectRatio = width && height ? `${width}:${height}` : '1:1';
424
424
  // Nano Banana (Gemini 2.5 Flash Image)
425
- const url = `https://generativelanguage.googleapis.com/v1beta/models/gemini-2.5-flash-preview-image-generation:generateContent?key=${apiKey}`;
425
+ const url = `https://generativelanguage.googleapis.com/v1beta/models/gemini-2.5-flash-image:generateContent?key=${apiKey}`;
426
426
  const requestBody = {
427
427
  contents: [{
428
428
  parts: [{
@@ -467,6 +467,143 @@ Requirements:
467
467
  }
468
468
  throw new Error('No image in Gemini response');
469
469
  }
470
+ function getImageMimeType(filePath) {
471
+ const ext = path.extname(filePath).toLowerCase();
472
+ const mimeMap = {
473
+ '.png': 'image/png',
474
+ '.jpg': 'image/jpeg',
475
+ '.jpeg': 'image/jpeg',
476
+ '.gif': 'image/gif',
477
+ '.webp': 'image/webp',
478
+ '.bmp': 'image/bmp',
479
+ };
480
+ return mimeMap[ext] || 'image/png';
481
+ }
482
+ /**
483
+ * Gemini Image Analysis (이미지 분석 - gemini-3-flash)
484
+ * 이미지 파일을 읽어서 Gemini 멀티모달 API로 분석
485
+ */
486
+ export async function analyzeImage(imagePath, prompt, options = {}) {
487
+ const { model = 'gemini-3-flash', maxTokens = 4096, temperature = 0.3, systemPrompt, } = options;
488
+ const absolutePath = path.resolve(imagePath);
489
+ if (!fs.existsSync(absolutePath)) {
490
+ throw new Error(`Image file not found: ${absolutePath}`);
491
+ }
492
+ const imageData = fs.readFileSync(absolutePath);
493
+ const base64Data = imageData.toString('base64');
494
+ const mimeType = getImageMimeType(absolutePath);
495
+ // Multimodal contents: inlineData + text
496
+ const contents = [{
497
+ role: 'user',
498
+ parts: [
499
+ { inlineData: { mimeType, data: base64Data } },
500
+ { text: prompt },
501
+ ],
502
+ }];
503
+ const authInfo = await getAuthInfo();
504
+ const apiKey = getApiKeyFromConfig();
505
+ // API Key
506
+ if (authInfo.type === 'apikey' && authInfo.apiKey) {
507
+ return analyzeImageWithApiKey(authInfo.apiKey, contents, { model, maxTokens, temperature, systemPrompt });
508
+ }
509
+ // OAuth (API Key fallback)
510
+ if (authInfo.type === 'oauth' && authInfo.accessToken) {
511
+ try {
512
+ return await analyzeImageWithOAuth(authInfo.accessToken, authInfo.projectId, contents, { model, maxTokens, temperature, systemPrompt });
513
+ }
514
+ catch (error) {
515
+ const errorMsg = error.message;
516
+ if (apiKey && (errorMsg.includes('429') || errorMsg.includes('401') || errorMsg.includes('403'))) {
517
+ return analyzeImageWithApiKey(apiKey, contents, { model, maxTokens, temperature, systemPrompt });
518
+ }
519
+ throw error;
520
+ }
521
+ }
522
+ throw new Error('Gemini credentials not found. Run "vibe gemini auth" or "vibe gemini key <key>".');
523
+ }
524
+ async function analyzeImageWithApiKey(apiKey, contents, options) {
525
+ const apiKeyModelMap = {
526
+ 'gemini-3-pro': 'gemini-3-pro-preview',
527
+ 'gemini-3-flash': 'gemini-3-flash-preview',
528
+ };
529
+ const actualModel = apiKeyModelMap[options.model] || 'gemini-3-flash-preview';
530
+ const requestBody = {
531
+ contents,
532
+ generationConfig: {
533
+ maxOutputTokens: options.maxTokens,
534
+ temperature: options.temperature,
535
+ },
536
+ };
537
+ if (options.systemPrompt) {
538
+ requestBody.systemInstruction = { parts: [{ text: options.systemPrompt }] };
539
+ }
540
+ const url = `https://generativelanguage.googleapis.com/v1beta/models/${actualModel}:generateContent?key=${apiKey}`;
541
+ const response = await fetch(url, {
542
+ method: 'POST',
543
+ headers: { 'Content-Type': 'application/json' },
544
+ body: JSON.stringify(requestBody),
545
+ });
546
+ if (!response.ok) {
547
+ const errorText = await response.text();
548
+ throw new Error(`Gemini API error (${response.status}): ${errorText}`);
549
+ }
550
+ const result = await response.json();
551
+ if (!result.candidates || result.candidates.length === 0) {
552
+ throw new Error('Gemini API response is empty.');
553
+ }
554
+ return result.candidates[0].content?.parts?.[0]?.text || '';
555
+ }
556
+ async function analyzeImageWithOAuth(accessToken, projectId, contents, options) {
557
+ const modelInfo = GEMINI_MODELS[options.model] || GEMINI_MODELS[DEFAULT_MODEL];
558
+ const innerRequest = {
559
+ contents,
560
+ generationConfig: {
561
+ maxOutputTokens: Math.min(options.maxTokens, modelInfo.maxTokens),
562
+ temperature: options.temperature,
563
+ },
564
+ };
565
+ if (options.systemPrompt) {
566
+ innerRequest.systemInstruction = { parts: [{ text: options.systemPrompt }] };
567
+ }
568
+ const requestBody = wrapRequestBody(innerRequest, projectId || ANTIGRAVITY_DEFAULT_PROJECT_ID, modelInfo.id);
569
+ let lastError = null;
570
+ for (const endpoint of ENDPOINT_FALLBACKS) {
571
+ const url = `${endpoint}/${ANTIGRAVITY_API_VERSION}:generateContent`;
572
+ try {
573
+ const response = await fetch(url, {
574
+ method: 'POST',
575
+ headers: {
576
+ 'Authorization': `Bearer ${accessToken}`,
577
+ 'Content-Type': 'application/json',
578
+ ...ANTIGRAVITY_HEADERS,
579
+ },
580
+ body: JSON.stringify(requestBody),
581
+ });
582
+ if (!response.ok) {
583
+ const errorText = await response.text();
584
+ if (response.status === 404) {
585
+ lastError = new Error(`API not found: ${errorText}`);
586
+ continue;
587
+ }
588
+ throw new Error(`Gemini API error (${response.status}): ${errorText}`);
589
+ }
590
+ const result = await response.json();
591
+ const responseData = result.response || result;
592
+ if (!responseData.candidates || responseData.candidates.length === 0) {
593
+ throw new Error('Gemini API response is empty.');
594
+ }
595
+ return responseData.candidates[0].content?.parts?.[0]?.text || '';
596
+ }
597
+ catch (error) {
598
+ lastError = error;
599
+ if (error.name === 'TypeError' || error.message.includes('not found')) {
600
+ continue;
601
+ }
602
+ throw error;
603
+ }
604
+ }
605
+ throw lastError || new Error('All Antigravity endpoints failed');
606
+ }
470
607
  /**
471
608
  * Vibe Gemini 오케스트레이션 (검색 없음, JSON 모드)
472
609
  * - 검색 제외로 빠른 응답
@@ -1 +1 @@
1
- {"version":3,"file":"gemini-api.js","sourceRoot":"","sources":["../../src/lib/gemini-api.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"gemini-api.js","sourceRoot":"","sources":["../../src/lib/gemini-api.ts"],"names":[],"mappings":"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"}
@@ -151,7 +151,7 @@ export async function startSession(args) {
151
151
  */
152
152
  function getRecentGitLog(projectRoot) {
153
153
  try {
154
- const result = execSync('git log --oneline -3 2>/dev/null', { cwd: projectRoot, encoding: 'utf-8', stdio: ['pipe', 'pipe', 'pipe'] }).trim();
154
+ const result = execSync(`git log --oneline -3 2>/dev/null`, { cwd: projectRoot, encoding: 'utf-8', stdio: ['pipe', 'pipe', 'pipe'] }).trim();
155
155
  if (result) {
156
156
  return result.split('\n').map(line => ` • ${line}`).join('\n') + '\n';
157
157
  }
@@ -6,7 +6,7 @@
6
6
  * node llm-orchestrate.js <provider> <mode> "systemPrompt" "prompt"
7
7
  *
8
8
  * provider: gpt | gemini
9
- * mode: orchestrate | orchestrate-json | image
9
+ * mode: orchestrate | orchestrate-json | image | analyze-image
10
10
  *
11
11
  * Image Mode:
12
12
  * node llm-orchestrate.js gemini image "prompt" --output "./image.png"
@@ -17,6 +17,11 @@
17
17
  * - Auto fallback: gemini → gpt, gpt → gemini
18
18
  * - Overload/rate-limit detection
19
19
  * - Image generation (Gemini only, Nano Banana model)
20
+ * - Image analysis (Gemini multimodal)
21
+ *
22
+ * Analyze-Image Mode:
23
+ * node llm-orchestrate.js gemini analyze-image "./image.png" "Analyze this UI"
24
+ * node llm-orchestrate.js gemini analyze-image "./image.png" "prompt" --system "system prompt"
20
25
  *
21
26
  * Input: JSON from stdin with { prompt: string } (when no CLI args)
22
27
  */
@@ -86,6 +91,26 @@ function parseImageArgs(args) {
86
91
  return result;
87
92
  }
88
93
 
94
+ // ============================================
95
+ // Image Analysis (delegates to gemini-api)
96
+ // ============================================
97
+
98
+ function parseAnalyzeImageArgs(args) {
99
+ const result = { imagePath: null, prompt: null, systemPrompt: null };
100
+ for (let i = 0; i < args.length; i++) {
101
+ if (args[i] === '--system' || args[i] === '-s') {
102
+ result.systemPrompt = args[++i];
103
+ } else if (!args[i].startsWith('-')) {
104
+ if (!result.imagePath) {
105
+ result.imagePath = args[i];
106
+ } else if (!result.prompt) {
107
+ result.prompt = args[i];
108
+ }
109
+ }
110
+ }
111
+ return result;
112
+ }
113
+
89
114
  async function callProvider(providerName, prompt, sysPrompt, jsonMode) {
90
115
  const modulePath = `${LIB_URL}${providerName}-api.js`;
91
116
  const module = await import(modulePath);
@@ -177,6 +202,60 @@ async function main() {
177
202
  return;
178
203
  }
179
204
 
205
+ // Analyze-image mode handling
206
+ if (mode === 'analyze-image') {
207
+ if (provider !== 'gemini') {
208
+ console.log('[ANALYZE-IMAGE] Error: Image analysis only supports gemini provider');
209
+ return;
210
+ }
211
+
212
+ const analyzeArgs = parseAnalyzeImageArgs(process.argv.slice(4));
213
+ if (!analyzeArgs.imagePath) {
214
+ console.log('[ANALYZE-IMAGE] Error: image path is required');
215
+ return;
216
+ }
217
+ if (!analyzeArgs.prompt) {
218
+ console.log('[ANALYZE-IMAGE] Error: analysis prompt is required');
219
+ return;
220
+ }
221
+
222
+ const absolutePath = path.resolve(analyzeArgs.imagePath);
223
+ if (!fs.existsSync(absolutePath)) {
224
+ console.log(JSON.stringify({
225
+ success: false,
226
+ error: `Image file not found: ${absolutePath}`,
227
+ imagePath: analyzeArgs.imagePath,
228
+ }));
229
+ return;
230
+ }
231
+
232
+ console.error(`[ANALYZE-IMAGE] Analyzing image with Gemini...`);
233
+ console.error(` Image: ${absolutePath}`);
234
+ console.error(` Prompt: ${analyzeArgs.prompt}`);
235
+
236
+ try {
237
+ const geminiApi = await import(`${LIB_URL}gemini-api.js`);
238
+ const options = {};
239
+ if (analyzeArgs.systemPrompt) {
240
+ options.systemPrompt = analyzeArgs.systemPrompt;
241
+ }
242
+ const analysis = await geminiApi.analyzeImage(absolutePath, analyzeArgs.prompt, options);
243
+
244
+ console.log(JSON.stringify({
245
+ success: true,
246
+ analysis,
247
+ imagePath: absolutePath,
248
+ }));
249
+ } catch (err) {
250
+ console.log(JSON.stringify({
251
+ success: false,
252
+ error: err.message,
253
+ imagePath: absolutePath,
254
+ }));
255
+ }
256
+ return;
257
+ }
258
+
180
259
  // Text generation mode (orchestrate / orchestrate-json)
181
260
  let prompt;
182
261
  let systemPrompt = DEFAULT_SYSTEM_PROMPT;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@su-record/vibe",
3
- "version": "2.6.33",
3
+ "version": "2.6.35",
4
4
  "description": "Vibe - Claude Code exclusive SPEC-driven AI coding framework with 35+ integrated tools",
5
5
  "type": "module",
6
6
  "main": "dist/cli/index.js",
@@ -59,7 +59,7 @@ Extract: name, colors, style keywords
59
59
  Generate Prompt: "App icon for [name], [style], [colors]..."
60
60
  |
61
61
  v
62
- Gemini Image API (imagen-3)
62
+ Gemini Image API (gemini-2.5-flash-image)
63
63
  |
64
64
  v
65
65
  Resize & Convert: All platform sizes
@@ -102,12 +102,8 @@ Requirements:
102
102
  ## Manual Usage
103
103
 
104
104
  ```bash
105
- # Generate via hook script (when Gemini configured)
106
- node hooks/scripts/generate-brand-assets.js \
107
- --name "MyApp" \
108
- --color "#2F6BFF" \
109
- --style "modern minimal" \
110
- --output "./public"
105
+ # Generate via llm-orchestrate (when Gemini configured)
106
+ node "$(node -p "process.env.APPDATA || require('os').homedir() + '/.config'")/vibe/hooks/scripts/llm-orchestrate.js" gemini image "App icon for MyApp, primary color #2F6BFF, square format 1:1, simple recognizable design, works well at small sizes, no text or letters, solid or gradient background, modern minimalist" --output "./public/app-icon.png"
111
107
  ```
112
108
 
113
109
  ## Integration with /vibe.run
@@ -1,281 +0,0 @@
1
- #!/usr/bin/env node
2
-
3
- /**
4
- * Gemini UI Code Generator
5
- *
6
- * 디자인 파일(이미지, HTML 등)을 분석해서 UI 코드를 생성합니다.
7
- * 기존 gemini-api 인프라 사용.
8
- *
9
- * Usage:
10
- * node gemini-ui-gen.js --image ./design.png --framework react --output ./src/components
11
- * node gemini-ui-gen.js --html ./mockup.html --framework vue --output ./src/components
12
- * node gemini-ui-gen.js --design-folder ./design/ --framework react --output ./src
13
- */
14
-
15
- import fs from 'fs';
16
- import path from 'path';
17
- import { getLibBaseUrl } from './utils.js';
18
-
19
- const LIB_URL = getLibBaseUrl();
20
-
21
- // ============================================
22
- // Gemini API (기존 인프라 사용)
23
- // ============================================
24
-
25
- let geminiApi = null;
26
-
27
- async function getGeminiApi() {
28
- if (!geminiApi) {
29
- geminiApi = await import(`${LIB_URL}gemini-api.js`);
30
- }
31
- return geminiApi;
32
- }
33
-
34
- async function askGemini(prompt) {
35
- const api = await getGeminiApi();
36
- return api.ask(prompt, { model: 'gemini-3-flash', maxTokens: 8192, temperature: 0.3 });
37
- }
38
-
39
- // ============================================
40
- // UI Code Generation
41
- // ============================================
42
-
43
- function getFrameworkPrompt(framework) {
44
- const prompts = {
45
- react: `Generate React TypeScript components using:
46
- - Functional components with hooks
47
- - Tailwind CSS for styling
48
- - Proper TypeScript types/interfaces
49
- - Export as default`,
50
-
51
- vue: `Generate Vue 3 components using:
52
- - Composition API with <script setup>
53
- - Tailwind CSS for styling
54
- - TypeScript support
55
- - Single File Component format`,
56
-
57
- svelte: `Generate Svelte components using:
58
- - Svelte 5 runes syntax
59
- - Tailwind CSS for styling
60
- - TypeScript support`,
61
-
62
- html: `Generate semantic HTML5 with:
63
- - Tailwind CSS classes
64
- - Accessible markup
65
- - Responsive design`,
66
- };
67
-
68
- return prompts[framework] || prompts.react;
69
- }
70
-
71
- async function generateUIFromImage(imagePath, framework) {
72
- const imageBuffer = fs.readFileSync(imagePath);
73
- const imageBase64 = imageBuffer.toString('base64');
74
-
75
- const ext = path.extname(imagePath).toLowerCase();
76
- const mimeTypes = {
77
- '.png': 'image/png',
78
- '.jpg': 'image/jpeg',
79
- '.jpeg': 'image/jpeg',
80
- '.webp': 'image/webp',
81
- '.gif': 'image/gif',
82
- };
83
- const mimeType = mimeTypes[ext] || 'image/png';
84
-
85
- const prompt = `[Image attached as base64: ${mimeType}]
86
- data:${mimeType};base64,${imageBase64}
87
-
88
- Analyze this UI design image and generate production-ready code.
89
-
90
- ${getFrameworkPrompt(framework)}
91
-
92
- Requirements:
93
- 1. Match the visual design exactly (colors, spacing, typography, layout)
94
- 2. Extract exact colors as hex values
95
- 3. Use proper semantic HTML structure
96
- 4. Make it responsive (mobile-first)
97
- 5. Include hover/focus states where appropriate
98
- 6. Add appropriate accessibility attributes
99
-
100
- Output format:
101
- \`\`\`${framework === 'html' ? 'html' : 'tsx'}
102
- // Component code here
103
- \`\`\`
104
-
105
- Also provide a summary of:
106
- - Colors extracted
107
- - Components identified
108
- - Layout structure`;
109
-
110
- return askGemini(prompt);
111
- }
112
-
113
- async function generateUIFromHTML(htmlPath, framework) {
114
- const htmlContent = fs.readFileSync(htmlPath, 'utf-8');
115
-
116
- const prompt = `Convert this HTML mockup to production-ready ${framework} code.
117
-
118
- HTML Mockup:
119
- \`\`\`html
120
- ${htmlContent}
121
- \`\`\`
122
-
123
- ${getFrameworkPrompt(framework)}
124
-
125
- Requirements:
126
- 1. Preserve the exact visual appearance
127
- 2. Extract inline styles to Tailwind classes
128
- 3. Create reusable components where appropriate
129
- 4. Add proper TypeScript types
130
- 5. Make it responsive
131
-
132
- Output the converted code in proper format.`;
133
-
134
- return askGemini(prompt);
135
- }
136
-
137
- async function analyzeDesignFolder(folderPath, framework) {
138
- const files = fs.readdirSync(folderPath);
139
- let combinedPrompt = `Analyze the following design files and generate production-ready ${framework} code.\n\n`;
140
-
141
- for (const file of files) {
142
- const filePath = path.join(folderPath, file);
143
- const ext = path.extname(file).toLowerCase();
144
-
145
- if (['.png', '.jpg', '.jpeg', '.webp', '.gif'].includes(ext)) {
146
- const imageBuffer = fs.readFileSync(filePath);
147
- const imageBase64 = imageBuffer.toString('base64');
148
- const mimeType = ext === '.png' ? 'image/png' : ext === '.webp' ? 'image/webp' : 'image/jpeg';
149
- combinedPrompt += `\n--- Image: ${file} ---\ndata:${mimeType};base64,${imageBase64}\n`;
150
- console.log(`📷 ${file}`);
151
- } else if (ext === '.html') {
152
- const content = fs.readFileSync(filePath, 'utf-8');
153
- combinedPrompt += `\n--- HTML: ${file} ---\n${content}\n`;
154
- console.log(`📄 ${file}`);
155
- } else if (ext === '.json') {
156
- const content = fs.readFileSync(filePath, 'utf-8');
157
- combinedPrompt += `\n--- Design Tokens: ${file} ---\n${content}\n`;
158
- console.log(`📋 ${file}`);
159
- } else if (['.css', '.scss'].includes(ext)) {
160
- const content = fs.readFileSync(filePath, 'utf-8');
161
- combinedPrompt += `\n--- Styles: ${file} ---\n${content}\n`;
162
- console.log(`🎨 ${file}`);
163
- } else if (ext === '.md') {
164
- const content = fs.readFileSync(filePath, 'utf-8');
165
- combinedPrompt += `\n--- Guide: ${file} ---\n${content}\n`;
166
- console.log(`📝 ${file}`);
167
- }
168
- }
169
-
170
- combinedPrompt += `\n${getFrameworkPrompt(framework)}
171
-
172
- Requirements:
173
- 1. Match the visual design exactly
174
- 2. Extract design tokens from JSON if provided
175
- 3. Use CSS variables from stylesheets if provided
176
- 4. Create separate component files for each major UI section
177
- 5. Make it responsive (mobile-first)
178
- 6. Include accessibility attributes
179
-
180
- Output complete component code.`;
181
-
182
- return askGemini(combinedPrompt);
183
- }
184
-
185
- // ============================================
186
- // CLI
187
- // ============================================
188
-
189
- async function main() {
190
- const args = process.argv.slice(2);
191
-
192
- const options = {
193
- image: null,
194
- html: null,
195
- designFolder: null,
196
- framework: 'react',
197
- output: './generated',
198
- };
199
-
200
- for (let i = 0; i < args.length; i++) {
201
- switch (args[i]) {
202
- case '--image':
203
- options.image = args[++i];
204
- break;
205
- case '--html':
206
- options.html = args[++i];
207
- break;
208
- case '--design-folder':
209
- case '--folder':
210
- options.designFolder = args[++i];
211
- break;
212
- case '--framework':
213
- case '-f':
214
- options.framework = args[++i];
215
- break;
216
- case '--output':
217
- case '-o':
218
- options.output = args[++i];
219
- break;
220
- case '--help':
221
- case '-h':
222
- console.log(`
223
- Gemini UI Code Generator
224
-
225
- Usage:
226
- node gemini-ui-gen.js --image ./design.png --framework react
227
- node gemini-ui-gen.js --html ./mockup.html --framework vue
228
- node gemini-ui-gen.js --design-folder ./design/ --framework react
229
-
230
- Options:
231
- --image <path> Image file to analyze
232
- --html <path> HTML mockup to convert
233
- --design-folder <path> Folder with design files
234
- --framework <name> Target framework (react, vue, svelte, html)
235
- --output <path> Output directory
236
- --help Show this help
237
- `);
238
- process.exit(0);
239
- }
240
- }
241
-
242
- console.log(`🤖 Gemini UI Generator`);
243
- console.log(`📦 Framework: ${options.framework}`);
244
-
245
- try {
246
- let result;
247
-
248
- if (options.image) {
249
- console.log(`\n📷 Analyzing: ${options.image}\n`);
250
- result = await generateUIFromImage(options.image, options.framework);
251
- } else if (options.html) {
252
- console.log(`\n📄 Converting: ${options.html}\n`);
253
- result = await generateUIFromHTML(options.html, options.framework);
254
- } else if (options.designFolder) {
255
- console.log(`\n📂 Analyzing folder: ${options.designFolder}\n`);
256
- result = await analyzeDesignFolder(options.designFolder, options.framework);
257
- } else {
258
- console.error('❌ No input specified. Use --image, --html, or --design-folder');
259
- process.exit(1);
260
- }
261
-
262
- console.log('\n' + '='.repeat(60) + '\n');
263
- console.log(result);
264
- console.log('\n' + '='.repeat(60));
265
-
266
- if (options.output && result) {
267
- if (!fs.existsSync(options.output)) {
268
- fs.mkdirSync(options.output, { recursive: true });
269
- }
270
- const outputFile = path.join(options.output, `generated-${Date.now()}.txt`);
271
- fs.writeFileSync(outputFile, result);
272
- console.log(`\n✅ Output saved to: ${outputFile}`);
273
- }
274
-
275
- } catch (error) {
276
- console.error(`\n❌ Error: ${error.message}`);
277
- process.exit(1);
278
- }
279
- }
280
-
281
- main();
@@ -1,474 +0,0 @@
1
- #!/usr/bin/env node
2
- /**
3
- * Brand Assets Generator
4
- * Gemini Image API를 사용하여 앱 아이콘/파비콘 자동 생성
5
- *
6
- * Usage:
7
- * node generate-brand-assets.js --name "AppName" --color "#2F6BFF" --style "modern" --output "./public"
8
- * node generate-brand-assets.js --spec ".claude/vibe/specs/feature.md" --output "./public"
9
- */
10
-
11
- import fs from 'fs';
12
- import path from 'path';
13
- import os from 'os';
14
- import https from 'https';
15
- import { execSync } from 'child_process';
16
-
17
- // ============================================
18
- // Configuration
19
- // ============================================
20
-
21
- const CONFIG_PATH = path.join(os.homedir(), '.config', 'vibe', 'gemini.json');
22
-
23
- const ICON_SIZES = {
24
- 'favicon-16x16.png': 16,
25
- 'favicon-32x32.png': 32,
26
- 'apple-touch-icon.png': 180,
27
- 'android-chrome-192x192.png': 192,
28
- 'android-chrome-512x512.png': 512,
29
- };
30
-
31
- // ============================================
32
- // Gemini API
33
- // ============================================
34
-
35
- function getGeminiApiKey() {
36
- // 1. Environment variable
37
- if (process.env.GEMINI_API_KEY) {
38
- return process.env.GEMINI_API_KEY;
39
- }
40
-
41
- // 2. Config file
42
- if (fs.existsSync(CONFIG_PATH)) {
43
- try {
44
- const config = JSON.parse(fs.readFileSync(CONFIG_PATH, 'utf8'));
45
- if (config.apiKey) return config.apiKey;
46
- } catch {
47
- // ignore
48
- }
49
- }
50
-
51
- return null;
52
- }
53
-
54
- async function generateImageWithGemini(prompt, apiKey) {
55
- // Nano Banana (Gemini 2.5 Flash Image) - fast image generation for icons/logos
56
- // For professional assets, use gemini-3-pro-image-preview (Nano Banana Pro)
57
- const url = `https://generativelanguage.googleapis.com/v1beta/models/gemini-2.5-flash-image:generateContent?key=${apiKey}`;
58
-
59
- const requestBody = {
60
- contents: [{
61
- parts: [{
62
- text: `Generate an app icon image. ${prompt}
63
-
64
- Requirements:
65
- - Square format (1:1 aspect ratio)
66
- - Simple, recognizable design
67
- - Works well at small sizes
68
- - No text or letters in the icon
69
- - Professional and modern look
70
- - Single focal element on solid or gradient background`
71
- }]
72
- }],
73
- generationConfig: {
74
- responseModalities: ['TEXT', 'IMAGE'],
75
- }
76
- };
77
-
78
- return new Promise((resolve, reject) => {
79
- const req = https.request(url, {
80
- method: 'POST',
81
- headers: {
82
- 'Content-Type': 'application/json',
83
- }
84
- }, (res) => {
85
- let data = '';
86
- res.on('data', chunk => data += chunk);
87
- res.on('end', () => {
88
- try {
89
- const result = JSON.parse(data);
90
- if (result.error) {
91
- reject(new Error(result.error.message));
92
- return;
93
- }
94
-
95
- // Find image part in response
96
- const parts = result.candidates?.[0]?.content?.parts || [];
97
- for (const part of parts) {
98
- if (part.inlineData?.mimeType?.startsWith('image/')) {
99
- resolve({
100
- data: Buffer.from(part.inlineData.data, 'base64'),
101
- mimeType: part.inlineData.mimeType
102
- });
103
- return;
104
- }
105
- }
106
-
107
- reject(new Error('No image in response'));
108
- } catch (e) {
109
- reject(e);
110
- }
111
- });
112
- });
113
-
114
- req.on('error', reject);
115
- req.write(JSON.stringify(requestBody));
116
- req.end();
117
- });
118
- }
119
-
120
- // ============================================
121
- // Image Processing
122
- // ============================================
123
-
124
- function resizeImage(inputPath, outputPath, size) {
125
- // Try sharp via npx, fallback to sips (macOS) or convert (ImageMagick)
126
- try {
127
- // Check if sharp is available
128
- execSync(`npx sharp-cli resize ${size} ${size} -i "${inputPath}" -o "${outputPath}"`, {
129
- stdio: 'pipe'
130
- });
131
- return true;
132
- } catch {
133
- // Fallback: macOS sips
134
- if (process.platform === 'darwin') {
135
- try {
136
- execSync(`sips -z ${size} ${size} "${inputPath}" --out "${outputPath}"`, {
137
- stdio: 'pipe'
138
- });
139
- return true;
140
- } catch {
141
- // ignore
142
- }
143
- }
144
-
145
- // Fallback: ImageMagick convert
146
- try {
147
- execSync(`convert "${inputPath}" -resize ${size}x${size} "${outputPath}"`, {
148
- stdio: 'pipe'
149
- });
150
- return true;
151
- } catch {
152
- // ignore
153
- }
154
- }
155
-
156
- return false;
157
- }
158
-
159
- function createFavicon(inputPath, outputPath) {
160
- // Create ICO file with multiple sizes
161
- try {
162
- // Try ImageMagick
163
- execSync(`convert "${inputPath}" -define icon:auto-resize=48,32,16 "${outputPath}"`, {
164
- stdio: 'pipe'
165
- });
166
- return true;
167
- } catch {
168
- // Fallback: just copy 32x32 as ico
169
- const png32 = outputPath.replace('favicon.ico', 'favicon-32x32.png');
170
- if (fs.existsSync(png32)) {
171
- fs.copyFileSync(png32, outputPath);
172
- return true;
173
- }
174
- }
175
- return false;
176
- }
177
-
178
- // ============================================
179
- // SPEC Parsing
180
- // ============================================
181
-
182
- function parseSpecForBrand(specPath) {
183
- if (!fs.existsSync(specPath)) {
184
- return null;
185
- }
186
-
187
- const content = fs.readFileSync(specPath, 'utf8');
188
- const brand = {
189
- name: null,
190
- color: null,
191
- style: null,
192
- concept: null
193
- };
194
-
195
- // Extract app name from title or context
196
- const titleMatch = content.match(/^#\s+(.+?)(?:\s+SPEC)?$/m);
197
- if (titleMatch) {
198
- brand.name = titleMatch[1].trim();
199
- }
200
-
201
- // Extract from context section
202
- const contextMatch = content.match(/<context>([\s\S]*?)<\/context>/i);
203
- if (contextMatch) {
204
- const context = contextMatch[1];
205
-
206
- // App Name
207
- const nameMatch = context.match(/App\s*Name[:\s]+([^\n]+)/i);
208
- if (nameMatch) brand.name = nameMatch[1].trim();
209
-
210
- // Primary Color
211
- const colorMatch = context.match(/Primary\s*Color[:\s]+(#[0-9A-Fa-f]{6}|#[0-9A-Fa-f]{3})/i);
212
- if (colorMatch) brand.color = colorMatch[1];
213
-
214
- // Style
215
- const styleMatch = context.match(/Style[:\s]+([^\n]+)/i);
216
- if (styleMatch) brand.style = styleMatch[1].trim();
217
-
218
- // Icon Concept
219
- const conceptMatch = context.match(/Icon\s*Concept[:\s]+([^\n]+)/i);
220
- if (conceptMatch) brand.concept = conceptMatch[1].trim();
221
- }
222
-
223
- // Fallback: extract from any brand-related content
224
- if (!brand.color) {
225
- const anyColor = content.match(/#([0-9A-Fa-f]{6}|[0-9A-Fa-f]{3})\b/);
226
- if (anyColor) brand.color = '#' + anyColor[1];
227
- }
228
-
229
- return brand;
230
- }
231
-
232
- // ============================================
233
- // Prompt Generation
234
- // ============================================
235
-
236
- function buildIconPrompt(brand) {
237
- const parts = [];
238
-
239
- if (brand.name) {
240
- parts.push(`App icon for "${brand.name}"`);
241
- } else {
242
- parts.push('Modern app icon');
243
- }
244
-
245
- if (brand.concept) {
246
- parts.push(`Concept: ${brand.concept}`);
247
- }
248
-
249
- if (brand.style) {
250
- parts.push(`Style: ${brand.style}`);
251
- } else {
252
- parts.push('Style: Modern, minimalist, professional');
253
- }
254
-
255
- if (brand.color) {
256
- parts.push(`Primary color: ${brand.color}`);
257
- }
258
-
259
- return parts.join('. ');
260
- }
261
-
262
- // ============================================
263
- // Fallback: Text Monogram
264
- // ============================================
265
-
266
- function generateFallbackIcon(name, color, outputPath) {
267
- // Generate simple SVG monogram
268
- const initial = (name || 'A')[0].toUpperCase();
269
- const bgColor = color || '#4A90D9';
270
-
271
- const svg = `<?xml version="1.0" encoding="UTF-8"?>
272
- <svg width="512" height="512" viewBox="0 0 512 512" xmlns="http://www.w3.org/2000/svg">
273
- <rect width="512" height="512" rx="64" fill="${bgColor}"/>
274
- <text x="256" y="320" font-family="Arial, sans-serif" font-size="280" font-weight="bold" fill="white" text-anchor="middle">${initial}</text>
275
- </svg>`;
276
-
277
- const svgPath = outputPath.replace(/\.(png|ico)$/, '.svg');
278
- fs.writeFileSync(svgPath, svg);
279
-
280
- // Convert SVG to PNG if possible
281
- try {
282
- execSync(`convert "${svgPath}" -resize 512x512 "${outputPath}"`, { stdio: 'pipe' });
283
- fs.unlinkSync(svgPath);
284
- return true;
285
- } catch {
286
- // Keep SVG as fallback
287
- console.log(` Created SVG fallback: ${svgPath}`);
288
- return false;
289
- }
290
- }
291
-
292
- // ============================================
293
- // Manifest Generation
294
- // ============================================
295
-
296
- function generateWebManifest(outputDir, name) {
297
- const manifest = {
298
- name: name || 'App',
299
- short_name: name || 'App',
300
- icons: [
301
- { src: '/android-chrome-192x192.png', sizes: '192x192', type: 'image/png' },
302
- { src: '/android-chrome-512x512.png', sizes: '512x512', type: 'image/png' }
303
- ],
304
- theme_color: '#ffffff',
305
- background_color: '#ffffff',
306
- display: 'standalone'
307
- };
308
-
309
- const manifestPath = path.join(outputDir, 'site.webmanifest');
310
- fs.writeFileSync(manifestPath, JSON.stringify(manifest, null, 2));
311
- return manifestPath;
312
- }
313
-
314
- // ============================================
315
- // Main
316
- // ============================================
317
-
318
- async function main() {
319
- const args = process.argv.slice(2);
320
-
321
- // Parse arguments
322
- let name = null;
323
- let color = null;
324
- let style = null;
325
- let specPath = null;
326
- let outputDir = './public';
327
- let force = false;
328
-
329
- for (let i = 0; i < args.length; i++) {
330
- switch (args[i]) {
331
- case '--name':
332
- name = args[++i];
333
- break;
334
- case '--color':
335
- color = args[++i];
336
- break;
337
- case '--style':
338
- style = args[++i];
339
- break;
340
- case '--spec':
341
- specPath = args[++i];
342
- break;
343
- case '--output':
344
- outputDir = args[++i];
345
- break;
346
- case '--force':
347
- case '--regenerate':
348
- force = true;
349
- break;
350
- case '--help':
351
- console.log(`
352
- Brand Assets Generator
353
-
354
- Usage:
355
- node generate-brand-assets.js [options]
356
-
357
- Options:
358
- --name <name> App name
359
- --color <hex> Primary color (e.g., #2F6BFF)
360
- --style <style> Design style keywords
361
- --spec <path> Path to SPEC file to extract brand info
362
- --output <dir> Output directory (default: ./public)
363
- --force Regenerate even if icons exist
364
-
365
- Examples:
366
- node generate-brand-assets.js --name "MyApp" --color "#FF5722" --output "./public"
367
- node generate-brand-assets.js --spec ".claude/vibe/specs/my-feature.md"
368
- `);
369
- process.exit(0);
370
- }
371
- }
372
-
373
- // Check if icons already exist
374
- const faviconPath = path.join(outputDir, 'favicon.ico');
375
- if (fs.existsSync(faviconPath) && !force) {
376
- console.log('Brand assets already exist. Use --force to regenerate.');
377
- process.exit(0);
378
- }
379
-
380
- // Parse SPEC if provided
381
- if (specPath) {
382
- const brand = parseSpecForBrand(specPath);
383
- if (brand) {
384
- name = name || brand.name;
385
- color = color || brand.color;
386
- style = style || brand.style;
387
- }
388
- }
389
-
390
- // Ensure output directory
391
- if (!fs.existsSync(outputDir)) {
392
- fs.mkdirSync(outputDir, { recursive: true });
393
- }
394
-
395
- // Check Gemini API key
396
- const apiKey = getGeminiApiKey();
397
-
398
- console.log('Generating brand assets...');
399
- console.log(` Name: ${name || '(not specified)'}`);
400
- console.log(` Color: ${color || '(not specified)'}`);
401
- console.log(` Style: ${style || '(not specified)'}`);
402
- console.log(` Output: ${outputDir}`);
403
- console.log(` Gemini: ${apiKey ? 'configured' : 'not configured'}`);
404
- console.log('');
405
-
406
- const masterIconPath = path.join(outputDir, 'icon-master.png');
407
- let generated = false;
408
-
409
- // Try Gemini Image API
410
- if (apiKey) {
411
- try {
412
- const prompt = buildIconPrompt({ name, color, style });
413
- console.log('Generating icon with Gemini...');
414
- console.log(` Prompt: ${prompt}`);
415
-
416
- const image = await generateImageWithGemini(prompt, apiKey);
417
- fs.writeFileSync(masterIconPath, image.data);
418
- console.log(' Master icon generated successfully');
419
- generated = true;
420
- } catch (err) {
421
- console.log(` Gemini generation failed: ${err.message}`);
422
- console.log(' Falling back to text monogram...');
423
- }
424
- }
425
-
426
- // Fallback to monogram
427
- if (!generated) {
428
- console.log('Generating fallback monogram icon...');
429
- generateFallbackIcon(name, color, masterIconPath);
430
- if (fs.existsSync(masterIconPath)) {
431
- generated = true;
432
- }
433
- }
434
-
435
- if (!generated) {
436
- console.error('Failed to generate icon');
437
- process.exit(1);
438
- }
439
-
440
- // Resize to all required sizes
441
- console.log('Resizing to platform sizes...');
442
- for (const [filename, size] of Object.entries(ICON_SIZES)) {
443
- const outPath = path.join(outputDir, filename);
444
- if (resizeImage(masterIconPath, outPath, size)) {
445
- console.log(` Created: ${filename}`);
446
- } else {
447
- console.log(` Warning: Could not create ${filename}`);
448
- }
449
- }
450
-
451
- // Create favicon.ico
452
- console.log('Creating favicon.ico...');
453
- if (createFavicon(masterIconPath, faviconPath)) {
454
- console.log(' Created: favicon.ico');
455
- }
456
-
457
- // Generate web manifest
458
- const manifestPath = generateWebManifest(outputDir, name);
459
- console.log(` Created: ${path.basename(manifestPath)}`);
460
-
461
- // Cleanup master icon
462
- if (fs.existsSync(masterIconPath)) {
463
- fs.unlinkSync(masterIconPath);
464
- }
465
-
466
- console.log('');
467
- console.log('Brand assets generation complete!');
468
- console.log(`Output directory: ${outputDir}`);
469
- }
470
-
471
- main().catch(err => {
472
- console.error('Error:', err.message);
473
- process.exit(1);
474
- });