@hitslop/shots 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 (151) hide show
  1. package/SKILL.md +536 -0
  2. package/dist/cli.d.ts +3 -0
  3. package/dist/cli.d.ts.map +1 -0
  4. package/dist/cli.js +113 -0
  5. package/dist/cli.js.map +1 -0
  6. package/dist/commands/auth.d.ts +7 -0
  7. package/dist/commands/auth.d.ts.map +1 -0
  8. package/dist/commands/auth.js +106 -0
  9. package/dist/commands/auth.js.map +1 -0
  10. package/dist/commands/crop.d.ts +5 -0
  11. package/dist/commands/crop.d.ts.map +1 -0
  12. package/dist/commands/crop.js +32 -0
  13. package/dist/commands/crop.js.map +1 -0
  14. package/dist/commands/default.d.ts +2 -0
  15. package/dist/commands/default.d.ts.map +1 -0
  16. package/dist/commands/default.js +142 -0
  17. package/dist/commands/default.js.map +1 -0
  18. package/dist/commands/feedback.d.ts +2 -0
  19. package/dist/commands/feedback.d.ts.map +1 -0
  20. package/dist/commands/feedback.js +6 -0
  21. package/dist/commands/feedback.js.map +1 -0
  22. package/dist/commands/generate.d.ts +3 -0
  23. package/dist/commands/generate.d.ts.map +1 -0
  24. package/dist/commands/generate.js +5 -0
  25. package/dist/commands/generate.js.map +1 -0
  26. package/dist/commands/init.d.ts +2 -0
  27. package/dist/commands/init.d.ts.map +1 -0
  28. package/dist/commands/init.js +5 -0
  29. package/dist/commands/init.js.map +1 -0
  30. package/dist/commands/install.d.ts +2 -0
  31. package/dist/commands/install.d.ts.map +1 -0
  32. package/dist/commands/install.js +13 -0
  33. package/dist/commands/install.js.map +1 -0
  34. package/dist/commands/scrape.d.ts +5 -0
  35. package/dist/commands/scrape.d.ts.map +1 -0
  36. package/dist/commands/scrape.js +5 -0
  37. package/dist/commands/scrape.js.map +1 -0
  38. package/dist/commands/studio.d.ts +7 -0
  39. package/dist/commands/studio.d.ts.map +1 -0
  40. package/dist/commands/studio.js +351 -0
  41. package/dist/commands/studio.js.map +1 -0
  42. package/dist/commands/styles.d.ts +2 -0
  43. package/dist/commands/styles.d.ts.map +1 -0
  44. package/dist/commands/styles.js +25 -0
  45. package/dist/commands/styles.js.map +1 -0
  46. package/dist/commands/view.d.ts +2 -0
  47. package/dist/commands/view.d.ts.map +1 -0
  48. package/dist/commands/view.js +25 -0
  49. package/dist/commands/view.js.map +1 -0
  50. package/dist/core/crop-pipeline.d.ts +28 -0
  51. package/dist/core/crop-pipeline.d.ts.map +1 -0
  52. package/dist/core/crop-pipeline.js +82 -0
  53. package/dist/core/crop-pipeline.js.map +1 -0
  54. package/dist/core/generate.d.ts +20 -0
  55. package/dist/core/generate.d.ts.map +1 -0
  56. package/dist/core/generate.js +388 -0
  57. package/dist/core/generate.js.map +1 -0
  58. package/dist/core/init.d.ts +3 -0
  59. package/dist/core/init.d.ts.map +1 -0
  60. package/dist/core/init.js +77 -0
  61. package/dist/core/init.js.map +1 -0
  62. package/dist/core/mock-generator.d.ts +5 -0
  63. package/dist/core/mock-generator.d.ts.map +1 -0
  64. package/dist/core/mock-generator.js +42 -0
  65. package/dist/core/mock-generator.js.map +1 -0
  66. package/dist/core/prompt-builder.d.ts +15 -0
  67. package/dist/core/prompt-builder.d.ts.map +1 -0
  68. package/dist/core/prompt-builder.js +195 -0
  69. package/dist/core/prompt-builder.js.map +1 -0
  70. package/dist/core/providers/fal.d.ts +3 -0
  71. package/dist/core/providers/fal.d.ts.map +1 -0
  72. package/dist/core/providers/fal.js +53 -0
  73. package/dist/core/providers/fal.js.map +1 -0
  74. package/dist/core/providers/index.d.ts +3 -0
  75. package/dist/core/providers/index.d.ts.map +1 -0
  76. package/dist/core/providers/index.js +2 -0
  77. package/dist/core/providers/index.js.map +1 -0
  78. package/dist/core/providers/managed.d.ts +3 -0
  79. package/dist/core/providers/managed.d.ts.map +1 -0
  80. package/dist/core/providers/managed.js +132 -0
  81. package/dist/core/providers/managed.js.map +1 -0
  82. package/dist/core/providers/openai.d.ts +3 -0
  83. package/dist/core/providers/openai.d.ts.map +1 -0
  84. package/dist/core/providers/openai.js +40 -0
  85. package/dist/core/providers/openai.js.map +1 -0
  86. package/dist/core/providers/replicate.d.ts +3 -0
  87. package/dist/core/providers/replicate.d.ts.map +1 -0
  88. package/dist/core/providers/replicate.js +87 -0
  89. package/dist/core/providers/replicate.js.map +1 -0
  90. package/dist/core/providers/resolve.d.ts +3 -0
  91. package/dist/core/providers/resolve.d.ts.map +1 -0
  92. package/dist/core/providers/resolve.js +41 -0
  93. package/dist/core/providers/resolve.js.map +1 -0
  94. package/dist/core/providers/types.d.ts +29 -0
  95. package/dist/core/providers/types.d.ts.map +1 -0
  96. package/dist/core/providers/types.js +2 -0
  97. package/dist/core/providers/types.js.map +1 -0
  98. package/dist/core/scraper.d.ts +22 -0
  99. package/dist/core/scraper.d.ts.map +1 -0
  100. package/dist/core/scraper.js +138 -0
  101. package/dist/core/scraper.js.map +1 -0
  102. package/dist/core/walkthrough.d.ts +10 -0
  103. package/dist/core/walkthrough.d.ts.map +1 -0
  104. package/dist/core/walkthrough.js +116 -0
  105. package/dist/core/walkthrough.js.map +1 -0
  106. package/dist/schema/config.d.ts +45 -0
  107. package/dist/schema/config.d.ts.map +1 -0
  108. package/dist/schema/config.js +36 -0
  109. package/dist/schema/config.js.map +1 -0
  110. package/dist/schema/manifest.d.ts +43 -0
  111. package/dist/schema/manifest.d.ts.map +1 -0
  112. package/dist/schema/manifest.js +5 -0
  113. package/dist/schema/manifest.js.map +1 -0
  114. package/dist/schema/style-meta.d.ts +8 -0
  115. package/dist/schema/style-meta.d.ts.map +1 -0
  116. package/dist/schema/style-meta.js +2 -0
  117. package/dist/schema/style-meta.js.map +1 -0
  118. package/dist/styles/installer.d.ts +2 -0
  119. package/dist/styles/installer.d.ts.map +1 -0
  120. package/dist/styles/installer.js +43 -0
  121. package/dist/styles/installer.js.map +1 -0
  122. package/dist/styles/registry.d.ts +20 -0
  123. package/dist/styles/registry.d.ts.map +1 -0
  124. package/dist/styles/registry.js +96 -0
  125. package/dist/styles/registry.js.map +1 -0
  126. package/dist/util/auth-store.d.ts +12 -0
  127. package/dist/util/auth-store.d.ts.map +1 -0
  128. package/dist/util/auth-store.js +46 -0
  129. package/dist/util/auth-store.js.map +1 -0
  130. package/dist/util/id.d.ts +2 -0
  131. package/dist/util/id.d.ts.map +1 -0
  132. package/dist/util/id.js +14 -0
  133. package/dist/util/id.js.map +1 -0
  134. package/dist/util/json.d.ts +3 -0
  135. package/dist/util/json.d.ts.map +1 -0
  136. package/dist/util/json.js +9 -0
  137. package/dist/util/json.js.map +1 -0
  138. package/dist/util/open.d.ts +2 -0
  139. package/dist/util/open.d.ts.map +1 -0
  140. package/dist/util/open.js +21 -0
  141. package/dist/util/open.js.map +1 -0
  142. package/dist/util/paths.d.ts +9 -0
  143. package/dist/util/paths.d.ts.map +1 -0
  144. package/dist/util/paths.js +21 -0
  145. package/dist/util/paths.js.map +1 -0
  146. package/package.json +37 -0
  147. package/studio/assets/index-BgiuT_Mv.css +1 -0
  148. package/studio/assets/index-DnN633_x.js +9 -0
  149. package/studio/index.html +13 -0
  150. package/styles/clean-premium/meta.json +7 -0
  151. package/styles/clean-premium/prompt.md +16 -0
@@ -0,0 +1,388 @@
1
+ import { Buffer } from "node:buffer";
2
+ import fs from "node:fs/promises";
3
+ import path from "node:path";
4
+ import sharp from "sharp";
5
+ import { generateId } from "../util/id.js";
6
+ import { readJson, writeJson } from "../util/json.js";
7
+ import { shotsDir } from "../util/paths.js";
8
+ import { buildPrompt, buildStyledPrompt, buildPanelPrompt } from "./prompt-builder.js";
9
+ import { cropAndResize, getCompositeSize, getPanelDimensions, } from "./crop-pipeline.js";
10
+ import { generateMockComposite } from "./mock-generator.js";
11
+ import { loadInstalledStyle } from "../styles/registry.js";
12
+ import { resolveProvider } from "./providers/index.js";
13
+ import { openPath } from "../util/open.js";
14
+ function mimeTypeFor(filePath) {
15
+ const ext = path.extname(filePath).toLowerCase();
16
+ if (ext === ".jpg" || ext === ".jpeg")
17
+ return "image/jpeg";
18
+ if (ext === ".webp")
19
+ return "image/webp";
20
+ if (ext === ".gif")
21
+ return "image/gif";
22
+ return "image/png";
23
+ }
24
+ function relativeToShotsDir(dir, filePath) {
25
+ const relative = path.relative(dir, filePath);
26
+ return relative.startsWith("..") ? filePath : relative;
27
+ }
28
+ export async function runGenerate(opts) {
29
+ const dir = shotsDir();
30
+ // Validate .shots/ exists
31
+ try {
32
+ await fs.access(dir);
33
+ }
34
+ catch {
35
+ console.error("Error: .shots/ directory not found. Run `npx -y @hitslop/shots@latest init` to initialize first.");
36
+ process.exit(1);
37
+ }
38
+ const config = await readJson(path.join(dir, "config.json"));
39
+ const manifest = await readJson(path.join(dir, "manifest.json"));
40
+ // Handle feedback-for
41
+ let basePrompt = opts.prompt ?? "";
42
+ let parentId = null;
43
+ const feedback = [];
44
+ if (opts.feedbackFor) {
45
+ const parentShot = manifest.shots.find((s) => s.id === opts.feedbackFor);
46
+ if (!parentShot) {
47
+ console.error(`Error: Shot "${opts.feedbackFor}" not found in manifest.`);
48
+ process.exit(1);
49
+ }
50
+ parentId = parentShot.id;
51
+ if (opts.prompt) {
52
+ feedback.push({
53
+ from: "user",
54
+ text: opts.prompt,
55
+ at: new Date().toISOString(),
56
+ });
57
+ basePrompt = `${parentShot.prompt}\n\nRevision instructions: ${opts.prompt}`;
58
+ }
59
+ else {
60
+ basePrompt = parentShot.prompt;
61
+ }
62
+ }
63
+ if (!basePrompt.trim()) {
64
+ console.error("Error: --prompt is required (or --feedback-for with an existing shot).");
65
+ process.exit(1);
66
+ }
67
+ // Determine style
68
+ const styleName = opts.style || config.activeStyle;
69
+ const panelCount = opts.panels ?? 3;
70
+ if (panelCount > 3) {
71
+ console.error(`Error: --panels ${panelCount} exceeds the maximum of 3 per run.`);
72
+ console.error("Run the generate command multiple times for more panels (e.g. two runs of 3 for 6 total).");
73
+ process.exit(1);
74
+ }
75
+ const mode = opts.mode ?? "composite";
76
+ const platform = opts.platform ?? "iphone";
77
+ let fullPrompt;
78
+ if (styleName) {
79
+ const style = await loadInstalledStyle(styleName);
80
+ if (style) {
81
+ fullPrompt = buildStyledPrompt(style.promptTemplate, config, basePrompt, panelCount, platform);
82
+ console.log(`Using style: ${style.meta.displayName}`);
83
+ }
84
+ else {
85
+ console.warn(`Warning: Style "${styleName}" not found, using default prompt.`);
86
+ fullPrompt = buildPrompt(config, basePrompt, panelCount, platform);
87
+ }
88
+ }
89
+ else {
90
+ fullPrompt = buildPrompt(config, basePrompt, panelCount, platform);
91
+ }
92
+ const quality = (opts.quality ?? "high");
93
+ const { width: compositeWidth, height: compositeHeight } = getCompositeSize(panelCount, platform);
94
+ const target = getPanelDimensions(platform);
95
+ const setName = opts.setName ?? "default";
96
+ // Load reference images (provider-agnostic)
97
+ const referenceImages = [];
98
+ const references = [];
99
+ if (opts.references) {
100
+ const refPaths = opts.references.split(",").map((p) => p.trim()).filter(Boolean);
101
+ for (const refPath of refPaths) {
102
+ const absolutePath = path.resolve(refPath);
103
+ try {
104
+ const buffer = await fs.readFile(absolutePath);
105
+ referenceImages.push({
106
+ buffer,
107
+ filename: path.basename(absolutePath),
108
+ mimeType: mimeTypeFor(absolutePath),
109
+ });
110
+ references.push({
111
+ source: "user",
112
+ filename: path.basename(absolutePath),
113
+ originalPath: absolutePath,
114
+ manifestPath: relativeToShotsDir(dir, absolutePath),
115
+ included: true,
116
+ });
117
+ }
118
+ catch (err) {
119
+ console.warn(`Warning: Could not read reference image "${refPath}": ${err}`);
120
+ references.push({
121
+ source: "user",
122
+ filename: path.basename(refPath),
123
+ originalPath: refPath,
124
+ manifestPath: refPath,
125
+ included: false,
126
+ });
127
+ }
128
+ }
129
+ if (referenceImages.length > 0) {
130
+ console.log(`Using ${referenceImages.length} reference image(s)`);
131
+ }
132
+ }
133
+ // Also include style assets as references if style is active
134
+ if (styleName) {
135
+ const styleAssetsDir = path.join(dir, "styles", styleName, "assets");
136
+ try {
137
+ const assetFiles = await fs.readdir(styleAssetsDir);
138
+ for (const assetFile of assetFiles) {
139
+ if (/\.(png|jpg|jpeg|webp)$/i.test(assetFile)) {
140
+ const assetPath = path.join(styleAssetsDir, assetFile);
141
+ const buffer = await fs.readFile(assetPath);
142
+ referenceImages.push({
143
+ buffer,
144
+ filename: assetFile,
145
+ mimeType: mimeTypeFor(assetPath),
146
+ });
147
+ references.push({
148
+ source: "style",
149
+ filename: assetFile,
150
+ originalPath: assetPath,
151
+ manifestPath: `styles/${styleName}/assets/${assetFile}`,
152
+ included: true,
153
+ });
154
+ }
155
+ }
156
+ }
157
+ catch {
158
+ // No assets directory or empty — that's fine
159
+ }
160
+ }
161
+ // Generate ID and set up run directory
162
+ const existingIds = new Set(manifest.shots.map((s) => s.id));
163
+ const shotId = generateId(existingIds);
164
+ const runRelativeDir = `runs/${shotId}`;
165
+ const runDir = path.join(dir, runRelativeDir);
166
+ const runScreenshotsDir = path.join(runDir, "screenshots");
167
+ await fs.mkdir(runScreenshotsDir, { recursive: true });
168
+ let screenshotFiles;
169
+ let providerName = "mock";
170
+ if (mode === "individual") {
171
+ // --- Individual mode: one API call per panel ---
172
+ const { width: singlePanelWidth, height: singlePanelHeight } = getCompositeSize(1, platform);
173
+ console.log(`Generating ${opts.mock ? "(mock) " : ""}${panelCount} individual panel${panelCount > 1 ? "s" : ""} for "${config.appName}"...`);
174
+ console.log(`Mode: individual (${singlePanelWidth}x${singlePanelHeight} per panel)`);
175
+ console.log(`Quality: ${quality}`);
176
+ screenshotFiles = [];
177
+ for (let i = 0; i < panelCount; i++) {
178
+ const panelPrompt = buildPanelPrompt(config, basePrompt, i, panelCount, platform);
179
+ console.log(`\nPanel ${i + 1}/${panelCount}: ${panelPrompt.slice(0, 120)}...`);
180
+ let panelBuffer;
181
+ if (opts.mock) {
182
+ // Mock: generate single-panel composite
183
+ panelBuffer = await generateMockComposite(config, panelPrompt, 1, platform);
184
+ }
185
+ else {
186
+ const provider = resolveProvider(opts.provider);
187
+ providerName = provider.name;
188
+ const result = await provider.generate({
189
+ prompt: panelPrompt,
190
+ references: referenceImages,
191
+ quality,
192
+ width: singlePanelWidth,
193
+ height: singlePanelHeight,
194
+ panelCount: 1,
195
+ platform,
196
+ managedProvider: opts.managedProvider,
197
+ n: 1,
198
+ });
199
+ panelBuffer = result.imageBuffer;
200
+ }
201
+ // Resize to target dimensions
202
+ const resizedBuffer = await sharp(panelBuffer)
203
+ .resize(target.width, target.height, { fit: "fill" })
204
+ .png()
205
+ .toBuffer();
206
+ const filename = `panel-${i + 1}.png`;
207
+ await fs.writeFile(path.join(runScreenshotsDir, filename), resizedBuffer);
208
+ screenshotFiles.push(`${runRelativeDir}/screenshots/${filename}`);
209
+ console.log(` Saved: ${runRelativeDir}/screenshots/${filename}`);
210
+ }
211
+ // Save a placeholder composite note (no actual composite in individual mode)
212
+ await fs.writeFile(path.join(runDir, "composite.png"), Buffer.from("individual mode — no composite generated"));
213
+ }
214
+ else {
215
+ // --- Composite mode (default): one API call for the full wide image ---
216
+ console.log(`Generating ${opts.mock ? "(mock) " : ""}composite for "${config.appName}"...`);
217
+ console.log(`Mode: composite`);
218
+ console.log(`Canvas: ${compositeWidth}x${compositeHeight} (${panelCount} panel${panelCount > 1 ? "s" : ""})`);
219
+ console.log(`Quality: ${quality}`);
220
+ console.log(`Prompt: ${fullPrompt.slice(0, 200)}...`);
221
+ let compositeBuffer;
222
+ if (opts.mock) {
223
+ compositeBuffer = await generateMockComposite(config, fullPrompt, panelCount, platform);
224
+ }
225
+ else {
226
+ const provider = resolveProvider(opts.provider);
227
+ providerName = provider.name;
228
+ const result = await provider.generate({
229
+ prompt: fullPrompt,
230
+ references: referenceImages,
231
+ quality,
232
+ width: compositeWidth,
233
+ height: compositeHeight,
234
+ panelCount,
235
+ platform,
236
+ managedProvider: opts.managedProvider,
237
+ n: 1,
238
+ });
239
+ compositeBuffer = result.imageBuffer;
240
+ }
241
+ // Save composite
242
+ await fs.writeFile(path.join(runDir, "composite.png"), compositeBuffer);
243
+ console.log(`Composite saved: ${runRelativeDir}/composite.png`);
244
+ // Crop and resize panels
245
+ screenshotFiles = await cropAndResize(compositeBuffer, shotId, panelCount, {
246
+ outputDir: runScreenshotsDir,
247
+ manifestPrefix: `${runRelativeDir}/screenshots`,
248
+ platform,
249
+ });
250
+ console.log(`Screenshots saved:`);
251
+ for (const f of screenshotFiles) {
252
+ console.log(` ${f}`);
253
+ }
254
+ }
255
+ const createdAt = new Date().toISOString();
256
+ const promptFile = `${runRelativeDir}/prompt.md`;
257
+ const referencesFile = `${runRelativeDir}/references.json`;
258
+ const feedbackFile = `${runRelativeDir}/feedback.json`;
259
+ const metadataFile = `${runRelativeDir}/metadata.json`;
260
+ const compositeFile = `${runRelativeDir}/composite.png`;
261
+ const modelName = modelNameForRun(opts.mock ?? false, providerName, opts.managedProvider);
262
+ const metadataCompositeSize = mode === "individual"
263
+ ? getCompositeSize(1, platform)
264
+ : { width: compositeWidth, height: compositeHeight };
265
+ await fs.writeFile(path.join(runDir, "prompt.md"), [
266
+ `# ${shotId}`,
267
+ "",
268
+ "## User Prompt",
269
+ "",
270
+ opts.prompt?.trim() || "(generated from parent prompt)",
271
+ "",
272
+ "## Full Prompt",
273
+ "",
274
+ fullPrompt,
275
+ "",
276
+ ].join("\n"), "utf-8");
277
+ await writeJson(path.join(runDir, "references.json"), {
278
+ shotId,
279
+ createdAt,
280
+ references,
281
+ });
282
+ await writeJson(path.join(runDir, "feedback.json"), feedback);
283
+ await writeJson(path.join(runDir, "metadata.json"), {
284
+ id: shotId,
285
+ model: modelName,
286
+ provider: providerName,
287
+ managedProvider: providerName === "managed" ? opts.managedProvider ?? "openai" : undefined,
288
+ mode,
289
+ quality,
290
+ setName,
291
+ parentId,
292
+ styleName: styleName ?? "",
293
+ panelCount,
294
+ dimensions: {
295
+ platform,
296
+ compositeWidth: metadataCompositeSize.width,
297
+ compositeHeight: metadataCompositeSize.height,
298
+ targetWidth: target.width,
299
+ targetHeight: target.height,
300
+ },
301
+ createdAt,
302
+ compositeFile,
303
+ screenshotFiles,
304
+ promptFile,
305
+ referencesFile,
306
+ feedbackFile,
307
+ metadataFile,
308
+ });
309
+ // Update manifest
310
+ const shot = {
311
+ id: shotId,
312
+ compositeFile,
313
+ screenshotFiles,
314
+ prompt: fullPrompt,
315
+ userPrompt: opts.prompt ?? "",
316
+ runDir: runRelativeDir,
317
+ promptFile,
318
+ referencesFile,
319
+ feedbackFile,
320
+ metadataFile,
321
+ model: modelName,
322
+ provider: providerName,
323
+ managedProvider: providerName === "managed" ? opts.managedProvider ?? "openai" : undefined,
324
+ mode,
325
+ quality,
326
+ referenceImages: references.filter((r) => r.included).map((r) => r.manifestPath),
327
+ feedback,
328
+ parentId,
329
+ styleName: styleName ?? "",
330
+ setName,
331
+ panelCount,
332
+ dimensions: {
333
+ platform,
334
+ compositeWidth: metadataCompositeSize.width,
335
+ compositeHeight: metadataCompositeSize.height,
336
+ targetWidth: target.width,
337
+ targetHeight: target.height,
338
+ },
339
+ createdAt,
340
+ };
341
+ manifest.version = Math.max(manifest.version ?? 1, 2);
342
+ manifest.shots.push(shot);
343
+ await writeJson(path.join(dir, "manifest.json"), manifest);
344
+ console.log(`\nDone! Shot ID: ${shotId} (provider: ${providerName}, mode: ${mode})`);
345
+ console.log(`Run folder: ${path.join(dir, runRelativeDir)}`);
346
+ if (!openPath(runDir)) {
347
+ console.log("Could not open the run folder automatically.");
348
+ }
349
+ }
350
+ function modelNameForRun(mock, providerName, managedProvider) {
351
+ if (mock)
352
+ return "mock";
353
+ if (providerName === "openai")
354
+ return "gpt-image-2";
355
+ if (providerName === "fal")
356
+ return "fal-ai/gpt-image-2";
357
+ if (providerName === "replicate")
358
+ return "openai/gpt-image-2";
359
+ if (providerName === "managed")
360
+ return `managed:${managedProvider ?? "openai"}`;
361
+ return providerName;
362
+ }
363
+ export async function appendFeedback(shotId, text, from = "user") {
364
+ const dir = shotsDir();
365
+ const manifestPath = path.join(dir, "manifest.json");
366
+ const manifest = await readJson(manifestPath);
367
+ const shot = manifest.shots.find((s) => s.id === shotId);
368
+ if (!shot) {
369
+ throw new Error(`Shot "${shotId}" not found in manifest.`);
370
+ }
371
+ const entry = {
372
+ from,
373
+ text,
374
+ at: new Date().toISOString(),
375
+ };
376
+ shot.feedback = [...(shot.feedback ?? []), entry];
377
+ if (shot.feedbackFile) {
378
+ await writeJson(path.join(dir, shot.feedbackFile), shot.feedback);
379
+ }
380
+ else if (shot.runDir) {
381
+ const feedbackFile = `${shot.runDir}/feedback.json`;
382
+ shot.feedbackFile = feedbackFile;
383
+ await writeJson(path.join(dir, feedbackFile), shot.feedback);
384
+ }
385
+ manifest.version = Math.max(manifest.version ?? 1, 2);
386
+ await writeJson(manifestPath, manifest);
387
+ }
388
+ //# sourceMappingURL=generate.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"generate.js","sourceRoot":"","sources":["../../src/core/generate.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ import { type Config } from "../schema/config.js";
2
+ export declare function initWorkspace(configOverride?: Partial<Config>): Promise<void>;
3
+ //# sourceMappingURL=init.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"init.d.ts","sourceRoot":"","sources":["../../src/core/init.ts"],"names":[],"mappings":"AAEA,OAAO,EAAkB,KAAK,MAAM,EAAE,MAAM,qBAAqB,CAAC;AAclE,wBAAsB,aAAa,CAAC,cAAc,CAAC,EAAE,OAAO,CAAC,MAAM,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC,CAyEnF"}
@@ -0,0 +1,77 @@
1
+ import fs from "node:fs/promises";
2
+ import path from "node:path";
3
+ import { DEFAULT_CONFIG } from "../schema/config.js";
4
+ import { DEFAULT_MANIFEST } from "../schema/manifest.js";
5
+ import { packageRoot, shotsDir } from "../util/paths.js";
6
+ import { writeJson } from "../util/json.js";
7
+ async function exists(filePath) {
8
+ try {
9
+ await fs.access(filePath);
10
+ return true;
11
+ }
12
+ catch {
13
+ return false;
14
+ }
15
+ }
16
+ export async function initWorkspace(configOverride) {
17
+ const dir = shotsDir();
18
+ if (await exists(dir)) {
19
+ console.log(".shots/ already exists — skipping initialization.");
20
+ console.log("To reinitialize, delete .shots/ and run again.");
21
+ return;
22
+ }
23
+ console.log("Initializing .shots/ workspace...\n");
24
+ // Create directory structure
25
+ const dirs = [
26
+ dir,
27
+ path.join(dir, "inspo"),
28
+ path.join(dir, "app-screenshots"),
29
+ path.join(dir, "previous-screenshots"),
30
+ path.join(dir, "runs"),
31
+ ];
32
+ for (const d of dirs) {
33
+ await fs.mkdir(d, { recursive: true });
34
+ console.log(` Created ${path.relative(process.cwd(), d)}/`);
35
+ }
36
+ // Write config (merge override with defaults if provided)
37
+ const configPath = path.join(dir, "config.json");
38
+ const config = configOverride
39
+ ? { ...DEFAULT_CONFIG, ...configOverride }
40
+ : DEFAULT_CONFIG;
41
+ await writeJson(configPath, config);
42
+ console.log(` Created ${path.relative(process.cwd(), configPath)}`);
43
+ // Write default manifest
44
+ const manifestPath = path.join(dir, "manifest.json");
45
+ await writeJson(manifestPath, DEFAULT_MANIFEST);
46
+ console.log(` Created ${path.relative(process.cwd(), manifestPath)}`);
47
+ // Write .gitignore
48
+ const gitignorePath = path.join(dir, ".gitignore");
49
+ await fs.writeFile(gitignorePath, [
50
+ "# Keep generated images out of git by default",
51
+ "runs/",
52
+ "",
53
+ ].join("\n"), "utf-8");
54
+ console.log(` Created ${path.relative(process.cwd(), gitignorePath)}`);
55
+ // Install SKILL.md as agent skills
56
+ const skillSource = path.join(packageRoot(), "SKILL.md");
57
+ const skillTargets = [
58
+ path.join(process.cwd(), ".claude", "skills", "shots", "SKILL.md"),
59
+ path.join(process.cwd(), ".agents", "skills", "shots", "SKILL.md"),
60
+ ];
61
+ try {
62
+ const skillContent = await fs.readFile(skillSource, "utf-8");
63
+ for (const target of skillTargets) {
64
+ await fs.mkdir(path.dirname(target), { recursive: true });
65
+ await fs.writeFile(target, skillContent, "utf-8");
66
+ console.log(` Created ${path.relative(process.cwd(), target)}`);
67
+ }
68
+ }
69
+ catch {
70
+ // SKILL.md not found in package — skip silently (dev mode, etc.)
71
+ }
72
+ console.log("\nReady! Next steps:");
73
+ console.log(" 1. Drop app screenshots into .shots/app-screenshots/");
74
+ console.log(" 2. Drop inspiration into .shots/inspo/");
75
+ console.log(" 3. Run `npx -y @hitslop/shots@latest studio` to open the local workspace UI");
76
+ }
77
+ //# sourceMappingURL=init.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"init.js","sourceRoot":"","sources":["../../src/core/init.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,5 @@
1
+ import { Buffer } from "node:buffer";
2
+ import type { Config } from "../schema/config.js";
3
+ import { type AppStorePlatform } from "./crop-pipeline.js";
4
+ export declare function generateMockComposite(config: Config, prompt: string, panelCount?: number, platform?: AppStorePlatform): Promise<Buffer>;
5
+ //# sourceMappingURL=mock-generator.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mock-generator.d.ts","sourceRoot":"","sources":["../../src/core/mock-generator.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AAErC,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,qBAAqB,CAAC;AAClD,OAAO,EAAoB,KAAK,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AAU7E,wBAAsB,qBAAqB,CACzC,MAAM,EAAE,MAAM,EACd,MAAM,EAAE,MAAM,EACd,UAAU,GAAE,MAAU,EACtB,QAAQ,GAAE,gBAA2B,GACpC,OAAO,CAAC,MAAM,CAAC,CAgCjB"}
@@ -0,0 +1,42 @@
1
+ import { Buffer } from "node:buffer";
2
+ import sharp from "sharp";
3
+ import { getCompositeSize } from "./crop-pipeline.js";
4
+ function escapeSvg(value) {
5
+ return value
6
+ .replaceAll("&", "&amp;")
7
+ .replaceAll("<", "&lt;")
8
+ .replaceAll(">", "&gt;")
9
+ .replaceAll('"', "&quot;");
10
+ }
11
+ export async function generateMockComposite(config, prompt, panelCount = 3, platform = "iphone") {
12
+ const { width: compositeWidth, height: compositeHeight } = getCompositeSize(panelCount, platform);
13
+ const panelWidth = Math.floor(compositeWidth / panelCount);
14
+ const hues = ["#f2efe8", "#e8eef2", "#eef1e4", "#f0e8f2", "#e4eef1", "#f2efe4"];
15
+ const promptLines = prompt.slice(0, 600).split(/[.!]\s+/).slice(0, panelCount);
16
+ const svgPanels = Array.from({ length: panelCount }, (_, index) => {
17
+ const x = index * panelWidth;
18
+ const hue = hues[index % hues.length];
19
+ const title = `Panel ${index + 1}`;
20
+ const desc = escapeSvg(promptLines[index] ?? title);
21
+ return `
22
+ <g transform="translate(${x} 0)">
23
+ <rect width="${panelWidth}" height="${compositeHeight}" fill="${hue}" />
24
+ <text x="96" y="250" font-size="56" font-family="Arial, sans-serif" font-weight="700" fill="#1f2528">${escapeSvg(title)}</text>
25
+ <foreignObject x="96" y="380" width="${panelWidth - 192}" height="620">
26
+ <div xmlns="http://www.w3.org/1999/xhtml" style="font-family: Arial, sans-serif; font-size: 88px; line-height: 1.02; font-weight: 800; color: #15191b;">${escapeSvg(config.appName)}</div>
27
+ </foreignObject>
28
+ <foreignObject x="96" y="1120" width="${panelWidth - 192}" height="420">
29
+ <div xmlns="http://www.w3.org/1999/xhtml" style="font-family: Arial, sans-serif; font-size: 44px; line-height: 1.25; color: #435057;">${desc}</div>
30
+ </foreignObject>
31
+ <rect x="96" y="1660" width="${panelWidth - 192}" height="520" rx="38" fill="${config.brandColors.primary}" opacity="0.88" />
32
+ <text x="144" y="1780" font-size="42" font-family="Arial, sans-serif" font-weight="700" fill="${config.brandColors.text}">${escapeSvg(config.appName)}</text>
33
+ <foreignObject x="144" y="1840" width="${panelWidth - 288}" height="240">
34
+ <div xmlns="http://www.w3.org/1999/xhtml" style="font-family: Arial, sans-serif; font-size: 36px; line-height: 1.22; color: ${config.brandColors.text};">Mock screenshot panel ${index + 1}</div>
35
+ </foreignObject>
36
+ </g>
37
+ `;
38
+ }).join("");
39
+ const svg = `<svg width="${compositeWidth}" height="${compositeHeight}" viewBox="0 0 ${compositeWidth} ${compositeHeight}" xmlns="http://www.w3.org/2000/svg">${svgPanels}</svg>`;
40
+ return await sharp(Buffer.from(svg)).png().toBuffer();
41
+ }
42
+ //# sourceMappingURL=mock-generator.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mock-generator.js","sourceRoot":"","sources":["../../src/core/mock-generator.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AACrC,OAAO,KAAK,MAAM,OAAO,CAAC;AAE1B,OAAO,EAAE,gBAAgB,EAAyB,MAAM,oBAAoB,CAAC;AAE7E,SAAS,SAAS,CAAC,KAAa;IAC9B,OAAO,KAAK;SACT,UAAU,CAAC,GAAG,EAAE,OAAO,CAAC;SACxB,UAAU,CAAC,GAAG,EAAE,MAAM,CAAC;SACvB,UAAU,CAAC,GAAG,EAAE,MAAM,CAAC;SACvB,UAAU,CAAC,GAAG,EAAE,QAAQ,CAAC,CAAC;AAC/B,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,qBAAqB,CACzC,MAAc,EACd,MAAc,EACd,aAAqB,CAAC,EACtB,WAA6B,QAAQ;IAErC,MAAM,EAAE,KAAK,EAAE,cAAc,EAAE,MAAM,EAAE,eAAe,EAAE,GAAG,gBAAgB,CAAC,UAAU,EAAE,QAAQ,CAAC,CAAC;IAClG,MAAM,UAAU,GAAG,IAAI,CAAC,KAAK,CAAC,cAAc,GAAG,UAAU,CAAC,CAAC;IAC3D,MAAM,IAAI,GAAG,CAAC,SAAS,EAAE,SAAS,EAAE,SAAS,EAAE,SAAS,EAAE,SAAS,EAAE,SAAS,CAAC,CAAC;IAChF,MAAM,WAAW,GAAG,MAAM,CAAC,KAAK,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC,KAAK,CAAC,SAAS,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,UAAU,CAAC,CAAC;IAE/E,MAAM,SAAS,GAAG,KAAK,CAAC,IAAI,CAAC,EAAE,MAAM,EAAE,UAAU,EAAE,EAAE,CAAC,CAAC,EAAE,KAAK,EAAE,EAAE;QAChE,MAAM,CAAC,GAAG,KAAK,GAAG,UAAU,CAAC;QAC7B,MAAM,GAAG,GAAG,IAAI,CAAC,KAAK,GAAG,IAAI,CAAC,MAAM,CAAC,CAAC;QACtC,MAAM,KAAK,GAAG,SAAS,KAAK,GAAG,CAAC,EAAE,CAAC;QACnC,MAAM,IAAI,GAAG,SAAS,CAAC,WAAW,CAAC,KAAK,CAAC,IAAI,KAAK,CAAC,CAAC;QACpD,OAAO;gCACqB,CAAC;uBACV,UAAU,aAAa,eAAe,WAAW,GAAG;+GACoC,SAAS,CAAC,KAAK,CAAC;+CAChF,UAAU,GAAG,GAAG;oKACqG,SAAS,CAAC,MAAM,CAAC,OAAO,CAAC;;gDAE7I,UAAU,GAAG,GAAG;kJACkF,IAAI;;uCAE/G,UAAU,GAAG,GAAG,gCAAgC,MAAM,CAAC,WAAW,CAAC,OAAO;wGACT,MAAM,CAAC,WAAW,CAAC,IAAI,KAAK,SAAS,CAAC,MAAM,CAAC,OAAO,CAAC;iDAC5G,UAAU,GAAG,GAAG;wIACuE,MAAM,CAAC,WAAW,CAAC,IAAI,4BAA4B,KAAK,GAAG,CAAC;;;KAG/L,CAAC;IACJ,CAAC,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IAEZ,MAAM,GAAG,GAAG,eAAe,cAAc,aAAa,eAAe,kBAAkB,cAAc,IAAI,eAAe,wCAAwC,SAAS,QAAQ,CAAC;IAClL,OAAO,MAAM,KAAK,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,EAAE,CAAC,QAAQ,EAAE,CAAC;AACxD,CAAC"}
@@ -0,0 +1,15 @@
1
+ import type { Config, Benefit } from "../schema/config.js";
2
+ import { type AppStorePlatform } from "./crop-pipeline.js";
3
+ /**
4
+ * Build per-panel descriptions from the benefits array, sorted by narrative arc.
5
+ * Returns an array of description strings, one per panel.
6
+ */
7
+ export declare function buildBenefitPanelDescriptions(benefits: Benefit[], panelCount: number): string[];
8
+ export declare function buildPrompt(config: Config, userPrompt: string, panelCount?: number, platform?: AppStorePlatform): string;
9
+ /**
10
+ * Build a focused prompt for a single panel in individual generation mode.
11
+ * Each panel gets the model's full attention with context about its position.
12
+ */
13
+ export declare function buildPanelPrompt(config: Config, userPrompt: string, panelIndex: number, panelCount: number, platform?: AppStorePlatform): string;
14
+ export declare function buildStyledPrompt(template: string, config: Config, userPrompt: string, panelCount?: number, platform?: AppStorePlatform): string;
15
+ //# sourceMappingURL=prompt-builder.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"prompt-builder.d.ts","sourceRoot":"","sources":["../../src/core/prompt-builder.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,qBAAqB,CAAC;AAC3D,OAAO,EAGL,KAAK,gBAAgB,EACtB,MAAM,oBAAoB,CAAC;AAW5B;;;GAGG;AACH,wBAAgB,6BAA6B,CAAC,QAAQ,EAAE,OAAO,EAAE,EAAE,UAAU,EAAE,MAAM,GAAG,MAAM,EAAE,CAgB/F;AAcD,wBAAgB,WAAW,CACzB,MAAM,EAAE,MAAM,EACd,UAAU,EAAE,MAAM,EAClB,UAAU,GAAE,MAAU,EACtB,QAAQ,GAAE,gBAA2B,GACpC,MAAM,CA0FR;AAOD;;;GAGG;AACH,wBAAgB,gBAAgB,CAC9B,MAAM,EAAE,MAAM,EACd,UAAU,EAAE,MAAM,EAClB,UAAU,EAAE,MAAM,EAClB,UAAU,EAAE,MAAM,EAClB,QAAQ,GAAE,gBAA2B,GACpC,MAAM,CAmDR;AAED,wBAAgB,iBAAiB,CAC/B,QAAQ,EAAE,MAAM,EAChB,MAAM,EAAE,MAAM,EACd,UAAU,EAAE,MAAM,EAClB,UAAU,GAAE,MAAU,EACtB,QAAQ,GAAE,gBAA2B,GACpC,MAAM,CAgER"}