camstack 1.2.67 → 1.2.69
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.
|
@@ -23633,9 +23633,9 @@ var require_zod = __commonJS({
|
|
|
23633
23633
|
}
|
|
23634
23634
|
});
|
|
23635
23635
|
|
|
23636
|
-
// ../system/dist/dist-
|
|
23637
|
-
var
|
|
23638
|
-
"../system/dist/dist-
|
|
23636
|
+
// ../system/dist/dist-B29Skpzo.js
|
|
23637
|
+
var require_dist_B29Skpzo = __commonJS({
|
|
23638
|
+
"../system/dist/dist-B29Skpzo.js"(exports) {
|
|
23639
23639
|
"use strict";
|
|
23640
23640
|
var zod = require_zod();
|
|
23641
23641
|
var EventCategory = /* @__PURE__ */ (function(EventCategory2) {
|
|
@@ -26274,6 +26274,20 @@ var require_dist_Keu5TDO7 = __commonJS({
|
|
|
26274
26274
|
* in its row, not in its name, so `MediaRelocateEngine` never reconciles one.
|
|
26275
26275
|
*/
|
|
26276
26276
|
rowsReconciled: zod.z.number().int().nonnegative().optional(),
|
|
26277
|
+
/**
|
|
26278
|
+
* Rows this run FORGOT because the file they name is not on disk.
|
|
26279
|
+
*
|
|
26280
|
+
* The mover derived the path from the row's own fields and `stat`ed it; an
|
|
26281
|
+
* ENOENT there is a per-path confirmation that the segment is gone (D296),
|
|
26282
|
+
* and the durable row is dropped through the same channel eviction uses. It
|
|
26283
|
+
* is reported for the same reason `rowsReconciled` is: this is a durable
|
|
26284
|
+
* mutation nobody asked for, and a migration that quietly erases hour rows is
|
|
26285
|
+
* the same failure as one that quietly skips them (D295).
|
|
26286
|
+
*
|
|
26287
|
+
* The production drain of 2026-08-30 would have reported 11 074 here — the
|
|
26288
|
+
* ledger claimed 5.65 GB of footage that no longer existed.
|
|
26289
|
+
*/
|
|
26290
|
+
rowsForgotten: zod.z.number().int().nonnegative().optional(),
|
|
26277
26291
|
startedAt: zod.z.number(),
|
|
26278
26292
|
finishedAt: zod.z.number().nullable(),
|
|
26279
26293
|
error: zod.z.string().nullable()
|
|
@@ -26481,6 +26495,71 @@ var require_dist_Keu5TDO7 = __commonJS({
|
|
|
26481
26495
|
segments: zod.z.number().int().nonnegative(),
|
|
26482
26496
|
bytes: zod.z.number().int().nonnegative()
|
|
26483
26497
|
}).nullable();
|
|
26498
|
+
var LedgerWalkInputSchema = zod.z.object({
|
|
26499
|
+
locationId: zod.z.string().min(1),
|
|
26500
|
+
/** Forget the confirmed-absent rows, rather than only counting them. */
|
|
26501
|
+
apply: zod.z.boolean().optional(),
|
|
26502
|
+
/** Narrow to one camera. */
|
|
26503
|
+
deviceId: zod.z.number().int().positive().optional(),
|
|
26504
|
+
/** Narrow to these recording profiles; empty/absent = every profile. */
|
|
26505
|
+
profiles: zod.z.array(zod.z.string().min(1)).optional()
|
|
26506
|
+
});
|
|
26507
|
+
var LedgerWalkRefusalSchema = zod.z.enum([
|
|
26508
|
+
"location-unknown",
|
|
26509
|
+
"source-writable",
|
|
26510
|
+
"no-ledger",
|
|
26511
|
+
"archive-unreadable",
|
|
26512
|
+
"anchor-absent",
|
|
26513
|
+
"anchor-unreadable",
|
|
26514
|
+
"anchor-moved"
|
|
26515
|
+
]);
|
|
26516
|
+
zod.z.enum([
|
|
26517
|
+
"live-tail",
|
|
26518
|
+
"listing-error",
|
|
26519
|
+
"path-mismatch",
|
|
26520
|
+
"durable-refused"
|
|
26521
|
+
]);
|
|
26522
|
+
var LedgerWalkSkipCountsSchema = zod.z.object({
|
|
26523
|
+
"live-tail": zod.z.number().int().nonnegative(),
|
|
26524
|
+
"listing-error": zod.z.number().int().nonnegative(),
|
|
26525
|
+
"path-mismatch": zod.z.number().int().nonnegative(),
|
|
26526
|
+
"durable-refused": zod.z.number().int().nonnegative()
|
|
26527
|
+
});
|
|
26528
|
+
var LedgerWalkDeviceReportSchema = zod.z.object({
|
|
26529
|
+
deviceId: zod.z.number().int(),
|
|
26530
|
+
hoursWalked: zod.z.number().int().nonnegative(),
|
|
26531
|
+
hoursMissing: zod.z.number().int().nonnegative(),
|
|
26532
|
+
ghostSegments: zod.z.number().int().nonnegative(),
|
|
26533
|
+
ghostBytes: zod.z.number().int().nonnegative(),
|
|
26534
|
+
forgottenSegments: zod.z.number().int().nonnegative(),
|
|
26535
|
+
orphanFiles: zod.z.number().int().nonnegative()
|
|
26536
|
+
});
|
|
26537
|
+
var LedgerWalkReportSchema = zod.z.object({
|
|
26538
|
+
locationId: zod.z.string(),
|
|
26539
|
+
applied: zod.z.boolean(),
|
|
26540
|
+
refused: LedgerWalkRefusalSchema.nullable(),
|
|
26541
|
+
archiveSegments: zod.z.number().int().nonnegative().nullable(),
|
|
26542
|
+
archiveBytes: zod.z.number().int().nonnegative().nullable(),
|
|
26543
|
+
hoursClaimed: zod.z.number().int().nonnegative(),
|
|
26544
|
+
hoursWalked: zod.z.number().int().nonnegative(),
|
|
26545
|
+
hoursMissing: zod.z.number().int().nonnegative(),
|
|
26546
|
+
/** `readdir` calls issued — the cost, stated in the unit that is paid. */
|
|
26547
|
+
listings: zod.z.number().int().nonnegative(),
|
|
26548
|
+
segmentsClaimed: zod.z.number().int().nonnegative(),
|
|
26549
|
+
ghostSegments: zod.z.number().int().nonnegative(),
|
|
26550
|
+
ghostBytes: zod.z.number().int().nonnegative(),
|
|
26551
|
+
ghostHoursWhole: zod.z.number().int().nonnegative(),
|
|
26552
|
+
forgottenSegments: zod.z.number().int().nonnegative(),
|
|
26553
|
+
forgottenBytes: zod.z.number().int().nonnegative(),
|
|
26554
|
+
/** Files under a claimed hour that no durable row names. Never deleted. */
|
|
26555
|
+
orphanFiles: zod.z.number().int().nonnegative(),
|
|
26556
|
+
orphanSample: zod.z.array(zod.z.string()).readonly(),
|
|
26557
|
+
hoursSkipped: zod.z.number().int().nonnegative(),
|
|
26558
|
+
skippedByReason: LedgerWalkSkipCountsSchema,
|
|
26559
|
+
/** The walk stopped at its per-pass hour bound with claims unwalked. */
|
|
26560
|
+
bounded: zod.z.boolean(),
|
|
26561
|
+
byDevice: zod.z.array(LedgerWalkDeviceReportSchema).readonly()
|
|
26562
|
+
});
|
|
26484
26563
|
var RelocatableMediaCountSchema = zod.z.object({ rows: zod.z.number().int().nonnegative() }).nullable();
|
|
26485
26564
|
var RelocatableMediaCountInputSchema = zod.z.object({
|
|
26486
26565
|
toLocationId: zod.z.string().min(1),
|
|
@@ -36998,13 +37077,15 @@ var require_dist_Keu5TDO7 = __commonJS({
|
|
|
36998
37077
|
groups: zod.z.array(AnalyticsGroupRecordSchema).readonly(),
|
|
36999
37078
|
nextCursor: zod.z.string().nullable()
|
|
37000
37079
|
});
|
|
37080
|
+
var KEY_EVENTS_DEFAULT_LIMIT = 50;
|
|
37081
|
+
var KEY_EVENTS_MAX_LIMIT = 200;
|
|
37001
37082
|
var KeyEventQueryInput = zod.z.object({
|
|
37002
37083
|
deviceId: zod.z.number(),
|
|
37003
37084
|
/** Window lower bound (track firstSeen ≥ since). */
|
|
37004
37085
|
since: zod.z.number(),
|
|
37005
37086
|
/** Window upper bound (track firstSeen ≤ until). */
|
|
37006
37087
|
until: zod.z.number(),
|
|
37007
|
-
limit: zod.z.number().int().min(1).max(
|
|
37088
|
+
limit: zod.z.number().int().min(1).max(KEY_EVENTS_MAX_LIMIT).default(KEY_EVENTS_DEFAULT_LIMIT),
|
|
37008
37089
|
/** Drop tracks scoring below this importance. */
|
|
37009
37090
|
minImportance: zod.z.number().min(0).max(1).optional(),
|
|
37010
37091
|
/** Restrict to a single class (e.g. 'person'). */
|
|
@@ -37026,6 +37107,21 @@ var require_dist_Keu5TDO7 = __commonJS({
|
|
|
37026
37107
|
...TrackFlagFields,
|
|
37027
37108
|
...TrackRetrainFields
|
|
37028
37109
|
});
|
|
37110
|
+
var KeyEventBatchQueryInput = zod.z.object({
|
|
37111
|
+
deviceIds: zod.z.array(zod.z.number()).min(1).max(200),
|
|
37112
|
+
since: zod.z.number(),
|
|
37113
|
+
until: zod.z.number(),
|
|
37114
|
+
/** Applied PER CAMERA, exactly as `getKeyEvents.limit` is — never a total
|
|
37115
|
+
* across the set, which would let a busy camera starve a quiet one of its
|
|
37116
|
+
* rows and change what the merged feed contains. */
|
|
37117
|
+
limit: zod.z.number().int().min(1).max(KEY_EVENTS_MAX_LIMIT).default(KEY_EVENTS_DEFAULT_LIMIT),
|
|
37118
|
+
minImportance: zod.z.number().min(0).max(1).optional(),
|
|
37119
|
+
classFilter: zod.z.string().optional()
|
|
37120
|
+
});
|
|
37121
|
+
var KeyEventsForDeviceSchema = zod.z.object({
|
|
37122
|
+
deviceId: zod.z.number(),
|
|
37123
|
+
events: zod.z.array(KeyEventSchema).readonly()
|
|
37124
|
+
});
|
|
37029
37125
|
zod.z.object({
|
|
37030
37126
|
trackId: zod.z.string(),
|
|
37031
37127
|
className: zod.z.string(),
|
|
@@ -37094,6 +37190,25 @@ var require_dist_Keu5TDO7 = __commonJS({
|
|
|
37094
37190
|
totalBytes: zod.z.number().int(),
|
|
37095
37191
|
devices: zod.z.array(EventStoreDeviceFootprintSchema).readonly()
|
|
37096
37192
|
});
|
|
37193
|
+
var EventMediaKindFootprintSchema = zod.z.object({
|
|
37194
|
+
kind: MediaFileKindEnum,
|
|
37195
|
+
/** Media rows of this kind. */
|
|
37196
|
+
rows: zod.z.number().int(),
|
|
37197
|
+
/** Bytes on disk held by those rows. */
|
|
37198
|
+
bytes: zod.z.number().int()
|
|
37199
|
+
});
|
|
37200
|
+
var EventMediaKindBreakdownSchema = zod.z.object({
|
|
37201
|
+
/** Every media row in scope, from one unfiltered aggregate. */
|
|
37202
|
+
totalRows: zod.z.number().int(),
|
|
37203
|
+
/** Every media byte in scope, from that same aggregate. */
|
|
37204
|
+
totalBytes: zod.z.number().int(),
|
|
37205
|
+
/** Per-kind footprint, ordered by bytes descending. */
|
|
37206
|
+
kinds: zod.z.array(EventMediaKindFootprintSchema).readonly(),
|
|
37207
|
+
/** `totalRows` minus the summed `kinds` rows — see the schema note. */
|
|
37208
|
+
unaccountedRows: zod.z.number().int(),
|
|
37209
|
+
/** `totalBytes` minus the summed `kinds` bytes — see the schema note. */
|
|
37210
|
+
unaccountedBytes: zod.z.number().int()
|
|
37211
|
+
});
|
|
37097
37212
|
var EventPruneCountsSchema = zod.z.object({
|
|
37098
37213
|
motion: zod.z.number().int(),
|
|
37099
37214
|
object: zod.z.number().int(),
|
|
@@ -37301,6 +37416,21 @@ var require_dist_Keu5TDO7 = __commonJS({
|
|
|
37301
37416
|
* scored on-read (no write). Degrades to `[]` on error.
|
|
37302
37417
|
*/
|
|
37303
37418
|
getKeyEvents: method(KeyEventQueryInput, zod.z.array(KeyEventSchema).readonly()),
|
|
37419
|
+
/**
|
|
37420
|
+
* The same ranking, for a SET of cameras, in one round trip.
|
|
37421
|
+
*
|
|
37422
|
+
* The Detection Intelligence events feed asks this of every selected
|
|
37423
|
+
* camera and re-asks on a 30s timer. Fanned out client-side that is N
|
|
37424
|
+
* round trips — browser → hub → post-analysis — for N independent,
|
|
37425
|
+
* already-indexed store queries. Batched, the queries are unchanged and
|
|
37426
|
+
* run concurrently INSIDE the owner; only the transport collapses.
|
|
37427
|
+
*
|
|
37428
|
+
* Deliberately per-device rather than pre-merged: `limit` stays per
|
|
37429
|
+
* camera (a total would let a busy camera starve a quiet one), and a
|
|
37430
|
+
* caller that renders one camera's lane needs to know which camera a row
|
|
37431
|
+
* came from. `getKeyEvents` stays for single-device callers.
|
|
37432
|
+
*/
|
|
37433
|
+
getKeyEventsBatch: method(KeyEventBatchQueryInput, zod.z.array(KeyEventsForDeviceSchema).readonly()),
|
|
37304
37434
|
/** Server-side bucketed event counts for the 24-hour timeline.
|
|
37305
37435
|
* Returns one entry per non-empty bucket; empty buckets are omitted. */
|
|
37306
37436
|
getEventDensity: method(zod.z.object({
|
|
@@ -37449,6 +37579,22 @@ var require_dist_Keu5TDO7 = __commonJS({
|
|
|
37449
37579
|
auth: "admin"
|
|
37450
37580
|
}),
|
|
37451
37581
|
/**
|
|
37582
|
+
* The same media footprint, broken down by {@link MediaFileKind} instead of
|
|
37583
|
+
* by camera — fleet-wide, or for one camera with `deviceId`.
|
|
37584
|
+
*
|
|
37585
|
+
* Separate from {@link getEventStoreFootprint} rather than a field on it:
|
|
37586
|
+
* the two answer different questions on different axes, the per-camera one
|
|
37587
|
+
* is what the management table renders on every open, and nothing should
|
|
37588
|
+
* pay for a per-kind pass to draw it. See
|
|
37589
|
+
* {@link EventMediaKindBreakdownSchema} for why `unaccounted*` exists —
|
|
37590
|
+
* `kinds` is enumerated, `totalBytes` is not, and the gap must be visible
|
|
37591
|
+
* to anyone sizing a deletion against it.
|
|
37592
|
+
*/
|
|
37593
|
+
getEventMediaFootprintByKind: method(zod.z.object({ deviceId: zod.z.number().int().optional() }), EventMediaKindBreakdownSchema, {
|
|
37594
|
+
kind: "query",
|
|
37595
|
+
auth: "admin"
|
|
37596
|
+
}),
|
|
37597
|
+
/**
|
|
37452
37598
|
* Cluster-wide prune of events older than `olderThanMs` (exclusive) across
|
|
37453
37599
|
* every camera, deleting each event's media in lockstep. Logged to the
|
|
37454
37600
|
* events ops-log with `reason` (default `'retention'`). Returns the summed
|
|
@@ -40047,6 +40193,20 @@ var require_dist_Keu5TDO7 = __commonJS({
|
|
|
40047
40193
|
listProviders: method(zod.z.void(), zod.z.array(ProviderListEntrySchema).readonly()),
|
|
40048
40194
|
testConfig: method(zod.z.object({
|
|
40049
40195
|
providerId: zod.z.string(),
|
|
40196
|
+
/**
|
|
40197
|
+
* The location this config is an UNSAVED edit of, when there is one.
|
|
40198
|
+
*
|
|
40199
|
+
* `listLocations` replaces every declared secret with the redaction
|
|
40200
|
+
* sentinel, so the edit modal's form state holds the sentinel for any
|
|
40201
|
+
* credential the operator did not retype — and posting that here
|
|
40202
|
+
* without a way to resolve it makes the provider try to authenticate
|
|
40203
|
+
* as `__camstack_redacted__` and report the operator's own working
|
|
40204
|
+
* password as wrong. Given this id, the orchestrator restores each
|
|
40205
|
+
* sentinel from the stored config (same rule as `upsertLocation`)
|
|
40206
|
+
* before dispatching. Omitted by the "Add location" wizard, where
|
|
40207
|
+
* every value was typed just now and nothing is stored yet.
|
|
40208
|
+
*/
|
|
40209
|
+
locationId: zod.z.string().optional(),
|
|
40050
40210
|
config: zod.z.record(zod.z.string(), zod.z.unknown())
|
|
40051
40211
|
}), zod.z.object({
|
|
40052
40212
|
ok: zod.z.boolean(),
|
|
@@ -47215,6 +47375,23 @@ var require_dist_Keu5TDO7 = __commonJS({
|
|
|
47215
47375
|
kind: "query",
|
|
47216
47376
|
auth: "admin"
|
|
47217
47377
|
}),
|
|
47378
|
+
/**
|
|
47379
|
+
* Does this location's LEDGER tell the truth about its disk? (D319)
|
|
47380
|
+
*
|
|
47381
|
+
* One `readdir` per claimed hour, diffed both ways: durable rows whose file
|
|
47382
|
+
* is not there, and files no durable row names. `apply` defaults to FALSE —
|
|
47383
|
+
* the report is the product, and the dry run is how an operator
|
|
47384
|
+
* sanity-checks the destructive run before authorising it.
|
|
47385
|
+
*
|
|
47386
|
+
* REFUSES a source that is still a write target: a listing of a live
|
|
47387
|
+
* location is a lower bound, which is not the strong evidence that lets
|
|
47388
|
+
* this pass forget without a budget. A live location is reconciled by the
|
|
47389
|
+
* mover, under D318's bound.
|
|
47390
|
+
*/
|
|
47391
|
+
reconcileLedgerAgainstDisk: method(LedgerWalkInputSchema, LedgerWalkReportSchema, {
|
|
47392
|
+
kind: "mutation",
|
|
47393
|
+
auth: "admin"
|
|
47394
|
+
}),
|
|
47218
47395
|
/** Cancel a running or queued relocate job. A queued job never runs. */
|
|
47219
47396
|
cancelRelocateJob: method(zod.z.object({ jobId: zod.z.string() }), zod.z.object({ cancelled: zod.z.boolean() }), {
|
|
47220
47397
|
kind: "mutation",
|
|
@@ -47512,6 +47689,10 @@ var require_dist_Keu5TDO7 = __commonJS({
|
|
|
47512
47689
|
monitors: zod.z.array(SceneMonitorSchema),
|
|
47513
47690
|
lastFetchedAt: zod.z.number()
|
|
47514
47691
|
});
|
|
47692
|
+
var SceneMonitorStatusForDeviceSchema = zod.z.object({
|
|
47693
|
+
deviceId: zod.z.number(),
|
|
47694
|
+
status: SceneMonitorStatusSchema.nullable()
|
|
47695
|
+
});
|
|
47515
47696
|
var sceneMonitorCapability = {
|
|
47516
47697
|
name: "scene-monitor",
|
|
47517
47698
|
scope: "device",
|
|
@@ -47521,6 +47702,22 @@ var require_dist_Keu5TDO7 = __commonJS({
|
|
|
47521
47702
|
deviceTypes: [DeviceType.Camera],
|
|
47522
47703
|
methods: {
|
|
47523
47704
|
listScenes: method(zod.z.object({ deviceId: zod.z.number() }), SceneMonitorStatusSchema),
|
|
47705
|
+
/**
|
|
47706
|
+
* The same answer, for a SET of cameras, in one round trip.
|
|
47707
|
+
*
|
|
47708
|
+
* `/scenes` renders every camera and re-reads them on a 30s safety-net
|
|
47709
|
+
* poll behind the push slice. Fanned out client-side that was one query
|
|
47710
|
+
* per camera — 29 round trips through the browser, the hub and the
|
|
47711
|
+
* post-analysis runner every 30 seconds to read an in-memory map the
|
|
47712
|
+
* owner had already merged. The work is unchanged (`statusFor` per
|
|
47713
|
+
* device, all in-process at the owner); what collapses is the transport.
|
|
47714
|
+
*
|
|
47715
|
+
* A camera that cannot answer still gets a row, with `status: null` —
|
|
47716
|
+
* see {@link SceneMonitorStatusForDeviceSchema}. Never fewer rows than
|
|
47717
|
+
* ids: a caller that asked for twenty-nine and got twenty-seven cannot
|
|
47718
|
+
* tell which two are missing, or that any are.
|
|
47719
|
+
*/
|
|
47720
|
+
listScenesBatch: method(zod.z.object({ deviceIds: zod.z.array(zod.z.number()).min(1).max(200) }), zod.z.array(SceneMonitorStatusForDeviceSchema).readonly()),
|
|
47524
47721
|
createScene: method(zod.z.object({
|
|
47525
47722
|
deviceId: zod.z.number(),
|
|
47526
47723
|
label: zod.z.string(),
|
|
@@ -49321,6 +49518,11 @@ var require_dist_Keu5TDO7 = __commonJS({
|
|
|
49321
49518
|
* than as repeated tracks/events. */
|
|
49322
49519
|
stationaryObjects: zod.z.array(StationaryObjectSchema).readonly().optional()
|
|
49323
49520
|
});
|
|
49521
|
+
var CameraOccupancySnapshotForDeviceSchema = zod.z.object({
|
|
49522
|
+
deviceId: zod.z.number(),
|
|
49523
|
+
read: zod.z.enum(["read", "unreadable"]),
|
|
49524
|
+
snapshot: CameraOccupancySnapshotSchema.nullable()
|
|
49525
|
+
});
|
|
49324
49526
|
var HistoryResolutionEnum = zod.z.enum([
|
|
49325
49527
|
"minute",
|
|
49326
49528
|
"5min",
|
|
@@ -49350,6 +49552,20 @@ var require_dist_Keu5TDO7 = __commonJS({
|
|
|
49350
49552
|
* (no inference result emitted since boot or since binding was
|
|
49351
49553
|
* activated). */
|
|
49352
49554
|
getCurrentSnapshot: method(zod.z.object({ deviceId: zod.z.number() }), CameraOccupancySnapshotSchema.nullable()),
|
|
49555
|
+
/**
|
|
49556
|
+
* The same snapshot, for a SET of cameras, in one round trip.
|
|
49557
|
+
*
|
|
49558
|
+
* The Events page's Stationary section polls this every 15s for every
|
|
49559
|
+
* selected camera. Fanned out client-side that is one query per camera to
|
|
49560
|
+
* read a `Map.get` at the owner — the answer costs nothing, the round trip
|
|
49561
|
+
* costs everything. Batched, N transports become one and the per-device
|
|
49562
|
+
* work is unchanged.
|
|
49563
|
+
*
|
|
49564
|
+
* Every requested deviceId gets a row, tagged `read` — see
|
|
49565
|
+
* {@link CameraOccupancySnapshotForDeviceSchema}. A camera the owner could
|
|
49566
|
+
* not answer for is `'unreadable'`, never an empty reading.
|
|
49567
|
+
*/
|
|
49568
|
+
getCurrentSnapshotBatch: method(zod.z.object({ deviceIds: zod.z.array(zod.z.number()).min(1).max(200) }), zod.z.array(CameraOccupancySnapshotForDeviceSchema).readonly()),
|
|
49353
49569
|
/** Time-series object count inside one zone. `className` optional —
|
|
49354
49570
|
* omit to count every class in the zone. */
|
|
49355
49571
|
getZoneHistory: method(zod.z.object({
|
|
@@ -53273,6 +53489,12 @@ var require_dist_Keu5TDO7 = __commonJS({
|
|
|
53273
53489
|
addonId: null,
|
|
53274
53490
|
access: "view"
|
|
53275
53491
|
},
|
|
53492
|
+
"pipelineAnalytics.getEventMediaFootprintByKind": {
|
|
53493
|
+
capName: "pipeline-analytics",
|
|
53494
|
+
capScope: "device",
|
|
53495
|
+
addonId: null,
|
|
53496
|
+
access: "view"
|
|
53497
|
+
},
|
|
53276
53498
|
"pipelineAnalytics.getEventStoreFootprint": {
|
|
53277
53499
|
capName: "pipeline-analytics",
|
|
53278
53500
|
capScope: "device",
|
|
@@ -53291,6 +53513,12 @@ var require_dist_Keu5TDO7 = __commonJS({
|
|
|
53291
53513
|
addonId: null,
|
|
53292
53514
|
access: "view"
|
|
53293
53515
|
},
|
|
53516
|
+
"pipelineAnalytics.getKeyEventsBatch": {
|
|
53517
|
+
capName: "pipeline-analytics",
|
|
53518
|
+
capScope: "device",
|
|
53519
|
+
addonId: null,
|
|
53520
|
+
access: "view"
|
|
53521
|
+
},
|
|
53294
53522
|
"pipelineAnalytics.getMotionEvents": {
|
|
53295
53523
|
capName: "pipeline-analytics",
|
|
53296
53524
|
capScope: "device",
|
|
@@ -54467,6 +54695,12 @@ var require_dist_Keu5TDO7 = __commonJS({
|
|
|
54467
54695
|
addonId: null,
|
|
54468
54696
|
access: "view"
|
|
54469
54697
|
},
|
|
54698
|
+
"recording.reconcileLedgerAgainstDisk": {
|
|
54699
|
+
capName: "recording",
|
|
54700
|
+
capScope: "system",
|
|
54701
|
+
addonId: null,
|
|
54702
|
+
access: "create"
|
|
54703
|
+
},
|
|
54470
54704
|
"recording.refreshStorageLocationsForMigration": {
|
|
54471
54705
|
capName: "recording",
|
|
54472
54706
|
capScope: "system",
|
|
@@ -54593,6 +54827,12 @@ var require_dist_Keu5TDO7 = __commonJS({
|
|
|
54593
54827
|
addonId: null,
|
|
54594
54828
|
access: "view"
|
|
54595
54829
|
},
|
|
54830
|
+
"sceneMonitor.listScenesBatch": {
|
|
54831
|
+
capName: "scene-monitor",
|
|
54832
|
+
capScope: "device",
|
|
54833
|
+
addonId: null,
|
|
54834
|
+
access: "view"
|
|
54835
|
+
},
|
|
54596
54836
|
"sceneMonitor.recheckNow": {
|
|
54597
54837
|
capName: "scene-monitor",
|
|
54598
54838
|
capScope: "device",
|
|
@@ -55949,6 +56189,12 @@ var require_dist_Keu5TDO7 = __commonJS({
|
|
|
55949
56189
|
addonId: null,
|
|
55950
56190
|
access: "view"
|
|
55951
56191
|
},
|
|
56192
|
+
"zoneAnalytics.getCurrentSnapshotBatch": {
|
|
56193
|
+
capName: "zone-analytics",
|
|
56194
|
+
capScope: "device",
|
|
56195
|
+
addonId: null,
|
|
56196
|
+
access: "view"
|
|
56197
|
+
},
|
|
55952
56198
|
"zoneAnalytics.getUnzonedHistory": {
|
|
55953
56199
|
capName: "zone-analytics",
|
|
55954
56200
|
capScope: "device",
|
|
@@ -56938,6 +57184,11 @@ var require_dist_Keu5TDO7 = __commonJS({
|
|
|
56938
57184
|
form: "single",
|
|
56939
57185
|
optional: false
|
|
56940
57186
|
}],
|
|
57187
|
+
"pipelineAnalytics.getEventMediaFootprintByKind": [{
|
|
57188
|
+
name: "deviceId",
|
|
57189
|
+
form: "single",
|
|
57190
|
+
optional: true
|
|
57191
|
+
}],
|
|
56941
57192
|
"pipelineAnalytics.getGroup": [{
|
|
56942
57193
|
name: "deviceId",
|
|
56943
57194
|
form: "single",
|
|
@@ -56948,6 +57199,11 @@ var require_dist_Keu5TDO7 = __commonJS({
|
|
|
56948
57199
|
form: "single",
|
|
56949
57200
|
optional: false
|
|
56950
57201
|
}],
|
|
57202
|
+
"pipelineAnalytics.getKeyEventsBatch": [{
|
|
57203
|
+
name: "deviceIds",
|
|
57204
|
+
form: "array",
|
|
57205
|
+
optional: false
|
|
57206
|
+
}],
|
|
56951
57207
|
"pipelineAnalytics.getMotionEvents": [{
|
|
56952
57208
|
name: "deviceId",
|
|
56953
57209
|
form: "single",
|
|
@@ -57388,6 +57644,11 @@ var require_dist_Keu5TDO7 = __commonJS({
|
|
|
57388
57644
|
form: "single",
|
|
57389
57645
|
optional: false
|
|
57390
57646
|
}],
|
|
57647
|
+
"recording.reconcileLedgerAgainstDisk": [{
|
|
57648
|
+
name: "deviceId",
|
|
57649
|
+
form: "single",
|
|
57650
|
+
optional: true
|
|
57651
|
+
}],
|
|
57391
57652
|
"recording.relocateFootage": [{
|
|
57392
57653
|
name: "deviceId",
|
|
57393
57654
|
form: "single",
|
|
@@ -57453,6 +57714,11 @@ var require_dist_Keu5TDO7 = __commonJS({
|
|
|
57453
57714
|
form: "single",
|
|
57454
57715
|
optional: false
|
|
57455
57716
|
}],
|
|
57717
|
+
"sceneMonitor.listScenesBatch": [{
|
|
57718
|
+
name: "deviceIds",
|
|
57719
|
+
form: "array",
|
|
57720
|
+
optional: false
|
|
57721
|
+
}],
|
|
57456
57722
|
"sceneMonitor.recheckNow": [{
|
|
57457
57723
|
name: "deviceId",
|
|
57458
57724
|
form: "single",
|
|
@@ -57714,6 +57980,11 @@ var require_dist_Keu5TDO7 = __commonJS({
|
|
|
57714
57980
|
form: "single",
|
|
57715
57981
|
optional: false
|
|
57716
57982
|
}],
|
|
57983
|
+
"zoneAnalytics.getCurrentSnapshotBatch": [{
|
|
57984
|
+
name: "deviceIds",
|
|
57985
|
+
form: "array",
|
|
57986
|
+
optional: false
|
|
57987
|
+
}],
|
|
57717
57988
|
"zoneAnalytics.getUnzonedHistory": [{
|
|
57718
57989
|
name: "deviceId",
|
|
57719
57990
|
form: "single",
|
|
@@ -59147,7 +59418,7 @@ var require_alerts_addon = __commonJS({
|
|
|
59147
59418
|
[Symbol.toStringTag]: { value: "Module" }
|
|
59148
59419
|
});
|
|
59149
59420
|
require_chunk_Cek0wNdY();
|
|
59150
|
-
var require_dist10 =
|
|
59421
|
+
var require_dist10 = require_dist_B29Skpzo();
|
|
59151
59422
|
function selectExpired(alerts, cutoffMs) {
|
|
59152
59423
|
return alerts.filter((a) => a.createdAt < cutoffMs).sort((a, b) => a.createdAt - b.createdAt).map((a) => a.id);
|
|
59153
59424
|
}
|
|
@@ -59966,7 +60237,7 @@ var require_console_logging = __commonJS({
|
|
|
59966
60237
|
[Symbol.toStringTag]: { value: "Module" }
|
|
59967
60238
|
});
|
|
59968
60239
|
require_chunk_Cek0wNdY();
|
|
59969
|
-
var require_dist10 =
|
|
60240
|
+
var require_dist10 = require_dist_B29Skpzo();
|
|
59970
60241
|
var require_formatter = require_formatter_DqAKDlvN();
|
|
59971
60242
|
var LEVEL_RANK = {
|
|
59972
60243
|
debug: 0,
|
|
@@ -60060,7 +60331,7 @@ var require_core_blocks_addon = __commonJS({
|
|
|
60060
60331
|
"use strict";
|
|
60061
60332
|
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
60062
60333
|
var require_chunk = require_chunk_Cek0wNdY();
|
|
60063
|
-
var require_dist10 =
|
|
60334
|
+
var require_dist10 = require_dist_B29Skpzo();
|
|
60064
60335
|
var node_crypto = __require("crypto");
|
|
60065
60336
|
var node_fs_promises = __require("fs/promises");
|
|
60066
60337
|
node_fs_promises = require_chunk.__toESM(node_fs_promises);
|
|
@@ -60957,11 +61228,11 @@ var require_core_blocks = __commonJS({
|
|
|
60957
61228
|
}
|
|
60958
61229
|
});
|
|
60959
61230
|
|
|
60960
|
-
// ../system/dist/retired-settings-keys-
|
|
60961
|
-
var
|
|
60962
|
-
"../system/dist/retired-settings-keys-
|
|
61231
|
+
// ../system/dist/retired-settings-keys-CRL0qOnU.js
|
|
61232
|
+
var require_retired_settings_keys_CRL0qOnU = __commonJS({
|
|
61233
|
+
"../system/dist/retired-settings-keys-CRL0qOnU.js"(exports) {
|
|
60963
61234
|
"use strict";
|
|
60964
|
-
var require_dist10 =
|
|
61235
|
+
var require_dist10 = require_dist_B29Skpzo();
|
|
60965
61236
|
function settingsStoreIsAuthoritativeHere(env) {
|
|
60966
61237
|
const raw = (env["CAMSTACK_ROLE"] ?? "").trim().toLowerCase();
|
|
60967
61238
|
return raw === "" || raw === "hub";
|
|
@@ -63175,8 +63446,8 @@ var require_device_manager_addon = __commonJS({
|
|
|
63175
63446
|
[Symbol.toStringTag]: { value: "Module" }
|
|
63176
63447
|
});
|
|
63177
63448
|
require_chunk_Cek0wNdY();
|
|
63178
|
-
var require_dist10 =
|
|
63179
|
-
var require_retired_settings_keys =
|
|
63449
|
+
var require_dist10 = require_dist_B29Skpzo();
|
|
63450
|
+
var require_retired_settings_keys = require_retired_settings_keys_CRL0qOnU();
|
|
63180
63451
|
var node_crypto = __require("crypto");
|
|
63181
63452
|
var _camstack_types_node = require_node();
|
|
63182
63453
|
var JOB_HISTORY = 20;
|
|
@@ -67989,7 +68260,7 @@ var require_hub_forwarder = __commonJS({
|
|
|
67989
68260
|
[Symbol.toStringTag]: { value: "Module" }
|
|
67990
68261
|
});
|
|
67991
68262
|
require_chunk_Cek0wNdY();
|
|
67992
|
-
var require_dist10 =
|
|
68263
|
+
var require_dist10 = require_dist_B29Skpzo();
|
|
67993
68264
|
var require_formatter = require_formatter_DqAKDlvN();
|
|
67994
68265
|
var DEFAULT_OUTBOUND_BUFFER_SIZE = 500;
|
|
67995
68266
|
var HubForwarderDestination = class {
|
|
@@ -68126,7 +68397,7 @@ var require_liveness_monitor_addon = __commonJS({
|
|
|
68126
68397
|
"use strict";
|
|
68127
68398
|
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
68128
68399
|
require_chunk_Cek0wNdY();
|
|
68129
|
-
var require_dist10 =
|
|
68400
|
+
var require_dist10 = require_dist_B29Skpzo();
|
|
68130
68401
|
var NO_DEVICES = "liveness:no-devices";
|
|
68131
68402
|
var ALL_OFFLINE = "liveness:all-devices-offline";
|
|
68132
68403
|
var NO_FOOTAGE_PREFIX = "liveness:no-footage:";
|
|
@@ -68316,7 +68587,7 @@ var require_local_auth_addon = __commonJS({
|
|
|
68316
68587
|
[Symbol.toStringTag]: { value: "Module" }
|
|
68317
68588
|
});
|
|
68318
68589
|
var require_chunk = require_chunk_Cek0wNdY();
|
|
68319
|
-
var require_dist10 =
|
|
68590
|
+
var require_dist10 = require_dist_B29Skpzo();
|
|
68320
68591
|
var node_crypto = __require("crypto");
|
|
68321
68592
|
node_crypto = require_chunk.__toESM(node_crypto);
|
|
68322
68593
|
var crypto$1 = __require("crypto");
|
|
@@ -76129,7 +76400,7 @@ var require_loki_logging = __commonJS({
|
|
|
76129
76400
|
[Symbol.toStringTag]: { value: "Module" }
|
|
76130
76401
|
});
|
|
76131
76402
|
require_chunk_Cek0wNdY();
|
|
76132
|
-
var require_dist10 =
|
|
76403
|
+
var require_dist10 = require_dist_B29Skpzo();
|
|
76133
76404
|
function sanitizeLabelName(raw) {
|
|
76134
76405
|
const replaced = raw.replaceAll(/[^a-zA-Z0-9_]/g, "_");
|
|
76135
76406
|
return /^[a-zA-Z_]/.test(replaced) ? replaced : `_${replaced}`;
|
|
@@ -76694,7 +76965,7 @@ var require_native_metrics_addon = __commonJS({
|
|
|
76694
76965
|
[Symbol.toStringTag]: { value: "Module" }
|
|
76695
76966
|
});
|
|
76696
76967
|
var require_chunk = require_chunk_Cek0wNdY();
|
|
76697
|
-
var require_dist10 =
|
|
76968
|
+
var require_dist10 = require_dist_B29Skpzo();
|
|
76698
76969
|
var node_fs_promises = __require("fs/promises");
|
|
76699
76970
|
var node_child_process = __require("child_process");
|
|
76700
76971
|
var node_util = __require("util");
|
|
@@ -79316,7 +79587,7 @@ var require_filesystem_storage_addon = __commonJS({
|
|
|
79316
79587
|
[Symbol.toStringTag]: { value: "Module" }
|
|
79317
79588
|
});
|
|
79318
79589
|
var require_chunk = require_chunk_Cek0wNdY();
|
|
79319
|
-
var require_dist10 =
|
|
79590
|
+
var require_dist10 = require_dist_B29Skpzo();
|
|
79320
79591
|
var node_crypto = __require("crypto");
|
|
79321
79592
|
var node_fs_promises = __require("fs/promises");
|
|
79322
79593
|
var node_path = __require("path");
|
|
@@ -80432,8 +80703,8 @@ var require_sqlite_settings_addon = __commonJS({
|
|
|
80432
80703
|
[Symbol.toStringTag]: { value: "Module" }
|
|
80433
80704
|
});
|
|
80434
80705
|
var require_chunk = require_chunk_Cek0wNdY();
|
|
80435
|
-
var require_dist10 =
|
|
80436
|
-
var require_retired_settings_keys =
|
|
80706
|
+
var require_dist10 = require_dist_B29Skpzo();
|
|
80707
|
+
var require_retired_settings_keys = require_retired_settings_keys_CRL0qOnU();
|
|
80437
80708
|
var node_crypto = __require("crypto");
|
|
80438
80709
|
var node_fs = __require("fs");
|
|
80439
80710
|
var node_module = __require("module");
|
|
@@ -82812,7 +83083,7 @@ var require_storage_orchestrator_addon = __commonJS({
|
|
|
82812
83083
|
[Symbol.toStringTag]: { value: "Module" }
|
|
82813
83084
|
});
|
|
82814
83085
|
var require_chunk = require_chunk_Cek0wNdY();
|
|
82815
|
-
var require_dist10 =
|
|
83086
|
+
var require_dist10 = require_dist_B29Skpzo();
|
|
82816
83087
|
var node_crypto = __require("crypto");
|
|
82817
83088
|
var node_fs_promises = __require("fs/promises");
|
|
82818
83089
|
node_fs_promises = require_chunk.__toESM(node_fs_promises);
|
|
@@ -83795,10 +84066,21 @@ var require_storage_orchestrator_addon = __commonJS({
|
|
|
83795
84066
|
declareCollection: async (input) => (await engine()).declareCollection(input)
|
|
83796
84067
|
};
|
|
83797
84068
|
}
|
|
83798
|
-
var
|
|
84069
|
+
var FRAMEWORK_CONFIG_KEYS = /* @__PURE__ */ new Set([
|
|
84070
|
+
"basePath",
|
|
84071
|
+
"readOnly",
|
|
84072
|
+
"maxUsedGb",
|
|
84073
|
+
"minFreePercent"
|
|
84074
|
+
]);
|
|
83799
84075
|
function secretKeysOfProviderInfo(info) {
|
|
83800
84076
|
return require_dist10.collectSecretConfigKeys(info.configSchema);
|
|
83801
84077
|
}
|
|
84078
|
+
function secretKeysForConfig(config, declared) {
|
|
84079
|
+
if (declared !== void 0) return declared;
|
|
84080
|
+
const out = /* @__PURE__ */ new Set();
|
|
84081
|
+
for (const key of Object.keys(config)) if (!FRAMEWORK_CONFIG_KEYS.has(key)) out.add(key);
|
|
84082
|
+
return out;
|
|
84083
|
+
}
|
|
83802
84084
|
function redactLocationConfig(config, secretKeys) {
|
|
83803
84085
|
if (secretKeys.size === 0) return config;
|
|
83804
84086
|
let touched = false;
|
|
@@ -84784,7 +85066,7 @@ var require_storage_orchestrator_addon = __commonJS({
|
|
|
84784
85066
|
listLocationDeclarations: async () => service.listDeclarations(),
|
|
84785
85067
|
upsertLocation: async (input) => {
|
|
84786
85068
|
const stored = service.getLocationById(input.id);
|
|
84787
|
-
const config = restoreRedactedSecrets(input.config, stored?.config, this.secretKeysFor(input.providerId));
|
|
85069
|
+
const config = restoreRedactedSecrets(input.config, stored?.config, this.secretKeysFor(input.providerId, stored?.config ?? {}));
|
|
84788
85070
|
const saved = service.upsertLocation(config === input.config ? input : {
|
|
84789
85071
|
...input,
|
|
84790
85072
|
config
|
|
@@ -84817,11 +85099,14 @@ var require_storage_orchestrator_addon = __commonJS({
|
|
|
84817
85099
|
} });
|
|
84818
85100
|
});
|
|
84819
85101
|
},
|
|
84820
|
-
testConfig: async ({ providerId, config }) => {
|
|
85102
|
+
testConfig: async ({ providerId, locationId, config }) => {
|
|
85103
|
+
const stored = locationId === void 0 ? void 0 : service.getLocationById(locationId);
|
|
85104
|
+
const base = stored?.providerId === providerId ? stored.config : void 0;
|
|
85105
|
+
const resolved = restoreRedactedSecrets(config, base, this.secretKeysFor(providerId, base ?? {}));
|
|
84821
85106
|
const providers = getProviders();
|
|
84822
85107
|
for (const p of providers) try {
|
|
84823
85108
|
if ((await p.getProviderInfo()).providerId !== providerId) continue;
|
|
84824
|
-
return p.testLocation({ config });
|
|
85109
|
+
return p.testLocation({ config: resolved });
|
|
84825
85110
|
} catch (err) {
|
|
84826
85111
|
return {
|
|
84827
85112
|
ok: false,
|
|
@@ -85141,13 +85426,21 @@ var require_storage_orchestrator_addon = __commonJS({
|
|
|
85141
85426
|
}
|
|
85142
85427
|
return out;
|
|
85143
85428
|
}
|
|
85144
|
-
/**
|
|
85145
|
-
|
|
85146
|
-
|
|
85429
|
+
/**
|
|
85430
|
+
* What the provider's own schema declared secret, or `undefined` when this
|
|
85431
|
+
* node has never heard from that provider. The distinction is the whole
|
|
85432
|
+
* point — see `secretKeysForConfig`, which fails CLOSED on `undefined`.
|
|
85433
|
+
*/
|
|
85434
|
+
declaredSecretKeys(providerId) {
|
|
85435
|
+
return this.secretKeysByProvider.get(providerId);
|
|
85436
|
+
}
|
|
85437
|
+
/** Which keys of a given stored config must never leave this process. */
|
|
85438
|
+
secretKeysFor(providerId, config) {
|
|
85439
|
+
return secretKeysForConfig(config, this.declaredSecretKeys(providerId));
|
|
85147
85440
|
}
|
|
85148
85441
|
/** A location with its provider's declared secrets replaced by the sentinel. */
|
|
85149
85442
|
redacted(location) {
|
|
85150
|
-
return redactLocation(location, this.secretKeysFor(location.providerId));
|
|
85443
|
+
return redactLocation(location, this.secretKeysFor(location.providerId, location.config));
|
|
85151
85444
|
}
|
|
85152
85445
|
/**
|
|
85153
85446
|
* Is this location backed by a provider that serves a genuine local
|
|
@@ -85387,7 +85680,7 @@ var require_system_config_addon = __commonJS({
|
|
|
85387
85680
|
[Symbol.toStringTag]: { value: "Module" }
|
|
85388
85681
|
});
|
|
85389
85682
|
require_chunk_Cek0wNdY();
|
|
85390
|
-
var require_dist10 =
|
|
85683
|
+
var require_dist10 = require_dist_B29Skpzo();
|
|
85391
85684
|
var SECTION_TITLES = {
|
|
85392
85685
|
server: "Server",
|
|
85393
85686
|
auth: "Authentication"
|
|
@@ -103448,7 +103741,7 @@ var require_winston_logging = __commonJS({
|
|
|
103448
103741
|
[Symbol.toStringTag]: { value: "Module" }
|
|
103449
103742
|
});
|
|
103450
103743
|
var require_chunk = require_chunk_Cek0wNdY();
|
|
103451
|
-
var require_dist10 =
|
|
103744
|
+
var require_dist10 = require_dist_B29Skpzo();
|
|
103452
103745
|
var require_formatter = require_formatter_DqAKDlvN();
|
|
103453
103746
|
var node_path = __require("path");
|
|
103454
103747
|
node_path = require_chunk.__toESM(node_path);
|
|
@@ -105391,9 +105684,9 @@ var require_event_category_BaEgqJNv = __commonJS({
|
|
|
105391
105684
|
}
|
|
105392
105685
|
});
|
|
105393
105686
|
|
|
105394
|
-
// ../types/dist/sleep-
|
|
105395
|
-
var
|
|
105396
|
-
"../types/dist/sleep-
|
|
105687
|
+
// ../types/dist/sleep-DIg3xuEw.js
|
|
105688
|
+
var require_sleep_DIg3xuEw = __commonJS({
|
|
105689
|
+
"../types/dist/sleep-DIg3xuEw.js"(exports) {
|
|
105397
105690
|
"use strict";
|
|
105398
105691
|
var require_event_category = require_event_category_BaEgqJNv();
|
|
105399
105692
|
var zod = require_zod();
|
|
@@ -108076,6 +108369,7 @@ var require_sleep_C3AniWy = __commonJS({
|
|
|
108076
108369
|
listEventKindsBatch: (input) => dispatch("pipeline-analytics", "pipelineAnalytics", "listEventKindsBatch", "query", input),
|
|
108077
108370
|
getSensorEvents: (input) => dispatch("pipeline-analytics", "pipelineAnalytics", "getSensorEvents", "query", input),
|
|
108078
108371
|
getKeyEvents: (input) => dispatch("pipeline-analytics", "pipelineAnalytics", "getKeyEvents", "query", input),
|
|
108372
|
+
getKeyEventsBatch: (input) => dispatch("pipeline-analytics", "pipelineAnalytics", "getKeyEventsBatch", "query", input),
|
|
108079
108373
|
getEventDensity: (input) => dispatch("pipeline-analytics", "pipelineAnalytics", "getEventDensity", "query", input),
|
|
108080
108374
|
pruneEventsBefore: (input) => dispatch("pipeline-analytics", "pipelineAnalytics", "pruneEventsBefore", "mutation", input),
|
|
108081
108375
|
pruneTracksBefore: (input) => dispatch("pipeline-analytics", "pipelineAnalytics", "pruneTracksBefore", "mutation", input),
|
|
@@ -108084,6 +108378,7 @@ var require_sleep_C3AniWy = __commonJS({
|
|
|
108084
108378
|
deleteTracks: (input) => dispatch("pipeline-analytics", "pipelineAnalytics", "deleteTracks", "mutation", input),
|
|
108085
108379
|
setTrackFlags: (input) => dispatch("pipeline-analytics", "pipelineAnalytics", "setTrackFlags", "mutation", input),
|
|
108086
108380
|
getEventStoreFootprint: (input) => dispatch("pipeline-analytics", "pipelineAnalytics", "getEventStoreFootprint", "query", input),
|
|
108381
|
+
getEventMediaFootprintByKind: (input) => dispatch("pipeline-analytics", "pipelineAnalytics", "getEventMediaFootprintByKind", "query", input),
|
|
108087
108382
|
pruneEvents: (input) => dispatch("pipeline-analytics", "pipelineAnalytics", "pruneEvents", "mutation", input),
|
|
108088
108383
|
deleteDeviceEvents: (input) => dispatch("pipeline-analytics", "pipelineAnalytics", "deleteDeviceEvents", "mutation", input),
|
|
108089
108384
|
pauseForStorageMigration: (input) => dispatch("pipeline-analytics", "pipelineAnalytics", "pauseForStorageMigration", "mutation", input),
|
|
@@ -108156,6 +108451,7 @@ var require_sleep_C3AniWy = __commonJS({
|
|
|
108156
108451
|
reboot: { reboot: (input) => dispatch("reboot", "reboot", "reboot", "mutation", input) },
|
|
108157
108452
|
sceneMonitor: {
|
|
108158
108453
|
listScenes: (input) => dispatch("scene-monitor", "sceneMonitor", "listScenes", "query", input),
|
|
108454
|
+
listScenesBatch: (input) => dispatch("scene-monitor", "sceneMonitor", "listScenesBatch", "query", input),
|
|
108159
108455
|
createScene: (input) => dispatch("scene-monitor", "sceneMonitor", "createScene", "mutation", input),
|
|
108160
108456
|
updateScene: (input) => dispatch("scene-monitor", "sceneMonitor", "updateScene", "mutation", input),
|
|
108161
108457
|
deleteScene: (input) => dispatch("scene-monitor", "sceneMonitor", "deleteScene", "mutation", input),
|
|
@@ -108240,6 +108536,7 @@ var require_sleep_C3AniWy = __commonJS({
|
|
|
108240
108536
|
},
|
|
108241
108537
|
zoneAnalytics: {
|
|
108242
108538
|
getCurrentSnapshot: (input) => dispatch("zone-analytics", "zoneAnalytics", "getCurrentSnapshot", "query", input),
|
|
108539
|
+
getCurrentSnapshotBatch: (input) => dispatch("zone-analytics", "zoneAnalytics", "getCurrentSnapshotBatch", "query", input),
|
|
108243
108540
|
getZoneHistory: (input) => dispatch("zone-analytics", "zoneAnalytics", "getZoneHistory", "query", input),
|
|
108244
108541
|
getCameraHistory: (input) => dispatch("zone-analytics", "zoneAnalytics", "getCameraHistory", "query", input),
|
|
108245
108542
|
getUnzonedHistory: (input) => dispatch("zone-analytics", "zoneAnalytics", "getUnzonedHistory", "query", input)
|
|
@@ -109060,7 +109357,7 @@ var require_addon = __commonJS({
|
|
|
109060
109357
|
"use strict";
|
|
109061
109358
|
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
109062
109359
|
var require_event_category = require_event_category_BaEgqJNv();
|
|
109063
|
-
var require_sleep =
|
|
109360
|
+
var require_sleep = require_sleep_DIg3xuEw();
|
|
109064
109361
|
var require_err_msg = require_err_msg_COpsHMw2();
|
|
109065
109362
|
var CAP_INPUT_DEFAULTS = Object.freeze({
|
|
109066
109363
|
"addons": { "getLogs": { "limit": 100 } },
|
|
@@ -109170,6 +109467,7 @@ var require_addon = __commonJS({
|
|
|
109170
109467
|
"pipeline-analytics": {
|
|
109171
109468
|
"getAudioEvents": { "limit": 1e3 },
|
|
109172
109469
|
"getKeyEvents": { "limit": 50 },
|
|
109470
|
+
"getKeyEventsBatch": { "limit": 50 },
|
|
109173
109471
|
"getMotionEvents": { "limit": 1e3 },
|
|
109174
109472
|
"getObjectEvents": { "limit": 1e3 },
|
|
109175
109473
|
"getSensorEvents": { "limit": 1e3 },
|
|
@@ -115942,12 +116240,12 @@ var require_dist2 = __commonJS({
|
|
|
115942
116240
|
}
|
|
115943
116241
|
});
|
|
115944
116242
|
|
|
115945
|
-
// ../system/dist/manifest-system-deps-
|
|
115946
|
-
var
|
|
115947
|
-
"../system/dist/manifest-system-deps-
|
|
116243
|
+
// ../system/dist/manifest-system-deps-DBje540e.js
|
|
116244
|
+
var require_manifest_system_deps_DBje540e = __commonJS({
|
|
116245
|
+
"../system/dist/manifest-system-deps-DBje540e.js"(exports) {
|
|
115948
116246
|
"use strict";
|
|
115949
116247
|
var require_chunk = require_chunk_Cek0wNdY();
|
|
115950
|
-
|
|
116248
|
+
require_dist_B29Skpzo();
|
|
115951
116249
|
var node_crypto = __require("crypto");
|
|
115952
116250
|
node_crypto = require_chunk.__toESM(node_crypto);
|
|
115953
116251
|
var _camstack_types_node = require_node();
|
|
@@ -127976,7 +128274,7 @@ var require_dist3 = __commonJS({
|
|
|
127976
128274
|
"use strict";
|
|
127977
128275
|
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
127978
128276
|
var require_chunk = require_chunk_Cek0wNdY();
|
|
127979
|
-
var require_dist10 =
|
|
128277
|
+
var require_dist10 = require_dist_B29Skpzo();
|
|
127980
128278
|
var require_builtins_alerts_alerts_addon = require_alerts_addon();
|
|
127981
128279
|
require_alerts();
|
|
127982
128280
|
var require_formatter = require_formatter_DqAKDlvN();
|
|
@@ -128002,7 +128300,7 @@ var require_dist3 = __commonJS({
|
|
|
128002
128300
|
var require_builtins_winston_logging_index = require_winston_logging();
|
|
128003
128301
|
var require_file_data_plane = require_file_data_plane_DO8KbxCe();
|
|
128004
128302
|
var require_tls$1 = require_tls_BxQlomxd();
|
|
128005
|
-
var require_manifest_system_deps =
|
|
128303
|
+
var require_manifest_system_deps = require_manifest_system_deps_DBje540e();
|
|
128006
128304
|
var require_resource_monitor = require_resource_monitor_CdnzxBLP();
|
|
128007
128305
|
var require_custom_action_registry = require_custom_action_registry_jY0NOZK8();
|
|
128008
128306
|
var zod = require_zod();
|
|
@@ -133890,19 +134188,37 @@ var require_dist3 = __commonJS({
|
|
|
133890
134188
|
if (!isRecord$1(parsed) || !("value" in parsed)) return parsed;
|
|
133891
134189
|
return parsed.value;
|
|
133892
134190
|
}
|
|
134191
|
+
var PREFIX_PAGE_ROWS = 1e3;
|
|
134192
|
+
var PREFIX_PAGE_BUDGET = 512;
|
|
133893
134193
|
async function loadPrefixed(door, collection, prefix) {
|
|
133894
134194
|
const range = require_builtins_sqlite_storage_sqlite_settings_addon.prefixRange(prefix);
|
|
133895
|
-
const rows = await door.query({
|
|
133896
|
-
collection,
|
|
133897
|
-
...range !== null ? { filter: { whereBetween: { id: [range.lo, range.hi] } } } : {}
|
|
133898
|
-
});
|
|
133899
134195
|
const result = {};
|
|
133900
|
-
|
|
133901
|
-
|
|
133902
|
-
if (
|
|
133903
|
-
|
|
134196
|
+
let cursor = range?.lo ?? null;
|
|
134197
|
+
for (let page = 0; ; page++) {
|
|
134198
|
+
if (page >= PREFIX_PAGE_BUDGET) throw new Error(`settings door: reading "${prefix}" from "${collection}" exceeded ${PREFIX_PAGE_BUDGET} pages of ${PREFIX_PAGE_ROWS} rows. Refusing to return the part that was read \u2014 a partial scope read is indistinguishable from an empty one.`);
|
|
134199
|
+
const rows = await door.query({
|
|
134200
|
+
collection,
|
|
134201
|
+
filter: {
|
|
134202
|
+
...range !== null && cursor !== null ? { whereBetween: { id: [cursor, range.hi] } } : {},
|
|
134203
|
+
orderBy: {
|
|
134204
|
+
field: "id",
|
|
134205
|
+
direction: "asc"
|
|
134206
|
+
},
|
|
134207
|
+
limit: PREFIX_PAGE_ROWS
|
|
134208
|
+
}
|
|
134209
|
+
});
|
|
134210
|
+
for (const row of rows) {
|
|
134211
|
+
if (range !== null && (row.id < range.lo || row.id >= range.hi)) continue;
|
|
134212
|
+
if (!row.id.startsWith(prefix)) continue;
|
|
134213
|
+
result[row.id.slice(prefix.length)] = unwrapValue(row.data);
|
|
134214
|
+
}
|
|
134215
|
+
if (rows.length < PREFIX_PAGE_ROWS) return result;
|
|
134216
|
+
const last = rows[rows.length - 1];
|
|
134217
|
+
if (last === void 0) return result;
|
|
134218
|
+
if (range === null) throw new Error(`settings door: prefix "${prefix}" on "${collection}" cannot be expressed as an id range, and the unfiltered read filled a page \u2014 the answer would be partial. Use an ASCII, non-empty prefix.`);
|
|
134219
|
+
if (last.id === cursor) throw new Error(`settings door: reading "${prefix}" from "${collection}" made no progress at id "${last.id}" \u2014 ids under a prefix must be unique.`);
|
|
134220
|
+
cursor = last.id;
|
|
133904
134221
|
}
|
|
133905
|
-
return result;
|
|
133906
134222
|
}
|
|
133907
134223
|
async function replacePrefixed(door, collection, prefix, values, wrap3) {
|
|
133908
134224
|
const range = require_builtins_sqlite_storage_sqlite_settings_addon.prefixRange(prefix);
|
|
@@ -208826,7 +209142,7 @@ var require_dist4 = __commonJS({
|
|
|
208826
209142
|
"use strict";
|
|
208827
209143
|
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
208828
209144
|
var require_event_category = require_event_category_BaEgqJNv();
|
|
208829
|
-
var require_sleep =
|
|
209145
|
+
var require_sleep = require_sleep_DIg3xuEw();
|
|
208830
209146
|
var require_canonical_hash = require_canonical_hash_DNV8S5ET();
|
|
208831
209147
|
var require_enums2 = require_enums();
|
|
208832
209148
|
var require_err_msg = require_err_msg_COpsHMw2();
|
|
@@ -210173,6 +210489,20 @@ var require_dist4 = __commonJS({
|
|
|
210173
210489
|
* in its row, not in its name, so `MediaRelocateEngine` never reconciles one.
|
|
210174
210490
|
*/
|
|
210175
210491
|
rowsReconciled: zod.z.number().int().nonnegative().optional(),
|
|
210492
|
+
/**
|
|
210493
|
+
* Rows this run FORGOT because the file they name is not on disk.
|
|
210494
|
+
*
|
|
210495
|
+
* The mover derived the path from the row's own fields and `stat`ed it; an
|
|
210496
|
+
* ENOENT there is a per-path confirmation that the segment is gone (D296),
|
|
210497
|
+
* and the durable row is dropped through the same channel eviction uses. It
|
|
210498
|
+
* is reported for the same reason `rowsReconciled` is: this is a durable
|
|
210499
|
+
* mutation nobody asked for, and a migration that quietly erases hour rows is
|
|
210500
|
+
* the same failure as one that quietly skips them (D295).
|
|
210501
|
+
*
|
|
210502
|
+
* The production drain of 2026-08-30 would have reported 11 074 here — the
|
|
210503
|
+
* ledger claimed 5.65 GB of footage that no longer existed.
|
|
210504
|
+
*/
|
|
210505
|
+
rowsForgotten: zod.z.number().int().nonnegative().optional(),
|
|
210176
210506
|
startedAt: zod.z.number(),
|
|
210177
210507
|
finishedAt: zod.z.number().nullable(),
|
|
210178
210508
|
error: zod.z.string().nullable()
|
|
@@ -210380,6 +210710,71 @@ var require_dist4 = __commonJS({
|
|
|
210380
210710
|
segments: zod.z.number().int().nonnegative(),
|
|
210381
210711
|
bytes: zod.z.number().int().nonnegative()
|
|
210382
210712
|
}).nullable();
|
|
210713
|
+
var LedgerWalkInputSchema = zod.z.object({
|
|
210714
|
+
locationId: zod.z.string().min(1),
|
|
210715
|
+
/** Forget the confirmed-absent rows, rather than only counting them. */
|
|
210716
|
+
apply: zod.z.boolean().optional(),
|
|
210717
|
+
/** Narrow to one camera. */
|
|
210718
|
+
deviceId: zod.z.number().int().positive().optional(),
|
|
210719
|
+
/** Narrow to these recording profiles; empty/absent = every profile. */
|
|
210720
|
+
profiles: zod.z.array(zod.z.string().min(1)).optional()
|
|
210721
|
+
});
|
|
210722
|
+
var LedgerWalkRefusalSchema = zod.z.enum([
|
|
210723
|
+
"location-unknown",
|
|
210724
|
+
"source-writable",
|
|
210725
|
+
"no-ledger",
|
|
210726
|
+
"archive-unreadable",
|
|
210727
|
+
"anchor-absent",
|
|
210728
|
+
"anchor-unreadable",
|
|
210729
|
+
"anchor-moved"
|
|
210730
|
+
]);
|
|
210731
|
+
var LedgerWalkSkipReasonSchema = zod.z.enum([
|
|
210732
|
+
"live-tail",
|
|
210733
|
+
"listing-error",
|
|
210734
|
+
"path-mismatch",
|
|
210735
|
+
"durable-refused"
|
|
210736
|
+
]);
|
|
210737
|
+
var LedgerWalkSkipCountsSchema = zod.z.object({
|
|
210738
|
+
"live-tail": zod.z.number().int().nonnegative(),
|
|
210739
|
+
"listing-error": zod.z.number().int().nonnegative(),
|
|
210740
|
+
"path-mismatch": zod.z.number().int().nonnegative(),
|
|
210741
|
+
"durable-refused": zod.z.number().int().nonnegative()
|
|
210742
|
+
});
|
|
210743
|
+
var LedgerWalkDeviceReportSchema = zod.z.object({
|
|
210744
|
+
deviceId: zod.z.number().int(),
|
|
210745
|
+
hoursWalked: zod.z.number().int().nonnegative(),
|
|
210746
|
+
hoursMissing: zod.z.number().int().nonnegative(),
|
|
210747
|
+
ghostSegments: zod.z.number().int().nonnegative(),
|
|
210748
|
+
ghostBytes: zod.z.number().int().nonnegative(),
|
|
210749
|
+
forgottenSegments: zod.z.number().int().nonnegative(),
|
|
210750
|
+
orphanFiles: zod.z.number().int().nonnegative()
|
|
210751
|
+
});
|
|
210752
|
+
var LedgerWalkReportSchema = zod.z.object({
|
|
210753
|
+
locationId: zod.z.string(),
|
|
210754
|
+
applied: zod.z.boolean(),
|
|
210755
|
+
refused: LedgerWalkRefusalSchema.nullable(),
|
|
210756
|
+
archiveSegments: zod.z.number().int().nonnegative().nullable(),
|
|
210757
|
+
archiveBytes: zod.z.number().int().nonnegative().nullable(),
|
|
210758
|
+
hoursClaimed: zod.z.number().int().nonnegative(),
|
|
210759
|
+
hoursWalked: zod.z.number().int().nonnegative(),
|
|
210760
|
+
hoursMissing: zod.z.number().int().nonnegative(),
|
|
210761
|
+
/** `readdir` calls issued — the cost, stated in the unit that is paid. */
|
|
210762
|
+
listings: zod.z.number().int().nonnegative(),
|
|
210763
|
+
segmentsClaimed: zod.z.number().int().nonnegative(),
|
|
210764
|
+
ghostSegments: zod.z.number().int().nonnegative(),
|
|
210765
|
+
ghostBytes: zod.z.number().int().nonnegative(),
|
|
210766
|
+
ghostHoursWhole: zod.z.number().int().nonnegative(),
|
|
210767
|
+
forgottenSegments: zod.z.number().int().nonnegative(),
|
|
210768
|
+
forgottenBytes: zod.z.number().int().nonnegative(),
|
|
210769
|
+
/** Files under a claimed hour that no durable row names. Never deleted. */
|
|
210770
|
+
orphanFiles: zod.z.number().int().nonnegative(),
|
|
210771
|
+
orphanSample: zod.z.array(zod.z.string()).readonly(),
|
|
210772
|
+
hoursSkipped: zod.z.number().int().nonnegative(),
|
|
210773
|
+
skippedByReason: LedgerWalkSkipCountsSchema,
|
|
210774
|
+
/** The walk stopped at its per-pass hour bound with claims unwalked. */
|
|
210775
|
+
bounded: zod.z.boolean(),
|
|
210776
|
+
byDevice: zod.z.array(LedgerWalkDeviceReportSchema).readonly()
|
|
210777
|
+
});
|
|
210383
210778
|
var RelocatableMediaCountSchema = zod.z.object({ rows: zod.z.number().int().nonnegative() }).nullable();
|
|
210384
210779
|
var RelocatableMediaCountInputSchema = zod.z.object({
|
|
210385
210780
|
toLocationId: zod.z.string().min(1),
|
|
@@ -222879,13 +223274,15 @@ ${recipe.triggers.map((t, i) => emitTrigger(t, i)).join("\n\n")}
|
|
|
222879
223274
|
groups: zod.z.array(AnalyticsGroupRecordSchema).readonly(),
|
|
222880
223275
|
nextCursor: zod.z.string().nullable()
|
|
222881
223276
|
});
|
|
223277
|
+
var KEY_EVENTS_DEFAULT_LIMIT = 50;
|
|
223278
|
+
var KEY_EVENTS_MAX_LIMIT = 200;
|
|
222882
223279
|
var KeyEventQueryInput = zod.z.object({
|
|
222883
223280
|
deviceId: zod.z.number(),
|
|
222884
223281
|
/** Window lower bound (track firstSeen ≥ since). */
|
|
222885
223282
|
since: zod.z.number(),
|
|
222886
223283
|
/** Window upper bound (track firstSeen ≤ until). */
|
|
222887
223284
|
until: zod.z.number(),
|
|
222888
|
-
limit: zod.z.number().int().min(1).max(
|
|
223285
|
+
limit: zod.z.number().int().min(1).max(KEY_EVENTS_MAX_LIMIT).default(KEY_EVENTS_DEFAULT_LIMIT),
|
|
222889
223286
|
/** Drop tracks scoring below this importance. */
|
|
222890
223287
|
minImportance: zod.z.number().min(0).max(1).optional(),
|
|
222891
223288
|
/** Restrict to a single class (e.g. 'person'). */
|
|
@@ -222907,6 +223304,21 @@ ${recipe.triggers.map((t, i) => emitTrigger(t, i)).join("\n\n")}
|
|
|
222907
223304
|
...TrackFlagFields,
|
|
222908
223305
|
...TrackRetrainFields
|
|
222909
223306
|
});
|
|
223307
|
+
var KeyEventBatchQueryInput = zod.z.object({
|
|
223308
|
+
deviceIds: zod.z.array(zod.z.number()).min(1).max(200),
|
|
223309
|
+
since: zod.z.number(),
|
|
223310
|
+
until: zod.z.number(),
|
|
223311
|
+
/** Applied PER CAMERA, exactly as `getKeyEvents.limit` is — never a total
|
|
223312
|
+
* across the set, which would let a busy camera starve a quiet one of its
|
|
223313
|
+
* rows and change what the merged feed contains. */
|
|
223314
|
+
limit: zod.z.number().int().min(1).max(KEY_EVENTS_MAX_LIMIT).default(KEY_EVENTS_DEFAULT_LIMIT),
|
|
223315
|
+
minImportance: zod.z.number().min(0).max(1).optional(),
|
|
223316
|
+
classFilter: zod.z.string().optional()
|
|
223317
|
+
});
|
|
223318
|
+
var KeyEventsForDeviceSchema = zod.z.object({
|
|
223319
|
+
deviceId: zod.z.number(),
|
|
223320
|
+
events: zod.z.array(KeyEventSchema).readonly()
|
|
223321
|
+
});
|
|
222910
223322
|
var TrackedDetectionSchema = zod.z.object({
|
|
222911
223323
|
trackId: zod.z.string(),
|
|
222912
223324
|
className: zod.z.string(),
|
|
@@ -222975,6 +223387,25 @@ ${recipe.triggers.map((t, i) => emitTrigger(t, i)).join("\n\n")}
|
|
|
222975
223387
|
totalBytes: zod.z.number().int(),
|
|
222976
223388
|
devices: zod.z.array(EventStoreDeviceFootprintSchema).readonly()
|
|
222977
223389
|
});
|
|
223390
|
+
var EventMediaKindFootprintSchema = zod.z.object({
|
|
223391
|
+
kind: MediaFileKindEnum,
|
|
223392
|
+
/** Media rows of this kind. */
|
|
223393
|
+
rows: zod.z.number().int(),
|
|
223394
|
+
/** Bytes on disk held by those rows. */
|
|
223395
|
+
bytes: zod.z.number().int()
|
|
223396
|
+
});
|
|
223397
|
+
var EventMediaKindBreakdownSchema = zod.z.object({
|
|
223398
|
+
/** Every media row in scope, from one unfiltered aggregate. */
|
|
223399
|
+
totalRows: zod.z.number().int(),
|
|
223400
|
+
/** Every media byte in scope, from that same aggregate. */
|
|
223401
|
+
totalBytes: zod.z.number().int(),
|
|
223402
|
+
/** Per-kind footprint, ordered by bytes descending. */
|
|
223403
|
+
kinds: zod.z.array(EventMediaKindFootprintSchema).readonly(),
|
|
223404
|
+
/** `totalRows` minus the summed `kinds` rows — see the schema note. */
|
|
223405
|
+
unaccountedRows: zod.z.number().int(),
|
|
223406
|
+
/** `totalBytes` minus the summed `kinds` bytes — see the schema note. */
|
|
223407
|
+
unaccountedBytes: zod.z.number().int()
|
|
223408
|
+
});
|
|
222978
223409
|
var EventPruneCountsSchema = zod.z.object({
|
|
222979
223410
|
motion: zod.z.number().int(),
|
|
222980
223411
|
object: zod.z.number().int(),
|
|
@@ -223182,6 +223613,21 @@ ${recipe.triggers.map((t, i) => emitTrigger(t, i)).join("\n\n")}
|
|
|
223182
223613
|
* scored on-read (no write). Degrades to `[]` on error.
|
|
223183
223614
|
*/
|
|
223184
223615
|
getKeyEvents: require_sleep.method(KeyEventQueryInput, zod.z.array(KeyEventSchema).readonly()),
|
|
223616
|
+
/**
|
|
223617
|
+
* The same ranking, for a SET of cameras, in one round trip.
|
|
223618
|
+
*
|
|
223619
|
+
* The Detection Intelligence events feed asks this of every selected
|
|
223620
|
+
* camera and re-asks on a 30s timer. Fanned out client-side that is N
|
|
223621
|
+
* round trips — browser → hub → post-analysis — for N independent,
|
|
223622
|
+
* already-indexed store queries. Batched, the queries are unchanged and
|
|
223623
|
+
* run concurrently INSIDE the owner; only the transport collapses.
|
|
223624
|
+
*
|
|
223625
|
+
* Deliberately per-device rather than pre-merged: `limit` stays per
|
|
223626
|
+
* camera (a total would let a busy camera starve a quiet one), and a
|
|
223627
|
+
* caller that renders one camera's lane needs to know which camera a row
|
|
223628
|
+
* came from. `getKeyEvents` stays for single-device callers.
|
|
223629
|
+
*/
|
|
223630
|
+
getKeyEventsBatch: require_sleep.method(KeyEventBatchQueryInput, zod.z.array(KeyEventsForDeviceSchema).readonly()),
|
|
223185
223631
|
/** Server-side bucketed event counts for the 24-hour timeline.
|
|
223186
223632
|
* Returns one entry per non-empty bucket; empty buckets are omitted. */
|
|
223187
223633
|
getEventDensity: require_sleep.method(zod.z.object({
|
|
@@ -223330,6 +223776,22 @@ ${recipe.triggers.map((t, i) => emitTrigger(t, i)).join("\n\n")}
|
|
|
223330
223776
|
auth: "admin"
|
|
223331
223777
|
}),
|
|
223332
223778
|
/**
|
|
223779
|
+
* The same media footprint, broken down by {@link MediaFileKind} instead of
|
|
223780
|
+
* by camera — fleet-wide, or for one camera with `deviceId`.
|
|
223781
|
+
*
|
|
223782
|
+
* Separate from {@link getEventStoreFootprint} rather than a field on it:
|
|
223783
|
+
* the two answer different questions on different axes, the per-camera one
|
|
223784
|
+
* is what the management table renders on every open, and nothing should
|
|
223785
|
+
* pay for a per-kind pass to draw it. See
|
|
223786
|
+
* {@link EventMediaKindBreakdownSchema} for why `unaccounted*` exists —
|
|
223787
|
+
* `kinds` is enumerated, `totalBytes` is not, and the gap must be visible
|
|
223788
|
+
* to anyone sizing a deletion against it.
|
|
223789
|
+
*/
|
|
223790
|
+
getEventMediaFootprintByKind: require_sleep.method(zod.z.object({ deviceId: zod.z.number().int().optional() }), EventMediaKindBreakdownSchema, {
|
|
223791
|
+
kind: "query",
|
|
223792
|
+
auth: "admin"
|
|
223793
|
+
}),
|
|
223794
|
+
/**
|
|
223333
223795
|
* Cluster-wide prune of events older than `olderThanMs` (exclusive) across
|
|
223334
223796
|
* every camera, deleting each event's media in lockstep. Logged to the
|
|
223335
223797
|
* events ops-log with `reason` (default `'retention'`). Returns the summed
|
|
@@ -226092,6 +226554,20 @@ ${recipe.triggers.map((t, i) => emitTrigger(t, i)).join("\n\n")}
|
|
|
226092
226554
|
listProviders: require_sleep.method(zod.z.void(), zod.z.array(ProviderListEntrySchema).readonly()),
|
|
226093
226555
|
testConfig: require_sleep.method(zod.z.object({
|
|
226094
226556
|
providerId: zod.z.string(),
|
|
226557
|
+
/**
|
|
226558
|
+
* The location this config is an UNSAVED edit of, when there is one.
|
|
226559
|
+
*
|
|
226560
|
+
* `listLocations` replaces every declared secret with the redaction
|
|
226561
|
+
* sentinel, so the edit modal's form state holds the sentinel for any
|
|
226562
|
+
* credential the operator did not retype — and posting that here
|
|
226563
|
+
* without a way to resolve it makes the provider try to authenticate
|
|
226564
|
+
* as `__camstack_redacted__` and report the operator's own working
|
|
226565
|
+
* password as wrong. Given this id, the orchestrator restores each
|
|
226566
|
+
* sentinel from the stored config (same rule as `upsertLocation`)
|
|
226567
|
+
* before dispatching. Omitted by the "Add location" wizard, where
|
|
226568
|
+
* every value was typed just now and nothing is stored yet.
|
|
226569
|
+
*/
|
|
226570
|
+
locationId: zod.z.string().optional(),
|
|
226095
226571
|
config: zod.z.record(zod.z.string(), zod.z.unknown())
|
|
226096
226572
|
}), zod.z.object({
|
|
226097
226573
|
ok: zod.z.boolean(),
|
|
@@ -233269,6 +233745,23 @@ ${recipe.triggers.map((t, i) => emitTrigger(t, i)).join("\n\n")}
|
|
|
233269
233745
|
kind: "query",
|
|
233270
233746
|
auth: "admin"
|
|
233271
233747
|
}),
|
|
233748
|
+
/**
|
|
233749
|
+
* Does this location's LEDGER tell the truth about its disk? (D319)
|
|
233750
|
+
*
|
|
233751
|
+
* One `readdir` per claimed hour, diffed both ways: durable rows whose file
|
|
233752
|
+
* is not there, and files no durable row names. `apply` defaults to FALSE —
|
|
233753
|
+
* the report is the product, and the dry run is how an operator
|
|
233754
|
+
* sanity-checks the destructive run before authorising it.
|
|
233755
|
+
*
|
|
233756
|
+
* REFUSES a source that is still a write target: a listing of a live
|
|
233757
|
+
* location is a lower bound, which is not the strong evidence that lets
|
|
233758
|
+
* this pass forget without a budget. A live location is reconciled by the
|
|
233759
|
+
* mover, under D318's bound.
|
|
233760
|
+
*/
|
|
233761
|
+
reconcileLedgerAgainstDisk: require_sleep.method(LedgerWalkInputSchema, LedgerWalkReportSchema, {
|
|
233762
|
+
kind: "mutation",
|
|
233763
|
+
auth: "admin"
|
|
233764
|
+
}),
|
|
233272
233765
|
/** Cancel a running or queued relocate job. A queued job never runs. */
|
|
233273
233766
|
cancelRelocateJob: require_sleep.method(zod.z.object({ jobId: zod.z.string() }), zod.z.object({ cancelled: zod.z.boolean() }), {
|
|
233274
233767
|
kind: "mutation",
|
|
@@ -233583,6 +234076,10 @@ ${recipe.triggers.map((t, i) => emitTrigger(t, i)).join("\n\n")}
|
|
|
233583
234076
|
monitors: zod.z.array(SceneMonitorSchema),
|
|
233584
234077
|
lastFetchedAt: zod.z.number()
|
|
233585
234078
|
});
|
|
234079
|
+
var SceneMonitorStatusForDeviceSchema = zod.z.object({
|
|
234080
|
+
deviceId: zod.z.number(),
|
|
234081
|
+
status: SceneMonitorStatusSchema.nullable()
|
|
234082
|
+
});
|
|
233586
234083
|
var sceneMonitorCapability = {
|
|
233587
234084
|
name: "scene-monitor",
|
|
233588
234085
|
scope: "device",
|
|
@@ -233592,6 +234089,22 @@ ${recipe.triggers.map((t, i) => emitTrigger(t, i)).join("\n\n")}
|
|
|
233592
234089
|
deviceTypes: [require_sleep.DeviceType.Camera],
|
|
233593
234090
|
methods: {
|
|
233594
234091
|
listScenes: require_sleep.method(zod.z.object({ deviceId: zod.z.number() }), SceneMonitorStatusSchema),
|
|
234092
|
+
/**
|
|
234093
|
+
* The same answer, for a SET of cameras, in one round trip.
|
|
234094
|
+
*
|
|
234095
|
+
* `/scenes` renders every camera and re-reads them on a 30s safety-net
|
|
234096
|
+
* poll behind the push slice. Fanned out client-side that was one query
|
|
234097
|
+
* per camera — 29 round trips through the browser, the hub and the
|
|
234098
|
+
* post-analysis runner every 30 seconds to read an in-memory map the
|
|
234099
|
+
* owner had already merged. The work is unchanged (`statusFor` per
|
|
234100
|
+
* device, all in-process at the owner); what collapses is the transport.
|
|
234101
|
+
*
|
|
234102
|
+
* A camera that cannot answer still gets a row, with `status: null` —
|
|
234103
|
+
* see {@link SceneMonitorStatusForDeviceSchema}. Never fewer rows than
|
|
234104
|
+
* ids: a caller that asked for twenty-nine and got twenty-seven cannot
|
|
234105
|
+
* tell which two are missing, or that any are.
|
|
234106
|
+
*/
|
|
234107
|
+
listScenesBatch: require_sleep.method(zod.z.object({ deviceIds: zod.z.array(zod.z.number()).min(1).max(200) }), zod.z.array(SceneMonitorStatusForDeviceSchema).readonly()),
|
|
233595
234108
|
createScene: require_sleep.method(zod.z.object({
|
|
233596
234109
|
deviceId: zod.z.number(),
|
|
233597
234110
|
label: zod.z.string(),
|
|
@@ -235393,6 +235906,11 @@ ${recipe.triggers.map((t, i) => emitTrigger(t, i)).join("\n\n")}
|
|
|
235393
235906
|
* than as repeated tracks/events. */
|
|
235394
235907
|
stationaryObjects: zod.z.array(StationaryObjectSchema).readonly().optional()
|
|
235395
235908
|
});
|
|
235909
|
+
var CameraOccupancySnapshotForDeviceSchema = zod.z.object({
|
|
235910
|
+
deviceId: zod.z.number(),
|
|
235911
|
+
read: zod.z.enum(["read", "unreadable"]),
|
|
235912
|
+
snapshot: CameraOccupancySnapshotSchema.nullable()
|
|
235913
|
+
});
|
|
235396
235914
|
var HistoryResolutionEnum = zod.z.enum([
|
|
235397
235915
|
"minute",
|
|
235398
235916
|
"5min",
|
|
@@ -235422,6 +235940,20 @@ ${recipe.triggers.map((t, i) => emitTrigger(t, i)).join("\n\n")}
|
|
|
235422
235940
|
* (no inference result emitted since boot or since binding was
|
|
235423
235941
|
* activated). */
|
|
235424
235942
|
getCurrentSnapshot: require_sleep.method(zod.z.object({ deviceId: zod.z.number() }), CameraOccupancySnapshotSchema.nullable()),
|
|
235943
|
+
/**
|
|
235944
|
+
* The same snapshot, for a SET of cameras, in one round trip.
|
|
235945
|
+
*
|
|
235946
|
+
* The Events page's Stationary section polls this every 15s for every
|
|
235947
|
+
* selected camera. Fanned out client-side that is one query per camera to
|
|
235948
|
+
* read a `Map.get` at the owner — the answer costs nothing, the round trip
|
|
235949
|
+
* costs everything. Batched, N transports become one and the per-device
|
|
235950
|
+
* work is unchanged.
|
|
235951
|
+
*
|
|
235952
|
+
* Every requested deviceId gets a row, tagged `read` — see
|
|
235953
|
+
* {@link CameraOccupancySnapshotForDeviceSchema}. A camera the owner could
|
|
235954
|
+
* not answer for is `'unreadable'`, never an empty reading.
|
|
235955
|
+
*/
|
|
235956
|
+
getCurrentSnapshotBatch: require_sleep.method(zod.z.object({ deviceIds: zod.z.array(zod.z.number()).min(1).max(200) }), zod.z.array(CameraOccupancySnapshotForDeviceSchema).readonly()),
|
|
235425
235957
|
/** Time-series object count inside one zone. `className` optional —
|
|
235426
235958
|
* omit to count every class in the zone. */
|
|
235427
235959
|
getZoneHistory: require_sleep.method(zod.z.object({
|
|
@@ -242263,6 +242795,12 @@ ${recipe.triggers.map((t, i) => emitTrigger(t, i)).join("\n\n")}
|
|
|
242263
242795
|
addonId: null,
|
|
242264
242796
|
access: "view"
|
|
242265
242797
|
},
|
|
242798
|
+
"pipelineAnalytics.getEventMediaFootprintByKind": {
|
|
242799
|
+
capName: "pipeline-analytics",
|
|
242800
|
+
capScope: "device",
|
|
242801
|
+
addonId: null,
|
|
242802
|
+
access: "view"
|
|
242803
|
+
},
|
|
242266
242804
|
"pipelineAnalytics.getEventStoreFootprint": {
|
|
242267
242805
|
capName: "pipeline-analytics",
|
|
242268
242806
|
capScope: "device",
|
|
@@ -242281,6 +242819,12 @@ ${recipe.triggers.map((t, i) => emitTrigger(t, i)).join("\n\n")}
|
|
|
242281
242819
|
addonId: null,
|
|
242282
242820
|
access: "view"
|
|
242283
242821
|
},
|
|
242822
|
+
"pipelineAnalytics.getKeyEventsBatch": {
|
|
242823
|
+
capName: "pipeline-analytics",
|
|
242824
|
+
capScope: "device",
|
|
242825
|
+
addonId: null,
|
|
242826
|
+
access: "view"
|
|
242827
|
+
},
|
|
242284
242828
|
"pipelineAnalytics.getMotionEvents": {
|
|
242285
242829
|
capName: "pipeline-analytics",
|
|
242286
242830
|
capScope: "device",
|
|
@@ -243457,6 +244001,12 @@ ${recipe.triggers.map((t, i) => emitTrigger(t, i)).join("\n\n")}
|
|
|
243457
244001
|
addonId: null,
|
|
243458
244002
|
access: "view"
|
|
243459
244003
|
},
|
|
244004
|
+
"recording.reconcileLedgerAgainstDisk": {
|
|
244005
|
+
capName: "recording",
|
|
244006
|
+
capScope: "system",
|
|
244007
|
+
addonId: null,
|
|
244008
|
+
access: "create"
|
|
244009
|
+
},
|
|
243460
244010
|
"recording.refreshStorageLocationsForMigration": {
|
|
243461
244011
|
capName: "recording",
|
|
243462
244012
|
capScope: "system",
|
|
@@ -243583,6 +244133,12 @@ ${recipe.triggers.map((t, i) => emitTrigger(t, i)).join("\n\n")}
|
|
|
243583
244133
|
addonId: null,
|
|
243584
244134
|
access: "view"
|
|
243585
244135
|
},
|
|
244136
|
+
"sceneMonitor.listScenesBatch": {
|
|
244137
|
+
capName: "scene-monitor",
|
|
244138
|
+
capScope: "device",
|
|
244139
|
+
addonId: null,
|
|
244140
|
+
access: "view"
|
|
244141
|
+
},
|
|
243586
244142
|
"sceneMonitor.recheckNow": {
|
|
243587
244143
|
capName: "scene-monitor",
|
|
243588
244144
|
capScope: "device",
|
|
@@ -244939,6 +245495,12 @@ ${recipe.triggers.map((t, i) => emitTrigger(t, i)).join("\n\n")}
|
|
|
244939
245495
|
addonId: null,
|
|
244940
245496
|
access: "view"
|
|
244941
245497
|
},
|
|
245498
|
+
"zoneAnalytics.getCurrentSnapshotBatch": {
|
|
245499
|
+
capName: "zone-analytics",
|
|
245500
|
+
capScope: "device",
|
|
245501
|
+
addonId: null,
|
|
245502
|
+
access: "view"
|
|
245503
|
+
},
|
|
244942
245504
|
"zoneAnalytics.getUnzonedHistory": {
|
|
244943
245505
|
capName: "zone-analytics",
|
|
244944
245506
|
capScope: "device",
|
|
@@ -246186,6 +246748,11 @@ ${recipe.triggers.map((t, i) => emitTrigger(t, i)).join("\n\n")}
|
|
|
246186
246748
|
form: "single",
|
|
246187
246749
|
optional: false
|
|
246188
246750
|
}],
|
|
246751
|
+
"pipelineAnalytics.getEventMediaFootprintByKind": [{
|
|
246752
|
+
name: "deviceId",
|
|
246753
|
+
form: "single",
|
|
246754
|
+
optional: true
|
|
246755
|
+
}],
|
|
246189
246756
|
"pipelineAnalytics.getGroup": [{
|
|
246190
246757
|
name: "deviceId",
|
|
246191
246758
|
form: "single",
|
|
@@ -246196,6 +246763,11 @@ ${recipe.triggers.map((t, i) => emitTrigger(t, i)).join("\n\n")}
|
|
|
246196
246763
|
form: "single",
|
|
246197
246764
|
optional: false
|
|
246198
246765
|
}],
|
|
246766
|
+
"pipelineAnalytics.getKeyEventsBatch": [{
|
|
246767
|
+
name: "deviceIds",
|
|
246768
|
+
form: "array",
|
|
246769
|
+
optional: false
|
|
246770
|
+
}],
|
|
246199
246771
|
"pipelineAnalytics.getMotionEvents": [{
|
|
246200
246772
|
name: "deviceId",
|
|
246201
246773
|
form: "single",
|
|
@@ -246636,6 +247208,11 @@ ${recipe.triggers.map((t, i) => emitTrigger(t, i)).join("\n\n")}
|
|
|
246636
247208
|
form: "single",
|
|
246637
247209
|
optional: false
|
|
246638
247210
|
}],
|
|
247211
|
+
"recording.reconcileLedgerAgainstDisk": [{
|
|
247212
|
+
name: "deviceId",
|
|
247213
|
+
form: "single",
|
|
247214
|
+
optional: true
|
|
247215
|
+
}],
|
|
246639
247216
|
"recording.relocateFootage": [{
|
|
246640
247217
|
name: "deviceId",
|
|
246641
247218
|
form: "single",
|
|
@@ -246701,6 +247278,11 @@ ${recipe.triggers.map((t, i) => emitTrigger(t, i)).join("\n\n")}
|
|
|
246701
247278
|
form: "single",
|
|
246702
247279
|
optional: false
|
|
246703
247280
|
}],
|
|
247281
|
+
"sceneMonitor.listScenesBatch": [{
|
|
247282
|
+
name: "deviceIds",
|
|
247283
|
+
form: "array",
|
|
247284
|
+
optional: false
|
|
247285
|
+
}],
|
|
246704
247286
|
"sceneMonitor.recheckNow": [{
|
|
246705
247287
|
name: "deviceId",
|
|
246706
247288
|
form: "single",
|
|
@@ -246962,6 +247544,11 @@ ${recipe.triggers.map((t, i) => emitTrigger(t, i)).join("\n\n")}
|
|
|
246962
247544
|
form: "single",
|
|
246963
247545
|
optional: false
|
|
246964
247546
|
}],
|
|
247547
|
+
"zoneAnalytics.getCurrentSnapshotBatch": [{
|
|
247548
|
+
name: "deviceIds",
|
|
247549
|
+
form: "array",
|
|
247550
|
+
optional: false
|
|
247551
|
+
}],
|
|
246965
247552
|
"zoneAnalytics.getUnzonedHistory": [{
|
|
246966
247553
|
name: "deviceId",
|
|
246967
247554
|
form: "single",
|
|
@@ -247114,6 +247701,7 @@ ${recipe.triggers.map((t, i) => emitTrigger(t, i)).join("\n\n")}
|
|
|
247114
247701
|
"recording.readGopBytes",
|
|
247115
247702
|
"recording.readSegmentBytes",
|
|
247116
247703
|
"recording.readWindowBytes",
|
|
247704
|
+
"recording.reconcileLedgerAgainstDisk",
|
|
247117
247705
|
"recording.relocateFootage",
|
|
247118
247706
|
"recording.renderClip",
|
|
247119
247707
|
"recording.renderGif",
|
|
@@ -247999,6 +248587,7 @@ ${recipe.triggers.map((t, i) => emitTrigger(t, i)).join("\n\n")}
|
|
|
247999
248587
|
relocateFootage: (input) => dispatch("recording", "relocateFootage", "mutation", input),
|
|
248000
248588
|
listRelocateJobs: (input) => dispatch("recording", "listRelocateJobs", "query", input),
|
|
248001
248589
|
getRelocateResidue: (input) => dispatch("recording", "getRelocateResidue", "query", input),
|
|
248590
|
+
reconcileLedgerAgainstDisk: (input) => dispatch("recording", "reconcileLedgerAgainstDisk", "mutation", input),
|
|
248002
248591
|
cancelRelocateJob: (input) => dispatch("recording", "cancelRelocateJob", "mutation", input),
|
|
248003
248592
|
planStorageRebalance: (input) => dispatch("recording", "planStorageRebalance", "query", input),
|
|
248004
248593
|
startStorageRebalance: (input) => dispatch("recording", "startStorageRebalance", "mutation", input)
|
|
@@ -250959,6 +251548,7 @@ ${recipe.triggers.map((t, i) => emitTrigger(t, i)).join("\n\n")}
|
|
|
250959
251548
|
exports.CameraMetricsSchema = CameraMetricsSchema;
|
|
250960
251549
|
exports.CameraMetricsWithDeviceIdSchema = CameraMetricsWithDeviceIdSchema;
|
|
250961
251550
|
exports.CameraMotionStatusSchema = CameraMotionStatusSchema;
|
|
251551
|
+
exports.CameraOccupancySnapshotForDeviceSchema = CameraOccupancySnapshotForDeviceSchema;
|
|
250962
251552
|
exports.CameraRecordingModeSchema = CameraRecordingModeSchema;
|
|
250963
251553
|
exports.CameraRecordingStatusSchema = CameraRecordingStatusSchema;
|
|
250964
251554
|
exports.CameraSourceStatusSchema = CameraSourceStatusSchema;
|
|
@@ -251209,6 +251799,12 @@ ${recipe.triggers.map((t, i) => emitTrigger(t, i)).join("\n\n")}
|
|
|
251209
251799
|
exports.LabelTierSchema = LabelTierSchema;
|
|
251210
251800
|
exports.LawnMowerActivitySchema = LawnMowerActivitySchema;
|
|
251211
251801
|
exports.LawnMowerControlStatusSchema = LawnMowerControlStatusSchema;
|
|
251802
|
+
exports.LedgerWalkDeviceReportSchema = LedgerWalkDeviceReportSchema;
|
|
251803
|
+
exports.LedgerWalkInputSchema = LedgerWalkInputSchema;
|
|
251804
|
+
exports.LedgerWalkRefusalSchema = LedgerWalkRefusalSchema;
|
|
251805
|
+
exports.LedgerWalkReportSchema = LedgerWalkReportSchema;
|
|
251806
|
+
exports.LedgerWalkSkipCountsSchema = LedgerWalkSkipCountsSchema;
|
|
251807
|
+
exports.LedgerWalkSkipReasonSchema = LedgerWalkSkipReasonSchema;
|
|
251212
251808
|
exports.LinkedDeviceSchema = LinkedDeviceSchema;
|
|
251213
251809
|
exports.LinkedDevicesModeSchema = LinkedDevicesModeSchema;
|
|
251214
251810
|
exports.ListGroupsPageSchema = ListGroupsPageSchema;
|
|
@@ -251291,6 +251887,7 @@ ${recipe.triggers.map((t, i) => emitTrigger(t, i)).join("\n\n")}
|
|
|
251291
251887
|
exports.MaskShapeKindSchema = MaskShapeKindSchema;
|
|
251292
251888
|
exports.MaskShapeSchema = MaskShapeSchema;
|
|
251293
251889
|
exports.MediaFileInfoSchema = MediaFileInfoSchema;
|
|
251890
|
+
exports.MediaFileKindEnum = MediaFileKindEnum;
|
|
251294
251891
|
exports.MediaFileRefSchema = MediaFileRefSchema;
|
|
251295
251892
|
exports.MediaFileSchema = MediaFileSchema;
|
|
251296
251893
|
exports.MediaPlayerRepeatSchema = MediaPlayerRepeatSchema;
|
|
@@ -251629,6 +252226,7 @@ ${recipe.triggers.map((t, i) => emitTrigger(t, i)).join("\n\n")}
|
|
|
251629
252226
|
exports.SceneConfirmSchema = SceneConfirmSchema;
|
|
251630
252227
|
exports.SceneMonitorSchema = SceneMonitorSchema;
|
|
251631
252228
|
exports.SceneMonitorStateSchema = SceneMonitorStateSchema;
|
|
252229
|
+
exports.SceneMonitorStatusForDeviceSchema = SceneMonitorStatusForDeviceSchema;
|
|
251632
252230
|
exports.SceneMonitorStatusSchema = SceneMonitorStatusSchema;
|
|
251633
252231
|
exports.SceneReferenceSchema = SceneReferenceSchema;
|
|
251634
252232
|
exports.SceneUnavailableSchema = SceneUnavailableSchema;
|
|
@@ -410449,6 +411047,7 @@ var require_cap_providers = __commonJS({
|
|
|
410449
411047
|
exports.buildSettingsStoreGateway = buildSettingsStoreGateway;
|
|
410450
411048
|
exports.buildNetworkQualityProvider = buildNetworkQualityProvider;
|
|
410451
411049
|
exports.buildToastProvider = buildToastProvider;
|
|
411050
|
+
exports.computeTopologyPass = computeTopologyPass;
|
|
410452
411051
|
exports.computeTopology = computeTopology;
|
|
410453
411052
|
exports.createNodeRootPackageLookup = createNodeRootPackageLookup;
|
|
410454
411053
|
exports.buildNodesProvider = buildNodesProvider;
|
|
@@ -410597,9 +411196,19 @@ var require_cap_providers = __commonJS({
|
|
|
410597
411196
|
}
|
|
410598
411197
|
return ips;
|
|
410599
411198
|
}
|
|
411199
|
+
async function computeTopologyPass(agentRegistry, addonRegistry, getNodeRootPackage) {
|
|
411200
|
+
const [nodes, liveNodes] = await computeTopologyInternal(agentRegistry, addonRegistry, getNodeRootPackage);
|
|
411201
|
+
return { nodes, liveNodes };
|
|
411202
|
+
}
|
|
410600
411203
|
async function computeTopology(agentRegistry, addonRegistry, getNodeRootPackage) {
|
|
410601
|
-
const nodes = await agentRegistry
|
|
410602
|
-
|
|
411204
|
+
const [nodes] = await computeTopologyInternal(agentRegistry, addonRegistry, getNodeRootPackage);
|
|
411205
|
+
return nodes;
|
|
411206
|
+
}
|
|
411207
|
+
async function computeTopologyInternal(agentRegistry, addonRegistry, getNodeRootPackage) {
|
|
411208
|
+
const [nodes, history] = await Promise.all([
|
|
411209
|
+
agentRegistry.listNodes(),
|
|
411210
|
+
agentRegistry.getClusterNodeHistory()
|
|
411211
|
+
]);
|
|
410603
411212
|
const historyById = new Map(history.map((h) => [h.id, h]));
|
|
410604
411213
|
const liveIds = new Set(nodes.map((n) => n.info.id));
|
|
410605
411214
|
const allAddons = addonRegistry?.listAddons() ?? [];
|
|
@@ -410754,7 +411363,7 @@ var require_cap_providers = __commonJS({
|
|
|
410754
411363
|
categories: [],
|
|
410755
411364
|
rootPackage: null
|
|
410756
411365
|
}));
|
|
410757
|
-
return [...liveNodes, ...offlineNodes];
|
|
411366
|
+
return [[...liveNodes, ...offlineNodes], nodes];
|
|
410758
411367
|
}
|
|
410759
411368
|
function createNodeRootPackageLookup(moleculer, serverUpdate) {
|
|
410760
411369
|
return (nodeId, isHub) => {
|
|
@@ -420480,6 +421089,19 @@ var require_agent_registry_service = __commonJS({
|
|
|
420480
421089
|
addonIds: [...entry.agentAddons ?? []]
|
|
420481
421090
|
};
|
|
420482
421091
|
}
|
|
421092
|
+
function toSubProcess(p) {
|
|
421093
|
+
return {
|
|
421094
|
+
pid: p.pid ?? 0,
|
|
421095
|
+
name: p.name ?? "",
|
|
421096
|
+
command: "moleculer-service",
|
|
421097
|
+
state: p.state ?? "running",
|
|
421098
|
+
cpuPercent: p.cpuPercent ?? 0,
|
|
421099
|
+
memoryRss: p.memoryRss ?? 0,
|
|
421100
|
+
uptimeSeconds: p.uptimeSeconds ?? 0,
|
|
421101
|
+
addonIds: p.addonIds ?? [],
|
|
421102
|
+
groupId: p.groupId ?? null
|
|
421103
|
+
};
|
|
421104
|
+
}
|
|
420483
421105
|
var AgentRegistryService = class {
|
|
420484
421106
|
eventBus;
|
|
420485
421107
|
moleculer;
|
|
@@ -421006,107 +421628,113 @@ var require_agent_registry_service = __commonJS({
|
|
|
421006
421628
|
return toNodeLiveness(this.moleculer.broker.registry.getNodeList({ onlyAvailable: false }));
|
|
421007
421629
|
}
|
|
421008
421630
|
async listNodes() {
|
|
421009
|
-
|
|
421631
|
+
const registry = this.moleculer.broker.registry;
|
|
421632
|
+
const nodes = registry?.getNodeList?.({ onlyAvailable: false }) ?? [];
|
|
421633
|
+
const remoteTargets = nodes.filter((node) => typeof node.id === "string" && node.id !== "hub" && !node.id.includes("/"));
|
|
421634
|
+
const [hubEntry, remoteEntries] = await Promise.all([
|
|
421635
|
+
this.listHubProcesses().then((procs) => this.buildHubEntry(procs)),
|
|
421636
|
+
Promise.all(remoteTargets.map((node) => node.available ? (
|
|
421637
|
+
// Online: one wave of `$agent.status` + `$process.list`.
|
|
421638
|
+
this.buildRemoteEntry(node.id)
|
|
421639
|
+
) : (
|
|
421640
|
+
// Offline: skip the RPC fan-out entirely (the node is unreachable —
|
|
421641
|
+
// those calls would just time out) and surface a minimal,
|
|
421642
|
+
// honestly-degraded row instead.
|
|
421643
|
+
Promise.resolve(this.buildOfflineEntry(node))
|
|
421644
|
+
)))
|
|
421645
|
+
]);
|
|
421646
|
+
return [hubEntry, ...remoteEntries.filter((entry) => entry !== null)];
|
|
421647
|
+
}
|
|
421648
|
+
/** The hub's own runner subprocesses (`$process.list`, hub-local). */
|
|
421649
|
+
async listHubProcesses() {
|
|
421010
421650
|
try {
|
|
421011
421651
|
const processes = await this.broker.call("$process.list");
|
|
421012
|
-
|
|
421013
|
-
pid: p.pid ?? 0,
|
|
421014
|
-
name: p.name ?? "",
|
|
421015
|
-
command: "moleculer-service",
|
|
421016
|
-
state: p.state ?? "running",
|
|
421017
|
-
cpuPercent: p.cpuPercent ?? 0,
|
|
421018
|
-
memoryRss: p.memoryRss ?? 0,
|
|
421019
|
-
uptimeSeconds: p.uptimeSeconds ?? 0,
|
|
421020
|
-
addonIds: p.addonIds ?? [],
|
|
421021
|
-
groupId: p.groupId ?? null
|
|
421022
|
-
}));
|
|
421652
|
+
return processes.map(toSubProcess);
|
|
421023
421653
|
} catch {
|
|
421654
|
+
return [];
|
|
421024
421655
|
}
|
|
421025
|
-
const hubEntry = await this.buildHubEntry(hubProcesses);
|
|
421026
|
-
const remoteEntries = [];
|
|
421027
|
-
const registry = this.moleculer.broker.registry;
|
|
421028
|
-
const nodes = registry?.getNodeList?.({ onlyAvailable: false }) ?? [];
|
|
421029
|
-
for (const node of nodes) {
|
|
421030
|
-
const nodeId = node.id;
|
|
421031
|
-
if (typeof nodeId !== "string" || nodeId === "hub" || nodeId.includes("/"))
|
|
421032
|
-
continue;
|
|
421033
|
-
if (!node.available) {
|
|
421034
|
-
remoteEntries.push(this.buildOfflineEntry(node));
|
|
421035
|
-
continue;
|
|
421036
|
-
}
|
|
421037
|
-
try {
|
|
421038
|
-
const status = await this.broker.call("$agent.status", {}, {
|
|
421039
|
-
nodeID: nodeId,
|
|
421040
|
-
timeout: 5e3
|
|
421041
|
-
});
|
|
421042
|
-
let subProcesses = [];
|
|
421043
|
-
try {
|
|
421044
|
-
const processes = await this.broker.call("$process.list", {}, {
|
|
421045
|
-
nodeID: nodeId,
|
|
421046
|
-
timeout: 5e3
|
|
421047
|
-
});
|
|
421048
|
-
subProcesses = processes.map((p) => ({
|
|
421049
|
-
pid: p.pid ?? 0,
|
|
421050
|
-
name: p.name ?? "",
|
|
421051
|
-
command: "moleculer-service",
|
|
421052
|
-
state: p.state ?? "running",
|
|
421053
|
-
cpuPercent: p.cpuPercent ?? 0,
|
|
421054
|
-
memoryRss: p.memoryRss ?? 0,
|
|
421055
|
-
uptimeSeconds: p.uptimeSeconds ?? 0,
|
|
421056
|
-
addonIds: p.addonIds ?? [],
|
|
421057
|
-
groupId: p.groupId ?? null
|
|
421058
|
-
}));
|
|
421059
|
-
} catch {
|
|
421060
|
-
subProcesses = status.addons?.map((a) => ({
|
|
421061
|
-
pid: 0,
|
|
421062
|
-
name: a.id ?? "",
|
|
421063
|
-
command: "moleculer-service",
|
|
421064
|
-
state: a.status ?? "running",
|
|
421065
|
-
cpuPercent: 0,
|
|
421066
|
-
memoryRss: 0,
|
|
421067
|
-
uptimeSeconds: 0
|
|
421068
|
-
})) ?? [];
|
|
421069
|
-
}
|
|
421070
|
-
const agentAddons = status.addons?.map((a) => a.id) ?? [];
|
|
421071
|
-
const hostname = typeof status.hostname === "string" ? status.hostname : null;
|
|
421072
|
-
const agentName = typeof status.name === "string" ? status.name : nodeId;
|
|
421073
|
-
remoteEntries.push({
|
|
421074
|
-
info: {
|
|
421075
|
-
id: nodeId,
|
|
421076
|
-
name: agentName,
|
|
421077
|
-
hostname: hostname ?? nodeId,
|
|
421078
|
-
capabilities: [],
|
|
421079
|
-
platform: status.platform ?? "unknown",
|
|
421080
|
-
arch: status.arch ?? "unknown",
|
|
421081
|
-
cpuCores: status.cpuCores ?? 0,
|
|
421082
|
-
memoryMB: status.totalMemoryMB ?? 0,
|
|
421083
|
-
cpuModel: status.cpuModel
|
|
421084
|
-
},
|
|
421085
|
-
localIps: Array.isArray(status.localIps) ? status.localIps : [],
|
|
421086
|
-
status: {
|
|
421087
|
-
activeCameras: 0,
|
|
421088
|
-
cpuPercent: status.cpuPercent ?? 0,
|
|
421089
|
-
memoryPercent: status.memoryPercent ?? 0,
|
|
421090
|
-
fps: {},
|
|
421091
|
-
errors: []
|
|
421092
|
-
},
|
|
421093
|
-
connectedSince: typeof status.uptime === "number" ? Date.now() - status.uptime * 1e3 : Date.now(),
|
|
421094
|
-
isHub: false,
|
|
421095
|
-
subProcesses,
|
|
421096
|
-
agentAddons
|
|
421097
|
-
});
|
|
421098
|
-
} catch {
|
|
421099
|
-
}
|
|
421100
|
-
}
|
|
421101
|
-
await this.snapshotOnlineNodes([hubEntry, ...remoteEntries]);
|
|
421102
|
-
return [hubEntry, ...remoteEntries];
|
|
421103
421656
|
}
|
|
421104
421657
|
/**
|
|
421105
|
-
*
|
|
421106
|
-
*
|
|
421107
|
-
* `
|
|
421658
|
+
* One online agent's row: `$agent.status` for the descriptor + live metrics,
|
|
421659
|
+
* `$process.list` for real sub-process stats. `null` when the node has no
|
|
421660
|
+
* `$agent` service (it is then simply absent from the list, as before).
|
|
421661
|
+
*
|
|
421662
|
+
* The two calls are ONE wave, not two: `$process.list` never reads anything
|
|
421663
|
+
* from `$agent.status` — only its FALLBACK does, and the fallback is applied
|
|
421664
|
+
* after both have settled.
|
|
421665
|
+
*/
|
|
421666
|
+
async buildRemoteEntry(nodeId) {
|
|
421667
|
+
const [statusResult, processResult] = await Promise.allSettled([
|
|
421668
|
+
this.broker.call("$agent.status", {}, { nodeID: nodeId, timeout: 5e3 }),
|
|
421669
|
+
this.broker.call("$process.list", {}, { nodeID: nodeId, timeout: 5e3 })
|
|
421670
|
+
]);
|
|
421671
|
+
if (statusResult.status === "rejected")
|
|
421672
|
+
return null;
|
|
421673
|
+
const status = statusResult.value;
|
|
421674
|
+
const subProcesses = processResult.status === "fulfilled" ? processResult.value.map(toSubProcess) : (
|
|
421675
|
+
// Fall back to the addon list from $agent.status (no stats)
|
|
421676
|
+
status.addons?.map((a) => ({
|
|
421677
|
+
pid: 0,
|
|
421678
|
+
name: a.id ?? "",
|
|
421679
|
+
command: "moleculer-service",
|
|
421680
|
+
state: a.status ?? "running",
|
|
421681
|
+
cpuPercent: 0,
|
|
421682
|
+
memoryRss: 0,
|
|
421683
|
+
uptimeSeconds: 0
|
|
421684
|
+
})) ?? []
|
|
421685
|
+
);
|
|
421686
|
+
const agentAddons = status.addons?.map((a) => a.id) ?? [];
|
|
421687
|
+
const hostname = typeof status.hostname === "string" ? status.hostname : null;
|
|
421688
|
+
const agentName = typeof status.name === "string" ? status.name : nodeId;
|
|
421689
|
+
return {
|
|
421690
|
+
info: {
|
|
421691
|
+
id: nodeId,
|
|
421692
|
+
name: agentName,
|
|
421693
|
+
hostname: hostname ?? nodeId,
|
|
421694
|
+
capabilities: [],
|
|
421695
|
+
platform: status.platform ?? "unknown",
|
|
421696
|
+
arch: status.arch ?? "unknown",
|
|
421697
|
+
cpuCores: status.cpuCores ?? 0,
|
|
421698
|
+
memoryMB: status.totalMemoryMB ?? 0,
|
|
421699
|
+
cpuModel: status.cpuModel
|
|
421700
|
+
},
|
|
421701
|
+
localIps: Array.isArray(status.localIps) ? status.localIps : [],
|
|
421702
|
+
status: {
|
|
421703
|
+
activeCameras: 0,
|
|
421704
|
+
cpuPercent: status.cpuPercent ?? 0,
|
|
421705
|
+
memoryPercent: status.memoryPercent ?? 0,
|
|
421706
|
+
fps: {},
|
|
421707
|
+
errors: []
|
|
421708
|
+
},
|
|
421709
|
+
connectedSince: typeof status.uptime === "number" ? Date.now() - status.uptime * 1e3 : Date.now(),
|
|
421710
|
+
isHub: false,
|
|
421711
|
+
subProcesses,
|
|
421712
|
+
agentAddons
|
|
421713
|
+
};
|
|
421714
|
+
}
|
|
421715
|
+
/**
|
|
421716
|
+
* A1 (R2 capture point): snapshot every ONLINE node's static descriptor +
|
|
421717
|
+
* last-known addon roster into the durable, routing-blind history store.
|
|
421718
|
+
* This is the ONLY place cpuModel/cores/memory/localIps are resolved from a
|
|
421719
|
+
* live `$agent.status`, so it is where an offline row's descriptor must be
|
|
421720
|
+
* captured while the node is still reachable. Offline entries are NOT
|
|
421721
|
+
* re-snapshotted — their `lastActive` is stamped on `$node.disconnected`
|
|
421722
|
+
* instead. This is a separate durable store, never a `knownAgents`-style
|
|
421723
|
+
* shadow of `HubNodeRegistry` (which stays the ephemeral live cap authority).
|
|
421724
|
+
*
|
|
421725
|
+
* **It belongs to the PERIODIC PASS, not to a read** (D317). It used to run
|
|
421726
|
+
* at the tail of `listNodes()`, which made every operator poll of
|
|
421727
|
+
* `nodes.topology` perform one durable read-back — and, past the five-minute
|
|
421728
|
+
* heartbeat, one durable write — per online node, in a phase that had to
|
|
421729
|
+
* finish before the history read could even start. Measured on the live hub
|
|
421730
|
+
* on 2026-08-31: one settings-store round trip cost 14.8–18.3 s and
|
|
421731
|
+
* `nodes.topology` cost exactly two of them, 30.5 s. `TopologyEmitterService`
|
|
421732
|
+
* already recomputes this picture every 30 s; the capture is its work.
|
|
421733
|
+
*
|
|
421734
|
+
* Never throws — the store swallows its own errors and this awaits
|
|
421735
|
+
* `allSettled` so a storage hiccup can never fail the pass.
|
|
421108
421736
|
*/
|
|
421109
|
-
async
|
|
421737
|
+
async captureNodeHistory(entries) {
|
|
421110
421738
|
if (!this.historyStore)
|
|
421111
421739
|
return;
|
|
421112
421740
|
const online = entries.filter((e) => e.isOnline !== false);
|
|
@@ -423756,7 +424384,7 @@ var require_topology_emitter_service = __commonJS({
|
|
|
423756
424384
|
return;
|
|
423757
424385
|
this.emitting = true;
|
|
423758
424386
|
try {
|
|
423759
|
-
const nodes = await (0, cap_providers_1.
|
|
424387
|
+
const { nodes, liveNodes } = await (0, cap_providers_1.computeTopologyPass)(this.agentRegistry, this.addonRegistry, this.getNodeRootPackage);
|
|
423760
424388
|
this.eventBus.emit({
|
|
423761
424389
|
id: (0, node_crypto_1.randomUUID)(),
|
|
423762
424390
|
timestamp: /* @__PURE__ */ new Date(),
|
|
@@ -423764,6 +424392,7 @@ var require_topology_emitter_service = __commonJS({
|
|
|
423764
424392
|
category: types_1.EventCategory.ClusterTopologySnapshot,
|
|
423765
424393
|
data: { nodes, timestamp: Date.now() }
|
|
423766
424394
|
});
|
|
424395
|
+
await this.agentRegistry.captureNodeHistory(liveNodes);
|
|
423767
424396
|
} catch {
|
|
423768
424397
|
} finally {
|
|
423769
424398
|
this.emitting = false;
|