@happyvertical/smrt-images 0.30.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 (75) hide show
  1. package/AGENTS.md +48 -0
  2. package/CLAUDE.md +1 -0
  3. package/LICENSE +7 -0
  4. package/README.md +92 -0
  5. package/dist/__smrt-register__.d.ts +2 -0
  6. package/dist/__smrt-register__.d.ts.map +1 -0
  7. package/dist/categorizer.d.ts +26 -0
  8. package/dist/categorizer.d.ts.map +1 -0
  9. package/dist/deriver.d.ts +33 -0
  10. package/dist/deriver.d.ts.map +1 -0
  11. package/dist/editor.d.ts +72 -0
  12. package/dist/editor.d.ts.map +1 -0
  13. package/dist/image.d.ts +53 -0
  14. package/dist/image.d.ts.map +1 -0
  15. package/dist/images.d.ts +80 -0
  16. package/dist/images.d.ts.map +1 -0
  17. package/dist/index.d.ts +12 -0
  18. package/dist/index.d.ts.map +1 -0
  19. package/dist/index.js +839 -0
  20. package/dist/index.js.map +1 -0
  21. package/dist/manifest.json +1179 -0
  22. package/dist/media-bundle-persistence.d.ts +15 -0
  23. package/dist/media-bundle-persistence.d.ts.map +1 -0
  24. package/dist/metadata.d.ts +19 -0
  25. package/dist/metadata.d.ts.map +1 -0
  26. package/dist/playground.d.ts +2 -0
  27. package/dist/playground.d.ts.map +1 -0
  28. package/dist/playground.js +140 -0
  29. package/dist/playground.js.map +1 -0
  30. package/dist/prompts.d.ts +8 -0
  31. package/dist/prompts.d.ts.map +1 -0
  32. package/dist/search.d.ts +42 -0
  33. package/dist/search.d.ts.map +1 -0
  34. package/dist/smrt-knowledge.json +561 -0
  35. package/dist/svelte/components/AssetsGallery.svelte +436 -0
  36. package/dist/svelte/components/AssetsGallery.svelte.d.ts +11 -0
  37. package/dist/svelte/components/AssetsGallery.svelte.d.ts.map +1 -0
  38. package/dist/svelte/components/ImageEditor.svelte +485 -0
  39. package/dist/svelte/components/ImageEditor.svelte.d.ts +12 -0
  40. package/dist/svelte/components/ImageEditor.svelte.d.ts.map +1 -0
  41. package/dist/svelte/components/ImageUploader.svelte +922 -0
  42. package/dist/svelte/components/ImageUploader.svelte.d.ts +15 -0
  43. package/dist/svelte/components/ImageUploader.svelte.d.ts.map +1 -0
  44. package/dist/svelte/i18n.d.ts +42 -0
  45. package/dist/svelte/i18n.d.ts.map +1 -0
  46. package/dist/svelte/i18n.js +46 -0
  47. package/dist/svelte/image-clients.d.ts +45 -0
  48. package/dist/svelte/image-clients.d.ts.map +1 -0
  49. package/dist/svelte/image-clients.js +1 -0
  50. package/dist/svelte/index.d.ts +14 -0
  51. package/dist/svelte/index.d.ts.map +1 -0
  52. package/dist/svelte/index.js +21 -0
  53. package/dist/svelte/playground.d.ts +74 -0
  54. package/dist/svelte/playground.d.ts.map +1 -0
  55. package/dist/svelte/playground.js +105 -0
  56. package/dist/svelte/routes/ImageStudioRoute.svelte +194 -0
  57. package/dist/svelte/routes/ImageStudioRoute.svelte.d.ts +7 -0
  58. package/dist/svelte/routes/ImageStudioRoute.svelte.d.ts.map +1 -0
  59. package/dist/svelte/routes/index.d.ts +2 -0
  60. package/dist/svelte/routes/index.d.ts.map +1 -0
  61. package/dist/svelte/routes/index.js +1 -0
  62. package/dist/svelte/routes/shared.d.ts +25 -0
  63. package/dist/svelte/routes/shared.d.ts.map +1 -0
  64. package/dist/svelte/routes/shared.js +31 -0
  65. package/dist/types.d.ts +51 -0
  66. package/dist/types.d.ts.map +1 -0
  67. package/dist/types.js +2 -0
  68. package/dist/types.js.map +1 -0
  69. package/dist/ui.d.ts +10 -0
  70. package/dist/ui.d.ts.map +1 -0
  71. package/dist/ui.js +42 -0
  72. package/dist/ui.js.map +1 -0
  73. package/dist/upstream.d.ts +65 -0
  74. package/dist/upstream.d.ts.map +1 -0
  75. package/package.json +95 -0
@@ -0,0 +1,561 @@
1
+ {
2
+ "schemaVersion": 1,
3
+ "generatedAt": "2026-06-23T01:11:40.766Z",
4
+ "packageName": "@happyvertical/smrt-images",
5
+ "packageVersion": "0.30.0",
6
+ "sourceManifestPath": "dist/manifest.json",
7
+ "agentDocPath": "AGENTS.md",
8
+ "sourceHashes": {
9
+ "manifest": "71b096d51171295f4ef0a123bd4dd8f5c1758a9be84c9ccc9111d90ae1abaa87",
10
+ "packageJson": "0a220e4b64fd1e05dd36430b005c6bd8e09e854944bf35343ae4bedd57694a06",
11
+ "agents": "b0cf63bd78f00cc1729ea7f1425291f8e23ab5591161cbbf0d08f4b16ace07fd"
12
+ },
13
+ "exports": [
14
+ ".",
15
+ "./manifest",
16
+ "./manifest.json",
17
+ "./playground",
18
+ "./svelte",
19
+ "./ui"
20
+ ],
21
+ "dependencies": {
22
+ "@happyvertical/ai": "catalog:",
23
+ "@happyvertical/images": "catalog:",
24
+ "@happyvertical/smrt-assets": "workspace:*",
25
+ "@happyvertical/smrt-core": "workspace:*",
26
+ "@happyvertical/smrt-prompts": "workspace:*",
27
+ "@happyvertical/smrt-tenancy": "workspace:*",
28
+ "@happyvertical/smrt-types": "workspace:*",
29
+ "@happyvertical/smrt-ui": "workspace:*",
30
+ "@happyvertical/utils": "catalog:",
31
+ "jimp": "catalog:",
32
+ "sharp": "catalog:",
33
+ "@happyvertical/smrt-playground": "workspace:*",
34
+ "@happyvertical/smrt-vitest": "workspace:*",
35
+ "@happyvertical/sql": "catalog:",
36
+ "@sveltejs/kit": "^2.5.7",
37
+ "@sveltejs/package": "^2.5.7",
38
+ "@sveltejs/vite-plugin-svelte": "^6.2.4",
39
+ "@types/node": "25.0.9",
40
+ "svelte": "^5.18.0",
41
+ "svelte-check": "^4.3.5",
42
+ "typescript": "^5.9.3",
43
+ "vite": "^7.3.1",
44
+ "vitest": "^4.0.17"
45
+ },
46
+ "smrtDependencies": [
47
+ "@happyvertical/smrt-assets",
48
+ "@happyvertical/smrt-core",
49
+ "@happyvertical/smrt-playground",
50
+ "@happyvertical/smrt-prompts",
51
+ "@happyvertical/smrt-tenancy",
52
+ "@happyvertical/smrt-types",
53
+ "@happyvertical/smrt-ui",
54
+ "@happyvertical/smrt-vitest"
55
+ ],
56
+ "sdkDependencies": [
57
+ "@happyvertical/ai",
58
+ "@happyvertical/images",
59
+ "@happyvertical/sql",
60
+ "@happyvertical/utils"
61
+ ],
62
+ "tags": [],
63
+ "risks": [],
64
+ "objects": [
65
+ {
66
+ "name": "Image",
67
+ "qualifiedName": "@happyvertical/smrt-images:Image",
68
+ "collection": "assets",
69
+ "tableName": "assets",
70
+ "packageName": "@happyvertical/smrt-images",
71
+ "extends": "Asset",
72
+ "fields": [
73
+ {
74
+ "name": "created_at",
75
+ "type": "datetime",
76
+ "required": false,
77
+ "columnType": "TIMESTAMP"
78
+ },
79
+ {
80
+ "name": "updated_at",
81
+ "type": "datetime",
82
+ "required": false,
83
+ "columnType": "TIMESTAMP"
84
+ },
85
+ {
86
+ "name": "tenantId",
87
+ "type": "text",
88
+ "required": false,
89
+ "columnType": "UUID"
90
+ },
91
+ {
92
+ "name": "name",
93
+ "type": "text",
94
+ "required": false,
95
+ "columnType": "TEXT"
96
+ },
97
+ {
98
+ "name": "sourceUri",
99
+ "type": "text",
100
+ "required": false,
101
+ "columnType": "TEXT"
102
+ },
103
+ {
104
+ "name": "mimeType",
105
+ "type": "text",
106
+ "required": false,
107
+ "columnType": "TEXT"
108
+ },
109
+ {
110
+ "name": "description",
111
+ "type": "text",
112
+ "required": false,
113
+ "columnType": "TEXT"
114
+ },
115
+ {
116
+ "name": "metadata",
117
+ "type": "text",
118
+ "required": false,
119
+ "columnType": "TEXT"
120
+ },
121
+ {
122
+ "name": "version",
123
+ "type": "integer",
124
+ "required": true,
125
+ "columnType": "INTEGER"
126
+ },
127
+ {
128
+ "name": "primaryVersionId",
129
+ "type": "foreignKey",
130
+ "required": false,
131
+ "related": "Asset",
132
+ "columnType": "UUID"
133
+ },
134
+ {
135
+ "name": "typeSlug",
136
+ "type": "text",
137
+ "required": false,
138
+ "columnType": "TEXT"
139
+ },
140
+ {
141
+ "name": "statusSlug",
142
+ "type": "text",
143
+ "required": false,
144
+ "columnType": "TEXT"
145
+ },
146
+ {
147
+ "name": "ownerProfileId",
148
+ "type": "crossPackageRef",
149
+ "required": false,
150
+ "related": "@happyvertical/smrt-profiles:Profile",
151
+ "columnType": "UUID"
152
+ },
153
+ {
154
+ "name": "sourceAssetId",
155
+ "type": "foreignKey",
156
+ "required": false,
157
+ "related": "Asset",
158
+ "columnType": "UUID"
159
+ },
160
+ {
161
+ "name": "folderId",
162
+ "type": "foreignKey",
163
+ "required": false,
164
+ "related": "Folder",
165
+ "columnType": "UUID"
166
+ },
167
+ {
168
+ "name": "sourceType",
169
+ "type": "text",
170
+ "required": false,
171
+ "columnType": "TEXT"
172
+ },
173
+ {
174
+ "name": "externalId",
175
+ "type": "text",
176
+ "required": false,
177
+ "columnType": "TEXT"
178
+ },
179
+ {
180
+ "name": "externalRefs",
181
+ "type": "text",
182
+ "required": false,
183
+ "columnType": "TEXT"
184
+ },
185
+ {
186
+ "name": "createdAt",
187
+ "type": "text",
188
+ "required": false,
189
+ "columnType": "TIMESTAMP"
190
+ },
191
+ {
192
+ "name": "updatedAt",
193
+ "type": "text",
194
+ "required": false,
195
+ "columnType": "TIMESTAMP"
196
+ },
197
+ {
198
+ "name": "width",
199
+ "type": "integer",
200
+ "required": false,
201
+ "columnType": "INTEGER"
202
+ },
203
+ {
204
+ "name": "height",
205
+ "type": "integer",
206
+ "required": false,
207
+ "columnType": "INTEGER"
208
+ },
209
+ {
210
+ "name": "alt",
211
+ "type": "text",
212
+ "required": false,
213
+ "columnType": "TEXT"
214
+ }
215
+ ],
216
+ "relationships": [
217
+ {
218
+ "name": "primaryVersionId",
219
+ "type": "foreignKey",
220
+ "required": false,
221
+ "related": "Asset",
222
+ "columnType": "UUID"
223
+ },
224
+ {
225
+ "name": "ownerProfileId",
226
+ "type": "crossPackageRef",
227
+ "required": false,
228
+ "related": "@happyvertical/smrt-profiles:Profile",
229
+ "columnType": "UUID"
230
+ },
231
+ {
232
+ "name": "sourceAssetId",
233
+ "type": "foreignKey",
234
+ "required": false,
235
+ "related": "Asset",
236
+ "columnType": "UUID"
237
+ },
238
+ {
239
+ "name": "folderId",
240
+ "type": "foreignKey",
241
+ "required": false,
242
+ "related": "Folder",
243
+ "columnType": "UUID"
244
+ }
245
+ ],
246
+ "methods": [
247
+ "associateWith",
248
+ "classifyConstraintError",
249
+ "clearEmbeddings",
250
+ "delete",
251
+ "describe",
252
+ "destroy",
253
+ "do",
254
+ "executeToolCall",
255
+ "forget",
256
+ "forgetScope",
257
+ "generateAltText",
258
+ "generateEmbeddings",
259
+ "getAiUsageSnapshot",
260
+ "getAssociations",
261
+ "getAvailableTools",
262
+ "getBySlug",
263
+ "getDerivatives",
264
+ "getEmbedding",
265
+ "getExternalRef",
266
+ "getExternalRefs",
267
+ "getFields",
268
+ "getId",
269
+ "getMetadata",
270
+ "getRelated",
271
+ "getSavedId",
272
+ "getSlug",
273
+ "getSource",
274
+ "getStatus",
275
+ "getTags",
276
+ "getType",
277
+ "hasStaleEmbeddings",
278
+ "hasTag",
279
+ "initialize",
280
+ "is",
281
+ "isHighResolution",
282
+ "isRelatedLoaded",
283
+ "isSaved",
284
+ "isValidImageFormat",
285
+ "listAiUsage",
286
+ "loadDataFromDb",
287
+ "loadFromId",
288
+ "loadFromSlug",
289
+ "loadRelated",
290
+ "loadRelatedMany",
291
+ "markAsPersisted",
292
+ "mergeMetadata",
293
+ "recall",
294
+ "recallAll",
295
+ "remember",
296
+ "resetAiUsage",
297
+ "save",
298
+ "setExternalRef",
299
+ "setMetadata",
300
+ "summarizeAiUsage",
301
+ "toJSON",
302
+ "toPlainObject",
303
+ "toPublicJSON"
304
+ ],
305
+ "surfaces": [
306
+ {
307
+ "kind": "api",
308
+ "name": "assets.list",
309
+ "operation": "list",
310
+ "objectName": "@happyvertical/smrt-images:Image",
311
+ "path": "/assets",
312
+ "method": "GET"
313
+ },
314
+ {
315
+ "kind": "api",
316
+ "name": "assets.get",
317
+ "operation": "get",
318
+ "objectName": "@happyvertical/smrt-images:Image",
319
+ "path": "/assets/[id]",
320
+ "method": "GET"
321
+ },
322
+ {
323
+ "kind": "api",
324
+ "name": "assets.create",
325
+ "operation": "create",
326
+ "objectName": "@happyvertical/smrt-images:Image",
327
+ "path": "/assets",
328
+ "method": "POST"
329
+ },
330
+ {
331
+ "kind": "api",
332
+ "name": "assets.update",
333
+ "operation": "update",
334
+ "objectName": "@happyvertical/smrt-images:Image",
335
+ "path": "/assets/[id]",
336
+ "method": "PATCH"
337
+ },
338
+ {
339
+ "kind": "api",
340
+ "name": "assets.delete",
341
+ "operation": "delete",
342
+ "objectName": "@happyvertical/smrt-images:Image",
343
+ "path": "/assets/[id]",
344
+ "method": "DELETE"
345
+ },
346
+ {
347
+ "kind": "cli",
348
+ "name": "image_list",
349
+ "operation": "list",
350
+ "objectName": "@happyvertical/smrt-images:Image"
351
+ },
352
+ {
353
+ "kind": "cli",
354
+ "name": "image_get",
355
+ "operation": "get",
356
+ "objectName": "@happyvertical/smrt-images:Image"
357
+ },
358
+ {
359
+ "kind": "cli",
360
+ "name": "image_create",
361
+ "operation": "create",
362
+ "objectName": "@happyvertical/smrt-images:Image"
363
+ },
364
+ {
365
+ "kind": "cli",
366
+ "name": "image_update",
367
+ "operation": "update",
368
+ "objectName": "@happyvertical/smrt-images:Image"
369
+ },
370
+ {
371
+ "kind": "cli",
372
+ "name": "image_delete",
373
+ "operation": "delete",
374
+ "objectName": "@happyvertical/smrt-images:Image"
375
+ },
376
+ {
377
+ "kind": "mcp",
378
+ "name": "image_list",
379
+ "operation": "list",
380
+ "objectName": "@happyvertical/smrt-images:Image"
381
+ },
382
+ {
383
+ "kind": "mcp",
384
+ "name": "image_get",
385
+ "operation": "get",
386
+ "objectName": "@happyvertical/smrt-images:Image"
387
+ },
388
+ {
389
+ "kind": "mcp",
390
+ "name": "image_create",
391
+ "operation": "create",
392
+ "objectName": "@happyvertical/smrt-images:Image"
393
+ },
394
+ {
395
+ "kind": "mcp",
396
+ "name": "image_update",
397
+ "operation": "update",
398
+ "objectName": "@happyvertical/smrt-images:Image"
399
+ },
400
+ {
401
+ "kind": "mcp",
402
+ "name": "image_generateAltText",
403
+ "operation": "generateAltText",
404
+ "objectName": "@happyvertical/smrt-images:Image"
405
+ }
406
+ ],
407
+ "relationshipFeatures": [
408
+ "crossPackageRef",
409
+ "foreignKey",
410
+ "uuidColumns"
411
+ ],
412
+ "tags": [],
413
+ "risks": []
414
+ },
415
+ {
416
+ "name": "ImageCollection",
417
+ "qualifiedName": "@happyvertical/smrt-images:ImageCollection",
418
+ "collection": "assets",
419
+ "tableName": "assets",
420
+ "packageName": "@happyvertical/smrt-images",
421
+ "extends": "SmrtCollection",
422
+ "fields": [],
423
+ "relationships": [],
424
+ "methods": [
425
+ "findByTenant",
426
+ "findGlobal",
427
+ "findWithGlobals",
428
+ "getByAspectRatio",
429
+ "getByMaxDimensions",
430
+ "getByMinDimensions",
431
+ "getHighResolution",
432
+ "getLandscape",
433
+ "getMissingAltText",
434
+ "getPortrait",
435
+ "getSquare"
436
+ ],
437
+ "surfaces": [],
438
+ "relationshipFeatures": [
439
+ "uuidColumns"
440
+ ],
441
+ "tags": [],
442
+ "risks": []
443
+ }
444
+ ],
445
+ "surfaces": [
446
+ {
447
+ "kind": "api",
448
+ "name": "assets.list",
449
+ "operation": "list",
450
+ "objectName": "@happyvertical/smrt-images:Image",
451
+ "path": "/assets",
452
+ "method": "GET"
453
+ },
454
+ {
455
+ "kind": "api",
456
+ "name": "assets.get",
457
+ "operation": "get",
458
+ "objectName": "@happyvertical/smrt-images:Image",
459
+ "path": "/assets/[id]",
460
+ "method": "GET"
461
+ },
462
+ {
463
+ "kind": "api",
464
+ "name": "assets.create",
465
+ "operation": "create",
466
+ "objectName": "@happyvertical/smrt-images:Image",
467
+ "path": "/assets",
468
+ "method": "POST"
469
+ },
470
+ {
471
+ "kind": "api",
472
+ "name": "assets.update",
473
+ "operation": "update",
474
+ "objectName": "@happyvertical/smrt-images:Image",
475
+ "path": "/assets/[id]",
476
+ "method": "PATCH"
477
+ },
478
+ {
479
+ "kind": "api",
480
+ "name": "assets.delete",
481
+ "operation": "delete",
482
+ "objectName": "@happyvertical/smrt-images:Image",
483
+ "path": "/assets/[id]",
484
+ "method": "DELETE"
485
+ },
486
+ {
487
+ "kind": "cli",
488
+ "name": "image_list",
489
+ "operation": "list",
490
+ "objectName": "@happyvertical/smrt-images:Image"
491
+ },
492
+ {
493
+ "kind": "cli",
494
+ "name": "image_get",
495
+ "operation": "get",
496
+ "objectName": "@happyvertical/smrt-images:Image"
497
+ },
498
+ {
499
+ "kind": "cli",
500
+ "name": "image_create",
501
+ "operation": "create",
502
+ "objectName": "@happyvertical/smrt-images:Image"
503
+ },
504
+ {
505
+ "kind": "cli",
506
+ "name": "image_update",
507
+ "operation": "update",
508
+ "objectName": "@happyvertical/smrt-images:Image"
509
+ },
510
+ {
511
+ "kind": "cli",
512
+ "name": "image_delete",
513
+ "operation": "delete",
514
+ "objectName": "@happyvertical/smrt-images:Image"
515
+ },
516
+ {
517
+ "kind": "mcp",
518
+ "name": "image_list",
519
+ "operation": "list",
520
+ "objectName": "@happyvertical/smrt-images:Image"
521
+ },
522
+ {
523
+ "kind": "mcp",
524
+ "name": "image_get",
525
+ "operation": "get",
526
+ "objectName": "@happyvertical/smrt-images:Image"
527
+ },
528
+ {
529
+ "kind": "mcp",
530
+ "name": "image_create",
531
+ "operation": "create",
532
+ "objectName": "@happyvertical/smrt-images:Image"
533
+ },
534
+ {
535
+ "kind": "mcp",
536
+ "name": "image_update",
537
+ "operation": "update",
538
+ "objectName": "@happyvertical/smrt-images:Image"
539
+ },
540
+ {
541
+ "kind": "mcp",
542
+ "name": "image_generateAltText",
543
+ "operation": "generateAltText",
544
+ "objectName": "@happyvertical/smrt-images:Image"
545
+ }
546
+ ],
547
+ "prompts": [
548
+ {
549
+ "filePath": "src/prompts.ts"
550
+ }
551
+ ],
552
+ "relationshipsV2": {
553
+ "foreignKeyFields": 3,
554
+ "crossPackageRefFields": 1,
555
+ "junctionCollections": 0,
556
+ "hierarchicalObjects": 0,
557
+ "polymorphicAssociations": 0,
558
+ "uuidColumns": 7
559
+ },
560
+ "agentDoc": "# @happyvertical/smrt-images\n\nImage management with AI categorization, editing, and metadata extraction. Extends Asset via cross-package STI.\n\n## Models\n\n- **Image**: STI subclass of Asset (from smrt-assets) — stored in same `assets` table with `_meta_type='Image'`. Adds `width`, `height`, `alt` text.\n\n## Key Services\n\n- **ImageCollection**: dimension/orientation filters — `getByMinDimensions()`, `getByAspectRatio()`, `getLandscape()`, `getPortrait()`, `getSquare()`, `getHighResolution()`, `getMissingAltText()`\n- **ImageMetadataExtractor**: dimensions, format, EXIF from buffers (via `@happyvertical/images`)\n- **ImageCategorizer**: AI vision analysis → tags, description, confidence, subjects (via `@happyvertical/ai`)\n- **ImageEditor**: resize/crop/convert/thumbnail + AI editing. Creates new Image records with `parentId` linking to source.\n- **ImageDeriver**: creates derived images and, when requested, records source provenance through generic `AssetAssociation` links\n- **ImageSearch**: text search across name/description/alt with orientation filters\n- **UpstreamManager**: import from external providers with provenance tracking\n\n## AI Operations\n\n`generateAltText()` uses the `smrtImages.image.generateAltText` prompt registered via `@happyvertical/smrt-prompts` (resolves tenant overrides via `resolvePrompt()` then dispatches through `getAiClient().message()`). Computed properties: `isLandscape`, `isPortrait`, `aspectRatio`.\n\n## Prompt Registry\n\n`Image.generateAltText()` is registered with `@happyvertical/smrt-prompts` so tenants can override template/model/params at runtime:\n\n```typescript\nimport { smrtImagesGenerateAltTextPrompt } from '@happyvertical/smrt-images';\n// key: 'smrtImages.image.generateAltText'\n```\n\nOnly non-PII metadata fields are passed to the AI provider: `name`, `description`. Source URIs, internal foreign-key fields (`parentId`, `tenantId`), and the extensible `metadata` blob are intentionally excluded — source URIs may embed signed/private bucket paths and `metadata` may contain EXIF GPS data or tenant-private configuration.\n\n## UI Registry\n\nSvelte components auto-register with `ModuleUIRegistry` on import of `@happyvertical/smrt-images/svelte`. UI slot declarations live in `src/ui.ts` and are exported via `@happyvertical/smrt-images/ui`:\n\n- `assets-gallery` — `AssetsGallery.svelte`\n- `image-editor` — `ImageEditor.svelte`\n- `image-uploader` — `ImageUploader.svelte`\n\n## Gotchas\n\n- **Cross-package STI**: Image extends Asset from different package — fragile if Asset schema changes\n- **AssetAssociation usage is intentional here**: image derivation uses it for provenance, not for base-model-owned asset storage\n- **Editor bypasses collection.create()**: creates Image instances directly (skips collection validation)\n- **Derivative creation**: 3 DB calls — `collection.create()` + `store.storeFile()` + `save()`\n- **Orientation filtering is in-memory**: queries all images, then filters by dimensions\n"
561
+ }