@camstack/addon-mqtt-broker 1.1.26 → 1.1.28
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/dist/mqtt-broker.addon.js +511 -2
- package/dist/mqtt-broker.addon.mjs +511 -2
- package/package.json +1 -1
|
@@ -7373,6 +7373,62 @@ var RecordingConfigSchema = object({
|
|
|
7373
7373
|
scrubThumbnails: ScrubThumbnailPresetSchema.optional()
|
|
7374
7374
|
});
|
|
7375
7375
|
/**
|
|
7376
|
+
* Ops-log — the durable, append-only operations audit shared by the
|
|
7377
|
+
* recordings and events management surfaces.
|
|
7378
|
+
*
|
|
7379
|
+
* ONE row shape is reused for both domains so a single "Activity" view can
|
|
7380
|
+
* merge the recorder's DurableState ring (recordings ops-log) and the
|
|
7381
|
+
* pipeline-analytics SQLite collection (events ops-log). Each row records a
|
|
7382
|
+
* management operation, WHY it ran (reason), and its measurable effect
|
|
7383
|
+
* (itemsAffected + bytesReclaimed). Writes are best-effort — a failed log must
|
|
7384
|
+
* never fail the operation it records.
|
|
7385
|
+
*/
|
|
7386
|
+
/** Which management domain the operation belongs to. */
|
|
7387
|
+
var OpsLogDomainSchema = _enum(["recording", "events"]);
|
|
7388
|
+
/** The kind of management operation performed. */
|
|
7389
|
+
var OpsLogOpSchema = _enum([
|
|
7390
|
+
"prune",
|
|
7391
|
+
"manual-delete",
|
|
7392
|
+
"rescan",
|
|
7393
|
+
"retention-run"
|
|
7394
|
+
]);
|
|
7395
|
+
/** Why the operation ran. */
|
|
7396
|
+
var OpsLogReasonSchema = _enum([
|
|
7397
|
+
"retention",
|
|
7398
|
+
"quota",
|
|
7399
|
+
"manual",
|
|
7400
|
+
"operator"
|
|
7401
|
+
]);
|
|
7402
|
+
/** One audit row, shared verbatim by both domains. */
|
|
7403
|
+
var OpsLogEntrySchema = object({
|
|
7404
|
+
/** Unique row id. */
|
|
7405
|
+
id: string(),
|
|
7406
|
+
/** Epoch ms the operation completed. */
|
|
7407
|
+
at: number(),
|
|
7408
|
+
domain: OpsLogDomainSchema,
|
|
7409
|
+
op: OpsLogOpSchema,
|
|
7410
|
+
reason: OpsLogReasonSchema,
|
|
7411
|
+
/** The camera the op targeted; null for a cluster/global op. */
|
|
7412
|
+
deviceId: number().nullable(),
|
|
7413
|
+
/** Node that performed the op (the log carries nodeId — no cross-node aggregation). */
|
|
7414
|
+
nodeId: string(),
|
|
7415
|
+
/** Buckets / rows deleted (op-specific unit). */
|
|
7416
|
+
itemsAffected: number(),
|
|
7417
|
+
/** Bytes reclaimed by the op (0 when not measurable). */
|
|
7418
|
+
bytesReclaimed: number(),
|
|
7419
|
+
/** Free-text detail (e.g. "floor moved to <ts>"); null when none. */
|
|
7420
|
+
detail: string().nullable(),
|
|
7421
|
+
/** Who/what triggered the op. */
|
|
7422
|
+
actor: string()
|
|
7423
|
+
});
|
|
7424
|
+
/** Shared query input for the per-domain `listOpsLog` cap methods. */
|
|
7425
|
+
var OpsLogQueryInputSchema = object({
|
|
7426
|
+
/** Restrict to a single camera; omit for every row. */
|
|
7427
|
+
deviceId: number().optional(),
|
|
7428
|
+
/** Max rows returned, newest-first. */
|
|
7429
|
+
limit: number().int().min(1).max(1e3).optional()
|
|
7430
|
+
});
|
|
7431
|
+
/**
|
|
7376
7432
|
* `StorageLocationType` — an addon-declared id that identifies the *kind* of
|
|
7377
7433
|
* storage a location serves. Defined here (not in `capabilities/storage.cap.ts`)
|
|
7378
7434
|
* so the persisted record schema and the consumer-facing cap can both consume it
|
|
@@ -7616,6 +7672,160 @@ var EncodeProfileSchema = object({
|
|
|
7616
7672
|
*/
|
|
7617
7673
|
outputArgs: array(string()).optional()
|
|
7618
7674
|
});
|
|
7675
|
+
var COCO_TO_MACRO = {
|
|
7676
|
+
mapping: {
|
|
7677
|
+
person: "person",
|
|
7678
|
+
bicycle: "vehicle",
|
|
7679
|
+
car: "vehicle",
|
|
7680
|
+
motorcycle: "vehicle",
|
|
7681
|
+
airplane: "vehicle",
|
|
7682
|
+
bus: "vehicle",
|
|
7683
|
+
train: "vehicle",
|
|
7684
|
+
truck: "vehicle",
|
|
7685
|
+
boat: "vehicle",
|
|
7686
|
+
bird: "animal",
|
|
7687
|
+
cat: "animal",
|
|
7688
|
+
dog: "animal",
|
|
7689
|
+
horse: "animal",
|
|
7690
|
+
sheep: "animal",
|
|
7691
|
+
cow: "animal",
|
|
7692
|
+
elephant: "animal",
|
|
7693
|
+
bear: "animal",
|
|
7694
|
+
zebra: "animal",
|
|
7695
|
+
giraffe: "animal",
|
|
7696
|
+
suitcase: "package",
|
|
7697
|
+
backpack: "package",
|
|
7698
|
+
handbag: "package"
|
|
7699
|
+
},
|
|
7700
|
+
preserveOriginal: false
|
|
7701
|
+
};
|
|
7702
|
+
var AUDIO_MACRO_LABELS = [
|
|
7703
|
+
{
|
|
7704
|
+
id: "speech",
|
|
7705
|
+
name: "Speech",
|
|
7706
|
+
icon: "🗣️"
|
|
7707
|
+
},
|
|
7708
|
+
{
|
|
7709
|
+
id: "scream",
|
|
7710
|
+
name: "Scream / Shout",
|
|
7711
|
+
icon: "😱"
|
|
7712
|
+
},
|
|
7713
|
+
{
|
|
7714
|
+
id: "crying",
|
|
7715
|
+
name: "Crying / Baby",
|
|
7716
|
+
icon: "😢"
|
|
7717
|
+
},
|
|
7718
|
+
{
|
|
7719
|
+
id: "laughter",
|
|
7720
|
+
name: "Laughter",
|
|
7721
|
+
icon: "😂"
|
|
7722
|
+
},
|
|
7723
|
+
{
|
|
7724
|
+
id: "music",
|
|
7725
|
+
name: "Music",
|
|
7726
|
+
icon: "🎵"
|
|
7727
|
+
},
|
|
7728
|
+
{
|
|
7729
|
+
id: "dog",
|
|
7730
|
+
name: "Dog",
|
|
7731
|
+
icon: "🐕"
|
|
7732
|
+
},
|
|
7733
|
+
{
|
|
7734
|
+
id: "cat",
|
|
7735
|
+
name: "Cat",
|
|
7736
|
+
icon: "🐈"
|
|
7737
|
+
},
|
|
7738
|
+
{
|
|
7739
|
+
id: "bird",
|
|
7740
|
+
name: "Bird",
|
|
7741
|
+
icon: "🐦"
|
|
7742
|
+
},
|
|
7743
|
+
{
|
|
7744
|
+
id: "animal",
|
|
7745
|
+
name: "Animal (other)",
|
|
7746
|
+
icon: "🐾"
|
|
7747
|
+
},
|
|
7748
|
+
{
|
|
7749
|
+
id: "alarm",
|
|
7750
|
+
name: "Alarm / Siren",
|
|
7751
|
+
icon: "🚨"
|
|
7752
|
+
},
|
|
7753
|
+
{
|
|
7754
|
+
id: "doorbell",
|
|
7755
|
+
name: "Doorbell / Knock",
|
|
7756
|
+
icon: "🔔"
|
|
7757
|
+
},
|
|
7758
|
+
{
|
|
7759
|
+
id: "glass_breaking",
|
|
7760
|
+
name: "Glass Breaking",
|
|
7761
|
+
icon: "💥"
|
|
7762
|
+
},
|
|
7763
|
+
{
|
|
7764
|
+
id: "gunshot",
|
|
7765
|
+
name: "Gunshot / Explosion",
|
|
7766
|
+
icon: "💣"
|
|
7767
|
+
},
|
|
7768
|
+
{
|
|
7769
|
+
id: "vehicle",
|
|
7770
|
+
name: "Vehicle",
|
|
7771
|
+
icon: "🚗"
|
|
7772
|
+
},
|
|
7773
|
+
{
|
|
7774
|
+
id: "siren",
|
|
7775
|
+
name: "Emergency Siren",
|
|
7776
|
+
icon: "🚑"
|
|
7777
|
+
},
|
|
7778
|
+
{
|
|
7779
|
+
id: "fire",
|
|
7780
|
+
name: "Fire / Smoke",
|
|
7781
|
+
icon: "🔥"
|
|
7782
|
+
},
|
|
7783
|
+
{
|
|
7784
|
+
id: "water",
|
|
7785
|
+
name: "Water",
|
|
7786
|
+
icon: "💧"
|
|
7787
|
+
},
|
|
7788
|
+
{
|
|
7789
|
+
id: "wind",
|
|
7790
|
+
name: "Wind / Weather",
|
|
7791
|
+
icon: "🌬️"
|
|
7792
|
+
},
|
|
7793
|
+
{
|
|
7794
|
+
id: "door",
|
|
7795
|
+
name: "Door",
|
|
7796
|
+
icon: "🚪"
|
|
7797
|
+
},
|
|
7798
|
+
{
|
|
7799
|
+
id: "footsteps",
|
|
7800
|
+
name: "Footsteps",
|
|
7801
|
+
icon: "👣"
|
|
7802
|
+
},
|
|
7803
|
+
{
|
|
7804
|
+
id: "crowd",
|
|
7805
|
+
name: "Crowd / Chatter",
|
|
7806
|
+
icon: "👥"
|
|
7807
|
+
},
|
|
7808
|
+
{
|
|
7809
|
+
id: "telephone",
|
|
7810
|
+
name: "Telephone",
|
|
7811
|
+
icon: "📞"
|
|
7812
|
+
},
|
|
7813
|
+
{
|
|
7814
|
+
id: "engine",
|
|
7815
|
+
name: "Engine / Motor",
|
|
7816
|
+
icon: "⚙️"
|
|
7817
|
+
},
|
|
7818
|
+
{
|
|
7819
|
+
id: "tools",
|
|
7820
|
+
name: "Tools / Construction",
|
|
7821
|
+
icon: "🔨"
|
|
7822
|
+
},
|
|
7823
|
+
{
|
|
7824
|
+
id: "silence",
|
|
7825
|
+
name: "Silence",
|
|
7826
|
+
icon: "🤫"
|
|
7827
|
+
}
|
|
7828
|
+
];
|
|
7619
7829
|
var YAMNET_TO_MACRO = {
|
|
7620
7830
|
mapping: {
|
|
7621
7831
|
Speech: "speech",
|
|
@@ -7882,6 +8092,125 @@ var _macroLookup = /* @__PURE__ */ new Map();
|
|
|
7882
8092
|
for (const [k, v] of Object.entries(YAMNET_TO_MACRO.mapping)) _macroLookup.set(k.toLowerCase(), v);
|
|
7883
8093
|
for (const [k, v] of Object.entries(APPLE_SA_TO_MACRO.mapping)) _macroLookup.set(k.toLowerCase(), v);
|
|
7884
8094
|
/**
|
|
8095
|
+
* Unified event-kind taxonomy — THE single source of truth for
|
|
8096
|
+
* `kind → { parentKind, category, level, color, iconId, labelKey, label,
|
|
8097
|
+
* icon }`.
|
|
8098
|
+
*
|
|
8099
|
+
* This dictionary folds together what used to be scattered across four
|
|
8100
|
+
* copies:
|
|
8101
|
+
* - `capabilities/sensor-event-kinds.ts` (sensor cap colors)
|
|
8102
|
+
* - `addon-post-analysis/.../services/event-kinds.ts`
|
|
8103
|
+
* (MOTION/PERSON/VEHICLE… _COLOR constants)
|
|
8104
|
+
* - `ui-library/composites/detection-colors.ts` (CLASS_COLORS)
|
|
8105
|
+
* - `addon-post-analysis/shared/frame/box-drawer.ts` (DEFAULT_COLOR)
|
|
8106
|
+
* - the COCO / audio class maps (macro ↔ sub relationships)
|
|
8107
|
+
*
|
|
8108
|
+
* The DATA (serializable — color/iconId/labelKey/parentKind) lives here in
|
|
8109
|
+
* `@camstack/types`. The UI-side mapping `iconId → lucide component` and
|
|
8110
|
+
* `labelKey → t()` lives in `@camstack/ui-library`. UIs never hardcode a
|
|
8111
|
+
* color or an icon: they read this dictionary (server descriptors carry the
|
|
8112
|
+
* fields inline; the client resolves color/icon/label from `iconId`/`kind`).
|
|
8113
|
+
*
|
|
8114
|
+
* Two levels only (v1 YAGNI): macro → sub. `person` is a leaf macro.
|
|
8115
|
+
*/
|
|
8116
|
+
var TAXONOMY_COLORS = {
|
|
8117
|
+
motion: "#f59e0b",
|
|
8118
|
+
audio: "#06b6d4",
|
|
8119
|
+
person: "#22c55e",
|
|
8120
|
+
vehicle: "#3b82f6",
|
|
8121
|
+
animal: "#f97316",
|
|
8122
|
+
package: "#a855f7",
|
|
8123
|
+
sensor: "#8b5cf6",
|
|
8124
|
+
control: "#10b981",
|
|
8125
|
+
genericDetection: "#64748b"
|
|
8126
|
+
};
|
|
8127
|
+
var DETECTION_SUB_COLORS = {
|
|
8128
|
+
car: "#f59e0b",
|
|
8129
|
+
truck: "#d97706",
|
|
8130
|
+
bus: "#b45309",
|
|
8131
|
+
motorcycle: "#eab308",
|
|
8132
|
+
bicycle: "#ca8a04",
|
|
8133
|
+
airplane: "#60a5fa",
|
|
8134
|
+
boat: "#2563eb",
|
|
8135
|
+
train: "#1d4ed8",
|
|
8136
|
+
bird: "#14b8a6",
|
|
8137
|
+
dog: "#84cc16",
|
|
8138
|
+
cat: "#f97316",
|
|
8139
|
+
horse: "#a16207",
|
|
8140
|
+
sheep: "#a3a3a3",
|
|
8141
|
+
cow: "#78716c",
|
|
8142
|
+
elephant: "#6b7280",
|
|
8143
|
+
bear: "#7c2d12",
|
|
8144
|
+
zebra: "#404040",
|
|
8145
|
+
giraffe: "#d4a373"
|
|
8146
|
+
};
|
|
8147
|
+
function titleCase(id) {
|
|
8148
|
+
return id.split(/[-_ ]/).filter((p) => p.length > 0).map((p) => p.charAt(0).toUpperCase() + p.slice(1)).join(" ");
|
|
8149
|
+
}
|
|
8150
|
+
var entries = /* @__PURE__ */ new Map();
|
|
8151
|
+
function macro(kind, category, color, iconId, label) {
|
|
8152
|
+
entries.set(kind, {
|
|
8153
|
+
kind,
|
|
8154
|
+
parentKind: null,
|
|
8155
|
+
level: "macro",
|
|
8156
|
+
category,
|
|
8157
|
+
color,
|
|
8158
|
+
iconId,
|
|
8159
|
+
labelKey: `eventKind.${kind}`,
|
|
8160
|
+
label
|
|
8161
|
+
});
|
|
8162
|
+
}
|
|
8163
|
+
function sub(kind, parentKind, category, color, iconId, label) {
|
|
8164
|
+
entries.set(kind, {
|
|
8165
|
+
kind,
|
|
8166
|
+
parentKind,
|
|
8167
|
+
level: "sub",
|
|
8168
|
+
category,
|
|
8169
|
+
color,
|
|
8170
|
+
iconId,
|
|
8171
|
+
labelKey: `eventKind.${kind}`,
|
|
8172
|
+
label
|
|
8173
|
+
});
|
|
8174
|
+
}
|
|
8175
|
+
macro("motion", "motion", TAXONOMY_COLORS.motion, "motion", "Motion");
|
|
8176
|
+
macro("audio", "audio", TAXONOMY_COLORS.audio, "audio", "Audio");
|
|
8177
|
+
macro("person", "detection", TAXONOMY_COLORS.person, "person", "Person");
|
|
8178
|
+
macro("vehicle", "detection", TAXONOMY_COLORS.vehicle, "vehicle", "Vehicle");
|
|
8179
|
+
macro("animal", "detection", TAXONOMY_COLORS.animal, "animal", "Animal");
|
|
8180
|
+
macro("package", "package", TAXONOMY_COLORS.package, "package", "Package");
|
|
8181
|
+
macro("sensor", "sensor", TAXONOMY_COLORS.sensor, "sensor", "Sensor");
|
|
8182
|
+
macro("control", "control", TAXONOMY_COLORS.control, "control", "Control");
|
|
8183
|
+
for (const [cocoClass, macroClass] of Object.entries(COCO_TO_MACRO.mapping)) {
|
|
8184
|
+
if (macroClass !== "vehicle" && macroClass !== "animal") continue;
|
|
8185
|
+
if (entries.has(cocoClass)) continue;
|
|
8186
|
+
sub(cocoClass, macroClass, "detection", DETECTION_SUB_COLORS[cocoClass] ?? TAXONOMY_COLORS.genericDetection, cocoClass, titleCase(cocoClass));
|
|
8187
|
+
}
|
|
8188
|
+
sub("package-delivered", "package", "package", TAXONOMY_COLORS.package, "package", "Package delivered");
|
|
8189
|
+
sub("package-picked-up", "package", "package", TAXONOMY_COLORS.package, "package", "Package picked up");
|
|
8190
|
+
sub("contact", "sensor", "sensor", "#f59e0b", "door", "Contact");
|
|
8191
|
+
sub("motion-sensor", "sensor", "sensor", TAXONOMY_COLORS.sensor, "pir", "Motion sensor");
|
|
8192
|
+
sub("smoke", "sensor", "sensor", "#ef4444", "smoke", "Smoke");
|
|
8193
|
+
sub("flood", "sensor", "sensor", "#3b82f6", "water", "Water leak");
|
|
8194
|
+
sub("gas", "sensor", "sensor", "#ef4444", "gas", "Gas");
|
|
8195
|
+
sub("carbon-monoxide", "sensor", "sensor", "#dc2626", "smoke", "Carbon monoxide");
|
|
8196
|
+
sub("vibration", "sensor", "sensor", "#eab308", "vibration", "Vibration");
|
|
8197
|
+
sub("tamper", "sensor", "sensor", "#f97316", "tamper", "Tamper");
|
|
8198
|
+
sub("presence", "sensor", "sensor", "#22c55e", "presence", "Presence");
|
|
8199
|
+
sub("enum-sensor", "sensor", "sensor", TAXONOMY_COLORS.sensor, "generic", "Sensor state");
|
|
8200
|
+
sub("device-event", "sensor", "sensor", "#10b981", "button", "Device event");
|
|
8201
|
+
sub("lock", "control", "control", "#0ea5e9", "lock", "Lock");
|
|
8202
|
+
sub("switch", "control", "control", TAXONOMY_COLORS.control, "switch", "Switch");
|
|
8203
|
+
sub("siren", "control", "control", "#dc2626", "siren", "Siren");
|
|
8204
|
+
sub("button", "control", "control", "#10b981", "button", "Button");
|
|
8205
|
+
sub("doorbell", "control", "control", "#a855f7", "doorbell", "Doorbell");
|
|
8206
|
+
for (const l of AUDIO_MACRO_LABELS) {
|
|
8207
|
+
const kind = `audio-${l.id}`;
|
|
8208
|
+
if (entries.has(kind)) continue;
|
|
8209
|
+
sub(kind, "audio", "audio", TAXONOMY_COLORS.audio, kind, l.name);
|
|
8210
|
+
}
|
|
8211
|
+
/** The complete taxonomy dictionary, keyed by kind. */
|
|
8212
|
+
var EVENT_TAXONOMY = Object.freeze(Object.fromEntries(entries));
|
|
8213
|
+
/**
|
|
7885
8214
|
* Error types for the safe expression engine. Two distinct classes so callers
|
|
7886
8215
|
* can tell a compile-time (grammar) failure from a runtime (evaluation)
|
|
7887
8216
|
* failure — both are non-fatal to the host: read paths degrade to "skip link".
|
|
@@ -15899,17 +16228,30 @@ var EventKindCategorySchema = _enum([
|
|
|
15899
16228
|
"audio",
|
|
15900
16229
|
"detection",
|
|
15901
16230
|
"sensor",
|
|
16231
|
+
"control",
|
|
15902
16232
|
"custom",
|
|
15903
16233
|
"package"
|
|
15904
16234
|
]);
|
|
16235
|
+
/** Taxonomy level — macro (timeline lane) vs sub (events-page leaf). */
|
|
16236
|
+
var EventKindLevelSchema = _enum(["macro", "sub"]);
|
|
15905
16237
|
var EventKindDescriptorSchema = object({
|
|
15906
|
-
/** Stable kind id (e.g. 'motion', '
|
|
16238
|
+
/** Stable kind id (e.g. 'motion', 'vehicle', 'car', 'lock'). */
|
|
15907
16239
|
kind: string(),
|
|
16240
|
+
/** i18n key resolved on the UI side; `label` is the English fallback. */
|
|
16241
|
+
labelKey: string(),
|
|
16242
|
+
/** English fallback label (kept for clients that don't translate). */
|
|
15908
16243
|
label: string(),
|
|
15909
16244
|
/** Hex color for timeline/legend rendering. */
|
|
15910
16245
|
color: string(),
|
|
16246
|
+
/** Dictionary id → lucide component on the UI side. */
|
|
16247
|
+
iconId: string(),
|
|
16248
|
+
/** Legacy closed-vocab glyph — fallback for `iconId`. */
|
|
15911
16249
|
icon: EventKindIconSchema,
|
|
15912
16250
|
category: EventKindCategorySchema,
|
|
16251
|
+
/** Macro parent for this kind ('car' → 'vehicle'); null for a macro. */
|
|
16252
|
+
parentKind: string().nullable(),
|
|
16253
|
+
/** Derived from `parentKind`, explicit for the client tree. */
|
|
16254
|
+
level: EventKindLevelSchema,
|
|
15913
16255
|
/** Which cap + device contributes this kind. For built-ins the camera
|
|
15914
16256
|
* itself; for sensor kinds the LINKED source device. */
|
|
15915
16257
|
source: object({
|
|
@@ -15982,11 +16324,21 @@ var TrackAudioLabelSchema = object({
|
|
|
15982
16324
|
firstAt: number(),
|
|
15983
16325
|
lastAt: number()
|
|
15984
16326
|
});
|
|
16327
|
+
/**
|
|
16328
|
+
* How a track was produced. `pipeline` (default / absent) = the spatial
|
|
16329
|
+
* detection+tracking pipeline. `sensor` = a SYNTHETIC track projected from a
|
|
16330
|
+
* linked sensor/control state change (no positions; carries a snapshot). The
|
|
16331
|
+
* spatial subsystems (tracker association, occupancy count, re-id/embedding,
|
|
16332
|
+
* resurrection) MUST skip `sensor` tracks — they have no bbox trajectory.
|
|
16333
|
+
*/
|
|
16334
|
+
var TrackSourceSchema = _enum(["pipeline", "sensor"]);
|
|
15985
16335
|
var TrackSchema = object({
|
|
15986
16336
|
trackId: string(),
|
|
15987
16337
|
deviceId: number(),
|
|
15988
16338
|
className: string(),
|
|
15989
16339
|
label: string().optional(),
|
|
16340
|
+
/** Track provenance. Absent ⇒ `pipeline` (legacy rows). */
|
|
16341
|
+
source: TrackSourceSchema.optional(),
|
|
15990
16342
|
firstSeen: number(),
|
|
15991
16343
|
lastSeen: number(),
|
|
15992
16344
|
/** Frame-rate position history (subject to maxPositionHistory cap). */
|
|
@@ -16241,6 +16593,26 @@ var TrackCascadeCountsSchema = object({
|
|
|
16241
16593
|
/** Per-track CLIP search vectors removed (best-effort). */
|
|
16242
16594
|
embeddings: number().int()
|
|
16243
16595
|
});
|
|
16596
|
+
/** Event-store footprint for one camera. */
|
|
16597
|
+
var EventStoreDeviceFootprintSchema = object({
|
|
16598
|
+
deviceId: number(),
|
|
16599
|
+
/** Persisted event rows (motion + object + audio) for the camera. */
|
|
16600
|
+
rows: number().int(),
|
|
16601
|
+
/** Event-owned media bytes on disk for the camera. */
|
|
16602
|
+
bytes: number().int()
|
|
16603
|
+
});
|
|
16604
|
+
/** Aggregate event-store footprint: global totals + per-camera breakdown. */
|
|
16605
|
+
var EventStoreFootprintSchema = object({
|
|
16606
|
+
totalRows: number().int(),
|
|
16607
|
+
totalBytes: number().int(),
|
|
16608
|
+
devices: array(EventStoreDeviceFootprintSchema).readonly()
|
|
16609
|
+
});
|
|
16610
|
+
/** Per-kind counts returned by the event-prune / device-delete mutations. */
|
|
16611
|
+
var EventPruneCountsSchema = object({
|
|
16612
|
+
motion: number().int(),
|
|
16613
|
+
object: number().int(),
|
|
16614
|
+
audio: number().int()
|
|
16615
|
+
});
|
|
16244
16616
|
DeviceType.Camera, method(object({ deviceId: number() }), array(TrackSchema).readonly()), method(object({
|
|
16245
16617
|
deviceId: number(),
|
|
16246
16618
|
trackId: string()
|
|
@@ -16304,6 +16676,21 @@ DeviceType.Camera, method(object({ deviceId: number() }), array(TrackSchema).rea
|
|
|
16304
16676
|
}), {
|
|
16305
16677
|
kind: "mutation",
|
|
16306
16678
|
auth: "admin"
|
|
16679
|
+
}), method(object({}), EventStoreFootprintSchema, {
|
|
16680
|
+
kind: "query",
|
|
16681
|
+
auth: "admin"
|
|
16682
|
+
}), method(object({
|
|
16683
|
+
olderThanMs: number(),
|
|
16684
|
+
reason: OpsLogReasonSchema.optional()
|
|
16685
|
+
}), EventPruneCountsSchema, {
|
|
16686
|
+
kind: "mutation",
|
|
16687
|
+
auth: "admin"
|
|
16688
|
+
}), method(object({ deviceId: number() }), EventPruneCountsSchema, {
|
|
16689
|
+
kind: "mutation",
|
|
16690
|
+
auth: "admin"
|
|
16691
|
+
}), method(OpsLogQueryInputSchema, array(OpsLogEntrySchema).readonly(), {
|
|
16692
|
+
kind: "query",
|
|
16693
|
+
auth: "admin"
|
|
16307
16694
|
}), method(object({
|
|
16308
16695
|
eventId: string(),
|
|
16309
16696
|
kind: MediaFileKindEnum.optional()
|
|
@@ -16328,6 +16715,76 @@ DeviceType.Camera, method(object({ deviceId: number() }), array(TrackSchema).rea
|
|
|
16328
16715
|
eventId: string(),
|
|
16329
16716
|
timestamp: number()
|
|
16330
16717
|
});
|
|
16718
|
+
/**
|
|
16719
|
+
* Cap → event-kind mapping for the SENSOR / CONTROL cap families — the table
|
|
16720
|
+
* `pipeline-analytics.listEventKinds` uses to turn a linked device's bound
|
|
16721
|
+
* caps into per-camera event-kind descriptors.
|
|
16722
|
+
*
|
|
16723
|
+
* The descriptor DATA (color / iconId / labelKey / parentKind / category)
|
|
16724
|
+
* is NOT duplicated here — every entry is derived from the single
|
|
16725
|
+
* `EVENT_TAXONOMY` dictionary (`catalogs/event-taxonomy.ts`). This file owns
|
|
16726
|
+
* ONLY the cap-name → taxonomy-kind mapping. Adding a new eventful sensor /
|
|
16727
|
+
* control cap means adding one line here (and a taxonomy entry); the anti-
|
|
16728
|
+
* drift guard `scripts/check-event-kind-coverage.ts` fails the build if an
|
|
16729
|
+
* eventful cap is missing.
|
|
16730
|
+
*/
|
|
16731
|
+
/** Map a taxonomy `iconId` onto the legacy closed `EventKindIcon` enum. */
|
|
16732
|
+
var LEGACY_ICON = {
|
|
16733
|
+
motion: "motion",
|
|
16734
|
+
audio: "audio",
|
|
16735
|
+
person: "person",
|
|
16736
|
+
vehicle: "vehicle",
|
|
16737
|
+
animal: "animal",
|
|
16738
|
+
package: "package",
|
|
16739
|
+
door: "door",
|
|
16740
|
+
pir: "pir",
|
|
16741
|
+
smoke: "smoke",
|
|
16742
|
+
water: "water",
|
|
16743
|
+
button: "button",
|
|
16744
|
+
generic: "generic",
|
|
16745
|
+
gas: "smoke",
|
|
16746
|
+
vibration: "generic",
|
|
16747
|
+
tamper: "generic",
|
|
16748
|
+
presence: "person",
|
|
16749
|
+
lock: "generic",
|
|
16750
|
+
siren: "generic",
|
|
16751
|
+
switch: "generic",
|
|
16752
|
+
doorbell: "button"
|
|
16753
|
+
};
|
|
16754
|
+
function legacyIcon(iconId) {
|
|
16755
|
+
return LEGACY_ICON[iconId] ?? "generic";
|
|
16756
|
+
}
|
|
16757
|
+
/**
|
|
16758
|
+
* Cap name → taxonomy kind id. Covers EVERY eventful sensor / control cap.
|
|
16759
|
+
* The anti-drift guard cross-checks this against the eventful caps declared
|
|
16760
|
+
* in `packages/types/src/capabilities/*.cap.ts`.
|
|
16761
|
+
*/
|
|
16762
|
+
var CAP_TO_KIND = {
|
|
16763
|
+
contact: "contact",
|
|
16764
|
+
motion: "motion-sensor",
|
|
16765
|
+
smoke: "smoke",
|
|
16766
|
+
flood: "flood",
|
|
16767
|
+
gas: "gas",
|
|
16768
|
+
"carbon-monoxide": "carbon-monoxide",
|
|
16769
|
+
vibration: "vibration",
|
|
16770
|
+
tamper: "tamper",
|
|
16771
|
+
presence: "presence",
|
|
16772
|
+
"enum-sensor": "enum-sensor",
|
|
16773
|
+
"event-emitter": "device-event",
|
|
16774
|
+
"lock-control": "lock",
|
|
16775
|
+
switch: "switch",
|
|
16776
|
+
button: "button",
|
|
16777
|
+
doorbell: "doorbell"
|
|
16778
|
+
};
|
|
16779
|
+
function buildDescriptor(capName, kind) {
|
|
16780
|
+
const t = EVENT_TAXONOMY[kind];
|
|
16781
|
+
if (t === void 0) throw new Error(`EVENT_KIND_BY_CAP: cap '${capName}' maps to unknown taxonomy kind '${kind}'`);
|
|
16782
|
+
return {
|
|
16783
|
+
...t,
|
|
16784
|
+
icon: legacyIcon(t.iconId)
|
|
16785
|
+
};
|
|
16786
|
+
}
|
|
16787
|
+
Object.freeze(Object.fromEntries(Object.entries(CAP_TO_KIND).map(([capName, kind]) => [capName, buildDescriptor(capName, kind)])));
|
|
16331
16788
|
var CameraPipelineConfigSchema = object({
|
|
16332
16789
|
engine: PipelineEngineChoiceSchema.optional(),
|
|
16333
16790
|
steps: array(PipelineStepInputSchema).readonly(),
|
|
@@ -19537,13 +19994,29 @@ method(object({
|
|
|
19537
19994
|
}), method(object({ deviceId: number() }), RecordingStatusSchema, {
|
|
19538
19995
|
kind: "mutation",
|
|
19539
19996
|
auth: "admin"
|
|
19540
|
-
}), method(object({
|
|
19997
|
+
}), method(object({
|
|
19998
|
+
deviceId: number(),
|
|
19999
|
+
reason: OpsLogReasonSchema.optional()
|
|
20000
|
+
}), object({
|
|
19541
20001
|
floorMs: number().nullable(),
|
|
19542
20002
|
deletedBuckets: number().int(),
|
|
19543
20003
|
reclaimedBytes: number().int()
|
|
19544
20004
|
}), {
|
|
19545
20005
|
kind: "mutation",
|
|
19546
20006
|
auth: "admin"
|
|
20007
|
+
}), method(object({
|
|
20008
|
+
deviceId: number(),
|
|
20009
|
+
fromMs: number().optional(),
|
|
20010
|
+
toMs: number().optional()
|
|
20011
|
+
}), object({
|
|
20012
|
+
deletedBuckets: number().int(),
|
|
20013
|
+
reclaimedBytes: number().int()
|
|
20014
|
+
}), {
|
|
20015
|
+
kind: "mutation",
|
|
20016
|
+
auth: "admin"
|
|
20017
|
+
}), method(OpsLogQueryInputSchema, array(OpsLogEntrySchema).readonly(), {
|
|
20018
|
+
kind: "query",
|
|
20019
|
+
auth: "admin"
|
|
19547
20020
|
});
|
|
19548
20021
|
/**
|
|
19549
20022
|
* `recordingExport` cap — render a footage time range into a single downloadable
|
|
@@ -22665,6 +23138,12 @@ Object.freeze({
|
|
|
22665
23138
|
addonId: null,
|
|
22666
23139
|
access: "delete"
|
|
22667
23140
|
},
|
|
23141
|
+
"pipelineAnalytics.deleteDeviceEvents": {
|
|
23142
|
+
capName: "pipeline-analytics",
|
|
23143
|
+
capScope: "device",
|
|
23144
|
+
addonId: null,
|
|
23145
|
+
access: "delete"
|
|
23146
|
+
},
|
|
22668
23147
|
"pipelineAnalytics.deleteTracks": {
|
|
22669
23148
|
capName: "pipeline-analytics",
|
|
22670
23149
|
capScope: "device",
|
|
@@ -22695,6 +23174,12 @@ Object.freeze({
|
|
|
22695
23174
|
addonId: null,
|
|
22696
23175
|
access: "view"
|
|
22697
23176
|
},
|
|
23177
|
+
"pipelineAnalytics.getEventStoreFootprint": {
|
|
23178
|
+
capName: "pipeline-analytics",
|
|
23179
|
+
capScope: "device",
|
|
23180
|
+
addonId: null,
|
|
23181
|
+
access: "view"
|
|
23182
|
+
},
|
|
22698
23183
|
"pipelineAnalytics.getKeyEvents": {
|
|
22699
23184
|
capName: "pipeline-analytics",
|
|
22700
23185
|
capScope: "device",
|
|
@@ -22737,6 +23222,12 @@ Object.freeze({
|
|
|
22737
23222
|
addonId: null,
|
|
22738
23223
|
access: "view"
|
|
22739
23224
|
},
|
|
23225
|
+
"pipelineAnalytics.listOpsLog": {
|
|
23226
|
+
capName: "pipeline-analytics",
|
|
23227
|
+
capScope: "device",
|
|
23228
|
+
addonId: null,
|
|
23229
|
+
access: "view"
|
|
23230
|
+
},
|
|
22740
23231
|
"pipelineAnalytics.listRecentTracks": {
|
|
22741
23232
|
capName: "pipeline-analytics",
|
|
22742
23233
|
capScope: "device",
|
|
@@ -22749,6 +23240,12 @@ Object.freeze({
|
|
|
22749
23240
|
addonId: null,
|
|
22750
23241
|
access: "view"
|
|
22751
23242
|
},
|
|
23243
|
+
"pipelineAnalytics.pruneEvents": {
|
|
23244
|
+
capName: "pipeline-analytics",
|
|
23245
|
+
capScope: "device",
|
|
23246
|
+
addonId: null,
|
|
23247
|
+
access: "create"
|
|
23248
|
+
},
|
|
22752
23249
|
"pipelineAnalytics.pruneEventsBefore": {
|
|
22753
23250
|
capName: "pipeline-analytics",
|
|
22754
23251
|
capScope: "device",
|
|
@@ -23511,6 +24008,12 @@ Object.freeze({
|
|
|
23511
24008
|
addonId: null,
|
|
23512
24009
|
access: "create"
|
|
23513
24010
|
},
|
|
24011
|
+
"recording.deleteFootprint": {
|
|
24012
|
+
capName: "recording",
|
|
24013
|
+
capScope: "system",
|
|
24014
|
+
addonId: null,
|
|
24015
|
+
access: "delete"
|
|
24016
|
+
},
|
|
23514
24017
|
"recording.getAvailability": {
|
|
23515
24018
|
capName: "recording",
|
|
23516
24019
|
capScope: "system",
|
|
@@ -23541,6 +24044,12 @@ Object.freeze({
|
|
|
23541
24044
|
addonId: null,
|
|
23542
24045
|
access: "view"
|
|
23543
24046
|
},
|
|
24047
|
+
"recording.listOpsLog": {
|
|
24048
|
+
capName: "recording",
|
|
24049
|
+
capScope: "system",
|
|
24050
|
+
addonId: null,
|
|
24051
|
+
access: "view"
|
|
24052
|
+
},
|
|
23544
24053
|
"recording.locateSegment": {
|
|
23545
24054
|
capName: "recording",
|
|
23546
24055
|
capScope: "system",
|
|
@@ -7368,6 +7368,62 @@ var RecordingConfigSchema = object({
|
|
|
7368
7368
|
scrubThumbnails: ScrubThumbnailPresetSchema.optional()
|
|
7369
7369
|
});
|
|
7370
7370
|
/**
|
|
7371
|
+
* Ops-log — the durable, append-only operations audit shared by the
|
|
7372
|
+
* recordings and events management surfaces.
|
|
7373
|
+
*
|
|
7374
|
+
* ONE row shape is reused for both domains so a single "Activity" view can
|
|
7375
|
+
* merge the recorder's DurableState ring (recordings ops-log) and the
|
|
7376
|
+
* pipeline-analytics SQLite collection (events ops-log). Each row records a
|
|
7377
|
+
* management operation, WHY it ran (reason), and its measurable effect
|
|
7378
|
+
* (itemsAffected + bytesReclaimed). Writes are best-effort — a failed log must
|
|
7379
|
+
* never fail the operation it records.
|
|
7380
|
+
*/
|
|
7381
|
+
/** Which management domain the operation belongs to. */
|
|
7382
|
+
var OpsLogDomainSchema = _enum(["recording", "events"]);
|
|
7383
|
+
/** The kind of management operation performed. */
|
|
7384
|
+
var OpsLogOpSchema = _enum([
|
|
7385
|
+
"prune",
|
|
7386
|
+
"manual-delete",
|
|
7387
|
+
"rescan",
|
|
7388
|
+
"retention-run"
|
|
7389
|
+
]);
|
|
7390
|
+
/** Why the operation ran. */
|
|
7391
|
+
var OpsLogReasonSchema = _enum([
|
|
7392
|
+
"retention",
|
|
7393
|
+
"quota",
|
|
7394
|
+
"manual",
|
|
7395
|
+
"operator"
|
|
7396
|
+
]);
|
|
7397
|
+
/** One audit row, shared verbatim by both domains. */
|
|
7398
|
+
var OpsLogEntrySchema = object({
|
|
7399
|
+
/** Unique row id. */
|
|
7400
|
+
id: string(),
|
|
7401
|
+
/** Epoch ms the operation completed. */
|
|
7402
|
+
at: number(),
|
|
7403
|
+
domain: OpsLogDomainSchema,
|
|
7404
|
+
op: OpsLogOpSchema,
|
|
7405
|
+
reason: OpsLogReasonSchema,
|
|
7406
|
+
/** The camera the op targeted; null for a cluster/global op. */
|
|
7407
|
+
deviceId: number().nullable(),
|
|
7408
|
+
/** Node that performed the op (the log carries nodeId — no cross-node aggregation). */
|
|
7409
|
+
nodeId: string(),
|
|
7410
|
+
/** Buckets / rows deleted (op-specific unit). */
|
|
7411
|
+
itemsAffected: number(),
|
|
7412
|
+
/** Bytes reclaimed by the op (0 when not measurable). */
|
|
7413
|
+
bytesReclaimed: number(),
|
|
7414
|
+
/** Free-text detail (e.g. "floor moved to <ts>"); null when none. */
|
|
7415
|
+
detail: string().nullable(),
|
|
7416
|
+
/** Who/what triggered the op. */
|
|
7417
|
+
actor: string()
|
|
7418
|
+
});
|
|
7419
|
+
/** Shared query input for the per-domain `listOpsLog` cap methods. */
|
|
7420
|
+
var OpsLogQueryInputSchema = object({
|
|
7421
|
+
/** Restrict to a single camera; omit for every row. */
|
|
7422
|
+
deviceId: number().optional(),
|
|
7423
|
+
/** Max rows returned, newest-first. */
|
|
7424
|
+
limit: number().int().min(1).max(1e3).optional()
|
|
7425
|
+
});
|
|
7426
|
+
/**
|
|
7371
7427
|
* `StorageLocationType` — an addon-declared id that identifies the *kind* of
|
|
7372
7428
|
* storage a location serves. Defined here (not in `capabilities/storage.cap.ts`)
|
|
7373
7429
|
* so the persisted record schema and the consumer-facing cap can both consume it
|
|
@@ -7611,6 +7667,160 @@ var EncodeProfileSchema = object({
|
|
|
7611
7667
|
*/
|
|
7612
7668
|
outputArgs: array(string()).optional()
|
|
7613
7669
|
});
|
|
7670
|
+
var COCO_TO_MACRO = {
|
|
7671
|
+
mapping: {
|
|
7672
|
+
person: "person",
|
|
7673
|
+
bicycle: "vehicle",
|
|
7674
|
+
car: "vehicle",
|
|
7675
|
+
motorcycle: "vehicle",
|
|
7676
|
+
airplane: "vehicle",
|
|
7677
|
+
bus: "vehicle",
|
|
7678
|
+
train: "vehicle",
|
|
7679
|
+
truck: "vehicle",
|
|
7680
|
+
boat: "vehicle",
|
|
7681
|
+
bird: "animal",
|
|
7682
|
+
cat: "animal",
|
|
7683
|
+
dog: "animal",
|
|
7684
|
+
horse: "animal",
|
|
7685
|
+
sheep: "animal",
|
|
7686
|
+
cow: "animal",
|
|
7687
|
+
elephant: "animal",
|
|
7688
|
+
bear: "animal",
|
|
7689
|
+
zebra: "animal",
|
|
7690
|
+
giraffe: "animal",
|
|
7691
|
+
suitcase: "package",
|
|
7692
|
+
backpack: "package",
|
|
7693
|
+
handbag: "package"
|
|
7694
|
+
},
|
|
7695
|
+
preserveOriginal: false
|
|
7696
|
+
};
|
|
7697
|
+
var AUDIO_MACRO_LABELS = [
|
|
7698
|
+
{
|
|
7699
|
+
id: "speech",
|
|
7700
|
+
name: "Speech",
|
|
7701
|
+
icon: "🗣️"
|
|
7702
|
+
},
|
|
7703
|
+
{
|
|
7704
|
+
id: "scream",
|
|
7705
|
+
name: "Scream / Shout",
|
|
7706
|
+
icon: "😱"
|
|
7707
|
+
},
|
|
7708
|
+
{
|
|
7709
|
+
id: "crying",
|
|
7710
|
+
name: "Crying / Baby",
|
|
7711
|
+
icon: "😢"
|
|
7712
|
+
},
|
|
7713
|
+
{
|
|
7714
|
+
id: "laughter",
|
|
7715
|
+
name: "Laughter",
|
|
7716
|
+
icon: "😂"
|
|
7717
|
+
},
|
|
7718
|
+
{
|
|
7719
|
+
id: "music",
|
|
7720
|
+
name: "Music",
|
|
7721
|
+
icon: "🎵"
|
|
7722
|
+
},
|
|
7723
|
+
{
|
|
7724
|
+
id: "dog",
|
|
7725
|
+
name: "Dog",
|
|
7726
|
+
icon: "🐕"
|
|
7727
|
+
},
|
|
7728
|
+
{
|
|
7729
|
+
id: "cat",
|
|
7730
|
+
name: "Cat",
|
|
7731
|
+
icon: "🐈"
|
|
7732
|
+
},
|
|
7733
|
+
{
|
|
7734
|
+
id: "bird",
|
|
7735
|
+
name: "Bird",
|
|
7736
|
+
icon: "🐦"
|
|
7737
|
+
},
|
|
7738
|
+
{
|
|
7739
|
+
id: "animal",
|
|
7740
|
+
name: "Animal (other)",
|
|
7741
|
+
icon: "🐾"
|
|
7742
|
+
},
|
|
7743
|
+
{
|
|
7744
|
+
id: "alarm",
|
|
7745
|
+
name: "Alarm / Siren",
|
|
7746
|
+
icon: "🚨"
|
|
7747
|
+
},
|
|
7748
|
+
{
|
|
7749
|
+
id: "doorbell",
|
|
7750
|
+
name: "Doorbell / Knock",
|
|
7751
|
+
icon: "🔔"
|
|
7752
|
+
},
|
|
7753
|
+
{
|
|
7754
|
+
id: "glass_breaking",
|
|
7755
|
+
name: "Glass Breaking",
|
|
7756
|
+
icon: "💥"
|
|
7757
|
+
},
|
|
7758
|
+
{
|
|
7759
|
+
id: "gunshot",
|
|
7760
|
+
name: "Gunshot / Explosion",
|
|
7761
|
+
icon: "💣"
|
|
7762
|
+
},
|
|
7763
|
+
{
|
|
7764
|
+
id: "vehicle",
|
|
7765
|
+
name: "Vehicle",
|
|
7766
|
+
icon: "🚗"
|
|
7767
|
+
},
|
|
7768
|
+
{
|
|
7769
|
+
id: "siren",
|
|
7770
|
+
name: "Emergency Siren",
|
|
7771
|
+
icon: "🚑"
|
|
7772
|
+
},
|
|
7773
|
+
{
|
|
7774
|
+
id: "fire",
|
|
7775
|
+
name: "Fire / Smoke",
|
|
7776
|
+
icon: "🔥"
|
|
7777
|
+
},
|
|
7778
|
+
{
|
|
7779
|
+
id: "water",
|
|
7780
|
+
name: "Water",
|
|
7781
|
+
icon: "💧"
|
|
7782
|
+
},
|
|
7783
|
+
{
|
|
7784
|
+
id: "wind",
|
|
7785
|
+
name: "Wind / Weather",
|
|
7786
|
+
icon: "🌬️"
|
|
7787
|
+
},
|
|
7788
|
+
{
|
|
7789
|
+
id: "door",
|
|
7790
|
+
name: "Door",
|
|
7791
|
+
icon: "🚪"
|
|
7792
|
+
},
|
|
7793
|
+
{
|
|
7794
|
+
id: "footsteps",
|
|
7795
|
+
name: "Footsteps",
|
|
7796
|
+
icon: "👣"
|
|
7797
|
+
},
|
|
7798
|
+
{
|
|
7799
|
+
id: "crowd",
|
|
7800
|
+
name: "Crowd / Chatter",
|
|
7801
|
+
icon: "👥"
|
|
7802
|
+
},
|
|
7803
|
+
{
|
|
7804
|
+
id: "telephone",
|
|
7805
|
+
name: "Telephone",
|
|
7806
|
+
icon: "📞"
|
|
7807
|
+
},
|
|
7808
|
+
{
|
|
7809
|
+
id: "engine",
|
|
7810
|
+
name: "Engine / Motor",
|
|
7811
|
+
icon: "⚙️"
|
|
7812
|
+
},
|
|
7813
|
+
{
|
|
7814
|
+
id: "tools",
|
|
7815
|
+
name: "Tools / Construction",
|
|
7816
|
+
icon: "🔨"
|
|
7817
|
+
},
|
|
7818
|
+
{
|
|
7819
|
+
id: "silence",
|
|
7820
|
+
name: "Silence",
|
|
7821
|
+
icon: "🤫"
|
|
7822
|
+
}
|
|
7823
|
+
];
|
|
7614
7824
|
var YAMNET_TO_MACRO = {
|
|
7615
7825
|
mapping: {
|
|
7616
7826
|
Speech: "speech",
|
|
@@ -7877,6 +8087,125 @@ var _macroLookup = /* @__PURE__ */ new Map();
|
|
|
7877
8087
|
for (const [k, v] of Object.entries(YAMNET_TO_MACRO.mapping)) _macroLookup.set(k.toLowerCase(), v);
|
|
7878
8088
|
for (const [k, v] of Object.entries(APPLE_SA_TO_MACRO.mapping)) _macroLookup.set(k.toLowerCase(), v);
|
|
7879
8089
|
/**
|
|
8090
|
+
* Unified event-kind taxonomy — THE single source of truth for
|
|
8091
|
+
* `kind → { parentKind, category, level, color, iconId, labelKey, label,
|
|
8092
|
+
* icon }`.
|
|
8093
|
+
*
|
|
8094
|
+
* This dictionary folds together what used to be scattered across four
|
|
8095
|
+
* copies:
|
|
8096
|
+
* - `capabilities/sensor-event-kinds.ts` (sensor cap colors)
|
|
8097
|
+
* - `addon-post-analysis/.../services/event-kinds.ts`
|
|
8098
|
+
* (MOTION/PERSON/VEHICLE… _COLOR constants)
|
|
8099
|
+
* - `ui-library/composites/detection-colors.ts` (CLASS_COLORS)
|
|
8100
|
+
* - `addon-post-analysis/shared/frame/box-drawer.ts` (DEFAULT_COLOR)
|
|
8101
|
+
* - the COCO / audio class maps (macro ↔ sub relationships)
|
|
8102
|
+
*
|
|
8103
|
+
* The DATA (serializable — color/iconId/labelKey/parentKind) lives here in
|
|
8104
|
+
* `@camstack/types`. The UI-side mapping `iconId → lucide component` and
|
|
8105
|
+
* `labelKey → t()` lives in `@camstack/ui-library`. UIs never hardcode a
|
|
8106
|
+
* color or an icon: they read this dictionary (server descriptors carry the
|
|
8107
|
+
* fields inline; the client resolves color/icon/label from `iconId`/`kind`).
|
|
8108
|
+
*
|
|
8109
|
+
* Two levels only (v1 YAGNI): macro → sub. `person` is a leaf macro.
|
|
8110
|
+
*/
|
|
8111
|
+
var TAXONOMY_COLORS = {
|
|
8112
|
+
motion: "#f59e0b",
|
|
8113
|
+
audio: "#06b6d4",
|
|
8114
|
+
person: "#22c55e",
|
|
8115
|
+
vehicle: "#3b82f6",
|
|
8116
|
+
animal: "#f97316",
|
|
8117
|
+
package: "#a855f7",
|
|
8118
|
+
sensor: "#8b5cf6",
|
|
8119
|
+
control: "#10b981",
|
|
8120
|
+
genericDetection: "#64748b"
|
|
8121
|
+
};
|
|
8122
|
+
var DETECTION_SUB_COLORS = {
|
|
8123
|
+
car: "#f59e0b",
|
|
8124
|
+
truck: "#d97706",
|
|
8125
|
+
bus: "#b45309",
|
|
8126
|
+
motorcycle: "#eab308",
|
|
8127
|
+
bicycle: "#ca8a04",
|
|
8128
|
+
airplane: "#60a5fa",
|
|
8129
|
+
boat: "#2563eb",
|
|
8130
|
+
train: "#1d4ed8",
|
|
8131
|
+
bird: "#14b8a6",
|
|
8132
|
+
dog: "#84cc16",
|
|
8133
|
+
cat: "#f97316",
|
|
8134
|
+
horse: "#a16207",
|
|
8135
|
+
sheep: "#a3a3a3",
|
|
8136
|
+
cow: "#78716c",
|
|
8137
|
+
elephant: "#6b7280",
|
|
8138
|
+
bear: "#7c2d12",
|
|
8139
|
+
zebra: "#404040",
|
|
8140
|
+
giraffe: "#d4a373"
|
|
8141
|
+
};
|
|
8142
|
+
function titleCase(id) {
|
|
8143
|
+
return id.split(/[-_ ]/).filter((p) => p.length > 0).map((p) => p.charAt(0).toUpperCase() + p.slice(1)).join(" ");
|
|
8144
|
+
}
|
|
8145
|
+
var entries = /* @__PURE__ */ new Map();
|
|
8146
|
+
function macro(kind, category, color, iconId, label) {
|
|
8147
|
+
entries.set(kind, {
|
|
8148
|
+
kind,
|
|
8149
|
+
parentKind: null,
|
|
8150
|
+
level: "macro",
|
|
8151
|
+
category,
|
|
8152
|
+
color,
|
|
8153
|
+
iconId,
|
|
8154
|
+
labelKey: `eventKind.${kind}`,
|
|
8155
|
+
label
|
|
8156
|
+
});
|
|
8157
|
+
}
|
|
8158
|
+
function sub(kind, parentKind, category, color, iconId, label) {
|
|
8159
|
+
entries.set(kind, {
|
|
8160
|
+
kind,
|
|
8161
|
+
parentKind,
|
|
8162
|
+
level: "sub",
|
|
8163
|
+
category,
|
|
8164
|
+
color,
|
|
8165
|
+
iconId,
|
|
8166
|
+
labelKey: `eventKind.${kind}`,
|
|
8167
|
+
label
|
|
8168
|
+
});
|
|
8169
|
+
}
|
|
8170
|
+
macro("motion", "motion", TAXONOMY_COLORS.motion, "motion", "Motion");
|
|
8171
|
+
macro("audio", "audio", TAXONOMY_COLORS.audio, "audio", "Audio");
|
|
8172
|
+
macro("person", "detection", TAXONOMY_COLORS.person, "person", "Person");
|
|
8173
|
+
macro("vehicle", "detection", TAXONOMY_COLORS.vehicle, "vehicle", "Vehicle");
|
|
8174
|
+
macro("animal", "detection", TAXONOMY_COLORS.animal, "animal", "Animal");
|
|
8175
|
+
macro("package", "package", TAXONOMY_COLORS.package, "package", "Package");
|
|
8176
|
+
macro("sensor", "sensor", TAXONOMY_COLORS.sensor, "sensor", "Sensor");
|
|
8177
|
+
macro("control", "control", TAXONOMY_COLORS.control, "control", "Control");
|
|
8178
|
+
for (const [cocoClass, macroClass] of Object.entries(COCO_TO_MACRO.mapping)) {
|
|
8179
|
+
if (macroClass !== "vehicle" && macroClass !== "animal") continue;
|
|
8180
|
+
if (entries.has(cocoClass)) continue;
|
|
8181
|
+
sub(cocoClass, macroClass, "detection", DETECTION_SUB_COLORS[cocoClass] ?? TAXONOMY_COLORS.genericDetection, cocoClass, titleCase(cocoClass));
|
|
8182
|
+
}
|
|
8183
|
+
sub("package-delivered", "package", "package", TAXONOMY_COLORS.package, "package", "Package delivered");
|
|
8184
|
+
sub("package-picked-up", "package", "package", TAXONOMY_COLORS.package, "package", "Package picked up");
|
|
8185
|
+
sub("contact", "sensor", "sensor", "#f59e0b", "door", "Contact");
|
|
8186
|
+
sub("motion-sensor", "sensor", "sensor", TAXONOMY_COLORS.sensor, "pir", "Motion sensor");
|
|
8187
|
+
sub("smoke", "sensor", "sensor", "#ef4444", "smoke", "Smoke");
|
|
8188
|
+
sub("flood", "sensor", "sensor", "#3b82f6", "water", "Water leak");
|
|
8189
|
+
sub("gas", "sensor", "sensor", "#ef4444", "gas", "Gas");
|
|
8190
|
+
sub("carbon-monoxide", "sensor", "sensor", "#dc2626", "smoke", "Carbon monoxide");
|
|
8191
|
+
sub("vibration", "sensor", "sensor", "#eab308", "vibration", "Vibration");
|
|
8192
|
+
sub("tamper", "sensor", "sensor", "#f97316", "tamper", "Tamper");
|
|
8193
|
+
sub("presence", "sensor", "sensor", "#22c55e", "presence", "Presence");
|
|
8194
|
+
sub("enum-sensor", "sensor", "sensor", TAXONOMY_COLORS.sensor, "generic", "Sensor state");
|
|
8195
|
+
sub("device-event", "sensor", "sensor", "#10b981", "button", "Device event");
|
|
8196
|
+
sub("lock", "control", "control", "#0ea5e9", "lock", "Lock");
|
|
8197
|
+
sub("switch", "control", "control", TAXONOMY_COLORS.control, "switch", "Switch");
|
|
8198
|
+
sub("siren", "control", "control", "#dc2626", "siren", "Siren");
|
|
8199
|
+
sub("button", "control", "control", "#10b981", "button", "Button");
|
|
8200
|
+
sub("doorbell", "control", "control", "#a855f7", "doorbell", "Doorbell");
|
|
8201
|
+
for (const l of AUDIO_MACRO_LABELS) {
|
|
8202
|
+
const kind = `audio-${l.id}`;
|
|
8203
|
+
if (entries.has(kind)) continue;
|
|
8204
|
+
sub(kind, "audio", "audio", TAXONOMY_COLORS.audio, kind, l.name);
|
|
8205
|
+
}
|
|
8206
|
+
/** The complete taxonomy dictionary, keyed by kind. */
|
|
8207
|
+
var EVENT_TAXONOMY = Object.freeze(Object.fromEntries(entries));
|
|
8208
|
+
/**
|
|
7880
8209
|
* Error types for the safe expression engine. Two distinct classes so callers
|
|
7881
8210
|
* can tell a compile-time (grammar) failure from a runtime (evaluation)
|
|
7882
8211
|
* failure — both are non-fatal to the host: read paths degrade to "skip link".
|
|
@@ -15894,17 +16223,30 @@ var EventKindCategorySchema = _enum([
|
|
|
15894
16223
|
"audio",
|
|
15895
16224
|
"detection",
|
|
15896
16225
|
"sensor",
|
|
16226
|
+
"control",
|
|
15897
16227
|
"custom",
|
|
15898
16228
|
"package"
|
|
15899
16229
|
]);
|
|
16230
|
+
/** Taxonomy level — macro (timeline lane) vs sub (events-page leaf). */
|
|
16231
|
+
var EventKindLevelSchema = _enum(["macro", "sub"]);
|
|
15900
16232
|
var EventKindDescriptorSchema = object({
|
|
15901
|
-
/** Stable kind id (e.g. 'motion', '
|
|
16233
|
+
/** Stable kind id (e.g. 'motion', 'vehicle', 'car', 'lock'). */
|
|
15902
16234
|
kind: string(),
|
|
16235
|
+
/** i18n key resolved on the UI side; `label` is the English fallback. */
|
|
16236
|
+
labelKey: string(),
|
|
16237
|
+
/** English fallback label (kept for clients that don't translate). */
|
|
15903
16238
|
label: string(),
|
|
15904
16239
|
/** Hex color for timeline/legend rendering. */
|
|
15905
16240
|
color: string(),
|
|
16241
|
+
/** Dictionary id → lucide component on the UI side. */
|
|
16242
|
+
iconId: string(),
|
|
16243
|
+
/** Legacy closed-vocab glyph — fallback for `iconId`. */
|
|
15906
16244
|
icon: EventKindIconSchema,
|
|
15907
16245
|
category: EventKindCategorySchema,
|
|
16246
|
+
/** Macro parent for this kind ('car' → 'vehicle'); null for a macro. */
|
|
16247
|
+
parentKind: string().nullable(),
|
|
16248
|
+
/** Derived from `parentKind`, explicit for the client tree. */
|
|
16249
|
+
level: EventKindLevelSchema,
|
|
15908
16250
|
/** Which cap + device contributes this kind. For built-ins the camera
|
|
15909
16251
|
* itself; for sensor kinds the LINKED source device. */
|
|
15910
16252
|
source: object({
|
|
@@ -15977,11 +16319,21 @@ var TrackAudioLabelSchema = object({
|
|
|
15977
16319
|
firstAt: number(),
|
|
15978
16320
|
lastAt: number()
|
|
15979
16321
|
});
|
|
16322
|
+
/**
|
|
16323
|
+
* How a track was produced. `pipeline` (default / absent) = the spatial
|
|
16324
|
+
* detection+tracking pipeline. `sensor` = a SYNTHETIC track projected from a
|
|
16325
|
+
* linked sensor/control state change (no positions; carries a snapshot). The
|
|
16326
|
+
* spatial subsystems (tracker association, occupancy count, re-id/embedding,
|
|
16327
|
+
* resurrection) MUST skip `sensor` tracks — they have no bbox trajectory.
|
|
16328
|
+
*/
|
|
16329
|
+
var TrackSourceSchema = _enum(["pipeline", "sensor"]);
|
|
15980
16330
|
var TrackSchema = object({
|
|
15981
16331
|
trackId: string(),
|
|
15982
16332
|
deviceId: number(),
|
|
15983
16333
|
className: string(),
|
|
15984
16334
|
label: string().optional(),
|
|
16335
|
+
/** Track provenance. Absent ⇒ `pipeline` (legacy rows). */
|
|
16336
|
+
source: TrackSourceSchema.optional(),
|
|
15985
16337
|
firstSeen: number(),
|
|
15986
16338
|
lastSeen: number(),
|
|
15987
16339
|
/** Frame-rate position history (subject to maxPositionHistory cap). */
|
|
@@ -16236,6 +16588,26 @@ var TrackCascadeCountsSchema = object({
|
|
|
16236
16588
|
/** Per-track CLIP search vectors removed (best-effort). */
|
|
16237
16589
|
embeddings: number().int()
|
|
16238
16590
|
});
|
|
16591
|
+
/** Event-store footprint for one camera. */
|
|
16592
|
+
var EventStoreDeviceFootprintSchema = object({
|
|
16593
|
+
deviceId: number(),
|
|
16594
|
+
/** Persisted event rows (motion + object + audio) for the camera. */
|
|
16595
|
+
rows: number().int(),
|
|
16596
|
+
/** Event-owned media bytes on disk for the camera. */
|
|
16597
|
+
bytes: number().int()
|
|
16598
|
+
});
|
|
16599
|
+
/** Aggregate event-store footprint: global totals + per-camera breakdown. */
|
|
16600
|
+
var EventStoreFootprintSchema = object({
|
|
16601
|
+
totalRows: number().int(),
|
|
16602
|
+
totalBytes: number().int(),
|
|
16603
|
+
devices: array(EventStoreDeviceFootprintSchema).readonly()
|
|
16604
|
+
});
|
|
16605
|
+
/** Per-kind counts returned by the event-prune / device-delete mutations. */
|
|
16606
|
+
var EventPruneCountsSchema = object({
|
|
16607
|
+
motion: number().int(),
|
|
16608
|
+
object: number().int(),
|
|
16609
|
+
audio: number().int()
|
|
16610
|
+
});
|
|
16239
16611
|
DeviceType.Camera, method(object({ deviceId: number() }), array(TrackSchema).readonly()), method(object({
|
|
16240
16612
|
deviceId: number(),
|
|
16241
16613
|
trackId: string()
|
|
@@ -16299,6 +16671,21 @@ DeviceType.Camera, method(object({ deviceId: number() }), array(TrackSchema).rea
|
|
|
16299
16671
|
}), {
|
|
16300
16672
|
kind: "mutation",
|
|
16301
16673
|
auth: "admin"
|
|
16674
|
+
}), method(object({}), EventStoreFootprintSchema, {
|
|
16675
|
+
kind: "query",
|
|
16676
|
+
auth: "admin"
|
|
16677
|
+
}), method(object({
|
|
16678
|
+
olderThanMs: number(),
|
|
16679
|
+
reason: OpsLogReasonSchema.optional()
|
|
16680
|
+
}), EventPruneCountsSchema, {
|
|
16681
|
+
kind: "mutation",
|
|
16682
|
+
auth: "admin"
|
|
16683
|
+
}), method(object({ deviceId: number() }), EventPruneCountsSchema, {
|
|
16684
|
+
kind: "mutation",
|
|
16685
|
+
auth: "admin"
|
|
16686
|
+
}), method(OpsLogQueryInputSchema, array(OpsLogEntrySchema).readonly(), {
|
|
16687
|
+
kind: "query",
|
|
16688
|
+
auth: "admin"
|
|
16302
16689
|
}), method(object({
|
|
16303
16690
|
eventId: string(),
|
|
16304
16691
|
kind: MediaFileKindEnum.optional()
|
|
@@ -16323,6 +16710,76 @@ DeviceType.Camera, method(object({ deviceId: number() }), array(TrackSchema).rea
|
|
|
16323
16710
|
eventId: string(),
|
|
16324
16711
|
timestamp: number()
|
|
16325
16712
|
});
|
|
16713
|
+
/**
|
|
16714
|
+
* Cap → event-kind mapping for the SENSOR / CONTROL cap families — the table
|
|
16715
|
+
* `pipeline-analytics.listEventKinds` uses to turn a linked device's bound
|
|
16716
|
+
* caps into per-camera event-kind descriptors.
|
|
16717
|
+
*
|
|
16718
|
+
* The descriptor DATA (color / iconId / labelKey / parentKind / category)
|
|
16719
|
+
* is NOT duplicated here — every entry is derived from the single
|
|
16720
|
+
* `EVENT_TAXONOMY` dictionary (`catalogs/event-taxonomy.ts`). This file owns
|
|
16721
|
+
* ONLY the cap-name → taxonomy-kind mapping. Adding a new eventful sensor /
|
|
16722
|
+
* control cap means adding one line here (and a taxonomy entry); the anti-
|
|
16723
|
+
* drift guard `scripts/check-event-kind-coverage.ts` fails the build if an
|
|
16724
|
+
* eventful cap is missing.
|
|
16725
|
+
*/
|
|
16726
|
+
/** Map a taxonomy `iconId` onto the legacy closed `EventKindIcon` enum. */
|
|
16727
|
+
var LEGACY_ICON = {
|
|
16728
|
+
motion: "motion",
|
|
16729
|
+
audio: "audio",
|
|
16730
|
+
person: "person",
|
|
16731
|
+
vehicle: "vehicle",
|
|
16732
|
+
animal: "animal",
|
|
16733
|
+
package: "package",
|
|
16734
|
+
door: "door",
|
|
16735
|
+
pir: "pir",
|
|
16736
|
+
smoke: "smoke",
|
|
16737
|
+
water: "water",
|
|
16738
|
+
button: "button",
|
|
16739
|
+
generic: "generic",
|
|
16740
|
+
gas: "smoke",
|
|
16741
|
+
vibration: "generic",
|
|
16742
|
+
tamper: "generic",
|
|
16743
|
+
presence: "person",
|
|
16744
|
+
lock: "generic",
|
|
16745
|
+
siren: "generic",
|
|
16746
|
+
switch: "generic",
|
|
16747
|
+
doorbell: "button"
|
|
16748
|
+
};
|
|
16749
|
+
function legacyIcon(iconId) {
|
|
16750
|
+
return LEGACY_ICON[iconId] ?? "generic";
|
|
16751
|
+
}
|
|
16752
|
+
/**
|
|
16753
|
+
* Cap name → taxonomy kind id. Covers EVERY eventful sensor / control cap.
|
|
16754
|
+
* The anti-drift guard cross-checks this against the eventful caps declared
|
|
16755
|
+
* in `packages/types/src/capabilities/*.cap.ts`.
|
|
16756
|
+
*/
|
|
16757
|
+
var CAP_TO_KIND = {
|
|
16758
|
+
contact: "contact",
|
|
16759
|
+
motion: "motion-sensor",
|
|
16760
|
+
smoke: "smoke",
|
|
16761
|
+
flood: "flood",
|
|
16762
|
+
gas: "gas",
|
|
16763
|
+
"carbon-monoxide": "carbon-monoxide",
|
|
16764
|
+
vibration: "vibration",
|
|
16765
|
+
tamper: "tamper",
|
|
16766
|
+
presence: "presence",
|
|
16767
|
+
"enum-sensor": "enum-sensor",
|
|
16768
|
+
"event-emitter": "device-event",
|
|
16769
|
+
"lock-control": "lock",
|
|
16770
|
+
switch: "switch",
|
|
16771
|
+
button: "button",
|
|
16772
|
+
doorbell: "doorbell"
|
|
16773
|
+
};
|
|
16774
|
+
function buildDescriptor(capName, kind) {
|
|
16775
|
+
const t = EVENT_TAXONOMY[kind];
|
|
16776
|
+
if (t === void 0) throw new Error(`EVENT_KIND_BY_CAP: cap '${capName}' maps to unknown taxonomy kind '${kind}'`);
|
|
16777
|
+
return {
|
|
16778
|
+
...t,
|
|
16779
|
+
icon: legacyIcon(t.iconId)
|
|
16780
|
+
};
|
|
16781
|
+
}
|
|
16782
|
+
Object.freeze(Object.fromEntries(Object.entries(CAP_TO_KIND).map(([capName, kind]) => [capName, buildDescriptor(capName, kind)])));
|
|
16326
16783
|
var CameraPipelineConfigSchema = object({
|
|
16327
16784
|
engine: PipelineEngineChoiceSchema.optional(),
|
|
16328
16785
|
steps: array(PipelineStepInputSchema).readonly(),
|
|
@@ -19532,13 +19989,29 @@ method(object({
|
|
|
19532
19989
|
}), method(object({ deviceId: number() }), RecordingStatusSchema, {
|
|
19533
19990
|
kind: "mutation",
|
|
19534
19991
|
auth: "admin"
|
|
19535
|
-
}), method(object({
|
|
19992
|
+
}), method(object({
|
|
19993
|
+
deviceId: number(),
|
|
19994
|
+
reason: OpsLogReasonSchema.optional()
|
|
19995
|
+
}), object({
|
|
19536
19996
|
floorMs: number().nullable(),
|
|
19537
19997
|
deletedBuckets: number().int(),
|
|
19538
19998
|
reclaimedBytes: number().int()
|
|
19539
19999
|
}), {
|
|
19540
20000
|
kind: "mutation",
|
|
19541
20001
|
auth: "admin"
|
|
20002
|
+
}), method(object({
|
|
20003
|
+
deviceId: number(),
|
|
20004
|
+
fromMs: number().optional(),
|
|
20005
|
+
toMs: number().optional()
|
|
20006
|
+
}), object({
|
|
20007
|
+
deletedBuckets: number().int(),
|
|
20008
|
+
reclaimedBytes: number().int()
|
|
20009
|
+
}), {
|
|
20010
|
+
kind: "mutation",
|
|
20011
|
+
auth: "admin"
|
|
20012
|
+
}), method(OpsLogQueryInputSchema, array(OpsLogEntrySchema).readonly(), {
|
|
20013
|
+
kind: "query",
|
|
20014
|
+
auth: "admin"
|
|
19542
20015
|
});
|
|
19543
20016
|
/**
|
|
19544
20017
|
* `recordingExport` cap — render a footage time range into a single downloadable
|
|
@@ -22660,6 +23133,12 @@ Object.freeze({
|
|
|
22660
23133
|
addonId: null,
|
|
22661
23134
|
access: "delete"
|
|
22662
23135
|
},
|
|
23136
|
+
"pipelineAnalytics.deleteDeviceEvents": {
|
|
23137
|
+
capName: "pipeline-analytics",
|
|
23138
|
+
capScope: "device",
|
|
23139
|
+
addonId: null,
|
|
23140
|
+
access: "delete"
|
|
23141
|
+
},
|
|
22663
23142
|
"pipelineAnalytics.deleteTracks": {
|
|
22664
23143
|
capName: "pipeline-analytics",
|
|
22665
23144
|
capScope: "device",
|
|
@@ -22690,6 +23169,12 @@ Object.freeze({
|
|
|
22690
23169
|
addonId: null,
|
|
22691
23170
|
access: "view"
|
|
22692
23171
|
},
|
|
23172
|
+
"pipelineAnalytics.getEventStoreFootprint": {
|
|
23173
|
+
capName: "pipeline-analytics",
|
|
23174
|
+
capScope: "device",
|
|
23175
|
+
addonId: null,
|
|
23176
|
+
access: "view"
|
|
23177
|
+
},
|
|
22693
23178
|
"pipelineAnalytics.getKeyEvents": {
|
|
22694
23179
|
capName: "pipeline-analytics",
|
|
22695
23180
|
capScope: "device",
|
|
@@ -22732,6 +23217,12 @@ Object.freeze({
|
|
|
22732
23217
|
addonId: null,
|
|
22733
23218
|
access: "view"
|
|
22734
23219
|
},
|
|
23220
|
+
"pipelineAnalytics.listOpsLog": {
|
|
23221
|
+
capName: "pipeline-analytics",
|
|
23222
|
+
capScope: "device",
|
|
23223
|
+
addonId: null,
|
|
23224
|
+
access: "view"
|
|
23225
|
+
},
|
|
22735
23226
|
"pipelineAnalytics.listRecentTracks": {
|
|
22736
23227
|
capName: "pipeline-analytics",
|
|
22737
23228
|
capScope: "device",
|
|
@@ -22744,6 +23235,12 @@ Object.freeze({
|
|
|
22744
23235
|
addonId: null,
|
|
22745
23236
|
access: "view"
|
|
22746
23237
|
},
|
|
23238
|
+
"pipelineAnalytics.pruneEvents": {
|
|
23239
|
+
capName: "pipeline-analytics",
|
|
23240
|
+
capScope: "device",
|
|
23241
|
+
addonId: null,
|
|
23242
|
+
access: "create"
|
|
23243
|
+
},
|
|
22747
23244
|
"pipelineAnalytics.pruneEventsBefore": {
|
|
22748
23245
|
capName: "pipeline-analytics",
|
|
22749
23246
|
capScope: "device",
|
|
@@ -23506,6 +24003,12 @@ Object.freeze({
|
|
|
23506
24003
|
addonId: null,
|
|
23507
24004
|
access: "create"
|
|
23508
24005
|
},
|
|
24006
|
+
"recording.deleteFootprint": {
|
|
24007
|
+
capName: "recording",
|
|
24008
|
+
capScope: "system",
|
|
24009
|
+
addonId: null,
|
|
24010
|
+
access: "delete"
|
|
24011
|
+
},
|
|
23509
24012
|
"recording.getAvailability": {
|
|
23510
24013
|
capName: "recording",
|
|
23511
24014
|
capScope: "system",
|
|
@@ -23536,6 +24039,12 @@ Object.freeze({
|
|
|
23536
24039
|
addonId: null,
|
|
23537
24040
|
access: "view"
|
|
23538
24041
|
},
|
|
24042
|
+
"recording.listOpsLog": {
|
|
24043
|
+
capName: "recording",
|
|
24044
|
+
capScope: "system",
|
|
24045
|
+
addonId: null,
|
|
24046
|
+
access: "view"
|
|
24047
|
+
},
|
|
23539
24048
|
"recording.locateSegment": {
|
|
23540
24049
|
capName: "recording",
|
|
23541
24050
|
capScope: "system",
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@camstack/addon-mqtt-broker",
|
|
3
|
-
"version": "1.1.
|
|
3
|
+
"version": "1.1.28",
|
|
4
4
|
"description": "MQTT broker registry addon for CamStack — manages external broker entries + an optional embedded aedes broker. Consumers spin up their own `mqtt.js` clients via the `mqtt-broker` cap.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"camstack",
|