opencode-nanobanana 0.1.0
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/.ralph-events.json +151 -0
- package/.ralph-last-branch +1 -0
- package/.ralph-monitor-state.json +7 -0
- package/.ralph-monitor.pid +1 -0
- package/.ralph-timing.json +26 -0
- package/README.md +708 -0
- package/dist/index.d.ts +18 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +21 -0
- package/dist/index.js.map +1 -0
- package/dist/platforms/android.d.ts +94 -0
- package/dist/platforms/android.d.ts.map +1 -0
- package/dist/platforms/android.js +123 -0
- package/dist/platforms/android.js.map +1 -0
- package/dist/platforms/ios.d.ts +51 -0
- package/dist/platforms/ios.d.ts.map +1 -0
- package/dist/platforms/ios.js +149 -0
- package/dist/platforms/ios.js.map +1 -0
- package/dist/platforms/macos.d.ts +33 -0
- package/dist/platforms/macos.d.ts.map +1 -0
- package/dist/platforms/macos.js +50 -0
- package/dist/platforms/macos.js.map +1 -0
- package/dist/platforms/watchos.d.ts +36 -0
- package/dist/platforms/watchos.d.ts.map +1 -0
- package/dist/platforms/watchos.js +113 -0
- package/dist/platforms/watchos.js.map +1 -0
- package/dist/platforms/web.d.ts +64 -0
- package/dist/platforms/web.d.ts.map +1 -0
- package/dist/platforms/web.js +96 -0
- package/dist/platforms/web.js.map +1 -0
- package/dist/providers/gemini.d.ts +41 -0
- package/dist/providers/gemini.d.ts.map +1 -0
- package/dist/providers/gemini.js +177 -0
- package/dist/providers/gemini.js.map +1 -0
- package/dist/tools/analyze/compare.d.ts +12 -0
- package/dist/tools/analyze/compare.d.ts.map +1 -0
- package/dist/tools/analyze/compare.js +83 -0
- package/dist/tools/analyze/compare.js.map +1 -0
- package/dist/tools/analyze/mockup.d.ts +12 -0
- package/dist/tools/analyze/mockup.d.ts.map +1 -0
- package/dist/tools/analyze/mockup.js +88 -0
- package/dist/tools/analyze/mockup.js.map +1 -0
- package/dist/tools/analyze/screenshot.d.ts +12 -0
- package/dist/tools/analyze/screenshot.d.ts.map +1 -0
- package/dist/tools/analyze/screenshot.js +61 -0
- package/dist/tools/analyze/screenshot.js.map +1 -0
- package/dist/tools/app-assets/app-icon.d.ts +9 -0
- package/dist/tools/app-assets/app-icon.d.ts.map +1 -0
- package/dist/tools/app-assets/app-icon.js +133 -0
- package/dist/tools/app-assets/app-icon.js.map +1 -0
- package/dist/tools/app-assets/device-mockup.d.ts +9 -0
- package/dist/tools/app-assets/device-mockup.d.ts.map +1 -0
- package/dist/tools/app-assets/device-mockup.js +139 -0
- package/dist/tools/app-assets/device-mockup.js.map +1 -0
- package/dist/tools/app-assets/launch-images.d.ts +3 -0
- package/dist/tools/app-assets/launch-images.d.ts.map +1 -0
- package/dist/tools/app-assets/launch-images.js +171 -0
- package/dist/tools/app-assets/launch-images.js.map +1 -0
- package/dist/tools/app-assets/resize-devices.d.ts +14 -0
- package/dist/tools/app-assets/resize-devices.d.ts.map +1 -0
- package/dist/tools/app-assets/resize-devices.js +296 -0
- package/dist/tools/app-assets/resize-devices.js.map +1 -0
- package/dist/tools/app-assets/screenshots.d.ts +14 -0
- package/dist/tools/app-assets/screenshots.d.ts.map +1 -0
- package/dist/tools/app-assets/screenshots.js +186 -0
- package/dist/tools/app-assets/screenshots.js.map +1 -0
- package/dist/tools/core/edit-image.d.ts +12 -0
- package/dist/tools/core/edit-image.d.ts.map +1 -0
- package/dist/tools/core/edit-image.js +102 -0
- package/dist/tools/core/edit-image.js.map +1 -0
- package/dist/tools/core/generate-image.d.ts +12 -0
- package/dist/tools/core/generate-image.d.ts.map +1 -0
- package/dist/tools/core/generate-image.js +96 -0
- package/dist/tools/core/generate-image.js.map +1 -0
- package/dist/tools/core/restore-image.d.ts +12 -0
- package/dist/tools/core/restore-image.d.ts.map +1 -0
- package/dist/tools/core/restore-image.js +104 -0
- package/dist/tools/core/restore-image.js.map +1 -0
- package/dist/tools/design/mockup-to-code.d.ts +3 -0
- package/dist/tools/design/mockup-to-code.d.ts.map +1 -0
- package/dist/tools/design/mockup-to-code.js +311 -0
- package/dist/tools/design/mockup-to-code.js.map +1 -0
- package/dist/tools/design/sketch-to-code.d.ts +3 -0
- package/dist/tools/design/sketch-to-code.d.ts.map +1 -0
- package/dist/tools/design/sketch-to-code.js +325 -0
- package/dist/tools/design/sketch-to-code.js.map +1 -0
- package/dist/tools/docs/architecture-diagram.d.ts +12 -0
- package/dist/tools/docs/architecture-diagram.d.ts.map +1 -0
- package/dist/tools/docs/architecture-diagram.js +179 -0
- package/dist/tools/docs/architecture-diagram.js.map +1 -0
- package/dist/tools/docs/readme-banner.d.ts +6 -0
- package/dist/tools/docs/readme-banner.d.ts.map +1 -0
- package/dist/tools/docs/readme-banner.js +108 -0
- package/dist/tools/docs/readme-banner.js.map +1 -0
- package/dist/tools/docs/sequence-diagram.d.ts +12 -0
- package/dist/tools/docs/sequence-diagram.d.ts.map +1 -0
- package/dist/tools/docs/sequence-diagram.js +161 -0
- package/dist/tools/docs/sequence-diagram.js.map +1 -0
- package/dist/tools/docs/social-preview.d.ts +11 -0
- package/dist/tools/docs/social-preview.d.ts.map +1 -0
- package/dist/tools/docs/social-preview.js +111 -0
- package/dist/tools/docs/social-preview.js.map +1 -0
- package/dist/tools/video/extend-video.d.ts +14 -0
- package/dist/tools/video/extend-video.d.ts.map +1 -0
- package/dist/tools/video/extend-video.js +39 -0
- package/dist/tools/video/extend-video.js.map +1 -0
- package/dist/tools/video/generate-video.d.ts +14 -0
- package/dist/tools/video/generate-video.d.ts.map +1 -0
- package/dist/tools/video/generate-video.js +39 -0
- package/dist/tools/video/generate-video.js.map +1 -0
- package/dist/tools/video/image-to-video.d.ts +15 -0
- package/dist/tools/video/image-to-video.d.ts.map +1 -0
- package/dist/tools/video/image-to-video.js +42 -0
- package/dist/tools/video/image-to-video.js.map +1 -0
- package/dist/tools/video/storyboard-video.d.ts +91 -0
- package/dist/tools/video/storyboard-video.d.ts.map +1 -0
- package/dist/tools/video/storyboard-video.js +230 -0
- package/dist/tools/video/storyboard-video.js.map +1 -0
- package/dist/utils/ffmpeg.d.ts +30 -0
- package/dist/utils/ffmpeg.d.ts.map +1 -0
- package/dist/utils/ffmpeg.js +205 -0
- package/dist/utils/ffmpeg.js.map +1 -0
- package/dist/utils/file-handler.d.ts +7 -0
- package/dist/utils/file-handler.d.ts.map +1 -0
- package/dist/utils/file-handler.js +10 -0
- package/dist/utils/file-handler.js.map +1 -0
- package/dist/utils/image-processing.d.ts +7 -0
- package/dist/utils/image-processing.d.ts.map +1 -0
- package/dist/utils/image-processing.js +10 -0
- package/dist/utils/image-processing.js.map +1 -0
- package/docs/PLUGIN-VERIFICATION.md +182 -0
- package/logs/notifications.jsonl +46 -0
- package/package.json +61 -0
- package/prd.json +216 -0
- package/progress.txt +145 -0
- package/ralph-report.html +297 -0
- package/src/index.ts +23 -0
- package/src/platforms/android/.gitkeep +0 -0
- package/src/platforms/ios/.gitkeep +0 -0
- package/src/platforms/web/.gitkeep +0 -0
- package/src/providers/.gitkeep +0 -0
- package/src/providers/gemini.ts +288 -0
- package/src/tools/core/.gitkeep +0 -0
- package/src/tools/platform/.gitkeep +0 -0
- package/src/tools/video/extend-video.ts +71 -0
- package/src/tools/video/generate-video.ts +70 -0
- package/src/tools/video/image-to-video.ts +76 -0
- package/src/tools/video/storyboard-video.ts +325 -0
- package/src/utils/.gitkeep +0 -0
- package/src/utils/ffmpeg.ts +266 -0
- package/src/utils/file-handler.ts +10 -0
- package/src/utils/image-processing.ts +10 -0
- package/templates/.gitkeep +0 -0
- package/test-analyze-screenshot.ts +50 -0
- package/test-app-icons.ts +55 -0
- package/test-cat-sunset.ts +30 -0
- package/test-full-plugin.ts +88 -0
- package/test-icon-gen.ts +30 -0
- package/test-output/test-edit.png +0 -0
- package/test-output/test-generate.png +0 -0
- package/test-output/test-video.mp4 +0 -0
- package/test-plugin-load.js +45 -0
- package/test-princess-emma-continue.ts +35 -0
- package/test-princess-emma-full.ts +38 -0
- package/test-princess-emma-short.ts +32 -0
- package/test-princess-emma-with-reference.ts +34 -0
- package/test-princess-emma.ts +38 -0
- package/test-product-ad.ts +66 -0
- package/test-ralph-droid.ts +30 -0
- package/test-social-preview.ts +61 -0
- package/test-veo31-live.ts +187 -0
- package/test-video-gen.ts +40 -0
- package/test-video-veo.ts +73 -0
- package/test-zurich-video.ts +64 -0
- package/tests/.gitkeep +0 -0
- package/tests/providers/gemini.test.ts +388 -0
- package/tests/utils/ffmpeg.test.ts +328 -0
- package/tests/video/storyboard.test.ts +469 -0
- package/tsconfig.json +25 -0
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Analyze Mockup Tool
|
|
3
|
+
*
|
|
4
|
+
* Extracts design specifications from mockup images including colors, typography,
|
|
5
|
+
* spacing, and component structure. Useful for design-to-code workflows.
|
|
6
|
+
*/
|
|
7
|
+
import { type ToolDefinition } from '@opencode-ai/plugin/tool';
|
|
8
|
+
/**
|
|
9
|
+
* Tool definition for analyze_mockup
|
|
10
|
+
*/
|
|
11
|
+
export declare const analyzeMockupTool: ToolDefinition;
|
|
12
|
+
//# sourceMappingURL=mockup.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"mockup.d.ts","sourceRoot":"","sources":["../../../src/tools/analyze/mockup.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAQ,KAAK,cAAc,EAAE,MAAM,0BAA0B,CAAC;AAkFrE;;GAEG;AACH,eAAO,MAAM,iBAAiB,EAAE,cA2C9B,CAAC"}
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Analyze Mockup Tool
|
|
3
|
+
*
|
|
4
|
+
* Extracts design specifications from mockup images including colors, typography,
|
|
5
|
+
* spacing, and component structure. Useful for design-to-code workflows.
|
|
6
|
+
*/
|
|
7
|
+
import { tool } from '@opencode-ai/plugin/tool';
|
|
8
|
+
import { GeminiProvider } from '../../providers/gemini.js';
|
|
9
|
+
import { loadImage } from '../../utils/file-handler.js';
|
|
10
|
+
/**
|
|
11
|
+
* Tool args schema
|
|
12
|
+
*/
|
|
13
|
+
const analyzeMockupArgs = {
|
|
14
|
+
imagePath: tool.schema.string()
|
|
15
|
+
.describe('Path to the design mockup image to analyze'),
|
|
16
|
+
extractColors: tool.schema.boolean()
|
|
17
|
+
.optional()
|
|
18
|
+
.default(true)
|
|
19
|
+
.describe('Whether to extract color palette from the design (default: true)'),
|
|
20
|
+
extractSpacing: tool.schema.boolean()
|
|
21
|
+
.optional()
|
|
22
|
+
.default(true)
|
|
23
|
+
.describe('Whether to extract spacing and layout measurements (default: true)')
|
|
24
|
+
};
|
|
25
|
+
/**
|
|
26
|
+
* Build comprehensive design analysis prompt
|
|
27
|
+
*/
|
|
28
|
+
function buildDesignAnalysisPrompt(extractColors, extractSpacing) {
|
|
29
|
+
const sections = [
|
|
30
|
+
'Analyze this design mockup and extract detailed design specifications.'
|
|
31
|
+
];
|
|
32
|
+
// Always extract component structure and typography
|
|
33
|
+
sections.push('\n## Component Structure', '- Identify all UI components (buttons, inputs, cards, navigation, etc.)', '- Describe the visual hierarchy', '- Note component states (hover, active, disabled) if visible');
|
|
34
|
+
sections.push('\n## Typography', '- Font families used (or similar web-safe alternatives)', '- Font sizes for headings, body text, captions', '- Font weights and styles', '- Line heights and letter spacing');
|
|
35
|
+
// Conditional: color extraction
|
|
36
|
+
if (extractColors) {
|
|
37
|
+
sections.push('\n## Color Palette', '- Primary, secondary, and accent colors (provide hex codes)', '- Background and surface colors', '- Text colors (body, headings, muted)', '- Border and divider colors', '- Status colors (success, warning, error, info) if present');
|
|
38
|
+
}
|
|
39
|
+
// Conditional: spacing and measurements
|
|
40
|
+
if (extractSpacing) {
|
|
41
|
+
sections.push('\n## Spacing & Layout', '- Margin and padding values (estimate in px or rem)', '- Grid or layout system used', '- Border radius values', '- Shadow specifications', '- Component dimensions and aspect ratios');
|
|
42
|
+
}
|
|
43
|
+
sections.push('\n## Design System Notes', '- Overall design style (modern, minimal, material, iOS, etc.)', '- Notable design patterns or conventions', '- Responsive considerations if visible');
|
|
44
|
+
sections.push('\nProvide specific, actionable values that a developer can use to implement this design.');
|
|
45
|
+
return sections.join('\n');
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* Tool definition for analyze_mockup
|
|
49
|
+
*/
|
|
50
|
+
export const analyzeMockupTool = tool({
|
|
51
|
+
description: 'Extract design specifications from mockup images. Identifies colors, typography, spacing, component structure, and design system details. Perfect for design-to-code workflows.',
|
|
52
|
+
args: analyzeMockupArgs,
|
|
53
|
+
async execute(args, _context) {
|
|
54
|
+
try {
|
|
55
|
+
const { imagePath, extractColors = true, extractSpacing = true } = args;
|
|
56
|
+
// Initialize Gemini provider
|
|
57
|
+
const provider = new GeminiProvider();
|
|
58
|
+
// Load the mockup image
|
|
59
|
+
const imageBuffer = await loadImage(imagePath);
|
|
60
|
+
// Build analysis prompt based on extraction options
|
|
61
|
+
const analysisPrompt = buildDesignAnalysisPrompt(extractColors, extractSpacing);
|
|
62
|
+
// Analyze the mockup using Gemini
|
|
63
|
+
const analysis = await provider.analyzeImage(imageBuffer, analysisPrompt);
|
|
64
|
+
// Build summary of what was extracted
|
|
65
|
+
const extractedFeatures = ['Component Structure', 'Typography'];
|
|
66
|
+
if (extractColors)
|
|
67
|
+
extractedFeatures.push('Color Palette');
|
|
68
|
+
if (extractSpacing)
|
|
69
|
+
extractedFeatures.push('Spacing & Layout');
|
|
70
|
+
return `✓ Design Mockup Analysis Complete
|
|
71
|
+
|
|
72
|
+
Path: ${imagePath}
|
|
73
|
+
Extracted: ${extractedFeatures.join(', ')}
|
|
74
|
+
|
|
75
|
+
${analysis}`;
|
|
76
|
+
}
|
|
77
|
+
catch (error) {
|
|
78
|
+
if (error instanceof Error && error.message.includes('GEMINI_API_KEY')) {
|
|
79
|
+
return '✗ Error: GEMINI_API_KEY is not set. Please configure your API key in environment variables.';
|
|
80
|
+
}
|
|
81
|
+
if (error instanceof Error && (error.message.includes('ENOENT') || error.message.includes('no such file'))) {
|
|
82
|
+
return `✗ Error: Could not load mockup image at path: ${args.imagePath}. Please verify the file exists.`;
|
|
83
|
+
}
|
|
84
|
+
return `✗ Error analyzing mockup: ${error instanceof Error ? error.message : String(error)}`;
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
});
|
|
88
|
+
//# sourceMappingURL=mockup.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"mockup.js","sourceRoot":"","sources":["../../../src/tools/analyze/mockup.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Analyze Screenshot Tool
|
|
3
|
+
*
|
|
4
|
+
* Provides detailed visual analysis of UI screenshots for debugging purposes.
|
|
5
|
+
* Identifies components, layout issues, accessibility concerns, and provides improvement suggestions.
|
|
6
|
+
*/
|
|
7
|
+
import { type ToolDefinition } from '@opencode-ai/plugin/tool';
|
|
8
|
+
/**
|
|
9
|
+
* Tool definition for analyze_screenshot
|
|
10
|
+
*/
|
|
11
|
+
export declare const analyzeScreenshotTool: ToolDefinition;
|
|
12
|
+
//# sourceMappingURL=screenshot.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"screenshot.d.ts","sourceRoot":"","sources":["../../../src/tools/analyze/screenshot.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAQ,KAAK,cAAc,EAAE,MAAM,0BAA0B,CAAC;AAerE;;GAEG;AACH,eAAO,MAAM,qBAAqB,EAAE,cA4ClC,CAAC"}
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Analyze Screenshot Tool
|
|
3
|
+
*
|
|
4
|
+
* Provides detailed visual analysis of UI screenshots for debugging purposes.
|
|
5
|
+
* Identifies components, layout issues, accessibility concerns, and provides improvement suggestions.
|
|
6
|
+
*/
|
|
7
|
+
import { tool } from '@opencode-ai/plugin/tool';
|
|
8
|
+
import { GeminiProvider } from '../../providers/gemini.js';
|
|
9
|
+
import { loadImage } from '../../utils/file-handler.js';
|
|
10
|
+
/**
|
|
11
|
+
* Tool args schema
|
|
12
|
+
*/
|
|
13
|
+
const analyzeScreenshotArgs = {
|
|
14
|
+
imagePath: tool.schema.string()
|
|
15
|
+
.describe('Path to the screenshot image to analyze'),
|
|
16
|
+
question: tool.schema.string()
|
|
17
|
+
.optional()
|
|
18
|
+
.describe('Specific question or focus area for the analysis. If not provided, performs comprehensive UI analysis')
|
|
19
|
+
};
|
|
20
|
+
/**
|
|
21
|
+
* Tool definition for analyze_screenshot
|
|
22
|
+
*/
|
|
23
|
+
export const analyzeScreenshotTool = tool({
|
|
24
|
+
description: 'Analyze UI screenshots for debugging. Identifies components, layout issues, accessibility concerns, and provides improvement suggestions. Optionally accepts a specific question to focus the analysis.',
|
|
25
|
+
args: analyzeScreenshotArgs,
|
|
26
|
+
async execute(args, _context) {
|
|
27
|
+
try {
|
|
28
|
+
const { imagePath, question } = args;
|
|
29
|
+
// Initialize Gemini provider
|
|
30
|
+
const provider = new GeminiProvider();
|
|
31
|
+
// Load the screenshot image
|
|
32
|
+
const imageBuffer = await loadImage(imagePath);
|
|
33
|
+
// Build analysis prompt
|
|
34
|
+
const analysisPrompt = question ||
|
|
35
|
+
'Analyze this UI screenshot in detail. Identify:\n' +
|
|
36
|
+
'1. UI components and their purpose\n' +
|
|
37
|
+
'2. Layout and spacing issues\n' +
|
|
38
|
+
'3. Accessibility concerns (contrast, text size, touch targets)\n' +
|
|
39
|
+
'4. Visual inconsistencies or bugs\n' +
|
|
40
|
+
'5. Suggestions for improvement\n\n' +
|
|
41
|
+
'Provide a clear, structured analysis.';
|
|
42
|
+
// Analyze the screenshot using Gemini
|
|
43
|
+
const analysis = await provider.analyzeImage(imageBuffer, analysisPrompt);
|
|
44
|
+
return `✓ Screenshot Analysis Complete
|
|
45
|
+
|
|
46
|
+
Path: ${imagePath}
|
|
47
|
+
|
|
48
|
+
${analysis}`;
|
|
49
|
+
}
|
|
50
|
+
catch (error) {
|
|
51
|
+
if (error instanceof Error && error.message.includes('GEMINI_API_KEY')) {
|
|
52
|
+
return '✗ Error: GEMINI_API_KEY is not set. Please configure your API key in environment variables.';
|
|
53
|
+
}
|
|
54
|
+
if (error instanceof Error && (error.message.includes('ENOENT') || error.message.includes('no such file'))) {
|
|
55
|
+
return `✗ Error: Could not load screenshot at path: ${args.imagePath}. Please verify the file exists.`;
|
|
56
|
+
}
|
|
57
|
+
return `✗ Error analyzing screenshot: ${error instanceof Error ? error.message : String(error)}`;
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
});
|
|
61
|
+
//# sourceMappingURL=screenshot.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"screenshot.js","sourceRoot":"","sources":["../../../src/tools/analyze/screenshot.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,IAAI,EAAuB,MAAM,0BAA0B,CAAC;AACrE,OAAO,EAAE,cAAc,EAAE,MAAM,2BAA2B,CAAC;AAC3D,OAAO,EAAE,SAAS,EAAE,MAAM,6BAA6B,CAAC;AAExD;;GAEG;AACH,MAAM,qBAAqB,GAAG;IAC5B,SAAS,EAAE,IAAI,CAAC,MAAM,CAAC,MAAM,EAAE;SAC5B,QAAQ,CAAC,yCAAyC,CAAC;IACtD,QAAQ,EAAE,IAAI,CAAC,MAAM,CAAC,MAAM,EAAE;SAC3B,QAAQ,EAAE;SACV,QAAQ,CAAC,uGAAuG,CAAC;CAC5G,CAAC;AAEX;;GAEG;AACH,MAAM,CAAC,MAAM,qBAAqB,GAAmB,IAAI,CAAC;IACxD,WAAW,EAAE,yMAAyM;IAEtN,IAAI,EAAE,qBAAqB;IAE3B,KAAK,CAAC,OAAO,CAAC,IAAI,EAAE,QAAQ;QAC1B,IAAI,CAAC;YACH,MAAM,EAAE,SAAS,EAAE,QAAQ,EAAE,GAAG,IAAI,CAAC;YAErC,6BAA6B;YAC7B,MAAM,QAAQ,GAAG,IAAI,cAAc,EAAE,CAAC;YAEtC,4BAA4B;YAC5B,MAAM,WAAW,GAAG,MAAM,SAAS,CAAC,SAAS,CAAC,CAAC;YAE/C,wBAAwB;YACxB,MAAM,cAAc,GAAG,QAAQ;gBAC7B,mDAAmD;oBACnD,sCAAsC;oBACtC,gCAAgC;oBAChC,kEAAkE;oBAClE,qCAAqC;oBACrC,oCAAoC;oBACpC,uCAAuC,CAAC;YAE1C,sCAAsC;YACtC,MAAM,QAAQ,GAAG,MAAM,QAAQ,CAAC,YAAY,CAAC,WAAW,EAAE,cAAc,CAAC,CAAC;YAE1E,OAAO;;QAEL,SAAS;;EAEf,QAAQ,EAAE,CAAC;QAET,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,IAAI,KAAK,YAAY,KAAK,IAAI,KAAK,CAAC,OAAO,CAAC,QAAQ,CAAC,gBAAgB,CAAC,EAAE,CAAC;gBACvE,OAAO,6FAA6F,CAAC;YACvG,CAAC;YACD,IAAI,KAAK,YAAY,KAAK,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAC,IAAI,KAAK,CAAC,OAAO,CAAC,QAAQ,CAAC,cAAc,CAAC,CAAC,EAAE,CAAC;gBAC3G,OAAO,+CAA+C,IAAI,CAAC,SAAS,kCAAkC,CAAC;YACzG,CAAC;YACD,OAAO,iCAAiC,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE,CAAC;QACnG,CAAC;IACH,CAAC;CACF,CAAC,CAAC"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Generate App Icon Tool
|
|
3
|
+
*
|
|
4
|
+
* Creates complete app icon sets for iOS and Android platforms.
|
|
5
|
+
* Generates 1024x1024 master icon via Gemini, then resizes to all required sizes.
|
|
6
|
+
*/
|
|
7
|
+
import { type ToolDefinition } from '@opencode-ai/plugin/tool';
|
|
8
|
+
export declare const generateAppIcon: ToolDefinition;
|
|
9
|
+
//# sourceMappingURL=app-icon.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"app-icon.d.ts","sourceRoot":"","sources":["../../../src/tools/app-assets/app-icon.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAQ,KAAK,cAAc,EAAE,MAAM,0BAA0B,CAAC;AA6BrE,eAAO,MAAM,eAAe,EAAE,cAsE5B,CAAC"}
|
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Generate App Icon Tool
|
|
3
|
+
*
|
|
4
|
+
* Creates complete app icon sets for iOS and Android platforms.
|
|
5
|
+
* Generates 1024x1024 master icon via Gemini, then resizes to all required sizes.
|
|
6
|
+
*/
|
|
7
|
+
import { tool } from '@opencode-ai/plugin/tool';
|
|
8
|
+
import { GeminiProvider } from '../../providers/gemini.js';
|
|
9
|
+
import { ensureDirectory, getOutputDir } from '../../utils/file-handler.js';
|
|
10
|
+
import { resize } from '../../utils/image-processing.js';
|
|
11
|
+
import { IOS_ICON_SIZES, WATCHOS_ICON_SIZES, CARPLAY_ICON_SIZES, generateContentsJson, } from '../../platforms/ios.js';
|
|
12
|
+
import { ANDROID_ICON_SIZES, generateAdaptiveIconXml, } from '../../platforms/android.js';
|
|
13
|
+
import * as fs from 'fs/promises';
|
|
14
|
+
import * as path from 'path';
|
|
15
|
+
const generateAppIconArgs = {
|
|
16
|
+
prompt: tool.schema.string().describe('Description of the app icon to generate'),
|
|
17
|
+
platforms: tool.schema
|
|
18
|
+
.array(tool.schema.string())
|
|
19
|
+
.optional()
|
|
20
|
+
.describe('Target platforms: ["ios", "android"] or ["ios"] or ["android"]. Defaults to both.'),
|
|
21
|
+
includeWatchOS: tool.schema.boolean().optional().describe('Include watchOS icon sizes. Defaults to false.'),
|
|
22
|
+
includeCarPlay: tool.schema.boolean().optional().describe('Include CarPlay icon sizes. Defaults to false.'),
|
|
23
|
+
outputDir: tool.schema.string().optional().describe('Custom output directory. Defaults to "./generated-assets/app-icons"'),
|
|
24
|
+
};
|
|
25
|
+
export const generateAppIcon = tool({
|
|
26
|
+
description: 'Generate complete app icon sets for iOS and Android from a text prompt. Creates 1024x1024 master icon and resizes to all required platform sizes.',
|
|
27
|
+
args: generateAppIconArgs,
|
|
28
|
+
async execute(args, _context) {
|
|
29
|
+
try {
|
|
30
|
+
// Initialize Gemini provider
|
|
31
|
+
const gemini = new GeminiProvider();
|
|
32
|
+
// Extract parameters with defaults
|
|
33
|
+
const { prompt, platforms = ['ios', 'android'], includeWatchOS = false, includeCarPlay = false, outputDir: customOutputDir } = args;
|
|
34
|
+
// Determine output directory
|
|
35
|
+
const baseOutputDir = customOutputDir || getOutputDir();
|
|
36
|
+
const iconOutputDir = path.join(baseOutputDir, 'app-icons');
|
|
37
|
+
await ensureDirectory(iconOutputDir);
|
|
38
|
+
// Generate 1024x1024 master icon
|
|
39
|
+
console.log('Generating 1024x1024 master icon...');
|
|
40
|
+
const masterIcons = await gemini.generateImage(`App icon: ${prompt}. Professional, simple, clean design suitable for a mobile app icon. Square format, centered composition.`, { aspectRatio: '1:1', count: 1 });
|
|
41
|
+
if (masterIcons.length === 0) {
|
|
42
|
+
return 'Failed to generate master icon';
|
|
43
|
+
}
|
|
44
|
+
const masterIcon = masterIcons[0];
|
|
45
|
+
if (!masterIcon) {
|
|
46
|
+
return 'Failed to generate master icon';
|
|
47
|
+
}
|
|
48
|
+
// Resize master to exactly 1024x1024 if needed
|
|
49
|
+
const master1024 = await resize(masterIcon, 1024, 1024, { fit: 'cover' });
|
|
50
|
+
const generatedPaths = [];
|
|
51
|
+
// Generate iOS icons
|
|
52
|
+
if (platforms.includes('ios')) {
|
|
53
|
+
const iosPaths = await generateIOSIcons(master1024, iconOutputDir, includeWatchOS, includeCarPlay);
|
|
54
|
+
generatedPaths.push(...iosPaths);
|
|
55
|
+
}
|
|
56
|
+
// Generate Android icons
|
|
57
|
+
if (platforms.includes('android')) {
|
|
58
|
+
const androidPaths = await generateAndroidIcons(master1024, iconOutputDir);
|
|
59
|
+
generatedPaths.push(...androidPaths);
|
|
60
|
+
}
|
|
61
|
+
return `✅ App icon generated successfully!\n\nGenerated ${generatedPaths.length} icon files:\n${generatedPaths.map(p => ` - ${p}`).join('\n')}\n\nMaster icon: 1024x1024`;
|
|
62
|
+
}
|
|
63
|
+
catch (error) {
|
|
64
|
+
if (error instanceof Error) {
|
|
65
|
+
return `❌ Failed to generate app icon: ${error.message}`;
|
|
66
|
+
}
|
|
67
|
+
return '❌ Failed to generate app icon: Unknown error';
|
|
68
|
+
}
|
|
69
|
+
},
|
|
70
|
+
});
|
|
71
|
+
/**
|
|
72
|
+
* Generate iOS icon set with Contents.json
|
|
73
|
+
*/
|
|
74
|
+
async function generateIOSIcons(masterIcon, baseOutputDir, includeWatchOS, includeCarPlay) {
|
|
75
|
+
const generatedPaths = [];
|
|
76
|
+
// Create AppIcon.appiconset directory
|
|
77
|
+
const appiconsetDir = path.join(baseOutputDir, 'ios', 'AppIcon.appiconset');
|
|
78
|
+
await ensureDirectory(appiconsetDir);
|
|
79
|
+
// Collect all iOS icon sizes
|
|
80
|
+
let allIconSizes = [...IOS_ICON_SIZES];
|
|
81
|
+
if (includeWatchOS) {
|
|
82
|
+
allIconSizes = allIconSizes.concat(WATCHOS_ICON_SIZES);
|
|
83
|
+
}
|
|
84
|
+
if (includeCarPlay) {
|
|
85
|
+
allIconSizes = allIconSizes.concat(CARPLAY_ICON_SIZES);
|
|
86
|
+
}
|
|
87
|
+
// Generate each icon size
|
|
88
|
+
for (const iconSize of allIconSizes) {
|
|
89
|
+
const resizedIcon = await resize(masterIcon, iconSize.pixels, iconSize.pixels, {
|
|
90
|
+
fit: 'cover',
|
|
91
|
+
});
|
|
92
|
+
const iconPath = path.join(appiconsetDir, iconSize.filename);
|
|
93
|
+
await fs.writeFile(iconPath, resizedIcon);
|
|
94
|
+
generatedPaths.push(iconPath);
|
|
95
|
+
}
|
|
96
|
+
// Generate Contents.json
|
|
97
|
+
const contentsJson = generateContentsJson(allIconSizes);
|
|
98
|
+
const contentsPath = path.join(appiconsetDir, 'Contents.json');
|
|
99
|
+
await fs.writeFile(contentsPath, JSON.stringify(contentsJson, null, 2));
|
|
100
|
+
generatedPaths.push(contentsPath);
|
|
101
|
+
return generatedPaths;
|
|
102
|
+
}
|
|
103
|
+
/**
|
|
104
|
+
* Generate Android icon set with adaptive icon XML
|
|
105
|
+
*/
|
|
106
|
+
async function generateAndroidIcons(masterIcon, baseOutputDir) {
|
|
107
|
+
const generatedPaths = [];
|
|
108
|
+
const androidDir = path.join(baseOutputDir, 'android');
|
|
109
|
+
await ensureDirectory(androidDir);
|
|
110
|
+
// Generate icons for each density
|
|
111
|
+
for (const androidIcon of ANDROID_ICON_SIZES) {
|
|
112
|
+
const densityDir = path.join(androidDir, androidIcon.directory);
|
|
113
|
+
await ensureDirectory(densityDir);
|
|
114
|
+
const resizedIcon = await resize(masterIcon, androidIcon.size, androidIcon.size, {
|
|
115
|
+
fit: 'cover',
|
|
116
|
+
});
|
|
117
|
+
const iconPath = path.join(densityDir, androidIcon.filename);
|
|
118
|
+
await fs.writeFile(iconPath, resizedIcon);
|
|
119
|
+
generatedPaths.push(iconPath);
|
|
120
|
+
}
|
|
121
|
+
// Generate adaptive icon XML
|
|
122
|
+
const adaptiveIconDir = path.join(androidDir, 'mipmap-anydpi-v26');
|
|
123
|
+
await ensureDirectory(adaptiveIconDir);
|
|
124
|
+
const adaptiveIconXml = generateAdaptiveIconXml();
|
|
125
|
+
const xmlPath = path.join(adaptiveIconDir, 'ic_launcher.xml');
|
|
126
|
+
await fs.writeFile(xmlPath, adaptiveIconXml);
|
|
127
|
+
generatedPaths.push(xmlPath);
|
|
128
|
+
// Note: For a complete adaptive icon setup, you would also generate separate
|
|
129
|
+
// foreground and background layers. For now, we use the standard icon as both.
|
|
130
|
+
// Users can customize by replacing ic_launcher_foreground and ic_launcher_background.
|
|
131
|
+
return generatedPaths;
|
|
132
|
+
}
|
|
133
|
+
//# sourceMappingURL=app-icon.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"app-icon.js","sourceRoot":"","sources":["../../../src/tools/app-assets/app-icon.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Device Mockup Tool
|
|
3
|
+
*
|
|
4
|
+
* Places screenshots in realistic device frames for App Store/marketing materials.
|
|
5
|
+
* Supports iPhone, iPad, and various device colors/orientations.
|
|
6
|
+
*/
|
|
7
|
+
import { type ToolDefinition } from '@opencode-ai/plugin/tool';
|
|
8
|
+
export declare const generateDeviceMockup: ToolDefinition;
|
|
9
|
+
//# sourceMappingURL=device-mockup.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"device-mockup.d.ts","sourceRoot":"","sources":["../../../src/tools/app-assets/device-mockup.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAQ,KAAK,cAAc,EAAE,MAAM,0BAA0B,CAAC;AAkDrE,eAAO,MAAM,oBAAoB,EAAE,cAkFjC,CAAC"}
|
|
@@ -0,0 +1,139 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Device Mockup Tool
|
|
3
|
+
*
|
|
4
|
+
* Places screenshots in realistic device frames for App Store/marketing materials.
|
|
5
|
+
* Supports iPhone, iPad, and various device colors/orientations.
|
|
6
|
+
*/
|
|
7
|
+
import { tool } from '@opencode-ai/plugin/tool';
|
|
8
|
+
import { GeminiProvider } from '../../providers/gemini.js';
|
|
9
|
+
import { loadImage, saveImage, ensureDirectory, getOutputDir } from '../../utils/file-handler.js';
|
|
10
|
+
import { getMetadata } from '../../utils/image-processing.js';
|
|
11
|
+
import * as path from 'path';
|
|
12
|
+
// Device specifications
|
|
13
|
+
const DEVICE_SPECS = {
|
|
14
|
+
// iPhone 16 Series
|
|
15
|
+
'iphone-16-pro-max': { displaySize: '6.9"', aspectRatio: '19.5:9', family: 'iPhone 16' },
|
|
16
|
+
'iphone-16-pro': { displaySize: '6.3"', aspectRatio: '19.5:9', family: 'iPhone 16' },
|
|
17
|
+
'iphone-16-plus': { displaySize: '6.7"', aspectRatio: '19.5:9', family: 'iPhone 16' },
|
|
18
|
+
'iphone-16': { displaySize: '6.1"', aspectRatio: '19.5:9', family: 'iPhone 16' },
|
|
19
|
+
// iPhone 15 Series
|
|
20
|
+
'iphone-15-pro-max': { displaySize: '6.7"', aspectRatio: '19.5:9', family: 'iPhone 15' },
|
|
21
|
+
'iphone-15-pro': { displaySize: '6.1"', aspectRatio: '19.5:9', family: 'iPhone 15' },
|
|
22
|
+
'iphone-15-plus': { displaySize: '6.7"', aspectRatio: '19.5:9', family: 'iPhone 15' },
|
|
23
|
+
'iphone-15': { displaySize: '6.1"', aspectRatio: '19.5:9', family: 'iPhone 15' },
|
|
24
|
+
// iPad Pro Series
|
|
25
|
+
'ipad-pro-12.9': { displaySize: '12.9"', aspectRatio: '4:3', family: 'iPad Pro' },
|
|
26
|
+
'ipad-pro-11': { displaySize: '11"', aspectRatio: '4.3:3', family: 'iPad Pro' },
|
|
27
|
+
// iPad Air & mini
|
|
28
|
+
'ipad-air': { displaySize: '10.9"', aspectRatio: '4.3:3', family: 'iPad Air' },
|
|
29
|
+
'ipad-mini': { displaySize: '8.3"', aspectRatio: '4:3', family: 'iPad mini' },
|
|
30
|
+
};
|
|
31
|
+
// Device colors are validated softly - any color string is accepted for flexibility
|
|
32
|
+
// Common options: silver, black, gold, titanium, blue, pink, green, purple, white, space-gray
|
|
33
|
+
const generateDeviceMockupArgs = {
|
|
34
|
+
imagePath: tool.schema.string().describe('Path to the screenshot image to place in device frame'),
|
|
35
|
+
device: tool.schema.string().describe('Device model: iphone-16-pro-max, iphone-16-pro, iphone-16-plus, iphone-16, iphone-15-pro-max, iphone-15-pro, iphone-15-plus, iphone-15, ipad-pro-12.9, ipad-pro-11, ipad-air, ipad-mini'),
|
|
36
|
+
color: tool.schema.string().optional().describe('Device color: silver, black, gold, titanium, blue, pink, green, purple, white, space-gray. Defaults to black.'),
|
|
37
|
+
orientation: tool.schema.string().optional().describe('Device orientation: portrait or landscape. Defaults to portrait.'),
|
|
38
|
+
outputPath: tool.schema.string().optional().describe('Custom output path for the mockup. Defaults to "./generated-assets/mockups/{device}-mockup.png"'),
|
|
39
|
+
};
|
|
40
|
+
export const generateDeviceMockup = tool({
|
|
41
|
+
description: 'Generate a realistic device mockup by placing a screenshot in a device frame. Supports iPhone 15/16 series and iPad models with various colors and orientations.',
|
|
42
|
+
args: generateDeviceMockupArgs,
|
|
43
|
+
async execute(args, _context) {
|
|
44
|
+
try {
|
|
45
|
+
// Initialize Gemini provider
|
|
46
|
+
const gemini = new GeminiProvider();
|
|
47
|
+
// Extract and validate parameters
|
|
48
|
+
const { imagePath, device, color = 'black', orientation = 'portrait', outputPath: customOutputPath, } = args;
|
|
49
|
+
// Validate device
|
|
50
|
+
if (!(device in DEVICE_SPECS)) {
|
|
51
|
+
const availableDevices = Object.keys(DEVICE_SPECS).join(', ');
|
|
52
|
+
return `❌ Invalid device model. Available devices: ${availableDevices}`;
|
|
53
|
+
}
|
|
54
|
+
const deviceModel = device;
|
|
55
|
+
const deviceSpec = DEVICE_SPECS[deviceModel];
|
|
56
|
+
// Validate color (soft validation - allow any color for flexibility)
|
|
57
|
+
const normalizedColor = color.toLowerCase();
|
|
58
|
+
// Validate orientation
|
|
59
|
+
if (orientation !== 'portrait' && orientation !== 'landscape') {
|
|
60
|
+
return `❌ Invalid orientation. Must be 'portrait' or 'landscape'.`;
|
|
61
|
+
}
|
|
62
|
+
// Load the screenshot image
|
|
63
|
+
console.log(`Loading screenshot from ${imagePath}...`);
|
|
64
|
+
const screenshotBuffer = await loadImage(imagePath);
|
|
65
|
+
// Get screenshot metadata
|
|
66
|
+
const metadata = await getMetadata(screenshotBuffer);
|
|
67
|
+
console.log(`Screenshot loaded: ${metadata.width}x${metadata.height}`);
|
|
68
|
+
// Determine output path
|
|
69
|
+
const baseOutputDir = getOutputDir();
|
|
70
|
+
const mockupsDir = path.join(baseOutputDir, 'mockups');
|
|
71
|
+
await ensureDirectory(mockupsDir);
|
|
72
|
+
// Prepare device filename for output
|
|
73
|
+
const deviceFileName = `${deviceModel}-${normalizedColor}-${orientation}-mockup`;
|
|
74
|
+
// Create a detailed prompt for Gemini to generate the mockup
|
|
75
|
+
const mockupPrompt = buildMockupPrompt(deviceSpec, deviceModel, normalizedColor, orientation);
|
|
76
|
+
console.log('Generating device mockup with Gemini...');
|
|
77
|
+
// Use Gemini's image editing capability to composite the screenshot into a device frame
|
|
78
|
+
// Strategy: Ask Gemini to generate a device frame with the screenshot placed inside
|
|
79
|
+
const mockupBuffer = await gemini.editImage(screenshotBuffer, mockupPrompt);
|
|
80
|
+
// Save the mockup
|
|
81
|
+
const savedPath = customOutputPath
|
|
82
|
+
? await saveImage(mockupBuffer, path.dirname(customOutputPath), path.basename(customOutputPath, path.extname(customOutputPath)), 0)
|
|
83
|
+
: await saveImage(mockupBuffer, mockupsDir, deviceFileName, 0);
|
|
84
|
+
return `✅ Device mockup generated successfully!\n\nDevice: ${deviceSpec.family} (${deviceSpec.displaySize})\nColor: ${normalizedColor}\nOrientation: ${orientation}\nOutput: ${savedPath}`;
|
|
85
|
+
}
|
|
86
|
+
catch (error) {
|
|
87
|
+
if (error instanceof Error) {
|
|
88
|
+
return `❌ Failed to generate device mockup: ${error.message}`;
|
|
89
|
+
}
|
|
90
|
+
return '❌ Failed to generate device mockup: Unknown error';
|
|
91
|
+
}
|
|
92
|
+
},
|
|
93
|
+
});
|
|
94
|
+
/**
|
|
95
|
+
* Build a detailed prompt for Gemini to generate realistic device mockup
|
|
96
|
+
*/
|
|
97
|
+
function buildMockupPrompt(deviceSpec, deviceModel, color, orientation) {
|
|
98
|
+
const isIPad = deviceModel.includes('ipad');
|
|
99
|
+
const deviceType = isIPad ? 'iPad' : 'iPhone';
|
|
100
|
+
const deviceName = deviceSpec.family;
|
|
101
|
+
// Build comprehensive prompt
|
|
102
|
+
let prompt = `Place this screenshot inside a realistic ${deviceName} device mockup. `;
|
|
103
|
+
// Device specifications
|
|
104
|
+
prompt += `The device should be a ${deviceName} with a ${deviceSpec.displaySize} display. `;
|
|
105
|
+
prompt += `Device color/finish: ${color}. `;
|
|
106
|
+
prompt += `Orientation: ${orientation}. `;
|
|
107
|
+
// Frame details based on device type
|
|
108
|
+
if (deviceType === 'iPhone') {
|
|
109
|
+
if (deviceModel.includes('16-pro') || deviceModel.includes('15-pro')) {
|
|
110
|
+
prompt += `Include the distinctive titanium frame with rounded corners. `;
|
|
111
|
+
prompt += `Show the Dynamic Island at the top of the screen. `;
|
|
112
|
+
prompt += `Add subtle reflections on the titanium edges. `;
|
|
113
|
+
}
|
|
114
|
+
else {
|
|
115
|
+
prompt += `Include the aluminum frame with rounded corners. `;
|
|
116
|
+
prompt += `Show the notch at the top of the screen. `;
|
|
117
|
+
}
|
|
118
|
+
prompt += `Include the volume buttons on the left side and power button on the right. `;
|
|
119
|
+
}
|
|
120
|
+
else {
|
|
121
|
+
// iPad
|
|
122
|
+
prompt += `Include the thin aluminum bezel with rounded corners characteristic of modern iPads. `;
|
|
123
|
+
prompt += `Show the minimal bezels around the display. `;
|
|
124
|
+
if (deviceModel.includes('pro')) {
|
|
125
|
+
prompt += `Include the flat squared-off edges of the iPad Pro design. `;
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
// Composition and lighting
|
|
129
|
+
prompt += `The screenshot should be perfectly fitted within the device screen area with accurate proportions. `;
|
|
130
|
+
prompt += `Add realistic lighting and shadows to make the device appear three-dimensional. `;
|
|
131
|
+
prompt += `Include subtle screen glare and reflections for realism. `;
|
|
132
|
+
prompt += `The device should be centered on a clean white or light gray background. `;
|
|
133
|
+
prompt += `Add a soft drop shadow beneath the device for depth. `;
|
|
134
|
+
// Final quality requirements
|
|
135
|
+
prompt += `The result should look professional and suitable for App Store marketing materials. `;
|
|
136
|
+
prompt += `Ensure the screenshot content is clearly visible and not distorted.`;
|
|
137
|
+
return prompt;
|
|
138
|
+
}
|
|
139
|
+
//# sourceMappingURL=device-mockup.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"device-mockup.js","sourceRoot":"","sources":["../../../src/tools/app-assets/device-mockup.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"launch-images.d.ts","sourceRoot":"","sources":["../../../src/tools/app-assets/launch-images.ts"],"names":[],"mappings":"AAAA,OAAO,EAAQ,KAAK,cAAc,EAAE,MAAM,0BAA0B,CAAC;AA8IrE,eAAO,MAAM,sBAAsB,EAAE,cA0EnC,CAAC"}
|