@camstack/addon-provider-rademacher 0.2.6 → 0.2.8
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/addon.js +463 -76
- package/dist/addon.mjs +463 -76
- package/package.json +1 -1
package/dist/addon.js
CHANGED
|
@@ -984,7 +984,7 @@ var Rademacher = class {
|
|
|
984
984
|
}
|
|
985
985
|
};
|
|
986
986
|
//#endregion
|
|
987
|
-
//#region ../types/dist/event-category-
|
|
987
|
+
//#region ../types/dist/event-category-Bz24uP1U.mjs
|
|
988
988
|
var EventCategory = /* @__PURE__ */ function(EventCategory) {
|
|
989
989
|
EventCategory["SystemBoot"] = "system.boot";
|
|
990
990
|
EventCategory["SystemAddonsReady"] = "system.addons-ready";
|
|
@@ -1255,6 +1255,19 @@ var EventCategory = /* @__PURE__ */ function(EventCategory) {
|
|
|
1255
1255
|
*/
|
|
1256
1256
|
EventCategory["DeviceStateChanged"] = "device.state-changed";
|
|
1257
1257
|
/**
|
|
1258
|
+
* Frame occupancy for a camera CHANGED — a tracked object was gained or
|
|
1259
|
+
* lost. Carries `{ deviceId, totalObjects, byClass, zones }`.
|
|
1260
|
+
*
|
|
1261
|
+
* Emitted only on a change, so a steady scene is silent. It exists so a
|
|
1262
|
+
* client can stop polling `zoneAnalytics.getCurrentSnapshot`: that was the
|
|
1263
|
+
* one live badge with no push signal at all, and it cost a request every
|
|
1264
|
+
* four seconds per visible camera.
|
|
1265
|
+
*
|
|
1266
|
+
* Like every event it is telemetry and may be dropped ([D8]) — a consumer
|
|
1267
|
+
* keeps a slow reconcile rather than trusting it alone.
|
|
1268
|
+
*/
|
|
1269
|
+
EventCategory["ZoneAnalyticsOccupancyChanged"] = "zone-analytics.occupancy-changed";
|
|
1270
|
+
/**
|
|
1258
1271
|
* Cap event fired by every device that registers the `battery`
|
|
1259
1272
|
* capability. Mirrors the cap definition's `onStatusChanged`. Carries
|
|
1260
1273
|
* `{ deviceId, status: BatteryStatus }`. Subscribers (alert center,
|
|
@@ -8198,35 +8211,22 @@ var ConvertResultSchema = object({
|
|
|
8198
8211
|
*/
|
|
8199
8212
|
var RecordingWeekdaySchema = number().int().min(0).max(6);
|
|
8200
8213
|
var HHMM = /^([01]\d|2[0-3]):[0-5]\d$/;
|
|
8201
|
-
var RecordingScheduleSchema = discriminatedUnion("kind", [object({ kind: literal("always") }), object({
|
|
8202
|
-
kind: literal("timeOfDay"),
|
|
8203
|
-
start: string().regex(HHMM),
|
|
8204
|
-
end: string().regex(HHMM),
|
|
8205
|
-
/** Restrict to these weekdays; omit = every day. */
|
|
8206
|
-
days: array(RecordingWeekdaySchema).optional()
|
|
8207
|
-
})]);
|
|
8208
|
-
var RecordingModeSchema = _enum([
|
|
8209
|
-
"continuous",
|
|
8210
|
-
"onMotion",
|
|
8211
|
-
"onAudioThreshold"
|
|
8212
|
-
]);
|
|
8213
8214
|
/**
|
|
8214
|
-
*
|
|
8215
|
-
*
|
|
8216
|
-
* - `off` —
|
|
8217
|
-
* - `events` —
|
|
8218
|
-
*
|
|
8219
|
-
* - `continuous` — record 24/7 within the schedule.
|
|
8215
|
+
* DERIVED per-camera storage summary — the single field cheap consumers read
|
|
8216
|
+
* (the viewer's status dot, the camera list) instead of walking `bands`:
|
|
8217
|
+
* - `off` — no band covers the camera (or it is disabled).
|
|
8218
|
+
* - `events` — every band records around triggers only.
|
|
8219
|
+
* - `continuous` — at least one band records continuously.
|
|
8220
8220
|
*
|
|
8221
|
-
*
|
|
8222
|
-
*
|
|
8221
|
+
* NEVER authored: the recorder stamps it from the authoritative `bands` on
|
|
8222
|
+
* every save (`activeModeForConfig`). Writing it has no effect.
|
|
8223
8223
|
*/
|
|
8224
8224
|
var RecordingStorageModeSchema = _enum([
|
|
8225
8225
|
"off",
|
|
8226
8226
|
"events",
|
|
8227
8227
|
"continuous"
|
|
8228
8228
|
]);
|
|
8229
|
-
/** Which detectors trigger an `events`-mode
|
|
8229
|
+
/** Which detectors trigger an `events`-mode band. */
|
|
8230
8230
|
var RecordingTriggersSchema = object({
|
|
8231
8231
|
motion: boolean().optional(),
|
|
8232
8232
|
audioThresholdDbfs: number().optional()
|
|
@@ -8262,18 +8262,6 @@ var RecordingBandSchema = object({
|
|
|
8262
8262
|
preBufferSec: number().min(0).optional(),
|
|
8263
8263
|
postBufferSec: number().min(0).optional()
|
|
8264
8264
|
});
|
|
8265
|
-
var RecordingRuleSchema = object({
|
|
8266
|
-
schedule: RecordingScheduleSchema,
|
|
8267
|
-
mode: RecordingModeSchema,
|
|
8268
|
-
/** Seconds of footage to retain BEFORE a trigger (applied at keep/discard). */
|
|
8269
|
-
preBufferSec: number().min(0).default(0),
|
|
8270
|
-
/** Keep recording until this many seconds after the last trigger. */
|
|
8271
|
-
postBufferSec: number().min(0).default(0),
|
|
8272
|
-
/** Each new trigger restarts the post-buffer window. */
|
|
8273
|
-
resetTimeoutOnNewEvent: boolean().default(true),
|
|
8274
|
-
/** onAudioThreshold only — dBFS level that counts as a trigger. */
|
|
8275
|
-
thresholdDbfs: number().optional()
|
|
8276
|
-
});
|
|
8277
8265
|
/**
|
|
8278
8266
|
* Per-device retention overrides. Every field is optional; an unset or `0`
|
|
8279
8267
|
* value inherits the node-wide recorder default. Only footage-lifetime limits
|
|
@@ -8307,40 +8295,28 @@ var ScrubThumbnailPresetSchema = _enum([
|
|
|
8307
8295
|
/**
|
|
8308
8296
|
* The full per-camera recording intent — the wire shape of a RecordingTarget.
|
|
8309
8297
|
*
|
|
8310
|
-
* `
|
|
8311
|
-
*
|
|
8312
|
-
*
|
|
8313
|
-
*
|
|
8298
|
+
* `bands` is the ONLY authored recording intent: what to record, when, and on
|
|
8299
|
+
* which trigger. `mode` is a derived summary the recorder stamps on save; every
|
|
8300
|
+
* other field is a storage knob (profiles, segment length, retention, scrub).
|
|
8301
|
+
*
|
|
8302
|
+
* STRICT on purpose: the legacy authoring surface (`schedule`/`schedules`/
|
|
8303
|
+
* `triggers`/`preBufferSec`/`postBufferSec`/`rules`) was retired 2026-07-30.
|
|
8304
|
+
* A stale caller must fail loudly — silently stripping its legacy intent would
|
|
8305
|
+
* persist a band-less config, i.e. silently stop recording the camera.
|
|
8314
8306
|
*/
|
|
8315
8307
|
var RecordingConfigSchema = object({
|
|
8316
8308
|
enabled: boolean(),
|
|
8317
|
-
/**
|
|
8318
|
-
*
|
|
8309
|
+
/** DERIVED summary of `bands`, stamped by the recorder on every save.
|
|
8310
|
+
* Authoring it has no effect — see {@link RecordingStorageModeSchema}. */
|
|
8319
8311
|
mode: RecordingStorageModeSchema.optional(),
|
|
8320
8312
|
profiles: array(CamProfileSchema).optional(),
|
|
8321
8313
|
segmentSeconds: number().int().positive().optional(),
|
|
8322
|
-
/** Shared recording time-bands for `events` & `continuous` — record only when
|
|
8323
|
-
* the wall-clock falls inside one of these windows. Omit or empty = always.
|
|
8324
|
-
* `continuous` compiles to one rule per band; `events` to band × trigger. */
|
|
8325
|
-
schedules: array(RecordingScheduleSchema).optional(),
|
|
8326
|
-
/** Legacy single-band predecessor of `schedules`. Read-compat only — it is
|
|
8327
|
-
* normalized into `schedules` on read and never written going forward. (Not
|
|
8328
|
-
* tagged `@deprecated`: the normalization paths must read it cast-free.) */
|
|
8329
|
-
schedule: RecordingScheduleSchema.optional(),
|
|
8330
|
-
/** `events`-mode only — which detectors trigger a recording. */
|
|
8331
|
-
triggers: RecordingTriggersSchema.optional(),
|
|
8332
|
-
/** `events`-mode only — seconds retained before / after a trigger. */
|
|
8333
|
-
preBufferSec: number().min(0).optional(),
|
|
8334
|
-
postBufferSec: number().min(0).optional(),
|
|
8335
|
-
/** DEPRECATED authoring input; retained for migration/transition. */
|
|
8336
|
-
rules: array(RecordingRuleSchema).optional(),
|
|
8337
8314
|
/**
|
|
8338
|
-
* AUTHORITATIVE mode-per-band recording model
|
|
8339
|
-
*
|
|
8340
|
-
*
|
|
8341
|
-
* derived into bands once via `migrateConfigToBands`.
|
|
8315
|
+
* AUTHORITATIVE mode-per-band recording model — the single source of truth
|
|
8316
|
+
* the recorder's band engine consumes. An empty array = record nothing;
|
|
8317
|
+
* "off" is the absence of a covering band, never a band value.
|
|
8342
8318
|
*/
|
|
8343
|
-
bands: array(RecordingBandSchema).
|
|
8319
|
+
bands: array(RecordingBandSchema).default([]),
|
|
8344
8320
|
retention: RecordingRetentionSchema.optional(),
|
|
8345
8321
|
/**
|
|
8346
8322
|
* Per-camera scrub-thumbnail fidelity preset (resolution + JPEG quality for
|
|
@@ -8348,8 +8324,15 @@ var RecordingConfigSchema = object({
|
|
|
8348
8324
|
* windows only — existing sheets are immutable, and each window's index
|
|
8349
8325
|
* carries its own tile dims so mixed-preset history renders correctly.
|
|
8350
8326
|
*/
|
|
8351
|
-
scrubThumbnails: ScrubThumbnailPresetSchema.optional()
|
|
8352
|
-
|
|
8327
|
+
scrubThumbnails: ScrubThumbnailPresetSchema.optional(),
|
|
8328
|
+
/**
|
|
8329
|
+
* OPT-IN thumbnail-strip generation for this camera: every keyframe of the
|
|
8330
|
+
* low recording saved as a JPEG (the fast-drag scrub depth), a derived
|
|
8331
|
+
* cache that eviction reclaims with the footage. Absent/false = no strips
|
|
8332
|
+
* are written and scrub reads exact keyframes at every velocity.
|
|
8333
|
+
*/
|
|
8334
|
+
stripsEnabled: boolean().optional()
|
|
8335
|
+
}).strict();
|
|
8353
8336
|
/**
|
|
8354
8337
|
* Ops-log — the durable, append-only operations audit shared by the
|
|
8355
8338
|
* recordings and events management surfaces.
|
|
@@ -8368,7 +8351,8 @@ var OpsLogOpSchema = _enum([
|
|
|
8368
8351
|
"prune",
|
|
8369
8352
|
"manual-delete",
|
|
8370
8353
|
"rescan",
|
|
8371
|
-
"retention-run"
|
|
8354
|
+
"retention-run",
|
|
8355
|
+
"relocate"
|
|
8372
8356
|
]);
|
|
8373
8357
|
/** Why the operation ran. */
|
|
8374
8358
|
var OpsLogReasonSchema = _enum([
|
|
@@ -8407,6 +8391,55 @@ var OpsLogQueryInputSchema = object({
|
|
|
8407
8391
|
limit: number().int().min(1).max(1e3).optional()
|
|
8408
8392
|
});
|
|
8409
8393
|
/**
|
|
8394
|
+
* Entity-relocation job state (storage entity-routing spec, Phase 4).
|
|
8395
|
+
*
|
|
8396
|
+
* One shape shared by the recorder's `relocateFootage` (segments + strips) and
|
|
8397
|
+
* pipeline-analytics' `relocateMedia` (event media blobs) so the admin Data
|
|
8398
|
+
* page renders both movers with one component. Jobs are in-RAM (a restart
|
|
8399
|
+
* forgets them — re-running is safe by construction: copy-if-absent, delete
|
|
8400
|
+
* after verify) and each completed/failed run also lands one durable ops-log
|
|
8401
|
+
* row on the owning addon's surface.
|
|
8402
|
+
*/
|
|
8403
|
+
var RelocateJobStateSchema = _enum([
|
|
8404
|
+
"running",
|
|
8405
|
+
"done",
|
|
8406
|
+
"failed",
|
|
8407
|
+
"cancelled"
|
|
8408
|
+
]);
|
|
8409
|
+
var RelocateJobSchema = object({
|
|
8410
|
+
jobId: string(),
|
|
8411
|
+
state: RelocateJobStateSchema,
|
|
8412
|
+
/** Source location — for media relocation this is informational ('*': rows
|
|
8413
|
+
* move from wherever they are to the target). */
|
|
8414
|
+
fromLocationId: string(),
|
|
8415
|
+
toLocationId: string(),
|
|
8416
|
+
/** Scoped device, or null = every device. */
|
|
8417
|
+
deviceId: number().nullable(),
|
|
8418
|
+
/** What the job moves (owner-addon specific: segments/strips or media). */
|
|
8419
|
+
entities: array(string()),
|
|
8420
|
+
filesMoved: number().int(),
|
|
8421
|
+
bytesMoved: number().int(),
|
|
8422
|
+
/** Total files discovered up front; null while (or when) unknown. */
|
|
8423
|
+
filesTotal: number().int().nullable(),
|
|
8424
|
+
startedAt: number(),
|
|
8425
|
+
finishedAt: number().nullable(),
|
|
8426
|
+
error: string().nullable()
|
|
8427
|
+
});
|
|
8428
|
+
var RelocateFootageInputSchema = object({
|
|
8429
|
+
deviceId: number().optional(),
|
|
8430
|
+
fromLocationId: string(),
|
|
8431
|
+
toLocationId: string(),
|
|
8432
|
+
entities: array(_enum(["segments", "strips"])).optional(),
|
|
8433
|
+
/** Copy throttle in MB/s (default 40) — the drain is a background chore,
|
|
8434
|
+
* never allowed to starve live writers. */
|
|
8435
|
+
throttleMbps: number().min(1).max(1e3).optional()
|
|
8436
|
+
});
|
|
8437
|
+
var RelocateMediaInputSchema = object({
|
|
8438
|
+
deviceId: number().optional(),
|
|
8439
|
+
toLocationId: string(),
|
|
8440
|
+
throttleMbps: number().min(1).max(1e3).optional()
|
|
8441
|
+
});
|
|
8442
|
+
/**
|
|
8410
8443
|
* `StorageLocationType` — an addon-declared id that identifies the *kind* of
|
|
8411
8444
|
* storage a location serves. Defined here (not in `capabilities/storage.cap.ts`)
|
|
8412
8445
|
* so the persisted record schema and the consumer-facing cap can both consume it
|
|
@@ -8456,6 +8489,13 @@ var StorageLocationSchema = object({
|
|
|
8456
8489
|
nodeId: string().optional(),
|
|
8457
8490
|
isDefault: boolean().default(false),
|
|
8458
8491
|
isSystem: boolean().default(false),
|
|
8492
|
+
/** COMPUTED at read time by the orchestrator (statfs of the backing volume
|
|
8493
|
+
* for node-local locations it can reach) — never persisted, absent when the
|
|
8494
|
+
* volume is remote/unreachable. The single capacity truth every UI reads. */
|
|
8495
|
+
capacity: object({
|
|
8496
|
+
totalBytes: number(),
|
|
8497
|
+
availableBytes: number()
|
|
8498
|
+
}).nullable().optional(),
|
|
8459
8499
|
createdAt: number(),
|
|
8460
8500
|
updatedAt: number()
|
|
8461
8501
|
});
|
|
@@ -9223,7 +9263,8 @@ var NcTaxonomyEntrySchema = object({
|
|
|
9223
9263
|
/** Macro/category parent for grouping ('car' → 'vehicle'); null for a top. */
|
|
9224
9264
|
parentKind: string().nullable()
|
|
9225
9265
|
});
|
|
9226
|
-
|
|
9266
|
+
/** The complete NC picker taxonomy — three grouped buckets. */
|
|
9267
|
+
var NcTaxonomySchema = object({
|
|
9227
9268
|
videoClasses: array(NcTaxonomyEntrySchema),
|
|
9228
9269
|
audioKinds: array(NcTaxonomyEntrySchema),
|
|
9229
9270
|
labels: array(NcTaxonomyEntrySchema)
|
|
@@ -10126,6 +10167,7 @@ function shallowEqual(a, b) {
|
|
|
10126
10167
|
for (const k of ak) if (a[k] !== b[k]) return false;
|
|
10127
10168
|
return true;
|
|
10128
10169
|
}
|
|
10170
|
+
new Set(["devices", "classes"]);
|
|
10129
10171
|
/**
|
|
10130
10172
|
* Shared geometry vocabulary for on-frame shape caps — privacy-mask,
|
|
10131
10173
|
* motion-zones, and the detection zones/lines editor all speak this one
|
|
@@ -10284,6 +10326,29 @@ var NcOccupancyConditionSchema = object({
|
|
|
10284
10326
|
count: number().int().min(0).default(1),
|
|
10285
10327
|
sustainSeconds: number().int().min(0).max(3600).default(15)
|
|
10286
10328
|
});
|
|
10329
|
+
/**
|
|
10330
|
+
* Which zone-crossing DIRECTION a rule accepts (`ObjectEvent.zoneCrossing`).
|
|
10331
|
+
*
|
|
10332
|
+
* The values are not symmetric, and deliberately so — the absent value has to
|
|
10333
|
+
* mean exactly what every rule authored before this condition existed already
|
|
10334
|
+
* does:
|
|
10335
|
+
* - `enter` — entries and every NON-crossing record (movement state,
|
|
10336
|
+
* package, sensor). Exits are rejected. **This is the absent behaviour**:
|
|
10337
|
+
* an operator who never asked for exits must not start receiving them.
|
|
10338
|
+
* - `exit` — ONLY an exit crossing. A record that is not a crossing at all
|
|
10339
|
+
* fails closed, because "the car left the drive" is a question about a
|
|
10340
|
+
* boundary, not about a detection.
|
|
10341
|
+
* - `any` — no direction filter; entries, exits and non-crossings alike.
|
|
10342
|
+
*
|
|
10343
|
+
* A rule asking for a direction should normally also scope `zones`, which the
|
|
10344
|
+
* engine evaluates against the crossed zone as well as the current membership
|
|
10345
|
+
* (an exit's membership no longer contains the zone it just left).
|
|
10346
|
+
*/
|
|
10347
|
+
var NcCrossingSchema = _enum([
|
|
10348
|
+
"enter",
|
|
10349
|
+
"exit",
|
|
10350
|
+
"any"
|
|
10351
|
+
]);
|
|
10287
10352
|
/** Admin-zone membership condition (zone IDs as stamped by the ZoneEngine). */
|
|
10288
10353
|
var NcZoneConditionSchema = object({
|
|
10289
10354
|
ids: array(string().min(1)).min(1),
|
|
@@ -10308,6 +10373,13 @@ var NcConditionsSchema = object({
|
|
|
10308
10373
|
/** Veto zones — any hit fails the rule. */
|
|
10309
10374
|
zonesExclude: array(string().min(1)).optional(),
|
|
10310
10375
|
/**
|
|
10376
|
+
* Zone-crossing direction. IMMEDIATE only — a crossing is a per-event fact
|
|
10377
|
+
* and a closed track carries none, so a `track-end` rule asking for one
|
|
10378
|
+
* fails closed (use `zones`, which tests `zonesVisited`). ABSENT = `enter`,
|
|
10379
|
+
* which is exactly today's behaviour. See {@link NcCrossingSchema}.
|
|
10380
|
+
*/
|
|
10381
|
+
crossing: NcCrossingSchema.optional(),
|
|
10382
|
+
/**
|
|
10311
10383
|
* Exact (case-insensitive) match on the record's collapsed `label`
|
|
10312
10384
|
* (identity name / plate text / subclass).
|
|
10313
10385
|
*/
|
|
@@ -10442,17 +10514,85 @@ var NcRuleTargetSchema = object({
|
|
|
10442
10514
|
* - `keyFrame` — the clean scene frame (no subject box).
|
|
10443
10515
|
* - `none` — no attachment.
|
|
10444
10516
|
*/
|
|
10445
|
-
|
|
10446
|
-
|
|
10447
|
-
|
|
10448
|
-
|
|
10449
|
-
|
|
10450
|
-
|
|
10517
|
+
/**
|
|
10518
|
+
* WHAT THE PICTURE SHOWS — chosen explicitly, because the implicit ladders
|
|
10519
|
+
* conflate it with the selection strategy and betray the request: asking for
|
|
10520
|
+
* the clean scene frame on an object-event owner used to start at
|
|
10521
|
+
* `fullFrameBoxed`, i.e. the annotated frame (2026-07-30).
|
|
10522
|
+
* - `cropped` — the subject, tight. What "who is at the door" wants.
|
|
10523
|
+
* - `full` — the clean scene, no annotation. What "what is going on" wants.
|
|
10524
|
+
* - `boxed` — the scene WITH the detection boxes drawn, for verifying what
|
|
10525
|
+
* the pipeline actually saw.
|
|
10526
|
+
*/
|
|
10527
|
+
var NcMediaFrameSchema = _enum([
|
|
10528
|
+
"cropped",
|
|
10529
|
+
"full",
|
|
10530
|
+
"boxed"
|
|
10531
|
+
]);
|
|
10532
|
+
var NcMediaPolicySchema = object({
|
|
10533
|
+
attach: _enum([
|
|
10534
|
+
"best",
|
|
10535
|
+
"best-matching",
|
|
10536
|
+
"keyFrame",
|
|
10537
|
+
"none"
|
|
10538
|
+
]).default("best"),
|
|
10539
|
+
/** What the still shows. Absent = `cropped` (the historical `best` shape). */
|
|
10540
|
+
frame: NcMediaFrameSchema.optional(),
|
|
10541
|
+
/** Crop the attached still to the rule's condition-zone bbox (padded) —
|
|
10542
|
+
* "show me the ZONE", not the whole scene or the subject crop. */
|
|
10543
|
+
zoneCrop: boolean().optional(),
|
|
10544
|
+
/**
|
|
10545
|
+
* Also attach a short GIF cut from the stream broker's clip ring around the
|
|
10546
|
+
* event — NOT from the recording, so the camera does not have to be
|
|
10547
|
+
* recording, and the window sits AROUND the moment instead of a segment
|
|
10548
|
+
* behind it. Fail-closed: a window the ring does not cover contributes no
|
|
10549
|
+
* gif, never a failed notification.
|
|
10550
|
+
*/
|
|
10551
|
+
gif: boolean().optional(),
|
|
10552
|
+
/**
|
|
10553
|
+
* Also attach a short MP4 CLIP of the same cut. Same source and the same
|
|
10554
|
+
* fail-closed rule as `gif`. Prefer it where the backend takes video
|
|
10555
|
+
* (telegram, discord, zentik, webhook); backends that do not are handled by
|
|
10556
|
+
* the degrade engine, which drops the video and keeps the still.
|
|
10557
|
+
*/
|
|
10558
|
+
clip: boolean().optional(),
|
|
10559
|
+
/** Seconds of footage BEFORE / AFTER the event instant. Defaults 3 / 7. */
|
|
10560
|
+
clipPreRollSec: number().int().min(0).max(30).optional(),
|
|
10561
|
+
clipPostRollSec: number().int().min(0).max(30).optional(),
|
|
10562
|
+
/**
|
|
10563
|
+
* Which stream profile the footage is cut from. Absent = the CHEAPEST
|
|
10564
|
+
* assigned profile: a notification is watched on a phone, so the 4K
|
|
10565
|
+
* rendition would burn CPU to produce a file the client downscales anyway.
|
|
10566
|
+
* A profile that is not assigned falls back to the cheapest, and the render
|
|
10567
|
+
* reports which one actually ran.
|
|
10568
|
+
*/
|
|
10569
|
+
profile: CamProfileSchema.optional()
|
|
10570
|
+
});
|
|
10571
|
+
/**
|
|
10572
|
+
* Cooldown GRANULARITY over the subject's class — how much a fired
|
|
10573
|
+
* notification suppresses.
|
|
10574
|
+
* - `shared` (default, and the absent value) — one window for the whole
|
|
10575
|
+
* rule/scope: a cat silences the next dog for `cooldownSec`.
|
|
10576
|
+
* - `per-class` — an independent window per detected class, so cat→dog fires
|
|
10577
|
+
* at once and cat→cat still waits.
|
|
10578
|
+
*
|
|
10579
|
+
* AUDIO subjects are ALWAYS per-class regardless of this setting: a scream
|
|
10580
|
+
* must not be swallowed by a bark's window (the precedent this generalizes —
|
|
10581
|
+
* see `cooldownKey` in the rule engine).
|
|
10582
|
+
*/
|
|
10583
|
+
var NcThrottleGranularitySchema = _enum(["shared", "per-class"]);
|
|
10451
10584
|
/** Throttle — cooldown survives restarts (rebuilt from the outbox on boot). */
|
|
10452
10585
|
var NcThrottleSchema = object({
|
|
10453
10586
|
cooldownSec: number().int().min(0).max(86400).default(60),
|
|
10454
10587
|
/** `rule` = one shared cooldown; `rule-device` = per-camera cooldown. */
|
|
10455
|
-
scope: _enum(["rule", "rule-device"]).default("rule-device")
|
|
10588
|
+
scope: _enum(["rule", "rule-device"]).default("rule-device"),
|
|
10589
|
+
/**
|
|
10590
|
+
* Class granularity of the cooldown key. Optional rather than defaulted:
|
|
10591
|
+
* a Zod default does NOT run on the addon→addon cap path, so a persisted
|
|
10592
|
+
* rule authored before this field simply carries none — and the engine
|
|
10593
|
+
* reads absent as `shared`, the pre-existing behaviour.
|
|
10594
|
+
*/
|
|
10595
|
+
granularity: NcThrottleGranularitySchema.optional()
|
|
10456
10596
|
});
|
|
10457
10597
|
/** Client-supplied rule fields (server stamps id/createdBy/createdAt/updatedAt). */
|
|
10458
10598
|
var NcRuleInputSchema = object({
|
|
@@ -10461,7 +10601,19 @@ var NcRuleInputSchema = object({
|
|
|
10461
10601
|
delivery: NcDeliverySchema,
|
|
10462
10602
|
conditions: NcConditionsSchema.default({}),
|
|
10463
10603
|
schedule: NcScheduleSchema.optional(),
|
|
10464
|
-
|
|
10604
|
+
/** May be empty when `targetUsers` addresses at least one user — the
|
|
10605
|
+
* "at least one addressee" invariant is enforced by the provider, because
|
|
10606
|
+
* a cross-field refine here would break `NcRulePatchSchema.partial()`. */
|
|
10607
|
+
targets: array(NcRuleTargetSchema),
|
|
10608
|
+
/**
|
|
10609
|
+
* USERS this rule addresses in addition to `targets` (Phase 4). At fire
|
|
10610
|
+
* time each user fans out to the personal targets they own
|
|
10611
|
+
* (`config.ownerUserId`), filtered by that user's `allowedDevices` for the
|
|
10612
|
+
* firing camera — a user is never notified about a device they cannot open.
|
|
10613
|
+
* Per-user opt-outs (`disabledTargetIds`) still apply to the fanned-out
|
|
10614
|
+
* targets.
|
|
10615
|
+
*/
|
|
10616
|
+
targetUsers: array(string()).optional(),
|
|
10465
10617
|
media: NcMediaPolicySchema.default({ attach: "best" }),
|
|
10466
10618
|
throttle: NcThrottleSchema.default({
|
|
10467
10619
|
cooldownSec: 60,
|
|
@@ -10548,6 +10700,7 @@ var NcConditionDescriptorSchema = object({
|
|
|
10548
10700
|
"schedule",
|
|
10549
10701
|
"plateMatcher",
|
|
10550
10702
|
"packagePhase",
|
|
10703
|
+
"crossingSelect",
|
|
10551
10704
|
"polygonDraw",
|
|
10552
10705
|
"occupancy"
|
|
10553
10706
|
]),
|
|
@@ -10674,7 +10827,10 @@ method(object({}), object({ rules: array(NcRuleSchema) }), { auth: "admin" }), m
|
|
|
10674
10827
|
}), object({ results: array(NcTestResultSchema) }), {
|
|
10675
10828
|
kind: "mutation",
|
|
10676
10829
|
auth: "admin"
|
|
10677
|
-
}), method(object({}), object({
|
|
10830
|
+
}), method(object({}), object({
|
|
10831
|
+
catalog: array(NcConditionDescriptorSchema),
|
|
10832
|
+
taxonomy: NcTaxonomySchema.optional()
|
|
10833
|
+
})), method(object({ filter: NcHistoryFilterSchema.default({ limit: 100 }) }), object({ entries: array(NcHistoryEntrySchema) }), { auth: "admin" });
|
|
10678
10834
|
/**
|
|
10679
10835
|
* TimelapseRule — the STANDALONE scheduled timelapse producer's rule model.
|
|
10680
10836
|
*
|
|
@@ -11683,6 +11839,28 @@ method(object({
|
|
|
11683
11839
|
}), object({ success: literal(true) }), {
|
|
11684
11840
|
kind: "mutation",
|
|
11685
11841
|
auth: "admin"
|
|
11842
|
+
}), method(object({
|
|
11843
|
+
deviceId: number(),
|
|
11844
|
+
/** Absent = the LOWEST assigned profile — a notification attachment is
|
|
11845
|
+
* watched on a phone, and the cheap rendition is the right default. */
|
|
11846
|
+
profile: CamProfileSchema.optional(),
|
|
11847
|
+
aroundMs: number(),
|
|
11848
|
+
preRollSec: number().min(0).max(20).default(3),
|
|
11849
|
+
postRollSec: number().min(0).max(20).default(5),
|
|
11850
|
+
format: _enum(["gif", "mp4"]).default("gif"),
|
|
11851
|
+
maxWidth: number().int().min(120).max(1920).default(480),
|
|
11852
|
+
/** GIF only — MP4 keeps the source cadence. */
|
|
11853
|
+
fps: number().int().min(1).max(15).default(5)
|
|
11854
|
+
}), object({
|
|
11855
|
+
base64: string(),
|
|
11856
|
+
mime: string(),
|
|
11857
|
+
bytes: number().int(),
|
|
11858
|
+
/** The profile actually rendered (what the default resolved to). */
|
|
11859
|
+
profile: CamProfileSchema,
|
|
11860
|
+
durationMs: number()
|
|
11861
|
+
}), {
|
|
11862
|
+
kind: "mutation",
|
|
11863
|
+
auth: "admin"
|
|
11686
11864
|
}), method(_void(), array(CameraStreamSchema).readonly()), method(_void(), array(ProfileSlotSchema).readonly()), method(object({ brokerId: string() }), BrokerStatsSchema), method(object({ brokerId: string() }), object({
|
|
11687
11865
|
probed: boolean(),
|
|
11688
11866
|
summary: string()
|
|
@@ -14813,6 +14991,18 @@ var motionCapability = {
|
|
|
14813
14991
|
name: "motion",
|
|
14814
14992
|
scope: "device",
|
|
14815
14993
|
mode: "singleton",
|
|
14994
|
+
/**
|
|
14995
|
+
* Providers register per-device natives via `ctx.registerNativeCap`
|
|
14996
|
+
* (Hikvision/Reolink/Amcrest/Wyze/HA/Homematic/Alexa/Matter) — there is
|
|
14997
|
+
* NO system singleton provider. Without this flag `resolveCapMount`
|
|
14998
|
+
* derived `{ kind: 'singleton' }`, so `motion.getStatus`/`isDetected`
|
|
14999
|
+
* resolved via `registry.getSingleton('motion')` (always null) and every
|
|
15000
|
+
* call 412'd "provider not available" while bindings listed a live
|
|
15001
|
+
* `motion` native (2026-08-02). The flag routes the router through
|
|
15002
|
+
* `requireDeviceScoped` → `getProviderForDevice`, like `motion-trigger`,
|
|
15003
|
+
* `snapshot` and every other per-device native cap.
|
|
15004
|
+
*/
|
|
15005
|
+
deviceNative: true,
|
|
14816
15006
|
deviceTypes: [DeviceType.Camera, DeviceType.Sensor],
|
|
14817
15007
|
methods: {
|
|
14818
15008
|
/**
|
|
@@ -19745,7 +19935,10 @@ method(object({
|
|
|
19745
19935
|
}), method(object({
|
|
19746
19936
|
deviceId: number(),
|
|
19747
19937
|
caps: array(string()).readonly().optional()
|
|
19748
|
-
}), record(string(), unknown().nullable()))
|
|
19938
|
+
}), record(string(), unknown().nullable())), method(object({
|
|
19939
|
+
deviceIds: array(number()).readonly(),
|
|
19940
|
+
caps: array(string()).readonly().optional()
|
|
19941
|
+
}), record(string(), record(string(), unknown().nullable())));
|
|
19749
19942
|
method(object({ deviceId: number() }), record(string(), record(string(), unknown()))), method(object({
|
|
19750
19943
|
deviceId: number(),
|
|
19751
19944
|
capName: string()
|
|
@@ -20676,6 +20869,36 @@ var TargetKindSchema = object({
|
|
|
20676
20869
|
icon: string(),
|
|
20677
20870
|
/** Stamped by each provider so the concat-fanned catalog stays routable. */
|
|
20678
20871
|
addonId: string(),
|
|
20872
|
+
/**
|
|
20873
|
+
* URL of the kind's bundled BRAND icon, served by the providing addon over
|
|
20874
|
+
* its own `addon-routes` surface (`/addon/<addonId>/icons/<kind>`). Absent
|
|
20875
|
+
* when the addon bundles no icon for that kind — the client then falls back
|
|
20876
|
+
* to a neutral glyph rather than rendering the raw `icon` NAME as text.
|
|
20877
|
+
*
|
|
20878
|
+
* Root-relative on purpose: it resolves against whatever origin serves a web
|
|
20879
|
+
* client, and a native client joins it onto its own hub base.
|
|
20880
|
+
*
|
|
20881
|
+
* DECLARED here deliberately. It used to travel as an undeclared passthrough
|
|
20882
|
+
* field that survived only because the runtime cap-router forwards provider
|
|
20883
|
+
* output verbatim — so every consumer had to re-declare it by hand to stop
|
|
20884
|
+
* its own Zod parse from stripping it, and the whole arrangement would have
|
|
20885
|
+
* broken silently the moment output validation was tightened anywhere.
|
|
20886
|
+
*/
|
|
20887
|
+
iconUrl: string().optional(),
|
|
20888
|
+
/**
|
|
20889
|
+
* Media type of {@link iconUrl} (`image/svg+xml`, `image/png`, …).
|
|
20890
|
+
*
|
|
20891
|
+
* The server knows this and therefore says it, because the client cannot
|
|
20892
|
+
* safely guess: a React-Native client renders SVG and raster through two
|
|
20893
|
+
* DIFFERENT components (`react-native-svg` vs `expo-image` — expo-image does
|
|
20894
|
+
* not decode SVG on iOS/Android), so without this it silently fell back to a
|
|
20895
|
+
* placeholder glyph for every vector icon while the web build looked fine.
|
|
20896
|
+
*
|
|
20897
|
+
* Absent when {@link iconUrl} is absent, or for a legacy provider that has
|
|
20898
|
+
* not been updated — a client that cannot determine the type should prefer
|
|
20899
|
+
* its raster path, which is the safe default for an unknown image.
|
|
20900
|
+
*/
|
|
20901
|
+
iconMediaType: string().optional(),
|
|
20679
20902
|
configSchema: ConfigSchemaPassthrough,
|
|
20680
20903
|
supportsDiscovery: boolean(),
|
|
20681
20904
|
caps: TargetKindCapsSchema
|
|
@@ -21123,6 +21346,29 @@ var MotionEventSchema = object({
|
|
|
21123
21346
|
* Absent on legacy rows ⇒ treat as `pipeline`.
|
|
21124
21347
|
*/
|
|
21125
21348
|
var DetectionSourceSchema = _enum(["pipeline", "onboard"]);
|
|
21349
|
+
/**
|
|
21350
|
+
* The confirmed zone crossing that produced an object event. Present ONLY on
|
|
21351
|
+
* an event emitted BY a crossing (`zone.enter` / `zone.exit`); a movement-state
|
|
21352
|
+
* event (`object.entering` / `leaving` / `stationary` / `loitering`) and an
|
|
21353
|
+
* appearance event carry none, so a rule asking for a direction fails closed
|
|
21354
|
+
* on them.
|
|
21355
|
+
*
|
|
21356
|
+
* Exactly ONE crossing per event: the emitter turns each confirmed crossing
|
|
21357
|
+
* into its own event, so a frame in which a track enters A while leaving B
|
|
21358
|
+
* produces two events with two directions — never one ambiguous row.
|
|
21359
|
+
*
|
|
21360
|
+
* `zoneId` is load-bearing for an EXIT: the event's `zones` list is the
|
|
21361
|
+
* membership the box has NOW, and by definition it no longer contains the zone
|
|
21362
|
+
* that was just left. Without the id here, a zone-scoped rule could never match
|
|
21363
|
+
* the exit it asked for.
|
|
21364
|
+
*/
|
|
21365
|
+
var ZoneCrossingSchema = object({
|
|
21366
|
+
direction: _enum(["enter", "exit"]),
|
|
21367
|
+
/** Admin zone id crossed. */
|
|
21368
|
+
zoneId: string(),
|
|
21369
|
+
/** Zone display name at crossing time (falls back to the id). */
|
|
21370
|
+
zoneName: string().optional()
|
|
21371
|
+
});
|
|
21126
21372
|
var ObjectEventSchema = object({
|
|
21127
21373
|
...BaseEventFields,
|
|
21128
21374
|
kind: literal("object"),
|
|
@@ -21149,6 +21395,12 @@ var ObjectEventSchema = object({
|
|
|
21149
21395
|
zones: array(string()).readonly().optional(),
|
|
21150
21396
|
/** Omitted in slim projection. */
|
|
21151
21397
|
state: TrackStateSchema.optional(),
|
|
21398
|
+
/**
|
|
21399
|
+
* The zone crossing this event IS, when it is one. Absent on every other
|
|
21400
|
+
* event kind (movement state, appearance, package) — see
|
|
21401
|
+
* {@link ZoneCrossingSchema}. Omitted in slim projection.
|
|
21402
|
+
*/
|
|
21403
|
+
zoneCrossing: ZoneCrossingSchema.optional(),
|
|
21152
21404
|
/** Detection-frame dimensions in pixels — let consumers normalize the
|
|
21153
21405
|
* pixel-space `bbox` onto a displayed image. Omitted in slim projection. */
|
|
21154
21406
|
frameWidth: number().optional(),
|
|
@@ -21407,6 +21659,15 @@ DeviceType.Camera, method(object({ deviceId: number() }), array(TrackSchema).rea
|
|
|
21407
21659
|
}), method(object({ deviceId: number() }), EventPruneCountsSchema, {
|
|
21408
21660
|
kind: "mutation",
|
|
21409
21661
|
auth: "admin"
|
|
21662
|
+
}), method(RelocateMediaInputSchema, object({ jobId: string() }), {
|
|
21663
|
+
kind: "mutation",
|
|
21664
|
+
auth: "admin"
|
|
21665
|
+
}), method(object({}), array(RelocateJobSchema).readonly(), {
|
|
21666
|
+
kind: "query",
|
|
21667
|
+
auth: "admin"
|
|
21668
|
+
}), method(object({ jobId: string() }), object({ cancelled: boolean() }), {
|
|
21669
|
+
kind: "mutation",
|
|
21670
|
+
auth: "admin"
|
|
21410
21671
|
}), method(OpsLogQueryInputSchema, array(OpsLogEntrySchema).readonly(), {
|
|
21411
21672
|
kind: "query",
|
|
21412
21673
|
auth: "admin"
|
|
@@ -23886,6 +24147,17 @@ var GetConnectionEndpointsResultSchema = object({ endpoints: array(object({
|
|
|
23886
24147
|
*/
|
|
23887
24148
|
priority: number()
|
|
23888
24149
|
})).readonly() });
|
|
24150
|
+
/**
|
|
24151
|
+
* The chosen outbound endpoint for notification artifacts. `baseUrl: null` =
|
|
24152
|
+
* AUTO (resolved from the candidate ranking at send time); `resolved` reports
|
|
24153
|
+
* what AUTO currently picks, so the UI can show the effective value either way.
|
|
24154
|
+
*/
|
|
24155
|
+
var NotificationEndpointSchema = object({
|
|
24156
|
+
/** The operator's explicit choice, or null for AUTO. */
|
|
24157
|
+
baseUrl: string().nullable(),
|
|
24158
|
+
/** What the ranking currently resolves to (null when nothing is reachable). */
|
|
24159
|
+
resolved: string().nullable()
|
|
24160
|
+
});
|
|
23889
24161
|
var AllowedAddressesSchema = object({
|
|
23890
24162
|
/**
|
|
23891
24163
|
* Allowlist of interface addresses operators have explicitly opted
|
|
@@ -23908,7 +24180,7 @@ method(_void(), ListResultSchema), method(_void(), PreferredSchema), method(obje
|
|
|
23908
24180
|
* to avoid mixed-content blocks in the browser. The public
|
|
23909
24181
|
* tunnel always emits `https://` regardless. */
|
|
23910
24182
|
scheme: _enum(["http", "https"]).optional()
|
|
23911
|
-
}), GetConnectionEndpointsResultSchema), method(_void(), AllowedAddressesSchema), method(AllowedAddressesSchema, object({ success: literal(true) }), { kind: "mutation" }), method(_void(), AllowedAddressesSchema, { kind: "mutation" });
|
|
24183
|
+
}), GetConnectionEndpointsResultSchema), method(_void(), NotificationEndpointSchema), method(object({ baseUrl: string().nullable() }), NotificationEndpointSchema, { kind: "mutation" }), method(_void(), AllowedAddressesSchema), method(AllowedAddressesSchema, object({ success: literal(true) }), { kind: "mutation" }), method(_void(), AllowedAddressesSchema, { kind: "mutation" });
|
|
23912
24184
|
/**
|
|
23913
24185
|
* mesh-network — collection cap for mesh-VPN providers.
|
|
23914
24186
|
*
|
|
@@ -24707,7 +24979,12 @@ var RecordingDeviceUsageSchema = object({
|
|
|
24707
24979
|
var RecordingLocationUsageSchema = object({
|
|
24708
24980
|
/** StorageLocation id; null for the legacy/degraded single-root fallback. */
|
|
24709
24981
|
locationId: string().nullable(),
|
|
24710
|
-
/**
|
|
24982
|
+
/** Every location id sharing this row's PHYSICAL volume (aliases). One row
|
|
24983
|
+
* is emitted per physical disk (2026-07-29): two locations on one root
|
|
24984
|
+
* previously rendered as two identical "disks" with a nonsensical used
|
|
24985
|
+
* split — hydrate attribution across aliases is arbitrary by nature. */
|
|
24986
|
+
locationIds: array(string()).optional(),
|
|
24987
|
+
/** Bytes of recordings stored on this PHYSICAL volume (all aliases). */
|
|
24711
24988
|
usedBytes: number(),
|
|
24712
24989
|
/** Free bytes on the location's volume; null when capacity is unknown (remote). */
|
|
24713
24990
|
availableBytes: number().nullable(),
|
|
@@ -24819,6 +25096,44 @@ method(object({
|
|
|
24819
25096
|
}), method(OpsLogQueryInputSchema, array(OpsLogEntrySchema).readonly(), {
|
|
24820
25097
|
kind: "query",
|
|
24821
25098
|
auth: "admin"
|
|
25099
|
+
}), method(object({
|
|
25100
|
+
deviceId: number(),
|
|
25101
|
+
aroundMs: number(),
|
|
25102
|
+
preRollSec: number().min(0).max(30).default(2),
|
|
25103
|
+
postRollSec: number().min(0).max(30).default(5),
|
|
25104
|
+
maxWidth: number().int().min(120).max(1280).default(480),
|
|
25105
|
+
fps: number().int().min(1).max(15).default(5)
|
|
25106
|
+
}), object({
|
|
25107
|
+
gifBase64: string(),
|
|
25108
|
+
fromMs: number(),
|
|
25109
|
+
toMs: number()
|
|
25110
|
+
}), {
|
|
25111
|
+
kind: "mutation",
|
|
25112
|
+
auth: "admin"
|
|
25113
|
+
}), method(object({
|
|
25114
|
+
deviceId: number(),
|
|
25115
|
+
aroundMs: number(),
|
|
25116
|
+
preRollSec: number().min(0).max(30).default(3),
|
|
25117
|
+
postRollSec: number().min(0).max(30).default(7),
|
|
25118
|
+
maxWidth: number().int().min(160).max(1920).default(640)
|
|
25119
|
+
}), object({
|
|
25120
|
+
clipBase64: string(),
|
|
25121
|
+
mime: string(),
|
|
25122
|
+
fromMs: number(),
|
|
25123
|
+
toMs: number(),
|
|
25124
|
+
bytes: number().int()
|
|
25125
|
+
}), {
|
|
25126
|
+
kind: "mutation",
|
|
25127
|
+
auth: "admin"
|
|
25128
|
+
}), method(RelocateFootageInputSchema, object({ jobId: string() }), {
|
|
25129
|
+
kind: "mutation",
|
|
25130
|
+
auth: "admin"
|
|
25131
|
+
}), method(object({}), array(RelocateJobSchema).readonly(), {
|
|
25132
|
+
kind: "query",
|
|
25133
|
+
auth: "admin"
|
|
25134
|
+
}), method(object({ jobId: string() }), object({ cancelled: boolean() }), {
|
|
25135
|
+
kind: "mutation",
|
|
25136
|
+
auth: "admin"
|
|
24822
25137
|
});
|
|
24823
25138
|
/**
|
|
24824
25139
|
* `recordingExport` cap — render a footage time range into a single downloadable
|
|
@@ -26410,6 +26725,12 @@ Object.freeze({
|
|
|
26410
26725
|
addonId: null,
|
|
26411
26726
|
access: "view"
|
|
26412
26727
|
},
|
|
26728
|
+
"deviceManager.getDeviceStatusAggregateBatch": {
|
|
26729
|
+
capName: "device-manager",
|
|
26730
|
+
capScope: "system",
|
|
26731
|
+
addonId: null,
|
|
26732
|
+
access: "view"
|
|
26733
|
+
},
|
|
26413
26734
|
"deviceManager.getLinkedDevices": {
|
|
26414
26735
|
capName: "device-manager",
|
|
26415
26736
|
capScope: "system",
|
|
@@ -27304,6 +27625,12 @@ Object.freeze({
|
|
|
27304
27625
|
addonId: null,
|
|
27305
27626
|
access: "view"
|
|
27306
27627
|
},
|
|
27628
|
+
"localNetwork.getNotificationEndpoint": {
|
|
27629
|
+
capName: "local-network",
|
|
27630
|
+
capScope: "system",
|
|
27631
|
+
addonId: null,
|
|
27632
|
+
access: "view"
|
|
27633
|
+
},
|
|
27307
27634
|
"localNetwork.getPreferred": {
|
|
27308
27635
|
capName: "local-network",
|
|
27309
27636
|
capScope: "system",
|
|
@@ -27328,6 +27655,12 @@ Object.freeze({
|
|
|
27328
27655
|
addonId: null,
|
|
27329
27656
|
access: "create"
|
|
27330
27657
|
},
|
|
27658
|
+
"localNetwork.setNotificationEndpoint": {
|
|
27659
|
+
capName: "local-network",
|
|
27660
|
+
capScope: "system",
|
|
27661
|
+
addonId: null,
|
|
27662
|
+
access: "create"
|
|
27663
|
+
},
|
|
27331
27664
|
"lockControl.lock": {
|
|
27332
27665
|
capName: "lock-control",
|
|
27333
27666
|
capScope: "device",
|
|
@@ -27970,6 +28303,12 @@ Object.freeze({
|
|
|
27970
28303
|
addonId: null,
|
|
27971
28304
|
access: "create"
|
|
27972
28305
|
},
|
|
28306
|
+
"pipelineAnalytics.cancelMediaRelocate": {
|
|
28307
|
+
capName: "pipeline-analytics",
|
|
28308
|
+
capScope: "device",
|
|
28309
|
+
addonId: null,
|
|
28310
|
+
access: "create"
|
|
28311
|
+
},
|
|
27973
28312
|
"pipelineAnalytics.clearTracks": {
|
|
27974
28313
|
capName: "pipeline-analytics",
|
|
27975
28314
|
capScope: "device",
|
|
@@ -28024,6 +28363,12 @@ Object.freeze({
|
|
|
28024
28363
|
addonId: null,
|
|
28025
28364
|
access: "view"
|
|
28026
28365
|
},
|
|
28366
|
+
"pipelineAnalytics.getMediaRelocateStatus": {
|
|
28367
|
+
capName: "pipeline-analytics",
|
|
28368
|
+
capScope: "device",
|
|
28369
|
+
addonId: null,
|
|
28370
|
+
access: "view"
|
|
28371
|
+
},
|
|
28027
28372
|
"pipelineAnalytics.getMotionEvents": {
|
|
28028
28373
|
capName: "pipeline-analytics",
|
|
28029
28374
|
capScope: "device",
|
|
@@ -28096,6 +28441,12 @@ Object.freeze({
|
|
|
28096
28441
|
addonId: null,
|
|
28097
28442
|
access: "create"
|
|
28098
28443
|
},
|
|
28444
|
+
"pipelineAnalytics.relocateMedia": {
|
|
28445
|
+
capName: "pipeline-analytics",
|
|
28446
|
+
capScope: "device",
|
|
28447
|
+
addonId: null,
|
|
28448
|
+
access: "create"
|
|
28449
|
+
},
|
|
28099
28450
|
"pipelineAnalytics.searchObjectEvents": {
|
|
28100
28451
|
capName: "pipeline-analytics",
|
|
28101
28452
|
capScope: "device",
|
|
@@ -28858,6 +29209,12 @@ Object.freeze({
|
|
|
28858
29209
|
addonId: null,
|
|
28859
29210
|
access: "create"
|
|
28860
29211
|
},
|
|
29212
|
+
"recording.cancelRelocate": {
|
|
29213
|
+
capName: "recording",
|
|
29214
|
+
capScope: "system",
|
|
29215
|
+
addonId: null,
|
|
29216
|
+
access: "create"
|
|
29217
|
+
},
|
|
28861
29218
|
"recording.deleteFootprint": {
|
|
28862
29219
|
capName: "recording",
|
|
28863
29220
|
capScope: "system",
|
|
@@ -28888,6 +29245,12 @@ Object.freeze({
|
|
|
28888
29245
|
addonId: null,
|
|
28889
29246
|
access: "view"
|
|
28890
29247
|
},
|
|
29248
|
+
"recording.getRelocateStatus": {
|
|
29249
|
+
capName: "recording",
|
|
29250
|
+
capScope: "system",
|
|
29251
|
+
addonId: null,
|
|
29252
|
+
access: "view"
|
|
29253
|
+
},
|
|
28891
29254
|
"recording.getStorageUsage": {
|
|
28892
29255
|
capName: "recording",
|
|
28893
29256
|
capScope: "system",
|
|
@@ -28918,6 +29281,24 @@ Object.freeze({
|
|
|
28918
29281
|
addonId: null,
|
|
28919
29282
|
access: "view"
|
|
28920
29283
|
},
|
|
29284
|
+
"recording.relocateFootage": {
|
|
29285
|
+
capName: "recording",
|
|
29286
|
+
capScope: "system",
|
|
29287
|
+
addonId: null,
|
|
29288
|
+
access: "create"
|
|
29289
|
+
},
|
|
29290
|
+
"recording.renderClip": {
|
|
29291
|
+
capName: "recording",
|
|
29292
|
+
capScope: "system",
|
|
29293
|
+
addonId: null,
|
|
29294
|
+
access: "create"
|
|
29295
|
+
},
|
|
29296
|
+
"recording.renderGif": {
|
|
29297
|
+
capName: "recording",
|
|
29298
|
+
capScope: "system",
|
|
29299
|
+
addonId: null,
|
|
29300
|
+
access: "create"
|
|
29301
|
+
},
|
|
28921
29302
|
"recording.rescanStorage": {
|
|
28922
29303
|
capName: "recording",
|
|
28923
29304
|
capScope: "system",
|
|
@@ -29512,6 +29893,12 @@ Object.freeze({
|
|
|
29512
29893
|
addonId: null,
|
|
29513
29894
|
access: "create"
|
|
29514
29895
|
},
|
|
29896
|
+
"streamBroker.renderPreBufferClip": {
|
|
29897
|
+
capName: "stream-broker",
|
|
29898
|
+
capScope: "system",
|
|
29899
|
+
addonId: null,
|
|
29900
|
+
access: "create"
|
|
29901
|
+
},
|
|
29515
29902
|
"streamBroker.restartProfile": {
|
|
29516
29903
|
capName: "stream-broker",
|
|
29517
29904
|
capScope: "system",
|