@camstack/addon-provider-homeassistant 1.2.172 → 1.2.173

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_dist = require("./dist-Ba9raKow.js");
2
+ const require_dist = require("./dist-DTt9hwTQ.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
@@ -1592,6 +1592,7 @@ var COLD_START$15 = {
1592
1592
  * - `target_temp_high` / `target_temp_low` → `targetHigh` / `targetLow`
1593
1593
  * - `target_humidity` → `targetHumidity`
1594
1594
  * - `current_temperature` / `current_humidity` → read-only
1595
+ * - `min_temp` / `max_temp` / `target_temp_step` → setpoint bounds
1595
1596
  *
1596
1597
  * Mutations route to:
1597
1598
  * - `climate.set_hvac_mode({ hvac_mode })`
@@ -1691,6 +1692,9 @@ function climateSliceFromState(state) {
1691
1692
  currentTemp: readNumberAttr$5(attrs, "current_temperature"),
1692
1693
  currentHumidity: readNumberAttr$5(attrs, "current_humidity"),
1693
1694
  ...readSwing(attrs),
1695
+ minTemp: readNumberAttr$5(attrs, "min_temp"),
1696
+ maxTemp: readNumberAttr$5(attrs, "max_temp"),
1697
+ tempStep: readNumberAttr$5(attrs, "target_temp_step"),
1694
1698
  lastFetchedAt
1695
1699
  };
1696
1700
  }
@@ -5805,7 +5809,7 @@ function mapHaEntityToCamStack(input) {
5805
5809
  switch (domain) {
5806
5810
  case "switch": return {
5807
5811
  deviceType: require_dist.DeviceType.Switch,
5808
- role: null,
5812
+ role: deviceClass === "outlet" ? require_dist.DeviceRole.Outlet : null,
5809
5813
  capabilities: ["switch"]
5810
5814
  };
5811
5815
  case "input_boolean": return {
package/dist/addon.mjs CHANGED
@@ -1,4 +1,4 @@
1
- import { A as connectivityCapability, At as record, B as floodCapability, C as buildAddonRouteProvider, Ct as _enum, D as carbonMonoxideCapability, Dt as literal, E as calendarSourceCapability, Et as discriminatedUnion, F as deviceAdoptionCapability, Ft as EventCategory, G as lawnMowerControlCapability, H as humidifierCapability, J as motionCapability, K as lockControlCapability, L as enumSensorCapability, M as controlCapability, Mt as union, N as coverCapability, Nt as unknown, O as climateControlCapability, Ot as number, P as deviceAdminLinkCapability, Pt as url, Q as numericSensorCapability, R as eventEmitterCapability, S as brokerCapability, T as buttonCapability, Tt as boolean, U as humiditySensorCapability, V as gasCapability, W as imageCapability, X as notificationOutputCapability, Y as normalizeUnit, Z as notifierCapability, _ as automationControlCapability, _t as DeviceRole, at as scriptRunnerCapability, b as binaryCapability, ct as tamperCapability, d as TargetSchema, dt as vacuumControlCapability, et as parseAdminBase, f as accessoriesCapability, ft as valveCapability, g as ambientLightSensorCapability, gt as DeviceFeature, h as alarmPanelCapability, ht as weatherCapability, it as pressureSensorCapability, j as contactCapability, jt as string, k as colorCapability, kt as object, lt as temperatureSensorCapability, m as airQualitySensorCapability, mt as waterHeaterCapability, n as BaseDevice, nt as prepareNotification, ot as smokeCapability, p as addonRoutesCapability, pt as vibrationCapability, q as mediaPlayerCapability, r as BaseDeviceProvider, rt as presenceCapability, s as EnumSensorDateTimeFormatSchema, st as switchCapability, tt as powerMeterCapability, ut as updateCapability, v as batteryCapability, vt as DeviceType, w as buildDeviceAdminUrl, wt as array, x as brightnessCapability, xt as createEvent, y as bestLocationMatch, yt as errMsg, z as fanControlCapability } from "./dist-B9xf8_Ix.mjs";
1
+ import { A as connectivityCapability, At as record, B as floodCapability, C as buildAddonRouteProvider, Ct as _enum, D as carbonMonoxideCapability, Dt as literal, E as calendarSourceCapability, Et as discriminatedUnion, F as deviceAdoptionCapability, Ft as EventCategory, G as lawnMowerControlCapability, H as humidifierCapability, J as motionCapability, K as lockControlCapability, L as enumSensorCapability, M as controlCapability, Mt as union, N as coverCapability, Nt as unknown, O as climateControlCapability, Ot as number, P as deviceAdminLinkCapability, Pt as url, Q as numericSensorCapability, R as eventEmitterCapability, S as brokerCapability, T as buttonCapability, Tt as boolean, U as humiditySensorCapability, V as gasCapability, W as imageCapability, X as notificationOutputCapability, Y as normalizeUnit, Z as notifierCapability, _ as automationControlCapability, _t as DeviceRole, at as scriptRunnerCapability, b as binaryCapability, ct as tamperCapability, d as TargetSchema, dt as vacuumControlCapability, et as parseAdminBase, f as accessoriesCapability, ft as valveCapability, g as ambientLightSensorCapability, gt as DeviceFeature, h as alarmPanelCapability, ht as weatherCapability, it as pressureSensorCapability, j as contactCapability, jt as string, k as colorCapability, kt as object, lt as temperatureSensorCapability, m as airQualitySensorCapability, mt as waterHeaterCapability, n as BaseDevice, nt as prepareNotification, ot as smokeCapability, p as addonRoutesCapability, pt as vibrationCapability, q as mediaPlayerCapability, r as BaseDeviceProvider, rt as presenceCapability, s as EnumSensorDateTimeFormatSchema, st as switchCapability, tt as powerMeterCapability, ut as updateCapability, v as batteryCapability, vt as DeviceType, w as buildDeviceAdminUrl, wt as array, x as brightnessCapability, xt as createEvent, y as bestLocationMatch, yt as errMsg, z as fanControlCapability } from "./dist-CSIrSsu7.mjs";
2
2
  import { randomUUID } from "node:crypto";
3
3
  import { brotliCompressSync, deflateSync, gzipSync } from "node:zlib";
4
4
  //#region src/ha-admin-link.ts
@@ -1591,6 +1591,7 @@ var COLD_START$15 = {
1591
1591
  * - `target_temp_high` / `target_temp_low` → `targetHigh` / `targetLow`
1592
1592
  * - `target_humidity` → `targetHumidity`
1593
1593
  * - `current_temperature` / `current_humidity` → read-only
1594
+ * - `min_temp` / `max_temp` / `target_temp_step` → setpoint bounds
1594
1595
  *
1595
1596
  * Mutations route to:
1596
1597
  * - `climate.set_hvac_mode({ hvac_mode })`
@@ -1690,6 +1691,9 @@ function climateSliceFromState(state) {
1690
1691
  currentTemp: readNumberAttr$5(attrs, "current_temperature"),
1691
1692
  currentHumidity: readNumberAttr$5(attrs, "current_humidity"),
1692
1693
  ...readSwing(attrs),
1694
+ minTemp: readNumberAttr$5(attrs, "min_temp"),
1695
+ maxTemp: readNumberAttr$5(attrs, "max_temp"),
1696
+ tempStep: readNumberAttr$5(attrs, "target_temp_step"),
1693
1697
  lastFetchedAt
1694
1698
  };
1695
1699
  }
@@ -5804,7 +5808,7 @@ function mapHaEntityToCamStack(input) {
5804
5808
  switch (domain) {
5805
5809
  case "switch": return {
5806
5810
  deviceType: DeviceType.Switch,
5807
- role: null,
5811
+ role: deviceClass === "outlet" ? DeviceRole.Outlet : null,
5808
5812
  capabilities: ["switch"]
5809
5813
  };
5810
5814
  case "input_boolean": return {
@@ -5386,7 +5386,7 @@ var ZodIssueCode = {
5386
5386
  var ZodFirstPartyTypeKind;
5387
5387
  ZodFirstPartyTypeKind || (ZodFirstPartyTypeKind = {});
5388
5388
  //#endregion
5389
- //#region ../types/dist/sleep-DRqxtc0C.mjs
5389
+ //#region ../types/dist/sleep-bwsTj221.mjs
5390
5390
  /**
5391
5391
  * The audio chunk plane's byte format, and the ONE expansion from a coded
5392
5392
  * window to float samples (D455).
@@ -6637,7 +6637,6 @@ function createHandle(raw, opts) {
6637
6637
  const writeAddon = (patch) => write("addon", opts.addonTree(), void 0, patch, () => readStoredAddonBlob(raw), (p) => raw.writeAddonStore(p));
6638
6638
  const readAddonStoreResult = raw.readAddonStoreResult;
6639
6639
  const readAddonStoreKeyResult = raw.readAddonStoreKeyResult;
6640
- const readDeviceStoreBatch = raw.readDeviceStoreBatch;
6641
6640
  const overrides = {
6642
6641
  readAddonStore: async () => resolveRead("addon", await raw.readAddonStore()),
6643
6642
  ...readAddonStoreResult !== void 0 ? { readAddonStoreResult: async () => {
@@ -6661,12 +6660,12 @@ function createHandle(raw, opts) {
6661
6660
  };
6662
6661
  } } : {},
6663
6662
  readDeviceStore: async (deviceId) => resolveRead(`device:${deviceId}`, await raw.readDeviceStore(deviceId)),
6664
- ...readDeviceStoreBatch !== void 0 ? { readDeviceStoreBatch: async (deviceIds) => {
6665
- const rows = await readDeviceStoreBatch.call(raw, deviceIds);
6663
+ readDeviceStoreBatch: async (deviceIds) => {
6664
+ const rows = await raw.readDeviceStoreBatch(deviceIds);
6666
6665
  const out = /* @__PURE__ */ new Map();
6667
6666
  for (const [deviceId, blob] of rows) out.set(deviceId, await resolveRead(`device:${deviceId}`, blob));
6668
6667
  return out;
6669
- } } : {},
6668
+ },
6670
6669
  writeAddonStore: async (patch) => {
6671
6670
  await writeAddon(patch);
6672
6671
  },
@@ -7493,7 +7492,7 @@ var BaseAddon = class {
7493
7492
  return this._addonSecretTree;
7494
7493
  }
7495
7494
  deviceSecretTree() {
7496
- this._deviceSecretTree ??= secretTreeFromSchema(this.deviceSettingsSchema());
7495
+ this._deviceSecretTree ??= mergeSecretStatePaths(secretTreeFromSchema(this.deviceSettingsSchema()), this.secretStatePaths);
7497
7496
  return this._deviceSecretTree;
7498
7497
  }
7499
7498
  /**
@@ -7569,42 +7568,135 @@ var BaseAddon = class {
7569
7568
  this[timerOf] = timer;
7570
7569
  }
7571
7570
  /**
7572
- * Wrap `ctx.settings.readAddonStore()` with a short retry budget so a
7573
- * transient settings-store outage (mid-restart of sqlite-settings, tsx-watch
7574
- * swap, or any race where the SqliteSettingsBackend is between shutdown and
7575
- * re-initialize) doesn't propagate up into `initialize()` and leave the
7571
+ * Wrap `ctx.settings.readAddonStore()` with a retry budget so a transient
7572
+ * settings-store outage doesn't propagate up into `initialize()` and leave the
7576
7573
  * addon permanently broken.
7577
7574
  *
7578
- * Retry only the two known infra fingerprints. Anything else propagates so
7579
- * real bugs surface immediately. After the budget expires we fall back to
7580
- * `{}` (defaults) — the addon's first successful patch will rehydrate.
7575
+ * Two kinds of outage, two budgets:
7576
+ * - the store's own restart fingerprints (`SqliteSettingsBackend not
7577
+ * initialized`, `provider not available`): a short budget, then the addon
7578
+ * falls back to `{}` (defaults) - its first successful patch rehydrates;
7579
+ * - a TRANSPORT failure (the hub is restarting while this runner boots:
7580
+ * `discovery deadline exceeded`, `parent could not route`, a refused or
7581
+ * timed-out connection). Since D870 a runner's settings read THROWS instead
7582
+ * of answering `{}`, so without a budget a hub restart ends in a respawn
7583
+ * loop. A long, bounded budget; only after it the error propagates - the
7584
+ * addon never runs on defaults for a store it could not ask.
7585
+ * Anything else propagates immediately so real bugs surface.
7581
7586
  */
7582
7587
  async readAddonStoreWithRetry() {
7583
7588
  const settings = this.rawSettings();
7584
7589
  if (!settings) return {};
7585
- const delaysMs = [
7586
- 150,
7587
- 350,
7588
- 600,
7589
- 900
7590
- ];
7591
7590
  let lastErr;
7592
- for (let attempt = 0; attempt <= delaysMs.length; attempt++) try {
7591
+ for (let attempt = 0;; attempt++) try {
7593
7592
  const stored = await settings.readAddonStore() ?? {};
7594
7593
  this.settingsStoreReady = true;
7595
7594
  return stored;
7596
7595
  } catch (err) {
7597
7596
  lastErr = err;
7598
- const msg = err instanceof Error ? err.message : String(err);
7599
- if (!(msg.includes("SqliteSettingsBackend not initialized") || msg.includes("provider not available"))) throw err;
7600
- if (attempt === delaysMs.length) break;
7601
- await new Promise((r) => setTimeout(r, delaysMs[attempt]));
7597
+ const kind = classifyStoreError(err);
7598
+ if (kind === "permanent") throw err;
7599
+ const delay = (kind === "transport" ? TRANSPORT_RETRY_DELAYS_MS : RESTART_RETRY_DELAYS_MS)[attempt];
7600
+ if (delay === void 0) {
7601
+ if (kind === "transport") throw err;
7602
+ break;
7603
+ }
7604
+ await new Promise((r) => setTimeout(r, delay));
7602
7605
  }
7603
7606
  this.settingsStoreReady = false;
7604
7607
  this._ctx?.logger?.warn?.("readAddonStore: settings-store unavailable after retries — using defaults", { meta: { error: lastErr instanceof Error ? lastErr.message : String(lastErr) } });
7605
7608
  return {};
7606
7609
  }
7607
7610
  };
7611
+ /** The settings store's own restart fingerprints. */
7612
+ var RESTART_RETRY_DELAYS_MS = [
7613
+ 150,
7614
+ 350,
7615
+ 600,
7616
+ 900
7617
+ ];
7618
+ /** A hub restarting under a booting runner: ~100 s in total. */
7619
+ var TRANSPORT_RETRY_DELAYS_MS = [
7620
+ 150,
7621
+ 350,
7622
+ 600,
7623
+ 900,
7624
+ 2e3,
7625
+ 5e3,
7626
+ 1e4,
7627
+ 2e4,
7628
+ 3e4,
7629
+ 3e4
7630
+ ];
7631
+ var RESTART_FINGERPRINTS = ["SqliteSettingsBackend not initialized", "provider not available"];
7632
+ /** Node / socket error codes of a connection that did not happen or broke. */
7633
+ var TRANSPORT_CODES = new Set([
7634
+ "ECONNREFUSED",
7635
+ "ECONNRESET",
7636
+ "ETIMEDOUT",
7637
+ "EPIPE",
7638
+ "EHOSTUNREACH",
7639
+ "ENETUNREACH"
7640
+ ]);
7641
+ /** tRPC error codes that mean "the other side is not answering now", not "your call is wrong". */
7642
+ var UNAVAILABLE_TRPC_CODES = new Set([
7643
+ "TIMEOUT",
7644
+ "SERVICE_UNAVAILABLE",
7645
+ "BAD_GATEWAY",
7646
+ "GATEWAY_TIMEOUT"
7647
+ ]);
7648
+ /** The exact phrases OUR transport raises when it cannot reach the hub. */
7649
+ var TRANSPORT_PHRASES = [
7650
+ "discovery deadline exceeded",
7651
+ "parent could not route child unowned cap call",
7652
+ "UDS request timed out after",
7653
+ "channel closed"
7654
+ ];
7655
+ /** Moleculer error `type`s of a call that could not be served right now. */
7656
+ var MOLECULER_TRANSIENT_TYPES = new Set([
7657
+ "REQUEST_TIMEOUT",
7658
+ "SERVICE_NOT_FOUND",
7659
+ "SERVICE_NOT_AVAILABLE",
7660
+ "REQUEST_REJECTED",
7661
+ "BROKER_DISCONNECTED"
7662
+ ]);
7663
+ function stringProp(value, key) {
7664
+ if (typeof value !== "object" || value === null) return void 0;
7665
+ const found = Reflect.get(value, key);
7666
+ return typeof found === "string" ? found : void 0;
7667
+ }
7668
+ /** The code an error carries: its own, its cause's, or a tRPC `data.code`. */
7669
+ function errorCode(err) {
7670
+ const out = {};
7671
+ const cause = typeof err === "object" && err !== null ? Reflect.get(err, "cause") : void 0;
7672
+ const data = typeof err === "object" && err !== null ? Reflect.get(err, "data") : void 0;
7673
+ const node = stringProp(err, "code") ?? stringProp(cause, "code");
7674
+ if (node !== void 0) out.node = node;
7675
+ const trpc = stringProp(data, "code");
7676
+ if (trpc !== void 0) out.trpc = trpc;
7677
+ return out;
7678
+ }
7679
+ /**
7680
+ * Is a settings read failure worth retrying, and with which budget? Only
7681
+ * EXPLICIT signals count: a socket error code, a tRPC "unavailable" code, or
7682
+ * one of the exact phrases our own transport raises. A message that merely
7683
+ * contains "timed out" or "unreachable" is not evidence of anything, and
7684
+ * `settings store not wired` is a wiring bug that retrying cannot fix.
7685
+ */
7686
+ function classifyStoreError(err) {
7687
+ const message = err instanceof Error ? err.message : String(err);
7688
+ if (RESTART_FINGERPRINTS.some((f) => message.includes(f))) return "restart";
7689
+ const code = errorCode(err);
7690
+ if (code.node !== void 0 && TRANSPORT_CODES.has(code.node)) return "transport";
7691
+ if (code.trpc !== void 0 && UNAVAILABLE_TRPC_CODES.has(code.trpc)) return "transport";
7692
+ if (typeof err === "object" && err !== null) {
7693
+ if (Reflect.get(err, "retryable") === true) return "transport";
7694
+ const type = stringProp(err, "type");
7695
+ if (type !== void 0 && MOLECULER_TRANSIENT_TYPES.has(type)) return "transport";
7696
+ }
7697
+ if (TRANSPORT_PHRASES.some((f) => message.includes(f))) return "transport";
7698
+ return "permanent";
7699
+ }
7608
7700
  /**
7609
7701
  * Collect the keys of every field marked `perNode: true`, recursing into
7610
7702
  * layout containers (`group` fields and `sub-tabs` tabs) the same way
@@ -8285,7 +8377,7 @@ object({
8285
8377
  params: record(string(), union([string(), number()])).optional()
8286
8378
  });
8287
8379
  //#endregion
8288
- //#region ../types/dist/err-msg-DLerKiVO.mjs
8380
+ //#region ../types/dist/err-msg--2RrYiLO.mjs
8289
8381
  var DeviceType = /* @__PURE__ */ function(DeviceType) {
8290
8382
  DeviceType["Camera"] = "camera";
8291
8383
  DeviceType["Hub"] = "hub";
@@ -8554,6 +8646,9 @@ var DeviceRole = /* @__PURE__ */ function(DeviceRole) {
8554
8646
  /** Virtual HA toggle (input_boolean.*) — distinguishable from a
8555
8647
  * real Switch device for UI rendering / export adapters. */
8556
8648
  DeviceRole["BinaryHelper"] = "binary-helper";
8649
+ /** A smart plug: a `switch` whose source says it is an outlet (HA
8650
+ * `device_class: outlet`). The Alexa export shows it as a SMARTPLUG. */
8651
+ DeviceRole["Outlet"] = "outlet";
8557
8652
  /** Generic motion / occupancy / moving event source. Distinct from
8558
8653
  * the camera accessory PirSensor role: that one is a camera child;
8559
8654
  * this is a standalone HA / 3rd-party motion sensor. */
@@ -8631,7 +8726,7 @@ function errMsg(err) {
8631
8726
  return String(err);
8632
8727
  }
8633
8728
  //#endregion
8634
- //#region ../types/dist/composition-EQ9Ok0Ee.mjs
8729
+ //#region ../types/dist/composition-DOwQB_Ua.mjs
8635
8730
  /**
8636
8731
  * The ffmpeg build every CamStack node downloads, per platform and arch.
8637
8732
  *
@@ -11979,11 +12074,10 @@ var ClipModelMetaSchema = object({
11979
12074
  /**
11980
12075
  * The `vector-store` index this model's vectors live in. ONE feature space
11981
12076
  * per index: two models share an index only when their vectors are ranked
11982
- * against each other, which for CLIP means never across families. MobileCLIP
11983
- * S1 and S2 share `object-clip` for history (separated by the row's
11984
- * `modelId`); any other model gets its own.
12077
+ * against each other, which for CLIP means never across families. Every
12078
+ * model gets its own.
11985
12079
  */
11986
- vectorIndex: string().regex(/^object-clip(-[a-z0-9][a-z0-9-]*)?$/),
12080
+ vectorIndex: string().regex(/^object-clip-[a-z0-9][a-z0-9-]*$/),
11987
12081
  /**
11988
12082
  * The text encoder's tokenizer, a declared SIBLING file of its onnx. The name
11989
12083
  * must be unique per tokenizer: every model's siblings land in ONE flat
@@ -16272,6 +16366,28 @@ id: union([string(), number()]) }), {
16272
16366
  kind: "mutation",
16273
16367
  auth: "admin"
16274
16368
  });
16369
+ /** One table of the settings database. */
16370
+ var StorageTableSchema = object({
16371
+ /** The table's full name, e.g. `recorder:addon-settings` or `addon-device-settings`. */
16372
+ name: string(),
16373
+ /** The owner prefix of a scoped name (`recorder` for `recorder:addon-settings`), else null. */
16374
+ owner: string().nullable(),
16375
+ rows: number().int().nonnegative(),
16376
+ /** Bytes the table's pages occupy (`dbstat`); null when the engine cannot measure. */
16377
+ bytes: number().int().nonnegative().nullable(),
16378
+ /** Declared by an addon since this engine process started (a running addon claims it). */
16379
+ declaredThisBoot: boolean()
16380
+ });
16381
+ method(object({ ownerPrefix: string().min(1).optional() }), object({ tables: array(StorageTableSchema) }), { auth: "admin" }), method(object({
16382
+ collection: string().min(1),
16383
+ expectRows: number().int().nonnegative()
16384
+ }), object({
16385
+ dropped: literal(true),
16386
+ rows: number().int().nonnegative()
16387
+ }), {
16388
+ kind: "mutation",
16389
+ auth: "admin"
16390
+ });
16275
16391
  /**
16276
16392
  * `keychain` — the hub's encrypted store of secret values (D787).
16277
16393
  *
@@ -16813,6 +16929,16 @@ method(object({}), KeychainStatusSchema, { auth: "admin" }), method(object({}),
16813
16929
  kind: "mutation",
16814
16930
  auth: "admin",
16815
16931
  caller: "required"
16932
+ }), method(object({
16933
+ ref: string().min(1),
16934
+ value: string().min(1)
16935
+ }), object({
16936
+ ref: string(),
16937
+ version: number().int()
16938
+ }), {
16939
+ kind: "mutation",
16940
+ auth: "admin",
16941
+ caller: "required"
16816
16942
  }), method(object({ refs: array(string().min(1)).max(1e3) }), object({
16817
16943
  deleted: array(string()).readonly(),
16818
16944
  kept: array(object({
@@ -54326,6 +54452,12 @@ var ClimateControlStatusSchema = object({
54326
54452
  /** Horizontal louver swing on/off. Null when the device has no
54327
54453
  * horizontal swing surface (gate with `DeviceFeature.ClimateSwingHorizontal`). */
54328
54454
  swingHorizontal: boolean().nullable(),
54455
+ /** Lowest setpoint the device accepts, Celsius. Absent / null = not reported. */
54456
+ minTemp: number().nullable().optional(),
54457
+ /** Highest setpoint the device accepts, Celsius. Absent / null = not reported. */
54458
+ maxTemp: number().nullable().optional(),
54459
+ /** Setpoint granularity, Celsius (0.5, 1). Absent / null = not reported. */
54460
+ tempStep: number().positive().nullable().optional(),
54329
54461
  /** Ms epoch when the slice was last updated (push or command). */
54330
54462
  lastFetchedAt: number()
54331
54463
  });
@@ -57106,7 +57238,19 @@ var TlsStatusSchema = object({
57106
57238
  sans: array(string()),
57107
57239
  caCertPem: string().nullable(),
57108
57240
  reissueError: string().nullable(),
57109
- restartRequired: boolean()
57241
+ restartRequired: boolean(),
57242
+ /** An uploaded certificate is served but no CA is kept for it and it is not publicly signed (D873). */
57243
+ caMissing: boolean(),
57244
+ /** Does the hub's own generated CA carry a critical name constraint? `null` while it has none. */
57245
+ localCaConstrained: boolean().nullable(),
57246
+ /** ISO time the generated CA was replaced by a constrained one; devices must re-download it. */
57247
+ caReplacedAt: string().nullable(),
57248
+ /** The uploaded certificate kept on disk, selectable again after "Revert to generated". */
57249
+ storedUpload: object({
57250
+ leafFingerprintSha256: string(),
57251
+ validTo: string(),
57252
+ hasCa: boolean()
57253
+ }).nullable()
57110
57254
  });
57111
57255
  method(_void(), ListResultSchema), method(_void(), PreferredSchema), method(object({
57112
57256
  /**
@@ -57162,6 +57306,9 @@ method(_void(), ListResultSchema), method(_void(), PreferredSchema), method(obje
57162
57306
  }), method(_void(), object({ pem: string() })), method(_void(), TlsStatusSchema, {
57163
57307
  kind: "mutation",
57164
57308
  auth: "admin"
57309
+ }), method(_void(), TlsStatusSchema, {
57310
+ kind: "mutation",
57311
+ auth: "admin"
57165
57312
  });
57166
57313
  var LockControlStatusSchema = object({
57167
57314
  /** Lifecycle state of the lock. `jammed` means the motor reported
@@ -69467,6 +69614,12 @@ Object.freeze({
69467
69614
  addonId: null,
69468
69615
  access: "create"
69469
69616
  },
69617
+ "keychainAdmin.importSecret": {
69618
+ capName: "keychain-admin",
69619
+ capScope: "system",
69620
+ addonId: null,
69621
+ access: "create"
69622
+ },
69470
69623
  "keychainAdmin.listAudit": {
69471
69624
  capName: "keychain-admin",
69472
69625
  capScope: "system",
@@ -69863,6 +70016,12 @@ Object.freeze({
69863
70016
  addonId: null,
69864
70017
  access: "create"
69865
70018
  },
70019
+ "localNetwork.useStoredUploadedCertificate": {
70020
+ capName: "local-network",
70021
+ capScope: "system",
70022
+ addonId: null,
70023
+ access: "create"
70024
+ },
69866
70025
  "lockControl.getStatus": {
69867
70026
  capName: "lock-control",
69868
70027
  capScope: "device",
@@ -73247,6 +73406,18 @@ Object.freeze({
73247
73406
  addonId: null,
73248
73407
  access: "create"
73249
73408
  },
73409
+ "storageAdmin.dropCollection": {
73410
+ capName: "storage-admin",
73411
+ capScope: "system",
73412
+ addonId: null,
73413
+ access: "delete"
73414
+ },
73415
+ "storageAdmin.listTables": {
73416
+ capName: "storage-admin",
73417
+ capScope: "system",
73418
+ addonId: null,
73419
+ access: "view"
73420
+ },
73250
73421
  "storageEvictable.evict": {
73251
73422
  capName: "storage-evictable",
73252
73423
  capScope: "system",
@@ -5387,7 +5387,7 @@ var ZodIssueCode = {
5387
5387
  var ZodFirstPartyTypeKind;
5388
5388
  ZodFirstPartyTypeKind || (ZodFirstPartyTypeKind = {});
5389
5389
  //#endregion
5390
- //#region ../types/dist/sleep-DRqxtc0C.mjs
5390
+ //#region ../types/dist/sleep-bwsTj221.mjs
5391
5391
  /**
5392
5392
  * The audio chunk plane's byte format, and the ONE expansion from a coded
5393
5393
  * window to float samples (D455).
@@ -6638,7 +6638,6 @@ function createHandle(raw, opts) {
6638
6638
  const writeAddon = (patch) => write("addon", opts.addonTree(), void 0, patch, () => readStoredAddonBlob(raw), (p) => raw.writeAddonStore(p));
6639
6639
  const readAddonStoreResult = raw.readAddonStoreResult;
6640
6640
  const readAddonStoreKeyResult = raw.readAddonStoreKeyResult;
6641
- const readDeviceStoreBatch = raw.readDeviceStoreBatch;
6642
6641
  const overrides = {
6643
6642
  readAddonStore: async () => resolveRead("addon", await raw.readAddonStore()),
6644
6643
  ...readAddonStoreResult !== void 0 ? { readAddonStoreResult: async () => {
@@ -6662,12 +6661,12 @@ function createHandle(raw, opts) {
6662
6661
  };
6663
6662
  } } : {},
6664
6663
  readDeviceStore: async (deviceId) => resolveRead(`device:${deviceId}`, await raw.readDeviceStore(deviceId)),
6665
- ...readDeviceStoreBatch !== void 0 ? { readDeviceStoreBatch: async (deviceIds) => {
6666
- const rows = await readDeviceStoreBatch.call(raw, deviceIds);
6664
+ readDeviceStoreBatch: async (deviceIds) => {
6665
+ const rows = await raw.readDeviceStoreBatch(deviceIds);
6667
6666
  const out = /* @__PURE__ */ new Map();
6668
6667
  for (const [deviceId, blob] of rows) out.set(deviceId, await resolveRead(`device:${deviceId}`, blob));
6669
6668
  return out;
6670
- } } : {},
6669
+ },
6671
6670
  writeAddonStore: async (patch) => {
6672
6671
  await writeAddon(patch);
6673
6672
  },
@@ -7494,7 +7493,7 @@ var BaseAddon = class {
7494
7493
  return this._addonSecretTree;
7495
7494
  }
7496
7495
  deviceSecretTree() {
7497
- this._deviceSecretTree ??= secretTreeFromSchema(this.deviceSettingsSchema());
7496
+ this._deviceSecretTree ??= mergeSecretStatePaths(secretTreeFromSchema(this.deviceSettingsSchema()), this.secretStatePaths);
7498
7497
  return this._deviceSecretTree;
7499
7498
  }
7500
7499
  /**
@@ -7570,42 +7569,135 @@ var BaseAddon = class {
7570
7569
  this[timerOf] = timer;
7571
7570
  }
7572
7571
  /**
7573
- * Wrap `ctx.settings.readAddonStore()` with a short retry budget so a
7574
- * transient settings-store outage (mid-restart of sqlite-settings, tsx-watch
7575
- * swap, or any race where the SqliteSettingsBackend is between shutdown and
7576
- * re-initialize) doesn't propagate up into `initialize()` and leave the
7572
+ * Wrap `ctx.settings.readAddonStore()` with a retry budget so a transient
7573
+ * settings-store outage doesn't propagate up into `initialize()` and leave the
7577
7574
  * addon permanently broken.
7578
7575
  *
7579
- * Retry only the two known infra fingerprints. Anything else propagates so
7580
- * real bugs surface immediately. After the budget expires we fall back to
7581
- * `{}` (defaults) — the addon's first successful patch will rehydrate.
7576
+ * Two kinds of outage, two budgets:
7577
+ * - the store's own restart fingerprints (`SqliteSettingsBackend not
7578
+ * initialized`, `provider not available`): a short budget, then the addon
7579
+ * falls back to `{}` (defaults) - its first successful patch rehydrates;
7580
+ * - a TRANSPORT failure (the hub is restarting while this runner boots:
7581
+ * `discovery deadline exceeded`, `parent could not route`, a refused or
7582
+ * timed-out connection). Since D870 a runner's settings read THROWS instead
7583
+ * of answering `{}`, so without a budget a hub restart ends in a respawn
7584
+ * loop. A long, bounded budget; only after it the error propagates - the
7585
+ * addon never runs on defaults for a store it could not ask.
7586
+ * Anything else propagates immediately so real bugs surface.
7582
7587
  */
7583
7588
  async readAddonStoreWithRetry() {
7584
7589
  const settings = this.rawSettings();
7585
7590
  if (!settings) return {};
7586
- const delaysMs = [
7587
- 150,
7588
- 350,
7589
- 600,
7590
- 900
7591
- ];
7592
7591
  let lastErr;
7593
- for (let attempt = 0; attempt <= delaysMs.length; attempt++) try {
7592
+ for (let attempt = 0;; attempt++) try {
7594
7593
  const stored = await settings.readAddonStore() ?? {};
7595
7594
  this.settingsStoreReady = true;
7596
7595
  return stored;
7597
7596
  } catch (err) {
7598
7597
  lastErr = err;
7599
- const msg = err instanceof Error ? err.message : String(err);
7600
- if (!(msg.includes("SqliteSettingsBackend not initialized") || msg.includes("provider not available"))) throw err;
7601
- if (attempt === delaysMs.length) break;
7602
- await new Promise((r) => setTimeout(r, delaysMs[attempt]));
7598
+ const kind = classifyStoreError(err);
7599
+ if (kind === "permanent") throw err;
7600
+ const delay = (kind === "transport" ? TRANSPORT_RETRY_DELAYS_MS : RESTART_RETRY_DELAYS_MS)[attempt];
7601
+ if (delay === void 0) {
7602
+ if (kind === "transport") throw err;
7603
+ break;
7604
+ }
7605
+ await new Promise((r) => setTimeout(r, delay));
7603
7606
  }
7604
7607
  this.settingsStoreReady = false;
7605
7608
  this._ctx?.logger?.warn?.("readAddonStore: settings-store unavailable after retries — using defaults", { meta: { error: lastErr instanceof Error ? lastErr.message : String(lastErr) } });
7606
7609
  return {};
7607
7610
  }
7608
7611
  };
7612
+ /** The settings store's own restart fingerprints. */
7613
+ var RESTART_RETRY_DELAYS_MS = [
7614
+ 150,
7615
+ 350,
7616
+ 600,
7617
+ 900
7618
+ ];
7619
+ /** A hub restarting under a booting runner: ~100 s in total. */
7620
+ var TRANSPORT_RETRY_DELAYS_MS = [
7621
+ 150,
7622
+ 350,
7623
+ 600,
7624
+ 900,
7625
+ 2e3,
7626
+ 5e3,
7627
+ 1e4,
7628
+ 2e4,
7629
+ 3e4,
7630
+ 3e4
7631
+ ];
7632
+ var RESTART_FINGERPRINTS = ["SqliteSettingsBackend not initialized", "provider not available"];
7633
+ /** Node / socket error codes of a connection that did not happen or broke. */
7634
+ var TRANSPORT_CODES = new Set([
7635
+ "ECONNREFUSED",
7636
+ "ECONNRESET",
7637
+ "ETIMEDOUT",
7638
+ "EPIPE",
7639
+ "EHOSTUNREACH",
7640
+ "ENETUNREACH"
7641
+ ]);
7642
+ /** tRPC error codes that mean "the other side is not answering now", not "your call is wrong". */
7643
+ var UNAVAILABLE_TRPC_CODES = new Set([
7644
+ "TIMEOUT",
7645
+ "SERVICE_UNAVAILABLE",
7646
+ "BAD_GATEWAY",
7647
+ "GATEWAY_TIMEOUT"
7648
+ ]);
7649
+ /** The exact phrases OUR transport raises when it cannot reach the hub. */
7650
+ var TRANSPORT_PHRASES = [
7651
+ "discovery deadline exceeded",
7652
+ "parent could not route child unowned cap call",
7653
+ "UDS request timed out after",
7654
+ "channel closed"
7655
+ ];
7656
+ /** Moleculer error `type`s of a call that could not be served right now. */
7657
+ var MOLECULER_TRANSIENT_TYPES = new Set([
7658
+ "REQUEST_TIMEOUT",
7659
+ "SERVICE_NOT_FOUND",
7660
+ "SERVICE_NOT_AVAILABLE",
7661
+ "REQUEST_REJECTED",
7662
+ "BROKER_DISCONNECTED"
7663
+ ]);
7664
+ function stringProp(value, key) {
7665
+ if (typeof value !== "object" || value === null) return void 0;
7666
+ const found = Reflect.get(value, key);
7667
+ return typeof found === "string" ? found : void 0;
7668
+ }
7669
+ /** The code an error carries: its own, its cause's, or a tRPC `data.code`. */
7670
+ function errorCode(err) {
7671
+ const out = {};
7672
+ const cause = typeof err === "object" && err !== null ? Reflect.get(err, "cause") : void 0;
7673
+ const data = typeof err === "object" && err !== null ? Reflect.get(err, "data") : void 0;
7674
+ const node = stringProp(err, "code") ?? stringProp(cause, "code");
7675
+ if (node !== void 0) out.node = node;
7676
+ const trpc = stringProp(data, "code");
7677
+ if (trpc !== void 0) out.trpc = trpc;
7678
+ return out;
7679
+ }
7680
+ /**
7681
+ * Is a settings read failure worth retrying, and with which budget? Only
7682
+ * EXPLICIT signals count: a socket error code, a tRPC "unavailable" code, or
7683
+ * one of the exact phrases our own transport raises. A message that merely
7684
+ * contains "timed out" or "unreachable" is not evidence of anything, and
7685
+ * `settings store not wired` is a wiring bug that retrying cannot fix.
7686
+ */
7687
+ function classifyStoreError(err) {
7688
+ const message = err instanceof Error ? err.message : String(err);
7689
+ if (RESTART_FINGERPRINTS.some((f) => message.includes(f))) return "restart";
7690
+ const code = errorCode(err);
7691
+ if (code.node !== void 0 && TRANSPORT_CODES.has(code.node)) return "transport";
7692
+ if (code.trpc !== void 0 && UNAVAILABLE_TRPC_CODES.has(code.trpc)) return "transport";
7693
+ if (typeof err === "object" && err !== null) {
7694
+ if (Reflect.get(err, "retryable") === true) return "transport";
7695
+ const type = stringProp(err, "type");
7696
+ if (type !== void 0 && MOLECULER_TRANSIENT_TYPES.has(type)) return "transport";
7697
+ }
7698
+ if (TRANSPORT_PHRASES.some((f) => message.includes(f))) return "transport";
7699
+ return "permanent";
7700
+ }
7609
7701
  /**
7610
7702
  * Collect the keys of every field marked `perNode: true`, recursing into
7611
7703
  * layout containers (`group` fields and `sub-tabs` tabs) the same way
@@ -8286,7 +8378,7 @@ object({
8286
8378
  params: record(string(), union([string(), number()])).optional()
8287
8379
  });
8288
8380
  //#endregion
8289
- //#region ../types/dist/err-msg-DLerKiVO.mjs
8381
+ //#region ../types/dist/err-msg--2RrYiLO.mjs
8290
8382
  var DeviceType = /* @__PURE__ */ function(DeviceType) {
8291
8383
  DeviceType["Camera"] = "camera";
8292
8384
  DeviceType["Hub"] = "hub";
@@ -8555,6 +8647,9 @@ var DeviceRole = /* @__PURE__ */ function(DeviceRole) {
8555
8647
  /** Virtual HA toggle (input_boolean.*) — distinguishable from a
8556
8648
  * real Switch device for UI rendering / export adapters. */
8557
8649
  DeviceRole["BinaryHelper"] = "binary-helper";
8650
+ /** A smart plug: a `switch` whose source says it is an outlet (HA
8651
+ * `device_class: outlet`). The Alexa export shows it as a SMARTPLUG. */
8652
+ DeviceRole["Outlet"] = "outlet";
8558
8653
  /** Generic motion / occupancy / moving event source. Distinct from
8559
8654
  * the camera accessory PirSensor role: that one is a camera child;
8560
8655
  * this is a standalone HA / 3rd-party motion sensor. */
@@ -8632,7 +8727,7 @@ function errMsg(err) {
8632
8727
  return String(err);
8633
8728
  }
8634
8729
  //#endregion
8635
- //#region ../types/dist/composition-EQ9Ok0Ee.mjs
8730
+ //#region ../types/dist/composition-DOwQB_Ua.mjs
8636
8731
  /**
8637
8732
  * The ffmpeg build every CamStack node downloads, per platform and arch.
8638
8733
  *
@@ -11980,11 +12075,10 @@ var ClipModelMetaSchema = object({
11980
12075
  /**
11981
12076
  * The `vector-store` index this model's vectors live in. ONE feature space
11982
12077
  * per index: two models share an index only when their vectors are ranked
11983
- * against each other, which for CLIP means never across families. MobileCLIP
11984
- * S1 and S2 share `object-clip` for history (separated by the row's
11985
- * `modelId`); any other model gets its own.
12078
+ * against each other, which for CLIP means never across families. Every
12079
+ * model gets its own.
11986
12080
  */
11987
- vectorIndex: string().regex(/^object-clip(-[a-z0-9][a-z0-9-]*)?$/),
12081
+ vectorIndex: string().regex(/^object-clip-[a-z0-9][a-z0-9-]*$/),
11988
12082
  /**
11989
12083
  * The text encoder's tokenizer, a declared SIBLING file of its onnx. The name
11990
12084
  * must be unique per tokenizer: every model's siblings land in ONE flat
@@ -16273,6 +16367,28 @@ id: union([string(), number()]) }), {
16273
16367
  kind: "mutation",
16274
16368
  auth: "admin"
16275
16369
  });
16370
+ /** One table of the settings database. */
16371
+ var StorageTableSchema = object({
16372
+ /** The table's full name, e.g. `recorder:addon-settings` or `addon-device-settings`. */
16373
+ name: string(),
16374
+ /** The owner prefix of a scoped name (`recorder` for `recorder:addon-settings`), else null. */
16375
+ owner: string().nullable(),
16376
+ rows: number().int().nonnegative(),
16377
+ /** Bytes the table's pages occupy (`dbstat`); null when the engine cannot measure. */
16378
+ bytes: number().int().nonnegative().nullable(),
16379
+ /** Declared by an addon since this engine process started (a running addon claims it). */
16380
+ declaredThisBoot: boolean()
16381
+ });
16382
+ method(object({ ownerPrefix: string().min(1).optional() }), object({ tables: array(StorageTableSchema) }), { auth: "admin" }), method(object({
16383
+ collection: string().min(1),
16384
+ expectRows: number().int().nonnegative()
16385
+ }), object({
16386
+ dropped: literal(true),
16387
+ rows: number().int().nonnegative()
16388
+ }), {
16389
+ kind: "mutation",
16390
+ auth: "admin"
16391
+ });
16276
16392
  /**
16277
16393
  * `keychain` — the hub's encrypted store of secret values (D787).
16278
16394
  *
@@ -16814,6 +16930,16 @@ method(object({}), KeychainStatusSchema, { auth: "admin" }), method(object({}),
16814
16930
  kind: "mutation",
16815
16931
  auth: "admin",
16816
16932
  caller: "required"
16933
+ }), method(object({
16934
+ ref: string().min(1),
16935
+ value: string().min(1)
16936
+ }), object({
16937
+ ref: string(),
16938
+ version: number().int()
16939
+ }), {
16940
+ kind: "mutation",
16941
+ auth: "admin",
16942
+ caller: "required"
16817
16943
  }), method(object({ refs: array(string().min(1)).max(1e3) }), object({
16818
16944
  deleted: array(string()).readonly(),
16819
16945
  kept: array(object({
@@ -54327,6 +54453,12 @@ var ClimateControlStatusSchema = object({
54327
54453
  /** Horizontal louver swing on/off. Null when the device has no
54328
54454
  * horizontal swing surface (gate with `DeviceFeature.ClimateSwingHorizontal`). */
54329
54455
  swingHorizontal: boolean().nullable(),
54456
+ /** Lowest setpoint the device accepts, Celsius. Absent / null = not reported. */
54457
+ minTemp: number().nullable().optional(),
54458
+ /** Highest setpoint the device accepts, Celsius. Absent / null = not reported. */
54459
+ maxTemp: number().nullable().optional(),
54460
+ /** Setpoint granularity, Celsius (0.5, 1). Absent / null = not reported. */
54461
+ tempStep: number().positive().nullable().optional(),
54330
54462
  /** Ms epoch when the slice was last updated (push or command). */
54331
54463
  lastFetchedAt: number()
54332
54464
  });
@@ -57107,7 +57239,19 @@ var TlsStatusSchema = object({
57107
57239
  sans: array(string()),
57108
57240
  caCertPem: string().nullable(),
57109
57241
  reissueError: string().nullable(),
57110
- restartRequired: boolean()
57242
+ restartRequired: boolean(),
57243
+ /** An uploaded certificate is served but no CA is kept for it and it is not publicly signed (D873). */
57244
+ caMissing: boolean(),
57245
+ /** Does the hub's own generated CA carry a critical name constraint? `null` while it has none. */
57246
+ localCaConstrained: boolean().nullable(),
57247
+ /** ISO time the generated CA was replaced by a constrained one; devices must re-download it. */
57248
+ caReplacedAt: string().nullable(),
57249
+ /** The uploaded certificate kept on disk, selectable again after "Revert to generated". */
57250
+ storedUpload: object({
57251
+ leafFingerprintSha256: string(),
57252
+ validTo: string(),
57253
+ hasCa: boolean()
57254
+ }).nullable()
57111
57255
  });
57112
57256
  method(_void(), ListResultSchema), method(_void(), PreferredSchema), method(object({
57113
57257
  /**
@@ -57163,6 +57307,9 @@ method(_void(), ListResultSchema), method(_void(), PreferredSchema), method(obje
57163
57307
  }), method(_void(), object({ pem: string() })), method(_void(), TlsStatusSchema, {
57164
57308
  kind: "mutation",
57165
57309
  auth: "admin"
57310
+ }), method(_void(), TlsStatusSchema, {
57311
+ kind: "mutation",
57312
+ auth: "admin"
57166
57313
  });
57167
57314
  var LockControlStatusSchema = object({
57168
57315
  /** Lifecycle state of the lock. `jammed` means the motor reported
@@ -69468,6 +69615,12 @@ Object.freeze({
69468
69615
  addonId: null,
69469
69616
  access: "create"
69470
69617
  },
69618
+ "keychainAdmin.importSecret": {
69619
+ capName: "keychain-admin",
69620
+ capScope: "system",
69621
+ addonId: null,
69622
+ access: "create"
69623
+ },
69471
69624
  "keychainAdmin.listAudit": {
69472
69625
  capName: "keychain-admin",
69473
69626
  capScope: "system",
@@ -69864,6 +70017,12 @@ Object.freeze({
69864
70017
  addonId: null,
69865
70018
  access: "create"
69866
70019
  },
70020
+ "localNetwork.useStoredUploadedCertificate": {
70021
+ capName: "local-network",
70022
+ capScope: "system",
70023
+ addonId: null,
70024
+ access: "create"
70025
+ },
69867
70026
  "lockControl.getStatus": {
69868
70027
  capName: "lock-control",
69869
70028
  capScope: "device",
@@ -73248,6 +73407,18 @@ Object.freeze({
73248
73407
  addonId: null,
73249
73408
  access: "create"
73250
73409
  },
73410
+ "storageAdmin.dropCollection": {
73411
+ capName: "storage-admin",
73412
+ capScope: "system",
73413
+ addonId: null,
73414
+ access: "delete"
73415
+ },
73416
+ "storageAdmin.listTables": {
73417
+ capName: "storage-admin",
73418
+ capScope: "system",
73419
+ addonId: null,
73420
+ access: "view"
73421
+ },
73251
73422
  "storageEvictable.evict": {
73252
73423
  capName: "storage-evictable",
73253
73424
  capScope: "system",
@@ -24,7 +24,7 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
24
24
  enumerable: true
25
25
  }) : target, mod));
26
26
  //#endregion
27
- const require_dist = require("../dist-Ba9raKow.js");
27
+ const require_dist = require("../dist-DTt9hwTQ.js");
28
28
  let node_crypto = require("node:crypto");
29
29
  require("node:zlib");
30
30
  let node_fs = require("node:fs");
@@ -1,4 +1,4 @@
1
- import { $ as oauthIntegrationCapability, C as buildAddonRouteProvider, Ft as EventCategory, I as deviceExportCapability, St as nodePin, a as COCO_TO_MACRO, bt as BaseAddon, c as FanDirectionSchema, i as CAMERA_SWITCH_ORDER, jt as string, l as HvacModeSchema, o as CameraSwitchIdSchema, p as addonRoutesCapability, t as AlarmArmModeSchema, u as MediaPlayerRepeatSchema } from "../dist-B9xf8_Ix.mjs";
1
+ import { $ as oauthIntegrationCapability, C as buildAddonRouteProvider, Ft as EventCategory, I as deviceExportCapability, St as nodePin, a as COCO_TO_MACRO, bt as BaseAddon, c as FanDirectionSchema, i as CAMERA_SWITCH_ORDER, jt as string, l as HvacModeSchema, o as CameraSwitchIdSchema, p as addonRoutesCapability, t as AlarmArmModeSchema, u as MediaPlayerRepeatSchema } from "../dist-CSIrSsu7.mjs";
2
2
  import { createHmac, timingSafeEqual } from "node:crypto";
3
3
  import "node:zlib";
4
4
  import "node:fs";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@camstack/addon-provider-homeassistant",
3
- "version": "1.2.172",
3
+ "version": "1.2.173",
4
4
  "description": "Home Assistant device provider addon for CamStack",
5
5
  "keywords": [
6
6
  "camstack",