@camstack/addon-matter-broker 0.1.22 → 0.1.24
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
|
@@ -13,7 +13,7 @@ let node_stream_promises = require("node:stream/promises");
|
|
|
13
13
|
let node_net = require("node:net");
|
|
14
14
|
let node_dgram = require("node:dgram");
|
|
15
15
|
node_dgram = require_esm.__toESM(node_dgram, 1);
|
|
16
|
-
//#region ../types/dist/event-category-
|
|
16
|
+
//#region ../types/dist/event-category-D4HJq7Mw.mjs
|
|
17
17
|
var EventCategory = /* @__PURE__ */ function(EventCategory) {
|
|
18
18
|
EventCategory["SystemBoot"] = "system.boot";
|
|
19
19
|
EventCategory["SystemAddonsReady"] = "system.addons-ready";
|
|
@@ -166,6 +166,11 @@ var EventCategory = /* @__PURE__ */ function(EventCategory) {
|
|
|
166
166
|
/** Runner-sampled scrub thumbnail (~1/5 s/camera). Telemetry (D8): a lost
|
|
167
167
|
* thumb is a scrub gap the recorder's keyframe backfill covers. */
|
|
168
168
|
EventCategory["RecordingThumbSampled"] = "recording.thumb-sampled";
|
|
169
|
+
/** Export render progress (0–100). Telemetry (D8): a lost tick is a stale
|
|
170
|
+
* progress bar the client reconciles via `recordingExport.getExport`. */
|
|
171
|
+
EventCategory["RecordingExportProgress"] = "recording.export.progress";
|
|
172
|
+
EventCategory["RecordingExportCompleted"] = "recording.export.completed";
|
|
173
|
+
EventCategory["RecordingExportFailed"] = "recording.export.failed";
|
|
169
174
|
EventCategory["DetectionEvent"] = "detection.event";
|
|
170
175
|
EventCategory["SessionTrackNew"] = "session.track.new";
|
|
171
176
|
EventCategory["SessionTrackExpired"] = "session.track.expired";
|
|
@@ -455,6 +460,25 @@ var EventCategory = /* @__PURE__ */ function(EventCategory) {
|
|
|
455
460
|
*/
|
|
456
461
|
EventCategory["PipelineAnalyticsStationaryChanged"] = "pipeline-analytics.stationary-changed";
|
|
457
462
|
/**
|
|
463
|
+
* Fired by `addon-post-analysis` when a package-drop is confirmed inside
|
|
464
|
+
* a package zone — a newly-appeared stationary object of a package class
|
|
465
|
+
* that cleared the class / zone / dwell / size gates. Payload:
|
|
466
|
+
* `PipelineAnalyticsPackageDeliveredPayload` carrying `{ deviceId,
|
|
467
|
+
* entryId, className, zoneIds, keyFrameMediaKey?, bbox, timestamp }`.
|
|
468
|
+
* Telemetry (D8): the durable record is the `package-events` store row;
|
|
469
|
+
* this bus topic drives notifier rules + live UI. See
|
|
470
|
+
* docs/superpowers/specs/2026-07-17-package-zones-design.md §5.1.
|
|
471
|
+
*/
|
|
472
|
+
EventCategory["PipelineAnalyticsPackageDelivered"] = "pipeline-analytics.package-delivered";
|
|
473
|
+
/**
|
|
474
|
+
* Fired by `addon-post-analysis` when a previously-delivered package
|
|
475
|
+
* leaves its zone (the stationary entry departed — moved or swept).
|
|
476
|
+
* Payload: `PipelineAnalyticsPackagePickedUpPayload` carrying
|
|
477
|
+
* `{ deviceId, entryId, deliveredEventId, className, timestamp }`.
|
|
478
|
+
* Telemetry (D8). See package-zones-design §5.2.
|
|
479
|
+
*/
|
|
480
|
+
EventCategory["PipelineAnalyticsPackagePickedUp"] = "pipeline-analytics.package-picked-up";
|
|
481
|
+
/**
|
|
458
482
|
* Fired by `addon-post-analysis` whenever a gallery face row changes:
|
|
459
483
|
* `kind:'buffered'` a new detected face was persisted, `'assigned'` /
|
|
460
484
|
* `'unassigned'` its identity link changed, `'deleted'` the row was
|
|
@@ -5207,6 +5231,25 @@ function preprocess(fn, schema) {
|
|
|
5207
5231
|
out: schema
|
|
5208
5232
|
});
|
|
5209
5233
|
}
|
|
5234
|
+
//#endregion
|
|
5235
|
+
//#region ../../node_modules/zod/v4/classic/compat.js
|
|
5236
|
+
/** @deprecated Use the raw string literal codes instead, e.g. "invalid_type". */
|
|
5237
|
+
var ZodIssueCode = {
|
|
5238
|
+
invalid_type: "invalid_type",
|
|
5239
|
+
too_big: "too_big",
|
|
5240
|
+
too_small: "too_small",
|
|
5241
|
+
invalid_format: "invalid_format",
|
|
5242
|
+
not_multiple_of: "not_multiple_of",
|
|
5243
|
+
unrecognized_keys: "unrecognized_keys",
|
|
5244
|
+
invalid_union: "invalid_union",
|
|
5245
|
+
invalid_key: "invalid_key",
|
|
5246
|
+
invalid_element: "invalid_element",
|
|
5247
|
+
invalid_value: "invalid_value",
|
|
5248
|
+
custom: "custom"
|
|
5249
|
+
};
|
|
5250
|
+
/** @deprecated Do not use. Stub definition, only included for zod-to-json-schema compatibility. */
|
|
5251
|
+
var ZodFirstPartyTypeKind;
|
|
5252
|
+
ZodFirstPartyTypeKind || (ZodFirstPartyTypeKind = {});
|
|
5210
5253
|
Object.fromEntries([
|
|
5211
5254
|
{
|
|
5212
5255
|
id: "overview",
|
|
@@ -7329,6 +7372,62 @@ var RecordingConfigSchema = object({
|
|
|
7329
7372
|
scrubThumbnails: ScrubThumbnailPresetSchema.optional()
|
|
7330
7373
|
});
|
|
7331
7374
|
/**
|
|
7375
|
+
* Ops-log — the durable, append-only operations audit shared by the
|
|
7376
|
+
* recordings and events management surfaces.
|
|
7377
|
+
*
|
|
7378
|
+
* ONE row shape is reused for both domains so a single "Activity" view can
|
|
7379
|
+
* merge the recorder's DurableState ring (recordings ops-log) and the
|
|
7380
|
+
* pipeline-analytics SQLite collection (events ops-log). Each row records a
|
|
7381
|
+
* management operation, WHY it ran (reason), and its measurable effect
|
|
7382
|
+
* (itemsAffected + bytesReclaimed). Writes are best-effort — a failed log must
|
|
7383
|
+
* never fail the operation it records.
|
|
7384
|
+
*/
|
|
7385
|
+
/** Which management domain the operation belongs to. */
|
|
7386
|
+
var OpsLogDomainSchema = _enum(["recording", "events"]);
|
|
7387
|
+
/** The kind of management operation performed. */
|
|
7388
|
+
var OpsLogOpSchema = _enum([
|
|
7389
|
+
"prune",
|
|
7390
|
+
"manual-delete",
|
|
7391
|
+
"rescan",
|
|
7392
|
+
"retention-run"
|
|
7393
|
+
]);
|
|
7394
|
+
/** Why the operation ran. */
|
|
7395
|
+
var OpsLogReasonSchema = _enum([
|
|
7396
|
+
"retention",
|
|
7397
|
+
"quota",
|
|
7398
|
+
"manual",
|
|
7399
|
+
"operator"
|
|
7400
|
+
]);
|
|
7401
|
+
/** One audit row, shared verbatim by both domains. */
|
|
7402
|
+
var OpsLogEntrySchema = object({
|
|
7403
|
+
/** Unique row id. */
|
|
7404
|
+
id: string$2(),
|
|
7405
|
+
/** Epoch ms the operation completed. */
|
|
7406
|
+
at: number(),
|
|
7407
|
+
domain: OpsLogDomainSchema,
|
|
7408
|
+
op: OpsLogOpSchema,
|
|
7409
|
+
reason: OpsLogReasonSchema,
|
|
7410
|
+
/** The camera the op targeted; null for a cluster/global op. */
|
|
7411
|
+
deviceId: number().nullable(),
|
|
7412
|
+
/** Node that performed the op (the log carries nodeId — no cross-node aggregation). */
|
|
7413
|
+
nodeId: string$2(),
|
|
7414
|
+
/** Buckets / rows deleted (op-specific unit). */
|
|
7415
|
+
itemsAffected: number(),
|
|
7416
|
+
/** Bytes reclaimed by the op (0 when not measurable). */
|
|
7417
|
+
bytesReclaimed: number(),
|
|
7418
|
+
/** Free-text detail (e.g. "floor moved to <ts>"); null when none. */
|
|
7419
|
+
detail: string$2().nullable(),
|
|
7420
|
+
/** Who/what triggered the op. */
|
|
7421
|
+
actor: string$2()
|
|
7422
|
+
});
|
|
7423
|
+
/** Shared query input for the per-domain `listOpsLog` cap methods. */
|
|
7424
|
+
var OpsLogQueryInputSchema = object({
|
|
7425
|
+
/** Restrict to a single camera; omit for every row. */
|
|
7426
|
+
deviceId: number().optional(),
|
|
7427
|
+
/** Max rows returned, newest-first. */
|
|
7428
|
+
limit: number().int().min(1).max(1e3).optional()
|
|
7429
|
+
});
|
|
7430
|
+
/**
|
|
7332
7431
|
* `StorageLocationType` — an addon-declared id that identifies the *kind* of
|
|
7333
7432
|
* storage a location serves. Defined here (not in `capabilities/storage.cap.ts`)
|
|
7334
7433
|
* so the persisted record schema and the consumer-facing cap can both consume it
|
|
@@ -14684,7 +14783,11 @@ array(ZoneRuleSchema).readonly();
|
|
|
14684
14783
|
* Extend the enum here when a new gating consumer comes online (audio
|
|
14685
14784
|
* gating, alert filtering, …) — no other surface needs to change.
|
|
14686
14785
|
*/
|
|
14687
|
-
var ZoneRuleStageEnum = _enum([
|
|
14786
|
+
var ZoneRuleStageEnum = _enum([
|
|
14787
|
+
"motion",
|
|
14788
|
+
"detection",
|
|
14789
|
+
"package"
|
|
14790
|
+
]);
|
|
14688
14791
|
/**
|
|
14689
14792
|
* Runtime registry: cap-property-name → cap definition. `BaseDevice`'s
|
|
14690
14793
|
* `state` getter looks up the cap definition here to construct a
|
|
@@ -14778,16 +14881,25 @@ var DEVICE_LOCAL_STATE_CAPS = {
|
|
|
14778
14881
|
})
|
|
14779
14882
|
},
|
|
14780
14883
|
/**
|
|
14781
|
-
* Runtime-state slice —
|
|
14884
|
+
* Runtime-state slice — every stage mirrored together so consumers
|
|
14782
14885
|
* see one reactive handle (`device.state.zoneRules.value`) instead
|
|
14783
|
-
* of
|
|
14784
|
-
* `{motion, detection}` shape, so subscribers always get the
|
|
14886
|
+
* of one per stage. Bulk-replace mutations on any stage write the full
|
|
14887
|
+
* `{motion, detection, package}` shape, so subscribers always get the
|
|
14785
14888
|
* complete current set. Consumers that only care about one stage
|
|
14786
14889
|
* just read the matching property.
|
|
14890
|
+
*
|
|
14891
|
+
* `package` backs the package-drop detector — a package zone is a
|
|
14892
|
+
* `ZoneRule` on the `'package'` stage referencing drawn polygons
|
|
14893
|
+
* (see docs/superpowers/specs/2026-07-17-package-zones-design.md §3.1).
|
|
14894
|
+
* The orchestrator provider writes this stage as a first-class slice
|
|
14895
|
+
* (Phase 4): every mutation mirrors the full `{motion, detection,
|
|
14896
|
+
* package}` shape, so consumers read the current package rules directly
|
|
14897
|
+
* off `device.state.zoneRules.value.package`.
|
|
14787
14898
|
*/
|
|
14788
14899
|
runtimeState: object({
|
|
14789
14900
|
motion: array(ZoneRuleSchema).readonly(),
|
|
14790
|
-
detection: array(ZoneRuleSchema).readonly()
|
|
14901
|
+
detection: array(ZoneRuleSchema).readonly(),
|
|
14902
|
+
package: array(ZoneRuleSchema).readonly()
|
|
14791
14903
|
})
|
|
14792
14904
|
},
|
|
14793
14905
|
zones: zonesCapability
|
|
@@ -18815,6 +18927,7 @@ var EventKindIconSchema = _enum([
|
|
|
18815
18927
|
"smoke",
|
|
18816
18928
|
"water",
|
|
18817
18929
|
"button",
|
|
18930
|
+
"package",
|
|
18818
18931
|
"generic"
|
|
18819
18932
|
]);
|
|
18820
18933
|
var EventKindCategorySchema = _enum([
|
|
@@ -18822,7 +18935,8 @@ var EventKindCategorySchema = _enum([
|
|
|
18822
18935
|
"audio",
|
|
18823
18936
|
"detection",
|
|
18824
18937
|
"sensor",
|
|
18825
|
-
"custom"
|
|
18938
|
+
"custom",
|
|
18939
|
+
"package"
|
|
18826
18940
|
]);
|
|
18827
18941
|
var EventKindDescriptorSchema = object({
|
|
18828
18942
|
/** Stable kind id (e.g. 'motion', 'person', 'contact'). */
|
|
@@ -19163,6 +19277,26 @@ var TrackCascadeCountsSchema = object({
|
|
|
19163
19277
|
/** Per-track CLIP search vectors removed (best-effort). */
|
|
19164
19278
|
embeddings: number().int()
|
|
19165
19279
|
});
|
|
19280
|
+
/** Event-store footprint for one camera. */
|
|
19281
|
+
var EventStoreDeviceFootprintSchema = object({
|
|
19282
|
+
deviceId: number(),
|
|
19283
|
+
/** Persisted event rows (motion + object + audio) for the camera. */
|
|
19284
|
+
rows: number().int(),
|
|
19285
|
+
/** Event-owned media bytes on disk for the camera. */
|
|
19286
|
+
bytes: number().int()
|
|
19287
|
+
});
|
|
19288
|
+
/** Aggregate event-store footprint: global totals + per-camera breakdown. */
|
|
19289
|
+
var EventStoreFootprintSchema = object({
|
|
19290
|
+
totalRows: number().int(),
|
|
19291
|
+
totalBytes: number().int(),
|
|
19292
|
+
devices: array(EventStoreDeviceFootprintSchema).readonly()
|
|
19293
|
+
});
|
|
19294
|
+
/** Per-kind counts returned by the event-prune / device-delete mutations. */
|
|
19295
|
+
var EventPruneCountsSchema = object({
|
|
19296
|
+
motion: number().int(),
|
|
19297
|
+
object: number().int(),
|
|
19298
|
+
audio: number().int()
|
|
19299
|
+
});
|
|
19166
19300
|
DeviceType.Camera, method(object({ deviceId: number() }), array(TrackSchema).readonly()), method(object({
|
|
19167
19301
|
deviceId: number(),
|
|
19168
19302
|
trackId: string$2()
|
|
@@ -19226,6 +19360,21 @@ DeviceType.Camera, method(object({ deviceId: number() }), array(TrackSchema).rea
|
|
|
19226
19360
|
}), {
|
|
19227
19361
|
kind: "mutation",
|
|
19228
19362
|
auth: "admin"
|
|
19363
|
+
}), method(object({}), EventStoreFootprintSchema, {
|
|
19364
|
+
kind: "query",
|
|
19365
|
+
auth: "admin"
|
|
19366
|
+
}), method(object({
|
|
19367
|
+
olderThanMs: number(),
|
|
19368
|
+
reason: OpsLogReasonSchema.optional()
|
|
19369
|
+
}), EventPruneCountsSchema, {
|
|
19370
|
+
kind: "mutation",
|
|
19371
|
+
auth: "admin"
|
|
19372
|
+
}), method(object({ deviceId: number() }), EventPruneCountsSchema, {
|
|
19373
|
+
kind: "mutation",
|
|
19374
|
+
auth: "admin"
|
|
19375
|
+
}), method(OpsLogQueryInputSchema, array(OpsLogEntrySchema).readonly(), {
|
|
19376
|
+
kind: "query",
|
|
19377
|
+
auth: "admin"
|
|
19229
19378
|
}), method(object({
|
|
19230
19379
|
eventId: string$2(),
|
|
19231
19380
|
kind: MediaFileKindEnum.optional()
|
|
@@ -22476,13 +22625,131 @@ method(object({
|
|
|
22476
22625
|
}), method(object({ deviceId: number() }), RecordingStatusSchema, {
|
|
22477
22626
|
kind: "mutation",
|
|
22478
22627
|
auth: "admin"
|
|
22479
|
-
}), method(object({
|
|
22628
|
+
}), method(object({
|
|
22629
|
+
deviceId: number(),
|
|
22630
|
+
reason: OpsLogReasonSchema.optional()
|
|
22631
|
+
}), object({
|
|
22480
22632
|
floorMs: number().nullable(),
|
|
22481
22633
|
deletedBuckets: number().int(),
|
|
22482
22634
|
reclaimedBytes: number().int()
|
|
22483
22635
|
}), {
|
|
22484
22636
|
kind: "mutation",
|
|
22485
22637
|
auth: "admin"
|
|
22638
|
+
}), method(object({
|
|
22639
|
+
deviceId: number(),
|
|
22640
|
+
fromMs: number().optional(),
|
|
22641
|
+
toMs: number().optional()
|
|
22642
|
+
}), object({
|
|
22643
|
+
deletedBuckets: number().int(),
|
|
22644
|
+
reclaimedBytes: number().int()
|
|
22645
|
+
}), {
|
|
22646
|
+
kind: "mutation",
|
|
22647
|
+
auth: "admin"
|
|
22648
|
+
}), method(OpsLogQueryInputSchema, array(OpsLogEntrySchema).readonly(), {
|
|
22649
|
+
kind: "query",
|
|
22650
|
+
auth: "admin"
|
|
22651
|
+
});
|
|
22652
|
+
/**
|
|
22653
|
+
* `recordingExport` cap — render a footage time range into a single downloadable
|
|
22654
|
+
* MP4 (regular / accelerated / decelerated / timelapse, ± audio), kept for a
|
|
22655
|
+
* bounded lifetime with a durable history, auto-expiry, and optional
|
|
22656
|
+
* delete-after-download.
|
|
22657
|
+
*
|
|
22658
|
+
* Like `recording` this is a `scope:'system', mode:'singleton'` cap: the
|
|
22659
|
+
* recorder self-gates so exactly ONE node (the designated `recordingNodeId`,
|
|
22660
|
+
* default `hub`) registers it. Device-scoped methods carry `deviceId` in their
|
|
22661
|
+
* input and dispatch to that single provider; the render runs on the node that
|
|
22662
|
+
* owns the footage (no cross-node segment transfer). Download rides the
|
|
22663
|
+
* framework addon data-plane. State persists in a DurableState blob (NOT
|
|
22664
|
+
* SQLite); history rows survive file deletion for audit.
|
|
22665
|
+
*/
|
|
22666
|
+
/** Playback-speed multiplier for the render (1 = realtime). */
|
|
22667
|
+
var ExportSpeedSchema = number().min(.25).max(32);
|
|
22668
|
+
/** Timelapse cadence — sample one source frame per `everyMs`, output at `outputFps`. */
|
|
22669
|
+
var ExportTimelapseSchema = object({
|
|
22670
|
+
everyMs: number().int().positive(),
|
|
22671
|
+
outputFps: number().int().min(1).max(60).optional()
|
|
22672
|
+
});
|
|
22673
|
+
/**
|
|
22674
|
+
* Render options. `speed` and `timelapse` are mutually exclusive. `includeAudio`
|
|
22675
|
+
* is honoured only for a realtime-ish speed (0.5–2×); timelapse is always
|
|
22676
|
+
* silent. `maxLifeMs` bounds how long the finished file is kept;
|
|
22677
|
+
* `deleteAfterDownload` removes it shortly after the first complete download.
|
|
22678
|
+
*/
|
|
22679
|
+
var ExportOptionsSchema = object({
|
|
22680
|
+
speed: ExportSpeedSchema.optional(),
|
|
22681
|
+
timelapse: ExportTimelapseSchema.optional(),
|
|
22682
|
+
includeAudio: boolean(),
|
|
22683
|
+
maxLifeMs: number().int().positive(),
|
|
22684
|
+
deleteAfterDownload: boolean(),
|
|
22685
|
+
title: string$2().max(200).optional()
|
|
22686
|
+
}).superRefine((v, ctx) => {
|
|
22687
|
+
if (v.speed !== void 0 && v.timelapse !== void 0) ctx.addIssue({
|
|
22688
|
+
code: ZodIssueCode.custom,
|
|
22689
|
+
message: "speed and timelapse are mutually exclusive",
|
|
22690
|
+
path: ["timelapse"]
|
|
22691
|
+
});
|
|
22692
|
+
});
|
|
22693
|
+
var ExportStateSchema = _enum([
|
|
22694
|
+
"queued",
|
|
22695
|
+
"rendering",
|
|
22696
|
+
"ready",
|
|
22697
|
+
"failed",
|
|
22698
|
+
"expired",
|
|
22699
|
+
"deleted"
|
|
22700
|
+
]);
|
|
22701
|
+
/** One export job / history row. */
|
|
22702
|
+
var ExportRecordSchema = object({
|
|
22703
|
+
id: string$2(),
|
|
22704
|
+
deviceId: number(),
|
|
22705
|
+
profile: string$2(),
|
|
22706
|
+
fromMs: number(),
|
|
22707
|
+
toMs: number(),
|
|
22708
|
+
options: ExportOptionsSchema,
|
|
22709
|
+
state: ExportStateSchema,
|
|
22710
|
+
/** 0–100 while rendering; null otherwise. */
|
|
22711
|
+
progressPct: number().nullable(),
|
|
22712
|
+
/** File size once ready; null before. */
|
|
22713
|
+
fileBytes: number().nullable(),
|
|
22714
|
+
expiresAt: number(),
|
|
22715
|
+
deleteAfterDownload: boolean(),
|
|
22716
|
+
/** Epoch of the first complete download; null until then. */
|
|
22717
|
+
downloadedAt: number().nullable(),
|
|
22718
|
+
createdAt: number(),
|
|
22719
|
+
/** User id/name that requested the export. */
|
|
22720
|
+
createdBy: string$2(),
|
|
22721
|
+
/** Failure reason when state is 'failed'; null otherwise. */
|
|
22722
|
+
error: string$2().nullable()
|
|
22723
|
+
});
|
|
22724
|
+
/** Candidate download URLs (LAN first, then operator extra hosts). */
|
|
22725
|
+
var ExportDownloadSchema = object({
|
|
22726
|
+
url: string$2(),
|
|
22727
|
+
endpoints: array(string$2())
|
|
22728
|
+
});
|
|
22729
|
+
method(object({
|
|
22730
|
+
deviceId: number(),
|
|
22731
|
+
profile: string$2(),
|
|
22732
|
+
fromMs: number(),
|
|
22733
|
+
toMs: number(),
|
|
22734
|
+
options: ExportOptionsSchema
|
|
22735
|
+
}), ExportRecordSchema, {
|
|
22736
|
+
kind: "mutation",
|
|
22737
|
+
auth: "protected"
|
|
22738
|
+
}), method(object({ deviceId: number().optional() }), array(ExportRecordSchema), {
|
|
22739
|
+
kind: "query",
|
|
22740
|
+
auth: "protected"
|
|
22741
|
+
}), method(object({ exportId: string$2() }), ExportRecordSchema, {
|
|
22742
|
+
kind: "query",
|
|
22743
|
+
auth: "protected"
|
|
22744
|
+
}), method(object({ exportId: string$2() }), ExportRecordSchema, {
|
|
22745
|
+
kind: "mutation",
|
|
22746
|
+
auth: "protected"
|
|
22747
|
+
}), method(object({ exportId: string$2() }), ExportRecordSchema, {
|
|
22748
|
+
kind: "mutation",
|
|
22749
|
+
auth: "protected"
|
|
22750
|
+
}), method(object({ exportId: string$2() }), ExportDownloadSchema, {
|
|
22751
|
+
kind: "query",
|
|
22752
|
+
auth: "protected"
|
|
22486
22753
|
});
|
|
22487
22754
|
/**
|
|
22488
22755
|
* One publishable camera stream as its OWNING PROVIDER describes it — the same
|
|
@@ -25502,6 +25769,12 @@ Object.freeze({
|
|
|
25502
25769
|
addonId: null,
|
|
25503
25770
|
access: "delete"
|
|
25504
25771
|
},
|
|
25772
|
+
"pipelineAnalytics.deleteDeviceEvents": {
|
|
25773
|
+
capName: "pipeline-analytics",
|
|
25774
|
+
capScope: "device",
|
|
25775
|
+
addonId: null,
|
|
25776
|
+
access: "delete"
|
|
25777
|
+
},
|
|
25505
25778
|
"pipelineAnalytics.deleteTracks": {
|
|
25506
25779
|
capName: "pipeline-analytics",
|
|
25507
25780
|
capScope: "device",
|
|
@@ -25532,6 +25805,12 @@ Object.freeze({
|
|
|
25532
25805
|
addonId: null,
|
|
25533
25806
|
access: "view"
|
|
25534
25807
|
},
|
|
25808
|
+
"pipelineAnalytics.getEventStoreFootprint": {
|
|
25809
|
+
capName: "pipeline-analytics",
|
|
25810
|
+
capScope: "device",
|
|
25811
|
+
addonId: null,
|
|
25812
|
+
access: "view"
|
|
25813
|
+
},
|
|
25535
25814
|
"pipelineAnalytics.getKeyEvents": {
|
|
25536
25815
|
capName: "pipeline-analytics",
|
|
25537
25816
|
capScope: "device",
|
|
@@ -25574,6 +25853,12 @@ Object.freeze({
|
|
|
25574
25853
|
addonId: null,
|
|
25575
25854
|
access: "view"
|
|
25576
25855
|
},
|
|
25856
|
+
"pipelineAnalytics.listOpsLog": {
|
|
25857
|
+
capName: "pipeline-analytics",
|
|
25858
|
+
capScope: "device",
|
|
25859
|
+
addonId: null,
|
|
25860
|
+
access: "view"
|
|
25861
|
+
},
|
|
25577
25862
|
"pipelineAnalytics.listRecentTracks": {
|
|
25578
25863
|
capName: "pipeline-analytics",
|
|
25579
25864
|
capScope: "device",
|
|
@@ -25586,6 +25871,12 @@ Object.freeze({
|
|
|
25586
25871
|
addonId: null,
|
|
25587
25872
|
access: "view"
|
|
25588
25873
|
},
|
|
25874
|
+
"pipelineAnalytics.pruneEvents": {
|
|
25875
|
+
capName: "pipeline-analytics",
|
|
25876
|
+
capScope: "device",
|
|
25877
|
+
addonId: null,
|
|
25878
|
+
access: "create"
|
|
25879
|
+
},
|
|
25589
25880
|
"pipelineAnalytics.pruneEventsBefore": {
|
|
25590
25881
|
capName: "pipeline-analytics",
|
|
25591
25882
|
capScope: "device",
|
|
@@ -26348,6 +26639,12 @@ Object.freeze({
|
|
|
26348
26639
|
addonId: null,
|
|
26349
26640
|
access: "create"
|
|
26350
26641
|
},
|
|
26642
|
+
"recording.deleteFootprint": {
|
|
26643
|
+
capName: "recording",
|
|
26644
|
+
capScope: "system",
|
|
26645
|
+
addonId: null,
|
|
26646
|
+
access: "delete"
|
|
26647
|
+
},
|
|
26351
26648
|
"recording.getAvailability": {
|
|
26352
26649
|
capName: "recording",
|
|
26353
26650
|
capScope: "system",
|
|
@@ -26378,6 +26675,12 @@ Object.freeze({
|
|
|
26378
26675
|
addonId: null,
|
|
26379
26676
|
access: "view"
|
|
26380
26677
|
},
|
|
26678
|
+
"recording.listOpsLog": {
|
|
26679
|
+
capName: "recording",
|
|
26680
|
+
capScope: "system",
|
|
26681
|
+
addonId: null,
|
|
26682
|
+
access: "view"
|
|
26683
|
+
},
|
|
26381
26684
|
"recording.locateSegment": {
|
|
26382
26685
|
capName: "recording",
|
|
26383
26686
|
capScope: "system",
|
|
@@ -26408,6 +26711,42 @@ Object.freeze({
|
|
|
26408
26711
|
addonId: null,
|
|
26409
26712
|
access: "create"
|
|
26410
26713
|
},
|
|
26714
|
+
"recordingExport.cancelExport": {
|
|
26715
|
+
capName: "recordingExport",
|
|
26716
|
+
capScope: "system",
|
|
26717
|
+
addonId: null,
|
|
26718
|
+
access: "create"
|
|
26719
|
+
},
|
|
26720
|
+
"recordingExport.createExport": {
|
|
26721
|
+
capName: "recordingExport",
|
|
26722
|
+
capScope: "system",
|
|
26723
|
+
addonId: null,
|
|
26724
|
+
access: "create"
|
|
26725
|
+
},
|
|
26726
|
+
"recordingExport.deleteExport": {
|
|
26727
|
+
capName: "recordingExport",
|
|
26728
|
+
capScope: "system",
|
|
26729
|
+
addonId: null,
|
|
26730
|
+
access: "delete"
|
|
26731
|
+
},
|
|
26732
|
+
"recordingExport.getDownloadUrl": {
|
|
26733
|
+
capName: "recordingExport",
|
|
26734
|
+
capScope: "system",
|
|
26735
|
+
addonId: null,
|
|
26736
|
+
access: "view"
|
|
26737
|
+
},
|
|
26738
|
+
"recordingExport.getExport": {
|
|
26739
|
+
capName: "recordingExport",
|
|
26740
|
+
capScope: "system",
|
|
26741
|
+
addonId: null,
|
|
26742
|
+
access: "view"
|
|
26743
|
+
},
|
|
26744
|
+
"recordingExport.listExports": {
|
|
26745
|
+
capName: "recordingExport",
|
|
26746
|
+
capScope: "system",
|
|
26747
|
+
addonId: null,
|
|
26748
|
+
access: "view"
|
|
26749
|
+
},
|
|
26411
26750
|
"sceneMonitor.captureReference": {
|
|
26412
26751
|
capName: "scene-monitor",
|
|
26413
26752
|
capScope: "device",
|
package/dist/addon.mjs
CHANGED
|
@@ -11,7 +11,7 @@ import { networkInterfaces, tmpdir, uptime } from "node:os";
|
|
|
11
11
|
import { finished } from "node:stream/promises";
|
|
12
12
|
import { createConnection, createServer as createServer$2 } from "node:net";
|
|
13
13
|
import * as dgram from "node:dgram";
|
|
14
|
-
//#region ../types/dist/event-category-
|
|
14
|
+
//#region ../types/dist/event-category-D4HJq7Mw.mjs
|
|
15
15
|
var EventCategory = /* @__PURE__ */ function(EventCategory) {
|
|
16
16
|
EventCategory["SystemBoot"] = "system.boot";
|
|
17
17
|
EventCategory["SystemAddonsReady"] = "system.addons-ready";
|
|
@@ -164,6 +164,11 @@ var EventCategory = /* @__PURE__ */ function(EventCategory) {
|
|
|
164
164
|
/** Runner-sampled scrub thumbnail (~1/5 s/camera). Telemetry (D8): a lost
|
|
165
165
|
* thumb is a scrub gap the recorder's keyframe backfill covers. */
|
|
166
166
|
EventCategory["RecordingThumbSampled"] = "recording.thumb-sampled";
|
|
167
|
+
/** Export render progress (0–100). Telemetry (D8): a lost tick is a stale
|
|
168
|
+
* progress bar the client reconciles via `recordingExport.getExport`. */
|
|
169
|
+
EventCategory["RecordingExportProgress"] = "recording.export.progress";
|
|
170
|
+
EventCategory["RecordingExportCompleted"] = "recording.export.completed";
|
|
171
|
+
EventCategory["RecordingExportFailed"] = "recording.export.failed";
|
|
167
172
|
EventCategory["DetectionEvent"] = "detection.event";
|
|
168
173
|
EventCategory["SessionTrackNew"] = "session.track.new";
|
|
169
174
|
EventCategory["SessionTrackExpired"] = "session.track.expired";
|
|
@@ -453,6 +458,25 @@ var EventCategory = /* @__PURE__ */ function(EventCategory) {
|
|
|
453
458
|
*/
|
|
454
459
|
EventCategory["PipelineAnalyticsStationaryChanged"] = "pipeline-analytics.stationary-changed";
|
|
455
460
|
/**
|
|
461
|
+
* Fired by `addon-post-analysis` when a package-drop is confirmed inside
|
|
462
|
+
* a package zone — a newly-appeared stationary object of a package class
|
|
463
|
+
* that cleared the class / zone / dwell / size gates. Payload:
|
|
464
|
+
* `PipelineAnalyticsPackageDeliveredPayload` carrying `{ deviceId,
|
|
465
|
+
* entryId, className, zoneIds, keyFrameMediaKey?, bbox, timestamp }`.
|
|
466
|
+
* Telemetry (D8): the durable record is the `package-events` store row;
|
|
467
|
+
* this bus topic drives notifier rules + live UI. See
|
|
468
|
+
* docs/superpowers/specs/2026-07-17-package-zones-design.md §5.1.
|
|
469
|
+
*/
|
|
470
|
+
EventCategory["PipelineAnalyticsPackageDelivered"] = "pipeline-analytics.package-delivered";
|
|
471
|
+
/**
|
|
472
|
+
* Fired by `addon-post-analysis` when a previously-delivered package
|
|
473
|
+
* leaves its zone (the stationary entry departed — moved or swept).
|
|
474
|
+
* Payload: `PipelineAnalyticsPackagePickedUpPayload` carrying
|
|
475
|
+
* `{ deviceId, entryId, deliveredEventId, className, timestamp }`.
|
|
476
|
+
* Telemetry (D8). See package-zones-design §5.2.
|
|
477
|
+
*/
|
|
478
|
+
EventCategory["PipelineAnalyticsPackagePickedUp"] = "pipeline-analytics.package-picked-up";
|
|
479
|
+
/**
|
|
456
480
|
* Fired by `addon-post-analysis` whenever a gallery face row changes:
|
|
457
481
|
* `kind:'buffered'` a new detected face was persisted, `'assigned'` /
|
|
458
482
|
* `'unassigned'` its identity link changed, `'deleted'` the row was
|
|
@@ -5205,6 +5229,25 @@ function preprocess(fn, schema) {
|
|
|
5205
5229
|
out: schema
|
|
5206
5230
|
});
|
|
5207
5231
|
}
|
|
5232
|
+
//#endregion
|
|
5233
|
+
//#region ../../node_modules/zod/v4/classic/compat.js
|
|
5234
|
+
/** @deprecated Use the raw string literal codes instead, e.g. "invalid_type". */
|
|
5235
|
+
var ZodIssueCode = {
|
|
5236
|
+
invalid_type: "invalid_type",
|
|
5237
|
+
too_big: "too_big",
|
|
5238
|
+
too_small: "too_small",
|
|
5239
|
+
invalid_format: "invalid_format",
|
|
5240
|
+
not_multiple_of: "not_multiple_of",
|
|
5241
|
+
unrecognized_keys: "unrecognized_keys",
|
|
5242
|
+
invalid_union: "invalid_union",
|
|
5243
|
+
invalid_key: "invalid_key",
|
|
5244
|
+
invalid_element: "invalid_element",
|
|
5245
|
+
invalid_value: "invalid_value",
|
|
5246
|
+
custom: "custom"
|
|
5247
|
+
};
|
|
5248
|
+
/** @deprecated Do not use. Stub definition, only included for zod-to-json-schema compatibility. */
|
|
5249
|
+
var ZodFirstPartyTypeKind;
|
|
5250
|
+
ZodFirstPartyTypeKind || (ZodFirstPartyTypeKind = {});
|
|
5208
5251
|
Object.fromEntries([
|
|
5209
5252
|
{
|
|
5210
5253
|
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$2(),
|
|
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$2(),
|
|
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$2().nullable(),
|
|
7418
|
+
/** Who/what triggered the op. */
|
|
7419
|
+
actor: string$2()
|
|
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
|
|
@@ -14682,7 +14781,11 @@ array(ZoneRuleSchema).readonly();
|
|
|
14682
14781
|
* Extend the enum here when a new gating consumer comes online (audio
|
|
14683
14782
|
* gating, alert filtering, …) — no other surface needs to change.
|
|
14684
14783
|
*/
|
|
14685
|
-
var ZoneRuleStageEnum = _enum([
|
|
14784
|
+
var ZoneRuleStageEnum = _enum([
|
|
14785
|
+
"motion",
|
|
14786
|
+
"detection",
|
|
14787
|
+
"package"
|
|
14788
|
+
]);
|
|
14686
14789
|
/**
|
|
14687
14790
|
* Runtime registry: cap-property-name → cap definition. `BaseDevice`'s
|
|
14688
14791
|
* `state` getter looks up the cap definition here to construct a
|
|
@@ -14776,16 +14879,25 @@ var DEVICE_LOCAL_STATE_CAPS = {
|
|
|
14776
14879
|
})
|
|
14777
14880
|
},
|
|
14778
14881
|
/**
|
|
14779
|
-
* Runtime-state slice —
|
|
14882
|
+
* Runtime-state slice — every stage mirrored together so consumers
|
|
14780
14883
|
* see one reactive handle (`device.state.zoneRules.value`) instead
|
|
14781
|
-
* of
|
|
14782
|
-
* `{motion, detection}` shape, so subscribers always get the
|
|
14884
|
+
* of one per stage. Bulk-replace mutations on any stage write the full
|
|
14885
|
+
* `{motion, detection, package}` shape, so subscribers always get the
|
|
14783
14886
|
* complete current set. Consumers that only care about one stage
|
|
14784
14887
|
* just read the matching property.
|
|
14888
|
+
*
|
|
14889
|
+
* `package` backs the package-drop detector — a package zone is a
|
|
14890
|
+
* `ZoneRule` on the `'package'` stage referencing drawn polygons
|
|
14891
|
+
* (see docs/superpowers/specs/2026-07-17-package-zones-design.md §3.1).
|
|
14892
|
+
* The orchestrator provider writes this stage as a first-class slice
|
|
14893
|
+
* (Phase 4): every mutation mirrors the full `{motion, detection,
|
|
14894
|
+
* package}` shape, so consumers read the current package rules directly
|
|
14895
|
+
* off `device.state.zoneRules.value.package`.
|
|
14785
14896
|
*/
|
|
14786
14897
|
runtimeState: object({
|
|
14787
14898
|
motion: array(ZoneRuleSchema).readonly(),
|
|
14788
|
-
detection: array(ZoneRuleSchema).readonly()
|
|
14899
|
+
detection: array(ZoneRuleSchema).readonly(),
|
|
14900
|
+
package: array(ZoneRuleSchema).readonly()
|
|
14789
14901
|
})
|
|
14790
14902
|
},
|
|
14791
14903
|
zones: zonesCapability
|
|
@@ -18813,6 +18925,7 @@ var EventKindIconSchema = _enum([
|
|
|
18813
18925
|
"smoke",
|
|
18814
18926
|
"water",
|
|
18815
18927
|
"button",
|
|
18928
|
+
"package",
|
|
18816
18929
|
"generic"
|
|
18817
18930
|
]);
|
|
18818
18931
|
var EventKindCategorySchema = _enum([
|
|
@@ -18820,7 +18933,8 @@ var EventKindCategorySchema = _enum([
|
|
|
18820
18933
|
"audio",
|
|
18821
18934
|
"detection",
|
|
18822
18935
|
"sensor",
|
|
18823
|
-
"custom"
|
|
18936
|
+
"custom",
|
|
18937
|
+
"package"
|
|
18824
18938
|
]);
|
|
18825
18939
|
var EventKindDescriptorSchema = object({
|
|
18826
18940
|
/** Stable kind id (e.g. 'motion', 'person', 'contact'). */
|
|
@@ -19161,6 +19275,26 @@ var TrackCascadeCountsSchema = object({
|
|
|
19161
19275
|
/** Per-track CLIP search vectors removed (best-effort). */
|
|
19162
19276
|
embeddings: number().int()
|
|
19163
19277
|
});
|
|
19278
|
+
/** Event-store footprint for one camera. */
|
|
19279
|
+
var EventStoreDeviceFootprintSchema = object({
|
|
19280
|
+
deviceId: number(),
|
|
19281
|
+
/** Persisted event rows (motion + object + audio) for the camera. */
|
|
19282
|
+
rows: number().int(),
|
|
19283
|
+
/** Event-owned media bytes on disk for the camera. */
|
|
19284
|
+
bytes: number().int()
|
|
19285
|
+
});
|
|
19286
|
+
/** Aggregate event-store footprint: global totals + per-camera breakdown. */
|
|
19287
|
+
var EventStoreFootprintSchema = object({
|
|
19288
|
+
totalRows: number().int(),
|
|
19289
|
+
totalBytes: number().int(),
|
|
19290
|
+
devices: array(EventStoreDeviceFootprintSchema).readonly()
|
|
19291
|
+
});
|
|
19292
|
+
/** Per-kind counts returned by the event-prune / device-delete mutations. */
|
|
19293
|
+
var EventPruneCountsSchema = object({
|
|
19294
|
+
motion: number().int(),
|
|
19295
|
+
object: number().int(),
|
|
19296
|
+
audio: number().int()
|
|
19297
|
+
});
|
|
19164
19298
|
DeviceType.Camera, method(object({ deviceId: number() }), array(TrackSchema).readonly()), method(object({
|
|
19165
19299
|
deviceId: number(),
|
|
19166
19300
|
trackId: string$2()
|
|
@@ -19224,6 +19358,21 @@ DeviceType.Camera, method(object({ deviceId: number() }), array(TrackSchema).rea
|
|
|
19224
19358
|
}), {
|
|
19225
19359
|
kind: "mutation",
|
|
19226
19360
|
auth: "admin"
|
|
19361
|
+
}), method(object({}), EventStoreFootprintSchema, {
|
|
19362
|
+
kind: "query",
|
|
19363
|
+
auth: "admin"
|
|
19364
|
+
}), method(object({
|
|
19365
|
+
olderThanMs: number(),
|
|
19366
|
+
reason: OpsLogReasonSchema.optional()
|
|
19367
|
+
}), EventPruneCountsSchema, {
|
|
19368
|
+
kind: "mutation",
|
|
19369
|
+
auth: "admin"
|
|
19370
|
+
}), method(object({ deviceId: number() }), EventPruneCountsSchema, {
|
|
19371
|
+
kind: "mutation",
|
|
19372
|
+
auth: "admin"
|
|
19373
|
+
}), method(OpsLogQueryInputSchema, array(OpsLogEntrySchema).readonly(), {
|
|
19374
|
+
kind: "query",
|
|
19375
|
+
auth: "admin"
|
|
19227
19376
|
}), method(object({
|
|
19228
19377
|
eventId: string$2(),
|
|
19229
19378
|
kind: MediaFileKindEnum.optional()
|
|
@@ -22474,13 +22623,131 @@ method(object({
|
|
|
22474
22623
|
}), method(object({ deviceId: number() }), RecordingStatusSchema, {
|
|
22475
22624
|
kind: "mutation",
|
|
22476
22625
|
auth: "admin"
|
|
22477
|
-
}), method(object({
|
|
22626
|
+
}), method(object({
|
|
22627
|
+
deviceId: number(),
|
|
22628
|
+
reason: OpsLogReasonSchema.optional()
|
|
22629
|
+
}), object({
|
|
22478
22630
|
floorMs: number().nullable(),
|
|
22479
22631
|
deletedBuckets: number().int(),
|
|
22480
22632
|
reclaimedBytes: number().int()
|
|
22481
22633
|
}), {
|
|
22482
22634
|
kind: "mutation",
|
|
22483
22635
|
auth: "admin"
|
|
22636
|
+
}), method(object({
|
|
22637
|
+
deviceId: number(),
|
|
22638
|
+
fromMs: number().optional(),
|
|
22639
|
+
toMs: number().optional()
|
|
22640
|
+
}), object({
|
|
22641
|
+
deletedBuckets: number().int(),
|
|
22642
|
+
reclaimedBytes: number().int()
|
|
22643
|
+
}), {
|
|
22644
|
+
kind: "mutation",
|
|
22645
|
+
auth: "admin"
|
|
22646
|
+
}), method(OpsLogQueryInputSchema, array(OpsLogEntrySchema).readonly(), {
|
|
22647
|
+
kind: "query",
|
|
22648
|
+
auth: "admin"
|
|
22649
|
+
});
|
|
22650
|
+
/**
|
|
22651
|
+
* `recordingExport` cap — render a footage time range into a single downloadable
|
|
22652
|
+
* MP4 (regular / accelerated / decelerated / timelapse, ± audio), kept for a
|
|
22653
|
+
* bounded lifetime with a durable history, auto-expiry, and optional
|
|
22654
|
+
* delete-after-download.
|
|
22655
|
+
*
|
|
22656
|
+
* Like `recording` this is a `scope:'system', mode:'singleton'` cap: the
|
|
22657
|
+
* recorder self-gates so exactly ONE node (the designated `recordingNodeId`,
|
|
22658
|
+
* default `hub`) registers it. Device-scoped methods carry `deviceId` in their
|
|
22659
|
+
* input and dispatch to that single provider; the render runs on the node that
|
|
22660
|
+
* owns the footage (no cross-node segment transfer). Download rides the
|
|
22661
|
+
* framework addon data-plane. State persists in a DurableState blob (NOT
|
|
22662
|
+
* SQLite); history rows survive file deletion for audit.
|
|
22663
|
+
*/
|
|
22664
|
+
/** Playback-speed multiplier for the render (1 = realtime). */
|
|
22665
|
+
var ExportSpeedSchema = number().min(.25).max(32);
|
|
22666
|
+
/** Timelapse cadence — sample one source frame per `everyMs`, output at `outputFps`. */
|
|
22667
|
+
var ExportTimelapseSchema = object({
|
|
22668
|
+
everyMs: number().int().positive(),
|
|
22669
|
+
outputFps: number().int().min(1).max(60).optional()
|
|
22670
|
+
});
|
|
22671
|
+
/**
|
|
22672
|
+
* Render options. `speed` and `timelapse` are mutually exclusive. `includeAudio`
|
|
22673
|
+
* is honoured only for a realtime-ish speed (0.5–2×); timelapse is always
|
|
22674
|
+
* silent. `maxLifeMs` bounds how long the finished file is kept;
|
|
22675
|
+
* `deleteAfterDownload` removes it shortly after the first complete download.
|
|
22676
|
+
*/
|
|
22677
|
+
var ExportOptionsSchema = object({
|
|
22678
|
+
speed: ExportSpeedSchema.optional(),
|
|
22679
|
+
timelapse: ExportTimelapseSchema.optional(),
|
|
22680
|
+
includeAudio: boolean(),
|
|
22681
|
+
maxLifeMs: number().int().positive(),
|
|
22682
|
+
deleteAfterDownload: boolean(),
|
|
22683
|
+
title: string$2().max(200).optional()
|
|
22684
|
+
}).superRefine((v, ctx) => {
|
|
22685
|
+
if (v.speed !== void 0 && v.timelapse !== void 0) ctx.addIssue({
|
|
22686
|
+
code: ZodIssueCode.custom,
|
|
22687
|
+
message: "speed and timelapse are mutually exclusive",
|
|
22688
|
+
path: ["timelapse"]
|
|
22689
|
+
});
|
|
22690
|
+
});
|
|
22691
|
+
var ExportStateSchema = _enum([
|
|
22692
|
+
"queued",
|
|
22693
|
+
"rendering",
|
|
22694
|
+
"ready",
|
|
22695
|
+
"failed",
|
|
22696
|
+
"expired",
|
|
22697
|
+
"deleted"
|
|
22698
|
+
]);
|
|
22699
|
+
/** One export job / history row. */
|
|
22700
|
+
var ExportRecordSchema = object({
|
|
22701
|
+
id: string$2(),
|
|
22702
|
+
deviceId: number(),
|
|
22703
|
+
profile: string$2(),
|
|
22704
|
+
fromMs: number(),
|
|
22705
|
+
toMs: number(),
|
|
22706
|
+
options: ExportOptionsSchema,
|
|
22707
|
+
state: ExportStateSchema,
|
|
22708
|
+
/** 0–100 while rendering; null otherwise. */
|
|
22709
|
+
progressPct: number().nullable(),
|
|
22710
|
+
/** File size once ready; null before. */
|
|
22711
|
+
fileBytes: number().nullable(),
|
|
22712
|
+
expiresAt: number(),
|
|
22713
|
+
deleteAfterDownload: boolean(),
|
|
22714
|
+
/** Epoch of the first complete download; null until then. */
|
|
22715
|
+
downloadedAt: number().nullable(),
|
|
22716
|
+
createdAt: number(),
|
|
22717
|
+
/** User id/name that requested the export. */
|
|
22718
|
+
createdBy: string$2(),
|
|
22719
|
+
/** Failure reason when state is 'failed'; null otherwise. */
|
|
22720
|
+
error: string$2().nullable()
|
|
22721
|
+
});
|
|
22722
|
+
/** Candidate download URLs (LAN first, then operator extra hosts). */
|
|
22723
|
+
var ExportDownloadSchema = object({
|
|
22724
|
+
url: string$2(),
|
|
22725
|
+
endpoints: array(string$2())
|
|
22726
|
+
});
|
|
22727
|
+
method(object({
|
|
22728
|
+
deviceId: number(),
|
|
22729
|
+
profile: string$2(),
|
|
22730
|
+
fromMs: number(),
|
|
22731
|
+
toMs: number(),
|
|
22732
|
+
options: ExportOptionsSchema
|
|
22733
|
+
}), ExportRecordSchema, {
|
|
22734
|
+
kind: "mutation",
|
|
22735
|
+
auth: "protected"
|
|
22736
|
+
}), method(object({ deviceId: number().optional() }), array(ExportRecordSchema), {
|
|
22737
|
+
kind: "query",
|
|
22738
|
+
auth: "protected"
|
|
22739
|
+
}), method(object({ exportId: string$2() }), ExportRecordSchema, {
|
|
22740
|
+
kind: "query",
|
|
22741
|
+
auth: "protected"
|
|
22742
|
+
}), method(object({ exportId: string$2() }), ExportRecordSchema, {
|
|
22743
|
+
kind: "mutation",
|
|
22744
|
+
auth: "protected"
|
|
22745
|
+
}), method(object({ exportId: string$2() }), ExportRecordSchema, {
|
|
22746
|
+
kind: "mutation",
|
|
22747
|
+
auth: "protected"
|
|
22748
|
+
}), method(object({ exportId: string$2() }), ExportDownloadSchema, {
|
|
22749
|
+
kind: "query",
|
|
22750
|
+
auth: "protected"
|
|
22484
22751
|
});
|
|
22485
22752
|
/**
|
|
22486
22753
|
* One publishable camera stream as its OWNING PROVIDER describes it — the same
|
|
@@ -25500,6 +25767,12 @@ Object.freeze({
|
|
|
25500
25767
|
addonId: null,
|
|
25501
25768
|
access: "delete"
|
|
25502
25769
|
},
|
|
25770
|
+
"pipelineAnalytics.deleteDeviceEvents": {
|
|
25771
|
+
capName: "pipeline-analytics",
|
|
25772
|
+
capScope: "device",
|
|
25773
|
+
addonId: null,
|
|
25774
|
+
access: "delete"
|
|
25775
|
+
},
|
|
25503
25776
|
"pipelineAnalytics.deleteTracks": {
|
|
25504
25777
|
capName: "pipeline-analytics",
|
|
25505
25778
|
capScope: "device",
|
|
@@ -25530,6 +25803,12 @@ Object.freeze({
|
|
|
25530
25803
|
addonId: null,
|
|
25531
25804
|
access: "view"
|
|
25532
25805
|
},
|
|
25806
|
+
"pipelineAnalytics.getEventStoreFootprint": {
|
|
25807
|
+
capName: "pipeline-analytics",
|
|
25808
|
+
capScope: "device",
|
|
25809
|
+
addonId: null,
|
|
25810
|
+
access: "view"
|
|
25811
|
+
},
|
|
25533
25812
|
"pipelineAnalytics.getKeyEvents": {
|
|
25534
25813
|
capName: "pipeline-analytics",
|
|
25535
25814
|
capScope: "device",
|
|
@@ -25572,6 +25851,12 @@ Object.freeze({
|
|
|
25572
25851
|
addonId: null,
|
|
25573
25852
|
access: "view"
|
|
25574
25853
|
},
|
|
25854
|
+
"pipelineAnalytics.listOpsLog": {
|
|
25855
|
+
capName: "pipeline-analytics",
|
|
25856
|
+
capScope: "device",
|
|
25857
|
+
addonId: null,
|
|
25858
|
+
access: "view"
|
|
25859
|
+
},
|
|
25575
25860
|
"pipelineAnalytics.listRecentTracks": {
|
|
25576
25861
|
capName: "pipeline-analytics",
|
|
25577
25862
|
capScope: "device",
|
|
@@ -25584,6 +25869,12 @@ Object.freeze({
|
|
|
25584
25869
|
addonId: null,
|
|
25585
25870
|
access: "view"
|
|
25586
25871
|
},
|
|
25872
|
+
"pipelineAnalytics.pruneEvents": {
|
|
25873
|
+
capName: "pipeline-analytics",
|
|
25874
|
+
capScope: "device",
|
|
25875
|
+
addonId: null,
|
|
25876
|
+
access: "create"
|
|
25877
|
+
},
|
|
25587
25878
|
"pipelineAnalytics.pruneEventsBefore": {
|
|
25588
25879
|
capName: "pipeline-analytics",
|
|
25589
25880
|
capScope: "device",
|
|
@@ -26346,6 +26637,12 @@ Object.freeze({
|
|
|
26346
26637
|
addonId: null,
|
|
26347
26638
|
access: "create"
|
|
26348
26639
|
},
|
|
26640
|
+
"recording.deleteFootprint": {
|
|
26641
|
+
capName: "recording",
|
|
26642
|
+
capScope: "system",
|
|
26643
|
+
addonId: null,
|
|
26644
|
+
access: "delete"
|
|
26645
|
+
},
|
|
26349
26646
|
"recording.getAvailability": {
|
|
26350
26647
|
capName: "recording",
|
|
26351
26648
|
capScope: "system",
|
|
@@ -26376,6 +26673,12 @@ Object.freeze({
|
|
|
26376
26673
|
addonId: null,
|
|
26377
26674
|
access: "view"
|
|
26378
26675
|
},
|
|
26676
|
+
"recording.listOpsLog": {
|
|
26677
|
+
capName: "recording",
|
|
26678
|
+
capScope: "system",
|
|
26679
|
+
addonId: null,
|
|
26680
|
+
access: "view"
|
|
26681
|
+
},
|
|
26379
26682
|
"recording.locateSegment": {
|
|
26380
26683
|
capName: "recording",
|
|
26381
26684
|
capScope: "system",
|
|
@@ -26406,6 +26709,42 @@ Object.freeze({
|
|
|
26406
26709
|
addonId: null,
|
|
26407
26710
|
access: "create"
|
|
26408
26711
|
},
|
|
26712
|
+
"recordingExport.cancelExport": {
|
|
26713
|
+
capName: "recordingExport",
|
|
26714
|
+
capScope: "system",
|
|
26715
|
+
addonId: null,
|
|
26716
|
+
access: "create"
|
|
26717
|
+
},
|
|
26718
|
+
"recordingExport.createExport": {
|
|
26719
|
+
capName: "recordingExport",
|
|
26720
|
+
capScope: "system",
|
|
26721
|
+
addonId: null,
|
|
26722
|
+
access: "create"
|
|
26723
|
+
},
|
|
26724
|
+
"recordingExport.deleteExport": {
|
|
26725
|
+
capName: "recordingExport",
|
|
26726
|
+
capScope: "system",
|
|
26727
|
+
addonId: null,
|
|
26728
|
+
access: "delete"
|
|
26729
|
+
},
|
|
26730
|
+
"recordingExport.getDownloadUrl": {
|
|
26731
|
+
capName: "recordingExport",
|
|
26732
|
+
capScope: "system",
|
|
26733
|
+
addonId: null,
|
|
26734
|
+
access: "view"
|
|
26735
|
+
},
|
|
26736
|
+
"recordingExport.getExport": {
|
|
26737
|
+
capName: "recordingExport",
|
|
26738
|
+
capScope: "system",
|
|
26739
|
+
addonId: null,
|
|
26740
|
+
access: "view"
|
|
26741
|
+
},
|
|
26742
|
+
"recordingExport.listExports": {
|
|
26743
|
+
capName: "recordingExport",
|
|
26744
|
+
capScope: "system",
|
|
26745
|
+
addonId: null,
|
|
26746
|
+
access: "view"
|
|
26747
|
+
},
|
|
26409
26748
|
"sceneMonitor.captureReference": {
|
|
26410
26749
|
capName: "scene-monitor",
|
|
26411
26750
|
capScope: "device",
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@camstack/addon-matter-broker",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.24",
|
|
4
4
|
"description": "Matter broker addon for CamStack — owns a Matter fabric (commissioning + the long-lived controller) via the matter.js controller and brokers commissioned Matter nodes into CamStack",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"camstack",
|