@camstack/addon-pipeline 1.1.58 → 1.1.59

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (37) hide show
  1. package/dist/audio-analyzer/index.js +4 -4
  2. package/dist/audio-analyzer/index.mjs +2 -2
  3. package/dist/detection-pipeline/index.js +9 -9
  4. package/dist/detection-pipeline/index.mjs +3 -3
  5. package/dist/{dist-Bn6Uq4vq.js → dist-B1u-QN05.js} +176 -12
  6. package/dist/{dist-CnwwDzX3.mjs → dist-DKeNH_5z.mjs} +176 -12
  7. package/dist/{model-download-service-C-IHWnXx-3Mmeob3l.mjs → model-download-service-Cp9f4dk6-0wh7OK3s.mjs} +2 -2
  8. package/dist/{model-download-service-C-IHWnXx-D326YNnt.js → model-download-service-Cp9f4dk6-Cp_GTKTw.js} +2 -2
  9. package/dist/motion-wasm/index.js +1 -1
  10. package/dist/motion-wasm/index.mjs +1 -1
  11. package/dist/pipeline-runner/index.js +123 -4
  12. package/dist/pipeline-runner/index.mjs +122 -3
  13. package/dist/recorder/index.js +993 -7
  14. package/dist/recorder/index.mjs +990 -5
  15. package/dist/session-decode/decode-worker-child.js +14 -1
  16. package/dist/session-decode/decode-worker-child.mjs +14 -1
  17. package/dist/{hub-hostname-cCknRYKj.mjs → sheet-geometry-BN80zpCa.js} +56 -1
  18. package/dist/{hub-hostname-DAJXlOgV.js → sheet-geometry-Bk3fR4s7.mjs} +39 -6
  19. package/dist/{step-definitions-D7NOrnzz.js → step-definitions-CPch37vh.js} +1 -1
  20. package/dist/{step-definitions-DhEe57Wn.mjs → step-definitions-DUB27V8Y.mjs} +1 -1
  21. package/dist/stream-broker/_stub.js +2 -2
  22. package/dist/stream-broker/{_virtual_mf-localSharedImportMap___mfe_internal__addon_stream_broker_widgets-B8FQ1e0a.mjs → _virtual_mf-localSharedImportMap___mfe_internal__addon_stream_broker_widgets-DdkfKDgw.mjs} +3 -3
  23. package/dist/stream-broker/_virtual_mf___mfe_internal__addon_stream_broker_widgets__loadShare___mf_0_camstack_mf_1_types__loadShare__.js-D3h_W9uu.mjs +26 -0
  24. package/dist/stream-broker/_virtual_mf___mfe_internal__addon_stream_broker_widgets__loadShare___mf_0_camstack_mf_1_ui_mf_2_library__loadShare__.js-DSXctoaw.mjs +26 -0
  25. package/dist/stream-broker/{hostInit-D1Vdyu-4.mjs → hostInit-BLn2Pv8Q.mjs} +3 -3
  26. package/dist/stream-broker/index.js +622 -149
  27. package/dist/stream-broker/index.mjs +622 -149
  28. package/dist/stream-broker/remoteEntry.js +1 -1
  29. package/embed-dist/assets/{MaskShapeCanvas-DI4BY7W2-CG5EE0W4.js → MaskShapeCanvas-DI4BY7W2-B0_nx15B.js} +1 -1
  30. package/embed-dist/assets/{MotionZonesSettings-NcxxQN8r-BFeLUNOl.js → MotionZonesSettings-NcxxQN8r-B8uM-VeO.js} +1 -1
  31. package/embed-dist/assets/{PrivacyMaskSettings-APgPLF7p-pQQunq1F.js → PrivacyMaskSettings-APgPLF7p-DMOs4Hj9.js} +1 -1
  32. package/embed-dist/assets/index-W9-H5LTj.js +81 -0
  33. package/embed-dist/index.html +1 -1
  34. package/package.json +1 -1
  35. package/dist/stream-broker/_virtual_mf___mfe_internal__addon_stream_broker_widgets__loadShare___mf_0_camstack_mf_1_types__loadShare__.js-Ba7Eyd47.mjs +0 -26
  36. package/dist/stream-broker/_virtual_mf___mfe_internal__addon_stream_broker_widgets__loadShare___mf_0_camstack_mf_1_ui_mf_2_library__loadShare__.js-TWCUWhCm.mjs +0 -26
  37. package/embed-dist/assets/index-BxqQ931j.js +0 -81
@@ -3,9 +3,9 @@ Object.defineProperties(exports, {
3
3
  [Symbol.toStringTag]: { value: "Module" }
4
4
  });
5
5
  const require_chunk = require("../chunk-D6vf50IK.js");
6
- const require_dist = require("../dist-Bn6Uq4vq.js");
6
+ const require_dist = require("../dist-B1u-QN05.js");
7
7
  const require_node_topology_platform = require("../node-topology-platform-CFZ7F4xW.js");
8
- const require_model_download_service_C_IHWnXx = require("../model-download-service-C-IHWnXx-D326YNnt.js");
8
+ const require_model_download_service_Cp9f4dk6 = require("../model-download-service-Cp9f4dk6-Cp_GTKTw.js");
9
9
  let node_fs = require("node:fs");
10
10
  node_fs = require_chunk.__toESM(node_fs);
11
11
  let node_path = require("node:path");
@@ -84,7 +84,7 @@ var YamnetPythonPipeline = class {
84
84
  url: YAMNET_MODEL_URL,
85
85
  dest: modelPath
86
86
  } });
87
- await require_model_download_service_C_IHWnXx.downloadFile(YAMNET_MODEL_URL, modelPath);
87
+ await require_model_download_service_Cp9f4dk6.downloadFile(YAMNET_MODEL_URL, modelPath);
88
88
  this.log.info("YAMNet ONNX model downloaded", { meta: { sizeBytes: node_fs.statSync(modelPath).size } });
89
89
  }
90
90
  if (!node_fs.existsSync(labelsPath)) {
@@ -92,7 +92,7 @@ var YamnetPythonPipeline = class {
92
92
  url: YAMNET_LABELS_URL,
93
93
  dest: labelsPath
94
94
  } });
95
- await require_model_download_service_C_IHWnXx.downloadFile(YAMNET_LABELS_URL, labelsPath);
95
+ await require_model_download_service_Cp9f4dk6.downloadFile(YAMNET_LABELS_URL, labelsPath);
96
96
  }
97
97
  const pythonDir = resolveAudioPythonDir();
98
98
  if (this.installPythonRequirements) await this.installPythonRequirements(node_path.join(pythonDir, "requirements-audio.txt"));
@@ -1,7 +1,7 @@
1
1
  import { t as __require } from "../chunk-BdkLduGY.mjs";
2
- import { C as mapAudioLabelToMacro, H as hydrateSchema, I as errMsg, L as BaseAddon, h as audioAnalyzerCapability, l as HF_BASE_URL, m as audioAnalysisCapability, n as AUDIO_BACKEND_CHOICES, o as DEFAULT_AUDIO_ANALYZER_CONFIG } from "../dist-CnwwDzX3.mjs";
2
+ import { C as mapAudioLabelToMacro, H as hydrateSchema, I as errMsg, L as BaseAddon, h as audioAnalyzerCapability, l as HF_BASE_URL, m as audioAnalysisCapability, n as AUDIO_BACKEND_CHOICES, o as DEFAULT_AUDIO_ANALYZER_CONFIG } from "../dist-DKeNH_5z.mjs";
3
3
  import { t as pickNodePlatformArch } from "../node-topology-platform-BkR_k6WT.mjs";
4
- import { r as downloadFile } from "../model-download-service-C-IHWnXx-3Mmeob3l.mjs";
4
+ import { r as downloadFile } from "../model-download-service-Cp9f4dk6-0wh7OK3s.mjs";
5
5
  import * as fs from "node:fs";
6
6
  import * as path$1 from "node:path";
7
7
  //#region src/audio-analyzer/audio-pipeline.ts
@@ -3,10 +3,10 @@ Object.defineProperties(exports, {
3
3
  [Symbol.toStringTag]: { value: "Module" }
4
4
  });
5
5
  const require_chunk = require("../chunk-D6vf50IK.js");
6
- const require_dist = require("../dist-Bn6Uq4vq.js");
7
- const require_step_definitions = require("../step-definitions-D7NOrnzz.js");
6
+ const require_dist = require("../dist-B1u-QN05.js");
7
+ const require_step_definitions = require("../step-definitions-CPch37vh.js");
8
8
  const require_node_topology_platform = require("../node-topology-platform-CFZ7F4xW.js");
9
- const require_model_download_service_C_IHWnXx = require("../model-download-service-C-IHWnXx-D326YNnt.js");
9
+ const require_model_download_service_Cp9f4dk6 = require("../model-download-service-Cp9f4dk6-Cp_GTKTw.js");
10
10
  let node_child_process = require("node:child_process");
11
11
  let sharp = require("sharp");
12
12
  sharp = require_chunk.__toESM(sharp);
@@ -4139,7 +4139,7 @@ var DetectionPipelineProvider = class DetectionPipelineProvider {
4139
4139
  if (!step.enabled) continue;
4140
4140
  const modelEntry = await this.resolveModelEntry(step.addonId, step.modelId);
4141
4141
  if (!modelEntry) continue;
4142
- if (require_model_download_service_C_IHWnXx.isModelDownloaded(this.modelsDir, modelEntry, format)) continue;
4142
+ if (require_model_download_service_Cp9f4dk6.isModelDownloaded(this.modelsDir, modelEntry, format)) continue;
4143
4143
  await this.downloadWithRetry(modelEntry, format, 3);
4144
4144
  }
4145
4145
  }
@@ -4514,7 +4514,7 @@ var DetectionPipelineProvider = class DetectionPipelineProvider {
4514
4514
  const formats = {};
4515
4515
  for (const [formatKey, entry] of Object.entries(m.formats)) {
4516
4516
  if (!entry) continue;
4517
- const downloaded = require_model_download_service_C_IHWnXx.isModelDownloaded(this.modelsDir, m, formatKey);
4517
+ const downloaded = require_model_download_service_Cp9f4dk6.isModelDownloaded(this.modelsDir, m, formatKey);
4518
4518
  formats[formatKey] = {
4519
4519
  url: entry.url,
4520
4520
  sizeMB: entry.sizeMB,
@@ -4637,7 +4637,7 @@ var DetectionPipelineProvider = class DetectionPipelineProvider {
4637
4637
  const { modelId, format, addonId } = input;
4638
4638
  const modelEntry = await this.resolveModelEntry(addonId, modelId);
4639
4639
  if (!modelEntry) throw new Error(`Model "${modelId}" not found in step "${addonId}" catalog`);
4640
- if (!require_model_download_service_C_IHWnXx.deleteModelFromDisk(this.modelsDir, modelEntry, format)) throw new Error(`Model "${modelId}" (${format}) is not downloaded — nothing to delete`);
4640
+ if (!require_model_download_service_Cp9f4dk6.deleteModelFromDisk(this.modelsDir, modelEntry, format)) throw new Error(`Model "${modelId}" (${format}) is not downloaded — nothing to delete`);
4641
4641
  this.log.info("Model deleted from disk", { meta: {
4642
4642
  modelId,
4643
4643
  format
@@ -5193,7 +5193,7 @@ var DetectionPipelineProvider = class DetectionPipelineProvider {
5193
5193
  const format = this.currentEngine?.format ?? "onnx";
5194
5194
  for (const step of needed) {
5195
5195
  const modelEntry = await this.resolveModelEntry(step.addonId, step.modelId);
5196
- if (modelEntry && !require_model_download_service_C_IHWnXx.isModelDownloaded(this.modelsDir, modelEntry, format)) {
5196
+ if (modelEntry && !require_model_download_service_Cp9f4dk6.isModelDownloaded(this.modelsDir, modelEntry, format)) {
5197
5197
  this.log.info("Downloading model for step", { meta: {
5198
5198
  modelId: step.modelId,
5199
5199
  format,
@@ -5218,7 +5218,7 @@ var DetectionPipelineProvider = class DetectionPipelineProvider {
5218
5218
  /** Download a model with retry + exponential backoff */
5219
5219
  async downloadWithRetry(entry, format, maxRetries, onProgress) {
5220
5220
  for (let attempt = 1; attempt <= maxRetries; attempt++) try {
5221
- await require_model_download_service_C_IHWnXx.ensureModel(this.modelsDir, entry, format, onProgress);
5221
+ await require_model_download_service_Cp9f4dk6.ensureModel(this.modelsDir, entry, format, onProgress);
5222
5222
  this.log.info("Model downloaded successfully", { meta: { modelId: entry.id } });
5223
5223
  return;
5224
5224
  } catch (err) {
@@ -6024,7 +6024,7 @@ function buildSchemaSlots(format, modelsDir, customByStep) {
6024
6024
  id: m.id,
6025
6025
  name: m.name,
6026
6026
  formats: Object.fromEntries(Object.entries(m.formats).map(([f, entry]) => [f, {
6027
- downloaded: require_model_download_service_C_IHWnXx.isModelDownloaded(modelsDir, m, f),
6027
+ downloaded: require_model_download_service_Cp9f4dk6.isModelDownloaded(modelsDir, m, f),
6028
6028
  sizeMB: entry.sizeMB
6029
6029
  }])),
6030
6030
  ...m.group ? { group: m.group } : {},
@@ -1,8 +1,8 @@
1
1
  import { t as __require } from "../chunk-BdkLduGY.mjs";
2
- import { D as nodePin, H as hydrateSchema, I as errMsg, K as parseJsonUnknown, L as BaseAddon, O as pipelineExecutorCapability, P as supportedRuntimes$1, V as createEvent, Y as sleep, b as detectionPipelineCapability, f as YAMNET_TO_MACRO, j as runtimeDevices$1, st as EventCategory, t as APPLE_SA_TO_MACRO, v as defaultDeviceFor$1, x as evaluateZoneRules } from "../dist-CnwwDzX3.mjs";
3
- import { a as getStepDefinition, i as getStep, n as ALL_STEPS, o as resolveModelForFormat, r as getDefaultModelForFormat, t as ALL_PIPELINE_STEPS } from "../step-definitions-DhEe57Wn.mjs";
2
+ import { D as nodePin, H as hydrateSchema, I as errMsg, K as parseJsonUnknown, L as BaseAddon, O as pipelineExecutorCapability, P as supportedRuntimes$1, V as createEvent, Y as sleep, b as detectionPipelineCapability, f as YAMNET_TO_MACRO, j as runtimeDevices$1, st as EventCategory, t as APPLE_SA_TO_MACRO, v as defaultDeviceFor$1, x as evaluateZoneRules } from "../dist-DKeNH_5z.mjs";
3
+ import { a as getStepDefinition, i as getStep, n as ALL_STEPS, o as resolveModelForFormat, r as getDefaultModelForFormat, t as ALL_PIPELINE_STEPS } from "../step-definitions-DUB27V8Y.mjs";
4
4
  import { t as pickNodePlatformArch } from "../node-topology-platform-BkR_k6WT.mjs";
5
- import { a as isModelDownloaded, i as ensureModel, n as deleteModelFromDisk } from "../model-download-service-C-IHWnXx-3Mmeob3l.mjs";
5
+ import { a as isModelDownloaded, i as ensureModel, n as deleteModelFromDisk } from "../model-download-service-Cp9f4dk6-0wh7OK3s.mjs";
6
6
  import { spawn } from "node:child_process";
7
7
  import sharp from "sharp";
8
8
  import * as fs from "node:fs";
@@ -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";
@@ -10738,7 +10741,7 @@ object({
10738
10741
  deviceId: number(),
10739
10742
  timestamp: number()
10740
10743
  });
10741
- DeviceType.Button;
10744
+ DeviceType.Button, DeviceType.Camera;
10742
10745
  /**
10743
10746
  * Enum-state sensor — a string value picked from a finite option set.
10744
10747
  * Drives HA `sensor` entries with `state_class: enum` (HVAC action
@@ -15569,6 +15572,14 @@ var ConfigEntrySchema = object({
15569
15572
  value: unknown(),
15570
15573
  description: string().optional()
15571
15574
  });
15575
+ var DeviceLinkModeSchema = _enum(["auto", "manual"]);
15576
+ /** One resolved linked device — the compact projection consumers need. */
15577
+ var LinkedDeviceSchema = object({
15578
+ deviceId: number(),
15579
+ name: string(),
15580
+ location: string().nullable(),
15581
+ features: array(string())
15582
+ });
15572
15583
  var SavedDeviceRowSchema = object({
15573
15584
  /** Numeric id reserved at allocateDeviceId time. */
15574
15585
  id: number(),
@@ -15790,7 +15801,10 @@ method(object({
15790
15801
  }), _void(), {
15791
15802
  kind: "mutation",
15792
15803
  auth: "admin"
15793
- }), 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({
15804
+ }), 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({
15805
+ mode: DeviceLinkModeSchema,
15806
+ devices: array(LinkedDeviceSchema)
15807
+ })), method(object({ deviceId: number() }), array(StreamSourceEntrySchema$1)), method(object({ deviceId: number() }), array(ConfigEntrySchema)), method(object({ deviceId: number() }), ConfigUISchemaOutput), method(object({
15794
15808
  deviceId: number(),
15795
15809
  values: record(string(), unknown())
15796
15810
  }), object({ success: literal(true) }), {
@@ -17059,6 +17073,61 @@ var EventKindSchema = _enum([
17059
17073
  "object",
17060
17074
  "audio"
17061
17075
  ]);
17076
+ /**
17077
+ * Spatial filter for `listTracks` — the rect + polygon variants of the shared
17078
+ * MaskShape vocabulary (see `mask-shape.ts`). Coordinates are NORMALIZED 0..1
17079
+ * of the camera frame (top-left origin), matching the drawing-plane editor.
17080
+ */
17081
+ var TrackZoneFilterSchema = discriminatedUnion("kind", [MaskRectShapeSchema, MaskPolygonShapeSchema]);
17082
+ /** Closed icon vocabulary so clients render a known glyph per kind. */
17083
+ var EventKindIconSchema = _enum([
17084
+ "motion",
17085
+ "audio",
17086
+ "person",
17087
+ "vehicle",
17088
+ "animal",
17089
+ "door",
17090
+ "pir",
17091
+ "smoke",
17092
+ "water",
17093
+ "button",
17094
+ "generic"
17095
+ ]);
17096
+ var EventKindCategorySchema = _enum([
17097
+ "motion",
17098
+ "audio",
17099
+ "detection",
17100
+ "sensor",
17101
+ "custom"
17102
+ ]);
17103
+ var EventKindDescriptorSchema = object({
17104
+ /** Stable kind id (e.g. 'motion', 'person', 'contact'). */
17105
+ kind: string(),
17106
+ label: string(),
17107
+ /** Hex color for timeline/legend rendering. */
17108
+ color: string(),
17109
+ icon: EventKindIconSchema,
17110
+ category: EventKindCategorySchema,
17111
+ /** Which cap + device contributes this kind. For built-ins the camera
17112
+ * itself; for sensor kinds the LINKED source device. */
17113
+ source: object({
17114
+ capName: string(),
17115
+ deviceId: number()
17116
+ })
17117
+ });
17118
+ var SensorEventSchema = object({
17119
+ id: string(),
17120
+ /** The CAMERA the event is attributed to (a sensor linked to N cameras
17121
+ * yields N rows, one per camera). */
17122
+ deviceId: number(),
17123
+ /** The linked sensor device whose state changed. */
17124
+ sourceDeviceId: number(),
17125
+ /** Event kind id — matches an `EventKindDescriptor.kind`. */
17126
+ kind: string(),
17127
+ /** Snapshot of the sensor cap's runtime-state slice at the change. */
17128
+ value: record(string(), unknown()).nullable(),
17129
+ timestamp: number()
17130
+ });
17062
17131
  var TrackPositionSchema = object({
17063
17132
  x: number(),
17064
17133
  y: number(),
@@ -17072,6 +17141,30 @@ var TrackSnapshotSchema = object({
17072
17141
  mediaKey: string()
17073
17142
  });
17074
17143
  /**
17144
+ * Normalized 0..1 trajectory envelope (min/max over every position bbox,
17145
+ * divided by the track's detection-frame dims), computed at persist time.
17146
+ * Absent when the frame dims were unknown when the track was persisted
17147
+ * (legacy rows / dims-less sources) and on active (in-RAM) tracks.
17148
+ */
17149
+ var TrackEnvelopeSchema = object({
17150
+ minX: number(),
17151
+ minY: number(),
17152
+ maxX: number(),
17153
+ maxY: number()
17154
+ });
17155
+ /**
17156
+ * Row projection for track list queries. `full` (default) returns the
17157
+ * complete Track including the frame-rate `positions[]` history and the
17158
+ * `snapshots[]` references — megabytes across a page of tracks. `slim`
17159
+ * keeps every scalar the list surfaces actually render (ids, class(es),
17160
+ * label / audioLabels / importance enrichment, firstSeen/lastSeen, state,
17161
+ * zonesVisited, bestEventId, envelope) and returns `positions` /
17162
+ * `snapshots` as EMPTY arrays — detail views re-fetch the full row via
17163
+ * `getTrack`. Mirrors the event-store `projection` convention
17164
+ * (`getObjectEvents` et al.).
17165
+ */
17166
+ var TrackProjectionSchema = _enum(["full", "slim"]);
17167
+ /**
17075
17168
  * One audio-classification label heard on the track's camera while the
17076
17169
  * track was alive, aggregated per label. An "episode" is one persisted
17077
17170
  * audio event (the confident-classification path: score ≥ the device's
@@ -17122,7 +17215,11 @@ var TrackSchema = object({
17122
17215
  /** Audio-classification labels heard on the camera during the track's
17123
17216
  * life (score ≥ device `classificationMinScore`), aggregated per label.
17124
17217
  * Absent on legacy rows / tracks with no confident audio. */
17125
- audioLabels: array(TrackAudioLabelSchema).readonly().optional()
17218
+ audioLabels: array(TrackAudioLabelSchema).readonly().optional(),
17219
+ /** Normalized 0..1 trajectory envelope (see {@link TrackEnvelopeSchema}).
17220
+ * Populated from the persisted envelope columns on historical reads;
17221
+ * absent on legacy rows, dims-less tracks and active (in-RAM) tracks. */
17222
+ envelope: TrackEnvelopeSchema.optional()
17126
17223
  });
17127
17224
  var BaseEventFields = {
17128
17225
  id: string(),
@@ -17232,11 +17329,13 @@ var MediaFileSchema = object({
17232
17329
  sizeBytes: number(),
17233
17330
  timestamp: number()
17234
17331
  });
17332
+ var DEFAULT_EVENT_QUERY_LIMIT = 1e3;
17333
+ var MAX_EVENT_QUERY_LIMIT = 5e3;
17235
17334
  var DeviceEventQueryInput = object({
17236
17335
  deviceId: number(),
17237
17336
  since: number().optional(),
17238
17337
  until: number().optional(),
17239
- limit: number().int().min(1).max(5e3).default(1e3),
17338
+ limit: number().int().min(1).max(MAX_EVENT_QUERY_LIMIT).default(DEFAULT_EVENT_QUERY_LIMIT),
17240
17339
  /** `slim` drops heavy JSON fields (regions/bbox/zones) and carries an
17241
17340
  * optional `mediaUrl` (populated by B5). `full` (default) keeps today's
17242
17341
  * exact behaviour. Callers may omit this field — the store defaults to
@@ -17244,6 +17343,27 @@ var DeviceEventQueryInput = object({
17244
17343
  projection: _enum(["full", "slim"]).optional()
17245
17344
  });
17246
17345
  var ObjectEventQueryInput = DeviceEventQueryInput.extend({ classFilter: string().optional() });
17346
+ var RecentTracksQueryInput = object({
17347
+ /** Devices to merge. An empty array yields `{ tracks: [], nextCursor: null }`. */
17348
+ deviceIds: array(number()),
17349
+ /** Window lower bound on `lastSeen` (inclusive). */
17350
+ since: number().optional(),
17351
+ /** Window upper bound on `lastSeen` (inclusive). */
17352
+ until: number().optional(),
17353
+ /** Page size. Default 200, max 1000. */
17354
+ limit: number().int().min(1).max(1e3).default(200),
17355
+ /** Opaque continuation cursor from a previous page's `nextCursor`.
17356
+ * Encodes the (lastSeen, trackId) sort position — treat as opaque. */
17357
+ cursor: string().optional(),
17358
+ /** See {@link TrackProjectionSchema}. Default `full`. */
17359
+ projection: TrackProjectionSchema.optional()
17360
+ });
17361
+ var RecentTracksPageSchema = object({
17362
+ /** Merged page, ordered by (`lastSeen` DESC, `trackId` DESC). */
17363
+ tracks: array(TrackSchema).readonly(),
17364
+ /** Cursor for the next page, or null when this page is the last. */
17365
+ nextCursor: string().nullable()
17366
+ });
17247
17367
  var KeyEventQueryInput = object({
17248
17368
  deviceId: number(),
17249
17369
  /** Window lower bound (track firstSeen ≥ since). */
@@ -17326,11 +17446,25 @@ DeviceType.Camera, method(object({ deviceId: number() }), array(TrackSchema).rea
17326
17446
  deviceId: number(),
17327
17447
  since: number().optional(),
17328
17448
  until: number().optional(),
17329
- limit: number().optional()
17330
- }), array(TrackSchema).readonly()), method(object({ deviceId: number() }), _void(), {
17331
- kind: "mutation",
17332
- auth: "admin"
17333
- }), method(DeviceEventQueryInput, array(MotionEventSchema).readonly()), method(ObjectEventQueryInput, array(ObjectEventSchema).readonly()), method(DeviceEventQueryInput, array(AudioEventSchema).readonly()), method(KeyEventQueryInput, array(KeyEventSchema).readonly()), method(object({
17449
+ limit: number().optional(),
17450
+ /** Spatial filter only tracks whose trajectory intersects the zone
17451
+ * (normalized 0..1 rect or polygon). SQL-prefiltered on the persisted
17452
+ * envelope columns, then precisely tested per position. Tracks with
17453
+ * an unknown envelope (no frame dims at persist time) always match. */
17454
+ zone: TrackZoneFilterSchema.optional(),
17455
+ /** See {@link TrackProjectionSchema}. Default `full` (backward
17456
+ * compatible — omitting the field keeps today's exact behaviour). */
17457
+ projection: TrackProjectionSchema.optional()
17458
+ }), array(TrackSchema).readonly()), method(RecentTracksQueryInput, RecentTracksPageSchema), method(object({ deviceId: number() }), _void(), {
17459
+ kind: "mutation",
17460
+ auth: "admin"
17461
+ }), method(DeviceEventQueryInput, array(MotionEventSchema).readonly()), method(ObjectEventQueryInput, array(ObjectEventSchema).readonly()), method(DeviceEventQueryInput, array(AudioEventSchema).readonly()), method(object({ deviceId: number() }), array(EventKindDescriptorSchema).readonly()), method(object({
17462
+ deviceId: number(),
17463
+ since: number().optional(),
17464
+ until: number().optional(),
17465
+ kinds: array(string()).optional(),
17466
+ limit: number().int().min(1).max(MAX_EVENT_QUERY_LIMIT).default(DEFAULT_EVENT_QUERY_LIMIT)
17467
+ }), array(SensorEventSchema).readonly()), method(KeyEventQueryInput, array(KeyEventSchema).readonly()), method(object({
17334
17468
  deviceId: number(),
17335
17469
  since: number(),
17336
17470
  until: number(),
@@ -20626,7 +20760,12 @@ var RecordingStorageUsageSchema = object({
20626
20760
  /**
20627
20761
  * Result of locating footage at a wall-clock instant for one device/profile.
20628
20762
  * `segment` carries the covering segment's window; `gap` reports the forward
20629
- * nearest covered edge (`null` past the end of footage / when none exists).
20763
+ * nearest covered edge (`null` past the end of footage / when none exists)
20764
+ * and the backward covered edge `prevEndMs` (exclusive end of the nearest
20765
+ * footage behind the epoch; `null` when none — optional so older providers
20766
+ * that omit it stay valid). `prevEndMs` lets a backward frame-step hop the
20767
+ * small inter-segment cracks (durMs under-covers the span to the next
20768
+ * startMs by ~11-17 ms) instead of no-opping at a segment head.
20630
20769
  */
20631
20770
  var LocateSegmentResultSchema = discriminatedUnion("kind", [object({
20632
20771
  kind: literal("segment"),
@@ -20635,7 +20774,8 @@ var LocateSegmentResultSchema = discriminatedUnion("kind", [object({
20635
20774
  bytes: number()
20636
20775
  }), object({
20637
20776
  kind: literal("gap"),
20638
- nearestEdgeMs: number().nullable()
20777
+ nearestEdgeMs: number().nullable(),
20778
+ prevEndMs: number().nullable().optional()
20639
20779
  })]);
20640
20780
  /** Raw bytes of one finalized footage segment (read off disk on the recording node). */
20641
20781
  var ReadSegmentBytesResultSchema = object({ data: _instanceof(Uint8Array) });
@@ -22237,6 +22377,12 @@ Object.freeze({
22237
22377
  addonId: null,
22238
22378
  access: "view"
22239
22379
  },
22380
+ "deviceManager.getLinkedDevices": {
22381
+ capName: "device-manager",
22382
+ capScope: "system",
22383
+ addonId: null,
22384
+ access: "view"
22385
+ },
22240
22386
  "deviceManager.getRoleDisplayDefaults": {
22241
22387
  capName: "device-manager",
22242
22388
  capScope: "system",
@@ -23791,6 +23937,12 @@ Object.freeze({
23791
23937
  addonId: null,
23792
23938
  access: "view"
23793
23939
  },
23940
+ "pipelineAnalytics.getSensorEvents": {
23941
+ capName: "pipeline-analytics",
23942
+ capScope: "device",
23943
+ addonId: null,
23944
+ access: "view"
23945
+ },
23794
23946
  "pipelineAnalytics.getTrack": {
23795
23947
  capName: "pipeline-analytics",
23796
23948
  capScope: "device",
@@ -23803,6 +23955,18 @@ Object.freeze({
23803
23955
  addonId: null,
23804
23956
  access: "view"
23805
23957
  },
23958
+ "pipelineAnalytics.listEventKinds": {
23959
+ capName: "pipeline-analytics",
23960
+ capScope: "device",
23961
+ addonId: null,
23962
+ access: "view"
23963
+ },
23964
+ "pipelineAnalytics.listRecentTracks": {
23965
+ capName: "pipeline-analytics",
23966
+ capScope: "device",
23967
+ addonId: null,
23968
+ access: "view"
23969
+ },
23806
23970
  "pipelineAnalytics.listTracks": {
23807
23971
  capName: "pipeline-analytics",
23808
23972
  capScope: "device",