@camstack/addon-decoder-nodeav 1.2.48 → 1.2.49
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 +218 -4
- package/dist/index.mjs +218 -4
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -8018,6 +8018,20 @@ var RelocateJobSchema = object({
|
|
|
8018
8018
|
* in its row, not in its name, so `MediaRelocateEngine` never reconciles one.
|
|
8019
8019
|
*/
|
|
8020
8020
|
rowsReconciled: number().int().nonnegative().optional(),
|
|
8021
|
+
/**
|
|
8022
|
+
* Rows this run FORGOT because the file they name is not on disk.
|
|
8023
|
+
*
|
|
8024
|
+
* The mover derived the path from the row's own fields and `stat`ed it; an
|
|
8025
|
+
* ENOENT there is a per-path confirmation that the segment is gone (D296),
|
|
8026
|
+
* and the durable row is dropped through the same channel eviction uses. It
|
|
8027
|
+
* is reported for the same reason `rowsReconciled` is: this is a durable
|
|
8028
|
+
* mutation nobody asked for, and a migration that quietly erases hour rows is
|
|
8029
|
+
* the same failure as one that quietly skips them (D295).
|
|
8030
|
+
*
|
|
8031
|
+
* The production drain of 2026-08-30 would have reported 11 074 here — the
|
|
8032
|
+
* ledger claimed 5.65 GB of footage that no longer existed.
|
|
8033
|
+
*/
|
|
8034
|
+
rowsForgotten: number().int().nonnegative().optional(),
|
|
8021
8035
|
startedAt: number(),
|
|
8022
8036
|
finishedAt: number().nullable(),
|
|
8023
8037
|
error: string().nullable()
|
|
@@ -8381,6 +8395,91 @@ var RelocateResidueSchema = object({
|
|
|
8381
8395
|
segments: number().int().nonnegative(),
|
|
8382
8396
|
bytes: number().int().nonnegative()
|
|
8383
8397
|
}).nullable();
|
|
8398
|
+
/**
|
|
8399
|
+
* Ask one location whether its durable hour rows describe the disk — the walk
|
|
8400
|
+
* (D319).
|
|
8401
|
+
*
|
|
8402
|
+
* `apply` DEFAULTS TO FALSE and that default is the product: the operator's
|
|
8403
|
+
* missing tool is the question, and the dry run is how they sanity-check the
|
|
8404
|
+
* destructive run before authorising it.
|
|
8405
|
+
*/
|
|
8406
|
+
var LedgerWalkInputSchema = object({
|
|
8407
|
+
locationId: string().min(1),
|
|
8408
|
+
/** Forget the confirmed-absent rows, rather than only counting them. */
|
|
8409
|
+
apply: boolean().optional(),
|
|
8410
|
+
/** Narrow to one camera. */
|
|
8411
|
+
deviceId: number().int().positive().optional(),
|
|
8412
|
+
/** Narrow to these recording profiles; empty/absent = every profile. */
|
|
8413
|
+
profiles: array(string().min(1)).optional()
|
|
8414
|
+
});
|
|
8415
|
+
/** Why a whole walk did nothing. Every one leaves the ledger untouched. */
|
|
8416
|
+
var LedgerWalkRefusalSchema = _enum([
|
|
8417
|
+
"location-unknown",
|
|
8418
|
+
"source-writable",
|
|
8419
|
+
"no-ledger",
|
|
8420
|
+
"archive-unreadable",
|
|
8421
|
+
"anchor-absent",
|
|
8422
|
+
"anchor-unreadable",
|
|
8423
|
+
"anchor-moved"
|
|
8424
|
+
]);
|
|
8425
|
+
_enum([
|
|
8426
|
+
"live-tail",
|
|
8427
|
+
"listing-error",
|
|
8428
|
+
"path-mismatch",
|
|
8429
|
+
"durable-refused"
|
|
8430
|
+
]);
|
|
8431
|
+
/** Every skip reason, always present, always a number — so a reason that never
|
|
8432
|
+
* fired reports as zero rather than absent and the report shape is constant
|
|
8433
|
+
* between passes. Spelled out rather than `z.record` for exactly that. */
|
|
8434
|
+
var LedgerWalkSkipCountsSchema = object({
|
|
8435
|
+
"live-tail": number().int().nonnegative(),
|
|
8436
|
+
"listing-error": number().int().nonnegative(),
|
|
8437
|
+
"path-mismatch": number().int().nonnegative(),
|
|
8438
|
+
"durable-refused": number().int().nonnegative()
|
|
8439
|
+
});
|
|
8440
|
+
/** One camera's share of a walk, so a report names cameras and not rows. */
|
|
8441
|
+
var LedgerWalkDeviceReportSchema = object({
|
|
8442
|
+
deviceId: number().int(),
|
|
8443
|
+
hoursWalked: number().int().nonnegative(),
|
|
8444
|
+
hoursMissing: number().int().nonnegative(),
|
|
8445
|
+
ghostSegments: number().int().nonnegative(),
|
|
8446
|
+
ghostBytes: number().int().nonnegative(),
|
|
8447
|
+
forgottenSegments: number().int().nonnegative(),
|
|
8448
|
+
orphanFiles: number().int().nonnegative()
|
|
8449
|
+
});
|
|
8450
|
+
/**
|
|
8451
|
+
* What one walk claimed, listed, found and (only when armed) forgot.
|
|
8452
|
+
*
|
|
8453
|
+
* `archiveSegments` is the **M** and `segmentsClaimed` the **N** (D295), so a
|
|
8454
|
+
* walk that saw a fraction of the location is visible in its own report rather
|
|
8455
|
+
* than in the absence of one.
|
|
8456
|
+
*/
|
|
8457
|
+
var LedgerWalkReportSchema = object({
|
|
8458
|
+
locationId: string(),
|
|
8459
|
+
applied: boolean(),
|
|
8460
|
+
refused: LedgerWalkRefusalSchema.nullable(),
|
|
8461
|
+
archiveSegments: number().int().nonnegative().nullable(),
|
|
8462
|
+
archiveBytes: number().int().nonnegative().nullable(),
|
|
8463
|
+
hoursClaimed: number().int().nonnegative(),
|
|
8464
|
+
hoursWalked: number().int().nonnegative(),
|
|
8465
|
+
hoursMissing: number().int().nonnegative(),
|
|
8466
|
+
/** `readdir` calls issued — the cost, stated in the unit that is paid. */
|
|
8467
|
+
listings: number().int().nonnegative(),
|
|
8468
|
+
segmentsClaimed: number().int().nonnegative(),
|
|
8469
|
+
ghostSegments: number().int().nonnegative(),
|
|
8470
|
+
ghostBytes: number().int().nonnegative(),
|
|
8471
|
+
ghostHoursWhole: number().int().nonnegative(),
|
|
8472
|
+
forgottenSegments: number().int().nonnegative(),
|
|
8473
|
+
forgottenBytes: number().int().nonnegative(),
|
|
8474
|
+
/** Files under a claimed hour that no durable row names. Never deleted. */
|
|
8475
|
+
orphanFiles: number().int().nonnegative(),
|
|
8476
|
+
orphanSample: array(string()).readonly(),
|
|
8477
|
+
hoursSkipped: number().int().nonnegative(),
|
|
8478
|
+
skippedByReason: LedgerWalkSkipCountsSchema,
|
|
8479
|
+
/** The walk stopped at its per-pass hour bound with claims unwalked. */
|
|
8480
|
+
bounded: boolean(),
|
|
8481
|
+
byDevice: array(LedgerWalkDeviceReportSchema).readonly()
|
|
8482
|
+
});
|
|
8384
8483
|
/** How many rows a media pass would still act on against a given target — the
|
|
8385
8484
|
* media lane's denominator AND its residue, from ONE derivation so the two can
|
|
8386
8485
|
* never disagree. `null` = the count could not be taken. */
|
|
@@ -18784,13 +18883,15 @@ var ListGroupsPageSchema = object({
|
|
|
18784
18883
|
groups: array(AnalyticsGroupRecordSchema).readonly(),
|
|
18785
18884
|
nextCursor: string().nullable()
|
|
18786
18885
|
});
|
|
18886
|
+
var KEY_EVENTS_DEFAULT_LIMIT = 50;
|
|
18887
|
+
var KEY_EVENTS_MAX_LIMIT = 200;
|
|
18787
18888
|
var KeyEventQueryInput = object({
|
|
18788
18889
|
deviceId: number(),
|
|
18789
18890
|
/** Window lower bound (track firstSeen ≥ since). */
|
|
18790
18891
|
since: number(),
|
|
18791
18892
|
/** Window upper bound (track firstSeen ≤ until). */
|
|
18792
18893
|
until: number(),
|
|
18793
|
-
limit: number().int().min(1).max(
|
|
18894
|
+
limit: number().int().min(1).max(KEY_EVENTS_MAX_LIMIT).default(KEY_EVENTS_DEFAULT_LIMIT),
|
|
18794
18895
|
/** Drop tracks scoring below this importance. */
|
|
18795
18896
|
minImportance: number().min(0).max(1).optional(),
|
|
18796
18897
|
/** Restrict to a single class (e.g. 'person'). */
|
|
@@ -18812,6 +18913,32 @@ var KeyEventSchema = object({
|
|
|
18812
18913
|
...TrackFlagFields,
|
|
18813
18914
|
...TrackRetrainFields
|
|
18814
18915
|
});
|
|
18916
|
+
/** `getKeyEvents`' window and filters, asked of a SET of cameras at once. */
|
|
18917
|
+
var KeyEventBatchQueryInput = object({
|
|
18918
|
+
deviceIds: array(number()).min(1).max(200),
|
|
18919
|
+
since: number(),
|
|
18920
|
+
until: number(),
|
|
18921
|
+
/** Applied PER CAMERA, exactly as `getKeyEvents.limit` is — never a total
|
|
18922
|
+
* across the set, which would let a busy camera starve a quiet one of its
|
|
18923
|
+
* rows and change what the merged feed contains. */
|
|
18924
|
+
limit: number().int().min(1).max(KEY_EVENTS_MAX_LIMIT).default(KEY_EVENTS_DEFAULT_LIMIT),
|
|
18925
|
+
minImportance: number().min(0).max(1).optional(),
|
|
18926
|
+
classFilter: string().optional()
|
|
18927
|
+
});
|
|
18928
|
+
/**
|
|
18929
|
+
* One camera's key events in a batch answer.
|
|
18930
|
+
*
|
|
18931
|
+
* The row exists for every requested id. `getKeyEvents` degrades to `[]` on
|
|
18932
|
+
* error rather than throwing, so a camera whose store read failed and one with
|
|
18933
|
+
* no events in the window were ALREADY indistinguishable per camera — the
|
|
18934
|
+
* batch does not make that worse, and the row keeps the deviceId the single
|
|
18935
|
+
* method's output never carried (the caller used to stamp it from the fan-out
|
|
18936
|
+
* key, which only worked because there was one query per camera).
|
|
18937
|
+
*/
|
|
18938
|
+
var KeyEventsForDeviceSchema = object({
|
|
18939
|
+
deviceId: number(),
|
|
18940
|
+
events: array(KeyEventSchema).readonly()
|
|
18941
|
+
});
|
|
18815
18942
|
object({
|
|
18816
18943
|
trackId: string(),
|
|
18817
18944
|
className: string(),
|
|
@@ -19081,7 +19208,7 @@ DeviceType.Camera, method(object({ deviceId: number() }), array(TrackSchema).rea
|
|
|
19081
19208
|
until: number().optional(),
|
|
19082
19209
|
kinds: array(string()).optional(),
|
|
19083
19210
|
limit: number().int().min(1).max(MAX_EVENT_QUERY_LIMIT).default(DEFAULT_EVENT_QUERY_LIMIT)
|
|
19084
|
-
}), array(SensorEventSchema).readonly()), method(KeyEventQueryInput, array(KeyEventSchema).readonly()), method(object({
|
|
19211
|
+
}), array(SensorEventSchema).readonly()), method(KeyEventQueryInput, array(KeyEventSchema).readonly()), method(KeyEventBatchQueryInput, array(KeyEventsForDeviceSchema).readonly()), method(object({
|
|
19085
19212
|
deviceId: number(),
|
|
19086
19213
|
since: number(),
|
|
19087
19214
|
until: number(),
|
|
@@ -26733,6 +26860,9 @@ method(object({
|
|
|
26733
26860
|
}), method(RelocateResidueInputSchema, RelocateResidueSchema, {
|
|
26734
26861
|
kind: "query",
|
|
26735
26862
|
auth: "admin"
|
|
26863
|
+
}), method(LedgerWalkInputSchema, LedgerWalkReportSchema, {
|
|
26864
|
+
kind: "mutation",
|
|
26865
|
+
auth: "admin"
|
|
26736
26866
|
}), method(object({ jobId: string() }), object({ cancelled: boolean() }), {
|
|
26737
26867
|
kind: "mutation",
|
|
26738
26868
|
auth: "admin"
|
|
@@ -27124,7 +27254,26 @@ var SceneMonitorStatusSchema = object({
|
|
|
27124
27254
|
monitors: array(SceneMonitorSchema),
|
|
27125
27255
|
lastFetchedAt: number()
|
|
27126
27256
|
});
|
|
27127
|
-
|
|
27257
|
+
/**
|
|
27258
|
+
* One camera's row in a `listScenesBatch` answer.
|
|
27259
|
+
*
|
|
27260
|
+
* `status` is NULLABLE and the nullability is the whole point. `scene-monitor`
|
|
27261
|
+
* is a `defaultActive` wrapper, so every camera is asked; a camera whose
|
|
27262
|
+
* provider is absent (pipeline-analytics not deployed, the post-processing node
|
|
27263
|
+
* down) cannot answer, and that is not the same fact as a camera with no scenes
|
|
27264
|
+
* configured. Fanned out per camera the difference was visible — one query
|
|
27265
|
+
* errored while the others resolved — and a batch that returned only the rows
|
|
27266
|
+
* it managed would have destroyed it, silently, by making an unreachable camera
|
|
27267
|
+
* indistinguishable from one that answered `monitors: []`.
|
|
27268
|
+
*
|
|
27269
|
+
* So: EVERY requested deviceId gets a row. `status: null` means "this camera
|
|
27270
|
+
* could not be read"; `status.monitors: []` means "read, and it has none".
|
|
27271
|
+
*/
|
|
27272
|
+
var SceneMonitorStatusForDeviceSchema = object({
|
|
27273
|
+
deviceId: number(),
|
|
27274
|
+
status: SceneMonitorStatusSchema.nullable()
|
|
27275
|
+
});
|
|
27276
|
+
DeviceType.Camera, method(object({ deviceId: number() }), SceneMonitorStatusSchema), method(object({ deviceIds: array(number()).min(1).max(200) }), array(SceneMonitorStatusForDeviceSchema).readonly()), method(object({
|
|
27128
27277
|
deviceId: number(),
|
|
27129
27278
|
label: string(),
|
|
27130
27279
|
roi: MaskRectShapeSchema,
|
|
@@ -28448,6 +28597,27 @@ var CameraOccupancySnapshotSchema = object({
|
|
|
28448
28597
|
stationaryObjects: array(StationaryObjectSchema).readonly().optional()
|
|
28449
28598
|
});
|
|
28450
28599
|
/**
|
|
28600
|
+
* One camera's row in a `getCurrentSnapshotBatch` answer.
|
|
28601
|
+
*
|
|
28602
|
+
* THREE outcomes, and the single-camera method could only express two of them
|
|
28603
|
+
* because `snapshot: null` was already spoken for:
|
|
28604
|
+
*
|
|
28605
|
+
* - `read: 'read'`, `snapshot` present — the live occupancy reading.
|
|
28606
|
+
* - `read: 'read'`, `snapshot: null` — read, and this camera has no reading
|
|
28607
|
+
* yet: no frame since boot, and no parked-object registry to hydrate from.
|
|
28608
|
+
* - `read: 'unreadable'` — the owner could not answer for this
|
|
28609
|
+
* camera. `snapshot` is null, and it does NOT mean "nothing parked here".
|
|
28610
|
+
*
|
|
28611
|
+
* Collapsing the last two is the failure this field exists to prevent: a
|
|
28612
|
+
* hydration that threw would otherwise render as an empty Stationary section,
|
|
28613
|
+
* which is a definite claim about a camera nobody could read.
|
|
28614
|
+
*/
|
|
28615
|
+
var CameraOccupancySnapshotForDeviceSchema = object({
|
|
28616
|
+
deviceId: number(),
|
|
28617
|
+
read: _enum(["read", "unreadable"]),
|
|
28618
|
+
snapshot: CameraOccupancySnapshotSchema.nullable()
|
|
28619
|
+
});
|
|
28620
|
+
/**
|
|
28451
28621
|
* Time-series resolution. The history methods return one bucket per
|
|
28452
28622
|
* step over the requested range. Smaller resolutions cost more
|
|
28453
28623
|
* memory + bandwidth; bound to discrete steps so caller cannot ask
|
|
@@ -28471,7 +28641,7 @@ var HistoryPointSchema = object({
|
|
|
28471
28641
|
/** Object count averaged over the bucket (rounded to nearest integer). */
|
|
28472
28642
|
count: number().int().nonnegative()
|
|
28473
28643
|
});
|
|
28474
|
-
DeviceType.Camera, method(object({ deviceId: number() }), CameraOccupancySnapshotSchema.nullable()), method(object({
|
|
28644
|
+
DeviceType.Camera, method(object({ deviceId: number() }), CameraOccupancySnapshotSchema.nullable()), method(object({ deviceIds: array(number()).min(1).max(200) }), array(CameraOccupancySnapshotForDeviceSchema).readonly()), method(object({
|
|
28475
28645
|
deviceId: number(),
|
|
28476
28646
|
zoneId: string(),
|
|
28477
28647
|
className: string().optional()
|
|
@@ -31776,6 +31946,12 @@ Object.freeze({
|
|
|
31776
31946
|
addonId: null,
|
|
31777
31947
|
access: "view"
|
|
31778
31948
|
},
|
|
31949
|
+
"pipelineAnalytics.getKeyEventsBatch": {
|
|
31950
|
+
capName: "pipeline-analytics",
|
|
31951
|
+
capScope: "device",
|
|
31952
|
+
addonId: null,
|
|
31953
|
+
access: "view"
|
|
31954
|
+
},
|
|
31779
31955
|
"pipelineAnalytics.getMotionEvents": {
|
|
31780
31956
|
capName: "pipeline-analytics",
|
|
31781
31957
|
capScope: "device",
|
|
@@ -32952,6 +33128,12 @@ Object.freeze({
|
|
|
32952
33128
|
addonId: null,
|
|
32953
33129
|
access: "view"
|
|
32954
33130
|
},
|
|
33131
|
+
"recording.reconcileLedgerAgainstDisk": {
|
|
33132
|
+
capName: "recording",
|
|
33133
|
+
capScope: "system",
|
|
33134
|
+
addonId: null,
|
|
33135
|
+
access: "create"
|
|
33136
|
+
},
|
|
32955
33137
|
"recording.refreshStorageLocationsForMigration": {
|
|
32956
33138
|
capName: "recording",
|
|
32957
33139
|
capScope: "system",
|
|
@@ -33078,6 +33260,12 @@ Object.freeze({
|
|
|
33078
33260
|
addonId: null,
|
|
33079
33261
|
access: "view"
|
|
33080
33262
|
},
|
|
33263
|
+
"sceneMonitor.listScenesBatch": {
|
|
33264
|
+
capName: "scene-monitor",
|
|
33265
|
+
capScope: "device",
|
|
33266
|
+
addonId: null,
|
|
33267
|
+
access: "view"
|
|
33268
|
+
},
|
|
33081
33269
|
"sceneMonitor.recheckNow": {
|
|
33082
33270
|
capName: "scene-monitor",
|
|
33083
33271
|
capScope: "device",
|
|
@@ -34434,6 +34622,12 @@ Object.freeze({
|
|
|
34434
34622
|
addonId: null,
|
|
34435
34623
|
access: "view"
|
|
34436
34624
|
},
|
|
34625
|
+
"zoneAnalytics.getCurrentSnapshotBatch": {
|
|
34626
|
+
capName: "zone-analytics",
|
|
34627
|
+
capScope: "device",
|
|
34628
|
+
addonId: null,
|
|
34629
|
+
access: "view"
|
|
34630
|
+
},
|
|
34437
34631
|
"zoneAnalytics.getUnzonedHistory": {
|
|
34438
34632
|
capName: "zone-analytics",
|
|
34439
34633
|
capScope: "device",
|
|
@@ -35438,6 +35632,11 @@ Object.freeze({
|
|
|
35438
35632
|
form: "single",
|
|
35439
35633
|
optional: false
|
|
35440
35634
|
}],
|
|
35635
|
+
"pipelineAnalytics.getKeyEventsBatch": [{
|
|
35636
|
+
name: "deviceIds",
|
|
35637
|
+
form: "array",
|
|
35638
|
+
optional: false
|
|
35639
|
+
}],
|
|
35441
35640
|
"pipelineAnalytics.getMotionEvents": [{
|
|
35442
35641
|
name: "deviceId",
|
|
35443
35642
|
form: "single",
|
|
@@ -35878,6 +36077,11 @@ Object.freeze({
|
|
|
35878
36077
|
form: "single",
|
|
35879
36078
|
optional: false
|
|
35880
36079
|
}],
|
|
36080
|
+
"recording.reconcileLedgerAgainstDisk": [{
|
|
36081
|
+
name: "deviceId",
|
|
36082
|
+
form: "single",
|
|
36083
|
+
optional: true
|
|
36084
|
+
}],
|
|
35881
36085
|
"recording.relocateFootage": [{
|
|
35882
36086
|
name: "deviceId",
|
|
35883
36087
|
form: "single",
|
|
@@ -35943,6 +36147,11 @@ Object.freeze({
|
|
|
35943
36147
|
form: "single",
|
|
35944
36148
|
optional: false
|
|
35945
36149
|
}],
|
|
36150
|
+
"sceneMonitor.listScenesBatch": [{
|
|
36151
|
+
name: "deviceIds",
|
|
36152
|
+
form: "array",
|
|
36153
|
+
optional: false
|
|
36154
|
+
}],
|
|
35946
36155
|
"sceneMonitor.recheckNow": [{
|
|
35947
36156
|
name: "deviceId",
|
|
35948
36157
|
form: "single",
|
|
@@ -36204,6 +36413,11 @@ Object.freeze({
|
|
|
36204
36413
|
form: "single",
|
|
36205
36414
|
optional: false
|
|
36206
36415
|
}],
|
|
36416
|
+
"zoneAnalytics.getCurrentSnapshotBatch": [{
|
|
36417
|
+
name: "deviceIds",
|
|
36418
|
+
form: "array",
|
|
36419
|
+
optional: false
|
|
36420
|
+
}],
|
|
36207
36421
|
"zoneAnalytics.getUnzonedHistory": [{
|
|
36208
36422
|
name: "deviceId",
|
|
36209
36423
|
form: "single",
|
package/dist/index.mjs
CHANGED
|
@@ -8014,6 +8014,20 @@ var RelocateJobSchema = object({
|
|
|
8014
8014
|
* in its row, not in its name, so `MediaRelocateEngine` never reconciles one.
|
|
8015
8015
|
*/
|
|
8016
8016
|
rowsReconciled: number().int().nonnegative().optional(),
|
|
8017
|
+
/**
|
|
8018
|
+
* Rows this run FORGOT because the file they name is not on disk.
|
|
8019
|
+
*
|
|
8020
|
+
* The mover derived the path from the row's own fields and `stat`ed it; an
|
|
8021
|
+
* ENOENT there is a per-path confirmation that the segment is gone (D296),
|
|
8022
|
+
* and the durable row is dropped through the same channel eviction uses. It
|
|
8023
|
+
* is reported for the same reason `rowsReconciled` is: this is a durable
|
|
8024
|
+
* mutation nobody asked for, and a migration that quietly erases hour rows is
|
|
8025
|
+
* the same failure as one that quietly skips them (D295).
|
|
8026
|
+
*
|
|
8027
|
+
* The production drain of 2026-08-30 would have reported 11 074 here — the
|
|
8028
|
+
* ledger claimed 5.65 GB of footage that no longer existed.
|
|
8029
|
+
*/
|
|
8030
|
+
rowsForgotten: number().int().nonnegative().optional(),
|
|
8017
8031
|
startedAt: number(),
|
|
8018
8032
|
finishedAt: number().nullable(),
|
|
8019
8033
|
error: string().nullable()
|
|
@@ -8377,6 +8391,91 @@ var RelocateResidueSchema = object({
|
|
|
8377
8391
|
segments: number().int().nonnegative(),
|
|
8378
8392
|
bytes: number().int().nonnegative()
|
|
8379
8393
|
}).nullable();
|
|
8394
|
+
/**
|
|
8395
|
+
* Ask one location whether its durable hour rows describe the disk — the walk
|
|
8396
|
+
* (D319).
|
|
8397
|
+
*
|
|
8398
|
+
* `apply` DEFAULTS TO FALSE and that default is the product: the operator's
|
|
8399
|
+
* missing tool is the question, and the dry run is how they sanity-check the
|
|
8400
|
+
* destructive run before authorising it.
|
|
8401
|
+
*/
|
|
8402
|
+
var LedgerWalkInputSchema = object({
|
|
8403
|
+
locationId: string().min(1),
|
|
8404
|
+
/** Forget the confirmed-absent rows, rather than only counting them. */
|
|
8405
|
+
apply: boolean().optional(),
|
|
8406
|
+
/** Narrow to one camera. */
|
|
8407
|
+
deviceId: number().int().positive().optional(),
|
|
8408
|
+
/** Narrow to these recording profiles; empty/absent = every profile. */
|
|
8409
|
+
profiles: array(string().min(1)).optional()
|
|
8410
|
+
});
|
|
8411
|
+
/** Why a whole walk did nothing. Every one leaves the ledger untouched. */
|
|
8412
|
+
var LedgerWalkRefusalSchema = _enum([
|
|
8413
|
+
"location-unknown",
|
|
8414
|
+
"source-writable",
|
|
8415
|
+
"no-ledger",
|
|
8416
|
+
"archive-unreadable",
|
|
8417
|
+
"anchor-absent",
|
|
8418
|
+
"anchor-unreadable",
|
|
8419
|
+
"anchor-moved"
|
|
8420
|
+
]);
|
|
8421
|
+
_enum([
|
|
8422
|
+
"live-tail",
|
|
8423
|
+
"listing-error",
|
|
8424
|
+
"path-mismatch",
|
|
8425
|
+
"durable-refused"
|
|
8426
|
+
]);
|
|
8427
|
+
/** Every skip reason, always present, always a number — so a reason that never
|
|
8428
|
+
* fired reports as zero rather than absent and the report shape is constant
|
|
8429
|
+
* between passes. Spelled out rather than `z.record` for exactly that. */
|
|
8430
|
+
var LedgerWalkSkipCountsSchema = object({
|
|
8431
|
+
"live-tail": number().int().nonnegative(),
|
|
8432
|
+
"listing-error": number().int().nonnegative(),
|
|
8433
|
+
"path-mismatch": number().int().nonnegative(),
|
|
8434
|
+
"durable-refused": number().int().nonnegative()
|
|
8435
|
+
});
|
|
8436
|
+
/** One camera's share of a walk, so a report names cameras and not rows. */
|
|
8437
|
+
var LedgerWalkDeviceReportSchema = object({
|
|
8438
|
+
deviceId: number().int(),
|
|
8439
|
+
hoursWalked: number().int().nonnegative(),
|
|
8440
|
+
hoursMissing: number().int().nonnegative(),
|
|
8441
|
+
ghostSegments: number().int().nonnegative(),
|
|
8442
|
+
ghostBytes: number().int().nonnegative(),
|
|
8443
|
+
forgottenSegments: number().int().nonnegative(),
|
|
8444
|
+
orphanFiles: number().int().nonnegative()
|
|
8445
|
+
});
|
|
8446
|
+
/**
|
|
8447
|
+
* What one walk claimed, listed, found and (only when armed) forgot.
|
|
8448
|
+
*
|
|
8449
|
+
* `archiveSegments` is the **M** and `segmentsClaimed` the **N** (D295), so a
|
|
8450
|
+
* walk that saw a fraction of the location is visible in its own report rather
|
|
8451
|
+
* than in the absence of one.
|
|
8452
|
+
*/
|
|
8453
|
+
var LedgerWalkReportSchema = object({
|
|
8454
|
+
locationId: string(),
|
|
8455
|
+
applied: boolean(),
|
|
8456
|
+
refused: LedgerWalkRefusalSchema.nullable(),
|
|
8457
|
+
archiveSegments: number().int().nonnegative().nullable(),
|
|
8458
|
+
archiveBytes: number().int().nonnegative().nullable(),
|
|
8459
|
+
hoursClaimed: number().int().nonnegative(),
|
|
8460
|
+
hoursWalked: number().int().nonnegative(),
|
|
8461
|
+
hoursMissing: number().int().nonnegative(),
|
|
8462
|
+
/** `readdir` calls issued — the cost, stated in the unit that is paid. */
|
|
8463
|
+
listings: number().int().nonnegative(),
|
|
8464
|
+
segmentsClaimed: number().int().nonnegative(),
|
|
8465
|
+
ghostSegments: number().int().nonnegative(),
|
|
8466
|
+
ghostBytes: number().int().nonnegative(),
|
|
8467
|
+
ghostHoursWhole: number().int().nonnegative(),
|
|
8468
|
+
forgottenSegments: number().int().nonnegative(),
|
|
8469
|
+
forgottenBytes: number().int().nonnegative(),
|
|
8470
|
+
/** Files under a claimed hour that no durable row names. Never deleted. */
|
|
8471
|
+
orphanFiles: number().int().nonnegative(),
|
|
8472
|
+
orphanSample: array(string()).readonly(),
|
|
8473
|
+
hoursSkipped: number().int().nonnegative(),
|
|
8474
|
+
skippedByReason: LedgerWalkSkipCountsSchema,
|
|
8475
|
+
/** The walk stopped at its per-pass hour bound with claims unwalked. */
|
|
8476
|
+
bounded: boolean(),
|
|
8477
|
+
byDevice: array(LedgerWalkDeviceReportSchema).readonly()
|
|
8478
|
+
});
|
|
8380
8479
|
/** How many rows a media pass would still act on against a given target — the
|
|
8381
8480
|
* media lane's denominator AND its residue, from ONE derivation so the two can
|
|
8382
8481
|
* never disagree. `null` = the count could not be taken. */
|
|
@@ -18780,13 +18879,15 @@ var ListGroupsPageSchema = object({
|
|
|
18780
18879
|
groups: array(AnalyticsGroupRecordSchema).readonly(),
|
|
18781
18880
|
nextCursor: string().nullable()
|
|
18782
18881
|
});
|
|
18882
|
+
var KEY_EVENTS_DEFAULT_LIMIT = 50;
|
|
18883
|
+
var KEY_EVENTS_MAX_LIMIT = 200;
|
|
18783
18884
|
var KeyEventQueryInput = object({
|
|
18784
18885
|
deviceId: number(),
|
|
18785
18886
|
/** Window lower bound (track firstSeen ≥ since). */
|
|
18786
18887
|
since: number(),
|
|
18787
18888
|
/** Window upper bound (track firstSeen ≤ until). */
|
|
18788
18889
|
until: number(),
|
|
18789
|
-
limit: number().int().min(1).max(
|
|
18890
|
+
limit: number().int().min(1).max(KEY_EVENTS_MAX_LIMIT).default(KEY_EVENTS_DEFAULT_LIMIT),
|
|
18790
18891
|
/** Drop tracks scoring below this importance. */
|
|
18791
18892
|
minImportance: number().min(0).max(1).optional(),
|
|
18792
18893
|
/** Restrict to a single class (e.g. 'person'). */
|
|
@@ -18808,6 +18909,32 @@ var KeyEventSchema = object({
|
|
|
18808
18909
|
...TrackFlagFields,
|
|
18809
18910
|
...TrackRetrainFields
|
|
18810
18911
|
});
|
|
18912
|
+
/** `getKeyEvents`' window and filters, asked of a SET of cameras at once. */
|
|
18913
|
+
var KeyEventBatchQueryInput = object({
|
|
18914
|
+
deviceIds: array(number()).min(1).max(200),
|
|
18915
|
+
since: number(),
|
|
18916
|
+
until: number(),
|
|
18917
|
+
/** Applied PER CAMERA, exactly as `getKeyEvents.limit` is — never a total
|
|
18918
|
+
* across the set, which would let a busy camera starve a quiet one of its
|
|
18919
|
+
* rows and change what the merged feed contains. */
|
|
18920
|
+
limit: number().int().min(1).max(KEY_EVENTS_MAX_LIMIT).default(KEY_EVENTS_DEFAULT_LIMIT),
|
|
18921
|
+
minImportance: number().min(0).max(1).optional(),
|
|
18922
|
+
classFilter: string().optional()
|
|
18923
|
+
});
|
|
18924
|
+
/**
|
|
18925
|
+
* One camera's key events in a batch answer.
|
|
18926
|
+
*
|
|
18927
|
+
* The row exists for every requested id. `getKeyEvents` degrades to `[]` on
|
|
18928
|
+
* error rather than throwing, so a camera whose store read failed and one with
|
|
18929
|
+
* no events in the window were ALREADY indistinguishable per camera — the
|
|
18930
|
+
* batch does not make that worse, and the row keeps the deviceId the single
|
|
18931
|
+
* method's output never carried (the caller used to stamp it from the fan-out
|
|
18932
|
+
* key, which only worked because there was one query per camera).
|
|
18933
|
+
*/
|
|
18934
|
+
var KeyEventsForDeviceSchema = object({
|
|
18935
|
+
deviceId: number(),
|
|
18936
|
+
events: array(KeyEventSchema).readonly()
|
|
18937
|
+
});
|
|
18811
18938
|
object({
|
|
18812
18939
|
trackId: string(),
|
|
18813
18940
|
className: string(),
|
|
@@ -19077,7 +19204,7 @@ DeviceType.Camera, method(object({ deviceId: number() }), array(TrackSchema).rea
|
|
|
19077
19204
|
until: number().optional(),
|
|
19078
19205
|
kinds: array(string()).optional(),
|
|
19079
19206
|
limit: number().int().min(1).max(MAX_EVENT_QUERY_LIMIT).default(DEFAULT_EVENT_QUERY_LIMIT)
|
|
19080
|
-
}), array(SensorEventSchema).readonly()), method(KeyEventQueryInput, array(KeyEventSchema).readonly()), method(object({
|
|
19207
|
+
}), array(SensorEventSchema).readonly()), method(KeyEventQueryInput, array(KeyEventSchema).readonly()), method(KeyEventBatchQueryInput, array(KeyEventsForDeviceSchema).readonly()), method(object({
|
|
19081
19208
|
deviceId: number(),
|
|
19082
19209
|
since: number(),
|
|
19083
19210
|
until: number(),
|
|
@@ -26729,6 +26856,9 @@ method(object({
|
|
|
26729
26856
|
}), method(RelocateResidueInputSchema, RelocateResidueSchema, {
|
|
26730
26857
|
kind: "query",
|
|
26731
26858
|
auth: "admin"
|
|
26859
|
+
}), method(LedgerWalkInputSchema, LedgerWalkReportSchema, {
|
|
26860
|
+
kind: "mutation",
|
|
26861
|
+
auth: "admin"
|
|
26732
26862
|
}), method(object({ jobId: string() }), object({ cancelled: boolean() }), {
|
|
26733
26863
|
kind: "mutation",
|
|
26734
26864
|
auth: "admin"
|
|
@@ -27120,7 +27250,26 @@ var SceneMonitorStatusSchema = object({
|
|
|
27120
27250
|
monitors: array(SceneMonitorSchema),
|
|
27121
27251
|
lastFetchedAt: number()
|
|
27122
27252
|
});
|
|
27123
|
-
|
|
27253
|
+
/**
|
|
27254
|
+
* One camera's row in a `listScenesBatch` answer.
|
|
27255
|
+
*
|
|
27256
|
+
* `status` is NULLABLE and the nullability is the whole point. `scene-monitor`
|
|
27257
|
+
* is a `defaultActive` wrapper, so every camera is asked; a camera whose
|
|
27258
|
+
* provider is absent (pipeline-analytics not deployed, the post-processing node
|
|
27259
|
+
* down) cannot answer, and that is not the same fact as a camera with no scenes
|
|
27260
|
+
* configured. Fanned out per camera the difference was visible — one query
|
|
27261
|
+
* errored while the others resolved — and a batch that returned only the rows
|
|
27262
|
+
* it managed would have destroyed it, silently, by making an unreachable camera
|
|
27263
|
+
* indistinguishable from one that answered `monitors: []`.
|
|
27264
|
+
*
|
|
27265
|
+
* So: EVERY requested deviceId gets a row. `status: null` means "this camera
|
|
27266
|
+
* could not be read"; `status.monitors: []` means "read, and it has none".
|
|
27267
|
+
*/
|
|
27268
|
+
var SceneMonitorStatusForDeviceSchema = object({
|
|
27269
|
+
deviceId: number(),
|
|
27270
|
+
status: SceneMonitorStatusSchema.nullable()
|
|
27271
|
+
});
|
|
27272
|
+
DeviceType.Camera, method(object({ deviceId: number() }), SceneMonitorStatusSchema), method(object({ deviceIds: array(number()).min(1).max(200) }), array(SceneMonitorStatusForDeviceSchema).readonly()), method(object({
|
|
27124
27273
|
deviceId: number(),
|
|
27125
27274
|
label: string(),
|
|
27126
27275
|
roi: MaskRectShapeSchema,
|
|
@@ -28444,6 +28593,27 @@ var CameraOccupancySnapshotSchema = object({
|
|
|
28444
28593
|
stationaryObjects: array(StationaryObjectSchema).readonly().optional()
|
|
28445
28594
|
});
|
|
28446
28595
|
/**
|
|
28596
|
+
* One camera's row in a `getCurrentSnapshotBatch` answer.
|
|
28597
|
+
*
|
|
28598
|
+
* THREE outcomes, and the single-camera method could only express two of them
|
|
28599
|
+
* because `snapshot: null` was already spoken for:
|
|
28600
|
+
*
|
|
28601
|
+
* - `read: 'read'`, `snapshot` present — the live occupancy reading.
|
|
28602
|
+
* - `read: 'read'`, `snapshot: null` — read, and this camera has no reading
|
|
28603
|
+
* yet: no frame since boot, and no parked-object registry to hydrate from.
|
|
28604
|
+
* - `read: 'unreadable'` — the owner could not answer for this
|
|
28605
|
+
* camera. `snapshot` is null, and it does NOT mean "nothing parked here".
|
|
28606
|
+
*
|
|
28607
|
+
* Collapsing the last two is the failure this field exists to prevent: a
|
|
28608
|
+
* hydration that threw would otherwise render as an empty Stationary section,
|
|
28609
|
+
* which is a definite claim about a camera nobody could read.
|
|
28610
|
+
*/
|
|
28611
|
+
var CameraOccupancySnapshotForDeviceSchema = object({
|
|
28612
|
+
deviceId: number(),
|
|
28613
|
+
read: _enum(["read", "unreadable"]),
|
|
28614
|
+
snapshot: CameraOccupancySnapshotSchema.nullable()
|
|
28615
|
+
});
|
|
28616
|
+
/**
|
|
28447
28617
|
* Time-series resolution. The history methods return one bucket per
|
|
28448
28618
|
* step over the requested range. Smaller resolutions cost more
|
|
28449
28619
|
* memory + bandwidth; bound to discrete steps so caller cannot ask
|
|
@@ -28467,7 +28637,7 @@ var HistoryPointSchema = object({
|
|
|
28467
28637
|
/** Object count averaged over the bucket (rounded to nearest integer). */
|
|
28468
28638
|
count: number().int().nonnegative()
|
|
28469
28639
|
});
|
|
28470
|
-
DeviceType.Camera, method(object({ deviceId: number() }), CameraOccupancySnapshotSchema.nullable()), method(object({
|
|
28640
|
+
DeviceType.Camera, method(object({ deviceId: number() }), CameraOccupancySnapshotSchema.nullable()), method(object({ deviceIds: array(number()).min(1).max(200) }), array(CameraOccupancySnapshotForDeviceSchema).readonly()), method(object({
|
|
28471
28641
|
deviceId: number(),
|
|
28472
28642
|
zoneId: string(),
|
|
28473
28643
|
className: string().optional()
|
|
@@ -31772,6 +31942,12 @@ Object.freeze({
|
|
|
31772
31942
|
addonId: null,
|
|
31773
31943
|
access: "view"
|
|
31774
31944
|
},
|
|
31945
|
+
"pipelineAnalytics.getKeyEventsBatch": {
|
|
31946
|
+
capName: "pipeline-analytics",
|
|
31947
|
+
capScope: "device",
|
|
31948
|
+
addonId: null,
|
|
31949
|
+
access: "view"
|
|
31950
|
+
},
|
|
31775
31951
|
"pipelineAnalytics.getMotionEvents": {
|
|
31776
31952
|
capName: "pipeline-analytics",
|
|
31777
31953
|
capScope: "device",
|
|
@@ -32948,6 +33124,12 @@ Object.freeze({
|
|
|
32948
33124
|
addonId: null,
|
|
32949
33125
|
access: "view"
|
|
32950
33126
|
},
|
|
33127
|
+
"recording.reconcileLedgerAgainstDisk": {
|
|
33128
|
+
capName: "recording",
|
|
33129
|
+
capScope: "system",
|
|
33130
|
+
addonId: null,
|
|
33131
|
+
access: "create"
|
|
33132
|
+
},
|
|
32951
33133
|
"recording.refreshStorageLocationsForMigration": {
|
|
32952
33134
|
capName: "recording",
|
|
32953
33135
|
capScope: "system",
|
|
@@ -33074,6 +33256,12 @@ Object.freeze({
|
|
|
33074
33256
|
addonId: null,
|
|
33075
33257
|
access: "view"
|
|
33076
33258
|
},
|
|
33259
|
+
"sceneMonitor.listScenesBatch": {
|
|
33260
|
+
capName: "scene-monitor",
|
|
33261
|
+
capScope: "device",
|
|
33262
|
+
addonId: null,
|
|
33263
|
+
access: "view"
|
|
33264
|
+
},
|
|
33077
33265
|
"sceneMonitor.recheckNow": {
|
|
33078
33266
|
capName: "scene-monitor",
|
|
33079
33267
|
capScope: "device",
|
|
@@ -34430,6 +34618,12 @@ Object.freeze({
|
|
|
34430
34618
|
addonId: null,
|
|
34431
34619
|
access: "view"
|
|
34432
34620
|
},
|
|
34621
|
+
"zoneAnalytics.getCurrentSnapshotBatch": {
|
|
34622
|
+
capName: "zone-analytics",
|
|
34623
|
+
capScope: "device",
|
|
34624
|
+
addonId: null,
|
|
34625
|
+
access: "view"
|
|
34626
|
+
},
|
|
34433
34627
|
"zoneAnalytics.getUnzonedHistory": {
|
|
34434
34628
|
capName: "zone-analytics",
|
|
34435
34629
|
capScope: "device",
|
|
@@ -35434,6 +35628,11 @@ Object.freeze({
|
|
|
35434
35628
|
form: "single",
|
|
35435
35629
|
optional: false
|
|
35436
35630
|
}],
|
|
35631
|
+
"pipelineAnalytics.getKeyEventsBatch": [{
|
|
35632
|
+
name: "deviceIds",
|
|
35633
|
+
form: "array",
|
|
35634
|
+
optional: false
|
|
35635
|
+
}],
|
|
35437
35636
|
"pipelineAnalytics.getMotionEvents": [{
|
|
35438
35637
|
name: "deviceId",
|
|
35439
35638
|
form: "single",
|
|
@@ -35874,6 +36073,11 @@ Object.freeze({
|
|
|
35874
36073
|
form: "single",
|
|
35875
36074
|
optional: false
|
|
35876
36075
|
}],
|
|
36076
|
+
"recording.reconcileLedgerAgainstDisk": [{
|
|
36077
|
+
name: "deviceId",
|
|
36078
|
+
form: "single",
|
|
36079
|
+
optional: true
|
|
36080
|
+
}],
|
|
35877
36081
|
"recording.relocateFootage": [{
|
|
35878
36082
|
name: "deviceId",
|
|
35879
36083
|
form: "single",
|
|
@@ -35939,6 +36143,11 @@ Object.freeze({
|
|
|
35939
36143
|
form: "single",
|
|
35940
36144
|
optional: false
|
|
35941
36145
|
}],
|
|
36146
|
+
"sceneMonitor.listScenesBatch": [{
|
|
36147
|
+
name: "deviceIds",
|
|
36148
|
+
form: "array",
|
|
36149
|
+
optional: false
|
|
36150
|
+
}],
|
|
35942
36151
|
"sceneMonitor.recheckNow": [{
|
|
35943
36152
|
name: "deviceId",
|
|
35944
36153
|
form: "single",
|
|
@@ -36200,6 +36409,11 @@ Object.freeze({
|
|
|
36200
36409
|
form: "single",
|
|
36201
36410
|
optional: false
|
|
36202
36411
|
}],
|
|
36412
|
+
"zoneAnalytics.getCurrentSnapshotBatch": [{
|
|
36413
|
+
name: "deviceIds",
|
|
36414
|
+
form: "array",
|
|
36415
|
+
optional: false
|
|
36416
|
+
}],
|
|
36203
36417
|
"zoneAnalytics.getUnzonedHistory": [{
|
|
36204
36418
|
name: "deviceId",
|
|
36205
36419
|
form: "single",
|