@camstack/addon-mqtt-broker 1.2.154 → 1.2.156
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/CHANGELOG.md +12 -0
- package/dist/mqtt-broker.addon.js +944 -1009
- package/dist/mqtt-broker.addon.mjs +944 -1009
- package/package.json +2 -2
|
@@ -39,7 +39,7 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
|
|
|
39
39
|
var __toCommonJS = (mod) => __hasOwnProp.call(mod, "module.exports") ? mod["module.exports"] : __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
40
40
|
var __require = /* @__PURE__ */ createRequire(import.meta.url);
|
|
41
41
|
//#endregion
|
|
42
|
-
//#region ../types/dist/event-category-
|
|
42
|
+
//#region ../types/dist/event-category-78tcBemo.mjs
|
|
43
43
|
var EventCategory = /* @__PURE__ */ function(EventCategory) {
|
|
44
44
|
EventCategory["SystemBoot"] = "system.boot";
|
|
45
45
|
EventCategory["SystemAddonsReady"] = "system.addons-ready";
|
|
@@ -160,6 +160,23 @@ var EventCategory = /* @__PURE__ */ function(EventCategory) {
|
|
|
160
160
|
*/
|
|
161
161
|
EventCategory["AddonLoadRecovered"] = "addon.load-recovered";
|
|
162
162
|
/**
|
|
163
|
+
* An addon is RUNNING although its installed package is below what the
|
|
164
|
+
* running server requires (`camstack.requires.addons` of the server, or the
|
|
165
|
+
* addon's own `requires.server`). Raised once per streak by the unsupported-
|
|
166
|
+
* addon tracker, on the hub and on agents; AlertCenter turns it into one
|
|
167
|
+
* operator alert per node and package. The addon is never held back for it.
|
|
168
|
+
*
|
|
169
|
+
* Payload: `{ packageName, addonId, nodeId, installedVersion, requiredMinimum, serverVersion, unmet }`.
|
|
170
|
+
*/
|
|
171
|
+
EventCategory["AddonUnsupportedVersion"] = "addon.unsupported-version";
|
|
172
|
+
/**
|
|
173
|
+
* The package of an {@link AddonUnsupportedVersion} alert reached a supported
|
|
174
|
+
* version, or is no longer installed on the node. AlertCenter dismisses the matching alert.
|
|
175
|
+
*
|
|
176
|
+
* Payload: `{ packageName, addonId, nodeId }`.
|
|
177
|
+
*/
|
|
178
|
+
EventCategory["AddonUnsupportedResolved"] = "addon.unsupported-resolved";
|
|
179
|
+
/**
|
|
163
180
|
* Monitor scheduled the next retry for a failed addon. Transient —
|
|
164
181
|
* surfaced to the UI for live-updating the "next retry in Ns"
|
|
165
182
|
* countdown on the Addons page row, NOT persisted as an alert.
|
|
@@ -270,7 +287,7 @@ var EventCategory = /* @__PURE__ */ function(EventCategory) {
|
|
|
270
287
|
EventCategory["ProcessRestarted"] = "process.restarted";
|
|
271
288
|
/**
|
|
272
289
|
* The SET of storage locations changed — one was created, edited, enabled,
|
|
273
|
-
* disabled or deleted through
|
|
290
|
+
* disabled or deleted through the location instances or the forced-delete action.
|
|
274
291
|
*
|
|
275
292
|
* Telemetry, not a transaction (D8/D11): every consumer that re-resolves on
|
|
276
293
|
* it must also converge on its own periodic path, because a dropped event
|
|
@@ -825,7 +842,7 @@ var EventCategory = /* @__PURE__ */ function(EventCategory) {
|
|
|
825
842
|
return EventCategory;
|
|
826
843
|
}({});
|
|
827
844
|
//#endregion
|
|
828
|
-
//#region ../types/dist/device-type-
|
|
845
|
+
//#region ../types/dist/device-type-DxCT0krO.mjs
|
|
829
846
|
/**
|
|
830
847
|
import { errMsg } from '@camstack/types'
|
|
831
848
|
* Extract a human-readable message from an unknown error value.
|
|
@@ -987,6 +1004,13 @@ var DeviceFeature = /* @__PURE__ */ function(DeviceFeature) {
|
|
|
987
1004
|
* filters that want "all devices with on-motion behaviour".
|
|
988
1005
|
*/
|
|
989
1006
|
DeviceFeature["MotionTrigger"] = "motion-trigger";
|
|
1007
|
+
/**
|
|
1008
|
+
* Device can be run for a chosen time and then stopped. Mirrors the
|
|
1009
|
+
* `timed-run` wrapper cap — the cap is bound by the core-blocks addon, not by
|
|
1010
|
+
* a driver, so the flag is derived from the device's bindings
|
|
1011
|
+
* (`featuresOfBoundCaps`). Gates the quick-run control in the viewer.
|
|
1012
|
+
*/
|
|
1013
|
+
DeviceFeature["TimedRun"] = "timed-run";
|
|
990
1014
|
/** Light supports rgb-triplet color via `color` cap. */
|
|
991
1015
|
DeviceFeature["LightColorRgb"] = "light-color-rgb";
|
|
992
1016
|
/** Light supports HSV color via `color` cap. */
|
|
@@ -6021,7 +6045,7 @@ var ZodIssueCode = {
|
|
|
6021
6045
|
var ZodFirstPartyTypeKind;
|
|
6022
6046
|
ZodFirstPartyTypeKind || (ZodFirstPartyTypeKind = {});
|
|
6023
6047
|
//#endregion
|
|
6024
|
-
//#region ../types/dist/sleep-
|
|
6048
|
+
//#region ../types/dist/sleep-7El4r5Bl.mjs
|
|
6025
6049
|
/**
|
|
6026
6050
|
* The audio chunk plane's byte format, and the ONE expansion from a coded
|
|
6027
6051
|
* window to float samples (D455).
|
|
@@ -6385,6 +6409,59 @@ Object.fromEntries([
|
|
|
6385
6409
|
function isValuelessField(field) {
|
|
6386
6410
|
return field.type === "separator" || field.type === "info" || field.type === "qr-code" || field.type === "button" || field.type === "object-array" || field.type === "widget" || field.type === "addon-action-button" || field.type === "device-action-button" || field.type === "account-sign-in" || field.type === "secret-presence";
|
|
6387
6411
|
}
|
|
6412
|
+
/**
|
|
6413
|
+
* Base collector: flatten a hydrated `ConfigUISchemaWithValues` into
|
|
6414
|
+
* `key → { value, default }`, recursing through `group` and `sub-tabs`
|
|
6415
|
+
* layout fields. Keeping `value` and `default` SEPARATE (rather than
|
|
6416
|
+
* pre-resolving) lets callers both read the effective value AND detect
|
|
6417
|
+
* overrides (`value` differs from `default`). Structural over `unknown`;
|
|
6418
|
+
* malformed input yields an empty map, never throws.
|
|
6419
|
+
*/
|
|
6420
|
+
function collectHydratedFieldEntries(schema) {
|
|
6421
|
+
const out = /* @__PURE__ */ new Map();
|
|
6422
|
+
if (typeof schema !== "object" || schema === null) return out;
|
|
6423
|
+
const sections = schema.sections;
|
|
6424
|
+
if (!Array.isArray(sections)) return out;
|
|
6425
|
+
for (const section of sections) if (typeof section === "object" && section !== null) collectFieldEntriesInto(section.fields, out);
|
|
6426
|
+
return out;
|
|
6427
|
+
}
|
|
6428
|
+
/** Recursive field walker for {@link collectHydratedFieldEntries}. */
|
|
6429
|
+
function collectFieldEntriesInto(fields, into) {
|
|
6430
|
+
if (!Array.isArray(fields)) return;
|
|
6431
|
+
for (const field of fields) {
|
|
6432
|
+
if (typeof field !== "object" || field === null) continue;
|
|
6433
|
+
const type = field.type;
|
|
6434
|
+
if (type === "group") {
|
|
6435
|
+
collectFieldEntriesInto(field.fields, into);
|
|
6436
|
+
continue;
|
|
6437
|
+
}
|
|
6438
|
+
if (type === "sub-tabs") {
|
|
6439
|
+
const tabs = field.tabs;
|
|
6440
|
+
if (Array.isArray(tabs)) {
|
|
6441
|
+
for (const tab of tabs) if (typeof tab === "object" && tab !== null) collectFieldEntriesInto(tab.fields, into);
|
|
6442
|
+
}
|
|
6443
|
+
continue;
|
|
6444
|
+
}
|
|
6445
|
+
const key = field.key;
|
|
6446
|
+
if (typeof key !== "string" || key.length === 0) continue;
|
|
6447
|
+
if (!("value" in field)) continue;
|
|
6448
|
+
into.set(key, {
|
|
6449
|
+
value: field.value,
|
|
6450
|
+
default: field.default
|
|
6451
|
+
});
|
|
6452
|
+
}
|
|
6453
|
+
}
|
|
6454
|
+
/**
|
|
6455
|
+
* Flatten a hydrated settings payload into `key → EFFECTIVE value`
|
|
6456
|
+
* (`value ?? default`). The read-side inverse of `hydrateSchema` for the
|
|
6457
|
+
* common "just give me the resolved values" case. Built on
|
|
6458
|
+
* {@link collectHydratedFieldEntries}.
|
|
6459
|
+
*/
|
|
6460
|
+
function collectHydratedFieldValues(schema) {
|
|
6461
|
+
const out = /* @__PURE__ */ new Map();
|
|
6462
|
+
for (const [key, entry] of collectHydratedFieldEntries(schema)) out.set(key, entry.value ?? entry.default);
|
|
6463
|
+
return out;
|
|
6464
|
+
}
|
|
6388
6465
|
function hydrateSchema(schema, values, options = {}) {
|
|
6389
6466
|
return {
|
|
6390
6467
|
...schema.tabs ? { tabs: [...schema.tabs] } : {},
|
|
@@ -6730,10 +6807,33 @@ function integrationRowsApiOver(api) {
|
|
|
6730
6807
|
};
|
|
6731
6808
|
}
|
|
6732
6809
|
var PREFIX = "records/";
|
|
6810
|
+
/**
|
|
6811
|
+
* Cross-realm brand. An addon bundles its own copy of this module (D15) while
|
|
6812
|
+
* `ctx.records` is the HOST's door, so an error thrown by the host is an
|
|
6813
|
+
* instance of the host's classes, not of the addon's. The brand plus the code
|
|
6814
|
+
* make `instanceof` answer by identity of the failure, not of the copy.
|
|
6815
|
+
*/
|
|
6816
|
+
var RECORDS_ERROR_BRAND = Symbol.for("camstack.records-error");
|
|
6817
|
+
function carriesBrand(value) {
|
|
6818
|
+
return typeof value === "object" && value !== null && Reflect.get(value, RECORDS_ERROR_BRAND) === true;
|
|
6819
|
+
}
|
|
6733
6820
|
/** The base of every records failure. `detail` is the human part of the message. */
|
|
6734
6821
|
var RecordsError = class extends Error {
|
|
6822
|
+
/** The code a subclass stands for; the base stands for every code. */
|
|
6823
|
+
static code = void 0;
|
|
6824
|
+
/**
|
|
6825
|
+
* `instanceof` across copies of this module: any branded error is a
|
|
6826
|
+
* `RecordsError`, and is an instance of a subclass only when its code is the
|
|
6827
|
+
* subclass's code. Same-copy answers are unchanged.
|
|
6828
|
+
*/
|
|
6829
|
+
static [Symbol.hasInstance](value) {
|
|
6830
|
+
if (Function.prototype[Symbol.hasInstance].call(this, value)) return true;
|
|
6831
|
+
if (!carriesBrand(value)) return false;
|
|
6832
|
+
return this.code === void 0 || value.code === this.code;
|
|
6833
|
+
}
|
|
6735
6834
|
code;
|
|
6736
6835
|
detail;
|
|
6836
|
+
[RECORDS_ERROR_BRAND] = true;
|
|
6737
6837
|
constructor(code, detail) {
|
|
6738
6838
|
super(`${PREFIX}${code}: ${detail}`);
|
|
6739
6839
|
this.name = "RecordsError";
|
|
@@ -6742,22 +6842,25 @@ var RecordsError = class extends Error {
|
|
|
6742
6842
|
}
|
|
6743
6843
|
};
|
|
6744
6844
|
/** The keychain could not store or serve a value: explicit, never an empty string. */
|
|
6745
|
-
var RecordSecretUnavailableError = class extends RecordsError {
|
|
6845
|
+
var RecordSecretUnavailableError = class RecordSecretUnavailableError extends RecordsError {
|
|
6846
|
+
static code = "secret-unavailable";
|
|
6746
6847
|
constructor(detail) {
|
|
6747
|
-
super(
|
|
6848
|
+
super(RecordSecretUnavailableError.code, detail);
|
|
6748
6849
|
this.name = "RecordSecretUnavailableError";
|
|
6749
6850
|
}
|
|
6750
6851
|
};
|
|
6751
|
-
var InvalidRecordError = class extends RecordsError {
|
|
6852
|
+
var InvalidRecordError = class InvalidRecordError extends RecordsError {
|
|
6853
|
+
static code = "invalid-record";
|
|
6752
6854
|
constructor(detail) {
|
|
6753
|
-
super(
|
|
6855
|
+
super(InvalidRecordError.code, detail);
|
|
6754
6856
|
this.name = "InvalidRecordError";
|
|
6755
6857
|
}
|
|
6756
6858
|
};
|
|
6757
6859
|
/** A kind declaration the engine refuses (non-additive change, bad shape, wrong file). */
|
|
6758
|
-
var DeclarationRefusedError = class extends RecordsError {
|
|
6860
|
+
var DeclarationRefusedError = class DeclarationRefusedError extends RecordsError {
|
|
6861
|
+
static code = "declaration-refused";
|
|
6759
6862
|
constructor(detail) {
|
|
6760
|
-
super(
|
|
6863
|
+
super(DeclarationRefusedError.code, detail);
|
|
6761
6864
|
this.name = "DeclarationRefusedError";
|
|
6762
6865
|
}
|
|
6763
6866
|
};
|
|
@@ -7235,17 +7338,35 @@ var RecordIntegrationInstances = class {
|
|
|
7235
7338
|
...kind !== void 0 ? { kind } : {}
|
|
7236
7339
|
});
|
|
7237
7340
|
if (minted === void 0) throw new Error("createInstance needs an id: this provider does not mint one");
|
|
7341
|
+
const initial = this.hooks.initialBody(name, kind);
|
|
7342
|
+
const patch = this.patchOf(values ?? {});
|
|
7343
|
+
if (Object.keys(patch).length > 0) Object.assign(patch, await this.hooks.validateWrite?.({
|
|
7344
|
+
kind,
|
|
7345
|
+
body: {
|
|
7346
|
+
...initial,
|
|
7347
|
+
...patch
|
|
7348
|
+
}
|
|
7349
|
+
}));
|
|
7238
7350
|
await this.handle.put({
|
|
7239
7351
|
id: minted,
|
|
7240
|
-
data:
|
|
7352
|
+
data: initial
|
|
7241
7353
|
}, { ifRev: 0 });
|
|
7242
|
-
const patch = this.patchOf(values ?? {});
|
|
7243
7354
|
if (Object.keys(patch).length > 0) await this.handle.patch(minted, patch);
|
|
7244
7355
|
await this.hooks.onChanged?.(minted, "created");
|
|
7245
7356
|
return { id: minted };
|
|
7246
7357
|
};
|
|
7247
7358
|
updateInstance = async ({ id, name, values }) => {
|
|
7248
7359
|
const patch = this.patchOf(values);
|
|
7360
|
+
if (this.hooks.validateWrite !== void 0 && Object.keys(patch).length > 0) {
|
|
7361
|
+
const stored = await this.handle.get(id);
|
|
7362
|
+
if (stored !== null) Object.assign(patch, await this.hooks.validateWrite({
|
|
7363
|
+
kind: void 0,
|
|
7364
|
+
body: {
|
|
7365
|
+
...stored.data,
|
|
7366
|
+
...patch
|
|
7367
|
+
}
|
|
7368
|
+
}));
|
|
7369
|
+
}
|
|
7249
7370
|
if (name !== void 0) patch[this.nameField] = name;
|
|
7250
7371
|
await this.handle.patch(id, patch);
|
|
7251
7372
|
await this.hooks.onChanged?.(id, "updated");
|
|
@@ -7556,6 +7677,21 @@ var SCOPED_SETTINGS_SCOPES = [
|
|
|
7556
7677
|
"device-defaults",
|
|
7557
7678
|
"node"
|
|
7558
7679
|
];
|
|
7680
|
+
/** The one refusal of a key a scope did not declare. */
|
|
7681
|
+
function assertDeclaredKeys(keys, declared) {
|
|
7682
|
+
const undeclared = keys.filter((key) => !declared.has(key));
|
|
7683
|
+
if (undeclared.length > 0) throw new Error(`scoped settings: [${undeclared.join(", ")}] not declared for this scope (declared: [${[...declared].join(", ")}])`);
|
|
7684
|
+
}
|
|
7685
|
+
/** Build the handle over an addon's scoped read, write and unset. */
|
|
7686
|
+
function createScopedSettings(deps) {
|
|
7687
|
+
return {
|
|
7688
|
+
async get() {
|
|
7689
|
+
return deps.schema.parse(await deps.read());
|
|
7690
|
+
},
|
|
7691
|
+
patch: (patch) => deps.write(Object.fromEntries(Object.entries(patch))),
|
|
7692
|
+
unset: (keys) => deps.unset(keys)
|
|
7693
|
+
};
|
|
7694
|
+
}
|
|
7559
7695
|
/** A write to a secret path could not be stored in the keychain, so it was refused. */
|
|
7560
7696
|
var KeychainWriteRefusedError = class extends Error {
|
|
7561
7697
|
fieldPath;
|
|
@@ -8131,7 +8267,16 @@ function createHandle(raw, opts) {
|
|
|
8131
8267
|
return blob;
|
|
8132
8268
|
}
|
|
8133
8269
|
},
|
|
8134
|
-
writeAddonStore: writeAddon
|
|
8270
|
+
writeAddonStore: writeAddon,
|
|
8271
|
+
removeClearedKeys: (keys) => serialize("addon", async () => {
|
|
8272
|
+
const stored = await readStoredAddonBlob(raw);
|
|
8273
|
+
index.seen("addon", stored);
|
|
8274
|
+
const removable = keys.filter((key) => collectSecretMarkerRefs(stored[key]).length === 0);
|
|
8275
|
+
if (removable.length === 0) return;
|
|
8276
|
+
const patch = Object.fromEntries(removable.map((key) => [key, void 0]));
|
|
8277
|
+
await raw.writeAddonStore(patch);
|
|
8278
|
+
index.wrote("addon", patch);
|
|
8279
|
+
})
|
|
8135
8280
|
};
|
|
8136
8281
|
}
|
|
8137
8282
|
/** The context the addon sees, plus the private raw view and write outcome. */
|
|
@@ -8261,7 +8406,7 @@ function boundOf(list) {
|
|
|
8261
8406
|
* Base class for CamStack addons. Eliminates settings boilerplate:
|
|
8262
8407
|
*
|
|
8263
8408
|
* - Typed `config` property with automatic resolution from store + defaults
|
|
8264
|
-
* -
|
|
8409
|
+
* - the scoped settings API (`clusterSettings` / `nodeSettings` / `deviceDefaults`) auto-implemented
|
|
8265
8410
|
* - `getAddonSettings()` / `updateAddonSettings()` auto-implemented
|
|
8266
8411
|
* - `getDeviceSettings()` / `updateDeviceSettings()` auto-implemented
|
|
8267
8412
|
* - `ctx` accessor for the AddonContext (no manual `this.ctxRef` storage)
|
|
@@ -8271,7 +8416,7 @@ function boundOf(list) {
|
|
|
8271
8416
|
* Subclasses override:
|
|
8272
8417
|
* - `onInitialize()` — addon-specific init logic, return ProviderRegistration[]
|
|
8273
8418
|
* - `onShutdown()` — cleanup
|
|
8274
|
-
* - `
|
|
8419
|
+
* - `clusterSettingsSchema()` / `nodeSettingsSchema()` / `deviceSettingsSchema()` — UI schemas
|
|
8275
8420
|
*
|
|
8276
8421
|
* @example
|
|
8277
8422
|
* ```ts
|
|
@@ -8285,7 +8430,7 @@ function boundOf(list) {
|
|
|
8285
8430
|
* super({ maxRetries: 3, endpoint: 'http://localhost' })
|
|
8286
8431
|
* }
|
|
8287
8432
|
*
|
|
8288
|
-
* protected
|
|
8433
|
+
* protected clusterSettingsSchema() {
|
|
8289
8434
|
* return this.schema({
|
|
8290
8435
|
* sections: [{
|
|
8291
8436
|
* id: 'main', title: 'Settings',
|
|
@@ -8328,7 +8473,7 @@ var BaseAddon = class {
|
|
|
8328
8473
|
defaults;
|
|
8329
8474
|
/**
|
|
8330
8475
|
* Hidden-state paths that hold secrets (D787) — values the addon writes
|
|
8331
|
-
* itself (`
|
|
8476
|
+
* itself (`state()`, the scoped writers) that no form field declares.
|
|
8332
8477
|
* Stored in the keychain exactly like a `password` field. Syntax:
|
|
8333
8478
|
* `'snapshotSigningKey'`, `'identity.pincode'`, `'tokens[userId].accessToken'`
|
|
8334
8479
|
* (`key[<id field>]` addresses array items by id, never by index).
|
|
@@ -8338,7 +8483,7 @@ var BaseAddon = class {
|
|
|
8338
8483
|
/**
|
|
8339
8484
|
* D986 M4: the scoped schemas this addon declared, resolved once per capability
|
|
8340
8485
|
* (`loadScopedSchemas`) so the sync readers (`perNodeKeys`, the secret tree, the restart check)
|
|
8341
|
-
* see them. Empty until loaded
|
|
8486
|
+
* see them. Empty until loaded.
|
|
8342
8487
|
*/
|
|
8343
8488
|
_scopedByCap = /* @__PURE__ */ new Map();
|
|
8344
8489
|
_nodeKeysByCap = /* @__PURE__ */ new Map();
|
|
@@ -8524,7 +8669,7 @@ var BaseAddon = class {
|
|
|
8524
8669
|
/** Addon-specific cleanup. Override if needed. */
|
|
8525
8670
|
async onShutdown() {}
|
|
8526
8671
|
/**
|
|
8527
|
-
* Called after config is resolved during
|
|
8672
|
+
* Called after config is resolved during a settings write.
|
|
8528
8673
|
* Override to react to config changes (e.g. restart a sampler, reconnect a service).
|
|
8529
8674
|
* Not called during initialize() — use onInitialize() for initial setup.
|
|
8530
8675
|
*/
|
|
@@ -8553,82 +8698,12 @@ var BaseAddon = class {
|
|
|
8553
8698
|
scopedSettingsCapabilities() {
|
|
8554
8699
|
return [];
|
|
8555
8700
|
}
|
|
8556
|
-
/** Override to provide global-level settings UI schema. */
|
|
8557
|
-
globalSettingsSchema(_cap) {
|
|
8558
|
-
return null;
|
|
8559
|
-
}
|
|
8560
8701
|
/** Override to provide device-level settings UI schema. */
|
|
8561
8702
|
deviceSettingsSchema() {
|
|
8562
8703
|
return null;
|
|
8563
8704
|
}
|
|
8564
8705
|
/**
|
|
8565
|
-
*
|
|
8566
|
-
* ARE the configuration of its integration.
|
|
8567
|
-
*
|
|
8568
|
-
* Return the `ConfigSection.id`s, from {@link globalSettingsSchema}, that an
|
|
8569
|
-
* operator should find on the addon's integration page (System →
|
|
8570
|
-
* Integrations → <name>) rather than only in the cluster-wide list of every
|
|
8571
|
-
* addon. Empty (the default) means the addon has no integration-level
|
|
8572
|
-
* settings and no such surface is offered — this is opt-in, because whether
|
|
8573
|
-
* an addon's configuration IS its integration's configuration depends on the
|
|
8574
|
-
* nature of the integration.
|
|
8575
|
-
*
|
|
8576
|
-
* WHAT THIS IS NOT. It is not a scope. The selected sections keep living in
|
|
8577
|
-
* the ONE global schema, in the ONE addon store, written by the ONE
|
|
8578
|
-
* `updateGlobalSettings` path. There is deliberately no
|
|
8579
|
-
* `updateIntegrationSettings`: a second write path is how a surface acquires
|
|
8580
|
-
* a second store key, and this repo has shipped that twice (`btmPath@hub`,
|
|
8581
|
-
* D266). Selecting sections cannot introduce a key that selecting cannot.
|
|
8582
|
-
*
|
|
8583
|
-
* WHY IT IS A LIST OF SECTION IDS AND NOT A MARKER ON THE SECTION.
|
|
8584
|
-
* `ConfigFieldBase` used to carry `scope?: 'device' | 'global'` and it was
|
|
8585
|
-
* removed with the reason recorded at
|
|
8586
|
-
* `packages/types/src/interfaces/config-ui.ts:249` — *"a field's scope is
|
|
8587
|
-
* determined by WHICH schema it lives in, not by a field-level marker."* A
|
|
8588
|
-
* marker sprinkled across sections also has to borrow a field that already
|
|
8589
|
-
* means something else; borrowing `section.tab` put the literal word
|
|
8590
|
-
* "integration" into an operator-facing tab bar, because `tab` means "how to
|
|
8591
|
-
* GROUP this visually" and cannot also mean "where this lives" (D269
|
|
8592
|
-
* supersedes D268). One declaration, in one place, next to the schema whose
|
|
8593
|
-
* ids it names.
|
|
8594
|
-
*/
|
|
8595
|
-
integrationSettingSections() {
|
|
8596
|
-
return [];
|
|
8597
|
-
}
|
|
8598
|
-
async getGlobalSettings(overlay, cap, nodeId) {
|
|
8599
|
-
await this.loadScopedSchemas(cap);
|
|
8600
|
-
const schema = this.globalSettingsSchema(cap) ?? this.scopedFormSchema(cap);
|
|
8601
|
-
if (!schema) return { sections: [] };
|
|
8602
|
-
const projected = await this.readRawProjectedStore(nodeId, cap);
|
|
8603
|
-
return hydrateSchema(schema, overlay ? await this.overlayKeepingMarkers(projected, overlay) : projected, { inlineSecretsAsViews: true });
|
|
8604
|
-
}
|
|
8605
|
-
/**
|
|
8606
|
-
* The integration-level view of this addon's settings: exactly the sections
|
|
8607
|
-
* named by {@link integrationSettingSections}, hydrated from the SAME store
|
|
8608
|
-
* `getGlobalSettings` reads, and narrowed to cluster-scoped fields.
|
|
8609
|
-
*
|
|
8610
|
-
* Returns `null` when the addon declared nothing — an addon that opts out has
|
|
8611
|
-
* no integration settings surface at all, rather than an empty one that reads
|
|
8612
|
-
* as a failed load.
|
|
8613
|
-
*
|
|
8614
|
-
* Three properties hold BY CONSTRUCTION, which is why they are here in core
|
|
8615
|
-
* and not in whichever UI happens to render this:
|
|
8616
|
-
*
|
|
8617
|
-
* 1. **One key.** The payload is a SUBSET of the global schema, so a field
|
|
8618
|
-
* shown here is the same field, with the same bare key, that the addon's
|
|
8619
|
-
* own page shows. There is no integration-specific writer — callers save
|
|
8620
|
-
* through `updateGlobalSettings` — so a second store key is unreachable,
|
|
8621
|
-
* not merely discouraged.
|
|
8622
|
-
* 2. **No node scope.** `perNode: true` fields are DROPPED. Their store key
|
|
8623
|
-
* is `<key>@<nodeId>` and an integration is not a node; whichever node
|
|
8624
|
-
* such a field silently picked would be a wrong answer for the operator
|
|
8625
|
-
* who opened the page (D266).
|
|
8626
|
-
* 3. **No silent typo.** A declared id that names no section throws. The
|
|
8627
|
-
* alternative — skip it — turns a rename into a surface that quietly
|
|
8628
|
-
* empties, which looks exactly like an addon with nothing to configure.
|
|
8629
|
-
*/
|
|
8630
|
-
/**
|
|
8631
|
-
* The form schema of ONE integration instance, or `null` to use {@link globalSettingsSchema}.
|
|
8706
|
+
* The form schema of ONE integration instance, or `null` to use the scoped form.
|
|
8632
8707
|
*
|
|
8633
8708
|
* Override it only when an `instanceMode: multiple` addon's instances differ: an NVR integration
|
|
8634
8709
|
* needs its connection fields, the default integration the addon's own sections. It is the
|
|
@@ -8676,37 +8751,178 @@ var BaseAddon = class {
|
|
|
8676
8751
|
}
|
|
8677
8752
|
}
|
|
8678
8753
|
/**
|
|
8754
|
+
* Hook: values layered over the stored ones when the FORM of one scope is served
|
|
8755
|
+
* ({@link getScopedSettings}) — a preview that derives dependent options without writing.
|
|
8756
|
+
* Never applied to {@link ScopedSettings.get} or to a write. `null` ⇒ no overlay.
|
|
8757
|
+
*/
|
|
8758
|
+
async scopedSettingsOverlay(_scope, _cap, _nodeId) {
|
|
8759
|
+
return null;
|
|
8760
|
+
}
|
|
8761
|
+
/**
|
|
8762
|
+
* Hook: a write of one scope changed stored values (not called when the store reports no change,
|
|
8763
|
+
* e.g. the write-back of a stored secret). `keys` are the bare field keys of the write, node keys included.
|
|
8764
|
+
*/
|
|
8765
|
+
async onScopedSettingsChanged(_scope, _cap, _keys) {}
|
|
8766
|
+
/** Typed handle over the CLUSTER settings `cap` declares (`clusterSettingsSchema`). */
|
|
8767
|
+
clusterSettings(cap, schema) {
|
|
8768
|
+
return this.scopedHandle("cluster", cap, schema);
|
|
8769
|
+
}
|
|
8770
|
+
/** Typed handle over the fleet defaults of the per-device settings `cap` declares. */
|
|
8771
|
+
deviceDefaults(cap, schema) {
|
|
8772
|
+
return this.scopedHandle("device-defaults", cap, schema);
|
|
8773
|
+
}
|
|
8774
|
+
/**
|
|
8775
|
+
* Typed handle over the settings `cap` owns PER NODE. `nodeId` omitted ⇒ the local node. A node
|
|
8776
|
+
* with no row yields the schema defaults — never a bare-key fallback.
|
|
8777
|
+
*/
|
|
8778
|
+
nodeSettings(cap, schema, nodeId) {
|
|
8779
|
+
return this.scopedHandle("node", cap, schema, nodeId);
|
|
8780
|
+
}
|
|
8781
|
+
/**
|
|
8782
|
+
* {@link state} for a value that is kept per node: stored under `<key>@<nodeId>`, and the
|
|
8783
|
+
* settings store carries `nodeId` in the row data (D986 §1), so a forgotten node's rows go in one
|
|
8784
|
+
* central delete. `nodeId` omitted ⇒ the local node.
|
|
8785
|
+
*/
|
|
8786
|
+
nodeState(key, schema, fallback, nodeId) {
|
|
8787
|
+
this._declaredStateKeys.add(key);
|
|
8788
|
+
return createDurableState({
|
|
8789
|
+
key: nodeScopedKey(key, nodeId ?? this._ctx?.kernel?.localNodeId ?? ""),
|
|
8790
|
+
schema,
|
|
8791
|
+
fallback,
|
|
8792
|
+
read: async () => this.resolveStoredSecrets(await this.readAddonStoreWithRetry()),
|
|
8793
|
+
write: async (patch) => {
|
|
8794
|
+
await this._ctx?.settings?.writeAddonStore(patch);
|
|
8795
|
+
},
|
|
8796
|
+
onParseError: (k, e) => this._ctx?.logger?.warn?.(`durable-state: stored "${k}" failed validation — using fallback`, { meta: {
|
|
8797
|
+
addonId: this._ctx?.id,
|
|
8798
|
+
key: k,
|
|
8799
|
+
error: String(e)
|
|
8800
|
+
} })
|
|
8801
|
+
});
|
|
8802
|
+
}
|
|
8803
|
+
/** The loaded schema `cap` declares for `scope`, or `null`. */
|
|
8804
|
+
async declaredScopedSchema(scope, cap) {
|
|
8805
|
+
await this.loadScopedSchemas(cap);
|
|
8806
|
+
return this.loadedScopedSchemas(cap).find((entry) => entry.scope === scope)?.schema ?? null;
|
|
8807
|
+
}
|
|
8808
|
+
async requireScopedSchema(scope, cap) {
|
|
8809
|
+
const schema = await this.declaredScopedSchema(scope, cap);
|
|
8810
|
+
if (schema === null) throw new Error(`${this.constructor.name}: cap "${cap}" declares no ${scope} settings`);
|
|
8811
|
+
return schema;
|
|
8812
|
+
}
|
|
8813
|
+
scopedKeys(schema) {
|
|
8814
|
+
return new Set(schema.sections.flatMap((section) => collectValueFieldKeys(section.fields)));
|
|
8815
|
+
}
|
|
8816
|
+
/** `store` narrowed to the keys `schema` declares. */
|
|
8817
|
+
narrowToScope(store, schema) {
|
|
8818
|
+
const keys = this.scopedKeys(schema);
|
|
8819
|
+
return Object.fromEntries(Object.entries(store).filter(([key]) => keys.has(key)));
|
|
8820
|
+
}
|
|
8821
|
+
scopedHandle(scope, cap, schema, nodeId) {
|
|
8822
|
+
return createScopedSettings({
|
|
8823
|
+
schema,
|
|
8824
|
+
read: async () => {
|
|
8825
|
+
const declared = await this.requireScopedSchema(scope, cap);
|
|
8826
|
+
const stored = this.narrowToScope(await this.resolveGlobalStore(nodeId, cap), declared);
|
|
8827
|
+
const effective = collectHydratedFieldValues(hydrateSchema(declared, stored));
|
|
8828
|
+
return {
|
|
8829
|
+
...Object.fromEntries([...effective].filter(([, value]) => value !== void 0)),
|
|
8830
|
+
...stored
|
|
8831
|
+
};
|
|
8832
|
+
},
|
|
8833
|
+
write: (patch) => this.writeScoped(scope, cap, patch, nodeId),
|
|
8834
|
+
unset: (keys) => this.unsetScoped(scope, cap, keys, nodeId)
|
|
8835
|
+
});
|
|
8836
|
+
}
|
|
8837
|
+
/** The one write path of the scoped API: declared keys only, then the global patch. */
|
|
8838
|
+
async writeScoped(scope, cap, patch, nodeId) {
|
|
8839
|
+
assertDeclaredKeys(Object.keys(patch), this.scopedKeys(await this.requireScopedSchema(scope, cap)));
|
|
8840
|
+
if (await this.applyGlobalPatch(patch, scope === "node" ? nodeId : void 0, cap)) await this.onScopedSettingsChanged(scope, cap, Object.keys(patch));
|
|
8841
|
+
}
|
|
8842
|
+
/**
|
|
8843
|
+
* Remove declared keys of one scope. A secret goes through {@link clearSecrets} — its keychain
|
|
8844
|
+
* value is released exactly as there — and the emptied row is then removed; every other key is
|
|
8845
|
+
* removed by an `undefined` patch (which a secret transform would read as "keep").
|
|
8846
|
+
*/
|
|
8847
|
+
async unsetScoped(scope, cap, keys, nodeId) {
|
|
8848
|
+
assertDeclaredKeys(keys, this.scopedKeys(await this.requireScopedSchema(scope, cap)));
|
|
8849
|
+
const target = scope === "node" ? nodeId : void 0;
|
|
8850
|
+
const tree = this.addonSecretTree();
|
|
8851
|
+
const secretKeys = keys.filter((key) => tree.has(key));
|
|
8852
|
+
const plainKeys = keys.filter((key) => !tree.has(key));
|
|
8853
|
+
let changed = false;
|
|
8854
|
+
if (plainKeys.length > 0) {
|
|
8855
|
+
const patch = Object.fromEntries(plainKeys.map((key) => [key, void 0]));
|
|
8856
|
+
changed = await this.applyGlobalPatch(patch, target, cap) || changed;
|
|
8857
|
+
}
|
|
8858
|
+
if (secretKeys.length > 0) {
|
|
8859
|
+
await this.clearSecretKeys(secretKeys, target, cap);
|
|
8860
|
+
const node = normalizeNodeId(target ?? this._ctx?.kernel?.localNodeId);
|
|
8861
|
+
const rows = secretKeys.map((key) => scope === "node" ? nodeScopedKey(key, node) : key);
|
|
8862
|
+
if (this._secretSettings !== null) await this._secretSettings.removeClearedKeys(rows);
|
|
8863
|
+
else await this._ctx?.settings?.writeAddonStore(Object.fromEntries(rows.map((row) => [row, void 0])));
|
|
8864
|
+
changed = true;
|
|
8865
|
+
}
|
|
8866
|
+
if (changed) await this.onScopedSettingsChanged(scope, cap, [...keys]);
|
|
8867
|
+
}
|
|
8868
|
+
/**
|
|
8869
|
+
* The hydrated form of one scope of one capability's settings (any
|
|
8870
|
+
* {@link scopedSettingsOverlay} applied), or `null` when the capability declares nothing there.
|
|
8871
|
+
*/
|
|
8872
|
+
async getScopedSettings(scope, cap, nodeId) {
|
|
8873
|
+
const schema = await this.declaredScopedSchema(scope, cap);
|
|
8874
|
+
if (schema === null) return null;
|
|
8875
|
+
const stored = this.narrowToScope(await this.readRawProjectedStore(nodeId, cap), schema);
|
|
8876
|
+
const overlay = await this.scopedSettingsOverlay(scope, cap, nodeId);
|
|
8877
|
+
return hydrateSchema(schema, overlay ? await this.overlayKeepingMarkers(stored, overlay) : stored, { inlineSecretsAsViews: true });
|
|
8878
|
+
}
|
|
8879
|
+
/**
|
|
8880
|
+
* The scoped schemas this addon serves: one entry per loaded (capability, scope), capabilities
|
|
8881
|
+
* in declaration order, scopes in {@link SCOPED_SETTINGS_SCOPES} order. `[]` when it declares
|
|
8882
|
+
* nothing.
|
|
8883
|
+
*/
|
|
8884
|
+
async listScopedSettings() {
|
|
8885
|
+
await this.loadScopedSchemas();
|
|
8886
|
+
return [...this._scopedByCap].flatMap(([cap, entries]) => entries.map((entry) => ({
|
|
8887
|
+
cap,
|
|
8888
|
+
scope: entry.scope,
|
|
8889
|
+
sectionIds: entry.schema.sections.map((section) => section.id)
|
|
8890
|
+
})));
|
|
8891
|
+
}
|
|
8892
|
+
/** The OPERATOR's write of declared keys of one scope (D787 secret semantics). */
|
|
8893
|
+
async updateScopedSettings(scope, cap, patch, nodeId) {
|
|
8894
|
+
this._operatorWriteDepth++;
|
|
8895
|
+
try {
|
|
8896
|
+
await this.writeScoped(scope, cap, patch, nodeId);
|
|
8897
|
+
} finally {
|
|
8898
|
+
this._operatorWriteDepth--;
|
|
8899
|
+
}
|
|
8900
|
+
}
|
|
8901
|
+
/**
|
|
8902
|
+
* The effective values (`stored ?? default`) of one scope, a secret as its `set` view — never
|
|
8903
|
+
* its value. `null` when the capability declares nothing for the scope.
|
|
8904
|
+
*/
|
|
8905
|
+
async readScopedValues(scope, cap, nodeId) {
|
|
8906
|
+
const schema = await this.declaredScopedSchema(scope, cap);
|
|
8907
|
+
if (schema === null) return null;
|
|
8908
|
+
const form = hydrateSchema(schema, this.narrowToScope(await this.readRawProjectedStore(nodeId, cap), schema), { inlineSecretsAsViews: true });
|
|
8909
|
+
return Object.fromEntries([...collectHydratedFieldValues(form)].filter(([, value]) => value !== void 0));
|
|
8910
|
+
}
|
|
8911
|
+
/**
|
|
8679
8912
|
* What the create wizard and the integration edit page render for one instance: the addon's
|
|
8680
8913
|
* per-instance schema when it declares one, else its global schema (what they always showed).
|
|
8681
8914
|
*/
|
|
8682
8915
|
async getIntegrationFormSchema(instance, nodeId) {
|
|
8683
8916
|
const scoped = await this.integrationFormSchema(instance);
|
|
8684
|
-
if (scoped === null) return this.
|
|
8917
|
+
if (scoped === null) return this.scopedForm(nodeId);
|
|
8685
8918
|
return hydrateSchema(scoped, {}, { inlineSecretsAsViews: true });
|
|
8686
8919
|
}
|
|
8687
|
-
|
|
8688
|
-
|
|
8689
|
-
|
|
8690
|
-
const schema = this.
|
|
8691
|
-
if (!schema)
|
|
8692
|
-
|
|
8693
|
-
const sections = [];
|
|
8694
|
-
for (const id of declared) {
|
|
8695
|
-
const section = byId.get(id);
|
|
8696
|
-
if (!section) throw new Error(`${this.constructor.name}: integrationSettingSections() names unknown section "${id}". Known sections: [${[...byId.keys()].join(", ")}].`);
|
|
8697
|
-
const fields = dropPerNodeFields(section.fields);
|
|
8698
|
-
if (fields.length === 0) continue;
|
|
8699
|
-
sections.push({
|
|
8700
|
-
...section,
|
|
8701
|
-
fields
|
|
8702
|
-
});
|
|
8703
|
-
}
|
|
8704
|
-
if (sections.length === 0) return null;
|
|
8705
|
-
const projected = await this.readRawProjectedStore(nodeId);
|
|
8706
|
-
return hydrateSchema({
|
|
8707
|
-
...schema,
|
|
8708
|
-
sections
|
|
8709
|
-
}, projected, { inlineSecretsAsViews: true });
|
|
8920
|
+
/** The form of the scoped schemas this addon declared, hydrated from its store. */
|
|
8921
|
+
async scopedForm(nodeId) {
|
|
8922
|
+
await this.loadScopedSchemas();
|
|
8923
|
+
const schema = this.scopedFormSchema();
|
|
8924
|
+
if (!schema) return { sections: [] };
|
|
8925
|
+
return hydrateSchema(schema, await this.readRawProjectedStore(nodeId), { inlineSecretsAsViews: true });
|
|
8710
8926
|
}
|
|
8711
8927
|
/**
|
|
8712
8928
|
* The raw addon store PROJECTED onto the target node's bare per-node keys:
|
|
@@ -8715,8 +8931,8 @@ var BaseAddon = class {
|
|
|
8715
8931
|
* bare fallback), all `@`-scoped and stray bare per-node keys are dropped.
|
|
8716
8932
|
* A no-op passthrough when the schema declares no `perNode` field.
|
|
8717
8933
|
*
|
|
8718
|
-
* This is the sanctioned way for
|
|
8719
|
-
* the store for custom
|
|
8934
|
+
* This is the sanctioned way for an addon that needs
|
|
8935
|
+
* the store for custom logic (option narrowing, value snapping) to
|
|
8720
8936
|
* read it per-node — never `ctx.settings.readAddonStore()` directly.
|
|
8721
8937
|
* `nodeId` omitted ⇒ the local node (node-blind injection from ctx).
|
|
8722
8938
|
*
|
|
@@ -8768,7 +8984,7 @@ var BaseAddon = class {
|
|
|
8768
8984
|
}
|
|
8769
8985
|
/**
|
|
8770
8986
|
* Whether ONE global key of this addon's store was written, read three-way
|
|
8771
|
-
* (D651). For a question a hydrated view cannot answer:
|
|
8987
|
+
* (D651). For a question a hydrated view cannot answer: a hydrated form
|
|
8772
8988
|
* reports `value ?? default`, so "the operator chose the default" and "nobody
|
|
8773
8989
|
* chose" look the same, and a failed read looks like both. A `perNode` key is
|
|
8774
8990
|
* not supported here: its stored name is scoped.
|
|
@@ -8802,7 +9018,7 @@ var BaseAddon = class {
|
|
|
8802
9018
|
}
|
|
8803
9019
|
/**
|
|
8804
9020
|
* The OPERATOR's write — a settings form or an admin API call, dispatched by
|
|
8805
|
-
* the kernel.
|
|
9021
|
+
* the kernel. The one in-process write of the addon blob that is not a scoped write; a secret
|
|
8806
9022
|
* the operator sends is stored as sent even when it equals a pre-keychain
|
|
8807
9023
|
* inline value: the operator re-entering a password is a change, an addon
|
|
8808
9024
|
* writing back what it read is not (D787).
|
|
@@ -8815,9 +9031,6 @@ var BaseAddon = class {
|
|
|
8815
9031
|
this._operatorWriteDepth--;
|
|
8816
9032
|
}
|
|
8817
9033
|
}
|
|
8818
|
-
async updateGlobalSettings(patch, nodeId) {
|
|
8819
|
-
await this.applyGlobalPatch(patch, nodeId);
|
|
8820
|
-
}
|
|
8821
9034
|
/**
|
|
8822
9035
|
* REMOVE stored secrets — their keychain values and their markers (D787).
|
|
8823
9036
|
*
|
|
@@ -8827,6 +9040,9 @@ var BaseAddon = class {
|
|
|
8827
9040
|
* a keychain (an older kernel) it writes `''`, as such code always did.
|
|
8828
9041
|
*/
|
|
8829
9042
|
async clearSecrets(keys, nodeId) {
|
|
9043
|
+
await this.clearSecretKeys(keys, nodeId);
|
|
9044
|
+
}
|
|
9045
|
+
async clearSecretKeys(keys, nodeId, cap) {
|
|
8830
9046
|
const tree = this.addonSecretTree();
|
|
8831
9047
|
const keychain = this._ctx?.secrets !== void 0;
|
|
8832
9048
|
const stored = keychain ? await this.readAddonStoreWithRetry() : {};
|
|
@@ -8839,25 +9055,26 @@ var BaseAddon = class {
|
|
|
8839
9055
|
const keychainStored = tree.has(key) || collectSecretMarkerRefs(stored[key]).length > 0;
|
|
8840
9056
|
patch[key] = keychain && keychainStored ? SECRET_CLEAR : "";
|
|
8841
9057
|
}
|
|
8842
|
-
await this.applyGlobalPatch(patch, nodeId);
|
|
9058
|
+
await this.applyGlobalPatch(patch, nodeId, cap);
|
|
8843
9059
|
}
|
|
8844
|
-
|
|
8845
|
-
|
|
8846
|
-
|
|
9060
|
+
/** Resolves `true` when the write changed stored values. */
|
|
9061
|
+
async applyGlobalPatch(barePatch, nodeId, cap) {
|
|
9062
|
+
await this.loadScopedSchemas(cap);
|
|
9063
|
+
const keys = this.perNodeKeys(cap);
|
|
8847
9064
|
const localNode = normalizeNodeId(this._ctx?.kernel?.localNodeId);
|
|
8848
9065
|
const target = normalizeNodeId(nodeId ?? this._ctx?.kernel?.localNodeId);
|
|
8849
9066
|
const scoped = keys.size > 0 ? scopePatch(barePatch, keys, target) : barePatch;
|
|
8850
9067
|
const handle = this._secretSettings;
|
|
8851
9068
|
if (handle !== null) {
|
|
8852
9069
|
const { changed } = await handle.writeAddonStore(scoped);
|
|
8853
|
-
if (!changed) return;
|
|
9070
|
+
if (!changed) return false;
|
|
8854
9071
|
} else await this._ctx?.settings?.writeAddonStore(scoped);
|
|
8855
|
-
if (target !== localNode) return;
|
|
9072
|
+
if (target !== localNode) return true;
|
|
8856
9073
|
await this.resolveConfig();
|
|
8857
9074
|
await this.onConfigChanged();
|
|
8858
9075
|
this.emitLifecycle(EventCategory.AddonUpdated, { level: "global" });
|
|
8859
|
-
|
|
8860
|
-
|
|
9076
|
+
this.maybeAutoRestart(Object.keys(barePatch), this.loadedScopedSchemas().map((entry) => entry.schema));
|
|
9077
|
+
return true;
|
|
8861
9078
|
}
|
|
8862
9079
|
/**
|
|
8863
9080
|
* The set of field keys the global settings schema declares `perNode: true`
|
|
@@ -8894,10 +9111,7 @@ var BaseAddon = class {
|
|
|
8894
9111
|
this._nodeKeysByCap = /* @__PURE__ */ new Map();
|
|
8895
9112
|
this._addonSecretTree = null;
|
|
8896
9113
|
}
|
|
8897
|
-
/**
|
|
8898
|
-
* The form the settings API serves while an addon declares no {@link globalSettingsSchema}: the
|
|
8899
|
-
* sections of its scoped schemas, so dropping the old hook does not blank the form.
|
|
8900
|
-
*/
|
|
9114
|
+
/** The form of an addon's scoped schemas: their sections, each shown once. */
|
|
8901
9115
|
scopedFormSchema(cap) {
|
|
8902
9116
|
const byId = /* @__PURE__ */ new Map();
|
|
8903
9117
|
for (const entry of this.loadedScopedSchemas(cap)) for (const section of entry.schema.sections) if (!byId.has(section.id)) byId.set(section.id, section);
|
|
@@ -8909,8 +9123,7 @@ var BaseAddon = class {
|
|
|
8909
9123
|
return [...this._scopedByCap.values()].flat();
|
|
8910
9124
|
}
|
|
8911
9125
|
/**
|
|
8912
|
-
* The field keys that are stored per node: every field of a {@link nodeSettingsSchema}
|
|
8913
|
-
* the fields the legacy {@link globalSettingsSchema} still marks `perNode: true`. Derived once
|
|
9126
|
+
* The field keys that are stored per node: every field of a {@link nodeSettingsSchema}. Derived once
|
|
8914
9127
|
* per `cap` argument and memoized (schemas are static declarations). Empty set ⇒ every
|
|
8915
9128
|
* per-node code path is bypassed and the settings API behaves like the node-agnostic one.
|
|
8916
9129
|
* Call {@link loadScopedSchemas} first (the async seams do).
|
|
@@ -8919,8 +9132,7 @@ var BaseAddon = class {
|
|
|
8919
9132
|
const cacheKey = cap ?? "";
|
|
8920
9133
|
const cached = this._nodeKeysByCap.get(cacheKey);
|
|
8921
9134
|
if (cached) return cached;
|
|
8922
|
-
const
|
|
8923
|
-
const keys = new Set(legacy ? legacy.sections.flatMap((section) => collectPerNodeFieldKeys(section.fields)) : []);
|
|
9135
|
+
const keys = /* @__PURE__ */ new Set();
|
|
8924
9136
|
for (const { scope, schema } of this.loadedScopedSchemas(cap)) {
|
|
8925
9137
|
if (scope !== "node") continue;
|
|
8926
9138
|
for (const section of schema.sections) for (const key of collectValueFieldKeys(section.fields)) keys.add(key);
|
|
@@ -9138,8 +9350,6 @@ var BaseAddon = class {
|
|
|
9138
9350
|
}
|
|
9139
9351
|
declaredKeySet() {
|
|
9140
9352
|
const keys = new Set(Object.keys(this.defaults));
|
|
9141
|
-
const schema = this.globalSettingsSchema();
|
|
9142
|
-
if (schema) for (const section of schema.sections) for (const key of collectFieldKeys(section.fields)) keys.add(key);
|
|
9143
9353
|
for (const { schema: scoped } of this.loadedScopedSchemas()) for (const section of scoped.sections) for (const key of collectFieldKeys(section.fields)) keys.add(key);
|
|
9144
9354
|
for (const key of this._declaredStateKeys) keys.add(key);
|
|
9145
9355
|
for (const path of this.secretStatePaths) {
|
|
@@ -9237,7 +9447,7 @@ var BaseAddon = class {
|
|
|
9237
9447
|
/** The addon store's secret tree: schema fields by TYPE, plus `secretStatePaths`. */
|
|
9238
9448
|
addonSecretTree() {
|
|
9239
9449
|
if (this._addonSecretTree === null) {
|
|
9240
|
-
const tree = new Map(
|
|
9450
|
+
const tree = /* @__PURE__ */ new Map();
|
|
9241
9451
|
for (const { schema } of this.loadedScopedSchemas()) for (const [key, node] of secretTreeFromSchema(schema)) tree.set(key, node);
|
|
9242
9452
|
this._addonSecretTree = mergeSecretStatePaths(tree, this.secretStatePaths);
|
|
9243
9453
|
}
|
|
@@ -9449,47 +9659,6 @@ function classifyStoreError(err) {
|
|
|
9449
9659
|
if (TRANSPORT_PHRASES.some((f) => message.includes(f))) return "transport";
|
|
9450
9660
|
return "permanent";
|
|
9451
9661
|
}
|
|
9452
|
-
/**
|
|
9453
|
-
* Collect the keys of every field marked `perNode: true`, recursing into
|
|
9454
|
-
* layout containers (`group` fields and `sub-tabs` tabs) the same way
|
|
9455
|
-
* `hydrateSchema` does. Valueless structural fields (separator/info/…)
|
|
9456
|
-
* don't declare `perNode` and are excluded by the `in` narrowing.
|
|
9457
|
-
*/
|
|
9458
|
-
/**
|
|
9459
|
-
* The same fields with every `perNode: true` one removed, recursing into layout
|
|
9460
|
-
* containers exactly as {@link collectPerNodeFieldKeys} does. A container left
|
|
9461
|
-
* with no child is dropped rather than rendered empty.
|
|
9462
|
-
*
|
|
9463
|
-
* Used by `getIntegrationSettings`: an integration is not a node, so a field
|
|
9464
|
-
* whose store key is `<key>@<nodeId>` has no node to belong to there.
|
|
9465
|
-
*/
|
|
9466
|
-
function dropPerNodeFields(fields) {
|
|
9467
|
-
const kept = [];
|
|
9468
|
-
for (const field of fields) {
|
|
9469
|
-
if (field.type === "group") {
|
|
9470
|
-
const inner = dropPerNodeFields(field.fields);
|
|
9471
|
-
if (inner.length > 0) kept.push({
|
|
9472
|
-
...field,
|
|
9473
|
-
fields: inner
|
|
9474
|
-
});
|
|
9475
|
-
continue;
|
|
9476
|
-
}
|
|
9477
|
-
if (field.type === "sub-tabs") {
|
|
9478
|
-
const tabs = field.tabs.map((tab) => ({
|
|
9479
|
-
...tab,
|
|
9480
|
-
fields: dropPerNodeFields(tab.fields)
|
|
9481
|
-
})).filter((tab) => tab.fields.length > 0);
|
|
9482
|
-
if (tabs.length > 0) kept.push({
|
|
9483
|
-
...field,
|
|
9484
|
-
tabs
|
|
9485
|
-
});
|
|
9486
|
-
continue;
|
|
9487
|
-
}
|
|
9488
|
-
if ("perNode" in field && field.perNode === true) continue;
|
|
9489
|
-
kept.push(field);
|
|
9490
|
-
}
|
|
9491
|
-
return kept;
|
|
9492
|
-
}
|
|
9493
9662
|
/** The keys of the value-holding fields, recursing into layout containers. */
|
|
9494
9663
|
function collectValueFieldKeys(fields) {
|
|
9495
9664
|
const collected = [];
|
|
@@ -9522,21 +9691,6 @@ function collectFieldKeys(fields) {
|
|
|
9522
9691
|
}
|
|
9523
9692
|
return collected;
|
|
9524
9693
|
}
|
|
9525
|
-
function collectPerNodeFieldKeys(fields) {
|
|
9526
|
-
const collected = [];
|
|
9527
|
-
for (const field of fields) {
|
|
9528
|
-
if (field.type === "group") {
|
|
9529
|
-
collected.push(...collectPerNodeFieldKeys(field.fields));
|
|
9530
|
-
continue;
|
|
9531
|
-
}
|
|
9532
|
-
if (field.type === "sub-tabs") {
|
|
9533
|
-
for (const tab of field.tabs) collected.push(...collectPerNodeFieldKeys(tab.fields));
|
|
9534
|
-
continue;
|
|
9535
|
-
}
|
|
9536
|
-
if ("perNode" in field && field.perNode === true) collected.push(field.key);
|
|
9537
|
-
}
|
|
9538
|
-
return collected;
|
|
9539
|
-
}
|
|
9540
9694
|
/**
|
|
9541
9695
|
* Normalize an `ICamstackAddon.initialize()` return value into the
|
|
9542
9696
|
* `AddonInitResult` envelope. Arrays are wrapped into `{ providers }`;
|
|
@@ -10587,7 +10741,6 @@ var CAP_NAMES = Object.freeze([
|
|
|
10587
10741
|
"notifier",
|
|
10588
10742
|
"numeric-sensor",
|
|
10589
10743
|
"oauth-integration",
|
|
10590
|
-
"oidc-connections",
|
|
10591
10744
|
"osd",
|
|
10592
10745
|
"osd-manager",
|
|
10593
10746
|
"pet-feeder",
|
|
@@ -12294,13 +12447,25 @@ Object.freeze({
|
|
|
12294
12447
|
"path": "temperature",
|
|
12295
12448
|
"valueType": "number"
|
|
12296
12449
|
}],
|
|
12297
|
-
"timed-run": [
|
|
12298
|
-
|
|
12299
|
-
|
|
12300
|
-
|
|
12301
|
-
|
|
12302
|
-
|
|
12303
|
-
|
|
12450
|
+
"timed-run": [
|
|
12451
|
+
{
|
|
12452
|
+
"path": "activeUntil",
|
|
12453
|
+
"valueType": "number"
|
|
12454
|
+
},
|
|
12455
|
+
{
|
|
12456
|
+
"path": "requestedBy",
|
|
12457
|
+
"valueType": "string"
|
|
12458
|
+
},
|
|
12459
|
+
{
|
|
12460
|
+
"path": "quickRun.duration",
|
|
12461
|
+
"valueType": "number"
|
|
12462
|
+
},
|
|
12463
|
+
{
|
|
12464
|
+
"path": "quickRun.unit",
|
|
12465
|
+
"valueType": "enum",
|
|
12466
|
+
"enumValues": ["s", "min"]
|
|
12467
|
+
}
|
|
12468
|
+
],
|
|
12304
12469
|
"update": [
|
|
12305
12470
|
{
|
|
12306
12471
|
"path": "currentVersion",
|
|
@@ -12479,8 +12644,7 @@ Object.freeze({
|
|
|
12479
12644
|
"device-provider": { "reloadDevice": 18e4 },
|
|
12480
12645
|
"llm": {
|
|
12481
12646
|
"generate": 6e5,
|
|
12482
|
-
"generateVision": 6e5
|
|
12483
|
-
"testProfile": 6e5
|
|
12647
|
+
"generateVision": 6e5
|
|
12484
12648
|
},
|
|
12485
12649
|
"llm-runtime": {
|
|
12486
12650
|
"complete": 6e5,
|
|
@@ -12525,7 +12689,7 @@ object({
|
|
|
12525
12689
|
params: record(string(), union([string(), number()])).optional()
|
|
12526
12690
|
});
|
|
12527
12691
|
//#endregion
|
|
12528
|
-
//#region ../types/dist/composition-
|
|
12692
|
+
//#region ../types/dist/composition-Bx0JvKUU.mjs
|
|
12529
12693
|
/**
|
|
12530
12694
|
* The ffmpeg build every CamStack node downloads, per platform and arch.
|
|
12531
12695
|
*
|
|
@@ -13687,6 +13851,387 @@ var NodeColorIdSchema = _enum([
|
|
|
13687
13851
|
"node-h"
|
|
13688
13852
|
]);
|
|
13689
13853
|
//#endregion
|
|
13854
|
+
//#region ../types/dist/convert-BAzH15HU.mjs
|
|
13855
|
+
/**
|
|
13856
|
+
* Frozen unit → spec table. `•` in the doc marks each dimension's canonical
|
|
13857
|
+
* unit (`factor: 1, offset: 0`). °F derives from `°C = (°F − 32) × 5/9` ⇒
|
|
13858
|
+
* `factor = 5/9`, `offset = -160/9` (kept as exact expressions, not rounded
|
|
13859
|
+
* decimals). K derives from `°C = K − 273.15`.
|
|
13860
|
+
*/
|
|
13861
|
+
var UNIT_TABLE = {
|
|
13862
|
+
"°C": {
|
|
13863
|
+
dimension: "temperature",
|
|
13864
|
+
factor: 1,
|
|
13865
|
+
offset: 0
|
|
13866
|
+
},
|
|
13867
|
+
"°F": {
|
|
13868
|
+
dimension: "temperature",
|
|
13869
|
+
factor: 5 / 9,
|
|
13870
|
+
offset: -160 / 9
|
|
13871
|
+
},
|
|
13872
|
+
K: {
|
|
13873
|
+
dimension: "temperature",
|
|
13874
|
+
factor: 1,
|
|
13875
|
+
offset: -273.15
|
|
13876
|
+
},
|
|
13877
|
+
hPa: {
|
|
13878
|
+
dimension: "pressure",
|
|
13879
|
+
factor: 1,
|
|
13880
|
+
offset: 0
|
|
13881
|
+
},
|
|
13882
|
+
kPa: {
|
|
13883
|
+
dimension: "pressure",
|
|
13884
|
+
factor: 10,
|
|
13885
|
+
offset: 0
|
|
13886
|
+
},
|
|
13887
|
+
Pa: {
|
|
13888
|
+
dimension: "pressure",
|
|
13889
|
+
factor: .01,
|
|
13890
|
+
offset: 0
|
|
13891
|
+
},
|
|
13892
|
+
mbar: {
|
|
13893
|
+
dimension: "pressure",
|
|
13894
|
+
factor: 1,
|
|
13895
|
+
offset: 0
|
|
13896
|
+
},
|
|
13897
|
+
bar: {
|
|
13898
|
+
dimension: "pressure",
|
|
13899
|
+
factor: 1e3,
|
|
13900
|
+
offset: 0
|
|
13901
|
+
},
|
|
13902
|
+
inHg: {
|
|
13903
|
+
dimension: "pressure",
|
|
13904
|
+
factor: 33.8639,
|
|
13905
|
+
offset: 0
|
|
13906
|
+
},
|
|
13907
|
+
mmHg: {
|
|
13908
|
+
dimension: "pressure",
|
|
13909
|
+
factor: 1.33322,
|
|
13910
|
+
offset: 0
|
|
13911
|
+
},
|
|
13912
|
+
psi: {
|
|
13913
|
+
dimension: "pressure",
|
|
13914
|
+
factor: 68.9476,
|
|
13915
|
+
offset: 0
|
|
13916
|
+
},
|
|
13917
|
+
"m/s": {
|
|
13918
|
+
dimension: "speed",
|
|
13919
|
+
factor: 1,
|
|
13920
|
+
offset: 0
|
|
13921
|
+
},
|
|
13922
|
+
"km/h": {
|
|
13923
|
+
dimension: "speed",
|
|
13924
|
+
factor: 1 / 3.6,
|
|
13925
|
+
offset: 0
|
|
13926
|
+
},
|
|
13927
|
+
mph: {
|
|
13928
|
+
dimension: "speed",
|
|
13929
|
+
factor: .44704,
|
|
13930
|
+
offset: 0
|
|
13931
|
+
},
|
|
13932
|
+
kn: {
|
|
13933
|
+
dimension: "speed",
|
|
13934
|
+
factor: .514444,
|
|
13935
|
+
offset: 0
|
|
13936
|
+
},
|
|
13937
|
+
"mm/h": {
|
|
13938
|
+
dimension: "precipitation-rate",
|
|
13939
|
+
factor: 1,
|
|
13940
|
+
offset: 0
|
|
13941
|
+
},
|
|
13942
|
+
"in/h": {
|
|
13943
|
+
dimension: "precipitation-rate",
|
|
13944
|
+
factor: 25.4,
|
|
13945
|
+
offset: 0
|
|
13946
|
+
},
|
|
13947
|
+
m: {
|
|
13948
|
+
dimension: "length",
|
|
13949
|
+
factor: 1,
|
|
13950
|
+
offset: 0
|
|
13951
|
+
},
|
|
13952
|
+
mm: {
|
|
13953
|
+
dimension: "length",
|
|
13954
|
+
factor: .001,
|
|
13955
|
+
offset: 0
|
|
13956
|
+
},
|
|
13957
|
+
cm: {
|
|
13958
|
+
dimension: "length",
|
|
13959
|
+
factor: .01,
|
|
13960
|
+
offset: 0
|
|
13961
|
+
},
|
|
13962
|
+
km: {
|
|
13963
|
+
dimension: "length",
|
|
13964
|
+
factor: 1e3,
|
|
13965
|
+
offset: 0
|
|
13966
|
+
},
|
|
13967
|
+
in: {
|
|
13968
|
+
dimension: "length",
|
|
13969
|
+
factor: .0254,
|
|
13970
|
+
offset: 0
|
|
13971
|
+
},
|
|
13972
|
+
ft: {
|
|
13973
|
+
dimension: "length",
|
|
13974
|
+
factor: .3048,
|
|
13975
|
+
offset: 0
|
|
13976
|
+
},
|
|
13977
|
+
mi: {
|
|
13978
|
+
dimension: "length",
|
|
13979
|
+
factor: 1609.344,
|
|
13980
|
+
offset: 0
|
|
13981
|
+
},
|
|
13982
|
+
"m²": {
|
|
13983
|
+
dimension: "area",
|
|
13984
|
+
factor: 1,
|
|
13985
|
+
offset: 0
|
|
13986
|
+
},
|
|
13987
|
+
lx: {
|
|
13988
|
+
dimension: "illuminance",
|
|
13989
|
+
factor: 1,
|
|
13990
|
+
offset: 0
|
|
13991
|
+
},
|
|
13992
|
+
"W/m²": {
|
|
13993
|
+
dimension: "irradiance",
|
|
13994
|
+
factor: 1,
|
|
13995
|
+
offset: 0
|
|
13996
|
+
},
|
|
13997
|
+
W: {
|
|
13998
|
+
dimension: "power",
|
|
13999
|
+
factor: 1,
|
|
14000
|
+
offset: 0
|
|
14001
|
+
},
|
|
14002
|
+
kW: {
|
|
14003
|
+
dimension: "power",
|
|
14004
|
+
factor: 1e3,
|
|
14005
|
+
offset: 0
|
|
14006
|
+
},
|
|
14007
|
+
VA: {
|
|
14008
|
+
dimension: "apparent-power",
|
|
14009
|
+
factor: 1,
|
|
14010
|
+
offset: 0
|
|
14011
|
+
},
|
|
14012
|
+
Wh: {
|
|
14013
|
+
dimension: "energy",
|
|
14014
|
+
factor: 1,
|
|
14015
|
+
offset: 0
|
|
14016
|
+
},
|
|
14017
|
+
kWh: {
|
|
14018
|
+
dimension: "energy",
|
|
14019
|
+
factor: 1e3,
|
|
14020
|
+
offset: 0
|
|
14021
|
+
},
|
|
14022
|
+
MWh: {
|
|
14023
|
+
dimension: "energy",
|
|
14024
|
+
factor: 1e6,
|
|
14025
|
+
offset: 0
|
|
14026
|
+
},
|
|
14027
|
+
V: {
|
|
14028
|
+
dimension: "voltage",
|
|
14029
|
+
factor: 1,
|
|
14030
|
+
offset: 0
|
|
14031
|
+
},
|
|
14032
|
+
mV: {
|
|
14033
|
+
dimension: "voltage",
|
|
14034
|
+
factor: .001,
|
|
14035
|
+
offset: 0
|
|
14036
|
+
},
|
|
14037
|
+
A: {
|
|
14038
|
+
dimension: "current",
|
|
14039
|
+
factor: 1,
|
|
14040
|
+
offset: 0
|
|
14041
|
+
},
|
|
14042
|
+
mA: {
|
|
14043
|
+
dimension: "current",
|
|
14044
|
+
factor: .001,
|
|
14045
|
+
offset: 0
|
|
14046
|
+
},
|
|
14047
|
+
ppm: {
|
|
14048
|
+
dimension: "concentration-volume",
|
|
14049
|
+
factor: 1,
|
|
14050
|
+
offset: 0
|
|
14051
|
+
},
|
|
14052
|
+
ppb: {
|
|
14053
|
+
dimension: "concentration-volume",
|
|
14054
|
+
factor: .001,
|
|
14055
|
+
offset: 0
|
|
14056
|
+
},
|
|
14057
|
+
"µg/m³": {
|
|
14058
|
+
dimension: "concentration-mass",
|
|
14059
|
+
factor: 1,
|
|
14060
|
+
offset: 0
|
|
14061
|
+
},
|
|
14062
|
+
"mg/m³": {
|
|
14063
|
+
dimension: "concentration-mass",
|
|
14064
|
+
factor: 1e3,
|
|
14065
|
+
offset: 0
|
|
14066
|
+
},
|
|
14067
|
+
kg: {
|
|
14068
|
+
dimension: "mass",
|
|
14069
|
+
factor: 1,
|
|
14070
|
+
offset: 0
|
|
14071
|
+
},
|
|
14072
|
+
g: {
|
|
14073
|
+
dimension: "mass",
|
|
14074
|
+
factor: .001,
|
|
14075
|
+
offset: 0
|
|
14076
|
+
},
|
|
14077
|
+
lb: {
|
|
14078
|
+
dimension: "mass",
|
|
14079
|
+
factor: .453592,
|
|
14080
|
+
offset: 0
|
|
14081
|
+
},
|
|
14082
|
+
oz: {
|
|
14083
|
+
dimension: "mass",
|
|
14084
|
+
factor: .0283495,
|
|
14085
|
+
offset: 0
|
|
14086
|
+
},
|
|
14087
|
+
"%": {
|
|
14088
|
+
dimension: "percentage",
|
|
14089
|
+
factor: 1,
|
|
14090
|
+
offset: 0
|
|
14091
|
+
},
|
|
14092
|
+
L: {
|
|
14093
|
+
dimension: "volume",
|
|
14094
|
+
factor: 1,
|
|
14095
|
+
offset: 0
|
|
14096
|
+
},
|
|
14097
|
+
mL: {
|
|
14098
|
+
dimension: "volume",
|
|
14099
|
+
factor: .001,
|
|
14100
|
+
offset: 0
|
|
14101
|
+
},
|
|
14102
|
+
gal: {
|
|
14103
|
+
dimension: "volume",
|
|
14104
|
+
factor: 3.785411784,
|
|
14105
|
+
offset: 0
|
|
14106
|
+
},
|
|
14107
|
+
s: {
|
|
14108
|
+
dimension: "duration",
|
|
14109
|
+
factor: 1,
|
|
14110
|
+
offset: 0
|
|
14111
|
+
},
|
|
14112
|
+
ms: {
|
|
14113
|
+
dimension: "duration",
|
|
14114
|
+
factor: .001,
|
|
14115
|
+
offset: 0
|
|
14116
|
+
},
|
|
14117
|
+
min: {
|
|
14118
|
+
dimension: "duration",
|
|
14119
|
+
factor: 60,
|
|
14120
|
+
offset: 0
|
|
14121
|
+
},
|
|
14122
|
+
h: {
|
|
14123
|
+
dimension: "duration",
|
|
14124
|
+
factor: 3600,
|
|
14125
|
+
offset: 0
|
|
14126
|
+
},
|
|
14127
|
+
d: {
|
|
14128
|
+
dimension: "duration",
|
|
14129
|
+
factor: 86400,
|
|
14130
|
+
offset: 0
|
|
14131
|
+
},
|
|
14132
|
+
B: {
|
|
14133
|
+
dimension: "information",
|
|
14134
|
+
factor: 1,
|
|
14135
|
+
offset: 0
|
|
14136
|
+
},
|
|
14137
|
+
KiB: {
|
|
14138
|
+
dimension: "information",
|
|
14139
|
+
factor: 1024,
|
|
14140
|
+
offset: 0
|
|
14141
|
+
},
|
|
14142
|
+
MiB: {
|
|
14143
|
+
dimension: "information",
|
|
14144
|
+
factor: 1024 ** 2,
|
|
14145
|
+
offset: 0
|
|
14146
|
+
},
|
|
14147
|
+
GiB: {
|
|
14148
|
+
dimension: "information",
|
|
14149
|
+
factor: 1024 ** 3,
|
|
14150
|
+
offset: 0
|
|
14151
|
+
},
|
|
14152
|
+
TiB: {
|
|
14153
|
+
dimension: "information",
|
|
14154
|
+
factor: 1024 ** 4,
|
|
14155
|
+
offset: 0
|
|
14156
|
+
},
|
|
14157
|
+
kB: {
|
|
14158
|
+
dimension: "information",
|
|
14159
|
+
factor: 1e3,
|
|
14160
|
+
offset: 0
|
|
14161
|
+
},
|
|
14162
|
+
MB: {
|
|
14163
|
+
dimension: "information",
|
|
14164
|
+
factor: 1e6,
|
|
14165
|
+
offset: 0
|
|
14166
|
+
},
|
|
14167
|
+
GB: {
|
|
14168
|
+
dimension: "information",
|
|
14169
|
+
factor: 1e9,
|
|
14170
|
+
offset: 0
|
|
14171
|
+
},
|
|
14172
|
+
"°": {
|
|
14173
|
+
dimension: "angle",
|
|
14174
|
+
factor: 1,
|
|
14175
|
+
offset: 0
|
|
14176
|
+
},
|
|
14177
|
+
dBFS: {
|
|
14178
|
+
dimension: "sound-level",
|
|
14179
|
+
factor: 1,
|
|
14180
|
+
offset: 0
|
|
14181
|
+
},
|
|
14182
|
+
dBm: {
|
|
14183
|
+
dimension: "signal-level",
|
|
14184
|
+
factor: 1,
|
|
14185
|
+
offset: 0
|
|
14186
|
+
},
|
|
14187
|
+
mired: {
|
|
14188
|
+
dimension: "colour-temperature",
|
|
14189
|
+
factor: 1,
|
|
14190
|
+
offset: 0
|
|
14191
|
+
},
|
|
14192
|
+
kbps: {
|
|
14193
|
+
dimension: "bitrate",
|
|
14194
|
+
factor: 1,
|
|
14195
|
+
offset: 0
|
|
14196
|
+
},
|
|
14197
|
+
Mbps: {
|
|
14198
|
+
dimension: "bitrate",
|
|
14199
|
+
factor: 1e3,
|
|
14200
|
+
offset: 0
|
|
14201
|
+
},
|
|
14202
|
+
fps: {
|
|
14203
|
+
dimension: "rate",
|
|
14204
|
+
factor: 1,
|
|
14205
|
+
offset: 0
|
|
14206
|
+
}
|
|
14207
|
+
};
|
|
14208
|
+
/** Resolve a unit's `UnitSpec`, or `undefined` when the spelling is unknown. */
|
|
14209
|
+
function specFor(unit) {
|
|
14210
|
+
return Object.hasOwn(UNIT_TABLE, unit) ? UNIT_TABLE[unit] : void 0;
|
|
14211
|
+
}
|
|
14212
|
+
/** Value in `spec`'s unit → its dimension's canonical unit. */
|
|
14213
|
+
function toCanonical(value, spec) {
|
|
14214
|
+
return value * spec.factor + spec.offset;
|
|
14215
|
+
}
|
|
14216
|
+
/** Canonical-unit value → the unit described by `spec`. */
|
|
14217
|
+
function fromCanonical(canonical, spec) {
|
|
14218
|
+
return (canonical - spec.offset) / spec.factor;
|
|
14219
|
+
}
|
|
14220
|
+
/**
|
|
14221
|
+
* Graceful variant for the render path: returns the converted value, or
|
|
14222
|
+
* `undefined` when the conversion is refused (unknown unit / cross-dimension).
|
|
14223
|
+
* Never throws — a render caller falls back to the raw value + source unit.
|
|
14224
|
+
*/
|
|
14225
|
+
function tryConvertUnit(value, from, to) {
|
|
14226
|
+
if (from === to) return value;
|
|
14227
|
+
const fromSpec = specFor(from);
|
|
14228
|
+
if (!fromSpec) return void 0;
|
|
14229
|
+
const toSpec = specFor(to);
|
|
14230
|
+
if (!toSpec) return void 0;
|
|
14231
|
+
if (fromSpec.dimension !== toSpec.dimension) return void 0;
|
|
14232
|
+
return fromCanonical(toCanonical(value, fromSpec), toSpec);
|
|
14233
|
+
}
|
|
14234
|
+
//#endregion
|
|
13690
14235
|
//#region ../types/dist/index.mjs
|
|
13691
14236
|
var SMTP_INBOUND_DEFAULT_PORT = 2525;
|
|
13692
14237
|
var SMTP_INBOUND_DEFAULT_DOMAIN = "camstack.local";
|
|
@@ -13883,17 +14428,18 @@ var IntegrationInstanceRefSchema = object({
|
|
|
13883
14428
|
* message to what the kind supports — callers never special-case a service.
|
|
13884
14429
|
*
|
|
13885
14430
|
* DESIGN DECISIONS (locked):
|
|
13886
|
-
* -
|
|
13887
|
-
*
|
|
13888
|
-
*
|
|
13889
|
-
*
|
|
13890
|
-
*
|
|
13891
|
-
*
|
|
13892
|
-
*
|
|
13893
|
-
*
|
|
13894
|
-
*
|
|
13895
|
-
* routable. `send` / `testTarget` /
|
|
13896
|
-
* `
|
|
14431
|
+
* - A target is an INSTANCE of this function cap (epic #440, step 6): the
|
|
14432
|
+
* providers serve their targets as `integration-instances` records, one
|
|
14433
|
+
* record kind per target kind, and the admin lists, adds, edits, switches
|
|
14434
|
+
* and deletes them through that cap. This cap keeps what an instance cannot
|
|
14435
|
+
* say: the kind catalogue (`listTargetKinds`: capabilities, delivery
|
|
14436
|
+
* parameters, brand icon), dispatch (`send`, `testTarget`) and the form
|
|
14437
|
+
* helpers (`discoverTargets`, `probeTargetConfig`).
|
|
14438
|
+
* - `listTargetKinds` / `discoverTargets` return arrays → the generated
|
|
14439
|
+
* cap-mount auto-`concatCollection`-fans them across every registered
|
|
14440
|
+
* provider so one catalog is routable. `send` / `testTarget` /
|
|
14441
|
+
* `probeTargetConfig` route to ONE provider by the `addonId` the generated
|
|
14442
|
+
* collection router extracts from the call input.
|
|
13897
14443
|
* - `Attachment.bytes` is `Uint8Array`. Transport-safe: superjson (the tRPC
|
|
13898
14444
|
* transformer) + UDS MsgPack both round-trip typed arrays — already used by
|
|
13899
14445
|
* `storage` / `storage-provider` / `recording` caps over the same path. No
|
|
@@ -14138,7 +14684,7 @@ var TargetKindCapsSchema = object({
|
|
|
14138
14684
|
* the union is large and not meant for runtime validation here; the exported
|
|
14139
14685
|
* `TargetKind` type re-tightens `configSchema` to `ConfigUISchema`.
|
|
14140
14686
|
*/
|
|
14141
|
-
var ConfigSchemaPassthrough$
|
|
14687
|
+
var ConfigSchemaPassthrough$3 = unknown();
|
|
14142
14688
|
var TargetKindSchema = object({
|
|
14143
14689
|
kind: string(),
|
|
14144
14690
|
label: string(),
|
|
@@ -14175,7 +14721,7 @@ var TargetKindSchema = object({
|
|
|
14175
14721
|
* its raster path, which is the safe default for an unknown image.
|
|
14176
14722
|
*/
|
|
14177
14723
|
iconMediaType: string().optional(),
|
|
14178
|
-
configSchema: ConfigSchemaPassthrough$
|
|
14724
|
+
configSchema: ConfigSchemaPassthrough$3,
|
|
14179
14725
|
/**
|
|
14180
14726
|
* The config keys that decide WHERE this kind's secrets are sent (server,
|
|
14181
14727
|
* base URL, instance, chat, recipient). A save that changes any of them
|
|
@@ -14197,9 +14743,11 @@ var TargetKindSchema = object({
|
|
|
14197
14743
|
caps: TargetKindCapsSchema
|
|
14198
14744
|
});
|
|
14199
14745
|
/**
|
|
14200
|
-
* A
|
|
14201
|
-
*
|
|
14202
|
-
*
|
|
14746
|
+
* A target as a provider's own code sees it (the notification-center bridge, the
|
|
14747
|
+
* send path): the flat record body split into the name, the switch and the
|
|
14748
|
+
* kind's fields. `config` holds secrets; a reader that serves it to a client
|
|
14749
|
+
* REDACTS secret fields (a presence marker only) — never round-trip a stored
|
|
14750
|
+
* secret to the UI.
|
|
14203
14751
|
*/
|
|
14204
14752
|
var TargetSchema = object({
|
|
14205
14753
|
id: string(),
|
|
@@ -14242,13 +14790,13 @@ var ProbeTargetConfigResultSchema = object({
|
|
|
14242
14790
|
stateInstance: string().optional(),
|
|
14243
14791
|
error: string().optional()
|
|
14244
14792
|
});
|
|
14245
|
-
method(object({}), array(TargetKindSchema)), method(object({
|
|
14793
|
+
method(object({}), array(TargetKindSchema)), method(object({
|
|
14246
14794
|
kind: string(),
|
|
14247
14795
|
config: record(string(), unknown()).optional(),
|
|
14248
14796
|
/**
|
|
14249
14797
|
* When editing / duplicating, the blank password field never round-trips
|
|
14250
14798
|
* the stored token. Pass the source target id so the provider can restore
|
|
14251
|
-
* secrets server-side before dialling
|
|
14799
|
+
* secrets server-side before dialling.
|
|
14252
14800
|
*/
|
|
14253
14801
|
targetId: string().optional()
|
|
14254
14802
|
}), array(DiscoveredTargetSchema), { auth: "admin" }), method(object({
|
|
@@ -14271,27 +14819,6 @@ method(object({}), array(TargetKindSchema)), method(object({}), array(TargetSche
|
|
|
14271
14819
|
}), TestResultSchema, {
|
|
14272
14820
|
kind: "mutation",
|
|
14273
14821
|
auth: "admin"
|
|
14274
|
-
}), method(object({
|
|
14275
|
-
target: TargetSchema,
|
|
14276
|
-
/**
|
|
14277
|
-
* Duplicate flow: create a NEW target id while copying secrets from an
|
|
14278
|
-
* existing row. The UI never holds the stored token; blank / redacted
|
|
14279
|
-
* password fields are restored from this source (D634 still applies if
|
|
14280
|
-
* destinations diverge without a re-typed secret).
|
|
14281
|
-
*/
|
|
14282
|
-
cloneSecretsFrom: string().optional()
|
|
14283
|
-
}), TargetSchema, {
|
|
14284
|
-
kind: "mutation",
|
|
14285
|
-
auth: "admin"
|
|
14286
|
-
}), method(object({ targetId: string() }), _void(), {
|
|
14287
|
-
kind: "mutation",
|
|
14288
|
-
auth: "admin"
|
|
14289
|
-
}), method(object({
|
|
14290
|
-
targetId: string(),
|
|
14291
|
-
enabled: boolean()
|
|
14292
|
-
}), _void(), {
|
|
14293
|
-
kind: "mutation",
|
|
14294
|
-
auth: "admin"
|
|
14295
14822
|
});
|
|
14296
14823
|
looseObject({
|
|
14297
14824
|
name: string().min(1),
|
|
@@ -22559,7 +23086,6 @@ var SYSTEM_CAP_VOCABULARY = {
|
|
|
22559
23086
|
"notification-output": system("notification delivery — reached through notifier devices and rules"),
|
|
22560
23087
|
"notification-rules": system("notification rules — authored on their own page"),
|
|
22561
23088
|
"oauth-integration": system(IDENTITY),
|
|
22562
|
-
"oidc-connections": system(IDENTITY),
|
|
22563
23089
|
"osd-manager": system(PIPELINE),
|
|
22564
23090
|
"pipeline-executor": system(PIPELINE),
|
|
22565
23091
|
"pipeline-orchestrator": system(PIPELINE),
|
|
@@ -42580,6 +43106,7 @@ var ExpressionBindingSourceSchema = union([
|
|
|
42580
43106
|
object({
|
|
42581
43107
|
kind: literal("global"),
|
|
42582
43108
|
sourceStableId: string(),
|
|
43109
|
+
addonId: string().optional(),
|
|
42583
43110
|
cap: string(),
|
|
42584
43111
|
fieldPath: string()
|
|
42585
43112
|
})
|
|
@@ -42646,385 +43173,6 @@ var SourceInfoSchema = object({
|
|
|
42646
43173
|
raw: record(string(), unknown()).optional()
|
|
42647
43174
|
});
|
|
42648
43175
|
/**
|
|
42649
|
-
* Frozen unit → spec table. `•` in the doc marks each dimension's canonical
|
|
42650
|
-
* unit (`factor: 1, offset: 0`). °F derives from `°C = (°F − 32) × 5/9` ⇒
|
|
42651
|
-
* `factor = 5/9`, `offset = -160/9` (kept as exact expressions, not rounded
|
|
42652
|
-
* decimals). K derives from `°C = K − 273.15`.
|
|
42653
|
-
*/
|
|
42654
|
-
var UNIT_TABLE = {
|
|
42655
|
-
"°C": {
|
|
42656
|
-
dimension: "temperature",
|
|
42657
|
-
factor: 1,
|
|
42658
|
-
offset: 0
|
|
42659
|
-
},
|
|
42660
|
-
"°F": {
|
|
42661
|
-
dimension: "temperature",
|
|
42662
|
-
factor: 5 / 9,
|
|
42663
|
-
offset: -160 / 9
|
|
42664
|
-
},
|
|
42665
|
-
K: {
|
|
42666
|
-
dimension: "temperature",
|
|
42667
|
-
factor: 1,
|
|
42668
|
-
offset: -273.15
|
|
42669
|
-
},
|
|
42670
|
-
hPa: {
|
|
42671
|
-
dimension: "pressure",
|
|
42672
|
-
factor: 1,
|
|
42673
|
-
offset: 0
|
|
42674
|
-
},
|
|
42675
|
-
kPa: {
|
|
42676
|
-
dimension: "pressure",
|
|
42677
|
-
factor: 10,
|
|
42678
|
-
offset: 0
|
|
42679
|
-
},
|
|
42680
|
-
Pa: {
|
|
42681
|
-
dimension: "pressure",
|
|
42682
|
-
factor: .01,
|
|
42683
|
-
offset: 0
|
|
42684
|
-
},
|
|
42685
|
-
mbar: {
|
|
42686
|
-
dimension: "pressure",
|
|
42687
|
-
factor: 1,
|
|
42688
|
-
offset: 0
|
|
42689
|
-
},
|
|
42690
|
-
bar: {
|
|
42691
|
-
dimension: "pressure",
|
|
42692
|
-
factor: 1e3,
|
|
42693
|
-
offset: 0
|
|
42694
|
-
},
|
|
42695
|
-
inHg: {
|
|
42696
|
-
dimension: "pressure",
|
|
42697
|
-
factor: 33.8639,
|
|
42698
|
-
offset: 0
|
|
42699
|
-
},
|
|
42700
|
-
mmHg: {
|
|
42701
|
-
dimension: "pressure",
|
|
42702
|
-
factor: 1.33322,
|
|
42703
|
-
offset: 0
|
|
42704
|
-
},
|
|
42705
|
-
psi: {
|
|
42706
|
-
dimension: "pressure",
|
|
42707
|
-
factor: 68.9476,
|
|
42708
|
-
offset: 0
|
|
42709
|
-
},
|
|
42710
|
-
"m/s": {
|
|
42711
|
-
dimension: "speed",
|
|
42712
|
-
factor: 1,
|
|
42713
|
-
offset: 0
|
|
42714
|
-
},
|
|
42715
|
-
"km/h": {
|
|
42716
|
-
dimension: "speed",
|
|
42717
|
-
factor: 1 / 3.6,
|
|
42718
|
-
offset: 0
|
|
42719
|
-
},
|
|
42720
|
-
mph: {
|
|
42721
|
-
dimension: "speed",
|
|
42722
|
-
factor: .44704,
|
|
42723
|
-
offset: 0
|
|
42724
|
-
},
|
|
42725
|
-
kn: {
|
|
42726
|
-
dimension: "speed",
|
|
42727
|
-
factor: .514444,
|
|
42728
|
-
offset: 0
|
|
42729
|
-
},
|
|
42730
|
-
"mm/h": {
|
|
42731
|
-
dimension: "precipitation-rate",
|
|
42732
|
-
factor: 1,
|
|
42733
|
-
offset: 0
|
|
42734
|
-
},
|
|
42735
|
-
"in/h": {
|
|
42736
|
-
dimension: "precipitation-rate",
|
|
42737
|
-
factor: 25.4,
|
|
42738
|
-
offset: 0
|
|
42739
|
-
},
|
|
42740
|
-
m: {
|
|
42741
|
-
dimension: "length",
|
|
42742
|
-
factor: 1,
|
|
42743
|
-
offset: 0
|
|
42744
|
-
},
|
|
42745
|
-
mm: {
|
|
42746
|
-
dimension: "length",
|
|
42747
|
-
factor: .001,
|
|
42748
|
-
offset: 0
|
|
42749
|
-
},
|
|
42750
|
-
cm: {
|
|
42751
|
-
dimension: "length",
|
|
42752
|
-
factor: .01,
|
|
42753
|
-
offset: 0
|
|
42754
|
-
},
|
|
42755
|
-
km: {
|
|
42756
|
-
dimension: "length",
|
|
42757
|
-
factor: 1e3,
|
|
42758
|
-
offset: 0
|
|
42759
|
-
},
|
|
42760
|
-
in: {
|
|
42761
|
-
dimension: "length",
|
|
42762
|
-
factor: .0254,
|
|
42763
|
-
offset: 0
|
|
42764
|
-
},
|
|
42765
|
-
ft: {
|
|
42766
|
-
dimension: "length",
|
|
42767
|
-
factor: .3048,
|
|
42768
|
-
offset: 0
|
|
42769
|
-
},
|
|
42770
|
-
mi: {
|
|
42771
|
-
dimension: "length",
|
|
42772
|
-
factor: 1609.344,
|
|
42773
|
-
offset: 0
|
|
42774
|
-
},
|
|
42775
|
-
"m²": {
|
|
42776
|
-
dimension: "area",
|
|
42777
|
-
factor: 1,
|
|
42778
|
-
offset: 0
|
|
42779
|
-
},
|
|
42780
|
-
lx: {
|
|
42781
|
-
dimension: "illuminance",
|
|
42782
|
-
factor: 1,
|
|
42783
|
-
offset: 0
|
|
42784
|
-
},
|
|
42785
|
-
"W/m²": {
|
|
42786
|
-
dimension: "irradiance",
|
|
42787
|
-
factor: 1,
|
|
42788
|
-
offset: 0
|
|
42789
|
-
},
|
|
42790
|
-
W: {
|
|
42791
|
-
dimension: "power",
|
|
42792
|
-
factor: 1,
|
|
42793
|
-
offset: 0
|
|
42794
|
-
},
|
|
42795
|
-
kW: {
|
|
42796
|
-
dimension: "power",
|
|
42797
|
-
factor: 1e3,
|
|
42798
|
-
offset: 0
|
|
42799
|
-
},
|
|
42800
|
-
VA: {
|
|
42801
|
-
dimension: "apparent-power",
|
|
42802
|
-
factor: 1,
|
|
42803
|
-
offset: 0
|
|
42804
|
-
},
|
|
42805
|
-
Wh: {
|
|
42806
|
-
dimension: "energy",
|
|
42807
|
-
factor: 1,
|
|
42808
|
-
offset: 0
|
|
42809
|
-
},
|
|
42810
|
-
kWh: {
|
|
42811
|
-
dimension: "energy",
|
|
42812
|
-
factor: 1e3,
|
|
42813
|
-
offset: 0
|
|
42814
|
-
},
|
|
42815
|
-
MWh: {
|
|
42816
|
-
dimension: "energy",
|
|
42817
|
-
factor: 1e6,
|
|
42818
|
-
offset: 0
|
|
42819
|
-
},
|
|
42820
|
-
V: {
|
|
42821
|
-
dimension: "voltage",
|
|
42822
|
-
factor: 1,
|
|
42823
|
-
offset: 0
|
|
42824
|
-
},
|
|
42825
|
-
mV: {
|
|
42826
|
-
dimension: "voltage",
|
|
42827
|
-
factor: .001,
|
|
42828
|
-
offset: 0
|
|
42829
|
-
},
|
|
42830
|
-
A: {
|
|
42831
|
-
dimension: "current",
|
|
42832
|
-
factor: 1,
|
|
42833
|
-
offset: 0
|
|
42834
|
-
},
|
|
42835
|
-
mA: {
|
|
42836
|
-
dimension: "current",
|
|
42837
|
-
factor: .001,
|
|
42838
|
-
offset: 0
|
|
42839
|
-
},
|
|
42840
|
-
ppm: {
|
|
42841
|
-
dimension: "concentration-volume",
|
|
42842
|
-
factor: 1,
|
|
42843
|
-
offset: 0
|
|
42844
|
-
},
|
|
42845
|
-
ppb: {
|
|
42846
|
-
dimension: "concentration-volume",
|
|
42847
|
-
factor: .001,
|
|
42848
|
-
offset: 0
|
|
42849
|
-
},
|
|
42850
|
-
"µg/m³": {
|
|
42851
|
-
dimension: "concentration-mass",
|
|
42852
|
-
factor: 1,
|
|
42853
|
-
offset: 0
|
|
42854
|
-
},
|
|
42855
|
-
"mg/m³": {
|
|
42856
|
-
dimension: "concentration-mass",
|
|
42857
|
-
factor: 1e3,
|
|
42858
|
-
offset: 0
|
|
42859
|
-
},
|
|
42860
|
-
kg: {
|
|
42861
|
-
dimension: "mass",
|
|
42862
|
-
factor: 1,
|
|
42863
|
-
offset: 0
|
|
42864
|
-
},
|
|
42865
|
-
g: {
|
|
42866
|
-
dimension: "mass",
|
|
42867
|
-
factor: .001,
|
|
42868
|
-
offset: 0
|
|
42869
|
-
},
|
|
42870
|
-
lb: {
|
|
42871
|
-
dimension: "mass",
|
|
42872
|
-
factor: .453592,
|
|
42873
|
-
offset: 0
|
|
42874
|
-
},
|
|
42875
|
-
oz: {
|
|
42876
|
-
dimension: "mass",
|
|
42877
|
-
factor: .0283495,
|
|
42878
|
-
offset: 0
|
|
42879
|
-
},
|
|
42880
|
-
"%": {
|
|
42881
|
-
dimension: "percentage",
|
|
42882
|
-
factor: 1,
|
|
42883
|
-
offset: 0
|
|
42884
|
-
},
|
|
42885
|
-
L: {
|
|
42886
|
-
dimension: "volume",
|
|
42887
|
-
factor: 1,
|
|
42888
|
-
offset: 0
|
|
42889
|
-
},
|
|
42890
|
-
mL: {
|
|
42891
|
-
dimension: "volume",
|
|
42892
|
-
factor: .001,
|
|
42893
|
-
offset: 0
|
|
42894
|
-
},
|
|
42895
|
-
gal: {
|
|
42896
|
-
dimension: "volume",
|
|
42897
|
-
factor: 3.785411784,
|
|
42898
|
-
offset: 0
|
|
42899
|
-
},
|
|
42900
|
-
s: {
|
|
42901
|
-
dimension: "duration",
|
|
42902
|
-
factor: 1,
|
|
42903
|
-
offset: 0
|
|
42904
|
-
},
|
|
42905
|
-
ms: {
|
|
42906
|
-
dimension: "duration",
|
|
42907
|
-
factor: .001,
|
|
42908
|
-
offset: 0
|
|
42909
|
-
},
|
|
42910
|
-
min: {
|
|
42911
|
-
dimension: "duration",
|
|
42912
|
-
factor: 60,
|
|
42913
|
-
offset: 0
|
|
42914
|
-
},
|
|
42915
|
-
h: {
|
|
42916
|
-
dimension: "duration",
|
|
42917
|
-
factor: 3600,
|
|
42918
|
-
offset: 0
|
|
42919
|
-
},
|
|
42920
|
-
d: {
|
|
42921
|
-
dimension: "duration",
|
|
42922
|
-
factor: 86400,
|
|
42923
|
-
offset: 0
|
|
42924
|
-
},
|
|
42925
|
-
B: {
|
|
42926
|
-
dimension: "information",
|
|
42927
|
-
factor: 1,
|
|
42928
|
-
offset: 0
|
|
42929
|
-
},
|
|
42930
|
-
KiB: {
|
|
42931
|
-
dimension: "information",
|
|
42932
|
-
factor: 1024,
|
|
42933
|
-
offset: 0
|
|
42934
|
-
},
|
|
42935
|
-
MiB: {
|
|
42936
|
-
dimension: "information",
|
|
42937
|
-
factor: 1024 ** 2,
|
|
42938
|
-
offset: 0
|
|
42939
|
-
},
|
|
42940
|
-
GiB: {
|
|
42941
|
-
dimension: "information",
|
|
42942
|
-
factor: 1024 ** 3,
|
|
42943
|
-
offset: 0
|
|
42944
|
-
},
|
|
42945
|
-
TiB: {
|
|
42946
|
-
dimension: "information",
|
|
42947
|
-
factor: 1024 ** 4,
|
|
42948
|
-
offset: 0
|
|
42949
|
-
},
|
|
42950
|
-
kB: {
|
|
42951
|
-
dimension: "information",
|
|
42952
|
-
factor: 1e3,
|
|
42953
|
-
offset: 0
|
|
42954
|
-
},
|
|
42955
|
-
MB: {
|
|
42956
|
-
dimension: "information",
|
|
42957
|
-
factor: 1e6,
|
|
42958
|
-
offset: 0
|
|
42959
|
-
},
|
|
42960
|
-
GB: {
|
|
42961
|
-
dimension: "information",
|
|
42962
|
-
factor: 1e9,
|
|
42963
|
-
offset: 0
|
|
42964
|
-
},
|
|
42965
|
-
"°": {
|
|
42966
|
-
dimension: "angle",
|
|
42967
|
-
factor: 1,
|
|
42968
|
-
offset: 0
|
|
42969
|
-
},
|
|
42970
|
-
dBFS: {
|
|
42971
|
-
dimension: "sound-level",
|
|
42972
|
-
factor: 1,
|
|
42973
|
-
offset: 0
|
|
42974
|
-
},
|
|
42975
|
-
dBm: {
|
|
42976
|
-
dimension: "signal-level",
|
|
42977
|
-
factor: 1,
|
|
42978
|
-
offset: 0
|
|
42979
|
-
},
|
|
42980
|
-
mired: {
|
|
42981
|
-
dimension: "colour-temperature",
|
|
42982
|
-
factor: 1,
|
|
42983
|
-
offset: 0
|
|
42984
|
-
},
|
|
42985
|
-
kbps: {
|
|
42986
|
-
dimension: "bitrate",
|
|
42987
|
-
factor: 1,
|
|
42988
|
-
offset: 0
|
|
42989
|
-
},
|
|
42990
|
-
Mbps: {
|
|
42991
|
-
dimension: "bitrate",
|
|
42992
|
-
factor: 1e3,
|
|
42993
|
-
offset: 0
|
|
42994
|
-
},
|
|
42995
|
-
fps: {
|
|
42996
|
-
dimension: "rate",
|
|
42997
|
-
factor: 1,
|
|
42998
|
-
offset: 0
|
|
42999
|
-
}
|
|
43000
|
-
};
|
|
43001
|
-
/** Resolve a unit's `UnitSpec`, or `undefined` when the spelling is unknown. */
|
|
43002
|
-
function specFor(unit) {
|
|
43003
|
-
return Object.hasOwn(UNIT_TABLE, unit) ? UNIT_TABLE[unit] : void 0;
|
|
43004
|
-
}
|
|
43005
|
-
/** Value in `spec`'s unit → its dimension's canonical unit. */
|
|
43006
|
-
function toCanonical(value, spec) {
|
|
43007
|
-
return value * spec.factor + spec.offset;
|
|
43008
|
-
}
|
|
43009
|
-
/** Canonical-unit value → the unit described by `spec`. */
|
|
43010
|
-
function fromCanonical(canonical, spec) {
|
|
43011
|
-
return (canonical - spec.offset) / spec.factor;
|
|
43012
|
-
}
|
|
43013
|
-
/**
|
|
43014
|
-
* Graceful variant for the render path: returns the converted value, or
|
|
43015
|
-
* `undefined` when the conversion is refused (unknown unit / cross-dimension).
|
|
43016
|
-
* Never throws — a render caller falls back to the raw value + source unit.
|
|
43017
|
-
*/
|
|
43018
|
-
function tryConvertUnit(value, from, to) {
|
|
43019
|
-
if (from === to) return value;
|
|
43020
|
-
const fromSpec = specFor(from);
|
|
43021
|
-
if (!fromSpec) return void 0;
|
|
43022
|
-
const toSpec = specFor(to);
|
|
43023
|
-
if (!toSpec) return void 0;
|
|
43024
|
-
if (fromSpec.dimension !== toSpec.dimension) return void 0;
|
|
43025
|
-
return fromCanonical(toCanonical(value, fromSpec), toSpec);
|
|
43026
|
-
}
|
|
43027
|
-
/**
|
|
43028
43176
|
* A number a person types for a physical quantity — the input side of the
|
|
43029
43177
|
* value + unit contract (D972).
|
|
43030
43178
|
*
|
|
@@ -44701,15 +44849,28 @@ var SettingsSchemaWithValuesSchema = object({
|
|
|
44701
44849
|
});
|
|
44702
44850
|
/** Patch object — keys are field names, values are the new field values. */
|
|
44703
44851
|
var SettingsPatchSchema = record(string(), unknown());
|
|
44852
|
+
/** The scope of a scoped-settings call (D986): where the capability declared the values. */
|
|
44853
|
+
var ScopedSettingsScopeSchema = _enum(SCOPED_SETTINGS_SCOPES);
|
|
44854
|
+
/** One scoped schema an addon serves: its capability, scope and section ids. */
|
|
44855
|
+
var ScopedSettingsDeclarationSchema = object({
|
|
44856
|
+
cap: string(),
|
|
44857
|
+
scope: ScopedSettingsScopeSchema,
|
|
44858
|
+
sectionIds: array(string())
|
|
44859
|
+
});
|
|
44704
44860
|
/** Standard success response for update operations. */
|
|
44705
44861
|
var SettingsUpdateResultSchema = object({ success: literal(true) });
|
|
44706
44862
|
method(object({
|
|
44707
44863
|
addonId: string(),
|
|
44708
|
-
|
|
44709
|
-
|
|
44710
|
-
|
|
44864
|
+
cap: string(),
|
|
44865
|
+
scope: ScopedSettingsScopeSchema,
|
|
44866
|
+
nodeId: string().optional()
|
|
44711
44867
|
}), SettingsSchemaWithValuesSchema.nullable()), method(object({
|
|
44712
44868
|
addonId: string(),
|
|
44869
|
+
nodeId: string().optional()
|
|
44870
|
+
}), array(ScopedSettingsDeclarationSchema).nullable()), method(object({
|
|
44871
|
+
addonId: string(),
|
|
44872
|
+
cap: string(),
|
|
44873
|
+
scope: ScopedSettingsScopeSchema,
|
|
44713
44874
|
nodeId: string().optional(),
|
|
44714
44875
|
patch: SettingsPatchSchema
|
|
44715
44876
|
}), SettingsUpdateResultSchema, {
|
|
@@ -44717,8 +44878,10 @@ method(object({
|
|
|
44717
44878
|
auth: "admin"
|
|
44718
44879
|
}), method(object({
|
|
44719
44880
|
addonId: string(),
|
|
44881
|
+
cap: string(),
|
|
44882
|
+
scope: ScopedSettingsScopeSchema,
|
|
44720
44883
|
nodeId: string().optional()
|
|
44721
|
-
}),
|
|
44884
|
+
}), record(string(), unknown()).nullable()), method(object({
|
|
44722
44885
|
addonId: string(),
|
|
44723
44886
|
nodeId: string().optional(),
|
|
44724
44887
|
instance: IntegrationInstanceRefSchema
|
|
@@ -46058,7 +46221,7 @@ var BackupDestinationInfoSchema = object({
|
|
|
46058
46221
|
id: string(),
|
|
46059
46222
|
/**
|
|
46060
46223
|
* Manifest id of the owning addon. The Settings button on the
|
|
46061
|
-
* destination card opens that addon's
|
|
46224
|
+
* destination card opens that addon's scoped settings panel.
|
|
46062
46225
|
*/
|
|
46063
46226
|
addonId: string(),
|
|
46064
46227
|
/** Operator-toggled enable flag from the destination-policy table. */
|
|
@@ -50528,6 +50691,7 @@ method(InstancePinSchema, DeviceExportStatusSchema), method(_void(), array(Expor
|
|
|
50528
50691
|
kind: "mutation",
|
|
50529
50692
|
auth: "admin"
|
|
50530
50693
|
});
|
|
50694
|
+
var DeviceAliasSchema = string().max(64).regex(/^[a-z][a-z0-9_]*$/);
|
|
50531
50695
|
/**
|
|
50532
50696
|
* A SITE ZONE — a named part of the property that several locations belong to.
|
|
50533
50697
|
*
|
|
@@ -50921,6 +51085,12 @@ var DeviceInfoSchema = object({
|
|
|
50921
51085
|
addonId: string(),
|
|
50922
51086
|
type: _enum(DeviceType),
|
|
50923
51087
|
name: string(),
|
|
51088
|
+
/** The name a value template uses for this device (`{{ stufa_veranda.temperature }}`),
|
|
51089
|
+
* entity_id style. Generated once from the name at first registration, unique
|
|
51090
|
+
* cluster-wide, editable through `setAlias`, NOT changed by a rename (D1021).
|
|
51091
|
+
* Optional: a record produced by an older build omits it until the boot
|
|
51092
|
+
* backfill has run. */
|
|
51093
|
+
alias: DeviceAliasSchema.optional(),
|
|
50924
51094
|
/** Operator-organisational location label. `null` when unset. */
|
|
50925
51095
|
location: string().nullable(),
|
|
50926
51096
|
/** Soft-disabled flag. */
|
|
@@ -51240,6 +51410,25 @@ method(object({
|
|
|
51240
51410
|
}), _void(), {
|
|
51241
51411
|
kind: "mutation",
|
|
51242
51412
|
auth: "admin"
|
|
51413
|
+
}), method(object({
|
|
51414
|
+
deviceId: number(),
|
|
51415
|
+
alias: string()
|
|
51416
|
+
}), discriminatedUnion("ok", [object({
|
|
51417
|
+
ok: literal(true),
|
|
51418
|
+
alias: DeviceAliasSchema
|
|
51419
|
+
}), object({
|
|
51420
|
+
ok: literal(false),
|
|
51421
|
+
reason: _enum([
|
|
51422
|
+
"empty",
|
|
51423
|
+
"too-long",
|
|
51424
|
+
"grammar",
|
|
51425
|
+
"reserved",
|
|
51426
|
+
"taken"
|
|
51427
|
+
]),
|
|
51428
|
+
takenBy: number().optional()
|
|
51429
|
+
})]), {
|
|
51430
|
+
kind: "mutation",
|
|
51431
|
+
auth: "admin"
|
|
51243
51432
|
}), method(object({
|
|
51244
51433
|
deviceId: number(),
|
|
51245
51434
|
location: string().nullable()
|
|
@@ -54265,7 +54454,7 @@ method(_void(), array(IntegrationWithStateSchema)), method(object({ id: string()
|
|
|
54265
54454
|
* or the redaction token KEEPS the stored secret; `{ $secretClear: true }`
|
|
54266
54455
|
* clears it.
|
|
54267
54456
|
*/
|
|
54268
|
-
var ConfigSchemaPassthrough$
|
|
54457
|
+
var ConfigSchemaPassthrough$2 = custom();
|
|
54269
54458
|
var IntegrationInstanceIdSchema = string().min(1);
|
|
54270
54459
|
var IntegrationInstanceModeSchema = _enum(["single", "multiple"]);
|
|
54271
54460
|
/**
|
|
@@ -54311,7 +54500,16 @@ var IntegrationInstanceKindSchema = object({
|
|
|
54311
54500
|
/** Relative hub path to start an interactive account link of an instance of this kind. */
|
|
54312
54501
|
connectPath: string().min(1).optional(),
|
|
54313
54502
|
/** Relative hub path to disconnect that account. */
|
|
54314
|
-
disconnectPath: string().min(1).optional()
|
|
54503
|
+
disconnectPath: string().min(1).optional(),
|
|
54504
|
+
/**
|
|
54505
|
+
* Parts of the edit dialog the flat form cannot draw (a node picker, a model source), named by a
|
|
54506
|
+
* GENERIC widget id the client maps to a component; a client that knows none of them shows none.
|
|
54507
|
+
* `connection` widgets write connection values, `model` widgets own the model choice.
|
|
54508
|
+
*/
|
|
54509
|
+
widgets: array(object({
|
|
54510
|
+
id: string().min(1),
|
|
54511
|
+
placement: _enum(["connection", "model"])
|
|
54512
|
+
})).optional()
|
|
54315
54513
|
});
|
|
54316
54514
|
/**
|
|
54317
54515
|
* How devices of an instance are found. `none`: the operator adds them by hand; `lan`: the addon
|
|
@@ -54416,7 +54614,7 @@ var integrationInstancesCapability = {
|
|
|
54416
54614
|
id: IntegrationInstanceIdSchema.nullable(),
|
|
54417
54615
|
/** The kind of the create form (`id: null`) of a provider with several. */
|
|
54418
54616
|
kind: string().min(1).optional()
|
|
54419
|
-
}), ConfigSchemaPassthrough$
|
|
54617
|
+
}), ConfigSchemaPassthrough$2, { auth: "admin" }),
|
|
54420
54618
|
listInstances: method(_void(), array(IntegrationInstanceSchema).readonly(), { auth: "admin" }),
|
|
54421
54619
|
getInstance: method(object({ id: IntegrationInstanceIdSchema }), IntegrationInstanceSchema.nullable(), { auth: "admin" }),
|
|
54422
54620
|
/**
|
|
@@ -55367,12 +55565,12 @@ var LlmModelInfoSchema = object({
|
|
|
55367
55565
|
});
|
|
55368
55566
|
/**
|
|
55369
55567
|
* The provider-specific part of a profile, validated by the provider that owns
|
|
55370
|
-
* the kind (
|
|
55568
|
+
* the kind (saving an instance refuses what it does not accept). A field its
|
|
55371
55569
|
* `connectionSchema` declares `type: 'password'` is a secret: it is held in the
|
|
55372
55570
|
* keychain, never in the row, and reads back as the redaction marker.
|
|
55373
55571
|
*/
|
|
55374
55572
|
var LlmProviderConfigSchema = record(string(), unknown());
|
|
55375
|
-
|
|
55573
|
+
object({
|
|
55376
55574
|
id: string(),
|
|
55377
55575
|
name: string(),
|
|
55378
55576
|
/** The provider-declared kind (`LlmProfileKindDescriptor.kind`). */
|
|
@@ -55466,8 +55664,8 @@ var LlmProviderWidgetSchema = object({
|
|
|
55466
55664
|
/** ConfigUISchema tree passed through untyped on the wire (the
|
|
55467
55665
|
* notification-output `ConfigSchemaPassthrough` precedent at
|
|
55468
55666
|
* notification-output.cap.ts:151); the exported TS type re-tightens it. */
|
|
55469
|
-
var ConfigSchemaPassthrough$
|
|
55470
|
-
|
|
55667
|
+
var ConfigSchemaPassthrough$1 = unknown();
|
|
55668
|
+
object({
|
|
55471
55669
|
kind: LlmProfileKindSchema,
|
|
55472
55670
|
label: string(),
|
|
55473
55671
|
/** A generic icon name (`cloud`, `plug`, `cpu`) — never a glyph or a logo. */
|
|
@@ -55475,9 +55673,9 @@ var LlmProfileKindDescriptorSchema = object({
|
|
|
55475
55673
|
/** Stamped by each provider so the concat-fanned catalog stays routable. */
|
|
55476
55674
|
addonId: string(),
|
|
55477
55675
|
/** The provider's own fields (`providerConfig`); `password` fields are keychain-held. */
|
|
55478
|
-
connectionSchema: ConfigSchemaPassthrough$
|
|
55676
|
+
connectionSchema: ConfigSchemaPassthrough$1,
|
|
55479
55677
|
/** Provider fields that belong under "Advanced" (extra headers, runtime tuning). */
|
|
55480
|
-
advancedSchema: ConfigSchemaPassthrough$
|
|
55678
|
+
advancedSchema: ConfigSchemaPassthrough$1.optional(),
|
|
55481
55679
|
/** The kind's defaults; a model from `listModels` may override any of them. */
|
|
55482
55680
|
features: LlmModelFeaturesSchema,
|
|
55483
55681
|
/** `false` = the provider stamps `supportsVision` itself (from what a node reports). */
|
|
@@ -55606,20 +55804,7 @@ method(LlmGenerateBaseInputSchema, LlmGenerateResultSchema, {
|
|
|
55606
55804
|
}), method(object({
|
|
55607
55805
|
addonId: string().optional(),
|
|
55608
55806
|
requestId: string()
|
|
55609
|
-
}), _void(), { kind: "mutation" }), method(
|
|
55610
|
-
kind: "mutation",
|
|
55611
|
-
auth: "admin"
|
|
55612
|
-
}), method(RawSecretMigrationInputSchema, RawSecretMigrationReportSchema, {
|
|
55613
|
-
kind: "mutation",
|
|
55614
|
-
auth: "admin"
|
|
55615
|
-
}), method(ProfileRefInputSchema, _void(), {
|
|
55616
|
-
kind: "mutation",
|
|
55617
|
-
auth: "admin"
|
|
55618
|
-
}), method(ProfileRefInputSchema, LlmGenerateResultSchema, {
|
|
55619
|
-
kind: "mutation",
|
|
55620
|
-
auth: "admin",
|
|
55621
|
-
timeoutMs: AI_CAP_TRANSPORT_TIMEOUT_MS
|
|
55622
|
-
}), method(LlmListModelsInputSchema, LlmListModelsResultSchema, {
|
|
55807
|
+
}), _void(), { kind: "mutation" }), method(LlmListModelsInputSchema, LlmListModelsResultSchema, {
|
|
55623
55808
|
kind: "mutation",
|
|
55624
55809
|
auth: "admin"
|
|
55625
55810
|
}), method(object({}), array(LlmDefaultSchema)), method(object({
|
|
@@ -56614,20 +56799,7 @@ method(_void(), MeshStatusSchema), method(object({
|
|
|
56614
56799
|
/** Optional hostname override the host should advertise once joined. */
|
|
56615
56800
|
hostname: string().optional() }), object({
|
|
56616
56801
|
/** Authentication URL the operator should open in a browser. */
|
|
56617
|
-
loginUrl: string() }), { kind: "mutation" }), method(_void(), object({ left: literal(true) }), { kind: "mutation" }), method(_void(), object({ loggedOut: literal(true) }), { kind: "mutation" }), method(_void(), object({ peers: array(MeshPeerSchema).readonly() }))
|
|
56618
|
-
/** Optional auth key — when provided, probes the key validity
|
|
56619
|
-
* against the provider's API. Omit when already joined to
|
|
56620
|
-
* just ping the daemon. */
|
|
56621
|
-
authKey: string().optional() }), object({
|
|
56622
|
-
ok: boolean(),
|
|
56623
|
-
/** Provider-side identifier resolved by the probe (tailnet
|
|
56624
|
-
* name for Tailscale, network id for ZeroTier, etc.). */
|
|
56625
|
-
tenant: string().optional(),
|
|
56626
|
-
/** Daemon binary version, when reachable. */
|
|
56627
|
-
daemonVersion: string().optional(),
|
|
56628
|
-
/** Human-readable error when `ok: false`. */
|
|
56629
|
-
error: string().optional()
|
|
56630
|
-
}), { kind: "mutation" });
|
|
56802
|
+
loginUrl: string() }), { kind: "mutation" }), method(_void(), object({ left: literal(true) }), { kind: "mutation" }), method(_void(), object({ loggedOut: literal(true) }), { kind: "mutation" }), method(_void(), object({ peers: array(MeshPeerSchema).readonly() }));
|
|
56631
56803
|
object({
|
|
56632
56804
|
value: number().nullable().meta(readingMeta("device", { label: "Total" })),
|
|
56633
56805
|
lastFetchedAt: number()
|
|
@@ -64006,6 +64178,11 @@ var NcScheduleSchema = object({
|
|
|
64006
64178
|
* as a STATE SUMMARY at the end of each window of `schedule`.
|
|
64007
64179
|
*/
|
|
64008
64180
|
var NcSystemEventDeliveryModeSchema = _enum(["instant", "summary"]);
|
|
64181
|
+
_enum([
|
|
64182
|
+
"activation",
|
|
64183
|
+
"deactivation",
|
|
64184
|
+
"schedule"
|
|
64185
|
+
]);
|
|
64009
64186
|
/**
|
|
64010
64187
|
* How a summary window is SENT (D698): `rule` (absent) = ONE notification with
|
|
64011
64188
|
* every section; `section` = one notification per section with something to
|
|
@@ -64022,11 +64199,26 @@ var NcStateSummarySplitSchema = _enum(["rule", "section"]);
|
|
|
64022
64199
|
* midnight crossing); the send time is each window's END. Refused on the
|
|
64023
64200
|
* `alarm` family, which stays instant (`systemEventDeliveryProblems`).
|
|
64024
64201
|
*/
|
|
64025
|
-
var NcSystemEventDeliverySchema = discriminatedUnion("mode", [
|
|
64026
|
-
mode: literal("
|
|
64027
|
-
|
|
64028
|
-
|
|
64029
|
-
|
|
64202
|
+
var NcSystemEventDeliverySchema = discriminatedUnion("mode", [
|
|
64203
|
+
object({ mode: literal("instant") }),
|
|
64204
|
+
object({
|
|
64205
|
+
mode: literal("summary"),
|
|
64206
|
+
schedule: NcScheduleSchema,
|
|
64207
|
+
split: NcStateSummarySplitSchema.optional()
|
|
64208
|
+
}),
|
|
64209
|
+
object({
|
|
64210
|
+
mode: literal("modes"),
|
|
64211
|
+
/** The bad edge, and every kind that has a single edge. */
|
|
64212
|
+
onActivation: boolean(),
|
|
64213
|
+
/** The recovery edges of the classes of the selected kinds (derived, never stored per kind). */
|
|
64214
|
+
onDeactivation: boolean(),
|
|
64215
|
+
/** A state summary at the end of each window; absent = no summary. */
|
|
64216
|
+
onSchedule: object({
|
|
64217
|
+
schedule: NcScheduleSchema,
|
|
64218
|
+
grouping: NcStateSummarySplitSchema
|
|
64219
|
+
}).optional()
|
|
64220
|
+
})
|
|
64221
|
+
]);
|
|
64030
64222
|
/** Fuzzy plate matcher — OCR noise makes exact match useless (spec row 12/13). */
|
|
64031
64223
|
var NcPlateMatcherSchema = object({
|
|
64032
64224
|
/**
|
|
@@ -66303,61 +66495,6 @@ var OauthIntegrationDescriptorSchema = object({
|
|
|
66303
66495
|
});
|
|
66304
66496
|
method(_void(), OauthIntegrationDescriptorSchema, { auth: "admin" });
|
|
66305
66497
|
/**
|
|
66306
|
-
* `oidc-connections` — CRUD for IdP rows under `auth-oidc` (D828 sibling).
|
|
66307
|
-
*
|
|
66308
|
-
* One hub-only singleton (`auth-oidc`). The Settings UI is a DataTable +
|
|
66309
|
-
* ItemFormDialog; there is no `editable-array` in `globalSettingsSchema`.
|
|
66310
|
-
* Operator-chosen `id` is the URL slug (`/addon/auth-oidc/<id>/…`) and is
|
|
66311
|
-
* immutable after create.
|
|
66312
|
-
*/
|
|
66313
|
-
var ConfigSchemaPassthrough$1 = unknown();
|
|
66314
|
-
var OidcConnectionSchema = object({
|
|
66315
|
-
id: string().min(1),
|
|
66316
|
-
displayName: string(),
|
|
66317
|
-
icon: string(),
|
|
66318
|
-
issuerUrl: string(),
|
|
66319
|
-
clientId: string(),
|
|
66320
|
-
/** Client id + secret present — never the secret value. */
|
|
66321
|
-
configured: boolean(),
|
|
66322
|
-
/**
|
|
66323
|
-
* Values for the connection form schema. `clientSecret` is a keychain
|
|
66324
|
-
* {@link SecretFieldView} or `null` / `''`, never plaintext (D789).
|
|
66325
|
-
*/
|
|
66326
|
-
formValues: record(string(), unknown()).optional()
|
|
66327
|
-
});
|
|
66328
|
-
/**
|
|
66329
|
-
* Patch one connection. Omitted or empty `clientSecret` keeps the stored
|
|
66330
|
-
* secret (D787). `{ $secretClear: true }` clears it. `id` is never renamed.
|
|
66331
|
-
*/
|
|
66332
|
-
var OidcConnectionUpdateInputSchema = object({
|
|
66333
|
-
id: string().min(1),
|
|
66334
|
-
displayName: string().min(1),
|
|
66335
|
-
icon: string().optional(),
|
|
66336
|
-
issuerUrl: string().optional(),
|
|
66337
|
-
clientId: string().optional(),
|
|
66338
|
-
clientSecret: union([string(), object({ $secretClear: literal(true) })]).optional(),
|
|
66339
|
-
redirectUri: string().optional(),
|
|
66340
|
-
scopes: string().optional(),
|
|
66341
|
-
usernameClaim: _enum([
|
|
66342
|
-
"preferred_username",
|
|
66343
|
-
"email",
|
|
66344
|
-
"sub"
|
|
66345
|
-
]).optional()
|
|
66346
|
-
});
|
|
66347
|
-
method(object({}), ConfigSchemaPassthrough$1, { auth: "admin" }), method(object({}), array(OidcConnectionSchema).readonly(), { auth: "admin" }), method(object({
|
|
66348
|
-
id: string().min(1).regex(/^[a-z0-9][a-z0-9-]{0,63}$/, "id must be a lowercase slug"),
|
|
66349
|
-
displayName: string().min(1)
|
|
66350
|
-
}), object({ id: string() }), {
|
|
66351
|
-
kind: "mutation",
|
|
66352
|
-
auth: "admin"
|
|
66353
|
-
}), method(OidcConnectionUpdateInputSchema, object({ ok: literal(true) }), {
|
|
66354
|
-
kind: "mutation",
|
|
66355
|
-
auth: "admin"
|
|
66356
|
-
}), method(object({ id: string().min(1) }), object({ ok: literal(true) }), {
|
|
66357
|
-
kind: "mutation",
|
|
66358
|
-
auth: "admin"
|
|
66359
|
-
});
|
|
66360
|
-
/**
|
|
66361
66498
|
* Generic on-screen-display (video overlay) cap. Each camera exposes
|
|
66362
66499
|
* a firmware-defined list of overlays (channel name, timestamp,
|
|
66363
66500
|
* watermark, logo, …); the cap models them as a homogeneous array of
|
|
@@ -72530,21 +72667,6 @@ method(object({
|
|
|
72530
72667
|
*/
|
|
72531
72668
|
ttlSec: union([number().int().positive(), literal("never")]).optional()
|
|
72532
72669
|
}), object({ token: string() }), { auth: "admin" }), method(object({ token: string() }), SsoBridgeClaimsSchema.nullable(), { auth: "admin" });
|
|
72533
|
-
var ProviderListEntrySchema = discriminatedUnion("shouldSaveDiskSpace", [object({
|
|
72534
|
-
providerId: string().min(1),
|
|
72535
|
-
displayName: string().min(1),
|
|
72536
|
-
configSchema: unknown(),
|
|
72537
|
-
nodeLocal: boolean(),
|
|
72538
|
-
shouldSaveDiskSpace: literal(true),
|
|
72539
|
-
minFreePercent: number().min(0).max(100)
|
|
72540
|
-
}), object({
|
|
72541
|
-
providerId: string().min(1),
|
|
72542
|
-
displayName: string().min(1),
|
|
72543
|
-
configSchema: unknown(),
|
|
72544
|
-
nodeLocal: boolean(),
|
|
72545
|
-
shouldSaveDiskSpace: literal(false),
|
|
72546
|
-
minFreePercent: literal(null)
|
|
72547
|
-
})]);
|
|
72548
72670
|
method(object({
|
|
72549
72671
|
location: StorageLocationRefSchema,
|
|
72550
72672
|
relativePath: string()
|
|
@@ -72606,42 +72728,7 @@ method(object({
|
|
|
72606
72728
|
}), _instanceof(Uint8Array), { auth: "admin" }), method(object({ downloadId: string() }), _void(), {
|
|
72607
72729
|
kind: "mutation",
|
|
72608
72730
|
auth: "admin"
|
|
72609
|
-
}), method(object({ type: StorageLocationTypeSchema.optional() }), array(StorageLocationSchema).readonly()), method(_void(), array(StorageLocationDeclarationSchema).readonly()), method(
|
|
72610
|
-
createdAt: true,
|
|
72611
|
-
updatedAt: true
|
|
72612
|
-
}), StorageLocationSchema, {
|
|
72613
|
-
kind: "mutation",
|
|
72614
|
-
auth: "admin"
|
|
72615
|
-
}), method(object({
|
|
72616
|
-
id: string(),
|
|
72617
|
-
force: boolean().optional()
|
|
72618
|
-
}), _void(), {
|
|
72619
|
-
kind: "mutation",
|
|
72620
|
-
auth: "admin"
|
|
72621
|
-
}), method(_void(), array(StorageDrainProgressSchema).readonly()), method(object({ id: string() }), object({
|
|
72622
|
-
ok: boolean(),
|
|
72623
|
-
error: string().optional()
|
|
72624
|
-
}), { auth: "admin" }), method(_void(), array(ProviderListEntrySchema).readonly()), method(object({
|
|
72625
|
-
providerId: string(),
|
|
72626
|
-
/**
|
|
72627
|
-
* The location this config is an UNSAVED edit of, when there is one.
|
|
72628
|
-
*
|
|
72629
|
-
* `listLocations` replaces every declared secret with the redaction
|
|
72630
|
-
* sentinel, so the edit modal's form state holds the sentinel for any
|
|
72631
|
-
* credential the operator did not retype — and posting that here
|
|
72632
|
-
* without a way to resolve it makes the provider try to authenticate
|
|
72633
|
-
* as `__camstack_redacted__` and report the operator's own working
|
|
72634
|
-
* password as wrong. Given this id, the orchestrator restores each
|
|
72635
|
-
* sentinel from the stored config (same rule as `upsertLocation`)
|
|
72636
|
-
* before dispatching. Omitted by the "Add location" wizard, where
|
|
72637
|
-
* every value was typed just now and nothing is stored yet.
|
|
72638
|
-
*/
|
|
72639
|
-
locationId: string().optional(),
|
|
72640
|
-
config: record(string(), unknown())
|
|
72641
|
-
}), object({
|
|
72642
|
-
ok: boolean(),
|
|
72643
|
-
error: string().optional()
|
|
72644
|
-
}), { auth: "admin" });
|
|
72731
|
+
}), method(object({ type: StorageLocationTypeSchema.optional() }), array(StorageLocationSchema).readonly()), method(_void(), array(StorageLocationDeclarationSchema).readonly()), method(_void(), array(StorageDrainProgressSchema).readonly());
|
|
72645
72732
|
/** One table of the settings database. */
|
|
72646
72733
|
var StorageTableSchema = object({
|
|
72647
72734
|
/** The table's full name, e.g. `recorder:addon-settings` or `addon-device-settings`. */
|
|
@@ -73872,7 +73959,7 @@ var TerminalInstanceInfoSchema = object({
|
|
|
73872
73959
|
/**
|
|
73873
73960
|
* False while the node the instance is bound to is not in the cluster
|
|
73874
73961
|
* topology (forgotten, renamed, re-paired). The instance is kept; the
|
|
73875
|
-
* operator re-points it
|
|
73962
|
+
* operator re-points it on the Terminal page.
|
|
73876
73963
|
*/
|
|
73877
73964
|
nodeInCluster: boolean(),
|
|
73878
73965
|
profileId: string(),
|
|
@@ -73910,41 +73997,7 @@ var TerminalOutputBatchSchema = object({
|
|
|
73910
73997
|
snapshot: string().optional(),
|
|
73911
73998
|
events: array(TerminalOutputEventSchema).readonly()
|
|
73912
73999
|
});
|
|
73913
|
-
method(_void(), array(TerminalProfileInfoSchema).readonly(), { auth: "admin" }), method(_void(), array(
|
|
73914
|
-
targetNodeId: string().min(1),
|
|
73915
|
-
profileId: string().min(1),
|
|
73916
|
-
name: string().trim().min(1).max(160).optional(),
|
|
73917
|
-
executable: string().max(1024).optional(),
|
|
73918
|
-
args: array(string().max(2048)).max(64).optional(),
|
|
73919
|
-
cwd: string().max(1024).optional(),
|
|
73920
|
-
environment: array(string().max(4096)).max(64).optional(),
|
|
73921
|
-
profileSettings: ProfileSettingsBagSchema.optional()
|
|
73922
|
-
}), TerminalInstanceInfoSchema, {
|
|
73923
|
-
kind: "mutation",
|
|
73924
|
-
auth: "admin"
|
|
73925
|
-
}), method(object({
|
|
73926
|
-
instanceId: string().min(1),
|
|
73927
|
-
/** Re-point the instance to another node; the profile must exist there. */
|
|
73928
|
-
targetNodeId: string().min(1).max(256).optional(),
|
|
73929
|
-
name: string().trim().min(1).max(160).optional(),
|
|
73930
|
-
executable: string().max(1024).optional(),
|
|
73931
|
-
args: array(string().max(2048)).max(64).optional(),
|
|
73932
|
-
cwd: string().max(1024).optional(),
|
|
73933
|
-
environment: array(string().max(4096)).max(64).optional(),
|
|
73934
|
-
profileSettings: ProfileSettingsBagSchema.optional()
|
|
73935
|
-
}), TerminalInstanceInfoSchema, {
|
|
73936
|
-
kind: "mutation",
|
|
73937
|
-
auth: "admin"
|
|
73938
|
-
}), method(object({ instanceId: string().min(1) }), _void(), {
|
|
73939
|
-
kind: "mutation",
|
|
73940
|
-
auth: "admin"
|
|
73941
|
-
}), method(object({
|
|
73942
|
-
instanceId: string().min(1),
|
|
73943
|
-
enabled: boolean()
|
|
73944
|
-
}), TerminalInstanceInfoSchema, {
|
|
73945
|
-
kind: "mutation",
|
|
73946
|
-
auth: "admin"
|
|
73947
|
-
}), method(_void(), array(TerminalLegacyCameraSchema).readonly(), { auth: "admin" }), method(object({
|
|
74000
|
+
method(_void(), array(TerminalProfileInfoSchema).readonly(), { auth: "admin" }), method(_void(), array(TerminalLegacyCameraSchema).readonly(), { auth: "admin" }), method(object({
|
|
73948
74001
|
stableId: string().min(1),
|
|
73949
74002
|
name: string().trim().min(1).max(160).optional()
|
|
73950
74003
|
}), TerminalInstanceInfoSchema, {
|
|
@@ -74013,6 +74066,11 @@ var TimedRunUnitSchema = _enum(["s", "min"]);
|
|
|
74013
74066
|
_enum(["switch", "pet-fountain"]);
|
|
74014
74067
|
DeviceType.Heater, DeviceType.PetFountain;
|
|
74015
74068
|
DeviceType.Heater, DeviceType.PetFountain;
|
|
74069
|
+
/** One duration, as the one-tap run asks for it. */
|
|
74070
|
+
var TimedRunQuickRunSchema = object({
|
|
74071
|
+
duration: number().positive().finite(),
|
|
74072
|
+
unit: TimedRunUnitSchema
|
|
74073
|
+
});
|
|
74016
74074
|
/** Why a request was not carried out. Typed, so a caller can say it in words. */
|
|
74017
74075
|
var TimedRunRefusalSchema = _enum([
|
|
74018
74076
|
"unsupported-device",
|
|
@@ -74033,9 +74091,30 @@ object({
|
|
|
74033
74091
|
activeUntil: number().nullable(),
|
|
74034
74092
|
/** Who asked for the run (a user id or an addon id); `null` when nothing is armed or it did not say. */
|
|
74035
74093
|
requestedBy: string().nullable(),
|
|
74094
|
+
/**
|
|
74095
|
+
* The one-tap run of THIS device: what a "Run" button on any surface starts. `null` when
|
|
74096
|
+
* the device is gone or its type has no timed run; a status from before this field
|
|
74097
|
+
* existed has none, and a surface falls back to the type's default.
|
|
74098
|
+
*/
|
|
74099
|
+
quickRun: TimedRunQuickRunSchema.nullable(),
|
|
74036
74100
|
lastFetchedAt: number()
|
|
74037
74101
|
});
|
|
74038
|
-
|
|
74102
|
+
/** What the settings form needs: the unit, the bounds and the type's default. */
|
|
74103
|
+
var TimedRunOptionsSchema = object({
|
|
74104
|
+
unit: TimedRunUnitSchema,
|
|
74105
|
+
/** The longest run, in `unit`. */
|
|
74106
|
+
maxDuration: number(),
|
|
74107
|
+
defaultDuration: number()
|
|
74108
|
+
});
|
|
74109
|
+
/** The one-tap run duration, in the type's unit; `null` returns to the type's default. */
|
|
74110
|
+
var TimedRunSettingsPatchSchema = object({ quickRunDuration: number().positive().finite().nullable().optional() });
|
|
74111
|
+
method(object({ deviceId: number().int() }), TimedRunOptionsSchema), method(object({
|
|
74112
|
+
deviceId: number().int(),
|
|
74113
|
+
settings: TimedRunSettingsPatchSchema
|
|
74114
|
+
}), _void(), {
|
|
74115
|
+
kind: "mutation",
|
|
74116
|
+
auth: "admin"
|
|
74117
|
+
}), method(object({
|
|
74039
74118
|
deviceId: number().int(),
|
|
74040
74119
|
duration: number().positive().finite(),
|
|
74041
74120
|
unit: TimedRunUnitSchema
|
|
@@ -76741,21 +76820,28 @@ Object.freeze({
|
|
|
76741
76820
|
access: "view",
|
|
76742
76821
|
role: "admin"
|
|
76743
76822
|
},
|
|
76744
|
-
"addonSettings.
|
|
76823
|
+
"addonSettings.getIntegrationFormSchema": {
|
|
76824
|
+
capName: "addon-settings",
|
|
76825
|
+
capScope: "system",
|
|
76826
|
+
addonId: null,
|
|
76827
|
+
access: "view",
|
|
76828
|
+
role: "admin"
|
|
76829
|
+
},
|
|
76830
|
+
"addonSettings.getScopedSettings": {
|
|
76745
76831
|
capName: "addon-settings",
|
|
76746
76832
|
capScope: "system",
|
|
76747
76833
|
addonId: null,
|
|
76748
76834
|
access: "view",
|
|
76749
76835
|
role: "admin"
|
|
76750
76836
|
},
|
|
76751
|
-
"addonSettings.
|
|
76837
|
+
"addonSettings.listScopedSettings": {
|
|
76752
76838
|
capName: "addon-settings",
|
|
76753
76839
|
capScope: "system",
|
|
76754
76840
|
addonId: null,
|
|
76755
76841
|
access: "view",
|
|
76756
76842
|
role: "admin"
|
|
76757
76843
|
},
|
|
76758
|
-
"addonSettings.
|
|
76844
|
+
"addonSettings.readScopedValues": {
|
|
76759
76845
|
capName: "addon-settings",
|
|
76760
76846
|
capScope: "system",
|
|
76761
76847
|
addonId: null,
|
|
@@ -76776,7 +76862,7 @@ Object.freeze({
|
|
|
76776
76862
|
access: "create",
|
|
76777
76863
|
role: "admin"
|
|
76778
76864
|
},
|
|
76779
|
-
"addonSettings.
|
|
76865
|
+
"addonSettings.updateScopedSettings": {
|
|
76780
76866
|
capName: "addon-settings",
|
|
76781
76867
|
capScope: "system",
|
|
76782
76868
|
addonId: null,
|
|
@@ -78946,6 +79032,13 @@ Object.freeze({
|
|
|
78946
79032
|
access: "create",
|
|
78947
79033
|
role: "admin"
|
|
78948
79034
|
},
|
|
79035
|
+
"deviceManager.setAlias": {
|
|
79036
|
+
capName: "device-manager",
|
|
79037
|
+
capScope: "system",
|
|
79038
|
+
addonId: null,
|
|
79039
|
+
access: "create",
|
|
79040
|
+
role: "admin"
|
|
79041
|
+
},
|
|
78949
79042
|
"deviceManager.setChildLayout": {
|
|
78950
79043
|
capName: "device-manager",
|
|
78951
79044
|
capScope: "system",
|
|
@@ -80234,13 +80327,6 @@ Object.freeze({
|
|
|
80234
80327
|
access: "delete",
|
|
80235
80328
|
role: "admin"
|
|
80236
80329
|
},
|
|
80237
|
-
"llm.deleteProfile": {
|
|
80238
|
-
capName: "llm",
|
|
80239
|
-
capScope: "system",
|
|
80240
|
-
addonId: null,
|
|
80241
|
-
access: "delete",
|
|
80242
|
-
role: "admin"
|
|
80243
|
-
},
|
|
80244
80330
|
"llm.generate": {
|
|
80245
80331
|
capName: "llm",
|
|
80246
80332
|
capScope: "system",
|
|
@@ -80304,20 +80390,6 @@ Object.freeze({
|
|
|
80304
80390
|
access: "view",
|
|
80305
80391
|
role: "admin"
|
|
80306
80392
|
},
|
|
80307
|
-
"llm.listProfileKinds": {
|
|
80308
|
-
capName: "llm",
|
|
80309
|
-
capScope: "system",
|
|
80310
|
-
addonId: null,
|
|
80311
|
-
access: "view",
|
|
80312
|
-
role: "admin"
|
|
80313
|
-
},
|
|
80314
|
-
"llm.listProfiles": {
|
|
80315
|
-
capName: "llm",
|
|
80316
|
-
capScope: "system",
|
|
80317
|
-
addonId: null,
|
|
80318
|
-
access: "view",
|
|
80319
|
-
role: "admin"
|
|
80320
|
-
},
|
|
80321
80393
|
"llm.listRuntimeNodes": {
|
|
80322
80394
|
capName: "llm",
|
|
80323
80395
|
capScope: "system",
|
|
@@ -80325,13 +80397,6 @@ Object.freeze({
|
|
|
80325
80397
|
access: "view",
|
|
80326
80398
|
role: "admin"
|
|
80327
80399
|
},
|
|
80328
|
-
"llm.migrateRawSecrets": {
|
|
80329
|
-
capName: "llm",
|
|
80330
|
-
capScope: "system",
|
|
80331
|
-
addonId: null,
|
|
80332
|
-
access: "create",
|
|
80333
|
-
role: "admin"
|
|
80334
|
-
},
|
|
80335
80400
|
"llm.resolveModelRef": {
|
|
80336
80401
|
capName: "llm",
|
|
80337
80402
|
capScope: "system",
|
|
@@ -80360,20 +80425,6 @@ Object.freeze({
|
|
|
80360
80425
|
access: "create",
|
|
80361
80426
|
role: "admin"
|
|
80362
80427
|
},
|
|
80363
|
-
"llm.testProfile": {
|
|
80364
|
-
capName: "llm",
|
|
80365
|
-
capScope: "system",
|
|
80366
|
-
addonId: null,
|
|
80367
|
-
access: "create",
|
|
80368
|
-
role: "admin"
|
|
80369
|
-
},
|
|
80370
|
-
"llm.upsertProfile": {
|
|
80371
|
-
capName: "llm",
|
|
80372
|
-
capScope: "system",
|
|
80373
|
-
addonId: null,
|
|
80374
|
-
access: "create",
|
|
80375
|
-
role: "admin"
|
|
80376
|
-
},
|
|
80377
80428
|
"llmRuntime.appleAvailability": {
|
|
80378
80429
|
capName: "llm-runtime",
|
|
80379
80430
|
capScope: "system",
|
|
@@ -80878,13 +80929,6 @@ Object.freeze({
|
|
|
80878
80929
|
access: "create",
|
|
80879
80930
|
role: "admin"
|
|
80880
80931
|
},
|
|
80881
|
-
"meshNetwork.testConnection": {
|
|
80882
|
-
capName: "mesh-network",
|
|
80883
|
-
capScope: "system",
|
|
80884
|
-
addonId: null,
|
|
80885
|
-
access: "create",
|
|
80886
|
-
role: "admin"
|
|
80887
|
-
},
|
|
80888
80932
|
"meter.getStatus": {
|
|
80889
80933
|
capName: "meter",
|
|
80890
80934
|
capScope: "device",
|
|
@@ -81543,13 +81587,6 @@ Object.freeze({
|
|
|
81543
81587
|
access: "create",
|
|
81544
81588
|
role: "admin"
|
|
81545
81589
|
},
|
|
81546
|
-
"notificationOutput.deleteTarget": {
|
|
81547
|
-
capName: "notification-output",
|
|
81548
|
-
capScope: "system",
|
|
81549
|
-
addonId: null,
|
|
81550
|
-
access: "delete",
|
|
81551
|
-
role: "admin"
|
|
81552
|
-
},
|
|
81553
81590
|
"notificationOutput.discoverTargets": {
|
|
81554
81591
|
capName: "notification-output",
|
|
81555
81592
|
capScope: "system",
|
|
@@ -81557,13 +81594,6 @@ Object.freeze({
|
|
|
81557
81594
|
access: "view",
|
|
81558
81595
|
role: "admin"
|
|
81559
81596
|
},
|
|
81560
|
-
"notificationOutput.getTarget": {
|
|
81561
|
-
capName: "notification-output",
|
|
81562
|
-
capScope: "system",
|
|
81563
|
-
addonId: null,
|
|
81564
|
-
access: "view",
|
|
81565
|
-
role: "admin"
|
|
81566
|
-
},
|
|
81567
81597
|
"notificationOutput.listTargetKinds": {
|
|
81568
81598
|
capName: "notification-output",
|
|
81569
81599
|
capScope: "system",
|
|
@@ -81571,13 +81601,6 @@ Object.freeze({
|
|
|
81571
81601
|
access: "view",
|
|
81572
81602
|
role: "admin"
|
|
81573
81603
|
},
|
|
81574
|
-
"notificationOutput.listTargets": {
|
|
81575
|
-
capName: "notification-output",
|
|
81576
|
-
capScope: "system",
|
|
81577
|
-
addonId: null,
|
|
81578
|
-
access: "view",
|
|
81579
|
-
role: "admin"
|
|
81580
|
-
},
|
|
81581
81604
|
"notificationOutput.probeTargetConfig": {
|
|
81582
81605
|
capName: "notification-output",
|
|
81583
81606
|
capScope: "system",
|
|
@@ -81592,13 +81615,6 @@ Object.freeze({
|
|
|
81592
81615
|
access: "create",
|
|
81593
81616
|
role: "admin"
|
|
81594
81617
|
},
|
|
81595
|
-
"notificationOutput.setTargetEnabled": {
|
|
81596
|
-
capName: "notification-output",
|
|
81597
|
-
capScope: "system",
|
|
81598
|
-
addonId: null,
|
|
81599
|
-
access: "create",
|
|
81600
|
-
role: "admin"
|
|
81601
|
-
},
|
|
81602
81618
|
"notificationOutput.testTarget": {
|
|
81603
81619
|
capName: "notification-output",
|
|
81604
81620
|
capScope: "system",
|
|
@@ -81606,13 +81622,6 @@ Object.freeze({
|
|
|
81606
81622
|
access: "create",
|
|
81607
81623
|
role: "admin"
|
|
81608
81624
|
},
|
|
81609
|
-
"notificationOutput.upsertTarget": {
|
|
81610
|
-
capName: "notification-output",
|
|
81611
|
-
capScope: "system",
|
|
81612
|
-
addonId: null,
|
|
81613
|
-
access: "create",
|
|
81614
|
-
role: "admin"
|
|
81615
|
-
},
|
|
81616
81625
|
"notificationRules.activateAlarmProfile": {
|
|
81617
81626
|
capName: "notification-rules",
|
|
81618
81627
|
capScope: "system",
|
|
@@ -81872,41 +81881,6 @@ Object.freeze({
|
|
|
81872
81881
|
access: "view",
|
|
81873
81882
|
role: "admin"
|
|
81874
81883
|
},
|
|
81875
|
-
"oidcConnections.connectionFormSchema": {
|
|
81876
|
-
capName: "oidc-connections",
|
|
81877
|
-
capScope: "system",
|
|
81878
|
-
addonId: null,
|
|
81879
|
-
access: "view",
|
|
81880
|
-
role: "admin"
|
|
81881
|
-
},
|
|
81882
|
-
"oidcConnections.createConnection": {
|
|
81883
|
-
capName: "oidc-connections",
|
|
81884
|
-
capScope: "system",
|
|
81885
|
-
addonId: null,
|
|
81886
|
-
access: "create",
|
|
81887
|
-
role: "admin"
|
|
81888
|
-
},
|
|
81889
|
-
"oidcConnections.deleteConnection": {
|
|
81890
|
-
capName: "oidc-connections",
|
|
81891
|
-
capScope: "system",
|
|
81892
|
-
addonId: null,
|
|
81893
|
-
access: "delete",
|
|
81894
|
-
role: "admin"
|
|
81895
|
-
},
|
|
81896
|
-
"oidcConnections.listConnections": {
|
|
81897
|
-
capName: "oidc-connections",
|
|
81898
|
-
capScope: "system",
|
|
81899
|
-
addonId: null,
|
|
81900
|
-
access: "view",
|
|
81901
|
-
role: "admin"
|
|
81902
|
-
},
|
|
81903
|
-
"oidcConnections.updateConnection": {
|
|
81904
|
-
capName: "oidc-connections",
|
|
81905
|
-
capScope: "system",
|
|
81906
|
-
addonId: null,
|
|
81907
|
-
access: "create",
|
|
81908
|
-
role: "admin"
|
|
81909
|
-
},
|
|
81910
81884
|
"osd.getStatus": {
|
|
81911
81885
|
capName: "osd",
|
|
81912
81886
|
capScope: "device",
|
|
@@ -84938,13 +84912,6 @@ Object.freeze({
|
|
|
84938
84912
|
access: "delete",
|
|
84939
84913
|
role: "admin"
|
|
84940
84914
|
},
|
|
84941
|
-
"storage.deleteLocation": {
|
|
84942
|
-
capName: "storage",
|
|
84943
|
-
capScope: "system",
|
|
84944
|
-
addonId: null,
|
|
84945
|
-
access: "delete",
|
|
84946
|
-
role: "admin"
|
|
84947
|
-
},
|
|
84948
84915
|
"storage.endDownload": {
|
|
84949
84916
|
capName: "storage",
|
|
84950
84917
|
capScope: "system",
|
|
@@ -85001,13 +84968,6 @@ Object.freeze({
|
|
|
85001
84968
|
access: "view",
|
|
85002
84969
|
role: "admin"
|
|
85003
84970
|
},
|
|
85004
|
-
"storage.listProviders": {
|
|
85005
|
-
capName: "storage",
|
|
85006
|
-
capScope: "system",
|
|
85007
|
-
addonId: null,
|
|
85008
|
-
access: "view",
|
|
85009
|
-
role: "admin"
|
|
85010
|
-
},
|
|
85011
84971
|
"storage.read": {
|
|
85012
84972
|
capName: "storage",
|
|
85013
84973
|
capScope: "system",
|
|
@@ -85029,27 +84989,6 @@ Object.freeze({
|
|
|
85029
84989
|
access: "view",
|
|
85030
84990
|
role: "admin"
|
|
85031
84991
|
},
|
|
85032
|
-
"storage.testConfig": {
|
|
85033
|
-
capName: "storage",
|
|
85034
|
-
capScope: "system",
|
|
85035
|
-
addonId: null,
|
|
85036
|
-
access: "view",
|
|
85037
|
-
role: "admin"
|
|
85038
|
-
},
|
|
85039
|
-
"storage.testLocation": {
|
|
85040
|
-
capName: "storage",
|
|
85041
|
-
capScope: "system",
|
|
85042
|
-
addonId: null,
|
|
85043
|
-
access: "view",
|
|
85044
|
-
role: "admin"
|
|
85045
|
-
},
|
|
85046
|
-
"storage.upsertLocation": {
|
|
85047
|
-
capName: "storage",
|
|
85048
|
-
capScope: "system",
|
|
85049
|
-
addonId: null,
|
|
85050
|
-
access: "create",
|
|
85051
|
-
role: "admin"
|
|
85052
|
-
},
|
|
85053
84992
|
"storage.write": {
|
|
85054
84993
|
capName: "storage",
|
|
85055
84994
|
capScope: "system",
|
|
@@ -85827,27 +85766,6 @@ Object.freeze({
|
|
|
85827
85766
|
access: "create",
|
|
85828
85767
|
role: "admin"
|
|
85829
85768
|
},
|
|
85830
|
-
"terminalSession.createInstance": {
|
|
85831
|
-
capName: "terminal-session",
|
|
85832
|
-
capScope: "system",
|
|
85833
|
-
addonId: null,
|
|
85834
|
-
access: "create",
|
|
85835
|
-
role: "admin"
|
|
85836
|
-
},
|
|
85837
|
-
"terminalSession.deleteInstance": {
|
|
85838
|
-
capName: "terminal-session",
|
|
85839
|
-
capScope: "system",
|
|
85840
|
-
addonId: null,
|
|
85841
|
-
access: "delete",
|
|
85842
|
-
role: "admin"
|
|
85843
|
-
},
|
|
85844
|
-
"terminalSession.listInstances": {
|
|
85845
|
-
capName: "terminal-session",
|
|
85846
|
-
capScope: "system",
|
|
85847
|
-
addonId: null,
|
|
85848
|
-
access: "view",
|
|
85849
|
-
role: "admin"
|
|
85850
|
-
},
|
|
85851
85769
|
"terminalSession.listLegacyCameras": {
|
|
85852
85770
|
capName: "terminal-session",
|
|
85853
85771
|
capScope: "system",
|
|
@@ -85890,20 +85808,6 @@ Object.freeze({
|
|
|
85890
85808
|
access: "create",
|
|
85891
85809
|
role: "admin"
|
|
85892
85810
|
},
|
|
85893
|
-
"terminalSession.setInstanceEnabled": {
|
|
85894
|
-
capName: "terminal-session",
|
|
85895
|
-
capScope: "system",
|
|
85896
|
-
addonId: null,
|
|
85897
|
-
access: "create",
|
|
85898
|
-
role: "admin"
|
|
85899
|
-
},
|
|
85900
|
-
"terminalSession.updateInstance": {
|
|
85901
|
-
capName: "terminal-session",
|
|
85902
|
-
capScope: "system",
|
|
85903
|
-
addonId: null,
|
|
85904
|
-
access: "create",
|
|
85905
|
-
role: "admin"
|
|
85906
|
-
},
|
|
85907
85811
|
"terminalSession.writeInput": {
|
|
85908
85812
|
capName: "terminal-session",
|
|
85909
85813
|
capScope: "system",
|
|
@@ -85918,6 +85822,13 @@ Object.freeze({
|
|
|
85918
85822
|
access: "create",
|
|
85919
85823
|
role: "viewer"
|
|
85920
85824
|
},
|
|
85825
|
+
"timedRun.getOptions": {
|
|
85826
|
+
capName: "timed-run",
|
|
85827
|
+
capScope: "device",
|
|
85828
|
+
addonId: null,
|
|
85829
|
+
access: "view",
|
|
85830
|
+
role: "viewer"
|
|
85831
|
+
},
|
|
85921
85832
|
"timedRun.getStatus": {
|
|
85922
85833
|
capName: "timed-run",
|
|
85923
85834
|
capScope: "device",
|
|
@@ -85932,6 +85843,13 @@ Object.freeze({
|
|
|
85932
85843
|
access: "create",
|
|
85933
85844
|
role: "viewer"
|
|
85934
85845
|
},
|
|
85846
|
+
"timedRun.setSettings": {
|
|
85847
|
+
capName: "timed-run",
|
|
85848
|
+
capScope: "device",
|
|
85849
|
+
addonId: null,
|
|
85850
|
+
access: "create",
|
|
85851
|
+
role: "admin"
|
|
85852
|
+
},
|
|
85935
85853
|
"toast.onToast": {
|
|
85936
85854
|
capName: "toast",
|
|
85937
85855
|
capScope: "system",
|
|
@@ -86862,6 +86780,7 @@ function offered(received) {
|
|
|
86862
86780
|
};
|
|
86863
86781
|
}
|
|
86864
86782
|
offered(HA_AS), withheld(HOMEKIT_REASON), withheld(ALEXA_REASON), withheld(GOOGLE_REASON), withheld(MATTER_REASON);
|
|
86783
|
+
string().min(1).max(4096);
|
|
86865
86784
|
Object.freeze({
|
|
86866
86785
|
"accessories.getStatus": [{
|
|
86867
86786
|
name: "deviceId",
|
|
@@ -87545,6 +87464,11 @@ Object.freeze({
|
|
|
87545
87464
|
form: "single",
|
|
87546
87465
|
optional: false
|
|
87547
87466
|
}],
|
|
87467
|
+
"deviceManager.setAlias": [{
|
|
87468
|
+
name: "deviceId",
|
|
87469
|
+
form: "single",
|
|
87470
|
+
optional: false
|
|
87471
|
+
}],
|
|
87548
87472
|
"deviceManager.setChildLayout": [{
|
|
87549
87473
|
name: "deviceId",
|
|
87550
87474
|
form: "single",
|
|
@@ -89609,6 +89533,11 @@ Object.freeze({
|
|
|
89609
89533
|
form: "single",
|
|
89610
89534
|
optional: false
|
|
89611
89535
|
}],
|
|
89536
|
+
"timedRun.getOptions": [{
|
|
89537
|
+
name: "deviceId",
|
|
89538
|
+
form: "single",
|
|
89539
|
+
optional: false
|
|
89540
|
+
}],
|
|
89612
89541
|
"timedRun.getStatus": [{
|
|
89613
89542
|
name: "deviceId",
|
|
89614
89543
|
form: "single",
|
|
@@ -89619,6 +89548,11 @@ Object.freeze({
|
|
|
89619
89548
|
form: "single",
|
|
89620
89549
|
optional: false
|
|
89621
89550
|
}],
|
|
89551
|
+
"timedRun.setSettings": [{
|
|
89552
|
+
name: "deviceId",
|
|
89553
|
+
form: "single",
|
|
89554
|
+
optional: false
|
|
89555
|
+
}],
|
|
89622
89556
|
"update.getStatus": [{
|
|
89623
89557
|
name: "deviceId",
|
|
89624
89558
|
form: "single",
|
|
@@ -90481,6 +90415,7 @@ var STATE_SUMMARY_VARS = [
|
|
|
90481
90415
|
[...RULE_TEXT],
|
|
90482
90416
|
[...RULE_TEXT],
|
|
90483
90417
|
[...RULE_TEXT],
|
|
90418
|
+
[...RULE_TEXT],
|
|
90484
90419
|
[...RULE_BODY_ONLY],
|
|
90485
90420
|
[...RULE_TEXT],
|
|
90486
90421
|
([...RULE_TEXT], [...DEVICE_EVENTS]),
|