camstack 1.2.154 → 1.2.155

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.
@@ -23633,9 +23633,9 @@ var require_zod = __commonJS({
23633
23633
  }
23634
23634
  });
23635
23635
 
23636
- // ../system/dist/dist-DaSCLJVH.js
23637
- var require_dist_DaSCLJVH = __commonJS({
23638
- "../system/dist/dist-DaSCLJVH.js"(exports) {
23636
+ // ../system/dist/dist-Dze0l7UM.js
23637
+ var require_dist_Dze0l7UM = __commonJS({
23638
+ "../system/dist/dist-Dze0l7UM.js"(exports) {
23639
23639
  "use strict";
23640
23640
  var zod = require_zod();
23641
23641
  var EventCategory = /* @__PURE__ */ (function(EventCategory2) {
@@ -29471,6 +29471,21 @@ var require_dist_DaSCLJVH = __commonJS({
29471
29471
  mode: "singleton",
29472
29472
  deviceTypes: Object.values(DeviceType),
29473
29473
  runtimeState: StreamSignalsStatusSchema,
29474
+ /**
29475
+ * Runtime-state durability: **session** — mirrored in RAM, never written.
29476
+ *
29477
+ * The slice holds what the DEVICE says it can emit. That is a probed fact,
29478
+ * not an operator choice: the provider re-declares it on every registration,
29479
+ * so losing it loses nothing and persisting it would freeze an answer the
29480
+ * camera is entitled to change. Measured the same day on the sibling case —
29481
+ * `native-object-detection.supportedClasses` was persisted, and a firmware
29482
+ * class the camera really detected stayed missing for the life of the row
29483
+ * because the fix could not reach it.
29484
+ *
29485
+ * See `RuntimeStateDurability`. Enforced by
29486
+ * `scripts/check-runtime-state-durability.ts`.
29487
+ */
29488
+ durability: "session",
29474
29489
  methods: {
29475
29490
  /**
29476
29491
  * What this device can emit. Empty is a valid and common answer — most
@@ -30735,16 +30750,6 @@ var require_dist_DaSCLJVH = __commonJS({
30735
30750
  })) }), { auth: "admin" })
30736
30751
  }
30737
30752
  };
30738
- function describeCustomActions(catalog) {
30739
- const out = {};
30740
- for (const [name, spec] of Object.entries(catalog)) out[name] = {
30741
- kind: spec.kind,
30742
- auth: spec.auth,
30743
- scope: spec.scope,
30744
- ...spec.caller === "required" ? { caller: "required" } : {}
30745
- };
30746
- return out;
30747
- }
30748
30753
  var CustomModelDescriptorSchema = zod.z.object({
30749
30754
  stepId: zod.z.string(),
30750
30755
  entry: ModelCatalogEntrySchema
@@ -36354,6 +36359,29 @@ var require_dist_DaSCLJVH = __commonJS({
36354
36359
  settings: NcAlarmSettingsSchema,
36355
36360
  coverage: zod.z.array(NcAlarmModeCoverageSchema)
36356
36361
  });
36362
+ var NcClipRetentionAskSchema = zod.z.object({
36363
+ /**
36364
+ * The camera this ask is about. **Absent = every camera**, which is what a
36365
+ * rule with no `conditions.devices` means: it can fire anywhere, so it is
36366
+ * asking everywhere.
36367
+ */
36368
+ deviceId: zod.z.number().int().nonnegative().optional(),
36369
+ /** Seconds of history the rule needs held for it. Never zero — a rule that
36370
+ * needs nothing produces no ask at all. */
36371
+ seconds: zod.z.number().min(0).max(60),
36372
+ /** The profile the rule cuts from, when it named one. Absent = the cheapest
36373
+ * assigned, which is what the cut defaults to. */
36374
+ profile: CamProfileSchema.optional(),
36375
+ /** Who is asking — so a retention the operator did not expect names a rule. */
36376
+ ruleId: zod.z.string(),
36377
+ ruleName: zod.z.string(),
36378
+ /** Why this many seconds: the rule's own window, or the occupancy ceiling. */
36379
+ reason: zod.z.enum(["window", "occupancy"])
36380
+ });
36381
+ var NcClipRetentionPlanSchema = zod.z.object({
36382
+ rulesLoaded: zod.z.boolean(),
36383
+ asks: zod.z.array(NcClipRetentionAskSchema).readonly()
36384
+ });
36357
36385
  var notificationRulesCapability = {
36358
36386
  name: "notification-rules",
36359
36387
  scope: "system",
@@ -36386,6 +36414,23 @@ var require_dist_DaSCLJVH = __commonJS({
36386
36414
  auth: "admin"
36387
36415
  }),
36388
36416
  /**
36417
+ * WHAT THE RULES ACTUALLY ASK the stream broker to retain, per camera.
36418
+ *
36419
+ * The notification centre owns the rules, so it is the only thing that can
36420
+ * say how much history a camera's notifications will ever reach back for.
36421
+ * Before this the broker guessed — a flat minute on every camera — and
36422
+ * learned the PROFILE reactively, after the first clip had already been cut
36423
+ * from the wrong one. This is the same ask stated once, in front.
36424
+ *
36425
+ * A QUERY, pulled by each node's broker, not a push: brokers are per node
36426
+ * (a camera's ring lives wherever its stream is ingested) while this cap is
36427
+ * a singleton, so a push would have to enumerate the cluster. The pull also
36428
+ * makes the failure mode right — a broker that cannot reach the centre
36429
+ * keeps the plan it has, and a plan that has never arrived is UNKNOWN
36430
+ * rather than empty (D49: a read that fails changes nothing).
36431
+ */
36432
+ getClipRetentionAsks: method(zod.z.object({}), NcClipRetentionPlanSchema, { auth: "admin" }),
36433
+ /**
36389
36434
  * PERMANENT per-camera mute — the notifications half of the per-camera
36390
36435
  * function switch group ([D61](../../../../docs/decisions/adr-0067.md)).
36391
36436
  *
@@ -38594,6 +38639,20 @@ var require_dist_DaSCLJVH = __commonJS({
38594
38639
  framesMatched: zod.z.number().int()
38595
38640
  });
38596
38641
  var RunReplayFrameProcessorResultSchema = zod.z.object({ tracks: zod.z.array(ReplayTrackSchema).readonly() });
38642
+ var AnalyticsLtsSeriesSchema = zod.z.enum([
38643
+ "motion",
38644
+ "audio-dbfs",
38645
+ "battery",
38646
+ "occupancy"
38647
+ ]);
38648
+ var LtsBucketSchema = zod.z.object({
38649
+ scope: zod.z.string(),
38650
+ bucketStart: zod.z.number().int(),
38651
+ samples: zod.z.number().int().nonnegative(),
38652
+ sum: zod.z.number(),
38653
+ min: zod.z.number(),
38654
+ max: zod.z.number()
38655
+ });
38597
38656
  var pipelineAnalyticsCapability = {
38598
38657
  name: "pipeline-analytics",
38599
38658
  scope: "device",
@@ -38737,6 +38796,30 @@ var require_dist_DaSCLJVH = __commonJS({
38737
38796
  getKeyEventsBatch: method(KeyEventBatchQueryInput, zod.z.array(KeyEventsForDeviceSchema).readonly()),
38738
38797
  /** Server-side bucketed event counts for the 24-hour timeline.
38739
38798
  * Returns one entry per non-empty bucket; empty buckets are omitted. */
38799
+ /**
38800
+ * Read one camera's long-term series — 5-minute buckets, kept for a year.
38801
+ *
38802
+ * This is the history surface for every chart that used to be served from a
38803
+ * RAM ring: the ring dies with the process, cannot answer about last night,
38804
+ * and had a 60-minute horizon, while these rows are ~60 bytes and already
38805
+ * written. `scope` is the series' own dimension — for `occupancy`, spell it
38806
+ * with {@link occupancyScope} rather than by hand, and omit it to get every
38807
+ * scope back at once (the caller then groups with
38808
+ * {@link parseOccupancyScope}).
38809
+ *
38810
+ * Bounds are inclusive on the BUCKET START, so a range that ends mid-bucket
38811
+ * still returns the bucket it lands in — the alternative is a chart whose
38812
+ * last column silently disappears for five minutes out of every five.
38813
+ */
38814
+ readLongTermSeries: method(zod.z.object({
38815
+ deviceId: zod.z.number(),
38816
+ series: AnalyticsLtsSeriesSchema,
38817
+ /** Omit for EVERY scope of this series in the range. */
38818
+ scope: zod.z.string().optional(),
38819
+ from: zod.z.number(),
38820
+ to: zod.z.number(),
38821
+ limit: zod.z.number().int().positive().optional()
38822
+ }), zod.z.array(LtsBucketSchema).readonly()),
38740
38823
  getEventDensity: method(zod.z.object({
38741
38824
  deviceId: zod.z.number(),
38742
38825
  since: zod.z.number(),
@@ -40053,6 +40136,12 @@ var require_dist_DaSCLJVH = __commonJS({
40053
40136
  queueDepth: zod.z.number(),
40054
40137
  frameLazy: FrameLazyMetricsSchema.optional()
40055
40138
  });
40139
+ var OccupancyBurstRefusalSchema = zod.z.enum([
40140
+ "not-attached",
40141
+ "battery-asleep",
40142
+ "not-watching",
40143
+ "already-bursting"
40144
+ ]);
40056
40145
  var pipelineRunnerCapability = {
40057
40146
  name: "pipeline-runner",
40058
40147
  scope: "system",
@@ -40089,6 +40178,50 @@ var require_dist_DaSCLJVH = __commonJS({
40089
40178
  /** List the deviceIds currently attached to this runner. */
40090
40179
  getLocalCameras: method(zod.z.void(), zod.z.array(zod.z.number()).readonly()),
40091
40180
  /**
40181
+ * Look at a camera NOW, out of band, because something just happened that
40182
+ * only a fresh look can settle.
40183
+ *
40184
+ * The periodic recheck (`occupancyRecheckSec`, 300 s) exists to watch a
40185
+ * still scene. It is the wrong instrument for a QUESTION that has just been
40186
+ * asked: on device 617 a parked car's departure was observed, a departure
40187
+ * strike was armed — and then the motion session ended, the strike decayed
40188
+ * after its 30 s TTL, and the next periodic look arrived up to five minutes
40189
+ * later with nothing left to confirm. Every one of those departures was
40190
+ * settled by the entry ageing out 6 to 10 minutes of observed time later,
40191
+ * and the notification's clip showed an empty space with nothing leaving
40192
+ * it.
40193
+ *
40194
+ * Two numbers make the ask specific, and a caller that ignores them wastes
40195
+ * the burst: a confirmation must land at least
40196
+ * `DEPARTURE_CONFIRM_MIN_GAP_MS` (3 s) after the read that armed the
40197
+ * strike — before that it is the same optical event and is refused — and
40198
+ * `DEPARTURE_ABSENCE_MIN_READS` (5) consecutive unassociated frames are
40199
+ * needed, while `occupancyRecheckFrames` defaults to FOUR. A burst of four
40200
+ * can never confirm an absence; that is why two periodic looks were always
40201
+ * required.
40202
+ *
40203
+ * The runner answers whether it actually started one. A refusal is NAMED,
40204
+ * never a silent `false`: a camera that is asleep on battery (D173 — this
40205
+ * must not become a self-initiated wake), detached, mid-session or already
40206
+ * bursting are four different facts, and a caller told only "no" cannot
40207
+ * tell a protection from a bug.
40208
+ */
40209
+ requestOccupancyBurst: method(zod.z.object({
40210
+ deviceId: zod.z.number(),
40211
+ /** How many frames to collect. The caller sizes this against what its
40212
+ * own confirmation needs; the runner clamps it to the field's range. */
40213
+ frames: zod.z.number().int().positive().optional(),
40214
+ /** Why, for the log. A burst nobody can attribute is a cost nobody can
40215
+ * defend — the periodic one at least has a timer to point at. */
40216
+ reason: zod.z.string()
40217
+ }), zod.z.object({
40218
+ started: zod.z.boolean(),
40219
+ refusedBecause: OccupancyBurstRefusalSchema.optional()
40220
+ }), {
40221
+ auth: "admin",
40222
+ kind: "mutation"
40223
+ }),
40224
+ /**
40092
40225
  * Best-effort NATIVE-resolution crop of a retention-ring frame. Given the
40093
40226
  * `FrameHandle` that rode an inference-result event and a normalized `bbox`,
40094
40227
  * the runner asks the decode worker still holding that frame's NATIVE
@@ -51841,7 +51974,28 @@ var require_dist_DaSCLJVH = __commonJS({
51841
51974
  /** Total tracked objects in this scope (frame / zone / unzoned). */
51842
51975
  totalObjects: zod.z.number().int().nonnegative(),
51843
51976
  /** Per-class count. Keys are macro class names (e.g. `person`, `car`). */
51844
- byClass: zod.z.record(zod.z.string(), zod.z.number().int().nonnegative())
51977
+ byClass: zod.z.record(zod.z.string(), zod.z.number().int().nonnegative()),
51978
+ /**
51979
+ * Of `totalObjects`, how many are STANDING — objects the census holds,
51980
+ * present but not going anywhere (a parked car, a bin, a statue).
51981
+ *
51982
+ * The operator's question about a scene has two halves and they answer
51983
+ * different things: "what is parked here" is stable for hours and must not
51984
+ * flap, while "who is walking through" is the thing an alert is about. One
51985
+ * number could only serve one of them, and `totalObjects` served the first
51986
+ * badly — a passer-by moved it and every occupancy rule saw a change.
51987
+ *
51988
+ * `standing + transient === totalObjects`, always. The total keeps its old
51989
+ * meaning exactly, so no rule written against it changes behaviour.
51990
+ *
51991
+ * ABSENT means UNKNOWN, never zero (D393): a snapshot from a node older than
51992
+ * this field cannot say, and a reader that folds absence in as 0 reports "no
51993
+ * parked objects here" about a camera whose lot is full.
51994
+ */
51995
+ standingObjects: zod.z.number().int().nonnegative().optional(),
51996
+ /** Of `totalObjects`, how many are passing through. See `standingObjects` —
51997
+ * same absence rule. */
51998
+ transientObjects: zod.z.number().int().nonnegative().optional()
51845
51999
  });
51846
52000
  var ZoneScopeBreakdownSchema = PerScopeBreakdownSchema.extend({
51847
52001
  zoneId: zod.z.string(),
@@ -55763,6 +55917,12 @@ var require_dist_DaSCLJVH = __commonJS({
55763
55917
  addonId: null,
55764
55918
  access: "view"
55765
55919
  },
55920
+ "notificationRules.getClipRetentionAsks": {
55921
+ capName: "notification-rules",
55922
+ capScope: "system",
55923
+ addonId: null,
55924
+ access: "view"
55925
+ },
55766
55926
  "notificationRules.getConditionCatalog": {
55767
55927
  capName: "notification-rules",
55768
55928
  capScope: "system",
@@ -56273,6 +56433,12 @@ var require_dist_DaSCLJVH = __commonJS({
56273
56433
  addonId: null,
56274
56434
  access: "create"
56275
56435
  },
56436
+ "pipelineAnalytics.readLongTermSeries": {
56437
+ capName: "pipeline-analytics",
56438
+ capScope: "device",
56439
+ addonId: null,
56440
+ access: "view"
56441
+ },
56276
56442
  "pipelineAnalytics.rebuildObjectEmbeddings": {
56277
56443
  capName: "pipeline-analytics",
56278
56444
  capScope: "device",
@@ -56945,6 +57111,12 @@ var require_dist_DaSCLJVH = __commonJS({
56945
57111
  addonId: null,
56946
57112
  access: "create"
56947
57113
  },
57114
+ "pipelineRunner.requestOccupancyBurst": {
57115
+ capName: "pipeline-runner",
57116
+ capScope: "system",
57117
+ addonId: null,
57118
+ access: "create"
57119
+ },
56948
57120
  "pipelineRunner.runDetailSubtree": {
56949
57121
  capName: "pipeline-runner",
56950
57122
  capScope: "system",
@@ -60089,6 +60261,11 @@ var require_dist_DaSCLJVH = __commonJS({
60089
60261
  form: "single",
60090
60262
  optional: false
60091
60263
  }],
60264
+ "pipelineAnalytics.readLongTermSeries": [{
60265
+ name: "deviceId",
60266
+ form: "single",
60267
+ optional: false
60268
+ }],
60092
60269
  "pipelineAnalytics.rebuildObjectEmbeddings": [{
60093
60270
  name: "deviceId",
60094
60271
  form: "single",
@@ -60279,6 +60456,11 @@ var require_dist_DaSCLJVH = __commonJS({
60279
60456
  form: "single",
60280
60457
  optional: false
60281
60458
  }],
60459
+ "pipelineRunner.requestOccupancyBurst": [{
60460
+ name: "deviceId",
60461
+ form: "single",
60462
+ optional: false
60463
+ }],
60282
60464
  "pipelineRunner.runDetailSubtree": [{
60283
60465
  name: "deviceId",
60284
60466
  form: "single",
@@ -61947,12 +62129,6 @@ var require_dist_DaSCLJVH = __commonJS({
61947
62129
  return deriveBatteryPresence;
61948
62130
  }
61949
62131
  });
61950
- Object.defineProperty(exports, "describeCustomActions", {
61951
- enumerable: true,
61952
- get: function() {
61953
- return describeCustomActions;
61954
- }
61955
- });
61956
62132
  Object.defineProperty(exports, "deviceManagerCapability", {
61957
62133
  enumerable: true,
61958
62134
  get: function() {
@@ -62379,7 +62555,7 @@ var require_alerts_addon = __commonJS({
62379
62555
  [Symbol.toStringTag]: { value: "Module" }
62380
62556
  });
62381
62557
  require_chunk_Cek0wNdY();
62382
- var require_dist10 = require_dist_DaSCLJVH();
62558
+ var require_dist10 = require_dist_Dze0l7UM();
62383
62559
  function selectExpired(alerts, cutoffMs) {
62384
62560
  return alerts.filter((a) => a.createdAt < cutoffMs).sort((a, b) => a.createdAt - b.createdAt).map((a) => a.id);
62385
62561
  }
@@ -63198,7 +63374,7 @@ var require_console_logging = __commonJS({
63198
63374
  [Symbol.toStringTag]: { value: "Module" }
63199
63375
  });
63200
63376
  require_chunk_Cek0wNdY();
63201
- var require_dist10 = require_dist_DaSCLJVH();
63377
+ var require_dist10 = require_dist_Dze0l7UM();
63202
63378
  var require_formatter = require_formatter_DqAKDlvN();
63203
63379
  var LEVEL_RANK = {
63204
63380
  debug: 0,
@@ -63292,7 +63468,7 @@ var require_core_blocks_addon = __commonJS({
63292
63468
  "use strict";
63293
63469
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
63294
63470
  var require_chunk = require_chunk_Cek0wNdY();
63295
- var require_dist10 = require_dist_DaSCLJVH();
63471
+ var require_dist10 = require_dist_Dze0l7UM();
63296
63472
  var node_crypto = __require("crypto");
63297
63473
  var node_fs_promises = __require("fs/promises");
63298
63474
  node_fs_promises = require_chunk.__toESM(node_fs_promises);
@@ -64189,11 +64365,11 @@ var require_core_blocks = __commonJS({
64189
64365
  }
64190
64366
  });
64191
64367
 
64192
- // ../system/dist/retired-settings-keys-CZISf623.js
64193
- var require_retired_settings_keys_CZISf623 = __commonJS({
64194
- "../system/dist/retired-settings-keys-CZISf623.js"(exports) {
64368
+ // ../system/dist/retired-settings-keys-1GWw9mup.js
64369
+ var require_retired_settings_keys_1GWw9mup = __commonJS({
64370
+ "../system/dist/retired-settings-keys-1GWw9mup.js"(exports) {
64195
64371
  "use strict";
64196
- var require_dist10 = require_dist_DaSCLJVH();
64372
+ var require_dist10 = require_dist_Dze0l7UM();
64197
64373
  function settingsStoreIsAuthoritativeHere(env) {
64198
64374
  const raw = (env["CAMSTACK_ROLE"] ?? "").trim().toLowerCase();
64199
64375
  return raw === "" || raw === "hub";
@@ -66430,8 +66606,8 @@ var require_device_manager_addon = __commonJS({
66430
66606
  [Symbol.toStringTag]: { value: "Module" }
66431
66607
  });
66432
66608
  require_chunk_Cek0wNdY();
66433
- var require_dist10 = require_dist_DaSCLJVH();
66434
- var require_retired_settings_keys = require_retired_settings_keys_CZISf623();
66609
+ var require_dist10 = require_dist_Dze0l7UM();
66610
+ var require_retired_settings_keys = require_retired_settings_keys_1GWw9mup();
66435
66611
  var node_crypto = __require("crypto");
66436
66612
  var _camstack_types_node = require_node();
66437
66613
  var JOB_HISTORY = 20;
@@ -72141,7 +72317,7 @@ var require_hub_forwarder = __commonJS({
72141
72317
  [Symbol.toStringTag]: { value: "Module" }
72142
72318
  });
72143
72319
  require_chunk_Cek0wNdY();
72144
- var require_dist10 = require_dist_DaSCLJVH();
72320
+ var require_dist10 = require_dist_Dze0l7UM();
72145
72321
  var require_formatter = require_formatter_DqAKDlvN();
72146
72322
  var DEFAULT_OUTBOUND_BUFFER_SIZE = 500;
72147
72323
  var HubForwarderDestination = class {
@@ -72278,7 +72454,7 @@ var require_liveness_monitor_addon = __commonJS({
72278
72454
  "use strict";
72279
72455
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
72280
72456
  require_chunk_Cek0wNdY();
72281
- var require_dist10 = require_dist_DaSCLJVH();
72457
+ var require_dist10 = require_dist_Dze0l7UM();
72282
72458
  var NO_DEVICES = "liveness:no-devices";
72283
72459
  var ALL_OFFLINE = "liveness:all-devices-offline";
72284
72460
  var NO_FOOTAGE_PREFIX = "liveness:no-footage:";
@@ -72474,7 +72650,7 @@ var require_local_auth_addon = __commonJS({
72474
72650
  [Symbol.toStringTag]: { value: "Module" }
72475
72651
  });
72476
72652
  var require_chunk = require_chunk_Cek0wNdY();
72477
- var require_dist10 = require_dist_DaSCLJVH();
72653
+ var require_dist10 = require_dist_Dze0l7UM();
72478
72654
  var node_crypto = __require("crypto");
72479
72655
  node_crypto = require_chunk.__toESM(node_crypto);
72480
72656
  var crypto$1 = __require("crypto");
@@ -80287,7 +80463,7 @@ var require_loki_logging = __commonJS({
80287
80463
  [Symbol.toStringTag]: { value: "Module" }
80288
80464
  });
80289
80465
  require_chunk_Cek0wNdY();
80290
- var require_dist10 = require_dist_DaSCLJVH();
80466
+ var require_dist10 = require_dist_Dze0l7UM();
80291
80467
  function sanitizeLabelName(raw) {
80292
80468
  const replaced = raw.replaceAll(/[^a-zA-Z0-9_]/g, "_");
80293
80469
  return /^[a-zA-Z_]/.test(replaced) ? replaced : `_${replaced}`;
@@ -80874,7 +81050,7 @@ var require_native_metrics_addon = __commonJS({
80874
81050
  [Symbol.toStringTag]: { value: "Module" }
80875
81051
  });
80876
81052
  var require_chunk = require_chunk_Cek0wNdY();
80877
- var require_dist10 = require_dist_DaSCLJVH();
81053
+ var require_dist10 = require_dist_Dze0l7UM();
80878
81054
  var node_fs_promises = __require("fs/promises");
80879
81055
  var node_fs = __require("fs");
80880
81056
  node_fs = require_chunk.__toESM(node_fs);
@@ -83627,7 +83803,7 @@ var require_filesystem_storage_addon = __commonJS({
83627
83803
  [Symbol.toStringTag]: { value: "Module" }
83628
83804
  });
83629
83805
  var require_chunk = require_chunk_Cek0wNdY();
83630
- var require_dist10 = require_dist_DaSCLJVH();
83806
+ var require_dist10 = require_dist_Dze0l7UM();
83631
83807
  var node_crypto = __require("crypto");
83632
83808
  var node_fs_promises = __require("fs/promises");
83633
83809
  var node_path = __require("path");
@@ -84854,8 +85030,8 @@ var require_sqlite_settings_addon = __commonJS({
84854
85030
  [Symbol.toStringTag]: { value: "Module" }
84855
85031
  });
84856
85032
  var require_chunk = require_chunk_Cek0wNdY();
84857
- var require_dist10 = require_dist_DaSCLJVH();
84858
- var require_retired_settings_keys = require_retired_settings_keys_CZISf623();
85033
+ var require_dist10 = require_dist_Dze0l7UM();
85034
+ var require_retired_settings_keys = require_retired_settings_keys_1GWw9mup();
84859
85035
  var require_wal_checkpoint_policy = require_wal_checkpoint_policy_CCJZngds();
84860
85036
  var node_crypto = __require("crypto");
84861
85037
  var node_path = __require("path");
@@ -87642,7 +87818,7 @@ var require_storage_orchestrator_addon = __commonJS({
87642
87818
  [Symbol.toStringTag]: { value: "Module" }
87643
87819
  });
87644
87820
  var require_chunk = require_chunk_Cek0wNdY();
87645
- var require_dist10 = require_dist_DaSCLJVH();
87821
+ var require_dist10 = require_dist_Dze0l7UM();
87646
87822
  var require_hub_cap_forward = require_hub_cap_forward_DmHNjbB0();
87647
87823
  var zod = require_zod();
87648
87824
  var node_crypto = __require("crypto");
@@ -91369,7 +91545,7 @@ var require_system_config_addon = __commonJS({
91369
91545
  [Symbol.toStringTag]: { value: "Module" }
91370
91546
  });
91371
91547
  require_chunk_Cek0wNdY();
91372
- var require_dist10 = require_dist_DaSCLJVH();
91548
+ var require_dist10 = require_dist_Dze0l7UM();
91373
91549
  var SECTION_TITLES = {
91374
91550
  server: "Server",
91375
91551
  auth: "Authentication"
@@ -109430,7 +109606,7 @@ var require_winston_logging = __commonJS({
109430
109606
  [Symbol.toStringTag]: { value: "Module" }
109431
109607
  });
109432
109608
  var require_chunk = require_chunk_Cek0wNdY();
109433
- var require_dist10 = require_dist_DaSCLJVH();
109609
+ var require_dist10 = require_dist_Dze0l7UM();
109434
109610
  var require_formatter = require_formatter_DqAKDlvN();
109435
109611
  var node_path = __require("path");
109436
109612
  node_path = require_chunk.__toESM(node_path);
@@ -111468,9 +111644,9 @@ var require_event_category_BVfsrBYA = __commonJS({
111468
111644
  }
111469
111645
  });
111470
111646
 
111471
- // ../types/dist/sleep-B8nfmQ8a.js
111472
- var require_sleep_B8nfmQ8a = __commonJS({
111473
- "../types/dist/sleep-B8nfmQ8a.js"(exports) {
111647
+ // ../types/dist/sleep-DqtlfkSS.js
111648
+ var require_sleep_DqtlfkSS = __commonJS({
111649
+ "../types/dist/sleep-DqtlfkSS.js"(exports) {
111474
111650
  "use strict";
111475
111651
  var require_event_category = require_event_category_BVfsrBYA();
111476
111652
  var zod = require_zod();
@@ -113548,6 +113724,41 @@ var require_sleep_B8nfmQ8a = __commonJS({
113548
113724
  DeviceRole2["GenericNotifier"] = "generic-notifier";
113549
113725
  return DeviceRole2;
113550
113726
  })({});
113727
+ function defineCustomActions(spec) {
113728
+ return spec;
113729
+ }
113730
+ function customAction(input, output, options) {
113731
+ return {
113732
+ input,
113733
+ output,
113734
+ kind: options?.kind ?? "query",
113735
+ auth: options?.auth ?? "protected",
113736
+ scope: options?.scope ?? { kind: "system" },
113737
+ ...options?.caller ? { caller: "required" } : {}
113738
+ };
113739
+ }
113740
+ function deviceCustomAction(input, output, options) {
113741
+ return {
113742
+ input,
113743
+ output,
113744
+ kind: options?.kind ?? "query",
113745
+ auth: options?.auth ?? "protected",
113746
+ scope: {
113747
+ kind: "device",
113748
+ ...options?.deviceTypes ? { deviceTypes: options.deviceTypes } : {}
113749
+ }
113750
+ };
113751
+ }
113752
+ function describeCustomActions(catalog) {
113753
+ const out = {};
113754
+ for (const [name, spec] of Object.entries(catalog)) out[name] = {
113755
+ kind: spec.kind,
113756
+ auth: spec.auth,
113757
+ scope: spec.scope,
113758
+ ...spec.caller === "required" ? { caller: "required" } : {}
113759
+ };
113760
+ return out;
113761
+ }
113551
113762
  var DEVICE_CHILDREN_BATCH_MAX = 256;
113552
113763
  var StaticDirOutputSchema = zod.z.object({ staticDir: zod.z.string() });
113553
113764
  var VersionOutputSchema = zod.z.object({ version: zod.z.string() });
@@ -114211,6 +114422,7 @@ var require_sleep_B8nfmQ8a = __commonJS({
114211
114422
  updateRule: (input) => dispatch("notification-rules", "notificationRules", "updateRule", "mutation", input),
114212
114423
  deleteRule: (input) => dispatch("notification-rules", "notificationRules", "deleteRule", "mutation", input),
114213
114424
  setRuleEnabled: (input) => dispatch("notification-rules", "notificationRules", "setRuleEnabled", "mutation", input),
114425
+ getClipRetentionAsks: (input) => dispatch("notification-rules", "notificationRules", "getClipRetentionAsks", "query", input),
114214
114426
  listDeviceMutes: (input) => dispatch("notification-rules", "notificationRules", "listDeviceMutes", "query", input),
114215
114427
  setDeviceMuted: (input) => dispatch("notification-rules", "notificationRules", "setDeviceMuted", "mutation", input),
114216
114428
  testRule: (input) => dispatch("notification-rules", "notificationRules", "testRule", "mutation", input),
@@ -114263,6 +114475,7 @@ var require_sleep_B8nfmQ8a = __commonJS({
114263
114475
  getSensorEvents: (input) => dispatch("pipeline-analytics", "pipelineAnalytics", "getSensorEvents", "query", input),
114264
114476
  getKeyEvents: (input) => dispatch("pipeline-analytics", "pipelineAnalytics", "getKeyEvents", "query", input),
114265
114477
  getKeyEventsBatch: (input) => dispatch("pipeline-analytics", "pipelineAnalytics", "getKeyEventsBatch", "query", input),
114478
+ readLongTermSeries: (input) => dispatch("pipeline-analytics", "pipelineAnalytics", "readLongTermSeries", "query", input),
114266
114479
  getEventDensity: (input) => dispatch("pipeline-analytics", "pipelineAnalytics", "getEventDensity", "query", input),
114267
114480
  getEventDensityBatch: (input) => dispatch("pipeline-analytics", "pipelineAnalytics", "getEventDensityBatch", "query", input),
114268
114481
  pruneEventsBefore: (input) => dispatch("pipeline-analytics", "pipelineAnalytics", "pruneEventsBefore", "mutation", input),
@@ -114563,6 +114776,7 @@ var require_sleep_B8nfmQ8a = __commonJS({
114563
114776
  pipelineRunner: {
114564
114777
  detachCamera: (input) => dispatchSystem("pipelineRunner", "detachCamera", "mutation", input),
114565
114778
  getCameraMetrics: (input) => dispatchSystem("pipelineRunner", "getCameraMetrics", "query", input),
114779
+ requestOccupancyBurst: (input) => dispatchSystem("pipelineRunner", "requestOccupancyBurst", "mutation", input),
114566
114780
  runDetailSubtree: (input) => dispatchSystem("pipelineRunner", "runDetailSubtree", "mutation", input),
114567
114781
  parkTrackFrame: (input) => dispatchSystem("pipelineRunner", "parkTrackFrame", "mutation", input),
114568
114782
  getParkedTrackFrame: (input) => dispatchSystem("pipelineRunner", "getParkedTrackFrame", "query", input),
@@ -115115,6 +115329,30 @@ var require_sleep_B8nfmQ8a = __commonJS({
115115
115329
  return createSliceHandle;
115116
115330
  }
115117
115331
  });
115332
+ Object.defineProperty(exports, "customAction", {
115333
+ enumerable: true,
115334
+ get: function() {
115335
+ return customAction;
115336
+ }
115337
+ });
115338
+ Object.defineProperty(exports, "defineCustomActions", {
115339
+ enumerable: true,
115340
+ get: function() {
115341
+ return defineCustomActions;
115342
+ }
115343
+ });
115344
+ Object.defineProperty(exports, "describeCustomActions", {
115345
+ enumerable: true,
115346
+ get: function() {
115347
+ return describeCustomActions;
115348
+ }
115349
+ });
115350
+ Object.defineProperty(exports, "deviceCustomAction", {
115351
+ enumerable: true,
115352
+ get: function() {
115353
+ return deviceCustomAction;
115354
+ }
115355
+ });
115118
115356
  Object.defineProperty(exports, "deviceOpsCapability", {
115119
115357
  enumerable: true,
115120
115358
  get: function() {
@@ -115309,7 +115547,7 @@ var require_addon = __commonJS({
115309
115547
  "../types/dist/addon.js"(exports) {
115310
115548
  "use strict";
115311
115549
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
115312
- var require_sleep = require_sleep_B8nfmQ8a();
115550
+ var require_sleep = require_sleep_DqtlfkSS();
115313
115551
  var require_event_category = require_event_category_BVfsrBYA();
115314
115552
  var require_err_msg = require_err_msg_COpsHMw2();
115315
115553
  var CAP_INPUT_DEFAULTS = Object.freeze({
@@ -115622,6 +115860,7 @@ var require_addon = __commonJS({
115622
115860
  exports.asString = require_sleep.asString;
115623
115861
  exports.createDeviceProxy = require_sleep.createDeviceProxy;
115624
115862
  exports.createEventBusSliceSource = require_sleep.createEventBusSliceSource;
115863
+ exports.describeCustomActions = require_sleep.describeCustomActions;
115625
115864
  exports.deviceOpsCapability = require_sleep.deviceOpsCapability;
115626
115865
  exports.emitReadiness = require_sleep.emitReadiness;
115627
115866
  exports.errMsg = require_err_msg.errMsg;
@@ -122176,9 +122415,9 @@ var require_dist2 = __commonJS({
122176
122415
  }
122177
122416
  });
122178
122417
 
122179
- // ../system/dist/manifest-system-deps-CrSP0Kkp.js
122180
- var require_manifest_system_deps_CrSP0Kkp = __commonJS({
122181
- "../system/dist/manifest-system-deps-CrSP0Kkp.js"(exports) {
122418
+ // ../system/dist/manifest-system-deps-CzyjTMcO.js
122419
+ var require_manifest_system_deps_CzyjTMcO = __commonJS({
122420
+ "../system/dist/manifest-system-deps-CzyjTMcO.js"(exports) {
122182
122421
  "use strict";
122183
122422
  var require_chunk = require_chunk_Cek0wNdY();
122184
122423
  require_hub_cap_forward_DmHNjbB0();
@@ -127283,10 +127522,104 @@ var require_manifest_system_deps_CrSP0Kkp = __commonJS({
127283
127522
  function __resetCapUsageRegistryForTests() {
127284
127523
  singleton = null;
127285
127524
  }
127525
+ var MIRROR_REASON_BY_CATEGORY = new Map([
127526
+ {
127527
+ category: "device.state-changed",
127528
+ reason: "Device runtime-state mirror, 69.1 % of fleet traffic. Each event is a snapshot of the slice AFTER the change; the superseded snapshot describes a state the device is no longer in, and every consumer (SystemMirror, DeviceStateHandle) reads the latest one only."
127529
+ },
127530
+ {
127531
+ category: "camera-streams.onCamStreamsChanged",
127532
+ reason: "Full stream-list snapshot per camera, 20.1 % of fleet traffic. The payload is the complete current list, not a delta, so an older list is strictly less true than the newer one."
127533
+ },
127534
+ {
127535
+ category: "system.ready-state",
127536
+ reason: "Readiness is a LEVEL, not an edge: the event reports whether a capability is ready right now. Declared for the case where it carries a deviceId; when it does not it stays in the global ring like any other unattributed event."
127537
+ }
127538
+ ].map((m) => [m.category, m.reason]));
127539
+ function isMirrorCategory(category) {
127540
+ return MIRROR_REASON_BY_CATEGORY.has(category);
127541
+ }
127542
+ var MAX_DEVICE_RING_EVENTS = 2e3;
127543
+ function serializePayload(data) {
127544
+ try {
127545
+ const json = JSON.stringify(data);
127546
+ if (typeof json !== "string") return null;
127547
+ return {
127548
+ json,
127549
+ bytes: Buffer.byteLength(json, "utf8")
127550
+ };
127551
+ } catch {
127552
+ return null;
127553
+ }
127554
+ }
127555
+ function capEventData(event) {
127556
+ const serialized = serializePayload(event.data);
127557
+ if (serialized !== null && serialized.bytes <= 256) return event;
127558
+ const truncated = {
127559
+ __truncated: true,
127560
+ __originalBytes: serialized?.bytes ?? null,
127561
+ __preview: serialized === null ? "" : serialized.json.slice(0, 160)
127562
+ };
127563
+ return {
127564
+ ...event,
127565
+ data: truncated
127566
+ };
127567
+ }
127568
+ function eventDeviceId(event) {
127569
+ const explicit = event.source.deviceId;
127570
+ if (explicit !== void 0) return Number.isFinite(explicit) ? explicit : void 0;
127571
+ if (event.source.type !== "device") return void 0;
127572
+ const asNumber = Number(event.source.id);
127573
+ return Number.isFinite(asNumber) ? asNumber : void 0;
127574
+ }
127575
+ function createDeviceEventRings() {
127576
+ return { byDevice: /* @__PURE__ */ new Map() };
127577
+ }
127578
+ function ringFor(rings, deviceId) {
127579
+ const existing = rings.byDevice.get(deviceId);
127580
+ if (existing !== void 0) {
127581
+ rings.byDevice.delete(deviceId);
127582
+ rings.byDevice.set(deviceId, existing);
127583
+ return existing;
127584
+ }
127585
+ const created = {
127586
+ history: [],
127587
+ mirrors: /* @__PURE__ */ new Map()
127588
+ };
127589
+ rings.byDevice.set(deviceId, created);
127590
+ while (rings.byDevice.size > 512) {
127591
+ const oldest = rings.byDevice.keys().next();
127592
+ if (oldest.done === true) break;
127593
+ rings.byDevice.delete(oldest.value);
127594
+ }
127595
+ return created;
127596
+ }
127597
+ function recordDeviceEvent(rings, event) {
127598
+ const deviceId = eventDeviceId(event);
127599
+ if (deviceId === void 0) return void 0;
127600
+ const ring = ringFor(rings, deviceId);
127601
+ const retained = capEventData(event);
127602
+ if (isMirrorCategory(event.category)) {
127603
+ ring.mirrors.set(event.category, retained);
127604
+ return deviceId;
127605
+ }
127606
+ ring.history.push(retained);
127607
+ if (ring.history.length > 2e3) ring.history.splice(0, ring.history.length - MAX_DEVICE_RING_EVENTS);
127608
+ return deviceId;
127609
+ }
127610
+ function getDeviceRecent(rings, deviceId) {
127611
+ const ring = rings.byDevice.get(deviceId);
127612
+ if (ring === void 0) return [];
127613
+ if (ring.mirrors.size === 0) return ring.history;
127614
+ const merged = [...ring.history, ...ring.mirrors.values()];
127615
+ merged.sort((a, b) => a.timestamp.getTime() - b.timestamp.getTime());
127616
+ return merged;
127617
+ }
127286
127618
  function createSharedBusState(retainRecent = false) {
127287
127619
  return {
127288
127620
  handlers: /* @__PURE__ */ new Map(),
127289
127621
  recent: [],
127622
+ deviceRings: createDeviceEventRings(),
127290
127623
  retainRecent
127291
127624
  };
127292
127625
  }
@@ -127394,6 +127727,7 @@ var require_manifest_system_deps_CrSP0Kkp = __commonJS({
127394
127727
  if (state.retainRecent && !isHighFrequencyCategory(event.category)) {
127395
127728
  state.recent.push(event);
127396
127729
  if (state.recent.length > 1e3) state.recent.splice(0, state.recent.length - MAX_RECENT_EVENTS);
127730
+ recordDeviceEvent(state.deviceRings, event);
127397
127731
  }
127398
127732
  const delivered = /* @__PURE__ */ new Set();
127399
127733
  for (const [pattern, set] of state.handlers) {
@@ -129788,14 +130122,15 @@ var require_manifest_system_deps_CrSP0Kkp = __commonJS({
129788
130122
  });
129789
130123
  },
129790
130124
  getRecent(filter, limit) {
129791
- const filtered = filter ? state.recent.filter((e) => {
130125
+ const source = filter?.deviceId !== void 0 ? getDeviceRecent(state.deviceRings, filter.deviceId) : state.recent;
130126
+ const filtered = filter ? source.filter((e) => {
129792
130127
  const cat = filter.category;
129793
130128
  if (cat) {
129794
130129
  const categories = typeof cat === "string" ? [cat] : Array.isArray(cat) ? cat : [];
129795
130130
  if (categories.length > 0 && !categories.some((c) => matchesPattern(String(c), e.category))) return false;
129796
130131
  }
129797
130132
  return matchesEventFilter(e, filter);
129798
- }) : state.recent;
130133
+ }) : source;
129799
130134
  return limit !== void 0 ? filtered.slice(-limit) : filtered;
129800
130135
  }
129801
130136
  };
@@ -131720,11 +132055,11 @@ var require_manifest_system_deps_CrSP0Kkp = __commonJS({
131720
132055
  }
131721
132056
  });
131722
132057
 
131723
- // ../system/dist/custom-action-registry-DG-QIWxd.js
131724
- var require_custom_action_registry_DG_QIWxd = __commonJS({
131725
- "../system/dist/custom-action-registry-DG-QIWxd.js"(exports) {
132058
+ // ../system/dist/custom-action-registry-acBY3mHA.js
132059
+ var require_custom_action_registry_acBY3mHA = __commonJS({
132060
+ "../system/dist/custom-action-registry-acBY3mHA.js"(exports) {
131726
132061
  "use strict";
131727
- var require_dist10 = require_dist_DaSCLJVH();
132062
+ var _camstack_types_addon = require_addon();
131728
132063
  var CustomActionRegistry = class {
131729
132064
  byAddon = /* @__PURE__ */ new Map();
131730
132065
  registerAddon(addonId, catalog, handler) {
@@ -131765,7 +132100,7 @@ var require_custom_action_registry_DG_QIWxd = __commonJS({
131765
132100
  for (const [addonId, actions] of this.byAddon) {
131766
132101
  const catalog = {};
131767
132102
  for (const [name, entry] of actions) catalog[name] = entry.spec;
131768
- out[addonId] = require_dist10.describeCustomActions(catalog);
132103
+ out[addonId] = (0, _camstack_types_addon.describeCustomActions)(catalog);
131769
132104
  }
131770
132105
  return out;
131771
132106
  }
@@ -135538,7 +135873,7 @@ var require_dist3 = __commonJS({
135538
135873
  "use strict";
135539
135874
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
135540
135875
  var require_chunk = require_chunk_Cek0wNdY();
135541
- var require_dist10 = require_dist_DaSCLJVH();
135876
+ var require_dist10 = require_dist_Dze0l7UM();
135542
135877
  var require_builtins_alerts_alerts_addon = require_alerts_addon();
135543
135878
  require_alerts();
135544
135879
  var require_formatter = require_formatter_DqAKDlvN();
@@ -135565,9 +135900,9 @@ var require_dist3 = __commonJS({
135565
135900
  var require_builtins_winston_logging_index = require_winston_logging();
135566
135901
  var require_event_loop_stall_monitor = require_event_loop_stall_monitor_CAsHdMwP();
135567
135902
  var require_tls$1 = require_tls_BFs4PzoW();
135568
- var require_manifest_system_deps = require_manifest_system_deps_CrSP0Kkp();
135903
+ var require_manifest_system_deps = require_manifest_system_deps_CzyjTMcO();
135569
135904
  var require_resource_monitor = require_resource_monitor_LVE1BoLs();
135570
- var require_custom_action_registry = require_custom_action_registry_DG_QIWxd();
135905
+ var require_custom_action_registry = require_custom_action_registry_acBY3mHA();
135571
135906
  var zod = require_zod();
135572
135907
  var node_crypto = __require("crypto");
135573
135908
  var _camstack_types_node = require_node();
@@ -216676,7 +217011,7 @@ var require_dist4 = __commonJS({
216676
217011
  "../types/dist/index.js"(exports) {
216677
217012
  "use strict";
216678
217013
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
216679
- var require_sleep = require_sleep_B8nfmQ8a();
217014
+ var require_sleep = require_sleep_DqtlfkSS();
216680
217015
  var require_event_category = require_event_category_BVfsrBYA();
216681
217016
  var require_canonical_hash = require_canonical_hash_9lydiEzx();
216682
217017
  var require_enums2 = require_enums();
@@ -219486,6 +219821,49 @@ var require_dist4 = __commonJS({
219486
219821
  pixels: entry.resolution.width * entry.resolution.height
219487
219822
  }])].sort((a, b) => compareToTarget(a.pixels, b.pixels, targetPixels))[0]?.entry;
219488
219823
  }
219824
+ var OVERLAY_LAYERS = [
219825
+ "motion",
219826
+ "objects",
219827
+ "discarded",
219828
+ "stationary"
219829
+ ];
219830
+ var DEFAULT_OVERLAY_LAYERS = [
219831
+ "motion",
219832
+ "objects",
219833
+ "stationary"
219834
+ ];
219835
+ var STATIONARY_OVERLAY_STYLE = {
219836
+ /** Border width in px, at the surface's own scale. */
219837
+ borderWidth: 2,
219838
+ /** Dashed, not solid — the census is not a live detection. */
219839
+ dashed: true,
219840
+ /** Dash on/off lengths in px, for a renderer that needs them explicitly
219841
+ * (React Native cannot express `border-dashed` without them). */
219842
+ dashPattern: [6, 4],
219843
+ /**
219844
+ * FULL opacity, deliberately.
219845
+ *
219846
+ * This was 0.7, to make a parked car quieter than a live subject. It made it
219847
+ * quieter by lying about its colour: a class hue at 70% over a dark frame
219848
+ * reads as a different hue, and the operator saw the census boxes as the
219849
+ * wrong colour — which they effectively were.
219850
+ *
219851
+ * The dash already says "censused", and it says it without touching the
219852
+ * hue. Two signals for one fact was one too many, and the one that had to go
219853
+ * is the one that corrupts a value the rest of the system agrees on: the
219854
+ * class colour comes from `EVENT_TAXONOMY` and must reach the screen intact
219855
+ * on every surface, or the palette is shared in name only.
219856
+ */
219857
+ opacity: 1,
219858
+ /** Corner radius in px. */
219859
+ borderRadius: 2
219860
+ };
219861
+ function formatParkedFor(ms) {
219862
+ if (!Number.isFinite(ms) || ms <= 0) return "0 s";
219863
+ if (ms < 6e4) return `${String(Math.round(ms / 1e3))} s`;
219864
+ if (ms < 36e5) return `${String(Math.round(ms / 6e4))} min`;
219865
+ return `${String(Math.round(ms / 36e5))} h`;
219866
+ }
219489
219867
  var FORMAT_KEYS = [
219490
219868
  "onnx",
219491
219869
  "coreml",
@@ -222370,6 +222748,21 @@ ${recipe.triggers.map((t, i) => emitTrigger(t, i)).join("\n\n")}
222370
222748
  mode: "singleton",
222371
222749
  deviceTypes: Object.values(require_sleep.DeviceType),
222372
222750
  runtimeState: StreamSignalsStatusSchema,
222751
+ /**
222752
+ * Runtime-state durability: **session** — mirrored in RAM, never written.
222753
+ *
222754
+ * The slice holds what the DEVICE says it can emit. That is a probed fact,
222755
+ * not an operator choice: the provider re-declares it on every registration,
222756
+ * so losing it loses nothing and persisting it would freeze an answer the
222757
+ * camera is entitled to change. Measured the same day on the sibling case —
222758
+ * `native-object-detection.supportedClasses` was persisted, and a firmware
222759
+ * class the camera really detected stayed missing for the life of the row
222760
+ * because the fix could not reach it.
222761
+ *
222762
+ * See `RuntimeStateDurability`. Enforced by
222763
+ * `scripts/check-runtime-state-durability.ts`.
222764
+ */
222765
+ durability: "session",
222373
222766
  methods: {
222374
222767
  /**
222375
222768
  * What this device can emit. Empty is a valid and common answer — most
@@ -223634,41 +224027,6 @@ ${recipe.triggers.map((t, i) => emitTrigger(t, i)).join("\n\n")}
223634
224027
  })) }), { auth: "admin" })
223635
224028
  }
223636
224029
  };
223637
- function defineCustomActions(spec) {
223638
- return spec;
223639
- }
223640
- function customAction(input, output, options) {
223641
- return {
223642
- input,
223643
- output,
223644
- kind: options?.kind ?? "query",
223645
- auth: options?.auth ?? "protected",
223646
- scope: options?.scope ?? { kind: "system" },
223647
- ...options?.caller ? { caller: "required" } : {}
223648
- };
223649
- }
223650
- function deviceCustomAction(input, output, options) {
223651
- return {
223652
- input,
223653
- output,
223654
- kind: options?.kind ?? "query",
223655
- auth: options?.auth ?? "protected",
223656
- scope: {
223657
- kind: "device",
223658
- ...options?.deviceTypes ? { deviceTypes: options.deviceTypes } : {}
223659
- }
223660
- };
223661
- }
223662
- function describeCustomActions(catalog) {
223663
- const out = {};
223664
- for (const [name, spec] of Object.entries(catalog)) out[name] = {
223665
- kind: spec.kind,
223666
- auth: spec.auth,
223667
- scope: spec.scope,
223668
- ...spec.caller === "required" ? { caller: "required" } : {}
223669
- };
223670
- return out;
223671
- }
223672
224030
  var CustomModelDescriptorSchema = zod.z.object({
223673
224031
  stepId: zod.z.string(),
223674
224032
  entry: ModelCatalogEntrySchema
@@ -230190,6 +230548,30 @@ ${recipe.triggers.map((t, i) => emitTrigger(t, i)).join("\n\n")}
230190
230548
  settings: NcAlarmSettingsSchema,
230191
230549
  coverage: zod.z.array(NcAlarmModeCoverageSchema)
230192
230550
  });
230551
+ var NC_CLIP_RETENTION_MAX_SEC = 60;
230552
+ var NcClipRetentionAskSchema = zod.z.object({
230553
+ /**
230554
+ * The camera this ask is about. **Absent = every camera**, which is what a
230555
+ * rule with no `conditions.devices` means: it can fire anywhere, so it is
230556
+ * asking everywhere.
230557
+ */
230558
+ deviceId: zod.z.number().int().nonnegative().optional(),
230559
+ /** Seconds of history the rule needs held for it. Never zero — a rule that
230560
+ * needs nothing produces no ask at all. */
230561
+ seconds: zod.z.number().min(0).max(60),
230562
+ /** The profile the rule cuts from, when it named one. Absent = the cheapest
230563
+ * assigned, which is what the cut defaults to. */
230564
+ profile: require_sleep.CamProfileSchema.optional(),
230565
+ /** Who is asking — so a retention the operator did not expect names a rule. */
230566
+ ruleId: zod.z.string(),
230567
+ ruleName: zod.z.string(),
230568
+ /** Why this many seconds: the rule's own window, or the occupancy ceiling. */
230569
+ reason: zod.z.enum(["window", "occupancy"])
230570
+ });
230571
+ var NcClipRetentionPlanSchema = zod.z.object({
230572
+ rulesLoaded: zod.z.boolean(),
230573
+ asks: zod.z.array(NcClipRetentionAskSchema).readonly()
230574
+ });
230193
230575
  var notificationRulesCapability = {
230194
230576
  name: "notification-rules",
230195
230577
  scope: "system",
@@ -230222,6 +230604,23 @@ ${recipe.triggers.map((t, i) => emitTrigger(t, i)).join("\n\n")}
230222
230604
  auth: "admin"
230223
230605
  }),
230224
230606
  /**
230607
+ * WHAT THE RULES ACTUALLY ASK the stream broker to retain, per camera.
230608
+ *
230609
+ * The notification centre owns the rules, so it is the only thing that can
230610
+ * say how much history a camera's notifications will ever reach back for.
230611
+ * Before this the broker guessed — a flat minute on every camera — and
230612
+ * learned the PROFILE reactively, after the first clip had already been cut
230613
+ * from the wrong one. This is the same ask stated once, in front.
230614
+ *
230615
+ * A QUERY, pulled by each node's broker, not a push: brokers are per node
230616
+ * (a camera's ring lives wherever its stream is ingested) while this cap is
230617
+ * a singleton, so a push would have to enumerate the cluster. The pull also
230618
+ * makes the failure mode right — a broker that cannot reach the centre
230619
+ * keeps the plan it has, and a plan that has never arrived is UNKNOWN
230620
+ * rather than empty (D49: a read that fails changes nothing).
230621
+ */
230622
+ getClipRetentionAsks: require_sleep.method(zod.z.object({}), NcClipRetentionPlanSchema, { auth: "admin" }),
230623
+ /**
230225
230624
  * PERMANENT per-camera mute — the notifications half of the per-camera
230226
230625
  * function switch group ([D61](../../../../docs/decisions/adr-0067.md)).
230227
230626
  *
@@ -232435,6 +232834,33 @@ ${recipe.triggers.map((t, i) => emitTrigger(t, i)).join("\n\n")}
232435
232834
  framesMatched: zod.z.number().int()
232436
232835
  });
232437
232836
  var RunReplayFrameProcessorResultSchema = zod.z.object({ tracks: zod.z.array(ReplayTrackSchema).readonly() });
232837
+ var AnalyticsLtsSeriesSchema = zod.z.enum([
232838
+ "motion",
232839
+ "audio-dbfs",
232840
+ "battery",
232841
+ "occupancy"
232842
+ ]);
232843
+ var LTS_SCOPE_CLASS_SEPARATOR = "|";
232844
+ function occupancyScope(zoneId, className) {
232845
+ const place = zoneId ?? "";
232846
+ return className === void 0 ? place : `${place}|${className}`;
232847
+ }
232848
+ function parseOccupancyScope(scope) {
232849
+ const at = scope.indexOf("|");
232850
+ if (at < 0) return { zoneId: scope };
232851
+ return {
232852
+ zoneId: scope.slice(0, at),
232853
+ className: scope.slice(at + 1)
232854
+ };
232855
+ }
232856
+ var LtsBucketSchema = zod.z.object({
232857
+ scope: zod.z.string(),
232858
+ bucketStart: zod.z.number().int(),
232859
+ samples: zod.z.number().int().nonnegative(),
232860
+ sum: zod.z.number(),
232861
+ min: zod.z.number(),
232862
+ max: zod.z.number()
232863
+ });
232438
232864
  var pipelineAnalyticsCapability = {
232439
232865
  name: "pipeline-analytics",
232440
232866
  scope: "device",
@@ -232578,6 +233004,30 @@ ${recipe.triggers.map((t, i) => emitTrigger(t, i)).join("\n\n")}
232578
233004
  getKeyEventsBatch: require_sleep.method(KeyEventBatchQueryInput, zod.z.array(KeyEventsForDeviceSchema).readonly()),
232579
233005
  /** Server-side bucketed event counts for the 24-hour timeline.
232580
233006
  * Returns one entry per non-empty bucket; empty buckets are omitted. */
233007
+ /**
233008
+ * Read one camera's long-term series — 5-minute buckets, kept for a year.
233009
+ *
233010
+ * This is the history surface for every chart that used to be served from a
233011
+ * RAM ring: the ring dies with the process, cannot answer about last night,
233012
+ * and had a 60-minute horizon, while these rows are ~60 bytes and already
233013
+ * written. `scope` is the series' own dimension — for `occupancy`, spell it
233014
+ * with {@link occupancyScope} rather than by hand, and omit it to get every
233015
+ * scope back at once (the caller then groups with
233016
+ * {@link parseOccupancyScope}).
233017
+ *
233018
+ * Bounds are inclusive on the BUCKET START, so a range that ends mid-bucket
233019
+ * still returns the bucket it lands in — the alternative is a chart whose
233020
+ * last column silently disappears for five minutes out of every five.
233021
+ */
233022
+ readLongTermSeries: require_sleep.method(zod.z.object({
233023
+ deviceId: zod.z.number(),
233024
+ series: AnalyticsLtsSeriesSchema,
233025
+ /** Omit for EVERY scope of this series in the range. */
233026
+ scope: zod.z.string().optional(),
233027
+ from: zod.z.number(),
233028
+ to: zod.z.number(),
233029
+ limit: zod.z.number().int().positive().optional()
233030
+ }), zod.z.array(LtsBucketSchema).readonly()),
232581
233031
  getEventDensity: require_sleep.method(zod.z.object({
232582
233032
  deviceId: zod.z.number(),
232583
233033
  since: zod.z.number(),
@@ -234080,6 +234530,12 @@ ${recipe.triggers.map((t, i) => emitTrigger(t, i)).join("\n\n")}
234080
234530
  queueDepth: zod.z.number(),
234081
234531
  frameLazy: FrameLazyMetricsSchema.optional()
234082
234532
  });
234533
+ var OccupancyBurstRefusalSchema = zod.z.enum([
234534
+ "not-attached",
234535
+ "battery-asleep",
234536
+ "not-watching",
234537
+ "already-bursting"
234538
+ ]);
234083
234539
  var pipelineRunnerCapability = {
234084
234540
  name: "pipeline-runner",
234085
234541
  scope: "system",
@@ -234116,6 +234572,50 @@ ${recipe.triggers.map((t, i) => emitTrigger(t, i)).join("\n\n")}
234116
234572
  /** List the deviceIds currently attached to this runner. */
234117
234573
  getLocalCameras: require_sleep.method(zod.z.void(), zod.z.array(zod.z.number()).readonly()),
234118
234574
  /**
234575
+ * Look at a camera NOW, out of band, because something just happened that
234576
+ * only a fresh look can settle.
234577
+ *
234578
+ * The periodic recheck (`occupancyRecheckSec`, 300 s) exists to watch a
234579
+ * still scene. It is the wrong instrument for a QUESTION that has just been
234580
+ * asked: on device 617 a parked car's departure was observed, a departure
234581
+ * strike was armed — and then the motion session ended, the strike decayed
234582
+ * after its 30 s TTL, and the next periodic look arrived up to five minutes
234583
+ * later with nothing left to confirm. Every one of those departures was
234584
+ * settled by the entry ageing out 6 to 10 minutes of observed time later,
234585
+ * and the notification's clip showed an empty space with nothing leaving
234586
+ * it.
234587
+ *
234588
+ * Two numbers make the ask specific, and a caller that ignores them wastes
234589
+ * the burst: a confirmation must land at least
234590
+ * `DEPARTURE_CONFIRM_MIN_GAP_MS` (3 s) after the read that armed the
234591
+ * strike — before that it is the same optical event and is refused — and
234592
+ * `DEPARTURE_ABSENCE_MIN_READS` (5) consecutive unassociated frames are
234593
+ * needed, while `occupancyRecheckFrames` defaults to FOUR. A burst of four
234594
+ * can never confirm an absence; that is why two periodic looks were always
234595
+ * required.
234596
+ *
234597
+ * The runner answers whether it actually started one. A refusal is NAMED,
234598
+ * never a silent `false`: a camera that is asleep on battery (D173 — this
234599
+ * must not become a self-initiated wake), detached, mid-session or already
234600
+ * bursting are four different facts, and a caller told only "no" cannot
234601
+ * tell a protection from a bug.
234602
+ */
234603
+ requestOccupancyBurst: require_sleep.method(zod.z.object({
234604
+ deviceId: zod.z.number(),
234605
+ /** How many frames to collect. The caller sizes this against what its
234606
+ * own confirmation needs; the runner clamps it to the field's range. */
234607
+ frames: zod.z.number().int().positive().optional(),
234608
+ /** Why, for the log. A burst nobody can attribute is a cost nobody can
234609
+ * defend — the periodic one at least has a timer to point at. */
234610
+ reason: zod.z.string()
234611
+ }), zod.z.object({
234612
+ started: zod.z.boolean(),
234613
+ refusedBecause: OccupancyBurstRefusalSchema.optional()
234614
+ }), {
234615
+ auth: "admin",
234616
+ kind: "mutation"
234617
+ }),
234618
+ /**
234119
234619
  * Best-effort NATIVE-resolution crop of a retention-ring frame. Given the
234120
234620
  * `FrameHandle` that rode an inference-result event and a normalized `bbox`,
234121
234621
  * the runner asks the decode worker still holding that frame's NATIVE
@@ -246057,7 +246557,28 @@ ${recipe.triggers.map((t, i) => emitTrigger(t, i)).join("\n\n")}
246057
246557
  /** Total tracked objects in this scope (frame / zone / unzoned). */
246058
246558
  totalObjects: zod.z.number().int().nonnegative(),
246059
246559
  /** Per-class count. Keys are macro class names (e.g. `person`, `car`). */
246060
- byClass: zod.z.record(zod.z.string(), zod.z.number().int().nonnegative())
246560
+ byClass: zod.z.record(zod.z.string(), zod.z.number().int().nonnegative()),
246561
+ /**
246562
+ * Of `totalObjects`, how many are STANDING — objects the census holds,
246563
+ * present but not going anywhere (a parked car, a bin, a statue).
246564
+ *
246565
+ * The operator's question about a scene has two halves and they answer
246566
+ * different things: "what is parked here" is stable for hours and must not
246567
+ * flap, while "who is walking through" is the thing an alert is about. One
246568
+ * number could only serve one of them, and `totalObjects` served the first
246569
+ * badly — a passer-by moved it and every occupancy rule saw a change.
246570
+ *
246571
+ * `standing + transient === totalObjects`, always. The total keeps its old
246572
+ * meaning exactly, so no rule written against it changes behaviour.
246573
+ *
246574
+ * ABSENT means UNKNOWN, never zero (D393): a snapshot from a node older than
246575
+ * this field cannot say, and a reader that folds absence in as 0 reports "no
246576
+ * parked objects here" about a camera whose lot is full.
246577
+ */
246578
+ standingObjects: zod.z.number().int().nonnegative().optional(),
246579
+ /** Of `totalObjects`, how many are passing through. See `standingObjects` —
246580
+ * same absence rule. */
246581
+ transientObjects: zod.z.number().int().nonnegative().optional()
246061
246582
  });
246062
246583
  var ZoneScopeBreakdownSchema = PerScopeBreakdownSchema.extend({
246063
246584
  zoneId: zod.z.string(),
@@ -253334,6 +253855,12 @@ ${recipe.triggers.map((t, i) => emitTrigger(t, i)).join("\n\n")}
253334
253855
  addonId: null,
253335
253856
  access: "view"
253336
253857
  },
253858
+ "notificationRules.getClipRetentionAsks": {
253859
+ capName: "notification-rules",
253860
+ capScope: "system",
253861
+ addonId: null,
253862
+ access: "view"
253863
+ },
253337
253864
  "notificationRules.getConditionCatalog": {
253338
253865
  capName: "notification-rules",
253339
253866
  capScope: "system",
@@ -253844,6 +254371,12 @@ ${recipe.triggers.map((t, i) => emitTrigger(t, i)).join("\n\n")}
253844
254371
  addonId: null,
253845
254372
  access: "create"
253846
254373
  },
254374
+ "pipelineAnalytics.readLongTermSeries": {
254375
+ capName: "pipeline-analytics",
254376
+ capScope: "device",
254377
+ addonId: null,
254378
+ access: "view"
254379
+ },
253847
254380
  "pipelineAnalytics.rebuildObjectEmbeddings": {
253848
254381
  capName: "pipeline-analytics",
253849
254382
  capScope: "device",
@@ -254516,6 +255049,12 @@ ${recipe.triggers.map((t, i) => emitTrigger(t, i)).join("\n\n")}
254516
255049
  addonId: null,
254517
255050
  access: "create"
254518
255051
  },
255052
+ "pipelineRunner.requestOccupancyBurst": {
255053
+ capName: "pipeline-runner",
255054
+ capScope: "system",
255055
+ addonId: null,
255056
+ access: "create"
255057
+ },
254519
255058
  "pipelineRunner.runDetailSubtree": {
254520
255059
  capName: "pipeline-runner",
254521
255060
  capScope: "system",
@@ -257926,6 +258465,11 @@ ${recipe.triggers.map((t, i) => emitTrigger(t, i)).join("\n\n")}
257926
258465
  form: "single",
257927
258466
  optional: false
257928
258467
  }],
258468
+ "pipelineAnalytics.readLongTermSeries": [{
258469
+ name: "deviceId",
258470
+ form: "single",
258471
+ optional: false
258472
+ }],
257929
258473
  "pipelineAnalytics.rebuildObjectEmbeddings": [{
257930
258474
  name: "deviceId",
257931
258475
  form: "single",
@@ -258116,6 +258660,11 @@ ${recipe.triggers.map((t, i) => emitTrigger(t, i)).join("\n\n")}
258116
258660
  form: "single",
258117
258661
  optional: false
258118
258662
  }],
258663
+ "pipelineRunner.requestOccupancyBurst": [{
258664
+ name: "deviceId",
258665
+ form: "single",
258666
+ optional: false
258667
+ }],
258119
258668
  "pipelineRunner.runDetailSubtree": [{
258120
258669
  name: "deviceId",
258121
258670
  form: "single",
@@ -258799,6 +259348,7 @@ ${recipe.triggers.map((t, i) => emitTrigger(t, i)).join("\n\n")}
258799
259348
  "pipelineRunner.parkTrackFrame",
258800
259349
  "pipelineRunner.releaseParkedTrackFrames",
258801
259350
  "pipelineRunner.reportMotion",
259351
+ "pipelineRunner.requestOccupancyBurst",
258802
259352
  "pipelineRunner.runDetailSubtree",
258803
259353
  "pipelineRunner.runStatelessStep",
258804
259354
  "plateGallery.getPlateByTrack",
@@ -262607,6 +263157,7 @@ ${recipe.triggers.map((t, i) => emitTrigger(t, i)).join("\n\n")}
262607
263157
  exports.AlertSourceSchema = AlertSourceSchema;
262608
263158
  exports.AlertStatusSchema = AlertStatusSchema;
262609
263159
  exports.AmbientLightSensorStatusSchema = AmbientLightSensorStatusSchema;
263160
+ exports.AnalyticsLtsSeriesSchema = AnalyticsLtsSeriesSchema;
262610
263161
  exports.ApiKeyRecordSchema = ApiKeyRecordSchema;
262611
263162
  exports.ApiKeySummarySchema = ApiKeySummarySchema;
262612
263163
  exports.ArchiveEntrySchema = ArchiveEntrySchema;
@@ -262801,6 +263352,7 @@ ${recipe.triggers.map((t, i) => emitTrigger(t, i)).join("\n\n")}
262801
263352
  exports.DEFAULT_FIRST_SIGHTING_FRESHNESS_MS = DEFAULT_FIRST_SIGHTING_FRESHNESS_MS;
262802
263353
  exports.DEFAULT_MIN_LANDMARK_FACE_SIZE_PX = DEFAULT_MIN_LANDMARK_FACE_SIZE_PX;
262803
263354
  exports.DEFAULT_NATIVE_LEASE_SETTINGS = DEFAULT_NATIVE_LEASE_SETTINGS;
263355
+ exports.DEFAULT_OVERLAY_LAYERS = DEFAULT_OVERLAY_LAYERS;
262804
263356
  exports.DEFAULT_POOL_MEMORY_POLICY = DEFAULT_POOL_MEMORY_POLICY;
262805
263357
  exports.DEFAULT_RECORDING_PROFILES = DEFAULT_RECORDING_PROFILES;
262806
263358
  exports.DEFAULT_RETENTION = DEFAULT_RETENTION;
@@ -262984,6 +263536,7 @@ ${recipe.triggers.map((t, i) => emitTrigger(t, i)).join("\n\n")}
262984
263536
  exports.LOAD_CONTRIBUTION_ROLES = LOAD_CONTRIBUTION_ROLES;
262985
263537
  exports.LOG_CHANNEL_TICK_MS = LOG_CHANNEL_TICK_MS;
262986
263538
  exports.LOG_LEVEL_RANK = LOG_LEVEL_RANK;
263539
+ exports.LTS_SCOPE_CLASS_SEPARATOR = LTS_SCOPE_CLASS_SEPARATOR;
262987
263540
  exports.LabelAttributionSchema = LabelAttributionSchema;
262988
263541
  exports.LabelDefinitionSchema = LabelDefinitionSchema;
262989
263542
  exports.LabelTierSchema = LabelTierSchema;
@@ -263044,6 +263597,7 @@ ${recipe.triggers.map((t, i) => emitTrigger(t, i)).join("\n\n")}
263044
263597
  exports.LoggingSettingsStateSchema = LoggingSettingsStateSchema;
263045
263598
  exports.LoginMethodContributionSchema = LoginMethodContributionSchema;
263046
263599
  exports.LoginStageEnum = LoginStageEnum;
263600
+ exports.LtsBucketSchema = LtsBucketSchema;
263047
263601
  exports.MACRO_LABELS = MACRO_LABELS;
263048
263602
  exports.MAX_ARCHIVED_DEBUG_NOTES = MAX_ARCHIVED_DEBUG_NOTES;
263049
263603
  exports.MAX_BIRTH_DECISION_RECORDS = MAX_BIRTH_DECISION_RECORDS;
@@ -263157,6 +263711,7 @@ ${recipe.triggers.map((t, i) => emitTrigger(t, i)).join("\n\n")}
263157
263711
  exports.NC_AUDIO_SEED = NC_AUDIO_SEED;
263158
263712
  exports.NC_AUTHORABLE_SYSTEM_EVENT_KINDS = NC_AUTHORABLE_SYSTEM_EVENT_KINDS;
263159
263713
  exports.NC_BASE_CONDITION_KEYS = NC_BASE_CONDITION_KEYS;
263714
+ exports.NC_CLIP_RETENTION_MAX_SEC = NC_CLIP_RETENTION_MAX_SEC;
263160
263715
  exports.NC_CONDITION_CATALOG = NC_CONDITION_CATALOG;
263161
263716
  exports.NC_CONFIRM_DEFAULT_MAX_IMAGE_PX = NC_CONFIRM_DEFAULT_MAX_IMAGE_PX;
263162
263717
  exports.NC_CONFIRM_DEFAULT_TIMEOUT_MS = NC_CONFIRM_DEFAULT_TIMEOUT_MS;
@@ -263205,6 +263760,8 @@ ${recipe.triggers.map((t, i) => emitTrigger(t, i)).join("\n\n")}
263205
263760
  exports.NcAlarmSkipReasonSchema = NcAlarmSkipReasonSchema;
263206
263761
  exports.NcAlarmSkippedDeviceSchema = NcAlarmSkippedDeviceSchema;
263207
263762
  exports.NcAudioConditionSchema = NcAudioConditionSchema;
263763
+ exports.NcClipRetentionAskSchema = NcClipRetentionAskSchema;
263764
+ exports.NcClipRetentionPlanSchema = NcClipRetentionPlanSchema;
263208
263765
  exports.NcConditionDescriptorSchema = NcConditionDescriptorSchema;
263209
263766
  exports.NcConditionsSchema = NcConditionsSchema;
263210
263767
  exports.NcConfirmExpectSchema = NcConfirmExpectSchema;
@@ -263258,8 +263815,10 @@ ${recipe.triggers.map((t, i) => emitTrigger(t, i)).join("\n\n")}
263258
263815
  exports.OPS_LOG_DEFAULT_LIMIT = OPS_LOG_DEFAULT_LIMIT;
263259
263816
  exports.OPS_LOG_RING_DEFAULT_MAX = OPS_LOG_RING_DEFAULT_MAX;
263260
263817
  exports.OVERFLOW_REASON = OVERFLOW_REASON;
263818
+ exports.OVERLAY_LAYERS = OVERLAY_LAYERS;
263261
263819
  exports.OauthIntegrationDescriptorSchema = OauthIntegrationDescriptorSchema;
263262
263820
  exports.ObjectEventSchema = ObjectEventSchema;
263821
+ exports.OccupancyBurstRefusalSchema = OccupancyBurstRefusalSchema;
263263
263822
  exports.OpsLogDomainSchema = OpsLogDomainSchema;
263264
263823
  exports.OpsLogEntrySchema = OpsLogEntrySchema;
263265
263824
  exports.OpsLogOpSchema = OpsLogOpSchema;
@@ -263443,6 +264002,7 @@ ${recipe.triggers.map((t, i) => emitTrigger(t, i)).join("\n\n")}
263443
264002
  exports.SOURCE_CAP_CHANGED_AT_FIELD = SOURCE_CAP_CHANGED_AT_FIELD;
263444
264003
  exports.SOURCE_DEVICE_TYPES = SOURCE_DEVICE_TYPES;
263445
264004
  exports.SOURCE_INFO_METADATA_KEY = SOURCE_INFO_METADATA_KEY;
264005
+ exports.STATIONARY_OVERLAY_STYLE = STATIONARY_OVERLAY_STYLE;
263446
264006
  exports.STORAGE_ACCESS_FALLBACK = STORAGE_ACCESS_FALLBACK;
263447
264007
  exports.STORAGE_BYTES_PER_GB = STORAGE_BYTES_PER_GB;
263448
264008
  exports.STORAGE_LOCATION_MODES = STORAGE_LOCATION_MODES;
@@ -263775,7 +264335,7 @@ ${recipe.triggers.map((t, i) => emitTrigger(t, i)).join("\n\n")}
263775
264335
  exports.createRuntimeStateBridge = createRuntimeStateBridge;
263776
264336
  exports.createSliceHandle = require_sleep.createSliceHandle;
263777
264337
  exports.createSystemProxy = createSystemProxy;
263778
- exports.customAction = customAction;
264338
+ exports.customAction = require_sleep.customAction;
263779
264339
  exports.customModelRegistryCapability = customModelRegistryCapability;
263780
264340
  exports.dataStoreProviderCapability = dataStoreProviderCapability;
263781
264341
  exports.dayNightCapability = dayNightCapability;
@@ -263785,18 +264345,18 @@ ${recipe.triggers.map((t, i) => emitTrigger(t, i)).join("\n\n")}
263785
264345
  exports.decoderCapability = decoderCapability;
263786
264346
  exports.defaultDeliveryForSection = defaultDeliveryForSection;
263787
264347
  exports.defaultDeviceFor = defaultDeviceFor;
263788
- exports.defineCustomActions = defineCustomActions;
264348
+ exports.defineCustomActions = require_sleep.defineCustomActions;
263789
264349
  exports.deriveBatteryPresence = deriveBatteryPresence;
263790
264350
  exports.deriveCameraSwitches = deriveCameraSwitches;
263791
264351
  exports.deriveDetailCropRect = deriveDetailCropRect;
263792
264352
  exports.deriveRecordingMode = deriveRecordingMode;
263793
- exports.describeCustomActions = describeCustomActions;
264353
+ exports.describeCustomActions = require_sleep.describeCustomActions;
263794
264354
  exports.describeModelVariant = describeModelVariant;
263795
264355
  exports.detectAccessRole = detectAccessRole;
263796
264356
  exports.detectionPipelineCapability = detectionPipelineCapability;
263797
264357
  exports.deviceAdoptionCapability = deviceAdoptionCapability;
263798
264358
  exports.deviceBackendToFormat = deviceBackendToFormat;
263799
- exports.deviceCustomAction = deviceCustomAction;
264359
+ exports.deviceCustomAction = require_sleep.deviceCustomAction;
263800
264360
  exports.deviceDiscoveryCapability = deviceDiscoveryCapability;
263801
264361
  exports.deviceExportCapability = deviceExportCapability;
263802
264362
  exports.deviceManagerCapability = deviceManagerCapability;
@@ -263846,6 +264406,7 @@ ${recipe.triggers.map((t, i) => emitTrigger(t, i)).join("\n\n")}
263846
264406
  exports.formatForBackend = formatForBackend;
263847
264407
  exports.formatForRuntime = formatForRuntime;
263848
264408
  exports.formatMediaOwnerKey = formatMediaOwnerKey;
264409
+ exports.formatParkedFor = formatParkedFor;
263849
264410
  exports.gasCapability = gasCapability;
263850
264411
  exports.gbToBytes = gbToBytes;
263851
264412
  exports.generateAutomationBlock = generateAutomationBlock;
@@ -263962,6 +264523,7 @@ ${recipe.triggers.map((t, i) => emitTrigger(t, i)).join("\n\n")}
263962
264523
  exports.numericSensorCapability = numericSensorCapability;
263963
264524
  exports.oauthIntegrationCapability = oauthIntegrationCapability;
263964
264525
  exports.objectInputDeclaresAddonId = objectInputDeclaresAddonId;
264526
+ exports.occupancyScope = occupancyScope;
263965
264527
  exports.osdCapability = osdCapability;
263966
264528
  exports.osdManagerCapability = osdManagerCapability;
263967
264529
  exports.overlayClusterStepSettings = overlayClusterStepSettings;
@@ -263971,6 +264533,7 @@ ${recipe.triggers.map((t, i) => emitTrigger(t, i)).join("\n\n")}
263971
264533
  exports.parseJsonObject = require_sleep.parseJsonObject;
263972
264534
  exports.parseJsonUnknown = require_sleep.parseJsonUnknown;
263973
264535
  exports.parseMediaOwnerKey = parseMediaOwnerKey;
264536
+ exports.parseOccupancyScope = parseOccupancyScope;
263974
264537
  exports.parseProcStatus = parseProcStatus;
263975
264538
  exports.parseProfileBrokerId = require_sleep.parseProfileBrokerId;
263976
264539
  exports.parseRuleSection = parseRuleSection;