@camstack/addon-pipeline-orchestrator 1.1.48 → 1.1.49

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/index.js CHANGED
@@ -29,7 +29,7 @@ node_fs = __toESM(node_fs);
29
29
  let node_path = require("node:path");
30
30
  node_path = __toESM(node_path);
31
31
  let node_url = require("node:url");
32
- //#region ../types/dist/event-category-CFZs3jI4.mjs
32
+ //#region ../types/dist/event-category-H4AVePnn.mjs
33
33
  var EventCategory = /* @__PURE__ */ function(EventCategory) {
34
34
  EventCategory["SystemBoot"] = "system.boot";
35
35
  EventCategory["SystemAddonsReady"] = "system.addons-ready";
@@ -179,6 +179,9 @@ var EventCategory = /* @__PURE__ */ function(EventCategory) {
179
179
  EventCategory["RecordingSegmentWritten"] = "recording.segment.written";
180
180
  EventCategory["RecordingPolicyFallback"] = "recording.policy.fallback";
181
181
  EventCategory["RecordingRetentionCompleted"] = "recording.retention.completed";
182
+ /** Runner-sampled scrub thumbnail (~1/5 s/camera). Telemetry (D8): a lost
183
+ * thumb is a scrub gap the recorder's keyframe backfill covers. */
184
+ EventCategory["RecordingThumbSampled"] = "recording.thumb-sampled";
182
185
  EventCategory["DetectionEvent"] = "detection.event";
183
186
  EventCategory["SessionTrackNew"] = "session.track.new";
184
187
  EventCategory["SessionTrackExpired"] = "session.track.expired";
@@ -10332,7 +10335,7 @@ object({
10332
10335
  deviceId: number(),
10333
10336
  timestamp: number()
10334
10337
  });
10335
- DeviceType.Button;
10338
+ DeviceType.Button, DeviceType.Camera;
10336
10339
  /**
10337
10340
  * Enum-state sensor — a string value picked from a finite option set.
10338
10341
  * Drives HA `sensor` entries with `state_class: enum` (HVAC action
@@ -15128,6 +15131,14 @@ var ConfigEntrySchema = object({
15128
15131
  value: unknown(),
15129
15132
  description: string().optional()
15130
15133
  });
15134
+ var DeviceLinkModeSchema = _enum(["auto", "manual"]);
15135
+ /** One resolved linked device — the compact projection consumers need. */
15136
+ var LinkedDeviceSchema = object({
15137
+ deviceId: number(),
15138
+ name: string(),
15139
+ location: string().nullable(),
15140
+ features: array(string())
15141
+ });
15131
15142
  var SavedDeviceRowSchema = object({
15132
15143
  /** Numeric id reserved at allocateDeviceId time. */
15133
15144
  id: number(),
@@ -15349,7 +15360,10 @@ method(object({
15349
15360
  }), _void(), {
15350
15361
  kind: "mutation",
15351
15362
  auth: "admin"
15352
- }), 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({
15363
+ }), 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({
15364
+ mode: DeviceLinkModeSchema,
15365
+ devices: array(LinkedDeviceSchema)
15366
+ })), method(object({ deviceId: number() }), array(StreamSourceEntrySchema$1)), method(object({ deviceId: number() }), array(ConfigEntrySchema)), method(object({ deviceId: number() }), ConfigUISchemaOutput), method(object({
15353
15367
  deviceId: number(),
15354
15368
  values: record(string(), unknown())
15355
15369
  }), object({ success: literal(true) }), {
@@ -16618,6 +16632,61 @@ var EventKindSchema = _enum([
16618
16632
  "object",
16619
16633
  "audio"
16620
16634
  ]);
16635
+ /**
16636
+ * Spatial filter for `listTracks` — the rect + polygon variants of the shared
16637
+ * MaskShape vocabulary (see `mask-shape.ts`). Coordinates are NORMALIZED 0..1
16638
+ * of the camera frame (top-left origin), matching the drawing-plane editor.
16639
+ */
16640
+ var TrackZoneFilterSchema = discriminatedUnion("kind", [MaskRectShapeSchema, MaskPolygonShapeSchema]);
16641
+ /** Closed icon vocabulary so clients render a known glyph per kind. */
16642
+ var EventKindIconSchema = _enum([
16643
+ "motion",
16644
+ "audio",
16645
+ "person",
16646
+ "vehicle",
16647
+ "animal",
16648
+ "door",
16649
+ "pir",
16650
+ "smoke",
16651
+ "water",
16652
+ "button",
16653
+ "generic"
16654
+ ]);
16655
+ var EventKindCategorySchema = _enum([
16656
+ "motion",
16657
+ "audio",
16658
+ "detection",
16659
+ "sensor",
16660
+ "custom"
16661
+ ]);
16662
+ var EventKindDescriptorSchema = object({
16663
+ /** Stable kind id (e.g. 'motion', 'person', 'contact'). */
16664
+ kind: string(),
16665
+ label: string(),
16666
+ /** Hex color for timeline/legend rendering. */
16667
+ color: string(),
16668
+ icon: EventKindIconSchema,
16669
+ category: EventKindCategorySchema,
16670
+ /** Which cap + device contributes this kind. For built-ins the camera
16671
+ * itself; for sensor kinds the LINKED source device. */
16672
+ source: object({
16673
+ capName: string(),
16674
+ deviceId: number()
16675
+ })
16676
+ });
16677
+ var SensorEventSchema = object({
16678
+ id: string(),
16679
+ /** The CAMERA the event is attributed to (a sensor linked to N cameras
16680
+ * yields N rows, one per camera). */
16681
+ deviceId: number(),
16682
+ /** The linked sensor device whose state changed. */
16683
+ sourceDeviceId: number(),
16684
+ /** Event kind id — matches an `EventKindDescriptor.kind`. */
16685
+ kind: string(),
16686
+ /** Snapshot of the sensor cap's runtime-state slice at the change. */
16687
+ value: record(string(), unknown()).nullable(),
16688
+ timestamp: number()
16689
+ });
16621
16690
  var TrackPositionSchema = object({
16622
16691
  x: number(),
16623
16692
  y: number(),
@@ -16631,6 +16700,30 @@ var TrackSnapshotSchema = object({
16631
16700
  mediaKey: string()
16632
16701
  });
16633
16702
  /**
16703
+ * Normalized 0..1 trajectory envelope (min/max over every position bbox,
16704
+ * divided by the track's detection-frame dims), computed at persist time.
16705
+ * Absent when the frame dims were unknown when the track was persisted
16706
+ * (legacy rows / dims-less sources) and on active (in-RAM) tracks.
16707
+ */
16708
+ var TrackEnvelopeSchema = object({
16709
+ minX: number(),
16710
+ minY: number(),
16711
+ maxX: number(),
16712
+ maxY: number()
16713
+ });
16714
+ /**
16715
+ * Row projection for track list queries. `full` (default) returns the
16716
+ * complete Track including the frame-rate `positions[]` history and the
16717
+ * `snapshots[]` references — megabytes across a page of tracks. `slim`
16718
+ * keeps every scalar the list surfaces actually render (ids, class(es),
16719
+ * label / audioLabels / importance enrichment, firstSeen/lastSeen, state,
16720
+ * zonesVisited, bestEventId, envelope) and returns `positions` /
16721
+ * `snapshots` as EMPTY arrays — detail views re-fetch the full row via
16722
+ * `getTrack`. Mirrors the event-store `projection` convention
16723
+ * (`getObjectEvents` et al.).
16724
+ */
16725
+ var TrackProjectionSchema = _enum(["full", "slim"]);
16726
+ /**
16634
16727
  * One audio-classification label heard on the track's camera while the
16635
16728
  * track was alive, aggregated per label. An "episode" is one persisted
16636
16729
  * audio event (the confident-classification path: score ≥ the device's
@@ -16681,7 +16774,11 @@ var TrackSchema = object({
16681
16774
  /** Audio-classification labels heard on the camera during the track's
16682
16775
  * life (score ≥ device `classificationMinScore`), aggregated per label.
16683
16776
  * Absent on legacy rows / tracks with no confident audio. */
16684
- audioLabels: array(TrackAudioLabelSchema).readonly().optional()
16777
+ audioLabels: array(TrackAudioLabelSchema).readonly().optional(),
16778
+ /** Normalized 0..1 trajectory envelope (see {@link TrackEnvelopeSchema}).
16779
+ * Populated from the persisted envelope columns on historical reads;
16780
+ * absent on legacy rows, dims-less tracks and active (in-RAM) tracks. */
16781
+ envelope: TrackEnvelopeSchema.optional()
16685
16782
  });
16686
16783
  var BaseEventFields = {
16687
16784
  id: string(),
@@ -16791,11 +16888,13 @@ var MediaFileSchema = object({
16791
16888
  sizeBytes: number(),
16792
16889
  timestamp: number()
16793
16890
  });
16891
+ var DEFAULT_EVENT_QUERY_LIMIT = 1e3;
16892
+ var MAX_EVENT_QUERY_LIMIT = 5e3;
16794
16893
  var DeviceEventQueryInput = object({
16795
16894
  deviceId: number(),
16796
16895
  since: number().optional(),
16797
16896
  until: number().optional(),
16798
- limit: number().int().min(1).max(5e3).default(1e3),
16897
+ limit: number().int().min(1).max(MAX_EVENT_QUERY_LIMIT).default(DEFAULT_EVENT_QUERY_LIMIT),
16799
16898
  /** `slim` drops heavy JSON fields (regions/bbox/zones) and carries an
16800
16899
  * optional `mediaUrl` (populated by B5). `full` (default) keeps today's
16801
16900
  * exact behaviour. Callers may omit this field — the store defaults to
@@ -16803,6 +16902,27 @@ var DeviceEventQueryInput = object({
16803
16902
  projection: _enum(["full", "slim"]).optional()
16804
16903
  });
16805
16904
  var ObjectEventQueryInput = DeviceEventQueryInput.extend({ classFilter: string().optional() });
16905
+ var RecentTracksQueryInput = object({
16906
+ /** Devices to merge. An empty array yields `{ tracks: [], nextCursor: null }`. */
16907
+ deviceIds: array(number()),
16908
+ /** Window lower bound on `lastSeen` (inclusive). */
16909
+ since: number().optional(),
16910
+ /** Window upper bound on `lastSeen` (inclusive). */
16911
+ until: number().optional(),
16912
+ /** Page size. Default 200, max 1000. */
16913
+ limit: number().int().min(1).max(1e3).default(200),
16914
+ /** Opaque continuation cursor from a previous page's `nextCursor`.
16915
+ * Encodes the (lastSeen, trackId) sort position — treat as opaque. */
16916
+ cursor: string().optional(),
16917
+ /** See {@link TrackProjectionSchema}. Default `full`. */
16918
+ projection: TrackProjectionSchema.optional()
16919
+ });
16920
+ var RecentTracksPageSchema = object({
16921
+ /** Merged page, ordered by (`lastSeen` DESC, `trackId` DESC). */
16922
+ tracks: array(TrackSchema).readonly(),
16923
+ /** Cursor for the next page, or null when this page is the last. */
16924
+ nextCursor: string().nullable()
16925
+ });
16806
16926
  var KeyEventQueryInput = object({
16807
16927
  deviceId: number(),
16808
16928
  /** Window lower bound (track firstSeen ≥ since). */
@@ -16885,11 +17005,25 @@ DeviceType.Camera, method(object({ deviceId: number() }), array(TrackSchema).rea
16885
17005
  deviceId: number(),
16886
17006
  since: number().optional(),
16887
17007
  until: number().optional(),
16888
- limit: number().optional()
16889
- }), array(TrackSchema).readonly()), method(object({ deviceId: number() }), _void(), {
16890
- kind: "mutation",
16891
- auth: "admin"
16892
- }), method(DeviceEventQueryInput, array(MotionEventSchema).readonly()), method(ObjectEventQueryInput, array(ObjectEventSchema).readonly()), method(DeviceEventQueryInput, array(AudioEventSchema).readonly()), method(KeyEventQueryInput, array(KeyEventSchema).readonly()), method(object({
17008
+ limit: number().optional(),
17009
+ /** Spatial filter only tracks whose trajectory intersects the zone
17010
+ * (normalized 0..1 rect or polygon). SQL-prefiltered on the persisted
17011
+ * envelope columns, then precisely tested per position. Tracks with
17012
+ * an unknown envelope (no frame dims at persist time) always match. */
17013
+ zone: TrackZoneFilterSchema.optional(),
17014
+ /** See {@link TrackProjectionSchema}. Default `full` (backward
17015
+ * compatible — omitting the field keeps today's exact behaviour). */
17016
+ projection: TrackProjectionSchema.optional()
17017
+ }), array(TrackSchema).readonly()), method(RecentTracksQueryInput, RecentTracksPageSchema), method(object({ deviceId: number() }), _void(), {
17018
+ kind: "mutation",
17019
+ auth: "admin"
17020
+ }), method(DeviceEventQueryInput, array(MotionEventSchema).readonly()), method(ObjectEventQueryInput, array(ObjectEventSchema).readonly()), method(DeviceEventQueryInput, array(AudioEventSchema).readonly()), method(object({ deviceId: number() }), array(EventKindDescriptorSchema).readonly()), method(object({
17021
+ deviceId: number(),
17022
+ since: number().optional(),
17023
+ until: number().optional(),
17024
+ kinds: array(string()).optional(),
17025
+ limit: number().int().min(1).max(MAX_EVENT_QUERY_LIMIT).default(DEFAULT_EVENT_QUERY_LIMIT)
17026
+ }), array(SensorEventSchema).readonly()), method(KeyEventQueryInput, array(KeyEventSchema).readonly()), method(object({
16893
17027
  deviceId: number(),
16894
17028
  since: number(),
16895
17029
  until: number(),
@@ -20301,7 +20435,12 @@ var RecordingStorageUsageSchema = object({
20301
20435
  /**
20302
20436
  * Result of locating footage at a wall-clock instant for one device/profile.
20303
20437
  * `segment` carries the covering segment's window; `gap` reports the forward
20304
- * nearest covered edge (`null` past the end of footage / when none exists).
20438
+ * nearest covered edge (`null` past the end of footage / when none exists)
20439
+ * and the backward covered edge `prevEndMs` (exclusive end of the nearest
20440
+ * footage behind the epoch; `null` when none — optional so older providers
20441
+ * that omit it stay valid). `prevEndMs` lets a backward frame-step hop the
20442
+ * small inter-segment cracks (durMs under-covers the span to the next
20443
+ * startMs by ~11-17 ms) instead of no-opping at a segment head.
20305
20444
  */
20306
20445
  var LocateSegmentResultSchema = discriminatedUnion("kind", [object({
20307
20446
  kind: literal("segment"),
@@ -20310,7 +20449,8 @@ var LocateSegmentResultSchema = discriminatedUnion("kind", [object({
20310
20449
  bytes: number()
20311
20450
  }), object({
20312
20451
  kind: literal("gap"),
20313
- nearestEdgeMs: number().nullable()
20452
+ nearestEdgeMs: number().nullable(),
20453
+ prevEndMs: number().nullable().optional()
20314
20454
  })]);
20315
20455
  /** Raw bytes of one finalized footage segment (read off disk on the recording node). */
20316
20456
  var ReadSegmentBytesResultSchema = object({ data: _instanceof(Uint8Array) });
@@ -21879,6 +22019,12 @@ Object.freeze({
21879
22019
  addonId: null,
21880
22020
  access: "view"
21881
22021
  },
22022
+ "deviceManager.getLinkedDevices": {
22023
+ capName: "device-manager",
22024
+ capScope: "system",
22025
+ addonId: null,
22026
+ access: "view"
22027
+ },
21882
22028
  "deviceManager.getRoleDisplayDefaults": {
21883
22029
  capName: "device-manager",
21884
22030
  capScope: "system",
@@ -23433,6 +23579,12 @@ Object.freeze({
23433
23579
  addonId: null,
23434
23580
  access: "view"
23435
23581
  },
23582
+ "pipelineAnalytics.getSensorEvents": {
23583
+ capName: "pipeline-analytics",
23584
+ capScope: "device",
23585
+ addonId: null,
23586
+ access: "view"
23587
+ },
23436
23588
  "pipelineAnalytics.getTrack": {
23437
23589
  capName: "pipeline-analytics",
23438
23590
  capScope: "device",
@@ -23445,6 +23597,18 @@ Object.freeze({
23445
23597
  addonId: null,
23446
23598
  access: "view"
23447
23599
  },
23600
+ "pipelineAnalytics.listEventKinds": {
23601
+ capName: "pipeline-analytics",
23602
+ capScope: "device",
23603
+ addonId: null,
23604
+ access: "view"
23605
+ },
23606
+ "pipelineAnalytics.listRecentTracks": {
23607
+ capName: "pipeline-analytics",
23608
+ capScope: "device",
23609
+ addonId: null,
23610
+ access: "view"
23611
+ },
23448
23612
  "pipelineAnalytics.listTracks": {
23449
23613
  capName: "pipeline-analytics",
23450
23614
  capScope: "device",
package/dist/index.mjs CHANGED
@@ -1,7 +1,7 @@
1
1
  import fs from "node:fs";
2
2
  import path from "node:path";
3
3
  import { fileURLToPath } from "node:url";
4
- //#region ../types/dist/event-category-CFZs3jI4.mjs
4
+ //#region ../types/dist/event-category-H4AVePnn.mjs
5
5
  var EventCategory = /* @__PURE__ */ function(EventCategory) {
6
6
  EventCategory["SystemBoot"] = "system.boot";
7
7
  EventCategory["SystemAddonsReady"] = "system.addons-ready";
@@ -151,6 +151,9 @@ var EventCategory = /* @__PURE__ */ function(EventCategory) {
151
151
  EventCategory["RecordingSegmentWritten"] = "recording.segment.written";
152
152
  EventCategory["RecordingPolicyFallback"] = "recording.policy.fallback";
153
153
  EventCategory["RecordingRetentionCompleted"] = "recording.retention.completed";
154
+ /** Runner-sampled scrub thumbnail (~1/5 s/camera). Telemetry (D8): a lost
155
+ * thumb is a scrub gap the recorder's keyframe backfill covers. */
156
+ EventCategory["RecordingThumbSampled"] = "recording.thumb-sampled";
154
157
  EventCategory["DetectionEvent"] = "detection.event";
155
158
  EventCategory["SessionTrackNew"] = "session.track.new";
156
159
  EventCategory["SessionTrackExpired"] = "session.track.expired";
@@ -10304,7 +10307,7 @@ object({
10304
10307
  deviceId: number(),
10305
10308
  timestamp: number()
10306
10309
  });
10307
- DeviceType.Button;
10310
+ DeviceType.Button, DeviceType.Camera;
10308
10311
  /**
10309
10312
  * Enum-state sensor — a string value picked from a finite option set.
10310
10313
  * Drives HA `sensor` entries with `state_class: enum` (HVAC action
@@ -15100,6 +15103,14 @@ var ConfigEntrySchema = object({
15100
15103
  value: unknown(),
15101
15104
  description: string().optional()
15102
15105
  });
15106
+ var DeviceLinkModeSchema = _enum(["auto", "manual"]);
15107
+ /** One resolved linked device — the compact projection consumers need. */
15108
+ var LinkedDeviceSchema = object({
15109
+ deviceId: number(),
15110
+ name: string(),
15111
+ location: string().nullable(),
15112
+ features: array(string())
15113
+ });
15103
15114
  var SavedDeviceRowSchema = object({
15104
15115
  /** Numeric id reserved at allocateDeviceId time. */
15105
15116
  id: number(),
@@ -15321,7 +15332,10 @@ method(object({
15321
15332
  }), _void(), {
15322
15333
  kind: "mutation",
15323
15334
  auth: "admin"
15324
- }), 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({
15335
+ }), 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({
15336
+ mode: DeviceLinkModeSchema,
15337
+ devices: array(LinkedDeviceSchema)
15338
+ })), method(object({ deviceId: number() }), array(StreamSourceEntrySchema$1)), method(object({ deviceId: number() }), array(ConfigEntrySchema)), method(object({ deviceId: number() }), ConfigUISchemaOutput), method(object({
15325
15339
  deviceId: number(),
15326
15340
  values: record(string(), unknown())
15327
15341
  }), object({ success: literal(true) }), {
@@ -16590,6 +16604,61 @@ var EventKindSchema = _enum([
16590
16604
  "object",
16591
16605
  "audio"
16592
16606
  ]);
16607
+ /**
16608
+ * Spatial filter for `listTracks` — the rect + polygon variants of the shared
16609
+ * MaskShape vocabulary (see `mask-shape.ts`). Coordinates are NORMALIZED 0..1
16610
+ * of the camera frame (top-left origin), matching the drawing-plane editor.
16611
+ */
16612
+ var TrackZoneFilterSchema = discriminatedUnion("kind", [MaskRectShapeSchema, MaskPolygonShapeSchema]);
16613
+ /** Closed icon vocabulary so clients render a known glyph per kind. */
16614
+ var EventKindIconSchema = _enum([
16615
+ "motion",
16616
+ "audio",
16617
+ "person",
16618
+ "vehicle",
16619
+ "animal",
16620
+ "door",
16621
+ "pir",
16622
+ "smoke",
16623
+ "water",
16624
+ "button",
16625
+ "generic"
16626
+ ]);
16627
+ var EventKindCategorySchema = _enum([
16628
+ "motion",
16629
+ "audio",
16630
+ "detection",
16631
+ "sensor",
16632
+ "custom"
16633
+ ]);
16634
+ var EventKindDescriptorSchema = object({
16635
+ /** Stable kind id (e.g. 'motion', 'person', 'contact'). */
16636
+ kind: string(),
16637
+ label: string(),
16638
+ /** Hex color for timeline/legend rendering. */
16639
+ color: string(),
16640
+ icon: EventKindIconSchema,
16641
+ category: EventKindCategorySchema,
16642
+ /** Which cap + device contributes this kind. For built-ins the camera
16643
+ * itself; for sensor kinds the LINKED source device. */
16644
+ source: object({
16645
+ capName: string(),
16646
+ deviceId: number()
16647
+ })
16648
+ });
16649
+ var SensorEventSchema = object({
16650
+ id: string(),
16651
+ /** The CAMERA the event is attributed to (a sensor linked to N cameras
16652
+ * yields N rows, one per camera). */
16653
+ deviceId: number(),
16654
+ /** The linked sensor device whose state changed. */
16655
+ sourceDeviceId: number(),
16656
+ /** Event kind id — matches an `EventKindDescriptor.kind`. */
16657
+ kind: string(),
16658
+ /** Snapshot of the sensor cap's runtime-state slice at the change. */
16659
+ value: record(string(), unknown()).nullable(),
16660
+ timestamp: number()
16661
+ });
16593
16662
  var TrackPositionSchema = object({
16594
16663
  x: number(),
16595
16664
  y: number(),
@@ -16603,6 +16672,30 @@ var TrackSnapshotSchema = object({
16603
16672
  mediaKey: string()
16604
16673
  });
16605
16674
  /**
16675
+ * Normalized 0..1 trajectory envelope (min/max over every position bbox,
16676
+ * divided by the track's detection-frame dims), computed at persist time.
16677
+ * Absent when the frame dims were unknown when the track was persisted
16678
+ * (legacy rows / dims-less sources) and on active (in-RAM) tracks.
16679
+ */
16680
+ var TrackEnvelopeSchema = object({
16681
+ minX: number(),
16682
+ minY: number(),
16683
+ maxX: number(),
16684
+ maxY: number()
16685
+ });
16686
+ /**
16687
+ * Row projection for track list queries. `full` (default) returns the
16688
+ * complete Track including the frame-rate `positions[]` history and the
16689
+ * `snapshots[]` references — megabytes across a page of tracks. `slim`
16690
+ * keeps every scalar the list surfaces actually render (ids, class(es),
16691
+ * label / audioLabels / importance enrichment, firstSeen/lastSeen, state,
16692
+ * zonesVisited, bestEventId, envelope) and returns `positions` /
16693
+ * `snapshots` as EMPTY arrays — detail views re-fetch the full row via
16694
+ * `getTrack`. Mirrors the event-store `projection` convention
16695
+ * (`getObjectEvents` et al.).
16696
+ */
16697
+ var TrackProjectionSchema = _enum(["full", "slim"]);
16698
+ /**
16606
16699
  * One audio-classification label heard on the track's camera while the
16607
16700
  * track was alive, aggregated per label. An "episode" is one persisted
16608
16701
  * audio event (the confident-classification path: score ≥ the device's
@@ -16653,7 +16746,11 @@ var TrackSchema = object({
16653
16746
  /** Audio-classification labels heard on the camera during the track's
16654
16747
  * life (score ≥ device `classificationMinScore`), aggregated per label.
16655
16748
  * Absent on legacy rows / tracks with no confident audio. */
16656
- audioLabels: array(TrackAudioLabelSchema).readonly().optional()
16749
+ audioLabels: array(TrackAudioLabelSchema).readonly().optional(),
16750
+ /** Normalized 0..1 trajectory envelope (see {@link TrackEnvelopeSchema}).
16751
+ * Populated from the persisted envelope columns on historical reads;
16752
+ * absent on legacy rows, dims-less tracks and active (in-RAM) tracks. */
16753
+ envelope: TrackEnvelopeSchema.optional()
16657
16754
  });
16658
16755
  var BaseEventFields = {
16659
16756
  id: string(),
@@ -16763,11 +16860,13 @@ var MediaFileSchema = object({
16763
16860
  sizeBytes: number(),
16764
16861
  timestamp: number()
16765
16862
  });
16863
+ var DEFAULT_EVENT_QUERY_LIMIT = 1e3;
16864
+ var MAX_EVENT_QUERY_LIMIT = 5e3;
16766
16865
  var DeviceEventQueryInput = object({
16767
16866
  deviceId: number(),
16768
16867
  since: number().optional(),
16769
16868
  until: number().optional(),
16770
- limit: number().int().min(1).max(5e3).default(1e3),
16869
+ limit: number().int().min(1).max(MAX_EVENT_QUERY_LIMIT).default(DEFAULT_EVENT_QUERY_LIMIT),
16771
16870
  /** `slim` drops heavy JSON fields (regions/bbox/zones) and carries an
16772
16871
  * optional `mediaUrl` (populated by B5). `full` (default) keeps today's
16773
16872
  * exact behaviour. Callers may omit this field — the store defaults to
@@ -16775,6 +16874,27 @@ var DeviceEventQueryInput = object({
16775
16874
  projection: _enum(["full", "slim"]).optional()
16776
16875
  });
16777
16876
  var ObjectEventQueryInput = DeviceEventQueryInput.extend({ classFilter: string().optional() });
16877
+ var RecentTracksQueryInput = object({
16878
+ /** Devices to merge. An empty array yields `{ tracks: [], nextCursor: null }`. */
16879
+ deviceIds: array(number()),
16880
+ /** Window lower bound on `lastSeen` (inclusive). */
16881
+ since: number().optional(),
16882
+ /** Window upper bound on `lastSeen` (inclusive). */
16883
+ until: number().optional(),
16884
+ /** Page size. Default 200, max 1000. */
16885
+ limit: number().int().min(1).max(1e3).default(200),
16886
+ /** Opaque continuation cursor from a previous page's `nextCursor`.
16887
+ * Encodes the (lastSeen, trackId) sort position — treat as opaque. */
16888
+ cursor: string().optional(),
16889
+ /** See {@link TrackProjectionSchema}. Default `full`. */
16890
+ projection: TrackProjectionSchema.optional()
16891
+ });
16892
+ var RecentTracksPageSchema = object({
16893
+ /** Merged page, ordered by (`lastSeen` DESC, `trackId` DESC). */
16894
+ tracks: array(TrackSchema).readonly(),
16895
+ /** Cursor for the next page, or null when this page is the last. */
16896
+ nextCursor: string().nullable()
16897
+ });
16778
16898
  var KeyEventQueryInput = object({
16779
16899
  deviceId: number(),
16780
16900
  /** Window lower bound (track firstSeen ≥ since). */
@@ -16857,11 +16977,25 @@ DeviceType.Camera, method(object({ deviceId: number() }), array(TrackSchema).rea
16857
16977
  deviceId: number(),
16858
16978
  since: number().optional(),
16859
16979
  until: number().optional(),
16860
- limit: number().optional()
16861
- }), array(TrackSchema).readonly()), method(object({ deviceId: number() }), _void(), {
16862
- kind: "mutation",
16863
- auth: "admin"
16864
- }), method(DeviceEventQueryInput, array(MotionEventSchema).readonly()), method(ObjectEventQueryInput, array(ObjectEventSchema).readonly()), method(DeviceEventQueryInput, array(AudioEventSchema).readonly()), method(KeyEventQueryInput, array(KeyEventSchema).readonly()), method(object({
16980
+ limit: number().optional(),
16981
+ /** Spatial filter only tracks whose trajectory intersects the zone
16982
+ * (normalized 0..1 rect or polygon). SQL-prefiltered on the persisted
16983
+ * envelope columns, then precisely tested per position. Tracks with
16984
+ * an unknown envelope (no frame dims at persist time) always match. */
16985
+ zone: TrackZoneFilterSchema.optional(),
16986
+ /** See {@link TrackProjectionSchema}. Default `full` (backward
16987
+ * compatible — omitting the field keeps today's exact behaviour). */
16988
+ projection: TrackProjectionSchema.optional()
16989
+ }), array(TrackSchema).readonly()), method(RecentTracksQueryInput, RecentTracksPageSchema), method(object({ deviceId: number() }), _void(), {
16990
+ kind: "mutation",
16991
+ auth: "admin"
16992
+ }), method(DeviceEventQueryInput, array(MotionEventSchema).readonly()), method(ObjectEventQueryInput, array(ObjectEventSchema).readonly()), method(DeviceEventQueryInput, array(AudioEventSchema).readonly()), method(object({ deviceId: number() }), array(EventKindDescriptorSchema).readonly()), method(object({
16993
+ deviceId: number(),
16994
+ since: number().optional(),
16995
+ until: number().optional(),
16996
+ kinds: array(string()).optional(),
16997
+ limit: number().int().min(1).max(MAX_EVENT_QUERY_LIMIT).default(DEFAULT_EVENT_QUERY_LIMIT)
16998
+ }), array(SensorEventSchema).readonly()), method(KeyEventQueryInput, array(KeyEventSchema).readonly()), method(object({
16865
16999
  deviceId: number(),
16866
17000
  since: number(),
16867
17001
  until: number(),
@@ -20273,7 +20407,12 @@ var RecordingStorageUsageSchema = object({
20273
20407
  /**
20274
20408
  * Result of locating footage at a wall-clock instant for one device/profile.
20275
20409
  * `segment` carries the covering segment's window; `gap` reports the forward
20276
- * nearest covered edge (`null` past the end of footage / when none exists).
20410
+ * nearest covered edge (`null` past the end of footage / when none exists)
20411
+ * and the backward covered edge `prevEndMs` (exclusive end of the nearest
20412
+ * footage behind the epoch; `null` when none — optional so older providers
20413
+ * that omit it stay valid). `prevEndMs` lets a backward frame-step hop the
20414
+ * small inter-segment cracks (durMs under-covers the span to the next
20415
+ * startMs by ~11-17 ms) instead of no-opping at a segment head.
20277
20416
  */
20278
20417
  var LocateSegmentResultSchema = discriminatedUnion("kind", [object({
20279
20418
  kind: literal("segment"),
@@ -20282,7 +20421,8 @@ var LocateSegmentResultSchema = discriminatedUnion("kind", [object({
20282
20421
  bytes: number()
20283
20422
  }), object({
20284
20423
  kind: literal("gap"),
20285
- nearestEdgeMs: number().nullable()
20424
+ nearestEdgeMs: number().nullable(),
20425
+ prevEndMs: number().nullable().optional()
20286
20426
  })]);
20287
20427
  /** Raw bytes of one finalized footage segment (read off disk on the recording node). */
20288
20428
  var ReadSegmentBytesResultSchema = object({ data: _instanceof(Uint8Array) });
@@ -21851,6 +21991,12 @@ Object.freeze({
21851
21991
  addonId: null,
21852
21992
  access: "view"
21853
21993
  },
21994
+ "deviceManager.getLinkedDevices": {
21995
+ capName: "device-manager",
21996
+ capScope: "system",
21997
+ addonId: null,
21998
+ access: "view"
21999
+ },
21854
22000
  "deviceManager.getRoleDisplayDefaults": {
21855
22001
  capName: "device-manager",
21856
22002
  capScope: "system",
@@ -23405,6 +23551,12 @@ Object.freeze({
23405
23551
  addonId: null,
23406
23552
  access: "view"
23407
23553
  },
23554
+ "pipelineAnalytics.getSensorEvents": {
23555
+ capName: "pipeline-analytics",
23556
+ capScope: "device",
23557
+ addonId: null,
23558
+ access: "view"
23559
+ },
23408
23560
  "pipelineAnalytics.getTrack": {
23409
23561
  capName: "pipeline-analytics",
23410
23562
  capScope: "device",
@@ -23417,6 +23569,18 @@ Object.freeze({
23417
23569
  addonId: null,
23418
23570
  access: "view"
23419
23571
  },
23572
+ "pipelineAnalytics.listEventKinds": {
23573
+ capName: "pipeline-analytics",
23574
+ capScope: "device",
23575
+ addonId: null,
23576
+ access: "view"
23577
+ },
23578
+ "pipelineAnalytics.listRecentTracks": {
23579
+ capName: "pipeline-analytics",
23580
+ capScope: "device",
23581
+ addonId: null,
23582
+ access: "view"
23583
+ },
23420
23584
  "pipelineAnalytics.listTracks": {
23421
23585
  capName: "pipeline-analytics",
23422
23586
  capScope: "device",
@@ -30,7 +30,7 @@ async function d(e) {
30
30
  }
31
31
  }
32
32
  async function f() {
33
- return l ||= d(() => import("./_virtual_mf-localSharedImportMap___mfe_internal__addon_pipeline_orchestrator_widgets-yuOR48RL.mjs")).catch((e) => {
33
+ return l ||= d(() => import("./_virtual_mf-localSharedImportMap___mfe_internal__addon_pipeline_orchestrator_widgets-BEIKqOjC.mjs")).catch((e) => {
34
34
  throw l = void 0, e;
35
35
  }), l;
36
36
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@camstack/addon-pipeline-orchestrator",
3
- "version": "1.1.48",
3
+ "version": "1.1.49",
4
4
  "description": "Hub-side camera-to-agent load balancer — tracks runner capacity and dispatches attachCamera calls to the optimal pipeline-runner instance",
5
5
  "keywords": [
6
6
  "camstack",