@camstack/addon-export-google 0.1.12 → 0.1.13
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-google.addon.js +218 -4
- package/dist/export-google.addon.mjs +218 -4
- package/package.json +1 -1
|
@@ -8211,6 +8211,20 @@ var RelocateJobSchema = object({
|
|
|
8211
8211
|
* in its row, not in its name, so `MediaRelocateEngine` never reconciles one.
|
|
8212
8212
|
*/
|
|
8213
8213
|
rowsReconciled: number().int().nonnegative().optional(),
|
|
8214
|
+
/**
|
|
8215
|
+
* Rows this run FORGOT because the file they name is not on disk.
|
|
8216
|
+
*
|
|
8217
|
+
* The mover derived the path from the row's own fields and `stat`ed it; an
|
|
8218
|
+
* ENOENT there is a per-path confirmation that the segment is gone (D296),
|
|
8219
|
+
* and the durable row is dropped through the same channel eviction uses. It
|
|
8220
|
+
* is reported for the same reason `rowsReconciled` is: this is a durable
|
|
8221
|
+
* mutation nobody asked for, and a migration that quietly erases hour rows is
|
|
8222
|
+
* the same failure as one that quietly skips them (D295).
|
|
8223
|
+
*
|
|
8224
|
+
* The production drain of 2026-08-30 would have reported 11 074 here — the
|
|
8225
|
+
* ledger claimed 5.65 GB of footage that no longer existed.
|
|
8226
|
+
*/
|
|
8227
|
+
rowsForgotten: number().int().nonnegative().optional(),
|
|
8214
8228
|
startedAt: number(),
|
|
8215
8229
|
finishedAt: number().nullable(),
|
|
8216
8230
|
error: string().nullable()
|
|
@@ -8574,6 +8588,91 @@ var RelocateResidueSchema = object({
|
|
|
8574
8588
|
segments: number().int().nonnegative(),
|
|
8575
8589
|
bytes: number().int().nonnegative()
|
|
8576
8590
|
}).nullable();
|
|
8591
|
+
/**
|
|
8592
|
+
* Ask one location whether its durable hour rows describe the disk — the walk
|
|
8593
|
+
* (D319).
|
|
8594
|
+
*
|
|
8595
|
+
* `apply` DEFAULTS TO FALSE and that default is the product: the operator's
|
|
8596
|
+
* missing tool is the question, and the dry run is how they sanity-check the
|
|
8597
|
+
* destructive run before authorising it.
|
|
8598
|
+
*/
|
|
8599
|
+
var LedgerWalkInputSchema = object({
|
|
8600
|
+
locationId: string().min(1),
|
|
8601
|
+
/** Forget the confirmed-absent rows, rather than only counting them. */
|
|
8602
|
+
apply: boolean().optional(),
|
|
8603
|
+
/** Narrow to one camera. */
|
|
8604
|
+
deviceId: number().int().positive().optional(),
|
|
8605
|
+
/** Narrow to these recording profiles; empty/absent = every profile. */
|
|
8606
|
+
profiles: array(string().min(1)).optional()
|
|
8607
|
+
});
|
|
8608
|
+
/** Why a whole walk did nothing. Every one leaves the ledger untouched. */
|
|
8609
|
+
var LedgerWalkRefusalSchema = _enum([
|
|
8610
|
+
"location-unknown",
|
|
8611
|
+
"source-writable",
|
|
8612
|
+
"no-ledger",
|
|
8613
|
+
"archive-unreadable",
|
|
8614
|
+
"anchor-absent",
|
|
8615
|
+
"anchor-unreadable",
|
|
8616
|
+
"anchor-moved"
|
|
8617
|
+
]);
|
|
8618
|
+
_enum([
|
|
8619
|
+
"live-tail",
|
|
8620
|
+
"listing-error",
|
|
8621
|
+
"path-mismatch",
|
|
8622
|
+
"durable-refused"
|
|
8623
|
+
]);
|
|
8624
|
+
/** Every skip reason, always present, always a number — so a reason that never
|
|
8625
|
+
* fired reports as zero rather than absent and the report shape is constant
|
|
8626
|
+
* between passes. Spelled out rather than `z.record` for exactly that. */
|
|
8627
|
+
var LedgerWalkSkipCountsSchema = object({
|
|
8628
|
+
"live-tail": number().int().nonnegative(),
|
|
8629
|
+
"listing-error": number().int().nonnegative(),
|
|
8630
|
+
"path-mismatch": number().int().nonnegative(),
|
|
8631
|
+
"durable-refused": number().int().nonnegative()
|
|
8632
|
+
});
|
|
8633
|
+
/** One camera's share of a walk, so a report names cameras and not rows. */
|
|
8634
|
+
var LedgerWalkDeviceReportSchema = object({
|
|
8635
|
+
deviceId: number().int(),
|
|
8636
|
+
hoursWalked: number().int().nonnegative(),
|
|
8637
|
+
hoursMissing: number().int().nonnegative(),
|
|
8638
|
+
ghostSegments: number().int().nonnegative(),
|
|
8639
|
+
ghostBytes: number().int().nonnegative(),
|
|
8640
|
+
forgottenSegments: number().int().nonnegative(),
|
|
8641
|
+
orphanFiles: number().int().nonnegative()
|
|
8642
|
+
});
|
|
8643
|
+
/**
|
|
8644
|
+
* What one walk claimed, listed, found and (only when armed) forgot.
|
|
8645
|
+
*
|
|
8646
|
+
* `archiveSegments` is the **M** and `segmentsClaimed` the **N** (D295), so a
|
|
8647
|
+
* walk that saw a fraction of the location is visible in its own report rather
|
|
8648
|
+
* than in the absence of one.
|
|
8649
|
+
*/
|
|
8650
|
+
var LedgerWalkReportSchema = object({
|
|
8651
|
+
locationId: string(),
|
|
8652
|
+
applied: boolean(),
|
|
8653
|
+
refused: LedgerWalkRefusalSchema.nullable(),
|
|
8654
|
+
archiveSegments: number().int().nonnegative().nullable(),
|
|
8655
|
+
archiveBytes: number().int().nonnegative().nullable(),
|
|
8656
|
+
hoursClaimed: number().int().nonnegative(),
|
|
8657
|
+
hoursWalked: number().int().nonnegative(),
|
|
8658
|
+
hoursMissing: number().int().nonnegative(),
|
|
8659
|
+
/** `readdir` calls issued — the cost, stated in the unit that is paid. */
|
|
8660
|
+
listings: number().int().nonnegative(),
|
|
8661
|
+
segmentsClaimed: number().int().nonnegative(),
|
|
8662
|
+
ghostSegments: number().int().nonnegative(),
|
|
8663
|
+
ghostBytes: number().int().nonnegative(),
|
|
8664
|
+
ghostHoursWhole: number().int().nonnegative(),
|
|
8665
|
+
forgottenSegments: number().int().nonnegative(),
|
|
8666
|
+
forgottenBytes: number().int().nonnegative(),
|
|
8667
|
+
/** Files under a claimed hour that no durable row names. Never deleted. */
|
|
8668
|
+
orphanFiles: number().int().nonnegative(),
|
|
8669
|
+
orphanSample: array(string()).readonly(),
|
|
8670
|
+
hoursSkipped: number().int().nonnegative(),
|
|
8671
|
+
skippedByReason: LedgerWalkSkipCountsSchema,
|
|
8672
|
+
/** The walk stopped at its per-pass hour bound with claims unwalked. */
|
|
8673
|
+
bounded: boolean(),
|
|
8674
|
+
byDevice: array(LedgerWalkDeviceReportSchema).readonly()
|
|
8675
|
+
});
|
|
8577
8676
|
/** How many rows a media pass would still act on against a given target — the
|
|
8578
8677
|
* media lane's denominator AND its residue, from ONE derivation so the two can
|
|
8579
8678
|
* never disagree. `null` = the count could not be taken. */
|
|
@@ -18936,13 +19035,15 @@ var ListGroupsPageSchema = object({
|
|
|
18936
19035
|
groups: array(AnalyticsGroupRecordSchema).readonly(),
|
|
18937
19036
|
nextCursor: string().nullable()
|
|
18938
19037
|
});
|
|
19038
|
+
var KEY_EVENTS_DEFAULT_LIMIT = 50;
|
|
19039
|
+
var KEY_EVENTS_MAX_LIMIT = 200;
|
|
18939
19040
|
var KeyEventQueryInput = object({
|
|
18940
19041
|
deviceId: number(),
|
|
18941
19042
|
/** Window lower bound (track firstSeen ≥ since). */
|
|
18942
19043
|
since: number(),
|
|
18943
19044
|
/** Window upper bound (track firstSeen ≤ until). */
|
|
18944
19045
|
until: number(),
|
|
18945
|
-
limit: number().int().min(1).max(
|
|
19046
|
+
limit: number().int().min(1).max(KEY_EVENTS_MAX_LIMIT).default(KEY_EVENTS_DEFAULT_LIMIT),
|
|
18946
19047
|
/** Drop tracks scoring below this importance. */
|
|
18947
19048
|
minImportance: number().min(0).max(1).optional(),
|
|
18948
19049
|
/** Restrict to a single class (e.g. 'person'). */
|
|
@@ -18964,6 +19065,32 @@ var KeyEventSchema = object({
|
|
|
18964
19065
|
...TrackFlagFields,
|
|
18965
19066
|
...TrackRetrainFields
|
|
18966
19067
|
});
|
|
19068
|
+
/** `getKeyEvents`' window and filters, asked of a SET of cameras at once. */
|
|
19069
|
+
var KeyEventBatchQueryInput = object({
|
|
19070
|
+
deviceIds: array(number()).min(1).max(200),
|
|
19071
|
+
since: number(),
|
|
19072
|
+
until: number(),
|
|
19073
|
+
/** Applied PER CAMERA, exactly as `getKeyEvents.limit` is — never a total
|
|
19074
|
+
* across the set, which would let a busy camera starve a quiet one of its
|
|
19075
|
+
* rows and change what the merged feed contains. */
|
|
19076
|
+
limit: number().int().min(1).max(KEY_EVENTS_MAX_LIMIT).default(KEY_EVENTS_DEFAULT_LIMIT),
|
|
19077
|
+
minImportance: number().min(0).max(1).optional(),
|
|
19078
|
+
classFilter: string().optional()
|
|
19079
|
+
});
|
|
19080
|
+
/**
|
|
19081
|
+
* One camera's key events in a batch answer.
|
|
19082
|
+
*
|
|
19083
|
+
* The row exists for every requested id. `getKeyEvents` degrades to `[]` on
|
|
19084
|
+
* error rather than throwing, so a camera whose store read failed and one with
|
|
19085
|
+
* no events in the window were ALREADY indistinguishable per camera — the
|
|
19086
|
+
* batch does not make that worse, and the row keeps the deviceId the single
|
|
19087
|
+
* method's output never carried (the caller used to stamp it from the fan-out
|
|
19088
|
+
* key, which only worked because there was one query per camera).
|
|
19089
|
+
*/
|
|
19090
|
+
var KeyEventsForDeviceSchema = object({
|
|
19091
|
+
deviceId: number(),
|
|
19092
|
+
events: array(KeyEventSchema).readonly()
|
|
19093
|
+
});
|
|
18967
19094
|
object({
|
|
18968
19095
|
trackId: string(),
|
|
18969
19096
|
className: string(),
|
|
@@ -19233,7 +19360,7 @@ DeviceType.Camera, method(object({ deviceId: number() }), array(TrackSchema).rea
|
|
|
19233
19360
|
until: number().optional(),
|
|
19234
19361
|
kinds: array(string()).optional(),
|
|
19235
19362
|
limit: number().int().min(1).max(MAX_EVENT_QUERY_LIMIT).default(DEFAULT_EVENT_QUERY_LIMIT)
|
|
19236
|
-
}), array(SensorEventSchema).readonly()), method(KeyEventQueryInput, array(KeyEventSchema).readonly()), method(object({
|
|
19363
|
+
}), array(SensorEventSchema).readonly()), method(KeyEventQueryInput, array(KeyEventSchema).readonly()), method(KeyEventBatchQueryInput, array(KeyEventsForDeviceSchema).readonly()), method(object({
|
|
19237
19364
|
deviceId: number(),
|
|
19238
19365
|
since: number(),
|
|
19239
19366
|
until: number(),
|
|
@@ -26897,6 +27024,9 @@ method(object({
|
|
|
26897
27024
|
}), method(RelocateResidueInputSchema, RelocateResidueSchema, {
|
|
26898
27025
|
kind: "query",
|
|
26899
27026
|
auth: "admin"
|
|
27027
|
+
}), method(LedgerWalkInputSchema, LedgerWalkReportSchema, {
|
|
27028
|
+
kind: "mutation",
|
|
27029
|
+
auth: "admin"
|
|
26900
27030
|
}), method(object({ jobId: string() }), object({ cancelled: boolean() }), {
|
|
26901
27031
|
kind: "mutation",
|
|
26902
27032
|
auth: "admin"
|
|
@@ -27288,7 +27418,26 @@ var SceneMonitorStatusSchema = object({
|
|
|
27288
27418
|
monitors: array(SceneMonitorSchema),
|
|
27289
27419
|
lastFetchedAt: number()
|
|
27290
27420
|
});
|
|
27291
|
-
|
|
27421
|
+
/**
|
|
27422
|
+
* One camera's row in a `listScenesBatch` answer.
|
|
27423
|
+
*
|
|
27424
|
+
* `status` is NULLABLE and the nullability is the whole point. `scene-monitor`
|
|
27425
|
+
* is a `defaultActive` wrapper, so every camera is asked; a camera whose
|
|
27426
|
+
* provider is absent (pipeline-analytics not deployed, the post-processing node
|
|
27427
|
+
* down) cannot answer, and that is not the same fact as a camera with no scenes
|
|
27428
|
+
* configured. Fanned out per camera the difference was visible — one query
|
|
27429
|
+
* errored while the others resolved — and a batch that returned only the rows
|
|
27430
|
+
* it managed would have destroyed it, silently, by making an unreachable camera
|
|
27431
|
+
* indistinguishable from one that answered `monitors: []`.
|
|
27432
|
+
*
|
|
27433
|
+
* So: EVERY requested deviceId gets a row. `status: null` means "this camera
|
|
27434
|
+
* could not be read"; `status.monitors: []` means "read, and it has none".
|
|
27435
|
+
*/
|
|
27436
|
+
var SceneMonitorStatusForDeviceSchema = object({
|
|
27437
|
+
deviceId: number(),
|
|
27438
|
+
status: SceneMonitorStatusSchema.nullable()
|
|
27439
|
+
});
|
|
27440
|
+
DeviceType.Camera, method(object({ deviceId: number() }), SceneMonitorStatusSchema), method(object({ deviceIds: array(number()).min(1).max(200) }), array(SceneMonitorStatusForDeviceSchema).readonly()), method(object({
|
|
27292
27441
|
deviceId: number(),
|
|
27293
27442
|
label: string(),
|
|
27294
27443
|
roi: MaskRectShapeSchema,
|
|
@@ -28619,6 +28768,27 @@ var CameraOccupancySnapshotSchema = object({
|
|
|
28619
28768
|
stationaryObjects: array(StationaryObjectSchema).readonly().optional()
|
|
28620
28769
|
});
|
|
28621
28770
|
/**
|
|
28771
|
+
* One camera's row in a `getCurrentSnapshotBatch` answer.
|
|
28772
|
+
*
|
|
28773
|
+
* THREE outcomes, and the single-camera method could only express two of them
|
|
28774
|
+
* because `snapshot: null` was already spoken for:
|
|
28775
|
+
*
|
|
28776
|
+
* - `read: 'read'`, `snapshot` present — the live occupancy reading.
|
|
28777
|
+
* - `read: 'read'`, `snapshot: null` — read, and this camera has no reading
|
|
28778
|
+
* yet: no frame since boot, and no parked-object registry to hydrate from.
|
|
28779
|
+
* - `read: 'unreadable'` — the owner could not answer for this
|
|
28780
|
+
* camera. `snapshot` is null, and it does NOT mean "nothing parked here".
|
|
28781
|
+
*
|
|
28782
|
+
* Collapsing the last two is the failure this field exists to prevent: a
|
|
28783
|
+
* hydration that threw would otherwise render as an empty Stationary section,
|
|
28784
|
+
* which is a definite claim about a camera nobody could read.
|
|
28785
|
+
*/
|
|
28786
|
+
var CameraOccupancySnapshotForDeviceSchema = object({
|
|
28787
|
+
deviceId: number(),
|
|
28788
|
+
read: _enum(["read", "unreadable"]),
|
|
28789
|
+
snapshot: CameraOccupancySnapshotSchema.nullable()
|
|
28790
|
+
});
|
|
28791
|
+
/**
|
|
28622
28792
|
* Time-series resolution. The history methods return one bucket per
|
|
28623
28793
|
* step over the requested range. Smaller resolutions cost more
|
|
28624
28794
|
* memory + bandwidth; bound to discrete steps so caller cannot ask
|
|
@@ -28642,7 +28812,7 @@ var HistoryPointSchema = object({
|
|
|
28642
28812
|
/** Object count averaged over the bucket (rounded to nearest integer). */
|
|
28643
28813
|
count: number().int().nonnegative()
|
|
28644
28814
|
});
|
|
28645
|
-
DeviceType.Camera, method(object({ deviceId: number() }), CameraOccupancySnapshotSchema.nullable()), method(object({
|
|
28815
|
+
DeviceType.Camera, method(object({ deviceId: number() }), CameraOccupancySnapshotSchema.nullable()), method(object({ deviceIds: array(number()).min(1).max(200) }), array(CameraOccupancySnapshotForDeviceSchema).readonly()), method(object({
|
|
28646
28816
|
deviceId: number(),
|
|
28647
28817
|
zoneId: string(),
|
|
28648
28818
|
className: string().optional()
|
|
@@ -31947,6 +32117,12 @@ Object.freeze({
|
|
|
31947
32117
|
addonId: null,
|
|
31948
32118
|
access: "view"
|
|
31949
32119
|
},
|
|
32120
|
+
"pipelineAnalytics.getKeyEventsBatch": {
|
|
32121
|
+
capName: "pipeline-analytics",
|
|
32122
|
+
capScope: "device",
|
|
32123
|
+
addonId: null,
|
|
32124
|
+
access: "view"
|
|
32125
|
+
},
|
|
31950
32126
|
"pipelineAnalytics.getMotionEvents": {
|
|
31951
32127
|
capName: "pipeline-analytics",
|
|
31952
32128
|
capScope: "device",
|
|
@@ -33123,6 +33299,12 @@ Object.freeze({
|
|
|
33123
33299
|
addonId: null,
|
|
33124
33300
|
access: "view"
|
|
33125
33301
|
},
|
|
33302
|
+
"recording.reconcileLedgerAgainstDisk": {
|
|
33303
|
+
capName: "recording",
|
|
33304
|
+
capScope: "system",
|
|
33305
|
+
addonId: null,
|
|
33306
|
+
access: "create"
|
|
33307
|
+
},
|
|
33126
33308
|
"recording.refreshStorageLocationsForMigration": {
|
|
33127
33309
|
capName: "recording",
|
|
33128
33310
|
capScope: "system",
|
|
@@ -33249,6 +33431,12 @@ Object.freeze({
|
|
|
33249
33431
|
addonId: null,
|
|
33250
33432
|
access: "view"
|
|
33251
33433
|
},
|
|
33434
|
+
"sceneMonitor.listScenesBatch": {
|
|
33435
|
+
capName: "scene-monitor",
|
|
33436
|
+
capScope: "device",
|
|
33437
|
+
addonId: null,
|
|
33438
|
+
access: "view"
|
|
33439
|
+
},
|
|
33252
33440
|
"sceneMonitor.recheckNow": {
|
|
33253
33441
|
capName: "scene-monitor",
|
|
33254
33442
|
capScope: "device",
|
|
@@ -34605,6 +34793,12 @@ Object.freeze({
|
|
|
34605
34793
|
addonId: null,
|
|
34606
34794
|
access: "view"
|
|
34607
34795
|
},
|
|
34796
|
+
"zoneAnalytics.getCurrentSnapshotBatch": {
|
|
34797
|
+
capName: "zone-analytics",
|
|
34798
|
+
capScope: "device",
|
|
34799
|
+
addonId: null,
|
|
34800
|
+
access: "view"
|
|
34801
|
+
},
|
|
34608
34802
|
"zoneAnalytics.getUnzonedHistory": {
|
|
34609
34803
|
capName: "zone-analytics",
|
|
34610
34804
|
capScope: "device",
|
|
@@ -35609,6 +35803,11 @@ Object.freeze({
|
|
|
35609
35803
|
form: "single",
|
|
35610
35804
|
optional: false
|
|
35611
35805
|
}],
|
|
35806
|
+
"pipelineAnalytics.getKeyEventsBatch": [{
|
|
35807
|
+
name: "deviceIds",
|
|
35808
|
+
form: "array",
|
|
35809
|
+
optional: false
|
|
35810
|
+
}],
|
|
35612
35811
|
"pipelineAnalytics.getMotionEvents": [{
|
|
35613
35812
|
name: "deviceId",
|
|
35614
35813
|
form: "single",
|
|
@@ -36049,6 +36248,11 @@ Object.freeze({
|
|
|
36049
36248
|
form: "single",
|
|
36050
36249
|
optional: false
|
|
36051
36250
|
}],
|
|
36251
|
+
"recording.reconcileLedgerAgainstDisk": [{
|
|
36252
|
+
name: "deviceId",
|
|
36253
|
+
form: "single",
|
|
36254
|
+
optional: true
|
|
36255
|
+
}],
|
|
36052
36256
|
"recording.relocateFootage": [{
|
|
36053
36257
|
name: "deviceId",
|
|
36054
36258
|
form: "single",
|
|
@@ -36114,6 +36318,11 @@ Object.freeze({
|
|
|
36114
36318
|
form: "single",
|
|
36115
36319
|
optional: false
|
|
36116
36320
|
}],
|
|
36321
|
+
"sceneMonitor.listScenesBatch": [{
|
|
36322
|
+
name: "deviceIds",
|
|
36323
|
+
form: "array",
|
|
36324
|
+
optional: false
|
|
36325
|
+
}],
|
|
36117
36326
|
"sceneMonitor.recheckNow": [{
|
|
36118
36327
|
name: "deviceId",
|
|
36119
36328
|
form: "single",
|
|
@@ -36375,6 +36584,11 @@ Object.freeze({
|
|
|
36375
36584
|
form: "single",
|
|
36376
36585
|
optional: false
|
|
36377
36586
|
}],
|
|
36587
|
+
"zoneAnalytics.getCurrentSnapshotBatch": [{
|
|
36588
|
+
name: "deviceIds",
|
|
36589
|
+
form: "array",
|
|
36590
|
+
optional: false
|
|
36591
|
+
}],
|
|
36378
36592
|
"zoneAnalytics.getUnzonedHistory": [{
|
|
36379
36593
|
name: "deviceId",
|
|
36380
36594
|
form: "single",
|
|
@@ -8207,6 +8207,20 @@ var RelocateJobSchema = object({
|
|
|
8207
8207
|
* in its row, not in its name, so `MediaRelocateEngine` never reconciles one.
|
|
8208
8208
|
*/
|
|
8209
8209
|
rowsReconciled: number().int().nonnegative().optional(),
|
|
8210
|
+
/**
|
|
8211
|
+
* Rows this run FORGOT because the file they name is not on disk.
|
|
8212
|
+
*
|
|
8213
|
+
* The mover derived the path from the row's own fields and `stat`ed it; an
|
|
8214
|
+
* ENOENT there is a per-path confirmation that the segment is gone (D296),
|
|
8215
|
+
* and the durable row is dropped through the same channel eviction uses. It
|
|
8216
|
+
* is reported for the same reason `rowsReconciled` is: this is a durable
|
|
8217
|
+
* mutation nobody asked for, and a migration that quietly erases hour rows is
|
|
8218
|
+
* the same failure as one that quietly skips them (D295).
|
|
8219
|
+
*
|
|
8220
|
+
* The production drain of 2026-08-30 would have reported 11 074 here — the
|
|
8221
|
+
* ledger claimed 5.65 GB of footage that no longer existed.
|
|
8222
|
+
*/
|
|
8223
|
+
rowsForgotten: number().int().nonnegative().optional(),
|
|
8210
8224
|
startedAt: number(),
|
|
8211
8225
|
finishedAt: number().nullable(),
|
|
8212
8226
|
error: string().nullable()
|
|
@@ -8570,6 +8584,91 @@ var RelocateResidueSchema = object({
|
|
|
8570
8584
|
segments: number().int().nonnegative(),
|
|
8571
8585
|
bytes: number().int().nonnegative()
|
|
8572
8586
|
}).nullable();
|
|
8587
|
+
/**
|
|
8588
|
+
* Ask one location whether its durable hour rows describe the disk — the walk
|
|
8589
|
+
* (D319).
|
|
8590
|
+
*
|
|
8591
|
+
* `apply` DEFAULTS TO FALSE and that default is the product: the operator's
|
|
8592
|
+
* missing tool is the question, and the dry run is how they sanity-check the
|
|
8593
|
+
* destructive run before authorising it.
|
|
8594
|
+
*/
|
|
8595
|
+
var LedgerWalkInputSchema = object({
|
|
8596
|
+
locationId: string().min(1),
|
|
8597
|
+
/** Forget the confirmed-absent rows, rather than only counting them. */
|
|
8598
|
+
apply: boolean().optional(),
|
|
8599
|
+
/** Narrow to one camera. */
|
|
8600
|
+
deviceId: number().int().positive().optional(),
|
|
8601
|
+
/** Narrow to these recording profiles; empty/absent = every profile. */
|
|
8602
|
+
profiles: array(string().min(1)).optional()
|
|
8603
|
+
});
|
|
8604
|
+
/** Why a whole walk did nothing. Every one leaves the ledger untouched. */
|
|
8605
|
+
var LedgerWalkRefusalSchema = _enum([
|
|
8606
|
+
"location-unknown",
|
|
8607
|
+
"source-writable",
|
|
8608
|
+
"no-ledger",
|
|
8609
|
+
"archive-unreadable",
|
|
8610
|
+
"anchor-absent",
|
|
8611
|
+
"anchor-unreadable",
|
|
8612
|
+
"anchor-moved"
|
|
8613
|
+
]);
|
|
8614
|
+
_enum([
|
|
8615
|
+
"live-tail",
|
|
8616
|
+
"listing-error",
|
|
8617
|
+
"path-mismatch",
|
|
8618
|
+
"durable-refused"
|
|
8619
|
+
]);
|
|
8620
|
+
/** Every skip reason, always present, always a number — so a reason that never
|
|
8621
|
+
* fired reports as zero rather than absent and the report shape is constant
|
|
8622
|
+
* between passes. Spelled out rather than `z.record` for exactly that. */
|
|
8623
|
+
var LedgerWalkSkipCountsSchema = object({
|
|
8624
|
+
"live-tail": number().int().nonnegative(),
|
|
8625
|
+
"listing-error": number().int().nonnegative(),
|
|
8626
|
+
"path-mismatch": number().int().nonnegative(),
|
|
8627
|
+
"durable-refused": number().int().nonnegative()
|
|
8628
|
+
});
|
|
8629
|
+
/** One camera's share of a walk, so a report names cameras and not rows. */
|
|
8630
|
+
var LedgerWalkDeviceReportSchema = object({
|
|
8631
|
+
deviceId: number().int(),
|
|
8632
|
+
hoursWalked: number().int().nonnegative(),
|
|
8633
|
+
hoursMissing: number().int().nonnegative(),
|
|
8634
|
+
ghostSegments: number().int().nonnegative(),
|
|
8635
|
+
ghostBytes: number().int().nonnegative(),
|
|
8636
|
+
forgottenSegments: number().int().nonnegative(),
|
|
8637
|
+
orphanFiles: number().int().nonnegative()
|
|
8638
|
+
});
|
|
8639
|
+
/**
|
|
8640
|
+
* What one walk claimed, listed, found and (only when armed) forgot.
|
|
8641
|
+
*
|
|
8642
|
+
* `archiveSegments` is the **M** and `segmentsClaimed` the **N** (D295), so a
|
|
8643
|
+
* walk that saw a fraction of the location is visible in its own report rather
|
|
8644
|
+
* than in the absence of one.
|
|
8645
|
+
*/
|
|
8646
|
+
var LedgerWalkReportSchema = object({
|
|
8647
|
+
locationId: string(),
|
|
8648
|
+
applied: boolean(),
|
|
8649
|
+
refused: LedgerWalkRefusalSchema.nullable(),
|
|
8650
|
+
archiveSegments: number().int().nonnegative().nullable(),
|
|
8651
|
+
archiveBytes: number().int().nonnegative().nullable(),
|
|
8652
|
+
hoursClaimed: number().int().nonnegative(),
|
|
8653
|
+
hoursWalked: number().int().nonnegative(),
|
|
8654
|
+
hoursMissing: number().int().nonnegative(),
|
|
8655
|
+
/** `readdir` calls issued — the cost, stated in the unit that is paid. */
|
|
8656
|
+
listings: number().int().nonnegative(),
|
|
8657
|
+
segmentsClaimed: number().int().nonnegative(),
|
|
8658
|
+
ghostSegments: number().int().nonnegative(),
|
|
8659
|
+
ghostBytes: number().int().nonnegative(),
|
|
8660
|
+
ghostHoursWhole: number().int().nonnegative(),
|
|
8661
|
+
forgottenSegments: number().int().nonnegative(),
|
|
8662
|
+
forgottenBytes: number().int().nonnegative(),
|
|
8663
|
+
/** Files under a claimed hour that no durable row names. Never deleted. */
|
|
8664
|
+
orphanFiles: number().int().nonnegative(),
|
|
8665
|
+
orphanSample: array(string()).readonly(),
|
|
8666
|
+
hoursSkipped: number().int().nonnegative(),
|
|
8667
|
+
skippedByReason: LedgerWalkSkipCountsSchema,
|
|
8668
|
+
/** The walk stopped at its per-pass hour bound with claims unwalked. */
|
|
8669
|
+
bounded: boolean(),
|
|
8670
|
+
byDevice: array(LedgerWalkDeviceReportSchema).readonly()
|
|
8671
|
+
});
|
|
8573
8672
|
/** How many rows a media pass would still act on against a given target — the
|
|
8574
8673
|
* media lane's denominator AND its residue, from ONE derivation so the two can
|
|
8575
8674
|
* never disagree. `null` = the count could not be taken. */
|
|
@@ -18932,13 +19031,15 @@ var ListGroupsPageSchema = object({
|
|
|
18932
19031
|
groups: array(AnalyticsGroupRecordSchema).readonly(),
|
|
18933
19032
|
nextCursor: string().nullable()
|
|
18934
19033
|
});
|
|
19034
|
+
var KEY_EVENTS_DEFAULT_LIMIT = 50;
|
|
19035
|
+
var KEY_EVENTS_MAX_LIMIT = 200;
|
|
18935
19036
|
var KeyEventQueryInput = object({
|
|
18936
19037
|
deviceId: number(),
|
|
18937
19038
|
/** Window lower bound (track firstSeen ≥ since). */
|
|
18938
19039
|
since: number(),
|
|
18939
19040
|
/** Window upper bound (track firstSeen ≤ until). */
|
|
18940
19041
|
until: number(),
|
|
18941
|
-
limit: number().int().min(1).max(
|
|
19042
|
+
limit: number().int().min(1).max(KEY_EVENTS_MAX_LIMIT).default(KEY_EVENTS_DEFAULT_LIMIT),
|
|
18942
19043
|
/** Drop tracks scoring below this importance. */
|
|
18943
19044
|
minImportance: number().min(0).max(1).optional(),
|
|
18944
19045
|
/** Restrict to a single class (e.g. 'person'). */
|
|
@@ -18960,6 +19061,32 @@ var KeyEventSchema = object({
|
|
|
18960
19061
|
...TrackFlagFields,
|
|
18961
19062
|
...TrackRetrainFields
|
|
18962
19063
|
});
|
|
19064
|
+
/** `getKeyEvents`' window and filters, asked of a SET of cameras at once. */
|
|
19065
|
+
var KeyEventBatchQueryInput = object({
|
|
19066
|
+
deviceIds: array(number()).min(1).max(200),
|
|
19067
|
+
since: number(),
|
|
19068
|
+
until: number(),
|
|
19069
|
+
/** Applied PER CAMERA, exactly as `getKeyEvents.limit` is — never a total
|
|
19070
|
+
* across the set, which would let a busy camera starve a quiet one of its
|
|
19071
|
+
* rows and change what the merged feed contains. */
|
|
19072
|
+
limit: number().int().min(1).max(KEY_EVENTS_MAX_LIMIT).default(KEY_EVENTS_DEFAULT_LIMIT),
|
|
19073
|
+
minImportance: number().min(0).max(1).optional(),
|
|
19074
|
+
classFilter: string().optional()
|
|
19075
|
+
});
|
|
19076
|
+
/**
|
|
19077
|
+
* One camera's key events in a batch answer.
|
|
19078
|
+
*
|
|
19079
|
+
* The row exists for every requested id. `getKeyEvents` degrades to `[]` on
|
|
19080
|
+
* error rather than throwing, so a camera whose store read failed and one with
|
|
19081
|
+
* no events in the window were ALREADY indistinguishable per camera — the
|
|
19082
|
+
* batch does not make that worse, and the row keeps the deviceId the single
|
|
19083
|
+
* method's output never carried (the caller used to stamp it from the fan-out
|
|
19084
|
+
* key, which only worked because there was one query per camera).
|
|
19085
|
+
*/
|
|
19086
|
+
var KeyEventsForDeviceSchema = object({
|
|
19087
|
+
deviceId: number(),
|
|
19088
|
+
events: array(KeyEventSchema).readonly()
|
|
19089
|
+
});
|
|
18963
19090
|
object({
|
|
18964
19091
|
trackId: string(),
|
|
18965
19092
|
className: string(),
|
|
@@ -19229,7 +19356,7 @@ DeviceType.Camera, method(object({ deviceId: number() }), array(TrackSchema).rea
|
|
|
19229
19356
|
until: number().optional(),
|
|
19230
19357
|
kinds: array(string()).optional(),
|
|
19231
19358
|
limit: number().int().min(1).max(MAX_EVENT_QUERY_LIMIT).default(DEFAULT_EVENT_QUERY_LIMIT)
|
|
19232
|
-
}), array(SensorEventSchema).readonly()), method(KeyEventQueryInput, array(KeyEventSchema).readonly()), method(object({
|
|
19359
|
+
}), array(SensorEventSchema).readonly()), method(KeyEventQueryInput, array(KeyEventSchema).readonly()), method(KeyEventBatchQueryInput, array(KeyEventsForDeviceSchema).readonly()), method(object({
|
|
19233
19360
|
deviceId: number(),
|
|
19234
19361
|
since: number(),
|
|
19235
19362
|
until: number(),
|
|
@@ -26893,6 +27020,9 @@ method(object({
|
|
|
26893
27020
|
}), method(RelocateResidueInputSchema, RelocateResidueSchema, {
|
|
26894
27021
|
kind: "query",
|
|
26895
27022
|
auth: "admin"
|
|
27023
|
+
}), method(LedgerWalkInputSchema, LedgerWalkReportSchema, {
|
|
27024
|
+
kind: "mutation",
|
|
27025
|
+
auth: "admin"
|
|
26896
27026
|
}), method(object({ jobId: string() }), object({ cancelled: boolean() }), {
|
|
26897
27027
|
kind: "mutation",
|
|
26898
27028
|
auth: "admin"
|
|
@@ -27284,7 +27414,26 @@ var SceneMonitorStatusSchema = object({
|
|
|
27284
27414
|
monitors: array(SceneMonitorSchema),
|
|
27285
27415
|
lastFetchedAt: number()
|
|
27286
27416
|
});
|
|
27287
|
-
|
|
27417
|
+
/**
|
|
27418
|
+
* One camera's row in a `listScenesBatch` answer.
|
|
27419
|
+
*
|
|
27420
|
+
* `status` is NULLABLE and the nullability is the whole point. `scene-monitor`
|
|
27421
|
+
* is a `defaultActive` wrapper, so every camera is asked; a camera whose
|
|
27422
|
+
* provider is absent (pipeline-analytics not deployed, the post-processing node
|
|
27423
|
+
* down) cannot answer, and that is not the same fact as a camera with no scenes
|
|
27424
|
+
* configured. Fanned out per camera the difference was visible — one query
|
|
27425
|
+
* errored while the others resolved — and a batch that returned only the rows
|
|
27426
|
+
* it managed would have destroyed it, silently, by making an unreachable camera
|
|
27427
|
+
* indistinguishable from one that answered `monitors: []`.
|
|
27428
|
+
*
|
|
27429
|
+
* So: EVERY requested deviceId gets a row. `status: null` means "this camera
|
|
27430
|
+
* could not be read"; `status.monitors: []` means "read, and it has none".
|
|
27431
|
+
*/
|
|
27432
|
+
var SceneMonitorStatusForDeviceSchema = object({
|
|
27433
|
+
deviceId: number(),
|
|
27434
|
+
status: SceneMonitorStatusSchema.nullable()
|
|
27435
|
+
});
|
|
27436
|
+
DeviceType.Camera, method(object({ deviceId: number() }), SceneMonitorStatusSchema), method(object({ deviceIds: array(number()).min(1).max(200) }), array(SceneMonitorStatusForDeviceSchema).readonly()), method(object({
|
|
27288
27437
|
deviceId: number(),
|
|
27289
27438
|
label: string(),
|
|
27290
27439
|
roi: MaskRectShapeSchema,
|
|
@@ -28615,6 +28764,27 @@ var CameraOccupancySnapshotSchema = object({
|
|
|
28615
28764
|
stationaryObjects: array(StationaryObjectSchema).readonly().optional()
|
|
28616
28765
|
});
|
|
28617
28766
|
/**
|
|
28767
|
+
* One camera's row in a `getCurrentSnapshotBatch` answer.
|
|
28768
|
+
*
|
|
28769
|
+
* THREE outcomes, and the single-camera method could only express two of them
|
|
28770
|
+
* because `snapshot: null` was already spoken for:
|
|
28771
|
+
*
|
|
28772
|
+
* - `read: 'read'`, `snapshot` present — the live occupancy reading.
|
|
28773
|
+
* - `read: 'read'`, `snapshot: null` — read, and this camera has no reading
|
|
28774
|
+
* yet: no frame since boot, and no parked-object registry to hydrate from.
|
|
28775
|
+
* - `read: 'unreadable'` — the owner could not answer for this
|
|
28776
|
+
* camera. `snapshot` is null, and it does NOT mean "nothing parked here".
|
|
28777
|
+
*
|
|
28778
|
+
* Collapsing the last two is the failure this field exists to prevent: a
|
|
28779
|
+
* hydration that threw would otherwise render as an empty Stationary section,
|
|
28780
|
+
* which is a definite claim about a camera nobody could read.
|
|
28781
|
+
*/
|
|
28782
|
+
var CameraOccupancySnapshotForDeviceSchema = object({
|
|
28783
|
+
deviceId: number(),
|
|
28784
|
+
read: _enum(["read", "unreadable"]),
|
|
28785
|
+
snapshot: CameraOccupancySnapshotSchema.nullable()
|
|
28786
|
+
});
|
|
28787
|
+
/**
|
|
28618
28788
|
* Time-series resolution. The history methods return one bucket per
|
|
28619
28789
|
* step over the requested range. Smaller resolutions cost more
|
|
28620
28790
|
* memory + bandwidth; bound to discrete steps so caller cannot ask
|
|
@@ -28638,7 +28808,7 @@ var HistoryPointSchema = object({
|
|
|
28638
28808
|
/** Object count averaged over the bucket (rounded to nearest integer). */
|
|
28639
28809
|
count: number().int().nonnegative()
|
|
28640
28810
|
});
|
|
28641
|
-
DeviceType.Camera, method(object({ deviceId: number() }), CameraOccupancySnapshotSchema.nullable()), method(object({
|
|
28811
|
+
DeviceType.Camera, method(object({ deviceId: number() }), CameraOccupancySnapshotSchema.nullable()), method(object({ deviceIds: array(number()).min(1).max(200) }), array(CameraOccupancySnapshotForDeviceSchema).readonly()), method(object({
|
|
28642
28812
|
deviceId: number(),
|
|
28643
28813
|
zoneId: string(),
|
|
28644
28814
|
className: string().optional()
|
|
@@ -31943,6 +32113,12 @@ Object.freeze({
|
|
|
31943
32113
|
addonId: null,
|
|
31944
32114
|
access: "view"
|
|
31945
32115
|
},
|
|
32116
|
+
"pipelineAnalytics.getKeyEventsBatch": {
|
|
32117
|
+
capName: "pipeline-analytics",
|
|
32118
|
+
capScope: "device",
|
|
32119
|
+
addonId: null,
|
|
32120
|
+
access: "view"
|
|
32121
|
+
},
|
|
31946
32122
|
"pipelineAnalytics.getMotionEvents": {
|
|
31947
32123
|
capName: "pipeline-analytics",
|
|
31948
32124
|
capScope: "device",
|
|
@@ -33119,6 +33295,12 @@ Object.freeze({
|
|
|
33119
33295
|
addonId: null,
|
|
33120
33296
|
access: "view"
|
|
33121
33297
|
},
|
|
33298
|
+
"recording.reconcileLedgerAgainstDisk": {
|
|
33299
|
+
capName: "recording",
|
|
33300
|
+
capScope: "system",
|
|
33301
|
+
addonId: null,
|
|
33302
|
+
access: "create"
|
|
33303
|
+
},
|
|
33122
33304
|
"recording.refreshStorageLocationsForMigration": {
|
|
33123
33305
|
capName: "recording",
|
|
33124
33306
|
capScope: "system",
|
|
@@ -33245,6 +33427,12 @@ Object.freeze({
|
|
|
33245
33427
|
addonId: null,
|
|
33246
33428
|
access: "view"
|
|
33247
33429
|
},
|
|
33430
|
+
"sceneMonitor.listScenesBatch": {
|
|
33431
|
+
capName: "scene-monitor",
|
|
33432
|
+
capScope: "device",
|
|
33433
|
+
addonId: null,
|
|
33434
|
+
access: "view"
|
|
33435
|
+
},
|
|
33248
33436
|
"sceneMonitor.recheckNow": {
|
|
33249
33437
|
capName: "scene-monitor",
|
|
33250
33438
|
capScope: "device",
|
|
@@ -34601,6 +34789,12 @@ Object.freeze({
|
|
|
34601
34789
|
addonId: null,
|
|
34602
34790
|
access: "view"
|
|
34603
34791
|
},
|
|
34792
|
+
"zoneAnalytics.getCurrentSnapshotBatch": {
|
|
34793
|
+
capName: "zone-analytics",
|
|
34794
|
+
capScope: "device",
|
|
34795
|
+
addonId: null,
|
|
34796
|
+
access: "view"
|
|
34797
|
+
},
|
|
34604
34798
|
"zoneAnalytics.getUnzonedHistory": {
|
|
34605
34799
|
capName: "zone-analytics",
|
|
34606
34800
|
capScope: "device",
|
|
@@ -35605,6 +35799,11 @@ Object.freeze({
|
|
|
35605
35799
|
form: "single",
|
|
35606
35800
|
optional: false
|
|
35607
35801
|
}],
|
|
35802
|
+
"pipelineAnalytics.getKeyEventsBatch": [{
|
|
35803
|
+
name: "deviceIds",
|
|
35804
|
+
form: "array",
|
|
35805
|
+
optional: false
|
|
35806
|
+
}],
|
|
35608
35807
|
"pipelineAnalytics.getMotionEvents": [{
|
|
35609
35808
|
name: "deviceId",
|
|
35610
35809
|
form: "single",
|
|
@@ -36045,6 +36244,11 @@ Object.freeze({
|
|
|
36045
36244
|
form: "single",
|
|
36046
36245
|
optional: false
|
|
36047
36246
|
}],
|
|
36247
|
+
"recording.reconcileLedgerAgainstDisk": [{
|
|
36248
|
+
name: "deviceId",
|
|
36249
|
+
form: "single",
|
|
36250
|
+
optional: true
|
|
36251
|
+
}],
|
|
36048
36252
|
"recording.relocateFootage": [{
|
|
36049
36253
|
name: "deviceId",
|
|
36050
36254
|
form: "single",
|
|
@@ -36110,6 +36314,11 @@ Object.freeze({
|
|
|
36110
36314
|
form: "single",
|
|
36111
36315
|
optional: false
|
|
36112
36316
|
}],
|
|
36317
|
+
"sceneMonitor.listScenesBatch": [{
|
|
36318
|
+
name: "deviceIds",
|
|
36319
|
+
form: "array",
|
|
36320
|
+
optional: false
|
|
36321
|
+
}],
|
|
36113
36322
|
"sceneMonitor.recheckNow": [{
|
|
36114
36323
|
name: "deviceId",
|
|
36115
36324
|
form: "single",
|
|
@@ -36371,6 +36580,11 @@ Object.freeze({
|
|
|
36371
36580
|
form: "single",
|
|
36372
36581
|
optional: false
|
|
36373
36582
|
}],
|
|
36583
|
+
"zoneAnalytics.getCurrentSnapshotBatch": [{
|
|
36584
|
+
name: "deviceIds",
|
|
36585
|
+
form: "array",
|
|
36586
|
+
optional: false
|
|
36587
|
+
}],
|
|
36374
36588
|
"zoneAnalytics.getUnzonedHistory": [{
|
|
36375
36589
|
name: "deviceId",
|
|
36376
36590
|
form: "single",
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@camstack/addon-export-google",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.13",
|
|
4
4
|
"description": "Google Home export — hub-side smart-home fulfillment (SYNC / QUERY / EXECUTE / DISCONNECT) for the non-camera fleet, served over the hub's own OAuth account link. No Google credential is stored, sent or required.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"camstack",
|