@camstack/addon-provider-reolink 1.2.168 → 1.2.170

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 (3) hide show
  1. package/dist/addon.js +631 -172
  2. package/dist/addon.mjs +631 -172
  3. package/package.json +1 -3
package/dist/addon.js CHANGED
@@ -7503,7 +7503,7 @@ var DeviceRole = /* @__PURE__ */ function(DeviceRole) {
7503
7503
  return DeviceRole;
7504
7504
  }({});
7505
7505
  //#endregion
7506
- //#region ../types/dist/composition-43aqsZQj.mjs
7506
+ //#region ../types/dist/composition-Bzr7GwgP.mjs
7507
7507
  /**
7508
7508
  * The ffmpeg build every CamStack node downloads, per platform and arch.
7509
7509
  *
@@ -7557,20 +7557,20 @@ function portable(target) {
7557
7557
  }
7558
7558
  portable("linux64"), portable("linuxarm64"), portable("macarm64"), portable("mac64");
7559
7559
  /**
7560
- * LA tabella "quale booleano di questo tipo di device conta come ALTO", e il
7561
- * valutatore puro del suo FRONTE.
7560
+ * THE table "which boolean of this device type counts as HIGH", and the
7561
+ * pure evaluator of its EDGE.
7562
7562
  *
7563
- * UNA tabella per tutti quelli che chiedono "questo device è ALTO?": il
7564
- * trigger `RecordingTriggers.sensorDeviceIds` del recorder, i marker dei
7565
- * sensori della post-analysis, il bridge camera-sensors dell'orchestratore e
7566
- * le sorgenti di un campanello composto (`doorbellFeatureSources`, D671).
7567
- * Una seconda copia divergerebbe alla prima cap aggiunta, e il sintomo — "il
7568
- * sensore fa suonare il campanello ma non registra" — è esattamente D62.
7563
+ * ONE table for everyone who asks "is this device HIGH?": the
7564
+ * recorder's `RecordingTriggers.sensorDeviceIds` trigger, the post-analysis
7565
+ * sensor markers, the orchestrator's camera-sensors bridge and
7566
+ * the sources of a composite doorbell (`doorbellFeatureSources`, D671).
7567
+ * A second copy would diverge at the first cap added, and the symptom — "the
7568
+ * sensor rings the doorbell but does not record" — is exactly D62.
7569
7569
  *
7570
- * ⚠ NON è `DEVICE_STATE_READERS` (`catalogs/device-state-vocabulary.ts`), e le
7571
- * due non vanno unificate: quella risponde a "qual è la PAROLA di stato per una
7572
- * regola" (e include `presence`, `cover`, `alarm-panel`), questa a "qual è il
7573
- * booleano il cui FRONTE conta". Vocabolari deliberatamente diversi.
7570
+ * ⚠ NOT `DEVICE_STATE_READERS` (`catalogs/device-state-vocabulary.ts`), and the
7571
+ * two must not be unified: that one answers "what is the state WORD for a
7572
+ * rule" (and includes `presence`, `cover`, `alarm-panel`), this one "which
7573
+ * boolean's EDGE counts". Deliberately different vocabularies.
7574
7574
  */
7575
7575
  /**
7576
7576
  * Known binary / switch source caps → the boolean slice field whose
@@ -7591,6 +7591,8 @@ var SOURCE_CAP_ACTIVE_FIELD = {
7591
7591
  vibration: "detected",
7592
7592
  tamper: "tampered"
7593
7593
  };
7594
+ /** Cap names whose presence in a device's bindings qualify it as a source. */
7595
+ var SOURCE_CAPS = Object.keys(SOURCE_CAP_ACTIVE_FIELD);
7594
7596
  /**
7595
7597
  * Error types for the safe expression engine. Two distinct classes so callers
7596
7598
  * can tell a compile-time (grammar) failure from a runtime (evaluation)
@@ -9197,22 +9199,22 @@ var CLASS_MAP_MACRO_TARGETS = [
9197
9199
  "package"
9198
9200
  ];
9199
9201
  /**
9200
- * Le macro classi di PRIMO LIVELLO: quelle che un object detector emette e che
9201
- * un operatore può selezionare.
9202
+ * The FIRST-LEVEL macro classes: those an object detector emits and that
9203
+ * an operator can select.
9202
9204
  *
9203
- * Sono le tre offerte dallo step `object-detection`
9205
+ * They are the three offered by the `object-detection` step
9204
9206
  * (`addon-pipeline/src/detection-pipeline/registry/step-definitions.ts`,
9205
- * `enabledMacroClasses`). `package` sta in {@link CLASS_MAP_MACRO_TARGETS} e in
9206
- * `MACRO_LABELS` — è una macro vera — ma NON qui: appartiene allo step
9207
- * `package-detection`, la cui abilitazione è guidata dalle zone, e offrire la
9208
- * stessa parola due volte ha già fatto accendere a un operatore il proxy COCO
9207
+ * `enabledMacroClasses`). `package` is in {@link CLASS_MAP_MACRO_TARGETS} and in
9208
+ * `MACRO_LABELS` — it is a true macro — but NOT here: it belongs to the step
9209
+ * `package-detection`, whose enablement is driven by zones, and offering the
9210
+ * same word twice has already made an operator turn on the COCO proxy
9209
9211
  * (suitcase/backpack/handbag) lasciando spento il detector dedicato.
9210
9212
  *
9211
- * UNA lista. Prima di oggi le stesse tre erano scritte a mano nell'offerta
9212
- * dello step e una seconda volta come union `FirstLevelMacro`
9213
- * (`types/detection.ts`); una terza copia per il trigger di registrazione
9214
- * (`RecordingTriggers.objectClasses`) avrebbe reso invisibile la divergenza
9215
- * successiva.
9213
+ * ONE list. Before today the same three were hand-written in the step's offer
9214
+ * and a second time as the union `FirstLevelMacro`
9215
+ * (`types/detection.ts`); a third copy for the recording trigger
9216
+ * (`RecordingTriggers.objectClasses`) would have made the later divergence
9217
+ * invisible.
9216
9218
  */
9217
9219
  var FIRST_LEVEL_MACRO_CLASSES = [
9218
9220
  "person",
@@ -9277,17 +9279,17 @@ var RecordingStorageModeSchema = _enum([
9277
9279
  "on-device-decision"
9278
9280
  ]);
9279
9281
  /**
9280
- * Le macro classi che possono aprire una finestra di registrazione — le stesse
9281
- * tre offerte dallo step `object-detection`, da UNA lista
9282
+ * The macro classes that can open a recording window — the same
9283
+ * three offered by the `object-detection` step, from ONE list
9282
9284
  * ({@link FIRST_LEVEL_MACRO_CLASSES}).
9283
9285
  */
9284
9286
  var RecordingObjectTriggerClassSchema = _enum(FIRST_LEVEL_MACRO_CLASSES);
9285
9287
  /**
9286
- * True quando `values` non ripete un elemento.
9288
+ * True when `values` does not repeat an element.
9287
9289
  *
9288
- * Un duplicato non è innocuo: ogni voce di `objectClasses` / `sensorDeviceIds`
9289
- * diventa una SORGENTE in `bandTriggerSources`, e la stessa sorgente due volte
9290
- * conterebbe due volte le sue finestre in `segmentMissedByMs`.
9290
+ * A duplicate is not harmless: every entry of `objectClasses` / `sensorDeviceIds`
9291
+ * becomes a SOURCE in `bandTriggerSources`, and the same source twice
9292
+ * would count its windows twice in `segmentMissedByMs`.
9291
9293
  */
9292
9294
  var noDuplicates = (values) => new Set(values).size === values.length;
9293
9295
  /** Which detectors trigger an `events`-mode band. */
@@ -9295,34 +9297,34 @@ var RecordingTriggersSchema = object({
9295
9297
  motion: boolean().optional(),
9296
9298
  audioThresholdDbfs: number().optional(),
9297
9299
  /**
9298
- * Le macro classi la cui detection apre una finestra. ASSENTE = la sorgente
9299
- * non è ascoltata; un array VUOTO è rifiutato, perché "banda events, trigger
9300
- * object acceso, nessuna classe" è la stessa forma "abilitata e non registra
9301
- * nulla, per sempre" contro cui è scritto `eventsBandCanEverDemand`.
9300
+ * The macro classes whose detection opens a window. ABSENT = the source
9301
+ * is not listened to; an EMPTY array is rejected, because "events band, object
9302
+ * trigger on, no class" is the same shape "enabled and records
9303
+ * nothing, forever" that `eventsBandCanEverDemand` is written against.
9302
9304
  *
9303
- * Il segnale letto è GIÀ FILTRATO: solo detection `source: 'pipeline'`, cioè
9304
- * quelle che hanno attraversato `enabledMacroClasses`, i
9305
- * `minConfidence<Macro>` e il full-frame guard. L'AI a bordo camera
9306
- * (`source: 'onboard'`) non attraversa nessuno di quei gate e NON apre
9307
- * finestre — vedi `recorder/object-trigger.ts`.
9305
+ * The signal read is ALREADY FILTERED: only `source: 'pipeline'` detections, i.e.
9306
+ * those that went through `enabledMacroClasses`, the
9307
+ * `minConfidence<Macro>` and the full-frame guard. The camera's onboard AI
9308
+ * (`source: 'onboard'`) goes through none of those gates and does NOT open
9309
+ * windows — see `recorder/object-trigger.ts`.
9308
9310
  */
9309
9311
  objectClasses: array(RecordingObjectTriggerClassSchema).min(1).refine(noDuplicates, { message: "objectClasses must not repeat a class" }).optional(),
9310
9312
  /**
9311
- * I device LINKED il cui FRONTE ALTO apre una finestra. Assente = la sorgente
9312
- * non è ascoltata; un array vuoto è rifiutato per la stessa ragione di
9313
+ * The LINKED devices whose RISING EDGE opens a window. Absent = the source
9314
+ * is not listened to; an empty array is rejected for the same reason as
9313
9315
  * `objectClasses`.
9314
9316
  *
9315
- * Sono id di device SORGENTE, non camere: la banda li nomina, quindi il
9316
- * percorso caldo (`DeviceStateChanged`, a ritmo di bus su tutta la flotta)
9317
- * non fa RPC. L'OFFERTA da cui l'operatore li sceglie è un'altra domanda, e
9318
- * si risolve con `deviceManager.getLinkedDevices` + `getBindingsBatch` per
9319
- * device (D12) — mai un elenco globale di cap.
9317
+ * These are SOURCE device ids, not cameras: the band names them, so the
9318
+ * hot path (`DeviceStateChanged`, at bus rate across the whole fleet)
9319
+ * does no RPC. The OFFER from which the operator picks them is another question, and
9320
+ * is resolved with `deviceManager.getLinkedDevices` + `getBindingsBatch` per
9321
+ * device (D12) — never a global list of caps.
9320
9322
  *
9321
- * Cosa vuol dire "alto" dipende dal TIPO di device e non è deciso qui:
9322
- * `SOURCE_CAP_ACTIVE_FIELD` (`catalogs/sensor-active-state.ts`) è LA tabella,
9323
- * la stessa del campanello composto (D671). Ed è il FRONTE, non
9324
- * il livello: un contatto trovato già aperto al riavvio del runner non fa
9325
- * registrare.
9323
+ * What "high" means depends on the device TYPE and is not decided here:
9324
+ * `SOURCE_CAP_ACTIVE_FIELD` (`catalogs/sensor-active-state.ts`) is THE table,
9325
+ * the same one as the composite doorbell (D671). And it is the EDGE, not
9326
+ * the level: a contact found already open at runner restart does not
9327
+ * record.
9326
9328
  */
9327
9329
  sensorDeviceIds: array(number().int().positive()).min(1).max(16).refine(noDuplicates, { message: "sensorDeviceIds must not repeat a device" }).optional()
9328
9330
  });
@@ -10574,7 +10576,7 @@ function findTimezone(id) {
10574
10576
  * - **VALUE** — at which level, for which scope, until when. That stays ONE
10575
10577
  * thing: the logging settings document on the `system` cap. Two authorities
10576
10578
  * over the values is the exact defect
10577
- * `docs/design/plans/2026-08-26-logging-per-componente.md` was written to
10579
+ * `docs/design/plans/2026-08-26-per-component-logging.md` was written to
10578
10580
  * remove; re-introducing it from the cure side would be grotesque.
10579
10581
  *
10580
10582
  * Nothing in this file reads a clock, an env var or a store. The registry is
@@ -12642,7 +12644,7 @@ var BrokerStatusEnum = _enum([
12642
12644
  "unreachable",
12643
12645
  "error"
12644
12646
  ]);
12645
- var BrokerInfoSchema$1 = object({
12647
+ var BrokerInfoSchema = object({
12646
12648
  /** Stable broker id. Persisted; survives addon restarts. */
12647
12649
  id: string(),
12648
12650
  /** Addon id of the provider that OWNS this broker.
@@ -12775,7 +12777,7 @@ var GetStateInputSchema = object({
12775
12777
  * HA: entity_id (returns the cached entity state). */
12776
12778
  key: string()
12777
12779
  });
12778
- method(ListInputSchema, array(BrokerInfoSchema$1)), method(GetInputSchema, BrokerInfoSchema$1.nullable()), method(_void(), array(BrokerProviderInfoSchema), { auth: "admin" }), method(AddInputSchema, AddResultSchema, {
12780
+ method(ListInputSchema, array(BrokerInfoSchema)), method(GetInputSchema, BrokerInfoSchema.nullable()), method(_void(), array(BrokerProviderInfoSchema), { auth: "admin" }), method(AddInputSchema, AddResultSchema, {
12779
12781
  kind: "mutation",
12780
12782
  auth: "admin"
12781
12783
  }), method(RemoveInputSchema, _void(), {
@@ -14486,7 +14488,7 @@ method(_void(), EngineInfoSchema, { auth: "admin" }), method(object({
14486
14488
  *
14487
14489
  * ⚠ An earlier version of this comment blamed Zod stripping, and that
14488
14490
  * was wrong — corrected 2026-08-26 after the hop map
14489
- * (`docs/design/2026-08-26-mappa-hop-argomenti.md`) traced the path.
14491
+ * (`docs/design/2026-08-26-topic-hop-map.md`) traced the path.
14490
14492
  * There is **no Zod parse at all** between the door and the engine: the
14491
14493
  * dispatcher forwards the payload verbatim and UDS carries it whole. A
14492
14494
  * field declared here reaches `SqliteSettingsBackend` either way.
@@ -16689,7 +16691,7 @@ method(object({
16689
16691
  * per-device window, `KeyFrameCaptureLog`, `bumpCropMetric`. Every one of them
16690
16692
  * ends in a log line, and a log line is the thing the operator asked to stop
16691
16693
  * needing: *"possiamo armare questi errori intanto? Così al prossimo giro
16692
- * ricontrolliamo tutti questi punti"*. Reading them meant grepping Loki and
16694
+ * ricontrolliamo tutti questi punti"* [can we instrument these errors in the meantime? That way next round we recheck all these points]. Reading them meant grepping Loki and
16693
16695
  * hand-correlating timestamps, which is how a 22% thumbnail gap and a 3-hour
16694
16696
  * media blackout were both diagnosed. The counters stay; this is where they can
16695
16697
  * be READ.
@@ -18105,7 +18107,7 @@ var BrokerStatusSchema$1 = _enum([
18105
18107
  "unreachable",
18106
18108
  "tls-error"
18107
18109
  ]);
18108
- var BrokerInfoSchema = object({
18110
+ var BrokerInfoSchema$1 = object({
18109
18111
  id: string(),
18110
18112
  name: string(),
18111
18113
  url: string(),
@@ -18168,7 +18170,7 @@ var StatusSchema = object({
18168
18170
  brokerCount: number(),
18169
18171
  embeddedRunning: boolean()
18170
18172
  });
18171
- method(_void(), array(BrokerInfoSchema)), method(IdInputSchema, BrokerConnectionDetailsSchema, { auth: "admin" }), method(AddBrokerInputSchema, AddBrokerResultSchema, {
18173
+ method(_void(), array(BrokerInfoSchema$1)), method(IdInputSchema, BrokerConnectionDetailsSchema, { auth: "admin" }), method(AddBrokerInputSchema, AddBrokerResultSchema, {
18172
18174
  kind: "mutation",
18173
18175
  auth: "admin"
18174
18176
  }), method(IdInputSchema, _void(), {
@@ -20382,78 +20384,16 @@ var NcRuleInputSchema = object({
20382
20384
  */
20383
20385
  confirm: NcConfirmSchema.optional(),
20384
20386
  /**
20385
- * WAIT for face/plate recognition before saying anything.
20386
- *
20387
- * A notification's TEXT is frozen at enqueue and its media is re-resolved at
20388
- * send; the identity is neither. A face is confirmed after `confirmFrames`
20389
- * agreeing observations — p50 **11.4 s** after the track was first seen,
20390
- * measured on this hub — and an `immediate` rule enqueues on the first object
20391
- * event, seconds before that. So "Gianluca è arrivato" is unsayable on the
20392
- * immediate path, and no amount of media re-resolution fixes a sentence.
20393
- *
20394
- * Only two honest answers exist, and this flag picks between them. It has
20395
- * effect ONLY on a rule that declares a recognition scope
20396
- * ({@link NcConditions.identities} or {@link NcConditions.plates}) — on any
20397
- * other rule there is nothing to wait for and the flag is inert.
20398
- *
20399
- * | value | what happens |
20400
- * | --- | --- |
20401
- * | `true` | the rule stops firing on the object event and fires at TRACK CLOSE instead, once, with the name — later, and complete |
20402
- * | absent / `false` | it fires at once WITHOUT the name, and if recognition lands before the track closes a SECOND, "…is Gianluca" notification follows (one per track, per rule, per target) |
20403
- *
20404
- * `.optional()` and deliberately NOT `.default()`: a Zod default does not run
20405
- * on the addon cap path, and absent has to keep meaning exactly what every
20406
- * rule authored before this field meant.
20407
- *
20408
- * The cost of `true` is stated here because the editor states it too: a rule
20409
- * that waits also inherits track-close SEMANTICS — its `zones` condition
20410
- * tests every zone the track visited and a `crossing` condition can no longer
20411
- * be satisfied, because a closed track carries no crossing.
20387
+ * IMMEDIATE GROUPED (D692): the first matching subject opens a window of this many
20388
+ * seconds; the rule sends ONE message when the window closes — early, once every
20389
+ * subject in it is final, never before {@link NC_GROUPING_MIN_SEC} — naming everybody
20390
+ * the rule matched, with one mosaic tile per subject.
20391
+ * Absent = plain immediate (one message per track, at the first match).
20392
+ * Only an `immediate` DETECTION rule may carry it (`ruleGroupingApplies`, enforced on
20393
+ * save by the hub's grouping guard). `.optional()`, never `.default()`: the addon cap
20394
+ * path does not run Zod defaults.
20412
20395
  */
20413
- waitForEnhancement: boolean().optional(),
20414
- /**
20415
- * GROUP a burst of subjects into ONE notification that grows.
20416
- *
20417
- * Seconds of quiet after the last matching subject before the burst is
20418
- * considered over. While it is open, the first subject enqueues immediately —
20419
- * **exactly as today, with no added latency** — and every real growth (a new
20420
- * subject, or a name confirmed on one already in it) REPLACES that
20421
- * notification with an updated one naming everybody. The push carries the
20422
- * group's own coalescing tag, so the phone replaces rather than stacks.
20423
- *
20424
- * `0` / absent = off, and off is today's behaviour byte for byte.
20425
- *
20426
- * ### Why an idle cutoff and not a window
20427
- *
20428
- * The measured seven-person arrival on device 590 spans 110 s with every
20429
- * internal gap under 30 s. A 12 s fixed window cuts it into three groups; an
20430
- * idle cutoff holds it as one and ends it when the arrival actually ends.
20431
- * 30 s is a widely shipped value for the same decision.
20432
- *
20433
- * ### What it replaces
20434
- *
20435
- * The blind cooldown, which collapses a burst by DISCARDING it. Measured on
20436
- * device 615 / *Persona su Uscio* over six days: 116 qualifying tracks → 74
20437
- * notifications, **44 (37.9%) suppressed outright**, 23 of them overlapping a
20438
- * track that did fire and 7 carrying a confirmed identity nobody heard about.
20439
- * A group collapses the same volume by MERGING, so the cooldown becomes a
20440
- * budget over GROUPS — which is what it always meant — and a growth is never
20441
- * throttled by the window its own first member spent.
20442
- *
20443
- * ### Interaction with {@link waitForEnhancement}
20444
- *
20445
- * They compose, and the order matters. `waitForEnhancement` defers the rule to
20446
- * TRACK CLOSE, so with both set the group is opened by the first member to
20447
- * CLOSE — already carrying its name — and grows as later members close. That
20448
- * is later, and complete. With grouping alone the group opens on the first
20449
- * object event and picks up names as they are confirmed, through the growth
20450
- * path. Neither combination fires twice for one subject.
20451
- *
20452
- * `.optional()` and deliberately NOT `.default()`: a Zod default does not run
20453
- * on the addon cap path, so absent must keep meaning what it meant before this
20454
- * field existed.
20455
- */
20456
- groupIdleSec: number().int().min(0).max(600).optional()
20396
+ groupingSec: number().int().min(5).max(60).optional()
20457
20397
  });
20458
20398
  /**
20459
20399
  * Partial patch for `updateRule` — any subset of the input fields, plus the
@@ -20501,9 +20441,10 @@ var NcRuleClearableKeySchema = _enum([
20501
20441
  "targetUsers",
20502
20442
  "snoozeOptions",
20503
20443
  "snoozeAllowGlobal",
20504
- "waitForEnhancement",
20505
20444
  "actions",
20506
20445
  "confirm",
20446
+ "groupingSec",
20447
+ "waitForEnhancement",
20507
20448
  "groupIdleSec"
20508
20449
  ]);
20509
20450
  var NcRuleUpdateInputSchema = object({
@@ -20525,9 +20466,25 @@ var NcRuleSchema = NcRuleInputSchema.extend({
20525
20466
  */
20526
20467
  disabledTargetIds: array(string()).default([])
20527
20468
  });
20469
+ /**
20470
+ * The state-summary SECTIONS (D647 / D698): the D637 kind groups that report a
20471
+ * still-true state. `backups-exports` and `alarm` are not sections — a completed
20472
+ * job is not an open state, and the alarm stays instant.
20473
+ */
20474
+ var NcStateSummarySectionIdSchema = _enum([
20475
+ "device-state",
20476
+ "streams",
20477
+ "battery",
20478
+ "consumables",
20479
+ "tanks",
20480
+ "detection-blind",
20481
+ "nodes",
20482
+ "addons",
20483
+ "updates"
20484
+ ]);
20528
20485
  /** One section of a previewed state summary. `unavailable` = its state could not be read. */
20529
20486
  var NcStateSummaryPreviewSectionSchema = object({
20530
- id: string(),
20487
+ id: NcStateSummarySectionIdSchema,
20531
20488
  status: _enum(["read", "unavailable"]),
20532
20489
  items: number().int().nonnegative(),
20533
20490
  reason: string().optional()
@@ -20537,7 +20494,7 @@ var NcStateSummaryPreviewSectionSchema = object({
20537
20494
  * a `rule` split (no `section`), one section's on a `section` split.
20538
20495
  */
20539
20496
  var NcStateSummaryPreviewRowSchema = object({
20540
- section: string().optional(),
20497
+ section: NcStateSummarySectionIdSchema.optional(),
20541
20498
  /** The section's name on a per-section row; every reported section's, joined, on a combined one. */
20542
20499
  title: string(),
20543
20500
  text: string(),
@@ -22436,14 +22393,14 @@ var TrackSchema = object({
22436
22393
  * `derive-returned-null tile=standin`,
22437
22394
  * `native-tile tile=native no-key-frame-at-close`, …) written at close and
22438
22395
  * CLEARED by the late-keyFrame upgrade when a native tile lands after all.
22439
- * The operator-facing answer to "perché manca l'immagine?" on a track whose
22396
+ * The operator-facing answer to "perché manca l'immagine?" [why is the image missing?] on a track whose
22440
22397
  * tile is a face/plate stand-in, a raster crop, or an icon.
22441
22398
  *
22442
22399
  * **`no-key-frame-at-close` (D400).** The line used to be written ONLY when
22443
22400
  * the TILE ranked below native, so a track whose thumbnail landed natively
22444
22401
  * while its key frame missed carried no reason at all — three of the four
22445
22402
  * `MISSING_KEYFRAME` tracks in the 2026-09-07 operator audit were exactly
22446
- * that shape, and their "niente ultimo" had no cause anywhere on the row.
22403
+ * that shape, and their "niente ultimo" [no last frame] had no cause anywhere on the row.
22447
22404
  * The key frame is the head of a cascade (`keyFrame ⇒ keyFrameSmall ⇒ the
22448
22405
  * lastFrame copy source`), so its absence is now on this line whatever the
22449
22406
  * tile ended up being.
@@ -22530,7 +22487,7 @@ var MotionEventSchema = object({
22530
22487
  /**
22531
22488
  * Ms offsets from `timestamp` (the episode's own first rising edge, so the
22532
22489
  * first entry is always `0`) of every genuine off→on transition the
22533
- * episode saw — "ogni evento on si deve salvare" (D475). NOT one entry per
22490
+ * episode saw — "ogni evento on si deve salvare" [every ON event must be saved] (D475). NOT one entry per
22534
22491
  * push: a firmware source that keepalives at ~1 Hz for the whole burst
22535
22492
  * (Reolink, Hikvision) produces exactly one edge; a source that reports an
22536
22493
  * explicit `false` mid-episode and then resumes before the quiet window
@@ -23054,6 +23011,7 @@ var KeyEventSchema = object({
23054
23011
  bestEventId: string(),
23055
23012
  /** Track lifetime in ms (lastSeen - firstSeen). */
23056
23013
  windowMs: number().optional(),
23014
+ audioLabels: array(TrackAudioLabelSchema).readonly().optional(),
23057
23015
  ...TrackFlagFields,
23058
23016
  ...TrackRetrainFields
23059
23017
  });
@@ -27987,7 +27945,7 @@ var ClipPlaybackSchema = object({
27987
27945
  * **One authorised yes is one wake.** `next-natural` — take the clip the next
27988
27946
  * time the camera is awake for its own reasons — is deliberately not a member:
27989
27947
  * it was proposed, it is free on the battery, and the operator declined it on
27990
- * 2026-09-20 (*"Quando un export viene richiesto si sveglia la camera."*,
27948
+ * 2026-09-20 (*"Quando un export viene richiesto si sveglia la camera."* [When an export is requested the camera wakes up],
27991
27949
  * D558 "Considered and not taken").
27992
27950
  */
27993
27951
  var ClipWakeSchema = _enum(["authorised"]);
@@ -28383,7 +28341,7 @@ var videoclipsCapability = {
28383
28341
  * **It is a SECTION of the Recording tab, at the end of it — not a tab of
28384
28342
  * its own.** It shipped as a `clips` top-tab and the operator rejected the
28385
28343
  * placement: *"utilizzerei la stessa tab recordings, lì abbiamo già tutto il
28386
- * necessario, una nuova sezione alla fine per le clips"*. The Recording tab
28344
+ * necessario, una nuova sezione alla fine per le clips"* [I would use the same recordings tab, there we already have everything necessary, a new section at the end for the clips]. The Recording tab
28387
28345
  * already holds the recorder's panel, the schedule bands and the unified
28388
28346
  * retention policy; footage the camera itself holds is the same question,
28389
28347
  * asked of a different store. `order: 100` puts it after all of them with
@@ -28444,7 +28402,7 @@ var videoclipsCapability = {
28444
28402
  * It replaced `sources?: string[]`, a VIEW filter over source ids that
28445
28403
  * assumed the answer was a fan-out over everything a camera has. The
28446
28404
  * operator settled otherwise on 2026-09-20 — *"l'utilizzatore è uno
28447
- * solo"* — so the list is asked of one provider at a time and there is
28405
+ * solo"* [there is only one user] — so the list is asked of one provider at a time and there is
28448
28406
  * nothing to filter out of it.
28449
28407
  */
28450
28408
  provider: string().min(1)
@@ -36765,7 +36723,7 @@ var ReadGopBytesResultSchema = object({
36765
36723
  /**
36766
36724
  * A time WINDOW of one finalized segment, cut by byte range — the multi-GOP
36767
36725
  * twin of {@link ReadGopBytesResultSchema}'s single instant. Built for the
36768
- * replay clip's `recording` source (`docs/design/plans/2026-08-26-replay-clip-su-pipeline.md`):
36726
+ * replay clip's `recording` source (`docs/design/plans/2026-08-26-clip-replay-on-pipeline.md`):
36769
36727
  * a replay needs several seconds of native pixels, not one frame.
36770
36728
  *
36771
36729
  * `ok.data` is standalone-demuxable, same as a GOP read. `ok.reachesRequestedEnd`
@@ -40496,6 +40454,7 @@ var zoneRulesCapability = {
40496
40454
  */
40497
40455
  durability: "restored"
40498
40456
  };
40457
+ SOURCE_CAPS.filter((cap) => cap !== "switch" && cap !== "motion");
40499
40458
  /**
40500
40459
  * Accessory device helpers — shared across drivers.
40501
40460
  *
@@ -50760,6 +50719,11 @@ Object.freeze({
50760
50719
  }
50761
50720
  });
50762
50721
  Object.freeze({
50722
+ "accessories.getStatus": [{
50723
+ name: "deviceId",
50724
+ form: "single",
50725
+ optional: false
50726
+ }],
50763
50727
  "accessories.setChildHidden": [{
50764
50728
  name: "childDeviceId",
50765
50729
  form: "single",
@@ -50779,6 +50743,11 @@ Object.freeze({
50779
50743
  form: "single",
50780
50744
  optional: false
50781
50745
  }],
50746
+ "airQualitySensor.getStatus": [{
50747
+ name: "deviceId",
50748
+ form: "single",
50749
+ optional: false
50750
+ }],
50782
50751
  "alarmPanel.arm": [{
50783
50752
  name: "deviceId",
50784
50753
  form: "single",
@@ -50789,11 +50758,36 @@ Object.freeze({
50789
50758
  form: "single",
50790
50759
  optional: false
50791
50760
  }],
50761
+ "alarmPanel.getStatus": [{
50762
+ name: "deviceId",
50763
+ form: "single",
50764
+ optional: false
50765
+ }],
50792
50766
  "alarmPanel.trigger": [{
50793
50767
  name: "deviceId",
50794
50768
  form: "single",
50795
50769
  optional: false
50796
50770
  }],
50771
+ "ambientLightSensor.getStatus": [{
50772
+ name: "deviceId",
50773
+ form: "single",
50774
+ optional: false
50775
+ }],
50776
+ "audioAnalysis.applyDeviceSettingsPatch": [{
50777
+ name: "deviceId",
50778
+ form: "single",
50779
+ optional: false
50780
+ }],
50781
+ "audioAnalysis.getDeviceLiveContribution": [{
50782
+ name: "deviceId",
50783
+ form: "single",
50784
+ optional: false
50785
+ }],
50786
+ "audioAnalysis.getDeviceSettingsContribution": [{
50787
+ name: "deviceId",
50788
+ form: "single",
50789
+ optional: false
50790
+ }],
50797
50791
  "audioAnalysis.resolveDeviceSettings": [{
50798
50792
  name: "deviceId",
50799
50793
  form: "single",
@@ -50834,16 +50828,36 @@ Object.freeze({
50834
50828
  form: "single",
50835
50829
  optional: false
50836
50830
  }],
50831
+ "automationControl.getStatus": [{
50832
+ name: "deviceId",
50833
+ form: "single",
50834
+ optional: false
50835
+ }],
50837
50836
  "automationControl.trigger": [{
50838
50837
  name: "deviceId",
50839
50838
  form: "single",
50840
50839
  optional: false
50841
50840
  }],
50841
+ "battery.getStatus": [{
50842
+ name: "deviceId",
50843
+ form: "single",
50844
+ optional: false
50845
+ }],
50842
50846
  "battery.wakeForStream": [{
50843
50847
  name: "deviceId",
50844
50848
  form: "single",
50845
50849
  optional: false
50846
50850
  }],
50851
+ "binary.getStatus": [{
50852
+ name: "deviceId",
50853
+ form: "single",
50854
+ optional: false
50855
+ }],
50856
+ "brightness.getStatus": [{
50857
+ name: "deviceId",
50858
+ form: "single",
50859
+ optional: false
50860
+ }],
50847
50861
  "brightness.setBrightness": [{
50848
50862
  name: "deviceId",
50849
50863
  form: "single",
@@ -50859,6 +50873,26 @@ Object.freeze({
50859
50873
  form: "single",
50860
50874
  optional: false
50861
50875
  }],
50876
+ "cameraCredentials.getStatus": [{
50877
+ name: "deviceId",
50878
+ form: "single",
50879
+ optional: false
50880
+ }],
50881
+ "cameraGridLayout.applyDeviceSettingsPatch": [{
50882
+ name: "deviceId",
50883
+ form: "single",
50884
+ optional: false
50885
+ }],
50886
+ "cameraGridLayout.getDeviceLiveContribution": [{
50887
+ name: "deviceId",
50888
+ form: "single",
50889
+ optional: false
50890
+ }],
50891
+ "cameraGridLayout.getDeviceSettingsContribution": [{
50892
+ name: "deviceId",
50893
+ form: "single",
50894
+ optional: false
50895
+ }],
50862
50896
  "cameraGridLayout.getLayout": [{
50863
50897
  name: "deviceId",
50864
50898
  form: "single",
@@ -50874,6 +50908,21 @@ Object.freeze({
50874
50908
  form: "single",
50875
50909
  optional: false
50876
50910
  }],
50911
+ "cameraPipelineConfig.applyDeviceSettingsPatch": [{
50912
+ name: "deviceId",
50913
+ form: "single",
50914
+ optional: false
50915
+ }],
50916
+ "cameraPipelineConfig.getDeviceLiveContribution": [{
50917
+ name: "deviceId",
50918
+ form: "single",
50919
+ optional: false
50920
+ }],
50921
+ "cameraPipelineConfig.getDeviceSettingsContribution": [{
50922
+ name: "deviceId",
50923
+ form: "single",
50924
+ optional: false
50925
+ }],
50877
50926
  "cameraStreams.getBrokerStreams": [{
50878
50927
  name: "deviceId",
50879
50928
  form: "single",
@@ -50899,6 +50948,16 @@ Object.freeze({
50899
50948
  form: "single",
50900
50949
  optional: false
50901
50950
  }],
50951
+ "carbonMonoxide.getStatus": [{
50952
+ name: "deviceId",
50953
+ form: "single",
50954
+ optional: false
50955
+ }],
50956
+ "climateControl.getStatus": [{
50957
+ name: "deviceId",
50958
+ form: "single",
50959
+ optional: false
50960
+ }],
50902
50961
  "climateControl.setFanMode": [{
50903
50962
  name: "deviceId",
50904
50963
  form: "single",
@@ -50939,16 +50998,41 @@ Object.freeze({
50939
50998
  form: "single",
50940
50999
  optional: false
50941
51000
  }],
51001
+ "color.getStatus": [{
51002
+ name: "deviceId",
51003
+ form: "single",
51004
+ optional: false
51005
+ }],
50942
51006
  "color.setColor": [{
50943
51007
  name: "deviceId",
50944
51008
  form: "single",
50945
51009
  optional: false
50946
51010
  }],
51011
+ "connectivity.getStatus": [{
51012
+ name: "deviceId",
51013
+ form: "single",
51014
+ optional: false
51015
+ }],
51016
+ "consumables.getStatus": [{
51017
+ name: "deviceId",
51018
+ form: "single",
51019
+ optional: false
51020
+ }],
50947
51021
  "consumables.reset": [{
50948
51022
  name: "deviceId",
50949
51023
  form: "single",
50950
51024
  optional: false
50951
51025
  }],
51026
+ "contact.getStatus": [{
51027
+ name: "deviceId",
51028
+ form: "single",
51029
+ optional: false
51030
+ }],
51031
+ "control.getStatus": [{
51032
+ name: "deviceId",
51033
+ form: "single",
51034
+ optional: false
51035
+ }],
50952
51036
  "control.setValue": [{
50953
51037
  name: "deviceId",
50954
51038
  form: "single",
@@ -50959,6 +51043,11 @@ Object.freeze({
50959
51043
  form: "single",
50960
51044
  optional: false
50961
51045
  }],
51046
+ "cover.getStatus": [{
51047
+ name: "deviceId",
51048
+ form: "single",
51049
+ optional: false
51050
+ }],
50962
51051
  "cover.open": [{
50963
51052
  name: "deviceId",
50964
51053
  form: "single",
@@ -50984,6 +51073,11 @@ Object.freeze({
50984
51073
  form: "single",
50985
51074
  optional: false
50986
51075
  }],
51076
+ "dayNight.getStatus": [{
51077
+ name: "deviceId",
51078
+ form: "single",
51079
+ optional: false
51080
+ }],
50987
51081
  "dayNight.setSettings": [{
50988
51082
  name: "deviceId",
50989
51083
  form: "single",
@@ -50994,11 +51088,31 @@ Object.freeze({
50994
51088
  form: "single",
50995
51089
  optional: true
50996
51090
  }],
51091
+ "detectionPipeline.applyDeviceSettingsPatch": [{
51092
+ name: "deviceId",
51093
+ form: "single",
51094
+ optional: false
51095
+ }],
51096
+ "detectionPipeline.getDeviceLiveContribution": [{
51097
+ name: "deviceId",
51098
+ form: "single",
51099
+ optional: false
51100
+ }],
51101
+ "detectionPipeline.getDeviceSettingsContribution": [{
51102
+ name: "deviceId",
51103
+ form: "single",
51104
+ optional: false
51105
+ }],
50997
51106
  "deviceAdminLink.getAdminLink": [{
50998
51107
  name: "deviceId",
50999
51108
  form: "single",
51000
51109
  optional: false
51001
51110
  }],
51111
+ "deviceAdoption.getStatus": [{
51112
+ name: "deviceId",
51113
+ form: "single",
51114
+ optional: false
51115
+ }],
51002
51116
  "deviceAdoption.release": [{
51003
51117
  name: "camDeviceId",
51004
51118
  form: "single",
@@ -51014,6 +51128,11 @@ Object.freeze({
51014
51128
  form: "single",
51015
51129
  optional: false
51016
51130
  }],
51131
+ "deviceDiscovery.getStatus": [{
51132
+ name: "deviceId",
51133
+ form: "single",
51134
+ optional: false
51135
+ }],
51017
51136
  "deviceDiscovery.listDiscovered": [{
51018
51137
  name: "deviceId",
51019
51138
  form: "single",
@@ -51033,6 +51152,21 @@ Object.freeze({
51033
51152
  form: "single",
51034
51153
  optional: false
51035
51154
  }],
51155
+ "deviceExport.applyDeviceSettingsPatch": [{
51156
+ name: "deviceId",
51157
+ form: "single",
51158
+ optional: false
51159
+ }],
51160
+ "deviceExport.getDeviceLiveContribution": [{
51161
+ name: "deviceId",
51162
+ form: "single",
51163
+ optional: false
51164
+ }],
51165
+ "deviceExport.getDeviceSettingsContribution": [{
51166
+ name: "deviceId",
51167
+ form: "single",
51168
+ optional: false
51169
+ }],
51036
51170
  "deviceExtension.listCandidates": [{
51037
51171
  name: "deviceId",
51038
51172
  form: "single",
@@ -51381,6 +51515,26 @@ Object.freeze({
51381
51515
  form: "single",
51382
51516
  optional: false
51383
51517
  }],
51518
+ "deviceStatus.getStatus": [{
51519
+ name: "deviceId",
51520
+ form: "single",
51521
+ optional: false
51522
+ }],
51523
+ "doorbell.getStatus": [{
51524
+ name: "deviceId",
51525
+ form: "single",
51526
+ optional: false
51527
+ }],
51528
+ "enumSensor.getStatus": [{
51529
+ name: "deviceId",
51530
+ form: "single",
51531
+ optional: false
51532
+ }],
51533
+ "eventEmitter.getStatus": [{
51534
+ name: "deviceId",
51535
+ form: "single",
51536
+ optional: false
51537
+ }],
51384
51538
  "faceGallery.getFaceByTrack": [{
51385
51539
  name: "deviceId",
51386
51540
  form: "single",
@@ -51395,6 +51549,11 @@ Object.freeze({
51395
51549
  form: "array",
51396
51550
  optional: true
51397
51551
  }],
51552
+ "fanControl.getStatus": [{
51553
+ name: "deviceId",
51554
+ form: "single",
51555
+ optional: false
51556
+ }],
51398
51557
  "fanControl.setDirection": [{
51399
51558
  name: "deviceId",
51400
51559
  form: "single",
@@ -51415,6 +51574,26 @@ Object.freeze({
51415
51574
  form: "single",
51416
51575
  optional: false
51417
51576
  }],
51577
+ "featureProbe.getStatus": [{
51578
+ name: "deviceId",
51579
+ form: "single",
51580
+ optional: false
51581
+ }],
51582
+ "flood.getStatus": [{
51583
+ name: "deviceId",
51584
+ form: "single",
51585
+ optional: false
51586
+ }],
51587
+ "gas.getStatus": [{
51588
+ name: "deviceId",
51589
+ form: "single",
51590
+ optional: false
51591
+ }],
51592
+ "humidifier.getStatus": [{
51593
+ name: "deviceId",
51594
+ form: "single",
51595
+ optional: false
51596
+ }],
51418
51597
  "humidifier.setMode": [{
51419
51598
  name: "deviceId",
51420
51599
  form: "single",
@@ -51430,11 +51609,26 @@ Object.freeze({
51430
51609
  form: "single",
51431
51610
  optional: false
51432
51611
  }],
51612
+ "humiditySensor.getStatus": [{
51613
+ name: "deviceId",
51614
+ form: "single",
51615
+ optional: false
51616
+ }],
51617
+ "image.getStatus": [{
51618
+ name: "deviceId",
51619
+ form: "single",
51620
+ optional: false
51621
+ }],
51433
51622
  "imageSettings.getOptions": [{
51434
51623
  name: "deviceId",
51435
51624
  form: "single",
51436
51625
  optional: false
51437
51626
  }],
51627
+ "imageSettings.getStatus": [{
51628
+ name: "deviceId",
51629
+ form: "single",
51630
+ optional: false
51631
+ }],
51438
51632
  "imageSettings.setSettings": [{
51439
51633
  name: "deviceId",
51440
51634
  form: "single",
@@ -51445,6 +51639,11 @@ Object.freeze({
51445
51639
  form: "single",
51446
51640
  optional: false
51447
51641
  }],
51642
+ "intercom.getStatus": [{
51643
+ name: "deviceId",
51644
+ form: "single",
51645
+ optional: false
51646
+ }],
51448
51647
  "intercom.handleAnswer": [{
51449
51648
  name: "deviceId",
51450
51649
  form: "single",
@@ -51475,6 +51674,11 @@ Object.freeze({
51475
51674
  form: "single",
51476
51675
  optional: false
51477
51676
  }],
51677
+ "lawnMowerControl.getStatus": [{
51678
+ name: "deviceId",
51679
+ form: "single",
51680
+ optional: false
51681
+ }],
51478
51682
  "lawnMowerControl.pause": [{
51479
51683
  name: "deviceId",
51480
51684
  form: "single",
@@ -51485,6 +51689,11 @@ Object.freeze({
51485
51689
  form: "single",
51486
51690
  optional: false
51487
51691
  }],
51692
+ "lockControl.getStatus": [{
51693
+ name: "deviceId",
51694
+ form: "single",
51695
+ optional: false
51696
+ }],
51488
51697
  "lockControl.lock": [{
51489
51698
  name: "deviceId",
51490
51699
  form: "single",
@@ -51500,6 +51709,11 @@ Object.freeze({
51500
51709
  form: "single",
51501
51710
  optional: false
51502
51711
  }],
51712
+ "mediaPlayer.getStatus": [{
51713
+ name: "deviceId",
51714
+ form: "single",
51715
+ optional: false
51716
+ }],
51503
51717
  "mediaPlayer.next": [{
51504
51718
  name: "deviceId",
51505
51719
  form: "single",
@@ -51560,6 +51774,11 @@ Object.freeze({
51560
51774
  form: "single",
51561
51775
  optional: false
51562
51776
  }],
51777
+ "motion.getStatus": [{
51778
+ name: "deviceId",
51779
+ form: "single",
51780
+ optional: false
51781
+ }],
51563
51782
  "motion.isDetected": [{
51564
51783
  name: "deviceId",
51565
51784
  form: "single",
@@ -51570,11 +51789,31 @@ Object.freeze({
51570
51789
  form: "single",
51571
51790
  optional: false
51572
51791
  }],
51792
+ "motionDetection.applyDeviceSettingsPatch": [{
51793
+ name: "deviceId",
51794
+ form: "single",
51795
+ optional: false
51796
+ }],
51797
+ "motionDetection.getDeviceLiveContribution": [{
51798
+ name: "deviceId",
51799
+ form: "single",
51800
+ optional: false
51801
+ }],
51802
+ "motionDetection.getDeviceSettingsContribution": [{
51803
+ name: "deviceId",
51804
+ form: "single",
51805
+ optional: false
51806
+ }],
51573
51807
  "motionDetection.removeCamera": [{
51574
51808
  name: "deviceId",
51575
51809
  form: "single",
51576
51810
  optional: false
51577
51811
  }],
51812
+ "motionTrigger.getStatus": [{
51813
+ name: "deviceId",
51814
+ form: "single",
51815
+ optional: false
51816
+ }],
51578
51817
  "motionTrigger.setMotionTrigger": [{
51579
51818
  name: "deviceId",
51580
51819
  form: "single",
@@ -51585,6 +51824,11 @@ Object.freeze({
51585
51824
  form: "single",
51586
51825
  optional: false
51587
51826
  }],
51827
+ "motionZones.getStatus": [{
51828
+ name: "deviceId",
51829
+ form: "single",
51830
+ optional: false
51831
+ }],
51588
51832
  "motionZones.setZone": [{
51589
51833
  name: "deviceId",
51590
51834
  form: "single",
@@ -51595,6 +51839,11 @@ Object.freeze({
51595
51839
  form: "single",
51596
51840
  optional: false
51597
51841
  }],
51842
+ "nativeObjectDetection.getStatus": [{
51843
+ name: "deviceId",
51844
+ form: "single",
51845
+ optional: false
51846
+ }],
51598
51847
  "nativeObjectDetection.setEnabled": [{
51599
51848
  name: "deviceId",
51600
51849
  form: "single",
@@ -51610,6 +51859,11 @@ Object.freeze({
51610
51859
  form: "single",
51611
51860
  optional: false
51612
51861
  }],
51862
+ "navigation.getStatus": [{
51863
+ name: "deviceId",
51864
+ form: "single",
51865
+ optional: false
51866
+ }],
51613
51867
  "navigation.goToPoint": [{
51614
51868
  name: "deviceId",
51615
51869
  form: "single",
@@ -51655,6 +51909,11 @@ Object.freeze({
51655
51909
  form: "single",
51656
51910
  optional: false
51657
51911
  }],
51912
+ "networkLink.getStatus": [{
51913
+ name: "deviceId",
51914
+ form: "single",
51915
+ optional: false
51916
+ }],
51658
51917
  "networkQuality.getDeviceStats": [{
51659
51918
  name: "deviceId",
51660
51919
  form: "single",
@@ -51680,11 +51939,26 @@ Object.freeze({
51680
51939
  form: "single",
51681
51940
  optional: false
51682
51941
  }],
51942
+ "notifier.getStatus": [{
51943
+ name: "deviceId",
51944
+ form: "single",
51945
+ optional: false
51946
+ }],
51683
51947
  "notifier.send": [{
51684
51948
  name: "deviceId",
51685
51949
  form: "single",
51686
51950
  optional: false
51687
51951
  }],
51952
+ "numericSensor.getStatus": [{
51953
+ name: "deviceId",
51954
+ form: "single",
51955
+ optional: false
51956
+ }],
51957
+ "osd.getStatus": [{
51958
+ name: "deviceId",
51959
+ form: "single",
51960
+ optional: false
51961
+ }],
51688
51962
  "osd.setOverlay": [{
51689
51963
  name: "deviceId",
51690
51964
  form: "single",
@@ -51744,6 +52018,11 @@ Object.freeze({
51744
52018
  form: "single",
51745
52019
  optional: false
51746
52020
  }],
52021
+ "petFeeder.getStatus": [{
52022
+ name: "deviceId",
52023
+ form: "single",
52024
+ optional: false
52025
+ }],
51747
52026
  "petFeeder.markFoodReplenished": [{
51748
52027
  name: "deviceId",
51749
52028
  form: "single",
@@ -51779,6 +52058,11 @@ Object.freeze({
51779
52058
  form: "single",
51780
52059
  optional: false
51781
52060
  }],
52061
+ "pipelineAnalytics.applyDeviceSettingsPatch": [{
52062
+ name: "deviceId",
52063
+ form: "single",
52064
+ optional: false
52065
+ }],
51782
52066
  "pipelineAnalytics.clearTrackRelation": [{
51783
52067
  name: "deviceId",
51784
52068
  form: "single",
@@ -51819,6 +52103,16 @@ Object.freeze({
51819
52103
  form: "single",
51820
52104
  optional: false
51821
52105
  }],
52106
+ "pipelineAnalytics.getDeviceLiveContribution": [{
52107
+ name: "deviceId",
52108
+ form: "single",
52109
+ optional: false
52110
+ }],
52111
+ "pipelineAnalytics.getDeviceSettingsContribution": [{
52112
+ name: "deviceId",
52113
+ form: "single",
52114
+ optional: false
52115
+ }],
51822
52116
  "pipelineAnalytics.getEventDensity": [{
51823
52117
  name: "deviceId",
51824
52118
  form: "single",
@@ -52034,6 +52328,11 @@ Object.freeze({
52034
52328
  form: "single",
52035
52329
  optional: true
52036
52330
  }],
52331
+ "pipelineOrchestrator.applyDeviceSettingsPatch": [{
52332
+ name: "deviceId",
52333
+ form: "single",
52334
+ optional: false
52335
+ }],
52037
52336
  "pipelineOrchestrator.assignAudio": [{
52038
52337
  name: "deviceId",
52039
52338
  form: "single",
@@ -52079,6 +52378,16 @@ Object.freeze({
52079
52378
  form: "single",
52080
52379
  optional: false
52081
52380
  }],
52381
+ "pipelineOrchestrator.getDeviceLiveContribution": [{
52382
+ name: "deviceId",
52383
+ form: "single",
52384
+ optional: false
52385
+ }],
52386
+ "pipelineOrchestrator.getDeviceSettingsContribution": [{
52387
+ name: "deviceId",
52388
+ form: "single",
52389
+ optional: false
52390
+ }],
52082
52391
  "pipelineOrchestrator.getPipelineAssignment": [{
52083
52392
  name: "deviceId",
52084
52393
  form: "single",
@@ -52199,11 +52508,31 @@ Object.freeze({
52199
52508
  form: "single",
52200
52509
  optional: true
52201
52510
  }],
52511
+ "powerMeter.getStatus": [{
52512
+ name: "deviceId",
52513
+ form: "single",
52514
+ optional: false
52515
+ }],
52516
+ "presence.getStatus": [{
52517
+ name: "deviceId",
52518
+ form: "single",
52519
+ optional: false
52520
+ }],
52521
+ "pressureSensor.getStatus": [{
52522
+ name: "deviceId",
52523
+ form: "single",
52524
+ optional: false
52525
+ }],
52202
52526
  "privacyMask.getOptions": [{
52203
52527
  name: "deviceId",
52204
52528
  form: "single",
52205
52529
  optional: false
52206
52530
  }],
52531
+ "privacyMask.getStatus": [{
52532
+ name: "deviceId",
52533
+ form: "single",
52534
+ optional: false
52535
+ }],
52207
52536
  "privacyMask.setAudioEnabled": [{
52208
52537
  name: "deviceId",
52209
52538
  form: "single",
@@ -52254,6 +52583,11 @@ Object.freeze({
52254
52583
  form: "single",
52255
52584
  optional: false
52256
52585
  }],
52586
+ "ptz.getStatus": [{
52587
+ name: "deviceId",
52588
+ form: "single",
52589
+ optional: false
52590
+ }],
52257
52591
  "ptz.goHome": [{
52258
52592
  name: "deviceId",
52259
52593
  form: "single",
@@ -52344,6 +52678,11 @@ Object.freeze({
52344
52678
  form: "single",
52345
52679
  optional: false
52346
52680
  }],
52681
+ "recordingArchive.applyDeviceSettingsPatch": [{
52682
+ name: "deviceId",
52683
+ form: "single",
52684
+ optional: false
52685
+ }],
52347
52686
  "recordingArchive.deleteFootprint": [{
52348
52687
  name: "deviceId",
52349
52688
  form: "single",
@@ -52364,6 +52703,21 @@ Object.freeze({
52364
52703
  form: "single",
52365
52704
  optional: false
52366
52705
  }],
52706
+ "recordingArchive.getDeviceLiveContribution": [{
52707
+ name: "deviceId",
52708
+ form: "single",
52709
+ optional: false
52710
+ }],
52711
+ "recordingArchive.getDeviceSettingsContribution": [{
52712
+ name: "deviceId",
52713
+ form: "single",
52714
+ optional: false
52715
+ }],
52716
+ "recordingArchive.getStatus": [{
52717
+ name: "deviceId",
52718
+ form: "single",
52719
+ optional: false
52720
+ }],
52367
52721
  "recordingArchive.listOpsLog": [{
52368
52722
  name: "deviceId",
52369
52723
  form: "single",
@@ -52449,6 +52803,11 @@ Object.freeze({
52449
52803
  form: "single",
52450
52804
  optional: false
52451
52805
  }],
52806
+ "recordingOnboard.getStatus": [{
52807
+ name: "deviceId",
52808
+ form: "single",
52809
+ optional: false
52810
+ }],
52452
52811
  "recordingOnboard.setSettings": [{
52453
52812
  name: "deviceId",
52454
52813
  form: "single",
@@ -52479,6 +52838,11 @@ Object.freeze({
52479
52838
  form: "single",
52480
52839
  optional: false
52481
52840
  }],
52841
+ "sceneMonitor.getStatus": [{
52842
+ name: "deviceId",
52843
+ form: "single",
52844
+ optional: false
52845
+ }],
52482
52846
  "sceneMonitor.listScenes": [{
52483
52847
  name: "deviceId",
52484
52848
  form: "single",
@@ -52504,6 +52868,11 @@ Object.freeze({
52504
52868
  form: "single",
52505
52869
  optional: false
52506
52870
  }],
52871
+ "scriptRunner.getStatus": [{
52872
+ name: "deviceId",
52873
+ form: "single",
52874
+ optional: false
52875
+ }],
52507
52876
  "scriptRunner.run": [{
52508
52877
  name: "deviceId",
52509
52878
  form: "single",
@@ -52514,11 +52883,31 @@ Object.freeze({
52514
52883
  form: "single",
52515
52884
  optional: false
52516
52885
  }],
52886
+ "smoke.getStatus": [{
52887
+ name: "deviceId",
52888
+ form: "single",
52889
+ optional: false
52890
+ }],
52891
+ "snapshot.applyDeviceSettingsPatch": [{
52892
+ name: "deviceId",
52893
+ form: "single",
52894
+ optional: false
52895
+ }],
52517
52896
  "snapshot.getDebugState": [{
52518
52897
  name: "deviceId",
52519
52898
  form: "single",
52520
52899
  optional: false
52521
52900
  }],
52901
+ "snapshot.getDeviceLiveContribution": [{
52902
+ name: "deviceId",
52903
+ form: "single",
52904
+ optional: false
52905
+ }],
52906
+ "snapshot.getDeviceSettingsContribution": [{
52907
+ name: "deviceId",
52908
+ form: "single",
52909
+ optional: false
52910
+ }],
52522
52911
  "snapshot.getSnapshot": [{
52523
52912
  name: "deviceId",
52524
52913
  form: "single",
@@ -52535,6 +52924,11 @@ Object.freeze({
52535
52924
  form: "array",
52536
52925
  optional: false
52537
52926
  }],
52927
+ "snapshot.getStatus": [{
52928
+ name: "deviceId",
52929
+ form: "single",
52930
+ optional: false
52931
+ }],
52538
52932
  "snapshot.invalidateCache": [{
52539
52933
  name: "deviceId",
52540
52934
  form: "single",
@@ -52545,6 +52939,11 @@ Object.freeze({
52545
52939
  form: "single",
52546
52940
  optional: false
52547
52941
  }],
52942
+ "streamBroker.applyDeviceSettingsPatch": [{
52943
+ name: "deviceId",
52944
+ form: "single",
52945
+ optional: false
52946
+ }],
52548
52947
  "streamBroker.assignProfile": [{
52549
52948
  name: "deviceId",
52550
52949
  form: "single",
@@ -52560,6 +52959,16 @@ Object.freeze({
52560
52959
  form: "single",
52561
52960
  optional: false
52562
52961
  }],
52962
+ "streamBroker.getDeviceLiveContribution": [{
52963
+ name: "deviceId",
52964
+ form: "single",
52965
+ optional: false
52966
+ }],
52967
+ "streamBroker.getDeviceSettingsContribution": [{
52968
+ name: "deviceId",
52969
+ form: "single",
52970
+ optional: false
52971
+ }],
52563
52972
  "streamBroker.getStreamWithCodec": [{
52564
52973
  name: "deviceId",
52565
52974
  form: "single",
@@ -52620,16 +53029,46 @@ Object.freeze({
52620
53029
  form: "single",
52621
53030
  optional: false
52622
53031
  }],
53032
+ "streamParams.getStatus": [{
53033
+ name: "deviceId",
53034
+ form: "single",
53035
+ optional: false
53036
+ }],
52623
53037
  "streamParams.setProfile": [{
52624
53038
  name: "deviceId",
52625
53039
  form: "single",
52626
53040
  optional: false
52627
53041
  }],
53042
+ "switch.getStatus": [{
53043
+ name: "deviceId",
53044
+ form: "single",
53045
+ optional: false
53046
+ }],
52628
53047
  "switch.setState": [{
52629
53048
  name: "deviceId",
52630
53049
  form: "single",
52631
53050
  optional: false
52632
53051
  }],
53052
+ "tamper.getStatus": [{
53053
+ name: "deviceId",
53054
+ form: "single",
53055
+ optional: false
53056
+ }],
53057
+ "temperatureSensor.getStatus": [{
53058
+ name: "deviceId",
53059
+ form: "single",
53060
+ optional: false
53061
+ }],
53062
+ "update.getStatus": [{
53063
+ name: "deviceId",
53064
+ form: "single",
53065
+ optional: false
53066
+ }],
53067
+ "vacuumControl.getStatus": [{
53068
+ name: "deviceId",
53069
+ form: "single",
53070
+ optional: false
53071
+ }],
52633
53072
  "vacuumControl.locate": [{
52634
53073
  name: "deviceId",
52635
53074
  form: "single",
@@ -52665,6 +53104,11 @@ Object.freeze({
52665
53104
  form: "single",
52666
53105
  optional: false
52667
53106
  }],
53107
+ "valve.getStatus": [{
53108
+ name: "deviceId",
53109
+ form: "single",
53110
+ optional: false
53111
+ }],
52668
53112
  "valve.open": [{
52669
53113
  name: "deviceId",
52670
53114
  form: "single",
@@ -52680,6 +53124,11 @@ Object.freeze({
52680
53124
  form: "single",
52681
53125
  optional: false
52682
53126
  }],
53127
+ "vibration.getStatus": [{
53128
+ name: "deviceId",
53129
+ form: "single",
53130
+ optional: false
53131
+ }],
52683
53132
  "videoclips.dialClipStream": [{
52684
53133
  name: "deviceId",
52685
53134
  form: "single",
@@ -52715,6 +53164,11 @@ Object.freeze({
52715
53164
  form: "single",
52716
53165
  optional: false
52717
53166
  }],
53167
+ "waterHeater.getStatus": [{
53168
+ name: "deviceId",
53169
+ form: "single",
53170
+ optional: false
53171
+ }],
52718
53172
  "waterHeater.setAway": [{
52719
53173
  name: "deviceId",
52720
53174
  form: "single",
@@ -52730,6 +53184,11 @@ Object.freeze({
52730
53184
  form: "single",
52731
53185
  optional: false
52732
53186
  }],
53187
+ "weather.getStatus": [{
53188
+ name: "deviceId",
53189
+ form: "single",
53190
+ optional: false
53191
+ }],
52733
53192
  "webrtcSession.addIceCandidate": [{
52734
53193
  name: "deviceId",
52735
53194
  form: "single",
@@ -53467,7 +53926,7 @@ var PreviewTextField = string().max(200);
53467
53926
  * Whether the notification's preview is a STILL or a short animation.
53468
53927
  *
53469
53928
  * The operator's ask, verbatim: *"inviato come gif o video (come per le altre
53470
- * rule)"* — the other rules already offer an animated preview, and a ten-hour
53929
+ * rule)"* [sent as a gif or video (as for the other rules)] — the other rules already offer an animated preview, and a ten-hour
53471
53930
  * night reads better as three seconds of motion than as one frame of it. Both
53472
53931
  * modes get the SAME treatment (blurred frame, large centred title); `'gif'`
53473
53932
  * simply applies it to a dozen frames sampled across the render and assembles
@@ -161136,37 +161595,37 @@ function buildOnboardWrites(patch, schedule) {
161136
161595
  //#endregion
161137
161596
  //#region src/battery-charging.ts
161138
161597
  /**
161139
- * Da `adapterStatus` + `chargeStatus` alla sorgente di alimentazione.
161140
- *
161141
- * I due campi rispondono a DUE domande diverse, e confonderle è il bug che
161142
- * questo modulo esiste per chiudere:
161143
- *
161144
- * - `adapterStatus` — l'alimentazione è COLLEGATA? Il firmware manda 0/1/2
161145
- * (nessuna · adattatore DC · pannello solare) e il confine dell'hub lo
161146
- * traduce in `'none' | 'dc' | 'solarPanel'` (`mapHubChargeStatus` e
161147
- * `mapHubAdapterStatus` in `reolink-hub.ts`), perché il vocabolario del
161148
- * percorso standalone è già a stringhe.
161149
- * - `chargeStatus` — la CELLA cosa sta facendo? 0 ferma · 1 in carica ·
161150
- * 2 carica completa.
161151
- *
161152
- * La vecchia derivazione consultava l'adattatore SOLO per cercarci 'solar', e
161153
- * un DC collegato cadeva nel ripiego `'none'`. Due Argus 3E lo nascondevano per
161154
- * caso: piene e collegate rispondono `chargeStatus: 2`, che il ramo `isCharging`
161155
- * mappava su `'dc'` per la ragione sbagliata. La Argus MagiCam (batteryVersion
161156
- * 1, firmware 2026) collegata in permanenza risponde `chargeStatus: 0`, e per
161157
- * tutta la sua vita è stata riportata NON in carica.
161158
- *
161159
- * Che `adapterStatus` sia un segnale vero e non una costante è MISURATO: il
161160
- * 2026-09-05 l'operatore ha staccato il device 3628 e il payload grezzo è
161161
- * passato da `adapterStatus: 1` a `0`, con `chargeStatus: 0` da entrambe le
161162
- * parti — cioè `chargeStatus` da solo NON distingue i due stati.
161163
- *
161164
- * Due campi assenti NON sono `'none'`: `'none'` è un negativo che il firmware
161165
- * ha detto ("nessun adattatore, cella ferma"), l'assenza di entrambi è
161166
- * `'unknown'` — lo stesso confine che `percentage` ha chiuso diventando
161167
- * `nullable` (D315). Il chiamante (`mapBatteryInfo`) non arriva qui con un
161168
- * push che non parla di alimentazione: `reportsPowerSource` lo filtra prima e
161169
- * conserva la convinzione precedente.
161598
+ * From `adapterStatus` + `chargeStatus` to the power source.
161599
+ *
161600
+ * The two fields answer TWO different questions, and confusing them is the bug that
161601
+ * this module exists to close:
161602
+ *
161603
+ * - `adapterStatus` — is the power CONNECTED? The firmware sends 0/1/2
161604
+ * (none · DC adapter · solar panel) and the hub boundary
161605
+ * translates it into `'none' | 'dc' | 'solarPanel'` (`mapHubChargeStatus` and
161606
+ * `mapHubAdapterStatus` in `reolink-hub.ts`), because the vocabulary of the
161607
+ * standalone path is already strings.
161608
+ * - `chargeStatus` — what is the CELL doing? 0 stopped · 1 charging ·
161609
+ * 2 fully charged.
161610
+ *
161611
+ * The old derivation consulted the adapter ONLY to look for 'solar' in it, and
161612
+ * a connected DC fell into the fallback `'none'`. Two Argus 3E units hid it by
161613
+ * chance: full and connected they answer `chargeStatus: 2`, which the `isCharging`
161614
+ * branch mapped to `'dc'` for the wrong reason. The Argus MagiCam (batteryVersion
161615
+ * 1, firmware 2026) permanently connected answers `chargeStatus: 0`, and for
161616
+ * its whole life it was reported as NOT charging.
161617
+ *
161618
+ * That `adapterStatus` is a real signal and not a constant is MEASURED: on
161619
+ * 2026-09-05 the operator unplugged device 3628 and the raw payload
161620
+ * went from `adapterStatus: 1` to `0`, with `chargeStatus: 0` on both
161621
+ * sides — i.e. `chargeStatus` alone does NOT distinguish the two states.
161622
+ *
161623
+ * Two absent fields are NOT `'none'`: `'none'` is a negative the firmware
161624
+ * has stated ("no adapter, cell stopped"), the absence of both is
161625
+ * `'unknown'` — the same boundary `percentage` closed by becoming
161626
+ * `nullable` (D315). The caller (`mapBatteryInfo`) does not arrive here with a
161627
+ * push that says nothing about power: `reportsPowerSource` filters it out first and
161628
+ * keeps the previous belief.
161170
161629
  */
161171
161630
  function deriveChargingSource(adapterStatus, chargeStatus) {
161172
161631
  if (adapterStatus === void 0 && chargeStatus === void 0) return "unknown";