@camstack/addon-decoder-ffmpeg 1.1.17 → 1.1.19
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/index.js +511 -2
- package/dist/index.mjs +511 -2
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -7345,6 +7345,62 @@ var RecordingConfigSchema = object({
|
|
|
7345
7345
|
scrubThumbnails: ScrubThumbnailPresetSchema.optional()
|
|
7346
7346
|
});
|
|
7347
7347
|
/**
|
|
7348
|
+
* Ops-log — the durable, append-only operations audit shared by the
|
|
7349
|
+
* recordings and events management surfaces.
|
|
7350
|
+
*
|
|
7351
|
+
* ONE row shape is reused for both domains so a single "Activity" view can
|
|
7352
|
+
* merge the recorder's DurableState ring (recordings ops-log) and the
|
|
7353
|
+
* pipeline-analytics SQLite collection (events ops-log). Each row records a
|
|
7354
|
+
* management operation, WHY it ran (reason), and its measurable effect
|
|
7355
|
+
* (itemsAffected + bytesReclaimed). Writes are best-effort — a failed log must
|
|
7356
|
+
* never fail the operation it records.
|
|
7357
|
+
*/
|
|
7358
|
+
/** Which management domain the operation belongs to. */
|
|
7359
|
+
var OpsLogDomainSchema = _enum(["recording", "events"]);
|
|
7360
|
+
/** The kind of management operation performed. */
|
|
7361
|
+
var OpsLogOpSchema = _enum([
|
|
7362
|
+
"prune",
|
|
7363
|
+
"manual-delete",
|
|
7364
|
+
"rescan",
|
|
7365
|
+
"retention-run"
|
|
7366
|
+
]);
|
|
7367
|
+
/** Why the operation ran. */
|
|
7368
|
+
var OpsLogReasonSchema = _enum([
|
|
7369
|
+
"retention",
|
|
7370
|
+
"quota",
|
|
7371
|
+
"manual",
|
|
7372
|
+
"operator"
|
|
7373
|
+
]);
|
|
7374
|
+
/** One audit row, shared verbatim by both domains. */
|
|
7375
|
+
var OpsLogEntrySchema = object({
|
|
7376
|
+
/** Unique row id. */
|
|
7377
|
+
id: string(),
|
|
7378
|
+
/** Epoch ms the operation completed. */
|
|
7379
|
+
at: number(),
|
|
7380
|
+
domain: OpsLogDomainSchema,
|
|
7381
|
+
op: OpsLogOpSchema,
|
|
7382
|
+
reason: OpsLogReasonSchema,
|
|
7383
|
+
/** The camera the op targeted; null for a cluster/global op. */
|
|
7384
|
+
deviceId: number().nullable(),
|
|
7385
|
+
/** Node that performed the op (the log carries nodeId — no cross-node aggregation). */
|
|
7386
|
+
nodeId: string(),
|
|
7387
|
+
/** Buckets / rows deleted (op-specific unit). */
|
|
7388
|
+
itemsAffected: number(),
|
|
7389
|
+
/** Bytes reclaimed by the op (0 when not measurable). */
|
|
7390
|
+
bytesReclaimed: number(),
|
|
7391
|
+
/** Free-text detail (e.g. "floor moved to <ts>"); null when none. */
|
|
7392
|
+
detail: string().nullable(),
|
|
7393
|
+
/** Who/what triggered the op. */
|
|
7394
|
+
actor: string()
|
|
7395
|
+
});
|
|
7396
|
+
/** Shared query input for the per-domain `listOpsLog` cap methods. */
|
|
7397
|
+
var OpsLogQueryInputSchema = object({
|
|
7398
|
+
/** Restrict to a single camera; omit for every row. */
|
|
7399
|
+
deviceId: number().optional(),
|
|
7400
|
+
/** Max rows returned, newest-first. */
|
|
7401
|
+
limit: number().int().min(1).max(1e3).optional()
|
|
7402
|
+
});
|
|
7403
|
+
/**
|
|
7348
7404
|
* `StorageLocationType` — an addon-declared id that identifies the *kind* of
|
|
7349
7405
|
* storage a location serves. Defined here (not in `capabilities/storage.cap.ts`)
|
|
7350
7406
|
* so the persisted record schema and the consumer-facing cap can both consume it
|
|
@@ -7588,6 +7644,160 @@ var EncodeProfileSchema = object({
|
|
|
7588
7644
|
*/
|
|
7589
7645
|
outputArgs: array(string()).optional()
|
|
7590
7646
|
});
|
|
7647
|
+
var COCO_TO_MACRO = {
|
|
7648
|
+
mapping: {
|
|
7649
|
+
person: "person",
|
|
7650
|
+
bicycle: "vehicle",
|
|
7651
|
+
car: "vehicle",
|
|
7652
|
+
motorcycle: "vehicle",
|
|
7653
|
+
airplane: "vehicle",
|
|
7654
|
+
bus: "vehicle",
|
|
7655
|
+
train: "vehicle",
|
|
7656
|
+
truck: "vehicle",
|
|
7657
|
+
boat: "vehicle",
|
|
7658
|
+
bird: "animal",
|
|
7659
|
+
cat: "animal",
|
|
7660
|
+
dog: "animal",
|
|
7661
|
+
horse: "animal",
|
|
7662
|
+
sheep: "animal",
|
|
7663
|
+
cow: "animal",
|
|
7664
|
+
elephant: "animal",
|
|
7665
|
+
bear: "animal",
|
|
7666
|
+
zebra: "animal",
|
|
7667
|
+
giraffe: "animal",
|
|
7668
|
+
suitcase: "package",
|
|
7669
|
+
backpack: "package",
|
|
7670
|
+
handbag: "package"
|
|
7671
|
+
},
|
|
7672
|
+
preserveOriginal: false
|
|
7673
|
+
};
|
|
7674
|
+
var AUDIO_MACRO_LABELS = [
|
|
7675
|
+
{
|
|
7676
|
+
id: "speech",
|
|
7677
|
+
name: "Speech",
|
|
7678
|
+
icon: "🗣️"
|
|
7679
|
+
},
|
|
7680
|
+
{
|
|
7681
|
+
id: "scream",
|
|
7682
|
+
name: "Scream / Shout",
|
|
7683
|
+
icon: "😱"
|
|
7684
|
+
},
|
|
7685
|
+
{
|
|
7686
|
+
id: "crying",
|
|
7687
|
+
name: "Crying / Baby",
|
|
7688
|
+
icon: "😢"
|
|
7689
|
+
},
|
|
7690
|
+
{
|
|
7691
|
+
id: "laughter",
|
|
7692
|
+
name: "Laughter",
|
|
7693
|
+
icon: "😂"
|
|
7694
|
+
},
|
|
7695
|
+
{
|
|
7696
|
+
id: "music",
|
|
7697
|
+
name: "Music",
|
|
7698
|
+
icon: "🎵"
|
|
7699
|
+
},
|
|
7700
|
+
{
|
|
7701
|
+
id: "dog",
|
|
7702
|
+
name: "Dog",
|
|
7703
|
+
icon: "🐕"
|
|
7704
|
+
},
|
|
7705
|
+
{
|
|
7706
|
+
id: "cat",
|
|
7707
|
+
name: "Cat",
|
|
7708
|
+
icon: "🐈"
|
|
7709
|
+
},
|
|
7710
|
+
{
|
|
7711
|
+
id: "bird",
|
|
7712
|
+
name: "Bird",
|
|
7713
|
+
icon: "🐦"
|
|
7714
|
+
},
|
|
7715
|
+
{
|
|
7716
|
+
id: "animal",
|
|
7717
|
+
name: "Animal (other)",
|
|
7718
|
+
icon: "🐾"
|
|
7719
|
+
},
|
|
7720
|
+
{
|
|
7721
|
+
id: "alarm",
|
|
7722
|
+
name: "Alarm / Siren",
|
|
7723
|
+
icon: "🚨"
|
|
7724
|
+
},
|
|
7725
|
+
{
|
|
7726
|
+
id: "doorbell",
|
|
7727
|
+
name: "Doorbell / Knock",
|
|
7728
|
+
icon: "🔔"
|
|
7729
|
+
},
|
|
7730
|
+
{
|
|
7731
|
+
id: "glass_breaking",
|
|
7732
|
+
name: "Glass Breaking",
|
|
7733
|
+
icon: "💥"
|
|
7734
|
+
},
|
|
7735
|
+
{
|
|
7736
|
+
id: "gunshot",
|
|
7737
|
+
name: "Gunshot / Explosion",
|
|
7738
|
+
icon: "💣"
|
|
7739
|
+
},
|
|
7740
|
+
{
|
|
7741
|
+
id: "vehicle",
|
|
7742
|
+
name: "Vehicle",
|
|
7743
|
+
icon: "🚗"
|
|
7744
|
+
},
|
|
7745
|
+
{
|
|
7746
|
+
id: "siren",
|
|
7747
|
+
name: "Emergency Siren",
|
|
7748
|
+
icon: "🚑"
|
|
7749
|
+
},
|
|
7750
|
+
{
|
|
7751
|
+
id: "fire",
|
|
7752
|
+
name: "Fire / Smoke",
|
|
7753
|
+
icon: "🔥"
|
|
7754
|
+
},
|
|
7755
|
+
{
|
|
7756
|
+
id: "water",
|
|
7757
|
+
name: "Water",
|
|
7758
|
+
icon: "💧"
|
|
7759
|
+
},
|
|
7760
|
+
{
|
|
7761
|
+
id: "wind",
|
|
7762
|
+
name: "Wind / Weather",
|
|
7763
|
+
icon: "🌬️"
|
|
7764
|
+
},
|
|
7765
|
+
{
|
|
7766
|
+
id: "door",
|
|
7767
|
+
name: "Door",
|
|
7768
|
+
icon: "🚪"
|
|
7769
|
+
},
|
|
7770
|
+
{
|
|
7771
|
+
id: "footsteps",
|
|
7772
|
+
name: "Footsteps",
|
|
7773
|
+
icon: "👣"
|
|
7774
|
+
},
|
|
7775
|
+
{
|
|
7776
|
+
id: "crowd",
|
|
7777
|
+
name: "Crowd / Chatter",
|
|
7778
|
+
icon: "👥"
|
|
7779
|
+
},
|
|
7780
|
+
{
|
|
7781
|
+
id: "telephone",
|
|
7782
|
+
name: "Telephone",
|
|
7783
|
+
icon: "📞"
|
|
7784
|
+
},
|
|
7785
|
+
{
|
|
7786
|
+
id: "engine",
|
|
7787
|
+
name: "Engine / Motor",
|
|
7788
|
+
icon: "⚙️"
|
|
7789
|
+
},
|
|
7790
|
+
{
|
|
7791
|
+
id: "tools",
|
|
7792
|
+
name: "Tools / Construction",
|
|
7793
|
+
icon: "🔨"
|
|
7794
|
+
},
|
|
7795
|
+
{
|
|
7796
|
+
id: "silence",
|
|
7797
|
+
name: "Silence",
|
|
7798
|
+
icon: "🤫"
|
|
7799
|
+
}
|
|
7800
|
+
];
|
|
7591
7801
|
var YAMNET_TO_MACRO = {
|
|
7592
7802
|
mapping: {
|
|
7593
7803
|
Speech: "speech",
|
|
@@ -7854,6 +8064,125 @@ var _macroLookup = /* @__PURE__ */ new Map();
|
|
|
7854
8064
|
for (const [k, v] of Object.entries(YAMNET_TO_MACRO.mapping)) _macroLookup.set(k.toLowerCase(), v);
|
|
7855
8065
|
for (const [k, v] of Object.entries(APPLE_SA_TO_MACRO.mapping)) _macroLookup.set(k.toLowerCase(), v);
|
|
7856
8066
|
/**
|
|
8067
|
+
* Unified event-kind taxonomy — THE single source of truth for
|
|
8068
|
+
* `kind → { parentKind, category, level, color, iconId, labelKey, label,
|
|
8069
|
+
* icon }`.
|
|
8070
|
+
*
|
|
8071
|
+
* This dictionary folds together what used to be scattered across four
|
|
8072
|
+
* copies:
|
|
8073
|
+
* - `capabilities/sensor-event-kinds.ts` (sensor cap colors)
|
|
8074
|
+
* - `addon-post-analysis/.../services/event-kinds.ts`
|
|
8075
|
+
* (MOTION/PERSON/VEHICLE… _COLOR constants)
|
|
8076
|
+
* - `ui-library/composites/detection-colors.ts` (CLASS_COLORS)
|
|
8077
|
+
* - `addon-post-analysis/shared/frame/box-drawer.ts` (DEFAULT_COLOR)
|
|
8078
|
+
* - the COCO / audio class maps (macro ↔ sub relationships)
|
|
8079
|
+
*
|
|
8080
|
+
* The DATA (serializable — color/iconId/labelKey/parentKind) lives here in
|
|
8081
|
+
* `@camstack/types`. The UI-side mapping `iconId → lucide component` and
|
|
8082
|
+
* `labelKey → t()` lives in `@camstack/ui-library`. UIs never hardcode a
|
|
8083
|
+
* color or an icon: they read this dictionary (server descriptors carry the
|
|
8084
|
+
* fields inline; the client resolves color/icon/label from `iconId`/`kind`).
|
|
8085
|
+
*
|
|
8086
|
+
* Two levels only (v1 YAGNI): macro → sub. `person` is a leaf macro.
|
|
8087
|
+
*/
|
|
8088
|
+
var TAXONOMY_COLORS = {
|
|
8089
|
+
motion: "#f59e0b",
|
|
8090
|
+
audio: "#06b6d4",
|
|
8091
|
+
person: "#22c55e",
|
|
8092
|
+
vehicle: "#3b82f6",
|
|
8093
|
+
animal: "#f97316",
|
|
8094
|
+
package: "#a855f7",
|
|
8095
|
+
sensor: "#8b5cf6",
|
|
8096
|
+
control: "#10b981",
|
|
8097
|
+
genericDetection: "#64748b"
|
|
8098
|
+
};
|
|
8099
|
+
var DETECTION_SUB_COLORS = {
|
|
8100
|
+
car: "#f59e0b",
|
|
8101
|
+
truck: "#d97706",
|
|
8102
|
+
bus: "#b45309",
|
|
8103
|
+
motorcycle: "#eab308",
|
|
8104
|
+
bicycle: "#ca8a04",
|
|
8105
|
+
airplane: "#60a5fa",
|
|
8106
|
+
boat: "#2563eb",
|
|
8107
|
+
train: "#1d4ed8",
|
|
8108
|
+
bird: "#14b8a6",
|
|
8109
|
+
dog: "#84cc16",
|
|
8110
|
+
cat: "#f97316",
|
|
8111
|
+
horse: "#a16207",
|
|
8112
|
+
sheep: "#a3a3a3",
|
|
8113
|
+
cow: "#78716c",
|
|
8114
|
+
elephant: "#6b7280",
|
|
8115
|
+
bear: "#7c2d12",
|
|
8116
|
+
zebra: "#404040",
|
|
8117
|
+
giraffe: "#d4a373"
|
|
8118
|
+
};
|
|
8119
|
+
function titleCase(id) {
|
|
8120
|
+
return id.split(/[-_ ]/).filter((p) => p.length > 0).map((p) => p.charAt(0).toUpperCase() + p.slice(1)).join(" ");
|
|
8121
|
+
}
|
|
8122
|
+
var entries = /* @__PURE__ */ new Map();
|
|
8123
|
+
function macro(kind, category, color, iconId, label) {
|
|
8124
|
+
entries.set(kind, {
|
|
8125
|
+
kind,
|
|
8126
|
+
parentKind: null,
|
|
8127
|
+
level: "macro",
|
|
8128
|
+
category,
|
|
8129
|
+
color,
|
|
8130
|
+
iconId,
|
|
8131
|
+
labelKey: `eventKind.${kind}`,
|
|
8132
|
+
label
|
|
8133
|
+
});
|
|
8134
|
+
}
|
|
8135
|
+
function sub(kind, parentKind, category, color, iconId, label) {
|
|
8136
|
+
entries.set(kind, {
|
|
8137
|
+
kind,
|
|
8138
|
+
parentKind,
|
|
8139
|
+
level: "sub",
|
|
8140
|
+
category,
|
|
8141
|
+
color,
|
|
8142
|
+
iconId,
|
|
8143
|
+
labelKey: `eventKind.${kind}`,
|
|
8144
|
+
label
|
|
8145
|
+
});
|
|
8146
|
+
}
|
|
8147
|
+
macro("motion", "motion", TAXONOMY_COLORS.motion, "motion", "Motion");
|
|
8148
|
+
macro("audio", "audio", TAXONOMY_COLORS.audio, "audio", "Audio");
|
|
8149
|
+
macro("person", "detection", TAXONOMY_COLORS.person, "person", "Person");
|
|
8150
|
+
macro("vehicle", "detection", TAXONOMY_COLORS.vehicle, "vehicle", "Vehicle");
|
|
8151
|
+
macro("animal", "detection", TAXONOMY_COLORS.animal, "animal", "Animal");
|
|
8152
|
+
macro("package", "package", TAXONOMY_COLORS.package, "package", "Package");
|
|
8153
|
+
macro("sensor", "sensor", TAXONOMY_COLORS.sensor, "sensor", "Sensor");
|
|
8154
|
+
macro("control", "control", TAXONOMY_COLORS.control, "control", "Control");
|
|
8155
|
+
for (const [cocoClass, macroClass] of Object.entries(COCO_TO_MACRO.mapping)) {
|
|
8156
|
+
if (macroClass !== "vehicle" && macroClass !== "animal") continue;
|
|
8157
|
+
if (entries.has(cocoClass)) continue;
|
|
8158
|
+
sub(cocoClass, macroClass, "detection", DETECTION_SUB_COLORS[cocoClass] ?? TAXONOMY_COLORS.genericDetection, cocoClass, titleCase(cocoClass));
|
|
8159
|
+
}
|
|
8160
|
+
sub("package-delivered", "package", "package", TAXONOMY_COLORS.package, "package", "Package delivered");
|
|
8161
|
+
sub("package-picked-up", "package", "package", TAXONOMY_COLORS.package, "package", "Package picked up");
|
|
8162
|
+
sub("contact", "sensor", "sensor", "#f59e0b", "door", "Contact");
|
|
8163
|
+
sub("motion-sensor", "sensor", "sensor", TAXONOMY_COLORS.sensor, "pir", "Motion sensor");
|
|
8164
|
+
sub("smoke", "sensor", "sensor", "#ef4444", "smoke", "Smoke");
|
|
8165
|
+
sub("flood", "sensor", "sensor", "#3b82f6", "water", "Water leak");
|
|
8166
|
+
sub("gas", "sensor", "sensor", "#ef4444", "gas", "Gas");
|
|
8167
|
+
sub("carbon-monoxide", "sensor", "sensor", "#dc2626", "smoke", "Carbon monoxide");
|
|
8168
|
+
sub("vibration", "sensor", "sensor", "#eab308", "vibration", "Vibration");
|
|
8169
|
+
sub("tamper", "sensor", "sensor", "#f97316", "tamper", "Tamper");
|
|
8170
|
+
sub("presence", "sensor", "sensor", "#22c55e", "presence", "Presence");
|
|
8171
|
+
sub("enum-sensor", "sensor", "sensor", TAXONOMY_COLORS.sensor, "generic", "Sensor state");
|
|
8172
|
+
sub("device-event", "sensor", "sensor", "#10b981", "button", "Device event");
|
|
8173
|
+
sub("lock", "control", "control", "#0ea5e9", "lock", "Lock");
|
|
8174
|
+
sub("switch", "control", "control", TAXONOMY_COLORS.control, "switch", "Switch");
|
|
8175
|
+
sub("siren", "control", "control", "#dc2626", "siren", "Siren");
|
|
8176
|
+
sub("button", "control", "control", "#10b981", "button", "Button");
|
|
8177
|
+
sub("doorbell", "control", "control", "#a855f7", "doorbell", "Doorbell");
|
|
8178
|
+
for (const l of AUDIO_MACRO_LABELS) {
|
|
8179
|
+
const kind = `audio-${l.id}`;
|
|
8180
|
+
if (entries.has(kind)) continue;
|
|
8181
|
+
sub(kind, "audio", "audio", TAXONOMY_COLORS.audio, kind, l.name);
|
|
8182
|
+
}
|
|
8183
|
+
/** The complete taxonomy dictionary, keyed by kind. */
|
|
8184
|
+
var EVENT_TAXONOMY = Object.freeze(Object.fromEntries(entries));
|
|
8185
|
+
/**
|
|
7857
8186
|
* Error types for the safe expression engine. Two distinct classes so callers
|
|
7858
8187
|
* can tell a compile-time (grammar) failure from a runtime (evaluation)
|
|
7859
8188
|
* failure — both are non-fatal to the host: read paths degrade to "skip link".
|
|
@@ -15933,17 +16262,30 @@ var EventKindCategorySchema = _enum([
|
|
|
15933
16262
|
"audio",
|
|
15934
16263
|
"detection",
|
|
15935
16264
|
"sensor",
|
|
16265
|
+
"control",
|
|
15936
16266
|
"custom",
|
|
15937
16267
|
"package"
|
|
15938
16268
|
]);
|
|
16269
|
+
/** Taxonomy level — macro (timeline lane) vs sub (events-page leaf). */
|
|
16270
|
+
var EventKindLevelSchema = _enum(["macro", "sub"]);
|
|
15939
16271
|
var EventKindDescriptorSchema = object({
|
|
15940
|
-
/** Stable kind id (e.g. 'motion', '
|
|
16272
|
+
/** Stable kind id (e.g. 'motion', 'vehicle', 'car', 'lock'). */
|
|
15941
16273
|
kind: string(),
|
|
16274
|
+
/** i18n key resolved on the UI side; `label` is the English fallback. */
|
|
16275
|
+
labelKey: string(),
|
|
16276
|
+
/** English fallback label (kept for clients that don't translate). */
|
|
15942
16277
|
label: string(),
|
|
15943
16278
|
/** Hex color for timeline/legend rendering. */
|
|
15944
16279
|
color: string(),
|
|
16280
|
+
/** Dictionary id → lucide component on the UI side. */
|
|
16281
|
+
iconId: string(),
|
|
16282
|
+
/** Legacy closed-vocab glyph — fallback for `iconId`. */
|
|
15945
16283
|
icon: EventKindIconSchema,
|
|
15946
16284
|
category: EventKindCategorySchema,
|
|
16285
|
+
/** Macro parent for this kind ('car' → 'vehicle'); null for a macro. */
|
|
16286
|
+
parentKind: string().nullable(),
|
|
16287
|
+
/** Derived from `parentKind`, explicit for the client tree. */
|
|
16288
|
+
level: EventKindLevelSchema,
|
|
15947
16289
|
/** Which cap + device contributes this kind. For built-ins the camera
|
|
15948
16290
|
* itself; for sensor kinds the LINKED source device. */
|
|
15949
16291
|
source: object({
|
|
@@ -16016,11 +16358,21 @@ var TrackAudioLabelSchema = object({
|
|
|
16016
16358
|
firstAt: number(),
|
|
16017
16359
|
lastAt: number()
|
|
16018
16360
|
});
|
|
16361
|
+
/**
|
|
16362
|
+
* How a track was produced. `pipeline` (default / absent) = the spatial
|
|
16363
|
+
* detection+tracking pipeline. `sensor` = a SYNTHETIC track projected from a
|
|
16364
|
+
* linked sensor/control state change (no positions; carries a snapshot). The
|
|
16365
|
+
* spatial subsystems (tracker association, occupancy count, re-id/embedding,
|
|
16366
|
+
* resurrection) MUST skip `sensor` tracks — they have no bbox trajectory.
|
|
16367
|
+
*/
|
|
16368
|
+
var TrackSourceSchema = _enum(["pipeline", "sensor"]);
|
|
16019
16369
|
var TrackSchema = object({
|
|
16020
16370
|
trackId: string(),
|
|
16021
16371
|
deviceId: number(),
|
|
16022
16372
|
className: string(),
|
|
16023
16373
|
label: string().optional(),
|
|
16374
|
+
/** Track provenance. Absent ⇒ `pipeline` (legacy rows). */
|
|
16375
|
+
source: TrackSourceSchema.optional(),
|
|
16024
16376
|
firstSeen: number(),
|
|
16025
16377
|
lastSeen: number(),
|
|
16026
16378
|
/** Frame-rate position history (subject to maxPositionHistory cap). */
|
|
@@ -16275,6 +16627,26 @@ var TrackCascadeCountsSchema = object({
|
|
|
16275
16627
|
/** Per-track CLIP search vectors removed (best-effort). */
|
|
16276
16628
|
embeddings: number().int()
|
|
16277
16629
|
});
|
|
16630
|
+
/** Event-store footprint for one camera. */
|
|
16631
|
+
var EventStoreDeviceFootprintSchema = object({
|
|
16632
|
+
deviceId: number(),
|
|
16633
|
+
/** Persisted event rows (motion + object + audio) for the camera. */
|
|
16634
|
+
rows: number().int(),
|
|
16635
|
+
/** Event-owned media bytes on disk for the camera. */
|
|
16636
|
+
bytes: number().int()
|
|
16637
|
+
});
|
|
16638
|
+
/** Aggregate event-store footprint: global totals + per-camera breakdown. */
|
|
16639
|
+
var EventStoreFootprintSchema = object({
|
|
16640
|
+
totalRows: number().int(),
|
|
16641
|
+
totalBytes: number().int(),
|
|
16642
|
+
devices: array(EventStoreDeviceFootprintSchema).readonly()
|
|
16643
|
+
});
|
|
16644
|
+
/** Per-kind counts returned by the event-prune / device-delete mutations. */
|
|
16645
|
+
var EventPruneCountsSchema = object({
|
|
16646
|
+
motion: number().int(),
|
|
16647
|
+
object: number().int(),
|
|
16648
|
+
audio: number().int()
|
|
16649
|
+
});
|
|
16278
16650
|
DeviceType.Camera, method(object({ deviceId: number() }), array(TrackSchema).readonly()), method(object({
|
|
16279
16651
|
deviceId: number(),
|
|
16280
16652
|
trackId: string()
|
|
@@ -16338,6 +16710,21 @@ DeviceType.Camera, method(object({ deviceId: number() }), array(TrackSchema).rea
|
|
|
16338
16710
|
}), {
|
|
16339
16711
|
kind: "mutation",
|
|
16340
16712
|
auth: "admin"
|
|
16713
|
+
}), method(object({}), EventStoreFootprintSchema, {
|
|
16714
|
+
kind: "query",
|
|
16715
|
+
auth: "admin"
|
|
16716
|
+
}), method(object({
|
|
16717
|
+
olderThanMs: number(),
|
|
16718
|
+
reason: OpsLogReasonSchema.optional()
|
|
16719
|
+
}), EventPruneCountsSchema, {
|
|
16720
|
+
kind: "mutation",
|
|
16721
|
+
auth: "admin"
|
|
16722
|
+
}), method(object({ deviceId: number() }), EventPruneCountsSchema, {
|
|
16723
|
+
kind: "mutation",
|
|
16724
|
+
auth: "admin"
|
|
16725
|
+
}), method(OpsLogQueryInputSchema, array(OpsLogEntrySchema).readonly(), {
|
|
16726
|
+
kind: "query",
|
|
16727
|
+
auth: "admin"
|
|
16341
16728
|
}), method(object({
|
|
16342
16729
|
eventId: string(),
|
|
16343
16730
|
kind: MediaFileKindEnum.optional()
|
|
@@ -16362,6 +16749,76 @@ DeviceType.Camera, method(object({ deviceId: number() }), array(TrackSchema).rea
|
|
|
16362
16749
|
eventId: string(),
|
|
16363
16750
|
timestamp: number()
|
|
16364
16751
|
});
|
|
16752
|
+
/**
|
|
16753
|
+
* Cap → event-kind mapping for the SENSOR / CONTROL cap families — the table
|
|
16754
|
+
* `pipeline-analytics.listEventKinds` uses to turn a linked device's bound
|
|
16755
|
+
* caps into per-camera event-kind descriptors.
|
|
16756
|
+
*
|
|
16757
|
+
* The descriptor DATA (color / iconId / labelKey / parentKind / category)
|
|
16758
|
+
* is NOT duplicated here — every entry is derived from the single
|
|
16759
|
+
* `EVENT_TAXONOMY` dictionary (`catalogs/event-taxonomy.ts`). This file owns
|
|
16760
|
+
* ONLY the cap-name → taxonomy-kind mapping. Adding a new eventful sensor /
|
|
16761
|
+
* control cap means adding one line here (and a taxonomy entry); the anti-
|
|
16762
|
+
* drift guard `scripts/check-event-kind-coverage.ts` fails the build if an
|
|
16763
|
+
* eventful cap is missing.
|
|
16764
|
+
*/
|
|
16765
|
+
/** Map a taxonomy `iconId` onto the legacy closed `EventKindIcon` enum. */
|
|
16766
|
+
var LEGACY_ICON = {
|
|
16767
|
+
motion: "motion",
|
|
16768
|
+
audio: "audio",
|
|
16769
|
+
person: "person",
|
|
16770
|
+
vehicle: "vehicle",
|
|
16771
|
+
animal: "animal",
|
|
16772
|
+
package: "package",
|
|
16773
|
+
door: "door",
|
|
16774
|
+
pir: "pir",
|
|
16775
|
+
smoke: "smoke",
|
|
16776
|
+
water: "water",
|
|
16777
|
+
button: "button",
|
|
16778
|
+
generic: "generic",
|
|
16779
|
+
gas: "smoke",
|
|
16780
|
+
vibration: "generic",
|
|
16781
|
+
tamper: "generic",
|
|
16782
|
+
presence: "person",
|
|
16783
|
+
lock: "generic",
|
|
16784
|
+
siren: "generic",
|
|
16785
|
+
switch: "generic",
|
|
16786
|
+
doorbell: "button"
|
|
16787
|
+
};
|
|
16788
|
+
function legacyIcon(iconId) {
|
|
16789
|
+
return LEGACY_ICON[iconId] ?? "generic";
|
|
16790
|
+
}
|
|
16791
|
+
/**
|
|
16792
|
+
* Cap name → taxonomy kind id. Covers EVERY eventful sensor / control cap.
|
|
16793
|
+
* The anti-drift guard cross-checks this against the eventful caps declared
|
|
16794
|
+
* in `packages/types/src/capabilities/*.cap.ts`.
|
|
16795
|
+
*/
|
|
16796
|
+
var CAP_TO_KIND = {
|
|
16797
|
+
contact: "contact",
|
|
16798
|
+
motion: "motion-sensor",
|
|
16799
|
+
smoke: "smoke",
|
|
16800
|
+
flood: "flood",
|
|
16801
|
+
gas: "gas",
|
|
16802
|
+
"carbon-monoxide": "carbon-monoxide",
|
|
16803
|
+
vibration: "vibration",
|
|
16804
|
+
tamper: "tamper",
|
|
16805
|
+
presence: "presence",
|
|
16806
|
+
"enum-sensor": "enum-sensor",
|
|
16807
|
+
"event-emitter": "device-event",
|
|
16808
|
+
"lock-control": "lock",
|
|
16809
|
+
switch: "switch",
|
|
16810
|
+
button: "button",
|
|
16811
|
+
doorbell: "doorbell"
|
|
16812
|
+
};
|
|
16813
|
+
function buildDescriptor(capName, kind) {
|
|
16814
|
+
const t = EVENT_TAXONOMY[kind];
|
|
16815
|
+
if (t === void 0) throw new Error(`EVENT_KIND_BY_CAP: cap '${capName}' maps to unknown taxonomy kind '${kind}'`);
|
|
16816
|
+
return {
|
|
16817
|
+
...t,
|
|
16818
|
+
icon: legacyIcon(t.iconId)
|
|
16819
|
+
};
|
|
16820
|
+
}
|
|
16821
|
+
Object.freeze(Object.fromEntries(Object.entries(CAP_TO_KIND).map(([capName, kind]) => [capName, buildDescriptor(capName, kind)])));
|
|
16365
16822
|
var CameraPipelineConfigSchema = object({
|
|
16366
16823
|
engine: PipelineEngineChoiceSchema.optional(),
|
|
16367
16824
|
steps: array(PipelineStepInputSchema).readonly(),
|
|
@@ -19571,13 +20028,29 @@ method(object({
|
|
|
19571
20028
|
}), method(object({ deviceId: number() }), RecordingStatusSchema, {
|
|
19572
20029
|
kind: "mutation",
|
|
19573
20030
|
auth: "admin"
|
|
19574
|
-
}), method(object({
|
|
20031
|
+
}), method(object({
|
|
20032
|
+
deviceId: number(),
|
|
20033
|
+
reason: OpsLogReasonSchema.optional()
|
|
20034
|
+
}), object({
|
|
19575
20035
|
floorMs: number().nullable(),
|
|
19576
20036
|
deletedBuckets: number().int(),
|
|
19577
20037
|
reclaimedBytes: number().int()
|
|
19578
20038
|
}), {
|
|
19579
20039
|
kind: "mutation",
|
|
19580
20040
|
auth: "admin"
|
|
20041
|
+
}), method(object({
|
|
20042
|
+
deviceId: number(),
|
|
20043
|
+
fromMs: number().optional(),
|
|
20044
|
+
toMs: number().optional()
|
|
20045
|
+
}), object({
|
|
20046
|
+
deletedBuckets: number().int(),
|
|
20047
|
+
reclaimedBytes: number().int()
|
|
20048
|
+
}), {
|
|
20049
|
+
kind: "mutation",
|
|
20050
|
+
auth: "admin"
|
|
20051
|
+
}), method(OpsLogQueryInputSchema, array(OpsLogEntrySchema).readonly(), {
|
|
20052
|
+
kind: "query",
|
|
20053
|
+
auth: "admin"
|
|
19581
20054
|
});
|
|
19582
20055
|
/**
|
|
19583
20056
|
* `recordingExport` cap — render a footage time range into a single downloadable
|
|
@@ -22699,6 +23172,12 @@ Object.freeze({
|
|
|
22699
23172
|
addonId: null,
|
|
22700
23173
|
access: "delete"
|
|
22701
23174
|
},
|
|
23175
|
+
"pipelineAnalytics.deleteDeviceEvents": {
|
|
23176
|
+
capName: "pipeline-analytics",
|
|
23177
|
+
capScope: "device",
|
|
23178
|
+
addonId: null,
|
|
23179
|
+
access: "delete"
|
|
23180
|
+
},
|
|
22702
23181
|
"pipelineAnalytics.deleteTracks": {
|
|
22703
23182
|
capName: "pipeline-analytics",
|
|
22704
23183
|
capScope: "device",
|
|
@@ -22729,6 +23208,12 @@ Object.freeze({
|
|
|
22729
23208
|
addonId: null,
|
|
22730
23209
|
access: "view"
|
|
22731
23210
|
},
|
|
23211
|
+
"pipelineAnalytics.getEventStoreFootprint": {
|
|
23212
|
+
capName: "pipeline-analytics",
|
|
23213
|
+
capScope: "device",
|
|
23214
|
+
addonId: null,
|
|
23215
|
+
access: "view"
|
|
23216
|
+
},
|
|
22732
23217
|
"pipelineAnalytics.getKeyEvents": {
|
|
22733
23218
|
capName: "pipeline-analytics",
|
|
22734
23219
|
capScope: "device",
|
|
@@ -22771,6 +23256,12 @@ Object.freeze({
|
|
|
22771
23256
|
addonId: null,
|
|
22772
23257
|
access: "view"
|
|
22773
23258
|
},
|
|
23259
|
+
"pipelineAnalytics.listOpsLog": {
|
|
23260
|
+
capName: "pipeline-analytics",
|
|
23261
|
+
capScope: "device",
|
|
23262
|
+
addonId: null,
|
|
23263
|
+
access: "view"
|
|
23264
|
+
},
|
|
22774
23265
|
"pipelineAnalytics.listRecentTracks": {
|
|
22775
23266
|
capName: "pipeline-analytics",
|
|
22776
23267
|
capScope: "device",
|
|
@@ -22783,6 +23274,12 @@ Object.freeze({
|
|
|
22783
23274
|
addonId: null,
|
|
22784
23275
|
access: "view"
|
|
22785
23276
|
},
|
|
23277
|
+
"pipelineAnalytics.pruneEvents": {
|
|
23278
|
+
capName: "pipeline-analytics",
|
|
23279
|
+
capScope: "device",
|
|
23280
|
+
addonId: null,
|
|
23281
|
+
access: "create"
|
|
23282
|
+
},
|
|
22786
23283
|
"pipelineAnalytics.pruneEventsBefore": {
|
|
22787
23284
|
capName: "pipeline-analytics",
|
|
22788
23285
|
capScope: "device",
|
|
@@ -23545,6 +24042,12 @@ Object.freeze({
|
|
|
23545
24042
|
addonId: null,
|
|
23546
24043
|
access: "create"
|
|
23547
24044
|
},
|
|
24045
|
+
"recording.deleteFootprint": {
|
|
24046
|
+
capName: "recording",
|
|
24047
|
+
capScope: "system",
|
|
24048
|
+
addonId: null,
|
|
24049
|
+
access: "delete"
|
|
24050
|
+
},
|
|
23548
24051
|
"recording.getAvailability": {
|
|
23549
24052
|
capName: "recording",
|
|
23550
24053
|
capScope: "system",
|
|
@@ -23575,6 +24078,12 @@ Object.freeze({
|
|
|
23575
24078
|
addonId: null,
|
|
23576
24079
|
access: "view"
|
|
23577
24080
|
},
|
|
24081
|
+
"recording.listOpsLog": {
|
|
24082
|
+
capName: "recording",
|
|
24083
|
+
capScope: "system",
|
|
24084
|
+
addonId: null,
|
|
24085
|
+
access: "view"
|
|
24086
|
+
},
|
|
23578
24087
|
"recording.locateSegment": {
|
|
23579
24088
|
capName: "recording",
|
|
23580
24089
|
capScope: "system",
|
package/dist/index.mjs
CHANGED
|
@@ -7341,6 +7341,62 @@ var RecordingConfigSchema = object({
|
|
|
7341
7341
|
scrubThumbnails: ScrubThumbnailPresetSchema.optional()
|
|
7342
7342
|
});
|
|
7343
7343
|
/**
|
|
7344
|
+
* Ops-log — the durable, append-only operations audit shared by the
|
|
7345
|
+
* recordings and events management surfaces.
|
|
7346
|
+
*
|
|
7347
|
+
* ONE row shape is reused for both domains so a single "Activity" view can
|
|
7348
|
+
* merge the recorder's DurableState ring (recordings ops-log) and the
|
|
7349
|
+
* pipeline-analytics SQLite collection (events ops-log). Each row records a
|
|
7350
|
+
* management operation, WHY it ran (reason), and its measurable effect
|
|
7351
|
+
* (itemsAffected + bytesReclaimed). Writes are best-effort — a failed log must
|
|
7352
|
+
* never fail the operation it records.
|
|
7353
|
+
*/
|
|
7354
|
+
/** Which management domain the operation belongs to. */
|
|
7355
|
+
var OpsLogDomainSchema = _enum(["recording", "events"]);
|
|
7356
|
+
/** The kind of management operation performed. */
|
|
7357
|
+
var OpsLogOpSchema = _enum([
|
|
7358
|
+
"prune",
|
|
7359
|
+
"manual-delete",
|
|
7360
|
+
"rescan",
|
|
7361
|
+
"retention-run"
|
|
7362
|
+
]);
|
|
7363
|
+
/** Why the operation ran. */
|
|
7364
|
+
var OpsLogReasonSchema = _enum([
|
|
7365
|
+
"retention",
|
|
7366
|
+
"quota",
|
|
7367
|
+
"manual",
|
|
7368
|
+
"operator"
|
|
7369
|
+
]);
|
|
7370
|
+
/** One audit row, shared verbatim by both domains. */
|
|
7371
|
+
var OpsLogEntrySchema = object({
|
|
7372
|
+
/** Unique row id. */
|
|
7373
|
+
id: string(),
|
|
7374
|
+
/** Epoch ms the operation completed. */
|
|
7375
|
+
at: number(),
|
|
7376
|
+
domain: OpsLogDomainSchema,
|
|
7377
|
+
op: OpsLogOpSchema,
|
|
7378
|
+
reason: OpsLogReasonSchema,
|
|
7379
|
+
/** The camera the op targeted; null for a cluster/global op. */
|
|
7380
|
+
deviceId: number().nullable(),
|
|
7381
|
+
/** Node that performed the op (the log carries nodeId — no cross-node aggregation). */
|
|
7382
|
+
nodeId: string(),
|
|
7383
|
+
/** Buckets / rows deleted (op-specific unit). */
|
|
7384
|
+
itemsAffected: number(),
|
|
7385
|
+
/** Bytes reclaimed by the op (0 when not measurable). */
|
|
7386
|
+
bytesReclaimed: number(),
|
|
7387
|
+
/** Free-text detail (e.g. "floor moved to <ts>"); null when none. */
|
|
7388
|
+
detail: string().nullable(),
|
|
7389
|
+
/** Who/what triggered the op. */
|
|
7390
|
+
actor: string()
|
|
7391
|
+
});
|
|
7392
|
+
/** Shared query input for the per-domain `listOpsLog` cap methods. */
|
|
7393
|
+
var OpsLogQueryInputSchema = object({
|
|
7394
|
+
/** Restrict to a single camera; omit for every row. */
|
|
7395
|
+
deviceId: number().optional(),
|
|
7396
|
+
/** Max rows returned, newest-first. */
|
|
7397
|
+
limit: number().int().min(1).max(1e3).optional()
|
|
7398
|
+
});
|
|
7399
|
+
/**
|
|
7344
7400
|
* `StorageLocationType` — an addon-declared id that identifies the *kind* of
|
|
7345
7401
|
* storage a location serves. Defined here (not in `capabilities/storage.cap.ts`)
|
|
7346
7402
|
* so the persisted record schema and the consumer-facing cap can both consume it
|
|
@@ -7584,6 +7640,160 @@ var EncodeProfileSchema = object({
|
|
|
7584
7640
|
*/
|
|
7585
7641
|
outputArgs: array(string()).optional()
|
|
7586
7642
|
});
|
|
7643
|
+
var COCO_TO_MACRO = {
|
|
7644
|
+
mapping: {
|
|
7645
|
+
person: "person",
|
|
7646
|
+
bicycle: "vehicle",
|
|
7647
|
+
car: "vehicle",
|
|
7648
|
+
motorcycle: "vehicle",
|
|
7649
|
+
airplane: "vehicle",
|
|
7650
|
+
bus: "vehicle",
|
|
7651
|
+
train: "vehicle",
|
|
7652
|
+
truck: "vehicle",
|
|
7653
|
+
boat: "vehicle",
|
|
7654
|
+
bird: "animal",
|
|
7655
|
+
cat: "animal",
|
|
7656
|
+
dog: "animal",
|
|
7657
|
+
horse: "animal",
|
|
7658
|
+
sheep: "animal",
|
|
7659
|
+
cow: "animal",
|
|
7660
|
+
elephant: "animal",
|
|
7661
|
+
bear: "animal",
|
|
7662
|
+
zebra: "animal",
|
|
7663
|
+
giraffe: "animal",
|
|
7664
|
+
suitcase: "package",
|
|
7665
|
+
backpack: "package",
|
|
7666
|
+
handbag: "package"
|
|
7667
|
+
},
|
|
7668
|
+
preserveOriginal: false
|
|
7669
|
+
};
|
|
7670
|
+
var AUDIO_MACRO_LABELS = [
|
|
7671
|
+
{
|
|
7672
|
+
id: "speech",
|
|
7673
|
+
name: "Speech",
|
|
7674
|
+
icon: "🗣️"
|
|
7675
|
+
},
|
|
7676
|
+
{
|
|
7677
|
+
id: "scream",
|
|
7678
|
+
name: "Scream / Shout",
|
|
7679
|
+
icon: "😱"
|
|
7680
|
+
},
|
|
7681
|
+
{
|
|
7682
|
+
id: "crying",
|
|
7683
|
+
name: "Crying / Baby",
|
|
7684
|
+
icon: "😢"
|
|
7685
|
+
},
|
|
7686
|
+
{
|
|
7687
|
+
id: "laughter",
|
|
7688
|
+
name: "Laughter",
|
|
7689
|
+
icon: "😂"
|
|
7690
|
+
},
|
|
7691
|
+
{
|
|
7692
|
+
id: "music",
|
|
7693
|
+
name: "Music",
|
|
7694
|
+
icon: "🎵"
|
|
7695
|
+
},
|
|
7696
|
+
{
|
|
7697
|
+
id: "dog",
|
|
7698
|
+
name: "Dog",
|
|
7699
|
+
icon: "🐕"
|
|
7700
|
+
},
|
|
7701
|
+
{
|
|
7702
|
+
id: "cat",
|
|
7703
|
+
name: "Cat",
|
|
7704
|
+
icon: "🐈"
|
|
7705
|
+
},
|
|
7706
|
+
{
|
|
7707
|
+
id: "bird",
|
|
7708
|
+
name: "Bird",
|
|
7709
|
+
icon: "🐦"
|
|
7710
|
+
},
|
|
7711
|
+
{
|
|
7712
|
+
id: "animal",
|
|
7713
|
+
name: "Animal (other)",
|
|
7714
|
+
icon: "🐾"
|
|
7715
|
+
},
|
|
7716
|
+
{
|
|
7717
|
+
id: "alarm",
|
|
7718
|
+
name: "Alarm / Siren",
|
|
7719
|
+
icon: "🚨"
|
|
7720
|
+
},
|
|
7721
|
+
{
|
|
7722
|
+
id: "doorbell",
|
|
7723
|
+
name: "Doorbell / Knock",
|
|
7724
|
+
icon: "🔔"
|
|
7725
|
+
},
|
|
7726
|
+
{
|
|
7727
|
+
id: "glass_breaking",
|
|
7728
|
+
name: "Glass Breaking",
|
|
7729
|
+
icon: "💥"
|
|
7730
|
+
},
|
|
7731
|
+
{
|
|
7732
|
+
id: "gunshot",
|
|
7733
|
+
name: "Gunshot / Explosion",
|
|
7734
|
+
icon: "💣"
|
|
7735
|
+
},
|
|
7736
|
+
{
|
|
7737
|
+
id: "vehicle",
|
|
7738
|
+
name: "Vehicle",
|
|
7739
|
+
icon: "🚗"
|
|
7740
|
+
},
|
|
7741
|
+
{
|
|
7742
|
+
id: "siren",
|
|
7743
|
+
name: "Emergency Siren",
|
|
7744
|
+
icon: "🚑"
|
|
7745
|
+
},
|
|
7746
|
+
{
|
|
7747
|
+
id: "fire",
|
|
7748
|
+
name: "Fire / Smoke",
|
|
7749
|
+
icon: "🔥"
|
|
7750
|
+
},
|
|
7751
|
+
{
|
|
7752
|
+
id: "water",
|
|
7753
|
+
name: "Water",
|
|
7754
|
+
icon: "💧"
|
|
7755
|
+
},
|
|
7756
|
+
{
|
|
7757
|
+
id: "wind",
|
|
7758
|
+
name: "Wind / Weather",
|
|
7759
|
+
icon: "🌬️"
|
|
7760
|
+
},
|
|
7761
|
+
{
|
|
7762
|
+
id: "door",
|
|
7763
|
+
name: "Door",
|
|
7764
|
+
icon: "🚪"
|
|
7765
|
+
},
|
|
7766
|
+
{
|
|
7767
|
+
id: "footsteps",
|
|
7768
|
+
name: "Footsteps",
|
|
7769
|
+
icon: "👣"
|
|
7770
|
+
},
|
|
7771
|
+
{
|
|
7772
|
+
id: "crowd",
|
|
7773
|
+
name: "Crowd / Chatter",
|
|
7774
|
+
icon: "👥"
|
|
7775
|
+
},
|
|
7776
|
+
{
|
|
7777
|
+
id: "telephone",
|
|
7778
|
+
name: "Telephone",
|
|
7779
|
+
icon: "📞"
|
|
7780
|
+
},
|
|
7781
|
+
{
|
|
7782
|
+
id: "engine",
|
|
7783
|
+
name: "Engine / Motor",
|
|
7784
|
+
icon: "⚙️"
|
|
7785
|
+
},
|
|
7786
|
+
{
|
|
7787
|
+
id: "tools",
|
|
7788
|
+
name: "Tools / Construction",
|
|
7789
|
+
icon: "🔨"
|
|
7790
|
+
},
|
|
7791
|
+
{
|
|
7792
|
+
id: "silence",
|
|
7793
|
+
name: "Silence",
|
|
7794
|
+
icon: "🤫"
|
|
7795
|
+
}
|
|
7796
|
+
];
|
|
7587
7797
|
var YAMNET_TO_MACRO = {
|
|
7588
7798
|
mapping: {
|
|
7589
7799
|
Speech: "speech",
|
|
@@ -7850,6 +8060,125 @@ var _macroLookup = /* @__PURE__ */ new Map();
|
|
|
7850
8060
|
for (const [k, v] of Object.entries(YAMNET_TO_MACRO.mapping)) _macroLookup.set(k.toLowerCase(), v);
|
|
7851
8061
|
for (const [k, v] of Object.entries(APPLE_SA_TO_MACRO.mapping)) _macroLookup.set(k.toLowerCase(), v);
|
|
7852
8062
|
/**
|
|
8063
|
+
* Unified event-kind taxonomy — THE single source of truth for
|
|
8064
|
+
* `kind → { parentKind, category, level, color, iconId, labelKey, label,
|
|
8065
|
+
* icon }`.
|
|
8066
|
+
*
|
|
8067
|
+
* This dictionary folds together what used to be scattered across four
|
|
8068
|
+
* copies:
|
|
8069
|
+
* - `capabilities/sensor-event-kinds.ts` (sensor cap colors)
|
|
8070
|
+
* - `addon-post-analysis/.../services/event-kinds.ts`
|
|
8071
|
+
* (MOTION/PERSON/VEHICLE… _COLOR constants)
|
|
8072
|
+
* - `ui-library/composites/detection-colors.ts` (CLASS_COLORS)
|
|
8073
|
+
* - `addon-post-analysis/shared/frame/box-drawer.ts` (DEFAULT_COLOR)
|
|
8074
|
+
* - the COCO / audio class maps (macro ↔ sub relationships)
|
|
8075
|
+
*
|
|
8076
|
+
* The DATA (serializable — color/iconId/labelKey/parentKind) lives here in
|
|
8077
|
+
* `@camstack/types`. The UI-side mapping `iconId → lucide component` and
|
|
8078
|
+
* `labelKey → t()` lives in `@camstack/ui-library`. UIs never hardcode a
|
|
8079
|
+
* color or an icon: they read this dictionary (server descriptors carry the
|
|
8080
|
+
* fields inline; the client resolves color/icon/label from `iconId`/`kind`).
|
|
8081
|
+
*
|
|
8082
|
+
* Two levels only (v1 YAGNI): macro → sub. `person` is a leaf macro.
|
|
8083
|
+
*/
|
|
8084
|
+
var TAXONOMY_COLORS = {
|
|
8085
|
+
motion: "#f59e0b",
|
|
8086
|
+
audio: "#06b6d4",
|
|
8087
|
+
person: "#22c55e",
|
|
8088
|
+
vehicle: "#3b82f6",
|
|
8089
|
+
animal: "#f97316",
|
|
8090
|
+
package: "#a855f7",
|
|
8091
|
+
sensor: "#8b5cf6",
|
|
8092
|
+
control: "#10b981",
|
|
8093
|
+
genericDetection: "#64748b"
|
|
8094
|
+
};
|
|
8095
|
+
var DETECTION_SUB_COLORS = {
|
|
8096
|
+
car: "#f59e0b",
|
|
8097
|
+
truck: "#d97706",
|
|
8098
|
+
bus: "#b45309",
|
|
8099
|
+
motorcycle: "#eab308",
|
|
8100
|
+
bicycle: "#ca8a04",
|
|
8101
|
+
airplane: "#60a5fa",
|
|
8102
|
+
boat: "#2563eb",
|
|
8103
|
+
train: "#1d4ed8",
|
|
8104
|
+
bird: "#14b8a6",
|
|
8105
|
+
dog: "#84cc16",
|
|
8106
|
+
cat: "#f97316",
|
|
8107
|
+
horse: "#a16207",
|
|
8108
|
+
sheep: "#a3a3a3",
|
|
8109
|
+
cow: "#78716c",
|
|
8110
|
+
elephant: "#6b7280",
|
|
8111
|
+
bear: "#7c2d12",
|
|
8112
|
+
zebra: "#404040",
|
|
8113
|
+
giraffe: "#d4a373"
|
|
8114
|
+
};
|
|
8115
|
+
function titleCase(id) {
|
|
8116
|
+
return id.split(/[-_ ]/).filter((p) => p.length > 0).map((p) => p.charAt(0).toUpperCase() + p.slice(1)).join(" ");
|
|
8117
|
+
}
|
|
8118
|
+
var entries = /* @__PURE__ */ new Map();
|
|
8119
|
+
function macro(kind, category, color, iconId, label) {
|
|
8120
|
+
entries.set(kind, {
|
|
8121
|
+
kind,
|
|
8122
|
+
parentKind: null,
|
|
8123
|
+
level: "macro",
|
|
8124
|
+
category,
|
|
8125
|
+
color,
|
|
8126
|
+
iconId,
|
|
8127
|
+
labelKey: `eventKind.${kind}`,
|
|
8128
|
+
label
|
|
8129
|
+
});
|
|
8130
|
+
}
|
|
8131
|
+
function sub(kind, parentKind, category, color, iconId, label) {
|
|
8132
|
+
entries.set(kind, {
|
|
8133
|
+
kind,
|
|
8134
|
+
parentKind,
|
|
8135
|
+
level: "sub",
|
|
8136
|
+
category,
|
|
8137
|
+
color,
|
|
8138
|
+
iconId,
|
|
8139
|
+
labelKey: `eventKind.${kind}`,
|
|
8140
|
+
label
|
|
8141
|
+
});
|
|
8142
|
+
}
|
|
8143
|
+
macro("motion", "motion", TAXONOMY_COLORS.motion, "motion", "Motion");
|
|
8144
|
+
macro("audio", "audio", TAXONOMY_COLORS.audio, "audio", "Audio");
|
|
8145
|
+
macro("person", "detection", TAXONOMY_COLORS.person, "person", "Person");
|
|
8146
|
+
macro("vehicle", "detection", TAXONOMY_COLORS.vehicle, "vehicle", "Vehicle");
|
|
8147
|
+
macro("animal", "detection", TAXONOMY_COLORS.animal, "animal", "Animal");
|
|
8148
|
+
macro("package", "package", TAXONOMY_COLORS.package, "package", "Package");
|
|
8149
|
+
macro("sensor", "sensor", TAXONOMY_COLORS.sensor, "sensor", "Sensor");
|
|
8150
|
+
macro("control", "control", TAXONOMY_COLORS.control, "control", "Control");
|
|
8151
|
+
for (const [cocoClass, macroClass] of Object.entries(COCO_TO_MACRO.mapping)) {
|
|
8152
|
+
if (macroClass !== "vehicle" && macroClass !== "animal") continue;
|
|
8153
|
+
if (entries.has(cocoClass)) continue;
|
|
8154
|
+
sub(cocoClass, macroClass, "detection", DETECTION_SUB_COLORS[cocoClass] ?? TAXONOMY_COLORS.genericDetection, cocoClass, titleCase(cocoClass));
|
|
8155
|
+
}
|
|
8156
|
+
sub("package-delivered", "package", "package", TAXONOMY_COLORS.package, "package", "Package delivered");
|
|
8157
|
+
sub("package-picked-up", "package", "package", TAXONOMY_COLORS.package, "package", "Package picked up");
|
|
8158
|
+
sub("contact", "sensor", "sensor", "#f59e0b", "door", "Contact");
|
|
8159
|
+
sub("motion-sensor", "sensor", "sensor", TAXONOMY_COLORS.sensor, "pir", "Motion sensor");
|
|
8160
|
+
sub("smoke", "sensor", "sensor", "#ef4444", "smoke", "Smoke");
|
|
8161
|
+
sub("flood", "sensor", "sensor", "#3b82f6", "water", "Water leak");
|
|
8162
|
+
sub("gas", "sensor", "sensor", "#ef4444", "gas", "Gas");
|
|
8163
|
+
sub("carbon-monoxide", "sensor", "sensor", "#dc2626", "smoke", "Carbon monoxide");
|
|
8164
|
+
sub("vibration", "sensor", "sensor", "#eab308", "vibration", "Vibration");
|
|
8165
|
+
sub("tamper", "sensor", "sensor", "#f97316", "tamper", "Tamper");
|
|
8166
|
+
sub("presence", "sensor", "sensor", "#22c55e", "presence", "Presence");
|
|
8167
|
+
sub("enum-sensor", "sensor", "sensor", TAXONOMY_COLORS.sensor, "generic", "Sensor state");
|
|
8168
|
+
sub("device-event", "sensor", "sensor", "#10b981", "button", "Device event");
|
|
8169
|
+
sub("lock", "control", "control", "#0ea5e9", "lock", "Lock");
|
|
8170
|
+
sub("switch", "control", "control", TAXONOMY_COLORS.control, "switch", "Switch");
|
|
8171
|
+
sub("siren", "control", "control", "#dc2626", "siren", "Siren");
|
|
8172
|
+
sub("button", "control", "control", "#10b981", "button", "Button");
|
|
8173
|
+
sub("doorbell", "control", "control", "#a855f7", "doorbell", "Doorbell");
|
|
8174
|
+
for (const l of AUDIO_MACRO_LABELS) {
|
|
8175
|
+
const kind = `audio-${l.id}`;
|
|
8176
|
+
if (entries.has(kind)) continue;
|
|
8177
|
+
sub(kind, "audio", "audio", TAXONOMY_COLORS.audio, kind, l.name);
|
|
8178
|
+
}
|
|
8179
|
+
/** The complete taxonomy dictionary, keyed by kind. */
|
|
8180
|
+
var EVENT_TAXONOMY = Object.freeze(Object.fromEntries(entries));
|
|
8181
|
+
/**
|
|
7853
8182
|
* Error types for the safe expression engine. Two distinct classes so callers
|
|
7854
8183
|
* can tell a compile-time (grammar) failure from a runtime (evaluation)
|
|
7855
8184
|
* failure — both are non-fatal to the host: read paths degrade to "skip link".
|
|
@@ -15929,17 +16258,30 @@ var EventKindCategorySchema = _enum([
|
|
|
15929
16258
|
"audio",
|
|
15930
16259
|
"detection",
|
|
15931
16260
|
"sensor",
|
|
16261
|
+
"control",
|
|
15932
16262
|
"custom",
|
|
15933
16263
|
"package"
|
|
15934
16264
|
]);
|
|
16265
|
+
/** Taxonomy level — macro (timeline lane) vs sub (events-page leaf). */
|
|
16266
|
+
var EventKindLevelSchema = _enum(["macro", "sub"]);
|
|
15935
16267
|
var EventKindDescriptorSchema = object({
|
|
15936
|
-
/** Stable kind id (e.g. 'motion', '
|
|
16268
|
+
/** Stable kind id (e.g. 'motion', 'vehicle', 'car', 'lock'). */
|
|
15937
16269
|
kind: string(),
|
|
16270
|
+
/** i18n key resolved on the UI side; `label` is the English fallback. */
|
|
16271
|
+
labelKey: string(),
|
|
16272
|
+
/** English fallback label (kept for clients that don't translate). */
|
|
15938
16273
|
label: string(),
|
|
15939
16274
|
/** Hex color for timeline/legend rendering. */
|
|
15940
16275
|
color: string(),
|
|
16276
|
+
/** Dictionary id → lucide component on the UI side. */
|
|
16277
|
+
iconId: string(),
|
|
16278
|
+
/** Legacy closed-vocab glyph — fallback for `iconId`. */
|
|
15941
16279
|
icon: EventKindIconSchema,
|
|
15942
16280
|
category: EventKindCategorySchema,
|
|
16281
|
+
/** Macro parent for this kind ('car' → 'vehicle'); null for a macro. */
|
|
16282
|
+
parentKind: string().nullable(),
|
|
16283
|
+
/** Derived from `parentKind`, explicit for the client tree. */
|
|
16284
|
+
level: EventKindLevelSchema,
|
|
15943
16285
|
/** Which cap + device contributes this kind. For built-ins the camera
|
|
15944
16286
|
* itself; for sensor kinds the LINKED source device. */
|
|
15945
16287
|
source: object({
|
|
@@ -16012,11 +16354,21 @@ var TrackAudioLabelSchema = object({
|
|
|
16012
16354
|
firstAt: number(),
|
|
16013
16355
|
lastAt: number()
|
|
16014
16356
|
});
|
|
16357
|
+
/**
|
|
16358
|
+
* How a track was produced. `pipeline` (default / absent) = the spatial
|
|
16359
|
+
* detection+tracking pipeline. `sensor` = a SYNTHETIC track projected from a
|
|
16360
|
+
* linked sensor/control state change (no positions; carries a snapshot). The
|
|
16361
|
+
* spatial subsystems (tracker association, occupancy count, re-id/embedding,
|
|
16362
|
+
* resurrection) MUST skip `sensor` tracks — they have no bbox trajectory.
|
|
16363
|
+
*/
|
|
16364
|
+
var TrackSourceSchema = _enum(["pipeline", "sensor"]);
|
|
16015
16365
|
var TrackSchema = object({
|
|
16016
16366
|
trackId: string(),
|
|
16017
16367
|
deviceId: number(),
|
|
16018
16368
|
className: string(),
|
|
16019
16369
|
label: string().optional(),
|
|
16370
|
+
/** Track provenance. Absent ⇒ `pipeline` (legacy rows). */
|
|
16371
|
+
source: TrackSourceSchema.optional(),
|
|
16020
16372
|
firstSeen: number(),
|
|
16021
16373
|
lastSeen: number(),
|
|
16022
16374
|
/** Frame-rate position history (subject to maxPositionHistory cap). */
|
|
@@ -16271,6 +16623,26 @@ var TrackCascadeCountsSchema = object({
|
|
|
16271
16623
|
/** Per-track CLIP search vectors removed (best-effort). */
|
|
16272
16624
|
embeddings: number().int()
|
|
16273
16625
|
});
|
|
16626
|
+
/** Event-store footprint for one camera. */
|
|
16627
|
+
var EventStoreDeviceFootprintSchema = object({
|
|
16628
|
+
deviceId: number(),
|
|
16629
|
+
/** Persisted event rows (motion + object + audio) for the camera. */
|
|
16630
|
+
rows: number().int(),
|
|
16631
|
+
/** Event-owned media bytes on disk for the camera. */
|
|
16632
|
+
bytes: number().int()
|
|
16633
|
+
});
|
|
16634
|
+
/** Aggregate event-store footprint: global totals + per-camera breakdown. */
|
|
16635
|
+
var EventStoreFootprintSchema = object({
|
|
16636
|
+
totalRows: number().int(),
|
|
16637
|
+
totalBytes: number().int(),
|
|
16638
|
+
devices: array(EventStoreDeviceFootprintSchema).readonly()
|
|
16639
|
+
});
|
|
16640
|
+
/** Per-kind counts returned by the event-prune / device-delete mutations. */
|
|
16641
|
+
var EventPruneCountsSchema = object({
|
|
16642
|
+
motion: number().int(),
|
|
16643
|
+
object: number().int(),
|
|
16644
|
+
audio: number().int()
|
|
16645
|
+
});
|
|
16274
16646
|
DeviceType.Camera, method(object({ deviceId: number() }), array(TrackSchema).readonly()), method(object({
|
|
16275
16647
|
deviceId: number(),
|
|
16276
16648
|
trackId: string()
|
|
@@ -16334,6 +16706,21 @@ DeviceType.Camera, method(object({ deviceId: number() }), array(TrackSchema).rea
|
|
|
16334
16706
|
}), {
|
|
16335
16707
|
kind: "mutation",
|
|
16336
16708
|
auth: "admin"
|
|
16709
|
+
}), method(object({}), EventStoreFootprintSchema, {
|
|
16710
|
+
kind: "query",
|
|
16711
|
+
auth: "admin"
|
|
16712
|
+
}), method(object({
|
|
16713
|
+
olderThanMs: number(),
|
|
16714
|
+
reason: OpsLogReasonSchema.optional()
|
|
16715
|
+
}), EventPruneCountsSchema, {
|
|
16716
|
+
kind: "mutation",
|
|
16717
|
+
auth: "admin"
|
|
16718
|
+
}), method(object({ deviceId: number() }), EventPruneCountsSchema, {
|
|
16719
|
+
kind: "mutation",
|
|
16720
|
+
auth: "admin"
|
|
16721
|
+
}), method(OpsLogQueryInputSchema, array(OpsLogEntrySchema).readonly(), {
|
|
16722
|
+
kind: "query",
|
|
16723
|
+
auth: "admin"
|
|
16337
16724
|
}), method(object({
|
|
16338
16725
|
eventId: string(),
|
|
16339
16726
|
kind: MediaFileKindEnum.optional()
|
|
@@ -16358,6 +16745,76 @@ DeviceType.Camera, method(object({ deviceId: number() }), array(TrackSchema).rea
|
|
|
16358
16745
|
eventId: string(),
|
|
16359
16746
|
timestamp: number()
|
|
16360
16747
|
});
|
|
16748
|
+
/**
|
|
16749
|
+
* Cap → event-kind mapping for the SENSOR / CONTROL cap families — the table
|
|
16750
|
+
* `pipeline-analytics.listEventKinds` uses to turn a linked device's bound
|
|
16751
|
+
* caps into per-camera event-kind descriptors.
|
|
16752
|
+
*
|
|
16753
|
+
* The descriptor DATA (color / iconId / labelKey / parentKind / category)
|
|
16754
|
+
* is NOT duplicated here — every entry is derived from the single
|
|
16755
|
+
* `EVENT_TAXONOMY` dictionary (`catalogs/event-taxonomy.ts`). This file owns
|
|
16756
|
+
* ONLY the cap-name → taxonomy-kind mapping. Adding a new eventful sensor /
|
|
16757
|
+
* control cap means adding one line here (and a taxonomy entry); the anti-
|
|
16758
|
+
* drift guard `scripts/check-event-kind-coverage.ts` fails the build if an
|
|
16759
|
+
* eventful cap is missing.
|
|
16760
|
+
*/
|
|
16761
|
+
/** Map a taxonomy `iconId` onto the legacy closed `EventKindIcon` enum. */
|
|
16762
|
+
var LEGACY_ICON = {
|
|
16763
|
+
motion: "motion",
|
|
16764
|
+
audio: "audio",
|
|
16765
|
+
person: "person",
|
|
16766
|
+
vehicle: "vehicle",
|
|
16767
|
+
animal: "animal",
|
|
16768
|
+
package: "package",
|
|
16769
|
+
door: "door",
|
|
16770
|
+
pir: "pir",
|
|
16771
|
+
smoke: "smoke",
|
|
16772
|
+
water: "water",
|
|
16773
|
+
button: "button",
|
|
16774
|
+
generic: "generic",
|
|
16775
|
+
gas: "smoke",
|
|
16776
|
+
vibration: "generic",
|
|
16777
|
+
tamper: "generic",
|
|
16778
|
+
presence: "person",
|
|
16779
|
+
lock: "generic",
|
|
16780
|
+
siren: "generic",
|
|
16781
|
+
switch: "generic",
|
|
16782
|
+
doorbell: "button"
|
|
16783
|
+
};
|
|
16784
|
+
function legacyIcon(iconId) {
|
|
16785
|
+
return LEGACY_ICON[iconId] ?? "generic";
|
|
16786
|
+
}
|
|
16787
|
+
/**
|
|
16788
|
+
* Cap name → taxonomy kind id. Covers EVERY eventful sensor / control cap.
|
|
16789
|
+
* The anti-drift guard cross-checks this against the eventful caps declared
|
|
16790
|
+
* in `packages/types/src/capabilities/*.cap.ts`.
|
|
16791
|
+
*/
|
|
16792
|
+
var CAP_TO_KIND = {
|
|
16793
|
+
contact: "contact",
|
|
16794
|
+
motion: "motion-sensor",
|
|
16795
|
+
smoke: "smoke",
|
|
16796
|
+
flood: "flood",
|
|
16797
|
+
gas: "gas",
|
|
16798
|
+
"carbon-monoxide": "carbon-monoxide",
|
|
16799
|
+
vibration: "vibration",
|
|
16800
|
+
tamper: "tamper",
|
|
16801
|
+
presence: "presence",
|
|
16802
|
+
"enum-sensor": "enum-sensor",
|
|
16803
|
+
"event-emitter": "device-event",
|
|
16804
|
+
"lock-control": "lock",
|
|
16805
|
+
switch: "switch",
|
|
16806
|
+
button: "button",
|
|
16807
|
+
doorbell: "doorbell"
|
|
16808
|
+
};
|
|
16809
|
+
function buildDescriptor(capName, kind) {
|
|
16810
|
+
const t = EVENT_TAXONOMY[kind];
|
|
16811
|
+
if (t === void 0) throw new Error(`EVENT_KIND_BY_CAP: cap '${capName}' maps to unknown taxonomy kind '${kind}'`);
|
|
16812
|
+
return {
|
|
16813
|
+
...t,
|
|
16814
|
+
icon: legacyIcon(t.iconId)
|
|
16815
|
+
};
|
|
16816
|
+
}
|
|
16817
|
+
Object.freeze(Object.fromEntries(Object.entries(CAP_TO_KIND).map(([capName, kind]) => [capName, buildDescriptor(capName, kind)])));
|
|
16361
16818
|
var CameraPipelineConfigSchema = object({
|
|
16362
16819
|
engine: PipelineEngineChoiceSchema.optional(),
|
|
16363
16820
|
steps: array(PipelineStepInputSchema).readonly(),
|
|
@@ -19567,13 +20024,29 @@ method(object({
|
|
|
19567
20024
|
}), method(object({ deviceId: number() }), RecordingStatusSchema, {
|
|
19568
20025
|
kind: "mutation",
|
|
19569
20026
|
auth: "admin"
|
|
19570
|
-
}), method(object({
|
|
20027
|
+
}), method(object({
|
|
20028
|
+
deviceId: number(),
|
|
20029
|
+
reason: OpsLogReasonSchema.optional()
|
|
20030
|
+
}), object({
|
|
19571
20031
|
floorMs: number().nullable(),
|
|
19572
20032
|
deletedBuckets: number().int(),
|
|
19573
20033
|
reclaimedBytes: number().int()
|
|
19574
20034
|
}), {
|
|
19575
20035
|
kind: "mutation",
|
|
19576
20036
|
auth: "admin"
|
|
20037
|
+
}), method(object({
|
|
20038
|
+
deviceId: number(),
|
|
20039
|
+
fromMs: number().optional(),
|
|
20040
|
+
toMs: number().optional()
|
|
20041
|
+
}), object({
|
|
20042
|
+
deletedBuckets: number().int(),
|
|
20043
|
+
reclaimedBytes: number().int()
|
|
20044
|
+
}), {
|
|
20045
|
+
kind: "mutation",
|
|
20046
|
+
auth: "admin"
|
|
20047
|
+
}), method(OpsLogQueryInputSchema, array(OpsLogEntrySchema).readonly(), {
|
|
20048
|
+
kind: "query",
|
|
20049
|
+
auth: "admin"
|
|
19577
20050
|
});
|
|
19578
20051
|
/**
|
|
19579
20052
|
* `recordingExport` cap — render a footage time range into a single downloadable
|
|
@@ -22695,6 +23168,12 @@ Object.freeze({
|
|
|
22695
23168
|
addonId: null,
|
|
22696
23169
|
access: "delete"
|
|
22697
23170
|
},
|
|
23171
|
+
"pipelineAnalytics.deleteDeviceEvents": {
|
|
23172
|
+
capName: "pipeline-analytics",
|
|
23173
|
+
capScope: "device",
|
|
23174
|
+
addonId: null,
|
|
23175
|
+
access: "delete"
|
|
23176
|
+
},
|
|
22698
23177
|
"pipelineAnalytics.deleteTracks": {
|
|
22699
23178
|
capName: "pipeline-analytics",
|
|
22700
23179
|
capScope: "device",
|
|
@@ -22725,6 +23204,12 @@ Object.freeze({
|
|
|
22725
23204
|
addonId: null,
|
|
22726
23205
|
access: "view"
|
|
22727
23206
|
},
|
|
23207
|
+
"pipelineAnalytics.getEventStoreFootprint": {
|
|
23208
|
+
capName: "pipeline-analytics",
|
|
23209
|
+
capScope: "device",
|
|
23210
|
+
addonId: null,
|
|
23211
|
+
access: "view"
|
|
23212
|
+
},
|
|
22728
23213
|
"pipelineAnalytics.getKeyEvents": {
|
|
22729
23214
|
capName: "pipeline-analytics",
|
|
22730
23215
|
capScope: "device",
|
|
@@ -22767,6 +23252,12 @@ Object.freeze({
|
|
|
22767
23252
|
addonId: null,
|
|
22768
23253
|
access: "view"
|
|
22769
23254
|
},
|
|
23255
|
+
"pipelineAnalytics.listOpsLog": {
|
|
23256
|
+
capName: "pipeline-analytics",
|
|
23257
|
+
capScope: "device",
|
|
23258
|
+
addonId: null,
|
|
23259
|
+
access: "view"
|
|
23260
|
+
},
|
|
22770
23261
|
"pipelineAnalytics.listRecentTracks": {
|
|
22771
23262
|
capName: "pipeline-analytics",
|
|
22772
23263
|
capScope: "device",
|
|
@@ -22779,6 +23270,12 @@ Object.freeze({
|
|
|
22779
23270
|
addonId: null,
|
|
22780
23271
|
access: "view"
|
|
22781
23272
|
},
|
|
23273
|
+
"pipelineAnalytics.pruneEvents": {
|
|
23274
|
+
capName: "pipeline-analytics",
|
|
23275
|
+
capScope: "device",
|
|
23276
|
+
addonId: null,
|
|
23277
|
+
access: "create"
|
|
23278
|
+
},
|
|
22782
23279
|
"pipelineAnalytics.pruneEventsBefore": {
|
|
22783
23280
|
capName: "pipeline-analytics",
|
|
22784
23281
|
capScope: "device",
|
|
@@ -23541,6 +24038,12 @@ Object.freeze({
|
|
|
23541
24038
|
addonId: null,
|
|
23542
24039
|
access: "create"
|
|
23543
24040
|
},
|
|
24041
|
+
"recording.deleteFootprint": {
|
|
24042
|
+
capName: "recording",
|
|
24043
|
+
capScope: "system",
|
|
24044
|
+
addonId: null,
|
|
24045
|
+
access: "delete"
|
|
24046
|
+
},
|
|
23544
24047
|
"recording.getAvailability": {
|
|
23545
24048
|
capName: "recording",
|
|
23546
24049
|
capScope: "system",
|
|
@@ -23571,6 +24074,12 @@ Object.freeze({
|
|
|
23571
24074
|
addonId: null,
|
|
23572
24075
|
access: "view"
|
|
23573
24076
|
},
|
|
24077
|
+
"recording.listOpsLog": {
|
|
24078
|
+
capName: "recording",
|
|
24079
|
+
capScope: "system",
|
|
24080
|
+
addonId: null,
|
|
24081
|
+
access: "view"
|
|
24082
|
+
},
|
|
23574
24083
|
"recording.locateSegment": {
|
|
23575
24084
|
capName: "recording",
|
|
23576
24085
|
capScope: "system",
|