@camstack/addon-matter-broker 0.1.22 → 0.1.23
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
|
@@ -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",
|
|
@@ -14684,7 +14727,11 @@ array(ZoneRuleSchema).readonly();
|
|
|
14684
14727
|
* Extend the enum here when a new gating consumer comes online (audio
|
|
14685
14728
|
* gating, alert filtering, …) — no other surface needs to change.
|
|
14686
14729
|
*/
|
|
14687
|
-
var ZoneRuleStageEnum = _enum([
|
|
14730
|
+
var ZoneRuleStageEnum = _enum([
|
|
14731
|
+
"motion",
|
|
14732
|
+
"detection",
|
|
14733
|
+
"package"
|
|
14734
|
+
]);
|
|
14688
14735
|
/**
|
|
14689
14736
|
* Runtime registry: cap-property-name → cap definition. `BaseDevice`'s
|
|
14690
14737
|
* `state` getter looks up the cap definition here to construct a
|
|
@@ -14778,16 +14825,24 @@ var DEVICE_LOCAL_STATE_CAPS = {
|
|
|
14778
14825
|
})
|
|
14779
14826
|
},
|
|
14780
14827
|
/**
|
|
14781
|
-
* Runtime-state slice —
|
|
14828
|
+
* Runtime-state slice — every stage mirrored together so consumers
|
|
14782
14829
|
* see one reactive handle (`device.state.zoneRules.value`) instead
|
|
14783
|
-
* of
|
|
14784
|
-
* `{motion, detection}` shape, so subscribers always get the
|
|
14830
|
+
* of one per stage. Bulk-replace mutations on any stage write the full
|
|
14831
|
+
* `{motion, detection, package}` shape, so subscribers always get the
|
|
14785
14832
|
* complete current set. Consumers that only care about one stage
|
|
14786
14833
|
* just read the matching property.
|
|
14834
|
+
*
|
|
14835
|
+
* `package` backs the package-drop detector — a package zone is a
|
|
14836
|
+
* `ZoneRule` on the `'package'` stage referencing drawn polygons
|
|
14837
|
+
* (see docs/superpowers/specs/2026-07-17-package-zones-design.md §3.1).
|
|
14838
|
+
* The orchestrator provider that writes this stage lands in a later
|
|
14839
|
+
* slice; until then the mirror carries only `{motion, detection}` and
|
|
14840
|
+
* consumers read `package` as absent (treat as `[]`).
|
|
14787
14841
|
*/
|
|
14788
14842
|
runtimeState: object({
|
|
14789
14843
|
motion: array(ZoneRuleSchema).readonly(),
|
|
14790
|
-
detection: array(ZoneRuleSchema).readonly()
|
|
14844
|
+
detection: array(ZoneRuleSchema).readonly(),
|
|
14845
|
+
package: array(ZoneRuleSchema).readonly()
|
|
14791
14846
|
})
|
|
14792
14847
|
},
|
|
14793
14848
|
zones: zonesCapability
|
|
@@ -18815,6 +18870,7 @@ var EventKindIconSchema = _enum([
|
|
|
18815
18870
|
"smoke",
|
|
18816
18871
|
"water",
|
|
18817
18872
|
"button",
|
|
18873
|
+
"package",
|
|
18818
18874
|
"generic"
|
|
18819
18875
|
]);
|
|
18820
18876
|
var EventKindCategorySchema = _enum([
|
|
@@ -18822,7 +18878,8 @@ var EventKindCategorySchema = _enum([
|
|
|
18822
18878
|
"audio",
|
|
18823
18879
|
"detection",
|
|
18824
18880
|
"sensor",
|
|
18825
|
-
"custom"
|
|
18881
|
+
"custom",
|
|
18882
|
+
"package"
|
|
18826
18883
|
]);
|
|
18827
18884
|
var EventKindDescriptorSchema = object({
|
|
18828
18885
|
/** Stable kind id (e.g. 'motion', 'person', 'contact'). */
|
|
@@ -22485,6 +22542,108 @@ method(object({
|
|
|
22485
22542
|
auth: "admin"
|
|
22486
22543
|
});
|
|
22487
22544
|
/**
|
|
22545
|
+
* `recordingExport` cap — render a footage time range into a single downloadable
|
|
22546
|
+
* MP4 (regular / accelerated / decelerated / timelapse, ± audio), kept for a
|
|
22547
|
+
* bounded lifetime with a durable history, auto-expiry, and optional
|
|
22548
|
+
* delete-after-download.
|
|
22549
|
+
*
|
|
22550
|
+
* Like `recording` this is a `scope:'system', mode:'singleton'` cap: the
|
|
22551
|
+
* recorder self-gates so exactly ONE node (the designated `recordingNodeId`,
|
|
22552
|
+
* default `hub`) registers it. Device-scoped methods carry `deviceId` in their
|
|
22553
|
+
* input and dispatch to that single provider; the render runs on the node that
|
|
22554
|
+
* owns the footage (no cross-node segment transfer). Download rides the
|
|
22555
|
+
* framework addon data-plane. State persists in a DurableState blob (NOT
|
|
22556
|
+
* SQLite); history rows survive file deletion for audit.
|
|
22557
|
+
*/
|
|
22558
|
+
/** Playback-speed multiplier for the render (1 = realtime). */
|
|
22559
|
+
var ExportSpeedSchema = number().min(.25).max(32);
|
|
22560
|
+
/** Timelapse cadence — sample one source frame per `everyMs`, output at `outputFps`. */
|
|
22561
|
+
var ExportTimelapseSchema = object({
|
|
22562
|
+
everyMs: number().int().positive(),
|
|
22563
|
+
outputFps: number().int().min(1).max(60).optional()
|
|
22564
|
+
});
|
|
22565
|
+
/**
|
|
22566
|
+
* Render options. `speed` and `timelapse` are mutually exclusive. `includeAudio`
|
|
22567
|
+
* is honoured only for a realtime-ish speed (0.5–2×); timelapse is always
|
|
22568
|
+
* silent. `maxLifeMs` bounds how long the finished file is kept;
|
|
22569
|
+
* `deleteAfterDownload` removes it shortly after the first complete download.
|
|
22570
|
+
*/
|
|
22571
|
+
var ExportOptionsSchema = object({
|
|
22572
|
+
speed: ExportSpeedSchema.optional(),
|
|
22573
|
+
timelapse: ExportTimelapseSchema.optional(),
|
|
22574
|
+
includeAudio: boolean(),
|
|
22575
|
+
maxLifeMs: number().int().positive(),
|
|
22576
|
+
deleteAfterDownload: boolean(),
|
|
22577
|
+
title: string$2().max(200).optional()
|
|
22578
|
+
}).superRefine((v, ctx) => {
|
|
22579
|
+
if (v.speed !== void 0 && v.timelapse !== void 0) ctx.addIssue({
|
|
22580
|
+
code: ZodIssueCode.custom,
|
|
22581
|
+
message: "speed and timelapse are mutually exclusive",
|
|
22582
|
+
path: ["timelapse"]
|
|
22583
|
+
});
|
|
22584
|
+
});
|
|
22585
|
+
var ExportStateSchema = _enum([
|
|
22586
|
+
"queued",
|
|
22587
|
+
"rendering",
|
|
22588
|
+
"ready",
|
|
22589
|
+
"failed",
|
|
22590
|
+
"expired",
|
|
22591
|
+
"deleted"
|
|
22592
|
+
]);
|
|
22593
|
+
/** One export job / history row. */
|
|
22594
|
+
var ExportRecordSchema = object({
|
|
22595
|
+
id: string$2(),
|
|
22596
|
+
deviceId: number(),
|
|
22597
|
+
profile: string$2(),
|
|
22598
|
+
fromMs: number(),
|
|
22599
|
+
toMs: number(),
|
|
22600
|
+
options: ExportOptionsSchema,
|
|
22601
|
+
state: ExportStateSchema,
|
|
22602
|
+
/** 0–100 while rendering; null otherwise. */
|
|
22603
|
+
progressPct: number().nullable(),
|
|
22604
|
+
/** File size once ready; null before. */
|
|
22605
|
+
fileBytes: number().nullable(),
|
|
22606
|
+
expiresAt: number(),
|
|
22607
|
+
deleteAfterDownload: boolean(),
|
|
22608
|
+
/** Epoch of the first complete download; null until then. */
|
|
22609
|
+
downloadedAt: number().nullable(),
|
|
22610
|
+
createdAt: number(),
|
|
22611
|
+
/** User id/name that requested the export. */
|
|
22612
|
+
createdBy: string$2(),
|
|
22613
|
+
/** Failure reason when state is 'failed'; null otherwise. */
|
|
22614
|
+
error: string$2().nullable()
|
|
22615
|
+
});
|
|
22616
|
+
/** Candidate download URLs (LAN first, then operator extra hosts). */
|
|
22617
|
+
var ExportDownloadSchema = object({
|
|
22618
|
+
url: string$2(),
|
|
22619
|
+
endpoints: array(string$2())
|
|
22620
|
+
});
|
|
22621
|
+
method(object({
|
|
22622
|
+
deviceId: number(),
|
|
22623
|
+
profile: string$2(),
|
|
22624
|
+
fromMs: number(),
|
|
22625
|
+
toMs: number(),
|
|
22626
|
+
options: ExportOptionsSchema
|
|
22627
|
+
}), ExportRecordSchema, {
|
|
22628
|
+
kind: "mutation",
|
|
22629
|
+
auth: "protected"
|
|
22630
|
+
}), method(object({ deviceId: number().optional() }), array(ExportRecordSchema), {
|
|
22631
|
+
kind: "query",
|
|
22632
|
+
auth: "protected"
|
|
22633
|
+
}), method(object({ exportId: string$2() }), ExportRecordSchema, {
|
|
22634
|
+
kind: "query",
|
|
22635
|
+
auth: "protected"
|
|
22636
|
+
}), method(object({ exportId: string$2() }), ExportRecordSchema, {
|
|
22637
|
+
kind: "mutation",
|
|
22638
|
+
auth: "protected"
|
|
22639
|
+
}), method(object({ exportId: string$2() }), ExportRecordSchema, {
|
|
22640
|
+
kind: "mutation",
|
|
22641
|
+
auth: "protected"
|
|
22642
|
+
}), method(object({ exportId: string$2() }), ExportDownloadSchema, {
|
|
22643
|
+
kind: "query",
|
|
22644
|
+
auth: "protected"
|
|
22645
|
+
});
|
|
22646
|
+
/**
|
|
22488
22647
|
* One publishable camera stream as its OWNING PROVIDER describes it — the same
|
|
22489
22648
|
* payload the (legacy) push `streamBroker.publishCameraStream` carried, minus
|
|
22490
22649
|
* `deviceId`.
|
|
@@ -26408,6 +26567,42 @@ Object.freeze({
|
|
|
26408
26567
|
addonId: null,
|
|
26409
26568
|
access: "create"
|
|
26410
26569
|
},
|
|
26570
|
+
"recordingExport.cancelExport": {
|
|
26571
|
+
capName: "recordingExport",
|
|
26572
|
+
capScope: "system",
|
|
26573
|
+
addonId: null,
|
|
26574
|
+
access: "create"
|
|
26575
|
+
},
|
|
26576
|
+
"recordingExport.createExport": {
|
|
26577
|
+
capName: "recordingExport",
|
|
26578
|
+
capScope: "system",
|
|
26579
|
+
addonId: null,
|
|
26580
|
+
access: "create"
|
|
26581
|
+
},
|
|
26582
|
+
"recordingExport.deleteExport": {
|
|
26583
|
+
capName: "recordingExport",
|
|
26584
|
+
capScope: "system",
|
|
26585
|
+
addonId: null,
|
|
26586
|
+
access: "delete"
|
|
26587
|
+
},
|
|
26588
|
+
"recordingExport.getDownloadUrl": {
|
|
26589
|
+
capName: "recordingExport",
|
|
26590
|
+
capScope: "system",
|
|
26591
|
+
addonId: null,
|
|
26592
|
+
access: "view"
|
|
26593
|
+
},
|
|
26594
|
+
"recordingExport.getExport": {
|
|
26595
|
+
capName: "recordingExport",
|
|
26596
|
+
capScope: "system",
|
|
26597
|
+
addonId: null,
|
|
26598
|
+
access: "view"
|
|
26599
|
+
},
|
|
26600
|
+
"recordingExport.listExports": {
|
|
26601
|
+
capName: "recordingExport",
|
|
26602
|
+
capScope: "system",
|
|
26603
|
+
addonId: null,
|
|
26604
|
+
access: "view"
|
|
26605
|
+
},
|
|
26411
26606
|
"sceneMonitor.captureReference": {
|
|
26412
26607
|
capName: "scene-monitor",
|
|
26413
26608
|
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",
|
|
@@ -14682,7 +14725,11 @@ array(ZoneRuleSchema).readonly();
|
|
|
14682
14725
|
* Extend the enum here when a new gating consumer comes online (audio
|
|
14683
14726
|
* gating, alert filtering, …) — no other surface needs to change.
|
|
14684
14727
|
*/
|
|
14685
|
-
var ZoneRuleStageEnum = _enum([
|
|
14728
|
+
var ZoneRuleStageEnum = _enum([
|
|
14729
|
+
"motion",
|
|
14730
|
+
"detection",
|
|
14731
|
+
"package"
|
|
14732
|
+
]);
|
|
14686
14733
|
/**
|
|
14687
14734
|
* Runtime registry: cap-property-name → cap definition. `BaseDevice`'s
|
|
14688
14735
|
* `state` getter looks up the cap definition here to construct a
|
|
@@ -14776,16 +14823,24 @@ var DEVICE_LOCAL_STATE_CAPS = {
|
|
|
14776
14823
|
})
|
|
14777
14824
|
},
|
|
14778
14825
|
/**
|
|
14779
|
-
* Runtime-state slice —
|
|
14826
|
+
* Runtime-state slice — every stage mirrored together so consumers
|
|
14780
14827
|
* see one reactive handle (`device.state.zoneRules.value`) instead
|
|
14781
|
-
* of
|
|
14782
|
-
* `{motion, detection}` shape, so subscribers always get the
|
|
14828
|
+
* of one per stage. Bulk-replace mutations on any stage write the full
|
|
14829
|
+
* `{motion, detection, package}` shape, so subscribers always get the
|
|
14783
14830
|
* complete current set. Consumers that only care about one stage
|
|
14784
14831
|
* just read the matching property.
|
|
14832
|
+
*
|
|
14833
|
+
* `package` backs the package-drop detector — a package zone is a
|
|
14834
|
+
* `ZoneRule` on the `'package'` stage referencing drawn polygons
|
|
14835
|
+
* (see docs/superpowers/specs/2026-07-17-package-zones-design.md §3.1).
|
|
14836
|
+
* The orchestrator provider that writes this stage lands in a later
|
|
14837
|
+
* slice; until then the mirror carries only `{motion, detection}` and
|
|
14838
|
+
* consumers read `package` as absent (treat as `[]`).
|
|
14785
14839
|
*/
|
|
14786
14840
|
runtimeState: object({
|
|
14787
14841
|
motion: array(ZoneRuleSchema).readonly(),
|
|
14788
|
-
detection: array(ZoneRuleSchema).readonly()
|
|
14842
|
+
detection: array(ZoneRuleSchema).readonly(),
|
|
14843
|
+
package: array(ZoneRuleSchema).readonly()
|
|
14789
14844
|
})
|
|
14790
14845
|
},
|
|
14791
14846
|
zones: zonesCapability
|
|
@@ -18813,6 +18868,7 @@ var EventKindIconSchema = _enum([
|
|
|
18813
18868
|
"smoke",
|
|
18814
18869
|
"water",
|
|
18815
18870
|
"button",
|
|
18871
|
+
"package",
|
|
18816
18872
|
"generic"
|
|
18817
18873
|
]);
|
|
18818
18874
|
var EventKindCategorySchema = _enum([
|
|
@@ -18820,7 +18876,8 @@ var EventKindCategorySchema = _enum([
|
|
|
18820
18876
|
"audio",
|
|
18821
18877
|
"detection",
|
|
18822
18878
|
"sensor",
|
|
18823
|
-
"custom"
|
|
18879
|
+
"custom",
|
|
18880
|
+
"package"
|
|
18824
18881
|
]);
|
|
18825
18882
|
var EventKindDescriptorSchema = object({
|
|
18826
18883
|
/** Stable kind id (e.g. 'motion', 'person', 'contact'). */
|
|
@@ -22483,6 +22540,108 @@ method(object({
|
|
|
22483
22540
|
auth: "admin"
|
|
22484
22541
|
});
|
|
22485
22542
|
/**
|
|
22543
|
+
* `recordingExport` cap — render a footage time range into a single downloadable
|
|
22544
|
+
* MP4 (regular / accelerated / decelerated / timelapse, ± audio), kept for a
|
|
22545
|
+
* bounded lifetime with a durable history, auto-expiry, and optional
|
|
22546
|
+
* delete-after-download.
|
|
22547
|
+
*
|
|
22548
|
+
* Like `recording` this is a `scope:'system', mode:'singleton'` cap: the
|
|
22549
|
+
* recorder self-gates so exactly ONE node (the designated `recordingNodeId`,
|
|
22550
|
+
* default `hub`) registers it. Device-scoped methods carry `deviceId` in their
|
|
22551
|
+
* input and dispatch to that single provider; the render runs on the node that
|
|
22552
|
+
* owns the footage (no cross-node segment transfer). Download rides the
|
|
22553
|
+
* framework addon data-plane. State persists in a DurableState blob (NOT
|
|
22554
|
+
* SQLite); history rows survive file deletion for audit.
|
|
22555
|
+
*/
|
|
22556
|
+
/** Playback-speed multiplier for the render (1 = realtime). */
|
|
22557
|
+
var ExportSpeedSchema = number().min(.25).max(32);
|
|
22558
|
+
/** Timelapse cadence — sample one source frame per `everyMs`, output at `outputFps`. */
|
|
22559
|
+
var ExportTimelapseSchema = object({
|
|
22560
|
+
everyMs: number().int().positive(),
|
|
22561
|
+
outputFps: number().int().min(1).max(60).optional()
|
|
22562
|
+
});
|
|
22563
|
+
/**
|
|
22564
|
+
* Render options. `speed` and `timelapse` are mutually exclusive. `includeAudio`
|
|
22565
|
+
* is honoured only for a realtime-ish speed (0.5–2×); timelapse is always
|
|
22566
|
+
* silent. `maxLifeMs` bounds how long the finished file is kept;
|
|
22567
|
+
* `deleteAfterDownload` removes it shortly after the first complete download.
|
|
22568
|
+
*/
|
|
22569
|
+
var ExportOptionsSchema = object({
|
|
22570
|
+
speed: ExportSpeedSchema.optional(),
|
|
22571
|
+
timelapse: ExportTimelapseSchema.optional(),
|
|
22572
|
+
includeAudio: boolean(),
|
|
22573
|
+
maxLifeMs: number().int().positive(),
|
|
22574
|
+
deleteAfterDownload: boolean(),
|
|
22575
|
+
title: string$2().max(200).optional()
|
|
22576
|
+
}).superRefine((v, ctx) => {
|
|
22577
|
+
if (v.speed !== void 0 && v.timelapse !== void 0) ctx.addIssue({
|
|
22578
|
+
code: ZodIssueCode.custom,
|
|
22579
|
+
message: "speed and timelapse are mutually exclusive",
|
|
22580
|
+
path: ["timelapse"]
|
|
22581
|
+
});
|
|
22582
|
+
});
|
|
22583
|
+
var ExportStateSchema = _enum([
|
|
22584
|
+
"queued",
|
|
22585
|
+
"rendering",
|
|
22586
|
+
"ready",
|
|
22587
|
+
"failed",
|
|
22588
|
+
"expired",
|
|
22589
|
+
"deleted"
|
|
22590
|
+
]);
|
|
22591
|
+
/** One export job / history row. */
|
|
22592
|
+
var ExportRecordSchema = object({
|
|
22593
|
+
id: string$2(),
|
|
22594
|
+
deviceId: number(),
|
|
22595
|
+
profile: string$2(),
|
|
22596
|
+
fromMs: number(),
|
|
22597
|
+
toMs: number(),
|
|
22598
|
+
options: ExportOptionsSchema,
|
|
22599
|
+
state: ExportStateSchema,
|
|
22600
|
+
/** 0–100 while rendering; null otherwise. */
|
|
22601
|
+
progressPct: number().nullable(),
|
|
22602
|
+
/** File size once ready; null before. */
|
|
22603
|
+
fileBytes: number().nullable(),
|
|
22604
|
+
expiresAt: number(),
|
|
22605
|
+
deleteAfterDownload: boolean(),
|
|
22606
|
+
/** Epoch of the first complete download; null until then. */
|
|
22607
|
+
downloadedAt: number().nullable(),
|
|
22608
|
+
createdAt: number(),
|
|
22609
|
+
/** User id/name that requested the export. */
|
|
22610
|
+
createdBy: string$2(),
|
|
22611
|
+
/** Failure reason when state is 'failed'; null otherwise. */
|
|
22612
|
+
error: string$2().nullable()
|
|
22613
|
+
});
|
|
22614
|
+
/** Candidate download URLs (LAN first, then operator extra hosts). */
|
|
22615
|
+
var ExportDownloadSchema = object({
|
|
22616
|
+
url: string$2(),
|
|
22617
|
+
endpoints: array(string$2())
|
|
22618
|
+
});
|
|
22619
|
+
method(object({
|
|
22620
|
+
deviceId: number(),
|
|
22621
|
+
profile: string$2(),
|
|
22622
|
+
fromMs: number(),
|
|
22623
|
+
toMs: number(),
|
|
22624
|
+
options: ExportOptionsSchema
|
|
22625
|
+
}), ExportRecordSchema, {
|
|
22626
|
+
kind: "mutation",
|
|
22627
|
+
auth: "protected"
|
|
22628
|
+
}), method(object({ deviceId: number().optional() }), array(ExportRecordSchema), {
|
|
22629
|
+
kind: "query",
|
|
22630
|
+
auth: "protected"
|
|
22631
|
+
}), method(object({ exportId: string$2() }), ExportRecordSchema, {
|
|
22632
|
+
kind: "query",
|
|
22633
|
+
auth: "protected"
|
|
22634
|
+
}), method(object({ exportId: string$2() }), ExportRecordSchema, {
|
|
22635
|
+
kind: "mutation",
|
|
22636
|
+
auth: "protected"
|
|
22637
|
+
}), method(object({ exportId: string$2() }), ExportRecordSchema, {
|
|
22638
|
+
kind: "mutation",
|
|
22639
|
+
auth: "protected"
|
|
22640
|
+
}), method(object({ exportId: string$2() }), ExportDownloadSchema, {
|
|
22641
|
+
kind: "query",
|
|
22642
|
+
auth: "protected"
|
|
22643
|
+
});
|
|
22644
|
+
/**
|
|
22486
22645
|
* One publishable camera stream as its OWNING PROVIDER describes it — the same
|
|
22487
22646
|
* payload the (legacy) push `streamBroker.publishCameraStream` carried, minus
|
|
22488
22647
|
* `deviceId`.
|
|
@@ -26406,6 +26565,42 @@ Object.freeze({
|
|
|
26406
26565
|
addonId: null,
|
|
26407
26566
|
access: "create"
|
|
26408
26567
|
},
|
|
26568
|
+
"recordingExport.cancelExport": {
|
|
26569
|
+
capName: "recordingExport",
|
|
26570
|
+
capScope: "system",
|
|
26571
|
+
addonId: null,
|
|
26572
|
+
access: "create"
|
|
26573
|
+
},
|
|
26574
|
+
"recordingExport.createExport": {
|
|
26575
|
+
capName: "recordingExport",
|
|
26576
|
+
capScope: "system",
|
|
26577
|
+
addonId: null,
|
|
26578
|
+
access: "create"
|
|
26579
|
+
},
|
|
26580
|
+
"recordingExport.deleteExport": {
|
|
26581
|
+
capName: "recordingExport",
|
|
26582
|
+
capScope: "system",
|
|
26583
|
+
addonId: null,
|
|
26584
|
+
access: "delete"
|
|
26585
|
+
},
|
|
26586
|
+
"recordingExport.getDownloadUrl": {
|
|
26587
|
+
capName: "recordingExport",
|
|
26588
|
+
capScope: "system",
|
|
26589
|
+
addonId: null,
|
|
26590
|
+
access: "view"
|
|
26591
|
+
},
|
|
26592
|
+
"recordingExport.getExport": {
|
|
26593
|
+
capName: "recordingExport",
|
|
26594
|
+
capScope: "system",
|
|
26595
|
+
addonId: null,
|
|
26596
|
+
access: "view"
|
|
26597
|
+
},
|
|
26598
|
+
"recordingExport.listExports": {
|
|
26599
|
+
capName: "recordingExport",
|
|
26600
|
+
capScope: "system",
|
|
26601
|
+
addonId: null,
|
|
26602
|
+
access: "view"
|
|
26603
|
+
},
|
|
26409
26604
|
"sceneMonitor.captureReference": {
|
|
26410
26605
|
capName: "scene-monitor",
|
|
26411
26606
|
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.23",
|
|
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",
|