@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.
- package/agents/ui-previewer.md +14 -22
- package/commands/vibe.run.md +1 -12
- package/commands/vibe.spec.md +22 -0
- package/commands/vibe.utils.md +1 -1
- package/dist/lib/gemini-api.d.ts +13 -2
- package/dist/lib/gemini-api.d.ts.map +1 -1
- package/dist/lib/gemini-api.js +140 -3
- package/dist/lib/gemini-api.js.map +1 -1
- package/dist/tools/memory/startSession.js +1 -1
- package/hooks/scripts/llm-orchestrate.js +80 -1
- package/package.json +1 -1
- package/skills/brand-assets.md +3 -7
- package/hooks/scripts/gemini-ui-gen.js +0 -281
- package/hooks/scripts/generate-brand-assets.js +0 -474
package/agents/ui-previewer.md
CHANGED
|
@@ -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
|
-
|
|
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
|
-
|
|
108
|
+
##### B. UI Code Generation (from design files)
|
|
110
109
|
|
|
111
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
|
package/commands/vibe.run.md
CHANGED
|
@@ -959,20 +959,9 @@ Brand:
|
|
|
959
959
|
|
|
960
960
|
**Manual Generation:**
|
|
961
961
|
```bash
|
|
962
|
-
node hooks/scripts/
|
|
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)
|
package/commands/vibe.spec.md
CHANGED
|
@@ -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
|
package/commands/vibe.utils.md
CHANGED
|
@@ -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**:
|
|
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:**
|
package/dist/lib/gemini-api.d.ts
CHANGED
|
@@ -75,10 +75,21 @@ interface ImageGenerationResult {
|
|
|
75
75
|
mimeType: string;
|
|
76
76
|
}
|
|
77
77
|
/**
|
|
78
|
-
* Gemini
|
|
79
|
-
* API Key
|
|
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":"AAAA;;;;GAIG;AAoFH,UAAU,eAAe;IACvB,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;IACpB,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,UAAU,WAAW;IACnB,IAAI,EAAE,MAAM,GAAG,WAAW,GAAG,QAAQ,GAAG,OAAO,CAAC;IAChD,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,UAAU,WAAW;IACnB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,QAAQ,CAAC,EAAE,WAAW,EAAE,CAAC;IACzB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAED,UAAU,YAAY;IACpB,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,EAAE,MAAM,CAAC;IACd,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,KAAK,CAAC,EAAE,OAAO,CAAC;CACjB;AAqBD,eAAO,MAAM,aAAa,EAAE,MAAM,CAAC,MAAM,EAAE,eAAe,CAsBzD,CAAC;AAGF,eAAO,MAAM,aAAa,mBAAmB,CAAC;AA2Q9C;;GAEG;AACH,wBAAsB,IAAI,CAAC,OAAO,EAAE,WAAW,GAAG,OAAO,CAAC,YAAY,CAAC,CAyBtE;AAED;;GAEG;AACH,wBAAuB,UAAU,CAAC,OAAO,EAAE,WAAW,GAAG,cAAc,CAAC,YAAY,CAAC,CAIpF;AAED;;GAEG;AACH,wBAAgB,kBAAkB,IAAI,eAAe,EAAE,CAEtD;AAED;;GAEG;AACH,wBAAgB,YAAY,CAAC,OAAO,EAAE,MAAM,GAAG,eAAe,GAAG,IAAI,CAEpE;AAED;;GAEG;AACH,wBAAsB,GAAG,CAAC,MAAM,EAAE,MAAM,EAAE,OAAO,GAAE,IAAI,CAAC,WAAW,EAAE,UAAU,CAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAMtG;AAED;;GAEG;AACH,wBAAsB,QAAQ,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAM9D;AAED;;GAEG;AACH,wBAAsB,SAAS,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAQ/D;AAED;;GAEG;AACH,wBAAsB,cAAc,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAOpE;AAED;;GAEG;AACH,wBAAsB,SAAS,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAO/D;AAMD,UAAU,sBAAsB;IAC9B,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,UAAU,qBAAqB;IAC7B,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED;;;GAGG;AACH,wBAAsB,aAAa,CACjC,MAAM,EAAE,MAAM,EACd,OAAO,GAAE,sBAA2B,GACnC,OAAO,CAAC,qBAAqB,CAAC,CAqEhC;
|
|
1
|
+
{"version":3,"file":"gemini-api.d.ts","sourceRoot":"","sources":["../../src/lib/gemini-api.ts"],"names":[],"mappings":"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"}
|
package/dist/lib/gemini-api.js
CHANGED
|
@@ -410,8 +410,8 @@ export async function analyzeUI(prompt) {
|
|
|
410
410
|
});
|
|
411
411
|
}
|
|
412
412
|
/**
|
|
413
|
-
* Gemini
|
|
414
|
-
* API Key
|
|
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-
|
|
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(
|
|
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
package/skills/brand-assets.md
CHANGED
|
@@ -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 (
|
|
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
|
|
106
|
-
node hooks/scripts/
|
|
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
|
-
});
|