@camstack/addon-provider-dreo 0.1.20 → 0.1.22
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
|
@@ -35,7 +35,7 @@ var __toCommonJS = (mod) => __hasOwnProp.call(mod, "module.exports") ? mod["modu
|
|
|
35
35
|
//#endregion
|
|
36
36
|
let crypto$1 = require("crypto");
|
|
37
37
|
let events = require("events");
|
|
38
|
-
//#region ../types/dist/event-category-
|
|
38
|
+
//#region ../types/dist/event-category-D4HJq7Mw.mjs
|
|
39
39
|
var EventCategory = /* @__PURE__ */ function(EventCategory) {
|
|
40
40
|
EventCategory["SystemBoot"] = "system.boot";
|
|
41
41
|
EventCategory["SystemAddonsReady"] = "system.addons-ready";
|
|
@@ -188,6 +188,11 @@ var EventCategory = /* @__PURE__ */ function(EventCategory) {
|
|
|
188
188
|
/** Runner-sampled scrub thumbnail (~1/5 s/camera). Telemetry (D8): a lost
|
|
189
189
|
* thumb is a scrub gap the recorder's keyframe backfill covers. */
|
|
190
190
|
EventCategory["RecordingThumbSampled"] = "recording.thumb-sampled";
|
|
191
|
+
/** Export render progress (0–100). Telemetry (D8): a lost tick is a stale
|
|
192
|
+
* progress bar the client reconciles via `recordingExport.getExport`. */
|
|
193
|
+
EventCategory["RecordingExportProgress"] = "recording.export.progress";
|
|
194
|
+
EventCategory["RecordingExportCompleted"] = "recording.export.completed";
|
|
195
|
+
EventCategory["RecordingExportFailed"] = "recording.export.failed";
|
|
191
196
|
EventCategory["DetectionEvent"] = "detection.event";
|
|
192
197
|
EventCategory["SessionTrackNew"] = "session.track.new";
|
|
193
198
|
EventCategory["SessionTrackExpired"] = "session.track.expired";
|
|
@@ -477,6 +482,25 @@ var EventCategory = /* @__PURE__ */ function(EventCategory) {
|
|
|
477
482
|
*/
|
|
478
483
|
EventCategory["PipelineAnalyticsStationaryChanged"] = "pipeline-analytics.stationary-changed";
|
|
479
484
|
/**
|
|
485
|
+
* Fired by `addon-post-analysis` when a package-drop is confirmed inside
|
|
486
|
+
* a package zone — a newly-appeared stationary object of a package class
|
|
487
|
+
* that cleared the class / zone / dwell / size gates. Payload:
|
|
488
|
+
* `PipelineAnalyticsPackageDeliveredPayload` carrying `{ deviceId,
|
|
489
|
+
* entryId, className, zoneIds, keyFrameMediaKey?, bbox, timestamp }`.
|
|
490
|
+
* Telemetry (D8): the durable record is the `package-events` store row;
|
|
491
|
+
* this bus topic drives notifier rules + live UI. See
|
|
492
|
+
* docs/superpowers/specs/2026-07-17-package-zones-design.md §5.1.
|
|
493
|
+
*/
|
|
494
|
+
EventCategory["PipelineAnalyticsPackageDelivered"] = "pipeline-analytics.package-delivered";
|
|
495
|
+
/**
|
|
496
|
+
* Fired by `addon-post-analysis` when a previously-delivered package
|
|
497
|
+
* leaves its zone (the stationary entry departed — moved or swept).
|
|
498
|
+
* Payload: `PipelineAnalyticsPackagePickedUpPayload` carrying
|
|
499
|
+
* `{ deviceId, entryId, deliveredEventId, className, timestamp }`.
|
|
500
|
+
* Telemetry (D8). See package-zones-design §5.2.
|
|
501
|
+
*/
|
|
502
|
+
EventCategory["PipelineAnalyticsPackagePickedUp"] = "pipeline-analytics.package-picked-up";
|
|
503
|
+
/**
|
|
480
504
|
* Fired by `addon-post-analysis` whenever a gallery face row changes:
|
|
481
505
|
* `kind:'buffered'` a new detected face was persisted, `'assigned'` /
|
|
482
506
|
* `'unassigned'` its identity link changed, `'deleted'` the row was
|
|
@@ -5215,6 +5239,25 @@ function _instanceof(cls, params = {}) {
|
|
|
5215
5239
|
};
|
|
5216
5240
|
return inst;
|
|
5217
5241
|
}
|
|
5242
|
+
//#endregion
|
|
5243
|
+
//#region ../../node_modules/zod/v4/classic/compat.js
|
|
5244
|
+
/** @deprecated Use the raw string literal codes instead, e.g. "invalid_type". */
|
|
5245
|
+
var ZodIssueCode = {
|
|
5246
|
+
invalid_type: "invalid_type",
|
|
5247
|
+
too_big: "too_big",
|
|
5248
|
+
too_small: "too_small",
|
|
5249
|
+
invalid_format: "invalid_format",
|
|
5250
|
+
not_multiple_of: "not_multiple_of",
|
|
5251
|
+
unrecognized_keys: "unrecognized_keys",
|
|
5252
|
+
invalid_union: "invalid_union",
|
|
5253
|
+
invalid_key: "invalid_key",
|
|
5254
|
+
invalid_element: "invalid_element",
|
|
5255
|
+
invalid_value: "invalid_value",
|
|
5256
|
+
custom: "custom"
|
|
5257
|
+
};
|
|
5258
|
+
/** @deprecated Do not use. Stub definition, only included for zod-to-json-schema compatibility. */
|
|
5259
|
+
var ZodFirstPartyTypeKind;
|
|
5260
|
+
ZodFirstPartyTypeKind || (ZodFirstPartyTypeKind = {});
|
|
5218
5261
|
Object.fromEntries([
|
|
5219
5262
|
{
|
|
5220
5263
|
id: "overview",
|
|
@@ -7337,6 +7380,62 @@ var RecordingConfigSchema = object({
|
|
|
7337
7380
|
scrubThumbnails: ScrubThumbnailPresetSchema.optional()
|
|
7338
7381
|
});
|
|
7339
7382
|
/**
|
|
7383
|
+
* Ops-log — the durable, append-only operations audit shared by the
|
|
7384
|
+
* recordings and events management surfaces.
|
|
7385
|
+
*
|
|
7386
|
+
* ONE row shape is reused for both domains so a single "Activity" view can
|
|
7387
|
+
* merge the recorder's DurableState ring (recordings ops-log) and the
|
|
7388
|
+
* pipeline-analytics SQLite collection (events ops-log). Each row records a
|
|
7389
|
+
* management operation, WHY it ran (reason), and its measurable effect
|
|
7390
|
+
* (itemsAffected + bytesReclaimed). Writes are best-effort — a failed log must
|
|
7391
|
+
* never fail the operation it records.
|
|
7392
|
+
*/
|
|
7393
|
+
/** Which management domain the operation belongs to. */
|
|
7394
|
+
var OpsLogDomainSchema = _enum(["recording", "events"]);
|
|
7395
|
+
/** The kind of management operation performed. */
|
|
7396
|
+
var OpsLogOpSchema = _enum([
|
|
7397
|
+
"prune",
|
|
7398
|
+
"manual-delete",
|
|
7399
|
+
"rescan",
|
|
7400
|
+
"retention-run"
|
|
7401
|
+
]);
|
|
7402
|
+
/** Why the operation ran. */
|
|
7403
|
+
var OpsLogReasonSchema = _enum([
|
|
7404
|
+
"retention",
|
|
7405
|
+
"quota",
|
|
7406
|
+
"manual",
|
|
7407
|
+
"operator"
|
|
7408
|
+
]);
|
|
7409
|
+
/** One audit row, shared verbatim by both domains. */
|
|
7410
|
+
var OpsLogEntrySchema = object({
|
|
7411
|
+
/** Unique row id. */
|
|
7412
|
+
id: string(),
|
|
7413
|
+
/** Epoch ms the operation completed. */
|
|
7414
|
+
at: number(),
|
|
7415
|
+
domain: OpsLogDomainSchema,
|
|
7416
|
+
op: OpsLogOpSchema,
|
|
7417
|
+
reason: OpsLogReasonSchema,
|
|
7418
|
+
/** The camera the op targeted; null for a cluster/global op. */
|
|
7419
|
+
deviceId: number().nullable(),
|
|
7420
|
+
/** Node that performed the op (the log carries nodeId — no cross-node aggregation). */
|
|
7421
|
+
nodeId: string(),
|
|
7422
|
+
/** Buckets / rows deleted (op-specific unit). */
|
|
7423
|
+
itemsAffected: number(),
|
|
7424
|
+
/** Bytes reclaimed by the op (0 when not measurable). */
|
|
7425
|
+
bytesReclaimed: number(),
|
|
7426
|
+
/** Free-text detail (e.g. "floor moved to <ts>"); null when none. */
|
|
7427
|
+
detail: string().nullable(),
|
|
7428
|
+
/** Who/what triggered the op. */
|
|
7429
|
+
actor: string()
|
|
7430
|
+
});
|
|
7431
|
+
/** Shared query input for the per-domain `listOpsLog` cap methods. */
|
|
7432
|
+
var OpsLogQueryInputSchema = object({
|
|
7433
|
+
/** Restrict to a single camera; omit for every row. */
|
|
7434
|
+
deviceId: number().optional(),
|
|
7435
|
+
/** Max rows returned, newest-first. */
|
|
7436
|
+
limit: number().int().min(1).max(1e3).optional()
|
|
7437
|
+
});
|
|
7438
|
+
/**
|
|
7340
7439
|
* `StorageLocationType` — an addon-declared id that identifies the *kind* of
|
|
7341
7440
|
* storage a location serves. Defined here (not in `capabilities/storage.cap.ts`)
|
|
7342
7441
|
* so the persisted record schema and the consumer-facing cap can both consume it
|
|
@@ -14692,7 +14791,11 @@ array(ZoneRuleSchema).readonly();
|
|
|
14692
14791
|
* Extend the enum here when a new gating consumer comes online (audio
|
|
14693
14792
|
* gating, alert filtering, …) — no other surface needs to change.
|
|
14694
14793
|
*/
|
|
14695
|
-
var ZoneRuleStageEnum = _enum([
|
|
14794
|
+
var ZoneRuleStageEnum = _enum([
|
|
14795
|
+
"motion",
|
|
14796
|
+
"detection",
|
|
14797
|
+
"package"
|
|
14798
|
+
]);
|
|
14696
14799
|
/**
|
|
14697
14800
|
* Runtime registry: cap-property-name → cap definition. `BaseDevice`'s
|
|
14698
14801
|
* `state` getter looks up the cap definition here to construct a
|
|
@@ -14786,16 +14889,25 @@ var DEVICE_LOCAL_STATE_CAPS = {
|
|
|
14786
14889
|
})
|
|
14787
14890
|
},
|
|
14788
14891
|
/**
|
|
14789
|
-
* Runtime-state slice —
|
|
14892
|
+
* Runtime-state slice — every stage mirrored together so consumers
|
|
14790
14893
|
* see one reactive handle (`device.state.zoneRules.value`) instead
|
|
14791
|
-
* of
|
|
14792
|
-
* `{motion, detection}` shape, so subscribers always get the
|
|
14894
|
+
* of one per stage. Bulk-replace mutations on any stage write the full
|
|
14895
|
+
* `{motion, detection, package}` shape, so subscribers always get the
|
|
14793
14896
|
* complete current set. Consumers that only care about one stage
|
|
14794
14897
|
* just read the matching property.
|
|
14898
|
+
*
|
|
14899
|
+
* `package` backs the package-drop detector — a package zone is a
|
|
14900
|
+
* `ZoneRule` on the `'package'` stage referencing drawn polygons
|
|
14901
|
+
* (see docs/superpowers/specs/2026-07-17-package-zones-design.md §3.1).
|
|
14902
|
+
* The orchestrator provider writes this stage as a first-class slice
|
|
14903
|
+
* (Phase 4): every mutation mirrors the full `{motion, detection,
|
|
14904
|
+
* package}` shape, so consumers read the current package rules directly
|
|
14905
|
+
* off `device.state.zoneRules.value.package`.
|
|
14795
14906
|
*/
|
|
14796
14907
|
runtimeState: object({
|
|
14797
14908
|
motion: array(ZoneRuleSchema).readonly(),
|
|
14798
|
-
detection: array(ZoneRuleSchema).readonly()
|
|
14909
|
+
detection: array(ZoneRuleSchema).readonly(),
|
|
14910
|
+
package: array(ZoneRuleSchema).readonly()
|
|
14799
14911
|
})
|
|
14800
14912
|
},
|
|
14801
14913
|
zones: zonesCapability
|
|
@@ -18774,6 +18886,7 @@ var EventKindIconSchema = _enum([
|
|
|
18774
18886
|
"smoke",
|
|
18775
18887
|
"water",
|
|
18776
18888
|
"button",
|
|
18889
|
+
"package",
|
|
18777
18890
|
"generic"
|
|
18778
18891
|
]);
|
|
18779
18892
|
var EventKindCategorySchema = _enum([
|
|
@@ -18781,7 +18894,8 @@ var EventKindCategorySchema = _enum([
|
|
|
18781
18894
|
"audio",
|
|
18782
18895
|
"detection",
|
|
18783
18896
|
"sensor",
|
|
18784
|
-
"custom"
|
|
18897
|
+
"custom",
|
|
18898
|
+
"package"
|
|
18785
18899
|
]);
|
|
18786
18900
|
var EventKindDescriptorSchema = object({
|
|
18787
18901
|
/** Stable kind id (e.g. 'motion', 'person', 'contact'). */
|
|
@@ -19122,6 +19236,26 @@ var TrackCascadeCountsSchema = object({
|
|
|
19122
19236
|
/** Per-track CLIP search vectors removed (best-effort). */
|
|
19123
19237
|
embeddings: number().int()
|
|
19124
19238
|
});
|
|
19239
|
+
/** Event-store footprint for one camera. */
|
|
19240
|
+
var EventStoreDeviceFootprintSchema = object({
|
|
19241
|
+
deviceId: number(),
|
|
19242
|
+
/** Persisted event rows (motion + object + audio) for the camera. */
|
|
19243
|
+
rows: number().int(),
|
|
19244
|
+
/** Event-owned media bytes on disk for the camera. */
|
|
19245
|
+
bytes: number().int()
|
|
19246
|
+
});
|
|
19247
|
+
/** Aggregate event-store footprint: global totals + per-camera breakdown. */
|
|
19248
|
+
var EventStoreFootprintSchema = object({
|
|
19249
|
+
totalRows: number().int(),
|
|
19250
|
+
totalBytes: number().int(),
|
|
19251
|
+
devices: array(EventStoreDeviceFootprintSchema).readonly()
|
|
19252
|
+
});
|
|
19253
|
+
/** Per-kind counts returned by the event-prune / device-delete mutations. */
|
|
19254
|
+
var EventPruneCountsSchema = object({
|
|
19255
|
+
motion: number().int(),
|
|
19256
|
+
object: number().int(),
|
|
19257
|
+
audio: number().int()
|
|
19258
|
+
});
|
|
19125
19259
|
DeviceType.Camera, method(object({ deviceId: number() }), array(TrackSchema).readonly()), method(object({
|
|
19126
19260
|
deviceId: number(),
|
|
19127
19261
|
trackId: string()
|
|
@@ -19185,6 +19319,21 @@ DeviceType.Camera, method(object({ deviceId: number() }), array(TrackSchema).rea
|
|
|
19185
19319
|
}), {
|
|
19186
19320
|
kind: "mutation",
|
|
19187
19321
|
auth: "admin"
|
|
19322
|
+
}), method(object({}), EventStoreFootprintSchema, {
|
|
19323
|
+
kind: "query",
|
|
19324
|
+
auth: "admin"
|
|
19325
|
+
}), method(object({
|
|
19326
|
+
olderThanMs: number(),
|
|
19327
|
+
reason: OpsLogReasonSchema.optional()
|
|
19328
|
+
}), EventPruneCountsSchema, {
|
|
19329
|
+
kind: "mutation",
|
|
19330
|
+
auth: "admin"
|
|
19331
|
+
}), method(object({ deviceId: number() }), EventPruneCountsSchema, {
|
|
19332
|
+
kind: "mutation",
|
|
19333
|
+
auth: "admin"
|
|
19334
|
+
}), method(OpsLogQueryInputSchema, array(OpsLogEntrySchema).readonly(), {
|
|
19335
|
+
kind: "query",
|
|
19336
|
+
auth: "admin"
|
|
19188
19337
|
}), method(object({
|
|
19189
19338
|
eventId: string(),
|
|
19190
19339
|
kind: MediaFileKindEnum.optional()
|
|
@@ -22418,13 +22567,131 @@ method(object({
|
|
|
22418
22567
|
}), method(object({ deviceId: number() }), RecordingStatusSchema, {
|
|
22419
22568
|
kind: "mutation",
|
|
22420
22569
|
auth: "admin"
|
|
22421
|
-
}), method(object({
|
|
22570
|
+
}), method(object({
|
|
22571
|
+
deviceId: number(),
|
|
22572
|
+
reason: OpsLogReasonSchema.optional()
|
|
22573
|
+
}), object({
|
|
22422
22574
|
floorMs: number().nullable(),
|
|
22423
22575
|
deletedBuckets: number().int(),
|
|
22424
22576
|
reclaimedBytes: number().int()
|
|
22425
22577
|
}), {
|
|
22426
22578
|
kind: "mutation",
|
|
22427
22579
|
auth: "admin"
|
|
22580
|
+
}), method(object({
|
|
22581
|
+
deviceId: number(),
|
|
22582
|
+
fromMs: number().optional(),
|
|
22583
|
+
toMs: number().optional()
|
|
22584
|
+
}), object({
|
|
22585
|
+
deletedBuckets: number().int(),
|
|
22586
|
+
reclaimedBytes: number().int()
|
|
22587
|
+
}), {
|
|
22588
|
+
kind: "mutation",
|
|
22589
|
+
auth: "admin"
|
|
22590
|
+
}), method(OpsLogQueryInputSchema, array(OpsLogEntrySchema).readonly(), {
|
|
22591
|
+
kind: "query",
|
|
22592
|
+
auth: "admin"
|
|
22593
|
+
});
|
|
22594
|
+
/**
|
|
22595
|
+
* `recordingExport` cap — render a footage time range into a single downloadable
|
|
22596
|
+
* MP4 (regular / accelerated / decelerated / timelapse, ± audio), kept for a
|
|
22597
|
+
* bounded lifetime with a durable history, auto-expiry, and optional
|
|
22598
|
+
* delete-after-download.
|
|
22599
|
+
*
|
|
22600
|
+
* Like `recording` this is a `scope:'system', mode:'singleton'` cap: the
|
|
22601
|
+
* recorder self-gates so exactly ONE node (the designated `recordingNodeId`,
|
|
22602
|
+
* default `hub`) registers it. Device-scoped methods carry `deviceId` in their
|
|
22603
|
+
* input and dispatch to that single provider; the render runs on the node that
|
|
22604
|
+
* owns the footage (no cross-node segment transfer). Download rides the
|
|
22605
|
+
* framework addon data-plane. State persists in a DurableState blob (NOT
|
|
22606
|
+
* SQLite); history rows survive file deletion for audit.
|
|
22607
|
+
*/
|
|
22608
|
+
/** Playback-speed multiplier for the render (1 = realtime). */
|
|
22609
|
+
var ExportSpeedSchema = number().min(.25).max(32);
|
|
22610
|
+
/** Timelapse cadence — sample one source frame per `everyMs`, output at `outputFps`. */
|
|
22611
|
+
var ExportTimelapseSchema = object({
|
|
22612
|
+
everyMs: number().int().positive(),
|
|
22613
|
+
outputFps: number().int().min(1).max(60).optional()
|
|
22614
|
+
});
|
|
22615
|
+
/**
|
|
22616
|
+
* Render options. `speed` and `timelapse` are mutually exclusive. `includeAudio`
|
|
22617
|
+
* is honoured only for a realtime-ish speed (0.5–2×); timelapse is always
|
|
22618
|
+
* silent. `maxLifeMs` bounds how long the finished file is kept;
|
|
22619
|
+
* `deleteAfterDownload` removes it shortly after the first complete download.
|
|
22620
|
+
*/
|
|
22621
|
+
var ExportOptionsSchema = object({
|
|
22622
|
+
speed: ExportSpeedSchema.optional(),
|
|
22623
|
+
timelapse: ExportTimelapseSchema.optional(),
|
|
22624
|
+
includeAudio: boolean(),
|
|
22625
|
+
maxLifeMs: number().int().positive(),
|
|
22626
|
+
deleteAfterDownload: boolean(),
|
|
22627
|
+
title: string().max(200).optional()
|
|
22628
|
+
}).superRefine((v, ctx) => {
|
|
22629
|
+
if (v.speed !== void 0 && v.timelapse !== void 0) ctx.addIssue({
|
|
22630
|
+
code: ZodIssueCode.custom,
|
|
22631
|
+
message: "speed and timelapse are mutually exclusive",
|
|
22632
|
+
path: ["timelapse"]
|
|
22633
|
+
});
|
|
22634
|
+
});
|
|
22635
|
+
var ExportStateSchema = _enum([
|
|
22636
|
+
"queued",
|
|
22637
|
+
"rendering",
|
|
22638
|
+
"ready",
|
|
22639
|
+
"failed",
|
|
22640
|
+
"expired",
|
|
22641
|
+
"deleted"
|
|
22642
|
+
]);
|
|
22643
|
+
/** One export job / history row. */
|
|
22644
|
+
var ExportRecordSchema = object({
|
|
22645
|
+
id: string(),
|
|
22646
|
+
deviceId: number(),
|
|
22647
|
+
profile: string(),
|
|
22648
|
+
fromMs: number(),
|
|
22649
|
+
toMs: number(),
|
|
22650
|
+
options: ExportOptionsSchema,
|
|
22651
|
+
state: ExportStateSchema,
|
|
22652
|
+
/** 0–100 while rendering; null otherwise. */
|
|
22653
|
+
progressPct: number().nullable(),
|
|
22654
|
+
/** File size once ready; null before. */
|
|
22655
|
+
fileBytes: number().nullable(),
|
|
22656
|
+
expiresAt: number(),
|
|
22657
|
+
deleteAfterDownload: boolean(),
|
|
22658
|
+
/** Epoch of the first complete download; null until then. */
|
|
22659
|
+
downloadedAt: number().nullable(),
|
|
22660
|
+
createdAt: number(),
|
|
22661
|
+
/** User id/name that requested the export. */
|
|
22662
|
+
createdBy: string(),
|
|
22663
|
+
/** Failure reason when state is 'failed'; null otherwise. */
|
|
22664
|
+
error: string().nullable()
|
|
22665
|
+
});
|
|
22666
|
+
/** Candidate download URLs (LAN first, then operator extra hosts). */
|
|
22667
|
+
var ExportDownloadSchema = object({
|
|
22668
|
+
url: string(),
|
|
22669
|
+
endpoints: array(string())
|
|
22670
|
+
});
|
|
22671
|
+
method(object({
|
|
22672
|
+
deviceId: number(),
|
|
22673
|
+
profile: string(),
|
|
22674
|
+
fromMs: number(),
|
|
22675
|
+
toMs: number(),
|
|
22676
|
+
options: ExportOptionsSchema
|
|
22677
|
+
}), ExportRecordSchema, {
|
|
22678
|
+
kind: "mutation",
|
|
22679
|
+
auth: "protected"
|
|
22680
|
+
}), method(object({ deviceId: number().optional() }), array(ExportRecordSchema), {
|
|
22681
|
+
kind: "query",
|
|
22682
|
+
auth: "protected"
|
|
22683
|
+
}), method(object({ exportId: string() }), ExportRecordSchema, {
|
|
22684
|
+
kind: "query",
|
|
22685
|
+
auth: "protected"
|
|
22686
|
+
}), method(object({ exportId: string() }), ExportRecordSchema, {
|
|
22687
|
+
kind: "mutation",
|
|
22688
|
+
auth: "protected"
|
|
22689
|
+
}), method(object({ exportId: string() }), ExportRecordSchema, {
|
|
22690
|
+
kind: "mutation",
|
|
22691
|
+
auth: "protected"
|
|
22692
|
+
}), method(object({ exportId: string() }), ExportDownloadSchema, {
|
|
22693
|
+
kind: "query",
|
|
22694
|
+
auth: "protected"
|
|
22428
22695
|
});
|
|
22429
22696
|
/**
|
|
22430
22697
|
* One publishable camera stream as its OWNING PROVIDER describes it — the same
|
|
@@ -25444,6 +25711,12 @@ Object.freeze({
|
|
|
25444
25711
|
addonId: null,
|
|
25445
25712
|
access: "delete"
|
|
25446
25713
|
},
|
|
25714
|
+
"pipelineAnalytics.deleteDeviceEvents": {
|
|
25715
|
+
capName: "pipeline-analytics",
|
|
25716
|
+
capScope: "device",
|
|
25717
|
+
addonId: null,
|
|
25718
|
+
access: "delete"
|
|
25719
|
+
},
|
|
25447
25720
|
"pipelineAnalytics.deleteTracks": {
|
|
25448
25721
|
capName: "pipeline-analytics",
|
|
25449
25722
|
capScope: "device",
|
|
@@ -25474,6 +25747,12 @@ Object.freeze({
|
|
|
25474
25747
|
addonId: null,
|
|
25475
25748
|
access: "view"
|
|
25476
25749
|
},
|
|
25750
|
+
"pipelineAnalytics.getEventStoreFootprint": {
|
|
25751
|
+
capName: "pipeline-analytics",
|
|
25752
|
+
capScope: "device",
|
|
25753
|
+
addonId: null,
|
|
25754
|
+
access: "view"
|
|
25755
|
+
},
|
|
25477
25756
|
"pipelineAnalytics.getKeyEvents": {
|
|
25478
25757
|
capName: "pipeline-analytics",
|
|
25479
25758
|
capScope: "device",
|
|
@@ -25516,6 +25795,12 @@ Object.freeze({
|
|
|
25516
25795
|
addonId: null,
|
|
25517
25796
|
access: "view"
|
|
25518
25797
|
},
|
|
25798
|
+
"pipelineAnalytics.listOpsLog": {
|
|
25799
|
+
capName: "pipeline-analytics",
|
|
25800
|
+
capScope: "device",
|
|
25801
|
+
addonId: null,
|
|
25802
|
+
access: "view"
|
|
25803
|
+
},
|
|
25519
25804
|
"pipelineAnalytics.listRecentTracks": {
|
|
25520
25805
|
capName: "pipeline-analytics",
|
|
25521
25806
|
capScope: "device",
|
|
@@ -25528,6 +25813,12 @@ Object.freeze({
|
|
|
25528
25813
|
addonId: null,
|
|
25529
25814
|
access: "view"
|
|
25530
25815
|
},
|
|
25816
|
+
"pipelineAnalytics.pruneEvents": {
|
|
25817
|
+
capName: "pipeline-analytics",
|
|
25818
|
+
capScope: "device",
|
|
25819
|
+
addonId: null,
|
|
25820
|
+
access: "create"
|
|
25821
|
+
},
|
|
25531
25822
|
"pipelineAnalytics.pruneEventsBefore": {
|
|
25532
25823
|
capName: "pipeline-analytics",
|
|
25533
25824
|
capScope: "device",
|
|
@@ -26290,6 +26581,12 @@ Object.freeze({
|
|
|
26290
26581
|
addonId: null,
|
|
26291
26582
|
access: "create"
|
|
26292
26583
|
},
|
|
26584
|
+
"recording.deleteFootprint": {
|
|
26585
|
+
capName: "recording",
|
|
26586
|
+
capScope: "system",
|
|
26587
|
+
addonId: null,
|
|
26588
|
+
access: "delete"
|
|
26589
|
+
},
|
|
26293
26590
|
"recording.getAvailability": {
|
|
26294
26591
|
capName: "recording",
|
|
26295
26592
|
capScope: "system",
|
|
@@ -26320,6 +26617,12 @@ Object.freeze({
|
|
|
26320
26617
|
addonId: null,
|
|
26321
26618
|
access: "view"
|
|
26322
26619
|
},
|
|
26620
|
+
"recording.listOpsLog": {
|
|
26621
|
+
capName: "recording",
|
|
26622
|
+
capScope: "system",
|
|
26623
|
+
addonId: null,
|
|
26624
|
+
access: "view"
|
|
26625
|
+
},
|
|
26323
26626
|
"recording.locateSegment": {
|
|
26324
26627
|
capName: "recording",
|
|
26325
26628
|
capScope: "system",
|
|
@@ -26350,6 +26653,42 @@ Object.freeze({
|
|
|
26350
26653
|
addonId: null,
|
|
26351
26654
|
access: "create"
|
|
26352
26655
|
},
|
|
26656
|
+
"recordingExport.cancelExport": {
|
|
26657
|
+
capName: "recordingExport",
|
|
26658
|
+
capScope: "system",
|
|
26659
|
+
addonId: null,
|
|
26660
|
+
access: "create"
|
|
26661
|
+
},
|
|
26662
|
+
"recordingExport.createExport": {
|
|
26663
|
+
capName: "recordingExport",
|
|
26664
|
+
capScope: "system",
|
|
26665
|
+
addonId: null,
|
|
26666
|
+
access: "create"
|
|
26667
|
+
},
|
|
26668
|
+
"recordingExport.deleteExport": {
|
|
26669
|
+
capName: "recordingExport",
|
|
26670
|
+
capScope: "system",
|
|
26671
|
+
addonId: null,
|
|
26672
|
+
access: "delete"
|
|
26673
|
+
},
|
|
26674
|
+
"recordingExport.getDownloadUrl": {
|
|
26675
|
+
capName: "recordingExport",
|
|
26676
|
+
capScope: "system",
|
|
26677
|
+
addonId: null,
|
|
26678
|
+
access: "view"
|
|
26679
|
+
},
|
|
26680
|
+
"recordingExport.getExport": {
|
|
26681
|
+
capName: "recordingExport",
|
|
26682
|
+
capScope: "system",
|
|
26683
|
+
addonId: null,
|
|
26684
|
+
access: "view"
|
|
26685
|
+
},
|
|
26686
|
+
"recordingExport.listExports": {
|
|
26687
|
+
capName: "recordingExport",
|
|
26688
|
+
capScope: "system",
|
|
26689
|
+
addonId: null,
|
|
26690
|
+
access: "view"
|
|
26691
|
+
},
|
|
26353
26692
|
"sceneMonitor.captureReference": {
|
|
26354
26693
|
capName: "scene-monitor",
|
|
26355
26694
|
capScope: "device",
|
package/dist/addon.mjs
CHANGED
|
@@ -36,7 +36,7 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
|
|
|
36
36
|
var __toCommonJS = (mod) => __hasOwnProp.call(mod, "module.exports") ? mod["module.exports"] : __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
37
37
|
var __require = /* @__PURE__ */ createRequire(import.meta.url);
|
|
38
38
|
//#endregion
|
|
39
|
-
//#region ../types/dist/event-category-
|
|
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
|
|
@@ -5216,6 +5240,25 @@ function _instanceof(cls, params = {}) {
|
|
|
5216
5240
|
};
|
|
5217
5241
|
return inst;
|
|
5218
5242
|
}
|
|
5243
|
+
//#endregion
|
|
5244
|
+
//#region ../../node_modules/zod/v4/classic/compat.js
|
|
5245
|
+
/** @deprecated Use the raw string literal codes instead, e.g. "invalid_type". */
|
|
5246
|
+
var ZodIssueCode = {
|
|
5247
|
+
invalid_type: "invalid_type",
|
|
5248
|
+
too_big: "too_big",
|
|
5249
|
+
too_small: "too_small",
|
|
5250
|
+
invalid_format: "invalid_format",
|
|
5251
|
+
not_multiple_of: "not_multiple_of",
|
|
5252
|
+
unrecognized_keys: "unrecognized_keys",
|
|
5253
|
+
invalid_union: "invalid_union",
|
|
5254
|
+
invalid_key: "invalid_key",
|
|
5255
|
+
invalid_element: "invalid_element",
|
|
5256
|
+
invalid_value: "invalid_value",
|
|
5257
|
+
custom: "custom"
|
|
5258
|
+
};
|
|
5259
|
+
/** @deprecated Do not use. Stub definition, only included for zod-to-json-schema compatibility. */
|
|
5260
|
+
var ZodFirstPartyTypeKind;
|
|
5261
|
+
ZodFirstPartyTypeKind || (ZodFirstPartyTypeKind = {});
|
|
5219
5262
|
Object.fromEntries([
|
|
5220
5263
|
{
|
|
5221
5264
|
id: "overview",
|
|
@@ -7338,6 +7381,62 @@ var RecordingConfigSchema = object({
|
|
|
7338
7381
|
scrubThumbnails: ScrubThumbnailPresetSchema.optional()
|
|
7339
7382
|
});
|
|
7340
7383
|
/**
|
|
7384
|
+
* Ops-log — the durable, append-only operations audit shared by the
|
|
7385
|
+
* recordings and events management surfaces.
|
|
7386
|
+
*
|
|
7387
|
+
* ONE row shape is reused for both domains so a single "Activity" view can
|
|
7388
|
+
* merge the recorder's DurableState ring (recordings ops-log) and the
|
|
7389
|
+
* pipeline-analytics SQLite collection (events ops-log). Each row records a
|
|
7390
|
+
* management operation, WHY it ran (reason), and its measurable effect
|
|
7391
|
+
* (itemsAffected + bytesReclaimed). Writes are best-effort — a failed log must
|
|
7392
|
+
* never fail the operation it records.
|
|
7393
|
+
*/
|
|
7394
|
+
/** Which management domain the operation belongs to. */
|
|
7395
|
+
var OpsLogDomainSchema = _enum(["recording", "events"]);
|
|
7396
|
+
/** The kind of management operation performed. */
|
|
7397
|
+
var OpsLogOpSchema = _enum([
|
|
7398
|
+
"prune",
|
|
7399
|
+
"manual-delete",
|
|
7400
|
+
"rescan",
|
|
7401
|
+
"retention-run"
|
|
7402
|
+
]);
|
|
7403
|
+
/** Why the operation ran. */
|
|
7404
|
+
var OpsLogReasonSchema = _enum([
|
|
7405
|
+
"retention",
|
|
7406
|
+
"quota",
|
|
7407
|
+
"manual",
|
|
7408
|
+
"operator"
|
|
7409
|
+
]);
|
|
7410
|
+
/** One audit row, shared verbatim by both domains. */
|
|
7411
|
+
var OpsLogEntrySchema = object({
|
|
7412
|
+
/** Unique row id. */
|
|
7413
|
+
id: string(),
|
|
7414
|
+
/** Epoch ms the operation completed. */
|
|
7415
|
+
at: number(),
|
|
7416
|
+
domain: OpsLogDomainSchema,
|
|
7417
|
+
op: OpsLogOpSchema,
|
|
7418
|
+
reason: OpsLogReasonSchema,
|
|
7419
|
+
/** The camera the op targeted; null for a cluster/global op. */
|
|
7420
|
+
deviceId: number().nullable(),
|
|
7421
|
+
/** Node that performed the op (the log carries nodeId — no cross-node aggregation). */
|
|
7422
|
+
nodeId: string(),
|
|
7423
|
+
/** Buckets / rows deleted (op-specific unit). */
|
|
7424
|
+
itemsAffected: number(),
|
|
7425
|
+
/** Bytes reclaimed by the op (0 when not measurable). */
|
|
7426
|
+
bytesReclaimed: number(),
|
|
7427
|
+
/** Free-text detail (e.g. "floor moved to <ts>"); null when none. */
|
|
7428
|
+
detail: string().nullable(),
|
|
7429
|
+
/** Who/what triggered the op. */
|
|
7430
|
+
actor: string()
|
|
7431
|
+
});
|
|
7432
|
+
/** Shared query input for the per-domain `listOpsLog` cap methods. */
|
|
7433
|
+
var OpsLogQueryInputSchema = object({
|
|
7434
|
+
/** Restrict to a single camera; omit for every row. */
|
|
7435
|
+
deviceId: number().optional(),
|
|
7436
|
+
/** Max rows returned, newest-first. */
|
|
7437
|
+
limit: number().int().min(1).max(1e3).optional()
|
|
7438
|
+
});
|
|
7439
|
+
/**
|
|
7341
7440
|
* `StorageLocationType` — an addon-declared id that identifies the *kind* of
|
|
7342
7441
|
* storage a location serves. Defined here (not in `capabilities/storage.cap.ts`)
|
|
7343
7442
|
* so the persisted record schema and the consumer-facing cap can both consume it
|
|
@@ -14693,7 +14792,11 @@ array(ZoneRuleSchema).readonly();
|
|
|
14693
14792
|
* Extend the enum here when a new gating consumer comes online (audio
|
|
14694
14793
|
* gating, alert filtering, …) — no other surface needs to change.
|
|
14695
14794
|
*/
|
|
14696
|
-
var ZoneRuleStageEnum = _enum([
|
|
14795
|
+
var ZoneRuleStageEnum = _enum([
|
|
14796
|
+
"motion",
|
|
14797
|
+
"detection",
|
|
14798
|
+
"package"
|
|
14799
|
+
]);
|
|
14697
14800
|
/**
|
|
14698
14801
|
* Runtime registry: cap-property-name → cap definition. `BaseDevice`'s
|
|
14699
14802
|
* `state` getter looks up the cap definition here to construct a
|
|
@@ -14787,16 +14890,25 @@ var DEVICE_LOCAL_STATE_CAPS = {
|
|
|
14787
14890
|
})
|
|
14788
14891
|
},
|
|
14789
14892
|
/**
|
|
14790
|
-
* Runtime-state slice —
|
|
14893
|
+
* Runtime-state slice — every stage mirrored together so consumers
|
|
14791
14894
|
* see one reactive handle (`device.state.zoneRules.value`) instead
|
|
14792
|
-
* of
|
|
14793
|
-
* `{motion, detection}` shape, so subscribers always get the
|
|
14895
|
+
* of one per stage. Bulk-replace mutations on any stage write the full
|
|
14896
|
+
* `{motion, detection, package}` shape, so subscribers always get the
|
|
14794
14897
|
* complete current set. Consumers that only care about one stage
|
|
14795
14898
|
* just read the matching property.
|
|
14899
|
+
*
|
|
14900
|
+
* `package` backs the package-drop detector — a package zone is a
|
|
14901
|
+
* `ZoneRule` on the `'package'` stage referencing drawn polygons
|
|
14902
|
+
* (see docs/superpowers/specs/2026-07-17-package-zones-design.md §3.1).
|
|
14903
|
+
* The orchestrator provider writes this stage as a first-class slice
|
|
14904
|
+
* (Phase 4): every mutation mirrors the full `{motion, detection,
|
|
14905
|
+
* package}` shape, so consumers read the current package rules directly
|
|
14906
|
+
* off `device.state.zoneRules.value.package`.
|
|
14796
14907
|
*/
|
|
14797
14908
|
runtimeState: object({
|
|
14798
14909
|
motion: array(ZoneRuleSchema).readonly(),
|
|
14799
|
-
detection: array(ZoneRuleSchema).readonly()
|
|
14910
|
+
detection: array(ZoneRuleSchema).readonly(),
|
|
14911
|
+
package: array(ZoneRuleSchema).readonly()
|
|
14800
14912
|
})
|
|
14801
14913
|
},
|
|
14802
14914
|
zones: zonesCapability
|
|
@@ -18775,6 +18887,7 @@ var EventKindIconSchema = _enum([
|
|
|
18775
18887
|
"smoke",
|
|
18776
18888
|
"water",
|
|
18777
18889
|
"button",
|
|
18890
|
+
"package",
|
|
18778
18891
|
"generic"
|
|
18779
18892
|
]);
|
|
18780
18893
|
var EventKindCategorySchema = _enum([
|
|
@@ -18782,7 +18895,8 @@ var EventKindCategorySchema = _enum([
|
|
|
18782
18895
|
"audio",
|
|
18783
18896
|
"detection",
|
|
18784
18897
|
"sensor",
|
|
18785
|
-
"custom"
|
|
18898
|
+
"custom",
|
|
18899
|
+
"package"
|
|
18786
18900
|
]);
|
|
18787
18901
|
var EventKindDescriptorSchema = object({
|
|
18788
18902
|
/** Stable kind id (e.g. 'motion', 'person', 'contact'). */
|
|
@@ -19123,6 +19237,26 @@ var TrackCascadeCountsSchema = object({
|
|
|
19123
19237
|
/** Per-track CLIP search vectors removed (best-effort). */
|
|
19124
19238
|
embeddings: number().int()
|
|
19125
19239
|
});
|
|
19240
|
+
/** Event-store footprint for one camera. */
|
|
19241
|
+
var EventStoreDeviceFootprintSchema = object({
|
|
19242
|
+
deviceId: number(),
|
|
19243
|
+
/** Persisted event rows (motion + object + audio) for the camera. */
|
|
19244
|
+
rows: number().int(),
|
|
19245
|
+
/** Event-owned media bytes on disk for the camera. */
|
|
19246
|
+
bytes: number().int()
|
|
19247
|
+
});
|
|
19248
|
+
/** Aggregate event-store footprint: global totals + per-camera breakdown. */
|
|
19249
|
+
var EventStoreFootprintSchema = object({
|
|
19250
|
+
totalRows: number().int(),
|
|
19251
|
+
totalBytes: number().int(),
|
|
19252
|
+
devices: array(EventStoreDeviceFootprintSchema).readonly()
|
|
19253
|
+
});
|
|
19254
|
+
/** Per-kind counts returned by the event-prune / device-delete mutations. */
|
|
19255
|
+
var EventPruneCountsSchema = object({
|
|
19256
|
+
motion: number().int(),
|
|
19257
|
+
object: number().int(),
|
|
19258
|
+
audio: number().int()
|
|
19259
|
+
});
|
|
19126
19260
|
DeviceType.Camera, method(object({ deviceId: number() }), array(TrackSchema).readonly()), method(object({
|
|
19127
19261
|
deviceId: number(),
|
|
19128
19262
|
trackId: string()
|
|
@@ -19186,6 +19320,21 @@ DeviceType.Camera, method(object({ deviceId: number() }), array(TrackSchema).rea
|
|
|
19186
19320
|
}), {
|
|
19187
19321
|
kind: "mutation",
|
|
19188
19322
|
auth: "admin"
|
|
19323
|
+
}), method(object({}), EventStoreFootprintSchema, {
|
|
19324
|
+
kind: "query",
|
|
19325
|
+
auth: "admin"
|
|
19326
|
+
}), method(object({
|
|
19327
|
+
olderThanMs: number(),
|
|
19328
|
+
reason: OpsLogReasonSchema.optional()
|
|
19329
|
+
}), EventPruneCountsSchema, {
|
|
19330
|
+
kind: "mutation",
|
|
19331
|
+
auth: "admin"
|
|
19332
|
+
}), method(object({ deviceId: number() }), EventPruneCountsSchema, {
|
|
19333
|
+
kind: "mutation",
|
|
19334
|
+
auth: "admin"
|
|
19335
|
+
}), method(OpsLogQueryInputSchema, array(OpsLogEntrySchema).readonly(), {
|
|
19336
|
+
kind: "query",
|
|
19337
|
+
auth: "admin"
|
|
19189
19338
|
}), method(object({
|
|
19190
19339
|
eventId: string(),
|
|
19191
19340
|
kind: MediaFileKindEnum.optional()
|
|
@@ -22419,13 +22568,131 @@ method(object({
|
|
|
22419
22568
|
}), method(object({ deviceId: number() }), RecordingStatusSchema, {
|
|
22420
22569
|
kind: "mutation",
|
|
22421
22570
|
auth: "admin"
|
|
22422
|
-
}), method(object({
|
|
22571
|
+
}), method(object({
|
|
22572
|
+
deviceId: number(),
|
|
22573
|
+
reason: OpsLogReasonSchema.optional()
|
|
22574
|
+
}), object({
|
|
22423
22575
|
floorMs: number().nullable(),
|
|
22424
22576
|
deletedBuckets: number().int(),
|
|
22425
22577
|
reclaimedBytes: number().int()
|
|
22426
22578
|
}), {
|
|
22427
22579
|
kind: "mutation",
|
|
22428
22580
|
auth: "admin"
|
|
22581
|
+
}), method(object({
|
|
22582
|
+
deviceId: number(),
|
|
22583
|
+
fromMs: number().optional(),
|
|
22584
|
+
toMs: number().optional()
|
|
22585
|
+
}), object({
|
|
22586
|
+
deletedBuckets: number().int(),
|
|
22587
|
+
reclaimedBytes: number().int()
|
|
22588
|
+
}), {
|
|
22589
|
+
kind: "mutation",
|
|
22590
|
+
auth: "admin"
|
|
22591
|
+
}), method(OpsLogQueryInputSchema, array(OpsLogEntrySchema).readonly(), {
|
|
22592
|
+
kind: "query",
|
|
22593
|
+
auth: "admin"
|
|
22594
|
+
});
|
|
22595
|
+
/**
|
|
22596
|
+
* `recordingExport` cap — render a footage time range into a single downloadable
|
|
22597
|
+
* MP4 (regular / accelerated / decelerated / timelapse, ± audio), kept for a
|
|
22598
|
+
* bounded lifetime with a durable history, auto-expiry, and optional
|
|
22599
|
+
* delete-after-download.
|
|
22600
|
+
*
|
|
22601
|
+
* Like `recording` this is a `scope:'system', mode:'singleton'` cap: the
|
|
22602
|
+
* recorder self-gates so exactly ONE node (the designated `recordingNodeId`,
|
|
22603
|
+
* default `hub`) registers it. Device-scoped methods carry `deviceId` in their
|
|
22604
|
+
* input and dispatch to that single provider; the render runs on the node that
|
|
22605
|
+
* owns the footage (no cross-node segment transfer). Download rides the
|
|
22606
|
+
* framework addon data-plane. State persists in a DurableState blob (NOT
|
|
22607
|
+
* SQLite); history rows survive file deletion for audit.
|
|
22608
|
+
*/
|
|
22609
|
+
/** Playback-speed multiplier for the render (1 = realtime). */
|
|
22610
|
+
var ExportSpeedSchema = number().min(.25).max(32);
|
|
22611
|
+
/** Timelapse cadence — sample one source frame per `everyMs`, output at `outputFps`. */
|
|
22612
|
+
var ExportTimelapseSchema = object({
|
|
22613
|
+
everyMs: number().int().positive(),
|
|
22614
|
+
outputFps: number().int().min(1).max(60).optional()
|
|
22615
|
+
});
|
|
22616
|
+
/**
|
|
22617
|
+
* Render options. `speed` and `timelapse` are mutually exclusive. `includeAudio`
|
|
22618
|
+
* is honoured only for a realtime-ish speed (0.5–2×); timelapse is always
|
|
22619
|
+
* silent. `maxLifeMs` bounds how long the finished file is kept;
|
|
22620
|
+
* `deleteAfterDownload` removes it shortly after the first complete download.
|
|
22621
|
+
*/
|
|
22622
|
+
var ExportOptionsSchema = object({
|
|
22623
|
+
speed: ExportSpeedSchema.optional(),
|
|
22624
|
+
timelapse: ExportTimelapseSchema.optional(),
|
|
22625
|
+
includeAudio: boolean(),
|
|
22626
|
+
maxLifeMs: number().int().positive(),
|
|
22627
|
+
deleteAfterDownload: boolean(),
|
|
22628
|
+
title: string().max(200).optional()
|
|
22629
|
+
}).superRefine((v, ctx) => {
|
|
22630
|
+
if (v.speed !== void 0 && v.timelapse !== void 0) ctx.addIssue({
|
|
22631
|
+
code: ZodIssueCode.custom,
|
|
22632
|
+
message: "speed and timelapse are mutually exclusive",
|
|
22633
|
+
path: ["timelapse"]
|
|
22634
|
+
});
|
|
22635
|
+
});
|
|
22636
|
+
var ExportStateSchema = _enum([
|
|
22637
|
+
"queued",
|
|
22638
|
+
"rendering",
|
|
22639
|
+
"ready",
|
|
22640
|
+
"failed",
|
|
22641
|
+
"expired",
|
|
22642
|
+
"deleted"
|
|
22643
|
+
]);
|
|
22644
|
+
/** One export job / history row. */
|
|
22645
|
+
var ExportRecordSchema = object({
|
|
22646
|
+
id: string(),
|
|
22647
|
+
deviceId: number(),
|
|
22648
|
+
profile: string(),
|
|
22649
|
+
fromMs: number(),
|
|
22650
|
+
toMs: number(),
|
|
22651
|
+
options: ExportOptionsSchema,
|
|
22652
|
+
state: ExportStateSchema,
|
|
22653
|
+
/** 0–100 while rendering; null otherwise. */
|
|
22654
|
+
progressPct: number().nullable(),
|
|
22655
|
+
/** File size once ready; null before. */
|
|
22656
|
+
fileBytes: number().nullable(),
|
|
22657
|
+
expiresAt: number(),
|
|
22658
|
+
deleteAfterDownload: boolean(),
|
|
22659
|
+
/** Epoch of the first complete download; null until then. */
|
|
22660
|
+
downloadedAt: number().nullable(),
|
|
22661
|
+
createdAt: number(),
|
|
22662
|
+
/** User id/name that requested the export. */
|
|
22663
|
+
createdBy: string(),
|
|
22664
|
+
/** Failure reason when state is 'failed'; null otherwise. */
|
|
22665
|
+
error: string().nullable()
|
|
22666
|
+
});
|
|
22667
|
+
/** Candidate download URLs (LAN first, then operator extra hosts). */
|
|
22668
|
+
var ExportDownloadSchema = object({
|
|
22669
|
+
url: string(),
|
|
22670
|
+
endpoints: array(string())
|
|
22671
|
+
});
|
|
22672
|
+
method(object({
|
|
22673
|
+
deviceId: number(),
|
|
22674
|
+
profile: string(),
|
|
22675
|
+
fromMs: number(),
|
|
22676
|
+
toMs: number(),
|
|
22677
|
+
options: ExportOptionsSchema
|
|
22678
|
+
}), ExportRecordSchema, {
|
|
22679
|
+
kind: "mutation",
|
|
22680
|
+
auth: "protected"
|
|
22681
|
+
}), method(object({ deviceId: number().optional() }), array(ExportRecordSchema), {
|
|
22682
|
+
kind: "query",
|
|
22683
|
+
auth: "protected"
|
|
22684
|
+
}), method(object({ exportId: string() }), ExportRecordSchema, {
|
|
22685
|
+
kind: "query",
|
|
22686
|
+
auth: "protected"
|
|
22687
|
+
}), method(object({ exportId: string() }), ExportRecordSchema, {
|
|
22688
|
+
kind: "mutation",
|
|
22689
|
+
auth: "protected"
|
|
22690
|
+
}), method(object({ exportId: string() }), ExportRecordSchema, {
|
|
22691
|
+
kind: "mutation",
|
|
22692
|
+
auth: "protected"
|
|
22693
|
+
}), method(object({ exportId: string() }), ExportDownloadSchema, {
|
|
22694
|
+
kind: "query",
|
|
22695
|
+
auth: "protected"
|
|
22429
22696
|
});
|
|
22430
22697
|
/**
|
|
22431
22698
|
* One publishable camera stream as its OWNING PROVIDER describes it — the same
|
|
@@ -25445,6 +25712,12 @@ Object.freeze({
|
|
|
25445
25712
|
addonId: null,
|
|
25446
25713
|
access: "delete"
|
|
25447
25714
|
},
|
|
25715
|
+
"pipelineAnalytics.deleteDeviceEvents": {
|
|
25716
|
+
capName: "pipeline-analytics",
|
|
25717
|
+
capScope: "device",
|
|
25718
|
+
addonId: null,
|
|
25719
|
+
access: "delete"
|
|
25720
|
+
},
|
|
25448
25721
|
"pipelineAnalytics.deleteTracks": {
|
|
25449
25722
|
capName: "pipeline-analytics",
|
|
25450
25723
|
capScope: "device",
|
|
@@ -25475,6 +25748,12 @@ Object.freeze({
|
|
|
25475
25748
|
addonId: null,
|
|
25476
25749
|
access: "view"
|
|
25477
25750
|
},
|
|
25751
|
+
"pipelineAnalytics.getEventStoreFootprint": {
|
|
25752
|
+
capName: "pipeline-analytics",
|
|
25753
|
+
capScope: "device",
|
|
25754
|
+
addonId: null,
|
|
25755
|
+
access: "view"
|
|
25756
|
+
},
|
|
25478
25757
|
"pipelineAnalytics.getKeyEvents": {
|
|
25479
25758
|
capName: "pipeline-analytics",
|
|
25480
25759
|
capScope: "device",
|
|
@@ -25517,6 +25796,12 @@ Object.freeze({
|
|
|
25517
25796
|
addonId: null,
|
|
25518
25797
|
access: "view"
|
|
25519
25798
|
},
|
|
25799
|
+
"pipelineAnalytics.listOpsLog": {
|
|
25800
|
+
capName: "pipeline-analytics",
|
|
25801
|
+
capScope: "device",
|
|
25802
|
+
addonId: null,
|
|
25803
|
+
access: "view"
|
|
25804
|
+
},
|
|
25520
25805
|
"pipelineAnalytics.listRecentTracks": {
|
|
25521
25806
|
capName: "pipeline-analytics",
|
|
25522
25807
|
capScope: "device",
|
|
@@ -25529,6 +25814,12 @@ Object.freeze({
|
|
|
25529
25814
|
addonId: null,
|
|
25530
25815
|
access: "view"
|
|
25531
25816
|
},
|
|
25817
|
+
"pipelineAnalytics.pruneEvents": {
|
|
25818
|
+
capName: "pipeline-analytics",
|
|
25819
|
+
capScope: "device",
|
|
25820
|
+
addonId: null,
|
|
25821
|
+
access: "create"
|
|
25822
|
+
},
|
|
25532
25823
|
"pipelineAnalytics.pruneEventsBefore": {
|
|
25533
25824
|
capName: "pipeline-analytics",
|
|
25534
25825
|
capScope: "device",
|
|
@@ -26291,6 +26582,12 @@ Object.freeze({
|
|
|
26291
26582
|
addonId: null,
|
|
26292
26583
|
access: "create"
|
|
26293
26584
|
},
|
|
26585
|
+
"recording.deleteFootprint": {
|
|
26586
|
+
capName: "recording",
|
|
26587
|
+
capScope: "system",
|
|
26588
|
+
addonId: null,
|
|
26589
|
+
access: "delete"
|
|
26590
|
+
},
|
|
26294
26591
|
"recording.getAvailability": {
|
|
26295
26592
|
capName: "recording",
|
|
26296
26593
|
capScope: "system",
|
|
@@ -26321,6 +26618,12 @@ Object.freeze({
|
|
|
26321
26618
|
addonId: null,
|
|
26322
26619
|
access: "view"
|
|
26323
26620
|
},
|
|
26621
|
+
"recording.listOpsLog": {
|
|
26622
|
+
capName: "recording",
|
|
26623
|
+
capScope: "system",
|
|
26624
|
+
addonId: null,
|
|
26625
|
+
access: "view"
|
|
26626
|
+
},
|
|
26324
26627
|
"recording.locateSegment": {
|
|
26325
26628
|
capName: "recording",
|
|
26326
26629
|
capScope: "system",
|
|
@@ -26351,6 +26654,42 @@ Object.freeze({
|
|
|
26351
26654
|
addonId: null,
|
|
26352
26655
|
access: "create"
|
|
26353
26656
|
},
|
|
26657
|
+
"recordingExport.cancelExport": {
|
|
26658
|
+
capName: "recordingExport",
|
|
26659
|
+
capScope: "system",
|
|
26660
|
+
addonId: null,
|
|
26661
|
+
access: "create"
|
|
26662
|
+
},
|
|
26663
|
+
"recordingExport.createExport": {
|
|
26664
|
+
capName: "recordingExport",
|
|
26665
|
+
capScope: "system",
|
|
26666
|
+
addonId: null,
|
|
26667
|
+
access: "create"
|
|
26668
|
+
},
|
|
26669
|
+
"recordingExport.deleteExport": {
|
|
26670
|
+
capName: "recordingExport",
|
|
26671
|
+
capScope: "system",
|
|
26672
|
+
addonId: null,
|
|
26673
|
+
access: "delete"
|
|
26674
|
+
},
|
|
26675
|
+
"recordingExport.getDownloadUrl": {
|
|
26676
|
+
capName: "recordingExport",
|
|
26677
|
+
capScope: "system",
|
|
26678
|
+
addonId: null,
|
|
26679
|
+
access: "view"
|
|
26680
|
+
},
|
|
26681
|
+
"recordingExport.getExport": {
|
|
26682
|
+
capName: "recordingExport",
|
|
26683
|
+
capScope: "system",
|
|
26684
|
+
addonId: null,
|
|
26685
|
+
access: "view"
|
|
26686
|
+
},
|
|
26687
|
+
"recordingExport.listExports": {
|
|
26688
|
+
capName: "recordingExport",
|
|
26689
|
+
capScope: "system",
|
|
26690
|
+
addonId: null,
|
|
26691
|
+
access: "view"
|
|
26692
|
+
},
|
|
26354
26693
|
"sceneMonitor.captureReference": {
|
|
26355
26694
|
capName: "scene-monitor",
|
|
26356
26695
|
capScope: "device",
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@camstack/addon-provider-dreo",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.22",
|
|
4
4
|
"description": "Dreo smart-device (fan / air-circulator / purifier / heater / humidifier) device-provider addon for CamStack — wraps the @apocaliss92/nodedreo Dreo cloud client (REST + WebSocket)",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"camstack",
|