@camstack/addon-provider-homematic 1.1.24 → 1.1.25
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 +202 -7
- package/dist/addon.mjs +202 -7
- 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",
|
|
@@ -14679,7 +14722,11 @@ array(ZoneRuleSchema).readonly();
|
|
|
14679
14722
|
* Extend the enum here when a new gating consumer comes online (audio
|
|
14680
14723
|
* gating, alert filtering, …) — no other surface needs to change.
|
|
14681
14724
|
*/
|
|
14682
|
-
var ZoneRuleStageEnum = _enum([
|
|
14725
|
+
var ZoneRuleStageEnum = _enum([
|
|
14726
|
+
"motion",
|
|
14727
|
+
"detection",
|
|
14728
|
+
"package"
|
|
14729
|
+
]);
|
|
14683
14730
|
/**
|
|
14684
14731
|
* Runtime registry: cap-property-name → cap definition. `BaseDevice`'s
|
|
14685
14732
|
* `state` getter looks up the cap definition here to construct a
|
|
@@ -14773,16 +14820,24 @@ var DEVICE_LOCAL_STATE_CAPS = {
|
|
|
14773
14820
|
})
|
|
14774
14821
|
},
|
|
14775
14822
|
/**
|
|
14776
|
-
* Runtime-state slice —
|
|
14823
|
+
* Runtime-state slice — every stage mirrored together so consumers
|
|
14777
14824
|
* see one reactive handle (`device.state.zoneRules.value`) instead
|
|
14778
|
-
* of
|
|
14779
|
-
* `{motion, detection}` shape, so subscribers always get the
|
|
14825
|
+
* of one per stage. Bulk-replace mutations on any stage write the full
|
|
14826
|
+
* `{motion, detection, package}` shape, so subscribers always get the
|
|
14780
14827
|
* complete current set. Consumers that only care about one stage
|
|
14781
14828
|
* just read the matching property.
|
|
14829
|
+
*
|
|
14830
|
+
* `package` backs the package-drop detector — a package zone is a
|
|
14831
|
+
* `ZoneRule` on the `'package'` stage referencing drawn polygons
|
|
14832
|
+
* (see docs/superpowers/specs/2026-07-17-package-zones-design.md §3.1).
|
|
14833
|
+
* The orchestrator provider that writes this stage lands in a later
|
|
14834
|
+
* slice; until then the mirror carries only `{motion, detection}` and
|
|
14835
|
+
* consumers read `package` as absent (treat as `[]`).
|
|
14782
14836
|
*/
|
|
14783
14837
|
runtimeState: object({
|
|
14784
14838
|
motion: array(ZoneRuleSchema).readonly(),
|
|
14785
|
-
detection: array(ZoneRuleSchema).readonly()
|
|
14839
|
+
detection: array(ZoneRuleSchema).readonly(),
|
|
14840
|
+
package: array(ZoneRuleSchema).readonly()
|
|
14786
14841
|
})
|
|
14787
14842
|
},
|
|
14788
14843
|
zones: zonesCapability
|
|
@@ -18810,6 +18865,7 @@ var EventKindIconSchema = _enum([
|
|
|
18810
18865
|
"smoke",
|
|
18811
18866
|
"water",
|
|
18812
18867
|
"button",
|
|
18868
|
+
"package",
|
|
18813
18869
|
"generic"
|
|
18814
18870
|
]);
|
|
18815
18871
|
var EventKindCategorySchema = _enum([
|
|
@@ -18817,7 +18873,8 @@ var EventKindCategorySchema = _enum([
|
|
|
18817
18873
|
"audio",
|
|
18818
18874
|
"detection",
|
|
18819
18875
|
"sensor",
|
|
18820
|
-
"custom"
|
|
18876
|
+
"custom",
|
|
18877
|
+
"package"
|
|
18821
18878
|
]);
|
|
18822
18879
|
var EventKindDescriptorSchema = object({
|
|
18823
18880
|
/** Stable kind id (e.g. 'motion', 'person', 'contact'). */
|
|
@@ -22463,6 +22520,108 @@ method(object({
|
|
|
22463
22520
|
auth: "admin"
|
|
22464
22521
|
});
|
|
22465
22522
|
/**
|
|
22523
|
+
* `recordingExport` cap — render a footage time range into a single downloadable
|
|
22524
|
+
* MP4 (regular / accelerated / decelerated / timelapse, ± audio), kept for a
|
|
22525
|
+
* bounded lifetime with a durable history, auto-expiry, and optional
|
|
22526
|
+
* delete-after-download.
|
|
22527
|
+
*
|
|
22528
|
+
* Like `recording` this is a `scope:'system', mode:'singleton'` cap: the
|
|
22529
|
+
* recorder self-gates so exactly ONE node (the designated `recordingNodeId`,
|
|
22530
|
+
* default `hub`) registers it. Device-scoped methods carry `deviceId` in their
|
|
22531
|
+
* input and dispatch to that single provider; the render runs on the node that
|
|
22532
|
+
* owns the footage (no cross-node segment transfer). Download rides the
|
|
22533
|
+
* framework addon data-plane. State persists in a DurableState blob (NOT
|
|
22534
|
+
* SQLite); history rows survive file deletion for audit.
|
|
22535
|
+
*/
|
|
22536
|
+
/** Playback-speed multiplier for the render (1 = realtime). */
|
|
22537
|
+
var ExportSpeedSchema = number().min(.25).max(32);
|
|
22538
|
+
/** Timelapse cadence — sample one source frame per `everyMs`, output at `outputFps`. */
|
|
22539
|
+
var ExportTimelapseSchema = object({
|
|
22540
|
+
everyMs: number().int().positive(),
|
|
22541
|
+
outputFps: number().int().min(1).max(60).optional()
|
|
22542
|
+
});
|
|
22543
|
+
/**
|
|
22544
|
+
* Render options. `speed` and `timelapse` are mutually exclusive. `includeAudio`
|
|
22545
|
+
* is honoured only for a realtime-ish speed (0.5–2×); timelapse is always
|
|
22546
|
+
* silent. `maxLifeMs` bounds how long the finished file is kept;
|
|
22547
|
+
* `deleteAfterDownload` removes it shortly after the first complete download.
|
|
22548
|
+
*/
|
|
22549
|
+
var ExportOptionsSchema = object({
|
|
22550
|
+
speed: ExportSpeedSchema.optional(),
|
|
22551
|
+
timelapse: ExportTimelapseSchema.optional(),
|
|
22552
|
+
includeAudio: boolean(),
|
|
22553
|
+
maxLifeMs: number().int().positive(),
|
|
22554
|
+
deleteAfterDownload: boolean(),
|
|
22555
|
+
title: string().max(200).optional()
|
|
22556
|
+
}).superRefine((v, ctx) => {
|
|
22557
|
+
if (v.speed !== void 0 && v.timelapse !== void 0) ctx.addIssue({
|
|
22558
|
+
code: ZodIssueCode.custom,
|
|
22559
|
+
message: "speed and timelapse are mutually exclusive",
|
|
22560
|
+
path: ["timelapse"]
|
|
22561
|
+
});
|
|
22562
|
+
});
|
|
22563
|
+
var ExportStateSchema = _enum([
|
|
22564
|
+
"queued",
|
|
22565
|
+
"rendering",
|
|
22566
|
+
"ready",
|
|
22567
|
+
"failed",
|
|
22568
|
+
"expired",
|
|
22569
|
+
"deleted"
|
|
22570
|
+
]);
|
|
22571
|
+
/** One export job / history row. */
|
|
22572
|
+
var ExportRecordSchema = object({
|
|
22573
|
+
id: string(),
|
|
22574
|
+
deviceId: number(),
|
|
22575
|
+
profile: string(),
|
|
22576
|
+
fromMs: number(),
|
|
22577
|
+
toMs: number(),
|
|
22578
|
+
options: ExportOptionsSchema,
|
|
22579
|
+
state: ExportStateSchema,
|
|
22580
|
+
/** 0–100 while rendering; null otherwise. */
|
|
22581
|
+
progressPct: number().nullable(),
|
|
22582
|
+
/** File size once ready; null before. */
|
|
22583
|
+
fileBytes: number().nullable(),
|
|
22584
|
+
expiresAt: number(),
|
|
22585
|
+
deleteAfterDownload: boolean(),
|
|
22586
|
+
/** Epoch of the first complete download; null until then. */
|
|
22587
|
+
downloadedAt: number().nullable(),
|
|
22588
|
+
createdAt: number(),
|
|
22589
|
+
/** User id/name that requested the export. */
|
|
22590
|
+
createdBy: string(),
|
|
22591
|
+
/** Failure reason when state is 'failed'; null otherwise. */
|
|
22592
|
+
error: string().nullable()
|
|
22593
|
+
});
|
|
22594
|
+
/** Candidate download URLs (LAN first, then operator extra hosts). */
|
|
22595
|
+
var ExportDownloadSchema = object({
|
|
22596
|
+
url: string(),
|
|
22597
|
+
endpoints: array(string())
|
|
22598
|
+
});
|
|
22599
|
+
method(object({
|
|
22600
|
+
deviceId: number(),
|
|
22601
|
+
profile: string(),
|
|
22602
|
+
fromMs: number(),
|
|
22603
|
+
toMs: number(),
|
|
22604
|
+
options: ExportOptionsSchema
|
|
22605
|
+
}), ExportRecordSchema, {
|
|
22606
|
+
kind: "mutation",
|
|
22607
|
+
auth: "protected"
|
|
22608
|
+
}), method(object({ deviceId: number().optional() }), array(ExportRecordSchema), {
|
|
22609
|
+
kind: "query",
|
|
22610
|
+
auth: "protected"
|
|
22611
|
+
}), method(object({ exportId: string() }), ExportRecordSchema, {
|
|
22612
|
+
kind: "query",
|
|
22613
|
+
auth: "protected"
|
|
22614
|
+
}), method(object({ exportId: string() }), ExportRecordSchema, {
|
|
22615
|
+
kind: "mutation",
|
|
22616
|
+
auth: "protected"
|
|
22617
|
+
}), method(object({ exportId: string() }), ExportRecordSchema, {
|
|
22618
|
+
kind: "mutation",
|
|
22619
|
+
auth: "protected"
|
|
22620
|
+
}), method(object({ exportId: string() }), ExportDownloadSchema, {
|
|
22621
|
+
kind: "query",
|
|
22622
|
+
auth: "protected"
|
|
22623
|
+
});
|
|
22624
|
+
/**
|
|
22466
22625
|
* One publishable camera stream as its OWNING PROVIDER describes it — the same
|
|
22467
22626
|
* payload the (legacy) push `streamBroker.publishCameraStream` carried, minus
|
|
22468
22627
|
* `deviceId`.
|
|
@@ -26386,6 +26545,42 @@ Object.freeze({
|
|
|
26386
26545
|
addonId: null,
|
|
26387
26546
|
access: "create"
|
|
26388
26547
|
},
|
|
26548
|
+
"recordingExport.cancelExport": {
|
|
26549
|
+
capName: "recordingExport",
|
|
26550
|
+
capScope: "system",
|
|
26551
|
+
addonId: null,
|
|
26552
|
+
access: "create"
|
|
26553
|
+
},
|
|
26554
|
+
"recordingExport.createExport": {
|
|
26555
|
+
capName: "recordingExport",
|
|
26556
|
+
capScope: "system",
|
|
26557
|
+
addonId: null,
|
|
26558
|
+
access: "create"
|
|
26559
|
+
},
|
|
26560
|
+
"recordingExport.deleteExport": {
|
|
26561
|
+
capName: "recordingExport",
|
|
26562
|
+
capScope: "system",
|
|
26563
|
+
addonId: null,
|
|
26564
|
+
access: "delete"
|
|
26565
|
+
},
|
|
26566
|
+
"recordingExport.getDownloadUrl": {
|
|
26567
|
+
capName: "recordingExport",
|
|
26568
|
+
capScope: "system",
|
|
26569
|
+
addonId: null,
|
|
26570
|
+
access: "view"
|
|
26571
|
+
},
|
|
26572
|
+
"recordingExport.getExport": {
|
|
26573
|
+
capName: "recordingExport",
|
|
26574
|
+
capScope: "system",
|
|
26575
|
+
addonId: null,
|
|
26576
|
+
access: "view"
|
|
26577
|
+
},
|
|
26578
|
+
"recordingExport.listExports": {
|
|
26579
|
+
capName: "recordingExport",
|
|
26580
|
+
capScope: "system",
|
|
26581
|
+
addonId: null,
|
|
26582
|
+
access: "view"
|
|
26583
|
+
},
|
|
26389
26584
|
"sceneMonitor.captureReference": {
|
|
26390
26585
|
capName: "scene-monitor",
|
|
26391
26586
|
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",
|
|
@@ -14680,7 +14723,11 @@ array(ZoneRuleSchema).readonly();
|
|
|
14680
14723
|
* Extend the enum here when a new gating consumer comes online (audio
|
|
14681
14724
|
* gating, alert filtering, …) — no other surface needs to change.
|
|
14682
14725
|
*/
|
|
14683
|
-
var ZoneRuleStageEnum = _enum([
|
|
14726
|
+
var ZoneRuleStageEnum = _enum([
|
|
14727
|
+
"motion",
|
|
14728
|
+
"detection",
|
|
14729
|
+
"package"
|
|
14730
|
+
]);
|
|
14684
14731
|
/**
|
|
14685
14732
|
* Runtime registry: cap-property-name → cap definition. `BaseDevice`'s
|
|
14686
14733
|
* `state` getter looks up the cap definition here to construct a
|
|
@@ -14774,16 +14821,24 @@ var DEVICE_LOCAL_STATE_CAPS = {
|
|
|
14774
14821
|
})
|
|
14775
14822
|
},
|
|
14776
14823
|
/**
|
|
14777
|
-
* Runtime-state slice —
|
|
14824
|
+
* Runtime-state slice — every stage mirrored together so consumers
|
|
14778
14825
|
* see one reactive handle (`device.state.zoneRules.value`) instead
|
|
14779
|
-
* of
|
|
14780
|
-
* `{motion, detection}` shape, so subscribers always get the
|
|
14826
|
+
* of one per stage. Bulk-replace mutations on any stage write the full
|
|
14827
|
+
* `{motion, detection, package}` shape, so subscribers always get the
|
|
14781
14828
|
* complete current set. Consumers that only care about one stage
|
|
14782
14829
|
* just read the matching property.
|
|
14830
|
+
*
|
|
14831
|
+
* `package` backs the package-drop detector — a package zone is a
|
|
14832
|
+
* `ZoneRule` on the `'package'` stage referencing drawn polygons
|
|
14833
|
+
* (see docs/superpowers/specs/2026-07-17-package-zones-design.md §3.1).
|
|
14834
|
+
* The orchestrator provider that writes this stage lands in a later
|
|
14835
|
+
* slice; until then the mirror carries only `{motion, detection}` and
|
|
14836
|
+
* consumers read `package` as absent (treat as `[]`).
|
|
14783
14837
|
*/
|
|
14784
14838
|
runtimeState: object({
|
|
14785
14839
|
motion: array(ZoneRuleSchema).readonly(),
|
|
14786
|
-
detection: array(ZoneRuleSchema).readonly()
|
|
14840
|
+
detection: array(ZoneRuleSchema).readonly(),
|
|
14841
|
+
package: array(ZoneRuleSchema).readonly()
|
|
14787
14842
|
})
|
|
14788
14843
|
},
|
|
14789
14844
|
zones: zonesCapability
|
|
@@ -18811,6 +18866,7 @@ var EventKindIconSchema = _enum([
|
|
|
18811
18866
|
"smoke",
|
|
18812
18867
|
"water",
|
|
18813
18868
|
"button",
|
|
18869
|
+
"package",
|
|
18814
18870
|
"generic"
|
|
18815
18871
|
]);
|
|
18816
18872
|
var EventKindCategorySchema = _enum([
|
|
@@ -18818,7 +18874,8 @@ var EventKindCategorySchema = _enum([
|
|
|
18818
18874
|
"audio",
|
|
18819
18875
|
"detection",
|
|
18820
18876
|
"sensor",
|
|
18821
|
-
"custom"
|
|
18877
|
+
"custom",
|
|
18878
|
+
"package"
|
|
18822
18879
|
]);
|
|
18823
18880
|
var EventKindDescriptorSchema = object({
|
|
18824
18881
|
/** Stable kind id (e.g. 'motion', 'person', 'contact'). */
|
|
@@ -22464,6 +22521,108 @@ method(object({
|
|
|
22464
22521
|
auth: "admin"
|
|
22465
22522
|
});
|
|
22466
22523
|
/**
|
|
22524
|
+
* `recordingExport` cap — render a footage time range into a single downloadable
|
|
22525
|
+
* MP4 (regular / accelerated / decelerated / timelapse, ± audio), kept for a
|
|
22526
|
+
* bounded lifetime with a durable history, auto-expiry, and optional
|
|
22527
|
+
* delete-after-download.
|
|
22528
|
+
*
|
|
22529
|
+
* Like `recording` this is a `scope:'system', mode:'singleton'` cap: the
|
|
22530
|
+
* recorder self-gates so exactly ONE node (the designated `recordingNodeId`,
|
|
22531
|
+
* default `hub`) registers it. Device-scoped methods carry `deviceId` in their
|
|
22532
|
+
* input and dispatch to that single provider; the render runs on the node that
|
|
22533
|
+
* owns the footage (no cross-node segment transfer). Download rides the
|
|
22534
|
+
* framework addon data-plane. State persists in a DurableState blob (NOT
|
|
22535
|
+
* SQLite); history rows survive file deletion for audit.
|
|
22536
|
+
*/
|
|
22537
|
+
/** Playback-speed multiplier for the render (1 = realtime). */
|
|
22538
|
+
var ExportSpeedSchema = number().min(.25).max(32);
|
|
22539
|
+
/** Timelapse cadence — sample one source frame per `everyMs`, output at `outputFps`. */
|
|
22540
|
+
var ExportTimelapseSchema = object({
|
|
22541
|
+
everyMs: number().int().positive(),
|
|
22542
|
+
outputFps: number().int().min(1).max(60).optional()
|
|
22543
|
+
});
|
|
22544
|
+
/**
|
|
22545
|
+
* Render options. `speed` and `timelapse` are mutually exclusive. `includeAudio`
|
|
22546
|
+
* is honoured only for a realtime-ish speed (0.5–2×); timelapse is always
|
|
22547
|
+
* silent. `maxLifeMs` bounds how long the finished file is kept;
|
|
22548
|
+
* `deleteAfterDownload` removes it shortly after the first complete download.
|
|
22549
|
+
*/
|
|
22550
|
+
var ExportOptionsSchema = object({
|
|
22551
|
+
speed: ExportSpeedSchema.optional(),
|
|
22552
|
+
timelapse: ExportTimelapseSchema.optional(),
|
|
22553
|
+
includeAudio: boolean(),
|
|
22554
|
+
maxLifeMs: number().int().positive(),
|
|
22555
|
+
deleteAfterDownload: boolean(),
|
|
22556
|
+
title: string().max(200).optional()
|
|
22557
|
+
}).superRefine((v, ctx) => {
|
|
22558
|
+
if (v.speed !== void 0 && v.timelapse !== void 0) ctx.addIssue({
|
|
22559
|
+
code: ZodIssueCode.custom,
|
|
22560
|
+
message: "speed and timelapse are mutually exclusive",
|
|
22561
|
+
path: ["timelapse"]
|
|
22562
|
+
});
|
|
22563
|
+
});
|
|
22564
|
+
var ExportStateSchema = _enum([
|
|
22565
|
+
"queued",
|
|
22566
|
+
"rendering",
|
|
22567
|
+
"ready",
|
|
22568
|
+
"failed",
|
|
22569
|
+
"expired",
|
|
22570
|
+
"deleted"
|
|
22571
|
+
]);
|
|
22572
|
+
/** One export job / history row. */
|
|
22573
|
+
var ExportRecordSchema = object({
|
|
22574
|
+
id: string(),
|
|
22575
|
+
deviceId: number(),
|
|
22576
|
+
profile: string(),
|
|
22577
|
+
fromMs: number(),
|
|
22578
|
+
toMs: number(),
|
|
22579
|
+
options: ExportOptionsSchema,
|
|
22580
|
+
state: ExportStateSchema,
|
|
22581
|
+
/** 0–100 while rendering; null otherwise. */
|
|
22582
|
+
progressPct: number().nullable(),
|
|
22583
|
+
/** File size once ready; null before. */
|
|
22584
|
+
fileBytes: number().nullable(),
|
|
22585
|
+
expiresAt: number(),
|
|
22586
|
+
deleteAfterDownload: boolean(),
|
|
22587
|
+
/** Epoch of the first complete download; null until then. */
|
|
22588
|
+
downloadedAt: number().nullable(),
|
|
22589
|
+
createdAt: number(),
|
|
22590
|
+
/** User id/name that requested the export. */
|
|
22591
|
+
createdBy: string(),
|
|
22592
|
+
/** Failure reason when state is 'failed'; null otherwise. */
|
|
22593
|
+
error: string().nullable()
|
|
22594
|
+
});
|
|
22595
|
+
/** Candidate download URLs (LAN first, then operator extra hosts). */
|
|
22596
|
+
var ExportDownloadSchema = object({
|
|
22597
|
+
url: string(),
|
|
22598
|
+
endpoints: array(string())
|
|
22599
|
+
});
|
|
22600
|
+
method(object({
|
|
22601
|
+
deviceId: number(),
|
|
22602
|
+
profile: string(),
|
|
22603
|
+
fromMs: number(),
|
|
22604
|
+
toMs: number(),
|
|
22605
|
+
options: ExportOptionsSchema
|
|
22606
|
+
}), ExportRecordSchema, {
|
|
22607
|
+
kind: "mutation",
|
|
22608
|
+
auth: "protected"
|
|
22609
|
+
}), method(object({ deviceId: number().optional() }), array(ExportRecordSchema), {
|
|
22610
|
+
kind: "query",
|
|
22611
|
+
auth: "protected"
|
|
22612
|
+
}), method(object({ exportId: string() }), ExportRecordSchema, {
|
|
22613
|
+
kind: "query",
|
|
22614
|
+
auth: "protected"
|
|
22615
|
+
}), method(object({ exportId: string() }), ExportRecordSchema, {
|
|
22616
|
+
kind: "mutation",
|
|
22617
|
+
auth: "protected"
|
|
22618
|
+
}), method(object({ exportId: string() }), ExportRecordSchema, {
|
|
22619
|
+
kind: "mutation",
|
|
22620
|
+
auth: "protected"
|
|
22621
|
+
}), method(object({ exportId: string() }), ExportDownloadSchema, {
|
|
22622
|
+
kind: "query",
|
|
22623
|
+
auth: "protected"
|
|
22624
|
+
});
|
|
22625
|
+
/**
|
|
22467
22626
|
* One publishable camera stream as its OWNING PROVIDER describes it — the same
|
|
22468
22627
|
* payload the (legacy) push `streamBroker.publishCameraStream` carried, minus
|
|
22469
22628
|
* `deviceId`.
|
|
@@ -26387,6 +26546,42 @@ Object.freeze({
|
|
|
26387
26546
|
addonId: null,
|
|
26388
26547
|
access: "create"
|
|
26389
26548
|
},
|
|
26549
|
+
"recordingExport.cancelExport": {
|
|
26550
|
+
capName: "recordingExport",
|
|
26551
|
+
capScope: "system",
|
|
26552
|
+
addonId: null,
|
|
26553
|
+
access: "create"
|
|
26554
|
+
},
|
|
26555
|
+
"recordingExport.createExport": {
|
|
26556
|
+
capName: "recordingExport",
|
|
26557
|
+
capScope: "system",
|
|
26558
|
+
addonId: null,
|
|
26559
|
+
access: "create"
|
|
26560
|
+
},
|
|
26561
|
+
"recordingExport.deleteExport": {
|
|
26562
|
+
capName: "recordingExport",
|
|
26563
|
+
capScope: "system",
|
|
26564
|
+
addonId: null,
|
|
26565
|
+
access: "delete"
|
|
26566
|
+
},
|
|
26567
|
+
"recordingExport.getDownloadUrl": {
|
|
26568
|
+
capName: "recordingExport",
|
|
26569
|
+
capScope: "system",
|
|
26570
|
+
addonId: null,
|
|
26571
|
+
access: "view"
|
|
26572
|
+
},
|
|
26573
|
+
"recordingExport.getExport": {
|
|
26574
|
+
capName: "recordingExport",
|
|
26575
|
+
capScope: "system",
|
|
26576
|
+
addonId: null,
|
|
26577
|
+
access: "view"
|
|
26578
|
+
},
|
|
26579
|
+
"recordingExport.listExports": {
|
|
26580
|
+
capName: "recordingExport",
|
|
26581
|
+
capScope: "system",
|
|
26582
|
+
addonId: null,
|
|
26583
|
+
access: "view"
|
|
26584
|
+
},
|
|
26390
26585
|
"sceneMonitor.captureReference": {
|
|
26391
26586
|
capName: "scene-monitor",
|
|
26392
26587
|
capScope: "device",
|
package/package.json
CHANGED