@camstack/types 1.1.46 → 1.1.48

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.
@@ -265,7 +265,7 @@ export interface DeviceProxy {
265
265
  readonly cameraPipelineConfig: Pick<InferDeviceProxyCap<typeof cameraPipelineConfigCapability>, 'getDeviceSettingsContribution' | 'getDeviceLiveContribution' | 'applyDeviceSettingsPatch'>;
266
266
  readonly deviceAdoption: Pick<InferDeviceProxyCap<typeof deviceAdoptionCapability>, 'getStatus'>;
267
267
  readonly deviceExport: Pick<InferDeviceProxyCap<typeof deviceExportCapability>, 'getDeviceSettingsContribution' | 'getDeviceLiveContribution' | 'applyDeviceSettingsPatch'>;
268
- readonly deviceManager: Pick<InferDeviceProxyCap<typeof deviceManagerCapability>, 'loadConfig' | 'loadRuntimeState' | 'loadMeta' | 'setName' | 'setLocation' | 'setType' | 'setIntegrationId' | 'setLinkDeviceId' | 'setPrimaryChildEntityId' | 'setChildLayout' | 'setDeviceLinks' | 'setDisplay' | 'getWireableFields' | 'setRole' | 'applyInitialMeta' | 'setMetadata' | 'setDisabled' | 'getDevice' | 'getStreamSources' | 'getConfigSchema' | 'getSettingsSchema' | 'updateConfig' | 'enable' | 'disable' | 'remove' | 'getStreamProfileMap' | 'setStreamProfileMap' | 'probeStreams' | 'getBindings' | 'getAllBindings' | 'setWrapperActive' | 'getDeviceSettingsAggregate' | 'getDeviceLiveInfoAggregate' | 'getDeviceAggregate' | 'runDeviceAction' | 'updateDeviceField' | 'updateDeviceFieldsBatch' | 'testField' | 'getDeviceStatusAggregate'>;
268
+ readonly deviceManager: Pick<InferDeviceProxyCap<typeof deviceManagerCapability>, 'loadConfig' | 'loadRuntimeState' | 'loadMeta' | 'setName' | 'setLocation' | 'setType' | 'setIntegrationId' | 'setLinkDeviceId' | 'setPrimaryChildEntityId' | 'setChildLayout' | 'setDeviceLinks' | 'setDisplay' | 'getWireableFields' | 'setRole' | 'applyInitialMeta' | 'setMetadata' | 'setDisabled' | 'getDevice' | 'getLinkedDevices' | 'getStreamSources' | 'getConfigSchema' | 'getSettingsSchema' | 'updateConfig' | 'enable' | 'disable' | 'remove' | 'getStreamProfileMap' | 'setStreamProfileMap' | 'probeStreams' | 'getBindings' | 'getAllBindings' | 'setWrapperActive' | 'getDeviceSettingsAggregate' | 'getDeviceLiveInfoAggregate' | 'getDeviceAggregate' | 'runDeviceAction' | 'updateDeviceField' | 'updateDeviceFieldsBatch' | 'testField' | 'getDeviceStatusAggregate' | 'getDeviceSettingsContribution' | 'getDeviceLiveContribution' | 'applyDeviceSettingsPatch'>;
269
269
  readonly deviceState: Pick<InferDeviceProxyCap<typeof deviceStateCapability>, 'getSnapshot' | 'getCapSlice' | 'setCapSlice'>;
270
270
  readonly faceGallery: Pick<InferDeviceProxyCap<typeof faceGalleryCapability>, 'getFaceByTrack'>;
271
271
  readonly networkQuality: Pick<InferDeviceProxyCap<typeof networkQualityCapability>, 'getDeviceStats' | 'reportClientStats'>;
@@ -6,7 +6,7 @@
6
6
  * scope+access check inside `protectedProcedure` (see
7
7
  * `server/backend/src/api/trpc/trpc.middleware.ts`).
8
8
  *
9
- * Coverage: 785 method paths across 115 capabilities.
9
+ * Coverage: 789 method paths across 115 capabilities.
10
10
  */
11
11
  import type { CapabilityMethodAccess } from '../capabilities/capability-definition.js';
12
12
  export interface MethodAccessRecord {
package/dist/index.js CHANGED
@@ -1,6 +1,6 @@
1
1
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
- const require_sleep = require("./sleep-Vh_bux78.js");
3
- const require_event_category = require("./event-category-BXd6yeJi.js");
2
+ const require_sleep = require("./sleep-BoTIF1d4.js");
3
+ const require_event_category = require("./event-category-AkBNxg_X.js");
4
4
  const require_enums = require("./enums.js");
5
5
  const require_err_msg = require("./err-msg-COpsHMw2.js");
6
6
  let zod = require("zod");
@@ -870,6 +870,83 @@ var RecordingRetentionSchema = zod.z.object({
870
870
  maxSizeGb: zod.z.number().min(0).optional()
871
871
  });
872
872
  /**
873
+ * Scrub-thumbnail fidelity preset — the single per-camera selector bundling the
874
+ * sprite tile RESOLUTION + JPEG QUALITY the recorder packs timeline-scrub
875
+ * previews at. Five graduated steps; absent on a config = `standard` (the
876
+ * shipped default, matching `sheet-geometry`/`sheet-composer`).
877
+ *
878
+ * Existing sheets are IMMUTABLE — a changed preset applies to NEW windows only.
879
+ * Each window's index sidecar carries its own tile dims, so a camera whose
880
+ * preset changed over time renders every historical window at the dims it was
881
+ * written with.
882
+ */
883
+ var ScrubThumbnailPresetSchema = zod.z.enum([
884
+ "minimal",
885
+ "low",
886
+ "standard",
887
+ "high",
888
+ "max"
889
+ ]);
890
+ /** The default preset when a config omits `scrubThumbnails`. */
891
+ var DEFAULT_SCRUB_THUMBNAIL_PRESET = "standard";
892
+ /**
893
+ * Preset → tile geometry + JPEG quality. Every step is 16:9; the graduated
894
+ * ladder trades sheet size (and remote fetch cost) for scrub crispness.
895
+ * `standard` matches the shipped `sheet-geometry`/`sheet-composer` defaults
896
+ * (480×270 q72), so an unset config is byte-identical to today. The map is
897
+ * strictly monotone in resolution AND quality across the ordered steps.
898
+ */
899
+ var SCRUB_THUMBNAIL_PRESETS = {
900
+ minimal: {
901
+ tileWidth: 240,
902
+ tileHeight: 135,
903
+ quality: 55
904
+ },
905
+ low: {
906
+ tileWidth: 320,
907
+ tileHeight: 180,
908
+ quality: 60
909
+ },
910
+ standard: {
911
+ tileWidth: 480,
912
+ tileHeight: 270,
913
+ quality: 72
914
+ },
915
+ high: {
916
+ tileWidth: 640,
917
+ tileHeight: 360,
918
+ quality: 80
919
+ },
920
+ max: {
921
+ tileWidth: 960,
922
+ tileHeight: 540,
923
+ quality: 85
924
+ }
925
+ };
926
+ /** Human labels for each preset (resolution-tagged), for settings UIs. */
927
+ var SCRUB_THUMBNAIL_PRESET_LABELS = {
928
+ minimal: "Minimal (240p)",
929
+ low: "Low (320p)",
930
+ standard: "Standard (480p)",
931
+ high: "High (640p)",
932
+ max: "Max (960p)"
933
+ };
934
+ /** Ordered low→high so a UI can render the ladder in graduated order. */
935
+ var SCRUB_THUMBNAIL_PRESET_ORDER = [
936
+ "minimal",
937
+ "low",
938
+ "standard",
939
+ "high",
940
+ "max"
941
+ ];
942
+ /**
943
+ * Resolve the geometry for a recording config's scrub-thumbnail preset,
944
+ * defaulting to `standard` when unset. Pure — no I/O.
945
+ */
946
+ function resolveScrubThumbnailGeometry(preset) {
947
+ return SCRUB_THUMBNAIL_PRESETS[preset ?? "standard"];
948
+ }
949
+ /**
873
950
  * The full per-camera recording intent — the wire shape of a RecordingTarget.
874
951
  *
875
952
  * `mode` is the authoritative storage choice; `schedule`/`triggers`/`pre`/`post`
@@ -906,7 +983,14 @@ var RecordingConfigSchema = zod.z.object({
906
983
  * derived into bands once via `migrateConfigToBands`.
907
984
  */
908
985
  bands: zod.z.array(RecordingBandSchema).optional(),
909
- retention: RecordingRetentionSchema.optional()
986
+ retention: RecordingRetentionSchema.optional(),
987
+ /**
988
+ * Per-camera scrub-thumbnail fidelity preset (resolution + JPEG quality for
989
+ * timeline-scrub sprite previews). Absent = `standard`. Applies to NEW
990
+ * windows only — existing sheets are immutable, and each window's index
991
+ * carries its own tile dims so mixed-preset history renders correctly.
992
+ */
993
+ scrubThumbnails: ScrubThumbnailPresetSchema.optional()
910
994
  });
911
995
  //#endregion
912
996
  //#region src/interfaces/recording-config-migrate.ts
@@ -6487,10 +6571,23 @@ var deviceDiscoveryCapability = {
6487
6571
  //#endregion
6488
6572
  //#region src/capabilities/doorbell.cap.ts
6489
6573
  /**
6490
- * Doorbell button cap. Installed on a `DeviceType.Button` accessory
6491
- * with `role: DeviceRole.Doorbell`. Emits an `onPressed` event every
6492
- * time the firmware pushes a ring; status tracks the last press and
6493
- * a pressCount since start (diagnostic).
6574
+ * Doorbell button cap. Two kinds of providers coexist behind this cap
6575
+ * name (same pattern as `snapshot`):
6576
+ *
6577
+ * - **Native** providers: registered per-device by device-driver
6578
+ * addons via `ctx.registerNativeCap` — either on a
6579
+ * `DeviceType.Button` accessory with `role: DeviceRole.Doorbell`,
6580
+ * or directly on the camera (Reolink registers at camera level).
6581
+ * Emits an `onPressed` event every time the firmware pushes a
6582
+ * ring; status tracks the last press and a pressCount since start
6583
+ * (diagnostic).
6584
+ *
6585
+ * - **Wrapper** provider: the `virtual-doorbell` system builtin
6586
+ * (`@camstack/system/builtins/doorbell`). Turns ANY binary-ish
6587
+ * device (contact / switch / event-emitter …) into a doorbell for
6588
+ * a camera. `defaultActive: false` — the operator explicitly binds
6589
+ * it per camera in the device-bindings UI, then picks the source
6590
+ * device + trigger in the per-device settings.
6494
6591
  *
6495
6592
  * The DeviceEventPropagator re-emits `onPressed` on the camera parent
6496
6593
  * — subscribers listening at the camera level receive ring events
@@ -6511,7 +6608,10 @@ var doorbellCapability = {
6511
6608
  scope: "device",
6512
6609
  deviceNative: true,
6513
6610
  mode: "singleton",
6514
- deviceTypes: [require_sleep.DeviceType.Button],
6611
+ kind: "wrapper",
6612
+ defaultActive: false,
6613
+ deviceTypes: [require_sleep.DeviceType.Button, require_sleep.DeviceType.Camera],
6614
+ exposesDeviceSettings: true,
6515
6615
  methods: {},
6516
6616
  events: {
6517
6617
  /**
@@ -16058,6 +16158,14 @@ var ConfigEntrySchema = zod.z.object({
16058
16158
  value: zod.z.unknown(),
16059
16159
  description: zod.z.string().optional()
16060
16160
  });
16161
+ var DeviceLinkModeSchema = zod.z.enum(["auto", "manual"]);
16162
+ /** One resolved linked device — the compact projection consumers need. */
16163
+ var LinkedDeviceSchema = zod.z.object({
16164
+ deviceId: zod.z.number(),
16165
+ name: zod.z.string(),
16166
+ location: zod.z.string().nullable(),
16167
+ features: zod.z.array(zod.z.string())
16168
+ });
16061
16169
  var SavedDeviceRowSchema = zod.z.object({
16062
16170
  /** Numeric id reserved at allocateDeviceId time. */
16063
16171
  id: zod.z.number(),
@@ -16165,6 +16273,7 @@ var deviceManagerCapability = {
16165
16273
  name: "device-manager",
16166
16274
  scope: "system",
16167
16275
  mode: "singleton",
16276
+ exposesDeviceSettings: true,
16168
16277
  methods: {
16169
16278
  /** Reserve (or re-resolve) a progressive numeric id for `(addonId, stableId)`.
16170
16279
  * Idempotent: returns the existing id if one is already persisted for the
@@ -16415,6 +16524,19 @@ var deviceManagerCapability = {
16415
16524
  getDevice: require_sleep.method(zod.z.object({ deviceId: zod.z.number() }), DeviceInfoSchema.nullable()),
16416
16525
  /** List children of a parent device (by parent numeric id). */
16417
16526
  getChildren: require_sleep.method(zod.z.object({ parentDeviceId: zod.z.number() }), zod.z.array(DeviceInfoSchema)),
16527
+ /**
16528
+ * Resolve the devices LINKED to a camera — the single policy authority
16529
+ * both consumers call (viewer devices panel + pipeline-analytics event
16530
+ * kinds/ingest). Device-tree children are ALWAYS included; mode 'auto'
16531
+ * (default) adds every device sharing the camera's non-null `location`,
16532
+ * mode 'manual' adds the persisted manual list instead. Excludes the
16533
+ * camera itself; deduped. Configuration is standard per-device settings
16534
+ * (see the module docblock) — there are no bespoke link mutations.
16535
+ */
16536
+ getLinkedDevices: require_sleep.method(zod.z.object({ deviceId: zod.z.number() }), zod.z.object({
16537
+ mode: DeviceLinkModeSchema,
16538
+ devices: zod.z.array(LinkedDeviceSchema)
16539
+ })),
16418
16540
  /** Get stream sources for a camera device. */
16419
16541
  getStreamSources: require_sleep.method(zod.z.object({ deviceId: zod.z.number() }), zod.z.array(require_sleep.StreamSourceEntrySchema)),
16420
16542
  /** Get config entries (key + value + description) for a device. */
@@ -18179,6 +18301,61 @@ var EventKindSchema = zod.z.enum([
18179
18301
  "object",
18180
18302
  "audio"
18181
18303
  ]);
18304
+ /**
18305
+ * Spatial filter for `listTracks` — the rect + polygon variants of the shared
18306
+ * MaskShape vocabulary (see `mask-shape.ts`). Coordinates are NORMALIZED 0..1
18307
+ * of the camera frame (top-left origin), matching the drawing-plane editor.
18308
+ */
18309
+ var TrackZoneFilterSchema = zod.z.discriminatedUnion("kind", [MaskRectShapeSchema, MaskPolygonShapeSchema]);
18310
+ /** Closed icon vocabulary so clients render a known glyph per kind. */
18311
+ var EventKindIconSchema = zod.z.enum([
18312
+ "motion",
18313
+ "audio",
18314
+ "person",
18315
+ "vehicle",
18316
+ "animal",
18317
+ "door",
18318
+ "pir",
18319
+ "smoke",
18320
+ "water",
18321
+ "button",
18322
+ "generic"
18323
+ ]);
18324
+ var EventKindCategorySchema = zod.z.enum([
18325
+ "motion",
18326
+ "audio",
18327
+ "detection",
18328
+ "sensor",
18329
+ "custom"
18330
+ ]);
18331
+ var EventKindDescriptorSchema = zod.z.object({
18332
+ /** Stable kind id (e.g. 'motion', 'person', 'contact'). */
18333
+ kind: zod.z.string(),
18334
+ label: zod.z.string(),
18335
+ /** Hex color for timeline/legend rendering. */
18336
+ color: zod.z.string(),
18337
+ icon: EventKindIconSchema,
18338
+ category: EventKindCategorySchema,
18339
+ /** Which cap + device contributes this kind. For built-ins the camera
18340
+ * itself; for sensor kinds the LINKED source device. */
18341
+ source: zod.z.object({
18342
+ capName: zod.z.string(),
18343
+ deviceId: zod.z.number()
18344
+ })
18345
+ });
18346
+ var SensorEventSchema = zod.z.object({
18347
+ id: zod.z.string(),
18348
+ /** The CAMERA the event is attributed to (a sensor linked to N cameras
18349
+ * yields N rows, one per camera). */
18350
+ deviceId: zod.z.number(),
18351
+ /** The linked sensor device whose state changed. */
18352
+ sourceDeviceId: zod.z.number(),
18353
+ /** Event kind id — matches an `EventKindDescriptor.kind`. */
18354
+ kind: zod.z.string(),
18355
+ /** Snapshot of the sensor cap's runtime-state slice at the change. */
18356
+ value: zod.z.record(zod.z.string(), zod.z.unknown()).nullable(),
18357
+ timestamp: zod.z.number()
18358
+ });
18182
18359
  var TrackPositionSchema = zod.z.object({
18183
18360
  x: zod.z.number(),
18184
18361
  y: zod.z.number(),
@@ -18192,6 +18369,30 @@ var TrackSnapshotSchema = zod.z.object({
18192
18369
  mediaKey: zod.z.string()
18193
18370
  });
18194
18371
  /**
18372
+ * Normalized 0..1 trajectory envelope (min/max over every position bbox,
18373
+ * divided by the track's detection-frame dims), computed at persist time.
18374
+ * Absent when the frame dims were unknown when the track was persisted
18375
+ * (legacy rows / dims-less sources) and on active (in-RAM) tracks.
18376
+ */
18377
+ var TrackEnvelopeSchema = zod.z.object({
18378
+ minX: zod.z.number(),
18379
+ minY: zod.z.number(),
18380
+ maxX: zod.z.number(),
18381
+ maxY: zod.z.number()
18382
+ });
18383
+ /**
18384
+ * Row projection for track list queries. `full` (default) returns the
18385
+ * complete Track including the frame-rate `positions[]` history and the
18386
+ * `snapshots[]` references — megabytes across a page of tracks. `slim`
18387
+ * keeps every scalar the list surfaces actually render (ids, class(es),
18388
+ * label / audioLabels / importance enrichment, firstSeen/lastSeen, state,
18389
+ * zonesVisited, bestEventId, envelope) and returns `positions` /
18390
+ * `snapshots` as EMPTY arrays — detail views re-fetch the full row via
18391
+ * `getTrack`. Mirrors the event-store `projection` convention
18392
+ * (`getObjectEvents` et al.).
18393
+ */
18394
+ var TrackProjectionSchema = zod.z.enum(["full", "slim"]);
18395
+ /**
18195
18396
  * One audio-classification label heard on the track's camera while the
18196
18397
  * track was alive, aggregated per label. An "episode" is one persisted
18197
18398
  * audio event (the confident-classification path: score ≥ the device's
@@ -18242,7 +18443,11 @@ var TrackSchema = zod.z.object({
18242
18443
  /** Audio-classification labels heard on the camera during the track's
18243
18444
  * life (score ≥ device `classificationMinScore`), aggregated per label.
18244
18445
  * Absent on legacy rows / tracks with no confident audio. */
18245
- audioLabels: zod.z.array(TrackAudioLabelSchema).readonly().optional()
18446
+ audioLabels: zod.z.array(TrackAudioLabelSchema).readonly().optional(),
18447
+ /** Normalized 0..1 trajectory envelope (see {@link TrackEnvelopeSchema}).
18448
+ * Populated from the persisted envelope columns on historical reads;
18449
+ * absent on legacy rows, dims-less tracks and active (in-RAM) tracks. */
18450
+ envelope: TrackEnvelopeSchema.optional()
18246
18451
  });
18247
18452
  var BaseEventFields = {
18248
18453
  id: zod.z.string(),
@@ -18352,11 +18557,13 @@ var MediaFileSchema = zod.z.object({
18352
18557
  sizeBytes: zod.z.number(),
18353
18558
  timestamp: zod.z.number()
18354
18559
  });
18560
+ var DEFAULT_EVENT_QUERY_LIMIT = 1e3;
18561
+ var MAX_EVENT_QUERY_LIMIT = 5e3;
18355
18562
  var DeviceEventQueryInput = zod.z.object({
18356
18563
  deviceId: zod.z.number(),
18357
18564
  since: zod.z.number().optional(),
18358
18565
  until: zod.z.number().optional(),
18359
- limit: zod.z.number().int().min(1).max(5e3).default(1e3),
18566
+ limit: zod.z.number().int().min(1).max(MAX_EVENT_QUERY_LIMIT).default(DEFAULT_EVENT_QUERY_LIMIT),
18360
18567
  /** `slim` drops heavy JSON fields (regions/bbox/zones) and carries an
18361
18568
  * optional `mediaUrl` (populated by B5). `full` (default) keeps today's
18362
18569
  * exact behaviour. Callers may omit this field — the store defaults to
@@ -18364,6 +18571,27 @@ var DeviceEventQueryInput = zod.z.object({
18364
18571
  projection: zod.z.enum(["full", "slim"]).optional()
18365
18572
  });
18366
18573
  var ObjectEventQueryInput = DeviceEventQueryInput.extend({ classFilter: zod.z.string().optional() });
18574
+ var RecentTracksQueryInput = zod.z.object({
18575
+ /** Devices to merge. An empty array yields `{ tracks: [], nextCursor: null }`. */
18576
+ deviceIds: zod.z.array(zod.z.number()),
18577
+ /** Window lower bound on `lastSeen` (inclusive). */
18578
+ since: zod.z.number().optional(),
18579
+ /** Window upper bound on `lastSeen` (inclusive). */
18580
+ until: zod.z.number().optional(),
18581
+ /** Page size. Default 200, max 1000. */
18582
+ limit: zod.z.number().int().min(1).max(1e3).default(200),
18583
+ /** Opaque continuation cursor from a previous page's `nextCursor`.
18584
+ * Encodes the (lastSeen, trackId) sort position — treat as opaque. */
18585
+ cursor: zod.z.string().optional(),
18586
+ /** See {@link TrackProjectionSchema}. Default `full`. */
18587
+ projection: TrackProjectionSchema.optional()
18588
+ });
18589
+ var RecentTracksPageSchema = zod.z.object({
18590
+ /** Merged page, ordered by (`lastSeen` DESC, `trackId` DESC). */
18591
+ tracks: zod.z.array(TrackSchema).readonly(),
18592
+ /** Cursor for the next page, or null when this page is the last. */
18593
+ nextCursor: zod.z.string().nullable()
18594
+ });
18367
18595
  var KeyEventQueryInput = zod.z.object({
18368
18596
  deviceId: zod.z.number(),
18369
18597
  /** Window lower bound (track firstSeen ≥ since). */
@@ -18460,8 +18688,27 @@ var pipelineAnalyticsCapability = {
18460
18688
  deviceId: zod.z.number(),
18461
18689
  since: zod.z.number().optional(),
18462
18690
  until: zod.z.number().optional(),
18463
- limit: zod.z.number().optional()
18691
+ limit: zod.z.number().optional(),
18692
+ /** Spatial filter — only tracks whose trajectory intersects the zone
18693
+ * (normalized 0..1 rect or polygon). SQL-prefiltered on the persisted
18694
+ * envelope columns, then precisely tested per position. Tracks with
18695
+ * an unknown envelope (no frame dims at persist time) always match. */
18696
+ zone: TrackZoneFilterSchema.optional(),
18697
+ /** See {@link TrackProjectionSchema}. Default `full` (backward
18698
+ * compatible — omitting the field keeps today's exact behaviour). */
18699
+ projection: TrackProjectionSchema.optional()
18464
18700
  }), zod.z.array(TrackSchema).readonly()),
18701
+ /**
18702
+ * Batched cluster-wide track listing — ONE call for the events page /
18703
+ * reel first paint instead of a per-camera `listTracks` fan-out. Merges
18704
+ * the persisted completed tracks of every requested device, sorted by
18705
+ * `lastSeen` DESC with a stable (lastSeen, trackId) cursor. Per-device
18706
+ * indexed pages (`idx_tracks_device_lastSeen`) are k-way merged
18707
+ * provider-side; `projection: 'slim'` drops the heavy `positions[]` /
18708
+ * `snapshots[]` JSON (returned as empty arrays). Active in-RAM tracks
18709
+ * are not included (same contract as `listTracks`).
18710
+ */
18711
+ listRecentTracks: require_sleep.method(RecentTracksQueryInput, RecentTracksPageSchema),
18465
18712
  clearTracks: require_sleep.method(zod.z.object({ deviceId: zod.z.number() }), zod.z.void(), {
18466
18713
  kind: "mutation",
18467
18714
  auth: "admin"
@@ -18470,6 +18717,26 @@ var pipelineAnalyticsCapability = {
18470
18717
  getObjectEvents: require_sleep.method(ObjectEventQueryInput, zod.z.array(ObjectEventSchema).readonly()),
18471
18718
  getAudioEvents: require_sleep.method(DeviceEventQueryInput, zod.z.array(AudioEventSchema).readonly()),
18472
18719
  /**
18720
+ * Every event kind the device can produce: built-ins (motion + audio),
18721
+ * detection classes actually observed for the device (from the track
18722
+ * history), and sensor kinds contributed by LINKED devices (resolved via
18723
+ * `device-manager.getLinkedDevices`, mapped through `EVENT_KIND_BY_CAP`).
18724
+ */
18725
+ listEventKinds: require_sleep.method(zod.z.object({ deviceId: zod.z.number() }), zod.z.array(EventKindDescriptorSchema).readonly()),
18726
+ /**
18727
+ * Sensor-event history for a camera: state changes of LINKED sensor
18728
+ * devices, attributed to the camera at ingest time (one row per linked
18729
+ * camera). Mirrors `getAudioEvents` query semantics; `kinds` narrows to
18730
+ * a kind subset.
18731
+ */
18732
+ getSensorEvents: require_sleep.method(zod.z.object({
18733
+ deviceId: zod.z.number(),
18734
+ since: zod.z.number().optional(),
18735
+ until: zod.z.number().optional(),
18736
+ kinds: zod.z.array(zod.z.string()).optional(),
18737
+ limit: zod.z.number().int().min(1).max(MAX_EVENT_QUERY_LIMIT).default(DEFAULT_EVENT_QUERY_LIMIT)
18738
+ }), zod.z.array(SensorEventSchema).readonly()),
18739
+ /**
18473
18740
  * Importance-ranked highlights for a device+window. Queries completed
18474
18741
  * tracks by (deviceId, firstSeen ∈ [since,until]), scores each (or reuses
18475
18742
  * the persisted score), filters by minImportance/classFilter, orders by
@@ -18615,6 +18882,56 @@ var pipelineAnalyticsCapability = {
18615
18882
  }
18616
18883
  };
18617
18884
  //#endregion
18885
+ //#region src/capabilities/sensor-event-kinds.ts
18886
+ /**
18887
+ * Sensor cap name → static event-kind descriptor. A linked device
18888
+ * contributes one entry per bound cap present in this map.
18889
+ */
18890
+ var EVENT_KIND_BY_CAP = {
18891
+ contact: {
18892
+ kind: "contact",
18893
+ label: "Contact",
18894
+ color: "#f59e0b",
18895
+ icon: "door",
18896
+ category: "sensor"
18897
+ },
18898
+ flood: {
18899
+ kind: "flood",
18900
+ label: "Water leak",
18901
+ color: "#3b82f6",
18902
+ icon: "water",
18903
+ category: "sensor"
18904
+ },
18905
+ gas: {
18906
+ kind: "gas",
18907
+ label: "Gas",
18908
+ color: "#ef4444",
18909
+ icon: "smoke",
18910
+ category: "sensor"
18911
+ },
18912
+ "carbon-monoxide": {
18913
+ kind: "carbon-monoxide",
18914
+ label: "Carbon monoxide",
18915
+ color: "#dc2626",
18916
+ icon: "smoke",
18917
+ category: "sensor"
18918
+ },
18919
+ "enum-sensor": {
18920
+ kind: "enum-sensor",
18921
+ label: "Sensor state",
18922
+ color: "#8b5cf6",
18923
+ icon: "generic",
18924
+ category: "sensor"
18925
+ },
18926
+ "event-emitter": {
18927
+ kind: "device-event",
18928
+ label: "Device event",
18929
+ color: "#10b981",
18930
+ icon: "button",
18931
+ category: "sensor"
18932
+ }
18933
+ };
18934
+ //#endregion
18618
18935
  //#region src/capabilities/pipeline-orchestrator.cap.ts
18619
18936
  var CameraPipelineConfigSchema = zod.z.object({
18620
18937
  engine: PipelineEngineChoiceSchema.optional(),
@@ -23148,7 +23465,12 @@ var RecordingStorageUsageSchema = zod.z.object({
23148
23465
  /**
23149
23466
  * Result of locating footage at a wall-clock instant for one device/profile.
23150
23467
  * `segment` carries the covering segment's window; `gap` reports the forward
23151
- * nearest covered edge (`null` past the end of footage / when none exists).
23468
+ * nearest covered edge (`null` past the end of footage / when none exists)
23469
+ * and the backward covered edge `prevEndMs` (exclusive end of the nearest
23470
+ * footage behind the epoch; `null` when none — optional so older providers
23471
+ * that omit it stay valid). `prevEndMs` lets a backward frame-step hop the
23472
+ * small inter-segment cracks (durMs under-covers the span to the next
23473
+ * startMs by ~11-17 ms) instead of no-opping at a segment head.
23152
23474
  */
23153
23475
  var LocateSegmentResultSchema = zod.z.discriminatedUnion("kind", [zod.z.object({
23154
23476
  kind: zod.z.literal("segment"),
@@ -23157,7 +23479,8 @@ var LocateSegmentResultSchema = zod.z.discriminatedUnion("kind", [zod.z.object({
23157
23479
  bytes: zod.z.number()
23158
23480
  }), zod.z.object({
23159
23481
  kind: zod.z.literal("gap"),
23160
- nearestEdgeMs: zod.z.number().nullable()
23482
+ nearestEdgeMs: zod.z.number().nullable(),
23483
+ prevEndMs: zod.z.number().nullable().optional()
23161
23484
  })]);
23162
23485
  /** Raw bytes of one finalized footage segment (read off disk on the recording node). */
23163
23486
  var ReadSegmentBytesResultSchema = zod.z.object({ data: zod.z.instanceof(Uint8Array) });
@@ -26073,6 +26396,12 @@ var METHOD_ACCESS_MAP = Object.freeze({
26073
26396
  addonId: null,
26074
26397
  access: "view"
26075
26398
  },
26399
+ "deviceManager.getLinkedDevices": {
26400
+ capName: "device-manager",
26401
+ capScope: "system",
26402
+ addonId: null,
26403
+ access: "view"
26404
+ },
26076
26405
  "deviceManager.getRoleDisplayDefaults": {
26077
26406
  capName: "device-manager",
26078
26407
  capScope: "system",
@@ -27627,6 +27956,12 @@ var METHOD_ACCESS_MAP = Object.freeze({
27627
27956
  addonId: null,
27628
27957
  access: "view"
27629
27958
  },
27959
+ "pipelineAnalytics.getSensorEvents": {
27960
+ capName: "pipeline-analytics",
27961
+ capScope: "device",
27962
+ addonId: null,
27963
+ access: "view"
27964
+ },
27630
27965
  "pipelineAnalytics.getTrack": {
27631
27966
  capName: "pipeline-analytics",
27632
27967
  capScope: "device",
@@ -27639,6 +27974,18 @@ var METHOD_ACCESS_MAP = Object.freeze({
27639
27974
  addonId: null,
27640
27975
  access: "view"
27641
27976
  },
27977
+ "pipelineAnalytics.listEventKinds": {
27978
+ capName: "pipeline-analytics",
27979
+ capScope: "device",
27980
+ addonId: null,
27981
+ access: "view"
27982
+ },
27983
+ "pipelineAnalytics.listRecentTracks": {
27984
+ capName: "pipeline-analytics",
27985
+ capScope: "device",
27986
+ addonId: null,
27987
+ access: "view"
27988
+ },
27642
27989
  "pipelineAnalytics.listTracks": {
27643
27990
  capName: "pipeline-analytics",
27644
27991
  capScope: "device",
@@ -30562,6 +30909,7 @@ exports.DEFAULT_AUDIO_ANALYZER_CONFIG = DEFAULT_AUDIO_ANALYZER_CONFIG;
30562
30909
  exports.DEFAULT_DECODER_HWACCEL_CONFIG = DEFAULT_DECODER_HWACCEL_CONFIG;
30563
30910
  exports.DEFAULT_FEATURES = DEFAULT_FEATURES;
30564
30911
  exports.DEFAULT_RETENTION = DEFAULT_RETENTION;
30912
+ exports.DEFAULT_SCRUB_THUMBNAIL_PRESET = DEFAULT_SCRUB_THUMBNAIL_PRESET;
30565
30913
  exports.DEVICE_CAP_NAMES = DEVICE_CAP_NAMES;
30566
30914
  exports.DEVICE_PROFILES = DEVICE_PROFILES;
30567
30915
  exports.DEVICE_SETTINGS_CONTRIBUTION_METHODS = require_sleep.DEVICE_SETTINGS_CONTRIBUTION_METHODS;
@@ -30585,6 +30933,7 @@ exports.DeviceExportStatusSchema = DeviceExportStatusSchema;
30585
30933
  exports.DeviceExportUnexposeInputSchema = UnexposeInputSchema;
30586
30934
  exports.DeviceFeature = require_sleep.DeviceFeature;
30587
30935
  exports.DeviceInfoSchema = DeviceInfoSchema;
30936
+ exports.DeviceLinkModeSchema = DeviceLinkModeSchema;
30588
30937
  exports.DeviceNetworkStatsSchema = DeviceNetworkStatsSchema;
30589
30938
  exports.DeviceRole = require_sleep.DeviceRole;
30590
30939
  exports.DeviceRuntimeState = DeviceRuntimeState;
@@ -30597,6 +30946,7 @@ exports.DiscoveredTargetSchema = DiscoveredTargetSchema;
30597
30946
  exports.DisposerChain = require_sleep.DisposerChain;
30598
30947
  exports.DoorbellPressEventSchema = DoorbellPressEventSchema;
30599
30948
  exports.DoorbellStatusSchema = DoorbellStatusSchema;
30949
+ exports.EVENT_KIND_BY_CAP = EVENT_KIND_BY_CAP;
30600
30950
  exports.EVENT_PAD_MS = EVENT_PAD_MS;
30601
30951
  exports.EXPRESSION_BUILTINS = EXPRESSION_BUILTINS;
30602
30952
  exports.EXPRESSION_BUILTIN_NAMES = EXPRESSION_BUILTIN_NAMES;
@@ -30615,6 +30965,9 @@ exports.EventCategory = require_event_category.EventCategory;
30615
30965
  exports.EventEmitterStatusSchema = EventEmitterStatusSchema;
30616
30966
  exports.EventFireSchema = EventFireSchema;
30617
30967
  exports.EventItemSchema = EventItemSchema;
30968
+ exports.EventKindCategorySchema = EventKindCategorySchema;
30969
+ exports.EventKindDescriptorSchema = EventKindDescriptorSchema;
30970
+ exports.EventKindIconSchema = EventKindIconSchema;
30618
30971
  exports.EventKindSchema = EventKindSchema;
30619
30972
  exports.EventSourceType = require_enums.EventSourceType$1;
30620
30973
  exports.ExportSetupFieldSchema = ExportSetupFieldSchema;
@@ -30659,6 +31012,7 @@ exports.KeyEventSchema = KeyEventSchema;
30659
31012
  exports.LabelDefinitionSchema = LabelDefinitionSchema;
30660
31013
  exports.LawnMowerActivitySchema = LawnMowerActivitySchema;
30661
31014
  exports.LawnMowerControlStatusSchema = LawnMowerControlStatusSchema;
31015
+ exports.LinkedDeviceSchema = LinkedDeviceSchema;
30662
31016
  exports.LlmDefaultSchema = LlmDefaultSchema;
30663
31017
  exports.LlmDefaultSelectorSchema = LlmDefaultSelectorSchema;
30664
31018
  exports.LlmErrorCodeSchema = LlmErrorCodeSchema;
@@ -30816,6 +31170,8 @@ exports.RawStateResultSchema = require_sleep.RawStateResultSchema;
30816
31170
  exports.ReadSegmentBytesResultSchema = ReadSegmentBytesResultSchema;
30817
31171
  exports.ReadinessRegistry = require_sleep.ReadinessRegistry;
30818
31172
  exports.ReadinessTimeoutError = require_sleep.ReadinessTimeoutError;
31173
+ exports.RecentTracksPageSchema = RecentTracksPageSchema;
31174
+ exports.RecentTracksQueryInput = RecentTracksQueryInput;
30819
31175
  exports.RecordingAvailabilitySchema = RecordingAvailabilitySchema;
30820
31176
  exports.RecordingBandModeSchema = RecordingBandModeSchema;
30821
31177
  exports.RecordingBandSchema = RecordingBandSchema;
@@ -30847,6 +31203,9 @@ exports.RunnerFrameSourceSchema = RunnerFrameSourceSchema;
30847
31203
  exports.RunnerLocalLoadSchema = RunnerLocalLoadSchema;
30848
31204
  exports.RunnerLocalMetricsSchema = RunnerLocalMetricsSchema;
30849
31205
  exports.SCOPE_PRESETS = SCOPE_PRESETS;
31206
+ exports.SCRUB_THUMBNAIL_PRESETS = SCRUB_THUMBNAIL_PRESETS;
31207
+ exports.SCRUB_THUMBNAIL_PRESET_LABELS = SCRUB_THUMBNAIL_PRESET_LABELS;
31208
+ exports.SCRUB_THUMBNAIL_PRESET_ORDER = SCRUB_THUMBNAIL_PRESET_ORDER;
30850
31209
  exports.SOURCE_INFO_METADATA_KEY = SOURCE_INFO_METADATA_KEY;
30851
31210
  exports.STREAM_PROFILE_META = STREAM_PROFILE_META;
30852
31211
  exports.STREAM_QUALITY_LABELS = STREAM_QUALITY_LABELS;
@@ -30862,10 +31221,12 @@ exports.ScopedTokenSchema = ScopedTokenSchema;
30862
31221
  exports.ScopedTokenSummarySchema = ScopedTokenSummarySchema;
30863
31222
  exports.ScoredObjectEventSchema = ScoredObjectEventSchema;
30864
31223
  exports.ScriptRunnerStatusSchema = ScriptRunnerStatusSchema;
31224
+ exports.ScrubThumbnailPresetSchema = ScrubThumbnailPresetSchema;
30865
31225
  exports.SearchResultSchema = SearchResultSchema;
30866
31226
  exports.SendEmailInputSchema = SendEmailInputSchema;
30867
31227
  exports.SendEmailResultSchema = SendEmailResultSchema;
30868
31228
  exports.SendResultSchema = SendResultSchema;
31229
+ exports.SensorEventSchema = SensorEventSchema;
30869
31230
  exports.ServerBootModeSchema = ServerBootModeSchema;
30870
31231
  exports.ServerPackageStatusSchema = ServerPackageStatusSchema;
30871
31232
  exports.ServerRollbackInfoSchema = ServerRollbackInfoSchema;
@@ -30934,8 +31295,11 @@ exports.TopologyNodeSchema = TopologyNodeSchema;
30934
31295
  exports.TopologyProcessSchema = TopologyProcessSchema;
30935
31296
  exports.TopologyServiceSchema = TopologyServiceSchema;
30936
31297
  exports.TrackCascadeCountsSchema = TrackCascadeCountsSchema;
31298
+ exports.TrackEnvelopeSchema = TrackEnvelopeSchema;
31299
+ exports.TrackProjectionSchema = TrackProjectionSchema;
30937
31300
  exports.TrackSchema = TrackSchema;
30938
31301
  exports.TrackStateSchema = TrackStateSchema;
31302
+ exports.TrackZoneFilterSchema = TrackZoneFilterSchema;
30939
31303
  exports.TrackedDetectionSchema = TrackedDetectionSchema;
30940
31304
  exports.TurnServerSchema = TurnServerSchema;
30941
31305
  exports.UNIT_TABLE = UNIT_TABLE;
@@ -31198,6 +31562,7 @@ exports.resolveFormat = resolveFormat;
31198
31562
  exports.resolveHydratedFieldValue = require_sleep.resolveHydratedFieldValue;
31199
31563
  exports.resolveModelFormat = resolveModelFormat;
31200
31564
  exports.resolveRunnerId = resolveRunnerId;
31565
+ exports.resolveScrubThumbnailGeometry = resolveScrubThumbnailGeometry;
31201
31566
  exports.resolveVariantModelId = resolveVariantModelId;
31202
31567
  exports.runInferenceStep = runInferenceStep;
31203
31568
  exports.runtimeDevices = runtimeDevices;