@camstack/addon-provider-rademacher 0.1.11 → 0.1.13
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/addon.js +347 -8
- package/dist/addon.mjs +347 -8
- package/package.json +1 -1
package/dist/addon.js
CHANGED
|
@@ -984,7 +984,7 @@ var Rademacher = class {
|
|
|
984
984
|
}
|
|
985
985
|
};
|
|
986
986
|
//#endregion
|
|
987
|
-
//#region ../types/dist/event-category-
|
|
987
|
+
//#region ../types/dist/event-category-D4HJq7Mw.mjs
|
|
988
988
|
var EventCategory = /* @__PURE__ */ function(EventCategory) {
|
|
989
989
|
EventCategory["SystemBoot"] = "system.boot";
|
|
990
990
|
EventCategory["SystemAddonsReady"] = "system.addons-ready";
|
|
@@ -1137,6 +1137,11 @@ var EventCategory = /* @__PURE__ */ function(EventCategory) {
|
|
|
1137
1137
|
/** Runner-sampled scrub thumbnail (~1/5 s/camera). Telemetry (D8): a lost
|
|
1138
1138
|
* thumb is a scrub gap the recorder's keyframe backfill covers. */
|
|
1139
1139
|
EventCategory["RecordingThumbSampled"] = "recording.thumb-sampled";
|
|
1140
|
+
/** Export render progress (0–100). Telemetry (D8): a lost tick is a stale
|
|
1141
|
+
* progress bar the client reconciles via `recordingExport.getExport`. */
|
|
1142
|
+
EventCategory["RecordingExportProgress"] = "recording.export.progress";
|
|
1143
|
+
EventCategory["RecordingExportCompleted"] = "recording.export.completed";
|
|
1144
|
+
EventCategory["RecordingExportFailed"] = "recording.export.failed";
|
|
1140
1145
|
EventCategory["DetectionEvent"] = "detection.event";
|
|
1141
1146
|
EventCategory["SessionTrackNew"] = "session.track.new";
|
|
1142
1147
|
EventCategory["SessionTrackExpired"] = "session.track.expired";
|
|
@@ -1426,6 +1431,25 @@ var EventCategory = /* @__PURE__ */ function(EventCategory) {
|
|
|
1426
1431
|
*/
|
|
1427
1432
|
EventCategory["PipelineAnalyticsStationaryChanged"] = "pipeline-analytics.stationary-changed";
|
|
1428
1433
|
/**
|
|
1434
|
+
* Fired by `addon-post-analysis` when a package-drop is confirmed inside
|
|
1435
|
+
* a package zone — a newly-appeared stationary object of a package class
|
|
1436
|
+
* that cleared the class / zone / dwell / size gates. Payload:
|
|
1437
|
+
* `PipelineAnalyticsPackageDeliveredPayload` carrying `{ deviceId,
|
|
1438
|
+
* entryId, className, zoneIds, keyFrameMediaKey?, bbox, timestamp }`.
|
|
1439
|
+
* Telemetry (D8): the durable record is the `package-events` store row;
|
|
1440
|
+
* this bus topic drives notifier rules + live UI. See
|
|
1441
|
+
* docs/superpowers/specs/2026-07-17-package-zones-design.md §5.1.
|
|
1442
|
+
*/
|
|
1443
|
+
EventCategory["PipelineAnalyticsPackageDelivered"] = "pipeline-analytics.package-delivered";
|
|
1444
|
+
/**
|
|
1445
|
+
* Fired by `addon-post-analysis` when a previously-delivered package
|
|
1446
|
+
* leaves its zone (the stationary entry departed — moved or swept).
|
|
1447
|
+
* Payload: `PipelineAnalyticsPackagePickedUpPayload` carrying
|
|
1448
|
+
* `{ deviceId, entryId, deliveredEventId, className, timestamp }`.
|
|
1449
|
+
* Telemetry (D8). See package-zones-design §5.2.
|
|
1450
|
+
*/
|
|
1451
|
+
EventCategory["PipelineAnalyticsPackagePickedUp"] = "pipeline-analytics.package-picked-up";
|
|
1452
|
+
/**
|
|
1429
1453
|
* Fired by `addon-post-analysis` whenever a gallery face row changes:
|
|
1430
1454
|
* `kind:'buffered'` a new detected face was persisted, `'assigned'` /
|
|
1431
1455
|
* `'unassigned'` its identity link changed, `'deleted'` the row was
|
|
@@ -6178,6 +6202,25 @@ function preprocess(fn, schema) {
|
|
|
6178
6202
|
out: schema
|
|
6179
6203
|
});
|
|
6180
6204
|
}
|
|
6205
|
+
//#endregion
|
|
6206
|
+
//#region ../../node_modules/zod/v4/classic/compat.js
|
|
6207
|
+
/** @deprecated Use the raw string literal codes instead, e.g. "invalid_type". */
|
|
6208
|
+
var ZodIssueCode = {
|
|
6209
|
+
invalid_type: "invalid_type",
|
|
6210
|
+
too_big: "too_big",
|
|
6211
|
+
too_small: "too_small",
|
|
6212
|
+
invalid_format: "invalid_format",
|
|
6213
|
+
not_multiple_of: "not_multiple_of",
|
|
6214
|
+
unrecognized_keys: "unrecognized_keys",
|
|
6215
|
+
invalid_union: "invalid_union",
|
|
6216
|
+
invalid_key: "invalid_key",
|
|
6217
|
+
invalid_element: "invalid_element",
|
|
6218
|
+
invalid_value: "invalid_value",
|
|
6219
|
+
custom: "custom"
|
|
6220
|
+
};
|
|
6221
|
+
/** @deprecated Do not use. Stub definition, only included for zod-to-json-schema compatibility. */
|
|
6222
|
+
var ZodFirstPartyTypeKind;
|
|
6223
|
+
ZodFirstPartyTypeKind || (ZodFirstPartyTypeKind = {});
|
|
6181
6224
|
Object.fromEntries([
|
|
6182
6225
|
{
|
|
6183
6226
|
id: "overview",
|
|
@@ -8300,6 +8343,62 @@ var RecordingConfigSchema = object({
|
|
|
8300
8343
|
scrubThumbnails: ScrubThumbnailPresetSchema.optional()
|
|
8301
8344
|
});
|
|
8302
8345
|
/**
|
|
8346
|
+
* Ops-log — the durable, append-only operations audit shared by the
|
|
8347
|
+
* recordings and events management surfaces.
|
|
8348
|
+
*
|
|
8349
|
+
* ONE row shape is reused for both domains so a single "Activity" view can
|
|
8350
|
+
* merge the recorder's DurableState ring (recordings ops-log) and the
|
|
8351
|
+
* pipeline-analytics SQLite collection (events ops-log). Each row records a
|
|
8352
|
+
* management operation, WHY it ran (reason), and its measurable effect
|
|
8353
|
+
* (itemsAffected + bytesReclaimed). Writes are best-effort — a failed log must
|
|
8354
|
+
* never fail the operation it records.
|
|
8355
|
+
*/
|
|
8356
|
+
/** Which management domain the operation belongs to. */
|
|
8357
|
+
var OpsLogDomainSchema = _enum(["recording", "events"]);
|
|
8358
|
+
/** The kind of management operation performed. */
|
|
8359
|
+
var OpsLogOpSchema = _enum([
|
|
8360
|
+
"prune",
|
|
8361
|
+
"manual-delete",
|
|
8362
|
+
"rescan",
|
|
8363
|
+
"retention-run"
|
|
8364
|
+
]);
|
|
8365
|
+
/** Why the operation ran. */
|
|
8366
|
+
var OpsLogReasonSchema = _enum([
|
|
8367
|
+
"retention",
|
|
8368
|
+
"quota",
|
|
8369
|
+
"manual",
|
|
8370
|
+
"operator"
|
|
8371
|
+
]);
|
|
8372
|
+
/** One audit row, shared verbatim by both domains. */
|
|
8373
|
+
var OpsLogEntrySchema = object({
|
|
8374
|
+
/** Unique row id. */
|
|
8375
|
+
id: string(),
|
|
8376
|
+
/** Epoch ms the operation completed. */
|
|
8377
|
+
at: number(),
|
|
8378
|
+
domain: OpsLogDomainSchema,
|
|
8379
|
+
op: OpsLogOpSchema,
|
|
8380
|
+
reason: OpsLogReasonSchema,
|
|
8381
|
+
/** The camera the op targeted; null for a cluster/global op. */
|
|
8382
|
+
deviceId: number().nullable(),
|
|
8383
|
+
/** Node that performed the op (the log carries nodeId — no cross-node aggregation). */
|
|
8384
|
+
nodeId: string(),
|
|
8385
|
+
/** Buckets / rows deleted (op-specific unit). */
|
|
8386
|
+
itemsAffected: number(),
|
|
8387
|
+
/** Bytes reclaimed by the op (0 when not measurable). */
|
|
8388
|
+
bytesReclaimed: number(),
|
|
8389
|
+
/** Free-text detail (e.g. "floor moved to <ts>"); null when none. */
|
|
8390
|
+
detail: string().nullable(),
|
|
8391
|
+
/** Who/what triggered the op. */
|
|
8392
|
+
actor: string()
|
|
8393
|
+
});
|
|
8394
|
+
/** Shared query input for the per-domain `listOpsLog` cap methods. */
|
|
8395
|
+
var OpsLogQueryInputSchema = object({
|
|
8396
|
+
/** Restrict to a single camera; omit for every row. */
|
|
8397
|
+
deviceId: number().optional(),
|
|
8398
|
+
/** Max rows returned, newest-first. */
|
|
8399
|
+
limit: number().int().min(1).max(1e3).optional()
|
|
8400
|
+
});
|
|
8401
|
+
/**
|
|
8303
8402
|
* `StorageLocationType` — an addon-declared id that identifies the *kind* of
|
|
8304
8403
|
* storage a location serves. Defined here (not in `capabilities/storage.cap.ts`)
|
|
8305
8404
|
* so the persisted record schema and the consumer-facing cap can both consume it
|
|
@@ -15655,7 +15754,11 @@ array(ZoneRuleSchema).readonly();
|
|
|
15655
15754
|
* Extend the enum here when a new gating consumer comes online (audio
|
|
15656
15755
|
* gating, alert filtering, …) — no other surface needs to change.
|
|
15657
15756
|
*/
|
|
15658
|
-
var ZoneRuleStageEnum = _enum([
|
|
15757
|
+
var ZoneRuleStageEnum = _enum([
|
|
15758
|
+
"motion",
|
|
15759
|
+
"detection",
|
|
15760
|
+
"package"
|
|
15761
|
+
]);
|
|
15659
15762
|
/**
|
|
15660
15763
|
* Runtime registry: cap-property-name → cap definition. `BaseDevice`'s
|
|
15661
15764
|
* `state` getter looks up the cap definition here to construct a
|
|
@@ -15749,16 +15852,25 @@ var DEVICE_LOCAL_STATE_CAPS = {
|
|
|
15749
15852
|
})
|
|
15750
15853
|
},
|
|
15751
15854
|
/**
|
|
15752
|
-
* Runtime-state slice —
|
|
15855
|
+
* Runtime-state slice — every stage mirrored together so consumers
|
|
15753
15856
|
* see one reactive handle (`device.state.zoneRules.value`) instead
|
|
15754
|
-
* of
|
|
15755
|
-
* `{motion, detection}` shape, so subscribers always get the
|
|
15857
|
+
* of one per stage. Bulk-replace mutations on any stage write the full
|
|
15858
|
+
* `{motion, detection, package}` shape, so subscribers always get the
|
|
15756
15859
|
* complete current set. Consumers that only care about one stage
|
|
15757
15860
|
* just read the matching property.
|
|
15861
|
+
*
|
|
15862
|
+
* `package` backs the package-drop detector — a package zone is a
|
|
15863
|
+
* `ZoneRule` on the `'package'` stage referencing drawn polygons
|
|
15864
|
+
* (see docs/superpowers/specs/2026-07-17-package-zones-design.md §3.1).
|
|
15865
|
+
* The orchestrator provider writes this stage as a first-class slice
|
|
15866
|
+
* (Phase 4): every mutation mirrors the full `{motion, detection,
|
|
15867
|
+
* package}` shape, so consumers read the current package rules directly
|
|
15868
|
+
* off `device.state.zoneRules.value.package`.
|
|
15758
15869
|
*/
|
|
15759
15870
|
runtimeState: object({
|
|
15760
15871
|
motion: array(ZoneRuleSchema).readonly(),
|
|
15761
|
-
detection: array(ZoneRuleSchema).readonly()
|
|
15872
|
+
detection: array(ZoneRuleSchema).readonly(),
|
|
15873
|
+
package: array(ZoneRuleSchema).readonly()
|
|
15762
15874
|
})
|
|
15763
15875
|
},
|
|
15764
15876
|
zones: zonesCapability
|
|
@@ -19720,6 +19832,7 @@ var EventKindIconSchema = _enum([
|
|
|
19720
19832
|
"smoke",
|
|
19721
19833
|
"water",
|
|
19722
19834
|
"button",
|
|
19835
|
+
"package",
|
|
19723
19836
|
"generic"
|
|
19724
19837
|
]);
|
|
19725
19838
|
var EventKindCategorySchema = _enum([
|
|
@@ -19727,7 +19840,8 @@ var EventKindCategorySchema = _enum([
|
|
|
19727
19840
|
"audio",
|
|
19728
19841
|
"detection",
|
|
19729
19842
|
"sensor",
|
|
19730
|
-
"custom"
|
|
19843
|
+
"custom",
|
|
19844
|
+
"package"
|
|
19731
19845
|
]);
|
|
19732
19846
|
var EventKindDescriptorSchema = object({
|
|
19733
19847
|
/** Stable kind id (e.g. 'motion', 'person', 'contact'). */
|
|
@@ -20068,6 +20182,26 @@ var TrackCascadeCountsSchema = object({
|
|
|
20068
20182
|
/** Per-track CLIP search vectors removed (best-effort). */
|
|
20069
20183
|
embeddings: number().int()
|
|
20070
20184
|
});
|
|
20185
|
+
/** Event-store footprint for one camera. */
|
|
20186
|
+
var EventStoreDeviceFootprintSchema = object({
|
|
20187
|
+
deviceId: number(),
|
|
20188
|
+
/** Persisted event rows (motion + object + audio) for the camera. */
|
|
20189
|
+
rows: number().int(),
|
|
20190
|
+
/** Event-owned media bytes on disk for the camera. */
|
|
20191
|
+
bytes: number().int()
|
|
20192
|
+
});
|
|
20193
|
+
/** Aggregate event-store footprint: global totals + per-camera breakdown. */
|
|
20194
|
+
var EventStoreFootprintSchema = object({
|
|
20195
|
+
totalRows: number().int(),
|
|
20196
|
+
totalBytes: number().int(),
|
|
20197
|
+
devices: array(EventStoreDeviceFootprintSchema).readonly()
|
|
20198
|
+
});
|
|
20199
|
+
/** Per-kind counts returned by the event-prune / device-delete mutations. */
|
|
20200
|
+
var EventPruneCountsSchema = object({
|
|
20201
|
+
motion: number().int(),
|
|
20202
|
+
object: number().int(),
|
|
20203
|
+
audio: number().int()
|
|
20204
|
+
});
|
|
20071
20205
|
DeviceType.Camera, method(object({ deviceId: number() }), array(TrackSchema).readonly()), method(object({
|
|
20072
20206
|
deviceId: number(),
|
|
20073
20207
|
trackId: string()
|
|
@@ -20131,6 +20265,21 @@ DeviceType.Camera, method(object({ deviceId: number() }), array(TrackSchema).rea
|
|
|
20131
20265
|
}), {
|
|
20132
20266
|
kind: "mutation",
|
|
20133
20267
|
auth: "admin"
|
|
20268
|
+
}), method(object({}), EventStoreFootprintSchema, {
|
|
20269
|
+
kind: "query",
|
|
20270
|
+
auth: "admin"
|
|
20271
|
+
}), method(object({
|
|
20272
|
+
olderThanMs: number(),
|
|
20273
|
+
reason: OpsLogReasonSchema.optional()
|
|
20274
|
+
}), EventPruneCountsSchema, {
|
|
20275
|
+
kind: "mutation",
|
|
20276
|
+
auth: "admin"
|
|
20277
|
+
}), method(object({ deviceId: number() }), EventPruneCountsSchema, {
|
|
20278
|
+
kind: "mutation",
|
|
20279
|
+
auth: "admin"
|
|
20280
|
+
}), method(OpsLogQueryInputSchema, array(OpsLogEntrySchema).readonly(), {
|
|
20281
|
+
kind: "query",
|
|
20282
|
+
auth: "admin"
|
|
20134
20283
|
}), method(object({
|
|
20135
20284
|
eventId: string(),
|
|
20136
20285
|
kind: MediaFileKindEnum.optional()
|
|
@@ -23364,13 +23513,131 @@ method(object({
|
|
|
23364
23513
|
}), method(object({ deviceId: number() }), RecordingStatusSchema, {
|
|
23365
23514
|
kind: "mutation",
|
|
23366
23515
|
auth: "admin"
|
|
23367
|
-
}), method(object({
|
|
23516
|
+
}), method(object({
|
|
23517
|
+
deviceId: number(),
|
|
23518
|
+
reason: OpsLogReasonSchema.optional()
|
|
23519
|
+
}), object({
|
|
23368
23520
|
floorMs: number().nullable(),
|
|
23369
23521
|
deletedBuckets: number().int(),
|
|
23370
23522
|
reclaimedBytes: number().int()
|
|
23371
23523
|
}), {
|
|
23372
23524
|
kind: "mutation",
|
|
23373
23525
|
auth: "admin"
|
|
23526
|
+
}), method(object({
|
|
23527
|
+
deviceId: number(),
|
|
23528
|
+
fromMs: number().optional(),
|
|
23529
|
+
toMs: number().optional()
|
|
23530
|
+
}), object({
|
|
23531
|
+
deletedBuckets: number().int(),
|
|
23532
|
+
reclaimedBytes: number().int()
|
|
23533
|
+
}), {
|
|
23534
|
+
kind: "mutation",
|
|
23535
|
+
auth: "admin"
|
|
23536
|
+
}), method(OpsLogQueryInputSchema, array(OpsLogEntrySchema).readonly(), {
|
|
23537
|
+
kind: "query",
|
|
23538
|
+
auth: "admin"
|
|
23539
|
+
});
|
|
23540
|
+
/**
|
|
23541
|
+
* `recordingExport` cap — render a footage time range into a single downloadable
|
|
23542
|
+
* MP4 (regular / accelerated / decelerated / timelapse, ± audio), kept for a
|
|
23543
|
+
* bounded lifetime with a durable history, auto-expiry, and optional
|
|
23544
|
+
* delete-after-download.
|
|
23545
|
+
*
|
|
23546
|
+
* Like `recording` this is a `scope:'system', mode:'singleton'` cap: the
|
|
23547
|
+
* recorder self-gates so exactly ONE node (the designated `recordingNodeId`,
|
|
23548
|
+
* default `hub`) registers it. Device-scoped methods carry `deviceId` in their
|
|
23549
|
+
* input and dispatch to that single provider; the render runs on the node that
|
|
23550
|
+
* owns the footage (no cross-node segment transfer). Download rides the
|
|
23551
|
+
* framework addon data-plane. State persists in a DurableState blob (NOT
|
|
23552
|
+
* SQLite); history rows survive file deletion for audit.
|
|
23553
|
+
*/
|
|
23554
|
+
/** Playback-speed multiplier for the render (1 = realtime). */
|
|
23555
|
+
var ExportSpeedSchema = number().min(.25).max(32);
|
|
23556
|
+
/** Timelapse cadence — sample one source frame per `everyMs`, output at `outputFps`. */
|
|
23557
|
+
var ExportTimelapseSchema = object({
|
|
23558
|
+
everyMs: number().int().positive(),
|
|
23559
|
+
outputFps: number().int().min(1).max(60).optional()
|
|
23560
|
+
});
|
|
23561
|
+
/**
|
|
23562
|
+
* Render options. `speed` and `timelapse` are mutually exclusive. `includeAudio`
|
|
23563
|
+
* is honoured only for a realtime-ish speed (0.5–2×); timelapse is always
|
|
23564
|
+
* silent. `maxLifeMs` bounds how long the finished file is kept;
|
|
23565
|
+
* `deleteAfterDownload` removes it shortly after the first complete download.
|
|
23566
|
+
*/
|
|
23567
|
+
var ExportOptionsSchema = object({
|
|
23568
|
+
speed: ExportSpeedSchema.optional(),
|
|
23569
|
+
timelapse: ExportTimelapseSchema.optional(),
|
|
23570
|
+
includeAudio: boolean(),
|
|
23571
|
+
maxLifeMs: number().int().positive(),
|
|
23572
|
+
deleteAfterDownload: boolean(),
|
|
23573
|
+
title: string().max(200).optional()
|
|
23574
|
+
}).superRefine((v, ctx) => {
|
|
23575
|
+
if (v.speed !== void 0 && v.timelapse !== void 0) ctx.addIssue({
|
|
23576
|
+
code: ZodIssueCode.custom,
|
|
23577
|
+
message: "speed and timelapse are mutually exclusive",
|
|
23578
|
+
path: ["timelapse"]
|
|
23579
|
+
});
|
|
23580
|
+
});
|
|
23581
|
+
var ExportStateSchema = _enum([
|
|
23582
|
+
"queued",
|
|
23583
|
+
"rendering",
|
|
23584
|
+
"ready",
|
|
23585
|
+
"failed",
|
|
23586
|
+
"expired",
|
|
23587
|
+
"deleted"
|
|
23588
|
+
]);
|
|
23589
|
+
/** One export job / history row. */
|
|
23590
|
+
var ExportRecordSchema = object({
|
|
23591
|
+
id: string(),
|
|
23592
|
+
deviceId: number(),
|
|
23593
|
+
profile: string(),
|
|
23594
|
+
fromMs: number(),
|
|
23595
|
+
toMs: number(),
|
|
23596
|
+
options: ExportOptionsSchema,
|
|
23597
|
+
state: ExportStateSchema,
|
|
23598
|
+
/** 0–100 while rendering; null otherwise. */
|
|
23599
|
+
progressPct: number().nullable(),
|
|
23600
|
+
/** File size once ready; null before. */
|
|
23601
|
+
fileBytes: number().nullable(),
|
|
23602
|
+
expiresAt: number(),
|
|
23603
|
+
deleteAfterDownload: boolean(),
|
|
23604
|
+
/** Epoch of the first complete download; null until then. */
|
|
23605
|
+
downloadedAt: number().nullable(),
|
|
23606
|
+
createdAt: number(),
|
|
23607
|
+
/** User id/name that requested the export. */
|
|
23608
|
+
createdBy: string(),
|
|
23609
|
+
/** Failure reason when state is 'failed'; null otherwise. */
|
|
23610
|
+
error: string().nullable()
|
|
23611
|
+
});
|
|
23612
|
+
/** Candidate download URLs (LAN first, then operator extra hosts). */
|
|
23613
|
+
var ExportDownloadSchema = object({
|
|
23614
|
+
url: string(),
|
|
23615
|
+
endpoints: array(string())
|
|
23616
|
+
});
|
|
23617
|
+
method(object({
|
|
23618
|
+
deviceId: number(),
|
|
23619
|
+
profile: string(),
|
|
23620
|
+
fromMs: number(),
|
|
23621
|
+
toMs: number(),
|
|
23622
|
+
options: ExportOptionsSchema
|
|
23623
|
+
}), ExportRecordSchema, {
|
|
23624
|
+
kind: "mutation",
|
|
23625
|
+
auth: "protected"
|
|
23626
|
+
}), method(object({ deviceId: number().optional() }), array(ExportRecordSchema), {
|
|
23627
|
+
kind: "query",
|
|
23628
|
+
auth: "protected"
|
|
23629
|
+
}), method(object({ exportId: string() }), ExportRecordSchema, {
|
|
23630
|
+
kind: "query",
|
|
23631
|
+
auth: "protected"
|
|
23632
|
+
}), method(object({ exportId: string() }), ExportRecordSchema, {
|
|
23633
|
+
kind: "mutation",
|
|
23634
|
+
auth: "protected"
|
|
23635
|
+
}), method(object({ exportId: string() }), ExportRecordSchema, {
|
|
23636
|
+
kind: "mutation",
|
|
23637
|
+
auth: "protected"
|
|
23638
|
+
}), method(object({ exportId: string() }), ExportDownloadSchema, {
|
|
23639
|
+
kind: "query",
|
|
23640
|
+
auth: "protected"
|
|
23374
23641
|
});
|
|
23375
23642
|
/**
|
|
23376
23643
|
* One publishable camera stream as its OWNING PROVIDER describes it — the same
|
|
@@ -26390,6 +26657,12 @@ Object.freeze({
|
|
|
26390
26657
|
addonId: null,
|
|
26391
26658
|
access: "delete"
|
|
26392
26659
|
},
|
|
26660
|
+
"pipelineAnalytics.deleteDeviceEvents": {
|
|
26661
|
+
capName: "pipeline-analytics",
|
|
26662
|
+
capScope: "device",
|
|
26663
|
+
addonId: null,
|
|
26664
|
+
access: "delete"
|
|
26665
|
+
},
|
|
26393
26666
|
"pipelineAnalytics.deleteTracks": {
|
|
26394
26667
|
capName: "pipeline-analytics",
|
|
26395
26668
|
capScope: "device",
|
|
@@ -26420,6 +26693,12 @@ Object.freeze({
|
|
|
26420
26693
|
addonId: null,
|
|
26421
26694
|
access: "view"
|
|
26422
26695
|
},
|
|
26696
|
+
"pipelineAnalytics.getEventStoreFootprint": {
|
|
26697
|
+
capName: "pipeline-analytics",
|
|
26698
|
+
capScope: "device",
|
|
26699
|
+
addonId: null,
|
|
26700
|
+
access: "view"
|
|
26701
|
+
},
|
|
26423
26702
|
"pipelineAnalytics.getKeyEvents": {
|
|
26424
26703
|
capName: "pipeline-analytics",
|
|
26425
26704
|
capScope: "device",
|
|
@@ -26462,6 +26741,12 @@ Object.freeze({
|
|
|
26462
26741
|
addonId: null,
|
|
26463
26742
|
access: "view"
|
|
26464
26743
|
},
|
|
26744
|
+
"pipelineAnalytics.listOpsLog": {
|
|
26745
|
+
capName: "pipeline-analytics",
|
|
26746
|
+
capScope: "device",
|
|
26747
|
+
addonId: null,
|
|
26748
|
+
access: "view"
|
|
26749
|
+
},
|
|
26465
26750
|
"pipelineAnalytics.listRecentTracks": {
|
|
26466
26751
|
capName: "pipeline-analytics",
|
|
26467
26752
|
capScope: "device",
|
|
@@ -26474,6 +26759,12 @@ Object.freeze({
|
|
|
26474
26759
|
addonId: null,
|
|
26475
26760
|
access: "view"
|
|
26476
26761
|
},
|
|
26762
|
+
"pipelineAnalytics.pruneEvents": {
|
|
26763
|
+
capName: "pipeline-analytics",
|
|
26764
|
+
capScope: "device",
|
|
26765
|
+
addonId: null,
|
|
26766
|
+
access: "create"
|
|
26767
|
+
},
|
|
26477
26768
|
"pipelineAnalytics.pruneEventsBefore": {
|
|
26478
26769
|
capName: "pipeline-analytics",
|
|
26479
26770
|
capScope: "device",
|
|
@@ -27236,6 +27527,12 @@ Object.freeze({
|
|
|
27236
27527
|
addonId: null,
|
|
27237
27528
|
access: "create"
|
|
27238
27529
|
},
|
|
27530
|
+
"recording.deleteFootprint": {
|
|
27531
|
+
capName: "recording",
|
|
27532
|
+
capScope: "system",
|
|
27533
|
+
addonId: null,
|
|
27534
|
+
access: "delete"
|
|
27535
|
+
},
|
|
27239
27536
|
"recording.getAvailability": {
|
|
27240
27537
|
capName: "recording",
|
|
27241
27538
|
capScope: "system",
|
|
@@ -27266,6 +27563,12 @@ Object.freeze({
|
|
|
27266
27563
|
addonId: null,
|
|
27267
27564
|
access: "view"
|
|
27268
27565
|
},
|
|
27566
|
+
"recording.listOpsLog": {
|
|
27567
|
+
capName: "recording",
|
|
27568
|
+
capScope: "system",
|
|
27569
|
+
addonId: null,
|
|
27570
|
+
access: "view"
|
|
27571
|
+
},
|
|
27269
27572
|
"recording.locateSegment": {
|
|
27270
27573
|
capName: "recording",
|
|
27271
27574
|
capScope: "system",
|
|
@@ -27296,6 +27599,42 @@ Object.freeze({
|
|
|
27296
27599
|
addonId: null,
|
|
27297
27600
|
access: "create"
|
|
27298
27601
|
},
|
|
27602
|
+
"recordingExport.cancelExport": {
|
|
27603
|
+
capName: "recordingExport",
|
|
27604
|
+
capScope: "system",
|
|
27605
|
+
addonId: null,
|
|
27606
|
+
access: "create"
|
|
27607
|
+
},
|
|
27608
|
+
"recordingExport.createExport": {
|
|
27609
|
+
capName: "recordingExport",
|
|
27610
|
+
capScope: "system",
|
|
27611
|
+
addonId: null,
|
|
27612
|
+
access: "create"
|
|
27613
|
+
},
|
|
27614
|
+
"recordingExport.deleteExport": {
|
|
27615
|
+
capName: "recordingExport",
|
|
27616
|
+
capScope: "system",
|
|
27617
|
+
addonId: null,
|
|
27618
|
+
access: "delete"
|
|
27619
|
+
},
|
|
27620
|
+
"recordingExport.getDownloadUrl": {
|
|
27621
|
+
capName: "recordingExport",
|
|
27622
|
+
capScope: "system",
|
|
27623
|
+
addonId: null,
|
|
27624
|
+
access: "view"
|
|
27625
|
+
},
|
|
27626
|
+
"recordingExport.getExport": {
|
|
27627
|
+
capName: "recordingExport",
|
|
27628
|
+
capScope: "system",
|
|
27629
|
+
addonId: null,
|
|
27630
|
+
access: "view"
|
|
27631
|
+
},
|
|
27632
|
+
"recordingExport.listExports": {
|
|
27633
|
+
capName: "recordingExport",
|
|
27634
|
+
capScope: "system",
|
|
27635
|
+
addonId: null,
|
|
27636
|
+
access: "view"
|
|
27637
|
+
},
|
|
27299
27638
|
"sceneMonitor.captureReference": {
|
|
27300
27639
|
capName: "scene-monitor",
|
|
27301
27640
|
capScope: "device",
|
package/dist/addon.mjs
CHANGED
|
@@ -983,7 +983,7 @@ var Rademacher = class {
|
|
|
983
983
|
}
|
|
984
984
|
};
|
|
985
985
|
//#endregion
|
|
986
|
-
//#region ../types/dist/event-category-
|
|
986
|
+
//#region ../types/dist/event-category-D4HJq7Mw.mjs
|
|
987
987
|
var EventCategory = /* @__PURE__ */ function(EventCategory) {
|
|
988
988
|
EventCategory["SystemBoot"] = "system.boot";
|
|
989
989
|
EventCategory["SystemAddonsReady"] = "system.addons-ready";
|
|
@@ -1136,6 +1136,11 @@ var EventCategory = /* @__PURE__ */ function(EventCategory) {
|
|
|
1136
1136
|
/** Runner-sampled scrub thumbnail (~1/5 s/camera). Telemetry (D8): a lost
|
|
1137
1137
|
* thumb is a scrub gap the recorder's keyframe backfill covers. */
|
|
1138
1138
|
EventCategory["RecordingThumbSampled"] = "recording.thumb-sampled";
|
|
1139
|
+
/** Export render progress (0–100). Telemetry (D8): a lost tick is a stale
|
|
1140
|
+
* progress bar the client reconciles via `recordingExport.getExport`. */
|
|
1141
|
+
EventCategory["RecordingExportProgress"] = "recording.export.progress";
|
|
1142
|
+
EventCategory["RecordingExportCompleted"] = "recording.export.completed";
|
|
1143
|
+
EventCategory["RecordingExportFailed"] = "recording.export.failed";
|
|
1139
1144
|
EventCategory["DetectionEvent"] = "detection.event";
|
|
1140
1145
|
EventCategory["SessionTrackNew"] = "session.track.new";
|
|
1141
1146
|
EventCategory["SessionTrackExpired"] = "session.track.expired";
|
|
@@ -1425,6 +1430,25 @@ var EventCategory = /* @__PURE__ */ function(EventCategory) {
|
|
|
1425
1430
|
*/
|
|
1426
1431
|
EventCategory["PipelineAnalyticsStationaryChanged"] = "pipeline-analytics.stationary-changed";
|
|
1427
1432
|
/**
|
|
1433
|
+
* Fired by `addon-post-analysis` when a package-drop is confirmed inside
|
|
1434
|
+
* a package zone — a newly-appeared stationary object of a package class
|
|
1435
|
+
* that cleared the class / zone / dwell / size gates. Payload:
|
|
1436
|
+
* `PipelineAnalyticsPackageDeliveredPayload` carrying `{ deviceId,
|
|
1437
|
+
* entryId, className, zoneIds, keyFrameMediaKey?, bbox, timestamp }`.
|
|
1438
|
+
* Telemetry (D8): the durable record is the `package-events` store row;
|
|
1439
|
+
* this bus topic drives notifier rules + live UI. See
|
|
1440
|
+
* docs/superpowers/specs/2026-07-17-package-zones-design.md §5.1.
|
|
1441
|
+
*/
|
|
1442
|
+
EventCategory["PipelineAnalyticsPackageDelivered"] = "pipeline-analytics.package-delivered";
|
|
1443
|
+
/**
|
|
1444
|
+
* Fired by `addon-post-analysis` when a previously-delivered package
|
|
1445
|
+
* leaves its zone (the stationary entry departed — moved or swept).
|
|
1446
|
+
* Payload: `PipelineAnalyticsPackagePickedUpPayload` carrying
|
|
1447
|
+
* `{ deviceId, entryId, deliveredEventId, className, timestamp }`.
|
|
1448
|
+
* Telemetry (D8). See package-zones-design §5.2.
|
|
1449
|
+
*/
|
|
1450
|
+
EventCategory["PipelineAnalyticsPackagePickedUp"] = "pipeline-analytics.package-picked-up";
|
|
1451
|
+
/**
|
|
1428
1452
|
* Fired by `addon-post-analysis` whenever a gallery face row changes:
|
|
1429
1453
|
* `kind:'buffered'` a new detected face was persisted, `'assigned'` /
|
|
1430
1454
|
* `'unassigned'` its identity link changed, `'deleted'` the row was
|
|
@@ -6177,6 +6201,25 @@ function preprocess(fn, schema) {
|
|
|
6177
6201
|
out: schema
|
|
6178
6202
|
});
|
|
6179
6203
|
}
|
|
6204
|
+
//#endregion
|
|
6205
|
+
//#region ../../node_modules/zod/v4/classic/compat.js
|
|
6206
|
+
/** @deprecated Use the raw string literal codes instead, e.g. "invalid_type". */
|
|
6207
|
+
var ZodIssueCode = {
|
|
6208
|
+
invalid_type: "invalid_type",
|
|
6209
|
+
too_big: "too_big",
|
|
6210
|
+
too_small: "too_small",
|
|
6211
|
+
invalid_format: "invalid_format",
|
|
6212
|
+
not_multiple_of: "not_multiple_of",
|
|
6213
|
+
unrecognized_keys: "unrecognized_keys",
|
|
6214
|
+
invalid_union: "invalid_union",
|
|
6215
|
+
invalid_key: "invalid_key",
|
|
6216
|
+
invalid_element: "invalid_element",
|
|
6217
|
+
invalid_value: "invalid_value",
|
|
6218
|
+
custom: "custom"
|
|
6219
|
+
};
|
|
6220
|
+
/** @deprecated Do not use. Stub definition, only included for zod-to-json-schema compatibility. */
|
|
6221
|
+
var ZodFirstPartyTypeKind;
|
|
6222
|
+
ZodFirstPartyTypeKind || (ZodFirstPartyTypeKind = {});
|
|
6180
6223
|
Object.fromEntries([
|
|
6181
6224
|
{
|
|
6182
6225
|
id: "overview",
|
|
@@ -8299,6 +8342,62 @@ var RecordingConfigSchema = object({
|
|
|
8299
8342
|
scrubThumbnails: ScrubThumbnailPresetSchema.optional()
|
|
8300
8343
|
});
|
|
8301
8344
|
/**
|
|
8345
|
+
* Ops-log — the durable, append-only operations audit shared by the
|
|
8346
|
+
* recordings and events management surfaces.
|
|
8347
|
+
*
|
|
8348
|
+
* ONE row shape is reused for both domains so a single "Activity" view can
|
|
8349
|
+
* merge the recorder's DurableState ring (recordings ops-log) and the
|
|
8350
|
+
* pipeline-analytics SQLite collection (events ops-log). Each row records a
|
|
8351
|
+
* management operation, WHY it ran (reason), and its measurable effect
|
|
8352
|
+
* (itemsAffected + bytesReclaimed). Writes are best-effort — a failed log must
|
|
8353
|
+
* never fail the operation it records.
|
|
8354
|
+
*/
|
|
8355
|
+
/** Which management domain the operation belongs to. */
|
|
8356
|
+
var OpsLogDomainSchema = _enum(["recording", "events"]);
|
|
8357
|
+
/** The kind of management operation performed. */
|
|
8358
|
+
var OpsLogOpSchema = _enum([
|
|
8359
|
+
"prune",
|
|
8360
|
+
"manual-delete",
|
|
8361
|
+
"rescan",
|
|
8362
|
+
"retention-run"
|
|
8363
|
+
]);
|
|
8364
|
+
/** Why the operation ran. */
|
|
8365
|
+
var OpsLogReasonSchema = _enum([
|
|
8366
|
+
"retention",
|
|
8367
|
+
"quota",
|
|
8368
|
+
"manual",
|
|
8369
|
+
"operator"
|
|
8370
|
+
]);
|
|
8371
|
+
/** One audit row, shared verbatim by both domains. */
|
|
8372
|
+
var OpsLogEntrySchema = object({
|
|
8373
|
+
/** Unique row id. */
|
|
8374
|
+
id: string(),
|
|
8375
|
+
/** Epoch ms the operation completed. */
|
|
8376
|
+
at: number(),
|
|
8377
|
+
domain: OpsLogDomainSchema,
|
|
8378
|
+
op: OpsLogOpSchema,
|
|
8379
|
+
reason: OpsLogReasonSchema,
|
|
8380
|
+
/** The camera the op targeted; null for a cluster/global op. */
|
|
8381
|
+
deviceId: number().nullable(),
|
|
8382
|
+
/** Node that performed the op (the log carries nodeId — no cross-node aggregation). */
|
|
8383
|
+
nodeId: string(),
|
|
8384
|
+
/** Buckets / rows deleted (op-specific unit). */
|
|
8385
|
+
itemsAffected: number(),
|
|
8386
|
+
/** Bytes reclaimed by the op (0 when not measurable). */
|
|
8387
|
+
bytesReclaimed: number(),
|
|
8388
|
+
/** Free-text detail (e.g. "floor moved to <ts>"); null when none. */
|
|
8389
|
+
detail: string().nullable(),
|
|
8390
|
+
/** Who/what triggered the op. */
|
|
8391
|
+
actor: string()
|
|
8392
|
+
});
|
|
8393
|
+
/** Shared query input for the per-domain `listOpsLog` cap methods. */
|
|
8394
|
+
var OpsLogQueryInputSchema = object({
|
|
8395
|
+
/** Restrict to a single camera; omit for every row. */
|
|
8396
|
+
deviceId: number().optional(),
|
|
8397
|
+
/** Max rows returned, newest-first. */
|
|
8398
|
+
limit: number().int().min(1).max(1e3).optional()
|
|
8399
|
+
});
|
|
8400
|
+
/**
|
|
8302
8401
|
* `StorageLocationType` — an addon-declared id that identifies the *kind* of
|
|
8303
8402
|
* storage a location serves. Defined here (not in `capabilities/storage.cap.ts`)
|
|
8304
8403
|
* so the persisted record schema and the consumer-facing cap can both consume it
|
|
@@ -15654,7 +15753,11 @@ array(ZoneRuleSchema).readonly();
|
|
|
15654
15753
|
* Extend the enum here when a new gating consumer comes online (audio
|
|
15655
15754
|
* gating, alert filtering, …) — no other surface needs to change.
|
|
15656
15755
|
*/
|
|
15657
|
-
var ZoneRuleStageEnum = _enum([
|
|
15756
|
+
var ZoneRuleStageEnum = _enum([
|
|
15757
|
+
"motion",
|
|
15758
|
+
"detection",
|
|
15759
|
+
"package"
|
|
15760
|
+
]);
|
|
15658
15761
|
/**
|
|
15659
15762
|
* Runtime registry: cap-property-name → cap definition. `BaseDevice`'s
|
|
15660
15763
|
* `state` getter looks up the cap definition here to construct a
|
|
@@ -15748,16 +15851,25 @@ var DEVICE_LOCAL_STATE_CAPS = {
|
|
|
15748
15851
|
})
|
|
15749
15852
|
},
|
|
15750
15853
|
/**
|
|
15751
|
-
* Runtime-state slice —
|
|
15854
|
+
* Runtime-state slice — every stage mirrored together so consumers
|
|
15752
15855
|
* see one reactive handle (`device.state.zoneRules.value`) instead
|
|
15753
|
-
* of
|
|
15754
|
-
* `{motion, detection}` shape, so subscribers always get the
|
|
15856
|
+
* of one per stage. Bulk-replace mutations on any stage write the full
|
|
15857
|
+
* `{motion, detection, package}` shape, so subscribers always get the
|
|
15755
15858
|
* complete current set. Consumers that only care about one stage
|
|
15756
15859
|
* just read the matching property.
|
|
15860
|
+
*
|
|
15861
|
+
* `package` backs the package-drop detector — a package zone is a
|
|
15862
|
+
* `ZoneRule` on the `'package'` stage referencing drawn polygons
|
|
15863
|
+
* (see docs/superpowers/specs/2026-07-17-package-zones-design.md §3.1).
|
|
15864
|
+
* The orchestrator provider writes this stage as a first-class slice
|
|
15865
|
+
* (Phase 4): every mutation mirrors the full `{motion, detection,
|
|
15866
|
+
* package}` shape, so consumers read the current package rules directly
|
|
15867
|
+
* off `device.state.zoneRules.value.package`.
|
|
15757
15868
|
*/
|
|
15758
15869
|
runtimeState: object({
|
|
15759
15870
|
motion: array(ZoneRuleSchema).readonly(),
|
|
15760
|
-
detection: array(ZoneRuleSchema).readonly()
|
|
15871
|
+
detection: array(ZoneRuleSchema).readonly(),
|
|
15872
|
+
package: array(ZoneRuleSchema).readonly()
|
|
15761
15873
|
})
|
|
15762
15874
|
},
|
|
15763
15875
|
zones: zonesCapability
|
|
@@ -19719,6 +19831,7 @@ var EventKindIconSchema = _enum([
|
|
|
19719
19831
|
"smoke",
|
|
19720
19832
|
"water",
|
|
19721
19833
|
"button",
|
|
19834
|
+
"package",
|
|
19722
19835
|
"generic"
|
|
19723
19836
|
]);
|
|
19724
19837
|
var EventKindCategorySchema = _enum([
|
|
@@ -19726,7 +19839,8 @@ var EventKindCategorySchema = _enum([
|
|
|
19726
19839
|
"audio",
|
|
19727
19840
|
"detection",
|
|
19728
19841
|
"sensor",
|
|
19729
|
-
"custom"
|
|
19842
|
+
"custom",
|
|
19843
|
+
"package"
|
|
19730
19844
|
]);
|
|
19731
19845
|
var EventKindDescriptorSchema = object({
|
|
19732
19846
|
/** Stable kind id (e.g. 'motion', 'person', 'contact'). */
|
|
@@ -20067,6 +20181,26 @@ var TrackCascadeCountsSchema = object({
|
|
|
20067
20181
|
/** Per-track CLIP search vectors removed (best-effort). */
|
|
20068
20182
|
embeddings: number().int()
|
|
20069
20183
|
});
|
|
20184
|
+
/** Event-store footprint for one camera. */
|
|
20185
|
+
var EventStoreDeviceFootprintSchema = object({
|
|
20186
|
+
deviceId: number(),
|
|
20187
|
+
/** Persisted event rows (motion + object + audio) for the camera. */
|
|
20188
|
+
rows: number().int(),
|
|
20189
|
+
/** Event-owned media bytes on disk for the camera. */
|
|
20190
|
+
bytes: number().int()
|
|
20191
|
+
});
|
|
20192
|
+
/** Aggregate event-store footprint: global totals + per-camera breakdown. */
|
|
20193
|
+
var EventStoreFootprintSchema = object({
|
|
20194
|
+
totalRows: number().int(),
|
|
20195
|
+
totalBytes: number().int(),
|
|
20196
|
+
devices: array(EventStoreDeviceFootprintSchema).readonly()
|
|
20197
|
+
});
|
|
20198
|
+
/** Per-kind counts returned by the event-prune / device-delete mutations. */
|
|
20199
|
+
var EventPruneCountsSchema = object({
|
|
20200
|
+
motion: number().int(),
|
|
20201
|
+
object: number().int(),
|
|
20202
|
+
audio: number().int()
|
|
20203
|
+
});
|
|
20070
20204
|
DeviceType.Camera, method(object({ deviceId: number() }), array(TrackSchema).readonly()), method(object({
|
|
20071
20205
|
deviceId: number(),
|
|
20072
20206
|
trackId: string()
|
|
@@ -20130,6 +20264,21 @@ DeviceType.Camera, method(object({ deviceId: number() }), array(TrackSchema).rea
|
|
|
20130
20264
|
}), {
|
|
20131
20265
|
kind: "mutation",
|
|
20132
20266
|
auth: "admin"
|
|
20267
|
+
}), method(object({}), EventStoreFootprintSchema, {
|
|
20268
|
+
kind: "query",
|
|
20269
|
+
auth: "admin"
|
|
20270
|
+
}), method(object({
|
|
20271
|
+
olderThanMs: number(),
|
|
20272
|
+
reason: OpsLogReasonSchema.optional()
|
|
20273
|
+
}), EventPruneCountsSchema, {
|
|
20274
|
+
kind: "mutation",
|
|
20275
|
+
auth: "admin"
|
|
20276
|
+
}), method(object({ deviceId: number() }), EventPruneCountsSchema, {
|
|
20277
|
+
kind: "mutation",
|
|
20278
|
+
auth: "admin"
|
|
20279
|
+
}), method(OpsLogQueryInputSchema, array(OpsLogEntrySchema).readonly(), {
|
|
20280
|
+
kind: "query",
|
|
20281
|
+
auth: "admin"
|
|
20133
20282
|
}), method(object({
|
|
20134
20283
|
eventId: string(),
|
|
20135
20284
|
kind: MediaFileKindEnum.optional()
|
|
@@ -23363,13 +23512,131 @@ method(object({
|
|
|
23363
23512
|
}), method(object({ deviceId: number() }), RecordingStatusSchema, {
|
|
23364
23513
|
kind: "mutation",
|
|
23365
23514
|
auth: "admin"
|
|
23366
|
-
}), method(object({
|
|
23515
|
+
}), method(object({
|
|
23516
|
+
deviceId: number(),
|
|
23517
|
+
reason: OpsLogReasonSchema.optional()
|
|
23518
|
+
}), object({
|
|
23367
23519
|
floorMs: number().nullable(),
|
|
23368
23520
|
deletedBuckets: number().int(),
|
|
23369
23521
|
reclaimedBytes: number().int()
|
|
23370
23522
|
}), {
|
|
23371
23523
|
kind: "mutation",
|
|
23372
23524
|
auth: "admin"
|
|
23525
|
+
}), method(object({
|
|
23526
|
+
deviceId: number(),
|
|
23527
|
+
fromMs: number().optional(),
|
|
23528
|
+
toMs: number().optional()
|
|
23529
|
+
}), object({
|
|
23530
|
+
deletedBuckets: number().int(),
|
|
23531
|
+
reclaimedBytes: number().int()
|
|
23532
|
+
}), {
|
|
23533
|
+
kind: "mutation",
|
|
23534
|
+
auth: "admin"
|
|
23535
|
+
}), method(OpsLogQueryInputSchema, array(OpsLogEntrySchema).readonly(), {
|
|
23536
|
+
kind: "query",
|
|
23537
|
+
auth: "admin"
|
|
23538
|
+
});
|
|
23539
|
+
/**
|
|
23540
|
+
* `recordingExport` cap — render a footage time range into a single downloadable
|
|
23541
|
+
* MP4 (regular / accelerated / decelerated / timelapse, ± audio), kept for a
|
|
23542
|
+
* bounded lifetime with a durable history, auto-expiry, and optional
|
|
23543
|
+
* delete-after-download.
|
|
23544
|
+
*
|
|
23545
|
+
* Like `recording` this is a `scope:'system', mode:'singleton'` cap: the
|
|
23546
|
+
* recorder self-gates so exactly ONE node (the designated `recordingNodeId`,
|
|
23547
|
+
* default `hub`) registers it. Device-scoped methods carry `deviceId` in their
|
|
23548
|
+
* input and dispatch to that single provider; the render runs on the node that
|
|
23549
|
+
* owns the footage (no cross-node segment transfer). Download rides the
|
|
23550
|
+
* framework addon data-plane. State persists in a DurableState blob (NOT
|
|
23551
|
+
* SQLite); history rows survive file deletion for audit.
|
|
23552
|
+
*/
|
|
23553
|
+
/** Playback-speed multiplier for the render (1 = realtime). */
|
|
23554
|
+
var ExportSpeedSchema = number().min(.25).max(32);
|
|
23555
|
+
/** Timelapse cadence — sample one source frame per `everyMs`, output at `outputFps`. */
|
|
23556
|
+
var ExportTimelapseSchema = object({
|
|
23557
|
+
everyMs: number().int().positive(),
|
|
23558
|
+
outputFps: number().int().min(1).max(60).optional()
|
|
23559
|
+
});
|
|
23560
|
+
/**
|
|
23561
|
+
* Render options. `speed` and `timelapse` are mutually exclusive. `includeAudio`
|
|
23562
|
+
* is honoured only for a realtime-ish speed (0.5–2×); timelapse is always
|
|
23563
|
+
* silent. `maxLifeMs` bounds how long the finished file is kept;
|
|
23564
|
+
* `deleteAfterDownload` removes it shortly after the first complete download.
|
|
23565
|
+
*/
|
|
23566
|
+
var ExportOptionsSchema = object({
|
|
23567
|
+
speed: ExportSpeedSchema.optional(),
|
|
23568
|
+
timelapse: ExportTimelapseSchema.optional(),
|
|
23569
|
+
includeAudio: boolean(),
|
|
23570
|
+
maxLifeMs: number().int().positive(),
|
|
23571
|
+
deleteAfterDownload: boolean(),
|
|
23572
|
+
title: string().max(200).optional()
|
|
23573
|
+
}).superRefine((v, ctx) => {
|
|
23574
|
+
if (v.speed !== void 0 && v.timelapse !== void 0) ctx.addIssue({
|
|
23575
|
+
code: ZodIssueCode.custom,
|
|
23576
|
+
message: "speed and timelapse are mutually exclusive",
|
|
23577
|
+
path: ["timelapse"]
|
|
23578
|
+
});
|
|
23579
|
+
});
|
|
23580
|
+
var ExportStateSchema = _enum([
|
|
23581
|
+
"queued",
|
|
23582
|
+
"rendering",
|
|
23583
|
+
"ready",
|
|
23584
|
+
"failed",
|
|
23585
|
+
"expired",
|
|
23586
|
+
"deleted"
|
|
23587
|
+
]);
|
|
23588
|
+
/** One export job / history row. */
|
|
23589
|
+
var ExportRecordSchema = object({
|
|
23590
|
+
id: string(),
|
|
23591
|
+
deviceId: number(),
|
|
23592
|
+
profile: string(),
|
|
23593
|
+
fromMs: number(),
|
|
23594
|
+
toMs: number(),
|
|
23595
|
+
options: ExportOptionsSchema,
|
|
23596
|
+
state: ExportStateSchema,
|
|
23597
|
+
/** 0–100 while rendering; null otherwise. */
|
|
23598
|
+
progressPct: number().nullable(),
|
|
23599
|
+
/** File size once ready; null before. */
|
|
23600
|
+
fileBytes: number().nullable(),
|
|
23601
|
+
expiresAt: number(),
|
|
23602
|
+
deleteAfterDownload: boolean(),
|
|
23603
|
+
/** Epoch of the first complete download; null until then. */
|
|
23604
|
+
downloadedAt: number().nullable(),
|
|
23605
|
+
createdAt: number(),
|
|
23606
|
+
/** User id/name that requested the export. */
|
|
23607
|
+
createdBy: string(),
|
|
23608
|
+
/** Failure reason when state is 'failed'; null otherwise. */
|
|
23609
|
+
error: string().nullable()
|
|
23610
|
+
});
|
|
23611
|
+
/** Candidate download URLs (LAN first, then operator extra hosts). */
|
|
23612
|
+
var ExportDownloadSchema = object({
|
|
23613
|
+
url: string(),
|
|
23614
|
+
endpoints: array(string())
|
|
23615
|
+
});
|
|
23616
|
+
method(object({
|
|
23617
|
+
deviceId: number(),
|
|
23618
|
+
profile: string(),
|
|
23619
|
+
fromMs: number(),
|
|
23620
|
+
toMs: number(),
|
|
23621
|
+
options: ExportOptionsSchema
|
|
23622
|
+
}), ExportRecordSchema, {
|
|
23623
|
+
kind: "mutation",
|
|
23624
|
+
auth: "protected"
|
|
23625
|
+
}), method(object({ deviceId: number().optional() }), array(ExportRecordSchema), {
|
|
23626
|
+
kind: "query",
|
|
23627
|
+
auth: "protected"
|
|
23628
|
+
}), method(object({ exportId: string() }), ExportRecordSchema, {
|
|
23629
|
+
kind: "query",
|
|
23630
|
+
auth: "protected"
|
|
23631
|
+
}), method(object({ exportId: string() }), ExportRecordSchema, {
|
|
23632
|
+
kind: "mutation",
|
|
23633
|
+
auth: "protected"
|
|
23634
|
+
}), method(object({ exportId: string() }), ExportRecordSchema, {
|
|
23635
|
+
kind: "mutation",
|
|
23636
|
+
auth: "protected"
|
|
23637
|
+
}), method(object({ exportId: string() }), ExportDownloadSchema, {
|
|
23638
|
+
kind: "query",
|
|
23639
|
+
auth: "protected"
|
|
23373
23640
|
});
|
|
23374
23641
|
/**
|
|
23375
23642
|
* One publishable camera stream as its OWNING PROVIDER describes it — the same
|
|
@@ -26389,6 +26656,12 @@ Object.freeze({
|
|
|
26389
26656
|
addonId: null,
|
|
26390
26657
|
access: "delete"
|
|
26391
26658
|
},
|
|
26659
|
+
"pipelineAnalytics.deleteDeviceEvents": {
|
|
26660
|
+
capName: "pipeline-analytics",
|
|
26661
|
+
capScope: "device",
|
|
26662
|
+
addonId: null,
|
|
26663
|
+
access: "delete"
|
|
26664
|
+
},
|
|
26392
26665
|
"pipelineAnalytics.deleteTracks": {
|
|
26393
26666
|
capName: "pipeline-analytics",
|
|
26394
26667
|
capScope: "device",
|
|
@@ -26419,6 +26692,12 @@ Object.freeze({
|
|
|
26419
26692
|
addonId: null,
|
|
26420
26693
|
access: "view"
|
|
26421
26694
|
},
|
|
26695
|
+
"pipelineAnalytics.getEventStoreFootprint": {
|
|
26696
|
+
capName: "pipeline-analytics",
|
|
26697
|
+
capScope: "device",
|
|
26698
|
+
addonId: null,
|
|
26699
|
+
access: "view"
|
|
26700
|
+
},
|
|
26422
26701
|
"pipelineAnalytics.getKeyEvents": {
|
|
26423
26702
|
capName: "pipeline-analytics",
|
|
26424
26703
|
capScope: "device",
|
|
@@ -26461,6 +26740,12 @@ Object.freeze({
|
|
|
26461
26740
|
addonId: null,
|
|
26462
26741
|
access: "view"
|
|
26463
26742
|
},
|
|
26743
|
+
"pipelineAnalytics.listOpsLog": {
|
|
26744
|
+
capName: "pipeline-analytics",
|
|
26745
|
+
capScope: "device",
|
|
26746
|
+
addonId: null,
|
|
26747
|
+
access: "view"
|
|
26748
|
+
},
|
|
26464
26749
|
"pipelineAnalytics.listRecentTracks": {
|
|
26465
26750
|
capName: "pipeline-analytics",
|
|
26466
26751
|
capScope: "device",
|
|
@@ -26473,6 +26758,12 @@ Object.freeze({
|
|
|
26473
26758
|
addonId: null,
|
|
26474
26759
|
access: "view"
|
|
26475
26760
|
},
|
|
26761
|
+
"pipelineAnalytics.pruneEvents": {
|
|
26762
|
+
capName: "pipeline-analytics",
|
|
26763
|
+
capScope: "device",
|
|
26764
|
+
addonId: null,
|
|
26765
|
+
access: "create"
|
|
26766
|
+
},
|
|
26476
26767
|
"pipelineAnalytics.pruneEventsBefore": {
|
|
26477
26768
|
capName: "pipeline-analytics",
|
|
26478
26769
|
capScope: "device",
|
|
@@ -27235,6 +27526,12 @@ Object.freeze({
|
|
|
27235
27526
|
addonId: null,
|
|
27236
27527
|
access: "create"
|
|
27237
27528
|
},
|
|
27529
|
+
"recording.deleteFootprint": {
|
|
27530
|
+
capName: "recording",
|
|
27531
|
+
capScope: "system",
|
|
27532
|
+
addonId: null,
|
|
27533
|
+
access: "delete"
|
|
27534
|
+
},
|
|
27238
27535
|
"recording.getAvailability": {
|
|
27239
27536
|
capName: "recording",
|
|
27240
27537
|
capScope: "system",
|
|
@@ -27265,6 +27562,12 @@ Object.freeze({
|
|
|
27265
27562
|
addonId: null,
|
|
27266
27563
|
access: "view"
|
|
27267
27564
|
},
|
|
27565
|
+
"recording.listOpsLog": {
|
|
27566
|
+
capName: "recording",
|
|
27567
|
+
capScope: "system",
|
|
27568
|
+
addonId: null,
|
|
27569
|
+
access: "view"
|
|
27570
|
+
},
|
|
27268
27571
|
"recording.locateSegment": {
|
|
27269
27572
|
capName: "recording",
|
|
27270
27573
|
capScope: "system",
|
|
@@ -27295,6 +27598,42 @@ Object.freeze({
|
|
|
27295
27598
|
addonId: null,
|
|
27296
27599
|
access: "create"
|
|
27297
27600
|
},
|
|
27601
|
+
"recordingExport.cancelExport": {
|
|
27602
|
+
capName: "recordingExport",
|
|
27603
|
+
capScope: "system",
|
|
27604
|
+
addonId: null,
|
|
27605
|
+
access: "create"
|
|
27606
|
+
},
|
|
27607
|
+
"recordingExport.createExport": {
|
|
27608
|
+
capName: "recordingExport",
|
|
27609
|
+
capScope: "system",
|
|
27610
|
+
addonId: null,
|
|
27611
|
+
access: "create"
|
|
27612
|
+
},
|
|
27613
|
+
"recordingExport.deleteExport": {
|
|
27614
|
+
capName: "recordingExport",
|
|
27615
|
+
capScope: "system",
|
|
27616
|
+
addonId: null,
|
|
27617
|
+
access: "delete"
|
|
27618
|
+
},
|
|
27619
|
+
"recordingExport.getDownloadUrl": {
|
|
27620
|
+
capName: "recordingExport",
|
|
27621
|
+
capScope: "system",
|
|
27622
|
+
addonId: null,
|
|
27623
|
+
access: "view"
|
|
27624
|
+
},
|
|
27625
|
+
"recordingExport.getExport": {
|
|
27626
|
+
capName: "recordingExport",
|
|
27627
|
+
capScope: "system",
|
|
27628
|
+
addonId: null,
|
|
27629
|
+
access: "view"
|
|
27630
|
+
},
|
|
27631
|
+
"recordingExport.listExports": {
|
|
27632
|
+
capName: "recordingExport",
|
|
27633
|
+
capScope: "system",
|
|
27634
|
+
addonId: null,
|
|
27635
|
+
access: "view"
|
|
27636
|
+
},
|
|
27298
27637
|
"sceneMonitor.captureReference": {
|
|
27299
27638
|
capName: "scene-monitor",
|
|
27300
27639
|
capScope: "device",
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@camstack/addon-provider-rademacher",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.13",
|
|
4
4
|
"description": "Rademacher HomePilot device-provider addon for CamStack — wraps the @apocaliss92/noderademacher local-hub client (roller shutters over the cover cap)",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"camstack",
|