@mesh-sync/worker-backend-client 4.0.19 → 4.0.24

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/types.d.ts CHANGED
@@ -2,9 +2,8 @@
2
2
  * Message type constants
3
3
  */
4
4
  export declare const MessageTypes: {
5
+ readonly ANALYTICS_COLLECTION_REQUEST: "analytics-collection-request";
5
6
  readonly BACKEND_LOGGING_EVENT: "backend-logging-event";
6
- readonly EKG_EDGE_BATCH_CREATE_COMPLETED: "ekg-edge-batch-create-completed";
7
- readonly EKG_EDGE_BATCH_CREATE_REQUEST: "ekg-edge-batch-create-request";
8
7
  readonly ETSY_ANALYTICS_SYNC_COMPLETED: "etsy-analytics-sync-completed";
9
8
  readonly ETSY_ANALYTICS_SYNC_REQUEST: "etsy-analytics-sync-request";
10
9
  readonly ETSY_PUBLISH_LISTING_COMPLETED: "etsy-publish-listing-completed";
@@ -13,13 +12,17 @@ export declare const MessageTypes: {
13
12
  readonly FILE_DOWNLOAD_REQUEST: "file-download-request";
14
13
  readonly FILE_VECTORIZE_COMPLETED: "file-vectorize-completed";
15
14
  readonly FILE_VECTORIZE_REQUEST: "file-vectorize-request";
15
+ readonly IP_CHECK_COMPLETED: "ip-check-completed";
16
+ readonly IP_CHECK_REQUEST: "ip-check-request";
16
17
  readonly MARKETPLACE_ANALYTICS_SYNC_COMPLETED: "marketplace-analytics-sync-completed";
17
18
  readonly MARKETPLACE_ANALYTICS_SYNC_REQUEST: "marketplace-analytics-sync-request";
18
19
  readonly MARKETPLACE_CONNECTION_SYNC_COMPLETED: "marketplace-connection-sync-completed";
19
20
  readonly MARKETPLACE_CONNECTION_SYNC_REQUEST: "marketplace-connection-sync-request";
20
21
  readonly MARKETPLACE_CREDENTIAL_ROTATION_COMPLETED: "marketplace-credential-rotation-completed";
21
22
  readonly MARKETPLACE_CREDENTIAL_ROTATION_REQUEST: "marketplace-credential-rotation-request";
23
+ readonly MARKETPLACE_INTELLIGENCE_COMPLETED: "marketplace-intelligence-completed";
22
24
  readonly MARKETPLACE_INTELLIGENCE_EVENT: "marketplace-intelligence-event";
25
+ readonly MARKETPLACE_INTELLIGENCE_REQUEST: "marketplace-intelligence-request";
23
26
  readonly MARKETPLACE_LISTING_DESCRIPTION_GENERATION_COMPLETED: "marketplace-listing-description-generation-completed";
24
27
  readonly MARKETPLACE_LISTING_DESCRIPTION_GENERATION_REQUEST: "marketplace-listing-description-generation-request";
25
28
  readonly MARKETPLACE_LISTING_SYNC_COMPLETED: "marketplace-listing-sync-completed";
@@ -48,12 +51,20 @@ export declare const MessageTypes: {
48
51
  readonly MODEL_METADATA_GENERATION_REQUEST: "model-metadata-generation-request";
49
52
  readonly MODEL_METAMODEL_DETECTION_FOUND: "model-metamodel-detection-found";
50
53
  readonly MODEL_METAMODEL_DETECTION_REQUEST: "model-metamodel-detection-request";
54
+ readonly MODEL_PRINT_ANALYSIS_COMPLETED: "model-print-analysis-completed";
55
+ readonly MODEL_PRINT_ANALYSIS_REQUEST: "model-print-analysis-request";
51
56
  readonly MODEL_SELLABILITY_ANALYSIS_COMPLETED: "model-sellability-analysis-completed";
52
57
  readonly MODEL_SELLABILITY_ANALYSIS_REQUEST: "model-sellability-analysis-request";
53
58
  readonly MODEL_SEMANTIC_ANALYSIS_COMPLETED: "model-semantic-analysis-completed";
54
59
  readonly MODEL_SEMANTIC_ANALYSIS_REQUEST: "model-semantic-analysis-request";
55
60
  readonly MODEL_TECHNICAL_METADATA_COMPLETED: "model-technical-metadata-completed";
56
61
  readonly MODEL_TECHNICAL_METADATA_REQUEST: "model-technical-metadata-request";
62
+ readonly SLICING_FDM_REQUEST: "slicing-fdm-request";
63
+ readonly SLICING_FDM_RESULT: "slicing-fdm-result";
64
+ readonly SLICING_SIMULATION_REQUEST: "slicing-simulation-request";
65
+ readonly SLICING_SIMULATION_RESULT: "slicing-simulation-result";
66
+ readonly SLICING_SLA_REQUEST: "slicing-sla-request";
67
+ readonly SLICING_SLA_RESULT: "slicing-sla-result";
57
68
  readonly THUMBNAIL_GENERATION_COMPLETED: "thumbnail-generation-completed";
58
69
  readonly THUMBNAIL_GENERATION_REQUEST: "thumbnail-generation-request";
59
70
  readonly USER_ENGAGEMENT_EVENT: "user-engagement-event";
@@ -61,6 +72,21 @@ export declare const MessageTypes: {
61
72
  readonly WORKER_METRICS_ENRICHED_EVENT: "worker-metrics-enriched-event";
62
73
  };
63
74
  export type MessageType = typeof MessageTypes[keyof typeof MessageTypes];
75
+ /**
76
+ * Request to trigger a manual market data collection job.
77
+ Used for ad-hoc scraping of specific queries on marketplaces.
78
+
79
+ */
80
+ export interface AnalyticsCollectionRequestMessage {
81
+ /** The marketplace to scrape (etsy, ebay, etc.) */
82
+ marketplace?: string;
83
+ /** The search query to use */
84
+ query: string;
85
+ /** Collection options (pages, filters, etc.) */
86
+ options?: {
87
+ pages?: number;
88
+ };
89
+ }
64
90
  /**
65
91
  * Centralized logging event for capturing all warn/error/failure logs from meshsync-backend.
66
92
  This event is sent to ELK for centralized monitoring, alerting, and debugging.
@@ -99,7 +125,7 @@ export interface BackendLoggingEventMessage {
99
125
  /** Request URL path (without query params for privacy) */
100
126
  httpUrl?: string;
101
127
  /** HTTP response status code */
102
- httpStatusCode?: string | number | boolean;
128
+ httpStatusCode?: number;
103
129
  /** Error class/type name */
104
130
  errorType?: string;
105
131
  /** Stack trace (sanitized, no sensitive data) */
@@ -107,7 +133,14 @@ export interface BackendLoggingEventMessage {
107
133
  /** Application-specific error code for categorization */
108
134
  errorCode?: string;
109
135
  /** Additional structured context (sanitized, no PII) */
110
- metadata?: Record<string, string | number | boolean>;
136
+ metadata?: {
137
+ modelId?: string;
138
+ storageId?: string;
139
+ workerId?: string;
140
+ jobId?: string;
141
+ marketplace?: string;
142
+ operation?: string;
143
+ };
111
144
  /** Deployment environment */
112
145
  environment?: string;
113
146
  /** Backend service version */
@@ -117,38 +150,6 @@ export interface BackendLoggingEventMessage {
117
150
  /** Operation duration in milliseconds (if applicable) */
118
151
  durationMs?: number;
119
152
  }
120
- /**
121
- * Completion event for EKG edge batch creation with propagation results.
122
- */
123
- export interface EkgEdgeBatchCreateCompletedMessage {
124
- /** Original request ID from ekg-edge-batch-create-request */
125
- requestId: string;
126
- /** Whether the batch operation succeeded */
127
- success: boolean;
128
- /** Batch operation statistics */
129
- statistics: Record<string, string | number | boolean>;
130
- /** List of high-conflict edges requiring review */
131
- conflicts?: Array<Record<string, string | number | boolean>>;
132
- /** Errors encountered during processing */
133
- errors?: Array<Record<string, string | number | boolean>>;
134
- /** Overall graph state after this batch */
135
- graphMetrics?: Record<string, string | number | boolean>;
136
- }
137
- /**
138
- * Create multiple EKG edges with Dempster-Shafer mass functions. Triggered by metamodel detection completion.
139
- */
140
- export interface EkgEdgeBatchCreateRequestMessage {
141
- /** Unique request ID for tracking (e.g., metamodel detection job ID) */
142
- requestId: string;
143
- /** Source of the edges: metamodel-heuristic, manual, taxonomy-import, etc. */
144
- source: string;
145
- /** Batch of edges to create/update in the EKG */
146
- edges: Array<Record<string, string | number | boolean>>;
147
- /** Options for evidential edge propagation after edge creation */
148
- propagationOptions?: Record<string, string | number | boolean>;
149
- /** Optional webhook URL for async completion notification */
150
- webhookUrl?: string;
151
- }
152
153
  /**
153
154
  * Contains synced analytics data for Etsy listings. Backend stores this in etsy_analytics_snapshots table and indexes to ELK.
154
155
 
@@ -159,15 +160,42 @@ export interface EtsyAnalyticsSyncCompletedMessage {
159
160
  /** */
160
161
  status?: string;
161
162
  /** Number of listings successfully synced */
162
- syncedCount?: string | number | boolean;
163
+ syncedCount?: number;
163
164
  /** Number of listings that failed */
164
- errorCount?: string | number | boolean;
165
+ errorCount?: number;
165
166
  /** Analytics for each synced listing */
166
- results?: Array<Record<string, string | number | boolean>>;
167
+ results?: Array<{
168
+ listingId?: string;
169
+ etsyListingId?: string;
170
+ materialName?: string;
171
+ analytics?: {
172
+ views?: number;
173
+ favorites?: number;
174
+ sales?: number;
175
+ revenue?: number;
176
+ conversionRate?: number;
177
+ averageOrderValue?: number;
178
+ topSearchTerms?: string[];
179
+ trafficSources?: Record<string, number>;
180
+ timeSeries?: Array<{
181
+ date?: string;
182
+ views?: number;
183
+ sales?: number;
184
+ }>;
185
+ };
186
+ status?: string;
187
+ }>;
167
188
  /** New credentials if token was refreshed during operation */
168
- credentialUpdate?: Record<string, string | number | boolean>;
189
+ credentialUpdate?: {
190
+ newAccessToken?: string;
191
+ newRefreshToken?: string;
192
+ expiresIn?: number;
193
+ };
169
194
  /** Errors for failed listings */
170
- errors?: Array<Record<string, string | number | boolean>>;
195
+ errors?: Array<{
196
+ listingId?: string;
197
+ error?: string;
198
+ }>;
171
199
  /** */
172
200
  syncedAt?: string;
173
201
  /** When next automatic sync should occur */
@@ -180,19 +208,34 @@ Can sync: - Specific listings (provide listingIds) - All user listings (provide
180
208
  */
181
209
  export interface EtsyAnalyticsSyncRequestMessage {
182
210
  /** Internal listing IDs to sync. Empty = sync all for user. */
183
- listingIds?: Array<Record<string, string | number | boolean>>;
211
+ listingIds?: string[];
184
212
  /** User whose listings to sync (if listingIds empty) */
185
213
  userId?: string;
186
214
  /** Etsy shop ID for shop-level analytics */
187
215
  shopId?: string;
188
216
  /** Etsy OAuth credentials */
189
- credentials?: Record<string, string | number | boolean>;
217
+ credentials?: {
218
+ apiKey?: string;
219
+ shopId?: string;
220
+ accessToken?: string;
221
+ refreshToken?: string;
222
+ };
190
223
  /** Date range for historical analytics */
191
- timeRange?: Record<string, string | number | boolean>;
224
+ timeRange?: {
225
+ startDate: string;
226
+ endDate: string;
227
+ };
192
228
  /** */
193
- syncOptions?: Record<string, string | number | boolean>;
229
+ syncOptions?: {
230
+ includeDetailedMetrics?: boolean;
231
+ includeTrafficSources?: boolean;
232
+ includeSearchTerms?: boolean;
233
+ };
194
234
  /** Encrypted Etsy OAuth credentials */
195
- etsyCredentials?: Record<string, string | number | boolean>;
235
+ etsyCredentials?: {
236
+ accessToken: string;
237
+ shopId: string;
238
+ };
196
239
  /** */
197
240
  webhookUrl?: string;
198
241
  }
@@ -216,15 +259,24 @@ export interface EtsyPublishListingCompletedMessage {
216
259
  /** URL to view listing on Etsy (only if status=SUCCESS) */
217
260
  etsyListingUrl?: string;
218
261
  /** New credentials if token was refreshed during operation */
219
- credentialUpdate?: Record<string, string | number | boolean>;
262
+ credentialUpdate?: {
263
+ newAccessToken?: string;
264
+ newRefreshToken?: string;
265
+ expiresIn?: number;
266
+ };
220
267
  /** Etsy digital file ID (only if status=SUCCESS) */
221
268
  etsyFileId?: string;
222
269
  /** Error details (only if status=FAILED) */
223
- error?: Record<string, string | number | boolean>;
270
+ error?: {
271
+ code?: string;
272
+ message?: string;
273
+ details?: Record<string, unknown>;
274
+ retryable?: boolean;
275
+ };
224
276
  /** When the listing was created (only if status=SUCCESS) */
225
277
  publishedAt?: string;
226
278
  /** Processing time in milliseconds */
227
- processingDuration?: string | number | boolean;
279
+ processingDuration?: number;
228
280
  }
229
281
  /**
230
282
  * Publishes a single metamodel listing to Etsy for a specific material variant. Creates Etsy listing, uploads digital file, and returns external listing ID.
@@ -240,17 +292,48 @@ export interface EtsyPublishListingRequestMessage {
240
292
  /** User ID who owns the metamodel */
241
293
  ownerId?: string;
242
294
  /** Etsy OAuth credentials */
243
- credentials?: Record<string, string | number | boolean>;
295
+ credentials?: {
296
+ apiKey?: string;
297
+ shopId?: string;
298
+ accessToken?: string;
299
+ refreshToken?: string;
300
+ };
244
301
  /** Material-specific listing configuration */
245
- materialVariant?: Record<string, string | number | boolean>;
302
+ materialVariant?: {
303
+ materialName: string;
304
+ price: number;
305
+ sku?: string;
306
+ currency?: string;
307
+ };
246
308
  /** Common listing information */
247
- baseListingData?: Record<string, string | number | boolean>;
309
+ baseListingData?: {
310
+ title: string;
311
+ description: string;
312
+ tags: string[];
313
+ taxonomyId: number;
314
+ whoMade?: string;
315
+ whenMade?: string;
316
+ isDigital?: boolean;
317
+ quantity?: number;
318
+ };
248
319
  /** */
249
- publishOptions?: Record<string, string | number | boolean>;
320
+ publishOptions?: {
321
+ autoActivate?: boolean;
322
+ shippingProfileId?: number;
323
+ };
250
324
  /** Encrypted Etsy OAuth credentials */
251
- etsyCredentials?: Record<string, string | number | boolean>;
325
+ etsyCredentials?: {
326
+ accessToken: string;
327
+ shopId: string;
328
+ expiresAt?: string;
329
+ };
252
330
  /** Digital file to upload */
253
- fileMetadata?: Record<string, string | number | boolean>;
331
+ fileMetadata?: {
332
+ storageItemId: string;
333
+ fileName: string;
334
+ fileSize?: number;
335
+ mimeType?: string;
336
+ };
254
337
  /** Callback URL for completion notification */
255
338
  webhookUrl?: string;
256
339
  }
@@ -265,7 +348,11 @@ export interface FileDownloadCompletedMessage {
265
348
  /** The final status of the download operation. */
266
349
  status?: string;
267
350
  /** Details of the file's location in Minio S3 (present on success). */
268
- s3Location?: Record<string, string | number | boolean>;
351
+ s3Location?: {
352
+ bucket: string;
353
+ key: string;
354
+ versionId?: string;
355
+ };
269
356
  /** Contains error details if the status is FAILED. */
270
357
  errorMessage?: string;
271
358
  /** The timestamp when the download was completed or failed. */
@@ -288,13 +375,31 @@ export interface FileDownloadRequestMessage {
288
375
  /** The identifier of the user who owns the model. Optional - if not provided, will be retrieved from StorageConnection. */
289
376
  ownerId?: string;
290
377
  /** The storage location of the model. */
291
- storageLocation?: Record<string, string | number | boolean>;
378
+ storageLocation?: {
379
+ storageConnectionId: string;
380
+ path: string;
381
+ };
292
382
  /** Optional metadata from discovery. For Thingiverse, contains downloadUrl for direct file access. */
293
- metadata?: Record<string, string | number | boolean>;
383
+ metadata?: {
384
+ downloadUrl?: string;
385
+ };
294
386
  /** Decrypted credentials required for this specific download operation. Injected by the backend. */
295
- credentials?: Record<string, string | number | boolean>;
387
+ credentials?: {
388
+ providerType?: string;
389
+ accessKeyId?: string;
390
+ secretAccessKey?: string;
391
+ region?: string;
392
+ accessToken?: string;
393
+ refreshToken?: string;
394
+ username?: string;
395
+ password?: string;
396
+ privateKey?: string;
397
+ };
296
398
  /** Destination in MinIO where file will be uploaded after download. */
297
- minioDestination?: Record<string, string | number | boolean>;
399
+ minioDestination?: {
400
+ bucket?: string;
401
+ path: string;
402
+ };
298
403
  /** Automatically enqueue thumbnail generation, technical metadata analysis, and metadata generation jobs after download completes. */
299
404
  autoEnqueueChildren?: boolean;
300
405
  /** Preview type for thumbnail generation (passed to child job). */
@@ -311,11 +416,11 @@ export interface FileVectorizeCompletedMessage {
311
416
  /** */
312
417
  fileId?: string;
313
418
  /** The computed embedding vector */
314
- vector?: Array<Record<string, string | number | boolean>>;
419
+ vector?: number[];
315
420
  /** */
316
421
  modelName?: string;
317
422
  /** Length of the vector (e.g., 512) */
318
- dimension?: string | number | boolean;
423
+ dimension?: number;
319
424
  }
320
425
  /**
321
426
  * Request to generate a vector embedding for an image file using CLIP.
@@ -324,10 +429,109 @@ export interface FileVectorizeRequestMessage {
324
429
  /** The ID of the file in the database */
325
430
  fileId?: string;
326
431
  /** Location of the image file */
327
- storageItem?: string | number | boolean;
432
+ storageItem?: unknown;
328
433
  /** Optional: Specific model version to use */
329
434
  modelName?: string;
330
435
  }
436
+ /**
437
+ * Contains IP verification results including trademark risk, copyright risk, detected brands/franchises, and analysis confidence scores
438
+ */
439
+ export interface IpCheckCompletedMessage {
440
+ /** Model UUID that was analyzed */
441
+ modelId?: string;
442
+ /** Owner user ID */
443
+ ownerId?: string;
444
+ /** Type of entity checked: 'model' or 'metamodel' */
445
+ entityType?: string;
446
+ /** Overall IP check outcome: 'clear', 'flagged', or 'error' */
447
+ status?: string;
448
+ /** Detected trademark infringement risk level: 'none', 'low', 'medium', 'high' */
449
+ trademarkRisk?: string;
450
+ /** Detected copyright infringement risk level: 'none', 'low', 'medium', 'high' */
451
+ copyrightRisk?: string;
452
+ /** Brand names detected in model name or content */
453
+ matchedBrands?: string[];
454
+ /** Franchise/character names detected */
455
+ matchedFranchises?: string[];
456
+ /** Number of visually similar models found */
457
+ similarModelsCount?: number;
458
+ /** Overall confidence score for the analysis (0.0-1.0) */
459
+ confidence?: number;
460
+ /** Risk score as 0-100 integer (FR-024: >70 HIGH, 40-70 MEDIUM, <40 LOW) */
461
+ riskScorePercent?: number;
462
+ /** Overall risk level: 'none', 'low', 'medium', 'high' */
463
+ riskLevel?: string;
464
+ /** Recommended action: 'block' (HIGH risk), 'warn' (MEDIUM risk), 'allow' (LOW/NONE risk) */
465
+ recommendation?: string;
466
+ /** Suggested modifications to reduce IP risk */
467
+ suggestedChanges?: {
468
+ title?: string;
469
+ tagsToRemove?: string[];
470
+ descriptionChanges?: string;
471
+ };
472
+ /** Detailed results from each heuristic check */
473
+ heuristicResults?: {
474
+ perceptualHash?: {
475
+ executed?: boolean;
476
+ matchesFound?: number;
477
+ highestSimilarity?: number;
478
+ flagged?: boolean;
479
+ };
480
+ trademark?: {
481
+ executed?: boolean;
482
+ brandsDetected?: string[];
483
+ flagged?: boolean;
484
+ };
485
+ franchise?: {
486
+ executed?: boolean;
487
+ franchisesDetected?: string[];
488
+ flagged?: boolean;
489
+ };
490
+ reverseSearch?: {
491
+ executed?: boolean;
492
+ provider?: string;
493
+ matchesFound?: number;
494
+ commercialMatchesFound?: number;
495
+ flagged?: boolean;
496
+ };
497
+ };
498
+ /** Error details if status is 'error' */
499
+ error?: {
500
+ code?: string;
501
+ message?: string;
502
+ };
503
+ /** Total processing time in milliseconds */
504
+ processingDurationMs?: number;
505
+ }
506
+ /**
507
+ * Triggers intellectual property verification analysis for a model thumbnail, detecting potential trademark and copyright issues using perceptual hashing, text analysis, and optional reverse image search.
508
+ */
509
+ export interface IpCheckRequestMessage {
510
+ /** Unique identifier for the model to analyze */
511
+ modelId?: string;
512
+ /** User ID who owns the model */
513
+ ownerId?: string;
514
+ /** Type of entity being checked: 'model' or 'metamodel' */
515
+ entityType?: string;
516
+ /** Name of the model for trademark/franchise text detection */
517
+ modelName?: string;
518
+ /** Model tags for IP reference detection */
519
+ tags?: string[];
520
+ /** Model description for text-based IP analysis */
521
+ description?: string;
522
+ /** URL to fetch the thumbnail image for visual analysis */
523
+ thumbnailUrl?: string;
524
+ /** Path to thumbnail in MinIO if stored internally */
525
+ minioPath?: string;
526
+ /** Optional additional images for more comprehensive analysis (e.g., 360° views) */
527
+ additionalImageUrls?: string[];
528
+ /** Optional analysis configuration */
529
+ analysisOptions?: {
530
+ enableExternalSearch?: boolean;
531
+ strictMode?: boolean;
532
+ skipHeuristics?: string[];
533
+ };
534
+ }
331
535
  /**
332
536
  * Contains synced analytics data for marketplace listings. Backend stores this in marketplace_analytics_snapshots table and indexes to ELK. Works with any marketplace provider.
333
537
  */
@@ -339,13 +543,36 @@ export interface MarketplaceAnalyticsSyncCompletedMessage {
339
543
  /** Sync result (SUCCESS, PARTIAL_SUCCESS, or FAILED) */
340
544
  status?: string;
341
545
  /** Number of listings successfully synced */
342
- syncedCount?: string | number | boolean;
546
+ syncedCount?: number;
343
547
  /** Number of listings that failed */
344
- errorCount?: string | number | boolean;
548
+ errorCount?: number;
345
549
  /** Analytics for each synced listing */
346
- results?: Array<Record<string, string | number | boolean>>;
550
+ results?: Array<{
551
+ listingId?: string;
552
+ externalListingId?: string;
553
+ materialName?: string;
554
+ analytics?: {
555
+ views?: number;
556
+ favorites?: number;
557
+ sales?: number;
558
+ revenue?: number;
559
+ conversionRate?: number;
560
+ averageOrderValue?: number;
561
+ topSearchTerms?: string[];
562
+ trafficSources?: Record<string, unknown>;
563
+ timeSeries?: Array<{
564
+ date?: string;
565
+ views?: number;
566
+ sales?: number;
567
+ }>;
568
+ };
569
+ status?: string;
570
+ }>;
347
571
  /** Errors for failed listings */
348
- errors?: Array<Record<string, string | number | boolean>>;
572
+ errors?: Array<{
573
+ listingId?: string;
574
+ error?: string;
575
+ }>;
349
576
  /** When sync completed (ISO 8601) */
350
577
  syncedAt?: string;
351
578
  /** When next automatic sync should occur (ISO 8601) */
@@ -360,17 +587,27 @@ export interface MarketplaceAnalyticsSyncRequestMessage {
360
587
  /** UUID of the marketplace connection configuration */
361
588
  marketplaceConnectionId?: string;
362
589
  /** Internal listing UUIDs to sync. Empty array = sync all for user. */
363
- listingIds?: Array<Record<string, string | number | boolean>>;
590
+ listingIds?: string[];
364
591
  /** UUID of user whose listings to sync (if listingIds empty) */
365
592
  userId?: string;
366
593
  /** External marketplace shop ID for shop-level analytics */
367
594
  externalShopId?: string;
368
595
  /** Date range for historical analytics */
369
- timeRange?: Record<string, string | number | boolean>;
596
+ timeRange?: {
597
+ startDate: string;
598
+ endDate: string;
599
+ };
370
600
  /** Optional sync configuration */
371
- syncOptions?: Record<string, string | number | boolean>;
601
+ syncOptions?: {
602
+ includeDetailedMetrics?: boolean;
603
+ includeTrafficSources?: boolean;
604
+ includeSearchTerms?: boolean;
605
+ };
372
606
  /** Encrypted marketplace credentials (retrieved from marketplaceConnectionId) */
373
- marketplaceCredentials?: Record<string, string | number | boolean>;
607
+ marketplaceCredentials?: {
608
+ accessToken: string;
609
+ externalShopId?: string;
610
+ };
374
611
  /** Callback URL for completion notification */
375
612
  webhookUrl?: string;
376
613
  }
@@ -392,15 +629,42 @@ export interface MarketplaceConnectionSyncCompletedMessage {
392
629
  /** Type of sync that was performed */
393
630
  syncType?: string;
394
631
  /** Updated connection information */
395
- connectionData?: Record<string, string | number | boolean>;
632
+ connectionData?: {
633
+ status?: string;
634
+ shopName?: string;
635
+ shopUrl?: string;
636
+ shopId?: string;
637
+ permissions?: string[];
638
+ rateLimit?: {
639
+ remaining?: number;
640
+ resetAt?: string;
641
+ };
642
+ };
396
643
  /** Available marketplace categories */
397
- categories?: Array<Record<string, string | number | boolean>>;
644
+ categories?: Array<{
645
+ id?: string;
646
+ name?: string;
647
+ path?: string;
648
+ level?: number;
649
+ }>;
398
650
  /** Sync operation statistics */
399
- statistics?: Record<string, string | number | boolean>;
651
+ statistics?: {
652
+ duration?: number;
653
+ itemsSynced?: number;
654
+ errors?: Array<{
655
+ type?: string;
656
+ message?: string;
657
+ timestamp?: string;
658
+ }>;
659
+ };
400
660
  /** When sync completed */
401
661
  completedAt?: string;
402
662
  /** Error details if sync failed */
403
- error?: Record<string, string | number | boolean>;
663
+ error?: {
664
+ code?: string;
665
+ message?: string;
666
+ details?: Record<string, unknown>;
667
+ };
404
668
  }
405
669
  /**
406
670
  * Requests synchronization of marketplace connection data including: - Profile information and shop details - Account status and permissions - Available categories and shipping profiles - Rate limits and API quotas
@@ -423,7 +687,10 @@ export interface MarketplaceConnectionSyncRequestMessage {
423
687
  /** Webhook URL to call when sync completes */
424
688
  webhookUrl?: string;
425
689
  /** Additional context data */
426
- metadata?: Record<string, string | number | boolean>;
690
+ metadata?: {
691
+ source?: string;
692
+ retryCount?: number;
693
+ };
427
694
  }
428
695
  /**
429
696
  * Notification that marketplace credential rotation has completed. Contains the rotation results, new credential metadata, and any issues encountered.
@@ -445,19 +712,62 @@ export interface MarketplaceCredentialRotationCompletedMessage {
445
712
  /** Original reason for rotation */
446
713
  reason?: string;
447
714
  /** Metadata about new credentials */
448
- newCredentials?: Record<string, string | number | boolean>;
715
+ newCredentials?: {
716
+ tokenType?: string;
717
+ createdAt?: string;
718
+ expiresAt?: string;
719
+ scope?: string[];
720
+ testResult?: {
721
+ tested?: boolean;
722
+ success?: boolean;
723
+ testedAt?: string;
724
+ testError?: string;
725
+ };
726
+ };
449
727
  /** Status of previous credentials */
450
- oldCredentials?: Record<string, string | number | boolean>;
728
+ oldCredentials?: {
729
+ revoked?: boolean;
730
+ revokedAt?: string;
731
+ preservedUntil?: string;
732
+ };
451
733
  /** Details of the rotation operation */
452
- operationDetails?: Record<string, string | number | boolean>;
734
+ operationDetails?: {
735
+ duration?: number;
736
+ attempts?: number;
737
+ method?: string;
738
+ completedAt?: string;
739
+ };
453
740
  /** Connection status after credential rotation */
454
- connectionStatus?: Record<string, string | number | boolean>;
741
+ connectionStatus?: {
742
+ status?: string;
743
+ lastTest?: {
744
+ success?: boolean;
745
+ timestamp?: string;
746
+ error?: string;
747
+ };
748
+ permissions?: string[];
749
+ };
455
750
  /** Information about next scheduled rotation */
456
- nextRotation?: Record<string, string | number | boolean>;
751
+ nextRotation?: {
752
+ scheduledAt?: string;
753
+ reason?: string;
754
+ reminderAt?: string;
755
+ };
457
756
  /** Error details if rotation failed */
458
- error?: Record<string, string | number | boolean>;
757
+ error?: {
758
+ code?: string;
759
+ message?: string;
760
+ details?: Record<string, unknown>;
761
+ retryable?: boolean;
762
+ nextRetryAt?: string;
763
+ };
459
764
  /** Notifications sent as part of rotation */
460
- notifications?: Array<Record<string, string | number | boolean>>;
765
+ notifications?: Array<{
766
+ type?: string;
767
+ recipient?: string;
768
+ status?: string;
769
+ sentAt?: string;
770
+ }>;
461
771
  }
462
772
  /**
463
773
  * Requests rotation/refresh of marketplace connection credentials. This is used for: - OAuth token refresh when tokens are near expiry - API key rotation for enhanced security - Re-authentication after connection errors - Scheduled credential updates
@@ -477,9 +787,20 @@ export interface MarketplaceCredentialRotationRequestMessage {
477
787
  /** How urgently the rotation is needed */
478
788
  urgency?: string;
479
789
  /** Current credential metadata (no actual secrets) */
480
- currentCredentials?: Record<string, string | number | boolean>;
790
+ currentCredentials?: {
791
+ tokenType?: string;
792
+ expiresAt?: string;
793
+ lastUsedAt?: string;
794
+ errorsSinceLastRotation?: number;
795
+ };
481
796
  /** Rotation configuration options */
482
- options?: Record<string, string | number | boolean>;
797
+ options?: {
798
+ preserveOldToken?: boolean;
799
+ testNewCredentials?: boolean;
800
+ notifyUser?: boolean;
801
+ retryOnFailure?: boolean;
802
+ maxRetries?: number;
803
+ };
483
804
  /** Unique request identifier */
484
805
  requestId?: string;
485
806
  /** Webhook URL for completion notification */
@@ -487,7 +808,70 @@ export interface MarketplaceCredentialRotationRequestMessage {
487
808
  /** When this rotation was scheduled (if scheduled) */
488
809
  scheduledAt?: string;
489
810
  /** Additional request context */
490
- metadata?: Record<string, string | number | boolean>;
811
+ metadata?: {
812
+ source?: string;
813
+ originalError?: {
814
+ code?: string;
815
+ message?: string;
816
+ timestamp?: string;
817
+ };
818
+ };
819
+ }
820
+ /**
821
+ * Response from marketplace intelligence scraping.
822
+ Contains aggregated similarity data from marketplace searches.
823
+
824
+ Consumed by worker-backend to update pipeline context before
825
+ sellability analysis runs.
826
+
827
+ */
828
+ export interface MarketplaceIntelligenceCompletedMessage {
829
+ /** UUID of the model that was researched */
830
+ modelId: string;
831
+ /** UUID of the model owner */
832
+ ownerId: string;
833
+ /** Result status */
834
+ status: string;
835
+ /** Aggregated market intelligence across all scraped marketplaces */
836
+ marketData?: {
837
+ totalListingsFound?: number;
838
+ averagePrice?: number;
839
+ priceRange?: {
840
+ min?: number;
841
+ max?: number;
842
+ median?: number;
843
+ };
844
+ averageRating?: number;
845
+ averageSalesCount?: number;
846
+ topTags?: string[];
847
+ competitorCount?: number;
848
+ hasDigitalDownloads?: boolean;
849
+ bestSellerPercentage?: number;
850
+ };
851
+ /** Results per marketplace */
852
+ marketplaceBreakdown?: Array<{
853
+ marketplace?: string;
854
+ listingsFound?: number;
855
+ averagePrice?: number;
856
+ topResult?: {
857
+ title?: string;
858
+ price?: number;
859
+ url?: string;
860
+ favorites?: number;
861
+ };
862
+ }>;
863
+ /** How saturated the market is for this model type (0=unique, 100=very common) */
864
+ similarityScore?: number;
865
+ /** Error information if status is FAILED */
866
+ error?: {
867
+ code?: string;
868
+ message?: string;
869
+ failedMarketplaces?: string[];
870
+ };
871
+ /** When the analysis completed */
872
+ analyzedAt?: string;
873
+ /** Version of the intelligence collector */
874
+ analysisVersion?: string;
491
875
  }
492
876
  /**
493
877
  * Public marketplace intelligence data scraped from external marketplaces.
@@ -513,13 +897,48 @@ export interface MarketplaceIntelligenceEventMessage {
513
897
  /** Marketplace-native listing ID */
514
898
  externalId: string;
515
899
  /** Core listing information */
516
- listing: Record<string, string | number | boolean>;
900
+ listing: {
901
+ title: string;
902
+ price: number;
903
+ currency: string;
904
+ url: string;
905
+ thumbnailUrl: string;
906
+ };
517
907
  /** Public engagement and sales metrics */
518
- metrics?: Record<string, string | number | boolean>;
908
+ metrics?: {
909
+ favorites?: number;
910
+ reviewsCount?: number;
911
+ averageRating?: number;
912
+ views?: number;
913
+ salesCount?: number;
914
+ salesVelocity?: number;
915
+ sentimentScore?: number;
916
+ };
519
917
  /** Additional listing context and categorization */
520
- metadata?: Record<string, string | number | boolean>;
918
+ metadata?: {
919
+ tags?: string[];
920
+ materials?: string[];
921
+ shopName?: string;
922
+ shopLocation?: string;
923
+ isDigital?: boolean;
924
+ isBestseller?: boolean;
925
+ isAd?: boolean;
926
+ isPopularNow?: boolean;
927
+ isStarSeller?: boolean;
928
+ hasFreeShipping?: boolean;
929
+ originalPrice?: number;
930
+ discountPercent?: number;
931
+ shopRating?: number;
932
+ shopReviewsCount?: number;
933
+ reviews?: string[];
934
+ };
521
935
  /** Search context that found this listing */
522
- queryContext?: Record<string, string | number | boolean>;
936
+ queryContext?: {
937
+ searchQuery?: string;
938
+ pageNumber?: number;
939
+ position?: number;
940
+ filters?: Record<string, unknown>;
941
+ };
523
942
  /** ISO 8601 timestamp when data was scraped */
524
943
  collectedAt: string;
525
944
  /** Version of collector that scraped this data */
@@ -527,6 +946,48 @@ export interface MarketplaceIntelligenceEventMessage {
527
946
  /** Method used for scraping */
528
947
  scrapingMethod?: string;
529
948
  }
949
+ /**
950
+ * Triggers automated marketplace scraping to find similar/competing listings
951
+ for a given model. This is a pipeline stage that runs after metadata generation
952
+ to inform sellability analysis with real market data.
953
+
954
+ The worker-analytic-collector (or marketplace-connectors worker) will:
955
+ 1. Use model metadata (title, tags, category) to build search queries
956
+ 2. Scrape connected marketplaces (Etsy, eBay, etc.) for similar listings
957
+ 3. Emit marketplace-intelligence-event results for Elasticsearch indexing
958
+ 4. Return aggregated similarity data to the pipeline context
959
+
960
+ Pipeline integration:
961
+ - Triggered after: metadata-generation (needs model title/tags/category)
962
+ - Results feed into: sellability-analysis (market positioning data)
963
+
964
+ */
965
+ export interface MarketplaceIntelligenceRequestMessage {
966
+ /** UUID of the model to research */
967
+ modelId: string;
968
+ /** UUID of the model owner */
969
+ ownerId: string;
970
+ /** Model metadata used to build marketplace search queries */
971
+ searchContext?: {
972
+ title?: string;
973
+ tags?: string[];
974
+ category?: string;
975
+ description?: string;
976
+ materials?: string[];
977
+ };
978
+ /** Configuration for the marketplace scraping */
979
+ scrapingOptions?: {
980
+ targetMarketplaces?: string[];
981
+ maxResultsPerMarketplace?: number;
982
+ maxPages?: number;
983
+ includeMetrics?: boolean;
984
+ includeReviews?: boolean;
985
+ };
986
+ /** Pipeline execution ID for correlation */
987
+ pipelineId?: string;
988
+ /** Pipeline execution UUID for correlation */
989
+ executionId?: string;
990
+ }
530
991
  /**
531
992
  * Notifies backend that marketplace description generation completed. Contains generated description with metadata tracking (AI model, confidence, generation timestamp) and suggested price.
532
993
  */
@@ -540,9 +1001,21 @@ export interface MarketplaceListingDescriptionGenerationCompletedMessage {
540
1001
  /** SEO-optimized marketplace description (3-5 sentences) */
541
1002
  description: string;
542
1003
  /** Content generation metadata for tracking */
543
- metadata: Record<string, string | number | boolean>;
1004
+ metadata: {
1005
+ source: string;
1006
+ generatedAt: string;
1007
+ aiModel: string;
1008
+ confidence: number;
1009
+ };
544
1010
  /** Volume-based price calculation for 3D printed item */
545
- suggestedPrice?: Record<string, string | number | boolean>;
1011
+ suggestedPrice?: {
1012
+ suggestedPrice?: number;
1013
+ currency?: string;
1014
+ materialCost?: number;
1015
+ laborCost?: number;
1016
+ marketplaceMarkup?: number;
1017
+ breakdown?: Record<string, unknown>;
1018
+ };
546
1019
  /** Error message if generation failed */
547
1020
  error?: string;
548
1021
  }
@@ -563,11 +1036,17 @@ export interface MarketplaceListingDescriptionGenerationRequestMessage {
563
1036
  /** Callback URL for completion notification */
564
1037
  webhookUrl?: string;
565
1038
  /** Technical analysis data for context */
566
- technicalMetadata?: Record<string, string | number | boolean>;
1039
+ technicalMetadata?: {
1040
+ vertices?: number;
1041
+ faces?: number;
1042
+ volumeMm3?: number;
1043
+ dimensionsMm?: number[];
1044
+ isWatertight?: boolean;
1045
+ };
567
1046
  /** URLs to 360-degree thumbnail views */
568
- thumbnailUrls?: Array<Record<string, string | number | boolean>>;
1047
+ thumbnailUrls?: string[];
569
1048
  /** Currently assigned tags for context */
570
- existingTags?: Array<Record<string, string | number | boolean>>;
1049
+ existingTags?: string[];
571
1050
  /** Current classification for context */
572
1051
  existingCategory?: string;
573
1052
  /** Desired tone/voice for the listing (e.g., 'professional', 'playful') */
@@ -575,7 +1054,7 @@ export interface MarketplaceListingDescriptionGenerationRequestMessage {
575
1054
  /** Target geographic market (e.g., 'US', 'EU') */
576
1055
  targetMarket?: string;
577
1056
  /** Specific keywords to include */
578
- keywords?: Array<Record<string, string | number | boolean>>;
1057
+ keywords?: string[];
579
1058
  }
580
1059
  /**
581
1060
  * Notification that marketplace listing sync operation has completed. Contains detailed results of the sync including created/updated listings, errors encountered, and performance statistics.
@@ -595,15 +1074,56 @@ export interface MarketplaceListingSyncCompletedMessage {
595
1074
  /** Direction of sync that was performed */
596
1075
  syncDirection?: string;
597
1076
  /** Detailed sync operation statistics */
598
- statistics?: Record<string, string | number | boolean>;
1077
+ statistics?: {
1078
+ duration?: number;
1079
+ listingsProcessed?: number;
1080
+ listingsCreated?: number;
1081
+ listingsUpdated?: number;
1082
+ listingsSkipped?: number;
1083
+ listingsFailed?: number;
1084
+ imagesProcessed?: number;
1085
+ variationsProcessed?: number;
1086
+ };
599
1087
  /** Detailed sync results by operation */
600
- results?: Record<string, string | number | boolean>;
1088
+ results?: {
1089
+ pull?: {
1090
+ listingsRetrieved?: number;
1091
+ newListingsCreated?: number;
1092
+ existingListingsUpdated?: number;
1093
+ };
1094
+ push?: {
1095
+ listingsPushed?: number;
1096
+ listingsCreated?: number;
1097
+ listingsUpdated?: number;
1098
+ };
1099
+ };
601
1100
  /** Details of successfully processed listings */
602
- successfulListings?: Array<Record<string, string | number | boolean>>;
1101
+ successfulListings?: Array<{
1102
+ internalId?: string;
1103
+ externalId?: string;
1104
+ title?: string;
1105
+ operation?: string;
1106
+ timestamp?: string;
1107
+ }>;
603
1108
  /** Details of listings that failed to sync */
604
- failedListings?: Array<Record<string, string | number | boolean>>;
1109
+ failedListings?: Array<{
1110
+ internalId?: string;
1111
+ externalId?: string;
1112
+ title?: string;
1113
+ error?: {
1114
+ code?: string;
1115
+ message?: string;
1116
+ details?: Record<string, unknown>;
1117
+ };
1118
+ timestamp?: string;
1119
+ }>;
605
1120
  /** Non-listing-specific errors encountered */
606
- errors?: Array<Record<string, string | number | boolean>>;
1121
+ errors?: Array<{
1122
+ type?: string;
1123
+ message?: string;
1124
+ timestamp?: string;
1125
+ details?: Record<string, unknown>;
1126
+ }>;
607
1127
  /** When sync operation completed */
608
1128
  completedAt?: string;
609
1129
  /** When next sync is recommended */
@@ -626,11 +1146,17 @@ export interface MarketplaceListingSyncRequestMessage {
626
1146
  /** Scope of listings to sync */
627
1147
  syncScope?: string;
628
1148
  /** Specific listing IDs to sync (if syncScope=specific) */
629
- listingIds?: Array<Record<string, string | number | boolean>>;
1149
+ listingIds?: string[];
630
1150
  /** External marketplace listing IDs to sync */
631
- externalListingIds?: Array<Record<string, string | number | boolean>>;
1151
+ externalListingIds?: string[];
632
1152
  /** Sync configuration options */
633
- options?: Record<string, string | number | boolean>;
1153
+ options?: {
1154
+ includeInactive?: boolean;
1155
+ includeImages?: boolean;
1156
+ includeVariations?: boolean;
1157
+ includeAnalytics?: boolean;
1158
+ batchSize?: number;
1159
+ };
634
1160
  /** Processing priority */
635
1161
  priority?: string;
636
1162
  /** Unique request identifier */
@@ -638,7 +1164,11 @@ export interface MarketplaceListingSyncRequestMessage {
638
1164
  /** Webhook URL for completion notification */
639
1165
  webhookUrl?: string;
640
1166
  /** Additional request context */
641
- metadata?: Record<string, string | number | boolean>;
1167
+ metadata?: {
1168
+ source?: string;
1169
+ scheduledSync?: boolean;
1170
+ retryCount?: number;
1171
+ };
642
1172
  }
643
1173
  /**
644
1174
  * Notifies backend that marketplace tags generation completed. Contains generated tags optimized for discoverability with metadata tracking.
@@ -649,9 +1179,14 @@ export interface MarketplaceListingTagsGenerationCompletedMessage {
649
1179
  /** Type of entity processed */
650
1180
  entityType: string;
651
1181
  /** Generated searchability tags (style, technical, usage keywords) */
652
- tags: Array<Record<string, string | number | boolean>>;
1182
+ tags: string[];
653
1183
  /** Content generation metadata for tracking */
654
- metadata: Record<string, string | number | boolean>;
1184
+ metadata: {
1185
+ source: string;
1186
+ generatedAt: string;
1187
+ aiModel: string;
1188
+ confidence: number;
1189
+ };
655
1190
  /** Error message if generation failed */
656
1191
  error?: string;
657
1192
  }
@@ -672,11 +1207,17 @@ export interface MarketplaceListingTagsGenerationRequestMessage {
672
1207
  /** Callback URL for completion notification */
673
1208
  webhookUrl?: string;
674
1209
  /** Technical analysis data for tag generation */
675
- technicalMetadata?: Record<string, string | number | boolean>;
1210
+ technicalMetadata?: {
1211
+ vertices?: number;
1212
+ faces?: number;
1213
+ volumeMm3?: number;
1214
+ dimensionsMm?: number[];
1215
+ isWatertight?: boolean;
1216
+ };
676
1217
  /** URLs to 360-degree thumbnail views for visual analysis */
677
- thumbnailUrls?: Array<Record<string, string | number | boolean>>;
1218
+ thumbnailUrls?: string[];
678
1219
  /** Currently assigned tags to supplement or replace */
679
- existingTags?: Array<Record<string, string | number | boolean>>;
1220
+ existingTags?: string[];
680
1221
  /** Current classification for category-based tags */
681
1222
  existingCategory?: string;
682
1223
  /** Maximum number of tags for marketplace (e.g., 13 for Etsy) */
@@ -686,7 +1227,7 @@ export interface MarketplaceListingTagsGenerationRequestMessage {
686
1227
  /** Artistic style of the model (e.g., 'realistic', 'low-poly') */
687
1228
  style?: string;
688
1229
  /** Intended uses for the model */
689
- useCases?: Array<Record<string, string | number | boolean>>;
1230
+ useCases?: string[];
690
1231
  }
691
1232
  /**
692
1233
  * Notifies backend that marketplace title generation completed. Contains generated title with metadata tracking.
@@ -699,7 +1240,12 @@ export interface MarketplaceListingTitleGenerationCompletedMessage {
699
1240
  /** Marketplace-optimized title */
700
1241
  title: string;
701
1242
  /** Content generation metadata for tracking */
702
- metadata: Record<string, string | number | boolean>;
1243
+ metadata: {
1244
+ source: string;
1245
+ generatedAt: string;
1246
+ aiModel: string;
1247
+ confidence: number;
1248
+ };
703
1249
  /** Error message if generation failed */
704
1250
  error?: string;
705
1251
  }
@@ -720,9 +1266,13 @@ export interface MarketplaceListingTitleGenerationRequestMessage {
720
1266
  /** Callback URL for completion notification */
721
1267
  webhookUrl?: string;
722
1268
  /** Technical analysis data for context */
723
- technicalMetadata?: Record<string, string | number | boolean>;
1269
+ technicalMetadata?: {
1270
+ vertices?: number;
1271
+ faces?: number;
1272
+ dimensionsMm?: number[];
1273
+ };
724
1274
  /** Currently assigned tags for SEO keywords */
725
- existingTags?: Array<Record<string, string | number | boolean>>;
1275
+ existingTags?: string[];
726
1276
  /** Current classification for categorization */
727
1277
  existingCategory?: string;
728
1278
  /** Maximum character count for marketplace (e.g., 140 for Etsy) */
@@ -732,7 +1282,7 @@ export interface MarketplaceListingTitleGenerationRequestMessage {
732
1282
  /** Target geographic market (e.g., 'US', 'EU') */
733
1283
  targetMarket?: string;
734
1284
  /** Specific keywords to include */
735
- keywords?: Array<Record<string, string | number | boolean>>;
1285
+ keywords?: string[];
736
1286
  }
737
1287
  /**
738
1288
  * Result of a listing update operation
@@ -745,7 +1295,7 @@ export interface MarketplaceListingUpdateCompletedMessage {
745
1295
  /** Status of the update (success, failed) */
746
1296
  status?: string;
747
1297
  /** Result details from the marketplace API */
748
- result?: Record<string, string | number | boolean>;
1298
+ result?: Record<string, unknown>;
749
1299
  /** Error message if failed */
750
1300
  error?: string;
751
1301
  }
@@ -758,9 +1308,21 @@ export interface MarketplaceListingUpdateRequestMessage {
758
1308
  /** External ID of the listing to update */
759
1309
  listingId?: string;
760
1310
  /** Fields to update */
761
- updates?: Record<string, string | number | boolean>;
1311
+ updates?: {
1312
+ price?: number;
1313
+ quantity?: number;
1314
+ title?: string;
1315
+ description?: string;
1316
+ tags?: string[];
1317
+ };
762
1318
  /** User credentials for the marketplace */
763
- credentials?: Record<string, string | number | boolean>;
1319
+ credentials?: {
1320
+ access_token?: string;
1321
+ refresh_token?: string;
1322
+ expires_at?: number;
1323
+ api_key?: string;
1324
+ api_secret?: string;
1325
+ };
764
1326
  }
765
1327
  /**
766
1328
  * Indicates completion of marketplace listing publication. Contains external listing ID and URL, or error details if failed. Works with any marketplace provider (etsy, ebay, etc.).
@@ -785,11 +1347,16 @@ export interface MarketplacePublishListingCompletedMessage {
785
1347
  /** External marketplace file ID (only if status=SUCCESS) */
786
1348
  externalFileId?: string;
787
1349
  /** Error details (only if status=FAILED) */
788
- error?: Record<string, string | number | boolean>;
1350
+ error?: {
1351
+ code?: string;
1352
+ message?: string;
1353
+ details?: Record<string, unknown>;
1354
+ retryable?: boolean;
1355
+ };
789
1356
  /** When the listing was created (ISO 8601, only if status=SUCCESS) */
790
1357
  publishedAt?: string;
791
1358
  /** Processing time in milliseconds */
792
- processingDuration?: string | number | boolean;
1359
+ processingDuration?: number;
793
1360
  }
794
1361
  /**
795
1362
  * Publishes a single metamodel listing to a marketplace for a specific material variant. Creates listing, uploads digital file, and returns external listing ID. This message is enqueued for EACH material variant when publishing a metamodel. The marketplace type (etsy, ebay, etc.) is determined by the marketplaceProvider field.
@@ -806,15 +1373,41 @@ export interface MarketplacePublishListingRequestMessage {
806
1373
  /** UUID of the marketplace connection configuration */
807
1374
  marketplaceConnectionId?: string;
808
1375
  /** Material-specific listing configuration */
809
- materialVariant?: Record<string, string | number | boolean>;
1376
+ materialVariant?: {
1377
+ materialName: string;
1378
+ price: number;
1379
+ sku?: string;
1380
+ currency?: string;
1381
+ };
810
1382
  /** Common listing information shared across variants */
811
- baseListingData?: Record<string, string | number | boolean>;
1383
+ baseListingData?: {
1384
+ title: string;
1385
+ description: string;
1386
+ tags: string[];
1387
+ taxonomyId: number;
1388
+ whoMade?: string;
1389
+ whenMade?: string;
1390
+ isDigital?: boolean;
1391
+ quantity?: number;
1392
+ };
812
1393
  /** Publishing configuration (marketplace-specific options) */
813
- publishOptions?: Record<string, string | number | boolean>;
1394
+ publishOptions?: {
1395
+ autoActivate?: boolean;
1396
+ marketplaceSpecificOptions?: Record<string, unknown>;
1397
+ };
814
1398
  /** Encrypted marketplace credentials (retrieved from marketplaceConnectionId) */
815
- marketplaceCredentials?: Record<string, string | number | boolean>;
1399
+ marketplaceCredentials?: {
1400
+ accessToken: string;
1401
+ externalShopId?: string;
1402
+ expiresAt?: string;
1403
+ };
816
1404
  /** Digital file to upload */
817
- fileMetadata?: Record<string, string | number | boolean>;
1405
+ fileMetadata?: {
1406
+ storageItemId: string;
1407
+ fileName: string;
1408
+ fileSize?: number;
1409
+ mimeType?: string;
1410
+ };
818
1411
  /** Callback URL for completion notification */
819
1412
  webhookUrl?: string;
820
1413
  }
@@ -827,13 +1420,36 @@ export interface MediaBatchDownloadCompletedMessage {
827
1420
  /** The final status of the batch download operation. */
828
1421
  status: string;
829
1422
  /** List of successfully processed files. */
830
- processedFiles?: Array<Record<string, string | number | boolean>>;
1423
+ processedFiles?: Array<{
1424
+ originalPath: string;
1425
+ originalName?: string;
1426
+ s3Location: {
1427
+ bucket?: string;
1428
+ key?: string;
1429
+ url?: string;
1430
+ };
1431
+ processedType?: string;
1432
+ originalSize?: number;
1433
+ processedSize?: number;
1434
+ compressionRatio?: number;
1435
+ }>;
831
1436
  /** List of files that failed to process. */
832
- failedFiles?: Array<Record<string, string | number | boolean>>;
1437
+ failedFiles?: Array<{
1438
+ path?: string;
1439
+ error?: string;
1440
+ }>;
833
1441
  /** Timestamp when the batch processing completed. */
834
1442
  processedAt: string;
835
1443
  /** Statistics about the batch processing. */
836
- statistics?: Record<string, string | number | boolean>;
1444
+ statistics?: {
1445
+ totalFiles?: number;
1446
+ successfulFiles?: number;
1447
+ failedFiles?: number;
1448
+ totalOriginalSize?: number;
1449
+ totalProcessedSize?: number;
1450
+ averageCompressionRatio?: number;
1451
+ processingDuration?: number;
1452
+ };
837
1453
  }
838
1454
  /**
839
1455
  * Request to download and process a batch of media files from a storage provider. Images are compressed and resized to specified dimensions, converted to WebP format. Text files and documents are processed and stored with metadata. All processed files are uploaded to MinIO S3 storage under the media/{batchId}/ prefix.
@@ -857,13 +1473,28 @@ export interface MediaBatchDownloadRequestMessage {
857
1473
  storageConnectionId?: string;
858
1474
  /** Decrypted credentials for the storage provider (Fat Payload pattern). Required when downloadStrategy is 'storage_provider'.
859
1475
  */
860
- credentials?: Record<string, string | number | boolean>;
1476
+ credentials?: {
1477
+ provider?: string;
1478
+ accessToken?: string;
1479
+ refreshToken?: string;
1480
+ clientId?: string;
1481
+ clientSecret?: string;
1482
+ host?: string;
1483
+ username?: string;
1484
+ password?: string;
1485
+ port?: number;
1486
+ };
861
1487
  /** Array of media files to download and process. Must contain at least one file. Each file includes metadata for identification and processing.
862
1488
  */
863
- mediaFiles?: Array<Record<string, string | number | boolean>>;
1489
+ mediaFiles?: Array<unknown>;
864
1490
  /** Optional compression settings that override deployment environment defaults. If not provided, uses values from MAX_IMAGE_WIDTH, MAX_IMAGE_HEIGHT, IMAGE_QUALITY, and OUTPUT_FORMAT environment variables.
865
1491
  */
866
- compressionSettings?: Record<string, string | number | boolean>;
1492
+ compressionSettings?: {
1493
+ maxWidth?: number;
1494
+ maxHeight?: number;
1495
+ imageQuality?: number;
1496
+ outputFormat?: string;
1497
+ };
867
1498
  }
868
1499
  /**
869
1500
  * Handles metamodel metadata generation completion. Contains AI-generated metadata and aggregated technical analysis.
@@ -872,9 +1503,99 @@ export interface MetamodelMetadataGenerationCompletedMessage {
872
1503
  /** The unique identifier for the metamodel */
873
1504
  metamodelId: string;
874
1505
  /** AI-generated metadata for the metamodel */
875
- metadata: Record<string, string | number | boolean>;
1506
+ metadata: {
1507
+ classification: {
1508
+ primary_category?: string;
1509
+ sub_category?: string;
1510
+ confidence?: number;
1511
+ reasoning?: string[];
1512
+ };
1513
+ printTechnology: {
1514
+ recommended?: string;
1515
+ confidence?: number;
1516
+ reasoning?: string[];
1517
+ constituentsAnalysis?: {
1518
+ fdmCompatible?: number;
1519
+ resinRequired?: number;
1520
+ totalParts?: number;
1521
+ };
1522
+ };
1523
+ franchise: {
1524
+ name?: string;
1525
+ universe?: string;
1526
+ confidence?: number;
1527
+ licensingInfo?: string;
1528
+ };
1529
+ tagDataJson: {
1530
+ style?: string[];
1531
+ technical?: string[];
1532
+ source?: string[];
1533
+ quality?: string[];
1534
+ scale?: string[];
1535
+ usage?: string[];
1536
+ custom?: string[];
1537
+ };
1538
+ assemblyMetadata: {
1539
+ totalParts?: number;
1540
+ complexity?: string;
1541
+ estimatedAssemblyTime?: number;
1542
+ requiresGlue?: boolean;
1543
+ requiresPainting?: boolean;
1544
+ requiresSupports?: boolean;
1545
+ instructions?: {
1546
+ url?: string;
1547
+ embedded?: string;
1548
+ };
1549
+ };
1550
+ aiGenerationMetadata: {
1551
+ workerVersion?: string;
1552
+ ollamaModels?: string[];
1553
+ totalResponses?: number;
1554
+ processingTimeSeconds?: number;
1555
+ promptTokens?: number;
1556
+ completionTokens?: number;
1557
+ generatedAt?: string;
1558
+ };
1559
+ generatedDescription: string;
1560
+ pricing: Record<string, unknown>;
1561
+ marketplaceListingsJson: Record<string, unknown>;
1562
+ };
876
1563
  /** Aggregated technical analysis from constituent models */
877
- technicalMetadata: Record<string, string | number | boolean>;
1564
+ technicalMetadata: {
1565
+ totalVertices: number;
1566
+ totalFaces: number;
1567
+ totalEdges: number;
1568
+ averageDetailLevel: string;
1569
+ assembledBoundingBox: {
1570
+ width?: number;
1571
+ height?: number;
1572
+ depth?: number;
1573
+ originalUnit?: string;
1574
+ };
1575
+ totalVolumeCubicMm: number;
1576
+ totalSurfaceAreaSqMm: number;
1577
+ allPartsManifold: boolean;
1578
+ lowestQualityScore: number;
1579
+ lowestPrintabilityScore: number;
1580
+ partsRequiringRepair: number;
1581
+ partsWithThinWalls: number;
1582
+ constituentModels: Array<{
1583
+ modelId?: string;
1584
+ name?: string;
1585
+ orderIndex?: number;
1586
+ purpose?: string;
1587
+ isOptional?: boolean;
1588
+ }>;
1589
+ validationStatus: {
1590
+ allPartsPresent?: boolean;
1591
+ allPartsAnalyzed?: boolean;
1592
+ assemblyInstructionsComplete?: boolean;
1593
+ minimumQualityMet?: boolean;
1594
+ readyForMarketplace?: boolean;
1595
+ };
1596
+ analyzedAt: string;
1597
+ analysisVersion: string;
1598
+ };
878
1599
  }
879
1600
  /**
880
1601
  * Handles metamodel metadata generation requests via Ollama. Aggregates data from constituent models and generates AI-enhanced metadata.
@@ -883,7 +1604,7 @@ export interface MetamodelMetadataGenerationRequestMessage {
883
1604
  /** The unique identifier for the metamodel */
884
1605
  metamodelId?: string;
885
1606
  /** Array of model IDs that compose this metamodel */
886
- constituentModelIds?: Array<Record<string, string | number | boolean>>;
1607
+ constituentModelIds?: string[];
887
1608
  /** The name of the metamodel */
888
1609
  name?: string;
889
1610
  /** The owner's user ID */
@@ -891,7 +1612,19 @@ export interface MetamodelMetadataGenerationRequestMessage {
891
1612
  /** The library containing this metamodel */
892
1613
  libraryId?: string;
893
1614
  /** Enriched metadata for constituent models (includes storage items) */
894
- constituentModels?: Array<Record<string, string | number | boolean>>;
1615
+ constituentModels?: Array<{
1616
+ modelId?: string;
1617
+ name?: string;
1618
+ storageConnectionId?: string;
1619
+ storageItems?: Array<{
1620
+ path?: string;
1621
+ mimeType?: string;
1622
+ size?: number;
1623
+ s3Key?: string;
1624
+ bucket?: string;
1625
+ isImage?: boolean;
1626
+ }>;
1627
+ }>;
895
1628
  /** Optional webhook URL for async completion notification */
896
1629
  webhookUrl?: string;
897
1630
  }
@@ -913,7 +1646,7 @@ export interface ModelAnalyticsCollectionRequestMessage {
913
1646
  /** Sub-category for more specific targeting */
914
1647
  subCategory?: string;
915
1648
  /** Relevant tags from metamodel metadata (max 10) */
916
- tags?: Array<Record<string, string | number | boolean>>;
1649
+ tags?: string[];
917
1650
  /** Franchise name if detected (e.g., "Dungeons & Dragons") */
918
1651
  franchise?: string;
919
1652
  /** Classification confidence score */
@@ -934,13 +1667,29 @@ export interface ModelDiscoveryFolderProcessedEventMessage {
934
1667
  /** The path to the processed folder. */
935
1668
  folderPath?: string;
936
1669
  /** A list of files discovered in the folder. */
937
- discoveredFiles?: Array<Record<string, string | number | boolean>>;
1670
+ discoveredFiles?: Array<{
1671
+ path: string;
1672
+ name: string;
1673
+ size: number;
1674
+ modifiedAt: string;
1675
+ }>;
938
1676
  /** A signature representing the state of the folder. */
939
- folderSignature?: Record<string, string | number | boolean>;
1677
+ folderSignature?: {
1678
+ hash: string;
1679
+ calculatedAt: string;
1680
+ };
940
1681
  /** The timestamp when the folder was processed. */
941
1682
  processedAt?: string;
942
1683
  /** Statistics about the processed folder. */
943
- statistics?: Record<string, string | number | boolean>;
1684
+ statistics?: {
1685
+ totalFiles: number;
1686
+ modelFiles: number;
1687
+ mediaFiles: number;
1688
+ accessoryFiles: number;
1689
+ totalFolders: number;
1690
+ totalSize: number;
1691
+ processingDuration: number;
1692
+ };
944
1693
  }
945
1694
  /**
946
1695
  * Handles model discovery scan found events.
@@ -955,22 +1704,34 @@ export interface ModelDiscoveryScanFoundEventMessage {
955
1704
  /** A description of the model. */
956
1705
  description?: string;
957
1706
  /** An array of file types associated with the model. */
958
- fileTypes?: Array<Record<string, string | number | boolean>>;
1707
+ fileTypes?: string[];
959
1708
  /** The size of the model file in bytes. */
960
1709
  size?: number;
961
1710
  /** The storage location of the model. */
962
- storageLocation?: Record<string, string | number | boolean>;
1711
+ storageLocation?: {
1712
+ storageConnectionId: string;
1713
+ path: string;
1714
+ libraryId: string;
1715
+ ownerId: string;
1716
+ };
963
1717
  /** The type of the storage provider. */
964
1718
  providerType?: string;
965
1719
  /** A flexible object for additional metadata. */
966
- metadata?: Record<string, string | number | boolean>;
1720
+ metadata?: Record<string, unknown>;
967
1721
  }
968
1722
  /**
969
1723
  * Handles model discovery scan progress events.
970
1724
  */
971
1725
  export interface ModelDiscoveryScanProgressEventMessage {
972
1726
  /** Contains the discovery scan progress details. */
973
- payload?: Record<string, string | number | boolean>;
1727
+ payload?: {
1728
+ jobId: string;
1729
+ storageConnectionId: string;
1730
+ status: string;
1731
+ message: string;
1732
+ progress: number;
1733
+ error?: string;
1734
+ };
974
1735
  }
975
1736
  /**
976
1737
  * Handles model discovery scan requests events.
@@ -985,9 +1746,9 @@ export interface ModelDiscoveryScanRequestMessage {
985
1746
  /** The specific path within the storage connection to scan for this library. */
986
1747
  path?: string;
987
1748
  /** Decrypted credentials for the storage provider. */
988
- credentials?: Record<string, string | number | boolean>;
1749
+ credentials?: Record<string, unknown>;
989
1750
  /** Configuration for the storage connection (e.g. scanRootPath). */
990
- configuration?: Record<string, string | number | boolean>;
1751
+ configuration?: Record<string, unknown>;
991
1752
  }
992
1753
  /**
993
1754
  * Request to index a 3D model for similarity search.
@@ -996,7 +1757,7 @@ export interface ModelFinderIndexRequestMessage {
996
1757
  /** */
997
1758
  modelId?: string;
998
1759
  /** */
999
- storageItem?: string | number | boolean;
1760
+ storageItem?: unknown;
1000
1761
  }
1001
1762
  /**
1002
1763
  * Response containing search results from the model finder.
@@ -1005,7 +1766,11 @@ export interface ModelFinderResponseMessage {
1005
1766
  /** */
1006
1767
  requestId?: string;
1007
1768
  /** */
1008
- results?: Array<Record<string, string | number | boolean>>;
1769
+ results?: Array<{
1770
+ modelId?: string;
1771
+ similarity?: number;
1772
+ metamodelIds?: string[];
1773
+ }>;
1009
1774
  }
1010
1775
  /**
1011
1776
  * Request to search for similar 3D models.
@@ -1016,7 +1781,7 @@ export interface ModelFinderSearchRequestMessage {
1016
1781
  /** Optional: Search using an uploaded image */
1017
1782
  referenceImageId?: string;
1018
1783
  /** */
1019
- limit?: string | number | boolean;
1784
+ limit?: number;
1020
1785
  }
1021
1786
  /**
1022
1787
  * Notifies backend that enriched marketplace metadata generation completed. Backend updates Model entity with generated description, tags, classification, etc.
@@ -1025,7 +1790,12 @@ export interface ModelMetadataGenerationCompletedMessage {
1025
1790
  /** UUID of the model that was processed. */
1026
1791
  modelId: string;
1027
1792
  /** Enriched marketplace metadata generated by LLM. */
1028
- metadata: Record<string, string | number | boolean>;
1793
+ metadata: {
1794
+ description: string;
1795
+ tags: string[];
1796
+ primaryCategory: string;
1797
+ subCategory: string;
1798
+ };
1029
1799
  }
1030
1800
  /**
1031
1801
  * Generates enriched marketplace metadata (SEO descriptions, tags, categories) for 3D models using LLM vision analysis. Worker receives all necessary data in the payload (Model, TechnicalMetadata, Thumbnails) and does NOT query the database. Prerequisites: file download, technical metadata, and thumbnail generation must be complete before this message is sent.
@@ -1034,20 +1804,89 @@ export interface ModelMetadataGenerationRequestMessage {
1034
1804
  /** UUID of the model (reference only) */
1035
1805
  modelId?: string;
1036
1806
  /** Core model entity data */
1037
- model?: Record<string, string | number | boolean>;
1807
+ model?: {
1808
+ name?: string;
1809
+ fileName?: string;
1810
+ fileSize?: number;
1811
+ ownerId?: string;
1812
+ };
1038
1813
  /** Geometric and technical analysis results */
1039
- technicalMetadata?: Record<string, string | number | boolean>;
1814
+ technicalMetadata?: {
1815
+ vertices?: number;
1816
+ faces?: number;
1817
+ volumeMm3?: number;
1818
+ dimensionsMm?: number[];
1819
+ isWatertight?: boolean;
1820
+ boundingBox?: Record<string, unknown>;
1821
+ };
1040
1822
  /** List of 360 degree thumbnail views (URLs or paths) */
1041
- thumbnails?: Array<Record<string, string | number | boolean>>;
1823
+ thumbnails?: Array<{
1824
+ id?: string;
1825
+ url?: string;
1826
+ angle?: number;
1827
+ }>;
1042
1828
  }
1043
1829
  /**
1044
1830
  * Handles model metamodel detection found with hierarchical relationships.
1045
1831
  */
1046
1832
  export interface ModelMetamodelDetectionFoundMessage {
1047
1833
  /** List of metamodel nodes in hierarchical structure (roots and children). */
1048
- metamodels: Array<Record<string, string | number | boolean>>;
1834
+ metamodels: Array<{
1835
+ internalId: string;
1836
+ name: string;
1837
+ storageItemIds?: string[];
1838
+ childMetamodelIds?: string[];
1839
+ parentMetamodelId?: string;
1840
+ confidenceScore: number;
1841
+ libraryId: string;
1842
+ mediaBatchId?: string;
1843
+ metaModelType?: string;
1844
+ metadata?: {
1845
+ level?: number;
1846
+ sku?: string;
1847
+ scale?: string;
1848
+ creator?: string;
1849
+ isVariant?: boolean;
1850
+ partType?: string;
1851
+ source?: string;
1852
+ thingId?: string;
1853
+ url?: string;
1854
+ thumbnail?: string;
1855
+ mediaUrls?: Array<{
1856
+ url: string;
1857
+ name?: string;
1858
+ type?: string;
1859
+ metadata?: {
1860
+ mediaType?: string;
1861
+ isPrimary?: boolean;
1862
+ width?: number;
1863
+ height?: number;
1864
+ thingId?: string;
1865
+ fileId?: string;
1866
+ };
1867
+ }>;
1868
+ };
1869
+ }>;
1049
1870
  /** EKG edges derived from Louvain clustering (OPTIONAL - new field) */
1050
- ekgEdges?: Array<Record<string, string | number | boolean>>;
1871
+ ekgEdges?: Array<{
1872
+ sourceMetamodelId: string;
1873
+ targetId?: string;
1874
+ targetType?: string;
1875
+ massFunction: {
1876
+ related?: number;
1877
+ unrelated?: number;
1878
+ uncertainty?: number;
1879
+ };
1880
+ heuristicContributions?: Array<{
1881
+ name?: string;
1882
+ belief?: number;
1883
+ }>;
1884
+ louvainMetadata?: {
1885
+ communityId?: string;
1886
+ modularity?: number;
1887
+ edgeWeight?: number;
1888
+ };
1889
+ }>;
1051
1890
  }
1052
1891
  /**
1053
1892
  * Handles model metamodel detection requests.
@@ -1058,15 +1897,91 @@ export interface ModelMetamodelDetectionRequestMessage {
1058
1897
  /** The path to the folder that was processed. */
1059
1898
  folderPath: string;
1060
1899
  /** A list of files discovered in the folder. Worker should check this first, then manifestUrl. */
1061
- discoveredFiles?: Array<Record<string, string | number | boolean>>;
1900
+ discoveredFiles?: Array<{
1901
+ path: string;
1902
+ name: string;
1903
+ size: number;
1904
+ modifiedAt: string;
1905
+ }>;
1062
1906
  /** URL to a JSON file containing the list of discovered files (for large folders) */
1063
1907
  manifestUrl?: string;
1064
1908
  /** A signature representing the state of the folder. */
1065
- folderSignature: Record<string, string | number | boolean>;
1909
+ folderSignature: {
1910
+ hash: string;
1911
+ calculatedAt: string;
1912
+ };
1066
1913
  /** The timestamp when the folder was processed. */
1067
1914
  processedAt: string;
1068
1915
  /** Statistics about the processed folder. */
1069
- statistics: Record<string, string | number | boolean>;
1916
+ statistics: {
1917
+ totalFiles: number;
1918
+ modelFiles: number;
1919
+ mediaFiles: number;
1920
+ accessoryFiles: number;
1921
+ totalFolders: number;
1922
+ totalSize: number;
1923
+ processingDuration: number;
1924
+ };
1925
+ }
1926
+ /**
1927
+ * Reports completion of 3D print analysis — contains estimation, printability, and cost breakdown per FR-022
1928
+ */
1929
+ export interface ModelPrintAnalysisCompletedMessage {
1930
+ /** ID of the original analysis request job */
1931
+ originalJobId?: string;
1932
+ /** UUID of the analysed model */
1933
+ modelId?: string;
1934
+ /** Analysis result status */
1935
+ status?: string;
1936
+ /** Error description when status is FAILED */
1937
+ errorMessage?: string;
1938
+ /** Material type used for estimation */
1939
+ material?: string;
1940
+ /** Quality preset used */
1941
+ quality?: string;
1942
+ /** Estimated total print time in minutes */
1943
+ printTimeMinutes?: number;
1944
+ /** Estimated material consumption in grams (body only) */
1945
+ materialGrams?: number;
1946
+ /** Whether the model requires support structures */
1947
+ needsSupport?: boolean;
1948
+ /** Estimated support material in grams */
1949
+ supportMaterialGrams?: number;
1950
+ /** Percentage of surface area with overhangs > 45° */
1951
+ overhangPercentage?: number;
1952
+ /** Thinnest detected wall in millimeters */
1953
+ minWallThicknessMm?: number;
1954
+ /** Solid volume of the mesh in cm³ */
1955
+ solidVolumeCm3?: number;
1956
+ /** Total surface area in cm² */
1957
+ surfaceAreaCm2?: number;
1958
+ /** Bounding box in millimeters */
1959
+ boundingBox?: {
1960
+ x?: number;
1961
+ y?: number;
1962
+ z?: number;
1963
+ };
1964
+ /** Total estimated production cost in EUR */
1965
+ estimatedCostEUR?: number;
1966
+ /** Granular cost breakdown per WF-009 MaterialCostCalculatorService */
1967
+ costBreakdown?: Record<string, unknown>;
1968
+ }
1969
+ /**
1970
+ * Triggers 3D print analysis for a model — estimates print time, material usage, support needs, and cost breakdown per FR-022
1971
+ */
1972
+ export interface ModelPrintAnalysisRequestMessage {
1973
+ /** UUID of the model to analyse */
1974
+ modelId?: string;
1975
+ /** UUID of the user who owns the model */
1976
+ ownerId?: string;
1977
+ /** Material type enum value (e.g. PLA, PETG, RESIN_STANDARD) */
1978
+ material?: string;
1979
+ /** Print quality preset */
1980
+ quality?: string;
1981
+ /** URL called when analysis completes or fails */
1982
+ webhookUrl?: string;
1983
+ /** Path to model in MinIO storage for geometry analysis (e.g. 'raw_models/{modelId}/original.glb') */
1984
+ minioPath?: string;
1070
1985
  }
1071
1986
  /**
1072
1987
  * Contains sellability analysis results including Etsy-specific recommendations, material pricing, and marketplace compatibility scores
@@ -1079,21 +1994,67 @@ export interface ModelSellabilityAnalysisCompletedMessage {
1079
1994
  /** Overall sellability score (0-100) */
1080
1995
  sellabilityScore?: number;
1081
1996
  /** Pricing analysis and recommendations with material-specific pricing (v2.0.0) */
1082
- pricingRecommendations?: Record<string, string | number | boolean>;
1997
+ pricingRecommendations?: {
1998
+ suggestedPrice?: number;
1999
+ priceRange?: {
2000
+ min?: number;
2001
+ max?: number;
2002
+ median?: number;
2003
+ };
2004
+ competitorAverage?: number;
2005
+ materialPricing?: Record<string, unknown>;
2006
+ factors?: Array<{
2007
+ factor?: string;
2008
+ impact?: string;
2009
+ description?: string;
2010
+ }>;
2011
+ };
1083
2012
  /** Recommended marketplaces with Etsy-specific scoring (v2.0.0) */
1084
- marketplaceRecommendations?: Array<Record<string, string | number | boolean>>;
2013
+ marketplaceRecommendations?: Array<{
2014
+ marketplace?: string;
2015
+ compatibilityScore?: number;
2016
+ reasoning?: string;
2017
+ estimatedReach?: number;
2018
+ platformFee?: number;
2019
+ etsySpecificData?: {
2020
+ categoryFitScore?: number;
2021
+ recommendedMaterials?: string[];
2022
+ estimatedTimeToFirstSale?: string;
2023
+ };
2024
+ }>;
1085
2025
  /** Market demand insights */
1086
- demandAnalysis?: Record<string, string | number | boolean>;
2026
+ demandAnalysis?: {
2027
+ categoryDemand?: string;
2028
+ trendingScore?: number;
2029
+ searchVolume?: number;
2030
+ competitionLevel?: string;
2031
+ trendDirection?: string;
2032
+ };
1087
2033
  /** Quality-related factors affecting sellability */
1088
- qualityFactors?: Record<string, string | number | boolean>;
2034
+ qualityFactors?: {
2035
+ technicalQuality?: number;
2036
+ printability?: number;
2037
+ uniqueness?: number;
2038
+ marketFit?: number;
2039
+ };
1089
2040
  /** Actionable recommendations to improve sellability */
1090
- recommendations?: Array<Record<string, string | number | boolean>>;
2041
+ recommendations?: Array<{
2042
+ category?: string;
2043
+ priority?: string;
2044
+ title?: string;
2045
+ description?: string;
2046
+ expectedImpact?: string;
2047
+ }>;
1091
2048
  /** Analysis completion timestamp (ISO 8601) */
1092
2049
  analyzedAt?: string;
1093
2050
  /** Analysis algorithm version */
1094
2051
  analysisVersion?: string;
1095
2052
  /** Error information if analysis failed */
1096
- error?: Record<string, string | number | boolean>;
2053
+ error?: {
2054
+ code?: string;
2055
+ message?: string;
2056
+ details?: Record<string, unknown>;
2057
+ };
1097
2058
  }
1098
2059
  /**
1099
2060
  * Analyzes a metamodel to determine sellability score, pricing recommendations, and optimal marketplace selection. Enhanced with Etsy-specific analysis including competitor pricing, category demand trends, and material suitability.
@@ -1104,11 +2065,21 @@ export interface ModelSellabilityAnalysisRequestMessage {
1104
2065
  /** UUID of the user who owns the metamodel */
1105
2066
  ownerId?: string;
1106
2067
  /** Full metamodel data including technical metadata, enriched metadata, and child models. Injected by backend to avoid DB access. */
1107
- metamodelData?: Record<string, string | number | boolean>;
2068
+ metamodelData?: Record<string, unknown>;
1108
2069
  /** URL to a JSON manifest containing the metamodel data if it is too large for the message payload. */
1109
2070
  manifestUrl?: string;
1110
2071
  /** Optional analysis configuration */
1111
- analysisOptions?: Record<string, string | number | boolean>;
2072
+ analysisOptions?: {
2073
+ targetMarketplaces?: string[];
2074
+ competitorAnalysis?: boolean;
2075
+ demandAnalysis?: boolean;
2076
+ includeChildModels?: boolean;
2077
+ etsyAnalysisOptions?: {
2078
+ analyzeMaterialSuitability?: boolean;
2079
+ fetchEtsyTrends?: boolean;
2080
+ competitorCount?: number;
2081
+ };
2082
+ };
1112
2083
  }
1113
2084
  /**
1114
2085
  * Handles completion of 3D model semantic analysis with generated tags and similarity results.
@@ -1121,15 +2092,61 @@ export interface ModelSemanticAnalysisCompletedMessage {
1121
2092
  /** Final processing status. */
1122
2093
  processingStatus?: string;
1123
2094
  /** Generated semantic metadata and analysis results. */
1124
- semanticMetadata?: Record<string, string | number | boolean>;
2095
+ semanticMetadata?: {
2096
+ semanticTags?: Array<{
2097
+ tagName?: string;
2098
+ confidence?: number;
2099
+ category?: string;
2100
+ }>;
2101
+ embedding?: number[];
2102
+ similarModels?: Array<{
2103
+ modelId?: string;
2104
+ similarity?: number;
2105
+ metadata?: Record<string, unknown>;
2106
+ }>;
2107
+ geometricFeatures?: {
2108
+ vertexCount?: number;
2109
+ faceCount?: number;
2110
+ volume?: number;
2111
+ surfaceArea?: number;
2112
+ boundingBox?: {
2113
+ width?: number;
2114
+ height?: number;
2115
+ depth?: number;
2116
+ };
2117
+ isWatertight?: boolean;
2118
+ hasTextureCoords?: boolean;
2119
+ complexity?: string;
2120
+ };
2121
+ };
1125
2122
  /** Processing performance metrics. */
1126
- processingTime?: Record<string, string | number | boolean>;
2123
+ processingTime?: {
2124
+ totalTimeMs?: number;
2125
+ geometryTimeMs?: number;
2126
+ neuralTimeMs?: number;
2127
+ searchTimeMs?: number;
2128
+ };
1127
2129
  /** Processing quality and confidence metrics. */
1128
- qualityMetrics?: Record<string, string | number | boolean>;
2130
+ qualityMetrics?: {
2131
+ overallConfidence?: number;
2132
+ tagCount?: number;
2133
+ duplicateDetected?: boolean;
2134
+ knowledgeBaseUpdated?: boolean;
2135
+ };
1129
2136
  /** Error information if processing failed. */
1130
- error?: Record<string, string | number | boolean>;
2137
+ error?: {
2138
+ message?: string;
2139
+ category?: string;
2140
+ retryable?: boolean;
2141
+ technicalDetails?: string;
2142
+ };
1131
2143
  /** Additional debug information for troubleshooting. */
1132
- debugInfo?: Record<string, string | number | boolean>;
2144
+ debugInfo?: {
2145
+ workerVersion?: string;
2146
+ processingNode?: string;
2147
+ gpuUsed?: boolean;
2148
+ memoryUsageMb?: number;
2149
+ };
1133
2150
  }
1134
2151
  /**
1135
2152
  * Handles 3D model semantic analysis requests using ULIP-2 neural networks and FAISS vector similarity search.
@@ -1150,7 +2167,13 @@ export interface ModelSemanticAnalysisRequestMessage {
1150
2167
  /** The type of the storage provider (S3, GoogleDrive, SFTP, etc). */
1151
2168
  storageProviderType?: string;
1152
2169
  /** Configuration options for semantic analysis. */
1153
- processingOptions?: Record<string, string | number | boolean>;
2170
+ processingOptions?: {
2171
+ pointCloudSize?: number;
2172
+ similarityThreshold?: number;
2173
+ similarityK?: number;
2174
+ enableDuplicateDetection?: boolean;
2175
+ generateThumbnail?: boolean;
2176
+ };
1154
2177
  /** Processing priority (1=highest, 10=lowest). */
1155
2178
  priority?: number;
1156
2179
  /** Optional webhook URL for completion notification. */
@@ -1169,15 +2192,20 @@ export interface ModelTechnicalMetadataCompletedMessage {
1169
2192
  /** Analysis completion status */
1170
2193
  status?: string;
1171
2194
  /** Number of vertices in the mesh */
1172
- vertices?: string | number | boolean;
2195
+ vertices?: number;
1173
2196
  /** Number of faces/polygons in the mesh */
1174
- faces?: string | number | boolean;
2197
+ faces?: number;
1175
2198
  /** Number of edges in the mesh */
1176
- edges?: string | number | boolean;
2199
+ edges?: number;
1177
2200
  /** Visual detail level based on polygon density */
1178
2201
  detailLevel?: string;
1179
2202
  /** 3D bounding box dimensions in millimeters */
1180
- boundingBox?: Record<string, string | number | boolean>;
2203
+ boundingBox?: {
2204
+ width?: number;
2205
+ height?: number;
2206
+ depth?: number;
2207
+ originalUnit?: string;
2208
+ };
1181
2209
  /** Model volume in cubic millimeters (for material calculation) */
1182
2210
  volumeCubicMm?: number;
1183
2211
  /** Total surface area in square millimeters */
@@ -1189,13 +2217,13 @@ export interface ModelTechnicalMetadataCompletedMessage {
1189
2217
  /** Is the mesh watertight/manifold? Critical for 3D printing (true = printable) */
1190
2218
  manifold?: boolean;
1191
2219
  /** Number of non-manifold edges (repair needed if > 0) */
1192
- nonManifoldEdges?: string | number | boolean;
2220
+ nonManifoldEdges?: number;
1193
2221
  /** Number of holes/boundary loops in the mesh (0 = closed mesh) */
1194
- holes?: string | number | boolean;
2222
+ holes?: number;
1195
2223
  /** Number of faces with inverted normals (causes rendering/slicing issues) */
1196
- flippedNormals?: string | number | boolean;
2224
+ flippedNormals?: number;
1197
2225
  /** Number of self-intersecting faces (0 = clean geometry) */
1198
- selfIntersections?: string | number | boolean;
2226
+ selfIntersections?: number;
1199
2227
  /** Overall quality score 0-100 (100 = perfect for printing, <60 needs repair) */
1200
2228
  qualityScore?: number;
1201
2229
  /** Printability score 0-100 (considers supports, orientation, size constraints) */
@@ -1203,17 +2231,47 @@ export interface ModelTechnicalMetadataCompletedMessage {
1203
2231
  /** Does this model require support structures for 3D printing? */
1204
2232
  requiresSupports?: boolean;
1205
2233
  /** Detected overhang areas requiring support structures */
1206
- overhangs?: Array<Record<string, string | number | boolean>>;
2234
+ overhangs?: Array<{
2235
+ angle?: number;
2236
+ area?: number;
2237
+ location?: string;
2238
+ }>;
1207
2239
  /** Estimated print time in minutes using normal quality settings (0.2mm layers, 20% infill) */
1208
- estimatedPrintTimeMinutes?: string | number | boolean;
2240
+ estimatedPrintTimeMinutes?: number;
1209
2241
  /** Print time estimates for different quality presets */
1210
- printTimeEstimates?: Record<string, string | number | boolean>;
2242
+ printTimeEstimates?: {
2243
+ draft?: number;
2244
+ normal?: number;
2245
+ highQuality?: number;
2246
+ };
1211
2247
  /** Estimated material usage in grams using 20% infill (assumes PLA density 1.24g/cm³) */
1212
2248
  estimatedMaterialGrams?: number;
1213
2249
  /** Material usage estimates for different infill percentages */
1214
- materialEstimates?: Record<string, string | number | boolean>;
2250
+ materialEstimates?: {
2251
+ infill10?: number;
2252
+ infill20?: number;
2253
+ infill50?: number;
2254
+ infill100?: number;
2255
+ };
1215
2256
  /** Recommended print orientation for minimal support material and best results */
1216
- recommendedOrientation?: Record<string, string | number | boolean>;
2257
+ recommendedOrientation?: {
2258
+ rotationX?: number;
2259
+ rotationY?: number;
2260
+ rotationZ?: number;
2261
+ reasoning?: string;
2262
+ };
2263
+ /** Slicer-derived recommended print settings based on model analysis (feeds into print job creation as defaults) */
2264
+ slicerRecommendations?: {
2265
+ layerHeightMm?: number;
2266
+ infillPercentage?: number;
2267
+ nozzleSizeMm?: number;
2268
+ printSpeedMmS?: number;
2269
+ temperatureC?: number;
2270
+ bedTemperatureC?: number;
2271
+ supportEnabled?: boolean;
2272
+ materialType?: string;
2273
+ estimatedLayerCount?: number;
2274
+ };
1217
2275
  /** Original file format unit detected from metadata or inferred from scale */
1218
2276
  originalUnit?: string;
1219
2277
  /** File format version (e.g., 'STL Binary', 'OBJ v4', 'PLY 1.0') */
@@ -1231,7 +2289,11 @@ export interface ModelTechnicalMetadataCompletedMessage {
1231
2289
  /** Confidence level of analysis results (0.0 = uncertain, 1.0 = highly confident) */
1232
2290
  analysisConfidence?: number;
1233
2291
  /** Warnings or issues detected during analysis (structured for programmatic handling) */
1234
- analysisWarnings?: Array<Record<string, string | number | boolean>>;
2292
+ analysisWarnings?: Array<{
2293
+ code?: string;
2294
+ message?: string;
2295
+ severity?: string;
2296
+ }>;
1235
2297
  /** ISO 8601 timestamp when analysis was performed (e.g., '2025-11-19T14:35:22Z') */
1236
2298
  analyzedAt?: string;
1237
2299
  /** Detailed error message if status is FAILED */
@@ -1248,13 +2310,226 @@ export interface ModelTechnicalMetadataRequestMessage {
1248
2310
  /** User ID who owns the model */
1249
2311
  ownerId?: string;
1250
2312
  /** Location of the 3D model file (legacy - used for direct download if minioPath not provided) */
1251
- storageLocation?: Record<string, string | number | boolean>;
2313
+ storageLocation?: {
2314
+ storageConnectionId: string;
2315
+ path: string;
2316
+ };
1252
2317
  /** Path to model in MinIO (e.g., 'raw_models/{modelId}/original.glb'). If provided, file will be read from MinIO instead of downloading from storage provider. */
1253
2318
  minioPath?: string;
1254
2319
  /** ID of parent file-download job (for BullMQ dependency tracking). */
1255
2320
  parentJobId?: string;
1256
2321
  /** Optional analysis configuration parameters */
1257
- analysisOptions?: Record<string, string | number | boolean>;
2322
+ analysisOptions?: {
2323
+ detailedAnalysis?: boolean;
2324
+ estimatePrintMetrics?: boolean;
2325
+ skipCache?: boolean;
2326
+ };
2327
+ }
2328
+ /**
2329
+ * Request FDM slicing simulation via OrcaSlicer (preferred) or heuristic fallback. Accepts OrcaSlicer-compatible printer/process/filament JSON profiles.
2330
+ */
2331
+ export interface SlicingFdmRequestMessage {
2332
+ /** UUID of the model */
2333
+ modelId?: string;
2334
+ /** UUID or path of the storage item to download the STL/3MF */
2335
+ storageItemId?: string;
2336
+ /** UUID of the user's slicer profile from the database */
2337
+ profileId?: string;
2338
+ /** Human-readable profile name (e.g. 'My Bambu X1C - PLA Fine') */
2339
+ profileName?: string;
2340
+ /** OrcaSlicer printer profile JSON: nozzle_diameter, bed_shape, max speeds, acceleration, retraction */
2341
+ printerProfile?: Record<string, unknown>;
2342
+ /** OrcaSlicer process profile JSON: layer_height, sparse_infill_density, wall_loops, speeds, support settings */
2343
+ processProfile?: Record<string, unknown>;
2344
+ /** OrcaSlicer filament profile JSON: filament_type, filament_density, temperature, flow_ratio, retraction */
2345
+ filamentProfile?: Record<string, unknown>;
2346
+ /** Override: layer height in mm (takes precedence over processProfile) */
2347
+ layerHeight?: number;
2348
+ /** Override: infill percentage (0-100) */
2349
+ infillPercentage?: number;
2350
+ /** Override: nozzle diameter in mm */
2351
+ nozzleDiameter?: number;
2352
+ /** Override: outer wall print speed in mm/s */
2353
+ printSpeed?: number;
2354
+ /** Override: number of wall loops / perimeters */
2355
+ wallCount?: number;
2356
+ /** Override: generate support structures */
2357
+ supportEnabled?: boolean;
2358
+ /** Override: filament density in g/cm³ (default: 1.24 PLA) */
2359
+ materialDensity?: number;
2360
+ /** URL to POST the slicing result back to */
2361
+ webhookUrl?: string;
2362
+ }
2363
+ /**
2364
+ * Result of FDM slicing simulation from OrcaSlicer (toolpath) or heuristic fallback. Contains exact physical metrics for cost calculation.
2365
+ */
2366
+ export interface SlicingFdmResultMessage {
2367
+ /** UUID of the model */
2368
+ modelId?: string;
2369
+ /** Status of the simulation */
2370
+ status?: string;
2371
+ /** Exact print time in hours (from toolpath analysis) */
2372
+ printTimeHours?: number;
2373
+ /** Total filament weight in grams (including supports) */
2374
+ materialWeightGrams?: number;
2375
+ /** Extruded material volume in cm³ */
2376
+ materialVolumeCm3?: number;
2377
+ /** Maximum Z height in mm */
2378
+ maxZHeightMM?: number;
2379
+ /** Support structure filament weight in grams */
2380
+ supportMaterialWeightGrams?: number;
2381
+ /** Total number of layers */
2382
+ layerCount?: number;
2383
+ /** Total filament extrusion length in mm */
2384
+ totalExtrusionLengthMm?: number;
2385
+ /** Engine that produced the result */
2386
+ slicingMethod?: string;
2387
+ /** Version of the slicer engine used */
2388
+ slicerVersion?: string;
2389
+ /** Name or ID of the slicer profile used */
2390
+ profileUsed?: string;
2391
+ /** Error code if simulation failed */
2392
+ errorCode?: string;
2393
+ /** Error message if simulation failed */
2394
+ errorMessage?: string;
2395
+ }
2396
+ /**
2397
+ * DEPRECATED: Use slicing-fdm-request or slicing-sla-request instead. Unified contract kept for backward compatibility only.
2398
+ */
2399
+ export interface SlicingSimulationRequestMessage {
2400
+ /** UUID of the model */
2401
+ modelId?: string;
2402
+ /** UUID or path of the storage item to download the STL/3MF */
2403
+ storageItemId?: string;
2404
+ /** Printing technology: FDM, SLA, MSLA, SLS */
2405
+ technology?: string;
2406
+ /** Complete slicer profile with user settings. For FDM: OrcaSlicer-compatible JSON profiles. For SLA: exposure/lift parameters. */
2407
+ slicerProfile?: {
2408
+ profileId?: string;
2409
+ profileName?: string;
2410
+ printerProfile?: Record<string, unknown>;
2411
+ processProfile?: Record<string, unknown>;
2412
+ filamentProfile?: Record<string, unknown>;
2413
+ slaProfile?: Record<string, unknown>;
2414
+ layerHeight?: number;
2415
+ infillPercentage?: number;
2416
+ materialDensity?: number;
2417
+ nozzleDiameter?: number;
2418
+ printSpeed?: number;
2419
+ supportEnabled?: boolean;
2420
+ wallCount?: number;
2421
+ };
2422
+ /** DEPRECATED: Legacy simple config format. Use slicerProfile instead. */
2423
+ slicerConfig?: {
2424
+ layerHeight?: number;
2425
+ infill?: number;
2426
+ materialDensity?: number;
2427
+ };
2428
+ /** DEPRECATED: UUID of the slicer profile. Use slicerProfile.profileId instead. */
2429
+ slicerProfileId?: string;
2430
+ /** URL to POST the slicing result back to */
2431
+ webhookUrl?: string;
2432
+ }
2433
+ /**
2434
+ * DEPRECATED: Use slicing-fdm-result or slicing-sla-result instead. Unified contract kept for backward compatibility only.
2435
+ */
2436
+ export interface SlicingSimulationResultMessage {
2437
+ /** UUID of the model */
2438
+ modelId?: string;
2439
+ /** Status of the simulation */
2440
+ status?: string;
2441
+ /** Exact print time in hours (from toolpath or cross-sectional analysis) */
2442
+ printTimeHours?: number;
2443
+ /** Total material weight in grams (filament or resin, including supports) */
2444
+ materialWeightGrams?: number;
2445
+ /** Material volume in cm³ */
2446
+ materialVolumeCm3?: number;
2447
+ /** Maximum Z height in mm */
2448
+ maxZHeightMM?: number;
2449
+ /** Support structure material weight in grams */
2450
+ supportMaterialWeightGrams?: number;
2451
+ /** Total number of layers */
2452
+ layerCount?: number;
2453
+ /** Total filament extrusion length in mm (FDM only) */
2454
+ totalExtrusionLengthMm?: number;
2455
+ /** Engine that produced the result: orcaslicer_toolpath, pyslm_cross_section, heuristic_volumetric */
2456
+ slicingMethod?: string;
2457
+ /** Version of the slicer engine used */
2458
+ slicerVersion?: string;
2459
+ /** Name or ID of the slicer profile used */
2460
+ profileUsed?: string;
2461
+ /** Error code if simulation failed */
2462
+ errorCode?: string;
2463
+ /** Error message if simulation failed */
2464
+ errorMessage?: string;
2465
+ }
2466
+ /**
2467
+ * Request SLA/MSLA slicing simulation via PySLM cross-sectional analysis. Accepts resin printer profile with exposure, lift, and layer parameters.
2468
+ */
2469
+ export interface SlicingSlaRequestMessage {
2470
+ /** UUID of the model */
2471
+ modelId?: string;
2472
+ /** UUID or path of the storage item to download the STL/3MF */
2473
+ storageItemId?: string;
2474
+ /** SLA or MSLA */
2475
+ technology?: string;
2476
+ /** UUID of the user's slicer profile from the database */
2477
+ profileId?: string;
2478
+ /** Human-readable profile name (e.g. 'Elegoo Mars 3 - Standard Grey') */
2479
+ profileName?: string;
2480
+ /** Layer height in mm (default: 0.05) */
2481
+ layerHeight?: number;
2482
+ /** Normal layer UV exposure time in seconds (default: 2.5) */
2483
+ exposureTime?: number;
2484
+ /** Bottom/burn-in layer exposure time in seconds (default: 30) */
2485
+ bottomExposureTime?: number;
2486
+ /** Number of bottom/burn-in layers (default: 5) */
2487
+ bottomLayers?: number;
2488
+ /** Platform lift height in mm between layers (default: 5.0) */
2489
+ liftHeight?: number;
2490
+ /** Platform lift speed in mm/min (default: 60) */
2491
+ liftSpeed?: number;
2492
+ /** Platform retract speed in mm/min (default: 150) */
2493
+ retractSpeed?: number;
2494
+ /** Resin density in g/cm³ (default: 1.1) */
2495
+ resinDensity?: number;
2496
+ /** Generate support structures (default: true for SLA) */
2497
+ supportEnabled?: boolean;
2498
+ /** URL to POST the slicing result back to */
2499
+ webhookUrl?: string;
2500
+ }
2501
+ /**
2502
+ * Result of SLA/MSLA slicing simulation from PySLM cross-sectional analysis. Contains exact resin usage and print time metrics.
2503
+ */
2504
+ export interface SlicingSlaResultMessage {
2505
+ /** UUID of the model */
2506
+ modelId?: string;
2507
+ /** Status of the simulation */
2508
+ status?: string;
2509
+ /** Exact print time in hours (from cross-sectional analysis) */
2510
+ printTimeHours?: number;
2511
+ /** Total resin weight in grams (including supports) */
2512
+ materialWeightGrams?: number;
2513
+ /** Cured resin volume in cm³ (from cross-sectional area integration) */
2514
+ materialVolumeCm3?: number;
2515
+ /** Maximum Z height in mm */
2516
+ maxZHeightMM?: number;
2517
+ /** Support structure resin weight in grams */
2518
+ supportMaterialWeightGrams?: number;
2519
+ /** Total number of layers */
2520
+ layerCount?: number;
2521
+ /** Maximum cross-sectional area in mm² (affects MSLA peel force) */
2522
+ maxCrossSectionAreaMm2?: number;
2523
+ /** Engine that produced the result */
2524
+ slicingMethod?: string;
2525
+ /** Version of PySLM / trimesh used */
2526
+ slicerVersion?: string;
2527
+ /** Name or ID of the slicer profile used */
2528
+ profileUsed?: string;
2529
+ /** Error code if simulation failed */
2530
+ errorCode?: string;
2531
+ /** Error message if simulation failed */
2532
+ errorMessage?: string;
1258
2533
  }
1259
2534
  /**
1260
2535
  * Handles thumbnail generation completed.
@@ -1269,13 +2544,23 @@ export interface ThumbnailGenerationCompletedMessage {
1269
2544
  /** The path to the generated thumbnail. */
1270
2545
  thumbnailPath?: string;
1271
2546
  /** Array of 360° thumbnail view paths (16 angles) for vision-based analysis. */
1272
- thumbnail360Views?: Array<Record<string, string | number | boolean>>;
2547
+ thumbnail360Views?: Array<{
2548
+ angle_index?: number;
2549
+ index?: number;
2550
+ storage_path?: string;
2551
+ url?: string;
2552
+ }>;
1273
2553
  /** The path to the generated GLTF/GLB 3D preview file. */
1274
2554
  gltfPreviewPath?: string;
2555
+ /** The path to the generated animated MP4 preview file. */
2556
+ animatedPreviewPath?: string;
1275
2557
  /** An error message if the thumbnail generation failed. */
1276
2558
  errorMessage?: string;
1277
2559
  /** The storage location of the model. */
1278
- storageLocation?: Record<string, string | number | boolean>;
2560
+ storageLocation?: {
2561
+ storageConnectionId: string;
2562
+ path: string;
2563
+ };
1279
2564
  }
1280
2565
  /**
1281
2566
  * Handles thumbnail generation requests with customization options. Supports both storage provider downloads and MinIO-cached files.
@@ -1286,7 +2571,10 @@ export interface ThumbnailGenerationRequestMessage {
1286
2571
  /** The identifier of the user who owns the entity. */
1287
2572
  ownerId?: string;
1288
2573
  /** The storage location of the model (legacy - used for direct download if minioPath not provided). */
1289
- storageLocation?: Record<string, string | number | boolean>;
2574
+ storageLocation?: {
2575
+ storageConnectionId: string;
2576
+ path: string;
2577
+ };
1290
2578
  /** Path to model in MinIO (e.g., 'raw_models/{modelId}/original.glb'). If provided, file will be read from MinIO instead of downloading from storage provider. */
1291
2579
  minioPath?: string;
1292
2580
  /** The type of preview to generate, e.g., 'default', 'static', 'glb'. */
@@ -1296,7 +2584,24 @@ export interface ThumbnailGenerationRequestMessage {
1296
2584
  /** ID of parent file-download job (for BullMQ dependency tracking). */
1297
2585
  parentJobId?: string;
1298
2586
  /** User-defined customizations for the thumbnail. */
1299
- customization?: Record<string, string | number | boolean>;
2587
+ customization?: {
2588
+ texture?: {
2589
+ storageConnectionId?: string;
2590
+ path?: string;
2591
+ };
2592
+ background?: {
2593
+ storageConnectionId?: string;
2594
+ path?: string;
2595
+ color?: string;
2596
+ };
2597
+ watermark?: {
2598
+ storageConnectionId?: string;
2599
+ path?: string;
2600
+ text?: string;
2601
+ position?: string;
2602
+ opacity?: number;
2603
+ };
2604
+ };
1300
2605
  }
1301
2606
  /**
1302
2607
  * User engagement and onboarding tracking events for analytics and behavioral insights.
@@ -1337,7 +2642,21 @@ export interface UserEngagementEventMessage {
1337
2642
  /** Request ID for correlation with logs */
1338
2643
  requestId?: string;
1339
2644
  /** Additional context about the action */
1340
- actionDetails?: Record<string, string | number | boolean>;
2645
+ actionDetails?: {
2646
+ onboardingStep?: string;
2647
+ modelId?: string;
2648
+ modelStatus?: string;
2649
+ modelCount?: number;
2650
+ marketplace?: string;
2651
+ marketplaceListingId?: string;
2652
+ marketplaceAction?: string;
2653
+ previousPlanTier?: string;
2654
+ newPlanTier?: string;
2655
+ featureName?: string;
2656
+ featureCategory?: string;
2657
+ storageProvider?: string;
2658
+ settingChanged?: string;
2659
+ };
1341
2660
  /** Where the action originated */
1342
2661
  source?: string;
1343
2662
  /** HTTP method used */
@@ -1345,7 +2664,7 @@ export interface UserEngagementEventMessage {
1345
2664
  /** API endpoint path */
1346
2665
  httpUrl?: string;
1347
2666
  /** HTTP response status code */
1348
- httpStatusCode?: string | number | boolean;
2667
+ httpStatusCode?: number;
1349
2668
  /** Action duration in milliseconds */
1350
2669
  durationMs?: number;
1351
2670
  /** A/B test or experiment ID */
@@ -1355,7 +2674,12 @@ export interface UserEngagementEventMessage {
1355
2674
  /** Deployment environment */
1356
2675
  environment?: string;
1357
2676
  /** Client/browser information (anonymized) */
1358
- clientInfo?: Record<string, string | number | boolean>;
2677
+ clientInfo?: {
2678
+ userAgent?: string;
2679
+ platform?: string;
2680
+ browser?: string;
2681
+ browserVersion?: string;
2682
+ };
1359
2683
  }
1360
2684
  /**
1361
2685
  * Analytics event emitted by workers for tracking processing metrics, user behavior,
@@ -1389,9 +2713,13 @@ export interface WorkerAnalyticsEventMessage {
1389
2713
  /** Error message if status is failure */
1390
2714
  errorMessage?: string;
1391
2715
  /** Processing time metrics in milliseconds */
1392
- timing?: Record<string, string | number | boolean>;
2716
+ timing?: {
2717
+ queueWaitMs?: number;
2718
+ processingMs?: number;
2719
+ stages?: Record<string, number>;
2720
+ };
1393
2721
  /** Worker-specific metrics. Structure varies by eventType. */
1394
- metrics?: Record<string, string | number | boolean>;
2722
+ metrics?: Record<string, unknown>;
1395
2723
  }
1396
2724
  /**
1397
2725
  * Enriched metrics event for detailed worker monitoring, cost tracking,
@@ -1432,15 +2760,62 @@ export interface WorkerMetricsEnrichedEventMessage {
1432
2760
  /** Storage item ID (for file operations) */
1433
2761
  storageItemId?: string;
1434
2762
  /** Comprehensive timing breakdown */
1435
- timing?: Record<string, string | number | boolean>;
2763
+ timing?: {
2764
+ queueWaitMs?: number;
2765
+ processingMs?: number;
2766
+ stages?: Record<string, number>;
2767
+ };
1436
2768
  /** LLM token usage and cost breakdown */
1437
- llmUsage?: Record<string, string | number | boolean>;
2769
+ llmUsage?: {
2770
+ provider?: string;
2771
+ model?: string;
2772
+ tokensPrompt?: number;
2773
+ tokensCompletion?: number;
2774
+ tokensTotal?: number;
2775
+ costPerPromptToken?: number;
2776
+ costPerCompletionToken?: number;
2777
+ totalCostUsd?: number;
2778
+ cacheHit?: boolean;
2779
+ retries?: number;
2780
+ fallbackUsed?: boolean;
2781
+ modelLatencyMs?: number;
2782
+ };
1438
2783
  /** System resource consumption during job */
1439
- resources?: Record<string, string | number | boolean>;
2784
+ resources?: {
2785
+ cpu?: {
2786
+ peakPercent?: number;
2787
+ avgPercent?: number;
2788
+ systemTimeMs?: number;
2789
+ userTimeMs?: number;
2790
+ };
2791
+ memory?: {
2792
+ peakMb?: number;
2793
+ avgMb?: number;
2794
+ startMb?: number;
2795
+ endMb?: number;
2796
+ leakDetected?: boolean;
2797
+ };
2798
+ disk?: {
2799
+ bytesRead?: number;
2800
+ bytesWritten?: number;
2801
+ opsRead?: number;
2802
+ opsWrite?: number;
2803
+ };
2804
+ network?: {
2805
+ bytesReceived?: number;
2806
+ bytesSent?: number;
2807
+ apiCallsCount?: number;
2808
+ avgLatencyMs?: number;
2809
+ };
2810
+ };
1440
2811
  /** Worker-specific metrics (varies by worker type) */
1441
- workerMetrics?: Record<string, string | number | boolean>;
2812
+ workerMetrics?: Record<string, unknown>;
1442
2813
  /** Error details if status is failure */
1443
- error?: Record<string, string | number | boolean>;
2814
+ error?: {
2815
+ code?: string;
2816
+ message?: string;
2817
+ category?: string;
2818
+ };
1444
2819
  /** Deployment environment */
1445
2820
  environment?: string;
1446
2821
  /** Cloud region/datacenter */