@camstack/addon-terminal 0.1.122 → 0.1.123

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 +887 -321
  2. package/dist/addon.mjs +887 -321
  3. package/package.json +1 -3
package/dist/addon.mjs CHANGED
@@ -8,7 +8,7 @@ import { createServer } from "node:http";
8
8
  //#region \0rolldown/runtime.js
9
9
  var __commonJSMin = (cb, mod) => () => (mod || (cb((mod = { exports: {} }).exports, mod), cb = null), mod.exports);
10
10
  //#endregion
11
- //#region ../types/dist/event-category-C5xZWqz6.mjs
11
+ //#region ../types/dist/event-category-BGmz_oxW.mjs
12
12
  var EventCategory = /* @__PURE__ */ function(EventCategory) {
13
13
  EventCategory["SystemBoot"] = "system.boot";
14
14
  EventCategory["SystemAddonsReady"] = "system.addons-ready";
@@ -541,6 +541,15 @@ var EventCategory = /* @__PURE__ */ function(EventCategory) {
541
541
  */
542
542
  EventCategory["PipelineAudioInferenceResult"] = "pipeline.audio-inference-result";
543
543
  EventCategory["DetectionPhaseTransition"] = "detection.phase-transition";
544
+ /**
545
+ * A camera provider's RAW onboard motion push (D673): the `MotionOnMotionChanged`
546
+ * data shape without `triggeredBy`, built by `providerMotionEvent`. Its one
547
+ * consumer is the orchestrator's camera-sensors bridge, which re-emits the
548
+ * camera's EFFECTIVE onboard motion as `MotionOnMotionChanged` (a pass-through
549
+ * for a camera with no attached sensor). Providers must not emit
550
+ * `MotionOnMotionChanged` themselves; `scripts/check-onboard-motion-emitters.ts`
551
+ * keeps it so (camera-grid is a named, deferred exception).
552
+ */
544
553
  EventCategory["ProviderMotion"] = "provider.motion";
545
554
  EventCategory["ProviderDetection"] = "provider.detection";
546
555
  EventCategory["EnrichmentEmbeddingStored"] = "enrichment.embedding.stored";
@@ -5379,7 +5388,7 @@ var ZodIssueCode = {
5379
5388
  var ZodFirstPartyTypeKind;
5380
5389
  ZodFirstPartyTypeKind || (ZodFirstPartyTypeKind = {});
5381
5390
  //#endregion
5382
- //#region ../types/dist/sleep-gU6hqv4_.mjs
5391
+ //#region ../types/dist/sleep-CDCONfkt.mjs
5383
5392
  /**
5384
5393
  * The audio chunk plane's byte format, and the ONE expansion from a coded
5385
5394
  * window to float samples (D455).
@@ -7481,7 +7490,7 @@ function errMsg(err) {
7481
7490
  return String(err);
7482
7491
  }
7483
7492
  //#endregion
7484
- //#region ../types/dist/composition-Dq42XWp0.mjs
7493
+ //#region ../types/dist/composition-Bzr7GwgP.mjs
7485
7494
  /**
7486
7495
  * The ffmpeg build every CamStack node downloads, per platform and arch.
7487
7496
  *
@@ -7535,21 +7544,20 @@ function portable(target) {
7535
7544
  }
7536
7545
  portable("linux64"), portable("linuxarm64"), portable("macarm64"), portable("mac64");
7537
7546
  /**
7538
- * LA tabella "quale booleano di questo tipo di device conta come ALTO", e il
7539
- * valutatore puro del suo FRONTE.
7547
+ * THE table "which boolean of this device type counts as HIGH", and the
7548
+ * pure evaluator of its EDGE.
7540
7549
  *
7541
- * Viveva dentro il builtin virtual-doorbell
7542
- * (`@camstack/system` — `builtins/doorbell/trigger-engine.ts`) e i suoi
7543
- * predicati erano privati al modulo. Il recorder ne ha bisogno per il trigger
7544
- * `RecordingTriggers.sensorDeviceIds`: copiarla avrebbe creato la SECONDA
7545
- * tabella, che diverge alla prima cap aggiunta e il cui sintomo — "il sensore
7546
- * fa suonare il campanello ma non registra" — è esattamente D62. Quindi si
7547
- * SPOSTA qui e il doorbell la ri-esporta.
7550
+ * ONE table for everyone who asks "is this device HIGH?": the
7551
+ * recorder's `RecordingTriggers.sensorDeviceIds` trigger, the post-analysis
7552
+ * sensor markers, the orchestrator's camera-sensors bridge and
7553
+ * the sources of a composite doorbell (`doorbellFeatureSources`, D671).
7554
+ * A second copy would diverge at the first cap added, and the symptom — "the
7555
+ * sensor rings the doorbell but does not record" — is exactly D62.
7548
7556
  *
7549
- * ⚠ NON è `DEVICE_STATE_READERS` (`catalogs/device-state-vocabulary.ts`), e le
7550
- * due non vanno unificate: quella risponde a "qual è la PAROLA di stato per una
7551
- * regola" (e include `presence`, `cover`, `alarm-panel`), questa a "qual è il
7552
- * booleano il cui FRONTE conta". Vocabolari deliberatamente diversi.
7557
+ * ⚠ NOT `DEVICE_STATE_READERS` (`catalogs/device-state-vocabulary.ts`), and the
7558
+ * two must not be unified: that one answers "what is the state WORD for a
7559
+ * rule" (and includes `presence`, `cover`, `alarm-panel`), this one "which
7560
+ * boolean's EDGE counts". Deliberately different vocabularies.
7553
7561
  */
7554
7562
  /**
7555
7563
  * Known binary / switch source caps → the boolean slice field whose
@@ -9190,22 +9198,22 @@ var CLASS_MAP_MACRO_TARGETS = [
9190
9198
  "package"
9191
9199
  ];
9192
9200
  /**
9193
- * Le macro classi di PRIMO LIVELLO: quelle che un object detector emette e che
9194
- * un operatore può selezionare.
9201
+ * The FIRST-LEVEL macro classes: those an object detector emits and that
9202
+ * an operator can select.
9195
9203
  *
9196
- * Sono le tre offerte dallo step `object-detection`
9204
+ * They are the three offered by the `object-detection` step
9197
9205
  * (`addon-pipeline/src/detection-pipeline/registry/step-definitions.ts`,
9198
- * `enabledMacroClasses`). `package` sta in {@link CLASS_MAP_MACRO_TARGETS} e in
9199
- * `MACRO_LABELS` — è una macro vera — ma NON qui: appartiene allo step
9200
- * `package-detection`, la cui abilitazione è guidata dalle zone, e offrire la
9201
- * stessa parola due volte ha già fatto accendere a un operatore il proxy COCO
9206
+ * `enabledMacroClasses`). `package` is in {@link CLASS_MAP_MACRO_TARGETS} and in
9207
+ * `MACRO_LABELS` — it is a true macro — but NOT here: it belongs to the step
9208
+ * `package-detection`, whose enablement is driven by zones, and offering the
9209
+ * same word twice has already made an operator turn on the COCO proxy
9202
9210
  * (suitcase/backpack/handbag) lasciando spento il detector dedicato.
9203
9211
  *
9204
- * UNA lista. Prima di oggi le stesse tre erano scritte a mano nell'offerta
9205
- * dello step e una seconda volta come union `FirstLevelMacro`
9206
- * (`types/detection.ts`); una terza copia per il trigger di registrazione
9207
- * (`RecordingTriggers.objectClasses`) avrebbe reso invisibile la divergenza
9208
- * successiva.
9212
+ * ONE list. Before today the same three were hand-written in the step's offer
9213
+ * and a second time as the union `FirstLevelMacro`
9214
+ * (`types/detection.ts`); a third copy for the recording trigger
9215
+ * (`RecordingTriggers.objectClasses`) would have made the later divergence
9216
+ * invisible.
9209
9217
  */
9210
9218
  var FIRST_LEVEL_MACRO_CLASSES = [
9211
9219
  "person",
@@ -9270,17 +9278,17 @@ var RecordingStorageModeSchema = _enum([
9270
9278
  "on-device-decision"
9271
9279
  ]);
9272
9280
  /**
9273
- * Le macro classi che possono aprire una finestra di registrazione — le stesse
9274
- * tre offerte dallo step `object-detection`, da UNA lista
9281
+ * The macro classes that can open a recording window — the same
9282
+ * three offered by the `object-detection` step, from ONE list
9275
9283
  * ({@link FIRST_LEVEL_MACRO_CLASSES}).
9276
9284
  */
9277
9285
  var RecordingObjectTriggerClassSchema = _enum(FIRST_LEVEL_MACRO_CLASSES);
9278
9286
  /**
9279
- * True quando `values` non ripete un elemento.
9287
+ * True when `values` does not repeat an element.
9280
9288
  *
9281
- * Un duplicato non è innocuo: ogni voce di `objectClasses` / `sensorDeviceIds`
9282
- * diventa una SORGENTE in `bandTriggerSources`, e la stessa sorgente due volte
9283
- * conterebbe due volte le sue finestre in `segmentMissedByMs`.
9289
+ * A duplicate is not harmless: every entry of `objectClasses` / `sensorDeviceIds`
9290
+ * becomes a SOURCE in `bandTriggerSources`, and the same source twice
9291
+ * would count its windows twice in `segmentMissedByMs`.
9284
9292
  */
9285
9293
  var noDuplicates = (values) => new Set(values).size === values.length;
9286
9294
  /** Which detectors trigger an `events`-mode band. */
@@ -9288,34 +9296,34 @@ var RecordingTriggersSchema = object({
9288
9296
  motion: boolean().optional(),
9289
9297
  audioThresholdDbfs: number().optional(),
9290
9298
  /**
9291
- * Le macro classi la cui detection apre una finestra. ASSENTE = la sorgente
9292
- * non è ascoltata; un array VUOTO è rifiutato, perché "banda events, trigger
9293
- * object acceso, nessuna classe" è la stessa forma "abilitata e non registra
9294
- * nulla, per sempre" contro cui è scritto `eventsBandCanEverDemand`.
9299
+ * The macro classes whose detection opens a window. ABSENT = the source
9300
+ * is not listened to; an EMPTY array is rejected, because "events band, object
9301
+ * trigger on, no class" is the same shape "enabled and records
9302
+ * nothing, forever" that `eventsBandCanEverDemand` is written against.
9295
9303
  *
9296
- * Il segnale letto è GIÀ FILTRATO: solo detection `source: 'pipeline'`, cioè
9297
- * quelle che hanno attraversato `enabledMacroClasses`, i
9298
- * `minConfidence<Macro>` e il full-frame guard. L'AI a bordo camera
9299
- * (`source: 'onboard'`) non attraversa nessuno di quei gate e NON apre
9300
- * finestre — vedi `recorder/object-trigger.ts`.
9304
+ * The signal read is ALREADY FILTERED: only `source: 'pipeline'` detections, i.e.
9305
+ * those that went through `enabledMacroClasses`, the
9306
+ * `minConfidence<Macro>` and the full-frame guard. The camera's onboard AI
9307
+ * (`source: 'onboard'`) goes through none of those gates and does NOT open
9308
+ * windows — see `recorder/object-trigger.ts`.
9301
9309
  */
9302
9310
  objectClasses: array(RecordingObjectTriggerClassSchema).min(1).refine(noDuplicates, { message: "objectClasses must not repeat a class" }).optional(),
9303
9311
  /**
9304
- * I device LINKED il cui FRONTE ALTO apre una finestra. Assente = la sorgente
9305
- * non è ascoltata; un array vuoto è rifiutato per la stessa ragione di
9312
+ * The LINKED devices whose RISING EDGE opens a window. Absent = the source
9313
+ * is not listened to; an empty array is rejected for the same reason as
9306
9314
  * `objectClasses`.
9307
9315
  *
9308
- * Sono id di device SORGENTE, non camere: la banda li nomina, quindi il
9309
- * percorso caldo (`DeviceStateChanged`, a ritmo di bus su tutta la flotta)
9310
- * non fa RPC. L'OFFERTA da cui l'operatore li sceglie è un'altra domanda, e
9311
- * si risolve con `deviceManager.getLinkedDevices` + `getBindingsBatch` per
9312
- * device (D12) — mai un elenco globale di cap.
9316
+ * These are SOURCE device ids, not cameras: the band names them, so the
9317
+ * hot path (`DeviceStateChanged`, at bus rate across the whole fleet)
9318
+ * does no RPC. The OFFER from which the operator picks them is another question, and
9319
+ * is resolved with `deviceManager.getLinkedDevices` + `getBindingsBatch` per
9320
+ * device (D12) — never a global list of caps.
9313
9321
  *
9314
- * Cosa vuol dire "alto" dipende dal TIPO di device e non è deciso qui:
9315
- * `SOURCE_CAP_ACTIVE_FIELD` (`catalogs/sensor-active-state.ts`) è LA tabella,
9316
- * la stessa che il virtual-doorbell usa dal 2026-08-05. Ed è il FRONTE, non
9317
- * il livello: un contatto trovato già aperto al riavvio del runner non fa
9318
- * registrare.
9322
+ * What "high" means depends on the device TYPE and is not decided here:
9323
+ * `SOURCE_CAP_ACTIVE_FIELD` (`catalogs/sensor-active-state.ts`) is THE table,
9324
+ * the same one as the composite doorbell (D671). And it is the EDGE, not
9325
+ * the level: a contact found already open at runner restart does not
9326
+ * record.
9319
9327
  */
9320
9328
  sensorDeviceIds: array(number().int().positive()).min(1).max(16).refine(noDuplicates, { message: "sensorDeviceIds must not repeat a device" }).optional()
9321
9329
  });
@@ -10392,7 +10400,7 @@ var DecoderSessionConfigSchema = object({
10392
10400
  * - **VALUE** — at which level, for which scope, until when. That stays ONE
10393
10401
  * thing: the logging settings document on the `system` cap. Two authorities
10394
10402
  * over the values is the exact defect
10395
- * `docs/design/plans/2026-08-26-logging-per-componente.md` was written to
10403
+ * `docs/design/plans/2026-08-26-per-component-logging.md` was written to
10396
10404
  * remove; re-introducing it from the cure side would be grotesque.
10397
10405
  *
10398
10406
  * Nothing in this file reads a clock, an env var or a store. The registry is
@@ -12103,7 +12111,7 @@ var BrokerStatusEnum = _enum([
12103
12111
  "unreachable",
12104
12112
  "error"
12105
12113
  ]);
12106
- var BrokerInfoSchema$1 = object({
12114
+ var BrokerInfoSchema = object({
12107
12115
  /** Stable broker id. Persisted; survives addon restarts. */
12108
12116
  id: string(),
12109
12117
  /** Addon id of the provider that OWNS this broker.
@@ -12236,7 +12244,7 @@ var GetStateInputSchema = object({
12236
12244
  * HA: entity_id (returns the cached entity state). */
12237
12245
  key: string()
12238
12246
  });
12239
- method(ListInputSchema, array(BrokerInfoSchema$1)), method(GetInputSchema, BrokerInfoSchema$1.nullable()), method(_void(), array(BrokerProviderInfoSchema), { auth: "admin" }), method(AddInputSchema, AddResultSchema, {
12247
+ method(ListInputSchema, array(BrokerInfoSchema)), method(GetInputSchema, BrokerInfoSchema.nullable()), method(_void(), array(BrokerProviderInfoSchema), { auth: "admin" }), method(AddInputSchema, AddResultSchema, {
12240
12248
  kind: "mutation",
12241
12249
  auth: "admin"
12242
12250
  }), method(RemoveInputSchema, _void(), {
@@ -13947,7 +13955,7 @@ method(_void(), EngineInfoSchema, { auth: "admin" }), method(object({
13947
13955
  *
13948
13956
  * ⚠ An earlier version of this comment blamed Zod stripping, and that
13949
13957
  * was wrong — corrected 2026-08-26 after the hop map
13950
- * (`docs/design/2026-08-26-mappa-hop-argomenti.md`) traced the path.
13958
+ * (`docs/design/2026-08-26-topic-hop-map.md`) traced the path.
13951
13959
  * There is **no Zod parse at all** between the door and the engine: the
13952
13960
  * dispatcher forwards the payload verbatim and UDS carries it whole. A
13953
13961
  * field declared here reaches `SqliteSettingsBackend` either way.
@@ -14810,7 +14818,17 @@ var SiteZoneSchema = object({
14810
14818
  var ProviderStatusSchema = object({
14811
14819
  connected: boolean(),
14812
14820
  deviceCount: number(),
14813
- error: string().optional()
14821
+ error: string().optional(),
14822
+ /**
14823
+ * `'orchestrator'`: this provider writes NO camera's `motion` runtime slice
14824
+ * — the orchestrator is its only writer (D696). Set by `BaseDeviceProvider`,
14825
+ * which every provider bundles, so only a provider BUILT from D696-amended
14826
+ * code says it. ABSENT means an older provider that may still write it (raw
14827
+ * VMD writes, a boot seed), and the orchestrator's provider gate keeps that
14828
+ * provider's cameras unwritten (`camera-sensors/motion-slice-provider-gate.ts`)
14829
+ * — the provider twin of the runner's `getLocalLoad().motionSliceWriter`.
14830
+ */
14831
+ motionSliceWriter: literal("orchestrator").optional()
14814
14832
  });
14815
14833
  object({
14816
14834
  externalId: string(),
@@ -15608,109 +15626,10 @@ method(object({
15608
15626
  deviceIds: array(number()).readonly(),
15609
15627
  caps: array(string()).readonly().optional()
15610
15628
  }), record(string(), record(string(), unknown().nullable())));
15611
- /**
15612
- * Doorbell button cap. Two kinds of providers coexist behind this cap
15613
- * name (same pattern as `snapshot`):
15614
- *
15615
- * - **Native** providers: registered per-device by device-driver
15616
- * addons via `ctx.registerNativeCap` — either on a
15617
- * `DeviceType.Button` accessory with `role: DeviceRole.Doorbell`,
15618
- * or directly on the camera (Reolink registers at camera level).
15619
- * Emits an `onPressed` event every time the firmware pushes a
15620
- * ring; status tracks the last press and a pressCount since start
15621
- * (diagnostic).
15622
- *
15623
- * - **Wrapper** provider: the `virtual-doorbell` system builtin
15624
- * (`@camstack/system/builtins/doorbell`). Turns ANY binary-ish
15625
- * device (contact / switch / event-emitter …) into a doorbell for
15626
- * a camera. `defaultActive: false` — the operator explicitly binds
15627
- * it per camera in the device-bindings UI, then picks the source
15628
- * device + trigger in the per-device settings.
15629
- *
15630
- * The DeviceEventPropagator re-emits `onPressed` on the camera parent
15631
- * — subscribers listening at the camera level receive ring events
15632
- * with `via[]` populated. No code on the parent needed.
15633
- */
15634
- var DoorbellStatusSchema = object({
15635
- /** Ms epoch of the last press. null = never observed since this provider started. */
15636
- lastPressedAt: number().nullable(),
15637
- /** Counter since provider start. Resets on reboot. Useful for metrics/debug. */
15638
- pressCountSinceStart: number()
15639
- });
15640
- var DoorbellPressEventSchema = object({
15641
- deviceId: number(),
15642
- timestamp: number()
15643
- });
15644
- /**
15645
- * The `doorbell-source` extension slot's editable value (D648): the camera's
15646
- * virtual-doorbell trigger devices, exactly what the wrapper's
15647
- * `doorbellSources` persists (as `{ deviceId }` records).
15648
- */
15649
- var DoorbellSourceSlotValueSchema = object({ deviceIds: array(number().int().positive()) });
15650
- /**
15651
- * The `doorbell-source` slot — which devices ring this camera's VIRTUAL
15652
- * doorbell, owned by the `virtual-doorbell` wrapper over its
15653
- * `doorbellSources` store (D648). A source rings when one of its
15654
- * `SOURCE_CAPS` rises. Whether the wrapper is bound to the camera at all is a
15655
- * different authority (`deviceManager.setWrapperActive`, D62) — the slot
15656
- * reports it, it never writes it.
15657
- */
15658
- var DOORBELL_SOURCE_SLOT = {
15659
- id: "doorbell-source",
15660
- label: "Doorbell trigger devices",
15661
- description: "Any of these becoming active rings this camera's virtual doorbell: a binary sensor when it goes active, a switch when it turns on.",
15662
- shape: "association",
15663
- hostDeviceTypes: [DeviceType.Camera],
15664
- sourceCaps: SOURCE_CAPS,
15665
- cardinality: "many",
15666
- value: DoorbellSourceSlotValueSchema
15667
- };
15668
- var doorbellCapability = {
15669
- name: "doorbell",
15670
- scope: "device",
15671
- deviceNative: true,
15672
- mode: "singleton",
15673
- kind: "wrapper",
15674
- defaultActive: false,
15675
- deviceTypes: [DeviceType.Button, DeviceType.Camera],
15676
- extensionSlots: [DOORBELL_SOURCE_SLOT],
15677
- methods: {},
15678
- events: {
15679
- /**
15680
- * Fires once per physical press. Reolink delivers via Baichuan
15681
- * push (`ReolinkSimpleEvent.type === 'doorbell'`). There is no
15682
- * release/duration — it's a pulse.
15683
- */
15684
- onPressed: {
15685
- data: DoorbellPressEventSchema,
15686
- fromState: {
15687
- field: "lastPressedAt",
15688
- on: "advance"
15689
- }
15690
- } },
15691
- status: {
15692
- schema: DoorbellStatusSchema,
15693
- kind: "push"
15694
- },
15695
- /**
15696
- * Runtime-state slice — last press timestamp + lifetime press count.
15697
- * Mirrored by the kernel and readable via
15698
- * `device.state.doorbell.value`. UIs can show "last ring 5m ago"
15699
- * without subscribing.
15700
- */
15701
- runtimeState: DoorbellStatusSchema,
15702
- /**
15703
- * Runtime-state durability: **restored** — a monotonic accumulator: the slice IS the record. `lastPressedAt` is content here, not a clock, so it is deliberately NOT volatile.
15704
- *
15705
- * See `RuntimeStateDurability`. Enforced by
15706
- * `scripts/check-runtime-state-durability.ts`.
15707
- */
15708
- durability: "restored"
15709
- };
15710
- var ExtensionSlotIdSchema = _enum(["doorbell-source", "linked-devices"]);
15711
- DeviceType.Camera, DeviceType.Camera;
15629
+ var ExtensionSlotIdSchema = _enum(["linked-devices"]);
15630
+ DeviceType.Camera;
15712
15631
  /** A slot's editable value, discriminated on `slot`. */
15713
- var ExtensionSlotValueSchema = discriminatedUnion("slot", [DoorbellSourceSlotValueSchema.extend({ slot: literal("doorbell-source") }), LinkedDevicesSlotValueSchema.extend({ slot: literal("linked-devices") })]);
15632
+ var ExtensionSlotValueSchema = discriminatedUnion("slot", [LinkedDevicesSlotValueSchema.extend({ slot: literal("linked-devices") })]);
15714
15633
  DeviceType.Camera;
15715
15634
  var ExtensionSourceAvailabilitySchema = discriminatedUnion("state", [object({ state: literal("ok") }), object({
15716
15635
  state: literal("unreachable"),
@@ -15747,10 +15666,11 @@ var ExtensionSlotSourceSchema = object({
15747
15666
  });
15748
15667
  /**
15749
15668
  * A DIFFERENT authority that gates whether the slot's sources do anything —
15750
- * reported read-only, named, never written through this contract (D62). The
15751
- * virtual doorbell's sources ring only while the wrapper is bound to the
15752
- * camera, and that binding belongs to `deviceManager.setWrapperActive`.
15753
- * `unknown` means the gate could not be read; it is not "inactive" (D315).
15669
+ * reported read-only, named, never written through this contract (D62) — e.g.
15670
+ * a slot whose sources act only while a wrapper is bound to the host, a
15671
+ * binding that belongs to `deviceManager.setWrapperActive`. No slot reports
15672
+ * one today (`linked-devices` answers `null`). `unknown` means the gate could
15673
+ * not be read; it is not "inactive" (D315).
15754
15674
  */
15755
15675
  var ExtensionSlotActivationSchema = object({
15756
15676
  state: _enum([
@@ -15766,7 +15686,7 @@ var ExtensionSlotRowSchema = discriminatedUnion("state", [object({
15766
15686
  /** `<source>:<slotId>` — the routing key for `listCandidates` / `setSlot`. */
15767
15687
  slotRef: string(),
15768
15688
  slot: ExtensionSlotIdSchema,
15769
- /** Names the store written (D62), e.g. `virtual-doorbell:doorbellSources`. */
15689
+ /** Names the store written (D62), e.g. `device-manager:_linkedDeviceIds`. */
15770
15690
  authority: string(),
15771
15691
  activation: ExtensionSlotActivationSchema.nullable(),
15772
15692
  value: ExtensionSlotValueSchema,
@@ -16044,7 +15964,7 @@ method(object({
16044
15964
  * per-device window, `KeyFrameCaptureLog`, `bumpCropMetric`. Every one of them
16045
15965
  * ends in a log line, and a log line is the thing the operator asked to stop
16046
15966
  * needing: *"possiamo armare questi errori intanto? Così al prossimo giro
16047
- * ricontrolliamo tutti questi punti"*. Reading them meant grepping Loki and
15967
+ * 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
16048
15968
  * hand-correlating timestamps, which is how a 22% thumbnail gap and a 3-hour
16049
15969
  * media blackout were both diagnosed. The counters stay; this is where they can
16050
15970
  * be READ.
@@ -17420,7 +17340,7 @@ var BrokerStatusSchema$1 = _enum([
17420
17340
  "unreachable",
17421
17341
  "tls-error"
17422
17342
  ]);
17423
- var BrokerInfoSchema = object({
17343
+ var BrokerInfoSchema$1 = object({
17424
17344
  id: string(),
17425
17345
  name: string(),
17426
17346
  url: string(),
@@ -17483,7 +17403,7 @@ var StatusSchema = object({
17483
17403
  brokerCount: number(),
17484
17404
  embeddedRunning: boolean()
17485
17405
  });
17486
- method(_void(), array(BrokerInfoSchema)), method(IdInputSchema, BrokerConnectionDetailsSchema, { auth: "admin" }), method(AddBrokerInputSchema, AddBrokerResultSchema, {
17406
+ method(_void(), array(BrokerInfoSchema$1)), method(IdInputSchema, BrokerConnectionDetailsSchema, { auth: "admin" }), method(AddBrokerInputSchema, AddBrokerResultSchema, {
17487
17407
  kind: "mutation",
17488
17408
  auth: "admin"
17489
17409
  }), method(IdInputSchema, _void(), {
@@ -19697,78 +19617,16 @@ var NcRuleInputSchema = object({
19697
19617
  */
19698
19618
  confirm: NcConfirmSchema.optional(),
19699
19619
  /**
19700
- * WAIT for face/plate recognition before saying anything.
19701
- *
19702
- * A notification's TEXT is frozen at enqueue and its media is re-resolved at
19703
- * send; the identity is neither. A face is confirmed after `confirmFrames`
19704
- * agreeing observations — p50 **11.4 s** after the track was first seen,
19705
- * measured on this hub — and an `immediate` rule enqueues on the first object
19706
- * event, seconds before that. So "Gianluca è arrivato" is unsayable on the
19707
- * immediate path, and no amount of media re-resolution fixes a sentence.
19708
- *
19709
- * Only two honest answers exist, and this flag picks between them. It has
19710
- * effect ONLY on a rule that declares a recognition scope
19711
- * ({@link NcConditions.identities} or {@link NcConditions.plates}) — on any
19712
- * other rule there is nothing to wait for and the flag is inert.
19713
- *
19714
- * | value | what happens |
19715
- * | --- | --- |
19716
- * | `true` | the rule stops firing on the object event and fires at TRACK CLOSE instead, once, with the name — later, and complete |
19717
- * | 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) |
19718
- *
19719
- * `.optional()` and deliberately NOT `.default()`: a Zod default does not run
19720
- * on the addon cap path, and absent has to keep meaning exactly what every
19721
- * rule authored before this field meant.
19722
- *
19723
- * The cost of `true` is stated here because the editor states it too: a rule
19724
- * that waits also inherits track-close SEMANTICS — its `zones` condition
19725
- * tests every zone the track visited and a `crossing` condition can no longer
19726
- * be satisfied, because a closed track carries no crossing.
19620
+ * IMMEDIATE GROUPED (D692): the first matching subject opens a window of this many
19621
+ * seconds; the rule sends ONE message when the window closes — early, once every
19622
+ * subject in it is final, never before {@link NC_GROUPING_MIN_SEC} — naming everybody
19623
+ * the rule matched, with one mosaic tile per subject.
19624
+ * Absent = plain immediate (one message per track, at the first match).
19625
+ * Only an `immediate` DETECTION rule may carry it (`ruleGroupingApplies`, enforced on
19626
+ * save by the hub's grouping guard). `.optional()`, never `.default()`: the addon cap
19627
+ * path does not run Zod defaults.
19727
19628
  */
19728
- waitForEnhancement: boolean().optional(),
19729
- /**
19730
- * GROUP a burst of subjects into ONE notification that grows.
19731
- *
19732
- * Seconds of quiet after the last matching subject before the burst is
19733
- * considered over. While it is open, the first subject enqueues immediately —
19734
- * **exactly as today, with no added latency** — and every real growth (a new
19735
- * subject, or a name confirmed on one already in it) REPLACES that
19736
- * notification with an updated one naming everybody. The push carries the
19737
- * group's own coalescing tag, so the phone replaces rather than stacks.
19738
- *
19739
- * `0` / absent = off, and off is today's behaviour byte for byte.
19740
- *
19741
- * ### Why an idle cutoff and not a window
19742
- *
19743
- * The measured seven-person arrival on device 590 spans 110 s with every
19744
- * internal gap under 30 s. A 12 s fixed window cuts it into three groups; an
19745
- * idle cutoff holds it as one and ends it when the arrival actually ends.
19746
- * 30 s is a widely shipped value for the same decision.
19747
- *
19748
- * ### What it replaces
19749
- *
19750
- * The blind cooldown, which collapses a burst by DISCARDING it. Measured on
19751
- * device 615 / *Persona su Uscio* over six days: 116 qualifying tracks → 74
19752
- * notifications, **44 (37.9%) suppressed outright**, 23 of them overlapping a
19753
- * track that did fire and 7 carrying a confirmed identity nobody heard about.
19754
- * A group collapses the same volume by MERGING, so the cooldown becomes a
19755
- * budget over GROUPS — which is what it always meant — and a growth is never
19756
- * throttled by the window its own first member spent.
19757
- *
19758
- * ### Interaction with {@link waitForEnhancement}
19759
- *
19760
- * They compose, and the order matters. `waitForEnhancement` defers the rule to
19761
- * TRACK CLOSE, so with both set the group is opened by the first member to
19762
- * CLOSE — already carrying its name — and grows as later members close. That
19763
- * is later, and complete. With grouping alone the group opens on the first
19764
- * object event and picks up names as they are confirmed, through the growth
19765
- * path. Neither combination fires twice for one subject.
19766
- *
19767
- * `.optional()` and deliberately NOT `.default()`: a Zod default does not run
19768
- * on the addon cap path, so absent must keep meaning what it meant before this
19769
- * field existed.
19770
- */
19771
- groupIdleSec: number().int().min(0).max(600).optional()
19629
+ groupingSec: number().int().min(5).max(60).optional()
19772
19630
  });
19773
19631
  /**
19774
19632
  * Partial patch for `updateRule` — any subset of the input fields, plus the
@@ -19816,9 +19674,10 @@ var NcRuleClearableKeySchema = _enum([
19816
19674
  "targetUsers",
19817
19675
  "snoozeOptions",
19818
19676
  "snoozeAllowGlobal",
19819
- "waitForEnhancement",
19820
19677
  "actions",
19821
19678
  "confirm",
19679
+ "groupingSec",
19680
+ "waitForEnhancement",
19822
19681
  "groupIdleSec"
19823
19682
  ]);
19824
19683
  var NcRuleUpdateInputSchema = object({
@@ -19840,9 +19699,25 @@ var NcRuleSchema = NcRuleInputSchema.extend({
19840
19699
  */
19841
19700
  disabledTargetIds: array(string()).default([])
19842
19701
  });
19702
+ /**
19703
+ * The state-summary SECTIONS (D647 / D698): the D637 kind groups that report a
19704
+ * still-true state. `backups-exports` and `alarm` are not sections — a completed
19705
+ * job is not an open state, and the alarm stays instant.
19706
+ */
19707
+ var NcStateSummarySectionIdSchema = _enum([
19708
+ "device-state",
19709
+ "streams",
19710
+ "battery",
19711
+ "consumables",
19712
+ "tanks",
19713
+ "detection-blind",
19714
+ "nodes",
19715
+ "addons",
19716
+ "updates"
19717
+ ]);
19843
19718
  /** One section of a previewed state summary. `unavailable` = its state could not be read. */
19844
19719
  var NcStateSummaryPreviewSectionSchema = object({
19845
- id: string(),
19720
+ id: NcStateSummarySectionIdSchema,
19846
19721
  status: _enum(["read", "unavailable"]),
19847
19722
  items: number().int().nonnegative(),
19848
19723
  reason: string().optional()
@@ -19852,7 +19727,7 @@ var NcStateSummaryPreviewSectionSchema = object({
19852
19727
  * a `rule` split (no `section`), one section's on a `section` split.
19853
19728
  */
19854
19729
  var NcStateSummaryPreviewRowSchema = object({
19855
- section: string().optional(),
19730
+ section: NcStateSummarySectionIdSchema.optional(),
19856
19731
  /** The section's name on a per-section row; every reported section's, joined, on a combined one. */
19857
19732
  title: string(),
19858
19733
  text: string(),
@@ -20289,6 +20164,29 @@ object({
20289
20164
  firstAt: number(),
20290
20165
  lastAt: number()
20291
20166
  });
20167
+ var NC_ALARM_TRIGGERED_MAX_SEC = 3600;
20168
+ var NcAlarmDelaySecSchema = number().int().min(0).max(600);
20169
+ var NcAlarmTriggeredSecSchema = number().int().min(0).max(NC_ALARM_TRIGGERED_MAX_SEC);
20170
+ var uniqueModes = (entries) => new Set(entries.map((e) => e.mode)).size === entries.length;
20171
+ var NcAlarmModeDelaysListSchema = array(object({
20172
+ mode: AlarmArmModeSchema,
20173
+ exitDelaySec: NcAlarmDelaySecSchema.optional(),
20174
+ entryDelaySec: NcAlarmDelaySecSchema.optional(),
20175
+ triggeredDurationSec: NcAlarmTriggeredSecSchema.optional()
20176
+ })).max(8).refine(uniqueModes, { message: "modeDelays: at most one entry per arm mode" });
20177
+ var NcAlarmModeDelaysEditListSchema = array(object({
20178
+ mode: AlarmArmModeSchema,
20179
+ exitDelaySec: NcAlarmDelaySecSchema.nullable().optional(),
20180
+ entryDelaySec: NcAlarmDelaySecSchema.nullable().optional(),
20181
+ triggeredDurationSec: NcAlarmTriggeredSecSchema.nullable().optional()
20182
+ })).max(8).refine(uniqueModes, { message: "modeDelays: at most one edit per arm mode" });
20183
+ /** One switch of the alarm table: put ONE device on, or take it off, ONE mode's list. */
20184
+ var NcAlarmNonBlockingEditSchema = object({
20185
+ mode: AlarmArmModeSchema,
20186
+ deviceId: number().int().positive(),
20187
+ /** true = on the list (may be open, does not block); false = off the list (blocks). */
20188
+ nonBlocking: boolean()
20189
+ });
20292
20190
  /**
20293
20191
  * The per-mode lists, at most one per mode. Two lists for one mode have no
20294
20192
  * meaning a reader could agree on (union? the last one?), so they are refused
@@ -20297,10 +20195,10 @@ object({
20297
20195
  var NcAlarmNonBlockingListSchema = array(object({
20298
20196
  mode: AlarmArmModeSchema,
20299
20197
  deviceIds: array(number().int()).max(200)
20300
- })).max(8).refine((lists) => new Set(lists.map((l) => l.mode)).size === lists.length, { message: "nonBlocking: at most one list per arm mode" });
20198
+ })).max(8).refine(uniqueModes, { message: "nonBlocking: at most one list per arm mode" });
20301
20199
  /**
20302
- * The three durations the panel's state machine runs on, who hears about its
20303
- * transitions, and which openings each mode tolerates.
20200
+ * The three durations — global, and per mode since D697 — the panel's state
20201
+ * machine runs on, who hears about its transitions, and which openings each mode tolerates.
20304
20202
  *
20305
20203
  * They live on the NOTIFICATION-RULES cap, not on `alarm-panel`, on purpose:
20306
20204
  * `alarm-panel` is `deviceNative` and its other provider mirrors somebody
@@ -20310,15 +20208,15 @@ var NcAlarmNonBlockingListSchema = array(object({
20310
20208
  */
20311
20209
  var NcAlarmSettingsSchema = object({
20312
20210
  /** Grace period between arming and the mode taking effect. 0 = immediate. */
20313
- exitDelaySec: number().int().min(0).max(600),
20211
+ exitDelaySec: NcAlarmDelaySecSchema,
20314
20212
  /** Grace period between a trigger and the alarm firing. 0 = immediate. */
20315
- entryDelaySec: number().int().min(0).max(600),
20213
+ entryDelaySec: NcAlarmDelaySecSchema,
20316
20214
  /**
20317
20215
  * How long `triggered` lasts before the panel re-arms itself.
20318
20216
  * **0 = until an operator disarms it** — the behaviour before this field
20319
20217
  * existed, and therefore what an untouched install keeps doing.
20320
20218
  */
20321
- triggeredDurationSec: number().int().min(0).max(3600),
20219
+ triggeredDurationSec: NcAlarmTriggeredSecSchema,
20322
20220
  /**
20323
20221
  * Deprecated by D630 — every transition is announced. Parsed, never read;
20324
20222
  * remove after one release. Optional so an older admin's patch (which still
@@ -20341,17 +20239,30 @@ var NcAlarmSettingsSchema = object({
20341
20239
  * per mode is meaningful. Defaulted to `[]` so a blob stored before D630
20342
20240
  * parses as "every opening blocks" — the behaviour it was written under.
20343
20241
  */
20344
- nonBlocking: NcAlarmNonBlockingListSchema.default([])
20242
+ nonBlocking: NcAlarmNonBlockingListSchema.default([]),
20243
+ /**
20244
+ * Per arm mode, the delays that mode OVERRIDES (D697). A mode with no entry, or an entry
20245
+ * without a field, uses the global value above — so `[]`, the default, is exactly the
20246
+ * behaviour of a blob stored before this field existed. Read through `resolveModeDelays`.
20247
+ */
20248
+ modeDelays: NcAlarmModeDelaysListSchema.default([])
20345
20249
  });
20346
20250
  /**
20347
20251
  * Every field optional — a tab edits one control at a time.
20348
20252
  *
20349
- * `nonBlocking` is re-declared WITHOUT its default: `.partial()` does not
20350
- * remove an inner `.default()`, so a patch that never named the field would
20351
- * parse to `nonBlocking: []` and wipe every mode's list on an unrelated edit
20352
- * (the same trap {@link NcRulePatchSchema} documents).
20253
+ * `nonBlocking` and `modeDelays` are re-declared WITHOUT their defaults:
20254
+ * `.partial()` does not remove an inner `.default()`, so a patch that never
20255
+ * named the field would parse to `[]` and wipe every mode's list on an
20256
+ * unrelated edit (the same trap {@link NcRulePatchSchema} documents). Here
20257
+ * `modeDelays` means EDITS, not the stored overrides.
20353
20258
  */
20354
- var NcAlarmSettingsPatchSchema = NcAlarmSettingsSchema.extend({ nonBlocking: NcAlarmNonBlockingListSchema }).partial();
20259
+ var NcAlarmSettingsPatchSchema = NcAlarmSettingsSchema.extend({
20260
+ nonBlocking: NcAlarmNonBlockingListSchema,
20261
+ /** Per-mode, per-field edits — NOT the whole list (see NcAlarmModeDelaysEditSchema). */
20262
+ modeDelays: NcAlarmModeDelaysEditListSchema,
20263
+ /** ONE membership change; the panel applies it to the list it holds at its turn. */
20264
+ nonBlockingEdit: NcAlarmNonBlockingEditSchema
20265
+ }).partial().refine((p) => p.nonBlocking === void 0 || p.nonBlockingEdit === void 0, { message: "nonBlocking and nonBlockingEdit are exclusive — send the whole lists or one edit" });
20355
20266
  /**
20356
20267
  * What one arm mode actually arms, DERIVED from the enabled rules gated on it.
20357
20268
  * Never authored, never stored — see `alarm-mode-coverage.ts` for why a stored
@@ -20451,6 +20362,28 @@ var NcAlarmConfigSchema = object({
20451
20362
  */
20452
20363
  live: NcAlarmLiveSchema.optional()
20453
20364
  });
20365
+ var NcAlarmSensorReadingSchema = _enum([
20366
+ "open",
20367
+ "closed",
20368
+ "unknown",
20369
+ "not-opening"
20370
+ ]);
20371
+ /** One device's state as the alarm reads it — the classifier the arm check uses. */
20372
+ var NcAlarmSensorStateSchema = object({
20373
+ deviceId: number().int().positive(),
20374
+ reading: NcAlarmSensorReadingSchema,
20375
+ /** The word as read (`open`, `closed`, `unlocked`, `stopped`, …); null when unknown / not an opening. */
20376
+ state: string().nullable(),
20377
+ /** Why `unknown`: the read failed, or the slice holds no word its cap defines (a placeholder included). */
20378
+ unknownWhy: _enum(["read-failed", "unknown-word"]).nullable(),
20379
+ /** The device manager's liveness as the centre mirrors it; null = not known. */
20380
+ online: boolean().nullable()
20381
+ });
20382
+ var NcAlarmSensorsInputSchema = object({ deviceIds: array(number().int().positive()).max(500) });
20383
+ var NcAlarmSensorsSchema = object({
20384
+ sensors: array(NcAlarmSensorStateSchema),
20385
+ readAt: number().int().nonnegative()
20386
+ });
20454
20387
  /**
20455
20388
  * ONE rule's demand on ONE camera's clip ring.
20456
20389
  *
@@ -20541,7 +20474,7 @@ method(object({}), object({ rules: array(NcRuleSchema) }), { auth: "admin" }), m
20541
20474
  }), method(object({}), NcAlarmConfigSchema, { auth: "admin" }), method(object({ patch: NcAlarmSettingsPatchSchema }), NcAlarmConfigSchema, {
20542
20475
  kind: "mutation",
20543
20476
  auth: "admin"
20544
- });
20477
+ }), method(NcAlarmSensorsInputSchema, NcAlarmSensorsSchema, { auth: "admin" });
20545
20478
  /**
20546
20479
  * Zod schemas for persisted record types.
20547
20480
  *
@@ -20888,12 +20821,26 @@ var CameraSensorRefSchema = object({
20888
20821
  function cameraSensorRefKey(ref) {
20889
20822
  return `${ref.addonId}/${ref.stableId}`;
20890
20823
  }
20891
- /** CS-1 accepts exactly one mode; CS-2 (D673) widens it to confirm / replace. */
20892
- var CameraSensorsModeSchema = _enum(["in-addition"]);
20893
- var CameraSensorsConfigSchema = object({
20894
- mode: CameraSensorsModeSchema,
20895
- sensors: array(CameraSensorRefSchema).min(1).max(8)
20896
- }).superRefine((value, ctx) => {
20824
+ /**
20825
+ * A sensor's mode (D673). `in-addition`: its motion is the camera's motion too.
20826
+ * `replace`: its motion is the camera's, and while one is READY the camera's
20827
+ * own motion no longer counts on its own. `confirm`: while one is READY the
20828
+ * camera's own motion counts only while a confirm sensor is active — with or
20829
+ * without a replace sensor (spec C2, the controller's ruling on Q1).
20830
+ */
20831
+ var CameraSensorModeSchema = _enum([
20832
+ "in-addition",
20833
+ "confirm",
20834
+ "replace"
20835
+ ]);
20836
+ /** A stored sensor with no mode — every CS-1 row — is in addition. */
20837
+ var DEFAULT_CAMERA_SENSOR_MODE = "in-addition";
20838
+ /**
20839
+ * A camera's attached sensors. A CS-1 row carried an envelope
20840
+ * `mode: 'in-addition'`: `z.object` drops it on parse, and the PARSED value is
20841
+ * what the write stores (D672 rule 3), so it is never written again.
20842
+ */
20843
+ var CameraSensorsConfigSchema = object({ sensors: array(CameraSensorRefSchema.extend({ mode: CameraSensorModeSchema.default(DEFAULT_CAMERA_SENSOR_MODE) })).min(1).max(8) }).superRefine((value, ctx) => {
20897
20844
  const seen = /* @__PURE__ */ new Set();
20898
20845
  value.sensors.forEach((ref, index) => {
20899
20846
  const key = cameraSensorRefKey(ref);
@@ -20905,39 +20852,41 @@ var CameraSensorsConfigSchema = object({
20905
20852
  seen.add(key);
20906
20853
  });
20907
20854
  });
20908
- var RefFields = {
20855
+ /** Every attachment names its mode; an older orchestrator that does not is in addition. */
20856
+ var AttachmentFields = {
20909
20857
  addonId: string(),
20910
- stableId: string()
20858
+ stableId: string(),
20859
+ mode: CameraSensorModeSchema.default(DEFAULT_CAMERA_SENSOR_MODE)
20911
20860
  };
20912
20861
  var CameraSensorAttachmentSchema = discriminatedUnion("state", [
20913
20862
  object({
20914
- ...RefFields,
20863
+ ...AttachmentFields,
20915
20864
  state: literal("ready"),
20916
20865
  deviceId: number(),
20917
20866
  name: string(),
20918
20867
  caps: array(string()).readonly()
20919
20868
  }),
20920
20869
  object({
20921
- ...RefFields,
20870
+ ...AttachmentFields,
20922
20871
  state: literal("offline"),
20923
20872
  deviceId: number(),
20924
20873
  name: string(),
20925
20874
  reason: _enum(["offline", "disabled"])
20926
20875
  }),
20927
20876
  object({
20928
- ...RefFields,
20877
+ ...AttachmentFields,
20929
20878
  state: literal("missing"),
20930
20879
  reason: string()
20931
20880
  }),
20932
20881
  object({
20933
- ...RefFields,
20882
+ ...AttachmentFields,
20934
20883
  state: literal("unsupported"),
20935
20884
  deviceId: number(),
20936
20885
  name: string(),
20937
20886
  reason: string()
20938
20887
  }),
20939
20888
  object({
20940
- ...RefFields,
20889
+ ...AttachmentFields,
20941
20890
  state: literal("unreadable"),
20942
20891
  reason: string()
20943
20892
  })
@@ -20950,17 +20899,49 @@ var CameraSensorAttachmentSchema = discriminatedUnion("state", [
20950
20899
  * say.
20951
20900
  */
20952
20901
  var CameraSensorsNotForwardedSchema = _enum(["onboard-not-listed", "no-active-detection"]);
20902
+ /** Whether the camera's OWN motion counts on its own (D673 C2), from its READY sensors (C3). */
20903
+ var CameraOwnMotionSchema = _enum([
20904
+ "always",
20905
+ "when-confirmed",
20906
+ "never"
20907
+ ]);
20908
+ /** Confirm / Replace cannot suppress this camera's motion: its provider still emits it directly (D673 C13). */
20909
+ var CameraSensorsNotEnforcedSchema = _enum(["provider-not-split"]);
20910
+ /**
20911
+ * The camera's OWN onboard motion (D696): the raw input the bridge combines,
20912
+ * never the effective value. The camera's `motion` slice is the effective one,
20913
+ * so a view of the camera's own row reads this.
20914
+ * - `atMs`: when the bridge received the camera's last own edge.
20915
+ * - `detected`: evaluated WHEN THE STATUS IS ASKED — the last edge said `true`
20916
+ * AND it is younger than the window the bridge counts the camera's own motion
20917
+ * for (`motionCooldownMs`, floored at two sustain ticks). A camera that never
20918
+ * sends a clear (heartbeats only) therefore reads `false` once no push came
20919
+ * within the window; a status read is a snapshot, so a live view re-asks.
20920
+ * Absent = this orchestrator has not received the camera's own motion since it
20921
+ * started (unknown, never "quiet"), or an orchestrator older than D696.
20922
+ */
20923
+ var CameraRawLevelSchema = object({
20924
+ detected: boolean(),
20925
+ atMs: number()
20926
+ });
20953
20927
  var CameraSensorsStatusSchema = discriminatedUnion("state", [
20954
- object({ state: literal("not-configured") }),
20928
+ object({
20929
+ state: literal("not-configured"),
20930
+ cameraLevel: CameraRawLevelSchema.optional()
20931
+ }),
20955
20932
  object({
20956
20933
  state: literal("unreadable"),
20957
- reason: string()
20934
+ reason: string(),
20935
+ cameraLevel: CameraRawLevelSchema.optional()
20958
20936
  }),
20959
20937
  object({
20960
20938
  state: literal("configured"),
20961
- mode: CameraSensorsModeSchema,
20939
+ cameraLevel: CameraRawLevelSchema.optional(),
20962
20940
  sensors: array(CameraSensorAttachmentSchema).readonly(),
20963
- notForwarded: CameraSensorsNotForwardedSchema.optional()
20941
+ /** Absent = an orchestrator older than CS-2: it does not say (D315). */
20942
+ cameraMotion: CameraOwnMotionSchema.optional(),
20943
+ notForwarded: CameraSensorsNotForwardedSchema.optional(),
20944
+ notEnforced: CameraSensorsNotEnforcedSchema.optional()
20964
20945
  })
20965
20946
  ]);
20966
20947
  Object.freeze({
@@ -21645,14 +21626,14 @@ var TrackSchema = object({
21645
21626
  * `derive-returned-null tile=standin`,
21646
21627
  * `native-tile tile=native no-key-frame-at-close`, …) written at close and
21647
21628
  * CLEARED by the late-keyFrame upgrade when a native tile lands after all.
21648
- * The operator-facing answer to "perché manca l'immagine?" on a track whose
21629
+ * The operator-facing answer to "perché manca l'immagine?" [why is the image missing?] on a track whose
21649
21630
  * tile is a face/plate stand-in, a raster crop, or an icon.
21650
21631
  *
21651
21632
  * **`no-key-frame-at-close` (D400).** The line used to be written ONLY when
21652
21633
  * the TILE ranked below native, so a track whose thumbnail landed natively
21653
21634
  * while its key frame missed carried no reason at all — three of the four
21654
21635
  * `MISSING_KEYFRAME` tracks in the 2026-09-07 operator audit were exactly
21655
- * that shape, and their "niente ultimo" had no cause anywhere on the row.
21636
+ * that shape, and their "niente ultimo" [no last frame] had no cause anywhere on the row.
21656
21637
  * The key frame is the head of a cascade (`keyFrame ⇒ keyFrameSmall ⇒ the
21657
21638
  * lastFrame copy source`), so its absence is now on this line whatever the
21658
21639
  * tile ended up being.
@@ -21739,7 +21720,7 @@ var MotionEventSchema = object({
21739
21720
  /**
21740
21721
  * Ms offsets from `timestamp` (the episode's own first rising edge, so the
21741
21722
  * first entry is always `0`) of every genuine off→on transition the
21742
- * episode saw — "ogni evento on si deve salvare" (D475). NOT one entry per
21723
+ * episode saw — "ogni evento on si deve salvare" [every ON event must be saved] (D475). NOT one entry per
21743
21724
  * push: a firmware source that keepalives at ~1 Hz for the whole burst
21744
21725
  * (Reolink, Hikvision) produces exactly one edge; a source that reports an
21745
21726
  * explicit `false` mid-episode and then resumes before the quiet window
@@ -22263,6 +22244,7 @@ var KeyEventSchema = object({
22263
22244
  bestEventId: string(),
22264
22245
  /** Track lifetime in ms (lastSeen - firstSeen). */
22265
22246
  windowMs: number().optional(),
22247
+ audioLabels: array(TrackAudioLabelSchema).readonly().optional(),
22266
22248
  ...TrackFlagFields,
22267
22249
  ...TrackRetrainFields
22268
22250
  });
@@ -24191,8 +24173,10 @@ var RunnerCameraConfigSchema = object({
24191
24173
  * - `analyzer`: ML/frame-diff motion detection (motion-wasm or other
24192
24174
  * analyzer providers) running on decoded frames in this runner.
24193
24175
  * - `onboard`: camera-native motion pushes (Reolink Baichuan, ONVIF
24194
- * analytics). The provider emits ProviderMotion
24195
- * events; the orchestrator forwards to `reportMotion`.
24176
+ * analytics). The provider emits its raw push as `ProviderMotion`
24177
+ * (D673); the orchestrator's camera-sensors bridge re-emits the camera's
24178
+ * effective motion as `MotionOnMotionChanged`, which is what reaches
24179
+ * `reportMotion`.
24196
24180
  */
24197
24181
  motionSources: MotionSourcesSchema.default(["analyzer"]),
24198
24182
  /**
@@ -24369,7 +24353,15 @@ var RunnerLocalLoadSchema = object({
24369
24353
  hasGpu: boolean(),
24370
24354
  inferenceBackend: string().optional(),
24371
24355
  cpuCores: number().optional()
24372
- })
24356
+ }),
24357
+ /**
24358
+ * Who writes a camera's `motion` runtime slice (D696). `'orchestrator'`: this
24359
+ * runner never writes it. ABSENT = a runner older than D696, which still
24360
+ * writes the slice from its phase machine; the orchestrator does not write
24361
+ * while any runner node is absent-or-unanswered, so one slice never has two
24362
+ * writers.
24363
+ */
24364
+ motionSliceWriter: literal("orchestrator").optional()
24373
24365
  });
24374
24366
  /**
24375
24367
  * Aggregate runtime metrics for the runner's whole local pool. Mirrors the
@@ -27182,7 +27174,7 @@ var ClipPlaybackSchema = object({
27182
27174
  * **One authorised yes is one wake.** `next-natural` — take the clip the next
27183
27175
  * time the camera is awake for its own reasons — is deliberately not a member:
27184
27176
  * it was proposed, it is free on the battery, and the operator declined it on
27185
- * 2026-09-20 (*"Quando un export viene richiesto si sveglia la camera."*,
27177
+ * 2026-09-20 (*"Quando un export viene richiesto si sveglia la camera."* [When an export is requested the camera wakes up],
27186
27178
  * D558 "Considered and not taken").
27187
27179
  */
27188
27180
  var ClipWakeSchema = _enum(["authorised"]);
@@ -27443,7 +27435,7 @@ DeviceType.Camera, method(object({
27443
27435
  * It replaced `sources?: string[]`, a VIEW filter over source ids that
27444
27436
  * assumed the answer was a fan-out over everything a camera has. The
27445
27437
  * operator settled otherwise on 2026-09-20 — *"l'utilizzatore è uno
27446
- * solo"* — so the list is asked of one provider at a time and there is
27438
+ * solo"* [there is only one user] — so the list is asked of one provider at a time and there is
27447
27439
  * nothing to filter out of it.
27448
27440
  */
27449
27441
  provider: string().min(1)
@@ -30038,6 +30030,70 @@ onStatusChanged: { data: object({
30038
30030
  * whether persisting is worth a SQLite commit. */
30039
30031
  volatileStateFields: ["lastChangedAt"]
30040
30032
  };
30033
+ var DoorbellStatusSchema = object({
30034
+ /** Ms epoch of the last press. null = never observed since this provider started. */
30035
+ lastPressedAt: number().nullable(),
30036
+ /** Counter since provider start. Resets on reboot. Useful for metrics/debug. */
30037
+ pressCountSinceStart: number()
30038
+ });
30039
+ var DoorbellPressEventSchema = object({
30040
+ deviceId: number(),
30041
+ timestamp: number()
30042
+ });
30043
+ /**
30044
+ * Doorbell button cap. Two kinds of provider serve it, and to every consumer
30045
+ * they are the same cap:
30046
+ *
30047
+ * - **Native** providers, registered per device by a driver addon through
30048
+ * `ctx.registerNativeCap` — a `DeviceType.Button` accessory with
30049
+ * `role: DeviceRole.Doorbell`, or the camera itself (Reolink registers at
30050
+ * camera level). They emit `onPressed` on every firmware ring.
30051
+ * - **A composed doorbell** (D670, D671): a camera's customization gives it
30052
+ * the cap, its `lastPressedAt` rising from the sources the operator
30053
+ * assigned in Customize → Doorbell, and the composer emits `onPressed`
30054
+ * from that field's advance (`fromState`).
30055
+ *
30056
+ * The DeviceEventPropagator re-emits `onPressed` on the camera parent.
30057
+ */
30058
+ var doorbellCapability = {
30059
+ name: "doorbell",
30060
+ scope: "device",
30061
+ deviceNative: true,
30062
+ mode: "singleton",
30063
+ deviceTypes: [DeviceType.Button, DeviceType.Camera],
30064
+ methods: {},
30065
+ events: {
30066
+ /**
30067
+ * Fires once per physical press. Reolink delivers via Baichuan
30068
+ * push (`ReolinkSimpleEvent.type === 'doorbell'`). There is no
30069
+ * release/duration — it's a pulse.
30070
+ */
30071
+ onPressed: {
30072
+ data: DoorbellPressEventSchema,
30073
+ fromState: {
30074
+ field: "lastPressedAt",
30075
+ on: "advance"
30076
+ }
30077
+ } },
30078
+ status: {
30079
+ schema: DoorbellStatusSchema,
30080
+ kind: "push"
30081
+ },
30082
+ /**
30083
+ * Runtime-state slice — last press timestamp + lifetime press count.
30084
+ * Mirrored by the kernel and readable via
30085
+ * `device.state.doorbell.value`. UIs can show "last ring 5m ago"
30086
+ * without subscribing.
30087
+ */
30088
+ runtimeState: DoorbellStatusSchema,
30089
+ /**
30090
+ * Runtime-state durability: **restored** — a monotonic accumulator: the slice IS the record. `lastPressedAt` is content here, not a clock, so it is deliberately NOT volatile.
30091
+ *
30092
+ * See `RuntimeStateDurability`. Enforced by
30093
+ * `scripts/check-runtime-state-durability.ts`.
30094
+ */
30095
+ durability: "restored"
30096
+ };
30041
30097
  /**
30042
30098
  * Enum-state sensor — a string value picked from a finite option set.
30043
30099
  * Drives HA `sensor` entries with `state_class: enum` (HVAC action
@@ -32182,9 +32238,9 @@ var MotionStatusSchema = object({
32182
32238
  /** Ms epoch of the last detected-true observation. Null if never detected. */
32183
32239
  lastDetectedAt: number().nullable(),
32184
32240
  /**
32185
- * `MOTION_CLOSE_AFTER_MS` while `detected: true` on a `Camera` device,
32186
- * `null` while false and on every `Sensor` device (D475) — see that
32187
- * constant's doc for the one-authority rule.
32241
+ * `MOTION_CLOSE_AFTER_MS` while `detected: true` on a `Camera` device (the
32242
+ * orchestrator writes it, D696), `null` while false and on every `Sensor`
32243
+ * device (D475) — see that constant's doc for the one-authority rule.
32188
32244
  *
32189
32245
  * ## Reading this field still arms nothing
32190
32246
  *
@@ -32202,34 +32258,31 @@ var MotionStatusSchema = object({
32202
32258
  * `addon-export-alexa/src/motion-clear-hold.ts` and
32203
32259
  * `addon-export-hap`'s `RESET_DEBOUNCE_MS` both do.
32204
32260
  *
32205
- * ## Who writes it
32206
- *
32207
- * - **Cameras** — the runner's phase machine, `active → watching` on
32208
- * `cooldown_expired`, which then writes this slice with
32209
- * `detected: false` (`handlePhaseChanged` in
32210
- * `pipeline-runner/index.ts`). It produces the FALLING edge, which
32211
- * matters most for the sources that only ever push a rising one:
32212
- * Reolink emits `MotionOnMotionChanged { detected: true }` and never
32213
- * a false.
32214
- * - **Sensors** (Home Assistant binary sensors, Homematic) — the
32215
- * provider pushes the false itself, from the upstream system's own
32216
- * state change. No phase machine is involved.
32217
- *
32218
- * ### The phase machine is CANONICAL, not sole — and that is a defect
32219
- *
32220
- * An earlier revision of this docblock (mine, 2026-09-12) claimed the
32221
- * phase machine is the sole writer for a camera. It is not.
32222
- * `hikvision-camera.ts:3464` and `amcrest-camera.ts:445` both call
32223
- * `setCapSlice(motionCapability, …)` on their own rising edge, and
32224
- * Hikvision's comment says why: it read THIS docblock, agreed the
32225
- * runner is canonical, and wrote anyway to avoid per-tick churn. So
32226
- * two authorities can disagree about one slice, which this repo
32227
- * forbids, and the doc said otherwise — which is worse than saying
32228
- * nothing, because it reads as verification.
32229
- *
32230
- * This predates D475 and is not fixed there: the fix touches every
32231
- * camera provider. Recorded in D475's Consequences. Do not restore the
32232
- * "sole writer" wording without also removing the other writers.
32261
+ * ## Who writes it (D696)
32262
+ *
32263
+ * - **Cameras** — the orchestrator, and nothing else. It writes the camera's
32264
+ * EFFECTIVE motion (`addon-pipeline-orchestrator`
32265
+ * `camera-sensors/motion-slice.ts`), alongside the effective
32266
+ * `MotionOnMotionChanged` it emits or receives: the camera-sensors bridge
32267
+ * for a split camera, an unsplit emitter's direct event, the analyzer and
32268
+ * device activity, as the camera's `motionSources` counts them. A source
32269
+ * that never sends a clear falls one window after its last `true`.
32270
+ * `lastDetectedAt` moves only on an effective rise. No camera provider
32271
+ * writes this slice (not even a boot seed), and neither does the runner's
32272
+ * phase machine: its phase is "a session is attached" for every on-motion
32273
+ * session, not motion, and it now has its own `DetectionPhaseTransition`.
32274
+ * A provider's `isDetected` answers from the hub's slice.
32275
+ * - **Sensors** (Home Assistant binary sensors, Homematic, Matter, Alexa
32276
+ * imports) — the provider pushes both edges itself, from the upstream
32277
+ * system's own state change. That is the sensor's own fact.
32278
+ *
32279
+ * `scripts/check-onboard-motion-emitters.ts` refuses any other writer of a
32280
+ * `motion` slice; each sensor writer is a named exemption.
32281
+ *
32282
+ * This replaces the D475 §4 rule ("the phase machine is the sole writer").
32283
+ * That rule was never true: Hikvision and Amcrest wrote the slice raw beside
32284
+ * it, every provider seeded it at boot, and every session left it
32285
+ * `detected: true` after its detach.
32233
32286
  */
32234
32287
  autoClearAfterMs: number().nullable()
32235
32288
  });
@@ -32301,11 +32354,12 @@ onMotionChanged: { data: MotionOnMotionChangedDataSchema } },
32301
32354
  */
32302
32355
  runtimeState: MotionStatusSchema,
32303
32356
  /**
32304
- * Runtime-state durability: **session** — every writer of this slice
32357
+ * Runtime-state durability: **session** — the writer of this slice
32305
32358
  * writes only on an EDGE, so a restored `detected: true` would stay
32306
32359
  * frozen until the next one instead of being corrected. The next edge
32307
- * re-publishes the real state. (On who the writers are, and why there
32308
- * is more than one, see `autoClearAfterMs` above.)
32360
+ * re-publishes the real state, and the orchestrator re-publishes every
32361
+ * camera when it starts writing (D696; on who writes it, see
32362
+ * `autoClearAfterMs` above).
32309
32363
  *
32310
32364
  * See `RuntimeStateDurability`. Enforced by
32311
32365
  * `scripts/check-runtime-state-durability.ts`.
@@ -34688,8 +34742,7 @@ var ptzAutotrackCapability = {
34688
34742
  deviceNative: true,
34689
34743
  mode: "singleton",
34690
34744
  /**
34691
- * Two kinds of provider behind one name, the same shape `snapshot` and
34692
- * `doorbell` use:
34745
+ * Two kinds of provider behind one name, the same shape `snapshot` uses:
34693
34746
  *
34694
34747
  * - **Native**: the camera's own firmware autotrack, registered per device by
34695
34748
  * the driver when the probe says it exists (Reolink: yes; Hikvision:
@@ -34697,7 +34750,7 @@ var ptzAutotrackCapability = {
34697
34750
  * - **Wrapper**: the emulated implementation (`@camstack/system`'s `autotrack` builtin),
34698
34751
  * which follows a subject with `ptz.move` pulses driven by the detection
34699
34752
  * pipeline. `defaultActive: false` — the operator binds it per camera in
34700
- * the bindings UI, exactly as `virtual-doorbell` is bound.
34753
+ * the bindings UI.
34701
34754
  *
34702
34755
  * The binding chooses WHICH implementation answers; `setEnabled` stays the
34703
34756
  * one switch for the function either way. A camera never has both driving its
@@ -35372,7 +35425,7 @@ var ReadGopBytesResultSchema = object({
35372
35425
  /**
35373
35426
  * A time WINDOW of one finalized segment, cut by byte range — the multi-GOP
35374
35427
  * twin of {@link ReadGopBytesResultSchema}'s single instant. Built for the
35375
- * replay clip's `recording` source (`docs/design/plans/2026-08-26-replay-clip-su-pipeline.md`):
35428
+ * replay clip's `recording` source (`docs/design/plans/2026-08-26-clip-replay-on-pipeline.md`):
35376
35429
  * a replay needs several seconds of native pixels, not one frame.
35377
35430
  *
35378
35431
  * `ok.data` is standalone-demuxable, same as a GOP read. `ok.reachesRequestedEnd`
@@ -38736,6 +38789,7 @@ var zoneRulesCapability = {
38736
38789
  */
38737
38790
  durability: "restored"
38738
38791
  };
38792
+ SOURCE_CAPS.filter((cap) => cap !== "switch" && cap !== "motion");
38739
38793
  /**
38740
38794
  * Accessory device helpers — shared across drivers.
38741
38795
  *
@@ -44761,6 +44815,12 @@ Object.freeze({
44761
44815
  addonId: null,
44762
44816
  access: "view"
44763
44817
  },
44818
+ "notificationRules.getAlarmSensors": {
44819
+ capName: "notification-rules",
44820
+ capScope: "system",
44821
+ addonId: null,
44822
+ access: "view"
44823
+ },
44764
44824
  "notificationRules.getClipRetentionAsks": {
44765
44825
  capName: "notification-rules",
44766
44826
  capScope: "system",
@@ -48339,6 +48399,11 @@ Object.freeze({
48339
48399
  }
48340
48400
  });
48341
48401
  Object.freeze({
48402
+ "accessories.getStatus": [{
48403
+ name: "deviceId",
48404
+ form: "single",
48405
+ optional: false
48406
+ }],
48342
48407
  "accessories.setChildHidden": [{
48343
48408
  name: "childDeviceId",
48344
48409
  form: "single",
@@ -48358,6 +48423,11 @@ Object.freeze({
48358
48423
  form: "single",
48359
48424
  optional: false
48360
48425
  }],
48426
+ "airQualitySensor.getStatus": [{
48427
+ name: "deviceId",
48428
+ form: "single",
48429
+ optional: false
48430
+ }],
48361
48431
  "alarmPanel.arm": [{
48362
48432
  name: "deviceId",
48363
48433
  form: "single",
@@ -48368,11 +48438,36 @@ Object.freeze({
48368
48438
  form: "single",
48369
48439
  optional: false
48370
48440
  }],
48441
+ "alarmPanel.getStatus": [{
48442
+ name: "deviceId",
48443
+ form: "single",
48444
+ optional: false
48445
+ }],
48371
48446
  "alarmPanel.trigger": [{
48372
48447
  name: "deviceId",
48373
48448
  form: "single",
48374
48449
  optional: false
48375
48450
  }],
48451
+ "ambientLightSensor.getStatus": [{
48452
+ name: "deviceId",
48453
+ form: "single",
48454
+ optional: false
48455
+ }],
48456
+ "audioAnalysis.applyDeviceSettingsPatch": [{
48457
+ name: "deviceId",
48458
+ form: "single",
48459
+ optional: false
48460
+ }],
48461
+ "audioAnalysis.getDeviceLiveContribution": [{
48462
+ name: "deviceId",
48463
+ form: "single",
48464
+ optional: false
48465
+ }],
48466
+ "audioAnalysis.getDeviceSettingsContribution": [{
48467
+ name: "deviceId",
48468
+ form: "single",
48469
+ optional: false
48470
+ }],
48376
48471
  "audioAnalysis.resolveDeviceSettings": [{
48377
48472
  name: "deviceId",
48378
48473
  form: "single",
@@ -48413,16 +48508,36 @@ Object.freeze({
48413
48508
  form: "single",
48414
48509
  optional: false
48415
48510
  }],
48511
+ "automationControl.getStatus": [{
48512
+ name: "deviceId",
48513
+ form: "single",
48514
+ optional: false
48515
+ }],
48416
48516
  "automationControl.trigger": [{
48417
48517
  name: "deviceId",
48418
48518
  form: "single",
48419
48519
  optional: false
48420
48520
  }],
48521
+ "battery.getStatus": [{
48522
+ name: "deviceId",
48523
+ form: "single",
48524
+ optional: false
48525
+ }],
48421
48526
  "battery.wakeForStream": [{
48422
48527
  name: "deviceId",
48423
48528
  form: "single",
48424
48529
  optional: false
48425
48530
  }],
48531
+ "binary.getStatus": [{
48532
+ name: "deviceId",
48533
+ form: "single",
48534
+ optional: false
48535
+ }],
48536
+ "brightness.getStatus": [{
48537
+ name: "deviceId",
48538
+ form: "single",
48539
+ optional: false
48540
+ }],
48426
48541
  "brightness.setBrightness": [{
48427
48542
  name: "deviceId",
48428
48543
  form: "single",
@@ -48438,6 +48553,26 @@ Object.freeze({
48438
48553
  form: "single",
48439
48554
  optional: false
48440
48555
  }],
48556
+ "cameraCredentials.getStatus": [{
48557
+ name: "deviceId",
48558
+ form: "single",
48559
+ optional: false
48560
+ }],
48561
+ "cameraGridLayout.applyDeviceSettingsPatch": [{
48562
+ name: "deviceId",
48563
+ form: "single",
48564
+ optional: false
48565
+ }],
48566
+ "cameraGridLayout.getDeviceLiveContribution": [{
48567
+ name: "deviceId",
48568
+ form: "single",
48569
+ optional: false
48570
+ }],
48571
+ "cameraGridLayout.getDeviceSettingsContribution": [{
48572
+ name: "deviceId",
48573
+ form: "single",
48574
+ optional: false
48575
+ }],
48441
48576
  "cameraGridLayout.getLayout": [{
48442
48577
  name: "deviceId",
48443
48578
  form: "single",
@@ -48453,6 +48588,21 @@ Object.freeze({
48453
48588
  form: "single",
48454
48589
  optional: false
48455
48590
  }],
48591
+ "cameraPipelineConfig.applyDeviceSettingsPatch": [{
48592
+ name: "deviceId",
48593
+ form: "single",
48594
+ optional: false
48595
+ }],
48596
+ "cameraPipelineConfig.getDeviceLiveContribution": [{
48597
+ name: "deviceId",
48598
+ form: "single",
48599
+ optional: false
48600
+ }],
48601
+ "cameraPipelineConfig.getDeviceSettingsContribution": [{
48602
+ name: "deviceId",
48603
+ form: "single",
48604
+ optional: false
48605
+ }],
48456
48606
  "cameraStreams.getBrokerStreams": [{
48457
48607
  name: "deviceId",
48458
48608
  form: "single",
@@ -48478,6 +48628,16 @@ Object.freeze({
48478
48628
  form: "single",
48479
48629
  optional: false
48480
48630
  }],
48631
+ "carbonMonoxide.getStatus": [{
48632
+ name: "deviceId",
48633
+ form: "single",
48634
+ optional: false
48635
+ }],
48636
+ "climateControl.getStatus": [{
48637
+ name: "deviceId",
48638
+ form: "single",
48639
+ optional: false
48640
+ }],
48481
48641
  "climateControl.setFanMode": [{
48482
48642
  name: "deviceId",
48483
48643
  form: "single",
@@ -48518,16 +48678,41 @@ Object.freeze({
48518
48678
  form: "single",
48519
48679
  optional: false
48520
48680
  }],
48681
+ "color.getStatus": [{
48682
+ name: "deviceId",
48683
+ form: "single",
48684
+ optional: false
48685
+ }],
48521
48686
  "color.setColor": [{
48522
48687
  name: "deviceId",
48523
48688
  form: "single",
48524
48689
  optional: false
48525
48690
  }],
48691
+ "connectivity.getStatus": [{
48692
+ name: "deviceId",
48693
+ form: "single",
48694
+ optional: false
48695
+ }],
48696
+ "consumables.getStatus": [{
48697
+ name: "deviceId",
48698
+ form: "single",
48699
+ optional: false
48700
+ }],
48526
48701
  "consumables.reset": [{
48527
48702
  name: "deviceId",
48528
48703
  form: "single",
48529
48704
  optional: false
48530
48705
  }],
48706
+ "contact.getStatus": [{
48707
+ name: "deviceId",
48708
+ form: "single",
48709
+ optional: false
48710
+ }],
48711
+ "control.getStatus": [{
48712
+ name: "deviceId",
48713
+ form: "single",
48714
+ optional: false
48715
+ }],
48531
48716
  "control.setValue": [{
48532
48717
  name: "deviceId",
48533
48718
  form: "single",
@@ -48538,6 +48723,11 @@ Object.freeze({
48538
48723
  form: "single",
48539
48724
  optional: false
48540
48725
  }],
48726
+ "cover.getStatus": [{
48727
+ name: "deviceId",
48728
+ form: "single",
48729
+ optional: false
48730
+ }],
48541
48731
  "cover.open": [{
48542
48732
  name: "deviceId",
48543
48733
  form: "single",
@@ -48563,6 +48753,11 @@ Object.freeze({
48563
48753
  form: "single",
48564
48754
  optional: false
48565
48755
  }],
48756
+ "dayNight.getStatus": [{
48757
+ name: "deviceId",
48758
+ form: "single",
48759
+ optional: false
48760
+ }],
48566
48761
  "dayNight.setSettings": [{
48567
48762
  name: "deviceId",
48568
48763
  form: "single",
@@ -48573,11 +48768,31 @@ Object.freeze({
48573
48768
  form: "single",
48574
48769
  optional: true
48575
48770
  }],
48771
+ "detectionPipeline.applyDeviceSettingsPatch": [{
48772
+ name: "deviceId",
48773
+ form: "single",
48774
+ optional: false
48775
+ }],
48776
+ "detectionPipeline.getDeviceLiveContribution": [{
48777
+ name: "deviceId",
48778
+ form: "single",
48779
+ optional: false
48780
+ }],
48781
+ "detectionPipeline.getDeviceSettingsContribution": [{
48782
+ name: "deviceId",
48783
+ form: "single",
48784
+ optional: false
48785
+ }],
48576
48786
  "deviceAdminLink.getAdminLink": [{
48577
48787
  name: "deviceId",
48578
48788
  form: "single",
48579
48789
  optional: false
48580
48790
  }],
48791
+ "deviceAdoption.getStatus": [{
48792
+ name: "deviceId",
48793
+ form: "single",
48794
+ optional: false
48795
+ }],
48581
48796
  "deviceAdoption.release": [{
48582
48797
  name: "camDeviceId",
48583
48798
  form: "single",
@@ -48593,6 +48808,11 @@ Object.freeze({
48593
48808
  form: "single",
48594
48809
  optional: false
48595
48810
  }],
48811
+ "deviceDiscovery.getStatus": [{
48812
+ name: "deviceId",
48813
+ form: "single",
48814
+ optional: false
48815
+ }],
48596
48816
  "deviceDiscovery.listDiscovered": [{
48597
48817
  name: "deviceId",
48598
48818
  form: "single",
@@ -48612,6 +48832,21 @@ Object.freeze({
48612
48832
  form: "single",
48613
48833
  optional: false
48614
48834
  }],
48835
+ "deviceExport.applyDeviceSettingsPatch": [{
48836
+ name: "deviceId",
48837
+ form: "single",
48838
+ optional: false
48839
+ }],
48840
+ "deviceExport.getDeviceLiveContribution": [{
48841
+ name: "deviceId",
48842
+ form: "single",
48843
+ optional: false
48844
+ }],
48845
+ "deviceExport.getDeviceSettingsContribution": [{
48846
+ name: "deviceId",
48847
+ form: "single",
48848
+ optional: false
48849
+ }],
48615
48850
  "deviceExtension.listCandidates": [{
48616
48851
  name: "deviceId",
48617
48852
  form: "single",
@@ -48960,6 +49195,26 @@ Object.freeze({
48960
49195
  form: "single",
48961
49196
  optional: false
48962
49197
  }],
49198
+ "deviceStatus.getStatus": [{
49199
+ name: "deviceId",
49200
+ form: "single",
49201
+ optional: false
49202
+ }],
49203
+ "doorbell.getStatus": [{
49204
+ name: "deviceId",
49205
+ form: "single",
49206
+ optional: false
49207
+ }],
49208
+ "enumSensor.getStatus": [{
49209
+ name: "deviceId",
49210
+ form: "single",
49211
+ optional: false
49212
+ }],
49213
+ "eventEmitter.getStatus": [{
49214
+ name: "deviceId",
49215
+ form: "single",
49216
+ optional: false
49217
+ }],
48963
49218
  "faceGallery.getFaceByTrack": [{
48964
49219
  name: "deviceId",
48965
49220
  form: "single",
@@ -48974,6 +49229,11 @@ Object.freeze({
48974
49229
  form: "array",
48975
49230
  optional: true
48976
49231
  }],
49232
+ "fanControl.getStatus": [{
49233
+ name: "deviceId",
49234
+ form: "single",
49235
+ optional: false
49236
+ }],
48977
49237
  "fanControl.setDirection": [{
48978
49238
  name: "deviceId",
48979
49239
  form: "single",
@@ -48994,6 +49254,26 @@ Object.freeze({
48994
49254
  form: "single",
48995
49255
  optional: false
48996
49256
  }],
49257
+ "featureProbe.getStatus": [{
49258
+ name: "deviceId",
49259
+ form: "single",
49260
+ optional: false
49261
+ }],
49262
+ "flood.getStatus": [{
49263
+ name: "deviceId",
49264
+ form: "single",
49265
+ optional: false
49266
+ }],
49267
+ "gas.getStatus": [{
49268
+ name: "deviceId",
49269
+ form: "single",
49270
+ optional: false
49271
+ }],
49272
+ "humidifier.getStatus": [{
49273
+ name: "deviceId",
49274
+ form: "single",
49275
+ optional: false
49276
+ }],
48997
49277
  "humidifier.setMode": [{
48998
49278
  name: "deviceId",
48999
49279
  form: "single",
@@ -49009,11 +49289,26 @@ Object.freeze({
49009
49289
  form: "single",
49010
49290
  optional: false
49011
49291
  }],
49292
+ "humiditySensor.getStatus": [{
49293
+ name: "deviceId",
49294
+ form: "single",
49295
+ optional: false
49296
+ }],
49297
+ "image.getStatus": [{
49298
+ name: "deviceId",
49299
+ form: "single",
49300
+ optional: false
49301
+ }],
49012
49302
  "imageSettings.getOptions": [{
49013
49303
  name: "deviceId",
49014
49304
  form: "single",
49015
49305
  optional: false
49016
49306
  }],
49307
+ "imageSettings.getStatus": [{
49308
+ name: "deviceId",
49309
+ form: "single",
49310
+ optional: false
49311
+ }],
49017
49312
  "imageSettings.setSettings": [{
49018
49313
  name: "deviceId",
49019
49314
  form: "single",
@@ -49024,6 +49319,11 @@ Object.freeze({
49024
49319
  form: "single",
49025
49320
  optional: false
49026
49321
  }],
49322
+ "intercom.getStatus": [{
49323
+ name: "deviceId",
49324
+ form: "single",
49325
+ optional: false
49326
+ }],
49027
49327
  "intercom.handleAnswer": [{
49028
49328
  name: "deviceId",
49029
49329
  form: "single",
@@ -49054,6 +49354,11 @@ Object.freeze({
49054
49354
  form: "single",
49055
49355
  optional: false
49056
49356
  }],
49357
+ "lawnMowerControl.getStatus": [{
49358
+ name: "deviceId",
49359
+ form: "single",
49360
+ optional: false
49361
+ }],
49057
49362
  "lawnMowerControl.pause": [{
49058
49363
  name: "deviceId",
49059
49364
  form: "single",
@@ -49064,6 +49369,11 @@ Object.freeze({
49064
49369
  form: "single",
49065
49370
  optional: false
49066
49371
  }],
49372
+ "lockControl.getStatus": [{
49373
+ name: "deviceId",
49374
+ form: "single",
49375
+ optional: false
49376
+ }],
49067
49377
  "lockControl.lock": [{
49068
49378
  name: "deviceId",
49069
49379
  form: "single",
@@ -49079,6 +49389,11 @@ Object.freeze({
49079
49389
  form: "single",
49080
49390
  optional: false
49081
49391
  }],
49392
+ "mediaPlayer.getStatus": [{
49393
+ name: "deviceId",
49394
+ form: "single",
49395
+ optional: false
49396
+ }],
49082
49397
  "mediaPlayer.next": [{
49083
49398
  name: "deviceId",
49084
49399
  form: "single",
@@ -49139,6 +49454,11 @@ Object.freeze({
49139
49454
  form: "single",
49140
49455
  optional: false
49141
49456
  }],
49457
+ "motion.getStatus": [{
49458
+ name: "deviceId",
49459
+ form: "single",
49460
+ optional: false
49461
+ }],
49142
49462
  "motion.isDetected": [{
49143
49463
  name: "deviceId",
49144
49464
  form: "single",
@@ -49149,11 +49469,31 @@ Object.freeze({
49149
49469
  form: "single",
49150
49470
  optional: false
49151
49471
  }],
49472
+ "motionDetection.applyDeviceSettingsPatch": [{
49473
+ name: "deviceId",
49474
+ form: "single",
49475
+ optional: false
49476
+ }],
49477
+ "motionDetection.getDeviceLiveContribution": [{
49478
+ name: "deviceId",
49479
+ form: "single",
49480
+ optional: false
49481
+ }],
49482
+ "motionDetection.getDeviceSettingsContribution": [{
49483
+ name: "deviceId",
49484
+ form: "single",
49485
+ optional: false
49486
+ }],
49152
49487
  "motionDetection.removeCamera": [{
49153
49488
  name: "deviceId",
49154
49489
  form: "single",
49155
49490
  optional: false
49156
49491
  }],
49492
+ "motionTrigger.getStatus": [{
49493
+ name: "deviceId",
49494
+ form: "single",
49495
+ optional: false
49496
+ }],
49157
49497
  "motionTrigger.setMotionTrigger": [{
49158
49498
  name: "deviceId",
49159
49499
  form: "single",
@@ -49164,6 +49504,11 @@ Object.freeze({
49164
49504
  form: "single",
49165
49505
  optional: false
49166
49506
  }],
49507
+ "motionZones.getStatus": [{
49508
+ name: "deviceId",
49509
+ form: "single",
49510
+ optional: false
49511
+ }],
49167
49512
  "motionZones.setZone": [{
49168
49513
  name: "deviceId",
49169
49514
  form: "single",
@@ -49174,6 +49519,11 @@ Object.freeze({
49174
49519
  form: "single",
49175
49520
  optional: false
49176
49521
  }],
49522
+ "nativeObjectDetection.getStatus": [{
49523
+ name: "deviceId",
49524
+ form: "single",
49525
+ optional: false
49526
+ }],
49177
49527
  "nativeObjectDetection.setEnabled": [{
49178
49528
  name: "deviceId",
49179
49529
  form: "single",
@@ -49189,6 +49539,11 @@ Object.freeze({
49189
49539
  form: "single",
49190
49540
  optional: false
49191
49541
  }],
49542
+ "navigation.getStatus": [{
49543
+ name: "deviceId",
49544
+ form: "single",
49545
+ optional: false
49546
+ }],
49192
49547
  "navigation.goToPoint": [{
49193
49548
  name: "deviceId",
49194
49549
  form: "single",
@@ -49234,6 +49589,11 @@ Object.freeze({
49234
49589
  form: "single",
49235
49590
  optional: false
49236
49591
  }],
49592
+ "networkLink.getStatus": [{
49593
+ name: "deviceId",
49594
+ form: "single",
49595
+ optional: false
49596
+ }],
49237
49597
  "networkQuality.getDeviceStats": [{
49238
49598
  name: "deviceId",
49239
49599
  form: "single",
@@ -49244,6 +49604,11 @@ Object.freeze({
49244
49604
  form: "single",
49245
49605
  optional: false
49246
49606
  }],
49607
+ "notificationRules.getAlarmSensors": [{
49608
+ name: "deviceIds",
49609
+ form: "array",
49610
+ optional: false
49611
+ }],
49247
49612
  "notificationRules.setDeviceMuted": [{
49248
49613
  name: "deviceId",
49249
49614
  form: "single",
@@ -49254,11 +49619,26 @@ Object.freeze({
49254
49619
  form: "single",
49255
49620
  optional: false
49256
49621
  }],
49622
+ "notifier.getStatus": [{
49623
+ name: "deviceId",
49624
+ form: "single",
49625
+ optional: false
49626
+ }],
49257
49627
  "notifier.send": [{
49258
49628
  name: "deviceId",
49259
49629
  form: "single",
49260
49630
  optional: false
49261
49631
  }],
49632
+ "numericSensor.getStatus": [{
49633
+ name: "deviceId",
49634
+ form: "single",
49635
+ optional: false
49636
+ }],
49637
+ "osd.getStatus": [{
49638
+ name: "deviceId",
49639
+ form: "single",
49640
+ optional: false
49641
+ }],
49262
49642
  "osd.setOverlay": [{
49263
49643
  name: "deviceId",
49264
49644
  form: "single",
@@ -49318,6 +49698,11 @@ Object.freeze({
49318
49698
  form: "single",
49319
49699
  optional: false
49320
49700
  }],
49701
+ "petFeeder.getStatus": [{
49702
+ name: "deviceId",
49703
+ form: "single",
49704
+ optional: false
49705
+ }],
49321
49706
  "petFeeder.markFoodReplenished": [{
49322
49707
  name: "deviceId",
49323
49708
  form: "single",
@@ -49353,6 +49738,11 @@ Object.freeze({
49353
49738
  form: "single",
49354
49739
  optional: false
49355
49740
  }],
49741
+ "pipelineAnalytics.applyDeviceSettingsPatch": [{
49742
+ name: "deviceId",
49743
+ form: "single",
49744
+ optional: false
49745
+ }],
49356
49746
  "pipelineAnalytics.clearTrackRelation": [{
49357
49747
  name: "deviceId",
49358
49748
  form: "single",
@@ -49393,6 +49783,16 @@ Object.freeze({
49393
49783
  form: "single",
49394
49784
  optional: false
49395
49785
  }],
49786
+ "pipelineAnalytics.getDeviceLiveContribution": [{
49787
+ name: "deviceId",
49788
+ form: "single",
49789
+ optional: false
49790
+ }],
49791
+ "pipelineAnalytics.getDeviceSettingsContribution": [{
49792
+ name: "deviceId",
49793
+ form: "single",
49794
+ optional: false
49795
+ }],
49396
49796
  "pipelineAnalytics.getEventDensity": [{
49397
49797
  name: "deviceId",
49398
49798
  form: "single",
@@ -49608,6 +50008,11 @@ Object.freeze({
49608
50008
  form: "single",
49609
50009
  optional: true
49610
50010
  }],
50011
+ "pipelineOrchestrator.applyDeviceSettingsPatch": [{
50012
+ name: "deviceId",
50013
+ form: "single",
50014
+ optional: false
50015
+ }],
49611
50016
  "pipelineOrchestrator.assignAudio": [{
49612
50017
  name: "deviceId",
49613
50018
  form: "single",
@@ -49653,6 +50058,16 @@ Object.freeze({
49653
50058
  form: "single",
49654
50059
  optional: false
49655
50060
  }],
50061
+ "pipelineOrchestrator.getDeviceLiveContribution": [{
50062
+ name: "deviceId",
50063
+ form: "single",
50064
+ optional: false
50065
+ }],
50066
+ "pipelineOrchestrator.getDeviceSettingsContribution": [{
50067
+ name: "deviceId",
50068
+ form: "single",
50069
+ optional: false
50070
+ }],
49656
50071
  "pipelineOrchestrator.getPipelineAssignment": [{
49657
50072
  name: "deviceId",
49658
50073
  form: "single",
@@ -49773,11 +50188,31 @@ Object.freeze({
49773
50188
  form: "single",
49774
50189
  optional: true
49775
50190
  }],
50191
+ "powerMeter.getStatus": [{
50192
+ name: "deviceId",
50193
+ form: "single",
50194
+ optional: false
50195
+ }],
50196
+ "presence.getStatus": [{
50197
+ name: "deviceId",
50198
+ form: "single",
50199
+ optional: false
50200
+ }],
50201
+ "pressureSensor.getStatus": [{
50202
+ name: "deviceId",
50203
+ form: "single",
50204
+ optional: false
50205
+ }],
49776
50206
  "privacyMask.getOptions": [{
49777
50207
  name: "deviceId",
49778
50208
  form: "single",
49779
50209
  optional: false
49780
50210
  }],
50211
+ "privacyMask.getStatus": [{
50212
+ name: "deviceId",
50213
+ form: "single",
50214
+ optional: false
50215
+ }],
49781
50216
  "privacyMask.setAudioEnabled": [{
49782
50217
  name: "deviceId",
49783
50218
  form: "single",
@@ -49828,6 +50263,11 @@ Object.freeze({
49828
50263
  form: "single",
49829
50264
  optional: false
49830
50265
  }],
50266
+ "ptz.getStatus": [{
50267
+ name: "deviceId",
50268
+ form: "single",
50269
+ optional: false
50270
+ }],
49831
50271
  "ptz.goHome": [{
49832
50272
  name: "deviceId",
49833
50273
  form: "single",
@@ -49918,6 +50358,11 @@ Object.freeze({
49918
50358
  form: "single",
49919
50359
  optional: false
49920
50360
  }],
50361
+ "recordingArchive.applyDeviceSettingsPatch": [{
50362
+ name: "deviceId",
50363
+ form: "single",
50364
+ optional: false
50365
+ }],
49921
50366
  "recordingArchive.deleteFootprint": [{
49922
50367
  name: "deviceId",
49923
50368
  form: "single",
@@ -49938,6 +50383,21 @@ Object.freeze({
49938
50383
  form: "single",
49939
50384
  optional: false
49940
50385
  }],
50386
+ "recordingArchive.getDeviceLiveContribution": [{
50387
+ name: "deviceId",
50388
+ form: "single",
50389
+ optional: false
50390
+ }],
50391
+ "recordingArchive.getDeviceSettingsContribution": [{
50392
+ name: "deviceId",
50393
+ form: "single",
50394
+ optional: false
50395
+ }],
50396
+ "recordingArchive.getStatus": [{
50397
+ name: "deviceId",
50398
+ form: "single",
50399
+ optional: false
50400
+ }],
49941
50401
  "recordingArchive.listOpsLog": [{
49942
50402
  name: "deviceId",
49943
50403
  form: "single",
@@ -50023,6 +50483,11 @@ Object.freeze({
50023
50483
  form: "single",
50024
50484
  optional: false
50025
50485
  }],
50486
+ "recordingOnboard.getStatus": [{
50487
+ name: "deviceId",
50488
+ form: "single",
50489
+ optional: false
50490
+ }],
50026
50491
  "recordingOnboard.setSettings": [{
50027
50492
  name: "deviceId",
50028
50493
  form: "single",
@@ -50053,6 +50518,11 @@ Object.freeze({
50053
50518
  form: "single",
50054
50519
  optional: false
50055
50520
  }],
50521
+ "sceneMonitor.getStatus": [{
50522
+ name: "deviceId",
50523
+ form: "single",
50524
+ optional: false
50525
+ }],
50056
50526
  "sceneMonitor.listScenes": [{
50057
50527
  name: "deviceId",
50058
50528
  form: "single",
@@ -50078,6 +50548,11 @@ Object.freeze({
50078
50548
  form: "single",
50079
50549
  optional: false
50080
50550
  }],
50551
+ "scriptRunner.getStatus": [{
50552
+ name: "deviceId",
50553
+ form: "single",
50554
+ optional: false
50555
+ }],
50081
50556
  "scriptRunner.run": [{
50082
50557
  name: "deviceId",
50083
50558
  form: "single",
@@ -50088,11 +50563,31 @@ Object.freeze({
50088
50563
  form: "single",
50089
50564
  optional: false
50090
50565
  }],
50566
+ "smoke.getStatus": [{
50567
+ name: "deviceId",
50568
+ form: "single",
50569
+ optional: false
50570
+ }],
50571
+ "snapshot.applyDeviceSettingsPatch": [{
50572
+ name: "deviceId",
50573
+ form: "single",
50574
+ optional: false
50575
+ }],
50091
50576
  "snapshot.getDebugState": [{
50092
50577
  name: "deviceId",
50093
50578
  form: "single",
50094
50579
  optional: false
50095
50580
  }],
50581
+ "snapshot.getDeviceLiveContribution": [{
50582
+ name: "deviceId",
50583
+ form: "single",
50584
+ optional: false
50585
+ }],
50586
+ "snapshot.getDeviceSettingsContribution": [{
50587
+ name: "deviceId",
50588
+ form: "single",
50589
+ optional: false
50590
+ }],
50096
50591
  "snapshot.getSnapshot": [{
50097
50592
  name: "deviceId",
50098
50593
  form: "single",
@@ -50109,6 +50604,11 @@ Object.freeze({
50109
50604
  form: "array",
50110
50605
  optional: false
50111
50606
  }],
50607
+ "snapshot.getStatus": [{
50608
+ name: "deviceId",
50609
+ form: "single",
50610
+ optional: false
50611
+ }],
50112
50612
  "snapshot.invalidateCache": [{
50113
50613
  name: "deviceId",
50114
50614
  form: "single",
@@ -50119,6 +50619,11 @@ Object.freeze({
50119
50619
  form: "single",
50120
50620
  optional: false
50121
50621
  }],
50622
+ "streamBroker.applyDeviceSettingsPatch": [{
50623
+ name: "deviceId",
50624
+ form: "single",
50625
+ optional: false
50626
+ }],
50122
50627
  "streamBroker.assignProfile": [{
50123
50628
  name: "deviceId",
50124
50629
  form: "single",
@@ -50134,6 +50639,16 @@ Object.freeze({
50134
50639
  form: "single",
50135
50640
  optional: false
50136
50641
  }],
50642
+ "streamBroker.getDeviceLiveContribution": [{
50643
+ name: "deviceId",
50644
+ form: "single",
50645
+ optional: false
50646
+ }],
50647
+ "streamBroker.getDeviceSettingsContribution": [{
50648
+ name: "deviceId",
50649
+ form: "single",
50650
+ optional: false
50651
+ }],
50137
50652
  "streamBroker.getStreamWithCodec": [{
50138
50653
  name: "deviceId",
50139
50654
  form: "single",
@@ -50194,16 +50709,46 @@ Object.freeze({
50194
50709
  form: "single",
50195
50710
  optional: false
50196
50711
  }],
50712
+ "streamParams.getStatus": [{
50713
+ name: "deviceId",
50714
+ form: "single",
50715
+ optional: false
50716
+ }],
50197
50717
  "streamParams.setProfile": [{
50198
50718
  name: "deviceId",
50199
50719
  form: "single",
50200
50720
  optional: false
50201
50721
  }],
50722
+ "switch.getStatus": [{
50723
+ name: "deviceId",
50724
+ form: "single",
50725
+ optional: false
50726
+ }],
50202
50727
  "switch.setState": [{
50203
50728
  name: "deviceId",
50204
50729
  form: "single",
50205
50730
  optional: false
50206
50731
  }],
50732
+ "tamper.getStatus": [{
50733
+ name: "deviceId",
50734
+ form: "single",
50735
+ optional: false
50736
+ }],
50737
+ "temperatureSensor.getStatus": [{
50738
+ name: "deviceId",
50739
+ form: "single",
50740
+ optional: false
50741
+ }],
50742
+ "update.getStatus": [{
50743
+ name: "deviceId",
50744
+ form: "single",
50745
+ optional: false
50746
+ }],
50747
+ "vacuumControl.getStatus": [{
50748
+ name: "deviceId",
50749
+ form: "single",
50750
+ optional: false
50751
+ }],
50207
50752
  "vacuumControl.locate": [{
50208
50753
  name: "deviceId",
50209
50754
  form: "single",
@@ -50239,6 +50784,11 @@ Object.freeze({
50239
50784
  form: "single",
50240
50785
  optional: false
50241
50786
  }],
50787
+ "valve.getStatus": [{
50788
+ name: "deviceId",
50789
+ form: "single",
50790
+ optional: false
50791
+ }],
50242
50792
  "valve.open": [{
50243
50793
  name: "deviceId",
50244
50794
  form: "single",
@@ -50254,6 +50804,11 @@ Object.freeze({
50254
50804
  form: "single",
50255
50805
  optional: false
50256
50806
  }],
50807
+ "vibration.getStatus": [{
50808
+ name: "deviceId",
50809
+ form: "single",
50810
+ optional: false
50811
+ }],
50257
50812
  "videoclips.dialClipStream": [{
50258
50813
  name: "deviceId",
50259
50814
  form: "single",
@@ -50289,6 +50844,11 @@ Object.freeze({
50289
50844
  form: "single",
50290
50845
  optional: false
50291
50846
  }],
50847
+ "waterHeater.getStatus": [{
50848
+ name: "deviceId",
50849
+ form: "single",
50850
+ optional: false
50851
+ }],
50292
50852
  "waterHeater.setAway": [{
50293
50853
  name: "deviceId",
50294
50854
  form: "single",
@@ -50304,6 +50864,11 @@ Object.freeze({
50304
50864
  form: "single",
50305
50865
  optional: false
50306
50866
  }],
50867
+ "weather.getStatus": [{
50868
+ name: "deviceId",
50869
+ form: "single",
50870
+ optional: false
50871
+ }],
50307
50872
  "webrtcSession.addIceCandidate": [{
50308
50873
  name: "deviceId",
50309
50874
  form: "single",
@@ -51041,7 +51606,7 @@ var PreviewTextField = string().max(200);
51041
51606
  * Whether the notification's preview is a STILL or a short animation.
51042
51607
  *
51043
51608
  * The operator's ask, verbatim: *"inviato come gif o video (come per le altre
51044
- * rule)"* — the other rules already offer an animated preview, and a ten-hour
51609
+ * rule)"* [sent as a gif or video (as for the other rules)] — the other rules already offer an animated preview, and a ten-hour
51045
51610
  * night reads better as three seconds of motion than as one frame of it. Both
51046
51611
  * modes get the SAME treatment (blurred frame, large centred title); `'gif'`
51047
51612
  * simply applies it to a dozen frames sampled across the render and assembles
@@ -51179,6 +51744,7 @@ TimelapseRuleInputSchema.extend({
51179
51744
  createdAt: number(),
51180
51745
  updatedAt: number()
51181
51746
  });
51747
+ MotionOnMotionChangedDataSchema.omit({ triggeredBy: true });
51182
51748
  object({
51183
51749
  /**
51184
51750
  * Fraction of the box's own size added on EACH side before cutting.