@camstack/addon-remote-storage 1.2.46 → 1.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/s3.addon.js +1 -1
- package/dist/s3.addon.mjs +1 -1
- package/dist/sftp.addon.js +1 -1
- package/dist/sftp.addon.mjs +1 -1
- package/dist/{shared-DAxSJcnX.js → shared-Bwt_Ye8T.js} +290 -4
- package/dist/{shared-hUiD7Ohg.mjs → shared-CQEWmUcA.mjs} +290 -4
- package/dist/smb.addon.js +1 -1
- package/dist/smb.addon.mjs +1 -1
- package/dist/webdav.addon.js +1 -1
- package/dist/webdav.addon.mjs +1 -1
- package/package.json +1 -1
package/dist/s3.addon.js
CHANGED
|
@@ -2,7 +2,7 @@ Object.defineProperties(exports, {
|
|
|
2
2
|
__esModule: { value: true },
|
|
3
3
|
[Symbol.toStringTag]: { value: "Module" }
|
|
4
4
|
});
|
|
5
|
-
const require_shared = require("./shared-
|
|
5
|
+
const require_shared = require("./shared-Bwt_Ye8T.js");
|
|
6
6
|
let node_stream = require("node:stream");
|
|
7
7
|
let _aws_sdk_client_s3 = require("@aws-sdk/client-s3");
|
|
8
8
|
let _aws_sdk_lib_storage = require("@aws-sdk/lib-storage");
|
package/dist/s3.addon.mjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { c as BaseAddon, i as rearmIdleAbort, n as getOptionalBasePath, o as scheduleIdleAbort, s as storageProviderCapability, t as createSessionId } from "./shared-
|
|
1
|
+
import { c as BaseAddon, i as rearmIdleAbort, n as getOptionalBasePath, o as scheduleIdleAbort, s as storageProviderCapability, t as createSessionId } from "./shared-CQEWmUcA.mjs";
|
|
2
2
|
import { PassThrough } from "node:stream";
|
|
3
3
|
import { DeleteObjectCommand, GetObjectCommand, HeadBucketCommand, HeadObjectCommand, ListObjectsV2Command, PutObjectCommand, S3Client } from "@aws-sdk/client-s3";
|
|
4
4
|
import { Upload } from "@aws-sdk/lib-storage";
|
package/dist/sftp.addon.js
CHANGED
|
@@ -2,7 +2,7 @@ Object.defineProperties(exports, {
|
|
|
2
2
|
__esModule: { value: true },
|
|
3
3
|
[Symbol.toStringTag]: { value: "Module" }
|
|
4
4
|
});
|
|
5
|
-
const require_shared = require("./shared-
|
|
5
|
+
const require_shared = require("./shared-Bwt_Ye8T.js");
|
|
6
6
|
let ssh2 = require("ssh2");
|
|
7
7
|
let node_path = require("node:path");
|
|
8
8
|
node_path = require_shared.__toESM(node_path);
|
package/dist/sftp.addon.mjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { a as safeJoinRemotePath, c as BaseAddon, i as rearmIdleAbort, o as scheduleIdleAbort, r as getRequiredBasePath, s as storageProviderCapability, t as createSessionId } from "./shared-
|
|
1
|
+
import { a as safeJoinRemotePath, c as BaseAddon, i as rearmIdleAbort, o as scheduleIdleAbort, r as getRequiredBasePath, s as storageProviderCapability, t as createSessionId } from "./shared-CQEWmUcA.mjs";
|
|
2
2
|
import { Client } from "ssh2";
|
|
3
3
|
import * as path from "node:path";
|
|
4
4
|
//#region src/providers/sftp/sftp-config-schema.ts
|
|
@@ -8026,6 +8026,20 @@ var RelocateJobSchema = object({
|
|
|
8026
8026
|
* in its row, not in its name, so `MediaRelocateEngine` never reconciles one.
|
|
8027
8027
|
*/
|
|
8028
8028
|
rowsReconciled: number().int().nonnegative().optional(),
|
|
8029
|
+
/**
|
|
8030
|
+
* Rows this run FORGOT because the file they name is not on disk.
|
|
8031
|
+
*
|
|
8032
|
+
* The mover derived the path from the row's own fields and `stat`ed it; an
|
|
8033
|
+
* ENOENT there is a per-path confirmation that the segment is gone (D296),
|
|
8034
|
+
* and the durable row is dropped through the same channel eviction uses. It
|
|
8035
|
+
* is reported for the same reason `rowsReconciled` is: this is a durable
|
|
8036
|
+
* mutation nobody asked for, and a migration that quietly erases hour rows is
|
|
8037
|
+
* the same failure as one that quietly skips them (D295).
|
|
8038
|
+
*
|
|
8039
|
+
* The production drain of 2026-08-30 would have reported 11 074 here — the
|
|
8040
|
+
* ledger claimed 5.65 GB of footage that no longer existed.
|
|
8041
|
+
*/
|
|
8042
|
+
rowsForgotten: number().int().nonnegative().optional(),
|
|
8029
8043
|
startedAt: number(),
|
|
8030
8044
|
finishedAt: number().nullable(),
|
|
8031
8045
|
error: string().nullable()
|
|
@@ -8389,6 +8403,91 @@ var RelocateResidueSchema = object({
|
|
|
8389
8403
|
segments: number().int().nonnegative(),
|
|
8390
8404
|
bytes: number().int().nonnegative()
|
|
8391
8405
|
}).nullable();
|
|
8406
|
+
/**
|
|
8407
|
+
* Ask one location whether its durable hour rows describe the disk — the walk
|
|
8408
|
+
* (D319).
|
|
8409
|
+
*
|
|
8410
|
+
* `apply` DEFAULTS TO FALSE and that default is the product: the operator's
|
|
8411
|
+
* missing tool is the question, and the dry run is how they sanity-check the
|
|
8412
|
+
* destructive run before authorising it.
|
|
8413
|
+
*/
|
|
8414
|
+
var LedgerWalkInputSchema = object({
|
|
8415
|
+
locationId: string().min(1),
|
|
8416
|
+
/** Forget the confirmed-absent rows, rather than only counting them. */
|
|
8417
|
+
apply: boolean().optional(),
|
|
8418
|
+
/** Narrow to one camera. */
|
|
8419
|
+
deviceId: number().int().positive().optional(),
|
|
8420
|
+
/** Narrow to these recording profiles; empty/absent = every profile. */
|
|
8421
|
+
profiles: array(string().min(1)).optional()
|
|
8422
|
+
});
|
|
8423
|
+
/** Why a whole walk did nothing. Every one leaves the ledger untouched. */
|
|
8424
|
+
var LedgerWalkRefusalSchema = _enum([
|
|
8425
|
+
"location-unknown",
|
|
8426
|
+
"source-writable",
|
|
8427
|
+
"no-ledger",
|
|
8428
|
+
"archive-unreadable",
|
|
8429
|
+
"anchor-absent",
|
|
8430
|
+
"anchor-unreadable",
|
|
8431
|
+
"anchor-moved"
|
|
8432
|
+
]);
|
|
8433
|
+
_enum([
|
|
8434
|
+
"live-tail",
|
|
8435
|
+
"listing-error",
|
|
8436
|
+
"path-mismatch",
|
|
8437
|
+
"durable-refused"
|
|
8438
|
+
]);
|
|
8439
|
+
/** Every skip reason, always present, always a number — so a reason that never
|
|
8440
|
+
* fired reports as zero rather than absent and the report shape is constant
|
|
8441
|
+
* between passes. Spelled out rather than `z.record` for exactly that. */
|
|
8442
|
+
var LedgerWalkSkipCountsSchema = object({
|
|
8443
|
+
"live-tail": number().int().nonnegative(),
|
|
8444
|
+
"listing-error": number().int().nonnegative(),
|
|
8445
|
+
"path-mismatch": number().int().nonnegative(),
|
|
8446
|
+
"durable-refused": number().int().nonnegative()
|
|
8447
|
+
});
|
|
8448
|
+
/** One camera's share of a walk, so a report names cameras and not rows. */
|
|
8449
|
+
var LedgerWalkDeviceReportSchema = object({
|
|
8450
|
+
deviceId: number().int(),
|
|
8451
|
+
hoursWalked: number().int().nonnegative(),
|
|
8452
|
+
hoursMissing: number().int().nonnegative(),
|
|
8453
|
+
ghostSegments: number().int().nonnegative(),
|
|
8454
|
+
ghostBytes: number().int().nonnegative(),
|
|
8455
|
+
forgottenSegments: number().int().nonnegative(),
|
|
8456
|
+
orphanFiles: number().int().nonnegative()
|
|
8457
|
+
});
|
|
8458
|
+
/**
|
|
8459
|
+
* What one walk claimed, listed, found and (only when armed) forgot.
|
|
8460
|
+
*
|
|
8461
|
+
* `archiveSegments` is the **M** and `segmentsClaimed` the **N** (D295), so a
|
|
8462
|
+
* walk that saw a fraction of the location is visible in its own report rather
|
|
8463
|
+
* than in the absence of one.
|
|
8464
|
+
*/
|
|
8465
|
+
var LedgerWalkReportSchema = object({
|
|
8466
|
+
locationId: string(),
|
|
8467
|
+
applied: boolean(),
|
|
8468
|
+
refused: LedgerWalkRefusalSchema.nullable(),
|
|
8469
|
+
archiveSegments: number().int().nonnegative().nullable(),
|
|
8470
|
+
archiveBytes: number().int().nonnegative().nullable(),
|
|
8471
|
+
hoursClaimed: number().int().nonnegative(),
|
|
8472
|
+
hoursWalked: number().int().nonnegative(),
|
|
8473
|
+
hoursMissing: number().int().nonnegative(),
|
|
8474
|
+
/** `readdir` calls issued — the cost, stated in the unit that is paid. */
|
|
8475
|
+
listings: number().int().nonnegative(),
|
|
8476
|
+
segmentsClaimed: number().int().nonnegative(),
|
|
8477
|
+
ghostSegments: number().int().nonnegative(),
|
|
8478
|
+
ghostBytes: number().int().nonnegative(),
|
|
8479
|
+
ghostHoursWhole: number().int().nonnegative(),
|
|
8480
|
+
forgottenSegments: number().int().nonnegative(),
|
|
8481
|
+
forgottenBytes: number().int().nonnegative(),
|
|
8482
|
+
/** Files under a claimed hour that no durable row names. Never deleted. */
|
|
8483
|
+
orphanFiles: number().int().nonnegative(),
|
|
8484
|
+
orphanSample: array(string()).readonly(),
|
|
8485
|
+
hoursSkipped: number().int().nonnegative(),
|
|
8486
|
+
skippedByReason: LedgerWalkSkipCountsSchema,
|
|
8487
|
+
/** The walk stopped at its per-pass hour bound with claims unwalked. */
|
|
8488
|
+
bounded: boolean(),
|
|
8489
|
+
byDevice: array(LedgerWalkDeviceReportSchema).readonly()
|
|
8490
|
+
});
|
|
8392
8491
|
/** How many rows a media pass would still act on against a given target — the
|
|
8393
8492
|
* media lane's denominator AND its residue, from ONE derivation so the two can
|
|
8394
8493
|
* never disagree. `null` = the count could not be taken. */
|
|
@@ -18662,13 +18761,15 @@ var ListGroupsPageSchema = object({
|
|
|
18662
18761
|
groups: array(AnalyticsGroupRecordSchema).readonly(),
|
|
18663
18762
|
nextCursor: string().nullable()
|
|
18664
18763
|
});
|
|
18764
|
+
var KEY_EVENTS_DEFAULT_LIMIT = 50;
|
|
18765
|
+
var KEY_EVENTS_MAX_LIMIT = 200;
|
|
18665
18766
|
var KeyEventQueryInput = object({
|
|
18666
18767
|
deviceId: number(),
|
|
18667
18768
|
/** Window lower bound (track firstSeen ≥ since). */
|
|
18668
18769
|
since: number(),
|
|
18669
18770
|
/** Window upper bound (track firstSeen ≤ until). */
|
|
18670
18771
|
until: number(),
|
|
18671
|
-
limit: number().int().min(1).max(
|
|
18772
|
+
limit: number().int().min(1).max(KEY_EVENTS_MAX_LIMIT).default(KEY_EVENTS_DEFAULT_LIMIT),
|
|
18672
18773
|
/** Drop tracks scoring below this importance. */
|
|
18673
18774
|
minImportance: number().min(0).max(1).optional(),
|
|
18674
18775
|
/** Restrict to a single class (e.g. 'person'). */
|
|
@@ -18690,6 +18791,32 @@ var KeyEventSchema = object({
|
|
|
18690
18791
|
...TrackFlagFields,
|
|
18691
18792
|
...TrackRetrainFields
|
|
18692
18793
|
});
|
|
18794
|
+
/** `getKeyEvents`' window and filters, asked of a SET of cameras at once. */
|
|
18795
|
+
var KeyEventBatchQueryInput = object({
|
|
18796
|
+
deviceIds: array(number()).min(1).max(200),
|
|
18797
|
+
since: number(),
|
|
18798
|
+
until: number(),
|
|
18799
|
+
/** Applied PER CAMERA, exactly as `getKeyEvents.limit` is — never a total
|
|
18800
|
+
* across the set, which would let a busy camera starve a quiet one of its
|
|
18801
|
+
* rows and change what the merged feed contains. */
|
|
18802
|
+
limit: number().int().min(1).max(KEY_EVENTS_MAX_LIMIT).default(KEY_EVENTS_DEFAULT_LIMIT),
|
|
18803
|
+
minImportance: number().min(0).max(1).optional(),
|
|
18804
|
+
classFilter: string().optional()
|
|
18805
|
+
});
|
|
18806
|
+
/**
|
|
18807
|
+
* One camera's key events in a batch answer.
|
|
18808
|
+
*
|
|
18809
|
+
* The row exists for every requested id. `getKeyEvents` degrades to `[]` on
|
|
18810
|
+
* error rather than throwing, so a camera whose store read failed and one with
|
|
18811
|
+
* no events in the window were ALREADY indistinguishable per camera — the
|
|
18812
|
+
* batch does not make that worse, and the row keeps the deviceId the single
|
|
18813
|
+
* method's output never carried (the caller used to stamp it from the fan-out
|
|
18814
|
+
* key, which only worked because there was one query per camera).
|
|
18815
|
+
*/
|
|
18816
|
+
var KeyEventsForDeviceSchema = object({
|
|
18817
|
+
deviceId: number(),
|
|
18818
|
+
events: array(KeyEventSchema).readonly()
|
|
18819
|
+
});
|
|
18693
18820
|
object({
|
|
18694
18821
|
trackId: string(),
|
|
18695
18822
|
className: string(),
|
|
@@ -18761,6 +18888,50 @@ var EventStoreFootprintSchema = object({
|
|
|
18761
18888
|
totalBytes: number().int(),
|
|
18762
18889
|
devices: array(EventStoreDeviceFootprintSchema).readonly()
|
|
18763
18890
|
});
|
|
18891
|
+
/** Event-media footprint for one {@link MediaFileKind}. */
|
|
18892
|
+
var EventMediaKindFootprintSchema = object({
|
|
18893
|
+
kind: MediaFileKindEnum,
|
|
18894
|
+
/** Media rows of this kind. */
|
|
18895
|
+
rows: number().int(),
|
|
18896
|
+
/** Bytes on disk held by those rows. */
|
|
18897
|
+
bytes: number().int()
|
|
18898
|
+
});
|
|
18899
|
+
/**
|
|
18900
|
+
* The media footprint broken down by KIND — the axis a deletion decision
|
|
18901
|
+
* actually turns on.
|
|
18902
|
+
*
|
|
18903
|
+
* A byte total says how much there is; it cannot say what is safe to remove.
|
|
18904
|
+
* The deletable set (the periodic `snapshot` filmstrip, the surplus per-edge
|
|
18905
|
+
* motion stills) and the keep set (`firstFrame`, rolling `lastFrame`,
|
|
18906
|
+
* `thumbnail`/`thumbnailSmall`, `keyFrame`/`keyFrameSmall`, the face/plate
|
|
18907
|
+
* buffers, gallery media, the CLIP `crop`) are distinguished by `kind` and by
|
|
18908
|
+
* nothing else, so sizing a deletion means summing per kind.
|
|
18909
|
+
*
|
|
18910
|
+
* ## Why `unaccounted*` exists
|
|
18911
|
+
*
|
|
18912
|
+
* `kinds` is enumerated from {@link MediaFileKindEnum} — the closed set the
|
|
18913
|
+
* writers use — and summed one kind at a time. `totalRows` / `totalBytes` come
|
|
18914
|
+
* from a SEPARATE unfiltered aggregate over the same rows, never from adding
|
|
18915
|
+
* `kinds` up. A row whose stored `kind` is not in the enum (written by a
|
|
18916
|
+
* retired code path, or by a version that knew a kind this one does not) would
|
|
18917
|
+
* otherwise vanish from the total silently, and an operator would delete
|
|
18918
|
+
* against a denominator smaller than the disk.
|
|
18919
|
+
*
|
|
18920
|
+
* `unaccountedRows` / `unaccountedBytes` are the difference. They are normally
|
|
18921
|
+
* zero; a non-zero value is a real finding and must be shown, not rounded away.
|
|
18922
|
+
*/
|
|
18923
|
+
var EventMediaKindBreakdownSchema = object({
|
|
18924
|
+
/** Every media row in scope, from one unfiltered aggregate. */
|
|
18925
|
+
totalRows: number().int(),
|
|
18926
|
+
/** Every media byte in scope, from that same aggregate. */
|
|
18927
|
+
totalBytes: number().int(),
|
|
18928
|
+
/** Per-kind footprint, ordered by bytes descending. */
|
|
18929
|
+
kinds: array(EventMediaKindFootprintSchema).readonly(),
|
|
18930
|
+
/** `totalRows` minus the summed `kinds` rows — see the schema note. */
|
|
18931
|
+
unaccountedRows: number().int(),
|
|
18932
|
+
/** `totalBytes` minus the summed `kinds` bytes — see the schema note. */
|
|
18933
|
+
unaccountedBytes: number().int()
|
|
18934
|
+
});
|
|
18764
18935
|
/** Per-kind counts returned by the event-prune / device-delete mutations. */
|
|
18765
18936
|
var EventPruneCountsSchema = object({
|
|
18766
18937
|
motion: number().int(),
|
|
@@ -18915,7 +19086,7 @@ DeviceType.Camera, method(object({ deviceId: number() }), array(TrackSchema).rea
|
|
|
18915
19086
|
until: number().optional(),
|
|
18916
19087
|
kinds: array(string()).optional(),
|
|
18917
19088
|
limit: number().int().min(1).max(MAX_EVENT_QUERY_LIMIT).default(DEFAULT_EVENT_QUERY_LIMIT)
|
|
18918
|
-
}), array(SensorEventSchema).readonly()), method(KeyEventQueryInput, array(KeyEventSchema).readonly()), method(object({
|
|
19089
|
+
}), array(SensorEventSchema).readonly()), method(KeyEventQueryInput, array(KeyEventSchema).readonly()), method(KeyEventBatchQueryInput, array(KeyEventsForDeviceSchema).readonly()), method(object({
|
|
18919
19090
|
deviceId: number(),
|
|
18920
19091
|
since: number(),
|
|
18921
19092
|
until: number(),
|
|
@@ -18964,6 +19135,9 @@ DeviceType.Camera, method(object({ deviceId: number() }), array(TrackSchema).rea
|
|
|
18964
19135
|
}), TrackFlagsSchema, { kind: "mutation" }), method(object({}), EventStoreFootprintSchema, {
|
|
18965
19136
|
kind: "query",
|
|
18966
19137
|
auth: "admin"
|
|
19138
|
+
}), method(object({ deviceId: number().int().optional() }), EventMediaKindBreakdownSchema, {
|
|
19139
|
+
kind: "query",
|
|
19140
|
+
auth: "admin"
|
|
18967
19141
|
}), method(object({
|
|
18968
19142
|
olderThanMs: number(),
|
|
18969
19143
|
reason: OpsLogReasonSchema.optional()
|
|
@@ -20915,6 +21089,20 @@ method(object({
|
|
|
20915
21089
|
error: string().optional()
|
|
20916
21090
|
}), { auth: "admin" }), method(_void(), array(ProviderListEntrySchema).readonly()), method(object({
|
|
20917
21091
|
providerId: string(),
|
|
21092
|
+
/**
|
|
21093
|
+
* The location this config is an UNSAVED edit of, when there is one.
|
|
21094
|
+
*
|
|
21095
|
+
* `listLocations` replaces every declared secret with the redaction
|
|
21096
|
+
* sentinel, so the edit modal's form state holds the sentinel for any
|
|
21097
|
+
* credential the operator did not retype — and posting that here
|
|
21098
|
+
* without a way to resolve it makes the provider try to authenticate
|
|
21099
|
+
* as `__camstack_redacted__` and report the operator's own working
|
|
21100
|
+
* password as wrong. Given this id, the orchestrator restores each
|
|
21101
|
+
* sentinel from the stored config (same rule as `upsertLocation`)
|
|
21102
|
+
* before dispatching. Omitted by the "Add location" wizard, where
|
|
21103
|
+
* every value was typed just now and nothing is stored yet.
|
|
21104
|
+
*/
|
|
21105
|
+
locationId: string().optional(),
|
|
20918
21106
|
config: record(string(), unknown())
|
|
20919
21107
|
}), object({
|
|
20920
21108
|
ok: boolean(),
|
|
@@ -26610,6 +26798,9 @@ method(object({
|
|
|
26610
26798
|
}), method(RelocateResidueInputSchema, RelocateResidueSchema, {
|
|
26611
26799
|
kind: "query",
|
|
26612
26800
|
auth: "admin"
|
|
26801
|
+
}), method(LedgerWalkInputSchema, LedgerWalkReportSchema, {
|
|
26802
|
+
kind: "mutation",
|
|
26803
|
+
auth: "admin"
|
|
26613
26804
|
}), method(object({ jobId: string() }), object({ cancelled: boolean() }), {
|
|
26614
26805
|
kind: "mutation",
|
|
26615
26806
|
auth: "admin"
|
|
@@ -27001,7 +27192,26 @@ var SceneMonitorStatusSchema = object({
|
|
|
27001
27192
|
monitors: array(SceneMonitorSchema),
|
|
27002
27193
|
lastFetchedAt: number()
|
|
27003
27194
|
});
|
|
27004
|
-
|
|
27195
|
+
/**
|
|
27196
|
+
* One camera's row in a `listScenesBatch` answer.
|
|
27197
|
+
*
|
|
27198
|
+
* `status` is NULLABLE and the nullability is the whole point. `scene-monitor`
|
|
27199
|
+
* is a `defaultActive` wrapper, so every camera is asked; a camera whose
|
|
27200
|
+
* provider is absent (pipeline-analytics not deployed, the post-processing node
|
|
27201
|
+
* down) cannot answer, and that is not the same fact as a camera with no scenes
|
|
27202
|
+
* configured. Fanned out per camera the difference was visible — one query
|
|
27203
|
+
* errored while the others resolved — and a batch that returned only the rows
|
|
27204
|
+
* it managed would have destroyed it, silently, by making an unreachable camera
|
|
27205
|
+
* indistinguishable from one that answered `monitors: []`.
|
|
27206
|
+
*
|
|
27207
|
+
* So: EVERY requested deviceId gets a row. `status: null` means "this camera
|
|
27208
|
+
* could not be read"; `status.monitors: []` means "read, and it has none".
|
|
27209
|
+
*/
|
|
27210
|
+
var SceneMonitorStatusForDeviceSchema = object({
|
|
27211
|
+
deviceId: number(),
|
|
27212
|
+
status: SceneMonitorStatusSchema.nullable()
|
|
27213
|
+
});
|
|
27214
|
+
DeviceType.Camera, method(object({ deviceId: number() }), SceneMonitorStatusSchema), method(object({ deviceIds: array(number()).min(1).max(200) }), array(SceneMonitorStatusForDeviceSchema).readonly()), method(object({
|
|
27005
27215
|
deviceId: number(),
|
|
27006
27216
|
label: string(),
|
|
27007
27217
|
roi: MaskRectShapeSchema,
|
|
@@ -28325,6 +28535,27 @@ var CameraOccupancySnapshotSchema = object({
|
|
|
28325
28535
|
stationaryObjects: array(StationaryObjectSchema).readonly().optional()
|
|
28326
28536
|
});
|
|
28327
28537
|
/**
|
|
28538
|
+
* One camera's row in a `getCurrentSnapshotBatch` answer.
|
|
28539
|
+
*
|
|
28540
|
+
* THREE outcomes, and the single-camera method could only express two of them
|
|
28541
|
+
* because `snapshot: null` was already spoken for:
|
|
28542
|
+
*
|
|
28543
|
+
* - `read: 'read'`, `snapshot` present — the live occupancy reading.
|
|
28544
|
+
* - `read: 'read'`, `snapshot: null` — read, and this camera has no reading
|
|
28545
|
+
* yet: no frame since boot, and no parked-object registry to hydrate from.
|
|
28546
|
+
* - `read: 'unreadable'` — the owner could not answer for this
|
|
28547
|
+
* camera. `snapshot` is null, and it does NOT mean "nothing parked here".
|
|
28548
|
+
*
|
|
28549
|
+
* Collapsing the last two is the failure this field exists to prevent: a
|
|
28550
|
+
* hydration that threw would otherwise render as an empty Stationary section,
|
|
28551
|
+
* which is a definite claim about a camera nobody could read.
|
|
28552
|
+
*/
|
|
28553
|
+
var CameraOccupancySnapshotForDeviceSchema = object({
|
|
28554
|
+
deviceId: number(),
|
|
28555
|
+
read: _enum(["read", "unreadable"]),
|
|
28556
|
+
snapshot: CameraOccupancySnapshotSchema.nullable()
|
|
28557
|
+
});
|
|
28558
|
+
/**
|
|
28328
28559
|
* Time-series resolution. The history methods return one bucket per
|
|
28329
28560
|
* step over the requested range. Smaller resolutions cost more
|
|
28330
28561
|
* memory + bandwidth; bound to discrete steps so caller cannot ask
|
|
@@ -28348,7 +28579,7 @@ var HistoryPointSchema = object({
|
|
|
28348
28579
|
/** Object count averaged over the bucket (rounded to nearest integer). */
|
|
28349
28580
|
count: number().int().nonnegative()
|
|
28350
28581
|
});
|
|
28351
|
-
DeviceType.Camera, method(object({ deviceId: number() }), CameraOccupancySnapshotSchema.nullable()), method(object({
|
|
28582
|
+
DeviceType.Camera, method(object({ deviceId: number() }), CameraOccupancySnapshotSchema.nullable()), method(object({ deviceIds: array(number()).min(1).max(200) }), array(CameraOccupancySnapshotForDeviceSchema).readonly()), method(object({
|
|
28352
28583
|
deviceId: number(),
|
|
28353
28584
|
zoneId: string(),
|
|
28354
28585
|
className: string().optional()
|
|
@@ -31629,6 +31860,12 @@ Object.freeze({
|
|
|
31629
31860
|
addonId: null,
|
|
31630
31861
|
access: "view"
|
|
31631
31862
|
},
|
|
31863
|
+
"pipelineAnalytics.getEventMediaFootprintByKind": {
|
|
31864
|
+
capName: "pipeline-analytics",
|
|
31865
|
+
capScope: "device",
|
|
31866
|
+
addonId: null,
|
|
31867
|
+
access: "view"
|
|
31868
|
+
},
|
|
31632
31869
|
"pipelineAnalytics.getEventStoreFootprint": {
|
|
31633
31870
|
capName: "pipeline-analytics",
|
|
31634
31871
|
capScope: "device",
|
|
@@ -31647,6 +31884,12 @@ Object.freeze({
|
|
|
31647
31884
|
addonId: null,
|
|
31648
31885
|
access: "view"
|
|
31649
31886
|
},
|
|
31887
|
+
"pipelineAnalytics.getKeyEventsBatch": {
|
|
31888
|
+
capName: "pipeline-analytics",
|
|
31889
|
+
capScope: "device",
|
|
31890
|
+
addonId: null,
|
|
31891
|
+
access: "view"
|
|
31892
|
+
},
|
|
31650
31893
|
"pipelineAnalytics.getMotionEvents": {
|
|
31651
31894
|
capName: "pipeline-analytics",
|
|
31652
31895
|
capScope: "device",
|
|
@@ -32823,6 +33066,12 @@ Object.freeze({
|
|
|
32823
33066
|
addonId: null,
|
|
32824
33067
|
access: "view"
|
|
32825
33068
|
},
|
|
33069
|
+
"recording.reconcileLedgerAgainstDisk": {
|
|
33070
|
+
capName: "recording",
|
|
33071
|
+
capScope: "system",
|
|
33072
|
+
addonId: null,
|
|
33073
|
+
access: "create"
|
|
33074
|
+
},
|
|
32826
33075
|
"recording.refreshStorageLocationsForMigration": {
|
|
32827
33076
|
capName: "recording",
|
|
32828
33077
|
capScope: "system",
|
|
@@ -32949,6 +33198,12 @@ Object.freeze({
|
|
|
32949
33198
|
addonId: null,
|
|
32950
33199
|
access: "view"
|
|
32951
33200
|
},
|
|
33201
|
+
"sceneMonitor.listScenesBatch": {
|
|
33202
|
+
capName: "scene-monitor",
|
|
33203
|
+
capScope: "device",
|
|
33204
|
+
addonId: null,
|
|
33205
|
+
access: "view"
|
|
33206
|
+
},
|
|
32952
33207
|
"sceneMonitor.recheckNow": {
|
|
32953
33208
|
capName: "scene-monitor",
|
|
32954
33209
|
capScope: "device",
|
|
@@ -34305,6 +34560,12 @@ Object.freeze({
|
|
|
34305
34560
|
addonId: null,
|
|
34306
34561
|
access: "view"
|
|
34307
34562
|
},
|
|
34563
|
+
"zoneAnalytics.getCurrentSnapshotBatch": {
|
|
34564
|
+
capName: "zone-analytics",
|
|
34565
|
+
capScope: "device",
|
|
34566
|
+
addonId: null,
|
|
34567
|
+
access: "view"
|
|
34568
|
+
},
|
|
34308
34569
|
"zoneAnalytics.getUnzonedHistory": {
|
|
34309
34570
|
capName: "zone-analytics",
|
|
34310
34571
|
capScope: "device",
|
|
@@ -35294,6 +35555,11 @@ Object.freeze({
|
|
|
35294
35555
|
form: "single",
|
|
35295
35556
|
optional: false
|
|
35296
35557
|
}],
|
|
35558
|
+
"pipelineAnalytics.getEventMediaFootprintByKind": [{
|
|
35559
|
+
name: "deviceId",
|
|
35560
|
+
form: "single",
|
|
35561
|
+
optional: true
|
|
35562
|
+
}],
|
|
35297
35563
|
"pipelineAnalytics.getGroup": [{
|
|
35298
35564
|
name: "deviceId",
|
|
35299
35565
|
form: "single",
|
|
@@ -35304,6 +35570,11 @@ Object.freeze({
|
|
|
35304
35570
|
form: "single",
|
|
35305
35571
|
optional: false
|
|
35306
35572
|
}],
|
|
35573
|
+
"pipelineAnalytics.getKeyEventsBatch": [{
|
|
35574
|
+
name: "deviceIds",
|
|
35575
|
+
form: "array",
|
|
35576
|
+
optional: false
|
|
35577
|
+
}],
|
|
35307
35578
|
"pipelineAnalytics.getMotionEvents": [{
|
|
35308
35579
|
name: "deviceId",
|
|
35309
35580
|
form: "single",
|
|
@@ -35744,6 +36015,11 @@ Object.freeze({
|
|
|
35744
36015
|
form: "single",
|
|
35745
36016
|
optional: false
|
|
35746
36017
|
}],
|
|
36018
|
+
"recording.reconcileLedgerAgainstDisk": [{
|
|
36019
|
+
name: "deviceId",
|
|
36020
|
+
form: "single",
|
|
36021
|
+
optional: true
|
|
36022
|
+
}],
|
|
35747
36023
|
"recording.relocateFootage": [{
|
|
35748
36024
|
name: "deviceId",
|
|
35749
36025
|
form: "single",
|
|
@@ -35809,6 +36085,11 @@ Object.freeze({
|
|
|
35809
36085
|
form: "single",
|
|
35810
36086
|
optional: false
|
|
35811
36087
|
}],
|
|
36088
|
+
"sceneMonitor.listScenesBatch": [{
|
|
36089
|
+
name: "deviceIds",
|
|
36090
|
+
form: "array",
|
|
36091
|
+
optional: false
|
|
36092
|
+
}],
|
|
35812
36093
|
"sceneMonitor.recheckNow": [{
|
|
35813
36094
|
name: "deviceId",
|
|
35814
36095
|
form: "single",
|
|
@@ -36070,6 +36351,11 @@ Object.freeze({
|
|
|
36070
36351
|
form: "single",
|
|
36071
36352
|
optional: false
|
|
36072
36353
|
}],
|
|
36354
|
+
"zoneAnalytics.getCurrentSnapshotBatch": [{
|
|
36355
|
+
name: "deviceIds",
|
|
36356
|
+
form: "array",
|
|
36357
|
+
optional: false
|
|
36358
|
+
}],
|
|
36073
36359
|
"zoneAnalytics.getUnzonedHistory": [{
|
|
36074
36360
|
name: "deviceId",
|
|
36075
36361
|
form: "single",
|
|
@@ -8003,6 +8003,20 @@ var RelocateJobSchema = object({
|
|
|
8003
8003
|
* in its row, not in its name, so `MediaRelocateEngine` never reconciles one.
|
|
8004
8004
|
*/
|
|
8005
8005
|
rowsReconciled: number().int().nonnegative().optional(),
|
|
8006
|
+
/**
|
|
8007
|
+
* Rows this run FORGOT because the file they name is not on disk.
|
|
8008
|
+
*
|
|
8009
|
+
* The mover derived the path from the row's own fields and `stat`ed it; an
|
|
8010
|
+
* ENOENT there is a per-path confirmation that the segment is gone (D296),
|
|
8011
|
+
* and the durable row is dropped through the same channel eviction uses. It
|
|
8012
|
+
* is reported for the same reason `rowsReconciled` is: this is a durable
|
|
8013
|
+
* mutation nobody asked for, and a migration that quietly erases hour rows is
|
|
8014
|
+
* the same failure as one that quietly skips them (D295).
|
|
8015
|
+
*
|
|
8016
|
+
* The production drain of 2026-08-30 would have reported 11 074 here — the
|
|
8017
|
+
* ledger claimed 5.65 GB of footage that no longer existed.
|
|
8018
|
+
*/
|
|
8019
|
+
rowsForgotten: number().int().nonnegative().optional(),
|
|
8006
8020
|
startedAt: number(),
|
|
8007
8021
|
finishedAt: number().nullable(),
|
|
8008
8022
|
error: string().nullable()
|
|
@@ -8366,6 +8380,91 @@ var RelocateResidueSchema = object({
|
|
|
8366
8380
|
segments: number().int().nonnegative(),
|
|
8367
8381
|
bytes: number().int().nonnegative()
|
|
8368
8382
|
}).nullable();
|
|
8383
|
+
/**
|
|
8384
|
+
* Ask one location whether its durable hour rows describe the disk — the walk
|
|
8385
|
+
* (D319).
|
|
8386
|
+
*
|
|
8387
|
+
* `apply` DEFAULTS TO FALSE and that default is the product: the operator's
|
|
8388
|
+
* missing tool is the question, and the dry run is how they sanity-check the
|
|
8389
|
+
* destructive run before authorising it.
|
|
8390
|
+
*/
|
|
8391
|
+
var LedgerWalkInputSchema = object({
|
|
8392
|
+
locationId: string().min(1),
|
|
8393
|
+
/** Forget the confirmed-absent rows, rather than only counting them. */
|
|
8394
|
+
apply: boolean().optional(),
|
|
8395
|
+
/** Narrow to one camera. */
|
|
8396
|
+
deviceId: number().int().positive().optional(),
|
|
8397
|
+
/** Narrow to these recording profiles; empty/absent = every profile. */
|
|
8398
|
+
profiles: array(string().min(1)).optional()
|
|
8399
|
+
});
|
|
8400
|
+
/** Why a whole walk did nothing. Every one leaves the ledger untouched. */
|
|
8401
|
+
var LedgerWalkRefusalSchema = _enum([
|
|
8402
|
+
"location-unknown",
|
|
8403
|
+
"source-writable",
|
|
8404
|
+
"no-ledger",
|
|
8405
|
+
"archive-unreadable",
|
|
8406
|
+
"anchor-absent",
|
|
8407
|
+
"anchor-unreadable",
|
|
8408
|
+
"anchor-moved"
|
|
8409
|
+
]);
|
|
8410
|
+
_enum([
|
|
8411
|
+
"live-tail",
|
|
8412
|
+
"listing-error",
|
|
8413
|
+
"path-mismatch",
|
|
8414
|
+
"durable-refused"
|
|
8415
|
+
]);
|
|
8416
|
+
/** Every skip reason, always present, always a number — so a reason that never
|
|
8417
|
+
* fired reports as zero rather than absent and the report shape is constant
|
|
8418
|
+
* between passes. Spelled out rather than `z.record` for exactly that. */
|
|
8419
|
+
var LedgerWalkSkipCountsSchema = object({
|
|
8420
|
+
"live-tail": number().int().nonnegative(),
|
|
8421
|
+
"listing-error": number().int().nonnegative(),
|
|
8422
|
+
"path-mismatch": number().int().nonnegative(),
|
|
8423
|
+
"durable-refused": number().int().nonnegative()
|
|
8424
|
+
});
|
|
8425
|
+
/** One camera's share of a walk, so a report names cameras and not rows. */
|
|
8426
|
+
var LedgerWalkDeviceReportSchema = object({
|
|
8427
|
+
deviceId: number().int(),
|
|
8428
|
+
hoursWalked: number().int().nonnegative(),
|
|
8429
|
+
hoursMissing: number().int().nonnegative(),
|
|
8430
|
+
ghostSegments: number().int().nonnegative(),
|
|
8431
|
+
ghostBytes: number().int().nonnegative(),
|
|
8432
|
+
forgottenSegments: number().int().nonnegative(),
|
|
8433
|
+
orphanFiles: number().int().nonnegative()
|
|
8434
|
+
});
|
|
8435
|
+
/**
|
|
8436
|
+
* What one walk claimed, listed, found and (only when armed) forgot.
|
|
8437
|
+
*
|
|
8438
|
+
* `archiveSegments` is the **M** and `segmentsClaimed` the **N** (D295), so a
|
|
8439
|
+
* walk that saw a fraction of the location is visible in its own report rather
|
|
8440
|
+
* than in the absence of one.
|
|
8441
|
+
*/
|
|
8442
|
+
var LedgerWalkReportSchema = object({
|
|
8443
|
+
locationId: string(),
|
|
8444
|
+
applied: boolean(),
|
|
8445
|
+
refused: LedgerWalkRefusalSchema.nullable(),
|
|
8446
|
+
archiveSegments: number().int().nonnegative().nullable(),
|
|
8447
|
+
archiveBytes: number().int().nonnegative().nullable(),
|
|
8448
|
+
hoursClaimed: number().int().nonnegative(),
|
|
8449
|
+
hoursWalked: number().int().nonnegative(),
|
|
8450
|
+
hoursMissing: number().int().nonnegative(),
|
|
8451
|
+
/** `readdir` calls issued — the cost, stated in the unit that is paid. */
|
|
8452
|
+
listings: number().int().nonnegative(),
|
|
8453
|
+
segmentsClaimed: number().int().nonnegative(),
|
|
8454
|
+
ghostSegments: number().int().nonnegative(),
|
|
8455
|
+
ghostBytes: number().int().nonnegative(),
|
|
8456
|
+
ghostHoursWhole: number().int().nonnegative(),
|
|
8457
|
+
forgottenSegments: number().int().nonnegative(),
|
|
8458
|
+
forgottenBytes: number().int().nonnegative(),
|
|
8459
|
+
/** Files under a claimed hour that no durable row names. Never deleted. */
|
|
8460
|
+
orphanFiles: number().int().nonnegative(),
|
|
8461
|
+
orphanSample: array(string()).readonly(),
|
|
8462
|
+
hoursSkipped: number().int().nonnegative(),
|
|
8463
|
+
skippedByReason: LedgerWalkSkipCountsSchema,
|
|
8464
|
+
/** The walk stopped at its per-pass hour bound with claims unwalked. */
|
|
8465
|
+
bounded: boolean(),
|
|
8466
|
+
byDevice: array(LedgerWalkDeviceReportSchema).readonly()
|
|
8467
|
+
});
|
|
8369
8468
|
/** How many rows a media pass would still act on against a given target — the
|
|
8370
8469
|
* media lane's denominator AND its residue, from ONE derivation so the two can
|
|
8371
8470
|
* never disagree. `null` = the count could not be taken. */
|
|
@@ -18639,13 +18738,15 @@ var ListGroupsPageSchema = object({
|
|
|
18639
18738
|
groups: array(AnalyticsGroupRecordSchema).readonly(),
|
|
18640
18739
|
nextCursor: string().nullable()
|
|
18641
18740
|
});
|
|
18741
|
+
var KEY_EVENTS_DEFAULT_LIMIT = 50;
|
|
18742
|
+
var KEY_EVENTS_MAX_LIMIT = 200;
|
|
18642
18743
|
var KeyEventQueryInput = object({
|
|
18643
18744
|
deviceId: number(),
|
|
18644
18745
|
/** Window lower bound (track firstSeen ≥ since). */
|
|
18645
18746
|
since: number(),
|
|
18646
18747
|
/** Window upper bound (track firstSeen ≤ until). */
|
|
18647
18748
|
until: number(),
|
|
18648
|
-
limit: number().int().min(1).max(
|
|
18749
|
+
limit: number().int().min(1).max(KEY_EVENTS_MAX_LIMIT).default(KEY_EVENTS_DEFAULT_LIMIT),
|
|
18649
18750
|
/** Drop tracks scoring below this importance. */
|
|
18650
18751
|
minImportance: number().min(0).max(1).optional(),
|
|
18651
18752
|
/** Restrict to a single class (e.g. 'person'). */
|
|
@@ -18667,6 +18768,32 @@ var KeyEventSchema = object({
|
|
|
18667
18768
|
...TrackFlagFields,
|
|
18668
18769
|
...TrackRetrainFields
|
|
18669
18770
|
});
|
|
18771
|
+
/** `getKeyEvents`' window and filters, asked of a SET of cameras at once. */
|
|
18772
|
+
var KeyEventBatchQueryInput = object({
|
|
18773
|
+
deviceIds: array(number()).min(1).max(200),
|
|
18774
|
+
since: number(),
|
|
18775
|
+
until: number(),
|
|
18776
|
+
/** Applied PER CAMERA, exactly as `getKeyEvents.limit` is — never a total
|
|
18777
|
+
* across the set, which would let a busy camera starve a quiet one of its
|
|
18778
|
+
* rows and change what the merged feed contains. */
|
|
18779
|
+
limit: number().int().min(1).max(KEY_EVENTS_MAX_LIMIT).default(KEY_EVENTS_DEFAULT_LIMIT),
|
|
18780
|
+
minImportance: number().min(0).max(1).optional(),
|
|
18781
|
+
classFilter: string().optional()
|
|
18782
|
+
});
|
|
18783
|
+
/**
|
|
18784
|
+
* One camera's key events in a batch answer.
|
|
18785
|
+
*
|
|
18786
|
+
* The row exists for every requested id. `getKeyEvents` degrades to `[]` on
|
|
18787
|
+
* error rather than throwing, so a camera whose store read failed and one with
|
|
18788
|
+
* no events in the window were ALREADY indistinguishable per camera — the
|
|
18789
|
+
* batch does not make that worse, and the row keeps the deviceId the single
|
|
18790
|
+
* method's output never carried (the caller used to stamp it from the fan-out
|
|
18791
|
+
* key, which only worked because there was one query per camera).
|
|
18792
|
+
*/
|
|
18793
|
+
var KeyEventsForDeviceSchema = object({
|
|
18794
|
+
deviceId: number(),
|
|
18795
|
+
events: array(KeyEventSchema).readonly()
|
|
18796
|
+
});
|
|
18670
18797
|
object({
|
|
18671
18798
|
trackId: string(),
|
|
18672
18799
|
className: string(),
|
|
@@ -18738,6 +18865,50 @@ var EventStoreFootprintSchema = object({
|
|
|
18738
18865
|
totalBytes: number().int(),
|
|
18739
18866
|
devices: array(EventStoreDeviceFootprintSchema).readonly()
|
|
18740
18867
|
});
|
|
18868
|
+
/** Event-media footprint for one {@link MediaFileKind}. */
|
|
18869
|
+
var EventMediaKindFootprintSchema = object({
|
|
18870
|
+
kind: MediaFileKindEnum,
|
|
18871
|
+
/** Media rows of this kind. */
|
|
18872
|
+
rows: number().int(),
|
|
18873
|
+
/** Bytes on disk held by those rows. */
|
|
18874
|
+
bytes: number().int()
|
|
18875
|
+
});
|
|
18876
|
+
/**
|
|
18877
|
+
* The media footprint broken down by KIND — the axis a deletion decision
|
|
18878
|
+
* actually turns on.
|
|
18879
|
+
*
|
|
18880
|
+
* A byte total says how much there is; it cannot say what is safe to remove.
|
|
18881
|
+
* The deletable set (the periodic `snapshot` filmstrip, the surplus per-edge
|
|
18882
|
+
* motion stills) and the keep set (`firstFrame`, rolling `lastFrame`,
|
|
18883
|
+
* `thumbnail`/`thumbnailSmall`, `keyFrame`/`keyFrameSmall`, the face/plate
|
|
18884
|
+
* buffers, gallery media, the CLIP `crop`) are distinguished by `kind` and by
|
|
18885
|
+
* nothing else, so sizing a deletion means summing per kind.
|
|
18886
|
+
*
|
|
18887
|
+
* ## Why `unaccounted*` exists
|
|
18888
|
+
*
|
|
18889
|
+
* `kinds` is enumerated from {@link MediaFileKindEnum} — the closed set the
|
|
18890
|
+
* writers use — and summed one kind at a time. `totalRows` / `totalBytes` come
|
|
18891
|
+
* from a SEPARATE unfiltered aggregate over the same rows, never from adding
|
|
18892
|
+
* `kinds` up. A row whose stored `kind` is not in the enum (written by a
|
|
18893
|
+
* retired code path, or by a version that knew a kind this one does not) would
|
|
18894
|
+
* otherwise vanish from the total silently, and an operator would delete
|
|
18895
|
+
* against a denominator smaller than the disk.
|
|
18896
|
+
*
|
|
18897
|
+
* `unaccountedRows` / `unaccountedBytes` are the difference. They are normally
|
|
18898
|
+
* zero; a non-zero value is a real finding and must be shown, not rounded away.
|
|
18899
|
+
*/
|
|
18900
|
+
var EventMediaKindBreakdownSchema = object({
|
|
18901
|
+
/** Every media row in scope, from one unfiltered aggregate. */
|
|
18902
|
+
totalRows: number().int(),
|
|
18903
|
+
/** Every media byte in scope, from that same aggregate. */
|
|
18904
|
+
totalBytes: number().int(),
|
|
18905
|
+
/** Per-kind footprint, ordered by bytes descending. */
|
|
18906
|
+
kinds: array(EventMediaKindFootprintSchema).readonly(),
|
|
18907
|
+
/** `totalRows` minus the summed `kinds` rows — see the schema note. */
|
|
18908
|
+
unaccountedRows: number().int(),
|
|
18909
|
+
/** `totalBytes` minus the summed `kinds` bytes — see the schema note. */
|
|
18910
|
+
unaccountedBytes: number().int()
|
|
18911
|
+
});
|
|
18741
18912
|
/** Per-kind counts returned by the event-prune / device-delete mutations. */
|
|
18742
18913
|
var EventPruneCountsSchema = object({
|
|
18743
18914
|
motion: number().int(),
|
|
@@ -18892,7 +19063,7 @@ DeviceType.Camera, method(object({ deviceId: number() }), array(TrackSchema).rea
|
|
|
18892
19063
|
until: number().optional(),
|
|
18893
19064
|
kinds: array(string()).optional(),
|
|
18894
19065
|
limit: number().int().min(1).max(MAX_EVENT_QUERY_LIMIT).default(DEFAULT_EVENT_QUERY_LIMIT)
|
|
18895
|
-
}), array(SensorEventSchema).readonly()), method(KeyEventQueryInput, array(KeyEventSchema).readonly()), method(object({
|
|
19066
|
+
}), array(SensorEventSchema).readonly()), method(KeyEventQueryInput, array(KeyEventSchema).readonly()), method(KeyEventBatchQueryInput, array(KeyEventsForDeviceSchema).readonly()), method(object({
|
|
18896
19067
|
deviceId: number(),
|
|
18897
19068
|
since: number(),
|
|
18898
19069
|
until: number(),
|
|
@@ -18941,6 +19112,9 @@ DeviceType.Camera, method(object({ deviceId: number() }), array(TrackSchema).rea
|
|
|
18941
19112
|
}), TrackFlagsSchema, { kind: "mutation" }), method(object({}), EventStoreFootprintSchema, {
|
|
18942
19113
|
kind: "query",
|
|
18943
19114
|
auth: "admin"
|
|
19115
|
+
}), method(object({ deviceId: number().int().optional() }), EventMediaKindBreakdownSchema, {
|
|
19116
|
+
kind: "query",
|
|
19117
|
+
auth: "admin"
|
|
18944
19118
|
}), method(object({
|
|
18945
19119
|
olderThanMs: number(),
|
|
18946
19120
|
reason: OpsLogReasonSchema.optional()
|
|
@@ -20892,6 +21066,20 @@ method(object({
|
|
|
20892
21066
|
error: string().optional()
|
|
20893
21067
|
}), { auth: "admin" }), method(_void(), array(ProviderListEntrySchema).readonly()), method(object({
|
|
20894
21068
|
providerId: string(),
|
|
21069
|
+
/**
|
|
21070
|
+
* The location this config is an UNSAVED edit of, when there is one.
|
|
21071
|
+
*
|
|
21072
|
+
* `listLocations` replaces every declared secret with the redaction
|
|
21073
|
+
* sentinel, so the edit modal's form state holds the sentinel for any
|
|
21074
|
+
* credential the operator did not retype — and posting that here
|
|
21075
|
+
* without a way to resolve it makes the provider try to authenticate
|
|
21076
|
+
* as `__camstack_redacted__` and report the operator's own working
|
|
21077
|
+
* password as wrong. Given this id, the orchestrator restores each
|
|
21078
|
+
* sentinel from the stored config (same rule as `upsertLocation`)
|
|
21079
|
+
* before dispatching. Omitted by the "Add location" wizard, where
|
|
21080
|
+
* every value was typed just now and nothing is stored yet.
|
|
21081
|
+
*/
|
|
21082
|
+
locationId: string().optional(),
|
|
20895
21083
|
config: record(string(), unknown())
|
|
20896
21084
|
}), object({
|
|
20897
21085
|
ok: boolean(),
|
|
@@ -26587,6 +26775,9 @@ method(object({
|
|
|
26587
26775
|
}), method(RelocateResidueInputSchema, RelocateResidueSchema, {
|
|
26588
26776
|
kind: "query",
|
|
26589
26777
|
auth: "admin"
|
|
26778
|
+
}), method(LedgerWalkInputSchema, LedgerWalkReportSchema, {
|
|
26779
|
+
kind: "mutation",
|
|
26780
|
+
auth: "admin"
|
|
26590
26781
|
}), method(object({ jobId: string() }), object({ cancelled: boolean() }), {
|
|
26591
26782
|
kind: "mutation",
|
|
26592
26783
|
auth: "admin"
|
|
@@ -26978,7 +27169,26 @@ var SceneMonitorStatusSchema = object({
|
|
|
26978
27169
|
monitors: array(SceneMonitorSchema),
|
|
26979
27170
|
lastFetchedAt: number()
|
|
26980
27171
|
});
|
|
26981
|
-
|
|
27172
|
+
/**
|
|
27173
|
+
* One camera's row in a `listScenesBatch` answer.
|
|
27174
|
+
*
|
|
27175
|
+
* `status` is NULLABLE and the nullability is the whole point. `scene-monitor`
|
|
27176
|
+
* is a `defaultActive` wrapper, so every camera is asked; a camera whose
|
|
27177
|
+
* provider is absent (pipeline-analytics not deployed, the post-processing node
|
|
27178
|
+
* down) cannot answer, and that is not the same fact as a camera with no scenes
|
|
27179
|
+
* configured. Fanned out per camera the difference was visible — one query
|
|
27180
|
+
* errored while the others resolved — and a batch that returned only the rows
|
|
27181
|
+
* it managed would have destroyed it, silently, by making an unreachable camera
|
|
27182
|
+
* indistinguishable from one that answered `monitors: []`.
|
|
27183
|
+
*
|
|
27184
|
+
* So: EVERY requested deviceId gets a row. `status: null` means "this camera
|
|
27185
|
+
* could not be read"; `status.monitors: []` means "read, and it has none".
|
|
27186
|
+
*/
|
|
27187
|
+
var SceneMonitorStatusForDeviceSchema = object({
|
|
27188
|
+
deviceId: number(),
|
|
27189
|
+
status: SceneMonitorStatusSchema.nullable()
|
|
27190
|
+
});
|
|
27191
|
+
DeviceType.Camera, method(object({ deviceId: number() }), SceneMonitorStatusSchema), method(object({ deviceIds: array(number()).min(1).max(200) }), array(SceneMonitorStatusForDeviceSchema).readonly()), method(object({
|
|
26982
27192
|
deviceId: number(),
|
|
26983
27193
|
label: string(),
|
|
26984
27194
|
roi: MaskRectShapeSchema,
|
|
@@ -28302,6 +28512,27 @@ var CameraOccupancySnapshotSchema = object({
|
|
|
28302
28512
|
stationaryObjects: array(StationaryObjectSchema).readonly().optional()
|
|
28303
28513
|
});
|
|
28304
28514
|
/**
|
|
28515
|
+
* One camera's row in a `getCurrentSnapshotBatch` answer.
|
|
28516
|
+
*
|
|
28517
|
+
* THREE outcomes, and the single-camera method could only express two of them
|
|
28518
|
+
* because `snapshot: null` was already spoken for:
|
|
28519
|
+
*
|
|
28520
|
+
* - `read: 'read'`, `snapshot` present — the live occupancy reading.
|
|
28521
|
+
* - `read: 'read'`, `snapshot: null` — read, and this camera has no reading
|
|
28522
|
+
* yet: no frame since boot, and no parked-object registry to hydrate from.
|
|
28523
|
+
* - `read: 'unreadable'` — the owner could not answer for this
|
|
28524
|
+
* camera. `snapshot` is null, and it does NOT mean "nothing parked here".
|
|
28525
|
+
*
|
|
28526
|
+
* Collapsing the last two is the failure this field exists to prevent: a
|
|
28527
|
+
* hydration that threw would otherwise render as an empty Stationary section,
|
|
28528
|
+
* which is a definite claim about a camera nobody could read.
|
|
28529
|
+
*/
|
|
28530
|
+
var CameraOccupancySnapshotForDeviceSchema = object({
|
|
28531
|
+
deviceId: number(),
|
|
28532
|
+
read: _enum(["read", "unreadable"]),
|
|
28533
|
+
snapshot: CameraOccupancySnapshotSchema.nullable()
|
|
28534
|
+
});
|
|
28535
|
+
/**
|
|
28305
28536
|
* Time-series resolution. The history methods return one bucket per
|
|
28306
28537
|
* step over the requested range. Smaller resolutions cost more
|
|
28307
28538
|
* memory + bandwidth; bound to discrete steps so caller cannot ask
|
|
@@ -28325,7 +28556,7 @@ var HistoryPointSchema = object({
|
|
|
28325
28556
|
/** Object count averaged over the bucket (rounded to nearest integer). */
|
|
28326
28557
|
count: number().int().nonnegative()
|
|
28327
28558
|
});
|
|
28328
|
-
DeviceType.Camera, method(object({ deviceId: number() }), CameraOccupancySnapshotSchema.nullable()), method(object({
|
|
28559
|
+
DeviceType.Camera, method(object({ deviceId: number() }), CameraOccupancySnapshotSchema.nullable()), method(object({ deviceIds: array(number()).min(1).max(200) }), array(CameraOccupancySnapshotForDeviceSchema).readonly()), method(object({
|
|
28329
28560
|
deviceId: number(),
|
|
28330
28561
|
zoneId: string(),
|
|
28331
28562
|
className: string().optional()
|
|
@@ -31606,6 +31837,12 @@ Object.freeze({
|
|
|
31606
31837
|
addonId: null,
|
|
31607
31838
|
access: "view"
|
|
31608
31839
|
},
|
|
31840
|
+
"pipelineAnalytics.getEventMediaFootprintByKind": {
|
|
31841
|
+
capName: "pipeline-analytics",
|
|
31842
|
+
capScope: "device",
|
|
31843
|
+
addonId: null,
|
|
31844
|
+
access: "view"
|
|
31845
|
+
},
|
|
31609
31846
|
"pipelineAnalytics.getEventStoreFootprint": {
|
|
31610
31847
|
capName: "pipeline-analytics",
|
|
31611
31848
|
capScope: "device",
|
|
@@ -31624,6 +31861,12 @@ Object.freeze({
|
|
|
31624
31861
|
addonId: null,
|
|
31625
31862
|
access: "view"
|
|
31626
31863
|
},
|
|
31864
|
+
"pipelineAnalytics.getKeyEventsBatch": {
|
|
31865
|
+
capName: "pipeline-analytics",
|
|
31866
|
+
capScope: "device",
|
|
31867
|
+
addonId: null,
|
|
31868
|
+
access: "view"
|
|
31869
|
+
},
|
|
31627
31870
|
"pipelineAnalytics.getMotionEvents": {
|
|
31628
31871
|
capName: "pipeline-analytics",
|
|
31629
31872
|
capScope: "device",
|
|
@@ -32800,6 +33043,12 @@ Object.freeze({
|
|
|
32800
33043
|
addonId: null,
|
|
32801
33044
|
access: "view"
|
|
32802
33045
|
},
|
|
33046
|
+
"recording.reconcileLedgerAgainstDisk": {
|
|
33047
|
+
capName: "recording",
|
|
33048
|
+
capScope: "system",
|
|
33049
|
+
addonId: null,
|
|
33050
|
+
access: "create"
|
|
33051
|
+
},
|
|
32803
33052
|
"recording.refreshStorageLocationsForMigration": {
|
|
32804
33053
|
capName: "recording",
|
|
32805
33054
|
capScope: "system",
|
|
@@ -32926,6 +33175,12 @@ Object.freeze({
|
|
|
32926
33175
|
addonId: null,
|
|
32927
33176
|
access: "view"
|
|
32928
33177
|
},
|
|
33178
|
+
"sceneMonitor.listScenesBatch": {
|
|
33179
|
+
capName: "scene-monitor",
|
|
33180
|
+
capScope: "device",
|
|
33181
|
+
addonId: null,
|
|
33182
|
+
access: "view"
|
|
33183
|
+
},
|
|
32929
33184
|
"sceneMonitor.recheckNow": {
|
|
32930
33185
|
capName: "scene-monitor",
|
|
32931
33186
|
capScope: "device",
|
|
@@ -34282,6 +34537,12 @@ Object.freeze({
|
|
|
34282
34537
|
addonId: null,
|
|
34283
34538
|
access: "view"
|
|
34284
34539
|
},
|
|
34540
|
+
"zoneAnalytics.getCurrentSnapshotBatch": {
|
|
34541
|
+
capName: "zone-analytics",
|
|
34542
|
+
capScope: "device",
|
|
34543
|
+
addonId: null,
|
|
34544
|
+
access: "view"
|
|
34545
|
+
},
|
|
34285
34546
|
"zoneAnalytics.getUnzonedHistory": {
|
|
34286
34547
|
capName: "zone-analytics",
|
|
34287
34548
|
capScope: "device",
|
|
@@ -35271,6 +35532,11 @@ Object.freeze({
|
|
|
35271
35532
|
form: "single",
|
|
35272
35533
|
optional: false
|
|
35273
35534
|
}],
|
|
35535
|
+
"pipelineAnalytics.getEventMediaFootprintByKind": [{
|
|
35536
|
+
name: "deviceId",
|
|
35537
|
+
form: "single",
|
|
35538
|
+
optional: true
|
|
35539
|
+
}],
|
|
35274
35540
|
"pipelineAnalytics.getGroup": [{
|
|
35275
35541
|
name: "deviceId",
|
|
35276
35542
|
form: "single",
|
|
@@ -35281,6 +35547,11 @@ Object.freeze({
|
|
|
35281
35547
|
form: "single",
|
|
35282
35548
|
optional: false
|
|
35283
35549
|
}],
|
|
35550
|
+
"pipelineAnalytics.getKeyEventsBatch": [{
|
|
35551
|
+
name: "deviceIds",
|
|
35552
|
+
form: "array",
|
|
35553
|
+
optional: false
|
|
35554
|
+
}],
|
|
35284
35555
|
"pipelineAnalytics.getMotionEvents": [{
|
|
35285
35556
|
name: "deviceId",
|
|
35286
35557
|
form: "single",
|
|
@@ -35721,6 +35992,11 @@ Object.freeze({
|
|
|
35721
35992
|
form: "single",
|
|
35722
35993
|
optional: false
|
|
35723
35994
|
}],
|
|
35995
|
+
"recording.reconcileLedgerAgainstDisk": [{
|
|
35996
|
+
name: "deviceId",
|
|
35997
|
+
form: "single",
|
|
35998
|
+
optional: true
|
|
35999
|
+
}],
|
|
35724
36000
|
"recording.relocateFootage": [{
|
|
35725
36001
|
name: "deviceId",
|
|
35726
36002
|
form: "single",
|
|
@@ -35786,6 +36062,11 @@ Object.freeze({
|
|
|
35786
36062
|
form: "single",
|
|
35787
36063
|
optional: false
|
|
35788
36064
|
}],
|
|
36065
|
+
"sceneMonitor.listScenesBatch": [{
|
|
36066
|
+
name: "deviceIds",
|
|
36067
|
+
form: "array",
|
|
36068
|
+
optional: false
|
|
36069
|
+
}],
|
|
35789
36070
|
"sceneMonitor.recheckNow": [{
|
|
35790
36071
|
name: "deviceId",
|
|
35791
36072
|
form: "single",
|
|
@@ -36047,6 +36328,11 @@ Object.freeze({
|
|
|
36047
36328
|
form: "single",
|
|
36048
36329
|
optional: false
|
|
36049
36330
|
}],
|
|
36331
|
+
"zoneAnalytics.getCurrentSnapshotBatch": [{
|
|
36332
|
+
name: "deviceIds",
|
|
36333
|
+
form: "array",
|
|
36334
|
+
optional: false
|
|
36335
|
+
}],
|
|
36050
36336
|
"zoneAnalytics.getUnzonedHistory": [{
|
|
36051
36337
|
name: "deviceId",
|
|
36052
36338
|
form: "single",
|
package/dist/smb.addon.js
CHANGED
|
@@ -2,7 +2,7 @@ Object.defineProperties(exports, {
|
|
|
2
2
|
__esModule: { value: true },
|
|
3
3
|
[Symbol.toStringTag]: { value: "Module" }
|
|
4
4
|
});
|
|
5
|
-
const require_shared = require("./shared-
|
|
5
|
+
const require_shared = require("./shared-Bwt_Ye8T.js");
|
|
6
6
|
let node_crypto = require("node:crypto");
|
|
7
7
|
let node_path = require("node:path");
|
|
8
8
|
node_path = require_shared.__toESM(node_path);
|
package/dist/smb.addon.mjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { c as BaseAddon, i as rearmIdleAbort, o as scheduleIdleAbort, s as storageProviderCapability } from "./shared-
|
|
1
|
+
import { c as BaseAddon, i as rearmIdleAbort, o as scheduleIdleAbort, s as storageProviderCapability } from "./shared-CQEWmUcA.mjs";
|
|
2
2
|
import { randomUUID } from "node:crypto";
|
|
3
3
|
import * as path from "node:path";
|
|
4
4
|
import * as fsp from "node:fs/promises";
|
package/dist/webdav.addon.js
CHANGED
|
@@ -2,7 +2,7 @@ Object.defineProperties(exports, {
|
|
|
2
2
|
__esModule: { value: true },
|
|
3
3
|
[Symbol.toStringTag]: { value: "Module" }
|
|
4
4
|
});
|
|
5
|
-
const require_shared = require("./shared-
|
|
5
|
+
const require_shared = require("./shared-Bwt_Ye8T.js");
|
|
6
6
|
let node_stream = require("node:stream");
|
|
7
7
|
let webdav = require("webdav");
|
|
8
8
|
//#region src/providers/webdav/webdav-config-schema.ts
|
package/dist/webdav.addon.mjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { a as safeJoinRemotePath, c as BaseAddon, i as rearmIdleAbort, o as scheduleIdleAbort, r as getRequiredBasePath, s as storageProviderCapability, t as createSessionId } from "./shared-
|
|
1
|
+
import { a as safeJoinRemotePath, c as BaseAddon, i as rearmIdleAbort, o as scheduleIdleAbort, r as getRequiredBasePath, s as storageProviderCapability, t as createSessionId } from "./shared-CQEWmUcA.mjs";
|
|
2
2
|
import { PassThrough } from "node:stream";
|
|
3
3
|
import { AuthType, createClient } from "webdav";
|
|
4
4
|
//#region src/providers/webdav/webdav-config-schema.ts
|
package/package.json
CHANGED