@camstack/addon-provider-rtsp 1.1.25 → 1.1.27
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
|
@@ -23,7 +23,7 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
|
|
|
23
23
|
//#endregion
|
|
24
24
|
let node_net = require("node:net");
|
|
25
25
|
node_net = __toESM(node_net);
|
|
26
|
-
//#region ../types/dist/event-category-
|
|
26
|
+
//#region ../types/dist/event-category-D4HJq7Mw.mjs
|
|
27
27
|
var EventCategory = /* @__PURE__ */ function(EventCategory) {
|
|
28
28
|
EventCategory["SystemBoot"] = "system.boot";
|
|
29
29
|
EventCategory["SystemAddonsReady"] = "system.addons-ready";
|
|
@@ -176,6 +176,11 @@ var EventCategory = /* @__PURE__ */ function(EventCategory) {
|
|
|
176
176
|
/** Runner-sampled scrub thumbnail (~1/5 s/camera). Telemetry (D8): a lost
|
|
177
177
|
* thumb is a scrub gap the recorder's keyframe backfill covers. */
|
|
178
178
|
EventCategory["RecordingThumbSampled"] = "recording.thumb-sampled";
|
|
179
|
+
/** Export render progress (0–100). Telemetry (D8): a lost tick is a stale
|
|
180
|
+
* progress bar the client reconciles via `recordingExport.getExport`. */
|
|
181
|
+
EventCategory["RecordingExportProgress"] = "recording.export.progress";
|
|
182
|
+
EventCategory["RecordingExportCompleted"] = "recording.export.completed";
|
|
183
|
+
EventCategory["RecordingExportFailed"] = "recording.export.failed";
|
|
179
184
|
EventCategory["DetectionEvent"] = "detection.event";
|
|
180
185
|
EventCategory["SessionTrackNew"] = "session.track.new";
|
|
181
186
|
EventCategory["SessionTrackExpired"] = "session.track.expired";
|
|
@@ -465,6 +470,25 @@ var EventCategory = /* @__PURE__ */ function(EventCategory) {
|
|
|
465
470
|
*/
|
|
466
471
|
EventCategory["PipelineAnalyticsStationaryChanged"] = "pipeline-analytics.stationary-changed";
|
|
467
472
|
/**
|
|
473
|
+
* Fired by `addon-post-analysis` when a package-drop is confirmed inside
|
|
474
|
+
* a package zone — a newly-appeared stationary object of a package class
|
|
475
|
+
* that cleared the class / zone / dwell / size gates. Payload:
|
|
476
|
+
* `PipelineAnalyticsPackageDeliveredPayload` carrying `{ deviceId,
|
|
477
|
+
* entryId, className, zoneIds, keyFrameMediaKey?, bbox, timestamp }`.
|
|
478
|
+
* Telemetry (D8): the durable record is the `package-events` store row;
|
|
479
|
+
* this bus topic drives notifier rules + live UI. See
|
|
480
|
+
* docs/superpowers/specs/2026-07-17-package-zones-design.md §5.1.
|
|
481
|
+
*/
|
|
482
|
+
EventCategory["PipelineAnalyticsPackageDelivered"] = "pipeline-analytics.package-delivered";
|
|
483
|
+
/**
|
|
484
|
+
* Fired by `addon-post-analysis` when a previously-delivered package
|
|
485
|
+
* leaves its zone (the stationary entry departed — moved or swept).
|
|
486
|
+
* Payload: `PipelineAnalyticsPackagePickedUpPayload` carrying
|
|
487
|
+
* `{ deviceId, entryId, deliveredEventId, className, timestamp }`.
|
|
488
|
+
* Telemetry (D8). See package-zones-design §5.2.
|
|
489
|
+
*/
|
|
490
|
+
EventCategory["PipelineAnalyticsPackagePickedUp"] = "pipeline-analytics.package-picked-up";
|
|
491
|
+
/**
|
|
468
492
|
* Fired by `addon-post-analysis` whenever a gallery face row changes:
|
|
469
493
|
* `kind:'buffered'` a new detected face was persisted, `'assigned'` /
|
|
470
494
|
* `'unassigned'` its identity link changed, `'deleted'` the row was
|
|
@@ -5217,6 +5241,25 @@ function preprocess(fn, schema) {
|
|
|
5217
5241
|
out: schema
|
|
5218
5242
|
});
|
|
5219
5243
|
}
|
|
5244
|
+
//#endregion
|
|
5245
|
+
//#region ../../node_modules/zod/v4/classic/compat.js
|
|
5246
|
+
/** @deprecated Use the raw string literal codes instead, e.g. "invalid_type". */
|
|
5247
|
+
var ZodIssueCode = {
|
|
5248
|
+
invalid_type: "invalid_type",
|
|
5249
|
+
too_big: "too_big",
|
|
5250
|
+
too_small: "too_small",
|
|
5251
|
+
invalid_format: "invalid_format",
|
|
5252
|
+
not_multiple_of: "not_multiple_of",
|
|
5253
|
+
unrecognized_keys: "unrecognized_keys",
|
|
5254
|
+
invalid_union: "invalid_union",
|
|
5255
|
+
invalid_key: "invalid_key",
|
|
5256
|
+
invalid_element: "invalid_element",
|
|
5257
|
+
invalid_value: "invalid_value",
|
|
5258
|
+
custom: "custom"
|
|
5259
|
+
};
|
|
5260
|
+
/** @deprecated Do not use. Stub definition, only included for zod-to-json-schema compatibility. */
|
|
5261
|
+
var ZodFirstPartyTypeKind;
|
|
5262
|
+
ZodFirstPartyTypeKind || (ZodFirstPartyTypeKind = {});
|
|
5220
5263
|
Object.fromEntries([
|
|
5221
5264
|
{
|
|
5222
5265
|
id: "overview",
|
|
@@ -7327,6 +7370,62 @@ var RecordingConfigSchema = object({
|
|
|
7327
7370
|
scrubThumbnails: ScrubThumbnailPresetSchema.optional()
|
|
7328
7371
|
});
|
|
7329
7372
|
/**
|
|
7373
|
+
* Ops-log — the durable, append-only operations audit shared by the
|
|
7374
|
+
* recordings and events management surfaces.
|
|
7375
|
+
*
|
|
7376
|
+
* ONE row shape is reused for both domains so a single "Activity" view can
|
|
7377
|
+
* merge the recorder's DurableState ring (recordings ops-log) and the
|
|
7378
|
+
* pipeline-analytics SQLite collection (events ops-log). Each row records a
|
|
7379
|
+
* management operation, WHY it ran (reason), and its measurable effect
|
|
7380
|
+
* (itemsAffected + bytesReclaimed). Writes are best-effort — a failed log must
|
|
7381
|
+
* never fail the operation it records.
|
|
7382
|
+
*/
|
|
7383
|
+
/** Which management domain the operation belongs to. */
|
|
7384
|
+
var OpsLogDomainSchema = _enum(["recording", "events"]);
|
|
7385
|
+
/** The kind of management operation performed. */
|
|
7386
|
+
var OpsLogOpSchema = _enum([
|
|
7387
|
+
"prune",
|
|
7388
|
+
"manual-delete",
|
|
7389
|
+
"rescan",
|
|
7390
|
+
"retention-run"
|
|
7391
|
+
]);
|
|
7392
|
+
/** Why the operation ran. */
|
|
7393
|
+
var OpsLogReasonSchema = _enum([
|
|
7394
|
+
"retention",
|
|
7395
|
+
"quota",
|
|
7396
|
+
"manual",
|
|
7397
|
+
"operator"
|
|
7398
|
+
]);
|
|
7399
|
+
/** One audit row, shared verbatim by both domains. */
|
|
7400
|
+
var OpsLogEntrySchema = object({
|
|
7401
|
+
/** Unique row id. */
|
|
7402
|
+
id: string(),
|
|
7403
|
+
/** Epoch ms the operation completed. */
|
|
7404
|
+
at: number(),
|
|
7405
|
+
domain: OpsLogDomainSchema,
|
|
7406
|
+
op: OpsLogOpSchema,
|
|
7407
|
+
reason: OpsLogReasonSchema,
|
|
7408
|
+
/** The camera the op targeted; null for a cluster/global op. */
|
|
7409
|
+
deviceId: number().nullable(),
|
|
7410
|
+
/** Node that performed the op (the log carries nodeId — no cross-node aggregation). */
|
|
7411
|
+
nodeId: string(),
|
|
7412
|
+
/** Buckets / rows deleted (op-specific unit). */
|
|
7413
|
+
itemsAffected: number(),
|
|
7414
|
+
/** Bytes reclaimed by the op (0 when not measurable). */
|
|
7415
|
+
bytesReclaimed: number(),
|
|
7416
|
+
/** Free-text detail (e.g. "floor moved to <ts>"); null when none. */
|
|
7417
|
+
detail: string().nullable(),
|
|
7418
|
+
/** Who/what triggered the op. */
|
|
7419
|
+
actor: string()
|
|
7420
|
+
});
|
|
7421
|
+
/** Shared query input for the per-domain `listOpsLog` cap methods. */
|
|
7422
|
+
var OpsLogQueryInputSchema = object({
|
|
7423
|
+
/** Restrict to a single camera; omit for every row. */
|
|
7424
|
+
deviceId: number().optional(),
|
|
7425
|
+
/** Max rows returned, newest-first. */
|
|
7426
|
+
limit: number().int().min(1).max(1e3).optional()
|
|
7427
|
+
});
|
|
7428
|
+
/**
|
|
7330
7429
|
* `StorageLocationType` — an addon-declared id that identifies the *kind* of
|
|
7331
7430
|
* storage a location serves. Defined here (not in `capabilities/storage.cap.ts`)
|
|
7332
7431
|
* so the persisted record schema and the consumer-facing cap can both consume it
|
|
@@ -14780,7 +14879,11 @@ array(ZoneRuleSchema).readonly();
|
|
|
14780
14879
|
* Extend the enum here when a new gating consumer comes online (audio
|
|
14781
14880
|
* gating, alert filtering, …) — no other surface needs to change.
|
|
14782
14881
|
*/
|
|
14783
|
-
var ZoneRuleStageEnum = _enum([
|
|
14882
|
+
var ZoneRuleStageEnum = _enum([
|
|
14883
|
+
"motion",
|
|
14884
|
+
"detection",
|
|
14885
|
+
"package"
|
|
14886
|
+
]);
|
|
14784
14887
|
/**
|
|
14785
14888
|
* Runtime registry: cap-property-name → cap definition. `BaseDevice`'s
|
|
14786
14889
|
* `state` getter looks up the cap definition here to construct a
|
|
@@ -14874,16 +14977,25 @@ var DEVICE_LOCAL_STATE_CAPS = {
|
|
|
14874
14977
|
})
|
|
14875
14978
|
},
|
|
14876
14979
|
/**
|
|
14877
|
-
* Runtime-state slice —
|
|
14980
|
+
* Runtime-state slice — every stage mirrored together so consumers
|
|
14878
14981
|
* see one reactive handle (`device.state.zoneRules.value`) instead
|
|
14879
|
-
* of
|
|
14880
|
-
* `{motion, detection}` shape, so subscribers always get the
|
|
14982
|
+
* of one per stage. Bulk-replace mutations on any stage write the full
|
|
14983
|
+
* `{motion, detection, package}` shape, so subscribers always get the
|
|
14881
14984
|
* complete current set. Consumers that only care about one stage
|
|
14882
14985
|
* just read the matching property.
|
|
14986
|
+
*
|
|
14987
|
+
* `package` backs the package-drop detector — a package zone is a
|
|
14988
|
+
* `ZoneRule` on the `'package'` stage referencing drawn polygons
|
|
14989
|
+
* (see docs/superpowers/specs/2026-07-17-package-zones-design.md §3.1).
|
|
14990
|
+
* The orchestrator provider writes this stage as a first-class slice
|
|
14991
|
+
* (Phase 4): every mutation mirrors the full `{motion, detection,
|
|
14992
|
+
* package}` shape, so consumers read the current package rules directly
|
|
14993
|
+
* off `device.state.zoneRules.value.package`.
|
|
14883
14994
|
*/
|
|
14884
14995
|
runtimeState: object({
|
|
14885
14996
|
motion: array(ZoneRuleSchema).readonly(),
|
|
14886
|
-
detection: array(ZoneRuleSchema).readonly()
|
|
14997
|
+
detection: array(ZoneRuleSchema).readonly(),
|
|
14998
|
+
package: array(ZoneRuleSchema).readonly()
|
|
14887
14999
|
})
|
|
14888
15000
|
},
|
|
14889
15001
|
zones: zonesCapability
|
|
@@ -18845,6 +18957,7 @@ var EventKindIconSchema = _enum([
|
|
|
18845
18957
|
"smoke",
|
|
18846
18958
|
"water",
|
|
18847
18959
|
"button",
|
|
18960
|
+
"package",
|
|
18848
18961
|
"generic"
|
|
18849
18962
|
]);
|
|
18850
18963
|
var EventKindCategorySchema = _enum([
|
|
@@ -18852,7 +18965,8 @@ var EventKindCategorySchema = _enum([
|
|
|
18852
18965
|
"audio",
|
|
18853
18966
|
"detection",
|
|
18854
18967
|
"sensor",
|
|
18855
|
-
"custom"
|
|
18968
|
+
"custom",
|
|
18969
|
+
"package"
|
|
18856
18970
|
]);
|
|
18857
18971
|
var EventKindDescriptorSchema = object({
|
|
18858
18972
|
/** Stable kind id (e.g. 'motion', 'person', 'contact'). */
|
|
@@ -19193,6 +19307,26 @@ var TrackCascadeCountsSchema = object({
|
|
|
19193
19307
|
/** Per-track CLIP search vectors removed (best-effort). */
|
|
19194
19308
|
embeddings: number().int()
|
|
19195
19309
|
});
|
|
19310
|
+
/** Event-store footprint for one camera. */
|
|
19311
|
+
var EventStoreDeviceFootprintSchema = object({
|
|
19312
|
+
deviceId: number(),
|
|
19313
|
+
/** Persisted event rows (motion + object + audio) for the camera. */
|
|
19314
|
+
rows: number().int(),
|
|
19315
|
+
/** Event-owned media bytes on disk for the camera. */
|
|
19316
|
+
bytes: number().int()
|
|
19317
|
+
});
|
|
19318
|
+
/** Aggregate event-store footprint: global totals + per-camera breakdown. */
|
|
19319
|
+
var EventStoreFootprintSchema = object({
|
|
19320
|
+
totalRows: number().int(),
|
|
19321
|
+
totalBytes: number().int(),
|
|
19322
|
+
devices: array(EventStoreDeviceFootprintSchema).readonly()
|
|
19323
|
+
});
|
|
19324
|
+
/** Per-kind counts returned by the event-prune / device-delete mutations. */
|
|
19325
|
+
var EventPruneCountsSchema = object({
|
|
19326
|
+
motion: number().int(),
|
|
19327
|
+
object: number().int(),
|
|
19328
|
+
audio: number().int()
|
|
19329
|
+
});
|
|
19196
19330
|
DeviceType.Camera, method(object({ deviceId: number() }), array(TrackSchema).readonly()), method(object({
|
|
19197
19331
|
deviceId: number(),
|
|
19198
19332
|
trackId: string()
|
|
@@ -19256,6 +19390,21 @@ DeviceType.Camera, method(object({ deviceId: number() }), array(TrackSchema).rea
|
|
|
19256
19390
|
}), {
|
|
19257
19391
|
kind: "mutation",
|
|
19258
19392
|
auth: "admin"
|
|
19393
|
+
}), method(object({}), EventStoreFootprintSchema, {
|
|
19394
|
+
kind: "query",
|
|
19395
|
+
auth: "admin"
|
|
19396
|
+
}), method(object({
|
|
19397
|
+
olderThanMs: number(),
|
|
19398
|
+
reason: OpsLogReasonSchema.optional()
|
|
19399
|
+
}), EventPruneCountsSchema, {
|
|
19400
|
+
kind: "mutation",
|
|
19401
|
+
auth: "admin"
|
|
19402
|
+
}), method(object({ deviceId: number() }), EventPruneCountsSchema, {
|
|
19403
|
+
kind: "mutation",
|
|
19404
|
+
auth: "admin"
|
|
19405
|
+
}), method(OpsLogQueryInputSchema, array(OpsLogEntrySchema).readonly(), {
|
|
19406
|
+
kind: "query",
|
|
19407
|
+
auth: "admin"
|
|
19259
19408
|
}), method(object({
|
|
19260
19409
|
eventId: string(),
|
|
19261
19410
|
kind: MediaFileKindEnum.optional()
|
|
@@ -22540,13 +22689,131 @@ method(object({
|
|
|
22540
22689
|
}), method(object({ deviceId: number() }), RecordingStatusSchema, {
|
|
22541
22690
|
kind: "mutation",
|
|
22542
22691
|
auth: "admin"
|
|
22543
|
-
}), method(object({
|
|
22692
|
+
}), method(object({
|
|
22693
|
+
deviceId: number(),
|
|
22694
|
+
reason: OpsLogReasonSchema.optional()
|
|
22695
|
+
}), object({
|
|
22544
22696
|
floorMs: number().nullable(),
|
|
22545
22697
|
deletedBuckets: number().int(),
|
|
22546
22698
|
reclaimedBytes: number().int()
|
|
22547
22699
|
}), {
|
|
22548
22700
|
kind: "mutation",
|
|
22549
22701
|
auth: "admin"
|
|
22702
|
+
}), method(object({
|
|
22703
|
+
deviceId: number(),
|
|
22704
|
+
fromMs: number().optional(),
|
|
22705
|
+
toMs: number().optional()
|
|
22706
|
+
}), object({
|
|
22707
|
+
deletedBuckets: number().int(),
|
|
22708
|
+
reclaimedBytes: number().int()
|
|
22709
|
+
}), {
|
|
22710
|
+
kind: "mutation",
|
|
22711
|
+
auth: "admin"
|
|
22712
|
+
}), method(OpsLogQueryInputSchema, array(OpsLogEntrySchema).readonly(), {
|
|
22713
|
+
kind: "query",
|
|
22714
|
+
auth: "admin"
|
|
22715
|
+
});
|
|
22716
|
+
/**
|
|
22717
|
+
* `recordingExport` cap — render a footage time range into a single downloadable
|
|
22718
|
+
* MP4 (regular / accelerated / decelerated / timelapse, ± audio), kept for a
|
|
22719
|
+
* bounded lifetime with a durable history, auto-expiry, and optional
|
|
22720
|
+
* delete-after-download.
|
|
22721
|
+
*
|
|
22722
|
+
* Like `recording` this is a `scope:'system', mode:'singleton'` cap: the
|
|
22723
|
+
* recorder self-gates so exactly ONE node (the designated `recordingNodeId`,
|
|
22724
|
+
* default `hub`) registers it. Device-scoped methods carry `deviceId` in their
|
|
22725
|
+
* input and dispatch to that single provider; the render runs on the node that
|
|
22726
|
+
* owns the footage (no cross-node segment transfer). Download rides the
|
|
22727
|
+
* framework addon data-plane. State persists in a DurableState blob (NOT
|
|
22728
|
+
* SQLite); history rows survive file deletion for audit.
|
|
22729
|
+
*/
|
|
22730
|
+
/** Playback-speed multiplier for the render (1 = realtime). */
|
|
22731
|
+
var ExportSpeedSchema = number().min(.25).max(32);
|
|
22732
|
+
/** Timelapse cadence — sample one source frame per `everyMs`, output at `outputFps`. */
|
|
22733
|
+
var ExportTimelapseSchema = object({
|
|
22734
|
+
everyMs: number().int().positive(),
|
|
22735
|
+
outputFps: number().int().min(1).max(60).optional()
|
|
22736
|
+
});
|
|
22737
|
+
/**
|
|
22738
|
+
* Render options. `speed` and `timelapse` are mutually exclusive. `includeAudio`
|
|
22739
|
+
* is honoured only for a realtime-ish speed (0.5–2×); timelapse is always
|
|
22740
|
+
* silent. `maxLifeMs` bounds how long the finished file is kept;
|
|
22741
|
+
* `deleteAfterDownload` removes it shortly after the first complete download.
|
|
22742
|
+
*/
|
|
22743
|
+
var ExportOptionsSchema = object({
|
|
22744
|
+
speed: ExportSpeedSchema.optional(),
|
|
22745
|
+
timelapse: ExportTimelapseSchema.optional(),
|
|
22746
|
+
includeAudio: boolean(),
|
|
22747
|
+
maxLifeMs: number().int().positive(),
|
|
22748
|
+
deleteAfterDownload: boolean(),
|
|
22749
|
+
title: string().max(200).optional()
|
|
22750
|
+
}).superRefine((v, ctx) => {
|
|
22751
|
+
if (v.speed !== void 0 && v.timelapse !== void 0) ctx.addIssue({
|
|
22752
|
+
code: ZodIssueCode.custom,
|
|
22753
|
+
message: "speed and timelapse are mutually exclusive",
|
|
22754
|
+
path: ["timelapse"]
|
|
22755
|
+
});
|
|
22756
|
+
});
|
|
22757
|
+
var ExportStateSchema = _enum([
|
|
22758
|
+
"queued",
|
|
22759
|
+
"rendering",
|
|
22760
|
+
"ready",
|
|
22761
|
+
"failed",
|
|
22762
|
+
"expired",
|
|
22763
|
+
"deleted"
|
|
22764
|
+
]);
|
|
22765
|
+
/** One export job / history row. */
|
|
22766
|
+
var ExportRecordSchema = object({
|
|
22767
|
+
id: string(),
|
|
22768
|
+
deviceId: number(),
|
|
22769
|
+
profile: string(),
|
|
22770
|
+
fromMs: number(),
|
|
22771
|
+
toMs: number(),
|
|
22772
|
+
options: ExportOptionsSchema,
|
|
22773
|
+
state: ExportStateSchema,
|
|
22774
|
+
/** 0–100 while rendering; null otherwise. */
|
|
22775
|
+
progressPct: number().nullable(),
|
|
22776
|
+
/** File size once ready; null before. */
|
|
22777
|
+
fileBytes: number().nullable(),
|
|
22778
|
+
expiresAt: number(),
|
|
22779
|
+
deleteAfterDownload: boolean(),
|
|
22780
|
+
/** Epoch of the first complete download; null until then. */
|
|
22781
|
+
downloadedAt: number().nullable(),
|
|
22782
|
+
createdAt: number(),
|
|
22783
|
+
/** User id/name that requested the export. */
|
|
22784
|
+
createdBy: string(),
|
|
22785
|
+
/** Failure reason when state is 'failed'; null otherwise. */
|
|
22786
|
+
error: string().nullable()
|
|
22787
|
+
});
|
|
22788
|
+
/** Candidate download URLs (LAN first, then operator extra hosts). */
|
|
22789
|
+
var ExportDownloadSchema = object({
|
|
22790
|
+
url: string(),
|
|
22791
|
+
endpoints: array(string())
|
|
22792
|
+
});
|
|
22793
|
+
method(object({
|
|
22794
|
+
deviceId: number(),
|
|
22795
|
+
profile: string(),
|
|
22796
|
+
fromMs: number(),
|
|
22797
|
+
toMs: number(),
|
|
22798
|
+
options: ExportOptionsSchema
|
|
22799
|
+
}), ExportRecordSchema, {
|
|
22800
|
+
kind: "mutation",
|
|
22801
|
+
auth: "protected"
|
|
22802
|
+
}), method(object({ deviceId: number().optional() }), array(ExportRecordSchema), {
|
|
22803
|
+
kind: "query",
|
|
22804
|
+
auth: "protected"
|
|
22805
|
+
}), method(object({ exportId: string() }), ExportRecordSchema, {
|
|
22806
|
+
kind: "query",
|
|
22807
|
+
auth: "protected"
|
|
22808
|
+
}), method(object({ exportId: string() }), ExportRecordSchema, {
|
|
22809
|
+
kind: "mutation",
|
|
22810
|
+
auth: "protected"
|
|
22811
|
+
}), method(object({ exportId: string() }), ExportRecordSchema, {
|
|
22812
|
+
kind: "mutation",
|
|
22813
|
+
auth: "protected"
|
|
22814
|
+
}), method(object({ exportId: string() }), ExportDownloadSchema, {
|
|
22815
|
+
kind: "query",
|
|
22816
|
+
auth: "protected"
|
|
22550
22817
|
});
|
|
22551
22818
|
/**
|
|
22552
22819
|
* One publishable camera stream as its OWNING PROVIDER describes it — the same
|
|
@@ -25579,6 +25846,12 @@ Object.freeze({
|
|
|
25579
25846
|
addonId: null,
|
|
25580
25847
|
access: "delete"
|
|
25581
25848
|
},
|
|
25849
|
+
"pipelineAnalytics.deleteDeviceEvents": {
|
|
25850
|
+
capName: "pipeline-analytics",
|
|
25851
|
+
capScope: "device",
|
|
25852
|
+
addonId: null,
|
|
25853
|
+
access: "delete"
|
|
25854
|
+
},
|
|
25582
25855
|
"pipelineAnalytics.deleteTracks": {
|
|
25583
25856
|
capName: "pipeline-analytics",
|
|
25584
25857
|
capScope: "device",
|
|
@@ -25609,6 +25882,12 @@ Object.freeze({
|
|
|
25609
25882
|
addonId: null,
|
|
25610
25883
|
access: "view"
|
|
25611
25884
|
},
|
|
25885
|
+
"pipelineAnalytics.getEventStoreFootprint": {
|
|
25886
|
+
capName: "pipeline-analytics",
|
|
25887
|
+
capScope: "device",
|
|
25888
|
+
addonId: null,
|
|
25889
|
+
access: "view"
|
|
25890
|
+
},
|
|
25612
25891
|
"pipelineAnalytics.getKeyEvents": {
|
|
25613
25892
|
capName: "pipeline-analytics",
|
|
25614
25893
|
capScope: "device",
|
|
@@ -25651,6 +25930,12 @@ Object.freeze({
|
|
|
25651
25930
|
addonId: null,
|
|
25652
25931
|
access: "view"
|
|
25653
25932
|
},
|
|
25933
|
+
"pipelineAnalytics.listOpsLog": {
|
|
25934
|
+
capName: "pipeline-analytics",
|
|
25935
|
+
capScope: "device",
|
|
25936
|
+
addonId: null,
|
|
25937
|
+
access: "view"
|
|
25938
|
+
},
|
|
25654
25939
|
"pipelineAnalytics.listRecentTracks": {
|
|
25655
25940
|
capName: "pipeline-analytics",
|
|
25656
25941
|
capScope: "device",
|
|
@@ -25663,6 +25948,12 @@ Object.freeze({
|
|
|
25663
25948
|
addonId: null,
|
|
25664
25949
|
access: "view"
|
|
25665
25950
|
},
|
|
25951
|
+
"pipelineAnalytics.pruneEvents": {
|
|
25952
|
+
capName: "pipeline-analytics",
|
|
25953
|
+
capScope: "device",
|
|
25954
|
+
addonId: null,
|
|
25955
|
+
access: "create"
|
|
25956
|
+
},
|
|
25666
25957
|
"pipelineAnalytics.pruneEventsBefore": {
|
|
25667
25958
|
capName: "pipeline-analytics",
|
|
25668
25959
|
capScope: "device",
|
|
@@ -26425,6 +26716,12 @@ Object.freeze({
|
|
|
26425
26716
|
addonId: null,
|
|
26426
26717
|
access: "create"
|
|
26427
26718
|
},
|
|
26719
|
+
"recording.deleteFootprint": {
|
|
26720
|
+
capName: "recording",
|
|
26721
|
+
capScope: "system",
|
|
26722
|
+
addonId: null,
|
|
26723
|
+
access: "delete"
|
|
26724
|
+
},
|
|
26428
26725
|
"recording.getAvailability": {
|
|
26429
26726
|
capName: "recording",
|
|
26430
26727
|
capScope: "system",
|
|
@@ -26455,6 +26752,12 @@ Object.freeze({
|
|
|
26455
26752
|
addonId: null,
|
|
26456
26753
|
access: "view"
|
|
26457
26754
|
},
|
|
26755
|
+
"recording.listOpsLog": {
|
|
26756
|
+
capName: "recording",
|
|
26757
|
+
capScope: "system",
|
|
26758
|
+
addonId: null,
|
|
26759
|
+
access: "view"
|
|
26760
|
+
},
|
|
26458
26761
|
"recording.locateSegment": {
|
|
26459
26762
|
capName: "recording",
|
|
26460
26763
|
capScope: "system",
|
|
@@ -26485,6 +26788,42 @@ Object.freeze({
|
|
|
26485
26788
|
addonId: null,
|
|
26486
26789
|
access: "create"
|
|
26487
26790
|
},
|
|
26791
|
+
"recordingExport.cancelExport": {
|
|
26792
|
+
capName: "recordingExport",
|
|
26793
|
+
capScope: "system",
|
|
26794
|
+
addonId: null,
|
|
26795
|
+
access: "create"
|
|
26796
|
+
},
|
|
26797
|
+
"recordingExport.createExport": {
|
|
26798
|
+
capName: "recordingExport",
|
|
26799
|
+
capScope: "system",
|
|
26800
|
+
addonId: null,
|
|
26801
|
+
access: "create"
|
|
26802
|
+
},
|
|
26803
|
+
"recordingExport.deleteExport": {
|
|
26804
|
+
capName: "recordingExport",
|
|
26805
|
+
capScope: "system",
|
|
26806
|
+
addonId: null,
|
|
26807
|
+
access: "delete"
|
|
26808
|
+
},
|
|
26809
|
+
"recordingExport.getDownloadUrl": {
|
|
26810
|
+
capName: "recordingExport",
|
|
26811
|
+
capScope: "system",
|
|
26812
|
+
addonId: null,
|
|
26813
|
+
access: "view"
|
|
26814
|
+
},
|
|
26815
|
+
"recordingExport.getExport": {
|
|
26816
|
+
capName: "recordingExport",
|
|
26817
|
+
capScope: "system",
|
|
26818
|
+
addonId: null,
|
|
26819
|
+
access: "view"
|
|
26820
|
+
},
|
|
26821
|
+
"recordingExport.listExports": {
|
|
26822
|
+
capName: "recordingExport",
|
|
26823
|
+
capScope: "system",
|
|
26824
|
+
addonId: null,
|
|
26825
|
+
access: "view"
|
|
26826
|
+
},
|
|
26488
26827
|
"sceneMonitor.captureReference": {
|
|
26489
26828
|
capName: "scene-monitor",
|
|
26490
26829
|
capScope: "device",
|
package/dist/addon.mjs
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import net from "node:net";
|
|
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",
|
|
@@ -7303,6 +7346,62 @@ var RecordingConfigSchema = object({
|
|
|
7303
7346
|
scrubThumbnails: ScrubThumbnailPresetSchema.optional()
|
|
7304
7347
|
});
|
|
7305
7348
|
/**
|
|
7349
|
+
* Ops-log — the durable, append-only operations audit shared by the
|
|
7350
|
+
* recordings and events management surfaces.
|
|
7351
|
+
*
|
|
7352
|
+
* ONE row shape is reused for both domains so a single "Activity" view can
|
|
7353
|
+
* merge the recorder's DurableState ring (recordings ops-log) and the
|
|
7354
|
+
* pipeline-analytics SQLite collection (events ops-log). Each row records a
|
|
7355
|
+
* management operation, WHY it ran (reason), and its measurable effect
|
|
7356
|
+
* (itemsAffected + bytesReclaimed). Writes are best-effort — a failed log must
|
|
7357
|
+
* never fail the operation it records.
|
|
7358
|
+
*/
|
|
7359
|
+
/** Which management domain the operation belongs to. */
|
|
7360
|
+
var OpsLogDomainSchema = _enum(["recording", "events"]);
|
|
7361
|
+
/** The kind of management operation performed. */
|
|
7362
|
+
var OpsLogOpSchema = _enum([
|
|
7363
|
+
"prune",
|
|
7364
|
+
"manual-delete",
|
|
7365
|
+
"rescan",
|
|
7366
|
+
"retention-run"
|
|
7367
|
+
]);
|
|
7368
|
+
/** Why the operation ran. */
|
|
7369
|
+
var OpsLogReasonSchema = _enum([
|
|
7370
|
+
"retention",
|
|
7371
|
+
"quota",
|
|
7372
|
+
"manual",
|
|
7373
|
+
"operator"
|
|
7374
|
+
]);
|
|
7375
|
+
/** One audit row, shared verbatim by both domains. */
|
|
7376
|
+
var OpsLogEntrySchema = object({
|
|
7377
|
+
/** Unique row id. */
|
|
7378
|
+
id: string(),
|
|
7379
|
+
/** Epoch ms the operation completed. */
|
|
7380
|
+
at: number(),
|
|
7381
|
+
domain: OpsLogDomainSchema,
|
|
7382
|
+
op: OpsLogOpSchema,
|
|
7383
|
+
reason: OpsLogReasonSchema,
|
|
7384
|
+
/** The camera the op targeted; null for a cluster/global op. */
|
|
7385
|
+
deviceId: number().nullable(),
|
|
7386
|
+
/** Node that performed the op (the log carries nodeId — no cross-node aggregation). */
|
|
7387
|
+
nodeId: string(),
|
|
7388
|
+
/** Buckets / rows deleted (op-specific unit). */
|
|
7389
|
+
itemsAffected: number(),
|
|
7390
|
+
/** Bytes reclaimed by the op (0 when not measurable). */
|
|
7391
|
+
bytesReclaimed: number(),
|
|
7392
|
+
/** Free-text detail (e.g. "floor moved to <ts>"); null when none. */
|
|
7393
|
+
detail: string().nullable(),
|
|
7394
|
+
/** Who/what triggered the op. */
|
|
7395
|
+
actor: string()
|
|
7396
|
+
});
|
|
7397
|
+
/** Shared query input for the per-domain `listOpsLog` cap methods. */
|
|
7398
|
+
var OpsLogQueryInputSchema = object({
|
|
7399
|
+
/** Restrict to a single camera; omit for every row. */
|
|
7400
|
+
deviceId: number().optional(),
|
|
7401
|
+
/** Max rows returned, newest-first. */
|
|
7402
|
+
limit: number().int().min(1).max(1e3).optional()
|
|
7403
|
+
});
|
|
7404
|
+
/**
|
|
7306
7405
|
* `StorageLocationType` — an addon-declared id that identifies the *kind* of
|
|
7307
7406
|
* storage a location serves. Defined here (not in `capabilities/storage.cap.ts`)
|
|
7308
7407
|
* so the persisted record schema and the consumer-facing cap can both consume it
|
|
@@ -14756,7 +14855,11 @@ array(ZoneRuleSchema).readonly();
|
|
|
14756
14855
|
* Extend the enum here when a new gating consumer comes online (audio
|
|
14757
14856
|
* gating, alert filtering, …) — no other surface needs to change.
|
|
14758
14857
|
*/
|
|
14759
|
-
var ZoneRuleStageEnum = _enum([
|
|
14858
|
+
var ZoneRuleStageEnum = _enum([
|
|
14859
|
+
"motion",
|
|
14860
|
+
"detection",
|
|
14861
|
+
"package"
|
|
14862
|
+
]);
|
|
14760
14863
|
/**
|
|
14761
14864
|
* Runtime registry: cap-property-name → cap definition. `BaseDevice`'s
|
|
14762
14865
|
* `state` getter looks up the cap definition here to construct a
|
|
@@ -14850,16 +14953,25 @@ var DEVICE_LOCAL_STATE_CAPS = {
|
|
|
14850
14953
|
})
|
|
14851
14954
|
},
|
|
14852
14955
|
/**
|
|
14853
|
-
* Runtime-state slice —
|
|
14956
|
+
* Runtime-state slice — every stage mirrored together so consumers
|
|
14854
14957
|
* see one reactive handle (`device.state.zoneRules.value`) instead
|
|
14855
|
-
* of
|
|
14856
|
-
* `{motion, detection}` shape, so subscribers always get the
|
|
14958
|
+
* of one per stage. Bulk-replace mutations on any stage write the full
|
|
14959
|
+
* `{motion, detection, package}` shape, so subscribers always get the
|
|
14857
14960
|
* complete current set. Consumers that only care about one stage
|
|
14858
14961
|
* just read the matching property.
|
|
14962
|
+
*
|
|
14963
|
+
* `package` backs the package-drop detector — a package zone is a
|
|
14964
|
+
* `ZoneRule` on the `'package'` stage referencing drawn polygons
|
|
14965
|
+
* (see docs/superpowers/specs/2026-07-17-package-zones-design.md §3.1).
|
|
14966
|
+
* The orchestrator provider writes this stage as a first-class slice
|
|
14967
|
+
* (Phase 4): every mutation mirrors the full `{motion, detection,
|
|
14968
|
+
* package}` shape, so consumers read the current package rules directly
|
|
14969
|
+
* off `device.state.zoneRules.value.package`.
|
|
14859
14970
|
*/
|
|
14860
14971
|
runtimeState: object({
|
|
14861
14972
|
motion: array(ZoneRuleSchema).readonly(),
|
|
14862
|
-
detection: array(ZoneRuleSchema).readonly()
|
|
14973
|
+
detection: array(ZoneRuleSchema).readonly(),
|
|
14974
|
+
package: array(ZoneRuleSchema).readonly()
|
|
14863
14975
|
})
|
|
14864
14976
|
},
|
|
14865
14977
|
zones: zonesCapability
|
|
@@ -18821,6 +18933,7 @@ var EventKindIconSchema = _enum([
|
|
|
18821
18933
|
"smoke",
|
|
18822
18934
|
"water",
|
|
18823
18935
|
"button",
|
|
18936
|
+
"package",
|
|
18824
18937
|
"generic"
|
|
18825
18938
|
]);
|
|
18826
18939
|
var EventKindCategorySchema = _enum([
|
|
@@ -18828,7 +18941,8 @@ var EventKindCategorySchema = _enum([
|
|
|
18828
18941
|
"audio",
|
|
18829
18942
|
"detection",
|
|
18830
18943
|
"sensor",
|
|
18831
|
-
"custom"
|
|
18944
|
+
"custom",
|
|
18945
|
+
"package"
|
|
18832
18946
|
]);
|
|
18833
18947
|
var EventKindDescriptorSchema = object({
|
|
18834
18948
|
/** Stable kind id (e.g. 'motion', 'person', 'contact'). */
|
|
@@ -19169,6 +19283,26 @@ var TrackCascadeCountsSchema = object({
|
|
|
19169
19283
|
/** Per-track CLIP search vectors removed (best-effort). */
|
|
19170
19284
|
embeddings: number().int()
|
|
19171
19285
|
});
|
|
19286
|
+
/** Event-store footprint for one camera. */
|
|
19287
|
+
var EventStoreDeviceFootprintSchema = object({
|
|
19288
|
+
deviceId: number(),
|
|
19289
|
+
/** Persisted event rows (motion + object + audio) for the camera. */
|
|
19290
|
+
rows: number().int(),
|
|
19291
|
+
/** Event-owned media bytes on disk for the camera. */
|
|
19292
|
+
bytes: number().int()
|
|
19293
|
+
});
|
|
19294
|
+
/** Aggregate event-store footprint: global totals + per-camera breakdown. */
|
|
19295
|
+
var EventStoreFootprintSchema = object({
|
|
19296
|
+
totalRows: number().int(),
|
|
19297
|
+
totalBytes: number().int(),
|
|
19298
|
+
devices: array(EventStoreDeviceFootprintSchema).readonly()
|
|
19299
|
+
});
|
|
19300
|
+
/** Per-kind counts returned by the event-prune / device-delete mutations. */
|
|
19301
|
+
var EventPruneCountsSchema = object({
|
|
19302
|
+
motion: number().int(),
|
|
19303
|
+
object: number().int(),
|
|
19304
|
+
audio: number().int()
|
|
19305
|
+
});
|
|
19172
19306
|
DeviceType.Camera, method(object({ deviceId: number() }), array(TrackSchema).readonly()), method(object({
|
|
19173
19307
|
deviceId: number(),
|
|
19174
19308
|
trackId: string()
|
|
@@ -19232,6 +19366,21 @@ DeviceType.Camera, method(object({ deviceId: number() }), array(TrackSchema).rea
|
|
|
19232
19366
|
}), {
|
|
19233
19367
|
kind: "mutation",
|
|
19234
19368
|
auth: "admin"
|
|
19369
|
+
}), method(object({}), EventStoreFootprintSchema, {
|
|
19370
|
+
kind: "query",
|
|
19371
|
+
auth: "admin"
|
|
19372
|
+
}), method(object({
|
|
19373
|
+
olderThanMs: number(),
|
|
19374
|
+
reason: OpsLogReasonSchema.optional()
|
|
19375
|
+
}), EventPruneCountsSchema, {
|
|
19376
|
+
kind: "mutation",
|
|
19377
|
+
auth: "admin"
|
|
19378
|
+
}), method(object({ deviceId: number() }), EventPruneCountsSchema, {
|
|
19379
|
+
kind: "mutation",
|
|
19380
|
+
auth: "admin"
|
|
19381
|
+
}), method(OpsLogQueryInputSchema, array(OpsLogEntrySchema).readonly(), {
|
|
19382
|
+
kind: "query",
|
|
19383
|
+
auth: "admin"
|
|
19235
19384
|
}), method(object({
|
|
19236
19385
|
eventId: string(),
|
|
19237
19386
|
kind: MediaFileKindEnum.optional()
|
|
@@ -22516,13 +22665,131 @@ method(object({
|
|
|
22516
22665
|
}), method(object({ deviceId: number() }), RecordingStatusSchema, {
|
|
22517
22666
|
kind: "mutation",
|
|
22518
22667
|
auth: "admin"
|
|
22519
|
-
}), method(object({
|
|
22668
|
+
}), method(object({
|
|
22669
|
+
deviceId: number(),
|
|
22670
|
+
reason: OpsLogReasonSchema.optional()
|
|
22671
|
+
}), object({
|
|
22520
22672
|
floorMs: number().nullable(),
|
|
22521
22673
|
deletedBuckets: number().int(),
|
|
22522
22674
|
reclaimedBytes: number().int()
|
|
22523
22675
|
}), {
|
|
22524
22676
|
kind: "mutation",
|
|
22525
22677
|
auth: "admin"
|
|
22678
|
+
}), method(object({
|
|
22679
|
+
deviceId: number(),
|
|
22680
|
+
fromMs: number().optional(),
|
|
22681
|
+
toMs: number().optional()
|
|
22682
|
+
}), object({
|
|
22683
|
+
deletedBuckets: number().int(),
|
|
22684
|
+
reclaimedBytes: number().int()
|
|
22685
|
+
}), {
|
|
22686
|
+
kind: "mutation",
|
|
22687
|
+
auth: "admin"
|
|
22688
|
+
}), method(OpsLogQueryInputSchema, array(OpsLogEntrySchema).readonly(), {
|
|
22689
|
+
kind: "query",
|
|
22690
|
+
auth: "admin"
|
|
22691
|
+
});
|
|
22692
|
+
/**
|
|
22693
|
+
* `recordingExport` cap — render a footage time range into a single downloadable
|
|
22694
|
+
* MP4 (regular / accelerated / decelerated / timelapse, ± audio), kept for a
|
|
22695
|
+
* bounded lifetime with a durable history, auto-expiry, and optional
|
|
22696
|
+
* delete-after-download.
|
|
22697
|
+
*
|
|
22698
|
+
* Like `recording` this is a `scope:'system', mode:'singleton'` cap: the
|
|
22699
|
+
* recorder self-gates so exactly ONE node (the designated `recordingNodeId`,
|
|
22700
|
+
* default `hub`) registers it. Device-scoped methods carry `deviceId` in their
|
|
22701
|
+
* input and dispatch to that single provider; the render runs on the node that
|
|
22702
|
+
* owns the footage (no cross-node segment transfer). Download rides the
|
|
22703
|
+
* framework addon data-plane. State persists in a DurableState blob (NOT
|
|
22704
|
+
* SQLite); history rows survive file deletion for audit.
|
|
22705
|
+
*/
|
|
22706
|
+
/** Playback-speed multiplier for the render (1 = realtime). */
|
|
22707
|
+
var ExportSpeedSchema = number().min(.25).max(32);
|
|
22708
|
+
/** Timelapse cadence — sample one source frame per `everyMs`, output at `outputFps`. */
|
|
22709
|
+
var ExportTimelapseSchema = object({
|
|
22710
|
+
everyMs: number().int().positive(),
|
|
22711
|
+
outputFps: number().int().min(1).max(60).optional()
|
|
22712
|
+
});
|
|
22713
|
+
/**
|
|
22714
|
+
* Render options. `speed` and `timelapse` are mutually exclusive. `includeAudio`
|
|
22715
|
+
* is honoured only for a realtime-ish speed (0.5–2×); timelapse is always
|
|
22716
|
+
* silent. `maxLifeMs` bounds how long the finished file is kept;
|
|
22717
|
+
* `deleteAfterDownload` removes it shortly after the first complete download.
|
|
22718
|
+
*/
|
|
22719
|
+
var ExportOptionsSchema = object({
|
|
22720
|
+
speed: ExportSpeedSchema.optional(),
|
|
22721
|
+
timelapse: ExportTimelapseSchema.optional(),
|
|
22722
|
+
includeAudio: boolean(),
|
|
22723
|
+
maxLifeMs: number().int().positive(),
|
|
22724
|
+
deleteAfterDownload: boolean(),
|
|
22725
|
+
title: string().max(200).optional()
|
|
22726
|
+
}).superRefine((v, ctx) => {
|
|
22727
|
+
if (v.speed !== void 0 && v.timelapse !== void 0) ctx.addIssue({
|
|
22728
|
+
code: ZodIssueCode.custom,
|
|
22729
|
+
message: "speed and timelapse are mutually exclusive",
|
|
22730
|
+
path: ["timelapse"]
|
|
22731
|
+
});
|
|
22732
|
+
});
|
|
22733
|
+
var ExportStateSchema = _enum([
|
|
22734
|
+
"queued",
|
|
22735
|
+
"rendering",
|
|
22736
|
+
"ready",
|
|
22737
|
+
"failed",
|
|
22738
|
+
"expired",
|
|
22739
|
+
"deleted"
|
|
22740
|
+
]);
|
|
22741
|
+
/** One export job / history row. */
|
|
22742
|
+
var ExportRecordSchema = object({
|
|
22743
|
+
id: string(),
|
|
22744
|
+
deviceId: number(),
|
|
22745
|
+
profile: string(),
|
|
22746
|
+
fromMs: number(),
|
|
22747
|
+
toMs: number(),
|
|
22748
|
+
options: ExportOptionsSchema,
|
|
22749
|
+
state: ExportStateSchema,
|
|
22750
|
+
/** 0–100 while rendering; null otherwise. */
|
|
22751
|
+
progressPct: number().nullable(),
|
|
22752
|
+
/** File size once ready; null before. */
|
|
22753
|
+
fileBytes: number().nullable(),
|
|
22754
|
+
expiresAt: number(),
|
|
22755
|
+
deleteAfterDownload: boolean(),
|
|
22756
|
+
/** Epoch of the first complete download; null until then. */
|
|
22757
|
+
downloadedAt: number().nullable(),
|
|
22758
|
+
createdAt: number(),
|
|
22759
|
+
/** User id/name that requested the export. */
|
|
22760
|
+
createdBy: string(),
|
|
22761
|
+
/** Failure reason when state is 'failed'; null otherwise. */
|
|
22762
|
+
error: string().nullable()
|
|
22763
|
+
});
|
|
22764
|
+
/** Candidate download URLs (LAN first, then operator extra hosts). */
|
|
22765
|
+
var ExportDownloadSchema = object({
|
|
22766
|
+
url: string(),
|
|
22767
|
+
endpoints: array(string())
|
|
22768
|
+
});
|
|
22769
|
+
method(object({
|
|
22770
|
+
deviceId: number(),
|
|
22771
|
+
profile: string(),
|
|
22772
|
+
fromMs: number(),
|
|
22773
|
+
toMs: number(),
|
|
22774
|
+
options: ExportOptionsSchema
|
|
22775
|
+
}), ExportRecordSchema, {
|
|
22776
|
+
kind: "mutation",
|
|
22777
|
+
auth: "protected"
|
|
22778
|
+
}), method(object({ deviceId: number().optional() }), array(ExportRecordSchema), {
|
|
22779
|
+
kind: "query",
|
|
22780
|
+
auth: "protected"
|
|
22781
|
+
}), method(object({ exportId: string() }), ExportRecordSchema, {
|
|
22782
|
+
kind: "query",
|
|
22783
|
+
auth: "protected"
|
|
22784
|
+
}), method(object({ exportId: string() }), ExportRecordSchema, {
|
|
22785
|
+
kind: "mutation",
|
|
22786
|
+
auth: "protected"
|
|
22787
|
+
}), method(object({ exportId: string() }), ExportRecordSchema, {
|
|
22788
|
+
kind: "mutation",
|
|
22789
|
+
auth: "protected"
|
|
22790
|
+
}), method(object({ exportId: string() }), ExportDownloadSchema, {
|
|
22791
|
+
kind: "query",
|
|
22792
|
+
auth: "protected"
|
|
22526
22793
|
});
|
|
22527
22794
|
/**
|
|
22528
22795
|
* One publishable camera stream as its OWNING PROVIDER describes it — the same
|
|
@@ -25555,6 +25822,12 @@ Object.freeze({
|
|
|
25555
25822
|
addonId: null,
|
|
25556
25823
|
access: "delete"
|
|
25557
25824
|
},
|
|
25825
|
+
"pipelineAnalytics.deleteDeviceEvents": {
|
|
25826
|
+
capName: "pipeline-analytics",
|
|
25827
|
+
capScope: "device",
|
|
25828
|
+
addonId: null,
|
|
25829
|
+
access: "delete"
|
|
25830
|
+
},
|
|
25558
25831
|
"pipelineAnalytics.deleteTracks": {
|
|
25559
25832
|
capName: "pipeline-analytics",
|
|
25560
25833
|
capScope: "device",
|
|
@@ -25585,6 +25858,12 @@ Object.freeze({
|
|
|
25585
25858
|
addonId: null,
|
|
25586
25859
|
access: "view"
|
|
25587
25860
|
},
|
|
25861
|
+
"pipelineAnalytics.getEventStoreFootprint": {
|
|
25862
|
+
capName: "pipeline-analytics",
|
|
25863
|
+
capScope: "device",
|
|
25864
|
+
addonId: null,
|
|
25865
|
+
access: "view"
|
|
25866
|
+
},
|
|
25588
25867
|
"pipelineAnalytics.getKeyEvents": {
|
|
25589
25868
|
capName: "pipeline-analytics",
|
|
25590
25869
|
capScope: "device",
|
|
@@ -25627,6 +25906,12 @@ Object.freeze({
|
|
|
25627
25906
|
addonId: null,
|
|
25628
25907
|
access: "view"
|
|
25629
25908
|
},
|
|
25909
|
+
"pipelineAnalytics.listOpsLog": {
|
|
25910
|
+
capName: "pipeline-analytics",
|
|
25911
|
+
capScope: "device",
|
|
25912
|
+
addonId: null,
|
|
25913
|
+
access: "view"
|
|
25914
|
+
},
|
|
25630
25915
|
"pipelineAnalytics.listRecentTracks": {
|
|
25631
25916
|
capName: "pipeline-analytics",
|
|
25632
25917
|
capScope: "device",
|
|
@@ -25639,6 +25924,12 @@ Object.freeze({
|
|
|
25639
25924
|
addonId: null,
|
|
25640
25925
|
access: "view"
|
|
25641
25926
|
},
|
|
25927
|
+
"pipelineAnalytics.pruneEvents": {
|
|
25928
|
+
capName: "pipeline-analytics",
|
|
25929
|
+
capScope: "device",
|
|
25930
|
+
addonId: null,
|
|
25931
|
+
access: "create"
|
|
25932
|
+
},
|
|
25642
25933
|
"pipelineAnalytics.pruneEventsBefore": {
|
|
25643
25934
|
capName: "pipeline-analytics",
|
|
25644
25935
|
capScope: "device",
|
|
@@ -26401,6 +26692,12 @@ Object.freeze({
|
|
|
26401
26692
|
addonId: null,
|
|
26402
26693
|
access: "create"
|
|
26403
26694
|
},
|
|
26695
|
+
"recording.deleteFootprint": {
|
|
26696
|
+
capName: "recording",
|
|
26697
|
+
capScope: "system",
|
|
26698
|
+
addonId: null,
|
|
26699
|
+
access: "delete"
|
|
26700
|
+
},
|
|
26404
26701
|
"recording.getAvailability": {
|
|
26405
26702
|
capName: "recording",
|
|
26406
26703
|
capScope: "system",
|
|
@@ -26431,6 +26728,12 @@ Object.freeze({
|
|
|
26431
26728
|
addonId: null,
|
|
26432
26729
|
access: "view"
|
|
26433
26730
|
},
|
|
26731
|
+
"recording.listOpsLog": {
|
|
26732
|
+
capName: "recording",
|
|
26733
|
+
capScope: "system",
|
|
26734
|
+
addonId: null,
|
|
26735
|
+
access: "view"
|
|
26736
|
+
},
|
|
26434
26737
|
"recording.locateSegment": {
|
|
26435
26738
|
capName: "recording",
|
|
26436
26739
|
capScope: "system",
|
|
@@ -26461,6 +26764,42 @@ Object.freeze({
|
|
|
26461
26764
|
addonId: null,
|
|
26462
26765
|
access: "create"
|
|
26463
26766
|
},
|
|
26767
|
+
"recordingExport.cancelExport": {
|
|
26768
|
+
capName: "recordingExport",
|
|
26769
|
+
capScope: "system",
|
|
26770
|
+
addonId: null,
|
|
26771
|
+
access: "create"
|
|
26772
|
+
},
|
|
26773
|
+
"recordingExport.createExport": {
|
|
26774
|
+
capName: "recordingExport",
|
|
26775
|
+
capScope: "system",
|
|
26776
|
+
addonId: null,
|
|
26777
|
+
access: "create"
|
|
26778
|
+
},
|
|
26779
|
+
"recordingExport.deleteExport": {
|
|
26780
|
+
capName: "recordingExport",
|
|
26781
|
+
capScope: "system",
|
|
26782
|
+
addonId: null,
|
|
26783
|
+
access: "delete"
|
|
26784
|
+
},
|
|
26785
|
+
"recordingExport.getDownloadUrl": {
|
|
26786
|
+
capName: "recordingExport",
|
|
26787
|
+
capScope: "system",
|
|
26788
|
+
addonId: null,
|
|
26789
|
+
access: "view"
|
|
26790
|
+
},
|
|
26791
|
+
"recordingExport.getExport": {
|
|
26792
|
+
capName: "recordingExport",
|
|
26793
|
+
capScope: "system",
|
|
26794
|
+
addonId: null,
|
|
26795
|
+
access: "view"
|
|
26796
|
+
},
|
|
26797
|
+
"recordingExport.listExports": {
|
|
26798
|
+
capName: "recordingExport",
|
|
26799
|
+
capScope: "system",
|
|
26800
|
+
addonId: null,
|
|
26801
|
+
access: "view"
|
|
26802
|
+
},
|
|
26464
26803
|
"sceneMonitor.captureReference": {
|
|
26465
26804
|
capName: "scene-monitor",
|
|
26466
26805
|
capScope: "device",
|