@camstack/addon-import-alexa 0.2.178 → 0.2.179

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.mjs CHANGED
@@ -832,7 +832,7 @@ var EventCategory = /* @__PURE__ */ function(EventCategory) {
832
832
  return EventCategory;
833
833
  }({});
834
834
  //#endregion
835
- //#region ../types/dist/device-type-BOWLtoOt.mjs
835
+ //#region ../types/dist/device-type-CfHw_quR.mjs
836
836
  /**
837
837
  import { errMsg } from '@camstack/types'
838
838
  * Extract a human-readable message from an unknown error value.
@@ -1021,6 +1021,9 @@ var DeviceFeature = /* @__PURE__ */ function(DeviceFeature) {
1021
1021
  DeviceFeature["CoverPositionable"] = "cover-positionable";
1022
1022
  /** Cover exposes slat-tilt control. Gates the tilt slider UI. */
1023
1023
  DeviceFeature["CoverTilt"] = "cover-tilt";
1024
+ /** Cover has a real stop: `stop` halts the travel in place. Gates the stop
1025
+ * control in exporters; a provider whose `stop` is a no-op never declares it. */
1026
+ DeviceFeature["CoverStoppable"] = "cover-stoppable";
1024
1027
  /** Valve exposes intermediate position control (0..100). Gates the
1025
1028
  * position slider / drag surface UI. */
1026
1029
  DeviceFeature["ValvePositionable"] = "valve-positionable";
@@ -6033,7 +6036,7 @@ function number(params) {
6033
6036
  return /* @__PURE__ */ _coercedNumber(ZodNumber, params);
6034
6037
  }
6035
6038
  //#endregion
6036
- //#region ../types/dist/sleep-B-vp7x15.mjs
6039
+ //#region ../types/dist/sleep-hmSP-eJt.mjs
6037
6040
  /**
6038
6041
  * The audio chunk plane's byte format, and the ONE expansion from a coded
6039
6042
  * window to float samples (D455).
@@ -6150,7 +6153,7 @@ function isKeychainStoredField(field) {
6150
6153
  var SECRET_CLEAR = { $secretClear: true };
6151
6154
  /** The `'***'` token D634 redaction writes for non-admins. */
6152
6155
  var LEGACY_DEVICE_REDACTION = "***";
6153
- function isRecord$6(value) {
6156
+ function isRecord$7(value) {
6154
6157
  return typeof value === "object" && value !== null && !Array.isArray(value);
6155
6158
  }
6156
6159
  function makeSecretMarker(ref) {
@@ -6161,12 +6164,12 @@ function makeSecretMarker(ref) {
6161
6164
  }
6162
6165
  /** A stored marker: an object whose `$secret` is a non-empty string. */
6163
6166
  function isSecretMarker(value) {
6164
- if (!isRecord$6(value)) return false;
6167
+ if (!isRecord$7(value)) return false;
6165
6168
  const ref = value["$secret"];
6166
6169
  return typeof ref === "string" && ref.length > 0;
6167
6170
  }
6168
6171
  function isSecretClear(value) {
6169
- return isRecord$6(value) && value["$secretClear"] === true;
6172
+ return isRecord$7(value) && value["$secretClear"] === true;
6170
6173
  }
6171
6174
  /**
6172
6175
  * The UI view of a stored secret field value: a marker becomes "set", inline
@@ -6919,7 +6922,7 @@ var KeychainWriteRefusedError = class extends Error {
6919
6922
  }
6920
6923
  };
6921
6924
  var KEEP = { kind: "keep" };
6922
- function isRecord$5(value) {
6925
+ function isRecord$6(value) {
6923
6926
  return typeof value === "object" && value !== null && !Array.isArray(value);
6924
6927
  }
6925
6928
  function defaultMintId() {
@@ -6932,7 +6935,7 @@ function collectSecretMarkerRefs(value, out = []) {
6932
6935
  return out;
6933
6936
  }
6934
6937
  if (Array.isArray(value)) for (const item of value) collectSecretMarkerRefs(item, out);
6935
- else if (isRecord$5(value)) for (const child of Object.values(value)) collectSecretMarkerRefs(child, out);
6938
+ else if (isRecord$6(value)) for (const child of Object.values(value)) collectSecretMarkerRefs(child, out);
6936
6939
  return out;
6937
6940
  }
6938
6941
  async function storedValueEquals(secrets, marker, candidate) {
@@ -6987,7 +6990,7 @@ function rowId(row, idKey) {
6987
6990
  return null;
6988
6991
  }
6989
6992
  async function writeArray(ctx, node, incoming, stored, fieldPath) {
6990
- const storedRows = Array.isArray(stored) ? stored.filter(isRecord$5) : [];
6993
+ const storedRows = Array.isArray(stored) ? stored.filter(isRecord$6) : [];
6991
6994
  if (!Array.isArray(incoming)) {
6992
6995
  ctx.deletes.push(...collectSecretMarkerRefs(storedRows));
6993
6996
  return {
@@ -7003,7 +7006,7 @@ async function writeArray(ctx, node, incoming, stored, fieldPath) {
7003
7006
  const kept = /* @__PURE__ */ new Set();
7004
7007
  const rows = [];
7005
7008
  for (const row of incoming) {
7006
- if (!isRecord$5(row)) {
7009
+ if (!isRecord$6(row)) {
7007
7010
  rows.push(row);
7008
7011
  continue;
7009
7012
  }
@@ -7028,7 +7031,7 @@ async function writeNode(ctx, node, incoming, stored, fieldPath) {
7028
7031
  case "leaf": return writeLeaf(ctx, incoming, stored, fieldPath);
7029
7032
  case "array": return writeArray(ctx, node, incoming, stored, fieldPath);
7030
7033
  case "object": {
7031
- if (!isRecord$5(incoming)) {
7034
+ if (!isRecord$6(incoming)) {
7032
7035
  if (incoming === void 0) return KEEP;
7033
7036
  ctx.deletes.push(...collectSecretMarkerRefs(stored));
7034
7037
  return {
@@ -7036,7 +7039,7 @@ async function writeNode(ctx, node, incoming, stored, fieldPath) {
7036
7039
  value: incoming
7037
7040
  };
7038
7041
  }
7039
- const storedObj = isRecord$5(stored) ? stored : {};
7042
+ const storedObj = isRecord$6(stored) ? stored : {};
7040
7043
  return {
7041
7044
  kind: "value",
7042
7045
  value: await writeMembers(ctx, node.children, incoming, storedObj, (m) => `${fieldPath}.${m}`)
@@ -7159,7 +7162,7 @@ async function resolveSecretMarkers(value, secrets, options = {}) {
7159
7162
  value: items
7160
7163
  };
7161
7164
  }
7162
- if (isRecord$5(v)) {
7165
+ if (isRecord$6(v)) {
7163
7166
  const out = {};
7164
7167
  for (const [k, child] of Object.entries(v)) {
7165
7168
  const s = substitute(child);
@@ -7191,7 +7194,7 @@ var SecretOverwriteRefusedError = class extends Error {
7191
7194
  this.name = "SecretOverwriteRefusedError";
7192
7195
  }
7193
7196
  };
7194
- function isRecord$4$1(value) {
7197
+ function isRecord$5(value) {
7195
7198
  return typeof value === "object" && value !== null && !Array.isArray(value);
7196
7199
  }
7197
7200
  function resolvedValue(pass, marker) {
@@ -7220,7 +7223,7 @@ function inArray(pass, incoming, stored) {
7220
7223
  return incoming.map((item, index) => {
7221
7224
  const twin = stored[index];
7222
7225
  if (isSecretMarker(twin)) return typeof item === "string" && item === resolvedValue(pass, twin) ? twin : item;
7223
- if (isRecord$4$1(item) && isRecord$4$1(twin)) return inArrayRow(pass, item, twin);
7226
+ if (isRecord$5(item) && isRecord$5(twin)) return inArrayRow(pass, item, twin);
7224
7227
  if (Array.isArray(item) && Array.isArray(twin)) return inArray(pass, item, twin);
7225
7228
  return item;
7226
7229
  });
@@ -7231,7 +7234,7 @@ function inArrayRow(pass, incoming, stored) {
7231
7234
  const twin = stored[key];
7232
7235
  if (isSecretMarker(twin)) {
7233
7236
  if (typeof value === "string" && value === resolvedValue(pass, twin)) out[key] = twin;
7234
- } else if (isRecord$4$1(value) && isRecord$4$1(twin)) out[key] = inArrayRow(pass, value, twin);
7237
+ } else if (isRecord$5(value) && isRecord$5(twin)) out[key] = inArrayRow(pass, value, twin);
7235
7238
  else if (Array.isArray(value) && Array.isArray(twin)) out[key] = inArray(pass, value, twin);
7236
7239
  }
7237
7240
  return out;
@@ -7239,7 +7242,7 @@ function inArrayRow(pass, incoming, stored) {
7239
7242
  async function walk(pass, incoming, stored) {
7240
7243
  if (isSecretMarker(stored)) return atMarker(pass, incoming, stored);
7241
7244
  if (Array.isArray(incoming) && Array.isArray(stored)) return inArray(pass, incoming, stored);
7242
- if (!isRecord$4$1(incoming) || !isRecord$4$1(stored)) return incoming;
7245
+ if (!isRecord$5(incoming) || !isRecord$5(stored)) return incoming;
7243
7246
  const out = { ...incoming };
7244
7247
  for (const [key, value] of Object.entries(incoming)) out[key] = await walk(pass, value, stored[key]);
7245
7248
  return out;
@@ -7270,7 +7273,7 @@ async function restoreUnchangedSecrets(input) {
7270
7273
  function isJsonEqual(a, b) {
7271
7274
  if (Object.is(a, b)) return true;
7272
7275
  if (Array.isArray(a)) return Array.isArray(b) && a.length === b.length && a.every((v, i) => isJsonEqual(v, b[i]));
7273
- if (isRecord$4$1(a) && isRecord$4$1(b)) {
7276
+ if (isRecord$5(a) && isRecord$5(b)) {
7274
7277
  const keys = Object.keys(a);
7275
7278
  if (keys.length !== Object.keys(b).length) return false;
7276
7279
  return keys.every((k) => Object.prototype.hasOwnProperty.call(b, k) && isJsonEqual(a[k], b[k]));
@@ -7294,7 +7297,7 @@ function markerKeysOf(blob, owner) {
7294
7297
  }
7295
7298
  function nodeFromStored(value, owner) {
7296
7299
  if (isSecretMarker(value)) return isSecretRefOwnedBy(value.$secret, owner) ? { kind: "leaf" } : null;
7297
- if (!isRecord$4$1(value)) return null;
7300
+ if (!isRecord$5(value)) return null;
7298
7301
  const children = /* @__PURE__ */ new Map();
7299
7302
  for (const [key, child] of Object.entries(value)) {
7300
7303
  const node = nodeFromStored(child, owner);
@@ -7913,6 +7916,44 @@ var BaseAddon = class {
7913
7916
  return null;
7914
7917
  }
7915
7918
  /**
7919
+ * D986 scoped settings: the form shape of the CLUSTER-wide settings one capability this addon
7920
+ * provides owns, or `null` when it has none. `cap` is a capability name the addon's manifest
7921
+ * declares. Stored as `addon-settings` rows `<addonId>.<field>`. The keys of this schema, of
7922
+ * {@link nodeSettingsSchema} and of {@link deviceDefaultsSchema} are disjoint, and a key never
7923
+ * contains `@` (guard `check-scoped-settings-declared`). SHAPE only: values are read by scope.
7924
+ */
7925
+ async clusterSettingsSchema(_cap) {
7926
+ return null;
7927
+ }
7928
+ /**
7929
+ * D986: the form shape of the settings one capability owns PER NODE, or `null`. Stored as
7930
+ * `addon-settings` rows `<addonId>.<field>@<nodeId>` carrying `nodeId` in the row data, so a
7931
+ * forgotten node's rows go in one central delete.
7932
+ */
7933
+ async nodeSettingsSchema(_cap) {
7934
+ return null;
7935
+ }
7936
+ /**
7937
+ * D986: the form shape of the FLEET DEFAULTS of the per-device settings one capability owns,
7938
+ * or `null`. Stored as `addon-settings` rows `<addonId>.<field>`; a device resolves its value
7939
+ * as device row, then this default, then the schema default (`resolveDeviceSettings`).
7940
+ */
7941
+ async deviceDefaultsSchema(_cap) {
7942
+ return null;
7943
+ }
7944
+ /**
7945
+ * The host's read of the scoped declarations: the schema one capability declares for `scope`,
7946
+ * or `null`. Beside {@link getIntegrationFormSchema}, the same shape: the hook is protected, the
7947
+ * host asks this method.
7948
+ */
7949
+ async getScopedSettingsSchema(scope, cap) {
7950
+ switch (scope) {
7951
+ case "cluster": return this.clusterSettingsSchema(cap);
7952
+ case "node": return this.nodeSettingsSchema(cap);
7953
+ case "device-defaults": return this.deviceDefaultsSchema(cap);
7954
+ }
7955
+ }
7956
+ /**
7916
7957
  * What the create wizard and the integration edit page render for one instance: the addon's
7917
7958
  * per-instance schema when it declares one, else its global schema (what they always showed).
7918
7959
  */
@@ -8706,47 +8747,6 @@ function normalizeAddonInitResult(result) {
8706
8747
  if (Array.isArray(result)) return { providers: result };
8707
8748
  return result;
8708
8749
  }
8709
- /**
8710
- * The share-view scope kinds a share-link token can carry. The hub mints
8711
- * and validates them (`ShareViewGrantSchema` builds its
8712
- * enum from this list); a data plane names the kinds it ACCEPTS in `share`.
8713
- */
8714
- var SHARE_VIEW_KINDS = ["grid-view", "events-view"];
8715
- /** The wire shape of {@link PeerBytesTicket} — see the type for what it is. */
8716
- var PeerBytesTicketSchema = object({
8717
- /** `http://127.0.0.1:<port>/<token>`. One `GET` takes it. */
8718
- url: string().min(1),
8719
- /**
8720
- * The HOST node this URL means something on — the hub or a named agent,
8721
- * never a runner. {@link AddonPeerBytes.open} compares it to its own and
8722
- * refuses `cross-node` by name when they differ, without dialling.
8723
- */
8724
- hostNodeId: string().min(1),
8725
- expiresAtMs: number$1().int().nonnegative(),
8726
- /**
8727
- * What the producer DECLARED the body to be, when it knows — `null` when it
8728
- * does not. Never `0` for unknown (D393): a consumer sizing a bound off this
8729
- * must be able to tell "the producer did not say" from "the body is empty".
8730
- */
8731
- declaredBytes: number$1().int().nonnegative().nullable()
8732
- });
8733
- /** Limits and names of `ctx.records` (D881). One authority; the engine and the facade read it. */
8734
- /** The files a kind may live in. `history` is device-history's (D850), never records. */
8735
- var RECORD_DATABASES = ["settings", "events"];
8736
- /** The classes of a kind: the `@durable` vocabulary, one authority (replaces the annotation). */
8737
- var RECORD_CLASSES = [
8738
- "config",
8739
- "ledger",
8740
- "audit",
8741
- "mirror",
8742
- "ephemeral"
8743
- ];
8744
- var RECORD_DEFAULT_MAX_DATA_BYTES = 64 * 1024;
8745
- var RECORD_MAX_DATA_BYTES = 1024 * 1024;
8746
- var RECORD_BATCH_MAX = 1e3;
8747
- var RECORD_QUERY_MAX = 1e3;
8748
- /** A kind in the `settings` file may not bound itself above this (D447: high volume is `events`). */
8749
- var RECORD_SETTINGS_MAX_ROWS = 5e4;
8750
8750
  var PREFIX = "records/";
8751
8751
  /** The base of every records failure. `detail` is the human part of the message. */
8752
8752
  var RecordsError = class extends Error {
@@ -8779,6 +8779,83 @@ var DeclarationRefusedError = class extends RecordsError {
8779
8779
  this.name = "DeclarationRefusedError";
8780
8780
  }
8781
8781
  };
8782
+ /** Limits and names of `ctx.records` (D881). One authority; the engine and the facade read it. */
8783
+ /** The files a kind may live in. `history` is device-history's (D850), never records. */
8784
+ var RECORD_DATABASES = ["settings", "events"];
8785
+ /** The classes of a kind: the `@durable` vocabulary, one authority (replaces the annotation). */
8786
+ var RECORD_CLASSES = [
8787
+ "config",
8788
+ "ledger",
8789
+ "audit",
8790
+ "mirror",
8791
+ "ephemeral"
8792
+ ];
8793
+ var RECORD_DEFAULT_MAX_DATA_BYTES = 64 * 1024;
8794
+ var RECORD_MAX_DATA_BYTES = 1024 * 1024;
8795
+ var RECORD_BATCH_MAX = 1e3;
8796
+ var RECORD_QUERY_MAX = 1e3;
8797
+ /** A kind in the `settings` file may not bound itself above this (D447: high volume is `events`). */
8798
+ var RECORD_SETTINGS_MAX_ROWS = 5e4;
8799
+ /**
8800
+ * Secret fields of a record, addressed the way a Zod schema declares them
8801
+ * (`collectZodSecretPaths`): dotted keys, `[]` for "each element of this array"
8802
+ * (`auth.accessToken`, `headers[].value`).
8803
+ *
8804
+ * Array elements are matched by a DECLARED id key (`secretArrayKeys`:
8805
+ * `{ headers: 'name' }`), never by index, so reordering a list keeps every
8806
+ * keychain ref (the same rule as `arrayItemFieldPath`). The concrete path of a
8807
+ * leaf names its element: `headers[X-Api].value`.
8808
+ *
8809
+ * Pure and browser-safe. Nothing here mutates: every transform returns a new value.
8810
+ */
8811
+ /** The array prefixes (declared form, e.g. `headers` or `a.headers`) of a path. */
8812
+ function parseSecretPath(path) {
8813
+ if (path.length === 0) throw new InvalidRecordError("an empty secret path");
8814
+ return path.split(".").map((raw) => {
8815
+ const each = raw.endsWith("[]");
8816
+ const key = each ? raw.slice(0, -2) : raw;
8817
+ if (key.length === 0) throw new InvalidRecordError(`secret path "${path}" has an empty segment`);
8818
+ return {
8819
+ key,
8820
+ each
8821
+ };
8822
+ });
8823
+ }
8824
+ /** The declared array prefixes of `path` that need an id key (`headers`, `a.rows`). */
8825
+ function secretArrayPrefixes(path) {
8826
+ const segments = parseSecretPath(path);
8827
+ const prefixes = [];
8828
+ const walked = [];
8829
+ for (const segment of segments) {
8830
+ walked.push(segment.key);
8831
+ if (segment.each) prefixes.push(walked.join("."));
8832
+ }
8833
+ return prefixes;
8834
+ }
8835
+ /**
8836
+ * The share-view scope kinds a share-link token can carry. The hub mints
8837
+ * and validates them (`ShareViewGrantSchema` builds its
8838
+ * enum from this list); a data plane names the kinds it ACCEPTS in `share`.
8839
+ */
8840
+ var SHARE_VIEW_KINDS = ["grid-view", "events-view"];
8841
+ /** The wire shape of {@link PeerBytesTicket} — see the type for what it is. */
8842
+ var PeerBytesTicketSchema = object({
8843
+ /** `http://127.0.0.1:<port>/<token>`. One `GET` takes it. */
8844
+ url: string().min(1),
8845
+ /**
8846
+ * The HOST node this URL means something on — the hub or a named agent,
8847
+ * never a runner. {@link AddonPeerBytes.open} compares it to its own and
8848
+ * refuses `cross-node` by name when they differ, without dialling.
8849
+ */
8850
+ hostNodeId: string().min(1),
8851
+ expiresAtMs: number$1().int().nonnegative(),
8852
+ /**
8853
+ * What the producer DECLARED the body to be, when it knows — `null` when it
8854
+ * does not. Never `0` for unknown (D393): a consumer sizing a bound off this
8855
+ * must be able to tell "the producer did not say" from "the body is empty".
8856
+ */
8857
+ declaredBytes: number$1().int().nonnegative().nullable()
8858
+ });
8782
8859
  function defOf(schema) {
8783
8860
  const zodBag = Reflect.get(schema, "_zod");
8784
8861
  if (typeof zodBag !== "object" || zodBag === null) return {};
@@ -8847,42 +8924,6 @@ function collectZodSecretPaths(schema, prefix = "") {
8847
8924
  return [...new Set(paths)];
8848
8925
  }
8849
8926
  /**
8850
- * Secret fields of a record, addressed the way a Zod schema declares them
8851
- * (`collectZodSecretPaths`): dotted keys, `[]` for "each element of this array"
8852
- * (`auth.accessToken`, `headers[].value`).
8853
- *
8854
- * Array elements are matched by a DECLARED id key (`secretArrayKeys`:
8855
- * `{ headers: 'name' }`), never by index, so reordering a list keeps every
8856
- * keychain ref (the same rule as `arrayItemFieldPath`). The concrete path of a
8857
- * leaf names its element: `headers[X-Api].value`.
8858
- *
8859
- * Pure and browser-safe. Nothing here mutates: every transform returns a new value.
8860
- */
8861
- /** The array prefixes (declared form, e.g. `headers` or `a.headers`) of a path. */
8862
- function parseSecretPath(path) {
8863
- if (path.length === 0) throw new InvalidRecordError("an empty secret path");
8864
- return path.split(".").map((raw) => {
8865
- const each = raw.endsWith("[]");
8866
- const key = each ? raw.slice(0, -2) : raw;
8867
- if (key.length === 0) throw new InvalidRecordError(`secret path "${path}" has an empty segment`);
8868
- return {
8869
- key,
8870
- each
8871
- };
8872
- });
8873
- }
8874
- /** The declared array prefixes of `path` that need an id key (`headers`, `a.rows`). */
8875
- function secretArrayPrefixes(path) {
8876
- const segments = parseSecretPath(path);
8877
- const prefixes = [];
8878
- const walked = [];
8879
- for (const segment of segments) {
8880
- walked.push(segment.key);
8881
- if (segment.each) prefixes.push(walked.join("."));
8882
- }
8883
- return prefixes;
8884
- }
8885
- /**
8886
8927
  * Record kinds (D881): the declaration an addon makes of one kind of fact, the
8887
8928
  * Zod row schema that describes it, and the helper that turns the two into the
8888
8929
  * JSON the engine stores.
@@ -9722,6 +9763,7 @@ var CAP_NAMES = Object.freeze([
9722
9763
  "backup",
9723
9764
  "battery",
9724
9765
  "binary",
9766
+ "board-key-source",
9725
9767
  "brightness",
9726
9768
  "broker",
9727
9769
  "button",
@@ -9785,6 +9827,7 @@ var CAP_NAMES = Object.freeze([
9785
9827
  "humidity-sensor",
9786
9828
  "image",
9787
9829
  "image-settings",
9830
+ "integration-instances",
9788
9831
  "integrations",
9789
9832
  "intercom",
9790
9833
  "ir-transmitter",
@@ -9842,6 +9885,7 @@ var CAP_NAMES = Object.freeze([
9842
9885
  "privacy-mask",
9843
9886
  "ptz",
9844
9887
  "ptz-autotrack",
9888
+ "pump-cycle",
9845
9889
  "reboot",
9846
9890
  "record-entries",
9847
9891
  "recording",
@@ -11134,18 +11178,6 @@ Object.freeze({
11134
11178
  "path": "pumpRunning",
11135
11179
  "valueType": "boolean"
11136
11180
  },
11137
- {
11138
- "path": "pumpIntervalEnabled",
11139
- "valueType": "boolean"
11140
- },
11141
- {
11142
- "path": "pumpOnTime",
11143
- "valueType": "number"
11144
- },
11145
- {
11146
- "path": "pumpOffTime",
11147
- "valueType": "number"
11148
- },
11149
11181
  {
11150
11182
  "path": "lastDrink",
11151
11183
  "valueType": "number"
@@ -11269,6 +11301,20 @@ Object.freeze({
11269
11301
  "valueType": "number"
11270
11302
  }
11271
11303
  ],
11304
+ "pump-cycle": [
11305
+ {
11306
+ "path": "enabled",
11307
+ "valueType": "boolean"
11308
+ },
11309
+ {
11310
+ "path": "onTime",
11311
+ "valueType": "number"
11312
+ },
11313
+ {
11314
+ "path": "offTime",
11315
+ "valueType": "number"
11316
+ }
11317
+ ],
11272
11318
  "recording-archive": [
11273
11319
  {
11274
11320
  "path": "deviceId",
@@ -11718,7 +11764,7 @@ object({
11718
11764
  params: record(string(), union([string(), number$1()])).optional()
11719
11765
  });
11720
11766
  //#endregion
11721
- //#region ../types/dist/composition-kKKOdFIG.mjs
11767
+ //#region ../types/dist/composition-Dh3RfMx5.mjs
11722
11768
  /**
11723
11769
  * The ffmpeg build every CamStack node downloads, per platform and arch.
11724
11770
  *
@@ -12932,6 +12978,73 @@ var NodeColorIdSchema = _enum([
12932
12978
  "node-g",
12933
12979
  "node-h"
12934
12980
  ]);
12981
+ //#endregion
12982
+ //#region ../types/dist/index.mjs
12983
+ var SMTP_INBOUND_DEFAULT_PORT = 2525;
12984
+ var SMTP_INBOUND_DEFAULT_DOMAIN = "camstack.local";
12985
+ var SMTP_INBOUND_DEFAULT_MAX_MESSAGE_BYTES = 25 * 1024 * 1024;
12986
+ /** The text excerpt a message carries on the bus. */
12987
+ var SMTP_INBOUND_TEXT_MAX_CHARS = 4096;
12988
+ var PortSchema = number$1().int().min(1).max(65535);
12989
+ /** A recipient local-part: what stands before the `@`. */
12990
+ var SmtpRecipientSchema = string().min(1).max(64).regex(/^[A-Za-z0-9._+-]+$/);
12991
+ object({
12992
+ port: PortSchema.default(SMTP_INBOUND_DEFAULT_PORT),
12993
+ bindHost: string().min(1).default("0.0.0.0"),
12994
+ domain: string().min(1).default(SMTP_INBOUND_DEFAULT_DOMAIN),
12995
+ requireAuth: boolean().default(true),
12996
+ username: string().default(""),
12997
+ password: string().default("").meta({ secret: true }),
12998
+ starttls: boolean().default(false),
12999
+ maxMessageBytes: number$1().int().positive().default(SMTP_INBOUND_DEFAULT_MAX_MESSAGE_BYTES)
13000
+ });
13001
+ object({
13002
+ host: string().min(1).nullable(),
13003
+ hostReason: string().nullable(),
13004
+ port: PortSchema,
13005
+ domain: string().min(1),
13006
+ requireAuth: boolean(),
13007
+ username: string(),
13008
+ password: string(),
13009
+ starttls: boolean()
13010
+ });
13011
+ object({
13012
+ recipients: array(SmtpRecipientSchema).min(1),
13013
+ /**
13014
+ * Who is subscribing. A second `subscribe` with the same id REPLACES that subscriber's
13015
+ * recipients (the way a consumer that restarted, or lost a device, declares its set again);
13016
+ * a recipient held by another subscriber is refused with `smtp-inbound/recipient-claimed`.
13017
+ * Absent, the subscriber is anonymous and unique.
13018
+ */
13019
+ subscriberId: string().min(1).max(64).optional()
13020
+ });
13021
+ var SmtpInboundAttachmentSchema = object({
13022
+ filename: string(),
13023
+ contentType: string(),
13024
+ bytes: number$1().int().nonnegative()
13025
+ });
13026
+ /** The payload of one `broker.message` (the key is the recipient local-part). */
13027
+ var SmtpInboundMessageSchema = object({
13028
+ /** Monotonic per mailbox; a gap tells a consumer it missed an event. */
13029
+ seq: number$1().int().positive(),
13030
+ messageId: string(),
13031
+ receivedAt: number$1().int().nonnegative(),
13032
+ from: string(),
13033
+ to: string(),
13034
+ subject: string(),
13035
+ text: string().max(SMTP_INBOUND_TEXT_MAX_CHARS),
13036
+ attachments: array(SmtpInboundAttachmentSchema)
13037
+ });
13038
+ object({
13039
+ /** The newest seq issued so far (0 before any mail). */
13040
+ lastSeq: number$1().int().nonnegative(),
13041
+ /** The oldest seq still retained; messages below it are gone. */
13042
+ oldestSeq: number$1().int().nonnegative(),
13043
+ messages: array(object({
13044
+ key: string(),
13045
+ message: SmtpInboundMessageSchema
13046
+ }))
13047
+ });
12935
13048
  new Set([
12936
13049
  "track",
12937
13050
  "face",
@@ -16091,8 +16204,18 @@ var LogChannelDescriptorSchema = object({
16091
16204
  * the operator narrows to one camera, sees nothing, and concludes the code
16092
16205
  * path was never taken.
16093
16206
  */
16094
- perDevice: boolean()
16095
- });
16207
+ perDevice: boolean(),
16208
+ /**
16209
+ * What the channel is FOR, so the UI can list the channels an addon offers.
16210
+ *
16211
+ * - `diagnostic` (the default): a per-component diagnostic armed from the
16212
+ * Levels page, emitted at its declared level.
16213
+ * - `debug`: a `debug.<channel>` dump watched live for a short window
16214
+ * (`ctx.debug`). Always per-device, and its lines are denied by the log
16215
+ * ring unless somebody is watching that device.
16216
+ */
16217
+ kind: _enum(["diagnostic", "debug"]).default("diagnostic")
16218
+ }).refine((d) => d.kind !== "debug" || d.name.startsWith("debug.") && d.perDevice, { message: "a debug channel is named debug.<channel> and is per-device" });
16096
16219
  /**
16097
16220
  * An armed window over one channel, as the document hands it to a mirror.
16098
16221
  *
@@ -19310,56 +19433,6 @@ var APPLIANCE_CAP_VOCABULARY = {
19310
19433
  icon: "square",
19311
19434
  args: { on: false }
19312
19435
  },
19313
- {
19314
- id: "petFountain.intervalOn",
19315
- method: "setPumpInterval",
19316
- label: t("Pump cycle on", "Ciclo pompa attivo"),
19317
- phrase: t("Run the pump of {device} on its on/off cycle", "Fai lavorare la pompa di {device} a ciclo acceso/spento"),
19318
- icon: "timer",
19319
- args: { on: true }
19320
- },
19321
- {
19322
- id: "petFountain.intervalOff",
19323
- method: "setPumpInterval",
19324
- label: t("Pump cycle off", "Ciclo pompa spento"),
19325
- phrase: t("Run the pump of {device} continuously", "Fai lavorare la pompa di {device} in continuo"),
19326
- icon: "timer-off",
19327
- args: { on: false }
19328
- },
19329
- {
19330
- id: "petFountain.pumpOnMinutes",
19331
- method: "setPumpOnMinutes",
19332
- label: t("Set pump run time", "Imposta il tempo di lavoro della pompa"),
19333
- phrase: t("Set the pump of {device} to run {minutes} minutes per cycle", "Imposta la pompa di {device} a lavorare {minutes} minuti per ciclo"),
19334
- icon: "timer",
19335
- openArgs: [{
19336
- key: "minutes",
19337
- label: t("Minutes", "Minuti"),
19338
- offer: {
19339
- kind: "number",
19340
- min: 0,
19341
- step: 1,
19342
- unit: "min"
19343
- }
19344
- }]
19345
- },
19346
- {
19347
- id: "petFountain.pumpOffMinutes",
19348
- method: "setPumpOffMinutes",
19349
- label: t("Set pump rest time", "Imposta il tempo di riposo della pompa"),
19350
- phrase: t("Set the pump of {device} to rest {minutes} minutes per cycle", "Imposta la pompa di {device} a riposare {minutes} minuti per ciclo"),
19351
- icon: "timer-off",
19352
- openArgs: [{
19353
- key: "minutes",
19354
- label: t("Minutes", "Minuti"),
19355
- offer: {
19356
- kind: "number",
19357
- min: 0,
19358
- step: 1,
19359
- unit: "min"
19360
- }
19361
- }]
19362
- },
19363
19436
  {
19364
19437
  id: "petFountain.resetDailyConsumption",
19365
19438
  method: "resetDailyConsumption",
@@ -19384,6 +19457,70 @@ var APPLIANCE_CAP_VOCABULARY = {
19384
19457
  icon: "droplets"
19385
19458
  }]
19386
19459
  },
19460
+ "pump-cycle": {
19461
+ scope: "device",
19462
+ noun: t("Pump cycle", "Ciclo della pompa"),
19463
+ actions: [
19464
+ {
19465
+ id: "pumpCycle.on",
19466
+ method: "setEnabled",
19467
+ label: t("Pump cycle on", "Ciclo pompa attivo"),
19468
+ phrase: t("Run the pump of {device} on its on/off cycle", "Fai lavorare la pompa di {device} a ciclo acceso/spento"),
19469
+ icon: "timer",
19470
+ args: { on: true }
19471
+ },
19472
+ {
19473
+ id: "pumpCycle.off",
19474
+ method: "setEnabled",
19475
+ label: t("Pump cycle off", "Ciclo pompa spento"),
19476
+ phrase: t("Run the pump of {device} continuously", "Fai lavorare la pompa di {device} in continuo"),
19477
+ icon: "timer-off",
19478
+ args: { on: false }
19479
+ },
19480
+ {
19481
+ id: "pumpCycle.onMinutes",
19482
+ method: "setOnMinutes",
19483
+ label: t("Set pump run time", "Imposta il tempo di lavoro della pompa"),
19484
+ phrase: t("Set the pump of {device} to run {minutes} minutes per cycle", "Imposta la pompa di {device} a lavorare {minutes} minuti per ciclo"),
19485
+ icon: "timer",
19486
+ openArgs: [{
19487
+ key: "minutes",
19488
+ label: t("Minutes", "Minuti"),
19489
+ offer: {
19490
+ kind: "number",
19491
+ min: 0,
19492
+ step: 1,
19493
+ unit: "min"
19494
+ }
19495
+ }]
19496
+ },
19497
+ {
19498
+ id: "pumpCycle.offMinutes",
19499
+ method: "setOffMinutes",
19500
+ label: t("Set pump rest time", "Imposta il tempo di riposo della pompa"),
19501
+ phrase: t("Set the pump of {device} to rest {minutes} minutes per cycle", "Imposta la pompa di {device} a riposare {minutes} minuti per ciclo"),
19502
+ icon: "timer-off",
19503
+ openArgs: [{
19504
+ key: "minutes",
19505
+ label: t("Minutes", "Minuti"),
19506
+ offer: {
19507
+ kind: "number",
19508
+ min: 0,
19509
+ step: 1,
19510
+ unit: "min"
19511
+ }
19512
+ }]
19513
+ }
19514
+ ],
19515
+ state: [{
19516
+ kind: "boolean",
19517
+ field: "enabled",
19518
+ label: t("Pump cycle", "Ciclo pompa"),
19519
+ whenTrue: t("When {device} starts running its pump on a cycle", "Quando {device} inizia a far lavorare la pompa a ciclo"),
19520
+ whenFalse: t("When {device} runs its pump continuously", "Quando {device} fa lavorare la pompa in continuo"),
19521
+ icon: "timer"
19522
+ }]
19523
+ },
19387
19524
  "media-player": {
19388
19525
  scope: "device",
19389
19526
  noun: t("Media player", "Lettore multimediale"),
@@ -21274,6 +21411,7 @@ var SYSTEM_CAP_VOCABULARY = {
21274
21411
  "audio-analyzer": system(PIPELINE),
21275
21412
  "audio-codec": system(INTERNAL),
21276
21413
  "auth-provider": system(IDENTITY),
21414
+ "board-key-source": system(INTERNAL),
21277
21415
  backup: system("system backups — run and restored from the Backups page"),
21278
21416
  broker: system("message-broker connections — configured, not actuated"),
21279
21417
  "calendar-source": system(INTERNAL),
@@ -21308,6 +21446,7 @@ var SYSTEM_CAP_VOCABULARY = {
21308
21446
  "load-contribution": system(INTERNAL),
21309
21447
  "local-network": system(NETWORK),
21310
21448
  "log-channels": system(INTERNAL),
21449
+ "integration-instances": system(INTERNAL),
21311
21450
  "log-destination": system(INTERNAL),
21312
21451
  "login-method": system(IDENTITY),
21313
21452
  "mesh-network": system(NETWORK),
@@ -43514,7 +43653,7 @@ var TargetKindCapsSchema = object({
43514
43653
  * the union is large and not meant for runtime validation here; the exported
43515
43654
  * `TargetKind` type re-tightens `configSchema` to `ConfigUISchema`.
43516
43655
  */
43517
- var ConfigSchemaPassthrough$3 = unknown();
43656
+ var ConfigSchemaPassthrough$4 = unknown();
43518
43657
  var TargetKindSchema = object({
43519
43658
  kind: string(),
43520
43659
  label: string(),
@@ -43551,7 +43690,7 @@ var TargetKindSchema = object({
43551
43690
  * its raster path, which is the safe default for an unknown image.
43552
43691
  */
43553
43692
  iconMediaType: string().optional(),
43554
- configSchema: ConfigSchemaPassthrough$3,
43693
+ configSchema: ConfigSchemaPassthrough$4,
43555
43694
  /**
43556
43695
  * The config keys that decide WHERE this kind's secrets are sent (server,
43557
43696
  * base URL, instance, chat, recipient). A save that changes any of them
@@ -46223,6 +46362,49 @@ var binaryCapability = {
46223
46362
  volatileStateFields: ["lastChangedAt"]
46224
46363
  };
46225
46364
  /**
46365
+ * Why a board key could not be read. Typed so a caller reports the cause and
46366
+ * never treats "could not read" as "has no key" (D49).
46367
+ */
46368
+ var BoardKeyFailureReasonSchema = _enum([
46369
+ "unknown-source",
46370
+ "not-admin",
46371
+ "no-builder",
46372
+ "no-ingress-url",
46373
+ "unreachable",
46374
+ "unknown-board",
46375
+ "no-encryption-key",
46376
+ "unreadable-config"
46377
+ ]);
46378
+ var BoardKeySourceSchema = object({
46379
+ sourceId: string(),
46380
+ name: string()
46381
+ });
46382
+ var BoardKeyBoardSchema = object({
46383
+ /** The builder's file name, e.g. `kitchen.yaml`: the handle `getBoardKey` takes. */
46384
+ configuration: string(),
46385
+ /** The node name the builder gives the board. */
46386
+ name: string(),
46387
+ /** The address the builder knows the board by, when it has one. */
46388
+ address: string().nullable()
46389
+ });
46390
+ var BoardKeyFailureSchema = object({
46391
+ ok: literal(false),
46392
+ reason: BoardKeyFailureReasonSchema,
46393
+ detail: string().optional()
46394
+ });
46395
+ var ListBoardsResultSchema = discriminatedUnion("ok", [object({
46396
+ ok: literal(true),
46397
+ boards: array(BoardKeyBoardSchema).readonly()
46398
+ }), BoardKeyFailureSchema]);
46399
+ var GetBoardKeyResultSchema = discriminatedUnion("ok", [object({
46400
+ ok: literal(true),
46401
+ key: string()
46402
+ }), BoardKeyFailureSchema]);
46403
+ method(_void(), array(BoardKeySourceSchema).readonly(), { auth: "admin" }), method(object({ sourceId: string().min(1) }), ListBoardsResultSchema, { auth: "admin" }), method(object({
46404
+ sourceId: string().min(1),
46405
+ configuration: string().min(1)
46406
+ }), GetBoardKeyResultSchema, { auth: "admin" });
46407
+ /**
46226
46408
  * Dimmable-light brightness control. Co-exists with `switch` on the
46227
46409
  * same device — the switch toggles on/off, this cap sets the level
46228
46410
  * applied when the light is on. Drivers map their per-vendor dim
@@ -51256,6 +51438,45 @@ var deviceProviderCapability = {
51256
51438
  }
51257
51439
  };
51258
51440
  /**
51441
+ * What the passive listener of `local-network` saw on the wire, before any
51442
+ * provider classified it. Device-manager turns an observation into the hits
51443
+ * of the providers whose declared discovery modes it matches.
51444
+ */
51445
+ var DiscoveryObservationSchema = discriminatedUnion("kind", [object({
51446
+ kind: literal("mdns"),
51447
+ /** Normalised DNS-SD service type, e.g. `_esphomelib._tcp`. */
51448
+ serviceType: string(),
51449
+ instance: string(),
51450
+ host: string(),
51451
+ /** The A record address when the announcement carried one. */
51452
+ address: string().nullable(),
51453
+ port: number$1().int(),
51454
+ txt: record(string(), string())
51455
+ }), object({
51456
+ kind: literal("ssdp"),
51457
+ /** Sender address of the datagram. */
51458
+ host: string(),
51459
+ port: number$1().int(),
51460
+ /** `NT` of a NOTIFY, `ST` of a search response. */
51461
+ target: string(),
51462
+ headers: record(string(), string())
51463
+ })]);
51464
+ object({
51465
+ addonId: string(),
51466
+ candidate: DiscoveryCandidateSchema,
51467
+ firstSeenAt: number$1(),
51468
+ lastSeenAt: number$1(),
51469
+ dismissed: boolean()
51470
+ });
51471
+ var DiscoveryProposalSchema = object({
51472
+ id: string(),
51473
+ addonId: string(),
51474
+ candidate: DiscoveryCandidateSchema,
51475
+ firstSeenAt: number$1(),
51476
+ lastSeenAt: number$1(),
51477
+ dismissed: boolean()
51478
+ });
51479
+ /**
51259
51480
  * Device Manager capability — hub-side singleton that unifies device persistence,
51260
51481
  * live registry access, and all management operations into a single tRPC surface.
51261
51482
  *
@@ -51984,6 +52205,19 @@ method(object({
51984
52205
  }), object({ candidates: array(DiscoveryCandidateSchema).readonly() }), {
51985
52206
  kind: "mutation",
51986
52207
  auth: "admin"
52208
+ }), method(object({}), object({ proposals: array(DiscoveryProposalSchema).readonly() }), { auth: "admin" }), method(object({ id: string() }), object({ dismissed: boolean() }), {
52209
+ kind: "mutation",
52210
+ auth: "admin"
52211
+ }), method(object({ observations: array(DiscoveryObservationSchema).max(512) }), object({ proposed: number$1().int() }), {
52212
+ kind: "mutation",
52213
+ auth: "admin"
52214
+ }), method(object({}), object({
52215
+ providers: number$1().int(),
52216
+ proposed: number$1().int()
52217
+ }), {
52218
+ kind: "mutation",
52219
+ auth: "admin",
52220
+ timeoutMs: 12e4
51987
52221
  }), method(object({ addonId: string() }), object({ deviceType: _enum(DeviceType).nullable() }), { auth: "admin" }), method(object({ addonId: string() }), unknown(), { auth: "admin" }), method(object({
51988
52222
  deviceId: number$1(),
51989
52223
  key: string(),
@@ -52840,7 +53074,7 @@ var DishwasherStatusSchema = object({
52840
53074
  /** Ms epoch of the last value received from the appliance; 0 = never. */
52841
53075
  lastFetchedAt: number$1()
52842
53076
  });
52843
- var DeviceIdSchema$1 = number$1().int().nonnegative();
53077
+ var DeviceIdSchema$2 = number$1().int().nonnegative();
52844
53078
  /** A value a program option or setting can take. */
52845
53079
  var DishwasherValueSchema = union([
52846
53080
  boolean(),
@@ -52915,77 +53149,77 @@ var dishwasherCapability = {
52915
53149
  * option feature keys; each is checked against the program's constraints.
52916
53150
  */
52917
53151
  start: method(object({
52918
- deviceId: DeviceIdSchema$1,
53152
+ deviceId: DeviceIdSchema$2,
52919
53153
  program: string().min(1).optional(),
52920
53154
  options: record(string(), DishwasherValueSchema).optional()
52921
53155
  }), _void(), {
52922
53156
  kind: "mutation",
52923
53157
  auth: "protected"
52924
53158
  }),
52925
- pause: method(object({ deviceId: DeviceIdSchema$1 }), _void(), {
53159
+ pause: method(object({ deviceId: DeviceIdSchema$2 }), _void(), {
52926
53160
  kind: "mutation",
52927
53161
  auth: "protected"
52928
53162
  }),
52929
- resume: method(object({ deviceId: DeviceIdSchema$1 }), _void(), {
53163
+ resume: method(object({ deviceId: DeviceIdSchema$2 }), _void(), {
52930
53164
  kind: "mutation",
52931
53165
  auth: "protected"
52932
53166
  }),
52933
- stop: method(object({ deviceId: DeviceIdSchema$1 }), _void(), {
53167
+ stop: method(object({ deviceId: DeviceIdSchema$2 }), _void(), {
52934
53168
  kind: "mutation",
52935
53169
  auth: "protected"
52936
53170
  }),
52937
53171
  /** Select (not start) a program; refused when the appliance does not offer it. */
52938
53172
  setProgram: method(object({
52939
- deviceId: DeviceIdSchema$1,
53173
+ deviceId: DeviceIdSchema$2,
52940
53174
  program: string().min(1)
52941
53175
  }), _void(), {
52942
53176
  kind: "mutation",
52943
53177
  auth: "protected"
52944
53178
  }),
52945
53179
  setPower: method(object({
52946
- deviceId: DeviceIdSchema$1,
53180
+ deviceId: DeviceIdSchema$2,
52947
53181
  on: boolean()
52948
53182
  }), _void(), {
52949
53183
  kind: "mutation",
52950
53184
  auth: "protected"
52951
53185
  }),
52952
53186
  setHalfLoad: method(object({
52953
- deviceId: DeviceIdSchema$1,
53187
+ deviceId: DeviceIdSchema$2,
52954
53188
  on: boolean()
52955
53189
  }), _void(), {
52956
53190
  kind: "mutation",
52957
53191
  auth: "protected"
52958
53192
  }),
52959
53193
  setHygienePlus: method(object({
52960
- deviceId: DeviceIdSchema$1,
53194
+ deviceId: DeviceIdSchema$2,
52961
53195
  on: boolean()
52962
53196
  }), _void(), {
52963
53197
  kind: "mutation",
52964
53198
  auth: "protected"
52965
53199
  }),
52966
53200
  setExtraDry: method(object({
52967
- deviceId: DeviceIdSchema$1,
53201
+ deviceId: DeviceIdSchema$2,
52968
53202
  on: boolean()
52969
53203
  }), _void(), {
52970
53204
  kind: "mutation",
52971
53205
  auth: "protected"
52972
53206
  }),
52973
53207
  setIntensiveZone: method(object({
52974
- deviceId: DeviceIdSchema$1,
53208
+ deviceId: DeviceIdSchema$2,
52975
53209
  on: boolean()
52976
53210
  }), _void(), {
52977
53211
  kind: "mutation",
52978
53212
  auth: "protected"
52979
53213
  }),
52980
53214
  setVarioSpeedPlus: method(object({
52981
- deviceId: DeviceIdSchema$1,
53215
+ deviceId: DeviceIdSchema$2,
52982
53216
  on: boolean()
52983
53217
  }), _void(), {
52984
53218
  kind: "mutation",
52985
53219
  auth: "protected"
52986
53220
  }),
52987
53221
  setChildLock: method(object({
52988
- deviceId: DeviceIdSchema$1,
53222
+ deviceId: DeviceIdSchema$2,
52989
53223
  on: boolean()
52990
53224
  }), _void(), {
52991
53225
  kind: "mutation",
@@ -52997,7 +53231,7 @@ var dishwasherCapability = {
52997
53231
  * its declared range / members.
52998
53232
  */
52999
53233
  setOption: method(object({
53000
- deviceId: DeviceIdSchema$1,
53234
+ deviceId: DeviceIdSchema$2,
53001
53235
  key: string().min(1),
53002
53236
  value: DishwasherValueSchema
53003
53237
  }), _void(), {
@@ -53005,7 +53239,7 @@ var dishwasherCapability = {
53005
53239
  auth: "protected"
53006
53240
  }),
53007
53241
  /** What this appliance can do, from its own description — the UI is derived from it. */
53008
- getOptions: method(object({ deviceId: DeviceIdSchema$1 }), DishwasherOptionsSchema, { auth: "protected" })
53242
+ getOptions: method(object({ deviceId: DeviceIdSchema$2 }), DishwasherOptionsSchema, { auth: "protected" })
53009
53243
  },
53010
53244
  status: {
53011
53245
  schema: DishwasherStatusSchema,
@@ -55328,6 +55562,89 @@ method(_void(), array(IntegrationWithStateSchema)), method(object({ id: string()
55328
55562
  auth: "admin"
55329
55563
  });
55330
55564
  /**
55565
+ * `integration-instances` - the connection of an addon that holds ONE or SEVERAL
55566
+ * (an account, a relay, a destination) as typed records (D985, D986). The addon's
55567
+ * own function page reads and writes them (Logging for Loki); the Integrations
55568
+ * page lists only the integrations that bring devices (D996).
55569
+ *
55570
+ * A collection of providers: each addon that holds connections registers one and a
55571
+ * caller reaches a provider with the pinned `addonId`.
55572
+ *
55573
+ * Identity: the instance id is immutable and opaque to the caller. A record the
55574
+ * Loki migration made keeps the `integrations` registry id it was created under
55575
+ * (`int_NNNN`); a single instance made by its function page takes the addon id.
55576
+ * `name` is the editable label.
55577
+ *
55578
+ * Secrets: every field the instance kind marks `.meta({ secret: true })` reaches
55579
+ * the form as a `SecretFieldView`, never text (D789). A patch value omitted, `''`
55580
+ * or the redaction token KEEPS the stored secret; `{ $secretClear: true }`
55581
+ * clears it.
55582
+ */
55583
+ var ConfigSchemaPassthrough$3 = custom();
55584
+ var IntegrationInstanceIdSchema = string().min(1);
55585
+ var IntegrationInstanceDescriptionSchema = object({
55586
+ /** `single`: at most one instance can exist (Loki). `multiple`: an account each. */
55587
+ instanceMode: _enum(["single", "multiple"]),
55588
+ /** What the instance is, for the UI (`destination`, `relay`, `account`). */
55589
+ kind: string(),
55590
+ /** True when `testInstance` really probes the remote. */
55591
+ canTest: boolean()
55592
+ });
55593
+ var IntegrationInstanceStatusSchema = object({
55594
+ state: _enum([
55595
+ "ok",
55596
+ "off",
55597
+ "error",
55598
+ "unknown"
55599
+ ]),
55600
+ detail: string().optional()
55601
+ });
55602
+ var IntegrationInstanceSchema = object({
55603
+ id: IntegrationInstanceIdSchema,
55604
+ name: string(),
55605
+ /** The addon's own rule (an URL is present, a client id is present...). */
55606
+ configured: boolean(),
55607
+ /**
55608
+ * The instance's own on/off switch (D996): always present, derived from the record body
55609
+ * (`enabled !== false`, so a row written before the field existed is on).
55610
+ */
55611
+ enabled: boolean(),
55612
+ /** Values for the instance form; a secret is a `SecretFieldView`, never text. */
55613
+ formValues: record(string(), unknown()),
55614
+ status: IntegrationInstanceStatusSchema.optional()
55615
+ });
55616
+ var IntegrationInstancePatchSchema = object({
55617
+ id: IntegrationInstanceIdSchema,
55618
+ name: string().min(1).optional(),
55619
+ /** Omitted / '' / redaction token keeps a secret; `{ $secretClear: true }` clears it. */
55620
+ values: record(string(), unknown())
55621
+ });
55622
+ method(_void(), IntegrationInstanceDescriptionSchema, { auth: "admin" }), method(object({ id: IntegrationInstanceIdSchema.nullable() }), ConfigSchemaPassthrough$3, { auth: "admin" }), method(_void(), array(IntegrationInstanceSchema).readonly(), { auth: "admin" }), method(object({ id: IntegrationInstanceIdSchema }), IntegrationInstanceSchema.nullable(), { auth: "admin" }), method(object({
55623
+ id: IntegrationInstanceIdSchema,
55624
+ name: string().min(1)
55625
+ }), object({ id: string() }), {
55626
+ kind: "mutation",
55627
+ auth: "admin"
55628
+ }), method(IntegrationInstancePatchSchema, object({ ok: literal(true) }), {
55629
+ kind: "mutation",
55630
+ auth: "admin"
55631
+ }), method(object({
55632
+ id: IntegrationInstanceIdSchema,
55633
+ enabled: boolean()
55634
+ }), object({ ok: literal(true) }), {
55635
+ kind: "mutation",
55636
+ auth: "admin"
55637
+ }), method(object({ id: IntegrationInstanceIdSchema }), object({ ok: literal(true) }), {
55638
+ kind: "mutation",
55639
+ auth: "admin"
55640
+ }), optionalMethod(object({
55641
+ id: IntegrationInstanceIdSchema.nullable(),
55642
+ values: record(string(), unknown())
55643
+ }), TestConnectionResultSchema$1, {
55644
+ kind: "mutation",
55645
+ auth: "admin"
55646
+ });
55647
+ /**
55331
55648
  * Two-way audio / talk-back cap. Clients open a WebRTC audio-only
55332
55649
  * session (server-initiated offer pattern, identical to the main
55333
55650
  * video WebRTC flow) and the browser captures the mic; the server
@@ -66095,7 +66412,14 @@ var NcMediaPolicySchema = object({
66095
66412
  */
66096
66413
  profile: CamProfileSchema.optional(),
66097
66414
  /** See {@link NcLinkedCameraModeSchema}. */
66098
- linkedCameras: NcLinkedCameraModeSchema.optional()
66415
+ linkedCameras: NcLinkedCameraModeSchema.optional(),
66416
+ /**
66417
+ * Sensor rules only: may this rule wake a SLEEPING battery camera to take
66418
+ * the linked still it attaches (D998)? Absent means yes, an explicit `false`
66419
+ * opts out. Deliberately not a Zod default: a rule that never chose keeps
66420
+ * following the hub's. One bounded wake per event; nothing is attached later.
66421
+ */
66422
+ wakeSleepingCamera: boolean().optional()
66099
66423
  });
66100
66424
  /**
66101
66425
  * Cooldown GRANULARITY over the subject's class — how much a fired
@@ -68238,7 +68562,7 @@ var petFeederCapability = {
68238
68562
  /**
68239
68563
  * Pet water-fountain cap. Models the telemetry and the control surface of a
68240
68564
  * circulating drinking fountain: how much water is in the tank, how much the
68241
- * pet drank, whether the pump runs and on what duty cycle.
68565
+ * pet drank, whether the pump runs.
68242
68566
  *
68243
68567
  * It has no native vendor provider of its own: a fountain reaches CamStack as
68244
68568
  * a container of loose entities (a pump switch, two number boxes, a "filter
@@ -68254,8 +68578,10 @@ var petFeederCapability = {
68254
68578
  * never here. Every reading may be `null`: a source that is offline or does
68255
68579
  * not report is unknown, never zero.
68256
68580
  *
68257
- * The filter is not a field of this cap: it is an item of the `consumables`
68258
- * cap on the same device (kind `wear`), reset by the same forward mechanism.
68581
+ * The pump's on/off duty cycle is model-specific and lives in the optional
68582
+ * `pump-cycle` cap. The filter, the cleaning and the water change are not
68583
+ * fields of this cap: they are items of the `consumables` cap on the same
68584
+ * device (kind `wear`), reset by the same forward mechanism.
68259
68585
  */
68260
68586
  var PetFountainStatusSchema = object({
68261
68587
  /** Water in the tank, 0..100 (%). Null while the source has not reported. */
@@ -68266,27 +68592,20 @@ var PetFountainStatusSchema = object({
68266
68592
  empty: boolean().nullable(),
68267
68593
  /** True while the pump is running. Null while unknown. */
68268
68594
  pumpRunning: boolean().nullable(),
68269
- /** True when the pump works on an on/off duty cycle rather than continuously. */
68270
- pumpIntervalEnabled: boolean().nullable(),
68271
- /** How long the pump runs per cycle, in seconds. */
68272
- pumpOnTime: number$1().min(0).nullable().meta(readingMeta("duration")),
68273
- /** How long the pump rests per cycle, in seconds. */
68274
- pumpOffTime: number$1().min(0).nullable().meta(readingMeta("duration")),
68275
68595
  /** Water drunk in the last drink, in litres. */
68276
68596
  lastDrink: number$1().min(0).nullable().meta(readingMeta("volume")),
68277
68597
  /** Water drunk in the current hour, in litres. */
68278
68598
  currentHourDrink: number$1().min(0).nullable().meta(readingMeta("volume")),
68279
68599
  /** Water drunk over the last 24 hours (rolling), in litres. */
68280
68600
  last24hDrink: number$1().min(0).nullable().meta(readingMeta("volume")),
68281
- /** Water drunk since local midnight, in litres. */
68601
+ /** Water drunk since local midnight, in litres. Null when the fountain has no such sensor. */
68282
68602
  todayDrink: number$1().min(0).nullable().meta(readingMeta("volume")),
68283
68603
  /** Decoded fault message. Null means healthy; a non-null string is an active fault. */
68284
68604
  error: string().nullable(),
68285
68605
  /** Ms epoch when the slice was last refreshed. */
68286
68606
  lastFetchedAt: number$1()
68287
68607
  });
68288
- var DeviceIdSchema = number$1().int().nonnegative();
68289
- var MinutesSchema = number$1().int().min(0);
68608
+ var DeviceIdSchema$1 = number$1().int().nonnegative();
68290
68609
  var petFountainCapability = {
68291
68610
  name: "pet-fountain",
68292
68611
  scope: "device",
@@ -68296,38 +68615,14 @@ var petFountainCapability = {
68296
68615
  methods: {
68297
68616
  /** Start or stop the pump. */
68298
68617
  setPump: method(object({
68299
- deviceId: DeviceIdSchema,
68300
- on: boolean()
68301
- }), _void(), {
68302
- kind: "mutation",
68303
- auth: "protected"
68304
- }),
68305
- /** Switch the on/off duty cycle on or off (off = the pump runs continuously). */
68306
- setPumpInterval: method(object({
68307
- deviceId: DeviceIdSchema,
68618
+ deviceId: DeviceIdSchema$1,
68308
68619
  on: boolean()
68309
68620
  }), _void(), {
68310
68621
  kind: "mutation",
68311
68622
  auth: "protected"
68312
68623
  }),
68313
- /** Set how many minutes the pump runs per cycle. */
68314
- setPumpOnMinutes: method(object({
68315
- deviceId: DeviceIdSchema,
68316
- minutes: MinutesSchema
68317
- }), _void(), {
68318
- kind: "mutation",
68319
- auth: "protected"
68320
- }),
68321
- /** Set how many minutes the pump rests per cycle. */
68322
- setPumpOffMinutes: method(object({
68323
- deviceId: DeviceIdSchema,
68324
- minutes: MinutesSchema
68325
- }), _void(), {
68326
- kind: "mutation",
68327
- auth: "protected"
68328
- }),
68329
68624
  /** Clear the rolling daily consumption counters on the device. */
68330
- resetDailyConsumption: method(object({ deviceId: DeviceIdSchema }), _void(), {
68625
+ resetDailyConsumption: method(object({ deviceId: DeviceIdSchema$1 }), _void(), {
68331
68626
  kind: "mutation",
68332
68627
  auth: "protected"
68333
68628
  })
@@ -70660,6 +70955,79 @@ var ptzAutotrackCapability = {
70660
70955
  */
70661
70956
  history: "none"
70662
70957
  };
70958
+ /**
70959
+ * The on/off duty cycle of a pet fountain's pump. Some models run the pump
70960
+ * continuously and have nothing to configure; others can alternate a run time
70961
+ * and a rest time. That is model-specific, so it is its own optional cap on the
70962
+ * fountain device: a fountain without cycle entities simply never composes it
70963
+ * (planning#366), and the `pet-fountain` cap stays the model-independent core.
70964
+ *
70965
+ * Like `pet-fountain` it has no native vendor provider: an operator BUILDS the
70966
+ * cycle from loose entities (a cycle switch and two number boxes) and every
70967
+ * method is a forward to one source entity (D659, D967). Durations are stored
70968
+ * in SECONDS (D944); a number box that cannot be read back leaves them `null`
70969
+ * — unknown, never zero (D393).
70970
+ */
70971
+ var PumpCycleStatusSchema = object({
70972
+ /** True when the pump works on the on/off cycle, false when it runs continuously. Null while unknown. */
70973
+ enabled: boolean().nullable(),
70974
+ /** How long the pump runs per cycle, in seconds. Null while unknown. */
70975
+ onTime: number$1().min(0).nullable().meta(readingMeta("duration")),
70976
+ /** How long the pump rests per cycle, in seconds. Null while unknown. */
70977
+ offTime: number$1().min(0).nullable().meta(readingMeta("duration")),
70978
+ /** Ms epoch when the slice was last refreshed. */
70979
+ lastFetchedAt: number$1()
70980
+ });
70981
+ var DeviceIdSchema = number$1().int().nonnegative();
70982
+ var MinutesSchema = number$1().int().min(0);
70983
+ var pumpCycleCapability = {
70984
+ name: "pump-cycle",
70985
+ scope: "device",
70986
+ deviceNative: true,
70987
+ mode: "singleton",
70988
+ deviceTypes: [DeviceType.PetFountain],
70989
+ methods: {
70990
+ /** Switch the on/off duty cycle on or off (off = the pump runs continuously). */
70991
+ setEnabled: method(object({
70992
+ deviceId: DeviceIdSchema,
70993
+ on: boolean()
70994
+ }), _void(), {
70995
+ kind: "mutation",
70996
+ auth: "protected"
70997
+ }),
70998
+ /** Set how many minutes the pump runs per cycle. */
70999
+ setOnMinutes: method(object({
71000
+ deviceId: DeviceIdSchema,
71001
+ minutes: MinutesSchema
71002
+ }), _void(), {
71003
+ kind: "mutation",
71004
+ auth: "protected"
71005
+ }),
71006
+ /** Set how many minutes the pump rests per cycle. */
71007
+ setOffMinutes: method(object({
71008
+ deviceId: DeviceIdSchema,
71009
+ minutes: MinutesSchema
71010
+ }), _void(), {
71011
+ kind: "mutation",
71012
+ auth: "protected"
71013
+ })
71014
+ },
71015
+ status: {
71016
+ schema: PumpCycleStatusSchema,
71017
+ kind: "push"
71018
+ },
71019
+ /** Runtime-state slice — mirrored by the kernel; the hero card reads it whole. */
71020
+ runtimeState: PumpCycleStatusSchema,
71021
+ /**
71022
+ * Runtime-state durability: **session** — live appliance state re-published on connect.
71023
+ *
71024
+ * See `RuntimeStateDurability`. Enforced by
71025
+ * `scripts/check-runtime-state-durability.ts`.
71026
+ */
71027
+ durability: "session",
71028
+ /** History (D850): a duty-cycle setting is not a series worth recording. */
71029
+ history: "none"
71030
+ };
70663
71031
  DeviceType.Camera, DeviceType.Sensor, DeviceType.Switch, DeviceType.Gateway, method(object({ deviceId: number$1().int().nonnegative() }), object({ success: literal(true) }), {
70664
71032
  kind: "mutation",
70665
71033
  auth: "admin"
@@ -74652,7 +75020,16 @@ var smokeCapability = {
74652
75020
  * future fields without breaking the existing call sites.
74653
75021
  */
74654
75022
  var EmailAddressSchema = email();
75023
+ /**
75024
+ * Which relay of a multi-relay provider answers (D996). Absent = the provider's first / default
75025
+ * relay, so a caller written before relays existed keeps working unchanged. A provider with one
75026
+ * fixed relay ignores it. This is the integration instance id (`int_NNNN`), NOT the addon id: the
75027
+ * collection pin `addonId` still picks the provider, `instanceId` picks the relay inside it.
75028
+ */
75029
+ var InstanceIdSchema = string().min(1).optional();
75030
+ var RelayPinSchema = object({ instanceId: InstanceIdSchema });
74655
75031
  var SendEmailInputSchema = object({
75032
+ instanceId: InstanceIdSchema,
74656
75033
  to: union([EmailAddressSchema, array(EmailAddressSchema).min(1)]),
74657
75034
  cc: array(EmailAddressSchema).optional(),
74658
75035
  bcc: array(EmailAddressSchema).optional(),
@@ -74688,11 +75065,11 @@ method(SendEmailInputSchema, SendEmailResultSchema, {
74688
75065
  kind: "mutation",
74689
75066
  auth: "admin",
74690
75067
  access: "create"
74691
- }), method(_void(), SmtpStatusSchema, {
75068
+ }), method(RelayPinSchema, SmtpStatusSchema, {
74692
75069
  kind: "mutation",
74693
75070
  auth: "admin",
74694
75071
  access: "view"
74695
- }), method(_void(), SmtpStatusSchema, { auth: "admin" });
75072
+ }), method(RelayPinSchema, SmtpStatusSchema, { auth: "admin" });
74696
75073
  /**
74697
75074
  * A single device snapshot returned as base64 JPEG/PNG.
74698
75075
  *
@@ -74724,10 +75101,12 @@ DeviceType.Camera, method(object({
74724
75101
  * even when the cache is well within the device's
74725
75102
  * `snapshotMaxAgeS` window.
74726
75103
  *
74727
- * **`force` is an OPERATOR signal, not a freshness preference.** On a
75104
+ * **`force` is a demand with a named principal, not a freshness
75105
+ * preference** — an operator button, the scheduled refresh (D847), or a
75106
+ * notification rule that left the camera's wake allowed (D998). On a
74728
75107
  * battery camera it is the one thing that walks past the wrapper's
74729
- * sleep gate and wakes the camera, so a background caller — a poller,
74730
- * an event handler, a thumbnail — must NEVER set it. Every such caller
75108
+ * sleep gate and wakes the camera, so a poller, a thumbnail or a
75109
+ * prestream must NEVER set it. Every such caller
74731
75110
  * gets the cached frame, which on a sleeping battery camera is the
74732
75111
  * correct answer: stale but honest beats woken.
74733
75112
  */
@@ -76297,6 +76676,40 @@ var LoggingSettingsStateSchema = object({
76297
76676
  opsLogRetentionDays: number$1().int().min(0),
76298
76677
  persisted: boolean()
76299
76678
  });
76679
+ /**
76680
+ * Debug WATCH — a short, per-device window over `debug.<channel>` lines.
76681
+ *
76682
+ * `start` opens (or re-arms) a 10 minute window; `rearm` extends a LIVE one
76683
+ * and never revives a lapsed one; `stop` closes it; `list` only reads. No
76684
+ * chain of re-arms outlives 60 minutes from the first start. The hub holds the
76685
+ * watches in memory and pushes the interest to every node, so a watch lapses
76686
+ * by itself and survives nothing — a restart is a stop.
76687
+ */
76688
+ var DebugWatchInputSchema = object({
76689
+ action: _enum([
76690
+ "list",
76691
+ "start",
76692
+ "rearm",
76693
+ "stop"
76694
+ ]),
76695
+ /** Full channel names, `debug.<channel>`, each declared with `kind: 'debug'`. */
76696
+ channels: array(string().min(1)).readonly().default([]),
76697
+ /** Numeric device ids. Required (non-empty) for `start`. */
76698
+ deviceIds: array(number$1().int()).readonly().default([])
76699
+ });
76700
+ var DebugWatchStateSchema = object({
76701
+ channel: string(),
76702
+ deviceIds: array(number$1().int()).readonly(),
76703
+ startedAtMs: number$1(),
76704
+ untilMs: number$1(),
76705
+ capAtMs: number$1()
76706
+ });
76707
+ var DebugWatchResultSchema = object({
76708
+ nowMs: number$1(),
76709
+ watches: array(DebugWatchStateSchema).readonly(),
76710
+ /** Channels a `rearm` found already lapsed: nothing was revived. */
76711
+ lapsed: array(string()).readonly()
76712
+ });
76300
76713
  method(_void(), SystemInfoSchema), method(_void(), HealthStatusSchema), method(_void(), FeatureManifestSchema), method(_void(), array(NetworkAddressSchema).readonly()), method(_void(), unknown().nullable(), { auth: "admin" }), method(record(string(), unknown()), _null(), {
76301
76714
  kind: "mutation",
76302
76715
  auth: "admin"
@@ -76312,6 +76725,9 @@ method(_void(), SystemInfoSchema), method(_void(), HealthStatusSchema), method(_
76312
76725
  }), method(_void(), RequestCensusStatusSchema, { auth: "admin" }), method(_void(), array(ReportedLoadContributionSchema).readonly(), { auth: "admin" }), method(_void(), array(ReportedFailureContributionSchema).readonly(), { auth: "admin" }), method(GetLoggingSettingsInputSchema, LoggingSettingsStateSchema, { auth: "admin" }), method(SetLoggingSettingsInputSchema, LoggingSettingsStateSchema, {
76313
76726
  kind: "mutation",
76314
76727
  auth: "admin"
76728
+ }), method(DebugWatchInputSchema, DebugWatchResultSchema, {
76729
+ kind: "mutation",
76730
+ auth: "admin"
76315
76731
  });
76316
76732
  /**
76317
76733
  * Tamper / case-open detection sensor. Drives Home Assistant
@@ -79377,7 +79793,7 @@ discriminatedUnion("kind", [object({
79377
79793
  kind: literal("pronto"),
79378
79794
  code: string()
79379
79795
  })]);
79380
- DeviceFeature.FanSpeed, DeviceFeature.FanPreset, DeviceFeature.FanDirection, DeviceFeature.FanOscillating, DeviceFeature.CoverPositionable, DeviceFeature.CoverTilt, DeviceFeature.ValvePositionable, DeviceFeature.MediaPlayerVolume, DeviceFeature.ClimateFanMode;
79796
+ DeviceFeature.FanSpeed, DeviceFeature.FanPreset, DeviceFeature.FanDirection, DeviceFeature.FanOscillating, DeviceFeature.CoverStoppable, DeviceFeature.CoverPositionable, DeviceFeature.CoverTilt, DeviceFeature.ValvePositionable, DeviceFeature.MediaPlayerVolume, DeviceFeature.ClimateFanMode;
79381
79797
  SOURCE_CAPS.filter((cap) => cap !== "switch" && cap !== "motion");
79382
79798
  String.raw`rose\(active(\d+), changed(\d+), (\d+(?:\.\d+)?)\)`;
79383
79799
  DeviceRole.BinarySensor, DeviceRole.MotionSensor;
@@ -79737,6 +80153,7 @@ var DEVICE_LOCAL_STATE_CAPS = {
79737
80153
  pressureSensor: pressureSensorCapability,
79738
80154
  privacyMask: privacyMaskCapability,
79739
80155
  ptzAutotrack: ptzAutotrackCapability,
80156
+ pumpCycle: pumpCycleCapability,
79740
80157
  recordingOnboard: recordingOnboardCapability,
79741
80158
  recordingSignal: recordingSignalCapability,
79742
80159
  runningState: runningStateCapability,
@@ -81921,6 +82338,27 @@ Object.freeze({
81921
82338
  access: "view",
81922
82339
  role: "viewer"
81923
82340
  },
82341
+ "boardKeySource.getBoardKey": {
82342
+ capName: "board-key-source",
82343
+ capScope: "system",
82344
+ addonId: null,
82345
+ access: "view",
82346
+ role: "admin"
82347
+ },
82348
+ "boardKeySource.listBoards": {
82349
+ capName: "board-key-source",
82350
+ capScope: "system",
82351
+ addonId: null,
82352
+ access: "view",
82353
+ role: "admin"
82354
+ },
82355
+ "boardKeySource.listSources": {
82356
+ capName: "board-key-source",
82357
+ capScope: "system",
82358
+ addonId: null,
82359
+ access: "view",
82360
+ role: "admin"
82361
+ },
81924
82362
  "brightness.getStatus": {
81925
82363
  capName: "brightness",
81926
82364
  capScope: "device",
@@ -83258,6 +83696,13 @@ Object.freeze({
83258
83696
  access: "view",
83259
83697
  role: "admin"
83260
83698
  },
83699
+ "deviceManager.dismissDiscoveryProposal": {
83700
+ capName: "device-manager",
83701
+ capScope: "system",
83702
+ addonId: null,
83703
+ access: "create",
83704
+ role: "admin"
83705
+ },
83261
83706
  "deviceManager.enable": {
83262
83707
  capName: "device-manager",
83263
83708
  capScope: "system",
@@ -83440,6 +83885,13 @@ Object.freeze({
83440
83885
  access: "view",
83441
83886
  role: "viewer"
83442
83887
  },
83888
+ "deviceManager.listDiscoveryProposals": {
83889
+ capName: "device-manager",
83890
+ capScope: "system",
83891
+ addonId: null,
83892
+ access: "view",
83893
+ role: "admin"
83894
+ },
83443
83895
  "deviceManager.listLocationDescriptions": {
83444
83896
  capName: "device-manager",
83445
83897
  capScope: "system",
@@ -83594,6 +84046,13 @@ Object.freeze({
83594
84046
  access: "create",
83595
84047
  role: "admin"
83596
84048
  },
84049
+ "deviceManager.reportDiscoveryObservations": {
84050
+ capName: "device-manager",
84051
+ capScope: "system",
84052
+ addonId: null,
84053
+ access: "create",
84054
+ role: "admin"
84055
+ },
83597
84056
  "deviceManager.runDeviceAction": {
83598
84057
  capName: "device-manager",
83599
84058
  capScope: "system",
@@ -83601,6 +84060,13 @@ Object.freeze({
83601
84060
  access: "create",
83602
84061
  role: "admin"
83603
84062
  },
84063
+ "deviceManager.runDiscoverySweep": {
84064
+ capName: "device-manager",
84065
+ capScope: "system",
84066
+ addonId: null,
84067
+ access: "create",
84068
+ role: "admin"
84069
+ },
83604
84070
  "deviceManager.setChildLayout": {
83605
84071
  capName: "device-manager",
83606
84072
  capScope: "system",
@@ -84532,6 +84998,69 @@ Object.freeze({
84532
84998
  access: "create",
84533
84999
  role: "admin"
84534
85000
  },
85001
+ "integrationInstances.createInstance": {
85002
+ capName: "integration-instances",
85003
+ capScope: "system",
85004
+ addonId: null,
85005
+ access: "create",
85006
+ role: "admin"
85007
+ },
85008
+ "integrationInstances.deleteInstance": {
85009
+ capName: "integration-instances",
85010
+ capScope: "system",
85011
+ addonId: null,
85012
+ access: "delete",
85013
+ role: "admin"
85014
+ },
85015
+ "integrationInstances.describe": {
85016
+ capName: "integration-instances",
85017
+ capScope: "system",
85018
+ addonId: null,
85019
+ access: "view",
85020
+ role: "admin"
85021
+ },
85022
+ "integrationInstances.getInstance": {
85023
+ capName: "integration-instances",
85024
+ capScope: "system",
85025
+ addonId: null,
85026
+ access: "view",
85027
+ role: "admin"
85028
+ },
85029
+ "integrationInstances.instanceFormSchema": {
85030
+ capName: "integration-instances",
85031
+ capScope: "system",
85032
+ addonId: null,
85033
+ access: "view",
85034
+ role: "admin"
85035
+ },
85036
+ "integrationInstances.listInstances": {
85037
+ capName: "integration-instances",
85038
+ capScope: "system",
85039
+ addonId: null,
85040
+ access: "view",
85041
+ role: "admin"
85042
+ },
85043
+ "integrationInstances.setInstanceEnabled": {
85044
+ capName: "integration-instances",
85045
+ capScope: "system",
85046
+ addonId: null,
85047
+ access: "create",
85048
+ role: "admin"
85049
+ },
85050
+ "integrationInstances.testInstance": {
85051
+ capName: "integration-instances",
85052
+ capScope: "system",
85053
+ addonId: null,
85054
+ access: "create",
85055
+ role: "admin"
85056
+ },
85057
+ "integrationInstances.updateInstance": {
85058
+ capName: "integration-instances",
85059
+ capScope: "system",
85060
+ addonId: null,
85061
+ access: "create",
85062
+ role: "admin"
85063
+ },
84535
85064
  "integrations.create": {
84536
85065
  capName: "integrations",
84537
85066
  capScope: "system",
@@ -86653,27 +87182,6 @@ Object.freeze({
86653
87182
  access: "create",
86654
87183
  role: "viewer"
86655
87184
  },
86656
- "petFountain.setPumpInterval": {
86657
- capName: "pet-fountain",
86658
- capScope: "device",
86659
- addonId: null,
86660
- access: "create",
86661
- role: "viewer"
86662
- },
86663
- "petFountain.setPumpOffMinutes": {
86664
- capName: "pet-fountain",
86665
- capScope: "device",
86666
- addonId: null,
86667
- access: "create",
86668
- role: "viewer"
86669
- },
86670
- "petFountain.setPumpOnMinutes": {
86671
- capName: "pet-fountain",
86672
- capScope: "device",
86673
- addonId: null,
86674
- access: "create",
86675
- role: "viewer"
86676
- },
86677
87185
  "pipelineAnalytics.addRetrainFrameFromRecording": {
86678
87186
  capName: "pipeline-analytics",
86679
87187
  capScope: "device",
@@ -88452,6 +88960,34 @@ Object.freeze({
88452
88960
  access: "create",
88453
88961
  role: "admin"
88454
88962
  },
88963
+ "pumpCycle.getStatus": {
88964
+ capName: "pump-cycle",
88965
+ capScope: "device",
88966
+ addonId: null,
88967
+ access: "view",
88968
+ role: "viewer"
88969
+ },
88970
+ "pumpCycle.setEnabled": {
88971
+ capName: "pump-cycle",
88972
+ capScope: "device",
88973
+ addonId: null,
88974
+ access: "create",
88975
+ role: "viewer"
88976
+ },
88977
+ "pumpCycle.setOffMinutes": {
88978
+ capName: "pump-cycle",
88979
+ capScope: "device",
88980
+ addonId: null,
88981
+ access: "create",
88982
+ role: "viewer"
88983
+ },
88984
+ "pumpCycle.setOnMinutes": {
88985
+ capName: "pump-cycle",
88986
+ capScope: "device",
88987
+ addonId: null,
88988
+ access: "create",
88989
+ role: "viewer"
88990
+ },
88455
88991
  "reboot.reboot": {
88456
88992
  capName: "reboot",
88457
88993
  capScope: "device",
@@ -90188,6 +90724,13 @@ Object.freeze({
90188
90724
  access: "create",
90189
90725
  role: "viewer"
90190
90726
  },
90727
+ "system.debugWatch": {
90728
+ capName: "system",
90729
+ capScope: "system",
90730
+ addonId: null,
90731
+ access: "create",
90732
+ role: "admin"
90733
+ },
90191
90734
  "system.detectSiteLocation": {
90192
90735
  capName: "system",
90193
90736
  capScope: "system",
@@ -92989,21 +93532,6 @@ Object.freeze({
92989
93532
  form: "single",
92990
93533
  optional: false
92991
93534
  }],
92992
- "petFountain.setPumpInterval": [{
92993
- name: "deviceId",
92994
- form: "single",
92995
- optional: false
92996
- }],
92997
- "petFountain.setPumpOffMinutes": [{
92998
- name: "deviceId",
92999
- form: "single",
93000
- optional: false
93001
- }],
93002
- "petFountain.setPumpOnMinutes": [{
93003
- name: "deviceId",
93004
- form: "single",
93005
- optional: false
93006
- }],
93007
93535
  "pipelineAnalytics.addRetrainFrameFromRecording": [{
93008
93536
  name: "deviceId",
93009
93537
  form: "single",
@@ -93639,6 +94167,26 @@ Object.freeze({
93639
94167
  form: "single",
93640
94168
  optional: false
93641
94169
  }],
94170
+ "pumpCycle.getStatus": [{
94171
+ name: "deviceId",
94172
+ form: "single",
94173
+ optional: false
94174
+ }],
94175
+ "pumpCycle.setEnabled": [{
94176
+ name: "deviceId",
94177
+ form: "single",
94178
+ optional: false
94179
+ }],
94180
+ "pumpCycle.setOffMinutes": [{
94181
+ name: "deviceId",
94182
+ form: "single",
94183
+ optional: false
94184
+ }],
94185
+ "pumpCycle.setOnMinutes": [{
94186
+ name: "deviceId",
94187
+ form: "single",
94188
+ optional: false
94189
+ }],
93642
94190
  "reboot.reboot": [{
93643
94191
  name: "deviceId",
93644
94192
  form: "single",
@@ -94106,6 +94654,11 @@ Object.freeze({
94106
94654
  form: "single",
94107
94655
  optional: false
94108
94656
  }],
94657
+ "system.debugWatch": [{
94658
+ name: "deviceIds",
94659
+ form: "array",
94660
+ optional: true
94661
+ }],
94109
94662
  "tamper.getStatus": [{
94110
94663
  name: "deviceId",
94111
94664
  form: "single",
@@ -140567,7 +141120,7 @@ function buildAlexaBrokerProvider(deps) {
140567
141120
  label: "Alexa",
140568
141121
  signIn: {
140569
141122
  basePath: "/addon/import-alexa/login",
140570
- methods: ["device-code"]
141123
+ methods: ["device-code", "proxy"]
140571
141124
  }
140572
141125
  }]
140573
141126
  }],