@camstack/addon-provider-rademacher 0.1.12 → 0.1.14
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
|
@@ -8343,6 +8343,62 @@ var RecordingConfigSchema = object({
|
|
|
8343
8343
|
scrubThumbnails: ScrubThumbnailPresetSchema.optional()
|
|
8344
8344
|
});
|
|
8345
8345
|
/**
|
|
8346
|
+
* Ops-log — the durable, append-only operations audit shared by the
|
|
8347
|
+
* recordings and events management surfaces.
|
|
8348
|
+
*
|
|
8349
|
+
* ONE row shape is reused for both domains so a single "Activity" view can
|
|
8350
|
+
* merge the recorder's DurableState ring (recordings ops-log) and the
|
|
8351
|
+
* pipeline-analytics SQLite collection (events ops-log). Each row records a
|
|
8352
|
+
* management operation, WHY it ran (reason), and its measurable effect
|
|
8353
|
+
* (itemsAffected + bytesReclaimed). Writes are best-effort — a failed log must
|
|
8354
|
+
* never fail the operation it records.
|
|
8355
|
+
*/
|
|
8356
|
+
/** Which management domain the operation belongs to. */
|
|
8357
|
+
var OpsLogDomainSchema = _enum(["recording", "events"]);
|
|
8358
|
+
/** The kind of management operation performed. */
|
|
8359
|
+
var OpsLogOpSchema = _enum([
|
|
8360
|
+
"prune",
|
|
8361
|
+
"manual-delete",
|
|
8362
|
+
"rescan",
|
|
8363
|
+
"retention-run"
|
|
8364
|
+
]);
|
|
8365
|
+
/** Why the operation ran. */
|
|
8366
|
+
var OpsLogReasonSchema = _enum([
|
|
8367
|
+
"retention",
|
|
8368
|
+
"quota",
|
|
8369
|
+
"manual",
|
|
8370
|
+
"operator"
|
|
8371
|
+
]);
|
|
8372
|
+
/** One audit row, shared verbatim by both domains. */
|
|
8373
|
+
var OpsLogEntrySchema = object({
|
|
8374
|
+
/** Unique row id. */
|
|
8375
|
+
id: string(),
|
|
8376
|
+
/** Epoch ms the operation completed. */
|
|
8377
|
+
at: number(),
|
|
8378
|
+
domain: OpsLogDomainSchema,
|
|
8379
|
+
op: OpsLogOpSchema,
|
|
8380
|
+
reason: OpsLogReasonSchema,
|
|
8381
|
+
/** The camera the op targeted; null for a cluster/global op. */
|
|
8382
|
+
deviceId: number().nullable(),
|
|
8383
|
+
/** Node that performed the op (the log carries nodeId — no cross-node aggregation). */
|
|
8384
|
+
nodeId: string(),
|
|
8385
|
+
/** Buckets / rows deleted (op-specific unit). */
|
|
8386
|
+
itemsAffected: number(),
|
|
8387
|
+
/** Bytes reclaimed by the op (0 when not measurable). */
|
|
8388
|
+
bytesReclaimed: number(),
|
|
8389
|
+
/** Free-text detail (e.g. "floor moved to <ts>"); null when none. */
|
|
8390
|
+
detail: string().nullable(),
|
|
8391
|
+
/** Who/what triggered the op. */
|
|
8392
|
+
actor: string()
|
|
8393
|
+
});
|
|
8394
|
+
/** Shared query input for the per-domain `listOpsLog` cap methods. */
|
|
8395
|
+
var OpsLogQueryInputSchema = object({
|
|
8396
|
+
/** Restrict to a single camera; omit for every row. */
|
|
8397
|
+
deviceId: number().optional(),
|
|
8398
|
+
/** Max rows returned, newest-first. */
|
|
8399
|
+
limit: number().int().min(1).max(1e3).optional()
|
|
8400
|
+
});
|
|
8401
|
+
/**
|
|
8346
8402
|
* `StorageLocationType` — an addon-declared id that identifies the *kind* of
|
|
8347
8403
|
* storage a location serves. Defined here (not in `capabilities/storage.cap.ts`)
|
|
8348
8404
|
* so the persisted record schema and the consumer-facing cap can both consume it
|
|
@@ -8586,6 +8642,160 @@ var EncodeProfileSchema = object({
|
|
|
8586
8642
|
*/
|
|
8587
8643
|
outputArgs: array(string()).optional()
|
|
8588
8644
|
});
|
|
8645
|
+
var COCO_TO_MACRO = {
|
|
8646
|
+
mapping: {
|
|
8647
|
+
person: "person",
|
|
8648
|
+
bicycle: "vehicle",
|
|
8649
|
+
car: "vehicle",
|
|
8650
|
+
motorcycle: "vehicle",
|
|
8651
|
+
airplane: "vehicle",
|
|
8652
|
+
bus: "vehicle",
|
|
8653
|
+
train: "vehicle",
|
|
8654
|
+
truck: "vehicle",
|
|
8655
|
+
boat: "vehicle",
|
|
8656
|
+
bird: "animal",
|
|
8657
|
+
cat: "animal",
|
|
8658
|
+
dog: "animal",
|
|
8659
|
+
horse: "animal",
|
|
8660
|
+
sheep: "animal",
|
|
8661
|
+
cow: "animal",
|
|
8662
|
+
elephant: "animal",
|
|
8663
|
+
bear: "animal",
|
|
8664
|
+
zebra: "animal",
|
|
8665
|
+
giraffe: "animal",
|
|
8666
|
+
suitcase: "package",
|
|
8667
|
+
backpack: "package",
|
|
8668
|
+
handbag: "package"
|
|
8669
|
+
},
|
|
8670
|
+
preserveOriginal: false
|
|
8671
|
+
};
|
|
8672
|
+
var AUDIO_MACRO_LABELS = [
|
|
8673
|
+
{
|
|
8674
|
+
id: "speech",
|
|
8675
|
+
name: "Speech",
|
|
8676
|
+
icon: "🗣️"
|
|
8677
|
+
},
|
|
8678
|
+
{
|
|
8679
|
+
id: "scream",
|
|
8680
|
+
name: "Scream / Shout",
|
|
8681
|
+
icon: "😱"
|
|
8682
|
+
},
|
|
8683
|
+
{
|
|
8684
|
+
id: "crying",
|
|
8685
|
+
name: "Crying / Baby",
|
|
8686
|
+
icon: "😢"
|
|
8687
|
+
},
|
|
8688
|
+
{
|
|
8689
|
+
id: "laughter",
|
|
8690
|
+
name: "Laughter",
|
|
8691
|
+
icon: "😂"
|
|
8692
|
+
},
|
|
8693
|
+
{
|
|
8694
|
+
id: "music",
|
|
8695
|
+
name: "Music",
|
|
8696
|
+
icon: "🎵"
|
|
8697
|
+
},
|
|
8698
|
+
{
|
|
8699
|
+
id: "dog",
|
|
8700
|
+
name: "Dog",
|
|
8701
|
+
icon: "🐕"
|
|
8702
|
+
},
|
|
8703
|
+
{
|
|
8704
|
+
id: "cat",
|
|
8705
|
+
name: "Cat",
|
|
8706
|
+
icon: "🐈"
|
|
8707
|
+
},
|
|
8708
|
+
{
|
|
8709
|
+
id: "bird",
|
|
8710
|
+
name: "Bird",
|
|
8711
|
+
icon: "🐦"
|
|
8712
|
+
},
|
|
8713
|
+
{
|
|
8714
|
+
id: "animal",
|
|
8715
|
+
name: "Animal (other)",
|
|
8716
|
+
icon: "🐾"
|
|
8717
|
+
},
|
|
8718
|
+
{
|
|
8719
|
+
id: "alarm",
|
|
8720
|
+
name: "Alarm / Siren",
|
|
8721
|
+
icon: "🚨"
|
|
8722
|
+
},
|
|
8723
|
+
{
|
|
8724
|
+
id: "doorbell",
|
|
8725
|
+
name: "Doorbell / Knock",
|
|
8726
|
+
icon: "🔔"
|
|
8727
|
+
},
|
|
8728
|
+
{
|
|
8729
|
+
id: "glass_breaking",
|
|
8730
|
+
name: "Glass Breaking",
|
|
8731
|
+
icon: "💥"
|
|
8732
|
+
},
|
|
8733
|
+
{
|
|
8734
|
+
id: "gunshot",
|
|
8735
|
+
name: "Gunshot / Explosion",
|
|
8736
|
+
icon: "💣"
|
|
8737
|
+
},
|
|
8738
|
+
{
|
|
8739
|
+
id: "vehicle",
|
|
8740
|
+
name: "Vehicle",
|
|
8741
|
+
icon: "🚗"
|
|
8742
|
+
},
|
|
8743
|
+
{
|
|
8744
|
+
id: "siren",
|
|
8745
|
+
name: "Emergency Siren",
|
|
8746
|
+
icon: "🚑"
|
|
8747
|
+
},
|
|
8748
|
+
{
|
|
8749
|
+
id: "fire",
|
|
8750
|
+
name: "Fire / Smoke",
|
|
8751
|
+
icon: "🔥"
|
|
8752
|
+
},
|
|
8753
|
+
{
|
|
8754
|
+
id: "water",
|
|
8755
|
+
name: "Water",
|
|
8756
|
+
icon: "💧"
|
|
8757
|
+
},
|
|
8758
|
+
{
|
|
8759
|
+
id: "wind",
|
|
8760
|
+
name: "Wind / Weather",
|
|
8761
|
+
icon: "🌬️"
|
|
8762
|
+
},
|
|
8763
|
+
{
|
|
8764
|
+
id: "door",
|
|
8765
|
+
name: "Door",
|
|
8766
|
+
icon: "🚪"
|
|
8767
|
+
},
|
|
8768
|
+
{
|
|
8769
|
+
id: "footsteps",
|
|
8770
|
+
name: "Footsteps",
|
|
8771
|
+
icon: "👣"
|
|
8772
|
+
},
|
|
8773
|
+
{
|
|
8774
|
+
id: "crowd",
|
|
8775
|
+
name: "Crowd / Chatter",
|
|
8776
|
+
icon: "👥"
|
|
8777
|
+
},
|
|
8778
|
+
{
|
|
8779
|
+
id: "telephone",
|
|
8780
|
+
name: "Telephone",
|
|
8781
|
+
icon: "📞"
|
|
8782
|
+
},
|
|
8783
|
+
{
|
|
8784
|
+
id: "engine",
|
|
8785
|
+
name: "Engine / Motor",
|
|
8786
|
+
icon: "⚙️"
|
|
8787
|
+
},
|
|
8788
|
+
{
|
|
8789
|
+
id: "tools",
|
|
8790
|
+
name: "Tools / Construction",
|
|
8791
|
+
icon: "🔨"
|
|
8792
|
+
},
|
|
8793
|
+
{
|
|
8794
|
+
id: "silence",
|
|
8795
|
+
name: "Silence",
|
|
8796
|
+
icon: "🤫"
|
|
8797
|
+
}
|
|
8798
|
+
];
|
|
8589
8799
|
var YAMNET_TO_MACRO = {
|
|
8590
8800
|
mapping: {
|
|
8591
8801
|
Speech: "speech",
|
|
@@ -8852,6 +9062,125 @@ var _macroLookup = /* @__PURE__ */ new Map();
|
|
|
8852
9062
|
for (const [k, v] of Object.entries(YAMNET_TO_MACRO.mapping)) _macroLookup.set(k.toLowerCase(), v);
|
|
8853
9063
|
for (const [k, v] of Object.entries(APPLE_SA_TO_MACRO.mapping)) _macroLookup.set(k.toLowerCase(), v);
|
|
8854
9064
|
/**
|
|
9065
|
+
* Unified event-kind taxonomy — THE single source of truth for
|
|
9066
|
+
* `kind → { parentKind, category, level, color, iconId, labelKey, label,
|
|
9067
|
+
* icon }`.
|
|
9068
|
+
*
|
|
9069
|
+
* This dictionary folds together what used to be scattered across four
|
|
9070
|
+
* copies:
|
|
9071
|
+
* - `capabilities/sensor-event-kinds.ts` (sensor cap colors)
|
|
9072
|
+
* - `addon-post-analysis/.../services/event-kinds.ts`
|
|
9073
|
+
* (MOTION/PERSON/VEHICLE… _COLOR constants)
|
|
9074
|
+
* - `ui-library/composites/detection-colors.ts` (CLASS_COLORS)
|
|
9075
|
+
* - `addon-post-analysis/shared/frame/box-drawer.ts` (DEFAULT_COLOR)
|
|
9076
|
+
* - the COCO / audio class maps (macro ↔ sub relationships)
|
|
9077
|
+
*
|
|
9078
|
+
* The DATA (serializable — color/iconId/labelKey/parentKind) lives here in
|
|
9079
|
+
* `@camstack/types`. The UI-side mapping `iconId → lucide component` and
|
|
9080
|
+
* `labelKey → t()` lives in `@camstack/ui-library`. UIs never hardcode a
|
|
9081
|
+
* color or an icon: they read this dictionary (server descriptors carry the
|
|
9082
|
+
* fields inline; the client resolves color/icon/label from `iconId`/`kind`).
|
|
9083
|
+
*
|
|
9084
|
+
* Two levels only (v1 YAGNI): macro → sub. `person` is a leaf macro.
|
|
9085
|
+
*/
|
|
9086
|
+
var TAXONOMY_COLORS = {
|
|
9087
|
+
motion: "#f59e0b",
|
|
9088
|
+
audio: "#06b6d4",
|
|
9089
|
+
person: "#22c55e",
|
|
9090
|
+
vehicle: "#3b82f6",
|
|
9091
|
+
animal: "#f97316",
|
|
9092
|
+
package: "#a855f7",
|
|
9093
|
+
sensor: "#8b5cf6",
|
|
9094
|
+
control: "#10b981",
|
|
9095
|
+
genericDetection: "#64748b"
|
|
9096
|
+
};
|
|
9097
|
+
var DETECTION_SUB_COLORS = {
|
|
9098
|
+
car: "#f59e0b",
|
|
9099
|
+
truck: "#d97706",
|
|
9100
|
+
bus: "#b45309",
|
|
9101
|
+
motorcycle: "#eab308",
|
|
9102
|
+
bicycle: "#ca8a04",
|
|
9103
|
+
airplane: "#60a5fa",
|
|
9104
|
+
boat: "#2563eb",
|
|
9105
|
+
train: "#1d4ed8",
|
|
9106
|
+
bird: "#14b8a6",
|
|
9107
|
+
dog: "#84cc16",
|
|
9108
|
+
cat: "#f97316",
|
|
9109
|
+
horse: "#a16207",
|
|
9110
|
+
sheep: "#a3a3a3",
|
|
9111
|
+
cow: "#78716c",
|
|
9112
|
+
elephant: "#6b7280",
|
|
9113
|
+
bear: "#7c2d12",
|
|
9114
|
+
zebra: "#404040",
|
|
9115
|
+
giraffe: "#d4a373"
|
|
9116
|
+
};
|
|
9117
|
+
function titleCase(id) {
|
|
9118
|
+
return id.split(/[-_ ]/).filter((p) => p.length > 0).map((p) => p.charAt(0).toUpperCase() + p.slice(1)).join(" ");
|
|
9119
|
+
}
|
|
9120
|
+
var entries = /* @__PURE__ */ new Map();
|
|
9121
|
+
function macro(kind, category, color, iconId, label) {
|
|
9122
|
+
entries.set(kind, {
|
|
9123
|
+
kind,
|
|
9124
|
+
parentKind: null,
|
|
9125
|
+
level: "macro",
|
|
9126
|
+
category,
|
|
9127
|
+
color,
|
|
9128
|
+
iconId,
|
|
9129
|
+
labelKey: `eventKind.${kind}`,
|
|
9130
|
+
label
|
|
9131
|
+
});
|
|
9132
|
+
}
|
|
9133
|
+
function sub(kind, parentKind, category, color, iconId, label) {
|
|
9134
|
+
entries.set(kind, {
|
|
9135
|
+
kind,
|
|
9136
|
+
parentKind,
|
|
9137
|
+
level: "sub",
|
|
9138
|
+
category,
|
|
9139
|
+
color,
|
|
9140
|
+
iconId,
|
|
9141
|
+
labelKey: `eventKind.${kind}`,
|
|
9142
|
+
label
|
|
9143
|
+
});
|
|
9144
|
+
}
|
|
9145
|
+
macro("motion", "motion", TAXONOMY_COLORS.motion, "motion", "Motion");
|
|
9146
|
+
macro("audio", "audio", TAXONOMY_COLORS.audio, "audio", "Audio");
|
|
9147
|
+
macro("person", "detection", TAXONOMY_COLORS.person, "person", "Person");
|
|
9148
|
+
macro("vehicle", "detection", TAXONOMY_COLORS.vehicle, "vehicle", "Vehicle");
|
|
9149
|
+
macro("animal", "detection", TAXONOMY_COLORS.animal, "animal", "Animal");
|
|
9150
|
+
macro("package", "package", TAXONOMY_COLORS.package, "package", "Package");
|
|
9151
|
+
macro("sensor", "sensor", TAXONOMY_COLORS.sensor, "sensor", "Sensor");
|
|
9152
|
+
macro("control", "control", TAXONOMY_COLORS.control, "control", "Control");
|
|
9153
|
+
for (const [cocoClass, macroClass] of Object.entries(COCO_TO_MACRO.mapping)) {
|
|
9154
|
+
if (macroClass !== "vehicle" && macroClass !== "animal") continue;
|
|
9155
|
+
if (entries.has(cocoClass)) continue;
|
|
9156
|
+
sub(cocoClass, macroClass, "detection", DETECTION_SUB_COLORS[cocoClass] ?? TAXONOMY_COLORS.genericDetection, cocoClass, titleCase(cocoClass));
|
|
9157
|
+
}
|
|
9158
|
+
sub("package-delivered", "package", "package", TAXONOMY_COLORS.package, "package", "Package delivered");
|
|
9159
|
+
sub("package-picked-up", "package", "package", TAXONOMY_COLORS.package, "package", "Package picked up");
|
|
9160
|
+
sub("contact", "sensor", "sensor", "#f59e0b", "door", "Contact");
|
|
9161
|
+
sub("motion-sensor", "sensor", "sensor", TAXONOMY_COLORS.sensor, "pir", "Motion sensor");
|
|
9162
|
+
sub("smoke", "sensor", "sensor", "#ef4444", "smoke", "Smoke");
|
|
9163
|
+
sub("flood", "sensor", "sensor", "#3b82f6", "water", "Water leak");
|
|
9164
|
+
sub("gas", "sensor", "sensor", "#ef4444", "gas", "Gas");
|
|
9165
|
+
sub("carbon-monoxide", "sensor", "sensor", "#dc2626", "smoke", "Carbon monoxide");
|
|
9166
|
+
sub("vibration", "sensor", "sensor", "#eab308", "vibration", "Vibration");
|
|
9167
|
+
sub("tamper", "sensor", "sensor", "#f97316", "tamper", "Tamper");
|
|
9168
|
+
sub("presence", "sensor", "sensor", "#22c55e", "presence", "Presence");
|
|
9169
|
+
sub("enum-sensor", "sensor", "sensor", TAXONOMY_COLORS.sensor, "generic", "Sensor state");
|
|
9170
|
+
sub("device-event", "sensor", "sensor", "#10b981", "button", "Device event");
|
|
9171
|
+
sub("lock", "control", "control", "#0ea5e9", "lock", "Lock");
|
|
9172
|
+
sub("switch", "control", "control", TAXONOMY_COLORS.control, "switch", "Switch");
|
|
9173
|
+
sub("siren", "control", "control", "#dc2626", "siren", "Siren");
|
|
9174
|
+
sub("button", "control", "control", "#10b981", "button", "Button");
|
|
9175
|
+
sub("doorbell", "control", "control", "#a855f7", "doorbell", "Doorbell");
|
|
9176
|
+
for (const l of AUDIO_MACRO_LABELS) {
|
|
9177
|
+
const kind = `audio-${l.id}`;
|
|
9178
|
+
if (entries.has(kind)) continue;
|
|
9179
|
+
sub(kind, "audio", "audio", TAXONOMY_COLORS.audio, kind, l.name);
|
|
9180
|
+
}
|
|
9181
|
+
/** The complete taxonomy dictionary, keyed by kind. */
|
|
9182
|
+
var EVENT_TAXONOMY = Object.freeze(Object.fromEntries(entries));
|
|
9183
|
+
/**
|
|
8855
9184
|
* Error types for the safe expression engine. Two distinct classes so callers
|
|
8856
9185
|
* can tell a compile-time (grammar) failure from a runtime (evaluation)
|
|
8857
9186
|
* failure — both are non-fatal to the host: read paths degrade to "skip link".
|
|
@@ -15806,9 +16135,10 @@ var DEVICE_LOCAL_STATE_CAPS = {
|
|
|
15806
16135
|
* `package` backs the package-drop detector — a package zone is a
|
|
15807
16136
|
* `ZoneRule` on the `'package'` stage referencing drawn polygons
|
|
15808
16137
|
* (see docs/superpowers/specs/2026-07-17-package-zones-design.md §3.1).
|
|
15809
|
-
* The orchestrator provider
|
|
15810
|
-
*
|
|
15811
|
-
* consumers read
|
|
16138
|
+
* The orchestrator provider writes this stage as a first-class slice
|
|
16139
|
+
* (Phase 4): every mutation mirrors the full `{motion, detection,
|
|
16140
|
+
* package}` shape, so consumers read the current package rules directly
|
|
16141
|
+
* off `device.state.zoneRules.value.package`.
|
|
15812
16142
|
*/
|
|
15813
16143
|
runtimeState: object({
|
|
15814
16144
|
motion: array(ZoneRuleSchema).readonly(),
|
|
@@ -19783,17 +20113,30 @@ var EventKindCategorySchema = _enum([
|
|
|
19783
20113
|
"audio",
|
|
19784
20114
|
"detection",
|
|
19785
20115
|
"sensor",
|
|
20116
|
+
"control",
|
|
19786
20117
|
"custom",
|
|
19787
20118
|
"package"
|
|
19788
20119
|
]);
|
|
20120
|
+
/** Taxonomy level — macro (timeline lane) vs sub (events-page leaf). */
|
|
20121
|
+
var EventKindLevelSchema = _enum(["macro", "sub"]);
|
|
19789
20122
|
var EventKindDescriptorSchema = object({
|
|
19790
|
-
/** Stable kind id (e.g. 'motion', '
|
|
20123
|
+
/** Stable kind id (e.g. 'motion', 'vehicle', 'car', 'lock'). */
|
|
19791
20124
|
kind: string(),
|
|
20125
|
+
/** i18n key resolved on the UI side; `label` is the English fallback. */
|
|
20126
|
+
labelKey: string(),
|
|
20127
|
+
/** English fallback label (kept for clients that don't translate). */
|
|
19792
20128
|
label: string(),
|
|
19793
20129
|
/** Hex color for timeline/legend rendering. */
|
|
19794
20130
|
color: string(),
|
|
20131
|
+
/** Dictionary id → lucide component on the UI side. */
|
|
20132
|
+
iconId: string(),
|
|
20133
|
+
/** Legacy closed-vocab glyph — fallback for `iconId`. */
|
|
19795
20134
|
icon: EventKindIconSchema,
|
|
19796
20135
|
category: EventKindCategorySchema,
|
|
20136
|
+
/** Macro parent for this kind ('car' → 'vehicle'); null for a macro. */
|
|
20137
|
+
parentKind: string().nullable(),
|
|
20138
|
+
/** Derived from `parentKind`, explicit for the client tree. */
|
|
20139
|
+
level: EventKindLevelSchema,
|
|
19797
20140
|
/** Which cap + device contributes this kind. For built-ins the camera
|
|
19798
20141
|
* itself; for sensor kinds the LINKED source device. */
|
|
19799
20142
|
source: object({
|
|
@@ -19866,11 +20209,21 @@ var TrackAudioLabelSchema = object({
|
|
|
19866
20209
|
firstAt: number(),
|
|
19867
20210
|
lastAt: number()
|
|
19868
20211
|
});
|
|
20212
|
+
/**
|
|
20213
|
+
* How a track was produced. `pipeline` (default / absent) = the spatial
|
|
20214
|
+
* detection+tracking pipeline. `sensor` = a SYNTHETIC track projected from a
|
|
20215
|
+
* linked sensor/control state change (no positions; carries a snapshot). The
|
|
20216
|
+
* spatial subsystems (tracker association, occupancy count, re-id/embedding,
|
|
20217
|
+
* resurrection) MUST skip `sensor` tracks — they have no bbox trajectory.
|
|
20218
|
+
*/
|
|
20219
|
+
var TrackSourceSchema = _enum(["pipeline", "sensor"]);
|
|
19869
20220
|
var TrackSchema = object({
|
|
19870
20221
|
trackId: string(),
|
|
19871
20222
|
deviceId: number(),
|
|
19872
20223
|
className: string(),
|
|
19873
20224
|
label: string().optional(),
|
|
20225
|
+
/** Track provenance. Absent ⇒ `pipeline` (legacy rows). */
|
|
20226
|
+
source: TrackSourceSchema.optional(),
|
|
19874
20227
|
firstSeen: number(),
|
|
19875
20228
|
lastSeen: number(),
|
|
19876
20229
|
/** Frame-rate position history (subject to maxPositionHistory cap). */
|
|
@@ -20125,6 +20478,26 @@ var TrackCascadeCountsSchema = object({
|
|
|
20125
20478
|
/** Per-track CLIP search vectors removed (best-effort). */
|
|
20126
20479
|
embeddings: number().int()
|
|
20127
20480
|
});
|
|
20481
|
+
/** Event-store footprint for one camera. */
|
|
20482
|
+
var EventStoreDeviceFootprintSchema = object({
|
|
20483
|
+
deviceId: number(),
|
|
20484
|
+
/** Persisted event rows (motion + object + audio) for the camera. */
|
|
20485
|
+
rows: number().int(),
|
|
20486
|
+
/** Event-owned media bytes on disk for the camera. */
|
|
20487
|
+
bytes: number().int()
|
|
20488
|
+
});
|
|
20489
|
+
/** Aggregate event-store footprint: global totals + per-camera breakdown. */
|
|
20490
|
+
var EventStoreFootprintSchema = object({
|
|
20491
|
+
totalRows: number().int(),
|
|
20492
|
+
totalBytes: number().int(),
|
|
20493
|
+
devices: array(EventStoreDeviceFootprintSchema).readonly()
|
|
20494
|
+
});
|
|
20495
|
+
/** Per-kind counts returned by the event-prune / device-delete mutations. */
|
|
20496
|
+
var EventPruneCountsSchema = object({
|
|
20497
|
+
motion: number().int(),
|
|
20498
|
+
object: number().int(),
|
|
20499
|
+
audio: number().int()
|
|
20500
|
+
});
|
|
20128
20501
|
DeviceType.Camera, method(object({ deviceId: number() }), array(TrackSchema).readonly()), method(object({
|
|
20129
20502
|
deviceId: number(),
|
|
20130
20503
|
trackId: string()
|
|
@@ -20188,6 +20561,21 @@ DeviceType.Camera, method(object({ deviceId: number() }), array(TrackSchema).rea
|
|
|
20188
20561
|
}), {
|
|
20189
20562
|
kind: "mutation",
|
|
20190
20563
|
auth: "admin"
|
|
20564
|
+
}), method(object({}), EventStoreFootprintSchema, {
|
|
20565
|
+
kind: "query",
|
|
20566
|
+
auth: "admin"
|
|
20567
|
+
}), method(object({
|
|
20568
|
+
olderThanMs: number(),
|
|
20569
|
+
reason: OpsLogReasonSchema.optional()
|
|
20570
|
+
}), EventPruneCountsSchema, {
|
|
20571
|
+
kind: "mutation",
|
|
20572
|
+
auth: "admin"
|
|
20573
|
+
}), method(object({ deviceId: number() }), EventPruneCountsSchema, {
|
|
20574
|
+
kind: "mutation",
|
|
20575
|
+
auth: "admin"
|
|
20576
|
+
}), method(OpsLogQueryInputSchema, array(OpsLogEntrySchema).readonly(), {
|
|
20577
|
+
kind: "query",
|
|
20578
|
+
auth: "admin"
|
|
20191
20579
|
}), method(object({
|
|
20192
20580
|
eventId: string(),
|
|
20193
20581
|
kind: MediaFileKindEnum.optional()
|
|
@@ -20212,6 +20600,76 @@ DeviceType.Camera, method(object({ deviceId: number() }), array(TrackSchema).rea
|
|
|
20212
20600
|
eventId: string(),
|
|
20213
20601
|
timestamp: number()
|
|
20214
20602
|
});
|
|
20603
|
+
/**
|
|
20604
|
+
* Cap → event-kind mapping for the SENSOR / CONTROL cap families — the table
|
|
20605
|
+
* `pipeline-analytics.listEventKinds` uses to turn a linked device's bound
|
|
20606
|
+
* caps into per-camera event-kind descriptors.
|
|
20607
|
+
*
|
|
20608
|
+
* The descriptor DATA (color / iconId / labelKey / parentKind / category)
|
|
20609
|
+
* is NOT duplicated here — every entry is derived from the single
|
|
20610
|
+
* `EVENT_TAXONOMY` dictionary (`catalogs/event-taxonomy.ts`). This file owns
|
|
20611
|
+
* ONLY the cap-name → taxonomy-kind mapping. Adding a new eventful sensor /
|
|
20612
|
+
* control cap means adding one line here (and a taxonomy entry); the anti-
|
|
20613
|
+
* drift guard `scripts/check-event-kind-coverage.ts` fails the build if an
|
|
20614
|
+
* eventful cap is missing.
|
|
20615
|
+
*/
|
|
20616
|
+
/** Map a taxonomy `iconId` onto the legacy closed `EventKindIcon` enum. */
|
|
20617
|
+
var LEGACY_ICON = {
|
|
20618
|
+
motion: "motion",
|
|
20619
|
+
audio: "audio",
|
|
20620
|
+
person: "person",
|
|
20621
|
+
vehicle: "vehicle",
|
|
20622
|
+
animal: "animal",
|
|
20623
|
+
package: "package",
|
|
20624
|
+
door: "door",
|
|
20625
|
+
pir: "pir",
|
|
20626
|
+
smoke: "smoke",
|
|
20627
|
+
water: "water",
|
|
20628
|
+
button: "button",
|
|
20629
|
+
generic: "generic",
|
|
20630
|
+
gas: "smoke",
|
|
20631
|
+
vibration: "generic",
|
|
20632
|
+
tamper: "generic",
|
|
20633
|
+
presence: "person",
|
|
20634
|
+
lock: "generic",
|
|
20635
|
+
siren: "generic",
|
|
20636
|
+
switch: "generic",
|
|
20637
|
+
doorbell: "button"
|
|
20638
|
+
};
|
|
20639
|
+
function legacyIcon(iconId) {
|
|
20640
|
+
return LEGACY_ICON[iconId] ?? "generic";
|
|
20641
|
+
}
|
|
20642
|
+
/**
|
|
20643
|
+
* Cap name → taxonomy kind id. Covers EVERY eventful sensor / control cap.
|
|
20644
|
+
* The anti-drift guard cross-checks this against the eventful caps declared
|
|
20645
|
+
* in `packages/types/src/capabilities/*.cap.ts`.
|
|
20646
|
+
*/
|
|
20647
|
+
var CAP_TO_KIND = {
|
|
20648
|
+
contact: "contact",
|
|
20649
|
+
motion: "motion-sensor",
|
|
20650
|
+
smoke: "smoke",
|
|
20651
|
+
flood: "flood",
|
|
20652
|
+
gas: "gas",
|
|
20653
|
+
"carbon-monoxide": "carbon-monoxide",
|
|
20654
|
+
vibration: "vibration",
|
|
20655
|
+
tamper: "tamper",
|
|
20656
|
+
presence: "presence",
|
|
20657
|
+
"enum-sensor": "enum-sensor",
|
|
20658
|
+
"event-emitter": "device-event",
|
|
20659
|
+
"lock-control": "lock",
|
|
20660
|
+
switch: "switch",
|
|
20661
|
+
button: "button",
|
|
20662
|
+
doorbell: "doorbell"
|
|
20663
|
+
};
|
|
20664
|
+
function buildDescriptor(capName, kind) {
|
|
20665
|
+
const t = EVENT_TAXONOMY[kind];
|
|
20666
|
+
if (t === void 0) throw new Error(`EVENT_KIND_BY_CAP: cap '${capName}' maps to unknown taxonomy kind '${kind}'`);
|
|
20667
|
+
return {
|
|
20668
|
+
...t,
|
|
20669
|
+
icon: legacyIcon(t.iconId)
|
|
20670
|
+
};
|
|
20671
|
+
}
|
|
20672
|
+
Object.freeze(Object.fromEntries(Object.entries(CAP_TO_KIND).map(([capName, kind]) => [capName, buildDescriptor(capName, kind)])));
|
|
20215
20673
|
var CameraPipelineConfigSchema = object({
|
|
20216
20674
|
engine: PipelineEngineChoiceSchema.optional(),
|
|
20217
20675
|
steps: array(PipelineStepInputSchema).readonly(),
|
|
@@ -23421,13 +23879,29 @@ method(object({
|
|
|
23421
23879
|
}), method(object({ deviceId: number() }), RecordingStatusSchema, {
|
|
23422
23880
|
kind: "mutation",
|
|
23423
23881
|
auth: "admin"
|
|
23424
|
-
}), method(object({
|
|
23882
|
+
}), method(object({
|
|
23883
|
+
deviceId: number(),
|
|
23884
|
+
reason: OpsLogReasonSchema.optional()
|
|
23885
|
+
}), object({
|
|
23425
23886
|
floorMs: number().nullable(),
|
|
23426
23887
|
deletedBuckets: number().int(),
|
|
23427
23888
|
reclaimedBytes: number().int()
|
|
23428
23889
|
}), {
|
|
23429
23890
|
kind: "mutation",
|
|
23430
23891
|
auth: "admin"
|
|
23892
|
+
}), method(object({
|
|
23893
|
+
deviceId: number(),
|
|
23894
|
+
fromMs: number().optional(),
|
|
23895
|
+
toMs: number().optional()
|
|
23896
|
+
}), object({
|
|
23897
|
+
deletedBuckets: number().int(),
|
|
23898
|
+
reclaimedBytes: number().int()
|
|
23899
|
+
}), {
|
|
23900
|
+
kind: "mutation",
|
|
23901
|
+
auth: "admin"
|
|
23902
|
+
}), method(OpsLogQueryInputSchema, array(OpsLogEntrySchema).readonly(), {
|
|
23903
|
+
kind: "query",
|
|
23904
|
+
auth: "admin"
|
|
23431
23905
|
});
|
|
23432
23906
|
/**
|
|
23433
23907
|
* `recordingExport` cap — render a footage time range into a single downloadable
|
|
@@ -26549,6 +27023,12 @@ Object.freeze({
|
|
|
26549
27023
|
addonId: null,
|
|
26550
27024
|
access: "delete"
|
|
26551
27025
|
},
|
|
27026
|
+
"pipelineAnalytics.deleteDeviceEvents": {
|
|
27027
|
+
capName: "pipeline-analytics",
|
|
27028
|
+
capScope: "device",
|
|
27029
|
+
addonId: null,
|
|
27030
|
+
access: "delete"
|
|
27031
|
+
},
|
|
26552
27032
|
"pipelineAnalytics.deleteTracks": {
|
|
26553
27033
|
capName: "pipeline-analytics",
|
|
26554
27034
|
capScope: "device",
|
|
@@ -26579,6 +27059,12 @@ Object.freeze({
|
|
|
26579
27059
|
addonId: null,
|
|
26580
27060
|
access: "view"
|
|
26581
27061
|
},
|
|
27062
|
+
"pipelineAnalytics.getEventStoreFootprint": {
|
|
27063
|
+
capName: "pipeline-analytics",
|
|
27064
|
+
capScope: "device",
|
|
27065
|
+
addonId: null,
|
|
27066
|
+
access: "view"
|
|
27067
|
+
},
|
|
26582
27068
|
"pipelineAnalytics.getKeyEvents": {
|
|
26583
27069
|
capName: "pipeline-analytics",
|
|
26584
27070
|
capScope: "device",
|
|
@@ -26621,6 +27107,12 @@ Object.freeze({
|
|
|
26621
27107
|
addonId: null,
|
|
26622
27108
|
access: "view"
|
|
26623
27109
|
},
|
|
27110
|
+
"pipelineAnalytics.listOpsLog": {
|
|
27111
|
+
capName: "pipeline-analytics",
|
|
27112
|
+
capScope: "device",
|
|
27113
|
+
addonId: null,
|
|
27114
|
+
access: "view"
|
|
27115
|
+
},
|
|
26624
27116
|
"pipelineAnalytics.listRecentTracks": {
|
|
26625
27117
|
capName: "pipeline-analytics",
|
|
26626
27118
|
capScope: "device",
|
|
@@ -26633,6 +27125,12 @@ Object.freeze({
|
|
|
26633
27125
|
addonId: null,
|
|
26634
27126
|
access: "view"
|
|
26635
27127
|
},
|
|
27128
|
+
"pipelineAnalytics.pruneEvents": {
|
|
27129
|
+
capName: "pipeline-analytics",
|
|
27130
|
+
capScope: "device",
|
|
27131
|
+
addonId: null,
|
|
27132
|
+
access: "create"
|
|
27133
|
+
},
|
|
26636
27134
|
"pipelineAnalytics.pruneEventsBefore": {
|
|
26637
27135
|
capName: "pipeline-analytics",
|
|
26638
27136
|
capScope: "device",
|
|
@@ -27395,6 +27893,12 @@ Object.freeze({
|
|
|
27395
27893
|
addonId: null,
|
|
27396
27894
|
access: "create"
|
|
27397
27895
|
},
|
|
27896
|
+
"recording.deleteFootprint": {
|
|
27897
|
+
capName: "recording",
|
|
27898
|
+
capScope: "system",
|
|
27899
|
+
addonId: null,
|
|
27900
|
+
access: "delete"
|
|
27901
|
+
},
|
|
27398
27902
|
"recording.getAvailability": {
|
|
27399
27903
|
capName: "recording",
|
|
27400
27904
|
capScope: "system",
|
|
@@ -27425,6 +27929,12 @@ Object.freeze({
|
|
|
27425
27929
|
addonId: null,
|
|
27426
27930
|
access: "view"
|
|
27427
27931
|
},
|
|
27932
|
+
"recording.listOpsLog": {
|
|
27933
|
+
capName: "recording",
|
|
27934
|
+
capScope: "system",
|
|
27935
|
+
addonId: null,
|
|
27936
|
+
access: "view"
|
|
27937
|
+
},
|
|
27428
27938
|
"recording.locateSegment": {
|
|
27429
27939
|
capName: "recording",
|
|
27430
27940
|
capScope: "system",
|
package/dist/addon.mjs
CHANGED
|
@@ -8342,6 +8342,62 @@ var RecordingConfigSchema = object({
|
|
|
8342
8342
|
scrubThumbnails: ScrubThumbnailPresetSchema.optional()
|
|
8343
8343
|
});
|
|
8344
8344
|
/**
|
|
8345
|
+
* Ops-log — the durable, append-only operations audit shared by the
|
|
8346
|
+
* recordings and events management surfaces.
|
|
8347
|
+
*
|
|
8348
|
+
* ONE row shape is reused for both domains so a single "Activity" view can
|
|
8349
|
+
* merge the recorder's DurableState ring (recordings ops-log) and the
|
|
8350
|
+
* pipeline-analytics SQLite collection (events ops-log). Each row records a
|
|
8351
|
+
* management operation, WHY it ran (reason), and its measurable effect
|
|
8352
|
+
* (itemsAffected + bytesReclaimed). Writes are best-effort — a failed log must
|
|
8353
|
+
* never fail the operation it records.
|
|
8354
|
+
*/
|
|
8355
|
+
/** Which management domain the operation belongs to. */
|
|
8356
|
+
var OpsLogDomainSchema = _enum(["recording", "events"]);
|
|
8357
|
+
/** The kind of management operation performed. */
|
|
8358
|
+
var OpsLogOpSchema = _enum([
|
|
8359
|
+
"prune",
|
|
8360
|
+
"manual-delete",
|
|
8361
|
+
"rescan",
|
|
8362
|
+
"retention-run"
|
|
8363
|
+
]);
|
|
8364
|
+
/** Why the operation ran. */
|
|
8365
|
+
var OpsLogReasonSchema = _enum([
|
|
8366
|
+
"retention",
|
|
8367
|
+
"quota",
|
|
8368
|
+
"manual",
|
|
8369
|
+
"operator"
|
|
8370
|
+
]);
|
|
8371
|
+
/** One audit row, shared verbatim by both domains. */
|
|
8372
|
+
var OpsLogEntrySchema = object({
|
|
8373
|
+
/** Unique row id. */
|
|
8374
|
+
id: string(),
|
|
8375
|
+
/** Epoch ms the operation completed. */
|
|
8376
|
+
at: number(),
|
|
8377
|
+
domain: OpsLogDomainSchema,
|
|
8378
|
+
op: OpsLogOpSchema,
|
|
8379
|
+
reason: OpsLogReasonSchema,
|
|
8380
|
+
/** The camera the op targeted; null for a cluster/global op. */
|
|
8381
|
+
deviceId: number().nullable(),
|
|
8382
|
+
/** Node that performed the op (the log carries nodeId — no cross-node aggregation). */
|
|
8383
|
+
nodeId: string(),
|
|
8384
|
+
/** Buckets / rows deleted (op-specific unit). */
|
|
8385
|
+
itemsAffected: number(),
|
|
8386
|
+
/** Bytes reclaimed by the op (0 when not measurable). */
|
|
8387
|
+
bytesReclaimed: number(),
|
|
8388
|
+
/** Free-text detail (e.g. "floor moved to <ts>"); null when none. */
|
|
8389
|
+
detail: string().nullable(),
|
|
8390
|
+
/** Who/what triggered the op. */
|
|
8391
|
+
actor: string()
|
|
8392
|
+
});
|
|
8393
|
+
/** Shared query input for the per-domain `listOpsLog` cap methods. */
|
|
8394
|
+
var OpsLogQueryInputSchema = object({
|
|
8395
|
+
/** Restrict to a single camera; omit for every row. */
|
|
8396
|
+
deviceId: number().optional(),
|
|
8397
|
+
/** Max rows returned, newest-first. */
|
|
8398
|
+
limit: number().int().min(1).max(1e3).optional()
|
|
8399
|
+
});
|
|
8400
|
+
/**
|
|
8345
8401
|
* `StorageLocationType` — an addon-declared id that identifies the *kind* of
|
|
8346
8402
|
* storage a location serves. Defined here (not in `capabilities/storage.cap.ts`)
|
|
8347
8403
|
* so the persisted record schema and the consumer-facing cap can both consume it
|
|
@@ -8585,6 +8641,160 @@ var EncodeProfileSchema = object({
|
|
|
8585
8641
|
*/
|
|
8586
8642
|
outputArgs: array(string()).optional()
|
|
8587
8643
|
});
|
|
8644
|
+
var COCO_TO_MACRO = {
|
|
8645
|
+
mapping: {
|
|
8646
|
+
person: "person",
|
|
8647
|
+
bicycle: "vehicle",
|
|
8648
|
+
car: "vehicle",
|
|
8649
|
+
motorcycle: "vehicle",
|
|
8650
|
+
airplane: "vehicle",
|
|
8651
|
+
bus: "vehicle",
|
|
8652
|
+
train: "vehicle",
|
|
8653
|
+
truck: "vehicle",
|
|
8654
|
+
boat: "vehicle",
|
|
8655
|
+
bird: "animal",
|
|
8656
|
+
cat: "animal",
|
|
8657
|
+
dog: "animal",
|
|
8658
|
+
horse: "animal",
|
|
8659
|
+
sheep: "animal",
|
|
8660
|
+
cow: "animal",
|
|
8661
|
+
elephant: "animal",
|
|
8662
|
+
bear: "animal",
|
|
8663
|
+
zebra: "animal",
|
|
8664
|
+
giraffe: "animal",
|
|
8665
|
+
suitcase: "package",
|
|
8666
|
+
backpack: "package",
|
|
8667
|
+
handbag: "package"
|
|
8668
|
+
},
|
|
8669
|
+
preserveOriginal: false
|
|
8670
|
+
};
|
|
8671
|
+
var AUDIO_MACRO_LABELS = [
|
|
8672
|
+
{
|
|
8673
|
+
id: "speech",
|
|
8674
|
+
name: "Speech",
|
|
8675
|
+
icon: "🗣️"
|
|
8676
|
+
},
|
|
8677
|
+
{
|
|
8678
|
+
id: "scream",
|
|
8679
|
+
name: "Scream / Shout",
|
|
8680
|
+
icon: "😱"
|
|
8681
|
+
},
|
|
8682
|
+
{
|
|
8683
|
+
id: "crying",
|
|
8684
|
+
name: "Crying / Baby",
|
|
8685
|
+
icon: "😢"
|
|
8686
|
+
},
|
|
8687
|
+
{
|
|
8688
|
+
id: "laughter",
|
|
8689
|
+
name: "Laughter",
|
|
8690
|
+
icon: "😂"
|
|
8691
|
+
},
|
|
8692
|
+
{
|
|
8693
|
+
id: "music",
|
|
8694
|
+
name: "Music",
|
|
8695
|
+
icon: "🎵"
|
|
8696
|
+
},
|
|
8697
|
+
{
|
|
8698
|
+
id: "dog",
|
|
8699
|
+
name: "Dog",
|
|
8700
|
+
icon: "🐕"
|
|
8701
|
+
},
|
|
8702
|
+
{
|
|
8703
|
+
id: "cat",
|
|
8704
|
+
name: "Cat",
|
|
8705
|
+
icon: "🐈"
|
|
8706
|
+
},
|
|
8707
|
+
{
|
|
8708
|
+
id: "bird",
|
|
8709
|
+
name: "Bird",
|
|
8710
|
+
icon: "🐦"
|
|
8711
|
+
},
|
|
8712
|
+
{
|
|
8713
|
+
id: "animal",
|
|
8714
|
+
name: "Animal (other)",
|
|
8715
|
+
icon: "🐾"
|
|
8716
|
+
},
|
|
8717
|
+
{
|
|
8718
|
+
id: "alarm",
|
|
8719
|
+
name: "Alarm / Siren",
|
|
8720
|
+
icon: "🚨"
|
|
8721
|
+
},
|
|
8722
|
+
{
|
|
8723
|
+
id: "doorbell",
|
|
8724
|
+
name: "Doorbell / Knock",
|
|
8725
|
+
icon: "🔔"
|
|
8726
|
+
},
|
|
8727
|
+
{
|
|
8728
|
+
id: "glass_breaking",
|
|
8729
|
+
name: "Glass Breaking",
|
|
8730
|
+
icon: "💥"
|
|
8731
|
+
},
|
|
8732
|
+
{
|
|
8733
|
+
id: "gunshot",
|
|
8734
|
+
name: "Gunshot / Explosion",
|
|
8735
|
+
icon: "💣"
|
|
8736
|
+
},
|
|
8737
|
+
{
|
|
8738
|
+
id: "vehicle",
|
|
8739
|
+
name: "Vehicle",
|
|
8740
|
+
icon: "🚗"
|
|
8741
|
+
},
|
|
8742
|
+
{
|
|
8743
|
+
id: "siren",
|
|
8744
|
+
name: "Emergency Siren",
|
|
8745
|
+
icon: "🚑"
|
|
8746
|
+
},
|
|
8747
|
+
{
|
|
8748
|
+
id: "fire",
|
|
8749
|
+
name: "Fire / Smoke",
|
|
8750
|
+
icon: "🔥"
|
|
8751
|
+
},
|
|
8752
|
+
{
|
|
8753
|
+
id: "water",
|
|
8754
|
+
name: "Water",
|
|
8755
|
+
icon: "💧"
|
|
8756
|
+
},
|
|
8757
|
+
{
|
|
8758
|
+
id: "wind",
|
|
8759
|
+
name: "Wind / Weather",
|
|
8760
|
+
icon: "🌬️"
|
|
8761
|
+
},
|
|
8762
|
+
{
|
|
8763
|
+
id: "door",
|
|
8764
|
+
name: "Door",
|
|
8765
|
+
icon: "🚪"
|
|
8766
|
+
},
|
|
8767
|
+
{
|
|
8768
|
+
id: "footsteps",
|
|
8769
|
+
name: "Footsteps",
|
|
8770
|
+
icon: "👣"
|
|
8771
|
+
},
|
|
8772
|
+
{
|
|
8773
|
+
id: "crowd",
|
|
8774
|
+
name: "Crowd / Chatter",
|
|
8775
|
+
icon: "👥"
|
|
8776
|
+
},
|
|
8777
|
+
{
|
|
8778
|
+
id: "telephone",
|
|
8779
|
+
name: "Telephone",
|
|
8780
|
+
icon: "📞"
|
|
8781
|
+
},
|
|
8782
|
+
{
|
|
8783
|
+
id: "engine",
|
|
8784
|
+
name: "Engine / Motor",
|
|
8785
|
+
icon: "⚙️"
|
|
8786
|
+
},
|
|
8787
|
+
{
|
|
8788
|
+
id: "tools",
|
|
8789
|
+
name: "Tools / Construction",
|
|
8790
|
+
icon: "🔨"
|
|
8791
|
+
},
|
|
8792
|
+
{
|
|
8793
|
+
id: "silence",
|
|
8794
|
+
name: "Silence",
|
|
8795
|
+
icon: "🤫"
|
|
8796
|
+
}
|
|
8797
|
+
];
|
|
8588
8798
|
var YAMNET_TO_MACRO = {
|
|
8589
8799
|
mapping: {
|
|
8590
8800
|
Speech: "speech",
|
|
@@ -8851,6 +9061,125 @@ var _macroLookup = /* @__PURE__ */ new Map();
|
|
|
8851
9061
|
for (const [k, v] of Object.entries(YAMNET_TO_MACRO.mapping)) _macroLookup.set(k.toLowerCase(), v);
|
|
8852
9062
|
for (const [k, v] of Object.entries(APPLE_SA_TO_MACRO.mapping)) _macroLookup.set(k.toLowerCase(), v);
|
|
8853
9063
|
/**
|
|
9064
|
+
* Unified event-kind taxonomy — THE single source of truth for
|
|
9065
|
+
* `kind → { parentKind, category, level, color, iconId, labelKey, label,
|
|
9066
|
+
* icon }`.
|
|
9067
|
+
*
|
|
9068
|
+
* This dictionary folds together what used to be scattered across four
|
|
9069
|
+
* copies:
|
|
9070
|
+
* - `capabilities/sensor-event-kinds.ts` (sensor cap colors)
|
|
9071
|
+
* - `addon-post-analysis/.../services/event-kinds.ts`
|
|
9072
|
+
* (MOTION/PERSON/VEHICLE… _COLOR constants)
|
|
9073
|
+
* - `ui-library/composites/detection-colors.ts` (CLASS_COLORS)
|
|
9074
|
+
* - `addon-post-analysis/shared/frame/box-drawer.ts` (DEFAULT_COLOR)
|
|
9075
|
+
* - the COCO / audio class maps (macro ↔ sub relationships)
|
|
9076
|
+
*
|
|
9077
|
+
* The DATA (serializable — color/iconId/labelKey/parentKind) lives here in
|
|
9078
|
+
* `@camstack/types`. The UI-side mapping `iconId → lucide component` and
|
|
9079
|
+
* `labelKey → t()` lives in `@camstack/ui-library`. UIs never hardcode a
|
|
9080
|
+
* color or an icon: they read this dictionary (server descriptors carry the
|
|
9081
|
+
* fields inline; the client resolves color/icon/label from `iconId`/`kind`).
|
|
9082
|
+
*
|
|
9083
|
+
* Two levels only (v1 YAGNI): macro → sub. `person` is a leaf macro.
|
|
9084
|
+
*/
|
|
9085
|
+
var TAXONOMY_COLORS = {
|
|
9086
|
+
motion: "#f59e0b",
|
|
9087
|
+
audio: "#06b6d4",
|
|
9088
|
+
person: "#22c55e",
|
|
9089
|
+
vehicle: "#3b82f6",
|
|
9090
|
+
animal: "#f97316",
|
|
9091
|
+
package: "#a855f7",
|
|
9092
|
+
sensor: "#8b5cf6",
|
|
9093
|
+
control: "#10b981",
|
|
9094
|
+
genericDetection: "#64748b"
|
|
9095
|
+
};
|
|
9096
|
+
var DETECTION_SUB_COLORS = {
|
|
9097
|
+
car: "#f59e0b",
|
|
9098
|
+
truck: "#d97706",
|
|
9099
|
+
bus: "#b45309",
|
|
9100
|
+
motorcycle: "#eab308",
|
|
9101
|
+
bicycle: "#ca8a04",
|
|
9102
|
+
airplane: "#60a5fa",
|
|
9103
|
+
boat: "#2563eb",
|
|
9104
|
+
train: "#1d4ed8",
|
|
9105
|
+
bird: "#14b8a6",
|
|
9106
|
+
dog: "#84cc16",
|
|
9107
|
+
cat: "#f97316",
|
|
9108
|
+
horse: "#a16207",
|
|
9109
|
+
sheep: "#a3a3a3",
|
|
9110
|
+
cow: "#78716c",
|
|
9111
|
+
elephant: "#6b7280",
|
|
9112
|
+
bear: "#7c2d12",
|
|
9113
|
+
zebra: "#404040",
|
|
9114
|
+
giraffe: "#d4a373"
|
|
9115
|
+
};
|
|
9116
|
+
function titleCase(id) {
|
|
9117
|
+
return id.split(/[-_ ]/).filter((p) => p.length > 0).map((p) => p.charAt(0).toUpperCase() + p.slice(1)).join(" ");
|
|
9118
|
+
}
|
|
9119
|
+
var entries = /* @__PURE__ */ new Map();
|
|
9120
|
+
function macro(kind, category, color, iconId, label) {
|
|
9121
|
+
entries.set(kind, {
|
|
9122
|
+
kind,
|
|
9123
|
+
parentKind: null,
|
|
9124
|
+
level: "macro",
|
|
9125
|
+
category,
|
|
9126
|
+
color,
|
|
9127
|
+
iconId,
|
|
9128
|
+
labelKey: `eventKind.${kind}`,
|
|
9129
|
+
label
|
|
9130
|
+
});
|
|
9131
|
+
}
|
|
9132
|
+
function sub(kind, parentKind, category, color, iconId, label) {
|
|
9133
|
+
entries.set(kind, {
|
|
9134
|
+
kind,
|
|
9135
|
+
parentKind,
|
|
9136
|
+
level: "sub",
|
|
9137
|
+
category,
|
|
9138
|
+
color,
|
|
9139
|
+
iconId,
|
|
9140
|
+
labelKey: `eventKind.${kind}`,
|
|
9141
|
+
label
|
|
9142
|
+
});
|
|
9143
|
+
}
|
|
9144
|
+
macro("motion", "motion", TAXONOMY_COLORS.motion, "motion", "Motion");
|
|
9145
|
+
macro("audio", "audio", TAXONOMY_COLORS.audio, "audio", "Audio");
|
|
9146
|
+
macro("person", "detection", TAXONOMY_COLORS.person, "person", "Person");
|
|
9147
|
+
macro("vehicle", "detection", TAXONOMY_COLORS.vehicle, "vehicle", "Vehicle");
|
|
9148
|
+
macro("animal", "detection", TAXONOMY_COLORS.animal, "animal", "Animal");
|
|
9149
|
+
macro("package", "package", TAXONOMY_COLORS.package, "package", "Package");
|
|
9150
|
+
macro("sensor", "sensor", TAXONOMY_COLORS.sensor, "sensor", "Sensor");
|
|
9151
|
+
macro("control", "control", TAXONOMY_COLORS.control, "control", "Control");
|
|
9152
|
+
for (const [cocoClass, macroClass] of Object.entries(COCO_TO_MACRO.mapping)) {
|
|
9153
|
+
if (macroClass !== "vehicle" && macroClass !== "animal") continue;
|
|
9154
|
+
if (entries.has(cocoClass)) continue;
|
|
9155
|
+
sub(cocoClass, macroClass, "detection", DETECTION_SUB_COLORS[cocoClass] ?? TAXONOMY_COLORS.genericDetection, cocoClass, titleCase(cocoClass));
|
|
9156
|
+
}
|
|
9157
|
+
sub("package-delivered", "package", "package", TAXONOMY_COLORS.package, "package", "Package delivered");
|
|
9158
|
+
sub("package-picked-up", "package", "package", TAXONOMY_COLORS.package, "package", "Package picked up");
|
|
9159
|
+
sub("contact", "sensor", "sensor", "#f59e0b", "door", "Contact");
|
|
9160
|
+
sub("motion-sensor", "sensor", "sensor", TAXONOMY_COLORS.sensor, "pir", "Motion sensor");
|
|
9161
|
+
sub("smoke", "sensor", "sensor", "#ef4444", "smoke", "Smoke");
|
|
9162
|
+
sub("flood", "sensor", "sensor", "#3b82f6", "water", "Water leak");
|
|
9163
|
+
sub("gas", "sensor", "sensor", "#ef4444", "gas", "Gas");
|
|
9164
|
+
sub("carbon-monoxide", "sensor", "sensor", "#dc2626", "smoke", "Carbon monoxide");
|
|
9165
|
+
sub("vibration", "sensor", "sensor", "#eab308", "vibration", "Vibration");
|
|
9166
|
+
sub("tamper", "sensor", "sensor", "#f97316", "tamper", "Tamper");
|
|
9167
|
+
sub("presence", "sensor", "sensor", "#22c55e", "presence", "Presence");
|
|
9168
|
+
sub("enum-sensor", "sensor", "sensor", TAXONOMY_COLORS.sensor, "generic", "Sensor state");
|
|
9169
|
+
sub("device-event", "sensor", "sensor", "#10b981", "button", "Device event");
|
|
9170
|
+
sub("lock", "control", "control", "#0ea5e9", "lock", "Lock");
|
|
9171
|
+
sub("switch", "control", "control", TAXONOMY_COLORS.control, "switch", "Switch");
|
|
9172
|
+
sub("siren", "control", "control", "#dc2626", "siren", "Siren");
|
|
9173
|
+
sub("button", "control", "control", "#10b981", "button", "Button");
|
|
9174
|
+
sub("doorbell", "control", "control", "#a855f7", "doorbell", "Doorbell");
|
|
9175
|
+
for (const l of AUDIO_MACRO_LABELS) {
|
|
9176
|
+
const kind = `audio-${l.id}`;
|
|
9177
|
+
if (entries.has(kind)) continue;
|
|
9178
|
+
sub(kind, "audio", "audio", TAXONOMY_COLORS.audio, kind, l.name);
|
|
9179
|
+
}
|
|
9180
|
+
/** The complete taxonomy dictionary, keyed by kind. */
|
|
9181
|
+
var EVENT_TAXONOMY = Object.freeze(Object.fromEntries(entries));
|
|
9182
|
+
/**
|
|
8854
9183
|
* Error types for the safe expression engine. Two distinct classes so callers
|
|
8855
9184
|
* can tell a compile-time (grammar) failure from a runtime (evaluation)
|
|
8856
9185
|
* failure — both are non-fatal to the host: read paths degrade to "skip link".
|
|
@@ -15805,9 +16134,10 @@ var DEVICE_LOCAL_STATE_CAPS = {
|
|
|
15805
16134
|
* `package` backs the package-drop detector — a package zone is a
|
|
15806
16135
|
* `ZoneRule` on the `'package'` stage referencing drawn polygons
|
|
15807
16136
|
* (see docs/superpowers/specs/2026-07-17-package-zones-design.md §3.1).
|
|
15808
|
-
* The orchestrator provider
|
|
15809
|
-
*
|
|
15810
|
-
* consumers read
|
|
16137
|
+
* The orchestrator provider writes this stage as a first-class slice
|
|
16138
|
+
* (Phase 4): every mutation mirrors the full `{motion, detection,
|
|
16139
|
+
* package}` shape, so consumers read the current package rules directly
|
|
16140
|
+
* off `device.state.zoneRules.value.package`.
|
|
15811
16141
|
*/
|
|
15812
16142
|
runtimeState: object({
|
|
15813
16143
|
motion: array(ZoneRuleSchema).readonly(),
|
|
@@ -19782,17 +20112,30 @@ var EventKindCategorySchema = _enum([
|
|
|
19782
20112
|
"audio",
|
|
19783
20113
|
"detection",
|
|
19784
20114
|
"sensor",
|
|
20115
|
+
"control",
|
|
19785
20116
|
"custom",
|
|
19786
20117
|
"package"
|
|
19787
20118
|
]);
|
|
20119
|
+
/** Taxonomy level — macro (timeline lane) vs sub (events-page leaf). */
|
|
20120
|
+
var EventKindLevelSchema = _enum(["macro", "sub"]);
|
|
19788
20121
|
var EventKindDescriptorSchema = object({
|
|
19789
|
-
/** Stable kind id (e.g. 'motion', '
|
|
20122
|
+
/** Stable kind id (e.g. 'motion', 'vehicle', 'car', 'lock'). */
|
|
19790
20123
|
kind: string(),
|
|
20124
|
+
/** i18n key resolved on the UI side; `label` is the English fallback. */
|
|
20125
|
+
labelKey: string(),
|
|
20126
|
+
/** English fallback label (kept for clients that don't translate). */
|
|
19791
20127
|
label: string(),
|
|
19792
20128
|
/** Hex color for timeline/legend rendering. */
|
|
19793
20129
|
color: string(),
|
|
20130
|
+
/** Dictionary id → lucide component on the UI side. */
|
|
20131
|
+
iconId: string(),
|
|
20132
|
+
/** Legacy closed-vocab glyph — fallback for `iconId`. */
|
|
19794
20133
|
icon: EventKindIconSchema,
|
|
19795
20134
|
category: EventKindCategorySchema,
|
|
20135
|
+
/** Macro parent for this kind ('car' → 'vehicle'); null for a macro. */
|
|
20136
|
+
parentKind: string().nullable(),
|
|
20137
|
+
/** Derived from `parentKind`, explicit for the client tree. */
|
|
20138
|
+
level: EventKindLevelSchema,
|
|
19796
20139
|
/** Which cap + device contributes this kind. For built-ins the camera
|
|
19797
20140
|
* itself; for sensor kinds the LINKED source device. */
|
|
19798
20141
|
source: object({
|
|
@@ -19865,11 +20208,21 @@ var TrackAudioLabelSchema = object({
|
|
|
19865
20208
|
firstAt: number(),
|
|
19866
20209
|
lastAt: number()
|
|
19867
20210
|
});
|
|
20211
|
+
/**
|
|
20212
|
+
* How a track was produced. `pipeline` (default / absent) = the spatial
|
|
20213
|
+
* detection+tracking pipeline. `sensor` = a SYNTHETIC track projected from a
|
|
20214
|
+
* linked sensor/control state change (no positions; carries a snapshot). The
|
|
20215
|
+
* spatial subsystems (tracker association, occupancy count, re-id/embedding,
|
|
20216
|
+
* resurrection) MUST skip `sensor` tracks — they have no bbox trajectory.
|
|
20217
|
+
*/
|
|
20218
|
+
var TrackSourceSchema = _enum(["pipeline", "sensor"]);
|
|
19868
20219
|
var TrackSchema = object({
|
|
19869
20220
|
trackId: string(),
|
|
19870
20221
|
deviceId: number(),
|
|
19871
20222
|
className: string(),
|
|
19872
20223
|
label: string().optional(),
|
|
20224
|
+
/** Track provenance. Absent ⇒ `pipeline` (legacy rows). */
|
|
20225
|
+
source: TrackSourceSchema.optional(),
|
|
19873
20226
|
firstSeen: number(),
|
|
19874
20227
|
lastSeen: number(),
|
|
19875
20228
|
/** Frame-rate position history (subject to maxPositionHistory cap). */
|
|
@@ -20124,6 +20477,26 @@ var TrackCascadeCountsSchema = object({
|
|
|
20124
20477
|
/** Per-track CLIP search vectors removed (best-effort). */
|
|
20125
20478
|
embeddings: number().int()
|
|
20126
20479
|
});
|
|
20480
|
+
/** Event-store footprint for one camera. */
|
|
20481
|
+
var EventStoreDeviceFootprintSchema = object({
|
|
20482
|
+
deviceId: number(),
|
|
20483
|
+
/** Persisted event rows (motion + object + audio) for the camera. */
|
|
20484
|
+
rows: number().int(),
|
|
20485
|
+
/** Event-owned media bytes on disk for the camera. */
|
|
20486
|
+
bytes: number().int()
|
|
20487
|
+
});
|
|
20488
|
+
/** Aggregate event-store footprint: global totals + per-camera breakdown. */
|
|
20489
|
+
var EventStoreFootprintSchema = object({
|
|
20490
|
+
totalRows: number().int(),
|
|
20491
|
+
totalBytes: number().int(),
|
|
20492
|
+
devices: array(EventStoreDeviceFootprintSchema).readonly()
|
|
20493
|
+
});
|
|
20494
|
+
/** Per-kind counts returned by the event-prune / device-delete mutations. */
|
|
20495
|
+
var EventPruneCountsSchema = object({
|
|
20496
|
+
motion: number().int(),
|
|
20497
|
+
object: number().int(),
|
|
20498
|
+
audio: number().int()
|
|
20499
|
+
});
|
|
20127
20500
|
DeviceType.Camera, method(object({ deviceId: number() }), array(TrackSchema).readonly()), method(object({
|
|
20128
20501
|
deviceId: number(),
|
|
20129
20502
|
trackId: string()
|
|
@@ -20187,6 +20560,21 @@ DeviceType.Camera, method(object({ deviceId: number() }), array(TrackSchema).rea
|
|
|
20187
20560
|
}), {
|
|
20188
20561
|
kind: "mutation",
|
|
20189
20562
|
auth: "admin"
|
|
20563
|
+
}), method(object({}), EventStoreFootprintSchema, {
|
|
20564
|
+
kind: "query",
|
|
20565
|
+
auth: "admin"
|
|
20566
|
+
}), method(object({
|
|
20567
|
+
olderThanMs: number(),
|
|
20568
|
+
reason: OpsLogReasonSchema.optional()
|
|
20569
|
+
}), EventPruneCountsSchema, {
|
|
20570
|
+
kind: "mutation",
|
|
20571
|
+
auth: "admin"
|
|
20572
|
+
}), method(object({ deviceId: number() }), EventPruneCountsSchema, {
|
|
20573
|
+
kind: "mutation",
|
|
20574
|
+
auth: "admin"
|
|
20575
|
+
}), method(OpsLogQueryInputSchema, array(OpsLogEntrySchema).readonly(), {
|
|
20576
|
+
kind: "query",
|
|
20577
|
+
auth: "admin"
|
|
20190
20578
|
}), method(object({
|
|
20191
20579
|
eventId: string(),
|
|
20192
20580
|
kind: MediaFileKindEnum.optional()
|
|
@@ -20211,6 +20599,76 @@ DeviceType.Camera, method(object({ deviceId: number() }), array(TrackSchema).rea
|
|
|
20211
20599
|
eventId: string(),
|
|
20212
20600
|
timestamp: number()
|
|
20213
20601
|
});
|
|
20602
|
+
/**
|
|
20603
|
+
* Cap → event-kind mapping for the SENSOR / CONTROL cap families — the table
|
|
20604
|
+
* `pipeline-analytics.listEventKinds` uses to turn a linked device's bound
|
|
20605
|
+
* caps into per-camera event-kind descriptors.
|
|
20606
|
+
*
|
|
20607
|
+
* The descriptor DATA (color / iconId / labelKey / parentKind / category)
|
|
20608
|
+
* is NOT duplicated here — every entry is derived from the single
|
|
20609
|
+
* `EVENT_TAXONOMY` dictionary (`catalogs/event-taxonomy.ts`). This file owns
|
|
20610
|
+
* ONLY the cap-name → taxonomy-kind mapping. Adding a new eventful sensor /
|
|
20611
|
+
* control cap means adding one line here (and a taxonomy entry); the anti-
|
|
20612
|
+
* drift guard `scripts/check-event-kind-coverage.ts` fails the build if an
|
|
20613
|
+
* eventful cap is missing.
|
|
20614
|
+
*/
|
|
20615
|
+
/** Map a taxonomy `iconId` onto the legacy closed `EventKindIcon` enum. */
|
|
20616
|
+
var LEGACY_ICON = {
|
|
20617
|
+
motion: "motion",
|
|
20618
|
+
audio: "audio",
|
|
20619
|
+
person: "person",
|
|
20620
|
+
vehicle: "vehicle",
|
|
20621
|
+
animal: "animal",
|
|
20622
|
+
package: "package",
|
|
20623
|
+
door: "door",
|
|
20624
|
+
pir: "pir",
|
|
20625
|
+
smoke: "smoke",
|
|
20626
|
+
water: "water",
|
|
20627
|
+
button: "button",
|
|
20628
|
+
generic: "generic",
|
|
20629
|
+
gas: "smoke",
|
|
20630
|
+
vibration: "generic",
|
|
20631
|
+
tamper: "generic",
|
|
20632
|
+
presence: "person",
|
|
20633
|
+
lock: "generic",
|
|
20634
|
+
siren: "generic",
|
|
20635
|
+
switch: "generic",
|
|
20636
|
+
doorbell: "button"
|
|
20637
|
+
};
|
|
20638
|
+
function legacyIcon(iconId) {
|
|
20639
|
+
return LEGACY_ICON[iconId] ?? "generic";
|
|
20640
|
+
}
|
|
20641
|
+
/**
|
|
20642
|
+
* Cap name → taxonomy kind id. Covers EVERY eventful sensor / control cap.
|
|
20643
|
+
* The anti-drift guard cross-checks this against the eventful caps declared
|
|
20644
|
+
* in `packages/types/src/capabilities/*.cap.ts`.
|
|
20645
|
+
*/
|
|
20646
|
+
var CAP_TO_KIND = {
|
|
20647
|
+
contact: "contact",
|
|
20648
|
+
motion: "motion-sensor",
|
|
20649
|
+
smoke: "smoke",
|
|
20650
|
+
flood: "flood",
|
|
20651
|
+
gas: "gas",
|
|
20652
|
+
"carbon-monoxide": "carbon-monoxide",
|
|
20653
|
+
vibration: "vibration",
|
|
20654
|
+
tamper: "tamper",
|
|
20655
|
+
presence: "presence",
|
|
20656
|
+
"enum-sensor": "enum-sensor",
|
|
20657
|
+
"event-emitter": "device-event",
|
|
20658
|
+
"lock-control": "lock",
|
|
20659
|
+
switch: "switch",
|
|
20660
|
+
button: "button",
|
|
20661
|
+
doorbell: "doorbell"
|
|
20662
|
+
};
|
|
20663
|
+
function buildDescriptor(capName, kind) {
|
|
20664
|
+
const t = EVENT_TAXONOMY[kind];
|
|
20665
|
+
if (t === void 0) throw new Error(`EVENT_KIND_BY_CAP: cap '${capName}' maps to unknown taxonomy kind '${kind}'`);
|
|
20666
|
+
return {
|
|
20667
|
+
...t,
|
|
20668
|
+
icon: legacyIcon(t.iconId)
|
|
20669
|
+
};
|
|
20670
|
+
}
|
|
20671
|
+
Object.freeze(Object.fromEntries(Object.entries(CAP_TO_KIND).map(([capName, kind]) => [capName, buildDescriptor(capName, kind)])));
|
|
20214
20672
|
var CameraPipelineConfigSchema = object({
|
|
20215
20673
|
engine: PipelineEngineChoiceSchema.optional(),
|
|
20216
20674
|
steps: array(PipelineStepInputSchema).readonly(),
|
|
@@ -23420,13 +23878,29 @@ method(object({
|
|
|
23420
23878
|
}), method(object({ deviceId: number() }), RecordingStatusSchema, {
|
|
23421
23879
|
kind: "mutation",
|
|
23422
23880
|
auth: "admin"
|
|
23423
|
-
}), method(object({
|
|
23881
|
+
}), method(object({
|
|
23882
|
+
deviceId: number(),
|
|
23883
|
+
reason: OpsLogReasonSchema.optional()
|
|
23884
|
+
}), object({
|
|
23424
23885
|
floorMs: number().nullable(),
|
|
23425
23886
|
deletedBuckets: number().int(),
|
|
23426
23887
|
reclaimedBytes: number().int()
|
|
23427
23888
|
}), {
|
|
23428
23889
|
kind: "mutation",
|
|
23429
23890
|
auth: "admin"
|
|
23891
|
+
}), method(object({
|
|
23892
|
+
deviceId: number(),
|
|
23893
|
+
fromMs: number().optional(),
|
|
23894
|
+
toMs: number().optional()
|
|
23895
|
+
}), object({
|
|
23896
|
+
deletedBuckets: number().int(),
|
|
23897
|
+
reclaimedBytes: number().int()
|
|
23898
|
+
}), {
|
|
23899
|
+
kind: "mutation",
|
|
23900
|
+
auth: "admin"
|
|
23901
|
+
}), method(OpsLogQueryInputSchema, array(OpsLogEntrySchema).readonly(), {
|
|
23902
|
+
kind: "query",
|
|
23903
|
+
auth: "admin"
|
|
23430
23904
|
});
|
|
23431
23905
|
/**
|
|
23432
23906
|
* `recordingExport` cap — render a footage time range into a single downloadable
|
|
@@ -26548,6 +27022,12 @@ Object.freeze({
|
|
|
26548
27022
|
addonId: null,
|
|
26549
27023
|
access: "delete"
|
|
26550
27024
|
},
|
|
27025
|
+
"pipelineAnalytics.deleteDeviceEvents": {
|
|
27026
|
+
capName: "pipeline-analytics",
|
|
27027
|
+
capScope: "device",
|
|
27028
|
+
addonId: null,
|
|
27029
|
+
access: "delete"
|
|
27030
|
+
},
|
|
26551
27031
|
"pipelineAnalytics.deleteTracks": {
|
|
26552
27032
|
capName: "pipeline-analytics",
|
|
26553
27033
|
capScope: "device",
|
|
@@ -26578,6 +27058,12 @@ Object.freeze({
|
|
|
26578
27058
|
addonId: null,
|
|
26579
27059
|
access: "view"
|
|
26580
27060
|
},
|
|
27061
|
+
"pipelineAnalytics.getEventStoreFootprint": {
|
|
27062
|
+
capName: "pipeline-analytics",
|
|
27063
|
+
capScope: "device",
|
|
27064
|
+
addonId: null,
|
|
27065
|
+
access: "view"
|
|
27066
|
+
},
|
|
26581
27067
|
"pipelineAnalytics.getKeyEvents": {
|
|
26582
27068
|
capName: "pipeline-analytics",
|
|
26583
27069
|
capScope: "device",
|
|
@@ -26620,6 +27106,12 @@ Object.freeze({
|
|
|
26620
27106
|
addonId: null,
|
|
26621
27107
|
access: "view"
|
|
26622
27108
|
},
|
|
27109
|
+
"pipelineAnalytics.listOpsLog": {
|
|
27110
|
+
capName: "pipeline-analytics",
|
|
27111
|
+
capScope: "device",
|
|
27112
|
+
addonId: null,
|
|
27113
|
+
access: "view"
|
|
27114
|
+
},
|
|
26623
27115
|
"pipelineAnalytics.listRecentTracks": {
|
|
26624
27116
|
capName: "pipeline-analytics",
|
|
26625
27117
|
capScope: "device",
|
|
@@ -26632,6 +27124,12 @@ Object.freeze({
|
|
|
26632
27124
|
addonId: null,
|
|
26633
27125
|
access: "view"
|
|
26634
27126
|
},
|
|
27127
|
+
"pipelineAnalytics.pruneEvents": {
|
|
27128
|
+
capName: "pipeline-analytics",
|
|
27129
|
+
capScope: "device",
|
|
27130
|
+
addonId: null,
|
|
27131
|
+
access: "create"
|
|
27132
|
+
},
|
|
26635
27133
|
"pipelineAnalytics.pruneEventsBefore": {
|
|
26636
27134
|
capName: "pipeline-analytics",
|
|
26637
27135
|
capScope: "device",
|
|
@@ -27394,6 +27892,12 @@ Object.freeze({
|
|
|
27394
27892
|
addonId: null,
|
|
27395
27893
|
access: "create"
|
|
27396
27894
|
},
|
|
27895
|
+
"recording.deleteFootprint": {
|
|
27896
|
+
capName: "recording",
|
|
27897
|
+
capScope: "system",
|
|
27898
|
+
addonId: null,
|
|
27899
|
+
access: "delete"
|
|
27900
|
+
},
|
|
27397
27901
|
"recording.getAvailability": {
|
|
27398
27902
|
capName: "recording",
|
|
27399
27903
|
capScope: "system",
|
|
@@ -27424,6 +27928,12 @@ Object.freeze({
|
|
|
27424
27928
|
addonId: null,
|
|
27425
27929
|
access: "view"
|
|
27426
27930
|
},
|
|
27931
|
+
"recording.listOpsLog": {
|
|
27932
|
+
capName: "recording",
|
|
27933
|
+
capScope: "system",
|
|
27934
|
+
addonId: null,
|
|
27935
|
+
access: "view"
|
|
27936
|
+
},
|
|
27427
27937
|
"recording.locateSegment": {
|
|
27428
27938
|
capName: "recording",
|
|
27429
27939
|
capScope: "system",
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@camstack/addon-provider-rademacher",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.14",
|
|
4
4
|
"description": "Rademacher HomePilot device-provider addon for CamStack — wraps the @apocaliss92/noderademacher local-hub client (roller shutters over the cover cap)",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"camstack",
|