@camstack/addon-provider-tuya 0.2.125 → 0.2.127
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 +1404 -131
- package/dist/addon.mjs +1404 -131
- package/package.json +1 -1
package/dist/addon.js
CHANGED
|
@@ -819,7 +819,7 @@ async function discoverDevices(options = {}, binder = createDgramBinder()) {
|
|
|
819
819
|
return [...byId.values()];
|
|
820
820
|
}
|
|
821
821
|
//#endregion
|
|
822
|
-
//#region ../types/dist/event-category-
|
|
822
|
+
//#region ../types/dist/event-category-BvOFi6PY.mjs
|
|
823
823
|
var EventCategory = /* @__PURE__ */ function(EventCategory) {
|
|
824
824
|
EventCategory["SystemBoot"] = "system.boot";
|
|
825
825
|
EventCategory["SystemAddonsReady"] = "system.addons-ready";
|
|
@@ -883,6 +883,24 @@ var EventCategory = /* @__PURE__ */ function(EventCategory) {
|
|
|
883
883
|
* consumes this category and maps it to the `addon-crash-loop` kind.
|
|
884
884
|
*/
|
|
885
885
|
EventCategory["AddonRunnerFailed"] = "addon.runner-failed";
|
|
886
|
+
/**
|
|
887
|
+
* A runner whose addon refused to start with a typed reason (D877) - parked
|
|
888
|
+
* in `refused`, never counted by the crash breaker, retried on operator
|
|
889
|
+
* action. One event per refusal.
|
|
890
|
+
*/
|
|
891
|
+
EventCategory["AddonRunnerRefused"] = "addon.runner-refused";
|
|
892
|
+
/**
|
|
893
|
+
* A runner settled on a state (D877): `running` (READY), `crashed`, `failed` or
|
|
894
|
+
* `refused`. In-process telemetry for the boot check (re-evaluate while any
|
|
895
|
+
* runner is still pending) and the alert centre (close a recovered runner).
|
|
896
|
+
*/
|
|
897
|
+
EventCategory["ProcessStateChanged"] = "process.state-changed";
|
|
898
|
+
/**
|
|
899
|
+
* The node's one-shot runner boot check (D877): planned runners against the
|
|
900
|
+
* process service, `degraded` when any is failed, refused or missing. The
|
|
901
|
+
* alert centre turns it into one alert and a direct critical push.
|
|
902
|
+
*/
|
|
903
|
+
EventCategory["SystemRunnerCheck"] = "system.runner-check";
|
|
886
904
|
EventCategory["AddonError"] = "addon.error";
|
|
887
905
|
EventCategory["AddonPageReady"] = "addon.page-ready";
|
|
888
906
|
EventCategory["AddonWidgetReady"] = "addon.widget-ready";
|
|
@@ -6207,7 +6225,7 @@ var ZodIssueCode = {
|
|
|
6207
6225
|
var ZodFirstPartyTypeKind;
|
|
6208
6226
|
ZodFirstPartyTypeKind || (ZodFirstPartyTypeKind = {});
|
|
6209
6227
|
//#endregion
|
|
6210
|
-
//#region ../types/dist/sleep-
|
|
6228
|
+
//#region ../types/dist/sleep-BegKjwUu.mjs
|
|
6211
6229
|
/**
|
|
6212
6230
|
* The audio chunk plane's byte format, and the ONE expansion from a coded
|
|
6213
6231
|
* window to float samples (D455).
|
|
@@ -6324,7 +6342,7 @@ function isKeychainStoredField(field) {
|
|
|
6324
6342
|
var SECRET_CLEAR = { $secretClear: true };
|
|
6325
6343
|
/** The `'***'` token D634 redaction writes for non-admins. */
|
|
6326
6344
|
var LEGACY_DEVICE_REDACTION = "***";
|
|
6327
|
-
function isRecord$
|
|
6345
|
+
function isRecord$5(value) {
|
|
6328
6346
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
6329
6347
|
}
|
|
6330
6348
|
function makeSecretMarker(ref) {
|
|
@@ -6335,12 +6353,12 @@ function makeSecretMarker(ref) {
|
|
|
6335
6353
|
}
|
|
6336
6354
|
/** A stored marker: an object whose `$secret` is a non-empty string. */
|
|
6337
6355
|
function isSecretMarker(value) {
|
|
6338
|
-
if (!isRecord$
|
|
6356
|
+
if (!isRecord$5(value)) return false;
|
|
6339
6357
|
const ref = value["$secret"];
|
|
6340
6358
|
return typeof ref === "string" && ref.length > 0;
|
|
6341
6359
|
}
|
|
6342
6360
|
function isSecretClear(value) {
|
|
6343
|
-
return isRecord$
|
|
6361
|
+
return isRecord$5(value) && value["$secretClear"] === true;
|
|
6344
6362
|
}
|
|
6345
6363
|
/**
|
|
6346
6364
|
* The UI view of a stored secret field value: a marker becomes "set", inline
|
|
@@ -6950,7 +6968,7 @@ var KeychainWriteRefusedError = class extends Error {
|
|
|
6950
6968
|
}
|
|
6951
6969
|
};
|
|
6952
6970
|
var KEEP = { kind: "keep" };
|
|
6953
|
-
function isRecord$
|
|
6971
|
+
function isRecord$4(value) {
|
|
6954
6972
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
6955
6973
|
}
|
|
6956
6974
|
function defaultMintId() {
|
|
@@ -6963,7 +6981,7 @@ function collectSecretMarkerRefs(value, out = []) {
|
|
|
6963
6981
|
return out;
|
|
6964
6982
|
}
|
|
6965
6983
|
if (Array.isArray(value)) for (const item of value) collectSecretMarkerRefs(item, out);
|
|
6966
|
-
else if (isRecord$
|
|
6984
|
+
else if (isRecord$4(value)) for (const child of Object.values(value)) collectSecretMarkerRefs(child, out);
|
|
6967
6985
|
return out;
|
|
6968
6986
|
}
|
|
6969
6987
|
async function storedValueEquals(secrets, marker, candidate) {
|
|
@@ -7018,7 +7036,7 @@ function rowId(row, idKey) {
|
|
|
7018
7036
|
return null;
|
|
7019
7037
|
}
|
|
7020
7038
|
async function writeArray(ctx, node, incoming, stored, fieldPath) {
|
|
7021
|
-
const storedRows = Array.isArray(stored) ? stored.filter(isRecord$
|
|
7039
|
+
const storedRows = Array.isArray(stored) ? stored.filter(isRecord$4) : [];
|
|
7022
7040
|
if (!Array.isArray(incoming)) {
|
|
7023
7041
|
ctx.deletes.push(...collectSecretMarkerRefs(storedRows));
|
|
7024
7042
|
return {
|
|
@@ -7034,7 +7052,7 @@ async function writeArray(ctx, node, incoming, stored, fieldPath) {
|
|
|
7034
7052
|
const kept = /* @__PURE__ */ new Set();
|
|
7035
7053
|
const rows = [];
|
|
7036
7054
|
for (const row of incoming) {
|
|
7037
|
-
if (!isRecord$
|
|
7055
|
+
if (!isRecord$4(row)) {
|
|
7038
7056
|
rows.push(row);
|
|
7039
7057
|
continue;
|
|
7040
7058
|
}
|
|
@@ -7059,7 +7077,7 @@ async function writeNode(ctx, node, incoming, stored, fieldPath) {
|
|
|
7059
7077
|
case "leaf": return writeLeaf(ctx, incoming, stored, fieldPath);
|
|
7060
7078
|
case "array": return writeArray(ctx, node, incoming, stored, fieldPath);
|
|
7061
7079
|
case "object": {
|
|
7062
|
-
if (!isRecord$
|
|
7080
|
+
if (!isRecord$4(incoming)) {
|
|
7063
7081
|
if (incoming === void 0) return KEEP;
|
|
7064
7082
|
ctx.deletes.push(...collectSecretMarkerRefs(stored));
|
|
7065
7083
|
return {
|
|
@@ -7067,7 +7085,7 @@ async function writeNode(ctx, node, incoming, stored, fieldPath) {
|
|
|
7067
7085
|
value: incoming
|
|
7068
7086
|
};
|
|
7069
7087
|
}
|
|
7070
|
-
const storedObj = isRecord$
|
|
7088
|
+
const storedObj = isRecord$4(stored) ? stored : {};
|
|
7071
7089
|
return {
|
|
7072
7090
|
kind: "value",
|
|
7073
7091
|
value: await writeMembers(ctx, node.children, incoming, storedObj, (m) => `${fieldPath}.${m}`)
|
|
@@ -7190,7 +7208,7 @@ async function resolveSecretMarkers(value, secrets, options = {}) {
|
|
|
7190
7208
|
value: items
|
|
7191
7209
|
};
|
|
7192
7210
|
}
|
|
7193
|
-
if (isRecord$
|
|
7211
|
+
if (isRecord$4(v)) {
|
|
7194
7212
|
const out = {};
|
|
7195
7213
|
for (const [k, child] of Object.entries(v)) {
|
|
7196
7214
|
const s = substitute(child);
|
|
@@ -7222,7 +7240,7 @@ var SecretOverwriteRefusedError = class extends Error {
|
|
|
7222
7240
|
this.name = "SecretOverwriteRefusedError";
|
|
7223
7241
|
}
|
|
7224
7242
|
};
|
|
7225
|
-
function isRecord(value) {
|
|
7243
|
+
function isRecord$3(value) {
|
|
7226
7244
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
7227
7245
|
}
|
|
7228
7246
|
function resolvedValue(pass, marker) {
|
|
@@ -7251,7 +7269,7 @@ function inArray(pass, incoming, stored) {
|
|
|
7251
7269
|
return incoming.map((item, index) => {
|
|
7252
7270
|
const twin = stored[index];
|
|
7253
7271
|
if (isSecretMarker(twin)) return typeof item === "string" && item === resolvedValue(pass, twin) ? twin : item;
|
|
7254
|
-
if (isRecord(item) && isRecord(twin)) return inArrayRow(pass, item, twin);
|
|
7272
|
+
if (isRecord$3(item) && isRecord$3(twin)) return inArrayRow(pass, item, twin);
|
|
7255
7273
|
if (Array.isArray(item) && Array.isArray(twin)) return inArray(pass, item, twin);
|
|
7256
7274
|
return item;
|
|
7257
7275
|
});
|
|
@@ -7262,7 +7280,7 @@ function inArrayRow(pass, incoming, stored) {
|
|
|
7262
7280
|
const twin = stored[key];
|
|
7263
7281
|
if (isSecretMarker(twin)) {
|
|
7264
7282
|
if (typeof value === "string" && value === resolvedValue(pass, twin)) out[key] = twin;
|
|
7265
|
-
} else if (isRecord(value) && isRecord(twin)) out[key] = inArrayRow(pass, value, twin);
|
|
7283
|
+
} else if (isRecord$3(value) && isRecord$3(twin)) out[key] = inArrayRow(pass, value, twin);
|
|
7266
7284
|
else if (Array.isArray(value) && Array.isArray(twin)) out[key] = inArray(pass, value, twin);
|
|
7267
7285
|
}
|
|
7268
7286
|
return out;
|
|
@@ -7270,7 +7288,7 @@ function inArrayRow(pass, incoming, stored) {
|
|
|
7270
7288
|
async function walk(pass, incoming, stored) {
|
|
7271
7289
|
if (isSecretMarker(stored)) return atMarker(pass, incoming, stored);
|
|
7272
7290
|
if (Array.isArray(incoming) && Array.isArray(stored)) return inArray(pass, incoming, stored);
|
|
7273
|
-
if (!isRecord(incoming) || !isRecord(stored)) return incoming;
|
|
7291
|
+
if (!isRecord$3(incoming) || !isRecord$3(stored)) return incoming;
|
|
7274
7292
|
const out = { ...incoming };
|
|
7275
7293
|
for (const [key, value] of Object.entries(incoming)) out[key] = await walk(pass, value, stored[key]);
|
|
7276
7294
|
return out;
|
|
@@ -7301,7 +7319,7 @@ async function restoreUnchangedSecrets(input) {
|
|
|
7301
7319
|
function isJsonEqual(a, b) {
|
|
7302
7320
|
if (Object.is(a, b)) return true;
|
|
7303
7321
|
if (Array.isArray(a)) return Array.isArray(b) && a.length === b.length && a.every((v, i) => isJsonEqual(v, b[i]));
|
|
7304
|
-
if (isRecord(a) && isRecord(b)) {
|
|
7322
|
+
if (isRecord$3(a) && isRecord$3(b)) {
|
|
7305
7323
|
const keys = Object.keys(a);
|
|
7306
7324
|
if (keys.length !== Object.keys(b).length) return false;
|
|
7307
7325
|
return keys.every((k) => Object.prototype.hasOwnProperty.call(b, k) && isJsonEqual(a[k], b[k]));
|
|
@@ -7325,7 +7343,7 @@ function markerKeysOf(blob, owner) {
|
|
|
7325
7343
|
}
|
|
7326
7344
|
function nodeFromStored(value, owner) {
|
|
7327
7345
|
if (isSecretMarker(value)) return isSecretRefOwnedBy(value.$secret, owner) ? { kind: "leaf" } : null;
|
|
7328
|
-
if (!isRecord(value)) return null;
|
|
7346
|
+
if (!isRecord$3(value)) return null;
|
|
7329
7347
|
const children = /* @__PURE__ */ new Map();
|
|
7330
7348
|
for (const [key, child] of Object.entries(value)) {
|
|
7331
7349
|
const node = nodeFromStored(child, owner);
|
|
@@ -7458,7 +7476,6 @@ function createHandle(raw, opts) {
|
|
|
7458
7476
|
const writeAddon = (patch) => write("addon", opts.addonTree(), void 0, patch, () => readStoredAddonBlob(raw), (p) => raw.writeAddonStore(p));
|
|
7459
7477
|
const readAddonStoreResult = raw.readAddonStoreResult;
|
|
7460
7478
|
const readAddonStoreKeyResult = raw.readAddonStoreKeyResult;
|
|
7461
|
-
const readDeviceStoreBatch = raw.readDeviceStoreBatch;
|
|
7462
7479
|
const overrides = {
|
|
7463
7480
|
readAddonStore: async () => resolveRead("addon", await raw.readAddonStore()),
|
|
7464
7481
|
...readAddonStoreResult !== void 0 ? { readAddonStoreResult: async () => {
|
|
@@ -7482,12 +7499,12 @@ function createHandle(raw, opts) {
|
|
|
7482
7499
|
};
|
|
7483
7500
|
} } : {},
|
|
7484
7501
|
readDeviceStore: async (deviceId) => resolveRead(`device:${deviceId}`, await raw.readDeviceStore(deviceId)),
|
|
7485
|
-
|
|
7486
|
-
const rows = await readDeviceStoreBatch
|
|
7502
|
+
readDeviceStoreBatch: async (deviceIds) => {
|
|
7503
|
+
const rows = await raw.readDeviceStoreBatch(deviceIds);
|
|
7487
7504
|
const out = /* @__PURE__ */ new Map();
|
|
7488
7505
|
for (const [deviceId, blob] of rows) out.set(deviceId, await resolveRead(`device:${deviceId}`, blob));
|
|
7489
7506
|
return out;
|
|
7490
|
-
}
|
|
7507
|
+
},
|
|
7491
7508
|
writeAddonStore: async (patch) => {
|
|
7492
7509
|
await writeAddon(patch);
|
|
7493
7510
|
},
|
|
@@ -8114,7 +8131,7 @@ var BaseAddon = class {
|
|
|
8114
8131
|
if (!ctx) return;
|
|
8115
8132
|
const addonId = ctx.id;
|
|
8116
8133
|
setImmediate(() => {
|
|
8117
|
-
ctx.api.addons
|
|
8134
|
+
ctx.api.addons.restartAddon.mutate({ addonId }).then(() => {
|
|
8118
8135
|
ctx.logger.info("addon auto-restart triggered by restart-required setting change", { meta: { changedFields: patchKeys.filter((k) => restartKeys.has(k)) } });
|
|
8119
8136
|
}).catch((err) => {
|
|
8120
8137
|
ctx.logger.error("addon auto-restart failed", { meta: { error: err instanceof Error ? err.message : String(err) } });
|
|
@@ -8314,7 +8331,7 @@ var BaseAddon = class {
|
|
|
8314
8331
|
return this._addonSecretTree;
|
|
8315
8332
|
}
|
|
8316
8333
|
deviceSecretTree() {
|
|
8317
|
-
this._deviceSecretTree ??= secretTreeFromSchema(this.deviceSettingsSchema());
|
|
8334
|
+
this._deviceSecretTree ??= mergeSecretStatePaths(secretTreeFromSchema(this.deviceSettingsSchema()), this.secretStatePaths);
|
|
8318
8335
|
return this._deviceSecretTree;
|
|
8319
8336
|
}
|
|
8320
8337
|
/**
|
|
@@ -8390,42 +8407,135 @@ var BaseAddon = class {
|
|
|
8390
8407
|
this[timerOf] = timer;
|
|
8391
8408
|
}
|
|
8392
8409
|
/**
|
|
8393
|
-
* Wrap `ctx.settings.readAddonStore()` with a
|
|
8394
|
-
*
|
|
8395
|
-
* swap, or any race where the SqliteSettingsBackend is between shutdown and
|
|
8396
|
-
* re-initialize) doesn't propagate up into `initialize()` and leave the
|
|
8410
|
+
* Wrap `ctx.settings.readAddonStore()` with a retry budget so a transient
|
|
8411
|
+
* settings-store outage doesn't propagate up into `initialize()` and leave the
|
|
8397
8412
|
* addon permanently broken.
|
|
8398
8413
|
*
|
|
8399
|
-
*
|
|
8400
|
-
*
|
|
8401
|
-
* `
|
|
8414
|
+
* Two kinds of outage, two budgets:
|
|
8415
|
+
* - the store's own restart fingerprints (`SqliteSettingsBackend not
|
|
8416
|
+
* initialized`, `provider not available`): a short budget, then the addon
|
|
8417
|
+
* falls back to `{}` (defaults) - its first successful patch rehydrates;
|
|
8418
|
+
* - a TRANSPORT failure (the hub is restarting while this runner boots:
|
|
8419
|
+
* `discovery deadline exceeded`, `parent could not route`, a refused or
|
|
8420
|
+
* timed-out connection). Since D870 a runner's settings read THROWS instead
|
|
8421
|
+
* of answering `{}`, so without a budget a hub restart ends in a respawn
|
|
8422
|
+
* loop. A long, bounded budget; only after it the error propagates - the
|
|
8423
|
+
* addon never runs on defaults for a store it could not ask.
|
|
8424
|
+
* Anything else propagates immediately so real bugs surface.
|
|
8402
8425
|
*/
|
|
8403
8426
|
async readAddonStoreWithRetry() {
|
|
8404
8427
|
const settings = this.rawSettings();
|
|
8405
8428
|
if (!settings) return {};
|
|
8406
|
-
const delaysMs = [
|
|
8407
|
-
150,
|
|
8408
|
-
350,
|
|
8409
|
-
600,
|
|
8410
|
-
900
|
|
8411
|
-
];
|
|
8412
8429
|
let lastErr;
|
|
8413
|
-
for (let attempt = 0
|
|
8430
|
+
for (let attempt = 0;; attempt++) try {
|
|
8414
8431
|
const stored = await settings.readAddonStore() ?? {};
|
|
8415
8432
|
this.settingsStoreReady = true;
|
|
8416
8433
|
return stored;
|
|
8417
8434
|
} catch (err) {
|
|
8418
8435
|
lastErr = err;
|
|
8419
|
-
const
|
|
8420
|
-
if (
|
|
8421
|
-
|
|
8422
|
-
|
|
8436
|
+
const kind = classifyStoreError(err);
|
|
8437
|
+
if (kind === "permanent") throw err;
|
|
8438
|
+
const delay = (kind === "transport" ? TRANSPORT_RETRY_DELAYS_MS : RESTART_RETRY_DELAYS_MS)[attempt];
|
|
8439
|
+
if (delay === void 0) {
|
|
8440
|
+
if (kind === "transport") throw err;
|
|
8441
|
+
break;
|
|
8442
|
+
}
|
|
8443
|
+
await new Promise((r) => setTimeout(r, delay));
|
|
8423
8444
|
}
|
|
8424
8445
|
this.settingsStoreReady = false;
|
|
8425
8446
|
this._ctx?.logger?.warn?.("readAddonStore: settings-store unavailable after retries — using defaults", { meta: { error: lastErr instanceof Error ? lastErr.message : String(lastErr) } });
|
|
8426
8447
|
return {};
|
|
8427
8448
|
}
|
|
8428
8449
|
};
|
|
8450
|
+
/** The settings store's own restart fingerprints. */
|
|
8451
|
+
var RESTART_RETRY_DELAYS_MS = [
|
|
8452
|
+
150,
|
|
8453
|
+
350,
|
|
8454
|
+
600,
|
|
8455
|
+
900
|
|
8456
|
+
];
|
|
8457
|
+
/** A hub restarting under a booting runner: ~100 s in total. */
|
|
8458
|
+
var TRANSPORT_RETRY_DELAYS_MS = [
|
|
8459
|
+
150,
|
|
8460
|
+
350,
|
|
8461
|
+
600,
|
|
8462
|
+
900,
|
|
8463
|
+
2e3,
|
|
8464
|
+
5e3,
|
|
8465
|
+
1e4,
|
|
8466
|
+
2e4,
|
|
8467
|
+
3e4,
|
|
8468
|
+
3e4
|
|
8469
|
+
];
|
|
8470
|
+
var RESTART_FINGERPRINTS = ["SqliteSettingsBackend not initialized", "provider not available"];
|
|
8471
|
+
/** Node / socket error codes of a connection that did not happen or broke. */
|
|
8472
|
+
var TRANSPORT_CODES = new Set([
|
|
8473
|
+
"ECONNREFUSED",
|
|
8474
|
+
"ECONNRESET",
|
|
8475
|
+
"ETIMEDOUT",
|
|
8476
|
+
"EPIPE",
|
|
8477
|
+
"EHOSTUNREACH",
|
|
8478
|
+
"ENETUNREACH"
|
|
8479
|
+
]);
|
|
8480
|
+
/** tRPC error codes that mean "the other side is not answering now", not "your call is wrong". */
|
|
8481
|
+
var UNAVAILABLE_TRPC_CODES = new Set([
|
|
8482
|
+
"TIMEOUT",
|
|
8483
|
+
"SERVICE_UNAVAILABLE",
|
|
8484
|
+
"BAD_GATEWAY",
|
|
8485
|
+
"GATEWAY_TIMEOUT"
|
|
8486
|
+
]);
|
|
8487
|
+
/** The exact phrases OUR transport raises when it cannot reach the hub. */
|
|
8488
|
+
var TRANSPORT_PHRASES = [
|
|
8489
|
+
"discovery deadline exceeded",
|
|
8490
|
+
"parent could not route child unowned cap call",
|
|
8491
|
+
"UDS request timed out after",
|
|
8492
|
+
"channel closed"
|
|
8493
|
+
];
|
|
8494
|
+
/** Moleculer error `type`s of a call that could not be served right now. */
|
|
8495
|
+
var MOLECULER_TRANSIENT_TYPES = new Set([
|
|
8496
|
+
"REQUEST_TIMEOUT",
|
|
8497
|
+
"SERVICE_NOT_FOUND",
|
|
8498
|
+
"SERVICE_NOT_AVAILABLE",
|
|
8499
|
+
"REQUEST_REJECTED",
|
|
8500
|
+
"BROKER_DISCONNECTED"
|
|
8501
|
+
]);
|
|
8502
|
+
function stringProp(value, key) {
|
|
8503
|
+
if (typeof value !== "object" || value === null) return void 0;
|
|
8504
|
+
const found = Reflect.get(value, key);
|
|
8505
|
+
return typeof found === "string" ? found : void 0;
|
|
8506
|
+
}
|
|
8507
|
+
/** The code an error carries: its own, its cause's, or a tRPC `data.code`. */
|
|
8508
|
+
function errorCode(err) {
|
|
8509
|
+
const out = {};
|
|
8510
|
+
const cause = typeof err === "object" && err !== null ? Reflect.get(err, "cause") : void 0;
|
|
8511
|
+
const data = typeof err === "object" && err !== null ? Reflect.get(err, "data") : void 0;
|
|
8512
|
+
const node = stringProp(err, "code") ?? stringProp(cause, "code");
|
|
8513
|
+
if (node !== void 0) out.node = node;
|
|
8514
|
+
const trpc = stringProp(data, "code");
|
|
8515
|
+
if (trpc !== void 0) out.trpc = trpc;
|
|
8516
|
+
return out;
|
|
8517
|
+
}
|
|
8518
|
+
/**
|
|
8519
|
+
* Is a settings read failure worth retrying, and with which budget? Only
|
|
8520
|
+
* EXPLICIT signals count: a socket error code, a tRPC "unavailable" code, or
|
|
8521
|
+
* one of the exact phrases our own transport raises. A message that merely
|
|
8522
|
+
* contains "timed out" or "unreachable" is not evidence of anything, and
|
|
8523
|
+
* `settings store not wired` is a wiring bug that retrying cannot fix.
|
|
8524
|
+
*/
|
|
8525
|
+
function classifyStoreError(err) {
|
|
8526
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
8527
|
+
if (RESTART_FINGERPRINTS.some((f) => message.includes(f))) return "restart";
|
|
8528
|
+
const code = errorCode(err);
|
|
8529
|
+
if (code.node !== void 0 && TRANSPORT_CODES.has(code.node)) return "transport";
|
|
8530
|
+
if (code.trpc !== void 0 && UNAVAILABLE_TRPC_CODES.has(code.trpc)) return "transport";
|
|
8531
|
+
if (typeof err === "object" && err !== null) {
|
|
8532
|
+
if (Reflect.get(err, "retryable") === true) return "transport";
|
|
8533
|
+
const type = stringProp(err, "type");
|
|
8534
|
+
if (type !== void 0 && MOLECULER_TRANSIENT_TYPES.has(type)) return "transport";
|
|
8535
|
+
}
|
|
8536
|
+
if (TRANSPORT_PHRASES.some((f) => message.includes(f))) return "transport";
|
|
8537
|
+
return "permanent";
|
|
8538
|
+
}
|
|
8429
8539
|
/**
|
|
8430
8540
|
* Collect the keys of every field marked `perNode: true`, recursing into
|
|
8431
8541
|
* layout containers (`group` fields and `sub-tabs` tabs) the same way
|
|
@@ -8515,6 +8625,156 @@ var PeerBytesTicketSchema = object({
|
|
|
8515
8625
|
*/
|
|
8516
8626
|
declaredBytes: number().int().nonnegative().nullable()
|
|
8517
8627
|
});
|
|
8628
|
+
/** Limits and names of `ctx.records` (D881). One authority; the engine and the facade read it. */
|
|
8629
|
+
/** The files a kind may live in. `history` is device-history's (D850), never records. */
|
|
8630
|
+
var RECORD_DATABASES = ["settings", "events"];
|
|
8631
|
+
/** The classes of a kind: the `@durable` vocabulary, one authority (replaces the annotation). */
|
|
8632
|
+
var RECORD_CLASSES = [
|
|
8633
|
+
"config",
|
|
8634
|
+
"ledger",
|
|
8635
|
+
"audit",
|
|
8636
|
+
"mirror",
|
|
8637
|
+
"ephemeral"
|
|
8638
|
+
];
|
|
8639
|
+
var RECORD_DEFAULT_MAX_DATA_BYTES = 64 * 1024;
|
|
8640
|
+
var RECORD_MAX_DATA_BYTES = 1024 * 1024;
|
|
8641
|
+
var RECORD_BATCH_MAX = 1e3;
|
|
8642
|
+
var RECORD_QUERY_MAX = 1e3;
|
|
8643
|
+
function defOf(schema) {
|
|
8644
|
+
const zodBag = Reflect.get(schema, "_zod");
|
|
8645
|
+
if (typeof zodBag !== "object" || zodBag === null) return {};
|
|
8646
|
+
const def = Reflect.get(zodBag, "def");
|
|
8647
|
+
if (typeof def !== "object" || def === null) return {};
|
|
8648
|
+
return def;
|
|
8649
|
+
}
|
|
8650
|
+
function declaredHere(schema) {
|
|
8651
|
+
return globalRegistry.get(schema)?.secret === true;
|
|
8652
|
+
}
|
|
8653
|
+
/** Wrapper kinds whose `innerType` is the field itself. */
|
|
8654
|
+
var WRAPPERS = new Set([
|
|
8655
|
+
"optional",
|
|
8656
|
+
"nullable",
|
|
8657
|
+
"default",
|
|
8658
|
+
"prefault",
|
|
8659
|
+
"catch",
|
|
8660
|
+
"readonly",
|
|
8661
|
+
"nonoptional"
|
|
8662
|
+
]);
|
|
8663
|
+
/**
|
|
8664
|
+
* The schema layers that make up ONE field: the schema itself and every
|
|
8665
|
+
* wrapper below it (optional / default / nullable / readonly / catch), plus
|
|
8666
|
+
* both sides of a pipe (`z.preprocess` puts the real schema on `out`,
|
|
8667
|
+
* `.transform` on `in`).
|
|
8668
|
+
*/
|
|
8669
|
+
function layersOf(schema) {
|
|
8670
|
+
const out = [];
|
|
8671
|
+
const queue = [schema];
|
|
8672
|
+
while (queue.length > 0) {
|
|
8673
|
+
const s = queue.shift();
|
|
8674
|
+
if (!s || out.includes(s)) continue;
|
|
8675
|
+
out.push(s);
|
|
8676
|
+
const def = defOf(s);
|
|
8677
|
+
if (def.type !== void 0 && WRAPPERS.has(def.type) && def.innerType) queue.push(def.innerType);
|
|
8678
|
+
if (def.type === "pipe") {
|
|
8679
|
+
if (def.in) queue.push(def.in);
|
|
8680
|
+
if (def.out) queue.push(def.out);
|
|
8681
|
+
}
|
|
8682
|
+
}
|
|
8683
|
+
return out;
|
|
8684
|
+
}
|
|
8685
|
+
/** True when any layer of this field declares `.meta({ secret: true })`. */
|
|
8686
|
+
function isZodSecret(schema) {
|
|
8687
|
+
return layersOf(schema).some(declaredHere);
|
|
8688
|
+
}
|
|
8689
|
+
/**
|
|
8690
|
+
* Every declared secret path in a config schema: dotted keys, `[]` for "each
|
|
8691
|
+
* element of this array" (`connection.password`, `rows[].token`). A declared
|
|
8692
|
+
* object or array is reported as one path and not descended into — everything
|
|
8693
|
+
* under it is secret.
|
|
8694
|
+
*/
|
|
8695
|
+
function collectZodSecretPaths(schema, prefix = "") {
|
|
8696
|
+
if (isZodSecret(schema)) return prefix.length > 0 ? [prefix] : [];
|
|
8697
|
+
const paths = [];
|
|
8698
|
+
for (const layer of layersOf(schema)) {
|
|
8699
|
+
const def = defOf(layer);
|
|
8700
|
+
if (def.type === "object" && def.shape) for (const [key, child] of Object.entries(def.shape)) paths.push(...collectZodSecretPaths(child, prefix ? `${prefix}.${key}` : key));
|
|
8701
|
+
else if (def.type === "array" && def.element) paths.push(...collectZodSecretPaths(def.element, `${prefix}[]`));
|
|
8702
|
+
else if (def.type === "union" && def.options) for (const option of def.options) paths.push(...collectZodSecretPaths(option, prefix));
|
|
8703
|
+
else if (def.type === "intersection") {
|
|
8704
|
+
if (def.left) paths.push(...collectZodSecretPaths(def.left, prefix));
|
|
8705
|
+
if (def.right) paths.push(...collectZodSecretPaths(def.right, prefix));
|
|
8706
|
+
}
|
|
8707
|
+
}
|
|
8708
|
+
return [...new Set(paths)];
|
|
8709
|
+
}
|
|
8710
|
+
/**
|
|
8711
|
+
* Record kinds (D881): the declaration an addon makes of one kind of fact, the
|
|
8712
|
+
* Zod row schema that describes it, and the helper that turns the two into the
|
|
8713
|
+
* JSON the engine stores.
|
|
8714
|
+
*
|
|
8715
|
+
* A kind is declared ONCE, next to the code that owns it, and the engine's
|
|
8716
|
+
* reconciler creates its indexes - nothing creates DDL at runtime from a write.
|
|
8717
|
+
* Everything the generic machinery needs (secret fields, the entry descriptor)
|
|
8718
|
+
* is DERIVED from the Zod schema: `.meta({ secret: true })` marks a credential,
|
|
8719
|
+
* never a field name (D879).
|
|
8720
|
+
*/
|
|
8721
|
+
/** A JSON field path: `trackId`, `auth.accessToken`. Charset-restricted: it is rendered into DDL. */
|
|
8722
|
+
var RecordFieldPathSchema = string().regex(/^[A-Za-z_][A-Za-z0-9_]{0,63}(\.[A-Za-z_][A-Za-z0-9_]{0,63}){0,3}$/);
|
|
8723
|
+
var RecordIndexSchema = object({
|
|
8724
|
+
name: string().regex(/^[a-z][a-z0-9_]{0,31}$/),
|
|
8725
|
+
fields: array(RecordFieldPathSchema).min(1).max(4),
|
|
8726
|
+
unique: boolean().optional()
|
|
8727
|
+
}).strict();
|
|
8728
|
+
var RecordRetentionSchema = union([
|
|
8729
|
+
object({
|
|
8730
|
+
ttlMs: number().int().positive(),
|
|
8731
|
+
from: _enum(["at", "write"])
|
|
8732
|
+
}).strict(),
|
|
8733
|
+
object({
|
|
8734
|
+
maxRows: number().int().positive().optional(),
|
|
8735
|
+
maxRowsPerDevice: number().int().positive().optional()
|
|
8736
|
+
}).strict().refine((r) => r.maxRows !== void 0 || r.maxRowsPerDevice !== void 0, { message: "name maxRows, maxRowsPerDevice or both" }),
|
|
8737
|
+
object({
|
|
8738
|
+
owner: string().min(1),
|
|
8739
|
+
reason: string().min(1)
|
|
8740
|
+
}).strict(),
|
|
8741
|
+
object({ none: string().min(1) }).strict()
|
|
8742
|
+
]);
|
|
8743
|
+
/** The descriptor a generic entries UI reads (D881 "generic entries"). */
|
|
8744
|
+
var EntryDescriptorSchema = object({
|
|
8745
|
+
title: string().min(1),
|
|
8746
|
+
/** The record body field shown as the entry's name. */
|
|
8747
|
+
nameField: string().min(1),
|
|
8748
|
+
/** JSON Schema of the entry body; `secret: true` marks a password field. */
|
|
8749
|
+
fields: record(string(), unknown())
|
|
8750
|
+
}).strict();
|
|
8751
|
+
/** What crosses the wire and sits in the engine's catalog: JSON only, no Zod. */
|
|
8752
|
+
var RecordKindDeclarationSchema = object({
|
|
8753
|
+
database: _enum(RECORD_DATABASES).default("settings"),
|
|
8754
|
+
class: _enum(RECORD_CLASSES),
|
|
8755
|
+
writeTrigger: string().min(1),
|
|
8756
|
+
device: _enum([
|
|
8757
|
+
"required",
|
|
8758
|
+
"optional",
|
|
8759
|
+
"none"
|
|
8760
|
+
]).default("none"),
|
|
8761
|
+
at: _enum(["required", "none"]).default("none"),
|
|
8762
|
+
indexes: array(RecordIndexSchema).max(8).default([]),
|
|
8763
|
+
retention: RecordRetentionSchema,
|
|
8764
|
+
deviceRemoval: _enum(["delete", "none"]).default("none"),
|
|
8765
|
+
maxDataBytes: number().int().positive().max(RECORD_MAX_DATA_BYTES).default(RECORD_DEFAULT_MAX_DATA_BYTES),
|
|
8766
|
+
/** Derived from the Zod schema; never written by hand. */
|
|
8767
|
+
secretPaths: array(string().min(1)).default([]),
|
|
8768
|
+
/** The id key of each array that carries a secret (`{ headers: 'name' }`). */
|
|
8769
|
+
secretArrayKeys: record(string(), string()).default({}),
|
|
8770
|
+
/** The legacy table this kind adopts from; the boot guard reads it (D853: no migration code). */
|
|
8771
|
+
adoptsFrom: string().min(1).optional(),
|
|
8772
|
+
/** Kinds that must agree through `transact` sit in one file under one family name. */
|
|
8773
|
+
transactFamily: string().min(1).optional(),
|
|
8774
|
+
entry: EntryDescriptorSchema.optional()
|
|
8775
|
+
}).strict();
|
|
8776
|
+
/** The kind names: lower-case, dash separated, short enough for an index name. */
|
|
8777
|
+
var RecordKindNameSchema = string().regex(/^[a-z][a-z0-9-]{0,47}$/);
|
|
8518
8778
|
/** Shared Zod schemas used across streaming capabilities. */
|
|
8519
8779
|
var CamProfileSchema = _enum([
|
|
8520
8780
|
"high",
|
|
@@ -8979,75 +9239,12 @@ method(object({ deviceId: number() }), array(StreamSourceEntrySchema)), method(o
|
|
|
8979
9239
|
kind: "mutation",
|
|
8980
9240
|
auth: "admin"
|
|
8981
9241
|
}), method(object({ deviceId: number() }), unknown().nullable()), method(object({ deviceId: number() }), RawStateResultSchema.nullable(), { auth: "protected" });
|
|
8982
|
-
function defOf(schema) {
|
|
8983
|
-
return schema._zod?.def ?? {};
|
|
8984
|
-
}
|
|
8985
|
-
function declaredHere(schema) {
|
|
8986
|
-
return globalRegistry.get(schema)?.secret === true;
|
|
8987
|
-
}
|
|
8988
|
-
/** Wrapper kinds whose `innerType` is the field itself. */
|
|
8989
|
-
var WRAPPERS = new Set([
|
|
8990
|
-
"optional",
|
|
8991
|
-
"nullable",
|
|
8992
|
-
"default",
|
|
8993
|
-
"prefault",
|
|
8994
|
-
"catch",
|
|
8995
|
-
"readonly",
|
|
8996
|
-
"nonoptional"
|
|
8997
|
-
]);
|
|
8998
|
-
/**
|
|
8999
|
-
* The schema layers that make up ONE field: the schema itself and every
|
|
9000
|
-
* wrapper below it (optional / default / nullable / readonly / catch), plus
|
|
9001
|
-
* both sides of a pipe (`z.preprocess` puts the real schema on `out`,
|
|
9002
|
-
* `.transform` on `in`).
|
|
9003
|
-
*/
|
|
9004
|
-
function layersOf(schema) {
|
|
9005
|
-
const out = [];
|
|
9006
|
-
const queue = [schema];
|
|
9007
|
-
while (queue.length > 0) {
|
|
9008
|
-
const s = queue.shift();
|
|
9009
|
-
if (!s || out.includes(s)) continue;
|
|
9010
|
-
out.push(s);
|
|
9011
|
-
const def = defOf(s);
|
|
9012
|
-
if (def.type !== void 0 && WRAPPERS.has(def.type) && def.innerType) queue.push(def.innerType);
|
|
9013
|
-
if (def.type === "pipe") {
|
|
9014
|
-
if (def.in) queue.push(def.in);
|
|
9015
|
-
if (def.out) queue.push(def.out);
|
|
9016
|
-
}
|
|
9017
|
-
}
|
|
9018
|
-
return out;
|
|
9019
|
-
}
|
|
9020
|
-
/** True when any layer of this field declares `.meta({ secret: true })`. */
|
|
9021
|
-
function isZodSecret(schema) {
|
|
9022
|
-
return layersOf(schema).some(declaredHere);
|
|
9023
|
-
}
|
|
9024
|
-
/**
|
|
9025
|
-
* Every declared secret path in a config schema: dotted keys, `[]` for "each
|
|
9026
|
-
* element of this array" (`connection.password`, `rows[].token`). A declared
|
|
9027
|
-
* object or array is reported as one path and not descended into — everything
|
|
9028
|
-
* under it is secret.
|
|
9029
|
-
*/
|
|
9030
|
-
function collectZodSecretPaths(schema, prefix = "") {
|
|
9031
|
-
if (isZodSecret(schema)) return prefix.length > 0 ? [prefix] : [];
|
|
9032
|
-
const paths = [];
|
|
9033
|
-
for (const layer of layersOf(schema)) {
|
|
9034
|
-
const def = defOf(layer);
|
|
9035
|
-
if (def.type === "object" && def.shape) for (const [key, child] of Object.entries(def.shape)) paths.push(...collectZodSecretPaths(child, prefix ? `${prefix}.${key}` : key));
|
|
9036
|
-
else if (def.type === "array" && def.element) paths.push(...collectZodSecretPaths(def.element, `${prefix}[]`));
|
|
9037
|
-
else if (def.type === "union" && def.options) for (const option of def.options) paths.push(...collectZodSecretPaths(option, prefix));
|
|
9038
|
-
else if (def.type === "intersection") {
|
|
9039
|
-
if (def.left) paths.push(...collectZodSecretPaths(def.left, prefix));
|
|
9040
|
-
if (def.right) paths.push(...collectZodSecretPaths(def.right, prefix));
|
|
9041
|
-
}
|
|
9042
|
-
}
|
|
9043
|
-
return [...new Set(paths)];
|
|
9044
|
-
}
|
|
9045
9242
|
object({
|
|
9046
9243
|
code: string().regex(/^[a-z][a-z0-9-]*(\.[a-z0-9-]+)+$/),
|
|
9047
9244
|
params: record(string(), union([string(), number()])).optional()
|
|
9048
9245
|
});
|
|
9049
9246
|
//#endregion
|
|
9050
|
-
//#region ../types/dist/err-msg-
|
|
9247
|
+
//#region ../types/dist/err-msg-BXKzRBwg.mjs
|
|
9051
9248
|
var DeviceType = /* @__PURE__ */ function(DeviceType) {
|
|
9052
9249
|
DeviceType["Camera"] = "camera";
|
|
9053
9250
|
DeviceType["Hub"] = "hub";
|
|
@@ -9139,6 +9336,10 @@ var DeviceType = /* @__PURE__ */ function(DeviceType) {
|
|
|
9139
9336
|
* native PetKit (`nodepetkit` `FeederDevice`), reusable by other feeder
|
|
9140
9337
|
* integrations sharing the same food/desiccant/hopper surface. */
|
|
9141
9338
|
DeviceType["PetFeeder"] = "pet-feeder";
|
|
9339
|
+
/** Built-in dishwasher — program lifecycle, door / remote-start gates,
|
|
9340
|
+
* salt and rinse-aid levels. Installed with the `dishwasher` cap.
|
|
9341
|
+
* Sources: native Bosch Home Connect, reusable by similar integrations. */
|
|
9342
|
+
DeviceType["Dishwasher"] = "dishwasher";
|
|
9142
9343
|
return DeviceType;
|
|
9143
9344
|
}({});
|
|
9144
9345
|
var DeviceFeature = /* @__PURE__ */ function(DeviceFeature) {
|
|
@@ -9316,6 +9517,9 @@ var DeviceRole = /* @__PURE__ */ function(DeviceRole) {
|
|
|
9316
9517
|
/** Virtual HA toggle (input_boolean.*) — distinguishable from a
|
|
9317
9518
|
* real Switch device for UI rendering / export adapters. */
|
|
9318
9519
|
DeviceRole["BinaryHelper"] = "binary-helper";
|
|
9520
|
+
/** A smart plug: a `switch` whose source says it is an outlet (HA
|
|
9521
|
+
* `device_class: outlet`). The Alexa export shows it as a SMARTPLUG. */
|
|
9522
|
+
DeviceRole["Outlet"] = "outlet";
|
|
9319
9523
|
/** Generic motion / occupancy / moving event source. Distinct from
|
|
9320
9524
|
* the camera accessory PirSensor role: that one is a camera child;
|
|
9321
9525
|
* this is a standalone HA / 3rd-party motion sensor. */
|
|
@@ -9393,7 +9597,7 @@ function errMsg(err) {
|
|
|
9393
9597
|
return String(err);
|
|
9394
9598
|
}
|
|
9395
9599
|
//#endregion
|
|
9396
|
-
//#region ../types/dist/composition-
|
|
9600
|
+
//#region ../types/dist/composition-CB6PMT9p.mjs
|
|
9397
9601
|
/**
|
|
9398
9602
|
* The ffmpeg build every CamStack node downloads, per platform and arch.
|
|
9399
9603
|
*
|
|
@@ -12597,11 +12801,10 @@ var ClipModelMetaSchema = object({
|
|
|
12597
12801
|
/**
|
|
12598
12802
|
* The `vector-store` index this model's vectors live in. ONE feature space
|
|
12599
12803
|
* per index: two models share an index only when their vectors are ranked
|
|
12600
|
-
* against each other, which for CLIP means never across families.
|
|
12601
|
-
*
|
|
12602
|
-
* `modelId`); any other model gets its own.
|
|
12804
|
+
* against each other, which for CLIP means never across families. Every
|
|
12805
|
+
* model gets its own.
|
|
12603
12806
|
*/
|
|
12604
|
-
vectorIndex: string().regex(/^object-clip
|
|
12807
|
+
vectorIndex: string().regex(/^object-clip-[a-z0-9][a-z0-9-]*$/),
|
|
12605
12808
|
/**
|
|
12606
12809
|
* The text encoder's tokenizer, a declared SIBLING file of its onnx. The name
|
|
12607
12810
|
* must be unique per tokenizer: every model's siblings land in ONE flat
|
|
@@ -13780,8 +13983,13 @@ var AlertSeveritySchema = _enum([
|
|
|
13780
13983
|
"info",
|
|
13781
13984
|
"success",
|
|
13782
13985
|
"warning",
|
|
13783
|
-
"error"
|
|
13986
|
+
"error",
|
|
13987
|
+
"critical"
|
|
13784
13988
|
]);
|
|
13989
|
+
var AlertActionSchema = object({
|
|
13990
|
+
label: string(),
|
|
13991
|
+
href: string().optional()
|
|
13992
|
+
});
|
|
13785
13993
|
var AlertStatusSchema = _enum([
|
|
13786
13994
|
"active",
|
|
13787
13995
|
"in-progress",
|
|
@@ -13799,6 +14007,7 @@ var AlertSchema = object({
|
|
|
13799
14007
|
severity: AlertSeveritySchema,
|
|
13800
14008
|
title: string(),
|
|
13801
14009
|
message: string(),
|
|
14010
|
+
action: AlertActionSchema.optional(),
|
|
13802
14011
|
status: AlertStatusSchema,
|
|
13803
14012
|
progress: number().optional(),
|
|
13804
14013
|
read: boolean(),
|
|
@@ -16334,6 +16543,41 @@ var ComposableCapabilitiesSchema = object({ caps: array(object({
|
|
|
16334
16543
|
keyField: string()
|
|
16335
16544
|
}).optional()
|
|
16336
16545
|
})) });
|
|
16546
|
+
/**
|
|
16547
|
+
* The report of a one-shot "move this owner's plaintext secrets into the
|
|
16548
|
+
* keychain" run (D878). COUNTS only - never a value, never a ref.
|
|
16549
|
+
*
|
|
16550
|
+
* The owner runs it on its own rows, through its own write path; an operator
|
|
16551
|
+
* script (`scripts/hub/migrate-raw-secrets.ts`) calls the owner's cap method.
|
|
16552
|
+
* Dry run (`apply: false`) reports what WOULD move and changes nothing.
|
|
16553
|
+
*/
|
|
16554
|
+
var RawSecretMigrationInputSchema = object({
|
|
16555
|
+
/** `false` (the default of the script) = report only. */
|
|
16556
|
+
apply: boolean() });
|
|
16557
|
+
var RawSecretMigrationReportSchema = object({
|
|
16558
|
+
apply: boolean(),
|
|
16559
|
+
/** Rows that can carry a secret (a profile, an enrolment). */
|
|
16560
|
+
rows: number().int(),
|
|
16561
|
+
/** Rows whose secret was plaintext when the run started. */
|
|
16562
|
+
raw: number().int(),
|
|
16563
|
+
/** Rows that already held a keychain marker when the run started. */
|
|
16564
|
+
markers: number().int(),
|
|
16565
|
+
/** Plaintext rows moved by THIS run (always 0 on a dry run). */
|
|
16566
|
+
migrated: number().int(),
|
|
16567
|
+
/** Plaintext rows left in place because the move or its read-back failed. */
|
|
16568
|
+
failed: number().int(),
|
|
16569
|
+
/** After the run: rows still holding plaintext. */
|
|
16570
|
+
remainingRaw: number().int(),
|
|
16571
|
+
/** After the run: markers the keychain could not resolve right now. */
|
|
16572
|
+
unresolvedMarkers: number().int(),
|
|
16573
|
+
/**
|
|
16574
|
+
* A second, redundant copy of the secrets' rows that the run found (and, on
|
|
16575
|
+
* `apply`, deleted after verifying the first). Owners with a single copy omit it.
|
|
16576
|
+
*/
|
|
16577
|
+
redundantCopies: number().int().optional(),
|
|
16578
|
+
/** True when nothing is raw and every marker resolves. */
|
|
16579
|
+
verified: boolean()
|
|
16580
|
+
});
|
|
16337
16581
|
/** Where a block runs. The operator chooses — a block driving a device on an
|
|
16338
16582
|
* agent is the reason placement is not fixed to the hub. */
|
|
16339
16583
|
var CoreBlockPlacementSchema = union([literal("hub"), string().min(1)]);
|
|
@@ -16560,6 +16804,9 @@ method(object({}), object({ blocks: array(CoreBlockSchema) }), { auth: "admin" }
|
|
|
16560
16804
|
}), SettingsUpdateResultSchema, {
|
|
16561
16805
|
kind: "mutation",
|
|
16562
16806
|
auth: "admin"
|
|
16807
|
+
}), method(RawSecretMigrationInputSchema, RawSecretMigrationReportSchema, {
|
|
16808
|
+
kind: "mutation",
|
|
16809
|
+
auth: "admin"
|
|
16563
16810
|
}), method(object({}), object({ libs: array(object({
|
|
16564
16811
|
filePath: string(),
|
|
16565
16812
|
content: string()
|
|
@@ -16823,6 +17070,347 @@ id: union([string(), number()]) }), {
|
|
|
16823
17070
|
auth: "admin"
|
|
16824
17071
|
});
|
|
16825
17072
|
/**
|
|
17073
|
+
* records - an addon's own facts and documents (D881): ledgers, audit rows,
|
|
17074
|
+
* config documents, mirrors. The third storage API next to `ctx.settings`
|
|
17075
|
+
* (operator intent, D870) and device-history (numbers over time, D850).
|
|
17076
|
+
*
|
|
17077
|
+
* Who the OWNER is: `callerAddonId`, stamped by the transport on a call that
|
|
17078
|
+
* crossed a process and stated by a hub in-process caller (`ctx.records` does
|
|
17079
|
+
* that with the addon id closed over). It is deliberately NOT in any input
|
|
17080
|
+
* schema, so a session can never supply it, and a call with no stamp is refused
|
|
17081
|
+
* `records/no-caller`. A kind is readable and writable only by its owner; other
|
|
17082
|
+
* addons go through the owner's capability.
|
|
17083
|
+
*
|
|
17084
|
+
* Every read is three-way: a row, `null`, or the call THROWS. A failed read is
|
|
17085
|
+
* never `[]`. Secret fields are never on the wire: a read shows the
|
|
17086
|
+
* redaction token, `secretRefs` hands the owner's `ctx.secrets` the refs it
|
|
17087
|
+
* resolves itself, and a write may carry only a keychain marker bound to the
|
|
17088
|
+
* row's own ref.
|
|
17089
|
+
*
|
|
17090
|
+
* Internal: addons reach it through `ctx.records`, never directly.
|
|
17091
|
+
*/
|
|
17092
|
+
var RecordIdSchema = string().min(1).max(256);
|
|
17093
|
+
/** A JSON object body. Size is the engine's check (`maxDataBytes`), not a schema's. */
|
|
17094
|
+
var RecordBodySchema = record(string(), unknown());
|
|
17095
|
+
var RecordInputSchema = object({
|
|
17096
|
+
id: RecordIdSchema,
|
|
17097
|
+
/** The device this row belongs to (D865 removal, per-device reads). */
|
|
17098
|
+
deviceId: number().int().optional(),
|
|
17099
|
+
/** The domain clock, ms: observed / created / opened. */
|
|
17100
|
+
at: number().int().optional(),
|
|
17101
|
+
/** Producer-set expiry, ms. Refused on a kind whose retention is an engine TTL. */
|
|
17102
|
+
expiresAt: number().int().optional(),
|
|
17103
|
+
data: RecordBodySchema
|
|
17104
|
+
});
|
|
17105
|
+
var RecordViewSchema = object({
|
|
17106
|
+
id: string(),
|
|
17107
|
+
deviceId: number().int().nullable(),
|
|
17108
|
+
at: number().nullable(),
|
|
17109
|
+
expiresAt: number().nullable(),
|
|
17110
|
+
rev: number().int(),
|
|
17111
|
+
updatedAt: number(),
|
|
17112
|
+
data: RecordBodySchema
|
|
17113
|
+
});
|
|
17114
|
+
/** Declared index fields only. Anything else does not compile, by design. */
|
|
17115
|
+
var RecordWhereSchema = record(RecordFieldPathSchema, union([
|
|
17116
|
+
string(),
|
|
17117
|
+
number(),
|
|
17118
|
+
boolean(),
|
|
17119
|
+
object({ in: array(union([
|
|
17120
|
+
string(),
|
|
17121
|
+
number(),
|
|
17122
|
+
boolean()
|
|
17123
|
+
])).min(1).max(RECORD_BATCH_MAX) }),
|
|
17124
|
+
object({
|
|
17125
|
+
gt: union([string(), number()]).optional(),
|
|
17126
|
+
gte: union([string(), number()]).optional(),
|
|
17127
|
+
lt: union([string(), number()]).optional(),
|
|
17128
|
+
lte: union([string(), number()]).optional()
|
|
17129
|
+
}).refine((r) => Object.keys(r).length > 0, { message: "name at least one bound" })
|
|
17130
|
+
]));
|
|
17131
|
+
var KindShape = { kind: RecordKindNameSchema };
|
|
17132
|
+
var TimeWindowShape = {
|
|
17133
|
+
deviceId: number().int().optional(),
|
|
17134
|
+
atFrom: number().optional(),
|
|
17135
|
+
atTo: number().optional()
|
|
17136
|
+
};
|
|
17137
|
+
var RecordQueryInputSchema = object({
|
|
17138
|
+
...KindShape,
|
|
17139
|
+
...TimeWindowShape,
|
|
17140
|
+
where: RecordWhereSchema.optional(),
|
|
17141
|
+
/** Without `where`: `at` (default for a kind with a clock) or `id`. With `where` the order is the index's. */
|
|
17142
|
+
order: _enum(["at", "id"]).optional(),
|
|
17143
|
+
desc: boolean().optional(),
|
|
17144
|
+
limit: number().int().min(1).max(RECORD_QUERY_MAX).default(100),
|
|
17145
|
+
/** Opaque keyset cursor from a previous answer. There is no offset. */
|
|
17146
|
+
cursor: string().min(1).optional()
|
|
17147
|
+
});
|
|
17148
|
+
var RecordQueryResultSchema = object({
|
|
17149
|
+
records: array(RecordViewSchema),
|
|
17150
|
+
nextCursor: string().nullable()
|
|
17151
|
+
});
|
|
17152
|
+
var RecordKindStateSchema = _enum([
|
|
17153
|
+
"created",
|
|
17154
|
+
"unchanged",
|
|
17155
|
+
"updated"
|
|
17156
|
+
]);
|
|
17157
|
+
var DeclareKindResultSchema = object({
|
|
17158
|
+
kindId: number().int(),
|
|
17159
|
+
state: RecordKindStateSchema,
|
|
17160
|
+
createdIndexes: array(string()),
|
|
17161
|
+
/** The boot guard: the kind is empty while its legacy table still holds rows. */
|
|
17162
|
+
adoptionPending: object({
|
|
17163
|
+
legacyTable: string(),
|
|
17164
|
+
legacyRows: number().int()
|
|
17165
|
+
}).nullable()
|
|
17166
|
+
});
|
|
17167
|
+
/** Keychain refs a write released (the old marker is gone from the row): the owner deletes the values. */
|
|
17168
|
+
var SecretRefsList = array(string());
|
|
17169
|
+
var RecordSecretRefsSchema = record(string(), record(string(), string()));
|
|
17170
|
+
method(object({ kinds: record(RecordKindNameSchema, RecordKindDeclarationSchema) }), object({ kinds: record(string(), DeclareKindResultSchema) }), {
|
|
17171
|
+
kind: "mutation",
|
|
17172
|
+
auth: "admin"
|
|
17173
|
+
}), method(object({
|
|
17174
|
+
...KindShape,
|
|
17175
|
+
id: RecordIdSchema
|
|
17176
|
+
}), RecordViewSchema.nullable(), { auth: "admin" }), method(object({
|
|
17177
|
+
...KindShape,
|
|
17178
|
+
ids: array(RecordIdSchema).min(1).max(RECORD_BATCH_MAX)
|
|
17179
|
+
}), array(RecordViewSchema), { auth: "admin" }), method(object({
|
|
17180
|
+
...KindShape,
|
|
17181
|
+
ids: array(RecordIdSchema).min(1).max(RECORD_BATCH_MAX)
|
|
17182
|
+
}), RecordSecretRefsSchema, { auth: "admin" }), method(object({
|
|
17183
|
+
...KindShape,
|
|
17184
|
+
record: RecordInputSchema,
|
|
17185
|
+
/** Compare-and-set. `0` means "the row must not exist". */
|
|
17186
|
+
ifRev: number().int().min(0).optional()
|
|
17187
|
+
}), object({
|
|
17188
|
+
rev: number().int(),
|
|
17189
|
+
releasedRefs: SecretRefsList
|
|
17190
|
+
}), {
|
|
17191
|
+
kind: "mutation",
|
|
17192
|
+
auth: "admin"
|
|
17193
|
+
}), method(object({
|
|
17194
|
+
...KindShape,
|
|
17195
|
+
records: array(RecordInputSchema).min(1).max(RECORD_BATCH_MAX)
|
|
17196
|
+
}), object({
|
|
17197
|
+
count: number().int(),
|
|
17198
|
+
releasedRefs: SecretRefsList
|
|
17199
|
+
}), {
|
|
17200
|
+
kind: "mutation",
|
|
17201
|
+
auth: "admin"
|
|
17202
|
+
}), method(object({
|
|
17203
|
+
...KindShape,
|
|
17204
|
+
id: RecordIdSchema,
|
|
17205
|
+
data: RecordBodySchema,
|
|
17206
|
+
at: number().int().nullable().optional(),
|
|
17207
|
+
expiresAt: number().int().nullable().optional(),
|
|
17208
|
+
ifRev: number().int().min(1).optional()
|
|
17209
|
+
}), object({
|
|
17210
|
+
rev: number().int(),
|
|
17211
|
+
releasedRefs: SecretRefsList
|
|
17212
|
+
}), {
|
|
17213
|
+
kind: "mutation",
|
|
17214
|
+
auth: "admin"
|
|
17215
|
+
}), method(object({
|
|
17216
|
+
...KindShape,
|
|
17217
|
+
id: RecordIdSchema
|
|
17218
|
+
}), object({
|
|
17219
|
+
deleted: boolean(),
|
|
17220
|
+
secretRefs: SecretRefsList
|
|
17221
|
+
}), {
|
|
17222
|
+
kind: "mutation",
|
|
17223
|
+
auth: "admin"
|
|
17224
|
+
}), method(object({
|
|
17225
|
+
...KindShape,
|
|
17226
|
+
ids: array(RecordIdSchema).min(1).max(RECORD_BATCH_MAX)
|
|
17227
|
+
}), object({
|
|
17228
|
+
deleted: number().int(),
|
|
17229
|
+
secretRefs: SecretRefsList
|
|
17230
|
+
}), {
|
|
17231
|
+
kind: "mutation",
|
|
17232
|
+
auth: "admin"
|
|
17233
|
+
}), method(RecordQueryInputSchema, RecordQueryResultSchema, { auth: "admin" }), method(object({
|
|
17234
|
+
...KindShape,
|
|
17235
|
+
...TimeWindowShape,
|
|
17236
|
+
where: RecordWhereSchema.optional()
|
|
17237
|
+
}), object({ count: number().int() }), { auth: "admin" }), method(object({
|
|
17238
|
+
...KindShape,
|
|
17239
|
+
deviceId: number().int().optional(),
|
|
17240
|
+
from: number(),
|
|
17241
|
+
to: number(),
|
|
17242
|
+
bucketMs: number().int().positive()
|
|
17243
|
+
}), object({ buckets: array(object({
|
|
17244
|
+
bucketStart: number(),
|
|
17245
|
+
count: number().int()
|
|
17246
|
+
})) }), { auth: "admin" }), method(object({
|
|
17247
|
+
...KindShape,
|
|
17248
|
+
op: _enum([
|
|
17249
|
+
"sum",
|
|
17250
|
+
"min",
|
|
17251
|
+
"max",
|
|
17252
|
+
"count"
|
|
17253
|
+
]),
|
|
17254
|
+
field: RecordFieldPathSchema.optional(),
|
|
17255
|
+
groupBy: RecordFieldPathSchema.optional(),
|
|
17256
|
+
where: RecordWhereSchema.optional()
|
|
17257
|
+
}), object({ rows: array(object({
|
|
17258
|
+
group: union([
|
|
17259
|
+
string(),
|
|
17260
|
+
number(),
|
|
17261
|
+
_null()
|
|
17262
|
+
]),
|
|
17263
|
+
value: number().nullable()
|
|
17264
|
+
})) }), { auth: "admin" }), method(object({
|
|
17265
|
+
...KindShape,
|
|
17266
|
+
deviceId: number().int().optional(),
|
|
17267
|
+
atBefore: number().optional(),
|
|
17268
|
+
where: RecordWhereSchema.optional()
|
|
17269
|
+
}), object({
|
|
17270
|
+
deleted: number().int(),
|
|
17271
|
+
secretRefs: SecretRefsList
|
|
17272
|
+
}), {
|
|
17273
|
+
kind: "mutation",
|
|
17274
|
+
auth: "admin"
|
|
17275
|
+
}), method(object({
|
|
17276
|
+
deviceId: number().int(),
|
|
17277
|
+
kinds: array(RecordKindNameSchema).optional()
|
|
17278
|
+
}), object({
|
|
17279
|
+
deleted: record(string(), number().int()),
|
|
17280
|
+
secretRefs: SecretRefsList
|
|
17281
|
+
}), {
|
|
17282
|
+
kind: "mutation",
|
|
17283
|
+
auth: "admin"
|
|
17284
|
+
}), method(object(KindShape), object({ id: number().int() }), {
|
|
17285
|
+
kind: "mutation",
|
|
17286
|
+
auth: "admin"
|
|
17287
|
+
});
|
|
17288
|
+
/** One table of the settings database. */
|
|
17289
|
+
var StorageTableSchema = object({
|
|
17290
|
+
/** The table's full name, e.g. `recorder:addon-settings` or `addon-device-settings`. */
|
|
17291
|
+
name: string(),
|
|
17292
|
+
/** The owner prefix of a scoped name (`recorder` for `recorder:addon-settings`), else null. */
|
|
17293
|
+
owner: string().nullable(),
|
|
17294
|
+
rows: number().int().nonnegative(),
|
|
17295
|
+
/** Bytes the table's pages occupy (`dbstat`); null when the engine cannot measure. */
|
|
17296
|
+
bytes: number().int().nonnegative().nullable(),
|
|
17297
|
+
/** Declared by an addon since this engine process started (a running addon claims it). */
|
|
17298
|
+
declaredThisBoot: boolean()
|
|
17299
|
+
});
|
|
17300
|
+
/** One declared record kind (D881) as System -> Data shows it. */
|
|
17301
|
+
var StorageKindSchema = object({
|
|
17302
|
+
owner: string(),
|
|
17303
|
+
kind: string(),
|
|
17304
|
+
database: _enum(["settings", "events"]),
|
|
17305
|
+
class: string(),
|
|
17306
|
+
state: _enum([
|
|
17307
|
+
"declared",
|
|
17308
|
+
"orphaned",
|
|
17309
|
+
"dropped"
|
|
17310
|
+
]),
|
|
17311
|
+
/** `null` when the caller asked for no counts (`counts: false`). */
|
|
17312
|
+
rows: number().int().nonnegative().nullable(),
|
|
17313
|
+
/** Rows x the average size of a sample; null for an empty kind. */
|
|
17314
|
+
bytesEstimate: number().int().nonnegative().nullable(),
|
|
17315
|
+
writeTrigger: string(),
|
|
17316
|
+
retention: RecordRetentionSchema,
|
|
17317
|
+
/** `true` when the kind is an entry kind (the generic entries UI lists it). */
|
|
17318
|
+
entry: boolean(),
|
|
17319
|
+
/** The whole declaration, secret paths and entry descriptor included (the entries service builds its handle from it). */
|
|
17320
|
+
declaration: RecordKindDeclarationSchema
|
|
17321
|
+
});
|
|
17322
|
+
method(object({ ownerPrefix: string().min(1).optional() }), object({ tables: array(StorageTableSchema) }), { auth: "admin" }), method(object({
|
|
17323
|
+
collection: string().min(1),
|
|
17324
|
+
expectRows: number().int().nonnegative()
|
|
17325
|
+
}), object({
|
|
17326
|
+
dropped: literal(true),
|
|
17327
|
+
rows: number().int().nonnegative()
|
|
17328
|
+
}), {
|
|
17329
|
+
kind: "mutation",
|
|
17330
|
+
auth: "admin"
|
|
17331
|
+
}), method(object({
|
|
17332
|
+
owner: string().min(1).optional(),
|
|
17333
|
+
/** `false` skips the per-kind row count (a catalog read only). Default true. */
|
|
17334
|
+
counts: boolean().optional()
|
|
17335
|
+
}), object({ kinds: array(StorageKindSchema) }), { auth: "admin" }), method(RecordQueryInputSchema.extend({
|
|
17336
|
+
owner: string().min(1),
|
|
17337
|
+
kind: RecordKindNameSchema
|
|
17338
|
+
}), RecordQueryResultSchema, { auth: "admin" }), method(object({
|
|
17339
|
+
owner: string().min(1),
|
|
17340
|
+
kind: RecordKindNameSchema,
|
|
17341
|
+
records: array(RecordInputSchema).max(RECORD_BATCH_MAX),
|
|
17342
|
+
/** The LAST batch: the copy is complete, the boot guard stops asking. */
|
|
17343
|
+
complete: boolean().optional()
|
|
17344
|
+
}).refine((input) => input.records.length > 0 || input.complete === true, { message: "records must be non-empty unless complete is true" }), object({ adopted: number().int() }), {
|
|
17345
|
+
kind: "mutation",
|
|
17346
|
+
auth: "admin"
|
|
17347
|
+
}), method(object({
|
|
17348
|
+
collection: string().min(1),
|
|
17349
|
+
cursor: string().optional(),
|
|
17350
|
+
limit: number().int().min(1).max(1e3).optional()
|
|
17351
|
+
}), object({
|
|
17352
|
+
rows: array(object({
|
|
17353
|
+
id: string(),
|
|
17354
|
+
data: record(string(), unknown())
|
|
17355
|
+
})),
|
|
17356
|
+
nextCursor: string().nullable()
|
|
17357
|
+
}), { auth: "admin" }), method(object({ collection: string().min(1) }), object({ adopted: boolean() }), { auth: "admin" });
|
|
17358
|
+
/**
|
|
17359
|
+
* record-entries - the ONE admin surface for every list of user-created entries
|
|
17360
|
+
* (D881): notification targets, brokers, LLM profiles, anything an addon
|
|
17361
|
+
* declares as an ENTRY kind (`entry: { title }` in `defineRecordKinds`).
|
|
17362
|
+
*
|
|
17363
|
+
* The UI is generic. `listEntryKinds` hands it, per kind, the JSON Schema of
|
|
17364
|
+
* the entry body with `secret: true` on every credential field, so a password
|
|
17365
|
+
* field is derived from the schema and never from a name. `putEntry` takes the
|
|
17366
|
+
* redaction token for an untouched secret (the stored value is kept), a string
|
|
17367
|
+
* for a new one, and the clear instruction to remove one. A read never carries
|
|
17368
|
+
* a secret value, and a locked keychain refuses the write with
|
|
17369
|
+
* `records/secret-unavailable` instead of storing plaintext.
|
|
17370
|
+
*
|
|
17371
|
+
* Hub-only, served in-process (it acts for each entry's owner on the keychain).
|
|
17372
|
+
*/
|
|
17373
|
+
var EntryKindInfoSchema = object({
|
|
17374
|
+
owner: string(),
|
|
17375
|
+
kind: RecordKindNameSchema,
|
|
17376
|
+
title: string(),
|
|
17377
|
+
nameField: string(),
|
|
17378
|
+
/** JSON Schema of the body; `secret: true` marks a password field. */
|
|
17379
|
+
fields: record(string(), unknown()),
|
|
17380
|
+
secretPaths: array(string()),
|
|
17381
|
+
rows: number().int().nonnegative()
|
|
17382
|
+
});
|
|
17383
|
+
var EntryViewSchema = object({
|
|
17384
|
+
id: RecordIdSchema,
|
|
17385
|
+
name: string(),
|
|
17386
|
+
rev: number().int(),
|
|
17387
|
+
updatedAt: number(),
|
|
17388
|
+
/** Secret fields hold the redaction token. */
|
|
17389
|
+
data: RecordBodySchema
|
|
17390
|
+
});
|
|
17391
|
+
var EntryAddress = {
|
|
17392
|
+
owner: string().min(1),
|
|
17393
|
+
kind: RecordKindNameSchema
|
|
17394
|
+
};
|
|
17395
|
+
method(object({}), object({ kinds: array(EntryKindInfoSchema) }), { auth: "admin" }), method(object({ ...EntryAddress }), object({ entries: array(EntryViewSchema) }), { auth: "admin" }), method(object({
|
|
17396
|
+
...EntryAddress,
|
|
17397
|
+
id: RecordIdSchema.optional(),
|
|
17398
|
+
data: RecordBodySchema,
|
|
17399
|
+
ifRev: number().int().min(1).optional()
|
|
17400
|
+
}), object({
|
|
17401
|
+
id: string(),
|
|
17402
|
+
rev: number().int()
|
|
17403
|
+
}), {
|
|
17404
|
+
kind: "mutation",
|
|
17405
|
+
auth: "admin"
|
|
17406
|
+
}), method(object({
|
|
17407
|
+
...EntryAddress,
|
|
17408
|
+
id: RecordIdSchema
|
|
17409
|
+
}), object({ deleted: boolean() }), {
|
|
17410
|
+
kind: "mutation",
|
|
17411
|
+
auth: "admin"
|
|
17412
|
+
});
|
|
17413
|
+
/**
|
|
16826
17414
|
* `keychain` — the hub's encrypted store of secret values (D787).
|
|
16827
17415
|
*
|
|
16828
17416
|
* Settings blobs never hold a secret: they hold a marker
|
|
@@ -17363,6 +17951,16 @@ method(object({}), KeychainStatusSchema, { auth: "admin" }), method(object({}),
|
|
|
17363
17951
|
kind: "mutation",
|
|
17364
17952
|
auth: "admin",
|
|
17365
17953
|
caller: "required"
|
|
17954
|
+
}), method(object({
|
|
17955
|
+
ref: string().min(1),
|
|
17956
|
+
value: string().min(1)
|
|
17957
|
+
}), object({
|
|
17958
|
+
ref: string(),
|
|
17959
|
+
version: number().int()
|
|
17960
|
+
}), {
|
|
17961
|
+
kind: "mutation",
|
|
17962
|
+
auth: "admin",
|
|
17963
|
+
caller: "required"
|
|
17366
17964
|
}), method(object({ refs: array(string().min(1)).max(1e3) }), object({
|
|
17367
17965
|
deleted: array(string()).readonly(),
|
|
17368
17966
|
kept: array(object({
|
|
@@ -17771,7 +18369,11 @@ var deviceDiscoveryCapability = {
|
|
|
17771
18369
|
};
|
|
17772
18370
|
/**
|
|
17773
18371
|
* `device-adoption` — generic discovery + adoption surface,
|
|
17774
|
-
* system-scoped
|
|
18372
|
+
* system-scoped collection (one provider per integration addon), routed
|
|
18373
|
+
* by explicit `{ addonId }` on direct `deviceAdoption.*` calls — the same
|
|
18374
|
+
* pin model as `connection-test`. The admin UI keeps using
|
|
18375
|
+
* `deviceManager.adoption*` (which already threads `addonId`). The de-HA-ified
|
|
18376
|
+
* successor to `ha-discovery`:
|
|
17775
18377
|
* keyed by `integrationId` (the addon resolves integrationId → broker
|
|
17776
18378
|
* internally) rather than a connection-specific `brokerId`, and it
|
|
17777
18379
|
* REUSES the shared `DiscoveredChildDevice` candidate type from
|
|
@@ -17936,7 +18538,7 @@ var ResyncResultSchema = object({
|
|
|
17936
18538
|
var deviceAdoptionCapability = {
|
|
17937
18539
|
name: "device-adoption",
|
|
17938
18540
|
scope: "system",
|
|
17939
|
-
mode: "
|
|
18541
|
+
mode: "collection",
|
|
17940
18542
|
status: {
|
|
17941
18543
|
schema: AdoptionStatusSchema,
|
|
17942
18544
|
kind: "poll"
|
|
@@ -40041,6 +40643,9 @@ method(LlmGenerateBaseInputSchema, LlmGenerateResultSchema, {
|
|
|
40041
40643
|
}), _void(), { kind: "mutation" }), method(object({}), array(LlmProfileKindDescriptorSchema)), method(object({}), array(LlmProfileSchema)), method(object({ profile: LlmProfileSchema }), LlmProfileSchema, {
|
|
40042
40644
|
kind: "mutation",
|
|
40043
40645
|
auth: "admin"
|
|
40646
|
+
}), method(RawSecretMigrationInputSchema, RawSecretMigrationReportSchema, {
|
|
40647
|
+
kind: "mutation",
|
|
40648
|
+
auth: "admin"
|
|
40044
40649
|
}), method(ProfileRefInputSchema, _void(), {
|
|
40045
40650
|
kind: "mutation",
|
|
40046
40651
|
auth: "admin"
|
|
@@ -50550,6 +51155,41 @@ var ServerRollbackInfoSchema = object({
|
|
|
50550
51155
|
atMs: number(),
|
|
50551
51156
|
reason: string()
|
|
50552
51157
|
});
|
|
51158
|
+
/**
|
|
51159
|
+
* The runner boot check (D877): the runners this node PLANNED (hub: one per
|
|
51160
|
+
* `resolveRunnerId` over its forked addons; agent: the runners its process
|
|
51161
|
+
* service holds, because only the hub plans) against the states the process
|
|
51162
|
+
* service reports. Kept in memory, recomputed by the same one-shot check after
|
|
51163
|
+
* every boot, served on `getServerPackageStatus`.
|
|
51164
|
+
*
|
|
51165
|
+
* `failed` is the D6 breaker's terminal state, `refused` a deterministic Init
|
|
51166
|
+
* refusal (an addon that said "I will not start, and here is why"), `missing` a
|
|
51167
|
+
* planned runner the process service has no entry for.
|
|
51168
|
+
*/
|
|
51169
|
+
var RunnerRefusalSchema = object({
|
|
51170
|
+
runnerId: string(),
|
|
51171
|
+
addonIds: array(string()),
|
|
51172
|
+
reason: string()
|
|
51173
|
+
});
|
|
51174
|
+
var RunnerBootCheckSchema = object({
|
|
51175
|
+
checkedAtMs: number(),
|
|
51176
|
+
/** Runners planned for this node. */
|
|
51177
|
+
expected: number(),
|
|
51178
|
+
/** Planned runners whose process is `running`. */
|
|
51179
|
+
running: number(),
|
|
51180
|
+
failed: array(string()),
|
|
51181
|
+
refused: array(RunnerRefusalSchema),
|
|
51182
|
+
missing: array(string()),
|
|
51183
|
+
/**
|
|
51184
|
+
* Runners still on their way: `starting`, or `crashed` waiting on a backoff
|
|
51185
|
+
* respawn. The check is FINAL only when this is empty; until then nothing is
|
|
51186
|
+
* pushed and the verdict is re-evaluated on the next runner state change.
|
|
51187
|
+
* Optional for version skew (absent = settled).
|
|
51188
|
+
*/
|
|
51189
|
+
pending: array(string()).optional(),
|
|
51190
|
+
/** True when the plan is the hub's (`missing` is then meaningful); false on an agent. */
|
|
51191
|
+
planKnown: boolean()
|
|
51192
|
+
});
|
|
50553
51193
|
var ServerPackageStatusSchema = object({
|
|
50554
51194
|
/** Root package name (`@camstack/server` on the hub). */
|
|
50555
51195
|
packageName: string(),
|
|
@@ -50612,7 +51252,14 @@ var ServerPackageStatusSchema = object({
|
|
|
50612
51252
|
* for version skew: an older provider's payload simply omits it, and an
|
|
50613
51253
|
* absent wrapper is unknown — never `native`.
|
|
50614
51254
|
*/
|
|
50615
|
-
wrapper: WrapperIdentitySchema.optional()
|
|
51255
|
+
wrapper: WrapperIdentitySchema.optional(),
|
|
51256
|
+
/**
|
|
51257
|
+
* What this node PLANNED to run against what its process service reports
|
|
51258
|
+
* (D877). Absent until the one-shot boot check has run (~60 s after boot) and
|
|
51259
|
+
* on a provider that predates it. Absent is "not checked yet", never "all
|
|
51260
|
+
* well": a consumer that needs the answer treats it as pending.
|
|
51261
|
+
*/
|
|
51262
|
+
runners: RunnerBootCheckSchema.optional()
|
|
50616
51263
|
});
|
|
50617
51264
|
var ServerUpdateCheckResultSchema = object({
|
|
50618
51265
|
packageName: string(),
|
|
@@ -50663,6 +51310,13 @@ var ServerUpdateOutcomeSchema = _enum([
|
|
|
50663
51310
|
"refused",
|
|
50664
51311
|
"failed"
|
|
50665
51312
|
]);
|
|
51313
|
+
/** One addon the pre-flight found the target version would refuse (D877). */
|
|
51314
|
+
var UpdateBlockerSchema = object({
|
|
51315
|
+
addonId: string(),
|
|
51316
|
+
reason: string(),
|
|
51317
|
+
/** What the operator does about it. */
|
|
51318
|
+
remedy: string()
|
|
51319
|
+
});
|
|
50666
51320
|
var ServerUpdateActionResultSchema = object({
|
|
50667
51321
|
accepted: boolean(),
|
|
50668
51322
|
targetVersion: string().nullable(),
|
|
@@ -50680,14 +51334,27 @@ var ServerUpdateActionResultSchema = object({
|
|
|
50680
51334
|
* The failure itself, verbatim enough to act on (the npm output for a
|
|
50681
51335
|
* staging install). Non-null only for `failed`.
|
|
50682
51336
|
*/
|
|
50683
|
-
error: string().nullable().optional()
|
|
51337
|
+
error: string().nullable().optional(),
|
|
51338
|
+
/**
|
|
51339
|
+
* The addons the target version would refuse to start on this node's live
|
|
51340
|
+
* store (D877), present when the pre-flight refused the update
|
|
51341
|
+
* (`reason: 'addon-would-refuse'`). Optional for version skew.
|
|
51342
|
+
*/
|
|
51343
|
+
blockers: array(UpdateBlockerSchema).optional()
|
|
50684
51344
|
});
|
|
50685
51345
|
method(_void(), ServerPackageStatusSchema, { auth: "admin" }), method(_void(), ServerUpdateCheckResultSchema, {
|
|
50686
51346
|
kind: "mutation",
|
|
50687
51347
|
auth: "admin"
|
|
50688
|
-
}), method(object({
|
|
50689
|
-
/** Explicit target version; omitted = latest from the registry. */
|
|
50690
|
-
version: string().optional()
|
|
51348
|
+
}), method(object({
|
|
51349
|
+
/** Explicit target version; omitted = latest from the registry. */
|
|
51350
|
+
version: string().optional(),
|
|
51351
|
+
/**
|
|
51352
|
+
* Apply even though the pre-flight (D877) found addons the target would
|
|
51353
|
+
* refuse to start. Off by default: those addons stay down until the
|
|
51354
|
+
* remedy is run, which is the incident this gate exists to prevent.
|
|
51355
|
+
*/
|
|
51356
|
+
acknowledgeRefusals: boolean().optional()
|
|
51357
|
+
}), ServerUpdateActionResultSchema, {
|
|
50691
51358
|
kind: "mutation",
|
|
50692
51359
|
auth: "admin",
|
|
50693
51360
|
timeoutMs: 16 * 6e4
|
|
@@ -53133,7 +53800,9 @@ var ManifestShapeSchema = object({
|
|
|
53133
53800
|
var AddonProcessSchema = object({
|
|
53134
53801
|
pid: number().optional(),
|
|
53135
53802
|
mode: string(),
|
|
53136
|
-
state: string()
|
|
53803
|
+
state: string(),
|
|
53804
|
+
/** Why the runner is `refused` (an addon's own words), when it is (D877). */
|
|
53805
|
+
reason: string().optional()
|
|
53137
53806
|
});
|
|
53138
53807
|
/**
|
|
53139
53808
|
* Per-addon health snapshot from the kernel's AddonHealthMonitor.
|
|
@@ -53901,7 +54570,8 @@ var batteryCapability = {
|
|
|
53901
54570
|
DeviceType.Button,
|
|
53902
54571
|
DeviceType.Switch,
|
|
53903
54572
|
DeviceType.PetFeeder,
|
|
53904
|
-
DeviceType.Container
|
|
54573
|
+
DeviceType.Container,
|
|
54574
|
+
DeviceType.Thermostat
|
|
53905
54575
|
],
|
|
53906
54576
|
methods: {
|
|
53907
54577
|
/**
|
|
@@ -54522,6 +55192,12 @@ var ClimateControlStatusSchema = object({
|
|
|
54522
55192
|
/** Horizontal louver swing on/off. Null when the device has no
|
|
54523
55193
|
* horizontal swing surface (gate with `DeviceFeature.ClimateSwingHorizontal`). */
|
|
54524
55194
|
swingHorizontal: boolean().nullable(),
|
|
55195
|
+
/** Lowest setpoint the device accepts, Celsius. Absent / null = not reported. */
|
|
55196
|
+
minTemp: number().nullable().optional(),
|
|
55197
|
+
/** Highest setpoint the device accepts, Celsius. Absent / null = not reported. */
|
|
55198
|
+
maxTemp: number().nullable().optional(),
|
|
55199
|
+
/** Setpoint granularity, Celsius (0.5, 1). Absent / null = not reported. */
|
|
55200
|
+
tempStep: number().positive().nullable().optional(),
|
|
54525
55201
|
/** Ms epoch when the slice was last updated (push or command). */
|
|
54526
55202
|
lastFetchedAt: number()
|
|
54527
55203
|
});
|
|
@@ -55376,6 +56052,161 @@ onStatusChanged: { data: object({
|
|
|
55376
56052
|
* whether persisting is worth a SQLite commit. */
|
|
55377
56053
|
volatileStateFields: ["lastChangedAt"]
|
|
55378
56054
|
};
|
|
56055
|
+
/**
|
|
56056
|
+
* Smart-dishwasher cap — program lifecycle, door / remote-start gates,
|
|
56057
|
+
* consumable levels (salt, rinse aid) and common program options.
|
|
56058
|
+
*
|
|
56059
|
+
* Sources: native Bosch Home Connect (`dishwasher` device type). Reusable
|
|
56060
|
+
* by any integration that exposes the same program / option surface.
|
|
56061
|
+
*
|
|
56062
|
+
* `kind: 'poll'` — cloud REST APIs typically have no push channel; the
|
|
56063
|
+
* provider refreshes the slice on an interval and eagerly after commands.
|
|
56064
|
+
*/
|
|
56065
|
+
var DishwasherStateSchema = _enum([
|
|
56066
|
+
"idle",
|
|
56067
|
+
"running",
|
|
56068
|
+
"paused",
|
|
56069
|
+
"finished",
|
|
56070
|
+
"error",
|
|
56071
|
+
"unavailable"
|
|
56072
|
+
]);
|
|
56073
|
+
var DishwasherConsumableLevelSchema = _enum([
|
|
56074
|
+
"ok",
|
|
56075
|
+
"low",
|
|
56076
|
+
"empty"
|
|
56077
|
+
]);
|
|
56078
|
+
var DishwasherStatusSchema = object({
|
|
56079
|
+
state: DishwasherStateSchema,
|
|
56080
|
+
/** Active program id/name, or null when none selected / unknown. */
|
|
56081
|
+
program: string().nullable(),
|
|
56082
|
+
/** Program tokens the hardware accepts — drives the UI selector. */
|
|
56083
|
+
availablePrograms: array(string()),
|
|
56084
|
+
/** Minutes remaining on the active cycle, or null when not running. */
|
|
56085
|
+
remainingMinutes: number().int().nonnegative().nullable(),
|
|
56086
|
+
/** Cycle completion 0..100, or null when not applicable. */
|
|
56087
|
+
progressPercent: number().min(0).max(100).nullable(),
|
|
56088
|
+
/** True when the door is reported open. */
|
|
56089
|
+
doorOpen: boolean(),
|
|
56090
|
+
/** True when remote start is allowed (door closed, power on, etc.). */
|
|
56091
|
+
remoteStartAllowed: boolean(),
|
|
56092
|
+
/** Main power / switched-on state. */
|
|
56093
|
+
powerOn: boolean(),
|
|
56094
|
+
saltLevel: DishwasherConsumableLevelSchema.nullable(),
|
|
56095
|
+
rinseAidLevel: DishwasherConsumableLevelSchema.nullable(),
|
|
56096
|
+
halfLoad: boolean(),
|
|
56097
|
+
hygienePlus: boolean(),
|
|
56098
|
+
/** Extra dry option when the appliance exposes it. */
|
|
56099
|
+
extraDry: boolean(),
|
|
56100
|
+
/** Intensive zone (lower basket) when the appliance exposes it. */
|
|
56101
|
+
intensiveZone: boolean(),
|
|
56102
|
+
/** VarioSpeed / VarioSpeed+ when the appliance exposes it. */
|
|
56103
|
+
varioSpeedPlus: boolean(),
|
|
56104
|
+
/** Child lock (controls disabled on the appliance). */
|
|
56105
|
+
childLock: boolean(),
|
|
56106
|
+
errorCode: number().nullable(),
|
|
56107
|
+
errorLabel: string().nullable(),
|
|
56108
|
+
lastFetchedAt: number()
|
|
56109
|
+
});
|
|
56110
|
+
var dishwasherCapability = {
|
|
56111
|
+
name: "dishwasher",
|
|
56112
|
+
scope: "device",
|
|
56113
|
+
deviceNative: true,
|
|
56114
|
+
mode: "singleton",
|
|
56115
|
+
deviceTypes: [DeviceType.Dishwasher],
|
|
56116
|
+
methods: {
|
|
56117
|
+
start: method(object({ deviceId: number().int().nonnegative() }), _void(), {
|
|
56118
|
+
kind: "mutation",
|
|
56119
|
+
auth: "protected"
|
|
56120
|
+
}),
|
|
56121
|
+
pause: method(object({ deviceId: number().int().nonnegative() }), _void(), {
|
|
56122
|
+
kind: "mutation",
|
|
56123
|
+
auth: "protected"
|
|
56124
|
+
}),
|
|
56125
|
+
stop: method(object({ deviceId: number().int().nonnegative() }), _void(), {
|
|
56126
|
+
kind: "mutation",
|
|
56127
|
+
auth: "protected"
|
|
56128
|
+
}),
|
|
56129
|
+
setProgram: method(object({
|
|
56130
|
+
deviceId: number().int().nonnegative(),
|
|
56131
|
+
program: string().min(1)
|
|
56132
|
+
}), _void(), {
|
|
56133
|
+
kind: "mutation",
|
|
56134
|
+
auth: "protected"
|
|
56135
|
+
}),
|
|
56136
|
+
setPower: method(object({
|
|
56137
|
+
deviceId: number().int().nonnegative(),
|
|
56138
|
+
on: boolean()
|
|
56139
|
+
}), _void(), {
|
|
56140
|
+
kind: "mutation",
|
|
56141
|
+
auth: "protected"
|
|
56142
|
+
}),
|
|
56143
|
+
setHalfLoad: method(object({
|
|
56144
|
+
deviceId: number().int().nonnegative(),
|
|
56145
|
+
on: boolean()
|
|
56146
|
+
}), _void(), {
|
|
56147
|
+
kind: "mutation",
|
|
56148
|
+
auth: "protected"
|
|
56149
|
+
}),
|
|
56150
|
+
setHygienePlus: method(object({
|
|
56151
|
+
deviceId: number().int().nonnegative(),
|
|
56152
|
+
on: boolean()
|
|
56153
|
+
}), _void(), {
|
|
56154
|
+
kind: "mutation",
|
|
56155
|
+
auth: "protected"
|
|
56156
|
+
}),
|
|
56157
|
+
setExtraDry: method(object({
|
|
56158
|
+
deviceId: number().int().nonnegative(),
|
|
56159
|
+
on: boolean()
|
|
56160
|
+
}), _void(), {
|
|
56161
|
+
kind: "mutation",
|
|
56162
|
+
auth: "protected"
|
|
56163
|
+
}),
|
|
56164
|
+
setIntensiveZone: method(object({
|
|
56165
|
+
deviceId: number().int().nonnegative(),
|
|
56166
|
+
on: boolean()
|
|
56167
|
+
}), _void(), {
|
|
56168
|
+
kind: "mutation",
|
|
56169
|
+
auth: "protected"
|
|
56170
|
+
}),
|
|
56171
|
+
setVarioSpeedPlus: method(object({
|
|
56172
|
+
deviceId: number().int().nonnegative(),
|
|
56173
|
+
on: boolean()
|
|
56174
|
+
}), _void(), {
|
|
56175
|
+
kind: "mutation",
|
|
56176
|
+
auth: "protected"
|
|
56177
|
+
}),
|
|
56178
|
+
setChildLock: method(object({
|
|
56179
|
+
deviceId: number().int().nonnegative(),
|
|
56180
|
+
on: boolean()
|
|
56181
|
+
}), _void(), {
|
|
56182
|
+
kind: "mutation",
|
|
56183
|
+
auth: "protected"
|
|
56184
|
+
}),
|
|
56185
|
+
setOption: method(object({
|
|
56186
|
+
deviceId: number().int().nonnegative(),
|
|
56187
|
+
key: string().min(1),
|
|
56188
|
+
value: union([
|
|
56189
|
+
boolean(),
|
|
56190
|
+
string(),
|
|
56191
|
+
number()
|
|
56192
|
+
])
|
|
56193
|
+
}), _void(), {
|
|
56194
|
+
kind: "mutation",
|
|
56195
|
+
auth: "protected"
|
|
56196
|
+
})
|
|
56197
|
+
},
|
|
56198
|
+
status: {
|
|
56199
|
+
schema: DishwasherStatusSchema,
|
|
56200
|
+
kind: "poll"
|
|
56201
|
+
},
|
|
56202
|
+
runtimeState: DishwasherStatusSchema,
|
|
56203
|
+
durability: "session",
|
|
56204
|
+
history: { fields: { progressPercent: {
|
|
56205
|
+
kind: "gauge",
|
|
56206
|
+
unit: "%",
|
|
56207
|
+
deadband: 2
|
|
56208
|
+
} } }
|
|
56209
|
+
};
|
|
55379
56210
|
var DoorbellStatusSchema = object({
|
|
55380
56211
|
/** Ms epoch of the last press. null = never observed since this provider started. */
|
|
55381
56212
|
lastPressedAt: number().nullable(),
|
|
@@ -56178,6 +57009,32 @@ var gasCapability = {
|
|
|
56178
57009
|
* whether persisting is worth a SQLite commit. */
|
|
56179
57010
|
volatileStateFields: ["lastChangedAt"]
|
|
56180
57011
|
};
|
|
57012
|
+
var HeatingValveStatusSchema = object({
|
|
57013
|
+
/** Radiator valve opening 0 (closed) .. 100 (open). Null = not yet known. */
|
|
57014
|
+
position: number().min(0).max(100).nullable(),
|
|
57015
|
+
/** Ms epoch when the slice was last updated (push or poll). */
|
|
57016
|
+
lastFetchedAt: number()
|
|
57017
|
+
});
|
|
57018
|
+
var heatingValveCapability = {
|
|
57019
|
+
name: "heating-valve",
|
|
57020
|
+
scope: "device",
|
|
57021
|
+
deviceNative: true,
|
|
57022
|
+
mode: "singleton",
|
|
57023
|
+
deviceTypes: [DeviceType.Thermostat],
|
|
57024
|
+
methods: {},
|
|
57025
|
+
status: {
|
|
57026
|
+
schema: HeatingValveStatusSchema,
|
|
57027
|
+
kind: "push"
|
|
57028
|
+
},
|
|
57029
|
+
runtimeState: HeatingValveStatusSchema,
|
|
57030
|
+
durability: "session",
|
|
57031
|
+
history: { fields: { position: {
|
|
57032
|
+
kind: "gauge",
|
|
57033
|
+
unit: "%",
|
|
57034
|
+
deadband: 1
|
|
57035
|
+
} } },
|
|
57036
|
+
volatileStateFields: ["lastFetchedAt"]
|
|
57037
|
+
};
|
|
56181
57038
|
/**
|
|
56182
57039
|
* Humidifier / dehumidifier cap. Models HA `humidifier.*` entities —
|
|
56183
57040
|
* an on/off actuator with an optional target-humidity setpoint and an
|
|
@@ -57310,7 +58167,19 @@ var TlsStatusSchema = object({
|
|
|
57310
58167
|
sans: array(string()),
|
|
57311
58168
|
caCertPem: string().nullable(),
|
|
57312
58169
|
reissueError: string().nullable(),
|
|
57313
|
-
restartRequired: boolean()
|
|
58170
|
+
restartRequired: boolean(),
|
|
58171
|
+
/** An uploaded certificate is served but no CA is kept for it and it is not publicly signed (D873). */
|
|
58172
|
+
caMissing: boolean(),
|
|
58173
|
+
/** Does the hub's own generated CA carry a critical name constraint? `null` while it has none. */
|
|
58174
|
+
localCaConstrained: boolean().nullable(),
|
|
58175
|
+
/** ISO time the generated CA was replaced by a constrained one; devices must re-download it. */
|
|
58176
|
+
caReplacedAt: string().nullable(),
|
|
58177
|
+
/** The uploaded certificate kept on disk, selectable again after "Revert to generated". */
|
|
58178
|
+
storedUpload: object({
|
|
58179
|
+
leafFingerprintSha256: string(),
|
|
58180
|
+
validTo: string(),
|
|
58181
|
+
hasCa: boolean()
|
|
58182
|
+
}).nullable()
|
|
57314
58183
|
});
|
|
57315
58184
|
method(_void(), ListResultSchema), method(_void(), PreferredSchema), method(object({
|
|
57316
58185
|
/**
|
|
@@ -57366,6 +58235,9 @@ method(_void(), ListResultSchema), method(_void(), PreferredSchema), method(obje
|
|
|
57366
58235
|
}), method(_void(), object({ pem: string() })), method(_void(), TlsStatusSchema, {
|
|
57367
58236
|
kind: "mutation",
|
|
57368
58237
|
auth: "admin"
|
|
58238
|
+
}), method(_void(), TlsStatusSchema, {
|
|
58239
|
+
kind: "mutation",
|
|
58240
|
+
auth: "admin"
|
|
57369
58241
|
});
|
|
57370
58242
|
var LockControlStatusSchema = object({
|
|
57371
58243
|
/** Lifecycle state of the lock. `jammed` means the motor reported
|
|
@@ -63859,7 +64731,11 @@ method(_void(), array(UserSummarySchema), { auth: "admin" }), method(CreateUserI
|
|
|
63859
64731
|
kind: "mutation",
|
|
63860
64732
|
auth: "admin",
|
|
63861
64733
|
access: "delete"
|
|
63862
|
-
}), method(object({ userId: string() }), TotpStatusSchema, { auth: "admin" }), method(
|
|
64734
|
+
}), method(object({ userId: string() }), TotpStatusSchema, { auth: "admin" }), method(RawSecretMigrationInputSchema, RawSecretMigrationReportSchema, {
|
|
64735
|
+
kind: "mutation",
|
|
64736
|
+
auth: "admin",
|
|
64737
|
+
access: "create"
|
|
64738
|
+
}), method(object({
|
|
63863
64739
|
userId: string(),
|
|
63864
64740
|
code: string()
|
|
63865
64741
|
}), object({ valid: boolean() }), {
|
|
@@ -65579,6 +66455,7 @@ var DEVICE_LOCAL_STATE_CAPS = {
|
|
|
65579
66455
|
dayNight: dayNightCapability,
|
|
65580
66456
|
deviceDiscovery: deviceDiscoveryCapability,
|
|
65581
66457
|
deviceStatus: deviceStatusCapability,
|
|
66458
|
+
dishwasher: dishwasherCapability,
|
|
65582
66459
|
doorbell: doorbellCapability,
|
|
65583
66460
|
enumSensor: enumSensorCapability,
|
|
65584
66461
|
eventEmitter: eventEmitterCapability,
|
|
@@ -65586,6 +66463,7 @@ var DEVICE_LOCAL_STATE_CAPS = {
|
|
|
65586
66463
|
featureProbe: featureProbeCapability,
|
|
65587
66464
|
flood: floodCapability,
|
|
65588
66465
|
gas: gasCapability,
|
|
66466
|
+
heatingValve: heatingValveCapability,
|
|
65589
66467
|
humidifier: humidifierCapability,
|
|
65590
66468
|
humiditySensor: humiditySensorCapability,
|
|
65591
66469
|
image: imageCapability,
|
|
@@ -65671,13 +66549,14 @@ var BaseDevice = class {
|
|
|
65671
66549
|
get state() {
|
|
65672
66550
|
if (!this._stateProxyCache) {
|
|
65673
66551
|
const cache = {};
|
|
65674
|
-
const handler = { get: (
|
|
66552
|
+
const handler = { get: (target, key) => {
|
|
65675
66553
|
const k = key;
|
|
65676
|
-
|
|
66554
|
+
const existing = Reflect.get(target, k);
|
|
66555
|
+
if (existing !== void 0) return existing;
|
|
65677
66556
|
const cap = DEVICE_LOCAL_STATE_CAPS[k];
|
|
65678
66557
|
if (!cap) return void 0;
|
|
65679
66558
|
const proxy = this.sliceProxy(cap);
|
|
65680
|
-
|
|
66559
|
+
Reflect.set(target, k, proxy);
|
|
65681
66560
|
return proxy;
|
|
65682
66561
|
} };
|
|
65683
66562
|
this._stateProxyCache = new Proxy(cache, handler);
|
|
@@ -65876,7 +66755,7 @@ var BaseDevice = class {
|
|
|
65876
66755
|
async updateSourceInfo(patch) {
|
|
65877
66756
|
const next = mergeSourceInfo(this.sourceInfo, patch);
|
|
65878
66757
|
this._sourceInfoCache = Object.freeze({ ...next });
|
|
65879
|
-
const action = this.ctx.api
|
|
66758
|
+
const action = this.ctx.api.deviceManager?.setMetadata;
|
|
65880
66759
|
if (action) try {
|
|
65881
66760
|
await action.mutate({
|
|
65882
66761
|
deviceId: this.id,
|
|
@@ -65911,7 +66790,7 @@ var BaseDevice = class {
|
|
|
65911
66790
|
* device boot on a meta refresh.
|
|
65912
66791
|
*/
|
|
65913
66792
|
async refreshFeatures() {
|
|
65914
|
-
const action = this.ctx.api
|
|
66793
|
+
const action = this.ctx.api.deviceManager?.registerDevice;
|
|
65915
66794
|
if (!action) return;
|
|
65916
66795
|
try {
|
|
65917
66796
|
await action.mutate({
|
|
@@ -66310,6 +67189,12 @@ var BaseDeviceProvider = class extends BaseAddon {
|
|
|
66310
67189
|
provider: this
|
|
66311
67190
|
}];
|
|
66312
67191
|
}
|
|
67192
|
+
/** Flatten `super.onInitialize()` whether it returned an array or an envelope. */
|
|
67193
|
+
providerRegistrationsFromSuper(result) {
|
|
67194
|
+
if (Array.isArray(result)) return result;
|
|
67195
|
+
if (result !== void 0 && result.providers !== void 0) return [...result.providers];
|
|
67196
|
+
return [];
|
|
67197
|
+
}
|
|
66313
67198
|
async onShutdown() {
|
|
66314
67199
|
this._restoreShuttingDown = true;
|
|
66315
67200
|
this.cancelRestoreRetries();
|
|
@@ -66836,7 +67721,7 @@ var BaseDeviceProvider = class extends BaseAddon {
|
|
|
66836
67721
|
return toDeviceSummary(device, this.addonId);
|
|
66837
67722
|
}
|
|
66838
67723
|
};
|
|
66839
|
-
DeviceType.Cover, DeviceType.Valve, DeviceType.Humidifier, DeviceType.WaterHeater, DeviceType.Camera, DeviceType.Hub, DeviceType.Switch, DeviceType.Siren, DeviceType.Light, DeviceType.Fan, DeviceType.Sensor, DeviceType.Thermostat, DeviceType.Climate, DeviceType.Button, DeviceType.EventEmitter, DeviceType.Update, DeviceType.Generic, DeviceType.Notifier, DeviceType.Script, DeviceType.Automation, DeviceType.Lock, DeviceType.MediaPlayer, DeviceType.AlarmPanel, DeviceType.Control, DeviceType.Presence, DeviceType.Weather, DeviceType.Vacuum, DeviceType.LawnMower, DeviceType.Container, DeviceType.Image, DeviceType.PetFeeder;
|
|
67724
|
+
DeviceType.Cover, DeviceType.Valve, DeviceType.Humidifier, DeviceType.WaterHeater, DeviceType.Camera, DeviceType.Hub, DeviceType.Switch, DeviceType.Siren, DeviceType.Light, DeviceType.Fan, DeviceType.Sensor, DeviceType.Thermostat, DeviceType.Climate, DeviceType.Button, DeviceType.EventEmitter, DeviceType.Update, DeviceType.Generic, DeviceType.Notifier, DeviceType.Script, DeviceType.Automation, DeviceType.Lock, DeviceType.MediaPlayer, DeviceType.AlarmPanel, DeviceType.Control, DeviceType.Presence, DeviceType.Weather, DeviceType.Vacuum, DeviceType.LawnMower, DeviceType.Container, DeviceType.Image, DeviceType.PetFeeder, DeviceType.Dishwasher;
|
|
66840
67725
|
new Set(Object.values(DeviceType));
|
|
66841
67726
|
Object.freeze({
|
|
66842
67727
|
"accessories.getStatus": {
|
|
@@ -67985,6 +68870,12 @@ Object.freeze({
|
|
|
67985
68870
|
addonId: null,
|
|
67986
68871
|
access: "view"
|
|
67987
68872
|
},
|
|
68873
|
+
"coreBlocks.migrateRawSecrets": {
|
|
68874
|
+
capName: "core-blocks",
|
|
68875
|
+
capScope: "system",
|
|
68876
|
+
addonId: null,
|
|
68877
|
+
access: "create"
|
|
68878
|
+
},
|
|
67988
68879
|
"coreBlocks.restart": {
|
|
67989
68880
|
capName: "core-blocks",
|
|
67990
68881
|
capScope: "system",
|
|
@@ -69251,6 +70142,84 @@ Object.freeze({
|
|
|
69251
70142
|
addonId: null,
|
|
69252
70143
|
access: "view"
|
|
69253
70144
|
},
|
|
70145
|
+
"dishwasher.getStatus": {
|
|
70146
|
+
capName: "dishwasher",
|
|
70147
|
+
capScope: "device",
|
|
70148
|
+
addonId: null,
|
|
70149
|
+
access: "view"
|
|
70150
|
+
},
|
|
70151
|
+
"dishwasher.pause": {
|
|
70152
|
+
capName: "dishwasher",
|
|
70153
|
+
capScope: "device",
|
|
70154
|
+
addonId: null,
|
|
70155
|
+
access: "create"
|
|
70156
|
+
},
|
|
70157
|
+
"dishwasher.setChildLock": {
|
|
70158
|
+
capName: "dishwasher",
|
|
70159
|
+
capScope: "device",
|
|
70160
|
+
addonId: null,
|
|
70161
|
+
access: "create"
|
|
70162
|
+
},
|
|
70163
|
+
"dishwasher.setExtraDry": {
|
|
70164
|
+
capName: "dishwasher",
|
|
70165
|
+
capScope: "device",
|
|
70166
|
+
addonId: null,
|
|
70167
|
+
access: "create"
|
|
70168
|
+
},
|
|
70169
|
+
"dishwasher.setHalfLoad": {
|
|
70170
|
+
capName: "dishwasher",
|
|
70171
|
+
capScope: "device",
|
|
70172
|
+
addonId: null,
|
|
70173
|
+
access: "create"
|
|
70174
|
+
},
|
|
70175
|
+
"dishwasher.setHygienePlus": {
|
|
70176
|
+
capName: "dishwasher",
|
|
70177
|
+
capScope: "device",
|
|
70178
|
+
addonId: null,
|
|
70179
|
+
access: "create"
|
|
70180
|
+
},
|
|
70181
|
+
"dishwasher.setIntensiveZone": {
|
|
70182
|
+
capName: "dishwasher",
|
|
70183
|
+
capScope: "device",
|
|
70184
|
+
addonId: null,
|
|
70185
|
+
access: "create"
|
|
70186
|
+
},
|
|
70187
|
+
"dishwasher.setOption": {
|
|
70188
|
+
capName: "dishwasher",
|
|
70189
|
+
capScope: "device",
|
|
70190
|
+
addonId: null,
|
|
70191
|
+
access: "create"
|
|
70192
|
+
},
|
|
70193
|
+
"dishwasher.setPower": {
|
|
70194
|
+
capName: "dishwasher",
|
|
70195
|
+
capScope: "device",
|
|
70196
|
+
addonId: null,
|
|
70197
|
+
access: "create"
|
|
70198
|
+
},
|
|
70199
|
+
"dishwasher.setProgram": {
|
|
70200
|
+
capName: "dishwasher",
|
|
70201
|
+
capScope: "device",
|
|
70202
|
+
addonId: null,
|
|
70203
|
+
access: "create"
|
|
70204
|
+
},
|
|
70205
|
+
"dishwasher.setVarioSpeedPlus": {
|
|
70206
|
+
capName: "dishwasher",
|
|
70207
|
+
capScope: "device",
|
|
70208
|
+
addonId: null,
|
|
70209
|
+
access: "create"
|
|
70210
|
+
},
|
|
70211
|
+
"dishwasher.start": {
|
|
70212
|
+
capName: "dishwasher",
|
|
70213
|
+
capScope: "device",
|
|
70214
|
+
addonId: null,
|
|
70215
|
+
access: "create"
|
|
70216
|
+
},
|
|
70217
|
+
"dishwasher.stop": {
|
|
70218
|
+
capName: "dishwasher",
|
|
70219
|
+
capScope: "device",
|
|
70220
|
+
addonId: null,
|
|
70221
|
+
access: "create"
|
|
70222
|
+
},
|
|
69254
70223
|
"doorbell.getStatus": {
|
|
69255
70224
|
capName: "doorbell",
|
|
69256
70225
|
capScope: "device",
|
|
@@ -69461,6 +70430,12 @@ Object.freeze({
|
|
|
69461
70430
|
addonId: null,
|
|
69462
70431
|
access: "view"
|
|
69463
70432
|
},
|
|
70433
|
+
"heatingValve.getStatus": {
|
|
70434
|
+
capName: "heating-valve",
|
|
70435
|
+
capScope: "device",
|
|
70436
|
+
addonId: null,
|
|
70437
|
+
access: "view"
|
|
70438
|
+
},
|
|
69464
70439
|
"humidifier.getStatus": {
|
|
69465
70440
|
capName: "humidifier",
|
|
69466
70441
|
capScope: "device",
|
|
@@ -69671,6 +70646,12 @@ Object.freeze({
|
|
|
69671
70646
|
addonId: null,
|
|
69672
70647
|
access: "create"
|
|
69673
70648
|
},
|
|
70649
|
+
"keychainAdmin.importSecret": {
|
|
70650
|
+
capName: "keychain-admin",
|
|
70651
|
+
capScope: "system",
|
|
70652
|
+
addonId: null,
|
|
70653
|
+
access: "create"
|
|
70654
|
+
},
|
|
69674
70655
|
"keychainAdmin.listAudit": {
|
|
69675
70656
|
capName: "keychain-admin",
|
|
69676
70657
|
capScope: "system",
|
|
@@ -69839,6 +70820,12 @@ Object.freeze({
|
|
|
69839
70820
|
addonId: null,
|
|
69840
70821
|
access: "view"
|
|
69841
70822
|
},
|
|
70823
|
+
"llm.migrateRawSecrets": {
|
|
70824
|
+
capName: "llm",
|
|
70825
|
+
capScope: "system",
|
|
70826
|
+
addonId: null,
|
|
70827
|
+
access: "create"
|
|
70828
|
+
},
|
|
69842
70829
|
"llm.resolveModelRef": {
|
|
69843
70830
|
capName: "llm",
|
|
69844
70831
|
capScope: "system",
|
|
@@ -70067,6 +71054,12 @@ Object.freeze({
|
|
|
70067
71054
|
addonId: null,
|
|
70068
71055
|
access: "create"
|
|
70069
71056
|
},
|
|
71057
|
+
"localNetwork.useStoredUploadedCertificate": {
|
|
71058
|
+
capName: "local-network",
|
|
71059
|
+
capScope: "system",
|
|
71060
|
+
addonId: null,
|
|
71061
|
+
access: "create"
|
|
71062
|
+
},
|
|
70070
71063
|
"lockControl.getStatus": {
|
|
70071
71064
|
capName: "lock-control",
|
|
70072
71065
|
capScope: "device",
|
|
@@ -72719,6 +73712,30 @@ Object.freeze({
|
|
|
72719
73712
|
addonId: null,
|
|
72720
73713
|
access: "create"
|
|
72721
73714
|
},
|
|
73715
|
+
"recordEntries.deleteEntry": {
|
|
73716
|
+
capName: "record-entries",
|
|
73717
|
+
capScope: "system",
|
|
73718
|
+
addonId: null,
|
|
73719
|
+
access: "delete"
|
|
73720
|
+
},
|
|
73721
|
+
"recordEntries.listEntries": {
|
|
73722
|
+
capName: "record-entries",
|
|
73723
|
+
capScope: "system",
|
|
73724
|
+
addonId: null,
|
|
73725
|
+
access: "view"
|
|
73726
|
+
},
|
|
73727
|
+
"recordEntries.listEntryKinds": {
|
|
73728
|
+
capName: "record-entries",
|
|
73729
|
+
capScope: "system",
|
|
73730
|
+
addonId: null,
|
|
73731
|
+
access: "view"
|
|
73732
|
+
},
|
|
73733
|
+
"recordEntries.putEntry": {
|
|
73734
|
+
capName: "record-entries",
|
|
73735
|
+
capScope: "system",
|
|
73736
|
+
addonId: null,
|
|
73737
|
+
access: "create"
|
|
73738
|
+
},
|
|
72722
73739
|
"recording.getAvailability": {
|
|
72723
73740
|
capName: "recording",
|
|
72724
73741
|
capScope: "device",
|
|
@@ -73019,6 +74036,102 @@ Object.freeze({
|
|
|
73019
74036
|
addonId: null,
|
|
73020
74037
|
access: "view"
|
|
73021
74038
|
},
|
|
74039
|
+
"records.aggregate": {
|
|
74040
|
+
capName: "records",
|
|
74041
|
+
capScope: "system",
|
|
74042
|
+
addonId: null,
|
|
74043
|
+
access: "view"
|
|
74044
|
+
},
|
|
74045
|
+
"records.allocateId": {
|
|
74046
|
+
capName: "records",
|
|
74047
|
+
capScope: "system",
|
|
74048
|
+
addonId: null,
|
|
74049
|
+
access: "create"
|
|
74050
|
+
},
|
|
74051
|
+
"records.count": {
|
|
74052
|
+
capName: "records",
|
|
74053
|
+
capScope: "system",
|
|
74054
|
+
addonId: null,
|
|
74055
|
+
access: "view"
|
|
74056
|
+
},
|
|
74057
|
+
"records.declareKinds": {
|
|
74058
|
+
capName: "records",
|
|
74059
|
+
capScope: "system",
|
|
74060
|
+
addonId: null,
|
|
74061
|
+
access: "create"
|
|
74062
|
+
},
|
|
74063
|
+
"records.delete": {
|
|
74064
|
+
capName: "records",
|
|
74065
|
+
capScope: "system",
|
|
74066
|
+
addonId: null,
|
|
74067
|
+
access: "delete"
|
|
74068
|
+
},
|
|
74069
|
+
"records.deleteDevice": {
|
|
74070
|
+
capName: "records",
|
|
74071
|
+
capScope: "system",
|
|
74072
|
+
addonId: null,
|
|
74073
|
+
access: "delete"
|
|
74074
|
+
},
|
|
74075
|
+
"records.deleteMany": {
|
|
74076
|
+
capName: "records",
|
|
74077
|
+
capScope: "system",
|
|
74078
|
+
addonId: null,
|
|
74079
|
+
access: "delete"
|
|
74080
|
+
},
|
|
74081
|
+
"records.deleteWhere": {
|
|
74082
|
+
capName: "records",
|
|
74083
|
+
capScope: "system",
|
|
74084
|
+
addonId: null,
|
|
74085
|
+
access: "delete"
|
|
74086
|
+
},
|
|
74087
|
+
"records.get": {
|
|
74088
|
+
capName: "records",
|
|
74089
|
+
capScope: "system",
|
|
74090
|
+
addonId: null,
|
|
74091
|
+
access: "view"
|
|
74092
|
+
},
|
|
74093
|
+
"records.getMany": {
|
|
74094
|
+
capName: "records",
|
|
74095
|
+
capScope: "system",
|
|
74096
|
+
addonId: null,
|
|
74097
|
+
access: "view"
|
|
74098
|
+
},
|
|
74099
|
+
"records.histogram": {
|
|
74100
|
+
capName: "records",
|
|
74101
|
+
capScope: "system",
|
|
74102
|
+
addonId: null,
|
|
74103
|
+
access: "view"
|
|
74104
|
+
},
|
|
74105
|
+
"records.patch": {
|
|
74106
|
+
capName: "records",
|
|
74107
|
+
capScope: "system",
|
|
74108
|
+
addonId: null,
|
|
74109
|
+
access: "create"
|
|
74110
|
+
},
|
|
74111
|
+
"records.put": {
|
|
74112
|
+
capName: "records",
|
|
74113
|
+
capScope: "system",
|
|
74114
|
+
addonId: null,
|
|
74115
|
+
access: "create"
|
|
74116
|
+
},
|
|
74117
|
+
"records.putMany": {
|
|
74118
|
+
capName: "records",
|
|
74119
|
+
capScope: "system",
|
|
74120
|
+
addonId: null,
|
|
74121
|
+
access: "create"
|
|
74122
|
+
},
|
|
74123
|
+
"records.query": {
|
|
74124
|
+
capName: "records",
|
|
74125
|
+
capScope: "system",
|
|
74126
|
+
addonId: null,
|
|
74127
|
+
access: "view"
|
|
74128
|
+
},
|
|
74129
|
+
"records.secretRefs": {
|
|
74130
|
+
capName: "records",
|
|
74131
|
+
capScope: "system",
|
|
74132
|
+
addonId: null,
|
|
74133
|
+
access: "view"
|
|
74134
|
+
},
|
|
73022
74135
|
"sceneMonitor.captureReference": {
|
|
73023
74136
|
capName: "scene-monitor",
|
|
73024
74137
|
capScope: "device",
|
|
@@ -73451,6 +74564,48 @@ Object.freeze({
|
|
|
73451
74564
|
addonId: null,
|
|
73452
74565
|
access: "create"
|
|
73453
74566
|
},
|
|
74567
|
+
"storageAdmin.adoptRecords": {
|
|
74568
|
+
capName: "storage-admin",
|
|
74569
|
+
capScope: "system",
|
|
74570
|
+
addonId: null,
|
|
74571
|
+
access: "create"
|
|
74572
|
+
},
|
|
74573
|
+
"storageAdmin.dropCollection": {
|
|
74574
|
+
capName: "storage-admin",
|
|
74575
|
+
capScope: "system",
|
|
74576
|
+
addonId: null,
|
|
74577
|
+
access: "delete"
|
|
74578
|
+
},
|
|
74579
|
+
"storageAdmin.isAdoptedLegacyTable": {
|
|
74580
|
+
capName: "storage-admin",
|
|
74581
|
+
capScope: "system",
|
|
74582
|
+
addonId: null,
|
|
74583
|
+
access: "view"
|
|
74584
|
+
},
|
|
74585
|
+
"storageAdmin.listKinds": {
|
|
74586
|
+
capName: "storage-admin",
|
|
74587
|
+
capScope: "system",
|
|
74588
|
+
addonId: null,
|
|
74589
|
+
access: "view"
|
|
74590
|
+
},
|
|
74591
|
+
"storageAdmin.listTables": {
|
|
74592
|
+
capName: "storage-admin",
|
|
74593
|
+
capScope: "system",
|
|
74594
|
+
addonId: null,
|
|
74595
|
+
access: "view"
|
|
74596
|
+
},
|
|
74597
|
+
"storageAdmin.readLegacyCollection": {
|
|
74598
|
+
capName: "storage-admin",
|
|
74599
|
+
capScope: "system",
|
|
74600
|
+
addonId: null,
|
|
74601
|
+
access: "view"
|
|
74602
|
+
},
|
|
74603
|
+
"storageAdmin.readRecords": {
|
|
74604
|
+
capName: "storage-admin",
|
|
74605
|
+
capScope: "system",
|
|
74606
|
+
addonId: null,
|
|
74607
|
+
access: "view"
|
|
74608
|
+
},
|
|
73454
74609
|
"storageEvictable.evict": {
|
|
73455
74610
|
capName: "storage-evictable",
|
|
73456
74611
|
capScope: "system",
|
|
@@ -74363,6 +75518,12 @@ Object.freeze({
|
|
|
74363
75518
|
addonId: null,
|
|
74364
75519
|
access: "view"
|
|
74365
75520
|
},
|
|
75521
|
+
"userManagement.migrateRawSecrets": {
|
|
75522
|
+
capName: "user-management",
|
|
75523
|
+
capScope: "system",
|
|
75524
|
+
addonId: null,
|
|
75525
|
+
access: "create"
|
|
75526
|
+
},
|
|
74366
75527
|
"userManagement.oauthExchangeCode": {
|
|
74367
75528
|
capName: "user-management",
|
|
74368
75529
|
capScope: "system",
|
|
@@ -74862,7 +76023,7 @@ Object.freeze({
|
|
|
74862
76023
|
access: "create"
|
|
74863
76024
|
}
|
|
74864
76025
|
});
|
|
74865
|
-
DeviceType.Camera, DeviceType.Hub, DeviceType.Light, DeviceType.Siren, DeviceType.Switch, DeviceType.Sensor, DeviceType.Thermostat, DeviceType.Climate, DeviceType.Button, DeviceType.EventEmitter, DeviceType.Update, DeviceType.Generic, DeviceType.Notifier, DeviceType.Script, DeviceType.Automation, DeviceType.Lock, DeviceType.Cover, DeviceType.Valve, DeviceType.Humidifier, DeviceType.WaterHeater, DeviceType.Fan, DeviceType.MediaPlayer, DeviceType.AlarmPanel, DeviceType.Control, DeviceType.Presence, DeviceType.Weather, DeviceType.Vacuum, DeviceType.LawnMower, DeviceType.Container, DeviceType.Image, DeviceType.PetFeeder;
|
|
76026
|
+
DeviceType.Camera, DeviceType.Hub, DeviceType.Light, DeviceType.Siren, DeviceType.Switch, DeviceType.Sensor, DeviceType.Thermostat, DeviceType.Climate, DeviceType.Button, DeviceType.EventEmitter, DeviceType.Update, DeviceType.Generic, DeviceType.Notifier, DeviceType.Script, DeviceType.Automation, DeviceType.Lock, DeviceType.Cover, DeviceType.Valve, DeviceType.Humidifier, DeviceType.WaterHeater, DeviceType.Fan, DeviceType.MediaPlayer, DeviceType.AlarmPanel, DeviceType.Control, DeviceType.Presence, DeviceType.Weather, DeviceType.Vacuum, DeviceType.LawnMower, DeviceType.Container, DeviceType.Image, DeviceType.PetFeeder, DeviceType.Dishwasher;
|
|
74866
76027
|
DeviceFeature.BatteryOperated;
|
|
74867
76028
|
Object.freeze({
|
|
74868
76029
|
"accessories.getStatus": [{
|
|
@@ -75686,6 +76847,71 @@ Object.freeze({
|
|
|
75686
76847
|
form: "single",
|
|
75687
76848
|
optional: false
|
|
75688
76849
|
}],
|
|
76850
|
+
"dishwasher.getStatus": [{
|
|
76851
|
+
name: "deviceId",
|
|
76852
|
+
form: "single",
|
|
76853
|
+
optional: false
|
|
76854
|
+
}],
|
|
76855
|
+
"dishwasher.pause": [{
|
|
76856
|
+
name: "deviceId",
|
|
76857
|
+
form: "single",
|
|
76858
|
+
optional: false
|
|
76859
|
+
}],
|
|
76860
|
+
"dishwasher.setChildLock": [{
|
|
76861
|
+
name: "deviceId",
|
|
76862
|
+
form: "single",
|
|
76863
|
+
optional: false
|
|
76864
|
+
}],
|
|
76865
|
+
"dishwasher.setExtraDry": [{
|
|
76866
|
+
name: "deviceId",
|
|
76867
|
+
form: "single",
|
|
76868
|
+
optional: false
|
|
76869
|
+
}],
|
|
76870
|
+
"dishwasher.setHalfLoad": [{
|
|
76871
|
+
name: "deviceId",
|
|
76872
|
+
form: "single",
|
|
76873
|
+
optional: false
|
|
76874
|
+
}],
|
|
76875
|
+
"dishwasher.setHygienePlus": [{
|
|
76876
|
+
name: "deviceId",
|
|
76877
|
+
form: "single",
|
|
76878
|
+
optional: false
|
|
76879
|
+
}],
|
|
76880
|
+
"dishwasher.setIntensiveZone": [{
|
|
76881
|
+
name: "deviceId",
|
|
76882
|
+
form: "single",
|
|
76883
|
+
optional: false
|
|
76884
|
+
}],
|
|
76885
|
+
"dishwasher.setOption": [{
|
|
76886
|
+
name: "deviceId",
|
|
76887
|
+
form: "single",
|
|
76888
|
+
optional: false
|
|
76889
|
+
}],
|
|
76890
|
+
"dishwasher.setPower": [{
|
|
76891
|
+
name: "deviceId",
|
|
76892
|
+
form: "single",
|
|
76893
|
+
optional: false
|
|
76894
|
+
}],
|
|
76895
|
+
"dishwasher.setProgram": [{
|
|
76896
|
+
name: "deviceId",
|
|
76897
|
+
form: "single",
|
|
76898
|
+
optional: false
|
|
76899
|
+
}],
|
|
76900
|
+
"dishwasher.setVarioSpeedPlus": [{
|
|
76901
|
+
name: "deviceId",
|
|
76902
|
+
form: "single",
|
|
76903
|
+
optional: false
|
|
76904
|
+
}],
|
|
76905
|
+
"dishwasher.start": [{
|
|
76906
|
+
name: "deviceId",
|
|
76907
|
+
form: "single",
|
|
76908
|
+
optional: false
|
|
76909
|
+
}],
|
|
76910
|
+
"dishwasher.stop": [{
|
|
76911
|
+
name: "deviceId",
|
|
76912
|
+
form: "single",
|
|
76913
|
+
optional: false
|
|
76914
|
+
}],
|
|
75689
76915
|
"doorbell.getStatus": [{
|
|
75690
76916
|
name: "deviceId",
|
|
75691
76917
|
form: "single",
|
|
@@ -75755,6 +76981,11 @@ Object.freeze({
|
|
|
75755
76981
|
form: "single",
|
|
75756
76982
|
optional: false
|
|
75757
76983
|
}],
|
|
76984
|
+
"heatingValve.getStatus": [{
|
|
76985
|
+
name: "deviceId",
|
|
76986
|
+
form: "single",
|
|
76987
|
+
optional: false
|
|
76988
|
+
}],
|
|
75758
76989
|
"humidifier.getStatus": [{
|
|
75759
76990
|
name: "deviceId",
|
|
75760
76991
|
form: "single",
|
|
@@ -77039,6 +78270,37 @@ Object.freeze({
|
|
|
77039
78270
|
form: "single",
|
|
77040
78271
|
optional: false
|
|
77041
78272
|
}],
|
|
78273
|
+
"records.count": [{
|
|
78274
|
+
name: "deviceId",
|
|
78275
|
+
form: "single",
|
|
78276
|
+
optional: true
|
|
78277
|
+
}],
|
|
78278
|
+
"records.deleteDevice": [{
|
|
78279
|
+
name: "deviceId",
|
|
78280
|
+
form: "single",
|
|
78281
|
+
optional: false
|
|
78282
|
+
}],
|
|
78283
|
+
"records.deleteWhere": [{
|
|
78284
|
+
name: "deviceId",
|
|
78285
|
+
form: "single",
|
|
78286
|
+
optional: true
|
|
78287
|
+
}],
|
|
78288
|
+
"records.histogram": [{
|
|
78289
|
+
name: "deviceId",
|
|
78290
|
+
form: "single",
|
|
78291
|
+
optional: true
|
|
78292
|
+
}],
|
|
78293
|
+
"records.putMany": [{
|
|
78294
|
+
name: "records",
|
|
78295
|
+
form: "object-array",
|
|
78296
|
+
optional: false,
|
|
78297
|
+
itemField: "deviceId"
|
|
78298
|
+
}],
|
|
78299
|
+
"records.query": [{
|
|
78300
|
+
name: "deviceId",
|
|
78301
|
+
form: "single",
|
|
78302
|
+
optional: true
|
|
78303
|
+
}],
|
|
77042
78304
|
"sceneMonitor.captureReference": [{
|
|
77043
78305
|
name: "deviceId",
|
|
77044
78306
|
form: "single",
|
|
@@ -77155,6 +78417,17 @@ Object.freeze({
|
|
|
77155
78417
|
form: "single",
|
|
77156
78418
|
optional: false
|
|
77157
78419
|
}],
|
|
78420
|
+
"storageAdmin.adoptRecords": [{
|
|
78421
|
+
name: "records",
|
|
78422
|
+
form: "object-array",
|
|
78423
|
+
optional: false,
|
|
78424
|
+
itemField: "deviceId"
|
|
78425
|
+
}],
|
|
78426
|
+
"storageAdmin.readRecords": [{
|
|
78427
|
+
name: "deviceId",
|
|
78428
|
+
form: "single",
|
|
78429
|
+
optional: true
|
|
78430
|
+
}],
|
|
77158
78431
|
"streamBroker.acquireEgressTranscode": [{
|
|
77159
78432
|
name: "deviceId",
|
|
77160
78433
|
form: "single",
|
|
@@ -80021,7 +81294,7 @@ var TuyaProviderAddon = class extends BaseDeviceProvider {
|
|
|
80021
81294
|
super({});
|
|
80022
81295
|
}
|
|
80023
81296
|
async onInitialize() {
|
|
80024
|
-
const regs = await super.onInitialize();
|
|
81297
|
+
const regs = this.providerRegistrationsFromSuper(await super.onInitialize());
|
|
80025
81298
|
this.clients = new TuyaClientRegistry(this.ctx.logger, tuyaConnections);
|
|
80026
81299
|
this.clients.setOnConnected((integrationId) => {
|
|
80027
81300
|
this.ctx.logger.info("Tuya: integration connected", { meta: { integrationId } });
|