@camstack/addon-export-ha-mqtt 1.1.24 → 1.1.26

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.
@@ -36,7 +36,7 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
36
36
  }) : target, mod));
37
37
  var __toCommonJS = (mod) => __hasOwnProp.call(mod, "module.exports") ? mod["module.exports"] : __copyProps(__defProp({}, "__esModule", { value: true }), mod);
38
38
  //#endregion
39
- //#region ../types/dist/event-category-H4AVePnn.mjs
39
+ //#region ../types/dist/event-category-D4HJq7Mw.mjs
40
40
  var EventCategory = /* @__PURE__ */ function(EventCategory) {
41
41
  EventCategory["SystemBoot"] = "system.boot";
42
42
  EventCategory["SystemAddonsReady"] = "system.addons-ready";
@@ -189,6 +189,11 @@ var EventCategory = /* @__PURE__ */ function(EventCategory) {
189
189
  /** Runner-sampled scrub thumbnail (~1/5 s/camera). Telemetry (D8): a lost
190
190
  * thumb is a scrub gap the recorder's keyframe backfill covers. */
191
191
  EventCategory["RecordingThumbSampled"] = "recording.thumb-sampled";
192
+ /** Export render progress (0–100). Telemetry (D8): a lost tick is a stale
193
+ * progress bar the client reconciles via `recordingExport.getExport`. */
194
+ EventCategory["RecordingExportProgress"] = "recording.export.progress";
195
+ EventCategory["RecordingExportCompleted"] = "recording.export.completed";
196
+ EventCategory["RecordingExportFailed"] = "recording.export.failed";
192
197
  EventCategory["DetectionEvent"] = "detection.event";
193
198
  EventCategory["SessionTrackNew"] = "session.track.new";
194
199
  EventCategory["SessionTrackExpired"] = "session.track.expired";
@@ -478,6 +483,25 @@ var EventCategory = /* @__PURE__ */ function(EventCategory) {
478
483
  */
479
484
  EventCategory["PipelineAnalyticsStationaryChanged"] = "pipeline-analytics.stationary-changed";
480
485
  /**
486
+ * Fired by `addon-post-analysis` when a package-drop is confirmed inside
487
+ * a package zone — a newly-appeared stationary object of a package class
488
+ * that cleared the class / zone / dwell / size gates. Payload:
489
+ * `PipelineAnalyticsPackageDeliveredPayload` carrying `{ deviceId,
490
+ * entryId, className, zoneIds, keyFrameMediaKey?, bbox, timestamp }`.
491
+ * Telemetry (D8): the durable record is the `package-events` store row;
492
+ * this bus topic drives notifier rules + live UI. See
493
+ * docs/superpowers/specs/2026-07-17-package-zones-design.md §5.1.
494
+ */
495
+ EventCategory["PipelineAnalyticsPackageDelivered"] = "pipeline-analytics.package-delivered";
496
+ /**
497
+ * Fired by `addon-post-analysis` when a previously-delivered package
498
+ * leaves its zone (the stationary entry departed — moved or swept).
499
+ * Payload: `PipelineAnalyticsPackagePickedUpPayload` carrying
500
+ * `{ deviceId, entryId, deliveredEventId, className, timestamp }`.
501
+ * Telemetry (D8). See package-zones-design §5.2.
502
+ */
503
+ EventCategory["PipelineAnalyticsPackagePickedUp"] = "pipeline-analytics.package-picked-up";
504
+ /**
481
505
  * Fired by `addon-post-analysis` whenever a gallery face row changes:
482
506
  * `kind:'buffered'` a new detected face was persisted, `'assigned'` /
483
507
  * `'unassigned'` its identity link changed, `'deleted'` the row was
@@ -5226,6 +5250,25 @@ function _instanceof(cls, params = {}) {
5226
5250
  return inst;
5227
5251
  }
5228
5252
  //#endregion
5253
+ //#region ../../node_modules/zod/v4/classic/compat.js
5254
+ /** @deprecated Use the raw string literal codes instead, e.g. "invalid_type". */
5255
+ var ZodIssueCode = {
5256
+ invalid_type: "invalid_type",
5257
+ too_big: "too_big",
5258
+ too_small: "too_small",
5259
+ invalid_format: "invalid_format",
5260
+ not_multiple_of: "not_multiple_of",
5261
+ unrecognized_keys: "unrecognized_keys",
5262
+ invalid_union: "invalid_union",
5263
+ invalid_key: "invalid_key",
5264
+ invalid_element: "invalid_element",
5265
+ invalid_value: "invalid_value",
5266
+ custom: "custom"
5267
+ };
5268
+ /** @deprecated Do not use. Stub definition, only included for zod-to-json-schema compatibility. */
5269
+ var ZodFirstPartyTypeKind;
5270
+ ZodFirstPartyTypeKind || (ZodFirstPartyTypeKind = {});
5271
+ //#endregion
5229
5272
  //#region ../../node_modules/zod/v4/classic/coerce.js
5230
5273
  function number(params) {
5231
5274
  return /* @__PURE__ */ _coercedNumber(ZodNumber, params);
@@ -7336,6 +7379,62 @@ var RecordingConfigSchema = object({
7336
7379
  scrubThumbnails: ScrubThumbnailPresetSchema.optional()
7337
7380
  });
7338
7381
  /**
7382
+ * Ops-log — the durable, append-only operations audit shared by the
7383
+ * recordings and events management surfaces.
7384
+ *
7385
+ * ONE row shape is reused for both domains so a single "Activity" view can
7386
+ * merge the recorder's DurableState ring (recordings ops-log) and the
7387
+ * pipeline-analytics SQLite collection (events ops-log). Each row records a
7388
+ * management operation, WHY it ran (reason), and its measurable effect
7389
+ * (itemsAffected + bytesReclaimed). Writes are best-effort — a failed log must
7390
+ * never fail the operation it records.
7391
+ */
7392
+ /** Which management domain the operation belongs to. */
7393
+ var OpsLogDomainSchema = _enum(["recording", "events"]);
7394
+ /** The kind of management operation performed. */
7395
+ var OpsLogOpSchema = _enum([
7396
+ "prune",
7397
+ "manual-delete",
7398
+ "rescan",
7399
+ "retention-run"
7400
+ ]);
7401
+ /** Why the operation ran. */
7402
+ var OpsLogReasonSchema = _enum([
7403
+ "retention",
7404
+ "quota",
7405
+ "manual",
7406
+ "operator"
7407
+ ]);
7408
+ /** One audit row, shared verbatim by both domains. */
7409
+ var OpsLogEntrySchema = object({
7410
+ /** Unique row id. */
7411
+ id: string(),
7412
+ /** Epoch ms the operation completed. */
7413
+ at: number$1(),
7414
+ domain: OpsLogDomainSchema,
7415
+ op: OpsLogOpSchema,
7416
+ reason: OpsLogReasonSchema,
7417
+ /** The camera the op targeted; null for a cluster/global op. */
7418
+ deviceId: number$1().nullable(),
7419
+ /** Node that performed the op (the log carries nodeId — no cross-node aggregation). */
7420
+ nodeId: string(),
7421
+ /** Buckets / rows deleted (op-specific unit). */
7422
+ itemsAffected: number$1(),
7423
+ /** Bytes reclaimed by the op (0 when not measurable). */
7424
+ bytesReclaimed: number$1(),
7425
+ /** Free-text detail (e.g. "floor moved to <ts>"); null when none. */
7426
+ detail: string().nullable(),
7427
+ /** Who/what triggered the op. */
7428
+ actor: string()
7429
+ });
7430
+ /** Shared query input for the per-domain `listOpsLog` cap methods. */
7431
+ var OpsLogQueryInputSchema = object({
7432
+ /** Restrict to a single camera; omit for every row. */
7433
+ deviceId: number$1().optional(),
7434
+ /** Max rows returned, newest-first. */
7435
+ limit: number$1().int().min(1).max(1e3).optional()
7436
+ });
7437
+ /**
7339
7438
  * `StorageLocationType` — an addon-declared id that identifies the *kind* of
7340
7439
  * storage a location serves. Defined here (not in `capabilities/storage.cap.ts`)
7341
7440
  * so the persisted record schema and the consumer-facing cap can both consume it
@@ -12585,7 +12684,11 @@ array(ZoneRuleSchema).readonly();
12585
12684
  * Extend the enum here when a new gating consumer comes online (audio
12586
12685
  * gating, alert filtering, …) — no other surface needs to change.
12587
12686
  */
12588
- var ZoneRuleStageEnum = _enum(["motion", "detection"]);
12687
+ var ZoneRuleStageEnum = _enum([
12688
+ "motion",
12689
+ "detection",
12690
+ "package"
12691
+ ]);
12589
12692
  DeviceType.Camera, method(object({
12590
12693
  deviceId: number$1(),
12591
12694
  stage: ZoneRuleStageEnum
@@ -12598,7 +12701,8 @@ DeviceType.Camera, method(object({
12598
12701
  auth: "admin"
12599
12702
  }), object({
12600
12703
  motion: array(ZoneRuleSchema).readonly(),
12601
- detection: array(ZoneRuleSchema).readonly()
12704
+ detection: array(ZoneRuleSchema).readonly(),
12705
+ package: array(ZoneRuleSchema).readonly()
12602
12706
  });
12603
12707
  var ProviderStatusSchema = object({
12604
12708
  connected: boolean(),
@@ -15806,6 +15910,7 @@ var EventKindIconSchema = _enum([
15806
15910
  "smoke",
15807
15911
  "water",
15808
15912
  "button",
15913
+ "package",
15809
15914
  "generic"
15810
15915
  ]);
15811
15916
  var EventKindCategorySchema = _enum([
@@ -15813,7 +15918,8 @@ var EventKindCategorySchema = _enum([
15813
15918
  "audio",
15814
15919
  "detection",
15815
15920
  "sensor",
15816
- "custom"
15921
+ "custom",
15922
+ "package"
15817
15923
  ]);
15818
15924
  var EventKindDescriptorSchema = object({
15819
15925
  /** Stable kind id (e.g. 'motion', 'person', 'contact'). */
@@ -16154,6 +16260,26 @@ var TrackCascadeCountsSchema = object({
16154
16260
  /** Per-track CLIP search vectors removed (best-effort). */
16155
16261
  embeddings: number$1().int()
16156
16262
  });
16263
+ /** Event-store footprint for one camera. */
16264
+ var EventStoreDeviceFootprintSchema = object({
16265
+ deviceId: number$1(),
16266
+ /** Persisted event rows (motion + object + audio) for the camera. */
16267
+ rows: number$1().int(),
16268
+ /** Event-owned media bytes on disk for the camera. */
16269
+ bytes: number$1().int()
16270
+ });
16271
+ /** Aggregate event-store footprint: global totals + per-camera breakdown. */
16272
+ var EventStoreFootprintSchema = object({
16273
+ totalRows: number$1().int(),
16274
+ totalBytes: number$1().int(),
16275
+ devices: array(EventStoreDeviceFootprintSchema).readonly()
16276
+ });
16277
+ /** Per-kind counts returned by the event-prune / device-delete mutations. */
16278
+ var EventPruneCountsSchema = object({
16279
+ motion: number$1().int(),
16280
+ object: number$1().int(),
16281
+ audio: number$1().int()
16282
+ });
16157
16283
  DeviceType.Camera, method(object({ deviceId: number$1() }), array(TrackSchema).readonly()), method(object({
16158
16284
  deviceId: number$1(),
16159
16285
  trackId: string()
@@ -16217,6 +16343,21 @@ DeviceType.Camera, method(object({ deviceId: number$1() }), array(TrackSchema).r
16217
16343
  }), {
16218
16344
  kind: "mutation",
16219
16345
  auth: "admin"
16346
+ }), method(object({}), EventStoreFootprintSchema, {
16347
+ kind: "query",
16348
+ auth: "admin"
16349
+ }), method(object({
16350
+ olderThanMs: number$1(),
16351
+ reason: OpsLogReasonSchema.optional()
16352
+ }), EventPruneCountsSchema, {
16353
+ kind: "mutation",
16354
+ auth: "admin"
16355
+ }), method(object({ deviceId: number$1() }), EventPruneCountsSchema, {
16356
+ kind: "mutation",
16357
+ auth: "admin"
16358
+ }), method(OpsLogQueryInputSchema, array(OpsLogEntrySchema).readonly(), {
16359
+ kind: "query",
16360
+ auth: "admin"
16220
16361
  }), method(object({
16221
16362
  eventId: string(),
16222
16363
  kind: MediaFileKindEnum.optional()
@@ -19450,13 +19591,131 @@ method(object({
19450
19591
  }), method(object({ deviceId: number$1() }), RecordingStatusSchema, {
19451
19592
  kind: "mutation",
19452
19593
  auth: "admin"
19453
- }), method(object({ deviceId: number$1() }), object({
19594
+ }), method(object({
19595
+ deviceId: number$1(),
19596
+ reason: OpsLogReasonSchema.optional()
19597
+ }), object({
19454
19598
  floorMs: number$1().nullable(),
19455
19599
  deletedBuckets: number$1().int(),
19456
19600
  reclaimedBytes: number$1().int()
19457
19601
  }), {
19458
19602
  kind: "mutation",
19459
19603
  auth: "admin"
19604
+ }), method(object({
19605
+ deviceId: number$1(),
19606
+ fromMs: number$1().optional(),
19607
+ toMs: number$1().optional()
19608
+ }), object({
19609
+ deletedBuckets: number$1().int(),
19610
+ reclaimedBytes: number$1().int()
19611
+ }), {
19612
+ kind: "mutation",
19613
+ auth: "admin"
19614
+ }), method(OpsLogQueryInputSchema, array(OpsLogEntrySchema).readonly(), {
19615
+ kind: "query",
19616
+ auth: "admin"
19617
+ });
19618
+ /**
19619
+ * `recordingExport` cap — render a footage time range into a single downloadable
19620
+ * MP4 (regular / accelerated / decelerated / timelapse, ± audio), kept for a
19621
+ * bounded lifetime with a durable history, auto-expiry, and optional
19622
+ * delete-after-download.
19623
+ *
19624
+ * Like `recording` this is a `scope:'system', mode:'singleton'` cap: the
19625
+ * recorder self-gates so exactly ONE node (the designated `recordingNodeId`,
19626
+ * default `hub`) registers it. Device-scoped methods carry `deviceId` in their
19627
+ * input and dispatch to that single provider; the render runs on the node that
19628
+ * owns the footage (no cross-node segment transfer). Download rides the
19629
+ * framework addon data-plane. State persists in a DurableState blob (NOT
19630
+ * SQLite); history rows survive file deletion for audit.
19631
+ */
19632
+ /** Playback-speed multiplier for the render (1 = realtime). */
19633
+ var ExportSpeedSchema = number$1().min(.25).max(32);
19634
+ /** Timelapse cadence — sample one source frame per `everyMs`, output at `outputFps`. */
19635
+ var ExportTimelapseSchema = object({
19636
+ everyMs: number$1().int().positive(),
19637
+ outputFps: number$1().int().min(1).max(60).optional()
19638
+ });
19639
+ /**
19640
+ * Render options. `speed` and `timelapse` are mutually exclusive. `includeAudio`
19641
+ * is honoured only for a realtime-ish speed (0.5–2×); timelapse is always
19642
+ * silent. `maxLifeMs` bounds how long the finished file is kept;
19643
+ * `deleteAfterDownload` removes it shortly after the first complete download.
19644
+ */
19645
+ var ExportOptionsSchema = object({
19646
+ speed: ExportSpeedSchema.optional(),
19647
+ timelapse: ExportTimelapseSchema.optional(),
19648
+ includeAudio: boolean(),
19649
+ maxLifeMs: number$1().int().positive(),
19650
+ deleteAfterDownload: boolean(),
19651
+ title: string().max(200).optional()
19652
+ }).superRefine((v, ctx) => {
19653
+ if (v.speed !== void 0 && v.timelapse !== void 0) ctx.addIssue({
19654
+ code: ZodIssueCode.custom,
19655
+ message: "speed and timelapse are mutually exclusive",
19656
+ path: ["timelapse"]
19657
+ });
19658
+ });
19659
+ var ExportStateSchema = _enum([
19660
+ "queued",
19661
+ "rendering",
19662
+ "ready",
19663
+ "failed",
19664
+ "expired",
19665
+ "deleted"
19666
+ ]);
19667
+ /** One export job / history row. */
19668
+ var ExportRecordSchema = object({
19669
+ id: string(),
19670
+ deviceId: number$1(),
19671
+ profile: string(),
19672
+ fromMs: number$1(),
19673
+ toMs: number$1(),
19674
+ options: ExportOptionsSchema,
19675
+ state: ExportStateSchema,
19676
+ /** 0–100 while rendering; null otherwise. */
19677
+ progressPct: number$1().nullable(),
19678
+ /** File size once ready; null before. */
19679
+ fileBytes: number$1().nullable(),
19680
+ expiresAt: number$1(),
19681
+ deleteAfterDownload: boolean(),
19682
+ /** Epoch of the first complete download; null until then. */
19683
+ downloadedAt: number$1().nullable(),
19684
+ createdAt: number$1(),
19685
+ /** User id/name that requested the export. */
19686
+ createdBy: string(),
19687
+ /** Failure reason when state is 'failed'; null otherwise. */
19688
+ error: string().nullable()
19689
+ });
19690
+ /** Candidate download URLs (LAN first, then operator extra hosts). */
19691
+ var ExportDownloadSchema = object({
19692
+ url: string(),
19693
+ endpoints: array(string())
19694
+ });
19695
+ method(object({
19696
+ deviceId: number$1(),
19697
+ profile: string(),
19698
+ fromMs: number$1(),
19699
+ toMs: number$1(),
19700
+ options: ExportOptionsSchema
19701
+ }), ExportRecordSchema, {
19702
+ kind: "mutation",
19703
+ auth: "protected"
19704
+ }), method(object({ deviceId: number$1().optional() }), array(ExportRecordSchema), {
19705
+ kind: "query",
19706
+ auth: "protected"
19707
+ }), method(object({ exportId: string() }), ExportRecordSchema, {
19708
+ kind: "query",
19709
+ auth: "protected"
19710
+ }), method(object({ exportId: string() }), ExportRecordSchema, {
19711
+ kind: "mutation",
19712
+ auth: "protected"
19713
+ }), method(object({ exportId: string() }), ExportRecordSchema, {
19714
+ kind: "mutation",
19715
+ auth: "protected"
19716
+ }), method(object({ exportId: string() }), ExportDownloadSchema, {
19717
+ kind: "query",
19718
+ auth: "protected"
19460
19719
  });
19461
19720
  /**
19462
19721
  * One publishable camera stream as its OWNING PROVIDER describes it — the same
@@ -22476,6 +22735,12 @@ Object.freeze({
22476
22735
  addonId: null,
22477
22736
  access: "delete"
22478
22737
  },
22738
+ "pipelineAnalytics.deleteDeviceEvents": {
22739
+ capName: "pipeline-analytics",
22740
+ capScope: "device",
22741
+ addonId: null,
22742
+ access: "delete"
22743
+ },
22479
22744
  "pipelineAnalytics.deleteTracks": {
22480
22745
  capName: "pipeline-analytics",
22481
22746
  capScope: "device",
@@ -22506,6 +22771,12 @@ Object.freeze({
22506
22771
  addonId: null,
22507
22772
  access: "view"
22508
22773
  },
22774
+ "pipelineAnalytics.getEventStoreFootprint": {
22775
+ capName: "pipeline-analytics",
22776
+ capScope: "device",
22777
+ addonId: null,
22778
+ access: "view"
22779
+ },
22509
22780
  "pipelineAnalytics.getKeyEvents": {
22510
22781
  capName: "pipeline-analytics",
22511
22782
  capScope: "device",
@@ -22548,6 +22819,12 @@ Object.freeze({
22548
22819
  addonId: null,
22549
22820
  access: "view"
22550
22821
  },
22822
+ "pipelineAnalytics.listOpsLog": {
22823
+ capName: "pipeline-analytics",
22824
+ capScope: "device",
22825
+ addonId: null,
22826
+ access: "view"
22827
+ },
22551
22828
  "pipelineAnalytics.listRecentTracks": {
22552
22829
  capName: "pipeline-analytics",
22553
22830
  capScope: "device",
@@ -22560,6 +22837,12 @@ Object.freeze({
22560
22837
  addonId: null,
22561
22838
  access: "view"
22562
22839
  },
22840
+ "pipelineAnalytics.pruneEvents": {
22841
+ capName: "pipeline-analytics",
22842
+ capScope: "device",
22843
+ addonId: null,
22844
+ access: "create"
22845
+ },
22563
22846
  "pipelineAnalytics.pruneEventsBefore": {
22564
22847
  capName: "pipeline-analytics",
22565
22848
  capScope: "device",
@@ -23322,6 +23605,12 @@ Object.freeze({
23322
23605
  addonId: null,
23323
23606
  access: "create"
23324
23607
  },
23608
+ "recording.deleteFootprint": {
23609
+ capName: "recording",
23610
+ capScope: "system",
23611
+ addonId: null,
23612
+ access: "delete"
23613
+ },
23325
23614
  "recording.getAvailability": {
23326
23615
  capName: "recording",
23327
23616
  capScope: "system",
@@ -23352,6 +23641,12 @@ Object.freeze({
23352
23641
  addonId: null,
23353
23642
  access: "view"
23354
23643
  },
23644
+ "recording.listOpsLog": {
23645
+ capName: "recording",
23646
+ capScope: "system",
23647
+ addonId: null,
23648
+ access: "view"
23649
+ },
23355
23650
  "recording.locateSegment": {
23356
23651
  capName: "recording",
23357
23652
  capScope: "system",
@@ -23382,6 +23677,42 @@ Object.freeze({
23382
23677
  addonId: null,
23383
23678
  access: "create"
23384
23679
  },
23680
+ "recordingExport.cancelExport": {
23681
+ capName: "recordingExport",
23682
+ capScope: "system",
23683
+ addonId: null,
23684
+ access: "create"
23685
+ },
23686
+ "recordingExport.createExport": {
23687
+ capName: "recordingExport",
23688
+ capScope: "system",
23689
+ addonId: null,
23690
+ access: "create"
23691
+ },
23692
+ "recordingExport.deleteExport": {
23693
+ capName: "recordingExport",
23694
+ capScope: "system",
23695
+ addonId: null,
23696
+ access: "delete"
23697
+ },
23698
+ "recordingExport.getDownloadUrl": {
23699
+ capName: "recordingExport",
23700
+ capScope: "system",
23701
+ addonId: null,
23702
+ access: "view"
23703
+ },
23704
+ "recordingExport.getExport": {
23705
+ capName: "recordingExport",
23706
+ capScope: "system",
23707
+ addonId: null,
23708
+ access: "view"
23709
+ },
23710
+ "recordingExport.listExports": {
23711
+ capName: "recordingExport",
23712
+ capScope: "system",
23713
+ addonId: null,
23714
+ access: "view"
23715
+ },
23385
23716
  "sceneMonitor.captureReference": {
23386
23717
  capName: "scene-monitor",
23387
23718
  capScope: "device",
@@ -34,7 +34,7 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
34
34
  var __toCommonJS = (mod) => __hasOwnProp.call(mod, "module.exports") ? mod["module.exports"] : __copyProps(__defProp({}, "__esModule", { value: true }), mod);
35
35
  var __require = /* @__PURE__ */ createRequire(import.meta.url);
36
36
  //#endregion
37
- //#region ../types/dist/event-category-H4AVePnn.mjs
37
+ //#region ../types/dist/event-category-D4HJq7Mw.mjs
38
38
  var EventCategory = /* @__PURE__ */ function(EventCategory) {
39
39
  EventCategory["SystemBoot"] = "system.boot";
40
40
  EventCategory["SystemAddonsReady"] = "system.addons-ready";
@@ -187,6 +187,11 @@ var EventCategory = /* @__PURE__ */ function(EventCategory) {
187
187
  /** Runner-sampled scrub thumbnail (~1/5 s/camera). Telemetry (D8): a lost
188
188
  * thumb is a scrub gap the recorder's keyframe backfill covers. */
189
189
  EventCategory["RecordingThumbSampled"] = "recording.thumb-sampled";
190
+ /** Export render progress (0–100). Telemetry (D8): a lost tick is a stale
191
+ * progress bar the client reconciles via `recordingExport.getExport`. */
192
+ EventCategory["RecordingExportProgress"] = "recording.export.progress";
193
+ EventCategory["RecordingExportCompleted"] = "recording.export.completed";
194
+ EventCategory["RecordingExportFailed"] = "recording.export.failed";
190
195
  EventCategory["DetectionEvent"] = "detection.event";
191
196
  EventCategory["SessionTrackNew"] = "session.track.new";
192
197
  EventCategory["SessionTrackExpired"] = "session.track.expired";
@@ -476,6 +481,25 @@ var EventCategory = /* @__PURE__ */ function(EventCategory) {
476
481
  */
477
482
  EventCategory["PipelineAnalyticsStationaryChanged"] = "pipeline-analytics.stationary-changed";
478
483
  /**
484
+ * Fired by `addon-post-analysis` when a package-drop is confirmed inside
485
+ * a package zone — a newly-appeared stationary object of a package class
486
+ * that cleared the class / zone / dwell / size gates. Payload:
487
+ * `PipelineAnalyticsPackageDeliveredPayload` carrying `{ deviceId,
488
+ * entryId, className, zoneIds, keyFrameMediaKey?, bbox, timestamp }`.
489
+ * Telemetry (D8): the durable record is the `package-events` store row;
490
+ * this bus topic drives notifier rules + live UI. See
491
+ * docs/superpowers/specs/2026-07-17-package-zones-design.md §5.1.
492
+ */
493
+ EventCategory["PipelineAnalyticsPackageDelivered"] = "pipeline-analytics.package-delivered";
494
+ /**
495
+ * Fired by `addon-post-analysis` when a previously-delivered package
496
+ * leaves its zone (the stationary entry departed — moved or swept).
497
+ * Payload: `PipelineAnalyticsPackagePickedUpPayload` carrying
498
+ * `{ deviceId, entryId, deliveredEventId, className, timestamp }`.
499
+ * Telemetry (D8). See package-zones-design §5.2.
500
+ */
501
+ EventCategory["PipelineAnalyticsPackagePickedUp"] = "pipeline-analytics.package-picked-up";
502
+ /**
479
503
  * Fired by `addon-post-analysis` whenever a gallery face row changes:
480
504
  * `kind:'buffered'` a new detected face was persisted, `'assigned'` /
481
505
  * `'unassigned'` its identity link changed, `'deleted'` the row was
@@ -5224,6 +5248,25 @@ function _instanceof(cls, params = {}) {
5224
5248
  return inst;
5225
5249
  }
5226
5250
  //#endregion
5251
+ //#region ../../node_modules/zod/v4/classic/compat.js
5252
+ /** @deprecated Use the raw string literal codes instead, e.g. "invalid_type". */
5253
+ var ZodIssueCode = {
5254
+ invalid_type: "invalid_type",
5255
+ too_big: "too_big",
5256
+ too_small: "too_small",
5257
+ invalid_format: "invalid_format",
5258
+ not_multiple_of: "not_multiple_of",
5259
+ unrecognized_keys: "unrecognized_keys",
5260
+ invalid_union: "invalid_union",
5261
+ invalid_key: "invalid_key",
5262
+ invalid_element: "invalid_element",
5263
+ invalid_value: "invalid_value",
5264
+ custom: "custom"
5265
+ };
5266
+ /** @deprecated Do not use. Stub definition, only included for zod-to-json-schema compatibility. */
5267
+ var ZodFirstPartyTypeKind;
5268
+ ZodFirstPartyTypeKind || (ZodFirstPartyTypeKind = {});
5269
+ //#endregion
5227
5270
  //#region ../../node_modules/zod/v4/classic/coerce.js
5228
5271
  function number(params) {
5229
5272
  return /* @__PURE__ */ _coercedNumber(ZodNumber, params);
@@ -7334,6 +7377,62 @@ var RecordingConfigSchema = object({
7334
7377
  scrubThumbnails: ScrubThumbnailPresetSchema.optional()
7335
7378
  });
7336
7379
  /**
7380
+ * Ops-log — the durable, append-only operations audit shared by the
7381
+ * recordings and events management surfaces.
7382
+ *
7383
+ * ONE row shape is reused for both domains so a single "Activity" view can
7384
+ * merge the recorder's DurableState ring (recordings ops-log) and the
7385
+ * pipeline-analytics SQLite collection (events ops-log). Each row records a
7386
+ * management operation, WHY it ran (reason), and its measurable effect
7387
+ * (itemsAffected + bytesReclaimed). Writes are best-effort — a failed log must
7388
+ * never fail the operation it records.
7389
+ */
7390
+ /** Which management domain the operation belongs to. */
7391
+ var OpsLogDomainSchema = _enum(["recording", "events"]);
7392
+ /** The kind of management operation performed. */
7393
+ var OpsLogOpSchema = _enum([
7394
+ "prune",
7395
+ "manual-delete",
7396
+ "rescan",
7397
+ "retention-run"
7398
+ ]);
7399
+ /** Why the operation ran. */
7400
+ var OpsLogReasonSchema = _enum([
7401
+ "retention",
7402
+ "quota",
7403
+ "manual",
7404
+ "operator"
7405
+ ]);
7406
+ /** One audit row, shared verbatim by both domains. */
7407
+ var OpsLogEntrySchema = object({
7408
+ /** Unique row id. */
7409
+ id: string(),
7410
+ /** Epoch ms the operation completed. */
7411
+ at: number$1(),
7412
+ domain: OpsLogDomainSchema,
7413
+ op: OpsLogOpSchema,
7414
+ reason: OpsLogReasonSchema,
7415
+ /** The camera the op targeted; null for a cluster/global op. */
7416
+ deviceId: number$1().nullable(),
7417
+ /** Node that performed the op (the log carries nodeId — no cross-node aggregation). */
7418
+ nodeId: string(),
7419
+ /** Buckets / rows deleted (op-specific unit). */
7420
+ itemsAffected: number$1(),
7421
+ /** Bytes reclaimed by the op (0 when not measurable). */
7422
+ bytesReclaimed: number$1(),
7423
+ /** Free-text detail (e.g. "floor moved to <ts>"); null when none. */
7424
+ detail: string().nullable(),
7425
+ /** Who/what triggered the op. */
7426
+ actor: string()
7427
+ });
7428
+ /** Shared query input for the per-domain `listOpsLog` cap methods. */
7429
+ var OpsLogQueryInputSchema = object({
7430
+ /** Restrict to a single camera; omit for every row. */
7431
+ deviceId: number$1().optional(),
7432
+ /** Max rows returned, newest-first. */
7433
+ limit: number$1().int().min(1).max(1e3).optional()
7434
+ });
7435
+ /**
7337
7436
  * `StorageLocationType` — an addon-declared id that identifies the *kind* of
7338
7437
  * storage a location serves. Defined here (not in `capabilities/storage.cap.ts`)
7339
7438
  * so the persisted record schema and the consumer-facing cap can both consume it
@@ -12583,7 +12682,11 @@ array(ZoneRuleSchema).readonly();
12583
12682
  * Extend the enum here when a new gating consumer comes online (audio
12584
12683
  * gating, alert filtering, …) — no other surface needs to change.
12585
12684
  */
12586
- var ZoneRuleStageEnum = _enum(["motion", "detection"]);
12685
+ var ZoneRuleStageEnum = _enum([
12686
+ "motion",
12687
+ "detection",
12688
+ "package"
12689
+ ]);
12587
12690
  DeviceType.Camera, method(object({
12588
12691
  deviceId: number$1(),
12589
12692
  stage: ZoneRuleStageEnum
@@ -12596,7 +12699,8 @@ DeviceType.Camera, method(object({
12596
12699
  auth: "admin"
12597
12700
  }), object({
12598
12701
  motion: array(ZoneRuleSchema).readonly(),
12599
- detection: array(ZoneRuleSchema).readonly()
12702
+ detection: array(ZoneRuleSchema).readonly(),
12703
+ package: array(ZoneRuleSchema).readonly()
12600
12704
  });
12601
12705
  var ProviderStatusSchema = object({
12602
12706
  connected: boolean(),
@@ -15804,6 +15908,7 @@ var EventKindIconSchema = _enum([
15804
15908
  "smoke",
15805
15909
  "water",
15806
15910
  "button",
15911
+ "package",
15807
15912
  "generic"
15808
15913
  ]);
15809
15914
  var EventKindCategorySchema = _enum([
@@ -15811,7 +15916,8 @@ var EventKindCategorySchema = _enum([
15811
15916
  "audio",
15812
15917
  "detection",
15813
15918
  "sensor",
15814
- "custom"
15919
+ "custom",
15920
+ "package"
15815
15921
  ]);
15816
15922
  var EventKindDescriptorSchema = object({
15817
15923
  /** Stable kind id (e.g. 'motion', 'person', 'contact'). */
@@ -16152,6 +16258,26 @@ var TrackCascadeCountsSchema = object({
16152
16258
  /** Per-track CLIP search vectors removed (best-effort). */
16153
16259
  embeddings: number$1().int()
16154
16260
  });
16261
+ /** Event-store footprint for one camera. */
16262
+ var EventStoreDeviceFootprintSchema = object({
16263
+ deviceId: number$1(),
16264
+ /** Persisted event rows (motion + object + audio) for the camera. */
16265
+ rows: number$1().int(),
16266
+ /** Event-owned media bytes on disk for the camera. */
16267
+ bytes: number$1().int()
16268
+ });
16269
+ /** Aggregate event-store footprint: global totals + per-camera breakdown. */
16270
+ var EventStoreFootprintSchema = object({
16271
+ totalRows: number$1().int(),
16272
+ totalBytes: number$1().int(),
16273
+ devices: array(EventStoreDeviceFootprintSchema).readonly()
16274
+ });
16275
+ /** Per-kind counts returned by the event-prune / device-delete mutations. */
16276
+ var EventPruneCountsSchema = object({
16277
+ motion: number$1().int(),
16278
+ object: number$1().int(),
16279
+ audio: number$1().int()
16280
+ });
16155
16281
  DeviceType.Camera, method(object({ deviceId: number$1() }), array(TrackSchema).readonly()), method(object({
16156
16282
  deviceId: number$1(),
16157
16283
  trackId: string()
@@ -16215,6 +16341,21 @@ DeviceType.Camera, method(object({ deviceId: number$1() }), array(TrackSchema).r
16215
16341
  }), {
16216
16342
  kind: "mutation",
16217
16343
  auth: "admin"
16344
+ }), method(object({}), EventStoreFootprintSchema, {
16345
+ kind: "query",
16346
+ auth: "admin"
16347
+ }), method(object({
16348
+ olderThanMs: number$1(),
16349
+ reason: OpsLogReasonSchema.optional()
16350
+ }), EventPruneCountsSchema, {
16351
+ kind: "mutation",
16352
+ auth: "admin"
16353
+ }), method(object({ deviceId: number$1() }), EventPruneCountsSchema, {
16354
+ kind: "mutation",
16355
+ auth: "admin"
16356
+ }), method(OpsLogQueryInputSchema, array(OpsLogEntrySchema).readonly(), {
16357
+ kind: "query",
16358
+ auth: "admin"
16218
16359
  }), method(object({
16219
16360
  eventId: string(),
16220
16361
  kind: MediaFileKindEnum.optional()
@@ -19448,13 +19589,131 @@ method(object({
19448
19589
  }), method(object({ deviceId: number$1() }), RecordingStatusSchema, {
19449
19590
  kind: "mutation",
19450
19591
  auth: "admin"
19451
- }), method(object({ deviceId: number$1() }), object({
19592
+ }), method(object({
19593
+ deviceId: number$1(),
19594
+ reason: OpsLogReasonSchema.optional()
19595
+ }), object({
19452
19596
  floorMs: number$1().nullable(),
19453
19597
  deletedBuckets: number$1().int(),
19454
19598
  reclaimedBytes: number$1().int()
19455
19599
  }), {
19456
19600
  kind: "mutation",
19457
19601
  auth: "admin"
19602
+ }), method(object({
19603
+ deviceId: number$1(),
19604
+ fromMs: number$1().optional(),
19605
+ toMs: number$1().optional()
19606
+ }), object({
19607
+ deletedBuckets: number$1().int(),
19608
+ reclaimedBytes: number$1().int()
19609
+ }), {
19610
+ kind: "mutation",
19611
+ auth: "admin"
19612
+ }), method(OpsLogQueryInputSchema, array(OpsLogEntrySchema).readonly(), {
19613
+ kind: "query",
19614
+ auth: "admin"
19615
+ });
19616
+ /**
19617
+ * `recordingExport` cap — render a footage time range into a single downloadable
19618
+ * MP4 (regular / accelerated / decelerated / timelapse, ± audio), kept for a
19619
+ * bounded lifetime with a durable history, auto-expiry, and optional
19620
+ * delete-after-download.
19621
+ *
19622
+ * Like `recording` this is a `scope:'system', mode:'singleton'` cap: the
19623
+ * recorder self-gates so exactly ONE node (the designated `recordingNodeId`,
19624
+ * default `hub`) registers it. Device-scoped methods carry `deviceId` in their
19625
+ * input and dispatch to that single provider; the render runs on the node that
19626
+ * owns the footage (no cross-node segment transfer). Download rides the
19627
+ * framework addon data-plane. State persists in a DurableState blob (NOT
19628
+ * SQLite); history rows survive file deletion for audit.
19629
+ */
19630
+ /** Playback-speed multiplier for the render (1 = realtime). */
19631
+ var ExportSpeedSchema = number$1().min(.25).max(32);
19632
+ /** Timelapse cadence — sample one source frame per `everyMs`, output at `outputFps`. */
19633
+ var ExportTimelapseSchema = object({
19634
+ everyMs: number$1().int().positive(),
19635
+ outputFps: number$1().int().min(1).max(60).optional()
19636
+ });
19637
+ /**
19638
+ * Render options. `speed` and `timelapse` are mutually exclusive. `includeAudio`
19639
+ * is honoured only for a realtime-ish speed (0.5–2×); timelapse is always
19640
+ * silent. `maxLifeMs` bounds how long the finished file is kept;
19641
+ * `deleteAfterDownload` removes it shortly after the first complete download.
19642
+ */
19643
+ var ExportOptionsSchema = object({
19644
+ speed: ExportSpeedSchema.optional(),
19645
+ timelapse: ExportTimelapseSchema.optional(),
19646
+ includeAudio: boolean(),
19647
+ maxLifeMs: number$1().int().positive(),
19648
+ deleteAfterDownload: boolean(),
19649
+ title: string().max(200).optional()
19650
+ }).superRefine((v, ctx) => {
19651
+ if (v.speed !== void 0 && v.timelapse !== void 0) ctx.addIssue({
19652
+ code: ZodIssueCode.custom,
19653
+ message: "speed and timelapse are mutually exclusive",
19654
+ path: ["timelapse"]
19655
+ });
19656
+ });
19657
+ var ExportStateSchema = _enum([
19658
+ "queued",
19659
+ "rendering",
19660
+ "ready",
19661
+ "failed",
19662
+ "expired",
19663
+ "deleted"
19664
+ ]);
19665
+ /** One export job / history row. */
19666
+ var ExportRecordSchema = object({
19667
+ id: string(),
19668
+ deviceId: number$1(),
19669
+ profile: string(),
19670
+ fromMs: number$1(),
19671
+ toMs: number$1(),
19672
+ options: ExportOptionsSchema,
19673
+ state: ExportStateSchema,
19674
+ /** 0–100 while rendering; null otherwise. */
19675
+ progressPct: number$1().nullable(),
19676
+ /** File size once ready; null before. */
19677
+ fileBytes: number$1().nullable(),
19678
+ expiresAt: number$1(),
19679
+ deleteAfterDownload: boolean(),
19680
+ /** Epoch of the first complete download; null until then. */
19681
+ downloadedAt: number$1().nullable(),
19682
+ createdAt: number$1(),
19683
+ /** User id/name that requested the export. */
19684
+ createdBy: string(),
19685
+ /** Failure reason when state is 'failed'; null otherwise. */
19686
+ error: string().nullable()
19687
+ });
19688
+ /** Candidate download URLs (LAN first, then operator extra hosts). */
19689
+ var ExportDownloadSchema = object({
19690
+ url: string(),
19691
+ endpoints: array(string())
19692
+ });
19693
+ method(object({
19694
+ deviceId: number$1(),
19695
+ profile: string(),
19696
+ fromMs: number$1(),
19697
+ toMs: number$1(),
19698
+ options: ExportOptionsSchema
19699
+ }), ExportRecordSchema, {
19700
+ kind: "mutation",
19701
+ auth: "protected"
19702
+ }), method(object({ deviceId: number$1().optional() }), array(ExportRecordSchema), {
19703
+ kind: "query",
19704
+ auth: "protected"
19705
+ }), method(object({ exportId: string() }), ExportRecordSchema, {
19706
+ kind: "query",
19707
+ auth: "protected"
19708
+ }), method(object({ exportId: string() }), ExportRecordSchema, {
19709
+ kind: "mutation",
19710
+ auth: "protected"
19711
+ }), method(object({ exportId: string() }), ExportRecordSchema, {
19712
+ kind: "mutation",
19713
+ auth: "protected"
19714
+ }), method(object({ exportId: string() }), ExportDownloadSchema, {
19715
+ kind: "query",
19716
+ auth: "protected"
19458
19717
  });
19459
19718
  /**
19460
19719
  * One publishable camera stream as its OWNING PROVIDER describes it — the same
@@ -22474,6 +22733,12 @@ Object.freeze({
22474
22733
  addonId: null,
22475
22734
  access: "delete"
22476
22735
  },
22736
+ "pipelineAnalytics.deleteDeviceEvents": {
22737
+ capName: "pipeline-analytics",
22738
+ capScope: "device",
22739
+ addonId: null,
22740
+ access: "delete"
22741
+ },
22477
22742
  "pipelineAnalytics.deleteTracks": {
22478
22743
  capName: "pipeline-analytics",
22479
22744
  capScope: "device",
@@ -22504,6 +22769,12 @@ Object.freeze({
22504
22769
  addonId: null,
22505
22770
  access: "view"
22506
22771
  },
22772
+ "pipelineAnalytics.getEventStoreFootprint": {
22773
+ capName: "pipeline-analytics",
22774
+ capScope: "device",
22775
+ addonId: null,
22776
+ access: "view"
22777
+ },
22507
22778
  "pipelineAnalytics.getKeyEvents": {
22508
22779
  capName: "pipeline-analytics",
22509
22780
  capScope: "device",
@@ -22546,6 +22817,12 @@ Object.freeze({
22546
22817
  addonId: null,
22547
22818
  access: "view"
22548
22819
  },
22820
+ "pipelineAnalytics.listOpsLog": {
22821
+ capName: "pipeline-analytics",
22822
+ capScope: "device",
22823
+ addonId: null,
22824
+ access: "view"
22825
+ },
22549
22826
  "pipelineAnalytics.listRecentTracks": {
22550
22827
  capName: "pipeline-analytics",
22551
22828
  capScope: "device",
@@ -22558,6 +22835,12 @@ Object.freeze({
22558
22835
  addonId: null,
22559
22836
  access: "view"
22560
22837
  },
22838
+ "pipelineAnalytics.pruneEvents": {
22839
+ capName: "pipeline-analytics",
22840
+ capScope: "device",
22841
+ addonId: null,
22842
+ access: "create"
22843
+ },
22561
22844
  "pipelineAnalytics.pruneEventsBefore": {
22562
22845
  capName: "pipeline-analytics",
22563
22846
  capScope: "device",
@@ -23320,6 +23603,12 @@ Object.freeze({
23320
23603
  addonId: null,
23321
23604
  access: "create"
23322
23605
  },
23606
+ "recording.deleteFootprint": {
23607
+ capName: "recording",
23608
+ capScope: "system",
23609
+ addonId: null,
23610
+ access: "delete"
23611
+ },
23323
23612
  "recording.getAvailability": {
23324
23613
  capName: "recording",
23325
23614
  capScope: "system",
@@ -23350,6 +23639,12 @@ Object.freeze({
23350
23639
  addonId: null,
23351
23640
  access: "view"
23352
23641
  },
23642
+ "recording.listOpsLog": {
23643
+ capName: "recording",
23644
+ capScope: "system",
23645
+ addonId: null,
23646
+ access: "view"
23647
+ },
23353
23648
  "recording.locateSegment": {
23354
23649
  capName: "recording",
23355
23650
  capScope: "system",
@@ -23380,6 +23675,42 @@ Object.freeze({
23380
23675
  addonId: null,
23381
23676
  access: "create"
23382
23677
  },
23678
+ "recordingExport.cancelExport": {
23679
+ capName: "recordingExport",
23680
+ capScope: "system",
23681
+ addonId: null,
23682
+ access: "create"
23683
+ },
23684
+ "recordingExport.createExport": {
23685
+ capName: "recordingExport",
23686
+ capScope: "system",
23687
+ addonId: null,
23688
+ access: "create"
23689
+ },
23690
+ "recordingExport.deleteExport": {
23691
+ capName: "recordingExport",
23692
+ capScope: "system",
23693
+ addonId: null,
23694
+ access: "delete"
23695
+ },
23696
+ "recordingExport.getDownloadUrl": {
23697
+ capName: "recordingExport",
23698
+ capScope: "system",
23699
+ addonId: null,
23700
+ access: "view"
23701
+ },
23702
+ "recordingExport.getExport": {
23703
+ capName: "recordingExport",
23704
+ capScope: "system",
23705
+ addonId: null,
23706
+ access: "view"
23707
+ },
23708
+ "recordingExport.listExports": {
23709
+ capName: "recordingExport",
23710
+ capScope: "system",
23711
+ addonId: null,
23712
+ access: "view"
23713
+ },
23383
23714
  "sceneMonitor.captureReference": {
23384
23715
  capName: "scene-monitor",
23385
23716
  capScope: "device",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@camstack/addon-export-ha-mqtt",
3
- "version": "1.1.24",
3
+ "version": "1.1.26",
4
4
  "description": "HomeAssistant MQTT discovery exporter for CamStack devices. Publishes discovery topics so HA auto-creates entities for exposed cameras/switches/intercoms/sensors.",
5
5
  "keywords": [
6
6
  "camstack",