@camstack/addon-decoder-ffmpeg 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/index.js +186 -27
- package/dist/index.mjs +186 -27
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -4,7 +4,7 @@ Object.defineProperties(exports, {
|
|
|
4
4
|
});
|
|
5
5
|
let node_crypto = require("node:crypto");
|
|
6
6
|
let node_child_process = require("node:child_process");
|
|
7
|
-
//#region ../types/dist/event-category-
|
|
7
|
+
//#region ../types/dist/event-category-XfKNtfCc.mjs
|
|
8
8
|
var EventCategory = /* @__PURE__ */ function(EventCategory) {
|
|
9
9
|
EventCategory["SystemBoot"] = "system.boot";
|
|
10
10
|
EventCategory["SystemAddonsReady"] = "system.addons-ready";
|
|
@@ -21,9 +21,10 @@ var EventCategory = /* @__PURE__ */ function(EventCategory) {
|
|
|
21
21
|
EventCategory["SystemRestartCompleted"] = "system.restart-completed";
|
|
22
22
|
/**
|
|
23
23
|
* A newer addon or server-root package version was found by the
|
|
24
|
-
* authoritative registry check. Emitted once
|
|
25
|
-
* `(
|
|
26
|
-
*
|
|
24
|
+
* authoritative registry check. Emitted once when any observed
|
|
25
|
+
* `latestVersion` changes (or a package/node first appears behind);
|
|
26
|
+
* the payload carries the full currently-available list. Repeated
|
|
27
|
+
* polling of the same latests is silent.
|
|
27
28
|
*/
|
|
28
29
|
EventCategory["UpdateAvailable"] = "update.available";
|
|
29
30
|
/**
|
|
@@ -42,6 +43,22 @@ var EventCategory = /* @__PURE__ */ function(EventCategory) {
|
|
|
42
43
|
EventCategory["AddonInstalled"] = "addon.installed";
|
|
43
44
|
EventCategory["AddonUninstalled"] = "addon.uninstalled";
|
|
44
45
|
EventCategory["AddonCrashed"] = "addon.crashed";
|
|
46
|
+
/**
|
|
47
|
+
* A RUNNER the D6 crash circuit-breaker gave up on — terminal.
|
|
48
|
+
*
|
|
49
|
+
* `AddonCrashed` is the routine, self-healing fact ("it crashed; it is being
|
|
50
|
+
* respawned"); this is the one that never resolves itself. Emitted exactly
|
|
51
|
+
* once per trip, by `process-service.ts`, carrying the node, the runner, the
|
|
52
|
+
* addons it hosted and the crash count that tripped the breaker.
|
|
53
|
+
*
|
|
54
|
+
* It exists because a runner marked terminally `failed` used to be SILENT:
|
|
55
|
+
* on 2026-08-18 the `recorder` runner died of three unhandled ffmpeg spawn
|
|
56
|
+
* errors, the breaker stopped respawning it (correctly), `/health` kept
|
|
57
|
+
* returning 200, and fleet-wide recording was gone for 3h15 before the
|
|
58
|
+
* operator's phone told him. The Notification Center's system-event intake
|
|
59
|
+
* consumes this category and maps it to the `addon-crash-loop` kind.
|
|
60
|
+
*/
|
|
61
|
+
EventCategory["AddonRunnerFailed"] = "addon.runner-failed";
|
|
45
62
|
EventCategory["AddonError"] = "addon.error";
|
|
46
63
|
EventCategory["AddonPageReady"] = "addon.page-ready";
|
|
47
64
|
EventCategory["AddonWidgetReady"] = "addon.widget-ready";
|
|
@@ -7549,6 +7566,10 @@ var RecordingBandSchema = object({
|
|
|
7549
7566
|
preBufferSec: number().min(0).optional(),
|
|
7550
7567
|
postBufferSec: number().min(0).optional()
|
|
7551
7568
|
});
|
|
7569
|
+
({
|
|
7570
|
+
preBufferSec: 10,
|
|
7571
|
+
postBufferSec: 30
|
|
7572
|
+
}).postBufferSec * 1e3;
|
|
7552
7573
|
/**
|
|
7553
7574
|
* Per-device retention overrides. Every field is optional; an unset or `0`
|
|
7554
7575
|
* value inherits the node-wide recorder default. Only footage-lifetime limits
|
|
@@ -7596,6 +7617,12 @@ var RecordingConfigSchema = object({
|
|
|
7596
7617
|
/** DERIVED summary of `bands`, stamped by the recorder on every save.
|
|
7597
7618
|
* Authoring it has no effect — see {@link RecordingStorageModeSchema}. */
|
|
7598
7619
|
mode: RecordingStorageModeSchema.optional(),
|
|
7620
|
+
/**
|
|
7621
|
+
* Which assigned broker slots to record. Absent / empty = {@link
|
|
7622
|
+
* DEFAULT_RECORDING_PROFILES} (`high`+`low`) intersected with the
|
|
7623
|
+
* camera's currently assigned slots — never `mid` unless the operator
|
|
7624
|
+
* picks it, and never a slot the broker has not assigned.
|
|
7625
|
+
*/
|
|
7599
7626
|
profiles: array(CamProfileSchema).optional(),
|
|
7600
7627
|
segmentSeconds: number().int().positive().optional(),
|
|
7601
7628
|
/**
|
|
@@ -7676,7 +7703,11 @@ var RelocateFootageInputSchema = object({
|
|
|
7676
7703
|
profiles: array(string()).optional(),
|
|
7677
7704
|
/** Copy throttle in MB/s (default 40) — the drain is a background chore,
|
|
7678
7705
|
* never allowed to starve live writers. */
|
|
7679
|
-
throttleMbps: number().min(1).max(1e3).optional()
|
|
7706
|
+
throttleMbps: number().min(1).max(1e3).optional(),
|
|
7707
|
+
/** Move only segments whose startMs is >= this. Absent = the whole source
|
|
7708
|
+
* pile. Used when a full drain is too expensive and the operator only
|
|
7709
|
+
* wants the recent window on the new disk. */
|
|
7710
|
+
sinceMs: number().int().optional()
|
|
7680
7711
|
});
|
|
7681
7712
|
/** Internal, lease-scoped participant operation. It is intentionally separate
|
|
7682
7713
|
* from persistent recording settings: a migration never changes
|
|
@@ -14369,6 +14400,7 @@ var NcSystemEventKindSchema = _enum([
|
|
|
14369
14400
|
"node-offline",
|
|
14370
14401
|
"node-inference-unavailable",
|
|
14371
14402
|
"detection-blind",
|
|
14403
|
+
"addon-crash-loop",
|
|
14372
14404
|
"addon-update-available",
|
|
14373
14405
|
"server-update-available",
|
|
14374
14406
|
"alarm-triggered",
|
|
@@ -14376,6 +14408,9 @@ var NcSystemEventKindSchema = _enum([
|
|
|
14376
14408
|
"alarm-disarmed",
|
|
14377
14409
|
"alarm-arming",
|
|
14378
14410
|
"alarm-arm-refused",
|
|
14411
|
+
"addon-updated",
|
|
14412
|
+
"server-updated",
|
|
14413
|
+
"export-completed",
|
|
14379
14414
|
"camera-online",
|
|
14380
14415
|
"camera-offline",
|
|
14381
14416
|
"camera-disabled",
|
|
@@ -16269,13 +16304,19 @@ var RetrainStatusSchema = _enum([
|
|
|
16269
16304
|
* "never marked" from "already trained" must read `retrainStatus`.
|
|
16270
16305
|
*
|
|
16271
16306
|
* `debug` does NOT pin; it is attention, not durability.
|
|
16307
|
+
*
|
|
16308
|
+
* `favourited` IS a BOOLEAN pin (durability bit), not a retrain lifecycle.
|
|
16309
|
+
* A favourited track is skipped by retention the same way `staging` is, but
|
|
16310
|
+
* it does not enter `none|staging|trained` and has no staging budget.
|
|
16272
16311
|
*/
|
|
16273
16312
|
var TrackFlagFields = {
|
|
16274
16313
|
/** Operator marked this track as training material — i.e. `retrainStatus` is
|
|
16275
16314
|
* `'staging'`. */
|
|
16276
16315
|
markForTrain: boolean().optional(),
|
|
16277
16316
|
/** Operator marked this track for diagnostic attention. */
|
|
16278
|
-
debug: boolean().optional()
|
|
16317
|
+
debug: boolean().optional(),
|
|
16318
|
+
/** Operator favourited this track. Pins it against pruning. */
|
|
16319
|
+
favourited: boolean().optional()
|
|
16279
16320
|
};
|
|
16280
16321
|
/**
|
|
16281
16322
|
* The lifecycle field itself, on the READ surfaces only (`Track`, `KeyEvent`).
|
|
@@ -16300,6 +16341,7 @@ var TrackFlagsSchema = object({
|
|
|
16300
16341
|
trackId: string(),
|
|
16301
16342
|
markForTrain: boolean(),
|
|
16302
16343
|
debug: boolean(),
|
|
16344
|
+
favourited: boolean(),
|
|
16303
16345
|
/** The lifecycle state the boolean was derived from. Required here (unlike on
|
|
16304
16346
|
* a track row) because this shape is only ever produced by the write body,
|
|
16305
16347
|
* which always knows it — and a surface that has just written needs to render
|
|
@@ -16932,6 +16974,12 @@ var TrackCascadeCountsSchema = object({
|
|
|
16932
16974
|
/** Per-track CLIP search vectors removed (best-effort). */
|
|
16933
16975
|
embeddings: number().int()
|
|
16934
16976
|
});
|
|
16977
|
+
/** Disk-wins reconcile: media rows whose blobs are gone, then empty tracks. */
|
|
16978
|
+
var DiskReconcileCountsSchema = object({
|
|
16979
|
+
mediaDropped: number().int(),
|
|
16980
|
+
tracks: number().int(),
|
|
16981
|
+
events: number().int()
|
|
16982
|
+
});
|
|
16935
16983
|
/** Event-store footprint for one camera. */
|
|
16936
16984
|
var EventStoreDeviceFootprintSchema = object({
|
|
16937
16985
|
deviceId: number(),
|
|
@@ -17108,6 +17156,9 @@ DeviceType.Camera, method(object({ deviceId: number() }), array(TrackSchema).rea
|
|
|
17108
17156
|
}), method(object({ deviceId: number() }), TrackCascadeCountsSchema, {
|
|
17109
17157
|
kind: "mutation",
|
|
17110
17158
|
auth: "admin"
|
|
17159
|
+
}), method(object({ deviceId: number() }), DiskReconcileCountsSchema, {
|
|
17160
|
+
kind: "mutation",
|
|
17161
|
+
auth: "admin"
|
|
17111
17162
|
}), method(object({
|
|
17112
17163
|
deviceId: number(),
|
|
17113
17164
|
trackIds: array(string()).min(1)
|
|
@@ -18618,6 +18669,24 @@ var CameraStatusDegradationSchema = object({
|
|
|
18618
18669
|
*
|
|
18619
18670
|
* See spec: `docs/superpowers/specs/2026-06-24-camera-status-aggregator-cap.md`
|
|
18620
18671
|
*/
|
|
18672
|
+
var DiskReconcileJobSchema = object({
|
|
18673
|
+
state: _enum([
|
|
18674
|
+
"idle",
|
|
18675
|
+
"running",
|
|
18676
|
+
"done",
|
|
18677
|
+
"error"
|
|
18678
|
+
]),
|
|
18679
|
+
total: number().int().nonnegative(),
|
|
18680
|
+
completed: number().int().nonnegative(),
|
|
18681
|
+
currentDeviceId: number().int().nullable(),
|
|
18682
|
+
failed: array(number().int()).readonly(),
|
|
18683
|
+
mediaDropped: number().int().nonnegative(),
|
|
18684
|
+
tracks: number().int().nonnegative(),
|
|
18685
|
+
events: number().int().nonnegative(),
|
|
18686
|
+
startedAtMs: number().int().nullable(),
|
|
18687
|
+
finishedAtMs: number().int().nullable(),
|
|
18688
|
+
error: string().nullable()
|
|
18689
|
+
});
|
|
18621
18690
|
var CameraStatusSchema = object({
|
|
18622
18691
|
deviceId: number(),
|
|
18623
18692
|
assignment: CameraAssignmentStatusSchema,
|
|
@@ -18849,7 +18918,10 @@ method(StorageMigrationLeaseInputSchema, object({ paused: literal(true) }), {
|
|
|
18849
18918
|
}), CameraSwitchGroupSchema, {
|
|
18850
18919
|
kind: "mutation",
|
|
18851
18920
|
auth: "admin"
|
|
18852
|
-
}), method(object({ deviceId: number() }), CameraStatusSchema), method(object({ deviceIds: array(number()).optional() }), array(CameraStatusSchema).readonly()), method(_void(),
|
|
18921
|
+
}), method(object({ deviceId: number() }), CameraStatusSchema), method(object({ deviceIds: array(number()).optional() }), array(CameraStatusSchema).readonly()), method(_void(), DiskReconcileJobSchema, {
|
|
18922
|
+
kind: "mutation",
|
|
18923
|
+
auth: "admin"
|
|
18924
|
+
}), method(_void(), DiskReconcileJobSchema, { auth: "admin" }), method(_void(), array(PipelineTemplateSchema).readonly()), method(object({
|
|
18853
18925
|
name: string(),
|
|
18854
18926
|
description: string().optional(),
|
|
18855
18927
|
config: CameraPipelineConfigSchema
|
|
@@ -19922,20 +19994,6 @@ var VectorStatsResultSchema = object({
|
|
|
19922
19994
|
exact: boolean()
|
|
19923
19995
|
});
|
|
19924
19996
|
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);
|
|
19925
|
-
/**
|
|
19926
|
-
* `videoclips` — the unified, navigable-clip surface for a camera.
|
|
19927
|
-
*
|
|
19928
|
-
* A device-scoped WRAPPER cap (like `pipeline-analytics`): exactly one active
|
|
19929
|
-
* provider per device, substitutable. The DEFAULT provider (registered by
|
|
19930
|
-
* `addon-post-analysis`, `defaultActive: true`) composes the analytics event
|
|
19931
|
-
* log (markers + thumbnails) with the recorder's `getPlaybackManifest` — a clip
|
|
19932
|
-
* is a time-WINDOW over existing footage, never a separate file. A camera that
|
|
19933
|
-
* exposes NATIVE onboard clips (Reolink/Hikvision NVR) can later substitute the
|
|
19934
|
-
* wrapper provider for its device and serve its own clip catalog + URLs.
|
|
19935
|
-
*
|
|
19936
|
-
* A `Clip` is purely time-based (subtree-blind): playback resolves segments by
|
|
19937
|
-
* temporal overlap, so the API never decides `continuous` vs `events`.
|
|
19938
|
-
*/
|
|
19939
19997
|
var ClipSchema = object({
|
|
19940
19998
|
/** Opaque, provider-namespaced id. The default provider encodes the time
|
|
19941
19999
|
* window so `getClipPlayback` is self-contained (no event re-query). */
|
|
@@ -19952,8 +20010,65 @@ var ClipSchema = object({
|
|
|
19952
20010
|
startMs: number(),
|
|
19953
20011
|
endMs: number()
|
|
19954
20012
|
}),
|
|
19955
|
-
/**
|
|
19956
|
-
|
|
20013
|
+
/**
|
|
20014
|
+
* Distinct object classes attached to this visit (`person`, `car`, …),
|
|
20015
|
+
* dominant first, capped at {@link MAX_CLIP_LABELS}. The ribbon renders these
|
|
20016
|
+
* instead of the bare kind — "Object" tells the operator nothing a colour bar
|
|
20017
|
+
* did not. Absent (never empty) when the visit attached no classified object
|
|
20018
|
+
* event, so a motion/audio-only visit keeps its kind label.
|
|
20019
|
+
*/
|
|
20020
|
+
labels: array(string()).max(3).optional(),
|
|
20021
|
+
/**
|
|
20022
|
+
* Lazy thumbnail URL, never inlined.
|
|
20023
|
+
*
|
|
20024
|
+
* Recording-derived clips (events-mode keep-window, and the prepared
|
|
20025
|
+
* continuous event+fragment visit) MUST use the snapshot of the **main
|
|
20026
|
+
* event of the interval** — `getEventMedia({ eventId, kind: 'snapshot' })`
|
|
20027
|
+
* of the event that owns `kind` (object > motion > audio). Do not extract
|
|
20028
|
+
* a keyframe from the recorded segments. Other providers (onboard, HKSV)
|
|
20029
|
+
* mint their own stills.
|
|
20030
|
+
*
|
|
20031
|
+
* **VOUCHED, never fabricated.** A provider emits this only for an event it
|
|
20032
|
+
* has CONFIRMED owns at least one media row (its own, or its owning track's).
|
|
20033
|
+
* Absent is meaningful — "this visit has no event still" — never "we did not
|
|
20034
|
+
* look". Stamping it from a URL template made 35% of one camera's clips point
|
|
20035
|
+
* at a 404 (device 3836, 2026-08-17: 64 of 179 clips dead, 63 of them motion).
|
|
20036
|
+
* A read that FAILS drops the claim; it never invents it.
|
|
20037
|
+
*/
|
|
20038
|
+
thumbnail: string().optional(),
|
|
20039
|
+
/**
|
|
20040
|
+
* An instant INSIDE this visit's footage, hole-safe, where a recorded still
|
|
20041
|
+
* can be decoded. Present whenever the visit came from recorded availability;
|
|
20042
|
+
* absent on a per-event padded window (there is no footage to promise).
|
|
20043
|
+
*
|
|
20044
|
+
* This is not a thumbnail and not a second byte path: it is the argument to
|
|
20045
|
+
* the recorder's existing still route. The surface — never the provider —
|
|
20046
|
+
* decides whether to use it. It is the midpoint of the visit's LONGEST
|
|
20047
|
+
* contiguous range, not of the visit: a visit spans its holes by
|
|
20048
|
+
* construction, so a naive midpoint lands in dead air.
|
|
20049
|
+
*/
|
|
20050
|
+
stillAtMs: number().optional(),
|
|
20051
|
+
/**
|
|
20052
|
+
* Analytics event ids that overlap this visit — a BOUNDED sample, newest
|
|
20053
|
+
* first within kind (object → motion → audio), capped at
|
|
20054
|
+
* {@link MAX_CLIP_EVENT_IDS}. Empty on footage-only clips.
|
|
20055
|
+
*
|
|
20056
|
+
* Bounded because it is not a payload the surface pages through: one visit on
|
|
20057
|
+
* device 615 carried 2 345 ids, and `eventIds` was 99% of a 153 KB
|
|
20058
|
+
* camera-day. Read {@link eventCount} for the true total.
|
|
20059
|
+
*/
|
|
20060
|
+
eventIds: array(string()).optional(),
|
|
20061
|
+
/** How many analytics events actually overlap this visit. Differs from
|
|
20062
|
+
* `eventIds.length` exactly when the sample was capped — so a truncated
|
|
20063
|
+
* list is never mistaken for a quiet visit. */
|
|
20064
|
+
eventCount: number().int().nonnegative().optional(),
|
|
20065
|
+
/** Intra-visit footage holes (GOP rolls, discarded segments) still shorter
|
|
20066
|
+
* than `VISIT_MERGE_GAP_MS`. Playback concatenates around them; the timeline
|
|
20067
|
+
* bar keeps showing them via `recording.getAvailability`. */
|
|
20068
|
+
holes: array(object({
|
|
20069
|
+
startMs: number(),
|
|
20070
|
+
endMs: number()
|
|
20071
|
+
})).optional()
|
|
19957
20072
|
});
|
|
19958
20073
|
var ClipPlaybackSchema = object({
|
|
19959
20074
|
/** HLS master URL through the hub data-plane (Range + token in path). */
|
|
@@ -20417,7 +20532,14 @@ var SearchResultSchema = object({
|
|
|
20417
20532
|
});
|
|
20418
20533
|
var AutoUpdateSettingsSchema = object({
|
|
20419
20534
|
channel: ChannelSchema,
|
|
20420
|
-
intervalSeconds: number()
|
|
20535
|
+
intervalSeconds: number(),
|
|
20536
|
+
/**
|
|
20537
|
+
* Cadence of the "an update exists" POLLER, in seconds. Independent of
|
|
20538
|
+
* `channel`: the poller runs while auto-apply is `off`, because being told
|
|
20539
|
+
* about a publish and installing it are different decisions. Clamped
|
|
20540
|
+
* server-side to 900 s … 604800 s; defaults to 21600 s (6 h).
|
|
20541
|
+
*/
|
|
20542
|
+
updateCheckIntervalSeconds: number()
|
|
20421
20543
|
});
|
|
20422
20544
|
var AddonAutoUpdateSchema = ChannelWithInheritSchema;
|
|
20423
20545
|
var RestartAddonResultSchema = unknown();
|
|
@@ -20558,7 +20680,9 @@ method(_void(), array(AddonListItemSchema).readonly()), method(object({
|
|
|
20558
20680
|
auth: "admin"
|
|
20559
20681
|
}), method(_void(), AutoUpdateSettingsSchema, { auth: "admin" }), method(object({
|
|
20560
20682
|
channel: ChannelSchema,
|
|
20561
|
-
intervalSeconds: number().min(300).max(86400).optional()
|
|
20683
|
+
intervalSeconds: number().min(300).max(86400).optional(),
|
|
20684
|
+
/** Availability-poll cadence; see AutoUpdateSettingsSchema. */
|
|
20685
|
+
updateCheckIntervalSeconds: number().min(900).max(604800).optional()
|
|
20562
20686
|
}), unknown(), {
|
|
20563
20687
|
kind: "mutation",
|
|
20564
20688
|
auth: "admin"
|
|
@@ -24551,7 +24675,9 @@ var ExportOptionsSchema = object({
|
|
|
24551
24675
|
includeAudio: boolean(),
|
|
24552
24676
|
maxLifeMs: number().int().positive(),
|
|
24553
24677
|
deleteAfterDownload: boolean(),
|
|
24554
|
-
title: string().max(200).optional()
|
|
24678
|
+
title: string().max(200).optional(),
|
|
24679
|
+
/** Notification-output target ids to ping when this export becomes ready. */
|
|
24680
|
+
notifyTargetIds: array(string().min(1)).max(20).optional()
|
|
24555
24681
|
}).superRefine((v, ctx) => {
|
|
24556
24682
|
if (v.speed !== void 0 && v.timelapse !== void 0) ctx.addIssue({
|
|
24557
24683
|
code: ZodIssueCode.custom,
|
|
@@ -24610,10 +24736,18 @@ var ExportBytesSchema = object({
|
|
|
24610
24736
|
});
|
|
24611
24737
|
method(object({
|
|
24612
24738
|
deviceId: number(),
|
|
24613
|
-
|
|
24739
|
+
/** @deprecated Prefer `profiles`. Kept so timelapse/notifiers keep working. */
|
|
24740
|
+
profile: string().optional(),
|
|
24741
|
+
profiles: array(string()).min(1).optional(),
|
|
24614
24742
|
fromMs: number(),
|
|
24615
24743
|
toMs: number(),
|
|
24616
24744
|
options: ExportOptionsSchema
|
|
24745
|
+
}).superRefine((v, ctx) => {
|
|
24746
|
+
if ((v.profiles !== void 0 && v.profiles.length > 0 ? v.profiles : v.profile !== void 0 ? [v.profile] : []).length < 1) ctx.addIssue({
|
|
24747
|
+
code: ZodIssueCode.custom,
|
|
24748
|
+
message: "pass profiles[] (min 1) or legacy profile",
|
|
24749
|
+
path: ["profiles"]
|
|
24750
|
+
});
|
|
24617
24751
|
}), ExportRecordSchema, {
|
|
24618
24752
|
kind: "mutation",
|
|
24619
24753
|
auth: "protected"
|
|
@@ -29213,6 +29347,12 @@ Object.freeze({
|
|
|
29213
29347
|
addonId: null,
|
|
29214
29348
|
access: "create"
|
|
29215
29349
|
},
|
|
29350
|
+
"pipelineAnalytics.reconcileFromDisk": {
|
|
29351
|
+
capName: "pipeline-analytics",
|
|
29352
|
+
capScope: "device",
|
|
29353
|
+
addonId: null,
|
|
29354
|
+
access: "create"
|
|
29355
|
+
},
|
|
29216
29356
|
"pipelineAnalytics.refreshStorageLocationsForMigration": {
|
|
29217
29357
|
capName: "pipeline-analytics",
|
|
29218
29358
|
capScope: "device",
|
|
@@ -29615,6 +29755,12 @@ Object.freeze({
|
|
|
29615
29755
|
addonId: null,
|
|
29616
29756
|
access: "view"
|
|
29617
29757
|
},
|
|
29758
|
+
"pipelineOrchestrator.getReconcileFromDiskStatus": {
|
|
29759
|
+
capName: "pipeline-orchestrator",
|
|
29760
|
+
capScope: "system",
|
|
29761
|
+
addonId: null,
|
|
29762
|
+
access: "view"
|
|
29763
|
+
},
|
|
29618
29764
|
"pipelineOrchestrator.listAgentSettings": {
|
|
29619
29765
|
capName: "pipeline-orchestrator",
|
|
29620
29766
|
capScope: "system",
|
|
@@ -29639,6 +29785,12 @@ Object.freeze({
|
|
|
29639
29785
|
addonId: null,
|
|
29640
29786
|
access: "create"
|
|
29641
29787
|
},
|
|
29788
|
+
"pipelineOrchestrator.reconcileFromDisk": {
|
|
29789
|
+
capName: "pipeline-orchestrator",
|
|
29790
|
+
capScope: "system",
|
|
29791
|
+
addonId: null,
|
|
29792
|
+
access: "create"
|
|
29793
|
+
},
|
|
29642
29794
|
"pipelineOrchestrator.removeAgentSettings": {
|
|
29643
29795
|
capName: "pipeline-orchestrator",
|
|
29644
29796
|
capScope: "system",
|
|
@@ -32630,6 +32782,11 @@ Object.freeze({
|
|
|
32630
32782
|
form: "single",
|
|
32631
32783
|
optional: true
|
|
32632
32784
|
}],
|
|
32785
|
+
"pipelineAnalytics.reconcileFromDisk": [{
|
|
32786
|
+
name: "deviceId",
|
|
32787
|
+
form: "single",
|
|
32788
|
+
optional: false
|
|
32789
|
+
}],
|
|
32633
32790
|
"pipelineAnalytics.restageRetrainTrack": [{
|
|
32634
32791
|
name: "deviceId",
|
|
32635
32792
|
form: "single",
|
|
@@ -33695,6 +33852,8 @@ DEFAULT_NATIVE_LEASE_SETTINGS.budgetMb;
|
|
|
33695
33852
|
DEFAULT_NATIVE_LEASE_SETTINGS.activityMs;
|
|
33696
33853
|
DEFAULT_NATIVE_LEASE_SETTINGS.tileBudgetMb;
|
|
33697
33854
|
DEFAULT_NATIVE_LEASE_SETTINGS.admission;
|
|
33855
|
+
var MB = 1024 * 1024;
|
|
33856
|
+
1024 * MB, 3072 * MB;
|
|
33698
33857
|
/**
|
|
33699
33858
|
* Fixed-capacity ring buffer. When full, push() overwrites the oldest entry.
|
|
33700
33859
|
* drain() returns up to maxCount items in FIFO order and removes them.
|
package/dist/index.mjs
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { randomUUID } from "node:crypto";
|
|
2
2
|
import { spawn } from "node:child_process";
|
|
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";
|
|
@@ -7545,6 +7562,10 @@ var RecordingBandSchema = object({
|
|
|
7545
7562
|
preBufferSec: number().min(0).optional(),
|
|
7546
7563
|
postBufferSec: number().min(0).optional()
|
|
7547
7564
|
});
|
|
7565
|
+
({
|
|
7566
|
+
preBufferSec: 10,
|
|
7567
|
+
postBufferSec: 30
|
|
7568
|
+
}).postBufferSec * 1e3;
|
|
7548
7569
|
/**
|
|
7549
7570
|
* Per-device retention overrides. Every field is optional; an unset or `0`
|
|
7550
7571
|
* value inherits the node-wide recorder default. Only footage-lifetime limits
|
|
@@ -7592,6 +7613,12 @@ var RecordingConfigSchema = object({
|
|
|
7592
7613
|
/** DERIVED summary of `bands`, stamped by the recorder on every save.
|
|
7593
7614
|
* Authoring it has no effect — see {@link RecordingStorageModeSchema}. */
|
|
7594
7615
|
mode: RecordingStorageModeSchema.optional(),
|
|
7616
|
+
/**
|
|
7617
|
+
* Which assigned broker slots to record. Absent / empty = {@link
|
|
7618
|
+
* DEFAULT_RECORDING_PROFILES} (`high`+`low`) intersected with the
|
|
7619
|
+
* camera's currently assigned slots — never `mid` unless the operator
|
|
7620
|
+
* picks it, and never a slot the broker has not assigned.
|
|
7621
|
+
*/
|
|
7595
7622
|
profiles: array(CamProfileSchema).optional(),
|
|
7596
7623
|
segmentSeconds: number().int().positive().optional(),
|
|
7597
7624
|
/**
|
|
@@ -7672,7 +7699,11 @@ var RelocateFootageInputSchema = object({
|
|
|
7672
7699
|
profiles: array(string()).optional(),
|
|
7673
7700
|
/** Copy throttle in MB/s (default 40) — the drain is a background chore,
|
|
7674
7701
|
* never allowed to starve live writers. */
|
|
7675
|
-
throttleMbps: number().min(1).max(1e3).optional()
|
|
7702
|
+
throttleMbps: number().min(1).max(1e3).optional(),
|
|
7703
|
+
/** Move only segments whose startMs is >= this. Absent = the whole source
|
|
7704
|
+
* pile. Used when a full drain is too expensive and the operator only
|
|
7705
|
+
* wants the recent window on the new disk. */
|
|
7706
|
+
sinceMs: number().int().optional()
|
|
7676
7707
|
});
|
|
7677
7708
|
/** Internal, lease-scoped participant operation. It is intentionally separate
|
|
7678
7709
|
* from persistent recording settings: a migration never changes
|
|
@@ -14365,6 +14396,7 @@ var NcSystemEventKindSchema = _enum([
|
|
|
14365
14396
|
"node-offline",
|
|
14366
14397
|
"node-inference-unavailable",
|
|
14367
14398
|
"detection-blind",
|
|
14399
|
+
"addon-crash-loop",
|
|
14368
14400
|
"addon-update-available",
|
|
14369
14401
|
"server-update-available",
|
|
14370
14402
|
"alarm-triggered",
|
|
@@ -14372,6 +14404,9 @@ var NcSystemEventKindSchema = _enum([
|
|
|
14372
14404
|
"alarm-disarmed",
|
|
14373
14405
|
"alarm-arming",
|
|
14374
14406
|
"alarm-arm-refused",
|
|
14407
|
+
"addon-updated",
|
|
14408
|
+
"server-updated",
|
|
14409
|
+
"export-completed",
|
|
14375
14410
|
"camera-online",
|
|
14376
14411
|
"camera-offline",
|
|
14377
14412
|
"camera-disabled",
|
|
@@ -16265,13 +16300,19 @@ var RetrainStatusSchema = _enum([
|
|
|
16265
16300
|
* "never marked" from "already trained" must read `retrainStatus`.
|
|
16266
16301
|
*
|
|
16267
16302
|
* `debug` does NOT pin; it is attention, not durability.
|
|
16303
|
+
*
|
|
16304
|
+
* `favourited` IS a BOOLEAN pin (durability bit), not a retrain lifecycle.
|
|
16305
|
+
* A favourited track is skipped by retention the same way `staging` is, but
|
|
16306
|
+
* it does not enter `none|staging|trained` and has no staging budget.
|
|
16268
16307
|
*/
|
|
16269
16308
|
var TrackFlagFields = {
|
|
16270
16309
|
/** Operator marked this track as training material — i.e. `retrainStatus` is
|
|
16271
16310
|
* `'staging'`. */
|
|
16272
16311
|
markForTrain: boolean().optional(),
|
|
16273
16312
|
/** Operator marked this track for diagnostic attention. */
|
|
16274
|
-
debug: boolean().optional()
|
|
16313
|
+
debug: boolean().optional(),
|
|
16314
|
+
/** Operator favourited this track. Pins it against pruning. */
|
|
16315
|
+
favourited: boolean().optional()
|
|
16275
16316
|
};
|
|
16276
16317
|
/**
|
|
16277
16318
|
* The lifecycle field itself, on the READ surfaces only (`Track`, `KeyEvent`).
|
|
@@ -16296,6 +16337,7 @@ var TrackFlagsSchema = object({
|
|
|
16296
16337
|
trackId: string(),
|
|
16297
16338
|
markForTrain: boolean(),
|
|
16298
16339
|
debug: boolean(),
|
|
16340
|
+
favourited: boolean(),
|
|
16299
16341
|
/** The lifecycle state the boolean was derived from. Required here (unlike on
|
|
16300
16342
|
* a track row) because this shape is only ever produced by the write body,
|
|
16301
16343
|
* which always knows it — and a surface that has just written needs to render
|
|
@@ -16928,6 +16970,12 @@ var TrackCascadeCountsSchema = object({
|
|
|
16928
16970
|
/** Per-track CLIP search vectors removed (best-effort). */
|
|
16929
16971
|
embeddings: number().int()
|
|
16930
16972
|
});
|
|
16973
|
+
/** Disk-wins reconcile: media rows whose blobs are gone, then empty tracks. */
|
|
16974
|
+
var DiskReconcileCountsSchema = object({
|
|
16975
|
+
mediaDropped: number().int(),
|
|
16976
|
+
tracks: number().int(),
|
|
16977
|
+
events: number().int()
|
|
16978
|
+
});
|
|
16931
16979
|
/** Event-store footprint for one camera. */
|
|
16932
16980
|
var EventStoreDeviceFootprintSchema = object({
|
|
16933
16981
|
deviceId: number(),
|
|
@@ -17104,6 +17152,9 @@ DeviceType.Camera, method(object({ deviceId: number() }), array(TrackSchema).rea
|
|
|
17104
17152
|
}), method(object({ deviceId: number() }), TrackCascadeCountsSchema, {
|
|
17105
17153
|
kind: "mutation",
|
|
17106
17154
|
auth: "admin"
|
|
17155
|
+
}), method(object({ deviceId: number() }), DiskReconcileCountsSchema, {
|
|
17156
|
+
kind: "mutation",
|
|
17157
|
+
auth: "admin"
|
|
17107
17158
|
}), method(object({
|
|
17108
17159
|
deviceId: number(),
|
|
17109
17160
|
trackIds: array(string()).min(1)
|
|
@@ -18614,6 +18665,24 @@ var CameraStatusDegradationSchema = object({
|
|
|
18614
18665
|
*
|
|
18615
18666
|
* See spec: `docs/superpowers/specs/2026-06-24-camera-status-aggregator-cap.md`
|
|
18616
18667
|
*/
|
|
18668
|
+
var DiskReconcileJobSchema = object({
|
|
18669
|
+
state: _enum([
|
|
18670
|
+
"idle",
|
|
18671
|
+
"running",
|
|
18672
|
+
"done",
|
|
18673
|
+
"error"
|
|
18674
|
+
]),
|
|
18675
|
+
total: number().int().nonnegative(),
|
|
18676
|
+
completed: number().int().nonnegative(),
|
|
18677
|
+
currentDeviceId: number().int().nullable(),
|
|
18678
|
+
failed: array(number().int()).readonly(),
|
|
18679
|
+
mediaDropped: number().int().nonnegative(),
|
|
18680
|
+
tracks: number().int().nonnegative(),
|
|
18681
|
+
events: number().int().nonnegative(),
|
|
18682
|
+
startedAtMs: number().int().nullable(),
|
|
18683
|
+
finishedAtMs: number().int().nullable(),
|
|
18684
|
+
error: string().nullable()
|
|
18685
|
+
});
|
|
18617
18686
|
var CameraStatusSchema = object({
|
|
18618
18687
|
deviceId: number(),
|
|
18619
18688
|
assignment: CameraAssignmentStatusSchema,
|
|
@@ -18845,7 +18914,10 @@ method(StorageMigrationLeaseInputSchema, object({ paused: literal(true) }), {
|
|
|
18845
18914
|
}), CameraSwitchGroupSchema, {
|
|
18846
18915
|
kind: "mutation",
|
|
18847
18916
|
auth: "admin"
|
|
18848
|
-
}), method(object({ deviceId: number() }), CameraStatusSchema), method(object({ deviceIds: array(number()).optional() }), array(CameraStatusSchema).readonly()), method(_void(),
|
|
18917
|
+
}), method(object({ deviceId: number() }), CameraStatusSchema), method(object({ deviceIds: array(number()).optional() }), array(CameraStatusSchema).readonly()), method(_void(), DiskReconcileJobSchema, {
|
|
18918
|
+
kind: "mutation",
|
|
18919
|
+
auth: "admin"
|
|
18920
|
+
}), method(_void(), DiskReconcileJobSchema, { auth: "admin" }), method(_void(), array(PipelineTemplateSchema).readonly()), method(object({
|
|
18849
18921
|
name: string(),
|
|
18850
18922
|
description: string().optional(),
|
|
18851
18923
|
config: CameraPipelineConfigSchema
|
|
@@ -19918,20 +19990,6 @@ var VectorStatsResultSchema = object({
|
|
|
19918
19990
|
exact: boolean()
|
|
19919
19991
|
});
|
|
19920
19992
|
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);
|
|
19921
|
-
/**
|
|
19922
|
-
* `videoclips` — the unified, navigable-clip surface for a camera.
|
|
19923
|
-
*
|
|
19924
|
-
* A device-scoped WRAPPER cap (like `pipeline-analytics`): exactly one active
|
|
19925
|
-
* provider per device, substitutable. The DEFAULT provider (registered by
|
|
19926
|
-
* `addon-post-analysis`, `defaultActive: true`) composes the analytics event
|
|
19927
|
-
* log (markers + thumbnails) with the recorder's `getPlaybackManifest` — a clip
|
|
19928
|
-
* is a time-WINDOW over existing footage, never a separate file. A camera that
|
|
19929
|
-
* exposes NATIVE onboard clips (Reolink/Hikvision NVR) can later substitute the
|
|
19930
|
-
* wrapper provider for its device and serve its own clip catalog + URLs.
|
|
19931
|
-
*
|
|
19932
|
-
* A `Clip` is purely time-based (subtree-blind): playback resolves segments by
|
|
19933
|
-
* temporal overlap, so the API never decides `continuous` vs `events`.
|
|
19934
|
-
*/
|
|
19935
19993
|
var ClipSchema = object({
|
|
19936
19994
|
/** Opaque, provider-namespaced id. The default provider encodes the time
|
|
19937
19995
|
* window so `getClipPlayback` is self-contained (no event re-query). */
|
|
@@ -19948,8 +20006,65 @@ var ClipSchema = object({
|
|
|
19948
20006
|
startMs: number(),
|
|
19949
20007
|
endMs: number()
|
|
19950
20008
|
}),
|
|
19951
|
-
/**
|
|
19952
|
-
|
|
20009
|
+
/**
|
|
20010
|
+
* Distinct object classes attached to this visit (`person`, `car`, …),
|
|
20011
|
+
* dominant first, capped at {@link MAX_CLIP_LABELS}. The ribbon renders these
|
|
20012
|
+
* instead of the bare kind — "Object" tells the operator nothing a colour bar
|
|
20013
|
+
* did not. Absent (never empty) when the visit attached no classified object
|
|
20014
|
+
* event, so a motion/audio-only visit keeps its kind label.
|
|
20015
|
+
*/
|
|
20016
|
+
labels: array(string()).max(3).optional(),
|
|
20017
|
+
/**
|
|
20018
|
+
* Lazy thumbnail URL, never inlined.
|
|
20019
|
+
*
|
|
20020
|
+
* Recording-derived clips (events-mode keep-window, and the prepared
|
|
20021
|
+
* continuous event+fragment visit) MUST use the snapshot of the **main
|
|
20022
|
+
* event of the interval** — `getEventMedia({ eventId, kind: 'snapshot' })`
|
|
20023
|
+
* of the event that owns `kind` (object > motion > audio). Do not extract
|
|
20024
|
+
* a keyframe from the recorded segments. Other providers (onboard, HKSV)
|
|
20025
|
+
* mint their own stills.
|
|
20026
|
+
*
|
|
20027
|
+
* **VOUCHED, never fabricated.** A provider emits this only for an event it
|
|
20028
|
+
* has CONFIRMED owns at least one media row (its own, or its owning track's).
|
|
20029
|
+
* Absent is meaningful — "this visit has no event still" — never "we did not
|
|
20030
|
+
* look". Stamping it from a URL template made 35% of one camera's clips point
|
|
20031
|
+
* at a 404 (device 3836, 2026-08-17: 64 of 179 clips dead, 63 of them motion).
|
|
20032
|
+
* A read that FAILS drops the claim; it never invents it.
|
|
20033
|
+
*/
|
|
20034
|
+
thumbnail: string().optional(),
|
|
20035
|
+
/**
|
|
20036
|
+
* An instant INSIDE this visit's footage, hole-safe, where a recorded still
|
|
20037
|
+
* can be decoded. Present whenever the visit came from recorded availability;
|
|
20038
|
+
* absent on a per-event padded window (there is no footage to promise).
|
|
20039
|
+
*
|
|
20040
|
+
* This is not a thumbnail and not a second byte path: it is the argument to
|
|
20041
|
+
* the recorder's existing still route. The surface — never the provider —
|
|
20042
|
+
* decides whether to use it. It is the midpoint of the visit's LONGEST
|
|
20043
|
+
* contiguous range, not of the visit: a visit spans its holes by
|
|
20044
|
+
* construction, so a naive midpoint lands in dead air.
|
|
20045
|
+
*/
|
|
20046
|
+
stillAtMs: number().optional(),
|
|
20047
|
+
/**
|
|
20048
|
+
* Analytics event ids that overlap this visit — a BOUNDED sample, newest
|
|
20049
|
+
* first within kind (object → motion → audio), capped at
|
|
20050
|
+
* {@link MAX_CLIP_EVENT_IDS}. Empty on footage-only clips.
|
|
20051
|
+
*
|
|
20052
|
+
* Bounded because it is not a payload the surface pages through: one visit on
|
|
20053
|
+
* device 615 carried 2 345 ids, and `eventIds` was 99% of a 153 KB
|
|
20054
|
+
* camera-day. Read {@link eventCount} for the true total.
|
|
20055
|
+
*/
|
|
20056
|
+
eventIds: array(string()).optional(),
|
|
20057
|
+
/** How many analytics events actually overlap this visit. Differs from
|
|
20058
|
+
* `eventIds.length` exactly when the sample was capped — so a truncated
|
|
20059
|
+
* list is never mistaken for a quiet visit. */
|
|
20060
|
+
eventCount: number().int().nonnegative().optional(),
|
|
20061
|
+
/** Intra-visit footage holes (GOP rolls, discarded segments) still shorter
|
|
20062
|
+
* than `VISIT_MERGE_GAP_MS`. Playback concatenates around them; the timeline
|
|
20063
|
+
* bar keeps showing them via `recording.getAvailability`. */
|
|
20064
|
+
holes: array(object({
|
|
20065
|
+
startMs: number(),
|
|
20066
|
+
endMs: number()
|
|
20067
|
+
})).optional()
|
|
19953
20068
|
});
|
|
19954
20069
|
var ClipPlaybackSchema = object({
|
|
19955
20070
|
/** HLS master URL through the hub data-plane (Range + token in path). */
|
|
@@ -20413,7 +20528,14 @@ var SearchResultSchema = object({
|
|
|
20413
20528
|
});
|
|
20414
20529
|
var AutoUpdateSettingsSchema = object({
|
|
20415
20530
|
channel: ChannelSchema,
|
|
20416
|
-
intervalSeconds: number()
|
|
20531
|
+
intervalSeconds: number(),
|
|
20532
|
+
/**
|
|
20533
|
+
* Cadence of the "an update exists" POLLER, in seconds. Independent of
|
|
20534
|
+
* `channel`: the poller runs while auto-apply is `off`, because being told
|
|
20535
|
+
* about a publish and installing it are different decisions. Clamped
|
|
20536
|
+
* server-side to 900 s … 604800 s; defaults to 21600 s (6 h).
|
|
20537
|
+
*/
|
|
20538
|
+
updateCheckIntervalSeconds: number()
|
|
20417
20539
|
});
|
|
20418
20540
|
var AddonAutoUpdateSchema = ChannelWithInheritSchema;
|
|
20419
20541
|
var RestartAddonResultSchema = unknown();
|
|
@@ -20554,7 +20676,9 @@ method(_void(), array(AddonListItemSchema).readonly()), method(object({
|
|
|
20554
20676
|
auth: "admin"
|
|
20555
20677
|
}), method(_void(), AutoUpdateSettingsSchema, { auth: "admin" }), method(object({
|
|
20556
20678
|
channel: ChannelSchema,
|
|
20557
|
-
intervalSeconds: number().min(300).max(86400).optional()
|
|
20679
|
+
intervalSeconds: number().min(300).max(86400).optional(),
|
|
20680
|
+
/** Availability-poll cadence; see AutoUpdateSettingsSchema. */
|
|
20681
|
+
updateCheckIntervalSeconds: number().min(900).max(604800).optional()
|
|
20558
20682
|
}), unknown(), {
|
|
20559
20683
|
kind: "mutation",
|
|
20560
20684
|
auth: "admin"
|
|
@@ -24547,7 +24671,9 @@ var ExportOptionsSchema = object({
|
|
|
24547
24671
|
includeAudio: boolean(),
|
|
24548
24672
|
maxLifeMs: number().int().positive(),
|
|
24549
24673
|
deleteAfterDownload: boolean(),
|
|
24550
|
-
title: string().max(200).optional()
|
|
24674
|
+
title: string().max(200).optional(),
|
|
24675
|
+
/** Notification-output target ids to ping when this export becomes ready. */
|
|
24676
|
+
notifyTargetIds: array(string().min(1)).max(20).optional()
|
|
24551
24677
|
}).superRefine((v, ctx) => {
|
|
24552
24678
|
if (v.speed !== void 0 && v.timelapse !== void 0) ctx.addIssue({
|
|
24553
24679
|
code: ZodIssueCode.custom,
|
|
@@ -24606,10 +24732,18 @@ var ExportBytesSchema = object({
|
|
|
24606
24732
|
});
|
|
24607
24733
|
method(object({
|
|
24608
24734
|
deviceId: number(),
|
|
24609
|
-
|
|
24735
|
+
/** @deprecated Prefer `profiles`. Kept so timelapse/notifiers keep working. */
|
|
24736
|
+
profile: string().optional(),
|
|
24737
|
+
profiles: array(string()).min(1).optional(),
|
|
24610
24738
|
fromMs: number(),
|
|
24611
24739
|
toMs: number(),
|
|
24612
24740
|
options: ExportOptionsSchema
|
|
24741
|
+
}).superRefine((v, ctx) => {
|
|
24742
|
+
if ((v.profiles !== void 0 && v.profiles.length > 0 ? v.profiles : v.profile !== void 0 ? [v.profile] : []).length < 1) ctx.addIssue({
|
|
24743
|
+
code: ZodIssueCode.custom,
|
|
24744
|
+
message: "pass profiles[] (min 1) or legacy profile",
|
|
24745
|
+
path: ["profiles"]
|
|
24746
|
+
});
|
|
24613
24747
|
}), ExportRecordSchema, {
|
|
24614
24748
|
kind: "mutation",
|
|
24615
24749
|
auth: "protected"
|
|
@@ -29209,6 +29343,12 @@ Object.freeze({
|
|
|
29209
29343
|
addonId: null,
|
|
29210
29344
|
access: "create"
|
|
29211
29345
|
},
|
|
29346
|
+
"pipelineAnalytics.reconcileFromDisk": {
|
|
29347
|
+
capName: "pipeline-analytics",
|
|
29348
|
+
capScope: "device",
|
|
29349
|
+
addonId: null,
|
|
29350
|
+
access: "create"
|
|
29351
|
+
},
|
|
29212
29352
|
"pipelineAnalytics.refreshStorageLocationsForMigration": {
|
|
29213
29353
|
capName: "pipeline-analytics",
|
|
29214
29354
|
capScope: "device",
|
|
@@ -29611,6 +29751,12 @@ Object.freeze({
|
|
|
29611
29751
|
addonId: null,
|
|
29612
29752
|
access: "view"
|
|
29613
29753
|
},
|
|
29754
|
+
"pipelineOrchestrator.getReconcileFromDiskStatus": {
|
|
29755
|
+
capName: "pipeline-orchestrator",
|
|
29756
|
+
capScope: "system",
|
|
29757
|
+
addonId: null,
|
|
29758
|
+
access: "view"
|
|
29759
|
+
},
|
|
29614
29760
|
"pipelineOrchestrator.listAgentSettings": {
|
|
29615
29761
|
capName: "pipeline-orchestrator",
|
|
29616
29762
|
capScope: "system",
|
|
@@ -29635,6 +29781,12 @@ Object.freeze({
|
|
|
29635
29781
|
addonId: null,
|
|
29636
29782
|
access: "create"
|
|
29637
29783
|
},
|
|
29784
|
+
"pipelineOrchestrator.reconcileFromDisk": {
|
|
29785
|
+
capName: "pipeline-orchestrator",
|
|
29786
|
+
capScope: "system",
|
|
29787
|
+
addonId: null,
|
|
29788
|
+
access: "create"
|
|
29789
|
+
},
|
|
29638
29790
|
"pipelineOrchestrator.removeAgentSettings": {
|
|
29639
29791
|
capName: "pipeline-orchestrator",
|
|
29640
29792
|
capScope: "system",
|
|
@@ -32626,6 +32778,11 @@ Object.freeze({
|
|
|
32626
32778
|
form: "single",
|
|
32627
32779
|
optional: true
|
|
32628
32780
|
}],
|
|
32781
|
+
"pipelineAnalytics.reconcileFromDisk": [{
|
|
32782
|
+
name: "deviceId",
|
|
32783
|
+
form: "single",
|
|
32784
|
+
optional: false
|
|
32785
|
+
}],
|
|
32629
32786
|
"pipelineAnalytics.restageRetrainTrack": [{
|
|
32630
32787
|
name: "deviceId",
|
|
32631
32788
|
form: "single",
|
|
@@ -33691,6 +33848,8 @@ DEFAULT_NATIVE_LEASE_SETTINGS.budgetMb;
|
|
|
33691
33848
|
DEFAULT_NATIVE_LEASE_SETTINGS.activityMs;
|
|
33692
33849
|
DEFAULT_NATIVE_LEASE_SETTINGS.tileBudgetMb;
|
|
33693
33850
|
DEFAULT_NATIVE_LEASE_SETTINGS.admission;
|
|
33851
|
+
var MB = 1024 * 1024;
|
|
33852
|
+
1024 * MB, 3072 * MB;
|
|
33694
33853
|
/**
|
|
33695
33854
|
* Fixed-capacity ring buffer. When full, push() overwrites the oldest entry.
|
|
33696
33855
|
* drain() returns up to maxCount items in FIFO order and removes them.
|