@camstack/addon-ai 0.4.44 → 0.4.45
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/addon.js +218 -4
- package/dist/addon.mjs +218 -4
- package/package.json +1 -1
package/dist/addon.js
CHANGED
|
@@ -8221,6 +8221,20 @@ var RelocateJobSchema = object({
|
|
|
8221
8221
|
* in its row, not in its name, so `MediaRelocateEngine` never reconciles one.
|
|
8222
8222
|
*/
|
|
8223
8223
|
rowsReconciled: number$1().int().nonnegative().optional(),
|
|
8224
|
+
/**
|
|
8225
|
+
* Rows this run FORGOT because the file they name is not on disk.
|
|
8226
|
+
*
|
|
8227
|
+
* The mover derived the path from the row's own fields and `stat`ed it; an
|
|
8228
|
+
* ENOENT there is a per-path confirmation that the segment is gone (D296),
|
|
8229
|
+
* and the durable row is dropped through the same channel eviction uses. It
|
|
8230
|
+
* is reported for the same reason `rowsReconciled` is: this is a durable
|
|
8231
|
+
* mutation nobody asked for, and a migration that quietly erases hour rows is
|
|
8232
|
+
* the same failure as one that quietly skips them (D295).
|
|
8233
|
+
*
|
|
8234
|
+
* The production drain of 2026-08-30 would have reported 11 074 here — the
|
|
8235
|
+
* ledger claimed 5.65 GB of footage that no longer existed.
|
|
8236
|
+
*/
|
|
8237
|
+
rowsForgotten: number$1().int().nonnegative().optional(),
|
|
8224
8238
|
startedAt: number$1(),
|
|
8225
8239
|
finishedAt: number$1().nullable(),
|
|
8226
8240
|
error: string().nullable()
|
|
@@ -8584,6 +8598,91 @@ var RelocateResidueSchema = object({
|
|
|
8584
8598
|
segments: number$1().int().nonnegative(),
|
|
8585
8599
|
bytes: number$1().int().nonnegative()
|
|
8586
8600
|
}).nullable();
|
|
8601
|
+
/**
|
|
8602
|
+
* Ask one location whether its durable hour rows describe the disk — the walk
|
|
8603
|
+
* (D319).
|
|
8604
|
+
*
|
|
8605
|
+
* `apply` DEFAULTS TO FALSE and that default is the product: the operator's
|
|
8606
|
+
* missing tool is the question, and the dry run is how they sanity-check the
|
|
8607
|
+
* destructive run before authorising it.
|
|
8608
|
+
*/
|
|
8609
|
+
var LedgerWalkInputSchema = object({
|
|
8610
|
+
locationId: string().min(1),
|
|
8611
|
+
/** Forget the confirmed-absent rows, rather than only counting them. */
|
|
8612
|
+
apply: boolean().optional(),
|
|
8613
|
+
/** Narrow to one camera. */
|
|
8614
|
+
deviceId: number$1().int().positive().optional(),
|
|
8615
|
+
/** Narrow to these recording profiles; empty/absent = every profile. */
|
|
8616
|
+
profiles: array(string().min(1)).optional()
|
|
8617
|
+
});
|
|
8618
|
+
/** Why a whole walk did nothing. Every one leaves the ledger untouched. */
|
|
8619
|
+
var LedgerWalkRefusalSchema = _enum([
|
|
8620
|
+
"location-unknown",
|
|
8621
|
+
"source-writable",
|
|
8622
|
+
"no-ledger",
|
|
8623
|
+
"archive-unreadable",
|
|
8624
|
+
"anchor-absent",
|
|
8625
|
+
"anchor-unreadable",
|
|
8626
|
+
"anchor-moved"
|
|
8627
|
+
]);
|
|
8628
|
+
_enum([
|
|
8629
|
+
"live-tail",
|
|
8630
|
+
"listing-error",
|
|
8631
|
+
"path-mismatch",
|
|
8632
|
+
"durable-refused"
|
|
8633
|
+
]);
|
|
8634
|
+
/** Every skip reason, always present, always a number — so a reason that never
|
|
8635
|
+
* fired reports as zero rather than absent and the report shape is constant
|
|
8636
|
+
* between passes. Spelled out rather than `z.record` for exactly that. */
|
|
8637
|
+
var LedgerWalkSkipCountsSchema = object({
|
|
8638
|
+
"live-tail": number$1().int().nonnegative(),
|
|
8639
|
+
"listing-error": number$1().int().nonnegative(),
|
|
8640
|
+
"path-mismatch": number$1().int().nonnegative(),
|
|
8641
|
+
"durable-refused": number$1().int().nonnegative()
|
|
8642
|
+
});
|
|
8643
|
+
/** One camera's share of a walk, so a report names cameras and not rows. */
|
|
8644
|
+
var LedgerWalkDeviceReportSchema = object({
|
|
8645
|
+
deviceId: number$1().int(),
|
|
8646
|
+
hoursWalked: number$1().int().nonnegative(),
|
|
8647
|
+
hoursMissing: number$1().int().nonnegative(),
|
|
8648
|
+
ghostSegments: number$1().int().nonnegative(),
|
|
8649
|
+
ghostBytes: number$1().int().nonnegative(),
|
|
8650
|
+
forgottenSegments: number$1().int().nonnegative(),
|
|
8651
|
+
orphanFiles: number$1().int().nonnegative()
|
|
8652
|
+
});
|
|
8653
|
+
/**
|
|
8654
|
+
* What one walk claimed, listed, found and (only when armed) forgot.
|
|
8655
|
+
*
|
|
8656
|
+
* `archiveSegments` is the **M** and `segmentsClaimed` the **N** (D295), so a
|
|
8657
|
+
* walk that saw a fraction of the location is visible in its own report rather
|
|
8658
|
+
* than in the absence of one.
|
|
8659
|
+
*/
|
|
8660
|
+
var LedgerWalkReportSchema = object({
|
|
8661
|
+
locationId: string(),
|
|
8662
|
+
applied: boolean(),
|
|
8663
|
+
refused: LedgerWalkRefusalSchema.nullable(),
|
|
8664
|
+
archiveSegments: number$1().int().nonnegative().nullable(),
|
|
8665
|
+
archiveBytes: number$1().int().nonnegative().nullable(),
|
|
8666
|
+
hoursClaimed: number$1().int().nonnegative(),
|
|
8667
|
+
hoursWalked: number$1().int().nonnegative(),
|
|
8668
|
+
hoursMissing: number$1().int().nonnegative(),
|
|
8669
|
+
/** `readdir` calls issued — the cost, stated in the unit that is paid. */
|
|
8670
|
+
listings: number$1().int().nonnegative(),
|
|
8671
|
+
segmentsClaimed: number$1().int().nonnegative(),
|
|
8672
|
+
ghostSegments: number$1().int().nonnegative(),
|
|
8673
|
+
ghostBytes: number$1().int().nonnegative(),
|
|
8674
|
+
ghostHoursWhole: number$1().int().nonnegative(),
|
|
8675
|
+
forgottenSegments: number$1().int().nonnegative(),
|
|
8676
|
+
forgottenBytes: number$1().int().nonnegative(),
|
|
8677
|
+
/** Files under a claimed hour that no durable row names. Never deleted. */
|
|
8678
|
+
orphanFiles: number$1().int().nonnegative(),
|
|
8679
|
+
orphanSample: array(string()).readonly(),
|
|
8680
|
+
hoursSkipped: number$1().int().nonnegative(),
|
|
8681
|
+
skippedByReason: LedgerWalkSkipCountsSchema,
|
|
8682
|
+
/** The walk stopped at its per-pass hour bound with claims unwalked. */
|
|
8683
|
+
bounded: boolean(),
|
|
8684
|
+
byDevice: array(LedgerWalkDeviceReportSchema).readonly()
|
|
8685
|
+
});
|
|
8587
8686
|
/** How many rows a media pass would still act on against a given target — the
|
|
8588
8687
|
* media lane's denominator AND its residue, from ONE derivation so the two can
|
|
8589
8688
|
* never disagree. `null` = the count could not be taken. */
|
|
@@ -18951,13 +19050,15 @@ var ListGroupsPageSchema = object({
|
|
|
18951
19050
|
groups: array(AnalyticsGroupRecordSchema).readonly(),
|
|
18952
19051
|
nextCursor: string().nullable()
|
|
18953
19052
|
});
|
|
19053
|
+
var KEY_EVENTS_DEFAULT_LIMIT = 50;
|
|
19054
|
+
var KEY_EVENTS_MAX_LIMIT = 200;
|
|
18954
19055
|
var KeyEventQueryInput = object({
|
|
18955
19056
|
deviceId: number$1(),
|
|
18956
19057
|
/** Window lower bound (track firstSeen ≥ since). */
|
|
18957
19058
|
since: number$1(),
|
|
18958
19059
|
/** Window upper bound (track firstSeen ≤ until). */
|
|
18959
19060
|
until: number$1(),
|
|
18960
|
-
limit: number$1().int().min(1).max(
|
|
19061
|
+
limit: number$1().int().min(1).max(KEY_EVENTS_MAX_LIMIT).default(KEY_EVENTS_DEFAULT_LIMIT),
|
|
18961
19062
|
/** Drop tracks scoring below this importance. */
|
|
18962
19063
|
minImportance: number$1().min(0).max(1).optional(),
|
|
18963
19064
|
/** Restrict to a single class (e.g. 'person'). */
|
|
@@ -18979,6 +19080,32 @@ var KeyEventSchema = object({
|
|
|
18979
19080
|
...TrackFlagFields,
|
|
18980
19081
|
...TrackRetrainFields
|
|
18981
19082
|
});
|
|
19083
|
+
/** `getKeyEvents`' window and filters, asked of a SET of cameras at once. */
|
|
19084
|
+
var KeyEventBatchQueryInput = object({
|
|
19085
|
+
deviceIds: array(number$1()).min(1).max(200),
|
|
19086
|
+
since: number$1(),
|
|
19087
|
+
until: number$1(),
|
|
19088
|
+
/** Applied PER CAMERA, exactly as `getKeyEvents.limit` is — never a total
|
|
19089
|
+
* across the set, which would let a busy camera starve a quiet one of its
|
|
19090
|
+
* rows and change what the merged feed contains. */
|
|
19091
|
+
limit: number$1().int().min(1).max(KEY_EVENTS_MAX_LIMIT).default(KEY_EVENTS_DEFAULT_LIMIT),
|
|
19092
|
+
minImportance: number$1().min(0).max(1).optional(),
|
|
19093
|
+
classFilter: string().optional()
|
|
19094
|
+
});
|
|
19095
|
+
/**
|
|
19096
|
+
* One camera's key events in a batch answer.
|
|
19097
|
+
*
|
|
19098
|
+
* The row exists for every requested id. `getKeyEvents` degrades to `[]` on
|
|
19099
|
+
* error rather than throwing, so a camera whose store read failed and one with
|
|
19100
|
+
* no events in the window were ALREADY indistinguishable per camera — the
|
|
19101
|
+
* batch does not make that worse, and the row keeps the deviceId the single
|
|
19102
|
+
* method's output never carried (the caller used to stamp it from the fan-out
|
|
19103
|
+
* key, which only worked because there was one query per camera).
|
|
19104
|
+
*/
|
|
19105
|
+
var KeyEventsForDeviceSchema = object({
|
|
19106
|
+
deviceId: number$1(),
|
|
19107
|
+
events: array(KeyEventSchema).readonly()
|
|
19108
|
+
});
|
|
18982
19109
|
object({
|
|
18983
19110
|
trackId: string(),
|
|
18984
19111
|
className: string(),
|
|
@@ -19248,7 +19375,7 @@ DeviceType.Camera, method(object({ deviceId: number$1() }), array(TrackSchema).r
|
|
|
19248
19375
|
until: number$1().optional(),
|
|
19249
19376
|
kinds: array(string()).optional(),
|
|
19250
19377
|
limit: number$1().int().min(1).max(MAX_EVENT_QUERY_LIMIT).default(DEFAULT_EVENT_QUERY_LIMIT)
|
|
19251
|
-
}), array(SensorEventSchema).readonly()), method(KeyEventQueryInput, array(KeyEventSchema).readonly()), method(object({
|
|
19378
|
+
}), array(SensorEventSchema).readonly()), method(KeyEventQueryInput, array(KeyEventSchema).readonly()), method(KeyEventBatchQueryInput, array(KeyEventsForDeviceSchema).readonly()), method(object({
|
|
19252
19379
|
deviceId: number$1(),
|
|
19253
19380
|
since: number$1(),
|
|
19254
19381
|
until: number$1(),
|
|
@@ -26900,6 +27027,9 @@ method(object({
|
|
|
26900
27027
|
}), method(RelocateResidueInputSchema, RelocateResidueSchema, {
|
|
26901
27028
|
kind: "query",
|
|
26902
27029
|
auth: "admin"
|
|
27030
|
+
}), method(LedgerWalkInputSchema, LedgerWalkReportSchema, {
|
|
27031
|
+
kind: "mutation",
|
|
27032
|
+
auth: "admin"
|
|
26903
27033
|
}), method(object({ jobId: string() }), object({ cancelled: boolean() }), {
|
|
26904
27034
|
kind: "mutation",
|
|
26905
27035
|
auth: "admin"
|
|
@@ -27291,7 +27421,26 @@ var SceneMonitorStatusSchema = object({
|
|
|
27291
27421
|
monitors: array(SceneMonitorSchema),
|
|
27292
27422
|
lastFetchedAt: number$1()
|
|
27293
27423
|
});
|
|
27294
|
-
|
|
27424
|
+
/**
|
|
27425
|
+
* One camera's row in a `listScenesBatch` answer.
|
|
27426
|
+
*
|
|
27427
|
+
* `status` is NULLABLE and the nullability is the whole point. `scene-monitor`
|
|
27428
|
+
* is a `defaultActive` wrapper, so every camera is asked; a camera whose
|
|
27429
|
+
* provider is absent (pipeline-analytics not deployed, the post-processing node
|
|
27430
|
+
* down) cannot answer, and that is not the same fact as a camera with no scenes
|
|
27431
|
+
* configured. Fanned out per camera the difference was visible — one query
|
|
27432
|
+
* errored while the others resolved — and a batch that returned only the rows
|
|
27433
|
+
* it managed would have destroyed it, silently, by making an unreachable camera
|
|
27434
|
+
* indistinguishable from one that answered `monitors: []`.
|
|
27435
|
+
*
|
|
27436
|
+
* So: EVERY requested deviceId gets a row. `status: null` means "this camera
|
|
27437
|
+
* could not be read"; `status.monitors: []` means "read, and it has none".
|
|
27438
|
+
*/
|
|
27439
|
+
var SceneMonitorStatusForDeviceSchema = object({
|
|
27440
|
+
deviceId: number$1(),
|
|
27441
|
+
status: SceneMonitorStatusSchema.nullable()
|
|
27442
|
+
});
|
|
27443
|
+
DeviceType.Camera, method(object({ deviceId: number$1() }), SceneMonitorStatusSchema), method(object({ deviceIds: array(number$1()).min(1).max(200) }), array(SceneMonitorStatusForDeviceSchema).readonly()), method(object({
|
|
27295
27444
|
deviceId: number$1(),
|
|
27296
27445
|
label: string(),
|
|
27297
27446
|
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$1(),
|
|
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$1().int().nonnegative()
|
|
28640
28810
|
});
|
|
28641
|
-
DeviceType.Camera, method(object({ deviceId: number$1() }), CameraOccupancySnapshotSchema.nullable()), method(object({
|
|
28811
|
+
DeviceType.Camera, method(object({ deviceId: number$1() }), CameraOccupancySnapshotSchema.nullable()), method(object({ deviceIds: array(number$1()).min(1).max(200) }), array(CameraOccupancySnapshotForDeviceSchema).readonly()), method(object({
|
|
28642
28812
|
deviceId: number$1(),
|
|
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/dist/addon.mjs
CHANGED
|
@@ -8248,6 +8248,20 @@ var RelocateJobSchema = object({
|
|
|
8248
8248
|
* in its row, not in its name, so `MediaRelocateEngine` never reconciles one.
|
|
8249
8249
|
*/
|
|
8250
8250
|
rowsReconciled: number$1().int().nonnegative().optional(),
|
|
8251
|
+
/**
|
|
8252
|
+
* Rows this run FORGOT because the file they name is not on disk.
|
|
8253
|
+
*
|
|
8254
|
+
* The mover derived the path from the row's own fields and `stat`ed it; an
|
|
8255
|
+
* ENOENT there is a per-path confirmation that the segment is gone (D296),
|
|
8256
|
+
* and the durable row is dropped through the same channel eviction uses. It
|
|
8257
|
+
* is reported for the same reason `rowsReconciled` is: this is a durable
|
|
8258
|
+
* mutation nobody asked for, and a migration that quietly erases hour rows is
|
|
8259
|
+
* the same failure as one that quietly skips them (D295).
|
|
8260
|
+
*
|
|
8261
|
+
* The production drain of 2026-08-30 would have reported 11 074 here — the
|
|
8262
|
+
* ledger claimed 5.65 GB of footage that no longer existed.
|
|
8263
|
+
*/
|
|
8264
|
+
rowsForgotten: number$1().int().nonnegative().optional(),
|
|
8251
8265
|
startedAt: number$1(),
|
|
8252
8266
|
finishedAt: number$1().nullable(),
|
|
8253
8267
|
error: string().nullable()
|
|
@@ -8611,6 +8625,91 @@ var RelocateResidueSchema = object({
|
|
|
8611
8625
|
segments: number$1().int().nonnegative(),
|
|
8612
8626
|
bytes: number$1().int().nonnegative()
|
|
8613
8627
|
}).nullable();
|
|
8628
|
+
/**
|
|
8629
|
+
* Ask one location whether its durable hour rows describe the disk — the walk
|
|
8630
|
+
* (D319).
|
|
8631
|
+
*
|
|
8632
|
+
* `apply` DEFAULTS TO FALSE and that default is the product: the operator's
|
|
8633
|
+
* missing tool is the question, and the dry run is how they sanity-check the
|
|
8634
|
+
* destructive run before authorising it.
|
|
8635
|
+
*/
|
|
8636
|
+
var LedgerWalkInputSchema = object({
|
|
8637
|
+
locationId: string().min(1),
|
|
8638
|
+
/** Forget the confirmed-absent rows, rather than only counting them. */
|
|
8639
|
+
apply: boolean().optional(),
|
|
8640
|
+
/** Narrow to one camera. */
|
|
8641
|
+
deviceId: number$1().int().positive().optional(),
|
|
8642
|
+
/** Narrow to these recording profiles; empty/absent = every profile. */
|
|
8643
|
+
profiles: array(string().min(1)).optional()
|
|
8644
|
+
});
|
|
8645
|
+
/** Why a whole walk did nothing. Every one leaves the ledger untouched. */
|
|
8646
|
+
var LedgerWalkRefusalSchema = _enum([
|
|
8647
|
+
"location-unknown",
|
|
8648
|
+
"source-writable",
|
|
8649
|
+
"no-ledger",
|
|
8650
|
+
"archive-unreadable",
|
|
8651
|
+
"anchor-absent",
|
|
8652
|
+
"anchor-unreadable",
|
|
8653
|
+
"anchor-moved"
|
|
8654
|
+
]);
|
|
8655
|
+
_enum([
|
|
8656
|
+
"live-tail",
|
|
8657
|
+
"listing-error",
|
|
8658
|
+
"path-mismatch",
|
|
8659
|
+
"durable-refused"
|
|
8660
|
+
]);
|
|
8661
|
+
/** Every skip reason, always present, always a number — so a reason that never
|
|
8662
|
+
* fired reports as zero rather than absent and the report shape is constant
|
|
8663
|
+
* between passes. Spelled out rather than `z.record` for exactly that. */
|
|
8664
|
+
var LedgerWalkSkipCountsSchema = object({
|
|
8665
|
+
"live-tail": number$1().int().nonnegative(),
|
|
8666
|
+
"listing-error": number$1().int().nonnegative(),
|
|
8667
|
+
"path-mismatch": number$1().int().nonnegative(),
|
|
8668
|
+
"durable-refused": number$1().int().nonnegative()
|
|
8669
|
+
});
|
|
8670
|
+
/** One camera's share of a walk, so a report names cameras and not rows. */
|
|
8671
|
+
var LedgerWalkDeviceReportSchema = object({
|
|
8672
|
+
deviceId: number$1().int(),
|
|
8673
|
+
hoursWalked: number$1().int().nonnegative(),
|
|
8674
|
+
hoursMissing: number$1().int().nonnegative(),
|
|
8675
|
+
ghostSegments: number$1().int().nonnegative(),
|
|
8676
|
+
ghostBytes: number$1().int().nonnegative(),
|
|
8677
|
+
forgottenSegments: number$1().int().nonnegative(),
|
|
8678
|
+
orphanFiles: number$1().int().nonnegative()
|
|
8679
|
+
});
|
|
8680
|
+
/**
|
|
8681
|
+
* What one walk claimed, listed, found and (only when armed) forgot.
|
|
8682
|
+
*
|
|
8683
|
+
* `archiveSegments` is the **M** and `segmentsClaimed` the **N** (D295), so a
|
|
8684
|
+
* walk that saw a fraction of the location is visible in its own report rather
|
|
8685
|
+
* than in the absence of one.
|
|
8686
|
+
*/
|
|
8687
|
+
var LedgerWalkReportSchema = object({
|
|
8688
|
+
locationId: string(),
|
|
8689
|
+
applied: boolean(),
|
|
8690
|
+
refused: LedgerWalkRefusalSchema.nullable(),
|
|
8691
|
+
archiveSegments: number$1().int().nonnegative().nullable(),
|
|
8692
|
+
archiveBytes: number$1().int().nonnegative().nullable(),
|
|
8693
|
+
hoursClaimed: number$1().int().nonnegative(),
|
|
8694
|
+
hoursWalked: number$1().int().nonnegative(),
|
|
8695
|
+
hoursMissing: number$1().int().nonnegative(),
|
|
8696
|
+
/** `readdir` calls issued — the cost, stated in the unit that is paid. */
|
|
8697
|
+
listings: number$1().int().nonnegative(),
|
|
8698
|
+
segmentsClaimed: number$1().int().nonnegative(),
|
|
8699
|
+
ghostSegments: number$1().int().nonnegative(),
|
|
8700
|
+
ghostBytes: number$1().int().nonnegative(),
|
|
8701
|
+
ghostHoursWhole: number$1().int().nonnegative(),
|
|
8702
|
+
forgottenSegments: number$1().int().nonnegative(),
|
|
8703
|
+
forgottenBytes: number$1().int().nonnegative(),
|
|
8704
|
+
/** Files under a claimed hour that no durable row names. Never deleted. */
|
|
8705
|
+
orphanFiles: number$1().int().nonnegative(),
|
|
8706
|
+
orphanSample: array(string()).readonly(),
|
|
8707
|
+
hoursSkipped: number$1().int().nonnegative(),
|
|
8708
|
+
skippedByReason: LedgerWalkSkipCountsSchema,
|
|
8709
|
+
/** The walk stopped at its per-pass hour bound with claims unwalked. */
|
|
8710
|
+
bounded: boolean(),
|
|
8711
|
+
byDevice: array(LedgerWalkDeviceReportSchema).readonly()
|
|
8712
|
+
});
|
|
8614
8713
|
/** How many rows a media pass would still act on against a given target — the
|
|
8615
8714
|
* media lane's denominator AND its residue, from ONE derivation so the two can
|
|
8616
8715
|
* never disagree. `null` = the count could not be taken. */
|
|
@@ -18978,13 +19077,15 @@ var ListGroupsPageSchema = object({
|
|
|
18978
19077
|
groups: array(AnalyticsGroupRecordSchema).readonly(),
|
|
18979
19078
|
nextCursor: string().nullable()
|
|
18980
19079
|
});
|
|
19080
|
+
var KEY_EVENTS_DEFAULT_LIMIT = 50;
|
|
19081
|
+
var KEY_EVENTS_MAX_LIMIT = 200;
|
|
18981
19082
|
var KeyEventQueryInput = object({
|
|
18982
19083
|
deviceId: number$1(),
|
|
18983
19084
|
/** Window lower bound (track firstSeen ≥ since). */
|
|
18984
19085
|
since: number$1(),
|
|
18985
19086
|
/** Window upper bound (track firstSeen ≤ until). */
|
|
18986
19087
|
until: number$1(),
|
|
18987
|
-
limit: number$1().int().min(1).max(
|
|
19088
|
+
limit: number$1().int().min(1).max(KEY_EVENTS_MAX_LIMIT).default(KEY_EVENTS_DEFAULT_LIMIT),
|
|
18988
19089
|
/** Drop tracks scoring below this importance. */
|
|
18989
19090
|
minImportance: number$1().min(0).max(1).optional(),
|
|
18990
19091
|
/** Restrict to a single class (e.g. 'person'). */
|
|
@@ -19006,6 +19107,32 @@ var KeyEventSchema = object({
|
|
|
19006
19107
|
...TrackFlagFields,
|
|
19007
19108
|
...TrackRetrainFields
|
|
19008
19109
|
});
|
|
19110
|
+
/** `getKeyEvents`' window and filters, asked of a SET of cameras at once. */
|
|
19111
|
+
var KeyEventBatchQueryInput = object({
|
|
19112
|
+
deviceIds: array(number$1()).min(1).max(200),
|
|
19113
|
+
since: number$1(),
|
|
19114
|
+
until: number$1(),
|
|
19115
|
+
/** Applied PER CAMERA, exactly as `getKeyEvents.limit` is — never a total
|
|
19116
|
+
* across the set, which would let a busy camera starve a quiet one of its
|
|
19117
|
+
* rows and change what the merged feed contains. */
|
|
19118
|
+
limit: number$1().int().min(1).max(KEY_EVENTS_MAX_LIMIT).default(KEY_EVENTS_DEFAULT_LIMIT),
|
|
19119
|
+
minImportance: number$1().min(0).max(1).optional(),
|
|
19120
|
+
classFilter: string().optional()
|
|
19121
|
+
});
|
|
19122
|
+
/**
|
|
19123
|
+
* One camera's key events in a batch answer.
|
|
19124
|
+
*
|
|
19125
|
+
* The row exists for every requested id. `getKeyEvents` degrades to `[]` on
|
|
19126
|
+
* error rather than throwing, so a camera whose store read failed and one with
|
|
19127
|
+
* no events in the window were ALREADY indistinguishable per camera — the
|
|
19128
|
+
* batch does not make that worse, and the row keeps the deviceId the single
|
|
19129
|
+
* method's output never carried (the caller used to stamp it from the fan-out
|
|
19130
|
+
* key, which only worked because there was one query per camera).
|
|
19131
|
+
*/
|
|
19132
|
+
var KeyEventsForDeviceSchema = object({
|
|
19133
|
+
deviceId: number$1(),
|
|
19134
|
+
events: array(KeyEventSchema).readonly()
|
|
19135
|
+
});
|
|
19009
19136
|
object({
|
|
19010
19137
|
trackId: string(),
|
|
19011
19138
|
className: string(),
|
|
@@ -19275,7 +19402,7 @@ DeviceType.Camera, method(object({ deviceId: number$1() }), array(TrackSchema).r
|
|
|
19275
19402
|
until: number$1().optional(),
|
|
19276
19403
|
kinds: array(string()).optional(),
|
|
19277
19404
|
limit: number$1().int().min(1).max(MAX_EVENT_QUERY_LIMIT).default(DEFAULT_EVENT_QUERY_LIMIT)
|
|
19278
|
-
}), array(SensorEventSchema).readonly()), method(KeyEventQueryInput, array(KeyEventSchema).readonly()), method(object({
|
|
19405
|
+
}), array(SensorEventSchema).readonly()), method(KeyEventQueryInput, array(KeyEventSchema).readonly()), method(KeyEventBatchQueryInput, array(KeyEventsForDeviceSchema).readonly()), method(object({
|
|
19279
19406
|
deviceId: number$1(),
|
|
19280
19407
|
since: number$1(),
|
|
19281
19408
|
until: number$1(),
|
|
@@ -26927,6 +27054,9 @@ method(object({
|
|
|
26927
27054
|
}), method(RelocateResidueInputSchema, RelocateResidueSchema, {
|
|
26928
27055
|
kind: "query",
|
|
26929
27056
|
auth: "admin"
|
|
27057
|
+
}), method(LedgerWalkInputSchema, LedgerWalkReportSchema, {
|
|
27058
|
+
kind: "mutation",
|
|
27059
|
+
auth: "admin"
|
|
26930
27060
|
}), method(object({ jobId: string() }), object({ cancelled: boolean() }), {
|
|
26931
27061
|
kind: "mutation",
|
|
26932
27062
|
auth: "admin"
|
|
@@ -27318,7 +27448,26 @@ var SceneMonitorStatusSchema = object({
|
|
|
27318
27448
|
monitors: array(SceneMonitorSchema),
|
|
27319
27449
|
lastFetchedAt: number$1()
|
|
27320
27450
|
});
|
|
27321
|
-
|
|
27451
|
+
/**
|
|
27452
|
+
* One camera's row in a `listScenesBatch` answer.
|
|
27453
|
+
*
|
|
27454
|
+
* `status` is NULLABLE and the nullability is the whole point. `scene-monitor`
|
|
27455
|
+
* is a `defaultActive` wrapper, so every camera is asked; a camera whose
|
|
27456
|
+
* provider is absent (pipeline-analytics not deployed, the post-processing node
|
|
27457
|
+
* down) cannot answer, and that is not the same fact as a camera with no scenes
|
|
27458
|
+
* configured. Fanned out per camera the difference was visible — one query
|
|
27459
|
+
* errored while the others resolved — and a batch that returned only the rows
|
|
27460
|
+
* it managed would have destroyed it, silently, by making an unreachable camera
|
|
27461
|
+
* indistinguishable from one that answered `monitors: []`.
|
|
27462
|
+
*
|
|
27463
|
+
* So: EVERY requested deviceId gets a row. `status: null` means "this camera
|
|
27464
|
+
* could not be read"; `status.monitors: []` means "read, and it has none".
|
|
27465
|
+
*/
|
|
27466
|
+
var SceneMonitorStatusForDeviceSchema = object({
|
|
27467
|
+
deviceId: number$1(),
|
|
27468
|
+
status: SceneMonitorStatusSchema.nullable()
|
|
27469
|
+
});
|
|
27470
|
+
DeviceType.Camera, method(object({ deviceId: number$1() }), SceneMonitorStatusSchema), method(object({ deviceIds: array(number$1()).min(1).max(200) }), array(SceneMonitorStatusForDeviceSchema).readonly()), method(object({
|
|
27322
27471
|
deviceId: number$1(),
|
|
27323
27472
|
label: string(),
|
|
27324
27473
|
roi: MaskRectShapeSchema,
|
|
@@ -28642,6 +28791,27 @@ var CameraOccupancySnapshotSchema = object({
|
|
|
28642
28791
|
stationaryObjects: array(StationaryObjectSchema).readonly().optional()
|
|
28643
28792
|
});
|
|
28644
28793
|
/**
|
|
28794
|
+
* One camera's row in a `getCurrentSnapshotBatch` answer.
|
|
28795
|
+
*
|
|
28796
|
+
* THREE outcomes, and the single-camera method could only express two of them
|
|
28797
|
+
* because `snapshot: null` was already spoken for:
|
|
28798
|
+
*
|
|
28799
|
+
* - `read: 'read'`, `snapshot` present — the live occupancy reading.
|
|
28800
|
+
* - `read: 'read'`, `snapshot: null` — read, and this camera has no reading
|
|
28801
|
+
* yet: no frame since boot, and no parked-object registry to hydrate from.
|
|
28802
|
+
* - `read: 'unreadable'` — the owner could not answer for this
|
|
28803
|
+
* camera. `snapshot` is null, and it does NOT mean "nothing parked here".
|
|
28804
|
+
*
|
|
28805
|
+
* Collapsing the last two is the failure this field exists to prevent: a
|
|
28806
|
+
* hydration that threw would otherwise render as an empty Stationary section,
|
|
28807
|
+
* which is a definite claim about a camera nobody could read.
|
|
28808
|
+
*/
|
|
28809
|
+
var CameraOccupancySnapshotForDeviceSchema = object({
|
|
28810
|
+
deviceId: number$1(),
|
|
28811
|
+
read: _enum(["read", "unreadable"]),
|
|
28812
|
+
snapshot: CameraOccupancySnapshotSchema.nullable()
|
|
28813
|
+
});
|
|
28814
|
+
/**
|
|
28645
28815
|
* Time-series resolution. The history methods return one bucket per
|
|
28646
28816
|
* step over the requested range. Smaller resolutions cost more
|
|
28647
28817
|
* memory + bandwidth; bound to discrete steps so caller cannot ask
|
|
@@ -28665,7 +28835,7 @@ var HistoryPointSchema = object({
|
|
|
28665
28835
|
/** Object count averaged over the bucket (rounded to nearest integer). */
|
|
28666
28836
|
count: number$1().int().nonnegative()
|
|
28667
28837
|
});
|
|
28668
|
-
DeviceType.Camera, method(object({ deviceId: number$1() }), CameraOccupancySnapshotSchema.nullable()), method(object({
|
|
28838
|
+
DeviceType.Camera, method(object({ deviceId: number$1() }), CameraOccupancySnapshotSchema.nullable()), method(object({ deviceIds: array(number$1()).min(1).max(200) }), array(CameraOccupancySnapshotForDeviceSchema).readonly()), method(object({
|
|
28669
28839
|
deviceId: number$1(),
|
|
28670
28840
|
zoneId: string(),
|
|
28671
28841
|
className: string().optional()
|
|
@@ -31970,6 +32140,12 @@ Object.freeze({
|
|
|
31970
32140
|
addonId: null,
|
|
31971
32141
|
access: "view"
|
|
31972
32142
|
},
|
|
32143
|
+
"pipelineAnalytics.getKeyEventsBatch": {
|
|
32144
|
+
capName: "pipeline-analytics",
|
|
32145
|
+
capScope: "device",
|
|
32146
|
+
addonId: null,
|
|
32147
|
+
access: "view"
|
|
32148
|
+
},
|
|
31973
32149
|
"pipelineAnalytics.getMotionEvents": {
|
|
31974
32150
|
capName: "pipeline-analytics",
|
|
31975
32151
|
capScope: "device",
|
|
@@ -33146,6 +33322,12 @@ Object.freeze({
|
|
|
33146
33322
|
addonId: null,
|
|
33147
33323
|
access: "view"
|
|
33148
33324
|
},
|
|
33325
|
+
"recording.reconcileLedgerAgainstDisk": {
|
|
33326
|
+
capName: "recording",
|
|
33327
|
+
capScope: "system",
|
|
33328
|
+
addonId: null,
|
|
33329
|
+
access: "create"
|
|
33330
|
+
},
|
|
33149
33331
|
"recording.refreshStorageLocationsForMigration": {
|
|
33150
33332
|
capName: "recording",
|
|
33151
33333
|
capScope: "system",
|
|
@@ -33272,6 +33454,12 @@ Object.freeze({
|
|
|
33272
33454
|
addonId: null,
|
|
33273
33455
|
access: "view"
|
|
33274
33456
|
},
|
|
33457
|
+
"sceneMonitor.listScenesBatch": {
|
|
33458
|
+
capName: "scene-monitor",
|
|
33459
|
+
capScope: "device",
|
|
33460
|
+
addonId: null,
|
|
33461
|
+
access: "view"
|
|
33462
|
+
},
|
|
33275
33463
|
"sceneMonitor.recheckNow": {
|
|
33276
33464
|
capName: "scene-monitor",
|
|
33277
33465
|
capScope: "device",
|
|
@@ -34628,6 +34816,12 @@ Object.freeze({
|
|
|
34628
34816
|
addonId: null,
|
|
34629
34817
|
access: "view"
|
|
34630
34818
|
},
|
|
34819
|
+
"zoneAnalytics.getCurrentSnapshotBatch": {
|
|
34820
|
+
capName: "zone-analytics",
|
|
34821
|
+
capScope: "device",
|
|
34822
|
+
addonId: null,
|
|
34823
|
+
access: "view"
|
|
34824
|
+
},
|
|
34631
34825
|
"zoneAnalytics.getUnzonedHistory": {
|
|
34632
34826
|
capName: "zone-analytics",
|
|
34633
34827
|
capScope: "device",
|
|
@@ -35632,6 +35826,11 @@ Object.freeze({
|
|
|
35632
35826
|
form: "single",
|
|
35633
35827
|
optional: false
|
|
35634
35828
|
}],
|
|
35829
|
+
"pipelineAnalytics.getKeyEventsBatch": [{
|
|
35830
|
+
name: "deviceIds",
|
|
35831
|
+
form: "array",
|
|
35832
|
+
optional: false
|
|
35833
|
+
}],
|
|
35635
35834
|
"pipelineAnalytics.getMotionEvents": [{
|
|
35636
35835
|
name: "deviceId",
|
|
35637
35836
|
form: "single",
|
|
@@ -36072,6 +36271,11 @@ Object.freeze({
|
|
|
36072
36271
|
form: "single",
|
|
36073
36272
|
optional: false
|
|
36074
36273
|
}],
|
|
36274
|
+
"recording.reconcileLedgerAgainstDisk": [{
|
|
36275
|
+
name: "deviceId",
|
|
36276
|
+
form: "single",
|
|
36277
|
+
optional: true
|
|
36278
|
+
}],
|
|
36075
36279
|
"recording.relocateFootage": [{
|
|
36076
36280
|
name: "deviceId",
|
|
36077
36281
|
form: "single",
|
|
@@ -36137,6 +36341,11 @@ Object.freeze({
|
|
|
36137
36341
|
form: "single",
|
|
36138
36342
|
optional: false
|
|
36139
36343
|
}],
|
|
36344
|
+
"sceneMonitor.listScenesBatch": [{
|
|
36345
|
+
name: "deviceIds",
|
|
36346
|
+
form: "array",
|
|
36347
|
+
optional: false
|
|
36348
|
+
}],
|
|
36140
36349
|
"sceneMonitor.recheckNow": [{
|
|
36141
36350
|
name: "deviceId",
|
|
36142
36351
|
form: "single",
|
|
@@ -36398,6 +36607,11 @@ Object.freeze({
|
|
|
36398
36607
|
form: "single",
|
|
36399
36608
|
optional: false
|
|
36400
36609
|
}],
|
|
36610
|
+
"zoneAnalytics.getCurrentSnapshotBatch": [{
|
|
36611
|
+
name: "deviceIds",
|
|
36612
|
+
form: "array",
|
|
36613
|
+
optional: false
|
|
36614
|
+
}],
|
|
36401
36615
|
"zoneAnalytics.getUnzonedHistory": [{
|
|
36402
36616
|
name: "deviceId",
|
|
36403
36617
|
form: "single",
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@camstack/addon-ai",
|
|
3
|
-
"version": "0.4.
|
|
3
|
+
"version": "0.4.45",
|
|
4
4
|
"description": "AI addon for CamStack — the `llm` collection provider (cloud, LAN, and camstack-managed local llama.cpp profiles) plus the per-node `llm-runtime` managed executor.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"camstack",
|