@camstack/addon-provider-homeassistant 1.1.29 → 1.1.31
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
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
2
2
|
let node_crypto = require("node:crypto");
|
|
3
3
|
let node_zlib = require("node:zlib");
|
|
4
|
-
//#region ../types/dist/event-category-
|
|
4
|
+
//#region ../types/dist/event-category-D4HJq7Mw.mjs
|
|
5
5
|
var EventCategory = /* @__PURE__ */ function(EventCategory) {
|
|
6
6
|
EventCategory["SystemBoot"] = "system.boot";
|
|
7
7
|
EventCategory["SystemAddonsReady"] = "system.addons-ready";
|
|
@@ -154,6 +154,11 @@ var EventCategory = /* @__PURE__ */ function(EventCategory) {
|
|
|
154
154
|
/** Runner-sampled scrub thumbnail (~1/5 s/camera). Telemetry (D8): a lost
|
|
155
155
|
* thumb is a scrub gap the recorder's keyframe backfill covers. */
|
|
156
156
|
EventCategory["RecordingThumbSampled"] = "recording.thumb-sampled";
|
|
157
|
+
/** Export render progress (0–100). Telemetry (D8): a lost tick is a stale
|
|
158
|
+
* progress bar the client reconciles via `recordingExport.getExport`. */
|
|
159
|
+
EventCategory["RecordingExportProgress"] = "recording.export.progress";
|
|
160
|
+
EventCategory["RecordingExportCompleted"] = "recording.export.completed";
|
|
161
|
+
EventCategory["RecordingExportFailed"] = "recording.export.failed";
|
|
157
162
|
EventCategory["DetectionEvent"] = "detection.event";
|
|
158
163
|
EventCategory["SessionTrackNew"] = "session.track.new";
|
|
159
164
|
EventCategory["SessionTrackExpired"] = "session.track.expired";
|
|
@@ -443,6 +448,25 @@ var EventCategory = /* @__PURE__ */ function(EventCategory) {
|
|
|
443
448
|
*/
|
|
444
449
|
EventCategory["PipelineAnalyticsStationaryChanged"] = "pipeline-analytics.stationary-changed";
|
|
445
450
|
/**
|
|
451
|
+
* Fired by `addon-post-analysis` when a package-drop is confirmed inside
|
|
452
|
+
* a package zone — a newly-appeared stationary object of a package class
|
|
453
|
+
* that cleared the class / zone / dwell / size gates. Payload:
|
|
454
|
+
* `PipelineAnalyticsPackageDeliveredPayload` carrying `{ deviceId,
|
|
455
|
+
* entryId, className, zoneIds, keyFrameMediaKey?, bbox, timestamp }`.
|
|
456
|
+
* Telemetry (D8): the durable record is the `package-events` store row;
|
|
457
|
+
* this bus topic drives notifier rules + live UI. See
|
|
458
|
+
* docs/superpowers/specs/2026-07-17-package-zones-design.md §5.1.
|
|
459
|
+
*/
|
|
460
|
+
EventCategory["PipelineAnalyticsPackageDelivered"] = "pipeline-analytics.package-delivered";
|
|
461
|
+
/**
|
|
462
|
+
* Fired by `addon-post-analysis` when a previously-delivered package
|
|
463
|
+
* leaves its zone (the stationary entry departed — moved or swept).
|
|
464
|
+
* Payload: `PipelineAnalyticsPackagePickedUpPayload` carrying
|
|
465
|
+
* `{ deviceId, entryId, deliveredEventId, className, timestamp }`.
|
|
466
|
+
* Telemetry (D8). See package-zones-design §5.2.
|
|
467
|
+
*/
|
|
468
|
+
EventCategory["PipelineAnalyticsPackagePickedUp"] = "pipeline-analytics.package-picked-up";
|
|
469
|
+
/**
|
|
446
470
|
* Fired by `addon-post-analysis` whenever a gallery face row changes:
|
|
447
471
|
* `kind:'buffered'` a new detected face was persisted, `'assigned'` /
|
|
448
472
|
* `'unassigned'` its identity link changed, `'deleted'` the row was
|
|
@@ -5181,6 +5205,25 @@ function _instanceof(cls, params = {}) {
|
|
|
5181
5205
|
};
|
|
5182
5206
|
return inst;
|
|
5183
5207
|
}
|
|
5208
|
+
//#endregion
|
|
5209
|
+
//#region ../../node_modules/zod/v4/classic/compat.js
|
|
5210
|
+
/** @deprecated Use the raw string literal codes instead, e.g. "invalid_type". */
|
|
5211
|
+
var ZodIssueCode = {
|
|
5212
|
+
invalid_type: "invalid_type",
|
|
5213
|
+
too_big: "too_big",
|
|
5214
|
+
too_small: "too_small",
|
|
5215
|
+
invalid_format: "invalid_format",
|
|
5216
|
+
not_multiple_of: "not_multiple_of",
|
|
5217
|
+
unrecognized_keys: "unrecognized_keys",
|
|
5218
|
+
invalid_union: "invalid_union",
|
|
5219
|
+
invalid_key: "invalid_key",
|
|
5220
|
+
invalid_element: "invalid_element",
|
|
5221
|
+
invalid_value: "invalid_value",
|
|
5222
|
+
custom: "custom"
|
|
5223
|
+
};
|
|
5224
|
+
/** @deprecated Do not use. Stub definition, only included for zod-to-json-schema compatibility. */
|
|
5225
|
+
var ZodFirstPartyTypeKind;
|
|
5226
|
+
ZodFirstPartyTypeKind || (ZodFirstPartyTypeKind = {});
|
|
5184
5227
|
Object.fromEntries([
|
|
5185
5228
|
{
|
|
5186
5229
|
id: "overview",
|
|
@@ -7420,6 +7463,62 @@ var RecordingConfigSchema = object({
|
|
|
7420
7463
|
scrubThumbnails: ScrubThumbnailPresetSchema.optional()
|
|
7421
7464
|
});
|
|
7422
7465
|
/**
|
|
7466
|
+
* Ops-log — the durable, append-only operations audit shared by the
|
|
7467
|
+
* recordings and events management surfaces.
|
|
7468
|
+
*
|
|
7469
|
+
* ONE row shape is reused for both domains so a single "Activity" view can
|
|
7470
|
+
* merge the recorder's DurableState ring (recordings ops-log) and the
|
|
7471
|
+
* pipeline-analytics SQLite collection (events ops-log). Each row records a
|
|
7472
|
+
* management operation, WHY it ran (reason), and its measurable effect
|
|
7473
|
+
* (itemsAffected + bytesReclaimed). Writes are best-effort — a failed log must
|
|
7474
|
+
* never fail the operation it records.
|
|
7475
|
+
*/
|
|
7476
|
+
/** Which management domain the operation belongs to. */
|
|
7477
|
+
var OpsLogDomainSchema = _enum(["recording", "events"]);
|
|
7478
|
+
/** The kind of management operation performed. */
|
|
7479
|
+
var OpsLogOpSchema = _enum([
|
|
7480
|
+
"prune",
|
|
7481
|
+
"manual-delete",
|
|
7482
|
+
"rescan",
|
|
7483
|
+
"retention-run"
|
|
7484
|
+
]);
|
|
7485
|
+
/** Why the operation ran. */
|
|
7486
|
+
var OpsLogReasonSchema = _enum([
|
|
7487
|
+
"retention",
|
|
7488
|
+
"quota",
|
|
7489
|
+
"manual",
|
|
7490
|
+
"operator"
|
|
7491
|
+
]);
|
|
7492
|
+
/** One audit row, shared verbatim by both domains. */
|
|
7493
|
+
var OpsLogEntrySchema = object({
|
|
7494
|
+
/** Unique row id. */
|
|
7495
|
+
id: string(),
|
|
7496
|
+
/** Epoch ms the operation completed. */
|
|
7497
|
+
at: number(),
|
|
7498
|
+
domain: OpsLogDomainSchema,
|
|
7499
|
+
op: OpsLogOpSchema,
|
|
7500
|
+
reason: OpsLogReasonSchema,
|
|
7501
|
+
/** The camera the op targeted; null for a cluster/global op. */
|
|
7502
|
+
deviceId: number().nullable(),
|
|
7503
|
+
/** Node that performed the op (the log carries nodeId — no cross-node aggregation). */
|
|
7504
|
+
nodeId: string(),
|
|
7505
|
+
/** Buckets / rows deleted (op-specific unit). */
|
|
7506
|
+
itemsAffected: number(),
|
|
7507
|
+
/** Bytes reclaimed by the op (0 when not measurable). */
|
|
7508
|
+
bytesReclaimed: number(),
|
|
7509
|
+
/** Free-text detail (e.g. "floor moved to <ts>"); null when none. */
|
|
7510
|
+
detail: string().nullable(),
|
|
7511
|
+
/** Who/what triggered the op. */
|
|
7512
|
+
actor: string()
|
|
7513
|
+
});
|
|
7514
|
+
/** Shared query input for the per-domain `listOpsLog` cap methods. */
|
|
7515
|
+
var OpsLogQueryInputSchema = object({
|
|
7516
|
+
/** Restrict to a single camera; omit for every row. */
|
|
7517
|
+
deviceId: number().optional(),
|
|
7518
|
+
/** Max rows returned, newest-first. */
|
|
7519
|
+
limit: number().int().min(1).max(1e3).optional()
|
|
7520
|
+
});
|
|
7521
|
+
/**
|
|
7423
7522
|
* `StorageLocationType` — an addon-declared id that identifies the *kind* of
|
|
7424
7523
|
* storage a location serves. Defined here (not in `capabilities/storage.cap.ts`)
|
|
7425
7524
|
* so the persisted record schema and the consumer-facing cap can both consume it
|
|
@@ -15013,7 +15112,11 @@ array(ZoneRuleSchema).readonly();
|
|
|
15013
15112
|
* Extend the enum here when a new gating consumer comes online (audio
|
|
15014
15113
|
* gating, alert filtering, …) — no other surface needs to change.
|
|
15015
15114
|
*/
|
|
15016
|
-
var ZoneRuleStageEnum = _enum([
|
|
15115
|
+
var ZoneRuleStageEnum = _enum([
|
|
15116
|
+
"motion",
|
|
15117
|
+
"detection",
|
|
15118
|
+
"package"
|
|
15119
|
+
]);
|
|
15017
15120
|
/**
|
|
15018
15121
|
* Runtime registry: cap-property-name → cap definition. `BaseDevice`'s
|
|
15019
15122
|
* `state` getter looks up the cap definition here to construct a
|
|
@@ -15107,16 +15210,25 @@ var DEVICE_LOCAL_STATE_CAPS = {
|
|
|
15107
15210
|
})
|
|
15108
15211
|
},
|
|
15109
15212
|
/**
|
|
15110
|
-
* Runtime-state slice —
|
|
15213
|
+
* Runtime-state slice — every stage mirrored together so consumers
|
|
15111
15214
|
* see one reactive handle (`device.state.zoneRules.value`) instead
|
|
15112
|
-
* of
|
|
15113
|
-
* `{motion, detection}` shape, so subscribers always get the
|
|
15215
|
+
* of one per stage. Bulk-replace mutations on any stage write the full
|
|
15216
|
+
* `{motion, detection, package}` shape, so subscribers always get the
|
|
15114
15217
|
* complete current set. Consumers that only care about one stage
|
|
15115
15218
|
* just read the matching property.
|
|
15219
|
+
*
|
|
15220
|
+
* `package` backs the package-drop detector — a package zone is a
|
|
15221
|
+
* `ZoneRule` on the `'package'` stage referencing drawn polygons
|
|
15222
|
+
* (see docs/superpowers/specs/2026-07-17-package-zones-design.md §3.1).
|
|
15223
|
+
* The orchestrator provider writes this stage as a first-class slice
|
|
15224
|
+
* (Phase 4): every mutation mirrors the full `{motion, detection,
|
|
15225
|
+
* package}` shape, so consumers read the current package rules directly
|
|
15226
|
+
* off `device.state.zoneRules.value.package`.
|
|
15116
15227
|
*/
|
|
15117
15228
|
runtimeState: object({
|
|
15118
15229
|
motion: array(ZoneRuleSchema).readonly(),
|
|
15119
|
-
detection: array(ZoneRuleSchema).readonly()
|
|
15230
|
+
detection: array(ZoneRuleSchema).readonly(),
|
|
15231
|
+
package: array(ZoneRuleSchema).readonly()
|
|
15120
15232
|
})
|
|
15121
15233
|
},
|
|
15122
15234
|
zones: zonesCapability
|
|
@@ -19177,6 +19289,7 @@ var EventKindIconSchema = _enum([
|
|
|
19177
19289
|
"smoke",
|
|
19178
19290
|
"water",
|
|
19179
19291
|
"button",
|
|
19292
|
+
"package",
|
|
19180
19293
|
"generic"
|
|
19181
19294
|
]);
|
|
19182
19295
|
var EventKindCategorySchema = _enum([
|
|
@@ -19184,7 +19297,8 @@ var EventKindCategorySchema = _enum([
|
|
|
19184
19297
|
"audio",
|
|
19185
19298
|
"detection",
|
|
19186
19299
|
"sensor",
|
|
19187
|
-
"custom"
|
|
19300
|
+
"custom",
|
|
19301
|
+
"package"
|
|
19188
19302
|
]);
|
|
19189
19303
|
var EventKindDescriptorSchema = object({
|
|
19190
19304
|
/** Stable kind id (e.g. 'motion', 'person', 'contact'). */
|
|
@@ -19525,6 +19639,26 @@ var TrackCascadeCountsSchema = object({
|
|
|
19525
19639
|
/** Per-track CLIP search vectors removed (best-effort). */
|
|
19526
19640
|
embeddings: number().int()
|
|
19527
19641
|
});
|
|
19642
|
+
/** Event-store footprint for one camera. */
|
|
19643
|
+
var EventStoreDeviceFootprintSchema = object({
|
|
19644
|
+
deviceId: number(),
|
|
19645
|
+
/** Persisted event rows (motion + object + audio) for the camera. */
|
|
19646
|
+
rows: number().int(),
|
|
19647
|
+
/** Event-owned media bytes on disk for the camera. */
|
|
19648
|
+
bytes: number().int()
|
|
19649
|
+
});
|
|
19650
|
+
/** Aggregate event-store footprint: global totals + per-camera breakdown. */
|
|
19651
|
+
var EventStoreFootprintSchema = object({
|
|
19652
|
+
totalRows: number().int(),
|
|
19653
|
+
totalBytes: number().int(),
|
|
19654
|
+
devices: array(EventStoreDeviceFootprintSchema).readonly()
|
|
19655
|
+
});
|
|
19656
|
+
/** Per-kind counts returned by the event-prune / device-delete mutations. */
|
|
19657
|
+
var EventPruneCountsSchema = object({
|
|
19658
|
+
motion: number().int(),
|
|
19659
|
+
object: number().int(),
|
|
19660
|
+
audio: number().int()
|
|
19661
|
+
});
|
|
19528
19662
|
DeviceType.Camera, method(object({ deviceId: number() }), array(TrackSchema).readonly()), method(object({
|
|
19529
19663
|
deviceId: number(),
|
|
19530
19664
|
trackId: string()
|
|
@@ -19588,6 +19722,21 @@ DeviceType.Camera, method(object({ deviceId: number() }), array(TrackSchema).rea
|
|
|
19588
19722
|
}), {
|
|
19589
19723
|
kind: "mutation",
|
|
19590
19724
|
auth: "admin"
|
|
19725
|
+
}), method(object({}), EventStoreFootprintSchema, {
|
|
19726
|
+
kind: "query",
|
|
19727
|
+
auth: "admin"
|
|
19728
|
+
}), method(object({
|
|
19729
|
+
olderThanMs: number(),
|
|
19730
|
+
reason: OpsLogReasonSchema.optional()
|
|
19731
|
+
}), EventPruneCountsSchema, {
|
|
19732
|
+
kind: "mutation",
|
|
19733
|
+
auth: "admin"
|
|
19734
|
+
}), method(object({ deviceId: number() }), EventPruneCountsSchema, {
|
|
19735
|
+
kind: "mutation",
|
|
19736
|
+
auth: "admin"
|
|
19737
|
+
}), method(OpsLogQueryInputSchema, array(OpsLogEntrySchema).readonly(), {
|
|
19738
|
+
kind: "query",
|
|
19739
|
+
auth: "admin"
|
|
19591
19740
|
}), method(object({
|
|
19592
19741
|
eventId: string(),
|
|
19593
19742
|
kind: MediaFileKindEnum.optional()
|
|
@@ -22910,13 +23059,131 @@ method(object({
|
|
|
22910
23059
|
}), method(object({ deviceId: number() }), RecordingStatusSchema, {
|
|
22911
23060
|
kind: "mutation",
|
|
22912
23061
|
auth: "admin"
|
|
22913
|
-
}), method(object({
|
|
23062
|
+
}), method(object({
|
|
23063
|
+
deviceId: number(),
|
|
23064
|
+
reason: OpsLogReasonSchema.optional()
|
|
23065
|
+
}), object({
|
|
22914
23066
|
floorMs: number().nullable(),
|
|
22915
23067
|
deletedBuckets: number().int(),
|
|
22916
23068
|
reclaimedBytes: number().int()
|
|
22917
23069
|
}), {
|
|
22918
23070
|
kind: "mutation",
|
|
22919
23071
|
auth: "admin"
|
|
23072
|
+
}), method(object({
|
|
23073
|
+
deviceId: number(),
|
|
23074
|
+
fromMs: number().optional(),
|
|
23075
|
+
toMs: number().optional()
|
|
23076
|
+
}), object({
|
|
23077
|
+
deletedBuckets: number().int(),
|
|
23078
|
+
reclaimedBytes: number().int()
|
|
23079
|
+
}), {
|
|
23080
|
+
kind: "mutation",
|
|
23081
|
+
auth: "admin"
|
|
23082
|
+
}), method(OpsLogQueryInputSchema, array(OpsLogEntrySchema).readonly(), {
|
|
23083
|
+
kind: "query",
|
|
23084
|
+
auth: "admin"
|
|
23085
|
+
});
|
|
23086
|
+
/**
|
|
23087
|
+
* `recordingExport` cap — render a footage time range into a single downloadable
|
|
23088
|
+
* MP4 (regular / accelerated / decelerated / timelapse, ± audio), kept for a
|
|
23089
|
+
* bounded lifetime with a durable history, auto-expiry, and optional
|
|
23090
|
+
* delete-after-download.
|
|
23091
|
+
*
|
|
23092
|
+
* Like `recording` this is a `scope:'system', mode:'singleton'` cap: the
|
|
23093
|
+
* recorder self-gates so exactly ONE node (the designated `recordingNodeId`,
|
|
23094
|
+
* default `hub`) registers it. Device-scoped methods carry `deviceId` in their
|
|
23095
|
+
* input and dispatch to that single provider; the render runs on the node that
|
|
23096
|
+
* owns the footage (no cross-node segment transfer). Download rides the
|
|
23097
|
+
* framework addon data-plane. State persists in a DurableState blob (NOT
|
|
23098
|
+
* SQLite); history rows survive file deletion for audit.
|
|
23099
|
+
*/
|
|
23100
|
+
/** Playback-speed multiplier for the render (1 = realtime). */
|
|
23101
|
+
var ExportSpeedSchema = number().min(.25).max(32);
|
|
23102
|
+
/** Timelapse cadence — sample one source frame per `everyMs`, output at `outputFps`. */
|
|
23103
|
+
var ExportTimelapseSchema = object({
|
|
23104
|
+
everyMs: number().int().positive(),
|
|
23105
|
+
outputFps: number().int().min(1).max(60).optional()
|
|
23106
|
+
});
|
|
23107
|
+
/**
|
|
23108
|
+
* Render options. `speed` and `timelapse` are mutually exclusive. `includeAudio`
|
|
23109
|
+
* is honoured only for a realtime-ish speed (0.5–2×); timelapse is always
|
|
23110
|
+
* silent. `maxLifeMs` bounds how long the finished file is kept;
|
|
23111
|
+
* `deleteAfterDownload` removes it shortly after the first complete download.
|
|
23112
|
+
*/
|
|
23113
|
+
var ExportOptionsSchema = object({
|
|
23114
|
+
speed: ExportSpeedSchema.optional(),
|
|
23115
|
+
timelapse: ExportTimelapseSchema.optional(),
|
|
23116
|
+
includeAudio: boolean(),
|
|
23117
|
+
maxLifeMs: number().int().positive(),
|
|
23118
|
+
deleteAfterDownload: boolean(),
|
|
23119
|
+
title: string().max(200).optional()
|
|
23120
|
+
}).superRefine((v, ctx) => {
|
|
23121
|
+
if (v.speed !== void 0 && v.timelapse !== void 0) ctx.addIssue({
|
|
23122
|
+
code: ZodIssueCode.custom,
|
|
23123
|
+
message: "speed and timelapse are mutually exclusive",
|
|
23124
|
+
path: ["timelapse"]
|
|
23125
|
+
});
|
|
23126
|
+
});
|
|
23127
|
+
var ExportStateSchema = _enum([
|
|
23128
|
+
"queued",
|
|
23129
|
+
"rendering",
|
|
23130
|
+
"ready",
|
|
23131
|
+
"failed",
|
|
23132
|
+
"expired",
|
|
23133
|
+
"deleted"
|
|
23134
|
+
]);
|
|
23135
|
+
/** One export job / history row. */
|
|
23136
|
+
var ExportRecordSchema = object({
|
|
23137
|
+
id: string(),
|
|
23138
|
+
deviceId: number(),
|
|
23139
|
+
profile: string(),
|
|
23140
|
+
fromMs: number(),
|
|
23141
|
+
toMs: number(),
|
|
23142
|
+
options: ExportOptionsSchema,
|
|
23143
|
+
state: ExportStateSchema,
|
|
23144
|
+
/** 0–100 while rendering; null otherwise. */
|
|
23145
|
+
progressPct: number().nullable(),
|
|
23146
|
+
/** File size once ready; null before. */
|
|
23147
|
+
fileBytes: number().nullable(),
|
|
23148
|
+
expiresAt: number(),
|
|
23149
|
+
deleteAfterDownload: boolean(),
|
|
23150
|
+
/** Epoch of the first complete download; null until then. */
|
|
23151
|
+
downloadedAt: number().nullable(),
|
|
23152
|
+
createdAt: number(),
|
|
23153
|
+
/** User id/name that requested the export. */
|
|
23154
|
+
createdBy: string(),
|
|
23155
|
+
/** Failure reason when state is 'failed'; null otherwise. */
|
|
23156
|
+
error: string().nullable()
|
|
23157
|
+
});
|
|
23158
|
+
/** Candidate download URLs (LAN first, then operator extra hosts). */
|
|
23159
|
+
var ExportDownloadSchema = object({
|
|
23160
|
+
url: string(),
|
|
23161
|
+
endpoints: array(string())
|
|
23162
|
+
});
|
|
23163
|
+
method(object({
|
|
23164
|
+
deviceId: number(),
|
|
23165
|
+
profile: string(),
|
|
23166
|
+
fromMs: number(),
|
|
23167
|
+
toMs: number(),
|
|
23168
|
+
options: ExportOptionsSchema
|
|
23169
|
+
}), ExportRecordSchema, {
|
|
23170
|
+
kind: "mutation",
|
|
23171
|
+
auth: "protected"
|
|
23172
|
+
}), method(object({ deviceId: number().optional() }), array(ExportRecordSchema), {
|
|
23173
|
+
kind: "query",
|
|
23174
|
+
auth: "protected"
|
|
23175
|
+
}), method(object({ exportId: string() }), ExportRecordSchema, {
|
|
23176
|
+
kind: "query",
|
|
23177
|
+
auth: "protected"
|
|
23178
|
+
}), method(object({ exportId: string() }), ExportRecordSchema, {
|
|
23179
|
+
kind: "mutation",
|
|
23180
|
+
auth: "protected"
|
|
23181
|
+
}), method(object({ exportId: string() }), ExportRecordSchema, {
|
|
23182
|
+
kind: "mutation",
|
|
23183
|
+
auth: "protected"
|
|
23184
|
+
}), method(object({ exportId: string() }), ExportDownloadSchema, {
|
|
23185
|
+
kind: "query",
|
|
23186
|
+
auth: "protected"
|
|
22920
23187
|
});
|
|
22921
23188
|
/**
|
|
22922
23189
|
* One publishable camera stream as its OWNING PROVIDER describes it — the same
|
|
@@ -25936,6 +26203,12 @@ Object.freeze({
|
|
|
25936
26203
|
addonId: null,
|
|
25937
26204
|
access: "delete"
|
|
25938
26205
|
},
|
|
26206
|
+
"pipelineAnalytics.deleteDeviceEvents": {
|
|
26207
|
+
capName: "pipeline-analytics",
|
|
26208
|
+
capScope: "device",
|
|
26209
|
+
addonId: null,
|
|
26210
|
+
access: "delete"
|
|
26211
|
+
},
|
|
25939
26212
|
"pipelineAnalytics.deleteTracks": {
|
|
25940
26213
|
capName: "pipeline-analytics",
|
|
25941
26214
|
capScope: "device",
|
|
@@ -25966,6 +26239,12 @@ Object.freeze({
|
|
|
25966
26239
|
addonId: null,
|
|
25967
26240
|
access: "view"
|
|
25968
26241
|
},
|
|
26242
|
+
"pipelineAnalytics.getEventStoreFootprint": {
|
|
26243
|
+
capName: "pipeline-analytics",
|
|
26244
|
+
capScope: "device",
|
|
26245
|
+
addonId: null,
|
|
26246
|
+
access: "view"
|
|
26247
|
+
},
|
|
25969
26248
|
"pipelineAnalytics.getKeyEvents": {
|
|
25970
26249
|
capName: "pipeline-analytics",
|
|
25971
26250
|
capScope: "device",
|
|
@@ -26008,6 +26287,12 @@ Object.freeze({
|
|
|
26008
26287
|
addonId: null,
|
|
26009
26288
|
access: "view"
|
|
26010
26289
|
},
|
|
26290
|
+
"pipelineAnalytics.listOpsLog": {
|
|
26291
|
+
capName: "pipeline-analytics",
|
|
26292
|
+
capScope: "device",
|
|
26293
|
+
addonId: null,
|
|
26294
|
+
access: "view"
|
|
26295
|
+
},
|
|
26011
26296
|
"pipelineAnalytics.listRecentTracks": {
|
|
26012
26297
|
capName: "pipeline-analytics",
|
|
26013
26298
|
capScope: "device",
|
|
@@ -26020,6 +26305,12 @@ Object.freeze({
|
|
|
26020
26305
|
addonId: null,
|
|
26021
26306
|
access: "view"
|
|
26022
26307
|
},
|
|
26308
|
+
"pipelineAnalytics.pruneEvents": {
|
|
26309
|
+
capName: "pipeline-analytics",
|
|
26310
|
+
capScope: "device",
|
|
26311
|
+
addonId: null,
|
|
26312
|
+
access: "create"
|
|
26313
|
+
},
|
|
26023
26314
|
"pipelineAnalytics.pruneEventsBefore": {
|
|
26024
26315
|
capName: "pipeline-analytics",
|
|
26025
26316
|
capScope: "device",
|
|
@@ -26782,6 +27073,12 @@ Object.freeze({
|
|
|
26782
27073
|
addonId: null,
|
|
26783
27074
|
access: "create"
|
|
26784
27075
|
},
|
|
27076
|
+
"recording.deleteFootprint": {
|
|
27077
|
+
capName: "recording",
|
|
27078
|
+
capScope: "system",
|
|
27079
|
+
addonId: null,
|
|
27080
|
+
access: "delete"
|
|
27081
|
+
},
|
|
26785
27082
|
"recording.getAvailability": {
|
|
26786
27083
|
capName: "recording",
|
|
26787
27084
|
capScope: "system",
|
|
@@ -26812,6 +27109,12 @@ Object.freeze({
|
|
|
26812
27109
|
addonId: null,
|
|
26813
27110
|
access: "view"
|
|
26814
27111
|
},
|
|
27112
|
+
"recording.listOpsLog": {
|
|
27113
|
+
capName: "recording",
|
|
27114
|
+
capScope: "system",
|
|
27115
|
+
addonId: null,
|
|
27116
|
+
access: "view"
|
|
27117
|
+
},
|
|
26815
27118
|
"recording.locateSegment": {
|
|
26816
27119
|
capName: "recording",
|
|
26817
27120
|
capScope: "system",
|
|
@@ -26842,6 +27145,42 @@ Object.freeze({
|
|
|
26842
27145
|
addonId: null,
|
|
26843
27146
|
access: "create"
|
|
26844
27147
|
},
|
|
27148
|
+
"recordingExport.cancelExport": {
|
|
27149
|
+
capName: "recordingExport",
|
|
27150
|
+
capScope: "system",
|
|
27151
|
+
addonId: null,
|
|
27152
|
+
access: "create"
|
|
27153
|
+
},
|
|
27154
|
+
"recordingExport.createExport": {
|
|
27155
|
+
capName: "recordingExport",
|
|
27156
|
+
capScope: "system",
|
|
27157
|
+
addonId: null,
|
|
27158
|
+
access: "create"
|
|
27159
|
+
},
|
|
27160
|
+
"recordingExport.deleteExport": {
|
|
27161
|
+
capName: "recordingExport",
|
|
27162
|
+
capScope: "system",
|
|
27163
|
+
addonId: null,
|
|
27164
|
+
access: "delete"
|
|
27165
|
+
},
|
|
27166
|
+
"recordingExport.getDownloadUrl": {
|
|
27167
|
+
capName: "recordingExport",
|
|
27168
|
+
capScope: "system",
|
|
27169
|
+
addonId: null,
|
|
27170
|
+
access: "view"
|
|
27171
|
+
},
|
|
27172
|
+
"recordingExport.getExport": {
|
|
27173
|
+
capName: "recordingExport",
|
|
27174
|
+
capScope: "system",
|
|
27175
|
+
addonId: null,
|
|
27176
|
+
access: "view"
|
|
27177
|
+
},
|
|
27178
|
+
"recordingExport.listExports": {
|
|
27179
|
+
capName: "recordingExport",
|
|
27180
|
+
capScope: "system",
|
|
27181
|
+
addonId: null,
|
|
27182
|
+
access: "view"
|
|
27183
|
+
},
|
|
26845
27184
|
"sceneMonitor.captureReference": {
|
|
26846
27185
|
capName: "scene-monitor",
|
|
26847
27186
|
capScope: "device",
|
package/dist/addon.mjs
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { randomUUID } from "node:crypto";
|
|
2
2
|
import { brotliCompressSync, deflateSync, gzipSync } from "node:zlib";
|
|
3
|
-
//#region ../types/dist/event-category-
|
|
3
|
+
//#region ../types/dist/event-category-D4HJq7Mw.mjs
|
|
4
4
|
var EventCategory = /* @__PURE__ */ function(EventCategory) {
|
|
5
5
|
EventCategory["SystemBoot"] = "system.boot";
|
|
6
6
|
EventCategory["SystemAddonsReady"] = "system.addons-ready";
|
|
@@ -153,6 +153,11 @@ var EventCategory = /* @__PURE__ */ function(EventCategory) {
|
|
|
153
153
|
/** Runner-sampled scrub thumbnail (~1/5 s/camera). Telemetry (D8): a lost
|
|
154
154
|
* thumb is a scrub gap the recorder's keyframe backfill covers. */
|
|
155
155
|
EventCategory["RecordingThumbSampled"] = "recording.thumb-sampled";
|
|
156
|
+
/** Export render progress (0–100). Telemetry (D8): a lost tick is a stale
|
|
157
|
+
* progress bar the client reconciles via `recordingExport.getExport`. */
|
|
158
|
+
EventCategory["RecordingExportProgress"] = "recording.export.progress";
|
|
159
|
+
EventCategory["RecordingExportCompleted"] = "recording.export.completed";
|
|
160
|
+
EventCategory["RecordingExportFailed"] = "recording.export.failed";
|
|
156
161
|
EventCategory["DetectionEvent"] = "detection.event";
|
|
157
162
|
EventCategory["SessionTrackNew"] = "session.track.new";
|
|
158
163
|
EventCategory["SessionTrackExpired"] = "session.track.expired";
|
|
@@ -442,6 +447,25 @@ var EventCategory = /* @__PURE__ */ function(EventCategory) {
|
|
|
442
447
|
*/
|
|
443
448
|
EventCategory["PipelineAnalyticsStationaryChanged"] = "pipeline-analytics.stationary-changed";
|
|
444
449
|
/**
|
|
450
|
+
* Fired by `addon-post-analysis` when a package-drop is confirmed inside
|
|
451
|
+
* a package zone — a newly-appeared stationary object of a package class
|
|
452
|
+
* that cleared the class / zone / dwell / size gates. Payload:
|
|
453
|
+
* `PipelineAnalyticsPackageDeliveredPayload` carrying `{ deviceId,
|
|
454
|
+
* entryId, className, zoneIds, keyFrameMediaKey?, bbox, timestamp }`.
|
|
455
|
+
* Telemetry (D8): the durable record is the `package-events` store row;
|
|
456
|
+
* this bus topic drives notifier rules + live UI. See
|
|
457
|
+
* docs/superpowers/specs/2026-07-17-package-zones-design.md §5.1.
|
|
458
|
+
*/
|
|
459
|
+
EventCategory["PipelineAnalyticsPackageDelivered"] = "pipeline-analytics.package-delivered";
|
|
460
|
+
/**
|
|
461
|
+
* Fired by `addon-post-analysis` when a previously-delivered package
|
|
462
|
+
* leaves its zone (the stationary entry departed — moved or swept).
|
|
463
|
+
* Payload: `PipelineAnalyticsPackagePickedUpPayload` carrying
|
|
464
|
+
* `{ deviceId, entryId, deliveredEventId, className, timestamp }`.
|
|
465
|
+
* Telemetry (D8). See package-zones-design §5.2.
|
|
466
|
+
*/
|
|
467
|
+
EventCategory["PipelineAnalyticsPackagePickedUp"] = "pipeline-analytics.package-picked-up";
|
|
468
|
+
/**
|
|
445
469
|
* Fired by `addon-post-analysis` whenever a gallery face row changes:
|
|
446
470
|
* `kind:'buffered'` a new detected face was persisted, `'assigned'` /
|
|
447
471
|
* `'unassigned'` its identity link changed, `'deleted'` the row was
|
|
@@ -5180,6 +5204,25 @@ function _instanceof(cls, params = {}) {
|
|
|
5180
5204
|
};
|
|
5181
5205
|
return inst;
|
|
5182
5206
|
}
|
|
5207
|
+
//#endregion
|
|
5208
|
+
//#region ../../node_modules/zod/v4/classic/compat.js
|
|
5209
|
+
/** @deprecated Use the raw string literal codes instead, e.g. "invalid_type". */
|
|
5210
|
+
var ZodIssueCode = {
|
|
5211
|
+
invalid_type: "invalid_type",
|
|
5212
|
+
too_big: "too_big",
|
|
5213
|
+
too_small: "too_small",
|
|
5214
|
+
invalid_format: "invalid_format",
|
|
5215
|
+
not_multiple_of: "not_multiple_of",
|
|
5216
|
+
unrecognized_keys: "unrecognized_keys",
|
|
5217
|
+
invalid_union: "invalid_union",
|
|
5218
|
+
invalid_key: "invalid_key",
|
|
5219
|
+
invalid_element: "invalid_element",
|
|
5220
|
+
invalid_value: "invalid_value",
|
|
5221
|
+
custom: "custom"
|
|
5222
|
+
};
|
|
5223
|
+
/** @deprecated Do not use. Stub definition, only included for zod-to-json-schema compatibility. */
|
|
5224
|
+
var ZodFirstPartyTypeKind;
|
|
5225
|
+
ZodFirstPartyTypeKind || (ZodFirstPartyTypeKind = {});
|
|
5183
5226
|
Object.fromEntries([
|
|
5184
5227
|
{
|
|
5185
5228
|
id: "overview",
|
|
@@ -7419,6 +7462,62 @@ var RecordingConfigSchema = object({
|
|
|
7419
7462
|
scrubThumbnails: ScrubThumbnailPresetSchema.optional()
|
|
7420
7463
|
});
|
|
7421
7464
|
/**
|
|
7465
|
+
* Ops-log — the durable, append-only operations audit shared by the
|
|
7466
|
+
* recordings and events management surfaces.
|
|
7467
|
+
*
|
|
7468
|
+
* ONE row shape is reused for both domains so a single "Activity" view can
|
|
7469
|
+
* merge the recorder's DurableState ring (recordings ops-log) and the
|
|
7470
|
+
* pipeline-analytics SQLite collection (events ops-log). Each row records a
|
|
7471
|
+
* management operation, WHY it ran (reason), and its measurable effect
|
|
7472
|
+
* (itemsAffected + bytesReclaimed). Writes are best-effort — a failed log must
|
|
7473
|
+
* never fail the operation it records.
|
|
7474
|
+
*/
|
|
7475
|
+
/** Which management domain the operation belongs to. */
|
|
7476
|
+
var OpsLogDomainSchema = _enum(["recording", "events"]);
|
|
7477
|
+
/** The kind of management operation performed. */
|
|
7478
|
+
var OpsLogOpSchema = _enum([
|
|
7479
|
+
"prune",
|
|
7480
|
+
"manual-delete",
|
|
7481
|
+
"rescan",
|
|
7482
|
+
"retention-run"
|
|
7483
|
+
]);
|
|
7484
|
+
/** Why the operation ran. */
|
|
7485
|
+
var OpsLogReasonSchema = _enum([
|
|
7486
|
+
"retention",
|
|
7487
|
+
"quota",
|
|
7488
|
+
"manual",
|
|
7489
|
+
"operator"
|
|
7490
|
+
]);
|
|
7491
|
+
/** One audit row, shared verbatim by both domains. */
|
|
7492
|
+
var OpsLogEntrySchema = object({
|
|
7493
|
+
/** Unique row id. */
|
|
7494
|
+
id: string(),
|
|
7495
|
+
/** Epoch ms the operation completed. */
|
|
7496
|
+
at: number(),
|
|
7497
|
+
domain: OpsLogDomainSchema,
|
|
7498
|
+
op: OpsLogOpSchema,
|
|
7499
|
+
reason: OpsLogReasonSchema,
|
|
7500
|
+
/** The camera the op targeted; null for a cluster/global op. */
|
|
7501
|
+
deviceId: number().nullable(),
|
|
7502
|
+
/** Node that performed the op (the log carries nodeId — no cross-node aggregation). */
|
|
7503
|
+
nodeId: string(),
|
|
7504
|
+
/** Buckets / rows deleted (op-specific unit). */
|
|
7505
|
+
itemsAffected: number(),
|
|
7506
|
+
/** Bytes reclaimed by the op (0 when not measurable). */
|
|
7507
|
+
bytesReclaimed: number(),
|
|
7508
|
+
/** Free-text detail (e.g. "floor moved to <ts>"); null when none. */
|
|
7509
|
+
detail: string().nullable(),
|
|
7510
|
+
/** Who/what triggered the op. */
|
|
7511
|
+
actor: string()
|
|
7512
|
+
});
|
|
7513
|
+
/** Shared query input for the per-domain `listOpsLog` cap methods. */
|
|
7514
|
+
var OpsLogQueryInputSchema = object({
|
|
7515
|
+
/** Restrict to a single camera; omit for every row. */
|
|
7516
|
+
deviceId: number().optional(),
|
|
7517
|
+
/** Max rows returned, newest-first. */
|
|
7518
|
+
limit: number().int().min(1).max(1e3).optional()
|
|
7519
|
+
});
|
|
7520
|
+
/**
|
|
7422
7521
|
* `StorageLocationType` — an addon-declared id that identifies the *kind* of
|
|
7423
7522
|
* storage a location serves. Defined here (not in `capabilities/storage.cap.ts`)
|
|
7424
7523
|
* so the persisted record schema and the consumer-facing cap can both consume it
|
|
@@ -15012,7 +15111,11 @@ array(ZoneRuleSchema).readonly();
|
|
|
15012
15111
|
* Extend the enum here when a new gating consumer comes online (audio
|
|
15013
15112
|
* gating, alert filtering, …) — no other surface needs to change.
|
|
15014
15113
|
*/
|
|
15015
|
-
var ZoneRuleStageEnum = _enum([
|
|
15114
|
+
var ZoneRuleStageEnum = _enum([
|
|
15115
|
+
"motion",
|
|
15116
|
+
"detection",
|
|
15117
|
+
"package"
|
|
15118
|
+
]);
|
|
15016
15119
|
/**
|
|
15017
15120
|
* Runtime registry: cap-property-name → cap definition. `BaseDevice`'s
|
|
15018
15121
|
* `state` getter looks up the cap definition here to construct a
|
|
@@ -15106,16 +15209,25 @@ var DEVICE_LOCAL_STATE_CAPS = {
|
|
|
15106
15209
|
})
|
|
15107
15210
|
},
|
|
15108
15211
|
/**
|
|
15109
|
-
* Runtime-state slice —
|
|
15212
|
+
* Runtime-state slice — every stage mirrored together so consumers
|
|
15110
15213
|
* see one reactive handle (`device.state.zoneRules.value`) instead
|
|
15111
|
-
* of
|
|
15112
|
-
* `{motion, detection}` shape, so subscribers always get the
|
|
15214
|
+
* of one per stage. Bulk-replace mutations on any stage write the full
|
|
15215
|
+
* `{motion, detection, package}` shape, so subscribers always get the
|
|
15113
15216
|
* complete current set. Consumers that only care about one stage
|
|
15114
15217
|
* just read the matching property.
|
|
15218
|
+
*
|
|
15219
|
+
* `package` backs the package-drop detector — a package zone is a
|
|
15220
|
+
* `ZoneRule` on the `'package'` stage referencing drawn polygons
|
|
15221
|
+
* (see docs/superpowers/specs/2026-07-17-package-zones-design.md §3.1).
|
|
15222
|
+
* The orchestrator provider writes this stage as a first-class slice
|
|
15223
|
+
* (Phase 4): every mutation mirrors the full `{motion, detection,
|
|
15224
|
+
* package}` shape, so consumers read the current package rules directly
|
|
15225
|
+
* off `device.state.zoneRules.value.package`.
|
|
15115
15226
|
*/
|
|
15116
15227
|
runtimeState: object({
|
|
15117
15228
|
motion: array(ZoneRuleSchema).readonly(),
|
|
15118
|
-
detection: array(ZoneRuleSchema).readonly()
|
|
15229
|
+
detection: array(ZoneRuleSchema).readonly(),
|
|
15230
|
+
package: array(ZoneRuleSchema).readonly()
|
|
15119
15231
|
})
|
|
15120
15232
|
},
|
|
15121
15233
|
zones: zonesCapability
|
|
@@ -19176,6 +19288,7 @@ var EventKindIconSchema = _enum([
|
|
|
19176
19288
|
"smoke",
|
|
19177
19289
|
"water",
|
|
19178
19290
|
"button",
|
|
19291
|
+
"package",
|
|
19179
19292
|
"generic"
|
|
19180
19293
|
]);
|
|
19181
19294
|
var EventKindCategorySchema = _enum([
|
|
@@ -19183,7 +19296,8 @@ var EventKindCategorySchema = _enum([
|
|
|
19183
19296
|
"audio",
|
|
19184
19297
|
"detection",
|
|
19185
19298
|
"sensor",
|
|
19186
|
-
"custom"
|
|
19299
|
+
"custom",
|
|
19300
|
+
"package"
|
|
19187
19301
|
]);
|
|
19188
19302
|
var EventKindDescriptorSchema = object({
|
|
19189
19303
|
/** Stable kind id (e.g. 'motion', 'person', 'contact'). */
|
|
@@ -19524,6 +19638,26 @@ var TrackCascadeCountsSchema = object({
|
|
|
19524
19638
|
/** Per-track CLIP search vectors removed (best-effort). */
|
|
19525
19639
|
embeddings: number().int()
|
|
19526
19640
|
});
|
|
19641
|
+
/** Event-store footprint for one camera. */
|
|
19642
|
+
var EventStoreDeviceFootprintSchema = object({
|
|
19643
|
+
deviceId: number(),
|
|
19644
|
+
/** Persisted event rows (motion + object + audio) for the camera. */
|
|
19645
|
+
rows: number().int(),
|
|
19646
|
+
/** Event-owned media bytes on disk for the camera. */
|
|
19647
|
+
bytes: number().int()
|
|
19648
|
+
});
|
|
19649
|
+
/** Aggregate event-store footprint: global totals + per-camera breakdown. */
|
|
19650
|
+
var EventStoreFootprintSchema = object({
|
|
19651
|
+
totalRows: number().int(),
|
|
19652
|
+
totalBytes: number().int(),
|
|
19653
|
+
devices: array(EventStoreDeviceFootprintSchema).readonly()
|
|
19654
|
+
});
|
|
19655
|
+
/** Per-kind counts returned by the event-prune / device-delete mutations. */
|
|
19656
|
+
var EventPruneCountsSchema = object({
|
|
19657
|
+
motion: number().int(),
|
|
19658
|
+
object: number().int(),
|
|
19659
|
+
audio: number().int()
|
|
19660
|
+
});
|
|
19527
19661
|
DeviceType.Camera, method(object({ deviceId: number() }), array(TrackSchema).readonly()), method(object({
|
|
19528
19662
|
deviceId: number(),
|
|
19529
19663
|
trackId: string()
|
|
@@ -19587,6 +19721,21 @@ DeviceType.Camera, method(object({ deviceId: number() }), array(TrackSchema).rea
|
|
|
19587
19721
|
}), {
|
|
19588
19722
|
kind: "mutation",
|
|
19589
19723
|
auth: "admin"
|
|
19724
|
+
}), method(object({}), EventStoreFootprintSchema, {
|
|
19725
|
+
kind: "query",
|
|
19726
|
+
auth: "admin"
|
|
19727
|
+
}), method(object({
|
|
19728
|
+
olderThanMs: number(),
|
|
19729
|
+
reason: OpsLogReasonSchema.optional()
|
|
19730
|
+
}), EventPruneCountsSchema, {
|
|
19731
|
+
kind: "mutation",
|
|
19732
|
+
auth: "admin"
|
|
19733
|
+
}), method(object({ deviceId: number() }), EventPruneCountsSchema, {
|
|
19734
|
+
kind: "mutation",
|
|
19735
|
+
auth: "admin"
|
|
19736
|
+
}), method(OpsLogQueryInputSchema, array(OpsLogEntrySchema).readonly(), {
|
|
19737
|
+
kind: "query",
|
|
19738
|
+
auth: "admin"
|
|
19590
19739
|
}), method(object({
|
|
19591
19740
|
eventId: string(),
|
|
19592
19741
|
kind: MediaFileKindEnum.optional()
|
|
@@ -22909,13 +23058,131 @@ method(object({
|
|
|
22909
23058
|
}), method(object({ deviceId: number() }), RecordingStatusSchema, {
|
|
22910
23059
|
kind: "mutation",
|
|
22911
23060
|
auth: "admin"
|
|
22912
|
-
}), method(object({
|
|
23061
|
+
}), method(object({
|
|
23062
|
+
deviceId: number(),
|
|
23063
|
+
reason: OpsLogReasonSchema.optional()
|
|
23064
|
+
}), object({
|
|
22913
23065
|
floorMs: number().nullable(),
|
|
22914
23066
|
deletedBuckets: number().int(),
|
|
22915
23067
|
reclaimedBytes: number().int()
|
|
22916
23068
|
}), {
|
|
22917
23069
|
kind: "mutation",
|
|
22918
23070
|
auth: "admin"
|
|
23071
|
+
}), method(object({
|
|
23072
|
+
deviceId: number(),
|
|
23073
|
+
fromMs: number().optional(),
|
|
23074
|
+
toMs: number().optional()
|
|
23075
|
+
}), object({
|
|
23076
|
+
deletedBuckets: number().int(),
|
|
23077
|
+
reclaimedBytes: number().int()
|
|
23078
|
+
}), {
|
|
23079
|
+
kind: "mutation",
|
|
23080
|
+
auth: "admin"
|
|
23081
|
+
}), method(OpsLogQueryInputSchema, array(OpsLogEntrySchema).readonly(), {
|
|
23082
|
+
kind: "query",
|
|
23083
|
+
auth: "admin"
|
|
23084
|
+
});
|
|
23085
|
+
/**
|
|
23086
|
+
* `recordingExport` cap — render a footage time range into a single downloadable
|
|
23087
|
+
* MP4 (regular / accelerated / decelerated / timelapse, ± audio), kept for a
|
|
23088
|
+
* bounded lifetime with a durable history, auto-expiry, and optional
|
|
23089
|
+
* delete-after-download.
|
|
23090
|
+
*
|
|
23091
|
+
* Like `recording` this is a `scope:'system', mode:'singleton'` cap: the
|
|
23092
|
+
* recorder self-gates so exactly ONE node (the designated `recordingNodeId`,
|
|
23093
|
+
* default `hub`) registers it. Device-scoped methods carry `deviceId` in their
|
|
23094
|
+
* input and dispatch to that single provider; the render runs on the node that
|
|
23095
|
+
* owns the footage (no cross-node segment transfer). Download rides the
|
|
23096
|
+
* framework addon data-plane. State persists in a DurableState blob (NOT
|
|
23097
|
+
* SQLite); history rows survive file deletion for audit.
|
|
23098
|
+
*/
|
|
23099
|
+
/** Playback-speed multiplier for the render (1 = realtime). */
|
|
23100
|
+
var ExportSpeedSchema = number().min(.25).max(32);
|
|
23101
|
+
/** Timelapse cadence — sample one source frame per `everyMs`, output at `outputFps`. */
|
|
23102
|
+
var ExportTimelapseSchema = object({
|
|
23103
|
+
everyMs: number().int().positive(),
|
|
23104
|
+
outputFps: number().int().min(1).max(60).optional()
|
|
23105
|
+
});
|
|
23106
|
+
/**
|
|
23107
|
+
* Render options. `speed` and `timelapse` are mutually exclusive. `includeAudio`
|
|
23108
|
+
* is honoured only for a realtime-ish speed (0.5–2×); timelapse is always
|
|
23109
|
+
* silent. `maxLifeMs` bounds how long the finished file is kept;
|
|
23110
|
+
* `deleteAfterDownload` removes it shortly after the first complete download.
|
|
23111
|
+
*/
|
|
23112
|
+
var ExportOptionsSchema = object({
|
|
23113
|
+
speed: ExportSpeedSchema.optional(),
|
|
23114
|
+
timelapse: ExportTimelapseSchema.optional(),
|
|
23115
|
+
includeAudio: boolean(),
|
|
23116
|
+
maxLifeMs: number().int().positive(),
|
|
23117
|
+
deleteAfterDownload: boolean(),
|
|
23118
|
+
title: string().max(200).optional()
|
|
23119
|
+
}).superRefine((v, ctx) => {
|
|
23120
|
+
if (v.speed !== void 0 && v.timelapse !== void 0) ctx.addIssue({
|
|
23121
|
+
code: ZodIssueCode.custom,
|
|
23122
|
+
message: "speed and timelapse are mutually exclusive",
|
|
23123
|
+
path: ["timelapse"]
|
|
23124
|
+
});
|
|
23125
|
+
});
|
|
23126
|
+
var ExportStateSchema = _enum([
|
|
23127
|
+
"queued",
|
|
23128
|
+
"rendering",
|
|
23129
|
+
"ready",
|
|
23130
|
+
"failed",
|
|
23131
|
+
"expired",
|
|
23132
|
+
"deleted"
|
|
23133
|
+
]);
|
|
23134
|
+
/** One export job / history row. */
|
|
23135
|
+
var ExportRecordSchema = object({
|
|
23136
|
+
id: string(),
|
|
23137
|
+
deviceId: number(),
|
|
23138
|
+
profile: string(),
|
|
23139
|
+
fromMs: number(),
|
|
23140
|
+
toMs: number(),
|
|
23141
|
+
options: ExportOptionsSchema,
|
|
23142
|
+
state: ExportStateSchema,
|
|
23143
|
+
/** 0–100 while rendering; null otherwise. */
|
|
23144
|
+
progressPct: number().nullable(),
|
|
23145
|
+
/** File size once ready; null before. */
|
|
23146
|
+
fileBytes: number().nullable(),
|
|
23147
|
+
expiresAt: number(),
|
|
23148
|
+
deleteAfterDownload: boolean(),
|
|
23149
|
+
/** Epoch of the first complete download; null until then. */
|
|
23150
|
+
downloadedAt: number().nullable(),
|
|
23151
|
+
createdAt: number(),
|
|
23152
|
+
/** User id/name that requested the export. */
|
|
23153
|
+
createdBy: string(),
|
|
23154
|
+
/** Failure reason when state is 'failed'; null otherwise. */
|
|
23155
|
+
error: string().nullable()
|
|
23156
|
+
});
|
|
23157
|
+
/** Candidate download URLs (LAN first, then operator extra hosts). */
|
|
23158
|
+
var ExportDownloadSchema = object({
|
|
23159
|
+
url: string(),
|
|
23160
|
+
endpoints: array(string())
|
|
23161
|
+
});
|
|
23162
|
+
method(object({
|
|
23163
|
+
deviceId: number(),
|
|
23164
|
+
profile: string(),
|
|
23165
|
+
fromMs: number(),
|
|
23166
|
+
toMs: number(),
|
|
23167
|
+
options: ExportOptionsSchema
|
|
23168
|
+
}), ExportRecordSchema, {
|
|
23169
|
+
kind: "mutation",
|
|
23170
|
+
auth: "protected"
|
|
23171
|
+
}), method(object({ deviceId: number().optional() }), array(ExportRecordSchema), {
|
|
23172
|
+
kind: "query",
|
|
23173
|
+
auth: "protected"
|
|
23174
|
+
}), method(object({ exportId: string() }), ExportRecordSchema, {
|
|
23175
|
+
kind: "query",
|
|
23176
|
+
auth: "protected"
|
|
23177
|
+
}), method(object({ exportId: string() }), ExportRecordSchema, {
|
|
23178
|
+
kind: "mutation",
|
|
23179
|
+
auth: "protected"
|
|
23180
|
+
}), method(object({ exportId: string() }), ExportRecordSchema, {
|
|
23181
|
+
kind: "mutation",
|
|
23182
|
+
auth: "protected"
|
|
23183
|
+
}), method(object({ exportId: string() }), ExportDownloadSchema, {
|
|
23184
|
+
kind: "query",
|
|
23185
|
+
auth: "protected"
|
|
22919
23186
|
});
|
|
22920
23187
|
/**
|
|
22921
23188
|
* One publishable camera stream as its OWNING PROVIDER describes it — the same
|
|
@@ -25935,6 +26202,12 @@ Object.freeze({
|
|
|
25935
26202
|
addonId: null,
|
|
25936
26203
|
access: "delete"
|
|
25937
26204
|
},
|
|
26205
|
+
"pipelineAnalytics.deleteDeviceEvents": {
|
|
26206
|
+
capName: "pipeline-analytics",
|
|
26207
|
+
capScope: "device",
|
|
26208
|
+
addonId: null,
|
|
26209
|
+
access: "delete"
|
|
26210
|
+
},
|
|
25938
26211
|
"pipelineAnalytics.deleteTracks": {
|
|
25939
26212
|
capName: "pipeline-analytics",
|
|
25940
26213
|
capScope: "device",
|
|
@@ -25965,6 +26238,12 @@ Object.freeze({
|
|
|
25965
26238
|
addonId: null,
|
|
25966
26239
|
access: "view"
|
|
25967
26240
|
},
|
|
26241
|
+
"pipelineAnalytics.getEventStoreFootprint": {
|
|
26242
|
+
capName: "pipeline-analytics",
|
|
26243
|
+
capScope: "device",
|
|
26244
|
+
addonId: null,
|
|
26245
|
+
access: "view"
|
|
26246
|
+
},
|
|
25968
26247
|
"pipelineAnalytics.getKeyEvents": {
|
|
25969
26248
|
capName: "pipeline-analytics",
|
|
25970
26249
|
capScope: "device",
|
|
@@ -26007,6 +26286,12 @@ Object.freeze({
|
|
|
26007
26286
|
addonId: null,
|
|
26008
26287
|
access: "view"
|
|
26009
26288
|
},
|
|
26289
|
+
"pipelineAnalytics.listOpsLog": {
|
|
26290
|
+
capName: "pipeline-analytics",
|
|
26291
|
+
capScope: "device",
|
|
26292
|
+
addonId: null,
|
|
26293
|
+
access: "view"
|
|
26294
|
+
},
|
|
26010
26295
|
"pipelineAnalytics.listRecentTracks": {
|
|
26011
26296
|
capName: "pipeline-analytics",
|
|
26012
26297
|
capScope: "device",
|
|
@@ -26019,6 +26304,12 @@ Object.freeze({
|
|
|
26019
26304
|
addonId: null,
|
|
26020
26305
|
access: "view"
|
|
26021
26306
|
},
|
|
26307
|
+
"pipelineAnalytics.pruneEvents": {
|
|
26308
|
+
capName: "pipeline-analytics",
|
|
26309
|
+
capScope: "device",
|
|
26310
|
+
addonId: null,
|
|
26311
|
+
access: "create"
|
|
26312
|
+
},
|
|
26022
26313
|
"pipelineAnalytics.pruneEventsBefore": {
|
|
26023
26314
|
capName: "pipeline-analytics",
|
|
26024
26315
|
capScope: "device",
|
|
@@ -26781,6 +27072,12 @@ Object.freeze({
|
|
|
26781
27072
|
addonId: null,
|
|
26782
27073
|
access: "create"
|
|
26783
27074
|
},
|
|
27075
|
+
"recording.deleteFootprint": {
|
|
27076
|
+
capName: "recording",
|
|
27077
|
+
capScope: "system",
|
|
27078
|
+
addonId: null,
|
|
27079
|
+
access: "delete"
|
|
27080
|
+
},
|
|
26784
27081
|
"recording.getAvailability": {
|
|
26785
27082
|
capName: "recording",
|
|
26786
27083
|
capScope: "system",
|
|
@@ -26811,6 +27108,12 @@ Object.freeze({
|
|
|
26811
27108
|
addonId: null,
|
|
26812
27109
|
access: "view"
|
|
26813
27110
|
},
|
|
27111
|
+
"recording.listOpsLog": {
|
|
27112
|
+
capName: "recording",
|
|
27113
|
+
capScope: "system",
|
|
27114
|
+
addonId: null,
|
|
27115
|
+
access: "view"
|
|
27116
|
+
},
|
|
26814
27117
|
"recording.locateSegment": {
|
|
26815
27118
|
capName: "recording",
|
|
26816
27119
|
capScope: "system",
|
|
@@ -26841,6 +27144,42 @@ Object.freeze({
|
|
|
26841
27144
|
addonId: null,
|
|
26842
27145
|
access: "create"
|
|
26843
27146
|
},
|
|
27147
|
+
"recordingExport.cancelExport": {
|
|
27148
|
+
capName: "recordingExport",
|
|
27149
|
+
capScope: "system",
|
|
27150
|
+
addonId: null,
|
|
27151
|
+
access: "create"
|
|
27152
|
+
},
|
|
27153
|
+
"recordingExport.createExport": {
|
|
27154
|
+
capName: "recordingExport",
|
|
27155
|
+
capScope: "system",
|
|
27156
|
+
addonId: null,
|
|
27157
|
+
access: "create"
|
|
27158
|
+
},
|
|
27159
|
+
"recordingExport.deleteExport": {
|
|
27160
|
+
capName: "recordingExport",
|
|
27161
|
+
capScope: "system",
|
|
27162
|
+
addonId: null,
|
|
27163
|
+
access: "delete"
|
|
27164
|
+
},
|
|
27165
|
+
"recordingExport.getDownloadUrl": {
|
|
27166
|
+
capName: "recordingExport",
|
|
27167
|
+
capScope: "system",
|
|
27168
|
+
addonId: null,
|
|
27169
|
+
access: "view"
|
|
27170
|
+
},
|
|
27171
|
+
"recordingExport.getExport": {
|
|
27172
|
+
capName: "recordingExport",
|
|
27173
|
+
capScope: "system",
|
|
27174
|
+
addonId: null,
|
|
27175
|
+
access: "view"
|
|
27176
|
+
},
|
|
27177
|
+
"recordingExport.listExports": {
|
|
27178
|
+
capName: "recordingExport",
|
|
27179
|
+
capScope: "system",
|
|
27180
|
+
addonId: null,
|
|
27181
|
+
access: "view"
|
|
27182
|
+
},
|
|
26844
27183
|
"sceneMonitor.captureReference": {
|
|
26845
27184
|
capName: "scene-monitor",
|
|
26846
27185
|
capScope: "device",
|