@camstack/addon-provider-homematic 1.1.24 → 1.1.26
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
|
@@ -8,7 +8,7 @@ let http = require("http");
|
|
|
8
8
|
let crypto$1 = require("crypto");
|
|
9
9
|
let fs_promises = require("fs/promises");
|
|
10
10
|
let path = require("path");
|
|
11
|
-
//#region ../types/dist/event-category-
|
|
11
|
+
//#region ../types/dist/event-category-D4HJq7Mw.mjs
|
|
12
12
|
var EventCategory = /* @__PURE__ */ function(EventCategory) {
|
|
13
13
|
EventCategory["SystemBoot"] = "system.boot";
|
|
14
14
|
EventCategory["SystemAddonsReady"] = "system.addons-ready";
|
|
@@ -161,6 +161,11 @@ var EventCategory = /* @__PURE__ */ function(EventCategory) {
|
|
|
161
161
|
/** Runner-sampled scrub thumbnail (~1/5 s/camera). Telemetry (D8): a lost
|
|
162
162
|
* thumb is a scrub gap the recorder's keyframe backfill covers. */
|
|
163
163
|
EventCategory["RecordingThumbSampled"] = "recording.thumb-sampled";
|
|
164
|
+
/** Export render progress (0–100). Telemetry (D8): a lost tick is a stale
|
|
165
|
+
* progress bar the client reconciles via `recordingExport.getExport`. */
|
|
166
|
+
EventCategory["RecordingExportProgress"] = "recording.export.progress";
|
|
167
|
+
EventCategory["RecordingExportCompleted"] = "recording.export.completed";
|
|
168
|
+
EventCategory["RecordingExportFailed"] = "recording.export.failed";
|
|
164
169
|
EventCategory["DetectionEvent"] = "detection.event";
|
|
165
170
|
EventCategory["SessionTrackNew"] = "session.track.new";
|
|
166
171
|
EventCategory["SessionTrackExpired"] = "session.track.expired";
|
|
@@ -450,6 +455,25 @@ var EventCategory = /* @__PURE__ */ function(EventCategory) {
|
|
|
450
455
|
*/
|
|
451
456
|
EventCategory["PipelineAnalyticsStationaryChanged"] = "pipeline-analytics.stationary-changed";
|
|
452
457
|
/**
|
|
458
|
+
* Fired by `addon-post-analysis` when a package-drop is confirmed inside
|
|
459
|
+
* a package zone — a newly-appeared stationary object of a package class
|
|
460
|
+
* that cleared the class / zone / dwell / size gates. Payload:
|
|
461
|
+
* `PipelineAnalyticsPackageDeliveredPayload` carrying `{ deviceId,
|
|
462
|
+
* entryId, className, zoneIds, keyFrameMediaKey?, bbox, timestamp }`.
|
|
463
|
+
* Telemetry (D8): the durable record is the `package-events` store row;
|
|
464
|
+
* this bus topic drives notifier rules + live UI. See
|
|
465
|
+
* docs/superpowers/specs/2026-07-17-package-zones-design.md §5.1.
|
|
466
|
+
*/
|
|
467
|
+
EventCategory["PipelineAnalyticsPackageDelivered"] = "pipeline-analytics.package-delivered";
|
|
468
|
+
/**
|
|
469
|
+
* Fired by `addon-post-analysis` when a previously-delivered package
|
|
470
|
+
* leaves its zone (the stationary entry departed — moved or swept).
|
|
471
|
+
* Payload: `PipelineAnalyticsPackagePickedUpPayload` carrying
|
|
472
|
+
* `{ deviceId, entryId, deliveredEventId, className, timestamp }`.
|
|
473
|
+
* Telemetry (D8). See package-zones-design §5.2.
|
|
474
|
+
*/
|
|
475
|
+
EventCategory["PipelineAnalyticsPackagePickedUp"] = "pipeline-analytics.package-picked-up";
|
|
476
|
+
/**
|
|
453
477
|
* Fired by `addon-post-analysis` whenever a gallery face row changes:
|
|
454
478
|
* `kind:'buffered'` a new detected face was persisted, `'assigned'` /
|
|
455
479
|
* `'unassigned'` its identity link changed, `'deleted'` the row was
|
|
@@ -5202,6 +5226,25 @@ function preprocess(fn, schema) {
|
|
|
5202
5226
|
out: schema
|
|
5203
5227
|
});
|
|
5204
5228
|
}
|
|
5229
|
+
//#endregion
|
|
5230
|
+
//#region ../../node_modules/zod/v4/classic/compat.js
|
|
5231
|
+
/** @deprecated Use the raw string literal codes instead, e.g. "invalid_type". */
|
|
5232
|
+
var ZodIssueCode = {
|
|
5233
|
+
invalid_type: "invalid_type",
|
|
5234
|
+
too_big: "too_big",
|
|
5235
|
+
too_small: "too_small",
|
|
5236
|
+
invalid_format: "invalid_format",
|
|
5237
|
+
not_multiple_of: "not_multiple_of",
|
|
5238
|
+
unrecognized_keys: "unrecognized_keys",
|
|
5239
|
+
invalid_union: "invalid_union",
|
|
5240
|
+
invalid_key: "invalid_key",
|
|
5241
|
+
invalid_element: "invalid_element",
|
|
5242
|
+
invalid_value: "invalid_value",
|
|
5243
|
+
custom: "custom"
|
|
5244
|
+
};
|
|
5245
|
+
/** @deprecated Do not use. Stub definition, only included for zod-to-json-schema compatibility. */
|
|
5246
|
+
var ZodFirstPartyTypeKind;
|
|
5247
|
+
ZodFirstPartyTypeKind || (ZodFirstPartyTypeKind = {});
|
|
5205
5248
|
Object.fromEntries([
|
|
5206
5249
|
{
|
|
5207
5250
|
id: "overview",
|
|
@@ -7324,6 +7367,62 @@ var RecordingConfigSchema = object({
|
|
|
7324
7367
|
scrubThumbnails: ScrubThumbnailPresetSchema.optional()
|
|
7325
7368
|
});
|
|
7326
7369
|
/**
|
|
7370
|
+
* Ops-log — the durable, append-only operations audit shared by the
|
|
7371
|
+
* recordings and events management surfaces.
|
|
7372
|
+
*
|
|
7373
|
+
* ONE row shape is reused for both domains so a single "Activity" view can
|
|
7374
|
+
* merge the recorder's DurableState ring (recordings ops-log) and the
|
|
7375
|
+
* pipeline-analytics SQLite collection (events ops-log). Each row records a
|
|
7376
|
+
* management operation, WHY it ran (reason), and its measurable effect
|
|
7377
|
+
* (itemsAffected + bytesReclaimed). Writes are best-effort — a failed log must
|
|
7378
|
+
* never fail the operation it records.
|
|
7379
|
+
*/
|
|
7380
|
+
/** Which management domain the operation belongs to. */
|
|
7381
|
+
var OpsLogDomainSchema = _enum(["recording", "events"]);
|
|
7382
|
+
/** The kind of management operation performed. */
|
|
7383
|
+
var OpsLogOpSchema = _enum([
|
|
7384
|
+
"prune",
|
|
7385
|
+
"manual-delete",
|
|
7386
|
+
"rescan",
|
|
7387
|
+
"retention-run"
|
|
7388
|
+
]);
|
|
7389
|
+
/** Why the operation ran. */
|
|
7390
|
+
var OpsLogReasonSchema = _enum([
|
|
7391
|
+
"retention",
|
|
7392
|
+
"quota",
|
|
7393
|
+
"manual",
|
|
7394
|
+
"operator"
|
|
7395
|
+
]);
|
|
7396
|
+
/** One audit row, shared verbatim by both domains. */
|
|
7397
|
+
var OpsLogEntrySchema = object({
|
|
7398
|
+
/** Unique row id. */
|
|
7399
|
+
id: string(),
|
|
7400
|
+
/** Epoch ms the operation completed. */
|
|
7401
|
+
at: number(),
|
|
7402
|
+
domain: OpsLogDomainSchema,
|
|
7403
|
+
op: OpsLogOpSchema,
|
|
7404
|
+
reason: OpsLogReasonSchema,
|
|
7405
|
+
/** The camera the op targeted; null for a cluster/global op. */
|
|
7406
|
+
deviceId: number().nullable(),
|
|
7407
|
+
/** Node that performed the op (the log carries nodeId — no cross-node aggregation). */
|
|
7408
|
+
nodeId: string(),
|
|
7409
|
+
/** Buckets / rows deleted (op-specific unit). */
|
|
7410
|
+
itemsAffected: number(),
|
|
7411
|
+
/** Bytes reclaimed by the op (0 when not measurable). */
|
|
7412
|
+
bytesReclaimed: number(),
|
|
7413
|
+
/** Free-text detail (e.g. "floor moved to <ts>"); null when none. */
|
|
7414
|
+
detail: string().nullable(),
|
|
7415
|
+
/** Who/what triggered the op. */
|
|
7416
|
+
actor: string()
|
|
7417
|
+
});
|
|
7418
|
+
/** Shared query input for the per-domain `listOpsLog` cap methods. */
|
|
7419
|
+
var OpsLogQueryInputSchema = object({
|
|
7420
|
+
/** Restrict to a single camera; omit for every row. */
|
|
7421
|
+
deviceId: number().optional(),
|
|
7422
|
+
/** Max rows returned, newest-first. */
|
|
7423
|
+
limit: number().int().min(1).max(1e3).optional()
|
|
7424
|
+
});
|
|
7425
|
+
/**
|
|
7327
7426
|
* `StorageLocationType` — an addon-declared id that identifies the *kind* of
|
|
7328
7427
|
* storage a location serves. Defined here (not in `capabilities/storage.cap.ts`)
|
|
7329
7428
|
* so the persisted record schema and the consumer-facing cap can both consume it
|
|
@@ -14679,7 +14778,11 @@ array(ZoneRuleSchema).readonly();
|
|
|
14679
14778
|
* Extend the enum here when a new gating consumer comes online (audio
|
|
14680
14779
|
* gating, alert filtering, …) — no other surface needs to change.
|
|
14681
14780
|
*/
|
|
14682
|
-
var ZoneRuleStageEnum = _enum([
|
|
14781
|
+
var ZoneRuleStageEnum = _enum([
|
|
14782
|
+
"motion",
|
|
14783
|
+
"detection",
|
|
14784
|
+
"package"
|
|
14785
|
+
]);
|
|
14683
14786
|
/**
|
|
14684
14787
|
* Runtime registry: cap-property-name → cap definition. `BaseDevice`'s
|
|
14685
14788
|
* `state` getter looks up the cap definition here to construct a
|
|
@@ -14773,16 +14876,25 @@ var DEVICE_LOCAL_STATE_CAPS = {
|
|
|
14773
14876
|
})
|
|
14774
14877
|
},
|
|
14775
14878
|
/**
|
|
14776
|
-
* Runtime-state slice —
|
|
14879
|
+
* Runtime-state slice — every stage mirrored together so consumers
|
|
14777
14880
|
* see one reactive handle (`device.state.zoneRules.value`) instead
|
|
14778
|
-
* of
|
|
14779
|
-
* `{motion, detection}` shape, so subscribers always get the
|
|
14881
|
+
* of one per stage. Bulk-replace mutations on any stage write the full
|
|
14882
|
+
* `{motion, detection, package}` shape, so subscribers always get the
|
|
14780
14883
|
* complete current set. Consumers that only care about one stage
|
|
14781
14884
|
* just read the matching property.
|
|
14885
|
+
*
|
|
14886
|
+
* `package` backs the package-drop detector — a package zone is a
|
|
14887
|
+
* `ZoneRule` on the `'package'` stage referencing drawn polygons
|
|
14888
|
+
* (see docs/superpowers/specs/2026-07-17-package-zones-design.md §3.1).
|
|
14889
|
+
* The orchestrator provider writes this stage as a first-class slice
|
|
14890
|
+
* (Phase 4): every mutation mirrors the full `{motion, detection,
|
|
14891
|
+
* package}` shape, so consumers read the current package rules directly
|
|
14892
|
+
* off `device.state.zoneRules.value.package`.
|
|
14782
14893
|
*/
|
|
14783
14894
|
runtimeState: object({
|
|
14784
14895
|
motion: array(ZoneRuleSchema).readonly(),
|
|
14785
|
-
detection: array(ZoneRuleSchema).readonly()
|
|
14896
|
+
detection: array(ZoneRuleSchema).readonly(),
|
|
14897
|
+
package: array(ZoneRuleSchema).readonly()
|
|
14786
14898
|
})
|
|
14787
14899
|
},
|
|
14788
14900
|
zones: zonesCapability
|
|
@@ -18810,6 +18922,7 @@ var EventKindIconSchema = _enum([
|
|
|
18810
18922
|
"smoke",
|
|
18811
18923
|
"water",
|
|
18812
18924
|
"button",
|
|
18925
|
+
"package",
|
|
18813
18926
|
"generic"
|
|
18814
18927
|
]);
|
|
18815
18928
|
var EventKindCategorySchema = _enum([
|
|
@@ -18817,7 +18930,8 @@ var EventKindCategorySchema = _enum([
|
|
|
18817
18930
|
"audio",
|
|
18818
18931
|
"detection",
|
|
18819
18932
|
"sensor",
|
|
18820
|
-
"custom"
|
|
18933
|
+
"custom",
|
|
18934
|
+
"package"
|
|
18821
18935
|
]);
|
|
18822
18936
|
var EventKindDescriptorSchema = object({
|
|
18823
18937
|
/** Stable kind id (e.g. 'motion', 'person', 'contact'). */
|
|
@@ -19158,6 +19272,26 @@ var TrackCascadeCountsSchema = object({
|
|
|
19158
19272
|
/** Per-track CLIP search vectors removed (best-effort). */
|
|
19159
19273
|
embeddings: number().int()
|
|
19160
19274
|
});
|
|
19275
|
+
/** Event-store footprint for one camera. */
|
|
19276
|
+
var EventStoreDeviceFootprintSchema = object({
|
|
19277
|
+
deviceId: number(),
|
|
19278
|
+
/** Persisted event rows (motion + object + audio) for the camera. */
|
|
19279
|
+
rows: number().int(),
|
|
19280
|
+
/** Event-owned media bytes on disk for the camera. */
|
|
19281
|
+
bytes: number().int()
|
|
19282
|
+
});
|
|
19283
|
+
/** Aggregate event-store footprint: global totals + per-camera breakdown. */
|
|
19284
|
+
var EventStoreFootprintSchema = object({
|
|
19285
|
+
totalRows: number().int(),
|
|
19286
|
+
totalBytes: number().int(),
|
|
19287
|
+
devices: array(EventStoreDeviceFootprintSchema).readonly()
|
|
19288
|
+
});
|
|
19289
|
+
/** Per-kind counts returned by the event-prune / device-delete mutations. */
|
|
19290
|
+
var EventPruneCountsSchema = object({
|
|
19291
|
+
motion: number().int(),
|
|
19292
|
+
object: number().int(),
|
|
19293
|
+
audio: number().int()
|
|
19294
|
+
});
|
|
19161
19295
|
DeviceType.Camera, method(object({ deviceId: number() }), array(TrackSchema).readonly()), method(object({
|
|
19162
19296
|
deviceId: number(),
|
|
19163
19297
|
trackId: string()
|
|
@@ -19221,6 +19355,21 @@ DeviceType.Camera, method(object({ deviceId: number() }), array(TrackSchema).rea
|
|
|
19221
19355
|
}), {
|
|
19222
19356
|
kind: "mutation",
|
|
19223
19357
|
auth: "admin"
|
|
19358
|
+
}), method(object({}), EventStoreFootprintSchema, {
|
|
19359
|
+
kind: "query",
|
|
19360
|
+
auth: "admin"
|
|
19361
|
+
}), method(object({
|
|
19362
|
+
olderThanMs: number(),
|
|
19363
|
+
reason: OpsLogReasonSchema.optional()
|
|
19364
|
+
}), EventPruneCountsSchema, {
|
|
19365
|
+
kind: "mutation",
|
|
19366
|
+
auth: "admin"
|
|
19367
|
+
}), method(object({ deviceId: number() }), EventPruneCountsSchema, {
|
|
19368
|
+
kind: "mutation",
|
|
19369
|
+
auth: "admin"
|
|
19370
|
+
}), method(OpsLogQueryInputSchema, array(OpsLogEntrySchema).readonly(), {
|
|
19371
|
+
kind: "query",
|
|
19372
|
+
auth: "admin"
|
|
19224
19373
|
}), method(object({
|
|
19225
19374
|
eventId: string(),
|
|
19226
19375
|
kind: MediaFileKindEnum.optional()
|
|
@@ -22454,13 +22603,131 @@ method(object({
|
|
|
22454
22603
|
}), method(object({ deviceId: number() }), RecordingStatusSchema, {
|
|
22455
22604
|
kind: "mutation",
|
|
22456
22605
|
auth: "admin"
|
|
22457
|
-
}), method(object({
|
|
22606
|
+
}), method(object({
|
|
22607
|
+
deviceId: number(),
|
|
22608
|
+
reason: OpsLogReasonSchema.optional()
|
|
22609
|
+
}), object({
|
|
22458
22610
|
floorMs: number().nullable(),
|
|
22459
22611
|
deletedBuckets: number().int(),
|
|
22460
22612
|
reclaimedBytes: number().int()
|
|
22461
22613
|
}), {
|
|
22462
22614
|
kind: "mutation",
|
|
22463
22615
|
auth: "admin"
|
|
22616
|
+
}), method(object({
|
|
22617
|
+
deviceId: number(),
|
|
22618
|
+
fromMs: number().optional(),
|
|
22619
|
+
toMs: number().optional()
|
|
22620
|
+
}), object({
|
|
22621
|
+
deletedBuckets: number().int(),
|
|
22622
|
+
reclaimedBytes: number().int()
|
|
22623
|
+
}), {
|
|
22624
|
+
kind: "mutation",
|
|
22625
|
+
auth: "admin"
|
|
22626
|
+
}), method(OpsLogQueryInputSchema, array(OpsLogEntrySchema).readonly(), {
|
|
22627
|
+
kind: "query",
|
|
22628
|
+
auth: "admin"
|
|
22629
|
+
});
|
|
22630
|
+
/**
|
|
22631
|
+
* `recordingExport` cap — render a footage time range into a single downloadable
|
|
22632
|
+
* MP4 (regular / accelerated / decelerated / timelapse, ± audio), kept for a
|
|
22633
|
+
* bounded lifetime with a durable history, auto-expiry, and optional
|
|
22634
|
+
* delete-after-download.
|
|
22635
|
+
*
|
|
22636
|
+
* Like `recording` this is a `scope:'system', mode:'singleton'` cap: the
|
|
22637
|
+
* recorder self-gates so exactly ONE node (the designated `recordingNodeId`,
|
|
22638
|
+
* default `hub`) registers it. Device-scoped methods carry `deviceId` in their
|
|
22639
|
+
* input and dispatch to that single provider; the render runs on the node that
|
|
22640
|
+
* owns the footage (no cross-node segment transfer). Download rides the
|
|
22641
|
+
* framework addon data-plane. State persists in a DurableState blob (NOT
|
|
22642
|
+
* SQLite); history rows survive file deletion for audit.
|
|
22643
|
+
*/
|
|
22644
|
+
/** Playback-speed multiplier for the render (1 = realtime). */
|
|
22645
|
+
var ExportSpeedSchema = number().min(.25).max(32);
|
|
22646
|
+
/** Timelapse cadence — sample one source frame per `everyMs`, output at `outputFps`. */
|
|
22647
|
+
var ExportTimelapseSchema = object({
|
|
22648
|
+
everyMs: number().int().positive(),
|
|
22649
|
+
outputFps: number().int().min(1).max(60).optional()
|
|
22650
|
+
});
|
|
22651
|
+
/**
|
|
22652
|
+
* Render options. `speed` and `timelapse` are mutually exclusive. `includeAudio`
|
|
22653
|
+
* is honoured only for a realtime-ish speed (0.5–2×); timelapse is always
|
|
22654
|
+
* silent. `maxLifeMs` bounds how long the finished file is kept;
|
|
22655
|
+
* `deleteAfterDownload` removes it shortly after the first complete download.
|
|
22656
|
+
*/
|
|
22657
|
+
var ExportOptionsSchema = object({
|
|
22658
|
+
speed: ExportSpeedSchema.optional(),
|
|
22659
|
+
timelapse: ExportTimelapseSchema.optional(),
|
|
22660
|
+
includeAudio: boolean(),
|
|
22661
|
+
maxLifeMs: number().int().positive(),
|
|
22662
|
+
deleteAfterDownload: boolean(),
|
|
22663
|
+
title: string().max(200).optional()
|
|
22664
|
+
}).superRefine((v, ctx) => {
|
|
22665
|
+
if (v.speed !== void 0 && v.timelapse !== void 0) ctx.addIssue({
|
|
22666
|
+
code: ZodIssueCode.custom,
|
|
22667
|
+
message: "speed and timelapse are mutually exclusive",
|
|
22668
|
+
path: ["timelapse"]
|
|
22669
|
+
});
|
|
22670
|
+
});
|
|
22671
|
+
var ExportStateSchema = _enum([
|
|
22672
|
+
"queued",
|
|
22673
|
+
"rendering",
|
|
22674
|
+
"ready",
|
|
22675
|
+
"failed",
|
|
22676
|
+
"expired",
|
|
22677
|
+
"deleted"
|
|
22678
|
+
]);
|
|
22679
|
+
/** One export job / history row. */
|
|
22680
|
+
var ExportRecordSchema = object({
|
|
22681
|
+
id: string(),
|
|
22682
|
+
deviceId: number(),
|
|
22683
|
+
profile: string(),
|
|
22684
|
+
fromMs: number(),
|
|
22685
|
+
toMs: number(),
|
|
22686
|
+
options: ExportOptionsSchema,
|
|
22687
|
+
state: ExportStateSchema,
|
|
22688
|
+
/** 0–100 while rendering; null otherwise. */
|
|
22689
|
+
progressPct: number().nullable(),
|
|
22690
|
+
/** File size once ready; null before. */
|
|
22691
|
+
fileBytes: number().nullable(),
|
|
22692
|
+
expiresAt: number(),
|
|
22693
|
+
deleteAfterDownload: boolean(),
|
|
22694
|
+
/** Epoch of the first complete download; null until then. */
|
|
22695
|
+
downloadedAt: number().nullable(),
|
|
22696
|
+
createdAt: number(),
|
|
22697
|
+
/** User id/name that requested the export. */
|
|
22698
|
+
createdBy: string(),
|
|
22699
|
+
/** Failure reason when state is 'failed'; null otherwise. */
|
|
22700
|
+
error: string().nullable()
|
|
22701
|
+
});
|
|
22702
|
+
/** Candidate download URLs (LAN first, then operator extra hosts). */
|
|
22703
|
+
var ExportDownloadSchema = object({
|
|
22704
|
+
url: string(),
|
|
22705
|
+
endpoints: array(string())
|
|
22706
|
+
});
|
|
22707
|
+
method(object({
|
|
22708
|
+
deviceId: number(),
|
|
22709
|
+
profile: string(),
|
|
22710
|
+
fromMs: number(),
|
|
22711
|
+
toMs: number(),
|
|
22712
|
+
options: ExportOptionsSchema
|
|
22713
|
+
}), ExportRecordSchema, {
|
|
22714
|
+
kind: "mutation",
|
|
22715
|
+
auth: "protected"
|
|
22716
|
+
}), method(object({ deviceId: number().optional() }), array(ExportRecordSchema), {
|
|
22717
|
+
kind: "query",
|
|
22718
|
+
auth: "protected"
|
|
22719
|
+
}), method(object({ exportId: string() }), ExportRecordSchema, {
|
|
22720
|
+
kind: "query",
|
|
22721
|
+
auth: "protected"
|
|
22722
|
+
}), method(object({ exportId: string() }), ExportRecordSchema, {
|
|
22723
|
+
kind: "mutation",
|
|
22724
|
+
auth: "protected"
|
|
22725
|
+
}), method(object({ exportId: string() }), ExportRecordSchema, {
|
|
22726
|
+
kind: "mutation",
|
|
22727
|
+
auth: "protected"
|
|
22728
|
+
}), method(object({ exportId: string() }), ExportDownloadSchema, {
|
|
22729
|
+
kind: "query",
|
|
22730
|
+
auth: "protected"
|
|
22464
22731
|
});
|
|
22465
22732
|
/**
|
|
22466
22733
|
* One publishable camera stream as its OWNING PROVIDER describes it — the same
|
|
@@ -25480,6 +25747,12 @@ Object.freeze({
|
|
|
25480
25747
|
addonId: null,
|
|
25481
25748
|
access: "delete"
|
|
25482
25749
|
},
|
|
25750
|
+
"pipelineAnalytics.deleteDeviceEvents": {
|
|
25751
|
+
capName: "pipeline-analytics",
|
|
25752
|
+
capScope: "device",
|
|
25753
|
+
addonId: null,
|
|
25754
|
+
access: "delete"
|
|
25755
|
+
},
|
|
25483
25756
|
"pipelineAnalytics.deleteTracks": {
|
|
25484
25757
|
capName: "pipeline-analytics",
|
|
25485
25758
|
capScope: "device",
|
|
@@ -25510,6 +25783,12 @@ Object.freeze({
|
|
|
25510
25783
|
addonId: null,
|
|
25511
25784
|
access: "view"
|
|
25512
25785
|
},
|
|
25786
|
+
"pipelineAnalytics.getEventStoreFootprint": {
|
|
25787
|
+
capName: "pipeline-analytics",
|
|
25788
|
+
capScope: "device",
|
|
25789
|
+
addonId: null,
|
|
25790
|
+
access: "view"
|
|
25791
|
+
},
|
|
25513
25792
|
"pipelineAnalytics.getKeyEvents": {
|
|
25514
25793
|
capName: "pipeline-analytics",
|
|
25515
25794
|
capScope: "device",
|
|
@@ -25552,6 +25831,12 @@ Object.freeze({
|
|
|
25552
25831
|
addonId: null,
|
|
25553
25832
|
access: "view"
|
|
25554
25833
|
},
|
|
25834
|
+
"pipelineAnalytics.listOpsLog": {
|
|
25835
|
+
capName: "pipeline-analytics",
|
|
25836
|
+
capScope: "device",
|
|
25837
|
+
addonId: null,
|
|
25838
|
+
access: "view"
|
|
25839
|
+
},
|
|
25555
25840
|
"pipelineAnalytics.listRecentTracks": {
|
|
25556
25841
|
capName: "pipeline-analytics",
|
|
25557
25842
|
capScope: "device",
|
|
@@ -25564,6 +25849,12 @@ Object.freeze({
|
|
|
25564
25849
|
addonId: null,
|
|
25565
25850
|
access: "view"
|
|
25566
25851
|
},
|
|
25852
|
+
"pipelineAnalytics.pruneEvents": {
|
|
25853
|
+
capName: "pipeline-analytics",
|
|
25854
|
+
capScope: "device",
|
|
25855
|
+
addonId: null,
|
|
25856
|
+
access: "create"
|
|
25857
|
+
},
|
|
25567
25858
|
"pipelineAnalytics.pruneEventsBefore": {
|
|
25568
25859
|
capName: "pipeline-analytics",
|
|
25569
25860
|
capScope: "device",
|
|
@@ -26326,6 +26617,12 @@ Object.freeze({
|
|
|
26326
26617
|
addonId: null,
|
|
26327
26618
|
access: "create"
|
|
26328
26619
|
},
|
|
26620
|
+
"recording.deleteFootprint": {
|
|
26621
|
+
capName: "recording",
|
|
26622
|
+
capScope: "system",
|
|
26623
|
+
addonId: null,
|
|
26624
|
+
access: "delete"
|
|
26625
|
+
},
|
|
26329
26626
|
"recording.getAvailability": {
|
|
26330
26627
|
capName: "recording",
|
|
26331
26628
|
capScope: "system",
|
|
@@ -26356,6 +26653,12 @@ Object.freeze({
|
|
|
26356
26653
|
addonId: null,
|
|
26357
26654
|
access: "view"
|
|
26358
26655
|
},
|
|
26656
|
+
"recording.listOpsLog": {
|
|
26657
|
+
capName: "recording",
|
|
26658
|
+
capScope: "system",
|
|
26659
|
+
addonId: null,
|
|
26660
|
+
access: "view"
|
|
26661
|
+
},
|
|
26359
26662
|
"recording.locateSegment": {
|
|
26360
26663
|
capName: "recording",
|
|
26361
26664
|
capScope: "system",
|
|
@@ -26386,6 +26689,42 @@ Object.freeze({
|
|
|
26386
26689
|
addonId: null,
|
|
26387
26690
|
access: "create"
|
|
26388
26691
|
},
|
|
26692
|
+
"recordingExport.cancelExport": {
|
|
26693
|
+
capName: "recordingExport",
|
|
26694
|
+
capScope: "system",
|
|
26695
|
+
addonId: null,
|
|
26696
|
+
access: "create"
|
|
26697
|
+
},
|
|
26698
|
+
"recordingExport.createExport": {
|
|
26699
|
+
capName: "recordingExport",
|
|
26700
|
+
capScope: "system",
|
|
26701
|
+
addonId: null,
|
|
26702
|
+
access: "create"
|
|
26703
|
+
},
|
|
26704
|
+
"recordingExport.deleteExport": {
|
|
26705
|
+
capName: "recordingExport",
|
|
26706
|
+
capScope: "system",
|
|
26707
|
+
addonId: null,
|
|
26708
|
+
access: "delete"
|
|
26709
|
+
},
|
|
26710
|
+
"recordingExport.getDownloadUrl": {
|
|
26711
|
+
capName: "recordingExport",
|
|
26712
|
+
capScope: "system",
|
|
26713
|
+
addonId: null,
|
|
26714
|
+
access: "view"
|
|
26715
|
+
},
|
|
26716
|
+
"recordingExport.getExport": {
|
|
26717
|
+
capName: "recordingExport",
|
|
26718
|
+
capScope: "system",
|
|
26719
|
+
addonId: null,
|
|
26720
|
+
access: "view"
|
|
26721
|
+
},
|
|
26722
|
+
"recordingExport.listExports": {
|
|
26723
|
+
capName: "recordingExport",
|
|
26724
|
+
capScope: "system",
|
|
26725
|
+
addonId: null,
|
|
26726
|
+
access: "view"
|
|
26727
|
+
},
|
|
26389
26728
|
"sceneMonitor.captureReference": {
|
|
26390
26729
|
capName: "scene-monitor",
|
|
26391
26730
|
capScope: "device",
|
package/dist/addon.mjs
CHANGED
|
@@ -9,7 +9,7 @@ import { join } from "path";
|
|
|
9
9
|
var __commonJSMin = (cb, mod) => () => (mod || (cb((mod = { exports: {} }).exports, mod), cb = null), mod.exports);
|
|
10
10
|
var __require = /* @__PURE__ */ createRequire(import.meta.url);
|
|
11
11
|
//#endregion
|
|
12
|
-
//#region ../types/dist/event-category-
|
|
12
|
+
//#region ../types/dist/event-category-D4HJq7Mw.mjs
|
|
13
13
|
var EventCategory = /* @__PURE__ */ function(EventCategory) {
|
|
14
14
|
EventCategory["SystemBoot"] = "system.boot";
|
|
15
15
|
EventCategory["SystemAddonsReady"] = "system.addons-ready";
|
|
@@ -162,6 +162,11 @@ var EventCategory = /* @__PURE__ */ function(EventCategory) {
|
|
|
162
162
|
/** Runner-sampled scrub thumbnail (~1/5 s/camera). Telemetry (D8): a lost
|
|
163
163
|
* thumb is a scrub gap the recorder's keyframe backfill covers. */
|
|
164
164
|
EventCategory["RecordingThumbSampled"] = "recording.thumb-sampled";
|
|
165
|
+
/** Export render progress (0–100). Telemetry (D8): a lost tick is a stale
|
|
166
|
+
* progress bar the client reconciles via `recordingExport.getExport`. */
|
|
167
|
+
EventCategory["RecordingExportProgress"] = "recording.export.progress";
|
|
168
|
+
EventCategory["RecordingExportCompleted"] = "recording.export.completed";
|
|
169
|
+
EventCategory["RecordingExportFailed"] = "recording.export.failed";
|
|
165
170
|
EventCategory["DetectionEvent"] = "detection.event";
|
|
166
171
|
EventCategory["SessionTrackNew"] = "session.track.new";
|
|
167
172
|
EventCategory["SessionTrackExpired"] = "session.track.expired";
|
|
@@ -451,6 +456,25 @@ var EventCategory = /* @__PURE__ */ function(EventCategory) {
|
|
|
451
456
|
*/
|
|
452
457
|
EventCategory["PipelineAnalyticsStationaryChanged"] = "pipeline-analytics.stationary-changed";
|
|
453
458
|
/**
|
|
459
|
+
* Fired by `addon-post-analysis` when a package-drop is confirmed inside
|
|
460
|
+
* a package zone — a newly-appeared stationary object of a package class
|
|
461
|
+
* that cleared the class / zone / dwell / size gates. Payload:
|
|
462
|
+
* `PipelineAnalyticsPackageDeliveredPayload` carrying `{ deviceId,
|
|
463
|
+
* entryId, className, zoneIds, keyFrameMediaKey?, bbox, timestamp }`.
|
|
464
|
+
* Telemetry (D8): the durable record is the `package-events` store row;
|
|
465
|
+
* this bus topic drives notifier rules + live UI. See
|
|
466
|
+
* docs/superpowers/specs/2026-07-17-package-zones-design.md §5.1.
|
|
467
|
+
*/
|
|
468
|
+
EventCategory["PipelineAnalyticsPackageDelivered"] = "pipeline-analytics.package-delivered";
|
|
469
|
+
/**
|
|
470
|
+
* Fired by `addon-post-analysis` when a previously-delivered package
|
|
471
|
+
* leaves its zone (the stationary entry departed — moved or swept).
|
|
472
|
+
* Payload: `PipelineAnalyticsPackagePickedUpPayload` carrying
|
|
473
|
+
* `{ deviceId, entryId, deliveredEventId, className, timestamp }`.
|
|
474
|
+
* Telemetry (D8). See package-zones-design §5.2.
|
|
475
|
+
*/
|
|
476
|
+
EventCategory["PipelineAnalyticsPackagePickedUp"] = "pipeline-analytics.package-picked-up";
|
|
477
|
+
/**
|
|
454
478
|
* Fired by `addon-post-analysis` whenever a gallery face row changes:
|
|
455
479
|
* `kind:'buffered'` a new detected face was persisted, `'assigned'` /
|
|
456
480
|
* `'unassigned'` its identity link changed, `'deleted'` the row was
|
|
@@ -5203,6 +5227,25 @@ function preprocess(fn, schema) {
|
|
|
5203
5227
|
out: schema
|
|
5204
5228
|
});
|
|
5205
5229
|
}
|
|
5230
|
+
//#endregion
|
|
5231
|
+
//#region ../../node_modules/zod/v4/classic/compat.js
|
|
5232
|
+
/** @deprecated Use the raw string literal codes instead, e.g. "invalid_type". */
|
|
5233
|
+
var ZodIssueCode = {
|
|
5234
|
+
invalid_type: "invalid_type",
|
|
5235
|
+
too_big: "too_big",
|
|
5236
|
+
too_small: "too_small",
|
|
5237
|
+
invalid_format: "invalid_format",
|
|
5238
|
+
not_multiple_of: "not_multiple_of",
|
|
5239
|
+
unrecognized_keys: "unrecognized_keys",
|
|
5240
|
+
invalid_union: "invalid_union",
|
|
5241
|
+
invalid_key: "invalid_key",
|
|
5242
|
+
invalid_element: "invalid_element",
|
|
5243
|
+
invalid_value: "invalid_value",
|
|
5244
|
+
custom: "custom"
|
|
5245
|
+
};
|
|
5246
|
+
/** @deprecated Do not use. Stub definition, only included for zod-to-json-schema compatibility. */
|
|
5247
|
+
var ZodFirstPartyTypeKind;
|
|
5248
|
+
ZodFirstPartyTypeKind || (ZodFirstPartyTypeKind = {});
|
|
5206
5249
|
Object.fromEntries([
|
|
5207
5250
|
{
|
|
5208
5251
|
id: "overview",
|
|
@@ -7325,6 +7368,62 @@ var RecordingConfigSchema = object({
|
|
|
7325
7368
|
scrubThumbnails: ScrubThumbnailPresetSchema.optional()
|
|
7326
7369
|
});
|
|
7327
7370
|
/**
|
|
7371
|
+
* Ops-log — the durable, append-only operations audit shared by the
|
|
7372
|
+
* recordings and events management surfaces.
|
|
7373
|
+
*
|
|
7374
|
+
* ONE row shape is reused for both domains so a single "Activity" view can
|
|
7375
|
+
* merge the recorder's DurableState ring (recordings ops-log) and the
|
|
7376
|
+
* pipeline-analytics SQLite collection (events ops-log). Each row records a
|
|
7377
|
+
* management operation, WHY it ran (reason), and its measurable effect
|
|
7378
|
+
* (itemsAffected + bytesReclaimed). Writes are best-effort — a failed log must
|
|
7379
|
+
* never fail the operation it records.
|
|
7380
|
+
*/
|
|
7381
|
+
/** Which management domain the operation belongs to. */
|
|
7382
|
+
var OpsLogDomainSchema = _enum(["recording", "events"]);
|
|
7383
|
+
/** The kind of management operation performed. */
|
|
7384
|
+
var OpsLogOpSchema = _enum([
|
|
7385
|
+
"prune",
|
|
7386
|
+
"manual-delete",
|
|
7387
|
+
"rescan",
|
|
7388
|
+
"retention-run"
|
|
7389
|
+
]);
|
|
7390
|
+
/** Why the operation ran. */
|
|
7391
|
+
var OpsLogReasonSchema = _enum([
|
|
7392
|
+
"retention",
|
|
7393
|
+
"quota",
|
|
7394
|
+
"manual",
|
|
7395
|
+
"operator"
|
|
7396
|
+
]);
|
|
7397
|
+
/** One audit row, shared verbatim by both domains. */
|
|
7398
|
+
var OpsLogEntrySchema = object({
|
|
7399
|
+
/** Unique row id. */
|
|
7400
|
+
id: string(),
|
|
7401
|
+
/** Epoch ms the operation completed. */
|
|
7402
|
+
at: number(),
|
|
7403
|
+
domain: OpsLogDomainSchema,
|
|
7404
|
+
op: OpsLogOpSchema,
|
|
7405
|
+
reason: OpsLogReasonSchema,
|
|
7406
|
+
/** The camera the op targeted; null for a cluster/global op. */
|
|
7407
|
+
deviceId: number().nullable(),
|
|
7408
|
+
/** Node that performed the op (the log carries nodeId — no cross-node aggregation). */
|
|
7409
|
+
nodeId: string(),
|
|
7410
|
+
/** Buckets / rows deleted (op-specific unit). */
|
|
7411
|
+
itemsAffected: number(),
|
|
7412
|
+
/** Bytes reclaimed by the op (0 when not measurable). */
|
|
7413
|
+
bytesReclaimed: number(),
|
|
7414
|
+
/** Free-text detail (e.g. "floor moved to <ts>"); null when none. */
|
|
7415
|
+
detail: string().nullable(),
|
|
7416
|
+
/** Who/what triggered the op. */
|
|
7417
|
+
actor: string()
|
|
7418
|
+
});
|
|
7419
|
+
/** Shared query input for the per-domain `listOpsLog` cap methods. */
|
|
7420
|
+
var OpsLogQueryInputSchema = object({
|
|
7421
|
+
/** Restrict to a single camera; omit for every row. */
|
|
7422
|
+
deviceId: number().optional(),
|
|
7423
|
+
/** Max rows returned, newest-first. */
|
|
7424
|
+
limit: number().int().min(1).max(1e3).optional()
|
|
7425
|
+
});
|
|
7426
|
+
/**
|
|
7328
7427
|
* `StorageLocationType` — an addon-declared id that identifies the *kind* of
|
|
7329
7428
|
* storage a location serves. Defined here (not in `capabilities/storage.cap.ts`)
|
|
7330
7429
|
* so the persisted record schema and the consumer-facing cap can both consume it
|
|
@@ -14680,7 +14779,11 @@ array(ZoneRuleSchema).readonly();
|
|
|
14680
14779
|
* Extend the enum here when a new gating consumer comes online (audio
|
|
14681
14780
|
* gating, alert filtering, …) — no other surface needs to change.
|
|
14682
14781
|
*/
|
|
14683
|
-
var ZoneRuleStageEnum = _enum([
|
|
14782
|
+
var ZoneRuleStageEnum = _enum([
|
|
14783
|
+
"motion",
|
|
14784
|
+
"detection",
|
|
14785
|
+
"package"
|
|
14786
|
+
]);
|
|
14684
14787
|
/**
|
|
14685
14788
|
* Runtime registry: cap-property-name → cap definition. `BaseDevice`'s
|
|
14686
14789
|
* `state` getter looks up the cap definition here to construct a
|
|
@@ -14774,16 +14877,25 @@ var DEVICE_LOCAL_STATE_CAPS = {
|
|
|
14774
14877
|
})
|
|
14775
14878
|
},
|
|
14776
14879
|
/**
|
|
14777
|
-
* Runtime-state slice —
|
|
14880
|
+
* Runtime-state slice — every stage mirrored together so consumers
|
|
14778
14881
|
* see one reactive handle (`device.state.zoneRules.value`) instead
|
|
14779
|
-
* of
|
|
14780
|
-
* `{motion, detection}` shape, so subscribers always get the
|
|
14882
|
+
* of one per stage. Bulk-replace mutations on any stage write the full
|
|
14883
|
+
* `{motion, detection, package}` shape, so subscribers always get the
|
|
14781
14884
|
* complete current set. Consumers that only care about one stage
|
|
14782
14885
|
* just read the matching property.
|
|
14886
|
+
*
|
|
14887
|
+
* `package` backs the package-drop detector — a package zone is a
|
|
14888
|
+
* `ZoneRule` on the `'package'` stage referencing drawn polygons
|
|
14889
|
+
* (see docs/superpowers/specs/2026-07-17-package-zones-design.md §3.1).
|
|
14890
|
+
* The orchestrator provider writes this stage as a first-class slice
|
|
14891
|
+
* (Phase 4): every mutation mirrors the full `{motion, detection,
|
|
14892
|
+
* package}` shape, so consumers read the current package rules directly
|
|
14893
|
+
* off `device.state.zoneRules.value.package`.
|
|
14783
14894
|
*/
|
|
14784
14895
|
runtimeState: object({
|
|
14785
14896
|
motion: array(ZoneRuleSchema).readonly(),
|
|
14786
|
-
detection: array(ZoneRuleSchema).readonly()
|
|
14897
|
+
detection: array(ZoneRuleSchema).readonly(),
|
|
14898
|
+
package: array(ZoneRuleSchema).readonly()
|
|
14787
14899
|
})
|
|
14788
14900
|
},
|
|
14789
14901
|
zones: zonesCapability
|
|
@@ -18811,6 +18923,7 @@ var EventKindIconSchema = _enum([
|
|
|
18811
18923
|
"smoke",
|
|
18812
18924
|
"water",
|
|
18813
18925
|
"button",
|
|
18926
|
+
"package",
|
|
18814
18927
|
"generic"
|
|
18815
18928
|
]);
|
|
18816
18929
|
var EventKindCategorySchema = _enum([
|
|
@@ -18818,7 +18931,8 @@ var EventKindCategorySchema = _enum([
|
|
|
18818
18931
|
"audio",
|
|
18819
18932
|
"detection",
|
|
18820
18933
|
"sensor",
|
|
18821
|
-
"custom"
|
|
18934
|
+
"custom",
|
|
18935
|
+
"package"
|
|
18822
18936
|
]);
|
|
18823
18937
|
var EventKindDescriptorSchema = object({
|
|
18824
18938
|
/** Stable kind id (e.g. 'motion', 'person', 'contact'). */
|
|
@@ -19159,6 +19273,26 @@ var TrackCascadeCountsSchema = object({
|
|
|
19159
19273
|
/** Per-track CLIP search vectors removed (best-effort). */
|
|
19160
19274
|
embeddings: number().int()
|
|
19161
19275
|
});
|
|
19276
|
+
/** Event-store footprint for one camera. */
|
|
19277
|
+
var EventStoreDeviceFootprintSchema = object({
|
|
19278
|
+
deviceId: number(),
|
|
19279
|
+
/** Persisted event rows (motion + object + audio) for the camera. */
|
|
19280
|
+
rows: number().int(),
|
|
19281
|
+
/** Event-owned media bytes on disk for the camera. */
|
|
19282
|
+
bytes: number().int()
|
|
19283
|
+
});
|
|
19284
|
+
/** Aggregate event-store footprint: global totals + per-camera breakdown. */
|
|
19285
|
+
var EventStoreFootprintSchema = object({
|
|
19286
|
+
totalRows: number().int(),
|
|
19287
|
+
totalBytes: number().int(),
|
|
19288
|
+
devices: array(EventStoreDeviceFootprintSchema).readonly()
|
|
19289
|
+
});
|
|
19290
|
+
/** Per-kind counts returned by the event-prune / device-delete mutations. */
|
|
19291
|
+
var EventPruneCountsSchema = object({
|
|
19292
|
+
motion: number().int(),
|
|
19293
|
+
object: number().int(),
|
|
19294
|
+
audio: number().int()
|
|
19295
|
+
});
|
|
19162
19296
|
DeviceType.Camera, method(object({ deviceId: number() }), array(TrackSchema).readonly()), method(object({
|
|
19163
19297
|
deviceId: number(),
|
|
19164
19298
|
trackId: string()
|
|
@@ -19222,6 +19356,21 @@ DeviceType.Camera, method(object({ deviceId: number() }), array(TrackSchema).rea
|
|
|
19222
19356
|
}), {
|
|
19223
19357
|
kind: "mutation",
|
|
19224
19358
|
auth: "admin"
|
|
19359
|
+
}), method(object({}), EventStoreFootprintSchema, {
|
|
19360
|
+
kind: "query",
|
|
19361
|
+
auth: "admin"
|
|
19362
|
+
}), method(object({
|
|
19363
|
+
olderThanMs: number(),
|
|
19364
|
+
reason: OpsLogReasonSchema.optional()
|
|
19365
|
+
}), EventPruneCountsSchema, {
|
|
19366
|
+
kind: "mutation",
|
|
19367
|
+
auth: "admin"
|
|
19368
|
+
}), method(object({ deviceId: number() }), EventPruneCountsSchema, {
|
|
19369
|
+
kind: "mutation",
|
|
19370
|
+
auth: "admin"
|
|
19371
|
+
}), method(OpsLogQueryInputSchema, array(OpsLogEntrySchema).readonly(), {
|
|
19372
|
+
kind: "query",
|
|
19373
|
+
auth: "admin"
|
|
19225
19374
|
}), method(object({
|
|
19226
19375
|
eventId: string(),
|
|
19227
19376
|
kind: MediaFileKindEnum.optional()
|
|
@@ -22455,13 +22604,131 @@ method(object({
|
|
|
22455
22604
|
}), method(object({ deviceId: number() }), RecordingStatusSchema, {
|
|
22456
22605
|
kind: "mutation",
|
|
22457
22606
|
auth: "admin"
|
|
22458
|
-
}), method(object({
|
|
22607
|
+
}), method(object({
|
|
22608
|
+
deviceId: number(),
|
|
22609
|
+
reason: OpsLogReasonSchema.optional()
|
|
22610
|
+
}), object({
|
|
22459
22611
|
floorMs: number().nullable(),
|
|
22460
22612
|
deletedBuckets: number().int(),
|
|
22461
22613
|
reclaimedBytes: number().int()
|
|
22462
22614
|
}), {
|
|
22463
22615
|
kind: "mutation",
|
|
22464
22616
|
auth: "admin"
|
|
22617
|
+
}), method(object({
|
|
22618
|
+
deviceId: number(),
|
|
22619
|
+
fromMs: number().optional(),
|
|
22620
|
+
toMs: number().optional()
|
|
22621
|
+
}), object({
|
|
22622
|
+
deletedBuckets: number().int(),
|
|
22623
|
+
reclaimedBytes: number().int()
|
|
22624
|
+
}), {
|
|
22625
|
+
kind: "mutation",
|
|
22626
|
+
auth: "admin"
|
|
22627
|
+
}), method(OpsLogQueryInputSchema, array(OpsLogEntrySchema).readonly(), {
|
|
22628
|
+
kind: "query",
|
|
22629
|
+
auth: "admin"
|
|
22630
|
+
});
|
|
22631
|
+
/**
|
|
22632
|
+
* `recordingExport` cap — render a footage time range into a single downloadable
|
|
22633
|
+
* MP4 (regular / accelerated / decelerated / timelapse, ± audio), kept for a
|
|
22634
|
+
* bounded lifetime with a durable history, auto-expiry, and optional
|
|
22635
|
+
* delete-after-download.
|
|
22636
|
+
*
|
|
22637
|
+
* Like `recording` this is a `scope:'system', mode:'singleton'` cap: the
|
|
22638
|
+
* recorder self-gates so exactly ONE node (the designated `recordingNodeId`,
|
|
22639
|
+
* default `hub`) registers it. Device-scoped methods carry `deviceId` in their
|
|
22640
|
+
* input and dispatch to that single provider; the render runs on the node that
|
|
22641
|
+
* owns the footage (no cross-node segment transfer). Download rides the
|
|
22642
|
+
* framework addon data-plane. State persists in a DurableState blob (NOT
|
|
22643
|
+
* SQLite); history rows survive file deletion for audit.
|
|
22644
|
+
*/
|
|
22645
|
+
/** Playback-speed multiplier for the render (1 = realtime). */
|
|
22646
|
+
var ExportSpeedSchema = number().min(.25).max(32);
|
|
22647
|
+
/** Timelapse cadence — sample one source frame per `everyMs`, output at `outputFps`. */
|
|
22648
|
+
var ExportTimelapseSchema = object({
|
|
22649
|
+
everyMs: number().int().positive(),
|
|
22650
|
+
outputFps: number().int().min(1).max(60).optional()
|
|
22651
|
+
});
|
|
22652
|
+
/**
|
|
22653
|
+
* Render options. `speed` and `timelapse` are mutually exclusive. `includeAudio`
|
|
22654
|
+
* is honoured only for a realtime-ish speed (0.5–2×); timelapse is always
|
|
22655
|
+
* silent. `maxLifeMs` bounds how long the finished file is kept;
|
|
22656
|
+
* `deleteAfterDownload` removes it shortly after the first complete download.
|
|
22657
|
+
*/
|
|
22658
|
+
var ExportOptionsSchema = object({
|
|
22659
|
+
speed: ExportSpeedSchema.optional(),
|
|
22660
|
+
timelapse: ExportTimelapseSchema.optional(),
|
|
22661
|
+
includeAudio: boolean(),
|
|
22662
|
+
maxLifeMs: number().int().positive(),
|
|
22663
|
+
deleteAfterDownload: boolean(),
|
|
22664
|
+
title: string().max(200).optional()
|
|
22665
|
+
}).superRefine((v, ctx) => {
|
|
22666
|
+
if (v.speed !== void 0 && v.timelapse !== void 0) ctx.addIssue({
|
|
22667
|
+
code: ZodIssueCode.custom,
|
|
22668
|
+
message: "speed and timelapse are mutually exclusive",
|
|
22669
|
+
path: ["timelapse"]
|
|
22670
|
+
});
|
|
22671
|
+
});
|
|
22672
|
+
var ExportStateSchema = _enum([
|
|
22673
|
+
"queued",
|
|
22674
|
+
"rendering",
|
|
22675
|
+
"ready",
|
|
22676
|
+
"failed",
|
|
22677
|
+
"expired",
|
|
22678
|
+
"deleted"
|
|
22679
|
+
]);
|
|
22680
|
+
/** One export job / history row. */
|
|
22681
|
+
var ExportRecordSchema = object({
|
|
22682
|
+
id: string(),
|
|
22683
|
+
deviceId: number(),
|
|
22684
|
+
profile: string(),
|
|
22685
|
+
fromMs: number(),
|
|
22686
|
+
toMs: number(),
|
|
22687
|
+
options: ExportOptionsSchema,
|
|
22688
|
+
state: ExportStateSchema,
|
|
22689
|
+
/** 0–100 while rendering; null otherwise. */
|
|
22690
|
+
progressPct: number().nullable(),
|
|
22691
|
+
/** File size once ready; null before. */
|
|
22692
|
+
fileBytes: number().nullable(),
|
|
22693
|
+
expiresAt: number(),
|
|
22694
|
+
deleteAfterDownload: boolean(),
|
|
22695
|
+
/** Epoch of the first complete download; null until then. */
|
|
22696
|
+
downloadedAt: number().nullable(),
|
|
22697
|
+
createdAt: number(),
|
|
22698
|
+
/** User id/name that requested the export. */
|
|
22699
|
+
createdBy: string(),
|
|
22700
|
+
/** Failure reason when state is 'failed'; null otherwise. */
|
|
22701
|
+
error: string().nullable()
|
|
22702
|
+
});
|
|
22703
|
+
/** Candidate download URLs (LAN first, then operator extra hosts). */
|
|
22704
|
+
var ExportDownloadSchema = object({
|
|
22705
|
+
url: string(),
|
|
22706
|
+
endpoints: array(string())
|
|
22707
|
+
});
|
|
22708
|
+
method(object({
|
|
22709
|
+
deviceId: number(),
|
|
22710
|
+
profile: string(),
|
|
22711
|
+
fromMs: number(),
|
|
22712
|
+
toMs: number(),
|
|
22713
|
+
options: ExportOptionsSchema
|
|
22714
|
+
}), ExportRecordSchema, {
|
|
22715
|
+
kind: "mutation",
|
|
22716
|
+
auth: "protected"
|
|
22717
|
+
}), method(object({ deviceId: number().optional() }), array(ExportRecordSchema), {
|
|
22718
|
+
kind: "query",
|
|
22719
|
+
auth: "protected"
|
|
22720
|
+
}), method(object({ exportId: string() }), ExportRecordSchema, {
|
|
22721
|
+
kind: "query",
|
|
22722
|
+
auth: "protected"
|
|
22723
|
+
}), method(object({ exportId: string() }), ExportRecordSchema, {
|
|
22724
|
+
kind: "mutation",
|
|
22725
|
+
auth: "protected"
|
|
22726
|
+
}), method(object({ exportId: string() }), ExportRecordSchema, {
|
|
22727
|
+
kind: "mutation",
|
|
22728
|
+
auth: "protected"
|
|
22729
|
+
}), method(object({ exportId: string() }), ExportDownloadSchema, {
|
|
22730
|
+
kind: "query",
|
|
22731
|
+
auth: "protected"
|
|
22465
22732
|
});
|
|
22466
22733
|
/**
|
|
22467
22734
|
* One publishable camera stream as its OWNING PROVIDER describes it — the same
|
|
@@ -25481,6 +25748,12 @@ Object.freeze({
|
|
|
25481
25748
|
addonId: null,
|
|
25482
25749
|
access: "delete"
|
|
25483
25750
|
},
|
|
25751
|
+
"pipelineAnalytics.deleteDeviceEvents": {
|
|
25752
|
+
capName: "pipeline-analytics",
|
|
25753
|
+
capScope: "device",
|
|
25754
|
+
addonId: null,
|
|
25755
|
+
access: "delete"
|
|
25756
|
+
},
|
|
25484
25757
|
"pipelineAnalytics.deleteTracks": {
|
|
25485
25758
|
capName: "pipeline-analytics",
|
|
25486
25759
|
capScope: "device",
|
|
@@ -25511,6 +25784,12 @@ Object.freeze({
|
|
|
25511
25784
|
addonId: null,
|
|
25512
25785
|
access: "view"
|
|
25513
25786
|
},
|
|
25787
|
+
"pipelineAnalytics.getEventStoreFootprint": {
|
|
25788
|
+
capName: "pipeline-analytics",
|
|
25789
|
+
capScope: "device",
|
|
25790
|
+
addonId: null,
|
|
25791
|
+
access: "view"
|
|
25792
|
+
},
|
|
25514
25793
|
"pipelineAnalytics.getKeyEvents": {
|
|
25515
25794
|
capName: "pipeline-analytics",
|
|
25516
25795
|
capScope: "device",
|
|
@@ -25553,6 +25832,12 @@ Object.freeze({
|
|
|
25553
25832
|
addonId: null,
|
|
25554
25833
|
access: "view"
|
|
25555
25834
|
},
|
|
25835
|
+
"pipelineAnalytics.listOpsLog": {
|
|
25836
|
+
capName: "pipeline-analytics",
|
|
25837
|
+
capScope: "device",
|
|
25838
|
+
addonId: null,
|
|
25839
|
+
access: "view"
|
|
25840
|
+
},
|
|
25556
25841
|
"pipelineAnalytics.listRecentTracks": {
|
|
25557
25842
|
capName: "pipeline-analytics",
|
|
25558
25843
|
capScope: "device",
|
|
@@ -25565,6 +25850,12 @@ Object.freeze({
|
|
|
25565
25850
|
addonId: null,
|
|
25566
25851
|
access: "view"
|
|
25567
25852
|
},
|
|
25853
|
+
"pipelineAnalytics.pruneEvents": {
|
|
25854
|
+
capName: "pipeline-analytics",
|
|
25855
|
+
capScope: "device",
|
|
25856
|
+
addonId: null,
|
|
25857
|
+
access: "create"
|
|
25858
|
+
},
|
|
25568
25859
|
"pipelineAnalytics.pruneEventsBefore": {
|
|
25569
25860
|
capName: "pipeline-analytics",
|
|
25570
25861
|
capScope: "device",
|
|
@@ -26327,6 +26618,12 @@ Object.freeze({
|
|
|
26327
26618
|
addonId: null,
|
|
26328
26619
|
access: "create"
|
|
26329
26620
|
},
|
|
26621
|
+
"recording.deleteFootprint": {
|
|
26622
|
+
capName: "recording",
|
|
26623
|
+
capScope: "system",
|
|
26624
|
+
addonId: null,
|
|
26625
|
+
access: "delete"
|
|
26626
|
+
},
|
|
26330
26627
|
"recording.getAvailability": {
|
|
26331
26628
|
capName: "recording",
|
|
26332
26629
|
capScope: "system",
|
|
@@ -26357,6 +26654,12 @@ Object.freeze({
|
|
|
26357
26654
|
addonId: null,
|
|
26358
26655
|
access: "view"
|
|
26359
26656
|
},
|
|
26657
|
+
"recording.listOpsLog": {
|
|
26658
|
+
capName: "recording",
|
|
26659
|
+
capScope: "system",
|
|
26660
|
+
addonId: null,
|
|
26661
|
+
access: "view"
|
|
26662
|
+
},
|
|
26360
26663
|
"recording.locateSegment": {
|
|
26361
26664
|
capName: "recording",
|
|
26362
26665
|
capScope: "system",
|
|
@@ -26387,6 +26690,42 @@ Object.freeze({
|
|
|
26387
26690
|
addonId: null,
|
|
26388
26691
|
access: "create"
|
|
26389
26692
|
},
|
|
26693
|
+
"recordingExport.cancelExport": {
|
|
26694
|
+
capName: "recordingExport",
|
|
26695
|
+
capScope: "system",
|
|
26696
|
+
addonId: null,
|
|
26697
|
+
access: "create"
|
|
26698
|
+
},
|
|
26699
|
+
"recordingExport.createExport": {
|
|
26700
|
+
capName: "recordingExport",
|
|
26701
|
+
capScope: "system",
|
|
26702
|
+
addonId: null,
|
|
26703
|
+
access: "create"
|
|
26704
|
+
},
|
|
26705
|
+
"recordingExport.deleteExport": {
|
|
26706
|
+
capName: "recordingExport",
|
|
26707
|
+
capScope: "system",
|
|
26708
|
+
addonId: null,
|
|
26709
|
+
access: "delete"
|
|
26710
|
+
},
|
|
26711
|
+
"recordingExport.getDownloadUrl": {
|
|
26712
|
+
capName: "recordingExport",
|
|
26713
|
+
capScope: "system",
|
|
26714
|
+
addonId: null,
|
|
26715
|
+
access: "view"
|
|
26716
|
+
},
|
|
26717
|
+
"recordingExport.getExport": {
|
|
26718
|
+
capName: "recordingExport",
|
|
26719
|
+
capScope: "system",
|
|
26720
|
+
addonId: null,
|
|
26721
|
+
access: "view"
|
|
26722
|
+
},
|
|
26723
|
+
"recordingExport.listExports": {
|
|
26724
|
+
capName: "recordingExport",
|
|
26725
|
+
capScope: "system",
|
|
26726
|
+
addonId: null,
|
|
26727
|
+
access: "view"
|
|
26728
|
+
},
|
|
26390
26729
|
"sceneMonitor.captureReference": {
|
|
26391
26730
|
capName: "scene-monitor",
|
|
26392
26731
|
capScope: "device",
|
package/package.json
CHANGED