@camstack/system 1.2.330 → 1.2.332
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.
- package/dist/addon-runner.js +1 -1
- package/dist/addon-runner.mjs +1 -1
- package/dist/builtins/addon-pages-aggregator/addon-pages-aggregator.addon.js +1 -1
- package/dist/builtins/addon-pages-aggregator/addon-pages-aggregator.addon.mjs +1 -1
- package/dist/builtins/addon-widgets-aggregator/addon-widgets-aggregator.addon.js +1 -1
- package/dist/builtins/addon-widgets-aggregator/addon-widgets-aggregator.addon.mjs +1 -1
- package/dist/builtins/alerts/alerts.addon.js +1 -1
- package/dist/builtins/alerts/alerts.addon.mjs +1 -1
- package/dist/builtins/autotrack/index.js +3 -3
- package/dist/builtins/autotrack/index.mjs +3 -3
- package/dist/builtins/backup-orchestrator/backup-orchestrator.addon.js +1 -1
- package/dist/builtins/backup-orchestrator/backup-orchestrator.addon.mjs +1 -1
- package/dist/builtins/camera-grid/index.js +1 -1
- package/dist/builtins/camera-grid/index.mjs +1 -1
- package/dist/builtins/composer/composer.addon.js +27 -8
- package/dist/builtins/composer/composer.addon.mjs +21 -3
- package/dist/builtins/console-logging/index.js +1 -1
- package/dist/builtins/console-logging/index.mjs +1 -1
- package/dist/builtins/core-blocks/core-blocks.addon.js +2 -2
- package/dist/builtins/core-blocks/core-blocks.addon.mjs +2 -2
- package/dist/builtins/device-manager/device-bindings-store.d.ts +7 -0
- package/dist/builtins/device-manager/device-manager.addon.d.ts +3 -0
- package/dist/builtins/device-manager/device-manager.addon.js +130 -3
- package/dist/builtins/device-manager/device-manager.addon.mjs +130 -3
- package/dist/builtins/device-manager/stale-wrapper-activations.d.ts +26 -0
- package/dist/builtins/hub-forwarder/index.js +1 -1
- package/dist/builtins/hub-forwarder/index.mjs +1 -1
- package/dist/builtins/liveness-monitor/liveness-monitor.addon.js +1 -1
- package/dist/builtins/liveness-monitor/liveness-monitor.addon.mjs +1 -1
- package/dist/builtins/local-auth/local-auth.addon.js +1 -1
- package/dist/builtins/local-auth/local-auth.addon.mjs +1 -1
- package/dist/builtins/local-network/local-network.addon.js +1 -1
- package/dist/builtins/local-network/local-network.addon.mjs +1 -1
- package/dist/builtins/loki-logging/index.js +1 -1
- package/dist/builtins/loki-logging/index.mjs +1 -1
- package/dist/builtins/native-metrics/native-metrics.addon.js +1 -1
- package/dist/builtins/native-metrics/native-metrics.addon.mjs +1 -1
- package/dist/builtins/platform-probe/index.js +1 -1
- package/dist/builtins/platform-probe/index.mjs +1 -1
- package/dist/builtins/remote-access-orchestrator/remote-access-orchestrator.addon.js +1 -1
- package/dist/builtins/remote-access-orchestrator/remote-access-orchestrator.addon.mjs +1 -1
- package/dist/builtins/shared/device-state-changed.d.ts +3 -4
- package/dist/builtins/snapshot/index.js +1 -1
- package/dist/builtins/snapshot/index.mjs +1 -1
- package/dist/builtins/sqlite-storage/filesystem-storage.addon.js +1 -1
- package/dist/builtins/sqlite-storage/filesystem-storage.addon.mjs +1 -1
- package/dist/builtins/sqlite-storage/sqlite-settings.addon.js +0 -0
- package/dist/builtins/sqlite-storage/sqlite-settings.addon.mjs +0 -0
- package/dist/builtins/storage-orchestrator/storage-orchestrator.addon.js +1 -1
- package/dist/builtins/storage-orchestrator/storage-orchestrator.addon.mjs +1 -1
- package/dist/builtins/system-config/system-config.addon.js +1 -1
- package/dist/builtins/system-config/system-config.addon.mjs +1 -1
- package/dist/builtins/winston-logging/index.js +1 -1
- package/dist/builtins/winston-logging/index.mjs +1 -1
- package/dist/{child-cap-dispatch-C8uts1P4.js → child-cap-dispatch-93MfsaZL.js} +1 -0
- package/dist/{child-cap-dispatch-C2VINHu1.mjs → child-cap-dispatch-kLIiU1CG.mjs} +1 -0
- package/dist/{composition-sources-Wj2kWund.mjs → composition-sources-BpyaHvoR.mjs} +1 -1
- package/dist/{composition-sources-2XxNEet3.js → composition-sources-DK--XR5V.js} +1 -1
- package/dist/{dist-Dp043AI0.mjs → dist-BEPK2RUO.mjs} +323 -389
- package/dist/{dist-Bx4zxM9N.js → dist-CH3jfPMi.js} +322 -436
- package/dist/index.js +2 -2
- package/dist/index.mjs +2 -2
- package/dist/{retired-settings-keys-DR2WMe5d.js → retired-settings-keys-C5mSevGV.js} +1 -1
- package/dist/{retired-settings-keys-Dxf9vELs.mjs → retired-settings-keys-tDI1g7ab.mjs} +1 -1
- package/package.json +1 -16
- package/dist/builtins/doorbell/binding-mirror.d.ts +0 -110
- package/dist/builtins/doorbell/doorbell-composition-migration.d.ts +0 -47
- package/dist/builtins/doorbell/doorbell-extension-slot.d.ts +0 -67
- package/dist/builtins/doorbell/doorbell-settings.d.ts +0 -58
- package/dist/builtins/doorbell/index.d.ts +0 -2
- package/dist/builtins/doorbell/index.js +0 -8
- package/dist/builtins/doorbell/index.mjs +0 -2
- package/dist/builtins/doorbell/trigger-engine.d.ts +0 -92
- package/dist/builtins/doorbell/virtual-doorbell.addon.d.ts +0 -218
- package/dist/builtins/doorbell/virtual-doorbell.addon.js +0 -1413
- package/dist/builtins/doorbell/virtual-doorbell.addon.mjs +0 -1407
- package/dist/device-state-changed-Bk7cvTnz.js +0 -31
- package/dist/device-state-changed-DoBbkyEI.mjs +0 -20
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { z } from "zod";
|
|
2
2
|
import "node:crypto";
|
|
3
|
-
//#region ../types/dist/event-category-
|
|
3
|
+
//#region ../types/dist/event-category-BGmz_oxW.mjs
|
|
4
4
|
var EventCategory = /* @__PURE__ */ function(EventCategory) {
|
|
5
5
|
EventCategory["SystemBoot"] = "system.boot";
|
|
6
6
|
EventCategory["SystemAddonsReady"] = "system.addons-ready";
|
|
@@ -533,6 +533,15 @@ var EventCategory = /* @__PURE__ */ function(EventCategory) {
|
|
|
533
533
|
*/
|
|
534
534
|
EventCategory["PipelineAudioInferenceResult"] = "pipeline.audio-inference-result";
|
|
535
535
|
EventCategory["DetectionPhaseTransition"] = "detection.phase-transition";
|
|
536
|
+
/**
|
|
537
|
+
* A camera provider's RAW onboard motion push (D673): the `MotionOnMotionChanged`
|
|
538
|
+
* data shape without `triggeredBy`, built by `providerMotionEvent`. Its one
|
|
539
|
+
* consumer is the orchestrator's camera-sensors bridge, which re-emits the
|
|
540
|
+
* camera's EFFECTIVE onboard motion as `MotionOnMotionChanged` (a pass-through
|
|
541
|
+
* for a camera with no attached sensor). Providers must not emit
|
|
542
|
+
* `MotionOnMotionChanged` themselves; `scripts/check-onboard-motion-emitters.ts`
|
|
543
|
+
* keeps it so (camera-grid is a named, deferred exception).
|
|
544
|
+
*/
|
|
536
545
|
EventCategory["ProviderMotion"] = "provider.motion";
|
|
537
546
|
EventCategory["ProviderDetection"] = "provider.detection";
|
|
538
547
|
EventCategory["EnrichmentEmbeddingStored"] = "enrichment.embedding.stored";
|
|
@@ -701,7 +710,7 @@ var EventCategory = /* @__PURE__ */ function(EventCategory) {
|
|
|
701
710
|
return EventCategory;
|
|
702
711
|
}({});
|
|
703
712
|
//#endregion
|
|
704
|
-
//#region ../types/dist/sleep-
|
|
713
|
+
//#region ../types/dist/sleep-CDCONfkt.mjs
|
|
705
714
|
/**
|
|
706
715
|
* The audio chunk plane's byte format, and the ONE expansion from a coded
|
|
707
716
|
* window to float samples (D455).
|
|
@@ -3512,7 +3521,7 @@ function errMsg(err) {
|
|
|
3512
3521
|
return String(err);
|
|
3513
3522
|
}
|
|
3514
3523
|
//#endregion
|
|
3515
|
-
//#region ../types/dist/composition-
|
|
3524
|
+
//#region ../types/dist/composition-43aqsZQj.mjs
|
|
3516
3525
|
var AUDIO_ENCODER_BY_CODEC = {
|
|
3517
3526
|
opus: "libopus",
|
|
3518
3527
|
aac: "aac",
|
|
@@ -3961,13 +3970,12 @@ portable("linux64"), portable("linuxarm64"), portable("macarm64"), portable("mac
|
|
|
3961
3970
|
* LA tabella "quale booleano di questo tipo di device conta come ALTO", e il
|
|
3962
3971
|
* valutatore puro del suo FRONTE.
|
|
3963
3972
|
*
|
|
3964
|
-
*
|
|
3965
|
-
*
|
|
3966
|
-
*
|
|
3967
|
-
*
|
|
3968
|
-
*
|
|
3969
|
-
* fa suonare il campanello ma non registra" — è esattamente D62.
|
|
3970
|
-
* SPOSTA qui e il doorbell la ri-esporta.
|
|
3973
|
+
* UNA tabella per tutti quelli che chiedono "questo device è ALTO?": il
|
|
3974
|
+
* trigger `RecordingTriggers.sensorDeviceIds` del recorder, i marker dei
|
|
3975
|
+
* sensori della post-analysis, il bridge camera-sensors dell'orchestratore e
|
|
3976
|
+
* le sorgenti di un campanello composto (`doorbellFeatureSources`, D671).
|
|
3977
|
+
* Una seconda copia divergerebbe alla prima cap aggiunta, e il sintomo — "il
|
|
3978
|
+
* sensore fa suonare il campanello ma non registra" — è esattamente D62.
|
|
3971
3979
|
*
|
|
3972
3980
|
* ⚠ NON è `DEVICE_STATE_READERS` (`catalogs/device-state-vocabulary.ts`), e le
|
|
3973
3981
|
* due non vanno unificate: quella risponde a "qual è la PAROLA di stato per una
|
|
@@ -3994,53 +4002,6 @@ var SOURCE_CAP_ACTIVE_FIELD = {
|
|
|
3994
4002
|
tamper: "tampered"
|
|
3995
4003
|
};
|
|
3996
4004
|
/**
|
|
3997
|
-
* The same caps → the slice field carrying the ms-epoch timestamp of the
|
|
3998
|
-
* last transition. Every source cap MUST appear here (guarded by a spec):
|
|
3999
|
-
* without a transition timestamp the evaluator cannot tell a genuine rise
|
|
4000
|
-
* from a boot-time hydration when the FIRST slice it ever sees is already
|
|
4001
|
-
* active, and errs towards silence — swallowing the rise.
|
|
4002
|
-
*
|
|
4003
|
-
* These timestamps are UPSTREAM ones, not ingest ones: the Home Assistant
|
|
4004
|
-
* provider derives them from `state.last_changed`, so they survive our own
|
|
4005
|
-
* restarts and correctly read as "hours ago" for a state that has been
|
|
4006
|
-
* active for hours. `motion` names its rise timestamp `lastDetectedAt`.
|
|
4007
|
-
*/
|
|
4008
|
-
var SOURCE_CAP_CHANGED_AT_FIELD = {
|
|
4009
|
-
contact: "lastChangedAt",
|
|
4010
|
-
binary: "lastChangedAt",
|
|
4011
|
-
switch: "lastChangedAt",
|
|
4012
|
-
motion: "lastDetectedAt",
|
|
4013
|
-
flood: "lastChangedAt",
|
|
4014
|
-
gas: "lastChangedAt",
|
|
4015
|
-
smoke: "lastChangedAt",
|
|
4016
|
-
"carbon-monoxide": "lastChangedAt",
|
|
4017
|
-
vibration: "lastChangedAt",
|
|
4018
|
-
tamper: "lastChangedAt"
|
|
4019
|
-
};
|
|
4020
|
-
/** Cap names whose presence in a device's bindings qualify it as a source. */
|
|
4021
|
-
var SOURCE_CAPS = Object.keys(SOURCE_CAP_ACTIVE_FIELD);
|
|
4022
|
-
/** True when a cap is a recognised binary/switch source. */
|
|
4023
|
-
function isSourceCap(capName) {
|
|
4024
|
-
return Object.prototype.hasOwnProperty.call(SOURCE_CAP_ACTIVE_FIELD, capName);
|
|
4025
|
-
}
|
|
4026
|
-
/** Extract the "active" boolean a source cap's slice carries, or null when
|
|
4027
|
-
* the cap is unknown or the field is missing / non-boolean. */
|
|
4028
|
-
function sliceActiveValue(capName, slice) {
|
|
4029
|
-
const field = SOURCE_CAP_ACTIVE_FIELD[capName];
|
|
4030
|
-
if (field === void 0) return null;
|
|
4031
|
-
const raw = slice[field];
|
|
4032
|
-
return typeof raw === "boolean" ? raw : null;
|
|
4033
|
-
}
|
|
4034
|
-
/** Ms-epoch transition timestamp a source cap's slice carries, or null when
|
|
4035
|
-
* it is absent, non-numeric or the zero "never observed" sentinel. */
|
|
4036
|
-
function sliceChangedAt(capName, slice) {
|
|
4037
|
-
const field = SOURCE_CAP_CHANGED_AT_FIELD[capName];
|
|
4038
|
-
if (field === void 0) return null;
|
|
4039
|
-
const raw = slice[field];
|
|
4040
|
-
if (typeof raw !== "number" || !Number.isFinite(raw) || raw <= 0) return null;
|
|
4041
|
-
return raw;
|
|
4042
|
-
}
|
|
4043
|
-
/**
|
|
4044
4005
|
* How recent a source's own transition timestamp must be for a FIRST
|
|
4045
4006
|
* sighting that is already active to count as a genuine rise rather than a
|
|
4046
4007
|
* hydration of long-standing state.
|
|
@@ -4066,65 +4027,6 @@ function evaluateSensorLevelEdge(input) {
|
|
|
4066
4027
|
};
|
|
4067
4028
|
}
|
|
4068
4029
|
/**
|
|
4069
|
-
* IL fronte. Puro: nessun orologio proprio, nessuna memoria — il chiamante
|
|
4070
|
-
* porta `prior`, `nowMs` e il proprio `startedAtMs`.
|
|
4071
|
-
*
|
|
4072
|
-
* Il caso della PRIMA slice già attiva è trattato esplicitamente e vale come
|
|
4073
|
-
* fronte solo se il timestamp UPSTREAM della transizione è posteriore a
|
|
4074
|
-
* `startedAtMs` **e** entro `firstSightingFreshnessMs`. Entrambe le metà
|
|
4075
|
-
* servono: la sola freschezza scatterebbe su un'idratazione al boot di uno
|
|
4076
|
-
* stato flippato pochi secondi prima del riavvio, e il solo "dopo che abbiamo
|
|
4077
|
-
* iniziato" scatterebbe, su un processo di lunga vita, per una sorgente
|
|
4078
|
-
* adottata oggi il cui stato è cambiato ieri. Il caso ambiguo ERRA VERSO IL
|
|
4079
|
-
* SILENZIO e lo dichiara (`baseline-seeded-stale-active`).
|
|
4080
|
-
*/
|
|
4081
|
-
function evaluateSensorEdge(input) {
|
|
4082
|
-
const value = sliceActiveValue(input.capName, input.slice);
|
|
4083
|
-
if (value === null) return {
|
|
4084
|
-
edge: "none",
|
|
4085
|
-
value: null,
|
|
4086
|
-
reason: isSourceCap(input.capName) ? "non-boolean-value" : "unknown-cap"
|
|
4087
|
-
};
|
|
4088
|
-
if (evaluateSensorLevelEdge({
|
|
4089
|
-
level: value,
|
|
4090
|
-
changedAt: sliceChangedAt(input.capName, input.slice),
|
|
4091
|
-
priorLevel: input.prior,
|
|
4092
|
-
startedAtMs: input.startedAtMs,
|
|
4093
|
-
nowMs: input.nowMs,
|
|
4094
|
-
firstSightingFreshnessMs: input.firstSightingFreshnessMs
|
|
4095
|
-
}).kind === "rise") return {
|
|
4096
|
-
edge: "rising",
|
|
4097
|
-
value: true
|
|
4098
|
-
};
|
|
4099
|
-
if (input.prior === void 0) {
|
|
4100
|
-
if (!value) return {
|
|
4101
|
-
edge: "none",
|
|
4102
|
-
value,
|
|
4103
|
-
reason: "baseline-seeded-inactive"
|
|
4104
|
-
};
|
|
4105
|
-
return {
|
|
4106
|
-
edge: "none",
|
|
4107
|
-
value,
|
|
4108
|
-
reason: "baseline-seeded-stale-active"
|
|
4109
|
-
};
|
|
4110
|
-
}
|
|
4111
|
-
if (input.prior === value) return {
|
|
4112
|
-
edge: "none",
|
|
4113
|
-
value,
|
|
4114
|
-
reason: "no-change"
|
|
4115
|
-
};
|
|
4116
|
-
if (!value) return {
|
|
4117
|
-
edge: "none",
|
|
4118
|
-
value,
|
|
4119
|
-
reason: "falling-edge"
|
|
4120
|
-
};
|
|
4121
|
-
return {
|
|
4122
|
-
edge: "none",
|
|
4123
|
-
value,
|
|
4124
|
-
reason: "missing-timestamp"
|
|
4125
|
-
};
|
|
4126
|
-
}
|
|
4127
|
-
/**
|
|
4128
4030
|
* Error types for the safe expression engine. Two distinct classes so callers
|
|
4129
4031
|
* can tell a compile-time (grammar) failure from a runtime (evaluation)
|
|
4130
4032
|
* failure — both are non-fatal to the host: read paths degrade to "skip link".
|
|
@@ -6370,7 +6272,7 @@ var RecordingTriggersSchema = z.object({
|
|
|
6370
6272
|
*
|
|
6371
6273
|
* Cosa vuol dire "alto" dipende dal TIPO di device e non è deciso qui:
|
|
6372
6274
|
* `SOURCE_CAP_ACTIVE_FIELD` (`catalogs/sensor-active-state.ts`) è LA tabella,
|
|
6373
|
-
* la stessa
|
|
6275
|
+
* la stessa del campanello composto (D671). Ed è il FRONTE, non
|
|
6374
6276
|
* il livello: un contatto trovato già aperto al riavvio del runner non fa
|
|
6375
6277
|
* registrare.
|
|
6376
6278
|
*/
|
|
@@ -16056,8 +15958,8 @@ var deviceManagerCapability = {
|
|
|
16056
15958
|
* (`value` / `missing` / `failed`, see {@link WrapperActivationReadSchema}).
|
|
16057
15959
|
*
|
|
16058
15960
|
* The narrow read of the durable authority behind `getBindings`: a
|
|
16059
|
-
* consumer that must know what the operator PERSISTED (
|
|
16060
|
-
*
|
|
15961
|
+
* consumer that must know what the operator PERSISTED (before it drops
|
|
15962
|
+
* work on the strength of an unbind) asks this instead of pulling device-manager's
|
|
16061
15963
|
* whole addon store through `addonSettingsRaw.getGlobal` — which answered
|
|
16062
15964
|
* `{}` on every isolated-engine hub and so never worked (D675). It reads
|
|
16063
15965
|
* ONE row (the activation map, ~1.6 KB), never the ~625 KB store.
|
|
@@ -16347,120 +16249,14 @@ var deviceManagerCapability = {
|
|
|
16347
16249
|
}), z.record(z.string(), z.record(z.string(), z.unknown().nullable())))
|
|
16348
16250
|
}
|
|
16349
16251
|
};
|
|
16350
|
-
|
|
16351
|
-
|
|
16352
|
-
|
|
16353
|
-
|
|
16354
|
-
|
|
16355
|
-
|
|
16356
|
-
* `DeviceType.Button` accessory with `role: DeviceRole.Doorbell`,
|
|
16357
|
-
* or directly on the camera (Reolink registers at camera level).
|
|
16358
|
-
* Emits an `onPressed` event every time the firmware pushes a
|
|
16359
|
-
* ring; status tracks the last press and a pressCount since start
|
|
16360
|
-
* (diagnostic).
|
|
16361
|
-
*
|
|
16362
|
-
* - **Wrapper** provider: the `virtual-doorbell` system builtin
|
|
16363
|
-
* (`@camstack/system/builtins/doorbell`). Turns ANY binary-ish
|
|
16364
|
-
* device (contact / switch / event-emitter …) into a doorbell for
|
|
16365
|
-
* a camera. `defaultActive: false` — the operator explicitly binds
|
|
16366
|
-
* it per camera in the device-bindings UI, then picks the source
|
|
16367
|
-
* device + trigger in the per-device settings.
|
|
16368
|
-
*
|
|
16369
|
-
* The DeviceEventPropagator re-emits `onPressed` on the camera parent
|
|
16370
|
-
* — subscribers listening at the camera level receive ring events
|
|
16371
|
-
* with `via[]` populated. No code on the parent needed.
|
|
16372
|
-
*/
|
|
16373
|
-
var DoorbellStatusSchema = z.object({
|
|
16374
|
-
/** Ms epoch of the last press. null = never observed since this provider started. */
|
|
16375
|
-
lastPressedAt: z.number().nullable(),
|
|
16376
|
-
/** Counter since provider start. Resets on reboot. Useful for metrics/debug. */
|
|
16377
|
-
pressCountSinceStart: z.number()
|
|
16378
|
-
});
|
|
16379
|
-
var DoorbellPressEventSchema = z.object({
|
|
16380
|
-
deviceId: z.number(),
|
|
16381
|
-
timestamp: z.number()
|
|
16382
|
-
});
|
|
16383
|
-
/**
|
|
16384
|
-
* The `doorbell-source` extension slot's editable value (D648): the camera's
|
|
16385
|
-
* virtual-doorbell trigger devices, exactly what the wrapper's
|
|
16386
|
-
* `doorbellSources` persists (as `{ deviceId }` records).
|
|
16387
|
-
*/
|
|
16388
|
-
var DoorbellSourceSlotValueSchema = z.object({ deviceIds: z.array(z.number().int().positive()) });
|
|
16389
|
-
/**
|
|
16390
|
-
* The `doorbell-source` slot — which devices ring this camera's VIRTUAL
|
|
16391
|
-
* doorbell, owned by the `virtual-doorbell` wrapper over its
|
|
16392
|
-
* `doorbellSources` store (D648). A source rings when one of its
|
|
16393
|
-
* `SOURCE_CAPS` rises. Whether the wrapper is bound to the camera at all is a
|
|
16394
|
-
* different authority (`deviceManager.setWrapperActive`, D62) — the slot
|
|
16395
|
-
* reports it, it never writes it.
|
|
16396
|
-
*/
|
|
16397
|
-
var DOORBELL_SOURCE_SLOT = {
|
|
16398
|
-
id: "doorbell-source",
|
|
16399
|
-
label: "Doorbell trigger devices",
|
|
16400
|
-
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.",
|
|
16401
|
-
shape: "association",
|
|
16402
|
-
hostDeviceTypes: [DeviceType.Camera],
|
|
16403
|
-
sourceCaps: SOURCE_CAPS,
|
|
16404
|
-
cardinality: "many",
|
|
16405
|
-
value: DoorbellSourceSlotValueSchema
|
|
16406
|
-
};
|
|
16407
|
-
var doorbellCapability = {
|
|
16408
|
-
name: "doorbell",
|
|
16409
|
-
scope: "device",
|
|
16410
|
-
deviceNative: true,
|
|
16411
|
-
mode: "singleton",
|
|
16412
|
-
kind: "wrapper",
|
|
16413
|
-
defaultActive: false,
|
|
16414
|
-
deviceTypes: [DeviceType.Button, DeviceType.Camera],
|
|
16415
|
-
extensionSlots: [DOORBELL_SOURCE_SLOT],
|
|
16416
|
-
methods: {},
|
|
16417
|
-
events: {
|
|
16418
|
-
/**
|
|
16419
|
-
* Fires once per physical press. Reolink delivers via Baichuan
|
|
16420
|
-
* push (`ReolinkSimpleEvent.type === 'doorbell'`). There is no
|
|
16421
|
-
* release/duration — it's a pulse.
|
|
16422
|
-
*/
|
|
16423
|
-
onPressed: {
|
|
16424
|
-
data: DoorbellPressEventSchema,
|
|
16425
|
-
fromState: {
|
|
16426
|
-
field: "lastPressedAt",
|
|
16427
|
-
on: "advance"
|
|
16428
|
-
}
|
|
16429
|
-
} },
|
|
16430
|
-
status: {
|
|
16431
|
-
schema: DoorbellStatusSchema,
|
|
16432
|
-
kind: "push"
|
|
16433
|
-
},
|
|
16434
|
-
/**
|
|
16435
|
-
* Runtime-state slice — last press timestamp + lifetime press count.
|
|
16436
|
-
* Mirrored by the kernel and readable via
|
|
16437
|
-
* `device.state.doorbell.value`. UIs can show "last ring 5m ago"
|
|
16438
|
-
* without subscribing.
|
|
16439
|
-
*/
|
|
16440
|
-
runtimeState: DoorbellStatusSchema,
|
|
16441
|
-
/**
|
|
16442
|
-
* 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.
|
|
16443
|
-
*
|
|
16444
|
-
* See `RuntimeStateDurability`. Enforced by
|
|
16445
|
-
* `scripts/check-runtime-state-durability.ts`.
|
|
16446
|
-
*/
|
|
16447
|
-
durability: "restored"
|
|
16448
|
-
};
|
|
16449
|
-
var ExtensionSlotIdSchema = z.enum(["doorbell-source", "linked-devices"]);
|
|
16450
|
-
var EXTENSION_SLOTS = {
|
|
16451
|
-
"doorbell-source": {
|
|
16452
|
-
descriptor: DOORBELL_SOURCE_SLOT,
|
|
16453
|
-
declaringCap: "doorbell",
|
|
16454
|
-
hostDeviceTypes: [DeviceType.Camera]
|
|
16455
|
-
},
|
|
16456
|
-
"linked-devices": {
|
|
16457
|
-
descriptor: LINKED_DEVICES_SLOT,
|
|
16458
|
-
declaringCap: "device-manager",
|
|
16459
|
-
hostDeviceTypes: [DeviceType.Camera]
|
|
16460
|
-
}
|
|
16461
|
-
};
|
|
16252
|
+
var ExtensionSlotIdSchema = z.enum(["linked-devices"]);
|
|
16253
|
+
var EXTENSION_SLOTS = { "linked-devices": {
|
|
16254
|
+
descriptor: LINKED_DEVICES_SLOT,
|
|
16255
|
+
declaringCap: "device-manager",
|
|
16256
|
+
hostDeviceTypes: [DeviceType.Camera]
|
|
16257
|
+
} };
|
|
16462
16258
|
/** A slot's editable value, discriminated on `slot`. */
|
|
16463
|
-
var ExtensionSlotValueSchema = z.discriminatedUnion("slot", [
|
|
16259
|
+
var ExtensionSlotValueSchema = z.discriminatedUnion("slot", [LinkedDevicesSlotValueSchema.extend({ slot: z.literal("linked-devices") })]);
|
|
16464
16260
|
/** Every device type at least one slot is offered on — `device-extension`'s `deviceTypes`. */
|
|
16465
16261
|
var EXTENSION_HOST_DEVICE_TYPES = [DeviceType.Camera];
|
|
16466
16262
|
var ExtensionSourceAvailabilitySchema = z.discriminatedUnion("state", [z.object({ state: z.literal("ok") }), z.object({
|
|
@@ -16498,10 +16294,11 @@ var ExtensionSlotSourceSchema = z.object({
|
|
|
16498
16294
|
});
|
|
16499
16295
|
/**
|
|
16500
16296
|
* A DIFFERENT authority that gates whether the slot's sources do anything —
|
|
16501
|
-
* reported read-only, named, never written through this contract (D62).
|
|
16502
|
-
*
|
|
16503
|
-
*
|
|
16504
|
-
* `unknown` means the gate could
|
|
16297
|
+
* reported read-only, named, never written through this contract (D62) — e.g.
|
|
16298
|
+
* a slot whose sources act only while a wrapper is bound to the host, a
|
|
16299
|
+
* binding that belongs to `deviceManager.setWrapperActive`. No slot reports
|
|
16300
|
+
* one today (`linked-devices` answers `null`). `unknown` means the gate could
|
|
16301
|
+
* not be read; it is not "inactive" (D315).
|
|
16505
16302
|
*/
|
|
16506
16303
|
var ExtensionSlotActivationSchema = z.object({
|
|
16507
16304
|
state: z.enum([
|
|
@@ -16518,7 +16315,7 @@ var ExtensionSlotStateSchema = z.object({
|
|
|
16518
16315
|
/** `<source>:<slotId>` — the routing key for `listCandidates` / `setSlot`. */
|
|
16519
16316
|
slotRef: z.string(),
|
|
16520
16317
|
slot: ExtensionSlotIdSchema,
|
|
16521
|
-
/** Names the store written (D62), e.g. `
|
|
16318
|
+
/** Names the store written (D62), e.g. `device-manager:_linkedDeviceIds`. */
|
|
16522
16319
|
authority: z.string(),
|
|
16523
16320
|
activation: ExtensionSlotActivationSchema.nullable(),
|
|
16524
16321
|
value: ExtensionSlotValueSchema,
|
|
@@ -16712,8 +16509,8 @@ var deviceStateCapability = {
|
|
|
16712
16509
|
* Canonical cross-layer WRITE for one cap-keyed slice. Used by
|
|
16713
16510
|
* everyone who needs to publish runtime state for a device:
|
|
16714
16511
|
* device providers (via `BaseDevice.runtimeState.setCapState`
|
|
16715
|
-
* which delegates here), system-scope addons (e.g. the
|
|
16716
|
-
*
|
|
16512
|
+
* which delegates here), system-scope addons (e.g. the orchestrator
|
|
16513
|
+
* writing a camera's effective `motion` slice, D696), and
|
|
16717
16514
|
* direct cap-router callers in tests.
|
|
16718
16515
|
*
|
|
16719
16516
|
* Behavior on the hub:
|
|
@@ -21599,6 +21396,37 @@ z.object({
|
|
|
21599
21396
|
firstAt: z.number(),
|
|
21600
21397
|
lastAt: z.number()
|
|
21601
21398
|
});
|
|
21399
|
+
var NC_ALARM_TRIGGERED_MAX_SEC = 3600;
|
|
21400
|
+
var NcAlarmDelaySecSchema = z.number().int().min(0).max(600);
|
|
21401
|
+
var NcAlarmTriggeredSecSchema = z.number().int().min(0).max(NC_ALARM_TRIGGERED_MAX_SEC);
|
|
21402
|
+
var uniqueModes = (entries) => new Set(entries.map((e) => e.mode)).size === entries.length;
|
|
21403
|
+
/** One mode's OVERRIDES. An absent field inherits the global value (D697). */
|
|
21404
|
+
var NcAlarmModeDelaysSchema = z.object({
|
|
21405
|
+
mode: AlarmArmModeSchema,
|
|
21406
|
+
exitDelaySec: NcAlarmDelaySecSchema.optional(),
|
|
21407
|
+
entryDelaySec: NcAlarmDelaySecSchema.optional(),
|
|
21408
|
+
triggeredDurationSec: NcAlarmTriggeredSecSchema.optional()
|
|
21409
|
+
});
|
|
21410
|
+
var NcAlarmModeDelaysListSchema = z.array(NcAlarmModeDelaysSchema).max(8).refine(uniqueModes, { message: "modeDelays: at most one entry per arm mode" });
|
|
21411
|
+
/**
|
|
21412
|
+
* One mode's EDIT in a patch: a number sets the override, `null` removes it (the mode inherits
|
|
21413
|
+
* again), an absent field leaves it alone. Per field, so two editors changing two different
|
|
21414
|
+
* delays of one mode never undo each other.
|
|
21415
|
+
*/
|
|
21416
|
+
var NcAlarmModeDelaysEditSchema = z.object({
|
|
21417
|
+
mode: AlarmArmModeSchema,
|
|
21418
|
+
exitDelaySec: NcAlarmDelaySecSchema.nullable().optional(),
|
|
21419
|
+
entryDelaySec: NcAlarmDelaySecSchema.nullable().optional(),
|
|
21420
|
+
triggeredDurationSec: NcAlarmTriggeredSecSchema.nullable().optional()
|
|
21421
|
+
});
|
|
21422
|
+
var NcAlarmModeDelaysEditListSchema = z.array(NcAlarmModeDelaysEditSchema).max(8).refine(uniqueModes, { message: "modeDelays: at most one edit per arm mode" });
|
|
21423
|
+
/** One switch of the alarm table: put ONE device on, or take it off, ONE mode's list. */
|
|
21424
|
+
var NcAlarmNonBlockingEditSchema = z.object({
|
|
21425
|
+
mode: AlarmArmModeSchema,
|
|
21426
|
+
deviceId: z.number().int().positive(),
|
|
21427
|
+
/** true = on the list (may be open, does not block); false = off the list (blocks). */
|
|
21428
|
+
nonBlocking: z.boolean()
|
|
21429
|
+
});
|
|
21602
21430
|
/**
|
|
21603
21431
|
* One arm mode's non-blocking list: devices that may be open when that mode
|
|
21604
21432
|
* arms, without the arm being refused.
|
|
@@ -21612,10 +21440,10 @@ var NcAlarmNonBlockingSchema = z.object({
|
|
|
21612
21440
|
* meaning a reader could agree on (union? the last one?), so they are refused
|
|
21613
21441
|
* at the boundary rather than interpreted.
|
|
21614
21442
|
*/
|
|
21615
|
-
var NcAlarmNonBlockingListSchema = z.array(NcAlarmNonBlockingSchema).max(8).refine(
|
|
21443
|
+
var NcAlarmNonBlockingListSchema = z.array(NcAlarmNonBlockingSchema).max(8).refine(uniqueModes, { message: "nonBlocking: at most one list per arm mode" });
|
|
21616
21444
|
/**
|
|
21617
|
-
* The three durations
|
|
21618
|
-
* transitions, and which openings each mode tolerates.
|
|
21445
|
+
* The three durations — global, and per mode since D697 — the panel's state
|
|
21446
|
+
* machine runs on, who hears about its transitions, and which openings each mode tolerates.
|
|
21619
21447
|
*
|
|
21620
21448
|
* They live on the NOTIFICATION-RULES cap, not on `alarm-panel`, on purpose:
|
|
21621
21449
|
* `alarm-panel` is `deviceNative` and its other provider mirrors somebody
|
|
@@ -21625,15 +21453,15 @@ var NcAlarmNonBlockingListSchema = z.array(NcAlarmNonBlockingSchema).max(8).refi
|
|
|
21625
21453
|
*/
|
|
21626
21454
|
var NcAlarmSettingsSchema = z.object({
|
|
21627
21455
|
/** Grace period between arming and the mode taking effect. 0 = immediate. */
|
|
21628
|
-
exitDelaySec:
|
|
21456
|
+
exitDelaySec: NcAlarmDelaySecSchema,
|
|
21629
21457
|
/** Grace period between a trigger and the alarm firing. 0 = immediate. */
|
|
21630
|
-
entryDelaySec:
|
|
21458
|
+
entryDelaySec: NcAlarmDelaySecSchema,
|
|
21631
21459
|
/**
|
|
21632
21460
|
* How long `triggered` lasts before the panel re-arms itself.
|
|
21633
21461
|
* **0 = until an operator disarms it** — the behaviour before this field
|
|
21634
21462
|
* existed, and therefore what an untouched install keeps doing.
|
|
21635
21463
|
*/
|
|
21636
|
-
triggeredDurationSec:
|
|
21464
|
+
triggeredDurationSec: NcAlarmTriggeredSecSchema,
|
|
21637
21465
|
/**
|
|
21638
21466
|
* Deprecated by D630 — every transition is announced. Parsed, never read;
|
|
21639
21467
|
* remove after one release. Optional so an older admin's patch (which still
|
|
@@ -21656,17 +21484,30 @@ var NcAlarmSettingsSchema = z.object({
|
|
|
21656
21484
|
* per mode is meaningful. Defaulted to `[]` so a blob stored before D630
|
|
21657
21485
|
* parses as "every opening blocks" — the behaviour it was written under.
|
|
21658
21486
|
*/
|
|
21659
|
-
nonBlocking: NcAlarmNonBlockingListSchema.default([])
|
|
21487
|
+
nonBlocking: NcAlarmNonBlockingListSchema.default([]),
|
|
21488
|
+
/**
|
|
21489
|
+
* Per arm mode, the delays that mode OVERRIDES (D697). A mode with no entry, or an entry
|
|
21490
|
+
* without a field, uses the global value above — so `[]`, the default, is exactly the
|
|
21491
|
+
* behaviour of a blob stored before this field existed. Read through `resolveModeDelays`.
|
|
21492
|
+
*/
|
|
21493
|
+
modeDelays: NcAlarmModeDelaysListSchema.default([])
|
|
21660
21494
|
});
|
|
21661
21495
|
/**
|
|
21662
21496
|
* Every field optional — a tab edits one control at a time.
|
|
21663
21497
|
*
|
|
21664
|
-
* `nonBlocking`
|
|
21665
|
-
* remove an inner `.default()`, so a patch that never
|
|
21666
|
-
* parse to `
|
|
21667
|
-
* (the same trap {@link NcRulePatchSchema} documents).
|
|
21498
|
+
* `nonBlocking` and `modeDelays` are re-declared WITHOUT their defaults:
|
|
21499
|
+
* `.partial()` does not remove an inner `.default()`, so a patch that never
|
|
21500
|
+
* named the field would parse to `[]` and wipe every mode's list on an
|
|
21501
|
+
* unrelated edit (the same trap {@link NcRulePatchSchema} documents). Here
|
|
21502
|
+
* `modeDelays` means EDITS, not the stored overrides.
|
|
21668
21503
|
*/
|
|
21669
|
-
var NcAlarmSettingsPatchSchema = NcAlarmSettingsSchema.extend({
|
|
21504
|
+
var NcAlarmSettingsPatchSchema = NcAlarmSettingsSchema.extend({
|
|
21505
|
+
nonBlocking: NcAlarmNonBlockingListSchema,
|
|
21506
|
+
/** Per-mode, per-field edits — NOT the whole list (see NcAlarmModeDelaysEditSchema). */
|
|
21507
|
+
modeDelays: NcAlarmModeDelaysEditListSchema,
|
|
21508
|
+
/** ONE membership change; the panel applies it to the list it holds at its turn. */
|
|
21509
|
+
nonBlockingEdit: NcAlarmNonBlockingEditSchema
|
|
21510
|
+
}).partial().refine((p) => p.nonBlocking === void 0 || p.nonBlockingEdit === void 0, { message: "nonBlocking and nonBlockingEdit are exclusive — send the whole lists or one edit" });
|
|
21670
21511
|
/**
|
|
21671
21512
|
* What one arm mode actually arms, DERIVED from the enabled rules gated on it.
|
|
21672
21513
|
* Never authored, never stored — see `alarm-mode-coverage.ts` for why a stored
|
|
@@ -21766,6 +21607,28 @@ var NcAlarmConfigSchema = z.object({
|
|
|
21766
21607
|
*/
|
|
21767
21608
|
live: NcAlarmLiveSchema.optional()
|
|
21768
21609
|
});
|
|
21610
|
+
var NcAlarmSensorReadingSchema = z.enum([
|
|
21611
|
+
"open",
|
|
21612
|
+
"closed",
|
|
21613
|
+
"unknown",
|
|
21614
|
+
"not-opening"
|
|
21615
|
+
]);
|
|
21616
|
+
/** One device's state as the alarm reads it — the classifier the arm check uses. */
|
|
21617
|
+
var NcAlarmSensorStateSchema = z.object({
|
|
21618
|
+
deviceId: z.number().int().positive(),
|
|
21619
|
+
reading: NcAlarmSensorReadingSchema,
|
|
21620
|
+
/** The word as read (`open`, `closed`, `unlocked`, `stopped`, …); null when unknown / not an opening. */
|
|
21621
|
+
state: z.string().nullable(),
|
|
21622
|
+
/** Why `unknown`: the read failed, or the slice holds no word its cap defines (a placeholder included). */
|
|
21623
|
+
unknownWhy: z.enum(["read-failed", "unknown-word"]).nullable(),
|
|
21624
|
+
/** The device manager's liveness as the centre mirrors it; null = not known. */
|
|
21625
|
+
online: z.boolean().nullable()
|
|
21626
|
+
});
|
|
21627
|
+
var NcAlarmSensorsInputSchema = z.object({ deviceIds: z.array(z.number().int().positive()).max(500) });
|
|
21628
|
+
var NcAlarmSensorsSchema = z.object({
|
|
21629
|
+
sensors: z.array(NcAlarmSensorStateSchema),
|
|
21630
|
+
readAt: z.number().int().nonnegative()
|
|
21631
|
+
});
|
|
21769
21632
|
/**
|
|
21770
21633
|
* ONE rule's demand on ONE camera's clip ring.
|
|
21771
21634
|
*
|
|
@@ -22007,8 +21870,9 @@ var notificationRulesCapability = {
|
|
|
22007
21870
|
*/
|
|
22008
21871
|
getAlarmConfig: method(z.object({}), NcAlarmConfigSchema, { auth: "admin" }),
|
|
22009
21872
|
/**
|
|
22010
|
-
* Patch the settings (durations
|
|
22011
|
-
*
|
|
21873
|
+
* Patch the settings (durations — global and per mode —, recipients,
|
|
21874
|
+
* per-mode non-blocking lists or one membership edit; `announceArm` is
|
|
21875
|
+
* accepted and ignored — D630). Returns the WHOLE config,
|
|
22012
21876
|
* coverage and `live` included, so a
|
|
22013
21877
|
* client never has to guess what the server settled on — the panel clamps
|
|
22014
21878
|
* and normalises, and a form that re-rendered from its own input would
|
|
@@ -22017,7 +21881,15 @@ var notificationRulesCapability = {
|
|
|
22017
21881
|
setAlarmConfig: method(z.object({ patch: NcAlarmSettingsPatchSchema }), NcAlarmConfigSchema, {
|
|
22018
21882
|
kind: "mutation",
|
|
22019
21883
|
auth: "admin"
|
|
22020
|
-
})
|
|
21884
|
+
}),
|
|
21885
|
+
/**
|
|
21886
|
+
* The CURRENT state of each asked device as the alarm reads it (D697) — open, closed,
|
|
21887
|
+
* unknown (why) or not an opening, plus liveness. Classified by the same table the arm
|
|
21888
|
+
* check uses (`alarm-openings.ts`), so the editor and the arm can never disagree. The
|
|
21889
|
+
* caller names the ids (the household openings it already holds); at most
|
|
21890
|
+
* `NC_ALARM_SENSORS_MAX`.
|
|
21891
|
+
*/
|
|
21892
|
+
getAlarmSensors: method(NcAlarmSensorsInputSchema, NcAlarmSensorsSchema, { auth: "admin" })
|
|
22021
21893
|
}
|
|
22022
21894
|
};
|
|
22023
21895
|
/**
|
|
@@ -22382,12 +22254,27 @@ var CameraSensorRefSchema = z.object({
|
|
|
22382
22254
|
function cameraSensorRefKey(ref) {
|
|
22383
22255
|
return `${ref.addonId}/${ref.stableId}`;
|
|
22384
22256
|
}
|
|
22385
|
-
/**
|
|
22386
|
-
|
|
22387
|
-
|
|
22388
|
-
|
|
22389
|
-
|
|
22390
|
-
|
|
22257
|
+
/**
|
|
22258
|
+
* A sensor's mode (D673). `in-addition`: its motion is the camera's motion too.
|
|
22259
|
+
* `replace`: its motion is the camera's, and while one is READY the camera's
|
|
22260
|
+
* own motion no longer counts on its own. `confirm`: while one is READY the
|
|
22261
|
+
* camera's own motion counts only while a confirm sensor is active — with or
|
|
22262
|
+
* without a replace sensor (spec C2, the controller's ruling on Q1).
|
|
22263
|
+
*/
|
|
22264
|
+
var CameraSensorModeSchema = z.enum([
|
|
22265
|
+
"in-addition",
|
|
22266
|
+
"confirm",
|
|
22267
|
+
"replace"
|
|
22268
|
+
]);
|
|
22269
|
+
/** A stored sensor with no mode — every CS-1 row — is in addition. */
|
|
22270
|
+
var DEFAULT_CAMERA_SENSOR_MODE = "in-addition";
|
|
22271
|
+
var CameraSensorEntrySchema = CameraSensorRefSchema.extend({ mode: CameraSensorModeSchema.default(DEFAULT_CAMERA_SENSOR_MODE) });
|
|
22272
|
+
/**
|
|
22273
|
+
* A camera's attached sensors. A CS-1 row carried an envelope
|
|
22274
|
+
* `mode: 'in-addition'`: `z.object` drops it on parse, and the PARSED value is
|
|
22275
|
+
* what the write stores (D672 rule 3), so it is never written again.
|
|
22276
|
+
*/
|
|
22277
|
+
var CameraSensorsConfigSchema = z.object({ sensors: z.array(CameraSensorEntrySchema).min(1).max(8) }).superRefine((value, ctx) => {
|
|
22391
22278
|
const seen = /* @__PURE__ */ new Set();
|
|
22392
22279
|
value.sensors.forEach((ref, index) => {
|
|
22393
22280
|
const key = cameraSensorRefKey(ref);
|
|
@@ -22399,39 +22286,41 @@ var CameraSensorsConfigSchema = z.object({
|
|
|
22399
22286
|
seen.add(key);
|
|
22400
22287
|
});
|
|
22401
22288
|
});
|
|
22402
|
-
|
|
22289
|
+
/** Every attachment names its mode; an older orchestrator that does not is in addition. */
|
|
22290
|
+
var AttachmentFields = {
|
|
22403
22291
|
addonId: z.string(),
|
|
22404
|
-
stableId: z.string()
|
|
22292
|
+
stableId: z.string(),
|
|
22293
|
+
mode: CameraSensorModeSchema.default(DEFAULT_CAMERA_SENSOR_MODE)
|
|
22405
22294
|
};
|
|
22406
22295
|
var CameraSensorAttachmentSchema = z.discriminatedUnion("state", [
|
|
22407
22296
|
z.object({
|
|
22408
|
-
...
|
|
22297
|
+
...AttachmentFields,
|
|
22409
22298
|
state: z.literal("ready"),
|
|
22410
22299
|
deviceId: z.number(),
|
|
22411
22300
|
name: z.string(),
|
|
22412
22301
|
caps: z.array(z.string()).readonly()
|
|
22413
22302
|
}),
|
|
22414
22303
|
z.object({
|
|
22415
|
-
...
|
|
22304
|
+
...AttachmentFields,
|
|
22416
22305
|
state: z.literal("offline"),
|
|
22417
22306
|
deviceId: z.number(),
|
|
22418
22307
|
name: z.string(),
|
|
22419
22308
|
reason: z.enum(["offline", "disabled"])
|
|
22420
22309
|
}),
|
|
22421
22310
|
z.object({
|
|
22422
|
-
...
|
|
22311
|
+
...AttachmentFields,
|
|
22423
22312
|
state: z.literal("missing"),
|
|
22424
22313
|
reason: z.string()
|
|
22425
22314
|
}),
|
|
22426
22315
|
z.object({
|
|
22427
|
-
...
|
|
22316
|
+
...AttachmentFields,
|
|
22428
22317
|
state: z.literal("unsupported"),
|
|
22429
22318
|
deviceId: z.number(),
|
|
22430
22319
|
name: z.string(),
|
|
22431
22320
|
reason: z.string()
|
|
22432
22321
|
}),
|
|
22433
22322
|
z.object({
|
|
22434
|
-
...
|
|
22323
|
+
...AttachmentFields,
|
|
22435
22324
|
state: z.literal("unreadable"),
|
|
22436
22325
|
reason: z.string()
|
|
22437
22326
|
})
|
|
@@ -22444,17 +22333,49 @@ var CameraSensorAttachmentSchema = z.discriminatedUnion("state", [
|
|
|
22444
22333
|
* say.
|
|
22445
22334
|
*/
|
|
22446
22335
|
var CameraSensorsNotForwardedSchema = z.enum(["onboard-not-listed", "no-active-detection"]);
|
|
22336
|
+
/** Whether the camera's OWN motion counts on its own (D673 C2), from its READY sensors (C3). */
|
|
22337
|
+
var CameraOwnMotionSchema = z.enum([
|
|
22338
|
+
"always",
|
|
22339
|
+
"when-confirmed",
|
|
22340
|
+
"never"
|
|
22341
|
+
]);
|
|
22342
|
+
/** Confirm / Replace cannot suppress this camera's motion: its provider still emits it directly (D673 C13). */
|
|
22343
|
+
var CameraSensorsNotEnforcedSchema = z.enum(["provider-not-split"]);
|
|
22344
|
+
/**
|
|
22345
|
+
* The camera's OWN onboard motion (D696): the raw input the bridge combines,
|
|
22346
|
+
* never the effective value. The camera's `motion` slice is the effective one,
|
|
22347
|
+
* so a view of the camera's own row reads this.
|
|
22348
|
+
* - `atMs`: when the bridge received the camera's last own edge.
|
|
22349
|
+
* - `detected`: evaluated WHEN THE STATUS IS ASKED — the last edge said `true`
|
|
22350
|
+
* AND it is younger than the window the bridge counts the camera's own motion
|
|
22351
|
+
* for (`motionCooldownMs`, floored at two sustain ticks). A camera that never
|
|
22352
|
+
* sends a clear (heartbeats only) therefore reads `false` once no push came
|
|
22353
|
+
* within the window; a status read is a snapshot, so a live view re-asks.
|
|
22354
|
+
* Absent = this orchestrator has not received the camera's own motion since it
|
|
22355
|
+
* started (unknown, never "quiet"), or an orchestrator older than D696.
|
|
22356
|
+
*/
|
|
22357
|
+
var CameraRawLevelSchema = z.object({
|
|
22358
|
+
detected: z.boolean(),
|
|
22359
|
+
atMs: z.number()
|
|
22360
|
+
});
|
|
22447
22361
|
var CameraSensorsStatusSchema = z.discriminatedUnion("state", [
|
|
22448
|
-
z.object({
|
|
22362
|
+
z.object({
|
|
22363
|
+
state: z.literal("not-configured"),
|
|
22364
|
+
cameraLevel: CameraRawLevelSchema.optional()
|
|
22365
|
+
}),
|
|
22449
22366
|
z.object({
|
|
22450
22367
|
state: z.literal("unreadable"),
|
|
22451
|
-
reason: z.string()
|
|
22368
|
+
reason: z.string(),
|
|
22369
|
+
cameraLevel: CameraRawLevelSchema.optional()
|
|
22452
22370
|
}),
|
|
22453
22371
|
z.object({
|
|
22454
22372
|
state: z.literal("configured"),
|
|
22455
|
-
|
|
22373
|
+
cameraLevel: CameraRawLevelSchema.optional(),
|
|
22456
22374
|
sensors: z.array(CameraSensorAttachmentSchema).readonly(),
|
|
22457
|
-
|
|
22375
|
+
/** Absent = an orchestrator older than CS-2: it does not say (D315). */
|
|
22376
|
+
cameraMotion: CameraOwnMotionSchema.optional(),
|
|
22377
|
+
notForwarded: CameraSensorsNotForwardedSchema.optional(),
|
|
22378
|
+
notEnforced: CameraSensorsNotEnforcedSchema.optional()
|
|
22458
22379
|
})
|
|
22459
22380
|
]);
|
|
22460
22381
|
Object.freeze({
|
|
@@ -26550,8 +26471,10 @@ var RunnerCameraConfigSchema = z.object({
|
|
|
26550
26471
|
* - `analyzer`: ML/frame-diff motion detection (motion-wasm or other
|
|
26551
26472
|
* analyzer providers) running on decoded frames in this runner.
|
|
26552
26473
|
* - `onboard`: camera-native motion pushes (Reolink Baichuan, ONVIF
|
|
26553
|
-
* analytics). The provider emits ProviderMotion
|
|
26554
|
-
*
|
|
26474
|
+
* analytics). The provider emits its raw push as `ProviderMotion`
|
|
26475
|
+
* (D673); the orchestrator's camera-sensors bridge re-emits the camera's
|
|
26476
|
+
* effective motion as `MotionOnMotionChanged`, which is what reaches
|
|
26477
|
+
* `reportMotion`.
|
|
26555
26478
|
*/
|
|
26556
26479
|
motionSources: MotionSourcesSchema.default(["analyzer"]),
|
|
26557
26480
|
/**
|
|
@@ -26728,7 +26651,15 @@ var RunnerLocalLoadSchema = z.object({
|
|
|
26728
26651
|
hasGpu: z.boolean(),
|
|
26729
26652
|
inferenceBackend: z.string().optional(),
|
|
26730
26653
|
cpuCores: z.number().optional()
|
|
26731
|
-
})
|
|
26654
|
+
}),
|
|
26655
|
+
/**
|
|
26656
|
+
* Who writes a camera's `motion` runtime slice (D696). `'orchestrator'`: this
|
|
26657
|
+
* runner never writes it. ABSENT = a runner older than D696, which still
|
|
26658
|
+
* writes the slice from its phase machine; the orchestrator does not write
|
|
26659
|
+
* while any runner node is absent-or-unanswered, so one slice never has two
|
|
26660
|
+
* writers.
|
|
26661
|
+
*/
|
|
26662
|
+
motionSliceWriter: z.literal("orchestrator").optional()
|
|
26732
26663
|
});
|
|
26733
26664
|
/**
|
|
26734
26665
|
* Aggregate runtime metrics for the runner's whole local pool. Mirrors the
|
|
@@ -34052,6 +33983,70 @@ onStatusChanged: { data: z.object({
|
|
|
34052
33983
|
* whether persisting is worth a SQLite commit. */
|
|
34053
33984
|
volatileStateFields: ["lastChangedAt"]
|
|
34054
33985
|
};
|
|
33986
|
+
var DoorbellStatusSchema = z.object({
|
|
33987
|
+
/** Ms epoch of the last press. null = never observed since this provider started. */
|
|
33988
|
+
lastPressedAt: z.number().nullable(),
|
|
33989
|
+
/** Counter since provider start. Resets on reboot. Useful for metrics/debug. */
|
|
33990
|
+
pressCountSinceStart: z.number()
|
|
33991
|
+
});
|
|
33992
|
+
var DoorbellPressEventSchema = z.object({
|
|
33993
|
+
deviceId: z.number(),
|
|
33994
|
+
timestamp: z.number()
|
|
33995
|
+
});
|
|
33996
|
+
/**
|
|
33997
|
+
* Doorbell button cap. Two kinds of provider serve it, and to every consumer
|
|
33998
|
+
* they are the same cap:
|
|
33999
|
+
*
|
|
34000
|
+
* - **Native** providers, registered per device by a driver addon through
|
|
34001
|
+
* `ctx.registerNativeCap` — a `DeviceType.Button` accessory with
|
|
34002
|
+
* `role: DeviceRole.Doorbell`, or the camera itself (Reolink registers at
|
|
34003
|
+
* camera level). They emit `onPressed` on every firmware ring.
|
|
34004
|
+
* - **A composed doorbell** (D670, D671): a camera's customization gives it
|
|
34005
|
+
* the cap, its `lastPressedAt` rising from the sources the operator
|
|
34006
|
+
* assigned in Customize → Doorbell, and the composer emits `onPressed`
|
|
34007
|
+
* from that field's advance (`fromState`).
|
|
34008
|
+
*
|
|
34009
|
+
* The DeviceEventPropagator re-emits `onPressed` on the camera parent.
|
|
34010
|
+
*/
|
|
34011
|
+
var doorbellCapability = {
|
|
34012
|
+
name: "doorbell",
|
|
34013
|
+
scope: "device",
|
|
34014
|
+
deviceNative: true,
|
|
34015
|
+
mode: "singleton",
|
|
34016
|
+
deviceTypes: [DeviceType.Button, DeviceType.Camera],
|
|
34017
|
+
methods: {},
|
|
34018
|
+
events: {
|
|
34019
|
+
/**
|
|
34020
|
+
* Fires once per physical press. Reolink delivers via Baichuan
|
|
34021
|
+
* push (`ReolinkSimpleEvent.type === 'doorbell'`). There is no
|
|
34022
|
+
* release/duration — it's a pulse.
|
|
34023
|
+
*/
|
|
34024
|
+
onPressed: {
|
|
34025
|
+
data: DoorbellPressEventSchema,
|
|
34026
|
+
fromState: {
|
|
34027
|
+
field: "lastPressedAt",
|
|
34028
|
+
on: "advance"
|
|
34029
|
+
}
|
|
34030
|
+
} },
|
|
34031
|
+
status: {
|
|
34032
|
+
schema: DoorbellStatusSchema,
|
|
34033
|
+
kind: "push"
|
|
34034
|
+
},
|
|
34035
|
+
/**
|
|
34036
|
+
* Runtime-state slice — last press timestamp + lifetime press count.
|
|
34037
|
+
* Mirrored by the kernel and readable via
|
|
34038
|
+
* `device.state.doorbell.value`. UIs can show "last ring 5m ago"
|
|
34039
|
+
* without subscribing.
|
|
34040
|
+
*/
|
|
34041
|
+
runtimeState: DoorbellStatusSchema,
|
|
34042
|
+
/**
|
|
34043
|
+
* 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.
|
|
34044
|
+
*
|
|
34045
|
+
* See `RuntimeStateDurability`. Enforced by
|
|
34046
|
+
* `scripts/check-runtime-state-durability.ts`.
|
|
34047
|
+
*/
|
|
34048
|
+
durability: "restored"
|
|
34049
|
+
};
|
|
34055
34050
|
/**
|
|
34056
34051
|
* Enum-state sensor — a string value picked from a finite option set.
|
|
34057
34052
|
* Drives HA `sensor` entries with `state_class: enum` (HVAC action
|
|
@@ -36462,11 +36457,11 @@ authKey: z.string().optional() }), z.object({
|
|
|
36462
36457
|
/**
|
|
36463
36458
|
* How long after a camera's last rising edge `pipeline-analytics` closes the
|
|
36464
36459
|
* motion EPISODE row it kept open for it (D475) — "il delay della cap", in
|
|
36465
|
-
* the operator's words. One authority for the whole system:
|
|
36466
|
-
*
|
|
36467
|
-
*
|
|
36468
|
-
* seed its internal 3 s inactivity timer here,
|
|
36469
|
-
* a different purpose), and `MotionEpisodeTracker` imports it directly rather
|
|
36460
|
+
* the operator's words. One authority for the whole system: the writer of a
|
|
36461
|
+
* `Camera` device's slice (the orchestrator, D696) writes this SAME constant
|
|
36462
|
+
* in `autoClearAfterMs` while `detected: true` (never a camera's own clock —
|
|
36463
|
+
* Hikvision used to seed its internal 3 s inactivity timer here, a different
|
|
36464
|
+
* clock for a different purpose), and `MotionEpisodeTracker` imports it directly rather
|
|
36470
36465
|
* than reading the live cap value on the hot path. A `Sensor` device (HA
|
|
36471
36466
|
* binary sensor, Homematic) gets a genuine push both ways and has no episode
|
|
36472
36467
|
* to close on a timer, so it writes `null`, never this constant.
|
|
@@ -36477,9 +36472,9 @@ var MotionStatusSchema = z.object({
|
|
|
36477
36472
|
/** Ms epoch of the last detected-true observation. Null if never detected. */
|
|
36478
36473
|
lastDetectedAt: z.number().nullable(),
|
|
36479
36474
|
/**
|
|
36480
|
-
* `MOTION_CLOSE_AFTER_MS` while `detected: true` on a `Camera` device
|
|
36481
|
-
* `null` while false and on every `Sensor`
|
|
36482
|
-
* constant's doc for the one-authority rule.
|
|
36475
|
+
* `MOTION_CLOSE_AFTER_MS` while `detected: true` on a `Camera` device (the
|
|
36476
|
+
* orchestrator writes it, D696), `null` while false and on every `Sensor`
|
|
36477
|
+
* device (D475) — see that constant's doc for the one-authority rule.
|
|
36483
36478
|
*
|
|
36484
36479
|
* ## Reading this field still arms nothing
|
|
36485
36480
|
*
|
|
@@ -36497,34 +36492,31 @@ var MotionStatusSchema = z.object({
|
|
|
36497
36492
|
* `addon-export-alexa/src/motion-clear-hold.ts` and
|
|
36498
36493
|
* `addon-export-hap`'s `RESET_DEBOUNCE_MS` both do.
|
|
36499
36494
|
*
|
|
36500
|
-
* ## Who writes it
|
|
36501
|
-
*
|
|
36502
|
-
* - **Cameras** — the
|
|
36503
|
-
*
|
|
36504
|
-
* `
|
|
36505
|
-
* `
|
|
36506
|
-
*
|
|
36507
|
-
*
|
|
36508
|
-
* a
|
|
36509
|
-
*
|
|
36510
|
-
*
|
|
36511
|
-
*
|
|
36512
|
-
*
|
|
36513
|
-
*
|
|
36514
|
-
*
|
|
36515
|
-
*
|
|
36516
|
-
*
|
|
36517
|
-
*
|
|
36518
|
-
* `
|
|
36519
|
-
*
|
|
36520
|
-
*
|
|
36521
|
-
*
|
|
36522
|
-
*
|
|
36523
|
-
*
|
|
36524
|
-
*
|
|
36525
|
-
* This predates D475 and is not fixed there: the fix touches every
|
|
36526
|
-
* camera provider. Recorded in D475's Consequences. Do not restore the
|
|
36527
|
-
* "sole writer" wording without also removing the other writers.
|
|
36495
|
+
* ## Who writes it (D696)
|
|
36496
|
+
*
|
|
36497
|
+
* - **Cameras** — the orchestrator, and nothing else. It writes the camera's
|
|
36498
|
+
* EFFECTIVE motion (`addon-pipeline-orchestrator`
|
|
36499
|
+
* `camera-sensors/motion-slice.ts`), alongside the effective
|
|
36500
|
+
* `MotionOnMotionChanged` it emits or receives: the camera-sensors bridge
|
|
36501
|
+
* for a split camera, an unsplit emitter's direct event, the analyzer and
|
|
36502
|
+
* device activity, as the camera's `motionSources` counts them. A source
|
|
36503
|
+
* that never sends a clear falls one window after its last `true`.
|
|
36504
|
+
* `lastDetectedAt` moves only on an effective rise. No camera provider
|
|
36505
|
+
* writes this slice (not even a boot seed), and neither does the runner's
|
|
36506
|
+
* phase machine: its phase is "a session is attached" for every on-motion
|
|
36507
|
+
* session, not motion, and it now has its own `DetectionPhaseTransition`.
|
|
36508
|
+
* A provider's `isDetected` answers from the hub's slice.
|
|
36509
|
+
* - **Sensors** (Home Assistant binary sensors, Homematic, Matter, Alexa
|
|
36510
|
+
* imports) — the provider pushes both edges itself, from the upstream
|
|
36511
|
+
* system's own state change. That is the sensor's own fact.
|
|
36512
|
+
*
|
|
36513
|
+
* `scripts/check-onboard-motion-emitters.ts` refuses any other writer of a
|
|
36514
|
+
* `motion` slice; each sensor writer is a named exemption.
|
|
36515
|
+
*
|
|
36516
|
+
* This replaces the D475 §4 rule ("the phase machine is the sole writer").
|
|
36517
|
+
* That rule was never true: Hikvision and Amcrest wrote the slice raw beside
|
|
36518
|
+
* it, every provider seeded it at boot, and every session left it
|
|
36519
|
+
* `detected: true` after its detach.
|
|
36528
36520
|
*/
|
|
36529
36521
|
autoClearAfterMs: z.number().nullable()
|
|
36530
36522
|
});
|
|
@@ -36596,11 +36588,12 @@ onMotionChanged: { data: MotionOnMotionChangedDataSchema } },
|
|
|
36596
36588
|
*/
|
|
36597
36589
|
runtimeState: MotionStatusSchema,
|
|
36598
36590
|
/**
|
|
36599
|
-
* Runtime-state durability: **session** —
|
|
36591
|
+
* Runtime-state durability: **session** — the writer of this slice
|
|
36600
36592
|
* writes only on an EDGE, so a restored `detected: true` would stay
|
|
36601
36593
|
* frozen until the next one instead of being corrected. The next edge
|
|
36602
|
-
* re-publishes the real state
|
|
36603
|
-
*
|
|
36594
|
+
* re-publishes the real state, and the orchestrator re-publishes every
|
|
36595
|
+
* camera when it starts writing (D696; on who writes it, see
|
|
36596
|
+
* `autoClearAfterMs` above).
|
|
36604
36597
|
*
|
|
36605
36598
|
* See `RuntimeStateDurability`. Enforced by
|
|
36606
36599
|
* `scripts/check-runtime-state-durability.ts`.
|
|
@@ -39316,8 +39309,7 @@ var ptzAutotrackCapability = {
|
|
|
39316
39309
|
deviceNative: true,
|
|
39317
39310
|
mode: "singleton",
|
|
39318
39311
|
/**
|
|
39319
|
-
* Two kinds of provider behind one name, the same shape `snapshot`
|
|
39320
|
-
* `doorbell` use:
|
|
39312
|
+
* Two kinds of provider behind one name, the same shape `snapshot` uses:
|
|
39321
39313
|
*
|
|
39322
39314
|
* - **Native**: the camera's own firmware autotrack, registered per device by
|
|
39323
39315
|
* the driver when the probe says it exists (Reolink: yes; Hikvision:
|
|
@@ -39325,7 +39317,7 @@ var ptzAutotrackCapability = {
|
|
|
39325
39317
|
* - **Wrapper**: the emulated implementation (`@camstack/system`'s `autotrack` builtin),
|
|
39326
39318
|
* which follows a subject with `ptz.move` pulses driven by the detection
|
|
39327
39319
|
* pipeline. `defaultActive: false` — the operator binds it per camera in
|
|
39328
|
-
* the bindings UI
|
|
39320
|
+
* the bindings UI.
|
|
39329
39321
|
*
|
|
39330
39322
|
* The binding chooses WHICH implementation answers; `setEnabled` stays the
|
|
39331
39323
|
* one switch for the function either way. A camera never has both driving its
|
|
@@ -44697,72 +44689,6 @@ function evaluateCompositionField(input) {
|
|
|
44697
44689
|
}
|
|
44698
44690
|
}
|
|
44699
44691
|
/**
|
|
44700
|
-
* The doorbell of a camera as a customization (D671). ONE builder: the
|
|
44701
|
-
* virtual-doorbell migration and the admin UI's "Use as doorbell" preset both
|
|
44702
|
-
* call it, so a preset can never write a shape the migration would refuse as
|
|
44703
|
-
* "an unrelated existing block".
|
|
44704
|
-
*/
|
|
44705
|
-
/** A rise closer than this to the previous one is the same press (D671). */
|
|
44706
|
-
var DOORBELL_RISE_DEBOUNCE_MS = 2e3;
|
|
44707
|
-
/** Every source cap of `source` that `SOURCE_CAP_ACTIVE_FIELD` knows AND the device has bound. */
|
|
44708
|
-
function doorbellFeatureSources(source, boundCaps) {
|
|
44709
|
-
return Object.keys(SOURCE_CAP_ACTIVE_FIELD).filter((cap) => Object.hasOwn(SOURCE_CAP_CHANGED_AT_FIELD, cap) && boundCaps.includes(cap)).toSorted().flatMap((cap) => {
|
|
44710
|
-
const activeField = SOURCE_CAP_ACTIVE_FIELD[cap];
|
|
44711
|
-
const changedAtField = SOURCE_CAP_CHANGED_AT_FIELD[cap];
|
|
44712
|
-
return activeField === void 0 || changedAtField === void 0 ? [] : [{
|
|
44713
|
-
source,
|
|
44714
|
-
cap,
|
|
44715
|
-
activeField,
|
|
44716
|
-
changedAtField
|
|
44717
|
-
}];
|
|
44718
|
-
});
|
|
44719
|
-
}
|
|
44720
|
-
/** The D671 feature, byte for byte what the migration writes. Throws on zero sources. */
|
|
44721
|
-
function buildDoorbellCompositionFeature(input) {
|
|
44722
|
-
const sources = [...input.sources].toSorted((a, b) => `${a.source.addonId}/${a.source.stableId}#${a.cap}`.localeCompare(`${b.source.addonId}/${b.source.stableId}#${b.cap}`));
|
|
44723
|
-
if (sources.length === 0) throw new Error("doorbell composition needs at least one source");
|
|
44724
|
-
const edgeBindings = {};
|
|
44725
|
-
sources.forEach((entry, index) => {
|
|
44726
|
-
edgeBindings[`active${index}`] = {
|
|
44727
|
-
kind: "from",
|
|
44728
|
-
source: entry.source,
|
|
44729
|
-
cap: entry.cap,
|
|
44730
|
-
fieldPath: entry.activeField
|
|
44731
|
-
};
|
|
44732
|
-
edgeBindings[`changed${index}`] = {
|
|
44733
|
-
kind: "from",
|
|
44734
|
-
source: entry.source,
|
|
44735
|
-
cap: entry.cap,
|
|
44736
|
-
fieldPath: entry.changedAtField
|
|
44737
|
-
};
|
|
44738
|
-
});
|
|
44739
|
-
return {
|
|
44740
|
-
kind: "fields",
|
|
44741
|
-
cap: "doorbell",
|
|
44742
|
-
enabled: input.enabled,
|
|
44743
|
-
fields: {
|
|
44744
|
-
lastPressedAt: {
|
|
44745
|
-
kind: "expression",
|
|
44746
|
-
expr: `latest(${sources.map((_, index) => `rose(active${index}, changed${index}, ${DOORBELL_RISE_DEBOUNCE_MS})`).join(", ")})`,
|
|
44747
|
-
bindings: edgeBindings
|
|
44748
|
-
},
|
|
44749
|
-
pressCountSinceStart: {
|
|
44750
|
-
kind: "expression",
|
|
44751
|
-
expr: "count(lastPressedAt)",
|
|
44752
|
-
bindings: { lastPressedAt: {
|
|
44753
|
-
kind: "from",
|
|
44754
|
-
source: {
|
|
44755
|
-
addonId: input.camera.addonId,
|
|
44756
|
-
stableId: input.camera.stableId
|
|
44757
|
-
},
|
|
44758
|
-
cap: "doorbell",
|
|
44759
|
-
fieldPath: "lastPressedAt"
|
|
44760
|
-
} }
|
|
44761
|
-
}
|
|
44762
|
-
}
|
|
44763
|
-
};
|
|
44764
|
-
}
|
|
44765
|
-
/**
|
|
44766
44692
|
* Runtime defaults -- used by ConfigManager.get() for backward compatibility
|
|
44767
44693
|
* until Plan B wires all runtime settings to the system_settings SQL table.
|
|
44768
44694
|
*
|
|
@@ -51336,6 +51262,12 @@ var METHOD_ACCESS_MAP = Object.freeze({
|
|
|
51336
51262
|
addonId: null,
|
|
51337
51263
|
access: "view"
|
|
51338
51264
|
},
|
|
51265
|
+
"notificationRules.getAlarmSensors": {
|
|
51266
|
+
capName: "notification-rules",
|
|
51267
|
+
capScope: "system",
|
|
51268
|
+
addonId: null,
|
|
51269
|
+
access: "view"
|
|
51270
|
+
},
|
|
51339
51271
|
"notificationRules.getClipRetentionAsks": {
|
|
51340
51272
|
capName: "notification-rules",
|
|
51341
51273
|
capScope: "system",
|
|
@@ -55819,6 +55751,11 @@ Object.freeze({
|
|
|
55819
55751
|
form: "single",
|
|
55820
55752
|
optional: false
|
|
55821
55753
|
}],
|
|
55754
|
+
"notificationRules.getAlarmSensors": [{
|
|
55755
|
+
name: "deviceIds",
|
|
55756
|
+
form: "array",
|
|
55757
|
+
optional: false
|
|
55758
|
+
}],
|
|
55822
55759
|
"notificationRules.setDeviceMuted": [{
|
|
55823
55760
|
name: "deviceId",
|
|
55824
55761
|
form: "single",
|
|
@@ -58054,6 +57991,7 @@ TimelapseRuleInputSchema.extend({
|
|
|
58054
57991
|
createdAt: z.number(),
|
|
58055
57992
|
updatedAt: z.number()
|
|
58056
57993
|
});
|
|
57994
|
+
MotionOnMotionChangedDataSchema.omit({ triggeredBy: true });
|
|
58057
57995
|
z.object({
|
|
58058
57996
|
/**
|
|
58059
57997
|
* Fraction of the box's own size added on EACH side before cutting.
|
|
@@ -58253,8 +58191,8 @@ DEFAULT_NATIVE_LEASE_SETTINGS.admission;
|
|
|
58253
58191
|
* So `entry.providerAddonId === this.ctx.id` is silently, permanently false
|
|
58254
58192
|
* for a builtin — and only for a builtin, which is why it survives a green
|
|
58255
58193
|
* suite whose fake supplies the bare id. That is exactly how camera 615's
|
|
58256
|
-
* virtual doorbell latched `unbound` for twelve hours on
|
|
58257
|
-
* binding was intact ([D72](../../../../docs/decisions/adr-0072.md)).
|
|
58194
|
+
* virtual doorbell (retired since, D671) latched `unbound` for twelve hours on
|
|
58195
|
+
* 2026-08-07 while its binding was intact ([D72](../../../../docs/decisions/adr-0072.md)).
|
|
58258
58196
|
*
|
|
58259
58197
|
* Route every comparison between `ctx.id` and a registry/store addon id
|
|
58260
58198
|
* through {@link isSameAddonId}. `scripts/check-addon-id-comparison.ts`
|
|
@@ -58266,10 +58204,6 @@ var ADDON_ID_PREFIX = "addon:";
|
|
|
58266
58204
|
function bareAddonId(id) {
|
|
58267
58205
|
return id.startsWith(ADDON_ID_PREFIX) ? id.slice(6) : id;
|
|
58268
58206
|
}
|
|
58269
|
-
/** True when both ids name the same addon, prefixed or not. */
|
|
58270
|
-
function isSameAddonId(a, b) {
|
|
58271
|
-
return bareAddonId(a) === bareAddonId(b);
|
|
58272
|
-
}
|
|
58273
58207
|
var MB = 1024 * 1024;
|
|
58274
58208
|
1024 * MB, 3072 * MB;
|
|
58275
58209
|
/**
|
|
@@ -58404,4 +58338,4 @@ function enumerateInferenceDevices(hw) {
|
|
|
58404
58338
|
return out;
|
|
58405
58339
|
}
|
|
58406
58340
|
//#endregion
|
|
58407
|
-
export {
|
|
58341
|
+
export { composerCapability as $, createEvent as $n, parseStreamParamsFormPatch as $t, REDACTED_SECRET as A, cloneStatefulExpressionMemory as An, isArrayOutputSchema as At, UserRecordSchema as B, DeviceRole as Bn, locationIconKey as Bt, LOG_LEVEL_RANK as C, validateComposition as Cn, evictionPolicyOfLocation as Ct, MINUTES_PER_DAY as D, withLocationMode as Dn, foldSnapshotByFunction as Dt, METHOD_ACCESS_MAP as E, vectorStoreCapability as En, filesystemBrowseCapability as Et, ScopedTokenSchema as F, compositionSliceKey as Fn, kebabToCamel as Ft, authProviderCapability as G, DEVICE_SETTINGS_CONTRIBUTION_METHODS as Gn, mayWriteToLocation as Gt, addonSettingsCapability as H, errMsg as Hn, logLevelAtMost as Ht, StorageCleanupJobSchema as I, compositionSourceKey as In, legacyAutoLinkIds as It, batteryCapability as J, ReadinessTimeoutError as Jn, modeMayWrite as Jt, backupCapability as K, DEVICE_STATUS_METHOD as Kn, memoizePinnedFfmpeg as Kt, StorageLocationModeSchema as L, createStatefulExpressionMemory as Ln, legacyModeOf as Lt, RecordingStatusSchema as M, composedDeviceStableId as Mn, isLocationEnabled as Mt, STORAGE_ACCESS_FALLBACK as N, compositionFeatureEnabled as Nn, isObjectInput as Nt, MOTION_CLOSE_AFTER_MS as O, COMPOSER_ADDON_ID as On, formatMinutes as Ot, STREAM_PROFILE_META as P, compositionItemFieldPath as Pn, isVoidInput as Pt, collectSecretConfigKeys as Q, asString$1 as Qn, objectInputDeclaresRequiredDeviceId as Qt, StorageLocationTypeSchema as R, toExpressionValue as Rn, lifecycleJobSchema as Rt, FieldClaimSchema as S, userManagementCapability as Sn, evaluateCompositionField as St, LocationIconIdSchema as T, vectorIndexDimConflictError as Tn, extractNestedAddonId as Tt, addonWidgetsCapability as U, BaseAddon as Un, looseSchema as Ut, addonPagesCapability as V, DeviceType as Vn, logDestinationCapability as Vt, alertsCapability as W, DATAPLANE_SECRET_HEADER as Wn, mayReadLocation as Wt, buildStreamParamsConfigSchema as X, asJsonObject as Xn, normalizeUnit as Xt, buildCapabilityLookup as Y, WELL_KNOWN_TAB_MAP as Yn, motionCapability as Yt, cameraGridLayoutCapability as Z, asNumber as Zn, objectInputDeclaresAddonId as Zt, DERIVED_CAMERA_SILENCED_CAP_NAMES as _, storageMigrationCapability as _n, deviceStateCapability as _t, BatteryStatusSchema as a, replacedFieldKeys as an, isEvent as ar, coreBlockSourceKind as at, FIRST_LEVEL_MACRO_CLASSES as b, streamCatalogCapability as bn, enumerateItemArrayFields as bt, COMPOSED_ITEM_FIXED_FIELDS as c, resolveMethodAuth as cn, parseJsonUnknown as cr, dataStoreProviderCapability as ct, CORE_BLOCK_ADDON_PREFIX as d, scopesAllowDeviceCap as dn, scopeKey as dr, decodeVectorBase64 as dt, planComposition as en, emitDownForOwnedCaps as er, compositionFieldKey as et, CoreBlockSchema as f, scoreRuntimes as fn, sleep as fr, defineExtensionSlotProvider as ft, DAY_NAMES as g, storageCapability as gn, deviceManagerCapability as gt, DATABASE_SNAPSHOT_TIMEOUT_MS as h, snapshotCapability as hn, deviceExtensionCapability as ht, BaseDevice as i, reducePoints as in, isDeviceConfigCap as ir, coreBlockIdFromAddonId as it, RUNTIME_DEFAULTS as j, composedDeviceRef as jn, isCollectionArrayMethod as jt, RECORDING_SOURCE_CAMSTACK_ADDON as k, buildFfmpegArgs as kn, gbToBytes as kt, COMPOSER_RUNNER_ID as l, runtimeStatePolicyFor as ln, readinessKey as lr, databaseSnapshotCapability as lt, DATABASE_SNAPSHOT_SUFFIX as m, siteZoneKey as mn, EventCategory as mr, describeComposableCaps as mt, AlertSchema as n, procedureAuthKey as nn, expandCapMethods as nr, coreBlockAddonId as nt, CAMERA_SWITCH_ORDER as o, resolveBucketMs as on, nodePin as or, coreBlocksCapability as ot, DATABASE_SNAPSHOT_PARTIAL_SUFFIX as p, settingsStoreCapability as pn, toNodeId as pr, deriveBatteryPresence as pt, bareAddonId as q, ReadinessRegistry as qn, metricsProviderCapability as qt, ApiKeyRecordSchema as r, ptzAutotrackCapability as rn, hydrateSchema as rr, coreBlockComposition as rt, CAP_NAMES_WITH_STATUS as s, resolveLocationMode as sn, parseJsonObject as sr, createDeviceExtensionProvider as st, ALL_CAPABILITY_DEFINITIONS as t, platformProbeCapability as tn, emitReadiness as tr, compositionSourceRefs as tt, CORE_BLOCKS_ADDON_ID as u, scopesAllowAddon as un, resolveCapMount as ur, declarationOwnerNodeId as ut, DeclaredDevices as v, storageOccupancyCapability as vn, deviceStatusCapability as vt, LegacyStorageLocationDefaultSchema as w, vectorDimFromBase64 as wn, expandContainer as wt, FieldClaimModeSchema as x, streamQualityLabel as xn, enumerateSchemaFields as xt, DeviceStatusSchema as y, storageProviderCapability as yn, enumerateInferenceDevices as yt, StorageMigrationJobSchema as z, DeviceFeature as zn, localNetworkCapability as zt };
|