@camstack/addon-import-alexa 0.2.47 → 0.2.48
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 +246 -2
- package/dist/addon.mjs +246 -2
- package/package.json +1 -1
package/dist/addon.js
CHANGED
|
@@ -8176,6 +8176,20 @@ var RelocateJobSchema = object({
|
|
|
8176
8176
|
* in its row, not in its name, so `MediaRelocateEngine` never reconciles one.
|
|
8177
8177
|
*/
|
|
8178
8178
|
rowsReconciled: number().int().nonnegative().optional(),
|
|
8179
|
+
/**
|
|
8180
|
+
* Rows this run FORGOT because the file they name is not on disk.
|
|
8181
|
+
*
|
|
8182
|
+
* The mover derived the path from the row's own fields and `stat`ed it; an
|
|
8183
|
+
* ENOENT there is a per-path confirmation that the segment is gone (D296),
|
|
8184
|
+
* and the durable row is dropped through the same channel eviction uses. It
|
|
8185
|
+
* is reported for the same reason `rowsReconciled` is: this is a durable
|
|
8186
|
+
* mutation nobody asked for, and a migration that quietly erases hour rows is
|
|
8187
|
+
* the same failure as one that quietly skips them (D295).
|
|
8188
|
+
*
|
|
8189
|
+
* The production drain of 2026-08-30 would have reported 11 074 here — the
|
|
8190
|
+
* ledger claimed 5.65 GB of footage that no longer existed.
|
|
8191
|
+
*/
|
|
8192
|
+
rowsForgotten: number().int().nonnegative().optional(),
|
|
8179
8193
|
startedAt: number(),
|
|
8180
8194
|
finishedAt: number().nullable(),
|
|
8181
8195
|
error: string().nullable()
|
|
@@ -8539,6 +8553,91 @@ var RelocateResidueSchema = object({
|
|
|
8539
8553
|
segments: number().int().nonnegative(),
|
|
8540
8554
|
bytes: number().int().nonnegative()
|
|
8541
8555
|
}).nullable();
|
|
8556
|
+
/**
|
|
8557
|
+
* Ask one location whether its durable hour rows describe the disk — the walk
|
|
8558
|
+
* (D319).
|
|
8559
|
+
*
|
|
8560
|
+
* `apply` DEFAULTS TO FALSE and that default is the product: the operator's
|
|
8561
|
+
* missing tool is the question, and the dry run is how they sanity-check the
|
|
8562
|
+
* destructive run before authorising it.
|
|
8563
|
+
*/
|
|
8564
|
+
var LedgerWalkInputSchema = object({
|
|
8565
|
+
locationId: string().min(1),
|
|
8566
|
+
/** Forget the confirmed-absent rows, rather than only counting them. */
|
|
8567
|
+
apply: boolean().optional(),
|
|
8568
|
+
/** Narrow to one camera. */
|
|
8569
|
+
deviceId: number().int().positive().optional(),
|
|
8570
|
+
/** Narrow to these recording profiles; empty/absent = every profile. */
|
|
8571
|
+
profiles: array(string().min(1)).optional()
|
|
8572
|
+
});
|
|
8573
|
+
/** Why a whole walk did nothing. Every one leaves the ledger untouched. */
|
|
8574
|
+
var LedgerWalkRefusalSchema = _enum([
|
|
8575
|
+
"location-unknown",
|
|
8576
|
+
"source-writable",
|
|
8577
|
+
"no-ledger",
|
|
8578
|
+
"archive-unreadable",
|
|
8579
|
+
"anchor-absent",
|
|
8580
|
+
"anchor-unreadable",
|
|
8581
|
+
"anchor-moved"
|
|
8582
|
+
]);
|
|
8583
|
+
_enum([
|
|
8584
|
+
"live-tail",
|
|
8585
|
+
"listing-error",
|
|
8586
|
+
"path-mismatch",
|
|
8587
|
+
"durable-refused"
|
|
8588
|
+
]);
|
|
8589
|
+
/** Every skip reason, always present, always a number — so a reason that never
|
|
8590
|
+
* fired reports as zero rather than absent and the report shape is constant
|
|
8591
|
+
* between passes. Spelled out rather than `z.record` for exactly that. */
|
|
8592
|
+
var LedgerWalkSkipCountsSchema = object({
|
|
8593
|
+
"live-tail": number().int().nonnegative(),
|
|
8594
|
+
"listing-error": number().int().nonnegative(),
|
|
8595
|
+
"path-mismatch": number().int().nonnegative(),
|
|
8596
|
+
"durable-refused": number().int().nonnegative()
|
|
8597
|
+
});
|
|
8598
|
+
/** One camera's share of a walk, so a report names cameras and not rows. */
|
|
8599
|
+
var LedgerWalkDeviceReportSchema = object({
|
|
8600
|
+
deviceId: number().int(),
|
|
8601
|
+
hoursWalked: number().int().nonnegative(),
|
|
8602
|
+
hoursMissing: number().int().nonnegative(),
|
|
8603
|
+
ghostSegments: number().int().nonnegative(),
|
|
8604
|
+
ghostBytes: number().int().nonnegative(),
|
|
8605
|
+
forgottenSegments: number().int().nonnegative(),
|
|
8606
|
+
orphanFiles: number().int().nonnegative()
|
|
8607
|
+
});
|
|
8608
|
+
/**
|
|
8609
|
+
* What one walk claimed, listed, found and (only when armed) forgot.
|
|
8610
|
+
*
|
|
8611
|
+
* `archiveSegments` is the **M** and `segmentsClaimed` the **N** (D295), so a
|
|
8612
|
+
* walk that saw a fraction of the location is visible in its own report rather
|
|
8613
|
+
* than in the absence of one.
|
|
8614
|
+
*/
|
|
8615
|
+
var LedgerWalkReportSchema = object({
|
|
8616
|
+
locationId: string(),
|
|
8617
|
+
applied: boolean(),
|
|
8618
|
+
refused: LedgerWalkRefusalSchema.nullable(),
|
|
8619
|
+
archiveSegments: number().int().nonnegative().nullable(),
|
|
8620
|
+
archiveBytes: number().int().nonnegative().nullable(),
|
|
8621
|
+
hoursClaimed: number().int().nonnegative(),
|
|
8622
|
+
hoursWalked: number().int().nonnegative(),
|
|
8623
|
+
hoursMissing: number().int().nonnegative(),
|
|
8624
|
+
/** `readdir` calls issued — the cost, stated in the unit that is paid. */
|
|
8625
|
+
listings: number().int().nonnegative(),
|
|
8626
|
+
segmentsClaimed: number().int().nonnegative(),
|
|
8627
|
+
ghostSegments: number().int().nonnegative(),
|
|
8628
|
+
ghostBytes: number().int().nonnegative(),
|
|
8629
|
+
ghostHoursWhole: number().int().nonnegative(),
|
|
8630
|
+
forgottenSegments: number().int().nonnegative(),
|
|
8631
|
+
forgottenBytes: number().int().nonnegative(),
|
|
8632
|
+
/** Files under a claimed hour that no durable row names. Never deleted. */
|
|
8633
|
+
orphanFiles: number().int().nonnegative(),
|
|
8634
|
+
orphanSample: array(string()).readonly(),
|
|
8635
|
+
hoursSkipped: number().int().nonnegative(),
|
|
8636
|
+
skippedByReason: LedgerWalkSkipCountsSchema,
|
|
8637
|
+
/** The walk stopped at its per-pass hour bound with claims unwalked. */
|
|
8638
|
+
bounded: boolean(),
|
|
8639
|
+
byDevice: array(LedgerWalkDeviceReportSchema).readonly()
|
|
8640
|
+
});
|
|
8542
8641
|
/** How many rows a media pass would still act on against a given target — the
|
|
8543
8642
|
* media lane's denominator AND its residue, from ONE derivation so the two can
|
|
8544
8643
|
* never disagree. `null` = the count could not be taken. */
|
|
@@ -19239,13 +19338,15 @@ var ListGroupsPageSchema = object({
|
|
|
19239
19338
|
groups: array(AnalyticsGroupRecordSchema).readonly(),
|
|
19240
19339
|
nextCursor: string().nullable()
|
|
19241
19340
|
});
|
|
19341
|
+
var KEY_EVENTS_DEFAULT_LIMIT = 50;
|
|
19342
|
+
var KEY_EVENTS_MAX_LIMIT = 200;
|
|
19242
19343
|
var KeyEventQueryInput = object({
|
|
19243
19344
|
deviceId: number(),
|
|
19244
19345
|
/** Window lower bound (track firstSeen ≥ since). */
|
|
19245
19346
|
since: number(),
|
|
19246
19347
|
/** Window upper bound (track firstSeen ≤ until). */
|
|
19247
19348
|
until: number(),
|
|
19248
|
-
limit: number().int().min(1).max(
|
|
19349
|
+
limit: number().int().min(1).max(KEY_EVENTS_MAX_LIMIT).default(KEY_EVENTS_DEFAULT_LIMIT),
|
|
19249
19350
|
/** Drop tracks scoring below this importance. */
|
|
19250
19351
|
minImportance: number().min(0).max(1).optional(),
|
|
19251
19352
|
/** Restrict to a single class (e.g. 'person'). */
|
|
@@ -19267,6 +19368,32 @@ var KeyEventSchema = object({
|
|
|
19267
19368
|
...TrackFlagFields,
|
|
19268
19369
|
...TrackRetrainFields
|
|
19269
19370
|
});
|
|
19371
|
+
/** `getKeyEvents`' window and filters, asked of a SET of cameras at once. */
|
|
19372
|
+
var KeyEventBatchQueryInput = object({
|
|
19373
|
+
deviceIds: array(number()).min(1).max(200),
|
|
19374
|
+
since: number(),
|
|
19375
|
+
until: number(),
|
|
19376
|
+
/** Applied PER CAMERA, exactly as `getKeyEvents.limit` is — never a total
|
|
19377
|
+
* across the set, which would let a busy camera starve a quiet one of its
|
|
19378
|
+
* rows and change what the merged feed contains. */
|
|
19379
|
+
limit: number().int().min(1).max(KEY_EVENTS_MAX_LIMIT).default(KEY_EVENTS_DEFAULT_LIMIT),
|
|
19380
|
+
minImportance: number().min(0).max(1).optional(),
|
|
19381
|
+
classFilter: string().optional()
|
|
19382
|
+
});
|
|
19383
|
+
/**
|
|
19384
|
+
* One camera's key events in a batch answer.
|
|
19385
|
+
*
|
|
19386
|
+
* The row exists for every requested id. `getKeyEvents` degrades to `[]` on
|
|
19387
|
+
* error rather than throwing, so a camera whose store read failed and one with
|
|
19388
|
+
* no events in the window were ALREADY indistinguishable per camera — the
|
|
19389
|
+
* batch does not make that worse, and the row keeps the deviceId the single
|
|
19390
|
+
* method's output never carried (the caller used to stamp it from the fan-out
|
|
19391
|
+
* key, which only worked because there was one query per camera).
|
|
19392
|
+
*/
|
|
19393
|
+
var KeyEventsForDeviceSchema = object({
|
|
19394
|
+
deviceId: number(),
|
|
19395
|
+
events: array(KeyEventSchema).readonly()
|
|
19396
|
+
});
|
|
19270
19397
|
object({
|
|
19271
19398
|
trackId: string(),
|
|
19272
19399
|
className: string(),
|
|
@@ -19536,7 +19663,7 @@ DeviceType.Camera, method(object({ deviceId: number() }), array(TrackSchema).rea
|
|
|
19536
19663
|
until: number().optional(),
|
|
19537
19664
|
kinds: array(string()).optional(),
|
|
19538
19665
|
limit: number().int().min(1).max(MAX_EVENT_QUERY_LIMIT).default(DEFAULT_EVENT_QUERY_LIMIT)
|
|
19539
|
-
}), array(SensorEventSchema).readonly()), method(KeyEventQueryInput, array(KeyEventSchema).readonly()), method(object({
|
|
19666
|
+
}), array(SensorEventSchema).readonly()), method(KeyEventQueryInput, array(KeyEventSchema).readonly()), method(KeyEventBatchQueryInput, array(KeyEventsForDeviceSchema).readonly()), method(object({
|
|
19540
19667
|
deviceId: number(),
|
|
19541
19668
|
since: number(),
|
|
19542
19669
|
until: number(),
|
|
@@ -28920,6 +29047,9 @@ method(object({
|
|
|
28920
29047
|
}), method(RelocateResidueInputSchema, RelocateResidueSchema, {
|
|
28921
29048
|
kind: "query",
|
|
28922
29049
|
auth: "admin"
|
|
29050
|
+
}), method(LedgerWalkInputSchema, LedgerWalkReportSchema, {
|
|
29051
|
+
kind: "mutation",
|
|
29052
|
+
auth: "admin"
|
|
28923
29053
|
}), method(object({ jobId: string() }), object({ cancelled: boolean() }), {
|
|
28924
29054
|
kind: "mutation",
|
|
28925
29055
|
auth: "admin"
|
|
@@ -29311,6 +29441,25 @@ var SceneMonitorStatusSchema = object({
|
|
|
29311
29441
|
monitors: array(SceneMonitorSchema),
|
|
29312
29442
|
lastFetchedAt: number()
|
|
29313
29443
|
});
|
|
29444
|
+
/**
|
|
29445
|
+
* One camera's row in a `listScenesBatch` answer.
|
|
29446
|
+
*
|
|
29447
|
+
* `status` is NULLABLE and the nullability is the whole point. `scene-monitor`
|
|
29448
|
+
* is a `defaultActive` wrapper, so every camera is asked; a camera whose
|
|
29449
|
+
* provider is absent (pipeline-analytics not deployed, the post-processing node
|
|
29450
|
+
* down) cannot answer, and that is not the same fact as a camera with no scenes
|
|
29451
|
+
* configured. Fanned out per camera the difference was visible — one query
|
|
29452
|
+
* errored while the others resolved — and a batch that returned only the rows
|
|
29453
|
+
* it managed would have destroyed it, silently, by making an unreachable camera
|
|
29454
|
+
* indistinguishable from one that answered `monitors: []`.
|
|
29455
|
+
*
|
|
29456
|
+
* So: EVERY requested deviceId gets a row. `status: null` means "this camera
|
|
29457
|
+
* could not be read"; `status.monitors: []` means "read, and it has none".
|
|
29458
|
+
*/
|
|
29459
|
+
var SceneMonitorStatusForDeviceSchema = object({
|
|
29460
|
+
deviceId: number(),
|
|
29461
|
+
status: SceneMonitorStatusSchema.nullable()
|
|
29462
|
+
});
|
|
29314
29463
|
var sceneMonitorCapability = {
|
|
29315
29464
|
name: "scene-monitor",
|
|
29316
29465
|
scope: "device",
|
|
@@ -29320,6 +29469,22 @@ var sceneMonitorCapability = {
|
|
|
29320
29469
|
deviceTypes: [DeviceType.Camera],
|
|
29321
29470
|
methods: {
|
|
29322
29471
|
listScenes: method(object({ deviceId: number() }), SceneMonitorStatusSchema),
|
|
29472
|
+
/**
|
|
29473
|
+
* The same answer, for a SET of cameras, in one round trip.
|
|
29474
|
+
*
|
|
29475
|
+
* `/scenes` renders every camera and re-reads them on a 30s safety-net
|
|
29476
|
+
* poll behind the push slice. Fanned out client-side that was one query
|
|
29477
|
+
* per camera — 29 round trips through the browser, the hub and the
|
|
29478
|
+
* post-analysis runner every 30 seconds to read an in-memory map the
|
|
29479
|
+
* owner had already merged. The work is unchanged (`statusFor` per
|
|
29480
|
+
* device, all in-process at the owner); what collapses is the transport.
|
|
29481
|
+
*
|
|
29482
|
+
* A camera that cannot answer still gets a row, with `status: null` —
|
|
29483
|
+
* see {@link SceneMonitorStatusForDeviceSchema}. Never fewer rows than
|
|
29484
|
+
* ids: a caller that asked for twenty-nine and got twenty-seven cannot
|
|
29485
|
+
* tell which two are missing, or that any are.
|
|
29486
|
+
*/
|
|
29487
|
+
listScenesBatch: method(object({ deviceIds: array(number()).min(1).max(200) }), array(SceneMonitorStatusForDeviceSchema).readonly()),
|
|
29323
29488
|
createScene: method(object({
|
|
29324
29489
|
deviceId: number(),
|
|
29325
29490
|
label: string(),
|
|
@@ -31155,6 +31320,27 @@ var CameraOccupancySnapshotSchema = object({
|
|
|
31155
31320
|
stationaryObjects: array(StationaryObjectSchema).readonly().optional()
|
|
31156
31321
|
});
|
|
31157
31322
|
/**
|
|
31323
|
+
* One camera's row in a `getCurrentSnapshotBatch` answer.
|
|
31324
|
+
*
|
|
31325
|
+
* THREE outcomes, and the single-camera method could only express two of them
|
|
31326
|
+
* because `snapshot: null` was already spoken for:
|
|
31327
|
+
*
|
|
31328
|
+
* - `read: 'read'`, `snapshot` present — the live occupancy reading.
|
|
31329
|
+
* - `read: 'read'`, `snapshot: null` — read, and this camera has no reading
|
|
31330
|
+
* yet: no frame since boot, and no parked-object registry to hydrate from.
|
|
31331
|
+
* - `read: 'unreadable'` — the owner could not answer for this
|
|
31332
|
+
* camera. `snapshot` is null, and it does NOT mean "nothing parked here".
|
|
31333
|
+
*
|
|
31334
|
+
* Collapsing the last two is the failure this field exists to prevent: a
|
|
31335
|
+
* hydration that threw would otherwise render as an empty Stationary section,
|
|
31336
|
+
* which is a definite claim about a camera nobody could read.
|
|
31337
|
+
*/
|
|
31338
|
+
var CameraOccupancySnapshotForDeviceSchema = object({
|
|
31339
|
+
deviceId: number(),
|
|
31340
|
+
read: _enum(["read", "unreadable"]),
|
|
31341
|
+
snapshot: CameraOccupancySnapshotSchema.nullable()
|
|
31342
|
+
});
|
|
31343
|
+
/**
|
|
31158
31344
|
* Time-series resolution. The history methods return one bucket per
|
|
31159
31345
|
* step over the requested range. Smaller resolutions cost more
|
|
31160
31346
|
* memory + bandwidth; bound to discrete steps so caller cannot ask
|
|
@@ -31211,6 +31397,20 @@ var zoneAnalyticsCapability = {
|
|
|
31211
31397
|
* (no inference result emitted since boot or since binding was
|
|
31212
31398
|
* activated). */
|
|
31213
31399
|
getCurrentSnapshot: method(object({ deviceId: number() }), CameraOccupancySnapshotSchema.nullable()),
|
|
31400
|
+
/**
|
|
31401
|
+
* The same snapshot, for a SET of cameras, in one round trip.
|
|
31402
|
+
*
|
|
31403
|
+
* The Events page's Stationary section polls this every 15s for every
|
|
31404
|
+
* selected camera. Fanned out client-side that is one query per camera to
|
|
31405
|
+
* read a `Map.get` at the owner — the answer costs nothing, the round trip
|
|
31406
|
+
* costs everything. Batched, N transports become one and the per-device
|
|
31407
|
+
* work is unchanged.
|
|
31408
|
+
*
|
|
31409
|
+
* Every requested deviceId gets a row, tagged `read` — see
|
|
31410
|
+
* {@link CameraOccupancySnapshotForDeviceSchema}. A camera the owner could
|
|
31411
|
+
* not answer for is `'unreadable'`, never an empty reading.
|
|
31412
|
+
*/
|
|
31413
|
+
getCurrentSnapshotBatch: method(object({ deviceIds: array(number()).min(1).max(200) }), array(CameraOccupancySnapshotForDeviceSchema).readonly()),
|
|
31214
31414
|
/** Time-series object count inside one zone. `className` optional —
|
|
31215
31415
|
* omit to count every class in the zone. */
|
|
31216
31416
|
getZoneHistory: method(object({
|
|
@@ -35632,6 +35832,12 @@ Object.freeze({
|
|
|
35632
35832
|
addonId: null,
|
|
35633
35833
|
access: "view"
|
|
35634
35834
|
},
|
|
35835
|
+
"pipelineAnalytics.getKeyEventsBatch": {
|
|
35836
|
+
capName: "pipeline-analytics",
|
|
35837
|
+
capScope: "device",
|
|
35838
|
+
addonId: null,
|
|
35839
|
+
access: "view"
|
|
35840
|
+
},
|
|
35635
35841
|
"pipelineAnalytics.getMotionEvents": {
|
|
35636
35842
|
capName: "pipeline-analytics",
|
|
35637
35843
|
capScope: "device",
|
|
@@ -36808,6 +37014,12 @@ Object.freeze({
|
|
|
36808
37014
|
addonId: null,
|
|
36809
37015
|
access: "view"
|
|
36810
37016
|
},
|
|
37017
|
+
"recording.reconcileLedgerAgainstDisk": {
|
|
37018
|
+
capName: "recording",
|
|
37019
|
+
capScope: "system",
|
|
37020
|
+
addonId: null,
|
|
37021
|
+
access: "create"
|
|
37022
|
+
},
|
|
36811
37023
|
"recording.refreshStorageLocationsForMigration": {
|
|
36812
37024
|
capName: "recording",
|
|
36813
37025
|
capScope: "system",
|
|
@@ -36934,6 +37146,12 @@ Object.freeze({
|
|
|
36934
37146
|
addonId: null,
|
|
36935
37147
|
access: "view"
|
|
36936
37148
|
},
|
|
37149
|
+
"sceneMonitor.listScenesBatch": {
|
|
37150
|
+
capName: "scene-monitor",
|
|
37151
|
+
capScope: "device",
|
|
37152
|
+
addonId: null,
|
|
37153
|
+
access: "view"
|
|
37154
|
+
},
|
|
36937
37155
|
"sceneMonitor.recheckNow": {
|
|
36938
37156
|
capName: "scene-monitor",
|
|
36939
37157
|
capScope: "device",
|
|
@@ -38290,6 +38508,12 @@ Object.freeze({
|
|
|
38290
38508
|
addonId: null,
|
|
38291
38509
|
access: "view"
|
|
38292
38510
|
},
|
|
38511
|
+
"zoneAnalytics.getCurrentSnapshotBatch": {
|
|
38512
|
+
capName: "zone-analytics",
|
|
38513
|
+
capScope: "device",
|
|
38514
|
+
addonId: null,
|
|
38515
|
+
access: "view"
|
|
38516
|
+
},
|
|
38293
38517
|
"zoneAnalytics.getUnzonedHistory": {
|
|
38294
38518
|
capName: "zone-analytics",
|
|
38295
38519
|
capScope: "device",
|
|
@@ -39294,6 +39518,11 @@ Object.freeze({
|
|
|
39294
39518
|
form: "single",
|
|
39295
39519
|
optional: false
|
|
39296
39520
|
}],
|
|
39521
|
+
"pipelineAnalytics.getKeyEventsBatch": [{
|
|
39522
|
+
name: "deviceIds",
|
|
39523
|
+
form: "array",
|
|
39524
|
+
optional: false
|
|
39525
|
+
}],
|
|
39297
39526
|
"pipelineAnalytics.getMotionEvents": [{
|
|
39298
39527
|
name: "deviceId",
|
|
39299
39528
|
form: "single",
|
|
@@ -39734,6 +39963,11 @@ Object.freeze({
|
|
|
39734
39963
|
form: "single",
|
|
39735
39964
|
optional: false
|
|
39736
39965
|
}],
|
|
39966
|
+
"recording.reconcileLedgerAgainstDisk": [{
|
|
39967
|
+
name: "deviceId",
|
|
39968
|
+
form: "single",
|
|
39969
|
+
optional: true
|
|
39970
|
+
}],
|
|
39737
39971
|
"recording.relocateFootage": [{
|
|
39738
39972
|
name: "deviceId",
|
|
39739
39973
|
form: "single",
|
|
@@ -39799,6 +40033,11 @@ Object.freeze({
|
|
|
39799
40033
|
form: "single",
|
|
39800
40034
|
optional: false
|
|
39801
40035
|
}],
|
|
40036
|
+
"sceneMonitor.listScenesBatch": [{
|
|
40037
|
+
name: "deviceIds",
|
|
40038
|
+
form: "array",
|
|
40039
|
+
optional: false
|
|
40040
|
+
}],
|
|
39802
40041
|
"sceneMonitor.recheckNow": [{
|
|
39803
40042
|
name: "deviceId",
|
|
39804
40043
|
form: "single",
|
|
@@ -40060,6 +40299,11 @@ Object.freeze({
|
|
|
40060
40299
|
form: "single",
|
|
40061
40300
|
optional: false
|
|
40062
40301
|
}],
|
|
40302
|
+
"zoneAnalytics.getCurrentSnapshotBatch": [{
|
|
40303
|
+
name: "deviceIds",
|
|
40304
|
+
form: "array",
|
|
40305
|
+
optional: false
|
|
40306
|
+
}],
|
|
40063
40307
|
"zoneAnalytics.getUnzonedHistory": [{
|
|
40064
40308
|
name: "deviceId",
|
|
40065
40309
|
form: "single",
|
package/dist/addon.mjs
CHANGED
|
@@ -8176,6 +8176,20 @@ var RelocateJobSchema = object({
|
|
|
8176
8176
|
* in its row, not in its name, so `MediaRelocateEngine` never reconciles one.
|
|
8177
8177
|
*/
|
|
8178
8178
|
rowsReconciled: number().int().nonnegative().optional(),
|
|
8179
|
+
/**
|
|
8180
|
+
* Rows this run FORGOT because the file they name is not on disk.
|
|
8181
|
+
*
|
|
8182
|
+
* The mover derived the path from the row's own fields and `stat`ed it; an
|
|
8183
|
+
* ENOENT there is a per-path confirmation that the segment is gone (D296),
|
|
8184
|
+
* and the durable row is dropped through the same channel eviction uses. It
|
|
8185
|
+
* is reported for the same reason `rowsReconciled` is: this is a durable
|
|
8186
|
+
* mutation nobody asked for, and a migration that quietly erases hour rows is
|
|
8187
|
+
* the same failure as one that quietly skips them (D295).
|
|
8188
|
+
*
|
|
8189
|
+
* The production drain of 2026-08-30 would have reported 11 074 here — the
|
|
8190
|
+
* ledger claimed 5.65 GB of footage that no longer existed.
|
|
8191
|
+
*/
|
|
8192
|
+
rowsForgotten: number().int().nonnegative().optional(),
|
|
8179
8193
|
startedAt: number(),
|
|
8180
8194
|
finishedAt: number().nullable(),
|
|
8181
8195
|
error: string().nullable()
|
|
@@ -8539,6 +8553,91 @@ var RelocateResidueSchema = object({
|
|
|
8539
8553
|
segments: number().int().nonnegative(),
|
|
8540
8554
|
bytes: number().int().nonnegative()
|
|
8541
8555
|
}).nullable();
|
|
8556
|
+
/**
|
|
8557
|
+
* Ask one location whether its durable hour rows describe the disk — the walk
|
|
8558
|
+
* (D319).
|
|
8559
|
+
*
|
|
8560
|
+
* `apply` DEFAULTS TO FALSE and that default is the product: the operator's
|
|
8561
|
+
* missing tool is the question, and the dry run is how they sanity-check the
|
|
8562
|
+
* destructive run before authorising it.
|
|
8563
|
+
*/
|
|
8564
|
+
var LedgerWalkInputSchema = object({
|
|
8565
|
+
locationId: string().min(1),
|
|
8566
|
+
/** Forget the confirmed-absent rows, rather than only counting them. */
|
|
8567
|
+
apply: boolean().optional(),
|
|
8568
|
+
/** Narrow to one camera. */
|
|
8569
|
+
deviceId: number().int().positive().optional(),
|
|
8570
|
+
/** Narrow to these recording profiles; empty/absent = every profile. */
|
|
8571
|
+
profiles: array(string().min(1)).optional()
|
|
8572
|
+
});
|
|
8573
|
+
/** Why a whole walk did nothing. Every one leaves the ledger untouched. */
|
|
8574
|
+
var LedgerWalkRefusalSchema = _enum([
|
|
8575
|
+
"location-unknown",
|
|
8576
|
+
"source-writable",
|
|
8577
|
+
"no-ledger",
|
|
8578
|
+
"archive-unreadable",
|
|
8579
|
+
"anchor-absent",
|
|
8580
|
+
"anchor-unreadable",
|
|
8581
|
+
"anchor-moved"
|
|
8582
|
+
]);
|
|
8583
|
+
_enum([
|
|
8584
|
+
"live-tail",
|
|
8585
|
+
"listing-error",
|
|
8586
|
+
"path-mismatch",
|
|
8587
|
+
"durable-refused"
|
|
8588
|
+
]);
|
|
8589
|
+
/** Every skip reason, always present, always a number — so a reason that never
|
|
8590
|
+
* fired reports as zero rather than absent and the report shape is constant
|
|
8591
|
+
* between passes. Spelled out rather than `z.record` for exactly that. */
|
|
8592
|
+
var LedgerWalkSkipCountsSchema = object({
|
|
8593
|
+
"live-tail": number().int().nonnegative(),
|
|
8594
|
+
"listing-error": number().int().nonnegative(),
|
|
8595
|
+
"path-mismatch": number().int().nonnegative(),
|
|
8596
|
+
"durable-refused": number().int().nonnegative()
|
|
8597
|
+
});
|
|
8598
|
+
/** One camera's share of a walk, so a report names cameras and not rows. */
|
|
8599
|
+
var LedgerWalkDeviceReportSchema = object({
|
|
8600
|
+
deviceId: number().int(),
|
|
8601
|
+
hoursWalked: number().int().nonnegative(),
|
|
8602
|
+
hoursMissing: number().int().nonnegative(),
|
|
8603
|
+
ghostSegments: number().int().nonnegative(),
|
|
8604
|
+
ghostBytes: number().int().nonnegative(),
|
|
8605
|
+
forgottenSegments: number().int().nonnegative(),
|
|
8606
|
+
orphanFiles: number().int().nonnegative()
|
|
8607
|
+
});
|
|
8608
|
+
/**
|
|
8609
|
+
* What one walk claimed, listed, found and (only when armed) forgot.
|
|
8610
|
+
*
|
|
8611
|
+
* `archiveSegments` is the **M** and `segmentsClaimed` the **N** (D295), so a
|
|
8612
|
+
* walk that saw a fraction of the location is visible in its own report rather
|
|
8613
|
+
* than in the absence of one.
|
|
8614
|
+
*/
|
|
8615
|
+
var LedgerWalkReportSchema = object({
|
|
8616
|
+
locationId: string(),
|
|
8617
|
+
applied: boolean(),
|
|
8618
|
+
refused: LedgerWalkRefusalSchema.nullable(),
|
|
8619
|
+
archiveSegments: number().int().nonnegative().nullable(),
|
|
8620
|
+
archiveBytes: number().int().nonnegative().nullable(),
|
|
8621
|
+
hoursClaimed: number().int().nonnegative(),
|
|
8622
|
+
hoursWalked: number().int().nonnegative(),
|
|
8623
|
+
hoursMissing: number().int().nonnegative(),
|
|
8624
|
+
/** `readdir` calls issued — the cost, stated in the unit that is paid. */
|
|
8625
|
+
listings: number().int().nonnegative(),
|
|
8626
|
+
segmentsClaimed: number().int().nonnegative(),
|
|
8627
|
+
ghostSegments: number().int().nonnegative(),
|
|
8628
|
+
ghostBytes: number().int().nonnegative(),
|
|
8629
|
+
ghostHoursWhole: number().int().nonnegative(),
|
|
8630
|
+
forgottenSegments: number().int().nonnegative(),
|
|
8631
|
+
forgottenBytes: number().int().nonnegative(),
|
|
8632
|
+
/** Files under a claimed hour that no durable row names. Never deleted. */
|
|
8633
|
+
orphanFiles: number().int().nonnegative(),
|
|
8634
|
+
orphanSample: array(string()).readonly(),
|
|
8635
|
+
hoursSkipped: number().int().nonnegative(),
|
|
8636
|
+
skippedByReason: LedgerWalkSkipCountsSchema,
|
|
8637
|
+
/** The walk stopped at its per-pass hour bound with claims unwalked. */
|
|
8638
|
+
bounded: boolean(),
|
|
8639
|
+
byDevice: array(LedgerWalkDeviceReportSchema).readonly()
|
|
8640
|
+
});
|
|
8542
8641
|
/** How many rows a media pass would still act on against a given target — the
|
|
8543
8642
|
* media lane's denominator AND its residue, from ONE derivation so the two can
|
|
8544
8643
|
* never disagree. `null` = the count could not be taken. */
|
|
@@ -19239,13 +19338,15 @@ var ListGroupsPageSchema = object({
|
|
|
19239
19338
|
groups: array(AnalyticsGroupRecordSchema).readonly(),
|
|
19240
19339
|
nextCursor: string().nullable()
|
|
19241
19340
|
});
|
|
19341
|
+
var KEY_EVENTS_DEFAULT_LIMIT = 50;
|
|
19342
|
+
var KEY_EVENTS_MAX_LIMIT = 200;
|
|
19242
19343
|
var KeyEventQueryInput = object({
|
|
19243
19344
|
deviceId: number(),
|
|
19244
19345
|
/** Window lower bound (track firstSeen ≥ since). */
|
|
19245
19346
|
since: number(),
|
|
19246
19347
|
/** Window upper bound (track firstSeen ≤ until). */
|
|
19247
19348
|
until: number(),
|
|
19248
|
-
limit: number().int().min(1).max(
|
|
19349
|
+
limit: number().int().min(1).max(KEY_EVENTS_MAX_LIMIT).default(KEY_EVENTS_DEFAULT_LIMIT),
|
|
19249
19350
|
/** Drop tracks scoring below this importance. */
|
|
19250
19351
|
minImportance: number().min(0).max(1).optional(),
|
|
19251
19352
|
/** Restrict to a single class (e.g. 'person'). */
|
|
@@ -19267,6 +19368,32 @@ var KeyEventSchema = object({
|
|
|
19267
19368
|
...TrackFlagFields,
|
|
19268
19369
|
...TrackRetrainFields
|
|
19269
19370
|
});
|
|
19371
|
+
/** `getKeyEvents`' window and filters, asked of a SET of cameras at once. */
|
|
19372
|
+
var KeyEventBatchQueryInput = object({
|
|
19373
|
+
deviceIds: array(number()).min(1).max(200),
|
|
19374
|
+
since: number(),
|
|
19375
|
+
until: number(),
|
|
19376
|
+
/** Applied PER CAMERA, exactly as `getKeyEvents.limit` is — never a total
|
|
19377
|
+
* across the set, which would let a busy camera starve a quiet one of its
|
|
19378
|
+
* rows and change what the merged feed contains. */
|
|
19379
|
+
limit: number().int().min(1).max(KEY_EVENTS_MAX_LIMIT).default(KEY_EVENTS_DEFAULT_LIMIT),
|
|
19380
|
+
minImportance: number().min(0).max(1).optional(),
|
|
19381
|
+
classFilter: string().optional()
|
|
19382
|
+
});
|
|
19383
|
+
/**
|
|
19384
|
+
* One camera's key events in a batch answer.
|
|
19385
|
+
*
|
|
19386
|
+
* The row exists for every requested id. `getKeyEvents` degrades to `[]` on
|
|
19387
|
+
* error rather than throwing, so a camera whose store read failed and one with
|
|
19388
|
+
* no events in the window were ALREADY indistinguishable per camera — the
|
|
19389
|
+
* batch does not make that worse, and the row keeps the deviceId the single
|
|
19390
|
+
* method's output never carried (the caller used to stamp it from the fan-out
|
|
19391
|
+
* key, which only worked because there was one query per camera).
|
|
19392
|
+
*/
|
|
19393
|
+
var KeyEventsForDeviceSchema = object({
|
|
19394
|
+
deviceId: number(),
|
|
19395
|
+
events: array(KeyEventSchema).readonly()
|
|
19396
|
+
});
|
|
19270
19397
|
object({
|
|
19271
19398
|
trackId: string(),
|
|
19272
19399
|
className: string(),
|
|
@@ -19536,7 +19663,7 @@ DeviceType.Camera, method(object({ deviceId: number() }), array(TrackSchema).rea
|
|
|
19536
19663
|
until: number().optional(),
|
|
19537
19664
|
kinds: array(string()).optional(),
|
|
19538
19665
|
limit: number().int().min(1).max(MAX_EVENT_QUERY_LIMIT).default(DEFAULT_EVENT_QUERY_LIMIT)
|
|
19539
|
-
}), array(SensorEventSchema).readonly()), method(KeyEventQueryInput, array(KeyEventSchema).readonly()), method(object({
|
|
19666
|
+
}), array(SensorEventSchema).readonly()), method(KeyEventQueryInput, array(KeyEventSchema).readonly()), method(KeyEventBatchQueryInput, array(KeyEventsForDeviceSchema).readonly()), method(object({
|
|
19540
19667
|
deviceId: number(),
|
|
19541
19668
|
since: number(),
|
|
19542
19669
|
until: number(),
|
|
@@ -28920,6 +29047,9 @@ method(object({
|
|
|
28920
29047
|
}), method(RelocateResidueInputSchema, RelocateResidueSchema, {
|
|
28921
29048
|
kind: "query",
|
|
28922
29049
|
auth: "admin"
|
|
29050
|
+
}), method(LedgerWalkInputSchema, LedgerWalkReportSchema, {
|
|
29051
|
+
kind: "mutation",
|
|
29052
|
+
auth: "admin"
|
|
28923
29053
|
}), method(object({ jobId: string() }), object({ cancelled: boolean() }), {
|
|
28924
29054
|
kind: "mutation",
|
|
28925
29055
|
auth: "admin"
|
|
@@ -29311,6 +29441,25 @@ var SceneMonitorStatusSchema = object({
|
|
|
29311
29441
|
monitors: array(SceneMonitorSchema),
|
|
29312
29442
|
lastFetchedAt: number()
|
|
29313
29443
|
});
|
|
29444
|
+
/**
|
|
29445
|
+
* One camera's row in a `listScenesBatch` answer.
|
|
29446
|
+
*
|
|
29447
|
+
* `status` is NULLABLE and the nullability is the whole point. `scene-monitor`
|
|
29448
|
+
* is a `defaultActive` wrapper, so every camera is asked; a camera whose
|
|
29449
|
+
* provider is absent (pipeline-analytics not deployed, the post-processing node
|
|
29450
|
+
* down) cannot answer, and that is not the same fact as a camera with no scenes
|
|
29451
|
+
* configured. Fanned out per camera the difference was visible — one query
|
|
29452
|
+
* errored while the others resolved — and a batch that returned only the rows
|
|
29453
|
+
* it managed would have destroyed it, silently, by making an unreachable camera
|
|
29454
|
+
* indistinguishable from one that answered `monitors: []`.
|
|
29455
|
+
*
|
|
29456
|
+
* So: EVERY requested deviceId gets a row. `status: null` means "this camera
|
|
29457
|
+
* could not be read"; `status.monitors: []` means "read, and it has none".
|
|
29458
|
+
*/
|
|
29459
|
+
var SceneMonitorStatusForDeviceSchema = object({
|
|
29460
|
+
deviceId: number(),
|
|
29461
|
+
status: SceneMonitorStatusSchema.nullable()
|
|
29462
|
+
});
|
|
29314
29463
|
var sceneMonitorCapability = {
|
|
29315
29464
|
name: "scene-monitor",
|
|
29316
29465
|
scope: "device",
|
|
@@ -29320,6 +29469,22 @@ var sceneMonitorCapability = {
|
|
|
29320
29469
|
deviceTypes: [DeviceType.Camera],
|
|
29321
29470
|
methods: {
|
|
29322
29471
|
listScenes: method(object({ deviceId: number() }), SceneMonitorStatusSchema),
|
|
29472
|
+
/**
|
|
29473
|
+
* The same answer, for a SET of cameras, in one round trip.
|
|
29474
|
+
*
|
|
29475
|
+
* `/scenes` renders every camera and re-reads them on a 30s safety-net
|
|
29476
|
+
* poll behind the push slice. Fanned out client-side that was one query
|
|
29477
|
+
* per camera — 29 round trips through the browser, the hub and the
|
|
29478
|
+
* post-analysis runner every 30 seconds to read an in-memory map the
|
|
29479
|
+
* owner had already merged. The work is unchanged (`statusFor` per
|
|
29480
|
+
* device, all in-process at the owner); what collapses is the transport.
|
|
29481
|
+
*
|
|
29482
|
+
* A camera that cannot answer still gets a row, with `status: null` —
|
|
29483
|
+
* see {@link SceneMonitorStatusForDeviceSchema}. Never fewer rows than
|
|
29484
|
+
* ids: a caller that asked for twenty-nine and got twenty-seven cannot
|
|
29485
|
+
* tell which two are missing, or that any are.
|
|
29486
|
+
*/
|
|
29487
|
+
listScenesBatch: method(object({ deviceIds: array(number()).min(1).max(200) }), array(SceneMonitorStatusForDeviceSchema).readonly()),
|
|
29323
29488
|
createScene: method(object({
|
|
29324
29489
|
deviceId: number(),
|
|
29325
29490
|
label: string(),
|
|
@@ -31155,6 +31320,27 @@ var CameraOccupancySnapshotSchema = object({
|
|
|
31155
31320
|
stationaryObjects: array(StationaryObjectSchema).readonly().optional()
|
|
31156
31321
|
});
|
|
31157
31322
|
/**
|
|
31323
|
+
* One camera's row in a `getCurrentSnapshotBatch` answer.
|
|
31324
|
+
*
|
|
31325
|
+
* THREE outcomes, and the single-camera method could only express two of them
|
|
31326
|
+
* because `snapshot: null` was already spoken for:
|
|
31327
|
+
*
|
|
31328
|
+
* - `read: 'read'`, `snapshot` present — the live occupancy reading.
|
|
31329
|
+
* - `read: 'read'`, `snapshot: null` — read, and this camera has no reading
|
|
31330
|
+
* yet: no frame since boot, and no parked-object registry to hydrate from.
|
|
31331
|
+
* - `read: 'unreadable'` — the owner could not answer for this
|
|
31332
|
+
* camera. `snapshot` is null, and it does NOT mean "nothing parked here".
|
|
31333
|
+
*
|
|
31334
|
+
* Collapsing the last two is the failure this field exists to prevent: a
|
|
31335
|
+
* hydration that threw would otherwise render as an empty Stationary section,
|
|
31336
|
+
* which is a definite claim about a camera nobody could read.
|
|
31337
|
+
*/
|
|
31338
|
+
var CameraOccupancySnapshotForDeviceSchema = object({
|
|
31339
|
+
deviceId: number(),
|
|
31340
|
+
read: _enum(["read", "unreadable"]),
|
|
31341
|
+
snapshot: CameraOccupancySnapshotSchema.nullable()
|
|
31342
|
+
});
|
|
31343
|
+
/**
|
|
31158
31344
|
* Time-series resolution. The history methods return one bucket per
|
|
31159
31345
|
* step over the requested range. Smaller resolutions cost more
|
|
31160
31346
|
* memory + bandwidth; bound to discrete steps so caller cannot ask
|
|
@@ -31211,6 +31397,20 @@ var zoneAnalyticsCapability = {
|
|
|
31211
31397
|
* (no inference result emitted since boot or since binding was
|
|
31212
31398
|
* activated). */
|
|
31213
31399
|
getCurrentSnapshot: method(object({ deviceId: number() }), CameraOccupancySnapshotSchema.nullable()),
|
|
31400
|
+
/**
|
|
31401
|
+
* The same snapshot, for a SET of cameras, in one round trip.
|
|
31402
|
+
*
|
|
31403
|
+
* The Events page's Stationary section polls this every 15s for every
|
|
31404
|
+
* selected camera. Fanned out client-side that is one query per camera to
|
|
31405
|
+
* read a `Map.get` at the owner — the answer costs nothing, the round trip
|
|
31406
|
+
* costs everything. Batched, N transports become one and the per-device
|
|
31407
|
+
* work is unchanged.
|
|
31408
|
+
*
|
|
31409
|
+
* Every requested deviceId gets a row, tagged `read` — see
|
|
31410
|
+
* {@link CameraOccupancySnapshotForDeviceSchema}. A camera the owner could
|
|
31411
|
+
* not answer for is `'unreadable'`, never an empty reading.
|
|
31412
|
+
*/
|
|
31413
|
+
getCurrentSnapshotBatch: method(object({ deviceIds: array(number()).min(1).max(200) }), array(CameraOccupancySnapshotForDeviceSchema).readonly()),
|
|
31214
31414
|
/** Time-series object count inside one zone. `className` optional —
|
|
31215
31415
|
* omit to count every class in the zone. */
|
|
31216
31416
|
getZoneHistory: method(object({
|
|
@@ -35632,6 +35832,12 @@ Object.freeze({
|
|
|
35632
35832
|
addonId: null,
|
|
35633
35833
|
access: "view"
|
|
35634
35834
|
},
|
|
35835
|
+
"pipelineAnalytics.getKeyEventsBatch": {
|
|
35836
|
+
capName: "pipeline-analytics",
|
|
35837
|
+
capScope: "device",
|
|
35838
|
+
addonId: null,
|
|
35839
|
+
access: "view"
|
|
35840
|
+
},
|
|
35635
35841
|
"pipelineAnalytics.getMotionEvents": {
|
|
35636
35842
|
capName: "pipeline-analytics",
|
|
35637
35843
|
capScope: "device",
|
|
@@ -36808,6 +37014,12 @@ Object.freeze({
|
|
|
36808
37014
|
addonId: null,
|
|
36809
37015
|
access: "view"
|
|
36810
37016
|
},
|
|
37017
|
+
"recording.reconcileLedgerAgainstDisk": {
|
|
37018
|
+
capName: "recording",
|
|
37019
|
+
capScope: "system",
|
|
37020
|
+
addonId: null,
|
|
37021
|
+
access: "create"
|
|
37022
|
+
},
|
|
36811
37023
|
"recording.refreshStorageLocationsForMigration": {
|
|
36812
37024
|
capName: "recording",
|
|
36813
37025
|
capScope: "system",
|
|
@@ -36934,6 +37146,12 @@ Object.freeze({
|
|
|
36934
37146
|
addonId: null,
|
|
36935
37147
|
access: "view"
|
|
36936
37148
|
},
|
|
37149
|
+
"sceneMonitor.listScenesBatch": {
|
|
37150
|
+
capName: "scene-monitor",
|
|
37151
|
+
capScope: "device",
|
|
37152
|
+
addonId: null,
|
|
37153
|
+
access: "view"
|
|
37154
|
+
},
|
|
36937
37155
|
"sceneMonitor.recheckNow": {
|
|
36938
37156
|
capName: "scene-monitor",
|
|
36939
37157
|
capScope: "device",
|
|
@@ -38290,6 +38508,12 @@ Object.freeze({
|
|
|
38290
38508
|
addonId: null,
|
|
38291
38509
|
access: "view"
|
|
38292
38510
|
},
|
|
38511
|
+
"zoneAnalytics.getCurrentSnapshotBatch": {
|
|
38512
|
+
capName: "zone-analytics",
|
|
38513
|
+
capScope: "device",
|
|
38514
|
+
addonId: null,
|
|
38515
|
+
access: "view"
|
|
38516
|
+
},
|
|
38293
38517
|
"zoneAnalytics.getUnzonedHistory": {
|
|
38294
38518
|
capName: "zone-analytics",
|
|
38295
38519
|
capScope: "device",
|
|
@@ -39294,6 +39518,11 @@ Object.freeze({
|
|
|
39294
39518
|
form: "single",
|
|
39295
39519
|
optional: false
|
|
39296
39520
|
}],
|
|
39521
|
+
"pipelineAnalytics.getKeyEventsBatch": [{
|
|
39522
|
+
name: "deviceIds",
|
|
39523
|
+
form: "array",
|
|
39524
|
+
optional: false
|
|
39525
|
+
}],
|
|
39297
39526
|
"pipelineAnalytics.getMotionEvents": [{
|
|
39298
39527
|
name: "deviceId",
|
|
39299
39528
|
form: "single",
|
|
@@ -39734,6 +39963,11 @@ Object.freeze({
|
|
|
39734
39963
|
form: "single",
|
|
39735
39964
|
optional: false
|
|
39736
39965
|
}],
|
|
39966
|
+
"recording.reconcileLedgerAgainstDisk": [{
|
|
39967
|
+
name: "deviceId",
|
|
39968
|
+
form: "single",
|
|
39969
|
+
optional: true
|
|
39970
|
+
}],
|
|
39737
39971
|
"recording.relocateFootage": [{
|
|
39738
39972
|
name: "deviceId",
|
|
39739
39973
|
form: "single",
|
|
@@ -39799,6 +40033,11 @@ Object.freeze({
|
|
|
39799
40033
|
form: "single",
|
|
39800
40034
|
optional: false
|
|
39801
40035
|
}],
|
|
40036
|
+
"sceneMonitor.listScenesBatch": [{
|
|
40037
|
+
name: "deviceIds",
|
|
40038
|
+
form: "array",
|
|
40039
|
+
optional: false
|
|
40040
|
+
}],
|
|
39802
40041
|
"sceneMonitor.recheckNow": [{
|
|
39803
40042
|
name: "deviceId",
|
|
39804
40043
|
form: "single",
|
|
@@ -40060,6 +40299,11 @@ Object.freeze({
|
|
|
40060
40299
|
form: "single",
|
|
40061
40300
|
optional: false
|
|
40062
40301
|
}],
|
|
40302
|
+
"zoneAnalytics.getCurrentSnapshotBatch": [{
|
|
40303
|
+
name: "deviceIds",
|
|
40304
|
+
form: "array",
|
|
40305
|
+
optional: false
|
|
40306
|
+
}],
|
|
40063
40307
|
"zoneAnalytics.getUnzonedHistory": [{
|
|
40064
40308
|
name: "deviceId",
|
|
40065
40309
|
form: "single",
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@camstack/addon-import-alexa",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.48",
|
|
4
4
|
"description": "Alexa device-import provider for CamStack — imports the smart-home devices in a user's Alexa account via the unofficial alexa-remote2 cookie/token client (the inverse of the Alexa exporter)",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"camstack",
|