@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.js CHANGED
@@ -35,7 +35,7 @@ let node_stream_promises = require("node:stream/promises");
35
35
  let node_child_process = require("node:child_process");
36
36
  require("node:zlib");
37
37
  let node_os = require("node:os");
38
- //#region ../types/dist/event-category-BfJwUd2S.mjs
38
+ //#region ../types/dist/event-category-DHXxB8t9.mjs
39
39
  var EventCategory = /* @__PURE__ */ function(EventCategory) {
40
40
  EventCategory["SystemBoot"] = "system.boot";
41
41
  EventCategory["SystemAddonsReady"] = "system.addons-ready";
@@ -331,7 +331,7 @@ var EventCategory = /* @__PURE__ */ function(EventCategory) {
331
331
  * TRANSITION into that state (never per dispatch), and the node is dropped
332
332
  * from the placement candidate set for as long as it holds.
333
333
  *
334
- * This exists because the state was previously invisible: little-unraid
334
+ * This exists because the state was previously invisible: agent-a
335
335
  * absorbed 283k inference errors in a day while still being handed cameras,
336
336
  * and nothing in the system said so.
337
337
  *
@@ -362,9 +362,8 @@ var EventCategory = /* @__PURE__ */ function(EventCategory) {
362
362
  EventCategory["PipelineMotionCalm"] = "pipeline.motion-calm";
363
363
  /**
364
364
  * Per-camera pipeline config was mutated by the orchestrator
365
- * (3-level settings change via `setAgentAddonDefaults` /
366
- * `setCameraStepToggle` / `setCameraPipelineForAgent` or a
367
- * pipeline-scoped `applyDeviceSettingsPatch`). Orchestrator
365
+ * (a settings change via `setAgentInferenceDevices` /
366
+ * `setCameraStepToggle` / `setCameraStepSettings`). Orchestrator
368
367
  * subscribes to its own emission to hot-reload the assigned runner
369
368
  * via `attachCamera` so the next frame executes against the new
370
369
  * engine/steps without waiting for a rebalance or the next
@@ -508,6 +507,10 @@ var EventCategory = /* @__PURE__ */ function(EventCategory) {
508
507
  * on the device detail page.
509
508
  */
510
509
  EventCategory["DoorbellOnPressed"] = "doorbell.onPressed";
510
+ /** Mirrors `runningStateCapability.events.onStarted`. */
511
+ EventCategory["RunningStarted"] = "running.started";
512
+ /** Mirrors `runningStateCapability.events.onFinished`. */
513
+ EventCategory["RunningFinished"] = "running.finished";
511
514
  /**
512
515
  * Cap event fired by every device that registers the `event-emitter`
513
516
  * capability. Mirrors `eventEmitterCapability.events.onEvent`. Carries
@@ -5467,7 +5470,7 @@ var ZodIssueCode = {
5467
5470
  var ZodFirstPartyTypeKind;
5468
5471
  ZodFirstPartyTypeKind || (ZodFirstPartyTypeKind = {});
5469
5472
  //#endregion
5470
- //#region ../types/dist/sleep-6AqUnQIT.mjs
5473
+ //#region ../types/dist/sleep-BErAxhul.mjs
5471
5474
  /**
5472
5475
  * The audio chunk plane's byte format, and the ONE expansion from a coded
5473
5476
  * window to float samples (D455).
@@ -5806,7 +5809,7 @@ Object.fromEntries([
5806
5809
  * `hydrateSchema` to skip the `value` injection for structural-only fields.
5807
5810
  */
5808
5811
  function isValuelessField(field) {
5809
- 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";
5812
+ 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";
5810
5813
  }
5811
5814
  function hydrateSchema(schema, values, options = {}) {
5812
5815
  return {
@@ -8490,6 +8493,1980 @@ method(object({ deviceId: number() }), array(StreamSourceEntrySchema)), method(o
8490
8493
  kind: "mutation",
8491
8494
  auth: "admin"
8492
8495
  }), method(object({ deviceId: number() }), unknown().nullable()), method(object({ deviceId: number() }), RawStateResultSchema.nullable(), { auth: "protected" });
8496
+ Object.freeze({ "doorbell": "lastPressedAt" });
8497
+ /** Every capability name, so addon code can check a name without the schema graph. */
8498
+ var CAP_NAMES = Object.freeze([
8499
+ "accessories",
8500
+ "addon-pages",
8501
+ "addon-pages-source",
8502
+ "addon-routes",
8503
+ "addon-settings",
8504
+ "addon-widgets",
8505
+ "addon-widgets-source",
8506
+ "addons",
8507
+ "admin-ui",
8508
+ "air-quality-sensor",
8509
+ "alarm-panel",
8510
+ "alerts",
8511
+ "ambient-light-sensor",
8512
+ "audio-analysis",
8513
+ "audio-analyzer",
8514
+ "audio-codec",
8515
+ "audio-metrics",
8516
+ "auth-provider",
8517
+ "automation-control",
8518
+ "backup",
8519
+ "battery",
8520
+ "binary",
8521
+ "brightness",
8522
+ "broker",
8523
+ "button",
8524
+ "calendar-source",
8525
+ "calendars",
8526
+ "camera-credentials",
8527
+ "camera-grid-layout",
8528
+ "camera-pipeline-config",
8529
+ "camera-streams",
8530
+ "carbon-monoxide",
8531
+ "climate-control",
8532
+ "color",
8533
+ "composer",
8534
+ "connection-test",
8535
+ "connectivity",
8536
+ "consumables",
8537
+ "contact",
8538
+ "control",
8539
+ "core-blocks",
8540
+ "cover",
8541
+ "custom-model-registry",
8542
+ "data-store-provider",
8543
+ "database-snapshot",
8544
+ "day-night",
8545
+ "decoder",
8546
+ "detection-pipeline",
8547
+ "device-admin-link",
8548
+ "device-adoption",
8549
+ "device-credentials",
8550
+ "device-discovery",
8551
+ "device-export",
8552
+ "device-extension",
8553
+ "device-history",
8554
+ "device-manager",
8555
+ "device-ops",
8556
+ "device-provider",
8557
+ "device-removal-hook",
8558
+ "device-state",
8559
+ "device-status",
8560
+ "dishwasher",
8561
+ "display-palette",
8562
+ "doorbell",
8563
+ "embedding-encoder",
8564
+ "enum-sensor",
8565
+ "event-emitter",
8566
+ "face-gallery",
8567
+ "failure-contribution",
8568
+ "fan-control",
8569
+ "feature-probe",
8570
+ "filesystem-browse",
8571
+ "flood",
8572
+ "gas",
8573
+ "heating-valve",
8574
+ "humidifier",
8575
+ "humidity-sensor",
8576
+ "image",
8577
+ "image-settings",
8578
+ "integrations",
8579
+ "intercom",
8580
+ "keychain",
8581
+ "keychain-admin",
8582
+ "lawn-mower-control",
8583
+ "llm",
8584
+ "llm-runtime",
8585
+ "load-contribution",
8586
+ "local-network",
8587
+ "lock-control",
8588
+ "log-channels",
8589
+ "log-destination",
8590
+ "login-method",
8591
+ "media-player",
8592
+ "mesh-network",
8593
+ "metrics-provider",
8594
+ "model-convert",
8595
+ "model-distributor",
8596
+ "motion",
8597
+ "motion-detection",
8598
+ "motion-trigger",
8599
+ "motion-zones",
8600
+ "mqtt-broker",
8601
+ "native-object-detection",
8602
+ "navigation",
8603
+ "network-access",
8604
+ "network-link",
8605
+ "network-quality",
8606
+ "node-certificates",
8607
+ "nodes",
8608
+ "notification-output",
8609
+ "notification-rules",
8610
+ "notifier",
8611
+ "numeric-sensor",
8612
+ "oauth-integration",
8613
+ "oidc-connections",
8614
+ "osd",
8615
+ "osd-manager",
8616
+ "pet-feeder",
8617
+ "pipeline-analytics",
8618
+ "pipeline-executor",
8619
+ "pipeline-orchestrator",
8620
+ "pipeline-runner",
8621
+ "plate-gallery",
8622
+ "platform-probe",
8623
+ "power-meter",
8624
+ "presence",
8625
+ "pressure-sensor",
8626
+ "privacy-mask",
8627
+ "ptz",
8628
+ "ptz-autotrack",
8629
+ "reboot",
8630
+ "record-entries",
8631
+ "recording",
8632
+ "recording-archive",
8633
+ "recording-export",
8634
+ "recording-onboard",
8635
+ "recording-signal",
8636
+ "records",
8637
+ "running-state",
8638
+ "scene-monitor",
8639
+ "script-runner",
8640
+ "server-management",
8641
+ "settings-store",
8642
+ "smoke",
8643
+ "smtp-provider",
8644
+ "snapshot",
8645
+ "sso-bridge",
8646
+ "storage",
8647
+ "storage-admin",
8648
+ "storage-evictable",
8649
+ "storage-migration",
8650
+ "storage-occupancy",
8651
+ "storage-provider",
8652
+ "stream-broker",
8653
+ "stream-catalog",
8654
+ "stream-params",
8655
+ "stream-signals",
8656
+ "switch",
8657
+ "system",
8658
+ "tamper",
8659
+ "temperature-sensor",
8660
+ "terminal-session",
8661
+ "toast",
8662
+ "training",
8663
+ "training-provider",
8664
+ "turn-provider",
8665
+ "update",
8666
+ "user-management",
8667
+ "user-passkeys",
8668
+ "vacuum-control",
8669
+ "valve",
8670
+ "vector-store",
8671
+ "vibration",
8672
+ "videoclips",
8673
+ "viewer-ui",
8674
+ "water-heater",
8675
+ "weather",
8676
+ "webrtc-session",
8677
+ "zone-analytics",
8678
+ "zone-rules",
8679
+ "zones"
8680
+ ]);
8681
+ Object.freeze({
8682
+ "air-quality-sensor": [
8683
+ {
8684
+ "path": "co2Ppm",
8685
+ "valueType": "number"
8686
+ },
8687
+ {
8688
+ "path": "vocPpb",
8689
+ "valueType": "number"
8690
+ },
8691
+ {
8692
+ "path": "pm25",
8693
+ "valueType": "number"
8694
+ },
8695
+ {
8696
+ "path": "pm10",
8697
+ "valueType": "number"
8698
+ },
8699
+ {
8700
+ "path": "aqi",
8701
+ "valueType": "number"
8702
+ },
8703
+ {
8704
+ "path": "unit",
8705
+ "valueType": "string"
8706
+ },
8707
+ {
8708
+ "path": "precision",
8709
+ "valueType": "number"
8710
+ }
8711
+ ],
8712
+ "alarm-panel": [
8713
+ {
8714
+ "path": "state",
8715
+ "valueType": "enum",
8716
+ "enumValues": [
8717
+ "disarmed",
8718
+ "armed_home",
8719
+ "armed_away",
8720
+ "armed_night",
8721
+ "armed_vacation",
8722
+ "armed_custom_bypass",
8723
+ "arming",
8724
+ "disarming",
8725
+ "pending",
8726
+ "triggered"
8727
+ ]
8728
+ },
8729
+ {
8730
+ "path": "targetMode",
8731
+ "valueType": "enum",
8732
+ "enumValues": [
8733
+ "home",
8734
+ "away",
8735
+ "night",
8736
+ "vacation",
8737
+ "custom_bypass"
8738
+ ]
8739
+ },
8740
+ {
8741
+ "path": "requiresCode",
8742
+ "valueType": "boolean"
8743
+ }
8744
+ ],
8745
+ "ambient-light-sensor": [
8746
+ {
8747
+ "path": "lux",
8748
+ "valueType": "number"
8749
+ },
8750
+ {
8751
+ "path": "unit",
8752
+ "valueType": "string"
8753
+ },
8754
+ {
8755
+ "path": "precision",
8756
+ "valueType": "number"
8757
+ }
8758
+ ],
8759
+ "audio-metrics": [
8760
+ {
8761
+ "path": "ts",
8762
+ "valueType": "number"
8763
+ },
8764
+ {
8765
+ "path": "windowSec",
8766
+ "valueType": "number"
8767
+ },
8768
+ {
8769
+ "path": "level.rms",
8770
+ "valueType": "number"
8771
+ },
8772
+ {
8773
+ "path": "level.dbfs",
8774
+ "valueType": "number"
8775
+ },
8776
+ {
8777
+ "path": "peakDbfs",
8778
+ "valueType": "number"
8779
+ },
8780
+ {
8781
+ "path": "avgDbfs",
8782
+ "valueType": "number"
8783
+ },
8784
+ {
8785
+ "path": "current.className",
8786
+ "valueType": "string"
8787
+ },
8788
+ {
8789
+ "path": "current.score",
8790
+ "valueType": "number"
8791
+ },
8792
+ {
8793
+ "path": "current.timestamp",
8794
+ "valueType": "number"
8795
+ }
8796
+ ],
8797
+ "automation-control": [
8798
+ {
8799
+ "path": "enabled",
8800
+ "valueType": "boolean"
8801
+ },
8802
+ {
8803
+ "path": "isRunning",
8804
+ "valueType": "boolean"
8805
+ },
8806
+ {
8807
+ "path": "lastTriggeredAt",
8808
+ "valueType": "number"
8809
+ },
8810
+ {
8811
+ "path": "lastError",
8812
+ "valueType": "string"
8813
+ }
8814
+ ],
8815
+ "battery": [
8816
+ {
8817
+ "path": "percentage",
8818
+ "valueType": "number"
8819
+ },
8820
+ {
8821
+ "path": "charging",
8822
+ "valueType": "enum",
8823
+ "enumValues": [
8824
+ "dc",
8825
+ "solar",
8826
+ "none",
8827
+ "unknown"
8828
+ ]
8829
+ },
8830
+ {
8831
+ "path": "sleeping",
8832
+ "valueType": "boolean"
8833
+ },
8834
+ {
8835
+ "path": "lastUpdated",
8836
+ "valueType": "number"
8837
+ },
8838
+ {
8839
+ "path": "lastContactAt",
8840
+ "valueType": "number"
8841
+ },
8842
+ {
8843
+ "path": "lastFullRefreshAt",
8844
+ "valueType": "number"
8845
+ },
8846
+ {
8847
+ "path": "binary",
8848
+ "valueType": "boolean"
8849
+ }
8850
+ ],
8851
+ "binary": [{
8852
+ "path": "on",
8853
+ "valueType": "boolean"
8854
+ }],
8855
+ "brightness": [{
8856
+ "path": "percentage",
8857
+ "valueType": "number"
8858
+ }],
8859
+ "broker": [{
8860
+ "path": "brokerCount",
8861
+ "valueType": "number"
8862
+ }, {
8863
+ "path": "connectedCount",
8864
+ "valueType": "number"
8865
+ }],
8866
+ "camera-credentials": [
8867
+ {
8868
+ "path": "host",
8869
+ "valueType": "string"
8870
+ },
8871
+ {
8872
+ "path": "port",
8873
+ "valueType": "number"
8874
+ },
8875
+ {
8876
+ "path": "onvifPort",
8877
+ "valueType": "number"
8878
+ },
8879
+ {
8880
+ "path": "rtspPort",
8881
+ "valueType": "number"
8882
+ },
8883
+ {
8884
+ "path": "https",
8885
+ "valueType": "boolean"
8886
+ },
8887
+ {
8888
+ "path": "hasUsername",
8889
+ "valueType": "boolean"
8890
+ },
8891
+ {
8892
+ "path": "hasPassword",
8893
+ "valueType": "boolean"
8894
+ },
8895
+ {
8896
+ "path": "onvifProfile",
8897
+ "valueType": "string"
8898
+ }
8899
+ ],
8900
+ "camera-streams": [
8901
+ {
8902
+ "path": "online",
8903
+ "valueType": "boolean"
8904
+ },
8905
+ {
8906
+ "path": "slotStatuses.high",
8907
+ "valueType": "enum",
8908
+ "enumValues": [
8909
+ "unassigned",
8910
+ "idle",
8911
+ "connecting",
8912
+ "streaming",
8913
+ "error"
8914
+ ]
8915
+ },
8916
+ {
8917
+ "path": "slotStatuses.mid",
8918
+ "valueType": "enum",
8919
+ "enumValues": [
8920
+ "unassigned",
8921
+ "idle",
8922
+ "connecting",
8923
+ "streaming",
8924
+ "error"
8925
+ ]
8926
+ },
8927
+ {
8928
+ "path": "slotStatuses.low",
8929
+ "valueType": "enum",
8930
+ "enumValues": [
8931
+ "unassigned",
8932
+ "idle",
8933
+ "connecting",
8934
+ "streaming",
8935
+ "error"
8936
+ ]
8937
+ },
8938
+ {
8939
+ "path": "slotErrors.high",
8940
+ "valueType": "string"
8941
+ },
8942
+ {
8943
+ "path": "slotErrors.mid",
8944
+ "valueType": "string"
8945
+ },
8946
+ {
8947
+ "path": "slotErrors.low",
8948
+ "valueType": "string"
8949
+ }
8950
+ ],
8951
+ "carbon-monoxide": [{
8952
+ "path": "detected",
8953
+ "valueType": "boolean"
8954
+ }],
8955
+ "climate-control": [
8956
+ {
8957
+ "path": "mode",
8958
+ "valueType": "enum",
8959
+ "enumValues": [
8960
+ "off",
8961
+ "heat",
8962
+ "cool",
8963
+ "auto",
8964
+ "heat_cool",
8965
+ "fan_only",
8966
+ "dry"
8967
+ ]
8968
+ },
8969
+ {
8970
+ "path": "fanMode",
8971
+ "valueType": "string"
8972
+ },
8973
+ {
8974
+ "path": "preset",
8975
+ "valueType": "string"
8976
+ },
8977
+ {
8978
+ "path": "target",
8979
+ "valueType": "number"
8980
+ },
8981
+ {
8982
+ "path": "targetHigh",
8983
+ "valueType": "number"
8984
+ },
8985
+ {
8986
+ "path": "targetLow",
8987
+ "valueType": "number"
8988
+ },
8989
+ {
8990
+ "path": "targetHumidity",
8991
+ "valueType": "number"
8992
+ },
8993
+ {
8994
+ "path": "currentTemp",
8995
+ "valueType": "number"
8996
+ },
8997
+ {
8998
+ "path": "currentHumidity",
8999
+ "valueType": "number"
9000
+ },
9001
+ {
9002
+ "path": "swingVertical",
9003
+ "valueType": "boolean"
9004
+ },
9005
+ {
9006
+ "path": "swingHorizontal",
9007
+ "valueType": "boolean"
9008
+ },
9009
+ {
9010
+ "path": "minTemp",
9011
+ "valueType": "number"
9012
+ },
9013
+ {
9014
+ "path": "maxTemp",
9015
+ "valueType": "number"
9016
+ },
9017
+ {
9018
+ "path": "tempStep",
9019
+ "valueType": "number"
9020
+ }
9021
+ ],
9022
+ "color": [
9023
+ {
9024
+ "path": "mode",
9025
+ "valueType": "enum",
9026
+ "enumValues": [
9027
+ "rgb",
9028
+ "hsv",
9029
+ "mired"
9030
+ ]
9031
+ },
9032
+ {
9033
+ "path": "rgb.r",
9034
+ "valueType": "number"
9035
+ },
9036
+ {
9037
+ "path": "rgb.g",
9038
+ "valueType": "number"
9039
+ },
9040
+ {
9041
+ "path": "rgb.b",
9042
+ "valueType": "number"
9043
+ },
9044
+ {
9045
+ "path": "hsv.h",
9046
+ "valueType": "number"
9047
+ },
9048
+ {
9049
+ "path": "hsv.s",
9050
+ "valueType": "number"
9051
+ },
9052
+ {
9053
+ "path": "hsv.v",
9054
+ "valueType": "number"
9055
+ },
9056
+ {
9057
+ "path": "mireds",
9058
+ "valueType": "number"
9059
+ }
9060
+ ],
9061
+ "connectivity": [{
9062
+ "path": "connected",
9063
+ "valueType": "boolean"
9064
+ }],
9065
+ "contact": [{
9066
+ "path": "entryOpen",
9067
+ "valueType": "boolean"
9068
+ }],
9069
+ "control": [
9070
+ {
9071
+ "path": "kind",
9072
+ "valueType": "enum",
9073
+ "enumValues": [
9074
+ "numeric",
9075
+ "select",
9076
+ "text",
9077
+ "datetime"
9078
+ ]
9079
+ },
9080
+ {
9081
+ "path": "unit",
9082
+ "valueType": "string"
9083
+ },
9084
+ {
9085
+ "path": "min",
9086
+ "valueType": "number"
9087
+ },
9088
+ {
9089
+ "path": "max",
9090
+ "valueType": "number"
9091
+ },
9092
+ {
9093
+ "path": "step",
9094
+ "valueType": "number"
9095
+ },
9096
+ {
9097
+ "path": "precision",
9098
+ "valueType": "number"
9099
+ },
9100
+ {
9101
+ "path": "format",
9102
+ "valueType": "enum",
9103
+ "enumValues": [
9104
+ "date",
9105
+ "time",
9106
+ "datetime"
9107
+ ]
9108
+ }
9109
+ ],
9110
+ "cover": [
9111
+ {
9112
+ "path": "state",
9113
+ "valueType": "enum",
9114
+ "enumValues": [
9115
+ "open",
9116
+ "opening",
9117
+ "closing",
9118
+ "closed",
9119
+ "stopped"
9120
+ ]
9121
+ },
9122
+ {
9123
+ "path": "position",
9124
+ "valueType": "number"
9125
+ },
9126
+ {
9127
+ "path": "tiltPosition",
9128
+ "valueType": "number"
9129
+ }
9130
+ ],
9131
+ "day-night": [
9132
+ {
9133
+ "path": "mode",
9134
+ "valueType": "enum",
9135
+ "enumValues": [
9136
+ "auto",
9137
+ "day",
9138
+ "night",
9139
+ "schedule"
9140
+ ]
9141
+ },
9142
+ {
9143
+ "path": "sensitivity",
9144
+ "valueType": "number"
9145
+ },
9146
+ {
9147
+ "path": "switchDelaySec",
9148
+ "valueType": "number"
9149
+ }
9150
+ ],
9151
+ "device-adoption": [
9152
+ {
9153
+ "path": "lastDiscoveryAt",
9154
+ "valueType": "number"
9155
+ },
9156
+ {
9157
+ "path": "candidateCount",
9158
+ "valueType": "number"
9159
+ },
9160
+ {
9161
+ "path": "adoptedCount",
9162
+ "valueType": "number"
9163
+ },
9164
+ {
9165
+ "path": "lastError",
9166
+ "valueType": "string"
9167
+ }
9168
+ ],
9169
+ "device-discovery": [{
9170
+ "path": "lastDiscoveryAt",
9171
+ "valueType": "number"
9172
+ }, {
9173
+ "path": "lastError",
9174
+ "valueType": "string"
9175
+ }],
9176
+ "device-export": [
9177
+ {
9178
+ "path": "linkState",
9179
+ "valueType": "enum",
9180
+ "enumValues": [
9181
+ "unlinked",
9182
+ "linked",
9183
+ "error"
9184
+ ]
9185
+ },
9186
+ {
9187
+ "path": "exposedDeviceCount",
9188
+ "valueType": "number"
9189
+ },
9190
+ {
9191
+ "path": "error",
9192
+ "valueType": "string"
9193
+ },
9194
+ {
9195
+ "path": "setup.qr",
9196
+ "valueType": "string"
9197
+ },
9198
+ {
9199
+ "path": "setup.note",
9200
+ "valueType": "string"
9201
+ }
9202
+ ],
9203
+ "device-status": [{
9204
+ "path": "online",
9205
+ "valueType": "boolean"
9206
+ }],
9207
+ "dishwasher": [
9208
+ {
9209
+ "path": "availability",
9210
+ "valueType": "enum",
9211
+ "enumValues": [
9212
+ "available",
9213
+ "offline",
9214
+ "description-missing"
9215
+ ]
9216
+ },
9217
+ {
9218
+ "path": "state",
9219
+ "valueType": "enum",
9220
+ "enumValues": [
9221
+ "idle",
9222
+ "running",
9223
+ "paused",
9224
+ "finished",
9225
+ "error",
9226
+ "unavailable"
9227
+ ]
9228
+ },
9229
+ {
9230
+ "path": "operationState",
9231
+ "valueType": "enum",
9232
+ "enumValues": [
9233
+ "Inactive",
9234
+ "Ready",
9235
+ "DelayedStart",
9236
+ "Run",
9237
+ "Pause",
9238
+ "ActionRequired",
9239
+ "Finished",
9240
+ "Error",
9241
+ "Aborting"
9242
+ ]
9243
+ },
9244
+ {
9245
+ "path": "program",
9246
+ "valueType": "string"
9247
+ },
9248
+ {
9249
+ "path": "selectedProgram",
9250
+ "valueType": "string"
9251
+ },
9252
+ {
9253
+ "path": "remainingSeconds",
9254
+ "valueType": "number"
9255
+ },
9256
+ {
9257
+ "path": "delayedStartSeconds",
9258
+ "valueType": "number"
9259
+ },
9260
+ {
9261
+ "path": "progressPercent",
9262
+ "valueType": "number"
9263
+ },
9264
+ {
9265
+ "path": "doorOpen",
9266
+ "valueType": "boolean"
9267
+ },
9268
+ {
9269
+ "path": "doorLocked",
9270
+ "valueType": "boolean"
9271
+ },
9272
+ {
9273
+ "path": "remoteStartAllowed",
9274
+ "valueType": "boolean"
9275
+ },
9276
+ {
9277
+ "path": "remoteControlActive",
9278
+ "valueType": "boolean"
9279
+ },
9280
+ {
9281
+ "path": "localControlActive",
9282
+ "valueType": "boolean"
9283
+ },
9284
+ {
9285
+ "path": "powerOn",
9286
+ "valueType": "boolean"
9287
+ },
9288
+ {
9289
+ "path": "powerState",
9290
+ "valueType": "string"
9291
+ },
9292
+ {
9293
+ "path": "filterCleaningDue",
9294
+ "valueType": "boolean"
9295
+ },
9296
+ {
9297
+ "path": "machineCareDue",
9298
+ "valueType": "boolean"
9299
+ },
9300
+ {
9301
+ "path": "machineCareRemainingRuns",
9302
+ "valueType": "number"
9303
+ },
9304
+ {
9305
+ "path": "halfLoad",
9306
+ "valueType": "boolean"
9307
+ },
9308
+ {
9309
+ "path": "hygienePlus",
9310
+ "valueType": "boolean"
9311
+ },
9312
+ {
9313
+ "path": "extraDry",
9314
+ "valueType": "boolean"
9315
+ },
9316
+ {
9317
+ "path": "intensiveZone",
9318
+ "valueType": "boolean"
9319
+ },
9320
+ {
9321
+ "path": "varioSpeedPlus",
9322
+ "valueType": "boolean"
9323
+ },
9324
+ {
9325
+ "path": "childLock",
9326
+ "valueType": "boolean"
9327
+ },
9328
+ {
9329
+ "path": "errorCode",
9330
+ "valueType": "number"
9331
+ },
9332
+ {
9333
+ "path": "errorLabel",
9334
+ "valueType": "string"
9335
+ }
9336
+ ],
9337
+ "doorbell": [{
9338
+ "path": "lastPressedAt",
9339
+ "valueType": "number"
9340
+ }, {
9341
+ "path": "pressCountSinceStart",
9342
+ "valueType": "number"
9343
+ }],
9344
+ "enum-sensor": [{
9345
+ "path": "value",
9346
+ "valueType": "string"
9347
+ }, {
9348
+ "path": "format",
9349
+ "valueType": "enum",
9350
+ "enumValues": [
9351
+ "date",
9352
+ "time",
9353
+ "datetime"
9354
+ ]
9355
+ }],
9356
+ "event-emitter": [
9357
+ {
9358
+ "path": "lastEvent.deviceId",
9359
+ "valueType": "number"
9360
+ },
9361
+ {
9362
+ "path": "lastEvent.eventType",
9363
+ "valueType": "string"
9364
+ },
9365
+ {
9366
+ "path": "lastEvent.timestamp",
9367
+ "valueType": "number"
9368
+ },
9369
+ {
9370
+ "path": "lastEvent.seq",
9371
+ "valueType": "number"
9372
+ },
9373
+ {
9374
+ "path": "eventCountSinceStart",
9375
+ "valueType": "number"
9376
+ }
9377
+ ],
9378
+ "fan-control": [
9379
+ {
9380
+ "path": "percentage",
9381
+ "valueType": "number"
9382
+ },
9383
+ {
9384
+ "path": "percentageStep",
9385
+ "valueType": "number"
9386
+ },
9387
+ {
9388
+ "path": "preset",
9389
+ "valueType": "string"
9390
+ },
9391
+ {
9392
+ "path": "direction",
9393
+ "valueType": "enum",
9394
+ "enumValues": ["forward", "reverse"]
9395
+ },
9396
+ {
9397
+ "path": "oscillating",
9398
+ "valueType": "boolean"
9399
+ }
9400
+ ],
9401
+ "feature-probe": [
9402
+ {
9403
+ "path": "deviceType",
9404
+ "valueType": "string"
9405
+ },
9406
+ {
9407
+ "path": "model",
9408
+ "valueType": "string"
9409
+ },
9410
+ {
9411
+ "path": "channelCount",
9412
+ "valueType": "number"
9413
+ },
9414
+ {
9415
+ "path": "lastProbedAt",
9416
+ "valueType": "number"
9417
+ }
9418
+ ],
9419
+ "flood": [{
9420
+ "path": "flooded",
9421
+ "valueType": "boolean"
9422
+ }],
9423
+ "gas": [{
9424
+ "path": "detected",
9425
+ "valueType": "boolean"
9426
+ }],
9427
+ "heating-valve": [{
9428
+ "path": "position",
9429
+ "valueType": "number"
9430
+ }],
9431
+ "humidifier": [
9432
+ {
9433
+ "path": "on",
9434
+ "valueType": "boolean"
9435
+ },
9436
+ {
9437
+ "path": "currentHumidity",
9438
+ "valueType": "number"
9439
+ },
9440
+ {
9441
+ "path": "targetHumidity",
9442
+ "valueType": "number"
9443
+ },
9444
+ {
9445
+ "path": "mode",
9446
+ "valueType": "string"
9447
+ },
9448
+ {
9449
+ "path": "action",
9450
+ "valueType": "string"
9451
+ },
9452
+ {
9453
+ "path": "minHumidity",
9454
+ "valueType": "number"
9455
+ },
9456
+ {
9457
+ "path": "maxHumidity",
9458
+ "valueType": "number"
9459
+ }
9460
+ ],
9461
+ "humidity-sensor": [
9462
+ {
9463
+ "path": "percent",
9464
+ "valueType": "number"
9465
+ },
9466
+ {
9467
+ "path": "unit",
9468
+ "valueType": "string"
9469
+ },
9470
+ {
9471
+ "path": "precision",
9472
+ "valueType": "number"
9473
+ }
9474
+ ],
9475
+ "image": [{
9476
+ "path": "url",
9477
+ "valueType": "string"
9478
+ }, {
9479
+ "path": "lastUpdated",
9480
+ "valueType": "number"
9481
+ }],
9482
+ "image-settings": [
9483
+ {
9484
+ "path": "brightness",
9485
+ "valueType": "number"
9486
+ },
9487
+ {
9488
+ "path": "contrast",
9489
+ "valueType": "number"
9490
+ },
9491
+ {
9492
+ "path": "saturation",
9493
+ "valueType": "number"
9494
+ },
9495
+ {
9496
+ "path": "sharpness",
9497
+ "valueType": "number"
9498
+ },
9499
+ {
9500
+ "path": "mirror",
9501
+ "valueType": "boolean"
9502
+ },
9503
+ {
9504
+ "path": "flip",
9505
+ "valueType": "boolean"
9506
+ },
9507
+ {
9508
+ "path": "rotate",
9509
+ "valueType": "enum",
9510
+ "enumValues": [
9511
+ "0",
9512
+ "90",
9513
+ "180",
9514
+ "270"
9515
+ ]
9516
+ },
9517
+ {
9518
+ "path": "whiteBalance",
9519
+ "valueType": "enum",
9520
+ "enumValues": ["auto", "manual"]
9521
+ },
9522
+ {
9523
+ "path": "warmth",
9524
+ "valueType": "number"
9525
+ },
9526
+ {
9527
+ "path": "exposureMode",
9528
+ "valueType": "enum",
9529
+ "enumValues": ["auto", "manual"]
9530
+ },
9531
+ {
9532
+ "path": "backlightMode",
9533
+ "valueType": "enum",
9534
+ "enumValues": [
9535
+ "off",
9536
+ "blc",
9537
+ "wdr",
9538
+ "hlc"
9539
+ ]
9540
+ }
9541
+ ],
9542
+ "intercom": [
9543
+ {
9544
+ "path": "talking",
9545
+ "valueType": "boolean"
9546
+ },
9547
+ {
9548
+ "path": "lastSessionAt",
9549
+ "valueType": "number"
9550
+ },
9551
+ {
9552
+ "path": "ability.sampleRate",
9553
+ "valueType": "number"
9554
+ },
9555
+ {
9556
+ "path": "ability.duplex",
9557
+ "valueType": "enum",
9558
+ "enumValues": ["half", "full"]
9559
+ },
9560
+ {
9561
+ "path": "ability.maxBacklogMs",
9562
+ "valueType": "number"
9563
+ }
9564
+ ],
9565
+ "lawn-mower-control": [
9566
+ {
9567
+ "path": "activity",
9568
+ "valueType": "enum",
9569
+ "enumValues": [
9570
+ "idle",
9571
+ "mowing",
9572
+ "paused",
9573
+ "docked",
9574
+ "error"
9575
+ ]
9576
+ },
9577
+ {
9578
+ "path": "batteryLevel",
9579
+ "valueType": "number"
9580
+ },
9581
+ {
9582
+ "path": "progressPercent",
9583
+ "valueType": "number"
9584
+ },
9585
+ {
9586
+ "path": "currentCode",
9587
+ "valueType": "number"
9588
+ },
9589
+ {
9590
+ "path": "currentCodeLabel",
9591
+ "valueType": "string"
9592
+ },
9593
+ {
9594
+ "path": "severity",
9595
+ "valueType": "enum",
9596
+ "enumValues": [
9597
+ "info",
9598
+ "warning",
9599
+ "error"
9600
+ ]
9601
+ }
9602
+ ],
9603
+ "lock-control": [{
9604
+ "path": "state",
9605
+ "valueType": "enum",
9606
+ "enumValues": [
9607
+ "locked",
9608
+ "unlocked",
9609
+ "locking",
9610
+ "unlocking",
9611
+ "jammed"
9612
+ ]
9613
+ }],
9614
+ "media-player": [
9615
+ {
9616
+ "path": "state",
9617
+ "valueType": "enum",
9618
+ "enumValues": [
9619
+ "off",
9620
+ "on",
9621
+ "idle",
9622
+ "playing",
9623
+ "paused",
9624
+ "buffering",
9625
+ "standby"
9626
+ ]
9627
+ },
9628
+ {
9629
+ "path": "volumeLevel",
9630
+ "valueType": "number"
9631
+ },
9632
+ {
9633
+ "path": "isMuted",
9634
+ "valueType": "boolean"
9635
+ },
9636
+ {
9637
+ "path": "source",
9638
+ "valueType": "string"
9639
+ },
9640
+ {
9641
+ "path": "currentMedia.type",
9642
+ "valueType": "string"
9643
+ },
9644
+ {
9645
+ "path": "currentMedia.title",
9646
+ "valueType": "string"
9647
+ },
9648
+ {
9649
+ "path": "currentMedia.artist",
9650
+ "valueType": "string"
9651
+ },
9652
+ {
9653
+ "path": "currentMedia.album",
9654
+ "valueType": "string"
9655
+ },
9656
+ {
9657
+ "path": "currentMedia.imageUrl",
9658
+ "valueType": "string"
9659
+ },
9660
+ {
9661
+ "path": "positionMs",
9662
+ "valueType": "number"
9663
+ },
9664
+ {
9665
+ "path": "durationMs",
9666
+ "valueType": "number"
9667
+ },
9668
+ {
9669
+ "path": "shuffle",
9670
+ "valueType": "boolean"
9671
+ },
9672
+ {
9673
+ "path": "repeat",
9674
+ "valueType": "enum",
9675
+ "enumValues": [
9676
+ "off",
9677
+ "all",
9678
+ "one"
9679
+ ]
9680
+ }
9681
+ ],
9682
+ "motion": [
9683
+ {
9684
+ "path": "detected",
9685
+ "valueType": "boolean"
9686
+ },
9687
+ {
9688
+ "path": "lastDetectedAt",
9689
+ "valueType": "number"
9690
+ },
9691
+ {
9692
+ "path": "autoClearAfterMs",
9693
+ "valueType": "number"
9694
+ }
9695
+ ],
9696
+ "motion-trigger": [{
9697
+ "path": "enabled",
9698
+ "valueType": "boolean"
9699
+ }],
9700
+ "motion-zones": [{
9701
+ "path": "enabled",
9702
+ "valueType": "boolean"
9703
+ }, {
9704
+ "path": "sensitivity",
9705
+ "valueType": "number"
9706
+ }],
9707
+ "mqtt-broker": [{
9708
+ "path": "brokerCount",
9709
+ "valueType": "number"
9710
+ }, {
9711
+ "path": "embeddedRunning",
9712
+ "valueType": "boolean"
9713
+ }],
9714
+ "native-object-detection": [{
9715
+ "path": "enabled",
9716
+ "valueType": "boolean"
9717
+ }],
9718
+ "navigation": [
9719
+ {
9720
+ "path": "mode",
9721
+ "valueType": "enum",
9722
+ "enumValues": [
9723
+ "idle",
9724
+ "cleaning",
9725
+ "spot",
9726
+ "following",
9727
+ "goto",
9728
+ "returning",
9729
+ "paused",
9730
+ "unknown"
9731
+ ]
9732
+ },
9733
+ {
9734
+ "path": "following",
9735
+ "valueType": "boolean"
9736
+ },
9737
+ {
9738
+ "path": "flash",
9739
+ "valueType": "boolean"
9740
+ },
9741
+ {
9742
+ "path": "lightMode",
9743
+ "valueType": "enum",
9744
+ "enumValues": ["auto", "manual"]
9745
+ },
9746
+ {
9747
+ "path": "lightLevel",
9748
+ "valueType": "number"
9749
+ }
9750
+ ],
9751
+ "network-link": [
9752
+ {
9753
+ "path": "type",
9754
+ "valueType": "enum",
9755
+ "enumValues": [
9756
+ "wifi",
9757
+ "ethernet",
9758
+ "cellular",
9759
+ "unknown"
9760
+ ]
9761
+ },
9762
+ {
9763
+ "path": "signalPercent",
9764
+ "valueType": "number"
9765
+ },
9766
+ {
9767
+ "path": "rssiDbm",
9768
+ "valueType": "number"
9769
+ },
9770
+ {
9771
+ "path": "ssid",
9772
+ "valueType": "string"
9773
+ },
9774
+ {
9775
+ "path": "lastUpdated",
9776
+ "valueType": "number"
9777
+ }
9778
+ ],
9779
+ "notifier": [
9780
+ {
9781
+ "path": "lastSentAt",
9782
+ "valueType": "number"
9783
+ },
9784
+ {
9785
+ "path": "lastError",
9786
+ "valueType": "string"
9787
+ },
9788
+ {
9789
+ "path": "queueDepth",
9790
+ "valueType": "number"
9791
+ },
9792
+ {
9793
+ "path": "supports.image",
9794
+ "valueType": "boolean"
9795
+ },
9796
+ {
9797
+ "path": "supports.priority",
9798
+ "valueType": "boolean"
9799
+ },
9800
+ {
9801
+ "path": "supports.data",
9802
+ "valueType": "boolean"
9803
+ },
9804
+ {
9805
+ "path": "supports.actions",
9806
+ "valueType": "boolean"
9807
+ },
9808
+ {
9809
+ "path": "supports.recipients",
9810
+ "valueType": "boolean"
9811
+ }
9812
+ ],
9813
+ "numeric-sensor": [
9814
+ {
9815
+ "path": "value",
9816
+ "valueType": "number"
9817
+ },
9818
+ {
9819
+ "path": "unit",
9820
+ "valueType": "string"
9821
+ },
9822
+ {
9823
+ "path": "precision",
9824
+ "valueType": "number"
9825
+ }
9826
+ ],
9827
+ "pet-feeder": [
9828
+ {
9829
+ "path": "foodLevel",
9830
+ "valueType": "number"
9831
+ },
9832
+ {
9833
+ "path": "food1",
9834
+ "valueType": "number"
9835
+ },
9836
+ {
9837
+ "path": "food2",
9838
+ "valueType": "number"
9839
+ },
9840
+ {
9841
+ "path": "lowFood",
9842
+ "valueType": "boolean"
9843
+ },
9844
+ {
9845
+ "path": "batteryPower",
9846
+ "valueType": "number"
9847
+ },
9848
+ {
9849
+ "path": "desiccantLeftDays",
9850
+ "valueType": "number"
9851
+ },
9852
+ {
9853
+ "path": "feeding",
9854
+ "valueType": "boolean"
9855
+ },
9856
+ {
9857
+ "path": "status",
9858
+ "valueType": "enum",
9859
+ "enumValues": [
9860
+ "normal",
9861
+ "offline",
9862
+ "on_batteries"
9863
+ ]
9864
+ },
9865
+ {
9866
+ "path": "error",
9867
+ "valueType": "string"
9868
+ },
9869
+ {
9870
+ "path": "errorCode",
9871
+ "valueType": "number"
9872
+ },
9873
+ {
9874
+ "path": "isDualHopper",
9875
+ "valueType": "boolean"
9876
+ },
9877
+ {
9878
+ "path": "childLock",
9879
+ "valueType": "boolean"
9880
+ },
9881
+ {
9882
+ "path": "indicatorLight",
9883
+ "valueType": "boolean"
9884
+ },
9885
+ {
9886
+ "path": "feedSound",
9887
+ "valueType": "boolean"
9888
+ },
9889
+ {
9890
+ "path": "volume",
9891
+ "valueType": "number"
9892
+ }
9893
+ ],
9894
+ "power-meter": [
9895
+ {
9896
+ "path": "watts",
9897
+ "valueType": "number"
9898
+ },
9899
+ {
9900
+ "path": "kwhTotal",
9901
+ "valueType": "number"
9902
+ },
9903
+ {
9904
+ "path": "volts",
9905
+ "valueType": "number"
9906
+ },
9907
+ {
9908
+ "path": "amps",
9909
+ "valueType": "number"
9910
+ },
9911
+ {
9912
+ "path": "va",
9913
+ "valueType": "number"
9914
+ },
9915
+ {
9916
+ "path": "powerFactor",
9917
+ "valueType": "number"
9918
+ },
9919
+ {
9920
+ "path": "unit",
9921
+ "valueType": "string"
9922
+ },
9923
+ {
9924
+ "path": "precision",
9925
+ "valueType": "number"
9926
+ }
9927
+ ],
9928
+ "presence": [
9929
+ {
9930
+ "path": "state",
9931
+ "valueType": "string"
9932
+ },
9933
+ {
9934
+ "path": "location",
9935
+ "valueType": "string"
9936
+ },
9937
+ {
9938
+ "path": "gps.latitude",
9939
+ "valueType": "number"
9940
+ },
9941
+ {
9942
+ "path": "gps.longitude",
9943
+ "valueType": "number"
9944
+ },
9945
+ {
9946
+ "path": "gps.accuracyMeters",
9947
+ "valueType": "number"
9948
+ },
9949
+ {
9950
+ "path": "batteryPercent",
9951
+ "valueType": "number"
9952
+ }
9953
+ ],
9954
+ "pressure-sensor": [
9955
+ {
9956
+ "path": "hpa",
9957
+ "valueType": "number"
9958
+ },
9959
+ {
9960
+ "path": "unit",
9961
+ "valueType": "string"
9962
+ },
9963
+ {
9964
+ "path": "precision",
9965
+ "valueType": "number"
9966
+ }
9967
+ ],
9968
+ "privacy-mask": [{
9969
+ "path": "enabled",
9970
+ "valueType": "boolean"
9971
+ }, {
9972
+ "path": "audioEnabled",
9973
+ "valueType": "boolean"
9974
+ }],
9975
+ "ptz": [
9976
+ {
9977
+ "path": "pan",
9978
+ "valueType": "number"
9979
+ },
9980
+ {
9981
+ "path": "tilt",
9982
+ "valueType": "number"
9983
+ },
9984
+ {
9985
+ "path": "zoom",
9986
+ "valueType": "number"
9987
+ },
9988
+ {
9989
+ "path": "autofocus",
9990
+ "valueType": "boolean"
9991
+ }
9992
+ ],
9993
+ "ptz-autotrack": [
9994
+ {
9995
+ "path": "enabled",
9996
+ "valueType": "boolean"
9997
+ },
9998
+ {
9999
+ "path": "currentSettings.targetType",
10000
+ "valueType": "string"
10001
+ },
10002
+ {
10003
+ "path": "currentSettings.stopDelaySeconds",
10004
+ "valueType": "number"
10005
+ },
10006
+ {
10007
+ "path": "currentSettings.disappearDelaySeconds",
10008
+ "valueType": "number"
10009
+ }
10010
+ ],
10011
+ "recording-archive": [
10012
+ {
10013
+ "path": "deviceId",
10014
+ "valueType": "number"
10015
+ },
10016
+ {
10017
+ "path": "enabled",
10018
+ "valueType": "boolean"
10019
+ },
10020
+ {
10021
+ "path": "activeMode",
10022
+ "valueType": "enum",
10023
+ "enumValues": [
10024
+ "off",
10025
+ "events",
10026
+ "continuous",
10027
+ "on-device-decision"
10028
+ ]
10029
+ },
10030
+ {
10031
+ "path": "nodeId",
10032
+ "valueType": "string"
10033
+ },
10034
+ {
10035
+ "path": "storageBytes",
10036
+ "valueType": "number"
10037
+ }
10038
+ ],
10039
+ "recording-onboard": [
10040
+ {
10041
+ "path": "primaryTrackId",
10042
+ "valueType": "string"
10043
+ },
10044
+ {
10045
+ "path": "enabled",
10046
+ "valueType": "boolean"
10047
+ },
10048
+ {
10049
+ "path": "overwriteWhenFull",
10050
+ "valueType": "boolean"
10051
+ },
10052
+ {
10053
+ "path": "preRecordSec",
10054
+ "valueType": "number"
10055
+ },
10056
+ {
10057
+ "path": "postRecordSec",
10058
+ "valueType": "number"
10059
+ },
10060
+ {
10061
+ "path": "segmentMinutes",
10062
+ "valueType": "number"
10063
+ },
10064
+ {
10065
+ "path": "unreadableWindows",
10066
+ "valueType": "number"
10067
+ },
10068
+ {
10069
+ "path": "recordingToNowhere",
10070
+ "valueType": "boolean"
10071
+ }
10072
+ ],
10073
+ "recording-signal": [{
10074
+ "path": "active",
10075
+ "valueType": "boolean"
10076
+ }, {
10077
+ "path": "reason",
10078
+ "valueType": "string"
10079
+ }],
10080
+ "running-state": [
10081
+ {
10082
+ "path": "running",
10083
+ "valueType": "boolean"
10084
+ },
10085
+ {
10086
+ "path": "since",
10087
+ "valueType": "number"
10088
+ },
10089
+ {
10090
+ "path": "source",
10091
+ "valueType": "enum",
10092
+ "enumValues": ["native", "assigned"]
10093
+ },
10094
+ {
10095
+ "path": "phase",
10096
+ "valueType": "string"
10097
+ }
10098
+ ],
10099
+ "script-runner": [
10100
+ {
10101
+ "path": "isRunning",
10102
+ "valueType": "boolean"
10103
+ },
10104
+ {
10105
+ "path": "lastRunAt",
10106
+ "valueType": "number"
10107
+ },
10108
+ {
10109
+ "path": "lastRunSuccess",
10110
+ "valueType": "boolean"
10111
+ },
10112
+ {
10113
+ "path": "lastError",
10114
+ "valueType": "string"
10115
+ }
10116
+ ],
10117
+ "smoke": [{
10118
+ "path": "detected",
10119
+ "valueType": "boolean"
10120
+ }],
10121
+ "snapshot": [
10122
+ {
10123
+ "path": "lastCapturedAt",
10124
+ "valueType": "number"
10125
+ },
10126
+ {
10127
+ "path": "cacheAgeMs",
10128
+ "valueType": "number"
10129
+ },
10130
+ {
10131
+ "path": "lastBytes",
10132
+ "valueType": "number"
10133
+ },
10134
+ {
10135
+ "path": "lastStreamId",
10136
+ "valueType": "string"
10137
+ }
10138
+ ],
10139
+ "stream-params": [
10140
+ {
10141
+ "path": "main.width",
10142
+ "valueType": "number"
10143
+ },
10144
+ {
10145
+ "path": "main.height",
10146
+ "valueType": "number"
10147
+ },
10148
+ {
10149
+ "path": "main.codec",
10150
+ "valueType": "enum",
10151
+ "enumValues": ["h264", "h265"]
10152
+ },
10153
+ {
10154
+ "path": "main.framerate",
10155
+ "valueType": "number"
10156
+ },
10157
+ {
10158
+ "path": "main.bitrate",
10159
+ "valueType": "number"
10160
+ },
10161
+ {
10162
+ "path": "main.bitrateMode",
10163
+ "valueType": "enum",
10164
+ "enumValues": ["vbr", "cbr"]
10165
+ },
10166
+ {
10167
+ "path": "main.encoderProfile",
10168
+ "valueType": "enum",
10169
+ "enumValues": [
10170
+ "high",
10171
+ "main",
10172
+ "baseline"
10173
+ ]
10174
+ },
10175
+ {
10176
+ "path": "main.gop",
10177
+ "valueType": "number"
10178
+ },
10179
+ {
10180
+ "path": "main.audio",
10181
+ "valueType": "boolean"
10182
+ },
10183
+ {
10184
+ "path": "sub.width",
10185
+ "valueType": "number"
10186
+ },
10187
+ {
10188
+ "path": "sub.height",
10189
+ "valueType": "number"
10190
+ },
10191
+ {
10192
+ "path": "sub.codec",
10193
+ "valueType": "enum",
10194
+ "enumValues": ["h264", "h265"]
10195
+ },
10196
+ {
10197
+ "path": "sub.framerate",
10198
+ "valueType": "number"
10199
+ },
10200
+ {
10201
+ "path": "sub.bitrate",
10202
+ "valueType": "number"
10203
+ },
10204
+ {
10205
+ "path": "sub.bitrateMode",
10206
+ "valueType": "enum",
10207
+ "enumValues": ["vbr", "cbr"]
10208
+ },
10209
+ {
10210
+ "path": "sub.encoderProfile",
10211
+ "valueType": "enum",
10212
+ "enumValues": [
10213
+ "high",
10214
+ "main",
10215
+ "baseline"
10216
+ ]
10217
+ },
10218
+ {
10219
+ "path": "sub.gop",
10220
+ "valueType": "number"
10221
+ },
10222
+ {
10223
+ "path": "sub.audio",
10224
+ "valueType": "boolean"
10225
+ },
10226
+ {
10227
+ "path": "ext.width",
10228
+ "valueType": "number"
10229
+ },
10230
+ {
10231
+ "path": "ext.height",
10232
+ "valueType": "number"
10233
+ },
10234
+ {
10235
+ "path": "ext.codec",
10236
+ "valueType": "enum",
10237
+ "enumValues": ["h264", "h265"]
10238
+ },
10239
+ {
10240
+ "path": "ext.framerate",
10241
+ "valueType": "number"
10242
+ },
10243
+ {
10244
+ "path": "ext.bitrate",
10245
+ "valueType": "number"
10246
+ },
10247
+ {
10248
+ "path": "ext.bitrateMode",
10249
+ "valueType": "enum",
10250
+ "enumValues": ["vbr", "cbr"]
10251
+ },
10252
+ {
10253
+ "path": "ext.encoderProfile",
10254
+ "valueType": "enum",
10255
+ "enumValues": [
10256
+ "high",
10257
+ "main",
10258
+ "baseline"
10259
+ ]
10260
+ },
10261
+ {
10262
+ "path": "ext.gop",
10263
+ "valueType": "number"
10264
+ },
10265
+ {
10266
+ "path": "ext.audio",
10267
+ "valueType": "boolean"
10268
+ }
10269
+ ],
10270
+ "switch": [{
10271
+ "path": "on",
10272
+ "valueType": "boolean"
10273
+ }],
10274
+ "tamper": [{
10275
+ "path": "tampered",
10276
+ "valueType": "boolean"
10277
+ }],
10278
+ "temperature-sensor": [
10279
+ {
10280
+ "path": "celsius",
10281
+ "valueType": "number"
10282
+ },
10283
+ {
10284
+ "path": "unit",
10285
+ "valueType": "string"
10286
+ },
10287
+ {
10288
+ "path": "precision",
10289
+ "valueType": "number"
10290
+ }
10291
+ ],
10292
+ "update": [
10293
+ {
10294
+ "path": "currentVersion",
10295
+ "valueType": "string"
10296
+ },
10297
+ {
10298
+ "path": "availableVersion",
10299
+ "valueType": "string"
10300
+ },
10301
+ {
10302
+ "path": "updatable",
10303
+ "valueType": "boolean"
10304
+ },
10305
+ {
10306
+ "path": "state",
10307
+ "valueType": "string"
10308
+ },
10309
+ {
10310
+ "path": "inProgress",
10311
+ "valueType": "boolean"
10312
+ }
10313
+ ],
10314
+ "vacuum-control": [
10315
+ {
10316
+ "path": "state",
10317
+ "valueType": "enum",
10318
+ "enumValues": [
10319
+ "idle",
10320
+ "cleaning",
10321
+ "paused",
10322
+ "returning",
10323
+ "docked",
10324
+ "drying",
10325
+ "error"
10326
+ ]
10327
+ },
10328
+ {
10329
+ "path": "batteryLevel",
10330
+ "valueType": "number"
10331
+ },
10332
+ {
10333
+ "path": "fanSpeed",
10334
+ "valueType": "string"
10335
+ },
10336
+ {
10337
+ "path": "progressPercent",
10338
+ "valueType": "number"
10339
+ },
10340
+ {
10341
+ "path": "errorCode",
10342
+ "valueType": "number"
10343
+ },
10344
+ {
10345
+ "path": "errorLabel",
10346
+ "valueType": "string"
10347
+ }
10348
+ ],
10349
+ "valve": [{
10350
+ "path": "state",
10351
+ "valueType": "enum",
10352
+ "enumValues": [
10353
+ "open",
10354
+ "opening",
10355
+ "closing",
10356
+ "closed",
10357
+ "stopped"
10358
+ ]
10359
+ }, {
10360
+ "path": "position",
10361
+ "valueType": "number"
10362
+ }],
10363
+ "vibration": [{
10364
+ "path": "detected",
10365
+ "valueType": "boolean"
10366
+ }],
10367
+ "water-heater": [
10368
+ {
10369
+ "path": "currentTemp",
10370
+ "valueType": "number"
10371
+ },
10372
+ {
10373
+ "path": "targetTemp",
10374
+ "valueType": "number"
10375
+ },
10376
+ {
10377
+ "path": "operationMode",
10378
+ "valueType": "string"
10379
+ },
10380
+ {
10381
+ "path": "away",
10382
+ "valueType": "boolean"
10383
+ },
10384
+ {
10385
+ "path": "minTemp",
10386
+ "valueType": "number"
10387
+ },
10388
+ {
10389
+ "path": "maxTemp",
10390
+ "valueType": "number"
10391
+ }
10392
+ ],
10393
+ "weather": [
10394
+ {
10395
+ "path": "condition",
10396
+ "valueType": "string"
10397
+ },
10398
+ {
10399
+ "path": "temperature",
10400
+ "valueType": "number"
10401
+ },
10402
+ {
10403
+ "path": "temperatureUnit",
10404
+ "valueType": "string"
10405
+ },
10406
+ {
10407
+ "path": "humidity",
10408
+ "valueType": "number"
10409
+ },
10410
+ {
10411
+ "path": "pressure",
10412
+ "valueType": "number"
10413
+ },
10414
+ {
10415
+ "path": "pressureUnit",
10416
+ "valueType": "string"
10417
+ },
10418
+ {
10419
+ "path": "windSpeed",
10420
+ "valueType": "number"
10421
+ },
10422
+ {
10423
+ "path": "windSpeedUnit",
10424
+ "valueType": "string"
10425
+ },
10426
+ {
10427
+ "path": "windBearing",
10428
+ "valueType": "number"
10429
+ }
10430
+ ],
10431
+ "zone-analytics": [
10432
+ {
10433
+ "path": "ts",
10434
+ "valueType": "number"
10435
+ },
10436
+ {
10437
+ "path": "frameWidth",
10438
+ "valueType": "number"
10439
+ },
10440
+ {
10441
+ "path": "frameHeight",
10442
+ "valueType": "number"
10443
+ },
10444
+ {
10445
+ "path": "frame.totalObjects",
10446
+ "valueType": "number"
10447
+ },
10448
+ {
10449
+ "path": "frame.standingObjects",
10450
+ "valueType": "number"
10451
+ },
10452
+ {
10453
+ "path": "frame.transientObjects",
10454
+ "valueType": "number"
10455
+ },
10456
+ {
10457
+ "path": "unzoned.totalObjects",
10458
+ "valueType": "number"
10459
+ },
10460
+ {
10461
+ "path": "unzoned.standingObjects",
10462
+ "valueType": "number"
10463
+ },
10464
+ {
10465
+ "path": "unzoned.transientObjects",
10466
+ "valueType": "number"
10467
+ }
10468
+ ]
10469
+ });
8493
10470
  object({
8494
10471
  code: string().regex(/^[a-z][a-z0-9-]*(\.[a-z0-9-]+)+$/),
8495
10472
  params: record(string(), union([string(), number()])).optional()
@@ -8852,7 +10829,7 @@ var DeviceRole = /* @__PURE__ */ function(DeviceRole) {
8852
10829
  return DeviceRole;
8853
10830
  }({});
8854
10831
  //#endregion
8855
- //#region ../types/dist/composition-CB6PMT9p.mjs
10832
+ //#region ../types/dist/composition-kEl9mevu.mjs
8856
10833
  /**
8857
10834
  * The ffmpeg build every CamStack node downloads, per platform and arch.
8858
10835
  *
@@ -8912,7 +10889,7 @@ portable("linux64"), portable("linuxarm64"), portable("macarm64"), portable("mac
8912
10889
  * ONE table for everyone who asks "is this device HIGH?": the
8913
10890
  * recorder's `RecordingTriggers.sensorDeviceIds` trigger, the post-analysis
8914
10891
  * sensor markers, the orchestrator's camera-sensors bridge and
8915
- * the sources of a composite doorbell (`doorbellFeatureSources`, D671).
10892
+ * the sources of a pulse (`compilePulseOverride`, D936).
8916
10893
  * A second copy would diverge at the first cap added, and the symptom — "the
8917
10894
  * sensor rings the doorbell but does not record" — is exactly D62.
8918
10895
  *
@@ -9153,6 +11130,20 @@ var table = {
9153
11130
  apply: () => {
9154
11131
  throw new ExpressionEvalError("count: stateful evaluation context is required");
9155
11132
  }
11133
+ },
11134
+ dwell: {
11135
+ minArgs: 3,
11136
+ maxArgs: 3,
11137
+ apply: () => {
11138
+ throw new ExpressionEvalError("dwell: stateful evaluation context is required");
11139
+ }
11140
+ },
11141
+ latchedAt: {
11142
+ minArgs: 1,
11143
+ maxArgs: 1,
11144
+ apply: () => {
11145
+ throw new ExpressionEvalError("latchedAt: stateful evaluation context is required");
11146
+ }
9156
11147
  }
9157
11148
  };
9158
11149
  Object.freeze(Object.assign(Object.create(null), table));
@@ -10592,13 +12583,22 @@ var BirthDecisionRecordSchema = object({
10592
12583
  decidedByBirthEvidence: boolean(),
10593
12584
  /** Best class-compatible crop score, or `null` when nothing compatible was
10594
12585
  * found — deliberately not 0, which would be a measurement that never was.
10595
- * Includes a box the detector's own per-class floor refused (reason
10596
- * `below-detector-floor`, D922): that box never confirms, but it is the
10597
- * score the crop really held. */
12586
+ * Includes a box the detector's own per-class floor refused (D922): since
12587
+ * D925 the gate's bar, not that floor, decides whether it confirms. */
10598
12588
  bestScore: number().nullable(),
10599
12589
  /** The bar this candidate actually faced (the phantom-cell hook may raise it). */
10600
12590
  appliedMinConfidence: number().nullable(),
10601
12591
  /**
12592
+ * The detector the gate re-judged the birth WITH (D925): the session's own
12593
+ * root model, inference-device pool and node — never a node default. `null`
12594
+ * when the frame named no session detector or no gate ran, and on rows
12595
+ * written before D925. A `session-device-unavailable` row names the session
12596
+ * detector that could not be reached.
12597
+ */
12598
+ detectorModelId: string().nullable().default(null),
12599
+ detectorDeviceKey: string().nullable().default(null),
12600
+ detectorNodeId: string().nullable().default(null),
12601
+ /**
10602
12602
  * The track's own `firstSeen` — the candidate's first frame, which is where
10603
12603
  * the timeline starts. `null` for a suppressed birth, which has no track.
10604
12604
  */
@@ -12082,7 +14082,7 @@ var LogChannelDescriptorSchema = object({
12082
14082
  * `true` is a PROMISE with two halves, and both must hold: the gate is
12083
14083
  * consulted with the numeric device id, AND every line the channel admits
12084
14084
  * carries `tags: { deviceId }` with that same numeric id. The second half is
12085
- * what makes `| json | deviceId="617"` work in Loki — `loki-payload.ts`
14085
+ * what makes `| json | deviceId="102"` work in Loki — `loki-payload.ts`
12086
14086
  * keeps `deviceId` out of the stream labels for cardinality, so the tag in
12087
14087
  * the body is the only way to filter.
12088
14088
  *
@@ -12270,7 +14270,7 @@ var ModelVariantGroupSchema = object({
12270
14270
  precision: _enum(["fp32", "int8"]).optional(),
12271
14271
  /**
12272
14272
  * Training / latency-variant axis. Omit ⇒ the standard build. `test` marks
12273
- * an alternate training of the same family (Scrypted `relu_test`); chip
14273
+ * an alternate training of the same family (plugin catalog `relu_test`); chip
12274
14274
  * label is "Test".
12275
14275
  */
12276
14276
  optimization: _enum(["standard", "test"]).optional(),
@@ -12522,8 +14522,8 @@ var ModelCatalogEntrySchema = object({
12522
14522
  provider: ModelProviderIdSchema.optional(),
12523
14523
  /**
12524
14524
  * Per-MODEL class map override. Absent ⇒ the step's `StepDefinition.classMap`
12525
- * applies (Frigate / COCO public catalog). Set on a custom model whose raw
12526
- * labels already ARE the CamStack macros (Scrypted identity map).
14525
+ * applies (plus catalog / COCO public catalog). Set on a custom model whose raw
14526
+ * labels already ARE the CamStack macros (plugin catalog identity map).
12527
14527
  */
12528
14528
  classMap: DetectionCatalogClassMapSchema.optional(),
12529
14529
  /**
@@ -15492,7 +17492,7 @@ method(object({
15492
17492
  * `1` is real time and is the ONLY value that allows the copy branch —
15493
17493
  * anything else forces `libx264` over the window. That was priced
15494
17494
  * before it was chosen: a per-event burst measured at 0.23 s and 254 KB
15495
- * on a real 615 720p cut, against 922 KB for the copy it replaces. A
17495
+ * on a real 101 720p cut, against 922 KB for the copy it replaces. A
15496
17496
  * re-encode is capped at 720p (`EVENT_CLIP_ENCODE_MAX_WIDTH`), because
15497
17497
  * once the decode is forced the width stops being free.
15498
17498
  */
@@ -16018,6 +18018,7 @@ var CompositionRunStatusSchema = _enum([
16018
18018
  "starting",
16019
18019
  "running",
16020
18020
  "degraded",
18021
+ "incomplete",
16021
18022
  "failed"
16022
18023
  ]);
16023
18024
  var CompositionFieldStateKindSchema = _enum([
@@ -16067,6 +18068,13 @@ var ComposerUnreadableBlockSchema = object({
16067
18068
  /** The parse error, in the operator's words. */
16068
18069
  error: string()
16069
18070
  });
18071
+ /** A confirmed release the hub did not accept. `deviceId` is the claim's device. */
18072
+ var UnreleasedClaimSchema = object({
18073
+ deviceId: number().int(),
18074
+ capName: string(),
18075
+ owner: string(),
18076
+ error: string()
18077
+ });
16070
18078
  method(object({
16071
18079
  /** The shared Blocks integration; null until `core-blocks` has reconciled it. */
16072
18080
  integrationId: string().nullable(),
@@ -16076,7 +18084,13 @@ method(object({
16076
18084
  /** Operator restarts: rebuild these runtimes and re-resolve their sources. Stores nothing (D62). */
16077
18085
  restartBlockIds: array(string()),
16078
18086
  /** Composition rows that exist but do not parse: held, never withdrawn, reported failed. */
16079
- unreadableBlocks: array(ComposerUnreadableBlockSchema)
18087
+ unreadableBlocks: array(ComposerUnreadableBlockSchema),
18088
+ /**
18089
+ * Operator-confirmed deletions. Their claims are released on this apply,
18090
+ * before any replacement block claims. A block that merely vanished from the
18091
+ * snapshot is not listed here and still waits for two applies (D49).
18092
+ */
18093
+ retiredBlockIds: array(string()).optional()
16080
18094
  }), object({
16081
18095
  blocks: array(object({
16082
18096
  blockId: string(),
@@ -16088,7 +18102,13 @@ method(object({
16088
18102
  * integration unknown, its own rows unread or read empty once). An empty
16089
18103
  * apply the caller owes is paid off only by one the composer acted on (D49).
16090
18104
  */
16091
- acted: boolean()
18105
+ acted: boolean(),
18106
+ /**
18107
+ * Confirmed releases this apply tried and the hub did not accept. Empty when
18108
+ * every one landed (or there was nothing to hand back). Absent on a result
18109
+ * that never got that far.
18110
+ */
18111
+ unreleasedClaims: array(UnreleasedClaimSchema).optional()
16092
18112
  }), {
16093
18113
  kind: "mutation",
16094
18114
  auth: "admin"
@@ -16131,7 +18151,15 @@ Object.freeze({
16131
18151
  kind: "fixed",
16132
18152
  result: ["number", "null"]
16133
18153
  },
16134
- count: NUMBER
18154
+ count: NUMBER,
18155
+ dwell: {
18156
+ kind: "fixed",
18157
+ result: ["boolean", "null"]
18158
+ },
18159
+ latchedAt: {
18160
+ kind: "fixed",
18161
+ result: ["number", "null"]
18162
+ }
16135
18163
  });
16136
18164
  `${COMPOSED_DEVICE_STABLE_ID_PREFIX}`;
16137
18165
  /**
@@ -16204,6 +18232,7 @@ var CoreBlockStatusSchema = _enum([
16204
18232
  "starting",
16205
18233
  "running",
16206
18234
  "degraded",
18235
+ "incomplete",
16207
18236
  "failed"
16208
18237
  ]);
16209
18238
  /** path → TypeScript source for a multi-file block. */
@@ -38351,7 +40380,7 @@ var PRIMARY_CATEGORIES = new Set(ENTRIES.map((e) => e.primaryCategory));
38351
40380
  * `locationKey` is ALWAYS {@link locationIconKey} of the label — never the
38352
40381
  * operator's casing. The registry matches labels trimmed + case-insensitively
38353
40382
  * everywhere (`addLocation`, `removeLocation`, `renameLocation`), and a
38354
- * case-only rename (`cucina` → `Cucina`) is a real edit this repo supports; a
40383
+ * case-only rename (`kitchen` → `Kitchen`) is a real edit this repo supports; a
38355
40384
  * map keyed on the displayed casing would orphan its entry on exactly that
38356
40385
  * edit. Consumers join by keying their own label through `locationIconKey`.
38357
40386
  */
@@ -38376,7 +40405,7 @@ var LocationDescriptionAssignmentSchema = object({
38376
40405
  /**
38377
40406
  * A SITE ZONE — a named part of the property that several locations belong to.
38378
40407
  *
38379
- * "Zona notte" holds every bedroom; "Zona giorno" the living room and the
40408
+ * "Night zone" holds every bedroom; "Zona giorno" the living room and the
38380
40409
  * kitchen. A camera belongs to exactly one location, and a location to at most
38381
40410
  * one zone, so a camera's zone is derived and never stored on the device: the
38382
40411
  * whole point of this entity is that grouping rooms touches no device row.
@@ -38405,7 +40434,7 @@ var LocationDescriptionAssignmentSchema = object({
38405
40434
  * the locations inside it.
38406
40435
  *
38407
40436
  * The LABEL is carried alongside the key because the key is lossy on purpose —
38408
- * a surface must show "Zona notte", not "zona notte". Locations are carried
40437
+ * a surface must show "Night zone", not "night zone". Locations are carried
38409
40438
  * here, rather than left to a second call, because every consumer wants both
38410
40439
  * at once and a viewer that asked twice could render a zone whose membership
38411
40440
  * it has not fetched yet.
@@ -40599,8 +42628,8 @@ var LoadContributionSchema = object({
40599
42628
  "unattributable"
40600
42629
  ]),
40601
42630
  /**
40602
- * What ONE entry is, in the contributor's own words — `615/high`,
40603
- * `617/native`, `cuda:0 shared pool`. Free text because the unit differs per
42631
+ * What ONE entry is, in the contributor's own words — `101/high`,
42632
+ * `102/native`, `cuda:0 shared pool`. Free text because the unit differs per
40604
42633
  * family and inventing a common one would lose the only information that
40605
42634
  * makes two entries for the same camera distinguishable.
40606
42635
  */
@@ -42248,6 +44277,381 @@ var _macroLookup = /* @__PURE__ */ new Map();
42248
44277
  for (const [k, v] of Object.entries(YAMNET_TO_MACRO.mapping)) _macroLookup.set(k.toLowerCase(), v);
42249
44278
  for (const [k, v] of Object.entries(APPLE_SA_TO_MACRO.mapping)) _macroLookup.set(k.toLowerCase(), v);
42250
44279
  /**
44280
+ * Palette entry ids (D939). Audio is the one gradient; `audio-*` leaves are
44281
+ * not entries. `heatmapScrub` is a mark, not an event kind.
44282
+ */
44283
+ var PALETTE_ENTRY_IDS = [
44284
+ "motion",
44285
+ "audio",
44286
+ "recording",
44287
+ "live",
44288
+ "heatmapScrub",
44289
+ "person",
44290
+ "vehicle",
44291
+ "animal",
44292
+ "package",
44293
+ "sensor",
44294
+ "control",
44295
+ "face",
44296
+ "plate",
44297
+ "car",
44298
+ "truck",
44299
+ "bus",
44300
+ "motorcycle",
44301
+ "bicycle",
44302
+ "airplane",
44303
+ "boat",
44304
+ "train",
44305
+ "bird",
44306
+ "dog",
44307
+ "cat",
44308
+ "horse",
44309
+ "sheep",
44310
+ "cow",
44311
+ "elephant",
44312
+ "bear",
44313
+ "zebra",
44314
+ "giraffe",
44315
+ "package-delivered",
44316
+ "package-picked-up",
44317
+ "suitcase",
44318
+ "backpack",
44319
+ "handbag",
44320
+ "contact",
44321
+ "motion-sensor",
44322
+ "smoke",
44323
+ "flood",
44324
+ "gas",
44325
+ "carbon-monoxide",
44326
+ "vibration",
44327
+ "tamper",
44328
+ "presence",
44329
+ "enum-sensor",
44330
+ "device-event",
44331
+ "lock",
44332
+ "cover",
44333
+ "switch",
44334
+ "siren",
44335
+ "button",
44336
+ "doorbell"
44337
+ ];
44338
+ var AUDIO_ENTRY_ID = "audio";
44339
+ /** Six rungs, quiet → loud. The opaque end is the entry's hex. */
44340
+ var AUDIO_GRADIENT_ALPHAS = [
44341
+ .3,
44342
+ .42,
44343
+ .55,
44344
+ .7,
44345
+ .85,
44346
+ 1
44347
+ ];
44348
+ var PALETTE_PRESET_IDS = [
44349
+ "camstack",
44350
+ "high-contrast",
44351
+ "okabe-ito"
44352
+ ];
44353
+ /** Frozen palette tables (D939). The spec refuses a table that breaks the rule. */
44354
+ var CAMSTACK_HEX = {
44355
+ motion: "#d946ef",
44356
+ audio: "#059eb8",
44357
+ recording: "#ef4444",
44358
+ live: "#8d7a00",
44359
+ heatmapScrub: "#4b32ff",
44360
+ person: "#11a64c",
44361
+ vehicle: "#3b82f6",
44362
+ animal: "#ea6a09",
44363
+ package: "#924667",
44364
+ sensor: "#624bbc",
44365
+ control: "#944d24",
44366
+ face: "#ed4f8d",
44367
+ plate: "#4b7027",
44368
+ car: "#9684cf",
44369
+ truck: "#0f9b89",
44370
+ bus: "#a734a9",
44371
+ motorcycle: "#c1133a",
44372
+ bicycle: "#0e6a9b",
44373
+ airplane: "#7c9928",
44374
+ boat: "#b17933",
44375
+ train: "#ad6ca3",
44376
+ bird: "#0f7c55",
44377
+ dog: "#c82700",
44378
+ cat: "#7268f2",
44379
+ horse: "#cb795e",
44380
+ sheep: "#b8636b",
44381
+ cow: "#cb2969",
44382
+ elephant: "#1158d2",
44383
+ bear: "#8d5e00",
44384
+ zebra: "#0097d6",
44385
+ giraffe: "#8f61bb",
44386
+ "package-delivered": "#cd3f9b",
44387
+ "package-picked-up": "#388a08",
44388
+ suitcase: "#666800",
44389
+ backpack: "#ec5022",
44390
+ handbag: "#a76ef8",
44391
+ contact: "#ab5a49",
44392
+ "motion-sensor": "#b95d1a",
44393
+ smoke: "#dd3858",
44394
+ flood: "#b31e7d",
44395
+ gas: "#5b70b5",
44396
+ "carbon-monoxide": "#7b4e8e",
44397
+ vibration: "#e65bba",
44398
+ tamper: "#98464b",
44399
+ presence: "#3a9468",
44400
+ "enum-sensor": "#7885f8",
44401
+ "device-event": "#8c43c8",
44402
+ lock: "#649653",
44403
+ cover: "#c67597",
44404
+ switch: "#7a812a",
44405
+ siren: "#ac5d7f",
44406
+ button: "#b276cd",
44407
+ doorbell: "#0087ab"
44408
+ };
44409
+ var CAMSTACK_FALLBACK = [
44410
+ "#b34dc7",
44411
+ "#1d7d34",
44412
+ "#db6b6c",
44413
+ "#a43d29",
44414
+ "#0e6ee6",
44415
+ "#29a10b",
44416
+ "#a98731",
44417
+ "#0181c6"
44418
+ ];
44419
+ var HIGH_CONTRAST_HEX = {
44420
+ motion: "#964360",
44421
+ audio: "#23a132",
44422
+ recording: "#2494ca",
44423
+ live: "#bd7e2b",
44424
+ heatmapScrub: "#ad6eea",
44425
+ person: "#62611e",
44426
+ vehicle: "#f4534c",
44427
+ animal: "#1556cd",
44428
+ package: "#9c4415",
44429
+ sensor: "#066c48",
44430
+ control: "#f2479f",
44431
+ face: "#139d8a",
44432
+ plate: "#909024",
44433
+ car: "#8e35ab",
44434
+ truck: "#bd0b2b",
44435
+ bus: "#7a88ca",
44436
+ motorcycle: "#e26725",
44437
+ bicycle: "#a6679b",
44438
+ airplane: "#7c5720",
44439
+ boat: "#467a1b",
44440
+ train: "#6f65a4",
44441
+ bird: "#cb717f",
44442
+ dog: "#c62490",
44443
+ cat: "#b36850",
44444
+ horse: "#1872ac",
44445
+ sheep: "#927939",
44446
+ cow: "#428a5c",
44447
+ elephant: "#d41160",
44448
+ bear: "#799453",
44449
+ zebra: "#a85455",
44450
+ giraffe: "#746be8",
44451
+ "package-delivered": "#824a80",
44452
+ "package-picked-up": "#614ac1",
44453
+ suitcase: "#2f77f3",
44454
+ backpack: "#fa476d",
44455
+ handbag: "#c14cbe",
44456
+ contact: "#c83921",
44457
+ "motion-sensor": "#a07ebd",
44458
+ smoke: "#a25b13",
44459
+ flood: "#526bab",
44460
+ gas: "#924938",
44461
+ "carbon-monoxide": "#bb7e53",
44462
+ vibration: "#b66182",
44463
+ tamper: "#3c6931",
44464
+ presence: "#6c851d",
44465
+ "enum-sensor": "#ad2d48",
44466
+ "device-event": "#5e9b04",
44467
+ lock: "#00a062",
44468
+ cover: "#ad8624",
44469
+ switch: "#d05259",
44470
+ siren: "#cd67b3",
44471
+ button: "#c9746a",
44472
+ doorbell: "#338eeb"
44473
+ };
44474
+ var HIGH_CONTRAST_FALLBACK = [
44475
+ "#817f3b",
44476
+ "#a0733e",
44477
+ "#8658b2",
44478
+ "#956301",
44479
+ "#bc652d",
44480
+ "#647331",
44481
+ "#a14c9e",
44482
+ "#d14e71"
44483
+ ];
44484
+ var OKABE_ITO_HEX = {
44485
+ motion: "#b88128",
44486
+ audio: "#1096c8",
44487
+ recording: "#009e73",
44488
+ live: "#9c8c22",
44489
+ heatmapScrub: "#0072b2",
44490
+ person: "#d55e00",
44491
+ vehicle: "#c0739f",
44492
+ animal: "#226d18",
44493
+ package: "#91446c",
44494
+ sensor: "#217b56",
44495
+ control: "#648647",
44496
+ face: "#c22998",
44497
+ plate: "#fa4575",
44498
+ car: "#956301",
44499
+ truck: "#2f77f3",
44500
+ bus: "#7a4e86",
44501
+ motorcycle: "#f54597",
44502
+ bicycle: "#bb3e75",
44503
+ airplane: "#e054c0",
44504
+ boat: "#457942",
44505
+ train: "#867afa",
44506
+ bird: "#88914c",
44507
+ dog: "#1556cd",
44508
+ cat: "#71702c",
44509
+ horse: "#9b4fa4",
44510
+ sheep: "#c0559d",
44511
+ cow: "#d14f65",
44512
+ elephant: "#98470f",
44513
+ bear: "#595896",
44514
+ zebra: "#96790e",
44515
+ giraffe: "#cb717b",
44516
+ "package-delivered": "#139d8a",
44517
+ "package-picked-up": "#906ead",
44518
+ suitcase: "#d02939",
44519
+ backpack: "#d41160",
44520
+ handbag: "#f64f54",
44521
+ contact: "#7258d2",
44522
+ "motion-sensor": "#b66182",
44523
+ smoke: "#627abb",
44524
+ flood: "#b86ae4",
44525
+ gas: "#a95261",
44526
+ "carbon-monoxide": "#c65d3c",
44527
+ vibration: "#7a40b7",
44528
+ tamper: "#914b34",
44529
+ presence: "#9481c3",
44530
+ "enum-sensor": "#ac6d47",
44531
+ "device-event": "#7b6fce",
44532
+ lock: "#c67662",
44533
+ cover: "#a6564d",
44534
+ switch: "#ad2c4e",
44535
+ siren: "#348e08",
44536
+ button: "#d27303",
44537
+ doorbell: "#55770f"
44538
+ };
44539
+ var OKABE_ITO_FALLBACK = [
44540
+ "#9a3784",
44541
+ "#a7392c",
44542
+ "#409d50",
44543
+ "#6987e7",
44544
+ "#ee5b3d",
44545
+ "#c0430d",
44546
+ "#af79b3",
44547
+ "#4b6628"
44548
+ ];
44549
+ /**
44550
+ * The display palette (D939). One table of colours, three presets, one
44551
+ * validator. Taxonomy colours and every consumer read this — there is no
44552
+ * second hex table.
44553
+ */
44554
+ var paletteHexSchema = string().regex(/^#[0-9a-f]{6}$/);
44555
+ var paletteSwatchSchema = discriminatedUnion("form", [object({
44556
+ form: literal("solid"),
44557
+ hex: paletteHexSchema
44558
+ }), object({
44559
+ form: literal("gradient"),
44560
+ hex: paletteHexSchema,
44561
+ alphas: array(number().gt(0).lte(1)).length(AUDIO_GRADIENT_ALPHAS.length)
44562
+ })]);
44563
+ var paletteReadySchema = object({
44564
+ status: literal("ready"),
44565
+ presetId: _enum(PALETTE_PRESET_IDS),
44566
+ customized: boolean(),
44567
+ source: _enum(["stored", "unconfigured"]),
44568
+ swatches: record(string(), paletteSwatchSchema),
44569
+ fallbacks: array(paletteHexSchema).length(8)
44570
+ });
44571
+ var paletteResultSchema = discriminatedUnion("status", [paletteReadySchema, object({
44572
+ status: literal("unknown"),
44573
+ reason: string()
44574
+ })]);
44575
+ var setPaletteInputSchema = union([object({ presetId: string() }), object({
44576
+ presetId: string(),
44577
+ overrides: record(string(), paletteSwatchSchema)
44578
+ })]);
44579
+ object({
44580
+ presetId: string(),
44581
+ overrides: record(string(), paletteSwatchSchema)
44582
+ });
44583
+ function solid(hex) {
44584
+ return {
44585
+ form: "solid",
44586
+ hex
44587
+ };
44588
+ }
44589
+ function audioGradient(hex) {
44590
+ return {
44591
+ form: "gradient",
44592
+ hex,
44593
+ alphas: [...AUDIO_GRADIENT_ALPHAS]
44594
+ };
44595
+ }
44596
+ function swatchesFrom(hexes) {
44597
+ const out = {};
44598
+ for (const id of PALETTE_ENTRY_IDS) {
44599
+ const hex = hexes[id];
44600
+ if (hex === void 0) throw new Error(`palette table missing ${id}`);
44601
+ out[id] = id === "audio" ? audioGradient(hex) : solid(hex);
44602
+ }
44603
+ return out;
44604
+ }
44605
+ function preset(id, name, hexes, fallbacks) {
44606
+ return {
44607
+ id,
44608
+ name,
44609
+ swatches: swatchesFrom(hexes),
44610
+ fallbacks
44611
+ };
44612
+ }
44613
+ var DISPLAY_PRESETS = [
44614
+ preset("camstack", "CamStack", CAMSTACK_HEX, CAMSTACK_FALLBACK),
44615
+ preset("high-contrast", "High contrast", HIGH_CONTRAST_HEX, HIGH_CONTRAST_FALLBACK),
44616
+ preset("okabe-ito", "Colour-blind safe", OKABE_ITO_HEX, OKABE_ITO_FALLBACK)
44617
+ ];
44618
+ function presetById(id) {
44619
+ return DISPLAY_PRESETS.find((item) => item.id === id);
44620
+ }
44621
+ function bundledCamstack() {
44622
+ const presetRow = presetById("camstack");
44623
+ if (presetRow === void 0) throw new Error("CamStack preset missing");
44624
+ return readyOf(presetRow, "unconfigured", false);
44625
+ }
44626
+ function readyOf(row, source, customized) {
44627
+ return {
44628
+ status: "ready",
44629
+ presetId: row.id,
44630
+ customized,
44631
+ source,
44632
+ swatches: row.swatches,
44633
+ fallbacks: [...row.fallbacks]
44634
+ };
44635
+ }
44636
+ function hashFallback(kind, fallbacks) {
44637
+ let hash = 0;
44638
+ for (let i = 0; i < kind.length; i++) hash = hash * 31 + (kind.codePointAt(i) ?? 0) >>> 0;
44639
+ const hex = fallbacks[hash % fallbacks.length];
44640
+ if (hex === void 0) throw new Error("display palette has no fallback colour");
44641
+ return hex;
44642
+ }
44643
+ /** Colour a kind paints with. Audio leaves share the audio gradient's hex. */
44644
+ function paintHex(swatches, fallbacks, kind) {
44645
+ const key = kind.trim().toLowerCase();
44646
+ if (key.startsWith("audio-")) {
44647
+ const audio = swatches[AUDIO_ENTRY_ID];
44648
+ return audio !== void 0 ? audio.hex : hashFallback(key, fallbacks);
44649
+ }
44650
+ const direct = swatches[key];
44651
+ if (direct !== void 0) return direct.hex;
44652
+ return hashFallback(key, fallbacks);
44653
+ }
44654
+ /**
42251
44655
  * Unified event-kind taxonomy — THE single source of truth for
42252
44656
  * `kind → { parentKind, category, level, color, iconId, labelKey, label,
42253
44657
  * icon }`.
@@ -42261,109 +44665,88 @@ for (const [k, v] of Object.entries(APPLE_SA_TO_MACRO.mapping)) _macroLookup.set
42261
44665
  * - `addon-post-analysis/shared/frame/box-drawer.ts` (DEFAULT_COLOR)
42262
44666
  * - the COCO / audio class maps (macro ↔ sub relationships)
42263
44667
  *
42264
- * The DATA (serializable — color/iconId/labelKey/parentKind) lives here in
42265
- * `@camstack/types`. The UI-side mapping `iconId → lucide component` and
42266
- * `labelKey → t()` lives in `@camstack/ui-library`. UIs never hardcode a
42267
- * color or an icon: they read this dictionary (server descriptors carry the
42268
- * fields inline; the client resolves color/icon/label from `iconId`/`kind`).
44668
+ * The DATA (serializable — parentKind / iconId / labelKey) lives here in
44669
+ * `@camstack/types`. Colour is NOT a second table: each entry's `color` is
44670
+ * the bundled CamStack display palette (D939). The effective cluster palette
44671
+ * is the `display-palette` capability. The UI-side mapping `iconId → lucide
44672
+ * component` and `labelKey → t()` lives in `@camstack/ui-library`.
42269
44673
  *
42270
44674
  * Two levels only (v1 YAGNI): macro → sub. `person` is a leaf macro.
42271
44675
  */
42272
- var TAXONOMY_COLORS = {
42273
- motion: "#f59e0b",
42274
- audio: "#06b6d4",
42275
- person: "#22c55e",
42276
- vehicle: "#3b82f6",
42277
- animal: "#f97316",
42278
- package: "#a855f7",
42279
- sensor: "#8b5cf6",
42280
- control: "#10b981",
42281
- genericDetection: "#64748b"
42282
- };
42283
- var DETECTION_SUB_COLORS = {
42284
- car: "#f59e0b",
42285
- truck: "#d97706",
42286
- bus: "#b45309",
42287
- motorcycle: "#eab308",
42288
- bicycle: "#ca8a04",
42289
- airplane: "#60a5fa",
42290
- boat: "#2563eb",
42291
- train: "#1d4ed8",
42292
- bird: "#14b8a6",
42293
- dog: "#84cc16",
42294
- cat: "#f97316",
42295
- horse: "#a16207",
42296
- sheep: "#a3a3a3",
42297
- cow: "#78716c",
42298
- elephant: "#6b7280",
42299
- bear: "#7c2d12",
42300
- zebra: "#404040",
42301
- giraffe: "#d4a373"
42302
- };
44676
+ var BUNDLED_PALETTE = bundledCamstack();
44677
+ function kindColor(kind) {
44678
+ return paintHex(BUNDLED_PALETTE.swatches, BUNDLED_PALETTE.fallbacks, kind);
44679
+ }
44680
+ function firstFallback(fallbacks) {
44681
+ const hex = fallbacks[0];
44682
+ if (hex === void 0) throw new Error("display palette has no fallback colour");
44683
+ return hex;
44684
+ }
44685
+ firstFallback(BUNDLED_PALETTE.fallbacks);
42303
44686
  function titleCase(id) {
42304
44687
  return id.split(/[-_ ]/).filter((p) => p.length > 0).map((p) => p.charAt(0).toUpperCase() + p.slice(1)).join(" ");
42305
44688
  }
42306
44689
  var entries = /* @__PURE__ */ new Map();
42307
- function macro(kind, category, color, iconId, label) {
44690
+ function macro(kind, category, iconId, label) {
42308
44691
  entries.set(kind, {
42309
44692
  kind,
42310
44693
  parentKind: null,
42311
44694
  level: "macro",
42312
44695
  category,
42313
- color,
44696
+ color: kindColor(kind),
42314
44697
  iconId,
42315
44698
  labelKey: `eventKind.${kind}`,
42316
44699
  label
42317
44700
  });
42318
44701
  }
42319
- function sub(kind, parentKind, category, color, iconId, label) {
44702
+ function sub(kind, parentKind, category, iconId, label) {
42320
44703
  entries.set(kind, {
42321
44704
  kind,
42322
44705
  parentKind,
42323
44706
  level: "sub",
42324
44707
  category,
42325
- color,
44708
+ color: kindColor(kind),
42326
44709
  iconId,
42327
44710
  labelKey: `eventKind.${kind}`,
42328
44711
  label
42329
44712
  });
42330
44713
  }
42331
- macro("motion", "motion", TAXONOMY_COLORS.motion, "motion", "Motion");
42332
- macro("audio", "audio", TAXONOMY_COLORS.audio, "audio", "Audio");
42333
- macro("person", "detection", TAXONOMY_COLORS.person, "person", "Person");
42334
- macro("vehicle", "detection", TAXONOMY_COLORS.vehicle, "vehicle", "Vehicle");
42335
- macro("animal", "detection", TAXONOMY_COLORS.animal, "animal", "Animal");
42336
- macro("package", "package", TAXONOMY_COLORS.package, "package", "Package");
42337
- macro("sensor", "sensor", TAXONOMY_COLORS.sensor, "sensor", "Sensor");
42338
- macro("control", "control", TAXONOMY_COLORS.control, "control", "Control");
44714
+ macro("motion", "motion", "motion", "Motion");
44715
+ macro("audio", "audio", "audio", "Audio");
44716
+ macro("person", "detection", "person", "Person");
44717
+ macro("vehicle", "detection", "vehicle", "Vehicle");
44718
+ macro("animal", "detection", "animal", "Animal");
44719
+ macro("package", "package", "package", "Package");
44720
+ macro("sensor", "sensor", "sensor", "Sensor");
44721
+ macro("control", "control", "control", "Control");
42339
44722
  for (const [cocoClass, macroClass] of Object.entries(COCO_TO_MACRO.mapping)) {
42340
44723
  if (macroClass !== "vehicle" && macroClass !== "animal") continue;
42341
44724
  if (entries.has(cocoClass)) continue;
42342
- sub(cocoClass, macroClass, "detection", DETECTION_SUB_COLORS[cocoClass] ?? TAXONOMY_COLORS.genericDetection, cocoClass, titleCase(cocoClass));
44725
+ sub(cocoClass, macroClass, "detection", cocoClass, titleCase(cocoClass));
42343
44726
  }
42344
- sub("package-delivered", "package", "package", TAXONOMY_COLORS.package, "package", "Package delivered");
42345
- sub("package-picked-up", "package", "package", TAXONOMY_COLORS.package, "package", "Package picked up");
42346
- sub("contact", "sensor", "sensor", "#f59e0b", "door", "Contact");
42347
- sub("motion-sensor", "sensor", "sensor", TAXONOMY_COLORS.sensor, "pir", "Motion sensor");
42348
- sub("smoke", "sensor", "sensor", "#ef4444", "smoke", "Smoke");
42349
- sub("flood", "sensor", "sensor", "#3b82f6", "water", "Water leak");
42350
- sub("gas", "sensor", "sensor", "#ef4444", "gas", "Gas");
42351
- sub("carbon-monoxide", "sensor", "sensor", "#dc2626", "smoke", "Carbon monoxide");
42352
- sub("vibration", "sensor", "sensor", "#eab308", "vibration", "Vibration");
42353
- sub("tamper", "sensor", "sensor", "#f97316", "tamper", "Tamper");
42354
- sub("presence", "sensor", "sensor", "#22c55e", "presence", "Presence");
42355
- sub("enum-sensor", "sensor", "sensor", TAXONOMY_COLORS.sensor, "generic", "Sensor state");
42356
- sub("device-event", "sensor", "sensor", "#10b981", "button", "Device event");
42357
- sub("lock", "control", "control", "#0ea5e9", "lock", "Lock");
42358
- sub("cover", "control", "control", "#0ea5e9", "door", "Cover");
42359
- sub("switch", "control", "control", TAXONOMY_COLORS.control, "switch", "Switch");
42360
- sub("siren", "control", "control", "#dc2626", "siren", "Siren");
42361
- sub("button", "control", "control", "#10b981", "button", "Button");
42362
- sub("doorbell", "control", "control", "#a855f7", "doorbell", "Doorbell");
44727
+ sub("package-delivered", "package", "package", "package", "Package delivered");
44728
+ sub("package-picked-up", "package", "package", "package", "Package picked up");
44729
+ sub("contact", "sensor", "sensor", "door", "Contact");
44730
+ sub("motion-sensor", "sensor", "sensor", "pir", "Motion sensor");
44731
+ sub("smoke", "sensor", "sensor", "smoke", "Smoke");
44732
+ sub("flood", "sensor", "sensor", "water", "Water leak");
44733
+ sub("gas", "sensor", "sensor", "gas", "Gas");
44734
+ sub("carbon-monoxide", "sensor", "sensor", "smoke", "Carbon monoxide");
44735
+ sub("vibration", "sensor", "sensor", "vibration", "Vibration");
44736
+ sub("tamper", "sensor", "sensor", "tamper", "Tamper");
44737
+ sub("presence", "sensor", "sensor", "presence", "Presence");
44738
+ sub("enum-sensor", "sensor", "sensor", "generic", "Sensor state");
44739
+ sub("device-event", "sensor", "sensor", "button", "Device event");
44740
+ sub("lock", "control", "control", "lock", "Lock");
44741
+ sub("cover", "control", "control", "door", "Cover");
44742
+ sub("switch", "control", "control", "switch", "Switch");
44743
+ sub("siren", "control", "control", "siren", "Siren");
44744
+ sub("button", "control", "control", "button", "Button");
44745
+ sub("doorbell", "control", "control", "doorbell", "Doorbell");
42363
44746
  for (const l of AUDIO_MACRO_LABELS) {
42364
44747
  const kind = `audio-${l.id}`;
42365
44748
  if (entries.has(kind)) continue;
42366
- sub(kind, "audio", "audio", TAXONOMY_COLORS.audio, kind, l.name);
44749
+ sub(kind, "audio", "audio", kind, l.name);
42367
44750
  }
42368
44751
  /** The complete taxonomy dictionary, keyed by kind. */
42369
44752
  var EVENT_TAXONOMY = Object.freeze(Object.fromEntries(entries));
@@ -42674,9 +45057,6 @@ var NcSystemEventKindSchema = _enum([
42674
45057
  "device-battery-normal",
42675
45058
  "device-consumable-low",
42676
45059
  "device-consumable-normal",
42677
- "device-tank-low",
42678
- "device-tank-full",
42679
- "device-tank-normal",
42680
45060
  "stream-online",
42681
45061
  "stream-offline",
42682
45062
  "node-online",
@@ -42723,13 +45103,14 @@ var NcSystemEventKindSchema = _enum([
42723
45103
  "camera-enabled"
42724
45104
  ]);
42725
45105
  /** The legacy tail of {@link NcSystemEventKindSchema} — see its docblock. */
42726
- var NC_LEGACY_SYSTEM_EVENT_KINDS = new Set([
45106
+ var NC_LEGACY_SYSTEM_EVENT_KINDS = [
42727
45107
  "camera-online",
42728
45108
  "camera-offline",
42729
45109
  "camera-disabled",
42730
45110
  "camera-enabled"
42731
- ]);
42732
- NcSystemEventKindSchema.options.filter((kind) => !NC_LEGACY_SYSTEM_EVENT_KINDS.has(kind));
45111
+ ];
45112
+ var NC_LEGACY_SYSTEM_EVENT_KIND_SET = new Set(NC_LEGACY_SYSTEM_EVENT_KINDS);
45113
+ NcSystemEventKindSchema.options.filter((kind) => !NC_LEGACY_SYSTEM_EVENT_KIND_SET.has(kind));
42733
45114
  /**
42734
45115
  * The panel's transitions, as ONE list.
42735
45116
  *
@@ -43252,7 +45633,7 @@ var NcConditionsSchema = object({
43252
45633
  * with the list under it is worse than no switch (D62).
43253
45634
  *
43254
45635
  * MEMBERS ARE FACE-GALLERY `Identity.id`s (uuid), not display names. A name is
43255
- * renameable, and a rule authored on "Gianluca" went silently dark the moment
45636
+ * renameable, and a rule authored on "Alice" went silently dark the moment
43256
45637
  * the operator fixed the spelling. The id reaches the record on
43257
45638
  * `LabelAttribution.identityId`; the name is what the editor shows and what
43258
45639
  * `{{label}}` renders.
@@ -43803,7 +46184,7 @@ var NcRulePatchSchema = NcRuleInputSchema.partial().extend({
43803
46184
  * A rule scoped to one camera and one zone silently became a rule that
43804
46185
  * matches EVERY event on EVERY camera, and lost its `media` policy
43805
46186
  * (zoneCrop / gif / clip / frame) and its `priority` at the same time. Seen
43806
- * live on 2026-08-12: a rule scoped to device 617 fired on 590 and 615
46187
+ * live on 2026-08-12: a rule scoped to device 102 fired on 104 and 101
43807
46188
  * within a minute of a two-field patch.
43808
46189
  *
43809
46190
  * So every defaulted field is re-declared here WITHOUT its default. The
@@ -43848,18 +46229,11 @@ var NcRuleSchema = NcRuleInputSchema.extend({
43848
46229
  */
43849
46230
  disabledTargetIds: array(string()).default([])
43850
46231
  });
43851
- /**
43852
- * The state-summary SECTIONS (D647 / D698 / D708): the D637 kind groups that
43853
- * report a still-true state. `addons` is the crash-looped addons only and
43854
- * `addon-updates` the addons that are behind (D708 split them). `backups-exports` and `alarm` are not sections — a completed
43855
- * job is not an open state, and the alarm stays instant.
43856
- */
43857
46232
  var NcStateSummarySectionIdSchema = _enum([
43858
46233
  "device-state",
43859
46234
  "streams",
43860
46235
  "battery",
43861
46236
  "consumables",
43862
- "tanks",
43863
46237
  "detection-blind",
43864
46238
  "nodes",
43865
46239
  "addons",
@@ -45160,6 +47534,18 @@ Object.freeze({
45160
47534
  reason: "camera sensor mappings not loaded"
45161
47535
  });
45162
47536
  /**
47537
+ * What the vision model must answer before a package event is emitted
47538
+ * when a packages rule has "Confirm with the LLM" on.
47539
+ *
47540
+ * `package` is the verdict. `confidence` is 0..1. `reason` is the model's
47541
+ * one-line explanation, stored on the event so a drop is not silent.
47542
+ */
47543
+ var PackageLlmVerdictSchema = object({
47544
+ package: boolean(),
47545
+ confidence: number().min(0).max(1),
47546
+ reason: string().min(1)
47547
+ });
47548
+ /**
45163
47549
  * A model choice has a SCOPE, and a scope change has a workflow.
45164
47550
  *
45165
47551
  * ## The two scopes
@@ -45611,7 +47997,7 @@ var LabelAttributionSchema = object({
45611
47997
  * `Identity.id` or a plate-gallery `Vehicle.id` (both `randomUUID`).
45612
47998
  *
45613
47999
  * The text alone is a DISPLAY NAME, and a display name is renameable: a
45614
- * notification rule authored on "Gianluca" stopped matching the moment the
48000
+ * notification rule authored on "Alice" stopped matching the moment the
45615
48001
  * operator fixed the spelling in the gallery, and nothing said so. The id is
45616
48002
  * the thing that does not move, so it is what a rule matches on
45617
48003
  * (`NcConditions.identities`) and the text is what a human is shown.
@@ -46096,6 +48482,21 @@ var ObjectEventSchema = object({
46096
48482
  * pick-up written before D684 — UNKNOWN, never 0 and never `timestamp`.
46097
48483
  */
46098
48484
  observedAt: number().optional(),
48485
+ /**
48486
+ * The delivery was emitted without a vision-model yes (D931).
48487
+ *
48488
+ * Set only when the packages rule asked for an LLM confirm and the model
48489
+ * was unreachable, timed out, or answered something that did not parse.
48490
+ * A notification reads it so it can say "possible" instead of a definite
48491
+ * delivery. Absent on every other row, and on a confirm that said yes.
48492
+ */
48493
+ packagePossible: boolean().optional(),
48494
+ /**
48495
+ * The vision model's verdict, when a packages rule asked for one and the
48496
+ * model answered the schema (D931). A "no" never becomes a row — the
48497
+ * detector drops it and logs the reason. Present on a yes.
48498
+ */
48499
+ packageLlmVerdict: PackageLlmVerdictSchema.optional(),
46099
48500
  /** The parent track's key-event importance [0,1], propagated to every object
46100
48501
  * event of the track (so an event row can be sorted by importance without a
46101
48502
  * track join). Absent on legacy rows / before the track was scored. */
@@ -47893,7 +50294,6 @@ var PipelineAddonSchemaSchema = object({
47893
50294
  defaultModelId: string(),
47894
50295
  defaultModelIdByFormat: record(string(), string()).optional(),
47895
50296
  enabledByDefault: boolean().optional(),
47896
- backfillIntoExistingOverrides: boolean().optional(),
47897
50297
  defaultConfidence: number(),
47898
50298
  group: string().optional(),
47899
50299
  configSchema: array(ConfigFieldBridge).readonly().optional()
@@ -48020,13 +50420,12 @@ var AudioTestResultSchema = object({
48020
50420
  error: string().optional(),
48021
50421
  frame: custom().optional()
48022
50422
  });
48023
- var PipelineConfigBridge = custom();
48024
50423
  var ConfigUISchemaBridge = custom();
48025
50424
  var ConfigUISchemaNullableBridge = custom();
48026
50425
  var InferenceCapabilitiesBridge = custom();
48027
50426
  var ModelAvailabilityListBridge = custom();
48028
50427
  var PipelineRunResultBridge = custom();
48029
- method(_void(), array(PipelineEngineChoiceSchema)), method(_void(), PipelineEngineChoiceSchema), method(PipelineEngineChoiceSchema, array(PipelineDefaultStepSchema)), method(object({ nodeId: string() }), EngineProvisioningSchema), method(_void(), record(string(), object({
50428
+ method(_void(), array(PipelineEngineChoiceSchema)), method(_void(), PipelineEngineChoiceSchema), method(object({ nodeId: string() }), EngineProvisioningSchema), method(_void(), record(string(), object({
48030
50429
  modelId: string(),
48031
50430
  settings: record(string(), unknown()).readonly()
48032
50431
  }))), method(object({ steps: record(string(), object({
@@ -48035,28 +50434,6 @@ method(_void(), array(PipelineEngineChoiceSchema)), method(_void(), PipelineEngi
48035
50434
  })) }), object({ success: literal(true) }), {
48036
50435
  kind: "mutation",
48037
50436
  auth: "admin"
48038
- }), method(object({ nodeId: string() }), object({
48039
- success: literal(true),
48040
- clearedDevices: number()
48041
- }), {
48042
- kind: "mutation",
48043
- auth: "admin"
48044
- }), method(object({
48045
- nodeId: string(),
48046
- deviceIds: array(number()).readonly().optional(),
48047
- dryRun: boolean()
48048
- }), object({
48049
- entries: array(object({
48050
- deviceId: number(),
48051
- keys: array(string()).readonly()
48052
- })).readonly(),
48053
- refused: array(object({
48054
- deviceId: number(),
48055
- reason: string()
48056
- })).readonly()
48057
- }), {
48058
- kind: "mutation",
48059
- auth: "admin"
48060
50437
  }), method(object({ nodeId: string() }), object({ unhealthy: array(object({
48061
50438
  /** `<backend>:<device>`, e.g. `openvino:gpu`. */
48062
50439
  deviceKey: string(),
@@ -48079,7 +50456,7 @@ method(_void(), array(PipelineEngineChoiceSchema)), method(_void(), PipelineEngi
48079
50456
  }), object({ rearmed: boolean() }), {
48080
50457
  kind: "mutation",
48081
50458
  auth: "admin"
48082
- }), method(_void(), PipelineSchemaSchema), method(_void(), array(PipelineDefaultStepSchema).readonly().nullable()), method(_void(), PipelineConfigBridge), method(_void(), ConfigUISchemaBridge), method(object({
50459
+ }), method(_void(), PipelineSchemaSchema), method(_void(), ConfigUISchemaBridge), method(object({
48083
50460
  steps: array(PipelineStepInputSchema),
48084
50461
  deviceKey: string().optional()
48085
50462
  }), PipelineValidationResultSchema), method(_void(), InferenceCapabilitiesBridge), method(object({ addonId: string() }), ModelAvailabilityListBridge), method(object({
@@ -48159,7 +50536,7 @@ method(_void(), array(PipelineEngineChoiceSchema)), method(_void(), PipelineEngi
48159
50536
  /**
48160
50537
  * Root-supplied detections for the tree's ROOT step (D730). Set by
48161
50538
  * `runDetailSubtree` when the camera's root model supplies a crop-kind
48162
- * step (a Frigate+ `license_plate` for `plate-detection`): the step is
50539
+ * step (a plus catalog `license_plate` for `plate-detection`): the step is
48163
50540
  * NOT inferred, these boxes are its output, and its children (the plate
48164
50541
  * reader) run on them through their own crop policy. Boxes are in the
48165
50542
  * PIXELS of the image this call carries. Absent ⇒ the root step runs.
@@ -48327,11 +50704,18 @@ var KeptReasonSchema = _enum(["custom-pin"]);
48327
50704
  * Where a choice's latency came from (D791): this node's own benchmark
48328
50705
  * result, or the hardware-class table. Measured on the node beats the table.
48329
50706
  */
48330
- var LatencySourceSchema = discriminatedUnion("kind", [object({ kind: literal("table") }), object({
48331
- kind: literal("node-benchmark"),
48332
- resultId: string(),
48333
- measuredAtMs: number()
48334
- })]);
50707
+ var LatencySourceSchema = discriminatedUnion("kind", [
50708
+ object({ kind: literal("table") }),
50709
+ object({
50710
+ kind: literal("node-benchmark"),
50711
+ resultId: string(),
50712
+ measuredAtMs: number()
50713
+ }),
50714
+ object({
50715
+ kind: literal("estimated"),
50716
+ estimatedFrom: HardwareClassIdSchema
50717
+ })
50718
+ ]);
48335
50719
  var DeviceModelChoiceSchema = object({
48336
50720
  modelId: string(),
48337
50721
  p50Ms: number(),
@@ -48339,6 +50723,11 @@ var DeviceModelChoiceSchema = object({
48339
50723
  measured: boolean(),
48340
50724
  /** Absent on a plan from before D791 — read as the table. */
48341
50725
  source: LatencySourceSchema.optional(),
50726
+ /**
50727
+ * The measured class this latency was scaled from (D930). Absent when the
50728
+ * cell is the table or a node benchmark.
50729
+ */
50730
+ estimatedFrom: HardwareClassIdSchema.optional(),
48342
50731
  /** Parallel sessions at the camera rate with the headroom kept free: ⌊fps × (1 − headroom) / camera fps⌋. */
48343
50732
  capacitySessions: number(),
48344
50733
  personRecall: number()
@@ -48378,40 +50767,20 @@ var NodeDeviceChangeSchema = object({
48378
50767
  keys: array(string()).readonly()
48379
50768
  })).readonly()
48380
50769
  });
48381
- var CameraOverrideClearSchema = object({
48382
- deviceId: number(),
48383
- source: _enum(["step-override", "wholesale"]),
50770
+ /**
50771
+ * Every model and model-bound threshold lives on the accelerator that runs it
50772
+ * (D927), so the plan writes node / device entries only — there is no camera
50773
+ * layer for it to clear.
50774
+ */
50775
+ var AutoTuneWarningSchema = discriminatedUnion("kind", [object({
50776
+ kind: literal("custom-pin-kept"),
48384
50777
  nodeId: string(),
48385
- deviceKey: string().nullable(),
48386
- stepId: string(),
48387
- modelIdBefore: string().nullable(),
48388
- keys: array(string()).readonly()
48389
- });
48390
- var DetectorStoreClearSchema = object({
48391
- deviceId: number(),
48392
- keys: array(string()).readonly()
48393
- });
48394
- var AutoTuneWarningSchema = discriminatedUnion("kind", [
48395
- object({
48396
- kind: literal("detector-store-cluster-wide"),
48397
- skippedNodes: array(string()).readonly()
48398
- }),
48399
- object({
48400
- kind: literal("detector-store-unreadable"),
48401
- error: string()
48402
- }),
48403
- object({
48404
- kind: literal("custom-pin-kept"),
48405
- nodeId: string(),
48406
- deviceKey: string().nullable(),
48407
- deviceId: number().nullable(),
48408
- modelId: string()
48409
- }),
48410
- object({
48411
- kind: literal("custom-registry-unreadable"),
48412
- error: string()
48413
- })
48414
- ]);
50778
+ deviceKey: string(),
50779
+ modelId: string()
50780
+ }), object({
50781
+ kind: literal("custom-registry-unreadable"),
50782
+ error: string()
50783
+ })]);
48415
50784
  var AutoTuneOptionsSchema = object({
48416
50785
  /** Share of each accelerator's throughput kept free (0.3–0.5). */
48417
50786
  headroom: number().min(.3).max(.5).default(.4),
@@ -48433,8 +50802,6 @@ var AutoTunePlanSchema = object({
48433
50802
  generatedAt: number(),
48434
50803
  nodes: array(NodeRecommendationSchema).readonly(),
48435
50804
  nodeChanges: array(NodeDeviceChangeSchema).readonly(),
48436
- cameraClears: array(CameraOverrideClearSchema).readonly(),
48437
- detectorStoreClears: array(DetectorStoreClearSchema).readonly(),
48438
50805
  warnings: array(AutoTuneWarningSchema).readonly()
48439
50806
  });
48440
50807
  var AutoTuneApplyInputSchema = object({
@@ -48445,8 +50812,6 @@ var AutoTuneApplyInputSchema = object({
48445
50812
  var AutoTunePhaseResultSchema = object({
48446
50813
  phase: _enum([
48447
50814
  "download",
48448
- "camera-overrides",
48449
- "detector-thresholds",
48450
50815
  "node-models",
48451
50816
  "redispatch"
48452
50817
  ]),
@@ -49848,7 +52213,7 @@ var RunnerCameraConfigSchema = object({
49848
52213
  * detection session that asks for history. What shipped was a last-moment
49849
52214
  * discard — `FrameSlot`'s throttle compares wall clocks, and ~4 s of media
49850
52215
  * arriving inside a few hundred ms of wall clock looks to it like one frame's
49851
- * worth. Device 617, 2026-09-08: a re-run of the SAME model over the stored
52216
+ * worth. Device 102, 2026-09-08: a re-run of the SAME model over the stored
49852
52217
  * recording scored the subject `vehicle 0.5669` — above the 0.50 floor —
49853
52218
  * 1.68 s BEFORE the live track was born, on a frame that was in the pre-roll,
49854
52219
  * was decoded, and was freed.
@@ -50201,6 +52566,12 @@ var AgentPipelineSettingsSchema = object({
50201
52566
  /** Hub-persisted UI colour (`--color-node-*` theme tokens). */
50202
52567
  color: NodeColorIdSchema.optional(),
50203
52568
  /**
52569
+ * NODE-wide step settings (D927): `stepId → { key → value }`, applied on
52570
+ * every accelerator of the node under the device's own settings. Never a
52571
+ * model or a model-bound threshold. Written by `setNodeStepSettings`.
52572
+ */
52573
+ stepSettings: record(string(), record(string(), unknown()).readonly()).optional(),
52574
+ /**
50204
52575
  * Multi-device inference opt-in (Phase 4). Per-node map deviceKey → {enabled,
50205
52576
  * weight, steps}. Absent / all-disabled ⇒ the node's single default
50206
52577
  * accelerator (safe default); two+ enabled ⇒ the dispatcher balances
@@ -50216,17 +52587,6 @@ var AgentPipelineSettingsSchema = object({
50216
52587
  steps: record(string(), DeviceStepConfigSchema).optional()
50217
52588
  })).optional()
50218
52589
  });
50219
- var CameraPipelineForAgentSchema = object({
50220
- steps: array(PipelineStepInputSchema).readonly(),
50221
- audio: object({
50222
- modelId: string(),
50223
- enabled: boolean()
50224
- }).nullable()
50225
- });
50226
- var CameraStepOverridePatchSchema = object({
50227
- modelId: string().optional(),
50228
- settings: record(string(), unknown()).readonly().optional()
50229
- });
50230
52590
  var CameraStepSettingsSchema = record(string(), record(string(), unknown()).readonly());
50231
52591
  /** The three root-detector choices a camera has (D507: at most one root). */
50232
52592
  var CameraDetectionSourceSchema = _enum([
@@ -50236,9 +52596,7 @@ var CameraDetectionSourceSchema = _enum([
50236
52596
  ]);
50237
52597
  var CameraPipelineSettingsSchema = object({
50238
52598
  stepToggles: record(string(), boolean()).optional(),
50239
- stepSettings: CameraStepSettingsSchema.optional(),
50240
- stepOverridesByDevice: record(string(), record(string(), record(string(), CameraStepOverridePatchSchema))).optional(),
50241
- pipelineByAgent: record(string(), CameraPipelineForAgentSchema).optional()
52599
+ stepSettings: CameraStepSettingsSchema.optional()
50242
52600
  });
50243
52601
  /**
50244
52602
  * Pipeline placement record persisted by `addon-pipeline-orchestrator` via
@@ -50784,6 +53142,13 @@ method(object({
50784
53142
  }), object({ success: literal(true) }), {
50785
53143
  kind: "mutation",
50786
53144
  auth: "admin"
53145
+ }), method(object({
53146
+ agentNodeId: string(),
53147
+ addonId: string(),
53148
+ settings: record(string(), unknown()).nullable()
53149
+ }), object({ success: literal(true) }), {
53150
+ kind: "mutation",
53151
+ auth: "admin"
50787
53152
  }), method(object({ nodeId: string() }), NodeInferenceDevicesSchema), method(object({
50788
53153
  agentNodeId: string(),
50789
53154
  deviceKey: string()
@@ -50793,9 +53158,7 @@ method(object({
50793
53158
  }), method(object({ agentNodeId: string() }), object({
50794
53159
  success: literal(true),
50795
53160
  /** Hardware-aware default detection model now in effect on the node (null when unresolvable). */
50796
- effectiveModelId: string().nullable(),
50797
- /** Number of cameras whose node-scoped overrides were cleared. */
50798
- clearedCameraOverrides: number()
53161
+ effectiveModelId: string().nullable()
50799
53162
  }), {
50800
53163
  kind: "mutation",
50801
53164
  auth: "admin"
@@ -50850,15 +53213,6 @@ method(object({
50850
53213
  }), object({ success: literal(true) }), {
50851
53214
  kind: "mutation",
50852
53215
  auth: "admin"
50853
- }), method(object({ deviceId: number() }), record(string(), record(string(), record(string(), CameraStepOverridePatchSchema))).nullable()), method(object({
50854
- deviceId: number(),
50855
- agentNodeId: string(),
50856
- deviceKey: string(),
50857
- addonId: string(),
50858
- patch: CameraStepOverridePatchSchema.nullable()
50859
- }), object({ success: literal(true) }), {
50860
- kind: "mutation",
50861
- auth: "admin"
50862
53216
  }), method(object({
50863
53217
  deviceId: number(),
50864
53218
  addonId: string(),
@@ -50866,13 +53220,6 @@ method(object({
50866
53220
  }), object({ success: literal(true) }), {
50867
53221
  kind: "mutation",
50868
53222
  auth: "admin"
50869
- }), method(object({
50870
- deviceId: number(),
50871
- agentNodeId: string(),
50872
- pipeline: CameraPipelineForAgentSchema.nullable()
50873
- }), object({ success: literal(true) }), {
50874
- kind: "mutation",
50875
- auth: "admin"
50876
53223
  }), method(object({
50877
53224
  deviceId: number(),
50878
53225
  agentNodeId: string().optional()
@@ -52000,7 +54347,7 @@ method(_void(), ProviderInfoSchema, { auth: "admin" }), method(object({ config:
52000
54347
  * The signals a device can emit to WAKE its own stream.
52001
54348
  *
52002
54349
  * A camera whose stream is built on demand sleeps until something asks for it,
52003
- * and "something" cannot be a consumer that is merely attached — a Frigate-style
54350
+ * and "something" cannot be a consumer that is merely attached — a external-catalog
52004
54351
  * puller holds a session open for ever, and treating that as demand would keep
52005
54352
  * a battery camera awake for ever, which is the whole thing the battery is for
52006
54353
  * (D173). So the wake has to come from the CAMERA: an event it noticed by
@@ -52759,7 +55106,7 @@ var ClipSchema = object({
52759
55106
  * {@link MAX_CLIP_EVENT_IDS}. Empty on footage-only clips.
52760
55107
  *
52761
55108
  * Bounded because it is not a payload the surface pages through: one visit on
52762
- * device 615 carried 2 345 ids, and `eventIds` was 99% of a 153 KB
55109
+ * device 101 carried 2 345 ids, and `eventIds` was 99% of a 153 KB
52763
55110
  * camera-day. Read {@link eventCount} for the true total.
52764
55111
  */
52765
55112
  eventIds: array(string()).optional(),
@@ -52904,7 +55251,7 @@ var ClipPlaybackSchema = object({
52904
55251
  * camera has no recordings", which is the defect this whole line of work is
52905
55252
  * about: a battery camera nobody woke (`sleeping`), a camera that could not be
52906
55253
  * reached at all (`unreachable`, also what a provider that THREW reports), a
52907
- * camera whose SD card is not mounted (`no-storage`, measured on 640 —
55254
+ * camera whose SD card is not mounted (`no-storage`, measured on 106 —
52908
55255
  * `HddInfo mount 0`, honestly nothing to list rather than "no clips"), and a
52909
55256
  * camera whose OWN index disagrees with its OWN calendar (`index-empty`,
52910
55257
  * measured on 618: the calendar marks 3–20 September, days 6–20 list zero
@@ -53365,7 +55712,7 @@ var videoclipsCapability = {
53365
55712
  *
53366
55713
  * It was optional, documented as "absent means the device's BOUND
53367
55714
  * provider, which is CamStack on every camera". No code implemented
53368
- * that. Measured on the live hub 2026-09-20 — device 592, bound to
55715
+ * that. Measured on the live hub 2026-09-20 — device 107, bound to
53369
55716
  * `recorder` AND `provider-reolink` — a bare call with `limit: 3`
53370
55717
  * answered SIX rows, three from each source, merged newest-first:
53371
55718
  * `device-collection-dispatch.ts` simply left the fan-out un-narrowed,
@@ -54682,7 +57029,10 @@ var airQualitySensorCapability = {
54682
57029
  */
54683
57030
  var AmbientLightSensorStatusSchema = object({
54684
57031
  /** Current illuminance in lux (lx). */
54685
- lux: number().min(0),
57032
+ lux: number().min(0).meta({
57033
+ unit: "lx",
57034
+ label: "Illuminance"
57035
+ }),
54686
57036
  /** Ms epoch when the slice was last updated. */
54687
57037
  lastFetchedAt: number(),
54688
57038
  /** Live display unit from the upstream source (e.g. HA
@@ -54725,7 +57075,12 @@ var ambientLightSensorCapability = {
54725
57075
  } } },
54726
57076
  /** Clock fields: written, but excluded from the compare that decides
54727
57077
  * whether persisting is worth a SQLite commit. */
54728
- volatileStateFields: ["lastFetchedAt"]
57078
+ volatileStateFields: ["lastFetchedAt"],
57079
+ customize: {
57080
+ version: 1,
57081
+ advanced: "derive",
57082
+ targets: []
57083
+ }
54729
57084
  };
54730
57085
  /**
54731
57086
  * Per-class audio metrics aggregated over a sliding window.
@@ -54952,7 +57307,10 @@ var BatteryStatusSchema = object({
54952
57307
  * Consumers must SKIP a null rather than coerce it — `battery-band` already
54953
57308
  * declines to band a non-finite reading, which is the correct shape.
54954
57309
  */
54955
- percentage: number().min(0).max(100).nullable(),
57310
+ percentage: number().min(0).max(100).nullable().meta({
57311
+ unit: "%",
57312
+ label: "Charge"
57313
+ }),
54956
57314
  /**
54957
57315
  * Charging source. `'dc'` covers wall/USB adapters; `'solar'` is
54958
57316
  * Reolink-specific for the Solar Panel 2 accessory (will become
@@ -54971,13 +57329,13 @@ var BatteryStatusSchema = object({
54971
57329
  "solar",
54972
57330
  "none",
54973
57331
  "unknown"
54974
- ]),
57332
+ ]).meta({ label: "Charging source" }),
54975
57333
  /**
54976
57334
  * True when the camera firmware has gone into low-power mode. Battery
54977
57335
  * providers MUST avoid polling during sleep — reading the battery
54978
57336
  * wakes the camera up and drains charge.
54979
57337
  */
54980
- sleeping: boolean(),
57338
+ sleeping: boolean().meta({ label: "Sleeping" }),
54981
57339
  /** Ms epoch of the last observation. Lets consumers reason about freshness. */
54982
57340
  lastUpdated: number(),
54983
57341
  /**
@@ -55017,22 +57375,71 @@ var BatteryStatusSchema = object({
55017
57375
  * sub-threshold = low). UI MUST render "Normal"/"Low" instead of a
55018
57376
  * misleading exact percentage. Absent/false → genuine 0–100 % reading.
55019
57377
  */
55020
- binary: boolean().optional()
57378
+ binary: boolean().optional().meta({ label: "Binary indicator" })
55021
57379
  });
57380
+ var BATTERY_DEVICE_TYPES = [
57381
+ DeviceType.Camera,
57382
+ DeviceType.Sensor,
57383
+ DeviceType.Button,
57384
+ DeviceType.Switch,
57385
+ DeviceType.PetFeeder,
57386
+ DeviceType.Container,
57387
+ DeviceType.Thermostat
57388
+ ];
57389
+ /** Generic Customize target for the percentage reading (D936). */
57390
+ var batteryCustomize = {
57391
+ version: 1,
57392
+ advanced: "derive",
57393
+ targets: [{
57394
+ id: "percentage",
57395
+ cardinality: "scalar",
57396
+ vocabulary: {
57397
+ cap: "battery",
57398
+ stateField: "percentage"
57399
+ },
57400
+ deviceTypes: BATTERY_DEVICE_TYPES,
57401
+ apply: "add-or-replace",
57402
+ path: "percentage",
57403
+ sources: [{
57404
+ kind: "field",
57405
+ valueKinds: ["number", "string"],
57406
+ transforms: [{ kind: "identity" }, {
57407
+ kind: "linear",
57408
+ defaultScale: 1,
57409
+ defaultOffset: 0,
57410
+ clampMin: 0,
57411
+ clampMax: 100
57412
+ }]
57413
+ }],
57414
+ companions: [
57415
+ {
57416
+ kind: "constant",
57417
+ path: "charging",
57418
+ value: "unknown",
57419
+ when: "add"
57420
+ },
57421
+ {
57422
+ kind: "constant",
57423
+ path: "sleeping",
57424
+ value: false,
57425
+ when: "add"
57426
+ },
57427
+ {
57428
+ kind: "clock",
57429
+ path: "lastUpdated",
57430
+ when: "add"
57431
+ }
57432
+ ],
57433
+ sourceReport: { status: "assignment-status" },
57434
+ advancedExpression: true
57435
+ }]
57436
+ };
55022
57437
  var batteryCapability = {
55023
57438
  name: "battery",
55024
57439
  scope: "device",
55025
57440
  deviceNative: true,
55026
57441
  mode: "singleton",
55027
- deviceTypes: [
55028
- DeviceType.Camera,
55029
- DeviceType.Sensor,
55030
- DeviceType.Button,
55031
- DeviceType.Switch,
55032
- DeviceType.PetFeeder,
55033
- DeviceType.Container,
55034
- DeviceType.Thermostat
55035
- ],
57442
+ deviceTypes: BATTERY_DEVICE_TYPES,
55036
57443
  methods: {
55037
57444
  /**
55038
57445
  * Explicitly wake the camera from low-power sleep ahead of a
@@ -55116,6 +57523,7 @@ onStatusChanged: { data: object({
55116
57523
  kind: "gauge",
55117
57524
  unit: "%"
55118
57525
  } } },
57526
+ customize: batteryCustomize,
55119
57527
  /** Clock fields: written, but excluded from the compare that decides
55120
57528
  * whether persisting is worth a SQLite commit. */
55121
57529
  volatileStateFields: ["lastUpdated"]
@@ -55132,7 +57540,7 @@ onStatusChanged: { data: object({
55132
57540
  * with the right HomeKit / Alexa display category.
55133
57541
  */
55134
57542
  var BinaryStatusSchema = object({
55135
- on: boolean(),
57543
+ on: boolean().meta({ label: "On" }),
55136
57544
  /** Ms epoch of the last transition. 0 if never observed. */
55137
57545
  lastChangedAt: number()
55138
57546
  });
@@ -55161,7 +57569,12 @@ var binaryCapability = {
55161
57569
  history: { fields: { on: { kind: "boolean" } } },
55162
57570
  /** Clock fields: written, but excluded from the compare that decides
55163
57571
  * whether persisting is worth a SQLite commit. */
55164
- volatileStateFields: ["lastChangedAt"]
57572
+ volatileStateFields: ["lastChangedAt"],
57573
+ customize: {
57574
+ version: 1,
57575
+ advanced: "derive",
57576
+ targets: []
57577
+ }
55165
57578
  };
55166
57579
  /**
55167
57580
  * Dimmable-light brightness control. Co-exists with `switch` on the
@@ -55467,7 +57880,7 @@ var GridLayoutCellSchema = object({
55467
57880
  *
55468
57881
  * A grid's `high` composes its sources' `high` and its `low` their `low`, so a
55469
57882
  * profile is on offer only when EVERY source can serve it. The refusal NAMES
55470
- * the sources, because "this grid has no low" is not a finding — "615 has no
57883
+ * the sources, because "this grid has no low" is not a finding — "101 has no
55471
57884
  * low" is, and it is the one an operator can act on.
55472
57885
  */
55473
57886
  var GridProfileOfferSchema = object({
@@ -56076,6 +58489,106 @@ var ConsumablesStatusSchema = object({
56076
58489
  items: array(ConsumableItemSchema),
56077
58490
  lastChangedAt: number()
56078
58491
  });
58492
+ /** Synthesize seed for a link-built status (no native provider).
58493
+ *
58494
+ * ⚠ NO LIVE CALLER since 2026-08-08 (device-links deleted; see
58495
+ * `CapabilityStatusSchema.empty`). The wiring guidance below was written for
58496
+ * exactly the case the operator is asking about again — a Dreame's HA
58497
+ * consumable-life sensors — so it is kept for that conversation, not because
58498
+ * anything reads it today. */
58499
+ var EMPTY_STATUS = {
58500
+ items: [],
58501
+ lastChangedAt: 0
58502
+ };
58503
+ /** Seed for a NEW link-built consumable item. `key`/`label` are overwritten
58504
+ * with the link's `itemKey` (see `status.itemArray`), so the placeholder
58505
+ * empty strings never survive into a validated item. Link-built items are
58506
+ * not resettable — there is no native provider to receive `reset()`.
58507
+ *
58508
+ * Wiring guidance (HA vacuum consumable-life sensors):
58509
+ * - a percent-remaining source (`numeric-sensor`, unit '%') → `level` via
58510
+ * `identity` (or `linear` scale 1 offset 0 clamp [0,100] to be safe);
58511
+ * - an hours-remaining source (e.g. Dreame 'Main Brush Time Left', unit 'h')
58512
+ * → `level` via `linear` with scale = 100 / max-hours for that item
58513
+ * (e.g. main brush 300 h → scale 0.3333) + clamp [0,100];
58514
+ * - a discrete source (`enum-sensor`, e.g. mop pad 'installed') → `status`
58515
+ * via `enum-map` (e.g. { installed: 'ok', missing: 'replace' }).
58516
+ * A numeric→'replace' THRESHOLD (level < 10 → 'replace') is NOT expressible
58517
+ * with the current transform kinds — leave `status` null (valid) until the
58518
+ * expression transform lands. */
58519
+ /** Generic Customize target for one consumable item (D936). Native rows stay read-only. */
58520
+ var consumablesCustomize = {
58521
+ version: 1,
58522
+ targets: [{
58523
+ id: "items",
58524
+ cardinality: "keyedArray",
58525
+ vocabulary: { cap: "consumables" },
58526
+ deviceTypes: Object.values(DeviceType),
58527
+ apply: "add",
58528
+ path: "items",
58529
+ keyField: "key",
58530
+ labelField: "label",
58531
+ itemSchema: ConsumableItemSchema,
58532
+ nativeItems: "read-only",
58533
+ sourceReport: { status: "assignment-status" },
58534
+ fields: [
58535
+ {
58536
+ path: "level",
58537
+ sources: [{
58538
+ kind: "numeric",
58539
+ transforms: [{ kind: "identity" }, {
58540
+ kind: "linear",
58541
+ defaultScale: 1,
58542
+ defaultOffset: 0,
58543
+ clampMin: 0,
58544
+ clampMax: 100
58545
+ }]
58546
+ }]
58547
+ },
58548
+ {
58549
+ path: "remaining.value",
58550
+ sources: [{
58551
+ kind: "numeric",
58552
+ transforms: [{ kind: "identity" }]
58553
+ }],
58554
+ literals: [{
58555
+ path: "remaining.unit",
58556
+ values: [...ConsumableRemainingUnitSchema.options]
58557
+ }]
58558
+ },
58559
+ {
58560
+ path: "status",
58561
+ sources: [{
58562
+ kind: "enum",
58563
+ transforms: [{
58564
+ kind: "enum-map",
58565
+ outputValues: [...ConsumableStatusSchema.options],
58566
+ unmapped: null
58567
+ }]
58568
+ }]
58569
+ }
58570
+ ],
58571
+ traits: [{
58572
+ path: "kind",
58573
+ values: [...ConsumableKindSchema.options],
58574
+ defaultValue: "wear"
58575
+ }, {
58576
+ path: "form",
58577
+ values: [...ConsumableFormSchema.options],
58578
+ defaultValue: "part"
58579
+ }],
58580
+ companions: [{
58581
+ kind: "clock",
58582
+ path: "lastChangedAt",
58583
+ when: "add"
58584
+ }, {
58585
+ kind: "clock",
58586
+ path: "lastFetchedAt",
58587
+ when: "add"
58588
+ }],
58589
+ advancedExpression: true
58590
+ }]
58591
+ };
56079
58592
  var consumablesCapability = {
56080
58593
  name: "consumables",
56081
58594
  scope: "device",
@@ -56113,10 +58626,7 @@ reset: method(object({
56113
58626
  status: {
56114
58627
  schema: ConsumablesStatusSchema,
56115
58628
  kind: "push",
56116
- empty: {
56117
- items: [],
56118
- lastChangedAt: 0
56119
- },
58629
+ empty: EMPTY_STATUS,
56120
58630
  itemArray: {
56121
58631
  path: "items",
56122
58632
  keyField: "key",
@@ -56152,6 +58662,7 @@ reset: method(object({
56152
58662
  * brush's remaining life and a dishwasher's salt are each recorded the moment
56153
58663
  * their provider reports them; an item that appears later gets its series.
56154
58664
  */
58665
+ customize: consumablesCustomize,
56155
58666
  history: {
56156
58667
  fields: {},
56157
58668
  items: {
@@ -56531,6 +59042,30 @@ var dayNightCapability = {
56531
59042
  volatileStateFields: ["lastFetchedAt"]
56532
59043
  };
56533
59044
  /**
59045
+ * display-palette — the cluster's one colour table (D939).
59046
+ *
59047
+ * Hub singleton. `getPalette` reports `unknown` when the settings store
59048
+ * cannot be read; it does not pretend the bundled preset was stored.
59049
+ * `setPalette` refuses a palette that fails the ΔE / contrast rule and names
59050
+ * the pairs.
59051
+ */
59052
+ var presetSummarySchema = object({
59053
+ id: string(),
59054
+ name: string(),
59055
+ swatches: record(string(), paletteSwatchSchema),
59056
+ fallbacks: array(string())
59057
+ });
59058
+ method(_void(), paletteResultSchema, {
59059
+ auth: "protected",
59060
+ role: "viewer"
59061
+ }), method(_void(), array(presetSummarySchema).readonly(), {
59062
+ auth: "protected",
59063
+ role: "viewer"
59064
+ }), method(setPaletteInputSchema, paletteReadySchema, {
59065
+ kind: "mutation",
59066
+ auth: "admin"
59067
+ });
59068
+ /**
56534
59069
  * Generic device-level status snapshot. Auto-registered by `BaseDevice`
56535
59070
  * for every device, regardless of provider — the kernel needs a uniform
56536
59071
  * cap-keyed slice for the basic device flags every consumer expects to
@@ -56894,6 +59429,36 @@ var dishwasherCapability = {
56894
59429
  powerOn: { kind: "boolean" }
56895
59430
  } }
56896
59431
  };
59432
+ /** Pulse override: a rising edge advances `lastPressedAt` and the press count. */
59433
+ var doorbellCustomize = {
59434
+ version: 1,
59435
+ targets: [{
59436
+ id: "pressed",
59437
+ cardinality: "event",
59438
+ shape: "pulse",
59439
+ vocabulary: {
59440
+ cap: "doorbell",
59441
+ eventName: "onPressed"
59442
+ },
59443
+ deviceTypes: [DeviceType.Camera],
59444
+ apply: "add",
59445
+ applyAuthority: { kind: "composition-claim" },
59446
+ eventName: "onPressed",
59447
+ edges: ["rising"],
59448
+ timestampPath: "lastPressedAt",
59449
+ counterPath: "pressCountSinceStart",
59450
+ highWater: "composer-advance",
59451
+ combine: "any",
59452
+ debounce: {
59453
+ kind: "rising-edge",
59454
+ defaultDebounceMs: 2e3,
59455
+ changedAtRequired: true
59456
+ },
59457
+ sources: [{ kind: "binary" }, { kind: "switch" }],
59458
+ sourceReport: { status: "assignment-status" },
59459
+ advancedExpression: true
59460
+ }]
59461
+ };
56897
59462
  var DoorbellStatusSchema = object({
56898
59463
  /** Ms epoch of the last press. null = never observed since this provider started. */
56899
59464
  lastPressedAt: number().nullable(),
@@ -56960,7 +59525,8 @@ onPressed: {
56960
59525
  /**
56961
59526
  * History (D850): none — `pressCountSinceStart` resets with the addon, so it is not a monotonic meter; presses live in the events ledger.
56962
59527
  */
56963
- history: "none"
59528
+ history: "none",
59529
+ customize: doorbellCustomize
56964
59530
  };
56965
59531
  /**
56966
59532
  * Enum-state sensor — a string value picked from a finite option set.
@@ -57832,7 +60398,10 @@ var humidifierCapability = {
57832
60398
  */
57833
60399
  var HumiditySensorStatusSchema = object({
57834
60400
  /** Current relative humidity, 0..100. */
57835
- percent: number().min(0).max(100),
60401
+ percent: number().min(0).max(100).meta({
60402
+ unit: "%",
60403
+ label: "Humidity"
60404
+ }),
57836
60405
  /** Ms epoch when the slice was last updated. */
57837
60406
  lastFetchedAt: number(),
57838
60407
  /** Live display unit from the upstream source (e.g. HA
@@ -57874,7 +60443,12 @@ var humiditySensorCapability = {
57874
60443
  } } },
57875
60444
  /** Clock fields: written, but excluded from the compare that decides
57876
60445
  * whether persisting is worth a SQLite commit. */
57877
- volatileStateFields: ["lastFetchedAt"]
60446
+ volatileStateFields: ["lastFetchedAt"],
60447
+ customize: {
60448
+ version: 1,
60449
+ advanced: "derive",
60450
+ targets: []
60451
+ }
57878
60452
  };
57879
60453
  /**
57880
60454
  * Image display cap. Models a single still image exposed by an integration —
@@ -59356,6 +61930,38 @@ authKey: string().optional() }), object({
59356
61930
  /** Human-readable error when `ok: false`. */
59357
61931
  error: string().optional()
59358
61932
  }), { kind: "mutation" });
61933
+ /** Span override: start on a rising edge, end on a fall or this timeout. */
61934
+ var motionCustomize = {
61935
+ version: 1,
61936
+ targets: [{
61937
+ id: "detected",
61938
+ cardinality: "event",
61939
+ shape: "span",
61940
+ vocabulary: {
61941
+ cap: "motion",
61942
+ eventName: "onMotionChanged"
61943
+ },
61944
+ deviceTypes: [DeviceType.Camera],
61945
+ apply: "replace",
61946
+ applyAuthority: {
61947
+ kind: "camera-sensors",
61948
+ timeoutField: "motionCooldownMs"
61949
+ },
61950
+ eventName: "onMotionChanged",
61951
+ start: "rising-edge",
61952
+ end: "falling-edge-or-timeout",
61953
+ timeoutMs: 3e4,
61954
+ combine: "any",
61955
+ sourceModes: [
61956
+ "in-addition",
61957
+ "confirm",
61958
+ "replace"
61959
+ ],
61960
+ sources: [{ kind: "binary" }, { kind: "switch" }],
61961
+ sourceReport: { status: "assignment-status" },
61962
+ advancedExpression: false
61963
+ }]
61964
+ };
59359
61965
  var MotionStatusSchema = object({
59360
61966
  detected: boolean(),
59361
61967
  /** Ms epoch of the last detected-true observation. Null if never detected. */
@@ -59495,7 +62101,8 @@ onMotionChanged: { data: MotionOnMotionChangedDataSchema } },
59495
62101
  history: { fields: { detected: {
59496
62102
  kind: "boolean",
59497
62103
  excludeDeviceTypes: [DeviceType.Camera]
59498
- } } }
62104
+ } } },
62105
+ customize: motionCustomize
59499
62106
  };
59500
62107
  /**
59501
62108
  * Motion-trigger toggle for accessory devices.
@@ -61294,6 +63901,30 @@ includeCrops: boolean().optional() }).optional(), array(VehicleSchema).readonly(
61294
63901
  kind: "mutation",
61295
63902
  auth: "admin"
61296
63903
  });
63904
+ var CORE_ULTRA_265K_IGPU_CLOCK_MHZ = 2e3;
63905
+ var positiveOrNull = number().nullable().transform((value) => value !== null && Number.isFinite(value) && value > 0 ? value : null);
63906
+ var textOrNull = string().nullable().transform((value) => value !== null && value.trim() !== "" ? value : null);
63907
+ var PrecisionGopsSchema = object({
63908
+ int8: positiveOrNull,
63909
+ fp16: positiveOrNull
63910
+ });
63911
+ /** What one accelerator device reported. Every failed query is null. */
63912
+ var AcceleratorComputeSchema = object({
63913
+ deviceKey: string(),
63914
+ fullDeviceName: textOrNull,
63915
+ executionUnits: positiveOrNull,
63916
+ clockMHz: positiveOrNull,
63917
+ gops: PrecisionGopsSchema.nullable(),
63918
+ architecture: textOrNull,
63919
+ npuName: textOrNull,
63920
+ tops: positiveOrNull,
63921
+ vendor: textOrNull,
63922
+ webgpuArchitecture: textOrNull,
63923
+ webgpuDevice: textOrNull,
63924
+ computeUnits: positiveOrNull
63925
+ });
63926
+ object({ accelerators: array(AcceleratorComputeSchema).nullable() });
63927
+ 64 * CORE_ULTRA_265K_IGPU_CLOCK_MHZ;
61297
63928
  var ModelFormatSchema = _enum(MODEL_FORMATS);
61298
63929
  var HwAccelBackendInputSchema = _enum([
61299
63930
  "videotoolbox",
@@ -61407,7 +64038,12 @@ var HardwareInfoSchema = object({
61407
64038
  availableRAM_MB: number(),
61408
64039
  gpu: GpuInfoSchema.nullable(),
61409
64040
  npu: NpuInfoSchema.nullable(),
61410
- coral: CoralInfoSchema.nullable().optional()
64041
+ coral: CoralInfoSchema.nullable().optional(),
64042
+ /**
64043
+ * Per-accelerator compute (D930). Omitted by a node that has not probed it.
64044
+ * `null` fields inside an entry are a failed query, never a zero.
64045
+ */
64046
+ accelerators: array(AcceleratorComputeSchema).readonly().optional()
61411
64047
  });
61412
64048
  var PlatformScoreSchema = object({
61413
64049
  runtime: literal("python"),
@@ -61491,9 +64127,15 @@ method(_void(), PlatformCapabilitiesSchema), method(_void(), HardwareInfoSchema)
61491
64127
  */
61492
64128
  var PowerMeterStatusSchema = object({
61493
64129
  /** Instantaneous power draw in watts. */
61494
- watts: number().optional(),
64130
+ watts: number().optional().meta({
64131
+ unit: "W",
64132
+ label: "Power"
64133
+ }),
61495
64134
  /** Cumulative energy in kilowatt-hours since the meter was reset. */
61496
- kwhTotal: number().optional(),
64135
+ kwhTotal: number().optional().meta({
64136
+ unit: "kWh",
64137
+ label: "Energy"
64138
+ }),
61497
64139
  /** Voltage in volts. */
61498
64140
  volts: number().optional(),
61499
64141
  /** Current in amperes. */
@@ -61578,7 +64220,12 @@ var powerMeterCapability = {
61578
64220
  } },
61579
64221
  /** Clock fields: written, but excluded from the compare that decides
61580
64222
  * whether persisting is worth a SQLite commit. */
61581
- volatileStateFields: ["lastFetchedAt"]
64223
+ volatileStateFields: ["lastFetchedAt"],
64224
+ customize: {
64225
+ version: 1,
64226
+ advanced: "derive",
64227
+ targets: []
64228
+ }
61582
64229
  };
61583
64230
  /**
61584
64231
  * Presence cap. Models HA `person.*` and `device_tracker.*` entities
@@ -62023,9 +64670,9 @@ var PtzOptionsSchema = object({
62023
64670
  * Reolink preset 0, Hikvision preset '1', Dahua preset 1 -- and on this fleet
62024
64671
  * not one of the three cameras honours its own:
62025
64672
  *
62026
- * 592 Videocamera camera Daniel (reolink) preset 0 holds "stanza"
62027
- * 1438 Videocamera dispensa (hikvision) preset 1 holds "Credenza"
62028
- * 3836 Videocamera studio (amcrest) preset 1 holds "Preset1"
64673
+ * 107 Camera camera Carol (reolink) preset 0 holds "stanza"
64674
+ * 1438 Camera dispensa (hikvision) preset 1 holds "Credenza"
64675
+ * 3836 Camera studio (amcrest) preset 1 holds "Preset1"
62029
64676
  *
62030
64677
  * So `goHome` meant "go wherever the operator happened to save in slot 0 or 1",
62031
64678
  * and two of the three swallowed the failure in a bare `catch`. For autotrack
@@ -62350,6 +64997,126 @@ var ptzAutotrackCapability = {
62350
64997
  */
62351
64998
  history: "none"
62352
64999
  };
65000
+ var RUNNING_POWER_START_DELAY_MS = 3e4;
65001
+ var RUNNING_POWER_STOP_DELAY_MS = 18e4;
65002
+ var RunningStateSourceSchema = _enum(["native", "assigned"]);
65003
+ var RunningStateStatusSchema = object({
65004
+ /** null = unknown — never coerced to false (D393). */
65005
+ running: boolean().nullable(),
65006
+ /** Epoch ms the current boolean began; null while `running` is null. */
65007
+ since: number().nullable(),
65008
+ source: RunningStateSourceSchema.meta({ label: "Source" }),
65009
+ phase: string().nullable(),
65010
+ /** null until a reading has been published (D393). */
65011
+ lastFetchedAt: number().nullable()
65012
+ });
65013
+ var RunningFlipEventDataSchema = object({
65014
+ deviceId: number(),
65015
+ since: number().nullable(),
65016
+ phase: string().nullable()
65017
+ });
65018
+ var RUNNING_DEVICE_TYPES = Object.values(DeviceType);
65019
+ /** Generic Customize target for the running boolean (D936). */
65020
+ var runningCustomize = {
65021
+ version: 1,
65022
+ advanced: "derive",
65023
+ targets: [{
65024
+ id: "running",
65025
+ cardinality: "scalar",
65026
+ vocabulary: {
65027
+ cap: "running-state",
65028
+ stateField: "running"
65029
+ },
65030
+ deviceTypes: [
65031
+ DeviceType.Dishwasher,
65032
+ DeviceType.Vacuum,
65033
+ DeviceType.LawnMower,
65034
+ DeviceType.MediaPlayer,
65035
+ DeviceType.WaterHeater,
65036
+ DeviceType.Humidifier,
65037
+ DeviceType.Fan,
65038
+ DeviceType.Climate,
65039
+ DeviceType.Thermostat,
65040
+ DeviceType.PetFeeder
65041
+ ],
65042
+ apply: "add-or-replace",
65043
+ path: "running",
65044
+ sources: [
65045
+ {
65046
+ kind: "switch",
65047
+ transforms: [{ kind: "identity" }]
65048
+ },
65049
+ {
65050
+ kind: "binary",
65051
+ transforms: [{ kind: "identity" }, { kind: "invert" }]
65052
+ },
65053
+ {
65054
+ kind: "numeric",
65055
+ requiredUnit: "W",
65056
+ transforms: [{
65057
+ kind: "threshold",
65058
+ comparison: "gte",
65059
+ defaultThreshold: 5,
65060
+ defaultStartDwellMs: RUNNING_POWER_START_DELAY_MS,
65061
+ defaultStopDwellMs: RUNNING_POWER_STOP_DELAY_MS,
65062
+ thresholdUnit: "W"
65063
+ }]
65064
+ }
65065
+ ],
65066
+ companions: [
65067
+ {
65068
+ kind: "constant",
65069
+ path: "source",
65070
+ value: "assigned",
65071
+ when: "always"
65072
+ },
65073
+ {
65074
+ kind: "constant",
65075
+ path: "phase",
65076
+ value: null,
65077
+ when: "always"
65078
+ },
65079
+ {
65080
+ kind: "clock",
65081
+ path: "lastFetchedAt",
65082
+ when: "always"
65083
+ },
65084
+ {
65085
+ kind: "transition-time",
65086
+ path: "since",
65087
+ sourceChangedAt: "prefer"
65088
+ }
65089
+ ],
65090
+ sourceReport: {
65091
+ status: "assignment-status",
65092
+ runtimeField: "source",
65093
+ nativeValue: "native",
65094
+ assignedValue: "assigned"
65095
+ },
65096
+ advancedExpression: true
65097
+ }]
65098
+ };
65099
+ var runningStateCapability = {
65100
+ name: "running-state",
65101
+ scope: "device",
65102
+ deviceNative: true,
65103
+ mode: "singleton",
65104
+ deviceTypes: RUNNING_DEVICE_TYPES,
65105
+ methods: {},
65106
+ events: {
65107
+ onStarted: { data: RunningFlipEventDataSchema },
65108
+ onFinished: { data: RunningFlipEventDataSchema }
65109
+ },
65110
+ status: {
65111
+ schema: RunningStateStatusSchema,
65112
+ kind: "push"
65113
+ },
65114
+ runtimeState: RunningStateStatusSchema,
65115
+ durability: "restored",
65116
+ history: { fields: { running: { kind: "boolean" } } },
65117
+ volatileStateFields: ["lastFetchedAt"],
65118
+ customize: runningCustomize
65119
+ };
62353
65120
  DeviceType.Camera, DeviceType.Sensor, DeviceType.Switch, method(object({ deviceId: number().int().nonnegative() }), object({ success: literal(true) }), {
62354
65121
  kind: "mutation",
62355
65122
  auth: "admin"
@@ -62391,7 +65158,7 @@ var RecordingAvailabilitySchema = object({
62391
65158
  * would look identical. But the answer used to say nothing about that, so a
62392
65159
  * caller asking "what can I export?" read the single preferred profile as
62393
65160
  * the only one that exists — on this deployment every camera records `high`
62394
- * AND `low`, the low tree holding 14 GB for camera 615 alone, and the export
65161
+ * AND `low`, the low tree holding 14 GB for camera 101 alone, and the export
62395
65162
  * UI could not see it.
62396
65163
  *
62397
65164
  * Cheap: it is the same shallow directory read the profile CHOICE already
@@ -62490,7 +65257,7 @@ var RecordingSourceOptionsSchema = object({
62490
65257
  * `sparse` = gaps are the absence of one, and must be drawn as such.
62491
65258
  *
62492
65259
  * Not an onboard-only concession: measured 2026-09-24, OUR bar covers 98.8 %
62493
- * of 592's day and 1.2 % of 1436's. It is a fact about a (source, camera)
65260
+ * of 107's day and 1.2 % of 1436's. It is a fact about a (source, camera)
62494
65261
  * pair, and ours answers it per camera from `deriveRecordingMode`. */
62495
65262
  coverage: _enum(["continuous", "sparse"]),
62496
65263
  /** Where the playhead may be put.
@@ -62566,7 +65333,7 @@ DeviceType.Camera, method(object({ deviceId: number() }), array(RecordingSourceS
62566
65333
  * merely discouraged (D554 amended).
62567
65334
  *
62568
65335
  * It was learned the expensive way on `videoclips.listClips`: measured
62569
- * on the live hub 2026-09-20, device 592 bound to `recorder` AND
65336
+ * on the live hub 2026-09-20, device 107 bound to `recorder` AND
62570
65337
  * `provider-reolink`, a bare call with `limit: 3` answered SIX rows,
62571
65338
  * three from each source, merged — `device-collection-dispatch.ts`
62572
65339
  * leaves an unpinned fan-out un-narrowed, so absence buys the union the
@@ -63167,7 +65934,7 @@ var ExportSpeedSchema = number().min(.25).max(32);
63167
65934
  * on a 10 h window holding 29,393 s of footage every range landed late by the
63168
65935
  * gap accumulated before it — up to 6,607 s, well past EOF. Nothing matched,
63169
65936
  * the video was a uniform timelapse, and the log line reported the five ranges
63170
- * that had been ASKED for (2026-08-13, export `57d14363`, camera 615).
65937
+ * that had been ASKED for (2026-08-13, export `57d14363`, camera 101).
63171
65938
  *
63172
65939
  * Relative and not absolute epoch, because an absolute epoch would make every
63173
65940
  * call site responsible for the same subtraction.
@@ -63984,7 +66751,7 @@ getStatus: method(object({ deviceId: number() }), RecordingSignalStatusSchema) }
63984
66751
  * which put a "Scenes" tab on one camera's detail page. That is the wrong shape
63985
66752
  * for the thing: a scene is a standing question about the property ("is the bin
63986
66753
  * still out"), and the operator's question is "which of my scenes have tripped",
63987
- * across every camera at once — not "what does camera 617 think". Buried one
66754
+ * across every camera at once — not "what does camera 102 think". Buried one
63988
66755
  * camera deep it also could not be found. The surface is now a top-level admin
63989
66756
  * page (`/scenes`, `pages/Scenes.tsx`) that lists every scene on every camera and
63990
66757
  * picks the camera inside the create flow, the same shape Events and Faces have.
@@ -64433,7 +67200,20 @@ var ZoneRuleSchema = object({
64433
67200
  * Defaults to `true` so operators creating a rule via the UI
64434
67201
  * see it active immediately.
64435
67202
  */
64436
- enabled: boolean().default(true)
67203
+ enabled: boolean().default(true),
67204
+ /**
67205
+ * Package stage only. When true, a package candidate may open from a
67206
+ * scene difference in this rule's zone after a person leaves. The
67207
+ * package model, when it boxes something overlapping, is extra evidence
67208
+ * and is not the gate. Absent or false keeps today's model path.
67209
+ */
67210
+ detectBySceneDifference: boolean().optional(),
67211
+ /**
67212
+ * Package stage only. When true, a promoted package is shown to the
67213
+ * `llm` cap before the delivery event is emitted. Absent or false emits
67214
+ * as today. Usable with or without `detectBySceneDifference`.
67215
+ */
67216
+ confirmWithLlm: boolean().optional()
64437
67217
  });
64438
67218
  array(ZoneRuleSchema).readonly();
64439
67219
  /**
@@ -65028,7 +67808,7 @@ function buildStreamParamsConfigSchema(options, status) {
65028
67808
  * `getSettingsUISchema()` surface.
65029
67809
  */
65030
67810
  var SwitchStatusSchema = object({
65031
- on: boolean(),
67811
+ on: boolean().meta({ label: "On" }),
65032
67812
  /** Ms epoch of the last state change. Useful for UI "X minutes ago". */
65033
67813
  lastChangedAt: number()
65034
67814
  });
@@ -65087,7 +67867,12 @@ var switchCapability = {
65087
67867
  label: "On",
65088
67868
  kind: "boolean"
65089
67869
  }
65090
- }] }
67870
+ }] },
67871
+ customize: {
67872
+ version: 1,
67873
+ advanced: "derive",
67874
+ targets: []
67875
+ }
65091
67876
  };
65092
67877
  /** C0 controls, DEL and the C1 range: none of them belongs in a name. */
65093
67878
  function hasControlCharacter(value) {
@@ -65683,7 +68468,10 @@ var tamperCapability = {
65683
68468
  */
65684
68469
  var TemperatureSensorStatusSchema = object({
65685
68470
  /** Current temperature in Celsius. */
65686
- celsius: number(),
68471
+ celsius: number().meta({
68472
+ unit: "°C",
68473
+ label: "Temperature"
68474
+ }),
65687
68475
  /** Ms epoch when the slice was last updated (push or poll). */
65688
68476
  lastFetchedAt: number(),
65689
68477
  /** Live display unit from the upstream source (e.g. HA
@@ -65726,7 +68514,12 @@ var temperatureSensorCapability = {
65726
68514
  } } },
65727
68515
  /** Clock fields: written, but excluded from the compare that decides
65728
68516
  * whether persisting is worth a SQLite commit. */
65729
- volatileStateFields: ["lastFetchedAt"]
68517
+ volatileStateFields: ["lastFetchedAt"],
68518
+ customize: {
68519
+ version: 1,
68520
+ advanced: "derive",
68521
+ targets: []
68522
+ }
65730
68523
  };
65731
68524
  /**
65732
68525
  * toast — system-scoped singleton capability that streams toast
@@ -66989,7 +69782,7 @@ method(object({}), array(TrainingProviderDescriptorSchema).readonly(), { auth: "
66989
69782
  * - **Jobs.** A persisted state machine, a reconcile loop against the
66990
69783
  * provider, a cost guard, a daily orphan sweep and the retention rules.
66991
69784
  * - **The return flow.** Verified artefacts → Model Studio
66992
- * (`custom-model-registry.importModelBundle`) → canary on cameras →
69785
+ * (`custom-model-registry.importModelBundle`) → canary on accelerators →
66993
69786
  * rollback. Nothing is ever registered automatically.
66994
69787
  *
66995
69788
  * Plan/start takes a live {@link TrainingCorpusSelection} (collections +
@@ -67126,20 +69919,24 @@ var TrainingProgressPointSchema = object({
67126
69919
  map50: number().nullable(),
67127
69920
  map50_95: number().nullable()
67128
69921
  });
69922
+ /** One accelerator: a `(node, inference device)` that runs the root detector. */
69923
+ var TrainingAcceleratorRefSchema = object({
69924
+ nodeId: string(),
69925
+ deviceKey: string()
69926
+ });
69927
+ /**
69928
+ * A canary pins the registered model on chosen ACCELERATORS — a model is
69929
+ * chosen by the accelerator that runs it (D927); every camera balanced onto
69930
+ * one runs it. `previous` is the root-detector pin each one had (`null` = it
69931
+ * ran its default), exactly, so rollback restores it.
69932
+ */
67129
69933
  var TrainingCanarySchema = object({
67130
- deviceIds: array(number().int()).readonly(),
69934
+ accelerators: array(TrainingAcceleratorRefSchema).readonly(),
67131
69935
  since: number(),
67132
- /** Every override the canary replaced, exactly, so rollback restores it. */
67133
- previous: array(object({
67134
- deviceId: number().int(),
67135
- nodeId: string(),
67136
- deviceKey: string(),
67137
- patch: object({
67138
- modelId: string().optional(),
67139
- settings: record(string(), unknown()).readonly().optional()
67140
- }).nullable()
67141
- })).readonly()
69936
+ previous: array(TrainingAcceleratorRefSchema.extend({ modelId: string().nullable() })).readonly()
67142
69937
  });
69938
+ /** An accelerator a canary may pin: it runs the root detector, on this model now. */
69939
+ var TrainingCanaryTargetSchema = TrainingAcceleratorRefSchema.extend({ pinnedModelId: string().nullable() });
67143
69940
  var TrainingJobSchema = object({
67144
69941
  id: string(),
67145
69942
  idempotencyKey: string(),
@@ -67251,11 +70048,11 @@ method(object({}), array(TrainingBaseModelSchema).readonly(), { auth: "admin" })
67251
70048
  kind: "mutation",
67252
70049
  auth: "admin",
67253
70050
  timeoutMs: 12e4
67254
- }), method(IdInput, TrainingResultSchema.nullable(), { auth: "admin" }), method(IdInput.extend({ canaryDeviceIds: array(number().int()).readonly() }), TrainingJobSchema, {
70051
+ }), method(IdInput, TrainingResultSchema.nullable(), { auth: "admin" }), method(_void(), array(TrainingCanaryTargetSchema).readonly(), { auth: "admin" }), method(IdInput.extend({ canaryAccelerators: array(TrainingAcceleratorRefSchema).readonly() }), TrainingJobSchema, {
67255
70052
  kind: "mutation",
67256
70053
  auth: "admin",
67257
70054
  timeoutMs: 30 * 6e4
67258
- }), method(IdInput.extend({ deviceIds: array(number().int()).min(1).readonly() }), TrainingJobSchema, {
70055
+ }), method(IdInput.extend({ accelerators: array(TrainingAcceleratorRefSchema).min(1).readonly() }), TrainingJobSchema, {
67259
70056
  kind: "mutation",
67260
70057
  auth: "admin",
67261
70058
  timeoutMs: 12e4
@@ -67401,6 +70198,10 @@ function withClipEventLabels(provider, deps) {
67401
70198
  };
67402
70199
  }
67403
70200
  SOURCE_CAPS.filter((cap) => cap !== "switch" && cap !== "motion");
70201
+ 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;
70202
+ String.raw`rose\(active(\d+), changed(\d+), (\d+(?:\.\d+)?)\)`;
70203
+ DeviceRole.BinarySensor, DeviceRole.MotionSensor;
70204
+ new Set(CAP_NAMES);
67404
70205
  Object.freeze({
67405
70206
  person: .5,
67406
70207
  vehicle: .5,
@@ -67751,6 +70552,7 @@ var DEVICE_LOCAL_STATE_CAPS = {
67751
70552
  ptzAutotrack: ptzAutotrackCapability,
67752
70553
  recordingOnboard: recordingOnboardCapability,
67753
70554
  recordingSignal: recordingSignalCapability,
70555
+ runningState: runningStateCapability,
67754
70556
  sceneMonitor: sceneMonitorCapability,
67755
70557
  scriptRunner: scriptRunnerCapability,
67756
70558
  smoke: smokeCapability,
@@ -68633,7 +71435,7 @@ var BaseDeviceProvider = class extends BaseAddon {
68633
71435
  * A top-level persisted row with NO configuration is a leftover, not a
68634
71436
  * device — quarantine it instead of dialling it.
68635
71437
  *
68636
- * Device 614 was deleted, resurrected as a config-less shell by a write
71438
+ * Device 105 was deleted, resurrected as a config-less shell by a write
68637
71439
  * already in flight (D376), and then dialled at every single boot: eight
68638
71440
  * `Failed to restore device — bounded retry scheduled` lines in one day,
68639
71441
  * each one the same Zod refusal on `host` and `password`. The bound was
@@ -71947,6 +74749,27 @@ Object.freeze({
71947
74749
  access: "create",
71948
74750
  role: "viewer"
71949
74751
  },
74752
+ "displayPalette.getPalette": {
74753
+ capName: "display-palette",
74754
+ capScope: "system",
74755
+ addonId: null,
74756
+ access: "view",
74757
+ role: "viewer"
74758
+ },
74759
+ "displayPalette.listPresets": {
74760
+ capName: "display-palette",
74761
+ capScope: "system",
74762
+ addonId: null,
74763
+ access: "view",
74764
+ role: "viewer"
74765
+ },
74766
+ "displayPalette.setPalette": {
74767
+ capName: "display-palette",
74768
+ capScope: "system",
74769
+ addonId: null,
74770
+ access: "create",
74771
+ role: "admin"
74772
+ },
71950
74773
  "doorbell.getStatus": {
71951
74774
  capName: "doorbell",
71952
74775
  capScope: "device",
@@ -74866,20 +77689,6 @@ Object.freeze({
74866
77689
  access: "create",
74867
77690
  role: "admin"
74868
77691
  },
74869
- "pipelineExecutor.clearDeviceOverrides": {
74870
- capName: "pipeline-executor",
74871
- capScope: "system",
74872
- addonId: null,
74873
- access: "delete",
74874
- role: "admin"
74875
- },
74876
- "pipelineExecutor.clearModelBoundDeviceOverrides": {
74877
- capName: "pipeline-executor",
74878
- capScope: "system",
74879
- addonId: null,
74880
- access: "delete",
74881
- role: "admin"
74882
- },
74883
77692
  "pipelineExecutor.deleteModel": {
74884
77693
  capName: "pipeline-executor",
74885
77694
  capScope: "system",
@@ -74922,13 +77731,6 @@ Object.freeze({
74922
77731
  access: "view",
74923
77732
  role: "admin"
74924
77733
  },
74925
- "pipelineExecutor.getDefaultSteps": {
74926
- capName: "pipeline-executor",
74927
- capScope: "system",
74928
- addonId: null,
74929
- access: "view",
74930
- role: "admin"
74931
- },
74932
77734
  "pipelineExecutor.getDetectionConfigSchema": {
74933
77735
  capName: "pipeline-executor",
74934
77736
  capScope: "system",
@@ -74950,20 +77752,6 @@ Object.freeze({
74950
77752
  access: "view",
74951
77753
  role: "admin"
74952
77754
  },
74953
- "pipelineExecutor.getGlobalPipelineConfig": {
74954
- capName: "pipeline-executor",
74955
- capScope: "system",
74956
- addonId: null,
74957
- access: "view",
74958
- role: "admin"
74959
- },
74960
- "pipelineExecutor.getGlobalSteps": {
74961
- capName: "pipeline-executor",
74962
- capScope: "system",
74963
- addonId: null,
74964
- access: "view",
74965
- role: "admin"
74966
- },
74967
77755
  "pipelineExecutor.getInferenceDeviceHealth": {
74968
77756
  capName: "pipeline-executor",
74969
77757
  capScope: "system",
@@ -75223,13 +78011,6 @@ Object.freeze({
75223
78011
  access: "view",
75224
78012
  role: "admin"
75225
78013
  },
75226
- "pipelineOrchestrator.getCameraStepOverrides": {
75227
- capName: "pipeline-orchestrator",
75228
- capScope: "system",
75229
- addonId: null,
75230
- access: "view",
75231
- role: "admin"
75232
- },
75233
78014
  "pipelineOrchestrator.getCameraSwitches": {
75234
78015
  capName: "pipeline-orchestrator",
75235
78016
  capScope: "system",
@@ -75468,13 +78249,6 @@ Object.freeze({
75468
78249
  access: "create",
75469
78250
  role: "admin"
75470
78251
  },
75471
- "pipelineOrchestrator.setCameraPipelineForAgent": {
75472
- capName: "pipeline-orchestrator",
75473
- capScope: "system",
75474
- addonId: null,
75475
- access: "create",
75476
- role: "admin"
75477
- },
75478
78252
  "pipelineOrchestrator.setCameraSensors": {
75479
78253
  capName: "pipeline-orchestrator",
75480
78254
  capScope: "system",
@@ -75482,42 +78256,42 @@ Object.freeze({
75482
78256
  access: "create",
75483
78257
  role: "admin"
75484
78258
  },
75485
- "pipelineOrchestrator.setCameraStepOverride": {
78259
+ "pipelineOrchestrator.setCameraStepSettings": {
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.setCameraStepSettings": {
78266
+ "pipelineOrchestrator.setCameraStepToggle": {
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.setCameraStepToggle": {
78273
+ "pipelineOrchestrator.setCameraSwitch": {
75500
78274
  capName: "pipeline-orchestrator",
75501
78275
  capScope: "system",
75502
78276
  addonId: null,
75503
78277
  access: "create",
75504
78278
  role: "admin"
75505
78279
  },
75506
- "pipelineOrchestrator.setCameraSwitch": {
78280
+ "pipelineOrchestrator.setCapabilityBinding": {
75507
78281
  capName: "pipeline-orchestrator",
75508
78282
  capScope: "system",
75509
78283
  addonId: null,
75510
78284
  access: "create",
75511
78285
  role: "admin"
75512
78286
  },
75513
- "pipelineOrchestrator.setCapabilityBinding": {
78287
+ "pipelineOrchestrator.setLoadBalancingShares": {
75514
78288
  capName: "pipeline-orchestrator",
75515
78289
  capScope: "system",
75516
78290
  addonId: null,
75517
78291
  access: "create",
75518
78292
  role: "admin"
75519
78293
  },
75520
- "pipelineOrchestrator.setLoadBalancingShares": {
78294
+ "pipelineOrchestrator.setNodeStepSettings": {
75521
78295
  capName: "pipeline-orchestrator",
75522
78296
  capScope: "system",
75523
78297
  addonId: null,
@@ -76546,6 +79320,13 @@ Object.freeze({
76546
79320
  access: "create",
76547
79321
  role: "admin"
76548
79322
  },
79323
+ "runningState.getStatus": {
79324
+ capName: "running-state",
79325
+ capScope: "device",
79326
+ addonId: null,
79327
+ access: "view",
79328
+ role: "viewer"
79329
+ },
76549
79330
  "sceneMonitor.captureReference": {
76550
79331
  capName: "scene-monitor",
76551
79332
  capScope: "device",
@@ -77876,6 +80657,13 @@ Object.freeze({
77876
80657
  access: "view",
77877
80658
  role: "admin"
77878
80659
  },
80660
+ "training.listCanaryTargets": {
80661
+ capName: "training",
80662
+ capScope: "system",
80663
+ addonId: null,
80664
+ access: "view",
80665
+ role: "admin"
80666
+ },
77879
80667
  "training.listJobs": {
77880
80668
  capName: "training",
77881
80669
  capScope: "system",
@@ -81253,6 +84041,32 @@ var APPLIANCE_CAP_VOCABULARY = {
81253
84041
  }],
81254
84042
  events: { onSent: { notOperatorFacing: "a delivery receipt of a send this system made — not a fact about the world" } }
81255
84043
  },
84044
+ "running-state": {
84045
+ scope: "device",
84046
+ noun: t("Running", "In funzione"),
84047
+ state: [{
84048
+ kind: "boolean",
84049
+ field: "running",
84050
+ label: t("Running", "In funzione"),
84051
+ whenTrue: t("When {device} starts", "Quando {device} inizia"),
84052
+ whenFalse: t("When {device} finishes", "Quando {device} finisce"),
84053
+ icon: "play"
84054
+ }],
84055
+ events: {
84056
+ onStarted: {
84057
+ category: EventCategory.RunningStarted,
84058
+ label: t("Started running", "Ha iniziato a funzionare"),
84059
+ phrase: t("When {device} starts running", "Quando {device} inizia a funzionare"),
84060
+ icon: "play"
84061
+ },
84062
+ onFinished: {
84063
+ category: EventCategory.RunningFinished,
84064
+ label: t("Finished", "Ha finito"),
84065
+ phrase: t("When {device} finishes", "Quando {device} finisce"),
84066
+ icon: "square"
84067
+ }
84068
+ }
84069
+ },
81256
84070
  update: {
81257
84071
  scope: "device",
81258
84072
  noun: t("Firmware update", "Aggiornamento firmware"),
@@ -81873,7 +84687,7 @@ var SENSOR_CAP_VOCABULARY = {
81873
84687
  state: [{
81874
84688
  kind: "boolean",
81875
84689
  field: "on",
81876
- label: t("Active", "Attivo"),
84690
+ label: t("On", "Acceso"),
81877
84691
  whenTrue: t("When {device} turns active", "Quando {device} si attiva"),
81878
84692
  whenFalse: t("When {device} turns inactive", "Quando {device} si disattiva"),
81879
84693
  icon: "toggle-right"
@@ -82412,6 +85226,7 @@ var SYSTEM_CAP_VOCABULARY = {
82412
85226
  "device-provider": system(INTERNAL),
82413
85227
  "device-removal-hook": system(INTERNAL),
82414
85228
  "device-state": system("the runtime-state mirror every trigger already reads through"),
85229
+ "display-palette": system("the cluster display palette — one colour table for every client, not a device action"),
82415
85230
  "embedding-encoder": system(ML),
82416
85231
  "face-gallery": system("the face gallery — curated on its own page"),
82417
85232
  "failure-contribution": system(INTERNAL),
@@ -84468,11 +87283,6 @@ Object.freeze({
84468
87283
  form: "single",
84469
87284
  optional: false
84470
87285
  }],
84471
- "pipelineExecutor.clearModelBoundDeviceOverrides": [{
84472
- name: "deviceIds",
84473
- form: "array",
84474
- optional: true
84475
- }],
84476
87286
  "pipelineExecutor.runPipeline": [{
84477
87287
  name: "deviceId",
84478
87288
  form: "single",
@@ -84528,11 +87338,6 @@ Object.freeze({
84528
87338
  form: "array",
84529
87339
  optional: true
84530
87340
  }],
84531
- "pipelineOrchestrator.getCameraStepOverrides": [{
84532
- name: "deviceId",
84533
- form: "single",
84534
- optional: false
84535
- }],
84536
87341
  "pipelineOrchestrator.getCameraSwitches": [{
84537
87342
  name: "deviceId",
84538
87343
  form: "single",
@@ -84573,21 +87378,11 @@ Object.freeze({
84573
87378
  form: "single",
84574
87379
  optional: false
84575
87380
  }],
84576
- "pipelineOrchestrator.setCameraPipelineForAgent": [{
84577
- name: "deviceId",
84578
- form: "single",
84579
- optional: false
84580
- }],
84581
87381
  "pipelineOrchestrator.setCameraSensors": [{
84582
87382
  name: "deviceId",
84583
87383
  form: "single",
84584
87384
  optional: false
84585
87385
  }],
84586
- "pipelineOrchestrator.setCameraStepOverride": [{
84587
- name: "deviceId",
84588
- form: "single",
84589
- optional: false
84590
- }],
84591
87386
  "pipelineOrchestrator.setCameraStepSettings": [{
84592
87387
  name: "deviceId",
84593
87388
  form: "single",
@@ -85019,6 +87814,11 @@ Object.freeze({
85019
87814
  form: "single",
85020
87815
  optional: true
85021
87816
  }],
87817
+ "runningState.getStatus": [{
87818
+ name: "deviceId",
87819
+ form: "single",
87820
+ optional: false
87821
+ }],
85022
87822
  "sceneMonitor.captureReference": [{
85023
87823
  name: "deviceId",
85024
87824
  form: "single",
@@ -85265,11 +88065,6 @@ Object.freeze({
85265
88065
  form: "single",
85266
88066
  optional: false
85267
88067
  }],
85268
- "training.canaryResult": [{
85269
- name: "deviceIds",
85270
- form: "array",
85271
- optional: false
85272
- }],
85273
88068
  "update.getStatus": [{
85274
88069
  name: "deviceId",
85275
88070
  form: "single",
@@ -85522,6 +88317,94 @@ Object.freeze({
85522
88317
  "smtp-provider": "email"
85523
88318
  });
85524
88319
  DeviceType.Camera;
88320
+ /**
88321
+ * A saved Customize assignment (D936). The schema is the type: callers use
88322
+ * `z.infer`, they do not restate the shape.
88323
+ */
88324
+ var OverrideSourceSchema = object({
88325
+ addonId: string().min(1),
88326
+ stableId: string().min(1),
88327
+ cap: string().min(1),
88328
+ fieldPath: string().min(1)
88329
+ });
88330
+ var CustomizeTransformDraftSchema = discriminatedUnion("kind", [
88331
+ object({ kind: literal("identity") }),
88332
+ object({ kind: literal("invert") }),
88333
+ object({
88334
+ kind: literal("threshold"),
88335
+ comparison: _enum(["gte", "lte"]),
88336
+ threshold: number(),
88337
+ startDwellMs: number().nonnegative(),
88338
+ stopDwellMs: number().nonnegative()
88339
+ }),
88340
+ object({
88341
+ kind: literal("linear"),
88342
+ scale: number(),
88343
+ offset: number(),
88344
+ clampMin: number().optional(),
88345
+ clampMax: number().optional()
88346
+ }),
88347
+ object({
88348
+ kind: literal("enum-map"),
88349
+ mapping: record(string(), string().nullable())
88350
+ }),
88351
+ object({ kind: literal("number") })
88352
+ ]);
88353
+ var ScalarOverrideDraftSchema = object({
88354
+ kind: literal("scalar"),
88355
+ cap: string().min(1),
88356
+ targetId: string().min(1),
88357
+ source: OverrideSourceSchema,
88358
+ transform: CustomizeTransformDraftSchema
88359
+ });
88360
+ var KeyedArrayOverrideDraftSchema = object({
88361
+ kind: literal("keyedArray"),
88362
+ cap: string().min(1),
88363
+ targetId: string().min(1),
88364
+ key: string().min(1),
88365
+ label: string().min(1),
88366
+ fieldPath: string().min(1),
88367
+ source: OverrideSourceSchema,
88368
+ transform: CustomizeTransformDraftSchema
88369
+ });
88370
+ var PulseOverrideDraftSchema = object({
88371
+ kind: literal("pulse"),
88372
+ cap: string().min(1),
88373
+ targetId: string().min(1),
88374
+ enabled: boolean(),
88375
+ debounceMs: number().nonnegative(),
88376
+ sources: array(OverrideSourceSchema).min(1)
88377
+ });
88378
+ var SpanSourceDraftSchema = OverrideSourceSchema.extend({ mode: _enum([
88379
+ "in-addition",
88380
+ "confirm",
88381
+ "replace"
88382
+ ]).optional() });
88383
+ discriminatedUnion("kind", [
88384
+ ScalarOverrideDraftSchema,
88385
+ KeyedArrayOverrideDraftSchema,
88386
+ PulseOverrideDraftSchema,
88387
+ object({
88388
+ kind: literal("span"),
88389
+ cap: string().min(1),
88390
+ targetId: string().min(1),
88391
+ timeoutMs: number().nonnegative(),
88392
+ cooldownMs: number().nonnegative().optional(),
88393
+ sources: array(SpanSourceDraftSchema)
88394
+ })
88395
+ ]);
88396
+ object({
88397
+ targetId: string().min(1),
88398
+ configured: boolean(),
88399
+ source: _enum(["native", "assigned"]),
88400
+ state: _enum([
88401
+ "active",
88402
+ "stale",
88403
+ "released",
88404
+ "unavailable"
88405
+ ]),
88406
+ reason: string().nullable()
88407
+ });
85525
88408
  var G711_SCALE_CORRECTION_DB = {
85526
88409
  PCMU: 20 * Math.log10(4),
85527
88410
  PCMA: 20 * Math.log10(8)
@@ -85574,40 +88457,7 @@ var NC_AUDIO_DEFAULTS = {
85574
88457
  samplingSeconds: 10
85575
88458
  };
85576
88459
  new Set(["devices", "classes"]);
85577
- /**
85578
- * WHICH narrowing filter speaks about WHICH system-event kind — one predicate,
85579
- * consumed by the rule ENGINE and by every rule EDITOR.
85580
- *
85581
- * ── The failure this file exists for ───────────────────────────────────────
85582
- * `NcSystemEventConditionSchema` carries four optional narrowing lists
85583
- * (`deviceIds`, `deviceTypes`, `nodeIds`, `packageNames`) beside a required
85584
- * `kinds` gate. They are not four filters over one vocabulary: each belongs to
85585
- * a FAMILY of kinds and is meaningless outside it. A node going away has no
85586
- * device type; a completed export has no package; `stream-offline` deliberately
85587
- * carries no device type at all (a stream belongs to a camera by construction).
85588
- *
85589
- * The engine applied all four to every kind, so a filter from one family failed
85590
- * a kind from another family CLOSED. The operator's live rule "Eventi di
85591
- * sistema" selected eleven kinds and set `deviceTypes: ['camera']` — the only
85592
- * way to say "only my cameras" about the two liveness kinds — and NINE of the
85593
- * eleven silently stopped being deliverable. Four days of history contained
85594
- * `device-online` and `device-offline` and nothing else, across a window in
85595
- * which agents were restarted and addons were updated.
85596
- *
85597
- * Both editors already computed this scoping, to decide which filter boxes to
85598
- * render; the cap's own docblock already promised it ("Narrow a `device-*` kind
85599
- * to these device TYPES"). Only the engine disagreed, and it disagreed in the
85600
- * destructive direction. So the rule is stated ONCE, here, and the engine and
85601
- * the editors are readers of it rather than three independent authors.
85602
- *
85603
- * ── The direction ─────────────────────────────────────────────────────────
85604
- * Out of family ⇒ the filter is IGNORED, never fail-closed. An editor that
85605
- * hides a box has already told the operator this filter does not speak about
85606
- * these kinds, so honouring it as an exclusion contradicts the only
85607
- * explanation the operator was ever given. Inside its family the filter still
85608
- * narrows, and still fails CLOSED on a subject that cannot produce the identity
85609
- * it tests (a device the mirror cannot name is not evidence of a camera).
85610
- */
88460
+ new Set(NC_LEGACY_SYSTEM_EVENT_KINDS);
85611
88461
  /**
85612
88462
  * Every filter, for the callers that must cover all of them (guards, tests).
85613
88463
  *
@@ -85633,9 +88483,6 @@ new Map(Object.entries({
85633
88483
  "device-battery-normal": "device-events",
85634
88484
  "device-consumable-low": "device-events",
85635
88485
  "device-consumable-normal": "device-events",
85636
- "device-tank-low": "device-events",
85637
- "device-tank-full": "device-events",
85638
- "device-tank-normal": "device-events",
85639
88486
  "stream-online": "device-events",
85640
88487
  "stream-offline": "device-events",
85641
88488
  "detection-blind": "device-events",
@@ -85712,16 +88559,6 @@ var NC_SYSTEM_EVENT_KIND_GROUP_SPECS = [
85712
88559
  label: "Consumables",
85713
88560
  kinds: ["device-consumable-low", "device-consumable-normal"]
85714
88561
  },
85715
- {
85716
- id: "tanks",
85717
- family: "device-events",
85718
- label: "Tanks",
85719
- kinds: [
85720
- "device-tank-low",
85721
- "device-tank-full",
85722
- "device-tank-normal"
85723
- ]
85724
- },
85725
88562
  {
85726
88563
  id: "detection-blind",
85727
88564
  family: "device-events",
@@ -85879,11 +88716,6 @@ var RULE_BODY_ONLY = ["body"];
85879
88716
  var RULE_TEXT = ["title", "body"];
85880
88717
  var BATTERY = ["device-battery-low", "device-battery-normal"];
85881
88718
  var CONSUMABLE = ["device-consumable-low", "device-consumable-normal"];
85882
- var TANK = [
85883
- "device-tank-low",
85884
- "device-tank-full",
85885
- "device-tank-normal"
85886
- ];
85887
88719
  var ALERT_EPISODE = [
85888
88720
  "alert-critical",
85889
88721
  "alert-error",
@@ -85915,7 +88747,6 @@ var DEVICE_EVENTS = [
85915
88747
  "device-enabled",
85916
88748
  ...BATTERY,
85917
88749
  ...CONSUMABLE,
85918
- ...TANK,
85919
88750
  "stream-online",
85920
88751
  "stream-offline",
85921
88752
  "detection-blind",
@@ -85946,7 +88777,7 @@ var STATE_SUMMARY_SECTION_VARS = [
85946
88777
  {
85947
88778
  name: "summaryStreams",
85948
88779
  label: "Summary: streams offline",
85949
- example: "Ingresso (high) — since 06:40",
88780
+ example: "Front door (high) — since 06:40",
85950
88781
  kinds: ["stream-offline", "stream-online"]
85951
88782
  },
85952
88783
  {
@@ -85961,22 +88792,16 @@ var STATE_SUMMARY_SECTION_VARS = [
85961
88792
  example: "Robot — filter 10 %",
85962
88793
  kinds: CONSUMABLE
85963
88794
  },
85964
- {
85965
- name: "summaryTanks",
85966
- label: "Summary: tanks",
85967
- example: "Robot — clean water low",
85968
- kinds: TANK
85969
- },
85970
88795
  {
85971
88796
  name: "summaryDetection",
85972
88797
  label: "Summary: cameras detecting nothing",
85973
- example: "Ingresso — since 05:10",
88798
+ example: "Front door — since 05:10",
85974
88799
  kinds: ["detection-blind"]
85975
88800
  },
85976
88801
  {
85977
88802
  name: "summaryNodes",
85978
88803
  label: "Summary: nodes",
85979
- example: "little-unraid — offline since 03:00",
88804
+ example: "agent-a — offline since 03:00",
85980
88805
  kinds: [
85981
88806
  "node-offline",
85982
88807
  "node-online",
@@ -86082,8 +88907,7 @@ var STATE_SUMMARY_VARS = [
86082
88907
  ([...RULE_TEXT], [...COMBINED_ALARM]),
86083
88908
  ([...RULE_TEXT], [...DEVICE_EVENTS]),
86084
88909
  ([...RULE_TEXT], [...BATTERY, ...CONSUMABLE]),
86085
- ([...RULE_TEXT], [...CONSUMABLE, ...TANK]),
86086
- ([...RULE_TEXT], [...TANK]),
88910
+ ([...RULE_TEXT], [...CONSUMABLE]),
86087
88911
  [...RULE_TEXT],
86088
88912
  ([...RULE_TEXT], [...UPDATES, ...ALERT_EPISODE]),
86089
88913
  ([...RULE_TEXT], [...UPDATES, ...ALERT_EPISODE]),
@@ -86187,15 +89011,6 @@ new Map([
86187
89011
  snapshotLabel: "Consumables low now",
86188
89012
  snapshotSection: "consumables"
86189
89013
  },
86190
- {
86191
- id: "tanks",
86192
- family: "device-events",
86193
- label: "Tanks (low or full / back to normal)",
86194
- bad: ["device-tank-low", "device-tank-full"],
86195
- recovery: ["device-tank-normal"],
86196
- snapshotLabel: "Tanks low or full now",
86197
- snapshotSection: "tanks"
86198
- },
86199
89014
  {
86200
89015
  id: "motion-noise",
86201
89016
  family: "device-events",
@@ -86648,6 +89463,10 @@ MotionOnMotionChangedDataSchema.omit({ triggeredBy: true });
86648
89463
  function providerMotionEvent(source, data) {
86649
89464
  return createEvent(EventCategory.ProviderMotion, source, data);
86650
89465
  }
89466
+ Object.freeze({
89467
+ person: .8,
89468
+ vehicle: .8
89469
+ });
86651
89470
  object({
86652
89471
  /**
86653
89472
  * Fraction of the box's own size added on EACH side before cutting.
@@ -88787,7 +91606,7 @@ var amcrestCameraSchema = object({
88787
91606
  *
88788
91607
  * Empty = nothing configured, and `goHome` then REFUSES. It used to go to a
88789
91608
  * hardcoded slot on a vendor "convention" this fleet contradicts: reolink
88790
- * went to preset 0, which on device 592 holds "stanza"; amcrest went to
91609
+ * went to preset 0, which on device 107 holds "stanza"; amcrest went to
88791
91610
  * preset 1, which on device 3836 holds "Preset1". Both swallowed the failure
88792
91611
  * in a bare catch, so a head that never moved was indistinguishable from a
88793
91612
  * head that went home.