@camstack/addon-provider-unifi 0.1.11 → 0.1.13
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 +347 -8
- package/dist/addon.mjs +347 -8
- package/package.json +1 -1
package/dist/addon.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
2
|
-
//#region ../types/dist/event-category-
|
|
2
|
+
//#region ../types/dist/event-category-D4HJq7Mw.mjs
|
|
3
3
|
var EventCategory = /* @__PURE__ */ function(EventCategory) {
|
|
4
4
|
EventCategory["SystemBoot"] = "system.boot";
|
|
5
5
|
EventCategory["SystemAddonsReady"] = "system.addons-ready";
|
|
@@ -152,6 +152,11 @@ var EventCategory = /* @__PURE__ */ function(EventCategory) {
|
|
|
152
152
|
/** Runner-sampled scrub thumbnail (~1/5 s/camera). Telemetry (D8): a lost
|
|
153
153
|
* thumb is a scrub gap the recorder's keyframe backfill covers. */
|
|
154
154
|
EventCategory["RecordingThumbSampled"] = "recording.thumb-sampled";
|
|
155
|
+
/** Export render progress (0–100). Telemetry (D8): a lost tick is a stale
|
|
156
|
+
* progress bar the client reconciles via `recordingExport.getExport`. */
|
|
157
|
+
EventCategory["RecordingExportProgress"] = "recording.export.progress";
|
|
158
|
+
EventCategory["RecordingExportCompleted"] = "recording.export.completed";
|
|
159
|
+
EventCategory["RecordingExportFailed"] = "recording.export.failed";
|
|
155
160
|
EventCategory["DetectionEvent"] = "detection.event";
|
|
156
161
|
EventCategory["SessionTrackNew"] = "session.track.new";
|
|
157
162
|
EventCategory["SessionTrackExpired"] = "session.track.expired";
|
|
@@ -441,6 +446,25 @@ var EventCategory = /* @__PURE__ */ function(EventCategory) {
|
|
|
441
446
|
*/
|
|
442
447
|
EventCategory["PipelineAnalyticsStationaryChanged"] = "pipeline-analytics.stationary-changed";
|
|
443
448
|
/**
|
|
449
|
+
* Fired by `addon-post-analysis` when a package-drop is confirmed inside
|
|
450
|
+
* a package zone — a newly-appeared stationary object of a package class
|
|
451
|
+
* that cleared the class / zone / dwell / size gates. Payload:
|
|
452
|
+
* `PipelineAnalyticsPackageDeliveredPayload` carrying `{ deviceId,
|
|
453
|
+
* entryId, className, zoneIds, keyFrameMediaKey?, bbox, timestamp }`.
|
|
454
|
+
* Telemetry (D8): the durable record is the `package-events` store row;
|
|
455
|
+
* this bus topic drives notifier rules + live UI. See
|
|
456
|
+
* docs/superpowers/specs/2026-07-17-package-zones-design.md §5.1.
|
|
457
|
+
*/
|
|
458
|
+
EventCategory["PipelineAnalyticsPackageDelivered"] = "pipeline-analytics.package-delivered";
|
|
459
|
+
/**
|
|
460
|
+
* Fired by `addon-post-analysis` when a previously-delivered package
|
|
461
|
+
* leaves its zone (the stationary entry departed — moved or swept).
|
|
462
|
+
* Payload: `PipelineAnalyticsPackagePickedUpPayload` carrying
|
|
463
|
+
* `{ deviceId, entryId, deliveredEventId, className, timestamp }`.
|
|
464
|
+
* Telemetry (D8). See package-zones-design §5.2.
|
|
465
|
+
*/
|
|
466
|
+
EventCategory["PipelineAnalyticsPackagePickedUp"] = "pipeline-analytics.package-picked-up";
|
|
467
|
+
/**
|
|
444
468
|
* Fired by `addon-post-analysis` whenever a gallery face row changes:
|
|
445
469
|
* `kind:'buffered'` a new detected face was persisted, `'assigned'` /
|
|
446
470
|
* `'unassigned'` its identity link changed, `'deleted'` the row was
|
|
@@ -5193,6 +5217,25 @@ function preprocess(fn, schema) {
|
|
|
5193
5217
|
out: schema
|
|
5194
5218
|
});
|
|
5195
5219
|
}
|
|
5220
|
+
//#endregion
|
|
5221
|
+
//#region ../../node_modules/zod/v4/classic/compat.js
|
|
5222
|
+
/** @deprecated Use the raw string literal codes instead, e.g. "invalid_type". */
|
|
5223
|
+
var ZodIssueCode = {
|
|
5224
|
+
invalid_type: "invalid_type",
|
|
5225
|
+
too_big: "too_big",
|
|
5226
|
+
too_small: "too_small",
|
|
5227
|
+
invalid_format: "invalid_format",
|
|
5228
|
+
not_multiple_of: "not_multiple_of",
|
|
5229
|
+
unrecognized_keys: "unrecognized_keys",
|
|
5230
|
+
invalid_union: "invalid_union",
|
|
5231
|
+
invalid_key: "invalid_key",
|
|
5232
|
+
invalid_element: "invalid_element",
|
|
5233
|
+
invalid_value: "invalid_value",
|
|
5234
|
+
custom: "custom"
|
|
5235
|
+
};
|
|
5236
|
+
/** @deprecated Do not use. Stub definition, only included for zod-to-json-schema compatibility. */
|
|
5237
|
+
var ZodFirstPartyTypeKind;
|
|
5238
|
+
ZodFirstPartyTypeKind || (ZodFirstPartyTypeKind = {});
|
|
5196
5239
|
Object.fromEntries([
|
|
5197
5240
|
{
|
|
5198
5241
|
id: "overview",
|
|
@@ -7315,6 +7358,62 @@ var RecordingConfigSchema = object({
|
|
|
7315
7358
|
scrubThumbnails: ScrubThumbnailPresetSchema.optional()
|
|
7316
7359
|
});
|
|
7317
7360
|
/**
|
|
7361
|
+
* Ops-log — the durable, append-only operations audit shared by the
|
|
7362
|
+
* recordings and events management surfaces.
|
|
7363
|
+
*
|
|
7364
|
+
* ONE row shape is reused for both domains so a single "Activity" view can
|
|
7365
|
+
* merge the recorder's DurableState ring (recordings ops-log) and the
|
|
7366
|
+
* pipeline-analytics SQLite collection (events ops-log). Each row records a
|
|
7367
|
+
* management operation, WHY it ran (reason), and its measurable effect
|
|
7368
|
+
* (itemsAffected + bytesReclaimed). Writes are best-effort — a failed log must
|
|
7369
|
+
* never fail the operation it records.
|
|
7370
|
+
*/
|
|
7371
|
+
/** Which management domain the operation belongs to. */
|
|
7372
|
+
var OpsLogDomainSchema = _enum(["recording", "events"]);
|
|
7373
|
+
/** The kind of management operation performed. */
|
|
7374
|
+
var OpsLogOpSchema = _enum([
|
|
7375
|
+
"prune",
|
|
7376
|
+
"manual-delete",
|
|
7377
|
+
"rescan",
|
|
7378
|
+
"retention-run"
|
|
7379
|
+
]);
|
|
7380
|
+
/** Why the operation ran. */
|
|
7381
|
+
var OpsLogReasonSchema = _enum([
|
|
7382
|
+
"retention",
|
|
7383
|
+
"quota",
|
|
7384
|
+
"manual",
|
|
7385
|
+
"operator"
|
|
7386
|
+
]);
|
|
7387
|
+
/** One audit row, shared verbatim by both domains. */
|
|
7388
|
+
var OpsLogEntrySchema = object({
|
|
7389
|
+
/** Unique row id. */
|
|
7390
|
+
id: string(),
|
|
7391
|
+
/** Epoch ms the operation completed. */
|
|
7392
|
+
at: number(),
|
|
7393
|
+
domain: OpsLogDomainSchema,
|
|
7394
|
+
op: OpsLogOpSchema,
|
|
7395
|
+
reason: OpsLogReasonSchema,
|
|
7396
|
+
/** The camera the op targeted; null for a cluster/global op. */
|
|
7397
|
+
deviceId: number().nullable(),
|
|
7398
|
+
/** Node that performed the op (the log carries nodeId — no cross-node aggregation). */
|
|
7399
|
+
nodeId: string(),
|
|
7400
|
+
/** Buckets / rows deleted (op-specific unit). */
|
|
7401
|
+
itemsAffected: number(),
|
|
7402
|
+
/** Bytes reclaimed by the op (0 when not measurable). */
|
|
7403
|
+
bytesReclaimed: number(),
|
|
7404
|
+
/** Free-text detail (e.g. "floor moved to <ts>"); null when none. */
|
|
7405
|
+
detail: string().nullable(),
|
|
7406
|
+
/** Who/what triggered the op. */
|
|
7407
|
+
actor: string()
|
|
7408
|
+
});
|
|
7409
|
+
/** Shared query input for the per-domain `listOpsLog` cap methods. */
|
|
7410
|
+
var OpsLogQueryInputSchema = object({
|
|
7411
|
+
/** Restrict to a single camera; omit for every row. */
|
|
7412
|
+
deviceId: number().optional(),
|
|
7413
|
+
/** Max rows returned, newest-first. */
|
|
7414
|
+
limit: number().int().min(1).max(1e3).optional()
|
|
7415
|
+
});
|
|
7416
|
+
/**
|
|
7318
7417
|
* `StorageLocationType` — an addon-declared id that identifies the *kind* of
|
|
7319
7418
|
* storage a location serves. Defined here (not in `capabilities/storage.cap.ts`)
|
|
7320
7419
|
* so the persisted record schema and the consumer-facing cap can both consume it
|
|
@@ -14670,7 +14769,11 @@ array(ZoneRuleSchema).readonly();
|
|
|
14670
14769
|
* Extend the enum here when a new gating consumer comes online (audio
|
|
14671
14770
|
* gating, alert filtering, …) — no other surface needs to change.
|
|
14672
14771
|
*/
|
|
14673
|
-
var ZoneRuleStageEnum = _enum([
|
|
14772
|
+
var ZoneRuleStageEnum = _enum([
|
|
14773
|
+
"motion",
|
|
14774
|
+
"detection",
|
|
14775
|
+
"package"
|
|
14776
|
+
]);
|
|
14674
14777
|
/**
|
|
14675
14778
|
* Runtime registry: cap-property-name → cap definition. `BaseDevice`'s
|
|
14676
14779
|
* `state` getter looks up the cap definition here to construct a
|
|
@@ -14764,16 +14867,25 @@ var DEVICE_LOCAL_STATE_CAPS = {
|
|
|
14764
14867
|
})
|
|
14765
14868
|
},
|
|
14766
14869
|
/**
|
|
14767
|
-
* Runtime-state slice —
|
|
14870
|
+
* Runtime-state slice — every stage mirrored together so consumers
|
|
14768
14871
|
* see one reactive handle (`device.state.zoneRules.value`) instead
|
|
14769
|
-
* of
|
|
14770
|
-
* `{motion, detection}` shape, so subscribers always get the
|
|
14872
|
+
* of one per stage. Bulk-replace mutations on any stage write the full
|
|
14873
|
+
* `{motion, detection, package}` shape, so subscribers always get the
|
|
14771
14874
|
* complete current set. Consumers that only care about one stage
|
|
14772
14875
|
* just read the matching property.
|
|
14876
|
+
*
|
|
14877
|
+
* `package` backs the package-drop detector — a package zone is a
|
|
14878
|
+
* `ZoneRule` on the `'package'` stage referencing drawn polygons
|
|
14879
|
+
* (see docs/superpowers/specs/2026-07-17-package-zones-design.md §3.1).
|
|
14880
|
+
* The orchestrator provider writes this stage as a first-class slice
|
|
14881
|
+
* (Phase 4): every mutation mirrors the full `{motion, detection,
|
|
14882
|
+
* package}` shape, so consumers read the current package rules directly
|
|
14883
|
+
* off `device.state.zoneRules.value.package`.
|
|
14773
14884
|
*/
|
|
14774
14885
|
runtimeState: object({
|
|
14775
14886
|
motion: array(ZoneRuleSchema).readonly(),
|
|
14776
|
-
detection: array(ZoneRuleSchema).readonly()
|
|
14887
|
+
detection: array(ZoneRuleSchema).readonly(),
|
|
14888
|
+
package: array(ZoneRuleSchema).readonly()
|
|
14777
14889
|
})
|
|
14778
14890
|
},
|
|
14779
14891
|
zones: zonesCapability
|
|
@@ -18735,6 +18847,7 @@ var EventKindIconSchema = _enum([
|
|
|
18735
18847
|
"smoke",
|
|
18736
18848
|
"water",
|
|
18737
18849
|
"button",
|
|
18850
|
+
"package",
|
|
18738
18851
|
"generic"
|
|
18739
18852
|
]);
|
|
18740
18853
|
var EventKindCategorySchema = _enum([
|
|
@@ -18742,7 +18855,8 @@ var EventKindCategorySchema = _enum([
|
|
|
18742
18855
|
"audio",
|
|
18743
18856
|
"detection",
|
|
18744
18857
|
"sensor",
|
|
18745
|
-
"custom"
|
|
18858
|
+
"custom",
|
|
18859
|
+
"package"
|
|
18746
18860
|
]);
|
|
18747
18861
|
var EventKindDescriptorSchema = object({
|
|
18748
18862
|
/** Stable kind id (e.g. 'motion', 'person', 'contact'). */
|
|
@@ -19083,6 +19197,26 @@ var TrackCascadeCountsSchema = object({
|
|
|
19083
19197
|
/** Per-track CLIP search vectors removed (best-effort). */
|
|
19084
19198
|
embeddings: number().int()
|
|
19085
19199
|
});
|
|
19200
|
+
/** Event-store footprint for one camera. */
|
|
19201
|
+
var EventStoreDeviceFootprintSchema = object({
|
|
19202
|
+
deviceId: number(),
|
|
19203
|
+
/** Persisted event rows (motion + object + audio) for the camera. */
|
|
19204
|
+
rows: number().int(),
|
|
19205
|
+
/** Event-owned media bytes on disk for the camera. */
|
|
19206
|
+
bytes: number().int()
|
|
19207
|
+
});
|
|
19208
|
+
/** Aggregate event-store footprint: global totals + per-camera breakdown. */
|
|
19209
|
+
var EventStoreFootprintSchema = object({
|
|
19210
|
+
totalRows: number().int(),
|
|
19211
|
+
totalBytes: number().int(),
|
|
19212
|
+
devices: array(EventStoreDeviceFootprintSchema).readonly()
|
|
19213
|
+
});
|
|
19214
|
+
/** Per-kind counts returned by the event-prune / device-delete mutations. */
|
|
19215
|
+
var EventPruneCountsSchema = object({
|
|
19216
|
+
motion: number().int(),
|
|
19217
|
+
object: number().int(),
|
|
19218
|
+
audio: number().int()
|
|
19219
|
+
});
|
|
19086
19220
|
DeviceType.Camera, method(object({ deviceId: number() }), array(TrackSchema).readonly()), method(object({
|
|
19087
19221
|
deviceId: number(),
|
|
19088
19222
|
trackId: string()
|
|
@@ -19146,6 +19280,21 @@ DeviceType.Camera, method(object({ deviceId: number() }), array(TrackSchema).rea
|
|
|
19146
19280
|
}), {
|
|
19147
19281
|
kind: "mutation",
|
|
19148
19282
|
auth: "admin"
|
|
19283
|
+
}), method(object({}), EventStoreFootprintSchema, {
|
|
19284
|
+
kind: "query",
|
|
19285
|
+
auth: "admin"
|
|
19286
|
+
}), method(object({
|
|
19287
|
+
olderThanMs: number(),
|
|
19288
|
+
reason: OpsLogReasonSchema.optional()
|
|
19289
|
+
}), EventPruneCountsSchema, {
|
|
19290
|
+
kind: "mutation",
|
|
19291
|
+
auth: "admin"
|
|
19292
|
+
}), method(object({ deviceId: number() }), EventPruneCountsSchema, {
|
|
19293
|
+
kind: "mutation",
|
|
19294
|
+
auth: "admin"
|
|
19295
|
+
}), method(OpsLogQueryInputSchema, array(OpsLogEntrySchema).readonly(), {
|
|
19296
|
+
kind: "query",
|
|
19297
|
+
auth: "admin"
|
|
19149
19298
|
}), method(object({
|
|
19150
19299
|
eventId: string(),
|
|
19151
19300
|
kind: MediaFileKindEnum.optional()
|
|
@@ -22396,13 +22545,131 @@ method(object({
|
|
|
22396
22545
|
}), method(object({ deviceId: number() }), RecordingStatusSchema, {
|
|
22397
22546
|
kind: "mutation",
|
|
22398
22547
|
auth: "admin"
|
|
22399
|
-
}), method(object({
|
|
22548
|
+
}), method(object({
|
|
22549
|
+
deviceId: number(),
|
|
22550
|
+
reason: OpsLogReasonSchema.optional()
|
|
22551
|
+
}), object({
|
|
22400
22552
|
floorMs: number().nullable(),
|
|
22401
22553
|
deletedBuckets: number().int(),
|
|
22402
22554
|
reclaimedBytes: number().int()
|
|
22403
22555
|
}), {
|
|
22404
22556
|
kind: "mutation",
|
|
22405
22557
|
auth: "admin"
|
|
22558
|
+
}), method(object({
|
|
22559
|
+
deviceId: number(),
|
|
22560
|
+
fromMs: number().optional(),
|
|
22561
|
+
toMs: number().optional()
|
|
22562
|
+
}), object({
|
|
22563
|
+
deletedBuckets: number().int(),
|
|
22564
|
+
reclaimedBytes: number().int()
|
|
22565
|
+
}), {
|
|
22566
|
+
kind: "mutation",
|
|
22567
|
+
auth: "admin"
|
|
22568
|
+
}), method(OpsLogQueryInputSchema, array(OpsLogEntrySchema).readonly(), {
|
|
22569
|
+
kind: "query",
|
|
22570
|
+
auth: "admin"
|
|
22571
|
+
});
|
|
22572
|
+
/**
|
|
22573
|
+
* `recordingExport` cap — render a footage time range into a single downloadable
|
|
22574
|
+
* MP4 (regular / accelerated / decelerated / timelapse, ± audio), kept for a
|
|
22575
|
+
* bounded lifetime with a durable history, auto-expiry, and optional
|
|
22576
|
+
* delete-after-download.
|
|
22577
|
+
*
|
|
22578
|
+
* Like `recording` this is a `scope:'system', mode:'singleton'` cap: the
|
|
22579
|
+
* recorder self-gates so exactly ONE node (the designated `recordingNodeId`,
|
|
22580
|
+
* default `hub`) registers it. Device-scoped methods carry `deviceId` in their
|
|
22581
|
+
* input and dispatch to that single provider; the render runs on the node that
|
|
22582
|
+
* owns the footage (no cross-node segment transfer). Download rides the
|
|
22583
|
+
* framework addon data-plane. State persists in a DurableState blob (NOT
|
|
22584
|
+
* SQLite); history rows survive file deletion for audit.
|
|
22585
|
+
*/
|
|
22586
|
+
/** Playback-speed multiplier for the render (1 = realtime). */
|
|
22587
|
+
var ExportSpeedSchema = number().min(.25).max(32);
|
|
22588
|
+
/** Timelapse cadence — sample one source frame per `everyMs`, output at `outputFps`. */
|
|
22589
|
+
var ExportTimelapseSchema = object({
|
|
22590
|
+
everyMs: number().int().positive(),
|
|
22591
|
+
outputFps: number().int().min(1).max(60).optional()
|
|
22592
|
+
});
|
|
22593
|
+
/**
|
|
22594
|
+
* Render options. `speed` and `timelapse` are mutually exclusive. `includeAudio`
|
|
22595
|
+
* is honoured only for a realtime-ish speed (0.5–2×); timelapse is always
|
|
22596
|
+
* silent. `maxLifeMs` bounds how long the finished file is kept;
|
|
22597
|
+
* `deleteAfterDownload` removes it shortly after the first complete download.
|
|
22598
|
+
*/
|
|
22599
|
+
var ExportOptionsSchema = object({
|
|
22600
|
+
speed: ExportSpeedSchema.optional(),
|
|
22601
|
+
timelapse: ExportTimelapseSchema.optional(),
|
|
22602
|
+
includeAudio: boolean(),
|
|
22603
|
+
maxLifeMs: number().int().positive(),
|
|
22604
|
+
deleteAfterDownload: boolean(),
|
|
22605
|
+
title: string().max(200).optional()
|
|
22606
|
+
}).superRefine((v, ctx) => {
|
|
22607
|
+
if (v.speed !== void 0 && v.timelapse !== void 0) ctx.addIssue({
|
|
22608
|
+
code: ZodIssueCode.custom,
|
|
22609
|
+
message: "speed and timelapse are mutually exclusive",
|
|
22610
|
+
path: ["timelapse"]
|
|
22611
|
+
});
|
|
22612
|
+
});
|
|
22613
|
+
var ExportStateSchema = _enum([
|
|
22614
|
+
"queued",
|
|
22615
|
+
"rendering",
|
|
22616
|
+
"ready",
|
|
22617
|
+
"failed",
|
|
22618
|
+
"expired",
|
|
22619
|
+
"deleted"
|
|
22620
|
+
]);
|
|
22621
|
+
/** One export job / history row. */
|
|
22622
|
+
var ExportRecordSchema = object({
|
|
22623
|
+
id: string(),
|
|
22624
|
+
deviceId: number(),
|
|
22625
|
+
profile: string(),
|
|
22626
|
+
fromMs: number(),
|
|
22627
|
+
toMs: number(),
|
|
22628
|
+
options: ExportOptionsSchema,
|
|
22629
|
+
state: ExportStateSchema,
|
|
22630
|
+
/** 0–100 while rendering; null otherwise. */
|
|
22631
|
+
progressPct: number().nullable(),
|
|
22632
|
+
/** File size once ready; null before. */
|
|
22633
|
+
fileBytes: number().nullable(),
|
|
22634
|
+
expiresAt: number(),
|
|
22635
|
+
deleteAfterDownload: boolean(),
|
|
22636
|
+
/** Epoch of the first complete download; null until then. */
|
|
22637
|
+
downloadedAt: number().nullable(),
|
|
22638
|
+
createdAt: number(),
|
|
22639
|
+
/** User id/name that requested the export. */
|
|
22640
|
+
createdBy: string(),
|
|
22641
|
+
/** Failure reason when state is 'failed'; null otherwise. */
|
|
22642
|
+
error: string().nullable()
|
|
22643
|
+
});
|
|
22644
|
+
/** Candidate download URLs (LAN first, then operator extra hosts). */
|
|
22645
|
+
var ExportDownloadSchema = object({
|
|
22646
|
+
url: string(),
|
|
22647
|
+
endpoints: array(string())
|
|
22648
|
+
});
|
|
22649
|
+
method(object({
|
|
22650
|
+
deviceId: number(),
|
|
22651
|
+
profile: string(),
|
|
22652
|
+
fromMs: number(),
|
|
22653
|
+
toMs: number(),
|
|
22654
|
+
options: ExportOptionsSchema
|
|
22655
|
+
}), ExportRecordSchema, {
|
|
22656
|
+
kind: "mutation",
|
|
22657
|
+
auth: "protected"
|
|
22658
|
+
}), method(object({ deviceId: number().optional() }), array(ExportRecordSchema), {
|
|
22659
|
+
kind: "query",
|
|
22660
|
+
auth: "protected"
|
|
22661
|
+
}), method(object({ exportId: string() }), ExportRecordSchema, {
|
|
22662
|
+
kind: "query",
|
|
22663
|
+
auth: "protected"
|
|
22664
|
+
}), method(object({ exportId: string() }), ExportRecordSchema, {
|
|
22665
|
+
kind: "mutation",
|
|
22666
|
+
auth: "protected"
|
|
22667
|
+
}), method(object({ exportId: string() }), ExportRecordSchema, {
|
|
22668
|
+
kind: "mutation",
|
|
22669
|
+
auth: "protected"
|
|
22670
|
+
}), method(object({ exportId: string() }), ExportDownloadSchema, {
|
|
22671
|
+
kind: "query",
|
|
22672
|
+
auth: "protected"
|
|
22406
22673
|
});
|
|
22407
22674
|
/**
|
|
22408
22675
|
* One publishable camera stream as its OWNING PROVIDER describes it — the same
|
|
@@ -25422,6 +25689,12 @@ Object.freeze({
|
|
|
25422
25689
|
addonId: null,
|
|
25423
25690
|
access: "delete"
|
|
25424
25691
|
},
|
|
25692
|
+
"pipelineAnalytics.deleteDeviceEvents": {
|
|
25693
|
+
capName: "pipeline-analytics",
|
|
25694
|
+
capScope: "device",
|
|
25695
|
+
addonId: null,
|
|
25696
|
+
access: "delete"
|
|
25697
|
+
},
|
|
25425
25698
|
"pipelineAnalytics.deleteTracks": {
|
|
25426
25699
|
capName: "pipeline-analytics",
|
|
25427
25700
|
capScope: "device",
|
|
@@ -25452,6 +25725,12 @@ Object.freeze({
|
|
|
25452
25725
|
addonId: null,
|
|
25453
25726
|
access: "view"
|
|
25454
25727
|
},
|
|
25728
|
+
"pipelineAnalytics.getEventStoreFootprint": {
|
|
25729
|
+
capName: "pipeline-analytics",
|
|
25730
|
+
capScope: "device",
|
|
25731
|
+
addonId: null,
|
|
25732
|
+
access: "view"
|
|
25733
|
+
},
|
|
25455
25734
|
"pipelineAnalytics.getKeyEvents": {
|
|
25456
25735
|
capName: "pipeline-analytics",
|
|
25457
25736
|
capScope: "device",
|
|
@@ -25494,6 +25773,12 @@ Object.freeze({
|
|
|
25494
25773
|
addonId: null,
|
|
25495
25774
|
access: "view"
|
|
25496
25775
|
},
|
|
25776
|
+
"pipelineAnalytics.listOpsLog": {
|
|
25777
|
+
capName: "pipeline-analytics",
|
|
25778
|
+
capScope: "device",
|
|
25779
|
+
addonId: null,
|
|
25780
|
+
access: "view"
|
|
25781
|
+
},
|
|
25497
25782
|
"pipelineAnalytics.listRecentTracks": {
|
|
25498
25783
|
capName: "pipeline-analytics",
|
|
25499
25784
|
capScope: "device",
|
|
@@ -25506,6 +25791,12 @@ Object.freeze({
|
|
|
25506
25791
|
addonId: null,
|
|
25507
25792
|
access: "view"
|
|
25508
25793
|
},
|
|
25794
|
+
"pipelineAnalytics.pruneEvents": {
|
|
25795
|
+
capName: "pipeline-analytics",
|
|
25796
|
+
capScope: "device",
|
|
25797
|
+
addonId: null,
|
|
25798
|
+
access: "create"
|
|
25799
|
+
},
|
|
25509
25800
|
"pipelineAnalytics.pruneEventsBefore": {
|
|
25510
25801
|
capName: "pipeline-analytics",
|
|
25511
25802
|
capScope: "device",
|
|
@@ -26268,6 +26559,12 @@ Object.freeze({
|
|
|
26268
26559
|
addonId: null,
|
|
26269
26560
|
access: "create"
|
|
26270
26561
|
},
|
|
26562
|
+
"recording.deleteFootprint": {
|
|
26563
|
+
capName: "recording",
|
|
26564
|
+
capScope: "system",
|
|
26565
|
+
addonId: null,
|
|
26566
|
+
access: "delete"
|
|
26567
|
+
},
|
|
26271
26568
|
"recording.getAvailability": {
|
|
26272
26569
|
capName: "recording",
|
|
26273
26570
|
capScope: "system",
|
|
@@ -26298,6 +26595,12 @@ Object.freeze({
|
|
|
26298
26595
|
addonId: null,
|
|
26299
26596
|
access: "view"
|
|
26300
26597
|
},
|
|
26598
|
+
"recording.listOpsLog": {
|
|
26599
|
+
capName: "recording",
|
|
26600
|
+
capScope: "system",
|
|
26601
|
+
addonId: null,
|
|
26602
|
+
access: "view"
|
|
26603
|
+
},
|
|
26301
26604
|
"recording.locateSegment": {
|
|
26302
26605
|
capName: "recording",
|
|
26303
26606
|
capScope: "system",
|
|
@@ -26328,6 +26631,42 @@ Object.freeze({
|
|
|
26328
26631
|
addonId: null,
|
|
26329
26632
|
access: "create"
|
|
26330
26633
|
},
|
|
26634
|
+
"recordingExport.cancelExport": {
|
|
26635
|
+
capName: "recordingExport",
|
|
26636
|
+
capScope: "system",
|
|
26637
|
+
addonId: null,
|
|
26638
|
+
access: "create"
|
|
26639
|
+
},
|
|
26640
|
+
"recordingExport.createExport": {
|
|
26641
|
+
capName: "recordingExport",
|
|
26642
|
+
capScope: "system",
|
|
26643
|
+
addonId: null,
|
|
26644
|
+
access: "create"
|
|
26645
|
+
},
|
|
26646
|
+
"recordingExport.deleteExport": {
|
|
26647
|
+
capName: "recordingExport",
|
|
26648
|
+
capScope: "system",
|
|
26649
|
+
addonId: null,
|
|
26650
|
+
access: "delete"
|
|
26651
|
+
},
|
|
26652
|
+
"recordingExport.getDownloadUrl": {
|
|
26653
|
+
capName: "recordingExport",
|
|
26654
|
+
capScope: "system",
|
|
26655
|
+
addonId: null,
|
|
26656
|
+
access: "view"
|
|
26657
|
+
},
|
|
26658
|
+
"recordingExport.getExport": {
|
|
26659
|
+
capName: "recordingExport",
|
|
26660
|
+
capScope: "system",
|
|
26661
|
+
addonId: null,
|
|
26662
|
+
access: "view"
|
|
26663
|
+
},
|
|
26664
|
+
"recordingExport.listExports": {
|
|
26665
|
+
capName: "recordingExport",
|
|
26666
|
+
capScope: "system",
|
|
26667
|
+
addonId: null,
|
|
26668
|
+
access: "view"
|
|
26669
|
+
},
|
|
26331
26670
|
"sceneMonitor.captureReference": {
|
|
26332
26671
|
capName: "scene-monitor",
|
|
26333
26672
|
capScope: "device",
|
package/dist/addon.mjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
//#region ../types/dist/event-category-
|
|
1
|
+
//#region ../types/dist/event-category-D4HJq7Mw.mjs
|
|
2
2
|
var EventCategory = /* @__PURE__ */ function(EventCategory) {
|
|
3
3
|
EventCategory["SystemBoot"] = "system.boot";
|
|
4
4
|
EventCategory["SystemAddonsReady"] = "system.addons-ready";
|
|
@@ -151,6 +151,11 @@ var EventCategory = /* @__PURE__ */ function(EventCategory) {
|
|
|
151
151
|
/** Runner-sampled scrub thumbnail (~1/5 s/camera). Telemetry (D8): a lost
|
|
152
152
|
* thumb is a scrub gap the recorder's keyframe backfill covers. */
|
|
153
153
|
EventCategory["RecordingThumbSampled"] = "recording.thumb-sampled";
|
|
154
|
+
/** Export render progress (0–100). Telemetry (D8): a lost tick is a stale
|
|
155
|
+
* progress bar the client reconciles via `recordingExport.getExport`. */
|
|
156
|
+
EventCategory["RecordingExportProgress"] = "recording.export.progress";
|
|
157
|
+
EventCategory["RecordingExportCompleted"] = "recording.export.completed";
|
|
158
|
+
EventCategory["RecordingExportFailed"] = "recording.export.failed";
|
|
154
159
|
EventCategory["DetectionEvent"] = "detection.event";
|
|
155
160
|
EventCategory["SessionTrackNew"] = "session.track.new";
|
|
156
161
|
EventCategory["SessionTrackExpired"] = "session.track.expired";
|
|
@@ -440,6 +445,25 @@ var EventCategory = /* @__PURE__ */ function(EventCategory) {
|
|
|
440
445
|
*/
|
|
441
446
|
EventCategory["PipelineAnalyticsStationaryChanged"] = "pipeline-analytics.stationary-changed";
|
|
442
447
|
/**
|
|
448
|
+
* Fired by `addon-post-analysis` when a package-drop is confirmed inside
|
|
449
|
+
* a package zone — a newly-appeared stationary object of a package class
|
|
450
|
+
* that cleared the class / zone / dwell / size gates. Payload:
|
|
451
|
+
* `PipelineAnalyticsPackageDeliveredPayload` carrying `{ deviceId,
|
|
452
|
+
* entryId, className, zoneIds, keyFrameMediaKey?, bbox, timestamp }`.
|
|
453
|
+
* Telemetry (D8): the durable record is the `package-events` store row;
|
|
454
|
+
* this bus topic drives notifier rules + live UI. See
|
|
455
|
+
* docs/superpowers/specs/2026-07-17-package-zones-design.md §5.1.
|
|
456
|
+
*/
|
|
457
|
+
EventCategory["PipelineAnalyticsPackageDelivered"] = "pipeline-analytics.package-delivered";
|
|
458
|
+
/**
|
|
459
|
+
* Fired by `addon-post-analysis` when a previously-delivered package
|
|
460
|
+
* leaves its zone (the stationary entry departed — moved or swept).
|
|
461
|
+
* Payload: `PipelineAnalyticsPackagePickedUpPayload` carrying
|
|
462
|
+
* `{ deviceId, entryId, deliveredEventId, className, timestamp }`.
|
|
463
|
+
* Telemetry (D8). See package-zones-design §5.2.
|
|
464
|
+
*/
|
|
465
|
+
EventCategory["PipelineAnalyticsPackagePickedUp"] = "pipeline-analytics.package-picked-up";
|
|
466
|
+
/**
|
|
443
467
|
* Fired by `addon-post-analysis` whenever a gallery face row changes:
|
|
444
468
|
* `kind:'buffered'` a new detected face was persisted, `'assigned'` /
|
|
445
469
|
* `'unassigned'` its identity link changed, `'deleted'` the row was
|
|
@@ -5192,6 +5216,25 @@ function preprocess(fn, schema) {
|
|
|
5192
5216
|
out: schema
|
|
5193
5217
|
});
|
|
5194
5218
|
}
|
|
5219
|
+
//#endregion
|
|
5220
|
+
//#region ../../node_modules/zod/v4/classic/compat.js
|
|
5221
|
+
/** @deprecated Use the raw string literal codes instead, e.g. "invalid_type". */
|
|
5222
|
+
var ZodIssueCode = {
|
|
5223
|
+
invalid_type: "invalid_type",
|
|
5224
|
+
too_big: "too_big",
|
|
5225
|
+
too_small: "too_small",
|
|
5226
|
+
invalid_format: "invalid_format",
|
|
5227
|
+
not_multiple_of: "not_multiple_of",
|
|
5228
|
+
unrecognized_keys: "unrecognized_keys",
|
|
5229
|
+
invalid_union: "invalid_union",
|
|
5230
|
+
invalid_key: "invalid_key",
|
|
5231
|
+
invalid_element: "invalid_element",
|
|
5232
|
+
invalid_value: "invalid_value",
|
|
5233
|
+
custom: "custom"
|
|
5234
|
+
};
|
|
5235
|
+
/** @deprecated Do not use. Stub definition, only included for zod-to-json-schema compatibility. */
|
|
5236
|
+
var ZodFirstPartyTypeKind;
|
|
5237
|
+
ZodFirstPartyTypeKind || (ZodFirstPartyTypeKind = {});
|
|
5195
5238
|
Object.fromEntries([
|
|
5196
5239
|
{
|
|
5197
5240
|
id: "overview",
|
|
@@ -7314,6 +7357,62 @@ var RecordingConfigSchema = object({
|
|
|
7314
7357
|
scrubThumbnails: ScrubThumbnailPresetSchema.optional()
|
|
7315
7358
|
});
|
|
7316
7359
|
/**
|
|
7360
|
+
* Ops-log — the durable, append-only operations audit shared by the
|
|
7361
|
+
* recordings and events management surfaces.
|
|
7362
|
+
*
|
|
7363
|
+
* ONE row shape is reused for both domains so a single "Activity" view can
|
|
7364
|
+
* merge the recorder's DurableState ring (recordings ops-log) and the
|
|
7365
|
+
* pipeline-analytics SQLite collection (events ops-log). Each row records a
|
|
7366
|
+
* management operation, WHY it ran (reason), and its measurable effect
|
|
7367
|
+
* (itemsAffected + bytesReclaimed). Writes are best-effort — a failed log must
|
|
7368
|
+
* never fail the operation it records.
|
|
7369
|
+
*/
|
|
7370
|
+
/** Which management domain the operation belongs to. */
|
|
7371
|
+
var OpsLogDomainSchema = _enum(["recording", "events"]);
|
|
7372
|
+
/** The kind of management operation performed. */
|
|
7373
|
+
var OpsLogOpSchema = _enum([
|
|
7374
|
+
"prune",
|
|
7375
|
+
"manual-delete",
|
|
7376
|
+
"rescan",
|
|
7377
|
+
"retention-run"
|
|
7378
|
+
]);
|
|
7379
|
+
/** Why the operation ran. */
|
|
7380
|
+
var OpsLogReasonSchema = _enum([
|
|
7381
|
+
"retention",
|
|
7382
|
+
"quota",
|
|
7383
|
+
"manual",
|
|
7384
|
+
"operator"
|
|
7385
|
+
]);
|
|
7386
|
+
/** One audit row, shared verbatim by both domains. */
|
|
7387
|
+
var OpsLogEntrySchema = object({
|
|
7388
|
+
/** Unique row id. */
|
|
7389
|
+
id: string(),
|
|
7390
|
+
/** Epoch ms the operation completed. */
|
|
7391
|
+
at: number(),
|
|
7392
|
+
domain: OpsLogDomainSchema,
|
|
7393
|
+
op: OpsLogOpSchema,
|
|
7394
|
+
reason: OpsLogReasonSchema,
|
|
7395
|
+
/** The camera the op targeted; null for a cluster/global op. */
|
|
7396
|
+
deviceId: number().nullable(),
|
|
7397
|
+
/** Node that performed the op (the log carries nodeId — no cross-node aggregation). */
|
|
7398
|
+
nodeId: string(),
|
|
7399
|
+
/** Buckets / rows deleted (op-specific unit). */
|
|
7400
|
+
itemsAffected: number(),
|
|
7401
|
+
/** Bytes reclaimed by the op (0 when not measurable). */
|
|
7402
|
+
bytesReclaimed: number(),
|
|
7403
|
+
/** Free-text detail (e.g. "floor moved to <ts>"); null when none. */
|
|
7404
|
+
detail: string().nullable(),
|
|
7405
|
+
/** Who/what triggered the op. */
|
|
7406
|
+
actor: string()
|
|
7407
|
+
});
|
|
7408
|
+
/** Shared query input for the per-domain `listOpsLog` cap methods. */
|
|
7409
|
+
var OpsLogQueryInputSchema = object({
|
|
7410
|
+
/** Restrict to a single camera; omit for every row. */
|
|
7411
|
+
deviceId: number().optional(),
|
|
7412
|
+
/** Max rows returned, newest-first. */
|
|
7413
|
+
limit: number().int().min(1).max(1e3).optional()
|
|
7414
|
+
});
|
|
7415
|
+
/**
|
|
7317
7416
|
* `StorageLocationType` — an addon-declared id that identifies the *kind* of
|
|
7318
7417
|
* storage a location serves. Defined here (not in `capabilities/storage.cap.ts`)
|
|
7319
7418
|
* so the persisted record schema and the consumer-facing cap can both consume it
|
|
@@ -14669,7 +14768,11 @@ array(ZoneRuleSchema).readonly();
|
|
|
14669
14768
|
* Extend the enum here when a new gating consumer comes online (audio
|
|
14670
14769
|
* gating, alert filtering, …) — no other surface needs to change.
|
|
14671
14770
|
*/
|
|
14672
|
-
var ZoneRuleStageEnum = _enum([
|
|
14771
|
+
var ZoneRuleStageEnum = _enum([
|
|
14772
|
+
"motion",
|
|
14773
|
+
"detection",
|
|
14774
|
+
"package"
|
|
14775
|
+
]);
|
|
14673
14776
|
/**
|
|
14674
14777
|
* Runtime registry: cap-property-name → cap definition. `BaseDevice`'s
|
|
14675
14778
|
* `state` getter looks up the cap definition here to construct a
|
|
@@ -14763,16 +14866,25 @@ var DEVICE_LOCAL_STATE_CAPS = {
|
|
|
14763
14866
|
})
|
|
14764
14867
|
},
|
|
14765
14868
|
/**
|
|
14766
|
-
* Runtime-state slice —
|
|
14869
|
+
* Runtime-state slice — every stage mirrored together so consumers
|
|
14767
14870
|
* see one reactive handle (`device.state.zoneRules.value`) instead
|
|
14768
|
-
* of
|
|
14769
|
-
* `{motion, detection}` shape, so subscribers always get the
|
|
14871
|
+
* of one per stage. Bulk-replace mutations on any stage write the full
|
|
14872
|
+
* `{motion, detection, package}` shape, so subscribers always get the
|
|
14770
14873
|
* complete current set. Consumers that only care about one stage
|
|
14771
14874
|
* just read the matching property.
|
|
14875
|
+
*
|
|
14876
|
+
* `package` backs the package-drop detector — a package zone is a
|
|
14877
|
+
* `ZoneRule` on the `'package'` stage referencing drawn polygons
|
|
14878
|
+
* (see docs/superpowers/specs/2026-07-17-package-zones-design.md §3.1).
|
|
14879
|
+
* The orchestrator provider writes this stage as a first-class slice
|
|
14880
|
+
* (Phase 4): every mutation mirrors the full `{motion, detection,
|
|
14881
|
+
* package}` shape, so consumers read the current package rules directly
|
|
14882
|
+
* off `device.state.zoneRules.value.package`.
|
|
14772
14883
|
*/
|
|
14773
14884
|
runtimeState: object({
|
|
14774
14885
|
motion: array(ZoneRuleSchema).readonly(),
|
|
14775
|
-
detection: array(ZoneRuleSchema).readonly()
|
|
14886
|
+
detection: array(ZoneRuleSchema).readonly(),
|
|
14887
|
+
package: array(ZoneRuleSchema).readonly()
|
|
14776
14888
|
})
|
|
14777
14889
|
},
|
|
14778
14890
|
zones: zonesCapability
|
|
@@ -18734,6 +18846,7 @@ var EventKindIconSchema = _enum([
|
|
|
18734
18846
|
"smoke",
|
|
18735
18847
|
"water",
|
|
18736
18848
|
"button",
|
|
18849
|
+
"package",
|
|
18737
18850
|
"generic"
|
|
18738
18851
|
]);
|
|
18739
18852
|
var EventKindCategorySchema = _enum([
|
|
@@ -18741,7 +18854,8 @@ var EventKindCategorySchema = _enum([
|
|
|
18741
18854
|
"audio",
|
|
18742
18855
|
"detection",
|
|
18743
18856
|
"sensor",
|
|
18744
|
-
"custom"
|
|
18857
|
+
"custom",
|
|
18858
|
+
"package"
|
|
18745
18859
|
]);
|
|
18746
18860
|
var EventKindDescriptorSchema = object({
|
|
18747
18861
|
/** Stable kind id (e.g. 'motion', 'person', 'contact'). */
|
|
@@ -19082,6 +19196,26 @@ var TrackCascadeCountsSchema = object({
|
|
|
19082
19196
|
/** Per-track CLIP search vectors removed (best-effort). */
|
|
19083
19197
|
embeddings: number().int()
|
|
19084
19198
|
});
|
|
19199
|
+
/** Event-store footprint for one camera. */
|
|
19200
|
+
var EventStoreDeviceFootprintSchema = object({
|
|
19201
|
+
deviceId: number(),
|
|
19202
|
+
/** Persisted event rows (motion + object + audio) for the camera. */
|
|
19203
|
+
rows: number().int(),
|
|
19204
|
+
/** Event-owned media bytes on disk for the camera. */
|
|
19205
|
+
bytes: number().int()
|
|
19206
|
+
});
|
|
19207
|
+
/** Aggregate event-store footprint: global totals + per-camera breakdown. */
|
|
19208
|
+
var EventStoreFootprintSchema = object({
|
|
19209
|
+
totalRows: number().int(),
|
|
19210
|
+
totalBytes: number().int(),
|
|
19211
|
+
devices: array(EventStoreDeviceFootprintSchema).readonly()
|
|
19212
|
+
});
|
|
19213
|
+
/** Per-kind counts returned by the event-prune / device-delete mutations. */
|
|
19214
|
+
var EventPruneCountsSchema = object({
|
|
19215
|
+
motion: number().int(),
|
|
19216
|
+
object: number().int(),
|
|
19217
|
+
audio: number().int()
|
|
19218
|
+
});
|
|
19085
19219
|
DeviceType.Camera, method(object({ deviceId: number() }), array(TrackSchema).readonly()), method(object({
|
|
19086
19220
|
deviceId: number(),
|
|
19087
19221
|
trackId: string()
|
|
@@ -19145,6 +19279,21 @@ DeviceType.Camera, method(object({ deviceId: number() }), array(TrackSchema).rea
|
|
|
19145
19279
|
}), {
|
|
19146
19280
|
kind: "mutation",
|
|
19147
19281
|
auth: "admin"
|
|
19282
|
+
}), method(object({}), EventStoreFootprintSchema, {
|
|
19283
|
+
kind: "query",
|
|
19284
|
+
auth: "admin"
|
|
19285
|
+
}), method(object({
|
|
19286
|
+
olderThanMs: number(),
|
|
19287
|
+
reason: OpsLogReasonSchema.optional()
|
|
19288
|
+
}), EventPruneCountsSchema, {
|
|
19289
|
+
kind: "mutation",
|
|
19290
|
+
auth: "admin"
|
|
19291
|
+
}), method(object({ deviceId: number() }), EventPruneCountsSchema, {
|
|
19292
|
+
kind: "mutation",
|
|
19293
|
+
auth: "admin"
|
|
19294
|
+
}), method(OpsLogQueryInputSchema, array(OpsLogEntrySchema).readonly(), {
|
|
19295
|
+
kind: "query",
|
|
19296
|
+
auth: "admin"
|
|
19148
19297
|
}), method(object({
|
|
19149
19298
|
eventId: string(),
|
|
19150
19299
|
kind: MediaFileKindEnum.optional()
|
|
@@ -22395,13 +22544,131 @@ method(object({
|
|
|
22395
22544
|
}), method(object({ deviceId: number() }), RecordingStatusSchema, {
|
|
22396
22545
|
kind: "mutation",
|
|
22397
22546
|
auth: "admin"
|
|
22398
|
-
}), method(object({
|
|
22547
|
+
}), method(object({
|
|
22548
|
+
deviceId: number(),
|
|
22549
|
+
reason: OpsLogReasonSchema.optional()
|
|
22550
|
+
}), object({
|
|
22399
22551
|
floorMs: number().nullable(),
|
|
22400
22552
|
deletedBuckets: number().int(),
|
|
22401
22553
|
reclaimedBytes: number().int()
|
|
22402
22554
|
}), {
|
|
22403
22555
|
kind: "mutation",
|
|
22404
22556
|
auth: "admin"
|
|
22557
|
+
}), method(object({
|
|
22558
|
+
deviceId: number(),
|
|
22559
|
+
fromMs: number().optional(),
|
|
22560
|
+
toMs: number().optional()
|
|
22561
|
+
}), object({
|
|
22562
|
+
deletedBuckets: number().int(),
|
|
22563
|
+
reclaimedBytes: number().int()
|
|
22564
|
+
}), {
|
|
22565
|
+
kind: "mutation",
|
|
22566
|
+
auth: "admin"
|
|
22567
|
+
}), method(OpsLogQueryInputSchema, array(OpsLogEntrySchema).readonly(), {
|
|
22568
|
+
kind: "query",
|
|
22569
|
+
auth: "admin"
|
|
22570
|
+
});
|
|
22571
|
+
/**
|
|
22572
|
+
* `recordingExport` cap — render a footage time range into a single downloadable
|
|
22573
|
+
* MP4 (regular / accelerated / decelerated / timelapse, ± audio), kept for a
|
|
22574
|
+
* bounded lifetime with a durable history, auto-expiry, and optional
|
|
22575
|
+
* delete-after-download.
|
|
22576
|
+
*
|
|
22577
|
+
* Like `recording` this is a `scope:'system', mode:'singleton'` cap: the
|
|
22578
|
+
* recorder self-gates so exactly ONE node (the designated `recordingNodeId`,
|
|
22579
|
+
* default `hub`) registers it. Device-scoped methods carry `deviceId` in their
|
|
22580
|
+
* input and dispatch to that single provider; the render runs on the node that
|
|
22581
|
+
* owns the footage (no cross-node segment transfer). Download rides the
|
|
22582
|
+
* framework addon data-plane. State persists in a DurableState blob (NOT
|
|
22583
|
+
* SQLite); history rows survive file deletion for audit.
|
|
22584
|
+
*/
|
|
22585
|
+
/** Playback-speed multiplier for the render (1 = realtime). */
|
|
22586
|
+
var ExportSpeedSchema = number().min(.25).max(32);
|
|
22587
|
+
/** Timelapse cadence — sample one source frame per `everyMs`, output at `outputFps`. */
|
|
22588
|
+
var ExportTimelapseSchema = object({
|
|
22589
|
+
everyMs: number().int().positive(),
|
|
22590
|
+
outputFps: number().int().min(1).max(60).optional()
|
|
22591
|
+
});
|
|
22592
|
+
/**
|
|
22593
|
+
* Render options. `speed` and `timelapse` are mutually exclusive. `includeAudio`
|
|
22594
|
+
* is honoured only for a realtime-ish speed (0.5–2×); timelapse is always
|
|
22595
|
+
* silent. `maxLifeMs` bounds how long the finished file is kept;
|
|
22596
|
+
* `deleteAfterDownload` removes it shortly after the first complete download.
|
|
22597
|
+
*/
|
|
22598
|
+
var ExportOptionsSchema = object({
|
|
22599
|
+
speed: ExportSpeedSchema.optional(),
|
|
22600
|
+
timelapse: ExportTimelapseSchema.optional(),
|
|
22601
|
+
includeAudio: boolean(),
|
|
22602
|
+
maxLifeMs: number().int().positive(),
|
|
22603
|
+
deleteAfterDownload: boolean(),
|
|
22604
|
+
title: string().max(200).optional()
|
|
22605
|
+
}).superRefine((v, ctx) => {
|
|
22606
|
+
if (v.speed !== void 0 && v.timelapse !== void 0) ctx.addIssue({
|
|
22607
|
+
code: ZodIssueCode.custom,
|
|
22608
|
+
message: "speed and timelapse are mutually exclusive",
|
|
22609
|
+
path: ["timelapse"]
|
|
22610
|
+
});
|
|
22611
|
+
});
|
|
22612
|
+
var ExportStateSchema = _enum([
|
|
22613
|
+
"queued",
|
|
22614
|
+
"rendering",
|
|
22615
|
+
"ready",
|
|
22616
|
+
"failed",
|
|
22617
|
+
"expired",
|
|
22618
|
+
"deleted"
|
|
22619
|
+
]);
|
|
22620
|
+
/** One export job / history row. */
|
|
22621
|
+
var ExportRecordSchema = object({
|
|
22622
|
+
id: string(),
|
|
22623
|
+
deviceId: number(),
|
|
22624
|
+
profile: string(),
|
|
22625
|
+
fromMs: number(),
|
|
22626
|
+
toMs: number(),
|
|
22627
|
+
options: ExportOptionsSchema,
|
|
22628
|
+
state: ExportStateSchema,
|
|
22629
|
+
/** 0–100 while rendering; null otherwise. */
|
|
22630
|
+
progressPct: number().nullable(),
|
|
22631
|
+
/** File size once ready; null before. */
|
|
22632
|
+
fileBytes: number().nullable(),
|
|
22633
|
+
expiresAt: number(),
|
|
22634
|
+
deleteAfterDownload: boolean(),
|
|
22635
|
+
/** Epoch of the first complete download; null until then. */
|
|
22636
|
+
downloadedAt: number().nullable(),
|
|
22637
|
+
createdAt: number(),
|
|
22638
|
+
/** User id/name that requested the export. */
|
|
22639
|
+
createdBy: string(),
|
|
22640
|
+
/** Failure reason when state is 'failed'; null otherwise. */
|
|
22641
|
+
error: string().nullable()
|
|
22642
|
+
});
|
|
22643
|
+
/** Candidate download URLs (LAN first, then operator extra hosts). */
|
|
22644
|
+
var ExportDownloadSchema = object({
|
|
22645
|
+
url: string(),
|
|
22646
|
+
endpoints: array(string())
|
|
22647
|
+
});
|
|
22648
|
+
method(object({
|
|
22649
|
+
deviceId: number(),
|
|
22650
|
+
profile: string(),
|
|
22651
|
+
fromMs: number(),
|
|
22652
|
+
toMs: number(),
|
|
22653
|
+
options: ExportOptionsSchema
|
|
22654
|
+
}), ExportRecordSchema, {
|
|
22655
|
+
kind: "mutation",
|
|
22656
|
+
auth: "protected"
|
|
22657
|
+
}), method(object({ deviceId: number().optional() }), array(ExportRecordSchema), {
|
|
22658
|
+
kind: "query",
|
|
22659
|
+
auth: "protected"
|
|
22660
|
+
}), method(object({ exportId: string() }), ExportRecordSchema, {
|
|
22661
|
+
kind: "query",
|
|
22662
|
+
auth: "protected"
|
|
22663
|
+
}), method(object({ exportId: string() }), ExportRecordSchema, {
|
|
22664
|
+
kind: "mutation",
|
|
22665
|
+
auth: "protected"
|
|
22666
|
+
}), method(object({ exportId: string() }), ExportRecordSchema, {
|
|
22667
|
+
kind: "mutation",
|
|
22668
|
+
auth: "protected"
|
|
22669
|
+
}), method(object({ exportId: string() }), ExportDownloadSchema, {
|
|
22670
|
+
kind: "query",
|
|
22671
|
+
auth: "protected"
|
|
22405
22672
|
});
|
|
22406
22673
|
/**
|
|
22407
22674
|
* One publishable camera stream as its OWNING PROVIDER describes it — the same
|
|
@@ -25421,6 +25688,12 @@ Object.freeze({
|
|
|
25421
25688
|
addonId: null,
|
|
25422
25689
|
access: "delete"
|
|
25423
25690
|
},
|
|
25691
|
+
"pipelineAnalytics.deleteDeviceEvents": {
|
|
25692
|
+
capName: "pipeline-analytics",
|
|
25693
|
+
capScope: "device",
|
|
25694
|
+
addonId: null,
|
|
25695
|
+
access: "delete"
|
|
25696
|
+
},
|
|
25424
25697
|
"pipelineAnalytics.deleteTracks": {
|
|
25425
25698
|
capName: "pipeline-analytics",
|
|
25426
25699
|
capScope: "device",
|
|
@@ -25451,6 +25724,12 @@ Object.freeze({
|
|
|
25451
25724
|
addonId: null,
|
|
25452
25725
|
access: "view"
|
|
25453
25726
|
},
|
|
25727
|
+
"pipelineAnalytics.getEventStoreFootprint": {
|
|
25728
|
+
capName: "pipeline-analytics",
|
|
25729
|
+
capScope: "device",
|
|
25730
|
+
addonId: null,
|
|
25731
|
+
access: "view"
|
|
25732
|
+
},
|
|
25454
25733
|
"pipelineAnalytics.getKeyEvents": {
|
|
25455
25734
|
capName: "pipeline-analytics",
|
|
25456
25735
|
capScope: "device",
|
|
@@ -25493,6 +25772,12 @@ Object.freeze({
|
|
|
25493
25772
|
addonId: null,
|
|
25494
25773
|
access: "view"
|
|
25495
25774
|
},
|
|
25775
|
+
"pipelineAnalytics.listOpsLog": {
|
|
25776
|
+
capName: "pipeline-analytics",
|
|
25777
|
+
capScope: "device",
|
|
25778
|
+
addonId: null,
|
|
25779
|
+
access: "view"
|
|
25780
|
+
},
|
|
25496
25781
|
"pipelineAnalytics.listRecentTracks": {
|
|
25497
25782
|
capName: "pipeline-analytics",
|
|
25498
25783
|
capScope: "device",
|
|
@@ -25505,6 +25790,12 @@ Object.freeze({
|
|
|
25505
25790
|
addonId: null,
|
|
25506
25791
|
access: "view"
|
|
25507
25792
|
},
|
|
25793
|
+
"pipelineAnalytics.pruneEvents": {
|
|
25794
|
+
capName: "pipeline-analytics",
|
|
25795
|
+
capScope: "device",
|
|
25796
|
+
addonId: null,
|
|
25797
|
+
access: "create"
|
|
25798
|
+
},
|
|
25508
25799
|
"pipelineAnalytics.pruneEventsBefore": {
|
|
25509
25800
|
capName: "pipeline-analytics",
|
|
25510
25801
|
capScope: "device",
|
|
@@ -26267,6 +26558,12 @@ Object.freeze({
|
|
|
26267
26558
|
addonId: null,
|
|
26268
26559
|
access: "create"
|
|
26269
26560
|
},
|
|
26561
|
+
"recording.deleteFootprint": {
|
|
26562
|
+
capName: "recording",
|
|
26563
|
+
capScope: "system",
|
|
26564
|
+
addonId: null,
|
|
26565
|
+
access: "delete"
|
|
26566
|
+
},
|
|
26270
26567
|
"recording.getAvailability": {
|
|
26271
26568
|
capName: "recording",
|
|
26272
26569
|
capScope: "system",
|
|
@@ -26297,6 +26594,12 @@ Object.freeze({
|
|
|
26297
26594
|
addonId: null,
|
|
26298
26595
|
access: "view"
|
|
26299
26596
|
},
|
|
26597
|
+
"recording.listOpsLog": {
|
|
26598
|
+
capName: "recording",
|
|
26599
|
+
capScope: "system",
|
|
26600
|
+
addonId: null,
|
|
26601
|
+
access: "view"
|
|
26602
|
+
},
|
|
26300
26603
|
"recording.locateSegment": {
|
|
26301
26604
|
capName: "recording",
|
|
26302
26605
|
capScope: "system",
|
|
@@ -26327,6 +26630,42 @@ Object.freeze({
|
|
|
26327
26630
|
addonId: null,
|
|
26328
26631
|
access: "create"
|
|
26329
26632
|
},
|
|
26633
|
+
"recordingExport.cancelExport": {
|
|
26634
|
+
capName: "recordingExport",
|
|
26635
|
+
capScope: "system",
|
|
26636
|
+
addonId: null,
|
|
26637
|
+
access: "create"
|
|
26638
|
+
},
|
|
26639
|
+
"recordingExport.createExport": {
|
|
26640
|
+
capName: "recordingExport",
|
|
26641
|
+
capScope: "system",
|
|
26642
|
+
addonId: null,
|
|
26643
|
+
access: "create"
|
|
26644
|
+
},
|
|
26645
|
+
"recordingExport.deleteExport": {
|
|
26646
|
+
capName: "recordingExport",
|
|
26647
|
+
capScope: "system",
|
|
26648
|
+
addonId: null,
|
|
26649
|
+
access: "delete"
|
|
26650
|
+
},
|
|
26651
|
+
"recordingExport.getDownloadUrl": {
|
|
26652
|
+
capName: "recordingExport",
|
|
26653
|
+
capScope: "system",
|
|
26654
|
+
addonId: null,
|
|
26655
|
+
access: "view"
|
|
26656
|
+
},
|
|
26657
|
+
"recordingExport.getExport": {
|
|
26658
|
+
capName: "recordingExport",
|
|
26659
|
+
capScope: "system",
|
|
26660
|
+
addonId: null,
|
|
26661
|
+
access: "view"
|
|
26662
|
+
},
|
|
26663
|
+
"recordingExport.listExports": {
|
|
26664
|
+
capName: "recordingExport",
|
|
26665
|
+
capScope: "system",
|
|
26666
|
+
addonId: null,
|
|
26667
|
+
access: "view"
|
|
26668
|
+
},
|
|
26330
26669
|
"sceneMonitor.captureReference": {
|
|
26331
26670
|
capName: "scene-monitor",
|
|
26332
26671
|
capScope: "device",
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@camstack/addon-provider-unifi",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.13",
|
|
4
4
|
"description": "UniFi Network controller device-provider addon for CamStack — local-controller infra switches/APs (as containers) + network-client presence. NO cameras/Protect.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"camstack",
|