@camstack/addon-remote-storage 1.2.18 → 1.2.20
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-Cud38F0U.mjs → shared-C-bqmSqc.mjs} +186 -28
- package/dist/{shared-C48hU09g.js → shared-CGc-WGwO.js} +186 -28
- 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-CGc-WGwO.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-C-bqmSqc.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-CGc-WGwO.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-C-bqmSqc.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
|
|
@@ -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
|
|
@@ -19108,7 +19180,14 @@ targets: array(object({
|
|
|
19108
19180
|
"sleeping",
|
|
19109
19181
|
"unreachable",
|
|
19110
19182
|
"waking"
|
|
19111
|
-
]).nullable()
|
|
19183
|
+
]).nullable(),
|
|
19184
|
+
/** A battery camera (whatever its current state). An AWAKE battery
|
|
19185
|
+
* camera is deliberately NOT recaptured on the poll cadence — every
|
|
19186
|
+
* capture is a camera hit that would keep it out of sleep — so its
|
|
19187
|
+
* cached frame legitimately ages past the currency ceiling while
|
|
19188
|
+
* nothing is streaming. A surface must keep painting it (a fresh
|
|
19189
|
+
* frame is captured at each wake), not blank to "unavailable". */
|
|
19190
|
+
battery: boolean()
|
|
19112
19191
|
})));
|
|
19113
19192
|
/**
|
|
19114
19193
|
* `sso-bridge` — internal hub-only cap that lets SSO-style auth
|
|
@@ -19814,20 +19893,6 @@ var VectorStatsResultSchema = object({
|
|
|
19814
19893
|
exact: boolean()
|
|
19815
19894
|
});
|
|
19816
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);
|
|
19817
|
-
/**
|
|
19818
|
-
* `videoclips` — the unified, navigable-clip surface for a camera.
|
|
19819
|
-
*
|
|
19820
|
-
* A device-scoped WRAPPER cap (like `pipeline-analytics`): exactly one active
|
|
19821
|
-
* provider per device, substitutable. The DEFAULT provider (registered by
|
|
19822
|
-
* `addon-post-analysis`, `defaultActive: true`) composes the analytics event
|
|
19823
|
-
* log (markers + thumbnails) with the recorder's `getPlaybackManifest` — a clip
|
|
19824
|
-
* is a time-WINDOW over existing footage, never a separate file. A camera that
|
|
19825
|
-
* exposes NATIVE onboard clips (Reolink/Hikvision NVR) can later substitute the
|
|
19826
|
-
* wrapper provider for its device and serve its own clip catalog + URLs.
|
|
19827
|
-
*
|
|
19828
|
-
* A `Clip` is purely time-based (subtree-blind): playback resolves segments by
|
|
19829
|
-
* temporal overlap, so the API never decides `continuous` vs `events`.
|
|
19830
|
-
*/
|
|
19831
19896
|
var ClipSchema = object({
|
|
19832
19897
|
/** Opaque, provider-namespaced id. The default provider encodes the time
|
|
19833
19898
|
* window so `getClipPlayback` is self-contained (no event re-query). */
|
|
@@ -19844,8 +19909,57 @@ var ClipSchema = object({
|
|
|
19844
19909
|
startMs: number(),
|
|
19845
19910
|
endMs: number()
|
|
19846
19911
|
}),
|
|
19847
|
-
/**
|
|
19848
|
-
thumbnail
|
|
19912
|
+
/**
|
|
19913
|
+
* Lazy thumbnail URL, never inlined.
|
|
19914
|
+
*
|
|
19915
|
+
* Recording-derived clips (events-mode keep-window, and the prepared
|
|
19916
|
+
* continuous event+fragment visit) MUST use the snapshot of the **main
|
|
19917
|
+
* event of the interval** — `getEventMedia({ eventId, kind: 'snapshot' })`
|
|
19918
|
+
* of the event that owns `kind` (object > motion > audio). Do not extract
|
|
19919
|
+
* a keyframe from the recorded segments. Other providers (onboard, HKSV)
|
|
19920
|
+
* mint their own stills.
|
|
19921
|
+
*
|
|
19922
|
+
* **VOUCHED, never fabricated.** A provider emits this only for an event it
|
|
19923
|
+
* has CONFIRMED owns at least one media row (its own, or its owning track's).
|
|
19924
|
+
* Absent is meaningful — "this visit has no event still" — never "we did not
|
|
19925
|
+
* look". Stamping it from a URL template made 35% of one camera's clips point
|
|
19926
|
+
* at a 404 (device 3836, 2026-08-17: 64 of 179 clips dead, 63 of them motion).
|
|
19927
|
+
* A read that FAILS drops the claim; it never invents it.
|
|
19928
|
+
*/
|
|
19929
|
+
thumbnail: string().optional(),
|
|
19930
|
+
/**
|
|
19931
|
+
* An instant INSIDE this visit's footage, hole-safe, where a recorded still
|
|
19932
|
+
* can be decoded. Present whenever the visit came from recorded availability;
|
|
19933
|
+
* absent on a per-event padded window (there is no footage to promise).
|
|
19934
|
+
*
|
|
19935
|
+
* This is not a thumbnail and not a second byte path: it is the argument to
|
|
19936
|
+
* the recorder's existing still route. The surface — never the provider —
|
|
19937
|
+
* decides whether to use it. It is the midpoint of the visit's LONGEST
|
|
19938
|
+
* contiguous range, not of the visit: a visit spans its holes by
|
|
19939
|
+
* construction, so a naive midpoint lands in dead air.
|
|
19940
|
+
*/
|
|
19941
|
+
stillAtMs: number().optional(),
|
|
19942
|
+
/**
|
|
19943
|
+
* Analytics event ids that overlap this visit — a BOUNDED sample, newest
|
|
19944
|
+
* first within kind (object → motion → audio), capped at
|
|
19945
|
+
* {@link MAX_CLIP_EVENT_IDS}. Empty on footage-only clips.
|
|
19946
|
+
*
|
|
19947
|
+
* Bounded because it is not a payload the surface pages through: one visit on
|
|
19948
|
+
* device 615 carried 2 345 ids, and `eventIds` was 99% of a 153 KB
|
|
19949
|
+
* camera-day. Read {@link eventCount} for the true total.
|
|
19950
|
+
*/
|
|
19951
|
+
eventIds: array(string()).optional(),
|
|
19952
|
+
/** How many analytics events actually overlap this visit. Differs from
|
|
19953
|
+
* `eventIds.length` exactly when the sample was capped — so a truncated
|
|
19954
|
+
* list is never mistaken for a quiet visit. */
|
|
19955
|
+
eventCount: number().int().nonnegative().optional(),
|
|
19956
|
+
/** Intra-visit footage holes (GOP rolls, discarded segments) still shorter
|
|
19957
|
+
* than `VISIT_MERGE_GAP_MS`. Playback concatenates around them; the timeline
|
|
19958
|
+
* bar keeps showing them via `recording.getAvailability`. */
|
|
19959
|
+
holes: array(object({
|
|
19960
|
+
startMs: number(),
|
|
19961
|
+
endMs: number()
|
|
19962
|
+
})).optional()
|
|
19849
19963
|
});
|
|
19850
19964
|
var ClipPlaybackSchema = object({
|
|
19851
19965
|
/** HLS master URL through the hub data-plane (Range + token in path). */
|
|
@@ -20309,7 +20423,14 @@ var SearchResultSchema = object({
|
|
|
20309
20423
|
});
|
|
20310
20424
|
var AutoUpdateSettingsSchema = object({
|
|
20311
20425
|
channel: ChannelSchema,
|
|
20312
|
-
intervalSeconds: number()
|
|
20426
|
+
intervalSeconds: number(),
|
|
20427
|
+
/**
|
|
20428
|
+
* Cadence of the "an update exists" POLLER, in seconds. Independent of
|
|
20429
|
+
* `channel`: the poller runs while auto-apply is `off`, because being told
|
|
20430
|
+
* about a publish and installing it are different decisions. Clamped
|
|
20431
|
+
* server-side to 900 s … 604800 s; defaults to 21600 s (6 h).
|
|
20432
|
+
*/
|
|
20433
|
+
updateCheckIntervalSeconds: number()
|
|
20313
20434
|
});
|
|
20314
20435
|
var AddonAutoUpdateSchema = ChannelWithInheritSchema;
|
|
20315
20436
|
var RestartAddonResultSchema = unknown();
|
|
@@ -20450,7 +20571,9 @@ method(_void(), array(AddonListItemSchema).readonly()), method(object({
|
|
|
20450
20571
|
auth: "admin"
|
|
20451
20572
|
}), method(_void(), AutoUpdateSettingsSchema, { auth: "admin" }), method(object({
|
|
20452
20573
|
channel: ChannelSchema,
|
|
20453
|
-
intervalSeconds: number().min(300).max(86400).optional()
|
|
20574
|
+
intervalSeconds: number().min(300).max(86400).optional(),
|
|
20575
|
+
/** Availability-poll cadence; see AutoUpdateSettingsSchema. */
|
|
20576
|
+
updateCheckIntervalSeconds: number().min(900).max(604800).optional()
|
|
20454
20577
|
}), unknown(), {
|
|
20455
20578
|
kind: "mutation",
|
|
20456
20579
|
auth: "admin"
|
|
@@ -24443,7 +24566,9 @@ var ExportOptionsSchema = object({
|
|
|
24443
24566
|
includeAudio: boolean(),
|
|
24444
24567
|
maxLifeMs: number().int().positive(),
|
|
24445
24568
|
deleteAfterDownload: boolean(),
|
|
24446
|
-
title: string().max(200).optional()
|
|
24569
|
+
title: string().max(200).optional(),
|
|
24570
|
+
/** Notification-output target ids to ping when this export becomes ready. */
|
|
24571
|
+
notifyTargetIds: array(string().min(1)).max(20).optional()
|
|
24447
24572
|
}).superRefine((v, ctx) => {
|
|
24448
24573
|
if (v.speed !== void 0 && v.timelapse !== void 0) ctx.addIssue({
|
|
24449
24574
|
code: ZodIssueCode.custom,
|
|
@@ -24502,10 +24627,18 @@ var ExportBytesSchema = object({
|
|
|
24502
24627
|
});
|
|
24503
24628
|
method(object({
|
|
24504
24629
|
deviceId: number(),
|
|
24505
|
-
|
|
24630
|
+
/** @deprecated Prefer `profiles`. Kept so timelapse/notifiers keep working. */
|
|
24631
|
+
profile: string().optional(),
|
|
24632
|
+
profiles: array(string()).min(1).optional(),
|
|
24506
24633
|
fromMs: number(),
|
|
24507
24634
|
toMs: number(),
|
|
24508
24635
|
options: ExportOptionsSchema
|
|
24636
|
+
}).superRefine((v, ctx) => {
|
|
24637
|
+
if ((v.profiles !== void 0 && v.profiles.length > 0 ? v.profiles : v.profile !== void 0 ? [v.profile] : []).length < 1) ctx.addIssue({
|
|
24638
|
+
code: ZodIssueCode.custom,
|
|
24639
|
+
message: "pass profiles[] (min 1) or legacy profile",
|
|
24640
|
+
path: ["profiles"]
|
|
24641
|
+
});
|
|
24509
24642
|
}), ExportRecordSchema, {
|
|
24510
24643
|
kind: "mutation",
|
|
24511
24644
|
auth: "protected"
|
|
@@ -29105,6 +29238,12 @@ Object.freeze({
|
|
|
29105
29238
|
addonId: null,
|
|
29106
29239
|
access: "create"
|
|
29107
29240
|
},
|
|
29241
|
+
"pipelineAnalytics.reconcileFromDisk": {
|
|
29242
|
+
capName: "pipeline-analytics",
|
|
29243
|
+
capScope: "device",
|
|
29244
|
+
addonId: null,
|
|
29245
|
+
access: "create"
|
|
29246
|
+
},
|
|
29108
29247
|
"pipelineAnalytics.refreshStorageLocationsForMigration": {
|
|
29109
29248
|
capName: "pipeline-analytics",
|
|
29110
29249
|
capScope: "device",
|
|
@@ -29507,6 +29646,12 @@ Object.freeze({
|
|
|
29507
29646
|
addonId: null,
|
|
29508
29647
|
access: "view"
|
|
29509
29648
|
},
|
|
29649
|
+
"pipelineOrchestrator.getReconcileFromDiskStatus": {
|
|
29650
|
+
capName: "pipeline-orchestrator",
|
|
29651
|
+
capScope: "system",
|
|
29652
|
+
addonId: null,
|
|
29653
|
+
access: "view"
|
|
29654
|
+
},
|
|
29510
29655
|
"pipelineOrchestrator.listAgentSettings": {
|
|
29511
29656
|
capName: "pipeline-orchestrator",
|
|
29512
29657
|
capScope: "system",
|
|
@@ -29531,6 +29676,12 @@ Object.freeze({
|
|
|
29531
29676
|
addonId: null,
|
|
29532
29677
|
access: "create"
|
|
29533
29678
|
},
|
|
29679
|
+
"pipelineOrchestrator.reconcileFromDisk": {
|
|
29680
|
+
capName: "pipeline-orchestrator",
|
|
29681
|
+
capScope: "system",
|
|
29682
|
+
addonId: null,
|
|
29683
|
+
access: "create"
|
|
29684
|
+
},
|
|
29534
29685
|
"pipelineOrchestrator.removeAgentSettings": {
|
|
29535
29686
|
capName: "pipeline-orchestrator",
|
|
29536
29687
|
capScope: "system",
|
|
@@ -32522,6 +32673,11 @@ Object.freeze({
|
|
|
32522
32673
|
form: "single",
|
|
32523
32674
|
optional: true
|
|
32524
32675
|
}],
|
|
32676
|
+
"pipelineAnalytics.reconcileFromDisk": [{
|
|
32677
|
+
name: "deviceId",
|
|
32678
|
+
form: "single",
|
|
32679
|
+
optional: false
|
|
32680
|
+
}],
|
|
32525
32681
|
"pipelineAnalytics.restageRetrainTrack": [{
|
|
32526
32682
|
name: "deviceId",
|
|
32527
32683
|
form: "single",
|
|
@@ -33587,6 +33743,8 @@ DEFAULT_NATIVE_LEASE_SETTINGS.budgetMb;
|
|
|
33587
33743
|
DEFAULT_NATIVE_LEASE_SETTINGS.activityMs;
|
|
33588
33744
|
DEFAULT_NATIVE_LEASE_SETTINGS.tileBudgetMb;
|
|
33589
33745
|
DEFAULT_NATIVE_LEASE_SETTINGS.admission;
|
|
33746
|
+
var MB = 1024 * 1024;
|
|
33747
|
+
1024 * MB, 3072 * MB;
|
|
33590
33748
|
//#endregion
|
|
33591
33749
|
//#region src/shared.ts
|
|
33592
33750
|
/**
|
|
@@ -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
|
|
@@ -19131,7 +19203,14 @@ targets: array(object({
|
|
|
19131
19203
|
"sleeping",
|
|
19132
19204
|
"unreachable",
|
|
19133
19205
|
"waking"
|
|
19134
|
-
]).nullable()
|
|
19206
|
+
]).nullable(),
|
|
19207
|
+
/** A battery camera (whatever its current state). An AWAKE battery
|
|
19208
|
+
* camera is deliberately NOT recaptured on the poll cadence — every
|
|
19209
|
+
* capture is a camera hit that would keep it out of sleep — so its
|
|
19210
|
+
* cached frame legitimately ages past the currency ceiling while
|
|
19211
|
+
* nothing is streaming. A surface must keep painting it (a fresh
|
|
19212
|
+
* frame is captured at each wake), not blank to "unavailable". */
|
|
19213
|
+
battery: boolean()
|
|
19135
19214
|
})));
|
|
19136
19215
|
/**
|
|
19137
19216
|
* `sso-bridge` — internal hub-only cap that lets SSO-style auth
|
|
@@ -19837,20 +19916,6 @@ var VectorStatsResultSchema = object({
|
|
|
19837
19916
|
exact: boolean()
|
|
19838
19917
|
});
|
|
19839
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);
|
|
19840
|
-
/**
|
|
19841
|
-
* `videoclips` — the unified, navigable-clip surface for a camera.
|
|
19842
|
-
*
|
|
19843
|
-
* A device-scoped WRAPPER cap (like `pipeline-analytics`): exactly one active
|
|
19844
|
-
* provider per device, substitutable. The DEFAULT provider (registered by
|
|
19845
|
-
* `addon-post-analysis`, `defaultActive: true`) composes the analytics event
|
|
19846
|
-
* log (markers + thumbnails) with the recorder's `getPlaybackManifest` — a clip
|
|
19847
|
-
* is a time-WINDOW over existing footage, never a separate file. A camera that
|
|
19848
|
-
* exposes NATIVE onboard clips (Reolink/Hikvision NVR) can later substitute the
|
|
19849
|
-
* wrapper provider for its device and serve its own clip catalog + URLs.
|
|
19850
|
-
*
|
|
19851
|
-
* A `Clip` is purely time-based (subtree-blind): playback resolves segments by
|
|
19852
|
-
* temporal overlap, so the API never decides `continuous` vs `events`.
|
|
19853
|
-
*/
|
|
19854
19919
|
var ClipSchema = object({
|
|
19855
19920
|
/** Opaque, provider-namespaced id. The default provider encodes the time
|
|
19856
19921
|
* window so `getClipPlayback` is self-contained (no event re-query). */
|
|
@@ -19867,8 +19932,57 @@ var ClipSchema = object({
|
|
|
19867
19932
|
startMs: number(),
|
|
19868
19933
|
endMs: number()
|
|
19869
19934
|
}),
|
|
19870
|
-
/**
|
|
19871
|
-
thumbnail
|
|
19935
|
+
/**
|
|
19936
|
+
* Lazy thumbnail URL, never inlined.
|
|
19937
|
+
*
|
|
19938
|
+
* Recording-derived clips (events-mode keep-window, and the prepared
|
|
19939
|
+
* continuous event+fragment visit) MUST use the snapshot of the **main
|
|
19940
|
+
* event of the interval** — `getEventMedia({ eventId, kind: 'snapshot' })`
|
|
19941
|
+
* of the event that owns `kind` (object > motion > audio). Do not extract
|
|
19942
|
+
* a keyframe from the recorded segments. Other providers (onboard, HKSV)
|
|
19943
|
+
* mint their own stills.
|
|
19944
|
+
*
|
|
19945
|
+
* **VOUCHED, never fabricated.** A provider emits this only for an event it
|
|
19946
|
+
* has CONFIRMED owns at least one media row (its own, or its owning track's).
|
|
19947
|
+
* Absent is meaningful — "this visit has no event still" — never "we did not
|
|
19948
|
+
* look". Stamping it from a URL template made 35% of one camera's clips point
|
|
19949
|
+
* at a 404 (device 3836, 2026-08-17: 64 of 179 clips dead, 63 of them motion).
|
|
19950
|
+
* A read that FAILS drops the claim; it never invents it.
|
|
19951
|
+
*/
|
|
19952
|
+
thumbnail: string().optional(),
|
|
19953
|
+
/**
|
|
19954
|
+
* An instant INSIDE this visit's footage, hole-safe, where a recorded still
|
|
19955
|
+
* can be decoded. Present whenever the visit came from recorded availability;
|
|
19956
|
+
* absent on a per-event padded window (there is no footage to promise).
|
|
19957
|
+
*
|
|
19958
|
+
* This is not a thumbnail and not a second byte path: it is the argument to
|
|
19959
|
+
* the recorder's existing still route. The surface — never the provider —
|
|
19960
|
+
* decides whether to use it. It is the midpoint of the visit's LONGEST
|
|
19961
|
+
* contiguous range, not of the visit: a visit spans its holes by
|
|
19962
|
+
* construction, so a naive midpoint lands in dead air.
|
|
19963
|
+
*/
|
|
19964
|
+
stillAtMs: number().optional(),
|
|
19965
|
+
/**
|
|
19966
|
+
* Analytics event ids that overlap this visit — a BOUNDED sample, newest
|
|
19967
|
+
* first within kind (object → motion → audio), capped at
|
|
19968
|
+
* {@link MAX_CLIP_EVENT_IDS}. Empty on footage-only clips.
|
|
19969
|
+
*
|
|
19970
|
+
* Bounded because it is not a payload the surface pages through: one visit on
|
|
19971
|
+
* device 615 carried 2 345 ids, and `eventIds` was 99% of a 153 KB
|
|
19972
|
+
* camera-day. Read {@link eventCount} for the true total.
|
|
19973
|
+
*/
|
|
19974
|
+
eventIds: array(string()).optional(),
|
|
19975
|
+
/** How many analytics events actually overlap this visit. Differs from
|
|
19976
|
+
* `eventIds.length` exactly when the sample was capped — so a truncated
|
|
19977
|
+
* list is never mistaken for a quiet visit. */
|
|
19978
|
+
eventCount: number().int().nonnegative().optional(),
|
|
19979
|
+
/** Intra-visit footage holes (GOP rolls, discarded segments) still shorter
|
|
19980
|
+
* than `VISIT_MERGE_GAP_MS`. Playback concatenates around them; the timeline
|
|
19981
|
+
* bar keeps showing them via `recording.getAvailability`. */
|
|
19982
|
+
holes: array(object({
|
|
19983
|
+
startMs: number(),
|
|
19984
|
+
endMs: number()
|
|
19985
|
+
})).optional()
|
|
19872
19986
|
});
|
|
19873
19987
|
var ClipPlaybackSchema = object({
|
|
19874
19988
|
/** HLS master URL through the hub data-plane (Range + token in path). */
|
|
@@ -20332,7 +20446,14 @@ var SearchResultSchema = object({
|
|
|
20332
20446
|
});
|
|
20333
20447
|
var AutoUpdateSettingsSchema = object({
|
|
20334
20448
|
channel: ChannelSchema,
|
|
20335
|
-
intervalSeconds: number()
|
|
20449
|
+
intervalSeconds: number(),
|
|
20450
|
+
/**
|
|
20451
|
+
* Cadence of the "an update exists" POLLER, in seconds. Independent of
|
|
20452
|
+
* `channel`: the poller runs while auto-apply is `off`, because being told
|
|
20453
|
+
* about a publish and installing it are different decisions. Clamped
|
|
20454
|
+
* server-side to 900 s … 604800 s; defaults to 21600 s (6 h).
|
|
20455
|
+
*/
|
|
20456
|
+
updateCheckIntervalSeconds: number()
|
|
20336
20457
|
});
|
|
20337
20458
|
var AddonAutoUpdateSchema = ChannelWithInheritSchema;
|
|
20338
20459
|
var RestartAddonResultSchema = unknown();
|
|
@@ -20473,7 +20594,9 @@ method(_void(), array(AddonListItemSchema).readonly()), method(object({
|
|
|
20473
20594
|
auth: "admin"
|
|
20474
20595
|
}), method(_void(), AutoUpdateSettingsSchema, { auth: "admin" }), method(object({
|
|
20475
20596
|
channel: ChannelSchema,
|
|
20476
|
-
intervalSeconds: number().min(300).max(86400).optional()
|
|
20597
|
+
intervalSeconds: number().min(300).max(86400).optional(),
|
|
20598
|
+
/** Availability-poll cadence; see AutoUpdateSettingsSchema. */
|
|
20599
|
+
updateCheckIntervalSeconds: number().min(900).max(604800).optional()
|
|
20477
20600
|
}), unknown(), {
|
|
20478
20601
|
kind: "mutation",
|
|
20479
20602
|
auth: "admin"
|
|
@@ -24466,7 +24589,9 @@ var ExportOptionsSchema = object({
|
|
|
24466
24589
|
includeAudio: boolean(),
|
|
24467
24590
|
maxLifeMs: number().int().positive(),
|
|
24468
24591
|
deleteAfterDownload: boolean(),
|
|
24469
|
-
title: string().max(200).optional()
|
|
24592
|
+
title: string().max(200).optional(),
|
|
24593
|
+
/** Notification-output target ids to ping when this export becomes ready. */
|
|
24594
|
+
notifyTargetIds: array(string().min(1)).max(20).optional()
|
|
24470
24595
|
}).superRefine((v, ctx) => {
|
|
24471
24596
|
if (v.speed !== void 0 && v.timelapse !== void 0) ctx.addIssue({
|
|
24472
24597
|
code: ZodIssueCode.custom,
|
|
@@ -24525,10 +24650,18 @@ var ExportBytesSchema = object({
|
|
|
24525
24650
|
});
|
|
24526
24651
|
method(object({
|
|
24527
24652
|
deviceId: number(),
|
|
24528
|
-
|
|
24653
|
+
/** @deprecated Prefer `profiles`. Kept so timelapse/notifiers keep working. */
|
|
24654
|
+
profile: string().optional(),
|
|
24655
|
+
profiles: array(string()).min(1).optional(),
|
|
24529
24656
|
fromMs: number(),
|
|
24530
24657
|
toMs: number(),
|
|
24531
24658
|
options: ExportOptionsSchema
|
|
24659
|
+
}).superRefine((v, ctx) => {
|
|
24660
|
+
if ((v.profiles !== void 0 && v.profiles.length > 0 ? v.profiles : v.profile !== void 0 ? [v.profile] : []).length < 1) ctx.addIssue({
|
|
24661
|
+
code: ZodIssueCode.custom,
|
|
24662
|
+
message: "pass profiles[] (min 1) or legacy profile",
|
|
24663
|
+
path: ["profiles"]
|
|
24664
|
+
});
|
|
24532
24665
|
}), ExportRecordSchema, {
|
|
24533
24666
|
kind: "mutation",
|
|
24534
24667
|
auth: "protected"
|
|
@@ -29128,6 +29261,12 @@ Object.freeze({
|
|
|
29128
29261
|
addonId: null,
|
|
29129
29262
|
access: "create"
|
|
29130
29263
|
},
|
|
29264
|
+
"pipelineAnalytics.reconcileFromDisk": {
|
|
29265
|
+
capName: "pipeline-analytics",
|
|
29266
|
+
capScope: "device",
|
|
29267
|
+
addonId: null,
|
|
29268
|
+
access: "create"
|
|
29269
|
+
},
|
|
29131
29270
|
"pipelineAnalytics.refreshStorageLocationsForMigration": {
|
|
29132
29271
|
capName: "pipeline-analytics",
|
|
29133
29272
|
capScope: "device",
|
|
@@ -29530,6 +29669,12 @@ Object.freeze({
|
|
|
29530
29669
|
addonId: null,
|
|
29531
29670
|
access: "view"
|
|
29532
29671
|
},
|
|
29672
|
+
"pipelineOrchestrator.getReconcileFromDiskStatus": {
|
|
29673
|
+
capName: "pipeline-orchestrator",
|
|
29674
|
+
capScope: "system",
|
|
29675
|
+
addonId: null,
|
|
29676
|
+
access: "view"
|
|
29677
|
+
},
|
|
29533
29678
|
"pipelineOrchestrator.listAgentSettings": {
|
|
29534
29679
|
capName: "pipeline-orchestrator",
|
|
29535
29680
|
capScope: "system",
|
|
@@ -29554,6 +29699,12 @@ Object.freeze({
|
|
|
29554
29699
|
addonId: null,
|
|
29555
29700
|
access: "create"
|
|
29556
29701
|
},
|
|
29702
|
+
"pipelineOrchestrator.reconcileFromDisk": {
|
|
29703
|
+
capName: "pipeline-orchestrator",
|
|
29704
|
+
capScope: "system",
|
|
29705
|
+
addonId: null,
|
|
29706
|
+
access: "create"
|
|
29707
|
+
},
|
|
29557
29708
|
"pipelineOrchestrator.removeAgentSettings": {
|
|
29558
29709
|
capName: "pipeline-orchestrator",
|
|
29559
29710
|
capScope: "system",
|
|
@@ -32545,6 +32696,11 @@ Object.freeze({
|
|
|
32545
32696
|
form: "single",
|
|
32546
32697
|
optional: true
|
|
32547
32698
|
}],
|
|
32699
|
+
"pipelineAnalytics.reconcileFromDisk": [{
|
|
32700
|
+
name: "deviceId",
|
|
32701
|
+
form: "single",
|
|
32702
|
+
optional: false
|
|
32703
|
+
}],
|
|
32548
32704
|
"pipelineAnalytics.restageRetrainTrack": [{
|
|
32549
32705
|
name: "deviceId",
|
|
32550
32706
|
form: "single",
|
|
@@ -33610,6 +33766,8 @@ DEFAULT_NATIVE_LEASE_SETTINGS.budgetMb;
|
|
|
33610
33766
|
DEFAULT_NATIVE_LEASE_SETTINGS.activityMs;
|
|
33611
33767
|
DEFAULT_NATIVE_LEASE_SETTINGS.tileBudgetMb;
|
|
33612
33768
|
DEFAULT_NATIVE_LEASE_SETTINGS.admission;
|
|
33769
|
+
var MB = 1024 * 1024;
|
|
33770
|
+
1024 * MB, 3072 * MB;
|
|
33613
33771
|
//#endregion
|
|
33614
33772
|
//#region src/shared.ts
|
|
33615
33773
|
/**
|
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-CGc-WGwO.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-C-bqmSqc.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