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.
Files changed (179) hide show
  1. package/.ralph-events.json +151 -0
  2. package/.ralph-last-branch +1 -0
  3. package/.ralph-monitor-state.json +7 -0
  4. package/.ralph-monitor.pid +1 -0
  5. package/.ralph-timing.json +26 -0
  6. package/README.md +708 -0
  7. package/dist/index.d.ts +18 -0
  8. package/dist/index.d.ts.map +1 -0
  9. package/dist/index.js +21 -0
  10. package/dist/index.js.map +1 -0
  11. package/dist/platforms/android.d.ts +94 -0
  12. package/dist/platforms/android.d.ts.map +1 -0
  13. package/dist/platforms/android.js +123 -0
  14. package/dist/platforms/android.js.map +1 -0
  15. package/dist/platforms/ios.d.ts +51 -0
  16. package/dist/platforms/ios.d.ts.map +1 -0
  17. package/dist/platforms/ios.js +149 -0
  18. package/dist/platforms/ios.js.map +1 -0
  19. package/dist/platforms/macos.d.ts +33 -0
  20. package/dist/platforms/macos.d.ts.map +1 -0
  21. package/dist/platforms/macos.js +50 -0
  22. package/dist/platforms/macos.js.map +1 -0
  23. package/dist/platforms/watchos.d.ts +36 -0
  24. package/dist/platforms/watchos.d.ts.map +1 -0
  25. package/dist/platforms/watchos.js +113 -0
  26. package/dist/platforms/watchos.js.map +1 -0
  27. package/dist/platforms/web.d.ts +64 -0
  28. package/dist/platforms/web.d.ts.map +1 -0
  29. package/dist/platforms/web.js +96 -0
  30. package/dist/platforms/web.js.map +1 -0
  31. package/dist/providers/gemini.d.ts +41 -0
  32. package/dist/providers/gemini.d.ts.map +1 -0
  33. package/dist/providers/gemini.js +177 -0
  34. package/dist/providers/gemini.js.map +1 -0
  35. package/dist/tools/analyze/compare.d.ts +12 -0
  36. package/dist/tools/analyze/compare.d.ts.map +1 -0
  37. package/dist/tools/analyze/compare.js +83 -0
  38. package/dist/tools/analyze/compare.js.map +1 -0
  39. package/dist/tools/analyze/mockup.d.ts +12 -0
  40. package/dist/tools/analyze/mockup.d.ts.map +1 -0
  41. package/dist/tools/analyze/mockup.js +88 -0
  42. package/dist/tools/analyze/mockup.js.map +1 -0
  43. package/dist/tools/analyze/screenshot.d.ts +12 -0
  44. package/dist/tools/analyze/screenshot.d.ts.map +1 -0
  45. package/dist/tools/analyze/screenshot.js +61 -0
  46. package/dist/tools/analyze/screenshot.js.map +1 -0
  47. package/dist/tools/app-assets/app-icon.d.ts +9 -0
  48. package/dist/tools/app-assets/app-icon.d.ts.map +1 -0
  49. package/dist/tools/app-assets/app-icon.js +133 -0
  50. package/dist/tools/app-assets/app-icon.js.map +1 -0
  51. package/dist/tools/app-assets/device-mockup.d.ts +9 -0
  52. package/dist/tools/app-assets/device-mockup.d.ts.map +1 -0
  53. package/dist/tools/app-assets/device-mockup.js +139 -0
  54. package/dist/tools/app-assets/device-mockup.js.map +1 -0
  55. package/dist/tools/app-assets/launch-images.d.ts +3 -0
  56. package/dist/tools/app-assets/launch-images.d.ts.map +1 -0
  57. package/dist/tools/app-assets/launch-images.js +171 -0
  58. package/dist/tools/app-assets/launch-images.js.map +1 -0
  59. package/dist/tools/app-assets/resize-devices.d.ts +14 -0
  60. package/dist/tools/app-assets/resize-devices.d.ts.map +1 -0
  61. package/dist/tools/app-assets/resize-devices.js +296 -0
  62. package/dist/tools/app-assets/resize-devices.js.map +1 -0
  63. package/dist/tools/app-assets/screenshots.d.ts +14 -0
  64. package/dist/tools/app-assets/screenshots.d.ts.map +1 -0
  65. package/dist/tools/app-assets/screenshots.js +186 -0
  66. package/dist/tools/app-assets/screenshots.js.map +1 -0
  67. package/dist/tools/core/edit-image.d.ts +12 -0
  68. package/dist/tools/core/edit-image.d.ts.map +1 -0
  69. package/dist/tools/core/edit-image.js +102 -0
  70. package/dist/tools/core/edit-image.js.map +1 -0
  71. package/dist/tools/core/generate-image.d.ts +12 -0
  72. package/dist/tools/core/generate-image.d.ts.map +1 -0
  73. package/dist/tools/core/generate-image.js +96 -0
  74. package/dist/tools/core/generate-image.js.map +1 -0
  75. package/dist/tools/core/restore-image.d.ts +12 -0
  76. package/dist/tools/core/restore-image.d.ts.map +1 -0
  77. package/dist/tools/core/restore-image.js +104 -0
  78. package/dist/tools/core/restore-image.js.map +1 -0
  79. package/dist/tools/design/mockup-to-code.d.ts +3 -0
  80. package/dist/tools/design/mockup-to-code.d.ts.map +1 -0
  81. package/dist/tools/design/mockup-to-code.js +311 -0
  82. package/dist/tools/design/mockup-to-code.js.map +1 -0
  83. package/dist/tools/design/sketch-to-code.d.ts +3 -0
  84. package/dist/tools/design/sketch-to-code.d.ts.map +1 -0
  85. package/dist/tools/design/sketch-to-code.js +325 -0
  86. package/dist/tools/design/sketch-to-code.js.map +1 -0
  87. package/dist/tools/docs/architecture-diagram.d.ts +12 -0
  88. package/dist/tools/docs/architecture-diagram.d.ts.map +1 -0
  89. package/dist/tools/docs/architecture-diagram.js +179 -0
  90. package/dist/tools/docs/architecture-diagram.js.map +1 -0
  91. package/dist/tools/docs/readme-banner.d.ts +6 -0
  92. package/dist/tools/docs/readme-banner.d.ts.map +1 -0
  93. package/dist/tools/docs/readme-banner.js +108 -0
  94. package/dist/tools/docs/readme-banner.js.map +1 -0
  95. package/dist/tools/docs/sequence-diagram.d.ts +12 -0
  96. package/dist/tools/docs/sequence-diagram.d.ts.map +1 -0
  97. package/dist/tools/docs/sequence-diagram.js +161 -0
  98. package/dist/tools/docs/sequence-diagram.js.map +1 -0
  99. package/dist/tools/docs/social-preview.d.ts +11 -0
  100. package/dist/tools/docs/social-preview.d.ts.map +1 -0
  101. package/dist/tools/docs/social-preview.js +111 -0
  102. package/dist/tools/docs/social-preview.js.map +1 -0
  103. package/dist/tools/video/extend-video.d.ts +14 -0
  104. package/dist/tools/video/extend-video.d.ts.map +1 -0
  105. package/dist/tools/video/extend-video.js +39 -0
  106. package/dist/tools/video/extend-video.js.map +1 -0
  107. package/dist/tools/video/generate-video.d.ts +14 -0
  108. package/dist/tools/video/generate-video.d.ts.map +1 -0
  109. package/dist/tools/video/generate-video.js +39 -0
  110. package/dist/tools/video/generate-video.js.map +1 -0
  111. package/dist/tools/video/image-to-video.d.ts +15 -0
  112. package/dist/tools/video/image-to-video.d.ts.map +1 -0
  113. package/dist/tools/video/image-to-video.js +42 -0
  114. package/dist/tools/video/image-to-video.js.map +1 -0
  115. package/dist/tools/video/storyboard-video.d.ts +91 -0
  116. package/dist/tools/video/storyboard-video.d.ts.map +1 -0
  117. package/dist/tools/video/storyboard-video.js +230 -0
  118. package/dist/tools/video/storyboard-video.js.map +1 -0
  119. package/dist/utils/ffmpeg.d.ts +30 -0
  120. package/dist/utils/ffmpeg.d.ts.map +1 -0
  121. package/dist/utils/ffmpeg.js +205 -0
  122. package/dist/utils/ffmpeg.js.map +1 -0
  123. package/dist/utils/file-handler.d.ts +7 -0
  124. package/dist/utils/file-handler.d.ts.map +1 -0
  125. package/dist/utils/file-handler.js +10 -0
  126. package/dist/utils/file-handler.js.map +1 -0
  127. package/dist/utils/image-processing.d.ts +7 -0
  128. package/dist/utils/image-processing.d.ts.map +1 -0
  129. package/dist/utils/image-processing.js +10 -0
  130. package/dist/utils/image-processing.js.map +1 -0
  131. package/docs/PLUGIN-VERIFICATION.md +182 -0
  132. package/logs/notifications.jsonl +46 -0
  133. package/package.json +61 -0
  134. package/prd.json +216 -0
  135. package/progress.txt +145 -0
  136. package/ralph-report.html +297 -0
  137. package/src/index.ts +23 -0
  138. package/src/platforms/android/.gitkeep +0 -0
  139. package/src/platforms/ios/.gitkeep +0 -0
  140. package/src/platforms/web/.gitkeep +0 -0
  141. package/src/providers/.gitkeep +0 -0
  142. package/src/providers/gemini.ts +288 -0
  143. package/src/tools/core/.gitkeep +0 -0
  144. package/src/tools/platform/.gitkeep +0 -0
  145. package/src/tools/video/extend-video.ts +71 -0
  146. package/src/tools/video/generate-video.ts +70 -0
  147. package/src/tools/video/image-to-video.ts +76 -0
  148. package/src/tools/video/storyboard-video.ts +325 -0
  149. package/src/utils/.gitkeep +0 -0
  150. package/src/utils/ffmpeg.ts +266 -0
  151. package/src/utils/file-handler.ts +10 -0
  152. package/src/utils/image-processing.ts +10 -0
  153. package/templates/.gitkeep +0 -0
  154. package/test-analyze-screenshot.ts +50 -0
  155. package/test-app-icons.ts +55 -0
  156. package/test-cat-sunset.ts +30 -0
  157. package/test-full-plugin.ts +88 -0
  158. package/test-icon-gen.ts +30 -0
  159. package/test-output/test-edit.png +0 -0
  160. package/test-output/test-generate.png +0 -0
  161. package/test-output/test-video.mp4 +0 -0
  162. package/test-plugin-load.js +45 -0
  163. package/test-princess-emma-continue.ts +35 -0
  164. package/test-princess-emma-full.ts +38 -0
  165. package/test-princess-emma-short.ts +32 -0
  166. package/test-princess-emma-with-reference.ts +34 -0
  167. package/test-princess-emma.ts +38 -0
  168. package/test-product-ad.ts +66 -0
  169. package/test-ralph-droid.ts +30 -0
  170. package/test-social-preview.ts +61 -0
  171. package/test-veo31-live.ts +187 -0
  172. package/test-video-gen.ts +40 -0
  173. package/test-video-veo.ts +73 -0
  174. package/test-zurich-video.ts +64 -0
  175. package/tests/.gitkeep +0 -0
  176. package/tests/providers/gemini.test.ts +388 -0
  177. package/tests/utils/ffmpeg.test.ts +328 -0
  178. package/tests/video/storyboard.test.ts +469 -0
  179. package/tsconfig.json +25 -0
@@ -0,0 +1,113 @@
1
+ /**
2
+ * watchOS Platform Specifications
3
+ *
4
+ * Defines icon sizes and specifications for Apple Watch apps across all watch sizes.
5
+ * Supports notification, home screen, short look, and App Store icons.
6
+ */
7
+ /**
8
+ * Complete watchOS icon sizes for all watch models and contexts
9
+ * Based on Apple's Human Interface Guidelines for watchOS
10
+ */
11
+ export const WATCHOS_ICON_SIZES = [
12
+ // 38mm Apple Watch (Series 1, 2, 3)
13
+ { size: 24, scale: 2, pixels: 48, context: 'notification', watchSize: '38mm', filename: 'Icon-Notification-38mm@2x.png' },
14
+ { size: 27.5, scale: 2, pixels: 55, context: 'short-look', watchSize: '38mm', filename: 'Icon-ShortLook-38mm@2x.png' },
15
+ { size: 40, scale: 2, pixels: 80, context: 'home', watchSize: '38mm', filename: 'Icon-Home-38mm@2x.png' },
16
+ { size: 86, scale: 2, pixels: 172, context: 'short-look', watchSize: '38mm', filename: 'Icon-ShortLook-Large-38mm@2x.png' },
17
+ // 40mm Apple Watch (Series 4, 5, 6, SE)
18
+ { size: 24, scale: 2, pixels: 48, context: 'notification', watchSize: '40mm', filename: 'Icon-Notification-40mm@2x.png' },
19
+ { size: 27.5, scale: 2, pixels: 55, context: 'short-look', watchSize: '40mm', filename: 'Icon-ShortLook-40mm@2x.png' },
20
+ { size: 40, scale: 2, pixels: 80, context: 'home', watchSize: '40mm', filename: 'Icon-Home-40mm@2x.png' },
21
+ { size: 86, scale: 2, pixels: 172, context: 'short-look', watchSize: '40mm', filename: 'Icon-ShortLook-Large-40mm@2x.png' },
22
+ { size: 92, scale: 2, pixels: 184, context: 'home', watchSize: '40mm', filename: 'Icon-Home-Large-40mm@2x.png' },
23
+ // 41mm Apple Watch (Series 7, 8, 9)
24
+ { size: 24, scale: 2, pixels: 48, context: 'notification', watchSize: '41mm', filename: 'Icon-Notification-41mm@2x.png' },
25
+ { size: 27.5, scale: 2, pixels: 55, context: 'short-look', watchSize: '41mm', filename: 'Icon-ShortLook-41mm@2x.png' },
26
+ { size: 40, scale: 2, pixels: 80, context: 'home', watchSize: '41mm', filename: 'Icon-Home-41mm@2x.png' },
27
+ { size: 86, scale: 2, pixels: 172, context: 'short-look', watchSize: '41mm', filename: 'Icon-ShortLook-Large-41mm@2x.png' },
28
+ { size: 92, scale: 2, pixels: 184, context: 'home', watchSize: '41mm', filename: 'Icon-Home-Large-41mm@2x.png' },
29
+ // 42mm Apple Watch (Series 1, 2, 3)
30
+ { size: 24, scale: 2, pixels: 48, context: 'notification', watchSize: '42mm', filename: 'Icon-Notification-42mm@2x.png' },
31
+ { size: 27.5, scale: 2, pixels: 55, context: 'short-look', watchSize: '42mm', filename: 'Icon-ShortLook-42mm@2x.png' },
32
+ { size: 44, scale: 2, pixels: 88, context: 'home', watchSize: '42mm', filename: 'Icon-Home-42mm@2x.png' },
33
+ { size: 98, scale: 2, pixels: 196, context: 'short-look', watchSize: '42mm', filename: 'Icon-ShortLook-Large-42mm@2x.png' },
34
+ // 44mm Apple Watch (Series 4, 5, 6, SE)
35
+ { size: 24, scale: 2, pixels: 48, context: 'notification', watchSize: '44mm', filename: 'Icon-Notification-44mm@2x.png' },
36
+ { size: 27.5, scale: 2, pixels: 55, context: 'short-look', watchSize: '44mm', filename: 'Icon-ShortLook-44mm@2x.png' },
37
+ { size: 44, scale: 2, pixels: 88, context: 'home', watchSize: '44mm', filename: 'Icon-Home-44mm@2x.png' },
38
+ { size: 98, scale: 2, pixels: 196, context: 'short-look', watchSize: '44mm', filename: 'Icon-ShortLook-Large-44mm@2x.png' },
39
+ { size: 100, scale: 2, pixels: 200, context: 'home', watchSize: '44mm', filename: 'Icon-Home-Large-44mm@2x.png' },
40
+ // 45mm Apple Watch (Series 7, 8, 9)
41
+ { size: 24, scale: 2, pixels: 48, context: 'notification', watchSize: '45mm', filename: 'Icon-Notification-45mm@2x.png' },
42
+ { size: 27.5, scale: 2, pixels: 55, context: 'short-look', watchSize: '45mm', filename: 'Icon-ShortLook-45mm@2x.png' },
43
+ { size: 44, scale: 2, pixels: 88, context: 'home', watchSize: '45mm', filename: 'Icon-Home-45mm@2x.png' },
44
+ { size: 98, scale: 2, pixels: 196, context: 'short-look', watchSize: '45mm', filename: 'Icon-ShortLook-Large-45mm@2x.png' },
45
+ { size: 100, scale: 2, pixels: 200, context: 'home', watchSize: '45mm', filename: 'Icon-Home-Large-45mm@2x.png' },
46
+ // 49mm Apple Watch (Series 9, Ultra, Ultra 2)
47
+ { size: 24, scale: 2, pixels: 48, context: 'notification', watchSize: '49mm', filename: 'Icon-Notification-49mm@2x.png' },
48
+ { size: 27.5, scale: 2, pixels: 55, context: 'short-look', watchSize: '49mm', filename: 'Icon-ShortLook-49mm@2x.png' },
49
+ { size: 44, scale: 2, pixels: 88, context: 'home', watchSize: '49mm', filename: 'Icon-Home-49mm@2x.png' },
50
+ { size: 98, scale: 2, pixels: 196, context: 'short-look', watchSize: '49mm', filename: 'Icon-ShortLook-Large-49mm@2x.png' },
51
+ { size: 108, scale: 2, pixels: 216, context: 'home', watchSize: '49mm', filename: 'Icon-Home-Large-49mm@2x.png' },
52
+ // App Store icon (1024x1024, universal)
53
+ { size: 1024, scale: 1, pixels: 1024, context: 'store', watchSize: 'all', filename: 'Icon-AppStore-1024x1024.png' },
54
+ ];
55
+ /**
56
+ * Generates Contents.json for Xcode watchOS asset catalog
57
+ */
58
+ export function generateWatchContentsJson(sizes) {
59
+ const images = sizes.map(s => ({
60
+ filename: s.filename,
61
+ idiom: 'watch',
62
+ role: s.context,
63
+ scale: `${s.scale}x`,
64
+ size: `${s.size}x${s.size}`,
65
+ subtype: s.watchSize !== 'all' ? s.watchSize : undefined,
66
+ }));
67
+ return JSON.stringify({
68
+ images: images.filter(img => img.subtype !== undefined),
69
+ info: {
70
+ author: 'opencode-visual-toolkit',
71
+ version: 1,
72
+ },
73
+ }, null, 2);
74
+ }
75
+ /**
76
+ * Gets appropriate icon filename for watch size and context
77
+ */
78
+ export function getWatchIconFilename(size, context, watchSize) {
79
+ if (size === 1024) {
80
+ return 'Icon-AppStore-1024x1024.png';
81
+ }
82
+ // Normalize context for filename
83
+ const contextMap = {
84
+ notification: 'Notification',
85
+ home: 'Home',
86
+ 'short-look': 'ShortLook',
87
+ store: 'AppStore',
88
+ };
89
+ const contextName = contextMap[context] || context;
90
+ return `Icon-${contextName}-${watchSize}@2x.png`;
91
+ }
92
+ /**
93
+ * Groups icon sizes by watch size for organized generation
94
+ */
95
+ export function groupIconsByWatchSize() {
96
+ const grouped = {};
97
+ for (const iconSize of WATCHOS_ICON_SIZES) {
98
+ const key = iconSize.watchSize;
99
+ if (!grouped[key]) {
100
+ grouped[key] = [];
101
+ }
102
+ grouped[key].push(iconSize);
103
+ }
104
+ return grouped;
105
+ }
106
+ /**
107
+ * Gets all unique contexts (notification, home, short-look, store)
108
+ */
109
+ export function getWatchContexts() {
110
+ const contexts = new Set(WATCHOS_ICON_SIZES.map(s => s.context));
111
+ return Array.from(contexts);
112
+ }
113
+ //# sourceMappingURL=watchos.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"watchos.js","sourceRoot":"","sources":["../../src/platforms/watchos.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,64 @@
1
+ /**
2
+ * Web Platform Specifications
3
+ * Complete icon sizes for web applications including favicon and PWA icons
4
+ */
5
+ export interface WebIconSize {
6
+ size: number;
7
+ purpose: 'favicon' | 'apple-touch' | 'pwa';
8
+ filename: string;
9
+ description: string;
10
+ }
11
+ /**
12
+ * Web Manifest Icon specification
13
+ * Used by PWA manifest.json
14
+ */
15
+ export interface WebManifestIcon {
16
+ src: string;
17
+ sizes: string;
18
+ type: string;
19
+ purpose?: string;
20
+ }
21
+ /**
22
+ * Complete web icon sizes
23
+ * Includes favicon (16, 32, 48), apple-touch-icon (180), PWA icons (192, 512)
24
+ */
25
+ export declare const WEB_ICON_SIZES: WebIconSize[];
26
+ /**
27
+ * Generate Web Manifest icons array for manifest.json
28
+ * @param basePath Base path to icon directory (e.g., '/icons' or './icons')
29
+ * @returns Array of manifest icon objects
30
+ */
31
+ export declare function generateWebManifestIcons(basePath?: string): WebManifestIcon[];
32
+ /**
33
+ * Generate favicon information
34
+ * Returns HTML link tags and .ico conversion instructions
35
+ * @returns Favicon configuration and HTML snippets
36
+ */
37
+ export declare function generateFavicon(): {
38
+ sizes: WebIconSize[];
39
+ htmlSnippets: string[];
40
+ icoInstructions: string;
41
+ };
42
+ /**
43
+ * Get web icon filename based on purpose and size
44
+ * @param purpose Icon purpose (favicon, apple-touch, pwa)
45
+ * @param size Size in pixels
46
+ * @returns Filename string following web conventions
47
+ */
48
+ export declare function getWebIconFilename(purpose: 'favicon' | 'apple-touch' | 'pwa', size: number): string;
49
+ /**
50
+ * Generate complete PWA manifest.json structure
51
+ * @param config PWA configuration
52
+ * @returns manifest.json object
53
+ */
54
+ export declare function generatePWAManifest(config: {
55
+ name: string;
56
+ shortName: string;
57
+ description?: string;
58
+ themeColor?: string;
59
+ backgroundColor?: string;
60
+ display?: 'standalone' | 'fullscreen' | 'minimal-ui' | 'browser';
61
+ orientation?: 'portrait' | 'landscape' | 'any';
62
+ iconBasePath?: string;
63
+ }): Record<string, unknown>;
64
+ //# sourceMappingURL=web.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"web.d.ts","sourceRoot":"","sources":["../../src/platforms/web.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,MAAM,WAAW,WAAW;IAC1B,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,SAAS,GAAG,aAAa,GAAG,KAAK,CAAC;IAC3C,QAAQ,EAAE,MAAM,CAAC;IACjB,WAAW,EAAE,MAAM,CAAC;CACrB;AAED;;;GAGG;AACH,MAAM,WAAW,eAAe;IAC9B,GAAG,EAAE,MAAM,CAAC;IACZ,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED;;;GAGG;AACH,eAAO,MAAM,cAAc,EAAE,WAAW,EAYvC,CAAC;AAEF;;;;GAIG;AACH,wBAAgB,wBAAwB,CAAC,QAAQ,GAAE,MAAiB,GAAG,eAAe,EAAE,CASvF;AAED;;;;GAIG;AACH,wBAAgB,eAAe,IAAI;IACjC,KAAK,EAAE,WAAW,EAAE,CAAC;IACrB,YAAY,EAAE,MAAM,EAAE,CAAC;IACvB,eAAe,EAAE,MAAM,CAAC;CACzB,CA4BA;AAED;;;;;GAKG;AACH,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,SAAS,GAAG,aAAa,GAAG,KAAK,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,CAQnG;AAED;;;;GAIG;AACH,wBAAgB,mBAAmB,CAAC,MAAM,EAAE;IAC1C,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,EAAE,MAAM,CAAC;IAClB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,OAAO,CAAC,EAAE,YAAY,GAAG,YAAY,GAAG,YAAY,GAAG,SAAS,CAAC;IACjE,WAAW,CAAC,EAAE,UAAU,GAAG,WAAW,GAAG,KAAK,CAAC;IAC/C,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAwB1B"}
@@ -0,0 +1,96 @@
1
+ /**
2
+ * Web Platform Specifications
3
+ * Complete icon sizes for web applications including favicon and PWA icons
4
+ */
5
+ /**
6
+ * Complete web icon sizes
7
+ * Includes favicon (16, 32, 48), apple-touch-icon (180), PWA icons (192, 512)
8
+ */
9
+ export const WEB_ICON_SIZES = [
10
+ // Favicon sizes (for browsers)
11
+ { size: 16, purpose: 'favicon', filename: 'favicon-16x16.png', description: 'Browser tab icon (small)' },
12
+ { size: 32, purpose: 'favicon', filename: 'favicon-32x32.png', description: 'Browser tab icon (medium)' },
13
+ { size: 48, purpose: 'favicon', filename: 'favicon-48x48.png', description: 'Browser tab icon (large)' },
14
+ // Apple Touch Icon
15
+ { size: 180, purpose: 'apple-touch', filename: 'apple-touch-icon.png', description: 'iOS home screen icon' },
16
+ // PWA Icons (Progressive Web App)
17
+ { size: 192, purpose: 'pwa', filename: 'icon-192x192.png', description: 'PWA icon (standard)' },
18
+ { size: 512, purpose: 'pwa', filename: 'icon-512x512.png', description: 'PWA icon (large/splash)' },
19
+ ];
20
+ /**
21
+ * Generate Web Manifest icons array for manifest.json
22
+ * @param basePath Base path to icon directory (e.g., '/icons' or './icons')
23
+ * @returns Array of manifest icon objects
24
+ */
25
+ export function generateWebManifestIcons(basePath = '/icons') {
26
+ const pwaIcons = WEB_ICON_SIZES.filter(icon => icon.purpose === 'pwa');
27
+ return pwaIcons.map(icon => ({
28
+ src: `${basePath}/${icon.filename}`,
29
+ sizes: `${icon.size}x${icon.size}`,
30
+ type: 'image/png',
31
+ purpose: 'any maskable', // Support both normal and maskable (Android adaptive)
32
+ }));
33
+ }
34
+ /**
35
+ * Generate favicon information
36
+ * Returns HTML link tags and .ico conversion instructions
37
+ * @returns Favicon configuration and HTML snippets
38
+ */
39
+ export function generateFavicon() {
40
+ const faviconSizes = WEB_ICON_SIZES.filter(icon => icon.purpose === 'favicon');
41
+ const appleTouchIcon = WEB_ICON_SIZES.find(icon => icon.purpose === 'apple-touch');
42
+ const htmlSnippets = [];
43
+ // Standard favicon.ico reference
44
+ htmlSnippets.push('<link rel="icon" href="/favicon.ico" sizes="any">');
45
+ // PNG favicons with size hints
46
+ faviconSizes.forEach(icon => {
47
+ htmlSnippets.push(`<link rel="icon" type="image/png" sizes="${icon.size}x${icon.size}" href="/${icon.filename}">`);
48
+ });
49
+ // Apple touch icon
50
+ if (appleTouchIcon) {
51
+ htmlSnippets.push(`<link rel="apple-touch-icon" href="/${appleTouchIcon.filename}">`);
52
+ }
53
+ // SVG favicon (modern browsers)
54
+ htmlSnippets.push('<link rel="icon" type="image/svg+xml" href="/favicon.svg">');
55
+ return {
56
+ sizes: faviconSizes,
57
+ htmlSnippets,
58
+ icoInstructions: 'To create favicon.ico: Use a multi-size ICO converter to combine 16x16, 32x32, and 48x48 PNG files into a single .ico file. Tools: ImageMagick (convert), online converters, or npm packages like png-to-ico.',
59
+ };
60
+ }
61
+ /**
62
+ * Get web icon filename based on purpose and size
63
+ * @param purpose Icon purpose (favicon, apple-touch, pwa)
64
+ * @param size Size in pixels
65
+ * @returns Filename string following web conventions
66
+ */
67
+ export function getWebIconFilename(purpose, size) {
68
+ if (purpose === 'apple-touch') {
69
+ return 'apple-touch-icon.png';
70
+ }
71
+ if (purpose === 'pwa') {
72
+ return `icon-${size}x${size}.png`;
73
+ }
74
+ return `favicon-${size}x${size}.png`;
75
+ }
76
+ /**
77
+ * Generate complete PWA manifest.json structure
78
+ * @param config PWA configuration
79
+ * @returns manifest.json object
80
+ */
81
+ export function generatePWAManifest(config) {
82
+ const { name, shortName, description = '', themeColor = '#000000', backgroundColor = '#ffffff', display = 'standalone', orientation = 'any', iconBasePath = '/icons', } = config;
83
+ return {
84
+ name,
85
+ short_name: shortName,
86
+ description,
87
+ theme_color: themeColor,
88
+ background_color: backgroundColor,
89
+ display,
90
+ orientation,
91
+ start_url: '/',
92
+ scope: '/',
93
+ icons: generateWebManifestIcons(iconBasePath),
94
+ };
95
+ }
96
+ //# sourceMappingURL=web.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"web.js","sourceRoot":"","sources":["../../src/platforms/web.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,41 @@
1
+ export interface VideoGenerationOptions {
2
+ aspectRatio?: '16:9' | '9:16';
3
+ resolution?: '720p' | '1080p';
4
+ duration?: 4 | 6 | 8;
5
+ numberOfVideos?: number;
6
+ negativePrompt?: string;
7
+ }
8
+ export interface ImageAnimationOptions {
9
+ aspectRatio?: '16:9' | '9:16';
10
+ resolution?: '720p' | '1080p';
11
+ duration?: 4 | 6 | 8;
12
+ }
13
+ export interface VideoExtensionOptions {
14
+ aspectRatio?: '16:9' | '9:16';
15
+ resolution?: '720p' | '1080p';
16
+ }
17
+ export interface ReferenceImage {
18
+ buffer: Buffer;
19
+ description: string;
20
+ }
21
+ export interface VideoGenerationResult {
22
+ buffer: Buffer;
23
+ url?: string;
24
+ generationTime: number;
25
+ }
26
+ export declare class GeminiProvider {
27
+ private ai;
28
+ private apiKey;
29
+ private readonly VEO_MODEL;
30
+ private readonly VEO_PREVIEW_MODEL;
31
+ private readonly POLL_INTERVAL_MS;
32
+ constructor(apiKey: string);
33
+ generateVideo(prompt: string, options?: VideoGenerationOptions): Promise<VideoGenerationResult>;
34
+ animateImage(imageBuffer: Buffer, prompt: string, options?: ImageAnimationOptions): Promise<VideoGenerationResult>;
35
+ extendVideo(videoBuffer: Buffer, prompt: string, options?: VideoExtensionOptions): Promise<VideoGenerationResult>;
36
+ generateVideoWithReferences(prompt: string, referenceImages: ReferenceImage[], options?: VideoGenerationOptions): Promise<VideoGenerationResult>;
37
+ private pollOperation;
38
+ private downloadVideo;
39
+ private detectImageMimeType;
40
+ }
41
+ //# sourceMappingURL=gemini.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"gemini.d.ts","sourceRoot":"","sources":["../../src/providers/gemini.ts"],"names":[],"mappings":"AAEA,MAAM,WAAW,sBAAsB;IACrC,WAAW,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;IAC9B,UAAU,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC;IAC9B,QAAQ,CAAC,EAAE,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;IACrB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,cAAc,CAAC,EAAE,MAAM,CAAC;CACzB;AAED,MAAM,WAAW,qBAAqB;IACpC,WAAW,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;IAC9B,UAAU,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC;IAC9B,QAAQ,CAAC,EAAE,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;CACtB;AAED,MAAM,WAAW,qBAAqB;IACpC,WAAW,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;IAC9B,UAAU,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC;CAC/B;AAED,MAAM,WAAW,cAAc;IAC7B,MAAM,EAAE,MAAM,CAAC;IACf,WAAW,EAAE,MAAM,CAAC;CACrB;AAED,MAAM,WAAW,qBAAqB;IACpC,MAAM,EAAE,MAAM,CAAC;IACf,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,cAAc,EAAE,MAAM,CAAC;CACxB;AAED,qBAAa,cAAc;IACzB,OAAO,CAAC,EAAE,CAAc;IACxB,OAAO,CAAC,MAAM,CAAS;IACvB,OAAO,CAAC,QAAQ,CAAC,SAAS,CAA0B;IACpD,OAAO,CAAC,QAAQ,CAAC,iBAAiB,CAA8B;IAChE,OAAO,CAAC,QAAQ,CAAC,gBAAgB,CAAS;gBAE9B,MAAM,EAAE,MAAM;IAKpB,aAAa,CACjB,MAAM,EAAE,MAAM,EACd,OAAO,GAAE,sBAA2B,GACnC,OAAO,CAAC,qBAAqB,CAAC;IA0C3B,YAAY,CAChB,WAAW,EAAE,MAAM,EACnB,MAAM,EAAE,MAAM,EACd,OAAO,GAAE,qBAA0B,GAClC,OAAO,CAAC,qBAAqB,CAAC;IA8C3B,WAAW,CACf,WAAW,EAAE,MAAM,EACnB,MAAM,EAAE,MAAM,EACd,OAAO,GAAE,qBAA0B,GAClC,OAAO,CAAC,qBAAqB,CAAC;IA2C3B,2BAA2B,CAC/B,MAAM,EAAE,MAAM,EACd,eAAe,EAAE,cAAc,EAAE,EACjC,OAAO,GAAE,sBAA2B,GACnC,OAAO,CAAC,qBAAqB,CAAC;YAqDnB,aAAa;YAab,aAAa;IAgB3B,OAAO,CAAC,mBAAmB;CAe5B"}
@@ -0,0 +1,177 @@
1
+ import { GoogleGenAI } from '@google/genai';
2
+ export class GeminiProvider {
3
+ ai;
4
+ apiKey;
5
+ VEO_MODEL = 'veo-3.0-generate-001';
6
+ VEO_PREVIEW_MODEL = 'veo-3.1-generate-preview';
7
+ POLL_INTERVAL_MS = 10000;
8
+ constructor(apiKey) {
9
+ this.apiKey = apiKey;
10
+ this.ai = new GoogleGenAI({ apiKey });
11
+ }
12
+ async generateVideo(prompt, options = {}) {
13
+ const startTime = Date.now();
14
+ const { aspectRatio = '16:9', resolution = '720p', duration = 8, numberOfVideos = 1, negativePrompt, } = options;
15
+ let operation = await this.ai.models.generateVideos({
16
+ model: this.VEO_MODEL,
17
+ prompt,
18
+ config: {
19
+ numberOfVideos,
20
+ aspectRatio,
21
+ resolution,
22
+ durationSeconds: duration,
23
+ ...(negativePrompt && { negativePrompt }),
24
+ },
25
+ });
26
+ operation = await this.pollOperation(operation);
27
+ if (!operation.response?.generatedVideos?.[0]) {
28
+ throw new Error('No video was generated');
29
+ }
30
+ const video = operation.response.generatedVideos[0];
31
+ const videoUrl = video.video?.uri;
32
+ if (!videoUrl) {
33
+ throw new Error('Video URL not available');
34
+ }
35
+ const buffer = await this.downloadVideo(videoUrl);
36
+ const generationTime = Date.now() - startTime;
37
+ return { buffer, url: videoUrl, generationTime };
38
+ }
39
+ async animateImage(imageBuffer, prompt, options = {}) {
40
+ const startTime = Date.now();
41
+ const { aspectRatio = '16:9', resolution = '720p', duration = 8, } = options;
42
+ const imageBase64 = imageBuffer.toString('base64');
43
+ const mimeType = this.detectImageMimeType(imageBuffer);
44
+ let operation = await this.ai.models.generateVideos({
45
+ model: this.VEO_MODEL,
46
+ prompt,
47
+ image: {
48
+ imageBytes: imageBase64,
49
+ mimeType,
50
+ },
51
+ config: {
52
+ numberOfVideos: 1,
53
+ aspectRatio,
54
+ resolution,
55
+ durationSeconds: duration,
56
+ },
57
+ });
58
+ operation = await this.pollOperation(operation);
59
+ if (!operation.response?.generatedVideos?.[0]) {
60
+ throw new Error('No video was generated from image');
61
+ }
62
+ const video = operation.response.generatedVideos[0];
63
+ const videoUrl = video.video?.uri;
64
+ if (!videoUrl) {
65
+ throw new Error('Video URL not available');
66
+ }
67
+ const buffer = await this.downloadVideo(videoUrl);
68
+ const generationTime = Date.now() - startTime;
69
+ return { buffer, url: videoUrl, generationTime };
70
+ }
71
+ async extendVideo(videoBuffer, prompt, options = {}) {
72
+ const startTime = Date.now();
73
+ const { aspectRatio = '16:9', resolution = '720p', } = options;
74
+ const videoBase64 = videoBuffer.toString('base64');
75
+ let operation = await this.ai.models.generateVideos({
76
+ model: this.VEO_MODEL,
77
+ prompt,
78
+ video: {
79
+ videoBytes: videoBase64,
80
+ mimeType: 'video/mp4',
81
+ },
82
+ config: {
83
+ numberOfVideos: 1,
84
+ aspectRatio,
85
+ resolution,
86
+ },
87
+ });
88
+ operation = await this.pollOperation(operation);
89
+ if (!operation.response?.generatedVideos?.[0]) {
90
+ throw new Error('Video extension failed');
91
+ }
92
+ const video = operation.response.generatedVideos[0];
93
+ const videoUrl = video.video?.uri;
94
+ if (!videoUrl) {
95
+ throw new Error('Video URL not available');
96
+ }
97
+ const buffer = await this.downloadVideo(videoUrl);
98
+ const generationTime = Date.now() - startTime;
99
+ return { buffer, url: videoUrl, generationTime };
100
+ }
101
+ async generateVideoWithReferences(prompt, referenceImages, options = {}) {
102
+ if (referenceImages.length === 0 || referenceImages.length > 3) {
103
+ throw new Error('Reference images must be between 1 and 3');
104
+ }
105
+ const startTime = Date.now();
106
+ const { aspectRatio = '16:9', resolution = '720p', duration = 8, numberOfVideos = 1, } = options;
107
+ const references = referenceImages.map((ref) => ({
108
+ image: {
109
+ imageBytes: ref.buffer.toString('base64'),
110
+ mimeType: this.detectImageMimeType(ref.buffer),
111
+ },
112
+ }));
113
+ let operation = await this.ai.models.generateVideos({
114
+ model: this.VEO_PREVIEW_MODEL,
115
+ prompt,
116
+ config: {
117
+ numberOfVideos,
118
+ aspectRatio,
119
+ resolution,
120
+ durationSeconds: duration,
121
+ referenceImages: references,
122
+ },
123
+ });
124
+ operation = await this.pollOperation(operation);
125
+ if (!operation.response?.generatedVideos?.[0]) {
126
+ console.error('Operation response:', JSON.stringify(operation, null, 2));
127
+ throw new Error('No video was generated with references');
128
+ }
129
+ const video = operation.response.generatedVideos[0];
130
+ const videoUrl = video.video?.uri;
131
+ if (!videoUrl) {
132
+ throw new Error('Video URL not available');
133
+ }
134
+ const buffer = await this.downloadVideo(videoUrl);
135
+ const generationTime = Date.now() - startTime;
136
+ return { buffer, url: videoUrl, generationTime };
137
+ }
138
+ async pollOperation(operation) {
139
+ let currentOperation = operation;
140
+ while (!currentOperation.done) {
141
+ await new Promise((resolve) => setTimeout(resolve, this.POLL_INTERVAL_MS));
142
+ currentOperation = await this.ai.operations.getVideosOperation({
143
+ operation: currentOperation,
144
+ });
145
+ }
146
+ return currentOperation;
147
+ }
148
+ async downloadVideo(url) {
149
+ const response = await fetch(url, {
150
+ headers: {
151
+ 'x-goog-api-key': this.apiKey,
152
+ },
153
+ redirect: 'follow',
154
+ });
155
+ if (!response.ok) {
156
+ throw new Error(`Failed to download video: ${response.statusText}`);
157
+ }
158
+ const arrayBuffer = await response.arrayBuffer();
159
+ return Buffer.from(arrayBuffer);
160
+ }
161
+ detectImageMimeType(buffer) {
162
+ if (buffer[0] === 0xff && buffer[1] === 0xd8) {
163
+ return 'image/jpeg';
164
+ }
165
+ if (buffer[0] === 0x89 && buffer[1] === 0x50 && buffer[2] === 0x4e && buffer[3] === 0x47) {
166
+ return 'image/png';
167
+ }
168
+ if (buffer[0] === 0x47 && buffer[1] === 0x49 && buffer[2] === 0x46) {
169
+ return 'image/gif';
170
+ }
171
+ if (buffer[0] === 0x52 && buffer[1] === 0x49 && buffer[2] === 0x46 && buffer[3] === 0x46) {
172
+ return 'image/webp';
173
+ }
174
+ return 'image/png';
175
+ }
176
+ }
177
+ //# sourceMappingURL=gemini.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"gemini.js","sourceRoot":"","sources":["../../src/providers/gemini.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,12 @@
1
+ /**
2
+ * Compare Screenshots Tool
3
+ *
4
+ * Compares two screenshots to detect visual differences.
5
+ * Useful for visual regression testing and identifying UI changes.
6
+ */
7
+ import { type ToolDefinition } from '@opencode-ai/plugin/tool';
8
+ /**
9
+ * Tool definition for compare_screenshots
10
+ */
11
+ export declare const compareScreenshotsTool: ToolDefinition;
12
+ //# sourceMappingURL=compare.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"compare.d.ts","sourceRoot":"","sources":["../../../src/tools/analyze/compare.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAQ,KAAK,cAAc,EAAE,MAAM,0BAA0B,CAAC;AAiBrE;;GAEG;AACH,eAAO,MAAM,sBAAsB,EAAE,cA8EnC,CAAC"}
@@ -0,0 +1,83 @@
1
+ /**
2
+ * Compare Screenshots Tool
3
+ *
4
+ * Compares two screenshots to detect visual differences.
5
+ * Useful for visual regression testing and identifying UI changes.
6
+ */
7
+ import { tool } from '@opencode-ai/plugin/tool';
8
+ import { GeminiProvider } from '../../providers/gemini.js';
9
+ import { loadImage, saveImage, getOutputDir } from '../../utils/file-handler.js';
10
+ /**
11
+ * Tool args schema
12
+ */
13
+ const compareScreenshotsArgs = {
14
+ imagePath1: tool.schema.string()
15
+ .describe('Path to the first screenshot image (baseline/before)'),
16
+ imagePath2: tool.schema.string()
17
+ .describe('Path to the second screenshot image (comparison/after)'),
18
+ highlightDifferences: tool.schema.boolean()
19
+ .optional()
20
+ .describe('If true, generate a visual diff image highlighting the differences. Default: false')
21
+ };
22
+ /**
23
+ * Tool definition for compare_screenshots
24
+ */
25
+ export const compareScreenshotsTool = tool({
26
+ description: 'Compare two screenshots to detect visual differences. Returns a detailed description of changes. Optionally generates a visual diff image highlighting the differences.',
27
+ args: compareScreenshotsArgs,
28
+ async execute(args, _context) {
29
+ try {
30
+ const { imagePath1, imagePath2, highlightDifferences = false } = args;
31
+ // Initialize Gemini provider
32
+ const provider = new GeminiProvider();
33
+ // Load both screenshot images
34
+ const image1Buffer = await loadImage(imagePath1);
35
+ const image2Buffer = await loadImage(imagePath2);
36
+ // Build comparison prompt
37
+ const comparisonPrompt = 'Compare these two screenshots in detail. Identify and describe:\n' +
38
+ '1. Visual differences (layout, colors, text, images)\n' +
39
+ '2. Component changes (added, removed, or modified elements)\n' +
40
+ '3. Spacing and alignment differences\n' +
41
+ '4. Typography changes (font size, weight, color)\n' +
42
+ '5. Overall impact of the changes\n\n' +
43
+ 'Be specific about locations and changes. If the images are identical, clearly state that.';
44
+ // Analyze the comparison using Gemini
45
+ // Note: Gemini's multi-image analysis requires sending both images in a single request
46
+ const analysis = await provider.analyzeMultipleImages([image1Buffer, image2Buffer], comparisonPrompt);
47
+ let resultMessage = `✓ Screenshot Comparison Complete
48
+
49
+ Image 1: ${imagePath1}
50
+ Image 2: ${imagePath2}
51
+
52
+ ${analysis}`;
53
+ // Generate diff highlight image if requested
54
+ if (highlightDifferences) {
55
+ try {
56
+ // Create a prompt for Gemini to generate a visual diff
57
+ const diffPrompt = 'Create a visual difference image that highlights the changes between the two screenshots. ' +
58
+ 'Use red/pink highlighting to mark areas that have changed. ' +
59
+ 'Show both screenshots side by side with the differences clearly marked.';
60
+ const diffBuffer = await provider.editImage(image1Buffer, diffPrompt);
61
+ // Save the diff image
62
+ const outputDir = getOutputDir();
63
+ const diffPath = await saveImage(diffBuffer, outputDir, 'screenshot-diff', 0);
64
+ resultMessage += `\n\n✓ Visual diff image generated: ${diffPath}`;
65
+ }
66
+ catch (diffError) {
67
+ resultMessage += `\n\n⚠ Warning: Could not generate visual diff image: ${diffError instanceof Error ? diffError.message : String(diffError)}`;
68
+ }
69
+ }
70
+ return resultMessage;
71
+ }
72
+ catch (error) {
73
+ if (error instanceof Error && error.message.includes('GEMINI_API_KEY')) {
74
+ return '✗ Error: GEMINI_API_KEY is not set. Please configure your API key in environment variables.';
75
+ }
76
+ if (error instanceof Error && (error.message.includes('ENOENT') || error.message.includes('no such file'))) {
77
+ return `✗ Error: Could not load one or both screenshots. Please verify the file paths exist:\n - ${args.imagePath1}\n - ${args.imagePath2}`;
78
+ }
79
+ return `✗ Error comparing screenshots: ${error instanceof Error ? error.message : String(error)}`;
80
+ }
81
+ }
82
+ });
83
+ //# sourceMappingURL=compare.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"compare.js","sourceRoot":"","sources":["../../../src/tools/analyze/compare.ts"],"names":[],"mappings":"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"}