@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.mjs CHANGED
@@ -14,7 +14,7 @@ import { networkInterfaces } from "node:os";
14
14
  var __commonJSMin = (cb, mod) => () => (mod || (cb((mod = { exports: {} }).exports, mod), cb = null), mod.exports);
15
15
  var __require = /* @__PURE__ */ createRequire(import.meta.url);
16
16
  //#endregion
17
- //#region ../types/dist/event-category-BfJwUd2S.mjs
17
+ //#region ../types/dist/event-category-Ceif8n-v.mjs
18
18
  var EventCategory = /* @__PURE__ */ function(EventCategory) {
19
19
  EventCategory["SystemBoot"] = "system.boot";
20
20
  EventCategory["SystemAddonsReady"] = "system.addons-ready";
@@ -341,9 +341,8 @@ var EventCategory = /* @__PURE__ */ function(EventCategory) {
341
341
  EventCategory["PipelineMotionCalm"] = "pipeline.motion-calm";
342
342
  /**
343
343
  * Per-camera pipeline config was mutated by the orchestrator
344
- * (3-level settings change via `setAgentAddonDefaults` /
345
- * `setCameraStepToggle` / `setCameraPipelineForAgent` or a
346
- * pipeline-scoped `applyDeviceSettingsPatch`). Orchestrator
344
+ * (a settings change via `setAgentInferenceDevices` /
345
+ * `setCameraStepToggle` / `setCameraStepSettings`). Orchestrator
347
346
  * subscribes to its own emission to hot-reload the assigned runner
348
347
  * via `attachCamera` so the next frame executes against the new
349
348
  * engine/steps without waiting for a rebalance or the next
@@ -487,6 +486,10 @@ var EventCategory = /* @__PURE__ */ function(EventCategory) {
487
486
  * on the device detail page.
488
487
  */
489
488
  EventCategory["DoorbellOnPressed"] = "doorbell.onPressed";
489
+ /** Mirrors `runningStateCapability.events.onStarted`. */
490
+ EventCategory["RunningStarted"] = "running.started";
491
+ /** Mirrors `runningStateCapability.events.onFinished`. */
492
+ EventCategory["RunningFinished"] = "running.finished";
490
493
  /**
491
494
  * Cap event fired by every device that registers the `event-emitter`
492
495
  * capability. Mirrors `eventEmitterCapability.events.onEvent`. Carries
@@ -5446,7 +5449,7 @@ var ZodIssueCode = {
5446
5449
  var ZodFirstPartyTypeKind;
5447
5450
  ZodFirstPartyTypeKind || (ZodFirstPartyTypeKind = {});
5448
5451
  //#endregion
5449
- //#region ../types/dist/sleep-6AqUnQIT.mjs
5452
+ //#region ../types/dist/sleep-CYfIZzGv.mjs
5450
5453
  /**
5451
5454
  * The audio chunk plane's byte format, and the ONE expansion from a coded
5452
5455
  * window to float samples (D455).
@@ -5785,7 +5788,7 @@ Object.fromEntries([
5785
5788
  * `hydrateSchema` to skip the `value` injection for structural-only fields.
5786
5789
  */
5787
5790
  function isValuelessField(field) {
5788
- return field.type === "separator" || field.type === "info" || field.type === "qr-code" || field.type === "button" || field.type === "object-array" || field.type === "widget" || field.type === "addon-action-button" || field.type === "device-action-button";
5791
+ return field.type === "separator" || field.type === "info" || field.type === "qr-code" || field.type === "button" || field.type === "object-array" || field.type === "widget" || field.type === "addon-action-button" || field.type === "device-action-button" || field.type === "account-sign-in" || field.type === "secret-presence";
5789
5792
  }
5790
5793
  function hydrateSchema(schema, values, options = {}) {
5791
5794
  return {
@@ -8831,7 +8834,7 @@ var DeviceRole = /* @__PURE__ */ function(DeviceRole) {
8831
8834
  return DeviceRole;
8832
8835
  }({});
8833
8836
  //#endregion
8834
- //#region ../types/dist/composition-CB6PMT9p.mjs
8837
+ //#region ../types/dist/composition-BJ8iAZb3.mjs
8835
8838
  /**
8836
8839
  * The ffmpeg build every CamStack node downloads, per platform and arch.
8837
8840
  *
@@ -8891,7 +8894,7 @@ portable("linux64"), portable("linuxarm64"), portable("macarm64"), portable("mac
8891
8894
  * ONE table for everyone who asks "is this device HIGH?": the
8892
8895
  * recorder's `RecordingTriggers.sensorDeviceIds` trigger, the post-analysis
8893
8896
  * sensor markers, the orchestrator's camera-sensors bridge and
8894
- * the sources of a composite doorbell (`doorbellFeatureSources`, D671).
8897
+ * the sources of a pulse (`compilePulseOverride`, D936).
8895
8898
  * A second copy would diverge at the first cap added, and the symptom — "the
8896
8899
  * sensor rings the doorbell but does not record" — is exactly D62.
8897
8900
  *
@@ -9132,6 +9135,20 @@ var table = {
9132
9135
  apply: () => {
9133
9136
  throw new ExpressionEvalError("count: stateful evaluation context is required");
9134
9137
  }
9138
+ },
9139
+ dwell: {
9140
+ minArgs: 3,
9141
+ maxArgs: 3,
9142
+ apply: () => {
9143
+ throw new ExpressionEvalError("dwell: stateful evaluation context is required");
9144
+ }
9145
+ },
9146
+ latchedAt: {
9147
+ minArgs: 1,
9148
+ maxArgs: 1,
9149
+ apply: () => {
9150
+ throw new ExpressionEvalError("latchedAt: stateful evaluation context is required");
9151
+ }
9135
9152
  }
9136
9153
  };
9137
9154
  Object.freeze(Object.assign(Object.create(null), table));
@@ -10571,13 +10588,22 @@ var BirthDecisionRecordSchema = object({
10571
10588
  decidedByBirthEvidence: boolean(),
10572
10589
  /** Best class-compatible crop score, or `null` when nothing compatible was
10573
10590
  * found — deliberately not 0, which would be a measurement that never was.
10574
- * Includes a box the detector's own per-class floor refused (reason
10575
- * `below-detector-floor`, D922): that box never confirms, but it is the
10576
- * score the crop really held. */
10591
+ * Includes a box the detector's own per-class floor refused (D922): since
10592
+ * D925 the gate's bar, not that floor, decides whether it confirms. */
10577
10593
  bestScore: number().nullable(),
10578
10594
  /** The bar this candidate actually faced (the phantom-cell hook may raise it). */
10579
10595
  appliedMinConfidence: number().nullable(),
10580
10596
  /**
10597
+ * The detector the gate re-judged the birth WITH (D925): the session's own
10598
+ * root model, inference-device pool and node — never a node default. `null`
10599
+ * when the frame named no session detector or no gate ran, and on rows
10600
+ * written before D925. A `session-device-unavailable` row names the session
10601
+ * detector that could not be reached.
10602
+ */
10603
+ detectorModelId: string().nullable().default(null),
10604
+ detectorDeviceKey: string().nullable().default(null),
10605
+ detectorNodeId: string().nullable().default(null),
10606
+ /**
10581
10607
  * The track's own `firstSeen` — the candidate's first frame, which is where
10582
10608
  * the timeline starts. `null` for a suppressed birth, which has no track.
10583
10609
  */
@@ -16046,6 +16072,13 @@ var ComposerUnreadableBlockSchema = object({
16046
16072
  /** The parse error, in the operator's words. */
16047
16073
  error: string()
16048
16074
  });
16075
+ /** A confirmed release the hub did not accept. `deviceId` is the claim's device. */
16076
+ var UnreleasedClaimSchema = object({
16077
+ deviceId: number().int(),
16078
+ capName: string(),
16079
+ owner: string(),
16080
+ error: string()
16081
+ });
16049
16082
  method(object({
16050
16083
  /** The shared Blocks integration; null until `core-blocks` has reconciled it. */
16051
16084
  integrationId: string().nullable(),
@@ -16055,7 +16088,13 @@ method(object({
16055
16088
  /** Operator restarts: rebuild these runtimes and re-resolve their sources. Stores nothing (D62). */
16056
16089
  restartBlockIds: array(string()),
16057
16090
  /** Composition rows that exist but do not parse: held, never withdrawn, reported failed. */
16058
- unreadableBlocks: array(ComposerUnreadableBlockSchema)
16091
+ unreadableBlocks: array(ComposerUnreadableBlockSchema),
16092
+ /**
16093
+ * Operator-confirmed deletions. Their claims are released on this apply,
16094
+ * before any replacement block claims. A block that merely vanished from the
16095
+ * snapshot is not listed here and still waits for two applies (D49).
16096
+ */
16097
+ retiredBlockIds: array(string()).optional()
16059
16098
  }), object({
16060
16099
  blocks: array(object({
16061
16100
  blockId: string(),
@@ -16067,7 +16106,13 @@ method(object({
16067
16106
  * integration unknown, its own rows unread or read empty once). An empty
16068
16107
  * apply the caller owes is paid off only by one the composer acted on (D49).
16069
16108
  */
16070
- acted: boolean()
16109
+ acted: boolean(),
16110
+ /**
16111
+ * Confirmed releases this apply tried and the hub did not accept. Empty when
16112
+ * every one landed (or there was nothing to hand back). Absent on a result
16113
+ * that never got that far.
16114
+ */
16115
+ unreleasedClaims: array(UnreleasedClaimSchema).optional()
16071
16116
  }), {
16072
16117
  kind: "mutation",
16073
16118
  auth: "admin"
@@ -16110,7 +16155,15 @@ Object.freeze({
16110
16155
  kind: "fixed",
16111
16156
  result: ["number", "null"]
16112
16157
  },
16113
- count: NUMBER
16158
+ count: NUMBER,
16159
+ dwell: {
16160
+ kind: "fixed",
16161
+ result: ["boolean", "null"]
16162
+ },
16163
+ latchedAt: {
16164
+ kind: "fixed",
16165
+ result: ["number", "null"]
16166
+ }
16114
16167
  });
16115
16168
  `${COMPOSED_DEVICE_STABLE_ID_PREFIX}`;
16116
16169
  /**
@@ -42227,6 +42280,381 @@ var _macroLookup = /* @__PURE__ */ new Map();
42227
42280
  for (const [k, v] of Object.entries(YAMNET_TO_MACRO.mapping)) _macroLookup.set(k.toLowerCase(), v);
42228
42281
  for (const [k, v] of Object.entries(APPLE_SA_TO_MACRO.mapping)) _macroLookup.set(k.toLowerCase(), v);
42229
42282
  /**
42283
+ * Palette entry ids (D939). Audio is the one gradient; `audio-*` leaves are
42284
+ * not entries. `heatmapScrub` is a mark, not an event kind.
42285
+ */
42286
+ var PALETTE_ENTRY_IDS = [
42287
+ "motion",
42288
+ "audio",
42289
+ "recording",
42290
+ "live",
42291
+ "heatmapScrub",
42292
+ "person",
42293
+ "vehicle",
42294
+ "animal",
42295
+ "package",
42296
+ "sensor",
42297
+ "control",
42298
+ "face",
42299
+ "plate",
42300
+ "car",
42301
+ "truck",
42302
+ "bus",
42303
+ "motorcycle",
42304
+ "bicycle",
42305
+ "airplane",
42306
+ "boat",
42307
+ "train",
42308
+ "bird",
42309
+ "dog",
42310
+ "cat",
42311
+ "horse",
42312
+ "sheep",
42313
+ "cow",
42314
+ "elephant",
42315
+ "bear",
42316
+ "zebra",
42317
+ "giraffe",
42318
+ "package-delivered",
42319
+ "package-picked-up",
42320
+ "suitcase",
42321
+ "backpack",
42322
+ "handbag",
42323
+ "contact",
42324
+ "motion-sensor",
42325
+ "smoke",
42326
+ "flood",
42327
+ "gas",
42328
+ "carbon-monoxide",
42329
+ "vibration",
42330
+ "tamper",
42331
+ "presence",
42332
+ "enum-sensor",
42333
+ "device-event",
42334
+ "lock",
42335
+ "cover",
42336
+ "switch",
42337
+ "siren",
42338
+ "button",
42339
+ "doorbell"
42340
+ ];
42341
+ var AUDIO_ENTRY_ID = "audio";
42342
+ /** Six rungs, quiet → loud. The opaque end is the entry's hex. */
42343
+ var AUDIO_GRADIENT_ALPHAS = [
42344
+ .3,
42345
+ .42,
42346
+ .55,
42347
+ .7,
42348
+ .85,
42349
+ 1
42350
+ ];
42351
+ var PALETTE_PRESET_IDS = [
42352
+ "camstack",
42353
+ "high-contrast",
42354
+ "okabe-ito"
42355
+ ];
42356
+ /** Frozen palette tables (D939). The spec refuses a table that breaks the rule. */
42357
+ var CAMSTACK_HEX = {
42358
+ motion: "#d946ef",
42359
+ audio: "#059eb8",
42360
+ recording: "#ef4444",
42361
+ live: "#8d7a00",
42362
+ heatmapScrub: "#4b32ff",
42363
+ person: "#11a64c",
42364
+ vehicle: "#3b82f6",
42365
+ animal: "#ea6a09",
42366
+ package: "#924667",
42367
+ sensor: "#624bbc",
42368
+ control: "#944d24",
42369
+ face: "#ed4f8d",
42370
+ plate: "#4b7027",
42371
+ car: "#9684cf",
42372
+ truck: "#0f9b89",
42373
+ bus: "#a734a9",
42374
+ motorcycle: "#c1133a",
42375
+ bicycle: "#0e6a9b",
42376
+ airplane: "#7c9928",
42377
+ boat: "#b17933",
42378
+ train: "#ad6ca3",
42379
+ bird: "#0f7c55",
42380
+ dog: "#c82700",
42381
+ cat: "#7268f2",
42382
+ horse: "#cb795e",
42383
+ sheep: "#b8636b",
42384
+ cow: "#cb2969",
42385
+ elephant: "#1158d2",
42386
+ bear: "#8d5e00",
42387
+ zebra: "#0097d6",
42388
+ giraffe: "#8f61bb",
42389
+ "package-delivered": "#cd3f9b",
42390
+ "package-picked-up": "#388a08",
42391
+ suitcase: "#666800",
42392
+ backpack: "#ec5022",
42393
+ handbag: "#a76ef8",
42394
+ contact: "#ab5a49",
42395
+ "motion-sensor": "#b95d1a",
42396
+ smoke: "#dd3858",
42397
+ flood: "#b31e7d",
42398
+ gas: "#5b70b5",
42399
+ "carbon-monoxide": "#7b4e8e",
42400
+ vibration: "#e65bba",
42401
+ tamper: "#98464b",
42402
+ presence: "#3a9468",
42403
+ "enum-sensor": "#7885f8",
42404
+ "device-event": "#8c43c8",
42405
+ lock: "#649653",
42406
+ cover: "#c67597",
42407
+ switch: "#7a812a",
42408
+ siren: "#ac5d7f",
42409
+ button: "#b276cd",
42410
+ doorbell: "#0087ab"
42411
+ };
42412
+ var CAMSTACK_FALLBACK = [
42413
+ "#b34dc7",
42414
+ "#1d7d34",
42415
+ "#db6b6c",
42416
+ "#a43d29",
42417
+ "#0e6ee6",
42418
+ "#29a10b",
42419
+ "#a98731",
42420
+ "#0181c6"
42421
+ ];
42422
+ var HIGH_CONTRAST_HEX = {
42423
+ motion: "#964360",
42424
+ audio: "#23a132",
42425
+ recording: "#2494ca",
42426
+ live: "#bd7e2b",
42427
+ heatmapScrub: "#ad6eea",
42428
+ person: "#62611e",
42429
+ vehicle: "#f4534c",
42430
+ animal: "#1556cd",
42431
+ package: "#9c4415",
42432
+ sensor: "#066c48",
42433
+ control: "#f2479f",
42434
+ face: "#139d8a",
42435
+ plate: "#909024",
42436
+ car: "#8e35ab",
42437
+ truck: "#bd0b2b",
42438
+ bus: "#7a88ca",
42439
+ motorcycle: "#e26725",
42440
+ bicycle: "#a6679b",
42441
+ airplane: "#7c5720",
42442
+ boat: "#467a1b",
42443
+ train: "#6f65a4",
42444
+ bird: "#cb717f",
42445
+ dog: "#c62490",
42446
+ cat: "#b36850",
42447
+ horse: "#1872ac",
42448
+ sheep: "#927939",
42449
+ cow: "#428a5c",
42450
+ elephant: "#d41160",
42451
+ bear: "#799453",
42452
+ zebra: "#a85455",
42453
+ giraffe: "#746be8",
42454
+ "package-delivered": "#824a80",
42455
+ "package-picked-up": "#614ac1",
42456
+ suitcase: "#2f77f3",
42457
+ backpack: "#fa476d",
42458
+ handbag: "#c14cbe",
42459
+ contact: "#c83921",
42460
+ "motion-sensor": "#a07ebd",
42461
+ smoke: "#a25b13",
42462
+ flood: "#526bab",
42463
+ gas: "#924938",
42464
+ "carbon-monoxide": "#bb7e53",
42465
+ vibration: "#b66182",
42466
+ tamper: "#3c6931",
42467
+ presence: "#6c851d",
42468
+ "enum-sensor": "#ad2d48",
42469
+ "device-event": "#5e9b04",
42470
+ lock: "#00a062",
42471
+ cover: "#ad8624",
42472
+ switch: "#d05259",
42473
+ siren: "#cd67b3",
42474
+ button: "#c9746a",
42475
+ doorbell: "#338eeb"
42476
+ };
42477
+ var HIGH_CONTRAST_FALLBACK = [
42478
+ "#817f3b",
42479
+ "#a0733e",
42480
+ "#8658b2",
42481
+ "#956301",
42482
+ "#bc652d",
42483
+ "#647331",
42484
+ "#a14c9e",
42485
+ "#d14e71"
42486
+ ];
42487
+ var OKABE_ITO_HEX = {
42488
+ motion: "#b88128",
42489
+ audio: "#1096c8",
42490
+ recording: "#009e73",
42491
+ live: "#9c8c22",
42492
+ heatmapScrub: "#0072b2",
42493
+ person: "#d55e00",
42494
+ vehicle: "#c0739f",
42495
+ animal: "#226d18",
42496
+ package: "#91446c",
42497
+ sensor: "#217b56",
42498
+ control: "#648647",
42499
+ face: "#c22998",
42500
+ plate: "#fa4575",
42501
+ car: "#956301",
42502
+ truck: "#2f77f3",
42503
+ bus: "#7a4e86",
42504
+ motorcycle: "#f54597",
42505
+ bicycle: "#bb3e75",
42506
+ airplane: "#e054c0",
42507
+ boat: "#457942",
42508
+ train: "#867afa",
42509
+ bird: "#88914c",
42510
+ dog: "#1556cd",
42511
+ cat: "#71702c",
42512
+ horse: "#9b4fa4",
42513
+ sheep: "#c0559d",
42514
+ cow: "#d14f65",
42515
+ elephant: "#98470f",
42516
+ bear: "#595896",
42517
+ zebra: "#96790e",
42518
+ giraffe: "#cb717b",
42519
+ "package-delivered": "#139d8a",
42520
+ "package-picked-up": "#906ead",
42521
+ suitcase: "#d02939",
42522
+ backpack: "#d41160",
42523
+ handbag: "#f64f54",
42524
+ contact: "#7258d2",
42525
+ "motion-sensor": "#b66182",
42526
+ smoke: "#627abb",
42527
+ flood: "#b86ae4",
42528
+ gas: "#a95261",
42529
+ "carbon-monoxide": "#c65d3c",
42530
+ vibration: "#7a40b7",
42531
+ tamper: "#914b34",
42532
+ presence: "#9481c3",
42533
+ "enum-sensor": "#ac6d47",
42534
+ "device-event": "#7b6fce",
42535
+ lock: "#c67662",
42536
+ cover: "#a6564d",
42537
+ switch: "#ad2c4e",
42538
+ siren: "#348e08",
42539
+ button: "#d27303",
42540
+ doorbell: "#55770f"
42541
+ };
42542
+ var OKABE_ITO_FALLBACK = [
42543
+ "#9a3784",
42544
+ "#a7392c",
42545
+ "#409d50",
42546
+ "#6987e7",
42547
+ "#ee5b3d",
42548
+ "#c0430d",
42549
+ "#af79b3",
42550
+ "#4b6628"
42551
+ ];
42552
+ /**
42553
+ * The display palette (D939). One table of colours, three presets, one
42554
+ * validator. Taxonomy colours and every consumer read this — there is no
42555
+ * second hex table.
42556
+ */
42557
+ var paletteHexSchema = string().regex(/^#[0-9a-f]{6}$/);
42558
+ var paletteSwatchSchema = discriminatedUnion("form", [object({
42559
+ form: literal("solid"),
42560
+ hex: paletteHexSchema
42561
+ }), object({
42562
+ form: literal("gradient"),
42563
+ hex: paletteHexSchema,
42564
+ alphas: array(number().gt(0).lte(1)).length(AUDIO_GRADIENT_ALPHAS.length)
42565
+ })]);
42566
+ var paletteReadySchema = object({
42567
+ status: literal("ready"),
42568
+ presetId: _enum(PALETTE_PRESET_IDS),
42569
+ customized: boolean(),
42570
+ source: _enum(["stored", "unconfigured"]),
42571
+ swatches: record(string(), paletteSwatchSchema),
42572
+ fallbacks: array(paletteHexSchema).length(8)
42573
+ });
42574
+ var paletteResultSchema = discriminatedUnion("status", [paletteReadySchema, object({
42575
+ status: literal("unknown"),
42576
+ reason: string()
42577
+ })]);
42578
+ var setPaletteInputSchema = union([object({ presetId: string() }), object({
42579
+ presetId: string(),
42580
+ overrides: record(string(), paletteSwatchSchema)
42581
+ })]);
42582
+ object({
42583
+ presetId: string(),
42584
+ overrides: record(string(), paletteSwatchSchema)
42585
+ });
42586
+ function solid(hex) {
42587
+ return {
42588
+ form: "solid",
42589
+ hex
42590
+ };
42591
+ }
42592
+ function audioGradient(hex) {
42593
+ return {
42594
+ form: "gradient",
42595
+ hex,
42596
+ alphas: [...AUDIO_GRADIENT_ALPHAS]
42597
+ };
42598
+ }
42599
+ function swatchesFrom(hexes) {
42600
+ const out = {};
42601
+ for (const id of PALETTE_ENTRY_IDS) {
42602
+ const hex = hexes[id];
42603
+ if (hex === void 0) throw new Error(`palette table missing ${id}`);
42604
+ out[id] = id === "audio" ? audioGradient(hex) : solid(hex);
42605
+ }
42606
+ return out;
42607
+ }
42608
+ function preset(id, name, hexes, fallbacks) {
42609
+ return {
42610
+ id,
42611
+ name,
42612
+ swatches: swatchesFrom(hexes),
42613
+ fallbacks
42614
+ };
42615
+ }
42616
+ var DISPLAY_PRESETS = [
42617
+ preset("camstack", "CamStack", CAMSTACK_HEX, CAMSTACK_FALLBACK),
42618
+ preset("high-contrast", "High contrast", HIGH_CONTRAST_HEX, HIGH_CONTRAST_FALLBACK),
42619
+ preset("okabe-ito", "Colour-blind safe", OKABE_ITO_HEX, OKABE_ITO_FALLBACK)
42620
+ ];
42621
+ function presetById(id) {
42622
+ return DISPLAY_PRESETS.find((item) => item.id === id);
42623
+ }
42624
+ function bundledCamstack() {
42625
+ const presetRow = presetById("camstack");
42626
+ if (presetRow === void 0) throw new Error("CamStack preset missing");
42627
+ return readyOf(presetRow, "unconfigured", false);
42628
+ }
42629
+ function readyOf(row, source, customized) {
42630
+ return {
42631
+ status: "ready",
42632
+ presetId: row.id,
42633
+ customized,
42634
+ source,
42635
+ swatches: row.swatches,
42636
+ fallbacks: [...row.fallbacks]
42637
+ };
42638
+ }
42639
+ function hashFallback(kind, fallbacks) {
42640
+ let hash = 0;
42641
+ for (let i = 0; i < kind.length; i++) hash = hash * 31 + (kind.codePointAt(i) ?? 0) >>> 0;
42642
+ const hex = fallbacks[hash % fallbacks.length];
42643
+ if (hex === void 0) throw new Error("display palette has no fallback colour");
42644
+ return hex;
42645
+ }
42646
+ /** Colour a kind paints with. Audio leaves share the audio gradient's hex. */
42647
+ function paintHex(swatches, fallbacks, kind) {
42648
+ const key = kind.trim().toLowerCase();
42649
+ if (key.startsWith("audio-")) {
42650
+ const audio = swatches[AUDIO_ENTRY_ID];
42651
+ return audio !== void 0 ? audio.hex : hashFallback(key, fallbacks);
42652
+ }
42653
+ const direct = swatches[key];
42654
+ if (direct !== void 0) return direct.hex;
42655
+ return hashFallback(key, fallbacks);
42656
+ }
42657
+ /**
42230
42658
  * Unified event-kind taxonomy — THE single source of truth for
42231
42659
  * `kind → { parentKind, category, level, color, iconId, labelKey, label,
42232
42660
  * icon }`.
@@ -42240,109 +42668,88 @@ for (const [k, v] of Object.entries(APPLE_SA_TO_MACRO.mapping)) _macroLookup.set
42240
42668
  * - `addon-post-analysis/shared/frame/box-drawer.ts` (DEFAULT_COLOR)
42241
42669
  * - the COCO / audio class maps (macro ↔ sub relationships)
42242
42670
  *
42243
- * The DATA (serializable — color/iconId/labelKey/parentKind) lives here in
42244
- * `@camstack/types`. The UI-side mapping `iconId → lucide component` and
42245
- * `labelKey → t()` lives in `@camstack/ui-library`. UIs never hardcode a
42246
- * color or an icon: they read this dictionary (server descriptors carry the
42247
- * fields inline; the client resolves color/icon/label from `iconId`/`kind`).
42671
+ * The DATA (serializable — parentKind / iconId / labelKey) lives here in
42672
+ * `@camstack/types`. Colour is NOT a second table: each entry's `color` is
42673
+ * the bundled CamStack display palette (D939). The effective cluster palette
42674
+ * is the `display-palette` capability. The UI-side mapping `iconId → lucide
42675
+ * component` and `labelKey → t()` lives in `@camstack/ui-library`.
42248
42676
  *
42249
42677
  * Two levels only (v1 YAGNI): macro → sub. `person` is a leaf macro.
42250
42678
  */
42251
- var TAXONOMY_COLORS = {
42252
- motion: "#f59e0b",
42253
- audio: "#06b6d4",
42254
- person: "#22c55e",
42255
- vehicle: "#3b82f6",
42256
- animal: "#f97316",
42257
- package: "#a855f7",
42258
- sensor: "#8b5cf6",
42259
- control: "#10b981",
42260
- genericDetection: "#64748b"
42261
- };
42262
- var DETECTION_SUB_COLORS = {
42263
- car: "#f59e0b",
42264
- truck: "#d97706",
42265
- bus: "#b45309",
42266
- motorcycle: "#eab308",
42267
- bicycle: "#ca8a04",
42268
- airplane: "#60a5fa",
42269
- boat: "#2563eb",
42270
- train: "#1d4ed8",
42271
- bird: "#14b8a6",
42272
- dog: "#84cc16",
42273
- cat: "#f97316",
42274
- horse: "#a16207",
42275
- sheep: "#a3a3a3",
42276
- cow: "#78716c",
42277
- elephant: "#6b7280",
42278
- bear: "#7c2d12",
42279
- zebra: "#404040",
42280
- giraffe: "#d4a373"
42281
- };
42679
+ var BUNDLED_PALETTE = bundledCamstack();
42680
+ function kindColor(kind) {
42681
+ return paintHex(BUNDLED_PALETTE.swatches, BUNDLED_PALETTE.fallbacks, kind);
42682
+ }
42683
+ function firstFallback(fallbacks) {
42684
+ const hex = fallbacks[0];
42685
+ if (hex === void 0) throw new Error("display palette has no fallback colour");
42686
+ return hex;
42687
+ }
42688
+ firstFallback(BUNDLED_PALETTE.fallbacks);
42282
42689
  function titleCase(id) {
42283
42690
  return id.split(/[-_ ]/).filter((p) => p.length > 0).map((p) => p.charAt(0).toUpperCase() + p.slice(1)).join(" ");
42284
42691
  }
42285
42692
  var entries = /* @__PURE__ */ new Map();
42286
- function macro(kind, category, color, iconId, label) {
42693
+ function macro(kind, category, iconId, label) {
42287
42694
  entries.set(kind, {
42288
42695
  kind,
42289
42696
  parentKind: null,
42290
42697
  level: "macro",
42291
42698
  category,
42292
- color,
42699
+ color: kindColor(kind),
42293
42700
  iconId,
42294
42701
  labelKey: `eventKind.${kind}`,
42295
42702
  label
42296
42703
  });
42297
42704
  }
42298
- function sub(kind, parentKind, category, color, iconId, label) {
42705
+ function sub(kind, parentKind, category, iconId, label) {
42299
42706
  entries.set(kind, {
42300
42707
  kind,
42301
42708
  parentKind,
42302
42709
  level: "sub",
42303
42710
  category,
42304
- color,
42711
+ color: kindColor(kind),
42305
42712
  iconId,
42306
42713
  labelKey: `eventKind.${kind}`,
42307
42714
  label
42308
42715
  });
42309
42716
  }
42310
- macro("motion", "motion", TAXONOMY_COLORS.motion, "motion", "Motion");
42311
- macro("audio", "audio", TAXONOMY_COLORS.audio, "audio", "Audio");
42312
- macro("person", "detection", TAXONOMY_COLORS.person, "person", "Person");
42313
- macro("vehicle", "detection", TAXONOMY_COLORS.vehicle, "vehicle", "Vehicle");
42314
- macro("animal", "detection", TAXONOMY_COLORS.animal, "animal", "Animal");
42315
- macro("package", "package", TAXONOMY_COLORS.package, "package", "Package");
42316
- macro("sensor", "sensor", TAXONOMY_COLORS.sensor, "sensor", "Sensor");
42317
- macro("control", "control", TAXONOMY_COLORS.control, "control", "Control");
42717
+ macro("motion", "motion", "motion", "Motion");
42718
+ macro("audio", "audio", "audio", "Audio");
42719
+ macro("person", "detection", "person", "Person");
42720
+ macro("vehicle", "detection", "vehicle", "Vehicle");
42721
+ macro("animal", "detection", "animal", "Animal");
42722
+ macro("package", "package", "package", "Package");
42723
+ macro("sensor", "sensor", "sensor", "Sensor");
42724
+ macro("control", "control", "control", "Control");
42318
42725
  for (const [cocoClass, macroClass] of Object.entries(COCO_TO_MACRO.mapping)) {
42319
42726
  if (macroClass !== "vehicle" && macroClass !== "animal") continue;
42320
42727
  if (entries.has(cocoClass)) continue;
42321
- sub(cocoClass, macroClass, "detection", DETECTION_SUB_COLORS[cocoClass] ?? TAXONOMY_COLORS.genericDetection, cocoClass, titleCase(cocoClass));
42728
+ sub(cocoClass, macroClass, "detection", cocoClass, titleCase(cocoClass));
42322
42729
  }
42323
- sub("package-delivered", "package", "package", TAXONOMY_COLORS.package, "package", "Package delivered");
42324
- sub("package-picked-up", "package", "package", TAXONOMY_COLORS.package, "package", "Package picked up");
42325
- sub("contact", "sensor", "sensor", "#f59e0b", "door", "Contact");
42326
- sub("motion-sensor", "sensor", "sensor", TAXONOMY_COLORS.sensor, "pir", "Motion sensor");
42327
- sub("smoke", "sensor", "sensor", "#ef4444", "smoke", "Smoke");
42328
- sub("flood", "sensor", "sensor", "#3b82f6", "water", "Water leak");
42329
- sub("gas", "sensor", "sensor", "#ef4444", "gas", "Gas");
42330
- sub("carbon-monoxide", "sensor", "sensor", "#dc2626", "smoke", "Carbon monoxide");
42331
- sub("vibration", "sensor", "sensor", "#eab308", "vibration", "Vibration");
42332
- sub("tamper", "sensor", "sensor", "#f97316", "tamper", "Tamper");
42333
- sub("presence", "sensor", "sensor", "#22c55e", "presence", "Presence");
42334
- sub("enum-sensor", "sensor", "sensor", TAXONOMY_COLORS.sensor, "generic", "Sensor state");
42335
- sub("device-event", "sensor", "sensor", "#10b981", "button", "Device event");
42336
- sub("lock", "control", "control", "#0ea5e9", "lock", "Lock");
42337
- sub("cover", "control", "control", "#0ea5e9", "door", "Cover");
42338
- sub("switch", "control", "control", TAXONOMY_COLORS.control, "switch", "Switch");
42339
- sub("siren", "control", "control", "#dc2626", "siren", "Siren");
42340
- sub("button", "control", "control", "#10b981", "button", "Button");
42341
- sub("doorbell", "control", "control", "#a855f7", "doorbell", "Doorbell");
42730
+ sub("package-delivered", "package", "package", "package", "Package delivered");
42731
+ sub("package-picked-up", "package", "package", "package", "Package picked up");
42732
+ sub("contact", "sensor", "sensor", "door", "Contact");
42733
+ sub("motion-sensor", "sensor", "sensor", "pir", "Motion sensor");
42734
+ sub("smoke", "sensor", "sensor", "smoke", "Smoke");
42735
+ sub("flood", "sensor", "sensor", "water", "Water leak");
42736
+ sub("gas", "sensor", "sensor", "gas", "Gas");
42737
+ sub("carbon-monoxide", "sensor", "sensor", "smoke", "Carbon monoxide");
42738
+ sub("vibration", "sensor", "sensor", "vibration", "Vibration");
42739
+ sub("tamper", "sensor", "sensor", "tamper", "Tamper");
42740
+ sub("presence", "sensor", "sensor", "presence", "Presence");
42741
+ sub("enum-sensor", "sensor", "sensor", "generic", "Sensor state");
42742
+ sub("device-event", "sensor", "sensor", "button", "Device event");
42743
+ sub("lock", "control", "control", "lock", "Lock");
42744
+ sub("cover", "control", "control", "door", "Cover");
42745
+ sub("switch", "control", "control", "switch", "Switch");
42746
+ sub("siren", "control", "control", "siren", "Siren");
42747
+ sub("button", "control", "control", "button", "Button");
42748
+ sub("doorbell", "control", "control", "doorbell", "Doorbell");
42342
42749
  for (const l of AUDIO_MACRO_LABELS) {
42343
42750
  const kind = `audio-${l.id}`;
42344
42751
  if (entries.has(kind)) continue;
42345
- sub(kind, "audio", "audio", TAXONOMY_COLORS.audio, kind, l.name);
42752
+ sub(kind, "audio", "audio", kind, l.name);
42346
42753
  }
42347
42754
  /** The complete taxonomy dictionary, keyed by kind. */
42348
42755
  var EVENT_TAXONOMY = Object.freeze(Object.fromEntries(entries));
@@ -42653,9 +43060,6 @@ var NcSystemEventKindSchema = _enum([
42653
43060
  "device-battery-normal",
42654
43061
  "device-consumable-low",
42655
43062
  "device-consumable-normal",
42656
- "device-tank-low",
42657
- "device-tank-full",
42658
- "device-tank-normal",
42659
43063
  "stream-online",
42660
43064
  "stream-offline",
42661
43065
  "node-online",
@@ -42702,13 +43106,14 @@ var NcSystemEventKindSchema = _enum([
42702
43106
  "camera-enabled"
42703
43107
  ]);
42704
43108
  /** The legacy tail of {@link NcSystemEventKindSchema} — see its docblock. */
42705
- var NC_LEGACY_SYSTEM_EVENT_KINDS = new Set([
43109
+ var NC_LEGACY_SYSTEM_EVENT_KINDS = [
42706
43110
  "camera-online",
42707
43111
  "camera-offline",
42708
43112
  "camera-disabled",
42709
43113
  "camera-enabled"
42710
- ]);
42711
- NcSystemEventKindSchema.options.filter((kind) => !NC_LEGACY_SYSTEM_EVENT_KINDS.has(kind));
43114
+ ];
43115
+ var NC_LEGACY_SYSTEM_EVENT_KIND_SET = new Set(NC_LEGACY_SYSTEM_EVENT_KINDS);
43116
+ NcSystemEventKindSchema.options.filter((kind) => !NC_LEGACY_SYSTEM_EVENT_KIND_SET.has(kind));
42712
43117
  /**
42713
43118
  * The panel's transitions, as ONE list.
42714
43119
  *
@@ -43827,18 +44232,11 @@ var NcRuleSchema = NcRuleInputSchema.extend({
43827
44232
  */
43828
44233
  disabledTargetIds: array(string()).default([])
43829
44234
  });
43830
- /**
43831
- * The state-summary SECTIONS (D647 / D698 / D708): the D637 kind groups that
43832
- * report a still-true state. `addons` is the crash-looped addons only and
43833
- * `addon-updates` the addons that are behind (D708 split them). `backups-exports` and `alarm` are not sections — a completed
43834
- * job is not an open state, and the alarm stays instant.
43835
- */
43836
44235
  var NcStateSummarySectionIdSchema = _enum([
43837
44236
  "device-state",
43838
44237
  "streams",
43839
44238
  "battery",
43840
44239
  "consumables",
43841
- "tanks",
43842
44240
  "detection-blind",
43843
44241
  "nodes",
43844
44242
  "addons",
@@ -45139,6 +45537,18 @@ Object.freeze({
45139
45537
  reason: "camera sensor mappings not loaded"
45140
45538
  });
45141
45539
  /**
45540
+ * What the vision model must answer before a package event is emitted
45541
+ * when a packages rule has "Confirm with the LLM" on.
45542
+ *
45543
+ * `package` is the verdict. `confidence` is 0..1. `reason` is the model's
45544
+ * one-line explanation, stored on the event so a drop is not silent.
45545
+ */
45546
+ var PackageLlmVerdictSchema = object({
45547
+ package: boolean(),
45548
+ confidence: number().min(0).max(1),
45549
+ reason: string().min(1)
45550
+ });
45551
+ /**
45142
45552
  * A model choice has a SCOPE, and a scope change has a workflow.
45143
45553
  *
45144
45554
  * ## The two scopes
@@ -46075,6 +46485,21 @@ var ObjectEventSchema = object({
46075
46485
  * pick-up written before D684 — UNKNOWN, never 0 and never `timestamp`.
46076
46486
  */
46077
46487
  observedAt: number().optional(),
46488
+ /**
46489
+ * The delivery was emitted without a vision-model yes (D931).
46490
+ *
46491
+ * Set only when the packages rule asked for an LLM confirm and the model
46492
+ * was unreachable, timed out, or answered something that did not parse.
46493
+ * A notification reads it so it can say "possible" instead of a definite
46494
+ * delivery. Absent on every other row, and on a confirm that said yes.
46495
+ */
46496
+ packagePossible: boolean().optional(),
46497
+ /**
46498
+ * The vision model's verdict, when a packages rule asked for one and the
46499
+ * model answered the schema (D931). A "no" never becomes a row — the
46500
+ * detector drops it and logs the reason. Present on a yes.
46501
+ */
46502
+ packageLlmVerdict: PackageLlmVerdictSchema.optional(),
46078
46503
  /** The parent track's key-event importance [0,1], propagated to every object
46079
46504
  * event of the track (so an event row can be sorted by importance without a
46080
46505
  * track join). Absent on legacy rows / before the track was scored. */
@@ -47872,7 +48297,6 @@ var PipelineAddonSchemaSchema = object({
47872
48297
  defaultModelId: string(),
47873
48298
  defaultModelIdByFormat: record(string(), string()).optional(),
47874
48299
  enabledByDefault: boolean().optional(),
47875
- backfillIntoExistingOverrides: boolean().optional(),
47876
48300
  defaultConfidence: number(),
47877
48301
  group: string().optional(),
47878
48302
  configSchema: array(ConfigFieldBridge).readonly().optional()
@@ -47999,13 +48423,12 @@ var AudioTestResultSchema = object({
47999
48423
  error: string().optional(),
48000
48424
  frame: custom().optional()
48001
48425
  });
48002
- var PipelineConfigBridge = custom();
48003
48426
  var ConfigUISchemaBridge = custom();
48004
48427
  var ConfigUISchemaNullableBridge = custom();
48005
48428
  var InferenceCapabilitiesBridge = custom();
48006
48429
  var ModelAvailabilityListBridge = custom();
48007
48430
  var PipelineRunResultBridge = custom();
48008
- method(_void(), array(PipelineEngineChoiceSchema)), method(_void(), PipelineEngineChoiceSchema), method(PipelineEngineChoiceSchema, array(PipelineDefaultStepSchema)), method(object({ nodeId: string() }), EngineProvisioningSchema), method(_void(), record(string(), object({
48431
+ method(_void(), array(PipelineEngineChoiceSchema)), method(_void(), PipelineEngineChoiceSchema), method(object({ nodeId: string() }), EngineProvisioningSchema), method(_void(), record(string(), object({
48009
48432
  modelId: string(),
48010
48433
  settings: record(string(), unknown()).readonly()
48011
48434
  }))), method(object({ steps: record(string(), object({
@@ -48014,28 +48437,6 @@ method(_void(), array(PipelineEngineChoiceSchema)), method(_void(), PipelineEngi
48014
48437
  })) }), object({ success: literal(true) }), {
48015
48438
  kind: "mutation",
48016
48439
  auth: "admin"
48017
- }), method(object({ nodeId: string() }), object({
48018
- success: literal(true),
48019
- clearedDevices: number()
48020
- }), {
48021
- kind: "mutation",
48022
- auth: "admin"
48023
- }), method(object({
48024
- nodeId: string(),
48025
- deviceIds: array(number()).readonly().optional(),
48026
- dryRun: boolean()
48027
- }), object({
48028
- entries: array(object({
48029
- deviceId: number(),
48030
- keys: array(string()).readonly()
48031
- })).readonly(),
48032
- refused: array(object({
48033
- deviceId: number(),
48034
- reason: string()
48035
- })).readonly()
48036
- }), {
48037
- kind: "mutation",
48038
- auth: "admin"
48039
48440
  }), method(object({ nodeId: string() }), object({ unhealthy: array(object({
48040
48441
  /** `<backend>:<device>`, e.g. `openvino:gpu`. */
48041
48442
  deviceKey: string(),
@@ -48058,7 +48459,7 @@ method(_void(), array(PipelineEngineChoiceSchema)), method(_void(), PipelineEngi
48058
48459
  }), object({ rearmed: boolean() }), {
48059
48460
  kind: "mutation",
48060
48461
  auth: "admin"
48061
- }), method(_void(), PipelineSchemaSchema), method(_void(), array(PipelineDefaultStepSchema).readonly().nullable()), method(_void(), PipelineConfigBridge), method(_void(), ConfigUISchemaBridge), method(object({
48462
+ }), method(_void(), PipelineSchemaSchema), method(_void(), ConfigUISchemaBridge), method(object({
48062
48463
  steps: array(PipelineStepInputSchema),
48063
48464
  deviceKey: string().optional()
48064
48465
  }), PipelineValidationResultSchema), method(_void(), InferenceCapabilitiesBridge), method(object({ addonId: string() }), ModelAvailabilityListBridge), method(object({
@@ -48306,11 +48707,18 @@ var KeptReasonSchema = _enum(["custom-pin"]);
48306
48707
  * Where a choice's latency came from (D791): this node's own benchmark
48307
48708
  * result, or the hardware-class table. Measured on the node beats the table.
48308
48709
  */
48309
- var LatencySourceSchema = discriminatedUnion("kind", [object({ kind: literal("table") }), object({
48310
- kind: literal("node-benchmark"),
48311
- resultId: string(),
48312
- measuredAtMs: number()
48313
- })]);
48710
+ var LatencySourceSchema = discriminatedUnion("kind", [
48711
+ object({ kind: literal("table") }),
48712
+ object({
48713
+ kind: literal("node-benchmark"),
48714
+ resultId: string(),
48715
+ measuredAtMs: number()
48716
+ }),
48717
+ object({
48718
+ kind: literal("estimated"),
48719
+ estimatedFrom: HardwareClassIdSchema
48720
+ })
48721
+ ]);
48314
48722
  var DeviceModelChoiceSchema = object({
48315
48723
  modelId: string(),
48316
48724
  p50Ms: number(),
@@ -48318,6 +48726,11 @@ var DeviceModelChoiceSchema = object({
48318
48726
  measured: boolean(),
48319
48727
  /** Absent on a plan from before D791 — read as the table. */
48320
48728
  source: LatencySourceSchema.optional(),
48729
+ /**
48730
+ * The measured class this latency was scaled from (D930). Absent when the
48731
+ * cell is the table or a node benchmark.
48732
+ */
48733
+ estimatedFrom: HardwareClassIdSchema.optional(),
48321
48734
  /** Parallel sessions at the camera rate with the headroom kept free: ⌊fps × (1 − headroom) / camera fps⌋. */
48322
48735
  capacitySessions: number(),
48323
48736
  personRecall: number()
@@ -48357,40 +48770,20 @@ var NodeDeviceChangeSchema = object({
48357
48770
  keys: array(string()).readonly()
48358
48771
  })).readonly()
48359
48772
  });
48360
- var CameraOverrideClearSchema = object({
48361
- deviceId: number(),
48362
- source: _enum(["step-override", "wholesale"]),
48773
+ /**
48774
+ * Every model and model-bound threshold lives on the accelerator that runs it
48775
+ * (D927), so the plan writes node / device entries only — there is no camera
48776
+ * layer for it to clear.
48777
+ */
48778
+ var AutoTuneWarningSchema = discriminatedUnion("kind", [object({
48779
+ kind: literal("custom-pin-kept"),
48363
48780
  nodeId: string(),
48364
- deviceKey: string().nullable(),
48365
- stepId: string(),
48366
- modelIdBefore: string().nullable(),
48367
- keys: array(string()).readonly()
48368
- });
48369
- var DetectorStoreClearSchema = object({
48370
- deviceId: number(),
48371
- keys: array(string()).readonly()
48372
- });
48373
- var AutoTuneWarningSchema = discriminatedUnion("kind", [
48374
- object({
48375
- kind: literal("detector-store-cluster-wide"),
48376
- skippedNodes: array(string()).readonly()
48377
- }),
48378
- object({
48379
- kind: literal("detector-store-unreadable"),
48380
- error: string()
48381
- }),
48382
- object({
48383
- kind: literal("custom-pin-kept"),
48384
- nodeId: string(),
48385
- deviceKey: string().nullable(),
48386
- deviceId: number().nullable(),
48387
- modelId: string()
48388
- }),
48389
- object({
48390
- kind: literal("custom-registry-unreadable"),
48391
- error: string()
48392
- })
48393
- ]);
48781
+ deviceKey: string(),
48782
+ modelId: string()
48783
+ }), object({
48784
+ kind: literal("custom-registry-unreadable"),
48785
+ error: string()
48786
+ })]);
48394
48787
  var AutoTuneOptionsSchema = object({
48395
48788
  /** Share of each accelerator's throughput kept free (0.3–0.5). */
48396
48789
  headroom: number().min(.3).max(.5).default(.4),
@@ -48412,8 +48805,6 @@ var AutoTunePlanSchema = object({
48412
48805
  generatedAt: number(),
48413
48806
  nodes: array(NodeRecommendationSchema).readonly(),
48414
48807
  nodeChanges: array(NodeDeviceChangeSchema).readonly(),
48415
- cameraClears: array(CameraOverrideClearSchema).readonly(),
48416
- detectorStoreClears: array(DetectorStoreClearSchema).readonly(),
48417
48808
  warnings: array(AutoTuneWarningSchema).readonly()
48418
48809
  });
48419
48810
  var AutoTuneApplyInputSchema = object({
@@ -48424,8 +48815,6 @@ var AutoTuneApplyInputSchema = object({
48424
48815
  var AutoTunePhaseResultSchema = object({
48425
48816
  phase: _enum([
48426
48817
  "download",
48427
- "camera-overrides",
48428
- "detector-thresholds",
48429
48818
  "node-models",
48430
48819
  "redispatch"
48431
48820
  ]),
@@ -50180,6 +50569,12 @@ var AgentPipelineSettingsSchema = object({
50180
50569
  /** Hub-persisted UI colour (`--color-node-*` theme tokens). */
50181
50570
  color: NodeColorIdSchema.optional(),
50182
50571
  /**
50572
+ * NODE-wide step settings (D927): `stepId → { key → value }`, applied on
50573
+ * every accelerator of the node under the device's own settings. Never a
50574
+ * model or a model-bound threshold. Written by `setNodeStepSettings`.
50575
+ */
50576
+ stepSettings: record(string(), record(string(), unknown()).readonly()).optional(),
50577
+ /**
50183
50578
  * Multi-device inference opt-in (Phase 4). Per-node map deviceKey → {enabled,
50184
50579
  * weight, steps}. Absent / all-disabled ⇒ the node's single default
50185
50580
  * accelerator (safe default); two+ enabled ⇒ the dispatcher balances
@@ -50195,17 +50590,6 @@ var AgentPipelineSettingsSchema = object({
50195
50590
  steps: record(string(), DeviceStepConfigSchema).optional()
50196
50591
  })).optional()
50197
50592
  });
50198
- var CameraPipelineForAgentSchema = object({
50199
- steps: array(PipelineStepInputSchema).readonly(),
50200
- audio: object({
50201
- modelId: string(),
50202
- enabled: boolean()
50203
- }).nullable()
50204
- });
50205
- var CameraStepOverridePatchSchema = object({
50206
- modelId: string().optional(),
50207
- settings: record(string(), unknown()).readonly().optional()
50208
- });
50209
50593
  var CameraStepSettingsSchema = record(string(), record(string(), unknown()).readonly());
50210
50594
  /** The three root-detector choices a camera has (D507: at most one root). */
50211
50595
  var CameraDetectionSourceSchema = _enum([
@@ -50215,9 +50599,7 @@ var CameraDetectionSourceSchema = _enum([
50215
50599
  ]);
50216
50600
  var CameraPipelineSettingsSchema = object({
50217
50601
  stepToggles: record(string(), boolean()).optional(),
50218
- stepSettings: CameraStepSettingsSchema.optional(),
50219
- stepOverridesByDevice: record(string(), record(string(), record(string(), CameraStepOverridePatchSchema))).optional(),
50220
- pipelineByAgent: record(string(), CameraPipelineForAgentSchema).optional()
50602
+ stepSettings: CameraStepSettingsSchema.optional()
50221
50603
  });
50222
50604
  /**
50223
50605
  * Pipeline placement record persisted by `addon-pipeline-orchestrator` via
@@ -50763,6 +51145,13 @@ method(object({
50763
51145
  }), object({ success: literal(true) }), {
50764
51146
  kind: "mutation",
50765
51147
  auth: "admin"
51148
+ }), method(object({
51149
+ agentNodeId: string(),
51150
+ addonId: string(),
51151
+ settings: record(string(), unknown()).nullable()
51152
+ }), object({ success: literal(true) }), {
51153
+ kind: "mutation",
51154
+ auth: "admin"
50766
51155
  }), method(object({ nodeId: string() }), NodeInferenceDevicesSchema), method(object({
50767
51156
  agentNodeId: string(),
50768
51157
  deviceKey: string()
@@ -50772,9 +51161,7 @@ method(object({
50772
51161
  }), method(object({ agentNodeId: string() }), object({
50773
51162
  success: literal(true),
50774
51163
  /** Hardware-aware default detection model now in effect on the node (null when unresolvable). */
50775
- effectiveModelId: string().nullable(),
50776
- /** Number of cameras whose node-scoped overrides were cleared. */
50777
- clearedCameraOverrides: number()
51164
+ effectiveModelId: string().nullable()
50778
51165
  }), {
50779
51166
  kind: "mutation",
50780
51167
  auth: "admin"
@@ -50829,15 +51216,6 @@ method(object({
50829
51216
  }), object({ success: literal(true) }), {
50830
51217
  kind: "mutation",
50831
51218
  auth: "admin"
50832
- }), method(object({ deviceId: number() }), record(string(), record(string(), record(string(), CameraStepOverridePatchSchema))).nullable()), method(object({
50833
- deviceId: number(),
50834
- agentNodeId: string(),
50835
- deviceKey: string(),
50836
- addonId: string(),
50837
- patch: CameraStepOverridePatchSchema.nullable()
50838
- }), object({ success: literal(true) }), {
50839
- kind: "mutation",
50840
- auth: "admin"
50841
51219
  }), method(object({
50842
51220
  deviceId: number(),
50843
51221
  addonId: string(),
@@ -50845,13 +51223,6 @@ method(object({
50845
51223
  }), object({ success: literal(true) }), {
50846
51224
  kind: "mutation",
50847
51225
  auth: "admin"
50848
- }), method(object({
50849
- deviceId: number(),
50850
- agentNodeId: string(),
50851
- pipeline: CameraPipelineForAgentSchema.nullable()
50852
- }), object({ success: literal(true) }), {
50853
- kind: "mutation",
50854
- auth: "admin"
50855
51226
  }), method(object({
50856
51227
  deviceId: number(),
50857
51228
  agentNodeId: string().optional()
@@ -54998,20 +55369,68 @@ var BatteryStatusSchema = object({
54998
55369
  */
54999
55370
  binary: boolean().optional()
55000
55371
  });
55372
+ var BATTERY_DEVICE_TYPES = [
55373
+ DeviceType.Camera,
55374
+ DeviceType.Sensor,
55375
+ DeviceType.Button,
55376
+ DeviceType.Switch,
55377
+ DeviceType.PetFeeder,
55378
+ DeviceType.Container,
55379
+ DeviceType.Thermostat
55380
+ ];
55381
+ /** Generic Customize target for the percentage reading (D936). */
55382
+ var batteryCustomize = {
55383
+ version: 1,
55384
+ targets: [{
55385
+ id: "percentage",
55386
+ cardinality: "scalar",
55387
+ vocabulary: {
55388
+ cap: "battery",
55389
+ stateField: "percentage"
55390
+ },
55391
+ deviceTypes: BATTERY_DEVICE_TYPES,
55392
+ apply: "add-or-replace",
55393
+ path: "percentage",
55394
+ sources: [{
55395
+ kind: "field",
55396
+ valueKinds: ["number", "string"],
55397
+ transforms: [{ kind: "identity" }, {
55398
+ kind: "linear",
55399
+ defaultScale: 1,
55400
+ defaultOffset: 0,
55401
+ clampMin: 0,
55402
+ clampMax: 100
55403
+ }]
55404
+ }],
55405
+ companions: [
55406
+ {
55407
+ kind: "constant",
55408
+ path: "charging",
55409
+ value: "unknown",
55410
+ when: "add"
55411
+ },
55412
+ {
55413
+ kind: "constant",
55414
+ path: "sleeping",
55415
+ value: false,
55416
+ when: "add"
55417
+ },
55418
+ {
55419
+ kind: "clock",
55420
+ path: "lastUpdated",
55421
+ when: "add"
55422
+ }
55423
+ ],
55424
+ sourceReport: { status: "assignment-status" },
55425
+ advancedExpression: true
55426
+ }]
55427
+ };
55001
55428
  var batteryCapability = {
55002
55429
  name: "battery",
55003
55430
  scope: "device",
55004
55431
  deviceNative: true,
55005
55432
  mode: "singleton",
55006
- deviceTypes: [
55007
- DeviceType.Camera,
55008
- DeviceType.Sensor,
55009
- DeviceType.Button,
55010
- DeviceType.Switch,
55011
- DeviceType.PetFeeder,
55012
- DeviceType.Container,
55013
- DeviceType.Thermostat
55014
- ],
55433
+ deviceTypes: BATTERY_DEVICE_TYPES,
55015
55434
  methods: {
55016
55435
  /**
55017
55436
  * Explicitly wake the camera from low-power sleep ahead of a
@@ -55095,6 +55514,7 @@ onStatusChanged: { data: object({
55095
55514
  kind: "gauge",
55096
55515
  unit: "%"
55097
55516
  } } },
55517
+ customize: batteryCustomize,
55098
55518
  /** Clock fields: written, but excluded from the compare that decides
55099
55519
  * whether persisting is worth a SQLite commit. */
55100
55520
  volatileStateFields: ["lastUpdated"]
@@ -56055,6 +56475,106 @@ var ConsumablesStatusSchema = object({
56055
56475
  items: array(ConsumableItemSchema),
56056
56476
  lastChangedAt: number()
56057
56477
  });
56478
+ /** Synthesize seed for a link-built status (no native provider).
56479
+ *
56480
+ * ⚠ NO LIVE CALLER since 2026-08-08 (device-links deleted; see
56481
+ * `CapabilityStatusSchema.empty`). The wiring guidance below was written for
56482
+ * exactly the case the operator is asking about again — a Dreame's HA
56483
+ * consumable-life sensors — so it is kept for that conversation, not because
56484
+ * anything reads it today. */
56485
+ var EMPTY_STATUS = {
56486
+ items: [],
56487
+ lastChangedAt: 0
56488
+ };
56489
+ /** Seed for a NEW link-built consumable item. `key`/`label` are overwritten
56490
+ * with the link's `itemKey` (see `status.itemArray`), so the placeholder
56491
+ * empty strings never survive into a validated item. Link-built items are
56492
+ * not resettable — there is no native provider to receive `reset()`.
56493
+ *
56494
+ * Wiring guidance (HA vacuum consumable-life sensors):
56495
+ * - a percent-remaining source (`numeric-sensor`, unit '%') → `level` via
56496
+ * `identity` (or `linear` scale 1 offset 0 clamp [0,100] to be safe);
56497
+ * - an hours-remaining source (e.g. Dreame 'Main Brush Time Left', unit 'h')
56498
+ * → `level` via `linear` with scale = 100 / max-hours for that item
56499
+ * (e.g. main brush 300 h → scale 0.3333) + clamp [0,100];
56500
+ * - a discrete source (`enum-sensor`, e.g. mop pad 'installed') → `status`
56501
+ * via `enum-map` (e.g. { installed: 'ok', missing: 'replace' }).
56502
+ * A numeric→'replace' THRESHOLD (level < 10 → 'replace') is NOT expressible
56503
+ * with the current transform kinds — leave `status` null (valid) until the
56504
+ * expression transform lands. */
56505
+ /** Generic Customize target for one consumable item (D936). Native rows stay read-only. */
56506
+ var consumablesCustomize = {
56507
+ version: 1,
56508
+ targets: [{
56509
+ id: "items",
56510
+ cardinality: "keyedArray",
56511
+ vocabulary: { cap: "consumables" },
56512
+ deviceTypes: Object.values(DeviceType),
56513
+ apply: "add",
56514
+ path: "items",
56515
+ keyField: "key",
56516
+ labelField: "label",
56517
+ itemSchema: ConsumableItemSchema,
56518
+ nativeItems: "read-only",
56519
+ sourceReport: { status: "assignment-status" },
56520
+ fields: [
56521
+ {
56522
+ path: "level",
56523
+ sources: [{
56524
+ kind: "numeric",
56525
+ transforms: [{ kind: "identity" }, {
56526
+ kind: "linear",
56527
+ defaultScale: 1,
56528
+ defaultOffset: 0,
56529
+ clampMin: 0,
56530
+ clampMax: 100
56531
+ }]
56532
+ }]
56533
+ },
56534
+ {
56535
+ path: "remaining.value",
56536
+ sources: [{
56537
+ kind: "numeric",
56538
+ transforms: [{ kind: "identity" }]
56539
+ }],
56540
+ literals: [{
56541
+ path: "remaining.unit",
56542
+ values: [...ConsumableRemainingUnitSchema.options]
56543
+ }]
56544
+ },
56545
+ {
56546
+ path: "status",
56547
+ sources: [{
56548
+ kind: "enum",
56549
+ transforms: [{
56550
+ kind: "enum-map",
56551
+ outputValues: [...ConsumableStatusSchema.options],
56552
+ unmapped: null
56553
+ }]
56554
+ }]
56555
+ }
56556
+ ],
56557
+ traits: [{
56558
+ path: "kind",
56559
+ values: [...ConsumableKindSchema.options],
56560
+ defaultValue: "wear"
56561
+ }, {
56562
+ path: "form",
56563
+ values: [...ConsumableFormSchema.options],
56564
+ defaultValue: "part"
56565
+ }],
56566
+ companions: [{
56567
+ kind: "clock",
56568
+ path: "lastChangedAt",
56569
+ when: "add"
56570
+ }, {
56571
+ kind: "clock",
56572
+ path: "lastFetchedAt",
56573
+ when: "add"
56574
+ }],
56575
+ advancedExpression: true
56576
+ }]
56577
+ };
56058
56578
  var consumablesCapability = {
56059
56579
  name: "consumables",
56060
56580
  scope: "device",
@@ -56092,10 +56612,7 @@ reset: method(object({
56092
56612
  status: {
56093
56613
  schema: ConsumablesStatusSchema,
56094
56614
  kind: "push",
56095
- empty: {
56096
- items: [],
56097
- lastChangedAt: 0
56098
- },
56615
+ empty: EMPTY_STATUS,
56099
56616
  itemArray: {
56100
56617
  path: "items",
56101
56618
  keyField: "key",
@@ -56131,6 +56648,7 @@ reset: method(object({
56131
56648
  * brush's remaining life and a dishwasher's salt are each recorded the moment
56132
56649
  * their provider reports them; an item that appears later gets its series.
56133
56650
  */
56651
+ customize: consumablesCustomize,
56134
56652
  history: {
56135
56653
  fields: {},
56136
56654
  items: {
@@ -56510,6 +57028,30 @@ var dayNightCapability = {
56510
57028
  volatileStateFields: ["lastFetchedAt"]
56511
57029
  };
56512
57030
  /**
57031
+ * display-palette — the cluster's one colour table (D939).
57032
+ *
57033
+ * Hub singleton. `getPalette` reports `unknown` when the settings store
57034
+ * cannot be read; it does not pretend the bundled preset was stored.
57035
+ * `setPalette` refuses a palette that fails the ΔE / contrast rule and names
57036
+ * the pairs.
57037
+ */
57038
+ var presetSummarySchema = object({
57039
+ id: string(),
57040
+ name: string(),
57041
+ swatches: record(string(), paletteSwatchSchema),
57042
+ fallbacks: array(string())
57043
+ });
57044
+ method(_void(), paletteResultSchema, {
57045
+ auth: "protected",
57046
+ role: "viewer"
57047
+ }), method(_void(), array(presetSummarySchema).readonly(), {
57048
+ auth: "protected",
57049
+ role: "viewer"
57050
+ }), method(setPaletteInputSchema, paletteReadySchema, {
57051
+ kind: "mutation",
57052
+ auth: "admin"
57053
+ });
57054
+ /**
56513
57055
  * Generic device-level status snapshot. Auto-registered by `BaseDevice`
56514
57056
  * for every device, regardless of provider — the kernel needs a uniform
56515
57057
  * cap-keyed slice for the basic device flags every consumer expects to
@@ -56873,6 +57415,36 @@ var dishwasherCapability = {
56873
57415
  powerOn: { kind: "boolean" }
56874
57416
  } }
56875
57417
  };
57418
+ /** Pulse override: a rising edge advances `lastPressedAt` and the press count. */
57419
+ var doorbellCustomize = {
57420
+ version: 1,
57421
+ targets: [{
57422
+ id: "pressed",
57423
+ cardinality: "event",
57424
+ shape: "pulse",
57425
+ vocabulary: {
57426
+ cap: "doorbell",
57427
+ eventName: "onPressed"
57428
+ },
57429
+ deviceTypes: [DeviceType.Camera],
57430
+ apply: "add",
57431
+ applyAuthority: { kind: "composition-claim" },
57432
+ eventName: "onPressed",
57433
+ edges: ["rising"],
57434
+ timestampPath: "lastPressedAt",
57435
+ counterPath: "pressCountSinceStart",
57436
+ highWater: "composer-advance",
57437
+ combine: "any",
57438
+ debounce: {
57439
+ kind: "rising-edge",
57440
+ defaultDebounceMs: 2e3,
57441
+ changedAtRequired: true
57442
+ },
57443
+ sources: [{ kind: "binary" }, { kind: "switch" }],
57444
+ sourceReport: { status: "assignment-status" },
57445
+ advancedExpression: true
57446
+ }]
57447
+ };
56876
57448
  var DoorbellStatusSchema = object({
56877
57449
  /** Ms epoch of the last press. null = never observed since this provider started. */
56878
57450
  lastPressedAt: number().nullable(),
@@ -56939,7 +57511,8 @@ onPressed: {
56939
57511
  /**
56940
57512
  * History (D850): none — `pressCountSinceStart` resets with the addon, so it is not a monotonic meter; presses live in the events ledger.
56941
57513
  */
56942
- history: "none"
57514
+ history: "none",
57515
+ customize: doorbellCustomize
56943
57516
  };
56944
57517
  /**
56945
57518
  * Enum-state sensor — a string value picked from a finite option set.
@@ -59335,6 +59908,38 @@ authKey: string().optional() }), object({
59335
59908
  /** Human-readable error when `ok: false`. */
59336
59909
  error: string().optional()
59337
59910
  }), { kind: "mutation" });
59911
+ /** Span override: start on a rising edge, end on a fall or this timeout. */
59912
+ var motionCustomize = {
59913
+ version: 1,
59914
+ targets: [{
59915
+ id: "detected",
59916
+ cardinality: "event",
59917
+ shape: "span",
59918
+ vocabulary: {
59919
+ cap: "motion",
59920
+ eventName: "onMotionChanged"
59921
+ },
59922
+ deviceTypes: [DeviceType.Camera],
59923
+ apply: "replace",
59924
+ applyAuthority: {
59925
+ kind: "camera-sensors",
59926
+ timeoutField: "motionCooldownMs"
59927
+ },
59928
+ eventName: "onMotionChanged",
59929
+ start: "rising-edge",
59930
+ end: "falling-edge-or-timeout",
59931
+ timeoutMs: 3e4,
59932
+ combine: "any",
59933
+ sourceModes: [
59934
+ "in-addition",
59935
+ "confirm",
59936
+ "replace"
59937
+ ],
59938
+ sources: [{ kind: "binary" }, { kind: "switch" }],
59939
+ sourceReport: { status: "assignment-status" },
59940
+ advancedExpression: false
59941
+ }]
59942
+ };
59338
59943
  var MotionStatusSchema = object({
59339
59944
  detected: boolean(),
59340
59945
  /** Ms epoch of the last detected-true observation. Null if never detected. */
@@ -59474,7 +60079,8 @@ onMotionChanged: { data: MotionOnMotionChangedDataSchema } },
59474
60079
  history: { fields: { detected: {
59475
60080
  kind: "boolean",
59476
60081
  excludeDeviceTypes: [DeviceType.Camera]
59477
- } } }
60082
+ } } },
60083
+ customize: motionCustomize
59478
60084
  };
59479
60085
  /**
59480
60086
  * Motion-trigger toggle for accessory devices.
@@ -61273,6 +61879,30 @@ includeCrops: boolean().optional() }).optional(), array(VehicleSchema).readonly(
61273
61879
  kind: "mutation",
61274
61880
  auth: "admin"
61275
61881
  });
61882
+ var CORE_ULTRA_265K_IGPU_CLOCK_MHZ = 2e3;
61883
+ var positiveOrNull = number().nullable().transform((value) => value !== null && Number.isFinite(value) && value > 0 ? value : null);
61884
+ var textOrNull = string().nullable().transform((value) => value !== null && value.trim() !== "" ? value : null);
61885
+ var PrecisionGopsSchema = object({
61886
+ int8: positiveOrNull,
61887
+ fp16: positiveOrNull
61888
+ });
61889
+ /** What one accelerator device reported. Every failed query is null. */
61890
+ var AcceleratorComputeSchema = object({
61891
+ deviceKey: string(),
61892
+ fullDeviceName: textOrNull,
61893
+ executionUnits: positiveOrNull,
61894
+ clockMHz: positiveOrNull,
61895
+ gops: PrecisionGopsSchema.nullable(),
61896
+ architecture: textOrNull,
61897
+ npuName: textOrNull,
61898
+ tops: positiveOrNull,
61899
+ vendor: textOrNull,
61900
+ webgpuArchitecture: textOrNull,
61901
+ webgpuDevice: textOrNull,
61902
+ computeUnits: positiveOrNull
61903
+ });
61904
+ object({ accelerators: array(AcceleratorComputeSchema).nullable() });
61905
+ 64 * CORE_ULTRA_265K_IGPU_CLOCK_MHZ;
61276
61906
  var ModelFormatSchema = _enum(MODEL_FORMATS);
61277
61907
  var HwAccelBackendInputSchema = _enum([
61278
61908
  "videotoolbox",
@@ -61386,7 +62016,12 @@ var HardwareInfoSchema = object({
61386
62016
  availableRAM_MB: number(),
61387
62017
  gpu: GpuInfoSchema.nullable(),
61388
62018
  npu: NpuInfoSchema.nullable(),
61389
- coral: CoralInfoSchema.nullable().optional()
62019
+ coral: CoralInfoSchema.nullable().optional(),
62020
+ /**
62021
+ * Per-accelerator compute (D930). Omitted by a node that has not probed it.
62022
+ * `null` fields inside an entry are a failed query, never a zero.
62023
+ */
62024
+ accelerators: array(AcceleratorComputeSchema).readonly().optional()
61390
62025
  });
61391
62026
  var PlatformScoreSchema = object({
61392
62027
  runtime: literal("python"),
@@ -62329,6 +62964,125 @@ var ptzAutotrackCapability = {
62329
62964
  */
62330
62965
  history: "none"
62331
62966
  };
62967
+ var RUNNING_POWER_START_DELAY_MS = 3e4;
62968
+ var RUNNING_POWER_STOP_DELAY_MS = 18e4;
62969
+ var RunningStateSourceSchema = _enum(["native", "assigned"]);
62970
+ var RunningStateStatusSchema = object({
62971
+ /** null = unknown — never coerced to false (D393). */
62972
+ running: boolean().nullable(),
62973
+ /** Epoch ms the current boolean began; null while `running` is null. */
62974
+ since: number().nullable(),
62975
+ source: RunningStateSourceSchema,
62976
+ phase: string().nullable(),
62977
+ /** null until a reading has been published (D393). */
62978
+ lastFetchedAt: number().nullable()
62979
+ });
62980
+ var RunningFlipEventDataSchema = object({
62981
+ deviceId: number(),
62982
+ since: number().nullable(),
62983
+ phase: string().nullable()
62984
+ });
62985
+ var RUNNING_DEVICE_TYPES = Object.values(DeviceType);
62986
+ /** Generic Customize target for the running boolean (D936). */
62987
+ var runningCustomize = {
62988
+ version: 1,
62989
+ targets: [{
62990
+ id: "running",
62991
+ cardinality: "scalar",
62992
+ vocabulary: {
62993
+ cap: "running-state",
62994
+ stateField: "running"
62995
+ },
62996
+ deviceTypes: [
62997
+ DeviceType.Dishwasher,
62998
+ DeviceType.Vacuum,
62999
+ DeviceType.LawnMower,
63000
+ DeviceType.MediaPlayer,
63001
+ DeviceType.WaterHeater,
63002
+ DeviceType.Humidifier,
63003
+ DeviceType.Fan,
63004
+ DeviceType.Climate,
63005
+ DeviceType.Thermostat,
63006
+ DeviceType.PetFeeder
63007
+ ],
63008
+ apply: "add-or-replace",
63009
+ path: "running",
63010
+ sources: [
63011
+ {
63012
+ kind: "switch",
63013
+ transforms: [{ kind: "identity" }]
63014
+ },
63015
+ {
63016
+ kind: "binary",
63017
+ transforms: [{ kind: "identity" }, { kind: "invert" }]
63018
+ },
63019
+ {
63020
+ kind: "numeric",
63021
+ requiredUnit: "W",
63022
+ transforms: [{
63023
+ kind: "threshold",
63024
+ comparison: "gte",
63025
+ defaultThreshold: 5,
63026
+ defaultStartDwellMs: RUNNING_POWER_START_DELAY_MS,
63027
+ defaultStopDwellMs: RUNNING_POWER_STOP_DELAY_MS,
63028
+ thresholdUnit: "W"
63029
+ }]
63030
+ }
63031
+ ],
63032
+ companions: [
63033
+ {
63034
+ kind: "constant",
63035
+ path: "source",
63036
+ value: "assigned",
63037
+ when: "always"
63038
+ },
63039
+ {
63040
+ kind: "constant",
63041
+ path: "phase",
63042
+ value: null,
63043
+ when: "always"
63044
+ },
63045
+ {
63046
+ kind: "clock",
63047
+ path: "lastFetchedAt",
63048
+ when: "always"
63049
+ },
63050
+ {
63051
+ kind: "transition-time",
63052
+ path: "since",
63053
+ sourceChangedAt: "prefer"
63054
+ }
63055
+ ],
63056
+ sourceReport: {
63057
+ status: "assignment-status",
63058
+ runtimeField: "source",
63059
+ nativeValue: "native",
63060
+ assignedValue: "assigned"
63061
+ },
63062
+ advancedExpression: true
63063
+ }]
63064
+ };
63065
+ var runningStateCapability = {
63066
+ name: "running-state",
63067
+ scope: "device",
63068
+ deviceNative: true,
63069
+ mode: "singleton",
63070
+ deviceTypes: RUNNING_DEVICE_TYPES,
63071
+ methods: {},
63072
+ events: {
63073
+ onStarted: { data: RunningFlipEventDataSchema },
63074
+ onFinished: { data: RunningFlipEventDataSchema }
63075
+ },
63076
+ status: {
63077
+ schema: RunningStateStatusSchema,
63078
+ kind: "push"
63079
+ },
63080
+ runtimeState: RunningStateStatusSchema,
63081
+ durability: "restored",
63082
+ history: { fields: { running: { kind: "boolean" } } },
63083
+ volatileStateFields: ["lastFetchedAt"],
63084
+ customize: runningCustomize
63085
+ };
62332
63086
  DeviceType.Camera, DeviceType.Sensor, DeviceType.Switch, method(object({ deviceId: number().int().nonnegative() }), object({ success: literal(true) }), {
62333
63087
  kind: "mutation",
62334
63088
  auth: "admin"
@@ -64412,7 +65166,20 @@ var ZoneRuleSchema = object({
64412
65166
  * Defaults to `true` so operators creating a rule via the UI
64413
65167
  * see it active immediately.
64414
65168
  */
64415
- enabled: boolean().default(true)
65169
+ enabled: boolean().default(true),
65170
+ /**
65171
+ * Package stage only. When true, a package candidate may open from a
65172
+ * scene difference in this rule's zone after a person leaves. The
65173
+ * package model, when it boxes something overlapping, is extra evidence
65174
+ * and is not the gate. Absent or false keeps today's model path.
65175
+ */
65176
+ detectBySceneDifference: boolean().optional(),
65177
+ /**
65178
+ * Package stage only. When true, a promoted package is shown to the
65179
+ * `llm` cap before the delivery event is emitted. Absent or false emits
65180
+ * as today. Usable with or without `detectBySceneDifference`.
65181
+ */
65182
+ confirmWithLlm: boolean().optional()
64416
65183
  });
64417
65184
  array(ZoneRuleSchema).readonly();
64418
65185
  /**
@@ -66968,7 +67735,7 @@ method(object({}), array(TrainingProviderDescriptorSchema).readonly(), { auth: "
66968
67735
  * - **Jobs.** A persisted state machine, a reconcile loop against the
66969
67736
  * provider, a cost guard, a daily orphan sweep and the retention rules.
66970
67737
  * - **The return flow.** Verified artefacts → Model Studio
66971
- * (`custom-model-registry.importModelBundle`) → canary on cameras →
67738
+ * (`custom-model-registry.importModelBundle`) → canary on accelerators →
66972
67739
  * rollback. Nothing is ever registered automatically.
66973
67740
  *
66974
67741
  * Plan/start takes a live {@link TrainingCorpusSelection} (collections +
@@ -67105,20 +67872,24 @@ var TrainingProgressPointSchema = object({
67105
67872
  map50: number().nullable(),
67106
67873
  map50_95: number().nullable()
67107
67874
  });
67875
+ /** One accelerator: a `(node, inference device)` that runs the root detector. */
67876
+ var TrainingAcceleratorRefSchema = object({
67877
+ nodeId: string(),
67878
+ deviceKey: string()
67879
+ });
67880
+ /**
67881
+ * A canary pins the registered model on chosen ACCELERATORS — a model is
67882
+ * chosen by the accelerator that runs it (D927); every camera balanced onto
67883
+ * one runs it. `previous` is the root-detector pin each one had (`null` = it
67884
+ * ran its default), exactly, so rollback restores it.
67885
+ */
67108
67886
  var TrainingCanarySchema = object({
67109
- deviceIds: array(number().int()).readonly(),
67887
+ accelerators: array(TrainingAcceleratorRefSchema).readonly(),
67110
67888
  since: number(),
67111
- /** Every override the canary replaced, exactly, so rollback restores it. */
67112
- previous: array(object({
67113
- deviceId: number().int(),
67114
- nodeId: string(),
67115
- deviceKey: string(),
67116
- patch: object({
67117
- modelId: string().optional(),
67118
- settings: record(string(), unknown()).readonly().optional()
67119
- }).nullable()
67120
- })).readonly()
67889
+ previous: array(TrainingAcceleratorRefSchema.extend({ modelId: string().nullable() })).readonly()
67121
67890
  });
67891
+ /** An accelerator a canary may pin: it runs the root detector, on this model now. */
67892
+ var TrainingCanaryTargetSchema = TrainingAcceleratorRefSchema.extend({ pinnedModelId: string().nullable() });
67122
67893
  var TrainingJobSchema = object({
67123
67894
  id: string(),
67124
67895
  idempotencyKey: string(),
@@ -67230,11 +68001,11 @@ method(object({}), array(TrainingBaseModelSchema).readonly(), { auth: "admin" })
67230
68001
  kind: "mutation",
67231
68002
  auth: "admin",
67232
68003
  timeoutMs: 12e4
67233
- }), method(IdInput, TrainingResultSchema.nullable(), { auth: "admin" }), method(IdInput.extend({ canaryDeviceIds: array(number().int()).readonly() }), TrainingJobSchema, {
68004
+ }), method(IdInput, TrainingResultSchema.nullable(), { auth: "admin" }), method(_void(), array(TrainingCanaryTargetSchema).readonly(), { auth: "admin" }), method(IdInput.extend({ canaryAccelerators: array(TrainingAcceleratorRefSchema).readonly() }), TrainingJobSchema, {
67234
68005
  kind: "mutation",
67235
68006
  auth: "admin",
67236
68007
  timeoutMs: 30 * 6e4
67237
- }), method(IdInput.extend({ deviceIds: array(number().int()).min(1).readonly() }), TrainingJobSchema, {
68008
+ }), method(IdInput.extend({ accelerators: array(TrainingAcceleratorRefSchema).min(1).readonly() }), TrainingJobSchema, {
67238
68009
  kind: "mutation",
67239
68010
  auth: "admin",
67240
68011
  timeoutMs: 12e4
@@ -67730,6 +68501,7 @@ var DEVICE_LOCAL_STATE_CAPS = {
67730
68501
  ptzAutotrack: ptzAutotrackCapability,
67731
68502
  recordingOnboard: recordingOnboardCapability,
67732
68503
  recordingSignal: recordingSignalCapability,
68504
+ runningState: runningStateCapability,
67733
68505
  sceneMonitor: sceneMonitorCapability,
67734
68506
  scriptRunner: scriptRunnerCapability,
67735
68507
  smoke: smokeCapability,
@@ -71926,6 +72698,27 @@ Object.freeze({
71926
72698
  access: "create",
71927
72699
  role: "viewer"
71928
72700
  },
72701
+ "displayPalette.getPalette": {
72702
+ capName: "display-palette",
72703
+ capScope: "system",
72704
+ addonId: null,
72705
+ access: "view",
72706
+ role: "viewer"
72707
+ },
72708
+ "displayPalette.listPresets": {
72709
+ capName: "display-palette",
72710
+ capScope: "system",
72711
+ addonId: null,
72712
+ access: "view",
72713
+ role: "viewer"
72714
+ },
72715
+ "displayPalette.setPalette": {
72716
+ capName: "display-palette",
72717
+ capScope: "system",
72718
+ addonId: null,
72719
+ access: "create",
72720
+ role: "admin"
72721
+ },
71929
72722
  "doorbell.getStatus": {
71930
72723
  capName: "doorbell",
71931
72724
  capScope: "device",
@@ -74845,20 +75638,6 @@ Object.freeze({
74845
75638
  access: "create",
74846
75639
  role: "admin"
74847
75640
  },
74848
- "pipelineExecutor.clearDeviceOverrides": {
74849
- capName: "pipeline-executor",
74850
- capScope: "system",
74851
- addonId: null,
74852
- access: "delete",
74853
- role: "admin"
74854
- },
74855
- "pipelineExecutor.clearModelBoundDeviceOverrides": {
74856
- capName: "pipeline-executor",
74857
- capScope: "system",
74858
- addonId: null,
74859
- access: "delete",
74860
- role: "admin"
74861
- },
74862
75641
  "pipelineExecutor.deleteModel": {
74863
75642
  capName: "pipeline-executor",
74864
75643
  capScope: "system",
@@ -74901,13 +75680,6 @@ Object.freeze({
74901
75680
  access: "view",
74902
75681
  role: "admin"
74903
75682
  },
74904
- "pipelineExecutor.getDefaultSteps": {
74905
- capName: "pipeline-executor",
74906
- capScope: "system",
74907
- addonId: null,
74908
- access: "view",
74909
- role: "admin"
74910
- },
74911
75683
  "pipelineExecutor.getDetectionConfigSchema": {
74912
75684
  capName: "pipeline-executor",
74913
75685
  capScope: "system",
@@ -74929,20 +75701,6 @@ Object.freeze({
74929
75701
  access: "view",
74930
75702
  role: "admin"
74931
75703
  },
74932
- "pipelineExecutor.getGlobalPipelineConfig": {
74933
- capName: "pipeline-executor",
74934
- capScope: "system",
74935
- addonId: null,
74936
- access: "view",
74937
- role: "admin"
74938
- },
74939
- "pipelineExecutor.getGlobalSteps": {
74940
- capName: "pipeline-executor",
74941
- capScope: "system",
74942
- addonId: null,
74943
- access: "view",
74944
- role: "admin"
74945
- },
74946
75704
  "pipelineExecutor.getInferenceDeviceHealth": {
74947
75705
  capName: "pipeline-executor",
74948
75706
  capScope: "system",
@@ -75202,13 +75960,6 @@ Object.freeze({
75202
75960
  access: "view",
75203
75961
  role: "admin"
75204
75962
  },
75205
- "pipelineOrchestrator.getCameraStepOverrides": {
75206
- capName: "pipeline-orchestrator",
75207
- capScope: "system",
75208
- addonId: null,
75209
- access: "view",
75210
- role: "admin"
75211
- },
75212
75963
  "pipelineOrchestrator.getCameraSwitches": {
75213
75964
  capName: "pipeline-orchestrator",
75214
75965
  capScope: "system",
@@ -75447,13 +76198,6 @@ Object.freeze({
75447
76198
  access: "create",
75448
76199
  role: "admin"
75449
76200
  },
75450
- "pipelineOrchestrator.setCameraPipelineForAgent": {
75451
- capName: "pipeline-orchestrator",
75452
- capScope: "system",
75453
- addonId: null,
75454
- access: "create",
75455
- role: "admin"
75456
- },
75457
76201
  "pipelineOrchestrator.setCameraSensors": {
75458
76202
  capName: "pipeline-orchestrator",
75459
76203
  capScope: "system",
@@ -75461,42 +76205,42 @@ Object.freeze({
75461
76205
  access: "create",
75462
76206
  role: "admin"
75463
76207
  },
75464
- "pipelineOrchestrator.setCameraStepOverride": {
76208
+ "pipelineOrchestrator.setCameraStepSettings": {
75465
76209
  capName: "pipeline-orchestrator",
75466
76210
  capScope: "system",
75467
76211
  addonId: null,
75468
76212
  access: "create",
75469
76213
  role: "admin"
75470
76214
  },
75471
- "pipelineOrchestrator.setCameraStepSettings": {
76215
+ "pipelineOrchestrator.setCameraStepToggle": {
75472
76216
  capName: "pipeline-orchestrator",
75473
76217
  capScope: "system",
75474
76218
  addonId: null,
75475
76219
  access: "create",
75476
76220
  role: "admin"
75477
76221
  },
75478
- "pipelineOrchestrator.setCameraStepToggle": {
76222
+ "pipelineOrchestrator.setCameraSwitch": {
75479
76223
  capName: "pipeline-orchestrator",
75480
76224
  capScope: "system",
75481
76225
  addonId: null,
75482
76226
  access: "create",
75483
76227
  role: "admin"
75484
76228
  },
75485
- "pipelineOrchestrator.setCameraSwitch": {
76229
+ "pipelineOrchestrator.setCapabilityBinding": {
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.setCapabilityBinding": {
76236
+ "pipelineOrchestrator.setLoadBalancingShares": {
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.setLoadBalancingShares": {
76243
+ "pipelineOrchestrator.setNodeStepSettings": {
75500
76244
  capName: "pipeline-orchestrator",
75501
76245
  capScope: "system",
75502
76246
  addonId: null,
@@ -76525,6 +77269,13 @@ Object.freeze({
76525
77269
  access: "create",
76526
77270
  role: "admin"
76527
77271
  },
77272
+ "runningState.getStatus": {
77273
+ capName: "running-state",
77274
+ capScope: "device",
77275
+ addonId: null,
77276
+ access: "view",
77277
+ role: "viewer"
77278
+ },
76528
77279
  "sceneMonitor.captureReference": {
76529
77280
  capName: "scene-monitor",
76530
77281
  capScope: "device",
@@ -77855,6 +78606,13 @@ Object.freeze({
77855
78606
  access: "view",
77856
78607
  role: "admin"
77857
78608
  },
78609
+ "training.listCanaryTargets": {
78610
+ capName: "training",
78611
+ capScope: "system",
78612
+ addonId: null,
78613
+ access: "view",
78614
+ role: "admin"
78615
+ },
77858
78616
  "training.listJobs": {
77859
78617
  capName: "training",
77860
78618
  capScope: "system",
@@ -81232,6 +81990,32 @@ var APPLIANCE_CAP_VOCABULARY = {
81232
81990
  }],
81233
81991
  events: { onSent: { notOperatorFacing: "a delivery receipt of a send this system made — not a fact about the world" } }
81234
81992
  },
81993
+ "running-state": {
81994
+ scope: "device",
81995
+ noun: t("Running", "In funzione"),
81996
+ state: [{
81997
+ kind: "boolean",
81998
+ field: "running",
81999
+ label: t("Running", "In funzione"),
82000
+ whenTrue: t("When {device} starts", "Quando {device} inizia"),
82001
+ whenFalse: t("When {device} finishes", "Quando {device} finisce"),
82002
+ icon: "play"
82003
+ }],
82004
+ events: {
82005
+ onStarted: {
82006
+ category: EventCategory.RunningStarted,
82007
+ label: t("Started running", "Ha iniziato a funzionare"),
82008
+ phrase: t("When {device} starts running", "Quando {device} inizia a funzionare"),
82009
+ icon: "play"
82010
+ },
82011
+ onFinished: {
82012
+ category: EventCategory.RunningFinished,
82013
+ label: t("Finished", "Ha finito"),
82014
+ phrase: t("When {device} finishes", "Quando {device} finisce"),
82015
+ icon: "square"
82016
+ }
82017
+ }
82018
+ },
81235
82019
  update: {
81236
82020
  scope: "device",
81237
82021
  noun: t("Firmware update", "Aggiornamento firmware"),
@@ -82391,6 +83175,7 @@ var SYSTEM_CAP_VOCABULARY = {
82391
83175
  "device-provider": system(INTERNAL),
82392
83176
  "device-removal-hook": system(INTERNAL),
82393
83177
  "device-state": system("the runtime-state mirror every trigger already reads through"),
83178
+ "display-palette": system("the cluster display palette — one colour table for every client, not a device action"),
82394
83179
  "embedding-encoder": system(ML),
82395
83180
  "face-gallery": system("the face gallery — curated on its own page"),
82396
83181
  "failure-contribution": system(INTERNAL),
@@ -84447,11 +85232,6 @@ Object.freeze({
84447
85232
  form: "single",
84448
85233
  optional: false
84449
85234
  }],
84450
- "pipelineExecutor.clearModelBoundDeviceOverrides": [{
84451
- name: "deviceIds",
84452
- form: "array",
84453
- optional: true
84454
- }],
84455
85235
  "pipelineExecutor.runPipeline": [{
84456
85236
  name: "deviceId",
84457
85237
  form: "single",
@@ -84507,11 +85287,6 @@ Object.freeze({
84507
85287
  form: "array",
84508
85288
  optional: true
84509
85289
  }],
84510
- "pipelineOrchestrator.getCameraStepOverrides": [{
84511
- name: "deviceId",
84512
- form: "single",
84513
- optional: false
84514
- }],
84515
85290
  "pipelineOrchestrator.getCameraSwitches": [{
84516
85291
  name: "deviceId",
84517
85292
  form: "single",
@@ -84552,21 +85327,11 @@ Object.freeze({
84552
85327
  form: "single",
84553
85328
  optional: false
84554
85329
  }],
84555
- "pipelineOrchestrator.setCameraPipelineForAgent": [{
84556
- name: "deviceId",
84557
- form: "single",
84558
- optional: false
84559
- }],
84560
85330
  "pipelineOrchestrator.setCameraSensors": [{
84561
85331
  name: "deviceId",
84562
85332
  form: "single",
84563
85333
  optional: false
84564
85334
  }],
84565
- "pipelineOrchestrator.setCameraStepOverride": [{
84566
- name: "deviceId",
84567
- form: "single",
84568
- optional: false
84569
- }],
84570
85335
  "pipelineOrchestrator.setCameraStepSettings": [{
84571
85336
  name: "deviceId",
84572
85337
  form: "single",
@@ -84998,6 +85763,11 @@ Object.freeze({
84998
85763
  form: "single",
84999
85764
  optional: true
85000
85765
  }],
85766
+ "runningState.getStatus": [{
85767
+ name: "deviceId",
85768
+ form: "single",
85769
+ optional: false
85770
+ }],
85001
85771
  "sceneMonitor.captureReference": [{
85002
85772
  name: "deviceId",
85003
85773
  form: "single",
@@ -85244,11 +86014,6 @@ Object.freeze({
85244
86014
  form: "single",
85245
86015
  optional: false
85246
86016
  }],
85247
- "training.canaryResult": [{
85248
- name: "deviceIds",
85249
- form: "array",
85250
- optional: false
85251
- }],
85252
86017
  "update.getStatus": [{
85253
86018
  name: "deviceId",
85254
86019
  form: "single",
@@ -85501,6 +86266,96 @@ Object.freeze({
85501
86266
  "smtp-provider": "email"
85502
86267
  });
85503
86268
  DeviceType.Camera;
86269
+ 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;
86270
+ /**
86271
+ * A saved Customize assignment (D936). The schema is the type: callers use
86272
+ * `z.infer`, they do not restate the shape.
86273
+ */
86274
+ var OverrideSourceSchema = object({
86275
+ addonId: string().min(1),
86276
+ stableId: string().min(1),
86277
+ cap: string().min(1),
86278
+ fieldPath: string().min(1)
86279
+ });
86280
+ var CustomizeTransformDraftSchema = discriminatedUnion("kind", [
86281
+ object({ kind: literal("identity") }),
86282
+ object({ kind: literal("invert") }),
86283
+ object({
86284
+ kind: literal("threshold"),
86285
+ comparison: _enum(["gte", "lte"]),
86286
+ threshold: number(),
86287
+ startDwellMs: number().nonnegative(),
86288
+ stopDwellMs: number().nonnegative()
86289
+ }),
86290
+ object({
86291
+ kind: literal("linear"),
86292
+ scale: number(),
86293
+ offset: number(),
86294
+ clampMin: number().optional(),
86295
+ clampMax: number().optional()
86296
+ }),
86297
+ object({
86298
+ kind: literal("enum-map"),
86299
+ mapping: record(string(), string().nullable())
86300
+ }),
86301
+ object({ kind: literal("number") })
86302
+ ]);
86303
+ var ScalarOverrideDraftSchema = object({
86304
+ kind: literal("scalar"),
86305
+ cap: string().min(1),
86306
+ targetId: string().min(1),
86307
+ source: OverrideSourceSchema,
86308
+ transform: CustomizeTransformDraftSchema
86309
+ });
86310
+ var KeyedArrayOverrideDraftSchema = object({
86311
+ kind: literal("keyedArray"),
86312
+ cap: string().min(1),
86313
+ targetId: string().min(1),
86314
+ key: string().min(1),
86315
+ label: string().min(1),
86316
+ fieldPath: string().min(1),
86317
+ source: OverrideSourceSchema,
86318
+ transform: CustomizeTransformDraftSchema
86319
+ });
86320
+ var PulseOverrideDraftSchema = object({
86321
+ kind: literal("pulse"),
86322
+ cap: string().min(1),
86323
+ targetId: string().min(1),
86324
+ enabled: boolean(),
86325
+ debounceMs: number().nonnegative(),
86326
+ sources: array(OverrideSourceSchema).min(1)
86327
+ });
86328
+ var SpanSourceDraftSchema = OverrideSourceSchema.extend({ mode: _enum([
86329
+ "in-addition",
86330
+ "confirm",
86331
+ "replace"
86332
+ ]).optional() });
86333
+ discriminatedUnion("kind", [
86334
+ ScalarOverrideDraftSchema,
86335
+ KeyedArrayOverrideDraftSchema,
86336
+ PulseOverrideDraftSchema,
86337
+ object({
86338
+ kind: literal("span"),
86339
+ cap: string().min(1),
86340
+ targetId: string().min(1),
86341
+ timeoutMs: number().nonnegative(),
86342
+ cooldownMs: number().nonnegative().optional(),
86343
+ sources: array(SpanSourceDraftSchema)
86344
+ })
86345
+ ]);
86346
+ object({
86347
+ targetId: string().min(1),
86348
+ configured: boolean(),
86349
+ source: _enum(["native", "assigned"]),
86350
+ state: _enum([
86351
+ "active",
86352
+ "stale",
86353
+ "released",
86354
+ "unavailable"
86355
+ ]),
86356
+ reason: string().nullable()
86357
+ });
86358
+ String.raw`rose\(active(\d+), changed(\d+), (\d+(?:\.\d+)?)\)`;
85504
86359
  var G711_SCALE_CORRECTION_DB = {
85505
86360
  PCMU: 20 * Math.log10(4),
85506
86361
  PCMA: 20 * Math.log10(8)
@@ -85553,40 +86408,7 @@ var NC_AUDIO_DEFAULTS = {
85553
86408
  samplingSeconds: 10
85554
86409
  };
85555
86410
  new Set(["devices", "classes"]);
85556
- /**
85557
- * WHICH narrowing filter speaks about WHICH system-event kind — one predicate,
85558
- * consumed by the rule ENGINE and by every rule EDITOR.
85559
- *
85560
- * ── The failure this file exists for ───────────────────────────────────────
85561
- * `NcSystemEventConditionSchema` carries four optional narrowing lists
85562
- * (`deviceIds`, `deviceTypes`, `nodeIds`, `packageNames`) beside a required
85563
- * `kinds` gate. They are not four filters over one vocabulary: each belongs to
85564
- * a FAMILY of kinds and is meaningless outside it. A node going away has no
85565
- * device type; a completed export has no package; `stream-offline` deliberately
85566
- * carries no device type at all (a stream belongs to a camera by construction).
85567
- *
85568
- * The engine applied all four to every kind, so a filter from one family failed
85569
- * a kind from another family CLOSED. The operator's live rule "Eventi di
85570
- * sistema" selected eleven kinds and set `deviceTypes: ['camera']` — the only
85571
- * way to say "only my cameras" about the two liveness kinds — and NINE of the
85572
- * eleven silently stopped being deliverable. Four days of history contained
85573
- * `device-online` and `device-offline` and nothing else, across a window in
85574
- * which agents were restarted and addons were updated.
85575
- *
85576
- * Both editors already computed this scoping, to decide which filter boxes to
85577
- * render; the cap's own docblock already promised it ("Narrow a `device-*` kind
85578
- * to these device TYPES"). Only the engine disagreed, and it disagreed in the
85579
- * destructive direction. So the rule is stated ONCE, here, and the engine and
85580
- * the editors are readers of it rather than three independent authors.
85581
- *
85582
- * ── The direction ─────────────────────────────────────────────────────────
85583
- * Out of family ⇒ the filter is IGNORED, never fail-closed. An editor that
85584
- * hides a box has already told the operator this filter does not speak about
85585
- * these kinds, so honouring it as an exclusion contradicts the only
85586
- * explanation the operator was ever given. Inside its family the filter still
85587
- * narrows, and still fails CLOSED on a subject that cannot produce the identity
85588
- * it tests (a device the mirror cannot name is not evidence of a camera).
85589
- */
86411
+ new Set(NC_LEGACY_SYSTEM_EVENT_KINDS);
85590
86412
  /**
85591
86413
  * Every filter, for the callers that must cover all of them (guards, tests).
85592
86414
  *
@@ -85612,9 +86434,6 @@ new Map(Object.entries({
85612
86434
  "device-battery-normal": "device-events",
85613
86435
  "device-consumable-low": "device-events",
85614
86436
  "device-consumable-normal": "device-events",
85615
- "device-tank-low": "device-events",
85616
- "device-tank-full": "device-events",
85617
- "device-tank-normal": "device-events",
85618
86437
  "stream-online": "device-events",
85619
86438
  "stream-offline": "device-events",
85620
86439
  "detection-blind": "device-events",
@@ -85691,16 +86510,6 @@ var NC_SYSTEM_EVENT_KIND_GROUP_SPECS = [
85691
86510
  label: "Consumables",
85692
86511
  kinds: ["device-consumable-low", "device-consumable-normal"]
85693
86512
  },
85694
- {
85695
- id: "tanks",
85696
- family: "device-events",
85697
- label: "Tanks",
85698
- kinds: [
85699
- "device-tank-low",
85700
- "device-tank-full",
85701
- "device-tank-normal"
85702
- ]
85703
- },
85704
86513
  {
85705
86514
  id: "detection-blind",
85706
86515
  family: "device-events",
@@ -85858,11 +86667,6 @@ var RULE_BODY_ONLY = ["body"];
85858
86667
  var RULE_TEXT = ["title", "body"];
85859
86668
  var BATTERY = ["device-battery-low", "device-battery-normal"];
85860
86669
  var CONSUMABLE = ["device-consumable-low", "device-consumable-normal"];
85861
- var TANK = [
85862
- "device-tank-low",
85863
- "device-tank-full",
85864
- "device-tank-normal"
85865
- ];
85866
86670
  var ALERT_EPISODE = [
85867
86671
  "alert-critical",
85868
86672
  "alert-error",
@@ -85894,7 +86698,6 @@ var DEVICE_EVENTS = [
85894
86698
  "device-enabled",
85895
86699
  ...BATTERY,
85896
86700
  ...CONSUMABLE,
85897
- ...TANK,
85898
86701
  "stream-online",
85899
86702
  "stream-offline",
85900
86703
  "detection-blind",
@@ -85940,12 +86743,6 @@ var STATE_SUMMARY_SECTION_VARS = [
85940
86743
  example: "Robot — filter 10 %",
85941
86744
  kinds: CONSUMABLE
85942
86745
  },
85943
- {
85944
- name: "summaryTanks",
85945
- label: "Summary: tanks",
85946
- example: "Robot — clean water low",
85947
- kinds: TANK
85948
- },
85949
86746
  {
85950
86747
  name: "summaryDetection",
85951
86748
  label: "Summary: cameras detecting nothing",
@@ -86061,8 +86858,7 @@ var STATE_SUMMARY_VARS = [
86061
86858
  ([...RULE_TEXT], [...COMBINED_ALARM]),
86062
86859
  ([...RULE_TEXT], [...DEVICE_EVENTS]),
86063
86860
  ([...RULE_TEXT], [...BATTERY, ...CONSUMABLE]),
86064
- ([...RULE_TEXT], [...CONSUMABLE, ...TANK]),
86065
- ([...RULE_TEXT], [...TANK]),
86861
+ ([...RULE_TEXT], [...CONSUMABLE]),
86066
86862
  [...RULE_TEXT],
86067
86863
  ([...RULE_TEXT], [...UPDATES, ...ALERT_EPISODE]),
86068
86864
  ([...RULE_TEXT], [...UPDATES, ...ALERT_EPISODE]),
@@ -86166,15 +86962,6 @@ new Map([
86166
86962
  snapshotLabel: "Consumables low now",
86167
86963
  snapshotSection: "consumables"
86168
86964
  },
86169
- {
86170
- id: "tanks",
86171
- family: "device-events",
86172
- label: "Tanks (low or full / back to normal)",
86173
- bad: ["device-tank-low", "device-tank-full"],
86174
- recovery: ["device-tank-normal"],
86175
- snapshotLabel: "Tanks low or full now",
86176
- snapshotSection: "tanks"
86177
- },
86178
86965
  {
86179
86966
  id: "motion-noise",
86180
86967
  family: "device-events",
@@ -86627,6 +87414,10 @@ MotionOnMotionChangedDataSchema.omit({ triggeredBy: true });
86627
87414
  function providerMotionEvent(source, data) {
86628
87415
  return createEvent(EventCategory.ProviderMotion, source, data);
86629
87416
  }
87417
+ Object.freeze({
87418
+ person: .8,
87419
+ vehicle: .8
87420
+ });
86630
87421
  object({
86631
87422
  /**
86632
87423
  * Fraction of the box's own size added on EACH side before cutting.