@camstack/addon-remote-storage 1.2.19 → 1.2.21
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/s3.addon.js +1 -1
- package/dist/s3.addon.mjs +1 -1
- package/dist/sftp.addon.js +1 -1
- package/dist/sftp.addon.mjs +1 -1
- package/dist/{shared-C7kobCEN.js → shared-CrotCkhF.js} +186 -27
- package/dist/{shared-CN_vleSm.mjs → shared-Toqenw3n.mjs} +186 -27
- package/dist/webdav.addon.js +1 -1
- package/dist/webdav.addon.mjs +1 -1
- package/package.json +1 -1
package/dist/s3.addon.js
CHANGED
|
@@ -2,7 +2,7 @@ Object.defineProperties(exports, {
|
|
|
2
2
|
__esModule: { value: true },
|
|
3
3
|
[Symbol.toStringTag]: { value: "Module" }
|
|
4
4
|
});
|
|
5
|
-
const require_shared = require("./shared-
|
|
5
|
+
const require_shared = require("./shared-CrotCkhF.js");
|
|
6
6
|
let node_stream = require("node:stream");
|
|
7
7
|
let _aws_sdk_client_s3 = require("@aws-sdk/client-s3");
|
|
8
8
|
let _aws_sdk_lib_storage = require("@aws-sdk/lib-storage");
|
package/dist/s3.addon.mjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { c as BaseAddon, i as rearmIdleAbort, n as getOptionalBasePath, o as scheduleIdleAbort, s as storageProviderCapability, t as createSessionId } from "./shared-
|
|
1
|
+
import { c as BaseAddon, i as rearmIdleAbort, n as getOptionalBasePath, o as scheduleIdleAbort, s as storageProviderCapability, t as createSessionId } from "./shared-Toqenw3n.mjs";
|
|
2
2
|
import { PassThrough } from "node:stream";
|
|
3
3
|
import { DeleteObjectCommand, GetObjectCommand, HeadBucketCommand, HeadObjectCommand, ListObjectsV2Command, PutObjectCommand, S3Client } from "@aws-sdk/client-s3";
|
|
4
4
|
import { Upload } from "@aws-sdk/lib-storage";
|
package/dist/sftp.addon.js
CHANGED
|
@@ -2,7 +2,7 @@ Object.defineProperties(exports, {
|
|
|
2
2
|
__esModule: { value: true },
|
|
3
3
|
[Symbol.toStringTag]: { value: "Module" }
|
|
4
4
|
});
|
|
5
|
-
const require_shared = require("./shared-
|
|
5
|
+
const require_shared = require("./shared-CrotCkhF.js");
|
|
6
6
|
let ssh2 = require("ssh2");
|
|
7
7
|
let node_path = require("node:path");
|
|
8
8
|
node_path = require_shared.__toESM(node_path);
|
package/dist/sftp.addon.mjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { a as safeJoinRemotePath, c as BaseAddon, i as rearmIdleAbort, o as scheduleIdleAbort, r as getRequiredBasePath, s as storageProviderCapability, t as createSessionId } from "./shared-
|
|
1
|
+
import { a as safeJoinRemotePath, c as BaseAddon, i as rearmIdleAbort, o as scheduleIdleAbort, r as getRequiredBasePath, s as storageProviderCapability, t as createSessionId } from "./shared-Toqenw3n.mjs";
|
|
2
2
|
import { Client } from "ssh2";
|
|
3
3
|
import * as path from "node:path";
|
|
4
4
|
//#region src/providers/sftp/sftp-config-schema.ts
|
|
@@ -23,7 +23,7 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
|
|
|
23
23
|
let node_crypto = require("node:crypto");
|
|
24
24
|
let node_path = require("node:path");
|
|
25
25
|
node_path = __toESM(node_path);
|
|
26
|
-
//#region ../types/dist/event-category-
|
|
26
|
+
//#region ../types/dist/event-category-XfKNtfCc.mjs
|
|
27
27
|
var EventCategory = /* @__PURE__ */ function(EventCategory) {
|
|
28
28
|
EventCategory["SystemBoot"] = "system.boot";
|
|
29
29
|
EventCategory["SystemAddonsReady"] = "system.addons-ready";
|
|
@@ -40,9 +40,10 @@ var EventCategory = /* @__PURE__ */ function(EventCategory) {
|
|
|
40
40
|
EventCategory["SystemRestartCompleted"] = "system.restart-completed";
|
|
41
41
|
/**
|
|
42
42
|
* A newer addon or server-root package version was found by the
|
|
43
|
-
* authoritative registry check. Emitted once
|
|
44
|
-
* `(
|
|
45
|
-
*
|
|
43
|
+
* authoritative registry check. Emitted once when any observed
|
|
44
|
+
* `latestVersion` changes (or a package/node first appears behind);
|
|
45
|
+
* the payload carries the full currently-available list. Repeated
|
|
46
|
+
* polling of the same latests is silent.
|
|
46
47
|
*/
|
|
47
48
|
EventCategory["UpdateAvailable"] = "update.available";
|
|
48
49
|
/**
|
|
@@ -61,6 +62,22 @@ var EventCategory = /* @__PURE__ */ function(EventCategory) {
|
|
|
61
62
|
EventCategory["AddonInstalled"] = "addon.installed";
|
|
62
63
|
EventCategory["AddonUninstalled"] = "addon.uninstalled";
|
|
63
64
|
EventCategory["AddonCrashed"] = "addon.crashed";
|
|
65
|
+
/**
|
|
66
|
+
* A RUNNER the D6 crash circuit-breaker gave up on — terminal.
|
|
67
|
+
*
|
|
68
|
+
* `AddonCrashed` is the routine, self-healing fact ("it crashed; it is being
|
|
69
|
+
* respawned"); this is the one that never resolves itself. Emitted exactly
|
|
70
|
+
* once per trip, by `process-service.ts`, carrying the node, the runner, the
|
|
71
|
+
* addons it hosted and the crash count that tripped the breaker.
|
|
72
|
+
*
|
|
73
|
+
* It exists because a runner marked terminally `failed` used to be SILENT:
|
|
74
|
+
* on 2026-08-18 the `recorder` runner died of three unhandled ffmpeg spawn
|
|
75
|
+
* errors, the breaker stopped respawning it (correctly), `/health` kept
|
|
76
|
+
* returning 200, and fleet-wide recording was gone for 3h15 before the
|
|
77
|
+
* operator's phone told him. The Notification Center's system-event intake
|
|
78
|
+
* consumes this category and maps it to the `addon-crash-loop` kind.
|
|
79
|
+
*/
|
|
80
|
+
EventCategory["AddonRunnerFailed"] = "addon.runner-failed";
|
|
64
81
|
EventCategory["AddonError"] = "addon.error";
|
|
65
82
|
EventCategory["AddonPageReady"] = "addon.page-ready";
|
|
66
83
|
EventCategory["AddonWidgetReady"] = "addon.widget-ready";
|
|
@@ -7556,6 +7573,10 @@ var RecordingBandSchema = object({
|
|
|
7556
7573
|
preBufferSec: number().min(0).optional(),
|
|
7557
7574
|
postBufferSec: number().min(0).optional()
|
|
7558
7575
|
});
|
|
7576
|
+
({
|
|
7577
|
+
preBufferSec: 10,
|
|
7578
|
+
postBufferSec: 30
|
|
7579
|
+
}).postBufferSec * 1e3;
|
|
7559
7580
|
/**
|
|
7560
7581
|
* Per-device retention overrides. Every field is optional; an unset or `0`
|
|
7561
7582
|
* value inherits the node-wide recorder default. Only footage-lifetime limits
|
|
@@ -7603,6 +7624,12 @@ var RecordingConfigSchema = object({
|
|
|
7603
7624
|
/** DERIVED summary of `bands`, stamped by the recorder on every save.
|
|
7604
7625
|
* Authoring it has no effect — see {@link RecordingStorageModeSchema}. */
|
|
7605
7626
|
mode: RecordingStorageModeSchema.optional(),
|
|
7627
|
+
/**
|
|
7628
|
+
* Which assigned broker slots to record. Absent / empty = {@link
|
|
7629
|
+
* DEFAULT_RECORDING_PROFILES} (`high`+`low`) intersected with the
|
|
7630
|
+
* camera's currently assigned slots — never `mid` unless the operator
|
|
7631
|
+
* picks it, and never a slot the broker has not assigned.
|
|
7632
|
+
*/
|
|
7606
7633
|
profiles: array(CamProfileSchema).optional(),
|
|
7607
7634
|
segmentSeconds: number().int().positive().optional(),
|
|
7608
7635
|
/**
|
|
@@ -7683,7 +7710,11 @@ var RelocateFootageInputSchema = object({
|
|
|
7683
7710
|
profiles: array(string()).optional(),
|
|
7684
7711
|
/** Copy throttle in MB/s (default 40) — the drain is a background chore,
|
|
7685
7712
|
* never allowed to starve live writers. */
|
|
7686
|
-
throttleMbps: number().min(1).max(1e3).optional()
|
|
7713
|
+
throttleMbps: number().min(1).max(1e3).optional(),
|
|
7714
|
+
/** Move only segments whose startMs is >= this. Absent = the whole source
|
|
7715
|
+
* pile. Used when a full drain is too expensive and the operator only
|
|
7716
|
+
* wants the recent window on the new disk. */
|
|
7717
|
+
sinceMs: number().int().optional()
|
|
7687
7718
|
});
|
|
7688
7719
|
/** Internal, lease-scoped participant operation. It is intentionally separate
|
|
7689
7720
|
* from persistent recording settings: a migration never changes
|
|
@@ -14246,6 +14277,7 @@ var NcSystemEventKindSchema = _enum([
|
|
|
14246
14277
|
"node-offline",
|
|
14247
14278
|
"node-inference-unavailable",
|
|
14248
14279
|
"detection-blind",
|
|
14280
|
+
"addon-crash-loop",
|
|
14249
14281
|
"addon-update-available",
|
|
14250
14282
|
"server-update-available",
|
|
14251
14283
|
"alarm-triggered",
|
|
@@ -14253,6 +14285,9 @@ var NcSystemEventKindSchema = _enum([
|
|
|
14253
14285
|
"alarm-disarmed",
|
|
14254
14286
|
"alarm-arming",
|
|
14255
14287
|
"alarm-arm-refused",
|
|
14288
|
+
"addon-updated",
|
|
14289
|
+
"server-updated",
|
|
14290
|
+
"export-completed",
|
|
14256
14291
|
"camera-online",
|
|
14257
14292
|
"camera-offline",
|
|
14258
14293
|
"camera-disabled",
|
|
@@ -16146,13 +16181,19 @@ var RetrainStatusSchema = _enum([
|
|
|
16146
16181
|
* "never marked" from "already trained" must read `retrainStatus`.
|
|
16147
16182
|
*
|
|
16148
16183
|
* `debug` does NOT pin; it is attention, not durability.
|
|
16184
|
+
*
|
|
16185
|
+
* `favourited` IS a BOOLEAN pin (durability bit), not a retrain lifecycle.
|
|
16186
|
+
* A favourited track is skipped by retention the same way `staging` is, but
|
|
16187
|
+
* it does not enter `none|staging|trained` and has no staging budget.
|
|
16149
16188
|
*/
|
|
16150
16189
|
var TrackFlagFields = {
|
|
16151
16190
|
/** Operator marked this track as training material — i.e. `retrainStatus` is
|
|
16152
16191
|
* `'staging'`. */
|
|
16153
16192
|
markForTrain: boolean().optional(),
|
|
16154
16193
|
/** Operator marked this track for diagnostic attention. */
|
|
16155
|
-
debug: boolean().optional()
|
|
16194
|
+
debug: boolean().optional(),
|
|
16195
|
+
/** Operator favourited this track. Pins it against pruning. */
|
|
16196
|
+
favourited: boolean().optional()
|
|
16156
16197
|
};
|
|
16157
16198
|
/**
|
|
16158
16199
|
* The lifecycle field itself, on the READ surfaces only (`Track`, `KeyEvent`).
|
|
@@ -16177,6 +16218,7 @@ var TrackFlagsSchema = object({
|
|
|
16177
16218
|
trackId: string(),
|
|
16178
16219
|
markForTrain: boolean(),
|
|
16179
16220
|
debug: boolean(),
|
|
16221
|
+
favourited: boolean(),
|
|
16180
16222
|
/** The lifecycle state the boolean was derived from. Required here (unlike on
|
|
16181
16223
|
* a track row) because this shape is only ever produced by the write body,
|
|
16182
16224
|
* which always knows it — and a surface that has just written needs to render
|
|
@@ -16809,6 +16851,12 @@ var TrackCascadeCountsSchema = object({
|
|
|
16809
16851
|
/** Per-track CLIP search vectors removed (best-effort). */
|
|
16810
16852
|
embeddings: number().int()
|
|
16811
16853
|
});
|
|
16854
|
+
/** Disk-wins reconcile: media rows whose blobs are gone, then empty tracks. */
|
|
16855
|
+
var DiskReconcileCountsSchema = object({
|
|
16856
|
+
mediaDropped: number().int(),
|
|
16857
|
+
tracks: number().int(),
|
|
16858
|
+
events: number().int()
|
|
16859
|
+
});
|
|
16812
16860
|
/** Event-store footprint for one camera. */
|
|
16813
16861
|
var EventStoreDeviceFootprintSchema = object({
|
|
16814
16862
|
deviceId: number(),
|
|
@@ -16985,6 +17033,9 @@ DeviceType.Camera, method(object({ deviceId: number() }), array(TrackSchema).rea
|
|
|
16985
17033
|
}), method(object({ deviceId: number() }), TrackCascadeCountsSchema, {
|
|
16986
17034
|
kind: "mutation",
|
|
16987
17035
|
auth: "admin"
|
|
17036
|
+
}), method(object({ deviceId: number() }), DiskReconcileCountsSchema, {
|
|
17037
|
+
kind: "mutation",
|
|
17038
|
+
auth: "admin"
|
|
16988
17039
|
}), method(object({
|
|
16989
17040
|
deviceId: number(),
|
|
16990
17041
|
trackIds: array(string()).min(1)
|
|
@@ -18495,6 +18546,24 @@ var CameraStatusDegradationSchema = object({
|
|
|
18495
18546
|
*
|
|
18496
18547
|
* See spec: `docs/superpowers/specs/2026-06-24-camera-status-aggregator-cap.md`
|
|
18497
18548
|
*/
|
|
18549
|
+
var DiskReconcileJobSchema = object({
|
|
18550
|
+
state: _enum([
|
|
18551
|
+
"idle",
|
|
18552
|
+
"running",
|
|
18553
|
+
"done",
|
|
18554
|
+
"error"
|
|
18555
|
+
]),
|
|
18556
|
+
total: number().int().nonnegative(),
|
|
18557
|
+
completed: number().int().nonnegative(),
|
|
18558
|
+
currentDeviceId: number().int().nullable(),
|
|
18559
|
+
failed: array(number().int()).readonly(),
|
|
18560
|
+
mediaDropped: number().int().nonnegative(),
|
|
18561
|
+
tracks: number().int().nonnegative(),
|
|
18562
|
+
events: number().int().nonnegative(),
|
|
18563
|
+
startedAtMs: number().int().nullable(),
|
|
18564
|
+
finishedAtMs: number().int().nullable(),
|
|
18565
|
+
error: string().nullable()
|
|
18566
|
+
});
|
|
18498
18567
|
var CameraStatusSchema = object({
|
|
18499
18568
|
deviceId: number(),
|
|
18500
18569
|
assignment: CameraAssignmentStatusSchema,
|
|
@@ -18726,7 +18795,10 @@ method(StorageMigrationLeaseInputSchema, object({ paused: literal(true) }), {
|
|
|
18726
18795
|
}), CameraSwitchGroupSchema, {
|
|
18727
18796
|
kind: "mutation",
|
|
18728
18797
|
auth: "admin"
|
|
18729
|
-
}), method(object({ deviceId: number() }), CameraStatusSchema), method(object({ deviceIds: array(number()).optional() }), array(CameraStatusSchema).readonly()), method(_void(),
|
|
18798
|
+
}), method(object({ deviceId: number() }), CameraStatusSchema), method(object({ deviceIds: array(number()).optional() }), array(CameraStatusSchema).readonly()), method(_void(), DiskReconcileJobSchema, {
|
|
18799
|
+
kind: "mutation",
|
|
18800
|
+
auth: "admin"
|
|
18801
|
+
}), method(_void(), DiskReconcileJobSchema, { auth: "admin" }), method(_void(), array(PipelineTemplateSchema).readonly()), method(object({
|
|
18730
18802
|
name: string(),
|
|
18731
18803
|
description: string().optional(),
|
|
18732
18804
|
config: CameraPipelineConfigSchema
|
|
@@ -19844,20 +19916,6 @@ var VectorStatsResultSchema = object({
|
|
|
19844
19916
|
exact: boolean()
|
|
19845
19917
|
});
|
|
19846
19918
|
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);
|
|
19847
|
-
/**
|
|
19848
|
-
* `videoclips` — the unified, navigable-clip surface for a camera.
|
|
19849
|
-
*
|
|
19850
|
-
* A device-scoped WRAPPER cap (like `pipeline-analytics`): exactly one active
|
|
19851
|
-
* provider per device, substitutable. The DEFAULT provider (registered by
|
|
19852
|
-
* `addon-post-analysis`, `defaultActive: true`) composes the analytics event
|
|
19853
|
-
* log (markers + thumbnails) with the recorder's `getPlaybackManifest` — a clip
|
|
19854
|
-
* is a time-WINDOW over existing footage, never a separate file. A camera that
|
|
19855
|
-
* exposes NATIVE onboard clips (Reolink/Hikvision NVR) can later substitute the
|
|
19856
|
-
* wrapper provider for its device and serve its own clip catalog + URLs.
|
|
19857
|
-
*
|
|
19858
|
-
* A `Clip` is purely time-based (subtree-blind): playback resolves segments by
|
|
19859
|
-
* temporal overlap, so the API never decides `continuous` vs `events`.
|
|
19860
|
-
*/
|
|
19861
19919
|
var ClipSchema = object({
|
|
19862
19920
|
/** Opaque, provider-namespaced id. The default provider encodes the time
|
|
19863
19921
|
* window so `getClipPlayback` is self-contained (no event re-query). */
|
|
@@ -19874,8 +19932,65 @@ var ClipSchema = object({
|
|
|
19874
19932
|
startMs: number(),
|
|
19875
19933
|
endMs: number()
|
|
19876
19934
|
}),
|
|
19877
|
-
/**
|
|
19878
|
-
|
|
19935
|
+
/**
|
|
19936
|
+
* Distinct object classes attached to this visit (`person`, `car`, …),
|
|
19937
|
+
* dominant first, capped at {@link MAX_CLIP_LABELS}. The ribbon renders these
|
|
19938
|
+
* instead of the bare kind — "Object" tells the operator nothing a colour bar
|
|
19939
|
+
* did not. Absent (never empty) when the visit attached no classified object
|
|
19940
|
+
* event, so a motion/audio-only visit keeps its kind label.
|
|
19941
|
+
*/
|
|
19942
|
+
labels: array(string()).max(3).optional(),
|
|
19943
|
+
/**
|
|
19944
|
+
* Lazy thumbnail URL, never inlined.
|
|
19945
|
+
*
|
|
19946
|
+
* Recording-derived clips (events-mode keep-window, and the prepared
|
|
19947
|
+
* continuous event+fragment visit) MUST use the snapshot of the **main
|
|
19948
|
+
* event of the interval** — `getEventMedia({ eventId, kind: 'snapshot' })`
|
|
19949
|
+
* of the event that owns `kind` (object > motion > audio). Do not extract
|
|
19950
|
+
* a keyframe from the recorded segments. Other providers (onboard, HKSV)
|
|
19951
|
+
* mint their own stills.
|
|
19952
|
+
*
|
|
19953
|
+
* **VOUCHED, never fabricated.** A provider emits this only for an event it
|
|
19954
|
+
* has CONFIRMED owns at least one media row (its own, or its owning track's).
|
|
19955
|
+
* Absent is meaningful — "this visit has no event still" — never "we did not
|
|
19956
|
+
* look". Stamping it from a URL template made 35% of one camera's clips point
|
|
19957
|
+
* at a 404 (device 3836, 2026-08-17: 64 of 179 clips dead, 63 of them motion).
|
|
19958
|
+
* A read that FAILS drops the claim; it never invents it.
|
|
19959
|
+
*/
|
|
19960
|
+
thumbnail: string().optional(),
|
|
19961
|
+
/**
|
|
19962
|
+
* An instant INSIDE this visit's footage, hole-safe, where a recorded still
|
|
19963
|
+
* can be decoded. Present whenever the visit came from recorded availability;
|
|
19964
|
+
* absent on a per-event padded window (there is no footage to promise).
|
|
19965
|
+
*
|
|
19966
|
+
* This is not a thumbnail and not a second byte path: it is the argument to
|
|
19967
|
+
* the recorder's existing still route. The surface — never the provider —
|
|
19968
|
+
* decides whether to use it. It is the midpoint of the visit's LONGEST
|
|
19969
|
+
* contiguous range, not of the visit: a visit spans its holes by
|
|
19970
|
+
* construction, so a naive midpoint lands in dead air.
|
|
19971
|
+
*/
|
|
19972
|
+
stillAtMs: number().optional(),
|
|
19973
|
+
/**
|
|
19974
|
+
* Analytics event ids that overlap this visit — a BOUNDED sample, newest
|
|
19975
|
+
* first within kind (object → motion → audio), capped at
|
|
19976
|
+
* {@link MAX_CLIP_EVENT_IDS}. Empty on footage-only clips.
|
|
19977
|
+
*
|
|
19978
|
+
* Bounded because it is not a payload the surface pages through: one visit on
|
|
19979
|
+
* device 615 carried 2 345 ids, and `eventIds` was 99% of a 153 KB
|
|
19980
|
+
* camera-day. Read {@link eventCount} for the true total.
|
|
19981
|
+
*/
|
|
19982
|
+
eventIds: array(string()).optional(),
|
|
19983
|
+
/** How many analytics events actually overlap this visit. Differs from
|
|
19984
|
+
* `eventIds.length` exactly when the sample was capped — so a truncated
|
|
19985
|
+
* list is never mistaken for a quiet visit. */
|
|
19986
|
+
eventCount: number().int().nonnegative().optional(),
|
|
19987
|
+
/** Intra-visit footage holes (GOP rolls, discarded segments) still shorter
|
|
19988
|
+
* than `VISIT_MERGE_GAP_MS`. Playback concatenates around them; the timeline
|
|
19989
|
+
* bar keeps showing them via `recording.getAvailability`. */
|
|
19990
|
+
holes: array(object({
|
|
19991
|
+
startMs: number(),
|
|
19992
|
+
endMs: number()
|
|
19993
|
+
})).optional()
|
|
19879
19994
|
});
|
|
19880
19995
|
var ClipPlaybackSchema = object({
|
|
19881
19996
|
/** HLS master URL through the hub data-plane (Range + token in path). */
|
|
@@ -20339,7 +20454,14 @@ var SearchResultSchema = object({
|
|
|
20339
20454
|
});
|
|
20340
20455
|
var AutoUpdateSettingsSchema = object({
|
|
20341
20456
|
channel: ChannelSchema,
|
|
20342
|
-
intervalSeconds: number()
|
|
20457
|
+
intervalSeconds: number(),
|
|
20458
|
+
/**
|
|
20459
|
+
* Cadence of the "an update exists" POLLER, in seconds. Independent of
|
|
20460
|
+
* `channel`: the poller runs while auto-apply is `off`, because being told
|
|
20461
|
+
* about a publish and installing it are different decisions. Clamped
|
|
20462
|
+
* server-side to 900 s … 604800 s; defaults to 21600 s (6 h).
|
|
20463
|
+
*/
|
|
20464
|
+
updateCheckIntervalSeconds: number()
|
|
20343
20465
|
});
|
|
20344
20466
|
var AddonAutoUpdateSchema = ChannelWithInheritSchema;
|
|
20345
20467
|
var RestartAddonResultSchema = unknown();
|
|
@@ -20480,7 +20602,9 @@ method(_void(), array(AddonListItemSchema).readonly()), method(object({
|
|
|
20480
20602
|
auth: "admin"
|
|
20481
20603
|
}), method(_void(), AutoUpdateSettingsSchema, { auth: "admin" }), method(object({
|
|
20482
20604
|
channel: ChannelSchema,
|
|
20483
|
-
intervalSeconds: number().min(300).max(86400).optional()
|
|
20605
|
+
intervalSeconds: number().min(300).max(86400).optional(),
|
|
20606
|
+
/** Availability-poll cadence; see AutoUpdateSettingsSchema. */
|
|
20607
|
+
updateCheckIntervalSeconds: number().min(900).max(604800).optional()
|
|
20484
20608
|
}), unknown(), {
|
|
20485
20609
|
kind: "mutation",
|
|
20486
20610
|
auth: "admin"
|
|
@@ -24473,7 +24597,9 @@ var ExportOptionsSchema = object({
|
|
|
24473
24597
|
includeAudio: boolean(),
|
|
24474
24598
|
maxLifeMs: number().int().positive(),
|
|
24475
24599
|
deleteAfterDownload: boolean(),
|
|
24476
|
-
title: string().max(200).optional()
|
|
24600
|
+
title: string().max(200).optional(),
|
|
24601
|
+
/** Notification-output target ids to ping when this export becomes ready. */
|
|
24602
|
+
notifyTargetIds: array(string().min(1)).max(20).optional()
|
|
24477
24603
|
}).superRefine((v, ctx) => {
|
|
24478
24604
|
if (v.speed !== void 0 && v.timelapse !== void 0) ctx.addIssue({
|
|
24479
24605
|
code: ZodIssueCode.custom,
|
|
@@ -24532,10 +24658,18 @@ var ExportBytesSchema = object({
|
|
|
24532
24658
|
});
|
|
24533
24659
|
method(object({
|
|
24534
24660
|
deviceId: number(),
|
|
24535
|
-
|
|
24661
|
+
/** @deprecated Prefer `profiles`. Kept so timelapse/notifiers keep working. */
|
|
24662
|
+
profile: string().optional(),
|
|
24663
|
+
profiles: array(string()).min(1).optional(),
|
|
24536
24664
|
fromMs: number(),
|
|
24537
24665
|
toMs: number(),
|
|
24538
24666
|
options: ExportOptionsSchema
|
|
24667
|
+
}).superRefine((v, ctx) => {
|
|
24668
|
+
if ((v.profiles !== void 0 && v.profiles.length > 0 ? v.profiles : v.profile !== void 0 ? [v.profile] : []).length < 1) ctx.addIssue({
|
|
24669
|
+
code: ZodIssueCode.custom,
|
|
24670
|
+
message: "pass profiles[] (min 1) or legacy profile",
|
|
24671
|
+
path: ["profiles"]
|
|
24672
|
+
});
|
|
24539
24673
|
}), ExportRecordSchema, {
|
|
24540
24674
|
kind: "mutation",
|
|
24541
24675
|
auth: "protected"
|
|
@@ -29135,6 +29269,12 @@ Object.freeze({
|
|
|
29135
29269
|
addonId: null,
|
|
29136
29270
|
access: "create"
|
|
29137
29271
|
},
|
|
29272
|
+
"pipelineAnalytics.reconcileFromDisk": {
|
|
29273
|
+
capName: "pipeline-analytics",
|
|
29274
|
+
capScope: "device",
|
|
29275
|
+
addonId: null,
|
|
29276
|
+
access: "create"
|
|
29277
|
+
},
|
|
29138
29278
|
"pipelineAnalytics.refreshStorageLocationsForMigration": {
|
|
29139
29279
|
capName: "pipeline-analytics",
|
|
29140
29280
|
capScope: "device",
|
|
@@ -29537,6 +29677,12 @@ Object.freeze({
|
|
|
29537
29677
|
addonId: null,
|
|
29538
29678
|
access: "view"
|
|
29539
29679
|
},
|
|
29680
|
+
"pipelineOrchestrator.getReconcileFromDiskStatus": {
|
|
29681
|
+
capName: "pipeline-orchestrator",
|
|
29682
|
+
capScope: "system",
|
|
29683
|
+
addonId: null,
|
|
29684
|
+
access: "view"
|
|
29685
|
+
},
|
|
29540
29686
|
"pipelineOrchestrator.listAgentSettings": {
|
|
29541
29687
|
capName: "pipeline-orchestrator",
|
|
29542
29688
|
capScope: "system",
|
|
@@ -29561,6 +29707,12 @@ Object.freeze({
|
|
|
29561
29707
|
addonId: null,
|
|
29562
29708
|
access: "create"
|
|
29563
29709
|
},
|
|
29710
|
+
"pipelineOrchestrator.reconcileFromDisk": {
|
|
29711
|
+
capName: "pipeline-orchestrator",
|
|
29712
|
+
capScope: "system",
|
|
29713
|
+
addonId: null,
|
|
29714
|
+
access: "create"
|
|
29715
|
+
},
|
|
29564
29716
|
"pipelineOrchestrator.removeAgentSettings": {
|
|
29565
29717
|
capName: "pipeline-orchestrator",
|
|
29566
29718
|
capScope: "system",
|
|
@@ -32552,6 +32704,11 @@ Object.freeze({
|
|
|
32552
32704
|
form: "single",
|
|
32553
32705
|
optional: true
|
|
32554
32706
|
}],
|
|
32707
|
+
"pipelineAnalytics.reconcileFromDisk": [{
|
|
32708
|
+
name: "deviceId",
|
|
32709
|
+
form: "single",
|
|
32710
|
+
optional: false
|
|
32711
|
+
}],
|
|
32555
32712
|
"pipelineAnalytics.restageRetrainTrack": [{
|
|
32556
32713
|
name: "deviceId",
|
|
32557
32714
|
form: "single",
|
|
@@ -33617,6 +33774,8 @@ DEFAULT_NATIVE_LEASE_SETTINGS.budgetMb;
|
|
|
33617
33774
|
DEFAULT_NATIVE_LEASE_SETTINGS.activityMs;
|
|
33618
33775
|
DEFAULT_NATIVE_LEASE_SETTINGS.tileBudgetMb;
|
|
33619
33776
|
DEFAULT_NATIVE_LEASE_SETTINGS.admission;
|
|
33777
|
+
var MB = 1024 * 1024;
|
|
33778
|
+
1024 * MB, 3072 * MB;
|
|
33620
33779
|
//#endregion
|
|
33621
33780
|
//#region src/shared.ts
|
|
33622
33781
|
/**
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { randomUUID } from "node:crypto";
|
|
2
2
|
import * as path from "node:path";
|
|
3
|
-
//#region ../types/dist/event-category-
|
|
3
|
+
//#region ../types/dist/event-category-XfKNtfCc.mjs
|
|
4
4
|
var EventCategory = /* @__PURE__ */ function(EventCategory) {
|
|
5
5
|
EventCategory["SystemBoot"] = "system.boot";
|
|
6
6
|
EventCategory["SystemAddonsReady"] = "system.addons-ready";
|
|
@@ -17,9 +17,10 @@ var EventCategory = /* @__PURE__ */ function(EventCategory) {
|
|
|
17
17
|
EventCategory["SystemRestartCompleted"] = "system.restart-completed";
|
|
18
18
|
/**
|
|
19
19
|
* A newer addon or server-root package version was found by the
|
|
20
|
-
* authoritative registry check. Emitted once
|
|
21
|
-
* `(
|
|
22
|
-
*
|
|
20
|
+
* authoritative registry check. Emitted once when any observed
|
|
21
|
+
* `latestVersion` changes (or a package/node first appears behind);
|
|
22
|
+
* the payload carries the full currently-available list. Repeated
|
|
23
|
+
* polling of the same latests is silent.
|
|
23
24
|
*/
|
|
24
25
|
EventCategory["UpdateAvailable"] = "update.available";
|
|
25
26
|
/**
|
|
@@ -38,6 +39,22 @@ var EventCategory = /* @__PURE__ */ function(EventCategory) {
|
|
|
38
39
|
EventCategory["AddonInstalled"] = "addon.installed";
|
|
39
40
|
EventCategory["AddonUninstalled"] = "addon.uninstalled";
|
|
40
41
|
EventCategory["AddonCrashed"] = "addon.crashed";
|
|
42
|
+
/**
|
|
43
|
+
* A RUNNER the D6 crash circuit-breaker gave up on — terminal.
|
|
44
|
+
*
|
|
45
|
+
* `AddonCrashed` is the routine, self-healing fact ("it crashed; it is being
|
|
46
|
+
* respawned"); this is the one that never resolves itself. Emitted exactly
|
|
47
|
+
* once per trip, by `process-service.ts`, carrying the node, the runner, the
|
|
48
|
+
* addons it hosted and the crash count that tripped the breaker.
|
|
49
|
+
*
|
|
50
|
+
* It exists because a runner marked terminally `failed` used to be SILENT:
|
|
51
|
+
* on 2026-08-18 the `recorder` runner died of three unhandled ffmpeg spawn
|
|
52
|
+
* errors, the breaker stopped respawning it (correctly), `/health` kept
|
|
53
|
+
* returning 200, and fleet-wide recording was gone for 3h15 before the
|
|
54
|
+
* operator's phone told him. The Notification Center's system-event intake
|
|
55
|
+
* consumes this category and maps it to the `addon-crash-loop` kind.
|
|
56
|
+
*/
|
|
57
|
+
EventCategory["AddonRunnerFailed"] = "addon.runner-failed";
|
|
41
58
|
EventCategory["AddonError"] = "addon.error";
|
|
42
59
|
EventCategory["AddonPageReady"] = "addon.page-ready";
|
|
43
60
|
EventCategory["AddonWidgetReady"] = "addon.widget-ready";
|
|
@@ -7533,6 +7550,10 @@ var RecordingBandSchema = object({
|
|
|
7533
7550
|
preBufferSec: number().min(0).optional(),
|
|
7534
7551
|
postBufferSec: number().min(0).optional()
|
|
7535
7552
|
});
|
|
7553
|
+
({
|
|
7554
|
+
preBufferSec: 10,
|
|
7555
|
+
postBufferSec: 30
|
|
7556
|
+
}).postBufferSec * 1e3;
|
|
7536
7557
|
/**
|
|
7537
7558
|
* Per-device retention overrides. Every field is optional; an unset or `0`
|
|
7538
7559
|
* value inherits the node-wide recorder default. Only footage-lifetime limits
|
|
@@ -7580,6 +7601,12 @@ var RecordingConfigSchema = object({
|
|
|
7580
7601
|
/** DERIVED summary of `bands`, stamped by the recorder on every save.
|
|
7581
7602
|
* Authoring it has no effect — see {@link RecordingStorageModeSchema}. */
|
|
7582
7603
|
mode: RecordingStorageModeSchema.optional(),
|
|
7604
|
+
/**
|
|
7605
|
+
* Which assigned broker slots to record. Absent / empty = {@link
|
|
7606
|
+
* DEFAULT_RECORDING_PROFILES} (`high`+`low`) intersected with the
|
|
7607
|
+
* camera's currently assigned slots — never `mid` unless the operator
|
|
7608
|
+
* picks it, and never a slot the broker has not assigned.
|
|
7609
|
+
*/
|
|
7583
7610
|
profiles: array(CamProfileSchema).optional(),
|
|
7584
7611
|
segmentSeconds: number().int().positive().optional(),
|
|
7585
7612
|
/**
|
|
@@ -7660,7 +7687,11 @@ var RelocateFootageInputSchema = object({
|
|
|
7660
7687
|
profiles: array(string()).optional(),
|
|
7661
7688
|
/** Copy throttle in MB/s (default 40) — the drain is a background chore,
|
|
7662
7689
|
* never allowed to starve live writers. */
|
|
7663
|
-
throttleMbps: number().min(1).max(1e3).optional()
|
|
7690
|
+
throttleMbps: number().min(1).max(1e3).optional(),
|
|
7691
|
+
/** Move only segments whose startMs is >= this. Absent = the whole source
|
|
7692
|
+
* pile. Used when a full drain is too expensive and the operator only
|
|
7693
|
+
* wants the recent window on the new disk. */
|
|
7694
|
+
sinceMs: number().int().optional()
|
|
7664
7695
|
});
|
|
7665
7696
|
/** Internal, lease-scoped participant operation. It is intentionally separate
|
|
7666
7697
|
* from persistent recording settings: a migration never changes
|
|
@@ -14223,6 +14254,7 @@ var NcSystemEventKindSchema = _enum([
|
|
|
14223
14254
|
"node-offline",
|
|
14224
14255
|
"node-inference-unavailable",
|
|
14225
14256
|
"detection-blind",
|
|
14257
|
+
"addon-crash-loop",
|
|
14226
14258
|
"addon-update-available",
|
|
14227
14259
|
"server-update-available",
|
|
14228
14260
|
"alarm-triggered",
|
|
@@ -14230,6 +14262,9 @@ var NcSystemEventKindSchema = _enum([
|
|
|
14230
14262
|
"alarm-disarmed",
|
|
14231
14263
|
"alarm-arming",
|
|
14232
14264
|
"alarm-arm-refused",
|
|
14265
|
+
"addon-updated",
|
|
14266
|
+
"server-updated",
|
|
14267
|
+
"export-completed",
|
|
14233
14268
|
"camera-online",
|
|
14234
14269
|
"camera-offline",
|
|
14235
14270
|
"camera-disabled",
|
|
@@ -16123,13 +16158,19 @@ var RetrainStatusSchema = _enum([
|
|
|
16123
16158
|
* "never marked" from "already trained" must read `retrainStatus`.
|
|
16124
16159
|
*
|
|
16125
16160
|
* `debug` does NOT pin; it is attention, not durability.
|
|
16161
|
+
*
|
|
16162
|
+
* `favourited` IS a BOOLEAN pin (durability bit), not a retrain lifecycle.
|
|
16163
|
+
* A favourited track is skipped by retention the same way `staging` is, but
|
|
16164
|
+
* it does not enter `none|staging|trained` and has no staging budget.
|
|
16126
16165
|
*/
|
|
16127
16166
|
var TrackFlagFields = {
|
|
16128
16167
|
/** Operator marked this track as training material — i.e. `retrainStatus` is
|
|
16129
16168
|
* `'staging'`. */
|
|
16130
16169
|
markForTrain: boolean().optional(),
|
|
16131
16170
|
/** Operator marked this track for diagnostic attention. */
|
|
16132
|
-
debug: boolean().optional()
|
|
16171
|
+
debug: boolean().optional(),
|
|
16172
|
+
/** Operator favourited this track. Pins it against pruning. */
|
|
16173
|
+
favourited: boolean().optional()
|
|
16133
16174
|
};
|
|
16134
16175
|
/**
|
|
16135
16176
|
* The lifecycle field itself, on the READ surfaces only (`Track`, `KeyEvent`).
|
|
@@ -16154,6 +16195,7 @@ var TrackFlagsSchema = object({
|
|
|
16154
16195
|
trackId: string(),
|
|
16155
16196
|
markForTrain: boolean(),
|
|
16156
16197
|
debug: boolean(),
|
|
16198
|
+
favourited: boolean(),
|
|
16157
16199
|
/** The lifecycle state the boolean was derived from. Required here (unlike on
|
|
16158
16200
|
* a track row) because this shape is only ever produced by the write body,
|
|
16159
16201
|
* which always knows it — and a surface that has just written needs to render
|
|
@@ -16786,6 +16828,12 @@ var TrackCascadeCountsSchema = object({
|
|
|
16786
16828
|
/** Per-track CLIP search vectors removed (best-effort). */
|
|
16787
16829
|
embeddings: number().int()
|
|
16788
16830
|
});
|
|
16831
|
+
/** Disk-wins reconcile: media rows whose blobs are gone, then empty tracks. */
|
|
16832
|
+
var DiskReconcileCountsSchema = object({
|
|
16833
|
+
mediaDropped: number().int(),
|
|
16834
|
+
tracks: number().int(),
|
|
16835
|
+
events: number().int()
|
|
16836
|
+
});
|
|
16789
16837
|
/** Event-store footprint for one camera. */
|
|
16790
16838
|
var EventStoreDeviceFootprintSchema = object({
|
|
16791
16839
|
deviceId: number(),
|
|
@@ -16962,6 +17010,9 @@ DeviceType.Camera, method(object({ deviceId: number() }), array(TrackSchema).rea
|
|
|
16962
17010
|
}), method(object({ deviceId: number() }), TrackCascadeCountsSchema, {
|
|
16963
17011
|
kind: "mutation",
|
|
16964
17012
|
auth: "admin"
|
|
17013
|
+
}), method(object({ deviceId: number() }), DiskReconcileCountsSchema, {
|
|
17014
|
+
kind: "mutation",
|
|
17015
|
+
auth: "admin"
|
|
16965
17016
|
}), method(object({
|
|
16966
17017
|
deviceId: number(),
|
|
16967
17018
|
trackIds: array(string()).min(1)
|
|
@@ -18472,6 +18523,24 @@ var CameraStatusDegradationSchema = object({
|
|
|
18472
18523
|
*
|
|
18473
18524
|
* See spec: `docs/superpowers/specs/2026-06-24-camera-status-aggregator-cap.md`
|
|
18474
18525
|
*/
|
|
18526
|
+
var DiskReconcileJobSchema = object({
|
|
18527
|
+
state: _enum([
|
|
18528
|
+
"idle",
|
|
18529
|
+
"running",
|
|
18530
|
+
"done",
|
|
18531
|
+
"error"
|
|
18532
|
+
]),
|
|
18533
|
+
total: number().int().nonnegative(),
|
|
18534
|
+
completed: number().int().nonnegative(),
|
|
18535
|
+
currentDeviceId: number().int().nullable(),
|
|
18536
|
+
failed: array(number().int()).readonly(),
|
|
18537
|
+
mediaDropped: number().int().nonnegative(),
|
|
18538
|
+
tracks: number().int().nonnegative(),
|
|
18539
|
+
events: number().int().nonnegative(),
|
|
18540
|
+
startedAtMs: number().int().nullable(),
|
|
18541
|
+
finishedAtMs: number().int().nullable(),
|
|
18542
|
+
error: string().nullable()
|
|
18543
|
+
});
|
|
18475
18544
|
var CameraStatusSchema = object({
|
|
18476
18545
|
deviceId: number(),
|
|
18477
18546
|
assignment: CameraAssignmentStatusSchema,
|
|
@@ -18703,7 +18772,10 @@ method(StorageMigrationLeaseInputSchema, object({ paused: literal(true) }), {
|
|
|
18703
18772
|
}), CameraSwitchGroupSchema, {
|
|
18704
18773
|
kind: "mutation",
|
|
18705
18774
|
auth: "admin"
|
|
18706
|
-
}), method(object({ deviceId: number() }), CameraStatusSchema), method(object({ deviceIds: array(number()).optional() }), array(CameraStatusSchema).readonly()), method(_void(),
|
|
18775
|
+
}), method(object({ deviceId: number() }), CameraStatusSchema), method(object({ deviceIds: array(number()).optional() }), array(CameraStatusSchema).readonly()), method(_void(), DiskReconcileJobSchema, {
|
|
18776
|
+
kind: "mutation",
|
|
18777
|
+
auth: "admin"
|
|
18778
|
+
}), method(_void(), DiskReconcileJobSchema, { auth: "admin" }), method(_void(), array(PipelineTemplateSchema).readonly()), method(object({
|
|
18707
18779
|
name: string(),
|
|
18708
18780
|
description: string().optional(),
|
|
18709
18781
|
config: CameraPipelineConfigSchema
|
|
@@ -19821,20 +19893,6 @@ var VectorStatsResultSchema = object({
|
|
|
19821
19893
|
exact: boolean()
|
|
19822
19894
|
});
|
|
19823
19895
|
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);
|
|
19824
|
-
/**
|
|
19825
|
-
* `videoclips` — the unified, navigable-clip surface for a camera.
|
|
19826
|
-
*
|
|
19827
|
-
* A device-scoped WRAPPER cap (like `pipeline-analytics`): exactly one active
|
|
19828
|
-
* provider per device, substitutable. The DEFAULT provider (registered by
|
|
19829
|
-
* `addon-post-analysis`, `defaultActive: true`) composes the analytics event
|
|
19830
|
-
* log (markers + thumbnails) with the recorder's `getPlaybackManifest` — a clip
|
|
19831
|
-
* is a time-WINDOW over existing footage, never a separate file. A camera that
|
|
19832
|
-
* exposes NATIVE onboard clips (Reolink/Hikvision NVR) can later substitute the
|
|
19833
|
-
* wrapper provider for its device and serve its own clip catalog + URLs.
|
|
19834
|
-
*
|
|
19835
|
-
* A `Clip` is purely time-based (subtree-blind): playback resolves segments by
|
|
19836
|
-
* temporal overlap, so the API never decides `continuous` vs `events`.
|
|
19837
|
-
*/
|
|
19838
19896
|
var ClipSchema = object({
|
|
19839
19897
|
/** Opaque, provider-namespaced id. The default provider encodes the time
|
|
19840
19898
|
* window so `getClipPlayback` is self-contained (no event re-query). */
|
|
@@ -19851,8 +19909,65 @@ var ClipSchema = object({
|
|
|
19851
19909
|
startMs: number(),
|
|
19852
19910
|
endMs: number()
|
|
19853
19911
|
}),
|
|
19854
|
-
/**
|
|
19855
|
-
|
|
19912
|
+
/**
|
|
19913
|
+
* Distinct object classes attached to this visit (`person`, `car`, …),
|
|
19914
|
+
* dominant first, capped at {@link MAX_CLIP_LABELS}. The ribbon renders these
|
|
19915
|
+
* instead of the bare kind — "Object" tells the operator nothing a colour bar
|
|
19916
|
+
* did not. Absent (never empty) when the visit attached no classified object
|
|
19917
|
+
* event, so a motion/audio-only visit keeps its kind label.
|
|
19918
|
+
*/
|
|
19919
|
+
labels: array(string()).max(3).optional(),
|
|
19920
|
+
/**
|
|
19921
|
+
* Lazy thumbnail URL, never inlined.
|
|
19922
|
+
*
|
|
19923
|
+
* Recording-derived clips (events-mode keep-window, and the prepared
|
|
19924
|
+
* continuous event+fragment visit) MUST use the snapshot of the **main
|
|
19925
|
+
* event of the interval** — `getEventMedia({ eventId, kind: 'snapshot' })`
|
|
19926
|
+
* of the event that owns `kind` (object > motion > audio). Do not extract
|
|
19927
|
+
* a keyframe from the recorded segments. Other providers (onboard, HKSV)
|
|
19928
|
+
* mint their own stills.
|
|
19929
|
+
*
|
|
19930
|
+
* **VOUCHED, never fabricated.** A provider emits this only for an event it
|
|
19931
|
+
* has CONFIRMED owns at least one media row (its own, or its owning track's).
|
|
19932
|
+
* Absent is meaningful — "this visit has no event still" — never "we did not
|
|
19933
|
+
* look". Stamping it from a URL template made 35% of one camera's clips point
|
|
19934
|
+
* at a 404 (device 3836, 2026-08-17: 64 of 179 clips dead, 63 of them motion).
|
|
19935
|
+
* A read that FAILS drops the claim; it never invents it.
|
|
19936
|
+
*/
|
|
19937
|
+
thumbnail: string().optional(),
|
|
19938
|
+
/**
|
|
19939
|
+
* An instant INSIDE this visit's footage, hole-safe, where a recorded still
|
|
19940
|
+
* can be decoded. Present whenever the visit came from recorded availability;
|
|
19941
|
+
* absent on a per-event padded window (there is no footage to promise).
|
|
19942
|
+
*
|
|
19943
|
+
* This is not a thumbnail and not a second byte path: it is the argument to
|
|
19944
|
+
* the recorder's existing still route. The surface — never the provider —
|
|
19945
|
+
* decides whether to use it. It is the midpoint of the visit's LONGEST
|
|
19946
|
+
* contiguous range, not of the visit: a visit spans its holes by
|
|
19947
|
+
* construction, so a naive midpoint lands in dead air.
|
|
19948
|
+
*/
|
|
19949
|
+
stillAtMs: number().optional(),
|
|
19950
|
+
/**
|
|
19951
|
+
* Analytics event ids that overlap this visit — a BOUNDED sample, newest
|
|
19952
|
+
* first within kind (object → motion → audio), capped at
|
|
19953
|
+
* {@link MAX_CLIP_EVENT_IDS}. Empty on footage-only clips.
|
|
19954
|
+
*
|
|
19955
|
+
* Bounded because it is not a payload the surface pages through: one visit on
|
|
19956
|
+
* device 615 carried 2 345 ids, and `eventIds` was 99% of a 153 KB
|
|
19957
|
+
* camera-day. Read {@link eventCount} for the true total.
|
|
19958
|
+
*/
|
|
19959
|
+
eventIds: array(string()).optional(),
|
|
19960
|
+
/** How many analytics events actually overlap this visit. Differs from
|
|
19961
|
+
* `eventIds.length` exactly when the sample was capped — so a truncated
|
|
19962
|
+
* list is never mistaken for a quiet visit. */
|
|
19963
|
+
eventCount: number().int().nonnegative().optional(),
|
|
19964
|
+
/** Intra-visit footage holes (GOP rolls, discarded segments) still shorter
|
|
19965
|
+
* than `VISIT_MERGE_GAP_MS`. Playback concatenates around them; the timeline
|
|
19966
|
+
* bar keeps showing them via `recording.getAvailability`. */
|
|
19967
|
+
holes: array(object({
|
|
19968
|
+
startMs: number(),
|
|
19969
|
+
endMs: number()
|
|
19970
|
+
})).optional()
|
|
19856
19971
|
});
|
|
19857
19972
|
var ClipPlaybackSchema = object({
|
|
19858
19973
|
/** HLS master URL through the hub data-plane (Range + token in path). */
|
|
@@ -20316,7 +20431,14 @@ var SearchResultSchema = object({
|
|
|
20316
20431
|
});
|
|
20317
20432
|
var AutoUpdateSettingsSchema = object({
|
|
20318
20433
|
channel: ChannelSchema,
|
|
20319
|
-
intervalSeconds: number()
|
|
20434
|
+
intervalSeconds: number(),
|
|
20435
|
+
/**
|
|
20436
|
+
* Cadence of the "an update exists" POLLER, in seconds. Independent of
|
|
20437
|
+
* `channel`: the poller runs while auto-apply is `off`, because being told
|
|
20438
|
+
* about a publish and installing it are different decisions. Clamped
|
|
20439
|
+
* server-side to 900 s … 604800 s; defaults to 21600 s (6 h).
|
|
20440
|
+
*/
|
|
20441
|
+
updateCheckIntervalSeconds: number()
|
|
20320
20442
|
});
|
|
20321
20443
|
var AddonAutoUpdateSchema = ChannelWithInheritSchema;
|
|
20322
20444
|
var RestartAddonResultSchema = unknown();
|
|
@@ -20457,7 +20579,9 @@ method(_void(), array(AddonListItemSchema).readonly()), method(object({
|
|
|
20457
20579
|
auth: "admin"
|
|
20458
20580
|
}), method(_void(), AutoUpdateSettingsSchema, { auth: "admin" }), method(object({
|
|
20459
20581
|
channel: ChannelSchema,
|
|
20460
|
-
intervalSeconds: number().min(300).max(86400).optional()
|
|
20582
|
+
intervalSeconds: number().min(300).max(86400).optional(),
|
|
20583
|
+
/** Availability-poll cadence; see AutoUpdateSettingsSchema. */
|
|
20584
|
+
updateCheckIntervalSeconds: number().min(900).max(604800).optional()
|
|
20461
20585
|
}), unknown(), {
|
|
20462
20586
|
kind: "mutation",
|
|
20463
20587
|
auth: "admin"
|
|
@@ -24450,7 +24574,9 @@ var ExportOptionsSchema = object({
|
|
|
24450
24574
|
includeAudio: boolean(),
|
|
24451
24575
|
maxLifeMs: number().int().positive(),
|
|
24452
24576
|
deleteAfterDownload: boolean(),
|
|
24453
|
-
title: string().max(200).optional()
|
|
24577
|
+
title: string().max(200).optional(),
|
|
24578
|
+
/** Notification-output target ids to ping when this export becomes ready. */
|
|
24579
|
+
notifyTargetIds: array(string().min(1)).max(20).optional()
|
|
24454
24580
|
}).superRefine((v, ctx) => {
|
|
24455
24581
|
if (v.speed !== void 0 && v.timelapse !== void 0) ctx.addIssue({
|
|
24456
24582
|
code: ZodIssueCode.custom,
|
|
@@ -24509,10 +24635,18 @@ var ExportBytesSchema = object({
|
|
|
24509
24635
|
});
|
|
24510
24636
|
method(object({
|
|
24511
24637
|
deviceId: number(),
|
|
24512
|
-
|
|
24638
|
+
/** @deprecated Prefer `profiles`. Kept so timelapse/notifiers keep working. */
|
|
24639
|
+
profile: string().optional(),
|
|
24640
|
+
profiles: array(string()).min(1).optional(),
|
|
24513
24641
|
fromMs: number(),
|
|
24514
24642
|
toMs: number(),
|
|
24515
24643
|
options: ExportOptionsSchema
|
|
24644
|
+
}).superRefine((v, ctx) => {
|
|
24645
|
+
if ((v.profiles !== void 0 && v.profiles.length > 0 ? v.profiles : v.profile !== void 0 ? [v.profile] : []).length < 1) ctx.addIssue({
|
|
24646
|
+
code: ZodIssueCode.custom,
|
|
24647
|
+
message: "pass profiles[] (min 1) or legacy profile",
|
|
24648
|
+
path: ["profiles"]
|
|
24649
|
+
});
|
|
24516
24650
|
}), ExportRecordSchema, {
|
|
24517
24651
|
kind: "mutation",
|
|
24518
24652
|
auth: "protected"
|
|
@@ -29112,6 +29246,12 @@ Object.freeze({
|
|
|
29112
29246
|
addonId: null,
|
|
29113
29247
|
access: "create"
|
|
29114
29248
|
},
|
|
29249
|
+
"pipelineAnalytics.reconcileFromDisk": {
|
|
29250
|
+
capName: "pipeline-analytics",
|
|
29251
|
+
capScope: "device",
|
|
29252
|
+
addonId: null,
|
|
29253
|
+
access: "create"
|
|
29254
|
+
},
|
|
29115
29255
|
"pipelineAnalytics.refreshStorageLocationsForMigration": {
|
|
29116
29256
|
capName: "pipeline-analytics",
|
|
29117
29257
|
capScope: "device",
|
|
@@ -29514,6 +29654,12 @@ Object.freeze({
|
|
|
29514
29654
|
addonId: null,
|
|
29515
29655
|
access: "view"
|
|
29516
29656
|
},
|
|
29657
|
+
"pipelineOrchestrator.getReconcileFromDiskStatus": {
|
|
29658
|
+
capName: "pipeline-orchestrator",
|
|
29659
|
+
capScope: "system",
|
|
29660
|
+
addonId: null,
|
|
29661
|
+
access: "view"
|
|
29662
|
+
},
|
|
29517
29663
|
"pipelineOrchestrator.listAgentSettings": {
|
|
29518
29664
|
capName: "pipeline-orchestrator",
|
|
29519
29665
|
capScope: "system",
|
|
@@ -29538,6 +29684,12 @@ Object.freeze({
|
|
|
29538
29684
|
addonId: null,
|
|
29539
29685
|
access: "create"
|
|
29540
29686
|
},
|
|
29687
|
+
"pipelineOrchestrator.reconcileFromDisk": {
|
|
29688
|
+
capName: "pipeline-orchestrator",
|
|
29689
|
+
capScope: "system",
|
|
29690
|
+
addonId: null,
|
|
29691
|
+
access: "create"
|
|
29692
|
+
},
|
|
29541
29693
|
"pipelineOrchestrator.removeAgentSettings": {
|
|
29542
29694
|
capName: "pipeline-orchestrator",
|
|
29543
29695
|
capScope: "system",
|
|
@@ -32529,6 +32681,11 @@ Object.freeze({
|
|
|
32529
32681
|
form: "single",
|
|
32530
32682
|
optional: true
|
|
32531
32683
|
}],
|
|
32684
|
+
"pipelineAnalytics.reconcileFromDisk": [{
|
|
32685
|
+
name: "deviceId",
|
|
32686
|
+
form: "single",
|
|
32687
|
+
optional: false
|
|
32688
|
+
}],
|
|
32532
32689
|
"pipelineAnalytics.restageRetrainTrack": [{
|
|
32533
32690
|
name: "deviceId",
|
|
32534
32691
|
form: "single",
|
|
@@ -33594,6 +33751,8 @@ DEFAULT_NATIVE_LEASE_SETTINGS.budgetMb;
|
|
|
33594
33751
|
DEFAULT_NATIVE_LEASE_SETTINGS.activityMs;
|
|
33595
33752
|
DEFAULT_NATIVE_LEASE_SETTINGS.tileBudgetMb;
|
|
33596
33753
|
DEFAULT_NATIVE_LEASE_SETTINGS.admission;
|
|
33754
|
+
var MB = 1024 * 1024;
|
|
33755
|
+
1024 * MB, 3072 * MB;
|
|
33597
33756
|
//#endregion
|
|
33598
33757
|
//#region src/shared.ts
|
|
33599
33758
|
/**
|
package/dist/webdav.addon.js
CHANGED
|
@@ -2,7 +2,7 @@ Object.defineProperties(exports, {
|
|
|
2
2
|
__esModule: { value: true },
|
|
3
3
|
[Symbol.toStringTag]: { value: "Module" }
|
|
4
4
|
});
|
|
5
|
-
const require_shared = require("./shared-
|
|
5
|
+
const require_shared = require("./shared-CrotCkhF.js");
|
|
6
6
|
let node_stream = require("node:stream");
|
|
7
7
|
let webdav = require("webdav");
|
|
8
8
|
//#region src/providers/webdav/webdav-config-schema.ts
|
package/dist/webdav.addon.mjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { a as safeJoinRemotePath, c as BaseAddon, i as rearmIdleAbort, o as scheduleIdleAbort, r as getRequiredBasePath, s as storageProviderCapability, t as createSessionId } from "./shared-
|
|
1
|
+
import { a as safeJoinRemotePath, c as BaseAddon, i as rearmIdleAbort, o as scheduleIdleAbort, r as getRequiredBasePath, s as storageProviderCapability, t as createSessionId } from "./shared-Toqenw3n.mjs";
|
|
2
2
|
import { PassThrough } from "node:stream";
|
|
3
3
|
import { AuthType, createClient } from "webdav";
|
|
4
4
|
//#region src/providers/webdav/webdav-config-schema.ts
|
package/package.json
CHANGED