@blueharford/scrypted-spatial-awareness 0.6.30 → 0.6.31

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/plugin.zip CHANGED
Binary file
@@ -34457,6 +34457,12 @@ class AlertManager {
34457
34457
  const notifierIds = rule.notifiers.length > 0
34458
34458
  ? rule.notifiers
34459
34459
  : this.getDefaultNotifiers();
34460
+ // Debug: log which notifiers we're using
34461
+ this.console.log(`[Notification] Rule ${rule.id} has ${rule.notifiers.length} notifiers, using ${notifierIds.length} notifier(s): ${notifierIds.join(', ') || 'NONE'}`);
34462
+ if (notifierIds.length === 0) {
34463
+ this.console.warn(`[Notification] No notifiers configured! Configure a notifier in plugin settings.`);
34464
+ return;
34465
+ }
34460
34466
  // Try to get a thumbnail from the camera
34461
34467
  let mediaObject;
34462
34468
  const cameraId = alert.details.toCameraId || alert.details.cameraId;
@@ -34551,27 +34557,34 @@ class AlertManager {
34551
34557
  try {
34552
34558
  // Try new multiple notifiers setting first
34553
34559
  const notifiers = this.storage.getItem('defaultNotifiers');
34560
+ this.console.log(`[Notifiers] Raw storage value: ${notifiers}`);
34554
34561
  if (notifiers) {
34555
34562
  // Could be JSON array or comma-separated string
34556
34563
  try {
34557
34564
  const parsed = JSON.parse(notifiers);
34558
34565
  if (Array.isArray(parsed)) {
34566
+ this.console.log(`[Notifiers] Parsed JSON array: ${parsed.join(', ')}`);
34559
34567
  return parsed;
34560
34568
  }
34561
34569
  }
34562
34570
  catch {
34563
34571
  // Not JSON, might be comma-separated or single value
34564
34572
  if (notifiers.includes(',')) {
34565
- return notifiers.split(',').map(s => s.trim()).filter(Boolean);
34573
+ const result = notifiers.split(',').map(s => s.trim()).filter(Boolean);
34574
+ this.console.log(`[Notifiers] Parsed comma-separated: ${result.join(', ')}`);
34575
+ return result;
34566
34576
  }
34577
+ this.console.log(`[Notifiers] Single value: ${notifiers}`);
34567
34578
  return [notifiers];
34568
34579
  }
34569
34580
  }
34570
34581
  // Fallback to old single notifier setting
34571
34582
  const defaultNotifier = this.storage.getItem('defaultNotifier');
34583
+ this.console.log(`[Notifiers] Fallback single notifier: ${defaultNotifier || 'NONE'}`);
34572
34584
  return defaultNotifier ? [defaultNotifier] : [];
34573
34585
  }
34574
- catch {
34586
+ catch (e) {
34587
+ this.console.error(`[Notifiers] Error reading notifiers:`, e);
34575
34588
  return [];
34576
34589
  }
34577
34590
  }
@@ -35427,7 +35440,7 @@ class SpatialReasoningEngine {
35427
35440
  id: deviceId,
35428
35441
  name: device.name || deviceId,
35429
35442
  providerType: providerTypeEnum,
35430
- lastUsed: 0,
35443
+ lastUsed: Date.now() - 60000, // Initialize to 1 minute ago so all LLMs start equal
35431
35444
  errorCount: 0,
35432
35445
  });
35433
35446
  this.console.log(`[LLM] Using configured LLM: ${device.name}`);
@@ -35455,7 +35468,7 @@ class SpatialReasoningEngine {
35455
35468
  id,
35456
35469
  name: device.name || id,
35457
35470
  providerType: providerTypeEnum,
35458
- lastUsed: 0,
35471
+ lastUsed: Date.now() - 60000, // Initialize to 1 minute ago so all LLMs start equal
35459
35472
  errorCount: 0,
35460
35473
  });
35461
35474
  this.console.log(`[LLM] Auto-discovered: ${device.name}`);
@@ -37706,31 +37719,31 @@ class TrackingEngine {
37706
37719
  }
37707
37720
  /** Capture and cache a snapshot for a tracked object, and start LLM analysis immediately */
37708
37721
  async captureAndCacheSnapshot(globalId, cameraId, eventType = 'entry') {
37722
+ // Skip if we already have a recent snapshot for this object (within 5 seconds)
37723
+ const existingSnapshot = this.snapshotCache.get(globalId);
37724
+ if (existingSnapshot && eventType !== 'exit') {
37725
+ // For entry/movement, we can reuse existing snapshot
37726
+ // For exit, we want a fresh snapshot while they're still visible
37727
+ return;
37728
+ }
37709
37729
  try {
37710
37730
  const camera = systemManager.getDeviceById(cameraId);
37711
37731
  if (camera?.interfaces?.includes(sdk_1.ScryptedInterface.Camera)) {
37712
37732
  const mediaObject = await camera.takePicture();
37713
37733
  if (mediaObject) {
37714
37734
  this.snapshotCache.set(globalId, mediaObject);
37715
- this.console.log(`[Snapshot] Cached snapshot for ${globalId.slice(0, 8)} from ${cameraId}`);
37716
37735
  // Start LLM analysis immediately in parallel (don't await) - but respect rate limits
37717
37736
  const tracked = this.state.getObject(globalId);
37718
37737
  if (tracked && this.config.useLlmDescriptions && this.tryLlmCall()) {
37719
- this.console.log(`[LLM Prefetch] Starting ${eventType} analysis for ${globalId.slice(0, 8)}`);
37720
37738
  const descriptionPromise = eventType === 'exit'
37721
37739
  ? this.spatialReasoning.generateExitDescription(tracked, cameraId, mediaObject)
37722
37740
  : this.spatialReasoning.generateEntryDescription(tracked, cameraId, mediaObject);
37723
37741
  this.pendingDescriptions.set(globalId, descriptionPromise);
37724
- // Log when complete (for debugging)
37725
- descriptionPromise.then(result => {
37726
- this.console.log(`[LLM Prefetch] ${eventType} analysis ready for ${globalId.slice(0, 8)}: "${result.description.substring(0, 40)}..."`);
37727
- }).catch(e => {
37742
+ // Log when complete (but don't spam logs)
37743
+ descriptionPromise.catch(e => {
37728
37744
  this.console.warn(`[LLM Prefetch] Failed for ${globalId.slice(0, 8)}: ${e}`);
37729
37745
  });
37730
37746
  }
37731
- else if (tracked && this.config.useLlmDescriptions) {
37732
- this.console.log(`[LLM Prefetch] Skipped for ${globalId.slice(0, 8)} - rate limited`);
37733
- }
37734
37747
  }
37735
37748
  }
37736
37749
  }