@camstack/types 1.2.283 → 1.2.285

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 (43) hide show
  1. package/dist/addon.js +2 -2
  2. package/dist/addon.mjs +2 -2
  3. package/dist/capabilities/device-extension.cap.d.ts +8 -25
  4. package/dist/capabilities/device-manager.cap.d.ts +2 -2
  5. package/dist/capabilities/device-state.cap.d.ts +2 -2
  6. package/dist/capabilities/doorbell.cap.d.ts +13 -64
  7. package/dist/capabilities/index.d.ts +2 -2
  8. package/dist/capabilities/motion.cap.d.ts +9 -8
  9. package/dist/capabilities/notification-rules.cap.d.ts +230 -8
  10. package/dist/capabilities/pipeline-orchestrator.cap.d.ts +147 -15
  11. package/dist/capabilities/pipeline-runner.cap.d.ts +2 -0
  12. package/dist/capabilities/ptz-autotrack.cap.d.ts +2 -3
  13. package/dist/catalogs/sensor-active-state.d.ts +8 -10
  14. package/dist/composition/presets/doorbell-feature.d.ts +1 -1
  15. package/dist/{composition-Dq42XWp0.mjs → composition-43aqsZQj.mjs} +6 -7
  16. package/dist/{composition-DG4jVTfB.js → composition-w3gBWMer.js} +6 -7
  17. package/dist/device/hub-motion-read.d.ts +22 -0
  18. package/dist/device-extension/slot-descriptor.d.ts +3 -3
  19. package/dist/enums/event-category.d.ts +9 -0
  20. package/dist/enums.js +1 -1
  21. package/dist/enums.mjs +1 -1
  22. package/dist/{event-category-C5xZWqz6.mjs → event-category-BGmz_oxW.mjs} +9 -0
  23. package/dist/{event-category-MbnB-6AN.js → event-category-DmS_tLsU.js} +9 -0
  24. package/dist/generated/addon-api.d.ts +7 -0
  25. package/dist/generated/extension-slots.d.ts +2 -6
  26. package/dist/generated/method-access-map.d.ts +1 -1
  27. package/dist/generated/method-device-selectors.d.ts +2 -2
  28. package/dist/generated/system-proxy.d.ts +1 -1
  29. package/dist/index.d.ts +5 -1
  30. package/dist/index.js +548 -217
  31. package/dist/index.mjs +523 -215
  32. package/dist/interfaces/event-bus.d.ts +5 -3
  33. package/dist/interfaces/pipeline-runner-capability.d.ts +2 -0
  34. package/dist/node.js +1 -1
  35. package/dist/node.mjs +1 -1
  36. package/dist/notification/alarm-settings.d.ts +58 -0
  37. package/dist/pipeline/camera-sensors.d.ts +133 -9
  38. package/dist/pipeline/motion-ownership.d.ts +13 -0
  39. package/dist/pipeline/provider-motion.d.ts +33 -0
  40. package/dist/{sleep-gU6hqv4_.mjs → sleep-CDCONfkt.mjs} +1 -1
  41. package/dist/{sleep-DCbD8sdg.js → sleep-G4F3X9X_.js} +1 -1
  42. package/dist/utils/addon-id.d.ts +2 -2
  43. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -1,7 +1,7 @@
1
1
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
- const require_sleep = require("./sleep-DCbD8sdg.js");
3
- const require_event_category = require("./event-category-MbnB-6AN.js");
4
- const require_composition = require("./composition-DG4jVTfB.js");
2
+ const require_sleep = require("./sleep-G4F3X9X_.js");
3
+ const require_event_category = require("./event-category-DmS_tLsU.js");
4
+ const require_composition = require("./composition-w3gBWMer.js");
5
5
  const require_err_msg = require("./err-msg-Dx2Kor0g.js");
6
6
  const require_enums = require("./enums.js");
7
7
  let zod = require("zod");
@@ -2538,7 +2538,7 @@ var RecordingTriggersSchema = zod.z.object({
2538
2538
  *
2539
2539
  * Cosa vuol dire "alto" dipende dal TIPO di device e non è deciso qui:
2540
2540
  * `SOURCE_CAP_ACTIVE_FIELD` (`catalogs/sensor-active-state.ts`) è LA tabella,
2541
- * la stessa che il virtual-doorbell usa dal 2026-08-05. Ed è il FRONTE, non
2541
+ * la stessa del campanello composto (D671). Ed è il FRONTE, non
2542
2542
  * il livello: un contatto trovato già aperto al riavvio del runner non fa
2543
2543
  * registrare.
2544
2544
  */
@@ -14541,8 +14541,8 @@ var deviceManagerCapability = {
14541
14541
  * (`value` / `missing` / `failed`, see {@link WrapperActivationReadSchema}).
14542
14542
  *
14543
14543
  * The narrow read of the durable authority behind `getBindings`: a
14544
- * consumer that must know what the operator PERSISTED (virtual-doorbell,
14545
- * before it drops a press) asks this instead of pulling device-manager's
14544
+ * consumer that must know what the operator PERSISTED (before it drops
14545
+ * work on the strength of an unbind) asks this instead of pulling device-manager's
14546
14546
  * whole addon store through `addonSettingsRaw.getGlobal` — which answered
14547
14547
  * `{}` on every isolated-engine hub and so never worked (D675). It reads
14548
14548
  * ONE row (the activation map, ~1.6 KB), never the ~625 KB store.
@@ -14833,107 +14833,6 @@ var deviceManagerCapability = {
14833
14833
  }
14834
14834
  };
14835
14835
  //#endregion
14836
- //#region src/capabilities/doorbell.cap.ts
14837
- /**
14838
- * Doorbell button cap. Two kinds of providers coexist behind this cap
14839
- * name (same pattern as `snapshot`):
14840
- *
14841
- * - **Native** providers: registered per-device by device-driver
14842
- * addons via `ctx.registerNativeCap` — either on a
14843
- * `DeviceType.Button` accessory with `role: DeviceRole.Doorbell`,
14844
- * or directly on the camera (Reolink registers at camera level).
14845
- * Emits an `onPressed` event every time the firmware pushes a
14846
- * ring; status tracks the last press and a pressCount since start
14847
- * (diagnostic).
14848
- *
14849
- * - **Wrapper** provider: the `virtual-doorbell` system builtin
14850
- * (`@camstack/system/builtins/doorbell`). Turns ANY binary-ish
14851
- * device (contact / switch / event-emitter …) into a doorbell for
14852
- * a camera. `defaultActive: false` — the operator explicitly binds
14853
- * it per camera in the device-bindings UI, then picks the source
14854
- * device + trigger in the per-device settings.
14855
- *
14856
- * The DeviceEventPropagator re-emits `onPressed` on the camera parent
14857
- * — subscribers listening at the camera level receive ring events
14858
- * with `via[]` populated. No code on the parent needed.
14859
- */
14860
- var DoorbellStatusSchema = zod.z.object({
14861
- /** Ms epoch of the last press. null = never observed since this provider started. */
14862
- lastPressedAt: zod.z.number().nullable(),
14863
- /** Counter since provider start. Resets on reboot. Useful for metrics/debug. */
14864
- pressCountSinceStart: zod.z.number()
14865
- });
14866
- var DoorbellPressEventSchema = zod.z.object({
14867
- deviceId: zod.z.number(),
14868
- timestamp: zod.z.number()
14869
- });
14870
- /**
14871
- * The `doorbell-source` extension slot's editable value (D648): the camera's
14872
- * virtual-doorbell trigger devices, exactly what the wrapper's
14873
- * `doorbellSources` persists (as `{ deviceId }` records).
14874
- */
14875
- var DoorbellSourceSlotValueSchema = zod.z.object({ deviceIds: zod.z.array(zod.z.number().int().positive()) });
14876
- /**
14877
- * The `doorbell-source` slot — which devices ring this camera's VIRTUAL
14878
- * doorbell, owned by the `virtual-doorbell` wrapper over its
14879
- * `doorbellSources` store (D648). A source rings when one of its
14880
- * `SOURCE_CAPS` rises. Whether the wrapper is bound to the camera at all is a
14881
- * different authority (`deviceManager.setWrapperActive`, D62) — the slot
14882
- * reports it, it never writes it.
14883
- */
14884
- var DOORBELL_SOURCE_SLOT = {
14885
- id: "doorbell-source",
14886
- label: "Doorbell trigger devices",
14887
- 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.",
14888
- shape: "association",
14889
- hostDeviceTypes: [require_err_msg.DeviceType.Camera],
14890
- sourceCaps: require_composition.SOURCE_CAPS,
14891
- cardinality: "many",
14892
- value: DoorbellSourceSlotValueSchema
14893
- };
14894
- var doorbellCapability = {
14895
- name: "doorbell",
14896
- scope: "device",
14897
- deviceNative: true,
14898
- mode: "singleton",
14899
- kind: "wrapper",
14900
- defaultActive: false,
14901
- deviceTypes: [require_err_msg.DeviceType.Button, require_err_msg.DeviceType.Camera],
14902
- extensionSlots: [DOORBELL_SOURCE_SLOT],
14903
- methods: {},
14904
- events: {
14905
- /**
14906
- * Fires once per physical press. Reolink delivers via Baichuan
14907
- * push (`ReolinkSimpleEvent.type === 'doorbell'`). There is no
14908
- * release/duration — it's a pulse.
14909
- */
14910
- onPressed: {
14911
- data: DoorbellPressEventSchema,
14912
- fromState: {
14913
- field: "lastPressedAt",
14914
- on: "advance"
14915
- }
14916
- } },
14917
- status: {
14918
- schema: DoorbellStatusSchema,
14919
- kind: "push"
14920
- },
14921
- /**
14922
- * Runtime-state slice — last press timestamp + lifetime press count.
14923
- * Mirrored by the kernel and readable via
14924
- * `device.state.doorbell.value`. UIs can show "last ring 5m ago"
14925
- * without subscribing.
14926
- */
14927
- runtimeState: DoorbellStatusSchema,
14928
- /**
14929
- * 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.
14930
- *
14931
- * See `RuntimeStateDurability`. Enforced by
14932
- * `scripts/check-runtime-state-durability.ts`.
14933
- */
14934
- durability: "restored"
14935
- };
14936
- //#endregion
14937
14836
  //#region src/generated/extension-slots.ts
14938
14837
  /**
14939
14838
  * AUTO-GENERATED by scripts/generate-extension-slots.ts — DO NOT EDIT.
@@ -14943,25 +14842,18 @@ onPressed: {
14943
14842
  * caps' descriptors and value schemas — never the caps barrel — so
14944
14843
  * `device-extension.cap.ts` can import this module without a cycle.
14945
14844
  *
14946
- * Coverage: 2 slot(s).
14845
+ * Coverage: 1 slot(s).
14947
14846
  */
14948
14847
  /** Every declared slot id, in table order. */
14949
- var EXTENSION_SLOT_IDS = ["doorbell-source", "linked-devices"];
14848
+ var EXTENSION_SLOT_IDS = ["linked-devices"];
14950
14849
  var ExtensionSlotIdSchema = zod.z.enum(EXTENSION_SLOT_IDS);
14951
- var EXTENSION_SLOTS = {
14952
- "doorbell-source": {
14953
- descriptor: DOORBELL_SOURCE_SLOT,
14954
- declaringCap: "doorbell",
14955
- hostDeviceTypes: [require_err_msg.DeviceType.Camera]
14956
- },
14957
- "linked-devices": {
14958
- descriptor: LINKED_DEVICES_SLOT,
14959
- declaringCap: "device-manager",
14960
- hostDeviceTypes: [require_err_msg.DeviceType.Camera]
14961
- }
14962
- };
14850
+ var EXTENSION_SLOTS = { "linked-devices": {
14851
+ descriptor: LINKED_DEVICES_SLOT,
14852
+ declaringCap: "device-manager",
14853
+ hostDeviceTypes: [require_err_msg.DeviceType.Camera]
14854
+ } };
14963
14855
  /** A slot's editable value, discriminated on `slot`. */
14964
- var ExtensionSlotValueSchema = zod.z.discriminatedUnion("slot", [DoorbellSourceSlotValueSchema.extend({ slot: zod.z.literal("doorbell-source") }), LinkedDevicesSlotValueSchema.extend({ slot: zod.z.literal("linked-devices") })]);
14856
+ var ExtensionSlotValueSchema = zod.z.discriminatedUnion("slot", [LinkedDevicesSlotValueSchema.extend({ slot: zod.z.literal("linked-devices") })]);
14965
14857
  /** Every device type at least one slot is offered on — `device-extension`'s `deviceTypes`. */
14966
14858
  var EXTENSION_HOST_DEVICE_TYPES = [require_err_msg.DeviceType.Camera];
14967
14859
  //#endregion
@@ -14970,8 +14862,8 @@ var EXTENSION_HOST_DEVICE_TYPES = [require_err_msg.DeviceType.Camera];
14970
14862
  * `device-extension` — ONE place to see and author what a device is extended
14971
14863
  * with by OTHER devices (D648).
14972
14864
  *
14973
- * **A contract, not a store.** Every slot (`linked-devices`, `doorbell-source`)
14974
- * is declared by the cap that owns the function (`extensionSlots` in its
14865
+ * **A contract, not a store.** Every slot (today one: `linked-devices`) is
14866
+ * declared by the cap that owns the function (`extensionSlots` in its
14975
14867
  * `*.cap.ts`, D4) and SERVED by the addon that already owns its store, over
14976
14868
  * that store and its existing write path. This cap persists nothing and has no config method (guarded by
14977
14869
  * `scripts/check-extension-slots.ts`): D62 applied to the whole feature, and
@@ -14980,7 +14872,7 @@ var EXTENSION_HOST_DEVICE_TYPES = [require_err_msg.DeviceType.Camera];
14980
14872
  * **Shape.** A device-scoped wrapper COLLECTION, the D554 shape `videoclips`
14981
14873
  * uses: `resolveCapMount` gives it the `device-scoped` mount and
14982
14874
  * `requireDeviceCollection` dispatches it. Its providers are the slot owners
14983
- * (device-manager, virtual-doorbell, …), and a device's sources are its
14875
+ * (today device-manager alone), and a device's sources are its
14984
14876
  * bindings (step 0 of `getBindings`, derived, persisted nowhere).
14985
14877
  *
14986
14878
  * - `listSources` — one row per provider, the D554 source-listing convention
@@ -15040,10 +14932,11 @@ var ExtensionSlotSourceSchema = zod.z.object({
15040
14932
  });
15041
14933
  /**
15042
14934
  * A DIFFERENT authority that gates whether the slot's sources do anything —
15043
- * reported read-only, named, never written through this contract (D62). The
15044
- * virtual doorbell's sources ring only while the wrapper is bound to the
15045
- * camera, and that binding belongs to `deviceManager.setWrapperActive`.
15046
- * `unknown` means the gate could not be read; it is not "inactive" (D315).
14935
+ * reported read-only, named, never written through this contract (D62) — e.g.
14936
+ * a slot whose sources act only while a wrapper is bound to the host, a
14937
+ * binding that belongs to `deviceManager.setWrapperActive`. No slot reports
14938
+ * one today (`linked-devices` answers `null`). `unknown` means the gate could
14939
+ * not be read; it is not "inactive" (D315).
15047
14940
  */
15048
14941
  var ExtensionSlotActivationSchema = zod.z.object({
15049
14942
  state: zod.z.enum([
@@ -15060,7 +14953,7 @@ var ExtensionSlotStateSchema = zod.z.object({
15060
14953
  /** `<source>:<slotId>` — the routing key for `listCandidates` / `setSlot`. */
15061
14954
  slotRef: zod.z.string(),
15062
14955
  slot: ExtensionSlotIdSchema,
15063
- /** Names the store written (D62), e.g. `virtual-doorbell:doorbellSources`. */
14956
+ /** Names the store written (D62), e.g. `device-manager:_linkedDeviceIds`. */
15064
14957
  authority: zod.z.string(),
15065
14958
  activation: ExtensionSlotActivationSchema.nullable(),
15066
14959
  value: ExtensionSlotValueSchema,
@@ -15264,8 +15157,8 @@ var deviceStateCapability = {
15264
15157
  * Canonical cross-layer WRITE for one cap-keyed slice. Used by
15265
15158
  * everyone who needs to publish runtime state for a device:
15266
15159
  * device providers (via `BaseDevice.runtimeState.setCapState`
15267
- * which delegates here), system-scope addons (e.g. the pipeline
15268
- * runner writing the `motion` slice on phase transitions), and
15160
+ * which delegates here), system-scope addons (e.g. the orchestrator
15161
+ * writing a camera's effective `motion` slice, D696), and
15269
15162
  * direct cap-router callers in tests.
15270
15163
  *
15271
15164
  * Behavior on the hub:
@@ -21390,6 +21283,41 @@ var NcSnoozeSuppressedSchema = zod.z.object({
21390
21283
  firstAt: zod.z.number(),
21391
21284
  lastAt: zod.z.number()
21392
21285
  });
21286
+ /** The bounds every alarm delay field carries — settings, per-mode overrides, both editors. */
21287
+ var NC_ALARM_DELAY_MAX_SEC = 600;
21288
+ var NC_ALARM_TRIGGERED_MAX_SEC = 3600;
21289
+ /** At most this many ids on one mode's non-blocking list. */
21290
+ var NC_ALARM_NONBLOCKING_MAX = 200;
21291
+ var NcAlarmDelaySecSchema = zod.z.number().int().min(0).max(600);
21292
+ var NcAlarmTriggeredSecSchema = zod.z.number().int().min(0).max(NC_ALARM_TRIGGERED_MAX_SEC);
21293
+ var uniqueModes = (entries) => new Set(entries.map((e) => e.mode)).size === entries.length;
21294
+ /** One mode's OVERRIDES. An absent field inherits the global value (D697). */
21295
+ var NcAlarmModeDelaysSchema = zod.z.object({
21296
+ mode: AlarmArmModeSchema,
21297
+ exitDelaySec: NcAlarmDelaySecSchema.optional(),
21298
+ entryDelaySec: NcAlarmDelaySecSchema.optional(),
21299
+ triggeredDurationSec: NcAlarmTriggeredSecSchema.optional()
21300
+ });
21301
+ var NcAlarmModeDelaysListSchema = zod.z.array(NcAlarmModeDelaysSchema).max(8).refine(uniqueModes, { message: "modeDelays: at most one entry per arm mode" });
21302
+ /**
21303
+ * One mode's EDIT in a patch: a number sets the override, `null` removes it (the mode inherits
21304
+ * again), an absent field leaves it alone. Per field, so two editors changing two different
21305
+ * delays of one mode never undo each other.
21306
+ */
21307
+ var NcAlarmModeDelaysEditSchema = zod.z.object({
21308
+ mode: AlarmArmModeSchema,
21309
+ exitDelaySec: NcAlarmDelaySecSchema.nullable().optional(),
21310
+ entryDelaySec: NcAlarmDelaySecSchema.nullable().optional(),
21311
+ triggeredDurationSec: NcAlarmTriggeredSecSchema.nullable().optional()
21312
+ });
21313
+ var NcAlarmModeDelaysEditListSchema = zod.z.array(NcAlarmModeDelaysEditSchema).max(8).refine(uniqueModes, { message: "modeDelays: at most one edit per arm mode" });
21314
+ /** One switch of the alarm table: put ONE device on, or take it off, ONE mode's list. */
21315
+ var NcAlarmNonBlockingEditSchema = zod.z.object({
21316
+ mode: AlarmArmModeSchema,
21317
+ deviceId: zod.z.number().int().positive(),
21318
+ /** true = on the list (may be open, does not block); false = off the list (blocks). */
21319
+ nonBlocking: zod.z.boolean()
21320
+ });
21393
21321
  /**
21394
21322
  * One arm mode's non-blocking list: devices that may be open when that mode
21395
21323
  * arms, without the arm being refused.
@@ -21403,10 +21331,10 @@ var NcAlarmNonBlockingSchema = zod.z.object({
21403
21331
  * meaning a reader could agree on (union? the last one?), so they are refused
21404
21332
  * at the boundary rather than interpreted.
21405
21333
  */
21406
- var NcAlarmNonBlockingListSchema = zod.z.array(NcAlarmNonBlockingSchema).max(8).refine((lists) => new Set(lists.map((l) => l.mode)).size === lists.length, { message: "nonBlocking: at most one list per arm mode" });
21334
+ var NcAlarmNonBlockingListSchema = zod.z.array(NcAlarmNonBlockingSchema).max(8).refine(uniqueModes, { message: "nonBlocking: at most one list per arm mode" });
21407
21335
  /**
21408
- * The three durations the panel's state machine runs on, who hears about its
21409
- * transitions, and which openings each mode tolerates.
21336
+ * The three durations — global, and per mode since D697 — the panel's state
21337
+ * machine runs on, who hears about its transitions, and which openings each mode tolerates.
21410
21338
  *
21411
21339
  * They live on the NOTIFICATION-RULES cap, not on `alarm-panel`, on purpose:
21412
21340
  * `alarm-panel` is `deviceNative` and its other provider mirrors somebody
@@ -21416,15 +21344,15 @@ var NcAlarmNonBlockingListSchema = zod.z.array(NcAlarmNonBlockingSchema).max(8).
21416
21344
  */
21417
21345
  var NcAlarmSettingsSchema = zod.z.object({
21418
21346
  /** Grace period between arming and the mode taking effect. 0 = immediate. */
21419
- exitDelaySec: zod.z.number().int().min(0).max(600),
21347
+ exitDelaySec: NcAlarmDelaySecSchema,
21420
21348
  /** Grace period between a trigger and the alarm firing. 0 = immediate. */
21421
- entryDelaySec: zod.z.number().int().min(0).max(600),
21349
+ entryDelaySec: NcAlarmDelaySecSchema,
21422
21350
  /**
21423
21351
  * How long `triggered` lasts before the panel re-arms itself.
21424
21352
  * **0 = until an operator disarms it** — the behaviour before this field
21425
21353
  * existed, and therefore what an untouched install keeps doing.
21426
21354
  */
21427
- triggeredDurationSec: zod.z.number().int().min(0).max(3600),
21355
+ triggeredDurationSec: NcAlarmTriggeredSecSchema,
21428
21356
  /**
21429
21357
  * Deprecated by D630 — every transition is announced. Parsed, never read;
21430
21358
  * remove after one release. Optional so an older admin's patch (which still
@@ -21447,17 +21375,30 @@ var NcAlarmSettingsSchema = zod.z.object({
21447
21375
  * per mode is meaningful. Defaulted to `[]` so a blob stored before D630
21448
21376
  * parses as "every opening blocks" — the behaviour it was written under.
21449
21377
  */
21450
- nonBlocking: NcAlarmNonBlockingListSchema.default([])
21378
+ nonBlocking: NcAlarmNonBlockingListSchema.default([]),
21379
+ /**
21380
+ * Per arm mode, the delays that mode OVERRIDES (D697). A mode with no entry, or an entry
21381
+ * without a field, uses the global value above — so `[]`, the default, is exactly the
21382
+ * behaviour of a blob stored before this field existed. Read through `resolveModeDelays`.
21383
+ */
21384
+ modeDelays: NcAlarmModeDelaysListSchema.default([])
21451
21385
  });
21452
21386
  /**
21453
21387
  * Every field optional — a tab edits one control at a time.
21454
21388
  *
21455
- * `nonBlocking` is re-declared WITHOUT its default: `.partial()` does not
21456
- * remove an inner `.default()`, so a patch that never named the field would
21457
- * parse to `nonBlocking: []` and wipe every mode's list on an unrelated edit
21458
- * (the same trap {@link NcRulePatchSchema} documents).
21389
+ * `nonBlocking` and `modeDelays` are re-declared WITHOUT their defaults:
21390
+ * `.partial()` does not remove an inner `.default()`, so a patch that never
21391
+ * named the field would parse to `[]` and wipe every mode's list on an
21392
+ * unrelated edit (the same trap {@link NcRulePatchSchema} documents). Here
21393
+ * `modeDelays` means EDITS, not the stored overrides.
21459
21394
  */
21460
- var NcAlarmSettingsPatchSchema = NcAlarmSettingsSchema.extend({ nonBlocking: NcAlarmNonBlockingListSchema }).partial();
21395
+ var NcAlarmSettingsPatchSchema = NcAlarmSettingsSchema.extend({
21396
+ nonBlocking: NcAlarmNonBlockingListSchema,
21397
+ /** Per-mode, per-field edits — NOT the whole list (see NcAlarmModeDelaysEditSchema). */
21398
+ modeDelays: NcAlarmModeDelaysEditListSchema,
21399
+ /** ONE membership change; the panel applies it to the list it holds at its turn. */
21400
+ nonBlockingEdit: NcAlarmNonBlockingEditSchema
21401
+ }).partial().refine((p) => p.nonBlocking === void 0 || p.nonBlockingEdit === void 0, { message: "nonBlocking and nonBlockingEdit are exclusive — send the whole lists or one edit" });
21461
21402
  /**
21462
21403
  * What one arm mode actually arms, DERIVED from the enabled rules gated on it.
21463
21404
  * Never authored, never stored — see `alarm-mode-coverage.ts` for why a stored
@@ -21557,6 +21498,30 @@ var NcAlarmConfigSchema = zod.z.object({
21557
21498
  */
21558
21499
  live: NcAlarmLiveSchema.optional()
21559
21500
  });
21501
+ /** At most this many ids in one `getAlarmSensors` call — a validation bound, not a target. */
21502
+ var NC_ALARM_SENSORS_MAX = 500;
21503
+ var NcAlarmSensorReadingSchema = zod.z.enum([
21504
+ "open",
21505
+ "closed",
21506
+ "unknown",
21507
+ "not-opening"
21508
+ ]);
21509
+ /** One device's state as the alarm reads it — the classifier the arm check uses. */
21510
+ var NcAlarmSensorStateSchema = zod.z.object({
21511
+ deviceId: zod.z.number().int().positive(),
21512
+ reading: NcAlarmSensorReadingSchema,
21513
+ /** The word as read (`open`, `closed`, `unlocked`, `stopped`, …); null when unknown / not an opening. */
21514
+ state: zod.z.string().nullable(),
21515
+ /** Why `unknown`: the read failed, or the slice holds no word its cap defines (a placeholder included). */
21516
+ unknownWhy: zod.z.enum(["read-failed", "unknown-word"]).nullable(),
21517
+ /** The device manager's liveness as the centre mirrors it; null = not known. */
21518
+ online: zod.z.boolean().nullable()
21519
+ });
21520
+ var NcAlarmSensorsInputSchema = zod.z.object({ deviceIds: zod.z.array(zod.z.number().int().positive()).max(500) });
21521
+ var NcAlarmSensorsSchema = zod.z.object({
21522
+ sensors: zod.z.array(NcAlarmSensorStateSchema),
21523
+ readAt: zod.z.number().int().nonnegative()
21524
+ });
21560
21525
  /**
21561
21526
  * The most seconds of footage any notification rule may ask a camera to retain.
21562
21527
  *
@@ -21816,8 +21781,9 @@ var notificationRulesCapability = {
21816
21781
  */
21817
21782
  getAlarmConfig: require_sleep.method(zod.z.object({}), NcAlarmConfigSchema, { auth: "admin" }),
21818
21783
  /**
21819
- * Patch the settings (durations, recipients, per-mode non-blocking lists;
21820
- * `announceArm` is accepted and ignored — D630). Returns the WHOLE config,
21784
+ * Patch the settings (durations — global and per mode —, recipients,
21785
+ * per-mode non-blocking lists or one membership edit; `announceArm` is
21786
+ * accepted and ignored — D630). Returns the WHOLE config,
21821
21787
  * coverage and `live` included, so a
21822
21788
  * client never has to guess what the server settled on — the panel clamps
21823
21789
  * and normalises, and a form that re-rendered from its own input would
@@ -21826,7 +21792,15 @@ var notificationRulesCapability = {
21826
21792
  setAlarmConfig: require_sleep.method(zod.z.object({ patch: NcAlarmSettingsPatchSchema }), NcAlarmConfigSchema, {
21827
21793
  kind: "mutation",
21828
21794
  auth: "admin"
21829
- })
21795
+ }),
21796
+ /**
21797
+ * The CURRENT state of each asked device as the alarm reads it (D697) — open, closed,
21798
+ * unknown (why) or not an opening, plus liveness. Classified by the same table the arm
21799
+ * check uses (`alarm-openings.ts`), so the editor and the arm can never disagree. The
21800
+ * caller names the ids (the household openings it already holds); at most
21801
+ * `NC_ALARM_SENSORS_MAX`.
21802
+ */
21803
+ getAlarmSensors: require_sleep.method(NcAlarmSensorsInputSchema, NcAlarmSensorsSchema, { auth: "admin" })
21830
21804
  }
21831
21805
  };
21832
21806
  //#endregion
@@ -22215,12 +22189,27 @@ var CameraSensorRefSchema = zod.z.object({
22215
22189
  function cameraSensorRefKey(ref) {
22216
22190
  return `${ref.addonId}/${ref.stableId}`;
22217
22191
  }
22218
- /** CS-1 accepts exactly one mode; CS-2 (D673) widens it to confirm / replace. */
22219
- var CameraSensorsModeSchema = zod.z.enum(["in-addition"]);
22220
- var CameraSensorsConfigSchema = zod.z.object({
22221
- mode: CameraSensorsModeSchema,
22222
- sensors: zod.z.array(CameraSensorRefSchema).min(1).max(8)
22223
- }).superRefine((value, ctx) => {
22192
+ /**
22193
+ * A sensor's mode (D673). `in-addition`: its motion is the camera's motion too.
22194
+ * `replace`: its motion is the camera's, and while one is READY the camera's
22195
+ * own motion no longer counts on its own. `confirm`: while one is READY the
22196
+ * camera's own motion counts only while a confirm sensor is active — with or
22197
+ * without a replace sensor (spec C2, the controller's ruling on Q1).
22198
+ */
22199
+ var CameraSensorModeSchema = zod.z.enum([
22200
+ "in-addition",
22201
+ "confirm",
22202
+ "replace"
22203
+ ]);
22204
+ /** A stored sensor with no mode — every CS-1 row — is in addition. */
22205
+ var DEFAULT_CAMERA_SENSOR_MODE = "in-addition";
22206
+ var CameraSensorEntrySchema = CameraSensorRefSchema.extend({ mode: CameraSensorModeSchema.default(DEFAULT_CAMERA_SENSOR_MODE) });
22207
+ /**
22208
+ * A camera's attached sensors. A CS-1 row carried an envelope
22209
+ * `mode: 'in-addition'`: `z.object` drops it on parse, and the PARSED value is
22210
+ * what the write stores (D672 rule 3), so it is never written again.
22211
+ */
22212
+ var CameraSensorsConfigSchema = zod.z.object({ sensors: zod.z.array(CameraSensorEntrySchema).min(1).max(8) }).superRefine((value, ctx) => {
22224
22213
  const seen = /* @__PURE__ */ new Set();
22225
22214
  value.sensors.forEach((ref, index) => {
22226
22215
  const key = cameraSensorRefKey(ref);
@@ -22232,39 +22221,41 @@ var CameraSensorsConfigSchema = zod.z.object({
22232
22221
  seen.add(key);
22233
22222
  });
22234
22223
  });
22235
- var RefFields = {
22224
+ /** Every attachment names its mode; an older orchestrator that does not is in addition. */
22225
+ var AttachmentFields = {
22236
22226
  addonId: zod.z.string(),
22237
- stableId: zod.z.string()
22227
+ stableId: zod.z.string(),
22228
+ mode: CameraSensorModeSchema.default(DEFAULT_CAMERA_SENSOR_MODE)
22238
22229
  };
22239
22230
  var CameraSensorAttachmentSchema = zod.z.discriminatedUnion("state", [
22240
22231
  zod.z.object({
22241
- ...RefFields,
22232
+ ...AttachmentFields,
22242
22233
  state: zod.z.literal("ready"),
22243
22234
  deviceId: zod.z.number(),
22244
22235
  name: zod.z.string(),
22245
22236
  caps: zod.z.array(zod.z.string()).readonly()
22246
22237
  }),
22247
22238
  zod.z.object({
22248
- ...RefFields,
22239
+ ...AttachmentFields,
22249
22240
  state: zod.z.literal("offline"),
22250
22241
  deviceId: zod.z.number(),
22251
22242
  name: zod.z.string(),
22252
22243
  reason: zod.z.enum(["offline", "disabled"])
22253
22244
  }),
22254
22245
  zod.z.object({
22255
- ...RefFields,
22246
+ ...AttachmentFields,
22256
22247
  state: zod.z.literal("missing"),
22257
22248
  reason: zod.z.string()
22258
22249
  }),
22259
22250
  zod.z.object({
22260
- ...RefFields,
22251
+ ...AttachmentFields,
22261
22252
  state: zod.z.literal("unsupported"),
22262
22253
  deviceId: zod.z.number(),
22263
22254
  name: zod.z.string(),
22264
22255
  reason: zod.z.string()
22265
22256
  }),
22266
22257
  zod.z.object({
22267
- ...RefFields,
22258
+ ...AttachmentFields,
22268
22259
  state: zod.z.literal("unreadable"),
22269
22260
  reason: zod.z.string()
22270
22261
  })
@@ -22277,17 +22268,49 @@ var CameraSensorAttachmentSchema = zod.z.discriminatedUnion("state", [
22277
22268
  * say.
22278
22269
  */
22279
22270
  var CameraSensorsNotForwardedSchema = zod.z.enum(["onboard-not-listed", "no-active-detection"]);
22271
+ /** Whether the camera's OWN motion counts on its own (D673 C2), from its READY sensors (C3). */
22272
+ var CameraOwnMotionSchema = zod.z.enum([
22273
+ "always",
22274
+ "when-confirmed",
22275
+ "never"
22276
+ ]);
22277
+ /** Confirm / Replace cannot suppress this camera's motion: its provider still emits it directly (D673 C13). */
22278
+ var CameraSensorsNotEnforcedSchema = zod.z.enum(["provider-not-split"]);
22279
+ /**
22280
+ * The camera's OWN onboard motion (D696): the raw input the bridge combines,
22281
+ * never the effective value. The camera's `motion` slice is the effective one,
22282
+ * so a view of the camera's own row reads this.
22283
+ * - `atMs`: when the bridge received the camera's last own edge.
22284
+ * - `detected`: evaluated WHEN THE STATUS IS ASKED — the last edge said `true`
22285
+ * AND it is younger than the window the bridge counts the camera's own motion
22286
+ * for (`motionCooldownMs`, floored at two sustain ticks). A camera that never
22287
+ * sends a clear (heartbeats only) therefore reads `false` once no push came
22288
+ * within the window; a status read is a snapshot, so a live view re-asks.
22289
+ * Absent = this orchestrator has not received the camera's own motion since it
22290
+ * started (unknown, never "quiet"), or an orchestrator older than D696.
22291
+ */
22292
+ var CameraRawLevelSchema = zod.z.object({
22293
+ detected: zod.z.boolean(),
22294
+ atMs: zod.z.number()
22295
+ });
22280
22296
  var CameraSensorsStatusSchema = zod.z.discriminatedUnion("state", [
22281
- zod.z.object({ state: zod.z.literal("not-configured") }),
22297
+ zod.z.object({
22298
+ state: zod.z.literal("not-configured"),
22299
+ cameraLevel: CameraRawLevelSchema.optional()
22300
+ }),
22282
22301
  zod.z.object({
22283
22302
  state: zod.z.literal("unreadable"),
22284
- reason: zod.z.string()
22303
+ reason: zod.z.string(),
22304
+ cameraLevel: CameraRawLevelSchema.optional()
22285
22305
  }),
22286
22306
  zod.z.object({
22287
22307
  state: zod.z.literal("configured"),
22288
- mode: CameraSensorsModeSchema,
22308
+ cameraLevel: CameraRawLevelSchema.optional(),
22289
22309
  sensors: zod.z.array(CameraSensorAttachmentSchema).readonly(),
22290
- notForwarded: CameraSensorsNotForwardedSchema.optional()
22310
+ /** Absent = an orchestrator older than CS-2: it does not say (D315). */
22311
+ cameraMotion: CameraOwnMotionSchema.optional(),
22312
+ notForwarded: CameraSensorsNotForwardedSchema.optional(),
22313
+ notEnforced: CameraSensorsNotEnforcedSchema.optional()
22291
22314
  })
22292
22315
  ]);
22293
22316
  /** What a camera reads before its first settings read ANSWERED (D315). */
@@ -26631,8 +26654,10 @@ var RunnerCameraConfigSchema = zod.z.object({
26631
26654
  * - `analyzer`: ML/frame-diff motion detection (motion-wasm or other
26632
26655
  * analyzer providers) running on decoded frames in this runner.
26633
26656
  * - `onboard`: camera-native motion pushes (Reolink Baichuan, ONVIF
26634
- * analytics). The provider emits ProviderMotion
26635
- * events; the orchestrator forwards to `reportMotion`.
26657
+ * analytics). The provider emits its raw push as `ProviderMotion`
26658
+ * (D673); the orchestrator's camera-sensors bridge re-emits the camera's
26659
+ * effective motion as `MotionOnMotionChanged`, which is what reaches
26660
+ * `reportMotion`.
26636
26661
  */
26637
26662
  motionSources: MotionSourcesSchema.default(["analyzer"]),
26638
26663
  /**
@@ -26997,7 +27022,15 @@ var RunnerLocalLoadSchema = zod.z.object({
26997
27022
  hasGpu: zod.z.boolean(),
26998
27023
  inferenceBackend: zod.z.string().optional(),
26999
27024
  cpuCores: zod.z.number().optional()
27000
- })
27025
+ }),
27026
+ /**
27027
+ * Who writes a camera's `motion` runtime slice (D696). `'orchestrator'`: this
27028
+ * runner never writes it. ABSENT = a runner older than D696, which still
27029
+ * writes the slice from its phase machine; the orchestrator does not write
27030
+ * while any runner node is absent-or-unanswered, so one slice never has two
27031
+ * writers.
27032
+ */
27033
+ motionSliceWriter: zod.z.literal("orchestrator").optional()
27001
27034
  });
27002
27035
  /**
27003
27036
  * Aggregate runtime metrics for the runner's whole local pool. Mirrors the
@@ -34859,6 +34892,72 @@ onStatusChanged: { data: zod.z.object({
34859
34892
  volatileStateFields: ["lastChangedAt"]
34860
34893
  };
34861
34894
  //#endregion
34895
+ //#region src/capabilities/doorbell.cap.ts
34896
+ var DoorbellStatusSchema = zod.z.object({
34897
+ /** Ms epoch of the last press. null = never observed since this provider started. */
34898
+ lastPressedAt: zod.z.number().nullable(),
34899
+ /** Counter since provider start. Resets on reboot. Useful for metrics/debug. */
34900
+ pressCountSinceStart: zod.z.number()
34901
+ });
34902
+ var DoorbellPressEventSchema = zod.z.object({
34903
+ deviceId: zod.z.number(),
34904
+ timestamp: zod.z.number()
34905
+ });
34906
+ /**
34907
+ * Doorbell button cap. Two kinds of provider serve it, and to every consumer
34908
+ * they are the same cap:
34909
+ *
34910
+ * - **Native** providers, registered per device by a driver addon through
34911
+ * `ctx.registerNativeCap` — a `DeviceType.Button` accessory with
34912
+ * `role: DeviceRole.Doorbell`, or the camera itself (Reolink registers at
34913
+ * camera level). They emit `onPressed` on every firmware ring.
34914
+ * - **A composed doorbell** (D670, D671): a camera's customization gives it
34915
+ * the cap, its `lastPressedAt` rising from the sources the operator
34916
+ * assigned in Customize → Doorbell, and the composer emits `onPressed`
34917
+ * from that field's advance (`fromState`).
34918
+ *
34919
+ * The DeviceEventPropagator re-emits `onPressed` on the camera parent.
34920
+ */
34921
+ var doorbellCapability = {
34922
+ name: "doorbell",
34923
+ scope: "device",
34924
+ deviceNative: true,
34925
+ mode: "singleton",
34926
+ deviceTypes: [require_err_msg.DeviceType.Button, require_err_msg.DeviceType.Camera],
34927
+ methods: {},
34928
+ events: {
34929
+ /**
34930
+ * Fires once per physical press. Reolink delivers via Baichuan
34931
+ * push (`ReolinkSimpleEvent.type === 'doorbell'`). There is no
34932
+ * release/duration — it's a pulse.
34933
+ */
34934
+ onPressed: {
34935
+ data: DoorbellPressEventSchema,
34936
+ fromState: {
34937
+ field: "lastPressedAt",
34938
+ on: "advance"
34939
+ }
34940
+ } },
34941
+ status: {
34942
+ schema: DoorbellStatusSchema,
34943
+ kind: "push"
34944
+ },
34945
+ /**
34946
+ * Runtime-state slice — last press timestamp + lifetime press count.
34947
+ * Mirrored by the kernel and readable via
34948
+ * `device.state.doorbell.value`. UIs can show "last ring 5m ago"
34949
+ * without subscribing.
34950
+ */
34951
+ runtimeState: DoorbellStatusSchema,
34952
+ /**
34953
+ * 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.
34954
+ *
34955
+ * See `RuntimeStateDurability`. Enforced by
34956
+ * `scripts/check-runtime-state-durability.ts`.
34957
+ */
34958
+ durability: "restored"
34959
+ };
34960
+ //#endregion
34862
34961
  //#region src/capabilities/enum-sensor.cap.ts
34863
34962
  /**
34864
34963
  * Enum-state sensor — a string value picked from a finite option set.
@@ -37306,11 +37405,11 @@ authKey: zod.z.string().optional() }), zod.z.object({
37306
37405
  /**
37307
37406
  * How long after a camera's last rising edge `pipeline-analytics` closes the
37308
37407
  * motion EPISODE row it kept open for it (D475) — "il delay della cap", in
37309
- * the operator's words. One authority for the whole system: every provider
37310
- * that seeds `autoClearAfterMs` on a `Camera` device writes this SAME
37311
- * constant while `detected: true` (never its own number — Hikvision used to
37312
- * seed its internal 3 s inactivity timer here, which is a different clock for
37313
- * a different purpose), and `MotionEpisodeTracker` imports it directly rather
37408
+ * the operator's words. One authority for the whole system: the writer of a
37409
+ * `Camera` device's slice (the orchestrator, D696) writes this SAME constant
37410
+ * in `autoClearAfterMs` while `detected: true` (never a camera's own clock —
37411
+ * Hikvision used to seed its internal 3 s inactivity timer here, a different
37412
+ * clock for a different purpose), and `MotionEpisodeTracker` imports it directly rather
37314
37413
  * than reading the live cap value on the hot path. A `Sensor` device (HA
37315
37414
  * binary sensor, Homematic) gets a genuine push both ways and has no episode
37316
37415
  * to close on a timer, so it writes `null`, never this constant.
@@ -37321,9 +37420,9 @@ var MotionStatusSchema = zod.z.object({
37321
37420
  /** Ms epoch of the last detected-true observation. Null if never detected. */
37322
37421
  lastDetectedAt: zod.z.number().nullable(),
37323
37422
  /**
37324
- * `MOTION_CLOSE_AFTER_MS` while `detected: true` on a `Camera` device,
37325
- * `null` while false and on every `Sensor` device (D475) — see that
37326
- * constant's doc for the one-authority rule.
37423
+ * `MOTION_CLOSE_AFTER_MS` while `detected: true` on a `Camera` device (the
37424
+ * orchestrator writes it, D696), `null` while false and on every `Sensor`
37425
+ * device (D475) — see that constant's doc for the one-authority rule.
37327
37426
  *
37328
37427
  * ## Reading this field still arms nothing
37329
37428
  *
@@ -37341,34 +37440,31 @@ var MotionStatusSchema = zod.z.object({
37341
37440
  * `addon-export-alexa/src/motion-clear-hold.ts` and
37342
37441
  * `addon-export-hap`'s `RESET_DEBOUNCE_MS` both do.
37343
37442
  *
37344
- * ## Who writes it
37345
- *
37346
- * - **Cameras** — the runner's phase machine, `active → watching` on
37347
- * `cooldown_expired`, which then writes this slice with
37348
- * `detected: false` (`handlePhaseChanged` in
37349
- * `pipeline-runner/index.ts`). It produces the FALLING edge, which
37350
- * matters most for the sources that only ever push a rising one:
37351
- * Reolink emits `MotionOnMotionChanged { detected: true }` and never
37352
- * a false.
37353
- * - **Sensors** (Home Assistant binary sensors, Homematic) — the
37354
- * provider pushes the false itself, from the upstream system's own
37355
- * state change. No phase machine is involved.
37443
+ * ## Who writes it (D696)
37356
37444
  *
37357
- * ### The phase machine is CANONICAL, not sole — and that is a defect
37445
+ * - **Cameras** — the orchestrator, and nothing else. It writes the camera's
37446
+ * EFFECTIVE motion (`addon-pipeline-orchestrator`
37447
+ * `camera-sensors/motion-slice.ts`), alongside the effective
37448
+ * `MotionOnMotionChanged` it emits or receives: the camera-sensors bridge
37449
+ * for a split camera, an unsplit emitter's direct event, the analyzer and
37450
+ * device activity, as the camera's `motionSources` counts them. A source
37451
+ * that never sends a clear falls one window after its last `true`.
37452
+ * `lastDetectedAt` moves only on an effective rise. No camera provider
37453
+ * writes this slice (not even a boot seed), and neither does the runner's
37454
+ * phase machine: its phase is "a session is attached" for every on-motion
37455
+ * session, not motion, and it now has its own `DetectionPhaseTransition`.
37456
+ * A provider's `isDetected` answers from the hub's slice.
37457
+ * - **Sensors** (Home Assistant binary sensors, Homematic, Matter, Alexa
37458
+ * imports) — the provider pushes both edges itself, from the upstream
37459
+ * system's own state change. That is the sensor's own fact.
37358
37460
  *
37359
- * An earlier revision of this docblock (mine, 2026-09-12) claimed the
37360
- * phase machine is the sole writer for a camera. It is not.
37361
- * `hikvision-camera.ts:3464` and `amcrest-camera.ts:445` both call
37362
- * `setCapSlice(motionCapability, …)` on their own rising edge, and
37363
- * Hikvision's comment says why: it read THIS docblock, agreed the
37364
- * runner is canonical, and wrote anyway to avoid per-tick churn. So
37365
- * two authorities can disagree about one slice, which this repo
37366
- * forbids, and the doc said otherwise — which is worse than saying
37367
- * nothing, because it reads as verification.
37461
+ * `scripts/check-onboard-motion-emitters.ts` refuses any other writer of a
37462
+ * `motion` slice; each sensor writer is a named exemption.
37368
37463
  *
37369
- * This predates D475 and is not fixed there: the fix touches every
37370
- * camera provider. Recorded in D475's Consequences. Do not restore the
37371
- * "sole writer" wording without also removing the other writers.
37464
+ * This replaces the D475 §4 rule ("the phase machine is the sole writer").
37465
+ * That rule was never true: Hikvision and Amcrest wrote the slice raw beside
37466
+ * it, every provider seeded it at boot, and every session left it
37467
+ * `detected: true` after its detach.
37372
37468
  */
37373
37469
  autoClearAfterMs: zod.z.number().nullable()
37374
37470
  });
@@ -37440,11 +37536,12 @@ onMotionChanged: { data: MotionOnMotionChangedDataSchema } },
37440
37536
  */
37441
37537
  runtimeState: MotionStatusSchema,
37442
37538
  /**
37443
- * Runtime-state durability: **session** — every writer of this slice
37539
+ * Runtime-state durability: **session** — the writer of this slice
37444
37540
  * writes only on an EDGE, so a restored `detected: true` would stay
37445
37541
  * frozen until the next one instead of being corrected. The next edge
37446
- * re-publishes the real state. (On who the writers are, and why there
37447
- * is more than one, see `autoClearAfterMs` above.)
37542
+ * re-publishes the real state, and the orchestrator re-publishes every
37543
+ * camera when it starts writing (D696; on who writes it, see
37544
+ * `autoClearAfterMs` above).
37448
37545
  *
37449
37546
  * See `RuntimeStateDurability`. Enforced by
37450
37547
  * `scripts/check-runtime-state-durability.ts`.
@@ -40427,8 +40524,7 @@ var ptzAutotrackCapability = {
40427
40524
  deviceNative: true,
40428
40525
  mode: "singleton",
40429
40526
  /**
40430
- * Two kinds of provider behind one name, the same shape `snapshot` and
40431
- * `doorbell` use:
40527
+ * Two kinds of provider behind one name, the same shape `snapshot` uses:
40432
40528
  *
40433
40529
  * - **Native**: the camera's own firmware autotrack, registered per device by
40434
40530
  * the driver when the probe says it exists (Reolink: yes; Hikvision:
@@ -40436,7 +40532,7 @@ var ptzAutotrackCapability = {
40436
40532
  * - **Wrapper**: the emulated implementation (`@camstack/system`'s `autotrack` builtin),
40437
40533
  * which follows a subject with `ptz.move` pulses driven by the detection
40438
40534
  * pipeline. `defaultActive: false` — the operator binds it per camera in
40439
- * the bindings UI, exactly as `virtual-doorbell` is bound.
40535
+ * the bindings UI.
40440
40536
  *
40441
40537
  * The binding chooses WHICH implementation answers; `setEnabled` stays the
40442
40538
  * one switch for the function either way. A camera never has both driving its
@@ -46659,10 +46755,10 @@ function feederCustomizationExample(sources) {
46659
46755
  //#endregion
46660
46756
  //#region src/composition/presets/doorbell-feature.ts
46661
46757
  /**
46662
- * The doorbell of a camera as a customization (D671). ONE builder: the
46663
- * virtual-doorbell migration and the admin UI's "Use as doorbell" preset both
46664
- * call it, so a preset can never write a shape the migration would refuse as
46665
- * "an unrelated existing block".
46758
+ * The doorbell of a camera as a customization (D671). ONE builder: the admin
46759
+ * UI's Customize → Doorbell card writes every doorbell feature through it, and
46760
+ * edits one only when it is exactly what this builds (`isDoorbellPresetFeature`)
46761
+ * — a composed doorbell has one canonical shape.
46666
46762
  */
46667
46763
  /** A rise closer than this to the previous one is the same press (D671). */
46668
46764
  var DOORBELL_RISE_DEBOUNCE_MS = 2e3;
@@ -46679,7 +46775,7 @@ function doorbellFeatureSources(source, boundCaps) {
46679
46775
  }];
46680
46776
  });
46681
46777
  }
46682
- /** The D671 feature, byte for byte what the migration writes. Throws on zero sources. */
46778
+ /** The canonical D671 doorbell feature. Throws on zero sources. */
46683
46779
  function buildDoorbellCompositionFeature(input) {
46684
46780
  const sources = [...input.sources].toSorted((a, b) => `${a.source.addonId}/${a.source.stableId}#${a.cap}`.localeCompare(`${b.source.addonId}/${b.source.stableId}#${b.cap}`));
46685
46781
  if (sources.length === 0) throw new Error("doorbell composition needs at least one source");
@@ -56409,6 +56505,12 @@ var METHOD_ACCESS_MAP = Object.freeze({
56409
56505
  addonId: null,
56410
56506
  access: "view"
56411
56507
  },
56508
+ "notificationRules.getAlarmSensors": {
56509
+ capName: "notification-rules",
56510
+ capScope: "system",
56511
+ addonId: null,
56512
+ access: "view"
56513
+ },
56412
56514
  "notificationRules.getClipRetentionAsks": {
56413
56515
  capName: "notification-rules",
56414
56516
  capScope: "system",
@@ -61229,6 +61331,11 @@ var METHOD_DEVICE_SELECTORS = Object.freeze({
61229
61331
  form: "single",
61230
61332
  optional: false
61231
61333
  }],
61334
+ "notificationRules.getAlarmSensors": [{
61335
+ name: "deviceIds",
61336
+ form: "array",
61337
+ optional: false
61338
+ }],
61232
61339
  "notificationRules.setDeviceMuted": [{
61233
61340
  name: "deviceId",
61234
61341
  form: "single",
@@ -62467,6 +62574,7 @@ var SYSTEM_SCOPE_DEVICE_METHODS = [
62467
62574
  "faceGallery.listRecentFaces",
62468
62575
  "networkQuality.getDeviceStats",
62469
62576
  "networkQuality.reportClientStats",
62577
+ "notificationRules.getAlarmSensors",
62470
62578
  "notificationRules.setDeviceMuted",
62471
62579
  "osdManager.clearSlotBinding",
62472
62580
  "osdManager.copyDeviceConfiguration",
@@ -63407,7 +63515,8 @@ function createSystemProxy(api) {
63407
63515
  createSnooze: (input) => dispatch("notificationRules", "createSnooze", "mutation", input),
63408
63516
  cancelSnooze: (input) => dispatch("notificationRules", "cancelSnooze", "mutation", input),
63409
63517
  getAlarmConfig: (input) => dispatch("notificationRules", "getAlarmConfig", "query", input),
63410
- setAlarmConfig: (input) => dispatch("notificationRules", "setAlarmConfig", "mutation", input)
63518
+ setAlarmConfig: (input) => dispatch("notificationRules", "setAlarmConfig", "mutation", input),
63519
+ getAlarmSensors: (input) => dispatch("notificationRules", "getAlarmSensors", "query", input)
63411
63520
  },
63412
63521
  osdManager: {
63413
63522
  getConditionSupport: (input) => dispatch("osdManager", "getConditionSupport", "query", input),
@@ -65442,6 +65551,176 @@ function sensorTransitionNeverFires(rule) {
65442
65551
  /** The warning an editor shows for {@link sensorTransitionNeverFires}. */
65443
65552
  var NC_SENSOR_TRANSITION_NEVER_FIRES_WARNING = "This rule belongs to the alarm, and an alarm rule fires only when an opening OPENS. Set to “only when it clears”, it can never fire.";
65444
65553
  //#endregion
65554
+ //#region src/notification/alarm-settings.ts
65555
+ var NC_ALARM_DELAY_FIELDS = [
65556
+ "exitDelaySec",
65557
+ "entryDelaySec",
65558
+ "triggeredDurationSec"
65559
+ ];
65560
+ /** The mode's value when it overrides the field, else the global one. */
65561
+ function pick(override, global) {
65562
+ return override === void 0 ? {
65563
+ value: global,
65564
+ source: "default"
65565
+ } : {
65566
+ value: override,
65567
+ source: "mode"
65568
+ };
65569
+ }
65570
+ /** What `mode` actually runs on: its own overrides, the global value for every other field. */
65571
+ function resolveModeDelays(settings, mode) {
65572
+ const entry = (settings.modeDelays ?? []).find((e) => e.mode === mode);
65573
+ const exit = pick(entry?.exitDelaySec, settings.exitDelaySec);
65574
+ const entryDelay = pick(entry?.entryDelaySec, settings.entryDelaySec);
65575
+ const triggered = pick(entry?.triggeredDurationSec, settings.triggeredDurationSec);
65576
+ return {
65577
+ exitDelaySec: exit.value,
65578
+ entryDelaySec: entryDelay.value,
65579
+ triggeredDurationSec: triggered.value,
65580
+ source: {
65581
+ exitDelaySec: exit.source,
65582
+ entryDelaySec: entryDelay.source,
65583
+ triggeredDurationSec: triggered.source
65584
+ }
65585
+ };
65586
+ }
65587
+ /** One field of an entry after an edit: number sets, null clears, undefined keeps. */
65588
+ function edited(current, edit) {
65589
+ if (edit === void 0) return current;
65590
+ return edit === null ? void 0 : edit;
65591
+ }
65592
+ /**
65593
+ * Apply per-field edits to the stored overrides. Returns new arrays, never mutates the input;
65594
+ * an entry with no field left is dropped (the mode inherits everything again).
65595
+ */
65596
+ function applyModeDelaysEdits(current, edits) {
65597
+ const out = current.map((e) => ({ ...e }));
65598
+ for (const edit of edits) {
65599
+ const at = out.findIndex((e) => e.mode === edit.mode);
65600
+ const base = at >= 0 ? out[at] ?? { mode: edit.mode } : { mode: edit.mode };
65601
+ const next = { mode: edit.mode };
65602
+ const exit = edited(base.exitDelaySec, edit.exitDelaySec);
65603
+ const entry = edited(base.entryDelaySec, edit.entryDelaySec);
65604
+ const triggered = edited(base.triggeredDurationSec, edit.triggeredDurationSec);
65605
+ if (exit !== void 0) next.exitDelaySec = exit;
65606
+ if (entry !== void 0) next.entryDelaySec = entry;
65607
+ if (triggered !== void 0) next.triggeredDurationSec = triggered;
65608
+ if (at >= 0) out[at] = next;
65609
+ else out.push(next);
65610
+ }
65611
+ return out.filter((e) => e.exitDelaySec !== void 0 || e.entryDelaySec !== void 0 || e.triggeredDurationSec !== void 0);
65612
+ }
65613
+ /**
65614
+ * Put ONE device on, or take it off, ONE mode's list. A no-op answers `changed: false`; an add
65615
+ * to a full list is REFUSED by reason (never silently dropped); an emptied list drops its entry.
65616
+ */
65617
+ function applyNonBlockingEdit(lists, edit) {
65618
+ const copy = lists.map((l) => ({
65619
+ mode: l.mode,
65620
+ deviceIds: [...l.deviceIds]
65621
+ }));
65622
+ const at = copy.findIndex((l) => l.mode === edit.mode);
65623
+ const held = at >= 0 ? copy[at]?.deviceIds ?? [] : [];
65624
+ const present = held.includes(edit.deviceId);
65625
+ if (edit.nonBlocking === present) return {
65626
+ kind: "applied",
65627
+ lists: copy,
65628
+ changed: false
65629
+ };
65630
+ if (edit.nonBlocking) {
65631
+ if (held.length >= 200) return {
65632
+ kind: "refused",
65633
+ reason: "list-full",
65634
+ mode: edit.mode,
65635
+ max: 200
65636
+ };
65637
+ const next = {
65638
+ mode: edit.mode,
65639
+ deviceIds: [...held, edit.deviceId]
65640
+ };
65641
+ if (at >= 0) copy[at] = next;
65642
+ else copy.push(next);
65643
+ } else {
65644
+ const next = {
65645
+ mode: edit.mode,
65646
+ deviceIds: held.filter((id) => id !== edit.deviceId)
65647
+ };
65648
+ if (at >= 0) copy[at] = next;
65649
+ }
65650
+ return {
65651
+ kind: "applied",
65652
+ lists: copy.filter((l) => l.deviceIds.length > 0),
65653
+ changed: true
65654
+ };
65655
+ }
65656
+ function sameSet(a, b) {
65657
+ const sa = new Set(a);
65658
+ const sb = new Set(b);
65659
+ return sa.size === sb.size && [...sa].every((x) => sb.has(x));
65660
+ }
65661
+ /** Per-mode id sets of a lists value, empty lists ignored. */
65662
+ function listsByMode(lists) {
65663
+ const out = /* @__PURE__ */ new Map();
65664
+ for (const l of lists) if (l.deviceIds.length > 0) out.set(l.mode, new Set(l.deviceIds));
65665
+ return out;
65666
+ }
65667
+ function sameLists(a, b) {
65668
+ const ma = listsByMode(a);
65669
+ const mb = listsByMode(b);
65670
+ if (ma.size !== mb.size) return false;
65671
+ for (const [mode, ids] of ma) {
65672
+ const other = mb.get(mode);
65673
+ if (other === void 0 || !sameSet([...ids], [...other])) return false;
65674
+ }
65675
+ return true;
65676
+ }
65677
+ /** The returned entry's value for one field of a mode-delays edit. */
65678
+ function fieldOf(entry, field) {
65679
+ if (entry === void 0) return void 0;
65680
+ switch (field) {
65681
+ case "exitDelaySec": return entry.exitDelaySec;
65682
+ case "entryDelaySec": return entry.entryDelaySec;
65683
+ case "triggeredDurationSec": return entry.triggeredDurationSec;
65684
+ }
65685
+ }
65686
+ /** The edit's value for one field. */
65687
+ function editFieldOf(edit, field) {
65688
+ switch (field) {
65689
+ case "exitDelaySec": return edit.exitDelaySec;
65690
+ case "entryDelaySec": return edit.entryDelaySec;
65691
+ case "triggeredDurationSec": return edit.triggeredDurationSec;
65692
+ }
65693
+ }
65694
+ /**
65695
+ * True iff every key the patch sent is reflected in what the host returned. A host older than
65696
+ * this build strips the keys it does not know; this is how a client tells "saved" from "parsed
65697
+ * and dropped". `announceArm` is ignored (parsed, never read). A `null` clear "lands" on a host
65698
+ * that stripped the key (it lacks the field) — harmless, because such a host stores no overrides.
65699
+ * A whole-list `nonBlocking` naming a mode the panel does not offer reads as "not landed" (the host
65700
+ * drops it); only older clients and the prune send whole lists, and they do not call this.
65701
+ */
65702
+ function alarmPatchLanded(patch, returned) {
65703
+ if (patch.exitDelaySec !== void 0 && patch.exitDelaySec !== returned.exitDelaySec) return false;
65704
+ if (patch.entryDelaySec !== void 0 && patch.entryDelaySec !== returned.entryDelaySec) return false;
65705
+ if (patch.triggeredDurationSec !== void 0 && patch.triggeredDurationSec !== returned.triggeredDurationSec) return false;
65706
+ if (patch.announceTargets !== void 0 && !sameSet(patch.announceTargets, returned.announceTargets)) return false;
65707
+ if (patch.nonBlocking !== void 0 && !sameLists(patch.nonBlocking, returned.nonBlocking ?? [])) return false;
65708
+ for (const edit of patch.modeDelays ?? []) {
65709
+ const entry = (returned.modeDelays ?? []).find((e) => e.mode === edit.mode);
65710
+ for (const field of NC_ALARM_DELAY_FIELDS) {
65711
+ const want = editFieldOf(edit, field);
65712
+ if (want === void 0) continue;
65713
+ const got = fieldOf(entry, field);
65714
+ if (want === null ? got !== void 0 : got !== want) return false;
65715
+ }
65716
+ }
65717
+ if (patch.nonBlockingEdit !== void 0) {
65718
+ const e = patch.nonBlockingEdit;
65719
+ if (((returned.nonBlocking ?? []).find((l) => l.mode === e.mode)?.deviceIds.includes(e.deviceId) ?? false) !== e.nonBlocking) return false;
65720
+ }
65721
+ return true;
65722
+ }
65723
+ //#endregion
65445
65724
  //#region src/notification/sensor-raised.ts
65446
65725
  /**
65447
65726
  * WHICH WAY A BOOLEAN SENSOR MOVED — read off the one slice a sensor event
@@ -67150,6 +67429,35 @@ function readTimelapseGeneratedAt(rule, deviceId) {
67150
67429
  return rule.lastGeneratedAt ?? 0;
67151
67430
  }
67152
67431
  //#endregion
67432
+ //#region src/pipeline/motion-ownership.ts
67433
+ function cameraOwnsMotionViaSensor(motionSources) {
67434
+ return motionSources.some((s) => s !== "analyzer");
67435
+ }
67436
+ //#endregion
67437
+ //#region src/device/hub-motion-read.ts
67438
+ async function readHubMotionDetected(deviceState, deviceId) {
67439
+ let slice;
67440
+ try {
67441
+ slice = await deviceState.getCapSlice.query({
67442
+ deviceId,
67443
+ capName: "motion"
67444
+ });
67445
+ } catch (err) {
67446
+ const reason = err instanceof Error ? err.message : String(err);
67447
+ throw new Error(`motion state of device ${deviceId} is unreadable: ${reason}`, { cause: err });
67448
+ }
67449
+ const detected = slice?.["detected"];
67450
+ if (typeof detected !== "boolean") throw new Error(`motion state of device ${deviceId} is not published yet (unknown)`);
67451
+ return detected;
67452
+ }
67453
+ //#endregion
67454
+ //#region src/pipeline/provider-motion.ts
67455
+ /** The motion event's data without `triggeredBy`: only the bridge names a trigger. */
67456
+ var ProviderMotionDataSchema = MotionOnMotionChangedDataSchema.omit({ triggeredBy: true });
67457
+ function providerMotionEvent(source, data) {
67458
+ return require_sleep.createEvent(require_event_category.EventCategory.ProviderMotion, source, data);
67459
+ }
67460
+ //#endregion
67153
67461
  //#region src/pipeline/step-format-runnable.ts
67154
67462
  /** True when `model` ships a build for `format`. */
67155
67463
  function hasBuild(model, format) {
@@ -68039,8 +68347,8 @@ function bestLocationMatch(externalName, existing, threshold = .8) {
68039
68347
  * So `entry.providerAddonId === this.ctx.id` is silently, permanently false
68040
68348
  * for a builtin — and only for a builtin, which is why it survives a green
68041
68349
  * suite whose fake supplies the bare id. That is exactly how camera 615's
68042
- * virtual doorbell latched `unbound` for twelve hours on 2026-08-07 while its
68043
- * binding was intact ([D72](../../../../docs/decisions/adr-0072.md)).
68350
+ * virtual doorbell (retired since, D671) latched `unbound` for twelve hours on
68351
+ * 2026-08-07 while its binding was intact ([D72](../../../../docs/decisions/adr-0072.md)).
68044
68352
  *
68045
68353
  * Route every comparison between `ctx.id` and a registry/store addon id
68046
68354
  * through {@link isSameAddonId}. `scripts/check-addon-id-comparison.ts`
@@ -69466,12 +69774,16 @@ exports.CameraMetricsSchema = CameraMetricsSchema;
69466
69774
  exports.CameraMetricsWithDeviceIdSchema = CameraMetricsWithDeviceIdSchema;
69467
69775
  exports.CameraMotionStatusSchema = CameraMotionStatusSchema;
69468
69776
  exports.CameraOccupancySnapshotForDeviceSchema = CameraOccupancySnapshotForDeviceSchema;
69777
+ exports.CameraOwnMotionSchema = CameraOwnMotionSchema;
69778
+ exports.CameraRawLevelSchema = CameraRawLevelSchema;
69469
69779
  exports.CameraRecordingModeSchema = CameraRecordingModeSchema;
69470
69780
  exports.CameraRecordingStatusSchema = CameraRecordingStatusSchema;
69471
69781
  exports.CameraSensorAttachmentSchema = CameraSensorAttachmentSchema;
69782
+ exports.CameraSensorEntrySchema = CameraSensorEntrySchema;
69783
+ exports.CameraSensorModeSchema = CameraSensorModeSchema;
69472
69784
  exports.CameraSensorRefSchema = CameraSensorRefSchema;
69473
69785
  exports.CameraSensorsConfigSchema = CameraSensorsConfigSchema;
69474
- exports.CameraSensorsModeSchema = CameraSensorsModeSchema;
69786
+ exports.CameraSensorsNotEnforcedSchema = CameraSensorsNotEnforcedSchema;
69475
69787
  exports.CameraSensorsNotForwardedSchema = CameraSensorsNotForwardedSchema;
69476
69788
  exports.CameraSensorsStatusSchema = CameraSensorsStatusSchema;
69477
69789
  exports.CameraSourceStatusSchema = CameraSourceStatusSchema;
@@ -69611,6 +69923,7 @@ exports.DECLARED_DEVICE_SWEEP_LIMIT = DECLARED_DEVICE_SWEEP_LIMIT;
69611
69923
  exports.DECLARED_INTEGRATION_FIXED_KEY = DECLARED_INTEGRATION_FIXED_KEY;
69612
69924
  exports.DEFAULT_ADDON_PLACEMENT = DEFAULT_ADDON_PLACEMENT;
69613
69925
  exports.DEFAULT_AUDIO_ANALYZER_CONFIG = DEFAULT_AUDIO_ANALYZER_CONFIG;
69926
+ exports.DEFAULT_CAMERA_SENSOR_MODE = DEFAULT_CAMERA_SENSOR_MODE;
69614
69927
  exports.DEFAULT_CLUSTER_STEP_MODELS = DEFAULT_CLUSTER_STEP_MODELS;
69615
69928
  exports.DEFAULT_CLUSTER_STEP_SETTINGS = DEFAULT_CLUSTER_STEP_SETTINGS;
69616
69929
  exports.DEFAULT_DECODER_HWACCEL_CONFIG = DEFAULT_DECODER_HWACCEL_CONFIG;
@@ -69652,7 +69965,6 @@ exports.DISPLAY_ICON_KEYS = DISPLAY_ICON_KEYS;
69652
69965
  exports.DISPLAY_ICON_OFFERED_KEYS = DISPLAY_ICON_OFFERED_KEYS;
69653
69966
  exports.DISPLAY_ICON_VOCABULARY = DISPLAY_ICON_VOCABULARY;
69654
69967
  exports.DOORBELL_RISE_DEBOUNCE_MS = DOORBELL_RISE_DEBOUNCE_MS;
69655
- exports.DOORBELL_SOURCE_SLOT = DOORBELL_SOURCE_SLOT;
69656
69968
  exports.DataStoreEngineInfoSchema = EngineInfoSchema;
69657
69969
  exports.DatabaseSnapshotResultSchema = DatabaseSnapshotResultSchema;
69658
69970
  exports.DatabaseSnapshotTableSchema = DatabaseSnapshotTableSchema;
@@ -69697,7 +70009,6 @@ exports.DiscoveredTargetSchema = DiscoveredTargetSchema;
69697
70009
  exports.DiskReconcileJobSchema = DiskReconcileJobSchema;
69698
70010
  exports.DisposerChain = require_sleep.DisposerChain;
69699
70011
  exports.DoorbellPressEventSchema = DoorbellPressEventSchema;
69700
- exports.DoorbellSourceSlotValueSchema = DoorbellSourceSlotValueSchema;
69701
70012
  exports.DoorbellStatusSchema = DoorbellStatusSchema;
69702
70013
  exports.EMBEDDING_MODEL_FAILED = EMBEDDING_MODEL_FAILED;
69703
70014
  exports.EMBEDDING_REQUIREMENTS_FAILED = EMBEDDING_REQUIREMENTS_FAILED;
@@ -70037,8 +70348,13 @@ exports.NATIVE_LEASE_TILE_BUDGET_KEY = NATIVE_LEASE_TILE_BUDGET_KEY;
70037
70348
  exports.NAVIGATION_ACTION_CATALOG = NAVIGATION_ACTION_CATALOG;
70038
70349
  exports.NAVIGATION_LIGHT_LEVEL_MAX = NAVIGATION_LIGHT_LEVEL_MAX;
70039
70350
  exports.NAVIGATION_LIGHT_LEVEL_MIN = NAVIGATION_LIGHT_LEVEL_MIN;
70351
+ exports.NC_ALARM_DELAY_FIELDS = NC_ALARM_DELAY_FIELDS;
70352
+ exports.NC_ALARM_DELAY_MAX_SEC = NC_ALARM_DELAY_MAX_SEC;
70353
+ exports.NC_ALARM_NONBLOCKING_MAX = NC_ALARM_NONBLOCKING_MAX;
70040
70354
  exports.NC_ALARM_OPENING_EVENT_KINDS = NC_ALARM_OPENING_EVENT_KINDS;
70355
+ exports.NC_ALARM_SENSORS_MAX = NC_ALARM_SENSORS_MAX;
70041
70356
  exports.NC_ALARM_SYSTEM_EVENT_KINDS = NC_ALARM_SYSTEM_EVENT_KINDS;
70357
+ exports.NC_ALARM_TRIGGERED_MAX_SEC = NC_ALARM_TRIGGERED_MAX_SEC;
70042
70358
  exports.NC_AUDIO_CONFIRM_HITS_DEFAULT = NC_AUDIO_CONFIRM_HITS_DEFAULT;
70043
70359
  exports.NC_AUDIO_CONFIRM_HITS_MAX = NC_AUDIO_CONFIRM_HITS_MAX;
70044
70360
  exports.NC_AUDIO_CONFIRM_HITS_MIN = NC_AUDIO_CONFIRM_HITS_MIN;
@@ -70126,6 +70442,13 @@ exports.NavigationRuntimeStateSchema = NavigationRuntimeStateSchema;
70126
70442
  exports.NavigationStatusSchema = NavigationStatusSchema;
70127
70443
  exports.NcAlarmConfigSchema = NcAlarmConfigSchema;
70128
70444
  exports.NcAlarmModeCoverageSchema = NcAlarmModeCoverageSchema;
70445
+ exports.NcAlarmModeDelaysEditSchema = NcAlarmModeDelaysEditSchema;
70446
+ exports.NcAlarmModeDelaysSchema = NcAlarmModeDelaysSchema;
70447
+ exports.NcAlarmNonBlockingEditSchema = NcAlarmNonBlockingEditSchema;
70448
+ exports.NcAlarmSensorReadingSchema = NcAlarmSensorReadingSchema;
70449
+ exports.NcAlarmSensorStateSchema = NcAlarmSensorStateSchema;
70450
+ exports.NcAlarmSensorsInputSchema = NcAlarmSensorsInputSchema;
70451
+ exports.NcAlarmSensorsSchema = NcAlarmSensorsSchema;
70129
70452
  exports.NcAlarmSettingsPatchSchema = NcAlarmSettingsPatchSchema;
70130
70453
  exports.NcAlarmSettingsSchema = NcAlarmSettingsSchema;
70131
70454
  exports.NcAlarmSkipReasonSchema = NcAlarmSkipReasonSchema;
@@ -70290,6 +70613,7 @@ exports.PrivacyMaskStatusSchema = PrivacyMaskStatusSchema;
70290
70613
  exports.ProfileRtspEntrySchema = require_sleep.ProfileRtspEntrySchema;
70291
70614
  exports.ProfileSlotSchema = require_sleep.ProfileSlotSchema;
70292
70615
  exports.ProfileSlotStatusSchema = require_sleep.ProfileSlotStatusSchema;
70616
+ exports.ProviderMotionDataSchema = ProviderMotionDataSchema;
70293
70617
  exports.ProviderStatusSchema = ProviderStatusSchema;
70294
70618
  exports.PtzAutotrackRuntimeStateSchema = PtzAutotrackRuntimeStateSchema;
70295
70619
  exports.PtzAutotrackSettingsSchema = PtzAutotrackSettingsSchema;
@@ -70697,8 +71021,11 @@ exports.addonsCapability = addonsCapability;
70697
71021
  exports.adminUiCapability = require_sleep.adminUiCapability;
70698
71022
  exports.airQualitySensorCapability = airQualitySensorCapability;
70699
71023
  exports.alarmPanelCapability = alarmPanelCapability;
71024
+ exports.alarmPatchLanded = alarmPatchLanded;
70700
71025
  exports.alertsCapability = alertsCapability;
70701
71026
  exports.ambientLightSensorCapability = ambientLightSensorCapability;
71027
+ exports.applyModeDelaysEdits = applyModeDelaysEdits;
71028
+ exports.applyNonBlockingEdit = applyNonBlockingEdit;
70702
71029
  exports.asBoolean = require_sleep.asBoolean;
70703
71030
  exports.asJsonArray = require_sleep.asJsonArray;
70704
71031
  exports.asJsonObject = require_sleep.asJsonObject;
@@ -70745,6 +71072,7 @@ exports.builtCapabilityBlockers = builtCapabilityBlockers;
70745
71072
  exports.buttonCapability = buttonCapability;
70746
71073
  exports.cameraCredentialsCapability = cameraCredentialsCapability;
70747
71074
  exports.cameraGridLayoutCapability = cameraGridLayoutCapability;
71075
+ exports.cameraOwnsMotionViaSensor = cameraOwnsMotionViaSensor;
70748
71076
  exports.cameraPipelineConfigCapability = cameraPipelineConfigCapability;
70749
71077
  exports.cameraSensorRefKey = cameraSensorRefKey;
70750
71078
  exports.cameraStreamsCapability = cameraStreamsCapability;
@@ -71119,6 +71447,7 @@ exports.pressureSensorCapability = pressureSensorCapability;
71119
71447
  exports.principalMayReachAddon = principalMayReachAddon;
71120
71448
  exports.privacyMaskCapability = privacyMaskCapability;
71121
71449
  exports.procedureAuthKey = procedureAuthKey;
71450
+ exports.providerMotionEvent = providerMotionEvent;
71122
71451
  exports.ptzAutotrackCapability = ptzAutotrackCapability;
71123
71452
  exports.ptzCapability = ptzCapability;
71124
71453
  exports.publicEventCategories = require_event_category.publicEventCategories;
@@ -71128,6 +71457,7 @@ exports.readClusterStepModels = readClusterStepModels;
71128
71457
  exports.readClusterStepSettings = readClusterStepSettings;
71129
71458
  exports.readDetailCropConvention = readDetailCropConvention;
71130
71459
  exports.readDeviceStateFrom = readDeviceStateFrom;
71460
+ exports.readHubMotionDetected = readHubMotionDetected;
71131
71461
  exports.readMotionTriggeredBy = readMotionTriggeredBy;
71132
71462
  exports.readNativeLeaseOverride = readNativeLeaseOverride;
71133
71463
  exports.readNodePin = require_sleep.readNodePin;
@@ -71164,6 +71494,7 @@ exports.resolveHydratedFieldValue = require_sleep.resolveHydratedFieldValue;
71164
71494
  exports.resolveLocationIcon = resolveLocationIcon;
71165
71495
  exports.resolveLocationMode = resolveLocationMode;
71166
71496
  exports.resolveMethodAuth = resolveMethodAuth;
71497
+ exports.resolveModeDelays = resolveModeDelays;
71167
71498
  exports.resolveMutate = resolveMutate;
71168
71499
  exports.resolvePoolMemoryPolicy = resolvePoolMemoryPolicy;
71169
71500
  exports.resolveRecordingProfiles = resolveRecordingProfiles;