@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
|
@@ -46,7 +46,7 @@ let node_fs = require("node:fs");
|
|
|
46
46
|
node_fs = __toESM(node_fs);
|
|
47
47
|
let node_path = require("node:path");
|
|
48
48
|
node_path = __toESM(node_path);
|
|
49
|
-
//#region ../types/dist/event-category-
|
|
49
|
+
//#region ../types/dist/event-category-78tcBemo.mjs
|
|
50
50
|
var EventCategory = /* @__PURE__ */ function(EventCategory) {
|
|
51
51
|
EventCategory["SystemBoot"] = "system.boot";
|
|
52
52
|
EventCategory["SystemAddonsReady"] = "system.addons-ready";
|
|
@@ -167,6 +167,23 @@ var EventCategory = /* @__PURE__ */ function(EventCategory) {
|
|
|
167
167
|
*/
|
|
168
168
|
EventCategory["AddonLoadRecovered"] = "addon.load-recovered";
|
|
169
169
|
/**
|
|
170
|
+
* An addon is RUNNING although its installed package is below what the
|
|
171
|
+
* running server requires (`camstack.requires.addons` of the server, or the
|
|
172
|
+
* addon's own `requires.server`). Raised once per streak by the unsupported-
|
|
173
|
+
* addon tracker, on the hub and on agents; AlertCenter turns it into one
|
|
174
|
+
* operator alert per node and package. The addon is never held back for it.
|
|
175
|
+
*
|
|
176
|
+
* Payload: `{ packageName, addonId, nodeId, installedVersion, requiredMinimum, serverVersion, unmet }`.
|
|
177
|
+
*/
|
|
178
|
+
EventCategory["AddonUnsupportedVersion"] = "addon.unsupported-version";
|
|
179
|
+
/**
|
|
180
|
+
* The package of an {@link AddonUnsupportedVersion} alert reached a supported
|
|
181
|
+
* version, or is no longer installed on the node. AlertCenter dismisses the matching alert.
|
|
182
|
+
*
|
|
183
|
+
* Payload: `{ packageName, addonId, nodeId }`.
|
|
184
|
+
*/
|
|
185
|
+
EventCategory["AddonUnsupportedResolved"] = "addon.unsupported-resolved";
|
|
186
|
+
/**
|
|
170
187
|
* Monitor scheduled the next retry for a failed addon. Transient —
|
|
171
188
|
* surfaced to the UI for live-updating the "next retry in Ns"
|
|
172
189
|
* countdown on the Addons page row, NOT persisted as an alert.
|
|
@@ -277,7 +294,7 @@ var EventCategory = /* @__PURE__ */ function(EventCategory) {
|
|
|
277
294
|
EventCategory["ProcessRestarted"] = "process.restarted";
|
|
278
295
|
/**
|
|
279
296
|
* The SET of storage locations changed — one was created, edited, enabled,
|
|
280
|
-
* disabled or deleted through
|
|
297
|
+
* disabled or deleted through the location instances or the forced-delete action.
|
|
281
298
|
*
|
|
282
299
|
* Telemetry, not a transaction (D8/D11): every consumer that re-resolves on
|
|
283
300
|
* it must also converge on its own periodic path, because a dropped event
|
|
@@ -832,7 +849,7 @@ var EventCategory = /* @__PURE__ */ function(EventCategory) {
|
|
|
832
849
|
return EventCategory;
|
|
833
850
|
}({});
|
|
834
851
|
//#endregion
|
|
835
|
-
//#region ../types/dist/device-type-
|
|
852
|
+
//#region ../types/dist/device-type-DxCT0krO.mjs
|
|
836
853
|
/**
|
|
837
854
|
import { errMsg } from '@camstack/types'
|
|
838
855
|
* Extract a human-readable message from an unknown error value.
|
|
@@ -994,6 +1011,13 @@ var DeviceFeature = /* @__PURE__ */ function(DeviceFeature) {
|
|
|
994
1011
|
* filters that want "all devices with on-motion behaviour".
|
|
995
1012
|
*/
|
|
996
1013
|
DeviceFeature["MotionTrigger"] = "motion-trigger";
|
|
1014
|
+
/**
|
|
1015
|
+
* Device can be run for a chosen time and then stopped. Mirrors the
|
|
1016
|
+
* `timed-run` wrapper cap — the cap is bound by the core-blocks addon, not by
|
|
1017
|
+
* a driver, so the flag is derived from the device's bindings
|
|
1018
|
+
* (`featuresOfBoundCaps`). Gates the quick-run control in the viewer.
|
|
1019
|
+
*/
|
|
1020
|
+
DeviceFeature["TimedRun"] = "timed-run";
|
|
997
1021
|
/** Light supports rgb-triplet color via `color` cap. */
|
|
998
1022
|
DeviceFeature["LightColorRgb"] = "light-color-rgb";
|
|
999
1023
|
/** Light supports HSV color via `color` cap. */
|
|
@@ -6028,7 +6052,7 @@ var ZodIssueCode = {
|
|
|
6028
6052
|
var ZodFirstPartyTypeKind;
|
|
6029
6053
|
ZodFirstPartyTypeKind || (ZodFirstPartyTypeKind = {});
|
|
6030
6054
|
//#endregion
|
|
6031
|
-
//#region ../types/dist/sleep-
|
|
6055
|
+
//#region ../types/dist/sleep-7El4r5Bl.mjs
|
|
6032
6056
|
/**
|
|
6033
6057
|
* The audio chunk plane's byte format, and the ONE expansion from a coded
|
|
6034
6058
|
* window to float samples (D455).
|
|
@@ -6392,6 +6416,59 @@ Object.fromEntries([
|
|
|
6392
6416
|
function isValuelessField(field) {
|
|
6393
6417
|
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";
|
|
6394
6418
|
}
|
|
6419
|
+
/**
|
|
6420
|
+
* Base collector: flatten a hydrated `ConfigUISchemaWithValues` into
|
|
6421
|
+
* `key → { value, default }`, recursing through `group` and `sub-tabs`
|
|
6422
|
+
* layout fields. Keeping `value` and `default` SEPARATE (rather than
|
|
6423
|
+
* pre-resolving) lets callers both read the effective value AND detect
|
|
6424
|
+
* overrides (`value` differs from `default`). Structural over `unknown`;
|
|
6425
|
+
* malformed input yields an empty map, never throws.
|
|
6426
|
+
*/
|
|
6427
|
+
function collectHydratedFieldEntries(schema) {
|
|
6428
|
+
const out = /* @__PURE__ */ new Map();
|
|
6429
|
+
if (typeof schema !== "object" || schema === null) return out;
|
|
6430
|
+
const sections = schema.sections;
|
|
6431
|
+
if (!Array.isArray(sections)) return out;
|
|
6432
|
+
for (const section of sections) if (typeof section === "object" && section !== null) collectFieldEntriesInto(section.fields, out);
|
|
6433
|
+
return out;
|
|
6434
|
+
}
|
|
6435
|
+
/** Recursive field walker for {@link collectHydratedFieldEntries}. */
|
|
6436
|
+
function collectFieldEntriesInto(fields, into) {
|
|
6437
|
+
if (!Array.isArray(fields)) return;
|
|
6438
|
+
for (const field of fields) {
|
|
6439
|
+
if (typeof field !== "object" || field === null) continue;
|
|
6440
|
+
const type = field.type;
|
|
6441
|
+
if (type === "group") {
|
|
6442
|
+
collectFieldEntriesInto(field.fields, into);
|
|
6443
|
+
continue;
|
|
6444
|
+
}
|
|
6445
|
+
if (type === "sub-tabs") {
|
|
6446
|
+
const tabs = field.tabs;
|
|
6447
|
+
if (Array.isArray(tabs)) {
|
|
6448
|
+
for (const tab of tabs) if (typeof tab === "object" && tab !== null) collectFieldEntriesInto(tab.fields, into);
|
|
6449
|
+
}
|
|
6450
|
+
continue;
|
|
6451
|
+
}
|
|
6452
|
+
const key = field.key;
|
|
6453
|
+
if (typeof key !== "string" || key.length === 0) continue;
|
|
6454
|
+
if (!("value" in field)) continue;
|
|
6455
|
+
into.set(key, {
|
|
6456
|
+
value: field.value,
|
|
6457
|
+
default: field.default
|
|
6458
|
+
});
|
|
6459
|
+
}
|
|
6460
|
+
}
|
|
6461
|
+
/**
|
|
6462
|
+
* Flatten a hydrated settings payload into `key → EFFECTIVE value`
|
|
6463
|
+
* (`value ?? default`). The read-side inverse of `hydrateSchema` for the
|
|
6464
|
+
* common "just give me the resolved values" case. Built on
|
|
6465
|
+
* {@link collectHydratedFieldEntries}.
|
|
6466
|
+
*/
|
|
6467
|
+
function collectHydratedFieldValues(schema) {
|
|
6468
|
+
const out = /* @__PURE__ */ new Map();
|
|
6469
|
+
for (const [key, entry] of collectHydratedFieldEntries(schema)) out.set(key, entry.value ?? entry.default);
|
|
6470
|
+
return out;
|
|
6471
|
+
}
|
|
6395
6472
|
function hydrateSchema(schema, values, options = {}) {
|
|
6396
6473
|
return {
|
|
6397
6474
|
...schema.tabs ? { tabs: [...schema.tabs] } : {},
|
|
@@ -6737,10 +6814,33 @@ function integrationRowsApiOver(api) {
|
|
|
6737
6814
|
};
|
|
6738
6815
|
}
|
|
6739
6816
|
var PREFIX = "records/";
|
|
6817
|
+
/**
|
|
6818
|
+
* Cross-realm brand. An addon bundles its own copy of this module (D15) while
|
|
6819
|
+
* `ctx.records` is the HOST's door, so an error thrown by the host is an
|
|
6820
|
+
* instance of the host's classes, not of the addon's. The brand plus the code
|
|
6821
|
+
* make `instanceof` answer by identity of the failure, not of the copy.
|
|
6822
|
+
*/
|
|
6823
|
+
var RECORDS_ERROR_BRAND = Symbol.for("camstack.records-error");
|
|
6824
|
+
function carriesBrand(value) {
|
|
6825
|
+
return typeof value === "object" && value !== null && Reflect.get(value, RECORDS_ERROR_BRAND) === true;
|
|
6826
|
+
}
|
|
6740
6827
|
/** The base of every records failure. `detail` is the human part of the message. */
|
|
6741
6828
|
var RecordsError = class extends Error {
|
|
6829
|
+
/** The code a subclass stands for; the base stands for every code. */
|
|
6830
|
+
static code = void 0;
|
|
6831
|
+
/**
|
|
6832
|
+
* `instanceof` across copies of this module: any branded error is a
|
|
6833
|
+
* `RecordsError`, and is an instance of a subclass only when its code is the
|
|
6834
|
+
* subclass's code. Same-copy answers are unchanged.
|
|
6835
|
+
*/
|
|
6836
|
+
static [Symbol.hasInstance](value) {
|
|
6837
|
+
if (Function.prototype[Symbol.hasInstance].call(this, value)) return true;
|
|
6838
|
+
if (!carriesBrand(value)) return false;
|
|
6839
|
+
return this.code === void 0 || value.code === this.code;
|
|
6840
|
+
}
|
|
6742
6841
|
code;
|
|
6743
6842
|
detail;
|
|
6843
|
+
[RECORDS_ERROR_BRAND] = true;
|
|
6744
6844
|
constructor(code, detail) {
|
|
6745
6845
|
super(`${PREFIX}${code}: ${detail}`);
|
|
6746
6846
|
this.name = "RecordsError";
|
|
@@ -6749,22 +6849,25 @@ var RecordsError = class extends Error {
|
|
|
6749
6849
|
}
|
|
6750
6850
|
};
|
|
6751
6851
|
/** The keychain could not store or serve a value: explicit, never an empty string. */
|
|
6752
|
-
var RecordSecretUnavailableError = class extends RecordsError {
|
|
6852
|
+
var RecordSecretUnavailableError = class RecordSecretUnavailableError extends RecordsError {
|
|
6853
|
+
static code = "secret-unavailable";
|
|
6753
6854
|
constructor(detail) {
|
|
6754
|
-
super(
|
|
6855
|
+
super(RecordSecretUnavailableError.code, detail);
|
|
6755
6856
|
this.name = "RecordSecretUnavailableError";
|
|
6756
6857
|
}
|
|
6757
6858
|
};
|
|
6758
|
-
var InvalidRecordError = class extends RecordsError {
|
|
6859
|
+
var InvalidRecordError = class InvalidRecordError extends RecordsError {
|
|
6860
|
+
static code = "invalid-record";
|
|
6759
6861
|
constructor(detail) {
|
|
6760
|
-
super(
|
|
6862
|
+
super(InvalidRecordError.code, detail);
|
|
6761
6863
|
this.name = "InvalidRecordError";
|
|
6762
6864
|
}
|
|
6763
6865
|
};
|
|
6764
6866
|
/** A kind declaration the engine refuses (non-additive change, bad shape, wrong file). */
|
|
6765
|
-
var DeclarationRefusedError = class extends RecordsError {
|
|
6867
|
+
var DeclarationRefusedError = class DeclarationRefusedError extends RecordsError {
|
|
6868
|
+
static code = "declaration-refused";
|
|
6766
6869
|
constructor(detail) {
|
|
6767
|
-
super(
|
|
6870
|
+
super(DeclarationRefusedError.code, detail);
|
|
6768
6871
|
this.name = "DeclarationRefusedError";
|
|
6769
6872
|
}
|
|
6770
6873
|
};
|
|
@@ -7242,17 +7345,35 @@ var RecordIntegrationInstances = class {
|
|
|
7242
7345
|
...kind !== void 0 ? { kind } : {}
|
|
7243
7346
|
});
|
|
7244
7347
|
if (minted === void 0) throw new Error("createInstance needs an id: this provider does not mint one");
|
|
7348
|
+
const initial = this.hooks.initialBody(name, kind);
|
|
7349
|
+
const patch = this.patchOf(values ?? {});
|
|
7350
|
+
if (Object.keys(patch).length > 0) Object.assign(patch, await this.hooks.validateWrite?.({
|
|
7351
|
+
kind,
|
|
7352
|
+
body: {
|
|
7353
|
+
...initial,
|
|
7354
|
+
...patch
|
|
7355
|
+
}
|
|
7356
|
+
}));
|
|
7245
7357
|
await this.handle.put({
|
|
7246
7358
|
id: minted,
|
|
7247
|
-
data:
|
|
7359
|
+
data: initial
|
|
7248
7360
|
}, { ifRev: 0 });
|
|
7249
|
-
const patch = this.patchOf(values ?? {});
|
|
7250
7361
|
if (Object.keys(patch).length > 0) await this.handle.patch(minted, patch);
|
|
7251
7362
|
await this.hooks.onChanged?.(minted, "created");
|
|
7252
7363
|
return { id: minted };
|
|
7253
7364
|
};
|
|
7254
7365
|
updateInstance = async ({ id, name, values }) => {
|
|
7255
7366
|
const patch = this.patchOf(values);
|
|
7367
|
+
if (this.hooks.validateWrite !== void 0 && Object.keys(patch).length > 0) {
|
|
7368
|
+
const stored = await this.handle.get(id);
|
|
7369
|
+
if (stored !== null) Object.assign(patch, await this.hooks.validateWrite({
|
|
7370
|
+
kind: void 0,
|
|
7371
|
+
body: {
|
|
7372
|
+
...stored.data,
|
|
7373
|
+
...patch
|
|
7374
|
+
}
|
|
7375
|
+
}));
|
|
7376
|
+
}
|
|
7256
7377
|
if (name !== void 0) patch[this.nameField] = name;
|
|
7257
7378
|
await this.handle.patch(id, patch);
|
|
7258
7379
|
await this.hooks.onChanged?.(id, "updated");
|
|
@@ -7563,6 +7684,21 @@ var SCOPED_SETTINGS_SCOPES = [
|
|
|
7563
7684
|
"device-defaults",
|
|
7564
7685
|
"node"
|
|
7565
7686
|
];
|
|
7687
|
+
/** The one refusal of a key a scope did not declare. */
|
|
7688
|
+
function assertDeclaredKeys(keys, declared) {
|
|
7689
|
+
const undeclared = keys.filter((key) => !declared.has(key));
|
|
7690
|
+
if (undeclared.length > 0) throw new Error(`scoped settings: [${undeclared.join(", ")}] not declared for this scope (declared: [${[...declared].join(", ")}])`);
|
|
7691
|
+
}
|
|
7692
|
+
/** Build the handle over an addon's scoped read, write and unset. */
|
|
7693
|
+
function createScopedSettings(deps) {
|
|
7694
|
+
return {
|
|
7695
|
+
async get() {
|
|
7696
|
+
return deps.schema.parse(await deps.read());
|
|
7697
|
+
},
|
|
7698
|
+
patch: (patch) => deps.write(Object.fromEntries(Object.entries(patch))),
|
|
7699
|
+
unset: (keys) => deps.unset(keys)
|
|
7700
|
+
};
|
|
7701
|
+
}
|
|
7566
7702
|
/** A write to a secret path could not be stored in the keychain, so it was refused. */
|
|
7567
7703
|
var KeychainWriteRefusedError = class extends Error {
|
|
7568
7704
|
fieldPath;
|
|
@@ -8138,7 +8274,16 @@ function createHandle(raw, opts) {
|
|
|
8138
8274
|
return blob;
|
|
8139
8275
|
}
|
|
8140
8276
|
},
|
|
8141
|
-
writeAddonStore: writeAddon
|
|
8277
|
+
writeAddonStore: writeAddon,
|
|
8278
|
+
removeClearedKeys: (keys) => serialize("addon", async () => {
|
|
8279
|
+
const stored = await readStoredAddonBlob(raw);
|
|
8280
|
+
index.seen("addon", stored);
|
|
8281
|
+
const removable = keys.filter((key) => collectSecretMarkerRefs(stored[key]).length === 0);
|
|
8282
|
+
if (removable.length === 0) return;
|
|
8283
|
+
const patch = Object.fromEntries(removable.map((key) => [key, void 0]));
|
|
8284
|
+
await raw.writeAddonStore(patch);
|
|
8285
|
+
index.wrote("addon", patch);
|
|
8286
|
+
})
|
|
8142
8287
|
};
|
|
8143
8288
|
}
|
|
8144
8289
|
/** The context the addon sees, plus the private raw view and write outcome. */
|
|
@@ -8268,7 +8413,7 @@ function boundOf(list) {
|
|
|
8268
8413
|
* Base class for CamStack addons. Eliminates settings boilerplate:
|
|
8269
8414
|
*
|
|
8270
8415
|
* - Typed `config` property with automatic resolution from store + defaults
|
|
8271
|
-
* -
|
|
8416
|
+
* - the scoped settings API (`clusterSettings` / `nodeSettings` / `deviceDefaults`) auto-implemented
|
|
8272
8417
|
* - `getAddonSettings()` / `updateAddonSettings()` auto-implemented
|
|
8273
8418
|
* - `getDeviceSettings()` / `updateDeviceSettings()` auto-implemented
|
|
8274
8419
|
* - `ctx` accessor for the AddonContext (no manual `this.ctxRef` storage)
|
|
@@ -8278,7 +8423,7 @@ function boundOf(list) {
|
|
|
8278
8423
|
* Subclasses override:
|
|
8279
8424
|
* - `onInitialize()` — addon-specific init logic, return ProviderRegistration[]
|
|
8280
8425
|
* - `onShutdown()` — cleanup
|
|
8281
|
-
* - `
|
|
8426
|
+
* - `clusterSettingsSchema()` / `nodeSettingsSchema()` / `deviceSettingsSchema()` — UI schemas
|
|
8282
8427
|
*
|
|
8283
8428
|
* @example
|
|
8284
8429
|
* ```ts
|
|
@@ -8292,7 +8437,7 @@ function boundOf(list) {
|
|
|
8292
8437
|
* super({ maxRetries: 3, endpoint: 'http://localhost' })
|
|
8293
8438
|
* }
|
|
8294
8439
|
*
|
|
8295
|
-
* protected
|
|
8440
|
+
* protected clusterSettingsSchema() {
|
|
8296
8441
|
* return this.schema({
|
|
8297
8442
|
* sections: [{
|
|
8298
8443
|
* id: 'main', title: 'Settings',
|
|
@@ -8335,7 +8480,7 @@ var BaseAddon = class {
|
|
|
8335
8480
|
defaults;
|
|
8336
8481
|
/**
|
|
8337
8482
|
* Hidden-state paths that hold secrets (D787) — values the addon writes
|
|
8338
|
-
* itself (`
|
|
8483
|
+
* itself (`state()`, the scoped writers) that no form field declares.
|
|
8339
8484
|
* Stored in the keychain exactly like a `password` field. Syntax:
|
|
8340
8485
|
* `'snapshotSigningKey'`, `'identity.pincode'`, `'tokens[userId].accessToken'`
|
|
8341
8486
|
* (`key[<id field>]` addresses array items by id, never by index).
|
|
@@ -8345,7 +8490,7 @@ var BaseAddon = class {
|
|
|
8345
8490
|
/**
|
|
8346
8491
|
* D986 M4: the scoped schemas this addon declared, resolved once per capability
|
|
8347
8492
|
* (`loadScopedSchemas`) so the sync readers (`perNodeKeys`, the secret tree, the restart check)
|
|
8348
|
-
* see them. Empty until loaded
|
|
8493
|
+
* see them. Empty until loaded.
|
|
8349
8494
|
*/
|
|
8350
8495
|
_scopedByCap = /* @__PURE__ */ new Map();
|
|
8351
8496
|
_nodeKeysByCap = /* @__PURE__ */ new Map();
|
|
@@ -8531,7 +8676,7 @@ var BaseAddon = class {
|
|
|
8531
8676
|
/** Addon-specific cleanup. Override if needed. */
|
|
8532
8677
|
async onShutdown() {}
|
|
8533
8678
|
/**
|
|
8534
|
-
* Called after config is resolved during
|
|
8679
|
+
* Called after config is resolved during a settings write.
|
|
8535
8680
|
* Override to react to config changes (e.g. restart a sampler, reconnect a service).
|
|
8536
8681
|
* Not called during initialize() — use onInitialize() for initial setup.
|
|
8537
8682
|
*/
|
|
@@ -8560,82 +8705,12 @@ var BaseAddon = class {
|
|
|
8560
8705
|
scopedSettingsCapabilities() {
|
|
8561
8706
|
return [];
|
|
8562
8707
|
}
|
|
8563
|
-
/** Override to provide global-level settings UI schema. */
|
|
8564
|
-
globalSettingsSchema(_cap) {
|
|
8565
|
-
return null;
|
|
8566
|
-
}
|
|
8567
8708
|
/** Override to provide device-level settings UI schema. */
|
|
8568
8709
|
deviceSettingsSchema() {
|
|
8569
8710
|
return null;
|
|
8570
8711
|
}
|
|
8571
8712
|
/**
|
|
8572
|
-
*
|
|
8573
|
-
* ARE the configuration of its integration.
|
|
8574
|
-
*
|
|
8575
|
-
* Return the `ConfigSection.id`s, from {@link globalSettingsSchema}, that an
|
|
8576
|
-
* operator should find on the addon's integration page (System →
|
|
8577
|
-
* Integrations → <name>) rather than only in the cluster-wide list of every
|
|
8578
|
-
* addon. Empty (the default) means the addon has no integration-level
|
|
8579
|
-
* settings and no such surface is offered — this is opt-in, because whether
|
|
8580
|
-
* an addon's configuration IS its integration's configuration depends on the
|
|
8581
|
-
* nature of the integration.
|
|
8582
|
-
*
|
|
8583
|
-
* WHAT THIS IS NOT. It is not a scope. The selected sections keep living in
|
|
8584
|
-
* the ONE global schema, in the ONE addon store, written by the ONE
|
|
8585
|
-
* `updateGlobalSettings` path. There is deliberately no
|
|
8586
|
-
* `updateIntegrationSettings`: a second write path is how a surface acquires
|
|
8587
|
-
* a second store key, and this repo has shipped that twice (`btmPath@hub`,
|
|
8588
|
-
* D266). Selecting sections cannot introduce a key that selecting cannot.
|
|
8589
|
-
*
|
|
8590
|
-
* WHY IT IS A LIST OF SECTION IDS AND NOT A MARKER ON THE SECTION.
|
|
8591
|
-
* `ConfigFieldBase` used to carry `scope?: 'device' | 'global'` and it was
|
|
8592
|
-
* removed with the reason recorded at
|
|
8593
|
-
* `packages/types/src/interfaces/config-ui.ts:249` — *"a field's scope is
|
|
8594
|
-
* determined by WHICH schema it lives in, not by a field-level marker."* A
|
|
8595
|
-
* marker sprinkled across sections also has to borrow a field that already
|
|
8596
|
-
* means something else; borrowing `section.tab` put the literal word
|
|
8597
|
-
* "integration" into an operator-facing tab bar, because `tab` means "how to
|
|
8598
|
-
* GROUP this visually" and cannot also mean "where this lives" (D269
|
|
8599
|
-
* supersedes D268). One declaration, in one place, next to the schema whose
|
|
8600
|
-
* ids it names.
|
|
8601
|
-
*/
|
|
8602
|
-
integrationSettingSections() {
|
|
8603
|
-
return [];
|
|
8604
|
-
}
|
|
8605
|
-
async getGlobalSettings(overlay, cap, nodeId) {
|
|
8606
|
-
await this.loadScopedSchemas(cap);
|
|
8607
|
-
const schema = this.globalSettingsSchema(cap) ?? this.scopedFormSchema(cap);
|
|
8608
|
-
if (!schema) return { sections: [] };
|
|
8609
|
-
const projected = await this.readRawProjectedStore(nodeId, cap);
|
|
8610
|
-
return hydrateSchema(schema, overlay ? await this.overlayKeepingMarkers(projected, overlay) : projected, { inlineSecretsAsViews: true });
|
|
8611
|
-
}
|
|
8612
|
-
/**
|
|
8613
|
-
* The integration-level view of this addon's settings: exactly the sections
|
|
8614
|
-
* named by {@link integrationSettingSections}, hydrated from the SAME store
|
|
8615
|
-
* `getGlobalSettings` reads, and narrowed to cluster-scoped fields.
|
|
8616
|
-
*
|
|
8617
|
-
* Returns `null` when the addon declared nothing — an addon that opts out has
|
|
8618
|
-
* no integration settings surface at all, rather than an empty one that reads
|
|
8619
|
-
* as a failed load.
|
|
8620
|
-
*
|
|
8621
|
-
* Three properties hold BY CONSTRUCTION, which is why they are here in core
|
|
8622
|
-
* and not in whichever UI happens to render this:
|
|
8623
|
-
*
|
|
8624
|
-
* 1. **One key.** The payload is a SUBSET of the global schema, so a field
|
|
8625
|
-
* shown here is the same field, with the same bare key, that the addon's
|
|
8626
|
-
* own page shows. There is no integration-specific writer — callers save
|
|
8627
|
-
* through `updateGlobalSettings` — so a second store key is unreachable,
|
|
8628
|
-
* not merely discouraged.
|
|
8629
|
-
* 2. **No node scope.** `perNode: true` fields are DROPPED. Their store key
|
|
8630
|
-
* is `<key>@<nodeId>` and an integration is not a node; whichever node
|
|
8631
|
-
* such a field silently picked would be a wrong answer for the operator
|
|
8632
|
-
* who opened the page (D266).
|
|
8633
|
-
* 3. **No silent typo.** A declared id that names no section throws. The
|
|
8634
|
-
* alternative — skip it — turns a rename into a surface that quietly
|
|
8635
|
-
* empties, which looks exactly like an addon with nothing to configure.
|
|
8636
|
-
*/
|
|
8637
|
-
/**
|
|
8638
|
-
* The form schema of ONE integration instance, or `null` to use {@link globalSettingsSchema}.
|
|
8713
|
+
* The form schema of ONE integration instance, or `null` to use the scoped form.
|
|
8639
8714
|
*
|
|
8640
8715
|
* Override it only when an `instanceMode: multiple` addon's instances differ: an NVR integration
|
|
8641
8716
|
* needs its connection fields, the default integration the addon's own sections. It is the
|
|
@@ -8683,37 +8758,178 @@ var BaseAddon = class {
|
|
|
8683
8758
|
}
|
|
8684
8759
|
}
|
|
8685
8760
|
/**
|
|
8761
|
+
* Hook: values layered over the stored ones when the FORM of one scope is served
|
|
8762
|
+
* ({@link getScopedSettings}) — a preview that derives dependent options without writing.
|
|
8763
|
+
* Never applied to {@link ScopedSettings.get} or to a write. `null` ⇒ no overlay.
|
|
8764
|
+
*/
|
|
8765
|
+
async scopedSettingsOverlay(_scope, _cap, _nodeId) {
|
|
8766
|
+
return null;
|
|
8767
|
+
}
|
|
8768
|
+
/**
|
|
8769
|
+
* Hook: a write of one scope changed stored values (not called when the store reports no change,
|
|
8770
|
+
* e.g. the write-back of a stored secret). `keys` are the bare field keys of the write, node keys included.
|
|
8771
|
+
*/
|
|
8772
|
+
async onScopedSettingsChanged(_scope, _cap, _keys) {}
|
|
8773
|
+
/** Typed handle over the CLUSTER settings `cap` declares (`clusterSettingsSchema`). */
|
|
8774
|
+
clusterSettings(cap, schema) {
|
|
8775
|
+
return this.scopedHandle("cluster", cap, schema);
|
|
8776
|
+
}
|
|
8777
|
+
/** Typed handle over the fleet defaults of the per-device settings `cap` declares. */
|
|
8778
|
+
deviceDefaults(cap, schema) {
|
|
8779
|
+
return this.scopedHandle("device-defaults", cap, schema);
|
|
8780
|
+
}
|
|
8781
|
+
/**
|
|
8782
|
+
* Typed handle over the settings `cap` owns PER NODE. `nodeId` omitted ⇒ the local node. A node
|
|
8783
|
+
* with no row yields the schema defaults — never a bare-key fallback.
|
|
8784
|
+
*/
|
|
8785
|
+
nodeSettings(cap, schema, nodeId) {
|
|
8786
|
+
return this.scopedHandle("node", cap, schema, nodeId);
|
|
8787
|
+
}
|
|
8788
|
+
/**
|
|
8789
|
+
* {@link state} for a value that is kept per node: stored under `<key>@<nodeId>`, and the
|
|
8790
|
+
* settings store carries `nodeId` in the row data (D986 §1), so a forgotten node's rows go in one
|
|
8791
|
+
* central delete. `nodeId` omitted ⇒ the local node.
|
|
8792
|
+
*/
|
|
8793
|
+
nodeState(key, schema, fallback, nodeId) {
|
|
8794
|
+
this._declaredStateKeys.add(key);
|
|
8795
|
+
return createDurableState({
|
|
8796
|
+
key: nodeScopedKey(key, nodeId ?? this._ctx?.kernel?.localNodeId ?? ""),
|
|
8797
|
+
schema,
|
|
8798
|
+
fallback,
|
|
8799
|
+
read: async () => this.resolveStoredSecrets(await this.readAddonStoreWithRetry()),
|
|
8800
|
+
write: async (patch) => {
|
|
8801
|
+
await this._ctx?.settings?.writeAddonStore(patch);
|
|
8802
|
+
},
|
|
8803
|
+
onParseError: (k, e) => this._ctx?.logger?.warn?.(`durable-state: stored "${k}" failed validation — using fallback`, { meta: {
|
|
8804
|
+
addonId: this._ctx?.id,
|
|
8805
|
+
key: k,
|
|
8806
|
+
error: String(e)
|
|
8807
|
+
} })
|
|
8808
|
+
});
|
|
8809
|
+
}
|
|
8810
|
+
/** The loaded schema `cap` declares for `scope`, or `null`. */
|
|
8811
|
+
async declaredScopedSchema(scope, cap) {
|
|
8812
|
+
await this.loadScopedSchemas(cap);
|
|
8813
|
+
return this.loadedScopedSchemas(cap).find((entry) => entry.scope === scope)?.schema ?? null;
|
|
8814
|
+
}
|
|
8815
|
+
async requireScopedSchema(scope, cap) {
|
|
8816
|
+
const schema = await this.declaredScopedSchema(scope, cap);
|
|
8817
|
+
if (schema === null) throw new Error(`${this.constructor.name}: cap "${cap}" declares no ${scope} settings`);
|
|
8818
|
+
return schema;
|
|
8819
|
+
}
|
|
8820
|
+
scopedKeys(schema) {
|
|
8821
|
+
return new Set(schema.sections.flatMap((section) => collectValueFieldKeys(section.fields)));
|
|
8822
|
+
}
|
|
8823
|
+
/** `store` narrowed to the keys `schema` declares. */
|
|
8824
|
+
narrowToScope(store, schema) {
|
|
8825
|
+
const keys = this.scopedKeys(schema);
|
|
8826
|
+
return Object.fromEntries(Object.entries(store).filter(([key]) => keys.has(key)));
|
|
8827
|
+
}
|
|
8828
|
+
scopedHandle(scope, cap, schema, nodeId) {
|
|
8829
|
+
return createScopedSettings({
|
|
8830
|
+
schema,
|
|
8831
|
+
read: async () => {
|
|
8832
|
+
const declared = await this.requireScopedSchema(scope, cap);
|
|
8833
|
+
const stored = this.narrowToScope(await this.resolveGlobalStore(nodeId, cap), declared);
|
|
8834
|
+
const effective = collectHydratedFieldValues(hydrateSchema(declared, stored));
|
|
8835
|
+
return {
|
|
8836
|
+
...Object.fromEntries([...effective].filter(([, value]) => value !== void 0)),
|
|
8837
|
+
...stored
|
|
8838
|
+
};
|
|
8839
|
+
},
|
|
8840
|
+
write: (patch) => this.writeScoped(scope, cap, patch, nodeId),
|
|
8841
|
+
unset: (keys) => this.unsetScoped(scope, cap, keys, nodeId)
|
|
8842
|
+
});
|
|
8843
|
+
}
|
|
8844
|
+
/** The one write path of the scoped API: declared keys only, then the global patch. */
|
|
8845
|
+
async writeScoped(scope, cap, patch, nodeId) {
|
|
8846
|
+
assertDeclaredKeys(Object.keys(patch), this.scopedKeys(await this.requireScopedSchema(scope, cap)));
|
|
8847
|
+
if (await this.applyGlobalPatch(patch, scope === "node" ? nodeId : void 0, cap)) await this.onScopedSettingsChanged(scope, cap, Object.keys(patch));
|
|
8848
|
+
}
|
|
8849
|
+
/**
|
|
8850
|
+
* Remove declared keys of one scope. A secret goes through {@link clearSecrets} — its keychain
|
|
8851
|
+
* value is released exactly as there — and the emptied row is then removed; every other key is
|
|
8852
|
+
* removed by an `undefined` patch (which a secret transform would read as "keep").
|
|
8853
|
+
*/
|
|
8854
|
+
async unsetScoped(scope, cap, keys, nodeId) {
|
|
8855
|
+
assertDeclaredKeys(keys, this.scopedKeys(await this.requireScopedSchema(scope, cap)));
|
|
8856
|
+
const target = scope === "node" ? nodeId : void 0;
|
|
8857
|
+
const tree = this.addonSecretTree();
|
|
8858
|
+
const secretKeys = keys.filter((key) => tree.has(key));
|
|
8859
|
+
const plainKeys = keys.filter((key) => !tree.has(key));
|
|
8860
|
+
let changed = false;
|
|
8861
|
+
if (plainKeys.length > 0) {
|
|
8862
|
+
const patch = Object.fromEntries(plainKeys.map((key) => [key, void 0]));
|
|
8863
|
+
changed = await this.applyGlobalPatch(patch, target, cap) || changed;
|
|
8864
|
+
}
|
|
8865
|
+
if (secretKeys.length > 0) {
|
|
8866
|
+
await this.clearSecretKeys(secretKeys, target, cap);
|
|
8867
|
+
const node = normalizeNodeId(target ?? this._ctx?.kernel?.localNodeId);
|
|
8868
|
+
const rows = secretKeys.map((key) => scope === "node" ? nodeScopedKey(key, node) : key);
|
|
8869
|
+
if (this._secretSettings !== null) await this._secretSettings.removeClearedKeys(rows);
|
|
8870
|
+
else await this._ctx?.settings?.writeAddonStore(Object.fromEntries(rows.map((row) => [row, void 0])));
|
|
8871
|
+
changed = true;
|
|
8872
|
+
}
|
|
8873
|
+
if (changed) await this.onScopedSettingsChanged(scope, cap, [...keys]);
|
|
8874
|
+
}
|
|
8875
|
+
/**
|
|
8876
|
+
* The hydrated form of one scope of one capability's settings (any
|
|
8877
|
+
* {@link scopedSettingsOverlay} applied), or `null` when the capability declares nothing there.
|
|
8878
|
+
*/
|
|
8879
|
+
async getScopedSettings(scope, cap, nodeId) {
|
|
8880
|
+
const schema = await this.declaredScopedSchema(scope, cap);
|
|
8881
|
+
if (schema === null) return null;
|
|
8882
|
+
const stored = this.narrowToScope(await this.readRawProjectedStore(nodeId, cap), schema);
|
|
8883
|
+
const overlay = await this.scopedSettingsOverlay(scope, cap, nodeId);
|
|
8884
|
+
return hydrateSchema(schema, overlay ? await this.overlayKeepingMarkers(stored, overlay) : stored, { inlineSecretsAsViews: true });
|
|
8885
|
+
}
|
|
8886
|
+
/**
|
|
8887
|
+
* The scoped schemas this addon serves: one entry per loaded (capability, scope), capabilities
|
|
8888
|
+
* in declaration order, scopes in {@link SCOPED_SETTINGS_SCOPES} order. `[]` when it declares
|
|
8889
|
+
* nothing.
|
|
8890
|
+
*/
|
|
8891
|
+
async listScopedSettings() {
|
|
8892
|
+
await this.loadScopedSchemas();
|
|
8893
|
+
return [...this._scopedByCap].flatMap(([cap, entries]) => entries.map((entry) => ({
|
|
8894
|
+
cap,
|
|
8895
|
+
scope: entry.scope,
|
|
8896
|
+
sectionIds: entry.schema.sections.map((section) => section.id)
|
|
8897
|
+
})));
|
|
8898
|
+
}
|
|
8899
|
+
/** The OPERATOR's write of declared keys of one scope (D787 secret semantics). */
|
|
8900
|
+
async updateScopedSettings(scope, cap, patch, nodeId) {
|
|
8901
|
+
this._operatorWriteDepth++;
|
|
8902
|
+
try {
|
|
8903
|
+
await this.writeScoped(scope, cap, patch, nodeId);
|
|
8904
|
+
} finally {
|
|
8905
|
+
this._operatorWriteDepth--;
|
|
8906
|
+
}
|
|
8907
|
+
}
|
|
8908
|
+
/**
|
|
8909
|
+
* The effective values (`stored ?? default`) of one scope, a secret as its `set` view — never
|
|
8910
|
+
* its value. `null` when the capability declares nothing for the scope.
|
|
8911
|
+
*/
|
|
8912
|
+
async readScopedValues(scope, cap, nodeId) {
|
|
8913
|
+
const schema = await this.declaredScopedSchema(scope, cap);
|
|
8914
|
+
if (schema === null) return null;
|
|
8915
|
+
const form = hydrateSchema(schema, this.narrowToScope(await this.readRawProjectedStore(nodeId, cap), schema), { inlineSecretsAsViews: true });
|
|
8916
|
+
return Object.fromEntries([...collectHydratedFieldValues(form)].filter(([, value]) => value !== void 0));
|
|
8917
|
+
}
|
|
8918
|
+
/**
|
|
8686
8919
|
* What the create wizard and the integration edit page render for one instance: the addon's
|
|
8687
8920
|
* per-instance schema when it declares one, else its global schema (what they always showed).
|
|
8688
8921
|
*/
|
|
8689
8922
|
async getIntegrationFormSchema(instance, nodeId) {
|
|
8690
8923
|
const scoped = await this.integrationFormSchema(instance);
|
|
8691
|
-
if (scoped === null) return this.
|
|
8924
|
+
if (scoped === null) return this.scopedForm(nodeId);
|
|
8692
8925
|
return hydrateSchema(scoped, {}, { inlineSecretsAsViews: true });
|
|
8693
8926
|
}
|
|
8694
|
-
|
|
8695
|
-
|
|
8696
|
-
|
|
8697
|
-
const schema = this.
|
|
8698
|
-
if (!schema)
|
|
8699
|
-
|
|
8700
|
-
const sections = [];
|
|
8701
|
-
for (const id of declared) {
|
|
8702
|
-
const section = byId.get(id);
|
|
8703
|
-
if (!section) throw new Error(`${this.constructor.name}: integrationSettingSections() names unknown section "${id}". Known sections: [${[...byId.keys()].join(", ")}].`);
|
|
8704
|
-
const fields = dropPerNodeFields(section.fields);
|
|
8705
|
-
if (fields.length === 0) continue;
|
|
8706
|
-
sections.push({
|
|
8707
|
-
...section,
|
|
8708
|
-
fields
|
|
8709
|
-
});
|
|
8710
|
-
}
|
|
8711
|
-
if (sections.length === 0) return null;
|
|
8712
|
-
const projected = await this.readRawProjectedStore(nodeId);
|
|
8713
|
-
return hydrateSchema({
|
|
8714
|
-
...schema,
|
|
8715
|
-
sections
|
|
8716
|
-
}, projected, { inlineSecretsAsViews: true });
|
|
8927
|
+
/** The form of the scoped schemas this addon declared, hydrated from its store. */
|
|
8928
|
+
async scopedForm(nodeId) {
|
|
8929
|
+
await this.loadScopedSchemas();
|
|
8930
|
+
const schema = this.scopedFormSchema();
|
|
8931
|
+
if (!schema) return { sections: [] };
|
|
8932
|
+
return hydrateSchema(schema, await this.readRawProjectedStore(nodeId), { inlineSecretsAsViews: true });
|
|
8717
8933
|
}
|
|
8718
8934
|
/**
|
|
8719
8935
|
* The raw addon store PROJECTED onto the target node's bare per-node keys:
|
|
@@ -8722,8 +8938,8 @@ var BaseAddon = class {
|
|
|
8722
8938
|
* bare fallback), all `@`-scoped and stray bare per-node keys are dropped.
|
|
8723
8939
|
* A no-op passthrough when the schema declares no `perNode` field.
|
|
8724
8940
|
*
|
|
8725
|
-
* This is the sanctioned way for
|
|
8726
|
-
* the store for custom
|
|
8941
|
+
* This is the sanctioned way for an addon that needs
|
|
8942
|
+
* the store for custom logic (option narrowing, value snapping) to
|
|
8727
8943
|
* read it per-node — never `ctx.settings.readAddonStore()` directly.
|
|
8728
8944
|
* `nodeId` omitted ⇒ the local node (node-blind injection from ctx).
|
|
8729
8945
|
*
|
|
@@ -8775,7 +8991,7 @@ var BaseAddon = class {
|
|
|
8775
8991
|
}
|
|
8776
8992
|
/**
|
|
8777
8993
|
* Whether ONE global key of this addon's store was written, read three-way
|
|
8778
|
-
* (D651). For a question a hydrated view cannot answer:
|
|
8994
|
+
* (D651). For a question a hydrated view cannot answer: a hydrated form
|
|
8779
8995
|
* reports `value ?? default`, so "the operator chose the default" and "nobody
|
|
8780
8996
|
* chose" look the same, and a failed read looks like both. A `perNode` key is
|
|
8781
8997
|
* not supported here: its stored name is scoped.
|
|
@@ -8809,7 +9025,7 @@ var BaseAddon = class {
|
|
|
8809
9025
|
}
|
|
8810
9026
|
/**
|
|
8811
9027
|
* The OPERATOR's write — a settings form or an admin API call, dispatched by
|
|
8812
|
-
* the kernel.
|
|
9028
|
+
* the kernel. The one in-process write of the addon blob that is not a scoped write; a secret
|
|
8813
9029
|
* the operator sends is stored as sent even when it equals a pre-keychain
|
|
8814
9030
|
* inline value: the operator re-entering a password is a change, an addon
|
|
8815
9031
|
* writing back what it read is not (D787).
|
|
@@ -8822,9 +9038,6 @@ var BaseAddon = class {
|
|
|
8822
9038
|
this._operatorWriteDepth--;
|
|
8823
9039
|
}
|
|
8824
9040
|
}
|
|
8825
|
-
async updateGlobalSettings(patch, nodeId) {
|
|
8826
|
-
await this.applyGlobalPatch(patch, nodeId);
|
|
8827
|
-
}
|
|
8828
9041
|
/**
|
|
8829
9042
|
* REMOVE stored secrets — their keychain values and their markers (D787).
|
|
8830
9043
|
*
|
|
@@ -8834,6 +9047,9 @@ var BaseAddon = class {
|
|
|
8834
9047
|
* a keychain (an older kernel) it writes `''`, as such code always did.
|
|
8835
9048
|
*/
|
|
8836
9049
|
async clearSecrets(keys, nodeId) {
|
|
9050
|
+
await this.clearSecretKeys(keys, nodeId);
|
|
9051
|
+
}
|
|
9052
|
+
async clearSecretKeys(keys, nodeId, cap) {
|
|
8837
9053
|
const tree = this.addonSecretTree();
|
|
8838
9054
|
const keychain = this._ctx?.secrets !== void 0;
|
|
8839
9055
|
const stored = keychain ? await this.readAddonStoreWithRetry() : {};
|
|
@@ -8846,25 +9062,26 @@ var BaseAddon = class {
|
|
|
8846
9062
|
const keychainStored = tree.has(key) || collectSecretMarkerRefs(stored[key]).length > 0;
|
|
8847
9063
|
patch[key] = keychain && keychainStored ? SECRET_CLEAR : "";
|
|
8848
9064
|
}
|
|
8849
|
-
await this.applyGlobalPatch(patch, nodeId);
|
|
9065
|
+
await this.applyGlobalPatch(patch, nodeId, cap);
|
|
8850
9066
|
}
|
|
8851
|
-
|
|
8852
|
-
|
|
8853
|
-
|
|
9067
|
+
/** Resolves `true` when the write changed stored values. */
|
|
9068
|
+
async applyGlobalPatch(barePatch, nodeId, cap) {
|
|
9069
|
+
await this.loadScopedSchemas(cap);
|
|
9070
|
+
const keys = this.perNodeKeys(cap);
|
|
8854
9071
|
const localNode = normalizeNodeId(this._ctx?.kernel?.localNodeId);
|
|
8855
9072
|
const target = normalizeNodeId(nodeId ?? this._ctx?.kernel?.localNodeId);
|
|
8856
9073
|
const scoped = keys.size > 0 ? scopePatch(barePatch, keys, target) : barePatch;
|
|
8857
9074
|
const handle = this._secretSettings;
|
|
8858
9075
|
if (handle !== null) {
|
|
8859
9076
|
const { changed } = await handle.writeAddonStore(scoped);
|
|
8860
|
-
if (!changed) return;
|
|
9077
|
+
if (!changed) return false;
|
|
8861
9078
|
} else await this._ctx?.settings?.writeAddonStore(scoped);
|
|
8862
|
-
if (target !== localNode) return;
|
|
9079
|
+
if (target !== localNode) return true;
|
|
8863
9080
|
await this.resolveConfig();
|
|
8864
9081
|
await this.onConfigChanged();
|
|
8865
9082
|
this.emitLifecycle(EventCategory.AddonUpdated, { level: "global" });
|
|
8866
|
-
|
|
8867
|
-
|
|
9083
|
+
this.maybeAutoRestart(Object.keys(barePatch), this.loadedScopedSchemas().map((entry) => entry.schema));
|
|
9084
|
+
return true;
|
|
8868
9085
|
}
|
|
8869
9086
|
/**
|
|
8870
9087
|
* The set of field keys the global settings schema declares `perNode: true`
|
|
@@ -8901,10 +9118,7 @@ var BaseAddon = class {
|
|
|
8901
9118
|
this._nodeKeysByCap = /* @__PURE__ */ new Map();
|
|
8902
9119
|
this._addonSecretTree = null;
|
|
8903
9120
|
}
|
|
8904
|
-
/**
|
|
8905
|
-
* The form the settings API serves while an addon declares no {@link globalSettingsSchema}: the
|
|
8906
|
-
* sections of its scoped schemas, so dropping the old hook does not blank the form.
|
|
8907
|
-
*/
|
|
9121
|
+
/** The form of an addon's scoped schemas: their sections, each shown once. */
|
|
8908
9122
|
scopedFormSchema(cap) {
|
|
8909
9123
|
const byId = /* @__PURE__ */ new Map();
|
|
8910
9124
|
for (const entry of this.loadedScopedSchemas(cap)) for (const section of entry.schema.sections) if (!byId.has(section.id)) byId.set(section.id, section);
|
|
@@ -8916,8 +9130,7 @@ var BaseAddon = class {
|
|
|
8916
9130
|
return [...this._scopedByCap.values()].flat();
|
|
8917
9131
|
}
|
|
8918
9132
|
/**
|
|
8919
|
-
* The field keys that are stored per node: every field of a {@link nodeSettingsSchema}
|
|
8920
|
-
* the fields the legacy {@link globalSettingsSchema} still marks `perNode: true`. Derived once
|
|
9133
|
+
* The field keys that are stored per node: every field of a {@link nodeSettingsSchema}. Derived once
|
|
8921
9134
|
* per `cap` argument and memoized (schemas are static declarations). Empty set ⇒ every
|
|
8922
9135
|
* per-node code path is bypassed and the settings API behaves like the node-agnostic one.
|
|
8923
9136
|
* Call {@link loadScopedSchemas} first (the async seams do).
|
|
@@ -8926,8 +9139,7 @@ var BaseAddon = class {
|
|
|
8926
9139
|
const cacheKey = cap ?? "";
|
|
8927
9140
|
const cached = this._nodeKeysByCap.get(cacheKey);
|
|
8928
9141
|
if (cached) return cached;
|
|
8929
|
-
const
|
|
8930
|
-
const keys = new Set(legacy ? legacy.sections.flatMap((section) => collectPerNodeFieldKeys(section.fields)) : []);
|
|
9142
|
+
const keys = /* @__PURE__ */ new Set();
|
|
8931
9143
|
for (const { scope, schema } of this.loadedScopedSchemas(cap)) {
|
|
8932
9144
|
if (scope !== "node") continue;
|
|
8933
9145
|
for (const section of schema.sections) for (const key of collectValueFieldKeys(section.fields)) keys.add(key);
|
|
@@ -9145,8 +9357,6 @@ var BaseAddon = class {
|
|
|
9145
9357
|
}
|
|
9146
9358
|
declaredKeySet() {
|
|
9147
9359
|
const keys = new Set(Object.keys(this.defaults));
|
|
9148
|
-
const schema = this.globalSettingsSchema();
|
|
9149
|
-
if (schema) for (const section of schema.sections) for (const key of collectFieldKeys(section.fields)) keys.add(key);
|
|
9150
9360
|
for (const { schema: scoped } of this.loadedScopedSchemas()) for (const section of scoped.sections) for (const key of collectFieldKeys(section.fields)) keys.add(key);
|
|
9151
9361
|
for (const key of this._declaredStateKeys) keys.add(key);
|
|
9152
9362
|
for (const path of this.secretStatePaths) {
|
|
@@ -9244,7 +9454,7 @@ var BaseAddon = class {
|
|
|
9244
9454
|
/** The addon store's secret tree: schema fields by TYPE, plus `secretStatePaths`. */
|
|
9245
9455
|
addonSecretTree() {
|
|
9246
9456
|
if (this._addonSecretTree === null) {
|
|
9247
|
-
const tree = new Map(
|
|
9457
|
+
const tree = /* @__PURE__ */ new Map();
|
|
9248
9458
|
for (const { schema } of this.loadedScopedSchemas()) for (const [key, node] of secretTreeFromSchema(schema)) tree.set(key, node);
|
|
9249
9459
|
this._addonSecretTree = mergeSecretStatePaths(tree, this.secretStatePaths);
|
|
9250
9460
|
}
|
|
@@ -9456,47 +9666,6 @@ function classifyStoreError(err) {
|
|
|
9456
9666
|
if (TRANSPORT_PHRASES.some((f) => message.includes(f))) return "transport";
|
|
9457
9667
|
return "permanent";
|
|
9458
9668
|
}
|
|
9459
|
-
/**
|
|
9460
|
-
* Collect the keys of every field marked `perNode: true`, recursing into
|
|
9461
|
-
* layout containers (`group` fields and `sub-tabs` tabs) the same way
|
|
9462
|
-
* `hydrateSchema` does. Valueless structural fields (separator/info/…)
|
|
9463
|
-
* don't declare `perNode` and are excluded by the `in` narrowing.
|
|
9464
|
-
*/
|
|
9465
|
-
/**
|
|
9466
|
-
* The same fields with every `perNode: true` one removed, recursing into layout
|
|
9467
|
-
* containers exactly as {@link collectPerNodeFieldKeys} does. A container left
|
|
9468
|
-
* with no child is dropped rather than rendered empty.
|
|
9469
|
-
*
|
|
9470
|
-
* Used by `getIntegrationSettings`: an integration is not a node, so a field
|
|
9471
|
-
* whose store key is `<key>@<nodeId>` has no node to belong to there.
|
|
9472
|
-
*/
|
|
9473
|
-
function dropPerNodeFields(fields) {
|
|
9474
|
-
const kept = [];
|
|
9475
|
-
for (const field of fields) {
|
|
9476
|
-
if (field.type === "group") {
|
|
9477
|
-
const inner = dropPerNodeFields(field.fields);
|
|
9478
|
-
if (inner.length > 0) kept.push({
|
|
9479
|
-
...field,
|
|
9480
|
-
fields: inner
|
|
9481
|
-
});
|
|
9482
|
-
continue;
|
|
9483
|
-
}
|
|
9484
|
-
if (field.type === "sub-tabs") {
|
|
9485
|
-
const tabs = field.tabs.map((tab) => ({
|
|
9486
|
-
...tab,
|
|
9487
|
-
fields: dropPerNodeFields(tab.fields)
|
|
9488
|
-
})).filter((tab) => tab.fields.length > 0);
|
|
9489
|
-
if (tabs.length > 0) kept.push({
|
|
9490
|
-
...field,
|
|
9491
|
-
tabs
|
|
9492
|
-
});
|
|
9493
|
-
continue;
|
|
9494
|
-
}
|
|
9495
|
-
if ("perNode" in field && field.perNode === true) continue;
|
|
9496
|
-
kept.push(field);
|
|
9497
|
-
}
|
|
9498
|
-
return kept;
|
|
9499
|
-
}
|
|
9500
9669
|
/** The keys of the value-holding fields, recursing into layout containers. */
|
|
9501
9670
|
function collectValueFieldKeys(fields) {
|
|
9502
9671
|
const collected = [];
|
|
@@ -9529,21 +9698,6 @@ function collectFieldKeys(fields) {
|
|
|
9529
9698
|
}
|
|
9530
9699
|
return collected;
|
|
9531
9700
|
}
|
|
9532
|
-
function collectPerNodeFieldKeys(fields) {
|
|
9533
|
-
const collected = [];
|
|
9534
|
-
for (const field of fields) {
|
|
9535
|
-
if (field.type === "group") {
|
|
9536
|
-
collected.push(...collectPerNodeFieldKeys(field.fields));
|
|
9537
|
-
continue;
|
|
9538
|
-
}
|
|
9539
|
-
if (field.type === "sub-tabs") {
|
|
9540
|
-
for (const tab of field.tabs) collected.push(...collectPerNodeFieldKeys(tab.fields));
|
|
9541
|
-
continue;
|
|
9542
|
-
}
|
|
9543
|
-
if ("perNode" in field && field.perNode === true) collected.push(field.key);
|
|
9544
|
-
}
|
|
9545
|
-
return collected;
|
|
9546
|
-
}
|
|
9547
9701
|
/**
|
|
9548
9702
|
* Normalize an `ICamstackAddon.initialize()` return value into the
|
|
9549
9703
|
* `AddonInitResult` envelope. Arrays are wrapped into `{ providers }`;
|
|
@@ -10594,7 +10748,6 @@ var CAP_NAMES = Object.freeze([
|
|
|
10594
10748
|
"notifier",
|
|
10595
10749
|
"numeric-sensor",
|
|
10596
10750
|
"oauth-integration",
|
|
10597
|
-
"oidc-connections",
|
|
10598
10751
|
"osd",
|
|
10599
10752
|
"osd-manager",
|
|
10600
10753
|
"pet-feeder",
|
|
@@ -12301,13 +12454,25 @@ Object.freeze({
|
|
|
12301
12454
|
"path": "temperature",
|
|
12302
12455
|
"valueType": "number"
|
|
12303
12456
|
}],
|
|
12304
|
-
"timed-run": [
|
|
12305
|
-
|
|
12306
|
-
|
|
12307
|
-
|
|
12308
|
-
|
|
12309
|
-
|
|
12310
|
-
|
|
12457
|
+
"timed-run": [
|
|
12458
|
+
{
|
|
12459
|
+
"path": "activeUntil",
|
|
12460
|
+
"valueType": "number"
|
|
12461
|
+
},
|
|
12462
|
+
{
|
|
12463
|
+
"path": "requestedBy",
|
|
12464
|
+
"valueType": "string"
|
|
12465
|
+
},
|
|
12466
|
+
{
|
|
12467
|
+
"path": "quickRun.duration",
|
|
12468
|
+
"valueType": "number"
|
|
12469
|
+
},
|
|
12470
|
+
{
|
|
12471
|
+
"path": "quickRun.unit",
|
|
12472
|
+
"valueType": "enum",
|
|
12473
|
+
"enumValues": ["s", "min"]
|
|
12474
|
+
}
|
|
12475
|
+
],
|
|
12311
12476
|
"update": [
|
|
12312
12477
|
{
|
|
12313
12478
|
"path": "currentVersion",
|
|
@@ -12486,8 +12651,7 @@ Object.freeze({
|
|
|
12486
12651
|
"device-provider": { "reloadDevice": 18e4 },
|
|
12487
12652
|
"llm": {
|
|
12488
12653
|
"generate": 6e5,
|
|
12489
|
-
"generateVision": 6e5
|
|
12490
|
-
"testProfile": 6e5
|
|
12654
|
+
"generateVision": 6e5
|
|
12491
12655
|
},
|
|
12492
12656
|
"llm-runtime": {
|
|
12493
12657
|
"complete": 6e5,
|
|
@@ -12532,7 +12696,7 @@ object({
|
|
|
12532
12696
|
params: record(string(), union([string(), number()])).optional()
|
|
12533
12697
|
});
|
|
12534
12698
|
//#endregion
|
|
12535
|
-
//#region ../types/dist/composition-
|
|
12699
|
+
//#region ../types/dist/composition-Bx0JvKUU.mjs
|
|
12536
12700
|
/**
|
|
12537
12701
|
* The ffmpeg build every CamStack node downloads, per platform and arch.
|
|
12538
12702
|
*
|
|
@@ -13694,6 +13858,387 @@ var NodeColorIdSchema = _enum([
|
|
|
13694
13858
|
"node-h"
|
|
13695
13859
|
]);
|
|
13696
13860
|
//#endregion
|
|
13861
|
+
//#region ../types/dist/convert-BAzH15HU.mjs
|
|
13862
|
+
/**
|
|
13863
|
+
* Frozen unit → spec table. `•` in the doc marks each dimension's canonical
|
|
13864
|
+
* unit (`factor: 1, offset: 0`). °F derives from `°C = (°F − 32) × 5/9` ⇒
|
|
13865
|
+
* `factor = 5/9`, `offset = -160/9` (kept as exact expressions, not rounded
|
|
13866
|
+
* decimals). K derives from `°C = K − 273.15`.
|
|
13867
|
+
*/
|
|
13868
|
+
var UNIT_TABLE = {
|
|
13869
|
+
"°C": {
|
|
13870
|
+
dimension: "temperature",
|
|
13871
|
+
factor: 1,
|
|
13872
|
+
offset: 0
|
|
13873
|
+
},
|
|
13874
|
+
"°F": {
|
|
13875
|
+
dimension: "temperature",
|
|
13876
|
+
factor: 5 / 9,
|
|
13877
|
+
offset: -160 / 9
|
|
13878
|
+
},
|
|
13879
|
+
K: {
|
|
13880
|
+
dimension: "temperature",
|
|
13881
|
+
factor: 1,
|
|
13882
|
+
offset: -273.15
|
|
13883
|
+
},
|
|
13884
|
+
hPa: {
|
|
13885
|
+
dimension: "pressure",
|
|
13886
|
+
factor: 1,
|
|
13887
|
+
offset: 0
|
|
13888
|
+
},
|
|
13889
|
+
kPa: {
|
|
13890
|
+
dimension: "pressure",
|
|
13891
|
+
factor: 10,
|
|
13892
|
+
offset: 0
|
|
13893
|
+
},
|
|
13894
|
+
Pa: {
|
|
13895
|
+
dimension: "pressure",
|
|
13896
|
+
factor: .01,
|
|
13897
|
+
offset: 0
|
|
13898
|
+
},
|
|
13899
|
+
mbar: {
|
|
13900
|
+
dimension: "pressure",
|
|
13901
|
+
factor: 1,
|
|
13902
|
+
offset: 0
|
|
13903
|
+
},
|
|
13904
|
+
bar: {
|
|
13905
|
+
dimension: "pressure",
|
|
13906
|
+
factor: 1e3,
|
|
13907
|
+
offset: 0
|
|
13908
|
+
},
|
|
13909
|
+
inHg: {
|
|
13910
|
+
dimension: "pressure",
|
|
13911
|
+
factor: 33.8639,
|
|
13912
|
+
offset: 0
|
|
13913
|
+
},
|
|
13914
|
+
mmHg: {
|
|
13915
|
+
dimension: "pressure",
|
|
13916
|
+
factor: 1.33322,
|
|
13917
|
+
offset: 0
|
|
13918
|
+
},
|
|
13919
|
+
psi: {
|
|
13920
|
+
dimension: "pressure",
|
|
13921
|
+
factor: 68.9476,
|
|
13922
|
+
offset: 0
|
|
13923
|
+
},
|
|
13924
|
+
"m/s": {
|
|
13925
|
+
dimension: "speed",
|
|
13926
|
+
factor: 1,
|
|
13927
|
+
offset: 0
|
|
13928
|
+
},
|
|
13929
|
+
"km/h": {
|
|
13930
|
+
dimension: "speed",
|
|
13931
|
+
factor: 1 / 3.6,
|
|
13932
|
+
offset: 0
|
|
13933
|
+
},
|
|
13934
|
+
mph: {
|
|
13935
|
+
dimension: "speed",
|
|
13936
|
+
factor: .44704,
|
|
13937
|
+
offset: 0
|
|
13938
|
+
},
|
|
13939
|
+
kn: {
|
|
13940
|
+
dimension: "speed",
|
|
13941
|
+
factor: .514444,
|
|
13942
|
+
offset: 0
|
|
13943
|
+
},
|
|
13944
|
+
"mm/h": {
|
|
13945
|
+
dimension: "precipitation-rate",
|
|
13946
|
+
factor: 1,
|
|
13947
|
+
offset: 0
|
|
13948
|
+
},
|
|
13949
|
+
"in/h": {
|
|
13950
|
+
dimension: "precipitation-rate",
|
|
13951
|
+
factor: 25.4,
|
|
13952
|
+
offset: 0
|
|
13953
|
+
},
|
|
13954
|
+
m: {
|
|
13955
|
+
dimension: "length",
|
|
13956
|
+
factor: 1,
|
|
13957
|
+
offset: 0
|
|
13958
|
+
},
|
|
13959
|
+
mm: {
|
|
13960
|
+
dimension: "length",
|
|
13961
|
+
factor: .001,
|
|
13962
|
+
offset: 0
|
|
13963
|
+
},
|
|
13964
|
+
cm: {
|
|
13965
|
+
dimension: "length",
|
|
13966
|
+
factor: .01,
|
|
13967
|
+
offset: 0
|
|
13968
|
+
},
|
|
13969
|
+
km: {
|
|
13970
|
+
dimension: "length",
|
|
13971
|
+
factor: 1e3,
|
|
13972
|
+
offset: 0
|
|
13973
|
+
},
|
|
13974
|
+
in: {
|
|
13975
|
+
dimension: "length",
|
|
13976
|
+
factor: .0254,
|
|
13977
|
+
offset: 0
|
|
13978
|
+
},
|
|
13979
|
+
ft: {
|
|
13980
|
+
dimension: "length",
|
|
13981
|
+
factor: .3048,
|
|
13982
|
+
offset: 0
|
|
13983
|
+
},
|
|
13984
|
+
mi: {
|
|
13985
|
+
dimension: "length",
|
|
13986
|
+
factor: 1609.344,
|
|
13987
|
+
offset: 0
|
|
13988
|
+
},
|
|
13989
|
+
"m²": {
|
|
13990
|
+
dimension: "area",
|
|
13991
|
+
factor: 1,
|
|
13992
|
+
offset: 0
|
|
13993
|
+
},
|
|
13994
|
+
lx: {
|
|
13995
|
+
dimension: "illuminance",
|
|
13996
|
+
factor: 1,
|
|
13997
|
+
offset: 0
|
|
13998
|
+
},
|
|
13999
|
+
"W/m²": {
|
|
14000
|
+
dimension: "irradiance",
|
|
14001
|
+
factor: 1,
|
|
14002
|
+
offset: 0
|
|
14003
|
+
},
|
|
14004
|
+
W: {
|
|
14005
|
+
dimension: "power",
|
|
14006
|
+
factor: 1,
|
|
14007
|
+
offset: 0
|
|
14008
|
+
},
|
|
14009
|
+
kW: {
|
|
14010
|
+
dimension: "power",
|
|
14011
|
+
factor: 1e3,
|
|
14012
|
+
offset: 0
|
|
14013
|
+
},
|
|
14014
|
+
VA: {
|
|
14015
|
+
dimension: "apparent-power",
|
|
14016
|
+
factor: 1,
|
|
14017
|
+
offset: 0
|
|
14018
|
+
},
|
|
14019
|
+
Wh: {
|
|
14020
|
+
dimension: "energy",
|
|
14021
|
+
factor: 1,
|
|
14022
|
+
offset: 0
|
|
14023
|
+
},
|
|
14024
|
+
kWh: {
|
|
14025
|
+
dimension: "energy",
|
|
14026
|
+
factor: 1e3,
|
|
14027
|
+
offset: 0
|
|
14028
|
+
},
|
|
14029
|
+
MWh: {
|
|
14030
|
+
dimension: "energy",
|
|
14031
|
+
factor: 1e6,
|
|
14032
|
+
offset: 0
|
|
14033
|
+
},
|
|
14034
|
+
V: {
|
|
14035
|
+
dimension: "voltage",
|
|
14036
|
+
factor: 1,
|
|
14037
|
+
offset: 0
|
|
14038
|
+
},
|
|
14039
|
+
mV: {
|
|
14040
|
+
dimension: "voltage",
|
|
14041
|
+
factor: .001,
|
|
14042
|
+
offset: 0
|
|
14043
|
+
},
|
|
14044
|
+
A: {
|
|
14045
|
+
dimension: "current",
|
|
14046
|
+
factor: 1,
|
|
14047
|
+
offset: 0
|
|
14048
|
+
},
|
|
14049
|
+
mA: {
|
|
14050
|
+
dimension: "current",
|
|
14051
|
+
factor: .001,
|
|
14052
|
+
offset: 0
|
|
14053
|
+
},
|
|
14054
|
+
ppm: {
|
|
14055
|
+
dimension: "concentration-volume",
|
|
14056
|
+
factor: 1,
|
|
14057
|
+
offset: 0
|
|
14058
|
+
},
|
|
14059
|
+
ppb: {
|
|
14060
|
+
dimension: "concentration-volume",
|
|
14061
|
+
factor: .001,
|
|
14062
|
+
offset: 0
|
|
14063
|
+
},
|
|
14064
|
+
"µg/m³": {
|
|
14065
|
+
dimension: "concentration-mass",
|
|
14066
|
+
factor: 1,
|
|
14067
|
+
offset: 0
|
|
14068
|
+
},
|
|
14069
|
+
"mg/m³": {
|
|
14070
|
+
dimension: "concentration-mass",
|
|
14071
|
+
factor: 1e3,
|
|
14072
|
+
offset: 0
|
|
14073
|
+
},
|
|
14074
|
+
kg: {
|
|
14075
|
+
dimension: "mass",
|
|
14076
|
+
factor: 1,
|
|
14077
|
+
offset: 0
|
|
14078
|
+
},
|
|
14079
|
+
g: {
|
|
14080
|
+
dimension: "mass",
|
|
14081
|
+
factor: .001,
|
|
14082
|
+
offset: 0
|
|
14083
|
+
},
|
|
14084
|
+
lb: {
|
|
14085
|
+
dimension: "mass",
|
|
14086
|
+
factor: .453592,
|
|
14087
|
+
offset: 0
|
|
14088
|
+
},
|
|
14089
|
+
oz: {
|
|
14090
|
+
dimension: "mass",
|
|
14091
|
+
factor: .0283495,
|
|
14092
|
+
offset: 0
|
|
14093
|
+
},
|
|
14094
|
+
"%": {
|
|
14095
|
+
dimension: "percentage",
|
|
14096
|
+
factor: 1,
|
|
14097
|
+
offset: 0
|
|
14098
|
+
},
|
|
14099
|
+
L: {
|
|
14100
|
+
dimension: "volume",
|
|
14101
|
+
factor: 1,
|
|
14102
|
+
offset: 0
|
|
14103
|
+
},
|
|
14104
|
+
mL: {
|
|
14105
|
+
dimension: "volume",
|
|
14106
|
+
factor: .001,
|
|
14107
|
+
offset: 0
|
|
14108
|
+
},
|
|
14109
|
+
gal: {
|
|
14110
|
+
dimension: "volume",
|
|
14111
|
+
factor: 3.785411784,
|
|
14112
|
+
offset: 0
|
|
14113
|
+
},
|
|
14114
|
+
s: {
|
|
14115
|
+
dimension: "duration",
|
|
14116
|
+
factor: 1,
|
|
14117
|
+
offset: 0
|
|
14118
|
+
},
|
|
14119
|
+
ms: {
|
|
14120
|
+
dimension: "duration",
|
|
14121
|
+
factor: .001,
|
|
14122
|
+
offset: 0
|
|
14123
|
+
},
|
|
14124
|
+
min: {
|
|
14125
|
+
dimension: "duration",
|
|
14126
|
+
factor: 60,
|
|
14127
|
+
offset: 0
|
|
14128
|
+
},
|
|
14129
|
+
h: {
|
|
14130
|
+
dimension: "duration",
|
|
14131
|
+
factor: 3600,
|
|
14132
|
+
offset: 0
|
|
14133
|
+
},
|
|
14134
|
+
d: {
|
|
14135
|
+
dimension: "duration",
|
|
14136
|
+
factor: 86400,
|
|
14137
|
+
offset: 0
|
|
14138
|
+
},
|
|
14139
|
+
B: {
|
|
14140
|
+
dimension: "information",
|
|
14141
|
+
factor: 1,
|
|
14142
|
+
offset: 0
|
|
14143
|
+
},
|
|
14144
|
+
KiB: {
|
|
14145
|
+
dimension: "information",
|
|
14146
|
+
factor: 1024,
|
|
14147
|
+
offset: 0
|
|
14148
|
+
},
|
|
14149
|
+
MiB: {
|
|
14150
|
+
dimension: "information",
|
|
14151
|
+
factor: 1024 ** 2,
|
|
14152
|
+
offset: 0
|
|
14153
|
+
},
|
|
14154
|
+
GiB: {
|
|
14155
|
+
dimension: "information",
|
|
14156
|
+
factor: 1024 ** 3,
|
|
14157
|
+
offset: 0
|
|
14158
|
+
},
|
|
14159
|
+
TiB: {
|
|
14160
|
+
dimension: "information",
|
|
14161
|
+
factor: 1024 ** 4,
|
|
14162
|
+
offset: 0
|
|
14163
|
+
},
|
|
14164
|
+
kB: {
|
|
14165
|
+
dimension: "information",
|
|
14166
|
+
factor: 1e3,
|
|
14167
|
+
offset: 0
|
|
14168
|
+
},
|
|
14169
|
+
MB: {
|
|
14170
|
+
dimension: "information",
|
|
14171
|
+
factor: 1e6,
|
|
14172
|
+
offset: 0
|
|
14173
|
+
},
|
|
14174
|
+
GB: {
|
|
14175
|
+
dimension: "information",
|
|
14176
|
+
factor: 1e9,
|
|
14177
|
+
offset: 0
|
|
14178
|
+
},
|
|
14179
|
+
"°": {
|
|
14180
|
+
dimension: "angle",
|
|
14181
|
+
factor: 1,
|
|
14182
|
+
offset: 0
|
|
14183
|
+
},
|
|
14184
|
+
dBFS: {
|
|
14185
|
+
dimension: "sound-level",
|
|
14186
|
+
factor: 1,
|
|
14187
|
+
offset: 0
|
|
14188
|
+
},
|
|
14189
|
+
dBm: {
|
|
14190
|
+
dimension: "signal-level",
|
|
14191
|
+
factor: 1,
|
|
14192
|
+
offset: 0
|
|
14193
|
+
},
|
|
14194
|
+
mired: {
|
|
14195
|
+
dimension: "colour-temperature",
|
|
14196
|
+
factor: 1,
|
|
14197
|
+
offset: 0
|
|
14198
|
+
},
|
|
14199
|
+
kbps: {
|
|
14200
|
+
dimension: "bitrate",
|
|
14201
|
+
factor: 1,
|
|
14202
|
+
offset: 0
|
|
14203
|
+
},
|
|
14204
|
+
Mbps: {
|
|
14205
|
+
dimension: "bitrate",
|
|
14206
|
+
factor: 1e3,
|
|
14207
|
+
offset: 0
|
|
14208
|
+
},
|
|
14209
|
+
fps: {
|
|
14210
|
+
dimension: "rate",
|
|
14211
|
+
factor: 1,
|
|
14212
|
+
offset: 0
|
|
14213
|
+
}
|
|
14214
|
+
};
|
|
14215
|
+
/** Resolve a unit's `UnitSpec`, or `undefined` when the spelling is unknown. */
|
|
14216
|
+
function specFor(unit) {
|
|
14217
|
+
return Object.hasOwn(UNIT_TABLE, unit) ? UNIT_TABLE[unit] : void 0;
|
|
14218
|
+
}
|
|
14219
|
+
/** Value in `spec`'s unit → its dimension's canonical unit. */
|
|
14220
|
+
function toCanonical(value, spec) {
|
|
14221
|
+
return value * spec.factor + spec.offset;
|
|
14222
|
+
}
|
|
14223
|
+
/** Canonical-unit value → the unit described by `spec`. */
|
|
14224
|
+
function fromCanonical(canonical, spec) {
|
|
14225
|
+
return (canonical - spec.offset) / spec.factor;
|
|
14226
|
+
}
|
|
14227
|
+
/**
|
|
14228
|
+
* Graceful variant for the render path: returns the converted value, or
|
|
14229
|
+
* `undefined` when the conversion is refused (unknown unit / cross-dimension).
|
|
14230
|
+
* Never throws — a render caller falls back to the raw value + source unit.
|
|
14231
|
+
*/
|
|
14232
|
+
function tryConvertUnit(value, from, to) {
|
|
14233
|
+
if (from === to) return value;
|
|
14234
|
+
const fromSpec = specFor(from);
|
|
14235
|
+
if (!fromSpec) return void 0;
|
|
14236
|
+
const toSpec = specFor(to);
|
|
14237
|
+
if (!toSpec) return void 0;
|
|
14238
|
+
if (fromSpec.dimension !== toSpec.dimension) return void 0;
|
|
14239
|
+
return fromCanonical(toCanonical(value, fromSpec), toSpec);
|
|
14240
|
+
}
|
|
14241
|
+
//#endregion
|
|
13697
14242
|
//#region ../types/dist/index.mjs
|
|
13698
14243
|
var SMTP_INBOUND_DEFAULT_PORT = 2525;
|
|
13699
14244
|
var SMTP_INBOUND_DEFAULT_DOMAIN = "camstack.local";
|
|
@@ -13890,17 +14435,18 @@ var IntegrationInstanceRefSchema = object({
|
|
|
13890
14435
|
* message to what the kind supports — callers never special-case a service.
|
|
13891
14436
|
*
|
|
13892
14437
|
* DESIGN DECISIONS (locked):
|
|
13893
|
-
* -
|
|
13894
|
-
*
|
|
13895
|
-
*
|
|
13896
|
-
*
|
|
13897
|
-
*
|
|
13898
|
-
*
|
|
13899
|
-
*
|
|
13900
|
-
*
|
|
13901
|
-
*
|
|
13902
|
-
* routable. `send` / `testTarget` /
|
|
13903
|
-
* `
|
|
14438
|
+
* - A target is an INSTANCE of this function cap (epic #440, step 6): the
|
|
14439
|
+
* providers serve their targets as `integration-instances` records, one
|
|
14440
|
+
* record kind per target kind, and the admin lists, adds, edits, switches
|
|
14441
|
+
* and deletes them through that cap. This cap keeps what an instance cannot
|
|
14442
|
+
* say: the kind catalogue (`listTargetKinds`: capabilities, delivery
|
|
14443
|
+
* parameters, brand icon), dispatch (`send`, `testTarget`) and the form
|
|
14444
|
+
* helpers (`discoverTargets`, `probeTargetConfig`).
|
|
14445
|
+
* - `listTargetKinds` / `discoverTargets` return arrays → the generated
|
|
14446
|
+
* cap-mount auto-`concatCollection`-fans them across every registered
|
|
14447
|
+
* provider so one catalog is routable. `send` / `testTarget` /
|
|
14448
|
+
* `probeTargetConfig` route to ONE provider by the `addonId` the generated
|
|
14449
|
+
* collection router extracts from the call input.
|
|
13904
14450
|
* - `Attachment.bytes` is `Uint8Array`. Transport-safe: superjson (the tRPC
|
|
13905
14451
|
* transformer) + UDS MsgPack both round-trip typed arrays — already used by
|
|
13906
14452
|
* `storage` / `storage-provider` / `recording` caps over the same path. No
|
|
@@ -14145,7 +14691,7 @@ var TargetKindCapsSchema = object({
|
|
|
14145
14691
|
* the union is large and not meant for runtime validation here; the exported
|
|
14146
14692
|
* `TargetKind` type re-tightens `configSchema` to `ConfigUISchema`.
|
|
14147
14693
|
*/
|
|
14148
|
-
var ConfigSchemaPassthrough$
|
|
14694
|
+
var ConfigSchemaPassthrough$3 = unknown();
|
|
14149
14695
|
var TargetKindSchema = object({
|
|
14150
14696
|
kind: string(),
|
|
14151
14697
|
label: string(),
|
|
@@ -14182,7 +14728,7 @@ var TargetKindSchema = object({
|
|
|
14182
14728
|
* its raster path, which is the safe default for an unknown image.
|
|
14183
14729
|
*/
|
|
14184
14730
|
iconMediaType: string().optional(),
|
|
14185
|
-
configSchema: ConfigSchemaPassthrough$
|
|
14731
|
+
configSchema: ConfigSchemaPassthrough$3,
|
|
14186
14732
|
/**
|
|
14187
14733
|
* The config keys that decide WHERE this kind's secrets are sent (server,
|
|
14188
14734
|
* base URL, instance, chat, recipient). A save that changes any of them
|
|
@@ -14204,9 +14750,11 @@ var TargetKindSchema = object({
|
|
|
14204
14750
|
caps: TargetKindCapsSchema
|
|
14205
14751
|
});
|
|
14206
14752
|
/**
|
|
14207
|
-
* A
|
|
14208
|
-
*
|
|
14209
|
-
*
|
|
14753
|
+
* A target as a provider's own code sees it (the notification-center bridge, the
|
|
14754
|
+
* send path): the flat record body split into the name, the switch and the
|
|
14755
|
+
* kind's fields. `config` holds secrets; a reader that serves it to a client
|
|
14756
|
+
* REDACTS secret fields (a presence marker only) — never round-trip a stored
|
|
14757
|
+
* secret to the UI.
|
|
14210
14758
|
*/
|
|
14211
14759
|
var TargetSchema = object({
|
|
14212
14760
|
id: string(),
|
|
@@ -14249,13 +14797,13 @@ var ProbeTargetConfigResultSchema = object({
|
|
|
14249
14797
|
stateInstance: string().optional(),
|
|
14250
14798
|
error: string().optional()
|
|
14251
14799
|
});
|
|
14252
|
-
method(object({}), array(TargetKindSchema)), method(object({
|
|
14800
|
+
method(object({}), array(TargetKindSchema)), method(object({
|
|
14253
14801
|
kind: string(),
|
|
14254
14802
|
config: record(string(), unknown()).optional(),
|
|
14255
14803
|
/**
|
|
14256
14804
|
* When editing / duplicating, the blank password field never round-trips
|
|
14257
14805
|
* the stored token. Pass the source target id so the provider can restore
|
|
14258
|
-
* secrets server-side before dialling
|
|
14806
|
+
* secrets server-side before dialling.
|
|
14259
14807
|
*/
|
|
14260
14808
|
targetId: string().optional()
|
|
14261
14809
|
}), array(DiscoveredTargetSchema), { auth: "admin" }), method(object({
|
|
@@ -14278,27 +14826,6 @@ method(object({}), array(TargetKindSchema)), method(object({}), array(TargetSche
|
|
|
14278
14826
|
}), TestResultSchema, {
|
|
14279
14827
|
kind: "mutation",
|
|
14280
14828
|
auth: "admin"
|
|
14281
|
-
}), method(object({
|
|
14282
|
-
target: TargetSchema,
|
|
14283
|
-
/**
|
|
14284
|
-
* Duplicate flow: create a NEW target id while copying secrets from an
|
|
14285
|
-
* existing row. The UI never holds the stored token; blank / redacted
|
|
14286
|
-
* password fields are restored from this source (D634 still applies if
|
|
14287
|
-
* destinations diverge without a re-typed secret).
|
|
14288
|
-
*/
|
|
14289
|
-
cloneSecretsFrom: string().optional()
|
|
14290
|
-
}), TargetSchema, {
|
|
14291
|
-
kind: "mutation",
|
|
14292
|
-
auth: "admin"
|
|
14293
|
-
}), method(object({ targetId: string() }), _void(), {
|
|
14294
|
-
kind: "mutation",
|
|
14295
|
-
auth: "admin"
|
|
14296
|
-
}), method(object({
|
|
14297
|
-
targetId: string(),
|
|
14298
|
-
enabled: boolean()
|
|
14299
|
-
}), _void(), {
|
|
14300
|
-
kind: "mutation",
|
|
14301
|
-
auth: "admin"
|
|
14302
14829
|
});
|
|
14303
14830
|
looseObject({
|
|
14304
14831
|
name: string().min(1),
|
|
@@ -22566,7 +23093,6 @@ var SYSTEM_CAP_VOCABULARY = {
|
|
|
22566
23093
|
"notification-output": system("notification delivery — reached through notifier devices and rules"),
|
|
22567
23094
|
"notification-rules": system("notification rules — authored on their own page"),
|
|
22568
23095
|
"oauth-integration": system(IDENTITY),
|
|
22569
|
-
"oidc-connections": system(IDENTITY),
|
|
22570
23096
|
"osd-manager": system(PIPELINE),
|
|
22571
23097
|
"pipeline-executor": system(PIPELINE),
|
|
22572
23098
|
"pipeline-orchestrator": system(PIPELINE),
|
|
@@ -42587,6 +43113,7 @@ var ExpressionBindingSourceSchema = union([
|
|
|
42587
43113
|
object({
|
|
42588
43114
|
kind: literal("global"),
|
|
42589
43115
|
sourceStableId: string(),
|
|
43116
|
+
addonId: string().optional(),
|
|
42590
43117
|
cap: string(),
|
|
42591
43118
|
fieldPath: string()
|
|
42592
43119
|
})
|
|
@@ -42653,385 +43180,6 @@ var SourceInfoSchema = object({
|
|
|
42653
43180
|
raw: record(string(), unknown()).optional()
|
|
42654
43181
|
});
|
|
42655
43182
|
/**
|
|
42656
|
-
* Frozen unit → spec table. `•` in the doc marks each dimension's canonical
|
|
42657
|
-
* unit (`factor: 1, offset: 0`). °F derives from `°C = (°F − 32) × 5/9` ⇒
|
|
42658
|
-
* `factor = 5/9`, `offset = -160/9` (kept as exact expressions, not rounded
|
|
42659
|
-
* decimals). K derives from `°C = K − 273.15`.
|
|
42660
|
-
*/
|
|
42661
|
-
var UNIT_TABLE = {
|
|
42662
|
-
"°C": {
|
|
42663
|
-
dimension: "temperature",
|
|
42664
|
-
factor: 1,
|
|
42665
|
-
offset: 0
|
|
42666
|
-
},
|
|
42667
|
-
"°F": {
|
|
42668
|
-
dimension: "temperature",
|
|
42669
|
-
factor: 5 / 9,
|
|
42670
|
-
offset: -160 / 9
|
|
42671
|
-
},
|
|
42672
|
-
K: {
|
|
42673
|
-
dimension: "temperature",
|
|
42674
|
-
factor: 1,
|
|
42675
|
-
offset: -273.15
|
|
42676
|
-
},
|
|
42677
|
-
hPa: {
|
|
42678
|
-
dimension: "pressure",
|
|
42679
|
-
factor: 1,
|
|
42680
|
-
offset: 0
|
|
42681
|
-
},
|
|
42682
|
-
kPa: {
|
|
42683
|
-
dimension: "pressure",
|
|
42684
|
-
factor: 10,
|
|
42685
|
-
offset: 0
|
|
42686
|
-
},
|
|
42687
|
-
Pa: {
|
|
42688
|
-
dimension: "pressure",
|
|
42689
|
-
factor: .01,
|
|
42690
|
-
offset: 0
|
|
42691
|
-
},
|
|
42692
|
-
mbar: {
|
|
42693
|
-
dimension: "pressure",
|
|
42694
|
-
factor: 1,
|
|
42695
|
-
offset: 0
|
|
42696
|
-
},
|
|
42697
|
-
bar: {
|
|
42698
|
-
dimension: "pressure",
|
|
42699
|
-
factor: 1e3,
|
|
42700
|
-
offset: 0
|
|
42701
|
-
},
|
|
42702
|
-
inHg: {
|
|
42703
|
-
dimension: "pressure",
|
|
42704
|
-
factor: 33.8639,
|
|
42705
|
-
offset: 0
|
|
42706
|
-
},
|
|
42707
|
-
mmHg: {
|
|
42708
|
-
dimension: "pressure",
|
|
42709
|
-
factor: 1.33322,
|
|
42710
|
-
offset: 0
|
|
42711
|
-
},
|
|
42712
|
-
psi: {
|
|
42713
|
-
dimension: "pressure",
|
|
42714
|
-
factor: 68.9476,
|
|
42715
|
-
offset: 0
|
|
42716
|
-
},
|
|
42717
|
-
"m/s": {
|
|
42718
|
-
dimension: "speed",
|
|
42719
|
-
factor: 1,
|
|
42720
|
-
offset: 0
|
|
42721
|
-
},
|
|
42722
|
-
"km/h": {
|
|
42723
|
-
dimension: "speed",
|
|
42724
|
-
factor: 1 / 3.6,
|
|
42725
|
-
offset: 0
|
|
42726
|
-
},
|
|
42727
|
-
mph: {
|
|
42728
|
-
dimension: "speed",
|
|
42729
|
-
factor: .44704,
|
|
42730
|
-
offset: 0
|
|
42731
|
-
},
|
|
42732
|
-
kn: {
|
|
42733
|
-
dimension: "speed",
|
|
42734
|
-
factor: .514444,
|
|
42735
|
-
offset: 0
|
|
42736
|
-
},
|
|
42737
|
-
"mm/h": {
|
|
42738
|
-
dimension: "precipitation-rate",
|
|
42739
|
-
factor: 1,
|
|
42740
|
-
offset: 0
|
|
42741
|
-
},
|
|
42742
|
-
"in/h": {
|
|
42743
|
-
dimension: "precipitation-rate",
|
|
42744
|
-
factor: 25.4,
|
|
42745
|
-
offset: 0
|
|
42746
|
-
},
|
|
42747
|
-
m: {
|
|
42748
|
-
dimension: "length",
|
|
42749
|
-
factor: 1,
|
|
42750
|
-
offset: 0
|
|
42751
|
-
},
|
|
42752
|
-
mm: {
|
|
42753
|
-
dimension: "length",
|
|
42754
|
-
factor: .001,
|
|
42755
|
-
offset: 0
|
|
42756
|
-
},
|
|
42757
|
-
cm: {
|
|
42758
|
-
dimension: "length",
|
|
42759
|
-
factor: .01,
|
|
42760
|
-
offset: 0
|
|
42761
|
-
},
|
|
42762
|
-
km: {
|
|
42763
|
-
dimension: "length",
|
|
42764
|
-
factor: 1e3,
|
|
42765
|
-
offset: 0
|
|
42766
|
-
},
|
|
42767
|
-
in: {
|
|
42768
|
-
dimension: "length",
|
|
42769
|
-
factor: .0254,
|
|
42770
|
-
offset: 0
|
|
42771
|
-
},
|
|
42772
|
-
ft: {
|
|
42773
|
-
dimension: "length",
|
|
42774
|
-
factor: .3048,
|
|
42775
|
-
offset: 0
|
|
42776
|
-
},
|
|
42777
|
-
mi: {
|
|
42778
|
-
dimension: "length",
|
|
42779
|
-
factor: 1609.344,
|
|
42780
|
-
offset: 0
|
|
42781
|
-
},
|
|
42782
|
-
"m²": {
|
|
42783
|
-
dimension: "area",
|
|
42784
|
-
factor: 1,
|
|
42785
|
-
offset: 0
|
|
42786
|
-
},
|
|
42787
|
-
lx: {
|
|
42788
|
-
dimension: "illuminance",
|
|
42789
|
-
factor: 1,
|
|
42790
|
-
offset: 0
|
|
42791
|
-
},
|
|
42792
|
-
"W/m²": {
|
|
42793
|
-
dimension: "irradiance",
|
|
42794
|
-
factor: 1,
|
|
42795
|
-
offset: 0
|
|
42796
|
-
},
|
|
42797
|
-
W: {
|
|
42798
|
-
dimension: "power",
|
|
42799
|
-
factor: 1,
|
|
42800
|
-
offset: 0
|
|
42801
|
-
},
|
|
42802
|
-
kW: {
|
|
42803
|
-
dimension: "power",
|
|
42804
|
-
factor: 1e3,
|
|
42805
|
-
offset: 0
|
|
42806
|
-
},
|
|
42807
|
-
VA: {
|
|
42808
|
-
dimension: "apparent-power",
|
|
42809
|
-
factor: 1,
|
|
42810
|
-
offset: 0
|
|
42811
|
-
},
|
|
42812
|
-
Wh: {
|
|
42813
|
-
dimension: "energy",
|
|
42814
|
-
factor: 1,
|
|
42815
|
-
offset: 0
|
|
42816
|
-
},
|
|
42817
|
-
kWh: {
|
|
42818
|
-
dimension: "energy",
|
|
42819
|
-
factor: 1e3,
|
|
42820
|
-
offset: 0
|
|
42821
|
-
},
|
|
42822
|
-
MWh: {
|
|
42823
|
-
dimension: "energy",
|
|
42824
|
-
factor: 1e6,
|
|
42825
|
-
offset: 0
|
|
42826
|
-
},
|
|
42827
|
-
V: {
|
|
42828
|
-
dimension: "voltage",
|
|
42829
|
-
factor: 1,
|
|
42830
|
-
offset: 0
|
|
42831
|
-
},
|
|
42832
|
-
mV: {
|
|
42833
|
-
dimension: "voltage",
|
|
42834
|
-
factor: .001,
|
|
42835
|
-
offset: 0
|
|
42836
|
-
},
|
|
42837
|
-
A: {
|
|
42838
|
-
dimension: "current",
|
|
42839
|
-
factor: 1,
|
|
42840
|
-
offset: 0
|
|
42841
|
-
},
|
|
42842
|
-
mA: {
|
|
42843
|
-
dimension: "current",
|
|
42844
|
-
factor: .001,
|
|
42845
|
-
offset: 0
|
|
42846
|
-
},
|
|
42847
|
-
ppm: {
|
|
42848
|
-
dimension: "concentration-volume",
|
|
42849
|
-
factor: 1,
|
|
42850
|
-
offset: 0
|
|
42851
|
-
},
|
|
42852
|
-
ppb: {
|
|
42853
|
-
dimension: "concentration-volume",
|
|
42854
|
-
factor: .001,
|
|
42855
|
-
offset: 0
|
|
42856
|
-
},
|
|
42857
|
-
"µg/m³": {
|
|
42858
|
-
dimension: "concentration-mass",
|
|
42859
|
-
factor: 1,
|
|
42860
|
-
offset: 0
|
|
42861
|
-
},
|
|
42862
|
-
"mg/m³": {
|
|
42863
|
-
dimension: "concentration-mass",
|
|
42864
|
-
factor: 1e3,
|
|
42865
|
-
offset: 0
|
|
42866
|
-
},
|
|
42867
|
-
kg: {
|
|
42868
|
-
dimension: "mass",
|
|
42869
|
-
factor: 1,
|
|
42870
|
-
offset: 0
|
|
42871
|
-
},
|
|
42872
|
-
g: {
|
|
42873
|
-
dimension: "mass",
|
|
42874
|
-
factor: .001,
|
|
42875
|
-
offset: 0
|
|
42876
|
-
},
|
|
42877
|
-
lb: {
|
|
42878
|
-
dimension: "mass",
|
|
42879
|
-
factor: .453592,
|
|
42880
|
-
offset: 0
|
|
42881
|
-
},
|
|
42882
|
-
oz: {
|
|
42883
|
-
dimension: "mass",
|
|
42884
|
-
factor: .0283495,
|
|
42885
|
-
offset: 0
|
|
42886
|
-
},
|
|
42887
|
-
"%": {
|
|
42888
|
-
dimension: "percentage",
|
|
42889
|
-
factor: 1,
|
|
42890
|
-
offset: 0
|
|
42891
|
-
},
|
|
42892
|
-
L: {
|
|
42893
|
-
dimension: "volume",
|
|
42894
|
-
factor: 1,
|
|
42895
|
-
offset: 0
|
|
42896
|
-
},
|
|
42897
|
-
mL: {
|
|
42898
|
-
dimension: "volume",
|
|
42899
|
-
factor: .001,
|
|
42900
|
-
offset: 0
|
|
42901
|
-
},
|
|
42902
|
-
gal: {
|
|
42903
|
-
dimension: "volume",
|
|
42904
|
-
factor: 3.785411784,
|
|
42905
|
-
offset: 0
|
|
42906
|
-
},
|
|
42907
|
-
s: {
|
|
42908
|
-
dimension: "duration",
|
|
42909
|
-
factor: 1,
|
|
42910
|
-
offset: 0
|
|
42911
|
-
},
|
|
42912
|
-
ms: {
|
|
42913
|
-
dimension: "duration",
|
|
42914
|
-
factor: .001,
|
|
42915
|
-
offset: 0
|
|
42916
|
-
},
|
|
42917
|
-
min: {
|
|
42918
|
-
dimension: "duration",
|
|
42919
|
-
factor: 60,
|
|
42920
|
-
offset: 0
|
|
42921
|
-
},
|
|
42922
|
-
h: {
|
|
42923
|
-
dimension: "duration",
|
|
42924
|
-
factor: 3600,
|
|
42925
|
-
offset: 0
|
|
42926
|
-
},
|
|
42927
|
-
d: {
|
|
42928
|
-
dimension: "duration",
|
|
42929
|
-
factor: 86400,
|
|
42930
|
-
offset: 0
|
|
42931
|
-
},
|
|
42932
|
-
B: {
|
|
42933
|
-
dimension: "information",
|
|
42934
|
-
factor: 1,
|
|
42935
|
-
offset: 0
|
|
42936
|
-
},
|
|
42937
|
-
KiB: {
|
|
42938
|
-
dimension: "information",
|
|
42939
|
-
factor: 1024,
|
|
42940
|
-
offset: 0
|
|
42941
|
-
},
|
|
42942
|
-
MiB: {
|
|
42943
|
-
dimension: "information",
|
|
42944
|
-
factor: 1024 ** 2,
|
|
42945
|
-
offset: 0
|
|
42946
|
-
},
|
|
42947
|
-
GiB: {
|
|
42948
|
-
dimension: "information",
|
|
42949
|
-
factor: 1024 ** 3,
|
|
42950
|
-
offset: 0
|
|
42951
|
-
},
|
|
42952
|
-
TiB: {
|
|
42953
|
-
dimension: "information",
|
|
42954
|
-
factor: 1024 ** 4,
|
|
42955
|
-
offset: 0
|
|
42956
|
-
},
|
|
42957
|
-
kB: {
|
|
42958
|
-
dimension: "information",
|
|
42959
|
-
factor: 1e3,
|
|
42960
|
-
offset: 0
|
|
42961
|
-
},
|
|
42962
|
-
MB: {
|
|
42963
|
-
dimension: "information",
|
|
42964
|
-
factor: 1e6,
|
|
42965
|
-
offset: 0
|
|
42966
|
-
},
|
|
42967
|
-
GB: {
|
|
42968
|
-
dimension: "information",
|
|
42969
|
-
factor: 1e9,
|
|
42970
|
-
offset: 0
|
|
42971
|
-
},
|
|
42972
|
-
"°": {
|
|
42973
|
-
dimension: "angle",
|
|
42974
|
-
factor: 1,
|
|
42975
|
-
offset: 0
|
|
42976
|
-
},
|
|
42977
|
-
dBFS: {
|
|
42978
|
-
dimension: "sound-level",
|
|
42979
|
-
factor: 1,
|
|
42980
|
-
offset: 0
|
|
42981
|
-
},
|
|
42982
|
-
dBm: {
|
|
42983
|
-
dimension: "signal-level",
|
|
42984
|
-
factor: 1,
|
|
42985
|
-
offset: 0
|
|
42986
|
-
},
|
|
42987
|
-
mired: {
|
|
42988
|
-
dimension: "colour-temperature",
|
|
42989
|
-
factor: 1,
|
|
42990
|
-
offset: 0
|
|
42991
|
-
},
|
|
42992
|
-
kbps: {
|
|
42993
|
-
dimension: "bitrate",
|
|
42994
|
-
factor: 1,
|
|
42995
|
-
offset: 0
|
|
42996
|
-
},
|
|
42997
|
-
Mbps: {
|
|
42998
|
-
dimension: "bitrate",
|
|
42999
|
-
factor: 1e3,
|
|
43000
|
-
offset: 0
|
|
43001
|
-
},
|
|
43002
|
-
fps: {
|
|
43003
|
-
dimension: "rate",
|
|
43004
|
-
factor: 1,
|
|
43005
|
-
offset: 0
|
|
43006
|
-
}
|
|
43007
|
-
};
|
|
43008
|
-
/** Resolve a unit's `UnitSpec`, or `undefined` when the spelling is unknown. */
|
|
43009
|
-
function specFor(unit) {
|
|
43010
|
-
return Object.hasOwn(UNIT_TABLE, unit) ? UNIT_TABLE[unit] : void 0;
|
|
43011
|
-
}
|
|
43012
|
-
/** Value in `spec`'s unit → its dimension's canonical unit. */
|
|
43013
|
-
function toCanonical(value, spec) {
|
|
43014
|
-
return value * spec.factor + spec.offset;
|
|
43015
|
-
}
|
|
43016
|
-
/** Canonical-unit value → the unit described by `spec`. */
|
|
43017
|
-
function fromCanonical(canonical, spec) {
|
|
43018
|
-
return (canonical - spec.offset) / spec.factor;
|
|
43019
|
-
}
|
|
43020
|
-
/**
|
|
43021
|
-
* Graceful variant for the render path: returns the converted value, or
|
|
43022
|
-
* `undefined` when the conversion is refused (unknown unit / cross-dimension).
|
|
43023
|
-
* Never throws — a render caller falls back to the raw value + source unit.
|
|
43024
|
-
*/
|
|
43025
|
-
function tryConvertUnit(value, from, to) {
|
|
43026
|
-
if (from === to) return value;
|
|
43027
|
-
const fromSpec = specFor(from);
|
|
43028
|
-
if (!fromSpec) return void 0;
|
|
43029
|
-
const toSpec = specFor(to);
|
|
43030
|
-
if (!toSpec) return void 0;
|
|
43031
|
-
if (fromSpec.dimension !== toSpec.dimension) return void 0;
|
|
43032
|
-
return fromCanonical(toCanonical(value, fromSpec), toSpec);
|
|
43033
|
-
}
|
|
43034
|
-
/**
|
|
43035
43183
|
* A number a person types for a physical quantity — the input side of the
|
|
43036
43184
|
* value + unit contract (D972).
|
|
43037
43185
|
*
|
|
@@ -44708,15 +44856,28 @@ var SettingsSchemaWithValuesSchema = object({
|
|
|
44708
44856
|
});
|
|
44709
44857
|
/** Patch object — keys are field names, values are the new field values. */
|
|
44710
44858
|
var SettingsPatchSchema = record(string(), unknown());
|
|
44859
|
+
/** The scope of a scoped-settings call (D986): where the capability declared the values. */
|
|
44860
|
+
var ScopedSettingsScopeSchema = _enum(SCOPED_SETTINGS_SCOPES);
|
|
44861
|
+
/** One scoped schema an addon serves: its capability, scope and section ids. */
|
|
44862
|
+
var ScopedSettingsDeclarationSchema = object({
|
|
44863
|
+
cap: string(),
|
|
44864
|
+
scope: ScopedSettingsScopeSchema,
|
|
44865
|
+
sectionIds: array(string())
|
|
44866
|
+
});
|
|
44711
44867
|
/** Standard success response for update operations. */
|
|
44712
44868
|
var SettingsUpdateResultSchema = object({ success: literal(true) });
|
|
44713
44869
|
method(object({
|
|
44714
44870
|
addonId: string(),
|
|
44715
|
-
|
|
44716
|
-
|
|
44717
|
-
|
|
44871
|
+
cap: string(),
|
|
44872
|
+
scope: ScopedSettingsScopeSchema,
|
|
44873
|
+
nodeId: string().optional()
|
|
44718
44874
|
}), SettingsSchemaWithValuesSchema.nullable()), method(object({
|
|
44719
44875
|
addonId: string(),
|
|
44876
|
+
nodeId: string().optional()
|
|
44877
|
+
}), array(ScopedSettingsDeclarationSchema).nullable()), method(object({
|
|
44878
|
+
addonId: string(),
|
|
44879
|
+
cap: string(),
|
|
44880
|
+
scope: ScopedSettingsScopeSchema,
|
|
44720
44881
|
nodeId: string().optional(),
|
|
44721
44882
|
patch: SettingsPatchSchema
|
|
44722
44883
|
}), SettingsUpdateResultSchema, {
|
|
@@ -44724,8 +44885,10 @@ method(object({
|
|
|
44724
44885
|
auth: "admin"
|
|
44725
44886
|
}), method(object({
|
|
44726
44887
|
addonId: string(),
|
|
44888
|
+
cap: string(),
|
|
44889
|
+
scope: ScopedSettingsScopeSchema,
|
|
44727
44890
|
nodeId: string().optional()
|
|
44728
|
-
}),
|
|
44891
|
+
}), record(string(), unknown()).nullable()), method(object({
|
|
44729
44892
|
addonId: string(),
|
|
44730
44893
|
nodeId: string().optional(),
|
|
44731
44894
|
instance: IntegrationInstanceRefSchema
|
|
@@ -46065,7 +46228,7 @@ var BackupDestinationInfoSchema = object({
|
|
|
46065
46228
|
id: string(),
|
|
46066
46229
|
/**
|
|
46067
46230
|
* Manifest id of the owning addon. The Settings button on the
|
|
46068
|
-
* destination card opens that addon's
|
|
46231
|
+
* destination card opens that addon's scoped settings panel.
|
|
46069
46232
|
*/
|
|
46070
46233
|
addonId: string(),
|
|
46071
46234
|
/** Operator-toggled enable flag from the destination-policy table. */
|
|
@@ -50535,6 +50698,7 @@ method(InstancePinSchema, DeviceExportStatusSchema), method(_void(), array(Expor
|
|
|
50535
50698
|
kind: "mutation",
|
|
50536
50699
|
auth: "admin"
|
|
50537
50700
|
});
|
|
50701
|
+
var DeviceAliasSchema = string().max(64).regex(/^[a-z][a-z0-9_]*$/);
|
|
50538
50702
|
/**
|
|
50539
50703
|
* A SITE ZONE — a named part of the property that several locations belong to.
|
|
50540
50704
|
*
|
|
@@ -50928,6 +51092,12 @@ var DeviceInfoSchema = object({
|
|
|
50928
51092
|
addonId: string(),
|
|
50929
51093
|
type: _enum(DeviceType),
|
|
50930
51094
|
name: string(),
|
|
51095
|
+
/** The name a value template uses for this device (`{{ stufa_veranda.temperature }}`),
|
|
51096
|
+
* entity_id style. Generated once from the name at first registration, unique
|
|
51097
|
+
* cluster-wide, editable through `setAlias`, NOT changed by a rename (D1021).
|
|
51098
|
+
* Optional: a record produced by an older build omits it until the boot
|
|
51099
|
+
* backfill has run. */
|
|
51100
|
+
alias: DeviceAliasSchema.optional(),
|
|
50931
51101
|
/** Operator-organisational location label. `null` when unset. */
|
|
50932
51102
|
location: string().nullable(),
|
|
50933
51103
|
/** Soft-disabled flag. */
|
|
@@ -51247,6 +51417,25 @@ method(object({
|
|
|
51247
51417
|
}), _void(), {
|
|
51248
51418
|
kind: "mutation",
|
|
51249
51419
|
auth: "admin"
|
|
51420
|
+
}), method(object({
|
|
51421
|
+
deviceId: number(),
|
|
51422
|
+
alias: string()
|
|
51423
|
+
}), discriminatedUnion("ok", [object({
|
|
51424
|
+
ok: literal(true),
|
|
51425
|
+
alias: DeviceAliasSchema
|
|
51426
|
+
}), object({
|
|
51427
|
+
ok: literal(false),
|
|
51428
|
+
reason: _enum([
|
|
51429
|
+
"empty",
|
|
51430
|
+
"too-long",
|
|
51431
|
+
"grammar",
|
|
51432
|
+
"reserved",
|
|
51433
|
+
"taken"
|
|
51434
|
+
]),
|
|
51435
|
+
takenBy: number().optional()
|
|
51436
|
+
})]), {
|
|
51437
|
+
kind: "mutation",
|
|
51438
|
+
auth: "admin"
|
|
51250
51439
|
}), method(object({
|
|
51251
51440
|
deviceId: number(),
|
|
51252
51441
|
location: string().nullable()
|
|
@@ -54272,7 +54461,7 @@ method(_void(), array(IntegrationWithStateSchema)), method(object({ id: string()
|
|
|
54272
54461
|
* or the redaction token KEEPS the stored secret; `{ $secretClear: true }`
|
|
54273
54462
|
* clears it.
|
|
54274
54463
|
*/
|
|
54275
|
-
var ConfigSchemaPassthrough$
|
|
54464
|
+
var ConfigSchemaPassthrough$2 = custom();
|
|
54276
54465
|
var IntegrationInstanceIdSchema = string().min(1);
|
|
54277
54466
|
var IntegrationInstanceModeSchema = _enum(["single", "multiple"]);
|
|
54278
54467
|
/**
|
|
@@ -54318,7 +54507,16 @@ var IntegrationInstanceKindSchema = object({
|
|
|
54318
54507
|
/** Relative hub path to start an interactive account link of an instance of this kind. */
|
|
54319
54508
|
connectPath: string().min(1).optional(),
|
|
54320
54509
|
/** Relative hub path to disconnect that account. */
|
|
54321
|
-
disconnectPath: string().min(1).optional()
|
|
54510
|
+
disconnectPath: string().min(1).optional(),
|
|
54511
|
+
/**
|
|
54512
|
+
* Parts of the edit dialog the flat form cannot draw (a node picker, a model source), named by a
|
|
54513
|
+
* GENERIC widget id the client maps to a component; a client that knows none of them shows none.
|
|
54514
|
+
* `connection` widgets write connection values, `model` widgets own the model choice.
|
|
54515
|
+
*/
|
|
54516
|
+
widgets: array(object({
|
|
54517
|
+
id: string().min(1),
|
|
54518
|
+
placement: _enum(["connection", "model"])
|
|
54519
|
+
})).optional()
|
|
54322
54520
|
});
|
|
54323
54521
|
/**
|
|
54324
54522
|
* How devices of an instance are found. `none`: the operator adds them by hand; `lan`: the addon
|
|
@@ -54423,7 +54621,7 @@ var integrationInstancesCapability = {
|
|
|
54423
54621
|
id: IntegrationInstanceIdSchema.nullable(),
|
|
54424
54622
|
/** The kind of the create form (`id: null`) of a provider with several. */
|
|
54425
54623
|
kind: string().min(1).optional()
|
|
54426
|
-
}), ConfigSchemaPassthrough$
|
|
54624
|
+
}), ConfigSchemaPassthrough$2, { auth: "admin" }),
|
|
54427
54625
|
listInstances: method(_void(), array(IntegrationInstanceSchema).readonly(), { auth: "admin" }),
|
|
54428
54626
|
getInstance: method(object({ id: IntegrationInstanceIdSchema }), IntegrationInstanceSchema.nullable(), { auth: "admin" }),
|
|
54429
54627
|
/**
|
|
@@ -55374,12 +55572,12 @@ var LlmModelInfoSchema = object({
|
|
|
55374
55572
|
});
|
|
55375
55573
|
/**
|
|
55376
55574
|
* The provider-specific part of a profile, validated by the provider that owns
|
|
55377
|
-
* the kind (
|
|
55575
|
+
* the kind (saving an instance refuses what it does not accept). A field its
|
|
55378
55576
|
* `connectionSchema` declares `type: 'password'` is a secret: it is held in the
|
|
55379
55577
|
* keychain, never in the row, and reads back as the redaction marker.
|
|
55380
55578
|
*/
|
|
55381
55579
|
var LlmProviderConfigSchema = record(string(), unknown());
|
|
55382
|
-
|
|
55580
|
+
object({
|
|
55383
55581
|
id: string(),
|
|
55384
55582
|
name: string(),
|
|
55385
55583
|
/** The provider-declared kind (`LlmProfileKindDescriptor.kind`). */
|
|
@@ -55473,8 +55671,8 @@ var LlmProviderWidgetSchema = object({
|
|
|
55473
55671
|
/** ConfigUISchema tree passed through untyped on the wire (the
|
|
55474
55672
|
* notification-output `ConfigSchemaPassthrough` precedent at
|
|
55475
55673
|
* notification-output.cap.ts:151); the exported TS type re-tightens it. */
|
|
55476
|
-
var ConfigSchemaPassthrough$
|
|
55477
|
-
|
|
55674
|
+
var ConfigSchemaPassthrough$1 = unknown();
|
|
55675
|
+
object({
|
|
55478
55676
|
kind: LlmProfileKindSchema,
|
|
55479
55677
|
label: string(),
|
|
55480
55678
|
/** A generic icon name (`cloud`, `plug`, `cpu`) — never a glyph or a logo. */
|
|
@@ -55482,9 +55680,9 @@ var LlmProfileKindDescriptorSchema = object({
|
|
|
55482
55680
|
/** Stamped by each provider so the concat-fanned catalog stays routable. */
|
|
55483
55681
|
addonId: string(),
|
|
55484
55682
|
/** The provider's own fields (`providerConfig`); `password` fields are keychain-held. */
|
|
55485
|
-
connectionSchema: ConfigSchemaPassthrough$
|
|
55683
|
+
connectionSchema: ConfigSchemaPassthrough$1,
|
|
55486
55684
|
/** Provider fields that belong under "Advanced" (extra headers, runtime tuning). */
|
|
55487
|
-
advancedSchema: ConfigSchemaPassthrough$
|
|
55685
|
+
advancedSchema: ConfigSchemaPassthrough$1.optional(),
|
|
55488
55686
|
/** The kind's defaults; a model from `listModels` may override any of them. */
|
|
55489
55687
|
features: LlmModelFeaturesSchema,
|
|
55490
55688
|
/** `false` = the provider stamps `supportsVision` itself (from what a node reports). */
|
|
@@ -55613,20 +55811,7 @@ method(LlmGenerateBaseInputSchema, LlmGenerateResultSchema, {
|
|
|
55613
55811
|
}), method(object({
|
|
55614
55812
|
addonId: string().optional(),
|
|
55615
55813
|
requestId: string()
|
|
55616
|
-
}), _void(), { kind: "mutation" }), method(
|
|
55617
|
-
kind: "mutation",
|
|
55618
|
-
auth: "admin"
|
|
55619
|
-
}), method(RawSecretMigrationInputSchema, RawSecretMigrationReportSchema, {
|
|
55620
|
-
kind: "mutation",
|
|
55621
|
-
auth: "admin"
|
|
55622
|
-
}), method(ProfileRefInputSchema, _void(), {
|
|
55623
|
-
kind: "mutation",
|
|
55624
|
-
auth: "admin"
|
|
55625
|
-
}), method(ProfileRefInputSchema, LlmGenerateResultSchema, {
|
|
55626
|
-
kind: "mutation",
|
|
55627
|
-
auth: "admin",
|
|
55628
|
-
timeoutMs: AI_CAP_TRANSPORT_TIMEOUT_MS
|
|
55629
|
-
}), method(LlmListModelsInputSchema, LlmListModelsResultSchema, {
|
|
55814
|
+
}), _void(), { kind: "mutation" }), method(LlmListModelsInputSchema, LlmListModelsResultSchema, {
|
|
55630
55815
|
kind: "mutation",
|
|
55631
55816
|
auth: "admin"
|
|
55632
55817
|
}), method(object({}), array(LlmDefaultSchema)), method(object({
|
|
@@ -56621,20 +56806,7 @@ method(_void(), MeshStatusSchema), method(object({
|
|
|
56621
56806
|
/** Optional hostname override the host should advertise once joined. */
|
|
56622
56807
|
hostname: string().optional() }), object({
|
|
56623
56808
|
/** Authentication URL the operator should open in a browser. */
|
|
56624
|
-
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() }))
|
|
56625
|
-
/** Optional auth key — when provided, probes the key validity
|
|
56626
|
-
* against the provider's API. Omit when already joined to
|
|
56627
|
-
* just ping the daemon. */
|
|
56628
|
-
authKey: string().optional() }), object({
|
|
56629
|
-
ok: boolean(),
|
|
56630
|
-
/** Provider-side identifier resolved by the probe (tailnet
|
|
56631
|
-
* name for Tailscale, network id for ZeroTier, etc.). */
|
|
56632
|
-
tenant: string().optional(),
|
|
56633
|
-
/** Daemon binary version, when reachable. */
|
|
56634
|
-
daemonVersion: string().optional(),
|
|
56635
|
-
/** Human-readable error when `ok: false`. */
|
|
56636
|
-
error: string().optional()
|
|
56637
|
-
}), { kind: "mutation" });
|
|
56809
|
+
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() }));
|
|
56638
56810
|
object({
|
|
56639
56811
|
value: number().nullable().meta(readingMeta("device", { label: "Total" })),
|
|
56640
56812
|
lastFetchedAt: number()
|
|
@@ -64013,6 +64185,11 @@ var NcScheduleSchema = object({
|
|
|
64013
64185
|
* as a STATE SUMMARY at the end of each window of `schedule`.
|
|
64014
64186
|
*/
|
|
64015
64187
|
var NcSystemEventDeliveryModeSchema = _enum(["instant", "summary"]);
|
|
64188
|
+
_enum([
|
|
64189
|
+
"activation",
|
|
64190
|
+
"deactivation",
|
|
64191
|
+
"schedule"
|
|
64192
|
+
]);
|
|
64016
64193
|
/**
|
|
64017
64194
|
* How a summary window is SENT (D698): `rule` (absent) = ONE notification with
|
|
64018
64195
|
* every section; `section` = one notification per section with something to
|
|
@@ -64029,11 +64206,26 @@ var NcStateSummarySplitSchema = _enum(["rule", "section"]);
|
|
|
64029
64206
|
* midnight crossing); the send time is each window's END. Refused on the
|
|
64030
64207
|
* `alarm` family, which stays instant (`systemEventDeliveryProblems`).
|
|
64031
64208
|
*/
|
|
64032
|
-
var NcSystemEventDeliverySchema = discriminatedUnion("mode", [
|
|
64033
|
-
mode: literal("
|
|
64034
|
-
|
|
64035
|
-
|
|
64036
|
-
|
|
64209
|
+
var NcSystemEventDeliverySchema = discriminatedUnion("mode", [
|
|
64210
|
+
object({ mode: literal("instant") }),
|
|
64211
|
+
object({
|
|
64212
|
+
mode: literal("summary"),
|
|
64213
|
+
schedule: NcScheduleSchema,
|
|
64214
|
+
split: NcStateSummarySplitSchema.optional()
|
|
64215
|
+
}),
|
|
64216
|
+
object({
|
|
64217
|
+
mode: literal("modes"),
|
|
64218
|
+
/** The bad edge, and every kind that has a single edge. */
|
|
64219
|
+
onActivation: boolean(),
|
|
64220
|
+
/** The recovery edges of the classes of the selected kinds (derived, never stored per kind). */
|
|
64221
|
+
onDeactivation: boolean(),
|
|
64222
|
+
/** A state summary at the end of each window; absent = no summary. */
|
|
64223
|
+
onSchedule: object({
|
|
64224
|
+
schedule: NcScheduleSchema,
|
|
64225
|
+
grouping: NcStateSummarySplitSchema
|
|
64226
|
+
}).optional()
|
|
64227
|
+
})
|
|
64228
|
+
]);
|
|
64037
64229
|
/** Fuzzy plate matcher — OCR noise makes exact match useless (spec row 12/13). */
|
|
64038
64230
|
var NcPlateMatcherSchema = object({
|
|
64039
64231
|
/**
|
|
@@ -66310,61 +66502,6 @@ var OauthIntegrationDescriptorSchema = object({
|
|
|
66310
66502
|
});
|
|
66311
66503
|
method(_void(), OauthIntegrationDescriptorSchema, { auth: "admin" });
|
|
66312
66504
|
/**
|
|
66313
|
-
* `oidc-connections` — CRUD for IdP rows under `auth-oidc` (D828 sibling).
|
|
66314
|
-
*
|
|
66315
|
-
* One hub-only singleton (`auth-oidc`). The Settings UI is a DataTable +
|
|
66316
|
-
* ItemFormDialog; there is no `editable-array` in `globalSettingsSchema`.
|
|
66317
|
-
* Operator-chosen `id` is the URL slug (`/addon/auth-oidc/<id>/…`) and is
|
|
66318
|
-
* immutable after create.
|
|
66319
|
-
*/
|
|
66320
|
-
var ConfigSchemaPassthrough$1 = unknown();
|
|
66321
|
-
var OidcConnectionSchema = object({
|
|
66322
|
-
id: string().min(1),
|
|
66323
|
-
displayName: string(),
|
|
66324
|
-
icon: string(),
|
|
66325
|
-
issuerUrl: string(),
|
|
66326
|
-
clientId: string(),
|
|
66327
|
-
/** Client id + secret present — never the secret value. */
|
|
66328
|
-
configured: boolean(),
|
|
66329
|
-
/**
|
|
66330
|
-
* Values for the connection form schema. `clientSecret` is a keychain
|
|
66331
|
-
* {@link SecretFieldView} or `null` / `''`, never plaintext (D789).
|
|
66332
|
-
*/
|
|
66333
|
-
formValues: record(string(), unknown()).optional()
|
|
66334
|
-
});
|
|
66335
|
-
/**
|
|
66336
|
-
* Patch one connection. Omitted or empty `clientSecret` keeps the stored
|
|
66337
|
-
* secret (D787). `{ $secretClear: true }` clears it. `id` is never renamed.
|
|
66338
|
-
*/
|
|
66339
|
-
var OidcConnectionUpdateInputSchema = object({
|
|
66340
|
-
id: string().min(1),
|
|
66341
|
-
displayName: string().min(1),
|
|
66342
|
-
icon: string().optional(),
|
|
66343
|
-
issuerUrl: string().optional(),
|
|
66344
|
-
clientId: string().optional(),
|
|
66345
|
-
clientSecret: union([string(), object({ $secretClear: literal(true) })]).optional(),
|
|
66346
|
-
redirectUri: string().optional(),
|
|
66347
|
-
scopes: string().optional(),
|
|
66348
|
-
usernameClaim: _enum([
|
|
66349
|
-
"preferred_username",
|
|
66350
|
-
"email",
|
|
66351
|
-
"sub"
|
|
66352
|
-
]).optional()
|
|
66353
|
-
});
|
|
66354
|
-
method(object({}), ConfigSchemaPassthrough$1, { auth: "admin" }), method(object({}), array(OidcConnectionSchema).readonly(), { auth: "admin" }), method(object({
|
|
66355
|
-
id: string().min(1).regex(/^[a-z0-9][a-z0-9-]{0,63}$/, "id must be a lowercase slug"),
|
|
66356
|
-
displayName: string().min(1)
|
|
66357
|
-
}), object({ id: string() }), {
|
|
66358
|
-
kind: "mutation",
|
|
66359
|
-
auth: "admin"
|
|
66360
|
-
}), method(OidcConnectionUpdateInputSchema, object({ ok: literal(true) }), {
|
|
66361
|
-
kind: "mutation",
|
|
66362
|
-
auth: "admin"
|
|
66363
|
-
}), method(object({ id: string().min(1) }), object({ ok: literal(true) }), {
|
|
66364
|
-
kind: "mutation",
|
|
66365
|
-
auth: "admin"
|
|
66366
|
-
});
|
|
66367
|
-
/**
|
|
66368
66505
|
* Generic on-screen-display (video overlay) cap. Each camera exposes
|
|
66369
66506
|
* a firmware-defined list of overlays (channel name, timestamp,
|
|
66370
66507
|
* watermark, logo, …); the cap models them as a homogeneous array of
|
|
@@ -72537,21 +72674,6 @@ method(object({
|
|
|
72537
72674
|
*/
|
|
72538
72675
|
ttlSec: union([number().int().positive(), literal("never")]).optional()
|
|
72539
72676
|
}), object({ token: string() }), { auth: "admin" }), method(object({ token: string() }), SsoBridgeClaimsSchema.nullable(), { auth: "admin" });
|
|
72540
|
-
var ProviderListEntrySchema = discriminatedUnion("shouldSaveDiskSpace", [object({
|
|
72541
|
-
providerId: string().min(1),
|
|
72542
|
-
displayName: string().min(1),
|
|
72543
|
-
configSchema: unknown(),
|
|
72544
|
-
nodeLocal: boolean(),
|
|
72545
|
-
shouldSaveDiskSpace: literal(true),
|
|
72546
|
-
minFreePercent: number().min(0).max(100)
|
|
72547
|
-
}), object({
|
|
72548
|
-
providerId: string().min(1),
|
|
72549
|
-
displayName: string().min(1),
|
|
72550
|
-
configSchema: unknown(),
|
|
72551
|
-
nodeLocal: boolean(),
|
|
72552
|
-
shouldSaveDiskSpace: literal(false),
|
|
72553
|
-
minFreePercent: literal(null)
|
|
72554
|
-
})]);
|
|
72555
72677
|
method(object({
|
|
72556
72678
|
location: StorageLocationRefSchema,
|
|
72557
72679
|
relativePath: string()
|
|
@@ -72613,42 +72735,7 @@ method(object({
|
|
|
72613
72735
|
}), _instanceof(Uint8Array), { auth: "admin" }), method(object({ downloadId: string() }), _void(), {
|
|
72614
72736
|
kind: "mutation",
|
|
72615
72737
|
auth: "admin"
|
|
72616
|
-
}), method(object({ type: StorageLocationTypeSchema.optional() }), array(StorageLocationSchema).readonly()), method(_void(), array(StorageLocationDeclarationSchema).readonly()), method(
|
|
72617
|
-
createdAt: true,
|
|
72618
|
-
updatedAt: true
|
|
72619
|
-
}), StorageLocationSchema, {
|
|
72620
|
-
kind: "mutation",
|
|
72621
|
-
auth: "admin"
|
|
72622
|
-
}), method(object({
|
|
72623
|
-
id: string(),
|
|
72624
|
-
force: boolean().optional()
|
|
72625
|
-
}), _void(), {
|
|
72626
|
-
kind: "mutation",
|
|
72627
|
-
auth: "admin"
|
|
72628
|
-
}), method(_void(), array(StorageDrainProgressSchema).readonly()), method(object({ id: string() }), object({
|
|
72629
|
-
ok: boolean(),
|
|
72630
|
-
error: string().optional()
|
|
72631
|
-
}), { auth: "admin" }), method(_void(), array(ProviderListEntrySchema).readonly()), method(object({
|
|
72632
|
-
providerId: string(),
|
|
72633
|
-
/**
|
|
72634
|
-
* The location this config is an UNSAVED edit of, when there is one.
|
|
72635
|
-
*
|
|
72636
|
-
* `listLocations` replaces every declared secret with the redaction
|
|
72637
|
-
* sentinel, so the edit modal's form state holds the sentinel for any
|
|
72638
|
-
* credential the operator did not retype — and posting that here
|
|
72639
|
-
* without a way to resolve it makes the provider try to authenticate
|
|
72640
|
-
* as `__camstack_redacted__` and report the operator's own working
|
|
72641
|
-
* password as wrong. Given this id, the orchestrator restores each
|
|
72642
|
-
* sentinel from the stored config (same rule as `upsertLocation`)
|
|
72643
|
-
* before dispatching. Omitted by the "Add location" wizard, where
|
|
72644
|
-
* every value was typed just now and nothing is stored yet.
|
|
72645
|
-
*/
|
|
72646
|
-
locationId: string().optional(),
|
|
72647
|
-
config: record(string(), unknown())
|
|
72648
|
-
}), object({
|
|
72649
|
-
ok: boolean(),
|
|
72650
|
-
error: string().optional()
|
|
72651
|
-
}), { auth: "admin" });
|
|
72738
|
+
}), method(object({ type: StorageLocationTypeSchema.optional() }), array(StorageLocationSchema).readonly()), method(_void(), array(StorageLocationDeclarationSchema).readonly()), method(_void(), array(StorageDrainProgressSchema).readonly());
|
|
72652
72739
|
/** One table of the settings database. */
|
|
72653
72740
|
var StorageTableSchema = object({
|
|
72654
72741
|
/** The table's full name, e.g. `recorder:addon-settings` or `addon-device-settings`. */
|
|
@@ -73879,7 +73966,7 @@ var TerminalInstanceInfoSchema = object({
|
|
|
73879
73966
|
/**
|
|
73880
73967
|
* False while the node the instance is bound to is not in the cluster
|
|
73881
73968
|
* topology (forgotten, renamed, re-paired). The instance is kept; the
|
|
73882
|
-
* operator re-points it
|
|
73969
|
+
* operator re-points it on the Terminal page.
|
|
73883
73970
|
*/
|
|
73884
73971
|
nodeInCluster: boolean(),
|
|
73885
73972
|
profileId: string(),
|
|
@@ -73917,41 +74004,7 @@ var TerminalOutputBatchSchema = object({
|
|
|
73917
74004
|
snapshot: string().optional(),
|
|
73918
74005
|
events: array(TerminalOutputEventSchema).readonly()
|
|
73919
74006
|
});
|
|
73920
|
-
method(_void(), array(TerminalProfileInfoSchema).readonly(), { auth: "admin" }), method(_void(), array(
|
|
73921
|
-
targetNodeId: string().min(1),
|
|
73922
|
-
profileId: string().min(1),
|
|
73923
|
-
name: string().trim().min(1).max(160).optional(),
|
|
73924
|
-
executable: string().max(1024).optional(),
|
|
73925
|
-
args: array(string().max(2048)).max(64).optional(),
|
|
73926
|
-
cwd: string().max(1024).optional(),
|
|
73927
|
-
environment: array(string().max(4096)).max(64).optional(),
|
|
73928
|
-
profileSettings: ProfileSettingsBagSchema.optional()
|
|
73929
|
-
}), TerminalInstanceInfoSchema, {
|
|
73930
|
-
kind: "mutation",
|
|
73931
|
-
auth: "admin"
|
|
73932
|
-
}), method(object({
|
|
73933
|
-
instanceId: string().min(1),
|
|
73934
|
-
/** Re-point the instance to another node; the profile must exist there. */
|
|
73935
|
-
targetNodeId: string().min(1).max(256).optional(),
|
|
73936
|
-
name: string().trim().min(1).max(160).optional(),
|
|
73937
|
-
executable: string().max(1024).optional(),
|
|
73938
|
-
args: array(string().max(2048)).max(64).optional(),
|
|
73939
|
-
cwd: string().max(1024).optional(),
|
|
73940
|
-
environment: array(string().max(4096)).max(64).optional(),
|
|
73941
|
-
profileSettings: ProfileSettingsBagSchema.optional()
|
|
73942
|
-
}), TerminalInstanceInfoSchema, {
|
|
73943
|
-
kind: "mutation",
|
|
73944
|
-
auth: "admin"
|
|
73945
|
-
}), method(object({ instanceId: string().min(1) }), _void(), {
|
|
73946
|
-
kind: "mutation",
|
|
73947
|
-
auth: "admin"
|
|
73948
|
-
}), method(object({
|
|
73949
|
-
instanceId: string().min(1),
|
|
73950
|
-
enabled: boolean()
|
|
73951
|
-
}), TerminalInstanceInfoSchema, {
|
|
73952
|
-
kind: "mutation",
|
|
73953
|
-
auth: "admin"
|
|
73954
|
-
}), method(_void(), array(TerminalLegacyCameraSchema).readonly(), { auth: "admin" }), method(object({
|
|
74007
|
+
method(_void(), array(TerminalProfileInfoSchema).readonly(), { auth: "admin" }), method(_void(), array(TerminalLegacyCameraSchema).readonly(), { auth: "admin" }), method(object({
|
|
73955
74008
|
stableId: string().min(1),
|
|
73956
74009
|
name: string().trim().min(1).max(160).optional()
|
|
73957
74010
|
}), TerminalInstanceInfoSchema, {
|
|
@@ -74020,6 +74073,11 @@ var TimedRunUnitSchema = _enum(["s", "min"]);
|
|
|
74020
74073
|
_enum(["switch", "pet-fountain"]);
|
|
74021
74074
|
DeviceType.Heater, DeviceType.PetFountain;
|
|
74022
74075
|
DeviceType.Heater, DeviceType.PetFountain;
|
|
74076
|
+
/** One duration, as the one-tap run asks for it. */
|
|
74077
|
+
var TimedRunQuickRunSchema = object({
|
|
74078
|
+
duration: number().positive().finite(),
|
|
74079
|
+
unit: TimedRunUnitSchema
|
|
74080
|
+
});
|
|
74023
74081
|
/** Why a request was not carried out. Typed, so a caller can say it in words. */
|
|
74024
74082
|
var TimedRunRefusalSchema = _enum([
|
|
74025
74083
|
"unsupported-device",
|
|
@@ -74040,9 +74098,30 @@ object({
|
|
|
74040
74098
|
activeUntil: number().nullable(),
|
|
74041
74099
|
/** Who asked for the run (a user id or an addon id); `null` when nothing is armed or it did not say. */
|
|
74042
74100
|
requestedBy: string().nullable(),
|
|
74101
|
+
/**
|
|
74102
|
+
* The one-tap run of THIS device: what a "Run" button on any surface starts. `null` when
|
|
74103
|
+
* the device is gone or its type has no timed run; a status from before this field
|
|
74104
|
+
* existed has none, and a surface falls back to the type's default.
|
|
74105
|
+
*/
|
|
74106
|
+
quickRun: TimedRunQuickRunSchema.nullable(),
|
|
74043
74107
|
lastFetchedAt: number()
|
|
74044
74108
|
});
|
|
74045
|
-
|
|
74109
|
+
/** What the settings form needs: the unit, the bounds and the type's default. */
|
|
74110
|
+
var TimedRunOptionsSchema = object({
|
|
74111
|
+
unit: TimedRunUnitSchema,
|
|
74112
|
+
/** The longest run, in `unit`. */
|
|
74113
|
+
maxDuration: number(),
|
|
74114
|
+
defaultDuration: number()
|
|
74115
|
+
});
|
|
74116
|
+
/** The one-tap run duration, in the type's unit; `null` returns to the type's default. */
|
|
74117
|
+
var TimedRunSettingsPatchSchema = object({ quickRunDuration: number().positive().finite().nullable().optional() });
|
|
74118
|
+
method(object({ deviceId: number().int() }), TimedRunOptionsSchema), method(object({
|
|
74119
|
+
deviceId: number().int(),
|
|
74120
|
+
settings: TimedRunSettingsPatchSchema
|
|
74121
|
+
}), _void(), {
|
|
74122
|
+
kind: "mutation",
|
|
74123
|
+
auth: "admin"
|
|
74124
|
+
}), method(object({
|
|
74046
74125
|
deviceId: number().int(),
|
|
74047
74126
|
duration: number().positive().finite(),
|
|
74048
74127
|
unit: TimedRunUnitSchema
|
|
@@ -76748,21 +76827,28 @@ Object.freeze({
|
|
|
76748
76827
|
access: "view",
|
|
76749
76828
|
role: "admin"
|
|
76750
76829
|
},
|
|
76751
|
-
"addonSettings.
|
|
76830
|
+
"addonSettings.getIntegrationFormSchema": {
|
|
76831
|
+
capName: "addon-settings",
|
|
76832
|
+
capScope: "system",
|
|
76833
|
+
addonId: null,
|
|
76834
|
+
access: "view",
|
|
76835
|
+
role: "admin"
|
|
76836
|
+
},
|
|
76837
|
+
"addonSettings.getScopedSettings": {
|
|
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.listScopedSettings": {
|
|
76759
76845
|
capName: "addon-settings",
|
|
76760
76846
|
capScope: "system",
|
|
76761
76847
|
addonId: null,
|
|
76762
76848
|
access: "view",
|
|
76763
76849
|
role: "admin"
|
|
76764
76850
|
},
|
|
76765
|
-
"addonSettings.
|
|
76851
|
+
"addonSettings.readScopedValues": {
|
|
76766
76852
|
capName: "addon-settings",
|
|
76767
76853
|
capScope: "system",
|
|
76768
76854
|
addonId: null,
|
|
@@ -76783,7 +76869,7 @@ Object.freeze({
|
|
|
76783
76869
|
access: "create",
|
|
76784
76870
|
role: "admin"
|
|
76785
76871
|
},
|
|
76786
|
-
"addonSettings.
|
|
76872
|
+
"addonSettings.updateScopedSettings": {
|
|
76787
76873
|
capName: "addon-settings",
|
|
76788
76874
|
capScope: "system",
|
|
76789
76875
|
addonId: null,
|
|
@@ -78953,6 +79039,13 @@ Object.freeze({
|
|
|
78953
79039
|
access: "create",
|
|
78954
79040
|
role: "admin"
|
|
78955
79041
|
},
|
|
79042
|
+
"deviceManager.setAlias": {
|
|
79043
|
+
capName: "device-manager",
|
|
79044
|
+
capScope: "system",
|
|
79045
|
+
addonId: null,
|
|
79046
|
+
access: "create",
|
|
79047
|
+
role: "admin"
|
|
79048
|
+
},
|
|
78956
79049
|
"deviceManager.setChildLayout": {
|
|
78957
79050
|
capName: "device-manager",
|
|
78958
79051
|
capScope: "system",
|
|
@@ -80241,13 +80334,6 @@ Object.freeze({
|
|
|
80241
80334
|
access: "delete",
|
|
80242
80335
|
role: "admin"
|
|
80243
80336
|
},
|
|
80244
|
-
"llm.deleteProfile": {
|
|
80245
|
-
capName: "llm",
|
|
80246
|
-
capScope: "system",
|
|
80247
|
-
addonId: null,
|
|
80248
|
-
access: "delete",
|
|
80249
|
-
role: "admin"
|
|
80250
|
-
},
|
|
80251
80337
|
"llm.generate": {
|
|
80252
80338
|
capName: "llm",
|
|
80253
80339
|
capScope: "system",
|
|
@@ -80311,20 +80397,6 @@ Object.freeze({
|
|
|
80311
80397
|
access: "view",
|
|
80312
80398
|
role: "admin"
|
|
80313
80399
|
},
|
|
80314
|
-
"llm.listProfileKinds": {
|
|
80315
|
-
capName: "llm",
|
|
80316
|
-
capScope: "system",
|
|
80317
|
-
addonId: null,
|
|
80318
|
-
access: "view",
|
|
80319
|
-
role: "admin"
|
|
80320
|
-
},
|
|
80321
|
-
"llm.listProfiles": {
|
|
80322
|
-
capName: "llm",
|
|
80323
|
-
capScope: "system",
|
|
80324
|
-
addonId: null,
|
|
80325
|
-
access: "view",
|
|
80326
|
-
role: "admin"
|
|
80327
|
-
},
|
|
80328
80400
|
"llm.listRuntimeNodes": {
|
|
80329
80401
|
capName: "llm",
|
|
80330
80402
|
capScope: "system",
|
|
@@ -80332,13 +80404,6 @@ Object.freeze({
|
|
|
80332
80404
|
access: "view",
|
|
80333
80405
|
role: "admin"
|
|
80334
80406
|
},
|
|
80335
|
-
"llm.migrateRawSecrets": {
|
|
80336
|
-
capName: "llm",
|
|
80337
|
-
capScope: "system",
|
|
80338
|
-
addonId: null,
|
|
80339
|
-
access: "create",
|
|
80340
|
-
role: "admin"
|
|
80341
|
-
},
|
|
80342
80407
|
"llm.resolveModelRef": {
|
|
80343
80408
|
capName: "llm",
|
|
80344
80409
|
capScope: "system",
|
|
@@ -80367,20 +80432,6 @@ Object.freeze({
|
|
|
80367
80432
|
access: "create",
|
|
80368
80433
|
role: "admin"
|
|
80369
80434
|
},
|
|
80370
|
-
"llm.testProfile": {
|
|
80371
|
-
capName: "llm",
|
|
80372
|
-
capScope: "system",
|
|
80373
|
-
addonId: null,
|
|
80374
|
-
access: "create",
|
|
80375
|
-
role: "admin"
|
|
80376
|
-
},
|
|
80377
|
-
"llm.upsertProfile": {
|
|
80378
|
-
capName: "llm",
|
|
80379
|
-
capScope: "system",
|
|
80380
|
-
addonId: null,
|
|
80381
|
-
access: "create",
|
|
80382
|
-
role: "admin"
|
|
80383
|
-
},
|
|
80384
80435
|
"llmRuntime.appleAvailability": {
|
|
80385
80436
|
capName: "llm-runtime",
|
|
80386
80437
|
capScope: "system",
|
|
@@ -80885,13 +80936,6 @@ Object.freeze({
|
|
|
80885
80936
|
access: "create",
|
|
80886
80937
|
role: "admin"
|
|
80887
80938
|
},
|
|
80888
|
-
"meshNetwork.testConnection": {
|
|
80889
|
-
capName: "mesh-network",
|
|
80890
|
-
capScope: "system",
|
|
80891
|
-
addonId: null,
|
|
80892
|
-
access: "create",
|
|
80893
|
-
role: "admin"
|
|
80894
|
-
},
|
|
80895
80939
|
"meter.getStatus": {
|
|
80896
80940
|
capName: "meter",
|
|
80897
80941
|
capScope: "device",
|
|
@@ -81550,13 +81594,6 @@ Object.freeze({
|
|
|
81550
81594
|
access: "create",
|
|
81551
81595
|
role: "admin"
|
|
81552
81596
|
},
|
|
81553
|
-
"notificationOutput.deleteTarget": {
|
|
81554
|
-
capName: "notification-output",
|
|
81555
|
-
capScope: "system",
|
|
81556
|
-
addonId: null,
|
|
81557
|
-
access: "delete",
|
|
81558
|
-
role: "admin"
|
|
81559
|
-
},
|
|
81560
81597
|
"notificationOutput.discoverTargets": {
|
|
81561
81598
|
capName: "notification-output",
|
|
81562
81599
|
capScope: "system",
|
|
@@ -81564,13 +81601,6 @@ Object.freeze({
|
|
|
81564
81601
|
access: "view",
|
|
81565
81602
|
role: "admin"
|
|
81566
81603
|
},
|
|
81567
|
-
"notificationOutput.getTarget": {
|
|
81568
|
-
capName: "notification-output",
|
|
81569
|
-
capScope: "system",
|
|
81570
|
-
addonId: null,
|
|
81571
|
-
access: "view",
|
|
81572
|
-
role: "admin"
|
|
81573
|
-
},
|
|
81574
81604
|
"notificationOutput.listTargetKinds": {
|
|
81575
81605
|
capName: "notification-output",
|
|
81576
81606
|
capScope: "system",
|
|
@@ -81578,13 +81608,6 @@ Object.freeze({
|
|
|
81578
81608
|
access: "view",
|
|
81579
81609
|
role: "admin"
|
|
81580
81610
|
},
|
|
81581
|
-
"notificationOutput.listTargets": {
|
|
81582
|
-
capName: "notification-output",
|
|
81583
|
-
capScope: "system",
|
|
81584
|
-
addonId: null,
|
|
81585
|
-
access: "view",
|
|
81586
|
-
role: "admin"
|
|
81587
|
-
},
|
|
81588
81611
|
"notificationOutput.probeTargetConfig": {
|
|
81589
81612
|
capName: "notification-output",
|
|
81590
81613
|
capScope: "system",
|
|
@@ -81599,13 +81622,6 @@ Object.freeze({
|
|
|
81599
81622
|
access: "create",
|
|
81600
81623
|
role: "admin"
|
|
81601
81624
|
},
|
|
81602
|
-
"notificationOutput.setTargetEnabled": {
|
|
81603
|
-
capName: "notification-output",
|
|
81604
|
-
capScope: "system",
|
|
81605
|
-
addonId: null,
|
|
81606
|
-
access: "create",
|
|
81607
|
-
role: "admin"
|
|
81608
|
-
},
|
|
81609
81625
|
"notificationOutput.testTarget": {
|
|
81610
81626
|
capName: "notification-output",
|
|
81611
81627
|
capScope: "system",
|
|
@@ -81613,13 +81629,6 @@ Object.freeze({
|
|
|
81613
81629
|
access: "create",
|
|
81614
81630
|
role: "admin"
|
|
81615
81631
|
},
|
|
81616
|
-
"notificationOutput.upsertTarget": {
|
|
81617
|
-
capName: "notification-output",
|
|
81618
|
-
capScope: "system",
|
|
81619
|
-
addonId: null,
|
|
81620
|
-
access: "create",
|
|
81621
|
-
role: "admin"
|
|
81622
|
-
},
|
|
81623
81632
|
"notificationRules.activateAlarmProfile": {
|
|
81624
81633
|
capName: "notification-rules",
|
|
81625
81634
|
capScope: "system",
|
|
@@ -81879,41 +81888,6 @@ Object.freeze({
|
|
|
81879
81888
|
access: "view",
|
|
81880
81889
|
role: "admin"
|
|
81881
81890
|
},
|
|
81882
|
-
"oidcConnections.connectionFormSchema": {
|
|
81883
|
-
capName: "oidc-connections",
|
|
81884
|
-
capScope: "system",
|
|
81885
|
-
addonId: null,
|
|
81886
|
-
access: "view",
|
|
81887
|
-
role: "admin"
|
|
81888
|
-
},
|
|
81889
|
-
"oidcConnections.createConnection": {
|
|
81890
|
-
capName: "oidc-connections",
|
|
81891
|
-
capScope: "system",
|
|
81892
|
-
addonId: null,
|
|
81893
|
-
access: "create",
|
|
81894
|
-
role: "admin"
|
|
81895
|
-
},
|
|
81896
|
-
"oidcConnections.deleteConnection": {
|
|
81897
|
-
capName: "oidc-connections",
|
|
81898
|
-
capScope: "system",
|
|
81899
|
-
addonId: null,
|
|
81900
|
-
access: "delete",
|
|
81901
|
-
role: "admin"
|
|
81902
|
-
},
|
|
81903
|
-
"oidcConnections.listConnections": {
|
|
81904
|
-
capName: "oidc-connections",
|
|
81905
|
-
capScope: "system",
|
|
81906
|
-
addonId: null,
|
|
81907
|
-
access: "view",
|
|
81908
|
-
role: "admin"
|
|
81909
|
-
},
|
|
81910
|
-
"oidcConnections.updateConnection": {
|
|
81911
|
-
capName: "oidc-connections",
|
|
81912
|
-
capScope: "system",
|
|
81913
|
-
addonId: null,
|
|
81914
|
-
access: "create",
|
|
81915
|
-
role: "admin"
|
|
81916
|
-
},
|
|
81917
81891
|
"osd.getStatus": {
|
|
81918
81892
|
capName: "osd",
|
|
81919
81893
|
capScope: "device",
|
|
@@ -84945,13 +84919,6 @@ Object.freeze({
|
|
|
84945
84919
|
access: "delete",
|
|
84946
84920
|
role: "admin"
|
|
84947
84921
|
},
|
|
84948
|
-
"storage.deleteLocation": {
|
|
84949
|
-
capName: "storage",
|
|
84950
|
-
capScope: "system",
|
|
84951
|
-
addonId: null,
|
|
84952
|
-
access: "delete",
|
|
84953
|
-
role: "admin"
|
|
84954
|
-
},
|
|
84955
84922
|
"storage.endDownload": {
|
|
84956
84923
|
capName: "storage",
|
|
84957
84924
|
capScope: "system",
|
|
@@ -85008,13 +84975,6 @@ Object.freeze({
|
|
|
85008
84975
|
access: "view",
|
|
85009
84976
|
role: "admin"
|
|
85010
84977
|
},
|
|
85011
|
-
"storage.listProviders": {
|
|
85012
|
-
capName: "storage",
|
|
85013
|
-
capScope: "system",
|
|
85014
|
-
addonId: null,
|
|
85015
|
-
access: "view",
|
|
85016
|
-
role: "admin"
|
|
85017
|
-
},
|
|
85018
84978
|
"storage.read": {
|
|
85019
84979
|
capName: "storage",
|
|
85020
84980
|
capScope: "system",
|
|
@@ -85036,27 +84996,6 @@ Object.freeze({
|
|
|
85036
84996
|
access: "view",
|
|
85037
84997
|
role: "admin"
|
|
85038
84998
|
},
|
|
85039
|
-
"storage.testConfig": {
|
|
85040
|
-
capName: "storage",
|
|
85041
|
-
capScope: "system",
|
|
85042
|
-
addonId: null,
|
|
85043
|
-
access: "view",
|
|
85044
|
-
role: "admin"
|
|
85045
|
-
},
|
|
85046
|
-
"storage.testLocation": {
|
|
85047
|
-
capName: "storage",
|
|
85048
|
-
capScope: "system",
|
|
85049
|
-
addonId: null,
|
|
85050
|
-
access: "view",
|
|
85051
|
-
role: "admin"
|
|
85052
|
-
},
|
|
85053
|
-
"storage.upsertLocation": {
|
|
85054
|
-
capName: "storage",
|
|
85055
|
-
capScope: "system",
|
|
85056
|
-
addonId: null,
|
|
85057
|
-
access: "create",
|
|
85058
|
-
role: "admin"
|
|
85059
|
-
},
|
|
85060
84999
|
"storage.write": {
|
|
85061
85000
|
capName: "storage",
|
|
85062
85001
|
capScope: "system",
|
|
@@ -85834,27 +85773,6 @@ Object.freeze({
|
|
|
85834
85773
|
access: "create",
|
|
85835
85774
|
role: "admin"
|
|
85836
85775
|
},
|
|
85837
|
-
"terminalSession.createInstance": {
|
|
85838
|
-
capName: "terminal-session",
|
|
85839
|
-
capScope: "system",
|
|
85840
|
-
addonId: null,
|
|
85841
|
-
access: "create",
|
|
85842
|
-
role: "admin"
|
|
85843
|
-
},
|
|
85844
|
-
"terminalSession.deleteInstance": {
|
|
85845
|
-
capName: "terminal-session",
|
|
85846
|
-
capScope: "system",
|
|
85847
|
-
addonId: null,
|
|
85848
|
-
access: "delete",
|
|
85849
|
-
role: "admin"
|
|
85850
|
-
},
|
|
85851
|
-
"terminalSession.listInstances": {
|
|
85852
|
-
capName: "terminal-session",
|
|
85853
|
-
capScope: "system",
|
|
85854
|
-
addonId: null,
|
|
85855
|
-
access: "view",
|
|
85856
|
-
role: "admin"
|
|
85857
|
-
},
|
|
85858
85776
|
"terminalSession.listLegacyCameras": {
|
|
85859
85777
|
capName: "terminal-session",
|
|
85860
85778
|
capScope: "system",
|
|
@@ -85897,20 +85815,6 @@ Object.freeze({
|
|
|
85897
85815
|
access: "create",
|
|
85898
85816
|
role: "admin"
|
|
85899
85817
|
},
|
|
85900
|
-
"terminalSession.setInstanceEnabled": {
|
|
85901
|
-
capName: "terminal-session",
|
|
85902
|
-
capScope: "system",
|
|
85903
|
-
addonId: null,
|
|
85904
|
-
access: "create",
|
|
85905
|
-
role: "admin"
|
|
85906
|
-
},
|
|
85907
|
-
"terminalSession.updateInstance": {
|
|
85908
|
-
capName: "terminal-session",
|
|
85909
|
-
capScope: "system",
|
|
85910
|
-
addonId: null,
|
|
85911
|
-
access: "create",
|
|
85912
|
-
role: "admin"
|
|
85913
|
-
},
|
|
85914
85818
|
"terminalSession.writeInput": {
|
|
85915
85819
|
capName: "terminal-session",
|
|
85916
85820
|
capScope: "system",
|
|
@@ -85925,6 +85829,13 @@ Object.freeze({
|
|
|
85925
85829
|
access: "create",
|
|
85926
85830
|
role: "viewer"
|
|
85927
85831
|
},
|
|
85832
|
+
"timedRun.getOptions": {
|
|
85833
|
+
capName: "timed-run",
|
|
85834
|
+
capScope: "device",
|
|
85835
|
+
addonId: null,
|
|
85836
|
+
access: "view",
|
|
85837
|
+
role: "viewer"
|
|
85838
|
+
},
|
|
85928
85839
|
"timedRun.getStatus": {
|
|
85929
85840
|
capName: "timed-run",
|
|
85930
85841
|
capScope: "device",
|
|
@@ -85939,6 +85850,13 @@ Object.freeze({
|
|
|
85939
85850
|
access: "create",
|
|
85940
85851
|
role: "viewer"
|
|
85941
85852
|
},
|
|
85853
|
+
"timedRun.setSettings": {
|
|
85854
|
+
capName: "timed-run",
|
|
85855
|
+
capScope: "device",
|
|
85856
|
+
addonId: null,
|
|
85857
|
+
access: "create",
|
|
85858
|
+
role: "admin"
|
|
85859
|
+
},
|
|
85942
85860
|
"toast.onToast": {
|
|
85943
85861
|
capName: "toast",
|
|
85944
85862
|
capScope: "system",
|
|
@@ -86869,6 +86787,7 @@ function offered(received) {
|
|
|
86869
86787
|
};
|
|
86870
86788
|
}
|
|
86871
86789
|
offered(HA_AS), withheld(HOMEKIT_REASON), withheld(ALEXA_REASON), withheld(GOOGLE_REASON), withheld(MATTER_REASON);
|
|
86790
|
+
string().min(1).max(4096);
|
|
86872
86791
|
Object.freeze({
|
|
86873
86792
|
"accessories.getStatus": [{
|
|
86874
86793
|
name: "deviceId",
|
|
@@ -87552,6 +87471,11 @@ Object.freeze({
|
|
|
87552
87471
|
form: "single",
|
|
87553
87472
|
optional: false
|
|
87554
87473
|
}],
|
|
87474
|
+
"deviceManager.setAlias": [{
|
|
87475
|
+
name: "deviceId",
|
|
87476
|
+
form: "single",
|
|
87477
|
+
optional: false
|
|
87478
|
+
}],
|
|
87555
87479
|
"deviceManager.setChildLayout": [{
|
|
87556
87480
|
name: "deviceId",
|
|
87557
87481
|
form: "single",
|
|
@@ -89616,6 +89540,11 @@ Object.freeze({
|
|
|
89616
89540
|
form: "single",
|
|
89617
89541
|
optional: false
|
|
89618
89542
|
}],
|
|
89543
|
+
"timedRun.getOptions": [{
|
|
89544
|
+
name: "deviceId",
|
|
89545
|
+
form: "single",
|
|
89546
|
+
optional: false
|
|
89547
|
+
}],
|
|
89619
89548
|
"timedRun.getStatus": [{
|
|
89620
89549
|
name: "deviceId",
|
|
89621
89550
|
form: "single",
|
|
@@ -89626,6 +89555,11 @@ Object.freeze({
|
|
|
89626
89555
|
form: "single",
|
|
89627
89556
|
optional: false
|
|
89628
89557
|
}],
|
|
89558
|
+
"timedRun.setSettings": [{
|
|
89559
|
+
name: "deviceId",
|
|
89560
|
+
form: "single",
|
|
89561
|
+
optional: false
|
|
89562
|
+
}],
|
|
89629
89563
|
"update.getStatus": [{
|
|
89630
89564
|
name: "deviceId",
|
|
89631
89565
|
form: "single",
|
|
@@ -90488,6 +90422,7 @@ var STATE_SUMMARY_VARS = [
|
|
|
90488
90422
|
[...RULE_TEXT],
|
|
90489
90423
|
[...RULE_TEXT],
|
|
90490
90424
|
[...RULE_TEXT],
|
|
90425
|
+
[...RULE_TEXT],
|
|
90491
90426
|
[...RULE_BODY_ONLY],
|
|
90492
90427
|
[...RULE_TEXT],
|
|
90493
90428
|
([...RULE_TEXT], [...DEVICE_EVENTS]),
|