@camstack/addon-post-analysis 1.2.653 → 1.2.654
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 +7 -0
- package/dist/{clip-model-registry-BrazZJvr.mjs → clip-model-registry-BX6j2lnF.mjs} +997 -147
- package/dist/{clip-model-registry-Bz1uQvQ8.js → clip-model-registry-CFQBxtE2.js} +997 -147
- package/dist/embedding-encoder/index.js +1 -1
- package/dist/embedding-encoder/index.mjs +1 -1
- package/dist/pipeline-analytics/_stub.js +2 -2
- package/dist/pipeline-analytics/{_virtual_mf-localSharedImportMap___mfe_internal__addon_pipeline_analytics_widgets-D6DnF6Vk.mjs → _virtual_mf-localSharedImportMap___mfe_internal__addon_pipeline_analytics_widgets-Vag6rhEh.mjs} +2 -2
- package/dist/pipeline-analytics/_virtual_mf___mfe_internal__addon_pipeline_analytics_widgets__loadShare___mf_0_camstack_mf_1_types__loadShare__.js-BUwWKfHC.mjs +26 -0
- package/dist/pipeline-analytics/_virtual_mf___mfe_internal__addon_pipeline_analytics_widgets__loadShare___mf_0_camstack_mf_1_ui_mf_2_library__loadShare__.js-DXQUFp7P.mjs +26 -0
- package/dist/pipeline-analytics/{hostInit-DtrcY1yz.mjs → hostInit-CnvnZsmk.mjs} +2 -2
- package/dist/pipeline-analytics/index.js +164 -10
- package/dist/pipeline-analytics/index.mjs +164 -10
- package/dist/pipeline-analytics/remoteEntry.js +1 -1
- package/package.json +1 -1
- package/dist/pipeline-analytics/_virtual_mf___mfe_internal__addon_pipeline_analytics_widgets__loadShare___mf_0_camstack_mf_1_types__loadShare__.js-BKMr4IqL.mjs +0 -26
- package/dist/pipeline-analytics/_virtual_mf___mfe_internal__addon_pipeline_analytics_widgets__loadShare___mf_0_camstack_mf_1_ui_mf_2_library__loadShare__.js-CtNyIYsM.mjs +0 -26
|
@@ -5676,7 +5676,7 @@ var ZodIssueCode = {
|
|
|
5676
5676
|
var ZodFirstPartyTypeKind;
|
|
5677
5677
|
ZodFirstPartyTypeKind || (ZodFirstPartyTypeKind = {});
|
|
5678
5678
|
//#endregion
|
|
5679
|
-
//#region ../types/dist/sleep-
|
|
5679
|
+
//#region ../types/dist/sleep-CeyhrcOk.mjs
|
|
5680
5680
|
/**
|
|
5681
5681
|
* The audio chunk plane's byte format, and the ONE expansion from a coded
|
|
5682
5682
|
* window to float samples (D455).
|
|
@@ -7743,6 +7743,7 @@ var BaseAddon = class {
|
|
|
7743
7743
|
* a warning and falls back rather than crashing boot.
|
|
7744
7744
|
*/
|
|
7745
7745
|
state(key, schema, fallback) {
|
|
7746
|
+
this._declaredStateKeys.add(key);
|
|
7746
7747
|
return createDurableState({
|
|
7747
7748
|
key,
|
|
7748
7749
|
schema,
|
|
@@ -7758,6 +7759,96 @@ var BaseAddon = class {
|
|
|
7758
7759
|
} })
|
|
7759
7760
|
});
|
|
7760
7761
|
}
|
|
7762
|
+
/** Durable-state keys this process registered through {@link state}. */
|
|
7763
|
+
_declaredStateKeys = /* @__PURE__ */ new Set();
|
|
7764
|
+
/**
|
|
7765
|
+
* Stale-data audit: every global-settings key this addon still declares —
|
|
7766
|
+
* constructor defaults, settings-schema fields (layout containers included),
|
|
7767
|
+
* durable-state keys and the root of each `secretStatePaths` entry. Answered
|
|
7768
|
+
* here, in the addon's own process, so the hub keeps no copy of it.
|
|
7769
|
+
*/
|
|
7770
|
+
async getDeclaredSettingsKeys() {
|
|
7771
|
+
return { keys: [...this.declaredKeySet()].toSorted() };
|
|
7772
|
+
}
|
|
7773
|
+
declaredKeySet() {
|
|
7774
|
+
const keys = new Set(Object.keys(this.defaults));
|
|
7775
|
+
const schema = this.globalSettingsSchema();
|
|
7776
|
+
if (schema) for (const section of schema.sections) for (const key of collectFieldKeys(section.fields)) keys.add(key);
|
|
7777
|
+
for (const key of this._declaredStateKeys) keys.add(key);
|
|
7778
|
+
for (const path of this.secretStatePaths) {
|
|
7779
|
+
const root = path.split(/[.[]/, 1)[0];
|
|
7780
|
+
if (root) keys.add(root);
|
|
7781
|
+
}
|
|
7782
|
+
return keys;
|
|
7783
|
+
}
|
|
7784
|
+
/**
|
|
7785
|
+
* Stale-data audit: remove stored global-settings keys the addon no longer
|
|
7786
|
+
* declares, and clear the keychain values their markers held — except a value
|
|
7787
|
+
* a surviving key still points at. A declared or absent key is refused.
|
|
7788
|
+
*/
|
|
7789
|
+
async unsetStoredSettingsKeys(keys) {
|
|
7790
|
+
const settings = this._ctx?.settings;
|
|
7791
|
+
const raw = this.rawSettings();
|
|
7792
|
+
if (!settings || !raw) return {
|
|
7793
|
+
removed: [],
|
|
7794
|
+
refused: keys.map((key) => ({
|
|
7795
|
+
key,
|
|
7796
|
+
reason: "no settings store"
|
|
7797
|
+
})),
|
|
7798
|
+
secretsCleared: 0
|
|
7799
|
+
};
|
|
7800
|
+
let stored;
|
|
7801
|
+
try {
|
|
7802
|
+
stored = await raw.readAddonStore();
|
|
7803
|
+
} catch (error) {
|
|
7804
|
+
const reason = `store unreadable: ${error instanceof Error ? error.message : "unknown"}`;
|
|
7805
|
+
return {
|
|
7806
|
+
removed: [],
|
|
7807
|
+
refused: keys.map((key) => ({
|
|
7808
|
+
key,
|
|
7809
|
+
reason
|
|
7810
|
+
})),
|
|
7811
|
+
secretsCleared: 0
|
|
7812
|
+
};
|
|
7813
|
+
}
|
|
7814
|
+
const declared = this.declaredKeySet();
|
|
7815
|
+
const removed = [];
|
|
7816
|
+
const refused = [];
|
|
7817
|
+
for (const key of keys) {
|
|
7818
|
+
const base = key.split("@", 1)[0] ?? key;
|
|
7819
|
+
if (declared.has(base)) refused.push({
|
|
7820
|
+
key,
|
|
7821
|
+
reason: "still declared by the addon"
|
|
7822
|
+
});
|
|
7823
|
+
else if (!(key in stored)) refused.push({
|
|
7824
|
+
key,
|
|
7825
|
+
reason: "not stored"
|
|
7826
|
+
});
|
|
7827
|
+
else removed.push(key);
|
|
7828
|
+
}
|
|
7829
|
+
if (removed.length === 0) return {
|
|
7830
|
+
removed,
|
|
7831
|
+
refused,
|
|
7832
|
+
secretsCleared: 0
|
|
7833
|
+
};
|
|
7834
|
+
const kept = /* @__PURE__ */ new Set();
|
|
7835
|
+
const held = /* @__PURE__ */ new Set();
|
|
7836
|
+
for (const [key, value] of Object.entries(stored)) {
|
|
7837
|
+
const target = removed.includes(key) ? held : kept;
|
|
7838
|
+
for (const ref of collectSecretMarkerRefs(value)) target.add(ref);
|
|
7839
|
+
}
|
|
7840
|
+
const refsToClear = [...held].filter((ref) => !kept.has(ref));
|
|
7841
|
+
const patch = {};
|
|
7842
|
+
for (const key of removed) patch[key] = void 0;
|
|
7843
|
+
await settings.writeAddonStore(patch);
|
|
7844
|
+
const secretsCleared = refsToClear.length > 0 && this._ctx?.secrets ? await this._ctx.secrets.delete(refsToClear) : 0;
|
|
7845
|
+
await this.resolveConfig();
|
|
7846
|
+
return {
|
|
7847
|
+
removed,
|
|
7848
|
+
refused,
|
|
7849
|
+
secretsCleared
|
|
7850
|
+
};
|
|
7851
|
+
}
|
|
7761
7852
|
/** Per-device variant of {@link state}, backed by the per-device store. */
|
|
7762
7853
|
deviceState(deviceId, key, schema, fallback) {
|
|
7763
7854
|
return createDurableState({
|
|
@@ -8028,6 +8119,21 @@ function dropPerNodeFields(fields) {
|
|
|
8028
8119
|
}
|
|
8029
8120
|
return kept;
|
|
8030
8121
|
}
|
|
8122
|
+
function collectFieldKeys(fields) {
|
|
8123
|
+
const collected = [];
|
|
8124
|
+
for (const field of fields) {
|
|
8125
|
+
if (field.type === "group") {
|
|
8126
|
+
collected.push(...collectFieldKeys(field.fields));
|
|
8127
|
+
continue;
|
|
8128
|
+
}
|
|
8129
|
+
if (field.type === "sub-tabs") {
|
|
8130
|
+
for (const tab of field.tabs) collected.push(...collectFieldKeys(tab.fields));
|
|
8131
|
+
continue;
|
|
8132
|
+
}
|
|
8133
|
+
if ("key" in field && typeof field.key === "string") collected.push(field.key);
|
|
8134
|
+
}
|
|
8135
|
+
return collected;
|
|
8136
|
+
}
|
|
8031
8137
|
function collectPerNodeFieldKeys(fields) {
|
|
8032
8138
|
const collected = [];
|
|
8033
8139
|
for (const field of fields) {
|
|
@@ -11231,7 +11337,7 @@ function sleep(ms) {
|
|
|
11231
11337
|
return new Promise((resolve) => setTimeout(resolve, Math.max(0, ms)));
|
|
11232
11338
|
}
|
|
11233
11339
|
//#endregion
|
|
11234
|
-
//#region ../types/dist/err-msg-
|
|
11340
|
+
//#region ../types/dist/err-msg-BD5buxvT.mjs
|
|
11235
11341
|
var DeviceType = /* @__PURE__ */ function(DeviceType) {
|
|
11236
11342
|
DeviceType["Camera"] = "camera";
|
|
11237
11343
|
DeviceType["Hub"] = "hub";
|
|
@@ -11337,6 +11443,12 @@ var DeviceType = /* @__PURE__ */ function(DeviceType) {
|
|
|
11337
11443
|
DeviceType["Washer"] = "washer";
|
|
11338
11444
|
/** Tumble dryer. Same plug-built running surface as {@link Washer}. */
|
|
11339
11445
|
DeviceType["Dryer"] = "dryer";
|
|
11446
|
+
/** The physical bridge box of a vendor ecosystem (Velux KLF-200, and later
|
|
11447
|
+
* other radio-to-IP bridges). It carries the box's own facts (firmware,
|
|
11448
|
+
* address, connection state) and the actions the box really supports
|
|
11449
|
+
* (`reboot`, `device-admin-link`). Products are NOT its children — they are
|
|
11450
|
+
* adopted beside it — and its connection settings stay on the integration. */
|
|
11451
|
+
DeviceType["Gateway"] = "gateway";
|
|
11340
11452
|
return DeviceType;
|
|
11341
11453
|
}({});
|
|
11342
11454
|
var DeviceFeature = /* @__PURE__ */ function(DeviceFeature) {
|
|
@@ -11597,7 +11709,7 @@ function errMsg(err) {
|
|
|
11597
11709
|
return String(err);
|
|
11598
11710
|
}
|
|
11599
11711
|
//#endregion
|
|
11600
|
-
//#region ../types/dist/composition-
|
|
11712
|
+
//#region ../types/dist/composition-C7WdThmP.mjs
|
|
11601
11713
|
/**
|
|
11602
11714
|
* Deterministic SHA-256 hash of an arbitrary serialisable value. The
|
|
11603
11715
|
* canonical form sorts object keys alphabetically at every depth so two
|
|
@@ -17566,8 +17678,194 @@ object({
|
|
|
17566
17678
|
quantity: ReadingQuantitySchema,
|
|
17567
17679
|
unit: string().min(1)
|
|
17568
17680
|
});
|
|
17569
|
-
/**
|
|
17570
|
-
*
|
|
17681
|
+
/**
|
|
17682
|
+
* The class names a per-class COUNT can ever be keyed on — the macro ids, and
|
|
17683
|
+
* only those.
|
|
17684
|
+
*
|
|
17685
|
+
* `preserveOriginal: false` below is the whole reason this set exists: the
|
|
17686
|
+
* executor maps each raw COCO label onto its macro and DROPS everything else,
|
|
17687
|
+
* so a tracked detection's `className` is always one of {@link MACRO_LABELS}.
|
|
17688
|
+
* Any surface that indexes counts by class name — the ZoneAnalytics occupancy
|
|
17689
|
+
* snapshot's `byClass`, and therefore every occupancy rule — can match nothing
|
|
17690
|
+
* else. Derived from the catalog, never hand-listed, so a new macro joins it by
|
|
17691
|
+
* being declared once.
|
|
17692
|
+
*
|
|
17693
|
+
* Cost of not having it, 2026-08-12: the notification rule editor offered the
|
|
17694
|
+
* full taxonomy for an occupancy class (occupancy is the one condition that
|
|
17695
|
+
* does not go through the engine's macro-expanding `expandClassSelector`), two
|
|
17696
|
+
* live rules were authored on `car`, and both counters read 0 forever.
|
|
17697
|
+
*/
|
|
17698
|
+
var DETECTION_MACRO_CLASSES = new Set([
|
|
17699
|
+
{
|
|
17700
|
+
id: "person",
|
|
17701
|
+
name: "Person"
|
|
17702
|
+
},
|
|
17703
|
+
{
|
|
17704
|
+
id: "vehicle",
|
|
17705
|
+
name: "Vehicle"
|
|
17706
|
+
},
|
|
17707
|
+
{
|
|
17708
|
+
id: "animal",
|
|
17709
|
+
name: "Animal"
|
|
17710
|
+
},
|
|
17711
|
+
{
|
|
17712
|
+
id: "package",
|
|
17713
|
+
name: "Package"
|
|
17714
|
+
}
|
|
17715
|
+
].map((l) => l.id));
|
|
17716
|
+
/** True when `className` is a macro the detector can actually emit (and hence a
|
|
17717
|
+
* class a count can be keyed on) — see {@link DETECTION_MACRO_CLASSES}. */
|
|
17718
|
+
function isDetectionMacroClass(className) {
|
|
17719
|
+
return DETECTION_MACRO_CLASSES.has(className.trim().toLowerCase());
|
|
17720
|
+
}
|
|
17721
|
+
var COCO_TO_MACRO = {
|
|
17722
|
+
mapping: {
|
|
17723
|
+
person: "person",
|
|
17724
|
+
bicycle: "vehicle",
|
|
17725
|
+
car: "vehicle",
|
|
17726
|
+
motorcycle: "vehicle",
|
|
17727
|
+
airplane: "vehicle",
|
|
17728
|
+
bus: "vehicle",
|
|
17729
|
+
train: "vehicle",
|
|
17730
|
+
truck: "vehicle",
|
|
17731
|
+
boat: "vehicle",
|
|
17732
|
+
bird: "animal",
|
|
17733
|
+
cat: "animal",
|
|
17734
|
+
dog: "animal",
|
|
17735
|
+
horse: "animal",
|
|
17736
|
+
sheep: "animal",
|
|
17737
|
+
cow: "animal",
|
|
17738
|
+
elephant: "animal",
|
|
17739
|
+
bear: "animal",
|
|
17740
|
+
zebra: "animal",
|
|
17741
|
+
giraffe: "animal",
|
|
17742
|
+
suitcase: "package",
|
|
17743
|
+
backpack: "package",
|
|
17744
|
+
handbag: "package"
|
|
17745
|
+
},
|
|
17746
|
+
preserveOriginal: false
|
|
17747
|
+
};
|
|
17748
|
+
/**
|
|
17749
|
+
* WHAT a detection-shaped leaf is about: one MACRO class (person, vehicle,
|
|
17750
|
+
* animal, package) plus an OPTIONAL label that narrows it.
|
|
17751
|
+
*
|
|
17752
|
+
* The taxonomy is `COCO_TO_MACRO` (and `CLASS_MAP_MACRO_TARGETS`) — never a
|
|
17753
|
+
* second list. The label that fits depends on the macro class:
|
|
17754
|
+
*
|
|
17755
|
+
* - `animal` → a sub-class (`dog`, `cat`, …);
|
|
17756
|
+
* - `person` → a known face (an identity of the `face-gallery`);
|
|
17757
|
+
* - `vehicle` → a plate (its text) or a sub-class (`car`, `truck`, …);
|
|
17758
|
+
* - `package` → a sub-class.
|
|
17759
|
+
*
|
|
17760
|
+
* `other` exists only so a class the taxonomy does not know (a custom model's
|
|
17761
|
+
* `forklift`) survives the conversion of a stored recipe without widening.
|
|
17762
|
+
*
|
|
17763
|
+
* A label is decided LATE (D683): face recognition and LPR land after the
|
|
17764
|
+
* detection starts. The track-lifecycle `update` event carries the newly
|
|
17765
|
+
* resolved `label` / `plateText`, which is why a leaf with a label fires when
|
|
17766
|
+
* the subject GETS it — not at the first detection.
|
|
17767
|
+
*/
|
|
17768
|
+
var SubClassLabelSchema = object({
|
|
17769
|
+
kind: literal("sub-class"),
|
|
17770
|
+
className: string().min(1)
|
|
17771
|
+
});
|
|
17772
|
+
var IdentityLabelSchema = object({
|
|
17773
|
+
kind: literal("identity"),
|
|
17774
|
+
/** The `face-gallery` identity id (stable across a rename). */
|
|
17775
|
+
identityId: string().min(1),
|
|
17776
|
+
/** The identity's name — what a track-lifecycle event carries as `label`. */
|
|
17777
|
+
name: string().min(1)
|
|
17778
|
+
});
|
|
17779
|
+
var PlateLabelSchema = object({
|
|
17780
|
+
kind: literal("plate"),
|
|
17781
|
+
text: string().min(1)
|
|
17782
|
+
});
|
|
17783
|
+
function macroOf$1(className) {
|
|
17784
|
+
return COCO_TO_MACRO.mapping[className.toLowerCase()] ?? className.toLowerCase();
|
|
17785
|
+
}
|
|
17786
|
+
/** A sub-class label must belong to the macro it is under. */
|
|
17787
|
+
function subClassBelongs(macro, label) {
|
|
17788
|
+
return label === void 0 || macroOf$1(label.className) === macro;
|
|
17789
|
+
}
|
|
17790
|
+
var subClassOf = (macro) => SubClassLabelSchema.refine((l) => subClassBelongs(macro, l), { message: `that class is not a kind of ${macro} in the detection taxonomy` });
|
|
17791
|
+
var DetectionSubjectSchema = discriminatedUnion("macro", [
|
|
17792
|
+
object({
|
|
17793
|
+
macro: literal("animal"),
|
|
17794
|
+
label: subClassOf("animal").optional()
|
|
17795
|
+
}),
|
|
17796
|
+
object({
|
|
17797
|
+
macro: literal("person"),
|
|
17798
|
+
label: IdentityLabelSchema.optional()
|
|
17799
|
+
}),
|
|
17800
|
+
object({
|
|
17801
|
+
macro: literal("vehicle"),
|
|
17802
|
+
label: discriminatedUnion("kind", [SubClassLabelSchema.refine((l) => subClassBelongs("vehicle", l), { message: "that class is not a kind of vehicle in the detection taxonomy" }), PlateLabelSchema]).optional()
|
|
17803
|
+
}),
|
|
17804
|
+
object({
|
|
17805
|
+
macro: literal("package"),
|
|
17806
|
+
label: subClassOf("package").optional()
|
|
17807
|
+
}),
|
|
17808
|
+
object({
|
|
17809
|
+
macro: literal("other"),
|
|
17810
|
+
className: string().min(1)
|
|
17811
|
+
})
|
|
17812
|
+
]);
|
|
17813
|
+
/**
|
|
17814
|
+
* The subject of a PARKED object. The stationary registry's event carries a
|
|
17815
|
+
* class and a zone, no face and no plate — an identity or plate label there
|
|
17816
|
+
* could never match, so the schema refuses it instead of letting it sit dead.
|
|
17817
|
+
*/
|
|
17818
|
+
var StationarySubjectSchema = DetectionSubjectSchema.refine((s) => s.macro === "other" || s.label === void 0 || s.label.kind === "sub-class", { message: "a parked object carries no face or plate — only a class can narrow it" });
|
|
17819
|
+
/**
|
|
17820
|
+
* A stored class string as a subject: a macro name stays a macro; a raw class
|
|
17821
|
+
* the taxonomy files under a macro becomes that macro plus the sub-class label
|
|
17822
|
+
* (`dog` → animal / dog); anything else is `other`, kept verbatim.
|
|
17823
|
+
*/
|
|
17824
|
+
function subjectFromClassName(className) {
|
|
17825
|
+
const name = className.trim().toLowerCase();
|
|
17826
|
+
const macro = COCO_TO_MACRO.mapping[name];
|
|
17827
|
+
if (new Set(Object.values(COCO_TO_MACRO.mapping)).has(name)) return macroOnly(name);
|
|
17828
|
+
if (macro === void 0) return {
|
|
17829
|
+
macro: "other",
|
|
17830
|
+
className
|
|
17831
|
+
};
|
|
17832
|
+
const label = {
|
|
17833
|
+
kind: "sub-class",
|
|
17834
|
+
className: name
|
|
17835
|
+
};
|
|
17836
|
+
switch (macro) {
|
|
17837
|
+
case "animal": return {
|
|
17838
|
+
macro: "animal",
|
|
17839
|
+
label
|
|
17840
|
+
};
|
|
17841
|
+
case "vehicle": return {
|
|
17842
|
+
macro: "vehicle",
|
|
17843
|
+
label
|
|
17844
|
+
};
|
|
17845
|
+
case "package": return {
|
|
17846
|
+
macro: "package",
|
|
17847
|
+
label
|
|
17848
|
+
};
|
|
17849
|
+
default: return {
|
|
17850
|
+
macro: "other",
|
|
17851
|
+
className
|
|
17852
|
+
};
|
|
17853
|
+
}
|
|
17854
|
+
}
|
|
17855
|
+
function macroOnly(macro) {
|
|
17856
|
+
switch (macro) {
|
|
17857
|
+
case "animal": return { macro: "animal" };
|
|
17858
|
+
case "person": return { macro: "person" };
|
|
17859
|
+
case "vehicle": return { macro: "vehicle" };
|
|
17860
|
+
case "package": return { macro: "package" };
|
|
17861
|
+
default: return {
|
|
17862
|
+
macro: "other",
|
|
17863
|
+
className: macro
|
|
17864
|
+
};
|
|
17865
|
+
}
|
|
17866
|
+
}
|
|
17867
|
+
/** How a state leaf compares a device field to a value. Derived from the
|
|
17868
|
+
* field's `kind` in `deviceManager.getWireableFields`, never hand-maintained. */
|
|
17571
17869
|
var AutomationConditionOperatorSchema = _enum([
|
|
17572
17870
|
"eq",
|
|
17573
17871
|
"ne",
|
|
@@ -17578,12 +17876,76 @@ var AutomationConditionOperatorSchema = _enum([
|
|
|
17578
17876
|
"contains",
|
|
17579
17877
|
"in"
|
|
17580
17878
|
]);
|
|
17581
|
-
|
|
17582
|
-
|
|
17879
|
+
/**
|
|
17880
|
+
* D8 compliance, and it is the reason a "becomes" leaf is not merely an event
|
|
17881
|
+
* subscription: it evaluates against the **state mirror**, which is reconciled,
|
|
17882
|
+
* and an event only WAKES the evaluation. A dropped event therefore DELAYS a
|
|
17883
|
+
* fire; it does not lose it.
|
|
17884
|
+
*/
|
|
17885
|
+
var DeviceBecomesLeafSchema = object({
|
|
17886
|
+
kind: literal("device-becomes"),
|
|
17887
|
+
deviceId: number().int().nonnegative(),
|
|
17888
|
+
cap: string().min(1),
|
|
17889
|
+
fieldPath: string().min(1),
|
|
17890
|
+
/** Fire when the field takes this value. Omit to fire on any change. */
|
|
17891
|
+
becomes: union([
|
|
17892
|
+
string(),
|
|
17893
|
+
number(),
|
|
17894
|
+
boolean()
|
|
17895
|
+
]).optional(),
|
|
17896
|
+
/** Only on a CHANGE of value, not on every re-report. */
|
|
17897
|
+
edge: boolean().optional(),
|
|
17898
|
+
/** The new value must hold this long before it counts. */
|
|
17899
|
+
forMs: number().int().min(0).max(864e5).optional(),
|
|
17900
|
+
/** Collapse a burst into one occurrence. */
|
|
17901
|
+
debounceMs: number().int().min(0).max(6e5).optional()
|
|
17902
|
+
});
|
|
17903
|
+
var DeviceEventLeafSchema = object({
|
|
17904
|
+
kind: literal("device-event"),
|
|
17905
|
+
/** An `EventCategory` value. */
|
|
17906
|
+
category: string().min(1),
|
|
17907
|
+
deviceId: number().int().nonnegative().optional()
|
|
17908
|
+
});
|
|
17909
|
+
var ScheduleLeafSchema = object({
|
|
17910
|
+
kind: literal("schedule"),
|
|
17911
|
+
cron: string().min(1).max(120)
|
|
17912
|
+
});
|
|
17913
|
+
var ManualLeafSchema = object({ kind: literal("manual") });
|
|
17914
|
+
var IntervalLeafSchema = object({
|
|
17915
|
+
kind: literal("interval"),
|
|
17916
|
+
minutes: number().int().min(1).max(1440)
|
|
17917
|
+
});
|
|
17918
|
+
var DetectionLeafSchema = object({
|
|
17919
|
+
kind: literal("detection"),
|
|
17920
|
+
/** One macro class each, optionally narrowed by a label; a track of any listed subject fires. */
|
|
17921
|
+
subjects: array(DetectionSubjectSchema).min(1),
|
|
17922
|
+
deviceIds: array(number().int().nonnegative()).min(1),
|
|
17923
|
+
/** The track must have visited at least one of these zones. */
|
|
17924
|
+
zones: array(string().min(1)).min(1).optional(),
|
|
17925
|
+
/** Best-so-far confidence the track must reach. */
|
|
17926
|
+
minScore: number().min(0).max(1).optional()
|
|
17927
|
+
});
|
|
17928
|
+
var StationaryLeafSchema = object({
|
|
17929
|
+
kind: literal("stationary"),
|
|
17930
|
+
deviceIds: array(number().int().nonnegative()).min(1),
|
|
17931
|
+
subjects: array(StationarySubjectSchema).min(1).optional(),
|
|
17932
|
+
zones: array(string().min(1)).min(1).optional(),
|
|
17933
|
+
/** `appeared`: it became parked. `departed`: the registry retired it. */
|
|
17934
|
+
phase: _enum(["appeared", "departed"])
|
|
17935
|
+
});
|
|
17936
|
+
/** "is": one device field compared to one value, NOW. */
|
|
17937
|
+
var DeviceIsLeafSchema = object({
|
|
17938
|
+
kind: literal("device-is"),
|
|
17583
17939
|
deviceId: number().int().nonnegative(),
|
|
17584
17940
|
cap: string().min(1),
|
|
17585
17941
|
fieldPath: string().min(1),
|
|
17586
17942
|
operator: AutomationConditionOperatorSchema,
|
|
17943
|
+
/**
|
|
17944
|
+
* The value. A number on a quantity field is stored in the field's base unit
|
|
17945
|
+
* (D944); a quantity value is the WRITE form, which the save boundary
|
|
17946
|
+
* replaces with the converted number and `unit`. A leaf that still carries
|
|
17947
|
+
* one is never evaluated (it fails).
|
|
17948
|
+
*/
|
|
17587
17949
|
value: union([
|
|
17588
17950
|
string(),
|
|
17589
17951
|
number(),
|
|
@@ -17591,24 +17953,26 @@ var AutomationConditionLeafSchema = object({
|
|
|
17591
17953
|
array(union([string(), number()])),
|
|
17592
17954
|
QuantityValueSchema
|
|
17593
17955
|
]),
|
|
17956
|
+
/** The unit the person picked for `value` (display only; `value` is in the base unit). */
|
|
17594
17957
|
unit: string().min(1).optional()
|
|
17595
17958
|
});
|
|
17596
|
-
|
|
17959
|
+
/**
|
|
17960
|
+
* True when the camera currently has a PARKED object matching `subjects` in at
|
|
17961
|
+
* least one of `zones`. Reads the zone-analytics snapshot through the same
|
|
17962
|
+
* mirror as every other state leaf, so a dropped event never decides it (D49).
|
|
17963
|
+
*/
|
|
17964
|
+
var StationaryPresentLeafSchema = object({
|
|
17597
17965
|
kind: literal("stationary-present"),
|
|
17598
17966
|
deviceId: number().int().nonnegative(),
|
|
17599
|
-
|
|
17600
|
-
classes: array(string().min(1)).min(1).optional(),
|
|
17601
|
-
/** The parked object must be in at least one of these zones. */
|
|
17967
|
+
subjects: array(StationarySubjectSchema).min(1).optional(),
|
|
17602
17968
|
zones: array(string().min(1)).min(1).optional()
|
|
17603
17969
|
});
|
|
17604
17970
|
/**
|
|
17605
|
-
* The
|
|
17606
|
-
*
|
|
17607
|
-
*
|
|
17608
|
-
* validation is the SAME function `ExpressionSourceSchema` runs, so the two
|
|
17609
|
-
* cannot drift — an expression that one accepts, the other accepts.
|
|
17971
|
+
* The escape hatch: the bounded expression engine over named device bindings.
|
|
17972
|
+
* Declared as a plain object so a discriminated union can read `kind`; the
|
|
17973
|
+
* author-time validation is the SAME function `ExpressionSourceSchema` runs.
|
|
17610
17974
|
*/
|
|
17611
|
-
var
|
|
17975
|
+
var ExpressionLeafSchema = object({
|
|
17612
17976
|
kind: literal("expression"),
|
|
17613
17977
|
expr: string().min(1).max(MAX_EXPRESSION_SOURCE_LENGTH),
|
|
17614
17978
|
bindings: record(string().regex(EXPRESSION_IDENTIFIER_RE), ExpressionBindingSourceSchema)
|
|
@@ -17620,55 +17984,62 @@ var AutomationConditionExpressionSchema = object({
|
|
|
17620
17984
|
path: ["expr"]
|
|
17621
17985
|
});
|
|
17622
17986
|
});
|
|
17623
|
-
var
|
|
17987
|
+
var AutomationWhenSchema = lazy(() => discriminatedUnion("kind", [
|
|
17624
17988
|
object({
|
|
17625
17989
|
kind: literal("all"),
|
|
17626
|
-
children: array(
|
|
17990
|
+
children: array(AutomationWhenSchema)
|
|
17627
17991
|
}),
|
|
17628
17992
|
object({
|
|
17629
17993
|
kind: literal("any"),
|
|
17630
|
-
children: array(
|
|
17994
|
+
children: array(AutomationWhenSchema)
|
|
17631
17995
|
}),
|
|
17632
17996
|
object({
|
|
17633
17997
|
kind: literal("not"),
|
|
17634
|
-
child:
|
|
17998
|
+
child: AutomationWhenSchema
|
|
17635
17999
|
}),
|
|
17636
|
-
|
|
17637
|
-
|
|
17638
|
-
|
|
18000
|
+
DeviceBecomesLeafSchema,
|
|
18001
|
+
DeviceEventLeafSchema,
|
|
18002
|
+
ScheduleLeafSchema,
|
|
18003
|
+
ManualLeafSchema,
|
|
18004
|
+
IntervalLeafSchema,
|
|
18005
|
+
DetectionLeafSchema,
|
|
18006
|
+
StationaryLeafSchema,
|
|
18007
|
+
DeviceIsLeafSchema,
|
|
18008
|
+
StationaryPresentLeafSchema,
|
|
18009
|
+
ExpressionLeafSchema
|
|
17639
18010
|
]));
|
|
17640
18011
|
/**
|
|
17641
|
-
*
|
|
17642
|
-
*
|
|
17643
|
-
*
|
|
17644
|
-
*
|
|
17645
|
-
*
|
|
17646
|
-
*
|
|
17647
|
-
*
|
|
17648
|
-
*
|
|
17649
|
-
|
|
17650
|
-
|
|
18012
|
+
* The recipe shape before the single `when` tree: a flat list of triggers
|
|
18013
|
+
* (OR'd, each an instant) and an optional condition tree. Stored recipes —
|
|
18014
|
+
* the `AUTOMATION_RECIPE` literal of every block saved so far, and whatever an
|
|
18015
|
+
* older client still posts — are in this shape, so it stays READABLE here, and
|
|
18016
|
+
* {@link convertLegacyRecipe} turns it into the new one, losslessly and one
|
|
18017
|
+
* way. Nothing writes this shape any more.
|
|
18018
|
+
*
|
|
18019
|
+
* `{ triggers: [t1…tn], conditions?: C }`
|
|
18020
|
+
* → `when = all(any(t1…tn), C)`, or `any(t1…tn)` without `C`;
|
|
18021
|
+
* a single trigger is not wrapped in `any`.
|
|
18022
|
+
* a `condition` leaf → a `device-is` leaf (the "is" verb);
|
|
18023
|
+
* a `device-state` trigger → a `device-becomes` leaf (the "becomes" verb);
|
|
18024
|
+
* `classes: ['dog']` → the macro `animal` with the label `dog`.
|
|
18025
|
+
*/
|
|
18026
|
+
var LegacyTriggerSchema = discriminatedUnion("kind", [
|
|
17651
18027
|
object({
|
|
17652
18028
|
kind: literal("device-state"),
|
|
17653
18029
|
deviceId: number().int().nonnegative(),
|
|
17654
18030
|
cap: string().min(1),
|
|
17655
18031
|
fieldPath: string().min(1),
|
|
17656
|
-
/** Fire when the field takes this value. Omit to fire on any change. */
|
|
17657
18032
|
becomes: union([
|
|
17658
18033
|
string(),
|
|
17659
18034
|
number(),
|
|
17660
18035
|
boolean()
|
|
17661
18036
|
]).optional(),
|
|
17662
|
-
/** Only on a CHANGE of value, not on every re-report. */
|
|
17663
18037
|
edge: boolean().optional(),
|
|
17664
|
-
/** The condition must hold this long before the run starts. */
|
|
17665
18038
|
forMs: number().int().min(0).max(864e5).optional(),
|
|
17666
|
-
/** Collapse a burst into one run. */
|
|
17667
18039
|
debounceMs: number().int().min(0).max(6e5).optional()
|
|
17668
18040
|
}),
|
|
17669
18041
|
object({
|
|
17670
18042
|
kind: literal("device-event"),
|
|
17671
|
-
/** An `EventCategory` value. */
|
|
17672
18043
|
category: string().min(1),
|
|
17673
18044
|
deviceId: number().int().nonnegative().optional()
|
|
17674
18045
|
}),
|
|
@@ -17679,25 +18050,16 @@ var AutomationTriggerSchema = discriminatedUnion("kind", [
|
|
|
17679
18050
|
object({ kind: literal("manual") }),
|
|
17680
18051
|
object({
|
|
17681
18052
|
kind: literal("detection"),
|
|
17682
|
-
/** Class names. A macro class (`animal`, `vehicle`, `person`, `package`)
|
|
17683
|
-
* matches every raw class that maps to it; any other name matches
|
|
17684
|
-
* exactly. */
|
|
17685
18053
|
classes: array(string().min(1)).min(1),
|
|
17686
18054
|
deviceIds: array(number().int().nonnegative()).min(1),
|
|
17687
|
-
/** The track must have visited at least one of these zones. */
|
|
17688
18055
|
zones: array(string().min(1)).min(1).optional(),
|
|
17689
|
-
/** Best-so-far confidence the track must reach. */
|
|
17690
18056
|
minScore: number().min(0).max(1).optional()
|
|
17691
18057
|
}),
|
|
17692
18058
|
object({
|
|
17693
18059
|
kind: literal("stationary"),
|
|
17694
18060
|
deviceIds: array(number().int().nonnegative()).min(1),
|
|
17695
|
-
/** Class names; a macro class matches like the detection trigger. */
|
|
17696
18061
|
classes: array(string().min(1)).min(1).optional(),
|
|
17697
|
-
/** The parked object must be in at least one of these zones. */
|
|
17698
18062
|
zones: array(string().min(1)).min(1).optional(),
|
|
17699
|
-
/** `appeared`: it became parked. `departed`: the registry retired it.
|
|
17700
|
-
* The vocabulary of `PipelineAnalyticsStationaryChanged`. */
|
|
17701
18063
|
phase: _enum(["appeared", "departed"])
|
|
17702
18064
|
}),
|
|
17703
18065
|
object({
|
|
@@ -17705,6 +18067,143 @@ var AutomationTriggerSchema = discriminatedUnion("kind", [
|
|
|
17705
18067
|
minutes: number().int().min(1).max(1440)
|
|
17706
18068
|
})
|
|
17707
18069
|
]);
|
|
18070
|
+
var LegacyConditionLeafSchema = object({
|
|
18071
|
+
kind: literal("condition"),
|
|
18072
|
+
deviceId: number().int().nonnegative(),
|
|
18073
|
+
cap: string().min(1),
|
|
18074
|
+
fieldPath: string().min(1),
|
|
18075
|
+
operator: AutomationConditionOperatorSchema,
|
|
18076
|
+
value: union([
|
|
18077
|
+
string(),
|
|
18078
|
+
number(),
|
|
18079
|
+
boolean(),
|
|
18080
|
+
array(union([string(), number()])),
|
|
18081
|
+
QuantityValueSchema
|
|
18082
|
+
]),
|
|
18083
|
+
unit: string().min(1).optional()
|
|
18084
|
+
});
|
|
18085
|
+
var LegacyStationaryPresentSchema = object({
|
|
18086
|
+
kind: literal("stationary-present"),
|
|
18087
|
+
deviceId: number().int().nonnegative(),
|
|
18088
|
+
classes: array(string().min(1)).min(1).optional(),
|
|
18089
|
+
zones: array(string().min(1)).min(1).optional()
|
|
18090
|
+
});
|
|
18091
|
+
var LegacyExpressionSchema = object({
|
|
18092
|
+
kind: literal("expression"),
|
|
18093
|
+
expr: string().min(1).max(MAX_EXPRESSION_SOURCE_LENGTH),
|
|
18094
|
+
bindings: record(string().regex(EXPRESSION_IDENTIFIER_RE), ExpressionBindingSourceSchema)
|
|
18095
|
+
}).superRefine((src, ctx) => {
|
|
18096
|
+
const err = validateExpressionSource(src);
|
|
18097
|
+
if (err !== null) ctx.addIssue({
|
|
18098
|
+
code: "custom",
|
|
18099
|
+
message: err,
|
|
18100
|
+
path: ["expr"]
|
|
18101
|
+
});
|
|
18102
|
+
});
|
|
18103
|
+
var LegacyConditionSchema = lazy(() => discriminatedUnion("kind", [
|
|
18104
|
+
object({
|
|
18105
|
+
kind: literal("all"),
|
|
18106
|
+
children: array(LegacyConditionSchema)
|
|
18107
|
+
}),
|
|
18108
|
+
object({
|
|
18109
|
+
kind: literal("any"),
|
|
18110
|
+
children: array(LegacyConditionSchema)
|
|
18111
|
+
}),
|
|
18112
|
+
object({
|
|
18113
|
+
kind: literal("not"),
|
|
18114
|
+
child: LegacyConditionSchema
|
|
18115
|
+
}),
|
|
18116
|
+
LegacyConditionLeafSchema,
|
|
18117
|
+
LegacyExpressionSchema,
|
|
18118
|
+
LegacyStationaryPresentSchema
|
|
18119
|
+
]));
|
|
18120
|
+
function convertTrigger(trigger) {
|
|
18121
|
+
switch (trigger.kind) {
|
|
18122
|
+
case "device-state": return {
|
|
18123
|
+
...trigger,
|
|
18124
|
+
kind: "device-becomes"
|
|
18125
|
+
};
|
|
18126
|
+
case "detection": {
|
|
18127
|
+
const { classes, ...rest } = trigger;
|
|
18128
|
+
return {
|
|
18129
|
+
...rest,
|
|
18130
|
+
subjects: classes.map(subjectFromClassName)
|
|
18131
|
+
};
|
|
18132
|
+
}
|
|
18133
|
+
case "stationary": {
|
|
18134
|
+
const { classes, ...rest } = trigger;
|
|
18135
|
+
return {
|
|
18136
|
+
...rest,
|
|
18137
|
+
...classes === void 0 ? {} : { subjects: classes.map(subjectFromClassName) }
|
|
18138
|
+
};
|
|
18139
|
+
}
|
|
18140
|
+
default: return trigger;
|
|
18141
|
+
}
|
|
18142
|
+
}
|
|
18143
|
+
/** An old condition tree as a `when` subtree: `condition` → "is", classes → subjects. */
|
|
18144
|
+
function convertLegacyCondition(condition) {
|
|
18145
|
+
switch (condition.kind) {
|
|
18146
|
+
case "condition": return {
|
|
18147
|
+
...condition,
|
|
18148
|
+
kind: "device-is"
|
|
18149
|
+
};
|
|
18150
|
+
case "stationary-present": {
|
|
18151
|
+
const { classes, ...rest } = condition;
|
|
18152
|
+
return {
|
|
18153
|
+
...rest,
|
|
18154
|
+
...classes === void 0 ? {} : { subjects: classes.map(subjectFromClassName) }
|
|
18155
|
+
};
|
|
18156
|
+
}
|
|
18157
|
+
case "expression": return condition;
|
|
18158
|
+
case "not": return {
|
|
18159
|
+
kind: "not",
|
|
18160
|
+
child: convertLegacyCondition(condition.child)
|
|
18161
|
+
};
|
|
18162
|
+
case "all":
|
|
18163
|
+
case "any": return {
|
|
18164
|
+
kind: condition.kind,
|
|
18165
|
+
children: condition.children.map(convertLegacyCondition)
|
|
18166
|
+
};
|
|
18167
|
+
}
|
|
18168
|
+
}
|
|
18169
|
+
/** `all(any(t1…tn), C)`, or `any(t1…tn)`; a single trigger is not wrapped in `any`. */
|
|
18170
|
+
function convertLegacyWhen(half) {
|
|
18171
|
+
const leaves = half.triggers.map(convertTrigger);
|
|
18172
|
+
const first = leaves[0];
|
|
18173
|
+
const triggers = leaves.length === 1 && first !== void 0 ? first : {
|
|
18174
|
+
kind: "any",
|
|
18175
|
+
children: leaves
|
|
18176
|
+
};
|
|
18177
|
+
if (half.conditions === void 0) return triggers;
|
|
18178
|
+
return {
|
|
18179
|
+
kind: "all",
|
|
18180
|
+
children: [triggers, convertLegacyCondition(half.conditions)]
|
|
18181
|
+
};
|
|
18182
|
+
}
|
|
18183
|
+
/**
|
|
18184
|
+
* The automation RECIPE — what a visually-authored automation is, before it
|
|
18185
|
+
* becomes code.
|
|
18186
|
+
*
|
|
18187
|
+
* This is the data half of `docs/design/2026-08-08-automation-scripts-custom-devices.md`
|
|
18188
|
+
* Phase 6. A recipe is not an engine and never evaluates anything: it is a
|
|
18189
|
+
* declarative description that {@link generateAutomationBlock} compiles to the
|
|
18190
|
+
* TypeScript of an ordinary core block. There is therefore no second rule
|
|
18191
|
+
* engine, no second store and no second runtime — the block runner is the
|
|
18192
|
+
* runtime, `core_blocks` is the store (§2.1).
|
|
18193
|
+
*
|
|
18194
|
+
* Two parts:
|
|
18195
|
+
*
|
|
18196
|
+
* - **`when`** — ONE tree (`./when.ts`) of all/any/not over event leaves
|
|
18197
|
+
* (instants) and state leaves (durations). It replaces the flat trigger list
|
|
18198
|
+
* plus the separate condition tree; the firing rule is in that file and in
|
|
18199
|
+
* ADR "one tree".
|
|
18200
|
+
* - **Actions** — `NcRuleActionSchema`'s two steps, plus the `{kind:'code'}`
|
|
18201
|
+
* fragment of §3.2.2. See {@link AutomationActionSchema} for the ONE place
|
|
18202
|
+
* this had to diverge from "verbatim", and why.
|
|
18203
|
+
*
|
|
18204
|
+
* A recipe stored in the old shape (`triggers` + `conditions`) still LOADS:
|
|
18205
|
+
* {@link AutomationRecipeSchema} (the parse-anywhere schema) converts it on parse. Nothing writes it.
|
|
18206
|
+
*/
|
|
17708
18207
|
/**
|
|
17709
18208
|
* One action step.
|
|
17710
18209
|
*
|
|
@@ -17807,91 +18306,49 @@ var AutomationRunModeSchema = discriminatedUnion("mode", [
|
|
|
17807
18306
|
minutes: number().int().min(1).max(1440)
|
|
17808
18307
|
})
|
|
17809
18308
|
]);
|
|
17810
|
-
var
|
|
17811
|
-
|
|
17812
|
-
conditions: AutomationConditionSchema.optional(),
|
|
18309
|
+
var CurrentAutomationRecipeSchema = object({
|
|
18310
|
+
when: AutomationWhenSchema,
|
|
17813
18311
|
actions: array(AutomationActionSchema),
|
|
17814
18312
|
runMode: AutomationRunModeSchema.optional(),
|
|
17815
18313
|
/** How many run traces the automation keeps (default {@link DEFAULT_TRACE_KEEP}). */
|
|
17816
18314
|
keepTraces: number().int().min(1).max(100).optional()
|
|
17817
18315
|
});
|
|
18316
|
+
/** A recipe as it was stored before the single tree. Read-only: nothing writes this. */
|
|
18317
|
+
var LegacyAutomationRecipeSchema = object({
|
|
18318
|
+
triggers: array(LegacyTriggerSchema),
|
|
18319
|
+
conditions: LegacyConditionSchema.optional(),
|
|
18320
|
+
actions: array(AutomationActionSchema),
|
|
18321
|
+
runMode: AutomationRunModeSchema.optional(),
|
|
18322
|
+
keepTraces: number().int().min(1).max(100).optional()
|
|
18323
|
+
});
|
|
18324
|
+
/** The old shape as the new one, lossless. */
|
|
18325
|
+
function convertLegacyRecipe(legacy) {
|
|
18326
|
+
const { triggers, conditions, ...rest } = legacy;
|
|
18327
|
+
return {
|
|
18328
|
+
when: convertLegacyWhen({
|
|
18329
|
+
triggers,
|
|
18330
|
+
conditions
|
|
18331
|
+
}),
|
|
18332
|
+
...rest
|
|
18333
|
+
};
|
|
18334
|
+
}
|
|
17818
18335
|
/**
|
|
17819
|
-
*
|
|
17820
|
-
*
|
|
17821
|
-
*
|
|
17822
|
-
* `preserveOriginal: false` below is the whole reason this set exists: the
|
|
17823
|
-
* executor maps each raw COCO label onto its macro and DROPS everything else,
|
|
17824
|
-
* so a tracked detection's `className` is always one of {@link MACRO_LABELS}.
|
|
17825
|
-
* Any surface that indexes counts by class name — the ZoneAnalytics occupancy
|
|
17826
|
-
* snapshot's `byClass`, and therefore every occupancy rule — can match nothing
|
|
17827
|
-
* else. Derived from the catalog, never hand-listed, so a new macro joins it by
|
|
17828
|
-
* being declared once.
|
|
17829
|
-
*
|
|
17830
|
-
* Cost of not having it, 2026-08-12: the notification rule editor offered the
|
|
17831
|
-
* full taxonomy for an occupancy class (occupancy is the one condition that
|
|
17832
|
-
* does not go through the engine's macro-expanding `expandClassSelector`), two
|
|
17833
|
-
* live rules were authored on `car`, and both counters read 0 forever.
|
|
18336
|
+
* Where recipes are PARSED (the core-blocks cap, the MCP tool, the literal a
|
|
18337
|
+
* saved block carries): the new shape as it is, or the old shape converted to
|
|
18338
|
+
* it. The output type is always the new one.
|
|
17834
18339
|
*/
|
|
17835
|
-
var
|
|
17836
|
-
{
|
|
17837
|
-
id: "person",
|
|
17838
|
-
name: "Person"
|
|
17839
|
-
},
|
|
17840
|
-
{
|
|
17841
|
-
id: "vehicle",
|
|
17842
|
-
name: "Vehicle"
|
|
17843
|
-
},
|
|
17844
|
-
{
|
|
17845
|
-
id: "animal",
|
|
17846
|
-
name: "Animal"
|
|
17847
|
-
},
|
|
17848
|
-
{
|
|
17849
|
-
id: "package",
|
|
17850
|
-
name: "Package"
|
|
17851
|
-
}
|
|
17852
|
-
].map((l) => l.id));
|
|
17853
|
-
/** True when `className` is a macro the detector can actually emit (and hence a
|
|
17854
|
-
* class a count can be keyed on) — see {@link DETECTION_MACRO_CLASSES}. */
|
|
17855
|
-
function isDetectionMacroClass(className) {
|
|
17856
|
-
return DETECTION_MACRO_CLASSES.has(className.trim().toLowerCase());
|
|
17857
|
-
}
|
|
17858
|
-
var COCO_TO_MACRO = {
|
|
17859
|
-
mapping: {
|
|
17860
|
-
person: "person",
|
|
17861
|
-
bicycle: "vehicle",
|
|
17862
|
-
car: "vehicle",
|
|
17863
|
-
motorcycle: "vehicle",
|
|
17864
|
-
airplane: "vehicle",
|
|
17865
|
-
bus: "vehicle",
|
|
17866
|
-
train: "vehicle",
|
|
17867
|
-
truck: "vehicle",
|
|
17868
|
-
boat: "vehicle",
|
|
17869
|
-
bird: "animal",
|
|
17870
|
-
cat: "animal",
|
|
17871
|
-
dog: "animal",
|
|
17872
|
-
horse: "animal",
|
|
17873
|
-
sheep: "animal",
|
|
17874
|
-
cow: "animal",
|
|
17875
|
-
elephant: "animal",
|
|
17876
|
-
bear: "animal",
|
|
17877
|
-
zebra: "animal",
|
|
17878
|
-
giraffe: "animal",
|
|
17879
|
-
suitcase: "package",
|
|
17880
|
-
backpack: "package",
|
|
17881
|
-
handbag: "package"
|
|
17882
|
-
},
|
|
17883
|
-
preserveOriginal: false
|
|
17884
|
-
};
|
|
18340
|
+
var AutomationRecipeSchema = union([CurrentAutomationRecipeSchema, LegacyAutomationRecipeSchema.transform(convertLegacyRecipe)]);
|
|
17885
18341
|
new Set(Object.values(COCO_TO_MACRO.mapping));
|
|
17886
18342
|
/**
|
|
17887
18343
|
* Run traces — what an automation (or, later, an Action run) DID, node by node,
|
|
17888
18344
|
* so the editor can paint every block green or red with its reason.
|
|
17889
18345
|
*
|
|
17890
|
-
* A trace is data, not a log: it covers the WHOLE tree — the
|
|
17891
|
-
* every
|
|
17892
|
-
* short-circuit never reached), the run-mode verdict and every action
|
|
17893
|
-
* each addressed by a stable path (`
|
|
17894
|
-
* for an Action run).
|
|
18346
|
+
* A trace is data, not a log: it covers the WHOLE tree — the event leaf that
|
|
18347
|
+
* fired, every node of the `when` tree (containers and leaves, including the
|
|
18348
|
+
* ones a short-circuit never reached), the run-mode verdict and every action
|
|
18349
|
+
* step — each addressed by a stable path (`when.0.1`, `actions.2`, or `steps.N`
|
|
18350
|
+
* for an Action run). Traces written before the single tree carry
|
|
18351
|
+
* `conditions.*` paths and still parse. Skipped
|
|
17895
18352
|
* evaluations are traced too, and identical consecutive skips collapse into a
|
|
17896
18353
|
* repeat count so a trigger that fails every 5 minutes cannot flush real runs.
|
|
17897
18354
|
*
|
|
@@ -17923,6 +18380,8 @@ var TraceNodeOutcomeSchema = _enum([
|
|
|
17923
18380
|
]);
|
|
17924
18381
|
var AutomationTriggerTraceSchema = object({
|
|
17925
18382
|
kind: string().min(1),
|
|
18383
|
+
/** The event leaf that fired (`when`, `when.0.1`); absent on traces written before the single tree. */
|
|
18384
|
+
path: string().min(1).optional(),
|
|
17926
18385
|
outcome: _enum(["pass", "fail"]),
|
|
17927
18386
|
/** Why an event was rejected ("class person not in [dog]") or what fired. */
|
|
17928
18387
|
reason: string(),
|
|
@@ -17930,15 +18389,23 @@ var AutomationTriggerTraceSchema = object({
|
|
|
17930
18389
|
vars: record(string(), TraceValueSchema)
|
|
17931
18390
|
});
|
|
17932
18391
|
var AutomationConditionTraceNodeSchema = object({
|
|
17933
|
-
/** `
|
|
18392
|
+
/** `when` for the root, `when.<i>` for its i-th child, … (`conditions…` on an old trace). */
|
|
17934
18393
|
path: string().min(1),
|
|
17935
18394
|
kind: _enum([
|
|
17936
18395
|
"all",
|
|
17937
18396
|
"any",
|
|
17938
18397
|
"not",
|
|
17939
18398
|
"condition",
|
|
18399
|
+
"device-is",
|
|
17940
18400
|
"expression",
|
|
17941
|
-
"stationary-present"
|
|
18401
|
+
"stationary-present",
|
|
18402
|
+
"device-becomes",
|
|
18403
|
+
"device-event",
|
|
18404
|
+
"schedule",
|
|
18405
|
+
"interval",
|
|
18406
|
+
"manual",
|
|
18407
|
+
"detection",
|
|
18408
|
+
"stationary"
|
|
17942
18409
|
]),
|
|
17943
18410
|
outcome: TraceNodeOutcomeSchema,
|
|
17944
18411
|
reason: string(),
|
|
@@ -17972,6 +18439,12 @@ var AutomationStepTraceSchema = object({
|
|
|
17972
18439
|
deviceId: number().int().optional(),
|
|
17973
18440
|
startedAt: number().optional(),
|
|
17974
18441
|
endedAt: number().optional(),
|
|
18442
|
+
/**
|
|
18443
|
+
* The parameters the step SENT, after `{{vars.x}}` substitution — what the
|
|
18444
|
+
* device was actually asked. Bounded like trigger `vars`; a secret parameter
|
|
18445
|
+
* is shown as {@link REDACTED_ARG}. Absent on traces written before it existed.
|
|
18446
|
+
*/
|
|
18447
|
+
args: record(string(), TraceValueSchema).optional(),
|
|
17975
18448
|
outcome: _enum([
|
|
17976
18449
|
"ok",
|
|
17977
18450
|
"error",
|
|
@@ -18721,6 +19194,23 @@ method(object({
|
|
|
18721
19194
|
addonId: string(),
|
|
18722
19195
|
nodeId: string().optional()
|
|
18723
19196
|
}), SettingsSchemaWithValuesSchema.nullable()), method(object({
|
|
19197
|
+
addonId: string(),
|
|
19198
|
+
nodeId: string().optional()
|
|
19199
|
+
}), object({ keys: array(string()) }).nullable(), { auth: "admin" }), method(object({
|
|
19200
|
+
addonId: string(),
|
|
19201
|
+
nodeId: string().optional(),
|
|
19202
|
+
keys: array(string())
|
|
19203
|
+
}), object({
|
|
19204
|
+
removed: array(string()),
|
|
19205
|
+
refused: array(object({
|
|
19206
|
+
key: string(),
|
|
19207
|
+
reason: string()
|
|
19208
|
+
})),
|
|
19209
|
+
secretsCleared: number()
|
|
19210
|
+
}), {
|
|
19211
|
+
kind: "mutation",
|
|
19212
|
+
auth: "admin"
|
|
19213
|
+
}), method(object({
|
|
18724
19214
|
addonId: string(),
|
|
18725
19215
|
deviceId: number(),
|
|
18726
19216
|
nodeId: string().optional()
|
|
@@ -20175,8 +20665,21 @@ var BrokerProviderInfoSchema = object({
|
|
|
20175
20665
|
* (`{ sessionId }`) drops the session. The dialog that edits a broker
|
|
20176
20666
|
* offers it as the default path; the fields the session fills are
|
|
20177
20667
|
* marked `filledBySignIn` in the kind's settings schema.
|
|
20668
|
+
*
|
|
20669
|
+
* `methods` lists the ways the session can sign in, recommended first:
|
|
20670
|
+
* `'device-code'` adds `POST {basePath}/code/start` (body: the form's
|
|
20671
|
+
* settings) answering `{ sessionId, userCode, verificationUrl,
|
|
20672
|
+
* expiresAt }` — the operator types `userCode` at `verificationUrl` on
|
|
20673
|
+
* any device, and the same `status` / `commit` / `cancel` routes follow
|
|
20674
|
+
* (status then carries `method`, `userCode`, `verificationUrl`,
|
|
20675
|
+
* `expiresAt` and the phases `'awaiting-code'` / `'expired'`);
|
|
20676
|
+
* `'proxy'` is the `{basePath}/start` flow above. Absent means
|
|
20677
|
+
* `['proxy']`.
|
|
20178
20678
|
*/
|
|
20179
|
-
signIn: object({
|
|
20679
|
+
signIn: object({
|
|
20680
|
+
basePath: string().min(1),
|
|
20681
|
+
methods: array(_enum(["device-code", "proxy"])).optional()
|
|
20682
|
+
}).optional()
|
|
20180
20683
|
}))
|
|
20181
20684
|
});
|
|
20182
20685
|
var ListInputSchema = object({
|
|
@@ -22767,6 +23270,8 @@ var StorageKindSchema = object({
|
|
|
22767
23270
|
"orphaned",
|
|
22768
23271
|
"dropped"
|
|
22769
23272
|
]),
|
|
23273
|
+
/** An owner declared this kind since the engine started. */
|
|
23274
|
+
declaredThisBoot: boolean(),
|
|
22770
23275
|
/** `null` when the caller asked for no counts (`counts: false`). */
|
|
22771
23276
|
rows: number().int().nonnegative().nullable(),
|
|
22772
23277
|
/** Rows x the average size of a sample; null for an empty kind. */
|
|
@@ -22778,6 +23283,51 @@ var StorageKindSchema = object({
|
|
|
22778
23283
|
/** The whole declaration, secret paths and entry descriptor included (the entries service builds its handle from it). */
|
|
22779
23284
|
declaration: RecordKindDeclarationSchema
|
|
22780
23285
|
});
|
|
23286
|
+
_enum([
|
|
23287
|
+
"orphaned",
|
|
23288
|
+
"stale",
|
|
23289
|
+
"unknown"
|
|
23290
|
+
]);
|
|
23291
|
+
/** A record kind nobody declared since its owner started, or whose owner is gone. */
|
|
23292
|
+
var StaleKindFindingSchema = object({
|
|
23293
|
+
owner: string(),
|
|
23294
|
+
kind: string(),
|
|
23295
|
+
/** `unknown`: the owner could not be judged (not running, or its state unreadable) - never dropped. */
|
|
23296
|
+
verdict: _enum(["orphaned", "unknown"]),
|
|
23297
|
+
reason: string(),
|
|
23298
|
+
rows: number().int().nonnegative().nullable(),
|
|
23299
|
+
/** local-auth's tables are never dropped by this audit. */
|
|
23300
|
+
protected: boolean()
|
|
23301
|
+
});
|
|
23302
|
+
/** A stored global-settings key the running addon no longer declares. */
|
|
23303
|
+
var StaleSettingsKeyFindingSchema = object({
|
|
23304
|
+
addonId: string(),
|
|
23305
|
+
/** The stored key as written, a per-node `<key>@<nodeId>` suffix included. */
|
|
23306
|
+
key: string(),
|
|
23307
|
+
/**
|
|
23308
|
+
* Keychain refs whose ONLY marker sits under this key: in use by stale data,
|
|
23309
|
+
* not orphans yet. Removing the key releases them.
|
|
23310
|
+
*/
|
|
23311
|
+
secretRefs: array(string())
|
|
23312
|
+
});
|
|
23313
|
+
/** An addon the audit could not judge, with the reason. Never reported as stale. */
|
|
23314
|
+
var StaleUnknownSchema = object({
|
|
23315
|
+
subject: string(),
|
|
23316
|
+
reason: string()
|
|
23317
|
+
});
|
|
23318
|
+
var StaleDataReportSchema = object({
|
|
23319
|
+
/** Epoch ms of the last finished scan; `null` before the first. */
|
|
23320
|
+
scannedAt: number().nullable(),
|
|
23321
|
+
scanning: boolean(),
|
|
23322
|
+
trigger: _enum([
|
|
23323
|
+
"boot",
|
|
23324
|
+
"interval",
|
|
23325
|
+
"manual"
|
|
23326
|
+
]).nullable(),
|
|
23327
|
+
kinds: array(StaleKindFindingSchema),
|
|
23328
|
+
settingsKeys: array(StaleSettingsKeyFindingSchema),
|
|
23329
|
+
unknown: array(StaleUnknownSchema)
|
|
23330
|
+
});
|
|
22781
23331
|
method(object({ ownerPrefix: string().min(1).optional() }), object({ tables: array(StorageTableSchema) }), { auth: "admin" }), method(object({
|
|
22782
23332
|
owner: string().min(1).optional(),
|
|
22783
23333
|
/** `false` skips the per-kind row count (a catalog read only). Default true. */
|
|
@@ -22785,7 +23335,30 @@ method(object({ ownerPrefix: string().min(1).optional() }), object({ tables: arr
|
|
|
22785
23335
|
}), object({ kinds: array(StorageKindSchema) }), { auth: "admin" }), method(RecordQueryInputSchema.extend({
|
|
22786
23336
|
owner: string().min(1),
|
|
22787
23337
|
kind: RecordKindNameSchema
|
|
22788
|
-
}), RecordQueryResultSchema, { auth: "admin" })
|
|
23338
|
+
}), RecordQueryResultSchema, { auth: "admin" }), method(object({}), StaleDataReportSchema, { auth: "admin" }), method(object({}), StaleDataReportSchema, {
|
|
23339
|
+
kind: "mutation",
|
|
23340
|
+
auth: "admin"
|
|
23341
|
+
}), method(object({
|
|
23342
|
+
owner: string().min(1),
|
|
23343
|
+
kind: RecordKindNameSchema
|
|
23344
|
+
}), object({
|
|
23345
|
+
deleted: number().int().nonnegative(),
|
|
23346
|
+
secretsReleased: number().int().nonnegative()
|
|
23347
|
+
}), {
|
|
23348
|
+
kind: "mutation",
|
|
23349
|
+
auth: "admin",
|
|
23350
|
+
caller: "required"
|
|
23351
|
+
}), method(object({
|
|
23352
|
+
addonId: string().min(1),
|
|
23353
|
+
key: string().min(1)
|
|
23354
|
+
}), object({
|
|
23355
|
+
removed: boolean(),
|
|
23356
|
+
secretsCleared: number().int().nonnegative()
|
|
23357
|
+
}), {
|
|
23358
|
+
kind: "mutation",
|
|
23359
|
+
auth: "admin",
|
|
23360
|
+
caller: "required"
|
|
23361
|
+
});
|
|
22789
23362
|
/**
|
|
22790
23363
|
* record-entries - the ONE admin surface for every list of user-created entries
|
|
22791
23364
|
* (D881): notification targets, brokers, LLM profiles, anything an addon
|
|
@@ -22924,6 +23497,12 @@ method(object({
|
|
|
22924
23497
|
}), method(object({ deviceId: number().int() }), object({ refs: array(string()).readonly() }), {
|
|
22925
23498
|
kind: "mutation",
|
|
22926
23499
|
auth: "admin"
|
|
23500
|
+
}), method(object({
|
|
23501
|
+
refs: RefListSchema,
|
|
23502
|
+
onBehalfOf: string().min(1)
|
|
23503
|
+
}), object({ released: number().int() }), {
|
|
23504
|
+
kind: "mutation",
|
|
23505
|
+
auth: "admin"
|
|
22927
23506
|
}), method(object({}), array(KeychainSecretMetaSchema).readonly(), { auth: "admin" }), method(object({}), KeychainStateSchema, { auth: "admin" });
|
|
22928
23507
|
/**
|
|
22929
23508
|
* device-history — the ONE mechanism for numeric history (D850).
|
|
@@ -23713,7 +24292,9 @@ var DiscoveredChildDeviceSchema = lazy(() => object({
|
|
|
23713
24292
|
/** Upstream-system identity + rendering hints for the candidate. */
|
|
23714
24293
|
sourceInfo: SourceInfoSchema.optional(),
|
|
23715
24294
|
/** Nested entity-children for accordion preview — integrations populate, Hubs omit. */
|
|
23716
|
-
children: array(DiscoveredChildDeviceSchema).readonly().optional()
|
|
24295
|
+
children: array(DiscoveredChildDeviceSchema).readonly().optional(),
|
|
24296
|
+
/** `childNativeId` of the gateway candidate in the same list this device sits behind. */
|
|
24297
|
+
parentStableId: string().optional()
|
|
23717
24298
|
}));
|
|
23718
24299
|
/**
|
|
23719
24300
|
* Status block — populated by the integration after each
|
|
@@ -44079,6 +44660,79 @@ object({
|
|
|
44079
44660
|
metadata: record(string(), unknown()).optional()
|
|
44080
44661
|
});
|
|
44081
44662
|
/**
|
|
44663
|
+
* HOW a provider can be found on the network. The provider only DECLARES the
|
|
44664
|
+
* mode; the `local-network` scan engine runs it once for every provider that
|
|
44665
|
+
* asked (one multicast browse, one host sweep) and hands the raw hits back to
|
|
44666
|
+
* `classifyDiscoveryHits`. A provider never opens a discovery socket itself,
|
|
44667
|
+
* except through a `custom` mode.
|
|
44668
|
+
*/
|
|
44669
|
+
var DiscoveryModeSchema = discriminatedUnion("kind", [
|
|
44670
|
+
object({
|
|
44671
|
+
kind: literal("mdns"),
|
|
44672
|
+
/** DNS-SD service type, e.g. `_esphomelib._tcp`. */
|
|
44673
|
+
serviceType: string().min(1),
|
|
44674
|
+
/** Regular expression an instance name must match (case-insensitive). */
|
|
44675
|
+
instancePattern: string().optional()
|
|
44676
|
+
}),
|
|
44677
|
+
object({
|
|
44678
|
+
kind: literal("ws-discovery"),
|
|
44679
|
+
/** Probe types (e.g. `dn:NetworkVideoTransmitter`); omitted = any device. */
|
|
44680
|
+
types: array(string()).optional()
|
|
44681
|
+
}),
|
|
44682
|
+
object({
|
|
44683
|
+
kind: literal("ssdp"),
|
|
44684
|
+
searchTarget: string().min(1)
|
|
44685
|
+
}),
|
|
44686
|
+
object({
|
|
44687
|
+
kind: literal("udp-broadcast"),
|
|
44688
|
+
port: number().int().min(1).max(65535),
|
|
44689
|
+
payloadHex: string().regex(/^([0-9a-fA-F]{2})*$/),
|
|
44690
|
+
/** Port replies arrive on, when the device answers somewhere other than the source port. */
|
|
44691
|
+
listenPort: number().int().min(1).max(65535).optional()
|
|
44692
|
+
}),
|
|
44693
|
+
object({
|
|
44694
|
+
kind: literal("http-probe"),
|
|
44695
|
+
port: number().int().min(1).max(65535),
|
|
44696
|
+
path: string().startsWith("/"),
|
|
44697
|
+
method: _enum(["GET", "POST"]).default("GET"),
|
|
44698
|
+
bodyText: string().optional(),
|
|
44699
|
+
contentType: string().optional(),
|
|
44700
|
+
tls: boolean().default(false),
|
|
44701
|
+
/** Status codes that count as a hit. Omitted = any HTTP answer. */
|
|
44702
|
+
acceptStatus: array(number().int()).optional()
|
|
44703
|
+
}),
|
|
44704
|
+
object({
|
|
44705
|
+
kind: literal("custom"),
|
|
44706
|
+
/** Why the engine cannot do it (an allowlisted exception, e.g. a vendor UDP protocol). */
|
|
44707
|
+
reason: string().min(1)
|
|
44708
|
+
})
|
|
44709
|
+
]);
|
|
44710
|
+
/** What the engine saw on the wire for ONE declared mode; the provider classifies it. */
|
|
44711
|
+
var DiscoveryHitSchema = object({
|
|
44712
|
+
/** Index into the provider's own `getDiscoveryModes()` array. */
|
|
44713
|
+
modeIndex: number().int().min(0),
|
|
44714
|
+
host: string(),
|
|
44715
|
+
port: number().int(),
|
|
44716
|
+
http: object({
|
|
44717
|
+
status: number().int(),
|
|
44718
|
+
headers: record(string(), string()),
|
|
44719
|
+
/** At most 16 KiB. */
|
|
44720
|
+
bodyText: string()
|
|
44721
|
+
}).optional(),
|
|
44722
|
+
mdns: object({
|
|
44723
|
+
instance: string(),
|
|
44724
|
+
host: string(),
|
|
44725
|
+
port: number().int(),
|
|
44726
|
+
txt: record(string(), string())
|
|
44727
|
+
}).optional(),
|
|
44728
|
+
udp: object({ payloadHex: string() }).optional(),
|
|
44729
|
+
wsd: object({
|
|
44730
|
+
xaddrs: array(string()),
|
|
44731
|
+
types: array(string()),
|
|
44732
|
+
scopes: array(string())
|
|
44733
|
+
}).optional()
|
|
44734
|
+
});
|
|
44735
|
+
/**
|
|
44082
44736
|
* Candidate handed back from discovery and accepted by
|
|
44083
44737
|
* `adoptDiscoveredDevice`. Shape mirrors the in-process
|
|
44084
44738
|
* `DiscoveredDevice` interface used by `DeviceDiscovery`.
|
|
@@ -44113,7 +44767,17 @@ var DiscoveryCandidateSchema = object({
|
|
|
44113
44767
|
/** Numeric id of the device this candidate was matched to. Set with `alreadyOnboarded`. */
|
|
44114
44768
|
onboardedDeviceId: number().optional(),
|
|
44115
44769
|
/** Operator-facing name of the matched device, so the UI can say WHICH one it is. */
|
|
44116
|
-
onboardedName: string().optional()
|
|
44770
|
+
onboardedName: string().optional(),
|
|
44771
|
+
/**
|
|
44772
|
+
* This candidate is an INTEGRATION to set up (a gateway, a hub, a controller),
|
|
44773
|
+
* not a device to adopt. Replaces the `prefilledConfig.setupIntegration` marker,
|
|
44774
|
+
* which is still read for one release.
|
|
44775
|
+
*/
|
|
44776
|
+
setupIntegration: boolean().optional(),
|
|
44777
|
+
/** `stableId` of the gateway candidate this device was found BEHIND. */
|
|
44778
|
+
parentStableId: string().optional(),
|
|
44779
|
+
/** `false` = shown for context but not pickable. Default true. */
|
|
44780
|
+
selectable: boolean().optional()
|
|
44117
44781
|
});
|
|
44118
44782
|
/**
|
|
44119
44783
|
* Flat device summary returned by `createDevice` / `adoptDiscoveredDevice`.
|
|
@@ -44166,6 +44830,12 @@ method(_void(), _void(), { kind: "mutation" }), method(_void(), _void(), { kind:
|
|
|
44166
44830
|
}), method(object({}), boolean()), method(object({ params: record(string(), unknown()).optional() }), array(DiscoveryCandidateSchema), {
|
|
44167
44831
|
kind: "mutation",
|
|
44168
44832
|
auth: "admin"
|
|
44833
|
+
}), method(object({}), array(DiscoveryModeSchema)), method(object({
|
|
44834
|
+
hits: array(DiscoveryHitSchema),
|
|
44835
|
+
params: record(string(), unknown()).optional()
|
|
44836
|
+
}), array(DiscoveryCandidateSchema), {
|
|
44837
|
+
kind: "mutation",
|
|
44838
|
+
auth: "admin"
|
|
44169
44839
|
}), method(object({}), CreationSchemaOutputSchema), method(object({}), object({ deviceType: _enum(DeviceType).nullable() })), method(object({ candidate: DiscoveryCandidateSchema }), DeviceSummarySchema, {
|
|
44170
44840
|
kind: "mutation",
|
|
44171
44841
|
auth: "admin"
|
|
@@ -44897,17 +45567,23 @@ method(object({
|
|
|
44897
45567
|
}), method(object({}), object({ providers: array(object({
|
|
44898
45568
|
addonId: string(),
|
|
44899
45569
|
label: string()
|
|
44900
|
-
})).readonly() }), { auth: "admin" }), method(
|
|
44901
|
-
|
|
44902
|
-
|
|
44903
|
-
|
|
44904
|
-
|
|
44905
|
-
|
|
44906
|
-
|
|
44907
|
-
|
|
44908
|
-
}),
|
|
45570
|
+
})).readonly() }), { auth: "admin" }), method(
|
|
45571
|
+
/** `subnets`: extra CIDRs for THIS scan, on top of the hub's own and the saved list. */
|
|
45572
|
+
object({ subnets: array(string()).optional() }),
|
|
45573
|
+
object({ groups: array(object({
|
|
45574
|
+
addonId: string(),
|
|
45575
|
+
label: string(),
|
|
45576
|
+
candidates: array(DiscoveryCandidateSchema).readonly(),
|
|
45577
|
+
error: string().nullable()
|
|
45578
|
+
})).readonly() }),
|
|
45579
|
+
{
|
|
45580
|
+
kind: "mutation",
|
|
45581
|
+
auth: "admin"
|
|
45582
|
+
}
|
|
45583
|
+
), method(object({
|
|
44909
45584
|
addonId: string(),
|
|
44910
|
-
params: record(string(), unknown()).optional()
|
|
45585
|
+
params: record(string(), unknown()).optional(),
|
|
45586
|
+
subnets: array(string()).optional()
|
|
44911
45587
|
}), object({ candidates: array(DiscoveryCandidateSchema).readonly() }), {
|
|
44912
45588
|
kind: "mutation",
|
|
44913
45589
|
auth: "admin"
|
|
@@ -59615,6 +60291,12 @@ var TerminalInstanceInfoSchema = object({
|
|
|
59615
60291
|
instanceId: string(),
|
|
59616
60292
|
cameraStableId: string(),
|
|
59617
60293
|
nodeId: string(),
|
|
60294
|
+
/**
|
|
60295
|
+
* False while the node the instance is bound to is not in the cluster
|
|
60296
|
+
* topology (forgotten, renamed, re-paired). The instance is kept; the
|
|
60297
|
+
* operator re-points it with `updateInstance({ targetNodeId })`.
|
|
60298
|
+
*/
|
|
60299
|
+
nodeInCluster: boolean(),
|
|
59618
60300
|
profileId: string(),
|
|
59619
60301
|
profileLabel: string(),
|
|
59620
60302
|
name: string(),
|
|
@@ -59664,6 +60346,8 @@ method(_void(), array(TerminalProfileInfoSchema).readonly(), { auth: "admin" }),
|
|
|
59664
60346
|
auth: "admin"
|
|
59665
60347
|
}), method(object({
|
|
59666
60348
|
instanceId: string().min(1),
|
|
60349
|
+
/** Re-point the instance to another node; the profile must exist there. */
|
|
60350
|
+
targetNodeId: string().min(1).max(256).optional(),
|
|
59667
60351
|
name: string().trim().min(1).max(160).optional(),
|
|
59668
60352
|
executable: string().max(1024).optional(),
|
|
59669
60353
|
args: array(string().max(2048)).max(64).optional(),
|
|
@@ -66399,7 +67083,9 @@ method(_void(), array(IntegrationWithStateSchema)), method(object({ id: string()
|
|
|
66399
67083
|
id: string(),
|
|
66400
67084
|
settings: record(string(), unknown()),
|
|
66401
67085
|
/** Keys the form's schema declares secret (by type) — keychain-stored (D787). */
|
|
66402
|
-
secretKeys: array(string()).optional()
|
|
67086
|
+
secretKeys: array(string()).optional(),
|
|
67087
|
+
/** The integration's own addon applies the change in-process and asks the hub not to respawn it. */
|
|
67088
|
+
skipRestart: boolean().optional()
|
|
66403
67089
|
}), object({ success: boolean() }), {
|
|
66404
67090
|
kind: "mutation",
|
|
66405
67091
|
auth: "admin"
|
|
@@ -67027,6 +67713,39 @@ var TlsStatusSchema = object({
|
|
|
67027
67713
|
hasCa: boolean()
|
|
67028
67714
|
}).nullable()
|
|
67029
67715
|
});
|
|
67716
|
+
/** One provider's ask of the scan engine: the modes it declared. */
|
|
67717
|
+
var ScanRequestSchema = object({
|
|
67718
|
+
providerId: string().min(1),
|
|
67719
|
+
modes: array(DiscoveryModeSchema)
|
|
67720
|
+
});
|
|
67721
|
+
var ScanErrorSchema = object({
|
|
67722
|
+
/** Absent for a failure that is the scan's own (a bad subnet, a socket that would not open). */
|
|
67723
|
+
providerId: string().optional(),
|
|
67724
|
+
/** The mode family that failed (`mdns`, `http-probe`, …). */
|
|
67725
|
+
mode: string().optional(),
|
|
67726
|
+
message: string()
|
|
67727
|
+
});
|
|
67728
|
+
/** What one scan did, per mode family; the engine logs the same numbers once. */
|
|
67729
|
+
var ScanStatsSchema = object({
|
|
67730
|
+
hostsProbed: number().int(),
|
|
67731
|
+
hits: number().int(),
|
|
67732
|
+
timeouts: number().int(),
|
|
67733
|
+
byMode: record(string(), object({
|
|
67734
|
+
probed: number().int(),
|
|
67735
|
+
hits: number().int(),
|
|
67736
|
+
timeouts: number().int()
|
|
67737
|
+
}))
|
|
67738
|
+
});
|
|
67739
|
+
var ScanNetworkResultSchema = object({
|
|
67740
|
+
hits: array(object({
|
|
67741
|
+
providerId: string(),
|
|
67742
|
+
hit: DiscoveryHitSchema
|
|
67743
|
+
})),
|
|
67744
|
+
/** CIDRs actually covered: the hub's own /24s, the saved list and the per-call list. */
|
|
67745
|
+
subnetsScanned: array(string()),
|
|
67746
|
+
errors: array(ScanErrorSchema),
|
|
67747
|
+
stats: ScanStatsSchema
|
|
67748
|
+
});
|
|
67030
67749
|
method(_void(), ListResultSchema), method(_void(), PreferredSchema), method(object({
|
|
67031
67750
|
/**
|
|
67032
67751
|
* LEGACY HINT — do not send from new code. Kept optional so clients
|
|
@@ -67081,6 +67800,16 @@ method(_void(), ListResultSchema), method(_void(), PreferredSchema), method(obje
|
|
|
67081
67800
|
}), method(_void(), object({ pem: string() })), method(_void(), TlsStatusSchema, {
|
|
67082
67801
|
kind: "mutation",
|
|
67083
67802
|
auth: "admin"
|
|
67803
|
+
}), method(object({
|
|
67804
|
+
requests: array(ScanRequestSchema),
|
|
67805
|
+
subnets: array(string()).optional()
|
|
67806
|
+
}), ScanNetworkResultSchema, {
|
|
67807
|
+
kind: "mutation",
|
|
67808
|
+
auth: "admin",
|
|
67809
|
+
timeoutMs: 9e4
|
|
67810
|
+
}), method(_void(), object({ subnets: array(string()) }), { auth: "admin" }), method(object({ subnets: array(string()) }), object({ subnets: array(string()) }), {
|
|
67811
|
+
kind: "mutation",
|
|
67812
|
+
auth: "admin"
|
|
67084
67813
|
}), method(_void(), TlsStatusSchema, {
|
|
67085
67814
|
kind: "mutation",
|
|
67086
67815
|
auth: "admin"
|
|
@@ -70881,7 +71610,7 @@ var runningStateCapability = {
|
|
|
70881
71610
|
volatileStateFields: ["lastFetchedAt"],
|
|
70882
71611
|
customize: runningCustomize
|
|
70883
71612
|
};
|
|
70884
|
-
DeviceType.Camera, DeviceType.Sensor, DeviceType.Switch, method(object({ deviceId: number().int().nonnegative() }), object({ success: literal(true) }), {
|
|
71613
|
+
DeviceType.Camera, DeviceType.Sensor, DeviceType.Switch, DeviceType.Gateway, method(object({ deviceId: number().int().nonnegative() }), object({ success: literal(true) }), {
|
|
70885
71614
|
kind: "mutation",
|
|
70886
71615
|
auth: "admin"
|
|
70887
71616
|
});
|
|
@@ -75574,52 +76303,89 @@ btn("power", 0, 0, {
|
|
|
75574
76303
|
role: "power",
|
|
75575
76304
|
shape: "round",
|
|
75576
76305
|
tone: "danger"
|
|
75577
|
-
}), btn("up", 0, 1, {
|
|
76306
|
+
}), btn("up", 0, 1, {
|
|
76307
|
+
role: "up",
|
|
76308
|
+
icon: "chevron-up"
|
|
76309
|
+
}), btn("left", 1, 0, {
|
|
76310
|
+
role: "left",
|
|
76311
|
+
icon: "chevron-left"
|
|
76312
|
+
}), btn("ok", 1, 1, {
|
|
75578
76313
|
role: "ok",
|
|
75579
76314
|
shape: "round",
|
|
75580
76315
|
tone: "accent"
|
|
75581
|
-
}), btn("right", 1, 2, {
|
|
76316
|
+
}), btn("right", 1, 2, {
|
|
76317
|
+
role: "right",
|
|
76318
|
+
icon: "chevron-right"
|
|
76319
|
+
}), btn("down", 2, 1, {
|
|
76320
|
+
role: "down",
|
|
76321
|
+
icon: "chevron-down"
|
|
76322
|
+
}), rocker("core:rocker-volume-v", "Volume rocker", "Bilanciere volume", "rocker-v", "VOL", [btn("up", 0, 0, {
|
|
75582
76323
|
role: "volume_up",
|
|
76324
|
+
icon: "plus",
|
|
75583
76325
|
shape: "pill"
|
|
75584
76326
|
}), btn("down", 1, 0, {
|
|
75585
76327
|
role: "volume_down",
|
|
76328
|
+
icon: "minus",
|
|
75586
76329
|
shape: "pill"
|
|
75587
76330
|
})], {
|
|
75588
76331
|
rows: 2,
|
|
75589
76332
|
cols: 1
|
|
75590
76333
|
}), rocker("core:rocker-channel-v", "Channel rocker", "Bilanciere canali", "rocker-v", "CH", [btn("up", 0, 0, {
|
|
75591
76334
|
role: "channel_up",
|
|
76335
|
+
icon: "chevron-up",
|
|
75592
76336
|
shape: "pill"
|
|
75593
76337
|
}), btn("down", 1, 0, {
|
|
75594
76338
|
role: "channel_down",
|
|
76339
|
+
icon: "chevron-down",
|
|
75595
76340
|
shape: "pill"
|
|
75596
76341
|
})], {
|
|
75597
76342
|
rows: 2,
|
|
75598
76343
|
cols: 1
|
|
75599
76344
|
}), rocker("core:rocker-h", "Minus / plus rocker", "Bilanciere meno / più", "rocker-h", null, [btn("minus", 0, 0, {
|
|
75600
76345
|
role: "custom:minus",
|
|
75601
|
-
label: "
|
|
76346
|
+
label: "Minus",
|
|
76347
|
+
icon: "minus",
|
|
75602
76348
|
shape: "pill"
|
|
75603
76349
|
}), btn("plus", 0, 1, {
|
|
75604
76350
|
role: "custom:plus",
|
|
75605
|
-
label: "
|
|
76351
|
+
label: "Plus",
|
|
76352
|
+
icon: "plus",
|
|
75606
76353
|
shape: "pill"
|
|
75607
76354
|
})], {
|
|
75608
76355
|
rows: 1,
|
|
75609
76356
|
cols: 2
|
|
75610
76357
|
}), [...Array.from({ length: 9 }, (_, i) => btn(`d${i + 1}`, Math.floor(i / 3), i % 3, { role: `digit_${i + 1}` })), btn("d0", 3, 1, { role: "digit_0" })], btn("red", 0, 0, {
|
|
75611
76358
|
role: "custom:color_red",
|
|
76359
|
+
label: "Red",
|
|
75612
76360
|
tone: "red"
|
|
75613
76361
|
}), btn("green", 0, 1, {
|
|
75614
76362
|
role: "custom:color_green",
|
|
76363
|
+
label: "Green",
|
|
75615
76364
|
tone: "green"
|
|
75616
76365
|
}), btn("yellow", 0, 2, {
|
|
75617
76366
|
role: "custom:color_yellow",
|
|
76367
|
+
label: "Yellow",
|
|
75618
76368
|
tone: "yellow"
|
|
75619
76369
|
}), btn("blue", 0, 3, {
|
|
75620
76370
|
role: "custom:color_blue",
|
|
76371
|
+
label: "Blue",
|
|
75621
76372
|
tone: "blue"
|
|
75622
|
-
}), btn("rewind", 0, 0, {
|
|
76373
|
+
}), btn("rewind", 0, 0, {
|
|
76374
|
+
role: "rewind",
|
|
76375
|
+
icon: "rewind"
|
|
76376
|
+
}), btn("play", 0, 1, {
|
|
76377
|
+
role: "play",
|
|
76378
|
+
icon: "play"
|
|
76379
|
+
}), btn("pause", 0, 2, {
|
|
76380
|
+
role: "pause",
|
|
76381
|
+
icon: "pause"
|
|
76382
|
+
}), btn("forward", 0, 3, {
|
|
76383
|
+
role: "fast_forward",
|
|
76384
|
+
icon: "fast-forward"
|
|
76385
|
+
}), btn("stop", 0, 4, {
|
|
76386
|
+
role: "stop",
|
|
76387
|
+
icon: "square"
|
|
76388
|
+
}), [
|
|
75623
76389
|
1,
|
|
75624
76390
|
2,
|
|
75625
76391
|
3,
|
|
@@ -75635,7 +76401,7 @@ discriminatedUnion("kind", [object({
|
|
|
75635
76401
|
})]);
|
|
75636
76402
|
DeviceFeature.FanSpeed, DeviceFeature.FanPreset, DeviceFeature.FanDirection, DeviceFeature.FanOscillating, DeviceFeature.CoverPositionable, DeviceFeature.CoverTilt, DeviceFeature.ValvePositionable, DeviceFeature.MediaPlayerVolume, DeviceFeature.ClimateFanMode;
|
|
75637
76403
|
SOURCE_CAPS.filter((cap) => cap !== "switch" && cap !== "motion");
|
|
75638
|
-
DeviceType.Camera, DeviceType.Sensor, DeviceType.Button, DeviceType.Switch, DeviceType.PetFeeder, DeviceType.Container, DeviceType.Thermostat, DeviceType.EventEmitter, DeviceType.Camera, DeviceType.Hub, DeviceType.Light, DeviceType.Siren, DeviceType.Switch, DeviceType.Sensor, DeviceType.Thermostat, DeviceType.Climate, DeviceType.Button, DeviceType.EventEmitter, DeviceType.Update, DeviceType.Generic, DeviceType.Notifier, DeviceType.Script, DeviceType.Automation, DeviceType.Lock, DeviceType.Cover, DeviceType.Valve, DeviceType.Humidifier, DeviceType.WaterHeater, DeviceType.Fan, DeviceType.MediaPlayer, DeviceType.AlarmPanel, DeviceType.Control, DeviceType.Presence, DeviceType.Weather, DeviceType.Vacuum, DeviceType.LawnMower, DeviceType.Container, DeviceType.Image, DeviceType.PetFeeder, DeviceType.PetFountain, DeviceType.Dishwasher, DeviceType.Washer, DeviceType.Dryer, DeviceType.Camera, DeviceType.Camera, DeviceType.Switch, DeviceType.Light, DeviceType.Fan, DeviceType.Climate, DeviceType.Thermostat, DeviceType.Humidifier, DeviceType.WaterHeater, DeviceType.MediaPlayer, DeviceType.Washer, DeviceType.Dryer, DeviceType.Dishwasher, DeviceType.Vacuum, DeviceType.LawnMower, DeviceType.PetFeeder, DeviceType.Switch, DeviceType.Light, DeviceType.Fan, DeviceType.Climate, DeviceType.Thermostat, DeviceType.Humidifier, DeviceType.WaterHeater, DeviceType.MediaPlayer, DeviceType.Washer, DeviceType.Dryer, DeviceType.Dishwasher, DeviceType.Vacuum, DeviceType.LawnMower, DeviceType.PetFeeder, DeviceType.Switch, DeviceType.Light, DeviceType.Fan, DeviceType.Climate, DeviceType.Thermostat, DeviceType.Humidifier, DeviceType.WaterHeater, DeviceType.MediaPlayer, DeviceType.Washer, DeviceType.Dryer, DeviceType.Dishwasher, DeviceType.Vacuum, DeviceType.LawnMower, DeviceType.PetFeeder, DeviceType.Switch, DeviceType.Light, DeviceType.Fan, DeviceType.Climate, DeviceType.Thermostat, DeviceType.Humidifier, DeviceType.WaterHeater, DeviceType.MediaPlayer, DeviceType.Washer, DeviceType.Dryer, DeviceType.Dishwasher, DeviceType.Vacuum, DeviceType.LawnMower, DeviceType.PetFeeder, DeviceType.MediaPlayer, DeviceType.Washer, DeviceType.Dryer, DeviceType.Dishwasher, DeviceType.Vacuum, DeviceType.LawnMower, DeviceType.MediaPlayer, DeviceType.WaterHeater, DeviceType.Humidifier, DeviceType.Fan, DeviceType.Climate, DeviceType.Thermostat, DeviceType.PetFeeder;
|
|
76404
|
+
DeviceType.Camera, DeviceType.Sensor, DeviceType.Button, DeviceType.Switch, DeviceType.PetFeeder, DeviceType.Container, DeviceType.Thermostat, DeviceType.EventEmitter, DeviceType.Camera, DeviceType.Hub, DeviceType.Light, DeviceType.Siren, DeviceType.Switch, DeviceType.Sensor, DeviceType.Thermostat, DeviceType.Climate, DeviceType.Button, DeviceType.EventEmitter, DeviceType.Update, DeviceType.Generic, DeviceType.Notifier, DeviceType.Script, DeviceType.Automation, DeviceType.Lock, DeviceType.Cover, DeviceType.Valve, DeviceType.Humidifier, DeviceType.WaterHeater, DeviceType.Fan, DeviceType.MediaPlayer, DeviceType.AlarmPanel, DeviceType.Control, DeviceType.Presence, DeviceType.Weather, DeviceType.Vacuum, DeviceType.LawnMower, DeviceType.Container, DeviceType.Image, DeviceType.PetFeeder, DeviceType.PetFountain, DeviceType.Dishwasher, DeviceType.Washer, DeviceType.Dryer, DeviceType.Gateway, DeviceType.Camera, DeviceType.Camera, DeviceType.Switch, DeviceType.Light, DeviceType.Fan, DeviceType.Climate, DeviceType.Thermostat, DeviceType.Humidifier, DeviceType.WaterHeater, DeviceType.MediaPlayer, DeviceType.Washer, DeviceType.Dryer, DeviceType.Dishwasher, DeviceType.Vacuum, DeviceType.LawnMower, DeviceType.PetFeeder, DeviceType.Switch, DeviceType.Light, DeviceType.Fan, DeviceType.Climate, DeviceType.Thermostat, DeviceType.Humidifier, DeviceType.WaterHeater, DeviceType.MediaPlayer, DeviceType.Washer, DeviceType.Dryer, DeviceType.Dishwasher, DeviceType.Vacuum, DeviceType.LawnMower, DeviceType.PetFeeder, DeviceType.Switch, DeviceType.Light, DeviceType.Fan, DeviceType.Climate, DeviceType.Thermostat, DeviceType.Humidifier, DeviceType.WaterHeater, DeviceType.MediaPlayer, DeviceType.Washer, DeviceType.Dryer, DeviceType.Dishwasher, DeviceType.Vacuum, DeviceType.LawnMower, DeviceType.PetFeeder, DeviceType.Switch, DeviceType.Light, DeviceType.Fan, DeviceType.Climate, DeviceType.Thermostat, DeviceType.Humidifier, DeviceType.WaterHeater, DeviceType.MediaPlayer, DeviceType.Washer, DeviceType.Dryer, DeviceType.Dishwasher, DeviceType.Vacuum, DeviceType.LawnMower, DeviceType.PetFeeder, DeviceType.MediaPlayer, DeviceType.Washer, DeviceType.Dryer, DeviceType.Dishwasher, DeviceType.Vacuum, DeviceType.LawnMower, DeviceType.MediaPlayer, DeviceType.WaterHeater, DeviceType.Humidifier, DeviceType.Fan, DeviceType.Climate, DeviceType.Thermostat, DeviceType.PetFeeder;
|
|
75639
76405
|
String.raw`rose\(active(\d+), changed(\d+), (\d+(?:\.\d+)?)\)`;
|
|
75640
76406
|
DeviceRole.BinarySensor, DeviceRole.MotionSensor;
|
|
75641
76407
|
new Set(CAP_NAMES);
|
|
@@ -76807,7 +77573,7 @@ var DeclaredDevices = class {
|
|
|
76807
77573
|
return removed;
|
|
76808
77574
|
}
|
|
76809
77575
|
};
|
|
76810
|
-
DeviceType.Cover, DeviceType.Valve, DeviceType.Humidifier, DeviceType.WaterHeater, DeviceType.Camera, DeviceType.Hub, DeviceType.Switch, DeviceType.Siren, DeviceType.Light, DeviceType.Fan, DeviceType.Sensor, DeviceType.Thermostat, DeviceType.Climate, DeviceType.Button, DeviceType.EventEmitter, DeviceType.Update, DeviceType.Generic, DeviceType.Notifier, DeviceType.Script, DeviceType.Automation, DeviceType.Lock, DeviceType.MediaPlayer, DeviceType.AlarmPanel, DeviceType.Control, DeviceType.Presence, DeviceType.Weather, DeviceType.Vacuum, DeviceType.LawnMower, DeviceType.Container, DeviceType.Image, DeviceType.PetFeeder, DeviceType.PetFountain, DeviceType.Dishwasher, DeviceType.Washer, DeviceType.Dryer;
|
|
77576
|
+
DeviceType.Cover, DeviceType.Valve, DeviceType.Humidifier, DeviceType.WaterHeater, DeviceType.Camera, DeviceType.Hub, DeviceType.Switch, DeviceType.Siren, DeviceType.Light, DeviceType.Fan, DeviceType.Sensor, DeviceType.Thermostat, DeviceType.Climate, DeviceType.Button, DeviceType.EventEmitter, DeviceType.Update, DeviceType.Generic, DeviceType.Notifier, DeviceType.Script, DeviceType.Automation, DeviceType.Lock, DeviceType.MediaPlayer, DeviceType.AlarmPanel, DeviceType.Control, DeviceType.Presence, DeviceType.Weather, DeviceType.Vacuum, DeviceType.LawnMower, DeviceType.Container, DeviceType.Image, DeviceType.PetFeeder, DeviceType.PetFountain, DeviceType.Dishwasher, DeviceType.Washer, DeviceType.Dryer, DeviceType.Gateway;
|
|
76811
77577
|
new Set(Object.values(DeviceType));
|
|
76812
77578
|
Object.freeze({
|
|
76813
77579
|
"accessories.getStatus": {
|
|
@@ -77195,6 +77961,13 @@ Object.freeze({
|
|
|
77195
77961
|
access: "create",
|
|
77196
77962
|
role: "admin"
|
|
77197
77963
|
},
|
|
77964
|
+
"addonSettings.getDeclaredSettingsKeys": {
|
|
77965
|
+
capName: "addon-settings",
|
|
77966
|
+
capScope: "system",
|
|
77967
|
+
addonId: null,
|
|
77968
|
+
access: "view",
|
|
77969
|
+
role: "admin"
|
|
77970
|
+
},
|
|
77198
77971
|
"addonSettings.getDeviceSettings": {
|
|
77199
77972
|
capName: "addon-settings",
|
|
77200
77973
|
capScope: "system",
|
|
@@ -77216,6 +77989,13 @@ Object.freeze({
|
|
|
77216
77989
|
access: "view",
|
|
77217
77990
|
role: "admin"
|
|
77218
77991
|
},
|
|
77992
|
+
"addonSettings.unsetStoredSettingsKeys": {
|
|
77993
|
+
capName: "addon-settings",
|
|
77994
|
+
capScope: "system",
|
|
77995
|
+
addonId: null,
|
|
77996
|
+
access: "create",
|
|
77997
|
+
role: "admin"
|
|
77998
|
+
},
|
|
77219
77999
|
"addonSettings.updateDeviceSettings": {
|
|
77220
78000
|
capName: "addon-settings",
|
|
77221
78001
|
capScope: "system",
|
|
@@ -79631,6 +80411,13 @@ Object.freeze({
|
|
|
79631
80411
|
access: "create",
|
|
79632
80412
|
role: "admin"
|
|
79633
80413
|
},
|
|
80414
|
+
"deviceProvider.classifyDiscoveryHits": {
|
|
80415
|
+
capName: "device-provider",
|
|
80416
|
+
capScope: "system",
|
|
80417
|
+
addonId: null,
|
|
80418
|
+
access: "create",
|
|
80419
|
+
role: "admin"
|
|
80420
|
+
},
|
|
79634
80421
|
"deviceProvider.createDevice": {
|
|
79635
80422
|
capName: "device-provider",
|
|
79636
80423
|
capScope: "system",
|
|
@@ -79659,6 +80446,13 @@ Object.freeze({
|
|
|
79659
80446
|
access: "view",
|
|
79660
80447
|
role: "admin"
|
|
79661
80448
|
},
|
|
80449
|
+
"deviceProvider.getDiscoveryModes": {
|
|
80450
|
+
capName: "device-provider",
|
|
80451
|
+
capScope: "system",
|
|
80452
|
+
addonId: null,
|
|
80453
|
+
access: "view",
|
|
80454
|
+
role: "admin"
|
|
80455
|
+
},
|
|
79662
80456
|
"deviceProvider.getDiscoveryParamsSchema": {
|
|
79663
80457
|
capName: "device-provider",
|
|
79664
80458
|
capScope: "system",
|
|
@@ -80436,6 +81230,13 @@ Object.freeze({
|
|
|
80436
81230
|
access: "create",
|
|
80437
81231
|
role: "admin"
|
|
80438
81232
|
},
|
|
81233
|
+
"keychain.releaseRecordRefs": {
|
|
81234
|
+
capName: "keychain",
|
|
81235
|
+
capScope: "system",
|
|
81236
|
+
addonId: null,
|
|
81237
|
+
access: "create",
|
|
81238
|
+
role: "admin"
|
|
81239
|
+
},
|
|
80439
81240
|
"keychain.resolve": {
|
|
80440
81241
|
capName: "keychain",
|
|
80441
81242
|
capScope: "system",
|
|
@@ -80856,6 +81657,13 @@ Object.freeze({
|
|
|
80856
81657
|
access: "view",
|
|
80857
81658
|
role: "admin"
|
|
80858
81659
|
},
|
|
81660
|
+
"localNetwork.getScanSubnets": {
|
|
81661
|
+
capName: "local-network",
|
|
81662
|
+
capScope: "system",
|
|
81663
|
+
addonId: null,
|
|
81664
|
+
access: "view",
|
|
81665
|
+
role: "admin"
|
|
81666
|
+
},
|
|
80859
81667
|
"localNetwork.getTlsStatus": {
|
|
80860
81668
|
capName: "local-network",
|
|
80861
81669
|
capScope: "system",
|
|
@@ -80905,6 +81713,13 @@ Object.freeze({
|
|
|
80905
81713
|
access: "create",
|
|
80906
81714
|
role: "admin"
|
|
80907
81715
|
},
|
|
81716
|
+
"localNetwork.scanNetwork": {
|
|
81717
|
+
capName: "local-network",
|
|
81718
|
+
capScope: "system",
|
|
81719
|
+
addonId: null,
|
|
81720
|
+
access: "create",
|
|
81721
|
+
role: "admin"
|
|
81722
|
+
},
|
|
80908
81723
|
"localNetwork.setAddressRole": {
|
|
80909
81724
|
capName: "local-network",
|
|
80910
81725
|
capScope: "system",
|
|
@@ -80926,6 +81741,13 @@ Object.freeze({
|
|
|
80926
81741
|
access: "create",
|
|
80927
81742
|
role: "admin"
|
|
80928
81743
|
},
|
|
81744
|
+
"localNetwork.setScanSubnets": {
|
|
81745
|
+
capName: "local-network",
|
|
81746
|
+
capScope: "system",
|
|
81747
|
+
addonId: null,
|
|
81748
|
+
access: "create",
|
|
81749
|
+
role: "admin"
|
|
81750
|
+
},
|
|
80929
81751
|
"localNetwork.setViewerEndpoints": {
|
|
80930
81752
|
capName: "local-network",
|
|
80931
81753
|
capScope: "system",
|
|
@@ -85147,6 +85969,13 @@ Object.freeze({
|
|
|
85147
85969
|
access: "create",
|
|
85148
85970
|
role: "admin"
|
|
85149
85971
|
},
|
|
85972
|
+
"storageAdmin.dropOrphanedKind": {
|
|
85973
|
+
capName: "storage-admin",
|
|
85974
|
+
capScope: "system",
|
|
85975
|
+
addonId: null,
|
|
85976
|
+
access: "delete",
|
|
85977
|
+
role: "admin"
|
|
85978
|
+
},
|
|
85150
85979
|
"storageAdmin.listKinds": {
|
|
85151
85980
|
capName: "storage-admin",
|
|
85152
85981
|
capScope: "system",
|
|
@@ -85168,6 +85997,27 @@ Object.freeze({
|
|
|
85168
85997
|
access: "view",
|
|
85169
85998
|
role: "admin"
|
|
85170
85999
|
},
|
|
86000
|
+
"storageAdmin.scanStaleData": {
|
|
86001
|
+
capName: "storage-admin",
|
|
86002
|
+
capScope: "system",
|
|
86003
|
+
addonId: null,
|
|
86004
|
+
access: "create",
|
|
86005
|
+
role: "admin"
|
|
86006
|
+
},
|
|
86007
|
+
"storageAdmin.staleDataReport": {
|
|
86008
|
+
capName: "storage-admin",
|
|
86009
|
+
capScope: "system",
|
|
86010
|
+
addonId: null,
|
|
86011
|
+
access: "view",
|
|
86012
|
+
role: "admin"
|
|
86013
|
+
},
|
|
86014
|
+
"storageAdmin.unsetStaleSettingsKey": {
|
|
86015
|
+
capName: "storage-admin",
|
|
86016
|
+
capScope: "system",
|
|
86017
|
+
addonId: null,
|
|
86018
|
+
access: "create",
|
|
86019
|
+
role: "admin"
|
|
86020
|
+
},
|
|
85171
86021
|
"storageEvictable.evict": {
|
|
85172
86022
|
capName: "storage-evictable",
|
|
85173
86023
|
capScope: "system",
|
|
@@ -90864,7 +91714,7 @@ function projectAction(cap, action) {
|
|
|
90864
91714
|
};
|
|
90865
91715
|
}
|
|
90866
91716
|
Object.entries(CAP_VOCABULARY_BY_NAME).flatMap(([cap, entry]) => entry.scope === "device" ? (entry.actions ?? []).map((a) => projectAction(cap, a)) : []);
|
|
90867
|
-
DeviceType.Camera, DeviceType.Hub, DeviceType.Light, DeviceType.Siren, DeviceType.Switch, DeviceType.Sensor, DeviceType.Thermostat, DeviceType.Climate, DeviceType.Button, DeviceType.EventEmitter, DeviceType.Update, DeviceType.Generic, DeviceType.Notifier, DeviceType.Script, DeviceType.Automation, DeviceType.Lock, DeviceType.Cover, DeviceType.Valve, DeviceType.Humidifier, DeviceType.WaterHeater, DeviceType.Fan, DeviceType.MediaPlayer, DeviceType.AlarmPanel, DeviceType.Control, DeviceType.Presence, DeviceType.Weather, DeviceType.Vacuum, DeviceType.LawnMower, DeviceType.Container, DeviceType.Image, DeviceType.PetFeeder, DeviceType.PetFountain, DeviceType.Dishwasher, DeviceType.Washer, DeviceType.Dryer;
|
|
91717
|
+
DeviceType.Camera, DeviceType.Hub, DeviceType.Light, DeviceType.Siren, DeviceType.Switch, DeviceType.Sensor, DeviceType.Thermostat, DeviceType.Climate, DeviceType.Button, DeviceType.EventEmitter, DeviceType.Update, DeviceType.Generic, DeviceType.Notifier, DeviceType.Script, DeviceType.Automation, DeviceType.Lock, DeviceType.Cover, DeviceType.Valve, DeviceType.Humidifier, DeviceType.WaterHeater, DeviceType.Fan, DeviceType.MediaPlayer, DeviceType.AlarmPanel, DeviceType.Control, DeviceType.Presence, DeviceType.Weather, DeviceType.Vacuum, DeviceType.LawnMower, DeviceType.Container, DeviceType.Image, DeviceType.PetFeeder, DeviceType.PetFountain, DeviceType.Dishwasher, DeviceType.Washer, DeviceType.Dryer, DeviceType.Gateway;
|
|
90868
91718
|
DeviceFeature.BatteryOperated;
|
|
90869
91719
|
DeviceType.Washer, DeviceType.Dryer, DeviceType.Dishwasher;
|
|
90870
91720
|
var HA_AS = "a power sensor (device_class power). Home Assistant has no laundry domain. running-state stays unexported until a null reading can be published as unavailable.";
|