@camstack/addon-provider-homeassistant 1.2.653 → 1.2.655

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.
package/dist/addon.js CHANGED
@@ -1,5 +1,5 @@
1
1
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
- const require_ha_broker_source = require("./ha-broker-source-DnSL-mbs.js");
2
+ const require_ha_instance_settings = require("./ha-instance-settings-5Ms7yRju.js");
3
3
  let node_crypto = require("node:crypto");
4
4
  let node_zlib = require("node:zlib");
5
5
  //#region src/ha-admin-link.ts
@@ -72,21 +72,21 @@ function registerHaAdminLink(ctx, deviceId, brokerId, subject) {
72
72
  });
73
73
  return null;
74
74
  };
75
- ctx.registerNativeCap(require_ha_broker_source.deviceAdminLinkCapability, { getAdminLink: async (input) => {
75
+ ctx.registerNativeCap(require_ha_instance_settings.deviceAdminLinkCapability, { getAdminLink: async (input) => {
76
76
  if (input.deviceId !== deviceId) throw new Error(`HaAdminLink: deviceId mismatch, expected ${deviceId}, got ${input.deviceId}`);
77
77
  if (cachedBaseUrl === null) {
78
78
  const raw = (await ctx.api.broker.getBrokerConfig.query({ id: brokerId }))?.["baseUrl"];
79
79
  if (typeof raw !== "string" || raw.length === 0) return refuse("no-base-url");
80
80
  cachedBaseUrl = raw;
81
81
  }
82
- const base = require_ha_broker_source.parseAdminBase(cachedBaseUrl);
82
+ const base = require_ha_instance_settings.parseAdminBase(cachedBaseUrl);
83
83
  if (!base.ok) {
84
84
  cachedBaseUrl = null;
85
85
  return refuse("base-unusable", { baseReason: base.reason });
86
86
  }
87
87
  const page = pageFor(subject, base.basePath);
88
88
  if (page === null) return refuse("empty-subject");
89
- const built = require_ha_broker_source.buildDeviceAdminUrl({
89
+ const built = require_ha_instance_settings.buildDeviceAdminUrl({
90
90
  host: base.host,
91
91
  port: base.port,
92
92
  scheme: base.scheme,
@@ -114,25 +114,25 @@ function registerHaAdminLink(ctx, deviceId, brokerId, subject) {
114
114
  * `readHaSource` (returns null) — do NOT use `z.object(haSourceSchemaFields).parse`.
115
115
  */
116
116
  var haSourceSchemaFields = {
117
- system: require_ha_broker_source.literal("homeassistant").optional(),
118
- brokerId: require_ha_broker_source.string(),
119
- haDeviceId: require_ha_broker_source.string().optional(),
120
- entityId: require_ha_broker_source.string().optional(),
121
- referenceEntityId: require_ha_broker_source.string().nullable().optional(),
122
- capabilities: require_ha_broker_source.array(require_ha_broker_source.string()).default([]),
123
- role: require_ha_broker_source.string().optional(),
124
- childDeviceIds: require_ha_broker_source.array(require_ha_broker_source.number()).default([]),
125
- unitOfMeasurement: require_ha_broker_source.string().optional(),
126
- deviceClass: require_ha_broker_source.string().optional(),
127
- integrationId: require_ha_broker_source.string().optional(),
128
- options: require_ha_broker_source.array(require_ha_broker_source.string()).optional(),
129
- features: require_ha_broker_source.array(require_ha_broker_source.string()).optional(),
117
+ system: require_ha_instance_settings.literal("homeassistant").optional(),
118
+ brokerId: require_ha_instance_settings.string(),
119
+ haDeviceId: require_ha_instance_settings.string().optional(),
120
+ entityId: require_ha_instance_settings.string().optional(),
121
+ referenceEntityId: require_ha_instance_settings.string().nullable().optional(),
122
+ capabilities: require_ha_instance_settings.array(require_ha_instance_settings.string()).default([]),
123
+ role: require_ha_instance_settings.string().optional(),
124
+ childDeviceIds: require_ha_instance_settings.array(require_ha_instance_settings.number()).default([]),
125
+ unitOfMeasurement: require_ha_instance_settings.string().optional(),
126
+ deviceClass: require_ha_instance_settings.string().optional(),
127
+ integrationId: require_ha_instance_settings.string().optional(),
128
+ options: require_ha_instance_settings.array(require_ha_instance_settings.string()).optional(),
129
+ features: require_ha_instance_settings.array(require_ha_instance_settings.string()).optional(),
130
130
  /** Sibling meter sensors whose readings this entity carries as `power-meter` (D951). */
131
- meterEntities: require_ha_broker_source.object({
132
- power: require_ha_broker_source.string().optional(),
133
- energy: require_ha_broker_source.string().optional(),
134
- voltage: require_ha_broker_source.string().optional(),
135
- current: require_ha_broker_source.string().optional()
131
+ meterEntities: require_ha_instance_settings.object({
132
+ power: require_ha_instance_settings.string().optional(),
133
+ energy: require_ha_instance_settings.string().optional(),
134
+ voltage: require_ha_instance_settings.string().optional(),
135
+ current: require_ha_instance_settings.string().optional()
136
136
  }).optional()
137
137
  };
138
138
  /** Project a persisted config blob into a typed source, or null when the
@@ -176,7 +176,7 @@ function readHaSource(config) {
176
176
  function attachAccessoriesCap(ctx, deviceId, opts) {
177
177
  let childIds = [];
178
178
  const hidden = new Set(opts.initialHidden);
179
- ctx.registerNativeCap(require_ha_broker_source.accessoriesCapability, {
179
+ ctx.registerNativeCap(require_ha_instance_settings.accessoriesCapability, {
180
180
  getStatus: async () => ({
181
181
  childDeviceIds: childIds,
182
182
  hiddenChildIds: [...hidden]
@@ -193,7 +193,7 @@ function attachAccessoriesCap(ctx, deviceId, opts) {
193
193
  type: "device",
194
194
  id: deviceId
195
195
  },
196
- category: require_ha_broker_source.EventCategory.AccessoriesChildVisibilityChanged,
196
+ category: require_ha_instance_settings.EventCategory.AccessoriesChildVisibilityChanged,
197
197
  data: {
198
198
  deviceId,
199
199
  childDeviceId,
@@ -211,7 +211,7 @@ function attachAccessoriesCap(ctx, deviceId, opts) {
211
211
  type: "device",
212
212
  id: deviceId
213
213
  },
214
- category: require_ha_broker_source.EventCategory.AccessoriesChanged,
214
+ category: require_ha_instance_settings.EventCategory.AccessoriesChanged,
215
215
  data: {
216
216
  deviceId,
217
217
  childDeviceIds: childIds,
@@ -232,23 +232,23 @@ function attachAccessoriesCap(ctx, deviceId, opts) {
232
232
  * in the materialisation factory (Phase E) where each domain becomes
233
233
  * its own DeviceType + cap set.
234
234
  */
235
- var HaEntityStateSchema = require_ha_broker_source.object({
236
- entity_id: require_ha_broker_source.string().min(1),
235
+ var HaEntityStateSchema = require_ha_instance_settings.object({
236
+ entity_id: require_ha_instance_settings.string().min(1),
237
237
  /** Domain-specific state value (`on`/`off`/`open`/temperature
238
238
  * number-as-string/etc.). Always a string in HA. */
239
- state: require_ha_broker_source.string(),
239
+ state: require_ha_instance_settings.string(),
240
240
  /** Free-form attribute map. Domain-specific. */
241
- attributes: require_ha_broker_source.record(require_ha_broker_source.string(), require_ha_broker_source.unknown()),
241
+ attributes: require_ha_instance_settings.record(require_ha_instance_settings.string(), require_ha_instance_settings.unknown()),
242
242
  /** Optional context envelope (user/parent id) the HA server attaches. */
243
- context: require_ha_broker_source.object({
244
- id: require_ha_broker_source.string(),
245
- parent_id: require_ha_broker_source.string().nullable(),
246
- user_id: require_ha_broker_source.string().nullable()
243
+ context: require_ha_instance_settings.object({
244
+ id: require_ha_instance_settings.string(),
245
+ parent_id: require_ha_instance_settings.string().nullable(),
246
+ user_id: require_ha_instance_settings.string().nullable()
247
247
  }).optional(),
248
248
  /** ISO 8601 timestamp of the last state change. */
249
- last_changed: require_ha_broker_source.string(),
249
+ last_changed: require_ha_instance_settings.string(),
250
250
  /** ISO 8601 timestamp of the last update (state OR attributes). */
251
- last_updated: require_ha_broker_source.string()
251
+ last_updated: require_ha_instance_settings.string()
252
252
  });
253
253
  /**
254
254
  * Auth strategy. Two mutually-exclusive options:
@@ -259,16 +259,16 @@ var HaEntityStateSchema = require_ha_broker_source.object({
259
259
  * the addon config; the WS URL points at their HA instance
260
260
  * (`ws://ha.example:8123/api/websocket` style).
261
261
  */
262
- var HaAuthConfigSchema = require_ha_broker_source.discriminatedUnion("kind", [require_ha_broker_source.object({
263
- kind: require_ha_broker_source.literal("supervisor"),
262
+ var HaAuthConfigSchema = require_ha_instance_settings.discriminatedUnion("kind", [require_ha_instance_settings.object({
263
+ kind: require_ha_instance_settings.literal("supervisor"),
264
264
  /** Token injected by the Supervisor at runtime via env. */
265
- supervisorToken: require_ha_broker_source.string().min(1).meta({ secret: true })
266
- }), require_ha_broker_source.object({
267
- kind: require_ha_broker_source.literal("long-lived"),
265
+ supervisorToken: require_ha_instance_settings.string().min(1).meta({ secret: true })
266
+ }), require_ha_instance_settings.object({
267
+ kind: require_ha_instance_settings.literal("long-lived"),
268
268
  /** Origin URL of the HA instance (e.g. `https://ha.example:8123`). */
269
- baseUrl: require_ha_broker_source.url(),
269
+ baseUrl: require_ha_instance_settings.url(),
270
270
  /** Long-lived access token issued by the user in their HA profile. */
271
- accessToken: require_ha_broker_source.string().min(1).meta({ secret: true })
271
+ accessToken: require_ha_instance_settings.string().min(1).meta({ secret: true })
272
272
  })]);
273
273
  /** HA's standard domain enum — supported subset; future domains added
274
274
  * as integration coverage grows. */
@@ -306,7 +306,7 @@ var HaDomain = /* @__PURE__ */ function(HaDomain) {
306
306
  * an unknown unit is never guessed (D393, D944).
307
307
  */
308
308
  function takeReading(logger, deviceId, value, rawUnit, quantity) {
309
- const result = require_ha_broker_source.ingestReading({
309
+ const result = require_ha_instance_settings.ingestReading({
310
310
  value,
311
311
  rawUnit,
312
312
  quantity
@@ -367,7 +367,7 @@ function applyMeterReading(prev, field, value, lastFetchedAt) {
367
367
  lastFetchedAt
368
368
  };
369
369
  }
370
- var LOAD_TYPES = new Set(require_ha_broker_source.powerMeterCapability.deviceTypes.filter((type) => type !== require_ha_broker_source.DeviceType.Sensor));
370
+ var LOAD_TYPES = new Set(require_ha_instance_settings.powerMeterCapability.deviceTypes.filter((type) => type !== require_ha_instance_settings.DeviceType.Sensor));
371
371
  function isLoad(entity) {
372
372
  return LOAD_TYPES.has(entity.deviceType) && entity.entityCategory === void 0 && !entity.capabilities.includes("power-meter");
373
373
  }
@@ -428,7 +428,7 @@ var HaMeterCarrier = class {
428
428
  const entityId = meters[field];
429
429
  return entityId === void 0 ? [] : [[entityId, field]];
430
430
  }));
431
- this.ctx.registerNativeCap(require_ha_broker_source.powerMeterCapability, { getStatus: async () => this.runtimeState.getCapState("power-meter") ?? COLD_START$20 });
431
+ this.ctx.registerNativeCap(require_ha_instance_settings.powerMeterCapability, { getStatus: async () => this.runtimeState.getCapState("power-meter") ?? COLD_START$20 });
432
432
  this.runtimeState.setCapState("power-meter", {
433
433
  ...COLD_START$20,
434
434
  ...this.runtimeState.getCapState("power-meter")
@@ -469,7 +469,7 @@ var HaMeterCarrier = class {
469
469
  * and carries `childDeviceIds` so parent-mode devices can host the
470
470
  * accessories cap for their entity-children.
471
471
  */
472
- var haChildDeviceSchema = require_ha_broker_source.object({ ...haSourceSchemaFields });
472
+ var haChildDeviceSchema = require_ha_instance_settings.object({ ...haSourceSchemaFields });
473
473
  /**
474
474
  * Abstract base for every HA-entity-backed CamStack accessory device.
475
475
  *
@@ -490,14 +490,14 @@ var haChildDeviceSchema = require_ha_broker_source.object({ ...haSourceSchemaFie
490
490
  * own (beyond BaseDevice's auto-registered `device-status` /
491
491
  * `feature-probe`).
492
492
  */
493
- var DEVICE_FEATURE_VALUES = new Set(Object.values(require_ha_broker_source.DeviceFeature));
493
+ var DEVICE_FEATURE_VALUES = new Set(Object.values(require_ha_instance_settings.DeviceFeature));
494
494
  /** Keep only strings that are valid DeviceFeature enum values (the persisted
495
495
  * config stores them as plain strings). */
496
496
  function parseDeviceFeatures(raw) {
497
497
  if (!Array.isArray(raw)) return [];
498
498
  return raw.filter((f) => typeof f === "string" && DEVICE_FEATURE_VALUES.has(f));
499
499
  }
500
- var HaBaseChildDevice = class HaBaseChildDevice extends require_ha_broker_source.BaseDevice {
500
+ var HaBaseChildDevice = class HaBaseChildDevice extends require_ha_instance_settings.BaseDevice {
501
501
  /** Mapping-derived feature flags (e.g. `lock-open`), read from the persisted
502
502
  * config at construction. Surfaced on `device.features` (and re-published to
503
503
  * the device meta in `onActivate` via `refreshFeatures`) so the UI gates
@@ -639,7 +639,7 @@ var HaBaseChildDevice = class HaBaseChildDevice extends require_ha_broker_source
639
639
  this.deviceLogger.warn("ha-child getRawState failed to read cached state", { meta: {
640
640
  brokerId: this.brokerId,
641
641
  entityId: this.entityId,
642
- error: require_ha_broker_source.errMsg(err)
642
+ error: require_ha_instance_settings.errMsg(err)
643
643
  } });
644
644
  return null;
645
645
  }
@@ -689,7 +689,7 @@ var HaBaseChildDevice = class HaBaseChildDevice extends require_ha_broker_source
689
689
  entityId: this.entityId,
690
690
  domain,
691
691
  service,
692
- error: require_ha_broker_source.errMsg(err)
692
+ error: require_ha_instance_settings.errMsg(err)
693
693
  } });
694
694
  throw err;
695
695
  }
@@ -716,7 +716,7 @@ var HaBaseChildDevice = class HaBaseChildDevice extends require_ha_broker_source
716
716
  this.deviceLogger.warn("ha-child failed to register broker subscription", { meta: {
717
717
  entityId: this.entityId,
718
718
  brokerId: this.brokerId,
719
- error: require_ha_broker_source.errMsg(err)
719
+ error: require_ha_instance_settings.errMsg(err)
720
720
  } });
721
721
  return false;
722
722
  }
@@ -757,7 +757,7 @@ var HaBaseChildDevice = class HaBaseChildDevice extends require_ha_broker_source
757
757
  } catch (err) {
758
758
  this.deviceLogger.warn("ha-child state-push handler error", { meta: {
759
759
  entityId: this.entityId,
760
- error: require_ha_broker_source.errMsg(err)
760
+ error: require_ha_instance_settings.errMsg(err)
761
761
  } });
762
762
  }
763
763
  };
@@ -786,7 +786,7 @@ var HaButtonDevice = class extends HaBaseChildDevice {
786
786
  this.registerButtonCap();
787
787
  }
788
788
  registerButtonCap() {
789
- this.ctx.registerNativeCap(require_ha_broker_source.buttonCapability, { press: async () => {
789
+ this.ctx.registerNativeCap(require_ha_instance_settings.buttonCapability, { press: async () => {
790
790
  const domain = this.entityId.split(".")[0] ?? "button";
791
791
  if (domain === "scene") {
792
792
  await this.callHaService("scene", "turn_on");
@@ -844,7 +844,7 @@ var HaUpdateDevice = class extends HaBaseChildDevice {
844
844
  });
845
845
  }
846
846
  registerUpdateCap() {
847
- this.ctx.registerNativeCap(require_ha_broker_source.updateCapability, {
847
+ this.ctx.registerNativeCap(require_ha_instance_settings.updateCapability, {
848
848
  getStatus: async () => {
849
849
  return this.runtimeState.getCapState(UPDATE_CAP) ?? COLD_START$19;
850
850
  },
@@ -928,7 +928,7 @@ var HaSwitchDevice = class extends HaBaseChildDevice {
928
928
  });
929
929
  }
930
930
  registerSwitchCap() {
931
- this.ctx.registerNativeCap(require_ha_broker_source.switchCapability, {
931
+ this.ctx.registerNativeCap(require_ha_instance_settings.switchCapability, {
932
932
  getStatus: async () => {
933
933
  return this.runtimeState.getCapState("switch") ?? {
934
934
  on: false,
@@ -1045,7 +1045,7 @@ var HaNumericSensorDevice = class extends HaBaseChildDevice {
1045
1045
  const stored = this.sourceInfo.quantity;
1046
1046
  if (stored !== void 0 && stored !== "device") return stored;
1047
1047
  if (unitRaw === void 0) return "none";
1048
- const learned = require_ha_broker_source.quantityFromUnit(unitRaw);
1048
+ const learned = require_ha_instance_settings.quantityFromUnit(unitRaw);
1049
1049
  if (learned === void 0 || learned === "device") {
1050
1050
  this.deviceLogger.warn("numeric reading refused", {
1051
1051
  tags: { deviceId: this.id },
@@ -1071,7 +1071,7 @@ var HaNumericSensorDevice = class extends HaBaseChildDevice {
1071
1071
  value: "",
1072
1072
  lastFetchedAt: 0
1073
1073
  };
1074
- this.ctx.registerNativeCap(require_ha_broker_source.enumSensorCapability, { getStatus: async () => {
1074
+ this.ctx.registerNativeCap(require_ha_instance_settings.enumSensorCapability, { getStatus: async () => {
1075
1075
  return this.runtimeState.getCapState("enum-sensor") ?? COLD_START;
1076
1076
  } });
1077
1077
  this.runtimeState.setCapState("enum-sensor", COLD_START);
@@ -1083,7 +1083,7 @@ var HaNumericSensorDevice = class extends HaBaseChildDevice {
1083
1083
  temperature: 0,
1084
1084
  lastFetchedAt: 0
1085
1085
  };
1086
- this.ctx.registerNativeCap(require_ha_broker_source.temperatureSensorCapability, { getStatus: async () => this.readSlice(COLD_START) });
1086
+ this.ctx.registerNativeCap(require_ha_instance_settings.temperatureSensorCapability, { getStatus: async () => this.readSlice(COLD_START) });
1087
1087
  return;
1088
1088
  }
1089
1089
  case "humidity-sensor": {
@@ -1091,7 +1091,7 @@ var HaNumericSensorDevice = class extends HaBaseChildDevice {
1091
1091
  humidity: 0,
1092
1092
  lastFetchedAt: 0
1093
1093
  };
1094
- this.ctx.registerNativeCap(require_ha_broker_source.humiditySensorCapability, { getStatus: async () => this.readSlice(COLD_START) });
1094
+ this.ctx.registerNativeCap(require_ha_instance_settings.humiditySensorCapability, { getStatus: async () => this.readSlice(COLD_START) });
1095
1095
  return;
1096
1096
  }
1097
1097
  case "ambient-light-sensor": {
@@ -1099,7 +1099,7 @@ var HaNumericSensorDevice = class extends HaBaseChildDevice {
1099
1099
  illuminance: 0,
1100
1100
  lastFetchedAt: 0
1101
1101
  };
1102
- this.ctx.registerNativeCap(require_ha_broker_source.ambientLightSensorCapability, { getStatus: async () => this.readSlice(COLD_START) });
1102
+ this.ctx.registerNativeCap(require_ha_instance_settings.ambientLightSensorCapability, { getStatus: async () => this.readSlice(COLD_START) });
1103
1103
  return;
1104
1104
  }
1105
1105
  case "pressure-sensor": {
@@ -1107,7 +1107,7 @@ var HaNumericSensorDevice = class extends HaBaseChildDevice {
1107
1107
  pressure: 0,
1108
1108
  lastFetchedAt: 0
1109
1109
  };
1110
- this.ctx.registerNativeCap(require_ha_broker_source.pressureSensorCapability, { getStatus: async () => this.readSlice(COLD_START) });
1110
+ this.ctx.registerNativeCap(require_ha_instance_settings.pressureSensorCapability, { getStatus: async () => this.readSlice(COLD_START) });
1111
1111
  return;
1112
1112
  }
1113
1113
  case "numeric-sensor": {
@@ -1115,7 +1115,7 @@ var HaNumericSensorDevice = class extends HaBaseChildDevice {
1115
1115
  value: 0,
1116
1116
  lastFetchedAt: 0
1117
1117
  };
1118
- this.ctx.registerNativeCap(require_ha_broker_source.numericSensorCapability, { getStatus: async () => this.readSlice(COLD_START) });
1118
+ this.ctx.registerNativeCap(require_ha_instance_settings.numericSensorCapability, { getStatus: async () => this.readSlice(COLD_START) });
1119
1119
  return;
1120
1120
  }
1121
1121
  }
@@ -1207,61 +1207,61 @@ var HaBinarySensorDevice = class extends HaBaseChildDevice {
1207
1207
  registerCap(name) {
1208
1208
  switch (name) {
1209
1209
  case "contact":
1210
- this.ctx.registerNativeCap(require_ha_broker_source.contactCapability, { getStatus: async () => this.readSlice({
1210
+ this.ctx.registerNativeCap(require_ha_instance_settings.contactCapability, { getStatus: async () => this.readSlice({
1211
1211
  entryOpen: false,
1212
1212
  lastChangedAt: 0
1213
1213
  }) });
1214
1214
  return;
1215
1215
  case "flood":
1216
- this.ctx.registerNativeCap(require_ha_broker_source.floodCapability, { getStatus: async () => this.readSlice({
1216
+ this.ctx.registerNativeCap(require_ha_instance_settings.floodCapability, { getStatus: async () => this.readSlice({
1217
1217
  flooded: false,
1218
1218
  lastChangedAt: 0
1219
1219
  }) });
1220
1220
  return;
1221
1221
  case "smoke":
1222
- this.ctx.registerNativeCap(require_ha_broker_source.smokeCapability, { getStatus: async () => this.readSlice({
1222
+ this.ctx.registerNativeCap(require_ha_instance_settings.smokeCapability, { getStatus: async () => this.readSlice({
1223
1223
  detected: false,
1224
1224
  lastChangedAt: 0
1225
1225
  }) });
1226
1226
  return;
1227
1227
  case "carbon-monoxide":
1228
- this.ctx.registerNativeCap(require_ha_broker_source.carbonMonoxideCapability, { getStatus: async () => this.readSlice({
1228
+ this.ctx.registerNativeCap(require_ha_instance_settings.carbonMonoxideCapability, { getStatus: async () => this.readSlice({
1229
1229
  detected: false,
1230
1230
  lastChangedAt: 0
1231
1231
  }) });
1232
1232
  return;
1233
1233
  case "gas":
1234
- this.ctx.registerNativeCap(require_ha_broker_source.gasCapability, { getStatus: async () => this.readSlice({
1234
+ this.ctx.registerNativeCap(require_ha_instance_settings.gasCapability, { getStatus: async () => this.readSlice({
1235
1235
  detected: false,
1236
1236
  lastChangedAt: 0
1237
1237
  }) });
1238
1238
  return;
1239
1239
  case "tamper":
1240
- this.ctx.registerNativeCap(require_ha_broker_source.tamperCapability, { getStatus: async () => this.readSlice({
1240
+ this.ctx.registerNativeCap(require_ha_instance_settings.tamperCapability, { getStatus: async () => this.readSlice({
1241
1241
  tampered: false,
1242
1242
  lastChangedAt: 0
1243
1243
  }) });
1244
1244
  return;
1245
1245
  case "vibration":
1246
- this.ctx.registerNativeCap(require_ha_broker_source.vibrationCapability, { getStatus: async () => this.readSlice({
1246
+ this.ctx.registerNativeCap(require_ha_instance_settings.vibrationCapability, { getStatus: async () => this.readSlice({
1247
1247
  detected: false,
1248
1248
  lastChangedAt: 0
1249
1249
  }) });
1250
1250
  return;
1251
1251
  case "connectivity":
1252
- this.ctx.registerNativeCap(require_ha_broker_source.connectivityCapability, { getStatus: async () => this.readSlice({
1252
+ this.ctx.registerNativeCap(require_ha_instance_settings.connectivityCapability, { getStatus: async () => this.readSlice({
1253
1253
  connected: false,
1254
1254
  lastChangedAt: 0
1255
1255
  }) });
1256
1256
  return;
1257
1257
  case "binary":
1258
- this.ctx.registerNativeCap(require_ha_broker_source.binaryCapability, { getStatus: async () => this.readSlice({
1258
+ this.ctx.registerNativeCap(require_ha_instance_settings.binaryCapability, { getStatus: async () => this.readSlice({
1259
1259
  on: false,
1260
1260
  lastChangedAt: 0
1261
1261
  }) });
1262
1262
  return;
1263
1263
  case "motion":
1264
- this.ctx.registerNativeCap(require_ha_broker_source.motionCapability, {
1264
+ this.ctx.registerNativeCap(require_ha_instance_settings.motionCapability, {
1265
1265
  getStatus: async () => this.readSlice({
1266
1266
  detected: false,
1267
1267
  lastDetectedAt: null,
@@ -1434,7 +1434,7 @@ var HaLightDevice = class extends HaBaseChildDevice {
1434
1434
  }
1435
1435
  }
1436
1436
  registerSwitchCap() {
1437
- this.ctx.registerNativeCap(require_ha_broker_source.switchCapability, {
1437
+ this.ctx.registerNativeCap(require_ha_instance_settings.switchCapability, {
1438
1438
  getStatus: async () => {
1439
1439
  return this.runtimeState.getCapState("switch") ?? {
1440
1440
  on: false,
@@ -1447,7 +1447,7 @@ var HaLightDevice = class extends HaBaseChildDevice {
1447
1447
  });
1448
1448
  }
1449
1449
  registerBrightnessCap() {
1450
- this.ctx.registerNativeCap(require_ha_broker_source.brightnessCapability, {
1450
+ this.ctx.registerNativeCap(require_ha_instance_settings.brightnessCapability, {
1451
1451
  getStatus: async () => {
1452
1452
  return this.runtimeState.getCapState("brightness") ?? {
1453
1453
  level: 0,
@@ -1460,7 +1460,7 @@ var HaLightDevice = class extends HaBaseChildDevice {
1460
1460
  });
1461
1461
  }
1462
1462
  registerColorCap() {
1463
- this.ctx.registerNativeCap(require_ha_broker_source.colorCapability, {
1463
+ this.ctx.registerNativeCap(require_ha_instance_settings.colorCapability, {
1464
1464
  getStatus: async () => {
1465
1465
  return this.runtimeState.getCapState("color") ?? {
1466
1466
  mode: "rgb",
@@ -1590,7 +1590,7 @@ var HaCoverDevice = class extends HaBaseChildDevice {
1590
1590
  });
1591
1591
  }
1592
1592
  registerCoverCap() {
1593
- this.ctx.registerNativeCap(require_ha_broker_source.coverCapability, {
1593
+ this.ctx.registerNativeCap(require_ha_instance_settings.coverCapability, {
1594
1594
  getStatus: async () => {
1595
1595
  return this.runtimeState.getCapState("cover") ?? COLD_START$18;
1596
1596
  },
@@ -1661,7 +1661,7 @@ var HaValveDevice = class extends HaBaseChildDevice {
1661
1661
  });
1662
1662
  }
1663
1663
  registerValveCap() {
1664
- this.ctx.registerNativeCap(require_ha_broker_source.valveCapability, {
1664
+ this.ctx.registerNativeCap(require_ha_instance_settings.valveCapability, {
1665
1665
  getStatus: async () => {
1666
1666
  return this.runtimeState.getCapState("valve") ?? COLD_START$17;
1667
1667
  },
@@ -1735,7 +1735,7 @@ var HaLockDevice = class extends HaBaseChildDevice {
1735
1735
  });
1736
1736
  }
1737
1737
  registerLockCap() {
1738
- this.ctx.registerNativeCap(require_ha_broker_source.lockControlCapability, {
1738
+ this.ctx.registerNativeCap(require_ha_instance_settings.lockControlCapability, {
1739
1739
  getStatus: async () => {
1740
1740
  return this.runtimeState.getCapState("lock-control") ?? COLD_START$16;
1741
1741
  },
@@ -1819,7 +1819,7 @@ var HaClimateDevice = class extends HaBaseChildDevice {
1819
1819
  this.swingHorizontalModes = readStringArray$4(state.attributes, "swing_horizontal_modes");
1820
1820
  const unit = readStringAttr$6(state.attributes, "temperature_unit");
1821
1821
  if (unit !== null) {
1822
- const probe = require_ha_broker_source.ingestReading({
1822
+ const probe = require_ha_instance_settings.ingestReading({
1823
1823
  value: 0,
1824
1824
  rawUnit: unit,
1825
1825
  quantity: "temperature"
@@ -1836,7 +1836,7 @@ var HaClimateDevice = class extends HaBaseChildDevice {
1836
1836
  this.runtimeState.setCapState("climate-control", climateSliceFromState(state));
1837
1837
  }
1838
1838
  registerClimateCap() {
1839
- this.ctx.registerNativeCap(require_ha_broker_source.climateControlCapability, {
1839
+ this.ctx.registerNativeCap(require_ha_instance_settings.climateControlCapability, {
1840
1840
  getStatus: async () => {
1841
1841
  return this.runtimeState.getCapState("climate-control") ?? COLD_START$15;
1842
1842
  },
@@ -1894,7 +1894,7 @@ function climateSliceFromState(state) {
1894
1894
  const tempUnit = readStringAttr$6(attrs, "temperature_unit") ?? void 0;
1895
1895
  const celsius = (raw) => {
1896
1896
  if (raw === null) return null;
1897
- const result = require_ha_broker_source.ingestReading({
1897
+ const result = require_ha_instance_settings.ingestReading({
1898
1898
  value: raw,
1899
1899
  rawUnit: tempUnit,
1900
1900
  quantity: "temperature"
@@ -2043,7 +2043,7 @@ var HaHumidifierDevice = class extends HaBaseChildDevice {
2043
2043
  });
2044
2044
  }
2045
2045
  registerHumidifierCap() {
2046
- this.ctx.registerNativeCap(require_ha_broker_source.humidifierCapability, {
2046
+ this.ctx.registerNativeCap(require_ha_instance_settings.humidifierCapability, {
2047
2047
  getStatus: async () => {
2048
2048
  return this.runtimeState.getCapState("humidifier") ?? COLD_START$14;
2049
2049
  },
@@ -2123,7 +2123,7 @@ var HaWaterHeaterDevice = class extends HaBaseChildDevice {
2123
2123
  });
2124
2124
  }
2125
2125
  registerWaterHeaterCap() {
2126
- this.ctx.registerNativeCap(require_ha_broker_source.waterHeaterCapability, {
2126
+ this.ctx.registerNativeCap(require_ha_instance_settings.waterHeaterCapability, {
2127
2127
  getStatus: async () => {
2128
2128
  return this.runtimeState.getCapState("water-heater") ?? COLD_START$13;
2129
2129
  },
@@ -2206,7 +2206,7 @@ var HaFanDevice = class extends HaBaseChildDevice {
2206
2206
  this.runtimeState.setCapState("fan-control", slice);
2207
2207
  }
2208
2208
  registerSwitchCap() {
2209
- this.ctx.registerNativeCap(require_ha_broker_source.switchCapability, {
2209
+ this.ctx.registerNativeCap(require_ha_instance_settings.switchCapability, {
2210
2210
  getStatus: async () => {
2211
2211
  return this.runtimeState.getCapState("switch") ?? {
2212
2212
  on: false,
@@ -2219,7 +2219,7 @@ var HaFanDevice = class extends HaBaseChildDevice {
2219
2219
  });
2220
2220
  }
2221
2221
  registerFanCap() {
2222
- this.ctx.registerNativeCap(require_ha_broker_source.fanControlCapability, {
2222
+ this.ctx.registerNativeCap(require_ha_instance_settings.fanControlCapability, {
2223
2223
  getStatus: async () => {
2224
2224
  return this.runtimeState.getCapState("fan-control") ?? FAN_COLD_START;
2225
2225
  },
@@ -2287,7 +2287,7 @@ var HaVacuumDevice = class extends HaBaseChildDevice {
2287
2287
  this.registerVacuumCap();
2288
2288
  this.registerRunningCap();
2289
2289
  this.runtimeState.setCapState("vacuum-control", COLD_START$12);
2290
- this.runtimeState.setCapState("running-state", require_ha_broker_source.RUNNING_STATE_COLD);
2290
+ this.runtimeState.setCapState("running-state", require_ha_instance_settings.RUNNING_STATE_COLD);
2291
2291
  }
2292
2292
  handleStatePush(state) {
2293
2293
  if (state.state === "unavailable" || state.state === "unknown") return;
@@ -2309,13 +2309,13 @@ var HaVacuumDevice = class extends HaBaseChildDevice {
2309
2309
  });
2310
2310
  const fetchedAt = Date.now();
2311
2311
  const previous = this.runtimeState.getCapState("running-state");
2312
- this.runtimeState.setCapState("running-state", require_ha_broker_source.runningFromVacuumState(lifecycleState, previous, fetchedAt, lastChangedAt));
2312
+ this.runtimeState.setCapState("running-state", require_ha_instance_settings.runningFromVacuumState(lifecycleState, previous, fetchedAt, lastChangedAt));
2313
2313
  }
2314
2314
  registerRunningCap() {
2315
- this.ctx.registerNativeCap(require_ha_broker_source.runningStateCapability, { getStatus: async () => this.runtimeState.getCapState("running-state") ?? require_ha_broker_source.RUNNING_STATE_COLD });
2315
+ this.ctx.registerNativeCap(require_ha_instance_settings.runningStateCapability, { getStatus: async () => this.runtimeState.getCapState("running-state") ?? require_ha_instance_settings.RUNNING_STATE_COLD });
2316
2316
  }
2317
2317
  registerVacuumCap() {
2318
- this.ctx.registerNativeCap(require_ha_broker_source.vacuumControlCapability, {
2318
+ this.ctx.registerNativeCap(require_ha_instance_settings.vacuumControlCapability, {
2319
2319
  getStatus: async () => {
2320
2320
  return this.runtimeState.getCapState("vacuum-control") ?? COLD_START$12;
2321
2321
  },
@@ -2387,7 +2387,7 @@ var HaLawnMowerDevice = class extends HaBaseChildDevice {
2387
2387
  this.registerLawnMowerCap();
2388
2388
  this.registerRunningCap();
2389
2389
  this.runtimeState.setCapState("lawn-mower-control", COLD_START$11);
2390
- this.runtimeState.setCapState("running-state", require_ha_broker_source.RUNNING_STATE_COLD);
2390
+ this.runtimeState.setCapState("running-state", require_ha_instance_settings.RUNNING_STATE_COLD);
2391
2391
  }
2392
2392
  handleStatePush(state) {
2393
2393
  if (state.state === "unavailable" || state.state === "unknown") return;
@@ -2405,13 +2405,13 @@ var HaLawnMowerDevice = class extends HaBaseChildDevice {
2405
2405
  });
2406
2406
  const fetchedAt = Date.now();
2407
2407
  const previous = this.runtimeState.getCapState("running-state");
2408
- this.runtimeState.setCapState("running-state", require_ha_broker_source.runningFromLawnMower(activity, previous, fetchedAt, lastChangedAt));
2408
+ this.runtimeState.setCapState("running-state", require_ha_instance_settings.runningFromLawnMower(activity, previous, fetchedAt, lastChangedAt));
2409
2409
  }
2410
2410
  registerRunningCap() {
2411
- this.ctx.registerNativeCap(require_ha_broker_source.runningStateCapability, { getStatus: async () => this.runtimeState.getCapState("running-state") ?? require_ha_broker_source.RUNNING_STATE_COLD });
2411
+ this.ctx.registerNativeCap(require_ha_instance_settings.runningStateCapability, { getStatus: async () => this.runtimeState.getCapState("running-state") ?? require_ha_instance_settings.RUNNING_STATE_COLD });
2412
2412
  }
2413
2413
  registerLawnMowerCap() {
2414
- this.ctx.registerNativeCap(require_ha_broker_source.lawnMowerControlCapability, {
2414
+ this.ctx.registerNativeCap(require_ha_instance_settings.lawnMowerControlCapability, {
2415
2415
  getStatus: async () => {
2416
2416
  return this.runtimeState.getCapState("lawn-mower-control") ?? COLD_START$11;
2417
2417
  },
@@ -2467,7 +2467,7 @@ var HaMediaPlayerDevice = class extends HaBaseChildDevice {
2467
2467
  this.registerMediaPlayerCap();
2468
2468
  this.registerRunningCap();
2469
2469
  this.runtimeState.setCapState("media-player", COLD_START$10);
2470
- this.runtimeState.setCapState("running-state", require_ha_broker_source.RUNNING_STATE_COLD);
2470
+ this.runtimeState.setCapState("running-state", require_ha_instance_settings.RUNNING_STATE_COLD);
2471
2471
  }
2472
2472
  handleStatePush(state) {
2473
2473
  if (state.state === "unavailable" || state.state === "unknown") return;
@@ -2492,16 +2492,38 @@ var HaMediaPlayerDevice = class extends HaBaseChildDevice {
2492
2492
  this.runtimeState.setCapState("media-player", slice);
2493
2493
  const fetchedAt = Date.now();
2494
2494
  const previous = this.runtimeState.getCapState("running-state");
2495
- this.runtimeState.setCapState("running-state", require_ha_broker_source.runningFromMediaPlayer(playerState, previous, fetchedAt, lastChangedAt));
2495
+ this.runtimeState.setCapState("running-state", require_ha_instance_settings.runningFromMediaPlayer(playerState, previous, fetchedAt, lastChangedAt));
2496
2496
  }
2497
2497
  registerRunningCap() {
2498
- this.ctx.registerNativeCap(require_ha_broker_source.runningStateCapability, { getStatus: async () => this.runtimeState.getCapState("running-state") ?? require_ha_broker_source.RUNNING_STATE_COLD });
2498
+ this.ctx.registerNativeCap(require_ha_instance_settings.runningStateCapability, { getStatus: async () => this.runtimeState.getCapState("running-state") ?? require_ha_instance_settings.RUNNING_STATE_COLD });
2499
+ }
2500
+ /** One service call per step, in order: HA has no "N steps" form. */
2501
+ async repeatHaService(service, steps) {
2502
+ for (let step = 0; step < steps; step += 1) await this.callHaService("media_player", service);
2499
2503
  }
2500
2504
  registerMediaPlayerCap() {
2501
- this.ctx.registerNativeCap(require_ha_broker_source.mediaPlayerCapability, {
2505
+ this.ctx.registerNativeCap(require_ha_instance_settings.mediaPlayerCapability, {
2502
2506
  getStatus: async () => {
2503
2507
  return this.runtimeState.getCapState("media-player") ?? COLD_START$10;
2504
2508
  },
2509
+ turnOn: async () => {
2510
+ await this.callHaService("media_player", "turn_on");
2511
+ },
2512
+ turnOff: async () => {
2513
+ await this.callHaService("media_player", "turn_off");
2514
+ },
2515
+ volumeUp: async ({ steps }) => {
2516
+ await this.repeatHaService("volume_up", steps);
2517
+ },
2518
+ volumeDown: async ({ steps }) => {
2519
+ await this.repeatHaService("volume_down", steps);
2520
+ },
2521
+ channelUp: async ({ steps }) => {
2522
+ await this.repeatHaService("media_next_track", steps);
2523
+ },
2524
+ channelDown: async ({ steps }) => {
2525
+ await this.repeatHaService("media_previous_track", steps);
2526
+ },
2505
2527
  play: async () => {
2506
2528
  await this.callHaService("media_player", "media_play");
2507
2529
  },
@@ -2630,7 +2652,7 @@ var HaAlarmPanelDevice = class extends HaBaseChildDevice {
2630
2652
  });
2631
2653
  }
2632
2654
  registerAlarmCap() {
2633
- this.ctx.registerNativeCap(require_ha_broker_source.alarmPanelCapability, {
2655
+ this.ctx.registerNativeCap(require_ha_instance_settings.alarmPanelCapability, {
2634
2656
  getStatus: async () => {
2635
2657
  return this.runtimeState.getCapState("alarm-panel") ?? COLD_START$9;
2636
2658
  },
@@ -2745,7 +2767,7 @@ var HaPresenceDevice = class extends HaBaseChildDevice {
2745
2767
  });
2746
2768
  }
2747
2769
  registerBatteryCap() {
2748
- this.ctx.registerNativeCap(require_ha_broker_source.batteryCapability, {
2770
+ this.ctx.registerNativeCap(require_ha_instance_settings.batteryCapability, {
2749
2771
  getStatus: async () => this.runtimeState.getCapState("battery") ?? COLD_BATTERY,
2750
2772
  wakeForStream: async () => ({
2751
2773
  awoke: true,
@@ -2754,7 +2776,7 @@ var HaPresenceDevice = class extends HaBaseChildDevice {
2754
2776
  });
2755
2777
  }
2756
2778
  registerPresenceCap() {
2757
- this.ctx.registerNativeCap(require_ha_broker_source.presenceCapability, { getStatus: async () => {
2779
+ this.ctx.registerNativeCap(require_ha_instance_settings.presenceCapability, { getStatus: async () => {
2758
2780
  return this.runtimeState.getCapState("presence") ?? COLD_START$8;
2759
2781
  } });
2760
2782
  }
@@ -2822,7 +2844,7 @@ var HaControlDevice = class extends HaBaseChildDevice {
2822
2844
  if (slice !== null) this.runtimeState.setCapState("control", slice);
2823
2845
  }
2824
2846
  registerControlCap() {
2825
- this.ctx.registerNativeCap(require_ha_broker_source.controlCapability, {
2847
+ this.ctx.registerNativeCap(require_ha_instance_settings.controlCapability, {
2826
2848
  getStatus: async () => {
2827
2849
  return this.runtimeState.getCapState("control") ?? {
2828
2850
  kind: this.kind,
@@ -2861,10 +2883,10 @@ var HaControlDevice = class extends HaBaseChildDevice {
2861
2883
  /** Base-unit value → the unit the upstream entity still speaks. */
2862
2884
  toUpstream(value) {
2863
2885
  const quantity = this.sourceInfo.quantity;
2864
- const base = quantity === void 0 ? void 0 : require_ha_broker_source.baseUnitOf(quantity);
2886
+ const base = quantity === void 0 ? void 0 : require_ha_instance_settings.baseUnitOf(quantity);
2865
2887
  const upstream = this.upstreamUnit;
2866
2888
  if (base === void 0 || upstream === void 0 || upstream === base) return value;
2867
- const converted = require_ha_broker_source.tryConvertUnit(value, base, upstream);
2889
+ const converted = require_ha_instance_settings.tryConvertUnit(value, base, upstream);
2868
2890
  if (converted !== void 0) return converted;
2869
2891
  this.deviceLogger.warn("numeric reading refused", {
2870
2892
  tags: { deviceId: this.id },
@@ -2965,7 +2987,7 @@ function decodeNumeric(state, lastChangedAt, decode) {
2965
2987
  if (!Number.isFinite(v)) return null;
2966
2988
  const rawUnit = state.attributes["unit_of_measurement"];
2967
2989
  const unit = typeof rawUnit === "string" && rawUnit.length > 0 ? rawUnit : void 0;
2968
- const incoming = unit === void 0 ? void 0 : require_ha_broker_source.quantityFromUnit(unit);
2990
+ const incoming = unit === void 0 ? void 0 : require_ha_instance_settings.quantityFromUnit(unit);
2969
2991
  if (unit !== void 0 && (incoming === void 0 || incoming === "device")) {
2970
2992
  decode.logger.warn("numeric reading refused", {
2971
2993
  tags: { deviceId: decode.deviceId },
@@ -2992,7 +3014,7 @@ function decodeNumeric(state, lastChangedAt, decode) {
2992
3014
  }
2993
3015
  const value = takeReading(decode.logger, decode.deviceId, v, unit, quantity);
2994
3016
  if (value === null) return null;
2995
- decode.note(quantity, unit === void 0 ? void 0 : require_ha_broker_source.normalizeUnit(unit));
3017
+ decode.note(quantity, unit === void 0 ? void 0 : require_ha_instance_settings.normalizeUnit(unit));
2996
3018
  const rawMin = state.attributes["min"];
2997
3019
  const rawMax = state.attributes["max"];
2998
3020
  const rawStep = state.attributes["step"];
@@ -3012,10 +3034,10 @@ function decodeNumeric(state, lastChangedAt, decode) {
3012
3034
  /** A step is a difference: °F's offset must not move it. */
3013
3035
  function convertStep(step, unit, quantity) {
3014
3036
  if (step === void 0) return void 0;
3015
- const base = require_ha_broker_source.baseUnitOf(quantity);
3016
- const from = unit === void 0 ? void 0 : require_ha_broker_source.normalizeUnit(unit);
3037
+ const base = require_ha_instance_settings.baseUnitOf(quantity);
3038
+ const from = unit === void 0 ? void 0 : require_ha_instance_settings.normalizeUnit(unit);
3017
3039
  if (base === void 0 || from === void 0 || from === base) return step;
3018
- return require_ha_broker_source.tryConvertDelta(step, from, base);
3040
+ return require_ha_instance_settings.tryConvertDelta(step, from, base);
3019
3041
  }
3020
3042
  //#endregion
3021
3043
  //#region src/devices/ha-script-device.ts
@@ -3058,7 +3080,7 @@ var HaScriptDevice = class extends HaBaseChildDevice {
3058
3080
  });
3059
3081
  }
3060
3082
  registerScriptCap() {
3061
- this.ctx.registerNativeCap(require_ha_broker_source.scriptRunnerCapability, {
3083
+ this.ctx.registerNativeCap(require_ha_instance_settings.scriptRunnerCapability, {
3062
3084
  getStatus: async () => {
3063
3085
  return this.runtimeState.getCapState("script-runner") ?? COLD_START$7;
3064
3086
  },
@@ -3117,7 +3139,7 @@ var HaAutomationDevice = class extends HaBaseChildDevice {
3117
3139
  });
3118
3140
  }
3119
3141
  registerAutomationCap() {
3120
- this.ctx.registerNativeCap(require_ha_broker_source.automationControlCapability, {
3142
+ this.ctx.registerNativeCap(require_ha_instance_settings.automationControlCapability, {
3121
3143
  getStatus: async () => {
3122
3144
  return this.runtimeState.getCapState("automation-control") ?? COLD_START$6;
3123
3145
  },
@@ -3176,7 +3198,7 @@ var HaNotifierDevice = class extends HaBaseChildDevice {
3176
3198
  handleStatePush(_state) {}
3177
3199
  registerNotifierCap() {
3178
3200
  const serviceName = this.entityId.split(".")[1] ?? "";
3179
- this.ctx.registerNativeCap(require_ha_broker_source.notifierCapability, {
3201
+ this.ctx.registerNativeCap(require_ha_instance_settings.notifierCapability, {
3180
3202
  getStatus: async () => {
3181
3203
  return this.runtimeState.getCapState("notifier") ?? COLD_START$5;
3182
3204
  },
@@ -3272,7 +3294,7 @@ var HaPowerMeterDevice = class extends HaBaseChildDevice {
3272
3294
  if (update !== null) this.runtimeState.setCapState("power-meter", update);
3273
3295
  }
3274
3296
  registerPowerMeterCap() {
3275
- this.ctx.registerNativeCap(require_ha_broker_source.powerMeterCapability, { getStatus: async () => {
3297
+ this.ctx.registerNativeCap(require_ha_instance_settings.powerMeterCapability, { getStatus: async () => {
3276
3298
  return this.runtimeState.getCapState("power-meter") ?? COLD_START$4;
3277
3299
  } });
3278
3300
  }
@@ -3351,7 +3373,7 @@ var HaAirQualityDevice = class extends HaBaseChildDevice {
3351
3373
  if (update !== null) this.runtimeState.setCapState("air-quality-sensor", update);
3352
3374
  }
3353
3375
  registerCap() {
3354
- this.ctx.registerNativeCap(require_ha_broker_source.airQualitySensorCapability, { getStatus: async () => {
3376
+ this.ctx.registerNativeCap(require_ha_instance_settings.airQualitySensorCapability, { getStatus: async () => {
3355
3377
  return this.runtimeState.getCapState("air-quality-sensor") ?? COLD_START$3;
3356
3378
  } });
3357
3379
  }
@@ -3426,7 +3448,7 @@ var HaEnumSensorDevice = class extends HaBaseChildDevice {
3426
3448
  constructor(ctx) {
3427
3449
  const persisted = ctx.persistedConfig ?? {};
3428
3450
  super(ctx, persisted.role !== void 0 ? { role: persisted.role } : {});
3429
- const parsedFormat = require_ha_broker_source.EnumSensorDateTimeFormatSchema.safeParse(persisted.dateTimeFormat);
3451
+ const parsedFormat = require_ha_instance_settings.EnumSensorDateTimeFormatSchema.safeParse(persisted.dateTimeFormat);
3430
3452
  this.dateTimeFormat = parsedFormat.success ? parsedFormat.data : void 0;
3431
3453
  if (this.dateTimeFormat !== void 0) this.updateSourceInfo({ dateTimeShape: this.dateTimeFormat });
3432
3454
  this.registerCap();
@@ -3448,7 +3470,7 @@ var HaEnumSensorDevice = class extends HaBaseChildDevice {
3448
3470
  });
3449
3471
  }
3450
3472
  registerCap() {
3451
- this.ctx.registerNativeCap(require_ha_broker_source.enumSensorCapability, { getStatus: async () => {
3473
+ this.ctx.registerNativeCap(require_ha_instance_settings.enumSensorCapability, { getStatus: async () => {
3452
3474
  return this.runtimeState.getCapState("enum-sensor") ?? this.coldStart();
3453
3475
  } });
3454
3476
  }
@@ -3547,7 +3569,7 @@ var HaEventEmitterDevice = class extends HaBaseChildDevice {
3547
3569
  timestamp: Date.now(),
3548
3570
  seq: ++this.#seq
3549
3571
  };
3550
- this.ctx.eventBus.emit(require_ha_broker_source.createEvent(require_ha_broker_source.EventCategory.EventEmitted, {
3572
+ this.ctx.eventBus.emit(require_ha_instance_settings.createEvent(require_ha_instance_settings.EventCategory.EventEmitted, {
3551
3573
  type: "device",
3552
3574
  id: this.stableId,
3553
3575
  deviceId: this.id,
@@ -3561,7 +3583,7 @@ var HaEventEmitterDevice = class extends HaBaseChildDevice {
3561
3583
  this.runtimeState.setCapState("event-emitter", slice);
3562
3584
  }
3563
3585
  registerEventEmitterCap() {
3564
- this.ctx.registerNativeCap(require_ha_broker_source.eventEmitterCapability, { getStatus: async () => this.readSlice() });
3586
+ this.ctx.registerNativeCap(require_ha_instance_settings.eventEmitterCapability, { getStatus: async () => this.readSlice() });
3565
3587
  }
3566
3588
  readSlice() {
3567
3589
  return this.runtimeState.getCapState("event-emitter") ?? {
@@ -3644,7 +3666,7 @@ var HaWeatherDevice = class extends HaBaseChildDevice {
3644
3666
  this.runtimeState.setCapState("weather", slice);
3645
3667
  }
3646
3668
  registerWeatherCap() {
3647
- this.ctx.registerNativeCap(require_ha_broker_source.weatherCapability, { getStatus: async () => {
3669
+ this.ctx.registerNativeCap(require_ha_instance_settings.weatherCapability, { getStatus: async () => {
3648
3670
  return this.runtimeState.getCapState("weather") ?? COLD_START$1;
3649
3671
  } });
3650
3672
  }
@@ -3742,7 +3764,7 @@ var HaImageDevice = class extends HaBaseChildDevice {
3742
3764
  this.deviceLogger.warn("ha-image: failed to build absolute image url", { meta: {
3743
3765
  entityId: this.entityId,
3744
3766
  brokerId: this.brokerId,
3745
- error: require_ha_broker_source.errMsg(err)
3767
+ error: require_ha_instance_settings.errMsg(err)
3746
3768
  } });
3747
3769
  url = null;
3748
3770
  }
@@ -3774,7 +3796,7 @@ var HaImageDevice = class extends HaBaseChildDevice {
3774
3796
  return typeof raw === "string" && raw.length > 0 ? raw : null;
3775
3797
  }
3776
3798
  registerImageCap() {
3777
- this.ctx.registerNativeCap(require_ha_broker_source.imageCapability, { getStatus: async () => {
3799
+ this.ctx.registerNativeCap(require_ha_instance_settings.imageCapability, { getStatus: async () => {
3778
3800
  return this.runtimeState.getCapState("image") ?? COLD_START;
3779
3801
  } });
3780
3802
  }
@@ -3868,28 +3890,28 @@ function pickHaChildClass(capabilities) {
3868
3890
  //#region src/ha-container-reconcile.ts
3869
3891
  /** Validates a persisted Container `entities[]` blob (mirrors `haEntitySchema`
3870
3892
  * in ha-container-device.ts). Returns `[]` on absent/invalid input. */
3871
- var containerEntitySchema = require_ha_broker_source.object({
3872
- entityId: require_ha_broker_source.string(),
3873
- deviceType: require_ha_broker_source._enum(require_ha_broker_source.DeviceType),
3874
- capabilities: require_ha_broker_source.array(require_ha_broker_source.string()),
3875
- role: require_ha_broker_source.string().optional(),
3876
- unitOfMeasurement: require_ha_broker_source.string().optional(),
3877
- deviceClass: require_ha_broker_source.string().optional(),
3878
- options: require_ha_broker_source.array(require_ha_broker_source.string()).optional(),
3879
- features: require_ha_broker_source.array(require_ha_broker_source.string()).optional(),
3880
- name: require_ha_broker_source.string().optional(),
3881
- dateTimeFormat: require_ha_broker_source.EnumSensorDateTimeFormatSchema.optional(),
3882
- entityCategory: require_ha_broker_source._enum(["config", "diagnostic"]).optional(),
3883
- meterEntities: require_ha_broker_source.object({
3884
- power: require_ha_broker_source.string().optional(),
3885
- energy: require_ha_broker_source.string().optional(),
3886
- voltage: require_ha_broker_source.string().optional(),
3887
- current: require_ha_broker_source.string().optional()
3893
+ var containerEntitySchema = require_ha_instance_settings.object({
3894
+ entityId: require_ha_instance_settings.string(),
3895
+ deviceType: require_ha_instance_settings._enum(require_ha_instance_settings.DeviceType),
3896
+ capabilities: require_ha_instance_settings.array(require_ha_instance_settings.string()),
3897
+ role: require_ha_instance_settings.string().optional(),
3898
+ unitOfMeasurement: require_ha_instance_settings.string().optional(),
3899
+ deviceClass: require_ha_instance_settings.string().optional(),
3900
+ options: require_ha_instance_settings.array(require_ha_instance_settings.string()).optional(),
3901
+ features: require_ha_instance_settings.array(require_ha_instance_settings.string()).optional(),
3902
+ name: require_ha_instance_settings.string().optional(),
3903
+ dateTimeFormat: require_ha_instance_settings.EnumSensorDateTimeFormatSchema.optional(),
3904
+ entityCategory: require_ha_instance_settings._enum(["config", "diagnostic"]).optional(),
3905
+ meterEntities: require_ha_instance_settings.object({
3906
+ power: require_ha_instance_settings.string().optional(),
3907
+ energy: require_ha_instance_settings.string().optional(),
3908
+ voltage: require_ha_instance_settings.string().optional(),
3909
+ current: require_ha_instance_settings.string().optional()
3888
3910
  }).optional(),
3889
- foldedInto: require_ha_broker_source.string().optional()
3911
+ foldedInto: require_ha_instance_settings.string().optional()
3890
3912
  });
3891
3913
  function parseContainerEntities(raw) {
3892
- const result = require_ha_broker_source.array(containerEntitySchema).safeParse(raw);
3914
+ const result = require_ha_instance_settings.array(containerEntitySchema).safeParse(raw);
3893
3915
  return result.success ? result.data : [];
3894
3916
  }
3895
3917
  /**
@@ -4043,45 +4065,45 @@ function deriveChildLayout(entities) {
4043
4065
  }
4044
4066
  //#endregion
4045
4067
  //#region src/devices/ha-container-device.ts
4046
- var haEntitySchema = require_ha_broker_source.object({
4047
- entityId: require_ha_broker_source.string(),
4048
- deviceType: require_ha_broker_source._enum(require_ha_broker_source.DeviceType),
4049
- capabilities: require_ha_broker_source.array(require_ha_broker_source.string()),
4050
- role: require_ha_broker_source.string().optional(),
4051
- unitOfMeasurement: require_ha_broker_source.string().optional(),
4052
- deviceClass: require_ha_broker_source.string().optional(),
4068
+ var haEntitySchema = require_ha_instance_settings.object({
4069
+ entityId: require_ha_instance_settings.string(),
4070
+ deviceType: require_ha_instance_settings._enum(require_ha_instance_settings.DeviceType),
4071
+ capabilities: require_ha_instance_settings.array(require_ha_instance_settings.string()),
4072
+ role: require_ha_instance_settings.string().optional(),
4073
+ unitOfMeasurement: require_ha_instance_settings.string().optional(),
4074
+ deviceClass: require_ha_instance_settings.string().optional(),
4053
4075
  /** HA `options` attribute — present on select / input_select entities.
4054
4076
  * Persisted at adoption so the control slice is seeded immediately. */
4055
- options: require_ha_broker_source.array(require_ha_broker_source.string()).optional(),
4077
+ options: require_ha_instance_settings.array(require_ha_instance_settings.string()).optional(),
4056
4078
  /** Mapping-derived DeviceFeature flags (e.g. `lock-open`) — surfaced on the
4057
4079
  * child's `device.features` so the UI gates feature affordances. */
4058
- features: require_ha_broker_source.array(require_ha_broker_source.string()).optional(),
4080
+ features: require_ha_instance_settings.array(require_ha_instance_settings.string()).optional(),
4059
4081
  /** HA friendly_name — persisted so the child device name survives
4060
4082
  * a reboot without a discovery round-trip. Falls back to entityId. */
4061
- name: require_ha_broker_source.string().optional(),
4083
+ name: require_ha_instance_settings.string().optional(),
4062
4084
  /** Locale-render shape for a `DateTimeSensor`-role enum sensor
4063
4085
  * (`device_class=timestamp` → `'datetime'`, `date` → `'date'`). Seeded into
4064
4086
  * the enum-sensor cap slice by the child so the UI renders the ISO `value`. */
4065
- dateTimeFormat: require_ha_broker_source.EnumSensorDateTimeFormatSchema.optional(),
4087
+ dateTimeFormat: require_ha_instance_settings.EnumSensorDateTimeFormatSchema.optional(),
4066
4088
  /** HA `entity_category` — `config` / `diagnostic` / absent (a normal
4067
4089
  * control). Drives the accordion section the child renders in. */
4068
- entityCategory: require_ha_broker_source._enum(["config", "diagnostic"]).optional(),
4090
+ entityCategory: require_ha_instance_settings._enum(["config", "diagnostic"]).optional(),
4069
4091
  /** Sibling meter sensors this entity reads as its own power-meter (D951). */
4070
- meterEntities: require_ha_broker_source.object({
4071
- power: require_ha_broker_source.string().optional(),
4072
- energy: require_ha_broker_source.string().optional(),
4073
- voltage: require_ha_broker_source.string().optional(),
4074
- current: require_ha_broker_source.string().optional()
4092
+ meterEntities: require_ha_instance_settings.object({
4093
+ power: require_ha_instance_settings.string().optional(),
4094
+ energy: require_ha_instance_settings.string().optional(),
4095
+ voltage: require_ha_instance_settings.string().optional(),
4096
+ current: require_ha_instance_settings.string().optional()
4075
4097
  }).optional(),
4076
4098
  /** Set on a meter sensor folded into another entity: sectioned as Diagnostic. */
4077
- foldedInto: require_ha_broker_source.string().optional()
4099
+ foldedInto: require_ha_instance_settings.string().optional()
4078
4100
  });
4079
- var haContainerSchema = require_ha_broker_source.object({
4080
- system: require_ha_broker_source.literal("homeassistant"),
4081
- brokerId: require_ha_broker_source.string(),
4082
- haDeviceId: require_ha_broker_source.string(),
4083
- integrationId: require_ha_broker_source.string().optional(),
4084
- entities: require_ha_broker_source.array(haEntitySchema).default([])
4101
+ var haContainerSchema = require_ha_instance_settings.object({
4102
+ system: require_ha_instance_settings.literal("homeassistant"),
4103
+ brokerId: require_ha_instance_settings.string(),
4104
+ haDeviceId: require_ha_instance_settings.string(),
4105
+ integrationId: require_ha_instance_settings.string().optional(),
4106
+ entities: require_ha_instance_settings.array(haEntitySchema).default([])
4085
4107
  });
4086
4108
  /**
4087
4109
  * A container entity is a battery source when the HA domain mapping
@@ -4091,7 +4113,7 @@ var haContainerSchema = require_ha_broker_source.object({
4091
4113
  * device_class is the original HA attribute that drove it.
4092
4114
  */
4093
4115
  function isBatteryEntity(entity) {
4094
- return entity.role === require_ha_broker_source.DeviceRole.BatterySensor || entity.deviceClass === "battery";
4116
+ return entity.role === require_ha_instance_settings.DeviceRole.BatterySensor || entity.deviceClass === "battery";
4095
4117
  }
4096
4118
  /**
4097
4119
  * A battery entity is BINARY when HA exposes it as a `binary_sensor`
@@ -4183,7 +4205,7 @@ function batteryEntityId(entities) {
4183
4205
  * persist initial config, build context, construct via factory, then
4184
4206
  * run the child's own probe + accessory + activate phases.
4185
4207
  */
4186
- var HaContainerDevice = class HaContainerDevice extends require_ha_broker_source.BaseDevice {
4208
+ var HaContainerDevice = class HaContainerDevice extends require_ha_instance_settings.BaseDevice {
4187
4209
  features;
4188
4210
  brokerId;
4189
4211
  integrationId;
@@ -4204,10 +4226,10 @@ var HaContainerDevice = class HaContainerDevice extends require_ha_broker_source
4204
4226
  constructor(ctx) {
4205
4227
  const cfg = haContainerSchema.parse(ctx.persistedConfig ?? {});
4206
4228
  const batteryEntity = selectBatteryEntity(cfg.entities);
4207
- super(ctx, haContainerSchema, { type: require_ha_broker_source.DeviceType.Container });
4229
+ super(ctx, haContainerSchema, { type: require_ha_instance_settings.DeviceType.Container });
4208
4230
  this.brokerId = cfg.brokerId;
4209
4231
  this.integrationId = cfg.integrationId;
4210
- this.features = batteryEntity !== null ? [require_ha_broker_source.DeviceFeature.Resyncable, require_ha_broker_source.DeviceFeature.BatteryOperated] : [require_ha_broker_source.DeviceFeature.Resyncable];
4232
+ this.features = batteryEntity !== null ? [require_ha_instance_settings.DeviceFeature.Resyncable, require_ha_instance_settings.DeviceFeature.BatteryOperated] : [require_ha_instance_settings.DeviceFeature.Resyncable];
4211
4233
  this.entityIds = new Set(cfg.entities.map((e) => e.entityId));
4212
4234
  this.online = false;
4213
4235
  this.batteryEntityId = batteryEntityId(cfg.entities);
@@ -4218,7 +4240,7 @@ var HaContainerDevice = class HaContainerDevice extends require_ha_broker_source
4218
4240
  sleeping: false,
4219
4241
  lastUpdated: 0
4220
4242
  };
4221
- this.ctx.registerNativeCap(require_ha_broker_source.batteryCapability, {
4243
+ this.ctx.registerNativeCap(require_ha_instance_settings.batteryCapability, {
4222
4244
  getStatus: async () => this.runtimeState.getCapState("battery") ?? COLD,
4223
4245
  wakeForStream: async () => ({
4224
4246
  awoke: true,
@@ -4293,7 +4315,7 @@ var HaContainerDevice = class HaContainerDevice extends require_ha_broker_source
4293
4315
  } catch (err) {
4294
4316
  this.ctx.logger.warn("ha-container failed to subscribe entities for availability", { meta: {
4295
4317
  brokerId: this.brokerId,
4296
- error: require_ha_broker_source.errMsg(err)
4318
+ error: require_ha_instance_settings.errMsg(err)
4297
4319
  } });
4298
4320
  }
4299
4321
  }
@@ -4334,7 +4356,7 @@ var HaContainerDevice = class HaContainerDevice extends require_ha_broker_source
4334
4356
  } catch (err) {
4335
4357
  this.ctx.logger.warn("ha-container failed to persist childLayout", { meta: {
4336
4358
  haDeviceId: this.config.values.haDeviceId,
4337
- error: require_ha_broker_source.errMsg(err)
4359
+ error: require_ha_instance_settings.errMsg(err)
4338
4360
  } });
4339
4361
  }
4340
4362
  }
@@ -4413,10 +4435,10 @@ var HaContainerDevice = class HaContainerDevice extends require_ha_broker_source
4413
4435
  * entity-backed (no `entityId`), so it does NOT extend the HA child base
4414
4436
  * device — it is a thin standalone `BaseDevice` subclass.
4415
4437
  */
4416
- var haEventBusDeviceSchema = require_ha_broker_source.object({
4417
- system: require_ha_broker_source.literal("homeassistant"),
4418
- brokerId: require_ha_broker_source.string(),
4419
- kind: require_ha_broker_source.literal("event-bus")
4438
+ var haEventBusDeviceSchema = require_ha_instance_settings.object({
4439
+ system: require_ha_instance_settings.literal("homeassistant"),
4440
+ brokerId: require_ha_instance_settings.string(),
4441
+ kind: require_ha_instance_settings.literal("event-bus")
4420
4442
  });
4421
4443
  /**
4422
4444
  * Case 2 — generic per-broker HA bus-event aggregator.
@@ -4437,7 +4459,7 @@ var haEventBusDeviceSchema = require_ha_broker_source.object({
4437
4459
  * directly via {@link handleBusEvent} (the integration manager subscribes
4438
4460
  * to the curated bus event types and threads each fire through the addon).
4439
4461
  */
4440
- var HaEventBusDevice = class extends require_ha_broker_source.BaseDevice {
4462
+ var HaEventBusDevice = class extends require_ha_instance_settings.BaseDevice {
4441
4463
  features = [];
4442
4464
  /** Monotonic sequence — two identical events still produce distinct slice
4443
4465
  * writes / bus emissions. */
@@ -4476,7 +4498,7 @@ var HaEventBusDevice = class extends require_ha_broker_source.BaseDevice {
4476
4498
  timestamp: Date.now(),
4477
4499
  seq: ++this.#seq
4478
4500
  };
4479
- this.ctx.eventBus.emit(require_ha_broker_source.createEvent(require_ha_broker_source.EventCategory.EventEmitted, {
4501
+ this.ctx.eventBus.emit(require_ha_instance_settings.createEvent(require_ha_instance_settings.EventCategory.EventEmitted, {
4480
4502
  type: "device",
4481
4503
  id: this.stableId,
4482
4504
  deviceId: this.id,
@@ -4490,7 +4512,7 @@ var HaEventBusDevice = class extends require_ha_broker_source.BaseDevice {
4490
4512
  this.runtimeState.setCapState("event-emitter", slice);
4491
4513
  }
4492
4514
  registerEventEmitterCap() {
4493
- this.ctx.registerNativeCap(require_ha_broker_source.eventEmitterCapability, { getStatus: async () => this.readSlice() });
4515
+ this.ctx.registerNativeCap(require_ha_instance_settings.eventEmitterCapability, { getStatus: async () => this.readSlice() });
4494
4516
  }
4495
4517
  readSlice() {
4496
4518
  return this.runtimeState.getCapState("event-emitter") ?? {
@@ -4525,7 +4547,7 @@ async function cascadeRemoveDevicesForBroker(input) {
4525
4547
  tags: { deviceId: d.id },
4526
4548
  meta: {
4527
4549
  brokerId,
4528
- error: require_ha_broker_source.errMsg(err)
4550
+ error: require_ha_instance_settings.errMsg(err)
4529
4551
  }
4530
4552
  });
4531
4553
  }
@@ -5431,7 +5453,7 @@ var HaIntegrationManager = class HaIntegrationManager {
5431
5453
  } catch (err) {
5432
5454
  this.opts.logger.warn("ha-broker onConnected handler threw", { meta: {
5433
5455
  brokerId: this.opts.id,
5434
- error: require_ha_broker_source.errMsg(err)
5456
+ error: require_ha_instance_settings.errMsg(err)
5435
5457
  } });
5436
5458
  }
5437
5459
  },
@@ -5446,12 +5468,12 @@ var HaIntegrationManager = class HaIntegrationManager {
5446
5468
  } catch (err) {
5447
5469
  this.opts.logger.warn("ha-broker onDisconnected handler threw", { meta: {
5448
5470
  brokerId: this.opts.id,
5449
- error: require_ha_broker_source.errMsg(err)
5471
+ error: require_ha_instance_settings.errMsg(err)
5450
5472
  } });
5451
5473
  }
5452
5474
  },
5453
5475
  onReconnectError: (err, nextDelayMs) => {
5454
- this.lastError = require_ha_broker_source.errMsg(err);
5476
+ this.lastError = require_ha_instance_settings.errMsg(err);
5455
5477
  this.opts.logger.warn("ha-broker reconnect attempt failed", { meta: {
5456
5478
  brokerId: this.opts.id,
5457
5479
  error: this.lastError,
@@ -5632,7 +5654,7 @@ var HaIntegrationManager = class HaIntegrationManager {
5632
5654
  this.opts.logger.warn("ha-broker bus-event subscribe failed", { meta: {
5633
5655
  brokerId: this.opts.id,
5634
5656
  eventType,
5635
- error: require_ha_broker_source.errMsg(err)
5657
+ error: require_ha_instance_settings.errMsg(err)
5636
5658
  } });
5637
5659
  }
5638
5660
  }
@@ -5668,7 +5690,7 @@ var HaIntegrationManager = class HaIntegrationManager {
5668
5690
  return false;
5669
5691
  }
5670
5692
  emitBrokerMessage(subscriptionId, entityId, state) {
5671
- this.opts.eventBus.emit(require_ha_broker_source.createEvent("broker.message", {
5693
+ this.opts.eventBus.emit(require_ha_instance_settings.createEvent("broker.message", {
5672
5694
  type: "addon",
5673
5695
  id: this.opts.id
5674
5696
  }, {
@@ -5690,7 +5712,7 @@ var HaIntegrationManager = class HaIntegrationManager {
5690
5712
  } catch (err) {
5691
5713
  this.opts.logger.debug("ha get_config probe failed", { meta: {
5692
5714
  brokerId: this.opts.id,
5693
- error: require_ha_broker_source.errMsg(err)
5715
+ error: require_ha_instance_settings.errMsg(err)
5694
5716
  } });
5695
5717
  }
5696
5718
  }
@@ -5698,7 +5720,7 @@ var HaIntegrationManager = class HaIntegrationManager {
5698
5720
  if (this.status === next) return;
5699
5721
  this.status = next;
5700
5722
  this.lastCheckedAt = Date.now();
5701
- this.opts.eventBus.emit(require_ha_broker_source.createEvent("broker.status-changed", {
5723
+ this.opts.eventBus.emit(require_ha_instance_settings.createEvent("broker.status-changed", {
5702
5724
  type: "addon",
5703
5725
  id: this.opts.id
5704
5726
  }, {
@@ -5719,7 +5741,7 @@ var HaIntegrationManager = class HaIntegrationManager {
5719
5741
  this.lastError = "Home Assistant host / URL is required";
5720
5742
  this.setStatus("unreachable");
5721
5743
  } else {
5722
- this.lastError = require_ha_broker_source.errMsg(err);
5744
+ this.lastError = require_ha_instance_settings.errMsg(err);
5723
5745
  this.setStatus("error");
5724
5746
  }
5725
5747
  }
@@ -5740,25 +5762,19 @@ var TEST_HANDSHAKE_TIMEOUT_MS = 8e3;
5740
5762
  * `dataDir` being protected by filesystem permissions. (MQTT broker
5741
5763
  * encrypts at rest; HA broker does not yet — TODO for hardening.)
5742
5764
  */
5743
- var HaBrokerEntrySchema = require_ha_broker_source.object({
5744
- id: require_ha_broker_source.string(),
5745
- name: require_ha_broker_source.string(),
5746
- /** Either Supervisor (token from env) or long-lived (persisted). */
5747
- auth: require_ha_broker_source.discriminatedUnion("kind", [require_ha_broker_source.object({
5748
- kind: require_ha_broker_source.literal("supervisor"),
5749
- supervisorToken: require_ha_broker_source.string().meta({ secret: true })
5750
- }), require_ha_broker_source.object({
5751
- kind: require_ha_broker_source.literal("long-lived"),
5752
- baseUrl: require_ha_broker_source.string(),
5753
- accessToken: require_ha_broker_source.string().meta({ secret: true })
5754
- })]),
5755
- /** Optional FK to the integration record that spawned this broker.
5756
- * Populated when the wizard's "+ New Integration" flow created the
5757
- * broker; null when the operator added it via the Settings panel
5758
- * directly. Used by the integration listener to keep the broker
5759
- * list in sync with the integrations table (cascade-delete on
5760
- * integration removal). */
5761
- integrationId: require_ha_broker_source.string().optional()
5765
+ var HaBrokerEntrySchema = require_ha_instance_settings.object({
5766
+ id: require_ha_instance_settings.string(),
5767
+ name: require_ha_instance_settings.string(),
5768
+ /** Supervisor (token from env) or long-lived (persisted); picks which fields below are used. */
5769
+ authKind: require_ha_instance_settings._enum(["long-lived", "supervisor"]),
5770
+ /** Origin URL of the HA instance; long-lived only. */
5771
+ baseUrl: require_ha_instance_settings.string().optional(),
5772
+ accessToken: require_ha_instance_settings.string().optional().meta({ secret: true }),
5773
+ supervisorToken: require_ha_instance_settings.string().optional().meta({ secret: true }),
5774
+ /** Optional FK to the integration record that spawned this broker. */
5775
+ integrationId: require_ha_instance_settings.string().optional(),
5776
+ /** The instance's own switch (D996); absent means on. */
5777
+ enabled: require_ha_instance_settings.boolean().optional()
5762
5778
  });
5763
5779
  /**
5764
5780
  * Validates a `broker.add` `settings` payload for the HA kind. Accepts:
@@ -5767,10 +5783,10 @@ var HaBrokerEntrySchema = require_ha_broker_source.object({
5767
5783
  * persisting allows the addon to keep working after the env var
5768
5784
  * rotates out of scope)
5769
5785
  */
5770
- var HaAddSettingsSchema = require_ha_broker_source.union([require_ha_broker_source.object({
5771
- baseUrl: require_ha_broker_source.url(),
5772
- accessToken: require_ha_broker_source.string().min(1).meta({ secret: true })
5773
- }), require_ha_broker_source.object({ supervisorToken: require_ha_broker_source.string().min(1).meta({ secret: true }) })]);
5786
+ var HaAddSettingsSchema = require_ha_instance_settings.union([require_ha_instance_settings.object({
5787
+ baseUrl: require_ha_instance_settings.url(),
5788
+ accessToken: require_ha_instance_settings.string().min(1).meta({ secret: true })
5789
+ }), require_ha_instance_settings.object({ supervisorToken: require_ha_instance_settings.string().min(1).meta({ secret: true }) })]);
5774
5790
  function settingsToAuth(settings) {
5775
5791
  const parsed = HaAddSettingsSchema.parse(settings);
5776
5792
  if ("supervisorToken" in parsed) return {
@@ -5783,6 +5799,34 @@ function settingsToAuth(settings) {
5783
5799
  accessToken: parsed.accessToken
5784
5800
  };
5785
5801
  }
5802
+ /** The flat entry fields of an auth config: the one place the two shapes meet. */
5803
+ function authToEntryFields(auth) {
5804
+ return auth.kind === "supervisor" ? {
5805
+ authKind: "supervisor",
5806
+ supervisorToken: auth.supervisorToken
5807
+ } : {
5808
+ authKind: "long-lived",
5809
+ baseUrl: auth.baseUrl,
5810
+ accessToken: auth.accessToken
5811
+ };
5812
+ }
5813
+ /** The auth config an entry stands for; null while the entry is not filled in. */
5814
+ function haAuthOf(entry) {
5815
+ const parsed = HaAuthConfigSchema.safeParse(entry.authKind === "supervisor" ? {
5816
+ kind: "supervisor",
5817
+ supervisorToken: entry.supervisorToken ?? ""
5818
+ } : {
5819
+ kind: "long-lived",
5820
+ baseUrl: entry.baseUrl ?? "",
5821
+ accessToken: entry.accessToken ?? ""
5822
+ });
5823
+ return parsed.success ? parsed.data : null;
5824
+ }
5825
+ /** The flat settings payload (`settingsToAuth` shape) of an entry; null while it is not filled in. */
5826
+ function entryToSettings(entry) {
5827
+ const auth = haAuthOf(entry);
5828
+ return auth === null ? null : authToSettings(auth);
5829
+ }
5786
5830
  function authToSettings(auth) {
5787
5831
  if (auth.kind === "supervisor") return { supervisorToken: auth.supervisorToken };
5788
5832
  return {
@@ -5845,13 +5889,13 @@ var HaBrokerRegistry = class {
5845
5889
  * started concurrently; transient errors don't block bootstrap. */
5846
5890
  async restore(entries) {
5847
5891
  this.seedCounterFromEntries(entries);
5848
- await Promise.all(entries.map(async (entry) => {
5892
+ await Promise.all(entries.filter((entry) => entry.enabled !== false && haAuthOf(entry) !== null).map(async (entry) => {
5849
5893
  try {
5850
5894
  await this.startManagerForEntry(entry);
5851
5895
  } catch (err) {
5852
5896
  this.logger.warn("ha-broker bootstrap failed", { meta: {
5853
5897
  brokerId: entry.id,
5854
- error: require_ha_broker_source.errMsg(err)
5898
+ error: require_ha_instance_settings.errMsg(err)
5855
5899
  } });
5856
5900
  }
5857
5901
  }));
@@ -5906,7 +5950,7 @@ var HaBrokerRegistry = class {
5906
5950
  const entry = {
5907
5951
  id: options.id !== void 0 ? this.adoptId(options.id) : this.allocateId(),
5908
5952
  name,
5909
- auth,
5953
+ ...authToEntryFields(auth),
5910
5954
  ...options.integrationId !== void 0 ? { integrationId: options.integrationId } : {}
5911
5955
  };
5912
5956
  await this.startManagerForEntry(entry);
@@ -5927,7 +5971,7 @@ var HaBrokerRegistry = class {
5927
5971
  return {
5928
5972
  id,
5929
5973
  name: existing.getInfo().name,
5930
- auth
5974
+ ...authToEntryFields(auth)
5931
5975
  };
5932
5976
  }
5933
5977
  /**
@@ -5945,7 +5989,7 @@ var HaBrokerRegistry = class {
5945
5989
  } catch (err) {
5946
5990
  return {
5947
5991
  ok: false,
5948
- error: require_ha_broker_source.errMsg(err)
5992
+ error: require_ha_instance_settings.errMsg(err)
5949
5993
  };
5950
5994
  }
5951
5995
  const startedAt = Date.now();
@@ -5983,7 +6027,7 @@ var HaBrokerRegistry = class {
5983
6027
  client?.stop();
5984
6028
  resolve({
5985
6029
  ok: false,
5986
- error: require_ha_broker_source.errMsg(err)
6030
+ error: require_ha_instance_settings.errMsg(err)
5987
6031
  });
5988
6032
  }
5989
6033
  }
@@ -5995,7 +6039,7 @@ var HaBrokerRegistry = class {
5995
6039
  client?.stop();
5996
6040
  resolve({
5997
6041
  ok: false,
5998
- error: require_ha_broker_source.errMsg(err)
6042
+ error: require_ha_instance_settings.errMsg(err)
5999
6043
  });
6000
6044
  });
6001
6045
  });
@@ -6110,10 +6154,12 @@ var HaBrokerRegistry = class {
6110
6154
  this.logger.debug("ha-broker already active — reusing existing connection", { meta: { brokerId: entry.id } });
6111
6155
  return;
6112
6156
  }
6157
+ const auth = haAuthOf(entry);
6158
+ if (auth === null) throw new Error(`ha-broker '${entry.id}' has no complete credentials`);
6113
6159
  const manager = new HaIntegrationManager({
6114
6160
  id: entry.id,
6115
6161
  name: entry.name,
6116
- auth: entry.auth,
6162
+ auth,
6117
6163
  logger: this.logger,
6118
6164
  eventBus: this.eventBus,
6119
6165
  onConnected: (brokerId) => this.onBrokerConnected?.(brokerId),
@@ -6190,27 +6236,27 @@ function mapHaEntityToCamStack(input) {
6190
6236
  const { domain, deviceClass, attributes } = input;
6191
6237
  switch (domain) {
6192
6238
  case "switch": return {
6193
- deviceType: require_ha_broker_source.DeviceType.Switch,
6194
- role: deviceClass === "outlet" ? require_ha_broker_source.DeviceRole.Outlet : null,
6239
+ deviceType: require_ha_instance_settings.DeviceType.Switch,
6240
+ role: deviceClass === "outlet" ? require_ha_instance_settings.DeviceRole.Outlet : null,
6195
6241
  capabilities: ["switch"]
6196
6242
  };
6197
6243
  case "input_boolean": return {
6198
- deviceType: require_ha_broker_source.DeviceType.Switch,
6199
- role: require_ha_broker_source.DeviceRole.BinaryHelper,
6244
+ deviceType: require_ha_instance_settings.DeviceType.Switch,
6245
+ role: require_ha_instance_settings.DeviceRole.BinaryHelper,
6200
6246
  capabilities: ["switch"]
6201
6247
  };
6202
6248
  case "remote": return {
6203
- deviceType: require_ha_broker_source.DeviceType.Switch,
6249
+ deviceType: require_ha_instance_settings.DeviceType.Switch,
6204
6250
  role: null,
6205
6251
  capabilities: ["switch"]
6206
6252
  };
6207
6253
  case "siren": return {
6208
- deviceType: require_ha_broker_source.DeviceType.Siren,
6254
+ deviceType: require_ha_instance_settings.DeviceType.Siren,
6209
6255
  role: null,
6210
6256
  capabilities: ["switch"]
6211
6257
  };
6212
6258
  case "update": return {
6213
- deviceType: require_ha_broker_source.DeviceType.Update,
6259
+ deviceType: require_ha_instance_settings.DeviceType.Update,
6214
6260
  role: null,
6215
6261
  capabilities: ["update"]
6216
6262
  };
@@ -6228,7 +6274,7 @@ function mapHaEntityToCamStack(input) {
6228
6274
  case "alarm_control_panel": return mapAlarmPanel(attributes);
6229
6275
  case "person":
6230
6276
  case "device_tracker": return {
6231
- deviceType: require_ha_broker_source.DeviceType.Presence,
6277
+ deviceType: require_ha_instance_settings.DeviceType.Presence,
6232
6278
  role: null,
6233
6279
  capabilities: ["presence"]
6234
6280
  };
@@ -6237,49 +6283,49 @@ function mapHaEntityToCamStack(input) {
6237
6283
  case "camera": return mapImage(attributes);
6238
6284
  case "number":
6239
6285
  case "input_number": return {
6240
- deviceType: require_ha_broker_source.DeviceType.Control,
6241
- role: require_ha_broker_source.DeviceRole.NumericControl,
6286
+ deviceType: require_ha_instance_settings.DeviceType.Control,
6287
+ role: require_ha_instance_settings.DeviceRole.NumericControl,
6242
6288
  capabilities: ["control"]
6243
6289
  };
6244
6290
  case "select":
6245
6291
  case "input_select": return {
6246
- deviceType: require_ha_broker_source.DeviceType.Control,
6247
- role: require_ha_broker_source.DeviceRole.SelectControl,
6292
+ deviceType: require_ha_instance_settings.DeviceType.Control,
6293
+ role: require_ha_instance_settings.DeviceRole.SelectControl,
6248
6294
  capabilities: ["control"]
6249
6295
  };
6250
6296
  case "text":
6251
6297
  case "input_text": return {
6252
- deviceType: require_ha_broker_source.DeviceType.Control,
6253
- role: require_ha_broker_source.DeviceRole.TextControl,
6298
+ deviceType: require_ha_instance_settings.DeviceType.Control,
6299
+ role: require_ha_instance_settings.DeviceRole.TextControl,
6254
6300
  capabilities: ["control"]
6255
6301
  };
6256
6302
  case "input_datetime":
6257
6303
  case "date":
6258
6304
  case "time":
6259
6305
  case "datetime": return {
6260
- deviceType: require_ha_broker_source.DeviceType.Control,
6261
- role: require_ha_broker_source.DeviceRole.DateTimeControl,
6306
+ deviceType: require_ha_instance_settings.DeviceType.Control,
6307
+ role: require_ha_instance_settings.DeviceRole.DateTimeControl,
6262
6308
  capabilities: ["control"]
6263
6309
  };
6264
6310
  case "button":
6265
6311
  case "input_button":
6266
6312
  case "scene": return {
6267
- deviceType: require_ha_broker_source.DeviceType.Button,
6313
+ deviceType: require_ha_instance_settings.DeviceType.Button,
6268
6314
  role: null,
6269
6315
  capabilities: ["button"]
6270
6316
  };
6271
6317
  case "event": return {
6272
- deviceType: require_ha_broker_source.DeviceType.EventEmitter,
6318
+ deviceType: require_ha_instance_settings.DeviceType.EventEmitter,
6273
6319
  role: null,
6274
6320
  capabilities: ["event-emitter"]
6275
6321
  };
6276
6322
  case "script": return {
6277
- deviceType: require_ha_broker_source.DeviceType.Script,
6323
+ deviceType: require_ha_instance_settings.DeviceType.Script,
6278
6324
  role: null,
6279
6325
  capabilities: ["script-runner"]
6280
6326
  };
6281
6327
  case "automation": return {
6282
- deviceType: require_ha_broker_source.DeviceType.Automation,
6328
+ deviceType: require_ha_instance_settings.DeviceType.Automation,
6283
6329
  role: null,
6284
6330
  capabilities: ["automation-control"]
6285
6331
  };
@@ -6305,12 +6351,12 @@ function mapLight(attributes) {
6305
6351
  const hasMired = modes.some((m) => m === "color_temp");
6306
6352
  if (hasRgb || hasMired) {
6307
6353
  capabilities.push("color");
6308
- if (modes.includes("rgb") || modes.includes("rgbw") || modes.includes("rgbww") || modes.includes("xy")) features.push(require_ha_broker_source.DeviceFeature.LightColorRgb);
6309
- if (modes.includes("hs")) features.push(require_ha_broker_source.DeviceFeature.LightColorHsv);
6310
- if (hasMired) features.push(require_ha_broker_source.DeviceFeature.LightColorMired);
6354
+ if (modes.includes("rgb") || modes.includes("rgbw") || modes.includes("rgbww") || modes.includes("xy")) features.push(require_ha_instance_settings.DeviceFeature.LightColorRgb);
6355
+ if (modes.includes("hs")) features.push(require_ha_instance_settings.DeviceFeature.LightColorHsv);
6356
+ if (hasMired) features.push(require_ha_instance_settings.DeviceFeature.LightColorMired);
6311
6357
  }
6312
6358
  return {
6313
- deviceType: require_ha_broker_source.DeviceType.Light,
6359
+ deviceType: require_ha_instance_settings.DeviceType.Light,
6314
6360
  role: null,
6315
6361
  capabilities,
6316
6362
  features
@@ -6318,11 +6364,11 @@ function mapLight(attributes) {
6318
6364
  }
6319
6365
  function mapLock(attributes) {
6320
6366
  const features = [];
6321
- if (attributes["code_format"] !== void 0 && attributes["code_format"] !== null) features.push(require_ha_broker_source.DeviceFeature.LockPinRequired);
6367
+ if (attributes["code_format"] !== void 0 && attributes["code_format"] !== null) features.push(require_ha_instance_settings.DeviceFeature.LockPinRequired);
6322
6368
  const sf = readNumericAttr(attributes, "supported_features");
6323
- if (sf !== null && (sf & 1) !== 0) features.push(require_ha_broker_source.DeviceFeature.LockOpen);
6369
+ if (sf !== null && (sf & 1) !== 0) features.push(require_ha_instance_settings.DeviceFeature.LockOpen);
6324
6370
  return {
6325
- deviceType: require_ha_broker_source.DeviceType.Lock,
6371
+ deviceType: require_ha_instance_settings.DeviceType.Lock,
6326
6372
  role: null,
6327
6373
  capabilities: ["lock-control"],
6328
6374
  features
@@ -6331,11 +6377,11 @@ function mapLock(attributes) {
6331
6377
  function mapCover(attributes, deviceClass) {
6332
6378
  const features = [];
6333
6379
  const sf = readNumericAttr(attributes, "supported_features");
6334
- if (sf !== null && (sf & 4) !== 0) features.push(require_ha_broker_source.DeviceFeature.CoverPositionable);
6335
- if (sf !== null && (sf & 8) !== 0) features.push(require_ha_broker_source.DeviceFeature.CoverStoppable);
6336
- if (sf !== null && (sf & 128) !== 0) features.push(require_ha_broker_source.DeviceFeature.CoverTilt);
6380
+ if (sf !== null && (sf & 4) !== 0) features.push(require_ha_instance_settings.DeviceFeature.CoverPositionable);
6381
+ if (sf !== null && (sf & 8) !== 0) features.push(require_ha_instance_settings.DeviceFeature.CoverStoppable);
6382
+ if (sf !== null && (sf & 128) !== 0) features.push(require_ha_instance_settings.DeviceFeature.CoverTilt);
6337
6383
  return {
6338
- deviceType: require_ha_broker_source.DeviceType.Cover,
6384
+ deviceType: require_ha_instance_settings.DeviceType.Cover,
6339
6385
  role: coverRoleFor(deviceClass),
6340
6386
  capabilities: ["cover"],
6341
6387
  features
@@ -6345,23 +6391,23 @@ function mapCover(attributes, deviceClass) {
6345
6391
  function coverRoleFor(deviceClass) {
6346
6392
  switch (deviceClass) {
6347
6393
  case "blind":
6348
- case "shade": return require_ha_broker_source.DeviceRole.CoverBlind;
6349
- case "shutter": return require_ha_broker_source.DeviceRole.CoverShutter;
6350
- case "awning": return require_ha_broker_source.DeviceRole.CoverAwning;
6351
- case "curtain": return require_ha_broker_source.DeviceRole.CoverCurtain;
6352
- case "garage": return require_ha_broker_source.DeviceRole.CoverGarage;
6353
- case "gate": return require_ha_broker_source.DeviceRole.CoverGate;
6354
- case "door": return require_ha_broker_source.DeviceRole.CoverDoor;
6355
- case "window": return require_ha_broker_source.DeviceRole.CoverWindow;
6394
+ case "shade": return require_ha_instance_settings.DeviceRole.CoverBlind;
6395
+ case "shutter": return require_ha_instance_settings.DeviceRole.CoverShutter;
6396
+ case "awning": return require_ha_instance_settings.DeviceRole.CoverAwning;
6397
+ case "curtain": return require_ha_instance_settings.DeviceRole.CoverCurtain;
6398
+ case "garage": return require_ha_instance_settings.DeviceRole.CoverGarage;
6399
+ case "gate": return require_ha_instance_settings.DeviceRole.CoverGate;
6400
+ case "door": return require_ha_instance_settings.DeviceRole.CoverDoor;
6401
+ case "window": return require_ha_instance_settings.DeviceRole.CoverWindow;
6356
6402
  default: return null;
6357
6403
  }
6358
6404
  }
6359
6405
  function mapValve(attributes, _deviceClass) {
6360
6406
  const features = [];
6361
6407
  const sf = readNumericAttr(attributes, "supported_features");
6362
- if (sf !== null && (sf & 4) !== 0) features.push(require_ha_broker_source.DeviceFeature.ValvePositionable);
6408
+ if (sf !== null && (sf & 4) !== 0) features.push(require_ha_instance_settings.DeviceFeature.ValvePositionable);
6363
6409
  return {
6364
- deviceType: require_ha_broker_source.DeviceType.Valve,
6410
+ deviceType: require_ha_instance_settings.DeviceType.Valve,
6365
6411
  role: null,
6366
6412
  capabilities: ["valve"],
6367
6413
  features
@@ -6369,7 +6415,7 @@ function mapValve(attributes, _deviceClass) {
6369
6415
  }
6370
6416
  function mapHumidifier(_attributes, _deviceClass) {
6371
6417
  return {
6372
- deviceType: require_ha_broker_source.DeviceType.Humidifier,
6418
+ deviceType: require_ha_instance_settings.DeviceType.Humidifier,
6373
6419
  role: null,
6374
6420
  capabilities: ["humidifier"],
6375
6421
  features: []
@@ -6377,7 +6423,7 @@ function mapHumidifier(_attributes, _deviceClass) {
6377
6423
  }
6378
6424
  function mapWaterHeater(_attributes, _deviceClass) {
6379
6425
  return {
6380
- deviceType: require_ha_broker_source.DeviceType.WaterHeater,
6426
+ deviceType: require_ha_instance_settings.DeviceType.WaterHeater,
6381
6427
  role: null,
6382
6428
  capabilities: ["water-heater"],
6383
6429
  features: []
@@ -6387,13 +6433,13 @@ function mapFan(attributes) {
6387
6433
  const features = [];
6388
6434
  const sf = readNumericAttr(attributes, "supported_features");
6389
6435
  if (sf !== null) {
6390
- if ((sf & 1) !== 0) features.push(require_ha_broker_source.DeviceFeature.FanSpeed);
6391
- if ((sf & 2) !== 0) features.push(require_ha_broker_source.DeviceFeature.FanOscillating);
6392
- if ((sf & 4) !== 0) features.push(require_ha_broker_source.DeviceFeature.FanDirection);
6393
- if ((sf & 8) !== 0) features.push(require_ha_broker_source.DeviceFeature.FanPreset);
6436
+ if ((sf & 1) !== 0) features.push(require_ha_instance_settings.DeviceFeature.FanSpeed);
6437
+ if ((sf & 2) !== 0) features.push(require_ha_instance_settings.DeviceFeature.FanOscillating);
6438
+ if ((sf & 4) !== 0) features.push(require_ha_instance_settings.DeviceFeature.FanDirection);
6439
+ if ((sf & 8) !== 0) features.push(require_ha_instance_settings.DeviceFeature.FanPreset);
6394
6440
  }
6395
6441
  return {
6396
- deviceType: require_ha_broker_source.DeviceType.Fan,
6442
+ deviceType: require_ha_instance_settings.DeviceType.Fan,
6397
6443
  role: null,
6398
6444
  capabilities: ["switch", "fan-control"],
6399
6445
  features
@@ -6401,7 +6447,7 @@ function mapFan(attributes) {
6401
6447
  }
6402
6448
  function mapVacuum(_attributes) {
6403
6449
  return {
6404
- deviceType: require_ha_broker_source.DeviceType.Vacuum,
6450
+ deviceType: require_ha_instance_settings.DeviceType.Vacuum,
6405
6451
  role: null,
6406
6452
  capabilities: ["vacuum-control"],
6407
6453
  features: []
@@ -6409,7 +6455,7 @@ function mapVacuum(_attributes) {
6409
6455
  }
6410
6456
  function mapLawnMower(_attributes) {
6411
6457
  return {
6412
- deviceType: require_ha_broker_source.DeviceType.LawnMower,
6458
+ deviceType: require_ha_instance_settings.DeviceType.LawnMower,
6413
6459
  role: null,
6414
6460
  capabilities: ["lawn-mower-control"],
6415
6461
  features: []
@@ -6419,13 +6465,13 @@ function mapClimate(attributes) {
6419
6465
  const features = [];
6420
6466
  const sf = readNumericAttr(attributes, "supported_features");
6421
6467
  if (sf !== null) {
6422
- if ((sf & 2) !== 0) features.push(require_ha_broker_source.DeviceFeature.ClimateDualSetpoint);
6423
- if ((sf & 4) !== 0) features.push(require_ha_broker_source.DeviceFeature.ClimateHumidity);
6424
- if ((sf & 8) !== 0) features.push(require_ha_broker_source.DeviceFeature.ClimateFanMode);
6425
- if ((sf & 16) !== 0) features.push(require_ha_broker_source.DeviceFeature.ClimatePreset);
6468
+ if ((sf & 2) !== 0) features.push(require_ha_instance_settings.DeviceFeature.ClimateDualSetpoint);
6469
+ if ((sf & 4) !== 0) features.push(require_ha_instance_settings.DeviceFeature.ClimateHumidity);
6470
+ if ((sf & 8) !== 0) features.push(require_ha_instance_settings.DeviceFeature.ClimateFanMode);
6471
+ if ((sf & 16) !== 0) features.push(require_ha_instance_settings.DeviceFeature.ClimatePreset);
6426
6472
  }
6427
6473
  return {
6428
- deviceType: require_ha_broker_source.DeviceType.Thermostat,
6474
+ deviceType: require_ha_instance_settings.DeviceType.Thermostat,
6429
6475
  role: null,
6430
6476
  capabilities: ["climate-control"],
6431
6477
  features
@@ -6435,19 +6481,21 @@ function mapMediaPlayer(attributes) {
6435
6481
  const features = [];
6436
6482
  const sf = readNumericAttr(attributes, "supported_features");
6437
6483
  if (sf !== null) {
6438
- if ((sf & 2) !== 0) features.push(require_ha_broker_source.DeviceFeature.MediaPlayerSeek);
6439
- if ((sf & 4) !== 0) features.push(require_ha_broker_source.DeviceFeature.MediaPlayerVolume);
6440
- if ((sf & 8) !== 0) features.push(require_ha_broker_source.DeviceFeature.MediaPlayerMute);
6441
- if ((sf & 16) !== 0) features.push(require_ha_broker_source.DeviceFeature.MediaPlayerPrevious);
6442
- if ((sf & 32) !== 0) features.push(require_ha_broker_source.DeviceFeature.MediaPlayerNext);
6443
- if ((sf & 512) !== 0) features.push(require_ha_broker_source.DeviceFeature.MediaPlayerPlayMedia);
6444
- if ((sf & 2048) !== 0) features.push(require_ha_broker_source.DeviceFeature.MediaPlayerSelectSource);
6445
- if ((sf & 4096) !== 0) features.push(require_ha_broker_source.DeviceFeature.MediaPlayerStop);
6446
- if ((sf & 32768) !== 0) features.push(require_ha_broker_source.DeviceFeature.MediaPlayerShuffle);
6447
- if ((sf & 262144) !== 0) features.push(require_ha_broker_source.DeviceFeature.MediaPlayerRepeat);
6484
+ if ((sf & 2) !== 0) features.push(require_ha_instance_settings.DeviceFeature.MediaPlayerSeek);
6485
+ if ((sf & 4) !== 0) features.push(require_ha_instance_settings.DeviceFeature.MediaPlayerVolume);
6486
+ if ((sf & 8) !== 0) features.push(require_ha_instance_settings.DeviceFeature.MediaPlayerMute);
6487
+ if ((sf & 16) !== 0) features.push(require_ha_instance_settings.DeviceFeature.MediaPlayerPrevious);
6488
+ if ((sf & 32) !== 0) features.push(require_ha_instance_settings.DeviceFeature.MediaPlayerNext);
6489
+ if ((sf & 384) === 384) features.push(require_ha_instance_settings.DeviceFeature.MediaPlayerPower);
6490
+ if ((sf & 1024) !== 0) features.push(require_ha_instance_settings.DeviceFeature.MediaPlayerVolumeStep);
6491
+ if ((sf & 512) !== 0) features.push(require_ha_instance_settings.DeviceFeature.MediaPlayerPlayMedia);
6492
+ if ((sf & 2048) !== 0) features.push(require_ha_instance_settings.DeviceFeature.MediaPlayerSelectSource);
6493
+ if ((sf & 4096) !== 0) features.push(require_ha_instance_settings.DeviceFeature.MediaPlayerStop);
6494
+ if ((sf & 32768) !== 0) features.push(require_ha_instance_settings.DeviceFeature.MediaPlayerShuffle);
6495
+ if ((sf & 262144) !== 0) features.push(require_ha_instance_settings.DeviceFeature.MediaPlayerRepeat);
6448
6496
  }
6449
6497
  return {
6450
- deviceType: require_ha_broker_source.DeviceType.MediaPlayer,
6498
+ deviceType: require_ha_instance_settings.DeviceType.MediaPlayer,
6451
6499
  role: null,
6452
6500
  capabilities: ["media-player"],
6453
6501
  features
@@ -6455,9 +6503,9 @@ function mapMediaPlayer(attributes) {
6455
6503
  }
6456
6504
  function mapAlarmPanel(attributes) {
6457
6505
  const features = [];
6458
- if (attributes["code_format"] !== void 0 && attributes["code_format"] !== null) features.push(require_ha_broker_source.DeviceFeature.AlarmPinRequired);
6506
+ if (attributes["code_format"] !== void 0 && attributes["code_format"] !== null) features.push(require_ha_instance_settings.DeviceFeature.AlarmPinRequired);
6459
6507
  return {
6460
- deviceType: require_ha_broker_source.DeviceType.AlarmPanel,
6508
+ deviceType: require_ha_instance_settings.DeviceType.AlarmPanel,
6461
6509
  role: null,
6462
6510
  capabilities: ["alarm-panel"],
6463
6511
  features
@@ -6465,21 +6513,21 @@ function mapAlarmPanel(attributes) {
6465
6513
  }
6466
6514
  function mapNotifier(_attributes) {
6467
6515
  return {
6468
- deviceType: require_ha_broker_source.DeviceType.Notifier,
6469
- role: require_ha_broker_source.DeviceRole.GenericNotifier,
6516
+ deviceType: require_ha_instance_settings.DeviceType.Notifier,
6517
+ role: require_ha_instance_settings.DeviceRole.GenericNotifier,
6470
6518
  capabilities: ["notifier"]
6471
6519
  };
6472
6520
  }
6473
6521
  function mapWeather(_attributes) {
6474
6522
  return {
6475
- deviceType: require_ha_broker_source.DeviceType.Weather,
6523
+ deviceType: require_ha_instance_settings.DeviceType.Weather,
6476
6524
  role: null,
6477
6525
  capabilities: ["weather"]
6478
6526
  };
6479
6527
  }
6480
6528
  function mapImage(_attributes) {
6481
6529
  return {
6482
- deviceType: require_ha_broker_source.DeviceType.Image,
6530
+ deviceType: require_ha_instance_settings.DeviceType.Image,
6483
6531
  role: null,
6484
6532
  capabilities: ["image"]
6485
6533
  };
@@ -6493,60 +6541,60 @@ function isTemperatureUnit(unit) {
6493
6541
  function mapNumericSensor(deviceClass, _attributes) {
6494
6542
  switch (deviceClass) {
6495
6543
  case "temperature": return {
6496
- deviceType: require_ha_broker_source.DeviceType.Sensor,
6497
- role: require_ha_broker_source.DeviceRole.TemperatureSensor,
6544
+ deviceType: require_ha_instance_settings.DeviceType.Sensor,
6545
+ role: require_ha_instance_settings.DeviceRole.TemperatureSensor,
6498
6546
  capabilities: ["temperature-sensor"]
6499
6547
  };
6500
6548
  case "humidity": return {
6501
- deviceType: require_ha_broker_source.DeviceType.Sensor,
6502
- role: require_ha_broker_source.DeviceRole.HumiditySensor,
6549
+ deviceType: require_ha_instance_settings.DeviceType.Sensor,
6550
+ role: require_ha_instance_settings.DeviceRole.HumiditySensor,
6503
6551
  capabilities: ["humidity-sensor"]
6504
6552
  };
6505
6553
  case "illuminance": return {
6506
- deviceType: require_ha_broker_source.DeviceType.Sensor,
6507
- role: require_ha_broker_source.DeviceRole.AmbientLightSensor,
6554
+ deviceType: require_ha_instance_settings.DeviceType.Sensor,
6555
+ role: require_ha_instance_settings.DeviceRole.AmbientLightSensor,
6508
6556
  capabilities: ["ambient-light-sensor"]
6509
6557
  };
6510
6558
  case "pressure":
6511
6559
  case "atmospheric_pressure": return {
6512
- deviceType: require_ha_broker_source.DeviceType.Sensor,
6513
- role: require_ha_broker_source.DeviceRole.PressureSensor,
6560
+ deviceType: require_ha_instance_settings.DeviceType.Sensor,
6561
+ role: require_ha_instance_settings.DeviceRole.PressureSensor,
6514
6562
  capabilities: ["pressure-sensor"]
6515
6563
  };
6516
6564
  case "wind_speed": return {
6517
- deviceType: require_ha_broker_source.DeviceType.Sensor,
6518
- role: require_ha_broker_source.DeviceRole.WindSensor,
6565
+ deviceType: require_ha_instance_settings.DeviceType.Sensor,
6566
+ role: require_ha_instance_settings.DeviceRole.WindSensor,
6519
6567
  capabilities: ["numeric-sensor"]
6520
6568
  };
6521
6569
  case "precipitation":
6522
6570
  case "precipitation_intensity": return {
6523
- deviceType: require_ha_broker_source.DeviceType.Sensor,
6524
- role: require_ha_broker_source.DeviceRole.RainSensor,
6571
+ deviceType: require_ha_instance_settings.DeviceType.Sensor,
6572
+ role: require_ha_instance_settings.DeviceRole.RainSensor,
6525
6573
  capabilities: ["numeric-sensor"]
6526
6574
  };
6527
6575
  case "irradiance": return {
6528
- deviceType: require_ha_broker_source.DeviceType.Sensor,
6529
- role: require_ha_broker_source.DeviceRole.SolarRadiationSensor,
6576
+ deviceType: require_ha_instance_settings.DeviceType.Sensor,
6577
+ role: require_ha_instance_settings.DeviceRole.SolarRadiationSensor,
6530
6578
  capabilities: ["numeric-sensor"]
6531
6579
  };
6532
6580
  case "power": return {
6533
- deviceType: require_ha_broker_source.DeviceType.Sensor,
6534
- role: require_ha_broker_source.DeviceRole.PowerSensor,
6581
+ deviceType: require_ha_instance_settings.DeviceType.Sensor,
6582
+ role: require_ha_instance_settings.DeviceRole.PowerSensor,
6535
6583
  capabilities: ["power-meter"]
6536
6584
  };
6537
6585
  case "energy": return {
6538
- deviceType: require_ha_broker_source.DeviceType.Sensor,
6539
- role: require_ha_broker_source.DeviceRole.EnergySensor,
6586
+ deviceType: require_ha_instance_settings.DeviceType.Sensor,
6587
+ role: require_ha_instance_settings.DeviceRole.EnergySensor,
6540
6588
  capabilities: ["power-meter"]
6541
6589
  };
6542
6590
  case "voltage": return {
6543
- deviceType: require_ha_broker_source.DeviceType.Sensor,
6544
- role: require_ha_broker_source.DeviceRole.VoltageSensor,
6591
+ deviceType: require_ha_instance_settings.DeviceType.Sensor,
6592
+ role: require_ha_instance_settings.DeviceRole.VoltageSensor,
6545
6593
  capabilities: ["power-meter"]
6546
6594
  };
6547
6595
  case "current": return {
6548
- deviceType: require_ha_broker_source.DeviceType.Sensor,
6549
- role: require_ha_broker_source.DeviceRole.CurrentSensor,
6596
+ deviceType: require_ha_instance_settings.DeviceType.Sensor,
6597
+ role: require_ha_instance_settings.DeviceRole.CurrentSensor,
6550
6598
  capabilities: ["power-meter"]
6551
6599
  };
6552
6600
  case "pm1":
@@ -6559,46 +6607,46 @@ function mapNumericSensor(deviceClass, _attributes) {
6559
6607
  case "sulphur_dioxide":
6560
6608
  case "volatile_organic_compounds":
6561
6609
  case "aqi": return {
6562
- deviceType: require_ha_broker_source.DeviceType.Sensor,
6563
- role: require_ha_broker_source.DeviceRole.AirQualitySensor,
6610
+ deviceType: require_ha_instance_settings.DeviceType.Sensor,
6611
+ role: require_ha_instance_settings.DeviceRole.AirQualitySensor,
6564
6612
  capabilities: ["air-quality-sensor"]
6565
6613
  };
6566
6614
  case "battery": return {
6567
- deviceType: require_ha_broker_source.DeviceType.Sensor,
6568
- role: require_ha_broker_source.DeviceRole.BatterySensor,
6615
+ deviceType: require_ha_instance_settings.DeviceType.Sensor,
6616
+ role: require_ha_instance_settings.DeviceRole.BatterySensor,
6569
6617
  capabilities: ["numeric-sensor"]
6570
6618
  };
6571
6619
  case "enum": return {
6572
- deviceType: require_ha_broker_source.DeviceType.Sensor,
6573
- role: require_ha_broker_source.DeviceRole.EnumSensor,
6620
+ deviceType: require_ha_instance_settings.DeviceType.Sensor,
6621
+ role: require_ha_instance_settings.DeviceRole.EnumSensor,
6574
6622
  capabilities: ["enum-sensor"]
6575
6623
  };
6576
6624
  case "timestamp": return {
6577
- deviceType: require_ha_broker_source.DeviceType.Sensor,
6578
- role: require_ha_broker_source.DeviceRole.DateTimeSensor,
6625
+ deviceType: require_ha_instance_settings.DeviceType.Sensor,
6626
+ role: require_ha_instance_settings.DeviceRole.DateTimeSensor,
6579
6627
  capabilities: ["enum-sensor"],
6580
6628
  dateTimeFormat: "datetime"
6581
6629
  };
6582
6630
  case "date": return {
6583
- deviceType: require_ha_broker_source.DeviceType.Sensor,
6584
- role: require_ha_broker_source.DeviceRole.DateTimeSensor,
6631
+ deviceType: require_ha_instance_settings.DeviceType.Sensor,
6632
+ role: require_ha_instance_settings.DeviceRole.DateTimeSensor,
6585
6633
  capabilities: ["enum-sensor"],
6586
6634
  dateTimeFormat: "date"
6587
6635
  };
6588
6636
  case null:
6589
6637
  if (isTemperatureUnit(_attributes["unit_of_measurement"])) return {
6590
- deviceType: require_ha_broker_source.DeviceType.Sensor,
6591
- role: require_ha_broker_source.DeviceRole.TemperatureSensor,
6638
+ deviceType: require_ha_instance_settings.DeviceType.Sensor,
6639
+ role: require_ha_instance_settings.DeviceRole.TemperatureSensor,
6592
6640
  capabilities: ["temperature-sensor"]
6593
6641
  };
6594
6642
  return {
6595
- deviceType: require_ha_broker_source.DeviceType.Sensor,
6596
- role: require_ha_broker_source.DeviceRole.EnumSensor,
6643
+ deviceType: require_ha_instance_settings.DeviceType.Sensor,
6644
+ role: require_ha_instance_settings.DeviceRole.EnumSensor,
6597
6645
  capabilities: ["enum-sensor"]
6598
6646
  };
6599
6647
  default: return {
6600
- deviceType: require_ha_broker_source.DeviceType.Sensor,
6601
- role: require_ha_broker_source.DeviceRole.NumericSensor,
6648
+ deviceType: require_ha_instance_settings.DeviceType.Sensor,
6649
+ role: require_ha_instance_settings.DeviceRole.NumericSensor,
6602
6650
  capabilities: ["numeric-sensor"]
6603
6651
  };
6604
6652
  }
@@ -6609,67 +6657,67 @@ function mapBinarySensor(deviceClass) {
6609
6657
  case "occupancy":
6610
6658
  case "presence":
6611
6659
  case "moving": return {
6612
- deviceType: require_ha_broker_source.DeviceType.Sensor,
6613
- role: require_ha_broker_source.DeviceRole.MotionSensor,
6660
+ deviceType: require_ha_instance_settings.DeviceType.Sensor,
6661
+ role: require_ha_instance_settings.DeviceRole.MotionSensor,
6614
6662
  capabilities: ["motion"]
6615
6663
  };
6616
6664
  case "door":
6617
6665
  case "window":
6618
6666
  case "garage_door":
6619
6667
  case "opening": return {
6620
- deviceType: require_ha_broker_source.DeviceType.Sensor,
6621
- role: require_ha_broker_source.DeviceRole.ContactSensor,
6668
+ deviceType: require_ha_instance_settings.DeviceType.Sensor,
6669
+ role: require_ha_instance_settings.DeviceRole.ContactSensor,
6622
6670
  capabilities: ["contact"]
6623
6671
  };
6624
6672
  case "moisture": return {
6625
- deviceType: require_ha_broker_source.DeviceType.Sensor,
6626
- role: require_ha_broker_source.DeviceRole.LeakSensor,
6673
+ deviceType: require_ha_instance_settings.DeviceType.Sensor,
6674
+ role: require_ha_instance_settings.DeviceRole.LeakSensor,
6627
6675
  capabilities: ["flood"]
6628
6676
  };
6629
6677
  case "smoke": return {
6630
- deviceType: require_ha_broker_source.DeviceType.Sensor,
6631
- role: require_ha_broker_source.DeviceRole.SmokeSensor,
6678
+ deviceType: require_ha_instance_settings.DeviceType.Sensor,
6679
+ role: require_ha_instance_settings.DeviceRole.SmokeSensor,
6632
6680
  capabilities: ["smoke"]
6633
6681
  };
6634
6682
  case "carbon_monoxide": return {
6635
- deviceType: require_ha_broker_source.DeviceType.Sensor,
6636
- role: require_ha_broker_source.DeviceRole.COSensor,
6683
+ deviceType: require_ha_instance_settings.DeviceType.Sensor,
6684
+ role: require_ha_instance_settings.DeviceRole.COSensor,
6637
6685
  capabilities: ["carbon-monoxide"]
6638
6686
  };
6639
6687
  case "gas": return {
6640
- deviceType: require_ha_broker_source.DeviceType.Sensor,
6641
- role: require_ha_broker_source.DeviceRole.GasSensor,
6688
+ deviceType: require_ha_instance_settings.DeviceType.Sensor,
6689
+ role: require_ha_instance_settings.DeviceRole.GasSensor,
6642
6690
  capabilities: ["gas"]
6643
6691
  };
6644
6692
  case "tamper":
6645
6693
  case "safety": return {
6646
- deviceType: require_ha_broker_source.DeviceType.Sensor,
6647
- role: require_ha_broker_source.DeviceRole.TamperSensor,
6694
+ deviceType: require_ha_instance_settings.DeviceType.Sensor,
6695
+ role: require_ha_instance_settings.DeviceRole.TamperSensor,
6648
6696
  capabilities: ["tamper"]
6649
6697
  };
6650
6698
  case "vibration": return {
6651
- deviceType: require_ha_broker_source.DeviceType.Sensor,
6652
- role: require_ha_broker_source.DeviceRole.VibrationSensor,
6699
+ deviceType: require_ha_instance_settings.DeviceType.Sensor,
6700
+ role: require_ha_instance_settings.DeviceRole.VibrationSensor,
6653
6701
  capabilities: ["vibration"]
6654
6702
  };
6655
6703
  case "connectivity": return {
6656
- deviceType: require_ha_broker_source.DeviceType.Sensor,
6657
- role: require_ha_broker_source.DeviceRole.ConnectivitySensor,
6704
+ deviceType: require_ha_instance_settings.DeviceType.Sensor,
6705
+ role: require_ha_instance_settings.DeviceRole.ConnectivitySensor,
6658
6706
  capabilities: ["connectivity"]
6659
6707
  };
6660
6708
  case "sound": return {
6661
- deviceType: require_ha_broker_source.DeviceType.Sensor,
6662
- role: require_ha_broker_source.DeviceRole.SoundSensor,
6709
+ deviceType: require_ha_instance_settings.DeviceType.Sensor,
6710
+ role: require_ha_instance_settings.DeviceRole.SoundSensor,
6663
6711
  capabilities: ["binary"]
6664
6712
  };
6665
6713
  case "battery": return {
6666
- deviceType: require_ha_broker_source.DeviceType.Sensor,
6667
- role: require_ha_broker_source.DeviceRole.BatterySensor,
6714
+ deviceType: require_ha_instance_settings.DeviceType.Sensor,
6715
+ role: require_ha_instance_settings.DeviceRole.BatterySensor,
6668
6716
  capabilities: ["binary"]
6669
6717
  };
6670
6718
  default: return {
6671
- deviceType: require_ha_broker_source.DeviceType.Sensor,
6672
- role: require_ha_broker_source.DeviceRole.BinarySensor,
6719
+ deviceType: require_ha_instance_settings.DeviceType.Sensor,
6720
+ role: require_ha_instance_settings.DeviceRole.BinarySensor,
6673
6721
  capabilities: ["binary"]
6674
6722
  };
6675
6723
  }
@@ -6692,40 +6740,40 @@ function readNumericAttr(attributes, key) {
6692
6740
  * Sensor; an HA-tracked light with motion sensor becomes Light).
6693
6741
  */
6694
6742
  var PARENT_TYPE_PRIORITY = [
6695
- require_ha_broker_source.DeviceType.MediaPlayer,
6696
- require_ha_broker_source.DeviceType.AlarmPanel,
6697
- require_ha_broker_source.DeviceType.Thermostat,
6698
- require_ha_broker_source.DeviceType.Climate,
6699
- require_ha_broker_source.DeviceType.Humidifier,
6700
- require_ha_broker_source.DeviceType.WaterHeater,
6701
- require_ha_broker_source.DeviceType.Lock,
6702
- require_ha_broker_source.DeviceType.Cover,
6703
- require_ha_broker_source.DeviceType.Valve,
6704
- require_ha_broker_source.DeviceType.Fan,
6705
- require_ha_broker_source.DeviceType.Vacuum,
6706
- require_ha_broker_source.DeviceType.LawnMower,
6707
- require_ha_broker_source.DeviceType.Washer,
6708
- require_ha_broker_source.DeviceType.Dryer,
6709
- require_ha_broker_source.DeviceType.Dishwasher,
6710
- require_ha_broker_source.DeviceType.Light,
6711
- require_ha_broker_source.DeviceType.Switch,
6712
- require_ha_broker_source.DeviceType.Siren,
6713
- require_ha_broker_source.DeviceType.Button,
6714
- require_ha_broker_source.DeviceType.Control,
6715
- require_ha_broker_source.DeviceType.Notifier,
6716
- require_ha_broker_source.DeviceType.Script,
6717
- require_ha_broker_source.DeviceType.Automation,
6718
- require_ha_broker_source.DeviceType.Update,
6719
- require_ha_broker_source.DeviceType.Presence,
6720
- require_ha_broker_source.DeviceType.Weather,
6721
- require_ha_broker_source.DeviceType.Image,
6722
- require_ha_broker_source.DeviceType.Sensor
6743
+ require_ha_instance_settings.DeviceType.MediaPlayer,
6744
+ require_ha_instance_settings.DeviceType.AlarmPanel,
6745
+ require_ha_instance_settings.DeviceType.Thermostat,
6746
+ require_ha_instance_settings.DeviceType.Climate,
6747
+ require_ha_instance_settings.DeviceType.Humidifier,
6748
+ require_ha_instance_settings.DeviceType.WaterHeater,
6749
+ require_ha_instance_settings.DeviceType.Lock,
6750
+ require_ha_instance_settings.DeviceType.Cover,
6751
+ require_ha_instance_settings.DeviceType.Valve,
6752
+ require_ha_instance_settings.DeviceType.Fan,
6753
+ require_ha_instance_settings.DeviceType.Vacuum,
6754
+ require_ha_instance_settings.DeviceType.LawnMower,
6755
+ require_ha_instance_settings.DeviceType.Washer,
6756
+ require_ha_instance_settings.DeviceType.Dryer,
6757
+ require_ha_instance_settings.DeviceType.Dishwasher,
6758
+ require_ha_instance_settings.DeviceType.Light,
6759
+ require_ha_instance_settings.DeviceType.Switch,
6760
+ require_ha_instance_settings.DeviceType.Siren,
6761
+ require_ha_instance_settings.DeviceType.Button,
6762
+ require_ha_instance_settings.DeviceType.Control,
6763
+ require_ha_instance_settings.DeviceType.Notifier,
6764
+ require_ha_instance_settings.DeviceType.Script,
6765
+ require_ha_instance_settings.DeviceType.Automation,
6766
+ require_ha_instance_settings.DeviceType.Update,
6767
+ require_ha_instance_settings.DeviceType.Presence,
6768
+ require_ha_instance_settings.DeviceType.Weather,
6769
+ require_ha_instance_settings.DeviceType.Image,
6770
+ require_ha_instance_settings.DeviceType.Sensor
6723
6771
  ];
6724
6772
  function inferParentDeviceType(mappings) {
6725
6773
  const set = /* @__PURE__ */ new Set();
6726
6774
  for (const m of mappings) if (m) set.add(m.deviceType);
6727
6775
  for (const dt of PARENT_TYPE_PRIORITY) if (set.has(dt)) return dt;
6728
- return require_ha_broker_source.DeviceType.Generic;
6776
+ return require_ha_instance_settings.DeviceType.Generic;
6729
6777
  }
6730
6778
  //#endregion
6731
6779
  //#region src/ha-candidate-mapper.ts
@@ -6747,7 +6795,7 @@ function haDeviceToCandidate(dev) {
6747
6795
  return {
6748
6796
  childNativeId: e.entityId,
6749
6797
  name: e.name,
6750
- type: e.mappedTo?.deviceType ?? require_ha_broker_source.DeviceType.Generic,
6798
+ type: e.mappedTo?.deviceType ?? require_ha_instance_settings.DeviceType.Generic,
6751
6799
  status: entityStatus$1(e.state),
6752
6800
  metadata: e.area !== null ? { externalLocation: e.area } : {},
6753
6801
  alreadyAdopted: e.alreadyAdopted,
@@ -6894,7 +6942,7 @@ function buildDiscoveryCandidates(input) {
6894
6942
  };
6895
6943
  candidates.push({
6896
6944
  stableId,
6897
- type: require_ha_broker_source.DeviceType.Container,
6945
+ type: require_ha_instance_settings.DeviceType.Container,
6898
6946
  suggestedName,
6899
6947
  prefilledConfig,
6900
6948
  sourceInfo
@@ -6922,52 +6970,52 @@ function buildDiscoveryCandidates(input) {
6922
6970
  * shown as a Devices-tab candidate.
6923
6971
  */
6924
6972
  var HA_ORPHAN_ENTITIES_DEVICE_ID = "__ha_orphan_entities__";
6925
- var HaEntityMappingSchema = require_ha_broker_source.object({
6973
+ var HaEntityMappingSchema = require_ha_instance_settings.object({
6926
6974
  /** CamStack DeviceType for the accessory child. */
6927
- deviceType: require_ha_broker_source._enum(require_ha_broker_source.DeviceType),
6975
+ deviceType: require_ha_instance_settings._enum(require_ha_instance_settings.DeviceType),
6928
6976
  /** Optional CamStack DeviceRole sub-role (e.g. `ContactSensor` for
6929
6977
  * a binary_sensor with `device_class: door`). */
6930
- role: require_ha_broker_source._enum(require_ha_broker_source.DeviceRole).nullable(),
6978
+ role: require_ha_instance_settings._enum(require_ha_instance_settings.DeviceRole).nullable(),
6931
6979
  /** Capability names the accessory child will register
6932
6980
  * (`switch` / `temperature-sensor` / …). UI may render the cap
6933
6981
  * badges to help the operator decide what to hide. */
6934
- capabilities: require_ha_broker_source.array(require_ha_broker_source.string()).readonly(),
6982
+ capabilities: require_ha_instance_settings.array(require_ha_instance_settings.string()).readonly(),
6935
6983
  /** Mapping-derived DeviceFeature flags (e.g. `lock-open`). Persisted onto
6936
6984
  * the child's `device.features` so the UI gates feature affordances. */
6937
- features: require_ha_broker_source.array(require_ha_broker_source.string()).readonly().optional(),
6985
+ features: require_ha_instance_settings.array(require_ha_instance_settings.string()).readonly().optional(),
6938
6986
  /** Locale-render shape for a `DateTimeSensor`-role enum sensor
6939
6987
  * (`device_class=timestamp` → `'datetime'`, `date` → `'date'`). Threaded
6940
6988
  * onto the child config so the enum-sensor device seeds it into the cap
6941
6989
  * slice. Absent for every non-DateTimeSensor mapping. */
6942
- dateTimeFormat: require_ha_broker_source.EnumSensorDateTimeFormatSchema.optional()
6990
+ dateTimeFormat: require_ha_instance_settings.EnumSensorDateTimeFormatSchema.optional()
6943
6991
  }).nullable();
6944
- var HaDiscoveredEntitySchema = require_ha_broker_source.object({
6992
+ var HaDiscoveredEntitySchema = require_ha_instance_settings.object({
6945
6993
  /** Fully-qualified HA entity id (`switch.kitchen`). */
6946
- entityId: require_ha_broker_source.string(),
6994
+ entityId: require_ha_instance_settings.string(),
6947
6995
  /** HA domain — first segment of entity_id (`switch` / `light` /
6948
6996
  * `sensor` / `binary_sensor` / `cover` / …). */
6949
- domain: require_ha_broker_source.string(),
6997
+ domain: require_ha_instance_settings.string(),
6950
6998
  /** Operator-visible friendly name (HA `friendly_name` attribute or
6951
6999
  * the entity_id when missing). */
6952
- name: require_ha_broker_source.string(),
7000
+ name: require_ha_instance_settings.string(),
6953
7001
  /** Current state value (e.g. `'on'`, `'21.5'`, `'open'`). */
6954
- state: require_ha_broker_source.string(),
7002
+ state: require_ha_instance_settings.string(),
6955
7003
  /** HA `device_class` attribute when present — drives the role +
6956
7004
  * cap mapping for sensors / binary_sensors / covers. */
6957
- deviceClass: require_ha_broker_source.string().nullable(),
7005
+ deviceClass: require_ha_instance_settings.string().nullable(),
6958
7006
  /** HA `unit_of_measurement` attribute when present. */
6959
- unitOfMeasurement: require_ha_broker_source.string().nullable(),
7007
+ unitOfMeasurement: require_ha_instance_settings.string().nullable(),
6960
7008
  /** Area name for this entity — the entity's own HA area if set, else its
6961
7009
  * parent device's area. Null when neither is assigned. */
6962
- area: require_ha_broker_source.string().nullable().default(null),
7010
+ area: require_ha_instance_settings.string().nullable().default(null),
6963
7011
  /** HA `options` attribute — present on `select` / `input_select` entities.
6964
7012
  * Captured at discovery so the adopt handler can persist them alongside
6965
7013
  * other entity config fields. Absent on non-select entities. */
6966
- options: require_ha_broker_source.array(require_ha_broker_source.string()).nullable().default(null),
7014
+ options: require_ha_instance_settings.array(require_ha_instance_settings.string()).nullable().default(null),
6967
7015
  /** HA `entity_category` — `config` / `diagnostic` / null (a normal control).
6968
7016
  * Drives the accordion section the adopted child renders in. Null/absent for
6969
7017
  * the common control case. */
6970
- entityCategory: require_ha_broker_source._enum(["config", "diagnostic"]).nullable().default(null),
7018
+ entityCategory: require_ha_instance_settings._enum(["config", "diagnostic"]).nullable().default(null),
6971
7019
  /** Pre-computed CamStack mapping. `null` when the entity's domain
6972
7020
  * has no supported mapping (the operator may still adopt the
6973
7021
  * parent — the entity will be skipped or surfaced as a fallback). */
@@ -6975,48 +7023,48 @@ var HaDiscoveredEntitySchema = require_ha_broker_source.object({
6975
7023
  /** When `true`, the entity was already materialised as a CamStack
6976
7024
  * accessory child under a prior adoption — surfaced so the UI can
6977
7025
  * highlight existing wiring. */
6978
- alreadyAdopted: require_ha_broker_source.boolean(),
7026
+ alreadyAdopted: require_ha_instance_settings.boolean(),
6979
7027
  /** When `alreadyAdopted === true`, the kernel-assigned accessory
6980
7028
  * child id. */
6981
- adoptedCamDeviceId: require_ha_broker_source.number().int().nonnegative().nullable()
7029
+ adoptedCamDeviceId: require_ha_instance_settings.number().int().nonnegative().nullable()
6982
7030
  });
6983
- require_ha_broker_source.object({
7031
+ require_ha_instance_settings.object({
6984
7032
  /** Stable HA `device_registry` id — survives renames + restarts. */
6985
- haDeviceId: require_ha_broker_source.string(),
7033
+ haDeviceId: require_ha_instance_settings.string(),
6986
7034
  /** Operator-visible name (HA device `name` or first entity's
6987
7035
  * friendly_name when device has none). */
6988
- name: require_ha_broker_source.string(),
7036
+ name: require_ha_instance_settings.string(),
6989
7037
  /** Area name from HA `area_registry` join. Null when unassigned. */
6990
- area: require_ha_broker_source.string().nullable(),
6991
- manufacturer: require_ha_broker_source.string().nullable(),
6992
- model: require_ha_broker_source.string().nullable(),
6993
- swVersion: require_ha_broker_source.string().nullable(),
7038
+ area: require_ha_instance_settings.string().nullable(),
7039
+ manufacturer: require_ha_instance_settings.string().nullable(),
7040
+ model: require_ha_instance_settings.string().nullable(),
7041
+ swVersion: require_ha_instance_settings.string().nullable(),
6994
7042
  /** Dominant integration / platform domain for this device, derived from its
6995
7043
  * entities' HA `entity_registry.platform` (e.g. `dreame_vacuum`). Generic /
6996
7044
  * helper platforms (`unifi` / `hacs` / `hassio`) are excluded when a real
6997
7045
  * platform is available. Null when the device has no entities. */
6998
- integration: require_ha_broker_source.string().nullable().default(null),
7046
+ integration: require_ha_instance_settings.string().nullable().default(null),
6999
7047
  /** Convenience field — count of `entities[]`. */
7000
- entityCount: require_ha_broker_source.number().int().nonnegative(),
7048
+ entityCount: require_ha_instance_settings.number().int().nonnegative(),
7001
7049
  /** Every entity HA's `entity_registry` links to this device. The
7002
7050
  * list survives row collapse — full devices are returned so
7003
7051
  * accordion expansion is a no-roundtrip render. */
7004
- entities: require_ha_broker_source.array(HaDiscoveredEntitySchema).readonly(),
7052
+ entities: require_ha_instance_settings.array(HaDiscoveredEntitySchema).readonly(),
7005
7053
  /** Whether this HA device has an active CamStack adoption. */
7006
- alreadyAdopted: require_ha_broker_source.boolean(),
7054
+ alreadyAdopted: require_ha_instance_settings.boolean(),
7007
7055
  /** When `alreadyAdopted === true`, the kernel-assigned parent id. */
7008
- adoptedCamDeviceId: require_ha_broker_source.number().int().nonnegative().nullable()
7056
+ adoptedCamDeviceId: require_ha_instance_settings.number().int().nonnegative().nullable()
7009
7057
  });
7010
- require_ha_broker_source.object({
7058
+ require_ha_instance_settings.object({
7011
7059
  /** Last refresh timestamp (ms epoch) — null when never refreshed. */
7012
- lastDiscoveryAt: require_ha_broker_source.number().int().nonnegative().nullable(),
7060
+ lastDiscoveryAt: require_ha_instance_settings.number().int().nonnegative().nullable(),
7013
7061
  /** Count of HA devices in the discovery cache (across all brokers). */
7014
- deviceCount: require_ha_broker_source.number().int().nonnegative(),
7062
+ deviceCount: require_ha_instance_settings.number().int().nonnegative(),
7015
7063
  /** Count of HA devices currently materialised as CamStack parent
7016
7064
  * devices. */
7017
- adoptedCount: require_ha_broker_source.number().int().nonnegative(),
7065
+ adoptedCount: require_ha_instance_settings.number().int().nonnegative(),
7018
7066
  /** Last error message from a refresh attempt. */
7019
- lastError: require_ha_broker_source.string().nullable()
7067
+ lastError: require_ha_instance_settings.string().nullable()
7020
7068
  });
7021
7069
  //#endregion
7022
7070
  //#region src/ha-integration-domain.ts
@@ -7155,7 +7203,7 @@ function negotiateEncoding(acceptEncoding) {
7155
7203
  }
7156
7204
  /** Build the `addon-routes` provider that serves the bundled Home Assistant icon. */
7157
7205
  function createHaIconRouteProvider() {
7158
- return require_ha_broker_source.buildAddonRouteProvider(HA_ROUTE_ID, [{
7206
+ return require_ha_instance_settings.buildAddonRouteProvider(HA_ROUTE_ID, [{
7159
7207
  method: "GET",
7160
7208
  path: `/icons/${HA_ICON_KIND}`,
7161
7209
  access: "public",
@@ -7172,16 +7220,24 @@ function createHaIconRouteProvider() {
7172
7220
  //#region src/broker-record-kinds.ts
7173
7221
  /**
7174
7222
  * Broker entry kind (B2): credentials live in records; integrations keep brokerId.
7223
+ *
7224
+ * The body is FLAT (planning#408 P3): the form the instances page edits is the stored shape,
7225
+ * with the two tokens at the top level where the records door keeps them in the keychain.
7175
7226
  */
7176
7227
  var HA_BROKERS_KIND = "brokers";
7177
- var HaBrokerBodySchema = require_ha_broker_source.entryBody({
7178
- auth: HaBrokerEntrySchema.shape.auth,
7179
- integrationId: require_ha_broker_source.string().optional()
7228
+ var HaBrokerBodySchema = require_ha_instance_settings.entryBody({
7229
+ authKind: HaBrokerEntrySchema.shape.authKind,
7230
+ baseUrl: HaBrokerEntrySchema.shape.baseUrl,
7231
+ accessToken: HaBrokerEntrySchema.shape.accessToken,
7232
+ supervisorToken: HaBrokerEntrySchema.shape.supervisorToken,
7233
+ integrationId: HaBrokerEntrySchema.shape.integrationId,
7234
+ enabled: HaBrokerEntrySchema.shape.enabled
7180
7235
  });
7181
- var haBrokersEntryKind = require_ha_broker_source.defineEntryKind(HA_BROKERS_KIND, {
7236
+ var haBrokersEntryKind = require_ha_instance_settings.defineEntryKind(HA_BROKERS_KIND, {
7182
7237
  title: "Home Assistant brokers",
7183
7238
  schema: HaBrokerBodySchema,
7184
- writeTrigger: "an operator adds, edits or removes a Home Assistant broker connection"
7239
+ writeTrigger: "an operator adds, edits or removes a Home Assistant broker connection",
7240
+ retiredSecretPaths: ["auth.accessToken", "auth.supervisorToken"]
7185
7241
  });
7186
7242
  //#endregion
7187
7243
  //#region src/record-kinds.ts
@@ -7192,8 +7248,8 @@ var haBrokersEntryKind = require_ha_broker_source.defineEntryKind(HA_BROKERS_KIN
7192
7248
  * credential — delivery reuses the broker WebSocket connection (the token
7193
7249
  * lives in the broker config, not in the target).
7194
7250
  */
7195
- var HaTargetBodySchema = require_ha_broker_source.TargetSchema.omit({ id: true });
7196
- var haRecordKinds = require_ha_broker_source.defineRecordKinds({
7251
+ var HaTargetBodySchema = require_ha_instance_settings.TargetSchema.omit({ id: true });
7252
+ var haRecordKinds = require_ha_instance_settings.defineRecordKinds({
7197
7253
  /**
7198
7254
  * One row per configured Home Assistant push target. Operator-managed via the
7199
7255
  * notification-output cap CRUD; no TTL.
@@ -7259,7 +7315,7 @@ function haConfigSchema() {
7259
7315
  labelKey: "provider-homeassistant:haConfig.s_connection.brokerId.label",
7260
7316
  description: "The Home Assistant connection the notification goes through.",
7261
7317
  descriptionKey: "provider-homeassistant:haConfig.s_connection.brokerId.description",
7262
- brokerKind: require_ha_broker_source.HA_BROKER_KIND
7318
+ brokerKind: require_ha_instance_settings.HA_BROKER_KIND
7263
7319
  }, {
7264
7320
  type: "select",
7265
7321
  key: "service",
@@ -7499,7 +7555,7 @@ var HaTargetStore = class HaTargetStore {
7499
7555
  const page = await this.kind.query({ limit: 1e3 });
7500
7556
  const out = [];
7501
7557
  for (const record of page.records) {
7502
- const parsed = require_ha_broker_source.TargetSchema.safeParse({
7558
+ const parsed = require_ha_instance_settings.TargetSchema.safeParse({
7503
7559
  id: record.id,
7504
7560
  ...record.data
7505
7561
  });
@@ -7510,7 +7566,7 @@ var HaTargetStore = class HaTargetStore {
7510
7566
  async getById(id) {
7511
7567
  const row = await this.kind.get(id);
7512
7568
  if (row === null) return null;
7513
- const parsed = require_ha_broker_source.TargetSchema.safeParse({
7569
+ const parsed = require_ha_instance_settings.TargetSchema.safeParse({
7514
7570
  id: row.id,
7515
7571
  ...row.data
7516
7572
  });
@@ -7571,12 +7627,12 @@ function createHaNotificationOutputProvider(deps) {
7571
7627
  }
7572
7628
  /** Degrade → build → publish. NEVER throws through the cap. */
7573
7629
  async function dispatch(target, raw) {
7574
- const notification = deps.readPublicEndpoint === void 0 ? raw : await require_ha_broker_source.resolveAttachmentUrls({
7630
+ const notification = deps.readPublicEndpoint === void 0 ? raw : await require_ha_instance_settings.resolveAttachmentUrls({
7575
7631
  notification: raw,
7576
7632
  readPublicEndpoint: deps.readPublicEndpoint,
7577
7633
  ...logger !== void 0 ? { logger } : {}
7578
7634
  });
7579
- const prepared = require_ha_broker_source.prepareNotification(descriptor.caps, notification);
7635
+ const prepared = require_ha_instance_settings.prepareNotification(descriptor.caps, notification);
7580
7636
  const service = readService(target.config);
7581
7637
  if (!service) return {
7582
7638
  success: false,
@@ -7600,11 +7656,11 @@ function createHaNotificationOutputProvider(deps) {
7600
7656
  logger?.warn("ha notify publish failed", { meta: {
7601
7657
  brokerId,
7602
7658
  service,
7603
- error: require_ha_broker_source.errMsg(err)
7659
+ error: require_ha_instance_settings.errMsg(err)
7604
7660
  } });
7605
7661
  return {
7606
7662
  success: false,
7607
- error: require_ha_broker_source.errMsg(err),
7663
+ error: require_ha_instance_settings.errMsg(err),
7608
7664
  renderedAs: prepared.renderedAs
7609
7665
  };
7610
7666
  }
@@ -7643,7 +7699,7 @@ function createHaNotificationOutputProvider(deps) {
7643
7699
  } catch (err) {
7644
7700
  logger?.warn("ha device registry read failed; naming services from their ids", { meta: {
7645
7701
  brokerId,
7646
- error: require_ha_broker_source.errMsg(err)
7702
+ error: require_ha_instance_settings.errMsg(err)
7647
7703
  } });
7648
7704
  return /* @__PURE__ */ new Map();
7649
7705
  }
@@ -7657,7 +7713,7 @@ function createHaNotificationOutputProvider(deps) {
7657
7713
  } catch (err) {
7658
7714
  logger?.warn("ha get_services discovery failed", { meta: {
7659
7715
  brokerId,
7660
- error: require_ha_broker_source.errMsg(err)
7716
+ error: require_ha_instance_settings.errMsg(err)
7661
7717
  } });
7662
7718
  }
7663
7719
  return out;
@@ -7713,8 +7769,12 @@ function rowToEntry(id, data) {
7713
7769
  const parsed = HaBrokerEntrySchema.safeParse({
7714
7770
  id,
7715
7771
  name: data.name,
7716
- auth: data.auth,
7717
- integrationId: data.integrationId
7772
+ authKind: data.authKind,
7773
+ baseUrl: data.baseUrl,
7774
+ accessToken: data.accessToken,
7775
+ supervisorToken: data.supervisorToken,
7776
+ integrationId: data.integrationId,
7777
+ enabled: data.enabled
7718
7778
  });
7719
7779
  return parsed.success ? parsed.data : null;
7720
7780
  }
@@ -7735,7 +7795,7 @@ var HaBrokerStore = class HaBrokerStore {
7735
7795
  const resolved = await this.kind.getResolved(record.id);
7736
7796
  if (resolved !== null) data = resolved.data;
7737
7797
  } catch (err) {
7738
- if (!(err instanceof require_ha_broker_source.RecordSecretUnavailableError)) throw err;
7798
+ if (!(err instanceof require_ha_instance_settings.RecordSecretUnavailableError)) throw err;
7739
7799
  }
7740
7800
  const entry = rowToEntry(record.id, data);
7741
7801
  if (entry !== null) out.push(entry);
@@ -7748,15 +7808,14 @@ var HaBrokerStore = class HaBrokerStore {
7748
7808
  if (row === null) return null;
7749
7809
  return rowToEntry(row.id, row.data);
7750
7810
  } catch (err) {
7751
- if (err instanceof require_ha_broker_source.RecordSecretUnavailableError) return null;
7811
+ if (err instanceof require_ha_instance_settings.RecordSecretUnavailableError) return null;
7752
7812
  throw err;
7753
7813
  }
7754
7814
  }
7755
7815
  async upsert(entry) {
7756
- const { id, name, auth, integrationId } = entry;
7816
+ const { id, integrationId, ...fields } = entry;
7757
7817
  const body = {
7758
- name,
7759
- auth,
7818
+ ...Object.fromEntries(Object.entries(fields).filter(([, v]) => v !== void 0)),
7760
7819
  ...integrationId === void 0 ? {} : { integrationId }
7761
7820
  };
7762
7821
  const parsed = haBrokersEntryKind.schema.safeParse(body);
@@ -7777,6 +7836,97 @@ var HaBrokerStore = class HaBrokerStore {
7777
7836
  }
7778
7837
  };
7779
7838
  //#endregion
7839
+ //#region src/ha-instances.ts
7840
+ /**
7841
+ * The Home Assistant connections as `integration-instances` (planning#408 P3): one instance per
7842
+ * `brokers` record, over the SAME records and ids (`ha_NNN`) the `broker` cap serves. The body is
7843
+ * flat, so the form the instances page edits is the stored shape.
7844
+ */
7845
+ var HA_INSTANCE_KIND = "home-assistant";
7846
+ function isHaBodyConfigured(body) {
7847
+ return body.authKind === "supervisor" ? (body.supervisorToken ?? "").length > 0 : (body.baseUrl ?? "").length > 0 && (body.accessToken ?? "").length > 0;
7848
+ }
7849
+ function statusOf(info) {
7850
+ if (info === null) return {
7851
+ state: "unknown",
7852
+ label: "Not connected"
7853
+ };
7854
+ if (info.status === "connected") return {
7855
+ state: "ok",
7856
+ label: "Connected"
7857
+ };
7858
+ if (info.status === "connecting") return {
7859
+ state: "unknown",
7860
+ label: "Connecting"
7861
+ };
7862
+ return {
7863
+ state: "error",
7864
+ label: info.status,
7865
+ ...info.error !== null ? { detail: info.error } : {}
7866
+ };
7867
+ }
7868
+ function buildHaInstances(records, deps) {
7869
+ return new require_ha_instance_settings.RecordIntegrationInstances(records, haBrokersEntryKind, {
7870
+ description: {
7871
+ instanceMode: "multiple",
7872
+ kind: "connection",
7873
+ canTest: true,
7874
+ kinds: [{
7875
+ id: HA_INSTANCE_KIND,
7876
+ label: "Home Assistant"
7877
+ }],
7878
+ allowRestoreId: true
7879
+ },
7880
+ formSchema: () => haBrokerSettingsSchema,
7881
+ initialBody: (name) => ({
7882
+ name,
7883
+ authKind: "long-lived"
7884
+ }),
7885
+ mintId: () => deps.mintId(),
7886
+ kindOf: () => HA_INSTANCE_KIND,
7887
+ health: (_body, id) => {
7888
+ const info = deps.infoOf(id);
7889
+ return {
7890
+ status: statusOf(info),
7891
+ ...info?.lastCheckedAt != null ? { lastCheckedAt: info.lastCheckedAt } : {}
7892
+ };
7893
+ },
7894
+ configured: isHaBodyConfigured,
7895
+ onChanged: deps.onChanged,
7896
+ test: async ({ id, values }) => {
7897
+ if (["accessToken", "supervisorToken"].some((key) => {
7898
+ const v = values[key];
7899
+ return typeof v === "string" && v.length > 0 && v !== "__camstack_redacted__";
7900
+ })) {
7901
+ const r = await deps.probe(values);
7902
+ return r.ok ? {
7903
+ success: true,
7904
+ status: "validated",
7905
+ ...r.latencyMs !== void 0 ? { latencyMs: r.latencyMs } : {}
7906
+ } : {
7907
+ success: false,
7908
+ status: "rejected",
7909
+ error: r.error ?? "Home Assistant rejected the connection"
7910
+ };
7911
+ }
7912
+ const info = id === null ? null : deps.infoOf(id);
7913
+ if (info === null) return {
7914
+ success: false,
7915
+ status: "inconclusive",
7916
+ error: "Not connected: save the connection first"
7917
+ };
7918
+ return info.status === "connected" ? {
7919
+ success: true,
7920
+ status: "validated"
7921
+ } : {
7922
+ success: false,
7923
+ status: "rejected",
7924
+ error: info.error ?? `status: ${info.status}`
7925
+ };
7926
+ }
7927
+ });
7928
+ }
7929
+ //#endregion
7780
7930
  //#region src/ha-board-key-source.ts
7781
7931
  /**
7782
7932
  * `board-key-source` for Home Assistant: reads an ESPHome board's API
@@ -7799,19 +7949,19 @@ var HaBrokerStore = class HaBrokerStore {
7799
7949
  */
7800
7950
  var INGRESS_PREFIX = "/api/hassio_ingress/";
7801
7951
  var ESPHOME_SERVICE = "esphome";
7802
- var DiscoverySchema = require_ha_broker_source.object({ discovery: require_ha_broker_source.array(require_ha_broker_source.object({
7803
- addon: require_ha_broker_source.string(),
7804
- service: require_ha_broker_source.string()
7952
+ var DiscoverySchema = require_ha_instance_settings.object({ discovery: require_ha_instance_settings.array(require_ha_instance_settings.object({
7953
+ addon: require_ha_instance_settings.string(),
7954
+ service: require_ha_instance_settings.string()
7805
7955
  })) });
7806
- var AddonInfoSchema = require_ha_broker_source.object({ ingress_url: require_ha_broker_source.string().nullable().optional() });
7807
- var SessionSchema = require_ha_broker_source.object({ session: require_ha_broker_source.string().min(1) });
7808
- var DevicesSchema = require_ha_broker_source.object({ configured: require_ha_broker_source.array(require_ha_broker_source.object({
7809
- name: require_ha_broker_source.string(),
7810
- configuration: require_ha_broker_source.string(),
7811
- address: require_ha_broker_source.string().nullable().optional()
7956
+ var AddonInfoSchema = require_ha_instance_settings.object({ ingress_url: require_ha_instance_settings.string().nullable().optional() });
7957
+ var SessionSchema = require_ha_instance_settings.object({ session: require_ha_instance_settings.string().min(1) });
7958
+ var DevicesSchema = require_ha_instance_settings.object({ configured: require_ha_instance_settings.array(require_ha_instance_settings.object({
7959
+ name: require_ha_instance_settings.string(),
7960
+ configuration: require_ha_instance_settings.string(),
7961
+ address: require_ha_instance_settings.string().nullable().optional()
7812
7962
  })) });
7813
7963
  /** The ONLY part of `json-config` that is read; every other field is dropped by the parse. */
7814
- var KeyConfigSchema = require_ha_broker_source.object({ api: require_ha_broker_source.object({ encryption: require_ha_broker_source.object({ key: require_ha_broker_source.string().min(1) }).optional() }).optional() });
7964
+ var KeyConfigSchema = require_ha_instance_settings.object({ api: require_ha_instance_settings.object({ encryption: require_ha_instance_settings.object({ key: require_ha_instance_settings.string().min(1) }).optional() }).optional() });
7815
7965
  var ADMIN_CODES = new Set([
7816
7966
  "unauthorized",
7817
7967
  "forbidden",
@@ -7877,7 +8027,7 @@ var HaBoardKeySource = class {
7877
8027
  }
7878
8028
  }
7879
8029
  fail(sourceId, op, err) {
7880
- const failure = err instanceof SourceFailure ? err : new SourceFailure("unreachable", require_ha_broker_source.errMsg(err));
8030
+ const failure = err instanceof SourceFailure ? err : new SourceFailure("unreachable", require_ha_instance_settings.errMsg(err));
7881
8031
  this.deps.logger.warn(`board-key-source ${op} refused`, { meta: {
7882
8032
  sourceId,
7883
8033
  reason: failure.reason
@@ -7901,7 +8051,7 @@ var HaBoardKeySource = class {
7901
8051
  } catch (err) {
7902
8052
  const code = errorCode(err);
7903
8053
  if (code !== null && ADMIN_CODES.has(code)) throw new SourceFailure("not-admin", "the Home Assistant token is not an administrator");
7904
- throw new SourceFailure("unreachable", require_ha_broker_source.errMsg(err));
8054
+ throw new SourceFailure("unreachable", require_ha_instance_settings.errMsg(err));
7905
8055
  }
7906
8056
  }
7907
8057
  async openIngress(sourceId) {
@@ -7929,7 +8079,7 @@ var HaBoardKeySource = class {
7929
8079
  Accept: "application/json"
7930
8080
  } });
7931
8081
  } catch (err) {
7932
- throw new SourceFailure("unreachable", require_ha_broker_source.errMsg(err));
8082
+ throw new SourceFailure("unreachable", require_ha_instance_settings.errMsg(err));
7933
8083
  }
7934
8084
  if (response.status === 404 && configuration !== void 0) throw new SourceFailure("unknown-board", configuration);
7935
8085
  if (response.status === 401 || response.status === 403) throw new SourceFailure("not-admin", `the builder answered ${response.status}`);
@@ -7950,6 +8100,178 @@ function createHaBoardKeyProvider(source) {
7950
8100
  };
7951
8101
  }
7952
8102
  //#endregion
8103
+ //#region src/migrations/flatten-broker-records.ts
8104
+ /**
8105
+ * The Home Assistant broker records keep their connection flat (planning#408 P3): the nested
8106
+ * `auth` object (`{ kind, baseUrl, accessToken }` or `{ kind, supervisorToken }`) becomes the top
8107
+ * level `authKind`, `baseUrl`, `accessToken` and `supervisorToken`, under the SAME record id, so
8108
+ * the devices that carry `ha_NNN` keep their broker. The work is `flattenNestedRecords`: every
8109
+ * secret is read before anything is written, read back from its new keychain ref before the
8110
+ * nested object goes, and the old refs are deleted last.
8111
+ */
8112
+ var FLATTEN_BROKER_RECORDS_ID = "provider-homeassistant/2026-11-04-flatten-broker-records";
8113
+ function text(value) {
8114
+ return typeof value === "string" ? value : void 0;
8115
+ }
8116
+ async function flattenBrokerRecords(ports) {
8117
+ return require_ha_instance_settings.flattenNestedRecords(ports, {
8118
+ legacyKey: "auth",
8119
+ flatSecretKeys: ["accessToken", "supervisorToken"],
8120
+ toFlat: (legacy) => {
8121
+ const kind = legacy["kind"] === "supervisor" ? "supervisor" : "long-lived";
8122
+ const baseUrl = text(legacy["baseUrl"]);
8123
+ const accessToken = text(legacy["accessToken"]);
8124
+ const supervisorToken = text(legacy["supervisorToken"]);
8125
+ return {
8126
+ authKind: kind,
8127
+ ...baseUrl !== void 0 ? { baseUrl } : {},
8128
+ ...accessToken !== void 0 ? { accessToken } : {},
8129
+ ...supervisorToken !== void 0 ? { supervisorToken } : {}
8130
+ };
8131
+ }
8132
+ });
8133
+ }
8134
+ //#endregion
8135
+ //#region src/migrations/calendar-ids-to-integration.ts
8136
+ /**
8137
+ * The HA calendars an instance imports are a fact of THAT instance (D985): each Home Assistant
8138
+ * integration carries its own `calendarIds` in its settings, and the addon-level `calendarIds`
8139
+ * setting (one set of `calendar.*` entity ids for every broker) goes away.
8140
+ *
8141
+ * Two migrations, in this order:
8142
+ *
8143
+ * 1. `calendar-ids-to-integration` (procedure) copies the shared set to EVERY integration that
8144
+ * has no `calendarIds` yet. An integration that already has one is never overwritten; one
8145
+ * deleted meanwhile is skipped, never recreated; a stored value that is not a list of strings
8146
+ * is an ambiguity and throws (nothing is guessed).
8147
+ * 2. `drop-shared-calendar-ids` (plan) deletes the shared setting after a read-back: every
8148
+ * integration must show its own set. When one holds a set that differs from the shared one,
8149
+ * the shared value is the loser and stays PARKED in place, never deleted.
8150
+ *
8151
+ * Both are idempotent.
8152
+ */
8153
+ var HA_PROVIDER_ID = "provider-homeassistant";
8154
+ /** The canonical settings table: one row per key, id `<addonId>.<key>`. */
8155
+ var ADDON_SETTINGS_TABLE = "addon-settings";
8156
+ var SHARED_CALENDAR_IDS_KEY = "calendarIds";
8157
+ async function readSharedSet(ports) {
8158
+ const answer = await ports.readStored(SHARED_CALENDAR_IDS_KEY);
8159
+ if (answer.kind === "unreadable") throw new Error(`provider-homeassistant: the shared calendarIds cannot be read (${answer.reason})`);
8160
+ if (answer.kind === "absent") return null;
8161
+ const value = answer.value;
8162
+ if (!Array.isArray(value) || !value.every((item) => typeof item === "string")) throw new Error("provider-homeassistant: the shared calendarIds is not a list of entity ids — nothing copied");
8163
+ return value;
8164
+ }
8165
+ async function copyCalendarIdsToIntegrations(ports) {
8166
+ const shared = await readSharedSet(ports);
8167
+ if (shared === null) return {
8168
+ outcome: "already-done",
8169
+ summary: { reason: "no-shared-set" }
8170
+ };
8171
+ let copied = 0;
8172
+ let kept = 0;
8173
+ let gone = 0;
8174
+ for (const instance of await ports.listInstances()) {
8175
+ if ("calendarIds" in instance.settings) {
8176
+ kept += 1;
8177
+ continue;
8178
+ }
8179
+ if (await ports.patchInstanceSettings(instance.integrationId, { calendarIds: [...shared] })) copied += 1;
8180
+ else gone += 1;
8181
+ }
8182
+ return {
8183
+ outcome: copied === 0 ? "already-done" : "done",
8184
+ summary: {
8185
+ copied,
8186
+ kept,
8187
+ gone
8188
+ }
8189
+ };
8190
+ }
8191
+ var asIds = (value) => Array.isArray(value) && value.every((item) => typeof item === "string") ? value : null;
8192
+ var sameSet = (a, b) => {
8193
+ const left = new Set(a);
8194
+ const right = new Set(b);
8195
+ return left.size === right.size && [...left].every((id) => right.has(id));
8196
+ };
8197
+ async function planDropSharedCalendarIds(ports) {
8198
+ const shared = await readSharedSet(ports);
8199
+ if (shared === null) return { edits: [] };
8200
+ const instances = await ports.listInstances();
8201
+ if (instances.length === 0) return { edits: [] };
8202
+ const own = instances.map((instance) => ({
8203
+ integrationId: instance.integrationId,
8204
+ ids: asIds(instance.settings[SHARED_CALENDAR_IDS_KEY])
8205
+ }));
8206
+ const missing = own.filter((entry) => entry.ids === null);
8207
+ if (missing.length > 0) throw new Error(`provider-homeassistant: the shared calendarIds is not dropped, ${missing.map((m) => m.integrationId).join(", ")} has no set of its own`);
8208
+ if (!own.every((entry) => sameSet(entry.ids ?? [], shared))) return { edits: [] };
8209
+ const rowId = `${HA_PROVIDER_ID}.${SHARED_CALENDAR_IDS_KEY}`;
8210
+ return { edits: [{
8211
+ op: "deleteKeys",
8212
+ scope: ADDON_SETTINGS_TABLE,
8213
+ keys: [rowId],
8214
+ precondition: require_ha_instance_settings.preconditionOf({ [rowId]: {
8215
+ addonId: HA_PROVIDER_ID,
8216
+ key: SHARED_CALENDAR_IDS_KEY,
8217
+ value: shared
8218
+ } })
8219
+ }] };
8220
+ }
8221
+ //#endregion
8222
+ //#region src/migrations/index.ts
8223
+ /** The `provider-homeassistant` catalogue (D987): offered to the engine when the addon initialises. */
8224
+ var ADDON_MIGRATIONS = [
8225
+ {
8226
+ meta: {
8227
+ id: "provider-homeassistant/2026-11-03-calendar-ids-to-integration",
8228
+ owner: "provider-homeassistant",
8229
+ level: "addon-state",
8230
+ seq: 1,
8231
+ dependsOn: [],
8232
+ store: "settings",
8233
+ scope: "cluster",
8234
+ onFailure: "tolerate",
8235
+ bodyKind: "procedure",
8236
+ description: "Copy the shared calendar set to the settings of every Home Assistant integration that has none",
8237
+ fixtureMark: "the broker link stored beside the calendars of an integration"
8238
+ },
8239
+ procedure: copyCalendarIdsToIntegrations
8240
+ },
8241
+ {
8242
+ meta: {
8243
+ id: "provider-homeassistant/2026-11-03-drop-shared-calendar-ids",
8244
+ owner: "provider-homeassistant",
8245
+ level: "addon-state",
8246
+ seq: 2,
8247
+ dependsOn: ["provider-homeassistant/2026-11-03-calendar-ids-to-integration"],
8248
+ store: "settings",
8249
+ scope: "cluster",
8250
+ onFailure: "tolerate",
8251
+ bodyKind: "plan",
8252
+ description: "Delete the shared calendar set once every integration shows its own",
8253
+ fixtureMark: "the shared set parked when an integration holds a different one"
8254
+ },
8255
+ plan: planDropSharedCalendarIds
8256
+ },
8257
+ {
8258
+ meta: {
8259
+ id: FLATTEN_BROKER_RECORDS_ID,
8260
+ owner: "provider-homeassistant",
8261
+ level: "addon-state",
8262
+ seq: 3,
8263
+ dependsOn: [],
8264
+ store: "settings",
8265
+ scope: "cluster",
8266
+ onFailure: "block-owner",
8267
+ bodyKind: "procedure",
8268
+ description: "Flatten the nested auth of every Home Assistant broker record under its own id, moving each token to a top-level keychain secret",
8269
+ fixtureMark: "a non-secret field stored beside the auth of a broker record"
8270
+ },
8271
+ procedure: flattenBrokerRecords
8272
+ }
8273
+ ];
8274
+ //#endregion
7953
8275
  //#region src/ha-calendar-source.ts
7954
8276
  function isCalendarEntity(entityId) {
7955
8277
  return entityId.startsWith("calendar.");
@@ -8060,9 +8382,9 @@ function isSelected(entityId, selected) {
8060
8382
  function createHaCalendarSource(deps) {
8061
8383
  return {
8062
8384
  listCalendars: async () => {
8063
- const selected = deps.selectedCalendarIds();
8064
8385
  const out = [];
8065
- for (const { manager } of deps.brokers.listManagers()) {
8386
+ for (const { brokerId, manager } of deps.brokers.listManagers()) {
8387
+ const selected = deps.selectedCalendarIds(brokerId);
8066
8388
  const states = manager.snapshotAllStates();
8067
8389
  for (const [entityId, raw] of Object.entries(states)) {
8068
8390
  if (!isCalendarEntity(entityId)) continue;
@@ -8082,10 +8404,10 @@ function createHaCalendarSource(deps) {
8082
8404
  listEvents: async (input) => {
8083
8405
  const startIso = new Date(input.startMs).toISOString();
8084
8406
  const endIso = new Date(input.endMs).toISOString();
8085
- const selected = deps.selectedCalendarIds();
8086
8407
  const wanted = input.calendarIds !== void 0 && input.calendarIds.length > 0 ? new Set(input.calendarIds) : null;
8087
8408
  const out = [];
8088
8409
  for (const { brokerId, manager } of deps.brokers.listManagers()) {
8410
+ const selected = deps.selectedCalendarIds(brokerId);
8089
8411
  const states = manager.snapshotAllStates();
8090
8412
  const entityIds = Object.keys(states).filter((id) => {
8091
8413
  if (!isCalendarEntity(id)) return false;
@@ -8109,10 +8431,11 @@ function createHaCalendarSource(deps) {
8109
8431
  };
8110
8432
  }
8111
8433
  /** Discover every HA calendar entity (ignores the import filter) — for settings catalog. */
8112
- function listHaCalendarCatalog(brokers) {
8434
+ function listHaCalendarCatalog(brokers, onlyBrokerId) {
8113
8435
  const out = [];
8114
8436
  const seen = /* @__PURE__ */ new Set();
8115
- for (const { manager } of brokers.listManagers()) {
8437
+ for (const { brokerId, manager } of brokers.listManagers()) {
8438
+ if (onlyBrokerId !== void 0 && brokerId !== onlyBrokerId) continue;
8116
8439
  const states = manager.snapshotAllStates();
8117
8440
  for (const [entityId, raw] of Object.entries(states)) {
8118
8441
  if (!isCalendarEntity(entityId) || seen.has(entityId)) continue;
@@ -8283,7 +8606,7 @@ function entityToStandaloneCandidate(entity, alreadyAdopted) {
8283
8606
  return {
8284
8607
  childNativeId: entity.entityId,
8285
8608
  name: entity.name,
8286
- type: entity.mappedTo?.deviceType ?? require_ha_broker_source.DeviceType.Generic,
8609
+ type: entity.mappedTo?.deviceType ?? require_ha_instance_settings.DeviceType.Generic,
8287
8610
  status: entityStatus(entity.state),
8288
8611
  metadata: entity.area !== null ? { externalLocation: entity.area } : {},
8289
8612
  alreadyAdopted,
@@ -8418,7 +8741,7 @@ function readPersistedStandaloneSpec(device) {
8418
8741
  * adoption-proof source field), so it is projected directly here, mirroring the
8419
8742
  * Container's `EnumSensorDateTimeFormatSchema.safeParse` guard. */
8420
8743
  function readDateTimeFormat(config) {
8421
- const parsed = require_ha_broker_source.EnumSensorDateTimeFormatSchema.safeParse(config["dateTimeFormat"]);
8744
+ const parsed = require_ha_instance_settings.EnumSensorDateTimeFormatSchema.safeParse(config["dateTimeFormat"]);
8422
8745
  return parsed.success ? parsed.data : void 0;
8423
8746
  }
8424
8747
  /** Flatten a live device's config into a plain blob for `readHaSource`. */
@@ -8561,10 +8884,7 @@ function planStandaloneReconcile(devices, freshById, brokerId) {
8561
8884
  var ADOPTION_FILTER_DEVICES = "devices";
8562
8885
  var ADOPTION_FILTER_ENTITIES = "entities";
8563
8886
  var HA_KIND = "home-assistant";
8564
- var DEFAULT_CONFIG = {
8565
- brokers: [],
8566
- calendarIds: []
8567
- };
8887
+ var DEFAULT_CONFIG = { calendarIds: [] };
8568
8888
  /**
8569
8889
  * Home Assistant provider addon.
8570
8890
  *
@@ -8585,12 +8905,12 @@ var DEFAULT_CONFIG = {
8585
8905
  * …) and route HA state pushes into runtime-state slices + cap
8586
8906
  * mutations into HA call_service.
8587
8907
  */
8588
- var HaProviderAddon = class HaProviderAddon extends require_ha_broker_source.BaseDeviceProvider {
8908
+ var HaProviderAddon = class HaProviderAddon extends require_ha_instance_settings.BaseDeviceProvider {
8589
8909
  addonId = "provider-homeassistant";
8590
8910
  providerName = "Home Assistant";
8591
8911
  deviceClasses = {
8592
- [require_ha_broker_source.DeviceType.Container]: HaContainerDevice,
8593
- [require_ha_broker_source.DeviceType.EventEmitter]: HaEventBusDevice
8912
+ [require_ha_instance_settings.DeviceType.Container]: HaContainerDevice,
8913
+ [require_ha_instance_settings.DeviceType.EventEmitter]: HaEventBusDevice
8594
8914
  };
8595
8915
  async onGetCreationSchema(_type) {
8596
8916
  return null;
@@ -8611,6 +8931,7 @@ var HaProviderAddon = class HaProviderAddon extends require_ha_broker_source.Bas
8611
8931
  }
8612
8932
  registry = null;
8613
8933
  brokerStore = null;
8934
+ instances = null;
8614
8935
  /** Runtime broker rows (records when B2 is live, else settings). */
8615
8936
  activeBrokers = [];
8616
8937
  /** Periodic re-sync sweep handle (cleared on shutdown). */
@@ -8625,11 +8946,26 @@ var HaProviderAddon = class HaProviderAddon extends require_ha_broker_source.Bas
8625
8946
  constructor() {
8626
8947
  super({ ...DEFAULT_CONFIG });
8627
8948
  }
8949
+ flattenPorts(records) {
8950
+ if (this.ctx.secrets === void 0) throw new Error("provider-homeassistant: ctx.secrets is required");
8951
+ return {
8952
+ readStored: (key) => this.readStoredGlobalKey(key),
8953
+ ...require_ha_instance_settings.haInstanceSettingsPortsOver(this.ctx.api.integrations),
8954
+ ...require_ha_instance_settings.flattenPortsOver(records.kind(haBrokersEntryKind))
8955
+ };
8956
+ }
8628
8957
  async onInitialize() {
8629
8958
  const records = this.ctx.records;
8630
8959
  if (records === void 0) throw new Error("provider-homeassistant: ctx.records is required (hub-only addon)");
8631
8960
  await records.declare(haAllRecordKinds);
8632
8961
  this.brokerStore = HaBrokerStore.of(records);
8962
+ this.instances = buildHaInstances(records, {
8963
+ mintId: () => this.requireRegistry().allocateId(),
8964
+ infoOf: (id) => this.registry?.get(id) ?? null,
8965
+ onChanged: (id) => this.syncBrokerRuntime(id),
8966
+ probe: (settings) => this.requireRegistry().testSettings(settings)
8967
+ });
8968
+ await this.runMigrations(require_ha_instance_settings.defineAddonMigrations(ADDON_MIGRATIONS.filter((m) => m.meta.id === FLATTEN_BROKER_RECORDS_ID), this.flattenPorts(records)));
8633
8969
  this.activeBrokers = await this.loadPersistedBrokers();
8634
8970
  this.registry = new HaBrokerRegistry(this.ctx.logger, this.ctx.eventBus);
8635
8971
  this.registry.setOnBrokerConnected((brokerId) => {
@@ -8646,35 +8982,40 @@ var HaProviderAddon = class HaProviderAddon extends require_ha_broker_source.Bas
8646
8982
  this.reconcileAllConnectedBrokers();
8647
8983
  }, HaProviderAddon.RESYNC_INTERVAL_MS);
8648
8984
  this.ctx.logger.info("ha provider initialised", { meta: { brokerCount: this.activeBrokers.length } });
8985
+ await this.runMigrations(require_ha_instance_settings.defineAddonMigrations(ADDON_MIGRATIONS.filter((m) => m.meta.id !== FLATTEN_BROKER_RECORDS_ID), this.flattenPorts(records)));
8649
8986
  await this.reconcileIntegrationsToBrokers();
8650
8987
  this.subscribeIntegrationLifecycle();
8651
8988
  return [
8652
8989
  {
8653
- capability: require_ha_broker_source.brokerCapability,
8990
+ capability: require_ha_instance_settings.brokerCapability,
8654
8991
  provider: this.buildBrokerProvider()
8655
8992
  },
8656
8993
  {
8657
- capability: require_ha_broker_source.deviceAdoptionCapability,
8994
+ capability: require_ha_instance_settings.integrationInstancesCapability,
8995
+ provider: this.requireInstances().toProvider()
8996
+ },
8997
+ {
8998
+ capability: require_ha_instance_settings.deviceAdoptionCapability,
8658
8999
  provider: this.buildAdoptionProvider()
8659
9000
  },
8660
9001
  {
8661
- capability: require_ha_broker_source.notificationOutputCapability,
9002
+ capability: require_ha_instance_settings.notificationOutputCapability,
8662
9003
  provider: await this.buildNotificationOutputProvider()
8663
9004
  },
8664
9005
  {
8665
- capability: require_ha_broker_source.addonRoutesCapability,
9006
+ capability: require_ha_instance_settings.addonRoutesCapability,
8666
9007
  provider: createHaIconRouteProvider()
8667
9008
  },
8668
9009
  {
8669
- capability: require_ha_broker_source.boardKeySourceCapability,
9010
+ capability: require_ha_instance_settings.boardKeySourceCapability,
8670
9011
  provider: this.buildBoardKeyProvider()
8671
9012
  },
8672
9013
  {
8673
- capability: require_ha_broker_source.calendarSourceCapability,
9014
+ capability: require_ha_instance_settings.calendarSourceCapability,
8674
9015
  provider: createHaCalendarSource({
8675
9016
  brokers: this.requireRegistry(),
8676
9017
  logger: this.ctx.logger.child("calendar-source"),
8677
- selectedCalendarIds: () => new Set(this.config.calendarIds ?? [])
9018
+ selectedCalendarIds: (brokerId) => this.calendarIdsOf(brokerId)
8678
9019
  })
8679
9020
  }
8680
9021
  ];
@@ -8722,7 +9063,7 @@ var HaProviderAddon = class HaProviderAddon extends require_ha_broker_source.Bas
8722
9063
  return manager.sendMessage({ type: "config/device_registry/list" });
8723
9064
  },
8724
9065
  listBrokerIds: () => this.activeBrokers.map((b) => b.id),
8725
- readPublicEndpoint: require_ha_broker_source.publicEndpointReaderFrom(this.ctx.api.localNetwork),
9066
+ readPublicEndpoint: require_ha_instance_settings.publicEndpointReaderFrom(this.ctx.api.localNetwork),
8726
9067
  logger: this.ctx.logger.child("notification-output")
8727
9068
  });
8728
9069
  }
@@ -8772,6 +9113,20 @@ var HaProviderAddon = class HaProviderAddon extends require_ha_broker_source.Bas
8772
9113
  *
8773
9114
  * Idempotent — runs on boot + on every integration.* event.
8774
9115
  */
9116
+ /**
9117
+ * Calendars to import, per broker (D985): the integration's own selection, filled by the
9118
+ * reconcile that already reads each integration's settings. A broker whose integration has no
9119
+ * selection yet (the move has not run) uses the legacy shared set, so a boot mid-move never
9120
+ * changes what is imported.
9121
+ */
9122
+ calendarIdsByBroker = /* @__PURE__ */ new Map();
9123
+ noteInstanceCalendars(brokerId, raw) {
9124
+ if (Array.isArray(raw) && raw.every((id) => typeof id === "string")) this.calendarIdsByBroker.set(brokerId, new Set(raw));
9125
+ else this.calendarIdsByBroker.delete(brokerId);
9126
+ }
9127
+ calendarIdsOf(brokerId) {
9128
+ return this.calendarIdsByBroker.get(brokerId) ?? new Set(this.config.calendarIds ?? []);
9129
+ }
8775
9130
  async reconcileIntegrationsToBrokers() {
8776
9131
  const api = this.ctx.api;
8777
9132
  if (!api.integrations?.list?.query || !api.integrations.getSettings?.query) return;
@@ -8783,6 +9138,7 @@ var HaProviderAddon = class HaProviderAddon extends require_ha_broker_source.Bas
8783
9138
  const settings = await api.integrations.getSettings.query({ id: integration.id });
8784
9139
  const brokerId = typeof settings["brokerId"] === "string" ? settings["brokerId"] : null;
8785
9140
  if (!brokerId) continue;
9141
+ this.noteInstanceCalendars(brokerId, settings["calendarIds"]);
8786
9142
  if (!this.activeBrokers.find((b) => b.id === brokerId)) {
8787
9143
  this.ctx.logger.warn("integration→broker: linked broker not found", { meta: {
8788
9144
  integrationId: integration.id,
@@ -8809,7 +9165,7 @@ var HaProviderAddon = class HaProviderAddon extends require_ha_broker_source.Bas
8809
9165
  integrationCount: haIntegrations.length
8810
9166
  } });
8811
9167
  } catch (err) {
8812
- this.ctx.logger.warn("integration→broker reconcile failed", { meta: { error: require_ha_broker_source.errMsg(err) } });
9168
+ this.ctx.logger.warn("integration→broker reconcile failed", { meta: { error: require_ha_instance_settings.errMsg(err) } });
8813
9169
  }
8814
9170
  }
8815
9171
  subscribeIntegrationLifecycle() {
@@ -8822,23 +9178,7 @@ var HaProviderAddon = class HaProviderAddon extends require_ha_broker_source.Bas
8822
9178
  eb.subscribe({ category: "integration.disabled" }, handler);
8823
9179
  eb.subscribe({ category: "integration.deleted" }, handler);
8824
9180
  }
8825
- globalSettingsSchema(cap) {
8826
- if (cap === "calendar-source") return this.schema({ sections: [{
8827
- id: "ha-calendars-import",
8828
- title: "Calendars to import",
8829
- titleKey: "provider-homeassistant:globalSettings.s_ha-calendars-import.title",
8830
- columns: 1,
8831
- fields: [{
8832
- type: "multiselect",
8833
- key: "calendarIds",
8834
- label: "Calendars",
8835
- labelKey: "provider-homeassistant:globalSettings.s_ha-calendars-import.calendarIds.label",
8836
- options: [],
8837
- optionsFrom: "_calendarCatalog",
8838
- description: "Discovered from connected HA brokers. Select at least one to import; leave empty to import none.",
8839
- descriptionKey: "provider-homeassistant:globalSettings.s_ha-calendars-import.calendarIds.description"
8840
- }]
8841
- }] });
9181
+ globalSettingsSchema(_cap) {
8842
9182
  return this.schema({ sections: [{
8843
9183
  id: "ha-broker",
8844
9184
  title: "Home Assistant broker",
@@ -8853,14 +9193,39 @@ var HaProviderAddon = class HaProviderAddon extends require_ha_broker_source.Bas
8853
9193
  }]
8854
9194
  }] });
8855
9195
  }
8856
- async getGlobalSettings(overlay, cap, nodeId) {
8857
- if (cap !== "calendar-source") return super.getGlobalSettings(overlay, cap, nodeId);
8858
- const catalog = this.registry ? listHaCalendarCatalog(this.registry) : [];
8859
- return super.getGlobalSettings({
8860
- ...overlay,
8861
- calendarIds: this.config.calendarIds ?? [],
8862
- ...catalog.length > 0 ? { _calendarCatalog: catalog } : {}
8863
- }, cap, nodeId);
9196
+ /**
9197
+ * The calendars of ONE Home Assistant instance (D985): picked on its integration, offered from
9198
+ * that broker's own `calendar.*` entities.
9199
+ */
9200
+ async integrationSettingsSchema(instance) {
9201
+ if (instance.integrationId === null || !this.registry) return null;
9202
+ let brokerId;
9203
+ try {
9204
+ brokerId = (await this.ctx.api.integrations.getSettings.query({ id: instance.integrationId }))["brokerId"];
9205
+ } catch (err) {
9206
+ this.ctx.logger.warn("HA integration form: instance lookup failed — broker form shown", { meta: {
9207
+ integrationId: instance.integrationId,
9208
+ error: require_ha_instance_settings.errMsg(err)
9209
+ } });
9210
+ return null;
9211
+ }
9212
+ if (typeof brokerId !== "string") return null;
9213
+ const options = listHaCalendarCatalog(this.registry, brokerId);
9214
+ return this.schema({ sections: [{
9215
+ id: "ha-calendars-import",
9216
+ title: "Calendars to import",
9217
+ titleKey: "provider-homeassistant:globalSettings.s_ha-calendars-import.title",
9218
+ columns: 1,
9219
+ fields: [{
9220
+ type: "multiselect",
9221
+ key: "calendarIds",
9222
+ label: "Calendars",
9223
+ labelKey: "provider-homeassistant:globalSettings.s_ha-calendars-import.calendarIds.label",
9224
+ options,
9225
+ description: "Discovered from this Home Assistant instance. Select at least one to import; leave empty to import none.",
9226
+ descriptionKey: "provider-homeassistant:globalSettings.s_ha-calendars-import.calendarIds.description"
9227
+ }]
9228
+ }] });
8864
9229
  }
8865
9230
  async onShutdown() {
8866
9231
  if (this.resyncTimer) {
@@ -8870,7 +9235,7 @@ var HaProviderAddon = class HaProviderAddon extends require_ha_broker_source.Bas
8870
9235
  try {
8871
9236
  await this.registry?.shutdown();
8872
9237
  } catch (err) {
8873
- this.ctx.logger.warn("ha provider shutdown error", { meta: { error: require_ha_broker_source.errMsg(err) } });
9238
+ this.ctx.logger.warn("ha provider shutdown error", { meta: { error: require_ha_instance_settings.errMsg(err) } });
8874
9239
  }
8875
9240
  this.registry = null;
8876
9241
  await super.onShutdown();
@@ -8902,30 +9267,25 @@ var HaProviderAddon = class HaProviderAddon extends require_ha_broker_source.Bas
8902
9267
  } catch (err) {
8903
9268
  this.ctx.logger.warn("ha onConfigChanged: removeEntry failed", { meta: {
8904
9269
  brokerId: liveId,
8905
- error: require_ha_broker_source.errMsg(err)
9270
+ error: require_ha_instance_settings.errMsg(err)
8906
9271
  } });
8907
9272
  }
8908
9273
  for (const entry of persisted) {
8909
9274
  if (entry.id && liveIds.has(entry.id)) {
8910
9275
  try {
8911
- const settings = entry.auth.kind === "supervisor" ? { supervisorToken: entry.auth.supervisorToken } : {
8912
- baseUrl: entry.auth.baseUrl,
8913
- accessToken: entry.auth.accessToken
8914
- };
8915
- await reg.updateEntry(entry.id, settings);
9276
+ const settings = entryToSettings(entry);
9277
+ if (settings !== null) await reg.updateEntry(entry.id, settings);
8916
9278
  } catch (err) {
8917
9279
  this.ctx.logger.warn("ha onConfigChanged: updateEntry failed", { meta: {
8918
9280
  brokerId: entry.id,
8919
- error: require_ha_broker_source.errMsg(err)
9281
+ error: require_ha_instance_settings.errMsg(err)
8920
9282
  } });
8921
9283
  }
8922
9284
  continue;
8923
9285
  }
8924
9286
  try {
8925
- const settings = entry.auth.kind === "supervisor" ? { supervisorToken: entry.auth.supervisorToken } : {
8926
- baseUrl: entry.auth.baseUrl,
8927
- accessToken: entry.auth.accessToken
8928
- };
9287
+ const settings = entryToSettings(entry);
9288
+ if (settings === null) continue;
8929
9289
  const created = await reg.createEntry(entry.name, settings);
8930
9290
  if (created.id !== entry.id) {
8931
9291
  const next = persisted.map((b) => b === entry ? {
@@ -8937,27 +9297,65 @@ var HaProviderAddon = class HaProviderAddon extends require_ha_broker_source.Bas
8937
9297
  } catch (err) {
8938
9298
  this.ctx.logger.warn("ha onConfigChanged: failed to start new broker", { meta: {
8939
9299
  brokerName: entry.name,
8940
- error: require_ha_broker_source.errMsg(err)
9300
+ error: require_ha_instance_settings.errMsg(err)
8941
9301
  } });
8942
9302
  }
8943
9303
  }
8944
9304
  }
8945
9305
  async loadPersistedBrokers() {
8946
- const store = this.brokerStore;
8947
- if (store !== null) {
8948
- const fromRecords = await store.listResolved();
8949
- if (fromRecords.length > 0) return fromRecords;
9306
+ return this.requireBrokerStore().listResolved();
9307
+ }
9308
+ requireInstances() {
9309
+ if (this.instances === null) throw new Error("provider-homeassistant: instances not ready");
9310
+ return this.instances;
9311
+ }
9312
+ /**
9313
+ * After an instance changed (created, edited, switched, deleted) the runtime follows the record:
9314
+ * a missing record removes the manager and its adopted devices, an off or unfilled one stops the
9315
+ * manager but keeps the devices, a filled one starts or re-authenticates it.
9316
+ */
9317
+ async syncBrokerRuntime(id) {
9318
+ const reg = this.requireRegistry();
9319
+ const entry = await this.requireBrokerStore().getById(id);
9320
+ this.activeBrokers = await this.loadPersistedBrokers();
9321
+ if (entry === null) {
9322
+ await reg.removeEntry(id);
9323
+ const deviceRegistry = this.ctx.kernel.deviceRegistry;
9324
+ const devices = this.ctx.kernel.devices;
9325
+ if (deviceRegistry && devices) await cascadeRemoveDevicesForBroker({
9326
+ reg: deviceRegistry,
9327
+ devices,
9328
+ addonId: this.ctx.id,
9329
+ brokerId: id,
9330
+ logger: this.ctx.logger
9331
+ });
9332
+ return;
9333
+ }
9334
+ const settings = entry.enabled === false ? null : entryToSettings(entry);
9335
+ if (settings === null) {
9336
+ await reg.removeEntry(id);
9337
+ return;
8950
9338
  }
8951
- return this.config.brokers;
9339
+ try {
9340
+ if (reg.get(id) !== null) await reg.updateEntry(id, settings);
9341
+ else await reg.createEntry(entry.name, settings, {
9342
+ id,
9343
+ ...entry.integrationId !== void 0 ? { integrationId: entry.integrationId } : {}
9344
+ });
9345
+ } catch (err) {
9346
+ this.ctx.logger.warn("ha instance: could not start the broker", { meta: {
9347
+ brokerId: id,
9348
+ error: require_ha_instance_settings.errMsg(err)
9349
+ } });
9350
+ }
9351
+ }
9352
+ requireBrokerStore() {
9353
+ if (this.brokerStore === null) throw new Error("provider-homeassistant: broker store not ready");
9354
+ return this.brokerStore;
8952
9355
  }
8953
9356
  async persistBrokerEntries(entries) {
8954
9357
  this.activeBrokers = [...entries];
8955
- const store = this.brokerStore;
8956
- if (store !== null) {
8957
- await store.replaceAll(entries);
8958
- return;
8959
- }
8960
- await this.updateGlobalSettings({ brokers: entries });
9358
+ await this.requireBrokerStore().replaceAll(entries);
8961
9359
  }
8962
9360
  buildBrokerProvider() {
8963
9361
  const ownerAddonId = this.ctx.id;
@@ -9031,7 +9429,7 @@ var HaProviderAddon = class HaProviderAddon extends require_ha_broker_source.Bas
9031
9429
  getSettings: async ({ id }) => {
9032
9430
  const entry = this.activeBrokers.find((b) => b.id === id);
9033
9431
  if (!entry) return null;
9034
- return authToSettings(entry.auth);
9432
+ return entryToSettings(entry);
9035
9433
  },
9036
9434
  setSettings: async ({ id, settings }) => {
9037
9435
  if (!owns(id)) return;
@@ -9042,7 +9440,7 @@ var HaProviderAddon = class HaProviderAddon extends require_ha_broker_source.Bas
9042
9440
  getBrokerConfig: async ({ id }) => {
9043
9441
  const entry = this.activeBrokers.find((b) => b.id === id);
9044
9442
  if (!entry) return null;
9045
- return authToSettings(entry.auth);
9443
+ return entryToSettings(entry);
9046
9444
  },
9047
9445
  getSettingsSchema: async ({ kind }) => {
9048
9446
  if (kind !== HA_KIND) return null;
@@ -9087,7 +9485,7 @@ var HaProviderAddon = class HaProviderAddon extends require_ha_broker_source.Bas
9087
9485
  const refreshedAt = Date.now();
9088
9486
  if (lastDiscoveryAt === null || refreshedAt > lastDiscoveryAt) lastDiscoveryAt = refreshedAt;
9089
9487
  } catch (err) {
9090
- lastError = require_ha_broker_source.errMsg(err);
9488
+ lastError = require_ha_instance_settings.errMsg(err);
9091
9489
  }
9092
9490
  const adoptedCount = (await this.ctx.kernel.devices.getAll()).filter((d) => d.parentDeviceId === null && String(d.config.get("system") ?? "") === "homeassistant").length;
9093
9491
  return {
@@ -9233,7 +9631,7 @@ var HaProviderAddon = class HaProviderAddon extends require_ha_broker_source.Bas
9233
9631
  name: deviceName
9234
9632
  };
9235
9633
  const summary = await this.createDevice({
9236
- type: require_ha_broker_source.DeviceType.Container,
9634
+ type: require_ha_instance_settings.DeviceType.Container,
9237
9635
  config: containerConfig
9238
9636
  });
9239
9637
  const accessoryDeviceIds = (await this.ctx.kernel.devices.getChildren(summary.id)).map((c) => c.id);
@@ -9263,7 +9661,7 @@ var HaProviderAddon = class HaProviderAddon extends require_ha_broker_source.Bas
9263
9661
  meta: {
9264
9662
  brokerId,
9265
9663
  haDeviceId,
9266
- error: require_ha_broker_source.errMsg(err)
9664
+ error: require_ha_instance_settings.errMsg(err)
9267
9665
  }
9268
9666
  });
9269
9667
  }
@@ -9410,7 +9808,7 @@ var HaProviderAddon = class HaProviderAddon extends require_ha_broker_source.Bas
9410
9808
  meta: {
9411
9809
  brokerId,
9412
9810
  entityId,
9413
- error: require_ha_broker_source.errMsg(err)
9811
+ error: require_ha_instance_settings.errMsg(err)
9414
9812
  }
9415
9813
  });
9416
9814
  }
@@ -9431,7 +9829,7 @@ var HaProviderAddon = class HaProviderAddon extends require_ha_broker_source.Bas
9431
9829
  */
9432
9830
  async assignImportedLocation(deviceId, externalLocation, knownLocations) {
9433
9831
  try {
9434
- const match = require_ha_broker_source.bestLocationMatch(externalLocation, knownLocations);
9832
+ const match = require_ha_instance_settings.bestLocationMatch(externalLocation, knownLocations);
9435
9833
  const name = match ?? externalLocation;
9436
9834
  let locations = knownLocations;
9437
9835
  if (match === null) {
@@ -9447,7 +9845,7 @@ var HaProviderAddon = class HaProviderAddon extends require_ha_broker_source.Bas
9447
9845
  this.ctx.logger.warn("ha-adoption: location import failed (non-fatal)", { meta: {
9448
9846
  deviceId,
9449
9847
  externalLocation,
9450
- error: require_ha_broker_source.errMsg(err)
9848
+ error: require_ha_instance_settings.errMsg(err)
9451
9849
  } });
9452
9850
  return knownLocations;
9453
9851
  }
@@ -9648,7 +10046,7 @@ var HaProviderAddon = class HaProviderAddon extends require_ha_broker_source.Bas
9648
10046
  } catch (err) {
9649
10047
  this.ctx.logger.warn("ha bus-event aggregator ensure failed", { meta: {
9650
10048
  brokerId,
9651
- error: require_ha_broker_source.errMsg(err)
10049
+ error: require_ha_instance_settings.errMsg(err)
9652
10050
  } });
9653
10051
  }
9654
10052
  await reconcileBroker(brokerId, {
@@ -9658,7 +10056,7 @@ var HaProviderAddon = class HaProviderAddon extends require_ha_broker_source.Bas
9658
10056
  onFetchError: (id, error) => {
9659
10057
  this.ctx.logger.warn("ha re-sync: inventory fetch failed", { meta: {
9660
10058
  brokerId: id,
9661
- error: require_ha_broker_source.errMsg(error)
10059
+ error: require_ha_instance_settings.errMsg(error)
9662
10060
  } });
9663
10061
  }
9664
10062
  });
@@ -9696,7 +10094,7 @@ var HaProviderAddon = class HaProviderAddon extends require_ha_broker_source.Bas
9696
10094
  meta: {
9697
10095
  brokerId,
9698
10096
  haDeviceId,
9699
- error: require_ha_broker_source.errMsg(err)
10097
+ error: require_ha_instance_settings.errMsg(err)
9700
10098
  }
9701
10099
  });
9702
10100
  }
@@ -9741,7 +10139,7 @@ var HaProviderAddon = class HaProviderAddon extends require_ha_broker_source.Bas
9741
10139
  tags: { deviceId: action.deviceId },
9742
10140
  meta: {
9743
10141
  brokerId,
9744
- error: require_ha_broker_source.errMsg(err)
10142
+ error: require_ha_instance_settings.errMsg(err)
9745
10143
  }
9746
10144
  });
9747
10145
  }
@@ -9822,7 +10220,7 @@ var HaProviderAddon = class HaProviderAddon extends require_ha_broker_source.Bas
9822
10220
  brokerId,
9823
10221
  kind: "event-bus"
9824
10222
  }, null, {
9825
- type: require_ha_broker_source.DeviceType.EventEmitter,
10223
+ type: require_ha_instance_settings.DeviceType.EventEmitter,
9826
10224
  name: "Home Assistant Events"
9827
10225
  });
9828
10226
  this.eventBusDeviceIds.set(brokerId, device.id);
@@ -9852,7 +10250,7 @@ var HaProviderAddon = class HaProviderAddon extends require_ha_broker_source.Bas
9852
10250
  this.ctx.logger.debug("ha bus-event dropped — aggregator not ready", { meta: {
9853
10251
  brokerId,
9854
10252
  eventType: ev.eventType,
9855
- error: require_ha_broker_source.errMsg(err)
10253
+ error: require_ha_instance_settings.errMsg(err)
9856
10254
  } });
9857
10255
  return;
9858
10256
  }