@camstack/addon-post-analysis 1.2.281 → 1.2.283
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/{dist-BtqlSCQT.js → dist-CT5xOY86.js} +394 -8
- package/dist/{dist-DkERzZfY.mjs → dist-zp1v7cCp.mjs} +353 -9
- package/dist/embedding-encoder/index.js +1 -1
- package/dist/embedding-encoder/index.mjs +1 -1
- package/dist/pipeline-analytics/_stub.js +2 -2
- package/dist/pipeline-analytics/{_virtual_mf-localSharedImportMap___mfe_internal__addon_pipeline_analytics_widgets-d-u88SNA.mjs → _virtual_mf-localSharedImportMap___mfe_internal__addon_pipeline_analytics_widgets-9UxXz_Yw.mjs} +2 -2
- package/dist/pipeline-analytics/_virtual_mf___mfe_internal__addon_pipeline_analytics_widgets__loadShare___mf_0_camstack_mf_1_types__loadShare__.js-CZkZhroP.mjs +26 -0
- package/dist/pipeline-analytics/{_virtual_mf___mfe_internal__addon_pipeline_analytics_widgets__loadShare___mf_0_camstack_mf_1_ui_mf_2_library__loadShare__.js-BA7N1yDM.mjs → _virtual_mf___mfe_internal__addon_pipeline_analytics_widgets__loadShare___mf_0_camstack_mf_1_ui_mf_2_library__loadShare__.js-DWPDYuJS.mjs} +1 -1
- package/dist/pipeline-analytics/{hostInit-Cq_8hgwY.mjs → hostInit-27I-ZEiW.mjs} +2 -2
- package/dist/pipeline-analytics/index.js +901 -81
- package/dist/pipeline-analytics/index.mjs +901 -81
- package/dist/pipeline-analytics/remoteEntry.js +1 -1
- package/package.json +1 -1
- package/dist/pipeline-analytics/_virtual_mf___mfe_internal__addon_pipeline_analytics_widgets__loadShare___mf_0_camstack_mf_1_types__loadShare__.js-OkXjMLHG.mjs +0 -26
|
@@ -5391,7 +5391,7 @@ var ZodIssueCode = {
|
|
|
5391
5391
|
var ZodFirstPartyTypeKind;
|
|
5392
5392
|
ZodFirstPartyTypeKind || (ZodFirstPartyTypeKind = {});
|
|
5393
5393
|
//#endregion
|
|
5394
|
-
//#region ../types/dist/sleep-
|
|
5394
|
+
//#region ../types/dist/sleep-DU7mu4wb.mjs
|
|
5395
5395
|
/**
|
|
5396
5396
|
* The audio chunk plane's byte format, and the ONE expansion from a coded
|
|
5397
5397
|
* window to float samples (D455).
|
|
@@ -17956,6 +17956,9 @@ var NcSystemEventKindSchema = _enum([
|
|
|
17956
17956
|
"device-battery-normal",
|
|
17957
17957
|
"device-consumable-low",
|
|
17958
17958
|
"device-consumable-normal",
|
|
17959
|
+
"device-tank-low",
|
|
17960
|
+
"device-tank-full",
|
|
17961
|
+
"device-tank-normal",
|
|
17959
17962
|
"stream-online",
|
|
17960
17963
|
"stream-offline",
|
|
17961
17964
|
"node-online",
|
|
@@ -18016,6 +18019,18 @@ var NC_ALARM_SYSTEM_EVENT_KINDS = [
|
|
|
18016
18019
|
"alarm-disarmed"
|
|
18017
18020
|
];
|
|
18018
18021
|
/**
|
|
18022
|
+
* The two kinds a RULE's consumable threshold speaks about (D642). Named once:
|
|
18023
|
+
* the filter scoping (`systemEventFilterApplies`), the hub's threshold census
|
|
18024
|
+
* and both editors read it.
|
|
18025
|
+
*/
|
|
18026
|
+
var NC_CONSUMABLE_SYSTEM_EVENT_KINDS = ["device-consumable-low", "device-consumable-normal"];
|
|
18027
|
+
/** A vacuum's tank alerts (D642) — raised on the provider's own verdict. */
|
|
18028
|
+
var NC_TANK_SYSTEM_EVENT_KINDS = [
|
|
18029
|
+
"device-tank-low",
|
|
18030
|
+
"device-tank-full",
|
|
18031
|
+
"device-tank-normal"
|
|
18032
|
+
];
|
|
18033
|
+
/**
|
|
18019
18034
|
* One coherent system-event condition. `kinds` is the required opt-in safety
|
|
18020
18035
|
* gate; the remaining lists are optional narrowing filters relevant to the
|
|
18021
18036
|
* selected kinds.
|
|
@@ -18049,8 +18064,27 @@ var NcSystemEventConditionSchema = object({
|
|
|
18049
18064
|
*/
|
|
18050
18065
|
excludeDeviceIds: array(number().int()).min(1).optional(),
|
|
18051
18066
|
nodeIds: array(string().min(1)).min(1).optional(),
|
|
18052
|
-
packageNames: array(string().min(1)).min(1).optional()
|
|
18067
|
+
packageNames: array(string().min(1)).min(1).optional(),
|
|
18068
|
+
/**
|
|
18069
|
+
* At or below this remaining-life %, a consumable is LOW for THIS rule
|
|
18070
|
+
* (D642). Absent = {@link NC_CONSUMABLE_LOW_PERCENT_DEFAULT}; at most
|
|
18071
|
+
* {@link NC_CONSUMABLE_LOW_PERCENT_MAX}, so every episode can recover. Scoped to the
|
|
18072
|
+
* consumable kinds (`systemEventFilterApplies`) and to the device-events
|
|
18073
|
+
* family; ignored on every other kind.
|
|
18074
|
+
*
|
|
18075
|
+
* It is a property of the RULE because the operator decided so: a rule at
|
|
18076
|
+
* 25 must be told about a filter at 20 %, a rule at 10 must not. The hub
|
|
18077
|
+
* keeps one episode per (threshold, device, item) — its own hysteresis, its
|
|
18078
|
+
* own reminder — and a rule hears only the episode judged at ITS threshold,
|
|
18079
|
+
* exactly as an occupancy rule hears only the edge of its own count. A
|
|
18080
|
+
* provider's own `replace` verdict is low at every threshold.
|
|
18081
|
+
*/
|
|
18082
|
+
consumableLowPercent: number().int().min(1).max(95).optional()
|
|
18053
18083
|
});
|
|
18084
|
+
/** The consumable threshold a system-event condition judges at (D642). */
|
|
18085
|
+
function consumableLowPercentOf(condition) {
|
|
18086
|
+
return condition.consumableLowPercent ?? 15;
|
|
18087
|
+
}
|
|
18054
18088
|
/** Hard ceiling on a window (24h). A snooze that could not expire would be an
|
|
18055
18089
|
* outage the operator asked for once and forgot. */
|
|
18056
18090
|
var NC_SNOOZE_MAX_MINUTES = 1440;
|
|
@@ -18209,6 +18243,16 @@ var NcCrossingSchema = _enum([
|
|
|
18209
18243
|
"exit",
|
|
18210
18244
|
"any"
|
|
18211
18245
|
]);
|
|
18246
|
+
/**
|
|
18247
|
+
* Which edge of a BOOLEAN sensor fires a device-event rule (D640).
|
|
18248
|
+
* - `raised` — the sensor went high: water detected, smoke, open, tampered.
|
|
18249
|
+
* - `cleared` — it went back: dry, clear, closed.
|
|
18250
|
+
* - absent — both edges, which is what every rule authored before this did.
|
|
18251
|
+
*
|
|
18252
|
+
* There is no third member for "both": absence already says it, and a value
|
|
18253
|
+
* that means the same as absence is a second way to write one rule.
|
|
18254
|
+
*/
|
|
18255
|
+
var NcSensorTransitionSchema = _enum(["raised", "cleared"]);
|
|
18212
18256
|
/** Admin-zone membership condition (zone IDs as stamped by the ZoneEngine). */
|
|
18213
18257
|
var NcZoneConditionSchema = object({
|
|
18214
18258
|
ids: array(string().min(1)).min(1),
|
|
@@ -18398,6 +18442,20 @@ var NcConditionsSchema = object({
|
|
|
18398
18442
|
scene: NcSceneConditionSchema.optional(),
|
|
18399
18443
|
/** Device scope — absent = all devices. */
|
|
18400
18444
|
devices: array(number()).optional(),
|
|
18445
|
+
/**
|
|
18446
|
+
* Device EXCLUSION (D641) — "every device except these". Judged on the SAME
|
|
18447
|
+
* subject ids {@link devices} is judged on (the camera, the sensor that
|
|
18448
|
+
* fired, a linked set's sensor and row cameras), so a sensor fanned out per
|
|
18449
|
+
* linked camera is excluded exactly where an include would have tested it.
|
|
18450
|
+
* `min(1)`: an empty exclusion excludes nothing and is written as absent.
|
|
18451
|
+
*
|
|
18452
|
+
* Not for `system-event` rules — those carry their own
|
|
18453
|
+
* `systemEvent.excludeDeviceIds` (D636), and the hub refuses this key there.
|
|
18454
|
+
* Editors present the two lists as ONE field (All | Only these | All except
|
|
18455
|
+
* these); the engine evaluates each independently, so a legacy rule
|
|
18456
|
+
* carrying both still means "these, minus those".
|
|
18457
|
+
*/
|
|
18458
|
+
devicesExclude: array(number()).min(1).optional(),
|
|
18401
18459
|
/** Detector class names (any overlap with the record's class set). */
|
|
18402
18460
|
classes: array(string().min(1)).optional(),
|
|
18403
18461
|
/** Veto classes — any overlap fails the rule. */
|
|
@@ -18531,6 +18589,16 @@ var NcConditionsSchema = object({
|
|
|
18531
18589
|
*/
|
|
18532
18590
|
sensorKinds: array(string().min(1)).optional(),
|
|
18533
18591
|
/**
|
|
18592
|
+
* DEVICE-EVENT only (D640). Fire on one edge of a boolean sensor —
|
|
18593
|
+
* {@link NcSensorTransitionSchema}. Which field of the slice means "raised"
|
|
18594
|
+
* is `@camstack/types` → `notification/sensor-raised.ts`. A reading the
|
|
18595
|
+
* engine cannot place (a kind with no raise, an unreadable slice) PASSES:
|
|
18596
|
+
* the condition fails open towards notifying, never towards silence. Editors
|
|
18597
|
+
* offer it only when every chosen {@link sensorKinds} member has a raise
|
|
18598
|
+
* (`sensorTransitionOffered`), and the hub refuses it on any other delivery.
|
|
18599
|
+
*/
|
|
18600
|
+
sensorTransition: NcSensorTransitionSchema.optional(),
|
|
18601
|
+
/**
|
|
18534
18602
|
* PACKAGE-EVENT only. Which package phase fires the rule — `delivered`
|
|
18535
18603
|
* (a parked parcel appeared), `picked-up` (it departed), or `both`. Fails
|
|
18536
18604
|
* when the subject's phase does not match (a subject always carries a phase
|
|
@@ -19149,6 +19217,7 @@ var NcConditionDescriptorSchema = object({
|
|
|
19149
19217
|
/** Editor widget the UI renders — never hardcode per-condition forms. */
|
|
19150
19218
|
valueType: _enum([
|
|
19151
19219
|
"deviceIdList",
|
|
19220
|
+
"deviceIdExcludeList",
|
|
19152
19221
|
"stringList",
|
|
19153
19222
|
"number01",
|
|
19154
19223
|
"number",
|
|
@@ -19159,6 +19228,7 @@ var NcConditionDescriptorSchema = object({
|
|
|
19159
19228
|
"plateMatcher",
|
|
19160
19229
|
"packagePhase",
|
|
19161
19230
|
"crossingSelect",
|
|
19231
|
+
"sensorTransition",
|
|
19162
19232
|
"polygonDraw",
|
|
19163
19233
|
"occupancy",
|
|
19164
19234
|
"audio",
|
|
@@ -19292,6 +19362,18 @@ var NC_CONDITION_CATALOG = [
|
|
|
19292
19362
|
value: "device-consumable-normal",
|
|
19293
19363
|
label: "Consumable replaced"
|
|
19294
19364
|
},
|
|
19365
|
+
{
|
|
19366
|
+
value: "device-tank-low",
|
|
19367
|
+
label: "Tank low (water, detergent)"
|
|
19368
|
+
},
|
|
19369
|
+
{
|
|
19370
|
+
value: "device-tank-full",
|
|
19371
|
+
label: "Tank full (dirty water, dust)"
|
|
19372
|
+
},
|
|
19373
|
+
{
|
|
19374
|
+
value: "device-tank-normal",
|
|
19375
|
+
label: "Tank back to normal"
|
|
19376
|
+
},
|
|
19295
19377
|
{
|
|
19296
19378
|
value: "export-completed",
|
|
19297
19379
|
label: "Export completed"
|
|
@@ -19357,6 +19439,21 @@ var NC_CONDITION_CATALOG = [
|
|
|
19357
19439
|
phase: "P1",
|
|
19358
19440
|
description: "Restrict the rule to these devices; absent = all devices. A sensor event matches either the SENSOR that fired or the camera it is attributed to, so a rule may name either one."
|
|
19359
19441
|
},
|
|
19442
|
+
{
|
|
19443
|
+
id: "devicesExclude",
|
|
19444
|
+
group: "scope",
|
|
19445
|
+
label: "Excluded devices",
|
|
19446
|
+
valueType: "deviceIdExcludeList",
|
|
19447
|
+
operator: "notIn",
|
|
19448
|
+
appliesTo: [
|
|
19449
|
+
"immediate",
|
|
19450
|
+
"track-end",
|
|
19451
|
+
"device-event",
|
|
19452
|
+
"package-event"
|
|
19453
|
+
],
|
|
19454
|
+
phase: "P1",
|
|
19455
|
+
description: "Every device except these. Judged on the same device ids as Devices: a sensor event is excluded by the SENSOR that fired or by the camera it is attributed to."
|
|
19456
|
+
},
|
|
19360
19457
|
{
|
|
19361
19458
|
id: "classes",
|
|
19362
19459
|
group: "class",
|
|
@@ -19613,6 +19710,33 @@ var NC_CONDITION_CATALOG = [
|
|
|
19613
19710
|
phase: "P1",
|
|
19614
19711
|
description: "Raw device event-type tokens (e.g. doorbell press / press_long) from the event-emitter slice; absent on doorbell-pulse / passive sensors."
|
|
19615
19712
|
},
|
|
19713
|
+
{
|
|
19714
|
+
id: "sensorTransition",
|
|
19715
|
+
group: "device",
|
|
19716
|
+
label: "Notify when",
|
|
19717
|
+
valueType: "sensorTransition",
|
|
19718
|
+
options: [
|
|
19719
|
+
{
|
|
19720
|
+
value: "",
|
|
19721
|
+
label: "It triggers and when it clears",
|
|
19722
|
+
hint: "Every change: water detected, and back to dry."
|
|
19723
|
+
},
|
|
19724
|
+
{
|
|
19725
|
+
value: "raised",
|
|
19726
|
+
label: "Only when it triggers",
|
|
19727
|
+
hint: "Water detected, smoke, a contact opening — never the return to normal."
|
|
19728
|
+
},
|
|
19729
|
+
{
|
|
19730
|
+
value: "cleared",
|
|
19731
|
+
label: "Only when it clears",
|
|
19732
|
+
hint: "Back to dry, smoke gone, a contact closing — never the alert itself."
|
|
19733
|
+
}
|
|
19734
|
+
],
|
|
19735
|
+
operator: "in",
|
|
19736
|
+
appliesTo: ["device-event"],
|
|
19737
|
+
phase: "P2",
|
|
19738
|
+
description: "Fire on one edge of a boolean sensor. Offered only when every chosen sensor kind raises and clears; a reading that cannot be placed still notifies."
|
|
19739
|
+
},
|
|
19616
19740
|
{
|
|
19617
19741
|
id: "packagePhase",
|
|
19618
19742
|
group: "package",
|
|
@@ -19796,6 +19920,28 @@ var NcHistoryFilterSchema = object({
|
|
|
19796
19920
|
limit: number().int().min(1).max(500).default(100)
|
|
19797
19921
|
});
|
|
19798
19922
|
/**
|
|
19923
|
+
* Every rule's last run, in one answer.
|
|
19924
|
+
*
|
|
19925
|
+
* A rule ABSENT from `runs` produced no delivery inside `horizonMs` — how far
|
|
19926
|
+
* back this answer looked, in ms before the hub's now. It is the outbox prune
|
|
19927
|
+
* window (7 days by default, operator-configurable), NARROWED when the read hit
|
|
19928
|
+
* its row bound: the answer never claims a window it did not read. `null` means
|
|
19929
|
+
* the operator keeps the outbox forever AND the read reached its end, so absent
|
|
19930
|
+
* means "never on record". A UI derives its "not in the last N days" from this
|
|
19931
|
+
* value, never from a constant — and only when the call ANSWERED (D315).
|
|
19932
|
+
*/
|
|
19933
|
+
var NcRuleLastRunsSchema = object({
|
|
19934
|
+
runs: array(object({
|
|
19935
|
+
ruleId: string(),
|
|
19936
|
+
/** Fire time of the newest row (`createdAt`, epoch ms). */
|
|
19937
|
+
lastAt: number(),
|
|
19938
|
+
status: NcHistoryStatusSchema,
|
|
19939
|
+
/** The camera/device of that row (a digest row files under its first camera). */
|
|
19940
|
+
deviceId: number()
|
|
19941
|
+
})),
|
|
19942
|
+
horizonMs: number().nonnegative().nullable()
|
|
19943
|
+
});
|
|
19944
|
+
/**
|
|
19799
19945
|
* What a snooze covers. Broader scopes win when several overlap, so one window
|
|
19800
19946
|
* leaves ONE digest rather than a rule snooze and a whole-feed snooze both
|
|
19801
19947
|
* summarising the same silence.
|
|
@@ -19977,6 +20123,14 @@ var NcAlarmModeCoverageSchema = object({
|
|
|
19977
20123
|
/** Ids named by the covering rules. A SUBSET when `allDevices` is true. */
|
|
19978
20124
|
deviceIds: array(number().int()),
|
|
19979
20125
|
/**
|
|
20126
|
+
* D641: the ids NOT covered although `allDevices` is true — every unscoped
|
|
20127
|
+
* covering rule EXCLUDES them (`conditions.devicesExclude`) and no named rule
|
|
20128
|
+
* covers them. Always `[]` when `allDevices` is false. Excluded by the rules,
|
|
20129
|
+
* which is not the same as skipped by a switch: never in `skippedDevices`.
|
|
20130
|
+
* Defaulted so an answer computed before this field parses as "none".
|
|
20131
|
+
*/
|
|
20132
|
+
allDevicesExcept: array(number().int()).default([]),
|
|
20133
|
+
/**
|
|
19980
20134
|
* Devices this mode NAMES but cannot actually arm, each with the switch that
|
|
19981
20135
|
* excludes it.
|
|
19982
20136
|
*
|
|
@@ -20200,6 +20354,15 @@ var notificationRulesCapability = {
|
|
|
20200
20354
|
*/
|
|
20201
20355
|
getHistory: method(object({ filter: NcHistoryFilterSchema.default({ limit: 100 }) }), object({ entries: array(NcHistoryEntrySchema) }), { auth: "admin" }),
|
|
20202
20356
|
/**
|
|
20357
|
+
* The newest delivery of every rule, in ONE bounded read of the outbox —
|
|
20358
|
+
* the "Last run" column. Never a `getHistory` per rule. A rule with no
|
|
20359
|
+
* delivery inside `horizonMs` is absent from `runs`; see
|
|
20360
|
+
* {@link NcRuleLastRunsSchema} for what absent means. A store that cannot
|
|
20361
|
+
* answer FAILS the call rather than answering "nothing ran". Admin-only,
|
|
20362
|
+
* like `getHistory`, of which it is a projection.
|
|
20363
|
+
*/
|
|
20364
|
+
getRuleLastRuns: method(object({}), NcRuleLastRunsSchema, { auth: "admin" }),
|
|
20365
|
+
/**
|
|
20203
20366
|
* Mint a fresh, externally-reachable URL for one artefact a history row
|
|
20204
20367
|
* named in {@link NcHistoryEntrySchema.shape.artifactIds} — the SAME
|
|
20205
20368
|
* signed-link mechanism the dispatcher uses to attach media to an
|
|
@@ -29606,12 +29769,20 @@ reset: method(object({
|
|
|
29606
29769
|
},
|
|
29607
29770
|
runtimeState: ConsumablesStatusSchema.extend({ lastFetchedAt: number() }),
|
|
29608
29771
|
/**
|
|
29609
|
-
* Runtime-state durability: **
|
|
29772
|
+
* Runtime-state durability: **restored** — nothing else holds the value
|
|
29773
|
+
* (D642). A consumable can often be read only in a device's wake window (the
|
|
29774
|
+
* Dreame mower's CMS counters answer only while it charges), so a restart
|
|
29775
|
+
* that wiped the slice left the panel empty and the alerts blind until the
|
|
29776
|
+
* next wake — 2026-09-26, mower 503 idle with `items: []`. A restored item is
|
|
29777
|
+
* the previous observation, not a claim about now; the provider overwrites it
|
|
29778
|
+
* the moment it reads the device again.
|
|
29610
29779
|
*
|
|
29611
29780
|
* See `RuntimeStateDurability`. Enforced by
|
|
29612
29781
|
* `scripts/check-runtime-state-durability.ts`.
|
|
29613
29782
|
*/
|
|
29614
|
-
durability: "
|
|
29783
|
+
durability: "restored",
|
|
29784
|
+
/** Clocks, not content: a re-read that changed no item costs no commit. */
|
|
29785
|
+
volatileStateFields: ["lastChangedAt", "lastFetchedAt"]
|
|
29615
29786
|
};
|
|
29616
29787
|
/**
|
|
29617
29788
|
* Door / window / opening / garage / valve contact sensor. Boolean
|
|
@@ -44977,6 +45148,12 @@ Object.freeze({
|
|
|
44977
45148
|
addonId: null,
|
|
44978
45149
|
access: "view"
|
|
44979
45150
|
},
|
|
45151
|
+
"notificationRules.getRuleLastRuns": {
|
|
45152
|
+
capName: "notification-rules",
|
|
45153
|
+
capScope: "system",
|
|
45154
|
+
addonId: null,
|
|
45155
|
+
access: "view"
|
|
45156
|
+
},
|
|
44980
45157
|
"notificationRules.getTemplateCatalog": {
|
|
44981
45158
|
capName: "notification-rules",
|
|
44982
45159
|
capScope: "system",
|
|
@@ -50593,12 +50770,55 @@ function audioModeOf(value) {
|
|
|
50593
50770
|
return null;
|
|
50594
50771
|
}
|
|
50595
50772
|
new Set(["devices", "classes"]);
|
|
50596
|
-
/**
|
|
50773
|
+
/**
|
|
50774
|
+
* WHICH narrowing filter speaks about WHICH system-event kind — one predicate,
|
|
50775
|
+
* consumed by the rule ENGINE and by every rule EDITOR.
|
|
50776
|
+
*
|
|
50777
|
+
* ── The failure this file exists for ───────────────────────────────────────
|
|
50778
|
+
* `NcSystemEventConditionSchema` carries four optional narrowing lists
|
|
50779
|
+
* (`deviceIds`, `deviceTypes`, `nodeIds`, `packageNames`) beside a required
|
|
50780
|
+
* `kinds` gate. They are not four filters over one vocabulary: each belongs to
|
|
50781
|
+
* a FAMILY of kinds and is meaningless outside it. A node going away has no
|
|
50782
|
+
* device type; a completed export has no package; `stream-offline` deliberately
|
|
50783
|
+
* carries no device type at all (a stream belongs to a camera by construction).
|
|
50784
|
+
*
|
|
50785
|
+
* The engine applied all four to every kind, so a filter from one family failed
|
|
50786
|
+
* a kind from another family CLOSED. The operator's live rule "Eventi di
|
|
50787
|
+
* sistema" selected eleven kinds and set `deviceTypes: ['camera']` — the only
|
|
50788
|
+
* way to say "only my cameras" about the two liveness kinds — and NINE of the
|
|
50789
|
+
* eleven silently stopped being deliverable. Four days of history contained
|
|
50790
|
+
* `device-online` and `device-offline` and nothing else, across a window in
|
|
50791
|
+
* which agents were restarted and addons were updated.
|
|
50792
|
+
*
|
|
50793
|
+
* Both editors already computed this scoping, to decide which filter boxes to
|
|
50794
|
+
* render; the cap's own docblock already promised it ("Narrow a `device-*` kind
|
|
50795
|
+
* to these device TYPES"). Only the engine disagreed, and it disagreed in the
|
|
50796
|
+
* destructive direction. So the rule is stated ONCE, here, and the engine and
|
|
50797
|
+
* the editors are readers of it rather than three independent authors.
|
|
50798
|
+
*
|
|
50799
|
+
* ── The direction ─────────────────────────────────────────────────────────
|
|
50800
|
+
* Out of family ⇒ the filter is IGNORED, never fail-closed. An editor that
|
|
50801
|
+
* hides a box has already told the operator this filter does not speak about
|
|
50802
|
+
* these kinds, so honouring it as an exclusion contradicts the only
|
|
50803
|
+
* explanation the operator was ever given. Inside its family the filter still
|
|
50804
|
+
* narrows, and still fails CLOSED on a subject that cannot produce the identity
|
|
50805
|
+
* it tests (a device the mirror cannot name is not evidence of a camera).
|
|
50806
|
+
*/
|
|
50807
|
+
/**
|
|
50808
|
+
* Every filter, for the callers that must cover all of them (guards, tests).
|
|
50809
|
+
*
|
|
50810
|
+
* `consumableLowPercent` (D642) is not a list but it is a filter in exactly
|
|
50811
|
+
* this sense: it belongs to a family of kinds (the consumable pair) and the
|
|
50812
|
+
* engine consults it only there. It differs in one way the readers must know —
|
|
50813
|
+
* its ABSENCE is not "no narrowing" but the default threshold, because a
|
|
50814
|
+
* consumable episode is always judged at SOME threshold.
|
|
50815
|
+
*/
|
|
50597
50816
|
var NC_SYSTEM_EVENT_FILTER_KEYS = [
|
|
50598
50817
|
"deviceIds",
|
|
50599
50818
|
"deviceTypes",
|
|
50600
50819
|
"nodeIds",
|
|
50601
|
-
"packageNames"
|
|
50820
|
+
"packageNames",
|
|
50821
|
+
"consumableLowPercent"
|
|
50602
50822
|
];
|
|
50603
50823
|
/**
|
|
50604
50824
|
* Does `filter` say anything about `kind`?
|
|
@@ -50612,6 +50832,7 @@ function systemEventFilterApplies(kind, filter) {
|
|
|
50612
50832
|
case "deviceTypes": return kind.startsWith("device-") || kind === "detection-blind";
|
|
50613
50833
|
case "nodeIds": return kind.startsWith("node-") || kind === "addon-crash-loop" || kind === "addon-update-available" || kind === "addon-updated" || kind === "server-update-available" || kind === "wrapper-update-available" || kind === "server-updated";
|
|
50614
50834
|
case "packageNames": return kind.endsWith("update-available") || kind === "addon-updated" || kind === "server-updated";
|
|
50835
|
+
case "consumableLowPercent": return NC_CONSUMABLE_SYSTEM_EVENT_KINDS.includes(kind);
|
|
50615
50836
|
}
|
|
50616
50837
|
}
|
|
50617
50838
|
/**
|
|
@@ -50647,6 +50868,9 @@ var NC_SYSTEM_EVENT_FAMILY = {
|
|
|
50647
50868
|
"device-battery-normal": "device-events",
|
|
50648
50869
|
"device-consumable-low": "device-events",
|
|
50649
50870
|
"device-consumable-normal": "device-events",
|
|
50871
|
+
"device-tank-low": "device-events",
|
|
50872
|
+
"device-tank-full": "device-events",
|
|
50873
|
+
"device-tank-normal": "device-events",
|
|
50650
50874
|
"stream-online": "device-events",
|
|
50651
50875
|
"stream-offline": "device-events",
|
|
50652
50876
|
"detection-blind": "device-events",
|
|
@@ -50678,7 +50902,7 @@ var NC_SYSTEM_EVENT_FAMILY = {
|
|
|
50678
50902
|
new Map(Object.entries(NC_SYSTEM_EVENT_FAMILY));
|
|
50679
50903
|
var NC_SYSTEM_EVENT_CONDITION_FILTER_KEYS = [...NC_SYSTEM_EVENT_FILTER_KEYS, "excludeDeviceIds"];
|
|
50680
50904
|
/**
|
|
50681
|
-
* The filters a family may carry. The
|
|
50905
|
+
* The filters a family may carry. The base filters are the union of
|
|
50682
50906
|
* `systemEventFilterApplies` over the family's kinds (the spec pins that
|
|
50683
50907
|
* equality). `excludeDeviceIds` is a device-events filter only: an alarm is
|
|
50684
50908
|
* narrowed to the camera that triggered it and excludes nothing.
|
|
@@ -50687,7 +50911,8 @@ var NC_SYSTEM_EVENT_FAMILY_FILTERS = {
|
|
|
50687
50911
|
"device-events": [
|
|
50688
50912
|
"deviceIds",
|
|
50689
50913
|
"excludeDeviceIds",
|
|
50690
|
-
"deviceTypes"
|
|
50914
|
+
"deviceTypes",
|
|
50915
|
+
"consumableLowPercent"
|
|
50691
50916
|
],
|
|
50692
50917
|
system: ["nodeIds", "packageNames"],
|
|
50693
50918
|
alarm: ["deviceIds"]
|
|
@@ -50722,6 +50947,16 @@ var NC_SYSTEM_EVENT_KIND_GROUP_SPECS = [
|
|
|
50722
50947
|
label: "Consumables",
|
|
50723
50948
|
kinds: ["device-consumable-low", "device-consumable-normal"]
|
|
50724
50949
|
},
|
|
50950
|
+
{
|
|
50951
|
+
id: "tanks",
|
|
50952
|
+
family: "device-events",
|
|
50953
|
+
label: "Tanks",
|
|
50954
|
+
kinds: [
|
|
50955
|
+
"device-tank-low",
|
|
50956
|
+
"device-tank-full",
|
|
50957
|
+
"device-tank-normal"
|
|
50958
|
+
]
|
|
50959
|
+
},
|
|
50725
50960
|
{
|
|
50726
50961
|
id: "detection-blind",
|
|
50727
50962
|
family: "device-events",
|
|
@@ -50901,10 +51136,75 @@ function isScheduleActive(schedule, atMs) {
|
|
|
50901
51136
|
}
|
|
50902
51137
|
return schedule.invert === true ? !inside : inside;
|
|
50903
51138
|
}
|
|
51139
|
+
var ARMED_WORD_PREFIX = "armed_";
|
|
51140
|
+
var ALARM_PANEL_CAP = "alarm-panel";
|
|
51141
|
+
var ALARM_PANEL_TRIGGER_METHOD = "trigger";
|
|
51142
|
+
/**
|
|
51143
|
+
* A rule belongs to the alarm when its `deviceState` gate names ANY device's
|
|
51144
|
+
* `armed_*` word, or an ENABLED `onTrigger` sequence pulls the alarm panel's
|
|
51145
|
+
* trigger (D630).
|
|
51146
|
+
*/
|
|
51147
|
+
function ruleBelongsToAlarm(rule) {
|
|
51148
|
+
if ((rule.conditions.deviceState?.states ?? []).some((s) => s.trim().toLowerCase().startsWith(ARMED_WORD_PREFIX))) return true;
|
|
51149
|
+
return (rule.onTrigger ?? []).some((sequence) => sequence.enabled && sequence.actions.some((step) => step.kind === "cap" && step.cap === ALARM_PANEL_CAP && step.method === ALARM_PANEL_TRIGGER_METHOD));
|
|
51150
|
+
}
|
|
51151
|
+
/**
|
|
51152
|
+
* WHICH WAY A BOOLEAN SENSOR MOVED — read off the one slice a sensor event
|
|
51153
|
+
* persists (D640 "a sensor rule fires on the raise, the clear, or both").
|
|
51154
|
+
*
|
|
51155
|
+
* A device-event rule over a flood sensor notified on BOTH edges: water
|
|
51156
|
+
* detected, and back to dry. `NcConditions.sensorTransition` lets the rule
|
|
51157
|
+
* name one edge; this file answers, for one `SensorEvent`, which edge it is.
|
|
51158
|
+
*
|
|
51159
|
+
* NOT A SECOND TABLE. The "which boolean of this cap counts as HIGH" question
|
|
51160
|
+
* already has one answer, `SOURCE_CAP_ACTIVE_FIELD`
|
|
51161
|
+
* (`catalogs/sensor-active-state.ts`, the doorbell's and the recorder's edge
|
|
51162
|
+
* table), and a sensor event names its kind, not its cap. So the table here is
|
|
51163
|
+
* DERIVED: event kind → cap (`EVENT_KIND_BY_CAP`) → that cap's active field.
|
|
51164
|
+
* Only kinds whose taxonomy category is `sensor` take part — a switch has an
|
|
51165
|
+
* `on` boolean too, but "it triggers / it clears" is not a sentence about a
|
|
51166
|
+
* light, and offering it there would be a knob with a misleading label.
|
|
51167
|
+
* `presence` is a WORD (`home` / `not_home` / a zone), not a boolean, and is
|
|
51168
|
+
* absent from the source table, so it is absent here.
|
|
51169
|
+
*
|
|
51170
|
+
* `undefined` = never guessed: a kind with no raise (a doorbell press, a
|
|
51171
|
+
* button, a cover), or a slice whose field is missing or not a boolean. The
|
|
51172
|
+
* engine then does NOT filter — a flood alert must not go silent because one
|
|
51173
|
+
* read came back unreadable (the same stance as the alarm's `sensorEdgeOf`).
|
|
51174
|
+
*
|
|
51175
|
+
* Pure, RN-safe: the viewer imports the support rule from here.
|
|
51176
|
+
*/
|
|
51177
|
+
/** Event kind → the boolean field of its cap slice that means "raised". */
|
|
51178
|
+
var NC_SENSOR_RAISED_FIELD_BY_KIND = Object.freeze(Object.fromEntries(Object.entries(EVENT_KIND_BY_CAP).flatMap(([capName, descriptor]) => {
|
|
51179
|
+
const field = SOURCE_CAP_ACTIVE_FIELD[capName];
|
|
51180
|
+
if (field === void 0 || descriptor.category !== "sensor") return [];
|
|
51181
|
+
return [[descriptor.kind, field]];
|
|
51182
|
+
})));
|
|
51183
|
+
/** The sensor kinds `sensorTransition` means something for. */
|
|
51184
|
+
var NC_SENSOR_TRANSITION_KINDS = Object.freeze(Object.keys(NC_SENSOR_RAISED_FIELD_BY_KIND));
|
|
51185
|
+
function normaliseKind(kind) {
|
|
51186
|
+
return kind.trim().toLowerCase();
|
|
51187
|
+
}
|
|
51188
|
+
/**
|
|
51189
|
+
* true = the sensor is raised (water, smoke, open, tampered…), false = it
|
|
51190
|
+
* cleared, undefined = this kind has no raise or the slice cannot say.
|
|
51191
|
+
*/
|
|
51192
|
+
function sensorRaisedOf(kind, value) {
|
|
51193
|
+
if (value === null) return void 0;
|
|
51194
|
+
const field = NC_SENSOR_RAISED_FIELD_BY_KIND[normaliseKind(kind)];
|
|
51195
|
+
if (field === void 0) return void 0;
|
|
51196
|
+
const raw = Object.entries(value).find(([key]) => key === field)?.[1];
|
|
51197
|
+
return typeof raw === "boolean" ? raw : void 0;
|
|
51198
|
+
}
|
|
50904
51199
|
var RULE_BODY_ONLY = ["body"];
|
|
50905
51200
|
var RULE_TEXT = ["title", "body"];
|
|
50906
51201
|
var BATTERY = ["device-battery-low", "device-battery-normal"];
|
|
50907
51202
|
var CONSUMABLE = ["device-consumable-low", "device-consumable-normal"];
|
|
51203
|
+
var TANK = [
|
|
51204
|
+
"device-tank-low",
|
|
51205
|
+
"device-tank-full",
|
|
51206
|
+
"device-tank-normal"
|
|
51207
|
+
];
|
|
50908
51208
|
var UPDATES = [
|
|
50909
51209
|
"addon-update-available",
|
|
50910
51210
|
"server-update-available",
|
|
@@ -50930,6 +51230,7 @@ var DEVICE_EVENTS = [
|
|
|
50930
51230
|
"device-enabled",
|
|
50931
51231
|
...BATTERY,
|
|
50932
51232
|
...CONSUMABLE,
|
|
51233
|
+
...TANK,
|
|
50933
51234
|
"stream-online",
|
|
50934
51235
|
"stream-offline",
|
|
50935
51236
|
"detection-blind",
|
|
@@ -51227,6 +51528,17 @@ var NC_TEMPLATE_VARS = [
|
|
|
51227
51528
|
kinds: ["system"],
|
|
51228
51529
|
systemEventKinds: [...CONSUMABLE]
|
|
51229
51530
|
},
|
|
51531
|
+
{
|
|
51532
|
+
name: "tank",
|
|
51533
|
+
label: "Tank",
|
|
51534
|
+
description: "Which tank: clean water, dirty water, detergent or dust bin.",
|
|
51535
|
+
example: "clean water",
|
|
51536
|
+
group: "system",
|
|
51537
|
+
families: ["rule"],
|
|
51538
|
+
fields: [...RULE_TEXT],
|
|
51539
|
+
kinds: ["system"],
|
|
51540
|
+
systemEventKinds: [...TANK]
|
|
51541
|
+
},
|
|
51230
51542
|
{
|
|
51231
51543
|
name: "profile",
|
|
51232
51544
|
label: "Stream profile",
|
|
@@ -51619,6 +51931,38 @@ var NC_TEMPLATE_VARS = [
|
|
|
51619
51931
|
fields: [...RULE_TEXT]
|
|
51620
51932
|
}
|
|
51621
51933
|
];
|
|
51934
|
+
/**
|
|
51935
|
+
* System-event kinds the SERVED catalog holds back (D642): the kinds the hub
|
|
51936
|
+
* produces before the installed viewers can parse them.
|
|
51937
|
+
*
|
|
51938
|
+
* The viewer parses `getTemplateCatalog` WHOLE, with its own strict
|
|
51939
|
+
* `NcSystemEventKindSchema` on every descriptor's `systemEventKinds`, so one
|
|
51940
|
+
* kind it does not know — in `{{deviceName}}`, which every device event names —
|
|
51941
|
+
* empties every {{var}} picker on every phone (the same trap
|
|
51942
|
+
* `NcTemplateVarKindSchema` froze the rule kinds for). The in-process catalog
|
|
51943
|
+
* keeps them: the producer parity and the preview render read it.
|
|
51944
|
+
*
|
|
51945
|
+
* SELF-EXPIRING: `scripts/check-nc-mirrors-in-sync.ts` reads this list as the
|
|
51946
|
+
* viewer's allowance and fails the day the viewer mirrors one of these kinds —
|
|
51947
|
+
* delete it from here then, and the served catalog names it again.
|
|
51948
|
+
*/
|
|
51949
|
+
var NC_TEMPLATE_HELD_BACK_SYSTEM_EVENT_KINDS = [
|
|
51950
|
+
"device-tank-low",
|
|
51951
|
+
"device-tank-full",
|
|
51952
|
+
"device-tank-normal"
|
|
51953
|
+
];
|
|
51954
|
+
/**
|
|
51955
|
+
* The catalog as `getTemplateCatalog` SERVES it: every descriptor, with the
|
|
51956
|
+
* held-back kinds removed from its `systemEventKinds`. A descriptor that named
|
|
51957
|
+
* only held-back kinds is served with an empty list — offered to no system
|
|
51958
|
+
* rule an installed viewer can author, which is exactly true.
|
|
51959
|
+
*/
|
|
51960
|
+
function servedTemplateVars() {
|
|
51961
|
+
return NC_TEMPLATE_VARS.map((d) => d.systemEventKinds === void 0 ? d : {
|
|
51962
|
+
...d,
|
|
51963
|
+
systemEventKinds: d.systemEventKinds.filter((kind) => !NC_TEMPLATE_HELD_BACK_SYSTEM_EVENT_KINDS.includes(kind))
|
|
51964
|
+
});
|
|
51965
|
+
}
|
|
51622
51966
|
/** The caption fields see a fixed, smaller vocabulary (`timelapsePreviewText`,
|
|
51623
51967
|
* `summaryCaptionText`). Declared here rather than as `fields` on every
|
|
51624
51968
|
* descriptor so the whole rule stays in one line of code. */
|
|
@@ -52885,18 +53229,36 @@ Object.defineProperty(exports, "NC_CONDITION_CATALOG", {
|
|
|
52885
53229
|
return NC_CONDITION_CATALOG;
|
|
52886
53230
|
}
|
|
52887
53231
|
});
|
|
53232
|
+
Object.defineProperty(exports, "NC_CONSUMABLE_SYSTEM_EVENT_KINDS", {
|
|
53233
|
+
enumerable: true,
|
|
53234
|
+
get: function() {
|
|
53235
|
+
return NC_CONSUMABLE_SYSTEM_EVENT_KINDS;
|
|
53236
|
+
}
|
|
53237
|
+
});
|
|
52888
53238
|
Object.defineProperty(exports, "NC_DEFAULT_SNOOZE_MINUTES", {
|
|
52889
53239
|
enumerable: true,
|
|
52890
53240
|
get: function() {
|
|
52891
53241
|
return NC_DEFAULT_SNOOZE_MINUTES;
|
|
52892
53242
|
}
|
|
52893
53243
|
});
|
|
53244
|
+
Object.defineProperty(exports, "NC_SENSOR_TRANSITION_KINDS", {
|
|
53245
|
+
enumerable: true,
|
|
53246
|
+
get: function() {
|
|
53247
|
+
return NC_SENSOR_TRANSITION_KINDS;
|
|
53248
|
+
}
|
|
53249
|
+
});
|
|
52894
53250
|
Object.defineProperty(exports, "NC_SNOOZE_MAX_MINUTES", {
|
|
52895
53251
|
enumerable: true,
|
|
52896
53252
|
get: function() {
|
|
52897
53253
|
return NC_SNOOZE_MAX_MINUTES;
|
|
52898
53254
|
}
|
|
52899
53255
|
});
|
|
53256
|
+
Object.defineProperty(exports, "NC_TANK_SYSTEM_EVENT_KINDS", {
|
|
53257
|
+
enumerable: true,
|
|
53258
|
+
get: function() {
|
|
53259
|
+
return NC_TANK_SYSTEM_EVENT_KINDS;
|
|
53260
|
+
}
|
|
53261
|
+
});
|
|
52900
53262
|
Object.defineProperty(exports, "NC_TAXONOMY", {
|
|
52901
53263
|
enumerable: true,
|
|
52902
53264
|
get: function() {
|
|
@@ -53179,6 +53541,12 @@ Object.defineProperty(exports, "canonicalHash", {
|
|
|
53179
53541
|
return canonicalHash;
|
|
53180
53542
|
}
|
|
53181
53543
|
});
|
|
53544
|
+
Object.defineProperty(exports, "consumableLowPercentOf", {
|
|
53545
|
+
enumerable: true,
|
|
53546
|
+
get: function() {
|
|
53547
|
+
return consumableLowPercentOf;
|
|
53548
|
+
}
|
|
53549
|
+
});
|
|
53182
53550
|
Object.defineProperty(exports, "cosineSimilarity", {
|
|
53183
53551
|
enumerable: true,
|
|
53184
53552
|
get: function() {
|
|
@@ -53431,12 +53799,30 @@ Object.defineProperty(exports, "resolvePoolMemoryPolicy", {
|
|
|
53431
53799
|
return resolvePoolMemoryPolicy;
|
|
53432
53800
|
}
|
|
53433
53801
|
});
|
|
53802
|
+
Object.defineProperty(exports, "ruleBelongsToAlarm", {
|
|
53803
|
+
enumerable: true,
|
|
53804
|
+
get: function() {
|
|
53805
|
+
return ruleBelongsToAlarm;
|
|
53806
|
+
}
|
|
53807
|
+
});
|
|
53434
53808
|
Object.defineProperty(exports, "sceneMonitorCapability", {
|
|
53435
53809
|
enumerable: true,
|
|
53436
53810
|
get: function() {
|
|
53437
53811
|
return sceneMonitorCapability;
|
|
53438
53812
|
}
|
|
53439
53813
|
});
|
|
53814
|
+
Object.defineProperty(exports, "sensorRaisedOf", {
|
|
53815
|
+
enumerable: true,
|
|
53816
|
+
get: function() {
|
|
53817
|
+
return sensorRaisedOf;
|
|
53818
|
+
}
|
|
53819
|
+
});
|
|
53820
|
+
Object.defineProperty(exports, "servedTemplateVars", {
|
|
53821
|
+
enumerable: true,
|
|
53822
|
+
get: function() {
|
|
53823
|
+
return servedTemplateVars;
|
|
53824
|
+
}
|
|
53825
|
+
});
|
|
53440
53826
|
Object.defineProperty(exports, "sleep", {
|
|
53441
53827
|
enumerable: true,
|
|
53442
53828
|
get: function() {
|