@camstack/addon-provider-bosch 0.1.14 → 0.1.16

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.
@@ -1,5 +1,5 @@
1
1
  import "node:crypto";
2
- //#region ../types/dist/event-category-DOl51-Ij.mjs
2
+ //#region ../types/dist/event-category-BfJwUd2S.mjs
3
3
  var EventCategory = /* @__PURE__ */ function(EventCategory) {
4
4
  EventCategory["SystemBoot"] = "system.boot";
5
5
  EventCategory["SystemAddonsReady"] = "system.addons-ready";
@@ -316,6 +316,15 @@ var EventCategory = /* @__PURE__ */ function(EventCategory) {
316
316
  */
317
317
  EventCategory["PipelineDetectionBlind"] = "pipeline.detection-blind";
318
318
  /**
319
+ * A camera's motion source has fired constantly with no subject for an hour
320
+ * (motion duty or session count over the bar, zero detections) — it is not
321
+ * blind, its motion zones or sensitivity want tuning (D907). Paired with
322
+ * {@link PipelineMotionCalm}.
323
+ */
324
+ EventCategory["PipelineMotionNoisy"] = "pipeline.motion-noisy";
325
+ /** The recovery edge of {@link PipelineMotionNoisy}: the motion fell back, or a detection arrived. */
326
+ EventCategory["PipelineMotionCalm"] = "pipeline.motion-calm";
327
+ /**
319
328
  * Per-camera pipeline config was mutated by the orchestrator
320
329
  * (3-level settings change via `setAgentAddonDefaults` /
321
330
  * `setCameraStepToggle` / `setCameraPipelineForAgent` or a
@@ -687,6 +696,14 @@ var EventCategory = /* @__PURE__ */ function(EventCategory) {
687
696
  EventCategory["BackupRestored"] = "backup.restored";
688
697
  EventCategory["NotificationDispatched"] = "notification.dispatched";
689
698
  EventCategory["NotificationFailed"] = "notification.failed";
699
+ /**
700
+ * A notification rule that cannot work (D905): its stored row does not load,
701
+ * or it still names a device / delivery target the prune CONFIRMED deleted.
702
+ * One edge per rule per distinct set of reasons; never on an unanswered read.
703
+ */
704
+ EventCategory["NotificationRuleBroken"] = "notification.rule-broken";
705
+ /** The clear of {@link NotificationRuleBroken}: the rule loads and names nothing deleted. */
706
+ EventCategory["NotificationRuleRepaired"] = "notification.rule-repaired";
690
707
  EventCategory["DeviceUpdated"] = "device.updated";
691
708
  /**
692
709
  * Transport-level connectivity. Emitted by the device driver when
@@ -5414,7 +5431,7 @@ var ZodIssueCode = {
5414
5431
  var ZodFirstPartyTypeKind;
5415
5432
  ZodFirstPartyTypeKind || (ZodFirstPartyTypeKind = {});
5416
5433
  //#endregion
5417
- //#region ../types/dist/sleep-_sV1BE2f.mjs
5434
+ //#region ../types/dist/sleep-DJFUfKvA.mjs
5418
5435
  /**
5419
5436
  * The audio chunk plane's byte format, and the ONE expansion from a coded
5420
5437
  * window to float samples (D455).
@@ -7947,7 +7964,7 @@ var EntryDescriptorSchema = object({
7947
7964
  /** JSON Schema of the entry body; `secret: true` marks a password field. */
7948
7965
  fields: record(string(), unknown())
7949
7966
  }).strict();
7950
- /** What crosses the wire and sits in the engine's catalog: JSON only, no Zod. */
7967
+ /** What crosses the wire from an addon: JSON only, no Zod. An unknown key is refused. */
7951
7968
  var RecordKindDeclarationSchema = object({
7952
7969
  database: _enum(RECORD_DATABASES).default("settings"),
7953
7970
  class: _enum(RECORD_CLASSES),
@@ -7966,14 +7983,6 @@ var RecordKindDeclarationSchema = object({
7966
7983
  secretPaths: array(string().min(1)).default([]),
7967
7984
  /** The id key of each array that carries a secret (`{ headers: 'name' }`). */
7968
7985
  secretArrayKeys: record(string(), string()).default({}),
7969
- /**
7970
- * RETIRED (D900): the legacy table a kind adopted from during the records
7971
- * migration. Nothing declares it any more and nothing reads it; the schema
7972
- * still ACCEPTS it because the catalog rows the migration wrote carry it
7973
- * (an orphaned kind is never redeclared) and an addon built before the
7974
- * removal still sends it. Never set it.
7975
- */
7976
- adoptsFrom: string().min(1).optional(),
7977
7986
  /** Kinds that must agree through `transact` sit in one file under one family name. */
7978
7987
  transactFamily: string().min(1).optional(),
7979
7988
  entry: EntryDescriptorSchema.optional()
@@ -12673,17 +12682,6 @@ object({
12673
12682
  createdAt: number(),
12674
12683
  updatedAt: number()
12675
12684
  });
12676
- object({
12677
- id: string(),
12678
- label: string(),
12679
- isAdmin: boolean().default(false),
12680
- allowedProviders: AllowedProviderSchema,
12681
- allowedDevices: AllowedDevicesSchema,
12682
- tokenHash: string(),
12683
- tokenPrefix: string(),
12684
- createdAt: number(),
12685
- lastUsedAt: number().optional()
12686
- });
12687
12685
  object({
12688
12686
  id: string(),
12689
12687
  userId: string(),
@@ -16665,16 +16663,36 @@ var RecordKindStateSchema = _enum([
16665
16663
  var DeclareKindResultSchema = object({
16666
16664
  kindId: number().int(),
16667
16665
  state: RecordKindStateSchema,
16668
- createdIndexes: array(string()),
16669
- /**
16670
- * RETIRED (D900): always `null`. It carried the records-migration boot guard;
16671
- * it stays on the wire, null, because an addon built before the removal reads
16672
- * an ABSENT field as "adoption pending" and refuses to start.
16673
- */
16674
- adoptionPending: _null()
16666
+ createdIndexes: array(string())
16675
16667
  });
16676
16668
  /** Keychain refs a write released (the old marker is gone from the row): the owner deletes the values. */
16677
16669
  var SecretRefsList = array(string());
16670
+ /**
16671
+ * One op of a `transact`: the single-row writes, each on a kind of the caller.
16672
+ * All ops of one call share ONE database file and ONE `transactFamily`.
16673
+ */
16674
+ var RecordTransactOpSchema = discriminatedUnion("op", [
16675
+ object({
16676
+ op: literal("put"),
16677
+ kind: RecordKindNameSchema,
16678
+ record: RecordInputSchema,
16679
+ ifRev: number().int().min(0).optional()
16680
+ }),
16681
+ object({
16682
+ op: literal("patch"),
16683
+ kind: RecordKindNameSchema,
16684
+ id: RecordIdSchema,
16685
+ data: RecordBodySchema,
16686
+ at: number().int().nullable().optional(),
16687
+ expiresAt: number().int().nullable().optional(),
16688
+ ifRev: number().int().min(1).optional()
16689
+ }),
16690
+ object({
16691
+ op: literal("delete"),
16692
+ kind: RecordKindNameSchema,
16693
+ id: RecordIdSchema
16694
+ })
16695
+ ]);
16678
16696
  var RecordSecretRefsSchema = record(string(), record(string(), string()));
16679
16697
  method(object({ kinds: record(RecordKindNameSchema, RecordKindDeclarationSchema) }), object({ kinds: record(string(), DeclareKindResultSchema) }), {
16680
16698
  kind: "mutation",
@@ -16781,6 +16799,16 @@ method(object({ kinds: record(RecordKindNameSchema, RecordKindDeclarationSchema)
16781
16799
  }), {
16782
16800
  kind: "mutation",
16783
16801
  auth: "admin"
16802
+ }), method(object({ ops: array(RecordTransactOpSchema).min(1).max(RECORD_BATCH_MAX) }), object({
16803
+ results: array(object({
16804
+ rev: number().int().nullable(),
16805
+ deleted: boolean()
16806
+ })),
16807
+ releasedRefs: SecretRefsList,
16808
+ secretRefs: SecretRefsList
16809
+ }), {
16810
+ kind: "mutation",
16811
+ auth: "admin"
16784
16812
  }), method(object({
16785
16813
  deviceId: number().int(),
16786
16814
  kinds: array(RecordKindNameSchema).optional()
@@ -42392,9 +42420,13 @@ var NcSystemEventKindSchema = _enum([
42392
42420
  "node-updating",
42393
42421
  "node-inference-unavailable",
42394
42422
  "detection-blind",
42423
+ "motion-noisy",
42424
+ "motion-calm",
42395
42425
  "recording-stalled",
42396
42426
  "recording-healthy",
42397
42427
  "recording-degraded",
42428
+ "device-attention-required",
42429
+ "device-attention-resolved",
42398
42430
  "storage-location-low",
42399
42431
  "storage-location-critical",
42400
42432
  "storage-location-ok",
@@ -42418,6 +42450,8 @@ var NcSystemEventKindSchema = _enum([
42418
42450
  "alert-critical",
42419
42451
  "alert-error",
42420
42452
  "alert-critical-resolved",
42453
+ "rule-broken",
42454
+ "rule-repaired",
42421
42455
  "camera-online",
42422
42456
  "camera-offline",
42423
42457
  "camera-disabled",
@@ -55724,6 +55758,16 @@ var DishwasherStatusSchema = object({
55724
55758
  powerState: string().nullable(),
55725
55759
  saltLevel: DishwasherConsumableLevelSchema.nullable(),
55726
55760
  rinseAidLevel: DishwasherConsumableLevelSchema.nullable(),
55761
+ /**
55762
+ * True while the appliance asks for its filter to be cleaned (smart-filter, filter-system or
55763
+ * combined care-and-filter reminder raised); false when every such reminder reads clear; null
55764
+ * when none is reported. A cleared reminder is not an unknown one.
55765
+ */
55766
+ filterCleaningDue: boolean().nullable(),
55767
+ /** True while the machine-care (descaling / cleaning-program) reminder is raised; false when clear; null when not reported. */
55768
+ machineCareDue: boolean().nullable(),
55769
+ /** Program runs left before the machine-care reminder is due; null when the appliance does not say. */
55770
+ machineCareRemainingRuns: number().int().nonnegative().nullable(),
55727
55771
  /** Option states: null when the appliance does not expose the option or has not said. */
55728
55772
  halfLoad: boolean().nullable(),
55729
55773
  hygienePlus: boolean().nullable(),
@@ -64374,16 +64418,6 @@ var UpdateUserInputSchema = object({
64374
64418
  allowedDevices: record(string(), union([array(string()), literal("*")])).optional(),
64375
64419
  scopes: array(TokenScopeSchema).optional()
64376
64420
  });
64377
- var ApiKeySummarySchema = object({
64378
- id: string(),
64379
- label: string(),
64380
- isAdmin: boolean().default(false),
64381
- allowedProviders: union([array(string()), literal("*")]).optional(),
64382
- allowedDevices: record(string(), union([array(string()), literal("*")])).optional(),
64383
- tokenPrefix: string(),
64384
- createdAt: number(),
64385
- lastUsedAt: number().optional()
64386
- });
64387
64421
  var OauthSessionSummarySchema = object({
64388
64422
  id: string(),
64389
64423
  userId: string(),
@@ -64405,8 +64439,7 @@ var TotpStatusSchema = object({
64405
64439
  confirmedAt: number().nullable()
64406
64440
  });
64407
64441
  /**
64408
- * user-management — singleton capability for user accounts and the
64409
- * legacy API-key rows.
64442
+ * user-management — singleton capability for user accounts.
64410
64443
  *
64411
64444
  * v2 model: every method gated by `auth: 'admin'`. Admin-only delegation
64412
64445
  * — the subset check on `setUserScopes` is moot
@@ -64462,10 +64495,6 @@ method(_void(), array(UserSummarySchema), { auth: "admin" }), method(CreateUserI
64462
64495
  }), UserSummarySchema.extend({ passwordHash: string() }).nullable(), {
64463
64496
  kind: "mutation",
64464
64497
  access: "view"
64465
- }), method(_void(), array(ApiKeySummarySchema), { auth: "admin" }), method(object({ id: string() }), object({ success: literal(true) }), {
64466
- kind: "mutation",
64467
- auth: "admin",
64468
- access: "delete"
64469
64498
  }), method(object({ userId: string() }), TotpSetupResultSchema, {
64470
64499
  kind: "mutation",
64471
64500
  auth: "admin",
@@ -73921,6 +73950,12 @@ Object.freeze({
73921
73950
  addonId: null,
73922
73951
  access: "view"
73923
73952
  },
73953
+ "records.transact": {
73954
+ capName: "records",
73955
+ capScope: "system",
73956
+ addonId: null,
73957
+ access: "create"
73958
+ },
73924
73959
  "sceneMonitor.captureReference": {
73925
73960
  capName: "scene-monitor",
73926
73961
  capScope: "device",
@@ -75253,12 +75288,6 @@ Object.freeze({
75253
75288
  addonId: null,
75254
75289
  access: "view"
75255
75290
  },
75256
- "userManagement.listApiKeys": {
75257
- capName: "user-management",
75258
- capScope: "system",
75259
- addonId: null,
75260
- access: "view"
75261
- },
75262
75291
  "userManagement.listExternalIdentities": {
75263
75292
  capName: "user-management",
75264
75293
  capScope: "system",
@@ -75313,12 +75342,6 @@ Object.freeze({
75313
75342
  addonId: null,
75314
75343
  access: "create"
75315
75344
  },
75316
- "userManagement.revokeApiKey": {
75317
- capName: "user-management",
75318
- capScope: "system",
75319
- addonId: null,
75320
- access: "delete"
75321
- },
75322
75345
  "userManagement.revokeOauthSession": {
75323
75346
  capName: "user-management",
75324
75347
  capScope: "system",
@@ -78683,9 +78706,13 @@ new Map(Object.entries({
78683
78706
  "stream-online": "device-events",
78684
78707
  "stream-offline": "device-events",
78685
78708
  "detection-blind": "device-events",
78709
+ "motion-noisy": "device-events",
78710
+ "motion-calm": "device-events",
78686
78711
  "recording-stalled": "device-events",
78687
78712
  "recording-healthy": "device-events",
78688
78713
  "recording-degraded": "device-events",
78714
+ "device-attention-required": "device-events",
78715
+ "device-attention-resolved": "device-events",
78689
78716
  "node-online": "system",
78690
78717
  "node-offline": "system",
78691
78718
  "node-restarting": "system",
@@ -78702,6 +78729,8 @@ new Map(Object.entries({
78702
78729
  "alert-critical": "system",
78703
78730
  "alert-error": "system",
78704
78731
  "alert-critical-resolved": "system",
78732
+ "rule-broken": "system",
78733
+ "rule-repaired": "system",
78705
78734
  "storage-location-low": "system",
78706
78735
  "storage-location-critical": "system",
78707
78736
  "storage-location-ok": "system",
@@ -78766,6 +78795,12 @@ var NC_SYSTEM_EVENT_KIND_GROUP_SPECS = [
78766
78795
  label: "Detecting nothing",
78767
78796
  kinds: ["detection-blind"]
78768
78797
  },
78798
+ {
78799
+ id: "motion-noise",
78800
+ family: "device-events",
78801
+ label: "Motion without a subject",
78802
+ kinds: ["motion-noisy", "motion-calm"]
78803
+ },
78769
78804
  {
78770
78805
  id: "recording",
78771
78806
  family: "device-events",
@@ -78776,6 +78811,12 @@ var NC_SYSTEM_EVENT_KIND_GROUP_SPECS = [
78776
78811
  "recording-degraded"
78777
78812
  ]
78778
78813
  },
78814
+ {
78815
+ id: "device-attention",
78816
+ family: "device-events",
78817
+ label: "Needs attention",
78818
+ kinds: ["device-attention-required", "device-attention-resolved"]
78819
+ },
78779
78820
  {
78780
78821
  id: "nodes",
78781
78822
  family: "system",
@@ -78836,6 +78877,12 @@ var NC_SYSTEM_EVENT_KIND_GROUP_SPECS = [
78836
78877
  "alert-critical-resolved"
78837
78878
  ]
78838
78879
  },
78880
+ {
78881
+ id: "rule-health",
78882
+ family: "system",
78883
+ label: "Notification rules",
78884
+ kinds: ["rule-broken", "rule-repaired"]
78885
+ },
78839
78886
  {
78840
78887
  id: "alarm",
78841
78888
  family: "alarm",
@@ -78909,6 +78956,7 @@ var ALERT_EPISODE = [
78909
78956
  "alert-error",
78910
78957
  "alert-critical-resolved"
78911
78958
  ];
78959
+ var DEVICE_ATTENTION = ["device-attention-required", "device-attention-resolved"];
78912
78960
  var UPDATES = [
78913
78961
  "addon-update-available",
78914
78962
  "server-update-available",
@@ -78938,9 +78986,12 @@ var DEVICE_EVENTS = [
78938
78986
  "stream-online",
78939
78987
  "stream-offline",
78940
78988
  "detection-blind",
78989
+ "motion-noisy",
78990
+ "motion-calm",
78941
78991
  "recording-stalled",
78942
78992
  "recording-healthy",
78943
78993
  "recording-degraded",
78994
+ ...DEVICE_ATTENTION,
78944
78995
  ...ALARM
78945
78996
  ];
78946
78997
  /** Every kind a summary may speak about — the two summarisable families. */
@@ -79108,7 +79159,13 @@ var STATE_SUMMARY_VARS = [
79108
79159
  [...RULE_TEXT],
79109
79160
  [...RULE_TEXT],
79110
79161
  [...RULE_TEXT],
79111
- ([...RULE_TEXT], [...ALERT_EPISODE]),
79162
+ [...RULE_TEXT],
79163
+ [...RULE_TEXT],
79164
+ ([...RULE_TEXT], [...DEVICE_ATTENTION, ...ALERT_EPISODE]),
79165
+ [...RULE_TEXT],
79166
+ [...RULE_TEXT],
79167
+ [...RULE_TEXT],
79168
+ [...RULE_TEXT],
79112
79169
  [...RULE_TEXT],
79113
79170
  [...RULE_TEXT],
79114
79171
  [...RULE_TEXT],
@@ -79126,11 +79183,11 @@ var STATE_SUMMARY_VARS = [
79126
79183
  [...RULE_TEXT],
79127
79184
  [...RULE_TEXT],
79128
79185
  [...RULE_TEXT],
79186
+ ([...RULE_TEXT], [...DEVICE_ATTENTION, ...ALERT_EPISODE]),
79129
79187
  ([...RULE_TEXT], [...ALERT_EPISODE]),
79188
+ ([...RULE_TEXT], [...DEVICE_ATTENTION, ...ALERT_EPISODE]),
79130
79189
  ([...RULE_TEXT], [...ALERT_EPISODE]),
79131
- ([...RULE_TEXT], [...ALERT_EPISODE]),
79132
- ([...RULE_TEXT], [...ALERT_EPISODE]),
79133
- ([...RULE_TEXT], [...ALERT_EPISODE]),
79190
+ ([...RULE_TEXT], [...DEVICE_ATTENTION, ...ALERT_EPISODE]),
79134
79191
  [...RULE_TEXT],
79135
79192
  [...RULE_TEXT],
79136
79193
  [...RULE_TEXT],
@@ -79151,6 +79208,125 @@ var STATE_SUMMARY_VARS = [
79151
79208
  [...RULE_TEXT],
79152
79209
  ...STATE_SUMMARY_VARS
79153
79210
  ];
79211
+ new Map([
79212
+ {
79213
+ id: "device-connectivity",
79214
+ family: "device-events",
79215
+ label: "Device connectivity (offline / back online)",
79216
+ bad: ["device-offline"],
79217
+ recovery: ["device-online"],
79218
+ snapshotLabel: "Devices offline now",
79219
+ snapshotSection: "device-state"
79220
+ },
79221
+ {
79222
+ id: "device-switch",
79223
+ family: "device-events",
79224
+ label: "Device switched off / back on",
79225
+ bad: ["device-disabled"],
79226
+ recovery: ["device-enabled"],
79227
+ snapshotLabel: "Devices switched off now",
79228
+ snapshotSection: "device-state"
79229
+ },
79230
+ {
79231
+ id: "stream-connectivity",
79232
+ family: "device-events",
79233
+ label: "Stream connectivity (offline / back online)",
79234
+ bad: ["stream-offline"],
79235
+ recovery: ["stream-online"],
79236
+ snapshotLabel: "Streams offline now",
79237
+ snapshotSection: "streams"
79238
+ },
79239
+ {
79240
+ id: "battery",
79241
+ family: "device-events",
79242
+ label: "Battery (low / back to normal)",
79243
+ bad: ["device-battery-low"],
79244
+ recovery: ["device-battery-normal"],
79245
+ snapshotLabel: "Batteries low now",
79246
+ snapshotSection: "battery"
79247
+ },
79248
+ {
79249
+ id: "consumables",
79250
+ family: "device-events",
79251
+ label: "Consumables (low / replaced)",
79252
+ bad: ["device-consumable-low"],
79253
+ recovery: ["device-consumable-normal"],
79254
+ snapshotLabel: "Consumables low now",
79255
+ snapshotSection: "consumables"
79256
+ },
79257
+ {
79258
+ id: "tanks",
79259
+ family: "device-events",
79260
+ label: "Tanks (low or full / back to normal)",
79261
+ bad: ["device-tank-low", "device-tank-full"],
79262
+ recovery: ["device-tank-normal"],
79263
+ snapshotLabel: "Tanks low or full now",
79264
+ snapshotSection: "tanks"
79265
+ },
79266
+ {
79267
+ id: "motion-noise",
79268
+ family: "device-events",
79269
+ label: "Motion without a subject (constant / calm again)",
79270
+ bad: ["motion-noisy"],
79271
+ recovery: ["motion-calm"],
79272
+ snapshotLabel: "Cameras with constant motion now",
79273
+ snapshotSection: null
79274
+ },
79275
+ {
79276
+ id: "recording-health",
79277
+ family: "device-events",
79278
+ label: "Recording health (stalled or degraded / recording again)",
79279
+ bad: ["recording-stalled", "recording-degraded"],
79280
+ recovery: ["recording-healthy"],
79281
+ snapshotLabel: "Recordings stalled now",
79282
+ snapshotSection: null
79283
+ },
79284
+ {
79285
+ id: "device-attention",
79286
+ family: "device-events",
79287
+ label: "Device needs attention (raised / resolved)",
79288
+ bad: ["device-attention-required"],
79289
+ recovery: ["device-attention-resolved"],
79290
+ snapshotLabel: "Devices needing attention now",
79291
+ snapshotSection: null
79292
+ },
79293
+ {
79294
+ id: "node-connectivity",
79295
+ family: "system",
79296
+ label: "Node connectivity (offline / back online)",
79297
+ bad: ["node-offline"],
79298
+ recovery: ["node-online"],
79299
+ snapshotLabel: "Nodes offline now",
79300
+ snapshotSection: "nodes"
79301
+ },
79302
+ {
79303
+ id: "storage-space",
79304
+ family: "system",
79305
+ label: "Storage space (low or critical / ok again)",
79306
+ bad: ["storage-location-low", "storage-location-critical"],
79307
+ recovery: ["storage-location-ok"],
79308
+ snapshotLabel: "Storage locations low now",
79309
+ snapshotSection: null
79310
+ },
79311
+ {
79312
+ id: "critical-alerts",
79313
+ family: "system",
79314
+ label: "Critical alerts (raised / resolved)",
79315
+ bad: ["alert-critical"],
79316
+ recovery: ["alert-critical-resolved"],
79317
+ snapshotLabel: "Critical alerts open now",
79318
+ snapshotSection: null
79319
+ },
79320
+ {
79321
+ id: "rule-health",
79322
+ family: "system",
79323
+ label: "Rule health (broken / repaired)",
79324
+ bad: ["rule-broken"],
79325
+ recovery: ["rule-repaired"],
79326
+ snapshotLabel: "Notification rules broken now",
79327
+ snapshotSection: null
79328
+ }
79329
+ ].flatMap((spec) => [...spec.bad, ...spec.recovery].map((kind) => [kind, spec])));
79154
79330
  new Set([
79155
79331
  "disarmed",
79156
79332
  "armed_home",
@@ -1,6 +1,6 @@
1
1
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
- const require_dist = require("../dist-CPBdrxct.js");
3
- const require_account_integration_offline = require("../account-integration-offline-Bk-vELSf.js");
2
+ const require_dist = require("../dist-BUFPeAeI.js");
3
+ const require_account_integration_offline = require("../account-integration-offline-BTvqsjjH.js");
4
4
  let node_crypto = require("node:crypto");
5
5
  let node_tls = require("node:tls");
6
6
  let node_zlib = require("node:zlib");
@@ -1400,7 +1400,7 @@ function buildHomeConnectFormSchema() {
1400
1400
  id: "gateway",
1401
1401
  title: "Home Connect",
1402
1402
  titleKey: "provider-bosch:home-connect.s_gateway.title",
1403
- description: "Create the login link and open it in a browser, then sign in. The browser cannot open the app and stops on an address starting with hcauth://auth/prod?code=. Paste that whole address below (or only the code) and press Complete sign-in. The address is shown in Chrome and Edge under DevTools (F12) > Network, with Preserve log ticked before you sign in: select the last redirect and copy its Location header. In Firefox use Network > Headers > Location; in Safari use Develop > Show Web Inspector > Network. A code works once and expires within minutes. The appliances are then downloaded and spoken to on the local network.",
1403
+ description: "Open the login link, sign in, then paste the address the browser stops on (hcauth://auth/prod?code=…). Chrome: DevTools > Network > last redirect > Location.",
1404
1404
  descriptionKey: "provider-bosch:home-connect.s_gateway.description",
1405
1405
  columns: 1,
1406
1406
  fields: [
@@ -3785,6 +3785,16 @@ function consumableFromEvents(view, nearlyEmpty, empty) {
3785
3785
  if (gone.includes(false) || nearly.includes(false)) return "ok";
3786
3786
  return null;
3787
3787
  }
3788
+ /** Any listed reminder raised → `true`; else any reading clear → `false`; none reported → `null`. */
3789
+ function reminderDue(view, shortNames) {
3790
+ const states = eventStates(view, shortNames);
3791
+ if (states.includes(true)) return true;
3792
+ return states.includes(false) ? false : null;
3793
+ }
3794
+ /** A non-negative whole count, or `null`. */
3795
+ function countOf(raw) {
3796
+ return typeof raw === "number" && Number.isInteger(raw) && raw >= 0 ? raw : null;
3797
+ }
3788
3798
  function programKey(raw) {
3789
3799
  return stringOf(raw);
3790
3800
  }
@@ -3818,6 +3828,9 @@ var COLD_DISHWASHER_STATUS = {
3818
3828
  powerState: null,
3819
3829
  saltLevel: null,
3820
3830
  rinseAidLevel: null,
3831
+ filterCleaningDue: null,
3832
+ machineCareDue: null,
3833
+ machineCareRemainingRuns: null,
3821
3834
  halfLoad: null,
3822
3835
  hygienePlus: null,
3823
3836
  extraDry: null,
@@ -3874,6 +3887,13 @@ function dishwasherStatusFromFeatures(input) {
3874
3887
  powerState: powerRaw,
3875
3888
  saltLevel: consumableFromEvents(input, ["SaltNearlyEmpty"], ["SaltEmpty", "SaltLack"]),
3876
3889
  rinseAidLevel: consumableFromEvents(input, ["RinseAidNearlyEmpty"], ["RinseAidEmpty", "RinseAidLack"]),
3890
+ filterCleaningDue: reminderDue(input, [
3891
+ "SmartFilterCleaningReminder",
3892
+ "CheckFilterSystem",
3893
+ "MachineCareAndFilterCleaningReminder"
3894
+ ]),
3895
+ machineCareDue: reminderDue(input, ["MachineCareReminder", "MachineCareAndFilterCleaningReminder"]),
3896
+ machineCareRemainingRuns: countOf(valueOf(input, findEntity(description, ["status"], ["RemainingProgramRuns"]))),
3877
3897
  halfLoad: optionBool(input, ["HalfLoad"]),
3878
3898
  hygienePlus: optionBool(input, ["HygienePlus"]),
3879
3899
  extraDry: optionBool(input, ["ExtraDry"]),
@@ -4219,7 +4239,7 @@ var LEGACY_CHILD_KEYS = {
4219
4239
  role: require_dist.DeviceRole.NumericSensor
4220
4240
  },
4221
4241
  "remote-control-level": {
4222
- key: "BSH.Common.Status.RemoteControlLevel",
4242
+ key: "BSH.Common.Setting.RemoteControlLevel",
4223
4243
  cap: "enum-sensor",
4224
4244
  role: require_dist.DeviceRole.EnumSensor
4225
4245
  },
@@ -4245,6 +4265,28 @@ var LEGACY_CHILD_KEYS = {
4245
4265
  }
4246
4266
  };
4247
4267
  /**
4268
+ * Keys the old fixed catalog guessed WRONG and persisted, mapped to the key the appliance really
4269
+ * lists. The remote-control level is a SETTING; the catalog filed it as a status, so a container
4270
+ * saved then carries `remote-control-level` on a key no description has, next to the derived
4271
+ * child the real key produced — one label, two devices.
4272
+ */
4273
+ var SUPERSEDED_LEGACY_KEYS = { "BSH.Common.Status.RemoteControlLevel": "BSH.Common.Setting.RemoteControlLevel" };
4274
+ /**
4275
+ * A persisted binding with a superseded legacy key re-pointed at the real one (same suffix, so
4276
+ * the same device); every other binding unchanged.
4277
+ */
4278
+ function withCurrentLegacyKey(binding) {
4279
+ const current = SUPERSEDED_LEGACY_KEYS[binding.key];
4280
+ return current === void 0 ? binding : {
4281
+ ...binding,
4282
+ key: current
4283
+ };
4284
+ }
4285
+ /** Whether a suffix is the one a key would derive — i.e. not an identity inherited from the old catalog. */
4286
+ function isDerivedSuffix(binding) {
4287
+ return binding.stableIdSuffix === slugFeatureKey(binding.key);
4288
+ }
4289
+ /**
4248
4290
  * The bindings that keep a container's EXISTING children alive until its description has been
4249
4291
  * read once: a container saved with the old fixed `children` list has no `entities` yet, and a
4250
4292
  * spec without those children would make the kernel delete them (removal by absence) before any
@@ -4288,6 +4330,20 @@ function keysMissingFromDescription(persisted, description) {
4288
4330
  return new Set(persisted.filter((b) => !isSyntheticKey(b.key) && description.entityByName(b.key) === void 0).map((b) => b.key));
4289
4331
  }
4290
4332
  /**
4333
+ * One row per Home Connect key. Two rows on one key are one entity filed twice (an identity from
4334
+ * the old catalog and the one derivation gave it): the older identity — the suffix that is NOT
4335
+ * the key's own slug — is the device the operator already has, so it stays and the twin leaves
4336
+ * (the kernel removes a child its spec no longer lists).
4337
+ */
4338
+ function oneRowPerKey(rows) {
4339
+ const byKey = /* @__PURE__ */ new Map();
4340
+ for (const row of rows) {
4341
+ const held = byKey.get(row.key);
4342
+ if (held === void 0 || isDerivedSuffix(held) && !isDerivedSuffix(row)) byKey.set(row.key, row);
4343
+ }
4344
+ return [...byKey.values()];
4345
+ }
4346
+ /**
4291
4347
  * The bindings a container should carry: what the description derives now, plus what it
4292
4348
  * already had. A child leaves only when its entity is missing from TWO agreeing reads (D49):
4293
4349
  * `missingBefore` is what the previous read lacked — one description that omits an entity is
@@ -4296,10 +4352,11 @@ function keysMissingFromDescription(persisted, description) {
4296
4352
  * derived model (legacy children) keeps its device ids instead of being rebuilt.
4297
4353
  */
4298
4354
  function mergeChildBindings(persisted, derived, description, missingBefore = /* @__PURE__ */ new Set()) {
4299
- const missingNow = keysMissingFromDescription(persisted, description);
4355
+ const rows = oneRowPerKey(persisted.map(withCurrentLegacyKey));
4356
+ const missingNow = keysMissingFromDescription(rows, description);
4300
4357
  const out = /* @__PURE__ */ new Map();
4301
4358
  const suffixByKey = /* @__PURE__ */ new Map();
4302
- for (const kept of persisted) {
4359
+ for (const kept of rows) {
4303
4360
  if (missingNow.has(kept.key) && missingBefore.has(kept.key)) continue;
4304
4361
  out.set(kept.stableIdSuffix, kept);
4305
4362
  suffixByKey.set(kept.key, kept);