@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.js CHANGED
@@ -36,7 +36,7 @@ let node_os = require("node:os");
36
36
  node_os = require_chunk.__toESM(node_os, 1);
37
37
  let node_fs = require("node:fs");
38
38
  node_fs = require_chunk.__toESM(node_fs, 1);
39
- //#region ../types/dist/event-category-BfJwUd2S.mjs
39
+ //#region ../types/dist/event-category-Ceif8n-v.mjs
40
40
  var EventCategory = /* @__PURE__ */ function(EventCategory) {
41
41
  EventCategory["SystemBoot"] = "system.boot";
42
42
  EventCategory["SystemAddonsReady"] = "system.addons-ready";
@@ -363,9 +363,8 @@ var EventCategory = /* @__PURE__ */ function(EventCategory) {
363
363
  EventCategory["PipelineMotionCalm"] = "pipeline.motion-calm";
364
364
  /**
365
365
  * Per-camera pipeline config was mutated by the orchestrator
366
- * (3-level settings change via `setAgentAddonDefaults` /
367
- * `setCameraStepToggle` / `setCameraPipelineForAgent` or a
368
- * pipeline-scoped `applyDeviceSettingsPatch`). Orchestrator
366
+ * (a settings change via `setAgentInferenceDevices` /
367
+ * `setCameraStepToggle` / `setCameraStepSettings`). Orchestrator
369
368
  * subscribes to its own emission to hot-reload the assigned runner
370
369
  * via `attachCamera` so the next frame executes against the new
371
370
  * engine/steps without waiting for a rebalance or the next
@@ -509,6 +508,10 @@ var EventCategory = /* @__PURE__ */ function(EventCategory) {
509
508
  * on the device detail page.
510
509
  */
511
510
  EventCategory["DoorbellOnPressed"] = "doorbell.onPressed";
511
+ /** Mirrors `runningStateCapability.events.onStarted`. */
512
+ EventCategory["RunningStarted"] = "running.started";
513
+ /** Mirrors `runningStateCapability.events.onFinished`. */
514
+ EventCategory["RunningFinished"] = "running.finished";
512
515
  /**
513
516
  * Cap event fired by every device that registers the `event-emitter`
514
517
  * capability. Mirrors `eventEmitterCapability.events.onEvent`. Carries
@@ -5468,7 +5471,7 @@ var ZodIssueCode = {
5468
5471
  var ZodFirstPartyTypeKind;
5469
5472
  ZodFirstPartyTypeKind || (ZodFirstPartyTypeKind = {});
5470
5473
  //#endregion
5471
- //#region ../types/dist/sleep-6AqUnQIT.mjs
5474
+ //#region ../types/dist/sleep-CYfIZzGv.mjs
5472
5475
  /**
5473
5476
  * The audio chunk plane's byte format, and the ONE expansion from a coded
5474
5477
  * window to float samples (D455).
@@ -5811,7 +5814,7 @@ Object.fromEntries([
5811
5814
  * `hydrateSchema` to skip the `value` injection for structural-only fields.
5812
5815
  */
5813
5816
  function isValuelessField(field) {
5814
- 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";
5817
+ 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";
5815
5818
  }
5816
5819
  function hydrateSchema(schema, values, options = {}) {
5817
5820
  return {
@@ -8915,7 +8918,7 @@ var DeviceRole = /* @__PURE__ */ function(DeviceRole) {
8915
8918
  return DeviceRole;
8916
8919
  }({});
8917
8920
  //#endregion
8918
- //#region ../types/dist/composition-CB6PMT9p.mjs
8921
+ //#region ../types/dist/composition-BJ8iAZb3.mjs
8919
8922
  /**
8920
8923
  * The ffmpeg build every CamStack node downloads, per platform and arch.
8921
8924
  *
@@ -8975,7 +8978,7 @@ portable("linux64"), portable("linuxarm64"), portable("macarm64"), portable("mac
8975
8978
  * ONE table for everyone who asks "is this device HIGH?": the
8976
8979
  * recorder's `RecordingTriggers.sensorDeviceIds` trigger, the post-analysis
8977
8980
  * sensor markers, the orchestrator's camera-sensors bridge and
8978
- * the sources of a composite doorbell (`doorbellFeatureSources`, D671).
8981
+ * the sources of a pulse (`compilePulseOverride`, D936).
8979
8982
  * A second copy would diverge at the first cap added, and the symptom — "the
8980
8983
  * sensor rings the doorbell but does not record" — is exactly D62.
8981
8984
  *
@@ -9216,6 +9219,20 @@ var table$1 = {
9216
9219
  apply: () => {
9217
9220
  throw new ExpressionEvalError("count: stateful evaluation context is required");
9218
9221
  }
9222
+ },
9223
+ dwell: {
9224
+ minArgs: 3,
9225
+ maxArgs: 3,
9226
+ apply: () => {
9227
+ throw new ExpressionEvalError("dwell: stateful evaluation context is required");
9228
+ }
9229
+ },
9230
+ latchedAt: {
9231
+ minArgs: 1,
9232
+ maxArgs: 1,
9233
+ apply: () => {
9234
+ throw new ExpressionEvalError("latchedAt: stateful evaluation context is required");
9235
+ }
9219
9236
  }
9220
9237
  };
9221
9238
  Object.freeze(Object.assign(Object.create(null), table$1));
@@ -10655,13 +10672,22 @@ var BirthDecisionRecordSchema = object({
10655
10672
  decidedByBirthEvidence: boolean(),
10656
10673
  /** Best class-compatible crop score, or `null` when nothing compatible was
10657
10674
  * found — deliberately not 0, which would be a measurement that never was.
10658
- * Includes a box the detector's own per-class floor refused (reason
10659
- * `below-detector-floor`, D922): that box never confirms, but it is the
10660
- * score the crop really held. */
10675
+ * Includes a box the detector's own per-class floor refused (D922): since
10676
+ * D925 the gate's bar, not that floor, decides whether it confirms. */
10661
10677
  bestScore: number().nullable(),
10662
10678
  /** The bar this candidate actually faced (the phantom-cell hook may raise it). */
10663
10679
  appliedMinConfidence: number().nullable(),
10664
10680
  /**
10681
+ * The detector the gate re-judged the birth WITH (D925): the session's own
10682
+ * root model, inference-device pool and node — never a node default. `null`
10683
+ * when the frame named no session detector or no gate ran, and on rows
10684
+ * written before D925. A `session-device-unavailable` row names the session
10685
+ * detector that could not be reached.
10686
+ */
10687
+ detectorModelId: string().nullable().default(null),
10688
+ detectorDeviceKey: string().nullable().default(null),
10689
+ detectorNodeId: string().nullable().default(null),
10690
+ /**
10665
10691
  * The track's own `firstSeen` — the candidate's first frame, which is where
10666
10692
  * the timeline starts. `null` for a suppressed birth, which has no track.
10667
10693
  */
@@ -16662,6 +16688,13 @@ var ComposerUnreadableBlockSchema = object({
16662
16688
  /** The parse error, in the operator's words. */
16663
16689
  error: string()
16664
16690
  });
16691
+ /** A confirmed release the hub did not accept. `deviceId` is the claim's device. */
16692
+ var UnreleasedClaimSchema = object({
16693
+ deviceId: number().int(),
16694
+ capName: string(),
16695
+ owner: string(),
16696
+ error: string()
16697
+ });
16665
16698
  method(object({
16666
16699
  /** The shared Blocks integration; null until `core-blocks` has reconciled it. */
16667
16700
  integrationId: string().nullable(),
@@ -16671,7 +16704,13 @@ method(object({
16671
16704
  /** Operator restarts: rebuild these runtimes and re-resolve their sources. Stores nothing (D62). */
16672
16705
  restartBlockIds: array(string()),
16673
16706
  /** Composition rows that exist but do not parse: held, never withdrawn, reported failed. */
16674
- unreadableBlocks: array(ComposerUnreadableBlockSchema)
16707
+ unreadableBlocks: array(ComposerUnreadableBlockSchema),
16708
+ /**
16709
+ * Operator-confirmed deletions. Their claims are released on this apply,
16710
+ * before any replacement block claims. A block that merely vanished from the
16711
+ * snapshot is not listed here and still waits for two applies (D49).
16712
+ */
16713
+ retiredBlockIds: array(string()).optional()
16675
16714
  }), object({
16676
16715
  blocks: array(object({
16677
16716
  blockId: string(),
@@ -16683,7 +16722,13 @@ method(object({
16683
16722
  * integration unknown, its own rows unread or read empty once). An empty
16684
16723
  * apply the caller owes is paid off only by one the composer acted on (D49).
16685
16724
  */
16686
- acted: boolean()
16725
+ acted: boolean(),
16726
+ /**
16727
+ * Confirmed releases this apply tried and the hub did not accept. Empty when
16728
+ * every one landed (or there was nothing to hand back). Absent on a result
16729
+ * that never got that far.
16730
+ */
16731
+ unreleasedClaims: array(UnreleasedClaimSchema).optional()
16687
16732
  }), {
16688
16733
  kind: "mutation",
16689
16734
  auth: "admin"
@@ -16726,7 +16771,15 @@ Object.freeze({
16726
16771
  kind: "fixed",
16727
16772
  result: ["number", "null"]
16728
16773
  },
16729
- count: NUMBER
16774
+ count: NUMBER,
16775
+ dwell: {
16776
+ kind: "fixed",
16777
+ result: ["boolean", "null"]
16778
+ },
16779
+ latchedAt: {
16780
+ kind: "fixed",
16781
+ result: ["number", "null"]
16782
+ }
16730
16783
  });
16731
16784
  `${COMPOSED_DEVICE_STABLE_ID_PREFIX}`;
16732
16785
  /**
@@ -42883,6 +42936,381 @@ var _macroLookup = /* @__PURE__ */ new Map();
42883
42936
  for (const [k, v] of Object.entries(YAMNET_TO_MACRO.mapping)) _macroLookup.set(k.toLowerCase(), v);
42884
42937
  for (const [k, v] of Object.entries(APPLE_SA_TO_MACRO.mapping)) _macroLookup.set(k.toLowerCase(), v);
42885
42938
  /**
42939
+ * Palette entry ids (D939). Audio is the one gradient; `audio-*` leaves are
42940
+ * not entries. `heatmapScrub` is a mark, not an event kind.
42941
+ */
42942
+ var PALETTE_ENTRY_IDS = [
42943
+ "motion",
42944
+ "audio",
42945
+ "recording",
42946
+ "live",
42947
+ "heatmapScrub",
42948
+ "person",
42949
+ "vehicle",
42950
+ "animal",
42951
+ "package",
42952
+ "sensor",
42953
+ "control",
42954
+ "face",
42955
+ "plate",
42956
+ "car",
42957
+ "truck",
42958
+ "bus",
42959
+ "motorcycle",
42960
+ "bicycle",
42961
+ "airplane",
42962
+ "boat",
42963
+ "train",
42964
+ "bird",
42965
+ "dog",
42966
+ "cat",
42967
+ "horse",
42968
+ "sheep",
42969
+ "cow",
42970
+ "elephant",
42971
+ "bear",
42972
+ "zebra",
42973
+ "giraffe",
42974
+ "package-delivered",
42975
+ "package-picked-up",
42976
+ "suitcase",
42977
+ "backpack",
42978
+ "handbag",
42979
+ "contact",
42980
+ "motion-sensor",
42981
+ "smoke",
42982
+ "flood",
42983
+ "gas",
42984
+ "carbon-monoxide",
42985
+ "vibration",
42986
+ "tamper",
42987
+ "presence",
42988
+ "enum-sensor",
42989
+ "device-event",
42990
+ "lock",
42991
+ "cover",
42992
+ "switch",
42993
+ "siren",
42994
+ "button",
42995
+ "doorbell"
42996
+ ];
42997
+ var AUDIO_ENTRY_ID = "audio";
42998
+ /** Six rungs, quiet → loud. The opaque end is the entry's hex. */
42999
+ var AUDIO_GRADIENT_ALPHAS = [
43000
+ .3,
43001
+ .42,
43002
+ .55,
43003
+ .7,
43004
+ .85,
43005
+ 1
43006
+ ];
43007
+ var PALETTE_PRESET_IDS = [
43008
+ "camstack",
43009
+ "high-contrast",
43010
+ "okabe-ito"
43011
+ ];
43012
+ /** Frozen palette tables (D939). The spec refuses a table that breaks the rule. */
43013
+ var CAMSTACK_HEX = {
43014
+ motion: "#d946ef",
43015
+ audio: "#059eb8",
43016
+ recording: "#ef4444",
43017
+ live: "#8d7a00",
43018
+ heatmapScrub: "#4b32ff",
43019
+ person: "#11a64c",
43020
+ vehicle: "#3b82f6",
43021
+ animal: "#ea6a09",
43022
+ package: "#924667",
43023
+ sensor: "#624bbc",
43024
+ control: "#944d24",
43025
+ face: "#ed4f8d",
43026
+ plate: "#4b7027",
43027
+ car: "#9684cf",
43028
+ truck: "#0f9b89",
43029
+ bus: "#a734a9",
43030
+ motorcycle: "#c1133a",
43031
+ bicycle: "#0e6a9b",
43032
+ airplane: "#7c9928",
43033
+ boat: "#b17933",
43034
+ train: "#ad6ca3",
43035
+ bird: "#0f7c55",
43036
+ dog: "#c82700",
43037
+ cat: "#7268f2",
43038
+ horse: "#cb795e",
43039
+ sheep: "#b8636b",
43040
+ cow: "#cb2969",
43041
+ elephant: "#1158d2",
43042
+ bear: "#8d5e00",
43043
+ zebra: "#0097d6",
43044
+ giraffe: "#8f61bb",
43045
+ "package-delivered": "#cd3f9b",
43046
+ "package-picked-up": "#388a08",
43047
+ suitcase: "#666800",
43048
+ backpack: "#ec5022",
43049
+ handbag: "#a76ef8",
43050
+ contact: "#ab5a49",
43051
+ "motion-sensor": "#b95d1a",
43052
+ smoke: "#dd3858",
43053
+ flood: "#b31e7d",
43054
+ gas: "#5b70b5",
43055
+ "carbon-monoxide": "#7b4e8e",
43056
+ vibration: "#e65bba",
43057
+ tamper: "#98464b",
43058
+ presence: "#3a9468",
43059
+ "enum-sensor": "#7885f8",
43060
+ "device-event": "#8c43c8",
43061
+ lock: "#649653",
43062
+ cover: "#c67597",
43063
+ switch: "#7a812a",
43064
+ siren: "#ac5d7f",
43065
+ button: "#b276cd",
43066
+ doorbell: "#0087ab"
43067
+ };
43068
+ var CAMSTACK_FALLBACK = [
43069
+ "#b34dc7",
43070
+ "#1d7d34",
43071
+ "#db6b6c",
43072
+ "#a43d29",
43073
+ "#0e6ee6",
43074
+ "#29a10b",
43075
+ "#a98731",
43076
+ "#0181c6"
43077
+ ];
43078
+ var HIGH_CONTRAST_HEX = {
43079
+ motion: "#964360",
43080
+ audio: "#23a132",
43081
+ recording: "#2494ca",
43082
+ live: "#bd7e2b",
43083
+ heatmapScrub: "#ad6eea",
43084
+ person: "#62611e",
43085
+ vehicle: "#f4534c",
43086
+ animal: "#1556cd",
43087
+ package: "#9c4415",
43088
+ sensor: "#066c48",
43089
+ control: "#f2479f",
43090
+ face: "#139d8a",
43091
+ plate: "#909024",
43092
+ car: "#8e35ab",
43093
+ truck: "#bd0b2b",
43094
+ bus: "#7a88ca",
43095
+ motorcycle: "#e26725",
43096
+ bicycle: "#a6679b",
43097
+ airplane: "#7c5720",
43098
+ boat: "#467a1b",
43099
+ train: "#6f65a4",
43100
+ bird: "#cb717f",
43101
+ dog: "#c62490",
43102
+ cat: "#b36850",
43103
+ horse: "#1872ac",
43104
+ sheep: "#927939",
43105
+ cow: "#428a5c",
43106
+ elephant: "#d41160",
43107
+ bear: "#799453",
43108
+ zebra: "#a85455",
43109
+ giraffe: "#746be8",
43110
+ "package-delivered": "#824a80",
43111
+ "package-picked-up": "#614ac1",
43112
+ suitcase: "#2f77f3",
43113
+ backpack: "#fa476d",
43114
+ handbag: "#c14cbe",
43115
+ contact: "#c83921",
43116
+ "motion-sensor": "#a07ebd",
43117
+ smoke: "#a25b13",
43118
+ flood: "#526bab",
43119
+ gas: "#924938",
43120
+ "carbon-monoxide": "#bb7e53",
43121
+ vibration: "#b66182",
43122
+ tamper: "#3c6931",
43123
+ presence: "#6c851d",
43124
+ "enum-sensor": "#ad2d48",
43125
+ "device-event": "#5e9b04",
43126
+ lock: "#00a062",
43127
+ cover: "#ad8624",
43128
+ switch: "#d05259",
43129
+ siren: "#cd67b3",
43130
+ button: "#c9746a",
43131
+ doorbell: "#338eeb"
43132
+ };
43133
+ var HIGH_CONTRAST_FALLBACK = [
43134
+ "#817f3b",
43135
+ "#a0733e",
43136
+ "#8658b2",
43137
+ "#956301",
43138
+ "#bc652d",
43139
+ "#647331",
43140
+ "#a14c9e",
43141
+ "#d14e71"
43142
+ ];
43143
+ var OKABE_ITO_HEX = {
43144
+ motion: "#b88128",
43145
+ audio: "#1096c8",
43146
+ recording: "#009e73",
43147
+ live: "#9c8c22",
43148
+ heatmapScrub: "#0072b2",
43149
+ person: "#d55e00",
43150
+ vehicle: "#c0739f",
43151
+ animal: "#226d18",
43152
+ package: "#91446c",
43153
+ sensor: "#217b56",
43154
+ control: "#648647",
43155
+ face: "#c22998",
43156
+ plate: "#fa4575",
43157
+ car: "#956301",
43158
+ truck: "#2f77f3",
43159
+ bus: "#7a4e86",
43160
+ motorcycle: "#f54597",
43161
+ bicycle: "#bb3e75",
43162
+ airplane: "#e054c0",
43163
+ boat: "#457942",
43164
+ train: "#867afa",
43165
+ bird: "#88914c",
43166
+ dog: "#1556cd",
43167
+ cat: "#71702c",
43168
+ horse: "#9b4fa4",
43169
+ sheep: "#c0559d",
43170
+ cow: "#d14f65",
43171
+ elephant: "#98470f",
43172
+ bear: "#595896",
43173
+ zebra: "#96790e",
43174
+ giraffe: "#cb717b",
43175
+ "package-delivered": "#139d8a",
43176
+ "package-picked-up": "#906ead",
43177
+ suitcase: "#d02939",
43178
+ backpack: "#d41160",
43179
+ handbag: "#f64f54",
43180
+ contact: "#7258d2",
43181
+ "motion-sensor": "#b66182",
43182
+ smoke: "#627abb",
43183
+ flood: "#b86ae4",
43184
+ gas: "#a95261",
43185
+ "carbon-monoxide": "#c65d3c",
43186
+ vibration: "#7a40b7",
43187
+ tamper: "#914b34",
43188
+ presence: "#9481c3",
43189
+ "enum-sensor": "#ac6d47",
43190
+ "device-event": "#7b6fce",
43191
+ lock: "#c67662",
43192
+ cover: "#a6564d",
43193
+ switch: "#ad2c4e",
43194
+ siren: "#348e08",
43195
+ button: "#d27303",
43196
+ doorbell: "#55770f"
43197
+ };
43198
+ var OKABE_ITO_FALLBACK = [
43199
+ "#9a3784",
43200
+ "#a7392c",
43201
+ "#409d50",
43202
+ "#6987e7",
43203
+ "#ee5b3d",
43204
+ "#c0430d",
43205
+ "#af79b3",
43206
+ "#4b6628"
43207
+ ];
43208
+ /**
43209
+ * The display palette (D939). One table of colours, three presets, one
43210
+ * validator. Taxonomy colours and every consumer read this — there is no
43211
+ * second hex table.
43212
+ */
43213
+ var paletteHexSchema = string().regex(/^#[0-9a-f]{6}$/);
43214
+ var paletteSwatchSchema = discriminatedUnion("form", [object({
43215
+ form: literal("solid"),
43216
+ hex: paletteHexSchema
43217
+ }), object({
43218
+ form: literal("gradient"),
43219
+ hex: paletteHexSchema,
43220
+ alphas: array(number().gt(0).lte(1)).length(AUDIO_GRADIENT_ALPHAS.length)
43221
+ })]);
43222
+ var paletteReadySchema = object({
43223
+ status: literal("ready"),
43224
+ presetId: _enum(PALETTE_PRESET_IDS),
43225
+ customized: boolean(),
43226
+ source: _enum(["stored", "unconfigured"]),
43227
+ swatches: record(string(), paletteSwatchSchema),
43228
+ fallbacks: array(paletteHexSchema).length(8)
43229
+ });
43230
+ var paletteResultSchema = discriminatedUnion("status", [paletteReadySchema, object({
43231
+ status: literal("unknown"),
43232
+ reason: string()
43233
+ })]);
43234
+ var setPaletteInputSchema = union([object({ presetId: string() }), object({
43235
+ presetId: string(),
43236
+ overrides: record(string(), paletteSwatchSchema)
43237
+ })]);
43238
+ object({
43239
+ presetId: string(),
43240
+ overrides: record(string(), paletteSwatchSchema)
43241
+ });
43242
+ function solid(hex) {
43243
+ return {
43244
+ form: "solid",
43245
+ hex
43246
+ };
43247
+ }
43248
+ function audioGradient(hex) {
43249
+ return {
43250
+ form: "gradient",
43251
+ hex,
43252
+ alphas: [...AUDIO_GRADIENT_ALPHAS]
43253
+ };
43254
+ }
43255
+ function swatchesFrom(hexes) {
43256
+ const out = {};
43257
+ for (const id of PALETTE_ENTRY_IDS) {
43258
+ const hex = hexes[id];
43259
+ if (hex === void 0) throw new Error(`palette table missing ${id}`);
43260
+ out[id] = id === "audio" ? audioGradient(hex) : solid(hex);
43261
+ }
43262
+ return out;
43263
+ }
43264
+ function preset(id, name, hexes, fallbacks) {
43265
+ return {
43266
+ id,
43267
+ name,
43268
+ swatches: swatchesFrom(hexes),
43269
+ fallbacks
43270
+ };
43271
+ }
43272
+ var DISPLAY_PRESETS = [
43273
+ preset("camstack", "CamStack", CAMSTACK_HEX, CAMSTACK_FALLBACK),
43274
+ preset("high-contrast", "High contrast", HIGH_CONTRAST_HEX, HIGH_CONTRAST_FALLBACK),
43275
+ preset("okabe-ito", "Colour-blind safe", OKABE_ITO_HEX, OKABE_ITO_FALLBACK)
43276
+ ];
43277
+ function presetById(id) {
43278
+ return DISPLAY_PRESETS.find((item) => item.id === id);
43279
+ }
43280
+ function bundledCamstack() {
43281
+ const presetRow = presetById("camstack");
43282
+ if (presetRow === void 0) throw new Error("CamStack preset missing");
43283
+ return readyOf(presetRow, "unconfigured", false);
43284
+ }
43285
+ function readyOf(row, source, customized) {
43286
+ return {
43287
+ status: "ready",
43288
+ presetId: row.id,
43289
+ customized,
43290
+ source,
43291
+ swatches: row.swatches,
43292
+ fallbacks: [...row.fallbacks]
43293
+ };
43294
+ }
43295
+ function hashFallback(kind, fallbacks) {
43296
+ let hash = 0;
43297
+ for (let i = 0; i < kind.length; i++) hash = hash * 31 + (kind.codePointAt(i) ?? 0) >>> 0;
43298
+ const hex = fallbacks[hash % fallbacks.length];
43299
+ if (hex === void 0) throw new Error("display palette has no fallback colour");
43300
+ return hex;
43301
+ }
43302
+ /** Colour a kind paints with. Audio leaves share the audio gradient's hex. */
43303
+ function paintHex(swatches, fallbacks, kind) {
43304
+ const key = kind.trim().toLowerCase();
43305
+ if (key.startsWith("audio-")) {
43306
+ const audio = swatches[AUDIO_ENTRY_ID];
43307
+ return audio !== void 0 ? audio.hex : hashFallback(key, fallbacks);
43308
+ }
43309
+ const direct = swatches[key];
43310
+ if (direct !== void 0) return direct.hex;
43311
+ return hashFallback(key, fallbacks);
43312
+ }
43313
+ /**
42886
43314
  * Unified event-kind taxonomy — THE single source of truth for
42887
43315
  * `kind → { parentKind, category, level, color, iconId, labelKey, label,
42888
43316
  * icon }`.
@@ -42896,109 +43324,88 @@ for (const [k, v] of Object.entries(APPLE_SA_TO_MACRO.mapping)) _macroLookup.set
42896
43324
  * - `addon-post-analysis/shared/frame/box-drawer.ts` (DEFAULT_COLOR)
42897
43325
  * - the COCO / audio class maps (macro ↔ sub relationships)
42898
43326
  *
42899
- * The DATA (serializable — color/iconId/labelKey/parentKind) lives here in
42900
- * `@camstack/types`. The UI-side mapping `iconId → lucide component` and
42901
- * `labelKey → t()` lives in `@camstack/ui-library`. UIs never hardcode a
42902
- * color or an icon: they read this dictionary (server descriptors carry the
42903
- * fields inline; the client resolves color/icon/label from `iconId`/`kind`).
43327
+ * The DATA (serializable — parentKind / iconId / labelKey) lives here in
43328
+ * `@camstack/types`. Colour is NOT a second table: each entry's `color` is
43329
+ * the bundled CamStack display palette (D939). The effective cluster palette
43330
+ * is the `display-palette` capability. The UI-side mapping `iconId → lucide
43331
+ * component` and `labelKey → t()` lives in `@camstack/ui-library`.
42904
43332
  *
42905
43333
  * Two levels only (v1 YAGNI): macro → sub. `person` is a leaf macro.
42906
43334
  */
42907
- var TAXONOMY_COLORS = {
42908
- motion: "#f59e0b",
42909
- audio: "#06b6d4",
42910
- person: "#22c55e",
42911
- vehicle: "#3b82f6",
42912
- animal: "#f97316",
42913
- package: "#a855f7",
42914
- sensor: "#8b5cf6",
42915
- control: "#10b981",
42916
- genericDetection: "#64748b"
42917
- };
42918
- var DETECTION_SUB_COLORS = {
42919
- car: "#f59e0b",
42920
- truck: "#d97706",
42921
- bus: "#b45309",
42922
- motorcycle: "#eab308",
42923
- bicycle: "#ca8a04",
42924
- airplane: "#60a5fa",
42925
- boat: "#2563eb",
42926
- train: "#1d4ed8",
42927
- bird: "#14b8a6",
42928
- dog: "#84cc16",
42929
- cat: "#f97316",
42930
- horse: "#a16207",
42931
- sheep: "#a3a3a3",
42932
- cow: "#78716c",
42933
- elephant: "#6b7280",
42934
- bear: "#7c2d12",
42935
- zebra: "#404040",
42936
- giraffe: "#d4a373"
42937
- };
43335
+ var BUNDLED_PALETTE = bundledCamstack();
43336
+ function kindColor(kind) {
43337
+ return paintHex(BUNDLED_PALETTE.swatches, BUNDLED_PALETTE.fallbacks, kind);
43338
+ }
43339
+ function firstFallback(fallbacks) {
43340
+ const hex = fallbacks[0];
43341
+ if (hex === void 0) throw new Error("display palette has no fallback colour");
43342
+ return hex;
43343
+ }
43344
+ firstFallback(BUNDLED_PALETTE.fallbacks);
42938
43345
  function titleCase(id) {
42939
43346
  return id.split(/[-_ ]/).filter((p) => p.length > 0).map((p) => p.charAt(0).toUpperCase() + p.slice(1)).join(" ");
42940
43347
  }
42941
43348
  var entries = /* @__PURE__ */ new Map();
42942
- function macro(kind, category, color, iconId, label) {
43349
+ function macro(kind, category, iconId, label) {
42943
43350
  entries.set(kind, {
42944
43351
  kind,
42945
43352
  parentKind: null,
42946
43353
  level: "macro",
42947
43354
  category,
42948
- color,
43355
+ color: kindColor(kind),
42949
43356
  iconId,
42950
43357
  labelKey: `eventKind.${kind}`,
42951
43358
  label
42952
43359
  });
42953
43360
  }
42954
- function sub(kind, parentKind, category, color, iconId, label) {
43361
+ function sub(kind, parentKind, category, iconId, label) {
42955
43362
  entries.set(kind, {
42956
43363
  kind,
42957
43364
  parentKind,
42958
43365
  level: "sub",
42959
43366
  category,
42960
- color,
43367
+ color: kindColor(kind),
42961
43368
  iconId,
42962
43369
  labelKey: `eventKind.${kind}`,
42963
43370
  label
42964
43371
  });
42965
43372
  }
42966
- macro("motion", "motion", TAXONOMY_COLORS.motion, "motion", "Motion");
42967
- macro("audio", "audio", TAXONOMY_COLORS.audio, "audio", "Audio");
42968
- macro("person", "detection", TAXONOMY_COLORS.person, "person", "Person");
42969
- macro("vehicle", "detection", TAXONOMY_COLORS.vehicle, "vehicle", "Vehicle");
42970
- macro("animal", "detection", TAXONOMY_COLORS.animal, "animal", "Animal");
42971
- macro("package", "package", TAXONOMY_COLORS.package, "package", "Package");
42972
- macro("sensor", "sensor", TAXONOMY_COLORS.sensor, "sensor", "Sensor");
42973
- macro("control", "control", TAXONOMY_COLORS.control, "control", "Control");
43373
+ macro("motion", "motion", "motion", "Motion");
43374
+ macro("audio", "audio", "audio", "Audio");
43375
+ macro("person", "detection", "person", "Person");
43376
+ macro("vehicle", "detection", "vehicle", "Vehicle");
43377
+ macro("animal", "detection", "animal", "Animal");
43378
+ macro("package", "package", "package", "Package");
43379
+ macro("sensor", "sensor", "sensor", "Sensor");
43380
+ macro("control", "control", "control", "Control");
42974
43381
  for (const [cocoClass, macroClass] of Object.entries(COCO_TO_MACRO.mapping)) {
42975
43382
  if (macroClass !== "vehicle" && macroClass !== "animal") continue;
42976
43383
  if (entries.has(cocoClass)) continue;
42977
- sub(cocoClass, macroClass, "detection", DETECTION_SUB_COLORS[cocoClass] ?? TAXONOMY_COLORS.genericDetection, cocoClass, titleCase(cocoClass));
42978
- }
42979
- sub("package-delivered", "package", "package", TAXONOMY_COLORS.package, "package", "Package delivered");
42980
- sub("package-picked-up", "package", "package", TAXONOMY_COLORS.package, "package", "Package picked up");
42981
- sub("contact", "sensor", "sensor", "#f59e0b", "door", "Contact");
42982
- sub("motion-sensor", "sensor", "sensor", TAXONOMY_COLORS.sensor, "pir", "Motion sensor");
42983
- sub("smoke", "sensor", "sensor", "#ef4444", "smoke", "Smoke");
42984
- sub("flood", "sensor", "sensor", "#3b82f6", "water", "Water leak");
42985
- sub("gas", "sensor", "sensor", "#ef4444", "gas", "Gas");
42986
- sub("carbon-monoxide", "sensor", "sensor", "#dc2626", "smoke", "Carbon monoxide");
42987
- sub("vibration", "sensor", "sensor", "#eab308", "vibration", "Vibration");
42988
- sub("tamper", "sensor", "sensor", "#f97316", "tamper", "Tamper");
42989
- sub("presence", "sensor", "sensor", "#22c55e", "presence", "Presence");
42990
- sub("enum-sensor", "sensor", "sensor", TAXONOMY_COLORS.sensor, "generic", "Sensor state");
42991
- sub("device-event", "sensor", "sensor", "#10b981", "button", "Device event");
42992
- sub("lock", "control", "control", "#0ea5e9", "lock", "Lock");
42993
- sub("cover", "control", "control", "#0ea5e9", "door", "Cover");
42994
- sub("switch", "control", "control", TAXONOMY_COLORS.control, "switch", "Switch");
42995
- sub("siren", "control", "control", "#dc2626", "siren", "Siren");
42996
- sub("button", "control", "control", "#10b981", "button", "Button");
42997
- sub("doorbell", "control", "control", "#a855f7", "doorbell", "Doorbell");
43384
+ sub(cocoClass, macroClass, "detection", cocoClass, titleCase(cocoClass));
43385
+ }
43386
+ sub("package-delivered", "package", "package", "package", "Package delivered");
43387
+ sub("package-picked-up", "package", "package", "package", "Package picked up");
43388
+ sub("contact", "sensor", "sensor", "door", "Contact");
43389
+ sub("motion-sensor", "sensor", "sensor", "pir", "Motion sensor");
43390
+ sub("smoke", "sensor", "sensor", "smoke", "Smoke");
43391
+ sub("flood", "sensor", "sensor", "water", "Water leak");
43392
+ sub("gas", "sensor", "sensor", "gas", "Gas");
43393
+ sub("carbon-monoxide", "sensor", "sensor", "smoke", "Carbon monoxide");
43394
+ sub("vibration", "sensor", "sensor", "vibration", "Vibration");
43395
+ sub("tamper", "sensor", "sensor", "tamper", "Tamper");
43396
+ sub("presence", "sensor", "sensor", "presence", "Presence");
43397
+ sub("enum-sensor", "sensor", "sensor", "generic", "Sensor state");
43398
+ sub("device-event", "sensor", "sensor", "button", "Device event");
43399
+ sub("lock", "control", "control", "lock", "Lock");
43400
+ sub("cover", "control", "control", "door", "Cover");
43401
+ sub("switch", "control", "control", "switch", "Switch");
43402
+ sub("siren", "control", "control", "siren", "Siren");
43403
+ sub("button", "control", "control", "button", "Button");
43404
+ sub("doorbell", "control", "control", "doorbell", "Doorbell");
42998
43405
  for (const l of AUDIO_MACRO_LABELS) {
42999
43406
  const kind = `audio-${l.id}`;
43000
43407
  if (entries.has(kind)) continue;
43001
- sub(kind, "audio", "audio", TAXONOMY_COLORS.audio, kind, l.name);
43408
+ sub(kind, "audio", "audio", kind, l.name);
43002
43409
  }
43003
43410
  /** The complete taxonomy dictionary, keyed by kind. */
43004
43411
  var EVENT_TAXONOMY = Object.freeze(Object.fromEntries(entries));
@@ -43309,9 +43716,6 @@ var NcSystemEventKindSchema = _enum([
43309
43716
  "device-battery-normal",
43310
43717
  "device-consumable-low",
43311
43718
  "device-consumable-normal",
43312
- "device-tank-low",
43313
- "device-tank-full",
43314
- "device-tank-normal",
43315
43719
  "stream-online",
43316
43720
  "stream-offline",
43317
43721
  "node-online",
@@ -43358,13 +43762,14 @@ var NcSystemEventKindSchema = _enum([
43358
43762
  "camera-enabled"
43359
43763
  ]);
43360
43764
  /** The legacy tail of {@link NcSystemEventKindSchema} — see its docblock. */
43361
- var NC_LEGACY_SYSTEM_EVENT_KINDS = new Set([
43765
+ var NC_LEGACY_SYSTEM_EVENT_KINDS = [
43362
43766
  "camera-online",
43363
43767
  "camera-offline",
43364
43768
  "camera-disabled",
43365
43769
  "camera-enabled"
43366
- ]);
43367
- NcSystemEventKindSchema.options.filter((kind) => !NC_LEGACY_SYSTEM_EVENT_KINDS.has(kind));
43770
+ ];
43771
+ var NC_LEGACY_SYSTEM_EVENT_KIND_SET = new Set(NC_LEGACY_SYSTEM_EVENT_KINDS);
43772
+ NcSystemEventKindSchema.options.filter((kind) => !NC_LEGACY_SYSTEM_EVENT_KIND_SET.has(kind));
43368
43773
  /**
43369
43774
  * The panel's transitions, as ONE list.
43370
43775
  *
@@ -44483,18 +44888,11 @@ var NcRuleSchema = NcRuleInputSchema.extend({
44483
44888
  */
44484
44889
  disabledTargetIds: array(string()).default([])
44485
44890
  });
44486
- /**
44487
- * The state-summary SECTIONS (D647 / D698 / D708): the D637 kind groups that
44488
- * report a still-true state. `addons` is the crash-looped addons only and
44489
- * `addon-updates` the addons that are behind (D708 split them). `backups-exports` and `alarm` are not sections — a completed
44490
- * job is not an open state, and the alarm stays instant.
44491
- */
44492
44891
  var NcStateSummarySectionIdSchema = _enum([
44493
44892
  "device-state",
44494
44893
  "streams",
44495
44894
  "battery",
44496
44895
  "consumables",
44497
- "tanks",
44498
44896
  "detection-blind",
44499
44897
  "nodes",
44500
44898
  "addons",
@@ -45795,6 +46193,18 @@ Object.freeze({
45795
46193
  reason: "camera sensor mappings not loaded"
45796
46194
  });
45797
46195
  /**
46196
+ * What the vision model must answer before a package event is emitted
46197
+ * when a packages rule has "Confirm with the LLM" on.
46198
+ *
46199
+ * `package` is the verdict. `confidence` is 0..1. `reason` is the model's
46200
+ * one-line explanation, stored on the event so a drop is not silent.
46201
+ */
46202
+ var PackageLlmVerdictSchema = object({
46203
+ package: boolean(),
46204
+ confidence: number().min(0).max(1),
46205
+ reason: string().min(1)
46206
+ });
46207
+ /**
45798
46208
  * A model choice has a SCOPE, and a scope change has a workflow.
45799
46209
  *
45800
46210
  * ## The two scopes
@@ -46731,6 +47141,21 @@ var ObjectEventSchema = object({
46731
47141
  * pick-up written before D684 — UNKNOWN, never 0 and never `timestamp`.
46732
47142
  */
46733
47143
  observedAt: number().optional(),
47144
+ /**
47145
+ * The delivery was emitted without a vision-model yes (D931).
47146
+ *
47147
+ * Set only when the packages rule asked for an LLM confirm and the model
47148
+ * was unreachable, timed out, or answered something that did not parse.
47149
+ * A notification reads it so it can say "possible" instead of a definite
47150
+ * delivery. Absent on every other row, and on a confirm that said yes.
47151
+ */
47152
+ packagePossible: boolean().optional(),
47153
+ /**
47154
+ * The vision model's verdict, when a packages rule asked for one and the
47155
+ * model answered the schema (D931). A "no" never becomes a row — the
47156
+ * detector drops it and logs the reason. Present on a yes.
47157
+ */
47158
+ packageLlmVerdict: PackageLlmVerdictSchema.optional(),
46734
47159
  /** The parent track's key-event importance [0,1], propagated to every object
46735
47160
  * event of the track (so an event row can be sorted by importance without a
46736
47161
  * track join). Absent on legacy rows / before the track was scored. */
@@ -48528,7 +48953,6 @@ var PipelineAddonSchemaSchema = object({
48528
48953
  defaultModelId: string(),
48529
48954
  defaultModelIdByFormat: record(string(), string()).optional(),
48530
48955
  enabledByDefault: boolean().optional(),
48531
- backfillIntoExistingOverrides: boolean().optional(),
48532
48956
  defaultConfidence: number(),
48533
48957
  group: string().optional(),
48534
48958
  configSchema: array(ConfigFieldBridge).readonly().optional()
@@ -48655,13 +49079,12 @@ var AudioTestResultSchema = object({
48655
49079
  error: string().optional(),
48656
49080
  frame: custom().optional()
48657
49081
  });
48658
- var PipelineConfigBridge = custom();
48659
49082
  var ConfigUISchemaBridge = custom();
48660
49083
  var ConfigUISchemaNullableBridge = custom();
48661
49084
  var InferenceCapabilitiesBridge = custom();
48662
49085
  var ModelAvailabilityListBridge = custom();
48663
49086
  var PipelineRunResultBridge = custom();
48664
- method(_void(), array(PipelineEngineChoiceSchema)), method(_void(), PipelineEngineChoiceSchema), method(PipelineEngineChoiceSchema, array(PipelineDefaultStepSchema)), method(object({ nodeId: string() }), EngineProvisioningSchema), method(_void(), record(string(), object({
49087
+ method(_void(), array(PipelineEngineChoiceSchema)), method(_void(), PipelineEngineChoiceSchema), method(object({ nodeId: string() }), EngineProvisioningSchema), method(_void(), record(string(), object({
48665
49088
  modelId: string(),
48666
49089
  settings: record(string(), unknown()).readonly()
48667
49090
  }))), method(object({ steps: record(string(), object({
@@ -48670,28 +49093,6 @@ method(_void(), array(PipelineEngineChoiceSchema)), method(_void(), PipelineEngi
48670
49093
  })) }), object({ success: literal(true) }), {
48671
49094
  kind: "mutation",
48672
49095
  auth: "admin"
48673
- }), method(object({ nodeId: string() }), object({
48674
- success: literal(true),
48675
- clearedDevices: number()
48676
- }), {
48677
- kind: "mutation",
48678
- auth: "admin"
48679
- }), method(object({
48680
- nodeId: string(),
48681
- deviceIds: array(number()).readonly().optional(),
48682
- dryRun: boolean()
48683
- }), object({
48684
- entries: array(object({
48685
- deviceId: number(),
48686
- keys: array(string()).readonly()
48687
- })).readonly(),
48688
- refused: array(object({
48689
- deviceId: number(),
48690
- reason: string()
48691
- })).readonly()
48692
- }), {
48693
- kind: "mutation",
48694
- auth: "admin"
48695
49096
  }), method(object({ nodeId: string() }), object({ unhealthy: array(object({
48696
49097
  /** `<backend>:<device>`, e.g. `openvino:gpu`. */
48697
49098
  deviceKey: string(),
@@ -48714,7 +49115,7 @@ method(_void(), array(PipelineEngineChoiceSchema)), method(_void(), PipelineEngi
48714
49115
  }), object({ rearmed: boolean() }), {
48715
49116
  kind: "mutation",
48716
49117
  auth: "admin"
48717
- }), method(_void(), PipelineSchemaSchema), method(_void(), array(PipelineDefaultStepSchema).readonly().nullable()), method(_void(), PipelineConfigBridge), method(_void(), ConfigUISchemaBridge), method(object({
49118
+ }), method(_void(), PipelineSchemaSchema), method(_void(), ConfigUISchemaBridge), method(object({
48718
49119
  steps: array(PipelineStepInputSchema),
48719
49120
  deviceKey: string().optional()
48720
49121
  }), PipelineValidationResultSchema), method(_void(), InferenceCapabilitiesBridge), method(object({ addonId: string() }), ModelAvailabilityListBridge), method(object({
@@ -48962,11 +49363,18 @@ var KeptReasonSchema = _enum(["custom-pin"]);
48962
49363
  * Where a choice's latency came from (D791): this node's own benchmark
48963
49364
  * result, or the hardware-class table. Measured on the node beats the table.
48964
49365
  */
48965
- var LatencySourceSchema = discriminatedUnion("kind", [object({ kind: literal("table") }), object({
48966
- kind: literal("node-benchmark"),
48967
- resultId: string(),
48968
- measuredAtMs: number()
48969
- })]);
49366
+ var LatencySourceSchema = discriminatedUnion("kind", [
49367
+ object({ kind: literal("table") }),
49368
+ object({
49369
+ kind: literal("node-benchmark"),
49370
+ resultId: string(),
49371
+ measuredAtMs: number()
49372
+ }),
49373
+ object({
49374
+ kind: literal("estimated"),
49375
+ estimatedFrom: HardwareClassIdSchema
49376
+ })
49377
+ ]);
48970
49378
  var DeviceModelChoiceSchema = object({
48971
49379
  modelId: string(),
48972
49380
  p50Ms: number(),
@@ -48974,6 +49382,11 @@ var DeviceModelChoiceSchema = object({
48974
49382
  measured: boolean(),
48975
49383
  /** Absent on a plan from before D791 — read as the table. */
48976
49384
  source: LatencySourceSchema.optional(),
49385
+ /**
49386
+ * The measured class this latency was scaled from (D930). Absent when the
49387
+ * cell is the table or a node benchmark.
49388
+ */
49389
+ estimatedFrom: HardwareClassIdSchema.optional(),
48977
49390
  /** Parallel sessions at the camera rate with the headroom kept free: ⌊fps × (1 − headroom) / camera fps⌋. */
48978
49391
  capacitySessions: number(),
48979
49392
  personRecall: number()
@@ -49013,40 +49426,20 @@ var NodeDeviceChangeSchema = object({
49013
49426
  keys: array(string()).readonly()
49014
49427
  })).readonly()
49015
49428
  });
49016
- var CameraOverrideClearSchema = object({
49017
- deviceId: number(),
49018
- source: _enum(["step-override", "wholesale"]),
49429
+ /**
49430
+ * Every model and model-bound threshold lives on the accelerator that runs it
49431
+ * (D927), so the plan writes node / device entries only — there is no camera
49432
+ * layer for it to clear.
49433
+ */
49434
+ var AutoTuneWarningSchema = discriminatedUnion("kind", [object({
49435
+ kind: literal("custom-pin-kept"),
49019
49436
  nodeId: string(),
49020
- deviceKey: string().nullable(),
49021
- stepId: string(),
49022
- modelIdBefore: string().nullable(),
49023
- keys: array(string()).readonly()
49024
- });
49025
- var DetectorStoreClearSchema = object({
49026
- deviceId: number(),
49027
- keys: array(string()).readonly()
49028
- });
49029
- var AutoTuneWarningSchema = discriminatedUnion("kind", [
49030
- object({
49031
- kind: literal("detector-store-cluster-wide"),
49032
- skippedNodes: array(string()).readonly()
49033
- }),
49034
- object({
49035
- kind: literal("detector-store-unreadable"),
49036
- error: string()
49037
- }),
49038
- object({
49039
- kind: literal("custom-pin-kept"),
49040
- nodeId: string(),
49041
- deviceKey: string().nullable(),
49042
- deviceId: number().nullable(),
49043
- modelId: string()
49044
- }),
49045
- object({
49046
- kind: literal("custom-registry-unreadable"),
49047
- error: string()
49048
- })
49049
- ]);
49437
+ deviceKey: string(),
49438
+ modelId: string()
49439
+ }), object({
49440
+ kind: literal("custom-registry-unreadable"),
49441
+ error: string()
49442
+ })]);
49050
49443
  var AutoTuneOptionsSchema = object({
49051
49444
  /** Share of each accelerator's throughput kept free (0.3–0.5). */
49052
49445
  headroom: number().min(.3).max(.5).default(.4),
@@ -49068,8 +49461,6 @@ var AutoTunePlanSchema = object({
49068
49461
  generatedAt: number(),
49069
49462
  nodes: array(NodeRecommendationSchema).readonly(),
49070
49463
  nodeChanges: array(NodeDeviceChangeSchema).readonly(),
49071
- cameraClears: array(CameraOverrideClearSchema).readonly(),
49072
- detectorStoreClears: array(DetectorStoreClearSchema).readonly(),
49073
49464
  warnings: array(AutoTuneWarningSchema).readonly()
49074
49465
  });
49075
49466
  var AutoTuneApplyInputSchema = object({
@@ -49080,8 +49471,6 @@ var AutoTuneApplyInputSchema = object({
49080
49471
  var AutoTunePhaseResultSchema = object({
49081
49472
  phase: _enum([
49082
49473
  "download",
49083
- "camera-overrides",
49084
- "detector-thresholds",
49085
49474
  "node-models",
49086
49475
  "redispatch"
49087
49476
  ]),
@@ -50836,6 +51225,12 @@ var AgentPipelineSettingsSchema = object({
50836
51225
  /** Hub-persisted UI colour (`--color-node-*` theme tokens). */
50837
51226
  color: NodeColorIdSchema.optional(),
50838
51227
  /**
51228
+ * NODE-wide step settings (D927): `stepId → { key → value }`, applied on
51229
+ * every accelerator of the node under the device's own settings. Never a
51230
+ * model or a model-bound threshold. Written by `setNodeStepSettings`.
51231
+ */
51232
+ stepSettings: record(string(), record(string(), unknown()).readonly()).optional(),
51233
+ /**
50839
51234
  * Multi-device inference opt-in (Phase 4). Per-node map deviceKey → {enabled,
50840
51235
  * weight, steps}. Absent / all-disabled ⇒ the node's single default
50841
51236
  * accelerator (safe default); two+ enabled ⇒ the dispatcher balances
@@ -50851,17 +51246,6 @@ var AgentPipelineSettingsSchema = object({
50851
51246
  steps: record(string(), DeviceStepConfigSchema).optional()
50852
51247
  })).optional()
50853
51248
  });
50854
- var CameraPipelineForAgentSchema = object({
50855
- steps: array(PipelineStepInputSchema).readonly(),
50856
- audio: object({
50857
- modelId: string(),
50858
- enabled: boolean()
50859
- }).nullable()
50860
- });
50861
- var CameraStepOverridePatchSchema = object({
50862
- modelId: string().optional(),
50863
- settings: record(string(), unknown()).readonly().optional()
50864
- });
50865
51249
  var CameraStepSettingsSchema = record(string(), record(string(), unknown()).readonly());
50866
51250
  /** The three root-detector choices a camera has (D507: at most one root). */
50867
51251
  var CameraDetectionSourceSchema = _enum([
@@ -50871,9 +51255,7 @@ var CameraDetectionSourceSchema = _enum([
50871
51255
  ]);
50872
51256
  var CameraPipelineSettingsSchema = object({
50873
51257
  stepToggles: record(string(), boolean()).optional(),
50874
- stepSettings: CameraStepSettingsSchema.optional(),
50875
- stepOverridesByDevice: record(string(), record(string(), record(string(), CameraStepOverridePatchSchema))).optional(),
50876
- pipelineByAgent: record(string(), CameraPipelineForAgentSchema).optional()
51258
+ stepSettings: CameraStepSettingsSchema.optional()
50877
51259
  });
50878
51260
  /**
50879
51261
  * Pipeline placement record persisted by `addon-pipeline-orchestrator` via
@@ -51419,6 +51801,13 @@ method(object({
51419
51801
  }), object({ success: literal(true) }), {
51420
51802
  kind: "mutation",
51421
51803
  auth: "admin"
51804
+ }), method(object({
51805
+ agentNodeId: string(),
51806
+ addonId: string(),
51807
+ settings: record(string(), unknown()).nullable()
51808
+ }), object({ success: literal(true) }), {
51809
+ kind: "mutation",
51810
+ auth: "admin"
51422
51811
  }), method(object({ nodeId: string() }), NodeInferenceDevicesSchema), method(object({
51423
51812
  agentNodeId: string(),
51424
51813
  deviceKey: string()
@@ -51428,9 +51817,7 @@ method(object({
51428
51817
  }), method(object({ agentNodeId: string() }), object({
51429
51818
  success: literal(true),
51430
51819
  /** Hardware-aware default detection model now in effect on the node (null when unresolvable). */
51431
- effectiveModelId: string().nullable(),
51432
- /** Number of cameras whose node-scoped overrides were cleared. */
51433
- clearedCameraOverrides: number()
51820
+ effectiveModelId: string().nullable()
51434
51821
  }), {
51435
51822
  kind: "mutation",
51436
51823
  auth: "admin"
@@ -51485,15 +51872,6 @@ method(object({
51485
51872
  }), object({ success: literal(true) }), {
51486
51873
  kind: "mutation",
51487
51874
  auth: "admin"
51488
- }), method(object({ deviceId: number() }), record(string(), record(string(), record(string(), CameraStepOverridePatchSchema))).nullable()), method(object({
51489
- deviceId: number(),
51490
- agentNodeId: string(),
51491
- deviceKey: string(),
51492
- addonId: string(),
51493
- patch: CameraStepOverridePatchSchema.nullable()
51494
- }), object({ success: literal(true) }), {
51495
- kind: "mutation",
51496
- auth: "admin"
51497
51875
  }), method(object({
51498
51876
  deviceId: number(),
51499
51877
  addonId: string(),
@@ -51501,13 +51879,6 @@ method(object({
51501
51879
  }), object({ success: literal(true) }), {
51502
51880
  kind: "mutation",
51503
51881
  auth: "admin"
51504
- }), method(object({
51505
- deviceId: number(),
51506
- agentNodeId: string(),
51507
- pipeline: CameraPipelineForAgentSchema.nullable()
51508
- }), object({ success: literal(true) }), {
51509
- kind: "mutation",
51510
- auth: "admin"
51511
51882
  }), method(object({
51512
51883
  deviceId: number(),
51513
51884
  agentNodeId: string().optional()
@@ -55663,20 +56034,68 @@ var BatteryStatusSchema = object({
55663
56034
  */
55664
56035
  binary: boolean().optional()
55665
56036
  });
56037
+ var BATTERY_DEVICE_TYPES = [
56038
+ DeviceType.Camera,
56039
+ DeviceType.Sensor,
56040
+ DeviceType.Button,
56041
+ DeviceType.Switch,
56042
+ DeviceType.PetFeeder,
56043
+ DeviceType.Container,
56044
+ DeviceType.Thermostat
56045
+ ];
56046
+ /** Generic Customize target for the percentage reading (D936). */
56047
+ var batteryCustomize = {
56048
+ version: 1,
56049
+ targets: [{
56050
+ id: "percentage",
56051
+ cardinality: "scalar",
56052
+ vocabulary: {
56053
+ cap: "battery",
56054
+ stateField: "percentage"
56055
+ },
56056
+ deviceTypes: BATTERY_DEVICE_TYPES,
56057
+ apply: "add-or-replace",
56058
+ path: "percentage",
56059
+ sources: [{
56060
+ kind: "field",
56061
+ valueKinds: ["number", "string"],
56062
+ transforms: [{ kind: "identity" }, {
56063
+ kind: "linear",
56064
+ defaultScale: 1,
56065
+ defaultOffset: 0,
56066
+ clampMin: 0,
56067
+ clampMax: 100
56068
+ }]
56069
+ }],
56070
+ companions: [
56071
+ {
56072
+ kind: "constant",
56073
+ path: "charging",
56074
+ value: "unknown",
56075
+ when: "add"
56076
+ },
56077
+ {
56078
+ kind: "constant",
56079
+ path: "sleeping",
56080
+ value: false,
56081
+ when: "add"
56082
+ },
56083
+ {
56084
+ kind: "clock",
56085
+ path: "lastUpdated",
56086
+ when: "add"
56087
+ }
56088
+ ],
56089
+ sourceReport: { status: "assignment-status" },
56090
+ advancedExpression: true
56091
+ }]
56092
+ };
55666
56093
  var batteryCapability = {
55667
56094
  name: "battery",
55668
56095
  scope: "device",
55669
56096
  deviceNative: true,
55670
56097
  mode: "singleton",
55671
- deviceTypes: [
55672
- DeviceType.Camera,
55673
- DeviceType.Sensor,
55674
- DeviceType.Button,
55675
- DeviceType.Switch,
55676
- DeviceType.PetFeeder,
55677
- DeviceType.Container,
55678
- DeviceType.Thermostat
55679
- ],
56098
+ deviceTypes: BATTERY_DEVICE_TYPES,
55680
56099
  methods: {
55681
56100
  /**
55682
56101
  * Explicitly wake the camera from low-power sleep ahead of a
@@ -55760,6 +56179,7 @@ onStatusChanged: { data: object({
55760
56179
  kind: "gauge",
55761
56180
  unit: "%"
55762
56181
  } } },
56182
+ customize: batteryCustomize,
55763
56183
  /** Clock fields: written, but excluded from the compare that decides
55764
56184
  * whether persisting is worth a SQLite commit. */
55765
56185
  volatileStateFields: ["lastUpdated"]
@@ -56720,6 +57140,106 @@ var ConsumablesStatusSchema = object({
56720
57140
  items: array(ConsumableItemSchema),
56721
57141
  lastChangedAt: number()
56722
57142
  });
57143
+ /** Synthesize seed for a link-built status (no native provider).
57144
+ *
57145
+ * ⚠ NO LIVE CALLER since 2026-08-08 (device-links deleted; see
57146
+ * `CapabilityStatusSchema.empty`). The wiring guidance below was written for
57147
+ * exactly the case the operator is asking about again — a Dreame's HA
57148
+ * consumable-life sensors — so it is kept for that conversation, not because
57149
+ * anything reads it today. */
57150
+ var EMPTY_STATUS = {
57151
+ items: [],
57152
+ lastChangedAt: 0
57153
+ };
57154
+ /** Seed for a NEW link-built consumable item. `key`/`label` are overwritten
57155
+ * with the link's `itemKey` (see `status.itemArray`), so the placeholder
57156
+ * empty strings never survive into a validated item. Link-built items are
57157
+ * not resettable — there is no native provider to receive `reset()`.
57158
+ *
57159
+ * Wiring guidance (HA vacuum consumable-life sensors):
57160
+ * - a percent-remaining source (`numeric-sensor`, unit '%') → `level` via
57161
+ * `identity` (or `linear` scale 1 offset 0 clamp [0,100] to be safe);
57162
+ * - an hours-remaining source (e.g. Dreame 'Main Brush Time Left', unit 'h')
57163
+ * → `level` via `linear` with scale = 100 / max-hours for that item
57164
+ * (e.g. main brush 300 h → scale 0.3333) + clamp [0,100];
57165
+ * - a discrete source (`enum-sensor`, e.g. mop pad 'installed') → `status`
57166
+ * via `enum-map` (e.g. { installed: 'ok', missing: 'replace' }).
57167
+ * A numeric→'replace' THRESHOLD (level < 10 → 'replace') is NOT expressible
57168
+ * with the current transform kinds — leave `status` null (valid) until the
57169
+ * expression transform lands. */
57170
+ /** Generic Customize target for one consumable item (D936). Native rows stay read-only. */
57171
+ var consumablesCustomize = {
57172
+ version: 1,
57173
+ targets: [{
57174
+ id: "items",
57175
+ cardinality: "keyedArray",
57176
+ vocabulary: { cap: "consumables" },
57177
+ deviceTypes: Object.values(DeviceType),
57178
+ apply: "add",
57179
+ path: "items",
57180
+ keyField: "key",
57181
+ labelField: "label",
57182
+ itemSchema: ConsumableItemSchema,
57183
+ nativeItems: "read-only",
57184
+ sourceReport: { status: "assignment-status" },
57185
+ fields: [
57186
+ {
57187
+ path: "level",
57188
+ sources: [{
57189
+ kind: "numeric",
57190
+ transforms: [{ kind: "identity" }, {
57191
+ kind: "linear",
57192
+ defaultScale: 1,
57193
+ defaultOffset: 0,
57194
+ clampMin: 0,
57195
+ clampMax: 100
57196
+ }]
57197
+ }]
57198
+ },
57199
+ {
57200
+ path: "remaining.value",
57201
+ sources: [{
57202
+ kind: "numeric",
57203
+ transforms: [{ kind: "identity" }]
57204
+ }],
57205
+ literals: [{
57206
+ path: "remaining.unit",
57207
+ values: [...ConsumableRemainingUnitSchema.options]
57208
+ }]
57209
+ },
57210
+ {
57211
+ path: "status",
57212
+ sources: [{
57213
+ kind: "enum",
57214
+ transforms: [{
57215
+ kind: "enum-map",
57216
+ outputValues: [...ConsumableStatusSchema.options],
57217
+ unmapped: null
57218
+ }]
57219
+ }]
57220
+ }
57221
+ ],
57222
+ traits: [{
57223
+ path: "kind",
57224
+ values: [...ConsumableKindSchema.options],
57225
+ defaultValue: "wear"
57226
+ }, {
57227
+ path: "form",
57228
+ values: [...ConsumableFormSchema.options],
57229
+ defaultValue: "part"
57230
+ }],
57231
+ companions: [{
57232
+ kind: "clock",
57233
+ path: "lastChangedAt",
57234
+ when: "add"
57235
+ }, {
57236
+ kind: "clock",
57237
+ path: "lastFetchedAt",
57238
+ when: "add"
57239
+ }],
57240
+ advancedExpression: true
57241
+ }]
57242
+ };
56723
57243
  var consumablesCapability = {
56724
57244
  name: "consumables",
56725
57245
  scope: "device",
@@ -56757,10 +57277,7 @@ reset: method(object({
56757
57277
  status: {
56758
57278
  schema: ConsumablesStatusSchema,
56759
57279
  kind: "push",
56760
- empty: {
56761
- items: [],
56762
- lastChangedAt: 0
56763
- },
57280
+ empty: EMPTY_STATUS,
56764
57281
  itemArray: {
56765
57282
  path: "items",
56766
57283
  keyField: "key",
@@ -56796,6 +57313,7 @@ reset: method(object({
56796
57313
  * brush's remaining life and a dishwasher's salt are each recorded the moment
56797
57314
  * their provider reports them; an item that appears later gets its series.
56798
57315
  */
57316
+ customize: consumablesCustomize,
56799
57317
  history: {
56800
57318
  fields: {},
56801
57319
  items: {
@@ -57175,6 +57693,30 @@ var dayNightCapability = {
57175
57693
  volatileStateFields: ["lastFetchedAt"]
57176
57694
  };
57177
57695
  /**
57696
+ * display-palette — the cluster's one colour table (D939).
57697
+ *
57698
+ * Hub singleton. `getPalette` reports `unknown` when the settings store
57699
+ * cannot be read; it does not pretend the bundled preset was stored.
57700
+ * `setPalette` refuses a palette that fails the ΔE / contrast rule and names
57701
+ * the pairs.
57702
+ */
57703
+ var presetSummarySchema = object({
57704
+ id: string(),
57705
+ name: string(),
57706
+ swatches: record(string(), paletteSwatchSchema),
57707
+ fallbacks: array(string())
57708
+ });
57709
+ method(_void(), paletteResultSchema, {
57710
+ auth: "protected",
57711
+ role: "viewer"
57712
+ }), method(_void(), array(presetSummarySchema).readonly(), {
57713
+ auth: "protected",
57714
+ role: "viewer"
57715
+ }), method(setPaletteInputSchema, paletteReadySchema, {
57716
+ kind: "mutation",
57717
+ auth: "admin"
57718
+ });
57719
+ /**
57178
57720
  * Generic device-level status snapshot. Auto-registered by `BaseDevice`
57179
57721
  * for every device, regardless of provider — the kernel needs a uniform
57180
57722
  * cap-keyed slice for the basic device flags every consumer expects to
@@ -57538,6 +58080,36 @@ var dishwasherCapability = {
57538
58080
  powerOn: { kind: "boolean" }
57539
58081
  } }
57540
58082
  };
58083
+ /** Pulse override: a rising edge advances `lastPressedAt` and the press count. */
58084
+ var doorbellCustomize = {
58085
+ version: 1,
58086
+ targets: [{
58087
+ id: "pressed",
58088
+ cardinality: "event",
58089
+ shape: "pulse",
58090
+ vocabulary: {
58091
+ cap: "doorbell",
58092
+ eventName: "onPressed"
58093
+ },
58094
+ deviceTypes: [DeviceType.Camera],
58095
+ apply: "add",
58096
+ applyAuthority: { kind: "composition-claim" },
58097
+ eventName: "onPressed",
58098
+ edges: ["rising"],
58099
+ timestampPath: "lastPressedAt",
58100
+ counterPath: "pressCountSinceStart",
58101
+ highWater: "composer-advance",
58102
+ combine: "any",
58103
+ debounce: {
58104
+ kind: "rising-edge",
58105
+ defaultDebounceMs: 2e3,
58106
+ changedAtRequired: true
58107
+ },
58108
+ sources: [{ kind: "binary" }, { kind: "switch" }],
58109
+ sourceReport: { status: "assignment-status" },
58110
+ advancedExpression: true
58111
+ }]
58112
+ };
57541
58113
  var DoorbellStatusSchema = object({
57542
58114
  /** Ms epoch of the last press. null = never observed since this provider started. */
57543
58115
  lastPressedAt: number().nullable(),
@@ -57604,7 +58176,8 @@ onPressed: {
57604
58176
  /**
57605
58177
  * History (D850): none — `pressCountSinceStart` resets with the addon, so it is not a monotonic meter; presses live in the events ledger.
57606
58178
  */
57607
- history: "none"
58179
+ history: "none",
58180
+ customize: doorbellCustomize
57608
58181
  };
57609
58182
  /**
57610
58183
  * Enum-state sensor — a string value picked from a finite option set.
@@ -60000,6 +60573,38 @@ authKey: string().optional() }), object({
60000
60573
  /** Human-readable error when `ok: false`. */
60001
60574
  error: string().optional()
60002
60575
  }), { kind: "mutation" });
60576
+ /** Span override: start on a rising edge, end on a fall or this timeout. */
60577
+ var motionCustomize = {
60578
+ version: 1,
60579
+ targets: [{
60580
+ id: "detected",
60581
+ cardinality: "event",
60582
+ shape: "span",
60583
+ vocabulary: {
60584
+ cap: "motion",
60585
+ eventName: "onMotionChanged"
60586
+ },
60587
+ deviceTypes: [DeviceType.Camera],
60588
+ apply: "replace",
60589
+ applyAuthority: {
60590
+ kind: "camera-sensors",
60591
+ timeoutField: "motionCooldownMs"
60592
+ },
60593
+ eventName: "onMotionChanged",
60594
+ start: "rising-edge",
60595
+ end: "falling-edge-or-timeout",
60596
+ timeoutMs: 3e4,
60597
+ combine: "any",
60598
+ sourceModes: [
60599
+ "in-addition",
60600
+ "confirm",
60601
+ "replace"
60602
+ ],
60603
+ sources: [{ kind: "binary" }, { kind: "switch" }],
60604
+ sourceReport: { status: "assignment-status" },
60605
+ advancedExpression: false
60606
+ }]
60607
+ };
60003
60608
  var MotionStatusSchema = object({
60004
60609
  detected: boolean(),
60005
60610
  /** Ms epoch of the last detected-true observation. Null if never detected. */
@@ -60139,7 +60744,8 @@ onMotionChanged: { data: MotionOnMotionChangedDataSchema } },
60139
60744
  history: { fields: { detected: {
60140
60745
  kind: "boolean",
60141
60746
  excludeDeviceTypes: [DeviceType.Camera]
60142
- } } }
60747
+ } } },
60748
+ customize: motionCustomize
60143
60749
  };
60144
60750
  /**
60145
60751
  * Motion-trigger toggle for accessory devices.
@@ -61958,6 +62564,30 @@ includeCrops: boolean().optional() }).optional(), array(VehicleSchema).readonly(
61958
62564
  kind: "mutation",
61959
62565
  auth: "admin"
61960
62566
  });
62567
+ var CORE_ULTRA_265K_IGPU_CLOCK_MHZ = 2e3;
62568
+ var positiveOrNull = number().nullable().transform((value) => value !== null && Number.isFinite(value) && value > 0 ? value : null);
62569
+ var textOrNull = string().nullable().transform((value) => value !== null && value.trim() !== "" ? value : null);
62570
+ var PrecisionGopsSchema = object({
62571
+ int8: positiveOrNull,
62572
+ fp16: positiveOrNull
62573
+ });
62574
+ /** What one accelerator device reported. Every failed query is null. */
62575
+ var AcceleratorComputeSchema = object({
62576
+ deviceKey: string(),
62577
+ fullDeviceName: textOrNull,
62578
+ executionUnits: positiveOrNull,
62579
+ clockMHz: positiveOrNull,
62580
+ gops: PrecisionGopsSchema.nullable(),
62581
+ architecture: textOrNull,
62582
+ npuName: textOrNull,
62583
+ tops: positiveOrNull,
62584
+ vendor: textOrNull,
62585
+ webgpuArchitecture: textOrNull,
62586
+ webgpuDevice: textOrNull,
62587
+ computeUnits: positiveOrNull
62588
+ });
62589
+ object({ accelerators: array(AcceleratorComputeSchema).nullable() });
62590
+ 64 * CORE_ULTRA_265K_IGPU_CLOCK_MHZ;
61961
62591
  var ModelFormatSchema = _enum(MODEL_FORMATS);
61962
62592
  var HwAccelBackendInputSchema = _enum([
61963
62593
  "videotoolbox",
@@ -62071,7 +62701,12 @@ var HardwareInfoSchema = object({
62071
62701
  availableRAM_MB: number(),
62072
62702
  gpu: GpuInfoSchema.nullable(),
62073
62703
  npu: NpuInfoSchema.nullable(),
62074
- coral: CoralInfoSchema.nullable().optional()
62704
+ coral: CoralInfoSchema.nullable().optional(),
62705
+ /**
62706
+ * Per-accelerator compute (D930). Omitted by a node that has not probed it.
62707
+ * `null` fields inside an entry are a failed query, never a zero.
62708
+ */
62709
+ accelerators: array(AcceleratorComputeSchema).readonly().optional()
62075
62710
  });
62076
62711
  var PlatformScoreSchema = object({
62077
62712
  runtime: literal("python"),
@@ -63014,6 +63649,125 @@ var ptzAutotrackCapability = {
63014
63649
  */
63015
63650
  history: "none"
63016
63651
  };
63652
+ var RUNNING_POWER_START_DELAY_MS = 3e4;
63653
+ var RUNNING_POWER_STOP_DELAY_MS = 18e4;
63654
+ var RunningStateSourceSchema = _enum(["native", "assigned"]);
63655
+ var RunningStateStatusSchema = object({
63656
+ /** null = unknown — never coerced to false (D393). */
63657
+ running: boolean().nullable(),
63658
+ /** Epoch ms the current boolean began; null while `running` is null. */
63659
+ since: number().nullable(),
63660
+ source: RunningStateSourceSchema,
63661
+ phase: string().nullable(),
63662
+ /** null until a reading has been published (D393). */
63663
+ lastFetchedAt: number().nullable()
63664
+ });
63665
+ var RunningFlipEventDataSchema = object({
63666
+ deviceId: number(),
63667
+ since: number().nullable(),
63668
+ phase: string().nullable()
63669
+ });
63670
+ var RUNNING_DEVICE_TYPES = Object.values(DeviceType);
63671
+ /** Generic Customize target for the running boolean (D936). */
63672
+ var runningCustomize = {
63673
+ version: 1,
63674
+ targets: [{
63675
+ id: "running",
63676
+ cardinality: "scalar",
63677
+ vocabulary: {
63678
+ cap: "running-state",
63679
+ stateField: "running"
63680
+ },
63681
+ deviceTypes: [
63682
+ DeviceType.Dishwasher,
63683
+ DeviceType.Vacuum,
63684
+ DeviceType.LawnMower,
63685
+ DeviceType.MediaPlayer,
63686
+ DeviceType.WaterHeater,
63687
+ DeviceType.Humidifier,
63688
+ DeviceType.Fan,
63689
+ DeviceType.Climate,
63690
+ DeviceType.Thermostat,
63691
+ DeviceType.PetFeeder
63692
+ ],
63693
+ apply: "add-or-replace",
63694
+ path: "running",
63695
+ sources: [
63696
+ {
63697
+ kind: "switch",
63698
+ transforms: [{ kind: "identity" }]
63699
+ },
63700
+ {
63701
+ kind: "binary",
63702
+ transforms: [{ kind: "identity" }, { kind: "invert" }]
63703
+ },
63704
+ {
63705
+ kind: "numeric",
63706
+ requiredUnit: "W",
63707
+ transforms: [{
63708
+ kind: "threshold",
63709
+ comparison: "gte",
63710
+ defaultThreshold: 5,
63711
+ defaultStartDwellMs: RUNNING_POWER_START_DELAY_MS,
63712
+ defaultStopDwellMs: RUNNING_POWER_STOP_DELAY_MS,
63713
+ thresholdUnit: "W"
63714
+ }]
63715
+ }
63716
+ ],
63717
+ companions: [
63718
+ {
63719
+ kind: "constant",
63720
+ path: "source",
63721
+ value: "assigned",
63722
+ when: "always"
63723
+ },
63724
+ {
63725
+ kind: "constant",
63726
+ path: "phase",
63727
+ value: null,
63728
+ when: "always"
63729
+ },
63730
+ {
63731
+ kind: "clock",
63732
+ path: "lastFetchedAt",
63733
+ when: "always"
63734
+ },
63735
+ {
63736
+ kind: "transition-time",
63737
+ path: "since",
63738
+ sourceChangedAt: "prefer"
63739
+ }
63740
+ ],
63741
+ sourceReport: {
63742
+ status: "assignment-status",
63743
+ runtimeField: "source",
63744
+ nativeValue: "native",
63745
+ assignedValue: "assigned"
63746
+ },
63747
+ advancedExpression: true
63748
+ }]
63749
+ };
63750
+ var runningStateCapability = {
63751
+ name: "running-state",
63752
+ scope: "device",
63753
+ deviceNative: true,
63754
+ mode: "singleton",
63755
+ deviceTypes: RUNNING_DEVICE_TYPES,
63756
+ methods: {},
63757
+ events: {
63758
+ onStarted: { data: RunningFlipEventDataSchema },
63759
+ onFinished: { data: RunningFlipEventDataSchema }
63760
+ },
63761
+ status: {
63762
+ schema: RunningStateStatusSchema,
63763
+ kind: "push"
63764
+ },
63765
+ runtimeState: RunningStateStatusSchema,
63766
+ durability: "restored",
63767
+ history: { fields: { running: { kind: "boolean" } } },
63768
+ volatileStateFields: ["lastFetchedAt"],
63769
+ customize: runningCustomize
63770
+ };
63017
63771
  /**
63018
63772
  * reboot — device-scoped capability for "soft" device reboots (firmware
63019
63773
  * reboot via vendor protocol; cameras, NVRs, doorbells). Surfaces a
@@ -65185,7 +65939,20 @@ var ZoneRuleSchema = object({
65185
65939
  * Defaults to `true` so operators creating a rule via the UI
65186
65940
  * see it active immediately.
65187
65941
  */
65188
- enabled: boolean().default(true)
65942
+ enabled: boolean().default(true),
65943
+ /**
65944
+ * Package stage only. When true, a package candidate may open from a
65945
+ * scene difference in this rule's zone after a person leaves. The
65946
+ * package model, when it boxes something overlapping, is extra evidence
65947
+ * and is not the gate. Absent or false keeps today's model path.
65948
+ */
65949
+ detectBySceneDifference: boolean().optional(),
65950
+ /**
65951
+ * Package stage only. When true, a promoted package is shown to the
65952
+ * `llm` cap before the delivery event is emitted. Absent or false emits
65953
+ * as today. Usable with or without `detectBySceneDifference`.
65954
+ */
65955
+ confirmWithLlm: boolean().optional()
65189
65956
  });
65190
65957
  array(ZoneRuleSchema).readonly();
65191
65958
  /**
@@ -67741,7 +68508,7 @@ method(object({}), array(TrainingProviderDescriptorSchema).readonly(), { auth: "
67741
68508
  * - **Jobs.** A persisted state machine, a reconcile loop against the
67742
68509
  * provider, a cost guard, a daily orphan sweep and the retention rules.
67743
68510
  * - **The return flow.** Verified artefacts → Model Studio
67744
- * (`custom-model-registry.importModelBundle`) → canary on cameras →
68511
+ * (`custom-model-registry.importModelBundle`) → canary on accelerators →
67745
68512
  * rollback. Nothing is ever registered automatically.
67746
68513
  *
67747
68514
  * Plan/start takes a live {@link TrainingCorpusSelection} (collections +
@@ -67878,20 +68645,24 @@ var TrainingProgressPointSchema = object({
67878
68645
  map50: number().nullable(),
67879
68646
  map50_95: number().nullable()
67880
68647
  });
68648
+ /** One accelerator: a `(node, inference device)` that runs the root detector. */
68649
+ var TrainingAcceleratorRefSchema = object({
68650
+ nodeId: string(),
68651
+ deviceKey: string()
68652
+ });
68653
+ /**
68654
+ * A canary pins the registered model on chosen ACCELERATORS — a model is
68655
+ * chosen by the accelerator that runs it (D927); every camera balanced onto
68656
+ * one runs it. `previous` is the root-detector pin each one had (`null` = it
68657
+ * ran its default), exactly, so rollback restores it.
68658
+ */
67881
68659
  var TrainingCanarySchema = object({
67882
- deviceIds: array(number().int()).readonly(),
68660
+ accelerators: array(TrainingAcceleratorRefSchema).readonly(),
67883
68661
  since: number(),
67884
- /** Every override the canary replaced, exactly, so rollback restores it. */
67885
- previous: array(object({
67886
- deviceId: number().int(),
67887
- nodeId: string(),
67888
- deviceKey: string(),
67889
- patch: object({
67890
- modelId: string().optional(),
67891
- settings: record(string(), unknown()).readonly().optional()
67892
- }).nullable()
67893
- })).readonly()
68662
+ previous: array(TrainingAcceleratorRefSchema.extend({ modelId: string().nullable() })).readonly()
67894
68663
  });
68664
+ /** An accelerator a canary may pin: it runs the root detector, on this model now. */
68665
+ var TrainingCanaryTargetSchema = TrainingAcceleratorRefSchema.extend({ pinnedModelId: string().nullable() });
67895
68666
  var TrainingJobSchema = object({
67896
68667
  id: string(),
67897
68668
  idempotencyKey: string(),
@@ -68003,11 +68774,11 @@ method(object({}), array(TrainingBaseModelSchema).readonly(), { auth: "admin" })
68003
68774
  kind: "mutation",
68004
68775
  auth: "admin",
68005
68776
  timeoutMs: 12e4
68006
- }), method(IdInput, TrainingResultSchema.nullable(), { auth: "admin" }), method(IdInput.extend({ canaryDeviceIds: array(number().int()).readonly() }), TrainingJobSchema, {
68777
+ }), method(IdInput, TrainingResultSchema.nullable(), { auth: "admin" }), method(_void(), array(TrainingCanaryTargetSchema).readonly(), { auth: "admin" }), method(IdInput.extend({ canaryAccelerators: array(TrainingAcceleratorRefSchema).readonly() }), TrainingJobSchema, {
68007
68778
  kind: "mutation",
68008
68779
  auth: "admin",
68009
68780
  timeoutMs: 30 * 6e4
68010
- }), method(IdInput.extend({ deviceIds: array(number().int()).min(1).readonly() }), TrainingJobSchema, {
68781
+ }), method(IdInput.extend({ accelerators: array(TrainingAcceleratorRefSchema).min(1).readonly() }), TrainingJobSchema, {
68011
68782
  kind: "mutation",
68012
68783
  auth: "admin",
68013
68784
  timeoutMs: 12e4
@@ -68518,6 +69289,7 @@ var DEVICE_LOCAL_STATE_CAPS = {
68518
69289
  ptzAutotrack: ptzAutotrackCapability,
68519
69290
  recordingOnboard: recordingOnboardCapability,
68520
69291
  recordingSignal: recordingSignalCapability,
69292
+ runningState: runningStateCapability,
68521
69293
  sceneMonitor: sceneMonitorCapability,
68522
69294
  scriptRunner: scriptRunnerCapability,
68523
69295
  smoke: smokeCapability,
@@ -72710,6 +73482,27 @@ Object.freeze({
72710
73482
  access: "create",
72711
73483
  role: "viewer"
72712
73484
  },
73485
+ "displayPalette.getPalette": {
73486
+ capName: "display-palette",
73487
+ capScope: "system",
73488
+ addonId: null,
73489
+ access: "view",
73490
+ role: "viewer"
73491
+ },
73492
+ "displayPalette.listPresets": {
73493
+ capName: "display-palette",
73494
+ capScope: "system",
73495
+ addonId: null,
73496
+ access: "view",
73497
+ role: "viewer"
73498
+ },
73499
+ "displayPalette.setPalette": {
73500
+ capName: "display-palette",
73501
+ capScope: "system",
73502
+ addonId: null,
73503
+ access: "create",
73504
+ role: "admin"
73505
+ },
72713
73506
  "doorbell.getStatus": {
72714
73507
  capName: "doorbell",
72715
73508
  capScope: "device",
@@ -75629,20 +76422,6 @@ Object.freeze({
75629
76422
  access: "create",
75630
76423
  role: "admin"
75631
76424
  },
75632
- "pipelineExecutor.clearDeviceOverrides": {
75633
- capName: "pipeline-executor",
75634
- capScope: "system",
75635
- addonId: null,
75636
- access: "delete",
75637
- role: "admin"
75638
- },
75639
- "pipelineExecutor.clearModelBoundDeviceOverrides": {
75640
- capName: "pipeline-executor",
75641
- capScope: "system",
75642
- addonId: null,
75643
- access: "delete",
75644
- role: "admin"
75645
- },
75646
76425
  "pipelineExecutor.deleteModel": {
75647
76426
  capName: "pipeline-executor",
75648
76427
  capScope: "system",
@@ -75685,13 +76464,6 @@ Object.freeze({
75685
76464
  access: "view",
75686
76465
  role: "admin"
75687
76466
  },
75688
- "pipelineExecutor.getDefaultSteps": {
75689
- capName: "pipeline-executor",
75690
- capScope: "system",
75691
- addonId: null,
75692
- access: "view",
75693
- role: "admin"
75694
- },
75695
76467
  "pipelineExecutor.getDetectionConfigSchema": {
75696
76468
  capName: "pipeline-executor",
75697
76469
  capScope: "system",
@@ -75713,20 +76485,6 @@ Object.freeze({
75713
76485
  access: "view",
75714
76486
  role: "admin"
75715
76487
  },
75716
- "pipelineExecutor.getGlobalPipelineConfig": {
75717
- capName: "pipeline-executor",
75718
- capScope: "system",
75719
- addonId: null,
75720
- access: "view",
75721
- role: "admin"
75722
- },
75723
- "pipelineExecutor.getGlobalSteps": {
75724
- capName: "pipeline-executor",
75725
- capScope: "system",
75726
- addonId: null,
75727
- access: "view",
75728
- role: "admin"
75729
- },
75730
76488
  "pipelineExecutor.getInferenceDeviceHealth": {
75731
76489
  capName: "pipeline-executor",
75732
76490
  capScope: "system",
@@ -75986,13 +76744,6 @@ Object.freeze({
75986
76744
  access: "view",
75987
76745
  role: "admin"
75988
76746
  },
75989
- "pipelineOrchestrator.getCameraStepOverrides": {
75990
- capName: "pipeline-orchestrator",
75991
- capScope: "system",
75992
- addonId: null,
75993
- access: "view",
75994
- role: "admin"
75995
- },
75996
76747
  "pipelineOrchestrator.getCameraSwitches": {
75997
76748
  capName: "pipeline-orchestrator",
75998
76749
  capScope: "system",
@@ -76231,13 +76982,6 @@ Object.freeze({
76231
76982
  access: "create",
76232
76983
  role: "admin"
76233
76984
  },
76234
- "pipelineOrchestrator.setCameraPipelineForAgent": {
76235
- capName: "pipeline-orchestrator",
76236
- capScope: "system",
76237
- addonId: null,
76238
- access: "create",
76239
- role: "admin"
76240
- },
76241
76985
  "pipelineOrchestrator.setCameraSensors": {
76242
76986
  capName: "pipeline-orchestrator",
76243
76987
  capScope: "system",
@@ -76245,42 +76989,42 @@ Object.freeze({
76245
76989
  access: "create",
76246
76990
  role: "admin"
76247
76991
  },
76248
- "pipelineOrchestrator.setCameraStepOverride": {
76992
+ "pipelineOrchestrator.setCameraStepSettings": {
76249
76993
  capName: "pipeline-orchestrator",
76250
76994
  capScope: "system",
76251
76995
  addonId: null,
76252
76996
  access: "create",
76253
76997
  role: "admin"
76254
76998
  },
76255
- "pipelineOrchestrator.setCameraStepSettings": {
76999
+ "pipelineOrchestrator.setCameraStepToggle": {
76256
77000
  capName: "pipeline-orchestrator",
76257
77001
  capScope: "system",
76258
77002
  addonId: null,
76259
77003
  access: "create",
76260
77004
  role: "admin"
76261
77005
  },
76262
- "pipelineOrchestrator.setCameraStepToggle": {
77006
+ "pipelineOrchestrator.setCameraSwitch": {
76263
77007
  capName: "pipeline-orchestrator",
76264
77008
  capScope: "system",
76265
77009
  addonId: null,
76266
77010
  access: "create",
76267
77011
  role: "admin"
76268
77012
  },
76269
- "pipelineOrchestrator.setCameraSwitch": {
77013
+ "pipelineOrchestrator.setCapabilityBinding": {
76270
77014
  capName: "pipeline-orchestrator",
76271
77015
  capScope: "system",
76272
77016
  addonId: null,
76273
77017
  access: "create",
76274
77018
  role: "admin"
76275
77019
  },
76276
- "pipelineOrchestrator.setCapabilityBinding": {
77020
+ "pipelineOrchestrator.setLoadBalancingShares": {
76277
77021
  capName: "pipeline-orchestrator",
76278
77022
  capScope: "system",
76279
77023
  addonId: null,
76280
77024
  access: "create",
76281
77025
  role: "admin"
76282
77026
  },
76283
- "pipelineOrchestrator.setLoadBalancingShares": {
77027
+ "pipelineOrchestrator.setNodeStepSettings": {
76284
77028
  capName: "pipeline-orchestrator",
76285
77029
  capScope: "system",
76286
77030
  addonId: null,
@@ -77309,6 +78053,13 @@ Object.freeze({
77309
78053
  access: "create",
77310
78054
  role: "admin"
77311
78055
  },
78056
+ "runningState.getStatus": {
78057
+ capName: "running-state",
78058
+ capScope: "device",
78059
+ addonId: null,
78060
+ access: "view",
78061
+ role: "viewer"
78062
+ },
77312
78063
  "sceneMonitor.captureReference": {
77313
78064
  capName: "scene-monitor",
77314
78065
  capScope: "device",
@@ -78639,6 +79390,13 @@ Object.freeze({
78639
79390
  access: "view",
78640
79391
  role: "admin"
78641
79392
  },
79393
+ "training.listCanaryTargets": {
79394
+ capName: "training",
79395
+ capScope: "system",
79396
+ addonId: null,
79397
+ access: "view",
79398
+ role: "admin"
79399
+ },
78642
79400
  "training.listJobs": {
78643
79401
  capName: "training",
78644
79402
  capScope: "system",
@@ -82016,6 +82774,32 @@ var APPLIANCE_CAP_VOCABULARY = {
82016
82774
  }],
82017
82775
  events: { onSent: { notOperatorFacing: "a delivery receipt of a send this system made — not a fact about the world" } }
82018
82776
  },
82777
+ "running-state": {
82778
+ scope: "device",
82779
+ noun: t("Running", "In funzione"),
82780
+ state: [{
82781
+ kind: "boolean",
82782
+ field: "running",
82783
+ label: t("Running", "In funzione"),
82784
+ whenTrue: t("When {device} starts", "Quando {device} inizia"),
82785
+ whenFalse: t("When {device} finishes", "Quando {device} finisce"),
82786
+ icon: "play"
82787
+ }],
82788
+ events: {
82789
+ onStarted: {
82790
+ category: EventCategory.RunningStarted,
82791
+ label: t("Started running", "Ha iniziato a funzionare"),
82792
+ phrase: t("When {device} starts running", "Quando {device} inizia a funzionare"),
82793
+ icon: "play"
82794
+ },
82795
+ onFinished: {
82796
+ category: EventCategory.RunningFinished,
82797
+ label: t("Finished", "Ha finito"),
82798
+ phrase: t("When {device} finishes", "Quando {device} finisce"),
82799
+ icon: "square"
82800
+ }
82801
+ }
82802
+ },
82019
82803
  update: {
82020
82804
  scope: "device",
82021
82805
  noun: t("Firmware update", "Aggiornamento firmware"),
@@ -83175,6 +83959,7 @@ var SYSTEM_CAP_VOCABULARY = {
83175
83959
  "device-provider": system(INTERNAL),
83176
83960
  "device-removal-hook": system(INTERNAL),
83177
83961
  "device-state": system("the runtime-state mirror every trigger already reads through"),
83962
+ "display-palette": system("the cluster display palette — one colour table for every client, not a device action"),
83178
83963
  "embedding-encoder": system(ML),
83179
83964
  "face-gallery": system("the face gallery — curated on its own page"),
83180
83965
  "failure-contribution": system(INTERNAL),
@@ -85177,11 +85962,6 @@ Object.freeze({
85177
85962
  form: "single",
85178
85963
  optional: false
85179
85964
  }],
85180
- "pipelineExecutor.clearModelBoundDeviceOverrides": [{
85181
- name: "deviceIds",
85182
- form: "array",
85183
- optional: true
85184
- }],
85185
85965
  "pipelineExecutor.runPipeline": [{
85186
85966
  name: "deviceId",
85187
85967
  form: "single",
@@ -85237,11 +86017,6 @@ Object.freeze({
85237
86017
  form: "array",
85238
86018
  optional: true
85239
86019
  }],
85240
- "pipelineOrchestrator.getCameraStepOverrides": [{
85241
- name: "deviceId",
85242
- form: "single",
85243
- optional: false
85244
- }],
85245
86020
  "pipelineOrchestrator.getCameraSwitches": [{
85246
86021
  name: "deviceId",
85247
86022
  form: "single",
@@ -85282,21 +86057,11 @@ Object.freeze({
85282
86057
  form: "single",
85283
86058
  optional: false
85284
86059
  }],
85285
- "pipelineOrchestrator.setCameraPipelineForAgent": [{
85286
- name: "deviceId",
85287
- form: "single",
85288
- optional: false
85289
- }],
85290
86060
  "pipelineOrchestrator.setCameraSensors": [{
85291
86061
  name: "deviceId",
85292
86062
  form: "single",
85293
86063
  optional: false
85294
86064
  }],
85295
- "pipelineOrchestrator.setCameraStepOverride": [{
85296
- name: "deviceId",
85297
- form: "single",
85298
- optional: false
85299
- }],
85300
86065
  "pipelineOrchestrator.setCameraStepSettings": [{
85301
86066
  name: "deviceId",
85302
86067
  form: "single",
@@ -85728,6 +86493,11 @@ Object.freeze({
85728
86493
  form: "single",
85729
86494
  optional: true
85730
86495
  }],
86496
+ "runningState.getStatus": [{
86497
+ name: "deviceId",
86498
+ form: "single",
86499
+ optional: false
86500
+ }],
85731
86501
  "sceneMonitor.captureReference": [{
85732
86502
  name: "deviceId",
85733
86503
  form: "single",
@@ -85974,11 +86744,6 @@ Object.freeze({
85974
86744
  form: "single",
85975
86745
  optional: false
85976
86746
  }],
85977
- "training.canaryResult": [{
85978
- name: "deviceIds",
85979
- form: "array",
85980
- optional: false
85981
- }],
85982
86747
  "update.getStatus": [{
85983
86748
  name: "deviceId",
85984
86749
  form: "single",
@@ -86231,6 +86996,96 @@ Object.freeze({
86231
86996
  "smtp-provider": "email"
86232
86997
  });
86233
86998
  DeviceType.Camera;
86999
+ 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;
87000
+ /**
87001
+ * A saved Customize assignment (D936). The schema is the type: callers use
87002
+ * `z.infer`, they do not restate the shape.
87003
+ */
87004
+ var OverrideSourceSchema = object({
87005
+ addonId: string().min(1),
87006
+ stableId: string().min(1),
87007
+ cap: string().min(1),
87008
+ fieldPath: string().min(1)
87009
+ });
87010
+ var CustomizeTransformDraftSchema = discriminatedUnion("kind", [
87011
+ object({ kind: literal("identity") }),
87012
+ object({ kind: literal("invert") }),
87013
+ object({
87014
+ kind: literal("threshold"),
87015
+ comparison: _enum(["gte", "lte"]),
87016
+ threshold: number(),
87017
+ startDwellMs: number().nonnegative(),
87018
+ stopDwellMs: number().nonnegative()
87019
+ }),
87020
+ object({
87021
+ kind: literal("linear"),
87022
+ scale: number(),
87023
+ offset: number(),
87024
+ clampMin: number().optional(),
87025
+ clampMax: number().optional()
87026
+ }),
87027
+ object({
87028
+ kind: literal("enum-map"),
87029
+ mapping: record(string(), string().nullable())
87030
+ }),
87031
+ object({ kind: literal("number") })
87032
+ ]);
87033
+ var ScalarOverrideDraftSchema = object({
87034
+ kind: literal("scalar"),
87035
+ cap: string().min(1),
87036
+ targetId: string().min(1),
87037
+ source: OverrideSourceSchema,
87038
+ transform: CustomizeTransformDraftSchema
87039
+ });
87040
+ var KeyedArrayOverrideDraftSchema = object({
87041
+ kind: literal("keyedArray"),
87042
+ cap: string().min(1),
87043
+ targetId: string().min(1),
87044
+ key: string().min(1),
87045
+ label: string().min(1),
87046
+ fieldPath: string().min(1),
87047
+ source: OverrideSourceSchema,
87048
+ transform: CustomizeTransformDraftSchema
87049
+ });
87050
+ var PulseOverrideDraftSchema = object({
87051
+ kind: literal("pulse"),
87052
+ cap: string().min(1),
87053
+ targetId: string().min(1),
87054
+ enabled: boolean(),
87055
+ debounceMs: number().nonnegative(),
87056
+ sources: array(OverrideSourceSchema).min(1)
87057
+ });
87058
+ var SpanSourceDraftSchema = OverrideSourceSchema.extend({ mode: _enum([
87059
+ "in-addition",
87060
+ "confirm",
87061
+ "replace"
87062
+ ]).optional() });
87063
+ discriminatedUnion("kind", [
87064
+ ScalarOverrideDraftSchema,
87065
+ KeyedArrayOverrideDraftSchema,
87066
+ PulseOverrideDraftSchema,
87067
+ object({
87068
+ kind: literal("span"),
87069
+ cap: string().min(1),
87070
+ targetId: string().min(1),
87071
+ timeoutMs: number().nonnegative(),
87072
+ cooldownMs: number().nonnegative().optional(),
87073
+ sources: array(SpanSourceDraftSchema)
87074
+ })
87075
+ ]);
87076
+ object({
87077
+ targetId: string().min(1),
87078
+ configured: boolean(),
87079
+ source: _enum(["native", "assigned"]),
87080
+ state: _enum([
87081
+ "active",
87082
+ "stale",
87083
+ "released",
87084
+ "unavailable"
87085
+ ]),
87086
+ reason: string().nullable()
87087
+ });
87088
+ String.raw`rose\(active(\d+), changed(\d+), (\d+(?:\.\d+)?)\)`;
86234
87089
  var G711_SCALE_CORRECTION_DB = {
86235
87090
  PCMU: 20 * Math.log10(4),
86236
87091
  PCMA: 20 * Math.log10(8)
@@ -86283,40 +87138,7 @@ var NC_AUDIO_DEFAULTS = {
86283
87138
  samplingSeconds: 10
86284
87139
  };
86285
87140
  new Set(["devices", "classes"]);
86286
- /**
86287
- * WHICH narrowing filter speaks about WHICH system-event kind — one predicate,
86288
- * consumed by the rule ENGINE and by every rule EDITOR.
86289
- *
86290
- * ── The failure this file exists for ───────────────────────────────────────
86291
- * `NcSystemEventConditionSchema` carries four optional narrowing lists
86292
- * (`deviceIds`, `deviceTypes`, `nodeIds`, `packageNames`) beside a required
86293
- * `kinds` gate. They are not four filters over one vocabulary: each belongs to
86294
- * a FAMILY of kinds and is meaningless outside it. A node going away has no
86295
- * device type; a completed export has no package; `stream-offline` deliberately
86296
- * carries no device type at all (a stream belongs to a camera by construction).
86297
- *
86298
- * The engine applied all four to every kind, so a filter from one family failed
86299
- * a kind from another family CLOSED. The operator's live rule "Eventi di
86300
- * sistema" selected eleven kinds and set `deviceTypes: ['camera']` — the only
86301
- * way to say "only my cameras" about the two liveness kinds — and NINE of the
86302
- * eleven silently stopped being deliverable. Four days of history contained
86303
- * `device-online` and `device-offline` and nothing else, across a window in
86304
- * which agents were restarted and addons were updated.
86305
- *
86306
- * Both editors already computed this scoping, to decide which filter boxes to
86307
- * render; the cap's own docblock already promised it ("Narrow a `device-*` kind
86308
- * to these device TYPES"). Only the engine disagreed, and it disagreed in the
86309
- * destructive direction. So the rule is stated ONCE, here, and the engine and
86310
- * the editors are readers of it rather than three independent authors.
86311
- *
86312
- * ── The direction ─────────────────────────────────────────────────────────
86313
- * Out of family ⇒ the filter is IGNORED, never fail-closed. An editor that
86314
- * hides a box has already told the operator this filter does not speak about
86315
- * these kinds, so honouring it as an exclusion contradicts the only
86316
- * explanation the operator was ever given. Inside its family the filter still
86317
- * narrows, and still fails CLOSED on a subject that cannot produce the identity
86318
- * it tests (a device the mirror cannot name is not evidence of a camera).
86319
- */
87141
+ new Set(NC_LEGACY_SYSTEM_EVENT_KINDS);
86320
87142
  /**
86321
87143
  * Every filter, for the callers that must cover all of them (guards, tests).
86322
87144
  *
@@ -86342,9 +87164,6 @@ new Map(Object.entries({
86342
87164
  "device-battery-normal": "device-events",
86343
87165
  "device-consumable-low": "device-events",
86344
87166
  "device-consumable-normal": "device-events",
86345
- "device-tank-low": "device-events",
86346
- "device-tank-full": "device-events",
86347
- "device-tank-normal": "device-events",
86348
87167
  "stream-online": "device-events",
86349
87168
  "stream-offline": "device-events",
86350
87169
  "detection-blind": "device-events",
@@ -86421,16 +87240,6 @@ var NC_SYSTEM_EVENT_KIND_GROUP_SPECS = [
86421
87240
  label: "Consumables",
86422
87241
  kinds: ["device-consumable-low", "device-consumable-normal"]
86423
87242
  },
86424
- {
86425
- id: "tanks",
86426
- family: "device-events",
86427
- label: "Tanks",
86428
- kinds: [
86429
- "device-tank-low",
86430
- "device-tank-full",
86431
- "device-tank-normal"
86432
- ]
86433
- },
86434
87243
  {
86435
87244
  id: "detection-blind",
86436
87245
  family: "device-events",
@@ -86588,11 +87397,6 @@ var RULE_BODY_ONLY = ["body"];
86588
87397
  var RULE_TEXT = ["title", "body"];
86589
87398
  var BATTERY = ["device-battery-low", "device-battery-normal"];
86590
87399
  var CONSUMABLE = ["device-consumable-low", "device-consumable-normal"];
86591
- var TANK = [
86592
- "device-tank-low",
86593
- "device-tank-full",
86594
- "device-tank-normal"
86595
- ];
86596
87400
  var ALERT_EPISODE = [
86597
87401
  "alert-critical",
86598
87402
  "alert-error",
@@ -86624,7 +87428,6 @@ var DEVICE_EVENTS = [
86624
87428
  "device-enabled",
86625
87429
  ...BATTERY,
86626
87430
  ...CONSUMABLE,
86627
- ...TANK,
86628
87431
  "stream-online",
86629
87432
  "stream-offline",
86630
87433
  "detection-blind",
@@ -86670,12 +87473,6 @@ var STATE_SUMMARY_SECTION_VARS = [
86670
87473
  example: "Robot — filter 10 %",
86671
87474
  kinds: CONSUMABLE
86672
87475
  },
86673
- {
86674
- name: "summaryTanks",
86675
- label: "Summary: tanks",
86676
- example: "Robot — clean water low",
86677
- kinds: TANK
86678
- },
86679
87476
  {
86680
87477
  name: "summaryDetection",
86681
87478
  label: "Summary: cameras detecting nothing",
@@ -86791,8 +87588,7 @@ var STATE_SUMMARY_VARS = [
86791
87588
  ([...RULE_TEXT], [...COMBINED_ALARM]),
86792
87589
  ([...RULE_TEXT], [...DEVICE_EVENTS]),
86793
87590
  ([...RULE_TEXT], [...BATTERY, ...CONSUMABLE]),
86794
- ([...RULE_TEXT], [...CONSUMABLE, ...TANK]),
86795
- ([...RULE_TEXT], [...TANK]),
87591
+ ([...RULE_TEXT], [...CONSUMABLE]),
86796
87592
  [...RULE_TEXT],
86797
87593
  ([...RULE_TEXT], [...UPDATES, ...ALERT_EPISODE]),
86798
87594
  ([...RULE_TEXT], [...UPDATES, ...ALERT_EPISODE]),
@@ -86896,15 +87692,6 @@ new Map([
86896
87692
  snapshotLabel: "Consumables low now",
86897
87693
  snapshotSection: "consumables"
86898
87694
  },
86899
- {
86900
- id: "tanks",
86901
- family: "device-events",
86902
- label: "Tanks (low or full / back to normal)",
86903
- bad: ["device-tank-low", "device-tank-full"],
86904
- recovery: ["device-tank-normal"],
86905
- snapshotLabel: "Tanks low or full now",
86906
- snapshotSection: "tanks"
86907
- },
86908
87695
  {
86909
87696
  id: "motion-noise",
86910
87697
  family: "device-events",
@@ -87357,6 +88144,10 @@ MotionOnMotionChangedDataSchema.omit({ triggeredBy: true });
87357
88144
  function providerMotionEvent(source, data) {
87358
88145
  return createEvent(EventCategory.ProviderMotion, source, data);
87359
88146
  }
88147
+ Object.freeze({
88148
+ person: .8,
88149
+ vehicle: .8
88150
+ });
87360
88151
  object({
87361
88152
  /**
87362
88153
  * Fraction of the box's own size added on EACH side before cutting.