@camstack/addon-advanced-notifier 1.1.25 → 1.1.26

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (3) hide show
  1. package/dist/addon.js +176 -12
  2. package/dist/addon.mjs +176 -12
  3. package/package.json +1 -1
package/dist/addon.js CHANGED
@@ -3,7 +3,7 @@ Object.defineProperties(exports, {
3
3
  [Symbol.toStringTag]: { value: "Module" }
4
4
  });
5
5
  let node_crypto = require("node:crypto");
6
- //#region ../types/dist/event-category-CFZs3jI4.mjs
6
+ //#region ../types/dist/event-category-H4AVePnn.mjs
7
7
  var EventCategory = /* @__PURE__ */ function(EventCategory) {
8
8
  EventCategory["SystemBoot"] = "system.boot";
9
9
  EventCategory["SystemAddonsReady"] = "system.addons-ready";
@@ -153,6 +153,9 @@ var EventCategory = /* @__PURE__ */ function(EventCategory) {
153
153
  EventCategory["RecordingSegmentWritten"] = "recording.segment.written";
154
154
  EventCategory["RecordingPolicyFallback"] = "recording.policy.fallback";
155
155
  EventCategory["RecordingRetentionCompleted"] = "recording.retention.completed";
156
+ /** Runner-sampled scrub thumbnail (~1/5 s/camera). Telemetry (D8): a lost
157
+ * thumb is a scrub gap the recorder's keyframe backfill covers. */
158
+ EventCategory["RecordingThumbSampled"] = "recording.thumb-sampled";
156
159
  EventCategory["DetectionEvent"] = "detection.event";
157
160
  EventCategory["SessionTrackNew"] = "session.track.new";
158
161
  EventCategory["SessionTrackExpired"] = "session.track.expired";
@@ -9831,7 +9834,7 @@ object({
9831
9834
  deviceId: number(),
9832
9835
  timestamp: number()
9833
9836
  });
9834
- DeviceType.Button;
9837
+ DeviceType.Button, DeviceType.Camera;
9835
9838
  /**
9836
9839
  * Enum-state sensor — a string value picked from a finite option set.
9837
9840
  * Drives HA `sensor` entries with `state_class: enum` (HVAC action
@@ -14213,6 +14216,14 @@ var ConfigEntrySchema = object({
14213
14216
  value: unknown(),
14214
14217
  description: string().optional()
14215
14218
  });
14219
+ var DeviceLinkModeSchema = _enum(["auto", "manual"]);
14220
+ /** One resolved linked device — the compact projection consumers need. */
14221
+ var LinkedDeviceSchema = object({
14222
+ deviceId: number(),
14223
+ name: string(),
14224
+ location: string().nullable(),
14225
+ features: array(string())
14226
+ });
14216
14227
  var SavedDeviceRowSchema = object({
14217
14228
  /** Numeric id reserved at allocateDeviceId time. */
14218
14229
  id: number(),
@@ -14434,7 +14445,10 @@ method(object({
14434
14445
  }), _void(), {
14435
14446
  kind: "mutation",
14436
14447
  auth: "admin"
14437
- }), method(object({ addonId: string() }), array(SavedDeviceRowSchema)), method(object({ addonId: string().optional() }), array(DeviceInfoSchema)), method(object({ deviceId: number() }), DeviceInfoSchema.nullable()), method(object({ parentDeviceId: number() }), array(DeviceInfoSchema)), method(object({ deviceId: number() }), array(StreamSourceEntrySchema$1)), method(object({ deviceId: number() }), array(ConfigEntrySchema)), method(object({ deviceId: number() }), ConfigUISchemaOutput), method(object({
14448
+ }), method(object({ addonId: string() }), array(SavedDeviceRowSchema)), method(object({ addonId: string().optional() }), array(DeviceInfoSchema)), method(object({ deviceId: number() }), DeviceInfoSchema.nullable()), method(object({ parentDeviceId: number() }), array(DeviceInfoSchema)), method(object({ deviceId: number() }), object({
14449
+ mode: DeviceLinkModeSchema,
14450
+ devices: array(LinkedDeviceSchema)
14451
+ })), method(object({ deviceId: number() }), array(StreamSourceEntrySchema$1)), method(object({ deviceId: number() }), array(ConfigEntrySchema)), method(object({ deviceId: number() }), ConfigUISchemaOutput), method(object({
14438
14452
  deviceId: number(),
14439
14453
  values: record(string(), unknown())
14440
14454
  }), object({ success: literal(true) }), {
@@ -15717,6 +15731,61 @@ var EventKindSchema = _enum([
15717
15731
  "object",
15718
15732
  "audio"
15719
15733
  ]);
15734
+ /**
15735
+ * Spatial filter for `listTracks` — the rect + polygon variants of the shared
15736
+ * MaskShape vocabulary (see `mask-shape.ts`). Coordinates are NORMALIZED 0..1
15737
+ * of the camera frame (top-left origin), matching the drawing-plane editor.
15738
+ */
15739
+ var TrackZoneFilterSchema = discriminatedUnion("kind", [MaskRectShapeSchema, MaskPolygonShapeSchema]);
15740
+ /** Closed icon vocabulary so clients render a known glyph per kind. */
15741
+ var EventKindIconSchema = _enum([
15742
+ "motion",
15743
+ "audio",
15744
+ "person",
15745
+ "vehicle",
15746
+ "animal",
15747
+ "door",
15748
+ "pir",
15749
+ "smoke",
15750
+ "water",
15751
+ "button",
15752
+ "generic"
15753
+ ]);
15754
+ var EventKindCategorySchema = _enum([
15755
+ "motion",
15756
+ "audio",
15757
+ "detection",
15758
+ "sensor",
15759
+ "custom"
15760
+ ]);
15761
+ var EventKindDescriptorSchema = object({
15762
+ /** Stable kind id (e.g. 'motion', 'person', 'contact'). */
15763
+ kind: string(),
15764
+ label: string(),
15765
+ /** Hex color for timeline/legend rendering. */
15766
+ color: string(),
15767
+ icon: EventKindIconSchema,
15768
+ category: EventKindCategorySchema,
15769
+ /** Which cap + device contributes this kind. For built-ins the camera
15770
+ * itself; for sensor kinds the LINKED source device. */
15771
+ source: object({
15772
+ capName: string(),
15773
+ deviceId: number()
15774
+ })
15775
+ });
15776
+ var SensorEventSchema = object({
15777
+ id: string(),
15778
+ /** The CAMERA the event is attributed to (a sensor linked to N cameras
15779
+ * yields N rows, one per camera). */
15780
+ deviceId: number(),
15781
+ /** The linked sensor device whose state changed. */
15782
+ sourceDeviceId: number(),
15783
+ /** Event kind id — matches an `EventKindDescriptor.kind`. */
15784
+ kind: string(),
15785
+ /** Snapshot of the sensor cap's runtime-state slice at the change. */
15786
+ value: record(string(), unknown()).nullable(),
15787
+ timestamp: number()
15788
+ });
15720
15789
  var TrackPositionSchema = object({
15721
15790
  x: number(),
15722
15791
  y: number(),
@@ -15730,6 +15799,30 @@ var TrackSnapshotSchema = object({
15730
15799
  mediaKey: string()
15731
15800
  });
15732
15801
  /**
15802
+ * Normalized 0..1 trajectory envelope (min/max over every position bbox,
15803
+ * divided by the track's detection-frame dims), computed at persist time.
15804
+ * Absent when the frame dims were unknown when the track was persisted
15805
+ * (legacy rows / dims-less sources) and on active (in-RAM) tracks.
15806
+ */
15807
+ var TrackEnvelopeSchema = object({
15808
+ minX: number(),
15809
+ minY: number(),
15810
+ maxX: number(),
15811
+ maxY: number()
15812
+ });
15813
+ /**
15814
+ * Row projection for track list queries. `full` (default) returns the
15815
+ * complete Track including the frame-rate `positions[]` history and the
15816
+ * `snapshots[]` references — megabytes across a page of tracks. `slim`
15817
+ * keeps every scalar the list surfaces actually render (ids, class(es),
15818
+ * label / audioLabels / importance enrichment, firstSeen/lastSeen, state,
15819
+ * zonesVisited, bestEventId, envelope) and returns `positions` /
15820
+ * `snapshots` as EMPTY arrays — detail views re-fetch the full row via
15821
+ * `getTrack`. Mirrors the event-store `projection` convention
15822
+ * (`getObjectEvents` et al.).
15823
+ */
15824
+ var TrackProjectionSchema = _enum(["full", "slim"]);
15825
+ /**
15733
15826
  * One audio-classification label heard on the track's camera while the
15734
15827
  * track was alive, aggregated per label. An "episode" is one persisted
15735
15828
  * audio event (the confident-classification path: score ≥ the device's
@@ -15780,7 +15873,11 @@ var TrackSchema = object({
15780
15873
  /** Audio-classification labels heard on the camera during the track's
15781
15874
  * life (score ≥ device `classificationMinScore`), aggregated per label.
15782
15875
  * Absent on legacy rows / tracks with no confident audio. */
15783
- audioLabels: array(TrackAudioLabelSchema).readonly().optional()
15876
+ audioLabels: array(TrackAudioLabelSchema).readonly().optional(),
15877
+ /** Normalized 0..1 trajectory envelope (see {@link TrackEnvelopeSchema}).
15878
+ * Populated from the persisted envelope columns on historical reads;
15879
+ * absent on legacy rows, dims-less tracks and active (in-RAM) tracks. */
15880
+ envelope: TrackEnvelopeSchema.optional()
15784
15881
  });
15785
15882
  var BaseEventFields = {
15786
15883
  id: string(),
@@ -15890,11 +15987,13 @@ var MediaFileSchema = object({
15890
15987
  sizeBytes: number(),
15891
15988
  timestamp: number()
15892
15989
  });
15990
+ var DEFAULT_EVENT_QUERY_LIMIT = 1e3;
15991
+ var MAX_EVENT_QUERY_LIMIT = 5e3;
15893
15992
  var DeviceEventQueryInput = object({
15894
15993
  deviceId: number(),
15895
15994
  since: number().optional(),
15896
15995
  until: number().optional(),
15897
- limit: number().int().min(1).max(5e3).default(1e3),
15996
+ limit: number().int().min(1).max(MAX_EVENT_QUERY_LIMIT).default(DEFAULT_EVENT_QUERY_LIMIT),
15898
15997
  /** `slim` drops heavy JSON fields (regions/bbox/zones) and carries an
15899
15998
  * optional `mediaUrl` (populated by B5). `full` (default) keeps today's
15900
15999
  * exact behaviour. Callers may omit this field — the store defaults to
@@ -15902,6 +16001,27 @@ var DeviceEventQueryInput = object({
15902
16001
  projection: _enum(["full", "slim"]).optional()
15903
16002
  });
15904
16003
  var ObjectEventQueryInput = DeviceEventQueryInput.extend({ classFilter: string().optional() });
16004
+ var RecentTracksQueryInput = object({
16005
+ /** Devices to merge. An empty array yields `{ tracks: [], nextCursor: null }`. */
16006
+ deviceIds: array(number()),
16007
+ /** Window lower bound on `lastSeen` (inclusive). */
16008
+ since: number().optional(),
16009
+ /** Window upper bound on `lastSeen` (inclusive). */
16010
+ until: number().optional(),
16011
+ /** Page size. Default 200, max 1000. */
16012
+ limit: number().int().min(1).max(1e3).default(200),
16013
+ /** Opaque continuation cursor from a previous page's `nextCursor`.
16014
+ * Encodes the (lastSeen, trackId) sort position — treat as opaque. */
16015
+ cursor: string().optional(),
16016
+ /** See {@link TrackProjectionSchema}. Default `full`. */
16017
+ projection: TrackProjectionSchema.optional()
16018
+ });
16019
+ var RecentTracksPageSchema = object({
16020
+ /** Merged page, ordered by (`lastSeen` DESC, `trackId` DESC). */
16021
+ tracks: array(TrackSchema).readonly(),
16022
+ /** Cursor for the next page, or null when this page is the last. */
16023
+ nextCursor: string().nullable()
16024
+ });
15905
16025
  var KeyEventQueryInput = object({
15906
16026
  deviceId: number(),
15907
16027
  /** Window lower bound (track firstSeen ≥ since). */
@@ -15984,11 +16104,25 @@ DeviceType.Camera, method(object({ deviceId: number() }), array(TrackSchema).rea
15984
16104
  deviceId: number(),
15985
16105
  since: number().optional(),
15986
16106
  until: number().optional(),
15987
- limit: number().optional()
15988
- }), array(TrackSchema).readonly()), method(object({ deviceId: number() }), _void(), {
15989
- kind: "mutation",
15990
- auth: "admin"
15991
- }), method(DeviceEventQueryInput, array(MotionEventSchema).readonly()), method(ObjectEventQueryInput, array(ObjectEventSchema).readonly()), method(DeviceEventQueryInput, array(AudioEventSchema).readonly()), method(KeyEventQueryInput, array(KeyEventSchema).readonly()), method(object({
16107
+ limit: number().optional(),
16108
+ /** Spatial filter only tracks whose trajectory intersects the zone
16109
+ * (normalized 0..1 rect or polygon). SQL-prefiltered on the persisted
16110
+ * envelope columns, then precisely tested per position. Tracks with
16111
+ * an unknown envelope (no frame dims at persist time) always match. */
16112
+ zone: TrackZoneFilterSchema.optional(),
16113
+ /** See {@link TrackProjectionSchema}. Default `full` (backward
16114
+ * compatible — omitting the field keeps today's exact behaviour). */
16115
+ projection: TrackProjectionSchema.optional()
16116
+ }), array(TrackSchema).readonly()), method(RecentTracksQueryInput, RecentTracksPageSchema), method(object({ deviceId: number() }), _void(), {
16117
+ kind: "mutation",
16118
+ auth: "admin"
16119
+ }), method(DeviceEventQueryInput, array(MotionEventSchema).readonly()), method(ObjectEventQueryInput, array(ObjectEventSchema).readonly()), method(DeviceEventQueryInput, array(AudioEventSchema).readonly()), method(object({ deviceId: number() }), array(EventKindDescriptorSchema).readonly()), method(object({
16120
+ deviceId: number(),
16121
+ since: number().optional(),
16122
+ until: number().optional(),
16123
+ kinds: array(string()).optional(),
16124
+ limit: number().int().min(1).max(MAX_EVENT_QUERY_LIMIT).default(DEFAULT_EVENT_QUERY_LIMIT)
16125
+ }), array(SensorEventSchema).readonly()), method(KeyEventQueryInput, array(KeyEventSchema).readonly()), method(object({
15992
16126
  deviceId: number(),
15993
16127
  since: number(),
15994
16128
  until: number(),
@@ -19189,7 +19323,12 @@ var RecordingStorageUsageSchema = object({
19189
19323
  /**
19190
19324
  * Result of locating footage at a wall-clock instant for one device/profile.
19191
19325
  * `segment` carries the covering segment's window; `gap` reports the forward
19192
- * nearest covered edge (`null` past the end of footage / when none exists).
19326
+ * nearest covered edge (`null` past the end of footage / when none exists)
19327
+ * and the backward covered edge `prevEndMs` (exclusive end of the nearest
19328
+ * footage behind the epoch; `null` when none — optional so older providers
19329
+ * that omit it stay valid). `prevEndMs` lets a backward frame-step hop the
19330
+ * small inter-segment cracks (durMs under-covers the span to the next
19331
+ * startMs by ~11-17 ms) instead of no-opping at a segment head.
19193
19332
  */
19194
19333
  var LocateSegmentResultSchema = discriminatedUnion("kind", [object({
19195
19334
  kind: literal("segment"),
@@ -19198,7 +19337,8 @@ var LocateSegmentResultSchema = discriminatedUnion("kind", [object({
19198
19337
  bytes: number()
19199
19338
  }), object({
19200
19339
  kind: literal("gap"),
19201
- nearestEdgeMs: number().nullable()
19340
+ nearestEdgeMs: number().nullable(),
19341
+ prevEndMs: number().nullable().optional()
19202
19342
  })]);
19203
19343
  /** Raw bytes of one finalized footage segment (read off disk on the recording node). */
19204
19344
  var ReadSegmentBytesResultSchema = object({ data: _instanceof(Uint8Array) });
@@ -20767,6 +20907,12 @@ Object.freeze({
20767
20907
  addonId: null,
20768
20908
  access: "view"
20769
20909
  },
20910
+ "deviceManager.getLinkedDevices": {
20911
+ capName: "device-manager",
20912
+ capScope: "system",
20913
+ addonId: null,
20914
+ access: "view"
20915
+ },
20770
20916
  "deviceManager.getRoleDisplayDefaults": {
20771
20917
  capName: "device-manager",
20772
20918
  capScope: "system",
@@ -22321,6 +22467,12 @@ Object.freeze({
22321
22467
  addonId: null,
22322
22468
  access: "view"
22323
22469
  },
22470
+ "pipelineAnalytics.getSensorEvents": {
22471
+ capName: "pipeline-analytics",
22472
+ capScope: "device",
22473
+ addonId: null,
22474
+ access: "view"
22475
+ },
22324
22476
  "pipelineAnalytics.getTrack": {
22325
22477
  capName: "pipeline-analytics",
22326
22478
  capScope: "device",
@@ -22333,6 +22485,18 @@ Object.freeze({
22333
22485
  addonId: null,
22334
22486
  access: "view"
22335
22487
  },
22488
+ "pipelineAnalytics.listEventKinds": {
22489
+ capName: "pipeline-analytics",
22490
+ capScope: "device",
22491
+ addonId: null,
22492
+ access: "view"
22493
+ },
22494
+ "pipelineAnalytics.listRecentTracks": {
22495
+ capName: "pipeline-analytics",
22496
+ capScope: "device",
22497
+ addonId: null,
22498
+ access: "view"
22499
+ },
22336
22500
  "pipelineAnalytics.listTracks": {
22337
22501
  capName: "pipeline-analytics",
22338
22502
  capScope: "device",
package/dist/addon.mjs CHANGED
@@ -1,5 +1,5 @@
1
1
  import { randomUUID } from "node:crypto";
2
- //#region ../types/dist/event-category-CFZs3jI4.mjs
2
+ //#region ../types/dist/event-category-H4AVePnn.mjs
3
3
  var EventCategory = /* @__PURE__ */ function(EventCategory) {
4
4
  EventCategory["SystemBoot"] = "system.boot";
5
5
  EventCategory["SystemAddonsReady"] = "system.addons-ready";
@@ -149,6 +149,9 @@ var EventCategory = /* @__PURE__ */ function(EventCategory) {
149
149
  EventCategory["RecordingSegmentWritten"] = "recording.segment.written";
150
150
  EventCategory["RecordingPolicyFallback"] = "recording.policy.fallback";
151
151
  EventCategory["RecordingRetentionCompleted"] = "recording.retention.completed";
152
+ /** Runner-sampled scrub thumbnail (~1/5 s/camera). Telemetry (D8): a lost
153
+ * thumb is a scrub gap the recorder's keyframe backfill covers. */
154
+ EventCategory["RecordingThumbSampled"] = "recording.thumb-sampled";
152
155
  EventCategory["DetectionEvent"] = "detection.event";
153
156
  EventCategory["SessionTrackNew"] = "session.track.new";
154
157
  EventCategory["SessionTrackExpired"] = "session.track.expired";
@@ -9827,7 +9830,7 @@ object({
9827
9830
  deviceId: number(),
9828
9831
  timestamp: number()
9829
9832
  });
9830
- DeviceType.Button;
9833
+ DeviceType.Button, DeviceType.Camera;
9831
9834
  /**
9832
9835
  * Enum-state sensor — a string value picked from a finite option set.
9833
9836
  * Drives HA `sensor` entries with `state_class: enum` (HVAC action
@@ -14209,6 +14212,14 @@ var ConfigEntrySchema = object({
14209
14212
  value: unknown(),
14210
14213
  description: string().optional()
14211
14214
  });
14215
+ var DeviceLinkModeSchema = _enum(["auto", "manual"]);
14216
+ /** One resolved linked device — the compact projection consumers need. */
14217
+ var LinkedDeviceSchema = object({
14218
+ deviceId: number(),
14219
+ name: string(),
14220
+ location: string().nullable(),
14221
+ features: array(string())
14222
+ });
14212
14223
  var SavedDeviceRowSchema = object({
14213
14224
  /** Numeric id reserved at allocateDeviceId time. */
14214
14225
  id: number(),
@@ -14430,7 +14441,10 @@ method(object({
14430
14441
  }), _void(), {
14431
14442
  kind: "mutation",
14432
14443
  auth: "admin"
14433
- }), method(object({ addonId: string() }), array(SavedDeviceRowSchema)), method(object({ addonId: string().optional() }), array(DeviceInfoSchema)), method(object({ deviceId: number() }), DeviceInfoSchema.nullable()), method(object({ parentDeviceId: number() }), array(DeviceInfoSchema)), method(object({ deviceId: number() }), array(StreamSourceEntrySchema$1)), method(object({ deviceId: number() }), array(ConfigEntrySchema)), method(object({ deviceId: number() }), ConfigUISchemaOutput), method(object({
14444
+ }), method(object({ addonId: string() }), array(SavedDeviceRowSchema)), method(object({ addonId: string().optional() }), array(DeviceInfoSchema)), method(object({ deviceId: number() }), DeviceInfoSchema.nullable()), method(object({ parentDeviceId: number() }), array(DeviceInfoSchema)), method(object({ deviceId: number() }), object({
14445
+ mode: DeviceLinkModeSchema,
14446
+ devices: array(LinkedDeviceSchema)
14447
+ })), method(object({ deviceId: number() }), array(StreamSourceEntrySchema$1)), method(object({ deviceId: number() }), array(ConfigEntrySchema)), method(object({ deviceId: number() }), ConfigUISchemaOutput), method(object({
14434
14448
  deviceId: number(),
14435
14449
  values: record(string(), unknown())
14436
14450
  }), object({ success: literal(true) }), {
@@ -15713,6 +15727,61 @@ var EventKindSchema = _enum([
15713
15727
  "object",
15714
15728
  "audio"
15715
15729
  ]);
15730
+ /**
15731
+ * Spatial filter for `listTracks` — the rect + polygon variants of the shared
15732
+ * MaskShape vocabulary (see `mask-shape.ts`). Coordinates are NORMALIZED 0..1
15733
+ * of the camera frame (top-left origin), matching the drawing-plane editor.
15734
+ */
15735
+ var TrackZoneFilterSchema = discriminatedUnion("kind", [MaskRectShapeSchema, MaskPolygonShapeSchema]);
15736
+ /** Closed icon vocabulary so clients render a known glyph per kind. */
15737
+ var EventKindIconSchema = _enum([
15738
+ "motion",
15739
+ "audio",
15740
+ "person",
15741
+ "vehicle",
15742
+ "animal",
15743
+ "door",
15744
+ "pir",
15745
+ "smoke",
15746
+ "water",
15747
+ "button",
15748
+ "generic"
15749
+ ]);
15750
+ var EventKindCategorySchema = _enum([
15751
+ "motion",
15752
+ "audio",
15753
+ "detection",
15754
+ "sensor",
15755
+ "custom"
15756
+ ]);
15757
+ var EventKindDescriptorSchema = object({
15758
+ /** Stable kind id (e.g. 'motion', 'person', 'contact'). */
15759
+ kind: string(),
15760
+ label: string(),
15761
+ /** Hex color for timeline/legend rendering. */
15762
+ color: string(),
15763
+ icon: EventKindIconSchema,
15764
+ category: EventKindCategorySchema,
15765
+ /** Which cap + device contributes this kind. For built-ins the camera
15766
+ * itself; for sensor kinds the LINKED source device. */
15767
+ source: object({
15768
+ capName: string(),
15769
+ deviceId: number()
15770
+ })
15771
+ });
15772
+ var SensorEventSchema = object({
15773
+ id: string(),
15774
+ /** The CAMERA the event is attributed to (a sensor linked to N cameras
15775
+ * yields N rows, one per camera). */
15776
+ deviceId: number(),
15777
+ /** The linked sensor device whose state changed. */
15778
+ sourceDeviceId: number(),
15779
+ /** Event kind id — matches an `EventKindDescriptor.kind`. */
15780
+ kind: string(),
15781
+ /** Snapshot of the sensor cap's runtime-state slice at the change. */
15782
+ value: record(string(), unknown()).nullable(),
15783
+ timestamp: number()
15784
+ });
15716
15785
  var TrackPositionSchema = object({
15717
15786
  x: number(),
15718
15787
  y: number(),
@@ -15726,6 +15795,30 @@ var TrackSnapshotSchema = object({
15726
15795
  mediaKey: string()
15727
15796
  });
15728
15797
  /**
15798
+ * Normalized 0..1 trajectory envelope (min/max over every position bbox,
15799
+ * divided by the track's detection-frame dims), computed at persist time.
15800
+ * Absent when the frame dims were unknown when the track was persisted
15801
+ * (legacy rows / dims-less sources) and on active (in-RAM) tracks.
15802
+ */
15803
+ var TrackEnvelopeSchema = object({
15804
+ minX: number(),
15805
+ minY: number(),
15806
+ maxX: number(),
15807
+ maxY: number()
15808
+ });
15809
+ /**
15810
+ * Row projection for track list queries. `full` (default) returns the
15811
+ * complete Track including the frame-rate `positions[]` history and the
15812
+ * `snapshots[]` references — megabytes across a page of tracks. `slim`
15813
+ * keeps every scalar the list surfaces actually render (ids, class(es),
15814
+ * label / audioLabels / importance enrichment, firstSeen/lastSeen, state,
15815
+ * zonesVisited, bestEventId, envelope) and returns `positions` /
15816
+ * `snapshots` as EMPTY arrays — detail views re-fetch the full row via
15817
+ * `getTrack`. Mirrors the event-store `projection` convention
15818
+ * (`getObjectEvents` et al.).
15819
+ */
15820
+ var TrackProjectionSchema = _enum(["full", "slim"]);
15821
+ /**
15729
15822
  * One audio-classification label heard on the track's camera while the
15730
15823
  * track was alive, aggregated per label. An "episode" is one persisted
15731
15824
  * audio event (the confident-classification path: score ≥ the device's
@@ -15776,7 +15869,11 @@ var TrackSchema = object({
15776
15869
  /** Audio-classification labels heard on the camera during the track's
15777
15870
  * life (score ≥ device `classificationMinScore`), aggregated per label.
15778
15871
  * Absent on legacy rows / tracks with no confident audio. */
15779
- audioLabels: array(TrackAudioLabelSchema).readonly().optional()
15872
+ audioLabels: array(TrackAudioLabelSchema).readonly().optional(),
15873
+ /** Normalized 0..1 trajectory envelope (see {@link TrackEnvelopeSchema}).
15874
+ * Populated from the persisted envelope columns on historical reads;
15875
+ * absent on legacy rows, dims-less tracks and active (in-RAM) tracks. */
15876
+ envelope: TrackEnvelopeSchema.optional()
15780
15877
  });
15781
15878
  var BaseEventFields = {
15782
15879
  id: string(),
@@ -15886,11 +15983,13 @@ var MediaFileSchema = object({
15886
15983
  sizeBytes: number(),
15887
15984
  timestamp: number()
15888
15985
  });
15986
+ var DEFAULT_EVENT_QUERY_LIMIT = 1e3;
15987
+ var MAX_EVENT_QUERY_LIMIT = 5e3;
15889
15988
  var DeviceEventQueryInput = object({
15890
15989
  deviceId: number(),
15891
15990
  since: number().optional(),
15892
15991
  until: number().optional(),
15893
- limit: number().int().min(1).max(5e3).default(1e3),
15992
+ limit: number().int().min(1).max(MAX_EVENT_QUERY_LIMIT).default(DEFAULT_EVENT_QUERY_LIMIT),
15894
15993
  /** `slim` drops heavy JSON fields (regions/bbox/zones) and carries an
15895
15994
  * optional `mediaUrl` (populated by B5). `full` (default) keeps today's
15896
15995
  * exact behaviour. Callers may omit this field — the store defaults to
@@ -15898,6 +15997,27 @@ var DeviceEventQueryInput = object({
15898
15997
  projection: _enum(["full", "slim"]).optional()
15899
15998
  });
15900
15999
  var ObjectEventQueryInput = DeviceEventQueryInput.extend({ classFilter: string().optional() });
16000
+ var RecentTracksQueryInput = object({
16001
+ /** Devices to merge. An empty array yields `{ tracks: [], nextCursor: null }`. */
16002
+ deviceIds: array(number()),
16003
+ /** Window lower bound on `lastSeen` (inclusive). */
16004
+ since: number().optional(),
16005
+ /** Window upper bound on `lastSeen` (inclusive). */
16006
+ until: number().optional(),
16007
+ /** Page size. Default 200, max 1000. */
16008
+ limit: number().int().min(1).max(1e3).default(200),
16009
+ /** Opaque continuation cursor from a previous page's `nextCursor`.
16010
+ * Encodes the (lastSeen, trackId) sort position — treat as opaque. */
16011
+ cursor: string().optional(),
16012
+ /** See {@link TrackProjectionSchema}. Default `full`. */
16013
+ projection: TrackProjectionSchema.optional()
16014
+ });
16015
+ var RecentTracksPageSchema = object({
16016
+ /** Merged page, ordered by (`lastSeen` DESC, `trackId` DESC). */
16017
+ tracks: array(TrackSchema).readonly(),
16018
+ /** Cursor for the next page, or null when this page is the last. */
16019
+ nextCursor: string().nullable()
16020
+ });
15901
16021
  var KeyEventQueryInput = object({
15902
16022
  deviceId: number(),
15903
16023
  /** Window lower bound (track firstSeen ≥ since). */
@@ -15980,11 +16100,25 @@ DeviceType.Camera, method(object({ deviceId: number() }), array(TrackSchema).rea
15980
16100
  deviceId: number(),
15981
16101
  since: number().optional(),
15982
16102
  until: number().optional(),
15983
- limit: number().optional()
15984
- }), array(TrackSchema).readonly()), method(object({ deviceId: number() }), _void(), {
15985
- kind: "mutation",
15986
- auth: "admin"
15987
- }), method(DeviceEventQueryInput, array(MotionEventSchema).readonly()), method(ObjectEventQueryInput, array(ObjectEventSchema).readonly()), method(DeviceEventQueryInput, array(AudioEventSchema).readonly()), method(KeyEventQueryInput, array(KeyEventSchema).readonly()), method(object({
16103
+ limit: number().optional(),
16104
+ /** Spatial filter only tracks whose trajectory intersects the zone
16105
+ * (normalized 0..1 rect or polygon). SQL-prefiltered on the persisted
16106
+ * envelope columns, then precisely tested per position. Tracks with
16107
+ * an unknown envelope (no frame dims at persist time) always match. */
16108
+ zone: TrackZoneFilterSchema.optional(),
16109
+ /** See {@link TrackProjectionSchema}. Default `full` (backward
16110
+ * compatible — omitting the field keeps today's exact behaviour). */
16111
+ projection: TrackProjectionSchema.optional()
16112
+ }), array(TrackSchema).readonly()), method(RecentTracksQueryInput, RecentTracksPageSchema), method(object({ deviceId: number() }), _void(), {
16113
+ kind: "mutation",
16114
+ auth: "admin"
16115
+ }), method(DeviceEventQueryInput, array(MotionEventSchema).readonly()), method(ObjectEventQueryInput, array(ObjectEventSchema).readonly()), method(DeviceEventQueryInput, array(AudioEventSchema).readonly()), method(object({ deviceId: number() }), array(EventKindDescriptorSchema).readonly()), method(object({
16116
+ deviceId: number(),
16117
+ since: number().optional(),
16118
+ until: number().optional(),
16119
+ kinds: array(string()).optional(),
16120
+ limit: number().int().min(1).max(MAX_EVENT_QUERY_LIMIT).default(DEFAULT_EVENT_QUERY_LIMIT)
16121
+ }), array(SensorEventSchema).readonly()), method(KeyEventQueryInput, array(KeyEventSchema).readonly()), method(object({
15988
16122
  deviceId: number(),
15989
16123
  since: number(),
15990
16124
  until: number(),
@@ -19185,7 +19319,12 @@ var RecordingStorageUsageSchema = object({
19185
19319
  /**
19186
19320
  * Result of locating footage at a wall-clock instant for one device/profile.
19187
19321
  * `segment` carries the covering segment's window; `gap` reports the forward
19188
- * nearest covered edge (`null` past the end of footage / when none exists).
19322
+ * nearest covered edge (`null` past the end of footage / when none exists)
19323
+ * and the backward covered edge `prevEndMs` (exclusive end of the nearest
19324
+ * footage behind the epoch; `null` when none — optional so older providers
19325
+ * that omit it stay valid). `prevEndMs` lets a backward frame-step hop the
19326
+ * small inter-segment cracks (durMs under-covers the span to the next
19327
+ * startMs by ~11-17 ms) instead of no-opping at a segment head.
19189
19328
  */
19190
19329
  var LocateSegmentResultSchema = discriminatedUnion("kind", [object({
19191
19330
  kind: literal("segment"),
@@ -19194,7 +19333,8 @@ var LocateSegmentResultSchema = discriminatedUnion("kind", [object({
19194
19333
  bytes: number()
19195
19334
  }), object({
19196
19335
  kind: literal("gap"),
19197
- nearestEdgeMs: number().nullable()
19336
+ nearestEdgeMs: number().nullable(),
19337
+ prevEndMs: number().nullable().optional()
19198
19338
  })]);
19199
19339
  /** Raw bytes of one finalized footage segment (read off disk on the recording node). */
19200
19340
  var ReadSegmentBytesResultSchema = object({ data: _instanceof(Uint8Array) });
@@ -20763,6 +20903,12 @@ Object.freeze({
20763
20903
  addonId: null,
20764
20904
  access: "view"
20765
20905
  },
20906
+ "deviceManager.getLinkedDevices": {
20907
+ capName: "device-manager",
20908
+ capScope: "system",
20909
+ addonId: null,
20910
+ access: "view"
20911
+ },
20766
20912
  "deviceManager.getRoleDisplayDefaults": {
20767
20913
  capName: "device-manager",
20768
20914
  capScope: "system",
@@ -22317,6 +22463,12 @@ Object.freeze({
22317
22463
  addonId: null,
22318
22464
  access: "view"
22319
22465
  },
22466
+ "pipelineAnalytics.getSensorEvents": {
22467
+ capName: "pipeline-analytics",
22468
+ capScope: "device",
22469
+ addonId: null,
22470
+ access: "view"
22471
+ },
22320
22472
  "pipelineAnalytics.getTrack": {
22321
22473
  capName: "pipeline-analytics",
22322
22474
  capScope: "device",
@@ -22329,6 +22481,18 @@ Object.freeze({
22329
22481
  addonId: null,
22330
22482
  access: "view"
22331
22483
  },
22484
+ "pipelineAnalytics.listEventKinds": {
22485
+ capName: "pipeline-analytics",
22486
+ capScope: "device",
22487
+ addonId: null,
22488
+ access: "view"
22489
+ },
22490
+ "pipelineAnalytics.listRecentTracks": {
22491
+ capName: "pipeline-analytics",
22492
+ capScope: "device",
22493
+ addonId: null,
22494
+ access: "view"
22495
+ },
22332
22496
  "pipelineAnalytics.listTracks": {
22333
22497
  capName: "pipeline-analytics",
22334
22498
  capScope: "device",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@camstack/addon-advanced-notifier",
3
- "version": "1.1.25",
3
+ "version": "1.1.26",
4
4
  "description": "Rules-based notification engine for CamStack",
5
5
  "license": "MIT",
6
6
  "main": "./dist/index.js",