@camstack/addon-provider-amcrest 0.2.157 → 0.2.158

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 +1169 -378
  2. package/dist/addon.mjs +1169 -378
  3. package/package.json +1 -1
package/dist/addon.js CHANGED
@@ -35,7 +35,7 @@ let node_stream_promises = require("node:stream/promises");
35
35
  let node_child_process = require("node:child_process");
36
36
  require("node:zlib");
37
37
  let node_os = require("node:os");
38
- //#region ../types/dist/event-category-BfJwUd2S.mjs
38
+ //#region ../types/dist/event-category-Ceif8n-v.mjs
39
39
  var EventCategory = /* @__PURE__ */ function(EventCategory) {
40
40
  EventCategory["SystemBoot"] = "system.boot";
41
41
  EventCategory["SystemAddonsReady"] = "system.addons-ready";
@@ -362,9 +362,8 @@ var EventCategory = /* @__PURE__ */ function(EventCategory) {
362
362
  EventCategory["PipelineMotionCalm"] = "pipeline.motion-calm";
363
363
  /**
364
364
  * Per-camera pipeline config was mutated by the orchestrator
365
- * (3-level settings change via `setAgentAddonDefaults` /
366
- * `setCameraStepToggle` / `setCameraPipelineForAgent` or a
367
- * pipeline-scoped `applyDeviceSettingsPatch`). Orchestrator
365
+ * (a settings change via `setAgentInferenceDevices` /
366
+ * `setCameraStepToggle` / `setCameraStepSettings`). Orchestrator
368
367
  * subscribes to its own emission to hot-reload the assigned runner
369
368
  * via `attachCamera` so the next frame executes against the new
370
369
  * engine/steps without waiting for a rebalance or the next
@@ -508,6 +507,10 @@ var EventCategory = /* @__PURE__ */ function(EventCategory) {
508
507
  * on the device detail page.
509
508
  */
510
509
  EventCategory["DoorbellOnPressed"] = "doorbell.onPressed";
510
+ /** Mirrors `runningStateCapability.events.onStarted`. */
511
+ EventCategory["RunningStarted"] = "running.started";
512
+ /** Mirrors `runningStateCapability.events.onFinished`. */
513
+ EventCategory["RunningFinished"] = "running.finished";
511
514
  /**
512
515
  * Cap event fired by every device that registers the `event-emitter`
513
516
  * capability. Mirrors `eventEmitterCapability.events.onEvent`. Carries
@@ -5467,7 +5470,7 @@ var ZodIssueCode = {
5467
5470
  var ZodFirstPartyTypeKind;
5468
5471
  ZodFirstPartyTypeKind || (ZodFirstPartyTypeKind = {});
5469
5472
  //#endregion
5470
- //#region ../types/dist/sleep-6AqUnQIT.mjs
5473
+ //#region ../types/dist/sleep-CYfIZzGv.mjs
5471
5474
  /**
5472
5475
  * The audio chunk plane's byte format, and the ONE expansion from a coded
5473
5476
  * window to float samples (D455).
@@ -5806,7 +5809,7 @@ Object.fromEntries([
5806
5809
  * `hydrateSchema` to skip the `value` injection for structural-only fields.
5807
5810
  */
5808
5811
  function isValuelessField(field) {
5809
- return field.type === "separator" || field.type === "info" || field.type === "qr-code" || field.type === "button" || field.type === "object-array" || field.type === "widget" || field.type === "addon-action-button" || field.type === "device-action-button";
5812
+ return field.type === "separator" || field.type === "info" || field.type === "qr-code" || field.type === "button" || field.type === "object-array" || field.type === "widget" || field.type === "addon-action-button" || field.type === "device-action-button" || field.type === "account-sign-in" || field.type === "secret-presence";
5810
5813
  }
5811
5814
  function hydrateSchema(schema, values, options = {}) {
5812
5815
  return {
@@ -8852,7 +8855,7 @@ var DeviceRole = /* @__PURE__ */ function(DeviceRole) {
8852
8855
  return DeviceRole;
8853
8856
  }({});
8854
8857
  //#endregion
8855
- //#region ../types/dist/composition-CB6PMT9p.mjs
8858
+ //#region ../types/dist/composition-BJ8iAZb3.mjs
8856
8859
  /**
8857
8860
  * The ffmpeg build every CamStack node downloads, per platform and arch.
8858
8861
  *
@@ -8912,7 +8915,7 @@ portable("linux64"), portable("linuxarm64"), portable("macarm64"), portable("mac
8912
8915
  * ONE table for everyone who asks "is this device HIGH?": the
8913
8916
  * recorder's `RecordingTriggers.sensorDeviceIds` trigger, the post-analysis
8914
8917
  * sensor markers, the orchestrator's camera-sensors bridge and
8915
- * the sources of a composite doorbell (`doorbellFeatureSources`, D671).
8918
+ * the sources of a pulse (`compilePulseOverride`, D936).
8916
8919
  * A second copy would diverge at the first cap added, and the symptom — "the
8917
8920
  * sensor rings the doorbell but does not record" — is exactly D62.
8918
8921
  *
@@ -9153,6 +9156,20 @@ var table = {
9153
9156
  apply: () => {
9154
9157
  throw new ExpressionEvalError("count: stateful evaluation context is required");
9155
9158
  }
9159
+ },
9160
+ dwell: {
9161
+ minArgs: 3,
9162
+ maxArgs: 3,
9163
+ apply: () => {
9164
+ throw new ExpressionEvalError("dwell: stateful evaluation context is required");
9165
+ }
9166
+ },
9167
+ latchedAt: {
9168
+ minArgs: 1,
9169
+ maxArgs: 1,
9170
+ apply: () => {
9171
+ throw new ExpressionEvalError("latchedAt: stateful evaluation context is required");
9172
+ }
9156
9173
  }
9157
9174
  };
9158
9175
  Object.freeze(Object.assign(Object.create(null), table));
@@ -10592,13 +10609,22 @@ var BirthDecisionRecordSchema = object({
10592
10609
  decidedByBirthEvidence: boolean(),
10593
10610
  /** Best class-compatible crop score, or `null` when nothing compatible was
10594
10611
  * found — deliberately not 0, which would be a measurement that never was.
10595
- * Includes a box the detector's own per-class floor refused (reason
10596
- * `below-detector-floor`, D922): that box never confirms, but it is the
10597
- * score the crop really held. */
10612
+ * Includes a box the detector's own per-class floor refused (D922): since
10613
+ * D925 the gate's bar, not that floor, decides whether it confirms. */
10598
10614
  bestScore: number().nullable(),
10599
10615
  /** The bar this candidate actually faced (the phantom-cell hook may raise it). */
10600
10616
  appliedMinConfidence: number().nullable(),
10601
10617
  /**
10618
+ * The detector the gate re-judged the birth WITH (D925): the session's own
10619
+ * root model, inference-device pool and node — never a node default. `null`
10620
+ * when the frame named no session detector or no gate ran, and on rows
10621
+ * written before D925. A `session-device-unavailable` row names the session
10622
+ * detector that could not be reached.
10623
+ */
10624
+ detectorModelId: string().nullable().default(null),
10625
+ detectorDeviceKey: string().nullable().default(null),
10626
+ detectorNodeId: string().nullable().default(null),
10627
+ /**
10602
10628
  * The track's own `firstSeen` — the candidate's first frame, which is where
10603
10629
  * the timeline starts. `null` for a suppressed birth, which has no track.
10604
10630
  */
@@ -16067,6 +16093,13 @@ var ComposerUnreadableBlockSchema = object({
16067
16093
  /** The parse error, in the operator's words. */
16068
16094
  error: string()
16069
16095
  });
16096
+ /** A confirmed release the hub did not accept. `deviceId` is the claim's device. */
16097
+ var UnreleasedClaimSchema = object({
16098
+ deviceId: number().int(),
16099
+ capName: string(),
16100
+ owner: string(),
16101
+ error: string()
16102
+ });
16070
16103
  method(object({
16071
16104
  /** The shared Blocks integration; null until `core-blocks` has reconciled it. */
16072
16105
  integrationId: string().nullable(),
@@ -16076,7 +16109,13 @@ method(object({
16076
16109
  /** Operator restarts: rebuild these runtimes and re-resolve their sources. Stores nothing (D62). */
16077
16110
  restartBlockIds: array(string()),
16078
16111
  /** Composition rows that exist but do not parse: held, never withdrawn, reported failed. */
16079
- unreadableBlocks: array(ComposerUnreadableBlockSchema)
16112
+ unreadableBlocks: array(ComposerUnreadableBlockSchema),
16113
+ /**
16114
+ * Operator-confirmed deletions. Their claims are released on this apply,
16115
+ * before any replacement block claims. A block that merely vanished from the
16116
+ * snapshot is not listed here and still waits for two applies (D49).
16117
+ */
16118
+ retiredBlockIds: array(string()).optional()
16080
16119
  }), object({
16081
16120
  blocks: array(object({
16082
16121
  blockId: string(),
@@ -16088,7 +16127,13 @@ method(object({
16088
16127
  * integration unknown, its own rows unread or read empty once). An empty
16089
16128
  * apply the caller owes is paid off only by one the composer acted on (D49).
16090
16129
  */
16091
- acted: boolean()
16130
+ acted: boolean(),
16131
+ /**
16132
+ * Confirmed releases this apply tried and the hub did not accept. Empty when
16133
+ * every one landed (or there was nothing to hand back). Absent on a result
16134
+ * that never got that far.
16135
+ */
16136
+ unreleasedClaims: array(UnreleasedClaimSchema).optional()
16092
16137
  }), {
16093
16138
  kind: "mutation",
16094
16139
  auth: "admin"
@@ -16131,7 +16176,15 @@ Object.freeze({
16131
16176
  kind: "fixed",
16132
16177
  result: ["number", "null"]
16133
16178
  },
16134
- count: NUMBER
16179
+ count: NUMBER,
16180
+ dwell: {
16181
+ kind: "fixed",
16182
+ result: ["boolean", "null"]
16183
+ },
16184
+ latchedAt: {
16185
+ kind: "fixed",
16186
+ result: ["number", "null"]
16187
+ }
16135
16188
  });
16136
16189
  `${COMPOSED_DEVICE_STABLE_ID_PREFIX}`;
16137
16190
  /**
@@ -42248,6 +42301,381 @@ var _macroLookup = /* @__PURE__ */ new Map();
42248
42301
  for (const [k, v] of Object.entries(YAMNET_TO_MACRO.mapping)) _macroLookup.set(k.toLowerCase(), v);
42249
42302
  for (const [k, v] of Object.entries(APPLE_SA_TO_MACRO.mapping)) _macroLookup.set(k.toLowerCase(), v);
42250
42303
  /**
42304
+ * Palette entry ids (D939). Audio is the one gradient; `audio-*` leaves are
42305
+ * not entries. `heatmapScrub` is a mark, not an event kind.
42306
+ */
42307
+ var PALETTE_ENTRY_IDS = [
42308
+ "motion",
42309
+ "audio",
42310
+ "recording",
42311
+ "live",
42312
+ "heatmapScrub",
42313
+ "person",
42314
+ "vehicle",
42315
+ "animal",
42316
+ "package",
42317
+ "sensor",
42318
+ "control",
42319
+ "face",
42320
+ "plate",
42321
+ "car",
42322
+ "truck",
42323
+ "bus",
42324
+ "motorcycle",
42325
+ "bicycle",
42326
+ "airplane",
42327
+ "boat",
42328
+ "train",
42329
+ "bird",
42330
+ "dog",
42331
+ "cat",
42332
+ "horse",
42333
+ "sheep",
42334
+ "cow",
42335
+ "elephant",
42336
+ "bear",
42337
+ "zebra",
42338
+ "giraffe",
42339
+ "package-delivered",
42340
+ "package-picked-up",
42341
+ "suitcase",
42342
+ "backpack",
42343
+ "handbag",
42344
+ "contact",
42345
+ "motion-sensor",
42346
+ "smoke",
42347
+ "flood",
42348
+ "gas",
42349
+ "carbon-monoxide",
42350
+ "vibration",
42351
+ "tamper",
42352
+ "presence",
42353
+ "enum-sensor",
42354
+ "device-event",
42355
+ "lock",
42356
+ "cover",
42357
+ "switch",
42358
+ "siren",
42359
+ "button",
42360
+ "doorbell"
42361
+ ];
42362
+ var AUDIO_ENTRY_ID = "audio";
42363
+ /** Six rungs, quiet → loud. The opaque end is the entry's hex. */
42364
+ var AUDIO_GRADIENT_ALPHAS = [
42365
+ .3,
42366
+ .42,
42367
+ .55,
42368
+ .7,
42369
+ .85,
42370
+ 1
42371
+ ];
42372
+ var PALETTE_PRESET_IDS = [
42373
+ "camstack",
42374
+ "high-contrast",
42375
+ "okabe-ito"
42376
+ ];
42377
+ /** Frozen palette tables (D939). The spec refuses a table that breaks the rule. */
42378
+ var CAMSTACK_HEX = {
42379
+ motion: "#d946ef",
42380
+ audio: "#059eb8",
42381
+ recording: "#ef4444",
42382
+ live: "#8d7a00",
42383
+ heatmapScrub: "#4b32ff",
42384
+ person: "#11a64c",
42385
+ vehicle: "#3b82f6",
42386
+ animal: "#ea6a09",
42387
+ package: "#924667",
42388
+ sensor: "#624bbc",
42389
+ control: "#944d24",
42390
+ face: "#ed4f8d",
42391
+ plate: "#4b7027",
42392
+ car: "#9684cf",
42393
+ truck: "#0f9b89",
42394
+ bus: "#a734a9",
42395
+ motorcycle: "#c1133a",
42396
+ bicycle: "#0e6a9b",
42397
+ airplane: "#7c9928",
42398
+ boat: "#b17933",
42399
+ train: "#ad6ca3",
42400
+ bird: "#0f7c55",
42401
+ dog: "#c82700",
42402
+ cat: "#7268f2",
42403
+ horse: "#cb795e",
42404
+ sheep: "#b8636b",
42405
+ cow: "#cb2969",
42406
+ elephant: "#1158d2",
42407
+ bear: "#8d5e00",
42408
+ zebra: "#0097d6",
42409
+ giraffe: "#8f61bb",
42410
+ "package-delivered": "#cd3f9b",
42411
+ "package-picked-up": "#388a08",
42412
+ suitcase: "#666800",
42413
+ backpack: "#ec5022",
42414
+ handbag: "#a76ef8",
42415
+ contact: "#ab5a49",
42416
+ "motion-sensor": "#b95d1a",
42417
+ smoke: "#dd3858",
42418
+ flood: "#b31e7d",
42419
+ gas: "#5b70b5",
42420
+ "carbon-monoxide": "#7b4e8e",
42421
+ vibration: "#e65bba",
42422
+ tamper: "#98464b",
42423
+ presence: "#3a9468",
42424
+ "enum-sensor": "#7885f8",
42425
+ "device-event": "#8c43c8",
42426
+ lock: "#649653",
42427
+ cover: "#c67597",
42428
+ switch: "#7a812a",
42429
+ siren: "#ac5d7f",
42430
+ button: "#b276cd",
42431
+ doorbell: "#0087ab"
42432
+ };
42433
+ var CAMSTACK_FALLBACK = [
42434
+ "#b34dc7",
42435
+ "#1d7d34",
42436
+ "#db6b6c",
42437
+ "#a43d29",
42438
+ "#0e6ee6",
42439
+ "#29a10b",
42440
+ "#a98731",
42441
+ "#0181c6"
42442
+ ];
42443
+ var HIGH_CONTRAST_HEX = {
42444
+ motion: "#964360",
42445
+ audio: "#23a132",
42446
+ recording: "#2494ca",
42447
+ live: "#bd7e2b",
42448
+ heatmapScrub: "#ad6eea",
42449
+ person: "#62611e",
42450
+ vehicle: "#f4534c",
42451
+ animal: "#1556cd",
42452
+ package: "#9c4415",
42453
+ sensor: "#066c48",
42454
+ control: "#f2479f",
42455
+ face: "#139d8a",
42456
+ plate: "#909024",
42457
+ car: "#8e35ab",
42458
+ truck: "#bd0b2b",
42459
+ bus: "#7a88ca",
42460
+ motorcycle: "#e26725",
42461
+ bicycle: "#a6679b",
42462
+ airplane: "#7c5720",
42463
+ boat: "#467a1b",
42464
+ train: "#6f65a4",
42465
+ bird: "#cb717f",
42466
+ dog: "#c62490",
42467
+ cat: "#b36850",
42468
+ horse: "#1872ac",
42469
+ sheep: "#927939",
42470
+ cow: "#428a5c",
42471
+ elephant: "#d41160",
42472
+ bear: "#799453",
42473
+ zebra: "#a85455",
42474
+ giraffe: "#746be8",
42475
+ "package-delivered": "#824a80",
42476
+ "package-picked-up": "#614ac1",
42477
+ suitcase: "#2f77f3",
42478
+ backpack: "#fa476d",
42479
+ handbag: "#c14cbe",
42480
+ contact: "#c83921",
42481
+ "motion-sensor": "#a07ebd",
42482
+ smoke: "#a25b13",
42483
+ flood: "#526bab",
42484
+ gas: "#924938",
42485
+ "carbon-monoxide": "#bb7e53",
42486
+ vibration: "#b66182",
42487
+ tamper: "#3c6931",
42488
+ presence: "#6c851d",
42489
+ "enum-sensor": "#ad2d48",
42490
+ "device-event": "#5e9b04",
42491
+ lock: "#00a062",
42492
+ cover: "#ad8624",
42493
+ switch: "#d05259",
42494
+ siren: "#cd67b3",
42495
+ button: "#c9746a",
42496
+ doorbell: "#338eeb"
42497
+ };
42498
+ var HIGH_CONTRAST_FALLBACK = [
42499
+ "#817f3b",
42500
+ "#a0733e",
42501
+ "#8658b2",
42502
+ "#956301",
42503
+ "#bc652d",
42504
+ "#647331",
42505
+ "#a14c9e",
42506
+ "#d14e71"
42507
+ ];
42508
+ var OKABE_ITO_HEX = {
42509
+ motion: "#b88128",
42510
+ audio: "#1096c8",
42511
+ recording: "#009e73",
42512
+ live: "#9c8c22",
42513
+ heatmapScrub: "#0072b2",
42514
+ person: "#d55e00",
42515
+ vehicle: "#c0739f",
42516
+ animal: "#226d18",
42517
+ package: "#91446c",
42518
+ sensor: "#217b56",
42519
+ control: "#648647",
42520
+ face: "#c22998",
42521
+ plate: "#fa4575",
42522
+ car: "#956301",
42523
+ truck: "#2f77f3",
42524
+ bus: "#7a4e86",
42525
+ motorcycle: "#f54597",
42526
+ bicycle: "#bb3e75",
42527
+ airplane: "#e054c0",
42528
+ boat: "#457942",
42529
+ train: "#867afa",
42530
+ bird: "#88914c",
42531
+ dog: "#1556cd",
42532
+ cat: "#71702c",
42533
+ horse: "#9b4fa4",
42534
+ sheep: "#c0559d",
42535
+ cow: "#d14f65",
42536
+ elephant: "#98470f",
42537
+ bear: "#595896",
42538
+ zebra: "#96790e",
42539
+ giraffe: "#cb717b",
42540
+ "package-delivered": "#139d8a",
42541
+ "package-picked-up": "#906ead",
42542
+ suitcase: "#d02939",
42543
+ backpack: "#d41160",
42544
+ handbag: "#f64f54",
42545
+ contact: "#7258d2",
42546
+ "motion-sensor": "#b66182",
42547
+ smoke: "#627abb",
42548
+ flood: "#b86ae4",
42549
+ gas: "#a95261",
42550
+ "carbon-monoxide": "#c65d3c",
42551
+ vibration: "#7a40b7",
42552
+ tamper: "#914b34",
42553
+ presence: "#9481c3",
42554
+ "enum-sensor": "#ac6d47",
42555
+ "device-event": "#7b6fce",
42556
+ lock: "#c67662",
42557
+ cover: "#a6564d",
42558
+ switch: "#ad2c4e",
42559
+ siren: "#348e08",
42560
+ button: "#d27303",
42561
+ doorbell: "#55770f"
42562
+ };
42563
+ var OKABE_ITO_FALLBACK = [
42564
+ "#9a3784",
42565
+ "#a7392c",
42566
+ "#409d50",
42567
+ "#6987e7",
42568
+ "#ee5b3d",
42569
+ "#c0430d",
42570
+ "#af79b3",
42571
+ "#4b6628"
42572
+ ];
42573
+ /**
42574
+ * The display palette (D939). One table of colours, three presets, one
42575
+ * validator. Taxonomy colours and every consumer read this — there is no
42576
+ * second hex table.
42577
+ */
42578
+ var paletteHexSchema = string().regex(/^#[0-9a-f]{6}$/);
42579
+ var paletteSwatchSchema = discriminatedUnion("form", [object({
42580
+ form: literal("solid"),
42581
+ hex: paletteHexSchema
42582
+ }), object({
42583
+ form: literal("gradient"),
42584
+ hex: paletteHexSchema,
42585
+ alphas: array(number().gt(0).lte(1)).length(AUDIO_GRADIENT_ALPHAS.length)
42586
+ })]);
42587
+ var paletteReadySchema = object({
42588
+ status: literal("ready"),
42589
+ presetId: _enum(PALETTE_PRESET_IDS),
42590
+ customized: boolean(),
42591
+ source: _enum(["stored", "unconfigured"]),
42592
+ swatches: record(string(), paletteSwatchSchema),
42593
+ fallbacks: array(paletteHexSchema).length(8)
42594
+ });
42595
+ var paletteResultSchema = discriminatedUnion("status", [paletteReadySchema, object({
42596
+ status: literal("unknown"),
42597
+ reason: string()
42598
+ })]);
42599
+ var setPaletteInputSchema = union([object({ presetId: string() }), object({
42600
+ presetId: string(),
42601
+ overrides: record(string(), paletteSwatchSchema)
42602
+ })]);
42603
+ object({
42604
+ presetId: string(),
42605
+ overrides: record(string(), paletteSwatchSchema)
42606
+ });
42607
+ function solid(hex) {
42608
+ return {
42609
+ form: "solid",
42610
+ hex
42611
+ };
42612
+ }
42613
+ function audioGradient(hex) {
42614
+ return {
42615
+ form: "gradient",
42616
+ hex,
42617
+ alphas: [...AUDIO_GRADIENT_ALPHAS]
42618
+ };
42619
+ }
42620
+ function swatchesFrom(hexes) {
42621
+ const out = {};
42622
+ for (const id of PALETTE_ENTRY_IDS) {
42623
+ const hex = hexes[id];
42624
+ if (hex === void 0) throw new Error(`palette table missing ${id}`);
42625
+ out[id] = id === "audio" ? audioGradient(hex) : solid(hex);
42626
+ }
42627
+ return out;
42628
+ }
42629
+ function preset(id, name, hexes, fallbacks) {
42630
+ return {
42631
+ id,
42632
+ name,
42633
+ swatches: swatchesFrom(hexes),
42634
+ fallbacks
42635
+ };
42636
+ }
42637
+ var DISPLAY_PRESETS = [
42638
+ preset("camstack", "CamStack", CAMSTACK_HEX, CAMSTACK_FALLBACK),
42639
+ preset("high-contrast", "High contrast", HIGH_CONTRAST_HEX, HIGH_CONTRAST_FALLBACK),
42640
+ preset("okabe-ito", "Colour-blind safe", OKABE_ITO_HEX, OKABE_ITO_FALLBACK)
42641
+ ];
42642
+ function presetById(id) {
42643
+ return DISPLAY_PRESETS.find((item) => item.id === id);
42644
+ }
42645
+ function bundledCamstack() {
42646
+ const presetRow = presetById("camstack");
42647
+ if (presetRow === void 0) throw new Error("CamStack preset missing");
42648
+ return readyOf(presetRow, "unconfigured", false);
42649
+ }
42650
+ function readyOf(row, source, customized) {
42651
+ return {
42652
+ status: "ready",
42653
+ presetId: row.id,
42654
+ customized,
42655
+ source,
42656
+ swatches: row.swatches,
42657
+ fallbacks: [...row.fallbacks]
42658
+ };
42659
+ }
42660
+ function hashFallback(kind, fallbacks) {
42661
+ let hash = 0;
42662
+ for (let i = 0; i < kind.length; i++) hash = hash * 31 + (kind.codePointAt(i) ?? 0) >>> 0;
42663
+ const hex = fallbacks[hash % fallbacks.length];
42664
+ if (hex === void 0) throw new Error("display palette has no fallback colour");
42665
+ return hex;
42666
+ }
42667
+ /** Colour a kind paints with. Audio leaves share the audio gradient's hex. */
42668
+ function paintHex(swatches, fallbacks, kind) {
42669
+ const key = kind.trim().toLowerCase();
42670
+ if (key.startsWith("audio-")) {
42671
+ const audio = swatches[AUDIO_ENTRY_ID];
42672
+ return audio !== void 0 ? audio.hex : hashFallback(key, fallbacks);
42673
+ }
42674
+ const direct = swatches[key];
42675
+ if (direct !== void 0) return direct.hex;
42676
+ return hashFallback(key, fallbacks);
42677
+ }
42678
+ /**
42251
42679
  * Unified event-kind taxonomy — THE single source of truth for
42252
42680
  * `kind → { parentKind, category, level, color, iconId, labelKey, label,
42253
42681
  * icon }`.
@@ -42261,109 +42689,88 @@ for (const [k, v] of Object.entries(APPLE_SA_TO_MACRO.mapping)) _macroLookup.set
42261
42689
  * - `addon-post-analysis/shared/frame/box-drawer.ts` (DEFAULT_COLOR)
42262
42690
  * - the COCO / audio class maps (macro ↔ sub relationships)
42263
42691
  *
42264
- * The DATA (serializable — color/iconId/labelKey/parentKind) lives here in
42265
- * `@camstack/types`. The UI-side mapping `iconId → lucide component` and
42266
- * `labelKey → t()` lives in `@camstack/ui-library`. UIs never hardcode a
42267
- * color or an icon: they read this dictionary (server descriptors carry the
42268
- * fields inline; the client resolves color/icon/label from `iconId`/`kind`).
42692
+ * The DATA (serializable — parentKind / iconId / labelKey) lives here in
42693
+ * `@camstack/types`. Colour is NOT a second table: each entry's `color` is
42694
+ * the bundled CamStack display palette (D939). The effective cluster palette
42695
+ * is the `display-palette` capability. The UI-side mapping `iconId → lucide
42696
+ * component` and `labelKey → t()` lives in `@camstack/ui-library`.
42269
42697
  *
42270
42698
  * Two levels only (v1 YAGNI): macro → sub. `person` is a leaf macro.
42271
42699
  */
42272
- var TAXONOMY_COLORS = {
42273
- motion: "#f59e0b",
42274
- audio: "#06b6d4",
42275
- person: "#22c55e",
42276
- vehicle: "#3b82f6",
42277
- animal: "#f97316",
42278
- package: "#a855f7",
42279
- sensor: "#8b5cf6",
42280
- control: "#10b981",
42281
- genericDetection: "#64748b"
42282
- };
42283
- var DETECTION_SUB_COLORS = {
42284
- car: "#f59e0b",
42285
- truck: "#d97706",
42286
- bus: "#b45309",
42287
- motorcycle: "#eab308",
42288
- bicycle: "#ca8a04",
42289
- airplane: "#60a5fa",
42290
- boat: "#2563eb",
42291
- train: "#1d4ed8",
42292
- bird: "#14b8a6",
42293
- dog: "#84cc16",
42294
- cat: "#f97316",
42295
- horse: "#a16207",
42296
- sheep: "#a3a3a3",
42297
- cow: "#78716c",
42298
- elephant: "#6b7280",
42299
- bear: "#7c2d12",
42300
- zebra: "#404040",
42301
- giraffe: "#d4a373"
42302
- };
42700
+ var BUNDLED_PALETTE = bundledCamstack();
42701
+ function kindColor(kind) {
42702
+ return paintHex(BUNDLED_PALETTE.swatches, BUNDLED_PALETTE.fallbacks, kind);
42703
+ }
42704
+ function firstFallback(fallbacks) {
42705
+ const hex = fallbacks[0];
42706
+ if (hex === void 0) throw new Error("display palette has no fallback colour");
42707
+ return hex;
42708
+ }
42709
+ firstFallback(BUNDLED_PALETTE.fallbacks);
42303
42710
  function titleCase(id) {
42304
42711
  return id.split(/[-_ ]/).filter((p) => p.length > 0).map((p) => p.charAt(0).toUpperCase() + p.slice(1)).join(" ");
42305
42712
  }
42306
42713
  var entries = /* @__PURE__ */ new Map();
42307
- function macro(kind, category, color, iconId, label) {
42714
+ function macro(kind, category, iconId, label) {
42308
42715
  entries.set(kind, {
42309
42716
  kind,
42310
42717
  parentKind: null,
42311
42718
  level: "macro",
42312
42719
  category,
42313
- color,
42720
+ color: kindColor(kind),
42314
42721
  iconId,
42315
42722
  labelKey: `eventKind.${kind}`,
42316
42723
  label
42317
42724
  });
42318
42725
  }
42319
- function sub(kind, parentKind, category, color, iconId, label) {
42726
+ function sub(kind, parentKind, category, iconId, label) {
42320
42727
  entries.set(kind, {
42321
42728
  kind,
42322
42729
  parentKind,
42323
42730
  level: "sub",
42324
42731
  category,
42325
- color,
42732
+ color: kindColor(kind),
42326
42733
  iconId,
42327
42734
  labelKey: `eventKind.${kind}`,
42328
42735
  label
42329
42736
  });
42330
42737
  }
42331
- macro("motion", "motion", TAXONOMY_COLORS.motion, "motion", "Motion");
42332
- macro("audio", "audio", TAXONOMY_COLORS.audio, "audio", "Audio");
42333
- macro("person", "detection", TAXONOMY_COLORS.person, "person", "Person");
42334
- macro("vehicle", "detection", TAXONOMY_COLORS.vehicle, "vehicle", "Vehicle");
42335
- macro("animal", "detection", TAXONOMY_COLORS.animal, "animal", "Animal");
42336
- macro("package", "package", TAXONOMY_COLORS.package, "package", "Package");
42337
- macro("sensor", "sensor", TAXONOMY_COLORS.sensor, "sensor", "Sensor");
42338
- macro("control", "control", TAXONOMY_COLORS.control, "control", "Control");
42738
+ macro("motion", "motion", "motion", "Motion");
42739
+ macro("audio", "audio", "audio", "Audio");
42740
+ macro("person", "detection", "person", "Person");
42741
+ macro("vehicle", "detection", "vehicle", "Vehicle");
42742
+ macro("animal", "detection", "animal", "Animal");
42743
+ macro("package", "package", "package", "Package");
42744
+ macro("sensor", "sensor", "sensor", "Sensor");
42745
+ macro("control", "control", "control", "Control");
42339
42746
  for (const [cocoClass, macroClass] of Object.entries(COCO_TO_MACRO.mapping)) {
42340
42747
  if (macroClass !== "vehicle" && macroClass !== "animal") continue;
42341
42748
  if (entries.has(cocoClass)) continue;
42342
- sub(cocoClass, macroClass, "detection", DETECTION_SUB_COLORS[cocoClass] ?? TAXONOMY_COLORS.genericDetection, cocoClass, titleCase(cocoClass));
42749
+ sub(cocoClass, macroClass, "detection", cocoClass, titleCase(cocoClass));
42343
42750
  }
42344
- sub("package-delivered", "package", "package", TAXONOMY_COLORS.package, "package", "Package delivered");
42345
- sub("package-picked-up", "package", "package", TAXONOMY_COLORS.package, "package", "Package picked up");
42346
- sub("contact", "sensor", "sensor", "#f59e0b", "door", "Contact");
42347
- sub("motion-sensor", "sensor", "sensor", TAXONOMY_COLORS.sensor, "pir", "Motion sensor");
42348
- sub("smoke", "sensor", "sensor", "#ef4444", "smoke", "Smoke");
42349
- sub("flood", "sensor", "sensor", "#3b82f6", "water", "Water leak");
42350
- sub("gas", "sensor", "sensor", "#ef4444", "gas", "Gas");
42351
- sub("carbon-monoxide", "sensor", "sensor", "#dc2626", "smoke", "Carbon monoxide");
42352
- sub("vibration", "sensor", "sensor", "#eab308", "vibration", "Vibration");
42353
- sub("tamper", "sensor", "sensor", "#f97316", "tamper", "Tamper");
42354
- sub("presence", "sensor", "sensor", "#22c55e", "presence", "Presence");
42355
- sub("enum-sensor", "sensor", "sensor", TAXONOMY_COLORS.sensor, "generic", "Sensor state");
42356
- sub("device-event", "sensor", "sensor", "#10b981", "button", "Device event");
42357
- sub("lock", "control", "control", "#0ea5e9", "lock", "Lock");
42358
- sub("cover", "control", "control", "#0ea5e9", "door", "Cover");
42359
- sub("switch", "control", "control", TAXONOMY_COLORS.control, "switch", "Switch");
42360
- sub("siren", "control", "control", "#dc2626", "siren", "Siren");
42361
- sub("button", "control", "control", "#10b981", "button", "Button");
42362
- sub("doorbell", "control", "control", "#a855f7", "doorbell", "Doorbell");
42751
+ sub("package-delivered", "package", "package", "package", "Package delivered");
42752
+ sub("package-picked-up", "package", "package", "package", "Package picked up");
42753
+ sub("contact", "sensor", "sensor", "door", "Contact");
42754
+ sub("motion-sensor", "sensor", "sensor", "pir", "Motion sensor");
42755
+ sub("smoke", "sensor", "sensor", "smoke", "Smoke");
42756
+ sub("flood", "sensor", "sensor", "water", "Water leak");
42757
+ sub("gas", "sensor", "sensor", "gas", "Gas");
42758
+ sub("carbon-monoxide", "sensor", "sensor", "smoke", "Carbon monoxide");
42759
+ sub("vibration", "sensor", "sensor", "vibration", "Vibration");
42760
+ sub("tamper", "sensor", "sensor", "tamper", "Tamper");
42761
+ sub("presence", "sensor", "sensor", "presence", "Presence");
42762
+ sub("enum-sensor", "sensor", "sensor", "generic", "Sensor state");
42763
+ sub("device-event", "sensor", "sensor", "button", "Device event");
42764
+ sub("lock", "control", "control", "lock", "Lock");
42765
+ sub("cover", "control", "control", "door", "Cover");
42766
+ sub("switch", "control", "control", "switch", "Switch");
42767
+ sub("siren", "control", "control", "siren", "Siren");
42768
+ sub("button", "control", "control", "button", "Button");
42769
+ sub("doorbell", "control", "control", "doorbell", "Doorbell");
42363
42770
  for (const l of AUDIO_MACRO_LABELS) {
42364
42771
  const kind = `audio-${l.id}`;
42365
42772
  if (entries.has(kind)) continue;
42366
- sub(kind, "audio", "audio", TAXONOMY_COLORS.audio, kind, l.name);
42773
+ sub(kind, "audio", "audio", kind, l.name);
42367
42774
  }
42368
42775
  /** The complete taxonomy dictionary, keyed by kind. */
42369
42776
  var EVENT_TAXONOMY = Object.freeze(Object.fromEntries(entries));
@@ -42674,9 +43081,6 @@ var NcSystemEventKindSchema = _enum([
42674
43081
  "device-battery-normal",
42675
43082
  "device-consumable-low",
42676
43083
  "device-consumable-normal",
42677
- "device-tank-low",
42678
- "device-tank-full",
42679
- "device-tank-normal",
42680
43084
  "stream-online",
42681
43085
  "stream-offline",
42682
43086
  "node-online",
@@ -42723,13 +43127,14 @@ var NcSystemEventKindSchema = _enum([
42723
43127
  "camera-enabled"
42724
43128
  ]);
42725
43129
  /** The legacy tail of {@link NcSystemEventKindSchema} — see its docblock. */
42726
- var NC_LEGACY_SYSTEM_EVENT_KINDS = new Set([
43130
+ var NC_LEGACY_SYSTEM_EVENT_KINDS = [
42727
43131
  "camera-online",
42728
43132
  "camera-offline",
42729
43133
  "camera-disabled",
42730
43134
  "camera-enabled"
42731
- ]);
42732
- NcSystemEventKindSchema.options.filter((kind) => !NC_LEGACY_SYSTEM_EVENT_KINDS.has(kind));
43135
+ ];
43136
+ var NC_LEGACY_SYSTEM_EVENT_KIND_SET = new Set(NC_LEGACY_SYSTEM_EVENT_KINDS);
43137
+ NcSystemEventKindSchema.options.filter((kind) => !NC_LEGACY_SYSTEM_EVENT_KIND_SET.has(kind));
42733
43138
  /**
42734
43139
  * The panel's transitions, as ONE list.
42735
43140
  *
@@ -43848,18 +44253,11 @@ var NcRuleSchema = NcRuleInputSchema.extend({
43848
44253
  */
43849
44254
  disabledTargetIds: array(string()).default([])
43850
44255
  });
43851
- /**
43852
- * The state-summary SECTIONS (D647 / D698 / D708): the D637 kind groups that
43853
- * report a still-true state. `addons` is the crash-looped addons only and
43854
- * `addon-updates` the addons that are behind (D708 split them). `backups-exports` and `alarm` are not sections — a completed
43855
- * job is not an open state, and the alarm stays instant.
43856
- */
43857
44256
  var NcStateSummarySectionIdSchema = _enum([
43858
44257
  "device-state",
43859
44258
  "streams",
43860
44259
  "battery",
43861
44260
  "consumables",
43862
- "tanks",
43863
44261
  "detection-blind",
43864
44262
  "nodes",
43865
44263
  "addons",
@@ -45160,6 +45558,18 @@ Object.freeze({
45160
45558
  reason: "camera sensor mappings not loaded"
45161
45559
  });
45162
45560
  /**
45561
+ * What the vision model must answer before a package event is emitted
45562
+ * when a packages rule has "Confirm with the LLM" on.
45563
+ *
45564
+ * `package` is the verdict. `confidence` is 0..1. `reason` is the model's
45565
+ * one-line explanation, stored on the event so a drop is not silent.
45566
+ */
45567
+ var PackageLlmVerdictSchema = object({
45568
+ package: boolean(),
45569
+ confidence: number().min(0).max(1),
45570
+ reason: string().min(1)
45571
+ });
45572
+ /**
45163
45573
  * A model choice has a SCOPE, and a scope change has a workflow.
45164
45574
  *
45165
45575
  * ## The two scopes
@@ -46096,6 +46506,21 @@ var ObjectEventSchema = object({
46096
46506
  * pick-up written before D684 — UNKNOWN, never 0 and never `timestamp`.
46097
46507
  */
46098
46508
  observedAt: number().optional(),
46509
+ /**
46510
+ * The delivery was emitted without a vision-model yes (D931).
46511
+ *
46512
+ * Set only when the packages rule asked for an LLM confirm and the model
46513
+ * was unreachable, timed out, or answered something that did not parse.
46514
+ * A notification reads it so it can say "possible" instead of a definite
46515
+ * delivery. Absent on every other row, and on a confirm that said yes.
46516
+ */
46517
+ packagePossible: boolean().optional(),
46518
+ /**
46519
+ * The vision model's verdict, when a packages rule asked for one and the
46520
+ * model answered the schema (D931). A "no" never becomes a row — the
46521
+ * detector drops it and logs the reason. Present on a yes.
46522
+ */
46523
+ packageLlmVerdict: PackageLlmVerdictSchema.optional(),
46099
46524
  /** The parent track's key-event importance [0,1], propagated to every object
46100
46525
  * event of the track (so an event row can be sorted by importance without a
46101
46526
  * track join). Absent on legacy rows / before the track was scored. */
@@ -47893,7 +48318,6 @@ var PipelineAddonSchemaSchema = object({
47893
48318
  defaultModelId: string(),
47894
48319
  defaultModelIdByFormat: record(string(), string()).optional(),
47895
48320
  enabledByDefault: boolean().optional(),
47896
- backfillIntoExistingOverrides: boolean().optional(),
47897
48321
  defaultConfidence: number(),
47898
48322
  group: string().optional(),
47899
48323
  configSchema: array(ConfigFieldBridge).readonly().optional()
@@ -48020,13 +48444,12 @@ var AudioTestResultSchema = object({
48020
48444
  error: string().optional(),
48021
48445
  frame: custom().optional()
48022
48446
  });
48023
- var PipelineConfigBridge = custom();
48024
48447
  var ConfigUISchemaBridge = custom();
48025
48448
  var ConfigUISchemaNullableBridge = custom();
48026
48449
  var InferenceCapabilitiesBridge = custom();
48027
48450
  var ModelAvailabilityListBridge = custom();
48028
48451
  var PipelineRunResultBridge = custom();
48029
- method(_void(), array(PipelineEngineChoiceSchema)), method(_void(), PipelineEngineChoiceSchema), method(PipelineEngineChoiceSchema, array(PipelineDefaultStepSchema)), method(object({ nodeId: string() }), EngineProvisioningSchema), method(_void(), record(string(), object({
48452
+ method(_void(), array(PipelineEngineChoiceSchema)), method(_void(), PipelineEngineChoiceSchema), method(object({ nodeId: string() }), EngineProvisioningSchema), method(_void(), record(string(), object({
48030
48453
  modelId: string(),
48031
48454
  settings: record(string(), unknown()).readonly()
48032
48455
  }))), method(object({ steps: record(string(), object({
@@ -48035,28 +48458,6 @@ method(_void(), array(PipelineEngineChoiceSchema)), method(_void(), PipelineEngi
48035
48458
  })) }), object({ success: literal(true) }), {
48036
48459
  kind: "mutation",
48037
48460
  auth: "admin"
48038
- }), method(object({ nodeId: string() }), object({
48039
- success: literal(true),
48040
- clearedDevices: number()
48041
- }), {
48042
- kind: "mutation",
48043
- auth: "admin"
48044
- }), method(object({
48045
- nodeId: string(),
48046
- deviceIds: array(number()).readonly().optional(),
48047
- dryRun: boolean()
48048
- }), object({
48049
- entries: array(object({
48050
- deviceId: number(),
48051
- keys: array(string()).readonly()
48052
- })).readonly(),
48053
- refused: array(object({
48054
- deviceId: number(),
48055
- reason: string()
48056
- })).readonly()
48057
- }), {
48058
- kind: "mutation",
48059
- auth: "admin"
48060
48461
  }), method(object({ nodeId: string() }), object({ unhealthy: array(object({
48061
48462
  /** `<backend>:<device>`, e.g. `openvino:gpu`. */
48062
48463
  deviceKey: string(),
@@ -48079,7 +48480,7 @@ method(_void(), array(PipelineEngineChoiceSchema)), method(_void(), PipelineEngi
48079
48480
  }), object({ rearmed: boolean() }), {
48080
48481
  kind: "mutation",
48081
48482
  auth: "admin"
48082
- }), method(_void(), PipelineSchemaSchema), method(_void(), array(PipelineDefaultStepSchema).readonly().nullable()), method(_void(), PipelineConfigBridge), method(_void(), ConfigUISchemaBridge), method(object({
48483
+ }), method(_void(), PipelineSchemaSchema), method(_void(), ConfigUISchemaBridge), method(object({
48083
48484
  steps: array(PipelineStepInputSchema),
48084
48485
  deviceKey: string().optional()
48085
48486
  }), PipelineValidationResultSchema), method(_void(), InferenceCapabilitiesBridge), method(object({ addonId: string() }), ModelAvailabilityListBridge), method(object({
@@ -48327,11 +48728,18 @@ var KeptReasonSchema = _enum(["custom-pin"]);
48327
48728
  * Where a choice's latency came from (D791): this node's own benchmark
48328
48729
  * result, or the hardware-class table. Measured on the node beats the table.
48329
48730
  */
48330
- var LatencySourceSchema = discriminatedUnion("kind", [object({ kind: literal("table") }), object({
48331
- kind: literal("node-benchmark"),
48332
- resultId: string(),
48333
- measuredAtMs: number()
48334
- })]);
48731
+ var LatencySourceSchema = discriminatedUnion("kind", [
48732
+ object({ kind: literal("table") }),
48733
+ object({
48734
+ kind: literal("node-benchmark"),
48735
+ resultId: string(),
48736
+ measuredAtMs: number()
48737
+ }),
48738
+ object({
48739
+ kind: literal("estimated"),
48740
+ estimatedFrom: HardwareClassIdSchema
48741
+ })
48742
+ ]);
48335
48743
  var DeviceModelChoiceSchema = object({
48336
48744
  modelId: string(),
48337
48745
  p50Ms: number(),
@@ -48339,6 +48747,11 @@ var DeviceModelChoiceSchema = object({
48339
48747
  measured: boolean(),
48340
48748
  /** Absent on a plan from before D791 — read as the table. */
48341
48749
  source: LatencySourceSchema.optional(),
48750
+ /**
48751
+ * The measured class this latency was scaled from (D930). Absent when the
48752
+ * cell is the table or a node benchmark.
48753
+ */
48754
+ estimatedFrom: HardwareClassIdSchema.optional(),
48342
48755
  /** Parallel sessions at the camera rate with the headroom kept free: ⌊fps × (1 − headroom) / camera fps⌋. */
48343
48756
  capacitySessions: number(),
48344
48757
  personRecall: number()
@@ -48378,40 +48791,20 @@ var NodeDeviceChangeSchema = object({
48378
48791
  keys: array(string()).readonly()
48379
48792
  })).readonly()
48380
48793
  });
48381
- var CameraOverrideClearSchema = object({
48382
- deviceId: number(),
48383
- source: _enum(["step-override", "wholesale"]),
48794
+ /**
48795
+ * Every model and model-bound threshold lives on the accelerator that runs it
48796
+ * (D927), so the plan writes node / device entries only — there is no camera
48797
+ * layer for it to clear.
48798
+ */
48799
+ var AutoTuneWarningSchema = discriminatedUnion("kind", [object({
48800
+ kind: literal("custom-pin-kept"),
48384
48801
  nodeId: string(),
48385
- deviceKey: string().nullable(),
48386
- stepId: string(),
48387
- modelIdBefore: string().nullable(),
48388
- keys: array(string()).readonly()
48389
- });
48390
- var DetectorStoreClearSchema = object({
48391
- deviceId: number(),
48392
- keys: array(string()).readonly()
48393
- });
48394
- var AutoTuneWarningSchema = discriminatedUnion("kind", [
48395
- object({
48396
- kind: literal("detector-store-cluster-wide"),
48397
- skippedNodes: array(string()).readonly()
48398
- }),
48399
- object({
48400
- kind: literal("detector-store-unreadable"),
48401
- error: string()
48402
- }),
48403
- object({
48404
- kind: literal("custom-pin-kept"),
48405
- nodeId: string(),
48406
- deviceKey: string().nullable(),
48407
- deviceId: number().nullable(),
48408
- modelId: string()
48409
- }),
48410
- object({
48411
- kind: literal("custom-registry-unreadable"),
48412
- error: string()
48413
- })
48414
- ]);
48802
+ deviceKey: string(),
48803
+ modelId: string()
48804
+ }), object({
48805
+ kind: literal("custom-registry-unreadable"),
48806
+ error: string()
48807
+ })]);
48415
48808
  var AutoTuneOptionsSchema = object({
48416
48809
  /** Share of each accelerator's throughput kept free (0.3–0.5). */
48417
48810
  headroom: number().min(.3).max(.5).default(.4),
@@ -48433,8 +48826,6 @@ var AutoTunePlanSchema = object({
48433
48826
  generatedAt: number(),
48434
48827
  nodes: array(NodeRecommendationSchema).readonly(),
48435
48828
  nodeChanges: array(NodeDeviceChangeSchema).readonly(),
48436
- cameraClears: array(CameraOverrideClearSchema).readonly(),
48437
- detectorStoreClears: array(DetectorStoreClearSchema).readonly(),
48438
48829
  warnings: array(AutoTuneWarningSchema).readonly()
48439
48830
  });
48440
48831
  var AutoTuneApplyInputSchema = object({
@@ -48445,8 +48836,6 @@ var AutoTuneApplyInputSchema = object({
48445
48836
  var AutoTunePhaseResultSchema = object({
48446
48837
  phase: _enum([
48447
48838
  "download",
48448
- "camera-overrides",
48449
- "detector-thresholds",
48450
48839
  "node-models",
48451
48840
  "redispatch"
48452
48841
  ]),
@@ -50201,6 +50590,12 @@ var AgentPipelineSettingsSchema = object({
50201
50590
  /** Hub-persisted UI colour (`--color-node-*` theme tokens). */
50202
50591
  color: NodeColorIdSchema.optional(),
50203
50592
  /**
50593
+ * NODE-wide step settings (D927): `stepId → { key → value }`, applied on
50594
+ * every accelerator of the node under the device's own settings. Never a
50595
+ * model or a model-bound threshold. Written by `setNodeStepSettings`.
50596
+ */
50597
+ stepSettings: record(string(), record(string(), unknown()).readonly()).optional(),
50598
+ /**
50204
50599
  * Multi-device inference opt-in (Phase 4). Per-node map deviceKey → {enabled,
50205
50600
  * weight, steps}. Absent / all-disabled ⇒ the node's single default
50206
50601
  * accelerator (safe default); two+ enabled ⇒ the dispatcher balances
@@ -50216,17 +50611,6 @@ var AgentPipelineSettingsSchema = object({
50216
50611
  steps: record(string(), DeviceStepConfigSchema).optional()
50217
50612
  })).optional()
50218
50613
  });
50219
- var CameraPipelineForAgentSchema = object({
50220
- steps: array(PipelineStepInputSchema).readonly(),
50221
- audio: object({
50222
- modelId: string(),
50223
- enabled: boolean()
50224
- }).nullable()
50225
- });
50226
- var CameraStepOverridePatchSchema = object({
50227
- modelId: string().optional(),
50228
- settings: record(string(), unknown()).readonly().optional()
50229
- });
50230
50614
  var CameraStepSettingsSchema = record(string(), record(string(), unknown()).readonly());
50231
50615
  /** The three root-detector choices a camera has (D507: at most one root). */
50232
50616
  var CameraDetectionSourceSchema = _enum([
@@ -50236,9 +50620,7 @@ var CameraDetectionSourceSchema = _enum([
50236
50620
  ]);
50237
50621
  var CameraPipelineSettingsSchema = object({
50238
50622
  stepToggles: record(string(), boolean()).optional(),
50239
- stepSettings: CameraStepSettingsSchema.optional(),
50240
- stepOverridesByDevice: record(string(), record(string(), record(string(), CameraStepOverridePatchSchema))).optional(),
50241
- pipelineByAgent: record(string(), CameraPipelineForAgentSchema).optional()
50623
+ stepSettings: CameraStepSettingsSchema.optional()
50242
50624
  });
50243
50625
  /**
50244
50626
  * Pipeline placement record persisted by `addon-pipeline-orchestrator` via
@@ -50784,6 +51166,13 @@ method(object({
50784
51166
  }), object({ success: literal(true) }), {
50785
51167
  kind: "mutation",
50786
51168
  auth: "admin"
51169
+ }), method(object({
51170
+ agentNodeId: string(),
51171
+ addonId: string(),
51172
+ settings: record(string(), unknown()).nullable()
51173
+ }), object({ success: literal(true) }), {
51174
+ kind: "mutation",
51175
+ auth: "admin"
50787
51176
  }), method(object({ nodeId: string() }), NodeInferenceDevicesSchema), method(object({
50788
51177
  agentNodeId: string(),
50789
51178
  deviceKey: string()
@@ -50793,9 +51182,7 @@ method(object({
50793
51182
  }), method(object({ agentNodeId: string() }), object({
50794
51183
  success: literal(true),
50795
51184
  /** Hardware-aware default detection model now in effect on the node (null when unresolvable). */
50796
- effectiveModelId: string().nullable(),
50797
- /** Number of cameras whose node-scoped overrides were cleared. */
50798
- clearedCameraOverrides: number()
51185
+ effectiveModelId: string().nullable()
50799
51186
  }), {
50800
51187
  kind: "mutation",
50801
51188
  auth: "admin"
@@ -50850,15 +51237,6 @@ method(object({
50850
51237
  }), object({ success: literal(true) }), {
50851
51238
  kind: "mutation",
50852
51239
  auth: "admin"
50853
- }), method(object({ deviceId: number() }), record(string(), record(string(), record(string(), CameraStepOverridePatchSchema))).nullable()), method(object({
50854
- deviceId: number(),
50855
- agentNodeId: string(),
50856
- deviceKey: string(),
50857
- addonId: string(),
50858
- patch: CameraStepOverridePatchSchema.nullable()
50859
- }), object({ success: literal(true) }), {
50860
- kind: "mutation",
50861
- auth: "admin"
50862
51240
  }), method(object({
50863
51241
  deviceId: number(),
50864
51242
  addonId: string(),
@@ -50866,13 +51244,6 @@ method(object({
50866
51244
  }), object({ success: literal(true) }), {
50867
51245
  kind: "mutation",
50868
51246
  auth: "admin"
50869
- }), method(object({
50870
- deviceId: number(),
50871
- agentNodeId: string(),
50872
- pipeline: CameraPipelineForAgentSchema.nullable()
50873
- }), object({ success: literal(true) }), {
50874
- kind: "mutation",
50875
- auth: "admin"
50876
51247
  }), method(object({
50877
51248
  deviceId: number(),
50878
51249
  agentNodeId: string().optional()
@@ -55019,20 +55390,68 @@ var BatteryStatusSchema = object({
55019
55390
  */
55020
55391
  binary: boolean().optional()
55021
55392
  });
55393
+ var BATTERY_DEVICE_TYPES = [
55394
+ DeviceType.Camera,
55395
+ DeviceType.Sensor,
55396
+ DeviceType.Button,
55397
+ DeviceType.Switch,
55398
+ DeviceType.PetFeeder,
55399
+ DeviceType.Container,
55400
+ DeviceType.Thermostat
55401
+ ];
55402
+ /** Generic Customize target for the percentage reading (D936). */
55403
+ var batteryCustomize = {
55404
+ version: 1,
55405
+ targets: [{
55406
+ id: "percentage",
55407
+ cardinality: "scalar",
55408
+ vocabulary: {
55409
+ cap: "battery",
55410
+ stateField: "percentage"
55411
+ },
55412
+ deviceTypes: BATTERY_DEVICE_TYPES,
55413
+ apply: "add-or-replace",
55414
+ path: "percentage",
55415
+ sources: [{
55416
+ kind: "field",
55417
+ valueKinds: ["number", "string"],
55418
+ transforms: [{ kind: "identity" }, {
55419
+ kind: "linear",
55420
+ defaultScale: 1,
55421
+ defaultOffset: 0,
55422
+ clampMin: 0,
55423
+ clampMax: 100
55424
+ }]
55425
+ }],
55426
+ companions: [
55427
+ {
55428
+ kind: "constant",
55429
+ path: "charging",
55430
+ value: "unknown",
55431
+ when: "add"
55432
+ },
55433
+ {
55434
+ kind: "constant",
55435
+ path: "sleeping",
55436
+ value: false,
55437
+ when: "add"
55438
+ },
55439
+ {
55440
+ kind: "clock",
55441
+ path: "lastUpdated",
55442
+ when: "add"
55443
+ }
55444
+ ],
55445
+ sourceReport: { status: "assignment-status" },
55446
+ advancedExpression: true
55447
+ }]
55448
+ };
55022
55449
  var batteryCapability = {
55023
55450
  name: "battery",
55024
55451
  scope: "device",
55025
55452
  deviceNative: true,
55026
55453
  mode: "singleton",
55027
- deviceTypes: [
55028
- DeviceType.Camera,
55029
- DeviceType.Sensor,
55030
- DeviceType.Button,
55031
- DeviceType.Switch,
55032
- DeviceType.PetFeeder,
55033
- DeviceType.Container,
55034
- DeviceType.Thermostat
55035
- ],
55454
+ deviceTypes: BATTERY_DEVICE_TYPES,
55036
55455
  methods: {
55037
55456
  /**
55038
55457
  * Explicitly wake the camera from low-power sleep ahead of a
@@ -55116,6 +55535,7 @@ onStatusChanged: { data: object({
55116
55535
  kind: "gauge",
55117
55536
  unit: "%"
55118
55537
  } } },
55538
+ customize: batteryCustomize,
55119
55539
  /** Clock fields: written, but excluded from the compare that decides
55120
55540
  * whether persisting is worth a SQLite commit. */
55121
55541
  volatileStateFields: ["lastUpdated"]
@@ -56076,6 +56496,106 @@ var ConsumablesStatusSchema = object({
56076
56496
  items: array(ConsumableItemSchema),
56077
56497
  lastChangedAt: number()
56078
56498
  });
56499
+ /** Synthesize seed for a link-built status (no native provider).
56500
+ *
56501
+ * ⚠ NO LIVE CALLER since 2026-08-08 (device-links deleted; see
56502
+ * `CapabilityStatusSchema.empty`). The wiring guidance below was written for
56503
+ * exactly the case the operator is asking about again — a Dreame's HA
56504
+ * consumable-life sensors — so it is kept for that conversation, not because
56505
+ * anything reads it today. */
56506
+ var EMPTY_STATUS = {
56507
+ items: [],
56508
+ lastChangedAt: 0
56509
+ };
56510
+ /** Seed for a NEW link-built consumable item. `key`/`label` are overwritten
56511
+ * with the link's `itemKey` (see `status.itemArray`), so the placeholder
56512
+ * empty strings never survive into a validated item. Link-built items are
56513
+ * not resettable — there is no native provider to receive `reset()`.
56514
+ *
56515
+ * Wiring guidance (HA vacuum consumable-life sensors):
56516
+ * - a percent-remaining source (`numeric-sensor`, unit '%') → `level` via
56517
+ * `identity` (or `linear` scale 1 offset 0 clamp [0,100] to be safe);
56518
+ * - an hours-remaining source (e.g. Dreame 'Main Brush Time Left', unit 'h')
56519
+ * → `level` via `linear` with scale = 100 / max-hours for that item
56520
+ * (e.g. main brush 300 h → scale 0.3333) + clamp [0,100];
56521
+ * - a discrete source (`enum-sensor`, e.g. mop pad 'installed') → `status`
56522
+ * via `enum-map` (e.g. { installed: 'ok', missing: 'replace' }).
56523
+ * A numeric→'replace' THRESHOLD (level < 10 → 'replace') is NOT expressible
56524
+ * with the current transform kinds — leave `status` null (valid) until the
56525
+ * expression transform lands. */
56526
+ /** Generic Customize target for one consumable item (D936). Native rows stay read-only. */
56527
+ var consumablesCustomize = {
56528
+ version: 1,
56529
+ targets: [{
56530
+ id: "items",
56531
+ cardinality: "keyedArray",
56532
+ vocabulary: { cap: "consumables" },
56533
+ deviceTypes: Object.values(DeviceType),
56534
+ apply: "add",
56535
+ path: "items",
56536
+ keyField: "key",
56537
+ labelField: "label",
56538
+ itemSchema: ConsumableItemSchema,
56539
+ nativeItems: "read-only",
56540
+ sourceReport: { status: "assignment-status" },
56541
+ fields: [
56542
+ {
56543
+ path: "level",
56544
+ sources: [{
56545
+ kind: "numeric",
56546
+ transforms: [{ kind: "identity" }, {
56547
+ kind: "linear",
56548
+ defaultScale: 1,
56549
+ defaultOffset: 0,
56550
+ clampMin: 0,
56551
+ clampMax: 100
56552
+ }]
56553
+ }]
56554
+ },
56555
+ {
56556
+ path: "remaining.value",
56557
+ sources: [{
56558
+ kind: "numeric",
56559
+ transforms: [{ kind: "identity" }]
56560
+ }],
56561
+ literals: [{
56562
+ path: "remaining.unit",
56563
+ values: [...ConsumableRemainingUnitSchema.options]
56564
+ }]
56565
+ },
56566
+ {
56567
+ path: "status",
56568
+ sources: [{
56569
+ kind: "enum",
56570
+ transforms: [{
56571
+ kind: "enum-map",
56572
+ outputValues: [...ConsumableStatusSchema.options],
56573
+ unmapped: null
56574
+ }]
56575
+ }]
56576
+ }
56577
+ ],
56578
+ traits: [{
56579
+ path: "kind",
56580
+ values: [...ConsumableKindSchema.options],
56581
+ defaultValue: "wear"
56582
+ }, {
56583
+ path: "form",
56584
+ values: [...ConsumableFormSchema.options],
56585
+ defaultValue: "part"
56586
+ }],
56587
+ companions: [{
56588
+ kind: "clock",
56589
+ path: "lastChangedAt",
56590
+ when: "add"
56591
+ }, {
56592
+ kind: "clock",
56593
+ path: "lastFetchedAt",
56594
+ when: "add"
56595
+ }],
56596
+ advancedExpression: true
56597
+ }]
56598
+ };
56079
56599
  var consumablesCapability = {
56080
56600
  name: "consumables",
56081
56601
  scope: "device",
@@ -56113,10 +56633,7 @@ reset: method(object({
56113
56633
  status: {
56114
56634
  schema: ConsumablesStatusSchema,
56115
56635
  kind: "push",
56116
- empty: {
56117
- items: [],
56118
- lastChangedAt: 0
56119
- },
56636
+ empty: EMPTY_STATUS,
56120
56637
  itemArray: {
56121
56638
  path: "items",
56122
56639
  keyField: "key",
@@ -56152,6 +56669,7 @@ reset: method(object({
56152
56669
  * brush's remaining life and a dishwasher's salt are each recorded the moment
56153
56670
  * their provider reports them; an item that appears later gets its series.
56154
56671
  */
56672
+ customize: consumablesCustomize,
56155
56673
  history: {
56156
56674
  fields: {},
56157
56675
  items: {
@@ -56531,6 +57049,30 @@ var dayNightCapability = {
56531
57049
  volatileStateFields: ["lastFetchedAt"]
56532
57050
  };
56533
57051
  /**
57052
+ * display-palette — the cluster's one colour table (D939).
57053
+ *
57054
+ * Hub singleton. `getPalette` reports `unknown` when the settings store
57055
+ * cannot be read; it does not pretend the bundled preset was stored.
57056
+ * `setPalette` refuses a palette that fails the ΔE / contrast rule and names
57057
+ * the pairs.
57058
+ */
57059
+ var presetSummarySchema = object({
57060
+ id: string(),
57061
+ name: string(),
57062
+ swatches: record(string(), paletteSwatchSchema),
57063
+ fallbacks: array(string())
57064
+ });
57065
+ method(_void(), paletteResultSchema, {
57066
+ auth: "protected",
57067
+ role: "viewer"
57068
+ }), method(_void(), array(presetSummarySchema).readonly(), {
57069
+ auth: "protected",
57070
+ role: "viewer"
57071
+ }), method(setPaletteInputSchema, paletteReadySchema, {
57072
+ kind: "mutation",
57073
+ auth: "admin"
57074
+ });
57075
+ /**
56534
57076
  * Generic device-level status snapshot. Auto-registered by `BaseDevice`
56535
57077
  * for every device, regardless of provider — the kernel needs a uniform
56536
57078
  * cap-keyed slice for the basic device flags every consumer expects to
@@ -56894,6 +57436,36 @@ var dishwasherCapability = {
56894
57436
  powerOn: { kind: "boolean" }
56895
57437
  } }
56896
57438
  };
57439
+ /** Pulse override: a rising edge advances `lastPressedAt` and the press count. */
57440
+ var doorbellCustomize = {
57441
+ version: 1,
57442
+ targets: [{
57443
+ id: "pressed",
57444
+ cardinality: "event",
57445
+ shape: "pulse",
57446
+ vocabulary: {
57447
+ cap: "doorbell",
57448
+ eventName: "onPressed"
57449
+ },
57450
+ deviceTypes: [DeviceType.Camera],
57451
+ apply: "add",
57452
+ applyAuthority: { kind: "composition-claim" },
57453
+ eventName: "onPressed",
57454
+ edges: ["rising"],
57455
+ timestampPath: "lastPressedAt",
57456
+ counterPath: "pressCountSinceStart",
57457
+ highWater: "composer-advance",
57458
+ combine: "any",
57459
+ debounce: {
57460
+ kind: "rising-edge",
57461
+ defaultDebounceMs: 2e3,
57462
+ changedAtRequired: true
57463
+ },
57464
+ sources: [{ kind: "binary" }, { kind: "switch" }],
57465
+ sourceReport: { status: "assignment-status" },
57466
+ advancedExpression: true
57467
+ }]
57468
+ };
56897
57469
  var DoorbellStatusSchema = object({
56898
57470
  /** Ms epoch of the last press. null = never observed since this provider started. */
56899
57471
  lastPressedAt: number().nullable(),
@@ -56960,7 +57532,8 @@ onPressed: {
56960
57532
  /**
56961
57533
  * History (D850): none — `pressCountSinceStart` resets with the addon, so it is not a monotonic meter; presses live in the events ledger.
56962
57534
  */
56963
- history: "none"
57535
+ history: "none",
57536
+ customize: doorbellCustomize
56964
57537
  };
56965
57538
  /**
56966
57539
  * Enum-state sensor — a string value picked from a finite option set.
@@ -59356,6 +59929,38 @@ authKey: string().optional() }), object({
59356
59929
  /** Human-readable error when `ok: false`. */
59357
59930
  error: string().optional()
59358
59931
  }), { kind: "mutation" });
59932
+ /** Span override: start on a rising edge, end on a fall or this timeout. */
59933
+ var motionCustomize = {
59934
+ version: 1,
59935
+ targets: [{
59936
+ id: "detected",
59937
+ cardinality: "event",
59938
+ shape: "span",
59939
+ vocabulary: {
59940
+ cap: "motion",
59941
+ eventName: "onMotionChanged"
59942
+ },
59943
+ deviceTypes: [DeviceType.Camera],
59944
+ apply: "replace",
59945
+ applyAuthority: {
59946
+ kind: "camera-sensors",
59947
+ timeoutField: "motionCooldownMs"
59948
+ },
59949
+ eventName: "onMotionChanged",
59950
+ start: "rising-edge",
59951
+ end: "falling-edge-or-timeout",
59952
+ timeoutMs: 3e4,
59953
+ combine: "any",
59954
+ sourceModes: [
59955
+ "in-addition",
59956
+ "confirm",
59957
+ "replace"
59958
+ ],
59959
+ sources: [{ kind: "binary" }, { kind: "switch" }],
59960
+ sourceReport: { status: "assignment-status" },
59961
+ advancedExpression: false
59962
+ }]
59963
+ };
59359
59964
  var MotionStatusSchema = object({
59360
59965
  detected: boolean(),
59361
59966
  /** Ms epoch of the last detected-true observation. Null if never detected. */
@@ -59495,7 +60100,8 @@ onMotionChanged: { data: MotionOnMotionChangedDataSchema } },
59495
60100
  history: { fields: { detected: {
59496
60101
  kind: "boolean",
59497
60102
  excludeDeviceTypes: [DeviceType.Camera]
59498
- } } }
60103
+ } } },
60104
+ customize: motionCustomize
59499
60105
  };
59500
60106
  /**
59501
60107
  * Motion-trigger toggle for accessory devices.
@@ -61294,6 +61900,30 @@ includeCrops: boolean().optional() }).optional(), array(VehicleSchema).readonly(
61294
61900
  kind: "mutation",
61295
61901
  auth: "admin"
61296
61902
  });
61903
+ var CORE_ULTRA_265K_IGPU_CLOCK_MHZ = 2e3;
61904
+ var positiveOrNull = number().nullable().transform((value) => value !== null && Number.isFinite(value) && value > 0 ? value : null);
61905
+ var textOrNull = string().nullable().transform((value) => value !== null && value.trim() !== "" ? value : null);
61906
+ var PrecisionGopsSchema = object({
61907
+ int8: positiveOrNull,
61908
+ fp16: positiveOrNull
61909
+ });
61910
+ /** What one accelerator device reported. Every failed query is null. */
61911
+ var AcceleratorComputeSchema = object({
61912
+ deviceKey: string(),
61913
+ fullDeviceName: textOrNull,
61914
+ executionUnits: positiveOrNull,
61915
+ clockMHz: positiveOrNull,
61916
+ gops: PrecisionGopsSchema.nullable(),
61917
+ architecture: textOrNull,
61918
+ npuName: textOrNull,
61919
+ tops: positiveOrNull,
61920
+ vendor: textOrNull,
61921
+ webgpuArchitecture: textOrNull,
61922
+ webgpuDevice: textOrNull,
61923
+ computeUnits: positiveOrNull
61924
+ });
61925
+ object({ accelerators: array(AcceleratorComputeSchema).nullable() });
61926
+ 64 * CORE_ULTRA_265K_IGPU_CLOCK_MHZ;
61297
61927
  var ModelFormatSchema = _enum(MODEL_FORMATS);
61298
61928
  var HwAccelBackendInputSchema = _enum([
61299
61929
  "videotoolbox",
@@ -61407,7 +62037,12 @@ var HardwareInfoSchema = object({
61407
62037
  availableRAM_MB: number(),
61408
62038
  gpu: GpuInfoSchema.nullable(),
61409
62039
  npu: NpuInfoSchema.nullable(),
61410
- coral: CoralInfoSchema.nullable().optional()
62040
+ coral: CoralInfoSchema.nullable().optional(),
62041
+ /**
62042
+ * Per-accelerator compute (D930). Omitted by a node that has not probed it.
62043
+ * `null` fields inside an entry are a failed query, never a zero.
62044
+ */
62045
+ accelerators: array(AcceleratorComputeSchema).readonly().optional()
61411
62046
  });
61412
62047
  var PlatformScoreSchema = object({
61413
62048
  runtime: literal("python"),
@@ -62350,6 +62985,125 @@ var ptzAutotrackCapability = {
62350
62985
  */
62351
62986
  history: "none"
62352
62987
  };
62988
+ var RUNNING_POWER_START_DELAY_MS = 3e4;
62989
+ var RUNNING_POWER_STOP_DELAY_MS = 18e4;
62990
+ var RunningStateSourceSchema = _enum(["native", "assigned"]);
62991
+ var RunningStateStatusSchema = object({
62992
+ /** null = unknown — never coerced to false (D393). */
62993
+ running: boolean().nullable(),
62994
+ /** Epoch ms the current boolean began; null while `running` is null. */
62995
+ since: number().nullable(),
62996
+ source: RunningStateSourceSchema,
62997
+ phase: string().nullable(),
62998
+ /** null until a reading has been published (D393). */
62999
+ lastFetchedAt: number().nullable()
63000
+ });
63001
+ var RunningFlipEventDataSchema = object({
63002
+ deviceId: number(),
63003
+ since: number().nullable(),
63004
+ phase: string().nullable()
63005
+ });
63006
+ var RUNNING_DEVICE_TYPES = Object.values(DeviceType);
63007
+ /** Generic Customize target for the running boolean (D936). */
63008
+ var runningCustomize = {
63009
+ version: 1,
63010
+ targets: [{
63011
+ id: "running",
63012
+ cardinality: "scalar",
63013
+ vocabulary: {
63014
+ cap: "running-state",
63015
+ stateField: "running"
63016
+ },
63017
+ deviceTypes: [
63018
+ DeviceType.Dishwasher,
63019
+ DeviceType.Vacuum,
63020
+ DeviceType.LawnMower,
63021
+ DeviceType.MediaPlayer,
63022
+ DeviceType.WaterHeater,
63023
+ DeviceType.Humidifier,
63024
+ DeviceType.Fan,
63025
+ DeviceType.Climate,
63026
+ DeviceType.Thermostat,
63027
+ DeviceType.PetFeeder
63028
+ ],
63029
+ apply: "add-or-replace",
63030
+ path: "running",
63031
+ sources: [
63032
+ {
63033
+ kind: "switch",
63034
+ transforms: [{ kind: "identity" }]
63035
+ },
63036
+ {
63037
+ kind: "binary",
63038
+ transforms: [{ kind: "identity" }, { kind: "invert" }]
63039
+ },
63040
+ {
63041
+ kind: "numeric",
63042
+ requiredUnit: "W",
63043
+ transforms: [{
63044
+ kind: "threshold",
63045
+ comparison: "gte",
63046
+ defaultThreshold: 5,
63047
+ defaultStartDwellMs: RUNNING_POWER_START_DELAY_MS,
63048
+ defaultStopDwellMs: RUNNING_POWER_STOP_DELAY_MS,
63049
+ thresholdUnit: "W"
63050
+ }]
63051
+ }
63052
+ ],
63053
+ companions: [
63054
+ {
63055
+ kind: "constant",
63056
+ path: "source",
63057
+ value: "assigned",
63058
+ when: "always"
63059
+ },
63060
+ {
63061
+ kind: "constant",
63062
+ path: "phase",
63063
+ value: null,
63064
+ when: "always"
63065
+ },
63066
+ {
63067
+ kind: "clock",
63068
+ path: "lastFetchedAt",
63069
+ when: "always"
63070
+ },
63071
+ {
63072
+ kind: "transition-time",
63073
+ path: "since",
63074
+ sourceChangedAt: "prefer"
63075
+ }
63076
+ ],
63077
+ sourceReport: {
63078
+ status: "assignment-status",
63079
+ runtimeField: "source",
63080
+ nativeValue: "native",
63081
+ assignedValue: "assigned"
63082
+ },
63083
+ advancedExpression: true
63084
+ }]
63085
+ };
63086
+ var runningStateCapability = {
63087
+ name: "running-state",
63088
+ scope: "device",
63089
+ deviceNative: true,
63090
+ mode: "singleton",
63091
+ deviceTypes: RUNNING_DEVICE_TYPES,
63092
+ methods: {},
63093
+ events: {
63094
+ onStarted: { data: RunningFlipEventDataSchema },
63095
+ onFinished: { data: RunningFlipEventDataSchema }
63096
+ },
63097
+ status: {
63098
+ schema: RunningStateStatusSchema,
63099
+ kind: "push"
63100
+ },
63101
+ runtimeState: RunningStateStatusSchema,
63102
+ durability: "restored",
63103
+ history: { fields: { running: { kind: "boolean" } } },
63104
+ volatileStateFields: ["lastFetchedAt"],
63105
+ customize: runningCustomize
63106
+ };
62353
63107
  DeviceType.Camera, DeviceType.Sensor, DeviceType.Switch, method(object({ deviceId: number().int().nonnegative() }), object({ success: literal(true) }), {
62354
63108
  kind: "mutation",
62355
63109
  auth: "admin"
@@ -64433,7 +65187,20 @@ var ZoneRuleSchema = object({
64433
65187
  * Defaults to `true` so operators creating a rule via the UI
64434
65188
  * see it active immediately.
64435
65189
  */
64436
- enabled: boolean().default(true)
65190
+ enabled: boolean().default(true),
65191
+ /**
65192
+ * Package stage only. When true, a package candidate may open from a
65193
+ * scene difference in this rule's zone after a person leaves. The
65194
+ * package model, when it boxes something overlapping, is extra evidence
65195
+ * and is not the gate. Absent or false keeps today's model path.
65196
+ */
65197
+ detectBySceneDifference: boolean().optional(),
65198
+ /**
65199
+ * Package stage only. When true, a promoted package is shown to the
65200
+ * `llm` cap before the delivery event is emitted. Absent or false emits
65201
+ * as today. Usable with or without `detectBySceneDifference`.
65202
+ */
65203
+ confirmWithLlm: boolean().optional()
64437
65204
  });
64438
65205
  array(ZoneRuleSchema).readonly();
64439
65206
  /**
@@ -66989,7 +67756,7 @@ method(object({}), array(TrainingProviderDescriptorSchema).readonly(), { auth: "
66989
67756
  * - **Jobs.** A persisted state machine, a reconcile loop against the
66990
67757
  * provider, a cost guard, a daily orphan sweep and the retention rules.
66991
67758
  * - **The return flow.** Verified artefacts → Model Studio
66992
- * (`custom-model-registry.importModelBundle`) → canary on cameras →
67759
+ * (`custom-model-registry.importModelBundle`) → canary on accelerators →
66993
67760
  * rollback. Nothing is ever registered automatically.
66994
67761
  *
66995
67762
  * Plan/start takes a live {@link TrainingCorpusSelection} (collections +
@@ -67126,20 +67893,24 @@ var TrainingProgressPointSchema = object({
67126
67893
  map50: number().nullable(),
67127
67894
  map50_95: number().nullable()
67128
67895
  });
67896
+ /** One accelerator: a `(node, inference device)` that runs the root detector. */
67897
+ var TrainingAcceleratorRefSchema = object({
67898
+ nodeId: string(),
67899
+ deviceKey: string()
67900
+ });
67901
+ /**
67902
+ * A canary pins the registered model on chosen ACCELERATORS — a model is
67903
+ * chosen by the accelerator that runs it (D927); every camera balanced onto
67904
+ * one runs it. `previous` is the root-detector pin each one had (`null` = it
67905
+ * ran its default), exactly, so rollback restores it.
67906
+ */
67129
67907
  var TrainingCanarySchema = object({
67130
- deviceIds: array(number().int()).readonly(),
67908
+ accelerators: array(TrainingAcceleratorRefSchema).readonly(),
67131
67909
  since: number(),
67132
- /** Every override the canary replaced, exactly, so rollback restores it. */
67133
- previous: array(object({
67134
- deviceId: number().int(),
67135
- nodeId: string(),
67136
- deviceKey: string(),
67137
- patch: object({
67138
- modelId: string().optional(),
67139
- settings: record(string(), unknown()).readonly().optional()
67140
- }).nullable()
67141
- })).readonly()
67910
+ previous: array(TrainingAcceleratorRefSchema.extend({ modelId: string().nullable() })).readonly()
67142
67911
  });
67912
+ /** An accelerator a canary may pin: it runs the root detector, on this model now. */
67913
+ var TrainingCanaryTargetSchema = TrainingAcceleratorRefSchema.extend({ pinnedModelId: string().nullable() });
67143
67914
  var TrainingJobSchema = object({
67144
67915
  id: string(),
67145
67916
  idempotencyKey: string(),
@@ -67251,11 +68022,11 @@ method(object({}), array(TrainingBaseModelSchema).readonly(), { auth: "admin" })
67251
68022
  kind: "mutation",
67252
68023
  auth: "admin",
67253
68024
  timeoutMs: 12e4
67254
- }), method(IdInput, TrainingResultSchema.nullable(), { auth: "admin" }), method(IdInput.extend({ canaryDeviceIds: array(number().int()).readonly() }), TrainingJobSchema, {
68025
+ }), method(IdInput, TrainingResultSchema.nullable(), { auth: "admin" }), method(_void(), array(TrainingCanaryTargetSchema).readonly(), { auth: "admin" }), method(IdInput.extend({ canaryAccelerators: array(TrainingAcceleratorRefSchema).readonly() }), TrainingJobSchema, {
67255
68026
  kind: "mutation",
67256
68027
  auth: "admin",
67257
68028
  timeoutMs: 30 * 6e4
67258
- }), method(IdInput.extend({ deviceIds: array(number().int()).min(1).readonly() }), TrainingJobSchema, {
68029
+ }), method(IdInput.extend({ accelerators: array(TrainingAcceleratorRefSchema).min(1).readonly() }), TrainingJobSchema, {
67259
68030
  kind: "mutation",
67260
68031
  auth: "admin",
67261
68032
  timeoutMs: 12e4
@@ -67751,6 +68522,7 @@ var DEVICE_LOCAL_STATE_CAPS = {
67751
68522
  ptzAutotrack: ptzAutotrackCapability,
67752
68523
  recordingOnboard: recordingOnboardCapability,
67753
68524
  recordingSignal: recordingSignalCapability,
68525
+ runningState: runningStateCapability,
67754
68526
  sceneMonitor: sceneMonitorCapability,
67755
68527
  scriptRunner: scriptRunnerCapability,
67756
68528
  smoke: smokeCapability,
@@ -71947,6 +72719,27 @@ Object.freeze({
71947
72719
  access: "create",
71948
72720
  role: "viewer"
71949
72721
  },
72722
+ "displayPalette.getPalette": {
72723
+ capName: "display-palette",
72724
+ capScope: "system",
72725
+ addonId: null,
72726
+ access: "view",
72727
+ role: "viewer"
72728
+ },
72729
+ "displayPalette.listPresets": {
72730
+ capName: "display-palette",
72731
+ capScope: "system",
72732
+ addonId: null,
72733
+ access: "view",
72734
+ role: "viewer"
72735
+ },
72736
+ "displayPalette.setPalette": {
72737
+ capName: "display-palette",
72738
+ capScope: "system",
72739
+ addonId: null,
72740
+ access: "create",
72741
+ role: "admin"
72742
+ },
71950
72743
  "doorbell.getStatus": {
71951
72744
  capName: "doorbell",
71952
72745
  capScope: "device",
@@ -74866,20 +75659,6 @@ Object.freeze({
74866
75659
  access: "create",
74867
75660
  role: "admin"
74868
75661
  },
74869
- "pipelineExecutor.clearDeviceOverrides": {
74870
- capName: "pipeline-executor",
74871
- capScope: "system",
74872
- addonId: null,
74873
- access: "delete",
74874
- role: "admin"
74875
- },
74876
- "pipelineExecutor.clearModelBoundDeviceOverrides": {
74877
- capName: "pipeline-executor",
74878
- capScope: "system",
74879
- addonId: null,
74880
- access: "delete",
74881
- role: "admin"
74882
- },
74883
75662
  "pipelineExecutor.deleteModel": {
74884
75663
  capName: "pipeline-executor",
74885
75664
  capScope: "system",
@@ -74922,13 +75701,6 @@ Object.freeze({
74922
75701
  access: "view",
74923
75702
  role: "admin"
74924
75703
  },
74925
- "pipelineExecutor.getDefaultSteps": {
74926
- capName: "pipeline-executor",
74927
- capScope: "system",
74928
- addonId: null,
74929
- access: "view",
74930
- role: "admin"
74931
- },
74932
75704
  "pipelineExecutor.getDetectionConfigSchema": {
74933
75705
  capName: "pipeline-executor",
74934
75706
  capScope: "system",
@@ -74950,20 +75722,6 @@ Object.freeze({
74950
75722
  access: "view",
74951
75723
  role: "admin"
74952
75724
  },
74953
- "pipelineExecutor.getGlobalPipelineConfig": {
74954
- capName: "pipeline-executor",
74955
- capScope: "system",
74956
- addonId: null,
74957
- access: "view",
74958
- role: "admin"
74959
- },
74960
- "pipelineExecutor.getGlobalSteps": {
74961
- capName: "pipeline-executor",
74962
- capScope: "system",
74963
- addonId: null,
74964
- access: "view",
74965
- role: "admin"
74966
- },
74967
75725
  "pipelineExecutor.getInferenceDeviceHealth": {
74968
75726
  capName: "pipeline-executor",
74969
75727
  capScope: "system",
@@ -75223,13 +75981,6 @@ Object.freeze({
75223
75981
  access: "view",
75224
75982
  role: "admin"
75225
75983
  },
75226
- "pipelineOrchestrator.getCameraStepOverrides": {
75227
- capName: "pipeline-orchestrator",
75228
- capScope: "system",
75229
- addonId: null,
75230
- access: "view",
75231
- role: "admin"
75232
- },
75233
75984
  "pipelineOrchestrator.getCameraSwitches": {
75234
75985
  capName: "pipeline-orchestrator",
75235
75986
  capScope: "system",
@@ -75468,13 +76219,6 @@ Object.freeze({
75468
76219
  access: "create",
75469
76220
  role: "admin"
75470
76221
  },
75471
- "pipelineOrchestrator.setCameraPipelineForAgent": {
75472
- capName: "pipeline-orchestrator",
75473
- capScope: "system",
75474
- addonId: null,
75475
- access: "create",
75476
- role: "admin"
75477
- },
75478
76222
  "pipelineOrchestrator.setCameraSensors": {
75479
76223
  capName: "pipeline-orchestrator",
75480
76224
  capScope: "system",
@@ -75482,42 +76226,42 @@ Object.freeze({
75482
76226
  access: "create",
75483
76227
  role: "admin"
75484
76228
  },
75485
- "pipelineOrchestrator.setCameraStepOverride": {
76229
+ "pipelineOrchestrator.setCameraStepSettings": {
75486
76230
  capName: "pipeline-orchestrator",
75487
76231
  capScope: "system",
75488
76232
  addonId: null,
75489
76233
  access: "create",
75490
76234
  role: "admin"
75491
76235
  },
75492
- "pipelineOrchestrator.setCameraStepSettings": {
76236
+ "pipelineOrchestrator.setCameraStepToggle": {
75493
76237
  capName: "pipeline-orchestrator",
75494
76238
  capScope: "system",
75495
76239
  addonId: null,
75496
76240
  access: "create",
75497
76241
  role: "admin"
75498
76242
  },
75499
- "pipelineOrchestrator.setCameraStepToggle": {
76243
+ "pipelineOrchestrator.setCameraSwitch": {
75500
76244
  capName: "pipeline-orchestrator",
75501
76245
  capScope: "system",
75502
76246
  addonId: null,
75503
76247
  access: "create",
75504
76248
  role: "admin"
75505
76249
  },
75506
- "pipelineOrchestrator.setCameraSwitch": {
76250
+ "pipelineOrchestrator.setCapabilityBinding": {
75507
76251
  capName: "pipeline-orchestrator",
75508
76252
  capScope: "system",
75509
76253
  addonId: null,
75510
76254
  access: "create",
75511
76255
  role: "admin"
75512
76256
  },
75513
- "pipelineOrchestrator.setCapabilityBinding": {
76257
+ "pipelineOrchestrator.setLoadBalancingShares": {
75514
76258
  capName: "pipeline-orchestrator",
75515
76259
  capScope: "system",
75516
76260
  addonId: null,
75517
76261
  access: "create",
75518
76262
  role: "admin"
75519
76263
  },
75520
- "pipelineOrchestrator.setLoadBalancingShares": {
76264
+ "pipelineOrchestrator.setNodeStepSettings": {
75521
76265
  capName: "pipeline-orchestrator",
75522
76266
  capScope: "system",
75523
76267
  addonId: null,
@@ -76546,6 +77290,13 @@ Object.freeze({
76546
77290
  access: "create",
76547
77291
  role: "admin"
76548
77292
  },
77293
+ "runningState.getStatus": {
77294
+ capName: "running-state",
77295
+ capScope: "device",
77296
+ addonId: null,
77297
+ access: "view",
77298
+ role: "viewer"
77299
+ },
76549
77300
  "sceneMonitor.captureReference": {
76550
77301
  capName: "scene-monitor",
76551
77302
  capScope: "device",
@@ -77876,6 +78627,13 @@ Object.freeze({
77876
78627
  access: "view",
77877
78628
  role: "admin"
77878
78629
  },
78630
+ "training.listCanaryTargets": {
78631
+ capName: "training",
78632
+ capScope: "system",
78633
+ addonId: null,
78634
+ access: "view",
78635
+ role: "admin"
78636
+ },
77879
78637
  "training.listJobs": {
77880
78638
  capName: "training",
77881
78639
  capScope: "system",
@@ -81253,6 +82011,32 @@ var APPLIANCE_CAP_VOCABULARY = {
81253
82011
  }],
81254
82012
  events: { onSent: { notOperatorFacing: "a delivery receipt of a send this system made — not a fact about the world" } }
81255
82013
  },
82014
+ "running-state": {
82015
+ scope: "device",
82016
+ noun: t("Running", "In funzione"),
82017
+ state: [{
82018
+ kind: "boolean",
82019
+ field: "running",
82020
+ label: t("Running", "In funzione"),
82021
+ whenTrue: t("When {device} starts", "Quando {device} inizia"),
82022
+ whenFalse: t("When {device} finishes", "Quando {device} finisce"),
82023
+ icon: "play"
82024
+ }],
82025
+ events: {
82026
+ onStarted: {
82027
+ category: EventCategory.RunningStarted,
82028
+ label: t("Started running", "Ha iniziato a funzionare"),
82029
+ phrase: t("When {device} starts running", "Quando {device} inizia a funzionare"),
82030
+ icon: "play"
82031
+ },
82032
+ onFinished: {
82033
+ category: EventCategory.RunningFinished,
82034
+ label: t("Finished", "Ha finito"),
82035
+ phrase: t("When {device} finishes", "Quando {device} finisce"),
82036
+ icon: "square"
82037
+ }
82038
+ }
82039
+ },
81256
82040
  update: {
81257
82041
  scope: "device",
81258
82042
  noun: t("Firmware update", "Aggiornamento firmware"),
@@ -82412,6 +83196,7 @@ var SYSTEM_CAP_VOCABULARY = {
82412
83196
  "device-provider": system(INTERNAL),
82413
83197
  "device-removal-hook": system(INTERNAL),
82414
83198
  "device-state": system("the runtime-state mirror every trigger already reads through"),
83199
+ "display-palette": system("the cluster display palette — one colour table for every client, not a device action"),
82415
83200
  "embedding-encoder": system(ML),
82416
83201
  "face-gallery": system("the face gallery — curated on its own page"),
82417
83202
  "failure-contribution": system(INTERNAL),
@@ -84468,11 +85253,6 @@ Object.freeze({
84468
85253
  form: "single",
84469
85254
  optional: false
84470
85255
  }],
84471
- "pipelineExecutor.clearModelBoundDeviceOverrides": [{
84472
- name: "deviceIds",
84473
- form: "array",
84474
- optional: true
84475
- }],
84476
85256
  "pipelineExecutor.runPipeline": [{
84477
85257
  name: "deviceId",
84478
85258
  form: "single",
@@ -84528,11 +85308,6 @@ Object.freeze({
84528
85308
  form: "array",
84529
85309
  optional: true
84530
85310
  }],
84531
- "pipelineOrchestrator.getCameraStepOverrides": [{
84532
- name: "deviceId",
84533
- form: "single",
84534
- optional: false
84535
- }],
84536
85311
  "pipelineOrchestrator.getCameraSwitches": [{
84537
85312
  name: "deviceId",
84538
85313
  form: "single",
@@ -84573,21 +85348,11 @@ Object.freeze({
84573
85348
  form: "single",
84574
85349
  optional: false
84575
85350
  }],
84576
- "pipelineOrchestrator.setCameraPipelineForAgent": [{
84577
- name: "deviceId",
84578
- form: "single",
84579
- optional: false
84580
- }],
84581
85351
  "pipelineOrchestrator.setCameraSensors": [{
84582
85352
  name: "deviceId",
84583
85353
  form: "single",
84584
85354
  optional: false
84585
85355
  }],
84586
- "pipelineOrchestrator.setCameraStepOverride": [{
84587
- name: "deviceId",
84588
- form: "single",
84589
- optional: false
84590
- }],
84591
85356
  "pipelineOrchestrator.setCameraStepSettings": [{
84592
85357
  name: "deviceId",
84593
85358
  form: "single",
@@ -85019,6 +85784,11 @@ Object.freeze({
85019
85784
  form: "single",
85020
85785
  optional: true
85021
85786
  }],
85787
+ "runningState.getStatus": [{
85788
+ name: "deviceId",
85789
+ form: "single",
85790
+ optional: false
85791
+ }],
85022
85792
  "sceneMonitor.captureReference": [{
85023
85793
  name: "deviceId",
85024
85794
  form: "single",
@@ -85265,11 +86035,6 @@ Object.freeze({
85265
86035
  form: "single",
85266
86036
  optional: false
85267
86037
  }],
85268
- "training.canaryResult": [{
85269
- name: "deviceIds",
85270
- form: "array",
85271
- optional: false
85272
- }],
85273
86038
  "update.getStatus": [{
85274
86039
  name: "deviceId",
85275
86040
  form: "single",
@@ -85522,6 +86287,96 @@ Object.freeze({
85522
86287
  "smtp-provider": "email"
85523
86288
  });
85524
86289
  DeviceType.Camera;
86290
+ 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;
86291
+ /**
86292
+ * A saved Customize assignment (D936). The schema is the type: callers use
86293
+ * `z.infer`, they do not restate the shape.
86294
+ */
86295
+ var OverrideSourceSchema = object({
86296
+ addonId: string().min(1),
86297
+ stableId: string().min(1),
86298
+ cap: string().min(1),
86299
+ fieldPath: string().min(1)
86300
+ });
86301
+ var CustomizeTransformDraftSchema = discriminatedUnion("kind", [
86302
+ object({ kind: literal("identity") }),
86303
+ object({ kind: literal("invert") }),
86304
+ object({
86305
+ kind: literal("threshold"),
86306
+ comparison: _enum(["gte", "lte"]),
86307
+ threshold: number(),
86308
+ startDwellMs: number().nonnegative(),
86309
+ stopDwellMs: number().nonnegative()
86310
+ }),
86311
+ object({
86312
+ kind: literal("linear"),
86313
+ scale: number(),
86314
+ offset: number(),
86315
+ clampMin: number().optional(),
86316
+ clampMax: number().optional()
86317
+ }),
86318
+ object({
86319
+ kind: literal("enum-map"),
86320
+ mapping: record(string(), string().nullable())
86321
+ }),
86322
+ object({ kind: literal("number") })
86323
+ ]);
86324
+ var ScalarOverrideDraftSchema = object({
86325
+ kind: literal("scalar"),
86326
+ cap: string().min(1),
86327
+ targetId: string().min(1),
86328
+ source: OverrideSourceSchema,
86329
+ transform: CustomizeTransformDraftSchema
86330
+ });
86331
+ var KeyedArrayOverrideDraftSchema = object({
86332
+ kind: literal("keyedArray"),
86333
+ cap: string().min(1),
86334
+ targetId: string().min(1),
86335
+ key: string().min(1),
86336
+ label: string().min(1),
86337
+ fieldPath: string().min(1),
86338
+ source: OverrideSourceSchema,
86339
+ transform: CustomizeTransformDraftSchema
86340
+ });
86341
+ var PulseOverrideDraftSchema = object({
86342
+ kind: literal("pulse"),
86343
+ cap: string().min(1),
86344
+ targetId: string().min(1),
86345
+ enabled: boolean(),
86346
+ debounceMs: number().nonnegative(),
86347
+ sources: array(OverrideSourceSchema).min(1)
86348
+ });
86349
+ var SpanSourceDraftSchema = OverrideSourceSchema.extend({ mode: _enum([
86350
+ "in-addition",
86351
+ "confirm",
86352
+ "replace"
86353
+ ]).optional() });
86354
+ discriminatedUnion("kind", [
86355
+ ScalarOverrideDraftSchema,
86356
+ KeyedArrayOverrideDraftSchema,
86357
+ PulseOverrideDraftSchema,
86358
+ object({
86359
+ kind: literal("span"),
86360
+ cap: string().min(1),
86361
+ targetId: string().min(1),
86362
+ timeoutMs: number().nonnegative(),
86363
+ cooldownMs: number().nonnegative().optional(),
86364
+ sources: array(SpanSourceDraftSchema)
86365
+ })
86366
+ ]);
86367
+ object({
86368
+ targetId: string().min(1),
86369
+ configured: boolean(),
86370
+ source: _enum(["native", "assigned"]),
86371
+ state: _enum([
86372
+ "active",
86373
+ "stale",
86374
+ "released",
86375
+ "unavailable"
86376
+ ]),
86377
+ reason: string().nullable()
86378
+ });
86379
+ String.raw`rose\(active(\d+), changed(\d+), (\d+(?:\.\d+)?)\)`;
85525
86380
  var G711_SCALE_CORRECTION_DB = {
85526
86381
  PCMU: 20 * Math.log10(4),
85527
86382
  PCMA: 20 * Math.log10(8)
@@ -85574,40 +86429,7 @@ var NC_AUDIO_DEFAULTS = {
85574
86429
  samplingSeconds: 10
85575
86430
  };
85576
86431
  new Set(["devices", "classes"]);
85577
- /**
85578
- * WHICH narrowing filter speaks about WHICH system-event kind — one predicate,
85579
- * consumed by the rule ENGINE and by every rule EDITOR.
85580
- *
85581
- * ── The failure this file exists for ───────────────────────────────────────
85582
- * `NcSystemEventConditionSchema` carries four optional narrowing lists
85583
- * (`deviceIds`, `deviceTypes`, `nodeIds`, `packageNames`) beside a required
85584
- * `kinds` gate. They are not four filters over one vocabulary: each belongs to
85585
- * a FAMILY of kinds and is meaningless outside it. A node going away has no
85586
- * device type; a completed export has no package; `stream-offline` deliberately
85587
- * carries no device type at all (a stream belongs to a camera by construction).
85588
- *
85589
- * The engine applied all four to every kind, so a filter from one family failed
85590
- * a kind from another family CLOSED. The operator's live rule "Eventi di
85591
- * sistema" selected eleven kinds and set `deviceTypes: ['camera']` — the only
85592
- * way to say "only my cameras" about the two liveness kinds — and NINE of the
85593
- * eleven silently stopped being deliverable. Four days of history contained
85594
- * `device-online` and `device-offline` and nothing else, across a window in
85595
- * which agents were restarted and addons were updated.
85596
- *
85597
- * Both editors already computed this scoping, to decide which filter boxes to
85598
- * render; the cap's own docblock already promised it ("Narrow a `device-*` kind
85599
- * to these device TYPES"). Only the engine disagreed, and it disagreed in the
85600
- * destructive direction. So the rule is stated ONCE, here, and the engine and
85601
- * the editors are readers of it rather than three independent authors.
85602
- *
85603
- * ── The direction ─────────────────────────────────────────────────────────
85604
- * Out of family ⇒ the filter is IGNORED, never fail-closed. An editor that
85605
- * hides a box has already told the operator this filter does not speak about
85606
- * these kinds, so honouring it as an exclusion contradicts the only
85607
- * explanation the operator was ever given. Inside its family the filter still
85608
- * narrows, and still fails CLOSED on a subject that cannot produce the identity
85609
- * it tests (a device the mirror cannot name is not evidence of a camera).
85610
- */
86432
+ new Set(NC_LEGACY_SYSTEM_EVENT_KINDS);
85611
86433
  /**
85612
86434
  * Every filter, for the callers that must cover all of them (guards, tests).
85613
86435
  *
@@ -85633,9 +86455,6 @@ new Map(Object.entries({
85633
86455
  "device-battery-normal": "device-events",
85634
86456
  "device-consumable-low": "device-events",
85635
86457
  "device-consumable-normal": "device-events",
85636
- "device-tank-low": "device-events",
85637
- "device-tank-full": "device-events",
85638
- "device-tank-normal": "device-events",
85639
86458
  "stream-online": "device-events",
85640
86459
  "stream-offline": "device-events",
85641
86460
  "detection-blind": "device-events",
@@ -85712,16 +86531,6 @@ var NC_SYSTEM_EVENT_KIND_GROUP_SPECS = [
85712
86531
  label: "Consumables",
85713
86532
  kinds: ["device-consumable-low", "device-consumable-normal"]
85714
86533
  },
85715
- {
85716
- id: "tanks",
85717
- family: "device-events",
85718
- label: "Tanks",
85719
- kinds: [
85720
- "device-tank-low",
85721
- "device-tank-full",
85722
- "device-tank-normal"
85723
- ]
85724
- },
85725
86534
  {
85726
86535
  id: "detection-blind",
85727
86536
  family: "device-events",
@@ -85879,11 +86688,6 @@ var RULE_BODY_ONLY = ["body"];
85879
86688
  var RULE_TEXT = ["title", "body"];
85880
86689
  var BATTERY = ["device-battery-low", "device-battery-normal"];
85881
86690
  var CONSUMABLE = ["device-consumable-low", "device-consumable-normal"];
85882
- var TANK = [
85883
- "device-tank-low",
85884
- "device-tank-full",
85885
- "device-tank-normal"
85886
- ];
85887
86691
  var ALERT_EPISODE = [
85888
86692
  "alert-critical",
85889
86693
  "alert-error",
@@ -85915,7 +86719,6 @@ var DEVICE_EVENTS = [
85915
86719
  "device-enabled",
85916
86720
  ...BATTERY,
85917
86721
  ...CONSUMABLE,
85918
- ...TANK,
85919
86722
  "stream-online",
85920
86723
  "stream-offline",
85921
86724
  "detection-blind",
@@ -85961,12 +86764,6 @@ var STATE_SUMMARY_SECTION_VARS = [
85961
86764
  example: "Robot — filter 10 %",
85962
86765
  kinds: CONSUMABLE
85963
86766
  },
85964
- {
85965
- name: "summaryTanks",
85966
- label: "Summary: tanks",
85967
- example: "Robot — clean water low",
85968
- kinds: TANK
85969
- },
85970
86767
  {
85971
86768
  name: "summaryDetection",
85972
86769
  label: "Summary: cameras detecting nothing",
@@ -86082,8 +86879,7 @@ var STATE_SUMMARY_VARS = [
86082
86879
  ([...RULE_TEXT], [...COMBINED_ALARM]),
86083
86880
  ([...RULE_TEXT], [...DEVICE_EVENTS]),
86084
86881
  ([...RULE_TEXT], [...BATTERY, ...CONSUMABLE]),
86085
- ([...RULE_TEXT], [...CONSUMABLE, ...TANK]),
86086
- ([...RULE_TEXT], [...TANK]),
86882
+ ([...RULE_TEXT], [...CONSUMABLE]),
86087
86883
  [...RULE_TEXT],
86088
86884
  ([...RULE_TEXT], [...UPDATES, ...ALERT_EPISODE]),
86089
86885
  ([...RULE_TEXT], [...UPDATES, ...ALERT_EPISODE]),
@@ -86187,15 +86983,6 @@ new Map([
86187
86983
  snapshotLabel: "Consumables low now",
86188
86984
  snapshotSection: "consumables"
86189
86985
  },
86190
- {
86191
- id: "tanks",
86192
- family: "device-events",
86193
- label: "Tanks (low or full / back to normal)",
86194
- bad: ["device-tank-low", "device-tank-full"],
86195
- recovery: ["device-tank-normal"],
86196
- snapshotLabel: "Tanks low or full now",
86197
- snapshotSection: "tanks"
86198
- },
86199
86986
  {
86200
86987
  id: "motion-noise",
86201
86988
  family: "device-events",
@@ -86648,6 +87435,10 @@ MotionOnMotionChangedDataSchema.omit({ triggeredBy: true });
86648
87435
  function providerMotionEvent(source, data) {
86649
87436
  return createEvent(EventCategory.ProviderMotion, source, data);
86650
87437
  }
87438
+ Object.freeze({
87439
+ person: .8,
87440
+ vehicle: .8
87441
+ });
86651
87442
  object({
86652
87443
  /**
86653
87444
  * Fraction of the box's own size added on EACH side before cutting.