@camstack/addon-training 0.1.112 → 0.1.114
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +12 -0
- package/dist/{MotionZonesSettings-1jL3cNrP.mjs → MotionZonesSettings-Fo1pD1Rt.mjs} +2 -2
- package/dist/{PrivacyMaskSettings-B5sDvjd1.mjs → PrivacyMaskSettings-CxJF-sR6.mjs} +2 -2
- package/dist/{SceneMonitorEditor-DUupJZPg.mjs → SceneMonitorEditor-BVjgmQ6j.mjs} +2 -2
- package/dist/_stub.js +5407 -5206
- package/dist/{_virtual_mf-localSharedImportMap___mfe_internal__addon_training_page-CcSHMntB.mjs → _virtual_mf-localSharedImportMap___mfe_internal__addon_training_page-Bf_j8H4f.mjs} +3 -3
- package/dist/_virtual_mf___mfe_internal__addon_training_page__loadShare___mf_0_camstack_mf_1_types__loadShare__.js-CMfDB80q.mjs +26 -0
- package/dist/{dist-BWaaetIL.js → dist-BmSTdM6f.js} +909 -115
- package/dist/{dist-DP3QaLL9.mjs → dist-Dp5lPNFN.mjs} +909 -115
- package/dist/{hostInit-CL4HR5_U.mjs → hostInit-DT20geoq.mjs} +2 -2
- package/dist/index.js +1 -1
- package/dist/orchestrator/training.addon.js +1 -1
- package/dist/orchestrator/training.addon.mjs +1 -1
- package/dist/{player-overlays-Db2cJVG2.mjs → player-overlays-DVT_LAXt.mjs} +1 -1
- package/dist/providers/modal/training-modal.addon.js +1 -1
- package/dist/providers/modal/training-modal.addon.mjs +1 -1
- package/dist/remoteEntry.js +1 -1
- package/dist/{responsive-CqQQYlZD.mjs → responsive-DhFXZ4Mn.mjs} +1 -1
- package/dist/{scene-monitor-copy-D-mtbfGW.mjs → scene-monitor-copy-Busxg-ds.mjs} +1 -1
- package/dist/{virtual_mf-REMOTE_ENTRY_ID___mfe_internal__addon_training_page__remoteEntry_js-EkAqF5M1.mjs → virtual_mf-REMOTE_ENTRY_ID___mfe_internal__addon_training_page__remoteEntry_js-CB2h_-hR.mjs} +1 -1
- package/package.json +1 -1
- package/dist/_virtual_mf___mfe_internal__addon_training_page__loadShare___mf_0_camstack_mf_1_types__loadShare__.js-os6FZfGz.mjs +0 -26
|
@@ -5588,7 +5588,7 @@ var ZodIssueCode = {
|
|
|
5588
5588
|
var ZodFirstPartyTypeKind;
|
|
5589
5589
|
ZodFirstPartyTypeKind || (ZodFirstPartyTypeKind = {});
|
|
5590
5590
|
//#endregion
|
|
5591
|
-
//#region ../types/dist/sleep-
|
|
5591
|
+
//#region ../types/dist/sleep-CeyhrcOk.mjs
|
|
5592
5592
|
/**
|
|
5593
5593
|
* The audio chunk plane's byte format, and the ONE expansion from a coded
|
|
5594
5594
|
* window to float samples (D455).
|
|
@@ -7655,6 +7655,7 @@ var BaseAddon = class {
|
|
|
7655
7655
|
* a warning and falls back rather than crashing boot.
|
|
7656
7656
|
*/
|
|
7657
7657
|
state(key, schema, fallback) {
|
|
7658
|
+
this._declaredStateKeys.add(key);
|
|
7658
7659
|
return createDurableState({
|
|
7659
7660
|
key,
|
|
7660
7661
|
schema,
|
|
@@ -7670,6 +7671,96 @@ var BaseAddon = class {
|
|
|
7670
7671
|
} })
|
|
7671
7672
|
});
|
|
7672
7673
|
}
|
|
7674
|
+
/** Durable-state keys this process registered through {@link state}. */
|
|
7675
|
+
_declaredStateKeys = /* @__PURE__ */ new Set();
|
|
7676
|
+
/**
|
|
7677
|
+
* Stale-data audit: every global-settings key this addon still declares —
|
|
7678
|
+
* constructor defaults, settings-schema fields (layout containers included),
|
|
7679
|
+
* durable-state keys and the root of each `secretStatePaths` entry. Answered
|
|
7680
|
+
* here, in the addon's own process, so the hub keeps no copy of it.
|
|
7681
|
+
*/
|
|
7682
|
+
async getDeclaredSettingsKeys() {
|
|
7683
|
+
return { keys: [...this.declaredKeySet()].toSorted() };
|
|
7684
|
+
}
|
|
7685
|
+
declaredKeySet() {
|
|
7686
|
+
const keys = new Set(Object.keys(this.defaults));
|
|
7687
|
+
const schema = this.globalSettingsSchema();
|
|
7688
|
+
if (schema) for (const section of schema.sections) for (const key of collectFieldKeys(section.fields)) keys.add(key);
|
|
7689
|
+
for (const key of this._declaredStateKeys) keys.add(key);
|
|
7690
|
+
for (const path of this.secretStatePaths) {
|
|
7691
|
+
const root = path.split(/[.[]/, 1)[0];
|
|
7692
|
+
if (root) keys.add(root);
|
|
7693
|
+
}
|
|
7694
|
+
return keys;
|
|
7695
|
+
}
|
|
7696
|
+
/**
|
|
7697
|
+
* Stale-data audit: remove stored global-settings keys the addon no longer
|
|
7698
|
+
* declares, and clear the keychain values their markers held — except a value
|
|
7699
|
+
* a surviving key still points at. A declared or absent key is refused.
|
|
7700
|
+
*/
|
|
7701
|
+
async unsetStoredSettingsKeys(keys) {
|
|
7702
|
+
const settings = this._ctx?.settings;
|
|
7703
|
+
const raw = this.rawSettings();
|
|
7704
|
+
if (!settings || !raw) return {
|
|
7705
|
+
removed: [],
|
|
7706
|
+
refused: keys.map((key) => ({
|
|
7707
|
+
key,
|
|
7708
|
+
reason: "no settings store"
|
|
7709
|
+
})),
|
|
7710
|
+
secretsCleared: 0
|
|
7711
|
+
};
|
|
7712
|
+
let stored;
|
|
7713
|
+
try {
|
|
7714
|
+
stored = await raw.readAddonStore();
|
|
7715
|
+
} catch (error) {
|
|
7716
|
+
const reason = `store unreadable: ${error instanceof Error ? error.message : "unknown"}`;
|
|
7717
|
+
return {
|
|
7718
|
+
removed: [],
|
|
7719
|
+
refused: keys.map((key) => ({
|
|
7720
|
+
key,
|
|
7721
|
+
reason
|
|
7722
|
+
})),
|
|
7723
|
+
secretsCleared: 0
|
|
7724
|
+
};
|
|
7725
|
+
}
|
|
7726
|
+
const declared = this.declaredKeySet();
|
|
7727
|
+
const removed = [];
|
|
7728
|
+
const refused = [];
|
|
7729
|
+
for (const key of keys) {
|
|
7730
|
+
const base = key.split("@", 1)[0] ?? key;
|
|
7731
|
+
if (declared.has(base)) refused.push({
|
|
7732
|
+
key,
|
|
7733
|
+
reason: "still declared by the addon"
|
|
7734
|
+
});
|
|
7735
|
+
else if (!(key in stored)) refused.push({
|
|
7736
|
+
key,
|
|
7737
|
+
reason: "not stored"
|
|
7738
|
+
});
|
|
7739
|
+
else removed.push(key);
|
|
7740
|
+
}
|
|
7741
|
+
if (removed.length === 0) return {
|
|
7742
|
+
removed,
|
|
7743
|
+
refused,
|
|
7744
|
+
secretsCleared: 0
|
|
7745
|
+
};
|
|
7746
|
+
const kept = /* @__PURE__ */ new Set();
|
|
7747
|
+
const held = /* @__PURE__ */ new Set();
|
|
7748
|
+
for (const [key, value] of Object.entries(stored)) {
|
|
7749
|
+
const target = removed.includes(key) ? held : kept;
|
|
7750
|
+
for (const ref of collectSecretMarkerRefs(value)) target.add(ref);
|
|
7751
|
+
}
|
|
7752
|
+
const refsToClear = [...held].filter((ref) => !kept.has(ref));
|
|
7753
|
+
const patch = {};
|
|
7754
|
+
for (const key of removed) patch[key] = void 0;
|
|
7755
|
+
await settings.writeAddonStore(patch);
|
|
7756
|
+
const secretsCleared = refsToClear.length > 0 && this._ctx?.secrets ? await this._ctx.secrets.delete(refsToClear) : 0;
|
|
7757
|
+
await this.resolveConfig();
|
|
7758
|
+
return {
|
|
7759
|
+
removed,
|
|
7760
|
+
refused,
|
|
7761
|
+
secretsCleared
|
|
7762
|
+
};
|
|
7763
|
+
}
|
|
7673
7764
|
/** Per-device variant of {@link state}, backed by the per-device store. */
|
|
7674
7765
|
deviceState(deviceId, key, schema, fallback) {
|
|
7675
7766
|
return createDurableState({
|
|
@@ -7940,6 +8031,21 @@ function dropPerNodeFields(fields) {
|
|
|
7940
8031
|
}
|
|
7941
8032
|
return kept;
|
|
7942
8033
|
}
|
|
8034
|
+
function collectFieldKeys(fields) {
|
|
8035
|
+
const collected = [];
|
|
8036
|
+
for (const field of fields) {
|
|
8037
|
+
if (field.type === "group") {
|
|
8038
|
+
collected.push(...collectFieldKeys(field.fields));
|
|
8039
|
+
continue;
|
|
8040
|
+
}
|
|
8041
|
+
if (field.type === "sub-tabs") {
|
|
8042
|
+
for (const tab of field.tabs) collected.push(...collectFieldKeys(tab.fields));
|
|
8043
|
+
continue;
|
|
8044
|
+
}
|
|
8045
|
+
if ("key" in field && typeof field.key === "string") collected.push(field.key);
|
|
8046
|
+
}
|
|
8047
|
+
return collected;
|
|
8048
|
+
}
|
|
7943
8049
|
function collectPerNodeFieldKeys(fields) {
|
|
7944
8050
|
const collected = [];
|
|
7945
8051
|
for (const field of fields) {
|
|
@@ -16331,8 +16437,172 @@ object({
|
|
|
16331
16437
|
quantity: ReadingQuantitySchema,
|
|
16332
16438
|
unit: string().min(1)
|
|
16333
16439
|
});
|
|
16334
|
-
|
|
16335
|
-
|
|
16440
|
+
new Set([
|
|
16441
|
+
{
|
|
16442
|
+
id: "person",
|
|
16443
|
+
name: "Person"
|
|
16444
|
+
},
|
|
16445
|
+
{
|
|
16446
|
+
id: "vehicle",
|
|
16447
|
+
name: "Vehicle"
|
|
16448
|
+
},
|
|
16449
|
+
{
|
|
16450
|
+
id: "animal",
|
|
16451
|
+
name: "Animal"
|
|
16452
|
+
},
|
|
16453
|
+
{
|
|
16454
|
+
id: "package",
|
|
16455
|
+
name: "Package"
|
|
16456
|
+
}
|
|
16457
|
+
].map((l) => l.id));
|
|
16458
|
+
var COCO_TO_MACRO = {
|
|
16459
|
+
mapping: {
|
|
16460
|
+
person: "person",
|
|
16461
|
+
bicycle: "vehicle",
|
|
16462
|
+
car: "vehicle",
|
|
16463
|
+
motorcycle: "vehicle",
|
|
16464
|
+
airplane: "vehicle",
|
|
16465
|
+
bus: "vehicle",
|
|
16466
|
+
train: "vehicle",
|
|
16467
|
+
truck: "vehicle",
|
|
16468
|
+
boat: "vehicle",
|
|
16469
|
+
bird: "animal",
|
|
16470
|
+
cat: "animal",
|
|
16471
|
+
dog: "animal",
|
|
16472
|
+
horse: "animal",
|
|
16473
|
+
sheep: "animal",
|
|
16474
|
+
cow: "animal",
|
|
16475
|
+
elephant: "animal",
|
|
16476
|
+
bear: "animal",
|
|
16477
|
+
zebra: "animal",
|
|
16478
|
+
giraffe: "animal",
|
|
16479
|
+
suitcase: "package",
|
|
16480
|
+
backpack: "package",
|
|
16481
|
+
handbag: "package"
|
|
16482
|
+
},
|
|
16483
|
+
preserveOriginal: false
|
|
16484
|
+
};
|
|
16485
|
+
/**
|
|
16486
|
+
* WHAT a detection-shaped leaf is about: one MACRO class (person, vehicle,
|
|
16487
|
+
* animal, package) plus an OPTIONAL label that narrows it.
|
|
16488
|
+
*
|
|
16489
|
+
* The taxonomy is `COCO_TO_MACRO` (and `CLASS_MAP_MACRO_TARGETS`) — never a
|
|
16490
|
+
* second list. The label that fits depends on the macro class:
|
|
16491
|
+
*
|
|
16492
|
+
* - `animal` → a sub-class (`dog`, `cat`, …);
|
|
16493
|
+
* - `person` → a known face (an identity of the `face-gallery`);
|
|
16494
|
+
* - `vehicle` → a plate (its text) or a sub-class (`car`, `truck`, …);
|
|
16495
|
+
* - `package` → a sub-class.
|
|
16496
|
+
*
|
|
16497
|
+
* `other` exists only so a class the taxonomy does not know (a custom model's
|
|
16498
|
+
* `forklift`) survives the conversion of a stored recipe without widening.
|
|
16499
|
+
*
|
|
16500
|
+
* A label is decided LATE (D683): face recognition and LPR land after the
|
|
16501
|
+
* detection starts. The track-lifecycle `update` event carries the newly
|
|
16502
|
+
* resolved `label` / `plateText`, which is why a leaf with a label fires when
|
|
16503
|
+
* the subject GETS it — not at the first detection.
|
|
16504
|
+
*/
|
|
16505
|
+
var SubClassLabelSchema = object({
|
|
16506
|
+
kind: literal("sub-class"),
|
|
16507
|
+
className: string().min(1)
|
|
16508
|
+
});
|
|
16509
|
+
var IdentityLabelSchema = object({
|
|
16510
|
+
kind: literal("identity"),
|
|
16511
|
+
/** The `face-gallery` identity id (stable across a rename). */
|
|
16512
|
+
identityId: string().min(1),
|
|
16513
|
+
/** The identity's name — what a track-lifecycle event carries as `label`. */
|
|
16514
|
+
name: string().min(1)
|
|
16515
|
+
});
|
|
16516
|
+
var PlateLabelSchema = object({
|
|
16517
|
+
kind: literal("plate"),
|
|
16518
|
+
text: string().min(1)
|
|
16519
|
+
});
|
|
16520
|
+
function macroOf$1(className) {
|
|
16521
|
+
return COCO_TO_MACRO.mapping[className.toLowerCase()] ?? className.toLowerCase();
|
|
16522
|
+
}
|
|
16523
|
+
/** A sub-class label must belong to the macro it is under. */
|
|
16524
|
+
function subClassBelongs(macro, label) {
|
|
16525
|
+
return label === void 0 || macroOf$1(label.className) === macro;
|
|
16526
|
+
}
|
|
16527
|
+
var subClassOf = (macro) => SubClassLabelSchema.refine((l) => subClassBelongs(macro, l), { message: `that class is not a kind of ${macro} in the detection taxonomy` });
|
|
16528
|
+
var DetectionSubjectSchema = discriminatedUnion("macro", [
|
|
16529
|
+
object({
|
|
16530
|
+
macro: literal("animal"),
|
|
16531
|
+
label: subClassOf("animal").optional()
|
|
16532
|
+
}),
|
|
16533
|
+
object({
|
|
16534
|
+
macro: literal("person"),
|
|
16535
|
+
label: IdentityLabelSchema.optional()
|
|
16536
|
+
}),
|
|
16537
|
+
object({
|
|
16538
|
+
macro: literal("vehicle"),
|
|
16539
|
+
label: discriminatedUnion("kind", [SubClassLabelSchema.refine((l) => subClassBelongs("vehicle", l), { message: "that class is not a kind of vehicle in the detection taxonomy" }), PlateLabelSchema]).optional()
|
|
16540
|
+
}),
|
|
16541
|
+
object({
|
|
16542
|
+
macro: literal("package"),
|
|
16543
|
+
label: subClassOf("package").optional()
|
|
16544
|
+
}),
|
|
16545
|
+
object({
|
|
16546
|
+
macro: literal("other"),
|
|
16547
|
+
className: string().min(1)
|
|
16548
|
+
})
|
|
16549
|
+
]);
|
|
16550
|
+
/**
|
|
16551
|
+
* The subject of a PARKED object. The stationary registry's event carries a
|
|
16552
|
+
* class and a zone, no face and no plate — an identity or plate label there
|
|
16553
|
+
* could never match, so the schema refuses it instead of letting it sit dead.
|
|
16554
|
+
*/
|
|
16555
|
+
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" });
|
|
16556
|
+
/**
|
|
16557
|
+
* A stored class string as a subject: a macro name stays a macro; a raw class
|
|
16558
|
+
* the taxonomy files under a macro becomes that macro plus the sub-class label
|
|
16559
|
+
* (`dog` → animal / dog); anything else is `other`, kept verbatim.
|
|
16560
|
+
*/
|
|
16561
|
+
function subjectFromClassName(className) {
|
|
16562
|
+
const name = className.trim().toLowerCase();
|
|
16563
|
+
const macro = COCO_TO_MACRO.mapping[name];
|
|
16564
|
+
if (new Set(Object.values(COCO_TO_MACRO.mapping)).has(name)) return macroOnly(name);
|
|
16565
|
+
if (macro === void 0) return {
|
|
16566
|
+
macro: "other",
|
|
16567
|
+
className
|
|
16568
|
+
};
|
|
16569
|
+
const label = {
|
|
16570
|
+
kind: "sub-class",
|
|
16571
|
+
className: name
|
|
16572
|
+
};
|
|
16573
|
+
switch (macro) {
|
|
16574
|
+
case "animal": return {
|
|
16575
|
+
macro: "animal",
|
|
16576
|
+
label
|
|
16577
|
+
};
|
|
16578
|
+
case "vehicle": return {
|
|
16579
|
+
macro: "vehicle",
|
|
16580
|
+
label
|
|
16581
|
+
};
|
|
16582
|
+
case "package": return {
|
|
16583
|
+
macro: "package",
|
|
16584
|
+
label
|
|
16585
|
+
};
|
|
16586
|
+
default: return {
|
|
16587
|
+
macro: "other",
|
|
16588
|
+
className
|
|
16589
|
+
};
|
|
16590
|
+
}
|
|
16591
|
+
}
|
|
16592
|
+
function macroOnly(macro) {
|
|
16593
|
+
switch (macro) {
|
|
16594
|
+
case "animal": return { macro: "animal" };
|
|
16595
|
+
case "person": return { macro: "person" };
|
|
16596
|
+
case "vehicle": return { macro: "vehicle" };
|
|
16597
|
+
case "package": return { macro: "package" };
|
|
16598
|
+
default: return {
|
|
16599
|
+
macro: "other",
|
|
16600
|
+
className: macro
|
|
16601
|
+
};
|
|
16602
|
+
}
|
|
16603
|
+
}
|
|
16604
|
+
/** How a state leaf compares a device field to a value. Derived from the
|
|
16605
|
+
* field's `kind` in `deviceManager.getWireableFields`, never hand-maintained. */
|
|
16336
16606
|
var AutomationConditionOperatorSchema = _enum([
|
|
16337
16607
|
"eq",
|
|
16338
16608
|
"ne",
|
|
@@ -16343,12 +16613,76 @@ var AutomationConditionOperatorSchema = _enum([
|
|
|
16343
16613
|
"contains",
|
|
16344
16614
|
"in"
|
|
16345
16615
|
]);
|
|
16346
|
-
|
|
16347
|
-
|
|
16616
|
+
/**
|
|
16617
|
+
* D8 compliance, and it is the reason a "becomes" leaf is not merely an event
|
|
16618
|
+
* subscription: it evaluates against the **state mirror**, which is reconciled,
|
|
16619
|
+
* and an event only WAKES the evaluation. A dropped event therefore DELAYS a
|
|
16620
|
+
* fire; it does not lose it.
|
|
16621
|
+
*/
|
|
16622
|
+
var DeviceBecomesLeafSchema = object({
|
|
16623
|
+
kind: literal("device-becomes"),
|
|
16624
|
+
deviceId: number().int().nonnegative(),
|
|
16625
|
+
cap: string().min(1),
|
|
16626
|
+
fieldPath: string().min(1),
|
|
16627
|
+
/** Fire when the field takes this value. Omit to fire on any change. */
|
|
16628
|
+
becomes: union([
|
|
16629
|
+
string(),
|
|
16630
|
+
number(),
|
|
16631
|
+
boolean()
|
|
16632
|
+
]).optional(),
|
|
16633
|
+
/** Only on a CHANGE of value, not on every re-report. */
|
|
16634
|
+
edge: boolean().optional(),
|
|
16635
|
+
/** The new value must hold this long before it counts. */
|
|
16636
|
+
forMs: number().int().min(0).max(864e5).optional(),
|
|
16637
|
+
/** Collapse a burst into one occurrence. */
|
|
16638
|
+
debounceMs: number().int().min(0).max(6e5).optional()
|
|
16639
|
+
});
|
|
16640
|
+
var DeviceEventLeafSchema = object({
|
|
16641
|
+
kind: literal("device-event"),
|
|
16642
|
+
/** An `EventCategory` value. */
|
|
16643
|
+
category: string().min(1),
|
|
16644
|
+
deviceId: number().int().nonnegative().optional()
|
|
16645
|
+
});
|
|
16646
|
+
var ScheduleLeafSchema = object({
|
|
16647
|
+
kind: literal("schedule"),
|
|
16648
|
+
cron: string().min(1).max(120)
|
|
16649
|
+
});
|
|
16650
|
+
var ManualLeafSchema = object({ kind: literal("manual") });
|
|
16651
|
+
var IntervalLeafSchema = object({
|
|
16652
|
+
kind: literal("interval"),
|
|
16653
|
+
minutes: number().int().min(1).max(1440)
|
|
16654
|
+
});
|
|
16655
|
+
var DetectionLeafSchema = object({
|
|
16656
|
+
kind: literal("detection"),
|
|
16657
|
+
/** One macro class each, optionally narrowed by a label; a track of any listed subject fires. */
|
|
16658
|
+
subjects: array(DetectionSubjectSchema).min(1),
|
|
16659
|
+
deviceIds: array(number().int().nonnegative()).min(1),
|
|
16660
|
+
/** The track must have visited at least one of these zones. */
|
|
16661
|
+
zones: array(string().min(1)).min(1).optional(),
|
|
16662
|
+
/** Best-so-far confidence the track must reach. */
|
|
16663
|
+
minScore: number().min(0).max(1).optional()
|
|
16664
|
+
});
|
|
16665
|
+
var StationaryLeafSchema = object({
|
|
16666
|
+
kind: literal("stationary"),
|
|
16667
|
+
deviceIds: array(number().int().nonnegative()).min(1),
|
|
16668
|
+
subjects: array(StationarySubjectSchema).min(1).optional(),
|
|
16669
|
+
zones: array(string().min(1)).min(1).optional(),
|
|
16670
|
+
/** `appeared`: it became parked. `departed`: the registry retired it. */
|
|
16671
|
+
phase: _enum(["appeared", "departed"])
|
|
16672
|
+
});
|
|
16673
|
+
/** "is": one device field compared to one value, NOW. */
|
|
16674
|
+
var DeviceIsLeafSchema = object({
|
|
16675
|
+
kind: literal("device-is"),
|
|
16348
16676
|
deviceId: number().int().nonnegative(),
|
|
16349
16677
|
cap: string().min(1),
|
|
16350
16678
|
fieldPath: string().min(1),
|
|
16351
16679
|
operator: AutomationConditionOperatorSchema,
|
|
16680
|
+
/**
|
|
16681
|
+
* The value. A number on a quantity field is stored in the field's base unit
|
|
16682
|
+
* (D944); a quantity value is the WRITE form, which the save boundary
|
|
16683
|
+
* replaces with the converted number and `unit`. A leaf that still carries
|
|
16684
|
+
* one is never evaluated (it fails).
|
|
16685
|
+
*/
|
|
16352
16686
|
value: union([
|
|
16353
16687
|
string(),
|
|
16354
16688
|
number(),
|
|
@@ -16356,24 +16690,26 @@ var AutomationConditionLeafSchema = object({
|
|
|
16356
16690
|
array(union([string(), number()])),
|
|
16357
16691
|
QuantityValueSchema
|
|
16358
16692
|
]),
|
|
16693
|
+
/** The unit the person picked for `value` (display only; `value` is in the base unit). */
|
|
16359
16694
|
unit: string().min(1).optional()
|
|
16360
16695
|
});
|
|
16361
|
-
|
|
16696
|
+
/**
|
|
16697
|
+
* True when the camera currently has a PARKED object matching `subjects` in at
|
|
16698
|
+
* least one of `zones`. Reads the zone-analytics snapshot through the same
|
|
16699
|
+
* mirror as every other state leaf, so a dropped event never decides it (D49).
|
|
16700
|
+
*/
|
|
16701
|
+
var StationaryPresentLeafSchema = object({
|
|
16362
16702
|
kind: literal("stationary-present"),
|
|
16363
16703
|
deviceId: number().int().nonnegative(),
|
|
16364
|
-
|
|
16365
|
-
classes: array(string().min(1)).min(1).optional(),
|
|
16366
|
-
/** The parked object must be in at least one of these zones. */
|
|
16704
|
+
subjects: array(StationarySubjectSchema).min(1).optional(),
|
|
16367
16705
|
zones: array(string().min(1)).min(1).optional()
|
|
16368
16706
|
});
|
|
16369
16707
|
/**
|
|
16370
|
-
* The
|
|
16371
|
-
*
|
|
16372
|
-
*
|
|
16373
|
-
* validation is the SAME function `ExpressionSourceSchema` runs, so the two
|
|
16374
|
-
* cannot drift — an expression that one accepts, the other accepts.
|
|
16708
|
+
* The escape hatch: the bounded expression engine over named device bindings.
|
|
16709
|
+
* Declared as a plain object so a discriminated union can read `kind`; the
|
|
16710
|
+
* author-time validation is the SAME function `ExpressionSourceSchema` runs.
|
|
16375
16711
|
*/
|
|
16376
|
-
var
|
|
16712
|
+
var ExpressionLeafSchema = object({
|
|
16377
16713
|
kind: literal("expression"),
|
|
16378
16714
|
expr: string().min(1).max(MAX_EXPRESSION_SOURCE_LENGTH),
|
|
16379
16715
|
bindings: record(string().regex(EXPRESSION_IDENTIFIER_RE), ExpressionBindingSourceSchema)
|
|
@@ -16385,55 +16721,62 @@ var AutomationConditionExpressionSchema = object({
|
|
|
16385
16721
|
path: ["expr"]
|
|
16386
16722
|
});
|
|
16387
16723
|
});
|
|
16388
|
-
var
|
|
16724
|
+
var AutomationWhenSchema = lazy(() => discriminatedUnion("kind", [
|
|
16389
16725
|
object({
|
|
16390
16726
|
kind: literal("all"),
|
|
16391
|
-
children: array(
|
|
16727
|
+
children: array(AutomationWhenSchema)
|
|
16392
16728
|
}),
|
|
16393
16729
|
object({
|
|
16394
16730
|
kind: literal("any"),
|
|
16395
|
-
children: array(
|
|
16731
|
+
children: array(AutomationWhenSchema)
|
|
16396
16732
|
}),
|
|
16397
16733
|
object({
|
|
16398
16734
|
kind: literal("not"),
|
|
16399
|
-
child:
|
|
16735
|
+
child: AutomationWhenSchema
|
|
16400
16736
|
}),
|
|
16401
|
-
|
|
16402
|
-
|
|
16403
|
-
|
|
16737
|
+
DeviceBecomesLeafSchema,
|
|
16738
|
+
DeviceEventLeafSchema,
|
|
16739
|
+
ScheduleLeafSchema,
|
|
16740
|
+
ManualLeafSchema,
|
|
16741
|
+
IntervalLeafSchema,
|
|
16742
|
+
DetectionLeafSchema,
|
|
16743
|
+
StationaryLeafSchema,
|
|
16744
|
+
DeviceIsLeafSchema,
|
|
16745
|
+
StationaryPresentLeafSchema,
|
|
16746
|
+
ExpressionLeafSchema
|
|
16404
16747
|
]));
|
|
16405
16748
|
/**
|
|
16406
|
-
*
|
|
16407
|
-
*
|
|
16408
|
-
*
|
|
16409
|
-
*
|
|
16410
|
-
*
|
|
16411
|
-
*
|
|
16412
|
-
*
|
|
16413
|
-
*
|
|
16414
|
-
|
|
16415
|
-
|
|
16749
|
+
* The recipe shape before the single `when` tree: a flat list of triggers
|
|
16750
|
+
* (OR'd, each an instant) and an optional condition tree. Stored recipes —
|
|
16751
|
+
* the `AUTOMATION_RECIPE` literal of every block saved so far, and whatever an
|
|
16752
|
+
* older client still posts — are in this shape, so it stays READABLE here, and
|
|
16753
|
+
* {@link convertLegacyRecipe} turns it into the new one, losslessly and one
|
|
16754
|
+
* way. Nothing writes this shape any more.
|
|
16755
|
+
*
|
|
16756
|
+
* `{ triggers: [t1…tn], conditions?: C }`
|
|
16757
|
+
* → `when = all(any(t1…tn), C)`, or `any(t1…tn)` without `C`;
|
|
16758
|
+
* a single trigger is not wrapped in `any`.
|
|
16759
|
+
* a `condition` leaf → a `device-is` leaf (the "is" verb);
|
|
16760
|
+
* a `device-state` trigger → a `device-becomes` leaf (the "becomes" verb);
|
|
16761
|
+
* `classes: ['dog']` → the macro `animal` with the label `dog`.
|
|
16762
|
+
*/
|
|
16763
|
+
var LegacyTriggerSchema = discriminatedUnion("kind", [
|
|
16416
16764
|
object({
|
|
16417
16765
|
kind: literal("device-state"),
|
|
16418
16766
|
deviceId: number().int().nonnegative(),
|
|
16419
16767
|
cap: string().min(1),
|
|
16420
16768
|
fieldPath: string().min(1),
|
|
16421
|
-
/** Fire when the field takes this value. Omit to fire on any change. */
|
|
16422
16769
|
becomes: union([
|
|
16423
16770
|
string(),
|
|
16424
16771
|
number(),
|
|
16425
16772
|
boolean()
|
|
16426
16773
|
]).optional(),
|
|
16427
|
-
/** Only on a CHANGE of value, not on every re-report. */
|
|
16428
16774
|
edge: boolean().optional(),
|
|
16429
|
-
/** The condition must hold this long before the run starts. */
|
|
16430
16775
|
forMs: number().int().min(0).max(864e5).optional(),
|
|
16431
|
-
/** Collapse a burst into one run. */
|
|
16432
16776
|
debounceMs: number().int().min(0).max(6e5).optional()
|
|
16433
16777
|
}),
|
|
16434
16778
|
object({
|
|
16435
16779
|
kind: literal("device-event"),
|
|
16436
|
-
/** An `EventCategory` value. */
|
|
16437
16780
|
category: string().min(1),
|
|
16438
16781
|
deviceId: number().int().nonnegative().optional()
|
|
16439
16782
|
}),
|
|
@@ -16444,25 +16787,16 @@ var AutomationTriggerSchema = discriminatedUnion("kind", [
|
|
|
16444
16787
|
object({ kind: literal("manual") }),
|
|
16445
16788
|
object({
|
|
16446
16789
|
kind: literal("detection"),
|
|
16447
|
-
/** Class names. A macro class (`animal`, `vehicle`, `person`, `package`)
|
|
16448
|
-
* matches every raw class that maps to it; any other name matches
|
|
16449
|
-
* exactly. */
|
|
16450
16790
|
classes: array(string().min(1)).min(1),
|
|
16451
16791
|
deviceIds: array(number().int().nonnegative()).min(1),
|
|
16452
|
-
/** The track must have visited at least one of these zones. */
|
|
16453
16792
|
zones: array(string().min(1)).min(1).optional(),
|
|
16454
|
-
/** Best-so-far confidence the track must reach. */
|
|
16455
16793
|
minScore: number().min(0).max(1).optional()
|
|
16456
16794
|
}),
|
|
16457
16795
|
object({
|
|
16458
16796
|
kind: literal("stationary"),
|
|
16459
16797
|
deviceIds: array(number().int().nonnegative()).min(1),
|
|
16460
|
-
/** Class names; a macro class matches like the detection trigger. */
|
|
16461
16798
|
classes: array(string().min(1)).min(1).optional(),
|
|
16462
|
-
/** The parked object must be in at least one of these zones. */
|
|
16463
16799
|
zones: array(string().min(1)).min(1).optional(),
|
|
16464
|
-
/** `appeared`: it became parked. `departed`: the registry retired it.
|
|
16465
|
-
* The vocabulary of `PipelineAnalyticsStationaryChanged`. */
|
|
16466
16800
|
phase: _enum(["appeared", "departed"])
|
|
16467
16801
|
}),
|
|
16468
16802
|
object({
|
|
@@ -16470,6 +16804,143 @@ var AutomationTriggerSchema = discriminatedUnion("kind", [
|
|
|
16470
16804
|
minutes: number().int().min(1).max(1440)
|
|
16471
16805
|
})
|
|
16472
16806
|
]);
|
|
16807
|
+
var LegacyConditionLeafSchema = object({
|
|
16808
|
+
kind: literal("condition"),
|
|
16809
|
+
deviceId: number().int().nonnegative(),
|
|
16810
|
+
cap: string().min(1),
|
|
16811
|
+
fieldPath: string().min(1),
|
|
16812
|
+
operator: AutomationConditionOperatorSchema,
|
|
16813
|
+
value: union([
|
|
16814
|
+
string(),
|
|
16815
|
+
number(),
|
|
16816
|
+
boolean(),
|
|
16817
|
+
array(union([string(), number()])),
|
|
16818
|
+
QuantityValueSchema
|
|
16819
|
+
]),
|
|
16820
|
+
unit: string().min(1).optional()
|
|
16821
|
+
});
|
|
16822
|
+
var LegacyStationaryPresentSchema = object({
|
|
16823
|
+
kind: literal("stationary-present"),
|
|
16824
|
+
deviceId: number().int().nonnegative(),
|
|
16825
|
+
classes: array(string().min(1)).min(1).optional(),
|
|
16826
|
+
zones: array(string().min(1)).min(1).optional()
|
|
16827
|
+
});
|
|
16828
|
+
var LegacyExpressionSchema = object({
|
|
16829
|
+
kind: literal("expression"),
|
|
16830
|
+
expr: string().min(1).max(MAX_EXPRESSION_SOURCE_LENGTH),
|
|
16831
|
+
bindings: record(string().regex(EXPRESSION_IDENTIFIER_RE), ExpressionBindingSourceSchema)
|
|
16832
|
+
}).superRefine((src, ctx) => {
|
|
16833
|
+
const err = validateExpressionSource(src);
|
|
16834
|
+
if (err !== null) ctx.addIssue({
|
|
16835
|
+
code: "custom",
|
|
16836
|
+
message: err,
|
|
16837
|
+
path: ["expr"]
|
|
16838
|
+
});
|
|
16839
|
+
});
|
|
16840
|
+
var LegacyConditionSchema = lazy(() => discriminatedUnion("kind", [
|
|
16841
|
+
object({
|
|
16842
|
+
kind: literal("all"),
|
|
16843
|
+
children: array(LegacyConditionSchema)
|
|
16844
|
+
}),
|
|
16845
|
+
object({
|
|
16846
|
+
kind: literal("any"),
|
|
16847
|
+
children: array(LegacyConditionSchema)
|
|
16848
|
+
}),
|
|
16849
|
+
object({
|
|
16850
|
+
kind: literal("not"),
|
|
16851
|
+
child: LegacyConditionSchema
|
|
16852
|
+
}),
|
|
16853
|
+
LegacyConditionLeafSchema,
|
|
16854
|
+
LegacyExpressionSchema,
|
|
16855
|
+
LegacyStationaryPresentSchema
|
|
16856
|
+
]));
|
|
16857
|
+
function convertTrigger(trigger) {
|
|
16858
|
+
switch (trigger.kind) {
|
|
16859
|
+
case "device-state": return {
|
|
16860
|
+
...trigger,
|
|
16861
|
+
kind: "device-becomes"
|
|
16862
|
+
};
|
|
16863
|
+
case "detection": {
|
|
16864
|
+
const { classes, ...rest } = trigger;
|
|
16865
|
+
return {
|
|
16866
|
+
...rest,
|
|
16867
|
+
subjects: classes.map(subjectFromClassName)
|
|
16868
|
+
};
|
|
16869
|
+
}
|
|
16870
|
+
case "stationary": {
|
|
16871
|
+
const { classes, ...rest } = trigger;
|
|
16872
|
+
return {
|
|
16873
|
+
...rest,
|
|
16874
|
+
...classes === void 0 ? {} : { subjects: classes.map(subjectFromClassName) }
|
|
16875
|
+
};
|
|
16876
|
+
}
|
|
16877
|
+
default: return trigger;
|
|
16878
|
+
}
|
|
16879
|
+
}
|
|
16880
|
+
/** An old condition tree as a `when` subtree: `condition` → "is", classes → subjects. */
|
|
16881
|
+
function convertLegacyCondition(condition) {
|
|
16882
|
+
switch (condition.kind) {
|
|
16883
|
+
case "condition": return {
|
|
16884
|
+
...condition,
|
|
16885
|
+
kind: "device-is"
|
|
16886
|
+
};
|
|
16887
|
+
case "stationary-present": {
|
|
16888
|
+
const { classes, ...rest } = condition;
|
|
16889
|
+
return {
|
|
16890
|
+
...rest,
|
|
16891
|
+
...classes === void 0 ? {} : { subjects: classes.map(subjectFromClassName) }
|
|
16892
|
+
};
|
|
16893
|
+
}
|
|
16894
|
+
case "expression": return condition;
|
|
16895
|
+
case "not": return {
|
|
16896
|
+
kind: "not",
|
|
16897
|
+
child: convertLegacyCondition(condition.child)
|
|
16898
|
+
};
|
|
16899
|
+
case "all":
|
|
16900
|
+
case "any": return {
|
|
16901
|
+
kind: condition.kind,
|
|
16902
|
+
children: condition.children.map(convertLegacyCondition)
|
|
16903
|
+
};
|
|
16904
|
+
}
|
|
16905
|
+
}
|
|
16906
|
+
/** `all(any(t1…tn), C)`, or `any(t1…tn)`; a single trigger is not wrapped in `any`. */
|
|
16907
|
+
function convertLegacyWhen(half) {
|
|
16908
|
+
const leaves = half.triggers.map(convertTrigger);
|
|
16909
|
+
const first = leaves[0];
|
|
16910
|
+
const triggers = leaves.length === 1 && first !== void 0 ? first : {
|
|
16911
|
+
kind: "any",
|
|
16912
|
+
children: leaves
|
|
16913
|
+
};
|
|
16914
|
+
if (half.conditions === void 0) return triggers;
|
|
16915
|
+
return {
|
|
16916
|
+
kind: "all",
|
|
16917
|
+
children: [triggers, convertLegacyCondition(half.conditions)]
|
|
16918
|
+
};
|
|
16919
|
+
}
|
|
16920
|
+
/**
|
|
16921
|
+
* The automation RECIPE — what a visually-authored automation is, before it
|
|
16922
|
+
* becomes code.
|
|
16923
|
+
*
|
|
16924
|
+
* This is the data half of `docs/design/2026-08-08-automation-scripts-custom-devices.md`
|
|
16925
|
+
* Phase 6. A recipe is not an engine and never evaluates anything: it is a
|
|
16926
|
+
* declarative description that {@link generateAutomationBlock} compiles to the
|
|
16927
|
+
* TypeScript of an ordinary core block. There is therefore no second rule
|
|
16928
|
+
* engine, no second store and no second runtime — the block runner is the
|
|
16929
|
+
* runtime, `core_blocks` is the store (§2.1).
|
|
16930
|
+
*
|
|
16931
|
+
* Two parts:
|
|
16932
|
+
*
|
|
16933
|
+
* - **`when`** — ONE tree (`./when.ts`) of all/any/not over event leaves
|
|
16934
|
+
* (instants) and state leaves (durations). It replaces the flat trigger list
|
|
16935
|
+
* plus the separate condition tree; the firing rule is in that file and in
|
|
16936
|
+
* ADR "one tree".
|
|
16937
|
+
* - **Actions** — `NcRuleActionSchema`'s two steps, plus the `{kind:'code'}`
|
|
16938
|
+
* fragment of §3.2.2. See {@link AutomationActionSchema} for the ONE place
|
|
16939
|
+
* this had to diverge from "verbatim", and why.
|
|
16940
|
+
*
|
|
16941
|
+
* A recipe stored in the old shape (`triggers` + `conditions`) still LOADS:
|
|
16942
|
+
* {@link AutomationRecipeSchema} (the parse-anywhere schema) converts it on parse. Nothing writes it.
|
|
16943
|
+
*/
|
|
16473
16944
|
/**
|
|
16474
16945
|
* One action step.
|
|
16475
16946
|
*
|
|
@@ -16572,69 +17043,49 @@ var AutomationRunModeSchema = discriminatedUnion("mode", [
|
|
|
16572
17043
|
minutes: number().int().min(1).max(1440)
|
|
16573
17044
|
})
|
|
16574
17045
|
]);
|
|
16575
|
-
var
|
|
16576
|
-
|
|
16577
|
-
conditions: AutomationConditionSchema.optional(),
|
|
17046
|
+
var CurrentAutomationRecipeSchema = object({
|
|
17047
|
+
when: AutomationWhenSchema,
|
|
16578
17048
|
actions: array(AutomationActionSchema),
|
|
16579
17049
|
runMode: AutomationRunModeSchema.optional(),
|
|
16580
17050
|
/** How many run traces the automation keeps (default {@link DEFAULT_TRACE_KEEP}). */
|
|
16581
17051
|
keepTraces: number().int().min(1).max(100).optional()
|
|
16582
17052
|
});
|
|
16583
|
-
|
|
16584
|
-
|
|
16585
|
-
|
|
16586
|
-
|
|
16587
|
-
|
|
16588
|
-
|
|
16589
|
-
|
|
16590
|
-
|
|
16591
|
-
|
|
16592
|
-
|
|
16593
|
-
|
|
16594
|
-
|
|
16595
|
-
|
|
16596
|
-
|
|
16597
|
-
|
|
16598
|
-
|
|
16599
|
-
|
|
16600
|
-
|
|
16601
|
-
|
|
16602
|
-
|
|
16603
|
-
|
|
16604
|
-
|
|
16605
|
-
|
|
16606
|
-
|
|
16607
|
-
|
|
16608
|
-
bus: "vehicle",
|
|
16609
|
-
train: "vehicle",
|
|
16610
|
-
truck: "vehicle",
|
|
16611
|
-
boat: "vehicle",
|
|
16612
|
-
bird: "animal",
|
|
16613
|
-
cat: "animal",
|
|
16614
|
-
dog: "animal",
|
|
16615
|
-
horse: "animal",
|
|
16616
|
-
sheep: "animal",
|
|
16617
|
-
cow: "animal",
|
|
16618
|
-
elephant: "animal",
|
|
16619
|
-
bear: "animal",
|
|
16620
|
-
zebra: "animal",
|
|
16621
|
-
giraffe: "animal",
|
|
16622
|
-
suitcase: "package",
|
|
16623
|
-
backpack: "package",
|
|
16624
|
-
handbag: "package"
|
|
16625
|
-
},
|
|
16626
|
-
preserveOriginal: false
|
|
16627
|
-
};
|
|
17053
|
+
/** A recipe as it was stored before the single tree. Read-only: nothing writes this. */
|
|
17054
|
+
var LegacyAutomationRecipeSchema = object({
|
|
17055
|
+
triggers: array(LegacyTriggerSchema),
|
|
17056
|
+
conditions: LegacyConditionSchema.optional(),
|
|
17057
|
+
actions: array(AutomationActionSchema),
|
|
17058
|
+
runMode: AutomationRunModeSchema.optional(),
|
|
17059
|
+
keepTraces: number().int().min(1).max(100).optional()
|
|
17060
|
+
});
|
|
17061
|
+
/** The old shape as the new one, lossless. */
|
|
17062
|
+
function convertLegacyRecipe(legacy) {
|
|
17063
|
+
const { triggers, conditions, ...rest } = legacy;
|
|
17064
|
+
return {
|
|
17065
|
+
when: convertLegacyWhen({
|
|
17066
|
+
triggers,
|
|
17067
|
+
conditions
|
|
17068
|
+
}),
|
|
17069
|
+
...rest
|
|
17070
|
+
};
|
|
17071
|
+
}
|
|
17072
|
+
/**
|
|
17073
|
+
* Where recipes are PARSED (the core-blocks cap, the MCP tool, the literal a
|
|
17074
|
+
* saved block carries): the new shape as it is, or the old shape converted to
|
|
17075
|
+
* it. The output type is always the new one.
|
|
17076
|
+
*/
|
|
17077
|
+
var AutomationRecipeSchema = union([CurrentAutomationRecipeSchema, LegacyAutomationRecipeSchema.transform(convertLegacyRecipe)]);
|
|
16628
17078
|
new Set(Object.values(COCO_TO_MACRO.mapping));
|
|
16629
17079
|
/**
|
|
16630
17080
|
* Run traces — what an automation (or, later, an Action run) DID, node by node,
|
|
16631
17081
|
* so the editor can paint every block green or red with its reason.
|
|
16632
17082
|
*
|
|
16633
|
-
* A trace is data, not a log: it covers the WHOLE tree — the
|
|
16634
|
-
* every
|
|
16635
|
-
* short-circuit never reached), the run-mode verdict and every action
|
|
16636
|
-
* each addressed by a stable path (`
|
|
16637
|
-
* for an Action run).
|
|
17083
|
+
* A trace is data, not a log: it covers the WHOLE tree — the event leaf that
|
|
17084
|
+
* fired, every node of the `when` tree (containers and leaves, including the
|
|
17085
|
+
* ones a short-circuit never reached), the run-mode verdict and every action
|
|
17086
|
+
* step — each addressed by a stable path (`when.0.1`, `actions.2`, or `steps.N`
|
|
17087
|
+
* for an Action run). Traces written before the single tree carry
|
|
17088
|
+
* `conditions.*` paths and still parse. Skipped
|
|
16638
17089
|
* evaluations are traced too, and identical consecutive skips collapse into a
|
|
16639
17090
|
* repeat count so a trigger that fails every 5 minutes cannot flush real runs.
|
|
16640
17091
|
*
|
|
@@ -16666,6 +17117,8 @@ var TraceNodeOutcomeSchema = _enum([
|
|
|
16666
17117
|
]);
|
|
16667
17118
|
var AutomationTriggerTraceSchema = object({
|
|
16668
17119
|
kind: string().min(1),
|
|
17120
|
+
/** The event leaf that fired (`when`, `when.0.1`); absent on traces written before the single tree. */
|
|
17121
|
+
path: string().min(1).optional(),
|
|
16669
17122
|
outcome: _enum(["pass", "fail"]),
|
|
16670
17123
|
/** Why an event was rejected ("class person not in [dog]") or what fired. */
|
|
16671
17124
|
reason: string(),
|
|
@@ -16673,15 +17126,23 @@ var AutomationTriggerTraceSchema = object({
|
|
|
16673
17126
|
vars: record(string(), TraceValueSchema)
|
|
16674
17127
|
});
|
|
16675
17128
|
var AutomationConditionTraceNodeSchema = object({
|
|
16676
|
-
/** `
|
|
17129
|
+
/** `when` for the root, `when.<i>` for its i-th child, … (`conditions…` on an old trace). */
|
|
16677
17130
|
path: string().min(1),
|
|
16678
17131
|
kind: _enum([
|
|
16679
17132
|
"all",
|
|
16680
17133
|
"any",
|
|
16681
17134
|
"not",
|
|
16682
17135
|
"condition",
|
|
17136
|
+
"device-is",
|
|
16683
17137
|
"expression",
|
|
16684
|
-
"stationary-present"
|
|
17138
|
+
"stationary-present",
|
|
17139
|
+
"device-becomes",
|
|
17140
|
+
"device-event",
|
|
17141
|
+
"schedule",
|
|
17142
|
+
"interval",
|
|
17143
|
+
"manual",
|
|
17144
|
+
"detection",
|
|
17145
|
+
"stationary"
|
|
16685
17146
|
]),
|
|
16686
17147
|
outcome: TraceNodeOutcomeSchema,
|
|
16687
17148
|
reason: string(),
|
|
@@ -16715,6 +17176,12 @@ var AutomationStepTraceSchema = object({
|
|
|
16715
17176
|
deviceId: number().int().optional(),
|
|
16716
17177
|
startedAt: number().optional(),
|
|
16717
17178
|
endedAt: number().optional(),
|
|
17179
|
+
/**
|
|
17180
|
+
* The parameters the step SENT, after `{{vars.x}}` substitution — what the
|
|
17181
|
+
* device was actually asked. Bounded like trigger `vars`; a secret parameter
|
|
17182
|
+
* is shown as {@link REDACTED_ARG}. Absent on traces written before it existed.
|
|
17183
|
+
*/
|
|
17184
|
+
args: record(string(), TraceValueSchema).optional(),
|
|
16718
17185
|
outcome: _enum([
|
|
16719
17186
|
"ok",
|
|
16720
17187
|
"error",
|
|
@@ -17464,6 +17931,23 @@ method(object({
|
|
|
17464
17931
|
addonId: string(),
|
|
17465
17932
|
nodeId: string().optional()
|
|
17466
17933
|
}), SettingsSchemaWithValuesSchema.nullable()), method(object({
|
|
17934
|
+
addonId: string(),
|
|
17935
|
+
nodeId: string().optional()
|
|
17936
|
+
}), object({ keys: array(string()) }).nullable(), { auth: "admin" }), method(object({
|
|
17937
|
+
addonId: string(),
|
|
17938
|
+
nodeId: string().optional(),
|
|
17939
|
+
keys: array(string())
|
|
17940
|
+
}), object({
|
|
17941
|
+
removed: array(string()),
|
|
17942
|
+
refused: array(object({
|
|
17943
|
+
key: string(),
|
|
17944
|
+
reason: string()
|
|
17945
|
+
})),
|
|
17946
|
+
secretsCleared: number()
|
|
17947
|
+
}), {
|
|
17948
|
+
kind: "mutation",
|
|
17949
|
+
auth: "admin"
|
|
17950
|
+
}), method(object({
|
|
17467
17951
|
addonId: string(),
|
|
17468
17952
|
deviceId: number(),
|
|
17469
17953
|
nodeId: string().optional()
|
|
@@ -21387,6 +21871,8 @@ var StorageKindSchema = object({
|
|
|
21387
21871
|
"orphaned",
|
|
21388
21872
|
"dropped"
|
|
21389
21873
|
]),
|
|
21874
|
+
/** An owner declared this kind since the engine started. */
|
|
21875
|
+
declaredThisBoot: boolean(),
|
|
21390
21876
|
/** `null` when the caller asked for no counts (`counts: false`). */
|
|
21391
21877
|
rows: number().int().nonnegative().nullable(),
|
|
21392
21878
|
/** Rows x the average size of a sample; null for an empty kind. */
|
|
@@ -21398,6 +21884,51 @@ var StorageKindSchema = object({
|
|
|
21398
21884
|
/** The whole declaration, secret paths and entry descriptor included (the entries service builds its handle from it). */
|
|
21399
21885
|
declaration: RecordKindDeclarationSchema
|
|
21400
21886
|
});
|
|
21887
|
+
_enum([
|
|
21888
|
+
"orphaned",
|
|
21889
|
+
"stale",
|
|
21890
|
+
"unknown"
|
|
21891
|
+
]);
|
|
21892
|
+
/** A record kind nobody declared since its owner started, or whose owner is gone. */
|
|
21893
|
+
var StaleKindFindingSchema = object({
|
|
21894
|
+
owner: string(),
|
|
21895
|
+
kind: string(),
|
|
21896
|
+
/** `unknown`: the owner could not be judged (not running, or its state unreadable) - never dropped. */
|
|
21897
|
+
verdict: _enum(["orphaned", "unknown"]),
|
|
21898
|
+
reason: string(),
|
|
21899
|
+
rows: number().int().nonnegative().nullable(),
|
|
21900
|
+
/** local-auth's tables are never dropped by this audit. */
|
|
21901
|
+
protected: boolean()
|
|
21902
|
+
});
|
|
21903
|
+
/** A stored global-settings key the running addon no longer declares. */
|
|
21904
|
+
var StaleSettingsKeyFindingSchema = object({
|
|
21905
|
+
addonId: string(),
|
|
21906
|
+
/** The stored key as written, a per-node `<key>@<nodeId>` suffix included. */
|
|
21907
|
+
key: string(),
|
|
21908
|
+
/**
|
|
21909
|
+
* Keychain refs whose ONLY marker sits under this key: in use by stale data,
|
|
21910
|
+
* not orphans yet. Removing the key releases them.
|
|
21911
|
+
*/
|
|
21912
|
+
secretRefs: array(string())
|
|
21913
|
+
});
|
|
21914
|
+
/** An addon the audit could not judge, with the reason. Never reported as stale. */
|
|
21915
|
+
var StaleUnknownSchema = object({
|
|
21916
|
+
subject: string(),
|
|
21917
|
+
reason: string()
|
|
21918
|
+
});
|
|
21919
|
+
var StaleDataReportSchema = object({
|
|
21920
|
+
/** Epoch ms of the last finished scan; `null` before the first. */
|
|
21921
|
+
scannedAt: number().nullable(),
|
|
21922
|
+
scanning: boolean(),
|
|
21923
|
+
trigger: _enum([
|
|
21924
|
+
"boot",
|
|
21925
|
+
"interval",
|
|
21926
|
+
"manual"
|
|
21927
|
+
]).nullable(),
|
|
21928
|
+
kinds: array(StaleKindFindingSchema),
|
|
21929
|
+
settingsKeys: array(StaleSettingsKeyFindingSchema),
|
|
21930
|
+
unknown: array(StaleUnknownSchema)
|
|
21931
|
+
});
|
|
21401
21932
|
method(object({ ownerPrefix: string().min(1).optional() }), object({ tables: array(StorageTableSchema) }), { auth: "admin" }), method(object({
|
|
21402
21933
|
owner: string().min(1).optional(),
|
|
21403
21934
|
/** `false` skips the per-kind row count (a catalog read only). Default true. */
|
|
@@ -21405,7 +21936,30 @@ method(object({ ownerPrefix: string().min(1).optional() }), object({ tables: arr
|
|
|
21405
21936
|
}), object({ kinds: array(StorageKindSchema) }), { auth: "admin" }), method(RecordQueryInputSchema.extend({
|
|
21406
21937
|
owner: string().min(1),
|
|
21407
21938
|
kind: RecordKindNameSchema
|
|
21408
|
-
}), RecordQueryResultSchema, { auth: "admin" })
|
|
21939
|
+
}), RecordQueryResultSchema, { auth: "admin" }), method(object({}), StaleDataReportSchema, { auth: "admin" }), method(object({}), StaleDataReportSchema, {
|
|
21940
|
+
kind: "mutation",
|
|
21941
|
+
auth: "admin"
|
|
21942
|
+
}), method(object({
|
|
21943
|
+
owner: string().min(1),
|
|
21944
|
+
kind: RecordKindNameSchema
|
|
21945
|
+
}), object({
|
|
21946
|
+
deleted: number().int().nonnegative(),
|
|
21947
|
+
secretsReleased: number().int().nonnegative()
|
|
21948
|
+
}), {
|
|
21949
|
+
kind: "mutation",
|
|
21950
|
+
auth: "admin",
|
|
21951
|
+
caller: "required"
|
|
21952
|
+
}), method(object({
|
|
21953
|
+
addonId: string().min(1),
|
|
21954
|
+
key: string().min(1)
|
|
21955
|
+
}), object({
|
|
21956
|
+
removed: boolean(),
|
|
21957
|
+
secretsCleared: number().int().nonnegative()
|
|
21958
|
+
}), {
|
|
21959
|
+
kind: "mutation",
|
|
21960
|
+
auth: "admin",
|
|
21961
|
+
caller: "required"
|
|
21962
|
+
});
|
|
21409
21963
|
/**
|
|
21410
21964
|
* record-entries - the ONE admin surface for every list of user-created entries
|
|
21411
21965
|
* (D881): notification targets, brokers, LLM profiles, anything an addon
|
|
@@ -21544,6 +22098,12 @@ method(object({
|
|
|
21544
22098
|
}), method(object({ deviceId: number().int() }), object({ refs: array(string()).readonly() }), {
|
|
21545
22099
|
kind: "mutation",
|
|
21546
22100
|
auth: "admin"
|
|
22101
|
+
}), method(object({
|
|
22102
|
+
refs: RefListSchema,
|
|
22103
|
+
onBehalfOf: string().min(1)
|
|
22104
|
+
}), object({ released: number().int() }), {
|
|
22105
|
+
kind: "mutation",
|
|
22106
|
+
auth: "admin"
|
|
21547
22107
|
}), method(object({}), array(KeychainSecretMetaSchema).readonly(), { auth: "admin" }), method(object({}), KeychainStateSchema, { auth: "admin" });
|
|
21548
22108
|
/**
|
|
21549
22109
|
* device-history — the ONE mechanism for numeric history (D850).
|
|
@@ -22333,7 +22893,9 @@ var DiscoveredChildDeviceSchema = lazy(() => object({
|
|
|
22333
22893
|
/** Upstream-system identity + rendering hints for the candidate. */
|
|
22334
22894
|
sourceInfo: SourceInfoSchema.optional(),
|
|
22335
22895
|
/** Nested entity-children for accordion preview — integrations populate, Hubs omit. */
|
|
22336
|
-
children: array(DiscoveredChildDeviceSchema).readonly().optional()
|
|
22896
|
+
children: array(DiscoveredChildDeviceSchema).readonly().optional(),
|
|
22897
|
+
/** `childNativeId` of the gateway candidate in the same list this device sits behind. */
|
|
22898
|
+
parentStableId: string().optional()
|
|
22337
22899
|
}));
|
|
22338
22900
|
/**
|
|
22339
22901
|
* Status block — populated by the integration after each
|
|
@@ -42648,6 +43210,79 @@ object({
|
|
|
42648
43210
|
metadata: record(string(), unknown()).optional()
|
|
42649
43211
|
});
|
|
42650
43212
|
/**
|
|
43213
|
+
* HOW a provider can be found on the network. The provider only DECLARES the
|
|
43214
|
+
* mode; the `local-network` scan engine runs it once for every provider that
|
|
43215
|
+
* asked (one multicast browse, one host sweep) and hands the raw hits back to
|
|
43216
|
+
* `classifyDiscoveryHits`. A provider never opens a discovery socket itself,
|
|
43217
|
+
* except through a `custom` mode.
|
|
43218
|
+
*/
|
|
43219
|
+
var DiscoveryModeSchema = discriminatedUnion("kind", [
|
|
43220
|
+
object({
|
|
43221
|
+
kind: literal("mdns"),
|
|
43222
|
+
/** DNS-SD service type, e.g. `_esphomelib._tcp`. */
|
|
43223
|
+
serviceType: string().min(1),
|
|
43224
|
+
/** Regular expression an instance name must match (case-insensitive). */
|
|
43225
|
+
instancePattern: string().optional()
|
|
43226
|
+
}),
|
|
43227
|
+
object({
|
|
43228
|
+
kind: literal("ws-discovery"),
|
|
43229
|
+
/** Probe types (e.g. `dn:NetworkVideoTransmitter`); omitted = any device. */
|
|
43230
|
+
types: array(string()).optional()
|
|
43231
|
+
}),
|
|
43232
|
+
object({
|
|
43233
|
+
kind: literal("ssdp"),
|
|
43234
|
+
searchTarget: string().min(1)
|
|
43235
|
+
}),
|
|
43236
|
+
object({
|
|
43237
|
+
kind: literal("udp-broadcast"),
|
|
43238
|
+
port: number().int().min(1).max(65535),
|
|
43239
|
+
payloadHex: string().regex(/^([0-9a-fA-F]{2})*$/),
|
|
43240
|
+
/** Port replies arrive on, when the device answers somewhere other than the source port. */
|
|
43241
|
+
listenPort: number().int().min(1).max(65535).optional()
|
|
43242
|
+
}),
|
|
43243
|
+
object({
|
|
43244
|
+
kind: literal("http-probe"),
|
|
43245
|
+
port: number().int().min(1).max(65535),
|
|
43246
|
+
path: string().startsWith("/"),
|
|
43247
|
+
method: _enum(["GET", "POST"]).default("GET"),
|
|
43248
|
+
bodyText: string().optional(),
|
|
43249
|
+
contentType: string().optional(),
|
|
43250
|
+
tls: boolean().default(false),
|
|
43251
|
+
/** Status codes that count as a hit. Omitted = any HTTP answer. */
|
|
43252
|
+
acceptStatus: array(number().int()).optional()
|
|
43253
|
+
}),
|
|
43254
|
+
object({
|
|
43255
|
+
kind: literal("custom"),
|
|
43256
|
+
/** Why the engine cannot do it (an allowlisted exception, e.g. a vendor UDP protocol). */
|
|
43257
|
+
reason: string().min(1)
|
|
43258
|
+
})
|
|
43259
|
+
]);
|
|
43260
|
+
/** What the engine saw on the wire for ONE declared mode; the provider classifies it. */
|
|
43261
|
+
var DiscoveryHitSchema = object({
|
|
43262
|
+
/** Index into the provider's own `getDiscoveryModes()` array. */
|
|
43263
|
+
modeIndex: number().int().min(0),
|
|
43264
|
+
host: string(),
|
|
43265
|
+
port: number().int(),
|
|
43266
|
+
http: object({
|
|
43267
|
+
status: number().int(),
|
|
43268
|
+
headers: record(string(), string()),
|
|
43269
|
+
/** At most 16 KiB. */
|
|
43270
|
+
bodyText: string()
|
|
43271
|
+
}).optional(),
|
|
43272
|
+
mdns: object({
|
|
43273
|
+
instance: string(),
|
|
43274
|
+
host: string(),
|
|
43275
|
+
port: number().int(),
|
|
43276
|
+
txt: record(string(), string())
|
|
43277
|
+
}).optional(),
|
|
43278
|
+
udp: object({ payloadHex: string() }).optional(),
|
|
43279
|
+
wsd: object({
|
|
43280
|
+
xaddrs: array(string()),
|
|
43281
|
+
types: array(string()),
|
|
43282
|
+
scopes: array(string())
|
|
43283
|
+
}).optional()
|
|
43284
|
+
});
|
|
43285
|
+
/**
|
|
42651
43286
|
* Candidate handed back from discovery and accepted by
|
|
42652
43287
|
* `adoptDiscoveredDevice`. Shape mirrors the in-process
|
|
42653
43288
|
* `DiscoveredDevice` interface used by `DeviceDiscovery`.
|
|
@@ -42682,7 +43317,17 @@ var DiscoveryCandidateSchema = object({
|
|
|
42682
43317
|
/** Numeric id of the device this candidate was matched to. Set with `alreadyOnboarded`. */
|
|
42683
43318
|
onboardedDeviceId: number().optional(),
|
|
42684
43319
|
/** Operator-facing name of the matched device, so the UI can say WHICH one it is. */
|
|
42685
|
-
onboardedName: string().optional()
|
|
43320
|
+
onboardedName: string().optional(),
|
|
43321
|
+
/**
|
|
43322
|
+
* This candidate is an INTEGRATION to set up (a gateway, a hub, a controller),
|
|
43323
|
+
* not a device to adopt. Replaces the `prefilledConfig.setupIntegration` marker,
|
|
43324
|
+
* which is still read for one release.
|
|
43325
|
+
*/
|
|
43326
|
+
setupIntegration: boolean().optional(),
|
|
43327
|
+
/** `stableId` of the gateway candidate this device was found BEHIND. */
|
|
43328
|
+
parentStableId: string().optional(),
|
|
43329
|
+
/** `false` = shown for context but not pickable. Default true. */
|
|
43330
|
+
selectable: boolean().optional()
|
|
42686
43331
|
});
|
|
42687
43332
|
/**
|
|
42688
43333
|
* Flat device summary returned by `createDevice` / `adoptDiscoveredDevice`.
|
|
@@ -42735,6 +43380,12 @@ method(_void(), _void(), { kind: "mutation" }), method(_void(), _void(), { kind:
|
|
|
42735
43380
|
}), method(object({}), boolean()), method(object({ params: record(string(), unknown()).optional() }), array(DiscoveryCandidateSchema), {
|
|
42736
43381
|
kind: "mutation",
|
|
42737
43382
|
auth: "admin"
|
|
43383
|
+
}), method(object({}), array(DiscoveryModeSchema)), method(object({
|
|
43384
|
+
hits: array(DiscoveryHitSchema),
|
|
43385
|
+
params: record(string(), unknown()).optional()
|
|
43386
|
+
}), array(DiscoveryCandidateSchema), {
|
|
43387
|
+
kind: "mutation",
|
|
43388
|
+
auth: "admin"
|
|
42738
43389
|
}), method(object({}), CreationSchemaOutputSchema), method(object({}), object({ deviceType: _enum(DeviceType).nullable() })), method(object({ candidate: DiscoveryCandidateSchema }), DeviceSummarySchema, {
|
|
42739
43390
|
kind: "mutation",
|
|
42740
43391
|
auth: "admin"
|
|
@@ -43462,17 +44113,23 @@ method(object({
|
|
|
43462
44113
|
}), method(object({}), object({ providers: array(object({
|
|
43463
44114
|
addonId: string(),
|
|
43464
44115
|
label: string()
|
|
43465
|
-
})).readonly() }), { auth: "admin" }), method(
|
|
43466
|
-
|
|
43467
|
-
|
|
43468
|
-
|
|
43469
|
-
|
|
43470
|
-
|
|
43471
|
-
|
|
43472
|
-
|
|
43473
|
-
}),
|
|
44116
|
+
})).readonly() }), { auth: "admin" }), method(
|
|
44117
|
+
/** `subnets`: extra CIDRs for THIS scan, on top of the hub's own and the saved list. */
|
|
44118
|
+
object({ subnets: array(string()).optional() }),
|
|
44119
|
+
object({ groups: array(object({
|
|
44120
|
+
addonId: string(),
|
|
44121
|
+
label: string(),
|
|
44122
|
+
candidates: array(DiscoveryCandidateSchema).readonly(),
|
|
44123
|
+
error: string().nullable()
|
|
44124
|
+
})).readonly() }),
|
|
44125
|
+
{
|
|
44126
|
+
kind: "mutation",
|
|
44127
|
+
auth: "admin"
|
|
44128
|
+
}
|
|
44129
|
+
), method(object({
|
|
43474
44130
|
addonId: string(),
|
|
43475
|
-
params: record(string(), unknown()).optional()
|
|
44131
|
+
params: record(string(), unknown()).optional(),
|
|
44132
|
+
subnets: array(string()).optional()
|
|
43476
44133
|
}), object({ candidates: array(DiscoveryCandidateSchema).readonly() }), {
|
|
43477
44134
|
kind: "mutation",
|
|
43478
44135
|
auth: "admin"
|
|
@@ -56018,6 +56675,12 @@ var TerminalInstanceInfoSchema = object({
|
|
|
56018
56675
|
instanceId: string(),
|
|
56019
56676
|
cameraStableId: string(),
|
|
56020
56677
|
nodeId: string(),
|
|
56678
|
+
/**
|
|
56679
|
+
* False while the node the instance is bound to is not in the cluster
|
|
56680
|
+
* topology (forgotten, renamed, re-paired). The instance is kept; the
|
|
56681
|
+
* operator re-points it with `updateInstance({ targetNodeId })`.
|
|
56682
|
+
*/
|
|
56683
|
+
nodeInCluster: boolean(),
|
|
56021
56684
|
profileId: string(),
|
|
56022
56685
|
profileLabel: string(),
|
|
56023
56686
|
name: string(),
|
|
@@ -56067,6 +56730,8 @@ method(_void(), array(TerminalProfileInfoSchema).readonly(), { auth: "admin" }),
|
|
|
56067
56730
|
auth: "admin"
|
|
56068
56731
|
}), method(object({
|
|
56069
56732
|
instanceId: string().min(1),
|
|
56733
|
+
/** Re-point the instance to another node; the profile must exist there. */
|
|
56734
|
+
targetNodeId: string().min(1).max(256).optional(),
|
|
56070
56735
|
name: string().trim().min(1).max(160).optional(),
|
|
56071
56736
|
executable: string().max(1024).optional(),
|
|
56072
56737
|
args: array(string().max(2048)).max(64).optional(),
|
|
@@ -61092,7 +61757,9 @@ method(_void(), array(IntegrationWithStateSchema)), method(object({ id: string()
|
|
|
61092
61757
|
id: string(),
|
|
61093
61758
|
settings: record(string(), unknown()),
|
|
61094
61759
|
/** Keys the form's schema declares secret (by type) — keychain-stored (D787). */
|
|
61095
|
-
secretKeys: array(string()).optional()
|
|
61760
|
+
secretKeys: array(string()).optional(),
|
|
61761
|
+
/** The integration's own addon applies the change in-process and asks the hub not to respawn it. */
|
|
61762
|
+
skipRestart: boolean().optional()
|
|
61096
61763
|
}), object({ success: boolean() }), {
|
|
61097
61764
|
kind: "mutation",
|
|
61098
61765
|
auth: "admin"
|
|
@@ -61569,6 +62236,39 @@ var TlsStatusSchema = object({
|
|
|
61569
62236
|
hasCa: boolean()
|
|
61570
62237
|
}).nullable()
|
|
61571
62238
|
});
|
|
62239
|
+
/** One provider's ask of the scan engine: the modes it declared. */
|
|
62240
|
+
var ScanRequestSchema = object({
|
|
62241
|
+
providerId: string().min(1),
|
|
62242
|
+
modes: array(DiscoveryModeSchema)
|
|
62243
|
+
});
|
|
62244
|
+
var ScanErrorSchema = object({
|
|
62245
|
+
/** Absent for a failure that is the scan's own (a bad subnet, a socket that would not open). */
|
|
62246
|
+
providerId: string().optional(),
|
|
62247
|
+
/** The mode family that failed (`mdns`, `http-probe`, …). */
|
|
62248
|
+
mode: string().optional(),
|
|
62249
|
+
message: string()
|
|
62250
|
+
});
|
|
62251
|
+
/** What one scan did, per mode family; the engine logs the same numbers once. */
|
|
62252
|
+
var ScanStatsSchema = object({
|
|
62253
|
+
hostsProbed: number().int(),
|
|
62254
|
+
hits: number().int(),
|
|
62255
|
+
timeouts: number().int(),
|
|
62256
|
+
byMode: record(string(), object({
|
|
62257
|
+
probed: number().int(),
|
|
62258
|
+
hits: number().int(),
|
|
62259
|
+
timeouts: number().int()
|
|
62260
|
+
}))
|
|
62261
|
+
});
|
|
62262
|
+
var ScanNetworkResultSchema = object({
|
|
62263
|
+
hits: array(object({
|
|
62264
|
+
providerId: string(),
|
|
62265
|
+
hit: DiscoveryHitSchema
|
|
62266
|
+
})),
|
|
62267
|
+
/** CIDRs actually covered: the hub's own /24s, the saved list and the per-call list. */
|
|
62268
|
+
subnetsScanned: array(string()),
|
|
62269
|
+
errors: array(ScanErrorSchema),
|
|
62270
|
+
stats: ScanStatsSchema
|
|
62271
|
+
});
|
|
61572
62272
|
method(_void(), ListResultSchema), method(_void(), PreferredSchema), method(object({
|
|
61573
62273
|
/**
|
|
61574
62274
|
* LEGACY HINT — do not send from new code. Kept optional so clients
|
|
@@ -61623,6 +62323,16 @@ method(_void(), ListResultSchema), method(_void(), PreferredSchema), method(obje
|
|
|
61623
62323
|
}), method(_void(), object({ pem: string() })), method(_void(), TlsStatusSchema, {
|
|
61624
62324
|
kind: "mutation",
|
|
61625
62325
|
auth: "admin"
|
|
62326
|
+
}), method(object({
|
|
62327
|
+
requests: array(ScanRequestSchema),
|
|
62328
|
+
subnets: array(string()).optional()
|
|
62329
|
+
}), ScanNetworkResultSchema, {
|
|
62330
|
+
kind: "mutation",
|
|
62331
|
+
auth: "admin",
|
|
62332
|
+
timeoutMs: 9e4
|
|
62333
|
+
}), method(_void(), object({ subnets: array(string()) }), { auth: "admin" }), method(object({ subnets: array(string()) }), object({ subnets: array(string()) }), {
|
|
62334
|
+
kind: "mutation",
|
|
62335
|
+
auth: "admin"
|
|
61626
62336
|
}), method(_void(), TlsStatusSchema, {
|
|
61627
62337
|
kind: "mutation",
|
|
61628
62338
|
auth: "admin"
|
|
@@ -68566,6 +69276,13 @@ Object.freeze({
|
|
|
68566
69276
|
access: "create",
|
|
68567
69277
|
role: "admin"
|
|
68568
69278
|
},
|
|
69279
|
+
"addonSettings.getDeclaredSettingsKeys": {
|
|
69280
|
+
capName: "addon-settings",
|
|
69281
|
+
capScope: "system",
|
|
69282
|
+
addonId: null,
|
|
69283
|
+
access: "view",
|
|
69284
|
+
role: "admin"
|
|
69285
|
+
},
|
|
68569
69286
|
"addonSettings.getDeviceSettings": {
|
|
68570
69287
|
capName: "addon-settings",
|
|
68571
69288
|
capScope: "system",
|
|
@@ -68587,6 +69304,13 @@ Object.freeze({
|
|
|
68587
69304
|
access: "view",
|
|
68588
69305
|
role: "admin"
|
|
68589
69306
|
},
|
|
69307
|
+
"addonSettings.unsetStoredSettingsKeys": {
|
|
69308
|
+
capName: "addon-settings",
|
|
69309
|
+
capScope: "system",
|
|
69310
|
+
addonId: null,
|
|
69311
|
+
access: "create",
|
|
69312
|
+
role: "admin"
|
|
69313
|
+
},
|
|
68590
69314
|
"addonSettings.updateDeviceSettings": {
|
|
68591
69315
|
capName: "addon-settings",
|
|
68592
69316
|
capScope: "system",
|
|
@@ -71002,6 +71726,13 @@ Object.freeze({
|
|
|
71002
71726
|
access: "create",
|
|
71003
71727
|
role: "admin"
|
|
71004
71728
|
},
|
|
71729
|
+
"deviceProvider.classifyDiscoveryHits": {
|
|
71730
|
+
capName: "device-provider",
|
|
71731
|
+
capScope: "system",
|
|
71732
|
+
addonId: null,
|
|
71733
|
+
access: "create",
|
|
71734
|
+
role: "admin"
|
|
71735
|
+
},
|
|
71005
71736
|
"deviceProvider.createDevice": {
|
|
71006
71737
|
capName: "device-provider",
|
|
71007
71738
|
capScope: "system",
|
|
@@ -71030,6 +71761,13 @@ Object.freeze({
|
|
|
71030
71761
|
access: "view",
|
|
71031
71762
|
role: "admin"
|
|
71032
71763
|
},
|
|
71764
|
+
"deviceProvider.getDiscoveryModes": {
|
|
71765
|
+
capName: "device-provider",
|
|
71766
|
+
capScope: "system",
|
|
71767
|
+
addonId: null,
|
|
71768
|
+
access: "view",
|
|
71769
|
+
role: "admin"
|
|
71770
|
+
},
|
|
71033
71771
|
"deviceProvider.getDiscoveryParamsSchema": {
|
|
71034
71772
|
capName: "device-provider",
|
|
71035
71773
|
capScope: "system",
|
|
@@ -71807,6 +72545,13 @@ Object.freeze({
|
|
|
71807
72545
|
access: "create",
|
|
71808
72546
|
role: "admin"
|
|
71809
72547
|
},
|
|
72548
|
+
"keychain.releaseRecordRefs": {
|
|
72549
|
+
capName: "keychain",
|
|
72550
|
+
capScope: "system",
|
|
72551
|
+
addonId: null,
|
|
72552
|
+
access: "create",
|
|
72553
|
+
role: "admin"
|
|
72554
|
+
},
|
|
71810
72555
|
"keychain.resolve": {
|
|
71811
72556
|
capName: "keychain",
|
|
71812
72557
|
capScope: "system",
|
|
@@ -72227,6 +72972,13 @@ Object.freeze({
|
|
|
72227
72972
|
access: "view",
|
|
72228
72973
|
role: "admin"
|
|
72229
72974
|
},
|
|
72975
|
+
"localNetwork.getScanSubnets": {
|
|
72976
|
+
capName: "local-network",
|
|
72977
|
+
capScope: "system",
|
|
72978
|
+
addonId: null,
|
|
72979
|
+
access: "view",
|
|
72980
|
+
role: "admin"
|
|
72981
|
+
},
|
|
72230
72982
|
"localNetwork.getTlsStatus": {
|
|
72231
72983
|
capName: "local-network",
|
|
72232
72984
|
capScope: "system",
|
|
@@ -72276,6 +73028,13 @@ Object.freeze({
|
|
|
72276
73028
|
access: "create",
|
|
72277
73029
|
role: "admin"
|
|
72278
73030
|
},
|
|
73031
|
+
"localNetwork.scanNetwork": {
|
|
73032
|
+
capName: "local-network",
|
|
73033
|
+
capScope: "system",
|
|
73034
|
+
addonId: null,
|
|
73035
|
+
access: "create",
|
|
73036
|
+
role: "admin"
|
|
73037
|
+
},
|
|
72279
73038
|
"localNetwork.setAddressRole": {
|
|
72280
73039
|
capName: "local-network",
|
|
72281
73040
|
capScope: "system",
|
|
@@ -72297,6 +73056,13 @@ Object.freeze({
|
|
|
72297
73056
|
access: "create",
|
|
72298
73057
|
role: "admin"
|
|
72299
73058
|
},
|
|
73059
|
+
"localNetwork.setScanSubnets": {
|
|
73060
|
+
capName: "local-network",
|
|
73061
|
+
capScope: "system",
|
|
73062
|
+
addonId: null,
|
|
73063
|
+
access: "create",
|
|
73064
|
+
role: "admin"
|
|
73065
|
+
},
|
|
72300
73066
|
"localNetwork.setViewerEndpoints": {
|
|
72301
73067
|
capName: "local-network",
|
|
72302
73068
|
capScope: "system",
|
|
@@ -76518,6 +77284,13 @@ Object.freeze({
|
|
|
76518
77284
|
access: "create",
|
|
76519
77285
|
role: "admin"
|
|
76520
77286
|
},
|
|
77287
|
+
"storageAdmin.dropOrphanedKind": {
|
|
77288
|
+
capName: "storage-admin",
|
|
77289
|
+
capScope: "system",
|
|
77290
|
+
addonId: null,
|
|
77291
|
+
access: "delete",
|
|
77292
|
+
role: "admin"
|
|
77293
|
+
},
|
|
76521
77294
|
"storageAdmin.listKinds": {
|
|
76522
77295
|
capName: "storage-admin",
|
|
76523
77296
|
capScope: "system",
|
|
@@ -76539,6 +77312,27 @@ Object.freeze({
|
|
|
76539
77312
|
access: "view",
|
|
76540
77313
|
role: "admin"
|
|
76541
77314
|
},
|
|
77315
|
+
"storageAdmin.scanStaleData": {
|
|
77316
|
+
capName: "storage-admin",
|
|
77317
|
+
capScope: "system",
|
|
77318
|
+
addonId: null,
|
|
77319
|
+
access: "create",
|
|
77320
|
+
role: "admin"
|
|
77321
|
+
},
|
|
77322
|
+
"storageAdmin.staleDataReport": {
|
|
77323
|
+
capName: "storage-admin",
|
|
77324
|
+
capScope: "system",
|
|
77325
|
+
addonId: null,
|
|
77326
|
+
access: "view",
|
|
77327
|
+
role: "admin"
|
|
77328
|
+
},
|
|
77329
|
+
"storageAdmin.unsetStaleSettingsKey": {
|
|
77330
|
+
capName: "storage-admin",
|
|
77331
|
+
capScope: "system",
|
|
77332
|
+
addonId: null,
|
|
77333
|
+
access: "create",
|
|
77334
|
+
role: "admin"
|
|
77335
|
+
},
|
|
76542
77336
|
"storageEvictable.evict": {
|
|
76543
77337
|
capName: "storage-evictable",
|
|
76544
77338
|
capScope: "system",
|