@camstack/addon-post-analysis 1.1.30 → 1.1.32

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.
@@ -1,4 +1,4 @@
1
- //#region ../types/dist/event-category-CFZs3jI4.mjs
1
+ //#region ../types/dist/event-category-H4AVePnn.mjs
2
2
  var EventCategory = /* @__PURE__ */ function(EventCategory) {
3
3
  EventCategory["SystemBoot"] = "system.boot";
4
4
  EventCategory["SystemAddonsReady"] = "system.addons-ready";
@@ -148,6 +148,9 @@ var EventCategory = /* @__PURE__ */ function(EventCategory) {
148
148
  EventCategory["RecordingSegmentWritten"] = "recording.segment.written";
149
149
  EventCategory["RecordingPolicyFallback"] = "recording.policy.fallback";
150
150
  EventCategory["RecordingRetentionCompleted"] = "recording.retention.completed";
151
+ /** Runner-sampled scrub thumbnail (~1/5 s/camera). Telemetry (D8): a lost
152
+ * thumb is a scrub gap the recorder's keyframe backfill covers. */
153
+ EventCategory["RecordingThumbSampled"] = "recording.thumb-sampled";
151
154
  EventCategory["DetectionEvent"] = "detection.event";
152
155
  EventCategory["SessionTrackNew"] = "session.track.new";
153
156
  EventCategory["SessionTrackExpired"] = "session.track.expired";
@@ -7248,6 +7251,24 @@ var RecordingRetentionSchema = object({
7248
7251
  maxSizeGb: number().min(0).optional()
7249
7252
  });
7250
7253
  /**
7254
+ * Scrub-thumbnail fidelity preset — the single per-camera selector bundling the
7255
+ * sprite tile RESOLUTION + JPEG QUALITY the recorder packs timeline-scrub
7256
+ * previews at. Five graduated steps; absent on a config = `standard` (the
7257
+ * shipped default, matching `sheet-geometry`/`sheet-composer`).
7258
+ *
7259
+ * Existing sheets are IMMUTABLE — a changed preset applies to NEW windows only.
7260
+ * Each window's index sidecar carries its own tile dims, so a camera whose
7261
+ * preset changed over time renders every historical window at the dims it was
7262
+ * written with.
7263
+ */
7264
+ var ScrubThumbnailPresetSchema = _enum([
7265
+ "minimal",
7266
+ "low",
7267
+ "standard",
7268
+ "high",
7269
+ "max"
7270
+ ]);
7271
+ /**
7251
7272
  * The full per-camera recording intent — the wire shape of a RecordingTarget.
7252
7273
  *
7253
7274
  * `mode` is the authoritative storage choice; `schedule`/`triggers`/`pre`/`post`
@@ -7284,7 +7305,14 @@ var RecordingConfigSchema = object({
7284
7305
  * derived into bands once via `migrateConfigToBands`.
7285
7306
  */
7286
7307
  bands: array(RecordingBandSchema).optional(),
7287
- retention: RecordingRetentionSchema.optional()
7308
+ retention: RecordingRetentionSchema.optional(),
7309
+ /**
7310
+ * Per-camera scrub-thumbnail fidelity preset (resolution + JPEG quality for
7311
+ * timeline-scrub sprite previews). Absent = `standard`. Applies to NEW
7312
+ * windows only — existing sheets are immutable, and each window's index
7313
+ * carries its own tile dims so mixed-preset history renders correctly.
7314
+ */
7315
+ scrubThumbnails: ScrubThumbnailPresetSchema.optional()
7288
7316
  });
7289
7317
  /**
7290
7318
  * `StorageLocationType` — an addon-declared id that identifies the *kind* of
@@ -9919,7 +9947,7 @@ object({
9919
9947
  deviceId: number(),
9920
9948
  timestamp: number()
9921
9949
  });
9922
- DeviceType.Button;
9950
+ DeviceType.Button, DeviceType.Camera;
9923
9951
  /**
9924
9952
  * Enum-state sensor — a string value picked from a finite option set.
9925
9953
  * Drives HA `sensor` entries with `state_class: enum` (HVAC action
@@ -14344,6 +14372,14 @@ var ConfigEntrySchema = object({
14344
14372
  value: unknown(),
14345
14373
  description: string().optional()
14346
14374
  });
14375
+ var DeviceLinkModeSchema = _enum(["auto", "manual"]);
14376
+ /** One resolved linked device — the compact projection consumers need. */
14377
+ var LinkedDeviceSchema = object({
14378
+ deviceId: number(),
14379
+ name: string(),
14380
+ location: string().nullable(),
14381
+ features: array(string())
14382
+ });
14347
14383
  var SavedDeviceRowSchema = object({
14348
14384
  /** Numeric id reserved at allocateDeviceId time. */
14349
14385
  id: number(),
@@ -14565,7 +14601,10 @@ method(object({
14565
14601
  }), _void(), {
14566
14602
  kind: "mutation",
14567
14603
  auth: "admin"
14568
- }), 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({
14604
+ }), 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({
14605
+ mode: DeviceLinkModeSchema,
14606
+ devices: array(LinkedDeviceSchema)
14607
+ })), method(object({ deviceId: number() }), array(StreamSourceEntrySchema$1)), method(object({ deviceId: number() }), array(ConfigEntrySchema)), method(object({ deviceId: number() }), ConfigUISchemaOutput), method(object({
14569
14608
  deviceId: number(),
14570
14609
  values: record(string(), unknown())
14571
14610
  }), object({ success: literal(true) }), {
@@ -15844,6 +15883,61 @@ var EventKindSchema = _enum([
15844
15883
  "object",
15845
15884
  "audio"
15846
15885
  ]);
15886
+ /**
15887
+ * Spatial filter for `listTracks` — the rect + polygon variants of the shared
15888
+ * MaskShape vocabulary (see `mask-shape.ts`). Coordinates are NORMALIZED 0..1
15889
+ * of the camera frame (top-left origin), matching the drawing-plane editor.
15890
+ */
15891
+ var TrackZoneFilterSchema = discriminatedUnion("kind", [MaskRectShapeSchema, MaskPolygonShapeSchema]);
15892
+ /** Closed icon vocabulary so clients render a known glyph per kind. */
15893
+ var EventKindIconSchema = _enum([
15894
+ "motion",
15895
+ "audio",
15896
+ "person",
15897
+ "vehicle",
15898
+ "animal",
15899
+ "door",
15900
+ "pir",
15901
+ "smoke",
15902
+ "water",
15903
+ "button",
15904
+ "generic"
15905
+ ]);
15906
+ var EventKindCategorySchema = _enum([
15907
+ "motion",
15908
+ "audio",
15909
+ "detection",
15910
+ "sensor",
15911
+ "custom"
15912
+ ]);
15913
+ var EventKindDescriptorSchema = object({
15914
+ /** Stable kind id (e.g. 'motion', 'person', 'contact'). */
15915
+ kind: string(),
15916
+ label: string(),
15917
+ /** Hex color for timeline/legend rendering. */
15918
+ color: string(),
15919
+ icon: EventKindIconSchema,
15920
+ category: EventKindCategorySchema,
15921
+ /** Which cap + device contributes this kind. For built-ins the camera
15922
+ * itself; for sensor kinds the LINKED source device. */
15923
+ source: object({
15924
+ capName: string(),
15925
+ deviceId: number()
15926
+ })
15927
+ });
15928
+ var SensorEventSchema = object({
15929
+ id: string(),
15930
+ /** The CAMERA the event is attributed to (a sensor linked to N cameras
15931
+ * yields N rows, one per camera). */
15932
+ deviceId: number(),
15933
+ /** The linked sensor device whose state changed. */
15934
+ sourceDeviceId: number(),
15935
+ /** Event kind id — matches an `EventKindDescriptor.kind`. */
15936
+ kind: string(),
15937
+ /** Snapshot of the sensor cap's runtime-state slice at the change. */
15938
+ value: record(string(), unknown()).nullable(),
15939
+ timestamp: number()
15940
+ });
15847
15941
  var TrackPositionSchema = object({
15848
15942
  x: number(),
15849
15943
  y: number(),
@@ -15857,6 +15951,30 @@ var TrackSnapshotSchema = object({
15857
15951
  mediaKey: string()
15858
15952
  });
15859
15953
  /**
15954
+ * Normalized 0..1 trajectory envelope (min/max over every position bbox,
15955
+ * divided by the track's detection-frame dims), computed at persist time.
15956
+ * Absent when the frame dims were unknown when the track was persisted
15957
+ * (legacy rows / dims-less sources) and on active (in-RAM) tracks.
15958
+ */
15959
+ var TrackEnvelopeSchema = object({
15960
+ minX: number(),
15961
+ minY: number(),
15962
+ maxX: number(),
15963
+ maxY: number()
15964
+ });
15965
+ /**
15966
+ * Row projection for track list queries. `full` (default) returns the
15967
+ * complete Track including the frame-rate `positions[]` history and the
15968
+ * `snapshots[]` references — megabytes across a page of tracks. `slim`
15969
+ * keeps every scalar the list surfaces actually render (ids, class(es),
15970
+ * label / audioLabels / importance enrichment, firstSeen/lastSeen, state,
15971
+ * zonesVisited, bestEventId, envelope) and returns `positions` /
15972
+ * `snapshots` as EMPTY arrays — detail views re-fetch the full row via
15973
+ * `getTrack`. Mirrors the event-store `projection` convention
15974
+ * (`getObjectEvents` et al.).
15975
+ */
15976
+ var TrackProjectionSchema = _enum(["full", "slim"]);
15977
+ /**
15860
15978
  * One audio-classification label heard on the track's camera while the
15861
15979
  * track was alive, aggregated per label. An "episode" is one persisted
15862
15980
  * audio event (the confident-classification path: score ≥ the device's
@@ -15907,7 +16025,11 @@ var TrackSchema = object({
15907
16025
  /** Audio-classification labels heard on the camera during the track's
15908
16026
  * life (score ≥ device `classificationMinScore`), aggregated per label.
15909
16027
  * Absent on legacy rows / tracks with no confident audio. */
15910
- audioLabels: array(TrackAudioLabelSchema).readonly().optional()
16028
+ audioLabels: array(TrackAudioLabelSchema).readonly().optional(),
16029
+ /** Normalized 0..1 trajectory envelope (see {@link TrackEnvelopeSchema}).
16030
+ * Populated from the persisted envelope columns on historical reads;
16031
+ * absent on legacy rows, dims-less tracks and active (in-RAM) tracks. */
16032
+ envelope: TrackEnvelopeSchema.optional()
15911
16033
  });
15912
16034
  var BaseEventFields = {
15913
16035
  id: string(),
@@ -16017,11 +16139,13 @@ var MediaFileSchema = object({
16017
16139
  sizeBytes: number(),
16018
16140
  timestamp: number()
16019
16141
  });
16142
+ var DEFAULT_EVENT_QUERY_LIMIT = 1e3;
16143
+ var MAX_EVENT_QUERY_LIMIT = 5e3;
16020
16144
  var DeviceEventQueryInput = object({
16021
16145
  deviceId: number(),
16022
16146
  since: number().optional(),
16023
16147
  until: number().optional(),
16024
- limit: number().int().min(1).max(5e3).default(1e3),
16148
+ limit: number().int().min(1).max(MAX_EVENT_QUERY_LIMIT).default(DEFAULT_EVENT_QUERY_LIMIT),
16025
16149
  /** `slim` drops heavy JSON fields (regions/bbox/zones) and carries an
16026
16150
  * optional `mediaUrl` (populated by B5). `full` (default) keeps today's
16027
16151
  * exact behaviour. Callers may omit this field — the store defaults to
@@ -16029,6 +16153,27 @@ var DeviceEventQueryInput = object({
16029
16153
  projection: _enum(["full", "slim"]).optional()
16030
16154
  });
16031
16155
  var ObjectEventQueryInput = DeviceEventQueryInput.extend({ classFilter: string().optional() });
16156
+ var RecentTracksQueryInput = object({
16157
+ /** Devices to merge. An empty array yields `{ tracks: [], nextCursor: null }`. */
16158
+ deviceIds: array(number()),
16159
+ /** Window lower bound on `lastSeen` (inclusive). */
16160
+ since: number().optional(),
16161
+ /** Window upper bound on `lastSeen` (inclusive). */
16162
+ until: number().optional(),
16163
+ /** Page size. Default 200, max 1000. */
16164
+ limit: number().int().min(1).max(1e3).default(200),
16165
+ /** Opaque continuation cursor from a previous page's `nextCursor`.
16166
+ * Encodes the (lastSeen, trackId) sort position — treat as opaque. */
16167
+ cursor: string().optional(),
16168
+ /** See {@link TrackProjectionSchema}. Default `full`. */
16169
+ projection: TrackProjectionSchema.optional()
16170
+ });
16171
+ var RecentTracksPageSchema = object({
16172
+ /** Merged page, ordered by (`lastSeen` DESC, `trackId` DESC). */
16173
+ tracks: array(TrackSchema).readonly(),
16174
+ /** Cursor for the next page, or null when this page is the last. */
16175
+ nextCursor: string().nullable()
16176
+ });
16032
16177
  var KeyEventQueryInput = object({
16033
16178
  deviceId: number(),
16034
16179
  /** Window lower bound (track firstSeen ≥ since). */
@@ -16125,8 +16270,27 @@ var pipelineAnalyticsCapability = {
16125
16270
  deviceId: number(),
16126
16271
  since: number().optional(),
16127
16272
  until: number().optional(),
16128
- limit: number().optional()
16273
+ limit: number().optional(),
16274
+ /** Spatial filter — only tracks whose trajectory intersects the zone
16275
+ * (normalized 0..1 rect or polygon). SQL-prefiltered on the persisted
16276
+ * envelope columns, then precisely tested per position. Tracks with
16277
+ * an unknown envelope (no frame dims at persist time) always match. */
16278
+ zone: TrackZoneFilterSchema.optional(),
16279
+ /** See {@link TrackProjectionSchema}. Default `full` (backward
16280
+ * compatible — omitting the field keeps today's exact behaviour). */
16281
+ projection: TrackProjectionSchema.optional()
16129
16282
  }), array(TrackSchema).readonly()),
16283
+ /**
16284
+ * Batched cluster-wide track listing — ONE call for the events page /
16285
+ * reel first paint instead of a per-camera `listTracks` fan-out. Merges
16286
+ * the persisted completed tracks of every requested device, sorted by
16287
+ * `lastSeen` DESC with a stable (lastSeen, trackId) cursor. Per-device
16288
+ * indexed pages (`idx_tracks_device_lastSeen`) are k-way merged
16289
+ * provider-side; `projection: 'slim'` drops the heavy `positions[]` /
16290
+ * `snapshots[]` JSON (returned as empty arrays). Active in-RAM tracks
16291
+ * are not included (same contract as `listTracks`).
16292
+ */
16293
+ listRecentTracks: method(RecentTracksQueryInput, RecentTracksPageSchema),
16130
16294
  clearTracks: method(object({ deviceId: number() }), _void(), {
16131
16295
  kind: "mutation",
16132
16296
  auth: "admin"
@@ -16135,6 +16299,26 @@ var pipelineAnalyticsCapability = {
16135
16299
  getObjectEvents: method(ObjectEventQueryInput, array(ObjectEventSchema).readonly()),
16136
16300
  getAudioEvents: method(DeviceEventQueryInput, array(AudioEventSchema).readonly()),
16137
16301
  /**
16302
+ * Every event kind the device can produce: built-ins (motion + audio),
16303
+ * detection classes actually observed for the device (from the track
16304
+ * history), and sensor kinds contributed by LINKED devices (resolved via
16305
+ * `device-manager.getLinkedDevices`, mapped through `EVENT_KIND_BY_CAP`).
16306
+ */
16307
+ listEventKinds: method(object({ deviceId: number() }), array(EventKindDescriptorSchema).readonly()),
16308
+ /**
16309
+ * Sensor-event history for a camera: state changes of LINKED sensor
16310
+ * devices, attributed to the camera at ingest time (one row per linked
16311
+ * camera). Mirrors `getAudioEvents` query semantics; `kinds` narrows to
16312
+ * a kind subset.
16313
+ */
16314
+ getSensorEvents: method(object({
16315
+ deviceId: number(),
16316
+ since: number().optional(),
16317
+ until: number().optional(),
16318
+ kinds: array(string()).optional(),
16319
+ limit: number().int().min(1).max(MAX_EVENT_QUERY_LIMIT).default(DEFAULT_EVENT_QUERY_LIMIT)
16320
+ }), array(SensorEventSchema).readonly()),
16321
+ /**
16138
16322
  * Importance-ranked highlights for a device+window. Queries completed
16139
16323
  * tracks by (deviceId, firstSeen ∈ [since,until]), scores each (or reuses
16140
16324
  * the persisted score), filters by minImportance/classFilter, orders by
@@ -16279,6 +16463,54 @@ var pipelineAnalyticsCapability = {
16279
16463
  }) }
16280
16464
  }
16281
16465
  };
16466
+ /**
16467
+ * Sensor cap name → static event-kind descriptor. A linked device
16468
+ * contributes one entry per bound cap present in this map.
16469
+ */
16470
+ var EVENT_KIND_BY_CAP = {
16471
+ contact: {
16472
+ kind: "contact",
16473
+ label: "Contact",
16474
+ color: "#f59e0b",
16475
+ icon: "door",
16476
+ category: "sensor"
16477
+ },
16478
+ flood: {
16479
+ kind: "flood",
16480
+ label: "Water leak",
16481
+ color: "#3b82f6",
16482
+ icon: "water",
16483
+ category: "sensor"
16484
+ },
16485
+ gas: {
16486
+ kind: "gas",
16487
+ label: "Gas",
16488
+ color: "#ef4444",
16489
+ icon: "smoke",
16490
+ category: "sensor"
16491
+ },
16492
+ "carbon-monoxide": {
16493
+ kind: "carbon-monoxide",
16494
+ label: "Carbon monoxide",
16495
+ color: "#dc2626",
16496
+ icon: "smoke",
16497
+ category: "sensor"
16498
+ },
16499
+ "enum-sensor": {
16500
+ kind: "enum-sensor",
16501
+ label: "Sensor state",
16502
+ color: "#8b5cf6",
16503
+ icon: "generic",
16504
+ category: "sensor"
16505
+ },
16506
+ "event-emitter": {
16507
+ kind: "device-event",
16508
+ label: "Device event",
16509
+ color: "#10b981",
16510
+ icon: "button",
16511
+ category: "sensor"
16512
+ }
16513
+ };
16282
16514
  var CameraPipelineConfigSchema = object({
16283
16515
  engine: PipelineEngineChoiceSchema.optional(),
16284
16516
  steps: array(PipelineStepInputSchema).readonly(),
@@ -19488,7 +19720,12 @@ var RecordingStorageUsageSchema = object({
19488
19720
  /**
19489
19721
  * Result of locating footage at a wall-clock instant for one device/profile.
19490
19722
  * `segment` carries the covering segment's window; `gap` reports the forward
19491
- * nearest covered edge (`null` past the end of footage / when none exists).
19723
+ * nearest covered edge (`null` past the end of footage / when none exists)
19724
+ * and the backward covered edge `prevEndMs` (exclusive end of the nearest
19725
+ * footage behind the epoch; `null` when none — optional so older providers
19726
+ * that omit it stay valid). `prevEndMs` lets a backward frame-step hop the
19727
+ * small inter-segment cracks (durMs under-covers the span to the next
19728
+ * startMs by ~11-17 ms) instead of no-opping at a segment head.
19492
19729
  */
19493
19730
  var LocateSegmentResultSchema = discriminatedUnion("kind", [object({
19494
19731
  kind: literal("segment"),
@@ -19497,7 +19734,8 @@ var LocateSegmentResultSchema = discriminatedUnion("kind", [object({
19497
19734
  bytes: number()
19498
19735
  }), object({
19499
19736
  kind: literal("gap"),
19500
- nearestEdgeMs: number().nullable()
19737
+ nearestEdgeMs: number().nullable(),
19738
+ prevEndMs: number().nullable().optional()
19501
19739
  })]);
19502
19740
  /** Raw bytes of one finalized footage segment (read off disk on the recording node). */
19503
19741
  var ReadSegmentBytesResultSchema = object({ data: _instanceof(Uint8Array) });
@@ -21066,6 +21304,12 @@ Object.freeze({
21066
21304
  addonId: null,
21067
21305
  access: "view"
21068
21306
  },
21307
+ "deviceManager.getLinkedDevices": {
21308
+ capName: "device-manager",
21309
+ capScope: "system",
21310
+ addonId: null,
21311
+ access: "view"
21312
+ },
21069
21313
  "deviceManager.getRoleDisplayDefaults": {
21070
21314
  capName: "device-manager",
21071
21315
  capScope: "system",
@@ -22620,6 +22864,12 @@ Object.freeze({
22620
22864
  addonId: null,
22621
22865
  access: "view"
22622
22866
  },
22867
+ "pipelineAnalytics.getSensorEvents": {
22868
+ capName: "pipeline-analytics",
22869
+ capScope: "device",
22870
+ addonId: null,
22871
+ access: "view"
22872
+ },
22623
22873
  "pipelineAnalytics.getTrack": {
22624
22874
  capName: "pipeline-analytics",
22625
22875
  capScope: "device",
@@ -22632,6 +22882,18 @@ Object.freeze({
22632
22882
  addonId: null,
22633
22883
  access: "view"
22634
22884
  },
22885
+ "pipelineAnalytics.listEventKinds": {
22886
+ capName: "pipeline-analytics",
22887
+ capScope: "device",
22888
+ addonId: null,
22889
+ access: "view"
22890
+ },
22891
+ "pipelineAnalytics.listRecentTracks": {
22892
+ capName: "pipeline-analytics",
22893
+ capScope: "device",
22894
+ addonId: null,
22895
+ access: "view"
22896
+ },
22635
22897
  "pipelineAnalytics.listTracks": {
22636
22898
  capName: "pipeline-analytics",
22637
22899
  capScope: "device",
@@ -24619,4 +24881,4 @@ object({
24619
24881
  schemaVersion: literal(1)
24620
24882
  });
24621
24883
  //#endregion
24622
- export { EventCategory as S, hydrateSchema as _, embeddingEncoderCapability as a, object as b, nodePin as c, videoclipsCapability as d, zoneAnalyticsCapability as f, createEvent as g, DeviceType as h, cosineSimilarity as i, pipelineAnalyticsCapability as l, BaseAddon as m, addonWidgetsSourceCapability as n, faceGalleryCapability as o, errMsg as p, audioMetricsCapability as r, hfModelUrl as s, EVENT_PAD_MS as t, plateGalleryCapability as u, boolean as v, string as x, number as y };
24884
+ export { EventCategory as C, string as S, createEvent as _, cosineSimilarity as a, number as b, hfModelUrl as c, plateGalleryCapability as d, videoclipsCapability as f, DeviceType as g, BaseAddon as h, audioMetricsCapability as i, nodePin as l, errMsg as m, EVENT_PAD_MS as n, embeddingEncoderCapability as o, zoneAnalyticsCapability as p, addonWidgetsSourceCapability as r, faceGalleryCapability as s, EVENT_KIND_BY_CAP as t, pipelineAnalyticsCapability as u, hydrateSchema as v, object as x, boolean as y };