@camstack/addon-export-hap 1.2.30 → 1.2.32
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 -28
- package/dist/hap-export.addon.mjs +186 -28
- 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
|
|
@@ -19924,7 +19996,14 @@ targets: array(object({
|
|
|
19924
19996
|
"sleeping",
|
|
19925
19997
|
"unreachable",
|
|
19926
19998
|
"waking"
|
|
19927
|
-
]).nullable()
|
|
19999
|
+
]).nullable(),
|
|
20000
|
+
/** A battery camera (whatever its current state). An AWAKE battery
|
|
20001
|
+
* camera is deliberately NOT recaptured on the poll cadence — every
|
|
20002
|
+
* capture is a camera hit that would keep it out of sleep — so its
|
|
20003
|
+
* cached frame legitimately ages past the currency ceiling while
|
|
20004
|
+
* nothing is streaming. A surface must keep painting it (a fresh
|
|
20005
|
+
* frame is captured at each wake), not blank to "unavailable". */
|
|
20006
|
+
battery: boolean()
|
|
19928
20007
|
})));
|
|
19929
20008
|
/**
|
|
19930
20009
|
* `sso-bridge` — internal hub-only cap that lets SSO-style auth
|
|
@@ -20585,20 +20664,6 @@ var VectorStatsResultSchema = object({
|
|
|
20585
20664
|
exact: boolean()
|
|
20586
20665
|
});
|
|
20587
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);
|
|
20588
|
-
/**
|
|
20589
|
-
* `videoclips` — the unified, navigable-clip surface for a camera.
|
|
20590
|
-
*
|
|
20591
|
-
* A device-scoped WRAPPER cap (like `pipeline-analytics`): exactly one active
|
|
20592
|
-
* provider per device, substitutable. The DEFAULT provider (registered by
|
|
20593
|
-
* `addon-post-analysis`, `defaultActive: true`) composes the analytics event
|
|
20594
|
-
* log (markers + thumbnails) with the recorder's `getPlaybackManifest` — a clip
|
|
20595
|
-
* is a time-WINDOW over existing footage, never a separate file. A camera that
|
|
20596
|
-
* exposes NATIVE onboard clips (Reolink/Hikvision NVR) can later substitute the
|
|
20597
|
-
* wrapper provider for its device and serve its own clip catalog + URLs.
|
|
20598
|
-
*
|
|
20599
|
-
* A `Clip` is purely time-based (subtree-blind): playback resolves segments by
|
|
20600
|
-
* temporal overlap, so the API never decides `continuous` vs `events`.
|
|
20601
|
-
*/
|
|
20602
20667
|
var ClipSchema = object({
|
|
20603
20668
|
/** Opaque, provider-namespaced id. The default provider encodes the time
|
|
20604
20669
|
* window so `getClipPlayback` is self-contained (no event re-query). */
|
|
@@ -20615,8 +20680,57 @@ var ClipSchema = object({
|
|
|
20615
20680
|
startMs: number(),
|
|
20616
20681
|
endMs: number()
|
|
20617
20682
|
}),
|
|
20618
|
-
/**
|
|
20619
|
-
thumbnail
|
|
20683
|
+
/**
|
|
20684
|
+
* Lazy thumbnail URL, never inlined.
|
|
20685
|
+
*
|
|
20686
|
+
* Recording-derived clips (events-mode keep-window, and the prepared
|
|
20687
|
+
* continuous event+fragment visit) MUST use the snapshot of the **main
|
|
20688
|
+
* event of the interval** — `getEventMedia({ eventId, kind: 'snapshot' })`
|
|
20689
|
+
* of the event that owns `kind` (object > motion > audio). Do not extract
|
|
20690
|
+
* a keyframe from the recorded segments. Other providers (onboard, HKSV)
|
|
20691
|
+
* mint their own stills.
|
|
20692
|
+
*
|
|
20693
|
+
* **VOUCHED, never fabricated.** A provider emits this only for an event it
|
|
20694
|
+
* has CONFIRMED owns at least one media row (its own, or its owning track's).
|
|
20695
|
+
* Absent is meaningful — "this visit has no event still" — never "we did not
|
|
20696
|
+
* look". Stamping it from a URL template made 35% of one camera's clips point
|
|
20697
|
+
* at a 404 (device 3836, 2026-08-17: 64 of 179 clips dead, 63 of them motion).
|
|
20698
|
+
* A read that FAILS drops the claim; it never invents it.
|
|
20699
|
+
*/
|
|
20700
|
+
thumbnail: string().optional(),
|
|
20701
|
+
/**
|
|
20702
|
+
* An instant INSIDE this visit's footage, hole-safe, where a recorded still
|
|
20703
|
+
* can be decoded. Present whenever the visit came from recorded availability;
|
|
20704
|
+
* absent on a per-event padded window (there is no footage to promise).
|
|
20705
|
+
*
|
|
20706
|
+
* This is not a thumbnail and not a second byte path: it is the argument to
|
|
20707
|
+
* the recorder's existing still route. The surface — never the provider —
|
|
20708
|
+
* decides whether to use it. It is the midpoint of the visit's LONGEST
|
|
20709
|
+
* contiguous range, not of the visit: a visit spans its holes by
|
|
20710
|
+
* construction, so a naive midpoint lands in dead air.
|
|
20711
|
+
*/
|
|
20712
|
+
stillAtMs: number().optional(),
|
|
20713
|
+
/**
|
|
20714
|
+
* Analytics event ids that overlap this visit — a BOUNDED sample, newest
|
|
20715
|
+
* first within kind (object → motion → audio), capped at
|
|
20716
|
+
* {@link MAX_CLIP_EVENT_IDS}. Empty on footage-only clips.
|
|
20717
|
+
*
|
|
20718
|
+
* Bounded because it is not a payload the surface pages through: one visit on
|
|
20719
|
+
* device 615 carried 2 345 ids, and `eventIds` was 99% of a 153 KB
|
|
20720
|
+
* camera-day. Read {@link eventCount} for the true total.
|
|
20721
|
+
*/
|
|
20722
|
+
eventIds: array(string()).optional(),
|
|
20723
|
+
/** How many analytics events actually overlap this visit. Differs from
|
|
20724
|
+
* `eventIds.length` exactly when the sample was capped — so a truncated
|
|
20725
|
+
* list is never mistaken for a quiet visit. */
|
|
20726
|
+
eventCount: number().int().nonnegative().optional(),
|
|
20727
|
+
/** Intra-visit footage holes (GOP rolls, discarded segments) still shorter
|
|
20728
|
+
* than `VISIT_MERGE_GAP_MS`. Playback concatenates around them; the timeline
|
|
20729
|
+
* bar keeps showing them via `recording.getAvailability`. */
|
|
20730
|
+
holes: array(object({
|
|
20731
|
+
startMs: number(),
|
|
20732
|
+
endMs: number()
|
|
20733
|
+
})).optional()
|
|
20620
20734
|
});
|
|
20621
20735
|
var ClipPlaybackSchema = object({
|
|
20622
20736
|
/** HLS master URL through the hub data-plane (Range + token in path). */
|
|
@@ -21080,7 +21194,14 @@ var SearchResultSchema = object({
|
|
|
21080
21194
|
});
|
|
21081
21195
|
var AutoUpdateSettingsSchema = object({
|
|
21082
21196
|
channel: ChannelSchema,
|
|
21083
|
-
intervalSeconds: number()
|
|
21197
|
+
intervalSeconds: number(),
|
|
21198
|
+
/**
|
|
21199
|
+
* Cadence of the "an update exists" POLLER, in seconds. Independent of
|
|
21200
|
+
* `channel`: the poller runs while auto-apply is `off`, because being told
|
|
21201
|
+
* about a publish and installing it are different decisions. Clamped
|
|
21202
|
+
* server-side to 900 s … 604800 s; defaults to 21600 s (6 h).
|
|
21203
|
+
*/
|
|
21204
|
+
updateCheckIntervalSeconds: number()
|
|
21084
21205
|
});
|
|
21085
21206
|
var AddonAutoUpdateSchema = ChannelWithInheritSchema;
|
|
21086
21207
|
var RestartAddonResultSchema = unknown();
|
|
@@ -21221,7 +21342,9 @@ method(_void(), array(AddonListItemSchema).readonly()), method(object({
|
|
|
21221
21342
|
auth: "admin"
|
|
21222
21343
|
}), method(_void(), AutoUpdateSettingsSchema, { auth: "admin" }), method(object({
|
|
21223
21344
|
channel: ChannelSchema,
|
|
21224
|
-
intervalSeconds: number().min(300).max(86400).optional()
|
|
21345
|
+
intervalSeconds: number().min(300).max(86400).optional(),
|
|
21346
|
+
/** Availability-poll cadence; see AutoUpdateSettingsSchema. */
|
|
21347
|
+
updateCheckIntervalSeconds: number().min(900).max(604800).optional()
|
|
21225
21348
|
}), unknown(), {
|
|
21226
21349
|
kind: "mutation",
|
|
21227
21350
|
auth: "admin"
|
|
@@ -25262,7 +25385,9 @@ var ExportOptionsSchema = object({
|
|
|
25262
25385
|
includeAudio: boolean(),
|
|
25263
25386
|
maxLifeMs: number().int().positive(),
|
|
25264
25387
|
deleteAfterDownload: boolean(),
|
|
25265
|
-
title: string().max(200).optional()
|
|
25388
|
+
title: string().max(200).optional(),
|
|
25389
|
+
/** Notification-output target ids to ping when this export becomes ready. */
|
|
25390
|
+
notifyTargetIds: array(string().min(1)).max(20).optional()
|
|
25266
25391
|
}).superRefine((v, ctx) => {
|
|
25267
25392
|
if (v.speed !== void 0 && v.timelapse !== void 0) ctx.addIssue({
|
|
25268
25393
|
code: ZodIssueCode.custom,
|
|
@@ -25321,10 +25446,18 @@ var ExportBytesSchema = object({
|
|
|
25321
25446
|
});
|
|
25322
25447
|
method(object({
|
|
25323
25448
|
deviceId: number(),
|
|
25324
|
-
|
|
25449
|
+
/** @deprecated Prefer `profiles`. Kept so timelapse/notifiers keep working. */
|
|
25450
|
+
profile: string().optional(),
|
|
25451
|
+
profiles: array(string()).min(1).optional(),
|
|
25325
25452
|
fromMs: number(),
|
|
25326
25453
|
toMs: number(),
|
|
25327
25454
|
options: ExportOptionsSchema
|
|
25455
|
+
}).superRefine((v, ctx) => {
|
|
25456
|
+
if ((v.profiles !== void 0 && v.profiles.length > 0 ? v.profiles : v.profile !== void 0 ? [v.profile] : []).length < 1) ctx.addIssue({
|
|
25457
|
+
code: ZodIssueCode.custom,
|
|
25458
|
+
message: "pass profiles[] (min 1) or legacy profile",
|
|
25459
|
+
path: ["profiles"]
|
|
25460
|
+
});
|
|
25328
25461
|
}), ExportRecordSchema, {
|
|
25329
25462
|
kind: "mutation",
|
|
25330
25463
|
auth: "protected"
|
|
@@ -29949,6 +30082,12 @@ Object.freeze({
|
|
|
29949
30082
|
addonId: null,
|
|
29950
30083
|
access: "create"
|
|
29951
30084
|
},
|
|
30085
|
+
"pipelineAnalytics.reconcileFromDisk": {
|
|
30086
|
+
capName: "pipeline-analytics",
|
|
30087
|
+
capScope: "device",
|
|
30088
|
+
addonId: null,
|
|
30089
|
+
access: "create"
|
|
30090
|
+
},
|
|
29952
30091
|
"pipelineAnalytics.refreshStorageLocationsForMigration": {
|
|
29953
30092
|
capName: "pipeline-analytics",
|
|
29954
30093
|
capScope: "device",
|
|
@@ -30351,6 +30490,12 @@ Object.freeze({
|
|
|
30351
30490
|
addonId: null,
|
|
30352
30491
|
access: "view"
|
|
30353
30492
|
},
|
|
30493
|
+
"pipelineOrchestrator.getReconcileFromDiskStatus": {
|
|
30494
|
+
capName: "pipeline-orchestrator",
|
|
30495
|
+
capScope: "system",
|
|
30496
|
+
addonId: null,
|
|
30497
|
+
access: "view"
|
|
30498
|
+
},
|
|
30354
30499
|
"pipelineOrchestrator.listAgentSettings": {
|
|
30355
30500
|
capName: "pipeline-orchestrator",
|
|
30356
30501
|
capScope: "system",
|
|
@@ -30375,6 +30520,12 @@ Object.freeze({
|
|
|
30375
30520
|
addonId: null,
|
|
30376
30521
|
access: "create"
|
|
30377
30522
|
},
|
|
30523
|
+
"pipelineOrchestrator.reconcileFromDisk": {
|
|
30524
|
+
capName: "pipeline-orchestrator",
|
|
30525
|
+
capScope: "system",
|
|
30526
|
+
addonId: null,
|
|
30527
|
+
access: "create"
|
|
30528
|
+
},
|
|
30378
30529
|
"pipelineOrchestrator.removeAgentSettings": {
|
|
30379
30530
|
capName: "pipeline-orchestrator",
|
|
30380
30531
|
capScope: "system",
|
|
@@ -33366,6 +33517,11 @@ Object.freeze({
|
|
|
33366
33517
|
form: "single",
|
|
33367
33518
|
optional: true
|
|
33368
33519
|
}],
|
|
33520
|
+
"pipelineAnalytics.reconcileFromDisk": [{
|
|
33521
|
+
name: "deviceId",
|
|
33522
|
+
form: "single",
|
|
33523
|
+
optional: false
|
|
33524
|
+
}],
|
|
33369
33525
|
"pipelineAnalytics.restageRetrainTrack": [{
|
|
33370
33526
|
name: "deviceId",
|
|
33371
33527
|
form: "single",
|
|
@@ -34431,6 +34587,8 @@ DEFAULT_NATIVE_LEASE_SETTINGS.budgetMb;
|
|
|
34431
34587
|
DEFAULT_NATIVE_LEASE_SETTINGS.activityMs;
|
|
34432
34588
|
DEFAULT_NATIVE_LEASE_SETTINGS.tileBudgetMb;
|
|
34433
34589
|
DEFAULT_NATIVE_LEASE_SETTINGS.admission;
|
|
34590
|
+
var MB = 1024 * 1024;
|
|
34591
|
+
1024 * MB, 3072 * MB;
|
|
34434
34592
|
/**
|
|
34435
34593
|
* Compute the stable 64-char lowercase-hex fingerprint of a device's
|
|
34436
34594
|
* 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
|
|
@@ -19912,7 +19984,14 @@ targets: array(object({
|
|
|
19912
19984
|
"sleeping",
|
|
19913
19985
|
"unreachable",
|
|
19914
19986
|
"waking"
|
|
19915
|
-
]).nullable()
|
|
19987
|
+
]).nullable(),
|
|
19988
|
+
/** A battery camera (whatever its current state). An AWAKE battery
|
|
19989
|
+
* camera is deliberately NOT recaptured on the poll cadence — every
|
|
19990
|
+
* capture is a camera hit that would keep it out of sleep — so its
|
|
19991
|
+
* cached frame legitimately ages past the currency ceiling while
|
|
19992
|
+
* nothing is streaming. A surface must keep painting it (a fresh
|
|
19993
|
+
* frame is captured at each wake), not blank to "unavailable". */
|
|
19994
|
+
battery: boolean()
|
|
19916
19995
|
})));
|
|
19917
19996
|
/**
|
|
19918
19997
|
* `sso-bridge` — internal hub-only cap that lets SSO-style auth
|
|
@@ -20573,20 +20652,6 @@ var VectorStatsResultSchema = object({
|
|
|
20573
20652
|
exact: boolean()
|
|
20574
20653
|
});
|
|
20575
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);
|
|
20576
|
-
/**
|
|
20577
|
-
* `videoclips` — the unified, navigable-clip surface for a camera.
|
|
20578
|
-
*
|
|
20579
|
-
* A device-scoped WRAPPER cap (like `pipeline-analytics`): exactly one active
|
|
20580
|
-
* provider per device, substitutable. The DEFAULT provider (registered by
|
|
20581
|
-
* `addon-post-analysis`, `defaultActive: true`) composes the analytics event
|
|
20582
|
-
* log (markers + thumbnails) with the recorder's `getPlaybackManifest` — a clip
|
|
20583
|
-
* is a time-WINDOW over existing footage, never a separate file. A camera that
|
|
20584
|
-
* exposes NATIVE onboard clips (Reolink/Hikvision NVR) can later substitute the
|
|
20585
|
-
* wrapper provider for its device and serve its own clip catalog + URLs.
|
|
20586
|
-
*
|
|
20587
|
-
* A `Clip` is purely time-based (subtree-blind): playback resolves segments by
|
|
20588
|
-
* temporal overlap, so the API never decides `continuous` vs `events`.
|
|
20589
|
-
*/
|
|
20590
20655
|
var ClipSchema = object({
|
|
20591
20656
|
/** Opaque, provider-namespaced id. The default provider encodes the time
|
|
20592
20657
|
* window so `getClipPlayback` is self-contained (no event re-query). */
|
|
@@ -20603,8 +20668,57 @@ var ClipSchema = object({
|
|
|
20603
20668
|
startMs: number(),
|
|
20604
20669
|
endMs: number()
|
|
20605
20670
|
}),
|
|
20606
|
-
/**
|
|
20607
|
-
thumbnail
|
|
20671
|
+
/**
|
|
20672
|
+
* Lazy thumbnail URL, never inlined.
|
|
20673
|
+
*
|
|
20674
|
+
* Recording-derived clips (events-mode keep-window, and the prepared
|
|
20675
|
+
* continuous event+fragment visit) MUST use the snapshot of the **main
|
|
20676
|
+
* event of the interval** — `getEventMedia({ eventId, kind: 'snapshot' })`
|
|
20677
|
+
* of the event that owns `kind` (object > motion > audio). Do not extract
|
|
20678
|
+
* a keyframe from the recorded segments. Other providers (onboard, HKSV)
|
|
20679
|
+
* mint their own stills.
|
|
20680
|
+
*
|
|
20681
|
+
* **VOUCHED, never fabricated.** A provider emits this only for an event it
|
|
20682
|
+
* has CONFIRMED owns at least one media row (its own, or its owning track's).
|
|
20683
|
+
* Absent is meaningful — "this visit has no event still" — never "we did not
|
|
20684
|
+
* look". Stamping it from a URL template made 35% of one camera's clips point
|
|
20685
|
+
* at a 404 (device 3836, 2026-08-17: 64 of 179 clips dead, 63 of them motion).
|
|
20686
|
+
* A read that FAILS drops the claim; it never invents it.
|
|
20687
|
+
*/
|
|
20688
|
+
thumbnail: string().optional(),
|
|
20689
|
+
/**
|
|
20690
|
+
* An instant INSIDE this visit's footage, hole-safe, where a recorded still
|
|
20691
|
+
* can be decoded. Present whenever the visit came from recorded availability;
|
|
20692
|
+
* absent on a per-event padded window (there is no footage to promise).
|
|
20693
|
+
*
|
|
20694
|
+
* This is not a thumbnail and not a second byte path: it is the argument to
|
|
20695
|
+
* the recorder's existing still route. The surface — never the provider —
|
|
20696
|
+
* decides whether to use it. It is the midpoint of the visit's LONGEST
|
|
20697
|
+
* contiguous range, not of the visit: a visit spans its holes by
|
|
20698
|
+
* construction, so a naive midpoint lands in dead air.
|
|
20699
|
+
*/
|
|
20700
|
+
stillAtMs: number().optional(),
|
|
20701
|
+
/**
|
|
20702
|
+
* Analytics event ids that overlap this visit — a BOUNDED sample, newest
|
|
20703
|
+
* first within kind (object → motion → audio), capped at
|
|
20704
|
+
* {@link MAX_CLIP_EVENT_IDS}. Empty on footage-only clips.
|
|
20705
|
+
*
|
|
20706
|
+
* Bounded because it is not a payload the surface pages through: one visit on
|
|
20707
|
+
* device 615 carried 2 345 ids, and `eventIds` was 99% of a 153 KB
|
|
20708
|
+
* camera-day. Read {@link eventCount} for the true total.
|
|
20709
|
+
*/
|
|
20710
|
+
eventIds: array(string()).optional(),
|
|
20711
|
+
/** How many analytics events actually overlap this visit. Differs from
|
|
20712
|
+
* `eventIds.length` exactly when the sample was capped — so a truncated
|
|
20713
|
+
* list is never mistaken for a quiet visit. */
|
|
20714
|
+
eventCount: number().int().nonnegative().optional(),
|
|
20715
|
+
/** Intra-visit footage holes (GOP rolls, discarded segments) still shorter
|
|
20716
|
+
* than `VISIT_MERGE_GAP_MS`. Playback concatenates around them; the timeline
|
|
20717
|
+
* bar keeps showing them via `recording.getAvailability`. */
|
|
20718
|
+
holes: array(object({
|
|
20719
|
+
startMs: number(),
|
|
20720
|
+
endMs: number()
|
|
20721
|
+
})).optional()
|
|
20608
20722
|
});
|
|
20609
20723
|
var ClipPlaybackSchema = object({
|
|
20610
20724
|
/** HLS master URL through the hub data-plane (Range + token in path). */
|
|
@@ -21068,7 +21182,14 @@ var SearchResultSchema = object({
|
|
|
21068
21182
|
});
|
|
21069
21183
|
var AutoUpdateSettingsSchema = object({
|
|
21070
21184
|
channel: ChannelSchema,
|
|
21071
|
-
intervalSeconds: number()
|
|
21185
|
+
intervalSeconds: number(),
|
|
21186
|
+
/**
|
|
21187
|
+
* Cadence of the "an update exists" POLLER, in seconds. Independent of
|
|
21188
|
+
* `channel`: the poller runs while auto-apply is `off`, because being told
|
|
21189
|
+
* about a publish and installing it are different decisions. Clamped
|
|
21190
|
+
* server-side to 900 s … 604800 s; defaults to 21600 s (6 h).
|
|
21191
|
+
*/
|
|
21192
|
+
updateCheckIntervalSeconds: number()
|
|
21072
21193
|
});
|
|
21073
21194
|
var AddonAutoUpdateSchema = ChannelWithInheritSchema;
|
|
21074
21195
|
var RestartAddonResultSchema = unknown();
|
|
@@ -21209,7 +21330,9 @@ method(_void(), array(AddonListItemSchema).readonly()), method(object({
|
|
|
21209
21330
|
auth: "admin"
|
|
21210
21331
|
}), method(_void(), AutoUpdateSettingsSchema, { auth: "admin" }), method(object({
|
|
21211
21332
|
channel: ChannelSchema,
|
|
21212
|
-
intervalSeconds: number().min(300).max(86400).optional()
|
|
21333
|
+
intervalSeconds: number().min(300).max(86400).optional(),
|
|
21334
|
+
/** Availability-poll cadence; see AutoUpdateSettingsSchema. */
|
|
21335
|
+
updateCheckIntervalSeconds: number().min(900).max(604800).optional()
|
|
21213
21336
|
}), unknown(), {
|
|
21214
21337
|
kind: "mutation",
|
|
21215
21338
|
auth: "admin"
|
|
@@ -25250,7 +25373,9 @@ var ExportOptionsSchema = object({
|
|
|
25250
25373
|
includeAudio: boolean(),
|
|
25251
25374
|
maxLifeMs: number().int().positive(),
|
|
25252
25375
|
deleteAfterDownload: boolean(),
|
|
25253
|
-
title: string().max(200).optional()
|
|
25376
|
+
title: string().max(200).optional(),
|
|
25377
|
+
/** Notification-output target ids to ping when this export becomes ready. */
|
|
25378
|
+
notifyTargetIds: array(string().min(1)).max(20).optional()
|
|
25254
25379
|
}).superRefine((v, ctx) => {
|
|
25255
25380
|
if (v.speed !== void 0 && v.timelapse !== void 0) ctx.addIssue({
|
|
25256
25381
|
code: ZodIssueCode.custom,
|
|
@@ -25309,10 +25434,18 @@ var ExportBytesSchema = object({
|
|
|
25309
25434
|
});
|
|
25310
25435
|
method(object({
|
|
25311
25436
|
deviceId: number(),
|
|
25312
|
-
|
|
25437
|
+
/** @deprecated Prefer `profiles`. Kept so timelapse/notifiers keep working. */
|
|
25438
|
+
profile: string().optional(),
|
|
25439
|
+
profiles: array(string()).min(1).optional(),
|
|
25313
25440
|
fromMs: number(),
|
|
25314
25441
|
toMs: number(),
|
|
25315
25442
|
options: ExportOptionsSchema
|
|
25443
|
+
}).superRefine((v, ctx) => {
|
|
25444
|
+
if ((v.profiles !== void 0 && v.profiles.length > 0 ? v.profiles : v.profile !== void 0 ? [v.profile] : []).length < 1) ctx.addIssue({
|
|
25445
|
+
code: ZodIssueCode.custom,
|
|
25446
|
+
message: "pass profiles[] (min 1) or legacy profile",
|
|
25447
|
+
path: ["profiles"]
|
|
25448
|
+
});
|
|
25316
25449
|
}), ExportRecordSchema, {
|
|
25317
25450
|
kind: "mutation",
|
|
25318
25451
|
auth: "protected"
|
|
@@ -29937,6 +30070,12 @@ Object.freeze({
|
|
|
29937
30070
|
addonId: null,
|
|
29938
30071
|
access: "create"
|
|
29939
30072
|
},
|
|
30073
|
+
"pipelineAnalytics.reconcileFromDisk": {
|
|
30074
|
+
capName: "pipeline-analytics",
|
|
30075
|
+
capScope: "device",
|
|
30076
|
+
addonId: null,
|
|
30077
|
+
access: "create"
|
|
30078
|
+
},
|
|
29940
30079
|
"pipelineAnalytics.refreshStorageLocationsForMigration": {
|
|
29941
30080
|
capName: "pipeline-analytics",
|
|
29942
30081
|
capScope: "device",
|
|
@@ -30339,6 +30478,12 @@ Object.freeze({
|
|
|
30339
30478
|
addonId: null,
|
|
30340
30479
|
access: "view"
|
|
30341
30480
|
},
|
|
30481
|
+
"pipelineOrchestrator.getReconcileFromDiskStatus": {
|
|
30482
|
+
capName: "pipeline-orchestrator",
|
|
30483
|
+
capScope: "system",
|
|
30484
|
+
addonId: null,
|
|
30485
|
+
access: "view"
|
|
30486
|
+
},
|
|
30342
30487
|
"pipelineOrchestrator.listAgentSettings": {
|
|
30343
30488
|
capName: "pipeline-orchestrator",
|
|
30344
30489
|
capScope: "system",
|
|
@@ -30363,6 +30508,12 @@ Object.freeze({
|
|
|
30363
30508
|
addonId: null,
|
|
30364
30509
|
access: "create"
|
|
30365
30510
|
},
|
|
30511
|
+
"pipelineOrchestrator.reconcileFromDisk": {
|
|
30512
|
+
capName: "pipeline-orchestrator",
|
|
30513
|
+
capScope: "system",
|
|
30514
|
+
addonId: null,
|
|
30515
|
+
access: "create"
|
|
30516
|
+
},
|
|
30366
30517
|
"pipelineOrchestrator.removeAgentSettings": {
|
|
30367
30518
|
capName: "pipeline-orchestrator",
|
|
30368
30519
|
capScope: "system",
|
|
@@ -33354,6 +33505,11 @@ Object.freeze({
|
|
|
33354
33505
|
form: "single",
|
|
33355
33506
|
optional: true
|
|
33356
33507
|
}],
|
|
33508
|
+
"pipelineAnalytics.reconcileFromDisk": [{
|
|
33509
|
+
name: "deviceId",
|
|
33510
|
+
form: "single",
|
|
33511
|
+
optional: false
|
|
33512
|
+
}],
|
|
33357
33513
|
"pipelineAnalytics.restageRetrainTrack": [{
|
|
33358
33514
|
name: "deviceId",
|
|
33359
33515
|
form: "single",
|
|
@@ -34419,6 +34575,8 @@ DEFAULT_NATIVE_LEASE_SETTINGS.budgetMb;
|
|
|
34419
34575
|
DEFAULT_NATIVE_LEASE_SETTINGS.activityMs;
|
|
34420
34576
|
DEFAULT_NATIVE_LEASE_SETTINGS.tileBudgetMb;
|
|
34421
34577
|
DEFAULT_NATIVE_LEASE_SETTINGS.admission;
|
|
34578
|
+
var MB = 1024 * 1024;
|
|
34579
|
+
1024 * MB, 3072 * MB;
|
|
34422
34580
|
/**
|
|
34423
34581
|
* Compute the stable 64-char lowercase-hex fingerprint of a device's
|
|
34424
34582
|
* 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.32",
|
|
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",
|