@blueharford/scrypted-spatial-awareness 0.6.23 → 0.6.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/out/plugin.zip CHANGED
Binary file
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@blueharford/scrypted-spatial-awareness",
3
- "version": "0.6.23",
3
+ "version": "0.6.24",
4
4
  "description": "Cross-camera object tracking for Scrypted NVR with spatial awareness",
5
5
  "author": "Joshua Seidel <blueharford>",
6
6
  "license": "Apache-2.0",
@@ -155,6 +155,7 @@ export class AlertManager {
155
155
 
156
156
  /**
157
157
  * Get notification title based on alert type
158
+ * For movement alerts with LLM descriptions, use the smart description as title
158
159
  */
159
160
  private getNotificationTitle(alert: Alert): string {
160
161
  const prefix = alert.severity === 'critical' ? '🚨 ' :
@@ -167,11 +168,26 @@ export class AlertManager {
167
168
 
168
169
  switch (alert.type) {
169
170
  case 'property_entry':
171
+ // Legacy - use simple title
170
172
  return `${prefix}${objectType} Arrived`;
171
173
  case 'property_exit':
174
+ // Legacy - use simple title
172
175
  return `${prefix}${objectType} Left`;
173
176
  case 'movement':
174
- // Include destination in title
177
+ // For smart activity alerts, use the LLM description as title if available
178
+ // This gives us rich context like "Person walking toward front door"
179
+ if (alert.details.objectLabel && alert.details.usedLlm) {
180
+ // Truncate to reasonable title length (first sentence or 60 chars)
181
+ let smartTitle = alert.details.objectLabel;
182
+ const firstPeriod = smartTitle.indexOf('.');
183
+ if (firstPeriod > 0 && firstPeriod < 60) {
184
+ smartTitle = smartTitle.substring(0, firstPeriod);
185
+ } else if (smartTitle.length > 60) {
186
+ smartTitle = smartTitle.substring(0, 57) + '...';
187
+ }
188
+ return `${prefix}${smartTitle}`;
189
+ }
190
+ // Fallback: include destination in title
175
191
  const dest = alert.details.toCameraName || 'area';
176
192
  return `${prefix}${objectType} → ${dest}`;
177
193
  case 'unusual_path':
@@ -579,32 +579,19 @@ export class TrackingEngine {
579
579
  this.console.log(`[Entry Alert] Got description: "${spatialResult.description.substring(0, 60)}...", usedLlm=${spatialResult.usedLlm}`);
580
580
  }
581
581
 
582
- if (isEntryPoint) {
583
- // Entry point - generate property entry alert
584
- await this.alertManager.checkAndAlert('property_entry', tracked, {
585
- cameraId: sighting.cameraId,
586
- cameraName: sighting.cameraName,
587
- objectClass: sighting.detection.className,
588
- objectLabel: spatialResult.description,
589
- detectionId: sighting.detectionId,
590
- involvedLandmarks: spatialResult.involvedLandmarks?.map(l => l.name),
591
- usedLlm: spatialResult.usedLlm,
592
- });
593
- } else {
594
- // Non-entry point - still alert about activity using movement alert type
595
- // This notifies about any activity around the property using topology context
596
- await this.alertManager.checkAndAlert('movement', tracked, {
597
- cameraId: sighting.cameraId,
598
- cameraName: sighting.cameraName,
599
- toCameraId: sighting.cameraId,
600
- toCameraName: sighting.cameraName,
601
- objectClass: sighting.detection.className,
602
- objectLabel: spatialResult.description, // Use spatial reasoning description (topology-based)
603
- detectionId: sighting.detectionId,
604
- involvedLandmarks: spatialResult.involvedLandmarks?.map(l => l.name),
605
- usedLlm: spatialResult.usedLlm,
606
- });
607
- }
582
+ // Always use movement alert type for smart notifications with LLM descriptions
583
+ // The property_entry/property_exit types are legacy and disabled by default
584
+ await this.alertManager.checkAndAlert('movement', tracked, {
585
+ cameraId: sighting.cameraId,
586
+ cameraName: sighting.cameraName,
587
+ toCameraId: sighting.cameraId,
588
+ toCameraName: sighting.cameraName,
589
+ objectClass: sighting.detection.className,
590
+ objectLabel: spatialResult.description, // Smart LLM-generated description
591
+ detectionId: sighting.detectionId,
592
+ involvedLandmarks: spatialResult.involvedLandmarks?.map(l => l.name),
593
+ usedLlm: spatialResult.usedLlm,
594
+ });
608
595
 
609
596
  this.recordAlertTime(globalId);
610
597
  }, this.config.loiteringThreshold);
@@ -731,9 +718,12 @@ export class TrackingEngine {
731
718
  this.console.log(`[Exit Alert] Got description: "${spatialResult.description.substring(0, 60)}...", usedLlm=${spatialResult.usedLlm}`);
732
719
  }
733
720
 
734
- await this.alertManager.checkAndAlert('property_exit', current, {
721
+ // Use movement alert for exit too - smart notifications with LLM descriptions
722
+ await this.alertManager.checkAndAlert('movement', current, {
735
723
  cameraId: sighting.cameraId,
736
724
  cameraName: sighting.cameraName,
725
+ toCameraId: sighting.cameraId,
726
+ toCameraName: sighting.cameraName,
737
727
  objectClass: current.className,
738
728
  objectLabel: spatialResult.description,
739
729
  involvedLandmarks: spatialResult.involvedLandmarks?.map(l => l.name),
@@ -128,8 +128,8 @@ export function createDefaultRules(): AlertRule[] {
128
128
  return [
129
129
  {
130
130
  id: 'property-entry',
131
- name: 'Property Entry',
132
- enabled: true,
131
+ name: 'Property Entry (Legacy)',
132
+ enabled: false, // Disabled - use movement alerts with LLM descriptions instead
133
133
  type: 'property_entry',
134
134
  conditions: [],
135
135
  severity: 'info',
@@ -138,8 +138,8 @@ export function createDefaultRules(): AlertRule[] {
138
138
  },
139
139
  {
140
140
  id: 'property-exit',
141
- name: 'Property Exit',
142
- enabled: true,
141
+ name: 'Property Exit (Legacy)',
142
+ enabled: false, // Disabled - use movement alerts with LLM descriptions instead
143
143
  type: 'property_exit',
144
144
  conditions: [],
145
145
  severity: 'info',
@@ -148,7 +148,7 @@ export function createDefaultRules(): AlertRule[] {
148
148
  },
149
149
  {
150
150
  id: 'movement',
151
- name: 'Movement Between Cameras',
151
+ name: 'Smart Activity Alerts',
152
152
  enabled: true,
153
153
  type: 'movement',
154
154
  conditions: [],