@camstack/addon-provider-dreo 0.1.21 → 0.1.23
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/addon.js +515 -5
- package/dist/addon.mjs +515 -5
- package/package.json +1 -1
package/dist/addon.js
CHANGED
|
@@ -7380,6 +7380,62 @@ var RecordingConfigSchema = object({
|
|
|
7380
7380
|
scrubThumbnails: ScrubThumbnailPresetSchema.optional()
|
|
7381
7381
|
});
|
|
7382
7382
|
/**
|
|
7383
|
+
* Ops-log — the durable, append-only operations audit shared by the
|
|
7384
|
+
* recordings and events management surfaces.
|
|
7385
|
+
*
|
|
7386
|
+
* ONE row shape is reused for both domains so a single "Activity" view can
|
|
7387
|
+
* merge the recorder's DurableState ring (recordings ops-log) and the
|
|
7388
|
+
* pipeline-analytics SQLite collection (events ops-log). Each row records a
|
|
7389
|
+
* management operation, WHY it ran (reason), and its measurable effect
|
|
7390
|
+
* (itemsAffected + bytesReclaimed). Writes are best-effort — a failed log must
|
|
7391
|
+
* never fail the operation it records.
|
|
7392
|
+
*/
|
|
7393
|
+
/** Which management domain the operation belongs to. */
|
|
7394
|
+
var OpsLogDomainSchema = _enum(["recording", "events"]);
|
|
7395
|
+
/** The kind of management operation performed. */
|
|
7396
|
+
var OpsLogOpSchema = _enum([
|
|
7397
|
+
"prune",
|
|
7398
|
+
"manual-delete",
|
|
7399
|
+
"rescan",
|
|
7400
|
+
"retention-run"
|
|
7401
|
+
]);
|
|
7402
|
+
/** Why the operation ran. */
|
|
7403
|
+
var OpsLogReasonSchema = _enum([
|
|
7404
|
+
"retention",
|
|
7405
|
+
"quota",
|
|
7406
|
+
"manual",
|
|
7407
|
+
"operator"
|
|
7408
|
+
]);
|
|
7409
|
+
/** One audit row, shared verbatim by both domains. */
|
|
7410
|
+
var OpsLogEntrySchema = object({
|
|
7411
|
+
/** Unique row id. */
|
|
7412
|
+
id: string(),
|
|
7413
|
+
/** Epoch ms the operation completed. */
|
|
7414
|
+
at: number(),
|
|
7415
|
+
domain: OpsLogDomainSchema,
|
|
7416
|
+
op: OpsLogOpSchema,
|
|
7417
|
+
reason: OpsLogReasonSchema,
|
|
7418
|
+
/** The camera the op targeted; null for a cluster/global op. */
|
|
7419
|
+
deviceId: number().nullable(),
|
|
7420
|
+
/** Node that performed the op (the log carries nodeId — no cross-node aggregation). */
|
|
7421
|
+
nodeId: string(),
|
|
7422
|
+
/** Buckets / rows deleted (op-specific unit). */
|
|
7423
|
+
itemsAffected: number(),
|
|
7424
|
+
/** Bytes reclaimed by the op (0 when not measurable). */
|
|
7425
|
+
bytesReclaimed: number(),
|
|
7426
|
+
/** Free-text detail (e.g. "floor moved to <ts>"); null when none. */
|
|
7427
|
+
detail: string().nullable(),
|
|
7428
|
+
/** Who/what triggered the op. */
|
|
7429
|
+
actor: string()
|
|
7430
|
+
});
|
|
7431
|
+
/** Shared query input for the per-domain `listOpsLog` cap methods. */
|
|
7432
|
+
var OpsLogQueryInputSchema = object({
|
|
7433
|
+
/** Restrict to a single camera; omit for every row. */
|
|
7434
|
+
deviceId: number().optional(),
|
|
7435
|
+
/** Max rows returned, newest-first. */
|
|
7436
|
+
limit: number().int().min(1).max(1e3).optional()
|
|
7437
|
+
});
|
|
7438
|
+
/**
|
|
7383
7439
|
* `StorageLocationType` — an addon-declared id that identifies the *kind* of
|
|
7384
7440
|
* storage a location serves. Defined here (not in `capabilities/storage.cap.ts`)
|
|
7385
7441
|
* so the persisted record schema and the consumer-facing cap can both consume it
|
|
@@ -7623,6 +7679,160 @@ var EncodeProfileSchema = object({
|
|
|
7623
7679
|
*/
|
|
7624
7680
|
outputArgs: array(string()).optional()
|
|
7625
7681
|
});
|
|
7682
|
+
var COCO_TO_MACRO = {
|
|
7683
|
+
mapping: {
|
|
7684
|
+
person: "person",
|
|
7685
|
+
bicycle: "vehicle",
|
|
7686
|
+
car: "vehicle",
|
|
7687
|
+
motorcycle: "vehicle",
|
|
7688
|
+
airplane: "vehicle",
|
|
7689
|
+
bus: "vehicle",
|
|
7690
|
+
train: "vehicle",
|
|
7691
|
+
truck: "vehicle",
|
|
7692
|
+
boat: "vehicle",
|
|
7693
|
+
bird: "animal",
|
|
7694
|
+
cat: "animal",
|
|
7695
|
+
dog: "animal",
|
|
7696
|
+
horse: "animal",
|
|
7697
|
+
sheep: "animal",
|
|
7698
|
+
cow: "animal",
|
|
7699
|
+
elephant: "animal",
|
|
7700
|
+
bear: "animal",
|
|
7701
|
+
zebra: "animal",
|
|
7702
|
+
giraffe: "animal",
|
|
7703
|
+
suitcase: "package",
|
|
7704
|
+
backpack: "package",
|
|
7705
|
+
handbag: "package"
|
|
7706
|
+
},
|
|
7707
|
+
preserveOriginal: false
|
|
7708
|
+
};
|
|
7709
|
+
var AUDIO_MACRO_LABELS = [
|
|
7710
|
+
{
|
|
7711
|
+
id: "speech",
|
|
7712
|
+
name: "Speech",
|
|
7713
|
+
icon: "🗣️"
|
|
7714
|
+
},
|
|
7715
|
+
{
|
|
7716
|
+
id: "scream",
|
|
7717
|
+
name: "Scream / Shout",
|
|
7718
|
+
icon: "😱"
|
|
7719
|
+
},
|
|
7720
|
+
{
|
|
7721
|
+
id: "crying",
|
|
7722
|
+
name: "Crying / Baby",
|
|
7723
|
+
icon: "😢"
|
|
7724
|
+
},
|
|
7725
|
+
{
|
|
7726
|
+
id: "laughter",
|
|
7727
|
+
name: "Laughter",
|
|
7728
|
+
icon: "😂"
|
|
7729
|
+
},
|
|
7730
|
+
{
|
|
7731
|
+
id: "music",
|
|
7732
|
+
name: "Music",
|
|
7733
|
+
icon: "🎵"
|
|
7734
|
+
},
|
|
7735
|
+
{
|
|
7736
|
+
id: "dog",
|
|
7737
|
+
name: "Dog",
|
|
7738
|
+
icon: "🐕"
|
|
7739
|
+
},
|
|
7740
|
+
{
|
|
7741
|
+
id: "cat",
|
|
7742
|
+
name: "Cat",
|
|
7743
|
+
icon: "🐈"
|
|
7744
|
+
},
|
|
7745
|
+
{
|
|
7746
|
+
id: "bird",
|
|
7747
|
+
name: "Bird",
|
|
7748
|
+
icon: "🐦"
|
|
7749
|
+
},
|
|
7750
|
+
{
|
|
7751
|
+
id: "animal",
|
|
7752
|
+
name: "Animal (other)",
|
|
7753
|
+
icon: "🐾"
|
|
7754
|
+
},
|
|
7755
|
+
{
|
|
7756
|
+
id: "alarm",
|
|
7757
|
+
name: "Alarm / Siren",
|
|
7758
|
+
icon: "🚨"
|
|
7759
|
+
},
|
|
7760
|
+
{
|
|
7761
|
+
id: "doorbell",
|
|
7762
|
+
name: "Doorbell / Knock",
|
|
7763
|
+
icon: "🔔"
|
|
7764
|
+
},
|
|
7765
|
+
{
|
|
7766
|
+
id: "glass_breaking",
|
|
7767
|
+
name: "Glass Breaking",
|
|
7768
|
+
icon: "💥"
|
|
7769
|
+
},
|
|
7770
|
+
{
|
|
7771
|
+
id: "gunshot",
|
|
7772
|
+
name: "Gunshot / Explosion",
|
|
7773
|
+
icon: "💣"
|
|
7774
|
+
},
|
|
7775
|
+
{
|
|
7776
|
+
id: "vehicle",
|
|
7777
|
+
name: "Vehicle",
|
|
7778
|
+
icon: "🚗"
|
|
7779
|
+
},
|
|
7780
|
+
{
|
|
7781
|
+
id: "siren",
|
|
7782
|
+
name: "Emergency Siren",
|
|
7783
|
+
icon: "🚑"
|
|
7784
|
+
},
|
|
7785
|
+
{
|
|
7786
|
+
id: "fire",
|
|
7787
|
+
name: "Fire / Smoke",
|
|
7788
|
+
icon: "🔥"
|
|
7789
|
+
},
|
|
7790
|
+
{
|
|
7791
|
+
id: "water",
|
|
7792
|
+
name: "Water",
|
|
7793
|
+
icon: "💧"
|
|
7794
|
+
},
|
|
7795
|
+
{
|
|
7796
|
+
id: "wind",
|
|
7797
|
+
name: "Wind / Weather",
|
|
7798
|
+
icon: "🌬️"
|
|
7799
|
+
},
|
|
7800
|
+
{
|
|
7801
|
+
id: "door",
|
|
7802
|
+
name: "Door",
|
|
7803
|
+
icon: "🚪"
|
|
7804
|
+
},
|
|
7805
|
+
{
|
|
7806
|
+
id: "footsteps",
|
|
7807
|
+
name: "Footsteps",
|
|
7808
|
+
icon: "👣"
|
|
7809
|
+
},
|
|
7810
|
+
{
|
|
7811
|
+
id: "crowd",
|
|
7812
|
+
name: "Crowd / Chatter",
|
|
7813
|
+
icon: "👥"
|
|
7814
|
+
},
|
|
7815
|
+
{
|
|
7816
|
+
id: "telephone",
|
|
7817
|
+
name: "Telephone",
|
|
7818
|
+
icon: "📞"
|
|
7819
|
+
},
|
|
7820
|
+
{
|
|
7821
|
+
id: "engine",
|
|
7822
|
+
name: "Engine / Motor",
|
|
7823
|
+
icon: "⚙️"
|
|
7824
|
+
},
|
|
7825
|
+
{
|
|
7826
|
+
id: "tools",
|
|
7827
|
+
name: "Tools / Construction",
|
|
7828
|
+
icon: "🔨"
|
|
7829
|
+
},
|
|
7830
|
+
{
|
|
7831
|
+
id: "silence",
|
|
7832
|
+
name: "Silence",
|
|
7833
|
+
icon: "🤫"
|
|
7834
|
+
}
|
|
7835
|
+
];
|
|
7626
7836
|
var YAMNET_TO_MACRO = {
|
|
7627
7837
|
mapping: {
|
|
7628
7838
|
Speech: "speech",
|
|
@@ -7889,6 +8099,125 @@ var _macroLookup = /* @__PURE__ */ new Map();
|
|
|
7889
8099
|
for (const [k, v] of Object.entries(YAMNET_TO_MACRO.mapping)) _macroLookup.set(k.toLowerCase(), v);
|
|
7890
8100
|
for (const [k, v] of Object.entries(APPLE_SA_TO_MACRO.mapping)) _macroLookup.set(k.toLowerCase(), v);
|
|
7891
8101
|
/**
|
|
8102
|
+
* Unified event-kind taxonomy — THE single source of truth for
|
|
8103
|
+
* `kind → { parentKind, category, level, color, iconId, labelKey, label,
|
|
8104
|
+
* icon }`.
|
|
8105
|
+
*
|
|
8106
|
+
* This dictionary folds together what used to be scattered across four
|
|
8107
|
+
* copies:
|
|
8108
|
+
* - `capabilities/sensor-event-kinds.ts` (sensor cap colors)
|
|
8109
|
+
* - `addon-post-analysis/.../services/event-kinds.ts`
|
|
8110
|
+
* (MOTION/PERSON/VEHICLE… _COLOR constants)
|
|
8111
|
+
* - `ui-library/composites/detection-colors.ts` (CLASS_COLORS)
|
|
8112
|
+
* - `addon-post-analysis/shared/frame/box-drawer.ts` (DEFAULT_COLOR)
|
|
8113
|
+
* - the COCO / audio class maps (macro ↔ sub relationships)
|
|
8114
|
+
*
|
|
8115
|
+
* The DATA (serializable — color/iconId/labelKey/parentKind) lives here in
|
|
8116
|
+
* `@camstack/types`. The UI-side mapping `iconId → lucide component` and
|
|
8117
|
+
* `labelKey → t()` lives in `@camstack/ui-library`. UIs never hardcode a
|
|
8118
|
+
* color or an icon: they read this dictionary (server descriptors carry the
|
|
8119
|
+
* fields inline; the client resolves color/icon/label from `iconId`/`kind`).
|
|
8120
|
+
*
|
|
8121
|
+
* Two levels only (v1 YAGNI): macro → sub. `person` is a leaf macro.
|
|
8122
|
+
*/
|
|
8123
|
+
var TAXONOMY_COLORS = {
|
|
8124
|
+
motion: "#f59e0b",
|
|
8125
|
+
audio: "#06b6d4",
|
|
8126
|
+
person: "#22c55e",
|
|
8127
|
+
vehicle: "#3b82f6",
|
|
8128
|
+
animal: "#f97316",
|
|
8129
|
+
package: "#a855f7",
|
|
8130
|
+
sensor: "#8b5cf6",
|
|
8131
|
+
control: "#10b981",
|
|
8132
|
+
genericDetection: "#64748b"
|
|
8133
|
+
};
|
|
8134
|
+
var DETECTION_SUB_COLORS = {
|
|
8135
|
+
car: "#f59e0b",
|
|
8136
|
+
truck: "#d97706",
|
|
8137
|
+
bus: "#b45309",
|
|
8138
|
+
motorcycle: "#eab308",
|
|
8139
|
+
bicycle: "#ca8a04",
|
|
8140
|
+
airplane: "#60a5fa",
|
|
8141
|
+
boat: "#2563eb",
|
|
8142
|
+
train: "#1d4ed8",
|
|
8143
|
+
bird: "#14b8a6",
|
|
8144
|
+
dog: "#84cc16",
|
|
8145
|
+
cat: "#f97316",
|
|
8146
|
+
horse: "#a16207",
|
|
8147
|
+
sheep: "#a3a3a3",
|
|
8148
|
+
cow: "#78716c",
|
|
8149
|
+
elephant: "#6b7280",
|
|
8150
|
+
bear: "#7c2d12",
|
|
8151
|
+
zebra: "#404040",
|
|
8152
|
+
giraffe: "#d4a373"
|
|
8153
|
+
};
|
|
8154
|
+
function titleCase(id) {
|
|
8155
|
+
return id.split(/[-_ ]/).filter((p) => p.length > 0).map((p) => p.charAt(0).toUpperCase() + p.slice(1)).join(" ");
|
|
8156
|
+
}
|
|
8157
|
+
var entries = /* @__PURE__ */ new Map();
|
|
8158
|
+
function macro(kind, category, color, iconId, label) {
|
|
8159
|
+
entries.set(kind, {
|
|
8160
|
+
kind,
|
|
8161
|
+
parentKind: null,
|
|
8162
|
+
level: "macro",
|
|
8163
|
+
category,
|
|
8164
|
+
color,
|
|
8165
|
+
iconId,
|
|
8166
|
+
labelKey: `eventKind.${kind}`,
|
|
8167
|
+
label
|
|
8168
|
+
});
|
|
8169
|
+
}
|
|
8170
|
+
function sub(kind, parentKind, category, color, iconId, label) {
|
|
8171
|
+
entries.set(kind, {
|
|
8172
|
+
kind,
|
|
8173
|
+
parentKind,
|
|
8174
|
+
level: "sub",
|
|
8175
|
+
category,
|
|
8176
|
+
color,
|
|
8177
|
+
iconId,
|
|
8178
|
+
labelKey: `eventKind.${kind}`,
|
|
8179
|
+
label
|
|
8180
|
+
});
|
|
8181
|
+
}
|
|
8182
|
+
macro("motion", "motion", TAXONOMY_COLORS.motion, "motion", "Motion");
|
|
8183
|
+
macro("audio", "audio", TAXONOMY_COLORS.audio, "audio", "Audio");
|
|
8184
|
+
macro("person", "detection", TAXONOMY_COLORS.person, "person", "Person");
|
|
8185
|
+
macro("vehicle", "detection", TAXONOMY_COLORS.vehicle, "vehicle", "Vehicle");
|
|
8186
|
+
macro("animal", "detection", TAXONOMY_COLORS.animal, "animal", "Animal");
|
|
8187
|
+
macro("package", "package", TAXONOMY_COLORS.package, "package", "Package");
|
|
8188
|
+
macro("sensor", "sensor", TAXONOMY_COLORS.sensor, "sensor", "Sensor");
|
|
8189
|
+
macro("control", "control", TAXONOMY_COLORS.control, "control", "Control");
|
|
8190
|
+
for (const [cocoClass, macroClass] of Object.entries(COCO_TO_MACRO.mapping)) {
|
|
8191
|
+
if (macroClass !== "vehicle" && macroClass !== "animal") continue;
|
|
8192
|
+
if (entries.has(cocoClass)) continue;
|
|
8193
|
+
sub(cocoClass, macroClass, "detection", DETECTION_SUB_COLORS[cocoClass] ?? TAXONOMY_COLORS.genericDetection, cocoClass, titleCase(cocoClass));
|
|
8194
|
+
}
|
|
8195
|
+
sub("package-delivered", "package", "package", TAXONOMY_COLORS.package, "package", "Package delivered");
|
|
8196
|
+
sub("package-picked-up", "package", "package", TAXONOMY_COLORS.package, "package", "Package picked up");
|
|
8197
|
+
sub("contact", "sensor", "sensor", "#f59e0b", "door", "Contact");
|
|
8198
|
+
sub("motion-sensor", "sensor", "sensor", TAXONOMY_COLORS.sensor, "pir", "Motion sensor");
|
|
8199
|
+
sub("smoke", "sensor", "sensor", "#ef4444", "smoke", "Smoke");
|
|
8200
|
+
sub("flood", "sensor", "sensor", "#3b82f6", "water", "Water leak");
|
|
8201
|
+
sub("gas", "sensor", "sensor", "#ef4444", "gas", "Gas");
|
|
8202
|
+
sub("carbon-monoxide", "sensor", "sensor", "#dc2626", "smoke", "Carbon monoxide");
|
|
8203
|
+
sub("vibration", "sensor", "sensor", "#eab308", "vibration", "Vibration");
|
|
8204
|
+
sub("tamper", "sensor", "sensor", "#f97316", "tamper", "Tamper");
|
|
8205
|
+
sub("presence", "sensor", "sensor", "#22c55e", "presence", "Presence");
|
|
8206
|
+
sub("enum-sensor", "sensor", "sensor", TAXONOMY_COLORS.sensor, "generic", "Sensor state");
|
|
8207
|
+
sub("device-event", "sensor", "sensor", "#10b981", "button", "Device event");
|
|
8208
|
+
sub("lock", "control", "control", "#0ea5e9", "lock", "Lock");
|
|
8209
|
+
sub("switch", "control", "control", TAXONOMY_COLORS.control, "switch", "Switch");
|
|
8210
|
+
sub("siren", "control", "control", "#dc2626", "siren", "Siren");
|
|
8211
|
+
sub("button", "control", "control", "#10b981", "button", "Button");
|
|
8212
|
+
sub("doorbell", "control", "control", "#a855f7", "doorbell", "Doorbell");
|
|
8213
|
+
for (const l of AUDIO_MACRO_LABELS) {
|
|
8214
|
+
const kind = `audio-${l.id}`;
|
|
8215
|
+
if (entries.has(kind)) continue;
|
|
8216
|
+
sub(kind, "audio", "audio", TAXONOMY_COLORS.audio, kind, l.name);
|
|
8217
|
+
}
|
|
8218
|
+
/** The complete taxonomy dictionary, keyed by kind. */
|
|
8219
|
+
var EVENT_TAXONOMY = Object.freeze(Object.fromEntries(entries));
|
|
8220
|
+
/**
|
|
7892
8221
|
* Error types for the safe expression engine. Two distinct classes so callers
|
|
7893
8222
|
* can tell a compile-time (grammar) failure from a runtime (evaluation)
|
|
7894
8223
|
* failure — both are non-fatal to the host: read paths degrade to "skip link".
|
|
@@ -14843,9 +15172,10 @@ var DEVICE_LOCAL_STATE_CAPS = {
|
|
|
14843
15172
|
* `package` backs the package-drop detector — a package zone is a
|
|
14844
15173
|
* `ZoneRule` on the `'package'` stage referencing drawn polygons
|
|
14845
15174
|
* (see docs/superpowers/specs/2026-07-17-package-zones-design.md §3.1).
|
|
14846
|
-
* The orchestrator provider
|
|
14847
|
-
*
|
|
14848
|
-
* consumers read
|
|
15175
|
+
* The orchestrator provider writes this stage as a first-class slice
|
|
15176
|
+
* (Phase 4): every mutation mirrors the full `{motion, detection,
|
|
15177
|
+
* package}` shape, so consumers read the current package rules directly
|
|
15178
|
+
* off `device.state.zoneRules.value.package`.
|
|
14849
15179
|
*/
|
|
14850
15180
|
runtimeState: object({
|
|
14851
15181
|
motion: array(ZoneRuleSchema).readonly(),
|
|
@@ -18837,17 +19167,30 @@ var EventKindCategorySchema = _enum([
|
|
|
18837
19167
|
"audio",
|
|
18838
19168
|
"detection",
|
|
18839
19169
|
"sensor",
|
|
19170
|
+
"control",
|
|
18840
19171
|
"custom",
|
|
18841
19172
|
"package"
|
|
18842
19173
|
]);
|
|
19174
|
+
/** Taxonomy level — macro (timeline lane) vs sub (events-page leaf). */
|
|
19175
|
+
var EventKindLevelSchema = _enum(["macro", "sub"]);
|
|
18843
19176
|
var EventKindDescriptorSchema = object({
|
|
18844
|
-
/** Stable kind id (e.g. 'motion', '
|
|
19177
|
+
/** Stable kind id (e.g. 'motion', 'vehicle', 'car', 'lock'). */
|
|
18845
19178
|
kind: string(),
|
|
19179
|
+
/** i18n key resolved on the UI side; `label` is the English fallback. */
|
|
19180
|
+
labelKey: string(),
|
|
19181
|
+
/** English fallback label (kept for clients that don't translate). */
|
|
18846
19182
|
label: string(),
|
|
18847
19183
|
/** Hex color for timeline/legend rendering. */
|
|
18848
19184
|
color: string(),
|
|
19185
|
+
/** Dictionary id → lucide component on the UI side. */
|
|
19186
|
+
iconId: string(),
|
|
19187
|
+
/** Legacy closed-vocab glyph — fallback for `iconId`. */
|
|
18849
19188
|
icon: EventKindIconSchema,
|
|
18850
19189
|
category: EventKindCategorySchema,
|
|
19190
|
+
/** Macro parent for this kind ('car' → 'vehicle'); null for a macro. */
|
|
19191
|
+
parentKind: string().nullable(),
|
|
19192
|
+
/** Derived from `parentKind`, explicit for the client tree. */
|
|
19193
|
+
level: EventKindLevelSchema,
|
|
18851
19194
|
/** Which cap + device contributes this kind. For built-ins the camera
|
|
18852
19195
|
* itself; for sensor kinds the LINKED source device. */
|
|
18853
19196
|
source: object({
|
|
@@ -18920,11 +19263,21 @@ var TrackAudioLabelSchema = object({
|
|
|
18920
19263
|
firstAt: number(),
|
|
18921
19264
|
lastAt: number()
|
|
18922
19265
|
});
|
|
19266
|
+
/**
|
|
19267
|
+
* How a track was produced. `pipeline` (default / absent) = the spatial
|
|
19268
|
+
* detection+tracking pipeline. `sensor` = a SYNTHETIC track projected from a
|
|
19269
|
+
* linked sensor/control state change (no positions; carries a snapshot). The
|
|
19270
|
+
* spatial subsystems (tracker association, occupancy count, re-id/embedding,
|
|
19271
|
+
* resurrection) MUST skip `sensor` tracks — they have no bbox trajectory.
|
|
19272
|
+
*/
|
|
19273
|
+
var TrackSourceSchema = _enum(["pipeline", "sensor"]);
|
|
18923
19274
|
var TrackSchema = object({
|
|
18924
19275
|
trackId: string(),
|
|
18925
19276
|
deviceId: number(),
|
|
18926
19277
|
className: string(),
|
|
18927
19278
|
label: string().optional(),
|
|
19279
|
+
/** Track provenance. Absent ⇒ `pipeline` (legacy rows). */
|
|
19280
|
+
source: TrackSourceSchema.optional(),
|
|
18928
19281
|
firstSeen: number(),
|
|
18929
19282
|
lastSeen: number(),
|
|
18930
19283
|
/** Frame-rate position history (subject to maxPositionHistory cap). */
|
|
@@ -19179,6 +19532,26 @@ var TrackCascadeCountsSchema = object({
|
|
|
19179
19532
|
/** Per-track CLIP search vectors removed (best-effort). */
|
|
19180
19533
|
embeddings: number().int()
|
|
19181
19534
|
});
|
|
19535
|
+
/** Event-store footprint for one camera. */
|
|
19536
|
+
var EventStoreDeviceFootprintSchema = object({
|
|
19537
|
+
deviceId: number(),
|
|
19538
|
+
/** Persisted event rows (motion + object + audio) for the camera. */
|
|
19539
|
+
rows: number().int(),
|
|
19540
|
+
/** Event-owned media bytes on disk for the camera. */
|
|
19541
|
+
bytes: number().int()
|
|
19542
|
+
});
|
|
19543
|
+
/** Aggregate event-store footprint: global totals + per-camera breakdown. */
|
|
19544
|
+
var EventStoreFootprintSchema = object({
|
|
19545
|
+
totalRows: number().int(),
|
|
19546
|
+
totalBytes: number().int(),
|
|
19547
|
+
devices: array(EventStoreDeviceFootprintSchema).readonly()
|
|
19548
|
+
});
|
|
19549
|
+
/** Per-kind counts returned by the event-prune / device-delete mutations. */
|
|
19550
|
+
var EventPruneCountsSchema = object({
|
|
19551
|
+
motion: number().int(),
|
|
19552
|
+
object: number().int(),
|
|
19553
|
+
audio: number().int()
|
|
19554
|
+
});
|
|
19182
19555
|
DeviceType.Camera, method(object({ deviceId: number() }), array(TrackSchema).readonly()), method(object({
|
|
19183
19556
|
deviceId: number(),
|
|
19184
19557
|
trackId: string()
|
|
@@ -19242,6 +19615,21 @@ DeviceType.Camera, method(object({ deviceId: number() }), array(TrackSchema).rea
|
|
|
19242
19615
|
}), {
|
|
19243
19616
|
kind: "mutation",
|
|
19244
19617
|
auth: "admin"
|
|
19618
|
+
}), method(object({}), EventStoreFootprintSchema, {
|
|
19619
|
+
kind: "query",
|
|
19620
|
+
auth: "admin"
|
|
19621
|
+
}), method(object({
|
|
19622
|
+
olderThanMs: number(),
|
|
19623
|
+
reason: OpsLogReasonSchema.optional()
|
|
19624
|
+
}), EventPruneCountsSchema, {
|
|
19625
|
+
kind: "mutation",
|
|
19626
|
+
auth: "admin"
|
|
19627
|
+
}), method(object({ deviceId: number() }), EventPruneCountsSchema, {
|
|
19628
|
+
kind: "mutation",
|
|
19629
|
+
auth: "admin"
|
|
19630
|
+
}), method(OpsLogQueryInputSchema, array(OpsLogEntrySchema).readonly(), {
|
|
19631
|
+
kind: "query",
|
|
19632
|
+
auth: "admin"
|
|
19245
19633
|
}), method(object({
|
|
19246
19634
|
eventId: string(),
|
|
19247
19635
|
kind: MediaFileKindEnum.optional()
|
|
@@ -19266,6 +19654,76 @@ DeviceType.Camera, method(object({ deviceId: number() }), array(TrackSchema).rea
|
|
|
19266
19654
|
eventId: string(),
|
|
19267
19655
|
timestamp: number()
|
|
19268
19656
|
});
|
|
19657
|
+
/**
|
|
19658
|
+
* Cap → event-kind mapping for the SENSOR / CONTROL cap families — the table
|
|
19659
|
+
* `pipeline-analytics.listEventKinds` uses to turn a linked device's bound
|
|
19660
|
+
* caps into per-camera event-kind descriptors.
|
|
19661
|
+
*
|
|
19662
|
+
* The descriptor DATA (color / iconId / labelKey / parentKind / category)
|
|
19663
|
+
* is NOT duplicated here — every entry is derived from the single
|
|
19664
|
+
* `EVENT_TAXONOMY` dictionary (`catalogs/event-taxonomy.ts`). This file owns
|
|
19665
|
+
* ONLY the cap-name → taxonomy-kind mapping. Adding a new eventful sensor /
|
|
19666
|
+
* control cap means adding one line here (and a taxonomy entry); the anti-
|
|
19667
|
+
* drift guard `scripts/check-event-kind-coverage.ts` fails the build if an
|
|
19668
|
+
* eventful cap is missing.
|
|
19669
|
+
*/
|
|
19670
|
+
/** Map a taxonomy `iconId` onto the legacy closed `EventKindIcon` enum. */
|
|
19671
|
+
var LEGACY_ICON = {
|
|
19672
|
+
motion: "motion",
|
|
19673
|
+
audio: "audio",
|
|
19674
|
+
person: "person",
|
|
19675
|
+
vehicle: "vehicle",
|
|
19676
|
+
animal: "animal",
|
|
19677
|
+
package: "package",
|
|
19678
|
+
door: "door",
|
|
19679
|
+
pir: "pir",
|
|
19680
|
+
smoke: "smoke",
|
|
19681
|
+
water: "water",
|
|
19682
|
+
button: "button",
|
|
19683
|
+
generic: "generic",
|
|
19684
|
+
gas: "smoke",
|
|
19685
|
+
vibration: "generic",
|
|
19686
|
+
tamper: "generic",
|
|
19687
|
+
presence: "person",
|
|
19688
|
+
lock: "generic",
|
|
19689
|
+
siren: "generic",
|
|
19690
|
+
switch: "generic",
|
|
19691
|
+
doorbell: "button"
|
|
19692
|
+
};
|
|
19693
|
+
function legacyIcon(iconId) {
|
|
19694
|
+
return LEGACY_ICON[iconId] ?? "generic";
|
|
19695
|
+
}
|
|
19696
|
+
/**
|
|
19697
|
+
* Cap name → taxonomy kind id. Covers EVERY eventful sensor / control cap.
|
|
19698
|
+
* The anti-drift guard cross-checks this against the eventful caps declared
|
|
19699
|
+
* in `packages/types/src/capabilities/*.cap.ts`.
|
|
19700
|
+
*/
|
|
19701
|
+
var CAP_TO_KIND = {
|
|
19702
|
+
contact: "contact",
|
|
19703
|
+
motion: "motion-sensor",
|
|
19704
|
+
smoke: "smoke",
|
|
19705
|
+
flood: "flood",
|
|
19706
|
+
gas: "gas",
|
|
19707
|
+
"carbon-monoxide": "carbon-monoxide",
|
|
19708
|
+
vibration: "vibration",
|
|
19709
|
+
tamper: "tamper",
|
|
19710
|
+
presence: "presence",
|
|
19711
|
+
"enum-sensor": "enum-sensor",
|
|
19712
|
+
"event-emitter": "device-event",
|
|
19713
|
+
"lock-control": "lock",
|
|
19714
|
+
switch: "switch",
|
|
19715
|
+
button: "button",
|
|
19716
|
+
doorbell: "doorbell"
|
|
19717
|
+
};
|
|
19718
|
+
function buildDescriptor(capName, kind) {
|
|
19719
|
+
const t = EVENT_TAXONOMY[kind];
|
|
19720
|
+
if (t === void 0) throw new Error(`EVENT_KIND_BY_CAP: cap '${capName}' maps to unknown taxonomy kind '${kind}'`);
|
|
19721
|
+
return {
|
|
19722
|
+
...t,
|
|
19723
|
+
icon: legacyIcon(t.iconId)
|
|
19724
|
+
};
|
|
19725
|
+
}
|
|
19726
|
+
Object.freeze(Object.fromEntries(Object.entries(CAP_TO_KIND).map(([capName, kind]) => [capName, buildDescriptor(capName, kind)])));
|
|
19269
19727
|
var CameraPipelineConfigSchema = object({
|
|
19270
19728
|
engine: PipelineEngineChoiceSchema.optional(),
|
|
19271
19729
|
steps: array(PipelineStepInputSchema).readonly(),
|
|
@@ -22475,13 +22933,29 @@ method(object({
|
|
|
22475
22933
|
}), method(object({ deviceId: number() }), RecordingStatusSchema, {
|
|
22476
22934
|
kind: "mutation",
|
|
22477
22935
|
auth: "admin"
|
|
22478
|
-
}), method(object({
|
|
22936
|
+
}), method(object({
|
|
22937
|
+
deviceId: number(),
|
|
22938
|
+
reason: OpsLogReasonSchema.optional()
|
|
22939
|
+
}), object({
|
|
22479
22940
|
floorMs: number().nullable(),
|
|
22480
22941
|
deletedBuckets: number().int(),
|
|
22481
22942
|
reclaimedBytes: number().int()
|
|
22482
22943
|
}), {
|
|
22483
22944
|
kind: "mutation",
|
|
22484
22945
|
auth: "admin"
|
|
22946
|
+
}), method(object({
|
|
22947
|
+
deviceId: number(),
|
|
22948
|
+
fromMs: number().optional(),
|
|
22949
|
+
toMs: number().optional()
|
|
22950
|
+
}), object({
|
|
22951
|
+
deletedBuckets: number().int(),
|
|
22952
|
+
reclaimedBytes: number().int()
|
|
22953
|
+
}), {
|
|
22954
|
+
kind: "mutation",
|
|
22955
|
+
auth: "admin"
|
|
22956
|
+
}), method(OpsLogQueryInputSchema, array(OpsLogEntrySchema).readonly(), {
|
|
22957
|
+
kind: "query",
|
|
22958
|
+
auth: "admin"
|
|
22485
22959
|
});
|
|
22486
22960
|
/**
|
|
22487
22961
|
* `recordingExport` cap — render a footage time range into a single downloadable
|
|
@@ -25603,6 +26077,12 @@ Object.freeze({
|
|
|
25603
26077
|
addonId: null,
|
|
25604
26078
|
access: "delete"
|
|
25605
26079
|
},
|
|
26080
|
+
"pipelineAnalytics.deleteDeviceEvents": {
|
|
26081
|
+
capName: "pipeline-analytics",
|
|
26082
|
+
capScope: "device",
|
|
26083
|
+
addonId: null,
|
|
26084
|
+
access: "delete"
|
|
26085
|
+
},
|
|
25606
26086
|
"pipelineAnalytics.deleteTracks": {
|
|
25607
26087
|
capName: "pipeline-analytics",
|
|
25608
26088
|
capScope: "device",
|
|
@@ -25633,6 +26113,12 @@ Object.freeze({
|
|
|
25633
26113
|
addonId: null,
|
|
25634
26114
|
access: "view"
|
|
25635
26115
|
},
|
|
26116
|
+
"pipelineAnalytics.getEventStoreFootprint": {
|
|
26117
|
+
capName: "pipeline-analytics",
|
|
26118
|
+
capScope: "device",
|
|
26119
|
+
addonId: null,
|
|
26120
|
+
access: "view"
|
|
26121
|
+
},
|
|
25636
26122
|
"pipelineAnalytics.getKeyEvents": {
|
|
25637
26123
|
capName: "pipeline-analytics",
|
|
25638
26124
|
capScope: "device",
|
|
@@ -25675,6 +26161,12 @@ Object.freeze({
|
|
|
25675
26161
|
addonId: null,
|
|
25676
26162
|
access: "view"
|
|
25677
26163
|
},
|
|
26164
|
+
"pipelineAnalytics.listOpsLog": {
|
|
26165
|
+
capName: "pipeline-analytics",
|
|
26166
|
+
capScope: "device",
|
|
26167
|
+
addonId: null,
|
|
26168
|
+
access: "view"
|
|
26169
|
+
},
|
|
25678
26170
|
"pipelineAnalytics.listRecentTracks": {
|
|
25679
26171
|
capName: "pipeline-analytics",
|
|
25680
26172
|
capScope: "device",
|
|
@@ -25687,6 +26179,12 @@ Object.freeze({
|
|
|
25687
26179
|
addonId: null,
|
|
25688
26180
|
access: "view"
|
|
25689
26181
|
},
|
|
26182
|
+
"pipelineAnalytics.pruneEvents": {
|
|
26183
|
+
capName: "pipeline-analytics",
|
|
26184
|
+
capScope: "device",
|
|
26185
|
+
addonId: null,
|
|
26186
|
+
access: "create"
|
|
26187
|
+
},
|
|
25690
26188
|
"pipelineAnalytics.pruneEventsBefore": {
|
|
25691
26189
|
capName: "pipeline-analytics",
|
|
25692
26190
|
capScope: "device",
|
|
@@ -26449,6 +26947,12 @@ Object.freeze({
|
|
|
26449
26947
|
addonId: null,
|
|
26450
26948
|
access: "create"
|
|
26451
26949
|
},
|
|
26950
|
+
"recording.deleteFootprint": {
|
|
26951
|
+
capName: "recording",
|
|
26952
|
+
capScope: "system",
|
|
26953
|
+
addonId: null,
|
|
26954
|
+
access: "delete"
|
|
26955
|
+
},
|
|
26452
26956
|
"recording.getAvailability": {
|
|
26453
26957
|
capName: "recording",
|
|
26454
26958
|
capScope: "system",
|
|
@@ -26479,6 +26983,12 @@ Object.freeze({
|
|
|
26479
26983
|
addonId: null,
|
|
26480
26984
|
access: "view"
|
|
26481
26985
|
},
|
|
26986
|
+
"recording.listOpsLog": {
|
|
26987
|
+
capName: "recording",
|
|
26988
|
+
capScope: "system",
|
|
26989
|
+
addonId: null,
|
|
26990
|
+
access: "view"
|
|
26991
|
+
},
|
|
26482
26992
|
"recording.locateSegment": {
|
|
26483
26993
|
capName: "recording",
|
|
26484
26994
|
capScope: "system",
|
package/dist/addon.mjs
CHANGED
|
@@ -7381,6 +7381,62 @@ var RecordingConfigSchema = object({
|
|
|
7381
7381
|
scrubThumbnails: ScrubThumbnailPresetSchema.optional()
|
|
7382
7382
|
});
|
|
7383
7383
|
/**
|
|
7384
|
+
* Ops-log — the durable, append-only operations audit shared by the
|
|
7385
|
+
* recordings and events management surfaces.
|
|
7386
|
+
*
|
|
7387
|
+
* ONE row shape is reused for both domains so a single "Activity" view can
|
|
7388
|
+
* merge the recorder's DurableState ring (recordings ops-log) and the
|
|
7389
|
+
* pipeline-analytics SQLite collection (events ops-log). Each row records a
|
|
7390
|
+
* management operation, WHY it ran (reason), and its measurable effect
|
|
7391
|
+
* (itemsAffected + bytesReclaimed). Writes are best-effort — a failed log must
|
|
7392
|
+
* never fail the operation it records.
|
|
7393
|
+
*/
|
|
7394
|
+
/** Which management domain the operation belongs to. */
|
|
7395
|
+
var OpsLogDomainSchema = _enum(["recording", "events"]);
|
|
7396
|
+
/** The kind of management operation performed. */
|
|
7397
|
+
var OpsLogOpSchema = _enum([
|
|
7398
|
+
"prune",
|
|
7399
|
+
"manual-delete",
|
|
7400
|
+
"rescan",
|
|
7401
|
+
"retention-run"
|
|
7402
|
+
]);
|
|
7403
|
+
/** Why the operation ran. */
|
|
7404
|
+
var OpsLogReasonSchema = _enum([
|
|
7405
|
+
"retention",
|
|
7406
|
+
"quota",
|
|
7407
|
+
"manual",
|
|
7408
|
+
"operator"
|
|
7409
|
+
]);
|
|
7410
|
+
/** One audit row, shared verbatim by both domains. */
|
|
7411
|
+
var OpsLogEntrySchema = object({
|
|
7412
|
+
/** Unique row id. */
|
|
7413
|
+
id: string(),
|
|
7414
|
+
/** Epoch ms the operation completed. */
|
|
7415
|
+
at: number(),
|
|
7416
|
+
domain: OpsLogDomainSchema,
|
|
7417
|
+
op: OpsLogOpSchema,
|
|
7418
|
+
reason: OpsLogReasonSchema,
|
|
7419
|
+
/** The camera the op targeted; null for a cluster/global op. */
|
|
7420
|
+
deviceId: number().nullable(),
|
|
7421
|
+
/** Node that performed the op (the log carries nodeId — no cross-node aggregation). */
|
|
7422
|
+
nodeId: string(),
|
|
7423
|
+
/** Buckets / rows deleted (op-specific unit). */
|
|
7424
|
+
itemsAffected: number(),
|
|
7425
|
+
/** Bytes reclaimed by the op (0 when not measurable). */
|
|
7426
|
+
bytesReclaimed: number(),
|
|
7427
|
+
/** Free-text detail (e.g. "floor moved to <ts>"); null when none. */
|
|
7428
|
+
detail: string().nullable(),
|
|
7429
|
+
/** Who/what triggered the op. */
|
|
7430
|
+
actor: string()
|
|
7431
|
+
});
|
|
7432
|
+
/** Shared query input for the per-domain `listOpsLog` cap methods. */
|
|
7433
|
+
var OpsLogQueryInputSchema = object({
|
|
7434
|
+
/** Restrict to a single camera; omit for every row. */
|
|
7435
|
+
deviceId: number().optional(),
|
|
7436
|
+
/** Max rows returned, newest-first. */
|
|
7437
|
+
limit: number().int().min(1).max(1e3).optional()
|
|
7438
|
+
});
|
|
7439
|
+
/**
|
|
7384
7440
|
* `StorageLocationType` — an addon-declared id that identifies the *kind* of
|
|
7385
7441
|
* storage a location serves. Defined here (not in `capabilities/storage.cap.ts`)
|
|
7386
7442
|
* so the persisted record schema and the consumer-facing cap can both consume it
|
|
@@ -7624,6 +7680,160 @@ var EncodeProfileSchema = object({
|
|
|
7624
7680
|
*/
|
|
7625
7681
|
outputArgs: array(string()).optional()
|
|
7626
7682
|
});
|
|
7683
|
+
var COCO_TO_MACRO = {
|
|
7684
|
+
mapping: {
|
|
7685
|
+
person: "person",
|
|
7686
|
+
bicycle: "vehicle",
|
|
7687
|
+
car: "vehicle",
|
|
7688
|
+
motorcycle: "vehicle",
|
|
7689
|
+
airplane: "vehicle",
|
|
7690
|
+
bus: "vehicle",
|
|
7691
|
+
train: "vehicle",
|
|
7692
|
+
truck: "vehicle",
|
|
7693
|
+
boat: "vehicle",
|
|
7694
|
+
bird: "animal",
|
|
7695
|
+
cat: "animal",
|
|
7696
|
+
dog: "animal",
|
|
7697
|
+
horse: "animal",
|
|
7698
|
+
sheep: "animal",
|
|
7699
|
+
cow: "animal",
|
|
7700
|
+
elephant: "animal",
|
|
7701
|
+
bear: "animal",
|
|
7702
|
+
zebra: "animal",
|
|
7703
|
+
giraffe: "animal",
|
|
7704
|
+
suitcase: "package",
|
|
7705
|
+
backpack: "package",
|
|
7706
|
+
handbag: "package"
|
|
7707
|
+
},
|
|
7708
|
+
preserveOriginal: false
|
|
7709
|
+
};
|
|
7710
|
+
var AUDIO_MACRO_LABELS = [
|
|
7711
|
+
{
|
|
7712
|
+
id: "speech",
|
|
7713
|
+
name: "Speech",
|
|
7714
|
+
icon: "🗣️"
|
|
7715
|
+
},
|
|
7716
|
+
{
|
|
7717
|
+
id: "scream",
|
|
7718
|
+
name: "Scream / Shout",
|
|
7719
|
+
icon: "😱"
|
|
7720
|
+
},
|
|
7721
|
+
{
|
|
7722
|
+
id: "crying",
|
|
7723
|
+
name: "Crying / Baby",
|
|
7724
|
+
icon: "😢"
|
|
7725
|
+
},
|
|
7726
|
+
{
|
|
7727
|
+
id: "laughter",
|
|
7728
|
+
name: "Laughter",
|
|
7729
|
+
icon: "😂"
|
|
7730
|
+
},
|
|
7731
|
+
{
|
|
7732
|
+
id: "music",
|
|
7733
|
+
name: "Music",
|
|
7734
|
+
icon: "🎵"
|
|
7735
|
+
},
|
|
7736
|
+
{
|
|
7737
|
+
id: "dog",
|
|
7738
|
+
name: "Dog",
|
|
7739
|
+
icon: "🐕"
|
|
7740
|
+
},
|
|
7741
|
+
{
|
|
7742
|
+
id: "cat",
|
|
7743
|
+
name: "Cat",
|
|
7744
|
+
icon: "🐈"
|
|
7745
|
+
},
|
|
7746
|
+
{
|
|
7747
|
+
id: "bird",
|
|
7748
|
+
name: "Bird",
|
|
7749
|
+
icon: "🐦"
|
|
7750
|
+
},
|
|
7751
|
+
{
|
|
7752
|
+
id: "animal",
|
|
7753
|
+
name: "Animal (other)",
|
|
7754
|
+
icon: "🐾"
|
|
7755
|
+
},
|
|
7756
|
+
{
|
|
7757
|
+
id: "alarm",
|
|
7758
|
+
name: "Alarm / Siren",
|
|
7759
|
+
icon: "🚨"
|
|
7760
|
+
},
|
|
7761
|
+
{
|
|
7762
|
+
id: "doorbell",
|
|
7763
|
+
name: "Doorbell / Knock",
|
|
7764
|
+
icon: "🔔"
|
|
7765
|
+
},
|
|
7766
|
+
{
|
|
7767
|
+
id: "glass_breaking",
|
|
7768
|
+
name: "Glass Breaking",
|
|
7769
|
+
icon: "💥"
|
|
7770
|
+
},
|
|
7771
|
+
{
|
|
7772
|
+
id: "gunshot",
|
|
7773
|
+
name: "Gunshot / Explosion",
|
|
7774
|
+
icon: "💣"
|
|
7775
|
+
},
|
|
7776
|
+
{
|
|
7777
|
+
id: "vehicle",
|
|
7778
|
+
name: "Vehicle",
|
|
7779
|
+
icon: "🚗"
|
|
7780
|
+
},
|
|
7781
|
+
{
|
|
7782
|
+
id: "siren",
|
|
7783
|
+
name: "Emergency Siren",
|
|
7784
|
+
icon: "🚑"
|
|
7785
|
+
},
|
|
7786
|
+
{
|
|
7787
|
+
id: "fire",
|
|
7788
|
+
name: "Fire / Smoke",
|
|
7789
|
+
icon: "🔥"
|
|
7790
|
+
},
|
|
7791
|
+
{
|
|
7792
|
+
id: "water",
|
|
7793
|
+
name: "Water",
|
|
7794
|
+
icon: "💧"
|
|
7795
|
+
},
|
|
7796
|
+
{
|
|
7797
|
+
id: "wind",
|
|
7798
|
+
name: "Wind / Weather",
|
|
7799
|
+
icon: "🌬️"
|
|
7800
|
+
},
|
|
7801
|
+
{
|
|
7802
|
+
id: "door",
|
|
7803
|
+
name: "Door",
|
|
7804
|
+
icon: "🚪"
|
|
7805
|
+
},
|
|
7806
|
+
{
|
|
7807
|
+
id: "footsteps",
|
|
7808
|
+
name: "Footsteps",
|
|
7809
|
+
icon: "👣"
|
|
7810
|
+
},
|
|
7811
|
+
{
|
|
7812
|
+
id: "crowd",
|
|
7813
|
+
name: "Crowd / Chatter",
|
|
7814
|
+
icon: "👥"
|
|
7815
|
+
},
|
|
7816
|
+
{
|
|
7817
|
+
id: "telephone",
|
|
7818
|
+
name: "Telephone",
|
|
7819
|
+
icon: "📞"
|
|
7820
|
+
},
|
|
7821
|
+
{
|
|
7822
|
+
id: "engine",
|
|
7823
|
+
name: "Engine / Motor",
|
|
7824
|
+
icon: "⚙️"
|
|
7825
|
+
},
|
|
7826
|
+
{
|
|
7827
|
+
id: "tools",
|
|
7828
|
+
name: "Tools / Construction",
|
|
7829
|
+
icon: "🔨"
|
|
7830
|
+
},
|
|
7831
|
+
{
|
|
7832
|
+
id: "silence",
|
|
7833
|
+
name: "Silence",
|
|
7834
|
+
icon: "🤫"
|
|
7835
|
+
}
|
|
7836
|
+
];
|
|
7627
7837
|
var YAMNET_TO_MACRO = {
|
|
7628
7838
|
mapping: {
|
|
7629
7839
|
Speech: "speech",
|
|
@@ -7890,6 +8100,125 @@ var _macroLookup = /* @__PURE__ */ new Map();
|
|
|
7890
8100
|
for (const [k, v] of Object.entries(YAMNET_TO_MACRO.mapping)) _macroLookup.set(k.toLowerCase(), v);
|
|
7891
8101
|
for (const [k, v] of Object.entries(APPLE_SA_TO_MACRO.mapping)) _macroLookup.set(k.toLowerCase(), v);
|
|
7892
8102
|
/**
|
|
8103
|
+
* Unified event-kind taxonomy — THE single source of truth for
|
|
8104
|
+
* `kind → { parentKind, category, level, color, iconId, labelKey, label,
|
|
8105
|
+
* icon }`.
|
|
8106
|
+
*
|
|
8107
|
+
* This dictionary folds together what used to be scattered across four
|
|
8108
|
+
* copies:
|
|
8109
|
+
* - `capabilities/sensor-event-kinds.ts` (sensor cap colors)
|
|
8110
|
+
* - `addon-post-analysis/.../services/event-kinds.ts`
|
|
8111
|
+
* (MOTION/PERSON/VEHICLE… _COLOR constants)
|
|
8112
|
+
* - `ui-library/composites/detection-colors.ts` (CLASS_COLORS)
|
|
8113
|
+
* - `addon-post-analysis/shared/frame/box-drawer.ts` (DEFAULT_COLOR)
|
|
8114
|
+
* - the COCO / audio class maps (macro ↔ sub relationships)
|
|
8115
|
+
*
|
|
8116
|
+
* The DATA (serializable — color/iconId/labelKey/parentKind) lives here in
|
|
8117
|
+
* `@camstack/types`. The UI-side mapping `iconId → lucide component` and
|
|
8118
|
+
* `labelKey → t()` lives in `@camstack/ui-library`. UIs never hardcode a
|
|
8119
|
+
* color or an icon: they read this dictionary (server descriptors carry the
|
|
8120
|
+
* fields inline; the client resolves color/icon/label from `iconId`/`kind`).
|
|
8121
|
+
*
|
|
8122
|
+
* Two levels only (v1 YAGNI): macro → sub. `person` is a leaf macro.
|
|
8123
|
+
*/
|
|
8124
|
+
var TAXONOMY_COLORS = {
|
|
8125
|
+
motion: "#f59e0b",
|
|
8126
|
+
audio: "#06b6d4",
|
|
8127
|
+
person: "#22c55e",
|
|
8128
|
+
vehicle: "#3b82f6",
|
|
8129
|
+
animal: "#f97316",
|
|
8130
|
+
package: "#a855f7",
|
|
8131
|
+
sensor: "#8b5cf6",
|
|
8132
|
+
control: "#10b981",
|
|
8133
|
+
genericDetection: "#64748b"
|
|
8134
|
+
};
|
|
8135
|
+
var DETECTION_SUB_COLORS = {
|
|
8136
|
+
car: "#f59e0b",
|
|
8137
|
+
truck: "#d97706",
|
|
8138
|
+
bus: "#b45309",
|
|
8139
|
+
motorcycle: "#eab308",
|
|
8140
|
+
bicycle: "#ca8a04",
|
|
8141
|
+
airplane: "#60a5fa",
|
|
8142
|
+
boat: "#2563eb",
|
|
8143
|
+
train: "#1d4ed8",
|
|
8144
|
+
bird: "#14b8a6",
|
|
8145
|
+
dog: "#84cc16",
|
|
8146
|
+
cat: "#f97316",
|
|
8147
|
+
horse: "#a16207",
|
|
8148
|
+
sheep: "#a3a3a3",
|
|
8149
|
+
cow: "#78716c",
|
|
8150
|
+
elephant: "#6b7280",
|
|
8151
|
+
bear: "#7c2d12",
|
|
8152
|
+
zebra: "#404040",
|
|
8153
|
+
giraffe: "#d4a373"
|
|
8154
|
+
};
|
|
8155
|
+
function titleCase(id) {
|
|
8156
|
+
return id.split(/[-_ ]/).filter((p) => p.length > 0).map((p) => p.charAt(0).toUpperCase() + p.slice(1)).join(" ");
|
|
8157
|
+
}
|
|
8158
|
+
var entries = /* @__PURE__ */ new Map();
|
|
8159
|
+
function macro(kind, category, color, iconId, label) {
|
|
8160
|
+
entries.set(kind, {
|
|
8161
|
+
kind,
|
|
8162
|
+
parentKind: null,
|
|
8163
|
+
level: "macro",
|
|
8164
|
+
category,
|
|
8165
|
+
color,
|
|
8166
|
+
iconId,
|
|
8167
|
+
labelKey: `eventKind.${kind}`,
|
|
8168
|
+
label
|
|
8169
|
+
});
|
|
8170
|
+
}
|
|
8171
|
+
function sub(kind, parentKind, category, color, iconId, label) {
|
|
8172
|
+
entries.set(kind, {
|
|
8173
|
+
kind,
|
|
8174
|
+
parentKind,
|
|
8175
|
+
level: "sub",
|
|
8176
|
+
category,
|
|
8177
|
+
color,
|
|
8178
|
+
iconId,
|
|
8179
|
+
labelKey: `eventKind.${kind}`,
|
|
8180
|
+
label
|
|
8181
|
+
});
|
|
8182
|
+
}
|
|
8183
|
+
macro("motion", "motion", TAXONOMY_COLORS.motion, "motion", "Motion");
|
|
8184
|
+
macro("audio", "audio", TAXONOMY_COLORS.audio, "audio", "Audio");
|
|
8185
|
+
macro("person", "detection", TAXONOMY_COLORS.person, "person", "Person");
|
|
8186
|
+
macro("vehicle", "detection", TAXONOMY_COLORS.vehicle, "vehicle", "Vehicle");
|
|
8187
|
+
macro("animal", "detection", TAXONOMY_COLORS.animal, "animal", "Animal");
|
|
8188
|
+
macro("package", "package", TAXONOMY_COLORS.package, "package", "Package");
|
|
8189
|
+
macro("sensor", "sensor", TAXONOMY_COLORS.sensor, "sensor", "Sensor");
|
|
8190
|
+
macro("control", "control", TAXONOMY_COLORS.control, "control", "Control");
|
|
8191
|
+
for (const [cocoClass, macroClass] of Object.entries(COCO_TO_MACRO.mapping)) {
|
|
8192
|
+
if (macroClass !== "vehicle" && macroClass !== "animal") continue;
|
|
8193
|
+
if (entries.has(cocoClass)) continue;
|
|
8194
|
+
sub(cocoClass, macroClass, "detection", DETECTION_SUB_COLORS[cocoClass] ?? TAXONOMY_COLORS.genericDetection, cocoClass, titleCase(cocoClass));
|
|
8195
|
+
}
|
|
8196
|
+
sub("package-delivered", "package", "package", TAXONOMY_COLORS.package, "package", "Package delivered");
|
|
8197
|
+
sub("package-picked-up", "package", "package", TAXONOMY_COLORS.package, "package", "Package picked up");
|
|
8198
|
+
sub("contact", "sensor", "sensor", "#f59e0b", "door", "Contact");
|
|
8199
|
+
sub("motion-sensor", "sensor", "sensor", TAXONOMY_COLORS.sensor, "pir", "Motion sensor");
|
|
8200
|
+
sub("smoke", "sensor", "sensor", "#ef4444", "smoke", "Smoke");
|
|
8201
|
+
sub("flood", "sensor", "sensor", "#3b82f6", "water", "Water leak");
|
|
8202
|
+
sub("gas", "sensor", "sensor", "#ef4444", "gas", "Gas");
|
|
8203
|
+
sub("carbon-monoxide", "sensor", "sensor", "#dc2626", "smoke", "Carbon monoxide");
|
|
8204
|
+
sub("vibration", "sensor", "sensor", "#eab308", "vibration", "Vibration");
|
|
8205
|
+
sub("tamper", "sensor", "sensor", "#f97316", "tamper", "Tamper");
|
|
8206
|
+
sub("presence", "sensor", "sensor", "#22c55e", "presence", "Presence");
|
|
8207
|
+
sub("enum-sensor", "sensor", "sensor", TAXONOMY_COLORS.sensor, "generic", "Sensor state");
|
|
8208
|
+
sub("device-event", "sensor", "sensor", "#10b981", "button", "Device event");
|
|
8209
|
+
sub("lock", "control", "control", "#0ea5e9", "lock", "Lock");
|
|
8210
|
+
sub("switch", "control", "control", TAXONOMY_COLORS.control, "switch", "Switch");
|
|
8211
|
+
sub("siren", "control", "control", "#dc2626", "siren", "Siren");
|
|
8212
|
+
sub("button", "control", "control", "#10b981", "button", "Button");
|
|
8213
|
+
sub("doorbell", "control", "control", "#a855f7", "doorbell", "Doorbell");
|
|
8214
|
+
for (const l of AUDIO_MACRO_LABELS) {
|
|
8215
|
+
const kind = `audio-${l.id}`;
|
|
8216
|
+
if (entries.has(kind)) continue;
|
|
8217
|
+
sub(kind, "audio", "audio", TAXONOMY_COLORS.audio, kind, l.name);
|
|
8218
|
+
}
|
|
8219
|
+
/** The complete taxonomy dictionary, keyed by kind. */
|
|
8220
|
+
var EVENT_TAXONOMY = Object.freeze(Object.fromEntries(entries));
|
|
8221
|
+
/**
|
|
7893
8222
|
* Error types for the safe expression engine. Two distinct classes so callers
|
|
7894
8223
|
* can tell a compile-time (grammar) failure from a runtime (evaluation)
|
|
7895
8224
|
* failure — both are non-fatal to the host: read paths degrade to "skip link".
|
|
@@ -14844,9 +15173,10 @@ var DEVICE_LOCAL_STATE_CAPS = {
|
|
|
14844
15173
|
* `package` backs the package-drop detector — a package zone is a
|
|
14845
15174
|
* `ZoneRule` on the `'package'` stage referencing drawn polygons
|
|
14846
15175
|
* (see docs/superpowers/specs/2026-07-17-package-zones-design.md §3.1).
|
|
14847
|
-
* The orchestrator provider
|
|
14848
|
-
*
|
|
14849
|
-
* consumers read
|
|
15176
|
+
* The orchestrator provider writes this stage as a first-class slice
|
|
15177
|
+
* (Phase 4): every mutation mirrors the full `{motion, detection,
|
|
15178
|
+
* package}` shape, so consumers read the current package rules directly
|
|
15179
|
+
* off `device.state.zoneRules.value.package`.
|
|
14850
15180
|
*/
|
|
14851
15181
|
runtimeState: object({
|
|
14852
15182
|
motion: array(ZoneRuleSchema).readonly(),
|
|
@@ -18838,17 +19168,30 @@ var EventKindCategorySchema = _enum([
|
|
|
18838
19168
|
"audio",
|
|
18839
19169
|
"detection",
|
|
18840
19170
|
"sensor",
|
|
19171
|
+
"control",
|
|
18841
19172
|
"custom",
|
|
18842
19173
|
"package"
|
|
18843
19174
|
]);
|
|
19175
|
+
/** Taxonomy level — macro (timeline lane) vs sub (events-page leaf). */
|
|
19176
|
+
var EventKindLevelSchema = _enum(["macro", "sub"]);
|
|
18844
19177
|
var EventKindDescriptorSchema = object({
|
|
18845
|
-
/** Stable kind id (e.g. 'motion', '
|
|
19178
|
+
/** Stable kind id (e.g. 'motion', 'vehicle', 'car', 'lock'). */
|
|
18846
19179
|
kind: string(),
|
|
19180
|
+
/** i18n key resolved on the UI side; `label` is the English fallback. */
|
|
19181
|
+
labelKey: string(),
|
|
19182
|
+
/** English fallback label (kept for clients that don't translate). */
|
|
18847
19183
|
label: string(),
|
|
18848
19184
|
/** Hex color for timeline/legend rendering. */
|
|
18849
19185
|
color: string(),
|
|
19186
|
+
/** Dictionary id → lucide component on the UI side. */
|
|
19187
|
+
iconId: string(),
|
|
19188
|
+
/** Legacy closed-vocab glyph — fallback for `iconId`. */
|
|
18850
19189
|
icon: EventKindIconSchema,
|
|
18851
19190
|
category: EventKindCategorySchema,
|
|
19191
|
+
/** Macro parent for this kind ('car' → 'vehicle'); null for a macro. */
|
|
19192
|
+
parentKind: string().nullable(),
|
|
19193
|
+
/** Derived from `parentKind`, explicit for the client tree. */
|
|
19194
|
+
level: EventKindLevelSchema,
|
|
18852
19195
|
/** Which cap + device contributes this kind. For built-ins the camera
|
|
18853
19196
|
* itself; for sensor kinds the LINKED source device. */
|
|
18854
19197
|
source: object({
|
|
@@ -18921,11 +19264,21 @@ var TrackAudioLabelSchema = object({
|
|
|
18921
19264
|
firstAt: number(),
|
|
18922
19265
|
lastAt: number()
|
|
18923
19266
|
});
|
|
19267
|
+
/**
|
|
19268
|
+
* How a track was produced. `pipeline` (default / absent) = the spatial
|
|
19269
|
+
* detection+tracking pipeline. `sensor` = a SYNTHETIC track projected from a
|
|
19270
|
+
* linked sensor/control state change (no positions; carries a snapshot). The
|
|
19271
|
+
* spatial subsystems (tracker association, occupancy count, re-id/embedding,
|
|
19272
|
+
* resurrection) MUST skip `sensor` tracks — they have no bbox trajectory.
|
|
19273
|
+
*/
|
|
19274
|
+
var TrackSourceSchema = _enum(["pipeline", "sensor"]);
|
|
18924
19275
|
var TrackSchema = object({
|
|
18925
19276
|
trackId: string(),
|
|
18926
19277
|
deviceId: number(),
|
|
18927
19278
|
className: string(),
|
|
18928
19279
|
label: string().optional(),
|
|
19280
|
+
/** Track provenance. Absent ⇒ `pipeline` (legacy rows). */
|
|
19281
|
+
source: TrackSourceSchema.optional(),
|
|
18929
19282
|
firstSeen: number(),
|
|
18930
19283
|
lastSeen: number(),
|
|
18931
19284
|
/** Frame-rate position history (subject to maxPositionHistory cap). */
|
|
@@ -19180,6 +19533,26 @@ var TrackCascadeCountsSchema = object({
|
|
|
19180
19533
|
/** Per-track CLIP search vectors removed (best-effort). */
|
|
19181
19534
|
embeddings: number().int()
|
|
19182
19535
|
});
|
|
19536
|
+
/** Event-store footprint for one camera. */
|
|
19537
|
+
var EventStoreDeviceFootprintSchema = object({
|
|
19538
|
+
deviceId: number(),
|
|
19539
|
+
/** Persisted event rows (motion + object + audio) for the camera. */
|
|
19540
|
+
rows: number().int(),
|
|
19541
|
+
/** Event-owned media bytes on disk for the camera. */
|
|
19542
|
+
bytes: number().int()
|
|
19543
|
+
});
|
|
19544
|
+
/** Aggregate event-store footprint: global totals + per-camera breakdown. */
|
|
19545
|
+
var EventStoreFootprintSchema = object({
|
|
19546
|
+
totalRows: number().int(),
|
|
19547
|
+
totalBytes: number().int(),
|
|
19548
|
+
devices: array(EventStoreDeviceFootprintSchema).readonly()
|
|
19549
|
+
});
|
|
19550
|
+
/** Per-kind counts returned by the event-prune / device-delete mutations. */
|
|
19551
|
+
var EventPruneCountsSchema = object({
|
|
19552
|
+
motion: number().int(),
|
|
19553
|
+
object: number().int(),
|
|
19554
|
+
audio: number().int()
|
|
19555
|
+
});
|
|
19183
19556
|
DeviceType.Camera, method(object({ deviceId: number() }), array(TrackSchema).readonly()), method(object({
|
|
19184
19557
|
deviceId: number(),
|
|
19185
19558
|
trackId: string()
|
|
@@ -19243,6 +19616,21 @@ DeviceType.Camera, method(object({ deviceId: number() }), array(TrackSchema).rea
|
|
|
19243
19616
|
}), {
|
|
19244
19617
|
kind: "mutation",
|
|
19245
19618
|
auth: "admin"
|
|
19619
|
+
}), method(object({}), EventStoreFootprintSchema, {
|
|
19620
|
+
kind: "query",
|
|
19621
|
+
auth: "admin"
|
|
19622
|
+
}), method(object({
|
|
19623
|
+
olderThanMs: number(),
|
|
19624
|
+
reason: OpsLogReasonSchema.optional()
|
|
19625
|
+
}), EventPruneCountsSchema, {
|
|
19626
|
+
kind: "mutation",
|
|
19627
|
+
auth: "admin"
|
|
19628
|
+
}), method(object({ deviceId: number() }), EventPruneCountsSchema, {
|
|
19629
|
+
kind: "mutation",
|
|
19630
|
+
auth: "admin"
|
|
19631
|
+
}), method(OpsLogQueryInputSchema, array(OpsLogEntrySchema).readonly(), {
|
|
19632
|
+
kind: "query",
|
|
19633
|
+
auth: "admin"
|
|
19246
19634
|
}), method(object({
|
|
19247
19635
|
eventId: string(),
|
|
19248
19636
|
kind: MediaFileKindEnum.optional()
|
|
@@ -19267,6 +19655,76 @@ DeviceType.Camera, method(object({ deviceId: number() }), array(TrackSchema).rea
|
|
|
19267
19655
|
eventId: string(),
|
|
19268
19656
|
timestamp: number()
|
|
19269
19657
|
});
|
|
19658
|
+
/**
|
|
19659
|
+
* Cap → event-kind mapping for the SENSOR / CONTROL cap families — the table
|
|
19660
|
+
* `pipeline-analytics.listEventKinds` uses to turn a linked device's bound
|
|
19661
|
+
* caps into per-camera event-kind descriptors.
|
|
19662
|
+
*
|
|
19663
|
+
* The descriptor DATA (color / iconId / labelKey / parentKind / category)
|
|
19664
|
+
* is NOT duplicated here — every entry is derived from the single
|
|
19665
|
+
* `EVENT_TAXONOMY` dictionary (`catalogs/event-taxonomy.ts`). This file owns
|
|
19666
|
+
* ONLY the cap-name → taxonomy-kind mapping. Adding a new eventful sensor /
|
|
19667
|
+
* control cap means adding one line here (and a taxonomy entry); the anti-
|
|
19668
|
+
* drift guard `scripts/check-event-kind-coverage.ts` fails the build if an
|
|
19669
|
+
* eventful cap is missing.
|
|
19670
|
+
*/
|
|
19671
|
+
/** Map a taxonomy `iconId` onto the legacy closed `EventKindIcon` enum. */
|
|
19672
|
+
var LEGACY_ICON = {
|
|
19673
|
+
motion: "motion",
|
|
19674
|
+
audio: "audio",
|
|
19675
|
+
person: "person",
|
|
19676
|
+
vehicle: "vehicle",
|
|
19677
|
+
animal: "animal",
|
|
19678
|
+
package: "package",
|
|
19679
|
+
door: "door",
|
|
19680
|
+
pir: "pir",
|
|
19681
|
+
smoke: "smoke",
|
|
19682
|
+
water: "water",
|
|
19683
|
+
button: "button",
|
|
19684
|
+
generic: "generic",
|
|
19685
|
+
gas: "smoke",
|
|
19686
|
+
vibration: "generic",
|
|
19687
|
+
tamper: "generic",
|
|
19688
|
+
presence: "person",
|
|
19689
|
+
lock: "generic",
|
|
19690
|
+
siren: "generic",
|
|
19691
|
+
switch: "generic",
|
|
19692
|
+
doorbell: "button"
|
|
19693
|
+
};
|
|
19694
|
+
function legacyIcon(iconId) {
|
|
19695
|
+
return LEGACY_ICON[iconId] ?? "generic";
|
|
19696
|
+
}
|
|
19697
|
+
/**
|
|
19698
|
+
* Cap name → taxonomy kind id. Covers EVERY eventful sensor / control cap.
|
|
19699
|
+
* The anti-drift guard cross-checks this against the eventful caps declared
|
|
19700
|
+
* in `packages/types/src/capabilities/*.cap.ts`.
|
|
19701
|
+
*/
|
|
19702
|
+
var CAP_TO_KIND = {
|
|
19703
|
+
contact: "contact",
|
|
19704
|
+
motion: "motion-sensor",
|
|
19705
|
+
smoke: "smoke",
|
|
19706
|
+
flood: "flood",
|
|
19707
|
+
gas: "gas",
|
|
19708
|
+
"carbon-monoxide": "carbon-monoxide",
|
|
19709
|
+
vibration: "vibration",
|
|
19710
|
+
tamper: "tamper",
|
|
19711
|
+
presence: "presence",
|
|
19712
|
+
"enum-sensor": "enum-sensor",
|
|
19713
|
+
"event-emitter": "device-event",
|
|
19714
|
+
"lock-control": "lock",
|
|
19715
|
+
switch: "switch",
|
|
19716
|
+
button: "button",
|
|
19717
|
+
doorbell: "doorbell"
|
|
19718
|
+
};
|
|
19719
|
+
function buildDescriptor(capName, kind) {
|
|
19720
|
+
const t = EVENT_TAXONOMY[kind];
|
|
19721
|
+
if (t === void 0) throw new Error(`EVENT_KIND_BY_CAP: cap '${capName}' maps to unknown taxonomy kind '${kind}'`);
|
|
19722
|
+
return {
|
|
19723
|
+
...t,
|
|
19724
|
+
icon: legacyIcon(t.iconId)
|
|
19725
|
+
};
|
|
19726
|
+
}
|
|
19727
|
+
Object.freeze(Object.fromEntries(Object.entries(CAP_TO_KIND).map(([capName, kind]) => [capName, buildDescriptor(capName, kind)])));
|
|
19270
19728
|
var CameraPipelineConfigSchema = object({
|
|
19271
19729
|
engine: PipelineEngineChoiceSchema.optional(),
|
|
19272
19730
|
steps: array(PipelineStepInputSchema).readonly(),
|
|
@@ -22476,13 +22934,29 @@ method(object({
|
|
|
22476
22934
|
}), method(object({ deviceId: number() }), RecordingStatusSchema, {
|
|
22477
22935
|
kind: "mutation",
|
|
22478
22936
|
auth: "admin"
|
|
22479
|
-
}), method(object({
|
|
22937
|
+
}), method(object({
|
|
22938
|
+
deviceId: number(),
|
|
22939
|
+
reason: OpsLogReasonSchema.optional()
|
|
22940
|
+
}), object({
|
|
22480
22941
|
floorMs: number().nullable(),
|
|
22481
22942
|
deletedBuckets: number().int(),
|
|
22482
22943
|
reclaimedBytes: number().int()
|
|
22483
22944
|
}), {
|
|
22484
22945
|
kind: "mutation",
|
|
22485
22946
|
auth: "admin"
|
|
22947
|
+
}), method(object({
|
|
22948
|
+
deviceId: number(),
|
|
22949
|
+
fromMs: number().optional(),
|
|
22950
|
+
toMs: number().optional()
|
|
22951
|
+
}), object({
|
|
22952
|
+
deletedBuckets: number().int(),
|
|
22953
|
+
reclaimedBytes: number().int()
|
|
22954
|
+
}), {
|
|
22955
|
+
kind: "mutation",
|
|
22956
|
+
auth: "admin"
|
|
22957
|
+
}), method(OpsLogQueryInputSchema, array(OpsLogEntrySchema).readonly(), {
|
|
22958
|
+
kind: "query",
|
|
22959
|
+
auth: "admin"
|
|
22486
22960
|
});
|
|
22487
22961
|
/**
|
|
22488
22962
|
* `recordingExport` cap — render a footage time range into a single downloadable
|
|
@@ -25604,6 +26078,12 @@ Object.freeze({
|
|
|
25604
26078
|
addonId: null,
|
|
25605
26079
|
access: "delete"
|
|
25606
26080
|
},
|
|
26081
|
+
"pipelineAnalytics.deleteDeviceEvents": {
|
|
26082
|
+
capName: "pipeline-analytics",
|
|
26083
|
+
capScope: "device",
|
|
26084
|
+
addonId: null,
|
|
26085
|
+
access: "delete"
|
|
26086
|
+
},
|
|
25607
26087
|
"pipelineAnalytics.deleteTracks": {
|
|
25608
26088
|
capName: "pipeline-analytics",
|
|
25609
26089
|
capScope: "device",
|
|
@@ -25634,6 +26114,12 @@ Object.freeze({
|
|
|
25634
26114
|
addonId: null,
|
|
25635
26115
|
access: "view"
|
|
25636
26116
|
},
|
|
26117
|
+
"pipelineAnalytics.getEventStoreFootprint": {
|
|
26118
|
+
capName: "pipeline-analytics",
|
|
26119
|
+
capScope: "device",
|
|
26120
|
+
addonId: null,
|
|
26121
|
+
access: "view"
|
|
26122
|
+
},
|
|
25637
26123
|
"pipelineAnalytics.getKeyEvents": {
|
|
25638
26124
|
capName: "pipeline-analytics",
|
|
25639
26125
|
capScope: "device",
|
|
@@ -25676,6 +26162,12 @@ Object.freeze({
|
|
|
25676
26162
|
addonId: null,
|
|
25677
26163
|
access: "view"
|
|
25678
26164
|
},
|
|
26165
|
+
"pipelineAnalytics.listOpsLog": {
|
|
26166
|
+
capName: "pipeline-analytics",
|
|
26167
|
+
capScope: "device",
|
|
26168
|
+
addonId: null,
|
|
26169
|
+
access: "view"
|
|
26170
|
+
},
|
|
25679
26171
|
"pipelineAnalytics.listRecentTracks": {
|
|
25680
26172
|
capName: "pipeline-analytics",
|
|
25681
26173
|
capScope: "device",
|
|
@@ -25688,6 +26180,12 @@ Object.freeze({
|
|
|
25688
26180
|
addonId: null,
|
|
25689
26181
|
access: "view"
|
|
25690
26182
|
},
|
|
26183
|
+
"pipelineAnalytics.pruneEvents": {
|
|
26184
|
+
capName: "pipeline-analytics",
|
|
26185
|
+
capScope: "device",
|
|
26186
|
+
addonId: null,
|
|
26187
|
+
access: "create"
|
|
26188
|
+
},
|
|
25691
26189
|
"pipelineAnalytics.pruneEventsBefore": {
|
|
25692
26190
|
capName: "pipeline-analytics",
|
|
25693
26191
|
capScope: "device",
|
|
@@ -26450,6 +26948,12 @@ Object.freeze({
|
|
|
26450
26948
|
addonId: null,
|
|
26451
26949
|
access: "create"
|
|
26452
26950
|
},
|
|
26951
|
+
"recording.deleteFootprint": {
|
|
26952
|
+
capName: "recording",
|
|
26953
|
+
capScope: "system",
|
|
26954
|
+
addonId: null,
|
|
26955
|
+
access: "delete"
|
|
26956
|
+
},
|
|
26453
26957
|
"recording.getAvailability": {
|
|
26454
26958
|
capName: "recording",
|
|
26455
26959
|
capScope: "system",
|
|
@@ -26480,6 +26984,12 @@ Object.freeze({
|
|
|
26480
26984
|
addonId: null,
|
|
26481
26985
|
access: "view"
|
|
26482
26986
|
},
|
|
26987
|
+
"recording.listOpsLog": {
|
|
26988
|
+
capName: "recording",
|
|
26989
|
+
capScope: "system",
|
|
26990
|
+
addonId: null,
|
|
26991
|
+
access: "view"
|
|
26992
|
+
},
|
|
26483
26993
|
"recording.locateSegment": {
|
|
26484
26994
|
capName: "recording",
|
|
26485
26995
|
capScope: "system",
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@camstack/addon-provider-dreo",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.23",
|
|
4
4
|
"description": "Dreo smart-device (fan / air-circulator / purifier / heater / humidifier) device-provider addon for CamStack — wraps the @apocaliss92/nodedreo Dreo cloud client (REST + WebSocket)",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"camstack",
|