@camstack/addon-training 0.1.112 → 0.1.113
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 +6 -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 +5211 -5181
- package/dist/{_virtual_mf-localSharedImportMap___mfe_internal__addon_training_page-CcSHMntB.mjs → _virtual_mf-localSharedImportMap___mfe_internal__addon_training_page-Bya5bIs3.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-DP3QaLL9.mjs → dist-B7trMqj7.mjs} +901 -115
- package/dist/{dist-BWaaetIL.js → dist-j2JtuQ21.js} +901 -115
- package/dist/{hostInit-CL4HR5_U.mjs → hostInit-7-7XYgjM.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-DlmMJ8_m.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
|
@@ -5621,7 +5621,7 @@ var ZodIssueCode = {
|
|
|
5621
5621
|
var ZodFirstPartyTypeKind;
|
|
5622
5622
|
ZodFirstPartyTypeKind || (ZodFirstPartyTypeKind = {});
|
|
5623
5623
|
//#endregion
|
|
5624
|
-
//#region ../types/dist/sleep-
|
|
5624
|
+
//#region ../types/dist/sleep-CeyhrcOk.mjs
|
|
5625
5625
|
/**
|
|
5626
5626
|
* The audio chunk plane's byte format, and the ONE expansion from a coded
|
|
5627
5627
|
* window to float samples (D455).
|
|
@@ -7688,6 +7688,7 @@ var BaseAddon = class {
|
|
|
7688
7688
|
* a warning and falls back rather than crashing boot.
|
|
7689
7689
|
*/
|
|
7690
7690
|
state(key, schema, fallback) {
|
|
7691
|
+
this._declaredStateKeys.add(key);
|
|
7691
7692
|
return createDurableState({
|
|
7692
7693
|
key,
|
|
7693
7694
|
schema,
|
|
@@ -7703,6 +7704,96 @@ var BaseAddon = class {
|
|
|
7703
7704
|
} })
|
|
7704
7705
|
});
|
|
7705
7706
|
}
|
|
7707
|
+
/** Durable-state keys this process registered through {@link state}. */
|
|
7708
|
+
_declaredStateKeys = /* @__PURE__ */ new Set();
|
|
7709
|
+
/**
|
|
7710
|
+
* Stale-data audit: every global-settings key this addon still declares —
|
|
7711
|
+
* constructor defaults, settings-schema fields (layout containers included),
|
|
7712
|
+
* durable-state keys and the root of each `secretStatePaths` entry. Answered
|
|
7713
|
+
* here, in the addon's own process, so the hub keeps no copy of it.
|
|
7714
|
+
*/
|
|
7715
|
+
async getDeclaredSettingsKeys() {
|
|
7716
|
+
return { keys: [...this.declaredKeySet()].toSorted() };
|
|
7717
|
+
}
|
|
7718
|
+
declaredKeySet() {
|
|
7719
|
+
const keys = new Set(Object.keys(this.defaults));
|
|
7720
|
+
const schema = this.globalSettingsSchema();
|
|
7721
|
+
if (schema) for (const section of schema.sections) for (const key of collectFieldKeys(section.fields)) keys.add(key);
|
|
7722
|
+
for (const key of this._declaredStateKeys) keys.add(key);
|
|
7723
|
+
for (const path of this.secretStatePaths) {
|
|
7724
|
+
const root = path.split(/[.[]/, 1)[0];
|
|
7725
|
+
if (root) keys.add(root);
|
|
7726
|
+
}
|
|
7727
|
+
return keys;
|
|
7728
|
+
}
|
|
7729
|
+
/**
|
|
7730
|
+
* Stale-data audit: remove stored global-settings keys the addon no longer
|
|
7731
|
+
* declares, and clear the keychain values their markers held — except a value
|
|
7732
|
+
* a surviving key still points at. A declared or absent key is refused.
|
|
7733
|
+
*/
|
|
7734
|
+
async unsetStoredSettingsKeys(keys) {
|
|
7735
|
+
const settings = this._ctx?.settings;
|
|
7736
|
+
const raw = this.rawSettings();
|
|
7737
|
+
if (!settings || !raw) return {
|
|
7738
|
+
removed: [],
|
|
7739
|
+
refused: keys.map((key) => ({
|
|
7740
|
+
key,
|
|
7741
|
+
reason: "no settings store"
|
|
7742
|
+
})),
|
|
7743
|
+
secretsCleared: 0
|
|
7744
|
+
};
|
|
7745
|
+
let stored;
|
|
7746
|
+
try {
|
|
7747
|
+
stored = await raw.readAddonStore();
|
|
7748
|
+
} catch (error) {
|
|
7749
|
+
const reason = `store unreadable: ${error instanceof Error ? error.message : "unknown"}`;
|
|
7750
|
+
return {
|
|
7751
|
+
removed: [],
|
|
7752
|
+
refused: keys.map((key) => ({
|
|
7753
|
+
key,
|
|
7754
|
+
reason
|
|
7755
|
+
})),
|
|
7756
|
+
secretsCleared: 0
|
|
7757
|
+
};
|
|
7758
|
+
}
|
|
7759
|
+
const declared = this.declaredKeySet();
|
|
7760
|
+
const removed = [];
|
|
7761
|
+
const refused = [];
|
|
7762
|
+
for (const key of keys) {
|
|
7763
|
+
const base = key.split("@", 1)[0] ?? key;
|
|
7764
|
+
if (declared.has(base)) refused.push({
|
|
7765
|
+
key,
|
|
7766
|
+
reason: "still declared by the addon"
|
|
7767
|
+
});
|
|
7768
|
+
else if (!(key in stored)) refused.push({
|
|
7769
|
+
key,
|
|
7770
|
+
reason: "not stored"
|
|
7771
|
+
});
|
|
7772
|
+
else removed.push(key);
|
|
7773
|
+
}
|
|
7774
|
+
if (removed.length === 0) return {
|
|
7775
|
+
removed,
|
|
7776
|
+
refused,
|
|
7777
|
+
secretsCleared: 0
|
|
7778
|
+
};
|
|
7779
|
+
const kept = /* @__PURE__ */ new Set();
|
|
7780
|
+
const held = /* @__PURE__ */ new Set();
|
|
7781
|
+
for (const [key, value] of Object.entries(stored)) {
|
|
7782
|
+
const target = removed.includes(key) ? held : kept;
|
|
7783
|
+
for (const ref of collectSecretMarkerRefs(value)) target.add(ref);
|
|
7784
|
+
}
|
|
7785
|
+
const refsToClear = [...held].filter((ref) => !kept.has(ref));
|
|
7786
|
+
const patch = {};
|
|
7787
|
+
for (const key of removed) patch[key] = void 0;
|
|
7788
|
+
await settings.writeAddonStore(patch);
|
|
7789
|
+
const secretsCleared = refsToClear.length > 0 && this._ctx?.secrets ? await this._ctx.secrets.delete(refsToClear) : 0;
|
|
7790
|
+
await this.resolveConfig();
|
|
7791
|
+
return {
|
|
7792
|
+
removed,
|
|
7793
|
+
refused,
|
|
7794
|
+
secretsCleared
|
|
7795
|
+
};
|
|
7796
|
+
}
|
|
7706
7797
|
/** Per-device variant of {@link state}, backed by the per-device store. */
|
|
7707
7798
|
deviceState(deviceId, key, schema, fallback) {
|
|
7708
7799
|
return createDurableState({
|
|
@@ -7973,6 +8064,21 @@ function dropPerNodeFields(fields) {
|
|
|
7973
8064
|
}
|
|
7974
8065
|
return kept;
|
|
7975
8066
|
}
|
|
8067
|
+
function collectFieldKeys(fields) {
|
|
8068
|
+
const collected = [];
|
|
8069
|
+
for (const field of fields) {
|
|
8070
|
+
if (field.type === "group") {
|
|
8071
|
+
collected.push(...collectFieldKeys(field.fields));
|
|
8072
|
+
continue;
|
|
8073
|
+
}
|
|
8074
|
+
if (field.type === "sub-tabs") {
|
|
8075
|
+
for (const tab of field.tabs) collected.push(...collectFieldKeys(tab.fields));
|
|
8076
|
+
continue;
|
|
8077
|
+
}
|
|
8078
|
+
if ("key" in field && typeof field.key === "string") collected.push(field.key);
|
|
8079
|
+
}
|
|
8080
|
+
return collected;
|
|
8081
|
+
}
|
|
7976
8082
|
function collectPerNodeFieldKeys(fields) {
|
|
7977
8083
|
const collected = [];
|
|
7978
8084
|
for (const field of fields) {
|
|
@@ -16364,8 +16470,172 @@ object({
|
|
|
16364
16470
|
quantity: ReadingQuantitySchema,
|
|
16365
16471
|
unit: string().min(1)
|
|
16366
16472
|
});
|
|
16367
|
-
|
|
16368
|
-
|
|
16473
|
+
new Set([
|
|
16474
|
+
{
|
|
16475
|
+
id: "person",
|
|
16476
|
+
name: "Person"
|
|
16477
|
+
},
|
|
16478
|
+
{
|
|
16479
|
+
id: "vehicle",
|
|
16480
|
+
name: "Vehicle"
|
|
16481
|
+
},
|
|
16482
|
+
{
|
|
16483
|
+
id: "animal",
|
|
16484
|
+
name: "Animal"
|
|
16485
|
+
},
|
|
16486
|
+
{
|
|
16487
|
+
id: "package",
|
|
16488
|
+
name: "Package"
|
|
16489
|
+
}
|
|
16490
|
+
].map((l) => l.id));
|
|
16491
|
+
var COCO_TO_MACRO = {
|
|
16492
|
+
mapping: {
|
|
16493
|
+
person: "person",
|
|
16494
|
+
bicycle: "vehicle",
|
|
16495
|
+
car: "vehicle",
|
|
16496
|
+
motorcycle: "vehicle",
|
|
16497
|
+
airplane: "vehicle",
|
|
16498
|
+
bus: "vehicle",
|
|
16499
|
+
train: "vehicle",
|
|
16500
|
+
truck: "vehicle",
|
|
16501
|
+
boat: "vehicle",
|
|
16502
|
+
bird: "animal",
|
|
16503
|
+
cat: "animal",
|
|
16504
|
+
dog: "animal",
|
|
16505
|
+
horse: "animal",
|
|
16506
|
+
sheep: "animal",
|
|
16507
|
+
cow: "animal",
|
|
16508
|
+
elephant: "animal",
|
|
16509
|
+
bear: "animal",
|
|
16510
|
+
zebra: "animal",
|
|
16511
|
+
giraffe: "animal",
|
|
16512
|
+
suitcase: "package",
|
|
16513
|
+
backpack: "package",
|
|
16514
|
+
handbag: "package"
|
|
16515
|
+
},
|
|
16516
|
+
preserveOriginal: false
|
|
16517
|
+
};
|
|
16518
|
+
/**
|
|
16519
|
+
* WHAT a detection-shaped leaf is about: one MACRO class (person, vehicle,
|
|
16520
|
+
* animal, package) plus an OPTIONAL label that narrows it.
|
|
16521
|
+
*
|
|
16522
|
+
* The taxonomy is `COCO_TO_MACRO` (and `CLASS_MAP_MACRO_TARGETS`) — never a
|
|
16523
|
+
* second list. The label that fits depends on the macro class:
|
|
16524
|
+
*
|
|
16525
|
+
* - `animal` → a sub-class (`dog`, `cat`, …);
|
|
16526
|
+
* - `person` → a known face (an identity of the `face-gallery`);
|
|
16527
|
+
* - `vehicle` → a plate (its text) or a sub-class (`car`, `truck`, …);
|
|
16528
|
+
* - `package` → a sub-class.
|
|
16529
|
+
*
|
|
16530
|
+
* `other` exists only so a class the taxonomy does not know (a custom model's
|
|
16531
|
+
* `forklift`) survives the conversion of a stored recipe without widening.
|
|
16532
|
+
*
|
|
16533
|
+
* A label is decided LATE (D683): face recognition and LPR land after the
|
|
16534
|
+
* detection starts. The track-lifecycle `update` event carries the newly
|
|
16535
|
+
* resolved `label` / `plateText`, which is why a leaf with a label fires when
|
|
16536
|
+
* the subject GETS it — not at the first detection.
|
|
16537
|
+
*/
|
|
16538
|
+
var SubClassLabelSchema = object({
|
|
16539
|
+
kind: literal("sub-class"),
|
|
16540
|
+
className: string().min(1)
|
|
16541
|
+
});
|
|
16542
|
+
var IdentityLabelSchema = object({
|
|
16543
|
+
kind: literal("identity"),
|
|
16544
|
+
/** The `face-gallery` identity id (stable across a rename). */
|
|
16545
|
+
identityId: string().min(1),
|
|
16546
|
+
/** The identity's name — what a track-lifecycle event carries as `label`. */
|
|
16547
|
+
name: string().min(1)
|
|
16548
|
+
});
|
|
16549
|
+
var PlateLabelSchema = object({
|
|
16550
|
+
kind: literal("plate"),
|
|
16551
|
+
text: string().min(1)
|
|
16552
|
+
});
|
|
16553
|
+
function macroOf$1(className) {
|
|
16554
|
+
return COCO_TO_MACRO.mapping[className.toLowerCase()] ?? className.toLowerCase();
|
|
16555
|
+
}
|
|
16556
|
+
/** A sub-class label must belong to the macro it is under. */
|
|
16557
|
+
function subClassBelongs(macro, label) {
|
|
16558
|
+
return label === void 0 || macroOf$1(label.className) === macro;
|
|
16559
|
+
}
|
|
16560
|
+
var subClassOf = (macro) => SubClassLabelSchema.refine((l) => subClassBelongs(macro, l), { message: `that class is not a kind of ${macro} in the detection taxonomy` });
|
|
16561
|
+
var DetectionSubjectSchema = discriminatedUnion("macro", [
|
|
16562
|
+
object({
|
|
16563
|
+
macro: literal("animal"),
|
|
16564
|
+
label: subClassOf("animal").optional()
|
|
16565
|
+
}),
|
|
16566
|
+
object({
|
|
16567
|
+
macro: literal("person"),
|
|
16568
|
+
label: IdentityLabelSchema.optional()
|
|
16569
|
+
}),
|
|
16570
|
+
object({
|
|
16571
|
+
macro: literal("vehicle"),
|
|
16572
|
+
label: discriminatedUnion("kind", [SubClassLabelSchema.refine((l) => subClassBelongs("vehicle", l), { message: "that class is not a kind of vehicle in the detection taxonomy" }), PlateLabelSchema]).optional()
|
|
16573
|
+
}),
|
|
16574
|
+
object({
|
|
16575
|
+
macro: literal("package"),
|
|
16576
|
+
label: subClassOf("package").optional()
|
|
16577
|
+
}),
|
|
16578
|
+
object({
|
|
16579
|
+
macro: literal("other"),
|
|
16580
|
+
className: string().min(1)
|
|
16581
|
+
})
|
|
16582
|
+
]);
|
|
16583
|
+
/**
|
|
16584
|
+
* The subject of a PARKED object. The stationary registry's event carries a
|
|
16585
|
+
* class and a zone, no face and no plate — an identity or plate label there
|
|
16586
|
+
* could never match, so the schema refuses it instead of letting it sit dead.
|
|
16587
|
+
*/
|
|
16588
|
+
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" });
|
|
16589
|
+
/**
|
|
16590
|
+
* A stored class string as a subject: a macro name stays a macro; a raw class
|
|
16591
|
+
* the taxonomy files under a macro becomes that macro plus the sub-class label
|
|
16592
|
+
* (`dog` → animal / dog); anything else is `other`, kept verbatim.
|
|
16593
|
+
*/
|
|
16594
|
+
function subjectFromClassName(className) {
|
|
16595
|
+
const name = className.trim().toLowerCase();
|
|
16596
|
+
const macro = COCO_TO_MACRO.mapping[name];
|
|
16597
|
+
if (new Set(Object.values(COCO_TO_MACRO.mapping)).has(name)) return macroOnly(name);
|
|
16598
|
+
if (macro === void 0) return {
|
|
16599
|
+
macro: "other",
|
|
16600
|
+
className
|
|
16601
|
+
};
|
|
16602
|
+
const label = {
|
|
16603
|
+
kind: "sub-class",
|
|
16604
|
+
className: name
|
|
16605
|
+
};
|
|
16606
|
+
switch (macro) {
|
|
16607
|
+
case "animal": return {
|
|
16608
|
+
macro: "animal",
|
|
16609
|
+
label
|
|
16610
|
+
};
|
|
16611
|
+
case "vehicle": return {
|
|
16612
|
+
macro: "vehicle",
|
|
16613
|
+
label
|
|
16614
|
+
};
|
|
16615
|
+
case "package": return {
|
|
16616
|
+
macro: "package",
|
|
16617
|
+
label
|
|
16618
|
+
};
|
|
16619
|
+
default: return {
|
|
16620
|
+
macro: "other",
|
|
16621
|
+
className
|
|
16622
|
+
};
|
|
16623
|
+
}
|
|
16624
|
+
}
|
|
16625
|
+
function macroOnly(macro) {
|
|
16626
|
+
switch (macro) {
|
|
16627
|
+
case "animal": return { macro: "animal" };
|
|
16628
|
+
case "person": return { macro: "person" };
|
|
16629
|
+
case "vehicle": return { macro: "vehicle" };
|
|
16630
|
+
case "package": return { macro: "package" };
|
|
16631
|
+
default: return {
|
|
16632
|
+
macro: "other",
|
|
16633
|
+
className: macro
|
|
16634
|
+
};
|
|
16635
|
+
}
|
|
16636
|
+
}
|
|
16637
|
+
/** How a state leaf compares a device field to a value. Derived from the
|
|
16638
|
+
* field's `kind` in `deviceManager.getWireableFields`, never hand-maintained. */
|
|
16369
16639
|
var AutomationConditionOperatorSchema = _enum([
|
|
16370
16640
|
"eq",
|
|
16371
16641
|
"ne",
|
|
@@ -16376,12 +16646,76 @@ var AutomationConditionOperatorSchema = _enum([
|
|
|
16376
16646
|
"contains",
|
|
16377
16647
|
"in"
|
|
16378
16648
|
]);
|
|
16379
|
-
|
|
16380
|
-
|
|
16649
|
+
/**
|
|
16650
|
+
* D8 compliance, and it is the reason a "becomes" leaf is not merely an event
|
|
16651
|
+
* subscription: it evaluates against the **state mirror**, which is reconciled,
|
|
16652
|
+
* and an event only WAKES the evaluation. A dropped event therefore DELAYS a
|
|
16653
|
+
* fire; it does not lose it.
|
|
16654
|
+
*/
|
|
16655
|
+
var DeviceBecomesLeafSchema = object({
|
|
16656
|
+
kind: literal("device-becomes"),
|
|
16657
|
+
deviceId: number().int().nonnegative(),
|
|
16658
|
+
cap: string().min(1),
|
|
16659
|
+
fieldPath: string().min(1),
|
|
16660
|
+
/** Fire when the field takes this value. Omit to fire on any change. */
|
|
16661
|
+
becomes: union([
|
|
16662
|
+
string(),
|
|
16663
|
+
number(),
|
|
16664
|
+
boolean()
|
|
16665
|
+
]).optional(),
|
|
16666
|
+
/** Only on a CHANGE of value, not on every re-report. */
|
|
16667
|
+
edge: boolean().optional(),
|
|
16668
|
+
/** The new value must hold this long before it counts. */
|
|
16669
|
+
forMs: number().int().min(0).max(864e5).optional(),
|
|
16670
|
+
/** Collapse a burst into one occurrence. */
|
|
16671
|
+
debounceMs: number().int().min(0).max(6e5).optional()
|
|
16672
|
+
});
|
|
16673
|
+
var DeviceEventLeafSchema = object({
|
|
16674
|
+
kind: literal("device-event"),
|
|
16675
|
+
/** An `EventCategory` value. */
|
|
16676
|
+
category: string().min(1),
|
|
16677
|
+
deviceId: number().int().nonnegative().optional()
|
|
16678
|
+
});
|
|
16679
|
+
var ScheduleLeafSchema = object({
|
|
16680
|
+
kind: literal("schedule"),
|
|
16681
|
+
cron: string().min(1).max(120)
|
|
16682
|
+
});
|
|
16683
|
+
var ManualLeafSchema = object({ kind: literal("manual") });
|
|
16684
|
+
var IntervalLeafSchema = object({
|
|
16685
|
+
kind: literal("interval"),
|
|
16686
|
+
minutes: number().int().min(1).max(1440)
|
|
16687
|
+
});
|
|
16688
|
+
var DetectionLeafSchema = object({
|
|
16689
|
+
kind: literal("detection"),
|
|
16690
|
+
/** One macro class each, optionally narrowed by a label; a track of any listed subject fires. */
|
|
16691
|
+
subjects: array(DetectionSubjectSchema).min(1),
|
|
16692
|
+
deviceIds: array(number().int().nonnegative()).min(1),
|
|
16693
|
+
/** The track must have visited at least one of these zones. */
|
|
16694
|
+
zones: array(string().min(1)).min(1).optional(),
|
|
16695
|
+
/** Best-so-far confidence the track must reach. */
|
|
16696
|
+
minScore: number().min(0).max(1).optional()
|
|
16697
|
+
});
|
|
16698
|
+
var StationaryLeafSchema = object({
|
|
16699
|
+
kind: literal("stationary"),
|
|
16700
|
+
deviceIds: array(number().int().nonnegative()).min(1),
|
|
16701
|
+
subjects: array(StationarySubjectSchema).min(1).optional(),
|
|
16702
|
+
zones: array(string().min(1)).min(1).optional(),
|
|
16703
|
+
/** `appeared`: it became parked. `departed`: the registry retired it. */
|
|
16704
|
+
phase: _enum(["appeared", "departed"])
|
|
16705
|
+
});
|
|
16706
|
+
/** "is": one device field compared to one value, NOW. */
|
|
16707
|
+
var DeviceIsLeafSchema = object({
|
|
16708
|
+
kind: literal("device-is"),
|
|
16381
16709
|
deviceId: number().int().nonnegative(),
|
|
16382
16710
|
cap: string().min(1),
|
|
16383
16711
|
fieldPath: string().min(1),
|
|
16384
16712
|
operator: AutomationConditionOperatorSchema,
|
|
16713
|
+
/**
|
|
16714
|
+
* The value. A number on a quantity field is stored in the field's base unit
|
|
16715
|
+
* (D944); a quantity value is the WRITE form, which the save boundary
|
|
16716
|
+
* replaces with the converted number and `unit`. A leaf that still carries
|
|
16717
|
+
* one is never evaluated (it fails).
|
|
16718
|
+
*/
|
|
16385
16719
|
value: union([
|
|
16386
16720
|
string(),
|
|
16387
16721
|
number(),
|
|
@@ -16389,24 +16723,26 @@ var AutomationConditionLeafSchema = object({
|
|
|
16389
16723
|
array(union([string(), number()])),
|
|
16390
16724
|
QuantityValueSchema
|
|
16391
16725
|
]),
|
|
16726
|
+
/** The unit the person picked for `value` (display only; `value` is in the base unit). */
|
|
16392
16727
|
unit: string().min(1).optional()
|
|
16393
16728
|
});
|
|
16394
|
-
|
|
16729
|
+
/**
|
|
16730
|
+
* True when the camera currently has a PARKED object matching `subjects` in at
|
|
16731
|
+
* least one of `zones`. Reads the zone-analytics snapshot through the same
|
|
16732
|
+
* mirror as every other state leaf, so a dropped event never decides it (D49).
|
|
16733
|
+
*/
|
|
16734
|
+
var StationaryPresentLeafSchema = object({
|
|
16395
16735
|
kind: literal("stationary-present"),
|
|
16396
16736
|
deviceId: number().int().nonnegative(),
|
|
16397
|
-
|
|
16398
|
-
classes: array(string().min(1)).min(1).optional(),
|
|
16399
|
-
/** The parked object must be in at least one of these zones. */
|
|
16737
|
+
subjects: array(StationarySubjectSchema).min(1).optional(),
|
|
16400
16738
|
zones: array(string().min(1)).min(1).optional()
|
|
16401
16739
|
});
|
|
16402
16740
|
/**
|
|
16403
|
-
* The
|
|
16404
|
-
*
|
|
16405
|
-
*
|
|
16406
|
-
* validation is the SAME function `ExpressionSourceSchema` runs, so the two
|
|
16407
|
-
* cannot drift — an expression that one accepts, the other accepts.
|
|
16741
|
+
* The escape hatch: the bounded expression engine over named device bindings.
|
|
16742
|
+
* Declared as a plain object so a discriminated union can read `kind`; the
|
|
16743
|
+
* author-time validation is the SAME function `ExpressionSourceSchema` runs.
|
|
16408
16744
|
*/
|
|
16409
|
-
var
|
|
16745
|
+
var ExpressionLeafSchema = object({
|
|
16410
16746
|
kind: literal("expression"),
|
|
16411
16747
|
expr: string().min(1).max(MAX_EXPRESSION_SOURCE_LENGTH),
|
|
16412
16748
|
bindings: record(string().regex(EXPRESSION_IDENTIFIER_RE), ExpressionBindingSourceSchema)
|
|
@@ -16418,55 +16754,62 @@ var AutomationConditionExpressionSchema = object({
|
|
|
16418
16754
|
path: ["expr"]
|
|
16419
16755
|
});
|
|
16420
16756
|
});
|
|
16421
|
-
var
|
|
16757
|
+
var AutomationWhenSchema = lazy(() => discriminatedUnion("kind", [
|
|
16422
16758
|
object({
|
|
16423
16759
|
kind: literal("all"),
|
|
16424
|
-
children: array(
|
|
16760
|
+
children: array(AutomationWhenSchema)
|
|
16425
16761
|
}),
|
|
16426
16762
|
object({
|
|
16427
16763
|
kind: literal("any"),
|
|
16428
|
-
children: array(
|
|
16764
|
+
children: array(AutomationWhenSchema)
|
|
16429
16765
|
}),
|
|
16430
16766
|
object({
|
|
16431
16767
|
kind: literal("not"),
|
|
16432
|
-
child:
|
|
16768
|
+
child: AutomationWhenSchema
|
|
16433
16769
|
}),
|
|
16434
|
-
|
|
16435
|
-
|
|
16436
|
-
|
|
16770
|
+
DeviceBecomesLeafSchema,
|
|
16771
|
+
DeviceEventLeafSchema,
|
|
16772
|
+
ScheduleLeafSchema,
|
|
16773
|
+
ManualLeafSchema,
|
|
16774
|
+
IntervalLeafSchema,
|
|
16775
|
+
DetectionLeafSchema,
|
|
16776
|
+
StationaryLeafSchema,
|
|
16777
|
+
DeviceIsLeafSchema,
|
|
16778
|
+
StationaryPresentLeafSchema,
|
|
16779
|
+
ExpressionLeafSchema
|
|
16437
16780
|
]));
|
|
16438
16781
|
/**
|
|
16439
|
-
*
|
|
16440
|
-
*
|
|
16441
|
-
*
|
|
16442
|
-
*
|
|
16443
|
-
*
|
|
16444
|
-
*
|
|
16445
|
-
*
|
|
16446
|
-
*
|
|
16447
|
-
|
|
16448
|
-
|
|
16782
|
+
* The recipe shape before the single `when` tree: a flat list of triggers
|
|
16783
|
+
* (OR'd, each an instant) and an optional condition tree. Stored recipes —
|
|
16784
|
+
* the `AUTOMATION_RECIPE` literal of every block saved so far, and whatever an
|
|
16785
|
+
* older client still posts — are in this shape, so it stays READABLE here, and
|
|
16786
|
+
* {@link convertLegacyRecipe} turns it into the new one, losslessly and one
|
|
16787
|
+
* way. Nothing writes this shape any more.
|
|
16788
|
+
*
|
|
16789
|
+
* `{ triggers: [t1…tn], conditions?: C }`
|
|
16790
|
+
* → `when = all(any(t1…tn), C)`, or `any(t1…tn)` without `C`;
|
|
16791
|
+
* a single trigger is not wrapped in `any`.
|
|
16792
|
+
* a `condition` leaf → a `device-is` leaf (the "is" verb);
|
|
16793
|
+
* a `device-state` trigger → a `device-becomes` leaf (the "becomes" verb);
|
|
16794
|
+
* `classes: ['dog']` → the macro `animal` with the label `dog`.
|
|
16795
|
+
*/
|
|
16796
|
+
var LegacyTriggerSchema = discriminatedUnion("kind", [
|
|
16449
16797
|
object({
|
|
16450
16798
|
kind: literal("device-state"),
|
|
16451
16799
|
deviceId: number().int().nonnegative(),
|
|
16452
16800
|
cap: string().min(1),
|
|
16453
16801
|
fieldPath: string().min(1),
|
|
16454
|
-
/** Fire when the field takes this value. Omit to fire on any change. */
|
|
16455
16802
|
becomes: union([
|
|
16456
16803
|
string(),
|
|
16457
16804
|
number(),
|
|
16458
16805
|
boolean()
|
|
16459
16806
|
]).optional(),
|
|
16460
|
-
/** Only on a CHANGE of value, not on every re-report. */
|
|
16461
16807
|
edge: boolean().optional(),
|
|
16462
|
-
/** The condition must hold this long before the run starts. */
|
|
16463
16808
|
forMs: number().int().min(0).max(864e5).optional(),
|
|
16464
|
-
/** Collapse a burst into one run. */
|
|
16465
16809
|
debounceMs: number().int().min(0).max(6e5).optional()
|
|
16466
16810
|
}),
|
|
16467
16811
|
object({
|
|
16468
16812
|
kind: literal("device-event"),
|
|
16469
|
-
/** An `EventCategory` value. */
|
|
16470
16813
|
category: string().min(1),
|
|
16471
16814
|
deviceId: number().int().nonnegative().optional()
|
|
16472
16815
|
}),
|
|
@@ -16477,25 +16820,16 @@ var AutomationTriggerSchema = discriminatedUnion("kind", [
|
|
|
16477
16820
|
object({ kind: literal("manual") }),
|
|
16478
16821
|
object({
|
|
16479
16822
|
kind: literal("detection"),
|
|
16480
|
-
/** Class names. A macro class (`animal`, `vehicle`, `person`, `package`)
|
|
16481
|
-
* matches every raw class that maps to it; any other name matches
|
|
16482
|
-
* exactly. */
|
|
16483
16823
|
classes: array(string().min(1)).min(1),
|
|
16484
16824
|
deviceIds: array(number().int().nonnegative()).min(1),
|
|
16485
|
-
/** The track must have visited at least one of these zones. */
|
|
16486
16825
|
zones: array(string().min(1)).min(1).optional(),
|
|
16487
|
-
/** Best-so-far confidence the track must reach. */
|
|
16488
16826
|
minScore: number().min(0).max(1).optional()
|
|
16489
16827
|
}),
|
|
16490
16828
|
object({
|
|
16491
16829
|
kind: literal("stationary"),
|
|
16492
16830
|
deviceIds: array(number().int().nonnegative()).min(1),
|
|
16493
|
-
/** Class names; a macro class matches like the detection trigger. */
|
|
16494
16831
|
classes: array(string().min(1)).min(1).optional(),
|
|
16495
|
-
/** The parked object must be in at least one of these zones. */
|
|
16496
16832
|
zones: array(string().min(1)).min(1).optional(),
|
|
16497
|
-
/** `appeared`: it became parked. `departed`: the registry retired it.
|
|
16498
|
-
* The vocabulary of `PipelineAnalyticsStationaryChanged`. */
|
|
16499
16833
|
phase: _enum(["appeared", "departed"])
|
|
16500
16834
|
}),
|
|
16501
16835
|
object({
|
|
@@ -16503,6 +16837,143 @@ var AutomationTriggerSchema = discriminatedUnion("kind", [
|
|
|
16503
16837
|
minutes: number().int().min(1).max(1440)
|
|
16504
16838
|
})
|
|
16505
16839
|
]);
|
|
16840
|
+
var LegacyConditionLeafSchema = object({
|
|
16841
|
+
kind: literal("condition"),
|
|
16842
|
+
deviceId: number().int().nonnegative(),
|
|
16843
|
+
cap: string().min(1),
|
|
16844
|
+
fieldPath: string().min(1),
|
|
16845
|
+
operator: AutomationConditionOperatorSchema,
|
|
16846
|
+
value: union([
|
|
16847
|
+
string(),
|
|
16848
|
+
number(),
|
|
16849
|
+
boolean(),
|
|
16850
|
+
array(union([string(), number()])),
|
|
16851
|
+
QuantityValueSchema
|
|
16852
|
+
]),
|
|
16853
|
+
unit: string().min(1).optional()
|
|
16854
|
+
});
|
|
16855
|
+
var LegacyStationaryPresentSchema = object({
|
|
16856
|
+
kind: literal("stationary-present"),
|
|
16857
|
+
deviceId: number().int().nonnegative(),
|
|
16858
|
+
classes: array(string().min(1)).min(1).optional(),
|
|
16859
|
+
zones: array(string().min(1)).min(1).optional()
|
|
16860
|
+
});
|
|
16861
|
+
var LegacyExpressionSchema = object({
|
|
16862
|
+
kind: literal("expression"),
|
|
16863
|
+
expr: string().min(1).max(MAX_EXPRESSION_SOURCE_LENGTH),
|
|
16864
|
+
bindings: record(string().regex(EXPRESSION_IDENTIFIER_RE), ExpressionBindingSourceSchema)
|
|
16865
|
+
}).superRefine((src, ctx) => {
|
|
16866
|
+
const err = validateExpressionSource(src);
|
|
16867
|
+
if (err !== null) ctx.addIssue({
|
|
16868
|
+
code: "custom",
|
|
16869
|
+
message: err,
|
|
16870
|
+
path: ["expr"]
|
|
16871
|
+
});
|
|
16872
|
+
});
|
|
16873
|
+
var LegacyConditionSchema = lazy(() => discriminatedUnion("kind", [
|
|
16874
|
+
object({
|
|
16875
|
+
kind: literal("all"),
|
|
16876
|
+
children: array(LegacyConditionSchema)
|
|
16877
|
+
}),
|
|
16878
|
+
object({
|
|
16879
|
+
kind: literal("any"),
|
|
16880
|
+
children: array(LegacyConditionSchema)
|
|
16881
|
+
}),
|
|
16882
|
+
object({
|
|
16883
|
+
kind: literal("not"),
|
|
16884
|
+
child: LegacyConditionSchema
|
|
16885
|
+
}),
|
|
16886
|
+
LegacyConditionLeafSchema,
|
|
16887
|
+
LegacyExpressionSchema,
|
|
16888
|
+
LegacyStationaryPresentSchema
|
|
16889
|
+
]));
|
|
16890
|
+
function convertTrigger(trigger) {
|
|
16891
|
+
switch (trigger.kind) {
|
|
16892
|
+
case "device-state": return {
|
|
16893
|
+
...trigger,
|
|
16894
|
+
kind: "device-becomes"
|
|
16895
|
+
};
|
|
16896
|
+
case "detection": {
|
|
16897
|
+
const { classes, ...rest } = trigger;
|
|
16898
|
+
return {
|
|
16899
|
+
...rest,
|
|
16900
|
+
subjects: classes.map(subjectFromClassName)
|
|
16901
|
+
};
|
|
16902
|
+
}
|
|
16903
|
+
case "stationary": {
|
|
16904
|
+
const { classes, ...rest } = trigger;
|
|
16905
|
+
return {
|
|
16906
|
+
...rest,
|
|
16907
|
+
...classes === void 0 ? {} : { subjects: classes.map(subjectFromClassName) }
|
|
16908
|
+
};
|
|
16909
|
+
}
|
|
16910
|
+
default: return trigger;
|
|
16911
|
+
}
|
|
16912
|
+
}
|
|
16913
|
+
/** An old condition tree as a `when` subtree: `condition` → "is", classes → subjects. */
|
|
16914
|
+
function convertLegacyCondition(condition) {
|
|
16915
|
+
switch (condition.kind) {
|
|
16916
|
+
case "condition": return {
|
|
16917
|
+
...condition,
|
|
16918
|
+
kind: "device-is"
|
|
16919
|
+
};
|
|
16920
|
+
case "stationary-present": {
|
|
16921
|
+
const { classes, ...rest } = condition;
|
|
16922
|
+
return {
|
|
16923
|
+
...rest,
|
|
16924
|
+
...classes === void 0 ? {} : { subjects: classes.map(subjectFromClassName) }
|
|
16925
|
+
};
|
|
16926
|
+
}
|
|
16927
|
+
case "expression": return condition;
|
|
16928
|
+
case "not": return {
|
|
16929
|
+
kind: "not",
|
|
16930
|
+
child: convertLegacyCondition(condition.child)
|
|
16931
|
+
};
|
|
16932
|
+
case "all":
|
|
16933
|
+
case "any": return {
|
|
16934
|
+
kind: condition.kind,
|
|
16935
|
+
children: condition.children.map(convertLegacyCondition)
|
|
16936
|
+
};
|
|
16937
|
+
}
|
|
16938
|
+
}
|
|
16939
|
+
/** `all(any(t1…tn), C)`, or `any(t1…tn)`; a single trigger is not wrapped in `any`. */
|
|
16940
|
+
function convertLegacyWhen(half) {
|
|
16941
|
+
const leaves = half.triggers.map(convertTrigger);
|
|
16942
|
+
const first = leaves[0];
|
|
16943
|
+
const triggers = leaves.length === 1 && first !== void 0 ? first : {
|
|
16944
|
+
kind: "any",
|
|
16945
|
+
children: leaves
|
|
16946
|
+
};
|
|
16947
|
+
if (half.conditions === void 0) return triggers;
|
|
16948
|
+
return {
|
|
16949
|
+
kind: "all",
|
|
16950
|
+
children: [triggers, convertLegacyCondition(half.conditions)]
|
|
16951
|
+
};
|
|
16952
|
+
}
|
|
16953
|
+
/**
|
|
16954
|
+
* The automation RECIPE — what a visually-authored automation is, before it
|
|
16955
|
+
* becomes code.
|
|
16956
|
+
*
|
|
16957
|
+
* This is the data half of `docs/design/2026-08-08-automation-scripts-custom-devices.md`
|
|
16958
|
+
* Phase 6. A recipe is not an engine and never evaluates anything: it is a
|
|
16959
|
+
* declarative description that {@link generateAutomationBlock} compiles to the
|
|
16960
|
+
* TypeScript of an ordinary core block. There is therefore no second rule
|
|
16961
|
+
* engine, no second store and no second runtime — the block runner is the
|
|
16962
|
+
* runtime, `core_blocks` is the store (§2.1).
|
|
16963
|
+
*
|
|
16964
|
+
* Two parts:
|
|
16965
|
+
*
|
|
16966
|
+
* - **`when`** — ONE tree (`./when.ts`) of all/any/not over event leaves
|
|
16967
|
+
* (instants) and state leaves (durations). It replaces the flat trigger list
|
|
16968
|
+
* plus the separate condition tree; the firing rule is in that file and in
|
|
16969
|
+
* ADR "one tree".
|
|
16970
|
+
* - **Actions** — `NcRuleActionSchema`'s two steps, plus the `{kind:'code'}`
|
|
16971
|
+
* fragment of §3.2.2. See {@link AutomationActionSchema} for the ONE place
|
|
16972
|
+
* this had to diverge from "verbatim", and why.
|
|
16973
|
+
*
|
|
16974
|
+
* A recipe stored in the old shape (`triggers` + `conditions`) still LOADS:
|
|
16975
|
+
* {@link AutomationRecipeSchema} (the parse-anywhere schema) converts it on parse. Nothing writes it.
|
|
16976
|
+
*/
|
|
16506
16977
|
/**
|
|
16507
16978
|
* One action step.
|
|
16508
16979
|
*
|
|
@@ -16605,69 +17076,49 @@ var AutomationRunModeSchema = discriminatedUnion("mode", [
|
|
|
16605
17076
|
minutes: number().int().min(1).max(1440)
|
|
16606
17077
|
})
|
|
16607
17078
|
]);
|
|
16608
|
-
var
|
|
16609
|
-
|
|
16610
|
-
conditions: AutomationConditionSchema.optional(),
|
|
17079
|
+
var CurrentAutomationRecipeSchema = object({
|
|
17080
|
+
when: AutomationWhenSchema,
|
|
16611
17081
|
actions: array(AutomationActionSchema),
|
|
16612
17082
|
runMode: AutomationRunModeSchema.optional(),
|
|
16613
17083
|
/** How many run traces the automation keeps (default {@link DEFAULT_TRACE_KEEP}). */
|
|
16614
17084
|
keepTraces: number().int().min(1).max(100).optional()
|
|
16615
17085
|
});
|
|
16616
|
-
|
|
16617
|
-
|
|
16618
|
-
|
|
16619
|
-
|
|
16620
|
-
|
|
16621
|
-
|
|
16622
|
-
|
|
16623
|
-
|
|
16624
|
-
|
|
16625
|
-
|
|
16626
|
-
|
|
16627
|
-
|
|
16628
|
-
|
|
16629
|
-
|
|
16630
|
-
|
|
16631
|
-
|
|
16632
|
-
|
|
16633
|
-
|
|
16634
|
-
|
|
16635
|
-
|
|
16636
|
-
|
|
16637
|
-
|
|
16638
|
-
|
|
16639
|
-
|
|
16640
|
-
|
|
16641
|
-
bus: "vehicle",
|
|
16642
|
-
train: "vehicle",
|
|
16643
|
-
truck: "vehicle",
|
|
16644
|
-
boat: "vehicle",
|
|
16645
|
-
bird: "animal",
|
|
16646
|
-
cat: "animal",
|
|
16647
|
-
dog: "animal",
|
|
16648
|
-
horse: "animal",
|
|
16649
|
-
sheep: "animal",
|
|
16650
|
-
cow: "animal",
|
|
16651
|
-
elephant: "animal",
|
|
16652
|
-
bear: "animal",
|
|
16653
|
-
zebra: "animal",
|
|
16654
|
-
giraffe: "animal",
|
|
16655
|
-
suitcase: "package",
|
|
16656
|
-
backpack: "package",
|
|
16657
|
-
handbag: "package"
|
|
16658
|
-
},
|
|
16659
|
-
preserveOriginal: false
|
|
16660
|
-
};
|
|
17086
|
+
/** A recipe as it was stored before the single tree. Read-only: nothing writes this. */
|
|
17087
|
+
var LegacyAutomationRecipeSchema = object({
|
|
17088
|
+
triggers: array(LegacyTriggerSchema),
|
|
17089
|
+
conditions: LegacyConditionSchema.optional(),
|
|
17090
|
+
actions: array(AutomationActionSchema),
|
|
17091
|
+
runMode: AutomationRunModeSchema.optional(),
|
|
17092
|
+
keepTraces: number().int().min(1).max(100).optional()
|
|
17093
|
+
});
|
|
17094
|
+
/** The old shape as the new one, lossless. */
|
|
17095
|
+
function convertLegacyRecipe(legacy) {
|
|
17096
|
+
const { triggers, conditions, ...rest } = legacy;
|
|
17097
|
+
return {
|
|
17098
|
+
when: convertLegacyWhen({
|
|
17099
|
+
triggers,
|
|
17100
|
+
conditions
|
|
17101
|
+
}),
|
|
17102
|
+
...rest
|
|
17103
|
+
};
|
|
17104
|
+
}
|
|
17105
|
+
/**
|
|
17106
|
+
* Where recipes are PARSED (the core-blocks cap, the MCP tool, the literal a
|
|
17107
|
+
* saved block carries): the new shape as it is, or the old shape converted to
|
|
17108
|
+
* it. The output type is always the new one.
|
|
17109
|
+
*/
|
|
17110
|
+
var AutomationRecipeSchema = union([CurrentAutomationRecipeSchema, LegacyAutomationRecipeSchema.transform(convertLegacyRecipe)]);
|
|
16661
17111
|
new Set(Object.values(COCO_TO_MACRO.mapping));
|
|
16662
17112
|
/**
|
|
16663
17113
|
* Run traces — what an automation (or, later, an Action run) DID, node by node,
|
|
16664
17114
|
* so the editor can paint every block green or red with its reason.
|
|
16665
17115
|
*
|
|
16666
|
-
* A trace is data, not a log: it covers the WHOLE tree — the
|
|
16667
|
-
* every
|
|
16668
|
-
* short-circuit never reached), the run-mode verdict and every action
|
|
16669
|
-
* each addressed by a stable path (`
|
|
16670
|
-
* for an Action run).
|
|
17116
|
+
* A trace is data, not a log: it covers the WHOLE tree — the event leaf that
|
|
17117
|
+
* fired, every node of the `when` tree (containers and leaves, including the
|
|
17118
|
+
* ones a short-circuit never reached), the run-mode verdict and every action
|
|
17119
|
+
* step — each addressed by a stable path (`when.0.1`, `actions.2`, or `steps.N`
|
|
17120
|
+
* for an Action run). Traces written before the single tree carry
|
|
17121
|
+
* `conditions.*` paths and still parse. Skipped
|
|
16671
17122
|
* evaluations are traced too, and identical consecutive skips collapse into a
|
|
16672
17123
|
* repeat count so a trigger that fails every 5 minutes cannot flush real runs.
|
|
16673
17124
|
*
|
|
@@ -16699,6 +17150,8 @@ var TraceNodeOutcomeSchema = _enum([
|
|
|
16699
17150
|
]);
|
|
16700
17151
|
var AutomationTriggerTraceSchema = object({
|
|
16701
17152
|
kind: string().min(1),
|
|
17153
|
+
/** The event leaf that fired (`when`, `when.0.1`); absent on traces written before the single tree. */
|
|
17154
|
+
path: string().min(1).optional(),
|
|
16702
17155
|
outcome: _enum(["pass", "fail"]),
|
|
16703
17156
|
/** Why an event was rejected ("class person not in [dog]") or what fired. */
|
|
16704
17157
|
reason: string(),
|
|
@@ -16706,15 +17159,23 @@ var AutomationTriggerTraceSchema = object({
|
|
|
16706
17159
|
vars: record(string(), TraceValueSchema)
|
|
16707
17160
|
});
|
|
16708
17161
|
var AutomationConditionTraceNodeSchema = object({
|
|
16709
|
-
/** `
|
|
17162
|
+
/** `when` for the root, `when.<i>` for its i-th child, … (`conditions…` on an old trace). */
|
|
16710
17163
|
path: string().min(1),
|
|
16711
17164
|
kind: _enum([
|
|
16712
17165
|
"all",
|
|
16713
17166
|
"any",
|
|
16714
17167
|
"not",
|
|
16715
17168
|
"condition",
|
|
17169
|
+
"device-is",
|
|
16716
17170
|
"expression",
|
|
16717
|
-
"stationary-present"
|
|
17171
|
+
"stationary-present",
|
|
17172
|
+
"device-becomes",
|
|
17173
|
+
"device-event",
|
|
17174
|
+
"schedule",
|
|
17175
|
+
"interval",
|
|
17176
|
+
"manual",
|
|
17177
|
+
"detection",
|
|
17178
|
+
"stationary"
|
|
16718
17179
|
]),
|
|
16719
17180
|
outcome: TraceNodeOutcomeSchema,
|
|
16720
17181
|
reason: string(),
|
|
@@ -16748,6 +17209,12 @@ var AutomationStepTraceSchema = object({
|
|
|
16748
17209
|
deviceId: number().int().optional(),
|
|
16749
17210
|
startedAt: number().optional(),
|
|
16750
17211
|
endedAt: number().optional(),
|
|
17212
|
+
/**
|
|
17213
|
+
* The parameters the step SENT, after `{{vars.x}}` substitution — what the
|
|
17214
|
+
* device was actually asked. Bounded like trigger `vars`; a secret parameter
|
|
17215
|
+
* is shown as {@link REDACTED_ARG}. Absent on traces written before it existed.
|
|
17216
|
+
*/
|
|
17217
|
+
args: record(string(), TraceValueSchema).optional(),
|
|
16751
17218
|
outcome: _enum([
|
|
16752
17219
|
"ok",
|
|
16753
17220
|
"error",
|
|
@@ -17497,6 +17964,23 @@ method(object({
|
|
|
17497
17964
|
addonId: string(),
|
|
17498
17965
|
nodeId: string().optional()
|
|
17499
17966
|
}), SettingsSchemaWithValuesSchema.nullable()), method(object({
|
|
17967
|
+
addonId: string(),
|
|
17968
|
+
nodeId: string().optional()
|
|
17969
|
+
}), object({ keys: array(string()) }).nullable(), { auth: "admin" }), method(object({
|
|
17970
|
+
addonId: string(),
|
|
17971
|
+
nodeId: string().optional(),
|
|
17972
|
+
keys: array(string())
|
|
17973
|
+
}), object({
|
|
17974
|
+
removed: array(string()),
|
|
17975
|
+
refused: array(object({
|
|
17976
|
+
key: string(),
|
|
17977
|
+
reason: string()
|
|
17978
|
+
})),
|
|
17979
|
+
secretsCleared: number()
|
|
17980
|
+
}), {
|
|
17981
|
+
kind: "mutation",
|
|
17982
|
+
auth: "admin"
|
|
17983
|
+
}), method(object({
|
|
17500
17984
|
addonId: string(),
|
|
17501
17985
|
deviceId: number(),
|
|
17502
17986
|
nodeId: string().optional()
|
|
@@ -21420,6 +21904,8 @@ var StorageKindSchema = object({
|
|
|
21420
21904
|
"orphaned",
|
|
21421
21905
|
"dropped"
|
|
21422
21906
|
]),
|
|
21907
|
+
/** An owner declared this kind since the engine started. */
|
|
21908
|
+
declaredThisBoot: boolean(),
|
|
21423
21909
|
/** `null` when the caller asked for no counts (`counts: false`). */
|
|
21424
21910
|
rows: number().int().nonnegative().nullable(),
|
|
21425
21911
|
/** Rows x the average size of a sample; null for an empty kind. */
|
|
@@ -21431,6 +21917,51 @@ var StorageKindSchema = object({
|
|
|
21431
21917
|
/** The whole declaration, secret paths and entry descriptor included (the entries service builds its handle from it). */
|
|
21432
21918
|
declaration: RecordKindDeclarationSchema
|
|
21433
21919
|
});
|
|
21920
|
+
_enum([
|
|
21921
|
+
"orphaned",
|
|
21922
|
+
"stale",
|
|
21923
|
+
"unknown"
|
|
21924
|
+
]);
|
|
21925
|
+
/** A record kind nobody declared since its owner started, or whose owner is gone. */
|
|
21926
|
+
var StaleKindFindingSchema = object({
|
|
21927
|
+
owner: string(),
|
|
21928
|
+
kind: string(),
|
|
21929
|
+
/** `unknown`: the owner could not be judged (not running, or its state unreadable) - never dropped. */
|
|
21930
|
+
verdict: _enum(["orphaned", "unknown"]),
|
|
21931
|
+
reason: string(),
|
|
21932
|
+
rows: number().int().nonnegative().nullable(),
|
|
21933
|
+
/** local-auth's tables are never dropped by this audit. */
|
|
21934
|
+
protected: boolean()
|
|
21935
|
+
});
|
|
21936
|
+
/** A stored global-settings key the running addon no longer declares. */
|
|
21937
|
+
var StaleSettingsKeyFindingSchema = object({
|
|
21938
|
+
addonId: string(),
|
|
21939
|
+
/** The stored key as written, a per-node `<key>@<nodeId>` suffix included. */
|
|
21940
|
+
key: string(),
|
|
21941
|
+
/**
|
|
21942
|
+
* Keychain refs whose ONLY marker sits under this key: in use by stale data,
|
|
21943
|
+
* not orphans yet. Removing the key releases them.
|
|
21944
|
+
*/
|
|
21945
|
+
secretRefs: array(string())
|
|
21946
|
+
});
|
|
21947
|
+
/** An addon the audit could not judge, with the reason. Never reported as stale. */
|
|
21948
|
+
var StaleUnknownSchema = object({
|
|
21949
|
+
subject: string(),
|
|
21950
|
+
reason: string()
|
|
21951
|
+
});
|
|
21952
|
+
var StaleDataReportSchema = object({
|
|
21953
|
+
/** Epoch ms of the last finished scan; `null` before the first. */
|
|
21954
|
+
scannedAt: number().nullable(),
|
|
21955
|
+
scanning: boolean(),
|
|
21956
|
+
trigger: _enum([
|
|
21957
|
+
"boot",
|
|
21958
|
+
"interval",
|
|
21959
|
+
"manual"
|
|
21960
|
+
]).nullable(),
|
|
21961
|
+
kinds: array(StaleKindFindingSchema),
|
|
21962
|
+
settingsKeys: array(StaleSettingsKeyFindingSchema),
|
|
21963
|
+
unknown: array(StaleUnknownSchema)
|
|
21964
|
+
});
|
|
21434
21965
|
method(object({ ownerPrefix: string().min(1).optional() }), object({ tables: array(StorageTableSchema) }), { auth: "admin" }), method(object({
|
|
21435
21966
|
owner: string().min(1).optional(),
|
|
21436
21967
|
/** `false` skips the per-kind row count (a catalog read only). Default true. */
|
|
@@ -21438,7 +21969,30 @@ method(object({ ownerPrefix: string().min(1).optional() }), object({ tables: arr
|
|
|
21438
21969
|
}), object({ kinds: array(StorageKindSchema) }), { auth: "admin" }), method(RecordQueryInputSchema.extend({
|
|
21439
21970
|
owner: string().min(1),
|
|
21440
21971
|
kind: RecordKindNameSchema
|
|
21441
|
-
}), RecordQueryResultSchema, { auth: "admin" })
|
|
21972
|
+
}), RecordQueryResultSchema, { auth: "admin" }), method(object({}), StaleDataReportSchema, { auth: "admin" }), method(object({}), StaleDataReportSchema, {
|
|
21973
|
+
kind: "mutation",
|
|
21974
|
+
auth: "admin"
|
|
21975
|
+
}), method(object({
|
|
21976
|
+
owner: string().min(1),
|
|
21977
|
+
kind: RecordKindNameSchema
|
|
21978
|
+
}), object({
|
|
21979
|
+
deleted: number().int().nonnegative(),
|
|
21980
|
+
secretsReleased: number().int().nonnegative()
|
|
21981
|
+
}), {
|
|
21982
|
+
kind: "mutation",
|
|
21983
|
+
auth: "admin",
|
|
21984
|
+
caller: "required"
|
|
21985
|
+
}), method(object({
|
|
21986
|
+
addonId: string().min(1),
|
|
21987
|
+
key: string().min(1)
|
|
21988
|
+
}), object({
|
|
21989
|
+
removed: boolean(),
|
|
21990
|
+
secretsCleared: number().int().nonnegative()
|
|
21991
|
+
}), {
|
|
21992
|
+
kind: "mutation",
|
|
21993
|
+
auth: "admin",
|
|
21994
|
+
caller: "required"
|
|
21995
|
+
});
|
|
21442
21996
|
/**
|
|
21443
21997
|
* record-entries - the ONE admin surface for every list of user-created entries
|
|
21444
21998
|
* (D881): notification targets, brokers, LLM profiles, anything an addon
|
|
@@ -21577,6 +22131,12 @@ method(object({
|
|
|
21577
22131
|
}), method(object({ deviceId: number().int() }), object({ refs: array(string()).readonly() }), {
|
|
21578
22132
|
kind: "mutation",
|
|
21579
22133
|
auth: "admin"
|
|
22134
|
+
}), method(object({
|
|
22135
|
+
refs: RefListSchema,
|
|
22136
|
+
onBehalfOf: string().min(1)
|
|
22137
|
+
}), object({ released: number().int() }), {
|
|
22138
|
+
kind: "mutation",
|
|
22139
|
+
auth: "admin"
|
|
21580
22140
|
}), method(object({}), array(KeychainSecretMetaSchema).readonly(), { auth: "admin" }), method(object({}), KeychainStateSchema, { auth: "admin" });
|
|
21581
22141
|
/**
|
|
21582
22142
|
* device-history — the ONE mechanism for numeric history (D850).
|
|
@@ -22366,7 +22926,9 @@ var DiscoveredChildDeviceSchema = lazy(() => object({
|
|
|
22366
22926
|
/** Upstream-system identity + rendering hints for the candidate. */
|
|
22367
22927
|
sourceInfo: SourceInfoSchema.optional(),
|
|
22368
22928
|
/** Nested entity-children for accordion preview — integrations populate, Hubs omit. */
|
|
22369
|
-
children: array(DiscoveredChildDeviceSchema).readonly().optional()
|
|
22929
|
+
children: array(DiscoveredChildDeviceSchema).readonly().optional(),
|
|
22930
|
+
/** `childNativeId` of the gateway candidate in the same list this device sits behind. */
|
|
22931
|
+
parentStableId: string().optional()
|
|
22370
22932
|
}));
|
|
22371
22933
|
/**
|
|
22372
22934
|
* Status block — populated by the integration after each
|
|
@@ -42681,6 +43243,79 @@ object({
|
|
|
42681
43243
|
metadata: record(string(), unknown()).optional()
|
|
42682
43244
|
});
|
|
42683
43245
|
/**
|
|
43246
|
+
* HOW a provider can be found on the network. The provider only DECLARES the
|
|
43247
|
+
* mode; the `local-network` scan engine runs it once for every provider that
|
|
43248
|
+
* asked (one multicast browse, one host sweep) and hands the raw hits back to
|
|
43249
|
+
* `classifyDiscoveryHits`. A provider never opens a discovery socket itself,
|
|
43250
|
+
* except through a `custom` mode.
|
|
43251
|
+
*/
|
|
43252
|
+
var DiscoveryModeSchema = discriminatedUnion("kind", [
|
|
43253
|
+
object({
|
|
43254
|
+
kind: literal("mdns"),
|
|
43255
|
+
/** DNS-SD service type, e.g. `_esphomelib._tcp`. */
|
|
43256
|
+
serviceType: string().min(1),
|
|
43257
|
+
/** Regular expression an instance name must match (case-insensitive). */
|
|
43258
|
+
instancePattern: string().optional()
|
|
43259
|
+
}),
|
|
43260
|
+
object({
|
|
43261
|
+
kind: literal("ws-discovery"),
|
|
43262
|
+
/** Probe types (e.g. `dn:NetworkVideoTransmitter`); omitted = any device. */
|
|
43263
|
+
types: array(string()).optional()
|
|
43264
|
+
}),
|
|
43265
|
+
object({
|
|
43266
|
+
kind: literal("ssdp"),
|
|
43267
|
+
searchTarget: string().min(1)
|
|
43268
|
+
}),
|
|
43269
|
+
object({
|
|
43270
|
+
kind: literal("udp-broadcast"),
|
|
43271
|
+
port: number().int().min(1).max(65535),
|
|
43272
|
+
payloadHex: string().regex(/^([0-9a-fA-F]{2})*$/),
|
|
43273
|
+
/** Port replies arrive on, when the device answers somewhere other than the source port. */
|
|
43274
|
+
listenPort: number().int().min(1).max(65535).optional()
|
|
43275
|
+
}),
|
|
43276
|
+
object({
|
|
43277
|
+
kind: literal("http-probe"),
|
|
43278
|
+
port: number().int().min(1).max(65535),
|
|
43279
|
+
path: string().startsWith("/"),
|
|
43280
|
+
method: _enum(["GET", "POST"]).default("GET"),
|
|
43281
|
+
bodyText: string().optional(),
|
|
43282
|
+
contentType: string().optional(),
|
|
43283
|
+
tls: boolean().default(false),
|
|
43284
|
+
/** Status codes that count as a hit. Omitted = any HTTP answer. */
|
|
43285
|
+
acceptStatus: array(number().int()).optional()
|
|
43286
|
+
}),
|
|
43287
|
+
object({
|
|
43288
|
+
kind: literal("custom"),
|
|
43289
|
+
/** Why the engine cannot do it (an allowlisted exception, e.g. a vendor UDP protocol). */
|
|
43290
|
+
reason: string().min(1)
|
|
43291
|
+
})
|
|
43292
|
+
]);
|
|
43293
|
+
/** What the engine saw on the wire for ONE declared mode; the provider classifies it. */
|
|
43294
|
+
var DiscoveryHitSchema = object({
|
|
43295
|
+
/** Index into the provider's own `getDiscoveryModes()` array. */
|
|
43296
|
+
modeIndex: number().int().min(0),
|
|
43297
|
+
host: string(),
|
|
43298
|
+
port: number().int(),
|
|
43299
|
+
http: object({
|
|
43300
|
+
status: number().int(),
|
|
43301
|
+
headers: record(string(), string()),
|
|
43302
|
+
/** At most 16 KiB. */
|
|
43303
|
+
bodyText: string()
|
|
43304
|
+
}).optional(),
|
|
43305
|
+
mdns: object({
|
|
43306
|
+
instance: string(),
|
|
43307
|
+
host: string(),
|
|
43308
|
+
port: number().int(),
|
|
43309
|
+
txt: record(string(), string())
|
|
43310
|
+
}).optional(),
|
|
43311
|
+
udp: object({ payloadHex: string() }).optional(),
|
|
43312
|
+
wsd: object({
|
|
43313
|
+
xaddrs: array(string()),
|
|
43314
|
+
types: array(string()),
|
|
43315
|
+
scopes: array(string())
|
|
43316
|
+
}).optional()
|
|
43317
|
+
});
|
|
43318
|
+
/**
|
|
42684
43319
|
* Candidate handed back from discovery and accepted by
|
|
42685
43320
|
* `adoptDiscoveredDevice`. Shape mirrors the in-process
|
|
42686
43321
|
* `DiscoveredDevice` interface used by `DeviceDiscovery`.
|
|
@@ -42715,7 +43350,17 @@ var DiscoveryCandidateSchema = object({
|
|
|
42715
43350
|
/** Numeric id of the device this candidate was matched to. Set with `alreadyOnboarded`. */
|
|
42716
43351
|
onboardedDeviceId: number().optional(),
|
|
42717
43352
|
/** Operator-facing name of the matched device, so the UI can say WHICH one it is. */
|
|
42718
|
-
onboardedName: string().optional()
|
|
43353
|
+
onboardedName: string().optional(),
|
|
43354
|
+
/**
|
|
43355
|
+
* This candidate is an INTEGRATION to set up (a gateway, a hub, a controller),
|
|
43356
|
+
* not a device to adopt. Replaces the `prefilledConfig.setupIntegration` marker,
|
|
43357
|
+
* which is still read for one release.
|
|
43358
|
+
*/
|
|
43359
|
+
setupIntegration: boolean().optional(),
|
|
43360
|
+
/** `stableId` of the gateway candidate this device was found BEHIND. */
|
|
43361
|
+
parentStableId: string().optional(),
|
|
43362
|
+
/** `false` = shown for context but not pickable. Default true. */
|
|
43363
|
+
selectable: boolean().optional()
|
|
42719
43364
|
});
|
|
42720
43365
|
/**
|
|
42721
43366
|
* Flat device summary returned by `createDevice` / `adoptDiscoveredDevice`.
|
|
@@ -42768,6 +43413,12 @@ method(_void(), _void(), { kind: "mutation" }), method(_void(), _void(), { kind:
|
|
|
42768
43413
|
}), method(object({}), boolean()), method(object({ params: record(string(), unknown()).optional() }), array(DiscoveryCandidateSchema), {
|
|
42769
43414
|
kind: "mutation",
|
|
42770
43415
|
auth: "admin"
|
|
43416
|
+
}), method(object({}), array(DiscoveryModeSchema)), method(object({
|
|
43417
|
+
hits: array(DiscoveryHitSchema),
|
|
43418
|
+
params: record(string(), unknown()).optional()
|
|
43419
|
+
}), array(DiscoveryCandidateSchema), {
|
|
43420
|
+
kind: "mutation",
|
|
43421
|
+
auth: "admin"
|
|
42771
43422
|
}), method(object({}), CreationSchemaOutputSchema), method(object({}), object({ deviceType: _enum(DeviceType).nullable() })), method(object({ candidate: DiscoveryCandidateSchema }), DeviceSummarySchema, {
|
|
42772
43423
|
kind: "mutation",
|
|
42773
43424
|
auth: "admin"
|
|
@@ -43495,17 +44146,23 @@ method(object({
|
|
|
43495
44146
|
}), method(object({}), object({ providers: array(object({
|
|
43496
44147
|
addonId: string(),
|
|
43497
44148
|
label: string()
|
|
43498
|
-
})).readonly() }), { auth: "admin" }), method(
|
|
43499
|
-
|
|
43500
|
-
|
|
43501
|
-
|
|
43502
|
-
|
|
43503
|
-
|
|
43504
|
-
|
|
43505
|
-
|
|
43506
|
-
}),
|
|
44149
|
+
})).readonly() }), { auth: "admin" }), method(
|
|
44150
|
+
/** `subnets`: extra CIDRs for THIS scan, on top of the hub's own and the saved list. */
|
|
44151
|
+
object({ subnets: array(string()).optional() }),
|
|
44152
|
+
object({ groups: array(object({
|
|
44153
|
+
addonId: string(),
|
|
44154
|
+
label: string(),
|
|
44155
|
+
candidates: array(DiscoveryCandidateSchema).readonly(),
|
|
44156
|
+
error: string().nullable()
|
|
44157
|
+
})).readonly() }),
|
|
44158
|
+
{
|
|
44159
|
+
kind: "mutation",
|
|
44160
|
+
auth: "admin"
|
|
44161
|
+
}
|
|
44162
|
+
), method(object({
|
|
43507
44163
|
addonId: string(),
|
|
43508
|
-
params: record(string(), unknown()).optional()
|
|
44164
|
+
params: record(string(), unknown()).optional(),
|
|
44165
|
+
subnets: array(string()).optional()
|
|
43509
44166
|
}), object({ candidates: array(DiscoveryCandidateSchema).readonly() }), {
|
|
43510
44167
|
kind: "mutation",
|
|
43511
44168
|
auth: "admin"
|
|
@@ -61125,7 +61782,9 @@ method(_void(), array(IntegrationWithStateSchema)), method(object({ id: string()
|
|
|
61125
61782
|
id: string(),
|
|
61126
61783
|
settings: record(string(), unknown()),
|
|
61127
61784
|
/** Keys the form's schema declares secret (by type) — keychain-stored (D787). */
|
|
61128
|
-
secretKeys: array(string()).optional()
|
|
61785
|
+
secretKeys: array(string()).optional(),
|
|
61786
|
+
/** The integration's own addon applies the change in-process and asks the hub not to respawn it. */
|
|
61787
|
+
skipRestart: boolean().optional()
|
|
61129
61788
|
}), object({ success: boolean() }), {
|
|
61130
61789
|
kind: "mutation",
|
|
61131
61790
|
auth: "admin"
|
|
@@ -61602,6 +62261,39 @@ var TlsStatusSchema = object({
|
|
|
61602
62261
|
hasCa: boolean()
|
|
61603
62262
|
}).nullable()
|
|
61604
62263
|
});
|
|
62264
|
+
/** One provider's ask of the scan engine: the modes it declared. */
|
|
62265
|
+
var ScanRequestSchema = object({
|
|
62266
|
+
providerId: string().min(1),
|
|
62267
|
+
modes: array(DiscoveryModeSchema)
|
|
62268
|
+
});
|
|
62269
|
+
var ScanErrorSchema = object({
|
|
62270
|
+
/** Absent for a failure that is the scan's own (a bad subnet, a socket that would not open). */
|
|
62271
|
+
providerId: string().optional(),
|
|
62272
|
+
/** The mode family that failed (`mdns`, `http-probe`, …). */
|
|
62273
|
+
mode: string().optional(),
|
|
62274
|
+
message: string()
|
|
62275
|
+
});
|
|
62276
|
+
/** What one scan did, per mode family; the engine logs the same numbers once. */
|
|
62277
|
+
var ScanStatsSchema = object({
|
|
62278
|
+
hostsProbed: number().int(),
|
|
62279
|
+
hits: number().int(),
|
|
62280
|
+
timeouts: number().int(),
|
|
62281
|
+
byMode: record(string(), object({
|
|
62282
|
+
probed: number().int(),
|
|
62283
|
+
hits: number().int(),
|
|
62284
|
+
timeouts: number().int()
|
|
62285
|
+
}))
|
|
62286
|
+
});
|
|
62287
|
+
var ScanNetworkResultSchema = object({
|
|
62288
|
+
hits: array(object({
|
|
62289
|
+
providerId: string(),
|
|
62290
|
+
hit: DiscoveryHitSchema
|
|
62291
|
+
})),
|
|
62292
|
+
/** CIDRs actually covered: the hub's own /24s, the saved list and the per-call list. */
|
|
62293
|
+
subnetsScanned: array(string()),
|
|
62294
|
+
errors: array(ScanErrorSchema),
|
|
62295
|
+
stats: ScanStatsSchema
|
|
62296
|
+
});
|
|
61605
62297
|
method(_void(), ListResultSchema), method(_void(), PreferredSchema), method(object({
|
|
61606
62298
|
/**
|
|
61607
62299
|
* LEGACY HINT — do not send from new code. Kept optional so clients
|
|
@@ -61656,6 +62348,16 @@ method(_void(), ListResultSchema), method(_void(), PreferredSchema), method(obje
|
|
|
61656
62348
|
}), method(_void(), object({ pem: string() })), method(_void(), TlsStatusSchema, {
|
|
61657
62349
|
kind: "mutation",
|
|
61658
62350
|
auth: "admin"
|
|
62351
|
+
}), method(object({
|
|
62352
|
+
requests: array(ScanRequestSchema),
|
|
62353
|
+
subnets: array(string()).optional()
|
|
62354
|
+
}), ScanNetworkResultSchema, {
|
|
62355
|
+
kind: "mutation",
|
|
62356
|
+
auth: "admin",
|
|
62357
|
+
timeoutMs: 9e4
|
|
62358
|
+
}), method(_void(), object({ subnets: array(string()) }), { auth: "admin" }), method(object({ subnets: array(string()) }), object({ subnets: array(string()) }), {
|
|
62359
|
+
kind: "mutation",
|
|
62360
|
+
auth: "admin"
|
|
61659
62361
|
}), method(_void(), TlsStatusSchema, {
|
|
61660
62362
|
kind: "mutation",
|
|
61661
62363
|
auth: "admin"
|
|
@@ -68599,6 +69301,13 @@ Object.freeze({
|
|
|
68599
69301
|
access: "create",
|
|
68600
69302
|
role: "admin"
|
|
68601
69303
|
},
|
|
69304
|
+
"addonSettings.getDeclaredSettingsKeys": {
|
|
69305
|
+
capName: "addon-settings",
|
|
69306
|
+
capScope: "system",
|
|
69307
|
+
addonId: null,
|
|
69308
|
+
access: "view",
|
|
69309
|
+
role: "admin"
|
|
69310
|
+
},
|
|
68602
69311
|
"addonSettings.getDeviceSettings": {
|
|
68603
69312
|
capName: "addon-settings",
|
|
68604
69313
|
capScope: "system",
|
|
@@ -68620,6 +69329,13 @@ Object.freeze({
|
|
|
68620
69329
|
access: "view",
|
|
68621
69330
|
role: "admin"
|
|
68622
69331
|
},
|
|
69332
|
+
"addonSettings.unsetStoredSettingsKeys": {
|
|
69333
|
+
capName: "addon-settings",
|
|
69334
|
+
capScope: "system",
|
|
69335
|
+
addonId: null,
|
|
69336
|
+
access: "create",
|
|
69337
|
+
role: "admin"
|
|
69338
|
+
},
|
|
68623
69339
|
"addonSettings.updateDeviceSettings": {
|
|
68624
69340
|
capName: "addon-settings",
|
|
68625
69341
|
capScope: "system",
|
|
@@ -71035,6 +71751,13 @@ Object.freeze({
|
|
|
71035
71751
|
access: "create",
|
|
71036
71752
|
role: "admin"
|
|
71037
71753
|
},
|
|
71754
|
+
"deviceProvider.classifyDiscoveryHits": {
|
|
71755
|
+
capName: "device-provider",
|
|
71756
|
+
capScope: "system",
|
|
71757
|
+
addonId: null,
|
|
71758
|
+
access: "create",
|
|
71759
|
+
role: "admin"
|
|
71760
|
+
},
|
|
71038
71761
|
"deviceProvider.createDevice": {
|
|
71039
71762
|
capName: "device-provider",
|
|
71040
71763
|
capScope: "system",
|
|
@@ -71063,6 +71786,13 @@ Object.freeze({
|
|
|
71063
71786
|
access: "view",
|
|
71064
71787
|
role: "admin"
|
|
71065
71788
|
},
|
|
71789
|
+
"deviceProvider.getDiscoveryModes": {
|
|
71790
|
+
capName: "device-provider",
|
|
71791
|
+
capScope: "system",
|
|
71792
|
+
addonId: null,
|
|
71793
|
+
access: "view",
|
|
71794
|
+
role: "admin"
|
|
71795
|
+
},
|
|
71066
71796
|
"deviceProvider.getDiscoveryParamsSchema": {
|
|
71067
71797
|
capName: "device-provider",
|
|
71068
71798
|
capScope: "system",
|
|
@@ -71840,6 +72570,13 @@ Object.freeze({
|
|
|
71840
72570
|
access: "create",
|
|
71841
72571
|
role: "admin"
|
|
71842
72572
|
},
|
|
72573
|
+
"keychain.releaseRecordRefs": {
|
|
72574
|
+
capName: "keychain",
|
|
72575
|
+
capScope: "system",
|
|
72576
|
+
addonId: null,
|
|
72577
|
+
access: "create",
|
|
72578
|
+
role: "admin"
|
|
72579
|
+
},
|
|
71843
72580
|
"keychain.resolve": {
|
|
71844
72581
|
capName: "keychain",
|
|
71845
72582
|
capScope: "system",
|
|
@@ -72260,6 +72997,13 @@ Object.freeze({
|
|
|
72260
72997
|
access: "view",
|
|
72261
72998
|
role: "admin"
|
|
72262
72999
|
},
|
|
73000
|
+
"localNetwork.getScanSubnets": {
|
|
73001
|
+
capName: "local-network",
|
|
73002
|
+
capScope: "system",
|
|
73003
|
+
addonId: null,
|
|
73004
|
+
access: "view",
|
|
73005
|
+
role: "admin"
|
|
73006
|
+
},
|
|
72263
73007
|
"localNetwork.getTlsStatus": {
|
|
72264
73008
|
capName: "local-network",
|
|
72265
73009
|
capScope: "system",
|
|
@@ -72309,6 +73053,13 @@ Object.freeze({
|
|
|
72309
73053
|
access: "create",
|
|
72310
73054
|
role: "admin"
|
|
72311
73055
|
},
|
|
73056
|
+
"localNetwork.scanNetwork": {
|
|
73057
|
+
capName: "local-network",
|
|
73058
|
+
capScope: "system",
|
|
73059
|
+
addonId: null,
|
|
73060
|
+
access: "create",
|
|
73061
|
+
role: "admin"
|
|
73062
|
+
},
|
|
72312
73063
|
"localNetwork.setAddressRole": {
|
|
72313
73064
|
capName: "local-network",
|
|
72314
73065
|
capScope: "system",
|
|
@@ -72330,6 +73081,13 @@ Object.freeze({
|
|
|
72330
73081
|
access: "create",
|
|
72331
73082
|
role: "admin"
|
|
72332
73083
|
},
|
|
73084
|
+
"localNetwork.setScanSubnets": {
|
|
73085
|
+
capName: "local-network",
|
|
73086
|
+
capScope: "system",
|
|
73087
|
+
addonId: null,
|
|
73088
|
+
access: "create",
|
|
73089
|
+
role: "admin"
|
|
73090
|
+
},
|
|
72333
73091
|
"localNetwork.setViewerEndpoints": {
|
|
72334
73092
|
capName: "local-network",
|
|
72335
73093
|
capScope: "system",
|
|
@@ -76551,6 +77309,13 @@ Object.freeze({
|
|
|
76551
77309
|
access: "create",
|
|
76552
77310
|
role: "admin"
|
|
76553
77311
|
},
|
|
77312
|
+
"storageAdmin.dropOrphanedKind": {
|
|
77313
|
+
capName: "storage-admin",
|
|
77314
|
+
capScope: "system",
|
|
77315
|
+
addonId: null,
|
|
77316
|
+
access: "delete",
|
|
77317
|
+
role: "admin"
|
|
77318
|
+
},
|
|
76554
77319
|
"storageAdmin.listKinds": {
|
|
76555
77320
|
capName: "storage-admin",
|
|
76556
77321
|
capScope: "system",
|
|
@@ -76572,6 +77337,27 @@ Object.freeze({
|
|
|
76572
77337
|
access: "view",
|
|
76573
77338
|
role: "admin"
|
|
76574
77339
|
},
|
|
77340
|
+
"storageAdmin.scanStaleData": {
|
|
77341
|
+
capName: "storage-admin",
|
|
77342
|
+
capScope: "system",
|
|
77343
|
+
addonId: null,
|
|
77344
|
+
access: "create",
|
|
77345
|
+
role: "admin"
|
|
77346
|
+
},
|
|
77347
|
+
"storageAdmin.staleDataReport": {
|
|
77348
|
+
capName: "storage-admin",
|
|
77349
|
+
capScope: "system",
|
|
77350
|
+
addonId: null,
|
|
77351
|
+
access: "view",
|
|
77352
|
+
role: "admin"
|
|
77353
|
+
},
|
|
77354
|
+
"storageAdmin.unsetStaleSettingsKey": {
|
|
77355
|
+
capName: "storage-admin",
|
|
77356
|
+
capScope: "system",
|
|
77357
|
+
addonId: null,
|
|
77358
|
+
access: "create",
|
|
77359
|
+
role: "admin"
|
|
77360
|
+
},
|
|
76575
77361
|
"storageEvictable.evict": {
|
|
76576
77362
|
capName: "storage-evictable",
|
|
76577
77363
|
capScope: "system",
|