@camstack/addon-export-alexa 1.1.22 → 1.1.23

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.
@@ -26,7 +26,7 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
26
26
  //#endregion
27
27
  let node_crypto = require("node:crypto");
28
28
  node_crypto = __toESM(node_crypto);
29
- //#region ../types/dist/event-category-CFZs3jI4.mjs
29
+ //#region ../types/dist/event-category-H4AVePnn.mjs
30
30
  var EventCategory = /* @__PURE__ */ function(EventCategory) {
31
31
  EventCategory["SystemBoot"] = "system.boot";
32
32
  EventCategory["SystemAddonsReady"] = "system.addons-ready";
@@ -176,6 +176,9 @@ var EventCategory = /* @__PURE__ */ function(EventCategory) {
176
176
  EventCategory["RecordingSegmentWritten"] = "recording.segment.written";
177
177
  EventCategory["RecordingPolicyFallback"] = "recording.policy.fallback";
178
178
  EventCategory["RecordingRetentionCompleted"] = "recording.retention.completed";
179
+ /** Runner-sampled scrub thumbnail (~1/5 s/camera). Telemetry (D8): a lost
180
+ * thumb is a scrub gap the recorder's keyframe backfill covers. */
181
+ EventCategory["RecordingThumbSampled"] = "recording.thumb-sampled";
179
182
  EventCategory["DetectionEvent"] = "detection.event";
180
183
  EventCategory["SessionTrackNew"] = "session.track.new";
181
184
  EventCategory["SessionTrackExpired"] = "session.track.expired";
@@ -10034,7 +10037,7 @@ object({
10034
10037
  deviceId: number(),
10035
10038
  timestamp: number()
10036
10039
  });
10037
- DeviceType.Button;
10040
+ DeviceType.Button, DeviceType.Camera;
10038
10041
  /**
10039
10042
  * Enum-state sensor — a string value picked from a finite option set.
10040
10043
  * Drives HA `sensor` entries with `state_class: enum` (HVAC action
@@ -14469,6 +14472,14 @@ var ConfigEntrySchema = object({
14469
14472
  value: unknown(),
14470
14473
  description: string().optional()
14471
14474
  });
14475
+ var DeviceLinkModeSchema = _enum(["auto", "manual"]);
14476
+ /** One resolved linked device — the compact projection consumers need. */
14477
+ var LinkedDeviceSchema = object({
14478
+ deviceId: number(),
14479
+ name: string(),
14480
+ location: string().nullable(),
14481
+ features: array(string())
14482
+ });
14472
14483
  var SavedDeviceRowSchema = object({
14473
14484
  /** Numeric id reserved at allocateDeviceId time. */
14474
14485
  id: number(),
@@ -14690,7 +14701,10 @@ method(object({
14690
14701
  }), _void(), {
14691
14702
  kind: "mutation",
14692
14703
  auth: "admin"
14693
- }), 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({
14704
+ }), 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({
14705
+ mode: DeviceLinkModeSchema,
14706
+ devices: array(LinkedDeviceSchema)
14707
+ })), method(object({ deviceId: number() }), array(StreamSourceEntrySchema$1)), method(object({ deviceId: number() }), array(ConfigEntrySchema)), method(object({ deviceId: number() }), ConfigUISchemaOutput), method(object({
14694
14708
  deviceId: number(),
14695
14709
  values: record(string(), unknown())
14696
14710
  }), object({ success: literal(true) }), {
@@ -15965,6 +15979,61 @@ var EventKindSchema = _enum([
15965
15979
  "object",
15966
15980
  "audio"
15967
15981
  ]);
15982
+ /**
15983
+ * Spatial filter for `listTracks` — the rect + polygon variants of the shared
15984
+ * MaskShape vocabulary (see `mask-shape.ts`). Coordinates are NORMALIZED 0..1
15985
+ * of the camera frame (top-left origin), matching the drawing-plane editor.
15986
+ */
15987
+ var TrackZoneFilterSchema = discriminatedUnion("kind", [MaskRectShapeSchema, MaskPolygonShapeSchema]);
15988
+ /** Closed icon vocabulary so clients render a known glyph per kind. */
15989
+ var EventKindIconSchema = _enum([
15990
+ "motion",
15991
+ "audio",
15992
+ "person",
15993
+ "vehicle",
15994
+ "animal",
15995
+ "door",
15996
+ "pir",
15997
+ "smoke",
15998
+ "water",
15999
+ "button",
16000
+ "generic"
16001
+ ]);
16002
+ var EventKindCategorySchema = _enum([
16003
+ "motion",
16004
+ "audio",
16005
+ "detection",
16006
+ "sensor",
16007
+ "custom"
16008
+ ]);
16009
+ var EventKindDescriptorSchema = object({
16010
+ /** Stable kind id (e.g. 'motion', 'person', 'contact'). */
16011
+ kind: string(),
16012
+ label: string(),
16013
+ /** Hex color for timeline/legend rendering. */
16014
+ color: string(),
16015
+ icon: EventKindIconSchema,
16016
+ category: EventKindCategorySchema,
16017
+ /** Which cap + device contributes this kind. For built-ins the camera
16018
+ * itself; for sensor kinds the LINKED source device. */
16019
+ source: object({
16020
+ capName: string(),
16021
+ deviceId: number()
16022
+ })
16023
+ });
16024
+ var SensorEventSchema = object({
16025
+ id: string(),
16026
+ /** The CAMERA the event is attributed to (a sensor linked to N cameras
16027
+ * yields N rows, one per camera). */
16028
+ deviceId: number(),
16029
+ /** The linked sensor device whose state changed. */
16030
+ sourceDeviceId: number(),
16031
+ /** Event kind id — matches an `EventKindDescriptor.kind`. */
16032
+ kind: string(),
16033
+ /** Snapshot of the sensor cap's runtime-state slice at the change. */
16034
+ value: record(string(), unknown()).nullable(),
16035
+ timestamp: number()
16036
+ });
15968
16037
  var TrackPositionSchema = object({
15969
16038
  x: number(),
15970
16039
  y: number(),
@@ -15978,6 +16047,30 @@ var TrackSnapshotSchema = object({
15978
16047
  mediaKey: string()
15979
16048
  });
15980
16049
  /**
16050
+ * Normalized 0..1 trajectory envelope (min/max over every position bbox,
16051
+ * divided by the track's detection-frame dims), computed at persist time.
16052
+ * Absent when the frame dims were unknown when the track was persisted
16053
+ * (legacy rows / dims-less sources) and on active (in-RAM) tracks.
16054
+ */
16055
+ var TrackEnvelopeSchema = object({
16056
+ minX: number(),
16057
+ minY: number(),
16058
+ maxX: number(),
16059
+ maxY: number()
16060
+ });
16061
+ /**
16062
+ * Row projection for track list queries. `full` (default) returns the
16063
+ * complete Track including the frame-rate `positions[]` history and the
16064
+ * `snapshots[]` references — megabytes across a page of tracks. `slim`
16065
+ * keeps every scalar the list surfaces actually render (ids, class(es),
16066
+ * label / audioLabels / importance enrichment, firstSeen/lastSeen, state,
16067
+ * zonesVisited, bestEventId, envelope) and returns `positions` /
16068
+ * `snapshots` as EMPTY arrays — detail views re-fetch the full row via
16069
+ * `getTrack`. Mirrors the event-store `projection` convention
16070
+ * (`getObjectEvents` et al.).
16071
+ */
16072
+ var TrackProjectionSchema = _enum(["full", "slim"]);
16073
+ /**
15981
16074
  * One audio-classification label heard on the track's camera while the
15982
16075
  * track was alive, aggregated per label. An "episode" is one persisted
15983
16076
  * audio event (the confident-classification path: score ≥ the device's
@@ -16028,7 +16121,11 @@ var TrackSchema = object({
16028
16121
  /** Audio-classification labels heard on the camera during the track's
16029
16122
  * life (score ≥ device `classificationMinScore`), aggregated per label.
16030
16123
  * Absent on legacy rows / tracks with no confident audio. */
16031
- audioLabels: array(TrackAudioLabelSchema).readonly().optional()
16124
+ audioLabels: array(TrackAudioLabelSchema).readonly().optional(),
16125
+ /** Normalized 0..1 trajectory envelope (see {@link TrackEnvelopeSchema}).
16126
+ * Populated from the persisted envelope columns on historical reads;
16127
+ * absent on legacy rows, dims-less tracks and active (in-RAM) tracks. */
16128
+ envelope: TrackEnvelopeSchema.optional()
16032
16129
  });
16033
16130
  var BaseEventFields = {
16034
16131
  id: string(),
@@ -16138,11 +16235,13 @@ var MediaFileSchema = object({
16138
16235
  sizeBytes: number(),
16139
16236
  timestamp: number()
16140
16237
  });
16238
+ var DEFAULT_EVENT_QUERY_LIMIT = 1e3;
16239
+ var MAX_EVENT_QUERY_LIMIT = 5e3;
16141
16240
  var DeviceEventQueryInput = object({
16142
16241
  deviceId: number(),
16143
16242
  since: number().optional(),
16144
16243
  until: number().optional(),
16145
- limit: number().int().min(1).max(5e3).default(1e3),
16244
+ limit: number().int().min(1).max(MAX_EVENT_QUERY_LIMIT).default(DEFAULT_EVENT_QUERY_LIMIT),
16146
16245
  /** `slim` drops heavy JSON fields (regions/bbox/zones) and carries an
16147
16246
  * optional `mediaUrl` (populated by B5). `full` (default) keeps today's
16148
16247
  * exact behaviour. Callers may omit this field — the store defaults to
@@ -16150,6 +16249,27 @@ var DeviceEventQueryInput = object({
16150
16249
  projection: _enum(["full", "slim"]).optional()
16151
16250
  });
16152
16251
  var ObjectEventQueryInput = DeviceEventQueryInput.extend({ classFilter: string().optional() });
16252
+ var RecentTracksQueryInput = object({
16253
+ /** Devices to merge. An empty array yields `{ tracks: [], nextCursor: null }`. */
16254
+ deviceIds: array(number()),
16255
+ /** Window lower bound on `lastSeen` (inclusive). */
16256
+ since: number().optional(),
16257
+ /** Window upper bound on `lastSeen` (inclusive). */
16258
+ until: number().optional(),
16259
+ /** Page size. Default 200, max 1000. */
16260
+ limit: number().int().min(1).max(1e3).default(200),
16261
+ /** Opaque continuation cursor from a previous page's `nextCursor`.
16262
+ * Encodes the (lastSeen, trackId) sort position — treat as opaque. */
16263
+ cursor: string().optional(),
16264
+ /** See {@link TrackProjectionSchema}. Default `full`. */
16265
+ projection: TrackProjectionSchema.optional()
16266
+ });
16267
+ var RecentTracksPageSchema = object({
16268
+ /** Merged page, ordered by (`lastSeen` DESC, `trackId` DESC). */
16269
+ tracks: array(TrackSchema).readonly(),
16270
+ /** Cursor for the next page, or null when this page is the last. */
16271
+ nextCursor: string().nullable()
16272
+ });
16153
16273
  var KeyEventQueryInput = object({
16154
16274
  deviceId: number(),
16155
16275
  /** Window lower bound (track firstSeen ≥ since). */
@@ -16232,11 +16352,25 @@ DeviceType.Camera, method(object({ deviceId: number() }), array(TrackSchema).rea
16232
16352
  deviceId: number(),
16233
16353
  since: number().optional(),
16234
16354
  until: number().optional(),
16235
- limit: number().optional()
16236
- }), array(TrackSchema).readonly()), method(object({ deviceId: number() }), _void(), {
16237
- kind: "mutation",
16238
- auth: "admin"
16239
- }), method(DeviceEventQueryInput, array(MotionEventSchema).readonly()), method(ObjectEventQueryInput, array(ObjectEventSchema).readonly()), method(DeviceEventQueryInput, array(AudioEventSchema).readonly()), method(KeyEventQueryInput, array(KeyEventSchema).readonly()), method(object({
16355
+ limit: number().optional(),
16356
+ /** Spatial filter only tracks whose trajectory intersects the zone
16357
+ * (normalized 0..1 rect or polygon). SQL-prefiltered on the persisted
16358
+ * envelope columns, then precisely tested per position. Tracks with
16359
+ * an unknown envelope (no frame dims at persist time) always match. */
16360
+ zone: TrackZoneFilterSchema.optional(),
16361
+ /** See {@link TrackProjectionSchema}. Default `full` (backward
16362
+ * compatible — omitting the field keeps today's exact behaviour). */
16363
+ projection: TrackProjectionSchema.optional()
16364
+ }), array(TrackSchema).readonly()), method(RecentTracksQueryInput, RecentTracksPageSchema), method(object({ deviceId: number() }), _void(), {
16365
+ kind: "mutation",
16366
+ auth: "admin"
16367
+ }), method(DeviceEventQueryInput, array(MotionEventSchema).readonly()), method(ObjectEventQueryInput, array(ObjectEventSchema).readonly()), method(DeviceEventQueryInput, array(AudioEventSchema).readonly()), method(object({ deviceId: number() }), array(EventKindDescriptorSchema).readonly()), method(object({
16368
+ deviceId: number(),
16369
+ since: number().optional(),
16370
+ until: number().optional(),
16371
+ kinds: array(string()).optional(),
16372
+ limit: number().int().min(1).max(MAX_EVENT_QUERY_LIMIT).default(DEFAULT_EVENT_QUERY_LIMIT)
16373
+ }), array(SensorEventSchema).readonly()), method(KeyEventQueryInput, array(KeyEventSchema).readonly()), method(object({
16240
16374
  deviceId: number(),
16241
16375
  since: number(),
16242
16376
  until: number(),
@@ -19437,7 +19571,12 @@ var RecordingStorageUsageSchema = object({
19437
19571
  /**
19438
19572
  * Result of locating footage at a wall-clock instant for one device/profile.
19439
19573
  * `segment` carries the covering segment's window; `gap` reports the forward
19440
- * nearest covered edge (`null` past the end of footage / when none exists).
19574
+ * nearest covered edge (`null` past the end of footage / when none exists)
19575
+ * and the backward covered edge `prevEndMs` (exclusive end of the nearest
19576
+ * footage behind the epoch; `null` when none — optional so older providers
19577
+ * that omit it stay valid). `prevEndMs` lets a backward frame-step hop the
19578
+ * small inter-segment cracks (durMs under-covers the span to the next
19579
+ * startMs by ~11-17 ms) instead of no-opping at a segment head.
19441
19580
  */
19442
19581
  var LocateSegmentResultSchema = discriminatedUnion("kind", [object({
19443
19582
  kind: literal("segment"),
@@ -19446,7 +19585,8 @@ var LocateSegmentResultSchema = discriminatedUnion("kind", [object({
19446
19585
  bytes: number()
19447
19586
  }), object({
19448
19587
  kind: literal("gap"),
19449
- nearestEdgeMs: number().nullable()
19588
+ nearestEdgeMs: number().nullable(),
19589
+ prevEndMs: number().nullable().optional()
19450
19590
  })]);
19451
19591
  /** Raw bytes of one finalized footage segment (read off disk on the recording node). */
19452
19592
  var ReadSegmentBytesResultSchema = object({ data: _instanceof(Uint8Array) });
@@ -21015,6 +21155,12 @@ Object.freeze({
21015
21155
  addonId: null,
21016
21156
  access: "view"
21017
21157
  },
21158
+ "deviceManager.getLinkedDevices": {
21159
+ capName: "device-manager",
21160
+ capScope: "system",
21161
+ addonId: null,
21162
+ access: "view"
21163
+ },
21018
21164
  "deviceManager.getRoleDisplayDefaults": {
21019
21165
  capName: "device-manager",
21020
21166
  capScope: "system",
@@ -22569,6 +22715,12 @@ Object.freeze({
22569
22715
  addonId: null,
22570
22716
  access: "view"
22571
22717
  },
22718
+ "pipelineAnalytics.getSensorEvents": {
22719
+ capName: "pipeline-analytics",
22720
+ capScope: "device",
22721
+ addonId: null,
22722
+ access: "view"
22723
+ },
22572
22724
  "pipelineAnalytics.getTrack": {
22573
22725
  capName: "pipeline-analytics",
22574
22726
  capScope: "device",
@@ -22581,6 +22733,18 @@ Object.freeze({
22581
22733
  addonId: null,
22582
22734
  access: "view"
22583
22735
  },
22736
+ "pipelineAnalytics.listEventKinds": {
22737
+ capName: "pipeline-analytics",
22738
+ capScope: "device",
22739
+ addonId: null,
22740
+ access: "view"
22741
+ },
22742
+ "pipelineAnalytics.listRecentTracks": {
22743
+ capName: "pipeline-analytics",
22744
+ capScope: "device",
22745
+ addonId: null,
22746
+ access: "view"
22747
+ },
22584
22748
  "pipelineAnalytics.listTracks": {
22585
22749
  capName: "pipeline-analytics",
22586
22750
  capScope: "device",
@@ -1,6 +1,6 @@
1
1
  import * as crypto$1 from "node:crypto";
2
2
  import { createHash } from "node:crypto";
3
- //#region ../types/dist/event-category-CFZs3jI4.mjs
3
+ //#region ../types/dist/event-category-H4AVePnn.mjs
4
4
  var EventCategory = /* @__PURE__ */ function(EventCategory) {
5
5
  EventCategory["SystemBoot"] = "system.boot";
6
6
  EventCategory["SystemAddonsReady"] = "system.addons-ready";
@@ -150,6 +150,9 @@ var EventCategory = /* @__PURE__ */ function(EventCategory) {
150
150
  EventCategory["RecordingSegmentWritten"] = "recording.segment.written";
151
151
  EventCategory["RecordingPolicyFallback"] = "recording.policy.fallback";
152
152
  EventCategory["RecordingRetentionCompleted"] = "recording.retention.completed";
153
+ /** Runner-sampled scrub thumbnail (~1/5 s/camera). Telemetry (D8): a lost
154
+ * thumb is a scrub gap the recorder's keyframe backfill covers. */
155
+ EventCategory["RecordingThumbSampled"] = "recording.thumb-sampled";
153
156
  EventCategory["DetectionEvent"] = "detection.event";
154
157
  EventCategory["SessionTrackNew"] = "session.track.new";
155
158
  EventCategory["SessionTrackExpired"] = "session.track.expired";
@@ -10008,7 +10011,7 @@ object({
10008
10011
  deviceId: number(),
10009
10012
  timestamp: number()
10010
10013
  });
10011
- DeviceType.Button;
10014
+ DeviceType.Button, DeviceType.Camera;
10012
10015
  /**
10013
10016
  * Enum-state sensor — a string value picked from a finite option set.
10014
10017
  * Drives HA `sensor` entries with `state_class: enum` (HVAC action
@@ -14443,6 +14446,14 @@ var ConfigEntrySchema = object({
14443
14446
  value: unknown(),
14444
14447
  description: string().optional()
14445
14448
  });
14449
+ var DeviceLinkModeSchema = _enum(["auto", "manual"]);
14450
+ /** One resolved linked device — the compact projection consumers need. */
14451
+ var LinkedDeviceSchema = object({
14452
+ deviceId: number(),
14453
+ name: string(),
14454
+ location: string().nullable(),
14455
+ features: array(string())
14456
+ });
14446
14457
  var SavedDeviceRowSchema = object({
14447
14458
  /** Numeric id reserved at allocateDeviceId time. */
14448
14459
  id: number(),
@@ -14664,7 +14675,10 @@ method(object({
14664
14675
  }), _void(), {
14665
14676
  kind: "mutation",
14666
14677
  auth: "admin"
14667
- }), 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({
14678
+ }), 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({
14679
+ mode: DeviceLinkModeSchema,
14680
+ devices: array(LinkedDeviceSchema)
14681
+ })), method(object({ deviceId: number() }), array(StreamSourceEntrySchema$1)), method(object({ deviceId: number() }), array(ConfigEntrySchema)), method(object({ deviceId: number() }), ConfigUISchemaOutput), method(object({
14668
14682
  deviceId: number(),
14669
14683
  values: record(string(), unknown())
14670
14684
  }), object({ success: literal(true) }), {
@@ -15939,6 +15953,61 @@ var EventKindSchema = _enum([
15939
15953
  "object",
15940
15954
  "audio"
15941
15955
  ]);
15956
+ /**
15957
+ * Spatial filter for `listTracks` — the rect + polygon variants of the shared
15958
+ * MaskShape vocabulary (see `mask-shape.ts`). Coordinates are NORMALIZED 0..1
15959
+ * of the camera frame (top-left origin), matching the drawing-plane editor.
15960
+ */
15961
+ var TrackZoneFilterSchema = discriminatedUnion("kind", [MaskRectShapeSchema, MaskPolygonShapeSchema]);
15962
+ /** Closed icon vocabulary so clients render a known glyph per kind. */
15963
+ var EventKindIconSchema = _enum([
15964
+ "motion",
15965
+ "audio",
15966
+ "person",
15967
+ "vehicle",
15968
+ "animal",
15969
+ "door",
15970
+ "pir",
15971
+ "smoke",
15972
+ "water",
15973
+ "button",
15974
+ "generic"
15975
+ ]);
15976
+ var EventKindCategorySchema = _enum([
15977
+ "motion",
15978
+ "audio",
15979
+ "detection",
15980
+ "sensor",
15981
+ "custom"
15982
+ ]);
15983
+ var EventKindDescriptorSchema = object({
15984
+ /** Stable kind id (e.g. 'motion', 'person', 'contact'). */
15985
+ kind: string(),
15986
+ label: string(),
15987
+ /** Hex color for timeline/legend rendering. */
15988
+ color: string(),
15989
+ icon: EventKindIconSchema,
15990
+ category: EventKindCategorySchema,
15991
+ /** Which cap + device contributes this kind. For built-ins the camera
15992
+ * itself; for sensor kinds the LINKED source device. */
15993
+ source: object({
15994
+ capName: string(),
15995
+ deviceId: number()
15996
+ })
15997
+ });
15998
+ var SensorEventSchema = object({
15999
+ id: string(),
16000
+ /** The CAMERA the event is attributed to (a sensor linked to N cameras
16001
+ * yields N rows, one per camera). */
16002
+ deviceId: number(),
16003
+ /** The linked sensor device whose state changed. */
16004
+ sourceDeviceId: number(),
16005
+ /** Event kind id — matches an `EventKindDescriptor.kind`. */
16006
+ kind: string(),
16007
+ /** Snapshot of the sensor cap's runtime-state slice at the change. */
16008
+ value: record(string(), unknown()).nullable(),
16009
+ timestamp: number()
16010
+ });
15942
16011
  var TrackPositionSchema = object({
15943
16012
  x: number(),
15944
16013
  y: number(),
@@ -15952,6 +16021,30 @@ var TrackSnapshotSchema = object({
15952
16021
  mediaKey: string()
15953
16022
  });
15954
16023
  /**
16024
+ * Normalized 0..1 trajectory envelope (min/max over every position bbox,
16025
+ * divided by the track's detection-frame dims), computed at persist time.
16026
+ * Absent when the frame dims were unknown when the track was persisted
16027
+ * (legacy rows / dims-less sources) and on active (in-RAM) tracks.
16028
+ */
16029
+ var TrackEnvelopeSchema = object({
16030
+ minX: number(),
16031
+ minY: number(),
16032
+ maxX: number(),
16033
+ maxY: number()
16034
+ });
16035
+ /**
16036
+ * Row projection for track list queries. `full` (default) returns the
16037
+ * complete Track including the frame-rate `positions[]` history and the
16038
+ * `snapshots[]` references — megabytes across a page of tracks. `slim`
16039
+ * keeps every scalar the list surfaces actually render (ids, class(es),
16040
+ * label / audioLabels / importance enrichment, firstSeen/lastSeen, state,
16041
+ * zonesVisited, bestEventId, envelope) and returns `positions` /
16042
+ * `snapshots` as EMPTY arrays — detail views re-fetch the full row via
16043
+ * `getTrack`. Mirrors the event-store `projection` convention
16044
+ * (`getObjectEvents` et al.).
16045
+ */
16046
+ var TrackProjectionSchema = _enum(["full", "slim"]);
16047
+ /**
15955
16048
  * One audio-classification label heard on the track's camera while the
15956
16049
  * track was alive, aggregated per label. An "episode" is one persisted
15957
16050
  * audio event (the confident-classification path: score ≥ the device's
@@ -16002,7 +16095,11 @@ var TrackSchema = object({
16002
16095
  /** Audio-classification labels heard on the camera during the track's
16003
16096
  * life (score ≥ device `classificationMinScore`), aggregated per label.
16004
16097
  * Absent on legacy rows / tracks with no confident audio. */
16005
- audioLabels: array(TrackAudioLabelSchema).readonly().optional()
16098
+ audioLabels: array(TrackAudioLabelSchema).readonly().optional(),
16099
+ /** Normalized 0..1 trajectory envelope (see {@link TrackEnvelopeSchema}).
16100
+ * Populated from the persisted envelope columns on historical reads;
16101
+ * absent on legacy rows, dims-less tracks and active (in-RAM) tracks. */
16102
+ envelope: TrackEnvelopeSchema.optional()
16006
16103
  });
16007
16104
  var BaseEventFields = {
16008
16105
  id: string(),
@@ -16112,11 +16209,13 @@ var MediaFileSchema = object({
16112
16209
  sizeBytes: number(),
16113
16210
  timestamp: number()
16114
16211
  });
16212
+ var DEFAULT_EVENT_QUERY_LIMIT = 1e3;
16213
+ var MAX_EVENT_QUERY_LIMIT = 5e3;
16115
16214
  var DeviceEventQueryInput = object({
16116
16215
  deviceId: number(),
16117
16216
  since: number().optional(),
16118
16217
  until: number().optional(),
16119
- limit: number().int().min(1).max(5e3).default(1e3),
16218
+ limit: number().int().min(1).max(MAX_EVENT_QUERY_LIMIT).default(DEFAULT_EVENT_QUERY_LIMIT),
16120
16219
  /** `slim` drops heavy JSON fields (regions/bbox/zones) and carries an
16121
16220
  * optional `mediaUrl` (populated by B5). `full` (default) keeps today's
16122
16221
  * exact behaviour. Callers may omit this field — the store defaults to
@@ -16124,6 +16223,27 @@ var DeviceEventQueryInput = object({
16124
16223
  projection: _enum(["full", "slim"]).optional()
16125
16224
  });
16126
16225
  var ObjectEventQueryInput = DeviceEventQueryInput.extend({ classFilter: string().optional() });
16226
+ var RecentTracksQueryInput = object({
16227
+ /** Devices to merge. An empty array yields `{ tracks: [], nextCursor: null }`. */
16228
+ deviceIds: array(number()),
16229
+ /** Window lower bound on `lastSeen` (inclusive). */
16230
+ since: number().optional(),
16231
+ /** Window upper bound on `lastSeen` (inclusive). */
16232
+ until: number().optional(),
16233
+ /** Page size. Default 200, max 1000. */
16234
+ limit: number().int().min(1).max(1e3).default(200),
16235
+ /** Opaque continuation cursor from a previous page's `nextCursor`.
16236
+ * Encodes the (lastSeen, trackId) sort position — treat as opaque. */
16237
+ cursor: string().optional(),
16238
+ /** See {@link TrackProjectionSchema}. Default `full`. */
16239
+ projection: TrackProjectionSchema.optional()
16240
+ });
16241
+ var RecentTracksPageSchema = object({
16242
+ /** Merged page, ordered by (`lastSeen` DESC, `trackId` DESC). */
16243
+ tracks: array(TrackSchema).readonly(),
16244
+ /** Cursor for the next page, or null when this page is the last. */
16245
+ nextCursor: string().nullable()
16246
+ });
16127
16247
  var KeyEventQueryInput = object({
16128
16248
  deviceId: number(),
16129
16249
  /** Window lower bound (track firstSeen ≥ since). */
@@ -16206,11 +16326,25 @@ DeviceType.Camera, method(object({ deviceId: number() }), array(TrackSchema).rea
16206
16326
  deviceId: number(),
16207
16327
  since: number().optional(),
16208
16328
  until: number().optional(),
16209
- limit: number().optional()
16210
- }), array(TrackSchema).readonly()), method(object({ deviceId: number() }), _void(), {
16211
- kind: "mutation",
16212
- auth: "admin"
16213
- }), method(DeviceEventQueryInput, array(MotionEventSchema).readonly()), method(ObjectEventQueryInput, array(ObjectEventSchema).readonly()), method(DeviceEventQueryInput, array(AudioEventSchema).readonly()), method(KeyEventQueryInput, array(KeyEventSchema).readonly()), method(object({
16329
+ limit: number().optional(),
16330
+ /** Spatial filter only tracks whose trajectory intersects the zone
16331
+ * (normalized 0..1 rect or polygon). SQL-prefiltered on the persisted
16332
+ * envelope columns, then precisely tested per position. Tracks with
16333
+ * an unknown envelope (no frame dims at persist time) always match. */
16334
+ zone: TrackZoneFilterSchema.optional(),
16335
+ /** See {@link TrackProjectionSchema}. Default `full` (backward
16336
+ * compatible — omitting the field keeps today's exact behaviour). */
16337
+ projection: TrackProjectionSchema.optional()
16338
+ }), array(TrackSchema).readonly()), method(RecentTracksQueryInput, RecentTracksPageSchema), method(object({ deviceId: number() }), _void(), {
16339
+ kind: "mutation",
16340
+ auth: "admin"
16341
+ }), method(DeviceEventQueryInput, array(MotionEventSchema).readonly()), method(ObjectEventQueryInput, array(ObjectEventSchema).readonly()), method(DeviceEventQueryInput, array(AudioEventSchema).readonly()), method(object({ deviceId: number() }), array(EventKindDescriptorSchema).readonly()), method(object({
16342
+ deviceId: number(),
16343
+ since: number().optional(),
16344
+ until: number().optional(),
16345
+ kinds: array(string()).optional(),
16346
+ limit: number().int().min(1).max(MAX_EVENT_QUERY_LIMIT).default(DEFAULT_EVENT_QUERY_LIMIT)
16347
+ }), array(SensorEventSchema).readonly()), method(KeyEventQueryInput, array(KeyEventSchema).readonly()), method(object({
16214
16348
  deviceId: number(),
16215
16349
  since: number(),
16216
16350
  until: number(),
@@ -19411,7 +19545,12 @@ var RecordingStorageUsageSchema = object({
19411
19545
  /**
19412
19546
  * Result of locating footage at a wall-clock instant for one device/profile.
19413
19547
  * `segment` carries the covering segment's window; `gap` reports the forward
19414
- * nearest covered edge (`null` past the end of footage / when none exists).
19548
+ * nearest covered edge (`null` past the end of footage / when none exists)
19549
+ * and the backward covered edge `prevEndMs` (exclusive end of the nearest
19550
+ * footage behind the epoch; `null` when none — optional so older providers
19551
+ * that omit it stay valid). `prevEndMs` lets a backward frame-step hop the
19552
+ * small inter-segment cracks (durMs under-covers the span to the next
19553
+ * startMs by ~11-17 ms) instead of no-opping at a segment head.
19415
19554
  */
19416
19555
  var LocateSegmentResultSchema = discriminatedUnion("kind", [object({
19417
19556
  kind: literal("segment"),
@@ -19420,7 +19559,8 @@ var LocateSegmentResultSchema = discriminatedUnion("kind", [object({
19420
19559
  bytes: number()
19421
19560
  }), object({
19422
19561
  kind: literal("gap"),
19423
- nearestEdgeMs: number().nullable()
19562
+ nearestEdgeMs: number().nullable(),
19563
+ prevEndMs: number().nullable().optional()
19424
19564
  })]);
19425
19565
  /** Raw bytes of one finalized footage segment (read off disk on the recording node). */
19426
19566
  var ReadSegmentBytesResultSchema = object({ data: _instanceof(Uint8Array) });
@@ -20989,6 +21129,12 @@ Object.freeze({
20989
21129
  addonId: null,
20990
21130
  access: "view"
20991
21131
  },
21132
+ "deviceManager.getLinkedDevices": {
21133
+ capName: "device-manager",
21134
+ capScope: "system",
21135
+ addonId: null,
21136
+ access: "view"
21137
+ },
20992
21138
  "deviceManager.getRoleDisplayDefaults": {
20993
21139
  capName: "device-manager",
20994
21140
  capScope: "system",
@@ -22543,6 +22689,12 @@ Object.freeze({
22543
22689
  addonId: null,
22544
22690
  access: "view"
22545
22691
  },
22692
+ "pipelineAnalytics.getSensorEvents": {
22693
+ capName: "pipeline-analytics",
22694
+ capScope: "device",
22695
+ addonId: null,
22696
+ access: "view"
22697
+ },
22546
22698
  "pipelineAnalytics.getTrack": {
22547
22699
  capName: "pipeline-analytics",
22548
22700
  capScope: "device",
@@ -22555,6 +22707,18 @@ Object.freeze({
22555
22707
  addonId: null,
22556
22708
  access: "view"
22557
22709
  },
22710
+ "pipelineAnalytics.listEventKinds": {
22711
+ capName: "pipeline-analytics",
22712
+ capScope: "device",
22713
+ addonId: null,
22714
+ access: "view"
22715
+ },
22716
+ "pipelineAnalytics.listRecentTracks": {
22717
+ capName: "pipeline-analytics",
22718
+ capScope: "device",
22719
+ addonId: null,
22720
+ access: "view"
22721
+ },
22558
22722
  "pipelineAnalytics.listTracks": {
22559
22723
  capName: "pipeline-analytics",
22560
22724
  capScope: "device",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@camstack/addon-export-alexa",
3
- "version": "1.1.22",
3
+ "version": "1.1.23",
4
4
  "description": "Alexa Smart Home Skill export — hub-side OAuth provider + directive handler. The companion AWS Lambda forwards Alexa directives to this addon's /addon/export-alexa/directive endpoint.",
5
5
  "keywords": [
6
6
  "camstack",