@camstack/addon-decoder-ffmpeg 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
|
@@ -8019,6 +8019,20 @@ var RelocateJobSchema = object({
|
|
|
8019
8019
|
* in its row, not in its name, so `MediaRelocateEngine` never reconciles one.
|
|
8020
8020
|
*/
|
|
8021
8021
|
rowsReconciled: number().int().nonnegative().optional(),
|
|
8022
|
+
/**
|
|
8023
|
+
* Rows this run FORGOT because the file they name is not on disk.
|
|
8024
|
+
*
|
|
8025
|
+
* The mover derived the path from the row's own fields and `stat`ed it; an
|
|
8026
|
+
* ENOENT there is a per-path confirmation that the segment is gone (D296),
|
|
8027
|
+
* and the durable row is dropped through the same channel eviction uses. It
|
|
8028
|
+
* is reported for the same reason `rowsReconciled` is: this is a durable
|
|
8029
|
+
* mutation nobody asked for, and a migration that quietly erases hour rows is
|
|
8030
|
+
* the same failure as one that quietly skips them (D295).
|
|
8031
|
+
*
|
|
8032
|
+
* The production drain of 2026-08-30 would have reported 11 074 here — the
|
|
8033
|
+
* ledger claimed 5.65 GB of footage that no longer existed.
|
|
8034
|
+
*/
|
|
8035
|
+
rowsForgotten: number().int().nonnegative().optional(),
|
|
8022
8036
|
startedAt: number(),
|
|
8023
8037
|
finishedAt: number().nullable(),
|
|
8024
8038
|
error: string().nullable()
|
|
@@ -8382,6 +8396,91 @@ var RelocateResidueSchema = object({
|
|
|
8382
8396
|
segments: number().int().nonnegative(),
|
|
8383
8397
|
bytes: number().int().nonnegative()
|
|
8384
8398
|
}).nullable();
|
|
8399
|
+
/**
|
|
8400
|
+
* Ask one location whether its durable hour rows describe the disk — the walk
|
|
8401
|
+
* (D319).
|
|
8402
|
+
*
|
|
8403
|
+
* `apply` DEFAULTS TO FALSE and that default is the product: the operator's
|
|
8404
|
+
* missing tool is the question, and the dry run is how they sanity-check the
|
|
8405
|
+
* destructive run before authorising it.
|
|
8406
|
+
*/
|
|
8407
|
+
var LedgerWalkInputSchema = object({
|
|
8408
|
+
locationId: string().min(1),
|
|
8409
|
+
/** Forget the confirmed-absent rows, rather than only counting them. */
|
|
8410
|
+
apply: boolean().optional(),
|
|
8411
|
+
/** Narrow to one camera. */
|
|
8412
|
+
deviceId: number().int().positive().optional(),
|
|
8413
|
+
/** Narrow to these recording profiles; empty/absent = every profile. */
|
|
8414
|
+
profiles: array(string().min(1)).optional()
|
|
8415
|
+
});
|
|
8416
|
+
/** Why a whole walk did nothing. Every one leaves the ledger untouched. */
|
|
8417
|
+
var LedgerWalkRefusalSchema = _enum([
|
|
8418
|
+
"location-unknown",
|
|
8419
|
+
"source-writable",
|
|
8420
|
+
"no-ledger",
|
|
8421
|
+
"archive-unreadable",
|
|
8422
|
+
"anchor-absent",
|
|
8423
|
+
"anchor-unreadable",
|
|
8424
|
+
"anchor-moved"
|
|
8425
|
+
]);
|
|
8426
|
+
_enum([
|
|
8427
|
+
"live-tail",
|
|
8428
|
+
"listing-error",
|
|
8429
|
+
"path-mismatch",
|
|
8430
|
+
"durable-refused"
|
|
8431
|
+
]);
|
|
8432
|
+
/** Every skip reason, always present, always a number — so a reason that never
|
|
8433
|
+
* fired reports as zero rather than absent and the report shape is constant
|
|
8434
|
+
* between passes. Spelled out rather than `z.record` for exactly that. */
|
|
8435
|
+
var LedgerWalkSkipCountsSchema = object({
|
|
8436
|
+
"live-tail": number().int().nonnegative(),
|
|
8437
|
+
"listing-error": number().int().nonnegative(),
|
|
8438
|
+
"path-mismatch": number().int().nonnegative(),
|
|
8439
|
+
"durable-refused": number().int().nonnegative()
|
|
8440
|
+
});
|
|
8441
|
+
/** One camera's share of a walk, so a report names cameras and not rows. */
|
|
8442
|
+
var LedgerWalkDeviceReportSchema = object({
|
|
8443
|
+
deviceId: number().int(),
|
|
8444
|
+
hoursWalked: number().int().nonnegative(),
|
|
8445
|
+
hoursMissing: number().int().nonnegative(),
|
|
8446
|
+
ghostSegments: number().int().nonnegative(),
|
|
8447
|
+
ghostBytes: number().int().nonnegative(),
|
|
8448
|
+
forgottenSegments: number().int().nonnegative(),
|
|
8449
|
+
orphanFiles: number().int().nonnegative()
|
|
8450
|
+
});
|
|
8451
|
+
/**
|
|
8452
|
+
* What one walk claimed, listed, found and (only when armed) forgot.
|
|
8453
|
+
*
|
|
8454
|
+
* `archiveSegments` is the **M** and `segmentsClaimed` the **N** (D295), so a
|
|
8455
|
+
* walk that saw a fraction of the location is visible in its own report rather
|
|
8456
|
+
* than in the absence of one.
|
|
8457
|
+
*/
|
|
8458
|
+
var LedgerWalkReportSchema = object({
|
|
8459
|
+
locationId: string(),
|
|
8460
|
+
applied: boolean(),
|
|
8461
|
+
refused: LedgerWalkRefusalSchema.nullable(),
|
|
8462
|
+
archiveSegments: number().int().nonnegative().nullable(),
|
|
8463
|
+
archiveBytes: number().int().nonnegative().nullable(),
|
|
8464
|
+
hoursClaimed: number().int().nonnegative(),
|
|
8465
|
+
hoursWalked: number().int().nonnegative(),
|
|
8466
|
+
hoursMissing: number().int().nonnegative(),
|
|
8467
|
+
/** `readdir` calls issued — the cost, stated in the unit that is paid. */
|
|
8468
|
+
listings: number().int().nonnegative(),
|
|
8469
|
+
segmentsClaimed: number().int().nonnegative(),
|
|
8470
|
+
ghostSegments: number().int().nonnegative(),
|
|
8471
|
+
ghostBytes: number().int().nonnegative(),
|
|
8472
|
+
ghostHoursWhole: number().int().nonnegative(),
|
|
8473
|
+
forgottenSegments: number().int().nonnegative(),
|
|
8474
|
+
forgottenBytes: number().int().nonnegative(),
|
|
8475
|
+
/** Files under a claimed hour that no durable row names. Never deleted. */
|
|
8476
|
+
orphanFiles: number().int().nonnegative(),
|
|
8477
|
+
orphanSample: array(string()).readonly(),
|
|
8478
|
+
hoursSkipped: number().int().nonnegative(),
|
|
8479
|
+
skippedByReason: LedgerWalkSkipCountsSchema,
|
|
8480
|
+
/** The walk stopped at its per-pass hour bound with claims unwalked. */
|
|
8481
|
+
bounded: boolean(),
|
|
8482
|
+
byDevice: array(LedgerWalkDeviceReportSchema).readonly()
|
|
8483
|
+
});
|
|
8385
8484
|
/** How many rows a media pass would still act on against a given target — the
|
|
8386
8485
|
* media lane's denominator AND its residue, from ONE derivation so the two can
|
|
8387
8486
|
* never disagree. `null` = the count could not be taken. */
|
|
@@ -18785,13 +18884,15 @@ var ListGroupsPageSchema = object({
|
|
|
18785
18884
|
groups: array(AnalyticsGroupRecordSchema).readonly(),
|
|
18786
18885
|
nextCursor: string().nullable()
|
|
18787
18886
|
});
|
|
18887
|
+
var KEY_EVENTS_DEFAULT_LIMIT = 50;
|
|
18888
|
+
var KEY_EVENTS_MAX_LIMIT = 200;
|
|
18788
18889
|
var KeyEventQueryInput = object({
|
|
18789
18890
|
deviceId: number(),
|
|
18790
18891
|
/** Window lower bound (track firstSeen ≥ since). */
|
|
18791
18892
|
since: number(),
|
|
18792
18893
|
/** Window upper bound (track firstSeen ≤ until). */
|
|
18793
18894
|
until: number(),
|
|
18794
|
-
limit: number().int().min(1).max(
|
|
18895
|
+
limit: number().int().min(1).max(KEY_EVENTS_MAX_LIMIT).default(KEY_EVENTS_DEFAULT_LIMIT),
|
|
18795
18896
|
/** Drop tracks scoring below this importance. */
|
|
18796
18897
|
minImportance: number().min(0).max(1).optional(),
|
|
18797
18898
|
/** Restrict to a single class (e.g. 'person'). */
|
|
@@ -18813,6 +18914,32 @@ var KeyEventSchema = object({
|
|
|
18813
18914
|
...TrackFlagFields,
|
|
18814
18915
|
...TrackRetrainFields
|
|
18815
18916
|
});
|
|
18917
|
+
/** `getKeyEvents`' window and filters, asked of a SET of cameras at once. */
|
|
18918
|
+
var KeyEventBatchQueryInput = object({
|
|
18919
|
+
deviceIds: array(number()).min(1).max(200),
|
|
18920
|
+
since: number(),
|
|
18921
|
+
until: number(),
|
|
18922
|
+
/** Applied PER CAMERA, exactly as `getKeyEvents.limit` is — never a total
|
|
18923
|
+
* across the set, which would let a busy camera starve a quiet one of its
|
|
18924
|
+
* rows and change what the merged feed contains. */
|
|
18925
|
+
limit: number().int().min(1).max(KEY_EVENTS_MAX_LIMIT).default(KEY_EVENTS_DEFAULT_LIMIT),
|
|
18926
|
+
minImportance: number().min(0).max(1).optional(),
|
|
18927
|
+
classFilter: string().optional()
|
|
18928
|
+
});
|
|
18929
|
+
/**
|
|
18930
|
+
* One camera's key events in a batch answer.
|
|
18931
|
+
*
|
|
18932
|
+
* The row exists for every requested id. `getKeyEvents` degrades to `[]` on
|
|
18933
|
+
* error rather than throwing, so a camera whose store read failed and one with
|
|
18934
|
+
* no events in the window were ALREADY indistinguishable per camera — the
|
|
18935
|
+
* batch does not make that worse, and the row keeps the deviceId the single
|
|
18936
|
+
* method's output never carried (the caller used to stamp it from the fan-out
|
|
18937
|
+
* key, which only worked because there was one query per camera).
|
|
18938
|
+
*/
|
|
18939
|
+
var KeyEventsForDeviceSchema = object({
|
|
18940
|
+
deviceId: number(),
|
|
18941
|
+
events: array(KeyEventSchema).readonly()
|
|
18942
|
+
});
|
|
18816
18943
|
object({
|
|
18817
18944
|
trackId: string(),
|
|
18818
18945
|
className: string(),
|
|
@@ -18884,6 +19011,50 @@ var EventStoreFootprintSchema = object({
|
|
|
18884
19011
|
totalBytes: number().int(),
|
|
18885
19012
|
devices: array(EventStoreDeviceFootprintSchema).readonly()
|
|
18886
19013
|
});
|
|
19014
|
+
/** Event-media footprint for one {@link MediaFileKind}. */
|
|
19015
|
+
var EventMediaKindFootprintSchema = object({
|
|
19016
|
+
kind: MediaFileKindEnum,
|
|
19017
|
+
/** Media rows of this kind. */
|
|
19018
|
+
rows: number().int(),
|
|
19019
|
+
/** Bytes on disk held by those rows. */
|
|
19020
|
+
bytes: number().int()
|
|
19021
|
+
});
|
|
19022
|
+
/**
|
|
19023
|
+
* The media footprint broken down by KIND — the axis a deletion decision
|
|
19024
|
+
* actually turns on.
|
|
19025
|
+
*
|
|
19026
|
+
* A byte total says how much there is; it cannot say what is safe to remove.
|
|
19027
|
+
* The deletable set (the periodic `snapshot` filmstrip, the surplus per-edge
|
|
19028
|
+
* motion stills) and the keep set (`firstFrame`, rolling `lastFrame`,
|
|
19029
|
+
* `thumbnail`/`thumbnailSmall`, `keyFrame`/`keyFrameSmall`, the face/plate
|
|
19030
|
+
* buffers, gallery media, the CLIP `crop`) are distinguished by `kind` and by
|
|
19031
|
+
* nothing else, so sizing a deletion means summing per kind.
|
|
19032
|
+
*
|
|
19033
|
+
* ## Why `unaccounted*` exists
|
|
19034
|
+
*
|
|
19035
|
+
* `kinds` is enumerated from {@link MediaFileKindEnum} — the closed set the
|
|
19036
|
+
* writers use — and summed one kind at a time. `totalRows` / `totalBytes` come
|
|
19037
|
+
* from a SEPARATE unfiltered aggregate over the same rows, never from adding
|
|
19038
|
+
* `kinds` up. A row whose stored `kind` is not in the enum (written by a
|
|
19039
|
+
* retired code path, or by a version that knew a kind this one does not) would
|
|
19040
|
+
* otherwise vanish from the total silently, and an operator would delete
|
|
19041
|
+
* against a denominator smaller than the disk.
|
|
19042
|
+
*
|
|
19043
|
+
* `unaccountedRows` / `unaccountedBytes` are the difference. They are normally
|
|
19044
|
+
* zero; a non-zero value is a real finding and must be shown, not rounded away.
|
|
19045
|
+
*/
|
|
19046
|
+
var EventMediaKindBreakdownSchema = object({
|
|
19047
|
+
/** Every media row in scope, from one unfiltered aggregate. */
|
|
19048
|
+
totalRows: number().int(),
|
|
19049
|
+
/** Every media byte in scope, from that same aggregate. */
|
|
19050
|
+
totalBytes: number().int(),
|
|
19051
|
+
/** Per-kind footprint, ordered by bytes descending. */
|
|
19052
|
+
kinds: array(EventMediaKindFootprintSchema).readonly(),
|
|
19053
|
+
/** `totalRows` minus the summed `kinds` rows — see the schema note. */
|
|
19054
|
+
unaccountedRows: number().int(),
|
|
19055
|
+
/** `totalBytes` minus the summed `kinds` bytes — see the schema note. */
|
|
19056
|
+
unaccountedBytes: number().int()
|
|
19057
|
+
});
|
|
18887
19058
|
/** Per-kind counts returned by the event-prune / device-delete mutations. */
|
|
18888
19059
|
var EventPruneCountsSchema = object({
|
|
18889
19060
|
motion: number().int(),
|
|
@@ -19038,7 +19209,7 @@ DeviceType.Camera, method(object({ deviceId: number() }), array(TrackSchema).rea
|
|
|
19038
19209
|
until: number().optional(),
|
|
19039
19210
|
kinds: array(string()).optional(),
|
|
19040
19211
|
limit: number().int().min(1).max(MAX_EVENT_QUERY_LIMIT).default(DEFAULT_EVENT_QUERY_LIMIT)
|
|
19041
|
-
}), array(SensorEventSchema).readonly()), method(KeyEventQueryInput, array(KeyEventSchema).readonly()), method(object({
|
|
19212
|
+
}), array(SensorEventSchema).readonly()), method(KeyEventQueryInput, array(KeyEventSchema).readonly()), method(KeyEventBatchQueryInput, array(KeyEventsForDeviceSchema).readonly()), method(object({
|
|
19042
19213
|
deviceId: number(),
|
|
19043
19214
|
since: number(),
|
|
19044
19215
|
until: number(),
|
|
@@ -19087,6 +19258,9 @@ DeviceType.Camera, method(object({ deviceId: number() }), array(TrackSchema).rea
|
|
|
19087
19258
|
}), TrackFlagsSchema, { kind: "mutation" }), method(object({}), EventStoreFootprintSchema, {
|
|
19088
19259
|
kind: "query",
|
|
19089
19260
|
auth: "admin"
|
|
19261
|
+
}), method(object({ deviceId: number().int().optional() }), EventMediaKindBreakdownSchema, {
|
|
19262
|
+
kind: "query",
|
|
19263
|
+
auth: "admin"
|
|
19090
19264
|
}), method(object({
|
|
19091
19265
|
olderThanMs: number(),
|
|
19092
19266
|
reason: OpsLogReasonSchema.optional()
|
|
@@ -21038,6 +21212,20 @@ method(object({
|
|
|
21038
21212
|
error: string().optional()
|
|
21039
21213
|
}), { auth: "admin" }), method(_void(), array(ProviderListEntrySchema).readonly()), method(object({
|
|
21040
21214
|
providerId: string(),
|
|
21215
|
+
/**
|
|
21216
|
+
* The location this config is an UNSAVED edit of, when there is one.
|
|
21217
|
+
*
|
|
21218
|
+
* `listLocations` replaces every declared secret with the redaction
|
|
21219
|
+
* sentinel, so the edit modal's form state holds the sentinel for any
|
|
21220
|
+
* credential the operator did not retype — and posting that here
|
|
21221
|
+
* without a way to resolve it makes the provider try to authenticate
|
|
21222
|
+
* as `__camstack_redacted__` and report the operator's own working
|
|
21223
|
+
* password as wrong. Given this id, the orchestrator restores each
|
|
21224
|
+
* sentinel from the stored config (same rule as `upsertLocation`)
|
|
21225
|
+
* before dispatching. Omitted by the "Add location" wizard, where
|
|
21226
|
+
* every value was typed just now and nothing is stored yet.
|
|
21227
|
+
*/
|
|
21228
|
+
locationId: string().optional(),
|
|
21041
21229
|
config: record(string(), unknown())
|
|
21042
21230
|
}), object({
|
|
21043
21231
|
ok: boolean(),
|
|
@@ -26673,6 +26861,9 @@ method(object({
|
|
|
26673
26861
|
}), method(RelocateResidueInputSchema, RelocateResidueSchema, {
|
|
26674
26862
|
kind: "query",
|
|
26675
26863
|
auth: "admin"
|
|
26864
|
+
}), method(LedgerWalkInputSchema, LedgerWalkReportSchema, {
|
|
26865
|
+
kind: "mutation",
|
|
26866
|
+
auth: "admin"
|
|
26676
26867
|
}), method(object({ jobId: string() }), object({ cancelled: boolean() }), {
|
|
26677
26868
|
kind: "mutation",
|
|
26678
26869
|
auth: "admin"
|
|
@@ -27064,7 +27255,26 @@ var SceneMonitorStatusSchema = object({
|
|
|
27064
27255
|
monitors: array(SceneMonitorSchema),
|
|
27065
27256
|
lastFetchedAt: number()
|
|
27066
27257
|
});
|
|
27067
|
-
|
|
27258
|
+
/**
|
|
27259
|
+
* One camera's row in a `listScenesBatch` answer.
|
|
27260
|
+
*
|
|
27261
|
+
* `status` is NULLABLE and the nullability is the whole point. `scene-monitor`
|
|
27262
|
+
* is a `defaultActive` wrapper, so every camera is asked; a camera whose
|
|
27263
|
+
* provider is absent (pipeline-analytics not deployed, the post-processing node
|
|
27264
|
+
* down) cannot answer, and that is not the same fact as a camera with no scenes
|
|
27265
|
+
* configured. Fanned out per camera the difference was visible — one query
|
|
27266
|
+
* errored while the others resolved — and a batch that returned only the rows
|
|
27267
|
+
* it managed would have destroyed it, silently, by making an unreachable camera
|
|
27268
|
+
* indistinguishable from one that answered `monitors: []`.
|
|
27269
|
+
*
|
|
27270
|
+
* So: EVERY requested deviceId gets a row. `status: null` means "this camera
|
|
27271
|
+
* could not be read"; `status.monitors: []` means "read, and it has none".
|
|
27272
|
+
*/
|
|
27273
|
+
var SceneMonitorStatusForDeviceSchema = object({
|
|
27274
|
+
deviceId: number(),
|
|
27275
|
+
status: SceneMonitorStatusSchema.nullable()
|
|
27276
|
+
});
|
|
27277
|
+
DeviceType.Camera, method(object({ deviceId: number() }), SceneMonitorStatusSchema), method(object({ deviceIds: array(number()).min(1).max(200) }), array(SceneMonitorStatusForDeviceSchema).readonly()), method(object({
|
|
27068
27278
|
deviceId: number(),
|
|
27069
27279
|
label: string(),
|
|
27070
27280
|
roi: MaskRectShapeSchema,
|
|
@@ -28388,6 +28598,27 @@ var CameraOccupancySnapshotSchema = object({
|
|
|
28388
28598
|
stationaryObjects: array(StationaryObjectSchema).readonly().optional()
|
|
28389
28599
|
});
|
|
28390
28600
|
/**
|
|
28601
|
+
* One camera's row in a `getCurrentSnapshotBatch` answer.
|
|
28602
|
+
*
|
|
28603
|
+
* THREE outcomes, and the single-camera method could only express two of them
|
|
28604
|
+
* because `snapshot: null` was already spoken for:
|
|
28605
|
+
*
|
|
28606
|
+
* - `read: 'read'`, `snapshot` present — the live occupancy reading.
|
|
28607
|
+
* - `read: 'read'`, `snapshot: null` — read, and this camera has no reading
|
|
28608
|
+
* yet: no frame since boot, and no parked-object registry to hydrate from.
|
|
28609
|
+
* - `read: 'unreadable'` — the owner could not answer for this
|
|
28610
|
+
* camera. `snapshot` is null, and it does NOT mean "nothing parked here".
|
|
28611
|
+
*
|
|
28612
|
+
* Collapsing the last two is the failure this field exists to prevent: a
|
|
28613
|
+
* hydration that threw would otherwise render as an empty Stationary section,
|
|
28614
|
+
* which is a definite claim about a camera nobody could read.
|
|
28615
|
+
*/
|
|
28616
|
+
var CameraOccupancySnapshotForDeviceSchema = object({
|
|
28617
|
+
deviceId: number(),
|
|
28618
|
+
read: _enum(["read", "unreadable"]),
|
|
28619
|
+
snapshot: CameraOccupancySnapshotSchema.nullable()
|
|
28620
|
+
});
|
|
28621
|
+
/**
|
|
28391
28622
|
* Time-series resolution. The history methods return one bucket per
|
|
28392
28623
|
* step over the requested range. Smaller resolutions cost more
|
|
28393
28624
|
* memory + bandwidth; bound to discrete steps so caller cannot ask
|
|
@@ -28411,7 +28642,7 @@ var HistoryPointSchema = object({
|
|
|
28411
28642
|
/** Object count averaged over the bucket (rounded to nearest integer). */
|
|
28412
28643
|
count: number().int().nonnegative()
|
|
28413
28644
|
});
|
|
28414
|
-
DeviceType.Camera, method(object({ deviceId: number() }), CameraOccupancySnapshotSchema.nullable()), method(object({
|
|
28645
|
+
DeviceType.Camera, method(object({ deviceId: number() }), CameraOccupancySnapshotSchema.nullable()), method(object({ deviceIds: array(number()).min(1).max(200) }), array(CameraOccupancySnapshotForDeviceSchema).readonly()), method(object({
|
|
28415
28646
|
deviceId: number(),
|
|
28416
28647
|
zoneId: string(),
|
|
28417
28648
|
className: string().optional()
|
|
@@ -31692,6 +31923,12 @@ Object.freeze({
|
|
|
31692
31923
|
addonId: null,
|
|
31693
31924
|
access: "view"
|
|
31694
31925
|
},
|
|
31926
|
+
"pipelineAnalytics.getEventMediaFootprintByKind": {
|
|
31927
|
+
capName: "pipeline-analytics",
|
|
31928
|
+
capScope: "device",
|
|
31929
|
+
addonId: null,
|
|
31930
|
+
access: "view"
|
|
31931
|
+
},
|
|
31695
31932
|
"pipelineAnalytics.getEventStoreFootprint": {
|
|
31696
31933
|
capName: "pipeline-analytics",
|
|
31697
31934
|
capScope: "device",
|
|
@@ -31710,6 +31947,12 @@ Object.freeze({
|
|
|
31710
31947
|
addonId: null,
|
|
31711
31948
|
access: "view"
|
|
31712
31949
|
},
|
|
31950
|
+
"pipelineAnalytics.getKeyEventsBatch": {
|
|
31951
|
+
capName: "pipeline-analytics",
|
|
31952
|
+
capScope: "device",
|
|
31953
|
+
addonId: null,
|
|
31954
|
+
access: "view"
|
|
31955
|
+
},
|
|
31713
31956
|
"pipelineAnalytics.getMotionEvents": {
|
|
31714
31957
|
capName: "pipeline-analytics",
|
|
31715
31958
|
capScope: "device",
|
|
@@ -32886,6 +33129,12 @@ Object.freeze({
|
|
|
32886
33129
|
addonId: null,
|
|
32887
33130
|
access: "view"
|
|
32888
33131
|
},
|
|
33132
|
+
"recording.reconcileLedgerAgainstDisk": {
|
|
33133
|
+
capName: "recording",
|
|
33134
|
+
capScope: "system",
|
|
33135
|
+
addonId: null,
|
|
33136
|
+
access: "create"
|
|
33137
|
+
},
|
|
32889
33138
|
"recording.refreshStorageLocationsForMigration": {
|
|
32890
33139
|
capName: "recording",
|
|
32891
33140
|
capScope: "system",
|
|
@@ -33012,6 +33261,12 @@ Object.freeze({
|
|
|
33012
33261
|
addonId: null,
|
|
33013
33262
|
access: "view"
|
|
33014
33263
|
},
|
|
33264
|
+
"sceneMonitor.listScenesBatch": {
|
|
33265
|
+
capName: "scene-monitor",
|
|
33266
|
+
capScope: "device",
|
|
33267
|
+
addonId: null,
|
|
33268
|
+
access: "view"
|
|
33269
|
+
},
|
|
33015
33270
|
"sceneMonitor.recheckNow": {
|
|
33016
33271
|
capName: "scene-monitor",
|
|
33017
33272
|
capScope: "device",
|
|
@@ -34368,6 +34623,12 @@ Object.freeze({
|
|
|
34368
34623
|
addonId: null,
|
|
34369
34624
|
access: "view"
|
|
34370
34625
|
},
|
|
34626
|
+
"zoneAnalytics.getCurrentSnapshotBatch": {
|
|
34627
|
+
capName: "zone-analytics",
|
|
34628
|
+
capScope: "device",
|
|
34629
|
+
addonId: null,
|
|
34630
|
+
access: "view"
|
|
34631
|
+
},
|
|
34371
34632
|
"zoneAnalytics.getUnzonedHistory": {
|
|
34372
34633
|
capName: "zone-analytics",
|
|
34373
34634
|
capScope: "device",
|
|
@@ -35357,6 +35618,11 @@ Object.freeze({
|
|
|
35357
35618
|
form: "single",
|
|
35358
35619
|
optional: false
|
|
35359
35620
|
}],
|
|
35621
|
+
"pipelineAnalytics.getEventMediaFootprintByKind": [{
|
|
35622
|
+
name: "deviceId",
|
|
35623
|
+
form: "single",
|
|
35624
|
+
optional: true
|
|
35625
|
+
}],
|
|
35360
35626
|
"pipelineAnalytics.getGroup": [{
|
|
35361
35627
|
name: "deviceId",
|
|
35362
35628
|
form: "single",
|
|
@@ -35367,6 +35633,11 @@ Object.freeze({
|
|
|
35367
35633
|
form: "single",
|
|
35368
35634
|
optional: false
|
|
35369
35635
|
}],
|
|
35636
|
+
"pipelineAnalytics.getKeyEventsBatch": [{
|
|
35637
|
+
name: "deviceIds",
|
|
35638
|
+
form: "array",
|
|
35639
|
+
optional: false
|
|
35640
|
+
}],
|
|
35370
35641
|
"pipelineAnalytics.getMotionEvents": [{
|
|
35371
35642
|
name: "deviceId",
|
|
35372
35643
|
form: "single",
|
|
@@ -35807,6 +36078,11 @@ Object.freeze({
|
|
|
35807
36078
|
form: "single",
|
|
35808
36079
|
optional: false
|
|
35809
36080
|
}],
|
|
36081
|
+
"recording.reconcileLedgerAgainstDisk": [{
|
|
36082
|
+
name: "deviceId",
|
|
36083
|
+
form: "single",
|
|
36084
|
+
optional: true
|
|
36085
|
+
}],
|
|
35810
36086
|
"recording.relocateFootage": [{
|
|
35811
36087
|
name: "deviceId",
|
|
35812
36088
|
form: "single",
|
|
@@ -35872,6 +36148,11 @@ Object.freeze({
|
|
|
35872
36148
|
form: "single",
|
|
35873
36149
|
optional: false
|
|
35874
36150
|
}],
|
|
36151
|
+
"sceneMonitor.listScenesBatch": [{
|
|
36152
|
+
name: "deviceIds",
|
|
36153
|
+
form: "array",
|
|
36154
|
+
optional: false
|
|
36155
|
+
}],
|
|
35875
36156
|
"sceneMonitor.recheckNow": [{
|
|
35876
36157
|
name: "deviceId",
|
|
35877
36158
|
form: "single",
|
|
@@ -36133,6 +36414,11 @@ Object.freeze({
|
|
|
36133
36414
|
form: "single",
|
|
36134
36415
|
optional: false
|
|
36135
36416
|
}],
|
|
36417
|
+
"zoneAnalytics.getCurrentSnapshotBatch": [{
|
|
36418
|
+
name: "deviceIds",
|
|
36419
|
+
form: "array",
|
|
36420
|
+
optional: false
|
|
36421
|
+
}],
|
|
36136
36422
|
"zoneAnalytics.getUnzonedHistory": [{
|
|
36137
36423
|
name: "deviceId",
|
|
36138
36424
|
form: "single",
|
package/dist/index.mjs
CHANGED
|
@@ -8015,6 +8015,20 @@ var RelocateJobSchema = object({
|
|
|
8015
8015
|
* in its row, not in its name, so `MediaRelocateEngine` never reconciles one.
|
|
8016
8016
|
*/
|
|
8017
8017
|
rowsReconciled: number().int().nonnegative().optional(),
|
|
8018
|
+
/**
|
|
8019
|
+
* Rows this run FORGOT because the file they name is not on disk.
|
|
8020
|
+
*
|
|
8021
|
+
* The mover derived the path from the row's own fields and `stat`ed it; an
|
|
8022
|
+
* ENOENT there is a per-path confirmation that the segment is gone (D296),
|
|
8023
|
+
* and the durable row is dropped through the same channel eviction uses. It
|
|
8024
|
+
* is reported for the same reason `rowsReconciled` is: this is a durable
|
|
8025
|
+
* mutation nobody asked for, and a migration that quietly erases hour rows is
|
|
8026
|
+
* the same failure as one that quietly skips them (D295).
|
|
8027
|
+
*
|
|
8028
|
+
* The production drain of 2026-08-30 would have reported 11 074 here — the
|
|
8029
|
+
* ledger claimed 5.65 GB of footage that no longer existed.
|
|
8030
|
+
*/
|
|
8031
|
+
rowsForgotten: number().int().nonnegative().optional(),
|
|
8018
8032
|
startedAt: number(),
|
|
8019
8033
|
finishedAt: number().nullable(),
|
|
8020
8034
|
error: string().nullable()
|
|
@@ -8378,6 +8392,91 @@ var RelocateResidueSchema = object({
|
|
|
8378
8392
|
segments: number().int().nonnegative(),
|
|
8379
8393
|
bytes: number().int().nonnegative()
|
|
8380
8394
|
}).nullable();
|
|
8395
|
+
/**
|
|
8396
|
+
* Ask one location whether its durable hour rows describe the disk — the walk
|
|
8397
|
+
* (D319).
|
|
8398
|
+
*
|
|
8399
|
+
* `apply` DEFAULTS TO FALSE and that default is the product: the operator's
|
|
8400
|
+
* missing tool is the question, and the dry run is how they sanity-check the
|
|
8401
|
+
* destructive run before authorising it.
|
|
8402
|
+
*/
|
|
8403
|
+
var LedgerWalkInputSchema = object({
|
|
8404
|
+
locationId: string().min(1),
|
|
8405
|
+
/** Forget the confirmed-absent rows, rather than only counting them. */
|
|
8406
|
+
apply: boolean().optional(),
|
|
8407
|
+
/** Narrow to one camera. */
|
|
8408
|
+
deviceId: number().int().positive().optional(),
|
|
8409
|
+
/** Narrow to these recording profiles; empty/absent = every profile. */
|
|
8410
|
+
profiles: array(string().min(1)).optional()
|
|
8411
|
+
});
|
|
8412
|
+
/** Why a whole walk did nothing. Every one leaves the ledger untouched. */
|
|
8413
|
+
var LedgerWalkRefusalSchema = _enum([
|
|
8414
|
+
"location-unknown",
|
|
8415
|
+
"source-writable",
|
|
8416
|
+
"no-ledger",
|
|
8417
|
+
"archive-unreadable",
|
|
8418
|
+
"anchor-absent",
|
|
8419
|
+
"anchor-unreadable",
|
|
8420
|
+
"anchor-moved"
|
|
8421
|
+
]);
|
|
8422
|
+
_enum([
|
|
8423
|
+
"live-tail",
|
|
8424
|
+
"listing-error",
|
|
8425
|
+
"path-mismatch",
|
|
8426
|
+
"durable-refused"
|
|
8427
|
+
]);
|
|
8428
|
+
/** Every skip reason, always present, always a number — so a reason that never
|
|
8429
|
+
* fired reports as zero rather than absent and the report shape is constant
|
|
8430
|
+
* between passes. Spelled out rather than `z.record` for exactly that. */
|
|
8431
|
+
var LedgerWalkSkipCountsSchema = object({
|
|
8432
|
+
"live-tail": number().int().nonnegative(),
|
|
8433
|
+
"listing-error": number().int().nonnegative(),
|
|
8434
|
+
"path-mismatch": number().int().nonnegative(),
|
|
8435
|
+
"durable-refused": number().int().nonnegative()
|
|
8436
|
+
});
|
|
8437
|
+
/** One camera's share of a walk, so a report names cameras and not rows. */
|
|
8438
|
+
var LedgerWalkDeviceReportSchema = object({
|
|
8439
|
+
deviceId: number().int(),
|
|
8440
|
+
hoursWalked: number().int().nonnegative(),
|
|
8441
|
+
hoursMissing: number().int().nonnegative(),
|
|
8442
|
+
ghostSegments: number().int().nonnegative(),
|
|
8443
|
+
ghostBytes: number().int().nonnegative(),
|
|
8444
|
+
forgottenSegments: number().int().nonnegative(),
|
|
8445
|
+
orphanFiles: number().int().nonnegative()
|
|
8446
|
+
});
|
|
8447
|
+
/**
|
|
8448
|
+
* What one walk claimed, listed, found and (only when armed) forgot.
|
|
8449
|
+
*
|
|
8450
|
+
* `archiveSegments` is the **M** and `segmentsClaimed` the **N** (D295), so a
|
|
8451
|
+
* walk that saw a fraction of the location is visible in its own report rather
|
|
8452
|
+
* than in the absence of one.
|
|
8453
|
+
*/
|
|
8454
|
+
var LedgerWalkReportSchema = object({
|
|
8455
|
+
locationId: string(),
|
|
8456
|
+
applied: boolean(),
|
|
8457
|
+
refused: LedgerWalkRefusalSchema.nullable(),
|
|
8458
|
+
archiveSegments: number().int().nonnegative().nullable(),
|
|
8459
|
+
archiveBytes: number().int().nonnegative().nullable(),
|
|
8460
|
+
hoursClaimed: number().int().nonnegative(),
|
|
8461
|
+
hoursWalked: number().int().nonnegative(),
|
|
8462
|
+
hoursMissing: number().int().nonnegative(),
|
|
8463
|
+
/** `readdir` calls issued — the cost, stated in the unit that is paid. */
|
|
8464
|
+
listings: number().int().nonnegative(),
|
|
8465
|
+
segmentsClaimed: number().int().nonnegative(),
|
|
8466
|
+
ghostSegments: number().int().nonnegative(),
|
|
8467
|
+
ghostBytes: number().int().nonnegative(),
|
|
8468
|
+
ghostHoursWhole: number().int().nonnegative(),
|
|
8469
|
+
forgottenSegments: number().int().nonnegative(),
|
|
8470
|
+
forgottenBytes: number().int().nonnegative(),
|
|
8471
|
+
/** Files under a claimed hour that no durable row names. Never deleted. */
|
|
8472
|
+
orphanFiles: number().int().nonnegative(),
|
|
8473
|
+
orphanSample: array(string()).readonly(),
|
|
8474
|
+
hoursSkipped: number().int().nonnegative(),
|
|
8475
|
+
skippedByReason: LedgerWalkSkipCountsSchema,
|
|
8476
|
+
/** The walk stopped at its per-pass hour bound with claims unwalked. */
|
|
8477
|
+
bounded: boolean(),
|
|
8478
|
+
byDevice: array(LedgerWalkDeviceReportSchema).readonly()
|
|
8479
|
+
});
|
|
8381
8480
|
/** How many rows a media pass would still act on against a given target — the
|
|
8382
8481
|
* media lane's denominator AND its residue, from ONE derivation so the two can
|
|
8383
8482
|
* never disagree. `null` = the count could not be taken. */
|
|
@@ -18781,13 +18880,15 @@ var ListGroupsPageSchema = object({
|
|
|
18781
18880
|
groups: array(AnalyticsGroupRecordSchema).readonly(),
|
|
18782
18881
|
nextCursor: string().nullable()
|
|
18783
18882
|
});
|
|
18883
|
+
var KEY_EVENTS_DEFAULT_LIMIT = 50;
|
|
18884
|
+
var KEY_EVENTS_MAX_LIMIT = 200;
|
|
18784
18885
|
var KeyEventQueryInput = object({
|
|
18785
18886
|
deviceId: number(),
|
|
18786
18887
|
/** Window lower bound (track firstSeen ≥ since). */
|
|
18787
18888
|
since: number(),
|
|
18788
18889
|
/** Window upper bound (track firstSeen ≤ until). */
|
|
18789
18890
|
until: number(),
|
|
18790
|
-
limit: number().int().min(1).max(
|
|
18891
|
+
limit: number().int().min(1).max(KEY_EVENTS_MAX_LIMIT).default(KEY_EVENTS_DEFAULT_LIMIT),
|
|
18791
18892
|
/** Drop tracks scoring below this importance. */
|
|
18792
18893
|
minImportance: number().min(0).max(1).optional(),
|
|
18793
18894
|
/** Restrict to a single class (e.g. 'person'). */
|
|
@@ -18809,6 +18910,32 @@ var KeyEventSchema = object({
|
|
|
18809
18910
|
...TrackFlagFields,
|
|
18810
18911
|
...TrackRetrainFields
|
|
18811
18912
|
});
|
|
18913
|
+
/** `getKeyEvents`' window and filters, asked of a SET of cameras at once. */
|
|
18914
|
+
var KeyEventBatchQueryInput = object({
|
|
18915
|
+
deviceIds: array(number()).min(1).max(200),
|
|
18916
|
+
since: number(),
|
|
18917
|
+
until: number(),
|
|
18918
|
+
/** Applied PER CAMERA, exactly as `getKeyEvents.limit` is — never a total
|
|
18919
|
+
* across the set, which would let a busy camera starve a quiet one of its
|
|
18920
|
+
* rows and change what the merged feed contains. */
|
|
18921
|
+
limit: number().int().min(1).max(KEY_EVENTS_MAX_LIMIT).default(KEY_EVENTS_DEFAULT_LIMIT),
|
|
18922
|
+
minImportance: number().min(0).max(1).optional(),
|
|
18923
|
+
classFilter: string().optional()
|
|
18924
|
+
});
|
|
18925
|
+
/**
|
|
18926
|
+
* One camera's key events in a batch answer.
|
|
18927
|
+
*
|
|
18928
|
+
* The row exists for every requested id. `getKeyEvents` degrades to `[]` on
|
|
18929
|
+
* error rather than throwing, so a camera whose store read failed and one with
|
|
18930
|
+
* no events in the window were ALREADY indistinguishable per camera — the
|
|
18931
|
+
* batch does not make that worse, and the row keeps the deviceId the single
|
|
18932
|
+
* method's output never carried (the caller used to stamp it from the fan-out
|
|
18933
|
+
* key, which only worked because there was one query per camera).
|
|
18934
|
+
*/
|
|
18935
|
+
var KeyEventsForDeviceSchema = object({
|
|
18936
|
+
deviceId: number(),
|
|
18937
|
+
events: array(KeyEventSchema).readonly()
|
|
18938
|
+
});
|
|
18812
18939
|
object({
|
|
18813
18940
|
trackId: string(),
|
|
18814
18941
|
className: string(),
|
|
@@ -18880,6 +19007,50 @@ var EventStoreFootprintSchema = object({
|
|
|
18880
19007
|
totalBytes: number().int(),
|
|
18881
19008
|
devices: array(EventStoreDeviceFootprintSchema).readonly()
|
|
18882
19009
|
});
|
|
19010
|
+
/** Event-media footprint for one {@link MediaFileKind}. */
|
|
19011
|
+
var EventMediaKindFootprintSchema = object({
|
|
19012
|
+
kind: MediaFileKindEnum,
|
|
19013
|
+
/** Media rows of this kind. */
|
|
19014
|
+
rows: number().int(),
|
|
19015
|
+
/** Bytes on disk held by those rows. */
|
|
19016
|
+
bytes: number().int()
|
|
19017
|
+
});
|
|
19018
|
+
/**
|
|
19019
|
+
* The media footprint broken down by KIND — the axis a deletion decision
|
|
19020
|
+
* actually turns on.
|
|
19021
|
+
*
|
|
19022
|
+
* A byte total says how much there is; it cannot say what is safe to remove.
|
|
19023
|
+
* The deletable set (the periodic `snapshot` filmstrip, the surplus per-edge
|
|
19024
|
+
* motion stills) and the keep set (`firstFrame`, rolling `lastFrame`,
|
|
19025
|
+
* `thumbnail`/`thumbnailSmall`, `keyFrame`/`keyFrameSmall`, the face/plate
|
|
19026
|
+
* buffers, gallery media, the CLIP `crop`) are distinguished by `kind` and by
|
|
19027
|
+
* nothing else, so sizing a deletion means summing per kind.
|
|
19028
|
+
*
|
|
19029
|
+
* ## Why `unaccounted*` exists
|
|
19030
|
+
*
|
|
19031
|
+
* `kinds` is enumerated from {@link MediaFileKindEnum} — the closed set the
|
|
19032
|
+
* writers use — and summed one kind at a time. `totalRows` / `totalBytes` come
|
|
19033
|
+
* from a SEPARATE unfiltered aggregate over the same rows, never from adding
|
|
19034
|
+
* `kinds` up. A row whose stored `kind` is not in the enum (written by a
|
|
19035
|
+
* retired code path, or by a version that knew a kind this one does not) would
|
|
19036
|
+
* otherwise vanish from the total silently, and an operator would delete
|
|
19037
|
+
* against a denominator smaller than the disk.
|
|
19038
|
+
*
|
|
19039
|
+
* `unaccountedRows` / `unaccountedBytes` are the difference. They are normally
|
|
19040
|
+
* zero; a non-zero value is a real finding and must be shown, not rounded away.
|
|
19041
|
+
*/
|
|
19042
|
+
var EventMediaKindBreakdownSchema = object({
|
|
19043
|
+
/** Every media row in scope, from one unfiltered aggregate. */
|
|
19044
|
+
totalRows: number().int(),
|
|
19045
|
+
/** Every media byte in scope, from that same aggregate. */
|
|
19046
|
+
totalBytes: number().int(),
|
|
19047
|
+
/** Per-kind footprint, ordered by bytes descending. */
|
|
19048
|
+
kinds: array(EventMediaKindFootprintSchema).readonly(),
|
|
19049
|
+
/** `totalRows` minus the summed `kinds` rows — see the schema note. */
|
|
19050
|
+
unaccountedRows: number().int(),
|
|
19051
|
+
/** `totalBytes` minus the summed `kinds` bytes — see the schema note. */
|
|
19052
|
+
unaccountedBytes: number().int()
|
|
19053
|
+
});
|
|
18883
19054
|
/** Per-kind counts returned by the event-prune / device-delete mutations. */
|
|
18884
19055
|
var EventPruneCountsSchema = object({
|
|
18885
19056
|
motion: number().int(),
|
|
@@ -19034,7 +19205,7 @@ DeviceType.Camera, method(object({ deviceId: number() }), array(TrackSchema).rea
|
|
|
19034
19205
|
until: number().optional(),
|
|
19035
19206
|
kinds: array(string()).optional(),
|
|
19036
19207
|
limit: number().int().min(1).max(MAX_EVENT_QUERY_LIMIT).default(DEFAULT_EVENT_QUERY_LIMIT)
|
|
19037
|
-
}), array(SensorEventSchema).readonly()), method(KeyEventQueryInput, array(KeyEventSchema).readonly()), method(object({
|
|
19208
|
+
}), array(SensorEventSchema).readonly()), method(KeyEventQueryInput, array(KeyEventSchema).readonly()), method(KeyEventBatchQueryInput, array(KeyEventsForDeviceSchema).readonly()), method(object({
|
|
19038
19209
|
deviceId: number(),
|
|
19039
19210
|
since: number(),
|
|
19040
19211
|
until: number(),
|
|
@@ -19083,6 +19254,9 @@ DeviceType.Camera, method(object({ deviceId: number() }), array(TrackSchema).rea
|
|
|
19083
19254
|
}), TrackFlagsSchema, { kind: "mutation" }), method(object({}), EventStoreFootprintSchema, {
|
|
19084
19255
|
kind: "query",
|
|
19085
19256
|
auth: "admin"
|
|
19257
|
+
}), method(object({ deviceId: number().int().optional() }), EventMediaKindBreakdownSchema, {
|
|
19258
|
+
kind: "query",
|
|
19259
|
+
auth: "admin"
|
|
19086
19260
|
}), method(object({
|
|
19087
19261
|
olderThanMs: number(),
|
|
19088
19262
|
reason: OpsLogReasonSchema.optional()
|
|
@@ -21034,6 +21208,20 @@ method(object({
|
|
|
21034
21208
|
error: string().optional()
|
|
21035
21209
|
}), { auth: "admin" }), method(_void(), array(ProviderListEntrySchema).readonly()), method(object({
|
|
21036
21210
|
providerId: string(),
|
|
21211
|
+
/**
|
|
21212
|
+
* The location this config is an UNSAVED edit of, when there is one.
|
|
21213
|
+
*
|
|
21214
|
+
* `listLocations` replaces every declared secret with the redaction
|
|
21215
|
+
* sentinel, so the edit modal's form state holds the sentinel for any
|
|
21216
|
+
* credential the operator did not retype — and posting that here
|
|
21217
|
+
* without a way to resolve it makes the provider try to authenticate
|
|
21218
|
+
* as `__camstack_redacted__` and report the operator's own working
|
|
21219
|
+
* password as wrong. Given this id, the orchestrator restores each
|
|
21220
|
+
* sentinel from the stored config (same rule as `upsertLocation`)
|
|
21221
|
+
* before dispatching. Omitted by the "Add location" wizard, where
|
|
21222
|
+
* every value was typed just now and nothing is stored yet.
|
|
21223
|
+
*/
|
|
21224
|
+
locationId: string().optional(),
|
|
21037
21225
|
config: record(string(), unknown())
|
|
21038
21226
|
}), object({
|
|
21039
21227
|
ok: boolean(),
|
|
@@ -26669,6 +26857,9 @@ method(object({
|
|
|
26669
26857
|
}), method(RelocateResidueInputSchema, RelocateResidueSchema, {
|
|
26670
26858
|
kind: "query",
|
|
26671
26859
|
auth: "admin"
|
|
26860
|
+
}), method(LedgerWalkInputSchema, LedgerWalkReportSchema, {
|
|
26861
|
+
kind: "mutation",
|
|
26862
|
+
auth: "admin"
|
|
26672
26863
|
}), method(object({ jobId: string() }), object({ cancelled: boolean() }), {
|
|
26673
26864
|
kind: "mutation",
|
|
26674
26865
|
auth: "admin"
|
|
@@ -27060,7 +27251,26 @@ var SceneMonitorStatusSchema = object({
|
|
|
27060
27251
|
monitors: array(SceneMonitorSchema),
|
|
27061
27252
|
lastFetchedAt: number()
|
|
27062
27253
|
});
|
|
27063
|
-
|
|
27254
|
+
/**
|
|
27255
|
+
* One camera's row in a `listScenesBatch` answer.
|
|
27256
|
+
*
|
|
27257
|
+
* `status` is NULLABLE and the nullability is the whole point. `scene-monitor`
|
|
27258
|
+
* is a `defaultActive` wrapper, so every camera is asked; a camera whose
|
|
27259
|
+
* provider is absent (pipeline-analytics not deployed, the post-processing node
|
|
27260
|
+
* down) cannot answer, and that is not the same fact as a camera with no scenes
|
|
27261
|
+
* configured. Fanned out per camera the difference was visible — one query
|
|
27262
|
+
* errored while the others resolved — and a batch that returned only the rows
|
|
27263
|
+
* it managed would have destroyed it, silently, by making an unreachable camera
|
|
27264
|
+
* indistinguishable from one that answered `monitors: []`.
|
|
27265
|
+
*
|
|
27266
|
+
* So: EVERY requested deviceId gets a row. `status: null` means "this camera
|
|
27267
|
+
* could not be read"; `status.monitors: []` means "read, and it has none".
|
|
27268
|
+
*/
|
|
27269
|
+
var SceneMonitorStatusForDeviceSchema = object({
|
|
27270
|
+
deviceId: number(),
|
|
27271
|
+
status: SceneMonitorStatusSchema.nullable()
|
|
27272
|
+
});
|
|
27273
|
+
DeviceType.Camera, method(object({ deviceId: number() }), SceneMonitorStatusSchema), method(object({ deviceIds: array(number()).min(1).max(200) }), array(SceneMonitorStatusForDeviceSchema).readonly()), method(object({
|
|
27064
27274
|
deviceId: number(),
|
|
27065
27275
|
label: string(),
|
|
27066
27276
|
roi: MaskRectShapeSchema,
|
|
@@ -28384,6 +28594,27 @@ var CameraOccupancySnapshotSchema = object({
|
|
|
28384
28594
|
stationaryObjects: array(StationaryObjectSchema).readonly().optional()
|
|
28385
28595
|
});
|
|
28386
28596
|
/**
|
|
28597
|
+
* One camera's row in a `getCurrentSnapshotBatch` answer.
|
|
28598
|
+
*
|
|
28599
|
+
* THREE outcomes, and the single-camera method could only express two of them
|
|
28600
|
+
* because `snapshot: null` was already spoken for:
|
|
28601
|
+
*
|
|
28602
|
+
* - `read: 'read'`, `snapshot` present — the live occupancy reading.
|
|
28603
|
+
* - `read: 'read'`, `snapshot: null` — read, and this camera has no reading
|
|
28604
|
+
* yet: no frame since boot, and no parked-object registry to hydrate from.
|
|
28605
|
+
* - `read: 'unreadable'` — the owner could not answer for this
|
|
28606
|
+
* camera. `snapshot` is null, and it does NOT mean "nothing parked here".
|
|
28607
|
+
*
|
|
28608
|
+
* Collapsing the last two is the failure this field exists to prevent: a
|
|
28609
|
+
* hydration that threw would otherwise render as an empty Stationary section,
|
|
28610
|
+
* which is a definite claim about a camera nobody could read.
|
|
28611
|
+
*/
|
|
28612
|
+
var CameraOccupancySnapshotForDeviceSchema = object({
|
|
28613
|
+
deviceId: number(),
|
|
28614
|
+
read: _enum(["read", "unreadable"]),
|
|
28615
|
+
snapshot: CameraOccupancySnapshotSchema.nullable()
|
|
28616
|
+
});
|
|
28617
|
+
/**
|
|
28387
28618
|
* Time-series resolution. The history methods return one bucket per
|
|
28388
28619
|
* step over the requested range. Smaller resolutions cost more
|
|
28389
28620
|
* memory + bandwidth; bound to discrete steps so caller cannot ask
|
|
@@ -28407,7 +28638,7 @@ var HistoryPointSchema = object({
|
|
|
28407
28638
|
/** Object count averaged over the bucket (rounded to nearest integer). */
|
|
28408
28639
|
count: number().int().nonnegative()
|
|
28409
28640
|
});
|
|
28410
|
-
DeviceType.Camera, method(object({ deviceId: number() }), CameraOccupancySnapshotSchema.nullable()), method(object({
|
|
28641
|
+
DeviceType.Camera, method(object({ deviceId: number() }), CameraOccupancySnapshotSchema.nullable()), method(object({ deviceIds: array(number()).min(1).max(200) }), array(CameraOccupancySnapshotForDeviceSchema).readonly()), method(object({
|
|
28411
28642
|
deviceId: number(),
|
|
28412
28643
|
zoneId: string(),
|
|
28413
28644
|
className: string().optional()
|
|
@@ -31688,6 +31919,12 @@ Object.freeze({
|
|
|
31688
31919
|
addonId: null,
|
|
31689
31920
|
access: "view"
|
|
31690
31921
|
},
|
|
31922
|
+
"pipelineAnalytics.getEventMediaFootprintByKind": {
|
|
31923
|
+
capName: "pipeline-analytics",
|
|
31924
|
+
capScope: "device",
|
|
31925
|
+
addonId: null,
|
|
31926
|
+
access: "view"
|
|
31927
|
+
},
|
|
31691
31928
|
"pipelineAnalytics.getEventStoreFootprint": {
|
|
31692
31929
|
capName: "pipeline-analytics",
|
|
31693
31930
|
capScope: "device",
|
|
@@ -31706,6 +31943,12 @@ Object.freeze({
|
|
|
31706
31943
|
addonId: null,
|
|
31707
31944
|
access: "view"
|
|
31708
31945
|
},
|
|
31946
|
+
"pipelineAnalytics.getKeyEventsBatch": {
|
|
31947
|
+
capName: "pipeline-analytics",
|
|
31948
|
+
capScope: "device",
|
|
31949
|
+
addonId: null,
|
|
31950
|
+
access: "view"
|
|
31951
|
+
},
|
|
31709
31952
|
"pipelineAnalytics.getMotionEvents": {
|
|
31710
31953
|
capName: "pipeline-analytics",
|
|
31711
31954
|
capScope: "device",
|
|
@@ -32882,6 +33125,12 @@ Object.freeze({
|
|
|
32882
33125
|
addonId: null,
|
|
32883
33126
|
access: "view"
|
|
32884
33127
|
},
|
|
33128
|
+
"recording.reconcileLedgerAgainstDisk": {
|
|
33129
|
+
capName: "recording",
|
|
33130
|
+
capScope: "system",
|
|
33131
|
+
addonId: null,
|
|
33132
|
+
access: "create"
|
|
33133
|
+
},
|
|
32885
33134
|
"recording.refreshStorageLocationsForMigration": {
|
|
32886
33135
|
capName: "recording",
|
|
32887
33136
|
capScope: "system",
|
|
@@ -33008,6 +33257,12 @@ Object.freeze({
|
|
|
33008
33257
|
addonId: null,
|
|
33009
33258
|
access: "view"
|
|
33010
33259
|
},
|
|
33260
|
+
"sceneMonitor.listScenesBatch": {
|
|
33261
|
+
capName: "scene-monitor",
|
|
33262
|
+
capScope: "device",
|
|
33263
|
+
addonId: null,
|
|
33264
|
+
access: "view"
|
|
33265
|
+
},
|
|
33011
33266
|
"sceneMonitor.recheckNow": {
|
|
33012
33267
|
capName: "scene-monitor",
|
|
33013
33268
|
capScope: "device",
|
|
@@ -34364,6 +34619,12 @@ Object.freeze({
|
|
|
34364
34619
|
addonId: null,
|
|
34365
34620
|
access: "view"
|
|
34366
34621
|
},
|
|
34622
|
+
"zoneAnalytics.getCurrentSnapshotBatch": {
|
|
34623
|
+
capName: "zone-analytics",
|
|
34624
|
+
capScope: "device",
|
|
34625
|
+
addonId: null,
|
|
34626
|
+
access: "view"
|
|
34627
|
+
},
|
|
34367
34628
|
"zoneAnalytics.getUnzonedHistory": {
|
|
34368
34629
|
capName: "zone-analytics",
|
|
34369
34630
|
capScope: "device",
|
|
@@ -35353,6 +35614,11 @@ Object.freeze({
|
|
|
35353
35614
|
form: "single",
|
|
35354
35615
|
optional: false
|
|
35355
35616
|
}],
|
|
35617
|
+
"pipelineAnalytics.getEventMediaFootprintByKind": [{
|
|
35618
|
+
name: "deviceId",
|
|
35619
|
+
form: "single",
|
|
35620
|
+
optional: true
|
|
35621
|
+
}],
|
|
35356
35622
|
"pipelineAnalytics.getGroup": [{
|
|
35357
35623
|
name: "deviceId",
|
|
35358
35624
|
form: "single",
|
|
@@ -35363,6 +35629,11 @@ Object.freeze({
|
|
|
35363
35629
|
form: "single",
|
|
35364
35630
|
optional: false
|
|
35365
35631
|
}],
|
|
35632
|
+
"pipelineAnalytics.getKeyEventsBatch": [{
|
|
35633
|
+
name: "deviceIds",
|
|
35634
|
+
form: "array",
|
|
35635
|
+
optional: false
|
|
35636
|
+
}],
|
|
35366
35637
|
"pipelineAnalytics.getMotionEvents": [{
|
|
35367
35638
|
name: "deviceId",
|
|
35368
35639
|
form: "single",
|
|
@@ -35803,6 +36074,11 @@ Object.freeze({
|
|
|
35803
36074
|
form: "single",
|
|
35804
36075
|
optional: false
|
|
35805
36076
|
}],
|
|
36077
|
+
"recording.reconcileLedgerAgainstDisk": [{
|
|
36078
|
+
name: "deviceId",
|
|
36079
|
+
form: "single",
|
|
36080
|
+
optional: true
|
|
36081
|
+
}],
|
|
35806
36082
|
"recording.relocateFootage": [{
|
|
35807
36083
|
name: "deviceId",
|
|
35808
36084
|
form: "single",
|
|
@@ -35868,6 +36144,11 @@ Object.freeze({
|
|
|
35868
36144
|
form: "single",
|
|
35869
36145
|
optional: false
|
|
35870
36146
|
}],
|
|
36147
|
+
"sceneMonitor.listScenesBatch": [{
|
|
36148
|
+
name: "deviceIds",
|
|
36149
|
+
form: "array",
|
|
36150
|
+
optional: false
|
|
36151
|
+
}],
|
|
35871
36152
|
"sceneMonitor.recheckNow": [{
|
|
35872
36153
|
name: "deviceId",
|
|
35873
36154
|
form: "single",
|
|
@@ -36129,6 +36410,11 @@ Object.freeze({
|
|
|
36129
36410
|
form: "single",
|
|
36130
36411
|
optional: false
|
|
36131
36412
|
}],
|
|
36413
|
+
"zoneAnalytics.getCurrentSnapshotBatch": [{
|
|
36414
|
+
name: "deviceIds",
|
|
36415
|
+
form: "array",
|
|
36416
|
+
optional: false
|
|
36417
|
+
}],
|
|
36132
36418
|
"zoneAnalytics.getUnzonedHistory": [{
|
|
36133
36419
|
name: "deviceId",
|
|
36134
36420
|
form: "single",
|