@camstack/addon-decoder-nodeav 1.2.47 → 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 +290 -4
- package/dist/index.mjs +290 -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(),
|
|
@@ -18883,6 +19010,50 @@ var EventStoreFootprintSchema = object({
|
|
|
18883
19010
|
totalBytes: number().int(),
|
|
18884
19011
|
devices: array(EventStoreDeviceFootprintSchema).readonly()
|
|
18885
19012
|
});
|
|
19013
|
+
/** Event-media footprint for one {@link MediaFileKind}. */
|
|
19014
|
+
var EventMediaKindFootprintSchema = object({
|
|
19015
|
+
kind: MediaFileKindEnum,
|
|
19016
|
+
/** Media rows of this kind. */
|
|
19017
|
+
rows: number().int(),
|
|
19018
|
+
/** Bytes on disk held by those rows. */
|
|
19019
|
+
bytes: number().int()
|
|
19020
|
+
});
|
|
19021
|
+
/**
|
|
19022
|
+
* The media footprint broken down by KIND — the axis a deletion decision
|
|
19023
|
+
* actually turns on.
|
|
19024
|
+
*
|
|
19025
|
+
* A byte total says how much there is; it cannot say what is safe to remove.
|
|
19026
|
+
* The deletable set (the periodic `snapshot` filmstrip, the surplus per-edge
|
|
19027
|
+
* motion stills) and the keep set (`firstFrame`, rolling `lastFrame`,
|
|
19028
|
+
* `thumbnail`/`thumbnailSmall`, `keyFrame`/`keyFrameSmall`, the face/plate
|
|
19029
|
+
* buffers, gallery media, the CLIP `crop`) are distinguished by `kind` and by
|
|
19030
|
+
* nothing else, so sizing a deletion means summing per kind.
|
|
19031
|
+
*
|
|
19032
|
+
* ## Why `unaccounted*` exists
|
|
19033
|
+
*
|
|
19034
|
+
* `kinds` is enumerated from {@link MediaFileKindEnum} — the closed set the
|
|
19035
|
+
* writers use — and summed one kind at a time. `totalRows` / `totalBytes` come
|
|
19036
|
+
* from a SEPARATE unfiltered aggregate over the same rows, never from adding
|
|
19037
|
+
* `kinds` up. A row whose stored `kind` is not in the enum (written by a
|
|
19038
|
+
* retired code path, or by a version that knew a kind this one does not) would
|
|
19039
|
+
* otherwise vanish from the total silently, and an operator would delete
|
|
19040
|
+
* against a denominator smaller than the disk.
|
|
19041
|
+
*
|
|
19042
|
+
* `unaccountedRows` / `unaccountedBytes` are the difference. They are normally
|
|
19043
|
+
* zero; a non-zero value is a real finding and must be shown, not rounded away.
|
|
19044
|
+
*/
|
|
19045
|
+
var EventMediaKindBreakdownSchema = object({
|
|
19046
|
+
/** Every media row in scope, from one unfiltered aggregate. */
|
|
19047
|
+
totalRows: number().int(),
|
|
19048
|
+
/** Every media byte in scope, from that same aggregate. */
|
|
19049
|
+
totalBytes: number().int(),
|
|
19050
|
+
/** Per-kind footprint, ordered by bytes descending. */
|
|
19051
|
+
kinds: array(EventMediaKindFootprintSchema).readonly(),
|
|
19052
|
+
/** `totalRows` minus the summed `kinds` rows — see the schema note. */
|
|
19053
|
+
unaccountedRows: number().int(),
|
|
19054
|
+
/** `totalBytes` minus the summed `kinds` bytes — see the schema note. */
|
|
19055
|
+
unaccountedBytes: number().int()
|
|
19056
|
+
});
|
|
18886
19057
|
/** Per-kind counts returned by the event-prune / device-delete mutations. */
|
|
18887
19058
|
var EventPruneCountsSchema = object({
|
|
18888
19059
|
motion: number().int(),
|
|
@@ -19037,7 +19208,7 @@ DeviceType.Camera, method(object({ deviceId: number() }), array(TrackSchema).rea
|
|
|
19037
19208
|
until: number().optional(),
|
|
19038
19209
|
kinds: array(string()).optional(),
|
|
19039
19210
|
limit: number().int().min(1).max(MAX_EVENT_QUERY_LIMIT).default(DEFAULT_EVENT_QUERY_LIMIT)
|
|
19040
|
-
}), 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({
|
|
19041
19212
|
deviceId: number(),
|
|
19042
19213
|
since: number(),
|
|
19043
19214
|
until: number(),
|
|
@@ -19086,6 +19257,9 @@ DeviceType.Camera, method(object({ deviceId: number() }), array(TrackSchema).rea
|
|
|
19086
19257
|
}), TrackFlagsSchema, { kind: "mutation" }), method(object({}), EventStoreFootprintSchema, {
|
|
19087
19258
|
kind: "query",
|
|
19088
19259
|
auth: "admin"
|
|
19260
|
+
}), method(object({ deviceId: number().int().optional() }), EventMediaKindBreakdownSchema, {
|
|
19261
|
+
kind: "query",
|
|
19262
|
+
auth: "admin"
|
|
19089
19263
|
}), method(object({
|
|
19090
19264
|
olderThanMs: number(),
|
|
19091
19265
|
reason: OpsLogReasonSchema.optional()
|
|
@@ -21037,6 +21211,20 @@ method(object({
|
|
|
21037
21211
|
error: string().optional()
|
|
21038
21212
|
}), { auth: "admin" }), method(_void(), array(ProviderListEntrySchema).readonly()), method(object({
|
|
21039
21213
|
providerId: string(),
|
|
21214
|
+
/**
|
|
21215
|
+
* The location this config is an UNSAVED edit of, when there is one.
|
|
21216
|
+
*
|
|
21217
|
+
* `listLocations` replaces every declared secret with the redaction
|
|
21218
|
+
* sentinel, so the edit modal's form state holds the sentinel for any
|
|
21219
|
+
* credential the operator did not retype — and posting that here
|
|
21220
|
+
* without a way to resolve it makes the provider try to authenticate
|
|
21221
|
+
* as `__camstack_redacted__` and report the operator's own working
|
|
21222
|
+
* password as wrong. Given this id, the orchestrator restores each
|
|
21223
|
+
* sentinel from the stored config (same rule as `upsertLocation`)
|
|
21224
|
+
* before dispatching. Omitted by the "Add location" wizard, where
|
|
21225
|
+
* every value was typed just now and nothing is stored yet.
|
|
21226
|
+
*/
|
|
21227
|
+
locationId: string().optional(),
|
|
21040
21228
|
config: record(string(), unknown())
|
|
21041
21229
|
}), object({
|
|
21042
21230
|
ok: boolean(),
|
|
@@ -26672,6 +26860,9 @@ method(object({
|
|
|
26672
26860
|
}), method(RelocateResidueInputSchema, RelocateResidueSchema, {
|
|
26673
26861
|
kind: "query",
|
|
26674
26862
|
auth: "admin"
|
|
26863
|
+
}), method(LedgerWalkInputSchema, LedgerWalkReportSchema, {
|
|
26864
|
+
kind: "mutation",
|
|
26865
|
+
auth: "admin"
|
|
26675
26866
|
}), method(object({ jobId: string() }), object({ cancelled: boolean() }), {
|
|
26676
26867
|
kind: "mutation",
|
|
26677
26868
|
auth: "admin"
|
|
@@ -27063,7 +27254,26 @@ var SceneMonitorStatusSchema = object({
|
|
|
27063
27254
|
monitors: array(SceneMonitorSchema),
|
|
27064
27255
|
lastFetchedAt: number()
|
|
27065
27256
|
});
|
|
27066
|
-
|
|
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({
|
|
27067
27277
|
deviceId: number(),
|
|
27068
27278
|
label: string(),
|
|
27069
27279
|
roi: MaskRectShapeSchema,
|
|
@@ -28387,6 +28597,27 @@ var CameraOccupancySnapshotSchema = object({
|
|
|
28387
28597
|
stationaryObjects: array(StationaryObjectSchema).readonly().optional()
|
|
28388
28598
|
});
|
|
28389
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
|
+
/**
|
|
28390
28621
|
* Time-series resolution. The history methods return one bucket per
|
|
28391
28622
|
* step over the requested range. Smaller resolutions cost more
|
|
28392
28623
|
* memory + bandwidth; bound to discrete steps so caller cannot ask
|
|
@@ -28410,7 +28641,7 @@ var HistoryPointSchema = object({
|
|
|
28410
28641
|
/** Object count averaged over the bucket (rounded to nearest integer). */
|
|
28411
28642
|
count: number().int().nonnegative()
|
|
28412
28643
|
});
|
|
28413
|
-
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({
|
|
28414
28645
|
deviceId: number(),
|
|
28415
28646
|
zoneId: string(),
|
|
28416
28647
|
className: string().optional()
|
|
@@ -31691,6 +31922,12 @@ Object.freeze({
|
|
|
31691
31922
|
addonId: null,
|
|
31692
31923
|
access: "view"
|
|
31693
31924
|
},
|
|
31925
|
+
"pipelineAnalytics.getEventMediaFootprintByKind": {
|
|
31926
|
+
capName: "pipeline-analytics",
|
|
31927
|
+
capScope: "device",
|
|
31928
|
+
addonId: null,
|
|
31929
|
+
access: "view"
|
|
31930
|
+
},
|
|
31694
31931
|
"pipelineAnalytics.getEventStoreFootprint": {
|
|
31695
31932
|
capName: "pipeline-analytics",
|
|
31696
31933
|
capScope: "device",
|
|
@@ -31709,6 +31946,12 @@ Object.freeze({
|
|
|
31709
31946
|
addonId: null,
|
|
31710
31947
|
access: "view"
|
|
31711
31948
|
},
|
|
31949
|
+
"pipelineAnalytics.getKeyEventsBatch": {
|
|
31950
|
+
capName: "pipeline-analytics",
|
|
31951
|
+
capScope: "device",
|
|
31952
|
+
addonId: null,
|
|
31953
|
+
access: "view"
|
|
31954
|
+
},
|
|
31712
31955
|
"pipelineAnalytics.getMotionEvents": {
|
|
31713
31956
|
capName: "pipeline-analytics",
|
|
31714
31957
|
capScope: "device",
|
|
@@ -32885,6 +33128,12 @@ Object.freeze({
|
|
|
32885
33128
|
addonId: null,
|
|
32886
33129
|
access: "view"
|
|
32887
33130
|
},
|
|
33131
|
+
"recording.reconcileLedgerAgainstDisk": {
|
|
33132
|
+
capName: "recording",
|
|
33133
|
+
capScope: "system",
|
|
33134
|
+
addonId: null,
|
|
33135
|
+
access: "create"
|
|
33136
|
+
},
|
|
32888
33137
|
"recording.refreshStorageLocationsForMigration": {
|
|
32889
33138
|
capName: "recording",
|
|
32890
33139
|
capScope: "system",
|
|
@@ -33011,6 +33260,12 @@ Object.freeze({
|
|
|
33011
33260
|
addonId: null,
|
|
33012
33261
|
access: "view"
|
|
33013
33262
|
},
|
|
33263
|
+
"sceneMonitor.listScenesBatch": {
|
|
33264
|
+
capName: "scene-monitor",
|
|
33265
|
+
capScope: "device",
|
|
33266
|
+
addonId: null,
|
|
33267
|
+
access: "view"
|
|
33268
|
+
},
|
|
33014
33269
|
"sceneMonitor.recheckNow": {
|
|
33015
33270
|
capName: "scene-monitor",
|
|
33016
33271
|
capScope: "device",
|
|
@@ -34367,6 +34622,12 @@ Object.freeze({
|
|
|
34367
34622
|
addonId: null,
|
|
34368
34623
|
access: "view"
|
|
34369
34624
|
},
|
|
34625
|
+
"zoneAnalytics.getCurrentSnapshotBatch": {
|
|
34626
|
+
capName: "zone-analytics",
|
|
34627
|
+
capScope: "device",
|
|
34628
|
+
addonId: null,
|
|
34629
|
+
access: "view"
|
|
34630
|
+
},
|
|
34370
34631
|
"zoneAnalytics.getUnzonedHistory": {
|
|
34371
34632
|
capName: "zone-analytics",
|
|
34372
34633
|
capScope: "device",
|
|
@@ -35356,6 +35617,11 @@ Object.freeze({
|
|
|
35356
35617
|
form: "single",
|
|
35357
35618
|
optional: false
|
|
35358
35619
|
}],
|
|
35620
|
+
"pipelineAnalytics.getEventMediaFootprintByKind": [{
|
|
35621
|
+
name: "deviceId",
|
|
35622
|
+
form: "single",
|
|
35623
|
+
optional: true
|
|
35624
|
+
}],
|
|
35359
35625
|
"pipelineAnalytics.getGroup": [{
|
|
35360
35626
|
name: "deviceId",
|
|
35361
35627
|
form: "single",
|
|
@@ -35366,6 +35632,11 @@ Object.freeze({
|
|
|
35366
35632
|
form: "single",
|
|
35367
35633
|
optional: false
|
|
35368
35634
|
}],
|
|
35635
|
+
"pipelineAnalytics.getKeyEventsBatch": [{
|
|
35636
|
+
name: "deviceIds",
|
|
35637
|
+
form: "array",
|
|
35638
|
+
optional: false
|
|
35639
|
+
}],
|
|
35369
35640
|
"pipelineAnalytics.getMotionEvents": [{
|
|
35370
35641
|
name: "deviceId",
|
|
35371
35642
|
form: "single",
|
|
@@ -35806,6 +36077,11 @@ Object.freeze({
|
|
|
35806
36077
|
form: "single",
|
|
35807
36078
|
optional: false
|
|
35808
36079
|
}],
|
|
36080
|
+
"recording.reconcileLedgerAgainstDisk": [{
|
|
36081
|
+
name: "deviceId",
|
|
36082
|
+
form: "single",
|
|
36083
|
+
optional: true
|
|
36084
|
+
}],
|
|
35809
36085
|
"recording.relocateFootage": [{
|
|
35810
36086
|
name: "deviceId",
|
|
35811
36087
|
form: "single",
|
|
@@ -35871,6 +36147,11 @@ Object.freeze({
|
|
|
35871
36147
|
form: "single",
|
|
35872
36148
|
optional: false
|
|
35873
36149
|
}],
|
|
36150
|
+
"sceneMonitor.listScenesBatch": [{
|
|
36151
|
+
name: "deviceIds",
|
|
36152
|
+
form: "array",
|
|
36153
|
+
optional: false
|
|
36154
|
+
}],
|
|
35874
36155
|
"sceneMonitor.recheckNow": [{
|
|
35875
36156
|
name: "deviceId",
|
|
35876
36157
|
form: "single",
|
|
@@ -36132,6 +36413,11 @@ Object.freeze({
|
|
|
36132
36413
|
form: "single",
|
|
36133
36414
|
optional: false
|
|
36134
36415
|
}],
|
|
36416
|
+
"zoneAnalytics.getCurrentSnapshotBatch": [{
|
|
36417
|
+
name: "deviceIds",
|
|
36418
|
+
form: "array",
|
|
36419
|
+
optional: false
|
|
36420
|
+
}],
|
|
36135
36421
|
"zoneAnalytics.getUnzonedHistory": [{
|
|
36136
36422
|
name: "deviceId",
|
|
36137
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(),
|
|
@@ -18879,6 +19006,50 @@ var EventStoreFootprintSchema = object({
|
|
|
18879
19006
|
totalBytes: number().int(),
|
|
18880
19007
|
devices: array(EventStoreDeviceFootprintSchema).readonly()
|
|
18881
19008
|
});
|
|
19009
|
+
/** Event-media footprint for one {@link MediaFileKind}. */
|
|
19010
|
+
var EventMediaKindFootprintSchema = object({
|
|
19011
|
+
kind: MediaFileKindEnum,
|
|
19012
|
+
/** Media rows of this kind. */
|
|
19013
|
+
rows: number().int(),
|
|
19014
|
+
/** Bytes on disk held by those rows. */
|
|
19015
|
+
bytes: number().int()
|
|
19016
|
+
});
|
|
19017
|
+
/**
|
|
19018
|
+
* The media footprint broken down by KIND — the axis a deletion decision
|
|
19019
|
+
* actually turns on.
|
|
19020
|
+
*
|
|
19021
|
+
* A byte total says how much there is; it cannot say what is safe to remove.
|
|
19022
|
+
* The deletable set (the periodic `snapshot` filmstrip, the surplus per-edge
|
|
19023
|
+
* motion stills) and the keep set (`firstFrame`, rolling `lastFrame`,
|
|
19024
|
+
* `thumbnail`/`thumbnailSmall`, `keyFrame`/`keyFrameSmall`, the face/plate
|
|
19025
|
+
* buffers, gallery media, the CLIP `crop`) are distinguished by `kind` and by
|
|
19026
|
+
* nothing else, so sizing a deletion means summing per kind.
|
|
19027
|
+
*
|
|
19028
|
+
* ## Why `unaccounted*` exists
|
|
19029
|
+
*
|
|
19030
|
+
* `kinds` is enumerated from {@link MediaFileKindEnum} — the closed set the
|
|
19031
|
+
* writers use — and summed one kind at a time. `totalRows` / `totalBytes` come
|
|
19032
|
+
* from a SEPARATE unfiltered aggregate over the same rows, never from adding
|
|
19033
|
+
* `kinds` up. A row whose stored `kind` is not in the enum (written by a
|
|
19034
|
+
* retired code path, or by a version that knew a kind this one does not) would
|
|
19035
|
+
* otherwise vanish from the total silently, and an operator would delete
|
|
19036
|
+
* against a denominator smaller than the disk.
|
|
19037
|
+
*
|
|
19038
|
+
* `unaccountedRows` / `unaccountedBytes` are the difference. They are normally
|
|
19039
|
+
* zero; a non-zero value is a real finding and must be shown, not rounded away.
|
|
19040
|
+
*/
|
|
19041
|
+
var EventMediaKindBreakdownSchema = object({
|
|
19042
|
+
/** Every media row in scope, from one unfiltered aggregate. */
|
|
19043
|
+
totalRows: number().int(),
|
|
19044
|
+
/** Every media byte in scope, from that same aggregate. */
|
|
19045
|
+
totalBytes: number().int(),
|
|
19046
|
+
/** Per-kind footprint, ordered by bytes descending. */
|
|
19047
|
+
kinds: array(EventMediaKindFootprintSchema).readonly(),
|
|
19048
|
+
/** `totalRows` minus the summed `kinds` rows — see the schema note. */
|
|
19049
|
+
unaccountedRows: number().int(),
|
|
19050
|
+
/** `totalBytes` minus the summed `kinds` bytes — see the schema note. */
|
|
19051
|
+
unaccountedBytes: number().int()
|
|
19052
|
+
});
|
|
18882
19053
|
/** Per-kind counts returned by the event-prune / device-delete mutations. */
|
|
18883
19054
|
var EventPruneCountsSchema = object({
|
|
18884
19055
|
motion: number().int(),
|
|
@@ -19033,7 +19204,7 @@ DeviceType.Camera, method(object({ deviceId: number() }), array(TrackSchema).rea
|
|
|
19033
19204
|
until: number().optional(),
|
|
19034
19205
|
kinds: array(string()).optional(),
|
|
19035
19206
|
limit: number().int().min(1).max(MAX_EVENT_QUERY_LIMIT).default(DEFAULT_EVENT_QUERY_LIMIT)
|
|
19036
|
-
}), 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({
|
|
19037
19208
|
deviceId: number(),
|
|
19038
19209
|
since: number(),
|
|
19039
19210
|
until: number(),
|
|
@@ -19082,6 +19253,9 @@ DeviceType.Camera, method(object({ deviceId: number() }), array(TrackSchema).rea
|
|
|
19082
19253
|
}), TrackFlagsSchema, { kind: "mutation" }), method(object({}), EventStoreFootprintSchema, {
|
|
19083
19254
|
kind: "query",
|
|
19084
19255
|
auth: "admin"
|
|
19256
|
+
}), method(object({ deviceId: number().int().optional() }), EventMediaKindBreakdownSchema, {
|
|
19257
|
+
kind: "query",
|
|
19258
|
+
auth: "admin"
|
|
19085
19259
|
}), method(object({
|
|
19086
19260
|
olderThanMs: number(),
|
|
19087
19261
|
reason: OpsLogReasonSchema.optional()
|
|
@@ -21033,6 +21207,20 @@ method(object({
|
|
|
21033
21207
|
error: string().optional()
|
|
21034
21208
|
}), { auth: "admin" }), method(_void(), array(ProviderListEntrySchema).readonly()), method(object({
|
|
21035
21209
|
providerId: string(),
|
|
21210
|
+
/**
|
|
21211
|
+
* The location this config is an UNSAVED edit of, when there is one.
|
|
21212
|
+
*
|
|
21213
|
+
* `listLocations` replaces every declared secret with the redaction
|
|
21214
|
+
* sentinel, so the edit modal's form state holds the sentinel for any
|
|
21215
|
+
* credential the operator did not retype — and posting that here
|
|
21216
|
+
* without a way to resolve it makes the provider try to authenticate
|
|
21217
|
+
* as `__camstack_redacted__` and report the operator's own working
|
|
21218
|
+
* password as wrong. Given this id, the orchestrator restores each
|
|
21219
|
+
* sentinel from the stored config (same rule as `upsertLocation`)
|
|
21220
|
+
* before dispatching. Omitted by the "Add location" wizard, where
|
|
21221
|
+
* every value was typed just now and nothing is stored yet.
|
|
21222
|
+
*/
|
|
21223
|
+
locationId: string().optional(),
|
|
21036
21224
|
config: record(string(), unknown())
|
|
21037
21225
|
}), object({
|
|
21038
21226
|
ok: boolean(),
|
|
@@ -26668,6 +26856,9 @@ method(object({
|
|
|
26668
26856
|
}), method(RelocateResidueInputSchema, RelocateResidueSchema, {
|
|
26669
26857
|
kind: "query",
|
|
26670
26858
|
auth: "admin"
|
|
26859
|
+
}), method(LedgerWalkInputSchema, LedgerWalkReportSchema, {
|
|
26860
|
+
kind: "mutation",
|
|
26861
|
+
auth: "admin"
|
|
26671
26862
|
}), method(object({ jobId: string() }), object({ cancelled: boolean() }), {
|
|
26672
26863
|
kind: "mutation",
|
|
26673
26864
|
auth: "admin"
|
|
@@ -27059,7 +27250,26 @@ var SceneMonitorStatusSchema = object({
|
|
|
27059
27250
|
monitors: array(SceneMonitorSchema),
|
|
27060
27251
|
lastFetchedAt: number()
|
|
27061
27252
|
});
|
|
27062
|
-
|
|
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({
|
|
27063
27273
|
deviceId: number(),
|
|
27064
27274
|
label: string(),
|
|
27065
27275
|
roi: MaskRectShapeSchema,
|
|
@@ -28383,6 +28593,27 @@ var CameraOccupancySnapshotSchema = object({
|
|
|
28383
28593
|
stationaryObjects: array(StationaryObjectSchema).readonly().optional()
|
|
28384
28594
|
});
|
|
28385
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
|
+
/**
|
|
28386
28617
|
* Time-series resolution. The history methods return one bucket per
|
|
28387
28618
|
* step over the requested range. Smaller resolutions cost more
|
|
28388
28619
|
* memory + bandwidth; bound to discrete steps so caller cannot ask
|
|
@@ -28406,7 +28637,7 @@ var HistoryPointSchema = object({
|
|
|
28406
28637
|
/** Object count averaged over the bucket (rounded to nearest integer). */
|
|
28407
28638
|
count: number().int().nonnegative()
|
|
28408
28639
|
});
|
|
28409
|
-
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({
|
|
28410
28641
|
deviceId: number(),
|
|
28411
28642
|
zoneId: string(),
|
|
28412
28643
|
className: string().optional()
|
|
@@ -31687,6 +31918,12 @@ Object.freeze({
|
|
|
31687
31918
|
addonId: null,
|
|
31688
31919
|
access: "view"
|
|
31689
31920
|
},
|
|
31921
|
+
"pipelineAnalytics.getEventMediaFootprintByKind": {
|
|
31922
|
+
capName: "pipeline-analytics",
|
|
31923
|
+
capScope: "device",
|
|
31924
|
+
addonId: null,
|
|
31925
|
+
access: "view"
|
|
31926
|
+
},
|
|
31690
31927
|
"pipelineAnalytics.getEventStoreFootprint": {
|
|
31691
31928
|
capName: "pipeline-analytics",
|
|
31692
31929
|
capScope: "device",
|
|
@@ -31705,6 +31942,12 @@ Object.freeze({
|
|
|
31705
31942
|
addonId: null,
|
|
31706
31943
|
access: "view"
|
|
31707
31944
|
},
|
|
31945
|
+
"pipelineAnalytics.getKeyEventsBatch": {
|
|
31946
|
+
capName: "pipeline-analytics",
|
|
31947
|
+
capScope: "device",
|
|
31948
|
+
addonId: null,
|
|
31949
|
+
access: "view"
|
|
31950
|
+
},
|
|
31708
31951
|
"pipelineAnalytics.getMotionEvents": {
|
|
31709
31952
|
capName: "pipeline-analytics",
|
|
31710
31953
|
capScope: "device",
|
|
@@ -32881,6 +33124,12 @@ Object.freeze({
|
|
|
32881
33124
|
addonId: null,
|
|
32882
33125
|
access: "view"
|
|
32883
33126
|
},
|
|
33127
|
+
"recording.reconcileLedgerAgainstDisk": {
|
|
33128
|
+
capName: "recording",
|
|
33129
|
+
capScope: "system",
|
|
33130
|
+
addonId: null,
|
|
33131
|
+
access: "create"
|
|
33132
|
+
},
|
|
32884
33133
|
"recording.refreshStorageLocationsForMigration": {
|
|
32885
33134
|
capName: "recording",
|
|
32886
33135
|
capScope: "system",
|
|
@@ -33007,6 +33256,12 @@ Object.freeze({
|
|
|
33007
33256
|
addonId: null,
|
|
33008
33257
|
access: "view"
|
|
33009
33258
|
},
|
|
33259
|
+
"sceneMonitor.listScenesBatch": {
|
|
33260
|
+
capName: "scene-monitor",
|
|
33261
|
+
capScope: "device",
|
|
33262
|
+
addonId: null,
|
|
33263
|
+
access: "view"
|
|
33264
|
+
},
|
|
33010
33265
|
"sceneMonitor.recheckNow": {
|
|
33011
33266
|
capName: "scene-monitor",
|
|
33012
33267
|
capScope: "device",
|
|
@@ -34363,6 +34618,12 @@ Object.freeze({
|
|
|
34363
34618
|
addonId: null,
|
|
34364
34619
|
access: "view"
|
|
34365
34620
|
},
|
|
34621
|
+
"zoneAnalytics.getCurrentSnapshotBatch": {
|
|
34622
|
+
capName: "zone-analytics",
|
|
34623
|
+
capScope: "device",
|
|
34624
|
+
addonId: null,
|
|
34625
|
+
access: "view"
|
|
34626
|
+
},
|
|
34366
34627
|
"zoneAnalytics.getUnzonedHistory": {
|
|
34367
34628
|
capName: "zone-analytics",
|
|
34368
34629
|
capScope: "device",
|
|
@@ -35352,6 +35613,11 @@ Object.freeze({
|
|
|
35352
35613
|
form: "single",
|
|
35353
35614
|
optional: false
|
|
35354
35615
|
}],
|
|
35616
|
+
"pipelineAnalytics.getEventMediaFootprintByKind": [{
|
|
35617
|
+
name: "deviceId",
|
|
35618
|
+
form: "single",
|
|
35619
|
+
optional: true
|
|
35620
|
+
}],
|
|
35355
35621
|
"pipelineAnalytics.getGroup": [{
|
|
35356
35622
|
name: "deviceId",
|
|
35357
35623
|
form: "single",
|
|
@@ -35362,6 +35628,11 @@ Object.freeze({
|
|
|
35362
35628
|
form: "single",
|
|
35363
35629
|
optional: false
|
|
35364
35630
|
}],
|
|
35631
|
+
"pipelineAnalytics.getKeyEventsBatch": [{
|
|
35632
|
+
name: "deviceIds",
|
|
35633
|
+
form: "array",
|
|
35634
|
+
optional: false
|
|
35635
|
+
}],
|
|
35365
35636
|
"pipelineAnalytics.getMotionEvents": [{
|
|
35366
35637
|
name: "deviceId",
|
|
35367
35638
|
form: "single",
|
|
@@ -35802,6 +36073,11 @@ Object.freeze({
|
|
|
35802
36073
|
form: "single",
|
|
35803
36074
|
optional: false
|
|
35804
36075
|
}],
|
|
36076
|
+
"recording.reconcileLedgerAgainstDisk": [{
|
|
36077
|
+
name: "deviceId",
|
|
36078
|
+
form: "single",
|
|
36079
|
+
optional: true
|
|
36080
|
+
}],
|
|
35805
36081
|
"recording.relocateFootage": [{
|
|
35806
36082
|
name: "deviceId",
|
|
35807
36083
|
form: "single",
|
|
@@ -35867,6 +36143,11 @@ Object.freeze({
|
|
|
35867
36143
|
form: "single",
|
|
35868
36144
|
optional: false
|
|
35869
36145
|
}],
|
|
36146
|
+
"sceneMonitor.listScenesBatch": [{
|
|
36147
|
+
name: "deviceIds",
|
|
36148
|
+
form: "array",
|
|
36149
|
+
optional: false
|
|
36150
|
+
}],
|
|
35870
36151
|
"sceneMonitor.recheckNow": [{
|
|
35871
36152
|
name: "deviceId",
|
|
35872
36153
|
form: "single",
|
|
@@ -36128,6 +36409,11 @@ Object.freeze({
|
|
|
36128
36409
|
form: "single",
|
|
36129
36410
|
optional: false
|
|
36130
36411
|
}],
|
|
36412
|
+
"zoneAnalytics.getCurrentSnapshotBatch": [{
|
|
36413
|
+
name: "deviceIds",
|
|
36414
|
+
form: "array",
|
|
36415
|
+
optional: false
|
|
36416
|
+
}],
|
|
36131
36417
|
"zoneAnalytics.getUnzonedHistory": [{
|
|
36132
36418
|
name: "deviceId",
|
|
36133
36419
|
form: "single",
|