@camstack/addon-provider-reolink 1.2.207 → 1.2.208

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (3) hide show
  1. package/dist/addon.js +1170 -379
  2. package/dist/addon.mjs +1170 -379
  3. package/package.json +1 -1
package/dist/addon.mjs CHANGED
@@ -28,7 +28,7 @@ import { URL as URL$1 } from "url";
28
28
  import { spawn as spawn$1 } from "node:child_process";
29
29
  import os, { tmpdir } from "node:os";
30
30
  import { createReadStream } from "node:fs";
31
- //#region ../types/dist/event-category-BfJwUd2S.mjs
31
+ //#region ../types/dist/event-category-Ceif8n-v.mjs
32
32
  var EventCategory = /* @__PURE__ */ function(EventCategory) {
33
33
  EventCategory["SystemBoot"] = "system.boot";
34
34
  EventCategory["SystemAddonsReady"] = "system.addons-ready";
@@ -355,9 +355,8 @@ var EventCategory = /* @__PURE__ */ function(EventCategory) {
355
355
  EventCategory["PipelineMotionCalm"] = "pipeline.motion-calm";
356
356
  /**
357
357
  * Per-camera pipeline config was mutated by the orchestrator
358
- * (3-level settings change via `setAgentAddonDefaults` /
359
- * `setCameraStepToggle` / `setCameraPipelineForAgent` or a
360
- * pipeline-scoped `applyDeviceSettingsPatch`). Orchestrator
358
+ * (a settings change via `setAgentInferenceDevices` /
359
+ * `setCameraStepToggle` / `setCameraStepSettings`). Orchestrator
361
360
  * subscribes to its own emission to hot-reload the assigned runner
362
361
  * via `attachCamera` so the next frame executes against the new
363
362
  * engine/steps without waiting for a rebalance or the next
@@ -501,6 +500,10 @@ var EventCategory = /* @__PURE__ */ function(EventCategory) {
501
500
  * on the device detail page.
502
501
  */
503
502
  EventCategory["DoorbellOnPressed"] = "doorbell.onPressed";
503
+ /** Mirrors `runningStateCapability.events.onStarted`. */
504
+ EventCategory["RunningStarted"] = "running.started";
505
+ /** Mirrors `runningStateCapability.events.onFinished`. */
506
+ EventCategory["RunningFinished"] = "running.finished";
504
507
  /**
505
508
  * Cap event fired by every device that registers the `event-emitter`
506
509
  * capability. Mirrors `eventEmitterCapability.events.onEvent`. Carries
@@ -5460,7 +5463,7 @@ var ZodIssueCode = {
5460
5463
  var ZodFirstPartyTypeKind;
5461
5464
  ZodFirstPartyTypeKind || (ZodFirstPartyTypeKind = {});
5462
5465
  //#endregion
5463
- //#region ../types/dist/sleep-6AqUnQIT.mjs
5466
+ //#region ../types/dist/sleep-CYfIZzGv.mjs
5464
5467
  /**
5465
5468
  * The audio chunk plane's byte format, and the ONE expansion from a coded
5466
5469
  * window to float samples (D455).
@@ -5803,7 +5806,7 @@ Object.fromEntries([
5803
5806
  * `hydrateSchema` to skip the `value` injection for structural-only fields.
5804
5807
  */
5805
5808
  function isValuelessField(field) {
5806
- 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";
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" || field.type === "account-sign-in" || field.type === "secret-presence";
5807
5810
  }
5808
5811
  function hydrateSchema(schema, values, options = {}) {
5809
5812
  return {
@@ -8907,7 +8910,7 @@ var DeviceRole = /* @__PURE__ */ function(DeviceRole) {
8907
8910
  return DeviceRole;
8908
8911
  }({});
8909
8912
  //#endregion
8910
- //#region ../types/dist/composition-CB6PMT9p.mjs
8913
+ //#region ../types/dist/composition-BJ8iAZb3.mjs
8911
8914
  /**
8912
8915
  * The ffmpeg build every CamStack node downloads, per platform and arch.
8913
8916
  *
@@ -8967,7 +8970,7 @@ portable("linux64"), portable("linuxarm64"), portable("macarm64"), portable("mac
8967
8970
  * ONE table for everyone who asks "is this device HIGH?": the
8968
8971
  * recorder's `RecordingTriggers.sensorDeviceIds` trigger, the post-analysis
8969
8972
  * sensor markers, the orchestrator's camera-sensors bridge and
8970
- * the sources of a composite doorbell (`doorbellFeatureSources`, D671).
8973
+ * the sources of a pulse (`compilePulseOverride`, D936).
8971
8974
  * A second copy would diverge at the first cap added, and the symptom — "the
8972
8975
  * sensor rings the doorbell but does not record" — is exactly D62.
8973
8976
  *
@@ -9208,6 +9211,20 @@ var table$1 = {
9208
9211
  apply: () => {
9209
9212
  throw new ExpressionEvalError("count: stateful evaluation context is required");
9210
9213
  }
9214
+ },
9215
+ dwell: {
9216
+ minArgs: 3,
9217
+ maxArgs: 3,
9218
+ apply: () => {
9219
+ throw new ExpressionEvalError("dwell: stateful evaluation context is required");
9220
+ }
9221
+ },
9222
+ latchedAt: {
9223
+ minArgs: 1,
9224
+ maxArgs: 1,
9225
+ apply: () => {
9226
+ throw new ExpressionEvalError("latchedAt: stateful evaluation context is required");
9227
+ }
9211
9228
  }
9212
9229
  };
9213
9230
  Object.freeze(Object.assign(Object.create(null), table$1));
@@ -10647,13 +10664,22 @@ var BirthDecisionRecordSchema = object({
10647
10664
  decidedByBirthEvidence: boolean(),
10648
10665
  /** Best class-compatible crop score, or `null` when nothing compatible was
10649
10666
  * found — deliberately not 0, which would be a measurement that never was.
10650
- * Includes a box the detector's own per-class floor refused (reason
10651
- * `below-detector-floor`, D922): that box never confirms, but it is the
10652
- * score the crop really held. */
10667
+ * Includes a box the detector's own per-class floor refused (D922): since
10668
+ * D925 the gate's bar, not that floor, decides whether it confirms. */
10653
10669
  bestScore: number().nullable(),
10654
10670
  /** The bar this candidate actually faced (the phantom-cell hook may raise it). */
10655
10671
  appliedMinConfidence: number().nullable(),
10656
10672
  /**
10673
+ * The detector the gate re-judged the birth WITH (D925): the session's own
10674
+ * root model, inference-device pool and node — never a node default. `null`
10675
+ * when the frame named no session detector or no gate ran, and on rows
10676
+ * written before D925. A `session-device-unavailable` row names the session
10677
+ * detector that could not be reached.
10678
+ */
10679
+ detectorModelId: string().nullable().default(null),
10680
+ detectorDeviceKey: string().nullable().default(null),
10681
+ detectorNodeId: string().nullable().default(null),
10682
+ /**
10657
10683
  * The track's own `firstSeen` — the candidate's first frame, which is where
10658
10684
  * the timeline starts. `null` for a suppressed birth, which has no track.
10659
10685
  */
@@ -16654,6 +16680,13 @@ var ComposerUnreadableBlockSchema = object({
16654
16680
  /** The parse error, in the operator's words. */
16655
16681
  error: string()
16656
16682
  });
16683
+ /** A confirmed release the hub did not accept. `deviceId` is the claim's device. */
16684
+ var UnreleasedClaimSchema = object({
16685
+ deviceId: number().int(),
16686
+ capName: string(),
16687
+ owner: string(),
16688
+ error: string()
16689
+ });
16657
16690
  method(object({
16658
16691
  /** The shared Blocks integration; null until `core-blocks` has reconciled it. */
16659
16692
  integrationId: string().nullable(),
@@ -16663,7 +16696,13 @@ method(object({
16663
16696
  /** Operator restarts: rebuild these runtimes and re-resolve their sources. Stores nothing (D62). */
16664
16697
  restartBlockIds: array(string()),
16665
16698
  /** Composition rows that exist but do not parse: held, never withdrawn, reported failed. */
16666
- unreadableBlocks: array(ComposerUnreadableBlockSchema)
16699
+ unreadableBlocks: array(ComposerUnreadableBlockSchema),
16700
+ /**
16701
+ * Operator-confirmed deletions. Their claims are released on this apply,
16702
+ * before any replacement block claims. A block that merely vanished from the
16703
+ * snapshot is not listed here and still waits for two applies (D49).
16704
+ */
16705
+ retiredBlockIds: array(string()).optional()
16667
16706
  }), object({
16668
16707
  blocks: array(object({
16669
16708
  blockId: string(),
@@ -16675,7 +16714,13 @@ method(object({
16675
16714
  * integration unknown, its own rows unread or read empty once). An empty
16676
16715
  * apply the caller owes is paid off only by one the composer acted on (D49).
16677
16716
  */
16678
- acted: boolean()
16717
+ acted: boolean(),
16718
+ /**
16719
+ * Confirmed releases this apply tried and the hub did not accept. Empty when
16720
+ * every one landed (or there was nothing to hand back). Absent on a result
16721
+ * that never got that far.
16722
+ */
16723
+ unreleasedClaims: array(UnreleasedClaimSchema).optional()
16679
16724
  }), {
16680
16725
  kind: "mutation",
16681
16726
  auth: "admin"
@@ -16718,7 +16763,15 @@ Object.freeze({
16718
16763
  kind: "fixed",
16719
16764
  result: ["number", "null"]
16720
16765
  },
16721
- count: NUMBER
16766
+ count: NUMBER,
16767
+ dwell: {
16768
+ kind: "fixed",
16769
+ result: ["boolean", "null"]
16770
+ },
16771
+ latchedAt: {
16772
+ kind: "fixed",
16773
+ result: ["number", "null"]
16774
+ }
16722
16775
  });
16723
16776
  `${COMPOSED_DEVICE_STABLE_ID_PREFIX}`;
16724
16777
  /**
@@ -42875,6 +42928,381 @@ var _macroLookup = /* @__PURE__ */ new Map();
42875
42928
  for (const [k, v] of Object.entries(YAMNET_TO_MACRO.mapping)) _macroLookup.set(k.toLowerCase(), v);
42876
42929
  for (const [k, v] of Object.entries(APPLE_SA_TO_MACRO.mapping)) _macroLookup.set(k.toLowerCase(), v);
42877
42930
  /**
42931
+ * Palette entry ids (D939). Audio is the one gradient; `audio-*` leaves are
42932
+ * not entries. `heatmapScrub` is a mark, not an event kind.
42933
+ */
42934
+ var PALETTE_ENTRY_IDS = [
42935
+ "motion",
42936
+ "audio",
42937
+ "recording",
42938
+ "live",
42939
+ "heatmapScrub",
42940
+ "person",
42941
+ "vehicle",
42942
+ "animal",
42943
+ "package",
42944
+ "sensor",
42945
+ "control",
42946
+ "face",
42947
+ "plate",
42948
+ "car",
42949
+ "truck",
42950
+ "bus",
42951
+ "motorcycle",
42952
+ "bicycle",
42953
+ "airplane",
42954
+ "boat",
42955
+ "train",
42956
+ "bird",
42957
+ "dog",
42958
+ "cat",
42959
+ "horse",
42960
+ "sheep",
42961
+ "cow",
42962
+ "elephant",
42963
+ "bear",
42964
+ "zebra",
42965
+ "giraffe",
42966
+ "package-delivered",
42967
+ "package-picked-up",
42968
+ "suitcase",
42969
+ "backpack",
42970
+ "handbag",
42971
+ "contact",
42972
+ "motion-sensor",
42973
+ "smoke",
42974
+ "flood",
42975
+ "gas",
42976
+ "carbon-monoxide",
42977
+ "vibration",
42978
+ "tamper",
42979
+ "presence",
42980
+ "enum-sensor",
42981
+ "device-event",
42982
+ "lock",
42983
+ "cover",
42984
+ "switch",
42985
+ "siren",
42986
+ "button",
42987
+ "doorbell"
42988
+ ];
42989
+ var AUDIO_ENTRY_ID = "audio";
42990
+ /** Six rungs, quiet → loud. The opaque end is the entry's hex. */
42991
+ var AUDIO_GRADIENT_ALPHAS = [
42992
+ .3,
42993
+ .42,
42994
+ .55,
42995
+ .7,
42996
+ .85,
42997
+ 1
42998
+ ];
42999
+ var PALETTE_PRESET_IDS = [
43000
+ "camstack",
43001
+ "high-contrast",
43002
+ "okabe-ito"
43003
+ ];
43004
+ /** Frozen palette tables (D939). The spec refuses a table that breaks the rule. */
43005
+ var CAMSTACK_HEX = {
43006
+ motion: "#d946ef",
43007
+ audio: "#059eb8",
43008
+ recording: "#ef4444",
43009
+ live: "#8d7a00",
43010
+ heatmapScrub: "#4b32ff",
43011
+ person: "#11a64c",
43012
+ vehicle: "#3b82f6",
43013
+ animal: "#ea6a09",
43014
+ package: "#924667",
43015
+ sensor: "#624bbc",
43016
+ control: "#944d24",
43017
+ face: "#ed4f8d",
43018
+ plate: "#4b7027",
43019
+ car: "#9684cf",
43020
+ truck: "#0f9b89",
43021
+ bus: "#a734a9",
43022
+ motorcycle: "#c1133a",
43023
+ bicycle: "#0e6a9b",
43024
+ airplane: "#7c9928",
43025
+ boat: "#b17933",
43026
+ train: "#ad6ca3",
43027
+ bird: "#0f7c55",
43028
+ dog: "#c82700",
43029
+ cat: "#7268f2",
43030
+ horse: "#cb795e",
43031
+ sheep: "#b8636b",
43032
+ cow: "#cb2969",
43033
+ elephant: "#1158d2",
43034
+ bear: "#8d5e00",
43035
+ zebra: "#0097d6",
43036
+ giraffe: "#8f61bb",
43037
+ "package-delivered": "#cd3f9b",
43038
+ "package-picked-up": "#388a08",
43039
+ suitcase: "#666800",
43040
+ backpack: "#ec5022",
43041
+ handbag: "#a76ef8",
43042
+ contact: "#ab5a49",
43043
+ "motion-sensor": "#b95d1a",
43044
+ smoke: "#dd3858",
43045
+ flood: "#b31e7d",
43046
+ gas: "#5b70b5",
43047
+ "carbon-monoxide": "#7b4e8e",
43048
+ vibration: "#e65bba",
43049
+ tamper: "#98464b",
43050
+ presence: "#3a9468",
43051
+ "enum-sensor": "#7885f8",
43052
+ "device-event": "#8c43c8",
43053
+ lock: "#649653",
43054
+ cover: "#c67597",
43055
+ switch: "#7a812a",
43056
+ siren: "#ac5d7f",
43057
+ button: "#b276cd",
43058
+ doorbell: "#0087ab"
43059
+ };
43060
+ var CAMSTACK_FALLBACK = [
43061
+ "#b34dc7",
43062
+ "#1d7d34",
43063
+ "#db6b6c",
43064
+ "#a43d29",
43065
+ "#0e6ee6",
43066
+ "#29a10b",
43067
+ "#a98731",
43068
+ "#0181c6"
43069
+ ];
43070
+ var HIGH_CONTRAST_HEX = {
43071
+ motion: "#964360",
43072
+ audio: "#23a132",
43073
+ recording: "#2494ca",
43074
+ live: "#bd7e2b",
43075
+ heatmapScrub: "#ad6eea",
43076
+ person: "#62611e",
43077
+ vehicle: "#f4534c",
43078
+ animal: "#1556cd",
43079
+ package: "#9c4415",
43080
+ sensor: "#066c48",
43081
+ control: "#f2479f",
43082
+ face: "#139d8a",
43083
+ plate: "#909024",
43084
+ car: "#8e35ab",
43085
+ truck: "#bd0b2b",
43086
+ bus: "#7a88ca",
43087
+ motorcycle: "#e26725",
43088
+ bicycle: "#a6679b",
43089
+ airplane: "#7c5720",
43090
+ boat: "#467a1b",
43091
+ train: "#6f65a4",
43092
+ bird: "#cb717f",
43093
+ dog: "#c62490",
43094
+ cat: "#b36850",
43095
+ horse: "#1872ac",
43096
+ sheep: "#927939",
43097
+ cow: "#428a5c",
43098
+ elephant: "#d41160",
43099
+ bear: "#799453",
43100
+ zebra: "#a85455",
43101
+ giraffe: "#746be8",
43102
+ "package-delivered": "#824a80",
43103
+ "package-picked-up": "#614ac1",
43104
+ suitcase: "#2f77f3",
43105
+ backpack: "#fa476d",
43106
+ handbag: "#c14cbe",
43107
+ contact: "#c83921",
43108
+ "motion-sensor": "#a07ebd",
43109
+ smoke: "#a25b13",
43110
+ flood: "#526bab",
43111
+ gas: "#924938",
43112
+ "carbon-monoxide": "#bb7e53",
43113
+ vibration: "#b66182",
43114
+ tamper: "#3c6931",
43115
+ presence: "#6c851d",
43116
+ "enum-sensor": "#ad2d48",
43117
+ "device-event": "#5e9b04",
43118
+ lock: "#00a062",
43119
+ cover: "#ad8624",
43120
+ switch: "#d05259",
43121
+ siren: "#cd67b3",
43122
+ button: "#c9746a",
43123
+ doorbell: "#338eeb"
43124
+ };
43125
+ var HIGH_CONTRAST_FALLBACK = [
43126
+ "#817f3b",
43127
+ "#a0733e",
43128
+ "#8658b2",
43129
+ "#956301",
43130
+ "#bc652d",
43131
+ "#647331",
43132
+ "#a14c9e",
43133
+ "#d14e71"
43134
+ ];
43135
+ var OKABE_ITO_HEX = {
43136
+ motion: "#b88128",
43137
+ audio: "#1096c8",
43138
+ recording: "#009e73",
43139
+ live: "#9c8c22",
43140
+ heatmapScrub: "#0072b2",
43141
+ person: "#d55e00",
43142
+ vehicle: "#c0739f",
43143
+ animal: "#226d18",
43144
+ package: "#91446c",
43145
+ sensor: "#217b56",
43146
+ control: "#648647",
43147
+ face: "#c22998",
43148
+ plate: "#fa4575",
43149
+ car: "#956301",
43150
+ truck: "#2f77f3",
43151
+ bus: "#7a4e86",
43152
+ motorcycle: "#f54597",
43153
+ bicycle: "#bb3e75",
43154
+ airplane: "#e054c0",
43155
+ boat: "#457942",
43156
+ train: "#867afa",
43157
+ bird: "#88914c",
43158
+ dog: "#1556cd",
43159
+ cat: "#71702c",
43160
+ horse: "#9b4fa4",
43161
+ sheep: "#c0559d",
43162
+ cow: "#d14f65",
43163
+ elephant: "#98470f",
43164
+ bear: "#595896",
43165
+ zebra: "#96790e",
43166
+ giraffe: "#cb717b",
43167
+ "package-delivered": "#139d8a",
43168
+ "package-picked-up": "#906ead",
43169
+ suitcase: "#d02939",
43170
+ backpack: "#d41160",
43171
+ handbag: "#f64f54",
43172
+ contact: "#7258d2",
43173
+ "motion-sensor": "#b66182",
43174
+ smoke: "#627abb",
43175
+ flood: "#b86ae4",
43176
+ gas: "#a95261",
43177
+ "carbon-monoxide": "#c65d3c",
43178
+ vibration: "#7a40b7",
43179
+ tamper: "#914b34",
43180
+ presence: "#9481c3",
43181
+ "enum-sensor": "#ac6d47",
43182
+ "device-event": "#7b6fce",
43183
+ lock: "#c67662",
43184
+ cover: "#a6564d",
43185
+ switch: "#ad2c4e",
43186
+ siren: "#348e08",
43187
+ button: "#d27303",
43188
+ doorbell: "#55770f"
43189
+ };
43190
+ var OKABE_ITO_FALLBACK = [
43191
+ "#9a3784",
43192
+ "#a7392c",
43193
+ "#409d50",
43194
+ "#6987e7",
43195
+ "#ee5b3d",
43196
+ "#c0430d",
43197
+ "#af79b3",
43198
+ "#4b6628"
43199
+ ];
43200
+ /**
43201
+ * The display palette (D939). One table of colours, three presets, one
43202
+ * validator. Taxonomy colours and every consumer read this — there is no
43203
+ * second hex table.
43204
+ */
43205
+ var paletteHexSchema = string().regex(/^#[0-9a-f]{6}$/);
43206
+ var paletteSwatchSchema = discriminatedUnion("form", [object({
43207
+ form: literal("solid"),
43208
+ hex: paletteHexSchema
43209
+ }), object({
43210
+ form: literal("gradient"),
43211
+ hex: paletteHexSchema,
43212
+ alphas: array(number().gt(0).lte(1)).length(AUDIO_GRADIENT_ALPHAS.length)
43213
+ })]);
43214
+ var paletteReadySchema = object({
43215
+ status: literal("ready"),
43216
+ presetId: _enum(PALETTE_PRESET_IDS),
43217
+ customized: boolean(),
43218
+ source: _enum(["stored", "unconfigured"]),
43219
+ swatches: record(string(), paletteSwatchSchema),
43220
+ fallbacks: array(paletteHexSchema).length(8)
43221
+ });
43222
+ var paletteResultSchema = discriminatedUnion("status", [paletteReadySchema, object({
43223
+ status: literal("unknown"),
43224
+ reason: string()
43225
+ })]);
43226
+ var setPaletteInputSchema = union([object({ presetId: string() }), object({
43227
+ presetId: string(),
43228
+ overrides: record(string(), paletteSwatchSchema)
43229
+ })]);
43230
+ object({
43231
+ presetId: string(),
43232
+ overrides: record(string(), paletteSwatchSchema)
43233
+ });
43234
+ function solid(hex) {
43235
+ return {
43236
+ form: "solid",
43237
+ hex
43238
+ };
43239
+ }
43240
+ function audioGradient(hex) {
43241
+ return {
43242
+ form: "gradient",
43243
+ hex,
43244
+ alphas: [...AUDIO_GRADIENT_ALPHAS]
43245
+ };
43246
+ }
43247
+ function swatchesFrom(hexes) {
43248
+ const out = {};
43249
+ for (const id of PALETTE_ENTRY_IDS) {
43250
+ const hex = hexes[id];
43251
+ if (hex === void 0) throw new Error(`palette table missing ${id}`);
43252
+ out[id] = id === "audio" ? audioGradient(hex) : solid(hex);
43253
+ }
43254
+ return out;
43255
+ }
43256
+ function preset(id, name, hexes, fallbacks) {
43257
+ return {
43258
+ id,
43259
+ name,
43260
+ swatches: swatchesFrom(hexes),
43261
+ fallbacks
43262
+ };
43263
+ }
43264
+ var DISPLAY_PRESETS = [
43265
+ preset("camstack", "CamStack", CAMSTACK_HEX, CAMSTACK_FALLBACK),
43266
+ preset("high-contrast", "High contrast", HIGH_CONTRAST_HEX, HIGH_CONTRAST_FALLBACK),
43267
+ preset("okabe-ito", "Colour-blind safe", OKABE_ITO_HEX, OKABE_ITO_FALLBACK)
43268
+ ];
43269
+ function presetById(id) {
43270
+ return DISPLAY_PRESETS.find((item) => item.id === id);
43271
+ }
43272
+ function bundledCamstack() {
43273
+ const presetRow = presetById("camstack");
43274
+ if (presetRow === void 0) throw new Error("CamStack preset missing");
43275
+ return readyOf(presetRow, "unconfigured", false);
43276
+ }
43277
+ function readyOf(row, source, customized) {
43278
+ return {
43279
+ status: "ready",
43280
+ presetId: row.id,
43281
+ customized,
43282
+ source,
43283
+ swatches: row.swatches,
43284
+ fallbacks: [...row.fallbacks]
43285
+ };
43286
+ }
43287
+ function hashFallback(kind, fallbacks) {
43288
+ let hash = 0;
43289
+ for (let i = 0; i < kind.length; i++) hash = hash * 31 + (kind.codePointAt(i) ?? 0) >>> 0;
43290
+ const hex = fallbacks[hash % fallbacks.length];
43291
+ if (hex === void 0) throw new Error("display palette has no fallback colour");
43292
+ return hex;
43293
+ }
43294
+ /** Colour a kind paints with. Audio leaves share the audio gradient's hex. */
43295
+ function paintHex(swatches, fallbacks, kind) {
43296
+ const key = kind.trim().toLowerCase();
43297
+ if (key.startsWith("audio-")) {
43298
+ const audio = swatches[AUDIO_ENTRY_ID];
43299
+ return audio !== void 0 ? audio.hex : hashFallback(key, fallbacks);
43300
+ }
43301
+ const direct = swatches[key];
43302
+ if (direct !== void 0) return direct.hex;
43303
+ return hashFallback(key, fallbacks);
43304
+ }
43305
+ /**
42878
43306
  * Unified event-kind taxonomy — THE single source of truth for
42879
43307
  * `kind → { parentKind, category, level, color, iconId, labelKey, label,
42880
43308
  * icon }`.
@@ -42888,109 +43316,88 @@ for (const [k, v] of Object.entries(APPLE_SA_TO_MACRO.mapping)) _macroLookup.set
42888
43316
  * - `addon-post-analysis/shared/frame/box-drawer.ts` (DEFAULT_COLOR)
42889
43317
  * - the COCO / audio class maps (macro ↔ sub relationships)
42890
43318
  *
42891
- * The DATA (serializable — color/iconId/labelKey/parentKind) lives here in
42892
- * `@camstack/types`. The UI-side mapping `iconId → lucide component` and
42893
- * `labelKey → t()` lives in `@camstack/ui-library`. UIs never hardcode a
42894
- * color or an icon: they read this dictionary (server descriptors carry the
42895
- * fields inline; the client resolves color/icon/label from `iconId`/`kind`).
43319
+ * The DATA (serializable — parentKind / iconId / labelKey) lives here in
43320
+ * `@camstack/types`. Colour is NOT a second table: each entry's `color` is
43321
+ * the bundled CamStack display palette (D939). The effective cluster palette
43322
+ * is the `display-palette` capability. The UI-side mapping `iconId → lucide
43323
+ * component` and `labelKey → t()` lives in `@camstack/ui-library`.
42896
43324
  *
42897
43325
  * Two levels only (v1 YAGNI): macro → sub. `person` is a leaf macro.
42898
43326
  */
42899
- var TAXONOMY_COLORS = {
42900
- motion: "#f59e0b",
42901
- audio: "#06b6d4",
42902
- person: "#22c55e",
42903
- vehicle: "#3b82f6",
42904
- animal: "#f97316",
42905
- package: "#a855f7",
42906
- sensor: "#8b5cf6",
42907
- control: "#10b981",
42908
- genericDetection: "#64748b"
42909
- };
42910
- var DETECTION_SUB_COLORS = {
42911
- car: "#f59e0b",
42912
- truck: "#d97706",
42913
- bus: "#b45309",
42914
- motorcycle: "#eab308",
42915
- bicycle: "#ca8a04",
42916
- airplane: "#60a5fa",
42917
- boat: "#2563eb",
42918
- train: "#1d4ed8",
42919
- bird: "#14b8a6",
42920
- dog: "#84cc16",
42921
- cat: "#f97316",
42922
- horse: "#a16207",
42923
- sheep: "#a3a3a3",
42924
- cow: "#78716c",
42925
- elephant: "#6b7280",
42926
- bear: "#7c2d12",
42927
- zebra: "#404040",
42928
- giraffe: "#d4a373"
42929
- };
43327
+ var BUNDLED_PALETTE = bundledCamstack();
43328
+ function kindColor(kind) {
43329
+ return paintHex(BUNDLED_PALETTE.swatches, BUNDLED_PALETTE.fallbacks, kind);
43330
+ }
43331
+ function firstFallback(fallbacks) {
43332
+ const hex = fallbacks[0];
43333
+ if (hex === void 0) throw new Error("display palette has no fallback colour");
43334
+ return hex;
43335
+ }
43336
+ firstFallback(BUNDLED_PALETTE.fallbacks);
42930
43337
  function titleCase(id) {
42931
43338
  return id.split(/[-_ ]/).filter((p) => p.length > 0).map((p) => p.charAt(0).toUpperCase() + p.slice(1)).join(" ");
42932
43339
  }
42933
43340
  var entries = /* @__PURE__ */ new Map();
42934
- function macro(kind, category, color, iconId, label) {
43341
+ function macro(kind, category, iconId, label) {
42935
43342
  entries.set(kind, {
42936
43343
  kind,
42937
43344
  parentKind: null,
42938
43345
  level: "macro",
42939
43346
  category,
42940
- color,
43347
+ color: kindColor(kind),
42941
43348
  iconId,
42942
43349
  labelKey: `eventKind.${kind}`,
42943
43350
  label
42944
43351
  });
42945
43352
  }
42946
- function sub(kind, parentKind, category, color, iconId, label) {
43353
+ function sub(kind, parentKind, category, iconId, label) {
42947
43354
  entries.set(kind, {
42948
43355
  kind,
42949
43356
  parentKind,
42950
43357
  level: "sub",
42951
43358
  category,
42952
- color,
43359
+ color: kindColor(kind),
42953
43360
  iconId,
42954
43361
  labelKey: `eventKind.${kind}`,
42955
43362
  label
42956
43363
  });
42957
43364
  }
42958
- macro("motion", "motion", TAXONOMY_COLORS.motion, "motion", "Motion");
42959
- macro("audio", "audio", TAXONOMY_COLORS.audio, "audio", "Audio");
42960
- macro("person", "detection", TAXONOMY_COLORS.person, "person", "Person");
42961
- macro("vehicle", "detection", TAXONOMY_COLORS.vehicle, "vehicle", "Vehicle");
42962
- macro("animal", "detection", TAXONOMY_COLORS.animal, "animal", "Animal");
42963
- macro("package", "package", TAXONOMY_COLORS.package, "package", "Package");
42964
- macro("sensor", "sensor", TAXONOMY_COLORS.sensor, "sensor", "Sensor");
42965
- macro("control", "control", TAXONOMY_COLORS.control, "control", "Control");
43365
+ macro("motion", "motion", "motion", "Motion");
43366
+ macro("audio", "audio", "audio", "Audio");
43367
+ macro("person", "detection", "person", "Person");
43368
+ macro("vehicle", "detection", "vehicle", "Vehicle");
43369
+ macro("animal", "detection", "animal", "Animal");
43370
+ macro("package", "package", "package", "Package");
43371
+ macro("sensor", "sensor", "sensor", "Sensor");
43372
+ macro("control", "control", "control", "Control");
42966
43373
  for (const [cocoClass, macroClass] of Object.entries(COCO_TO_MACRO.mapping)) {
42967
43374
  if (macroClass !== "vehicle" && macroClass !== "animal") continue;
42968
43375
  if (entries.has(cocoClass)) continue;
42969
- sub(cocoClass, macroClass, "detection", DETECTION_SUB_COLORS[cocoClass] ?? TAXONOMY_COLORS.genericDetection, cocoClass, titleCase(cocoClass));
42970
- }
42971
- sub("package-delivered", "package", "package", TAXONOMY_COLORS.package, "package", "Package delivered");
42972
- sub("package-picked-up", "package", "package", TAXONOMY_COLORS.package, "package", "Package picked up");
42973
- sub("contact", "sensor", "sensor", "#f59e0b", "door", "Contact");
42974
- sub("motion-sensor", "sensor", "sensor", TAXONOMY_COLORS.sensor, "pir", "Motion sensor");
42975
- sub("smoke", "sensor", "sensor", "#ef4444", "smoke", "Smoke");
42976
- sub("flood", "sensor", "sensor", "#3b82f6", "water", "Water leak");
42977
- sub("gas", "sensor", "sensor", "#ef4444", "gas", "Gas");
42978
- sub("carbon-monoxide", "sensor", "sensor", "#dc2626", "smoke", "Carbon monoxide");
42979
- sub("vibration", "sensor", "sensor", "#eab308", "vibration", "Vibration");
42980
- sub("tamper", "sensor", "sensor", "#f97316", "tamper", "Tamper");
42981
- sub("presence", "sensor", "sensor", "#22c55e", "presence", "Presence");
42982
- sub("enum-sensor", "sensor", "sensor", TAXONOMY_COLORS.sensor, "generic", "Sensor state");
42983
- sub("device-event", "sensor", "sensor", "#10b981", "button", "Device event");
42984
- sub("lock", "control", "control", "#0ea5e9", "lock", "Lock");
42985
- sub("cover", "control", "control", "#0ea5e9", "door", "Cover");
42986
- sub("switch", "control", "control", TAXONOMY_COLORS.control, "switch", "Switch");
42987
- sub("siren", "control", "control", "#dc2626", "siren", "Siren");
42988
- sub("button", "control", "control", "#10b981", "button", "Button");
42989
- sub("doorbell", "control", "control", "#a855f7", "doorbell", "Doorbell");
43376
+ sub(cocoClass, macroClass, "detection", cocoClass, titleCase(cocoClass));
43377
+ }
43378
+ sub("package-delivered", "package", "package", "package", "Package delivered");
43379
+ sub("package-picked-up", "package", "package", "package", "Package picked up");
43380
+ sub("contact", "sensor", "sensor", "door", "Contact");
43381
+ sub("motion-sensor", "sensor", "sensor", "pir", "Motion sensor");
43382
+ sub("smoke", "sensor", "sensor", "smoke", "Smoke");
43383
+ sub("flood", "sensor", "sensor", "water", "Water leak");
43384
+ sub("gas", "sensor", "sensor", "gas", "Gas");
43385
+ sub("carbon-monoxide", "sensor", "sensor", "smoke", "Carbon monoxide");
43386
+ sub("vibration", "sensor", "sensor", "vibration", "Vibration");
43387
+ sub("tamper", "sensor", "sensor", "tamper", "Tamper");
43388
+ sub("presence", "sensor", "sensor", "presence", "Presence");
43389
+ sub("enum-sensor", "sensor", "sensor", "generic", "Sensor state");
43390
+ sub("device-event", "sensor", "sensor", "button", "Device event");
43391
+ sub("lock", "control", "control", "lock", "Lock");
43392
+ sub("cover", "control", "control", "door", "Cover");
43393
+ sub("switch", "control", "control", "switch", "Switch");
43394
+ sub("siren", "control", "control", "siren", "Siren");
43395
+ sub("button", "control", "control", "button", "Button");
43396
+ sub("doorbell", "control", "control", "doorbell", "Doorbell");
42990
43397
  for (const l of AUDIO_MACRO_LABELS) {
42991
43398
  const kind = `audio-${l.id}`;
42992
43399
  if (entries.has(kind)) continue;
42993
- sub(kind, "audio", "audio", TAXONOMY_COLORS.audio, kind, l.name);
43400
+ sub(kind, "audio", "audio", kind, l.name);
42994
43401
  }
42995
43402
  /** The complete taxonomy dictionary, keyed by kind. */
42996
43403
  var EVENT_TAXONOMY = Object.freeze(Object.fromEntries(entries));
@@ -43301,9 +43708,6 @@ var NcSystemEventKindSchema = _enum([
43301
43708
  "device-battery-normal",
43302
43709
  "device-consumable-low",
43303
43710
  "device-consumable-normal",
43304
- "device-tank-low",
43305
- "device-tank-full",
43306
- "device-tank-normal",
43307
43711
  "stream-online",
43308
43712
  "stream-offline",
43309
43713
  "node-online",
@@ -43350,13 +43754,14 @@ var NcSystemEventKindSchema = _enum([
43350
43754
  "camera-enabled"
43351
43755
  ]);
43352
43756
  /** The legacy tail of {@link NcSystemEventKindSchema} — see its docblock. */
43353
- var NC_LEGACY_SYSTEM_EVENT_KINDS = new Set([
43757
+ var NC_LEGACY_SYSTEM_EVENT_KINDS = [
43354
43758
  "camera-online",
43355
43759
  "camera-offline",
43356
43760
  "camera-disabled",
43357
43761
  "camera-enabled"
43358
- ]);
43359
- NcSystemEventKindSchema.options.filter((kind) => !NC_LEGACY_SYSTEM_EVENT_KINDS.has(kind));
43762
+ ];
43763
+ var NC_LEGACY_SYSTEM_EVENT_KIND_SET = new Set(NC_LEGACY_SYSTEM_EVENT_KINDS);
43764
+ NcSystemEventKindSchema.options.filter((kind) => !NC_LEGACY_SYSTEM_EVENT_KIND_SET.has(kind));
43360
43765
  /**
43361
43766
  * The panel's transitions, as ONE list.
43362
43767
  *
@@ -44475,18 +44880,11 @@ var NcRuleSchema = NcRuleInputSchema.extend({
44475
44880
  */
44476
44881
  disabledTargetIds: array(string()).default([])
44477
44882
  });
44478
- /**
44479
- * The state-summary SECTIONS (D647 / D698 / D708): the D637 kind groups that
44480
- * report a still-true state. `addons` is the crash-looped addons only and
44481
- * `addon-updates` the addons that are behind (D708 split them). `backups-exports` and `alarm` are not sections — a completed
44482
- * job is not an open state, and the alarm stays instant.
44483
- */
44484
44883
  var NcStateSummarySectionIdSchema = _enum([
44485
44884
  "device-state",
44486
44885
  "streams",
44487
44886
  "battery",
44488
44887
  "consumables",
44489
- "tanks",
44490
44888
  "detection-blind",
44491
44889
  "nodes",
44492
44890
  "addons",
@@ -45787,6 +46185,18 @@ Object.freeze({
45787
46185
  reason: "camera sensor mappings not loaded"
45788
46186
  });
45789
46187
  /**
46188
+ * What the vision model must answer before a package event is emitted
46189
+ * when a packages rule has "Confirm with the LLM" on.
46190
+ *
46191
+ * `package` is the verdict. `confidence` is 0..1. `reason` is the model's
46192
+ * one-line explanation, stored on the event so a drop is not silent.
46193
+ */
46194
+ var PackageLlmVerdictSchema = object({
46195
+ package: boolean(),
46196
+ confidence: number().min(0).max(1),
46197
+ reason: string().min(1)
46198
+ });
46199
+ /**
45790
46200
  * A model choice has a SCOPE, and a scope change has a workflow.
45791
46201
  *
45792
46202
  * ## The two scopes
@@ -46723,6 +47133,21 @@ var ObjectEventSchema = object({
46723
47133
  * pick-up written before D684 — UNKNOWN, never 0 and never `timestamp`.
46724
47134
  */
46725
47135
  observedAt: number().optional(),
47136
+ /**
47137
+ * The delivery was emitted without a vision-model yes (D931).
47138
+ *
47139
+ * Set only when the packages rule asked for an LLM confirm and the model
47140
+ * was unreachable, timed out, or answered something that did not parse.
47141
+ * A notification reads it so it can say "possible" instead of a definite
47142
+ * delivery. Absent on every other row, and on a confirm that said yes.
47143
+ */
47144
+ packagePossible: boolean().optional(),
47145
+ /**
47146
+ * The vision model's verdict, when a packages rule asked for one and the
47147
+ * model answered the schema (D931). A "no" never becomes a row — the
47148
+ * detector drops it and logs the reason. Present on a yes.
47149
+ */
47150
+ packageLlmVerdict: PackageLlmVerdictSchema.optional(),
46726
47151
  /** The parent track's key-event importance [0,1], propagated to every object
46727
47152
  * event of the track (so an event row can be sorted by importance without a
46728
47153
  * track join). Absent on legacy rows / before the track was scored. */
@@ -48520,7 +48945,6 @@ var PipelineAddonSchemaSchema = object({
48520
48945
  defaultModelId: string(),
48521
48946
  defaultModelIdByFormat: record(string(), string()).optional(),
48522
48947
  enabledByDefault: boolean().optional(),
48523
- backfillIntoExistingOverrides: boolean().optional(),
48524
48948
  defaultConfidence: number(),
48525
48949
  group: string().optional(),
48526
48950
  configSchema: array(ConfigFieldBridge).readonly().optional()
@@ -48647,13 +49071,12 @@ var AudioTestResultSchema = object({
48647
49071
  error: string().optional(),
48648
49072
  frame: custom().optional()
48649
49073
  });
48650
- var PipelineConfigBridge = custom();
48651
49074
  var ConfigUISchemaBridge = custom();
48652
49075
  var ConfigUISchemaNullableBridge = custom();
48653
49076
  var InferenceCapabilitiesBridge = custom();
48654
49077
  var ModelAvailabilityListBridge = custom();
48655
49078
  var PipelineRunResultBridge = custom();
48656
- method(_void(), array(PipelineEngineChoiceSchema)), method(_void(), PipelineEngineChoiceSchema), method(PipelineEngineChoiceSchema, array(PipelineDefaultStepSchema)), method(object({ nodeId: string() }), EngineProvisioningSchema), method(_void(), record(string(), object({
49079
+ method(_void(), array(PipelineEngineChoiceSchema)), method(_void(), PipelineEngineChoiceSchema), method(object({ nodeId: string() }), EngineProvisioningSchema), method(_void(), record(string(), object({
48657
49080
  modelId: string(),
48658
49081
  settings: record(string(), unknown()).readonly()
48659
49082
  }))), method(object({ steps: record(string(), object({
@@ -48662,28 +49085,6 @@ method(_void(), array(PipelineEngineChoiceSchema)), method(_void(), PipelineEngi
48662
49085
  })) }), object({ success: literal(true) }), {
48663
49086
  kind: "mutation",
48664
49087
  auth: "admin"
48665
- }), method(object({ nodeId: string() }), object({
48666
- success: literal(true),
48667
- clearedDevices: number()
48668
- }), {
48669
- kind: "mutation",
48670
- auth: "admin"
48671
- }), method(object({
48672
- nodeId: string(),
48673
- deviceIds: array(number()).readonly().optional(),
48674
- dryRun: boolean()
48675
- }), object({
48676
- entries: array(object({
48677
- deviceId: number(),
48678
- keys: array(string()).readonly()
48679
- })).readonly(),
48680
- refused: array(object({
48681
- deviceId: number(),
48682
- reason: string()
48683
- })).readonly()
48684
- }), {
48685
- kind: "mutation",
48686
- auth: "admin"
48687
49088
  }), method(object({ nodeId: string() }), object({ unhealthy: array(object({
48688
49089
  /** `<backend>:<device>`, e.g. `openvino:gpu`. */
48689
49090
  deviceKey: string(),
@@ -48706,7 +49107,7 @@ method(_void(), array(PipelineEngineChoiceSchema)), method(_void(), PipelineEngi
48706
49107
  }), object({ rearmed: boolean() }), {
48707
49108
  kind: "mutation",
48708
49109
  auth: "admin"
48709
- }), method(_void(), PipelineSchemaSchema), method(_void(), array(PipelineDefaultStepSchema).readonly().nullable()), method(_void(), PipelineConfigBridge), method(_void(), ConfigUISchemaBridge), method(object({
49110
+ }), method(_void(), PipelineSchemaSchema), method(_void(), ConfigUISchemaBridge), method(object({
48710
49111
  steps: array(PipelineStepInputSchema),
48711
49112
  deviceKey: string().optional()
48712
49113
  }), PipelineValidationResultSchema), method(_void(), InferenceCapabilitiesBridge), method(object({ addonId: string() }), ModelAvailabilityListBridge), method(object({
@@ -48954,11 +49355,18 @@ var KeptReasonSchema = _enum(["custom-pin"]);
48954
49355
  * Where a choice's latency came from (D791): this node's own benchmark
48955
49356
  * result, or the hardware-class table. Measured on the node beats the table.
48956
49357
  */
48957
- var LatencySourceSchema = discriminatedUnion("kind", [object({ kind: literal("table") }), object({
48958
- kind: literal("node-benchmark"),
48959
- resultId: string(),
48960
- measuredAtMs: number()
48961
- })]);
49358
+ var LatencySourceSchema = discriminatedUnion("kind", [
49359
+ object({ kind: literal("table") }),
49360
+ object({
49361
+ kind: literal("node-benchmark"),
49362
+ resultId: string(),
49363
+ measuredAtMs: number()
49364
+ }),
49365
+ object({
49366
+ kind: literal("estimated"),
49367
+ estimatedFrom: HardwareClassIdSchema
49368
+ })
49369
+ ]);
48962
49370
  var DeviceModelChoiceSchema = object({
48963
49371
  modelId: string(),
48964
49372
  p50Ms: number(),
@@ -48966,6 +49374,11 @@ var DeviceModelChoiceSchema = object({
48966
49374
  measured: boolean(),
48967
49375
  /** Absent on a plan from before D791 — read as the table. */
48968
49376
  source: LatencySourceSchema.optional(),
49377
+ /**
49378
+ * The measured class this latency was scaled from (D930). Absent when the
49379
+ * cell is the table or a node benchmark.
49380
+ */
49381
+ estimatedFrom: HardwareClassIdSchema.optional(),
48969
49382
  /** Parallel sessions at the camera rate with the headroom kept free: ⌊fps × (1 − headroom) / camera fps⌋. */
48970
49383
  capacitySessions: number(),
48971
49384
  personRecall: number()
@@ -49005,40 +49418,20 @@ var NodeDeviceChangeSchema = object({
49005
49418
  keys: array(string()).readonly()
49006
49419
  })).readonly()
49007
49420
  });
49008
- var CameraOverrideClearSchema = object({
49009
- deviceId: number(),
49010
- source: _enum(["step-override", "wholesale"]),
49421
+ /**
49422
+ * Every model and model-bound threshold lives on the accelerator that runs it
49423
+ * (D927), so the plan writes node / device entries only — there is no camera
49424
+ * layer for it to clear.
49425
+ */
49426
+ var AutoTuneWarningSchema = discriminatedUnion("kind", [object({
49427
+ kind: literal("custom-pin-kept"),
49011
49428
  nodeId: string(),
49012
- deviceKey: string().nullable(),
49013
- stepId: string(),
49014
- modelIdBefore: string().nullable(),
49015
- keys: array(string()).readonly()
49016
- });
49017
- var DetectorStoreClearSchema = object({
49018
- deviceId: number(),
49019
- keys: array(string()).readonly()
49020
- });
49021
- var AutoTuneWarningSchema = discriminatedUnion("kind", [
49022
- object({
49023
- kind: literal("detector-store-cluster-wide"),
49024
- skippedNodes: array(string()).readonly()
49025
- }),
49026
- object({
49027
- kind: literal("detector-store-unreadable"),
49028
- error: string()
49029
- }),
49030
- object({
49031
- kind: literal("custom-pin-kept"),
49032
- nodeId: string(),
49033
- deviceKey: string().nullable(),
49034
- deviceId: number().nullable(),
49035
- modelId: string()
49036
- }),
49037
- object({
49038
- kind: literal("custom-registry-unreadable"),
49039
- error: string()
49040
- })
49041
- ]);
49429
+ deviceKey: string(),
49430
+ modelId: string()
49431
+ }), object({
49432
+ kind: literal("custom-registry-unreadable"),
49433
+ error: string()
49434
+ })]);
49042
49435
  var AutoTuneOptionsSchema = object({
49043
49436
  /** Share of each accelerator's throughput kept free (0.3–0.5). */
49044
49437
  headroom: number().min(.3).max(.5).default(.4),
@@ -49060,8 +49453,6 @@ var AutoTunePlanSchema = object({
49060
49453
  generatedAt: number(),
49061
49454
  nodes: array(NodeRecommendationSchema).readonly(),
49062
49455
  nodeChanges: array(NodeDeviceChangeSchema).readonly(),
49063
- cameraClears: array(CameraOverrideClearSchema).readonly(),
49064
- detectorStoreClears: array(DetectorStoreClearSchema).readonly(),
49065
49456
  warnings: array(AutoTuneWarningSchema).readonly()
49066
49457
  });
49067
49458
  var AutoTuneApplyInputSchema = object({
@@ -49072,8 +49463,6 @@ var AutoTuneApplyInputSchema = object({
49072
49463
  var AutoTunePhaseResultSchema = object({
49073
49464
  phase: _enum([
49074
49465
  "download",
49075
- "camera-overrides",
49076
- "detector-thresholds",
49077
49466
  "node-models",
49078
49467
  "redispatch"
49079
49468
  ]),
@@ -50828,6 +51217,12 @@ var AgentPipelineSettingsSchema = object({
50828
51217
  /** Hub-persisted UI colour (`--color-node-*` theme tokens). */
50829
51218
  color: NodeColorIdSchema.optional(),
50830
51219
  /**
51220
+ * NODE-wide step settings (D927): `stepId → { key → value }`, applied on
51221
+ * every accelerator of the node under the device's own settings. Never a
51222
+ * model or a model-bound threshold. Written by `setNodeStepSettings`.
51223
+ */
51224
+ stepSettings: record(string(), record(string(), unknown()).readonly()).optional(),
51225
+ /**
50831
51226
  * Multi-device inference opt-in (Phase 4). Per-node map deviceKey → {enabled,
50832
51227
  * weight, steps}. Absent / all-disabled ⇒ the node's single default
50833
51228
  * accelerator (safe default); two+ enabled ⇒ the dispatcher balances
@@ -50843,17 +51238,6 @@ var AgentPipelineSettingsSchema = object({
50843
51238
  steps: record(string(), DeviceStepConfigSchema).optional()
50844
51239
  })).optional()
50845
51240
  });
50846
- var CameraPipelineForAgentSchema = object({
50847
- steps: array(PipelineStepInputSchema).readonly(),
50848
- audio: object({
50849
- modelId: string(),
50850
- enabled: boolean()
50851
- }).nullable()
50852
- });
50853
- var CameraStepOverridePatchSchema = object({
50854
- modelId: string().optional(),
50855
- settings: record(string(), unknown()).readonly().optional()
50856
- });
50857
51241
  var CameraStepSettingsSchema = record(string(), record(string(), unknown()).readonly());
50858
51242
  /** The three root-detector choices a camera has (D507: at most one root). */
50859
51243
  var CameraDetectionSourceSchema = _enum([
@@ -50863,9 +51247,7 @@ var CameraDetectionSourceSchema = _enum([
50863
51247
  ]);
50864
51248
  var CameraPipelineSettingsSchema = object({
50865
51249
  stepToggles: record(string(), boolean()).optional(),
50866
- stepSettings: CameraStepSettingsSchema.optional(),
50867
- stepOverridesByDevice: record(string(), record(string(), record(string(), CameraStepOverridePatchSchema))).optional(),
50868
- pipelineByAgent: record(string(), CameraPipelineForAgentSchema).optional()
51250
+ stepSettings: CameraStepSettingsSchema.optional()
50869
51251
  });
50870
51252
  /**
50871
51253
  * Pipeline placement record persisted by `addon-pipeline-orchestrator` via
@@ -51411,6 +51793,13 @@ method(object({
51411
51793
  }), object({ success: literal(true) }), {
51412
51794
  kind: "mutation",
51413
51795
  auth: "admin"
51796
+ }), method(object({
51797
+ agentNodeId: string(),
51798
+ addonId: string(),
51799
+ settings: record(string(), unknown()).nullable()
51800
+ }), object({ success: literal(true) }), {
51801
+ kind: "mutation",
51802
+ auth: "admin"
51414
51803
  }), method(object({ nodeId: string() }), NodeInferenceDevicesSchema), method(object({
51415
51804
  agentNodeId: string(),
51416
51805
  deviceKey: string()
@@ -51420,9 +51809,7 @@ method(object({
51420
51809
  }), method(object({ agentNodeId: string() }), object({
51421
51810
  success: literal(true),
51422
51811
  /** Hardware-aware default detection model now in effect on the node (null when unresolvable). */
51423
- effectiveModelId: string().nullable(),
51424
- /** Number of cameras whose node-scoped overrides were cleared. */
51425
- clearedCameraOverrides: number()
51812
+ effectiveModelId: string().nullable()
51426
51813
  }), {
51427
51814
  kind: "mutation",
51428
51815
  auth: "admin"
@@ -51477,15 +51864,6 @@ method(object({
51477
51864
  }), object({ success: literal(true) }), {
51478
51865
  kind: "mutation",
51479
51866
  auth: "admin"
51480
- }), method(object({ deviceId: number() }), record(string(), record(string(), record(string(), CameraStepOverridePatchSchema))).nullable()), method(object({
51481
- deviceId: number(),
51482
- agentNodeId: string(),
51483
- deviceKey: string(),
51484
- addonId: string(),
51485
- patch: CameraStepOverridePatchSchema.nullable()
51486
- }), object({ success: literal(true) }), {
51487
- kind: "mutation",
51488
- auth: "admin"
51489
51867
  }), method(object({
51490
51868
  deviceId: number(),
51491
51869
  addonId: string(),
@@ -51493,13 +51871,6 @@ method(object({
51493
51871
  }), object({ success: literal(true) }), {
51494
51872
  kind: "mutation",
51495
51873
  auth: "admin"
51496
- }), method(object({
51497
- deviceId: number(),
51498
- agentNodeId: string(),
51499
- pipeline: CameraPipelineForAgentSchema.nullable()
51500
- }), object({ success: literal(true) }), {
51501
- kind: "mutation",
51502
- auth: "admin"
51503
51874
  }), method(object({
51504
51875
  deviceId: number(),
51505
51876
  agentNodeId: string().optional()
@@ -55655,20 +56026,68 @@ var BatteryStatusSchema = object({
55655
56026
  */
55656
56027
  binary: boolean().optional()
55657
56028
  });
56029
+ var BATTERY_DEVICE_TYPES = [
56030
+ DeviceType.Camera,
56031
+ DeviceType.Sensor,
56032
+ DeviceType.Button,
56033
+ DeviceType.Switch,
56034
+ DeviceType.PetFeeder,
56035
+ DeviceType.Container,
56036
+ DeviceType.Thermostat
56037
+ ];
56038
+ /** Generic Customize target for the percentage reading (D936). */
56039
+ var batteryCustomize = {
56040
+ version: 1,
56041
+ targets: [{
56042
+ id: "percentage",
56043
+ cardinality: "scalar",
56044
+ vocabulary: {
56045
+ cap: "battery",
56046
+ stateField: "percentage"
56047
+ },
56048
+ deviceTypes: BATTERY_DEVICE_TYPES,
56049
+ apply: "add-or-replace",
56050
+ path: "percentage",
56051
+ sources: [{
56052
+ kind: "field",
56053
+ valueKinds: ["number", "string"],
56054
+ transforms: [{ kind: "identity" }, {
56055
+ kind: "linear",
56056
+ defaultScale: 1,
56057
+ defaultOffset: 0,
56058
+ clampMin: 0,
56059
+ clampMax: 100
56060
+ }]
56061
+ }],
56062
+ companions: [
56063
+ {
56064
+ kind: "constant",
56065
+ path: "charging",
56066
+ value: "unknown",
56067
+ when: "add"
56068
+ },
56069
+ {
56070
+ kind: "constant",
56071
+ path: "sleeping",
56072
+ value: false,
56073
+ when: "add"
56074
+ },
56075
+ {
56076
+ kind: "clock",
56077
+ path: "lastUpdated",
56078
+ when: "add"
56079
+ }
56080
+ ],
56081
+ sourceReport: { status: "assignment-status" },
56082
+ advancedExpression: true
56083
+ }]
56084
+ };
55658
56085
  var batteryCapability = {
55659
56086
  name: "battery",
55660
56087
  scope: "device",
55661
56088
  deviceNative: true,
55662
56089
  mode: "singleton",
55663
- deviceTypes: [
55664
- DeviceType.Camera,
55665
- DeviceType.Sensor,
55666
- DeviceType.Button,
55667
- DeviceType.Switch,
55668
- DeviceType.PetFeeder,
55669
- DeviceType.Container,
55670
- DeviceType.Thermostat
55671
- ],
56090
+ deviceTypes: BATTERY_DEVICE_TYPES,
55672
56091
  methods: {
55673
56092
  /**
55674
56093
  * Explicitly wake the camera from low-power sleep ahead of a
@@ -55752,6 +56171,7 @@ onStatusChanged: { data: object({
55752
56171
  kind: "gauge",
55753
56172
  unit: "%"
55754
56173
  } } },
56174
+ customize: batteryCustomize,
55755
56175
  /** Clock fields: written, but excluded from the compare that decides
55756
56176
  * whether persisting is worth a SQLite commit. */
55757
56177
  volatileStateFields: ["lastUpdated"]
@@ -56712,6 +57132,106 @@ var ConsumablesStatusSchema = object({
56712
57132
  items: array(ConsumableItemSchema),
56713
57133
  lastChangedAt: number()
56714
57134
  });
57135
+ /** Synthesize seed for a link-built status (no native provider).
57136
+ *
57137
+ * ⚠ NO LIVE CALLER since 2026-08-08 (device-links deleted; see
57138
+ * `CapabilityStatusSchema.empty`). The wiring guidance below was written for
57139
+ * exactly the case the operator is asking about again — a Dreame's HA
57140
+ * consumable-life sensors — so it is kept for that conversation, not because
57141
+ * anything reads it today. */
57142
+ var EMPTY_STATUS = {
57143
+ items: [],
57144
+ lastChangedAt: 0
57145
+ };
57146
+ /** Seed for a NEW link-built consumable item. `key`/`label` are overwritten
57147
+ * with the link's `itemKey` (see `status.itemArray`), so the placeholder
57148
+ * empty strings never survive into a validated item. Link-built items are
57149
+ * not resettable — there is no native provider to receive `reset()`.
57150
+ *
57151
+ * Wiring guidance (HA vacuum consumable-life sensors):
57152
+ * - a percent-remaining source (`numeric-sensor`, unit '%') → `level` via
57153
+ * `identity` (or `linear` scale 1 offset 0 clamp [0,100] to be safe);
57154
+ * - an hours-remaining source (e.g. Dreame 'Main Brush Time Left', unit 'h')
57155
+ * → `level` via `linear` with scale = 100 / max-hours for that item
57156
+ * (e.g. main brush 300 h → scale 0.3333) + clamp [0,100];
57157
+ * - a discrete source (`enum-sensor`, e.g. mop pad 'installed') → `status`
57158
+ * via `enum-map` (e.g. { installed: 'ok', missing: 'replace' }).
57159
+ * A numeric→'replace' THRESHOLD (level < 10 → 'replace') is NOT expressible
57160
+ * with the current transform kinds — leave `status` null (valid) until the
57161
+ * expression transform lands. */
57162
+ /** Generic Customize target for one consumable item (D936). Native rows stay read-only. */
57163
+ var consumablesCustomize = {
57164
+ version: 1,
57165
+ targets: [{
57166
+ id: "items",
57167
+ cardinality: "keyedArray",
57168
+ vocabulary: { cap: "consumables" },
57169
+ deviceTypes: Object.values(DeviceType),
57170
+ apply: "add",
57171
+ path: "items",
57172
+ keyField: "key",
57173
+ labelField: "label",
57174
+ itemSchema: ConsumableItemSchema,
57175
+ nativeItems: "read-only",
57176
+ sourceReport: { status: "assignment-status" },
57177
+ fields: [
57178
+ {
57179
+ path: "level",
57180
+ sources: [{
57181
+ kind: "numeric",
57182
+ transforms: [{ kind: "identity" }, {
57183
+ kind: "linear",
57184
+ defaultScale: 1,
57185
+ defaultOffset: 0,
57186
+ clampMin: 0,
57187
+ clampMax: 100
57188
+ }]
57189
+ }]
57190
+ },
57191
+ {
57192
+ path: "remaining.value",
57193
+ sources: [{
57194
+ kind: "numeric",
57195
+ transforms: [{ kind: "identity" }]
57196
+ }],
57197
+ literals: [{
57198
+ path: "remaining.unit",
57199
+ values: [...ConsumableRemainingUnitSchema.options]
57200
+ }]
57201
+ },
57202
+ {
57203
+ path: "status",
57204
+ sources: [{
57205
+ kind: "enum",
57206
+ transforms: [{
57207
+ kind: "enum-map",
57208
+ outputValues: [...ConsumableStatusSchema.options],
57209
+ unmapped: null
57210
+ }]
57211
+ }]
57212
+ }
57213
+ ],
57214
+ traits: [{
57215
+ path: "kind",
57216
+ values: [...ConsumableKindSchema.options],
57217
+ defaultValue: "wear"
57218
+ }, {
57219
+ path: "form",
57220
+ values: [...ConsumableFormSchema.options],
57221
+ defaultValue: "part"
57222
+ }],
57223
+ companions: [{
57224
+ kind: "clock",
57225
+ path: "lastChangedAt",
57226
+ when: "add"
57227
+ }, {
57228
+ kind: "clock",
57229
+ path: "lastFetchedAt",
57230
+ when: "add"
57231
+ }],
57232
+ advancedExpression: true
57233
+ }]
57234
+ };
56715
57235
  var consumablesCapability = {
56716
57236
  name: "consumables",
56717
57237
  scope: "device",
@@ -56749,10 +57269,7 @@ reset: method(object({
56749
57269
  status: {
56750
57270
  schema: ConsumablesStatusSchema,
56751
57271
  kind: "push",
56752
- empty: {
56753
- items: [],
56754
- lastChangedAt: 0
56755
- },
57272
+ empty: EMPTY_STATUS,
56756
57273
  itemArray: {
56757
57274
  path: "items",
56758
57275
  keyField: "key",
@@ -56788,6 +57305,7 @@ reset: method(object({
56788
57305
  * brush's remaining life and a dishwasher's salt are each recorded the moment
56789
57306
  * their provider reports them; an item that appears later gets its series.
56790
57307
  */
57308
+ customize: consumablesCustomize,
56791
57309
  history: {
56792
57310
  fields: {},
56793
57311
  items: {
@@ -57167,6 +57685,30 @@ var dayNightCapability = {
57167
57685
  volatileStateFields: ["lastFetchedAt"]
57168
57686
  };
57169
57687
  /**
57688
+ * display-palette — the cluster's one colour table (D939).
57689
+ *
57690
+ * Hub singleton. `getPalette` reports `unknown` when the settings store
57691
+ * cannot be read; it does not pretend the bundled preset was stored.
57692
+ * `setPalette` refuses a palette that fails the ΔE / contrast rule and names
57693
+ * the pairs.
57694
+ */
57695
+ var presetSummarySchema = object({
57696
+ id: string(),
57697
+ name: string(),
57698
+ swatches: record(string(), paletteSwatchSchema),
57699
+ fallbacks: array(string())
57700
+ });
57701
+ method(_void(), paletteResultSchema, {
57702
+ auth: "protected",
57703
+ role: "viewer"
57704
+ }), method(_void(), array(presetSummarySchema).readonly(), {
57705
+ auth: "protected",
57706
+ role: "viewer"
57707
+ }), method(setPaletteInputSchema, paletteReadySchema, {
57708
+ kind: "mutation",
57709
+ auth: "admin"
57710
+ });
57711
+ /**
57170
57712
  * Generic device-level status snapshot. Auto-registered by `BaseDevice`
57171
57713
  * for every device, regardless of provider — the kernel needs a uniform
57172
57714
  * cap-keyed slice for the basic device flags every consumer expects to
@@ -57530,6 +58072,36 @@ var dishwasherCapability = {
57530
58072
  powerOn: { kind: "boolean" }
57531
58073
  } }
57532
58074
  };
58075
+ /** Pulse override: a rising edge advances `lastPressedAt` and the press count. */
58076
+ var doorbellCustomize = {
58077
+ version: 1,
58078
+ targets: [{
58079
+ id: "pressed",
58080
+ cardinality: "event",
58081
+ shape: "pulse",
58082
+ vocabulary: {
58083
+ cap: "doorbell",
58084
+ eventName: "onPressed"
58085
+ },
58086
+ deviceTypes: [DeviceType.Camera],
58087
+ apply: "add",
58088
+ applyAuthority: { kind: "composition-claim" },
58089
+ eventName: "onPressed",
58090
+ edges: ["rising"],
58091
+ timestampPath: "lastPressedAt",
58092
+ counterPath: "pressCountSinceStart",
58093
+ highWater: "composer-advance",
58094
+ combine: "any",
58095
+ debounce: {
58096
+ kind: "rising-edge",
58097
+ defaultDebounceMs: 2e3,
58098
+ changedAtRequired: true
58099
+ },
58100
+ sources: [{ kind: "binary" }, { kind: "switch" }],
58101
+ sourceReport: { status: "assignment-status" },
58102
+ advancedExpression: true
58103
+ }]
58104
+ };
57533
58105
  var DoorbellStatusSchema = object({
57534
58106
  /** Ms epoch of the last press. null = never observed since this provider started. */
57535
58107
  lastPressedAt: number().nullable(),
@@ -57596,7 +58168,8 @@ onPressed: {
57596
58168
  /**
57597
58169
  * History (D850): none — `pressCountSinceStart` resets with the addon, so it is not a monotonic meter; presses live in the events ledger.
57598
58170
  */
57599
- history: "none"
58171
+ history: "none",
58172
+ customize: doorbellCustomize
57600
58173
  };
57601
58174
  /**
57602
58175
  * Enum-state sensor — a string value picked from a finite option set.
@@ -59992,6 +60565,38 @@ authKey: string().optional() }), object({
59992
60565
  /** Human-readable error when `ok: false`. */
59993
60566
  error: string().optional()
59994
60567
  }), { kind: "mutation" });
60568
+ /** Span override: start on a rising edge, end on a fall or this timeout. */
60569
+ var motionCustomize = {
60570
+ version: 1,
60571
+ targets: [{
60572
+ id: "detected",
60573
+ cardinality: "event",
60574
+ shape: "span",
60575
+ vocabulary: {
60576
+ cap: "motion",
60577
+ eventName: "onMotionChanged"
60578
+ },
60579
+ deviceTypes: [DeviceType.Camera],
60580
+ apply: "replace",
60581
+ applyAuthority: {
60582
+ kind: "camera-sensors",
60583
+ timeoutField: "motionCooldownMs"
60584
+ },
60585
+ eventName: "onMotionChanged",
60586
+ start: "rising-edge",
60587
+ end: "falling-edge-or-timeout",
60588
+ timeoutMs: 3e4,
60589
+ combine: "any",
60590
+ sourceModes: [
60591
+ "in-addition",
60592
+ "confirm",
60593
+ "replace"
60594
+ ],
60595
+ sources: [{ kind: "binary" }, { kind: "switch" }],
60596
+ sourceReport: { status: "assignment-status" },
60597
+ advancedExpression: false
60598
+ }]
60599
+ };
59995
60600
  var MotionStatusSchema = object({
59996
60601
  detected: boolean(),
59997
60602
  /** Ms epoch of the last detected-true observation. Null if never detected. */
@@ -60131,7 +60736,8 @@ onMotionChanged: { data: MotionOnMotionChangedDataSchema } },
60131
60736
  history: { fields: { detected: {
60132
60737
  kind: "boolean",
60133
60738
  excludeDeviceTypes: [DeviceType.Camera]
60134
- } } }
60739
+ } } },
60740
+ customize: motionCustomize
60135
60741
  };
60136
60742
  /**
60137
60743
  * Motion-trigger toggle for accessory devices.
@@ -61950,6 +62556,30 @@ includeCrops: boolean().optional() }).optional(), array(VehicleSchema).readonly(
61950
62556
  kind: "mutation",
61951
62557
  auth: "admin"
61952
62558
  });
62559
+ var CORE_ULTRA_265K_IGPU_CLOCK_MHZ = 2e3;
62560
+ var positiveOrNull = number().nullable().transform((value) => value !== null && Number.isFinite(value) && value > 0 ? value : null);
62561
+ var textOrNull = string().nullable().transform((value) => value !== null && value.trim() !== "" ? value : null);
62562
+ var PrecisionGopsSchema = object({
62563
+ int8: positiveOrNull,
62564
+ fp16: positiveOrNull
62565
+ });
62566
+ /** What one accelerator device reported. Every failed query is null. */
62567
+ var AcceleratorComputeSchema = object({
62568
+ deviceKey: string(),
62569
+ fullDeviceName: textOrNull,
62570
+ executionUnits: positiveOrNull,
62571
+ clockMHz: positiveOrNull,
62572
+ gops: PrecisionGopsSchema.nullable(),
62573
+ architecture: textOrNull,
62574
+ npuName: textOrNull,
62575
+ tops: positiveOrNull,
62576
+ vendor: textOrNull,
62577
+ webgpuArchitecture: textOrNull,
62578
+ webgpuDevice: textOrNull,
62579
+ computeUnits: positiveOrNull
62580
+ });
62581
+ object({ accelerators: array(AcceleratorComputeSchema).nullable() });
62582
+ 64 * CORE_ULTRA_265K_IGPU_CLOCK_MHZ;
61953
62583
  var ModelFormatSchema = _enum(MODEL_FORMATS);
61954
62584
  var HwAccelBackendInputSchema = _enum([
61955
62585
  "videotoolbox",
@@ -62063,7 +62693,12 @@ var HardwareInfoSchema = object({
62063
62693
  availableRAM_MB: number(),
62064
62694
  gpu: GpuInfoSchema.nullable(),
62065
62695
  npu: NpuInfoSchema.nullable(),
62066
- coral: CoralInfoSchema.nullable().optional()
62696
+ coral: CoralInfoSchema.nullable().optional(),
62697
+ /**
62698
+ * Per-accelerator compute (D930). Omitted by a node that has not probed it.
62699
+ * `null` fields inside an entry are a failed query, never a zero.
62700
+ */
62701
+ accelerators: array(AcceleratorComputeSchema).readonly().optional()
62067
62702
  });
62068
62703
  var PlatformScoreSchema = object({
62069
62704
  runtime: literal("python"),
@@ -63006,6 +63641,125 @@ var ptzAutotrackCapability = {
63006
63641
  */
63007
63642
  history: "none"
63008
63643
  };
63644
+ var RUNNING_POWER_START_DELAY_MS = 3e4;
63645
+ var RUNNING_POWER_STOP_DELAY_MS = 18e4;
63646
+ var RunningStateSourceSchema = _enum(["native", "assigned"]);
63647
+ var RunningStateStatusSchema = object({
63648
+ /** null = unknown — never coerced to false (D393). */
63649
+ running: boolean().nullable(),
63650
+ /** Epoch ms the current boolean began; null while `running` is null. */
63651
+ since: number().nullable(),
63652
+ source: RunningStateSourceSchema,
63653
+ phase: string().nullable(),
63654
+ /** null until a reading has been published (D393). */
63655
+ lastFetchedAt: number().nullable()
63656
+ });
63657
+ var RunningFlipEventDataSchema = object({
63658
+ deviceId: number(),
63659
+ since: number().nullable(),
63660
+ phase: string().nullable()
63661
+ });
63662
+ var RUNNING_DEVICE_TYPES = Object.values(DeviceType);
63663
+ /** Generic Customize target for the running boolean (D936). */
63664
+ var runningCustomize = {
63665
+ version: 1,
63666
+ targets: [{
63667
+ id: "running",
63668
+ cardinality: "scalar",
63669
+ vocabulary: {
63670
+ cap: "running-state",
63671
+ stateField: "running"
63672
+ },
63673
+ deviceTypes: [
63674
+ DeviceType.Dishwasher,
63675
+ DeviceType.Vacuum,
63676
+ DeviceType.LawnMower,
63677
+ DeviceType.MediaPlayer,
63678
+ DeviceType.WaterHeater,
63679
+ DeviceType.Humidifier,
63680
+ DeviceType.Fan,
63681
+ DeviceType.Climate,
63682
+ DeviceType.Thermostat,
63683
+ DeviceType.PetFeeder
63684
+ ],
63685
+ apply: "add-or-replace",
63686
+ path: "running",
63687
+ sources: [
63688
+ {
63689
+ kind: "switch",
63690
+ transforms: [{ kind: "identity" }]
63691
+ },
63692
+ {
63693
+ kind: "binary",
63694
+ transforms: [{ kind: "identity" }, { kind: "invert" }]
63695
+ },
63696
+ {
63697
+ kind: "numeric",
63698
+ requiredUnit: "W",
63699
+ transforms: [{
63700
+ kind: "threshold",
63701
+ comparison: "gte",
63702
+ defaultThreshold: 5,
63703
+ defaultStartDwellMs: RUNNING_POWER_START_DELAY_MS,
63704
+ defaultStopDwellMs: RUNNING_POWER_STOP_DELAY_MS,
63705
+ thresholdUnit: "W"
63706
+ }]
63707
+ }
63708
+ ],
63709
+ companions: [
63710
+ {
63711
+ kind: "constant",
63712
+ path: "source",
63713
+ value: "assigned",
63714
+ when: "always"
63715
+ },
63716
+ {
63717
+ kind: "constant",
63718
+ path: "phase",
63719
+ value: null,
63720
+ when: "always"
63721
+ },
63722
+ {
63723
+ kind: "clock",
63724
+ path: "lastFetchedAt",
63725
+ when: "always"
63726
+ },
63727
+ {
63728
+ kind: "transition-time",
63729
+ path: "since",
63730
+ sourceChangedAt: "prefer"
63731
+ }
63732
+ ],
63733
+ sourceReport: {
63734
+ status: "assignment-status",
63735
+ runtimeField: "source",
63736
+ nativeValue: "native",
63737
+ assignedValue: "assigned"
63738
+ },
63739
+ advancedExpression: true
63740
+ }]
63741
+ };
63742
+ var runningStateCapability = {
63743
+ name: "running-state",
63744
+ scope: "device",
63745
+ deviceNative: true,
63746
+ mode: "singleton",
63747
+ deviceTypes: RUNNING_DEVICE_TYPES,
63748
+ methods: {},
63749
+ events: {
63750
+ onStarted: { data: RunningFlipEventDataSchema },
63751
+ onFinished: { data: RunningFlipEventDataSchema }
63752
+ },
63753
+ status: {
63754
+ schema: RunningStateStatusSchema,
63755
+ kind: "push"
63756
+ },
63757
+ runtimeState: RunningStateStatusSchema,
63758
+ durability: "restored",
63759
+ history: { fields: { running: { kind: "boolean" } } },
63760
+ volatileStateFields: ["lastFetchedAt"],
63761
+ customize: runningCustomize
63762
+ };
63009
63763
  /**
63010
63764
  * reboot — device-scoped capability for "soft" device reboots (firmware
63011
63765
  * reboot via vendor protocol; cameras, NVRs, doorbells). Surfaces a
@@ -65177,7 +65931,20 @@ var ZoneRuleSchema = object({
65177
65931
  * Defaults to `true` so operators creating a rule via the UI
65178
65932
  * see it active immediately.
65179
65933
  */
65180
- enabled: boolean().default(true)
65934
+ enabled: boolean().default(true),
65935
+ /**
65936
+ * Package stage only. When true, a package candidate may open from a
65937
+ * scene difference in this rule's zone after a person leaves. The
65938
+ * package model, when it boxes something overlapping, is extra evidence
65939
+ * and is not the gate. Absent or false keeps today's model path.
65940
+ */
65941
+ detectBySceneDifference: boolean().optional(),
65942
+ /**
65943
+ * Package stage only. When true, a promoted package is shown to the
65944
+ * `llm` cap before the delivery event is emitted. Absent or false emits
65945
+ * as today. Usable with or without `detectBySceneDifference`.
65946
+ */
65947
+ confirmWithLlm: boolean().optional()
65181
65948
  });
65182
65949
  array(ZoneRuleSchema).readonly();
65183
65950
  /**
@@ -67733,7 +68500,7 @@ method(object({}), array(TrainingProviderDescriptorSchema).readonly(), { auth: "
67733
68500
  * - **Jobs.** A persisted state machine, a reconcile loop against the
67734
68501
  * provider, a cost guard, a daily orphan sweep and the retention rules.
67735
68502
  * - **The return flow.** Verified artefacts → Model Studio
67736
- * (`custom-model-registry.importModelBundle`) → canary on cameras →
68503
+ * (`custom-model-registry.importModelBundle`) → canary on accelerators →
67737
68504
  * rollback. Nothing is ever registered automatically.
67738
68505
  *
67739
68506
  * Plan/start takes a live {@link TrainingCorpusSelection} (collections +
@@ -67870,20 +68637,24 @@ var TrainingProgressPointSchema = object({
67870
68637
  map50: number().nullable(),
67871
68638
  map50_95: number().nullable()
67872
68639
  });
68640
+ /** One accelerator: a `(node, inference device)` that runs the root detector. */
68641
+ var TrainingAcceleratorRefSchema = object({
68642
+ nodeId: string(),
68643
+ deviceKey: string()
68644
+ });
68645
+ /**
68646
+ * A canary pins the registered model on chosen ACCELERATORS — a model is
68647
+ * chosen by the accelerator that runs it (D927); every camera balanced onto
68648
+ * one runs it. `previous` is the root-detector pin each one had (`null` = it
68649
+ * ran its default), exactly, so rollback restores it.
68650
+ */
67873
68651
  var TrainingCanarySchema = object({
67874
- deviceIds: array(number().int()).readonly(),
68652
+ accelerators: array(TrainingAcceleratorRefSchema).readonly(),
67875
68653
  since: number(),
67876
- /** Every override the canary replaced, exactly, so rollback restores it. */
67877
- previous: array(object({
67878
- deviceId: number().int(),
67879
- nodeId: string(),
67880
- deviceKey: string(),
67881
- patch: object({
67882
- modelId: string().optional(),
67883
- settings: record(string(), unknown()).readonly().optional()
67884
- }).nullable()
67885
- })).readonly()
68654
+ previous: array(TrainingAcceleratorRefSchema.extend({ modelId: string().nullable() })).readonly()
67886
68655
  });
68656
+ /** An accelerator a canary may pin: it runs the root detector, on this model now. */
68657
+ var TrainingCanaryTargetSchema = TrainingAcceleratorRefSchema.extend({ pinnedModelId: string().nullable() });
67887
68658
  var TrainingJobSchema = object({
67888
68659
  id: string(),
67889
68660
  idempotencyKey: string(),
@@ -67995,11 +68766,11 @@ method(object({}), array(TrainingBaseModelSchema).readonly(), { auth: "admin" })
67995
68766
  kind: "mutation",
67996
68767
  auth: "admin",
67997
68768
  timeoutMs: 12e4
67998
- }), method(IdInput, TrainingResultSchema.nullable(), { auth: "admin" }), method(IdInput.extend({ canaryDeviceIds: array(number().int()).readonly() }), TrainingJobSchema, {
68769
+ }), method(IdInput, TrainingResultSchema.nullable(), { auth: "admin" }), method(_void(), array(TrainingCanaryTargetSchema).readonly(), { auth: "admin" }), method(IdInput.extend({ canaryAccelerators: array(TrainingAcceleratorRefSchema).readonly() }), TrainingJobSchema, {
67999
68770
  kind: "mutation",
68000
68771
  auth: "admin",
68001
68772
  timeoutMs: 30 * 6e4
68002
- }), method(IdInput.extend({ deviceIds: array(number().int()).min(1).readonly() }), TrainingJobSchema, {
68773
+ }), method(IdInput.extend({ accelerators: array(TrainingAcceleratorRefSchema).min(1).readonly() }), TrainingJobSchema, {
68003
68774
  kind: "mutation",
68004
68775
  auth: "admin",
68005
68776
  timeoutMs: 12e4
@@ -68510,6 +69281,7 @@ var DEVICE_LOCAL_STATE_CAPS = {
68510
69281
  ptzAutotrack: ptzAutotrackCapability,
68511
69282
  recordingOnboard: recordingOnboardCapability,
68512
69283
  recordingSignal: recordingSignalCapability,
69284
+ runningState: runningStateCapability,
68513
69285
  sceneMonitor: sceneMonitorCapability,
68514
69286
  scriptRunner: scriptRunnerCapability,
68515
69287
  smoke: smokeCapability,
@@ -72702,6 +73474,27 @@ Object.freeze({
72702
73474
  access: "create",
72703
73475
  role: "viewer"
72704
73476
  },
73477
+ "displayPalette.getPalette": {
73478
+ capName: "display-palette",
73479
+ capScope: "system",
73480
+ addonId: null,
73481
+ access: "view",
73482
+ role: "viewer"
73483
+ },
73484
+ "displayPalette.listPresets": {
73485
+ capName: "display-palette",
73486
+ capScope: "system",
73487
+ addonId: null,
73488
+ access: "view",
73489
+ role: "viewer"
73490
+ },
73491
+ "displayPalette.setPalette": {
73492
+ capName: "display-palette",
73493
+ capScope: "system",
73494
+ addonId: null,
73495
+ access: "create",
73496
+ role: "admin"
73497
+ },
72705
73498
  "doorbell.getStatus": {
72706
73499
  capName: "doorbell",
72707
73500
  capScope: "device",
@@ -75621,20 +76414,6 @@ Object.freeze({
75621
76414
  access: "create",
75622
76415
  role: "admin"
75623
76416
  },
75624
- "pipelineExecutor.clearDeviceOverrides": {
75625
- capName: "pipeline-executor",
75626
- capScope: "system",
75627
- addonId: null,
75628
- access: "delete",
75629
- role: "admin"
75630
- },
75631
- "pipelineExecutor.clearModelBoundDeviceOverrides": {
75632
- capName: "pipeline-executor",
75633
- capScope: "system",
75634
- addonId: null,
75635
- access: "delete",
75636
- role: "admin"
75637
- },
75638
76417
  "pipelineExecutor.deleteModel": {
75639
76418
  capName: "pipeline-executor",
75640
76419
  capScope: "system",
@@ -75677,13 +76456,6 @@ Object.freeze({
75677
76456
  access: "view",
75678
76457
  role: "admin"
75679
76458
  },
75680
- "pipelineExecutor.getDefaultSteps": {
75681
- capName: "pipeline-executor",
75682
- capScope: "system",
75683
- addonId: null,
75684
- access: "view",
75685
- role: "admin"
75686
- },
75687
76459
  "pipelineExecutor.getDetectionConfigSchema": {
75688
76460
  capName: "pipeline-executor",
75689
76461
  capScope: "system",
@@ -75705,20 +76477,6 @@ Object.freeze({
75705
76477
  access: "view",
75706
76478
  role: "admin"
75707
76479
  },
75708
- "pipelineExecutor.getGlobalPipelineConfig": {
75709
- capName: "pipeline-executor",
75710
- capScope: "system",
75711
- addonId: null,
75712
- access: "view",
75713
- role: "admin"
75714
- },
75715
- "pipelineExecutor.getGlobalSteps": {
75716
- capName: "pipeline-executor",
75717
- capScope: "system",
75718
- addonId: null,
75719
- access: "view",
75720
- role: "admin"
75721
- },
75722
76480
  "pipelineExecutor.getInferenceDeviceHealth": {
75723
76481
  capName: "pipeline-executor",
75724
76482
  capScope: "system",
@@ -75978,13 +76736,6 @@ Object.freeze({
75978
76736
  access: "view",
75979
76737
  role: "admin"
75980
76738
  },
75981
- "pipelineOrchestrator.getCameraStepOverrides": {
75982
- capName: "pipeline-orchestrator",
75983
- capScope: "system",
75984
- addonId: null,
75985
- access: "view",
75986
- role: "admin"
75987
- },
75988
76739
  "pipelineOrchestrator.getCameraSwitches": {
75989
76740
  capName: "pipeline-orchestrator",
75990
76741
  capScope: "system",
@@ -76223,13 +76974,6 @@ Object.freeze({
76223
76974
  access: "create",
76224
76975
  role: "admin"
76225
76976
  },
76226
- "pipelineOrchestrator.setCameraPipelineForAgent": {
76227
- capName: "pipeline-orchestrator",
76228
- capScope: "system",
76229
- addonId: null,
76230
- access: "create",
76231
- role: "admin"
76232
- },
76233
76977
  "pipelineOrchestrator.setCameraSensors": {
76234
76978
  capName: "pipeline-orchestrator",
76235
76979
  capScope: "system",
@@ -76237,42 +76981,42 @@ Object.freeze({
76237
76981
  access: "create",
76238
76982
  role: "admin"
76239
76983
  },
76240
- "pipelineOrchestrator.setCameraStepOverride": {
76984
+ "pipelineOrchestrator.setCameraStepSettings": {
76241
76985
  capName: "pipeline-orchestrator",
76242
76986
  capScope: "system",
76243
76987
  addonId: null,
76244
76988
  access: "create",
76245
76989
  role: "admin"
76246
76990
  },
76247
- "pipelineOrchestrator.setCameraStepSettings": {
76991
+ "pipelineOrchestrator.setCameraStepToggle": {
76248
76992
  capName: "pipeline-orchestrator",
76249
76993
  capScope: "system",
76250
76994
  addonId: null,
76251
76995
  access: "create",
76252
76996
  role: "admin"
76253
76997
  },
76254
- "pipelineOrchestrator.setCameraStepToggle": {
76998
+ "pipelineOrchestrator.setCameraSwitch": {
76255
76999
  capName: "pipeline-orchestrator",
76256
77000
  capScope: "system",
76257
77001
  addonId: null,
76258
77002
  access: "create",
76259
77003
  role: "admin"
76260
77004
  },
76261
- "pipelineOrchestrator.setCameraSwitch": {
77005
+ "pipelineOrchestrator.setCapabilityBinding": {
76262
77006
  capName: "pipeline-orchestrator",
76263
77007
  capScope: "system",
76264
77008
  addonId: null,
76265
77009
  access: "create",
76266
77010
  role: "admin"
76267
77011
  },
76268
- "pipelineOrchestrator.setCapabilityBinding": {
77012
+ "pipelineOrchestrator.setLoadBalancingShares": {
76269
77013
  capName: "pipeline-orchestrator",
76270
77014
  capScope: "system",
76271
77015
  addonId: null,
76272
77016
  access: "create",
76273
77017
  role: "admin"
76274
77018
  },
76275
- "pipelineOrchestrator.setLoadBalancingShares": {
77019
+ "pipelineOrchestrator.setNodeStepSettings": {
76276
77020
  capName: "pipeline-orchestrator",
76277
77021
  capScope: "system",
76278
77022
  addonId: null,
@@ -77301,6 +78045,13 @@ Object.freeze({
77301
78045
  access: "create",
77302
78046
  role: "admin"
77303
78047
  },
78048
+ "runningState.getStatus": {
78049
+ capName: "running-state",
78050
+ capScope: "device",
78051
+ addonId: null,
78052
+ access: "view",
78053
+ role: "viewer"
78054
+ },
77304
78055
  "sceneMonitor.captureReference": {
77305
78056
  capName: "scene-monitor",
77306
78057
  capScope: "device",
@@ -78631,6 +79382,13 @@ Object.freeze({
78631
79382
  access: "view",
78632
79383
  role: "admin"
78633
79384
  },
79385
+ "training.listCanaryTargets": {
79386
+ capName: "training",
79387
+ capScope: "system",
79388
+ addonId: null,
79389
+ access: "view",
79390
+ role: "admin"
79391
+ },
78634
79392
  "training.listJobs": {
78635
79393
  capName: "training",
78636
79394
  capScope: "system",
@@ -82008,6 +82766,32 @@ var APPLIANCE_CAP_VOCABULARY = {
82008
82766
  }],
82009
82767
  events: { onSent: { notOperatorFacing: "a delivery receipt of a send this system made — not a fact about the world" } }
82010
82768
  },
82769
+ "running-state": {
82770
+ scope: "device",
82771
+ noun: t("Running", "In funzione"),
82772
+ state: [{
82773
+ kind: "boolean",
82774
+ field: "running",
82775
+ label: t("Running", "In funzione"),
82776
+ whenTrue: t("When {device} starts", "Quando {device} inizia"),
82777
+ whenFalse: t("When {device} finishes", "Quando {device} finisce"),
82778
+ icon: "play"
82779
+ }],
82780
+ events: {
82781
+ onStarted: {
82782
+ category: EventCategory.RunningStarted,
82783
+ label: t("Started running", "Ha iniziato a funzionare"),
82784
+ phrase: t("When {device} starts running", "Quando {device} inizia a funzionare"),
82785
+ icon: "play"
82786
+ },
82787
+ onFinished: {
82788
+ category: EventCategory.RunningFinished,
82789
+ label: t("Finished", "Ha finito"),
82790
+ phrase: t("When {device} finishes", "Quando {device} finisce"),
82791
+ icon: "square"
82792
+ }
82793
+ }
82794
+ },
82011
82795
  update: {
82012
82796
  scope: "device",
82013
82797
  noun: t("Firmware update", "Aggiornamento firmware"),
@@ -83167,6 +83951,7 @@ var SYSTEM_CAP_VOCABULARY = {
83167
83951
  "device-provider": system(INTERNAL),
83168
83952
  "device-removal-hook": system(INTERNAL),
83169
83953
  "device-state": system("the runtime-state mirror every trigger already reads through"),
83954
+ "display-palette": system("the cluster display palette — one colour table for every client, not a device action"),
83170
83955
  "embedding-encoder": system(ML),
83171
83956
  "face-gallery": system("the face gallery — curated on its own page"),
83172
83957
  "failure-contribution": system(INTERNAL),
@@ -85169,11 +85954,6 @@ Object.freeze({
85169
85954
  form: "single",
85170
85955
  optional: false
85171
85956
  }],
85172
- "pipelineExecutor.clearModelBoundDeviceOverrides": [{
85173
- name: "deviceIds",
85174
- form: "array",
85175
- optional: true
85176
- }],
85177
85957
  "pipelineExecutor.runPipeline": [{
85178
85958
  name: "deviceId",
85179
85959
  form: "single",
@@ -85229,11 +86009,6 @@ Object.freeze({
85229
86009
  form: "array",
85230
86010
  optional: true
85231
86011
  }],
85232
- "pipelineOrchestrator.getCameraStepOverrides": [{
85233
- name: "deviceId",
85234
- form: "single",
85235
- optional: false
85236
- }],
85237
86012
  "pipelineOrchestrator.getCameraSwitches": [{
85238
86013
  name: "deviceId",
85239
86014
  form: "single",
@@ -85274,21 +86049,11 @@ Object.freeze({
85274
86049
  form: "single",
85275
86050
  optional: false
85276
86051
  }],
85277
- "pipelineOrchestrator.setCameraPipelineForAgent": [{
85278
- name: "deviceId",
85279
- form: "single",
85280
- optional: false
85281
- }],
85282
86052
  "pipelineOrchestrator.setCameraSensors": [{
85283
86053
  name: "deviceId",
85284
86054
  form: "single",
85285
86055
  optional: false
85286
86056
  }],
85287
- "pipelineOrchestrator.setCameraStepOverride": [{
85288
- name: "deviceId",
85289
- form: "single",
85290
- optional: false
85291
- }],
85292
86057
  "pipelineOrchestrator.setCameraStepSettings": [{
85293
86058
  name: "deviceId",
85294
86059
  form: "single",
@@ -85720,6 +86485,11 @@ Object.freeze({
85720
86485
  form: "single",
85721
86486
  optional: true
85722
86487
  }],
86488
+ "runningState.getStatus": [{
86489
+ name: "deviceId",
86490
+ form: "single",
86491
+ optional: false
86492
+ }],
85723
86493
  "sceneMonitor.captureReference": [{
85724
86494
  name: "deviceId",
85725
86495
  form: "single",
@@ -85966,11 +86736,6 @@ Object.freeze({
85966
86736
  form: "single",
85967
86737
  optional: false
85968
86738
  }],
85969
- "training.canaryResult": [{
85970
- name: "deviceIds",
85971
- form: "array",
85972
- optional: false
85973
- }],
85974
86739
  "update.getStatus": [{
85975
86740
  name: "deviceId",
85976
86741
  form: "single",
@@ -86223,6 +86988,96 @@ Object.freeze({
86223
86988
  "smtp-provider": "email"
86224
86989
  });
86225
86990
  DeviceType.Camera;
86991
+ 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;
86992
+ /**
86993
+ * A saved Customize assignment (D936). The schema is the type: callers use
86994
+ * `z.infer`, they do not restate the shape.
86995
+ */
86996
+ var OverrideSourceSchema = object({
86997
+ addonId: string().min(1),
86998
+ stableId: string().min(1),
86999
+ cap: string().min(1),
87000
+ fieldPath: string().min(1)
87001
+ });
87002
+ var CustomizeTransformDraftSchema = discriminatedUnion("kind", [
87003
+ object({ kind: literal("identity") }),
87004
+ object({ kind: literal("invert") }),
87005
+ object({
87006
+ kind: literal("threshold"),
87007
+ comparison: _enum(["gte", "lte"]),
87008
+ threshold: number(),
87009
+ startDwellMs: number().nonnegative(),
87010
+ stopDwellMs: number().nonnegative()
87011
+ }),
87012
+ object({
87013
+ kind: literal("linear"),
87014
+ scale: number(),
87015
+ offset: number(),
87016
+ clampMin: number().optional(),
87017
+ clampMax: number().optional()
87018
+ }),
87019
+ object({
87020
+ kind: literal("enum-map"),
87021
+ mapping: record(string(), string().nullable())
87022
+ }),
87023
+ object({ kind: literal("number") })
87024
+ ]);
87025
+ var ScalarOverrideDraftSchema = object({
87026
+ kind: literal("scalar"),
87027
+ cap: string().min(1),
87028
+ targetId: string().min(1),
87029
+ source: OverrideSourceSchema,
87030
+ transform: CustomizeTransformDraftSchema
87031
+ });
87032
+ var KeyedArrayOverrideDraftSchema = object({
87033
+ kind: literal("keyedArray"),
87034
+ cap: string().min(1),
87035
+ targetId: string().min(1),
87036
+ key: string().min(1),
87037
+ label: string().min(1),
87038
+ fieldPath: string().min(1),
87039
+ source: OverrideSourceSchema,
87040
+ transform: CustomizeTransformDraftSchema
87041
+ });
87042
+ var PulseOverrideDraftSchema = object({
87043
+ kind: literal("pulse"),
87044
+ cap: string().min(1),
87045
+ targetId: string().min(1),
87046
+ enabled: boolean(),
87047
+ debounceMs: number().nonnegative(),
87048
+ sources: array(OverrideSourceSchema).min(1)
87049
+ });
87050
+ var SpanSourceDraftSchema = OverrideSourceSchema.extend({ mode: _enum([
87051
+ "in-addition",
87052
+ "confirm",
87053
+ "replace"
87054
+ ]).optional() });
87055
+ discriminatedUnion("kind", [
87056
+ ScalarOverrideDraftSchema,
87057
+ KeyedArrayOverrideDraftSchema,
87058
+ PulseOverrideDraftSchema,
87059
+ object({
87060
+ kind: literal("span"),
87061
+ cap: string().min(1),
87062
+ targetId: string().min(1),
87063
+ timeoutMs: number().nonnegative(),
87064
+ cooldownMs: number().nonnegative().optional(),
87065
+ sources: array(SpanSourceDraftSchema)
87066
+ })
87067
+ ]);
87068
+ object({
87069
+ targetId: string().min(1),
87070
+ configured: boolean(),
87071
+ source: _enum(["native", "assigned"]),
87072
+ state: _enum([
87073
+ "active",
87074
+ "stale",
87075
+ "released",
87076
+ "unavailable"
87077
+ ]),
87078
+ reason: string().nullable()
87079
+ });
87080
+ String.raw`rose\(active(\d+), changed(\d+), (\d+(?:\.\d+)?)\)`;
86226
87081
  var G711_SCALE_CORRECTION_DB = {
86227
87082
  PCMU: 20 * Math.log10(4),
86228
87083
  PCMA: 20 * Math.log10(8)
@@ -86275,40 +87130,7 @@ var NC_AUDIO_DEFAULTS = {
86275
87130
  samplingSeconds: 10
86276
87131
  };
86277
87132
  new Set(["devices", "classes"]);
86278
- /**
86279
- * WHICH narrowing filter speaks about WHICH system-event kind — one predicate,
86280
- * consumed by the rule ENGINE and by every rule EDITOR.
86281
- *
86282
- * ── The failure this file exists for ───────────────────────────────────────
86283
- * `NcSystemEventConditionSchema` carries four optional narrowing lists
86284
- * (`deviceIds`, `deviceTypes`, `nodeIds`, `packageNames`) beside a required
86285
- * `kinds` gate. They are not four filters over one vocabulary: each belongs to
86286
- * a FAMILY of kinds and is meaningless outside it. A node going away has no
86287
- * device type; a completed export has no package; `stream-offline` deliberately
86288
- * carries no device type at all (a stream belongs to a camera by construction).
86289
- *
86290
- * The engine applied all four to every kind, so a filter from one family failed
86291
- * a kind from another family CLOSED. The operator's live rule "Eventi di
86292
- * sistema" selected eleven kinds and set `deviceTypes: ['camera']` — the only
86293
- * way to say "only my cameras" about the two liveness kinds — and NINE of the
86294
- * eleven silently stopped being deliverable. Four days of history contained
86295
- * `device-online` and `device-offline` and nothing else, across a window in
86296
- * which agents were restarted and addons were updated.
86297
- *
86298
- * Both editors already computed this scoping, to decide which filter boxes to
86299
- * render; the cap's own docblock already promised it ("Narrow a `device-*` kind
86300
- * to these device TYPES"). Only the engine disagreed, and it disagreed in the
86301
- * destructive direction. So the rule is stated ONCE, here, and the engine and
86302
- * the editors are readers of it rather than three independent authors.
86303
- *
86304
- * ── The direction ─────────────────────────────────────────────────────────
86305
- * Out of family ⇒ the filter is IGNORED, never fail-closed. An editor that
86306
- * hides a box has already told the operator this filter does not speak about
86307
- * these kinds, so honouring it as an exclusion contradicts the only
86308
- * explanation the operator was ever given. Inside its family the filter still
86309
- * narrows, and still fails CLOSED on a subject that cannot produce the identity
86310
- * it tests (a device the mirror cannot name is not evidence of a camera).
86311
- */
87133
+ new Set(NC_LEGACY_SYSTEM_EVENT_KINDS);
86312
87134
  /**
86313
87135
  * Every filter, for the callers that must cover all of them (guards, tests).
86314
87136
  *
@@ -86334,9 +87156,6 @@ new Map(Object.entries({
86334
87156
  "device-battery-normal": "device-events",
86335
87157
  "device-consumable-low": "device-events",
86336
87158
  "device-consumable-normal": "device-events",
86337
- "device-tank-low": "device-events",
86338
- "device-tank-full": "device-events",
86339
- "device-tank-normal": "device-events",
86340
87159
  "stream-online": "device-events",
86341
87160
  "stream-offline": "device-events",
86342
87161
  "detection-blind": "device-events",
@@ -86413,16 +87232,6 @@ var NC_SYSTEM_EVENT_KIND_GROUP_SPECS = [
86413
87232
  label: "Consumables",
86414
87233
  kinds: ["device-consumable-low", "device-consumable-normal"]
86415
87234
  },
86416
- {
86417
- id: "tanks",
86418
- family: "device-events",
86419
- label: "Tanks",
86420
- kinds: [
86421
- "device-tank-low",
86422
- "device-tank-full",
86423
- "device-tank-normal"
86424
- ]
86425
- },
86426
87235
  {
86427
87236
  id: "detection-blind",
86428
87237
  family: "device-events",
@@ -86580,11 +87389,6 @@ var RULE_BODY_ONLY = ["body"];
86580
87389
  var RULE_TEXT = ["title", "body"];
86581
87390
  var BATTERY = ["device-battery-low", "device-battery-normal"];
86582
87391
  var CONSUMABLE = ["device-consumable-low", "device-consumable-normal"];
86583
- var TANK = [
86584
- "device-tank-low",
86585
- "device-tank-full",
86586
- "device-tank-normal"
86587
- ];
86588
87392
  var ALERT_EPISODE = [
86589
87393
  "alert-critical",
86590
87394
  "alert-error",
@@ -86616,7 +87420,6 @@ var DEVICE_EVENTS = [
86616
87420
  "device-enabled",
86617
87421
  ...BATTERY,
86618
87422
  ...CONSUMABLE,
86619
- ...TANK,
86620
87423
  "stream-online",
86621
87424
  "stream-offline",
86622
87425
  "detection-blind",
@@ -86662,12 +87465,6 @@ var STATE_SUMMARY_SECTION_VARS = [
86662
87465
  example: "Robot — filter 10 %",
86663
87466
  kinds: CONSUMABLE
86664
87467
  },
86665
- {
86666
- name: "summaryTanks",
86667
- label: "Summary: tanks",
86668
- example: "Robot — clean water low",
86669
- kinds: TANK
86670
- },
86671
87468
  {
86672
87469
  name: "summaryDetection",
86673
87470
  label: "Summary: cameras detecting nothing",
@@ -86783,8 +87580,7 @@ var STATE_SUMMARY_VARS = [
86783
87580
  ([...RULE_TEXT], [...COMBINED_ALARM]),
86784
87581
  ([...RULE_TEXT], [...DEVICE_EVENTS]),
86785
87582
  ([...RULE_TEXT], [...BATTERY, ...CONSUMABLE]),
86786
- ([...RULE_TEXT], [...CONSUMABLE, ...TANK]),
86787
- ([...RULE_TEXT], [...TANK]),
87583
+ ([...RULE_TEXT], [...CONSUMABLE]),
86788
87584
  [...RULE_TEXT],
86789
87585
  ([...RULE_TEXT], [...UPDATES, ...ALERT_EPISODE]),
86790
87586
  ([...RULE_TEXT], [...UPDATES, ...ALERT_EPISODE]),
@@ -86888,15 +87684,6 @@ new Map([
86888
87684
  snapshotLabel: "Consumables low now",
86889
87685
  snapshotSection: "consumables"
86890
87686
  },
86891
- {
86892
- id: "tanks",
86893
- family: "device-events",
86894
- label: "Tanks (low or full / back to normal)",
86895
- bad: ["device-tank-low", "device-tank-full"],
86896
- recovery: ["device-tank-normal"],
86897
- snapshotLabel: "Tanks low or full now",
86898
- snapshotSection: "tanks"
86899
- },
86900
87687
  {
86901
87688
  id: "motion-noise",
86902
87689
  family: "device-events",
@@ -87349,6 +88136,10 @@ MotionOnMotionChangedDataSchema.omit({ triggeredBy: true });
87349
88136
  function providerMotionEvent(source, data) {
87350
88137
  return createEvent(EventCategory.ProviderMotion, source, data);
87351
88138
  }
88139
+ Object.freeze({
88140
+ person: .8,
88141
+ vehicle: .8
88142
+ });
87352
88143
  object({
87353
88144
  /**
87354
88145
  * Fraction of the box's own size added on EACH side before cutting.