camstack 1.1.29 → 1.1.31

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.
@@ -687,9 +687,9 @@ function assertNever(_x) {
687
687
  }
688
688
  function assert(_) {
689
689
  }
690
- function getEnumValues(entries) {
691
- const numericValues = Object.values(entries).filter((v) => typeof v === "number");
692
- const values = Object.entries(entries).filter(([k, _]) => numericValues.indexOf(+k) === -1).map(([_, v]) => v);
690
+ function getEnumValues(entries2) {
691
+ const numericValues = Object.values(entries2).filter((v) => typeof v === "number");
692
+ const values = Object.entries(entries2).filter(([k, _]) => numericValues.indexOf(+k) === -1).map(([_, v]) => v);
693
693
  return values;
694
694
  }
695
695
  function joinValues(array2, separator = "|") {
@@ -1325,12 +1325,12 @@ var $ZodRealError = $constructor("$ZodError", initializer, { Parent: Error });
1325
1325
  function flattenError(error51, mapper = (issue2) => issue2.message) {
1326
1326
  const fieldErrors = {};
1327
1327
  const formErrors = [];
1328
- for (const sub of error51.issues) {
1329
- if (sub.path.length > 0) {
1330
- fieldErrors[sub.path[0]] = fieldErrors[sub.path[0]] || [];
1331
- fieldErrors[sub.path[0]].push(mapper(sub));
1328
+ for (const sub2 of error51.issues) {
1329
+ if (sub2.path.length > 0) {
1330
+ fieldErrors[sub2.path[0]] = fieldErrors[sub2.path[0]] || [];
1331
+ fieldErrors[sub2.path[0]].push(mapper(sub2));
1332
1332
  } else {
1333
- formErrors.push(mapper(sub));
1333
+ formErrors.push(mapper(sub2));
1334
1334
  }
1335
1335
  }
1336
1336
  return { formErrors, fieldErrors };
@@ -11149,18 +11149,18 @@ function _set(Class2, valueType, params) {
11149
11149
  }
11150
11150
  // @__NO_SIDE_EFFECTS__
11151
11151
  function _enum(Class2, values, params) {
11152
- const entries = Array.isArray(values) ? Object.fromEntries(values.map((v) => [v, v])) : values;
11152
+ const entries2 = Array.isArray(values) ? Object.fromEntries(values.map((v) => [v, v])) : values;
11153
11153
  return new Class2({
11154
11154
  type: "enum",
11155
- entries,
11155
+ entries: entries2,
11156
11156
  ...normalizeParams(params)
11157
11157
  });
11158
11158
  }
11159
11159
  // @__NO_SIDE_EFFECTS__
11160
- function _nativeEnum(Class2, entries, params) {
11160
+ function _nativeEnum(Class2, entries2, params) {
11161
11161
  return new Class2({
11162
11162
  type: "enum",
11163
- entries,
11163
+ entries: entries2,
11164
11164
  ...normalizeParams(params)
11165
11165
  });
11166
11166
  }
@@ -13618,17 +13618,17 @@ var ZodEnum = /* @__PURE__ */ $constructor("ZodEnum", (inst, def) => {
13618
13618
  };
13619
13619
  });
13620
13620
  function _enum2(values, params) {
13621
- const entries = Array.isArray(values) ? Object.fromEntries(values.map((v) => [v, v])) : values;
13621
+ const entries2 = Array.isArray(values) ? Object.fromEntries(values.map((v) => [v, v])) : values;
13622
13622
  return new ZodEnum({
13623
13623
  type: "enum",
13624
- entries,
13624
+ entries: entries2,
13625
13625
  ...util_exports.normalizeParams(params)
13626
13626
  });
13627
13627
  }
13628
- function nativeEnum(entries, params) {
13628
+ function nativeEnum(entries2, params) {
13629
13629
  return new ZodEnum({
13630
13630
  type: "enum",
13631
- entries,
13631
+ entries: entries2,
13632
13632
  ...util_exports.normalizeParams(params)
13633
13633
  });
13634
13634
  }
@@ -14522,7 +14522,7 @@ function date4(params) {
14522
14522
  // ../../node_modules/zod/v4/classic/external.js
14523
14523
  config(en_default());
14524
14524
 
14525
- // ../types/dist/sleep-DOq2moJx.mjs
14525
+ // ../types/dist/sleep-D8ZkNoYz.mjs
14526
14526
  var WELL_KNOWN_TABS = [
14527
14527
  {
14528
14528
  id: "overview",
@@ -15585,6 +15585,46 @@ var RecordingConfigSchema = external_exports.object({
15585
15585
  */
15586
15586
  scrubThumbnails: ScrubThumbnailPresetSchema.optional()
15587
15587
  });
15588
+ var OpsLogDomainSchema = external_exports.enum(["recording", "events"]);
15589
+ var OpsLogOpSchema = external_exports.enum([
15590
+ "prune",
15591
+ "manual-delete",
15592
+ "rescan",
15593
+ "retention-run"
15594
+ ]);
15595
+ var OpsLogReasonSchema = external_exports.enum([
15596
+ "retention",
15597
+ "quota",
15598
+ "manual",
15599
+ "operator"
15600
+ ]);
15601
+ var OpsLogEntrySchema = external_exports.object({
15602
+ /** Unique row id. */
15603
+ id: external_exports.string(),
15604
+ /** Epoch ms the operation completed. */
15605
+ at: external_exports.number(),
15606
+ domain: OpsLogDomainSchema,
15607
+ op: OpsLogOpSchema,
15608
+ reason: OpsLogReasonSchema,
15609
+ /** The camera the op targeted; null for a cluster/global op. */
15610
+ deviceId: external_exports.number().nullable(),
15611
+ /** Node that performed the op (the log carries nodeId — no cross-node aggregation). */
15612
+ nodeId: external_exports.string(),
15613
+ /** Buckets / rows deleted (op-specific unit). */
15614
+ itemsAffected: external_exports.number(),
15615
+ /** Bytes reclaimed by the op (0 when not measurable). */
15616
+ bytesReclaimed: external_exports.number(),
15617
+ /** Free-text detail (e.g. "floor moved to <ts>"); null when none. */
15618
+ detail: external_exports.string().nullable(),
15619
+ /** Who/what triggered the op. */
15620
+ actor: external_exports.string()
15621
+ });
15622
+ var OpsLogQueryInputSchema = external_exports.object({
15623
+ /** Restrict to a single camera; omit for every row. */
15624
+ deviceId: external_exports.number().optional(),
15625
+ /** Max rows returned, newest-first. */
15626
+ limit: external_exports.number().int().min(1).max(1e3).optional()
15627
+ });
15588
15628
  var StorageLocationTypeSchema = external_exports.string().regex(/^[a-z][a-zA-Z0-9-]*$/);
15589
15629
  var StorageLocationSchema = external_exports.object({
15590
15630
  id: external_exports.string().regex(/^[a-z][a-zA-Z0-9-]*:[a-zA-Z0-9-]+$/),
@@ -15778,6 +15818,160 @@ var DEFAULT_RETENTION = {
15778
15818
  };
15779
15819
  var HF_REPO = "camstack/camstack-models";
15780
15820
  var HF_BASE_URL = `https://huggingface.co/${HF_REPO}/resolve/main`;
15821
+ var COCO_TO_MACRO = {
15822
+ mapping: {
15823
+ person: "person",
15824
+ bicycle: "vehicle",
15825
+ car: "vehicle",
15826
+ motorcycle: "vehicle",
15827
+ airplane: "vehicle",
15828
+ bus: "vehicle",
15829
+ train: "vehicle",
15830
+ truck: "vehicle",
15831
+ boat: "vehicle",
15832
+ bird: "animal",
15833
+ cat: "animal",
15834
+ dog: "animal",
15835
+ horse: "animal",
15836
+ sheep: "animal",
15837
+ cow: "animal",
15838
+ elephant: "animal",
15839
+ bear: "animal",
15840
+ zebra: "animal",
15841
+ giraffe: "animal",
15842
+ suitcase: "package",
15843
+ backpack: "package",
15844
+ handbag: "package"
15845
+ },
15846
+ preserveOriginal: false
15847
+ };
15848
+ var AUDIO_MACRO_LABELS = [
15849
+ {
15850
+ id: "speech",
15851
+ name: "Speech",
15852
+ icon: "\u{1F5E3}\uFE0F"
15853
+ },
15854
+ {
15855
+ id: "scream",
15856
+ name: "Scream / Shout",
15857
+ icon: "\u{1F631}"
15858
+ },
15859
+ {
15860
+ id: "crying",
15861
+ name: "Crying / Baby",
15862
+ icon: "\u{1F622}"
15863
+ },
15864
+ {
15865
+ id: "laughter",
15866
+ name: "Laughter",
15867
+ icon: "\u{1F602}"
15868
+ },
15869
+ {
15870
+ id: "music",
15871
+ name: "Music",
15872
+ icon: "\u{1F3B5}"
15873
+ },
15874
+ {
15875
+ id: "dog",
15876
+ name: "Dog",
15877
+ icon: "\u{1F415}"
15878
+ },
15879
+ {
15880
+ id: "cat",
15881
+ name: "Cat",
15882
+ icon: "\u{1F408}"
15883
+ },
15884
+ {
15885
+ id: "bird",
15886
+ name: "Bird",
15887
+ icon: "\u{1F426}"
15888
+ },
15889
+ {
15890
+ id: "animal",
15891
+ name: "Animal (other)",
15892
+ icon: "\u{1F43E}"
15893
+ },
15894
+ {
15895
+ id: "alarm",
15896
+ name: "Alarm / Siren",
15897
+ icon: "\u{1F6A8}"
15898
+ },
15899
+ {
15900
+ id: "doorbell",
15901
+ name: "Doorbell / Knock",
15902
+ icon: "\u{1F514}"
15903
+ },
15904
+ {
15905
+ id: "glass_breaking",
15906
+ name: "Glass Breaking",
15907
+ icon: "\u{1F4A5}"
15908
+ },
15909
+ {
15910
+ id: "gunshot",
15911
+ name: "Gunshot / Explosion",
15912
+ icon: "\u{1F4A3}"
15913
+ },
15914
+ {
15915
+ id: "vehicle",
15916
+ name: "Vehicle",
15917
+ icon: "\u{1F697}"
15918
+ },
15919
+ {
15920
+ id: "siren",
15921
+ name: "Emergency Siren",
15922
+ icon: "\u{1F691}"
15923
+ },
15924
+ {
15925
+ id: "fire",
15926
+ name: "Fire / Smoke",
15927
+ icon: "\u{1F525}"
15928
+ },
15929
+ {
15930
+ id: "water",
15931
+ name: "Water",
15932
+ icon: "\u{1F4A7}"
15933
+ },
15934
+ {
15935
+ id: "wind",
15936
+ name: "Wind / Weather",
15937
+ icon: "\u{1F32C}\uFE0F"
15938
+ },
15939
+ {
15940
+ id: "door",
15941
+ name: "Door",
15942
+ icon: "\u{1F6AA}"
15943
+ },
15944
+ {
15945
+ id: "footsteps",
15946
+ name: "Footsteps",
15947
+ icon: "\u{1F463}"
15948
+ },
15949
+ {
15950
+ id: "crowd",
15951
+ name: "Crowd / Chatter",
15952
+ icon: "\u{1F465}"
15953
+ },
15954
+ {
15955
+ id: "telephone",
15956
+ name: "Telephone",
15957
+ icon: "\u{1F4DE}"
15958
+ },
15959
+ {
15960
+ id: "engine",
15961
+ name: "Engine / Motor",
15962
+ icon: "\u2699\uFE0F"
15963
+ },
15964
+ {
15965
+ id: "tools",
15966
+ name: "Tools / Construction",
15967
+ icon: "\u{1F528}"
15968
+ },
15969
+ {
15970
+ id: "silence",
15971
+ name: "Silence",
15972
+ icon: "\u{1F92B}"
15973
+ }
15974
+ ];
15781
15975
  var YAMNET_TO_MACRO = {
15782
15976
  mapping: {
15783
15977
  Speech: "speech",
@@ -16043,6 +16237,102 @@ var APPLE_SA_TO_MACRO = {
16043
16237
  var _macroLookup = /* @__PURE__ */ new Map();
16044
16238
  for (const [k, v] of Object.entries(YAMNET_TO_MACRO.mapping)) _macroLookup.set(k.toLowerCase(), v);
16045
16239
  for (const [k, v] of Object.entries(APPLE_SA_TO_MACRO.mapping)) _macroLookup.set(k.toLowerCase(), v);
16240
+ var TAXONOMY_COLORS = {
16241
+ motion: "#f59e0b",
16242
+ audio: "#06b6d4",
16243
+ person: "#22c55e",
16244
+ vehicle: "#3b82f6",
16245
+ animal: "#f97316",
16246
+ package: "#a855f7",
16247
+ sensor: "#8b5cf6",
16248
+ control: "#10b981",
16249
+ genericDetection: "#64748b"
16250
+ };
16251
+ var DETECTION_SUB_COLORS = {
16252
+ car: "#f59e0b",
16253
+ truck: "#d97706",
16254
+ bus: "#b45309",
16255
+ motorcycle: "#eab308",
16256
+ bicycle: "#ca8a04",
16257
+ airplane: "#60a5fa",
16258
+ boat: "#2563eb",
16259
+ train: "#1d4ed8",
16260
+ bird: "#14b8a6",
16261
+ dog: "#84cc16",
16262
+ cat: "#f97316",
16263
+ horse: "#a16207",
16264
+ sheep: "#a3a3a3",
16265
+ cow: "#78716c",
16266
+ elephant: "#6b7280",
16267
+ bear: "#7c2d12",
16268
+ zebra: "#404040",
16269
+ giraffe: "#d4a373"
16270
+ };
16271
+ function titleCase(id) {
16272
+ return id.split(/[-_ ]/).filter((p) => p.length > 0).map((p) => p.charAt(0).toUpperCase() + p.slice(1)).join(" ");
16273
+ }
16274
+ var entries = /* @__PURE__ */ new Map();
16275
+ function macro(kind, category, color, iconId, label) {
16276
+ entries.set(kind, {
16277
+ kind,
16278
+ parentKind: null,
16279
+ level: "macro",
16280
+ category,
16281
+ color,
16282
+ iconId,
16283
+ labelKey: `eventKind.${kind}`,
16284
+ label
16285
+ });
16286
+ }
16287
+ function sub(kind, parentKind, category, color, iconId, label) {
16288
+ entries.set(kind, {
16289
+ kind,
16290
+ parentKind,
16291
+ level: "sub",
16292
+ category,
16293
+ color,
16294
+ iconId,
16295
+ labelKey: `eventKind.${kind}`,
16296
+ label
16297
+ });
16298
+ }
16299
+ macro("motion", "motion", TAXONOMY_COLORS.motion, "motion", "Motion");
16300
+ macro("audio", "audio", TAXONOMY_COLORS.audio, "audio", "Audio");
16301
+ macro("person", "detection", TAXONOMY_COLORS.person, "person", "Person");
16302
+ macro("vehicle", "detection", TAXONOMY_COLORS.vehicle, "vehicle", "Vehicle");
16303
+ macro("animal", "detection", TAXONOMY_COLORS.animal, "animal", "Animal");
16304
+ macro("package", "package", TAXONOMY_COLORS.package, "package", "Package");
16305
+ macro("sensor", "sensor", TAXONOMY_COLORS.sensor, "sensor", "Sensor");
16306
+ macro("control", "control", TAXONOMY_COLORS.control, "control", "Control");
16307
+ for (const [cocoClass, macroClass] of Object.entries(COCO_TO_MACRO.mapping)) {
16308
+ if (macroClass !== "vehicle" && macroClass !== "animal") continue;
16309
+ if (entries.has(cocoClass)) continue;
16310
+ sub(cocoClass, macroClass, "detection", DETECTION_SUB_COLORS[cocoClass] ?? TAXONOMY_COLORS.genericDetection, cocoClass, titleCase(cocoClass));
16311
+ }
16312
+ sub("package-delivered", "package", "package", TAXONOMY_COLORS.package, "package", "Package delivered");
16313
+ sub("package-picked-up", "package", "package", TAXONOMY_COLORS.package, "package", "Package picked up");
16314
+ sub("contact", "sensor", "sensor", "#f59e0b", "door", "Contact");
16315
+ sub("motion-sensor", "sensor", "sensor", TAXONOMY_COLORS.sensor, "pir", "Motion sensor");
16316
+ sub("smoke", "sensor", "sensor", "#ef4444", "smoke", "Smoke");
16317
+ sub("flood", "sensor", "sensor", "#3b82f6", "water", "Water leak");
16318
+ sub("gas", "sensor", "sensor", "#ef4444", "gas", "Gas");
16319
+ sub("carbon-monoxide", "sensor", "sensor", "#dc2626", "smoke", "Carbon monoxide");
16320
+ sub("vibration", "sensor", "sensor", "#eab308", "vibration", "Vibration");
16321
+ sub("tamper", "sensor", "sensor", "#f97316", "tamper", "Tamper");
16322
+ sub("presence", "sensor", "sensor", "#22c55e", "presence", "Presence");
16323
+ sub("enum-sensor", "sensor", "sensor", TAXONOMY_COLORS.sensor, "generic", "Sensor state");
16324
+ sub("device-event", "sensor", "sensor", "#10b981", "button", "Device event");
16325
+ sub("lock", "control", "control", "#0ea5e9", "lock", "Lock");
16326
+ sub("switch", "control", "control", TAXONOMY_COLORS.control, "switch", "Switch");
16327
+ sub("siren", "control", "control", "#dc2626", "siren", "Siren");
16328
+ sub("button", "control", "control", "#10b981", "button", "Button");
16329
+ sub("doorbell", "control", "control", "#a855f7", "doorbell", "Doorbell");
16330
+ for (const l of AUDIO_MACRO_LABELS) {
16331
+ const kind = `audio-${l.id}`;
16332
+ if (entries.has(kind)) continue;
16333
+ sub(kind, "audio", "audio", TAXONOMY_COLORS.audio, kind, l.name);
16334
+ }
16335
+ var EVENT_TAXONOMY = Object.freeze(Object.fromEntries(entries));
16046
16336
  var ExpressionParseError = class extends Error {
16047
16337
  position;
16048
16338
  constructor(message, position) {
@@ -21847,9 +22137,10 @@ var zoneRulesCapability = {
21847
22137
  * `package` backs the package-drop detector — a package zone is a
21848
22138
  * `ZoneRule` on the `'package'` stage referencing drawn polygons
21849
22139
  * (see docs/superpowers/specs/2026-07-17-package-zones-design.md §3.1).
21850
- * The orchestrator provider that writes this stage lands in a later
21851
- * slice; until then the mirror carries only `{motion, detection}` and
21852
- * consumers read `package` as absent (treat as `[]`).
22140
+ * The orchestrator provider writes this stage as a first-class slice
22141
+ * (Phase 4): every mutation mirrors the full `{motion, detection,
22142
+ * package}` shape, so consumers read the current package rules directly
22143
+ * off `device.state.zoneRules.value.package`.
21853
22144
  */
21854
22145
  runtimeState: external_exports.object({
21855
22146
  motion: external_exports.array(ZoneRuleSchema).readonly(),
@@ -25614,17 +25905,29 @@ var EventKindCategorySchema = external_exports.enum([
25614
25905
  "audio",
25615
25906
  "detection",
25616
25907
  "sensor",
25908
+ "control",
25617
25909
  "custom",
25618
25910
  "package"
25619
25911
  ]);
25912
+ var EventKindLevelSchema = external_exports.enum(["macro", "sub"]);
25620
25913
  var EventKindDescriptorSchema = external_exports.object({
25621
- /** Stable kind id (e.g. 'motion', 'person', 'contact'). */
25914
+ /** Stable kind id (e.g. 'motion', 'vehicle', 'car', 'lock'). */
25622
25915
  kind: external_exports.string(),
25916
+ /** i18n key resolved on the UI side; `label` is the English fallback. */
25917
+ labelKey: external_exports.string(),
25918
+ /** English fallback label (kept for clients that don't translate). */
25623
25919
  label: external_exports.string(),
25624
25920
  /** Hex color for timeline/legend rendering. */
25625
25921
  color: external_exports.string(),
25922
+ /** Dictionary id → lucide component on the UI side. */
25923
+ iconId: external_exports.string(),
25924
+ /** Legacy closed-vocab glyph — fallback for `iconId`. */
25626
25925
  icon: EventKindIconSchema,
25627
25926
  category: EventKindCategorySchema,
25927
+ /** Macro parent for this kind ('car' → 'vehicle'); null for a macro. */
25928
+ parentKind: external_exports.string().nullable(),
25929
+ /** Derived from `parentKind`, explicit for the client tree. */
25930
+ level: EventKindLevelSchema,
25628
25931
  /** Which cap + device contributes this kind. For built-ins the camera
25629
25932
  * itself; for sensor kinds the LINKED source device. */
25630
25933
  source: external_exports.object({
@@ -25673,11 +25976,14 @@ var TrackAudioLabelSchema = external_exports.object({
25673
25976
  firstAt: external_exports.number(),
25674
25977
  lastAt: external_exports.number()
25675
25978
  });
25979
+ var TrackSourceSchema = external_exports.enum(["pipeline", "sensor"]);
25676
25980
  var TrackSchema = external_exports.object({
25677
25981
  trackId: external_exports.string(),
25678
25982
  deviceId: external_exports.number(),
25679
25983
  className: external_exports.string(),
25680
25984
  label: external_exports.string().optional(),
25985
+ /** Track provenance. Absent ⇒ `pipeline` (legacy rows). */
25986
+ source: TrackSourceSchema.optional(),
25681
25987
  firstSeen: external_exports.number(),
25682
25988
  lastSeen: external_exports.number(),
25683
25989
  /** Frame-rate position history (subject to maxPositionHistory cap). */
@@ -25924,6 +26230,23 @@ var TrackCascadeCountsSchema = external_exports.object({
25924
26230
  /** Per-track CLIP search vectors removed (best-effort). */
25925
26231
  embeddings: external_exports.number().int()
25926
26232
  });
26233
+ var EventStoreDeviceFootprintSchema = external_exports.object({
26234
+ deviceId: external_exports.number(),
26235
+ /** Persisted event rows (motion + object + audio) for the camera. */
26236
+ rows: external_exports.number().int(),
26237
+ /** Event-owned media bytes on disk for the camera. */
26238
+ bytes: external_exports.number().int()
26239
+ });
26240
+ var EventStoreFootprintSchema = external_exports.object({
26241
+ totalRows: external_exports.number().int(),
26242
+ totalBytes: external_exports.number().int(),
26243
+ devices: external_exports.array(EventStoreDeviceFootprintSchema).readonly()
26244
+ });
26245
+ var EventPruneCountsSchema = external_exports.object({
26246
+ motion: external_exports.number().int(),
26247
+ object: external_exports.number().int(),
26248
+ audio: external_exports.number().int()
26249
+ });
25927
26250
  var pipelineAnalyticsCapability = {
25928
26251
  name: "pipeline-analytics",
25929
26252
  scope: "device",
@@ -26085,6 +26408,45 @@ var pipelineAnalyticsCapability = {
26085
26408
  kind: "mutation",
26086
26409
  auth: "admin"
26087
26410
  }),
26411
+ /**
26412
+ * Durable event-store footprint for the management UI: event rows
26413
+ * (motion + object + audio) counted per camera + total, plus the
26414
+ * event-owned media bytes on disk per camera + total. Stat/count-based,
26415
+ * computed on demand.
26416
+ */
26417
+ getEventStoreFootprint: method(external_exports.object({}), EventStoreFootprintSchema, {
26418
+ kind: "query",
26419
+ auth: "admin"
26420
+ }),
26421
+ /**
26422
+ * Cluster-wide prune of events older than `olderThanMs` (exclusive) across
26423
+ * every camera, deleting each event's media in lockstep. Logged to the
26424
+ * events ops-log with `reason` (default `'retention'`). Returns the summed
26425
+ * per-kind deleted counts.
26426
+ */
26427
+ pruneEvents: method(external_exports.object({
26428
+ olderThanMs: external_exports.number(),
26429
+ reason: OpsLogReasonSchema.optional()
26430
+ }), EventPruneCountsSchema, {
26431
+ kind: "mutation",
26432
+ auth: "admin"
26433
+ }),
26434
+ /**
26435
+ * Manually delete EVERY event (motion + object + audio) for one camera and
26436
+ * its event-owned media in lockstep. Logged to the events ops-log as
26437
+ * `op:'manual-delete', reason:'manual'`. Destructive — the admin UI guards
26438
+ * it behind a confirm.
26439
+ */
26440
+ deleteDeviceEvents: method(external_exports.object({ deviceId: external_exports.number() }), EventPruneCountsSchema, {
26441
+ kind: "mutation",
26442
+ auth: "admin"
26443
+ }),
26444
+ /** The events ops-log rows (newest-first), optionally scoped to one camera.
26445
+ * Backed by a declared pipeline-analytics SQLite collection. */
26446
+ listOpsLog: method(OpsLogQueryInputSchema, external_exports.array(OpsLogEntrySchema).readonly(), {
26447
+ kind: "query",
26448
+ auth: "admin"
26449
+ }),
26088
26450
  getEventMedia: method(external_exports.object({
26089
26451
  eventId: external_exports.string(),
26090
26452
  kind: MediaFileKindEnum.optional()
@@ -26138,6 +26500,58 @@ var pipelineAnalyticsCapability = {
26138
26500
  }) }
26139
26501
  }
26140
26502
  };
26503
+ var LEGACY_ICON = {
26504
+ motion: "motion",
26505
+ audio: "audio",
26506
+ person: "person",
26507
+ vehicle: "vehicle",
26508
+ animal: "animal",
26509
+ package: "package",
26510
+ door: "door",
26511
+ pir: "pir",
26512
+ smoke: "smoke",
26513
+ water: "water",
26514
+ button: "button",
26515
+ generic: "generic",
26516
+ gas: "smoke",
26517
+ vibration: "generic",
26518
+ tamper: "generic",
26519
+ presence: "person",
26520
+ lock: "generic",
26521
+ siren: "generic",
26522
+ switch: "generic",
26523
+ doorbell: "button"
26524
+ };
26525
+ function legacyIcon(iconId) {
26526
+ return LEGACY_ICON[iconId] ?? "generic";
26527
+ }
26528
+ var CAP_TO_KIND = {
26529
+ contact: "contact",
26530
+ motion: "motion-sensor",
26531
+ smoke: "smoke",
26532
+ flood: "flood",
26533
+ gas: "gas",
26534
+ "carbon-monoxide": "carbon-monoxide",
26535
+ vibration: "vibration",
26536
+ tamper: "tamper",
26537
+ presence: "presence",
26538
+ "enum-sensor": "enum-sensor",
26539
+ "event-emitter": "device-event",
26540
+ "lock-control": "lock",
26541
+ switch: "switch",
26542
+ button: "button",
26543
+ doorbell: "doorbell"
26544
+ };
26545
+ function buildDescriptor(capName, kind) {
26546
+ const t = EVENT_TAXONOMY[kind];
26547
+ if (t === void 0) throw new Error(`EVENT_KIND_BY_CAP: cap '${capName}' maps to unknown taxonomy kind '${kind}'`);
26548
+ return {
26549
+ ...t,
26550
+ icon: legacyIcon(t.iconId)
26551
+ };
26552
+ }
26553
+ var EVENT_KIND_BY_CAP = Object.freeze(Object.fromEntries(Object.entries(CAP_TO_KIND).map(([capName, kind]) => [capName, buildDescriptor(capName, kind)])));
26554
+ var EVENTFUL_CAP_NAMES = Object.keys(CAP_TO_KIND);
26141
26555
  var CameraPipelineConfigSchema = external_exports.object({
26142
26556
  engine: PipelineEngineChoiceSchema.optional(),
26143
26557
  steps: external_exports.array(PipelineStepInputSchema).readonly(),
@@ -30017,14 +30431,43 @@ var recordingCapability = {
30017
30431
  auth: "admin"
30018
30432
  }),
30019
30433
  /** Apply this device's retention policy to footage now; returns the oldest
30020
- * surviving footage start (the retention floor) or null if no footage. */
30021
- pruneFootage: method(external_exports.object({ deviceId: external_exports.number() }), external_exports.object({
30434
+ * surviving footage start (the retention floor) or null if no footage. The
30435
+ * prune is logged to the recordings ops-log with `reason` (default
30436
+ * `'retention'` — the policy-driven prune; `'quota'` when disk-pressure
30437
+ * triggered). */
30438
+ pruneFootage: method(external_exports.object({
30439
+ deviceId: external_exports.number(),
30440
+ reason: OpsLogReasonSchema.optional()
30441
+ }), external_exports.object({
30022
30442
  floorMs: external_exports.number().nullable(),
30023
30443
  deletedBuckets: external_exports.number().int(),
30024
30444
  reclaimedBytes: external_exports.number().int()
30025
30445
  }), {
30026
30446
  kind: "mutation",
30027
30447
  auth: "admin"
30448
+ }),
30449
+ /**
30450
+ * Manually delete a camera's footage — the whole footprint, or a
30451
+ * `[fromMs, toMs)` window when either bound is given. Logged to the
30452
+ * recordings ops-log as `op:'manual-delete', reason:'manual'`. Destructive:
30453
+ * the admin UI guards it behind a confirm.
30454
+ */
30455
+ deleteFootprint: method(external_exports.object({
30456
+ deviceId: external_exports.number(),
30457
+ fromMs: external_exports.number().optional(),
30458
+ toMs: external_exports.number().optional()
30459
+ }), external_exports.object({
30460
+ deletedBuckets: external_exports.number().int(),
30461
+ reclaimedBytes: external_exports.number().int()
30462
+ }), {
30463
+ kind: "mutation",
30464
+ auth: "admin"
30465
+ }),
30466
+ /** The recordings ops-log rows (newest-first), optionally scoped to one
30467
+ * camera. Backed by the recorder's bounded DurableState ring. */
30468
+ listOpsLog: method(OpsLogQueryInputSchema, external_exports.array(OpsLogEntrySchema).readonly(), {
30469
+ kind: "query",
30470
+ auth: "admin"
30028
30471
  })
30029
30472
  }
30030
30473
  };
@@ -33163,6 +33606,12 @@ var METHOD_ACCESS_MAP = Object.freeze({
33163
33606
  addonId: null,
33164
33607
  access: "delete"
33165
33608
  },
33609
+ "pipelineAnalytics.deleteDeviceEvents": {
33610
+ capName: "pipeline-analytics",
33611
+ capScope: "device",
33612
+ addonId: null,
33613
+ access: "delete"
33614
+ },
33166
33615
  "pipelineAnalytics.deleteTracks": {
33167
33616
  capName: "pipeline-analytics",
33168
33617
  capScope: "device",
@@ -33193,6 +33642,12 @@ var METHOD_ACCESS_MAP = Object.freeze({
33193
33642
  addonId: null,
33194
33643
  access: "view"
33195
33644
  },
33645
+ "pipelineAnalytics.getEventStoreFootprint": {
33646
+ capName: "pipeline-analytics",
33647
+ capScope: "device",
33648
+ addonId: null,
33649
+ access: "view"
33650
+ },
33196
33651
  "pipelineAnalytics.getKeyEvents": {
33197
33652
  capName: "pipeline-analytics",
33198
33653
  capScope: "device",
@@ -33235,6 +33690,12 @@ var METHOD_ACCESS_MAP = Object.freeze({
33235
33690
  addonId: null,
33236
33691
  access: "view"
33237
33692
  },
33693
+ "pipelineAnalytics.listOpsLog": {
33694
+ capName: "pipeline-analytics",
33695
+ capScope: "device",
33696
+ addonId: null,
33697
+ access: "view"
33698
+ },
33238
33699
  "pipelineAnalytics.listRecentTracks": {
33239
33700
  capName: "pipeline-analytics",
33240
33701
  capScope: "device",
@@ -33247,6 +33708,12 @@ var METHOD_ACCESS_MAP = Object.freeze({
33247
33708
  addonId: null,
33248
33709
  access: "view"
33249
33710
  },
33711
+ "pipelineAnalytics.pruneEvents": {
33712
+ capName: "pipeline-analytics",
33713
+ capScope: "device",
33714
+ addonId: null,
33715
+ access: "create"
33716
+ },
33250
33717
  "pipelineAnalytics.pruneEventsBefore": {
33251
33718
  capName: "pipeline-analytics",
33252
33719
  capScope: "device",
@@ -34009,6 +34476,12 @@ var METHOD_ACCESS_MAP = Object.freeze({
34009
34476
  addonId: null,
34010
34477
  access: "create"
34011
34478
  },
34479
+ "recording.deleteFootprint": {
34480
+ capName: "recording",
34481
+ capScope: "system",
34482
+ addonId: null,
34483
+ access: "delete"
34484
+ },
34012
34485
  "recording.getAvailability": {
34013
34486
  capName: "recording",
34014
34487
  capScope: "system",
@@ -34039,6 +34512,12 @@ var METHOD_ACCESS_MAP = Object.freeze({
34039
34512
  addonId: null,
34040
34513
  access: "view"
34041
34514
  },
34515
+ "recording.listOpsLog": {
34516
+ capName: "recording",
34517
+ capScope: "system",
34518
+ addonId: null,
34519
+ access: "view"
34520
+ },
34042
34521
  "recording.locateSegment": {
34043
34522
  capName: "recording",
34044
34523
  capScope: "system",
package/dist/cli.js CHANGED
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
3
  runDiscover
4
- } from "./chunk-XGNAIFKZ.js";
4
+ } from "./chunk-ZFONIXEK.js";
5
5
  import "./chunk-K3NQKI34.js";
6
6
 
7
7
  // src/cli.ts
@@ -1079,7 +1079,7 @@ function isUnknown(_value) {
1079
1079
  return true;
1080
1080
  }
1081
1081
  async function resolveServerInteractive(presetNamespace) {
1082
- const { discoverNodes, resolveHubFromDiscovered, filterHubNodes, DEFAULT_HUB_HTTPS_PORT } = await import("./discover-EB7LI523.js");
1082
+ const { discoverNodes, resolveHubFromDiscovered, filterHubNodes, DEFAULT_HUB_HTTPS_PORT } = await import("./discover-ZBSZJQ2R.js");
1083
1083
  if (presetNamespace) {
1084
1084
  const spinner4 = clack.spinner();
1085
1085
  spinner4.start(`Discovering hub on LAN (namespace "${presetNamespace}")`);
@@ -5,7 +5,7 @@ import {
5
5
  filterHubNodes,
6
6
  resolveHubFromDiscovered,
7
7
  runDiscover
8
- } from "./chunk-XGNAIFKZ.js";
8
+ } from "./chunk-ZFONIXEK.js";
9
9
  import "./chunk-K3NQKI34.js";
10
10
  export {
11
11
  DEFAULT_HUB_HTTPS_PORT,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "camstack",
3
- "version": "1.1.29",
3
+ "version": "1.1.31",
4
4
  "description": "CLI tool for managing and running CamStack server",
5
5
  "keywords": [
6
6
  "camstack",