@camstack/addon-export-hap 1.2.31 → 1.2.33
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/hap-export.addon.js +186 -27
- package/dist/hap-export.addon.mjs +186 -27
- package/package.json +1 -1
package/dist/hap-export.addon.js
CHANGED
|
@@ -84,7 +84,7 @@ function carryForward(base, existing, keys) {
|
|
|
84
84
|
return out;
|
|
85
85
|
}
|
|
86
86
|
//#endregion
|
|
87
|
-
//#region ../types/dist/event-category-
|
|
87
|
+
//#region ../types/dist/event-category-XfKNtfCc.mjs
|
|
88
88
|
var EventCategory = /* @__PURE__ */ function(EventCategory) {
|
|
89
89
|
EventCategory["SystemBoot"] = "system.boot";
|
|
90
90
|
EventCategory["SystemAddonsReady"] = "system.addons-ready";
|
|
@@ -101,9 +101,10 @@ var EventCategory = /* @__PURE__ */ function(EventCategory) {
|
|
|
101
101
|
EventCategory["SystemRestartCompleted"] = "system.restart-completed";
|
|
102
102
|
/**
|
|
103
103
|
* A newer addon or server-root package version was found by the
|
|
104
|
-
* authoritative registry check. Emitted once
|
|
105
|
-
* `(
|
|
106
|
-
*
|
|
104
|
+
* authoritative registry check. Emitted once when any observed
|
|
105
|
+
* `latestVersion` changes (or a package/node first appears behind);
|
|
106
|
+
* the payload carries the full currently-available list. Repeated
|
|
107
|
+
* polling of the same latests is silent.
|
|
107
108
|
*/
|
|
108
109
|
EventCategory["UpdateAvailable"] = "update.available";
|
|
109
110
|
/**
|
|
@@ -122,6 +123,22 @@ var EventCategory = /* @__PURE__ */ function(EventCategory) {
|
|
|
122
123
|
EventCategory["AddonInstalled"] = "addon.installed";
|
|
123
124
|
EventCategory["AddonUninstalled"] = "addon.uninstalled";
|
|
124
125
|
EventCategory["AddonCrashed"] = "addon.crashed";
|
|
126
|
+
/**
|
|
127
|
+
* A RUNNER the D6 crash circuit-breaker gave up on — terminal.
|
|
128
|
+
*
|
|
129
|
+
* `AddonCrashed` is the routine, self-healing fact ("it crashed; it is being
|
|
130
|
+
* respawned"); this is the one that never resolves itself. Emitted exactly
|
|
131
|
+
* once per trip, by `process-service.ts`, carrying the node, the runner, the
|
|
132
|
+
* addons it hosted and the crash count that tripped the breaker.
|
|
133
|
+
*
|
|
134
|
+
* It exists because a runner marked terminally `failed` used to be SILENT:
|
|
135
|
+
* on 2026-08-18 the `recorder` runner died of three unhandled ffmpeg spawn
|
|
136
|
+
* errors, the breaker stopped respawning it (correctly), `/health` kept
|
|
137
|
+
* returning 200, and fleet-wide recording was gone for 3h15 before the
|
|
138
|
+
* operator's phone told him. The Notification Center's system-event intake
|
|
139
|
+
* consumes this category and maps it to the `addon-crash-loop` kind.
|
|
140
|
+
*/
|
|
141
|
+
EventCategory["AddonRunnerFailed"] = "addon.runner-failed";
|
|
125
142
|
EventCategory["AddonError"] = "addon.error";
|
|
126
143
|
EventCategory["AddonPageReady"] = "addon.page-ready";
|
|
127
144
|
EventCategory["AddonWidgetReady"] = "addon.widget-ready";
|
|
@@ -8214,6 +8231,10 @@ var RecordingBandSchema = object({
|
|
|
8214
8231
|
preBufferSec: number().min(0).optional(),
|
|
8215
8232
|
postBufferSec: number().min(0).optional()
|
|
8216
8233
|
});
|
|
8234
|
+
({
|
|
8235
|
+
preBufferSec: 10,
|
|
8236
|
+
postBufferSec: 30
|
|
8237
|
+
}).postBufferSec * 1e3;
|
|
8217
8238
|
/**
|
|
8218
8239
|
* Per-device retention overrides. Every field is optional; an unset or `0`
|
|
8219
8240
|
* value inherits the node-wide recorder default. Only footage-lifetime limits
|
|
@@ -8261,6 +8282,12 @@ var RecordingConfigSchema = object({
|
|
|
8261
8282
|
/** DERIVED summary of `bands`, stamped by the recorder on every save.
|
|
8262
8283
|
* Authoring it has no effect — see {@link RecordingStorageModeSchema}. */
|
|
8263
8284
|
mode: RecordingStorageModeSchema.optional(),
|
|
8285
|
+
/**
|
|
8286
|
+
* Which assigned broker slots to record. Absent / empty = {@link
|
|
8287
|
+
* DEFAULT_RECORDING_PROFILES} (`high`+`low`) intersected with the
|
|
8288
|
+
* camera's currently assigned slots — never `mid` unless the operator
|
|
8289
|
+
* picks it, and never a slot the broker has not assigned.
|
|
8290
|
+
*/
|
|
8264
8291
|
profiles: array(CamProfileSchema).optional(),
|
|
8265
8292
|
segmentSeconds: number().int().positive().optional(),
|
|
8266
8293
|
/**
|
|
@@ -8341,7 +8368,11 @@ var RelocateFootageInputSchema = object({
|
|
|
8341
8368
|
profiles: array(string()).optional(),
|
|
8342
8369
|
/** Copy throttle in MB/s (default 40) — the drain is a background chore,
|
|
8343
8370
|
* never allowed to starve live writers. */
|
|
8344
|
-
throttleMbps: number().min(1).max(1e3).optional()
|
|
8371
|
+
throttleMbps: number().min(1).max(1e3).optional(),
|
|
8372
|
+
/** Move only segments whose startMs is >= this. Absent = the whole source
|
|
8373
|
+
* pile. Used when a full drain is too expensive and the operator only
|
|
8374
|
+
* wants the recent window on the new disk. */
|
|
8375
|
+
sinceMs: number().int().optional()
|
|
8345
8376
|
});
|
|
8346
8377
|
/** Internal, lease-scoped participant operation. It is intentionally separate
|
|
8347
8378
|
* from persistent recording settings: a migration never changes
|
|
@@ -15039,6 +15070,7 @@ var NcSystemEventKindSchema = _enum([
|
|
|
15039
15070
|
"node-offline",
|
|
15040
15071
|
"node-inference-unavailable",
|
|
15041
15072
|
"detection-blind",
|
|
15073
|
+
"addon-crash-loop",
|
|
15042
15074
|
"addon-update-available",
|
|
15043
15075
|
"server-update-available",
|
|
15044
15076
|
"alarm-triggered",
|
|
@@ -15046,6 +15078,9 @@ var NcSystemEventKindSchema = _enum([
|
|
|
15046
15078
|
"alarm-disarmed",
|
|
15047
15079
|
"alarm-arming",
|
|
15048
15080
|
"alarm-arm-refused",
|
|
15081
|
+
"addon-updated",
|
|
15082
|
+
"server-updated",
|
|
15083
|
+
"export-completed",
|
|
15049
15084
|
"camera-online",
|
|
15050
15085
|
"camera-offline",
|
|
15051
15086
|
"camera-disabled",
|
|
@@ -16939,13 +16974,19 @@ var RetrainStatusSchema = _enum([
|
|
|
16939
16974
|
* "never marked" from "already trained" must read `retrainStatus`.
|
|
16940
16975
|
*
|
|
16941
16976
|
* `debug` does NOT pin; it is attention, not durability.
|
|
16977
|
+
*
|
|
16978
|
+
* `favourited` IS a BOOLEAN pin (durability bit), not a retrain lifecycle.
|
|
16979
|
+
* A favourited track is skipped by retention the same way `staging` is, but
|
|
16980
|
+
* it does not enter `none|staging|trained` and has no staging budget.
|
|
16942
16981
|
*/
|
|
16943
16982
|
var TrackFlagFields = {
|
|
16944
16983
|
/** Operator marked this track as training material — i.e. `retrainStatus` is
|
|
16945
16984
|
* `'staging'`. */
|
|
16946
16985
|
markForTrain: boolean().optional(),
|
|
16947
16986
|
/** Operator marked this track for diagnostic attention. */
|
|
16948
|
-
debug: boolean().optional()
|
|
16987
|
+
debug: boolean().optional(),
|
|
16988
|
+
/** Operator favourited this track. Pins it against pruning. */
|
|
16989
|
+
favourited: boolean().optional()
|
|
16949
16990
|
};
|
|
16950
16991
|
/**
|
|
16951
16992
|
* The lifecycle field itself, on the READ surfaces only (`Track`, `KeyEvent`).
|
|
@@ -16970,6 +17011,7 @@ var TrackFlagsSchema = object({
|
|
|
16970
17011
|
trackId: string(),
|
|
16971
17012
|
markForTrain: boolean(),
|
|
16972
17013
|
debug: boolean(),
|
|
17014
|
+
favourited: boolean(),
|
|
16973
17015
|
/** The lifecycle state the boolean was derived from. Required here (unlike on
|
|
16974
17016
|
* a track row) because this shape is only ever produced by the write body,
|
|
16975
17017
|
* which always knows it — and a surface that has just written needs to render
|
|
@@ -17602,6 +17644,12 @@ var TrackCascadeCountsSchema = object({
|
|
|
17602
17644
|
/** Per-track CLIP search vectors removed (best-effort). */
|
|
17603
17645
|
embeddings: number().int()
|
|
17604
17646
|
});
|
|
17647
|
+
/** Disk-wins reconcile: media rows whose blobs are gone, then empty tracks. */
|
|
17648
|
+
var DiskReconcileCountsSchema = object({
|
|
17649
|
+
mediaDropped: number().int(),
|
|
17650
|
+
tracks: number().int(),
|
|
17651
|
+
events: number().int()
|
|
17652
|
+
});
|
|
17605
17653
|
/** Event-store footprint for one camera. */
|
|
17606
17654
|
var EventStoreDeviceFootprintSchema = object({
|
|
17607
17655
|
deviceId: number(),
|
|
@@ -17778,6 +17826,9 @@ DeviceType.Camera, method(object({ deviceId: number() }), array(TrackSchema).rea
|
|
|
17778
17826
|
}), method(object({ deviceId: number() }), TrackCascadeCountsSchema, {
|
|
17779
17827
|
kind: "mutation",
|
|
17780
17828
|
auth: "admin"
|
|
17829
|
+
}), method(object({ deviceId: number() }), DiskReconcileCountsSchema, {
|
|
17830
|
+
kind: "mutation",
|
|
17831
|
+
auth: "admin"
|
|
17781
17832
|
}), method(object({
|
|
17782
17833
|
deviceId: number(),
|
|
17783
17834
|
trackIds: array(string()).min(1)
|
|
@@ -19288,6 +19339,24 @@ var CameraStatusDegradationSchema = object({
|
|
|
19288
19339
|
*
|
|
19289
19340
|
* See spec: `docs/superpowers/specs/2026-06-24-camera-status-aggregator-cap.md`
|
|
19290
19341
|
*/
|
|
19342
|
+
var DiskReconcileJobSchema = object({
|
|
19343
|
+
state: _enum([
|
|
19344
|
+
"idle",
|
|
19345
|
+
"running",
|
|
19346
|
+
"done",
|
|
19347
|
+
"error"
|
|
19348
|
+
]),
|
|
19349
|
+
total: number().int().nonnegative(),
|
|
19350
|
+
completed: number().int().nonnegative(),
|
|
19351
|
+
currentDeviceId: number().int().nullable(),
|
|
19352
|
+
failed: array(number().int()).readonly(),
|
|
19353
|
+
mediaDropped: number().int().nonnegative(),
|
|
19354
|
+
tracks: number().int().nonnegative(),
|
|
19355
|
+
events: number().int().nonnegative(),
|
|
19356
|
+
startedAtMs: number().int().nullable(),
|
|
19357
|
+
finishedAtMs: number().int().nullable(),
|
|
19358
|
+
error: string().nullable()
|
|
19359
|
+
});
|
|
19291
19360
|
var CameraStatusSchema = object({
|
|
19292
19361
|
deviceId: number(),
|
|
19293
19362
|
assignment: CameraAssignmentStatusSchema,
|
|
@@ -19519,7 +19588,10 @@ method(StorageMigrationLeaseInputSchema, object({ paused: literal(true) }), {
|
|
|
19519
19588
|
}), CameraSwitchGroupSchema, {
|
|
19520
19589
|
kind: "mutation",
|
|
19521
19590
|
auth: "admin"
|
|
19522
|
-
}), method(object({ deviceId: number() }), CameraStatusSchema), method(object({ deviceIds: array(number()).optional() }), array(CameraStatusSchema).readonly()), method(_void(),
|
|
19591
|
+
}), method(object({ deviceId: number() }), CameraStatusSchema), method(object({ deviceIds: array(number()).optional() }), array(CameraStatusSchema).readonly()), method(_void(), DiskReconcileJobSchema, {
|
|
19592
|
+
kind: "mutation",
|
|
19593
|
+
auth: "admin"
|
|
19594
|
+
}), method(_void(), DiskReconcileJobSchema, { auth: "admin" }), method(_void(), array(PipelineTemplateSchema).readonly()), method(object({
|
|
19523
19595
|
name: string(),
|
|
19524
19596
|
description: string().optional(),
|
|
19525
19597
|
config: CameraPipelineConfigSchema
|
|
@@ -20592,20 +20664,6 @@ var VectorStatsResultSchema = object({
|
|
|
20592
20664
|
exact: boolean()
|
|
20593
20665
|
});
|
|
20594
20666
|
method(VectorDeclareIndexInputSchema, _void(), { kind: "mutation" }), method(VectorUpsertInputSchema, VectorUpsertResultSchema, { kind: "mutation" }), method(VectorQueryInputSchema, VectorQueryResultSchema), method(VectorGetInputSchema, VectorGetResultSchema), method(VectorDeleteInputSchema, VectorDeleteResultSchema, { kind: "mutation" }), method(VectorDeleteByFilterInputSchema, VectorDeleteResultSchema, { kind: "mutation" }), method(VectorStatsInputSchema, VectorStatsResultSchema);
|
|
20595
|
-
/**
|
|
20596
|
-
* `videoclips` — the unified, navigable-clip surface for a camera.
|
|
20597
|
-
*
|
|
20598
|
-
* A device-scoped WRAPPER cap (like `pipeline-analytics`): exactly one active
|
|
20599
|
-
* provider per device, substitutable. The DEFAULT provider (registered by
|
|
20600
|
-
* `addon-post-analysis`, `defaultActive: true`) composes the analytics event
|
|
20601
|
-
* log (markers + thumbnails) with the recorder's `getPlaybackManifest` — a clip
|
|
20602
|
-
* is a time-WINDOW over existing footage, never a separate file. A camera that
|
|
20603
|
-
* exposes NATIVE onboard clips (Reolink/Hikvision NVR) can later substitute the
|
|
20604
|
-
* wrapper provider for its device and serve its own clip catalog + URLs.
|
|
20605
|
-
*
|
|
20606
|
-
* A `Clip` is purely time-based (subtree-blind): playback resolves segments by
|
|
20607
|
-
* temporal overlap, so the API never decides `continuous` vs `events`.
|
|
20608
|
-
*/
|
|
20609
20667
|
var ClipSchema = object({
|
|
20610
20668
|
/** Opaque, provider-namespaced id. The default provider encodes the time
|
|
20611
20669
|
* window so `getClipPlayback` is self-contained (no event re-query). */
|
|
@@ -20622,8 +20680,65 @@ var ClipSchema = object({
|
|
|
20622
20680
|
startMs: number(),
|
|
20623
20681
|
endMs: number()
|
|
20624
20682
|
}),
|
|
20625
|
-
/**
|
|
20626
|
-
|
|
20683
|
+
/**
|
|
20684
|
+
* Distinct object classes attached to this visit (`person`, `car`, …),
|
|
20685
|
+
* dominant first, capped at {@link MAX_CLIP_LABELS}. The ribbon renders these
|
|
20686
|
+
* instead of the bare kind — "Object" tells the operator nothing a colour bar
|
|
20687
|
+
* did not. Absent (never empty) when the visit attached no classified object
|
|
20688
|
+
* event, so a motion/audio-only visit keeps its kind label.
|
|
20689
|
+
*/
|
|
20690
|
+
labels: array(string()).max(3).optional(),
|
|
20691
|
+
/**
|
|
20692
|
+
* Lazy thumbnail URL, never inlined.
|
|
20693
|
+
*
|
|
20694
|
+
* Recording-derived clips (events-mode keep-window, and the prepared
|
|
20695
|
+
* continuous event+fragment visit) MUST use the snapshot of the **main
|
|
20696
|
+
* event of the interval** — `getEventMedia({ eventId, kind: 'snapshot' })`
|
|
20697
|
+
* of the event that owns `kind` (object > motion > audio). Do not extract
|
|
20698
|
+
* a keyframe from the recorded segments. Other providers (onboard, HKSV)
|
|
20699
|
+
* mint their own stills.
|
|
20700
|
+
*
|
|
20701
|
+
* **VOUCHED, never fabricated.** A provider emits this only for an event it
|
|
20702
|
+
* has CONFIRMED owns at least one media row (its own, or its owning track's).
|
|
20703
|
+
* Absent is meaningful — "this visit has no event still" — never "we did not
|
|
20704
|
+
* look". Stamping it from a URL template made 35% of one camera's clips point
|
|
20705
|
+
* at a 404 (device 3836, 2026-08-17: 64 of 179 clips dead, 63 of them motion).
|
|
20706
|
+
* A read that FAILS drops the claim; it never invents it.
|
|
20707
|
+
*/
|
|
20708
|
+
thumbnail: string().optional(),
|
|
20709
|
+
/**
|
|
20710
|
+
* An instant INSIDE this visit's footage, hole-safe, where a recorded still
|
|
20711
|
+
* can be decoded. Present whenever the visit came from recorded availability;
|
|
20712
|
+
* absent on a per-event padded window (there is no footage to promise).
|
|
20713
|
+
*
|
|
20714
|
+
* This is not a thumbnail and not a second byte path: it is the argument to
|
|
20715
|
+
* the recorder's existing still route. The surface — never the provider —
|
|
20716
|
+
* decides whether to use it. It is the midpoint of the visit's LONGEST
|
|
20717
|
+
* contiguous range, not of the visit: a visit spans its holes by
|
|
20718
|
+
* construction, so a naive midpoint lands in dead air.
|
|
20719
|
+
*/
|
|
20720
|
+
stillAtMs: number().optional(),
|
|
20721
|
+
/**
|
|
20722
|
+
* Analytics event ids that overlap this visit — a BOUNDED sample, newest
|
|
20723
|
+
* first within kind (object → motion → audio), capped at
|
|
20724
|
+
* {@link MAX_CLIP_EVENT_IDS}. Empty on footage-only clips.
|
|
20725
|
+
*
|
|
20726
|
+
* Bounded because it is not a payload the surface pages through: one visit on
|
|
20727
|
+
* device 615 carried 2 345 ids, and `eventIds` was 99% of a 153 KB
|
|
20728
|
+
* camera-day. Read {@link eventCount} for the true total.
|
|
20729
|
+
*/
|
|
20730
|
+
eventIds: array(string()).optional(),
|
|
20731
|
+
/** How many analytics events actually overlap this visit. Differs from
|
|
20732
|
+
* `eventIds.length` exactly when the sample was capped — so a truncated
|
|
20733
|
+
* list is never mistaken for a quiet visit. */
|
|
20734
|
+
eventCount: number().int().nonnegative().optional(),
|
|
20735
|
+
/** Intra-visit footage holes (GOP rolls, discarded segments) still shorter
|
|
20736
|
+
* than `VISIT_MERGE_GAP_MS`. Playback concatenates around them; the timeline
|
|
20737
|
+
* bar keeps showing them via `recording.getAvailability`. */
|
|
20738
|
+
holes: array(object({
|
|
20739
|
+
startMs: number(),
|
|
20740
|
+
endMs: number()
|
|
20741
|
+
})).optional()
|
|
20627
20742
|
});
|
|
20628
20743
|
var ClipPlaybackSchema = object({
|
|
20629
20744
|
/** HLS master URL through the hub data-plane (Range + token in path). */
|
|
@@ -21087,7 +21202,14 @@ var SearchResultSchema = object({
|
|
|
21087
21202
|
});
|
|
21088
21203
|
var AutoUpdateSettingsSchema = object({
|
|
21089
21204
|
channel: ChannelSchema,
|
|
21090
|
-
intervalSeconds: number()
|
|
21205
|
+
intervalSeconds: number(),
|
|
21206
|
+
/**
|
|
21207
|
+
* Cadence of the "an update exists" POLLER, in seconds. Independent of
|
|
21208
|
+
* `channel`: the poller runs while auto-apply is `off`, because being told
|
|
21209
|
+
* about a publish and installing it are different decisions. Clamped
|
|
21210
|
+
* server-side to 900 s … 604800 s; defaults to 21600 s (6 h).
|
|
21211
|
+
*/
|
|
21212
|
+
updateCheckIntervalSeconds: number()
|
|
21091
21213
|
});
|
|
21092
21214
|
var AddonAutoUpdateSchema = ChannelWithInheritSchema;
|
|
21093
21215
|
var RestartAddonResultSchema = unknown();
|
|
@@ -21228,7 +21350,9 @@ method(_void(), array(AddonListItemSchema).readonly()), method(object({
|
|
|
21228
21350
|
auth: "admin"
|
|
21229
21351
|
}), method(_void(), AutoUpdateSettingsSchema, { auth: "admin" }), method(object({
|
|
21230
21352
|
channel: ChannelSchema,
|
|
21231
|
-
intervalSeconds: number().min(300).max(86400).optional()
|
|
21353
|
+
intervalSeconds: number().min(300).max(86400).optional(),
|
|
21354
|
+
/** Availability-poll cadence; see AutoUpdateSettingsSchema. */
|
|
21355
|
+
updateCheckIntervalSeconds: number().min(900).max(604800).optional()
|
|
21232
21356
|
}), unknown(), {
|
|
21233
21357
|
kind: "mutation",
|
|
21234
21358
|
auth: "admin"
|
|
@@ -25269,7 +25393,9 @@ var ExportOptionsSchema = object({
|
|
|
25269
25393
|
includeAudio: boolean(),
|
|
25270
25394
|
maxLifeMs: number().int().positive(),
|
|
25271
25395
|
deleteAfterDownload: boolean(),
|
|
25272
|
-
title: string().max(200).optional()
|
|
25396
|
+
title: string().max(200).optional(),
|
|
25397
|
+
/** Notification-output target ids to ping when this export becomes ready. */
|
|
25398
|
+
notifyTargetIds: array(string().min(1)).max(20).optional()
|
|
25273
25399
|
}).superRefine((v, ctx) => {
|
|
25274
25400
|
if (v.speed !== void 0 && v.timelapse !== void 0) ctx.addIssue({
|
|
25275
25401
|
code: ZodIssueCode.custom,
|
|
@@ -25328,10 +25454,18 @@ var ExportBytesSchema = object({
|
|
|
25328
25454
|
});
|
|
25329
25455
|
method(object({
|
|
25330
25456
|
deviceId: number(),
|
|
25331
|
-
|
|
25457
|
+
/** @deprecated Prefer `profiles`. Kept so timelapse/notifiers keep working. */
|
|
25458
|
+
profile: string().optional(),
|
|
25459
|
+
profiles: array(string()).min(1).optional(),
|
|
25332
25460
|
fromMs: number(),
|
|
25333
25461
|
toMs: number(),
|
|
25334
25462
|
options: ExportOptionsSchema
|
|
25463
|
+
}).superRefine((v, ctx) => {
|
|
25464
|
+
if ((v.profiles !== void 0 && v.profiles.length > 0 ? v.profiles : v.profile !== void 0 ? [v.profile] : []).length < 1) ctx.addIssue({
|
|
25465
|
+
code: ZodIssueCode.custom,
|
|
25466
|
+
message: "pass profiles[] (min 1) or legacy profile",
|
|
25467
|
+
path: ["profiles"]
|
|
25468
|
+
});
|
|
25335
25469
|
}), ExportRecordSchema, {
|
|
25336
25470
|
kind: "mutation",
|
|
25337
25471
|
auth: "protected"
|
|
@@ -29956,6 +30090,12 @@ Object.freeze({
|
|
|
29956
30090
|
addonId: null,
|
|
29957
30091
|
access: "create"
|
|
29958
30092
|
},
|
|
30093
|
+
"pipelineAnalytics.reconcileFromDisk": {
|
|
30094
|
+
capName: "pipeline-analytics",
|
|
30095
|
+
capScope: "device",
|
|
30096
|
+
addonId: null,
|
|
30097
|
+
access: "create"
|
|
30098
|
+
},
|
|
29959
30099
|
"pipelineAnalytics.refreshStorageLocationsForMigration": {
|
|
29960
30100
|
capName: "pipeline-analytics",
|
|
29961
30101
|
capScope: "device",
|
|
@@ -30358,6 +30498,12 @@ Object.freeze({
|
|
|
30358
30498
|
addonId: null,
|
|
30359
30499
|
access: "view"
|
|
30360
30500
|
},
|
|
30501
|
+
"pipelineOrchestrator.getReconcileFromDiskStatus": {
|
|
30502
|
+
capName: "pipeline-orchestrator",
|
|
30503
|
+
capScope: "system",
|
|
30504
|
+
addonId: null,
|
|
30505
|
+
access: "view"
|
|
30506
|
+
},
|
|
30361
30507
|
"pipelineOrchestrator.listAgentSettings": {
|
|
30362
30508
|
capName: "pipeline-orchestrator",
|
|
30363
30509
|
capScope: "system",
|
|
@@ -30382,6 +30528,12 @@ Object.freeze({
|
|
|
30382
30528
|
addonId: null,
|
|
30383
30529
|
access: "create"
|
|
30384
30530
|
},
|
|
30531
|
+
"pipelineOrchestrator.reconcileFromDisk": {
|
|
30532
|
+
capName: "pipeline-orchestrator",
|
|
30533
|
+
capScope: "system",
|
|
30534
|
+
addonId: null,
|
|
30535
|
+
access: "create"
|
|
30536
|
+
},
|
|
30385
30537
|
"pipelineOrchestrator.removeAgentSettings": {
|
|
30386
30538
|
capName: "pipeline-orchestrator",
|
|
30387
30539
|
capScope: "system",
|
|
@@ -33373,6 +33525,11 @@ Object.freeze({
|
|
|
33373
33525
|
form: "single",
|
|
33374
33526
|
optional: true
|
|
33375
33527
|
}],
|
|
33528
|
+
"pipelineAnalytics.reconcileFromDisk": [{
|
|
33529
|
+
name: "deviceId",
|
|
33530
|
+
form: "single",
|
|
33531
|
+
optional: false
|
|
33532
|
+
}],
|
|
33376
33533
|
"pipelineAnalytics.restageRetrainTrack": [{
|
|
33377
33534
|
name: "deviceId",
|
|
33378
33535
|
form: "single",
|
|
@@ -34438,6 +34595,8 @@ DEFAULT_NATIVE_LEASE_SETTINGS.budgetMb;
|
|
|
34438
34595
|
DEFAULT_NATIVE_LEASE_SETTINGS.activityMs;
|
|
34439
34596
|
DEFAULT_NATIVE_LEASE_SETTINGS.tileBudgetMb;
|
|
34440
34597
|
DEFAULT_NATIVE_LEASE_SETTINGS.admission;
|
|
34598
|
+
var MB = 1024 * 1024;
|
|
34599
|
+
1024 * MB, 3072 * MB;
|
|
34441
34600
|
/**
|
|
34442
34601
|
* Compute the stable 64-char lowercase-hex fingerprint of a device's
|
|
34443
34602
|
* export-relevant shape. Two structurally-equal shapes (any feature order,
|
|
@@ -72,7 +72,7 @@ function carryForward(base, existing, keys) {
|
|
|
72
72
|
return out;
|
|
73
73
|
}
|
|
74
74
|
//#endregion
|
|
75
|
-
//#region ../types/dist/event-category-
|
|
75
|
+
//#region ../types/dist/event-category-XfKNtfCc.mjs
|
|
76
76
|
var EventCategory = /* @__PURE__ */ function(EventCategory) {
|
|
77
77
|
EventCategory["SystemBoot"] = "system.boot";
|
|
78
78
|
EventCategory["SystemAddonsReady"] = "system.addons-ready";
|
|
@@ -89,9 +89,10 @@ var EventCategory = /* @__PURE__ */ function(EventCategory) {
|
|
|
89
89
|
EventCategory["SystemRestartCompleted"] = "system.restart-completed";
|
|
90
90
|
/**
|
|
91
91
|
* A newer addon or server-root package version was found by the
|
|
92
|
-
* authoritative registry check. Emitted once
|
|
93
|
-
* `(
|
|
94
|
-
*
|
|
92
|
+
* authoritative registry check. Emitted once when any observed
|
|
93
|
+
* `latestVersion` changes (or a package/node first appears behind);
|
|
94
|
+
* the payload carries the full currently-available list. Repeated
|
|
95
|
+
* polling of the same latests is silent.
|
|
95
96
|
*/
|
|
96
97
|
EventCategory["UpdateAvailable"] = "update.available";
|
|
97
98
|
/**
|
|
@@ -110,6 +111,22 @@ var EventCategory = /* @__PURE__ */ function(EventCategory) {
|
|
|
110
111
|
EventCategory["AddonInstalled"] = "addon.installed";
|
|
111
112
|
EventCategory["AddonUninstalled"] = "addon.uninstalled";
|
|
112
113
|
EventCategory["AddonCrashed"] = "addon.crashed";
|
|
114
|
+
/**
|
|
115
|
+
* A RUNNER the D6 crash circuit-breaker gave up on — terminal.
|
|
116
|
+
*
|
|
117
|
+
* `AddonCrashed` is the routine, self-healing fact ("it crashed; it is being
|
|
118
|
+
* respawned"); this is the one that never resolves itself. Emitted exactly
|
|
119
|
+
* once per trip, by `process-service.ts`, carrying the node, the runner, the
|
|
120
|
+
* addons it hosted and the crash count that tripped the breaker.
|
|
121
|
+
*
|
|
122
|
+
* It exists because a runner marked terminally `failed` used to be SILENT:
|
|
123
|
+
* on 2026-08-18 the `recorder` runner died of three unhandled ffmpeg spawn
|
|
124
|
+
* errors, the breaker stopped respawning it (correctly), `/health` kept
|
|
125
|
+
* returning 200, and fleet-wide recording was gone for 3h15 before the
|
|
126
|
+
* operator's phone told him. The Notification Center's system-event intake
|
|
127
|
+
* consumes this category and maps it to the `addon-crash-loop` kind.
|
|
128
|
+
*/
|
|
129
|
+
EventCategory["AddonRunnerFailed"] = "addon.runner-failed";
|
|
113
130
|
EventCategory["AddonError"] = "addon.error";
|
|
114
131
|
EventCategory["AddonPageReady"] = "addon.page-ready";
|
|
115
132
|
EventCategory["AddonWidgetReady"] = "addon.widget-ready";
|
|
@@ -8202,6 +8219,10 @@ var RecordingBandSchema = object({
|
|
|
8202
8219
|
preBufferSec: number().min(0).optional(),
|
|
8203
8220
|
postBufferSec: number().min(0).optional()
|
|
8204
8221
|
});
|
|
8222
|
+
({
|
|
8223
|
+
preBufferSec: 10,
|
|
8224
|
+
postBufferSec: 30
|
|
8225
|
+
}).postBufferSec * 1e3;
|
|
8205
8226
|
/**
|
|
8206
8227
|
* Per-device retention overrides. Every field is optional; an unset or `0`
|
|
8207
8228
|
* value inherits the node-wide recorder default. Only footage-lifetime limits
|
|
@@ -8249,6 +8270,12 @@ var RecordingConfigSchema = object({
|
|
|
8249
8270
|
/** DERIVED summary of `bands`, stamped by the recorder on every save.
|
|
8250
8271
|
* Authoring it has no effect — see {@link RecordingStorageModeSchema}. */
|
|
8251
8272
|
mode: RecordingStorageModeSchema.optional(),
|
|
8273
|
+
/**
|
|
8274
|
+
* Which assigned broker slots to record. Absent / empty = {@link
|
|
8275
|
+
* DEFAULT_RECORDING_PROFILES} (`high`+`low`) intersected with the
|
|
8276
|
+
* camera's currently assigned slots — never `mid` unless the operator
|
|
8277
|
+
* picks it, and never a slot the broker has not assigned.
|
|
8278
|
+
*/
|
|
8252
8279
|
profiles: array(CamProfileSchema).optional(),
|
|
8253
8280
|
segmentSeconds: number().int().positive().optional(),
|
|
8254
8281
|
/**
|
|
@@ -8329,7 +8356,11 @@ var RelocateFootageInputSchema = object({
|
|
|
8329
8356
|
profiles: array(string()).optional(),
|
|
8330
8357
|
/** Copy throttle in MB/s (default 40) — the drain is a background chore,
|
|
8331
8358
|
* never allowed to starve live writers. */
|
|
8332
|
-
throttleMbps: number().min(1).max(1e3).optional()
|
|
8359
|
+
throttleMbps: number().min(1).max(1e3).optional(),
|
|
8360
|
+
/** Move only segments whose startMs is >= this. Absent = the whole source
|
|
8361
|
+
* pile. Used when a full drain is too expensive and the operator only
|
|
8362
|
+
* wants the recent window on the new disk. */
|
|
8363
|
+
sinceMs: number().int().optional()
|
|
8333
8364
|
});
|
|
8334
8365
|
/** Internal, lease-scoped participant operation. It is intentionally separate
|
|
8335
8366
|
* from persistent recording settings: a migration never changes
|
|
@@ -15027,6 +15058,7 @@ var NcSystemEventKindSchema = _enum([
|
|
|
15027
15058
|
"node-offline",
|
|
15028
15059
|
"node-inference-unavailable",
|
|
15029
15060
|
"detection-blind",
|
|
15061
|
+
"addon-crash-loop",
|
|
15030
15062
|
"addon-update-available",
|
|
15031
15063
|
"server-update-available",
|
|
15032
15064
|
"alarm-triggered",
|
|
@@ -15034,6 +15066,9 @@ var NcSystemEventKindSchema = _enum([
|
|
|
15034
15066
|
"alarm-disarmed",
|
|
15035
15067
|
"alarm-arming",
|
|
15036
15068
|
"alarm-arm-refused",
|
|
15069
|
+
"addon-updated",
|
|
15070
|
+
"server-updated",
|
|
15071
|
+
"export-completed",
|
|
15037
15072
|
"camera-online",
|
|
15038
15073
|
"camera-offline",
|
|
15039
15074
|
"camera-disabled",
|
|
@@ -16927,13 +16962,19 @@ var RetrainStatusSchema = _enum([
|
|
|
16927
16962
|
* "never marked" from "already trained" must read `retrainStatus`.
|
|
16928
16963
|
*
|
|
16929
16964
|
* `debug` does NOT pin; it is attention, not durability.
|
|
16965
|
+
*
|
|
16966
|
+
* `favourited` IS a BOOLEAN pin (durability bit), not a retrain lifecycle.
|
|
16967
|
+
* A favourited track is skipped by retention the same way `staging` is, but
|
|
16968
|
+
* it does not enter `none|staging|trained` and has no staging budget.
|
|
16930
16969
|
*/
|
|
16931
16970
|
var TrackFlagFields = {
|
|
16932
16971
|
/** Operator marked this track as training material — i.e. `retrainStatus` is
|
|
16933
16972
|
* `'staging'`. */
|
|
16934
16973
|
markForTrain: boolean().optional(),
|
|
16935
16974
|
/** Operator marked this track for diagnostic attention. */
|
|
16936
|
-
debug: boolean().optional()
|
|
16975
|
+
debug: boolean().optional(),
|
|
16976
|
+
/** Operator favourited this track. Pins it against pruning. */
|
|
16977
|
+
favourited: boolean().optional()
|
|
16937
16978
|
};
|
|
16938
16979
|
/**
|
|
16939
16980
|
* The lifecycle field itself, on the READ surfaces only (`Track`, `KeyEvent`).
|
|
@@ -16958,6 +16999,7 @@ var TrackFlagsSchema = object({
|
|
|
16958
16999
|
trackId: string(),
|
|
16959
17000
|
markForTrain: boolean(),
|
|
16960
17001
|
debug: boolean(),
|
|
17002
|
+
favourited: boolean(),
|
|
16961
17003
|
/** The lifecycle state the boolean was derived from. Required here (unlike on
|
|
16962
17004
|
* a track row) because this shape is only ever produced by the write body,
|
|
16963
17005
|
* which always knows it — and a surface that has just written needs to render
|
|
@@ -17590,6 +17632,12 @@ var TrackCascadeCountsSchema = object({
|
|
|
17590
17632
|
/** Per-track CLIP search vectors removed (best-effort). */
|
|
17591
17633
|
embeddings: number().int()
|
|
17592
17634
|
});
|
|
17635
|
+
/** Disk-wins reconcile: media rows whose blobs are gone, then empty tracks. */
|
|
17636
|
+
var DiskReconcileCountsSchema = object({
|
|
17637
|
+
mediaDropped: number().int(),
|
|
17638
|
+
tracks: number().int(),
|
|
17639
|
+
events: number().int()
|
|
17640
|
+
});
|
|
17593
17641
|
/** Event-store footprint for one camera. */
|
|
17594
17642
|
var EventStoreDeviceFootprintSchema = object({
|
|
17595
17643
|
deviceId: number(),
|
|
@@ -17766,6 +17814,9 @@ DeviceType.Camera, method(object({ deviceId: number() }), array(TrackSchema).rea
|
|
|
17766
17814
|
}), method(object({ deviceId: number() }), TrackCascadeCountsSchema, {
|
|
17767
17815
|
kind: "mutation",
|
|
17768
17816
|
auth: "admin"
|
|
17817
|
+
}), method(object({ deviceId: number() }), DiskReconcileCountsSchema, {
|
|
17818
|
+
kind: "mutation",
|
|
17819
|
+
auth: "admin"
|
|
17769
17820
|
}), method(object({
|
|
17770
17821
|
deviceId: number(),
|
|
17771
17822
|
trackIds: array(string()).min(1)
|
|
@@ -19276,6 +19327,24 @@ var CameraStatusDegradationSchema = object({
|
|
|
19276
19327
|
*
|
|
19277
19328
|
* See spec: `docs/superpowers/specs/2026-06-24-camera-status-aggregator-cap.md`
|
|
19278
19329
|
*/
|
|
19330
|
+
var DiskReconcileJobSchema = object({
|
|
19331
|
+
state: _enum([
|
|
19332
|
+
"idle",
|
|
19333
|
+
"running",
|
|
19334
|
+
"done",
|
|
19335
|
+
"error"
|
|
19336
|
+
]),
|
|
19337
|
+
total: number().int().nonnegative(),
|
|
19338
|
+
completed: number().int().nonnegative(),
|
|
19339
|
+
currentDeviceId: number().int().nullable(),
|
|
19340
|
+
failed: array(number().int()).readonly(),
|
|
19341
|
+
mediaDropped: number().int().nonnegative(),
|
|
19342
|
+
tracks: number().int().nonnegative(),
|
|
19343
|
+
events: number().int().nonnegative(),
|
|
19344
|
+
startedAtMs: number().int().nullable(),
|
|
19345
|
+
finishedAtMs: number().int().nullable(),
|
|
19346
|
+
error: string().nullable()
|
|
19347
|
+
});
|
|
19279
19348
|
var CameraStatusSchema = object({
|
|
19280
19349
|
deviceId: number(),
|
|
19281
19350
|
assignment: CameraAssignmentStatusSchema,
|
|
@@ -19507,7 +19576,10 @@ method(StorageMigrationLeaseInputSchema, object({ paused: literal(true) }), {
|
|
|
19507
19576
|
}), CameraSwitchGroupSchema, {
|
|
19508
19577
|
kind: "mutation",
|
|
19509
19578
|
auth: "admin"
|
|
19510
|
-
}), method(object({ deviceId: number() }), CameraStatusSchema), method(object({ deviceIds: array(number()).optional() }), array(CameraStatusSchema).readonly()), method(_void(),
|
|
19579
|
+
}), method(object({ deviceId: number() }), CameraStatusSchema), method(object({ deviceIds: array(number()).optional() }), array(CameraStatusSchema).readonly()), method(_void(), DiskReconcileJobSchema, {
|
|
19580
|
+
kind: "mutation",
|
|
19581
|
+
auth: "admin"
|
|
19582
|
+
}), method(_void(), DiskReconcileJobSchema, { auth: "admin" }), method(_void(), array(PipelineTemplateSchema).readonly()), method(object({
|
|
19511
19583
|
name: string(),
|
|
19512
19584
|
description: string().optional(),
|
|
19513
19585
|
config: CameraPipelineConfigSchema
|
|
@@ -20580,20 +20652,6 @@ var VectorStatsResultSchema = object({
|
|
|
20580
20652
|
exact: boolean()
|
|
20581
20653
|
});
|
|
20582
20654
|
method(VectorDeclareIndexInputSchema, _void(), { kind: "mutation" }), method(VectorUpsertInputSchema, VectorUpsertResultSchema, { kind: "mutation" }), method(VectorQueryInputSchema, VectorQueryResultSchema), method(VectorGetInputSchema, VectorGetResultSchema), method(VectorDeleteInputSchema, VectorDeleteResultSchema, { kind: "mutation" }), method(VectorDeleteByFilterInputSchema, VectorDeleteResultSchema, { kind: "mutation" }), method(VectorStatsInputSchema, VectorStatsResultSchema);
|
|
20583
|
-
/**
|
|
20584
|
-
* `videoclips` — the unified, navigable-clip surface for a camera.
|
|
20585
|
-
*
|
|
20586
|
-
* A device-scoped WRAPPER cap (like `pipeline-analytics`): exactly one active
|
|
20587
|
-
* provider per device, substitutable. The DEFAULT provider (registered by
|
|
20588
|
-
* `addon-post-analysis`, `defaultActive: true`) composes the analytics event
|
|
20589
|
-
* log (markers + thumbnails) with the recorder's `getPlaybackManifest` — a clip
|
|
20590
|
-
* is a time-WINDOW over existing footage, never a separate file. A camera that
|
|
20591
|
-
* exposes NATIVE onboard clips (Reolink/Hikvision NVR) can later substitute the
|
|
20592
|
-
* wrapper provider for its device and serve its own clip catalog + URLs.
|
|
20593
|
-
*
|
|
20594
|
-
* A `Clip` is purely time-based (subtree-blind): playback resolves segments by
|
|
20595
|
-
* temporal overlap, so the API never decides `continuous` vs `events`.
|
|
20596
|
-
*/
|
|
20597
20655
|
var ClipSchema = object({
|
|
20598
20656
|
/** Opaque, provider-namespaced id. The default provider encodes the time
|
|
20599
20657
|
* window so `getClipPlayback` is self-contained (no event re-query). */
|
|
@@ -20610,8 +20668,65 @@ var ClipSchema = object({
|
|
|
20610
20668
|
startMs: number(),
|
|
20611
20669
|
endMs: number()
|
|
20612
20670
|
}),
|
|
20613
|
-
/**
|
|
20614
|
-
|
|
20671
|
+
/**
|
|
20672
|
+
* Distinct object classes attached to this visit (`person`, `car`, …),
|
|
20673
|
+
* dominant first, capped at {@link MAX_CLIP_LABELS}. The ribbon renders these
|
|
20674
|
+
* instead of the bare kind — "Object" tells the operator nothing a colour bar
|
|
20675
|
+
* did not. Absent (never empty) when the visit attached no classified object
|
|
20676
|
+
* event, so a motion/audio-only visit keeps its kind label.
|
|
20677
|
+
*/
|
|
20678
|
+
labels: array(string()).max(3).optional(),
|
|
20679
|
+
/**
|
|
20680
|
+
* Lazy thumbnail URL, never inlined.
|
|
20681
|
+
*
|
|
20682
|
+
* Recording-derived clips (events-mode keep-window, and the prepared
|
|
20683
|
+
* continuous event+fragment visit) MUST use the snapshot of the **main
|
|
20684
|
+
* event of the interval** — `getEventMedia({ eventId, kind: 'snapshot' })`
|
|
20685
|
+
* of the event that owns `kind` (object > motion > audio). Do not extract
|
|
20686
|
+
* a keyframe from the recorded segments. Other providers (onboard, HKSV)
|
|
20687
|
+
* mint their own stills.
|
|
20688
|
+
*
|
|
20689
|
+
* **VOUCHED, never fabricated.** A provider emits this only for an event it
|
|
20690
|
+
* has CONFIRMED owns at least one media row (its own, or its owning track's).
|
|
20691
|
+
* Absent is meaningful — "this visit has no event still" — never "we did not
|
|
20692
|
+
* look". Stamping it from a URL template made 35% of one camera's clips point
|
|
20693
|
+
* at a 404 (device 3836, 2026-08-17: 64 of 179 clips dead, 63 of them motion).
|
|
20694
|
+
* A read that FAILS drops the claim; it never invents it.
|
|
20695
|
+
*/
|
|
20696
|
+
thumbnail: string().optional(),
|
|
20697
|
+
/**
|
|
20698
|
+
* An instant INSIDE this visit's footage, hole-safe, where a recorded still
|
|
20699
|
+
* can be decoded. Present whenever the visit came from recorded availability;
|
|
20700
|
+
* absent on a per-event padded window (there is no footage to promise).
|
|
20701
|
+
*
|
|
20702
|
+
* This is not a thumbnail and not a second byte path: it is the argument to
|
|
20703
|
+
* the recorder's existing still route. The surface — never the provider —
|
|
20704
|
+
* decides whether to use it. It is the midpoint of the visit's LONGEST
|
|
20705
|
+
* contiguous range, not of the visit: a visit spans its holes by
|
|
20706
|
+
* construction, so a naive midpoint lands in dead air.
|
|
20707
|
+
*/
|
|
20708
|
+
stillAtMs: number().optional(),
|
|
20709
|
+
/**
|
|
20710
|
+
* Analytics event ids that overlap this visit — a BOUNDED sample, newest
|
|
20711
|
+
* first within kind (object → motion → audio), capped at
|
|
20712
|
+
* {@link MAX_CLIP_EVENT_IDS}. Empty on footage-only clips.
|
|
20713
|
+
*
|
|
20714
|
+
* Bounded because it is not a payload the surface pages through: one visit on
|
|
20715
|
+
* device 615 carried 2 345 ids, and `eventIds` was 99% of a 153 KB
|
|
20716
|
+
* camera-day. Read {@link eventCount} for the true total.
|
|
20717
|
+
*/
|
|
20718
|
+
eventIds: array(string()).optional(),
|
|
20719
|
+
/** How many analytics events actually overlap this visit. Differs from
|
|
20720
|
+
* `eventIds.length` exactly when the sample was capped — so a truncated
|
|
20721
|
+
* list is never mistaken for a quiet visit. */
|
|
20722
|
+
eventCount: number().int().nonnegative().optional(),
|
|
20723
|
+
/** Intra-visit footage holes (GOP rolls, discarded segments) still shorter
|
|
20724
|
+
* than `VISIT_MERGE_GAP_MS`. Playback concatenates around them; the timeline
|
|
20725
|
+
* bar keeps showing them via `recording.getAvailability`. */
|
|
20726
|
+
holes: array(object({
|
|
20727
|
+
startMs: number(),
|
|
20728
|
+
endMs: number()
|
|
20729
|
+
})).optional()
|
|
20615
20730
|
});
|
|
20616
20731
|
var ClipPlaybackSchema = object({
|
|
20617
20732
|
/** HLS master URL through the hub data-plane (Range + token in path). */
|
|
@@ -21075,7 +21190,14 @@ var SearchResultSchema = object({
|
|
|
21075
21190
|
});
|
|
21076
21191
|
var AutoUpdateSettingsSchema = object({
|
|
21077
21192
|
channel: ChannelSchema,
|
|
21078
|
-
intervalSeconds: number()
|
|
21193
|
+
intervalSeconds: number(),
|
|
21194
|
+
/**
|
|
21195
|
+
* Cadence of the "an update exists" POLLER, in seconds. Independent of
|
|
21196
|
+
* `channel`: the poller runs while auto-apply is `off`, because being told
|
|
21197
|
+
* about a publish and installing it are different decisions. Clamped
|
|
21198
|
+
* server-side to 900 s … 604800 s; defaults to 21600 s (6 h).
|
|
21199
|
+
*/
|
|
21200
|
+
updateCheckIntervalSeconds: number()
|
|
21079
21201
|
});
|
|
21080
21202
|
var AddonAutoUpdateSchema = ChannelWithInheritSchema;
|
|
21081
21203
|
var RestartAddonResultSchema = unknown();
|
|
@@ -21216,7 +21338,9 @@ method(_void(), array(AddonListItemSchema).readonly()), method(object({
|
|
|
21216
21338
|
auth: "admin"
|
|
21217
21339
|
}), method(_void(), AutoUpdateSettingsSchema, { auth: "admin" }), method(object({
|
|
21218
21340
|
channel: ChannelSchema,
|
|
21219
|
-
intervalSeconds: number().min(300).max(86400).optional()
|
|
21341
|
+
intervalSeconds: number().min(300).max(86400).optional(),
|
|
21342
|
+
/** Availability-poll cadence; see AutoUpdateSettingsSchema. */
|
|
21343
|
+
updateCheckIntervalSeconds: number().min(900).max(604800).optional()
|
|
21220
21344
|
}), unknown(), {
|
|
21221
21345
|
kind: "mutation",
|
|
21222
21346
|
auth: "admin"
|
|
@@ -25257,7 +25381,9 @@ var ExportOptionsSchema = object({
|
|
|
25257
25381
|
includeAudio: boolean(),
|
|
25258
25382
|
maxLifeMs: number().int().positive(),
|
|
25259
25383
|
deleteAfterDownload: boolean(),
|
|
25260
|
-
title: string().max(200).optional()
|
|
25384
|
+
title: string().max(200).optional(),
|
|
25385
|
+
/** Notification-output target ids to ping when this export becomes ready. */
|
|
25386
|
+
notifyTargetIds: array(string().min(1)).max(20).optional()
|
|
25261
25387
|
}).superRefine((v, ctx) => {
|
|
25262
25388
|
if (v.speed !== void 0 && v.timelapse !== void 0) ctx.addIssue({
|
|
25263
25389
|
code: ZodIssueCode.custom,
|
|
@@ -25316,10 +25442,18 @@ var ExportBytesSchema = object({
|
|
|
25316
25442
|
});
|
|
25317
25443
|
method(object({
|
|
25318
25444
|
deviceId: number(),
|
|
25319
|
-
|
|
25445
|
+
/** @deprecated Prefer `profiles`. Kept so timelapse/notifiers keep working. */
|
|
25446
|
+
profile: string().optional(),
|
|
25447
|
+
profiles: array(string()).min(1).optional(),
|
|
25320
25448
|
fromMs: number(),
|
|
25321
25449
|
toMs: number(),
|
|
25322
25450
|
options: ExportOptionsSchema
|
|
25451
|
+
}).superRefine((v, ctx) => {
|
|
25452
|
+
if ((v.profiles !== void 0 && v.profiles.length > 0 ? v.profiles : v.profile !== void 0 ? [v.profile] : []).length < 1) ctx.addIssue({
|
|
25453
|
+
code: ZodIssueCode.custom,
|
|
25454
|
+
message: "pass profiles[] (min 1) or legacy profile",
|
|
25455
|
+
path: ["profiles"]
|
|
25456
|
+
});
|
|
25323
25457
|
}), ExportRecordSchema, {
|
|
25324
25458
|
kind: "mutation",
|
|
25325
25459
|
auth: "protected"
|
|
@@ -29944,6 +30078,12 @@ Object.freeze({
|
|
|
29944
30078
|
addonId: null,
|
|
29945
30079
|
access: "create"
|
|
29946
30080
|
},
|
|
30081
|
+
"pipelineAnalytics.reconcileFromDisk": {
|
|
30082
|
+
capName: "pipeline-analytics",
|
|
30083
|
+
capScope: "device",
|
|
30084
|
+
addonId: null,
|
|
30085
|
+
access: "create"
|
|
30086
|
+
},
|
|
29947
30087
|
"pipelineAnalytics.refreshStorageLocationsForMigration": {
|
|
29948
30088
|
capName: "pipeline-analytics",
|
|
29949
30089
|
capScope: "device",
|
|
@@ -30346,6 +30486,12 @@ Object.freeze({
|
|
|
30346
30486
|
addonId: null,
|
|
30347
30487
|
access: "view"
|
|
30348
30488
|
},
|
|
30489
|
+
"pipelineOrchestrator.getReconcileFromDiskStatus": {
|
|
30490
|
+
capName: "pipeline-orchestrator",
|
|
30491
|
+
capScope: "system",
|
|
30492
|
+
addonId: null,
|
|
30493
|
+
access: "view"
|
|
30494
|
+
},
|
|
30349
30495
|
"pipelineOrchestrator.listAgentSettings": {
|
|
30350
30496
|
capName: "pipeline-orchestrator",
|
|
30351
30497
|
capScope: "system",
|
|
@@ -30370,6 +30516,12 @@ Object.freeze({
|
|
|
30370
30516
|
addonId: null,
|
|
30371
30517
|
access: "create"
|
|
30372
30518
|
},
|
|
30519
|
+
"pipelineOrchestrator.reconcileFromDisk": {
|
|
30520
|
+
capName: "pipeline-orchestrator",
|
|
30521
|
+
capScope: "system",
|
|
30522
|
+
addonId: null,
|
|
30523
|
+
access: "create"
|
|
30524
|
+
},
|
|
30373
30525
|
"pipelineOrchestrator.removeAgentSettings": {
|
|
30374
30526
|
capName: "pipeline-orchestrator",
|
|
30375
30527
|
capScope: "system",
|
|
@@ -33361,6 +33513,11 @@ Object.freeze({
|
|
|
33361
33513
|
form: "single",
|
|
33362
33514
|
optional: true
|
|
33363
33515
|
}],
|
|
33516
|
+
"pipelineAnalytics.reconcileFromDisk": [{
|
|
33517
|
+
name: "deviceId",
|
|
33518
|
+
form: "single",
|
|
33519
|
+
optional: false
|
|
33520
|
+
}],
|
|
33364
33521
|
"pipelineAnalytics.restageRetrainTrack": [{
|
|
33365
33522
|
name: "deviceId",
|
|
33366
33523
|
form: "single",
|
|
@@ -34426,6 +34583,8 @@ DEFAULT_NATIVE_LEASE_SETTINGS.budgetMb;
|
|
|
34426
34583
|
DEFAULT_NATIVE_LEASE_SETTINGS.activityMs;
|
|
34427
34584
|
DEFAULT_NATIVE_LEASE_SETTINGS.tileBudgetMb;
|
|
34428
34585
|
DEFAULT_NATIVE_LEASE_SETTINGS.admission;
|
|
34586
|
+
var MB = 1024 * 1024;
|
|
34587
|
+
1024 * MB, 3072 * MB;
|
|
34429
34588
|
/**
|
|
34430
34589
|
* Compute the stable 64-char lowercase-hex fingerprint of a device's
|
|
34431
34590
|
* export-relevant shape. Two structurally-equal shapes (any feature order,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@camstack/addon-export-hap",
|
|
3
|
-
"version": "1.2.
|
|
3
|
+
"version": "1.2.33",
|
|
4
4
|
"description": "HomeKit (HAP) exporter for CamStack devices. Publishes each exposed device as its own HomeKit accessory: cameras and doorbells with SRTP streaming, HomeKit Secure Video, motion, two-way audio, PTZ and battery; switches, lights, locks and sensors through a capability→service table.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"camstack",
|