@camstack/addon-provider-amcrest 0.2.157 → 0.2.159

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.mjs CHANGED
@@ -14,7 +14,7 @@ import { networkInterfaces } from "node:os";
14
14
  var __commonJSMin = (cb, mod) => () => (mod || (cb((mod = { exports: {} }).exports, mod), cb = null), mod.exports);
15
15
  var __require = /* @__PURE__ */ createRequire(import.meta.url);
16
16
  //#endregion
17
- //#region ../types/dist/event-category-BfJwUd2S.mjs
17
+ //#region ../types/dist/event-category-DHXxB8t9.mjs
18
18
  var EventCategory = /* @__PURE__ */ function(EventCategory) {
19
19
  EventCategory["SystemBoot"] = "system.boot";
20
20
  EventCategory["SystemAddonsReady"] = "system.addons-ready";
@@ -310,7 +310,7 @@ var EventCategory = /* @__PURE__ */ function(EventCategory) {
310
310
  * TRANSITION into that state (never per dispatch), and the node is dropped
311
311
  * from the placement candidate set for as long as it holds.
312
312
  *
313
- * This exists because the state was previously invisible: little-unraid
313
+ * This exists because the state was previously invisible: agent-a
314
314
  * absorbed 283k inference errors in a day while still being handed cameras,
315
315
  * and nothing in the system said so.
316
316
  *
@@ -341,9 +341,8 @@ var EventCategory = /* @__PURE__ */ function(EventCategory) {
341
341
  EventCategory["PipelineMotionCalm"] = "pipeline.motion-calm";
342
342
  /**
343
343
  * Per-camera pipeline config was mutated by the orchestrator
344
- * (3-level settings change via `setAgentAddonDefaults` /
345
- * `setCameraStepToggle` / `setCameraPipelineForAgent` or a
346
- * pipeline-scoped `applyDeviceSettingsPatch`). Orchestrator
344
+ * (a settings change via `setAgentInferenceDevices` /
345
+ * `setCameraStepToggle` / `setCameraStepSettings`). Orchestrator
347
346
  * subscribes to its own emission to hot-reload the assigned runner
348
347
  * via `attachCamera` so the next frame executes against the new
349
348
  * engine/steps without waiting for a rebalance or the next
@@ -487,6 +486,10 @@ var EventCategory = /* @__PURE__ */ function(EventCategory) {
487
486
  * on the device detail page.
488
487
  */
489
488
  EventCategory["DoorbellOnPressed"] = "doorbell.onPressed";
489
+ /** Mirrors `runningStateCapability.events.onStarted`. */
490
+ EventCategory["RunningStarted"] = "running.started";
491
+ /** Mirrors `runningStateCapability.events.onFinished`. */
492
+ EventCategory["RunningFinished"] = "running.finished";
490
493
  /**
491
494
  * Cap event fired by every device that registers the `event-emitter`
492
495
  * capability. Mirrors `eventEmitterCapability.events.onEvent`. Carries
@@ -5446,7 +5449,7 @@ var ZodIssueCode = {
5446
5449
  var ZodFirstPartyTypeKind;
5447
5450
  ZodFirstPartyTypeKind || (ZodFirstPartyTypeKind = {});
5448
5451
  //#endregion
5449
- //#region ../types/dist/sleep-6AqUnQIT.mjs
5452
+ //#region ../types/dist/sleep-BErAxhul.mjs
5450
5453
  /**
5451
5454
  * The audio chunk plane's byte format, and the ONE expansion from a coded
5452
5455
  * window to float samples (D455).
@@ -5785,7 +5788,7 @@ Object.fromEntries([
5785
5788
  * `hydrateSchema` to skip the `value` injection for structural-only fields.
5786
5789
  */
5787
5790
  function isValuelessField(field) {
5788
- return field.type === "separator" || field.type === "info" || field.type === "qr-code" || field.type === "button" || field.type === "object-array" || field.type === "widget" || field.type === "addon-action-button" || field.type === "device-action-button";
5791
+ return field.type === "separator" || field.type === "info" || field.type === "qr-code" || field.type === "button" || field.type === "object-array" || field.type === "widget" || field.type === "addon-action-button" || field.type === "device-action-button" || field.type === "account-sign-in" || field.type === "secret-presence";
5789
5792
  }
5790
5793
  function hydrateSchema(schema, values, options = {}) {
5791
5794
  return {
@@ -8469,6 +8472,1980 @@ method(object({ deviceId: number() }), array(StreamSourceEntrySchema)), method(o
8469
8472
  kind: "mutation",
8470
8473
  auth: "admin"
8471
8474
  }), method(object({ deviceId: number() }), unknown().nullable()), method(object({ deviceId: number() }), RawStateResultSchema.nullable(), { auth: "protected" });
8475
+ Object.freeze({ "doorbell": "lastPressedAt" });
8476
+ /** Every capability name, so addon code can check a name without the schema graph. */
8477
+ var CAP_NAMES = Object.freeze([
8478
+ "accessories",
8479
+ "addon-pages",
8480
+ "addon-pages-source",
8481
+ "addon-routes",
8482
+ "addon-settings",
8483
+ "addon-widgets",
8484
+ "addon-widgets-source",
8485
+ "addons",
8486
+ "admin-ui",
8487
+ "air-quality-sensor",
8488
+ "alarm-panel",
8489
+ "alerts",
8490
+ "ambient-light-sensor",
8491
+ "audio-analysis",
8492
+ "audio-analyzer",
8493
+ "audio-codec",
8494
+ "audio-metrics",
8495
+ "auth-provider",
8496
+ "automation-control",
8497
+ "backup",
8498
+ "battery",
8499
+ "binary",
8500
+ "brightness",
8501
+ "broker",
8502
+ "button",
8503
+ "calendar-source",
8504
+ "calendars",
8505
+ "camera-credentials",
8506
+ "camera-grid-layout",
8507
+ "camera-pipeline-config",
8508
+ "camera-streams",
8509
+ "carbon-monoxide",
8510
+ "climate-control",
8511
+ "color",
8512
+ "composer",
8513
+ "connection-test",
8514
+ "connectivity",
8515
+ "consumables",
8516
+ "contact",
8517
+ "control",
8518
+ "core-blocks",
8519
+ "cover",
8520
+ "custom-model-registry",
8521
+ "data-store-provider",
8522
+ "database-snapshot",
8523
+ "day-night",
8524
+ "decoder",
8525
+ "detection-pipeline",
8526
+ "device-admin-link",
8527
+ "device-adoption",
8528
+ "device-credentials",
8529
+ "device-discovery",
8530
+ "device-export",
8531
+ "device-extension",
8532
+ "device-history",
8533
+ "device-manager",
8534
+ "device-ops",
8535
+ "device-provider",
8536
+ "device-removal-hook",
8537
+ "device-state",
8538
+ "device-status",
8539
+ "dishwasher",
8540
+ "display-palette",
8541
+ "doorbell",
8542
+ "embedding-encoder",
8543
+ "enum-sensor",
8544
+ "event-emitter",
8545
+ "face-gallery",
8546
+ "failure-contribution",
8547
+ "fan-control",
8548
+ "feature-probe",
8549
+ "filesystem-browse",
8550
+ "flood",
8551
+ "gas",
8552
+ "heating-valve",
8553
+ "humidifier",
8554
+ "humidity-sensor",
8555
+ "image",
8556
+ "image-settings",
8557
+ "integrations",
8558
+ "intercom",
8559
+ "keychain",
8560
+ "keychain-admin",
8561
+ "lawn-mower-control",
8562
+ "llm",
8563
+ "llm-runtime",
8564
+ "load-contribution",
8565
+ "local-network",
8566
+ "lock-control",
8567
+ "log-channels",
8568
+ "log-destination",
8569
+ "login-method",
8570
+ "media-player",
8571
+ "mesh-network",
8572
+ "metrics-provider",
8573
+ "model-convert",
8574
+ "model-distributor",
8575
+ "motion",
8576
+ "motion-detection",
8577
+ "motion-trigger",
8578
+ "motion-zones",
8579
+ "mqtt-broker",
8580
+ "native-object-detection",
8581
+ "navigation",
8582
+ "network-access",
8583
+ "network-link",
8584
+ "network-quality",
8585
+ "node-certificates",
8586
+ "nodes",
8587
+ "notification-output",
8588
+ "notification-rules",
8589
+ "notifier",
8590
+ "numeric-sensor",
8591
+ "oauth-integration",
8592
+ "oidc-connections",
8593
+ "osd",
8594
+ "osd-manager",
8595
+ "pet-feeder",
8596
+ "pipeline-analytics",
8597
+ "pipeline-executor",
8598
+ "pipeline-orchestrator",
8599
+ "pipeline-runner",
8600
+ "plate-gallery",
8601
+ "platform-probe",
8602
+ "power-meter",
8603
+ "presence",
8604
+ "pressure-sensor",
8605
+ "privacy-mask",
8606
+ "ptz",
8607
+ "ptz-autotrack",
8608
+ "reboot",
8609
+ "record-entries",
8610
+ "recording",
8611
+ "recording-archive",
8612
+ "recording-export",
8613
+ "recording-onboard",
8614
+ "recording-signal",
8615
+ "records",
8616
+ "running-state",
8617
+ "scene-monitor",
8618
+ "script-runner",
8619
+ "server-management",
8620
+ "settings-store",
8621
+ "smoke",
8622
+ "smtp-provider",
8623
+ "snapshot",
8624
+ "sso-bridge",
8625
+ "storage",
8626
+ "storage-admin",
8627
+ "storage-evictable",
8628
+ "storage-migration",
8629
+ "storage-occupancy",
8630
+ "storage-provider",
8631
+ "stream-broker",
8632
+ "stream-catalog",
8633
+ "stream-params",
8634
+ "stream-signals",
8635
+ "switch",
8636
+ "system",
8637
+ "tamper",
8638
+ "temperature-sensor",
8639
+ "terminal-session",
8640
+ "toast",
8641
+ "training",
8642
+ "training-provider",
8643
+ "turn-provider",
8644
+ "update",
8645
+ "user-management",
8646
+ "user-passkeys",
8647
+ "vacuum-control",
8648
+ "valve",
8649
+ "vector-store",
8650
+ "vibration",
8651
+ "videoclips",
8652
+ "viewer-ui",
8653
+ "water-heater",
8654
+ "weather",
8655
+ "webrtc-session",
8656
+ "zone-analytics",
8657
+ "zone-rules",
8658
+ "zones"
8659
+ ]);
8660
+ Object.freeze({
8661
+ "air-quality-sensor": [
8662
+ {
8663
+ "path": "co2Ppm",
8664
+ "valueType": "number"
8665
+ },
8666
+ {
8667
+ "path": "vocPpb",
8668
+ "valueType": "number"
8669
+ },
8670
+ {
8671
+ "path": "pm25",
8672
+ "valueType": "number"
8673
+ },
8674
+ {
8675
+ "path": "pm10",
8676
+ "valueType": "number"
8677
+ },
8678
+ {
8679
+ "path": "aqi",
8680
+ "valueType": "number"
8681
+ },
8682
+ {
8683
+ "path": "unit",
8684
+ "valueType": "string"
8685
+ },
8686
+ {
8687
+ "path": "precision",
8688
+ "valueType": "number"
8689
+ }
8690
+ ],
8691
+ "alarm-panel": [
8692
+ {
8693
+ "path": "state",
8694
+ "valueType": "enum",
8695
+ "enumValues": [
8696
+ "disarmed",
8697
+ "armed_home",
8698
+ "armed_away",
8699
+ "armed_night",
8700
+ "armed_vacation",
8701
+ "armed_custom_bypass",
8702
+ "arming",
8703
+ "disarming",
8704
+ "pending",
8705
+ "triggered"
8706
+ ]
8707
+ },
8708
+ {
8709
+ "path": "targetMode",
8710
+ "valueType": "enum",
8711
+ "enumValues": [
8712
+ "home",
8713
+ "away",
8714
+ "night",
8715
+ "vacation",
8716
+ "custom_bypass"
8717
+ ]
8718
+ },
8719
+ {
8720
+ "path": "requiresCode",
8721
+ "valueType": "boolean"
8722
+ }
8723
+ ],
8724
+ "ambient-light-sensor": [
8725
+ {
8726
+ "path": "lux",
8727
+ "valueType": "number"
8728
+ },
8729
+ {
8730
+ "path": "unit",
8731
+ "valueType": "string"
8732
+ },
8733
+ {
8734
+ "path": "precision",
8735
+ "valueType": "number"
8736
+ }
8737
+ ],
8738
+ "audio-metrics": [
8739
+ {
8740
+ "path": "ts",
8741
+ "valueType": "number"
8742
+ },
8743
+ {
8744
+ "path": "windowSec",
8745
+ "valueType": "number"
8746
+ },
8747
+ {
8748
+ "path": "level.rms",
8749
+ "valueType": "number"
8750
+ },
8751
+ {
8752
+ "path": "level.dbfs",
8753
+ "valueType": "number"
8754
+ },
8755
+ {
8756
+ "path": "peakDbfs",
8757
+ "valueType": "number"
8758
+ },
8759
+ {
8760
+ "path": "avgDbfs",
8761
+ "valueType": "number"
8762
+ },
8763
+ {
8764
+ "path": "current.className",
8765
+ "valueType": "string"
8766
+ },
8767
+ {
8768
+ "path": "current.score",
8769
+ "valueType": "number"
8770
+ },
8771
+ {
8772
+ "path": "current.timestamp",
8773
+ "valueType": "number"
8774
+ }
8775
+ ],
8776
+ "automation-control": [
8777
+ {
8778
+ "path": "enabled",
8779
+ "valueType": "boolean"
8780
+ },
8781
+ {
8782
+ "path": "isRunning",
8783
+ "valueType": "boolean"
8784
+ },
8785
+ {
8786
+ "path": "lastTriggeredAt",
8787
+ "valueType": "number"
8788
+ },
8789
+ {
8790
+ "path": "lastError",
8791
+ "valueType": "string"
8792
+ }
8793
+ ],
8794
+ "battery": [
8795
+ {
8796
+ "path": "percentage",
8797
+ "valueType": "number"
8798
+ },
8799
+ {
8800
+ "path": "charging",
8801
+ "valueType": "enum",
8802
+ "enumValues": [
8803
+ "dc",
8804
+ "solar",
8805
+ "none",
8806
+ "unknown"
8807
+ ]
8808
+ },
8809
+ {
8810
+ "path": "sleeping",
8811
+ "valueType": "boolean"
8812
+ },
8813
+ {
8814
+ "path": "lastUpdated",
8815
+ "valueType": "number"
8816
+ },
8817
+ {
8818
+ "path": "lastContactAt",
8819
+ "valueType": "number"
8820
+ },
8821
+ {
8822
+ "path": "lastFullRefreshAt",
8823
+ "valueType": "number"
8824
+ },
8825
+ {
8826
+ "path": "binary",
8827
+ "valueType": "boolean"
8828
+ }
8829
+ ],
8830
+ "binary": [{
8831
+ "path": "on",
8832
+ "valueType": "boolean"
8833
+ }],
8834
+ "brightness": [{
8835
+ "path": "percentage",
8836
+ "valueType": "number"
8837
+ }],
8838
+ "broker": [{
8839
+ "path": "brokerCount",
8840
+ "valueType": "number"
8841
+ }, {
8842
+ "path": "connectedCount",
8843
+ "valueType": "number"
8844
+ }],
8845
+ "camera-credentials": [
8846
+ {
8847
+ "path": "host",
8848
+ "valueType": "string"
8849
+ },
8850
+ {
8851
+ "path": "port",
8852
+ "valueType": "number"
8853
+ },
8854
+ {
8855
+ "path": "onvifPort",
8856
+ "valueType": "number"
8857
+ },
8858
+ {
8859
+ "path": "rtspPort",
8860
+ "valueType": "number"
8861
+ },
8862
+ {
8863
+ "path": "https",
8864
+ "valueType": "boolean"
8865
+ },
8866
+ {
8867
+ "path": "hasUsername",
8868
+ "valueType": "boolean"
8869
+ },
8870
+ {
8871
+ "path": "hasPassword",
8872
+ "valueType": "boolean"
8873
+ },
8874
+ {
8875
+ "path": "onvifProfile",
8876
+ "valueType": "string"
8877
+ }
8878
+ ],
8879
+ "camera-streams": [
8880
+ {
8881
+ "path": "online",
8882
+ "valueType": "boolean"
8883
+ },
8884
+ {
8885
+ "path": "slotStatuses.high",
8886
+ "valueType": "enum",
8887
+ "enumValues": [
8888
+ "unassigned",
8889
+ "idle",
8890
+ "connecting",
8891
+ "streaming",
8892
+ "error"
8893
+ ]
8894
+ },
8895
+ {
8896
+ "path": "slotStatuses.mid",
8897
+ "valueType": "enum",
8898
+ "enumValues": [
8899
+ "unassigned",
8900
+ "idle",
8901
+ "connecting",
8902
+ "streaming",
8903
+ "error"
8904
+ ]
8905
+ },
8906
+ {
8907
+ "path": "slotStatuses.low",
8908
+ "valueType": "enum",
8909
+ "enumValues": [
8910
+ "unassigned",
8911
+ "idle",
8912
+ "connecting",
8913
+ "streaming",
8914
+ "error"
8915
+ ]
8916
+ },
8917
+ {
8918
+ "path": "slotErrors.high",
8919
+ "valueType": "string"
8920
+ },
8921
+ {
8922
+ "path": "slotErrors.mid",
8923
+ "valueType": "string"
8924
+ },
8925
+ {
8926
+ "path": "slotErrors.low",
8927
+ "valueType": "string"
8928
+ }
8929
+ ],
8930
+ "carbon-monoxide": [{
8931
+ "path": "detected",
8932
+ "valueType": "boolean"
8933
+ }],
8934
+ "climate-control": [
8935
+ {
8936
+ "path": "mode",
8937
+ "valueType": "enum",
8938
+ "enumValues": [
8939
+ "off",
8940
+ "heat",
8941
+ "cool",
8942
+ "auto",
8943
+ "heat_cool",
8944
+ "fan_only",
8945
+ "dry"
8946
+ ]
8947
+ },
8948
+ {
8949
+ "path": "fanMode",
8950
+ "valueType": "string"
8951
+ },
8952
+ {
8953
+ "path": "preset",
8954
+ "valueType": "string"
8955
+ },
8956
+ {
8957
+ "path": "target",
8958
+ "valueType": "number"
8959
+ },
8960
+ {
8961
+ "path": "targetHigh",
8962
+ "valueType": "number"
8963
+ },
8964
+ {
8965
+ "path": "targetLow",
8966
+ "valueType": "number"
8967
+ },
8968
+ {
8969
+ "path": "targetHumidity",
8970
+ "valueType": "number"
8971
+ },
8972
+ {
8973
+ "path": "currentTemp",
8974
+ "valueType": "number"
8975
+ },
8976
+ {
8977
+ "path": "currentHumidity",
8978
+ "valueType": "number"
8979
+ },
8980
+ {
8981
+ "path": "swingVertical",
8982
+ "valueType": "boolean"
8983
+ },
8984
+ {
8985
+ "path": "swingHorizontal",
8986
+ "valueType": "boolean"
8987
+ },
8988
+ {
8989
+ "path": "minTemp",
8990
+ "valueType": "number"
8991
+ },
8992
+ {
8993
+ "path": "maxTemp",
8994
+ "valueType": "number"
8995
+ },
8996
+ {
8997
+ "path": "tempStep",
8998
+ "valueType": "number"
8999
+ }
9000
+ ],
9001
+ "color": [
9002
+ {
9003
+ "path": "mode",
9004
+ "valueType": "enum",
9005
+ "enumValues": [
9006
+ "rgb",
9007
+ "hsv",
9008
+ "mired"
9009
+ ]
9010
+ },
9011
+ {
9012
+ "path": "rgb.r",
9013
+ "valueType": "number"
9014
+ },
9015
+ {
9016
+ "path": "rgb.g",
9017
+ "valueType": "number"
9018
+ },
9019
+ {
9020
+ "path": "rgb.b",
9021
+ "valueType": "number"
9022
+ },
9023
+ {
9024
+ "path": "hsv.h",
9025
+ "valueType": "number"
9026
+ },
9027
+ {
9028
+ "path": "hsv.s",
9029
+ "valueType": "number"
9030
+ },
9031
+ {
9032
+ "path": "hsv.v",
9033
+ "valueType": "number"
9034
+ },
9035
+ {
9036
+ "path": "mireds",
9037
+ "valueType": "number"
9038
+ }
9039
+ ],
9040
+ "connectivity": [{
9041
+ "path": "connected",
9042
+ "valueType": "boolean"
9043
+ }],
9044
+ "contact": [{
9045
+ "path": "entryOpen",
9046
+ "valueType": "boolean"
9047
+ }],
9048
+ "control": [
9049
+ {
9050
+ "path": "kind",
9051
+ "valueType": "enum",
9052
+ "enumValues": [
9053
+ "numeric",
9054
+ "select",
9055
+ "text",
9056
+ "datetime"
9057
+ ]
9058
+ },
9059
+ {
9060
+ "path": "unit",
9061
+ "valueType": "string"
9062
+ },
9063
+ {
9064
+ "path": "min",
9065
+ "valueType": "number"
9066
+ },
9067
+ {
9068
+ "path": "max",
9069
+ "valueType": "number"
9070
+ },
9071
+ {
9072
+ "path": "step",
9073
+ "valueType": "number"
9074
+ },
9075
+ {
9076
+ "path": "precision",
9077
+ "valueType": "number"
9078
+ },
9079
+ {
9080
+ "path": "format",
9081
+ "valueType": "enum",
9082
+ "enumValues": [
9083
+ "date",
9084
+ "time",
9085
+ "datetime"
9086
+ ]
9087
+ }
9088
+ ],
9089
+ "cover": [
9090
+ {
9091
+ "path": "state",
9092
+ "valueType": "enum",
9093
+ "enumValues": [
9094
+ "open",
9095
+ "opening",
9096
+ "closing",
9097
+ "closed",
9098
+ "stopped"
9099
+ ]
9100
+ },
9101
+ {
9102
+ "path": "position",
9103
+ "valueType": "number"
9104
+ },
9105
+ {
9106
+ "path": "tiltPosition",
9107
+ "valueType": "number"
9108
+ }
9109
+ ],
9110
+ "day-night": [
9111
+ {
9112
+ "path": "mode",
9113
+ "valueType": "enum",
9114
+ "enumValues": [
9115
+ "auto",
9116
+ "day",
9117
+ "night",
9118
+ "schedule"
9119
+ ]
9120
+ },
9121
+ {
9122
+ "path": "sensitivity",
9123
+ "valueType": "number"
9124
+ },
9125
+ {
9126
+ "path": "switchDelaySec",
9127
+ "valueType": "number"
9128
+ }
9129
+ ],
9130
+ "device-adoption": [
9131
+ {
9132
+ "path": "lastDiscoveryAt",
9133
+ "valueType": "number"
9134
+ },
9135
+ {
9136
+ "path": "candidateCount",
9137
+ "valueType": "number"
9138
+ },
9139
+ {
9140
+ "path": "adoptedCount",
9141
+ "valueType": "number"
9142
+ },
9143
+ {
9144
+ "path": "lastError",
9145
+ "valueType": "string"
9146
+ }
9147
+ ],
9148
+ "device-discovery": [{
9149
+ "path": "lastDiscoveryAt",
9150
+ "valueType": "number"
9151
+ }, {
9152
+ "path": "lastError",
9153
+ "valueType": "string"
9154
+ }],
9155
+ "device-export": [
9156
+ {
9157
+ "path": "linkState",
9158
+ "valueType": "enum",
9159
+ "enumValues": [
9160
+ "unlinked",
9161
+ "linked",
9162
+ "error"
9163
+ ]
9164
+ },
9165
+ {
9166
+ "path": "exposedDeviceCount",
9167
+ "valueType": "number"
9168
+ },
9169
+ {
9170
+ "path": "error",
9171
+ "valueType": "string"
9172
+ },
9173
+ {
9174
+ "path": "setup.qr",
9175
+ "valueType": "string"
9176
+ },
9177
+ {
9178
+ "path": "setup.note",
9179
+ "valueType": "string"
9180
+ }
9181
+ ],
9182
+ "device-status": [{
9183
+ "path": "online",
9184
+ "valueType": "boolean"
9185
+ }],
9186
+ "dishwasher": [
9187
+ {
9188
+ "path": "availability",
9189
+ "valueType": "enum",
9190
+ "enumValues": [
9191
+ "available",
9192
+ "offline",
9193
+ "description-missing"
9194
+ ]
9195
+ },
9196
+ {
9197
+ "path": "state",
9198
+ "valueType": "enum",
9199
+ "enumValues": [
9200
+ "idle",
9201
+ "running",
9202
+ "paused",
9203
+ "finished",
9204
+ "error",
9205
+ "unavailable"
9206
+ ]
9207
+ },
9208
+ {
9209
+ "path": "operationState",
9210
+ "valueType": "enum",
9211
+ "enumValues": [
9212
+ "Inactive",
9213
+ "Ready",
9214
+ "DelayedStart",
9215
+ "Run",
9216
+ "Pause",
9217
+ "ActionRequired",
9218
+ "Finished",
9219
+ "Error",
9220
+ "Aborting"
9221
+ ]
9222
+ },
9223
+ {
9224
+ "path": "program",
9225
+ "valueType": "string"
9226
+ },
9227
+ {
9228
+ "path": "selectedProgram",
9229
+ "valueType": "string"
9230
+ },
9231
+ {
9232
+ "path": "remainingSeconds",
9233
+ "valueType": "number"
9234
+ },
9235
+ {
9236
+ "path": "delayedStartSeconds",
9237
+ "valueType": "number"
9238
+ },
9239
+ {
9240
+ "path": "progressPercent",
9241
+ "valueType": "number"
9242
+ },
9243
+ {
9244
+ "path": "doorOpen",
9245
+ "valueType": "boolean"
9246
+ },
9247
+ {
9248
+ "path": "doorLocked",
9249
+ "valueType": "boolean"
9250
+ },
9251
+ {
9252
+ "path": "remoteStartAllowed",
9253
+ "valueType": "boolean"
9254
+ },
9255
+ {
9256
+ "path": "remoteControlActive",
9257
+ "valueType": "boolean"
9258
+ },
9259
+ {
9260
+ "path": "localControlActive",
9261
+ "valueType": "boolean"
9262
+ },
9263
+ {
9264
+ "path": "powerOn",
9265
+ "valueType": "boolean"
9266
+ },
9267
+ {
9268
+ "path": "powerState",
9269
+ "valueType": "string"
9270
+ },
9271
+ {
9272
+ "path": "filterCleaningDue",
9273
+ "valueType": "boolean"
9274
+ },
9275
+ {
9276
+ "path": "machineCareDue",
9277
+ "valueType": "boolean"
9278
+ },
9279
+ {
9280
+ "path": "machineCareRemainingRuns",
9281
+ "valueType": "number"
9282
+ },
9283
+ {
9284
+ "path": "halfLoad",
9285
+ "valueType": "boolean"
9286
+ },
9287
+ {
9288
+ "path": "hygienePlus",
9289
+ "valueType": "boolean"
9290
+ },
9291
+ {
9292
+ "path": "extraDry",
9293
+ "valueType": "boolean"
9294
+ },
9295
+ {
9296
+ "path": "intensiveZone",
9297
+ "valueType": "boolean"
9298
+ },
9299
+ {
9300
+ "path": "varioSpeedPlus",
9301
+ "valueType": "boolean"
9302
+ },
9303
+ {
9304
+ "path": "childLock",
9305
+ "valueType": "boolean"
9306
+ },
9307
+ {
9308
+ "path": "errorCode",
9309
+ "valueType": "number"
9310
+ },
9311
+ {
9312
+ "path": "errorLabel",
9313
+ "valueType": "string"
9314
+ }
9315
+ ],
9316
+ "doorbell": [{
9317
+ "path": "lastPressedAt",
9318
+ "valueType": "number"
9319
+ }, {
9320
+ "path": "pressCountSinceStart",
9321
+ "valueType": "number"
9322
+ }],
9323
+ "enum-sensor": [{
9324
+ "path": "value",
9325
+ "valueType": "string"
9326
+ }, {
9327
+ "path": "format",
9328
+ "valueType": "enum",
9329
+ "enumValues": [
9330
+ "date",
9331
+ "time",
9332
+ "datetime"
9333
+ ]
9334
+ }],
9335
+ "event-emitter": [
9336
+ {
9337
+ "path": "lastEvent.deviceId",
9338
+ "valueType": "number"
9339
+ },
9340
+ {
9341
+ "path": "lastEvent.eventType",
9342
+ "valueType": "string"
9343
+ },
9344
+ {
9345
+ "path": "lastEvent.timestamp",
9346
+ "valueType": "number"
9347
+ },
9348
+ {
9349
+ "path": "lastEvent.seq",
9350
+ "valueType": "number"
9351
+ },
9352
+ {
9353
+ "path": "eventCountSinceStart",
9354
+ "valueType": "number"
9355
+ }
9356
+ ],
9357
+ "fan-control": [
9358
+ {
9359
+ "path": "percentage",
9360
+ "valueType": "number"
9361
+ },
9362
+ {
9363
+ "path": "percentageStep",
9364
+ "valueType": "number"
9365
+ },
9366
+ {
9367
+ "path": "preset",
9368
+ "valueType": "string"
9369
+ },
9370
+ {
9371
+ "path": "direction",
9372
+ "valueType": "enum",
9373
+ "enumValues": ["forward", "reverse"]
9374
+ },
9375
+ {
9376
+ "path": "oscillating",
9377
+ "valueType": "boolean"
9378
+ }
9379
+ ],
9380
+ "feature-probe": [
9381
+ {
9382
+ "path": "deviceType",
9383
+ "valueType": "string"
9384
+ },
9385
+ {
9386
+ "path": "model",
9387
+ "valueType": "string"
9388
+ },
9389
+ {
9390
+ "path": "channelCount",
9391
+ "valueType": "number"
9392
+ },
9393
+ {
9394
+ "path": "lastProbedAt",
9395
+ "valueType": "number"
9396
+ }
9397
+ ],
9398
+ "flood": [{
9399
+ "path": "flooded",
9400
+ "valueType": "boolean"
9401
+ }],
9402
+ "gas": [{
9403
+ "path": "detected",
9404
+ "valueType": "boolean"
9405
+ }],
9406
+ "heating-valve": [{
9407
+ "path": "position",
9408
+ "valueType": "number"
9409
+ }],
9410
+ "humidifier": [
9411
+ {
9412
+ "path": "on",
9413
+ "valueType": "boolean"
9414
+ },
9415
+ {
9416
+ "path": "currentHumidity",
9417
+ "valueType": "number"
9418
+ },
9419
+ {
9420
+ "path": "targetHumidity",
9421
+ "valueType": "number"
9422
+ },
9423
+ {
9424
+ "path": "mode",
9425
+ "valueType": "string"
9426
+ },
9427
+ {
9428
+ "path": "action",
9429
+ "valueType": "string"
9430
+ },
9431
+ {
9432
+ "path": "minHumidity",
9433
+ "valueType": "number"
9434
+ },
9435
+ {
9436
+ "path": "maxHumidity",
9437
+ "valueType": "number"
9438
+ }
9439
+ ],
9440
+ "humidity-sensor": [
9441
+ {
9442
+ "path": "percent",
9443
+ "valueType": "number"
9444
+ },
9445
+ {
9446
+ "path": "unit",
9447
+ "valueType": "string"
9448
+ },
9449
+ {
9450
+ "path": "precision",
9451
+ "valueType": "number"
9452
+ }
9453
+ ],
9454
+ "image": [{
9455
+ "path": "url",
9456
+ "valueType": "string"
9457
+ }, {
9458
+ "path": "lastUpdated",
9459
+ "valueType": "number"
9460
+ }],
9461
+ "image-settings": [
9462
+ {
9463
+ "path": "brightness",
9464
+ "valueType": "number"
9465
+ },
9466
+ {
9467
+ "path": "contrast",
9468
+ "valueType": "number"
9469
+ },
9470
+ {
9471
+ "path": "saturation",
9472
+ "valueType": "number"
9473
+ },
9474
+ {
9475
+ "path": "sharpness",
9476
+ "valueType": "number"
9477
+ },
9478
+ {
9479
+ "path": "mirror",
9480
+ "valueType": "boolean"
9481
+ },
9482
+ {
9483
+ "path": "flip",
9484
+ "valueType": "boolean"
9485
+ },
9486
+ {
9487
+ "path": "rotate",
9488
+ "valueType": "enum",
9489
+ "enumValues": [
9490
+ "0",
9491
+ "90",
9492
+ "180",
9493
+ "270"
9494
+ ]
9495
+ },
9496
+ {
9497
+ "path": "whiteBalance",
9498
+ "valueType": "enum",
9499
+ "enumValues": ["auto", "manual"]
9500
+ },
9501
+ {
9502
+ "path": "warmth",
9503
+ "valueType": "number"
9504
+ },
9505
+ {
9506
+ "path": "exposureMode",
9507
+ "valueType": "enum",
9508
+ "enumValues": ["auto", "manual"]
9509
+ },
9510
+ {
9511
+ "path": "backlightMode",
9512
+ "valueType": "enum",
9513
+ "enumValues": [
9514
+ "off",
9515
+ "blc",
9516
+ "wdr",
9517
+ "hlc"
9518
+ ]
9519
+ }
9520
+ ],
9521
+ "intercom": [
9522
+ {
9523
+ "path": "talking",
9524
+ "valueType": "boolean"
9525
+ },
9526
+ {
9527
+ "path": "lastSessionAt",
9528
+ "valueType": "number"
9529
+ },
9530
+ {
9531
+ "path": "ability.sampleRate",
9532
+ "valueType": "number"
9533
+ },
9534
+ {
9535
+ "path": "ability.duplex",
9536
+ "valueType": "enum",
9537
+ "enumValues": ["half", "full"]
9538
+ },
9539
+ {
9540
+ "path": "ability.maxBacklogMs",
9541
+ "valueType": "number"
9542
+ }
9543
+ ],
9544
+ "lawn-mower-control": [
9545
+ {
9546
+ "path": "activity",
9547
+ "valueType": "enum",
9548
+ "enumValues": [
9549
+ "idle",
9550
+ "mowing",
9551
+ "paused",
9552
+ "docked",
9553
+ "error"
9554
+ ]
9555
+ },
9556
+ {
9557
+ "path": "batteryLevel",
9558
+ "valueType": "number"
9559
+ },
9560
+ {
9561
+ "path": "progressPercent",
9562
+ "valueType": "number"
9563
+ },
9564
+ {
9565
+ "path": "currentCode",
9566
+ "valueType": "number"
9567
+ },
9568
+ {
9569
+ "path": "currentCodeLabel",
9570
+ "valueType": "string"
9571
+ },
9572
+ {
9573
+ "path": "severity",
9574
+ "valueType": "enum",
9575
+ "enumValues": [
9576
+ "info",
9577
+ "warning",
9578
+ "error"
9579
+ ]
9580
+ }
9581
+ ],
9582
+ "lock-control": [{
9583
+ "path": "state",
9584
+ "valueType": "enum",
9585
+ "enumValues": [
9586
+ "locked",
9587
+ "unlocked",
9588
+ "locking",
9589
+ "unlocking",
9590
+ "jammed"
9591
+ ]
9592
+ }],
9593
+ "media-player": [
9594
+ {
9595
+ "path": "state",
9596
+ "valueType": "enum",
9597
+ "enumValues": [
9598
+ "off",
9599
+ "on",
9600
+ "idle",
9601
+ "playing",
9602
+ "paused",
9603
+ "buffering",
9604
+ "standby"
9605
+ ]
9606
+ },
9607
+ {
9608
+ "path": "volumeLevel",
9609
+ "valueType": "number"
9610
+ },
9611
+ {
9612
+ "path": "isMuted",
9613
+ "valueType": "boolean"
9614
+ },
9615
+ {
9616
+ "path": "source",
9617
+ "valueType": "string"
9618
+ },
9619
+ {
9620
+ "path": "currentMedia.type",
9621
+ "valueType": "string"
9622
+ },
9623
+ {
9624
+ "path": "currentMedia.title",
9625
+ "valueType": "string"
9626
+ },
9627
+ {
9628
+ "path": "currentMedia.artist",
9629
+ "valueType": "string"
9630
+ },
9631
+ {
9632
+ "path": "currentMedia.album",
9633
+ "valueType": "string"
9634
+ },
9635
+ {
9636
+ "path": "currentMedia.imageUrl",
9637
+ "valueType": "string"
9638
+ },
9639
+ {
9640
+ "path": "positionMs",
9641
+ "valueType": "number"
9642
+ },
9643
+ {
9644
+ "path": "durationMs",
9645
+ "valueType": "number"
9646
+ },
9647
+ {
9648
+ "path": "shuffle",
9649
+ "valueType": "boolean"
9650
+ },
9651
+ {
9652
+ "path": "repeat",
9653
+ "valueType": "enum",
9654
+ "enumValues": [
9655
+ "off",
9656
+ "all",
9657
+ "one"
9658
+ ]
9659
+ }
9660
+ ],
9661
+ "motion": [
9662
+ {
9663
+ "path": "detected",
9664
+ "valueType": "boolean"
9665
+ },
9666
+ {
9667
+ "path": "lastDetectedAt",
9668
+ "valueType": "number"
9669
+ },
9670
+ {
9671
+ "path": "autoClearAfterMs",
9672
+ "valueType": "number"
9673
+ }
9674
+ ],
9675
+ "motion-trigger": [{
9676
+ "path": "enabled",
9677
+ "valueType": "boolean"
9678
+ }],
9679
+ "motion-zones": [{
9680
+ "path": "enabled",
9681
+ "valueType": "boolean"
9682
+ }, {
9683
+ "path": "sensitivity",
9684
+ "valueType": "number"
9685
+ }],
9686
+ "mqtt-broker": [{
9687
+ "path": "brokerCount",
9688
+ "valueType": "number"
9689
+ }, {
9690
+ "path": "embeddedRunning",
9691
+ "valueType": "boolean"
9692
+ }],
9693
+ "native-object-detection": [{
9694
+ "path": "enabled",
9695
+ "valueType": "boolean"
9696
+ }],
9697
+ "navigation": [
9698
+ {
9699
+ "path": "mode",
9700
+ "valueType": "enum",
9701
+ "enumValues": [
9702
+ "idle",
9703
+ "cleaning",
9704
+ "spot",
9705
+ "following",
9706
+ "goto",
9707
+ "returning",
9708
+ "paused",
9709
+ "unknown"
9710
+ ]
9711
+ },
9712
+ {
9713
+ "path": "following",
9714
+ "valueType": "boolean"
9715
+ },
9716
+ {
9717
+ "path": "flash",
9718
+ "valueType": "boolean"
9719
+ },
9720
+ {
9721
+ "path": "lightMode",
9722
+ "valueType": "enum",
9723
+ "enumValues": ["auto", "manual"]
9724
+ },
9725
+ {
9726
+ "path": "lightLevel",
9727
+ "valueType": "number"
9728
+ }
9729
+ ],
9730
+ "network-link": [
9731
+ {
9732
+ "path": "type",
9733
+ "valueType": "enum",
9734
+ "enumValues": [
9735
+ "wifi",
9736
+ "ethernet",
9737
+ "cellular",
9738
+ "unknown"
9739
+ ]
9740
+ },
9741
+ {
9742
+ "path": "signalPercent",
9743
+ "valueType": "number"
9744
+ },
9745
+ {
9746
+ "path": "rssiDbm",
9747
+ "valueType": "number"
9748
+ },
9749
+ {
9750
+ "path": "ssid",
9751
+ "valueType": "string"
9752
+ },
9753
+ {
9754
+ "path": "lastUpdated",
9755
+ "valueType": "number"
9756
+ }
9757
+ ],
9758
+ "notifier": [
9759
+ {
9760
+ "path": "lastSentAt",
9761
+ "valueType": "number"
9762
+ },
9763
+ {
9764
+ "path": "lastError",
9765
+ "valueType": "string"
9766
+ },
9767
+ {
9768
+ "path": "queueDepth",
9769
+ "valueType": "number"
9770
+ },
9771
+ {
9772
+ "path": "supports.image",
9773
+ "valueType": "boolean"
9774
+ },
9775
+ {
9776
+ "path": "supports.priority",
9777
+ "valueType": "boolean"
9778
+ },
9779
+ {
9780
+ "path": "supports.data",
9781
+ "valueType": "boolean"
9782
+ },
9783
+ {
9784
+ "path": "supports.actions",
9785
+ "valueType": "boolean"
9786
+ },
9787
+ {
9788
+ "path": "supports.recipients",
9789
+ "valueType": "boolean"
9790
+ }
9791
+ ],
9792
+ "numeric-sensor": [
9793
+ {
9794
+ "path": "value",
9795
+ "valueType": "number"
9796
+ },
9797
+ {
9798
+ "path": "unit",
9799
+ "valueType": "string"
9800
+ },
9801
+ {
9802
+ "path": "precision",
9803
+ "valueType": "number"
9804
+ }
9805
+ ],
9806
+ "pet-feeder": [
9807
+ {
9808
+ "path": "foodLevel",
9809
+ "valueType": "number"
9810
+ },
9811
+ {
9812
+ "path": "food1",
9813
+ "valueType": "number"
9814
+ },
9815
+ {
9816
+ "path": "food2",
9817
+ "valueType": "number"
9818
+ },
9819
+ {
9820
+ "path": "lowFood",
9821
+ "valueType": "boolean"
9822
+ },
9823
+ {
9824
+ "path": "batteryPower",
9825
+ "valueType": "number"
9826
+ },
9827
+ {
9828
+ "path": "desiccantLeftDays",
9829
+ "valueType": "number"
9830
+ },
9831
+ {
9832
+ "path": "feeding",
9833
+ "valueType": "boolean"
9834
+ },
9835
+ {
9836
+ "path": "status",
9837
+ "valueType": "enum",
9838
+ "enumValues": [
9839
+ "normal",
9840
+ "offline",
9841
+ "on_batteries"
9842
+ ]
9843
+ },
9844
+ {
9845
+ "path": "error",
9846
+ "valueType": "string"
9847
+ },
9848
+ {
9849
+ "path": "errorCode",
9850
+ "valueType": "number"
9851
+ },
9852
+ {
9853
+ "path": "isDualHopper",
9854
+ "valueType": "boolean"
9855
+ },
9856
+ {
9857
+ "path": "childLock",
9858
+ "valueType": "boolean"
9859
+ },
9860
+ {
9861
+ "path": "indicatorLight",
9862
+ "valueType": "boolean"
9863
+ },
9864
+ {
9865
+ "path": "feedSound",
9866
+ "valueType": "boolean"
9867
+ },
9868
+ {
9869
+ "path": "volume",
9870
+ "valueType": "number"
9871
+ }
9872
+ ],
9873
+ "power-meter": [
9874
+ {
9875
+ "path": "watts",
9876
+ "valueType": "number"
9877
+ },
9878
+ {
9879
+ "path": "kwhTotal",
9880
+ "valueType": "number"
9881
+ },
9882
+ {
9883
+ "path": "volts",
9884
+ "valueType": "number"
9885
+ },
9886
+ {
9887
+ "path": "amps",
9888
+ "valueType": "number"
9889
+ },
9890
+ {
9891
+ "path": "va",
9892
+ "valueType": "number"
9893
+ },
9894
+ {
9895
+ "path": "powerFactor",
9896
+ "valueType": "number"
9897
+ },
9898
+ {
9899
+ "path": "unit",
9900
+ "valueType": "string"
9901
+ },
9902
+ {
9903
+ "path": "precision",
9904
+ "valueType": "number"
9905
+ }
9906
+ ],
9907
+ "presence": [
9908
+ {
9909
+ "path": "state",
9910
+ "valueType": "string"
9911
+ },
9912
+ {
9913
+ "path": "location",
9914
+ "valueType": "string"
9915
+ },
9916
+ {
9917
+ "path": "gps.latitude",
9918
+ "valueType": "number"
9919
+ },
9920
+ {
9921
+ "path": "gps.longitude",
9922
+ "valueType": "number"
9923
+ },
9924
+ {
9925
+ "path": "gps.accuracyMeters",
9926
+ "valueType": "number"
9927
+ },
9928
+ {
9929
+ "path": "batteryPercent",
9930
+ "valueType": "number"
9931
+ }
9932
+ ],
9933
+ "pressure-sensor": [
9934
+ {
9935
+ "path": "hpa",
9936
+ "valueType": "number"
9937
+ },
9938
+ {
9939
+ "path": "unit",
9940
+ "valueType": "string"
9941
+ },
9942
+ {
9943
+ "path": "precision",
9944
+ "valueType": "number"
9945
+ }
9946
+ ],
9947
+ "privacy-mask": [{
9948
+ "path": "enabled",
9949
+ "valueType": "boolean"
9950
+ }, {
9951
+ "path": "audioEnabled",
9952
+ "valueType": "boolean"
9953
+ }],
9954
+ "ptz": [
9955
+ {
9956
+ "path": "pan",
9957
+ "valueType": "number"
9958
+ },
9959
+ {
9960
+ "path": "tilt",
9961
+ "valueType": "number"
9962
+ },
9963
+ {
9964
+ "path": "zoom",
9965
+ "valueType": "number"
9966
+ },
9967
+ {
9968
+ "path": "autofocus",
9969
+ "valueType": "boolean"
9970
+ }
9971
+ ],
9972
+ "ptz-autotrack": [
9973
+ {
9974
+ "path": "enabled",
9975
+ "valueType": "boolean"
9976
+ },
9977
+ {
9978
+ "path": "currentSettings.targetType",
9979
+ "valueType": "string"
9980
+ },
9981
+ {
9982
+ "path": "currentSettings.stopDelaySeconds",
9983
+ "valueType": "number"
9984
+ },
9985
+ {
9986
+ "path": "currentSettings.disappearDelaySeconds",
9987
+ "valueType": "number"
9988
+ }
9989
+ ],
9990
+ "recording-archive": [
9991
+ {
9992
+ "path": "deviceId",
9993
+ "valueType": "number"
9994
+ },
9995
+ {
9996
+ "path": "enabled",
9997
+ "valueType": "boolean"
9998
+ },
9999
+ {
10000
+ "path": "activeMode",
10001
+ "valueType": "enum",
10002
+ "enumValues": [
10003
+ "off",
10004
+ "events",
10005
+ "continuous",
10006
+ "on-device-decision"
10007
+ ]
10008
+ },
10009
+ {
10010
+ "path": "nodeId",
10011
+ "valueType": "string"
10012
+ },
10013
+ {
10014
+ "path": "storageBytes",
10015
+ "valueType": "number"
10016
+ }
10017
+ ],
10018
+ "recording-onboard": [
10019
+ {
10020
+ "path": "primaryTrackId",
10021
+ "valueType": "string"
10022
+ },
10023
+ {
10024
+ "path": "enabled",
10025
+ "valueType": "boolean"
10026
+ },
10027
+ {
10028
+ "path": "overwriteWhenFull",
10029
+ "valueType": "boolean"
10030
+ },
10031
+ {
10032
+ "path": "preRecordSec",
10033
+ "valueType": "number"
10034
+ },
10035
+ {
10036
+ "path": "postRecordSec",
10037
+ "valueType": "number"
10038
+ },
10039
+ {
10040
+ "path": "segmentMinutes",
10041
+ "valueType": "number"
10042
+ },
10043
+ {
10044
+ "path": "unreadableWindows",
10045
+ "valueType": "number"
10046
+ },
10047
+ {
10048
+ "path": "recordingToNowhere",
10049
+ "valueType": "boolean"
10050
+ }
10051
+ ],
10052
+ "recording-signal": [{
10053
+ "path": "active",
10054
+ "valueType": "boolean"
10055
+ }, {
10056
+ "path": "reason",
10057
+ "valueType": "string"
10058
+ }],
10059
+ "running-state": [
10060
+ {
10061
+ "path": "running",
10062
+ "valueType": "boolean"
10063
+ },
10064
+ {
10065
+ "path": "since",
10066
+ "valueType": "number"
10067
+ },
10068
+ {
10069
+ "path": "source",
10070
+ "valueType": "enum",
10071
+ "enumValues": ["native", "assigned"]
10072
+ },
10073
+ {
10074
+ "path": "phase",
10075
+ "valueType": "string"
10076
+ }
10077
+ ],
10078
+ "script-runner": [
10079
+ {
10080
+ "path": "isRunning",
10081
+ "valueType": "boolean"
10082
+ },
10083
+ {
10084
+ "path": "lastRunAt",
10085
+ "valueType": "number"
10086
+ },
10087
+ {
10088
+ "path": "lastRunSuccess",
10089
+ "valueType": "boolean"
10090
+ },
10091
+ {
10092
+ "path": "lastError",
10093
+ "valueType": "string"
10094
+ }
10095
+ ],
10096
+ "smoke": [{
10097
+ "path": "detected",
10098
+ "valueType": "boolean"
10099
+ }],
10100
+ "snapshot": [
10101
+ {
10102
+ "path": "lastCapturedAt",
10103
+ "valueType": "number"
10104
+ },
10105
+ {
10106
+ "path": "cacheAgeMs",
10107
+ "valueType": "number"
10108
+ },
10109
+ {
10110
+ "path": "lastBytes",
10111
+ "valueType": "number"
10112
+ },
10113
+ {
10114
+ "path": "lastStreamId",
10115
+ "valueType": "string"
10116
+ }
10117
+ ],
10118
+ "stream-params": [
10119
+ {
10120
+ "path": "main.width",
10121
+ "valueType": "number"
10122
+ },
10123
+ {
10124
+ "path": "main.height",
10125
+ "valueType": "number"
10126
+ },
10127
+ {
10128
+ "path": "main.codec",
10129
+ "valueType": "enum",
10130
+ "enumValues": ["h264", "h265"]
10131
+ },
10132
+ {
10133
+ "path": "main.framerate",
10134
+ "valueType": "number"
10135
+ },
10136
+ {
10137
+ "path": "main.bitrate",
10138
+ "valueType": "number"
10139
+ },
10140
+ {
10141
+ "path": "main.bitrateMode",
10142
+ "valueType": "enum",
10143
+ "enumValues": ["vbr", "cbr"]
10144
+ },
10145
+ {
10146
+ "path": "main.encoderProfile",
10147
+ "valueType": "enum",
10148
+ "enumValues": [
10149
+ "high",
10150
+ "main",
10151
+ "baseline"
10152
+ ]
10153
+ },
10154
+ {
10155
+ "path": "main.gop",
10156
+ "valueType": "number"
10157
+ },
10158
+ {
10159
+ "path": "main.audio",
10160
+ "valueType": "boolean"
10161
+ },
10162
+ {
10163
+ "path": "sub.width",
10164
+ "valueType": "number"
10165
+ },
10166
+ {
10167
+ "path": "sub.height",
10168
+ "valueType": "number"
10169
+ },
10170
+ {
10171
+ "path": "sub.codec",
10172
+ "valueType": "enum",
10173
+ "enumValues": ["h264", "h265"]
10174
+ },
10175
+ {
10176
+ "path": "sub.framerate",
10177
+ "valueType": "number"
10178
+ },
10179
+ {
10180
+ "path": "sub.bitrate",
10181
+ "valueType": "number"
10182
+ },
10183
+ {
10184
+ "path": "sub.bitrateMode",
10185
+ "valueType": "enum",
10186
+ "enumValues": ["vbr", "cbr"]
10187
+ },
10188
+ {
10189
+ "path": "sub.encoderProfile",
10190
+ "valueType": "enum",
10191
+ "enumValues": [
10192
+ "high",
10193
+ "main",
10194
+ "baseline"
10195
+ ]
10196
+ },
10197
+ {
10198
+ "path": "sub.gop",
10199
+ "valueType": "number"
10200
+ },
10201
+ {
10202
+ "path": "sub.audio",
10203
+ "valueType": "boolean"
10204
+ },
10205
+ {
10206
+ "path": "ext.width",
10207
+ "valueType": "number"
10208
+ },
10209
+ {
10210
+ "path": "ext.height",
10211
+ "valueType": "number"
10212
+ },
10213
+ {
10214
+ "path": "ext.codec",
10215
+ "valueType": "enum",
10216
+ "enumValues": ["h264", "h265"]
10217
+ },
10218
+ {
10219
+ "path": "ext.framerate",
10220
+ "valueType": "number"
10221
+ },
10222
+ {
10223
+ "path": "ext.bitrate",
10224
+ "valueType": "number"
10225
+ },
10226
+ {
10227
+ "path": "ext.bitrateMode",
10228
+ "valueType": "enum",
10229
+ "enumValues": ["vbr", "cbr"]
10230
+ },
10231
+ {
10232
+ "path": "ext.encoderProfile",
10233
+ "valueType": "enum",
10234
+ "enumValues": [
10235
+ "high",
10236
+ "main",
10237
+ "baseline"
10238
+ ]
10239
+ },
10240
+ {
10241
+ "path": "ext.gop",
10242
+ "valueType": "number"
10243
+ },
10244
+ {
10245
+ "path": "ext.audio",
10246
+ "valueType": "boolean"
10247
+ }
10248
+ ],
10249
+ "switch": [{
10250
+ "path": "on",
10251
+ "valueType": "boolean"
10252
+ }],
10253
+ "tamper": [{
10254
+ "path": "tampered",
10255
+ "valueType": "boolean"
10256
+ }],
10257
+ "temperature-sensor": [
10258
+ {
10259
+ "path": "celsius",
10260
+ "valueType": "number"
10261
+ },
10262
+ {
10263
+ "path": "unit",
10264
+ "valueType": "string"
10265
+ },
10266
+ {
10267
+ "path": "precision",
10268
+ "valueType": "number"
10269
+ }
10270
+ ],
10271
+ "update": [
10272
+ {
10273
+ "path": "currentVersion",
10274
+ "valueType": "string"
10275
+ },
10276
+ {
10277
+ "path": "availableVersion",
10278
+ "valueType": "string"
10279
+ },
10280
+ {
10281
+ "path": "updatable",
10282
+ "valueType": "boolean"
10283
+ },
10284
+ {
10285
+ "path": "state",
10286
+ "valueType": "string"
10287
+ },
10288
+ {
10289
+ "path": "inProgress",
10290
+ "valueType": "boolean"
10291
+ }
10292
+ ],
10293
+ "vacuum-control": [
10294
+ {
10295
+ "path": "state",
10296
+ "valueType": "enum",
10297
+ "enumValues": [
10298
+ "idle",
10299
+ "cleaning",
10300
+ "paused",
10301
+ "returning",
10302
+ "docked",
10303
+ "drying",
10304
+ "error"
10305
+ ]
10306
+ },
10307
+ {
10308
+ "path": "batteryLevel",
10309
+ "valueType": "number"
10310
+ },
10311
+ {
10312
+ "path": "fanSpeed",
10313
+ "valueType": "string"
10314
+ },
10315
+ {
10316
+ "path": "progressPercent",
10317
+ "valueType": "number"
10318
+ },
10319
+ {
10320
+ "path": "errorCode",
10321
+ "valueType": "number"
10322
+ },
10323
+ {
10324
+ "path": "errorLabel",
10325
+ "valueType": "string"
10326
+ }
10327
+ ],
10328
+ "valve": [{
10329
+ "path": "state",
10330
+ "valueType": "enum",
10331
+ "enumValues": [
10332
+ "open",
10333
+ "opening",
10334
+ "closing",
10335
+ "closed",
10336
+ "stopped"
10337
+ ]
10338
+ }, {
10339
+ "path": "position",
10340
+ "valueType": "number"
10341
+ }],
10342
+ "vibration": [{
10343
+ "path": "detected",
10344
+ "valueType": "boolean"
10345
+ }],
10346
+ "water-heater": [
10347
+ {
10348
+ "path": "currentTemp",
10349
+ "valueType": "number"
10350
+ },
10351
+ {
10352
+ "path": "targetTemp",
10353
+ "valueType": "number"
10354
+ },
10355
+ {
10356
+ "path": "operationMode",
10357
+ "valueType": "string"
10358
+ },
10359
+ {
10360
+ "path": "away",
10361
+ "valueType": "boolean"
10362
+ },
10363
+ {
10364
+ "path": "minTemp",
10365
+ "valueType": "number"
10366
+ },
10367
+ {
10368
+ "path": "maxTemp",
10369
+ "valueType": "number"
10370
+ }
10371
+ ],
10372
+ "weather": [
10373
+ {
10374
+ "path": "condition",
10375
+ "valueType": "string"
10376
+ },
10377
+ {
10378
+ "path": "temperature",
10379
+ "valueType": "number"
10380
+ },
10381
+ {
10382
+ "path": "temperatureUnit",
10383
+ "valueType": "string"
10384
+ },
10385
+ {
10386
+ "path": "humidity",
10387
+ "valueType": "number"
10388
+ },
10389
+ {
10390
+ "path": "pressure",
10391
+ "valueType": "number"
10392
+ },
10393
+ {
10394
+ "path": "pressureUnit",
10395
+ "valueType": "string"
10396
+ },
10397
+ {
10398
+ "path": "windSpeed",
10399
+ "valueType": "number"
10400
+ },
10401
+ {
10402
+ "path": "windSpeedUnit",
10403
+ "valueType": "string"
10404
+ },
10405
+ {
10406
+ "path": "windBearing",
10407
+ "valueType": "number"
10408
+ }
10409
+ ],
10410
+ "zone-analytics": [
10411
+ {
10412
+ "path": "ts",
10413
+ "valueType": "number"
10414
+ },
10415
+ {
10416
+ "path": "frameWidth",
10417
+ "valueType": "number"
10418
+ },
10419
+ {
10420
+ "path": "frameHeight",
10421
+ "valueType": "number"
10422
+ },
10423
+ {
10424
+ "path": "frame.totalObjects",
10425
+ "valueType": "number"
10426
+ },
10427
+ {
10428
+ "path": "frame.standingObjects",
10429
+ "valueType": "number"
10430
+ },
10431
+ {
10432
+ "path": "frame.transientObjects",
10433
+ "valueType": "number"
10434
+ },
10435
+ {
10436
+ "path": "unzoned.totalObjects",
10437
+ "valueType": "number"
10438
+ },
10439
+ {
10440
+ "path": "unzoned.standingObjects",
10441
+ "valueType": "number"
10442
+ },
10443
+ {
10444
+ "path": "unzoned.transientObjects",
10445
+ "valueType": "number"
10446
+ }
10447
+ ]
10448
+ });
8472
10449
  object({
8473
10450
  code: string().regex(/^[a-z][a-z0-9-]*(\.[a-z0-9-]+)+$/),
8474
10451
  params: record(string(), union([string(), number()])).optional()
@@ -8831,7 +10808,7 @@ var DeviceRole = /* @__PURE__ */ function(DeviceRole) {
8831
10808
  return DeviceRole;
8832
10809
  }({});
8833
10810
  //#endregion
8834
- //#region ../types/dist/composition-CB6PMT9p.mjs
10811
+ //#region ../types/dist/composition-kEl9mevu.mjs
8835
10812
  /**
8836
10813
  * The ffmpeg build every CamStack node downloads, per platform and arch.
8837
10814
  *
@@ -8891,7 +10868,7 @@ portable("linux64"), portable("linuxarm64"), portable("macarm64"), portable("mac
8891
10868
  * ONE table for everyone who asks "is this device HIGH?": the
8892
10869
  * recorder's `RecordingTriggers.sensorDeviceIds` trigger, the post-analysis
8893
10870
  * sensor markers, the orchestrator's camera-sensors bridge and
8894
- * the sources of a composite doorbell (`doorbellFeatureSources`, D671).
10871
+ * the sources of a pulse (`compilePulseOverride`, D936).
8895
10872
  * A second copy would diverge at the first cap added, and the symptom — "the
8896
10873
  * sensor rings the doorbell but does not record" — is exactly D62.
8897
10874
  *
@@ -9132,6 +11109,20 @@ var table = {
9132
11109
  apply: () => {
9133
11110
  throw new ExpressionEvalError("count: stateful evaluation context is required");
9134
11111
  }
11112
+ },
11113
+ dwell: {
11114
+ minArgs: 3,
11115
+ maxArgs: 3,
11116
+ apply: () => {
11117
+ throw new ExpressionEvalError("dwell: stateful evaluation context is required");
11118
+ }
11119
+ },
11120
+ latchedAt: {
11121
+ minArgs: 1,
11122
+ maxArgs: 1,
11123
+ apply: () => {
11124
+ throw new ExpressionEvalError("latchedAt: stateful evaluation context is required");
11125
+ }
9135
11126
  }
9136
11127
  };
9137
11128
  Object.freeze(Object.assign(Object.create(null), table));
@@ -10571,13 +12562,22 @@ var BirthDecisionRecordSchema = object({
10571
12562
  decidedByBirthEvidence: boolean(),
10572
12563
  /** Best class-compatible crop score, or `null` when nothing compatible was
10573
12564
  * found — deliberately not 0, which would be a measurement that never was.
10574
- * Includes a box the detector's own per-class floor refused (reason
10575
- * `below-detector-floor`, D922): that box never confirms, but it is the
10576
- * score the crop really held. */
12565
+ * Includes a box the detector's own per-class floor refused (D922): since
12566
+ * D925 the gate's bar, not that floor, decides whether it confirms. */
10577
12567
  bestScore: number().nullable(),
10578
12568
  /** The bar this candidate actually faced (the phantom-cell hook may raise it). */
10579
12569
  appliedMinConfidence: number().nullable(),
10580
12570
  /**
12571
+ * The detector the gate re-judged the birth WITH (D925): the session's own
12572
+ * root model, inference-device pool and node — never a node default. `null`
12573
+ * when the frame named no session detector or no gate ran, and on rows
12574
+ * written before D925. A `session-device-unavailable` row names the session
12575
+ * detector that could not be reached.
12576
+ */
12577
+ detectorModelId: string().nullable().default(null),
12578
+ detectorDeviceKey: string().nullable().default(null),
12579
+ detectorNodeId: string().nullable().default(null),
12580
+ /**
10581
12581
  * The track's own `firstSeen` — the candidate's first frame, which is where
10582
12582
  * the timeline starts. `null` for a suppressed birth, which has no track.
10583
12583
  */
@@ -12061,7 +14061,7 @@ var LogChannelDescriptorSchema = object({
12061
14061
  * `true` is a PROMISE with two halves, and both must hold: the gate is
12062
14062
  * consulted with the numeric device id, AND every line the channel admits
12063
14063
  * carries `tags: { deviceId }` with that same numeric id. The second half is
12064
- * what makes `| json | deviceId="617"` work in Loki — `loki-payload.ts`
14064
+ * what makes `| json | deviceId="102"` work in Loki — `loki-payload.ts`
12065
14065
  * keeps `deviceId` out of the stream labels for cardinality, so the tag in
12066
14066
  * the body is the only way to filter.
12067
14067
  *
@@ -12249,7 +14249,7 @@ var ModelVariantGroupSchema = object({
12249
14249
  precision: _enum(["fp32", "int8"]).optional(),
12250
14250
  /**
12251
14251
  * Training / latency-variant axis. Omit ⇒ the standard build. `test` marks
12252
- * an alternate training of the same family (Scrypted `relu_test`); chip
14252
+ * an alternate training of the same family (plugin catalog `relu_test`); chip
12253
14253
  * label is "Test".
12254
14254
  */
12255
14255
  optimization: _enum(["standard", "test"]).optional(),
@@ -12501,8 +14501,8 @@ var ModelCatalogEntrySchema = object({
12501
14501
  provider: ModelProviderIdSchema.optional(),
12502
14502
  /**
12503
14503
  * Per-MODEL class map override. Absent ⇒ the step's `StepDefinition.classMap`
12504
- * applies (Frigate / COCO public catalog). Set on a custom model whose raw
12505
- * labels already ARE the CamStack macros (Scrypted identity map).
14504
+ * applies (plus catalog / COCO public catalog). Set on a custom model whose raw
14505
+ * labels already ARE the CamStack macros (plugin catalog identity map).
12506
14506
  */
12507
14507
  classMap: DetectionCatalogClassMapSchema.optional(),
12508
14508
  /**
@@ -15471,7 +17471,7 @@ method(object({
15471
17471
  * `1` is real time and is the ONLY value that allows the copy branch —
15472
17472
  * anything else forces `libx264` over the window. That was priced
15473
17473
  * before it was chosen: a per-event burst measured at 0.23 s and 254 KB
15474
- * on a real 615 720p cut, against 922 KB for the copy it replaces. A
17474
+ * on a real 101 720p cut, against 922 KB for the copy it replaces. A
15475
17475
  * re-encode is capped at 720p (`EVENT_CLIP_ENCODE_MAX_WIDTH`), because
15476
17476
  * once the decode is forced the width stops being free.
15477
17477
  */
@@ -15997,6 +17997,7 @@ var CompositionRunStatusSchema = _enum([
15997
17997
  "starting",
15998
17998
  "running",
15999
17999
  "degraded",
18000
+ "incomplete",
16000
18001
  "failed"
16001
18002
  ]);
16002
18003
  var CompositionFieldStateKindSchema = _enum([
@@ -16046,6 +18047,13 @@ var ComposerUnreadableBlockSchema = object({
16046
18047
  /** The parse error, in the operator's words. */
16047
18048
  error: string()
16048
18049
  });
18050
+ /** A confirmed release the hub did not accept. `deviceId` is the claim's device. */
18051
+ var UnreleasedClaimSchema = object({
18052
+ deviceId: number().int(),
18053
+ capName: string(),
18054
+ owner: string(),
18055
+ error: string()
18056
+ });
16049
18057
  method(object({
16050
18058
  /** The shared Blocks integration; null until `core-blocks` has reconciled it. */
16051
18059
  integrationId: string().nullable(),
@@ -16055,7 +18063,13 @@ method(object({
16055
18063
  /** Operator restarts: rebuild these runtimes and re-resolve their sources. Stores nothing (D62). */
16056
18064
  restartBlockIds: array(string()),
16057
18065
  /** Composition rows that exist but do not parse: held, never withdrawn, reported failed. */
16058
- unreadableBlocks: array(ComposerUnreadableBlockSchema)
18066
+ unreadableBlocks: array(ComposerUnreadableBlockSchema),
18067
+ /**
18068
+ * Operator-confirmed deletions. Their claims are released on this apply,
18069
+ * before any replacement block claims. A block that merely vanished from the
18070
+ * snapshot is not listed here and still waits for two applies (D49).
18071
+ */
18072
+ retiredBlockIds: array(string()).optional()
16059
18073
  }), object({
16060
18074
  blocks: array(object({
16061
18075
  blockId: string(),
@@ -16067,7 +18081,13 @@ method(object({
16067
18081
  * integration unknown, its own rows unread or read empty once). An empty
16068
18082
  * apply the caller owes is paid off only by one the composer acted on (D49).
16069
18083
  */
16070
- acted: boolean()
18084
+ acted: boolean(),
18085
+ /**
18086
+ * Confirmed releases this apply tried and the hub did not accept. Empty when
18087
+ * every one landed (or there was nothing to hand back). Absent on a result
18088
+ * that never got that far.
18089
+ */
18090
+ unreleasedClaims: array(UnreleasedClaimSchema).optional()
16071
18091
  }), {
16072
18092
  kind: "mutation",
16073
18093
  auth: "admin"
@@ -16110,7 +18130,15 @@ Object.freeze({
16110
18130
  kind: "fixed",
16111
18131
  result: ["number", "null"]
16112
18132
  },
16113
- count: NUMBER
18133
+ count: NUMBER,
18134
+ dwell: {
18135
+ kind: "fixed",
18136
+ result: ["boolean", "null"]
18137
+ },
18138
+ latchedAt: {
18139
+ kind: "fixed",
18140
+ result: ["number", "null"]
18141
+ }
16114
18142
  });
16115
18143
  `${COMPOSED_DEVICE_STABLE_ID_PREFIX}`;
16116
18144
  /**
@@ -16183,6 +18211,7 @@ var CoreBlockStatusSchema = _enum([
16183
18211
  "starting",
16184
18212
  "running",
16185
18213
  "degraded",
18214
+ "incomplete",
16186
18215
  "failed"
16187
18216
  ]);
16188
18217
  /** path → TypeScript source for a multi-file block. */
@@ -38330,7 +40359,7 @@ var PRIMARY_CATEGORIES = new Set(ENTRIES.map((e) => e.primaryCategory));
38330
40359
  * `locationKey` is ALWAYS {@link locationIconKey} of the label — never the
38331
40360
  * operator's casing. The registry matches labels trimmed + case-insensitively
38332
40361
  * everywhere (`addLocation`, `removeLocation`, `renameLocation`), and a
38333
- * case-only rename (`cucina` → `Cucina`) is a real edit this repo supports; a
40362
+ * case-only rename (`kitchen` → `Kitchen`) is a real edit this repo supports; a
38334
40363
  * map keyed on the displayed casing would orphan its entry on exactly that
38335
40364
  * edit. Consumers join by keying their own label through `locationIconKey`.
38336
40365
  */
@@ -38355,7 +40384,7 @@ var LocationDescriptionAssignmentSchema = object({
38355
40384
  /**
38356
40385
  * A SITE ZONE — a named part of the property that several locations belong to.
38357
40386
  *
38358
- * "Zona notte" holds every bedroom; "Zona giorno" the living room and the
40387
+ * "Night zone" holds every bedroom; "Zona giorno" the living room and the
38359
40388
  * kitchen. A camera belongs to exactly one location, and a location to at most
38360
40389
  * one zone, so a camera's zone is derived and never stored on the device: the
38361
40390
  * whole point of this entity is that grouping rooms touches no device row.
@@ -38384,7 +40413,7 @@ var LocationDescriptionAssignmentSchema = object({
38384
40413
  * the locations inside it.
38385
40414
  *
38386
40415
  * The LABEL is carried alongside the key because the key is lossy on purpose —
38387
- * a surface must show "Zona notte", not "zona notte". Locations are carried
40416
+ * a surface must show "Night zone", not "night zone". Locations are carried
38388
40417
  * here, rather than left to a second call, because every consumer wants both
38389
40418
  * at once and a viewer that asked twice could render a zone whose membership
38390
40419
  * it has not fetched yet.
@@ -40578,8 +42607,8 @@ var LoadContributionSchema = object({
40578
42607
  "unattributable"
40579
42608
  ]),
40580
42609
  /**
40581
- * What ONE entry is, in the contributor's own words — `615/high`,
40582
- * `617/native`, `cuda:0 shared pool`. Free text because the unit differs per
42610
+ * What ONE entry is, in the contributor's own words — `101/high`,
42611
+ * `102/native`, `cuda:0 shared pool`. Free text because the unit differs per
40583
42612
  * family and inventing a common one would lose the only information that
40584
42613
  * makes two entries for the same camera distinguishable.
40585
42614
  */
@@ -42227,6 +44256,381 @@ var _macroLookup = /* @__PURE__ */ new Map();
42227
44256
  for (const [k, v] of Object.entries(YAMNET_TO_MACRO.mapping)) _macroLookup.set(k.toLowerCase(), v);
42228
44257
  for (const [k, v] of Object.entries(APPLE_SA_TO_MACRO.mapping)) _macroLookup.set(k.toLowerCase(), v);
42229
44258
  /**
44259
+ * Palette entry ids (D939). Audio is the one gradient; `audio-*` leaves are
44260
+ * not entries. `heatmapScrub` is a mark, not an event kind.
44261
+ */
44262
+ var PALETTE_ENTRY_IDS = [
44263
+ "motion",
44264
+ "audio",
44265
+ "recording",
44266
+ "live",
44267
+ "heatmapScrub",
44268
+ "person",
44269
+ "vehicle",
44270
+ "animal",
44271
+ "package",
44272
+ "sensor",
44273
+ "control",
44274
+ "face",
44275
+ "plate",
44276
+ "car",
44277
+ "truck",
44278
+ "bus",
44279
+ "motorcycle",
44280
+ "bicycle",
44281
+ "airplane",
44282
+ "boat",
44283
+ "train",
44284
+ "bird",
44285
+ "dog",
44286
+ "cat",
44287
+ "horse",
44288
+ "sheep",
44289
+ "cow",
44290
+ "elephant",
44291
+ "bear",
44292
+ "zebra",
44293
+ "giraffe",
44294
+ "package-delivered",
44295
+ "package-picked-up",
44296
+ "suitcase",
44297
+ "backpack",
44298
+ "handbag",
44299
+ "contact",
44300
+ "motion-sensor",
44301
+ "smoke",
44302
+ "flood",
44303
+ "gas",
44304
+ "carbon-monoxide",
44305
+ "vibration",
44306
+ "tamper",
44307
+ "presence",
44308
+ "enum-sensor",
44309
+ "device-event",
44310
+ "lock",
44311
+ "cover",
44312
+ "switch",
44313
+ "siren",
44314
+ "button",
44315
+ "doorbell"
44316
+ ];
44317
+ var AUDIO_ENTRY_ID = "audio";
44318
+ /** Six rungs, quiet → loud. The opaque end is the entry's hex. */
44319
+ var AUDIO_GRADIENT_ALPHAS = [
44320
+ .3,
44321
+ .42,
44322
+ .55,
44323
+ .7,
44324
+ .85,
44325
+ 1
44326
+ ];
44327
+ var PALETTE_PRESET_IDS = [
44328
+ "camstack",
44329
+ "high-contrast",
44330
+ "okabe-ito"
44331
+ ];
44332
+ /** Frozen palette tables (D939). The spec refuses a table that breaks the rule. */
44333
+ var CAMSTACK_HEX = {
44334
+ motion: "#d946ef",
44335
+ audio: "#059eb8",
44336
+ recording: "#ef4444",
44337
+ live: "#8d7a00",
44338
+ heatmapScrub: "#4b32ff",
44339
+ person: "#11a64c",
44340
+ vehicle: "#3b82f6",
44341
+ animal: "#ea6a09",
44342
+ package: "#924667",
44343
+ sensor: "#624bbc",
44344
+ control: "#944d24",
44345
+ face: "#ed4f8d",
44346
+ plate: "#4b7027",
44347
+ car: "#9684cf",
44348
+ truck: "#0f9b89",
44349
+ bus: "#a734a9",
44350
+ motorcycle: "#c1133a",
44351
+ bicycle: "#0e6a9b",
44352
+ airplane: "#7c9928",
44353
+ boat: "#b17933",
44354
+ train: "#ad6ca3",
44355
+ bird: "#0f7c55",
44356
+ dog: "#c82700",
44357
+ cat: "#7268f2",
44358
+ horse: "#cb795e",
44359
+ sheep: "#b8636b",
44360
+ cow: "#cb2969",
44361
+ elephant: "#1158d2",
44362
+ bear: "#8d5e00",
44363
+ zebra: "#0097d6",
44364
+ giraffe: "#8f61bb",
44365
+ "package-delivered": "#cd3f9b",
44366
+ "package-picked-up": "#388a08",
44367
+ suitcase: "#666800",
44368
+ backpack: "#ec5022",
44369
+ handbag: "#a76ef8",
44370
+ contact: "#ab5a49",
44371
+ "motion-sensor": "#b95d1a",
44372
+ smoke: "#dd3858",
44373
+ flood: "#b31e7d",
44374
+ gas: "#5b70b5",
44375
+ "carbon-monoxide": "#7b4e8e",
44376
+ vibration: "#e65bba",
44377
+ tamper: "#98464b",
44378
+ presence: "#3a9468",
44379
+ "enum-sensor": "#7885f8",
44380
+ "device-event": "#8c43c8",
44381
+ lock: "#649653",
44382
+ cover: "#c67597",
44383
+ switch: "#7a812a",
44384
+ siren: "#ac5d7f",
44385
+ button: "#b276cd",
44386
+ doorbell: "#0087ab"
44387
+ };
44388
+ var CAMSTACK_FALLBACK = [
44389
+ "#b34dc7",
44390
+ "#1d7d34",
44391
+ "#db6b6c",
44392
+ "#a43d29",
44393
+ "#0e6ee6",
44394
+ "#29a10b",
44395
+ "#a98731",
44396
+ "#0181c6"
44397
+ ];
44398
+ var HIGH_CONTRAST_HEX = {
44399
+ motion: "#964360",
44400
+ audio: "#23a132",
44401
+ recording: "#2494ca",
44402
+ live: "#bd7e2b",
44403
+ heatmapScrub: "#ad6eea",
44404
+ person: "#62611e",
44405
+ vehicle: "#f4534c",
44406
+ animal: "#1556cd",
44407
+ package: "#9c4415",
44408
+ sensor: "#066c48",
44409
+ control: "#f2479f",
44410
+ face: "#139d8a",
44411
+ plate: "#909024",
44412
+ car: "#8e35ab",
44413
+ truck: "#bd0b2b",
44414
+ bus: "#7a88ca",
44415
+ motorcycle: "#e26725",
44416
+ bicycle: "#a6679b",
44417
+ airplane: "#7c5720",
44418
+ boat: "#467a1b",
44419
+ train: "#6f65a4",
44420
+ bird: "#cb717f",
44421
+ dog: "#c62490",
44422
+ cat: "#b36850",
44423
+ horse: "#1872ac",
44424
+ sheep: "#927939",
44425
+ cow: "#428a5c",
44426
+ elephant: "#d41160",
44427
+ bear: "#799453",
44428
+ zebra: "#a85455",
44429
+ giraffe: "#746be8",
44430
+ "package-delivered": "#824a80",
44431
+ "package-picked-up": "#614ac1",
44432
+ suitcase: "#2f77f3",
44433
+ backpack: "#fa476d",
44434
+ handbag: "#c14cbe",
44435
+ contact: "#c83921",
44436
+ "motion-sensor": "#a07ebd",
44437
+ smoke: "#a25b13",
44438
+ flood: "#526bab",
44439
+ gas: "#924938",
44440
+ "carbon-monoxide": "#bb7e53",
44441
+ vibration: "#b66182",
44442
+ tamper: "#3c6931",
44443
+ presence: "#6c851d",
44444
+ "enum-sensor": "#ad2d48",
44445
+ "device-event": "#5e9b04",
44446
+ lock: "#00a062",
44447
+ cover: "#ad8624",
44448
+ switch: "#d05259",
44449
+ siren: "#cd67b3",
44450
+ button: "#c9746a",
44451
+ doorbell: "#338eeb"
44452
+ };
44453
+ var HIGH_CONTRAST_FALLBACK = [
44454
+ "#817f3b",
44455
+ "#a0733e",
44456
+ "#8658b2",
44457
+ "#956301",
44458
+ "#bc652d",
44459
+ "#647331",
44460
+ "#a14c9e",
44461
+ "#d14e71"
44462
+ ];
44463
+ var OKABE_ITO_HEX = {
44464
+ motion: "#b88128",
44465
+ audio: "#1096c8",
44466
+ recording: "#009e73",
44467
+ live: "#9c8c22",
44468
+ heatmapScrub: "#0072b2",
44469
+ person: "#d55e00",
44470
+ vehicle: "#c0739f",
44471
+ animal: "#226d18",
44472
+ package: "#91446c",
44473
+ sensor: "#217b56",
44474
+ control: "#648647",
44475
+ face: "#c22998",
44476
+ plate: "#fa4575",
44477
+ car: "#956301",
44478
+ truck: "#2f77f3",
44479
+ bus: "#7a4e86",
44480
+ motorcycle: "#f54597",
44481
+ bicycle: "#bb3e75",
44482
+ airplane: "#e054c0",
44483
+ boat: "#457942",
44484
+ train: "#867afa",
44485
+ bird: "#88914c",
44486
+ dog: "#1556cd",
44487
+ cat: "#71702c",
44488
+ horse: "#9b4fa4",
44489
+ sheep: "#c0559d",
44490
+ cow: "#d14f65",
44491
+ elephant: "#98470f",
44492
+ bear: "#595896",
44493
+ zebra: "#96790e",
44494
+ giraffe: "#cb717b",
44495
+ "package-delivered": "#139d8a",
44496
+ "package-picked-up": "#906ead",
44497
+ suitcase: "#d02939",
44498
+ backpack: "#d41160",
44499
+ handbag: "#f64f54",
44500
+ contact: "#7258d2",
44501
+ "motion-sensor": "#b66182",
44502
+ smoke: "#627abb",
44503
+ flood: "#b86ae4",
44504
+ gas: "#a95261",
44505
+ "carbon-monoxide": "#c65d3c",
44506
+ vibration: "#7a40b7",
44507
+ tamper: "#914b34",
44508
+ presence: "#9481c3",
44509
+ "enum-sensor": "#ac6d47",
44510
+ "device-event": "#7b6fce",
44511
+ lock: "#c67662",
44512
+ cover: "#a6564d",
44513
+ switch: "#ad2c4e",
44514
+ siren: "#348e08",
44515
+ button: "#d27303",
44516
+ doorbell: "#55770f"
44517
+ };
44518
+ var OKABE_ITO_FALLBACK = [
44519
+ "#9a3784",
44520
+ "#a7392c",
44521
+ "#409d50",
44522
+ "#6987e7",
44523
+ "#ee5b3d",
44524
+ "#c0430d",
44525
+ "#af79b3",
44526
+ "#4b6628"
44527
+ ];
44528
+ /**
44529
+ * The display palette (D939). One table of colours, three presets, one
44530
+ * validator. Taxonomy colours and every consumer read this — there is no
44531
+ * second hex table.
44532
+ */
44533
+ var paletteHexSchema = string().regex(/^#[0-9a-f]{6}$/);
44534
+ var paletteSwatchSchema = discriminatedUnion("form", [object({
44535
+ form: literal("solid"),
44536
+ hex: paletteHexSchema
44537
+ }), object({
44538
+ form: literal("gradient"),
44539
+ hex: paletteHexSchema,
44540
+ alphas: array(number().gt(0).lte(1)).length(AUDIO_GRADIENT_ALPHAS.length)
44541
+ })]);
44542
+ var paletteReadySchema = object({
44543
+ status: literal("ready"),
44544
+ presetId: _enum(PALETTE_PRESET_IDS),
44545
+ customized: boolean(),
44546
+ source: _enum(["stored", "unconfigured"]),
44547
+ swatches: record(string(), paletteSwatchSchema),
44548
+ fallbacks: array(paletteHexSchema).length(8)
44549
+ });
44550
+ var paletteResultSchema = discriminatedUnion("status", [paletteReadySchema, object({
44551
+ status: literal("unknown"),
44552
+ reason: string()
44553
+ })]);
44554
+ var setPaletteInputSchema = union([object({ presetId: string() }), object({
44555
+ presetId: string(),
44556
+ overrides: record(string(), paletteSwatchSchema)
44557
+ })]);
44558
+ object({
44559
+ presetId: string(),
44560
+ overrides: record(string(), paletteSwatchSchema)
44561
+ });
44562
+ function solid(hex) {
44563
+ return {
44564
+ form: "solid",
44565
+ hex
44566
+ };
44567
+ }
44568
+ function audioGradient(hex) {
44569
+ return {
44570
+ form: "gradient",
44571
+ hex,
44572
+ alphas: [...AUDIO_GRADIENT_ALPHAS]
44573
+ };
44574
+ }
44575
+ function swatchesFrom(hexes) {
44576
+ const out = {};
44577
+ for (const id of PALETTE_ENTRY_IDS) {
44578
+ const hex = hexes[id];
44579
+ if (hex === void 0) throw new Error(`palette table missing ${id}`);
44580
+ out[id] = id === "audio" ? audioGradient(hex) : solid(hex);
44581
+ }
44582
+ return out;
44583
+ }
44584
+ function preset(id, name, hexes, fallbacks) {
44585
+ return {
44586
+ id,
44587
+ name,
44588
+ swatches: swatchesFrom(hexes),
44589
+ fallbacks
44590
+ };
44591
+ }
44592
+ var DISPLAY_PRESETS = [
44593
+ preset("camstack", "CamStack", CAMSTACK_HEX, CAMSTACK_FALLBACK),
44594
+ preset("high-contrast", "High contrast", HIGH_CONTRAST_HEX, HIGH_CONTRAST_FALLBACK),
44595
+ preset("okabe-ito", "Colour-blind safe", OKABE_ITO_HEX, OKABE_ITO_FALLBACK)
44596
+ ];
44597
+ function presetById(id) {
44598
+ return DISPLAY_PRESETS.find((item) => item.id === id);
44599
+ }
44600
+ function bundledCamstack() {
44601
+ const presetRow = presetById("camstack");
44602
+ if (presetRow === void 0) throw new Error("CamStack preset missing");
44603
+ return readyOf(presetRow, "unconfigured", false);
44604
+ }
44605
+ function readyOf(row, source, customized) {
44606
+ return {
44607
+ status: "ready",
44608
+ presetId: row.id,
44609
+ customized,
44610
+ source,
44611
+ swatches: row.swatches,
44612
+ fallbacks: [...row.fallbacks]
44613
+ };
44614
+ }
44615
+ function hashFallback(kind, fallbacks) {
44616
+ let hash = 0;
44617
+ for (let i = 0; i < kind.length; i++) hash = hash * 31 + (kind.codePointAt(i) ?? 0) >>> 0;
44618
+ const hex = fallbacks[hash % fallbacks.length];
44619
+ if (hex === void 0) throw new Error("display palette has no fallback colour");
44620
+ return hex;
44621
+ }
44622
+ /** Colour a kind paints with. Audio leaves share the audio gradient's hex. */
44623
+ function paintHex(swatches, fallbacks, kind) {
44624
+ const key = kind.trim().toLowerCase();
44625
+ if (key.startsWith("audio-")) {
44626
+ const audio = swatches[AUDIO_ENTRY_ID];
44627
+ return audio !== void 0 ? audio.hex : hashFallback(key, fallbacks);
44628
+ }
44629
+ const direct = swatches[key];
44630
+ if (direct !== void 0) return direct.hex;
44631
+ return hashFallback(key, fallbacks);
44632
+ }
44633
+ /**
42230
44634
  * Unified event-kind taxonomy — THE single source of truth for
42231
44635
  * `kind → { parentKind, category, level, color, iconId, labelKey, label,
42232
44636
  * icon }`.
@@ -42240,109 +44644,88 @@ for (const [k, v] of Object.entries(APPLE_SA_TO_MACRO.mapping)) _macroLookup.set
42240
44644
  * - `addon-post-analysis/shared/frame/box-drawer.ts` (DEFAULT_COLOR)
42241
44645
  * - the COCO / audio class maps (macro ↔ sub relationships)
42242
44646
  *
42243
- * The DATA (serializable — color/iconId/labelKey/parentKind) lives here in
42244
- * `@camstack/types`. The UI-side mapping `iconId → lucide component` and
42245
- * `labelKey → t()` lives in `@camstack/ui-library`. UIs never hardcode a
42246
- * color or an icon: they read this dictionary (server descriptors carry the
42247
- * fields inline; the client resolves color/icon/label from `iconId`/`kind`).
44647
+ * The DATA (serializable — parentKind / iconId / labelKey) lives here in
44648
+ * `@camstack/types`. Colour is NOT a second table: each entry's `color` is
44649
+ * the bundled CamStack display palette (D939). The effective cluster palette
44650
+ * is the `display-palette` capability. The UI-side mapping `iconId → lucide
44651
+ * component` and `labelKey → t()` lives in `@camstack/ui-library`.
42248
44652
  *
42249
44653
  * Two levels only (v1 YAGNI): macro → sub. `person` is a leaf macro.
42250
44654
  */
42251
- var TAXONOMY_COLORS = {
42252
- motion: "#f59e0b",
42253
- audio: "#06b6d4",
42254
- person: "#22c55e",
42255
- vehicle: "#3b82f6",
42256
- animal: "#f97316",
42257
- package: "#a855f7",
42258
- sensor: "#8b5cf6",
42259
- control: "#10b981",
42260
- genericDetection: "#64748b"
42261
- };
42262
- var DETECTION_SUB_COLORS = {
42263
- car: "#f59e0b",
42264
- truck: "#d97706",
42265
- bus: "#b45309",
42266
- motorcycle: "#eab308",
42267
- bicycle: "#ca8a04",
42268
- airplane: "#60a5fa",
42269
- boat: "#2563eb",
42270
- train: "#1d4ed8",
42271
- bird: "#14b8a6",
42272
- dog: "#84cc16",
42273
- cat: "#f97316",
42274
- horse: "#a16207",
42275
- sheep: "#a3a3a3",
42276
- cow: "#78716c",
42277
- elephant: "#6b7280",
42278
- bear: "#7c2d12",
42279
- zebra: "#404040",
42280
- giraffe: "#d4a373"
42281
- };
44655
+ var BUNDLED_PALETTE = bundledCamstack();
44656
+ function kindColor(kind) {
44657
+ return paintHex(BUNDLED_PALETTE.swatches, BUNDLED_PALETTE.fallbacks, kind);
44658
+ }
44659
+ function firstFallback(fallbacks) {
44660
+ const hex = fallbacks[0];
44661
+ if (hex === void 0) throw new Error("display palette has no fallback colour");
44662
+ return hex;
44663
+ }
44664
+ firstFallback(BUNDLED_PALETTE.fallbacks);
42282
44665
  function titleCase(id) {
42283
44666
  return id.split(/[-_ ]/).filter((p) => p.length > 0).map((p) => p.charAt(0).toUpperCase() + p.slice(1)).join(" ");
42284
44667
  }
42285
44668
  var entries = /* @__PURE__ */ new Map();
42286
- function macro(kind, category, color, iconId, label) {
44669
+ function macro(kind, category, iconId, label) {
42287
44670
  entries.set(kind, {
42288
44671
  kind,
42289
44672
  parentKind: null,
42290
44673
  level: "macro",
42291
44674
  category,
42292
- color,
44675
+ color: kindColor(kind),
42293
44676
  iconId,
42294
44677
  labelKey: `eventKind.${kind}`,
42295
44678
  label
42296
44679
  });
42297
44680
  }
42298
- function sub(kind, parentKind, category, color, iconId, label) {
44681
+ function sub(kind, parentKind, category, iconId, label) {
42299
44682
  entries.set(kind, {
42300
44683
  kind,
42301
44684
  parentKind,
42302
44685
  level: "sub",
42303
44686
  category,
42304
- color,
44687
+ color: kindColor(kind),
42305
44688
  iconId,
42306
44689
  labelKey: `eventKind.${kind}`,
42307
44690
  label
42308
44691
  });
42309
44692
  }
42310
- macro("motion", "motion", TAXONOMY_COLORS.motion, "motion", "Motion");
42311
- macro("audio", "audio", TAXONOMY_COLORS.audio, "audio", "Audio");
42312
- macro("person", "detection", TAXONOMY_COLORS.person, "person", "Person");
42313
- macro("vehicle", "detection", TAXONOMY_COLORS.vehicle, "vehicle", "Vehicle");
42314
- macro("animal", "detection", TAXONOMY_COLORS.animal, "animal", "Animal");
42315
- macro("package", "package", TAXONOMY_COLORS.package, "package", "Package");
42316
- macro("sensor", "sensor", TAXONOMY_COLORS.sensor, "sensor", "Sensor");
42317
- macro("control", "control", TAXONOMY_COLORS.control, "control", "Control");
44693
+ macro("motion", "motion", "motion", "Motion");
44694
+ macro("audio", "audio", "audio", "Audio");
44695
+ macro("person", "detection", "person", "Person");
44696
+ macro("vehicle", "detection", "vehicle", "Vehicle");
44697
+ macro("animal", "detection", "animal", "Animal");
44698
+ macro("package", "package", "package", "Package");
44699
+ macro("sensor", "sensor", "sensor", "Sensor");
44700
+ macro("control", "control", "control", "Control");
42318
44701
  for (const [cocoClass, macroClass] of Object.entries(COCO_TO_MACRO.mapping)) {
42319
44702
  if (macroClass !== "vehicle" && macroClass !== "animal") continue;
42320
44703
  if (entries.has(cocoClass)) continue;
42321
- sub(cocoClass, macroClass, "detection", DETECTION_SUB_COLORS[cocoClass] ?? TAXONOMY_COLORS.genericDetection, cocoClass, titleCase(cocoClass));
44704
+ sub(cocoClass, macroClass, "detection", cocoClass, titleCase(cocoClass));
42322
44705
  }
42323
- sub("package-delivered", "package", "package", TAXONOMY_COLORS.package, "package", "Package delivered");
42324
- sub("package-picked-up", "package", "package", TAXONOMY_COLORS.package, "package", "Package picked up");
42325
- sub("contact", "sensor", "sensor", "#f59e0b", "door", "Contact");
42326
- sub("motion-sensor", "sensor", "sensor", TAXONOMY_COLORS.sensor, "pir", "Motion sensor");
42327
- sub("smoke", "sensor", "sensor", "#ef4444", "smoke", "Smoke");
42328
- sub("flood", "sensor", "sensor", "#3b82f6", "water", "Water leak");
42329
- sub("gas", "sensor", "sensor", "#ef4444", "gas", "Gas");
42330
- sub("carbon-monoxide", "sensor", "sensor", "#dc2626", "smoke", "Carbon monoxide");
42331
- sub("vibration", "sensor", "sensor", "#eab308", "vibration", "Vibration");
42332
- sub("tamper", "sensor", "sensor", "#f97316", "tamper", "Tamper");
42333
- sub("presence", "sensor", "sensor", "#22c55e", "presence", "Presence");
42334
- sub("enum-sensor", "sensor", "sensor", TAXONOMY_COLORS.sensor, "generic", "Sensor state");
42335
- sub("device-event", "sensor", "sensor", "#10b981", "button", "Device event");
42336
- sub("lock", "control", "control", "#0ea5e9", "lock", "Lock");
42337
- sub("cover", "control", "control", "#0ea5e9", "door", "Cover");
42338
- sub("switch", "control", "control", TAXONOMY_COLORS.control, "switch", "Switch");
42339
- sub("siren", "control", "control", "#dc2626", "siren", "Siren");
42340
- sub("button", "control", "control", "#10b981", "button", "Button");
42341
- sub("doorbell", "control", "control", "#a855f7", "doorbell", "Doorbell");
44706
+ sub("package-delivered", "package", "package", "package", "Package delivered");
44707
+ sub("package-picked-up", "package", "package", "package", "Package picked up");
44708
+ sub("contact", "sensor", "sensor", "door", "Contact");
44709
+ sub("motion-sensor", "sensor", "sensor", "pir", "Motion sensor");
44710
+ sub("smoke", "sensor", "sensor", "smoke", "Smoke");
44711
+ sub("flood", "sensor", "sensor", "water", "Water leak");
44712
+ sub("gas", "sensor", "sensor", "gas", "Gas");
44713
+ sub("carbon-monoxide", "sensor", "sensor", "smoke", "Carbon monoxide");
44714
+ sub("vibration", "sensor", "sensor", "vibration", "Vibration");
44715
+ sub("tamper", "sensor", "sensor", "tamper", "Tamper");
44716
+ sub("presence", "sensor", "sensor", "presence", "Presence");
44717
+ sub("enum-sensor", "sensor", "sensor", "generic", "Sensor state");
44718
+ sub("device-event", "sensor", "sensor", "button", "Device event");
44719
+ sub("lock", "control", "control", "lock", "Lock");
44720
+ sub("cover", "control", "control", "door", "Cover");
44721
+ sub("switch", "control", "control", "switch", "Switch");
44722
+ sub("siren", "control", "control", "siren", "Siren");
44723
+ sub("button", "control", "control", "button", "Button");
44724
+ sub("doorbell", "control", "control", "doorbell", "Doorbell");
42342
44725
  for (const l of AUDIO_MACRO_LABELS) {
42343
44726
  const kind = `audio-${l.id}`;
42344
44727
  if (entries.has(kind)) continue;
42345
- sub(kind, "audio", "audio", TAXONOMY_COLORS.audio, kind, l.name);
44728
+ sub(kind, "audio", "audio", kind, l.name);
42346
44729
  }
42347
44730
  /** The complete taxonomy dictionary, keyed by kind. */
42348
44731
  var EVENT_TAXONOMY = Object.freeze(Object.fromEntries(entries));
@@ -42653,9 +45036,6 @@ var NcSystemEventKindSchema = _enum([
42653
45036
  "device-battery-normal",
42654
45037
  "device-consumable-low",
42655
45038
  "device-consumable-normal",
42656
- "device-tank-low",
42657
- "device-tank-full",
42658
- "device-tank-normal",
42659
45039
  "stream-online",
42660
45040
  "stream-offline",
42661
45041
  "node-online",
@@ -42702,13 +45082,14 @@ var NcSystemEventKindSchema = _enum([
42702
45082
  "camera-enabled"
42703
45083
  ]);
42704
45084
  /** The legacy tail of {@link NcSystemEventKindSchema} — see its docblock. */
42705
- var NC_LEGACY_SYSTEM_EVENT_KINDS = new Set([
45085
+ var NC_LEGACY_SYSTEM_EVENT_KINDS = [
42706
45086
  "camera-online",
42707
45087
  "camera-offline",
42708
45088
  "camera-disabled",
42709
45089
  "camera-enabled"
42710
- ]);
42711
- NcSystemEventKindSchema.options.filter((kind) => !NC_LEGACY_SYSTEM_EVENT_KINDS.has(kind));
45090
+ ];
45091
+ var NC_LEGACY_SYSTEM_EVENT_KIND_SET = new Set(NC_LEGACY_SYSTEM_EVENT_KINDS);
45092
+ NcSystemEventKindSchema.options.filter((kind) => !NC_LEGACY_SYSTEM_EVENT_KIND_SET.has(kind));
42712
45093
  /**
42713
45094
  * The panel's transitions, as ONE list.
42714
45095
  *
@@ -43231,7 +45612,7 @@ var NcConditionsSchema = object({
43231
45612
  * with the list under it is worse than no switch (D62).
43232
45613
  *
43233
45614
  * MEMBERS ARE FACE-GALLERY `Identity.id`s (uuid), not display names. A name is
43234
- * renameable, and a rule authored on "Gianluca" went silently dark the moment
45615
+ * renameable, and a rule authored on "Alice" went silently dark the moment
43235
45616
  * the operator fixed the spelling. The id reaches the record on
43236
45617
  * `LabelAttribution.identityId`; the name is what the editor shows and what
43237
45618
  * `{{label}}` renders.
@@ -43782,7 +46163,7 @@ var NcRulePatchSchema = NcRuleInputSchema.partial().extend({
43782
46163
  * A rule scoped to one camera and one zone silently became a rule that
43783
46164
  * matches EVERY event on EVERY camera, and lost its `media` policy
43784
46165
  * (zoneCrop / gif / clip / frame) and its `priority` at the same time. Seen
43785
- * live on 2026-08-12: a rule scoped to device 617 fired on 590 and 615
46166
+ * live on 2026-08-12: a rule scoped to device 102 fired on 104 and 101
43786
46167
  * within a minute of a two-field patch.
43787
46168
  *
43788
46169
  * So every defaulted field is re-declared here WITHOUT its default. The
@@ -43827,18 +46208,11 @@ var NcRuleSchema = NcRuleInputSchema.extend({
43827
46208
  */
43828
46209
  disabledTargetIds: array(string()).default([])
43829
46210
  });
43830
- /**
43831
- * The state-summary SECTIONS (D647 / D698 / D708): the D637 kind groups that
43832
- * report a still-true state. `addons` is the crash-looped addons only and
43833
- * `addon-updates` the addons that are behind (D708 split them). `backups-exports` and `alarm` are not sections — a completed
43834
- * job is not an open state, and the alarm stays instant.
43835
- */
43836
46211
  var NcStateSummarySectionIdSchema = _enum([
43837
46212
  "device-state",
43838
46213
  "streams",
43839
46214
  "battery",
43840
46215
  "consumables",
43841
- "tanks",
43842
46216
  "detection-blind",
43843
46217
  "nodes",
43844
46218
  "addons",
@@ -45139,6 +47513,18 @@ Object.freeze({
45139
47513
  reason: "camera sensor mappings not loaded"
45140
47514
  });
45141
47515
  /**
47516
+ * What the vision model must answer before a package event is emitted
47517
+ * when a packages rule has "Confirm with the LLM" on.
47518
+ *
47519
+ * `package` is the verdict. `confidence` is 0..1. `reason` is the model's
47520
+ * one-line explanation, stored on the event so a drop is not silent.
47521
+ */
47522
+ var PackageLlmVerdictSchema = object({
47523
+ package: boolean(),
47524
+ confidence: number().min(0).max(1),
47525
+ reason: string().min(1)
47526
+ });
47527
+ /**
45142
47528
  * A model choice has a SCOPE, and a scope change has a workflow.
45143
47529
  *
45144
47530
  * ## The two scopes
@@ -45590,7 +47976,7 @@ var LabelAttributionSchema = object({
45590
47976
  * `Identity.id` or a plate-gallery `Vehicle.id` (both `randomUUID`).
45591
47977
  *
45592
47978
  * The text alone is a DISPLAY NAME, and a display name is renameable: a
45593
- * notification rule authored on "Gianluca" stopped matching the moment the
47979
+ * notification rule authored on "Alice" stopped matching the moment the
45594
47980
  * operator fixed the spelling in the gallery, and nothing said so. The id is
45595
47981
  * the thing that does not move, so it is what a rule matches on
45596
47982
  * (`NcConditions.identities`) and the text is what a human is shown.
@@ -46075,6 +48461,21 @@ var ObjectEventSchema = object({
46075
48461
  * pick-up written before D684 — UNKNOWN, never 0 and never `timestamp`.
46076
48462
  */
46077
48463
  observedAt: number().optional(),
48464
+ /**
48465
+ * The delivery was emitted without a vision-model yes (D931).
48466
+ *
48467
+ * Set only when the packages rule asked for an LLM confirm and the model
48468
+ * was unreachable, timed out, or answered something that did not parse.
48469
+ * A notification reads it so it can say "possible" instead of a definite
48470
+ * delivery. Absent on every other row, and on a confirm that said yes.
48471
+ */
48472
+ packagePossible: boolean().optional(),
48473
+ /**
48474
+ * The vision model's verdict, when a packages rule asked for one and the
48475
+ * model answered the schema (D931). A "no" never becomes a row — the
48476
+ * detector drops it and logs the reason. Present on a yes.
48477
+ */
48478
+ packageLlmVerdict: PackageLlmVerdictSchema.optional(),
46078
48479
  /** The parent track's key-event importance [0,1], propagated to every object
46079
48480
  * event of the track (so an event row can be sorted by importance without a
46080
48481
  * track join). Absent on legacy rows / before the track was scored. */
@@ -47872,7 +50273,6 @@ var PipelineAddonSchemaSchema = object({
47872
50273
  defaultModelId: string(),
47873
50274
  defaultModelIdByFormat: record(string(), string()).optional(),
47874
50275
  enabledByDefault: boolean().optional(),
47875
- backfillIntoExistingOverrides: boolean().optional(),
47876
50276
  defaultConfidence: number(),
47877
50277
  group: string().optional(),
47878
50278
  configSchema: array(ConfigFieldBridge).readonly().optional()
@@ -47999,13 +50399,12 @@ var AudioTestResultSchema = object({
47999
50399
  error: string().optional(),
48000
50400
  frame: custom().optional()
48001
50401
  });
48002
- var PipelineConfigBridge = custom();
48003
50402
  var ConfigUISchemaBridge = custom();
48004
50403
  var ConfigUISchemaNullableBridge = custom();
48005
50404
  var InferenceCapabilitiesBridge = custom();
48006
50405
  var ModelAvailabilityListBridge = custom();
48007
50406
  var PipelineRunResultBridge = custom();
48008
- method(_void(), array(PipelineEngineChoiceSchema)), method(_void(), PipelineEngineChoiceSchema), method(PipelineEngineChoiceSchema, array(PipelineDefaultStepSchema)), method(object({ nodeId: string() }), EngineProvisioningSchema), method(_void(), record(string(), object({
50407
+ method(_void(), array(PipelineEngineChoiceSchema)), method(_void(), PipelineEngineChoiceSchema), method(object({ nodeId: string() }), EngineProvisioningSchema), method(_void(), record(string(), object({
48009
50408
  modelId: string(),
48010
50409
  settings: record(string(), unknown()).readonly()
48011
50410
  }))), method(object({ steps: record(string(), object({
@@ -48014,28 +50413,6 @@ method(_void(), array(PipelineEngineChoiceSchema)), method(_void(), PipelineEngi
48014
50413
  })) }), object({ success: literal(true) }), {
48015
50414
  kind: "mutation",
48016
50415
  auth: "admin"
48017
- }), method(object({ nodeId: string() }), object({
48018
- success: literal(true),
48019
- clearedDevices: number()
48020
- }), {
48021
- kind: "mutation",
48022
- auth: "admin"
48023
- }), method(object({
48024
- nodeId: string(),
48025
- deviceIds: array(number()).readonly().optional(),
48026
- dryRun: boolean()
48027
- }), object({
48028
- entries: array(object({
48029
- deviceId: number(),
48030
- keys: array(string()).readonly()
48031
- })).readonly(),
48032
- refused: array(object({
48033
- deviceId: number(),
48034
- reason: string()
48035
- })).readonly()
48036
- }), {
48037
- kind: "mutation",
48038
- auth: "admin"
48039
50416
  }), method(object({ nodeId: string() }), object({ unhealthy: array(object({
48040
50417
  /** `<backend>:<device>`, e.g. `openvino:gpu`. */
48041
50418
  deviceKey: string(),
@@ -48058,7 +50435,7 @@ method(_void(), array(PipelineEngineChoiceSchema)), method(_void(), PipelineEngi
48058
50435
  }), object({ rearmed: boolean() }), {
48059
50436
  kind: "mutation",
48060
50437
  auth: "admin"
48061
- }), method(_void(), PipelineSchemaSchema), method(_void(), array(PipelineDefaultStepSchema).readonly().nullable()), method(_void(), PipelineConfigBridge), method(_void(), ConfigUISchemaBridge), method(object({
50438
+ }), method(_void(), PipelineSchemaSchema), method(_void(), ConfigUISchemaBridge), method(object({
48062
50439
  steps: array(PipelineStepInputSchema),
48063
50440
  deviceKey: string().optional()
48064
50441
  }), PipelineValidationResultSchema), method(_void(), InferenceCapabilitiesBridge), method(object({ addonId: string() }), ModelAvailabilityListBridge), method(object({
@@ -48138,7 +50515,7 @@ method(_void(), array(PipelineEngineChoiceSchema)), method(_void(), PipelineEngi
48138
50515
  /**
48139
50516
  * Root-supplied detections for the tree's ROOT step (D730). Set by
48140
50517
  * `runDetailSubtree` when the camera's root model supplies a crop-kind
48141
- * step (a Frigate+ `license_plate` for `plate-detection`): the step is
50518
+ * step (a plus catalog `license_plate` for `plate-detection`): the step is
48142
50519
  * NOT inferred, these boxes are its output, and its children (the plate
48143
50520
  * reader) run on them through their own crop policy. Boxes are in the
48144
50521
  * PIXELS of the image this call carries. Absent ⇒ the root step runs.
@@ -48306,11 +50683,18 @@ var KeptReasonSchema = _enum(["custom-pin"]);
48306
50683
  * Where a choice's latency came from (D791): this node's own benchmark
48307
50684
  * result, or the hardware-class table. Measured on the node beats the table.
48308
50685
  */
48309
- var LatencySourceSchema = discriminatedUnion("kind", [object({ kind: literal("table") }), object({
48310
- kind: literal("node-benchmark"),
48311
- resultId: string(),
48312
- measuredAtMs: number()
48313
- })]);
50686
+ var LatencySourceSchema = discriminatedUnion("kind", [
50687
+ object({ kind: literal("table") }),
50688
+ object({
50689
+ kind: literal("node-benchmark"),
50690
+ resultId: string(),
50691
+ measuredAtMs: number()
50692
+ }),
50693
+ object({
50694
+ kind: literal("estimated"),
50695
+ estimatedFrom: HardwareClassIdSchema
50696
+ })
50697
+ ]);
48314
50698
  var DeviceModelChoiceSchema = object({
48315
50699
  modelId: string(),
48316
50700
  p50Ms: number(),
@@ -48318,6 +50702,11 @@ var DeviceModelChoiceSchema = object({
48318
50702
  measured: boolean(),
48319
50703
  /** Absent on a plan from before D791 — read as the table. */
48320
50704
  source: LatencySourceSchema.optional(),
50705
+ /**
50706
+ * The measured class this latency was scaled from (D930). Absent when the
50707
+ * cell is the table or a node benchmark.
50708
+ */
50709
+ estimatedFrom: HardwareClassIdSchema.optional(),
48321
50710
  /** Parallel sessions at the camera rate with the headroom kept free: ⌊fps × (1 − headroom) / camera fps⌋. */
48322
50711
  capacitySessions: number(),
48323
50712
  personRecall: number()
@@ -48357,40 +50746,20 @@ var NodeDeviceChangeSchema = object({
48357
50746
  keys: array(string()).readonly()
48358
50747
  })).readonly()
48359
50748
  });
48360
- var CameraOverrideClearSchema = object({
48361
- deviceId: number(),
48362
- source: _enum(["step-override", "wholesale"]),
50749
+ /**
50750
+ * Every model and model-bound threshold lives on the accelerator that runs it
50751
+ * (D927), so the plan writes node / device entries only — there is no camera
50752
+ * layer for it to clear.
50753
+ */
50754
+ var AutoTuneWarningSchema = discriminatedUnion("kind", [object({
50755
+ kind: literal("custom-pin-kept"),
48363
50756
  nodeId: string(),
48364
- deviceKey: string().nullable(),
48365
- stepId: string(),
48366
- modelIdBefore: string().nullable(),
48367
- keys: array(string()).readonly()
48368
- });
48369
- var DetectorStoreClearSchema = object({
48370
- deviceId: number(),
48371
- keys: array(string()).readonly()
48372
- });
48373
- var AutoTuneWarningSchema = discriminatedUnion("kind", [
48374
- object({
48375
- kind: literal("detector-store-cluster-wide"),
48376
- skippedNodes: array(string()).readonly()
48377
- }),
48378
- object({
48379
- kind: literal("detector-store-unreadable"),
48380
- error: string()
48381
- }),
48382
- object({
48383
- kind: literal("custom-pin-kept"),
48384
- nodeId: string(),
48385
- deviceKey: string().nullable(),
48386
- deviceId: number().nullable(),
48387
- modelId: string()
48388
- }),
48389
- object({
48390
- kind: literal("custom-registry-unreadable"),
48391
- error: string()
48392
- })
48393
- ]);
50757
+ deviceKey: string(),
50758
+ modelId: string()
50759
+ }), object({
50760
+ kind: literal("custom-registry-unreadable"),
50761
+ error: string()
50762
+ })]);
48394
50763
  var AutoTuneOptionsSchema = object({
48395
50764
  /** Share of each accelerator's throughput kept free (0.3–0.5). */
48396
50765
  headroom: number().min(.3).max(.5).default(.4),
@@ -48412,8 +50781,6 @@ var AutoTunePlanSchema = object({
48412
50781
  generatedAt: number(),
48413
50782
  nodes: array(NodeRecommendationSchema).readonly(),
48414
50783
  nodeChanges: array(NodeDeviceChangeSchema).readonly(),
48415
- cameraClears: array(CameraOverrideClearSchema).readonly(),
48416
- detectorStoreClears: array(DetectorStoreClearSchema).readonly(),
48417
50784
  warnings: array(AutoTuneWarningSchema).readonly()
48418
50785
  });
48419
50786
  var AutoTuneApplyInputSchema = object({
@@ -48424,8 +50791,6 @@ var AutoTuneApplyInputSchema = object({
48424
50791
  var AutoTunePhaseResultSchema = object({
48425
50792
  phase: _enum([
48426
50793
  "download",
48427
- "camera-overrides",
48428
- "detector-thresholds",
48429
50794
  "node-models",
48430
50795
  "redispatch"
48431
50796
  ]),
@@ -49827,7 +52192,7 @@ var RunnerCameraConfigSchema = object({
49827
52192
  * detection session that asks for history. What shipped was a last-moment
49828
52193
  * discard — `FrameSlot`'s throttle compares wall clocks, and ~4 s of media
49829
52194
  * arriving inside a few hundred ms of wall clock looks to it like one frame's
49830
- * worth. Device 617, 2026-09-08: a re-run of the SAME model over the stored
52195
+ * worth. Device 102, 2026-09-08: a re-run of the SAME model over the stored
49831
52196
  * recording scored the subject `vehicle 0.5669` — above the 0.50 floor —
49832
52197
  * 1.68 s BEFORE the live track was born, on a frame that was in the pre-roll,
49833
52198
  * was decoded, and was freed.
@@ -50180,6 +52545,12 @@ var AgentPipelineSettingsSchema = object({
50180
52545
  /** Hub-persisted UI colour (`--color-node-*` theme tokens). */
50181
52546
  color: NodeColorIdSchema.optional(),
50182
52547
  /**
52548
+ * NODE-wide step settings (D927): `stepId → { key → value }`, applied on
52549
+ * every accelerator of the node under the device's own settings. Never a
52550
+ * model or a model-bound threshold. Written by `setNodeStepSettings`.
52551
+ */
52552
+ stepSettings: record(string(), record(string(), unknown()).readonly()).optional(),
52553
+ /**
50183
52554
  * Multi-device inference opt-in (Phase 4). Per-node map deviceKey → {enabled,
50184
52555
  * weight, steps}. Absent / all-disabled ⇒ the node's single default
50185
52556
  * accelerator (safe default); two+ enabled ⇒ the dispatcher balances
@@ -50195,17 +52566,6 @@ var AgentPipelineSettingsSchema = object({
50195
52566
  steps: record(string(), DeviceStepConfigSchema).optional()
50196
52567
  })).optional()
50197
52568
  });
50198
- var CameraPipelineForAgentSchema = object({
50199
- steps: array(PipelineStepInputSchema).readonly(),
50200
- audio: object({
50201
- modelId: string(),
50202
- enabled: boolean()
50203
- }).nullable()
50204
- });
50205
- var CameraStepOverridePatchSchema = object({
50206
- modelId: string().optional(),
50207
- settings: record(string(), unknown()).readonly().optional()
50208
- });
50209
52569
  var CameraStepSettingsSchema = record(string(), record(string(), unknown()).readonly());
50210
52570
  /** The three root-detector choices a camera has (D507: at most one root). */
50211
52571
  var CameraDetectionSourceSchema = _enum([
@@ -50215,9 +52575,7 @@ var CameraDetectionSourceSchema = _enum([
50215
52575
  ]);
50216
52576
  var CameraPipelineSettingsSchema = object({
50217
52577
  stepToggles: record(string(), boolean()).optional(),
50218
- stepSettings: CameraStepSettingsSchema.optional(),
50219
- stepOverridesByDevice: record(string(), record(string(), record(string(), CameraStepOverridePatchSchema))).optional(),
50220
- pipelineByAgent: record(string(), CameraPipelineForAgentSchema).optional()
52578
+ stepSettings: CameraStepSettingsSchema.optional()
50221
52579
  });
50222
52580
  /**
50223
52581
  * Pipeline placement record persisted by `addon-pipeline-orchestrator` via
@@ -50763,6 +53121,13 @@ method(object({
50763
53121
  }), object({ success: literal(true) }), {
50764
53122
  kind: "mutation",
50765
53123
  auth: "admin"
53124
+ }), method(object({
53125
+ agentNodeId: string(),
53126
+ addonId: string(),
53127
+ settings: record(string(), unknown()).nullable()
53128
+ }), object({ success: literal(true) }), {
53129
+ kind: "mutation",
53130
+ auth: "admin"
50766
53131
  }), method(object({ nodeId: string() }), NodeInferenceDevicesSchema), method(object({
50767
53132
  agentNodeId: string(),
50768
53133
  deviceKey: string()
@@ -50772,9 +53137,7 @@ method(object({
50772
53137
  }), method(object({ agentNodeId: string() }), object({
50773
53138
  success: literal(true),
50774
53139
  /** Hardware-aware default detection model now in effect on the node (null when unresolvable). */
50775
- effectiveModelId: string().nullable(),
50776
- /** Number of cameras whose node-scoped overrides were cleared. */
50777
- clearedCameraOverrides: number()
53140
+ effectiveModelId: string().nullable()
50778
53141
  }), {
50779
53142
  kind: "mutation",
50780
53143
  auth: "admin"
@@ -50829,15 +53192,6 @@ method(object({
50829
53192
  }), object({ success: literal(true) }), {
50830
53193
  kind: "mutation",
50831
53194
  auth: "admin"
50832
- }), method(object({ deviceId: number() }), record(string(), record(string(), record(string(), CameraStepOverridePatchSchema))).nullable()), method(object({
50833
- deviceId: number(),
50834
- agentNodeId: string(),
50835
- deviceKey: string(),
50836
- addonId: string(),
50837
- patch: CameraStepOverridePatchSchema.nullable()
50838
- }), object({ success: literal(true) }), {
50839
- kind: "mutation",
50840
- auth: "admin"
50841
53195
  }), method(object({
50842
53196
  deviceId: number(),
50843
53197
  addonId: string(),
@@ -50845,13 +53199,6 @@ method(object({
50845
53199
  }), object({ success: literal(true) }), {
50846
53200
  kind: "mutation",
50847
53201
  auth: "admin"
50848
- }), method(object({
50849
- deviceId: number(),
50850
- agentNodeId: string(),
50851
- pipeline: CameraPipelineForAgentSchema.nullable()
50852
- }), object({ success: literal(true) }), {
50853
- kind: "mutation",
50854
- auth: "admin"
50855
53202
  }), method(object({
50856
53203
  deviceId: number(),
50857
53204
  agentNodeId: string().optional()
@@ -51979,7 +54326,7 @@ method(_void(), ProviderInfoSchema, { auth: "admin" }), method(object({ config:
51979
54326
  * The signals a device can emit to WAKE its own stream.
51980
54327
  *
51981
54328
  * A camera whose stream is built on demand sleeps until something asks for it,
51982
- * and "something" cannot be a consumer that is merely attached — a Frigate-style
54329
+ * and "something" cannot be a consumer that is merely attached — a external-catalog
51983
54330
  * puller holds a session open for ever, and treating that as demand would keep
51984
54331
  * a battery camera awake for ever, which is the whole thing the battery is for
51985
54332
  * (D173). So the wake has to come from the CAMERA: an event it noticed by
@@ -52738,7 +55085,7 @@ var ClipSchema = object({
52738
55085
  * {@link MAX_CLIP_EVENT_IDS}. Empty on footage-only clips.
52739
55086
  *
52740
55087
  * Bounded because it is not a payload the surface pages through: one visit on
52741
- * device 615 carried 2 345 ids, and `eventIds` was 99% of a 153 KB
55088
+ * device 101 carried 2 345 ids, and `eventIds` was 99% of a 153 KB
52742
55089
  * camera-day. Read {@link eventCount} for the true total.
52743
55090
  */
52744
55091
  eventIds: array(string()).optional(),
@@ -52883,7 +55230,7 @@ var ClipPlaybackSchema = object({
52883
55230
  * camera has no recordings", which is the defect this whole line of work is
52884
55231
  * about: a battery camera nobody woke (`sleeping`), a camera that could not be
52885
55232
  * reached at all (`unreachable`, also what a provider that THREW reports), a
52886
- * camera whose SD card is not mounted (`no-storage`, measured on 640 —
55233
+ * camera whose SD card is not mounted (`no-storage`, measured on 106 —
52887
55234
  * `HddInfo mount 0`, honestly nothing to list rather than "no clips"), and a
52888
55235
  * camera whose OWN index disagrees with its OWN calendar (`index-empty`,
52889
55236
  * measured on 618: the calendar marks 3–20 September, days 6–20 list zero
@@ -53344,7 +55691,7 @@ var videoclipsCapability = {
53344
55691
  *
53345
55692
  * It was optional, documented as "absent means the device's BOUND
53346
55693
  * provider, which is CamStack on every camera". No code implemented
53347
- * that. Measured on the live hub 2026-09-20 — device 592, bound to
55694
+ * that. Measured on the live hub 2026-09-20 — device 107, bound to
53348
55695
  * `recorder` AND `provider-reolink` — a bare call with `limit: 3`
53349
55696
  * answered SIX rows, three from each source, merged newest-first:
53350
55697
  * `device-collection-dispatch.ts` simply left the fan-out un-narrowed,
@@ -54661,7 +57008,10 @@ var airQualitySensorCapability = {
54661
57008
  */
54662
57009
  var AmbientLightSensorStatusSchema = object({
54663
57010
  /** Current illuminance in lux (lx). */
54664
- lux: number().min(0),
57011
+ lux: number().min(0).meta({
57012
+ unit: "lx",
57013
+ label: "Illuminance"
57014
+ }),
54665
57015
  /** Ms epoch when the slice was last updated. */
54666
57016
  lastFetchedAt: number(),
54667
57017
  /** Live display unit from the upstream source (e.g. HA
@@ -54704,7 +57054,12 @@ var ambientLightSensorCapability = {
54704
57054
  } } },
54705
57055
  /** Clock fields: written, but excluded from the compare that decides
54706
57056
  * whether persisting is worth a SQLite commit. */
54707
- volatileStateFields: ["lastFetchedAt"]
57057
+ volatileStateFields: ["lastFetchedAt"],
57058
+ customize: {
57059
+ version: 1,
57060
+ advanced: "derive",
57061
+ targets: []
57062
+ }
54708
57063
  };
54709
57064
  /**
54710
57065
  * Per-class audio metrics aggregated over a sliding window.
@@ -54931,7 +57286,10 @@ var BatteryStatusSchema = object({
54931
57286
  * Consumers must SKIP a null rather than coerce it — `battery-band` already
54932
57287
  * declines to band a non-finite reading, which is the correct shape.
54933
57288
  */
54934
- percentage: number().min(0).max(100).nullable(),
57289
+ percentage: number().min(0).max(100).nullable().meta({
57290
+ unit: "%",
57291
+ label: "Charge"
57292
+ }),
54935
57293
  /**
54936
57294
  * Charging source. `'dc'` covers wall/USB adapters; `'solar'` is
54937
57295
  * Reolink-specific for the Solar Panel 2 accessory (will become
@@ -54950,13 +57308,13 @@ var BatteryStatusSchema = object({
54950
57308
  "solar",
54951
57309
  "none",
54952
57310
  "unknown"
54953
- ]),
57311
+ ]).meta({ label: "Charging source" }),
54954
57312
  /**
54955
57313
  * True when the camera firmware has gone into low-power mode. Battery
54956
57314
  * providers MUST avoid polling during sleep — reading the battery
54957
57315
  * wakes the camera up and drains charge.
54958
57316
  */
54959
- sleeping: boolean(),
57317
+ sleeping: boolean().meta({ label: "Sleeping" }),
54960
57318
  /** Ms epoch of the last observation. Lets consumers reason about freshness. */
54961
57319
  lastUpdated: number(),
54962
57320
  /**
@@ -54996,22 +57354,71 @@ var BatteryStatusSchema = object({
54996
57354
  * sub-threshold = low). UI MUST render "Normal"/"Low" instead of a
54997
57355
  * misleading exact percentage. Absent/false → genuine 0–100 % reading.
54998
57356
  */
54999
- binary: boolean().optional()
57357
+ binary: boolean().optional().meta({ label: "Binary indicator" })
55000
57358
  });
57359
+ var BATTERY_DEVICE_TYPES = [
57360
+ DeviceType.Camera,
57361
+ DeviceType.Sensor,
57362
+ DeviceType.Button,
57363
+ DeviceType.Switch,
57364
+ DeviceType.PetFeeder,
57365
+ DeviceType.Container,
57366
+ DeviceType.Thermostat
57367
+ ];
57368
+ /** Generic Customize target for the percentage reading (D936). */
57369
+ var batteryCustomize = {
57370
+ version: 1,
57371
+ advanced: "derive",
57372
+ targets: [{
57373
+ id: "percentage",
57374
+ cardinality: "scalar",
57375
+ vocabulary: {
57376
+ cap: "battery",
57377
+ stateField: "percentage"
57378
+ },
57379
+ deviceTypes: BATTERY_DEVICE_TYPES,
57380
+ apply: "add-or-replace",
57381
+ path: "percentage",
57382
+ sources: [{
57383
+ kind: "field",
57384
+ valueKinds: ["number", "string"],
57385
+ transforms: [{ kind: "identity" }, {
57386
+ kind: "linear",
57387
+ defaultScale: 1,
57388
+ defaultOffset: 0,
57389
+ clampMin: 0,
57390
+ clampMax: 100
57391
+ }]
57392
+ }],
57393
+ companions: [
57394
+ {
57395
+ kind: "constant",
57396
+ path: "charging",
57397
+ value: "unknown",
57398
+ when: "add"
57399
+ },
57400
+ {
57401
+ kind: "constant",
57402
+ path: "sleeping",
57403
+ value: false,
57404
+ when: "add"
57405
+ },
57406
+ {
57407
+ kind: "clock",
57408
+ path: "lastUpdated",
57409
+ when: "add"
57410
+ }
57411
+ ],
57412
+ sourceReport: { status: "assignment-status" },
57413
+ advancedExpression: true
57414
+ }]
57415
+ };
55001
57416
  var batteryCapability = {
55002
57417
  name: "battery",
55003
57418
  scope: "device",
55004
57419
  deviceNative: true,
55005
57420
  mode: "singleton",
55006
- deviceTypes: [
55007
- DeviceType.Camera,
55008
- DeviceType.Sensor,
55009
- DeviceType.Button,
55010
- DeviceType.Switch,
55011
- DeviceType.PetFeeder,
55012
- DeviceType.Container,
55013
- DeviceType.Thermostat
55014
- ],
57421
+ deviceTypes: BATTERY_DEVICE_TYPES,
55015
57422
  methods: {
55016
57423
  /**
55017
57424
  * Explicitly wake the camera from low-power sleep ahead of a
@@ -55095,6 +57502,7 @@ onStatusChanged: { data: object({
55095
57502
  kind: "gauge",
55096
57503
  unit: "%"
55097
57504
  } } },
57505
+ customize: batteryCustomize,
55098
57506
  /** Clock fields: written, but excluded from the compare that decides
55099
57507
  * whether persisting is worth a SQLite commit. */
55100
57508
  volatileStateFields: ["lastUpdated"]
@@ -55111,7 +57519,7 @@ onStatusChanged: { data: object({
55111
57519
  * with the right HomeKit / Alexa display category.
55112
57520
  */
55113
57521
  var BinaryStatusSchema = object({
55114
- on: boolean(),
57522
+ on: boolean().meta({ label: "On" }),
55115
57523
  /** Ms epoch of the last transition. 0 if never observed. */
55116
57524
  lastChangedAt: number()
55117
57525
  });
@@ -55140,7 +57548,12 @@ var binaryCapability = {
55140
57548
  history: { fields: { on: { kind: "boolean" } } },
55141
57549
  /** Clock fields: written, but excluded from the compare that decides
55142
57550
  * whether persisting is worth a SQLite commit. */
55143
- volatileStateFields: ["lastChangedAt"]
57551
+ volatileStateFields: ["lastChangedAt"],
57552
+ customize: {
57553
+ version: 1,
57554
+ advanced: "derive",
57555
+ targets: []
57556
+ }
55144
57557
  };
55145
57558
  /**
55146
57559
  * Dimmable-light brightness control. Co-exists with `switch` on the
@@ -55446,7 +57859,7 @@ var GridLayoutCellSchema = object({
55446
57859
  *
55447
57860
  * A grid's `high` composes its sources' `high` and its `low` their `low`, so a
55448
57861
  * profile is on offer only when EVERY source can serve it. The refusal NAMES
55449
- * the sources, because "this grid has no low" is not a finding — "615 has no
57862
+ * the sources, because "this grid has no low" is not a finding — "101 has no
55450
57863
  * low" is, and it is the one an operator can act on.
55451
57864
  */
55452
57865
  var GridProfileOfferSchema = object({
@@ -56055,6 +58468,106 @@ var ConsumablesStatusSchema = object({
56055
58468
  items: array(ConsumableItemSchema),
56056
58469
  lastChangedAt: number()
56057
58470
  });
58471
+ /** Synthesize seed for a link-built status (no native provider).
58472
+ *
58473
+ * ⚠ NO LIVE CALLER since 2026-08-08 (device-links deleted; see
58474
+ * `CapabilityStatusSchema.empty`). The wiring guidance below was written for
58475
+ * exactly the case the operator is asking about again — a Dreame's HA
58476
+ * consumable-life sensors — so it is kept for that conversation, not because
58477
+ * anything reads it today. */
58478
+ var EMPTY_STATUS = {
58479
+ items: [],
58480
+ lastChangedAt: 0
58481
+ };
58482
+ /** Seed for a NEW link-built consumable item. `key`/`label` are overwritten
58483
+ * with the link's `itemKey` (see `status.itemArray`), so the placeholder
58484
+ * empty strings never survive into a validated item. Link-built items are
58485
+ * not resettable — there is no native provider to receive `reset()`.
58486
+ *
58487
+ * Wiring guidance (HA vacuum consumable-life sensors):
58488
+ * - a percent-remaining source (`numeric-sensor`, unit '%') → `level` via
58489
+ * `identity` (or `linear` scale 1 offset 0 clamp [0,100] to be safe);
58490
+ * - an hours-remaining source (e.g. Dreame 'Main Brush Time Left', unit 'h')
58491
+ * → `level` via `linear` with scale = 100 / max-hours for that item
58492
+ * (e.g. main brush 300 h → scale 0.3333) + clamp [0,100];
58493
+ * - a discrete source (`enum-sensor`, e.g. mop pad 'installed') → `status`
58494
+ * via `enum-map` (e.g. { installed: 'ok', missing: 'replace' }).
58495
+ * A numeric→'replace' THRESHOLD (level < 10 → 'replace') is NOT expressible
58496
+ * with the current transform kinds — leave `status` null (valid) until the
58497
+ * expression transform lands. */
58498
+ /** Generic Customize target for one consumable item (D936). Native rows stay read-only. */
58499
+ var consumablesCustomize = {
58500
+ version: 1,
58501
+ targets: [{
58502
+ id: "items",
58503
+ cardinality: "keyedArray",
58504
+ vocabulary: { cap: "consumables" },
58505
+ deviceTypes: Object.values(DeviceType),
58506
+ apply: "add",
58507
+ path: "items",
58508
+ keyField: "key",
58509
+ labelField: "label",
58510
+ itemSchema: ConsumableItemSchema,
58511
+ nativeItems: "read-only",
58512
+ sourceReport: { status: "assignment-status" },
58513
+ fields: [
58514
+ {
58515
+ path: "level",
58516
+ sources: [{
58517
+ kind: "numeric",
58518
+ transforms: [{ kind: "identity" }, {
58519
+ kind: "linear",
58520
+ defaultScale: 1,
58521
+ defaultOffset: 0,
58522
+ clampMin: 0,
58523
+ clampMax: 100
58524
+ }]
58525
+ }]
58526
+ },
58527
+ {
58528
+ path: "remaining.value",
58529
+ sources: [{
58530
+ kind: "numeric",
58531
+ transforms: [{ kind: "identity" }]
58532
+ }],
58533
+ literals: [{
58534
+ path: "remaining.unit",
58535
+ values: [...ConsumableRemainingUnitSchema.options]
58536
+ }]
58537
+ },
58538
+ {
58539
+ path: "status",
58540
+ sources: [{
58541
+ kind: "enum",
58542
+ transforms: [{
58543
+ kind: "enum-map",
58544
+ outputValues: [...ConsumableStatusSchema.options],
58545
+ unmapped: null
58546
+ }]
58547
+ }]
58548
+ }
58549
+ ],
58550
+ traits: [{
58551
+ path: "kind",
58552
+ values: [...ConsumableKindSchema.options],
58553
+ defaultValue: "wear"
58554
+ }, {
58555
+ path: "form",
58556
+ values: [...ConsumableFormSchema.options],
58557
+ defaultValue: "part"
58558
+ }],
58559
+ companions: [{
58560
+ kind: "clock",
58561
+ path: "lastChangedAt",
58562
+ when: "add"
58563
+ }, {
58564
+ kind: "clock",
58565
+ path: "lastFetchedAt",
58566
+ when: "add"
58567
+ }],
58568
+ advancedExpression: true
58569
+ }]
58570
+ };
56058
58571
  var consumablesCapability = {
56059
58572
  name: "consumables",
56060
58573
  scope: "device",
@@ -56092,10 +58605,7 @@ reset: method(object({
56092
58605
  status: {
56093
58606
  schema: ConsumablesStatusSchema,
56094
58607
  kind: "push",
56095
- empty: {
56096
- items: [],
56097
- lastChangedAt: 0
56098
- },
58608
+ empty: EMPTY_STATUS,
56099
58609
  itemArray: {
56100
58610
  path: "items",
56101
58611
  keyField: "key",
@@ -56131,6 +58641,7 @@ reset: method(object({
56131
58641
  * brush's remaining life and a dishwasher's salt are each recorded the moment
56132
58642
  * their provider reports them; an item that appears later gets its series.
56133
58643
  */
58644
+ customize: consumablesCustomize,
56134
58645
  history: {
56135
58646
  fields: {},
56136
58647
  items: {
@@ -56510,6 +59021,30 @@ var dayNightCapability = {
56510
59021
  volatileStateFields: ["lastFetchedAt"]
56511
59022
  };
56512
59023
  /**
59024
+ * display-palette — the cluster's one colour table (D939).
59025
+ *
59026
+ * Hub singleton. `getPalette` reports `unknown` when the settings store
59027
+ * cannot be read; it does not pretend the bundled preset was stored.
59028
+ * `setPalette` refuses a palette that fails the ΔE / contrast rule and names
59029
+ * the pairs.
59030
+ */
59031
+ var presetSummarySchema = object({
59032
+ id: string(),
59033
+ name: string(),
59034
+ swatches: record(string(), paletteSwatchSchema),
59035
+ fallbacks: array(string())
59036
+ });
59037
+ method(_void(), paletteResultSchema, {
59038
+ auth: "protected",
59039
+ role: "viewer"
59040
+ }), method(_void(), array(presetSummarySchema).readonly(), {
59041
+ auth: "protected",
59042
+ role: "viewer"
59043
+ }), method(setPaletteInputSchema, paletteReadySchema, {
59044
+ kind: "mutation",
59045
+ auth: "admin"
59046
+ });
59047
+ /**
56513
59048
  * Generic device-level status snapshot. Auto-registered by `BaseDevice`
56514
59049
  * for every device, regardless of provider — the kernel needs a uniform
56515
59050
  * cap-keyed slice for the basic device flags every consumer expects to
@@ -56873,6 +59408,36 @@ var dishwasherCapability = {
56873
59408
  powerOn: { kind: "boolean" }
56874
59409
  } }
56875
59410
  };
59411
+ /** Pulse override: a rising edge advances `lastPressedAt` and the press count. */
59412
+ var doorbellCustomize = {
59413
+ version: 1,
59414
+ targets: [{
59415
+ id: "pressed",
59416
+ cardinality: "event",
59417
+ shape: "pulse",
59418
+ vocabulary: {
59419
+ cap: "doorbell",
59420
+ eventName: "onPressed"
59421
+ },
59422
+ deviceTypes: [DeviceType.Camera],
59423
+ apply: "add",
59424
+ applyAuthority: { kind: "composition-claim" },
59425
+ eventName: "onPressed",
59426
+ edges: ["rising"],
59427
+ timestampPath: "lastPressedAt",
59428
+ counterPath: "pressCountSinceStart",
59429
+ highWater: "composer-advance",
59430
+ combine: "any",
59431
+ debounce: {
59432
+ kind: "rising-edge",
59433
+ defaultDebounceMs: 2e3,
59434
+ changedAtRequired: true
59435
+ },
59436
+ sources: [{ kind: "binary" }, { kind: "switch" }],
59437
+ sourceReport: { status: "assignment-status" },
59438
+ advancedExpression: true
59439
+ }]
59440
+ };
56876
59441
  var DoorbellStatusSchema = object({
56877
59442
  /** Ms epoch of the last press. null = never observed since this provider started. */
56878
59443
  lastPressedAt: number().nullable(),
@@ -56939,7 +59504,8 @@ onPressed: {
56939
59504
  /**
56940
59505
  * History (D850): none — `pressCountSinceStart` resets with the addon, so it is not a monotonic meter; presses live in the events ledger.
56941
59506
  */
56942
- history: "none"
59507
+ history: "none",
59508
+ customize: doorbellCustomize
56943
59509
  };
56944
59510
  /**
56945
59511
  * Enum-state sensor — a string value picked from a finite option set.
@@ -57811,7 +60377,10 @@ var humidifierCapability = {
57811
60377
  */
57812
60378
  var HumiditySensorStatusSchema = object({
57813
60379
  /** Current relative humidity, 0..100. */
57814
- percent: number().min(0).max(100),
60380
+ percent: number().min(0).max(100).meta({
60381
+ unit: "%",
60382
+ label: "Humidity"
60383
+ }),
57815
60384
  /** Ms epoch when the slice was last updated. */
57816
60385
  lastFetchedAt: number(),
57817
60386
  /** Live display unit from the upstream source (e.g. HA
@@ -57853,7 +60422,12 @@ var humiditySensorCapability = {
57853
60422
  } } },
57854
60423
  /** Clock fields: written, but excluded from the compare that decides
57855
60424
  * whether persisting is worth a SQLite commit. */
57856
- volatileStateFields: ["lastFetchedAt"]
60425
+ volatileStateFields: ["lastFetchedAt"],
60426
+ customize: {
60427
+ version: 1,
60428
+ advanced: "derive",
60429
+ targets: []
60430
+ }
57857
60431
  };
57858
60432
  /**
57859
60433
  * Image display cap. Models a single still image exposed by an integration —
@@ -59335,6 +61909,38 @@ authKey: string().optional() }), object({
59335
61909
  /** Human-readable error when `ok: false`. */
59336
61910
  error: string().optional()
59337
61911
  }), { kind: "mutation" });
61912
+ /** Span override: start on a rising edge, end on a fall or this timeout. */
61913
+ var motionCustomize = {
61914
+ version: 1,
61915
+ targets: [{
61916
+ id: "detected",
61917
+ cardinality: "event",
61918
+ shape: "span",
61919
+ vocabulary: {
61920
+ cap: "motion",
61921
+ eventName: "onMotionChanged"
61922
+ },
61923
+ deviceTypes: [DeviceType.Camera],
61924
+ apply: "replace",
61925
+ applyAuthority: {
61926
+ kind: "camera-sensors",
61927
+ timeoutField: "motionCooldownMs"
61928
+ },
61929
+ eventName: "onMotionChanged",
61930
+ start: "rising-edge",
61931
+ end: "falling-edge-or-timeout",
61932
+ timeoutMs: 3e4,
61933
+ combine: "any",
61934
+ sourceModes: [
61935
+ "in-addition",
61936
+ "confirm",
61937
+ "replace"
61938
+ ],
61939
+ sources: [{ kind: "binary" }, { kind: "switch" }],
61940
+ sourceReport: { status: "assignment-status" },
61941
+ advancedExpression: false
61942
+ }]
61943
+ };
59338
61944
  var MotionStatusSchema = object({
59339
61945
  detected: boolean(),
59340
61946
  /** Ms epoch of the last detected-true observation. Null if never detected. */
@@ -59474,7 +62080,8 @@ onMotionChanged: { data: MotionOnMotionChangedDataSchema } },
59474
62080
  history: { fields: { detected: {
59475
62081
  kind: "boolean",
59476
62082
  excludeDeviceTypes: [DeviceType.Camera]
59477
- } } }
62083
+ } } },
62084
+ customize: motionCustomize
59478
62085
  };
59479
62086
  /**
59480
62087
  * Motion-trigger toggle for accessory devices.
@@ -61273,6 +63880,30 @@ includeCrops: boolean().optional() }).optional(), array(VehicleSchema).readonly(
61273
63880
  kind: "mutation",
61274
63881
  auth: "admin"
61275
63882
  });
63883
+ var CORE_ULTRA_265K_IGPU_CLOCK_MHZ = 2e3;
63884
+ var positiveOrNull = number().nullable().transform((value) => value !== null && Number.isFinite(value) && value > 0 ? value : null);
63885
+ var textOrNull = string().nullable().transform((value) => value !== null && value.trim() !== "" ? value : null);
63886
+ var PrecisionGopsSchema = object({
63887
+ int8: positiveOrNull,
63888
+ fp16: positiveOrNull
63889
+ });
63890
+ /** What one accelerator device reported. Every failed query is null. */
63891
+ var AcceleratorComputeSchema = object({
63892
+ deviceKey: string(),
63893
+ fullDeviceName: textOrNull,
63894
+ executionUnits: positiveOrNull,
63895
+ clockMHz: positiveOrNull,
63896
+ gops: PrecisionGopsSchema.nullable(),
63897
+ architecture: textOrNull,
63898
+ npuName: textOrNull,
63899
+ tops: positiveOrNull,
63900
+ vendor: textOrNull,
63901
+ webgpuArchitecture: textOrNull,
63902
+ webgpuDevice: textOrNull,
63903
+ computeUnits: positiveOrNull
63904
+ });
63905
+ object({ accelerators: array(AcceleratorComputeSchema).nullable() });
63906
+ 64 * CORE_ULTRA_265K_IGPU_CLOCK_MHZ;
61276
63907
  var ModelFormatSchema = _enum(MODEL_FORMATS);
61277
63908
  var HwAccelBackendInputSchema = _enum([
61278
63909
  "videotoolbox",
@@ -61386,7 +64017,12 @@ var HardwareInfoSchema = object({
61386
64017
  availableRAM_MB: number(),
61387
64018
  gpu: GpuInfoSchema.nullable(),
61388
64019
  npu: NpuInfoSchema.nullable(),
61389
- coral: CoralInfoSchema.nullable().optional()
64020
+ coral: CoralInfoSchema.nullable().optional(),
64021
+ /**
64022
+ * Per-accelerator compute (D930). Omitted by a node that has not probed it.
64023
+ * `null` fields inside an entry are a failed query, never a zero.
64024
+ */
64025
+ accelerators: array(AcceleratorComputeSchema).readonly().optional()
61390
64026
  });
61391
64027
  var PlatformScoreSchema = object({
61392
64028
  runtime: literal("python"),
@@ -61470,9 +64106,15 @@ method(_void(), PlatformCapabilitiesSchema), method(_void(), HardwareInfoSchema)
61470
64106
  */
61471
64107
  var PowerMeterStatusSchema = object({
61472
64108
  /** Instantaneous power draw in watts. */
61473
- watts: number().optional(),
64109
+ watts: number().optional().meta({
64110
+ unit: "W",
64111
+ label: "Power"
64112
+ }),
61474
64113
  /** Cumulative energy in kilowatt-hours since the meter was reset. */
61475
- kwhTotal: number().optional(),
64114
+ kwhTotal: number().optional().meta({
64115
+ unit: "kWh",
64116
+ label: "Energy"
64117
+ }),
61476
64118
  /** Voltage in volts. */
61477
64119
  volts: number().optional(),
61478
64120
  /** Current in amperes. */
@@ -61557,7 +64199,12 @@ var powerMeterCapability = {
61557
64199
  } },
61558
64200
  /** Clock fields: written, but excluded from the compare that decides
61559
64201
  * whether persisting is worth a SQLite commit. */
61560
- volatileStateFields: ["lastFetchedAt"]
64202
+ volatileStateFields: ["lastFetchedAt"],
64203
+ customize: {
64204
+ version: 1,
64205
+ advanced: "derive",
64206
+ targets: []
64207
+ }
61561
64208
  };
61562
64209
  /**
61563
64210
  * Presence cap. Models HA `person.*` and `device_tracker.*` entities
@@ -62002,9 +64649,9 @@ var PtzOptionsSchema = object({
62002
64649
  * Reolink preset 0, Hikvision preset '1', Dahua preset 1 -- and on this fleet
62003
64650
  * not one of the three cameras honours its own:
62004
64651
  *
62005
- * 592 Videocamera camera Daniel (reolink) preset 0 holds "stanza"
62006
- * 1438 Videocamera dispensa (hikvision) preset 1 holds "Credenza"
62007
- * 3836 Videocamera studio (amcrest) preset 1 holds "Preset1"
64652
+ * 107 Camera camera Carol (reolink) preset 0 holds "stanza"
64653
+ * 1438 Camera dispensa (hikvision) preset 1 holds "Credenza"
64654
+ * 3836 Camera studio (amcrest) preset 1 holds "Preset1"
62008
64655
  *
62009
64656
  * So `goHome` meant "go wherever the operator happened to save in slot 0 or 1",
62010
64657
  * and two of the three swallowed the failure in a bare `catch`. For autotrack
@@ -62329,6 +64976,126 @@ var ptzAutotrackCapability = {
62329
64976
  */
62330
64977
  history: "none"
62331
64978
  };
64979
+ var RUNNING_POWER_START_DELAY_MS = 3e4;
64980
+ var RUNNING_POWER_STOP_DELAY_MS = 18e4;
64981
+ var RunningStateSourceSchema = _enum(["native", "assigned"]);
64982
+ var RunningStateStatusSchema = object({
64983
+ /** null = unknown — never coerced to false (D393). */
64984
+ running: boolean().nullable(),
64985
+ /** Epoch ms the current boolean began; null while `running` is null. */
64986
+ since: number().nullable(),
64987
+ source: RunningStateSourceSchema.meta({ label: "Source" }),
64988
+ phase: string().nullable(),
64989
+ /** null until a reading has been published (D393). */
64990
+ lastFetchedAt: number().nullable()
64991
+ });
64992
+ var RunningFlipEventDataSchema = object({
64993
+ deviceId: number(),
64994
+ since: number().nullable(),
64995
+ phase: string().nullable()
64996
+ });
64997
+ var RUNNING_DEVICE_TYPES = Object.values(DeviceType);
64998
+ /** Generic Customize target for the running boolean (D936). */
64999
+ var runningCustomize = {
65000
+ version: 1,
65001
+ advanced: "derive",
65002
+ targets: [{
65003
+ id: "running",
65004
+ cardinality: "scalar",
65005
+ vocabulary: {
65006
+ cap: "running-state",
65007
+ stateField: "running"
65008
+ },
65009
+ deviceTypes: [
65010
+ DeviceType.Dishwasher,
65011
+ DeviceType.Vacuum,
65012
+ DeviceType.LawnMower,
65013
+ DeviceType.MediaPlayer,
65014
+ DeviceType.WaterHeater,
65015
+ DeviceType.Humidifier,
65016
+ DeviceType.Fan,
65017
+ DeviceType.Climate,
65018
+ DeviceType.Thermostat,
65019
+ DeviceType.PetFeeder
65020
+ ],
65021
+ apply: "add-or-replace",
65022
+ path: "running",
65023
+ sources: [
65024
+ {
65025
+ kind: "switch",
65026
+ transforms: [{ kind: "identity" }]
65027
+ },
65028
+ {
65029
+ kind: "binary",
65030
+ transforms: [{ kind: "identity" }, { kind: "invert" }]
65031
+ },
65032
+ {
65033
+ kind: "numeric",
65034
+ requiredUnit: "W",
65035
+ transforms: [{
65036
+ kind: "threshold",
65037
+ comparison: "gte",
65038
+ defaultThreshold: 5,
65039
+ defaultStartDwellMs: RUNNING_POWER_START_DELAY_MS,
65040
+ defaultStopDwellMs: RUNNING_POWER_STOP_DELAY_MS,
65041
+ thresholdUnit: "W"
65042
+ }]
65043
+ }
65044
+ ],
65045
+ companions: [
65046
+ {
65047
+ kind: "constant",
65048
+ path: "source",
65049
+ value: "assigned",
65050
+ when: "always"
65051
+ },
65052
+ {
65053
+ kind: "constant",
65054
+ path: "phase",
65055
+ value: null,
65056
+ when: "always"
65057
+ },
65058
+ {
65059
+ kind: "clock",
65060
+ path: "lastFetchedAt",
65061
+ when: "always"
65062
+ },
65063
+ {
65064
+ kind: "transition-time",
65065
+ path: "since",
65066
+ sourceChangedAt: "prefer"
65067
+ }
65068
+ ],
65069
+ sourceReport: {
65070
+ status: "assignment-status",
65071
+ runtimeField: "source",
65072
+ nativeValue: "native",
65073
+ assignedValue: "assigned"
65074
+ },
65075
+ advancedExpression: true
65076
+ }]
65077
+ };
65078
+ var runningStateCapability = {
65079
+ name: "running-state",
65080
+ scope: "device",
65081
+ deviceNative: true,
65082
+ mode: "singleton",
65083
+ deviceTypes: RUNNING_DEVICE_TYPES,
65084
+ methods: {},
65085
+ events: {
65086
+ onStarted: { data: RunningFlipEventDataSchema },
65087
+ onFinished: { data: RunningFlipEventDataSchema }
65088
+ },
65089
+ status: {
65090
+ schema: RunningStateStatusSchema,
65091
+ kind: "push"
65092
+ },
65093
+ runtimeState: RunningStateStatusSchema,
65094
+ durability: "restored",
65095
+ history: { fields: { running: { kind: "boolean" } } },
65096
+ volatileStateFields: ["lastFetchedAt"],
65097
+ customize: runningCustomize
65098
+ };
62332
65099
  DeviceType.Camera, DeviceType.Sensor, DeviceType.Switch, method(object({ deviceId: number().int().nonnegative() }), object({ success: literal(true) }), {
62333
65100
  kind: "mutation",
62334
65101
  auth: "admin"
@@ -62370,7 +65137,7 @@ var RecordingAvailabilitySchema = object({
62370
65137
  * would look identical. But the answer used to say nothing about that, so a
62371
65138
  * caller asking "what can I export?" read the single preferred profile as
62372
65139
  * the only one that exists — on this deployment every camera records `high`
62373
- * AND `low`, the low tree holding 14 GB for camera 615 alone, and the export
65140
+ * AND `low`, the low tree holding 14 GB for camera 101 alone, and the export
62374
65141
  * UI could not see it.
62375
65142
  *
62376
65143
  * Cheap: it is the same shallow directory read the profile CHOICE already
@@ -62469,7 +65236,7 @@ var RecordingSourceOptionsSchema = object({
62469
65236
  * `sparse` = gaps are the absence of one, and must be drawn as such.
62470
65237
  *
62471
65238
  * Not an onboard-only concession: measured 2026-09-24, OUR bar covers 98.8 %
62472
- * of 592's day and 1.2 % of 1436's. It is a fact about a (source, camera)
65239
+ * of 107's day and 1.2 % of 1436's. It is a fact about a (source, camera)
62473
65240
  * pair, and ours answers it per camera from `deriveRecordingMode`. */
62474
65241
  coverage: _enum(["continuous", "sparse"]),
62475
65242
  /** Where the playhead may be put.
@@ -62545,7 +65312,7 @@ DeviceType.Camera, method(object({ deviceId: number() }), array(RecordingSourceS
62545
65312
  * merely discouraged (D554 amended).
62546
65313
  *
62547
65314
  * It was learned the expensive way on `videoclips.listClips`: measured
62548
- * on the live hub 2026-09-20, device 592 bound to `recorder` AND
65315
+ * on the live hub 2026-09-20, device 107 bound to `recorder` AND
62549
65316
  * `provider-reolink`, a bare call with `limit: 3` answered SIX rows,
62550
65317
  * three from each source, merged — `device-collection-dispatch.ts`
62551
65318
  * leaves an unpinned fan-out un-narrowed, so absence buys the union the
@@ -63146,7 +65913,7 @@ var ExportSpeedSchema = number().min(.25).max(32);
63146
65913
  * on a 10 h window holding 29,393 s of footage every range landed late by the
63147
65914
  * gap accumulated before it — up to 6,607 s, well past EOF. Nothing matched,
63148
65915
  * the video was a uniform timelapse, and the log line reported the five ranges
63149
- * that had been ASKED for (2026-08-13, export `57d14363`, camera 615).
65916
+ * that had been ASKED for (2026-08-13, export `57d14363`, camera 101).
63150
65917
  *
63151
65918
  * Relative and not absolute epoch, because an absolute epoch would make every
63152
65919
  * call site responsible for the same subtraction.
@@ -63963,7 +66730,7 @@ getStatus: method(object({ deviceId: number() }), RecordingSignalStatusSchema) }
63963
66730
  * which put a "Scenes" tab on one camera's detail page. That is the wrong shape
63964
66731
  * for the thing: a scene is a standing question about the property ("is the bin
63965
66732
  * still out"), and the operator's question is "which of my scenes have tripped",
63966
- * across every camera at once — not "what does camera 617 think". Buried one
66733
+ * across every camera at once — not "what does camera 102 think". Buried one
63967
66734
  * camera deep it also could not be found. The surface is now a top-level admin
63968
66735
  * page (`/scenes`, `pages/Scenes.tsx`) that lists every scene on every camera and
63969
66736
  * picks the camera inside the create flow, the same shape Events and Faces have.
@@ -64412,7 +67179,20 @@ var ZoneRuleSchema = object({
64412
67179
  * Defaults to `true` so operators creating a rule via the UI
64413
67180
  * see it active immediately.
64414
67181
  */
64415
- enabled: boolean().default(true)
67182
+ enabled: boolean().default(true),
67183
+ /**
67184
+ * Package stage only. When true, a package candidate may open from a
67185
+ * scene difference in this rule's zone after a person leaves. The
67186
+ * package model, when it boxes something overlapping, is extra evidence
67187
+ * and is not the gate. Absent or false keeps today's model path.
67188
+ */
67189
+ detectBySceneDifference: boolean().optional(),
67190
+ /**
67191
+ * Package stage only. When true, a promoted package is shown to the
67192
+ * `llm` cap before the delivery event is emitted. Absent or false emits
67193
+ * as today. Usable with or without `detectBySceneDifference`.
67194
+ */
67195
+ confirmWithLlm: boolean().optional()
64416
67196
  });
64417
67197
  array(ZoneRuleSchema).readonly();
64418
67198
  /**
@@ -65007,7 +67787,7 @@ function buildStreamParamsConfigSchema(options, status) {
65007
67787
  * `getSettingsUISchema()` surface.
65008
67788
  */
65009
67789
  var SwitchStatusSchema = object({
65010
- on: boolean(),
67790
+ on: boolean().meta({ label: "On" }),
65011
67791
  /** Ms epoch of the last state change. Useful for UI "X minutes ago". */
65012
67792
  lastChangedAt: number()
65013
67793
  });
@@ -65066,7 +67846,12 @@ var switchCapability = {
65066
67846
  label: "On",
65067
67847
  kind: "boolean"
65068
67848
  }
65069
- }] }
67849
+ }] },
67850
+ customize: {
67851
+ version: 1,
67852
+ advanced: "derive",
67853
+ targets: []
67854
+ }
65070
67855
  };
65071
67856
  /** C0 controls, DEL and the C1 range: none of them belongs in a name. */
65072
67857
  function hasControlCharacter(value) {
@@ -65662,7 +68447,10 @@ var tamperCapability = {
65662
68447
  */
65663
68448
  var TemperatureSensorStatusSchema = object({
65664
68449
  /** Current temperature in Celsius. */
65665
- celsius: number(),
68450
+ celsius: number().meta({
68451
+ unit: "°C",
68452
+ label: "Temperature"
68453
+ }),
65666
68454
  /** Ms epoch when the slice was last updated (push or poll). */
65667
68455
  lastFetchedAt: number(),
65668
68456
  /** Live display unit from the upstream source (e.g. HA
@@ -65705,7 +68493,12 @@ var temperatureSensorCapability = {
65705
68493
  } } },
65706
68494
  /** Clock fields: written, but excluded from the compare that decides
65707
68495
  * whether persisting is worth a SQLite commit. */
65708
- volatileStateFields: ["lastFetchedAt"]
68496
+ volatileStateFields: ["lastFetchedAt"],
68497
+ customize: {
68498
+ version: 1,
68499
+ advanced: "derive",
68500
+ targets: []
68501
+ }
65709
68502
  };
65710
68503
  /**
65711
68504
  * toast — system-scoped singleton capability that streams toast
@@ -66968,7 +69761,7 @@ method(object({}), array(TrainingProviderDescriptorSchema).readonly(), { auth: "
66968
69761
  * - **Jobs.** A persisted state machine, a reconcile loop against the
66969
69762
  * provider, a cost guard, a daily orphan sweep and the retention rules.
66970
69763
  * - **The return flow.** Verified artefacts → Model Studio
66971
- * (`custom-model-registry.importModelBundle`) → canary on cameras →
69764
+ * (`custom-model-registry.importModelBundle`) → canary on accelerators →
66972
69765
  * rollback. Nothing is ever registered automatically.
66973
69766
  *
66974
69767
  * Plan/start takes a live {@link TrainingCorpusSelection} (collections +
@@ -67105,20 +69898,24 @@ var TrainingProgressPointSchema = object({
67105
69898
  map50: number().nullable(),
67106
69899
  map50_95: number().nullable()
67107
69900
  });
69901
+ /** One accelerator: a `(node, inference device)` that runs the root detector. */
69902
+ var TrainingAcceleratorRefSchema = object({
69903
+ nodeId: string(),
69904
+ deviceKey: string()
69905
+ });
69906
+ /**
69907
+ * A canary pins the registered model on chosen ACCELERATORS — a model is
69908
+ * chosen by the accelerator that runs it (D927); every camera balanced onto
69909
+ * one runs it. `previous` is the root-detector pin each one had (`null` = it
69910
+ * ran its default), exactly, so rollback restores it.
69911
+ */
67108
69912
  var TrainingCanarySchema = object({
67109
- deviceIds: array(number().int()).readonly(),
69913
+ accelerators: array(TrainingAcceleratorRefSchema).readonly(),
67110
69914
  since: number(),
67111
- /** Every override the canary replaced, exactly, so rollback restores it. */
67112
- previous: array(object({
67113
- deviceId: number().int(),
67114
- nodeId: string(),
67115
- deviceKey: string(),
67116
- patch: object({
67117
- modelId: string().optional(),
67118
- settings: record(string(), unknown()).readonly().optional()
67119
- }).nullable()
67120
- })).readonly()
69915
+ previous: array(TrainingAcceleratorRefSchema.extend({ modelId: string().nullable() })).readonly()
67121
69916
  });
69917
+ /** An accelerator a canary may pin: it runs the root detector, on this model now. */
69918
+ var TrainingCanaryTargetSchema = TrainingAcceleratorRefSchema.extend({ pinnedModelId: string().nullable() });
67122
69919
  var TrainingJobSchema = object({
67123
69920
  id: string(),
67124
69921
  idempotencyKey: string(),
@@ -67230,11 +70027,11 @@ method(object({}), array(TrainingBaseModelSchema).readonly(), { auth: "admin" })
67230
70027
  kind: "mutation",
67231
70028
  auth: "admin",
67232
70029
  timeoutMs: 12e4
67233
- }), method(IdInput, TrainingResultSchema.nullable(), { auth: "admin" }), method(IdInput.extend({ canaryDeviceIds: array(number().int()).readonly() }), TrainingJobSchema, {
70030
+ }), method(IdInput, TrainingResultSchema.nullable(), { auth: "admin" }), method(_void(), array(TrainingCanaryTargetSchema).readonly(), { auth: "admin" }), method(IdInput.extend({ canaryAccelerators: array(TrainingAcceleratorRefSchema).readonly() }), TrainingJobSchema, {
67234
70031
  kind: "mutation",
67235
70032
  auth: "admin",
67236
70033
  timeoutMs: 30 * 6e4
67237
- }), method(IdInput.extend({ deviceIds: array(number().int()).min(1).readonly() }), TrainingJobSchema, {
70034
+ }), method(IdInput.extend({ accelerators: array(TrainingAcceleratorRefSchema).min(1).readonly() }), TrainingJobSchema, {
67238
70035
  kind: "mutation",
67239
70036
  auth: "admin",
67240
70037
  timeoutMs: 12e4
@@ -67380,6 +70177,10 @@ function withClipEventLabels(provider, deps) {
67380
70177
  };
67381
70178
  }
67382
70179
  SOURCE_CAPS.filter((cap) => cap !== "switch" && cap !== "motion");
70180
+ DeviceType.Camera, DeviceType.Sensor, DeviceType.Button, DeviceType.Switch, DeviceType.PetFeeder, DeviceType.Container, DeviceType.Thermostat, DeviceType.Camera, DeviceType.Hub, DeviceType.Light, DeviceType.Siren, DeviceType.Switch, DeviceType.Sensor, DeviceType.Thermostat, DeviceType.Climate, DeviceType.Button, DeviceType.EventEmitter, DeviceType.Update, DeviceType.Generic, DeviceType.Notifier, DeviceType.Script, DeviceType.Automation, DeviceType.Lock, DeviceType.Cover, DeviceType.Valve, DeviceType.Humidifier, DeviceType.WaterHeater, DeviceType.Fan, DeviceType.MediaPlayer, DeviceType.AlarmPanel, DeviceType.Control, DeviceType.Presence, DeviceType.Weather, DeviceType.Vacuum, DeviceType.LawnMower, DeviceType.Container, DeviceType.Image, DeviceType.PetFeeder, DeviceType.Dishwasher, DeviceType.Camera, DeviceType.Camera, DeviceType.Dishwasher, DeviceType.Vacuum, DeviceType.LawnMower, DeviceType.MediaPlayer, DeviceType.WaterHeater, DeviceType.Humidifier, DeviceType.Fan, DeviceType.Climate, DeviceType.Thermostat, DeviceType.PetFeeder;
70181
+ String.raw`rose\(active(\d+), changed(\d+), (\d+(?:\.\d+)?)\)`;
70182
+ DeviceRole.BinarySensor, DeviceRole.MotionSensor;
70183
+ new Set(CAP_NAMES);
67383
70184
  Object.freeze({
67384
70185
  person: .5,
67385
70186
  vehicle: .5,
@@ -67730,6 +70531,7 @@ var DEVICE_LOCAL_STATE_CAPS = {
67730
70531
  ptzAutotrack: ptzAutotrackCapability,
67731
70532
  recordingOnboard: recordingOnboardCapability,
67732
70533
  recordingSignal: recordingSignalCapability,
70534
+ runningState: runningStateCapability,
67733
70535
  sceneMonitor: sceneMonitorCapability,
67734
70536
  scriptRunner: scriptRunnerCapability,
67735
70537
  smoke: smokeCapability,
@@ -68612,7 +71414,7 @@ var BaseDeviceProvider = class extends BaseAddon {
68612
71414
  * A top-level persisted row with NO configuration is a leftover, not a
68613
71415
  * device — quarantine it instead of dialling it.
68614
71416
  *
68615
- * Device 614 was deleted, resurrected as a config-less shell by a write
71417
+ * Device 105 was deleted, resurrected as a config-less shell by a write
68616
71418
  * already in flight (D376), and then dialled at every single boot: eight
68617
71419
  * `Failed to restore device — bounded retry scheduled` lines in one day,
68618
71420
  * each one the same Zod refusal on `host` and `password`. The bound was
@@ -71926,6 +74728,27 @@ Object.freeze({
71926
74728
  access: "create",
71927
74729
  role: "viewer"
71928
74730
  },
74731
+ "displayPalette.getPalette": {
74732
+ capName: "display-palette",
74733
+ capScope: "system",
74734
+ addonId: null,
74735
+ access: "view",
74736
+ role: "viewer"
74737
+ },
74738
+ "displayPalette.listPresets": {
74739
+ capName: "display-palette",
74740
+ capScope: "system",
74741
+ addonId: null,
74742
+ access: "view",
74743
+ role: "viewer"
74744
+ },
74745
+ "displayPalette.setPalette": {
74746
+ capName: "display-palette",
74747
+ capScope: "system",
74748
+ addonId: null,
74749
+ access: "create",
74750
+ role: "admin"
74751
+ },
71929
74752
  "doorbell.getStatus": {
71930
74753
  capName: "doorbell",
71931
74754
  capScope: "device",
@@ -74845,20 +77668,6 @@ Object.freeze({
74845
77668
  access: "create",
74846
77669
  role: "admin"
74847
77670
  },
74848
- "pipelineExecutor.clearDeviceOverrides": {
74849
- capName: "pipeline-executor",
74850
- capScope: "system",
74851
- addonId: null,
74852
- access: "delete",
74853
- role: "admin"
74854
- },
74855
- "pipelineExecutor.clearModelBoundDeviceOverrides": {
74856
- capName: "pipeline-executor",
74857
- capScope: "system",
74858
- addonId: null,
74859
- access: "delete",
74860
- role: "admin"
74861
- },
74862
77671
  "pipelineExecutor.deleteModel": {
74863
77672
  capName: "pipeline-executor",
74864
77673
  capScope: "system",
@@ -74901,13 +77710,6 @@ Object.freeze({
74901
77710
  access: "view",
74902
77711
  role: "admin"
74903
77712
  },
74904
- "pipelineExecutor.getDefaultSteps": {
74905
- capName: "pipeline-executor",
74906
- capScope: "system",
74907
- addonId: null,
74908
- access: "view",
74909
- role: "admin"
74910
- },
74911
77713
  "pipelineExecutor.getDetectionConfigSchema": {
74912
77714
  capName: "pipeline-executor",
74913
77715
  capScope: "system",
@@ -74929,20 +77731,6 @@ Object.freeze({
74929
77731
  access: "view",
74930
77732
  role: "admin"
74931
77733
  },
74932
- "pipelineExecutor.getGlobalPipelineConfig": {
74933
- capName: "pipeline-executor",
74934
- capScope: "system",
74935
- addonId: null,
74936
- access: "view",
74937
- role: "admin"
74938
- },
74939
- "pipelineExecutor.getGlobalSteps": {
74940
- capName: "pipeline-executor",
74941
- capScope: "system",
74942
- addonId: null,
74943
- access: "view",
74944
- role: "admin"
74945
- },
74946
77734
  "pipelineExecutor.getInferenceDeviceHealth": {
74947
77735
  capName: "pipeline-executor",
74948
77736
  capScope: "system",
@@ -75202,13 +77990,6 @@ Object.freeze({
75202
77990
  access: "view",
75203
77991
  role: "admin"
75204
77992
  },
75205
- "pipelineOrchestrator.getCameraStepOverrides": {
75206
- capName: "pipeline-orchestrator",
75207
- capScope: "system",
75208
- addonId: null,
75209
- access: "view",
75210
- role: "admin"
75211
- },
75212
77993
  "pipelineOrchestrator.getCameraSwitches": {
75213
77994
  capName: "pipeline-orchestrator",
75214
77995
  capScope: "system",
@@ -75447,13 +78228,6 @@ Object.freeze({
75447
78228
  access: "create",
75448
78229
  role: "admin"
75449
78230
  },
75450
- "pipelineOrchestrator.setCameraPipelineForAgent": {
75451
- capName: "pipeline-orchestrator",
75452
- capScope: "system",
75453
- addonId: null,
75454
- access: "create",
75455
- role: "admin"
75456
- },
75457
78231
  "pipelineOrchestrator.setCameraSensors": {
75458
78232
  capName: "pipeline-orchestrator",
75459
78233
  capScope: "system",
@@ -75461,42 +78235,42 @@ Object.freeze({
75461
78235
  access: "create",
75462
78236
  role: "admin"
75463
78237
  },
75464
- "pipelineOrchestrator.setCameraStepOverride": {
78238
+ "pipelineOrchestrator.setCameraStepSettings": {
75465
78239
  capName: "pipeline-orchestrator",
75466
78240
  capScope: "system",
75467
78241
  addonId: null,
75468
78242
  access: "create",
75469
78243
  role: "admin"
75470
78244
  },
75471
- "pipelineOrchestrator.setCameraStepSettings": {
78245
+ "pipelineOrchestrator.setCameraStepToggle": {
75472
78246
  capName: "pipeline-orchestrator",
75473
78247
  capScope: "system",
75474
78248
  addonId: null,
75475
78249
  access: "create",
75476
78250
  role: "admin"
75477
78251
  },
75478
- "pipelineOrchestrator.setCameraStepToggle": {
78252
+ "pipelineOrchestrator.setCameraSwitch": {
75479
78253
  capName: "pipeline-orchestrator",
75480
78254
  capScope: "system",
75481
78255
  addonId: null,
75482
78256
  access: "create",
75483
78257
  role: "admin"
75484
78258
  },
75485
- "pipelineOrchestrator.setCameraSwitch": {
78259
+ "pipelineOrchestrator.setCapabilityBinding": {
75486
78260
  capName: "pipeline-orchestrator",
75487
78261
  capScope: "system",
75488
78262
  addonId: null,
75489
78263
  access: "create",
75490
78264
  role: "admin"
75491
78265
  },
75492
- "pipelineOrchestrator.setCapabilityBinding": {
78266
+ "pipelineOrchestrator.setLoadBalancingShares": {
75493
78267
  capName: "pipeline-orchestrator",
75494
78268
  capScope: "system",
75495
78269
  addonId: null,
75496
78270
  access: "create",
75497
78271
  role: "admin"
75498
78272
  },
75499
- "pipelineOrchestrator.setLoadBalancingShares": {
78273
+ "pipelineOrchestrator.setNodeStepSettings": {
75500
78274
  capName: "pipeline-orchestrator",
75501
78275
  capScope: "system",
75502
78276
  addonId: null,
@@ -76525,6 +79299,13 @@ Object.freeze({
76525
79299
  access: "create",
76526
79300
  role: "admin"
76527
79301
  },
79302
+ "runningState.getStatus": {
79303
+ capName: "running-state",
79304
+ capScope: "device",
79305
+ addonId: null,
79306
+ access: "view",
79307
+ role: "viewer"
79308
+ },
76528
79309
  "sceneMonitor.captureReference": {
76529
79310
  capName: "scene-monitor",
76530
79311
  capScope: "device",
@@ -77855,6 +80636,13 @@ Object.freeze({
77855
80636
  access: "view",
77856
80637
  role: "admin"
77857
80638
  },
80639
+ "training.listCanaryTargets": {
80640
+ capName: "training",
80641
+ capScope: "system",
80642
+ addonId: null,
80643
+ access: "view",
80644
+ role: "admin"
80645
+ },
77858
80646
  "training.listJobs": {
77859
80647
  capName: "training",
77860
80648
  capScope: "system",
@@ -81232,6 +84020,32 @@ var APPLIANCE_CAP_VOCABULARY = {
81232
84020
  }],
81233
84021
  events: { onSent: { notOperatorFacing: "a delivery receipt of a send this system made — not a fact about the world" } }
81234
84022
  },
84023
+ "running-state": {
84024
+ scope: "device",
84025
+ noun: t("Running", "In funzione"),
84026
+ state: [{
84027
+ kind: "boolean",
84028
+ field: "running",
84029
+ label: t("Running", "In funzione"),
84030
+ whenTrue: t("When {device} starts", "Quando {device} inizia"),
84031
+ whenFalse: t("When {device} finishes", "Quando {device} finisce"),
84032
+ icon: "play"
84033
+ }],
84034
+ events: {
84035
+ onStarted: {
84036
+ category: EventCategory.RunningStarted,
84037
+ label: t("Started running", "Ha iniziato a funzionare"),
84038
+ phrase: t("When {device} starts running", "Quando {device} inizia a funzionare"),
84039
+ icon: "play"
84040
+ },
84041
+ onFinished: {
84042
+ category: EventCategory.RunningFinished,
84043
+ label: t("Finished", "Ha finito"),
84044
+ phrase: t("When {device} finishes", "Quando {device} finisce"),
84045
+ icon: "square"
84046
+ }
84047
+ }
84048
+ },
81235
84049
  update: {
81236
84050
  scope: "device",
81237
84051
  noun: t("Firmware update", "Aggiornamento firmware"),
@@ -81852,7 +84666,7 @@ var SENSOR_CAP_VOCABULARY = {
81852
84666
  state: [{
81853
84667
  kind: "boolean",
81854
84668
  field: "on",
81855
- label: t("Active", "Attivo"),
84669
+ label: t("On", "Acceso"),
81856
84670
  whenTrue: t("When {device} turns active", "Quando {device} si attiva"),
81857
84671
  whenFalse: t("When {device} turns inactive", "Quando {device} si disattiva"),
81858
84672
  icon: "toggle-right"
@@ -82391,6 +85205,7 @@ var SYSTEM_CAP_VOCABULARY = {
82391
85205
  "device-provider": system(INTERNAL),
82392
85206
  "device-removal-hook": system(INTERNAL),
82393
85207
  "device-state": system("the runtime-state mirror every trigger already reads through"),
85208
+ "display-palette": system("the cluster display palette — one colour table for every client, not a device action"),
82394
85209
  "embedding-encoder": system(ML),
82395
85210
  "face-gallery": system("the face gallery — curated on its own page"),
82396
85211
  "failure-contribution": system(INTERNAL),
@@ -84447,11 +87262,6 @@ Object.freeze({
84447
87262
  form: "single",
84448
87263
  optional: false
84449
87264
  }],
84450
- "pipelineExecutor.clearModelBoundDeviceOverrides": [{
84451
- name: "deviceIds",
84452
- form: "array",
84453
- optional: true
84454
- }],
84455
87265
  "pipelineExecutor.runPipeline": [{
84456
87266
  name: "deviceId",
84457
87267
  form: "single",
@@ -84507,11 +87317,6 @@ Object.freeze({
84507
87317
  form: "array",
84508
87318
  optional: true
84509
87319
  }],
84510
- "pipelineOrchestrator.getCameraStepOverrides": [{
84511
- name: "deviceId",
84512
- form: "single",
84513
- optional: false
84514
- }],
84515
87320
  "pipelineOrchestrator.getCameraSwitches": [{
84516
87321
  name: "deviceId",
84517
87322
  form: "single",
@@ -84552,21 +87357,11 @@ Object.freeze({
84552
87357
  form: "single",
84553
87358
  optional: false
84554
87359
  }],
84555
- "pipelineOrchestrator.setCameraPipelineForAgent": [{
84556
- name: "deviceId",
84557
- form: "single",
84558
- optional: false
84559
- }],
84560
87360
  "pipelineOrchestrator.setCameraSensors": [{
84561
87361
  name: "deviceId",
84562
87362
  form: "single",
84563
87363
  optional: false
84564
87364
  }],
84565
- "pipelineOrchestrator.setCameraStepOverride": [{
84566
- name: "deviceId",
84567
- form: "single",
84568
- optional: false
84569
- }],
84570
87365
  "pipelineOrchestrator.setCameraStepSettings": [{
84571
87366
  name: "deviceId",
84572
87367
  form: "single",
@@ -84998,6 +87793,11 @@ Object.freeze({
84998
87793
  form: "single",
84999
87794
  optional: true
85000
87795
  }],
87796
+ "runningState.getStatus": [{
87797
+ name: "deviceId",
87798
+ form: "single",
87799
+ optional: false
87800
+ }],
85001
87801
  "sceneMonitor.captureReference": [{
85002
87802
  name: "deviceId",
85003
87803
  form: "single",
@@ -85244,11 +88044,6 @@ Object.freeze({
85244
88044
  form: "single",
85245
88045
  optional: false
85246
88046
  }],
85247
- "training.canaryResult": [{
85248
- name: "deviceIds",
85249
- form: "array",
85250
- optional: false
85251
- }],
85252
88047
  "update.getStatus": [{
85253
88048
  name: "deviceId",
85254
88049
  form: "single",
@@ -85501,6 +88296,94 @@ Object.freeze({
85501
88296
  "smtp-provider": "email"
85502
88297
  });
85503
88298
  DeviceType.Camera;
88299
+ /**
88300
+ * A saved Customize assignment (D936). The schema is the type: callers use
88301
+ * `z.infer`, they do not restate the shape.
88302
+ */
88303
+ var OverrideSourceSchema = object({
88304
+ addonId: string().min(1),
88305
+ stableId: string().min(1),
88306
+ cap: string().min(1),
88307
+ fieldPath: string().min(1)
88308
+ });
88309
+ var CustomizeTransformDraftSchema = discriminatedUnion("kind", [
88310
+ object({ kind: literal("identity") }),
88311
+ object({ kind: literal("invert") }),
88312
+ object({
88313
+ kind: literal("threshold"),
88314
+ comparison: _enum(["gte", "lte"]),
88315
+ threshold: number(),
88316
+ startDwellMs: number().nonnegative(),
88317
+ stopDwellMs: number().nonnegative()
88318
+ }),
88319
+ object({
88320
+ kind: literal("linear"),
88321
+ scale: number(),
88322
+ offset: number(),
88323
+ clampMin: number().optional(),
88324
+ clampMax: number().optional()
88325
+ }),
88326
+ object({
88327
+ kind: literal("enum-map"),
88328
+ mapping: record(string(), string().nullable())
88329
+ }),
88330
+ object({ kind: literal("number") })
88331
+ ]);
88332
+ var ScalarOverrideDraftSchema = object({
88333
+ kind: literal("scalar"),
88334
+ cap: string().min(1),
88335
+ targetId: string().min(1),
88336
+ source: OverrideSourceSchema,
88337
+ transform: CustomizeTransformDraftSchema
88338
+ });
88339
+ var KeyedArrayOverrideDraftSchema = object({
88340
+ kind: literal("keyedArray"),
88341
+ cap: string().min(1),
88342
+ targetId: string().min(1),
88343
+ key: string().min(1),
88344
+ label: string().min(1),
88345
+ fieldPath: string().min(1),
88346
+ source: OverrideSourceSchema,
88347
+ transform: CustomizeTransformDraftSchema
88348
+ });
88349
+ var PulseOverrideDraftSchema = object({
88350
+ kind: literal("pulse"),
88351
+ cap: string().min(1),
88352
+ targetId: string().min(1),
88353
+ enabled: boolean(),
88354
+ debounceMs: number().nonnegative(),
88355
+ sources: array(OverrideSourceSchema).min(1)
88356
+ });
88357
+ var SpanSourceDraftSchema = OverrideSourceSchema.extend({ mode: _enum([
88358
+ "in-addition",
88359
+ "confirm",
88360
+ "replace"
88361
+ ]).optional() });
88362
+ discriminatedUnion("kind", [
88363
+ ScalarOverrideDraftSchema,
88364
+ KeyedArrayOverrideDraftSchema,
88365
+ PulseOverrideDraftSchema,
88366
+ object({
88367
+ kind: literal("span"),
88368
+ cap: string().min(1),
88369
+ targetId: string().min(1),
88370
+ timeoutMs: number().nonnegative(),
88371
+ cooldownMs: number().nonnegative().optional(),
88372
+ sources: array(SpanSourceDraftSchema)
88373
+ })
88374
+ ]);
88375
+ object({
88376
+ targetId: string().min(1),
88377
+ configured: boolean(),
88378
+ source: _enum(["native", "assigned"]),
88379
+ state: _enum([
88380
+ "active",
88381
+ "stale",
88382
+ "released",
88383
+ "unavailable"
88384
+ ]),
88385
+ reason: string().nullable()
88386
+ });
85504
88387
  var G711_SCALE_CORRECTION_DB = {
85505
88388
  PCMU: 20 * Math.log10(4),
85506
88389
  PCMA: 20 * Math.log10(8)
@@ -85553,40 +88436,7 @@ var NC_AUDIO_DEFAULTS = {
85553
88436
  samplingSeconds: 10
85554
88437
  };
85555
88438
  new Set(["devices", "classes"]);
85556
- /**
85557
- * WHICH narrowing filter speaks about WHICH system-event kind — one predicate,
85558
- * consumed by the rule ENGINE and by every rule EDITOR.
85559
- *
85560
- * ── The failure this file exists for ───────────────────────────────────────
85561
- * `NcSystemEventConditionSchema` carries four optional narrowing lists
85562
- * (`deviceIds`, `deviceTypes`, `nodeIds`, `packageNames`) beside a required
85563
- * `kinds` gate. They are not four filters over one vocabulary: each belongs to
85564
- * a FAMILY of kinds and is meaningless outside it. A node going away has no
85565
- * device type; a completed export has no package; `stream-offline` deliberately
85566
- * carries no device type at all (a stream belongs to a camera by construction).
85567
- *
85568
- * The engine applied all four to every kind, so a filter from one family failed
85569
- * a kind from another family CLOSED. The operator's live rule "Eventi di
85570
- * sistema" selected eleven kinds and set `deviceTypes: ['camera']` — the only
85571
- * way to say "only my cameras" about the two liveness kinds — and NINE of the
85572
- * eleven silently stopped being deliverable. Four days of history contained
85573
- * `device-online` and `device-offline` and nothing else, across a window in
85574
- * which agents were restarted and addons were updated.
85575
- *
85576
- * Both editors already computed this scoping, to decide which filter boxes to
85577
- * render; the cap's own docblock already promised it ("Narrow a `device-*` kind
85578
- * to these device TYPES"). Only the engine disagreed, and it disagreed in the
85579
- * destructive direction. So the rule is stated ONCE, here, and the engine and
85580
- * the editors are readers of it rather than three independent authors.
85581
- *
85582
- * ── The direction ─────────────────────────────────────────────────────────
85583
- * Out of family ⇒ the filter is IGNORED, never fail-closed. An editor that
85584
- * hides a box has already told the operator this filter does not speak about
85585
- * these kinds, so honouring it as an exclusion contradicts the only
85586
- * explanation the operator was ever given. Inside its family the filter still
85587
- * narrows, and still fails CLOSED on a subject that cannot produce the identity
85588
- * it tests (a device the mirror cannot name is not evidence of a camera).
85589
- */
88439
+ new Set(NC_LEGACY_SYSTEM_EVENT_KINDS);
85590
88440
  /**
85591
88441
  * Every filter, for the callers that must cover all of them (guards, tests).
85592
88442
  *
@@ -85612,9 +88462,6 @@ new Map(Object.entries({
85612
88462
  "device-battery-normal": "device-events",
85613
88463
  "device-consumable-low": "device-events",
85614
88464
  "device-consumable-normal": "device-events",
85615
- "device-tank-low": "device-events",
85616
- "device-tank-full": "device-events",
85617
- "device-tank-normal": "device-events",
85618
88465
  "stream-online": "device-events",
85619
88466
  "stream-offline": "device-events",
85620
88467
  "detection-blind": "device-events",
@@ -85691,16 +88538,6 @@ var NC_SYSTEM_EVENT_KIND_GROUP_SPECS = [
85691
88538
  label: "Consumables",
85692
88539
  kinds: ["device-consumable-low", "device-consumable-normal"]
85693
88540
  },
85694
- {
85695
- id: "tanks",
85696
- family: "device-events",
85697
- label: "Tanks",
85698
- kinds: [
85699
- "device-tank-low",
85700
- "device-tank-full",
85701
- "device-tank-normal"
85702
- ]
85703
- },
85704
88541
  {
85705
88542
  id: "detection-blind",
85706
88543
  family: "device-events",
@@ -85858,11 +88695,6 @@ var RULE_BODY_ONLY = ["body"];
85858
88695
  var RULE_TEXT = ["title", "body"];
85859
88696
  var BATTERY = ["device-battery-low", "device-battery-normal"];
85860
88697
  var CONSUMABLE = ["device-consumable-low", "device-consumable-normal"];
85861
- var TANK = [
85862
- "device-tank-low",
85863
- "device-tank-full",
85864
- "device-tank-normal"
85865
- ];
85866
88698
  var ALERT_EPISODE = [
85867
88699
  "alert-critical",
85868
88700
  "alert-error",
@@ -85894,7 +88726,6 @@ var DEVICE_EVENTS = [
85894
88726
  "device-enabled",
85895
88727
  ...BATTERY,
85896
88728
  ...CONSUMABLE,
85897
- ...TANK,
85898
88729
  "stream-online",
85899
88730
  "stream-offline",
85900
88731
  "detection-blind",
@@ -85925,7 +88756,7 @@ var STATE_SUMMARY_SECTION_VARS = [
85925
88756
  {
85926
88757
  name: "summaryStreams",
85927
88758
  label: "Summary: streams offline",
85928
- example: "Ingresso (high) — since 06:40",
88759
+ example: "Front door (high) — since 06:40",
85929
88760
  kinds: ["stream-offline", "stream-online"]
85930
88761
  },
85931
88762
  {
@@ -85940,22 +88771,16 @@ var STATE_SUMMARY_SECTION_VARS = [
85940
88771
  example: "Robot — filter 10 %",
85941
88772
  kinds: CONSUMABLE
85942
88773
  },
85943
- {
85944
- name: "summaryTanks",
85945
- label: "Summary: tanks",
85946
- example: "Robot — clean water low",
85947
- kinds: TANK
85948
- },
85949
88774
  {
85950
88775
  name: "summaryDetection",
85951
88776
  label: "Summary: cameras detecting nothing",
85952
- example: "Ingresso — since 05:10",
88777
+ example: "Front door — since 05:10",
85953
88778
  kinds: ["detection-blind"]
85954
88779
  },
85955
88780
  {
85956
88781
  name: "summaryNodes",
85957
88782
  label: "Summary: nodes",
85958
- example: "little-unraid — offline since 03:00",
88783
+ example: "agent-a — offline since 03:00",
85959
88784
  kinds: [
85960
88785
  "node-offline",
85961
88786
  "node-online",
@@ -86061,8 +88886,7 @@ var STATE_SUMMARY_VARS = [
86061
88886
  ([...RULE_TEXT], [...COMBINED_ALARM]),
86062
88887
  ([...RULE_TEXT], [...DEVICE_EVENTS]),
86063
88888
  ([...RULE_TEXT], [...BATTERY, ...CONSUMABLE]),
86064
- ([...RULE_TEXT], [...CONSUMABLE, ...TANK]),
86065
- ([...RULE_TEXT], [...TANK]),
88889
+ ([...RULE_TEXT], [...CONSUMABLE]),
86066
88890
  [...RULE_TEXT],
86067
88891
  ([...RULE_TEXT], [...UPDATES, ...ALERT_EPISODE]),
86068
88892
  ([...RULE_TEXT], [...UPDATES, ...ALERT_EPISODE]),
@@ -86166,15 +88990,6 @@ new Map([
86166
88990
  snapshotLabel: "Consumables low now",
86167
88991
  snapshotSection: "consumables"
86168
88992
  },
86169
- {
86170
- id: "tanks",
86171
- family: "device-events",
86172
- label: "Tanks (low or full / back to normal)",
86173
- bad: ["device-tank-low", "device-tank-full"],
86174
- recovery: ["device-tank-normal"],
86175
- snapshotLabel: "Tanks low or full now",
86176
- snapshotSection: "tanks"
86177
- },
86178
88993
  {
86179
88994
  id: "motion-noise",
86180
88995
  family: "device-events",
@@ -86627,6 +89442,10 @@ MotionOnMotionChangedDataSchema.omit({ triggeredBy: true });
86627
89442
  function providerMotionEvent(source, data) {
86628
89443
  return createEvent(EventCategory.ProviderMotion, source, data);
86629
89444
  }
89445
+ Object.freeze({
89446
+ person: .8,
89447
+ vehicle: .8
89448
+ });
86630
89449
  object({
86631
89450
  /**
86632
89451
  * Fraction of the box's own size added on EACH side before cutting.
@@ -88766,7 +91585,7 @@ var amcrestCameraSchema = object({
88766
91585
  *
88767
91586
  * Empty = nothing configured, and `goHome` then REFUSES. It used to go to a
88768
91587
  * hardcoded slot on a vendor "convention" this fleet contradicts: reolink
88769
- * went to preset 0, which on device 592 holds "stanza"; amcrest went to
91588
+ * went to preset 0, which on device 107 holds "stanza"; amcrest went to
88770
91589
  * preset 1, which on device 3836 holds "Preset1". Both swallowed the failure
88771
91590
  * in a bare catch, so a head that never moved was indistinguishable from a
88772
91591
  * head that went home.