@camstack/addon-export-alexa 1.2.54 → 1.2.55
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/export-alexa.addon.js +218 -4
- package/dist/export-alexa.addon.mjs +218 -4
- package/package.json +1 -1
|
@@ -8186,6 +8186,20 @@ var RelocateJobSchema = object({
|
|
|
8186
8186
|
* in its row, not in its name, so `MediaRelocateEngine` never reconciles one.
|
|
8187
8187
|
*/
|
|
8188
8188
|
rowsReconciled: number().int().nonnegative().optional(),
|
|
8189
|
+
/**
|
|
8190
|
+
* Rows this run FORGOT because the file they name is not on disk.
|
|
8191
|
+
*
|
|
8192
|
+
* The mover derived the path from the row's own fields and `stat`ed it; an
|
|
8193
|
+
* ENOENT there is a per-path confirmation that the segment is gone (D296),
|
|
8194
|
+
* and the durable row is dropped through the same channel eviction uses. It
|
|
8195
|
+
* is reported for the same reason `rowsReconciled` is: this is a durable
|
|
8196
|
+
* mutation nobody asked for, and a migration that quietly erases hour rows is
|
|
8197
|
+
* the same failure as one that quietly skips them (D295).
|
|
8198
|
+
*
|
|
8199
|
+
* The production drain of 2026-08-30 would have reported 11 074 here — the
|
|
8200
|
+
* ledger claimed 5.65 GB of footage that no longer existed.
|
|
8201
|
+
*/
|
|
8202
|
+
rowsForgotten: number().int().nonnegative().optional(),
|
|
8189
8203
|
startedAt: number(),
|
|
8190
8204
|
finishedAt: number().nullable(),
|
|
8191
8205
|
error: string().nullable()
|
|
@@ -8549,6 +8563,91 @@ var RelocateResidueSchema = object({
|
|
|
8549
8563
|
segments: number().int().nonnegative(),
|
|
8550
8564
|
bytes: number().int().nonnegative()
|
|
8551
8565
|
}).nullable();
|
|
8566
|
+
/**
|
|
8567
|
+
* Ask one location whether its durable hour rows describe the disk — the walk
|
|
8568
|
+
* (D319).
|
|
8569
|
+
*
|
|
8570
|
+
* `apply` DEFAULTS TO FALSE and that default is the product: the operator's
|
|
8571
|
+
* missing tool is the question, and the dry run is how they sanity-check the
|
|
8572
|
+
* destructive run before authorising it.
|
|
8573
|
+
*/
|
|
8574
|
+
var LedgerWalkInputSchema = object({
|
|
8575
|
+
locationId: string().min(1),
|
|
8576
|
+
/** Forget the confirmed-absent rows, rather than only counting them. */
|
|
8577
|
+
apply: boolean().optional(),
|
|
8578
|
+
/** Narrow to one camera. */
|
|
8579
|
+
deviceId: number().int().positive().optional(),
|
|
8580
|
+
/** Narrow to these recording profiles; empty/absent = every profile. */
|
|
8581
|
+
profiles: array(string().min(1)).optional()
|
|
8582
|
+
});
|
|
8583
|
+
/** Why a whole walk did nothing. Every one leaves the ledger untouched. */
|
|
8584
|
+
var LedgerWalkRefusalSchema = _enum([
|
|
8585
|
+
"location-unknown",
|
|
8586
|
+
"source-writable",
|
|
8587
|
+
"no-ledger",
|
|
8588
|
+
"archive-unreadable",
|
|
8589
|
+
"anchor-absent",
|
|
8590
|
+
"anchor-unreadable",
|
|
8591
|
+
"anchor-moved"
|
|
8592
|
+
]);
|
|
8593
|
+
_enum([
|
|
8594
|
+
"live-tail",
|
|
8595
|
+
"listing-error",
|
|
8596
|
+
"path-mismatch",
|
|
8597
|
+
"durable-refused"
|
|
8598
|
+
]);
|
|
8599
|
+
/** Every skip reason, always present, always a number — so a reason that never
|
|
8600
|
+
* fired reports as zero rather than absent and the report shape is constant
|
|
8601
|
+
* between passes. Spelled out rather than `z.record` for exactly that. */
|
|
8602
|
+
var LedgerWalkSkipCountsSchema = object({
|
|
8603
|
+
"live-tail": number().int().nonnegative(),
|
|
8604
|
+
"listing-error": number().int().nonnegative(),
|
|
8605
|
+
"path-mismatch": number().int().nonnegative(),
|
|
8606
|
+
"durable-refused": number().int().nonnegative()
|
|
8607
|
+
});
|
|
8608
|
+
/** One camera's share of a walk, so a report names cameras and not rows. */
|
|
8609
|
+
var LedgerWalkDeviceReportSchema = object({
|
|
8610
|
+
deviceId: number().int(),
|
|
8611
|
+
hoursWalked: number().int().nonnegative(),
|
|
8612
|
+
hoursMissing: number().int().nonnegative(),
|
|
8613
|
+
ghostSegments: number().int().nonnegative(),
|
|
8614
|
+
ghostBytes: number().int().nonnegative(),
|
|
8615
|
+
forgottenSegments: number().int().nonnegative(),
|
|
8616
|
+
orphanFiles: number().int().nonnegative()
|
|
8617
|
+
});
|
|
8618
|
+
/**
|
|
8619
|
+
* What one walk claimed, listed, found and (only when armed) forgot.
|
|
8620
|
+
*
|
|
8621
|
+
* `archiveSegments` is the **M** and `segmentsClaimed` the **N** (D295), so a
|
|
8622
|
+
* walk that saw a fraction of the location is visible in its own report rather
|
|
8623
|
+
* than in the absence of one.
|
|
8624
|
+
*/
|
|
8625
|
+
var LedgerWalkReportSchema = object({
|
|
8626
|
+
locationId: string(),
|
|
8627
|
+
applied: boolean(),
|
|
8628
|
+
refused: LedgerWalkRefusalSchema.nullable(),
|
|
8629
|
+
archiveSegments: number().int().nonnegative().nullable(),
|
|
8630
|
+
archiveBytes: number().int().nonnegative().nullable(),
|
|
8631
|
+
hoursClaimed: number().int().nonnegative(),
|
|
8632
|
+
hoursWalked: number().int().nonnegative(),
|
|
8633
|
+
hoursMissing: number().int().nonnegative(),
|
|
8634
|
+
/** `readdir` calls issued — the cost, stated in the unit that is paid. */
|
|
8635
|
+
listings: number().int().nonnegative(),
|
|
8636
|
+
segmentsClaimed: number().int().nonnegative(),
|
|
8637
|
+
ghostSegments: number().int().nonnegative(),
|
|
8638
|
+
ghostBytes: number().int().nonnegative(),
|
|
8639
|
+
ghostHoursWhole: number().int().nonnegative(),
|
|
8640
|
+
forgottenSegments: number().int().nonnegative(),
|
|
8641
|
+
forgottenBytes: number().int().nonnegative(),
|
|
8642
|
+
/** Files under a claimed hour that no durable row names. Never deleted. */
|
|
8643
|
+
orphanFiles: number().int().nonnegative(),
|
|
8644
|
+
orphanSample: array(string()).readonly(),
|
|
8645
|
+
hoursSkipped: number().int().nonnegative(),
|
|
8646
|
+
skippedByReason: LedgerWalkSkipCountsSchema,
|
|
8647
|
+
/** The walk stopped at its per-pass hour bound with claims unwalked. */
|
|
8648
|
+
bounded: boolean(),
|
|
8649
|
+
byDevice: array(LedgerWalkDeviceReportSchema).readonly()
|
|
8650
|
+
});
|
|
8552
8651
|
/** How many rows a media pass would still act on against a given target — the
|
|
8553
8652
|
* media lane's denominator AND its residue, from ONE derivation so the two can
|
|
8554
8653
|
* never disagree. `null` = the count could not be taken. */
|
|
@@ -18965,13 +19064,15 @@ var ListGroupsPageSchema = object({
|
|
|
18965
19064
|
groups: array(AnalyticsGroupRecordSchema).readonly(),
|
|
18966
19065
|
nextCursor: string().nullable()
|
|
18967
19066
|
});
|
|
19067
|
+
var KEY_EVENTS_DEFAULT_LIMIT = 50;
|
|
19068
|
+
var KEY_EVENTS_MAX_LIMIT = 200;
|
|
18968
19069
|
var KeyEventQueryInput = object({
|
|
18969
19070
|
deviceId: number(),
|
|
18970
19071
|
/** Window lower bound (track firstSeen ≥ since). */
|
|
18971
19072
|
since: number(),
|
|
18972
19073
|
/** Window upper bound (track firstSeen ≤ until). */
|
|
18973
19074
|
until: number(),
|
|
18974
|
-
limit: number().int().min(1).max(
|
|
19075
|
+
limit: number().int().min(1).max(KEY_EVENTS_MAX_LIMIT).default(KEY_EVENTS_DEFAULT_LIMIT),
|
|
18975
19076
|
/** Drop tracks scoring below this importance. */
|
|
18976
19077
|
minImportance: number().min(0).max(1).optional(),
|
|
18977
19078
|
/** Restrict to a single class (e.g. 'person'). */
|
|
@@ -18993,6 +19094,32 @@ var KeyEventSchema = object({
|
|
|
18993
19094
|
...TrackFlagFields,
|
|
18994
19095
|
...TrackRetrainFields
|
|
18995
19096
|
});
|
|
19097
|
+
/** `getKeyEvents`' window and filters, asked of a SET of cameras at once. */
|
|
19098
|
+
var KeyEventBatchQueryInput = object({
|
|
19099
|
+
deviceIds: array(number()).min(1).max(200),
|
|
19100
|
+
since: number(),
|
|
19101
|
+
until: number(),
|
|
19102
|
+
/** Applied PER CAMERA, exactly as `getKeyEvents.limit` is — never a total
|
|
19103
|
+
* across the set, which would let a busy camera starve a quiet one of its
|
|
19104
|
+
* rows and change what the merged feed contains. */
|
|
19105
|
+
limit: number().int().min(1).max(KEY_EVENTS_MAX_LIMIT).default(KEY_EVENTS_DEFAULT_LIMIT),
|
|
19106
|
+
minImportance: number().min(0).max(1).optional(),
|
|
19107
|
+
classFilter: string().optional()
|
|
19108
|
+
});
|
|
19109
|
+
/**
|
|
19110
|
+
* One camera's key events in a batch answer.
|
|
19111
|
+
*
|
|
19112
|
+
* The row exists for every requested id. `getKeyEvents` degrades to `[]` on
|
|
19113
|
+
* error rather than throwing, so a camera whose store read failed and one with
|
|
19114
|
+
* no events in the window were ALREADY indistinguishable per camera — the
|
|
19115
|
+
* batch does not make that worse, and the row keeps the deviceId the single
|
|
19116
|
+
* method's output never carried (the caller used to stamp it from the fan-out
|
|
19117
|
+
* key, which only worked because there was one query per camera).
|
|
19118
|
+
*/
|
|
19119
|
+
var KeyEventsForDeviceSchema = object({
|
|
19120
|
+
deviceId: number(),
|
|
19121
|
+
events: array(KeyEventSchema).readonly()
|
|
19122
|
+
});
|
|
18996
19123
|
object({
|
|
18997
19124
|
trackId: string(),
|
|
18998
19125
|
className: string(),
|
|
@@ -19262,7 +19389,7 @@ DeviceType.Camera, method(object({ deviceId: number() }), array(TrackSchema).rea
|
|
|
19262
19389
|
until: number().optional(),
|
|
19263
19390
|
kinds: array(string()).optional(),
|
|
19264
19391
|
limit: number().int().min(1).max(MAX_EVENT_QUERY_LIMIT).default(DEFAULT_EVENT_QUERY_LIMIT)
|
|
19265
|
-
}), array(SensorEventSchema).readonly()), method(KeyEventQueryInput, array(KeyEventSchema).readonly()), method(object({
|
|
19392
|
+
}), array(SensorEventSchema).readonly()), method(KeyEventQueryInput, array(KeyEventSchema).readonly()), method(KeyEventBatchQueryInput, array(KeyEventsForDeviceSchema).readonly()), method(object({
|
|
19266
19393
|
deviceId: number(),
|
|
19267
19394
|
since: number(),
|
|
19268
19395
|
until: number(),
|
|
@@ -26914,6 +27041,9 @@ method(object({
|
|
|
26914
27041
|
}), method(RelocateResidueInputSchema, RelocateResidueSchema, {
|
|
26915
27042
|
kind: "query",
|
|
26916
27043
|
auth: "admin"
|
|
27044
|
+
}), method(LedgerWalkInputSchema, LedgerWalkReportSchema, {
|
|
27045
|
+
kind: "mutation",
|
|
27046
|
+
auth: "admin"
|
|
26917
27047
|
}), method(object({ jobId: string() }), object({ cancelled: boolean() }), {
|
|
26918
27048
|
kind: "mutation",
|
|
26919
27049
|
auth: "admin"
|
|
@@ -27305,7 +27435,26 @@ var SceneMonitorStatusSchema = object({
|
|
|
27305
27435
|
monitors: array(SceneMonitorSchema),
|
|
27306
27436
|
lastFetchedAt: number()
|
|
27307
27437
|
});
|
|
27308
|
-
|
|
27438
|
+
/**
|
|
27439
|
+
* One camera's row in a `listScenesBatch` answer.
|
|
27440
|
+
*
|
|
27441
|
+
* `status` is NULLABLE and the nullability is the whole point. `scene-monitor`
|
|
27442
|
+
* is a `defaultActive` wrapper, so every camera is asked; a camera whose
|
|
27443
|
+
* provider is absent (pipeline-analytics not deployed, the post-processing node
|
|
27444
|
+
* down) cannot answer, and that is not the same fact as a camera with no scenes
|
|
27445
|
+
* configured. Fanned out per camera the difference was visible — one query
|
|
27446
|
+
* errored while the others resolved — and a batch that returned only the rows
|
|
27447
|
+
* it managed would have destroyed it, silently, by making an unreachable camera
|
|
27448
|
+
* indistinguishable from one that answered `monitors: []`.
|
|
27449
|
+
*
|
|
27450
|
+
* So: EVERY requested deviceId gets a row. `status: null` means "this camera
|
|
27451
|
+
* could not be read"; `status.monitors: []` means "read, and it has none".
|
|
27452
|
+
*/
|
|
27453
|
+
var SceneMonitorStatusForDeviceSchema = object({
|
|
27454
|
+
deviceId: number(),
|
|
27455
|
+
status: SceneMonitorStatusSchema.nullable()
|
|
27456
|
+
});
|
|
27457
|
+
DeviceType.Camera, method(object({ deviceId: number() }), SceneMonitorStatusSchema), method(object({ deviceIds: array(number()).min(1).max(200) }), array(SceneMonitorStatusForDeviceSchema).readonly()), method(object({
|
|
27309
27458
|
deviceId: number(),
|
|
27310
27459
|
label: string(),
|
|
27311
27460
|
roi: MaskRectShapeSchema,
|
|
@@ -28629,6 +28778,27 @@ var CameraOccupancySnapshotSchema = object({
|
|
|
28629
28778
|
stationaryObjects: array(StationaryObjectSchema).readonly().optional()
|
|
28630
28779
|
});
|
|
28631
28780
|
/**
|
|
28781
|
+
* One camera's row in a `getCurrentSnapshotBatch` answer.
|
|
28782
|
+
*
|
|
28783
|
+
* THREE outcomes, and the single-camera method could only express two of them
|
|
28784
|
+
* because `snapshot: null` was already spoken for:
|
|
28785
|
+
*
|
|
28786
|
+
* - `read: 'read'`, `snapshot` present — the live occupancy reading.
|
|
28787
|
+
* - `read: 'read'`, `snapshot: null` — read, and this camera has no reading
|
|
28788
|
+
* yet: no frame since boot, and no parked-object registry to hydrate from.
|
|
28789
|
+
* - `read: 'unreadable'` — the owner could not answer for this
|
|
28790
|
+
* camera. `snapshot` is null, and it does NOT mean "nothing parked here".
|
|
28791
|
+
*
|
|
28792
|
+
* Collapsing the last two is the failure this field exists to prevent: a
|
|
28793
|
+
* hydration that threw would otherwise render as an empty Stationary section,
|
|
28794
|
+
* which is a definite claim about a camera nobody could read.
|
|
28795
|
+
*/
|
|
28796
|
+
var CameraOccupancySnapshotForDeviceSchema = object({
|
|
28797
|
+
deviceId: number(),
|
|
28798
|
+
read: _enum(["read", "unreadable"]),
|
|
28799
|
+
snapshot: CameraOccupancySnapshotSchema.nullable()
|
|
28800
|
+
});
|
|
28801
|
+
/**
|
|
28632
28802
|
* Time-series resolution. The history methods return one bucket per
|
|
28633
28803
|
* step over the requested range. Smaller resolutions cost more
|
|
28634
28804
|
* memory + bandwidth; bound to discrete steps so caller cannot ask
|
|
@@ -28652,7 +28822,7 @@ var HistoryPointSchema = object({
|
|
|
28652
28822
|
/** Object count averaged over the bucket (rounded to nearest integer). */
|
|
28653
28823
|
count: number().int().nonnegative()
|
|
28654
28824
|
});
|
|
28655
|
-
DeviceType.Camera, method(object({ deviceId: number() }), CameraOccupancySnapshotSchema.nullable()), method(object({
|
|
28825
|
+
DeviceType.Camera, method(object({ deviceId: number() }), CameraOccupancySnapshotSchema.nullable()), method(object({ deviceIds: array(number()).min(1).max(200) }), array(CameraOccupancySnapshotForDeviceSchema).readonly()), method(object({
|
|
28656
28826
|
deviceId: number(),
|
|
28657
28827
|
zoneId: string(),
|
|
28658
28828
|
className: string().optional()
|
|
@@ -31957,6 +32127,12 @@ Object.freeze({
|
|
|
31957
32127
|
addonId: null,
|
|
31958
32128
|
access: "view"
|
|
31959
32129
|
},
|
|
32130
|
+
"pipelineAnalytics.getKeyEventsBatch": {
|
|
32131
|
+
capName: "pipeline-analytics",
|
|
32132
|
+
capScope: "device",
|
|
32133
|
+
addonId: null,
|
|
32134
|
+
access: "view"
|
|
32135
|
+
},
|
|
31960
32136
|
"pipelineAnalytics.getMotionEvents": {
|
|
31961
32137
|
capName: "pipeline-analytics",
|
|
31962
32138
|
capScope: "device",
|
|
@@ -33133,6 +33309,12 @@ Object.freeze({
|
|
|
33133
33309
|
addonId: null,
|
|
33134
33310
|
access: "view"
|
|
33135
33311
|
},
|
|
33312
|
+
"recording.reconcileLedgerAgainstDisk": {
|
|
33313
|
+
capName: "recording",
|
|
33314
|
+
capScope: "system",
|
|
33315
|
+
addonId: null,
|
|
33316
|
+
access: "create"
|
|
33317
|
+
},
|
|
33136
33318
|
"recording.refreshStorageLocationsForMigration": {
|
|
33137
33319
|
capName: "recording",
|
|
33138
33320
|
capScope: "system",
|
|
@@ -33259,6 +33441,12 @@ Object.freeze({
|
|
|
33259
33441
|
addonId: null,
|
|
33260
33442
|
access: "view"
|
|
33261
33443
|
},
|
|
33444
|
+
"sceneMonitor.listScenesBatch": {
|
|
33445
|
+
capName: "scene-monitor",
|
|
33446
|
+
capScope: "device",
|
|
33447
|
+
addonId: null,
|
|
33448
|
+
access: "view"
|
|
33449
|
+
},
|
|
33262
33450
|
"sceneMonitor.recheckNow": {
|
|
33263
33451
|
capName: "scene-monitor",
|
|
33264
33452
|
capScope: "device",
|
|
@@ -34615,6 +34803,12 @@ Object.freeze({
|
|
|
34615
34803
|
addonId: null,
|
|
34616
34804
|
access: "view"
|
|
34617
34805
|
},
|
|
34806
|
+
"zoneAnalytics.getCurrentSnapshotBatch": {
|
|
34807
|
+
capName: "zone-analytics",
|
|
34808
|
+
capScope: "device",
|
|
34809
|
+
addonId: null,
|
|
34810
|
+
access: "view"
|
|
34811
|
+
},
|
|
34618
34812
|
"zoneAnalytics.getUnzonedHistory": {
|
|
34619
34813
|
capName: "zone-analytics",
|
|
34620
34814
|
capScope: "device",
|
|
@@ -35619,6 +35813,11 @@ Object.freeze({
|
|
|
35619
35813
|
form: "single",
|
|
35620
35814
|
optional: false
|
|
35621
35815
|
}],
|
|
35816
|
+
"pipelineAnalytics.getKeyEventsBatch": [{
|
|
35817
|
+
name: "deviceIds",
|
|
35818
|
+
form: "array",
|
|
35819
|
+
optional: false
|
|
35820
|
+
}],
|
|
35622
35821
|
"pipelineAnalytics.getMotionEvents": [{
|
|
35623
35822
|
name: "deviceId",
|
|
35624
35823
|
form: "single",
|
|
@@ -36059,6 +36258,11 @@ Object.freeze({
|
|
|
36059
36258
|
form: "single",
|
|
36060
36259
|
optional: false
|
|
36061
36260
|
}],
|
|
36261
|
+
"recording.reconcileLedgerAgainstDisk": [{
|
|
36262
|
+
name: "deviceId",
|
|
36263
|
+
form: "single",
|
|
36264
|
+
optional: true
|
|
36265
|
+
}],
|
|
36062
36266
|
"recording.relocateFootage": [{
|
|
36063
36267
|
name: "deviceId",
|
|
36064
36268
|
form: "single",
|
|
@@ -36124,6 +36328,11 @@ Object.freeze({
|
|
|
36124
36328
|
form: "single",
|
|
36125
36329
|
optional: false
|
|
36126
36330
|
}],
|
|
36331
|
+
"sceneMonitor.listScenesBatch": [{
|
|
36332
|
+
name: "deviceIds",
|
|
36333
|
+
form: "array",
|
|
36334
|
+
optional: false
|
|
36335
|
+
}],
|
|
36127
36336
|
"sceneMonitor.recheckNow": [{
|
|
36128
36337
|
name: "deviceId",
|
|
36129
36338
|
form: "single",
|
|
@@ -36385,6 +36594,11 @@ Object.freeze({
|
|
|
36385
36594
|
form: "single",
|
|
36386
36595
|
optional: false
|
|
36387
36596
|
}],
|
|
36597
|
+
"zoneAnalytics.getCurrentSnapshotBatch": [{
|
|
36598
|
+
name: "deviceIds",
|
|
36599
|
+
form: "array",
|
|
36600
|
+
optional: false
|
|
36601
|
+
}],
|
|
36388
36602
|
"zoneAnalytics.getUnzonedHistory": [{
|
|
36389
36603
|
name: "deviceId",
|
|
36390
36604
|
form: "single",
|
|
@@ -8159,6 +8159,20 @@ var RelocateJobSchema = object({
|
|
|
8159
8159
|
* in its row, not in its name, so `MediaRelocateEngine` never reconciles one.
|
|
8160
8160
|
*/
|
|
8161
8161
|
rowsReconciled: number().int().nonnegative().optional(),
|
|
8162
|
+
/**
|
|
8163
|
+
* Rows this run FORGOT because the file they name is not on disk.
|
|
8164
|
+
*
|
|
8165
|
+
* The mover derived the path from the row's own fields and `stat`ed it; an
|
|
8166
|
+
* ENOENT there is a per-path confirmation that the segment is gone (D296),
|
|
8167
|
+
* and the durable row is dropped through the same channel eviction uses. It
|
|
8168
|
+
* is reported for the same reason `rowsReconciled` is: this is a durable
|
|
8169
|
+
* mutation nobody asked for, and a migration that quietly erases hour rows is
|
|
8170
|
+
* the same failure as one that quietly skips them (D295).
|
|
8171
|
+
*
|
|
8172
|
+
* The production drain of 2026-08-30 would have reported 11 074 here — the
|
|
8173
|
+
* ledger claimed 5.65 GB of footage that no longer existed.
|
|
8174
|
+
*/
|
|
8175
|
+
rowsForgotten: number().int().nonnegative().optional(),
|
|
8162
8176
|
startedAt: number(),
|
|
8163
8177
|
finishedAt: number().nullable(),
|
|
8164
8178
|
error: string().nullable()
|
|
@@ -8522,6 +8536,91 @@ var RelocateResidueSchema = object({
|
|
|
8522
8536
|
segments: number().int().nonnegative(),
|
|
8523
8537
|
bytes: number().int().nonnegative()
|
|
8524
8538
|
}).nullable();
|
|
8539
|
+
/**
|
|
8540
|
+
* Ask one location whether its durable hour rows describe the disk — the walk
|
|
8541
|
+
* (D319).
|
|
8542
|
+
*
|
|
8543
|
+
* `apply` DEFAULTS TO FALSE and that default is the product: the operator's
|
|
8544
|
+
* missing tool is the question, and the dry run is how they sanity-check the
|
|
8545
|
+
* destructive run before authorising it.
|
|
8546
|
+
*/
|
|
8547
|
+
var LedgerWalkInputSchema = object({
|
|
8548
|
+
locationId: string().min(1),
|
|
8549
|
+
/** Forget the confirmed-absent rows, rather than only counting them. */
|
|
8550
|
+
apply: boolean().optional(),
|
|
8551
|
+
/** Narrow to one camera. */
|
|
8552
|
+
deviceId: number().int().positive().optional(),
|
|
8553
|
+
/** Narrow to these recording profiles; empty/absent = every profile. */
|
|
8554
|
+
profiles: array(string().min(1)).optional()
|
|
8555
|
+
});
|
|
8556
|
+
/** Why a whole walk did nothing. Every one leaves the ledger untouched. */
|
|
8557
|
+
var LedgerWalkRefusalSchema = _enum([
|
|
8558
|
+
"location-unknown",
|
|
8559
|
+
"source-writable",
|
|
8560
|
+
"no-ledger",
|
|
8561
|
+
"archive-unreadable",
|
|
8562
|
+
"anchor-absent",
|
|
8563
|
+
"anchor-unreadable",
|
|
8564
|
+
"anchor-moved"
|
|
8565
|
+
]);
|
|
8566
|
+
_enum([
|
|
8567
|
+
"live-tail",
|
|
8568
|
+
"listing-error",
|
|
8569
|
+
"path-mismatch",
|
|
8570
|
+
"durable-refused"
|
|
8571
|
+
]);
|
|
8572
|
+
/** Every skip reason, always present, always a number — so a reason that never
|
|
8573
|
+
* fired reports as zero rather than absent and the report shape is constant
|
|
8574
|
+
* between passes. Spelled out rather than `z.record` for exactly that. */
|
|
8575
|
+
var LedgerWalkSkipCountsSchema = object({
|
|
8576
|
+
"live-tail": number().int().nonnegative(),
|
|
8577
|
+
"listing-error": number().int().nonnegative(),
|
|
8578
|
+
"path-mismatch": number().int().nonnegative(),
|
|
8579
|
+
"durable-refused": number().int().nonnegative()
|
|
8580
|
+
});
|
|
8581
|
+
/** One camera's share of a walk, so a report names cameras and not rows. */
|
|
8582
|
+
var LedgerWalkDeviceReportSchema = object({
|
|
8583
|
+
deviceId: number().int(),
|
|
8584
|
+
hoursWalked: number().int().nonnegative(),
|
|
8585
|
+
hoursMissing: number().int().nonnegative(),
|
|
8586
|
+
ghostSegments: number().int().nonnegative(),
|
|
8587
|
+
ghostBytes: number().int().nonnegative(),
|
|
8588
|
+
forgottenSegments: number().int().nonnegative(),
|
|
8589
|
+
orphanFiles: number().int().nonnegative()
|
|
8590
|
+
});
|
|
8591
|
+
/**
|
|
8592
|
+
* What one walk claimed, listed, found and (only when armed) forgot.
|
|
8593
|
+
*
|
|
8594
|
+
* `archiveSegments` is the **M** and `segmentsClaimed` the **N** (D295), so a
|
|
8595
|
+
* walk that saw a fraction of the location is visible in its own report rather
|
|
8596
|
+
* than in the absence of one.
|
|
8597
|
+
*/
|
|
8598
|
+
var LedgerWalkReportSchema = object({
|
|
8599
|
+
locationId: string(),
|
|
8600
|
+
applied: boolean(),
|
|
8601
|
+
refused: LedgerWalkRefusalSchema.nullable(),
|
|
8602
|
+
archiveSegments: number().int().nonnegative().nullable(),
|
|
8603
|
+
archiveBytes: number().int().nonnegative().nullable(),
|
|
8604
|
+
hoursClaimed: number().int().nonnegative(),
|
|
8605
|
+
hoursWalked: number().int().nonnegative(),
|
|
8606
|
+
hoursMissing: number().int().nonnegative(),
|
|
8607
|
+
/** `readdir` calls issued — the cost, stated in the unit that is paid. */
|
|
8608
|
+
listings: number().int().nonnegative(),
|
|
8609
|
+
segmentsClaimed: number().int().nonnegative(),
|
|
8610
|
+
ghostSegments: number().int().nonnegative(),
|
|
8611
|
+
ghostBytes: number().int().nonnegative(),
|
|
8612
|
+
ghostHoursWhole: number().int().nonnegative(),
|
|
8613
|
+
forgottenSegments: number().int().nonnegative(),
|
|
8614
|
+
forgottenBytes: number().int().nonnegative(),
|
|
8615
|
+
/** Files under a claimed hour that no durable row names. Never deleted. */
|
|
8616
|
+
orphanFiles: number().int().nonnegative(),
|
|
8617
|
+
orphanSample: array(string()).readonly(),
|
|
8618
|
+
hoursSkipped: number().int().nonnegative(),
|
|
8619
|
+
skippedByReason: LedgerWalkSkipCountsSchema,
|
|
8620
|
+
/** The walk stopped at its per-pass hour bound with claims unwalked. */
|
|
8621
|
+
bounded: boolean(),
|
|
8622
|
+
byDevice: array(LedgerWalkDeviceReportSchema).readonly()
|
|
8623
|
+
});
|
|
8525
8624
|
/** How many rows a media pass would still act on against a given target — the
|
|
8526
8625
|
* media lane's denominator AND its residue, from ONE derivation so the two can
|
|
8527
8626
|
* never disagree. `null` = the count could not be taken. */
|
|
@@ -18938,13 +19037,15 @@ var ListGroupsPageSchema = object({
|
|
|
18938
19037
|
groups: array(AnalyticsGroupRecordSchema).readonly(),
|
|
18939
19038
|
nextCursor: string().nullable()
|
|
18940
19039
|
});
|
|
19040
|
+
var KEY_EVENTS_DEFAULT_LIMIT = 50;
|
|
19041
|
+
var KEY_EVENTS_MAX_LIMIT = 200;
|
|
18941
19042
|
var KeyEventQueryInput = object({
|
|
18942
19043
|
deviceId: number(),
|
|
18943
19044
|
/** Window lower bound (track firstSeen ≥ since). */
|
|
18944
19045
|
since: number(),
|
|
18945
19046
|
/** Window upper bound (track firstSeen ≤ until). */
|
|
18946
19047
|
until: number(),
|
|
18947
|
-
limit: number().int().min(1).max(
|
|
19048
|
+
limit: number().int().min(1).max(KEY_EVENTS_MAX_LIMIT).default(KEY_EVENTS_DEFAULT_LIMIT),
|
|
18948
19049
|
/** Drop tracks scoring below this importance. */
|
|
18949
19050
|
minImportance: number().min(0).max(1).optional(),
|
|
18950
19051
|
/** Restrict to a single class (e.g. 'person'). */
|
|
@@ -18966,6 +19067,32 @@ var KeyEventSchema = object({
|
|
|
18966
19067
|
...TrackFlagFields,
|
|
18967
19068
|
...TrackRetrainFields
|
|
18968
19069
|
});
|
|
19070
|
+
/** `getKeyEvents`' window and filters, asked of a SET of cameras at once. */
|
|
19071
|
+
var KeyEventBatchQueryInput = object({
|
|
19072
|
+
deviceIds: array(number()).min(1).max(200),
|
|
19073
|
+
since: number(),
|
|
19074
|
+
until: number(),
|
|
19075
|
+
/** Applied PER CAMERA, exactly as `getKeyEvents.limit` is — never a total
|
|
19076
|
+
* across the set, which would let a busy camera starve a quiet one of its
|
|
19077
|
+
* rows and change what the merged feed contains. */
|
|
19078
|
+
limit: number().int().min(1).max(KEY_EVENTS_MAX_LIMIT).default(KEY_EVENTS_DEFAULT_LIMIT),
|
|
19079
|
+
minImportance: number().min(0).max(1).optional(),
|
|
19080
|
+
classFilter: string().optional()
|
|
19081
|
+
});
|
|
19082
|
+
/**
|
|
19083
|
+
* One camera's key events in a batch answer.
|
|
19084
|
+
*
|
|
19085
|
+
* The row exists for every requested id. `getKeyEvents` degrades to `[]` on
|
|
19086
|
+
* error rather than throwing, so a camera whose store read failed and one with
|
|
19087
|
+
* no events in the window were ALREADY indistinguishable per camera — the
|
|
19088
|
+
* batch does not make that worse, and the row keeps the deviceId the single
|
|
19089
|
+
* method's output never carried (the caller used to stamp it from the fan-out
|
|
19090
|
+
* key, which only worked because there was one query per camera).
|
|
19091
|
+
*/
|
|
19092
|
+
var KeyEventsForDeviceSchema = object({
|
|
19093
|
+
deviceId: number(),
|
|
19094
|
+
events: array(KeyEventSchema).readonly()
|
|
19095
|
+
});
|
|
18969
19096
|
object({
|
|
18970
19097
|
trackId: string(),
|
|
18971
19098
|
className: string(),
|
|
@@ -19235,7 +19362,7 @@ DeviceType.Camera, method(object({ deviceId: number() }), array(TrackSchema).rea
|
|
|
19235
19362
|
until: number().optional(),
|
|
19236
19363
|
kinds: array(string()).optional(),
|
|
19237
19364
|
limit: number().int().min(1).max(MAX_EVENT_QUERY_LIMIT).default(DEFAULT_EVENT_QUERY_LIMIT)
|
|
19238
|
-
}), array(SensorEventSchema).readonly()), method(KeyEventQueryInput, array(KeyEventSchema).readonly()), method(object({
|
|
19365
|
+
}), array(SensorEventSchema).readonly()), method(KeyEventQueryInput, array(KeyEventSchema).readonly()), method(KeyEventBatchQueryInput, array(KeyEventsForDeviceSchema).readonly()), method(object({
|
|
19239
19366
|
deviceId: number(),
|
|
19240
19367
|
since: number(),
|
|
19241
19368
|
until: number(),
|
|
@@ -26887,6 +27014,9 @@ method(object({
|
|
|
26887
27014
|
}), method(RelocateResidueInputSchema, RelocateResidueSchema, {
|
|
26888
27015
|
kind: "query",
|
|
26889
27016
|
auth: "admin"
|
|
27017
|
+
}), method(LedgerWalkInputSchema, LedgerWalkReportSchema, {
|
|
27018
|
+
kind: "mutation",
|
|
27019
|
+
auth: "admin"
|
|
26890
27020
|
}), method(object({ jobId: string() }), object({ cancelled: boolean() }), {
|
|
26891
27021
|
kind: "mutation",
|
|
26892
27022
|
auth: "admin"
|
|
@@ -27278,7 +27408,26 @@ var SceneMonitorStatusSchema = object({
|
|
|
27278
27408
|
monitors: array(SceneMonitorSchema),
|
|
27279
27409
|
lastFetchedAt: number()
|
|
27280
27410
|
});
|
|
27281
|
-
|
|
27411
|
+
/**
|
|
27412
|
+
* One camera's row in a `listScenesBatch` answer.
|
|
27413
|
+
*
|
|
27414
|
+
* `status` is NULLABLE and the nullability is the whole point. `scene-monitor`
|
|
27415
|
+
* is a `defaultActive` wrapper, so every camera is asked; a camera whose
|
|
27416
|
+
* provider is absent (pipeline-analytics not deployed, the post-processing node
|
|
27417
|
+
* down) cannot answer, and that is not the same fact as a camera with no scenes
|
|
27418
|
+
* configured. Fanned out per camera the difference was visible — one query
|
|
27419
|
+
* errored while the others resolved — and a batch that returned only the rows
|
|
27420
|
+
* it managed would have destroyed it, silently, by making an unreachable camera
|
|
27421
|
+
* indistinguishable from one that answered `monitors: []`.
|
|
27422
|
+
*
|
|
27423
|
+
* So: EVERY requested deviceId gets a row. `status: null` means "this camera
|
|
27424
|
+
* could not be read"; `status.monitors: []` means "read, and it has none".
|
|
27425
|
+
*/
|
|
27426
|
+
var SceneMonitorStatusForDeviceSchema = object({
|
|
27427
|
+
deviceId: number(),
|
|
27428
|
+
status: SceneMonitorStatusSchema.nullable()
|
|
27429
|
+
});
|
|
27430
|
+
DeviceType.Camera, method(object({ deviceId: number() }), SceneMonitorStatusSchema), method(object({ deviceIds: array(number()).min(1).max(200) }), array(SceneMonitorStatusForDeviceSchema).readonly()), method(object({
|
|
27282
27431
|
deviceId: number(),
|
|
27283
27432
|
label: string(),
|
|
27284
27433
|
roi: MaskRectShapeSchema,
|
|
@@ -28602,6 +28751,27 @@ var CameraOccupancySnapshotSchema = object({
|
|
|
28602
28751
|
stationaryObjects: array(StationaryObjectSchema).readonly().optional()
|
|
28603
28752
|
});
|
|
28604
28753
|
/**
|
|
28754
|
+
* One camera's row in a `getCurrentSnapshotBatch` answer.
|
|
28755
|
+
*
|
|
28756
|
+
* THREE outcomes, and the single-camera method could only express two of them
|
|
28757
|
+
* because `snapshot: null` was already spoken for:
|
|
28758
|
+
*
|
|
28759
|
+
* - `read: 'read'`, `snapshot` present — the live occupancy reading.
|
|
28760
|
+
* - `read: 'read'`, `snapshot: null` — read, and this camera has no reading
|
|
28761
|
+
* yet: no frame since boot, and no parked-object registry to hydrate from.
|
|
28762
|
+
* - `read: 'unreadable'` — the owner could not answer for this
|
|
28763
|
+
* camera. `snapshot` is null, and it does NOT mean "nothing parked here".
|
|
28764
|
+
*
|
|
28765
|
+
* Collapsing the last two is the failure this field exists to prevent: a
|
|
28766
|
+
* hydration that threw would otherwise render as an empty Stationary section,
|
|
28767
|
+
* which is a definite claim about a camera nobody could read.
|
|
28768
|
+
*/
|
|
28769
|
+
var CameraOccupancySnapshotForDeviceSchema = object({
|
|
28770
|
+
deviceId: number(),
|
|
28771
|
+
read: _enum(["read", "unreadable"]),
|
|
28772
|
+
snapshot: CameraOccupancySnapshotSchema.nullable()
|
|
28773
|
+
});
|
|
28774
|
+
/**
|
|
28605
28775
|
* Time-series resolution. The history methods return one bucket per
|
|
28606
28776
|
* step over the requested range. Smaller resolutions cost more
|
|
28607
28777
|
* memory + bandwidth; bound to discrete steps so caller cannot ask
|
|
@@ -28625,7 +28795,7 @@ var HistoryPointSchema = object({
|
|
|
28625
28795
|
/** Object count averaged over the bucket (rounded to nearest integer). */
|
|
28626
28796
|
count: number().int().nonnegative()
|
|
28627
28797
|
});
|
|
28628
|
-
DeviceType.Camera, method(object({ deviceId: number() }), CameraOccupancySnapshotSchema.nullable()), method(object({
|
|
28798
|
+
DeviceType.Camera, method(object({ deviceId: number() }), CameraOccupancySnapshotSchema.nullable()), method(object({ deviceIds: array(number()).min(1).max(200) }), array(CameraOccupancySnapshotForDeviceSchema).readonly()), method(object({
|
|
28629
28799
|
deviceId: number(),
|
|
28630
28800
|
zoneId: string(),
|
|
28631
28801
|
className: string().optional()
|
|
@@ -31930,6 +32100,12 @@ Object.freeze({
|
|
|
31930
32100
|
addonId: null,
|
|
31931
32101
|
access: "view"
|
|
31932
32102
|
},
|
|
32103
|
+
"pipelineAnalytics.getKeyEventsBatch": {
|
|
32104
|
+
capName: "pipeline-analytics",
|
|
32105
|
+
capScope: "device",
|
|
32106
|
+
addonId: null,
|
|
32107
|
+
access: "view"
|
|
32108
|
+
},
|
|
31933
32109
|
"pipelineAnalytics.getMotionEvents": {
|
|
31934
32110
|
capName: "pipeline-analytics",
|
|
31935
32111
|
capScope: "device",
|
|
@@ -33106,6 +33282,12 @@ Object.freeze({
|
|
|
33106
33282
|
addonId: null,
|
|
33107
33283
|
access: "view"
|
|
33108
33284
|
},
|
|
33285
|
+
"recording.reconcileLedgerAgainstDisk": {
|
|
33286
|
+
capName: "recording",
|
|
33287
|
+
capScope: "system",
|
|
33288
|
+
addonId: null,
|
|
33289
|
+
access: "create"
|
|
33290
|
+
},
|
|
33109
33291
|
"recording.refreshStorageLocationsForMigration": {
|
|
33110
33292
|
capName: "recording",
|
|
33111
33293
|
capScope: "system",
|
|
@@ -33232,6 +33414,12 @@ Object.freeze({
|
|
|
33232
33414
|
addonId: null,
|
|
33233
33415
|
access: "view"
|
|
33234
33416
|
},
|
|
33417
|
+
"sceneMonitor.listScenesBatch": {
|
|
33418
|
+
capName: "scene-monitor",
|
|
33419
|
+
capScope: "device",
|
|
33420
|
+
addonId: null,
|
|
33421
|
+
access: "view"
|
|
33422
|
+
},
|
|
33235
33423
|
"sceneMonitor.recheckNow": {
|
|
33236
33424
|
capName: "scene-monitor",
|
|
33237
33425
|
capScope: "device",
|
|
@@ -34588,6 +34776,12 @@ Object.freeze({
|
|
|
34588
34776
|
addonId: null,
|
|
34589
34777
|
access: "view"
|
|
34590
34778
|
},
|
|
34779
|
+
"zoneAnalytics.getCurrentSnapshotBatch": {
|
|
34780
|
+
capName: "zone-analytics",
|
|
34781
|
+
capScope: "device",
|
|
34782
|
+
addonId: null,
|
|
34783
|
+
access: "view"
|
|
34784
|
+
},
|
|
34591
34785
|
"zoneAnalytics.getUnzonedHistory": {
|
|
34592
34786
|
capName: "zone-analytics",
|
|
34593
34787
|
capScope: "device",
|
|
@@ -35592,6 +35786,11 @@ Object.freeze({
|
|
|
35592
35786
|
form: "single",
|
|
35593
35787
|
optional: false
|
|
35594
35788
|
}],
|
|
35789
|
+
"pipelineAnalytics.getKeyEventsBatch": [{
|
|
35790
|
+
name: "deviceIds",
|
|
35791
|
+
form: "array",
|
|
35792
|
+
optional: false
|
|
35793
|
+
}],
|
|
35595
35794
|
"pipelineAnalytics.getMotionEvents": [{
|
|
35596
35795
|
name: "deviceId",
|
|
35597
35796
|
form: "single",
|
|
@@ -36032,6 +36231,11 @@ Object.freeze({
|
|
|
36032
36231
|
form: "single",
|
|
36033
36232
|
optional: false
|
|
36034
36233
|
}],
|
|
36234
|
+
"recording.reconcileLedgerAgainstDisk": [{
|
|
36235
|
+
name: "deviceId",
|
|
36236
|
+
form: "single",
|
|
36237
|
+
optional: true
|
|
36238
|
+
}],
|
|
36035
36239
|
"recording.relocateFootage": [{
|
|
36036
36240
|
name: "deviceId",
|
|
36037
36241
|
form: "single",
|
|
@@ -36097,6 +36301,11 @@ Object.freeze({
|
|
|
36097
36301
|
form: "single",
|
|
36098
36302
|
optional: false
|
|
36099
36303
|
}],
|
|
36304
|
+
"sceneMonitor.listScenesBatch": [{
|
|
36305
|
+
name: "deviceIds",
|
|
36306
|
+
form: "array",
|
|
36307
|
+
optional: false
|
|
36308
|
+
}],
|
|
36100
36309
|
"sceneMonitor.recheckNow": [{
|
|
36101
36310
|
name: "deviceId",
|
|
36102
36311
|
form: "single",
|
|
@@ -36358,6 +36567,11 @@ Object.freeze({
|
|
|
36358
36567
|
form: "single",
|
|
36359
36568
|
optional: false
|
|
36360
36569
|
}],
|
|
36570
|
+
"zoneAnalytics.getCurrentSnapshotBatch": [{
|
|
36571
|
+
name: "deviceIds",
|
|
36572
|
+
form: "array",
|
|
36573
|
+
optional: false
|
|
36574
|
+
}],
|
|
36361
36575
|
"zoneAnalytics.getUnzonedHistory": [{
|
|
36362
36576
|
name: "deviceId",
|
|
36363
36577
|
form: "single",
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@camstack/addon-export-alexa",
|
|
3
|
-
"version": "1.2.
|
|
3
|
+
"version": "1.2.55",
|
|
4
4
|
"description": "Alexa Smart Home Skill export — hub-side OAuth provider + directive handler. The companion AWS Lambda forwards Alexa directives to this addon's /addon/export-alexa/directive endpoint.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"camstack",
|