@camstack/addon-post-analysis 1.2.652 → 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 +13 -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 +293 -15
- package/dist/pipeline-analytics/index.mjs +293 -15
- 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
|
@@ -5645,7 +5645,7 @@ var ZodIssueCode = {
|
|
|
5645
5645
|
var ZodFirstPartyTypeKind;
|
|
5646
5646
|
ZodFirstPartyTypeKind || (ZodFirstPartyTypeKind = {});
|
|
5647
5647
|
//#endregion
|
|
5648
|
-
//#region ../types/dist/sleep-
|
|
5648
|
+
//#region ../types/dist/sleep-CeyhrcOk.mjs
|
|
5649
5649
|
/**
|
|
5650
5650
|
* The audio chunk plane's byte format, and the ONE expansion from a coded
|
|
5651
5651
|
* window to float samples (D455).
|
|
@@ -7712,6 +7712,7 @@ var BaseAddon = class {
|
|
|
7712
7712
|
* a warning and falls back rather than crashing boot.
|
|
7713
7713
|
*/
|
|
7714
7714
|
state(key, schema, fallback) {
|
|
7715
|
+
this._declaredStateKeys.add(key);
|
|
7715
7716
|
return createDurableState({
|
|
7716
7717
|
key,
|
|
7717
7718
|
schema,
|
|
@@ -7727,6 +7728,96 @@ var BaseAddon = class {
|
|
|
7727
7728
|
} })
|
|
7728
7729
|
});
|
|
7729
7730
|
}
|
|
7731
|
+
/** Durable-state keys this process registered through {@link state}. */
|
|
7732
|
+
_declaredStateKeys = /* @__PURE__ */ new Set();
|
|
7733
|
+
/**
|
|
7734
|
+
* Stale-data audit: every global-settings key this addon still declares —
|
|
7735
|
+
* constructor defaults, settings-schema fields (layout containers included),
|
|
7736
|
+
* durable-state keys and the root of each `secretStatePaths` entry. Answered
|
|
7737
|
+
* here, in the addon's own process, so the hub keeps no copy of it.
|
|
7738
|
+
*/
|
|
7739
|
+
async getDeclaredSettingsKeys() {
|
|
7740
|
+
return { keys: [...this.declaredKeySet()].toSorted() };
|
|
7741
|
+
}
|
|
7742
|
+
declaredKeySet() {
|
|
7743
|
+
const keys = new Set(Object.keys(this.defaults));
|
|
7744
|
+
const schema = this.globalSettingsSchema();
|
|
7745
|
+
if (schema) for (const section of schema.sections) for (const key of collectFieldKeys(section.fields)) keys.add(key);
|
|
7746
|
+
for (const key of this._declaredStateKeys) keys.add(key);
|
|
7747
|
+
for (const path of this.secretStatePaths) {
|
|
7748
|
+
const root = path.split(/[.[]/, 1)[0];
|
|
7749
|
+
if (root) keys.add(root);
|
|
7750
|
+
}
|
|
7751
|
+
return keys;
|
|
7752
|
+
}
|
|
7753
|
+
/**
|
|
7754
|
+
* Stale-data audit: remove stored global-settings keys the addon no longer
|
|
7755
|
+
* declares, and clear the keychain values their markers held — except a value
|
|
7756
|
+
* a surviving key still points at. A declared or absent key is refused.
|
|
7757
|
+
*/
|
|
7758
|
+
async unsetStoredSettingsKeys(keys) {
|
|
7759
|
+
const settings = this._ctx?.settings;
|
|
7760
|
+
const raw = this.rawSettings();
|
|
7761
|
+
if (!settings || !raw) return {
|
|
7762
|
+
removed: [],
|
|
7763
|
+
refused: keys.map((key) => ({
|
|
7764
|
+
key,
|
|
7765
|
+
reason: "no settings store"
|
|
7766
|
+
})),
|
|
7767
|
+
secretsCleared: 0
|
|
7768
|
+
};
|
|
7769
|
+
let stored;
|
|
7770
|
+
try {
|
|
7771
|
+
stored = await raw.readAddonStore();
|
|
7772
|
+
} catch (error) {
|
|
7773
|
+
const reason = `store unreadable: ${error instanceof Error ? error.message : "unknown"}`;
|
|
7774
|
+
return {
|
|
7775
|
+
removed: [],
|
|
7776
|
+
refused: keys.map((key) => ({
|
|
7777
|
+
key,
|
|
7778
|
+
reason
|
|
7779
|
+
})),
|
|
7780
|
+
secretsCleared: 0
|
|
7781
|
+
};
|
|
7782
|
+
}
|
|
7783
|
+
const declared = this.declaredKeySet();
|
|
7784
|
+
const removed = [];
|
|
7785
|
+
const refused = [];
|
|
7786
|
+
for (const key of keys) {
|
|
7787
|
+
const base = key.split("@", 1)[0] ?? key;
|
|
7788
|
+
if (declared.has(base)) refused.push({
|
|
7789
|
+
key,
|
|
7790
|
+
reason: "still declared by the addon"
|
|
7791
|
+
});
|
|
7792
|
+
else if (!(key in stored)) refused.push({
|
|
7793
|
+
key,
|
|
7794
|
+
reason: "not stored"
|
|
7795
|
+
});
|
|
7796
|
+
else removed.push(key);
|
|
7797
|
+
}
|
|
7798
|
+
if (removed.length === 0) return {
|
|
7799
|
+
removed,
|
|
7800
|
+
refused,
|
|
7801
|
+
secretsCleared: 0
|
|
7802
|
+
};
|
|
7803
|
+
const kept = /* @__PURE__ */ new Set();
|
|
7804
|
+
const held = /* @__PURE__ */ new Set();
|
|
7805
|
+
for (const [key, value] of Object.entries(stored)) {
|
|
7806
|
+
const target = removed.includes(key) ? held : kept;
|
|
7807
|
+
for (const ref of collectSecretMarkerRefs(value)) target.add(ref);
|
|
7808
|
+
}
|
|
7809
|
+
const refsToClear = [...held].filter((ref) => !kept.has(ref));
|
|
7810
|
+
const patch = {};
|
|
7811
|
+
for (const key of removed) patch[key] = void 0;
|
|
7812
|
+
await settings.writeAddonStore(patch);
|
|
7813
|
+
const secretsCleared = refsToClear.length > 0 && this._ctx?.secrets ? await this._ctx.secrets.delete(refsToClear) : 0;
|
|
7814
|
+
await this.resolveConfig();
|
|
7815
|
+
return {
|
|
7816
|
+
removed,
|
|
7817
|
+
refused,
|
|
7818
|
+
secretsCleared
|
|
7819
|
+
};
|
|
7820
|
+
}
|
|
7730
7821
|
/** Per-device variant of {@link state}, backed by the per-device store. */
|
|
7731
7822
|
deviceState(deviceId, key, schema, fallback) {
|
|
7732
7823
|
return createDurableState({
|
|
@@ -7997,6 +8088,21 @@ function dropPerNodeFields(fields) {
|
|
|
7997
8088
|
}
|
|
7998
8089
|
return kept;
|
|
7999
8090
|
}
|
|
8091
|
+
function collectFieldKeys(fields) {
|
|
8092
|
+
const collected = [];
|
|
8093
|
+
for (const field of fields) {
|
|
8094
|
+
if (field.type === "group") {
|
|
8095
|
+
collected.push(...collectFieldKeys(field.fields));
|
|
8096
|
+
continue;
|
|
8097
|
+
}
|
|
8098
|
+
if (field.type === "sub-tabs") {
|
|
8099
|
+
for (const tab of field.tabs) collected.push(...collectFieldKeys(tab.fields));
|
|
8100
|
+
continue;
|
|
8101
|
+
}
|
|
8102
|
+
if ("key" in field && typeof field.key === "string") collected.push(field.key);
|
|
8103
|
+
}
|
|
8104
|
+
return collected;
|
|
8105
|
+
}
|
|
8000
8106
|
function collectPerNodeFieldKeys(fields) {
|
|
8001
8107
|
const collected = [];
|
|
8002
8108
|
for (const field of fields) {
|
|
@@ -11200,7 +11306,7 @@ function sleep(ms) {
|
|
|
11200
11306
|
return new Promise((resolve) => setTimeout(resolve, Math.max(0, ms)));
|
|
11201
11307
|
}
|
|
11202
11308
|
//#endregion
|
|
11203
|
-
//#region ../types/dist/err-msg-
|
|
11309
|
+
//#region ../types/dist/err-msg-BD5buxvT.mjs
|
|
11204
11310
|
var DeviceType = /* @__PURE__ */ function(DeviceType) {
|
|
11205
11311
|
DeviceType["Camera"] = "camera";
|
|
11206
11312
|
DeviceType["Hub"] = "hub";
|
|
@@ -11306,6 +11412,12 @@ var DeviceType = /* @__PURE__ */ function(DeviceType) {
|
|
|
11306
11412
|
DeviceType["Washer"] = "washer";
|
|
11307
11413
|
/** Tumble dryer. Same plug-built running surface as {@link Washer}. */
|
|
11308
11414
|
DeviceType["Dryer"] = "dryer";
|
|
11415
|
+
/** The physical bridge box of a vendor ecosystem (Velux KLF-200, and later
|
|
11416
|
+
* other radio-to-IP bridges). It carries the box's own facts (firmware,
|
|
11417
|
+
* address, connection state) and the actions the box really supports
|
|
11418
|
+
* (`reboot`, `device-admin-link`). Products are NOT its children — they are
|
|
11419
|
+
* adopted beside it — and its connection settings stay on the integration. */
|
|
11420
|
+
DeviceType["Gateway"] = "gateway";
|
|
11309
11421
|
return DeviceType;
|
|
11310
11422
|
}({});
|
|
11311
11423
|
var DeviceFeature = /* @__PURE__ */ function(DeviceFeature) {
|
|
@@ -11566,7 +11678,7 @@ function errMsg(err) {
|
|
|
11566
11678
|
return String(err);
|
|
11567
11679
|
}
|
|
11568
11680
|
//#endregion
|
|
11569
|
-
//#region ../types/dist/composition-
|
|
11681
|
+
//#region ../types/dist/composition-C7WdThmP.mjs
|
|
11570
11682
|
/**
|
|
11571
11683
|
* Deterministic SHA-256 hash of an arbitrary serialisable value. The
|
|
11572
11684
|
* canonical form sorts object keys alphabetically at every depth so two
|
|
@@ -17535,8 +17647,194 @@ object({
|
|
|
17535
17647
|
quantity: ReadingQuantitySchema,
|
|
17536
17648
|
unit: string().min(1)
|
|
17537
17649
|
});
|
|
17538
|
-
/**
|
|
17539
|
-
*
|
|
17650
|
+
/**
|
|
17651
|
+
* The class names a per-class COUNT can ever be keyed on — the macro ids, and
|
|
17652
|
+
* only those.
|
|
17653
|
+
*
|
|
17654
|
+
* `preserveOriginal: false` below is the whole reason this set exists: the
|
|
17655
|
+
* executor maps each raw COCO label onto its macro and DROPS everything else,
|
|
17656
|
+
* so a tracked detection's `className` is always one of {@link MACRO_LABELS}.
|
|
17657
|
+
* Any surface that indexes counts by class name — the ZoneAnalytics occupancy
|
|
17658
|
+
* snapshot's `byClass`, and therefore every occupancy rule — can match nothing
|
|
17659
|
+
* else. Derived from the catalog, never hand-listed, so a new macro joins it by
|
|
17660
|
+
* being declared once.
|
|
17661
|
+
*
|
|
17662
|
+
* Cost of not having it, 2026-08-12: the notification rule editor offered the
|
|
17663
|
+
* full taxonomy for an occupancy class (occupancy is the one condition that
|
|
17664
|
+
* does not go through the engine's macro-expanding `expandClassSelector`), two
|
|
17665
|
+
* live rules were authored on `car`, and both counters read 0 forever.
|
|
17666
|
+
*/
|
|
17667
|
+
var DETECTION_MACRO_CLASSES = new Set([
|
|
17668
|
+
{
|
|
17669
|
+
id: "person",
|
|
17670
|
+
name: "Person"
|
|
17671
|
+
},
|
|
17672
|
+
{
|
|
17673
|
+
id: "vehicle",
|
|
17674
|
+
name: "Vehicle"
|
|
17675
|
+
},
|
|
17676
|
+
{
|
|
17677
|
+
id: "animal",
|
|
17678
|
+
name: "Animal"
|
|
17679
|
+
},
|
|
17680
|
+
{
|
|
17681
|
+
id: "package",
|
|
17682
|
+
name: "Package"
|
|
17683
|
+
}
|
|
17684
|
+
].map((l) => l.id));
|
|
17685
|
+
/** True when `className` is a macro the detector can actually emit (and hence a
|
|
17686
|
+
* class a count can be keyed on) — see {@link DETECTION_MACRO_CLASSES}. */
|
|
17687
|
+
function isDetectionMacroClass(className) {
|
|
17688
|
+
return DETECTION_MACRO_CLASSES.has(className.trim().toLowerCase());
|
|
17689
|
+
}
|
|
17690
|
+
var COCO_TO_MACRO = {
|
|
17691
|
+
mapping: {
|
|
17692
|
+
person: "person",
|
|
17693
|
+
bicycle: "vehicle",
|
|
17694
|
+
car: "vehicle",
|
|
17695
|
+
motorcycle: "vehicle",
|
|
17696
|
+
airplane: "vehicle",
|
|
17697
|
+
bus: "vehicle",
|
|
17698
|
+
train: "vehicle",
|
|
17699
|
+
truck: "vehicle",
|
|
17700
|
+
boat: "vehicle",
|
|
17701
|
+
bird: "animal",
|
|
17702
|
+
cat: "animal",
|
|
17703
|
+
dog: "animal",
|
|
17704
|
+
horse: "animal",
|
|
17705
|
+
sheep: "animal",
|
|
17706
|
+
cow: "animal",
|
|
17707
|
+
elephant: "animal",
|
|
17708
|
+
bear: "animal",
|
|
17709
|
+
zebra: "animal",
|
|
17710
|
+
giraffe: "animal",
|
|
17711
|
+
suitcase: "package",
|
|
17712
|
+
backpack: "package",
|
|
17713
|
+
handbag: "package"
|
|
17714
|
+
},
|
|
17715
|
+
preserveOriginal: false
|
|
17716
|
+
};
|
|
17717
|
+
/**
|
|
17718
|
+
* WHAT a detection-shaped leaf is about: one MACRO class (person, vehicle,
|
|
17719
|
+
* animal, package) plus an OPTIONAL label that narrows it.
|
|
17720
|
+
*
|
|
17721
|
+
* The taxonomy is `COCO_TO_MACRO` (and `CLASS_MAP_MACRO_TARGETS`) — never a
|
|
17722
|
+
* second list. The label that fits depends on the macro class:
|
|
17723
|
+
*
|
|
17724
|
+
* - `animal` → a sub-class (`dog`, `cat`, …);
|
|
17725
|
+
* - `person` → a known face (an identity of the `face-gallery`);
|
|
17726
|
+
* - `vehicle` → a plate (its text) or a sub-class (`car`, `truck`, …);
|
|
17727
|
+
* - `package` → a sub-class.
|
|
17728
|
+
*
|
|
17729
|
+
* `other` exists only so a class the taxonomy does not know (a custom model's
|
|
17730
|
+
* `forklift`) survives the conversion of a stored recipe without widening.
|
|
17731
|
+
*
|
|
17732
|
+
* A label is decided LATE (D683): face recognition and LPR land after the
|
|
17733
|
+
* detection starts. The track-lifecycle `update` event carries the newly
|
|
17734
|
+
* resolved `label` / `plateText`, which is why a leaf with a label fires when
|
|
17735
|
+
* the subject GETS it — not at the first detection.
|
|
17736
|
+
*/
|
|
17737
|
+
var SubClassLabelSchema = object({
|
|
17738
|
+
kind: literal("sub-class"),
|
|
17739
|
+
className: string().min(1)
|
|
17740
|
+
});
|
|
17741
|
+
var IdentityLabelSchema = object({
|
|
17742
|
+
kind: literal("identity"),
|
|
17743
|
+
/** The `face-gallery` identity id (stable across a rename). */
|
|
17744
|
+
identityId: string().min(1),
|
|
17745
|
+
/** The identity's name — what a track-lifecycle event carries as `label`. */
|
|
17746
|
+
name: string().min(1)
|
|
17747
|
+
});
|
|
17748
|
+
var PlateLabelSchema = object({
|
|
17749
|
+
kind: literal("plate"),
|
|
17750
|
+
text: string().min(1)
|
|
17751
|
+
});
|
|
17752
|
+
function macroOf$1(className) {
|
|
17753
|
+
return COCO_TO_MACRO.mapping[className.toLowerCase()] ?? className.toLowerCase();
|
|
17754
|
+
}
|
|
17755
|
+
/** A sub-class label must belong to the macro it is under. */
|
|
17756
|
+
function subClassBelongs(macro, label) {
|
|
17757
|
+
return label === void 0 || macroOf$1(label.className) === macro;
|
|
17758
|
+
}
|
|
17759
|
+
var subClassOf = (macro) => SubClassLabelSchema.refine((l) => subClassBelongs(macro, l), { message: `that class is not a kind of ${macro} in the detection taxonomy` });
|
|
17760
|
+
var DetectionSubjectSchema = discriminatedUnion("macro", [
|
|
17761
|
+
object({
|
|
17762
|
+
macro: literal("animal"),
|
|
17763
|
+
label: subClassOf("animal").optional()
|
|
17764
|
+
}),
|
|
17765
|
+
object({
|
|
17766
|
+
macro: literal("person"),
|
|
17767
|
+
label: IdentityLabelSchema.optional()
|
|
17768
|
+
}),
|
|
17769
|
+
object({
|
|
17770
|
+
macro: literal("vehicle"),
|
|
17771
|
+
label: discriminatedUnion("kind", [SubClassLabelSchema.refine((l) => subClassBelongs("vehicle", l), { message: "that class is not a kind of vehicle in the detection taxonomy" }), PlateLabelSchema]).optional()
|
|
17772
|
+
}),
|
|
17773
|
+
object({
|
|
17774
|
+
macro: literal("package"),
|
|
17775
|
+
label: subClassOf("package").optional()
|
|
17776
|
+
}),
|
|
17777
|
+
object({
|
|
17778
|
+
macro: literal("other"),
|
|
17779
|
+
className: string().min(1)
|
|
17780
|
+
})
|
|
17781
|
+
]);
|
|
17782
|
+
/**
|
|
17783
|
+
* The subject of a PARKED object. The stationary registry's event carries a
|
|
17784
|
+
* class and a zone, no face and no plate — an identity or plate label there
|
|
17785
|
+
* could never match, so the schema refuses it instead of letting it sit dead.
|
|
17786
|
+
*/
|
|
17787
|
+
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" });
|
|
17788
|
+
/**
|
|
17789
|
+
* A stored class string as a subject: a macro name stays a macro; a raw class
|
|
17790
|
+
* the taxonomy files under a macro becomes that macro plus the sub-class label
|
|
17791
|
+
* (`dog` → animal / dog); anything else is `other`, kept verbatim.
|
|
17792
|
+
*/
|
|
17793
|
+
function subjectFromClassName(className) {
|
|
17794
|
+
const name = className.trim().toLowerCase();
|
|
17795
|
+
const macro = COCO_TO_MACRO.mapping[name];
|
|
17796
|
+
if (new Set(Object.values(COCO_TO_MACRO.mapping)).has(name)) return macroOnly(name);
|
|
17797
|
+
if (macro === void 0) return {
|
|
17798
|
+
macro: "other",
|
|
17799
|
+
className
|
|
17800
|
+
};
|
|
17801
|
+
const label = {
|
|
17802
|
+
kind: "sub-class",
|
|
17803
|
+
className: name
|
|
17804
|
+
};
|
|
17805
|
+
switch (macro) {
|
|
17806
|
+
case "animal": return {
|
|
17807
|
+
macro: "animal",
|
|
17808
|
+
label
|
|
17809
|
+
};
|
|
17810
|
+
case "vehicle": return {
|
|
17811
|
+
macro: "vehicle",
|
|
17812
|
+
label
|
|
17813
|
+
};
|
|
17814
|
+
case "package": return {
|
|
17815
|
+
macro: "package",
|
|
17816
|
+
label
|
|
17817
|
+
};
|
|
17818
|
+
default: return {
|
|
17819
|
+
macro: "other",
|
|
17820
|
+
className
|
|
17821
|
+
};
|
|
17822
|
+
}
|
|
17823
|
+
}
|
|
17824
|
+
function macroOnly(macro) {
|
|
17825
|
+
switch (macro) {
|
|
17826
|
+
case "animal": return { macro: "animal" };
|
|
17827
|
+
case "person": return { macro: "person" };
|
|
17828
|
+
case "vehicle": return { macro: "vehicle" };
|
|
17829
|
+
case "package": return { macro: "package" };
|
|
17830
|
+
default: return {
|
|
17831
|
+
macro: "other",
|
|
17832
|
+
className: macro
|
|
17833
|
+
};
|
|
17834
|
+
}
|
|
17835
|
+
}
|
|
17836
|
+
/** How a state leaf compares a device field to a value. Derived from the
|
|
17837
|
+
* field's `kind` in `deviceManager.getWireableFields`, never hand-maintained. */
|
|
17540
17838
|
var AutomationConditionOperatorSchema = _enum([
|
|
17541
17839
|
"eq",
|
|
17542
17840
|
"ne",
|
|
@@ -17547,12 +17845,76 @@ var AutomationConditionOperatorSchema = _enum([
|
|
|
17547
17845
|
"contains",
|
|
17548
17846
|
"in"
|
|
17549
17847
|
]);
|
|
17550
|
-
|
|
17551
|
-
|
|
17848
|
+
/**
|
|
17849
|
+
* D8 compliance, and it is the reason a "becomes" leaf is not merely an event
|
|
17850
|
+
* subscription: it evaluates against the **state mirror**, which is reconciled,
|
|
17851
|
+
* and an event only WAKES the evaluation. A dropped event therefore DELAYS a
|
|
17852
|
+
* fire; it does not lose it.
|
|
17853
|
+
*/
|
|
17854
|
+
var DeviceBecomesLeafSchema = object({
|
|
17855
|
+
kind: literal("device-becomes"),
|
|
17856
|
+
deviceId: number().int().nonnegative(),
|
|
17857
|
+
cap: string().min(1),
|
|
17858
|
+
fieldPath: string().min(1),
|
|
17859
|
+
/** Fire when the field takes this value. Omit to fire on any change. */
|
|
17860
|
+
becomes: union([
|
|
17861
|
+
string(),
|
|
17862
|
+
number(),
|
|
17863
|
+
boolean()
|
|
17864
|
+
]).optional(),
|
|
17865
|
+
/** Only on a CHANGE of value, not on every re-report. */
|
|
17866
|
+
edge: boolean().optional(),
|
|
17867
|
+
/** The new value must hold this long before it counts. */
|
|
17868
|
+
forMs: number().int().min(0).max(864e5).optional(),
|
|
17869
|
+
/** Collapse a burst into one occurrence. */
|
|
17870
|
+
debounceMs: number().int().min(0).max(6e5).optional()
|
|
17871
|
+
});
|
|
17872
|
+
var DeviceEventLeafSchema = object({
|
|
17873
|
+
kind: literal("device-event"),
|
|
17874
|
+
/** An `EventCategory` value. */
|
|
17875
|
+
category: string().min(1),
|
|
17876
|
+
deviceId: number().int().nonnegative().optional()
|
|
17877
|
+
});
|
|
17878
|
+
var ScheduleLeafSchema = object({
|
|
17879
|
+
kind: literal("schedule"),
|
|
17880
|
+
cron: string().min(1).max(120)
|
|
17881
|
+
});
|
|
17882
|
+
var ManualLeafSchema = object({ kind: literal("manual") });
|
|
17883
|
+
var IntervalLeafSchema = object({
|
|
17884
|
+
kind: literal("interval"),
|
|
17885
|
+
minutes: number().int().min(1).max(1440)
|
|
17886
|
+
});
|
|
17887
|
+
var DetectionLeafSchema = object({
|
|
17888
|
+
kind: literal("detection"),
|
|
17889
|
+
/** One macro class each, optionally narrowed by a label; a track of any listed subject fires. */
|
|
17890
|
+
subjects: array(DetectionSubjectSchema).min(1),
|
|
17891
|
+
deviceIds: array(number().int().nonnegative()).min(1),
|
|
17892
|
+
/** The track must have visited at least one of these zones. */
|
|
17893
|
+
zones: array(string().min(1)).min(1).optional(),
|
|
17894
|
+
/** Best-so-far confidence the track must reach. */
|
|
17895
|
+
minScore: number().min(0).max(1).optional()
|
|
17896
|
+
});
|
|
17897
|
+
var StationaryLeafSchema = object({
|
|
17898
|
+
kind: literal("stationary"),
|
|
17899
|
+
deviceIds: array(number().int().nonnegative()).min(1),
|
|
17900
|
+
subjects: array(StationarySubjectSchema).min(1).optional(),
|
|
17901
|
+
zones: array(string().min(1)).min(1).optional(),
|
|
17902
|
+
/** `appeared`: it became parked. `departed`: the registry retired it. */
|
|
17903
|
+
phase: _enum(["appeared", "departed"])
|
|
17904
|
+
});
|
|
17905
|
+
/** "is": one device field compared to one value, NOW. */
|
|
17906
|
+
var DeviceIsLeafSchema = object({
|
|
17907
|
+
kind: literal("device-is"),
|
|
17552
17908
|
deviceId: number().int().nonnegative(),
|
|
17553
17909
|
cap: string().min(1),
|
|
17554
17910
|
fieldPath: string().min(1),
|
|
17555
17911
|
operator: AutomationConditionOperatorSchema,
|
|
17912
|
+
/**
|
|
17913
|
+
* The value. A number on a quantity field is stored in the field's base unit
|
|
17914
|
+
* (D944); a quantity value is the WRITE form, which the save boundary
|
|
17915
|
+
* replaces with the converted number and `unit`. A leaf that still carries
|
|
17916
|
+
* one is never evaluated (it fails).
|
|
17917
|
+
*/
|
|
17556
17918
|
value: union([
|
|
17557
17919
|
string(),
|
|
17558
17920
|
number(),
|
|
@@ -17560,24 +17922,26 @@ var AutomationConditionLeafSchema = object({
|
|
|
17560
17922
|
array(union([string(), number()])),
|
|
17561
17923
|
QuantityValueSchema
|
|
17562
17924
|
]),
|
|
17925
|
+
/** The unit the person picked for `value` (display only; `value` is in the base unit). */
|
|
17563
17926
|
unit: string().min(1).optional()
|
|
17564
17927
|
});
|
|
17565
|
-
|
|
17928
|
+
/**
|
|
17929
|
+
* True when the camera currently has a PARKED object matching `subjects` in at
|
|
17930
|
+
* least one of `zones`. Reads the zone-analytics snapshot through the same
|
|
17931
|
+
* mirror as every other state leaf, so a dropped event never decides it (D49).
|
|
17932
|
+
*/
|
|
17933
|
+
var StationaryPresentLeafSchema = object({
|
|
17566
17934
|
kind: literal("stationary-present"),
|
|
17567
17935
|
deviceId: number().int().nonnegative(),
|
|
17568
|
-
|
|
17569
|
-
classes: array(string().min(1)).min(1).optional(),
|
|
17570
|
-
/** The parked object must be in at least one of these zones. */
|
|
17936
|
+
subjects: array(StationarySubjectSchema).min(1).optional(),
|
|
17571
17937
|
zones: array(string().min(1)).min(1).optional()
|
|
17572
17938
|
});
|
|
17573
17939
|
/**
|
|
17574
|
-
* The
|
|
17575
|
-
*
|
|
17576
|
-
*
|
|
17577
|
-
* validation is the SAME function `ExpressionSourceSchema` runs, so the two
|
|
17578
|
-
* cannot drift — an expression that one accepts, the other accepts.
|
|
17940
|
+
* The escape hatch: the bounded expression engine over named device bindings.
|
|
17941
|
+
* Declared as a plain object so a discriminated union can read `kind`; the
|
|
17942
|
+
* author-time validation is the SAME function `ExpressionSourceSchema` runs.
|
|
17579
17943
|
*/
|
|
17580
|
-
var
|
|
17944
|
+
var ExpressionLeafSchema = object({
|
|
17581
17945
|
kind: literal("expression"),
|
|
17582
17946
|
expr: string().min(1).max(MAX_EXPRESSION_SOURCE_LENGTH),
|
|
17583
17947
|
bindings: record(string().regex(EXPRESSION_IDENTIFIER_RE), ExpressionBindingSourceSchema)
|
|
@@ -17589,55 +17953,62 @@ var AutomationConditionExpressionSchema = object({
|
|
|
17589
17953
|
path: ["expr"]
|
|
17590
17954
|
});
|
|
17591
17955
|
});
|
|
17592
|
-
var
|
|
17956
|
+
var AutomationWhenSchema = lazy(() => discriminatedUnion("kind", [
|
|
17593
17957
|
object({
|
|
17594
17958
|
kind: literal("all"),
|
|
17595
|
-
children: array(
|
|
17959
|
+
children: array(AutomationWhenSchema)
|
|
17596
17960
|
}),
|
|
17597
17961
|
object({
|
|
17598
17962
|
kind: literal("any"),
|
|
17599
|
-
children: array(
|
|
17963
|
+
children: array(AutomationWhenSchema)
|
|
17600
17964
|
}),
|
|
17601
17965
|
object({
|
|
17602
17966
|
kind: literal("not"),
|
|
17603
|
-
child:
|
|
17967
|
+
child: AutomationWhenSchema
|
|
17604
17968
|
}),
|
|
17605
|
-
|
|
17606
|
-
|
|
17607
|
-
|
|
17969
|
+
DeviceBecomesLeafSchema,
|
|
17970
|
+
DeviceEventLeafSchema,
|
|
17971
|
+
ScheduleLeafSchema,
|
|
17972
|
+
ManualLeafSchema,
|
|
17973
|
+
IntervalLeafSchema,
|
|
17974
|
+
DetectionLeafSchema,
|
|
17975
|
+
StationaryLeafSchema,
|
|
17976
|
+
DeviceIsLeafSchema,
|
|
17977
|
+
StationaryPresentLeafSchema,
|
|
17978
|
+
ExpressionLeafSchema
|
|
17608
17979
|
]));
|
|
17609
17980
|
/**
|
|
17610
|
-
*
|
|
17611
|
-
*
|
|
17612
|
-
*
|
|
17613
|
-
*
|
|
17614
|
-
*
|
|
17615
|
-
*
|
|
17616
|
-
*
|
|
17617
|
-
*
|
|
17618
|
-
|
|
17619
|
-
|
|
17981
|
+
* The recipe shape before the single `when` tree: a flat list of triggers
|
|
17982
|
+
* (OR'd, each an instant) and an optional condition tree. Stored recipes —
|
|
17983
|
+
* the `AUTOMATION_RECIPE` literal of every block saved so far, and whatever an
|
|
17984
|
+
* older client still posts — are in this shape, so it stays READABLE here, and
|
|
17985
|
+
* {@link convertLegacyRecipe} turns it into the new one, losslessly and one
|
|
17986
|
+
* way. Nothing writes this shape any more.
|
|
17987
|
+
*
|
|
17988
|
+
* `{ triggers: [t1…tn], conditions?: C }`
|
|
17989
|
+
* → `when = all(any(t1…tn), C)`, or `any(t1…tn)` without `C`;
|
|
17990
|
+
* a single trigger is not wrapped in `any`.
|
|
17991
|
+
* a `condition` leaf → a `device-is` leaf (the "is" verb);
|
|
17992
|
+
* a `device-state` trigger → a `device-becomes` leaf (the "becomes" verb);
|
|
17993
|
+
* `classes: ['dog']` → the macro `animal` with the label `dog`.
|
|
17994
|
+
*/
|
|
17995
|
+
var LegacyTriggerSchema = discriminatedUnion("kind", [
|
|
17620
17996
|
object({
|
|
17621
17997
|
kind: literal("device-state"),
|
|
17622
17998
|
deviceId: number().int().nonnegative(),
|
|
17623
17999
|
cap: string().min(1),
|
|
17624
18000
|
fieldPath: string().min(1),
|
|
17625
|
-
/** Fire when the field takes this value. Omit to fire on any change. */
|
|
17626
18001
|
becomes: union([
|
|
17627
18002
|
string(),
|
|
17628
18003
|
number(),
|
|
17629
18004
|
boolean()
|
|
17630
18005
|
]).optional(),
|
|
17631
|
-
/** Only on a CHANGE of value, not on every re-report. */
|
|
17632
18006
|
edge: boolean().optional(),
|
|
17633
|
-
/** The condition must hold this long before the run starts. */
|
|
17634
18007
|
forMs: number().int().min(0).max(864e5).optional(),
|
|
17635
|
-
/** Collapse a burst into one run. */
|
|
17636
18008
|
debounceMs: number().int().min(0).max(6e5).optional()
|
|
17637
18009
|
}),
|
|
17638
18010
|
object({
|
|
17639
18011
|
kind: literal("device-event"),
|
|
17640
|
-
/** An `EventCategory` value. */
|
|
17641
18012
|
category: string().min(1),
|
|
17642
18013
|
deviceId: number().int().nonnegative().optional()
|
|
17643
18014
|
}),
|
|
@@ -17648,25 +18019,16 @@ var AutomationTriggerSchema = discriminatedUnion("kind", [
|
|
|
17648
18019
|
object({ kind: literal("manual") }),
|
|
17649
18020
|
object({
|
|
17650
18021
|
kind: literal("detection"),
|
|
17651
|
-
/** Class names. A macro class (`animal`, `vehicle`, `person`, `package`)
|
|
17652
|
-
* matches every raw class that maps to it; any other name matches
|
|
17653
|
-
* exactly. */
|
|
17654
18022
|
classes: array(string().min(1)).min(1),
|
|
17655
18023
|
deviceIds: array(number().int().nonnegative()).min(1),
|
|
17656
|
-
/** The track must have visited at least one of these zones. */
|
|
17657
18024
|
zones: array(string().min(1)).min(1).optional(),
|
|
17658
|
-
/** Best-so-far confidence the track must reach. */
|
|
17659
18025
|
minScore: number().min(0).max(1).optional()
|
|
17660
18026
|
}),
|
|
17661
18027
|
object({
|
|
17662
18028
|
kind: literal("stationary"),
|
|
17663
18029
|
deviceIds: array(number().int().nonnegative()).min(1),
|
|
17664
|
-
/** Class names; a macro class matches like the detection trigger. */
|
|
17665
18030
|
classes: array(string().min(1)).min(1).optional(),
|
|
17666
|
-
/** The parked object must be in at least one of these zones. */
|
|
17667
18031
|
zones: array(string().min(1)).min(1).optional(),
|
|
17668
|
-
/** `appeared`: it became parked. `departed`: the registry retired it.
|
|
17669
|
-
* The vocabulary of `PipelineAnalyticsStationaryChanged`. */
|
|
17670
18032
|
phase: _enum(["appeared", "departed"])
|
|
17671
18033
|
}),
|
|
17672
18034
|
object({
|
|
@@ -17674,6 +18036,143 @@ var AutomationTriggerSchema = discriminatedUnion("kind", [
|
|
|
17674
18036
|
minutes: number().int().min(1).max(1440)
|
|
17675
18037
|
})
|
|
17676
18038
|
]);
|
|
18039
|
+
var LegacyConditionLeafSchema = object({
|
|
18040
|
+
kind: literal("condition"),
|
|
18041
|
+
deviceId: number().int().nonnegative(),
|
|
18042
|
+
cap: string().min(1),
|
|
18043
|
+
fieldPath: string().min(1),
|
|
18044
|
+
operator: AutomationConditionOperatorSchema,
|
|
18045
|
+
value: union([
|
|
18046
|
+
string(),
|
|
18047
|
+
number(),
|
|
18048
|
+
boolean(),
|
|
18049
|
+
array(union([string(), number()])),
|
|
18050
|
+
QuantityValueSchema
|
|
18051
|
+
]),
|
|
18052
|
+
unit: string().min(1).optional()
|
|
18053
|
+
});
|
|
18054
|
+
var LegacyStationaryPresentSchema = object({
|
|
18055
|
+
kind: literal("stationary-present"),
|
|
18056
|
+
deviceId: number().int().nonnegative(),
|
|
18057
|
+
classes: array(string().min(1)).min(1).optional(),
|
|
18058
|
+
zones: array(string().min(1)).min(1).optional()
|
|
18059
|
+
});
|
|
18060
|
+
var LegacyExpressionSchema = object({
|
|
18061
|
+
kind: literal("expression"),
|
|
18062
|
+
expr: string().min(1).max(MAX_EXPRESSION_SOURCE_LENGTH),
|
|
18063
|
+
bindings: record(string().regex(EXPRESSION_IDENTIFIER_RE), ExpressionBindingSourceSchema)
|
|
18064
|
+
}).superRefine((src, ctx) => {
|
|
18065
|
+
const err = validateExpressionSource(src);
|
|
18066
|
+
if (err !== null) ctx.addIssue({
|
|
18067
|
+
code: "custom",
|
|
18068
|
+
message: err,
|
|
18069
|
+
path: ["expr"]
|
|
18070
|
+
});
|
|
18071
|
+
});
|
|
18072
|
+
var LegacyConditionSchema = lazy(() => discriminatedUnion("kind", [
|
|
18073
|
+
object({
|
|
18074
|
+
kind: literal("all"),
|
|
18075
|
+
children: array(LegacyConditionSchema)
|
|
18076
|
+
}),
|
|
18077
|
+
object({
|
|
18078
|
+
kind: literal("any"),
|
|
18079
|
+
children: array(LegacyConditionSchema)
|
|
18080
|
+
}),
|
|
18081
|
+
object({
|
|
18082
|
+
kind: literal("not"),
|
|
18083
|
+
child: LegacyConditionSchema
|
|
18084
|
+
}),
|
|
18085
|
+
LegacyConditionLeafSchema,
|
|
18086
|
+
LegacyExpressionSchema,
|
|
18087
|
+
LegacyStationaryPresentSchema
|
|
18088
|
+
]));
|
|
18089
|
+
function convertTrigger(trigger) {
|
|
18090
|
+
switch (trigger.kind) {
|
|
18091
|
+
case "device-state": return {
|
|
18092
|
+
...trigger,
|
|
18093
|
+
kind: "device-becomes"
|
|
18094
|
+
};
|
|
18095
|
+
case "detection": {
|
|
18096
|
+
const { classes, ...rest } = trigger;
|
|
18097
|
+
return {
|
|
18098
|
+
...rest,
|
|
18099
|
+
subjects: classes.map(subjectFromClassName)
|
|
18100
|
+
};
|
|
18101
|
+
}
|
|
18102
|
+
case "stationary": {
|
|
18103
|
+
const { classes, ...rest } = trigger;
|
|
18104
|
+
return {
|
|
18105
|
+
...rest,
|
|
18106
|
+
...classes === void 0 ? {} : { subjects: classes.map(subjectFromClassName) }
|
|
18107
|
+
};
|
|
18108
|
+
}
|
|
18109
|
+
default: return trigger;
|
|
18110
|
+
}
|
|
18111
|
+
}
|
|
18112
|
+
/** An old condition tree as a `when` subtree: `condition` → "is", classes → subjects. */
|
|
18113
|
+
function convertLegacyCondition(condition) {
|
|
18114
|
+
switch (condition.kind) {
|
|
18115
|
+
case "condition": return {
|
|
18116
|
+
...condition,
|
|
18117
|
+
kind: "device-is"
|
|
18118
|
+
};
|
|
18119
|
+
case "stationary-present": {
|
|
18120
|
+
const { classes, ...rest } = condition;
|
|
18121
|
+
return {
|
|
18122
|
+
...rest,
|
|
18123
|
+
...classes === void 0 ? {} : { subjects: classes.map(subjectFromClassName) }
|
|
18124
|
+
};
|
|
18125
|
+
}
|
|
18126
|
+
case "expression": return condition;
|
|
18127
|
+
case "not": return {
|
|
18128
|
+
kind: "not",
|
|
18129
|
+
child: convertLegacyCondition(condition.child)
|
|
18130
|
+
};
|
|
18131
|
+
case "all":
|
|
18132
|
+
case "any": return {
|
|
18133
|
+
kind: condition.kind,
|
|
18134
|
+
children: condition.children.map(convertLegacyCondition)
|
|
18135
|
+
};
|
|
18136
|
+
}
|
|
18137
|
+
}
|
|
18138
|
+
/** `all(any(t1…tn), C)`, or `any(t1…tn)`; a single trigger is not wrapped in `any`. */
|
|
18139
|
+
function convertLegacyWhen(half) {
|
|
18140
|
+
const leaves = half.triggers.map(convertTrigger);
|
|
18141
|
+
const first = leaves[0];
|
|
18142
|
+
const triggers = leaves.length === 1 && first !== void 0 ? first : {
|
|
18143
|
+
kind: "any",
|
|
18144
|
+
children: leaves
|
|
18145
|
+
};
|
|
18146
|
+
if (half.conditions === void 0) return triggers;
|
|
18147
|
+
return {
|
|
18148
|
+
kind: "all",
|
|
18149
|
+
children: [triggers, convertLegacyCondition(half.conditions)]
|
|
18150
|
+
};
|
|
18151
|
+
}
|
|
18152
|
+
/**
|
|
18153
|
+
* The automation RECIPE — what a visually-authored automation is, before it
|
|
18154
|
+
* becomes code.
|
|
18155
|
+
*
|
|
18156
|
+
* This is the data half of `docs/design/2026-08-08-automation-scripts-custom-devices.md`
|
|
18157
|
+
* Phase 6. A recipe is not an engine and never evaluates anything: it is a
|
|
18158
|
+
* declarative description that {@link generateAutomationBlock} compiles to the
|
|
18159
|
+
* TypeScript of an ordinary core block. There is therefore no second rule
|
|
18160
|
+
* engine, no second store and no second runtime — the block runner is the
|
|
18161
|
+
* runtime, `core_blocks` is the store (§2.1).
|
|
18162
|
+
*
|
|
18163
|
+
* Two parts:
|
|
18164
|
+
*
|
|
18165
|
+
* - **`when`** — ONE tree (`./when.ts`) of all/any/not over event leaves
|
|
18166
|
+
* (instants) and state leaves (durations). It replaces the flat trigger list
|
|
18167
|
+
* plus the separate condition tree; the firing rule is in that file and in
|
|
18168
|
+
* ADR "one tree".
|
|
18169
|
+
* - **Actions** — `NcRuleActionSchema`'s two steps, plus the `{kind:'code'}`
|
|
18170
|
+
* fragment of §3.2.2. See {@link AutomationActionSchema} for the ONE place
|
|
18171
|
+
* this had to diverge from "verbatim", and why.
|
|
18172
|
+
*
|
|
18173
|
+
* A recipe stored in the old shape (`triggers` + `conditions`) still LOADS:
|
|
18174
|
+
* {@link AutomationRecipeSchema} (the parse-anywhere schema) converts it on parse. Nothing writes it.
|
|
18175
|
+
*/
|
|
17677
18176
|
/**
|
|
17678
18177
|
* One action step.
|
|
17679
18178
|
*
|
|
@@ -17776,91 +18275,49 @@ var AutomationRunModeSchema = discriminatedUnion("mode", [
|
|
|
17776
18275
|
minutes: number().int().min(1).max(1440)
|
|
17777
18276
|
})
|
|
17778
18277
|
]);
|
|
17779
|
-
var
|
|
17780
|
-
|
|
17781
|
-
conditions: AutomationConditionSchema.optional(),
|
|
18278
|
+
var CurrentAutomationRecipeSchema = object({
|
|
18279
|
+
when: AutomationWhenSchema,
|
|
17782
18280
|
actions: array(AutomationActionSchema),
|
|
17783
18281
|
runMode: AutomationRunModeSchema.optional(),
|
|
17784
18282
|
/** How many run traces the automation keeps (default {@link DEFAULT_TRACE_KEEP}). */
|
|
17785
18283
|
keepTraces: number().int().min(1).max(100).optional()
|
|
17786
18284
|
});
|
|
18285
|
+
/** A recipe as it was stored before the single tree. Read-only: nothing writes this. */
|
|
18286
|
+
var LegacyAutomationRecipeSchema = object({
|
|
18287
|
+
triggers: array(LegacyTriggerSchema),
|
|
18288
|
+
conditions: LegacyConditionSchema.optional(),
|
|
18289
|
+
actions: array(AutomationActionSchema),
|
|
18290
|
+
runMode: AutomationRunModeSchema.optional(),
|
|
18291
|
+
keepTraces: number().int().min(1).max(100).optional()
|
|
18292
|
+
});
|
|
18293
|
+
/** The old shape as the new one, lossless. */
|
|
18294
|
+
function convertLegacyRecipe(legacy) {
|
|
18295
|
+
const { triggers, conditions, ...rest } = legacy;
|
|
18296
|
+
return {
|
|
18297
|
+
when: convertLegacyWhen({
|
|
18298
|
+
triggers,
|
|
18299
|
+
conditions
|
|
18300
|
+
}),
|
|
18301
|
+
...rest
|
|
18302
|
+
};
|
|
18303
|
+
}
|
|
17787
18304
|
/**
|
|
17788
|
-
*
|
|
17789
|
-
*
|
|
17790
|
-
*
|
|
17791
|
-
* `preserveOriginal: false` below is the whole reason this set exists: the
|
|
17792
|
-
* executor maps each raw COCO label onto its macro and DROPS everything else,
|
|
17793
|
-
* so a tracked detection's `className` is always one of {@link MACRO_LABELS}.
|
|
17794
|
-
* Any surface that indexes counts by class name — the ZoneAnalytics occupancy
|
|
17795
|
-
* snapshot's `byClass`, and therefore every occupancy rule — can match nothing
|
|
17796
|
-
* else. Derived from the catalog, never hand-listed, so a new macro joins it by
|
|
17797
|
-
* being declared once.
|
|
17798
|
-
*
|
|
17799
|
-
* Cost of not having it, 2026-08-12: the notification rule editor offered the
|
|
17800
|
-
* full taxonomy for an occupancy class (occupancy is the one condition that
|
|
17801
|
-
* does not go through the engine's macro-expanding `expandClassSelector`), two
|
|
17802
|
-
* live rules were authored on `car`, and both counters read 0 forever.
|
|
18305
|
+
* Where recipes are PARSED (the core-blocks cap, the MCP tool, the literal a
|
|
18306
|
+
* saved block carries): the new shape as it is, or the old shape converted to
|
|
18307
|
+
* it. The output type is always the new one.
|
|
17803
18308
|
*/
|
|
17804
|
-
var
|
|
17805
|
-
{
|
|
17806
|
-
id: "person",
|
|
17807
|
-
name: "Person"
|
|
17808
|
-
},
|
|
17809
|
-
{
|
|
17810
|
-
id: "vehicle",
|
|
17811
|
-
name: "Vehicle"
|
|
17812
|
-
},
|
|
17813
|
-
{
|
|
17814
|
-
id: "animal",
|
|
17815
|
-
name: "Animal"
|
|
17816
|
-
},
|
|
17817
|
-
{
|
|
17818
|
-
id: "package",
|
|
17819
|
-
name: "Package"
|
|
17820
|
-
}
|
|
17821
|
-
].map((l) => l.id));
|
|
17822
|
-
/** True when `className` is a macro the detector can actually emit (and hence a
|
|
17823
|
-
* class a count can be keyed on) — see {@link DETECTION_MACRO_CLASSES}. */
|
|
17824
|
-
function isDetectionMacroClass(className) {
|
|
17825
|
-
return DETECTION_MACRO_CLASSES.has(className.trim().toLowerCase());
|
|
17826
|
-
}
|
|
17827
|
-
var COCO_TO_MACRO = {
|
|
17828
|
-
mapping: {
|
|
17829
|
-
person: "person",
|
|
17830
|
-
bicycle: "vehicle",
|
|
17831
|
-
car: "vehicle",
|
|
17832
|
-
motorcycle: "vehicle",
|
|
17833
|
-
airplane: "vehicle",
|
|
17834
|
-
bus: "vehicle",
|
|
17835
|
-
train: "vehicle",
|
|
17836
|
-
truck: "vehicle",
|
|
17837
|
-
boat: "vehicle",
|
|
17838
|
-
bird: "animal",
|
|
17839
|
-
cat: "animal",
|
|
17840
|
-
dog: "animal",
|
|
17841
|
-
horse: "animal",
|
|
17842
|
-
sheep: "animal",
|
|
17843
|
-
cow: "animal",
|
|
17844
|
-
elephant: "animal",
|
|
17845
|
-
bear: "animal",
|
|
17846
|
-
zebra: "animal",
|
|
17847
|
-
giraffe: "animal",
|
|
17848
|
-
suitcase: "package",
|
|
17849
|
-
backpack: "package",
|
|
17850
|
-
handbag: "package"
|
|
17851
|
-
},
|
|
17852
|
-
preserveOriginal: false
|
|
17853
|
-
};
|
|
18309
|
+
var AutomationRecipeSchema = union([CurrentAutomationRecipeSchema, LegacyAutomationRecipeSchema.transform(convertLegacyRecipe)]);
|
|
17854
18310
|
new Set(Object.values(COCO_TO_MACRO.mapping));
|
|
17855
18311
|
/**
|
|
17856
18312
|
* Run traces — what an automation (or, later, an Action run) DID, node by node,
|
|
17857
18313
|
* so the editor can paint every block green or red with its reason.
|
|
17858
18314
|
*
|
|
17859
|
-
* A trace is data, not a log: it covers the WHOLE tree — the
|
|
17860
|
-
* every
|
|
17861
|
-
* short-circuit never reached), the run-mode verdict and every action
|
|
17862
|
-
* each addressed by a stable path (`
|
|
17863
|
-
* for an Action run).
|
|
18315
|
+
* A trace is data, not a log: it covers the WHOLE tree — the event leaf that
|
|
18316
|
+
* fired, every node of the `when` tree (containers and leaves, including the
|
|
18317
|
+
* ones a short-circuit never reached), the run-mode verdict and every action
|
|
18318
|
+
* step — each addressed by a stable path (`when.0.1`, `actions.2`, or `steps.N`
|
|
18319
|
+
* for an Action run). Traces written before the single tree carry
|
|
18320
|
+
* `conditions.*` paths and still parse. Skipped
|
|
17864
18321
|
* evaluations are traced too, and identical consecutive skips collapse into a
|
|
17865
18322
|
* repeat count so a trigger that fails every 5 minutes cannot flush real runs.
|
|
17866
18323
|
*
|
|
@@ -17892,6 +18349,8 @@ var TraceNodeOutcomeSchema = _enum([
|
|
|
17892
18349
|
]);
|
|
17893
18350
|
var AutomationTriggerTraceSchema = object({
|
|
17894
18351
|
kind: string().min(1),
|
|
18352
|
+
/** The event leaf that fired (`when`, `when.0.1`); absent on traces written before the single tree. */
|
|
18353
|
+
path: string().min(1).optional(),
|
|
17895
18354
|
outcome: _enum(["pass", "fail"]),
|
|
17896
18355
|
/** Why an event was rejected ("class person not in [dog]") or what fired. */
|
|
17897
18356
|
reason: string(),
|
|
@@ -17899,15 +18358,23 @@ var AutomationTriggerTraceSchema = object({
|
|
|
17899
18358
|
vars: record(string(), TraceValueSchema)
|
|
17900
18359
|
});
|
|
17901
18360
|
var AutomationConditionTraceNodeSchema = object({
|
|
17902
|
-
/** `
|
|
18361
|
+
/** `when` for the root, `when.<i>` for its i-th child, … (`conditions…` on an old trace). */
|
|
17903
18362
|
path: string().min(1),
|
|
17904
18363
|
kind: _enum([
|
|
17905
18364
|
"all",
|
|
17906
18365
|
"any",
|
|
17907
18366
|
"not",
|
|
17908
18367
|
"condition",
|
|
18368
|
+
"device-is",
|
|
17909
18369
|
"expression",
|
|
17910
|
-
"stationary-present"
|
|
18370
|
+
"stationary-present",
|
|
18371
|
+
"device-becomes",
|
|
18372
|
+
"device-event",
|
|
18373
|
+
"schedule",
|
|
18374
|
+
"interval",
|
|
18375
|
+
"manual",
|
|
18376
|
+
"detection",
|
|
18377
|
+
"stationary"
|
|
17911
18378
|
]),
|
|
17912
18379
|
outcome: TraceNodeOutcomeSchema,
|
|
17913
18380
|
reason: string(),
|
|
@@ -17941,6 +18408,12 @@ var AutomationStepTraceSchema = object({
|
|
|
17941
18408
|
deviceId: number().int().optional(),
|
|
17942
18409
|
startedAt: number().optional(),
|
|
17943
18410
|
endedAt: number().optional(),
|
|
18411
|
+
/**
|
|
18412
|
+
* The parameters the step SENT, after `{{vars.x}}` substitution — what the
|
|
18413
|
+
* device was actually asked. Bounded like trigger `vars`; a secret parameter
|
|
18414
|
+
* is shown as {@link REDACTED_ARG}. Absent on traces written before it existed.
|
|
18415
|
+
*/
|
|
18416
|
+
args: record(string(), TraceValueSchema).optional(),
|
|
17944
18417
|
outcome: _enum([
|
|
17945
18418
|
"ok",
|
|
17946
18419
|
"error",
|
|
@@ -18690,6 +19163,23 @@ method(object({
|
|
|
18690
19163
|
addonId: string(),
|
|
18691
19164
|
nodeId: string().optional()
|
|
18692
19165
|
}), SettingsSchemaWithValuesSchema.nullable()), method(object({
|
|
19166
|
+
addonId: string(),
|
|
19167
|
+
nodeId: string().optional()
|
|
19168
|
+
}), object({ keys: array(string()) }).nullable(), { auth: "admin" }), method(object({
|
|
19169
|
+
addonId: string(),
|
|
19170
|
+
nodeId: string().optional(),
|
|
19171
|
+
keys: array(string())
|
|
19172
|
+
}), object({
|
|
19173
|
+
removed: array(string()),
|
|
19174
|
+
refused: array(object({
|
|
19175
|
+
key: string(),
|
|
19176
|
+
reason: string()
|
|
19177
|
+
})),
|
|
19178
|
+
secretsCleared: number()
|
|
19179
|
+
}), {
|
|
19180
|
+
kind: "mutation",
|
|
19181
|
+
auth: "admin"
|
|
19182
|
+
}), method(object({
|
|
18693
19183
|
addonId: string(),
|
|
18694
19184
|
deviceId: number(),
|
|
18695
19185
|
nodeId: string().optional()
|
|
@@ -20144,8 +20634,21 @@ var BrokerProviderInfoSchema = object({
|
|
|
20144
20634
|
* (`{ sessionId }`) drops the session. The dialog that edits a broker
|
|
20145
20635
|
* offers it as the default path; the fields the session fills are
|
|
20146
20636
|
* marked `filledBySignIn` in the kind's settings schema.
|
|
20637
|
+
*
|
|
20638
|
+
* `methods` lists the ways the session can sign in, recommended first:
|
|
20639
|
+
* `'device-code'` adds `POST {basePath}/code/start` (body: the form's
|
|
20640
|
+
* settings) answering `{ sessionId, userCode, verificationUrl,
|
|
20641
|
+
* expiresAt }` — the operator types `userCode` at `verificationUrl` on
|
|
20642
|
+
* any device, and the same `status` / `commit` / `cancel` routes follow
|
|
20643
|
+
* (status then carries `method`, `userCode`, `verificationUrl`,
|
|
20644
|
+
* `expiresAt` and the phases `'awaiting-code'` / `'expired'`);
|
|
20645
|
+
* `'proxy'` is the `{basePath}/start` flow above. Absent means
|
|
20646
|
+
* `['proxy']`.
|
|
20147
20647
|
*/
|
|
20148
|
-
signIn: object({
|
|
20648
|
+
signIn: object({
|
|
20649
|
+
basePath: string().min(1),
|
|
20650
|
+
methods: array(_enum(["device-code", "proxy"])).optional()
|
|
20651
|
+
}).optional()
|
|
20149
20652
|
}))
|
|
20150
20653
|
});
|
|
20151
20654
|
var ListInputSchema = object({
|
|
@@ -22736,6 +23239,8 @@ var StorageKindSchema = object({
|
|
|
22736
23239
|
"orphaned",
|
|
22737
23240
|
"dropped"
|
|
22738
23241
|
]),
|
|
23242
|
+
/** An owner declared this kind since the engine started. */
|
|
23243
|
+
declaredThisBoot: boolean(),
|
|
22739
23244
|
/** `null` when the caller asked for no counts (`counts: false`). */
|
|
22740
23245
|
rows: number().int().nonnegative().nullable(),
|
|
22741
23246
|
/** Rows x the average size of a sample; null for an empty kind. */
|
|
@@ -22747,6 +23252,51 @@ var StorageKindSchema = object({
|
|
|
22747
23252
|
/** The whole declaration, secret paths and entry descriptor included (the entries service builds its handle from it). */
|
|
22748
23253
|
declaration: RecordKindDeclarationSchema
|
|
22749
23254
|
});
|
|
23255
|
+
_enum([
|
|
23256
|
+
"orphaned",
|
|
23257
|
+
"stale",
|
|
23258
|
+
"unknown"
|
|
23259
|
+
]);
|
|
23260
|
+
/** A record kind nobody declared since its owner started, or whose owner is gone. */
|
|
23261
|
+
var StaleKindFindingSchema = object({
|
|
23262
|
+
owner: string(),
|
|
23263
|
+
kind: string(),
|
|
23264
|
+
/** `unknown`: the owner could not be judged (not running, or its state unreadable) - never dropped. */
|
|
23265
|
+
verdict: _enum(["orphaned", "unknown"]),
|
|
23266
|
+
reason: string(),
|
|
23267
|
+
rows: number().int().nonnegative().nullable(),
|
|
23268
|
+
/** local-auth's tables are never dropped by this audit. */
|
|
23269
|
+
protected: boolean()
|
|
23270
|
+
});
|
|
23271
|
+
/** A stored global-settings key the running addon no longer declares. */
|
|
23272
|
+
var StaleSettingsKeyFindingSchema = object({
|
|
23273
|
+
addonId: string(),
|
|
23274
|
+
/** The stored key as written, a per-node `<key>@<nodeId>` suffix included. */
|
|
23275
|
+
key: string(),
|
|
23276
|
+
/**
|
|
23277
|
+
* Keychain refs whose ONLY marker sits under this key: in use by stale data,
|
|
23278
|
+
* not orphans yet. Removing the key releases them.
|
|
23279
|
+
*/
|
|
23280
|
+
secretRefs: array(string())
|
|
23281
|
+
});
|
|
23282
|
+
/** An addon the audit could not judge, with the reason. Never reported as stale. */
|
|
23283
|
+
var StaleUnknownSchema = object({
|
|
23284
|
+
subject: string(),
|
|
23285
|
+
reason: string()
|
|
23286
|
+
});
|
|
23287
|
+
var StaleDataReportSchema = object({
|
|
23288
|
+
/** Epoch ms of the last finished scan; `null` before the first. */
|
|
23289
|
+
scannedAt: number().nullable(),
|
|
23290
|
+
scanning: boolean(),
|
|
23291
|
+
trigger: _enum([
|
|
23292
|
+
"boot",
|
|
23293
|
+
"interval",
|
|
23294
|
+
"manual"
|
|
23295
|
+
]).nullable(),
|
|
23296
|
+
kinds: array(StaleKindFindingSchema),
|
|
23297
|
+
settingsKeys: array(StaleSettingsKeyFindingSchema),
|
|
23298
|
+
unknown: array(StaleUnknownSchema)
|
|
23299
|
+
});
|
|
22750
23300
|
method(object({ ownerPrefix: string().min(1).optional() }), object({ tables: array(StorageTableSchema) }), { auth: "admin" }), method(object({
|
|
22751
23301
|
owner: string().min(1).optional(),
|
|
22752
23302
|
/** `false` skips the per-kind row count (a catalog read only). Default true. */
|
|
@@ -22754,7 +23304,30 @@ method(object({ ownerPrefix: string().min(1).optional() }), object({ tables: arr
|
|
|
22754
23304
|
}), object({ kinds: array(StorageKindSchema) }), { auth: "admin" }), method(RecordQueryInputSchema.extend({
|
|
22755
23305
|
owner: string().min(1),
|
|
22756
23306
|
kind: RecordKindNameSchema
|
|
22757
|
-
}), RecordQueryResultSchema, { auth: "admin" })
|
|
23307
|
+
}), RecordQueryResultSchema, { auth: "admin" }), method(object({}), StaleDataReportSchema, { auth: "admin" }), method(object({}), StaleDataReportSchema, {
|
|
23308
|
+
kind: "mutation",
|
|
23309
|
+
auth: "admin"
|
|
23310
|
+
}), method(object({
|
|
23311
|
+
owner: string().min(1),
|
|
23312
|
+
kind: RecordKindNameSchema
|
|
23313
|
+
}), object({
|
|
23314
|
+
deleted: number().int().nonnegative(),
|
|
23315
|
+
secretsReleased: number().int().nonnegative()
|
|
23316
|
+
}), {
|
|
23317
|
+
kind: "mutation",
|
|
23318
|
+
auth: "admin",
|
|
23319
|
+
caller: "required"
|
|
23320
|
+
}), method(object({
|
|
23321
|
+
addonId: string().min(1),
|
|
23322
|
+
key: string().min(1)
|
|
23323
|
+
}), object({
|
|
23324
|
+
removed: boolean(),
|
|
23325
|
+
secretsCleared: number().int().nonnegative()
|
|
23326
|
+
}), {
|
|
23327
|
+
kind: "mutation",
|
|
23328
|
+
auth: "admin",
|
|
23329
|
+
caller: "required"
|
|
23330
|
+
});
|
|
22758
23331
|
/**
|
|
22759
23332
|
* record-entries - the ONE admin surface for every list of user-created entries
|
|
22760
23333
|
* (D881): notification targets, brokers, LLM profiles, anything an addon
|
|
@@ -22893,6 +23466,12 @@ method(object({
|
|
|
22893
23466
|
}), method(object({ deviceId: number().int() }), object({ refs: array(string()).readonly() }), {
|
|
22894
23467
|
kind: "mutation",
|
|
22895
23468
|
auth: "admin"
|
|
23469
|
+
}), method(object({
|
|
23470
|
+
refs: RefListSchema,
|
|
23471
|
+
onBehalfOf: string().min(1)
|
|
23472
|
+
}), object({ released: number().int() }), {
|
|
23473
|
+
kind: "mutation",
|
|
23474
|
+
auth: "admin"
|
|
22896
23475
|
}), method(object({}), array(KeychainSecretMetaSchema).readonly(), { auth: "admin" }), method(object({}), KeychainStateSchema, { auth: "admin" });
|
|
22897
23476
|
/**
|
|
22898
23477
|
* device-history — the ONE mechanism for numeric history (D850).
|
|
@@ -23682,7 +24261,9 @@ var DiscoveredChildDeviceSchema = lazy(() => object({
|
|
|
23682
24261
|
/** Upstream-system identity + rendering hints for the candidate. */
|
|
23683
24262
|
sourceInfo: SourceInfoSchema.optional(),
|
|
23684
24263
|
/** Nested entity-children for accordion preview — integrations populate, Hubs omit. */
|
|
23685
|
-
children: array(DiscoveredChildDeviceSchema).readonly().optional()
|
|
24264
|
+
children: array(DiscoveredChildDeviceSchema).readonly().optional(),
|
|
24265
|
+
/** `childNativeId` of the gateway candidate in the same list this device sits behind. */
|
|
24266
|
+
parentStableId: string().optional()
|
|
23686
24267
|
}));
|
|
23687
24268
|
/**
|
|
23688
24269
|
* Status block — populated by the integration after each
|
|
@@ -44048,6 +44629,79 @@ object({
|
|
|
44048
44629
|
metadata: record(string(), unknown()).optional()
|
|
44049
44630
|
});
|
|
44050
44631
|
/**
|
|
44632
|
+
* HOW a provider can be found on the network. The provider only DECLARES the
|
|
44633
|
+
* mode; the `local-network` scan engine runs it once for every provider that
|
|
44634
|
+
* asked (one multicast browse, one host sweep) and hands the raw hits back to
|
|
44635
|
+
* `classifyDiscoveryHits`. A provider never opens a discovery socket itself,
|
|
44636
|
+
* except through a `custom` mode.
|
|
44637
|
+
*/
|
|
44638
|
+
var DiscoveryModeSchema = discriminatedUnion("kind", [
|
|
44639
|
+
object({
|
|
44640
|
+
kind: literal("mdns"),
|
|
44641
|
+
/** DNS-SD service type, e.g. `_esphomelib._tcp`. */
|
|
44642
|
+
serviceType: string().min(1),
|
|
44643
|
+
/** Regular expression an instance name must match (case-insensitive). */
|
|
44644
|
+
instancePattern: string().optional()
|
|
44645
|
+
}),
|
|
44646
|
+
object({
|
|
44647
|
+
kind: literal("ws-discovery"),
|
|
44648
|
+
/** Probe types (e.g. `dn:NetworkVideoTransmitter`); omitted = any device. */
|
|
44649
|
+
types: array(string()).optional()
|
|
44650
|
+
}),
|
|
44651
|
+
object({
|
|
44652
|
+
kind: literal("ssdp"),
|
|
44653
|
+
searchTarget: string().min(1)
|
|
44654
|
+
}),
|
|
44655
|
+
object({
|
|
44656
|
+
kind: literal("udp-broadcast"),
|
|
44657
|
+
port: number().int().min(1).max(65535),
|
|
44658
|
+
payloadHex: string().regex(/^([0-9a-fA-F]{2})*$/),
|
|
44659
|
+
/** Port replies arrive on, when the device answers somewhere other than the source port. */
|
|
44660
|
+
listenPort: number().int().min(1).max(65535).optional()
|
|
44661
|
+
}),
|
|
44662
|
+
object({
|
|
44663
|
+
kind: literal("http-probe"),
|
|
44664
|
+
port: number().int().min(1).max(65535),
|
|
44665
|
+
path: string().startsWith("/"),
|
|
44666
|
+
method: _enum(["GET", "POST"]).default("GET"),
|
|
44667
|
+
bodyText: string().optional(),
|
|
44668
|
+
contentType: string().optional(),
|
|
44669
|
+
tls: boolean().default(false),
|
|
44670
|
+
/** Status codes that count as a hit. Omitted = any HTTP answer. */
|
|
44671
|
+
acceptStatus: array(number().int()).optional()
|
|
44672
|
+
}),
|
|
44673
|
+
object({
|
|
44674
|
+
kind: literal("custom"),
|
|
44675
|
+
/** Why the engine cannot do it (an allowlisted exception, e.g. a vendor UDP protocol). */
|
|
44676
|
+
reason: string().min(1)
|
|
44677
|
+
})
|
|
44678
|
+
]);
|
|
44679
|
+
/** What the engine saw on the wire for ONE declared mode; the provider classifies it. */
|
|
44680
|
+
var DiscoveryHitSchema = object({
|
|
44681
|
+
/** Index into the provider's own `getDiscoveryModes()` array. */
|
|
44682
|
+
modeIndex: number().int().min(0),
|
|
44683
|
+
host: string(),
|
|
44684
|
+
port: number().int(),
|
|
44685
|
+
http: object({
|
|
44686
|
+
status: number().int(),
|
|
44687
|
+
headers: record(string(), string()),
|
|
44688
|
+
/** At most 16 KiB. */
|
|
44689
|
+
bodyText: string()
|
|
44690
|
+
}).optional(),
|
|
44691
|
+
mdns: object({
|
|
44692
|
+
instance: string(),
|
|
44693
|
+
host: string(),
|
|
44694
|
+
port: number().int(),
|
|
44695
|
+
txt: record(string(), string())
|
|
44696
|
+
}).optional(),
|
|
44697
|
+
udp: object({ payloadHex: string() }).optional(),
|
|
44698
|
+
wsd: object({
|
|
44699
|
+
xaddrs: array(string()),
|
|
44700
|
+
types: array(string()),
|
|
44701
|
+
scopes: array(string())
|
|
44702
|
+
}).optional()
|
|
44703
|
+
});
|
|
44704
|
+
/**
|
|
44051
44705
|
* Candidate handed back from discovery and accepted by
|
|
44052
44706
|
* `adoptDiscoveredDevice`. Shape mirrors the in-process
|
|
44053
44707
|
* `DiscoveredDevice` interface used by `DeviceDiscovery`.
|
|
@@ -44082,7 +44736,17 @@ var DiscoveryCandidateSchema = object({
|
|
|
44082
44736
|
/** Numeric id of the device this candidate was matched to. Set with `alreadyOnboarded`. */
|
|
44083
44737
|
onboardedDeviceId: number().optional(),
|
|
44084
44738
|
/** Operator-facing name of the matched device, so the UI can say WHICH one it is. */
|
|
44085
|
-
onboardedName: string().optional()
|
|
44739
|
+
onboardedName: string().optional(),
|
|
44740
|
+
/**
|
|
44741
|
+
* This candidate is an INTEGRATION to set up (a gateway, a hub, a controller),
|
|
44742
|
+
* not a device to adopt. Replaces the `prefilledConfig.setupIntegration` marker,
|
|
44743
|
+
* which is still read for one release.
|
|
44744
|
+
*/
|
|
44745
|
+
setupIntegration: boolean().optional(),
|
|
44746
|
+
/** `stableId` of the gateway candidate this device was found BEHIND. */
|
|
44747
|
+
parentStableId: string().optional(),
|
|
44748
|
+
/** `false` = shown for context but not pickable. Default true. */
|
|
44749
|
+
selectable: boolean().optional()
|
|
44086
44750
|
});
|
|
44087
44751
|
/**
|
|
44088
44752
|
* Flat device summary returned by `createDevice` / `adoptDiscoveredDevice`.
|
|
@@ -44135,6 +44799,12 @@ method(_void(), _void(), { kind: "mutation" }), method(_void(), _void(), { kind:
|
|
|
44135
44799
|
}), method(object({}), boolean()), method(object({ params: record(string(), unknown()).optional() }), array(DiscoveryCandidateSchema), {
|
|
44136
44800
|
kind: "mutation",
|
|
44137
44801
|
auth: "admin"
|
|
44802
|
+
}), method(object({}), array(DiscoveryModeSchema)), method(object({
|
|
44803
|
+
hits: array(DiscoveryHitSchema),
|
|
44804
|
+
params: record(string(), unknown()).optional()
|
|
44805
|
+
}), array(DiscoveryCandidateSchema), {
|
|
44806
|
+
kind: "mutation",
|
|
44807
|
+
auth: "admin"
|
|
44138
44808
|
}), method(object({}), CreationSchemaOutputSchema), method(object({}), object({ deviceType: _enum(DeviceType).nullable() })), method(object({ candidate: DiscoveryCandidateSchema }), DeviceSummarySchema, {
|
|
44139
44809
|
kind: "mutation",
|
|
44140
44810
|
auth: "admin"
|
|
@@ -44866,17 +45536,23 @@ method(object({
|
|
|
44866
45536
|
}), method(object({}), object({ providers: array(object({
|
|
44867
45537
|
addonId: string(),
|
|
44868
45538
|
label: string()
|
|
44869
|
-
})).readonly() }), { auth: "admin" }), method(
|
|
44870
|
-
|
|
44871
|
-
|
|
44872
|
-
|
|
44873
|
-
|
|
44874
|
-
|
|
44875
|
-
|
|
44876
|
-
|
|
44877
|
-
}),
|
|
45539
|
+
})).readonly() }), { auth: "admin" }), method(
|
|
45540
|
+
/** `subnets`: extra CIDRs for THIS scan, on top of the hub's own and the saved list. */
|
|
45541
|
+
object({ subnets: array(string()).optional() }),
|
|
45542
|
+
object({ groups: array(object({
|
|
45543
|
+
addonId: string(),
|
|
45544
|
+
label: string(),
|
|
45545
|
+
candidates: array(DiscoveryCandidateSchema).readonly(),
|
|
45546
|
+
error: string().nullable()
|
|
45547
|
+
})).readonly() }),
|
|
45548
|
+
{
|
|
45549
|
+
kind: "mutation",
|
|
45550
|
+
auth: "admin"
|
|
45551
|
+
}
|
|
45552
|
+
), method(object({
|
|
44878
45553
|
addonId: string(),
|
|
44879
|
-
params: record(string(), unknown()).optional()
|
|
45554
|
+
params: record(string(), unknown()).optional(),
|
|
45555
|
+
subnets: array(string()).optional()
|
|
44880
45556
|
}), object({ candidates: array(DiscoveryCandidateSchema).readonly() }), {
|
|
44881
45557
|
kind: "mutation",
|
|
44882
45558
|
auth: "admin"
|
|
@@ -59584,6 +60260,12 @@ var TerminalInstanceInfoSchema = object({
|
|
|
59584
60260
|
instanceId: string(),
|
|
59585
60261
|
cameraStableId: string(),
|
|
59586
60262
|
nodeId: string(),
|
|
60263
|
+
/**
|
|
60264
|
+
* False while the node the instance is bound to is not in the cluster
|
|
60265
|
+
* topology (forgotten, renamed, re-paired). The instance is kept; the
|
|
60266
|
+
* operator re-points it with `updateInstance({ targetNodeId })`.
|
|
60267
|
+
*/
|
|
60268
|
+
nodeInCluster: boolean(),
|
|
59587
60269
|
profileId: string(),
|
|
59588
60270
|
profileLabel: string(),
|
|
59589
60271
|
name: string(),
|
|
@@ -59633,6 +60315,8 @@ method(_void(), array(TerminalProfileInfoSchema).readonly(), { auth: "admin" }),
|
|
|
59633
60315
|
auth: "admin"
|
|
59634
60316
|
}), method(object({
|
|
59635
60317
|
instanceId: string().min(1),
|
|
60318
|
+
/** Re-point the instance to another node; the profile must exist there. */
|
|
60319
|
+
targetNodeId: string().min(1).max(256).optional(),
|
|
59636
60320
|
name: string().trim().min(1).max(160).optional(),
|
|
59637
60321
|
executable: string().max(1024).optional(),
|
|
59638
60322
|
args: array(string().max(2048)).max(64).optional(),
|
|
@@ -66368,7 +67052,9 @@ method(_void(), array(IntegrationWithStateSchema)), method(object({ id: string()
|
|
|
66368
67052
|
id: string(),
|
|
66369
67053
|
settings: record(string(), unknown()),
|
|
66370
67054
|
/** Keys the form's schema declares secret (by type) — keychain-stored (D787). */
|
|
66371
|
-
secretKeys: array(string()).optional()
|
|
67055
|
+
secretKeys: array(string()).optional(),
|
|
67056
|
+
/** The integration's own addon applies the change in-process and asks the hub not to respawn it. */
|
|
67057
|
+
skipRestart: boolean().optional()
|
|
66372
67058
|
}), object({ success: boolean() }), {
|
|
66373
67059
|
kind: "mutation",
|
|
66374
67060
|
auth: "admin"
|
|
@@ -66996,6 +67682,39 @@ var TlsStatusSchema = object({
|
|
|
66996
67682
|
hasCa: boolean()
|
|
66997
67683
|
}).nullable()
|
|
66998
67684
|
});
|
|
67685
|
+
/** One provider's ask of the scan engine: the modes it declared. */
|
|
67686
|
+
var ScanRequestSchema = object({
|
|
67687
|
+
providerId: string().min(1),
|
|
67688
|
+
modes: array(DiscoveryModeSchema)
|
|
67689
|
+
});
|
|
67690
|
+
var ScanErrorSchema = object({
|
|
67691
|
+
/** Absent for a failure that is the scan's own (a bad subnet, a socket that would not open). */
|
|
67692
|
+
providerId: string().optional(),
|
|
67693
|
+
/** The mode family that failed (`mdns`, `http-probe`, …). */
|
|
67694
|
+
mode: string().optional(),
|
|
67695
|
+
message: string()
|
|
67696
|
+
});
|
|
67697
|
+
/** What one scan did, per mode family; the engine logs the same numbers once. */
|
|
67698
|
+
var ScanStatsSchema = object({
|
|
67699
|
+
hostsProbed: number().int(),
|
|
67700
|
+
hits: number().int(),
|
|
67701
|
+
timeouts: number().int(),
|
|
67702
|
+
byMode: record(string(), object({
|
|
67703
|
+
probed: number().int(),
|
|
67704
|
+
hits: number().int(),
|
|
67705
|
+
timeouts: number().int()
|
|
67706
|
+
}))
|
|
67707
|
+
});
|
|
67708
|
+
var ScanNetworkResultSchema = object({
|
|
67709
|
+
hits: array(object({
|
|
67710
|
+
providerId: string(),
|
|
67711
|
+
hit: DiscoveryHitSchema
|
|
67712
|
+
})),
|
|
67713
|
+
/** CIDRs actually covered: the hub's own /24s, the saved list and the per-call list. */
|
|
67714
|
+
subnetsScanned: array(string()),
|
|
67715
|
+
errors: array(ScanErrorSchema),
|
|
67716
|
+
stats: ScanStatsSchema
|
|
67717
|
+
});
|
|
66999
67718
|
method(_void(), ListResultSchema), method(_void(), PreferredSchema), method(object({
|
|
67000
67719
|
/**
|
|
67001
67720
|
* LEGACY HINT — do not send from new code. Kept optional so clients
|
|
@@ -67050,6 +67769,16 @@ method(_void(), ListResultSchema), method(_void(), PreferredSchema), method(obje
|
|
|
67050
67769
|
}), method(_void(), object({ pem: string() })), method(_void(), TlsStatusSchema, {
|
|
67051
67770
|
kind: "mutation",
|
|
67052
67771
|
auth: "admin"
|
|
67772
|
+
}), method(object({
|
|
67773
|
+
requests: array(ScanRequestSchema),
|
|
67774
|
+
subnets: array(string()).optional()
|
|
67775
|
+
}), ScanNetworkResultSchema, {
|
|
67776
|
+
kind: "mutation",
|
|
67777
|
+
auth: "admin",
|
|
67778
|
+
timeoutMs: 9e4
|
|
67779
|
+
}), method(_void(), object({ subnets: array(string()) }), { auth: "admin" }), method(object({ subnets: array(string()) }), object({ subnets: array(string()) }), {
|
|
67780
|
+
kind: "mutation",
|
|
67781
|
+
auth: "admin"
|
|
67053
67782
|
}), method(_void(), TlsStatusSchema, {
|
|
67054
67783
|
kind: "mutation",
|
|
67055
67784
|
auth: "admin"
|
|
@@ -70850,7 +71579,7 @@ var runningStateCapability = {
|
|
|
70850
71579
|
volatileStateFields: ["lastFetchedAt"],
|
|
70851
71580
|
customize: runningCustomize
|
|
70852
71581
|
};
|
|
70853
|
-
DeviceType.Camera, DeviceType.Sensor, DeviceType.Switch, method(object({ deviceId: number().int().nonnegative() }), object({ success: literal(true) }), {
|
|
71582
|
+
DeviceType.Camera, DeviceType.Sensor, DeviceType.Switch, DeviceType.Gateway, method(object({ deviceId: number().int().nonnegative() }), object({ success: literal(true) }), {
|
|
70854
71583
|
kind: "mutation",
|
|
70855
71584
|
auth: "admin"
|
|
70856
71585
|
});
|
|
@@ -75543,52 +76272,89 @@ btn("power", 0, 0, {
|
|
|
75543
76272
|
role: "power",
|
|
75544
76273
|
shape: "round",
|
|
75545
76274
|
tone: "danger"
|
|
75546
|
-
}), btn("up", 0, 1, {
|
|
76275
|
+
}), btn("up", 0, 1, {
|
|
76276
|
+
role: "up",
|
|
76277
|
+
icon: "chevron-up"
|
|
76278
|
+
}), btn("left", 1, 0, {
|
|
76279
|
+
role: "left",
|
|
76280
|
+
icon: "chevron-left"
|
|
76281
|
+
}), btn("ok", 1, 1, {
|
|
75547
76282
|
role: "ok",
|
|
75548
76283
|
shape: "round",
|
|
75549
76284
|
tone: "accent"
|
|
75550
|
-
}), btn("right", 1, 2, {
|
|
76285
|
+
}), btn("right", 1, 2, {
|
|
76286
|
+
role: "right",
|
|
76287
|
+
icon: "chevron-right"
|
|
76288
|
+
}), btn("down", 2, 1, {
|
|
76289
|
+
role: "down",
|
|
76290
|
+
icon: "chevron-down"
|
|
76291
|
+
}), rocker("core:rocker-volume-v", "Volume rocker", "Bilanciere volume", "rocker-v", "VOL", [btn("up", 0, 0, {
|
|
75551
76292
|
role: "volume_up",
|
|
76293
|
+
icon: "plus",
|
|
75552
76294
|
shape: "pill"
|
|
75553
76295
|
}), btn("down", 1, 0, {
|
|
75554
76296
|
role: "volume_down",
|
|
76297
|
+
icon: "minus",
|
|
75555
76298
|
shape: "pill"
|
|
75556
76299
|
})], {
|
|
75557
76300
|
rows: 2,
|
|
75558
76301
|
cols: 1
|
|
75559
76302
|
}), rocker("core:rocker-channel-v", "Channel rocker", "Bilanciere canali", "rocker-v", "CH", [btn("up", 0, 0, {
|
|
75560
76303
|
role: "channel_up",
|
|
76304
|
+
icon: "chevron-up",
|
|
75561
76305
|
shape: "pill"
|
|
75562
76306
|
}), btn("down", 1, 0, {
|
|
75563
76307
|
role: "channel_down",
|
|
76308
|
+
icon: "chevron-down",
|
|
75564
76309
|
shape: "pill"
|
|
75565
76310
|
})], {
|
|
75566
76311
|
rows: 2,
|
|
75567
76312
|
cols: 1
|
|
75568
76313
|
}), rocker("core:rocker-h", "Minus / plus rocker", "Bilanciere meno / più", "rocker-h", null, [btn("minus", 0, 0, {
|
|
75569
76314
|
role: "custom:minus",
|
|
75570
|
-
label: "
|
|
76315
|
+
label: "Minus",
|
|
76316
|
+
icon: "minus",
|
|
75571
76317
|
shape: "pill"
|
|
75572
76318
|
}), btn("plus", 0, 1, {
|
|
75573
76319
|
role: "custom:plus",
|
|
75574
|
-
label: "
|
|
76320
|
+
label: "Plus",
|
|
76321
|
+
icon: "plus",
|
|
75575
76322
|
shape: "pill"
|
|
75576
76323
|
})], {
|
|
75577
76324
|
rows: 1,
|
|
75578
76325
|
cols: 2
|
|
75579
76326
|
}), [...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, {
|
|
75580
76327
|
role: "custom:color_red",
|
|
76328
|
+
label: "Red",
|
|
75581
76329
|
tone: "red"
|
|
75582
76330
|
}), btn("green", 0, 1, {
|
|
75583
76331
|
role: "custom:color_green",
|
|
76332
|
+
label: "Green",
|
|
75584
76333
|
tone: "green"
|
|
75585
76334
|
}), btn("yellow", 0, 2, {
|
|
75586
76335
|
role: "custom:color_yellow",
|
|
76336
|
+
label: "Yellow",
|
|
75587
76337
|
tone: "yellow"
|
|
75588
76338
|
}), btn("blue", 0, 3, {
|
|
75589
76339
|
role: "custom:color_blue",
|
|
76340
|
+
label: "Blue",
|
|
75590
76341
|
tone: "blue"
|
|
75591
|
-
}), btn("rewind", 0, 0, {
|
|
76342
|
+
}), btn("rewind", 0, 0, {
|
|
76343
|
+
role: "rewind",
|
|
76344
|
+
icon: "rewind"
|
|
76345
|
+
}), btn("play", 0, 1, {
|
|
76346
|
+
role: "play",
|
|
76347
|
+
icon: "play"
|
|
76348
|
+
}), btn("pause", 0, 2, {
|
|
76349
|
+
role: "pause",
|
|
76350
|
+
icon: "pause"
|
|
76351
|
+
}), btn("forward", 0, 3, {
|
|
76352
|
+
role: "fast_forward",
|
|
76353
|
+
icon: "fast-forward"
|
|
76354
|
+
}), btn("stop", 0, 4, {
|
|
76355
|
+
role: "stop",
|
|
76356
|
+
icon: "square"
|
|
76357
|
+
}), [
|
|
75592
76358
|
1,
|
|
75593
76359
|
2,
|
|
75594
76360
|
3,
|
|
@@ -75604,7 +76370,7 @@ discriminatedUnion("kind", [object({
|
|
|
75604
76370
|
})]);
|
|
75605
76371
|
DeviceFeature.FanSpeed, DeviceFeature.FanPreset, DeviceFeature.FanDirection, DeviceFeature.FanOscillating, DeviceFeature.CoverPositionable, DeviceFeature.CoverTilt, DeviceFeature.ValvePositionable, DeviceFeature.MediaPlayerVolume, DeviceFeature.ClimateFanMode;
|
|
75606
76372
|
SOURCE_CAPS.filter((cap) => cap !== "switch" && cap !== "motion");
|
|
75607
|
-
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;
|
|
76373
|
+
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;
|
|
75608
76374
|
String.raw`rose\(active(\d+), changed(\d+), (\d+(?:\.\d+)?)\)`;
|
|
75609
76375
|
DeviceRole.BinarySensor, DeviceRole.MotionSensor;
|
|
75610
76376
|
new Set(CAP_NAMES);
|
|
@@ -76776,7 +77542,7 @@ var DeclaredDevices = class {
|
|
|
76776
77542
|
return removed;
|
|
76777
77543
|
}
|
|
76778
77544
|
};
|
|
76779
|
-
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;
|
|
77545
|
+
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;
|
|
76780
77546
|
new Set(Object.values(DeviceType));
|
|
76781
77547
|
Object.freeze({
|
|
76782
77548
|
"accessories.getStatus": {
|
|
@@ -77164,6 +77930,13 @@ Object.freeze({
|
|
|
77164
77930
|
access: "create",
|
|
77165
77931
|
role: "admin"
|
|
77166
77932
|
},
|
|
77933
|
+
"addonSettings.getDeclaredSettingsKeys": {
|
|
77934
|
+
capName: "addon-settings",
|
|
77935
|
+
capScope: "system",
|
|
77936
|
+
addonId: null,
|
|
77937
|
+
access: "view",
|
|
77938
|
+
role: "admin"
|
|
77939
|
+
},
|
|
77167
77940
|
"addonSettings.getDeviceSettings": {
|
|
77168
77941
|
capName: "addon-settings",
|
|
77169
77942
|
capScope: "system",
|
|
@@ -77185,6 +77958,13 @@ Object.freeze({
|
|
|
77185
77958
|
access: "view",
|
|
77186
77959
|
role: "admin"
|
|
77187
77960
|
},
|
|
77961
|
+
"addonSettings.unsetStoredSettingsKeys": {
|
|
77962
|
+
capName: "addon-settings",
|
|
77963
|
+
capScope: "system",
|
|
77964
|
+
addonId: null,
|
|
77965
|
+
access: "create",
|
|
77966
|
+
role: "admin"
|
|
77967
|
+
},
|
|
77188
77968
|
"addonSettings.updateDeviceSettings": {
|
|
77189
77969
|
capName: "addon-settings",
|
|
77190
77970
|
capScope: "system",
|
|
@@ -79600,6 +80380,13 @@ Object.freeze({
|
|
|
79600
80380
|
access: "create",
|
|
79601
80381
|
role: "admin"
|
|
79602
80382
|
},
|
|
80383
|
+
"deviceProvider.classifyDiscoveryHits": {
|
|
80384
|
+
capName: "device-provider",
|
|
80385
|
+
capScope: "system",
|
|
80386
|
+
addonId: null,
|
|
80387
|
+
access: "create",
|
|
80388
|
+
role: "admin"
|
|
80389
|
+
},
|
|
79603
80390
|
"deviceProvider.createDevice": {
|
|
79604
80391
|
capName: "device-provider",
|
|
79605
80392
|
capScope: "system",
|
|
@@ -79628,6 +80415,13 @@ Object.freeze({
|
|
|
79628
80415
|
access: "view",
|
|
79629
80416
|
role: "admin"
|
|
79630
80417
|
},
|
|
80418
|
+
"deviceProvider.getDiscoveryModes": {
|
|
80419
|
+
capName: "device-provider",
|
|
80420
|
+
capScope: "system",
|
|
80421
|
+
addonId: null,
|
|
80422
|
+
access: "view",
|
|
80423
|
+
role: "admin"
|
|
80424
|
+
},
|
|
79631
80425
|
"deviceProvider.getDiscoveryParamsSchema": {
|
|
79632
80426
|
capName: "device-provider",
|
|
79633
80427
|
capScope: "system",
|
|
@@ -80405,6 +81199,13 @@ Object.freeze({
|
|
|
80405
81199
|
access: "create",
|
|
80406
81200
|
role: "admin"
|
|
80407
81201
|
},
|
|
81202
|
+
"keychain.releaseRecordRefs": {
|
|
81203
|
+
capName: "keychain",
|
|
81204
|
+
capScope: "system",
|
|
81205
|
+
addonId: null,
|
|
81206
|
+
access: "create",
|
|
81207
|
+
role: "admin"
|
|
81208
|
+
},
|
|
80408
81209
|
"keychain.resolve": {
|
|
80409
81210
|
capName: "keychain",
|
|
80410
81211
|
capScope: "system",
|
|
@@ -80825,6 +81626,13 @@ Object.freeze({
|
|
|
80825
81626
|
access: "view",
|
|
80826
81627
|
role: "admin"
|
|
80827
81628
|
},
|
|
81629
|
+
"localNetwork.getScanSubnets": {
|
|
81630
|
+
capName: "local-network",
|
|
81631
|
+
capScope: "system",
|
|
81632
|
+
addonId: null,
|
|
81633
|
+
access: "view",
|
|
81634
|
+
role: "admin"
|
|
81635
|
+
},
|
|
80828
81636
|
"localNetwork.getTlsStatus": {
|
|
80829
81637
|
capName: "local-network",
|
|
80830
81638
|
capScope: "system",
|
|
@@ -80874,6 +81682,13 @@ Object.freeze({
|
|
|
80874
81682
|
access: "create",
|
|
80875
81683
|
role: "admin"
|
|
80876
81684
|
},
|
|
81685
|
+
"localNetwork.scanNetwork": {
|
|
81686
|
+
capName: "local-network",
|
|
81687
|
+
capScope: "system",
|
|
81688
|
+
addonId: null,
|
|
81689
|
+
access: "create",
|
|
81690
|
+
role: "admin"
|
|
81691
|
+
},
|
|
80877
81692
|
"localNetwork.setAddressRole": {
|
|
80878
81693
|
capName: "local-network",
|
|
80879
81694
|
capScope: "system",
|
|
@@ -80895,6 +81710,13 @@ Object.freeze({
|
|
|
80895
81710
|
access: "create",
|
|
80896
81711
|
role: "admin"
|
|
80897
81712
|
},
|
|
81713
|
+
"localNetwork.setScanSubnets": {
|
|
81714
|
+
capName: "local-network",
|
|
81715
|
+
capScope: "system",
|
|
81716
|
+
addonId: null,
|
|
81717
|
+
access: "create",
|
|
81718
|
+
role: "admin"
|
|
81719
|
+
},
|
|
80898
81720
|
"localNetwork.setViewerEndpoints": {
|
|
80899
81721
|
capName: "local-network",
|
|
80900
81722
|
capScope: "system",
|
|
@@ -85116,6 +85938,13 @@ Object.freeze({
|
|
|
85116
85938
|
access: "create",
|
|
85117
85939
|
role: "admin"
|
|
85118
85940
|
},
|
|
85941
|
+
"storageAdmin.dropOrphanedKind": {
|
|
85942
|
+
capName: "storage-admin",
|
|
85943
|
+
capScope: "system",
|
|
85944
|
+
addonId: null,
|
|
85945
|
+
access: "delete",
|
|
85946
|
+
role: "admin"
|
|
85947
|
+
},
|
|
85119
85948
|
"storageAdmin.listKinds": {
|
|
85120
85949
|
capName: "storage-admin",
|
|
85121
85950
|
capScope: "system",
|
|
@@ -85137,6 +85966,27 @@ Object.freeze({
|
|
|
85137
85966
|
access: "view",
|
|
85138
85967
|
role: "admin"
|
|
85139
85968
|
},
|
|
85969
|
+
"storageAdmin.scanStaleData": {
|
|
85970
|
+
capName: "storage-admin",
|
|
85971
|
+
capScope: "system",
|
|
85972
|
+
addonId: null,
|
|
85973
|
+
access: "create",
|
|
85974
|
+
role: "admin"
|
|
85975
|
+
},
|
|
85976
|
+
"storageAdmin.staleDataReport": {
|
|
85977
|
+
capName: "storage-admin",
|
|
85978
|
+
capScope: "system",
|
|
85979
|
+
addonId: null,
|
|
85980
|
+
access: "view",
|
|
85981
|
+
role: "admin"
|
|
85982
|
+
},
|
|
85983
|
+
"storageAdmin.unsetStaleSettingsKey": {
|
|
85984
|
+
capName: "storage-admin",
|
|
85985
|
+
capScope: "system",
|
|
85986
|
+
addonId: null,
|
|
85987
|
+
access: "create",
|
|
85988
|
+
role: "admin"
|
|
85989
|
+
},
|
|
85140
85990
|
"storageEvictable.evict": {
|
|
85141
85991
|
capName: "storage-evictable",
|
|
85142
85992
|
capScope: "system",
|
|
@@ -90833,7 +91683,7 @@ function projectAction(cap, action) {
|
|
|
90833
91683
|
};
|
|
90834
91684
|
}
|
|
90835
91685
|
Object.entries(CAP_VOCABULARY_BY_NAME).flatMap(([cap, entry]) => entry.scope === "device" ? (entry.actions ?? []).map((a) => projectAction(cap, a)) : []);
|
|
90836
|
-
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;
|
|
91686
|
+
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;
|
|
90837
91687
|
DeviceFeature.BatteryOperated;
|
|
90838
91688
|
DeviceType.Washer, DeviceType.Dryer, DeviceType.Dishwasher;
|
|
90839
91689
|
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.";
|