@camstack/addon-provider-homeassistant 1.2.32 → 1.2.34
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 +1 -1
- package/dist/addon.mjs +1 -1
- package/dist/{dist-BMrkrIHs.mjs → dist-AzTGVuqy.mjs} +187 -45
- package/dist/{dist-BxZFHIBC.js → dist-ubUo7WrJ.js} +187 -45
- package/dist/ha-export/ha-export.addon.js +1 -1
- package/dist/ha-export/ha-export.addon.mjs +1 -1
- package/package.json +1 -1
package/dist/addon.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
2
|
-
const require_dist = require("./dist-
|
|
2
|
+
const require_dist = require("./dist-ubUo7WrJ.js");
|
|
3
3
|
let node_crypto = require("node:crypto");
|
|
4
4
|
let node_zlib = require("node:zlib");
|
|
5
5
|
//#region src/ha-device-source.ts
|
package/dist/addon.mjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { $ as pressureSensorCapability, A as coverCapability, B as imageCapability, C as buttonCapability, Ct as record, D as connectivityCapability, Dt as url, E as colorCapability, Et as unknown, F as fanControlCapability, G as normalizeUnit, H as lockControlCapability, I as floodCapability, J as numericSensorCapability, K as notificationOutputCapability, L as gasCapability, N as enumSensorCapability, O as contactCapability, Ot as EventCategory, P as eventEmitterCapability, Q as presenceCapability, R as humidifierCapability, S as buildAddonRouteProvider, St as object, T as climateControlCapability, Tt as union, U as mediaPlayerCapability, V as lawnMowerControlCapability, W as motionCapability, X as powerMeterCapability, Z as prepareNotification, _ as batteryCapability, _t as _enum, at as updateCapability, b as brightnessCapability, bt as literal, ct as vibrationCapability, d as accessoriesCapability, dt as errMsg, et as scriptRunnerCapability, f as addonRoutesCapability, g as automationControlCapability, gt as createEvent, h as ambientLightSensorCapability, ht as DeviceType, it as temperatureSensorCapability, j as deviceAdoptionCapability, k as controlCapability, lt as waterHeaterCapability, m as alarmPanelCapability, mt as DeviceRole, n as BaseDevice, nt as switchCapability, o as EnumSensorDateTimeFormatSchema, ot as vacuumControlCapability, p as airQualitySensorCapability, pt as DeviceFeature, q as notifierCapability, r as BaseDeviceProvider, rt as tamperCapability, st as valveCapability, tt as smokeCapability, u as TargetSchema, ut as weatherCapability, v as bestLocationMatch, vt as array, w as carbonMonoxideCapability, wt as string, x as brokerCapability, xt as number, y as binaryCapability, yt as discriminatedUnion, z as humiditySensorCapability } from "./dist-
|
|
1
|
+
import { $ as pressureSensorCapability, A as coverCapability, B as imageCapability, C as buttonCapability, Ct as record, D as connectivityCapability, Dt as url, E as colorCapability, Et as unknown, F as fanControlCapability, G as normalizeUnit, H as lockControlCapability, I as floodCapability, J as numericSensorCapability, K as notificationOutputCapability, L as gasCapability, N as enumSensorCapability, O as contactCapability, Ot as EventCategory, P as eventEmitterCapability, Q as presenceCapability, R as humidifierCapability, S as buildAddonRouteProvider, St as object, T as climateControlCapability, Tt as union, U as mediaPlayerCapability, V as lawnMowerControlCapability, W as motionCapability, X as powerMeterCapability, Z as prepareNotification, _ as batteryCapability, _t as _enum, at as updateCapability, b as brightnessCapability, bt as literal, ct as vibrationCapability, d as accessoriesCapability, dt as errMsg, et as scriptRunnerCapability, f as addonRoutesCapability, g as automationControlCapability, gt as createEvent, h as ambientLightSensorCapability, ht as DeviceType, it as temperatureSensorCapability, j as deviceAdoptionCapability, k as controlCapability, lt as waterHeaterCapability, m as alarmPanelCapability, mt as DeviceRole, n as BaseDevice, nt as switchCapability, o as EnumSensorDateTimeFormatSchema, ot as vacuumControlCapability, p as airQualitySensorCapability, pt as DeviceFeature, q as notifierCapability, r as BaseDeviceProvider, rt as tamperCapability, st as valveCapability, tt as smokeCapability, u as TargetSchema, ut as weatherCapability, v as bestLocationMatch, vt as array, w as carbonMonoxideCapability, wt as string, x as brokerCapability, xt as number, y as binaryCapability, yt as discriminatedUnion, z as humiditySensorCapability } from "./dist-AzTGVuqy.mjs";
|
|
2
2
|
import { randomUUID } from "node:crypto";
|
|
3
3
|
import { brotliCompressSync, deflateSync, gzipSync } from "node:zlib";
|
|
4
4
|
//#region src/ha-device-source.ts
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
//#region ../types/dist/event-category-
|
|
1
|
+
//#region ../types/dist/event-category-XfKNtfCc.mjs
|
|
2
2
|
var EventCategory = /* @__PURE__ */ function(EventCategory) {
|
|
3
3
|
EventCategory["SystemBoot"] = "system.boot";
|
|
4
4
|
EventCategory["SystemAddonsReady"] = "system.addons-ready";
|
|
@@ -15,9 +15,10 @@ var EventCategory = /* @__PURE__ */ function(EventCategory) {
|
|
|
15
15
|
EventCategory["SystemRestartCompleted"] = "system.restart-completed";
|
|
16
16
|
/**
|
|
17
17
|
* A newer addon or server-root package version was found by the
|
|
18
|
-
* authoritative registry check. Emitted once
|
|
19
|
-
* `(
|
|
20
|
-
*
|
|
18
|
+
* authoritative registry check. Emitted once when any observed
|
|
19
|
+
* `latestVersion` changes (or a package/node first appears behind);
|
|
20
|
+
* the payload carries the full currently-available list. Repeated
|
|
21
|
+
* polling of the same latests is silent.
|
|
21
22
|
*/
|
|
22
23
|
EventCategory["UpdateAvailable"] = "update.available";
|
|
23
24
|
/**
|
|
@@ -36,6 +37,22 @@ var EventCategory = /* @__PURE__ */ function(EventCategory) {
|
|
|
36
37
|
EventCategory["AddonInstalled"] = "addon.installed";
|
|
37
38
|
EventCategory["AddonUninstalled"] = "addon.uninstalled";
|
|
38
39
|
EventCategory["AddonCrashed"] = "addon.crashed";
|
|
40
|
+
/**
|
|
41
|
+
* A RUNNER the D6 crash circuit-breaker gave up on — terminal.
|
|
42
|
+
*
|
|
43
|
+
* `AddonCrashed` is the routine, self-healing fact ("it crashed; it is being
|
|
44
|
+
* respawned"); this is the one that never resolves itself. Emitted exactly
|
|
45
|
+
* once per trip, by `process-service.ts`, carrying the node, the runner, the
|
|
46
|
+
* addons it hosted and the crash count that tripped the breaker.
|
|
47
|
+
*
|
|
48
|
+
* It exists because a runner marked terminally `failed` used to be SILENT:
|
|
49
|
+
* on 2026-08-18 the `recorder` runner died of three unhandled ffmpeg spawn
|
|
50
|
+
* errors, the breaker stopped respawning it (correctly), `/health` kept
|
|
51
|
+
* returning 200, and fleet-wide recording was gone for 3h15 before the
|
|
52
|
+
* operator's phone told him. The Notification Center's system-event intake
|
|
53
|
+
* consumes this category and maps it to the `addon-crash-loop` kind.
|
|
54
|
+
*/
|
|
55
|
+
EventCategory["AddonRunnerFailed"] = "addon.runner-failed";
|
|
39
56
|
EventCategory["AddonError"] = "addon.error";
|
|
40
57
|
EventCategory["AddonPageReady"] = "addon.page-ready";
|
|
41
58
|
EventCategory["AddonWidgetReady"] = "addon.widget-ready";
|
|
@@ -7666,6 +7683,10 @@ var RecordingBandSchema = object({
|
|
|
7666
7683
|
preBufferSec: number().min(0).optional(),
|
|
7667
7684
|
postBufferSec: number().min(0).optional()
|
|
7668
7685
|
});
|
|
7686
|
+
({
|
|
7687
|
+
preBufferSec: 10,
|
|
7688
|
+
postBufferSec: 30
|
|
7689
|
+
}).postBufferSec * 1e3;
|
|
7669
7690
|
/**
|
|
7670
7691
|
* Per-device retention overrides. Every field is optional; an unset or `0`
|
|
7671
7692
|
* value inherits the node-wide recorder default. Only footage-lifetime limits
|
|
@@ -7713,6 +7734,12 @@ var RecordingConfigSchema = object({
|
|
|
7713
7734
|
/** DERIVED summary of `bands`, stamped by the recorder on every save.
|
|
7714
7735
|
* Authoring it has no effect — see {@link RecordingStorageModeSchema}. */
|
|
7715
7736
|
mode: RecordingStorageModeSchema.optional(),
|
|
7737
|
+
/**
|
|
7738
|
+
* Which assigned broker slots to record. Absent / empty = {@link
|
|
7739
|
+
* DEFAULT_RECORDING_PROFILES} (`high`+`low`) intersected with the
|
|
7740
|
+
* camera's currently assigned slots — never `mid` unless the operator
|
|
7741
|
+
* picks it, and never a slot the broker has not assigned.
|
|
7742
|
+
*/
|
|
7716
7743
|
profiles: array(CamProfileSchema).optional(),
|
|
7717
7744
|
segmentSeconds: number().int().positive().optional(),
|
|
7718
7745
|
/**
|
|
@@ -7793,7 +7820,11 @@ var RelocateFootageInputSchema = object({
|
|
|
7793
7820
|
profiles: array(string()).optional(),
|
|
7794
7821
|
/** Copy throttle in MB/s (default 40) — the drain is a background chore,
|
|
7795
7822
|
* never allowed to starve live writers. */
|
|
7796
|
-
throttleMbps: number().min(1).max(1e3).optional()
|
|
7823
|
+
throttleMbps: number().min(1).max(1e3).optional(),
|
|
7824
|
+
/** Move only segments whose startMs is >= this. Absent = the whole source
|
|
7825
|
+
* pile. Used when a full drain is too expensive and the operator only
|
|
7826
|
+
* wants the recent window on the new disk. */
|
|
7827
|
+
sinceMs: number().int().optional()
|
|
7797
7828
|
});
|
|
7798
7829
|
/** Internal, lease-scoped participant operation. It is intentionally separate
|
|
7799
7830
|
* from persistent recording settings: a migration never changes
|
|
@@ -14827,6 +14858,7 @@ var NcSystemEventKindSchema = _enum([
|
|
|
14827
14858
|
"node-offline",
|
|
14828
14859
|
"node-inference-unavailable",
|
|
14829
14860
|
"detection-blind",
|
|
14861
|
+
"addon-crash-loop",
|
|
14830
14862
|
"addon-update-available",
|
|
14831
14863
|
"server-update-available",
|
|
14832
14864
|
"alarm-triggered",
|
|
@@ -14834,6 +14866,9 @@ var NcSystemEventKindSchema = _enum([
|
|
|
14834
14866
|
"alarm-disarmed",
|
|
14835
14867
|
"alarm-arming",
|
|
14836
14868
|
"alarm-arm-refused",
|
|
14869
|
+
"addon-updated",
|
|
14870
|
+
"server-updated",
|
|
14871
|
+
"export-completed",
|
|
14837
14872
|
"camera-online",
|
|
14838
14873
|
"camera-offline",
|
|
14839
14874
|
"camera-disabled",
|
|
@@ -16733,13 +16768,19 @@ var RetrainStatusSchema = _enum([
|
|
|
16733
16768
|
* "never marked" from "already trained" must read `retrainStatus`.
|
|
16734
16769
|
*
|
|
16735
16770
|
* `debug` does NOT pin; it is attention, not durability.
|
|
16771
|
+
*
|
|
16772
|
+
* `favourited` IS a BOOLEAN pin (durability bit), not a retrain lifecycle.
|
|
16773
|
+
* A favourited track is skipped by retention the same way `staging` is, but
|
|
16774
|
+
* it does not enter `none|staging|trained` and has no staging budget.
|
|
16736
16775
|
*/
|
|
16737
16776
|
var TrackFlagFields = {
|
|
16738
16777
|
/** Operator marked this track as training material — i.e. `retrainStatus` is
|
|
16739
16778
|
* `'staging'`. */
|
|
16740
16779
|
markForTrain: boolean().optional(),
|
|
16741
16780
|
/** Operator marked this track for diagnostic attention. */
|
|
16742
|
-
debug: boolean().optional()
|
|
16781
|
+
debug: boolean().optional(),
|
|
16782
|
+
/** Operator favourited this track. Pins it against pruning. */
|
|
16783
|
+
favourited: boolean().optional()
|
|
16743
16784
|
};
|
|
16744
16785
|
/**
|
|
16745
16786
|
* The lifecycle field itself, on the READ surfaces only (`Track`, `KeyEvent`).
|
|
@@ -16764,6 +16805,7 @@ var TrackFlagsSchema = object({
|
|
|
16764
16805
|
trackId: string(),
|
|
16765
16806
|
markForTrain: boolean(),
|
|
16766
16807
|
debug: boolean(),
|
|
16808
|
+
favourited: boolean(),
|
|
16767
16809
|
/** The lifecycle state the boolean was derived from. Required here (unlike on
|
|
16768
16810
|
* a track row) because this shape is only ever produced by the write body,
|
|
16769
16811
|
* which always knows it — and a surface that has just written needs to render
|
|
@@ -17396,6 +17438,12 @@ var TrackCascadeCountsSchema = object({
|
|
|
17396
17438
|
/** Per-track CLIP search vectors removed (best-effort). */
|
|
17397
17439
|
embeddings: number().int()
|
|
17398
17440
|
});
|
|
17441
|
+
/** Disk-wins reconcile: media rows whose blobs are gone, then empty tracks. */
|
|
17442
|
+
var DiskReconcileCountsSchema = object({
|
|
17443
|
+
mediaDropped: number().int(),
|
|
17444
|
+
tracks: number().int(),
|
|
17445
|
+
events: number().int()
|
|
17446
|
+
});
|
|
17399
17447
|
/** Event-store footprint for one camera. */
|
|
17400
17448
|
var EventStoreDeviceFootprintSchema = object({
|
|
17401
17449
|
deviceId: number(),
|
|
@@ -17572,6 +17620,9 @@ DeviceType.Camera, method(object({ deviceId: number() }), array(TrackSchema).rea
|
|
|
17572
17620
|
}), method(object({ deviceId: number() }), TrackCascadeCountsSchema, {
|
|
17573
17621
|
kind: "mutation",
|
|
17574
17622
|
auth: "admin"
|
|
17623
|
+
}), method(object({ deviceId: number() }), DiskReconcileCountsSchema, {
|
|
17624
|
+
kind: "mutation",
|
|
17625
|
+
auth: "admin"
|
|
17575
17626
|
}), method(object({
|
|
17576
17627
|
deviceId: number(),
|
|
17577
17628
|
trackIds: array(string()).min(1)
|
|
@@ -19122,6 +19173,24 @@ var CameraStatusDegradationSchema = object({
|
|
|
19122
19173
|
*
|
|
19123
19174
|
* See spec: `docs/superpowers/specs/2026-06-24-camera-status-aggregator-cap.md`
|
|
19124
19175
|
*/
|
|
19176
|
+
var DiskReconcileJobSchema = object({
|
|
19177
|
+
state: _enum([
|
|
19178
|
+
"idle",
|
|
19179
|
+
"running",
|
|
19180
|
+
"done",
|
|
19181
|
+
"error"
|
|
19182
|
+
]),
|
|
19183
|
+
total: number().int().nonnegative(),
|
|
19184
|
+
completed: number().int().nonnegative(),
|
|
19185
|
+
currentDeviceId: number().int().nullable(),
|
|
19186
|
+
failed: array(number().int()).readonly(),
|
|
19187
|
+
mediaDropped: number().int().nonnegative(),
|
|
19188
|
+
tracks: number().int().nonnegative(),
|
|
19189
|
+
events: number().int().nonnegative(),
|
|
19190
|
+
startedAtMs: number().int().nullable(),
|
|
19191
|
+
finishedAtMs: number().int().nullable(),
|
|
19192
|
+
error: string().nullable()
|
|
19193
|
+
});
|
|
19125
19194
|
var CameraStatusSchema = object({
|
|
19126
19195
|
deviceId: number(),
|
|
19127
19196
|
assignment: CameraAssignmentStatusSchema,
|
|
@@ -19353,7 +19422,10 @@ method(StorageMigrationLeaseInputSchema, object({ paused: literal(true) }), {
|
|
|
19353
19422
|
}), CameraSwitchGroupSchema, {
|
|
19354
19423
|
kind: "mutation",
|
|
19355
19424
|
auth: "admin"
|
|
19356
|
-
}), method(object({ deviceId: number() }), CameraStatusSchema), method(object({ deviceIds: array(number()).optional() }), array(CameraStatusSchema).readonly()), method(_void(),
|
|
19425
|
+
}), method(object({ deviceId: number() }), CameraStatusSchema), method(object({ deviceIds: array(number()).optional() }), array(CameraStatusSchema).readonly()), method(_void(), DiskReconcileJobSchema, {
|
|
19426
|
+
kind: "mutation",
|
|
19427
|
+
auth: "admin"
|
|
19428
|
+
}), method(_void(), DiskReconcileJobSchema, { auth: "admin" }), method(_void(), array(PipelineTemplateSchema).readonly()), method(object({
|
|
19357
19429
|
name: string(),
|
|
19358
19430
|
description: string().optional(),
|
|
19359
19431
|
config: CameraPipelineConfigSchema
|
|
@@ -19758,7 +19830,14 @@ targets: array(object({
|
|
|
19758
19830
|
"sleeping",
|
|
19759
19831
|
"unreachable",
|
|
19760
19832
|
"waking"
|
|
19761
|
-
]).nullable()
|
|
19833
|
+
]).nullable(),
|
|
19834
|
+
/** A battery camera (whatever its current state). An AWAKE battery
|
|
19835
|
+
* camera is deliberately NOT recaptured on the poll cadence — every
|
|
19836
|
+
* capture is a camera hit that would keep it out of sleep — so its
|
|
19837
|
+
* cached frame legitimately ages past the currency ceiling while
|
|
19838
|
+
* nothing is streaming. A surface must keep painting it (a fresh
|
|
19839
|
+
* frame is captured at each wake), not blank to "unavailable". */
|
|
19840
|
+
battery: boolean()
|
|
19762
19841
|
})));
|
|
19763
19842
|
/**
|
|
19764
19843
|
* `sso-bridge` — internal hub-only cap that lets SSO-style auth
|
|
@@ -20419,20 +20498,6 @@ var VectorStatsResultSchema = object({
|
|
|
20419
20498
|
exact: boolean()
|
|
20420
20499
|
});
|
|
20421
20500
|
method(VectorDeclareIndexInputSchema, _void(), { kind: "mutation" }), method(VectorUpsertInputSchema, VectorUpsertResultSchema, { kind: "mutation" }), method(VectorQueryInputSchema, VectorQueryResultSchema), method(VectorGetInputSchema, VectorGetResultSchema), method(VectorDeleteInputSchema, VectorDeleteResultSchema, { kind: "mutation" }), method(VectorDeleteByFilterInputSchema, VectorDeleteResultSchema, { kind: "mutation" }), method(VectorStatsInputSchema, VectorStatsResultSchema);
|
|
20422
|
-
/**
|
|
20423
|
-
* `videoclips` — the unified, navigable-clip surface for a camera.
|
|
20424
|
-
*
|
|
20425
|
-
* A device-scoped WRAPPER cap (like `pipeline-analytics`): exactly one active
|
|
20426
|
-
* provider per device, substitutable. The DEFAULT provider (registered by
|
|
20427
|
-
* `addon-post-analysis`, `defaultActive: true`) composes the analytics event
|
|
20428
|
-
* log (markers + thumbnails) with the recorder's `getPlaybackManifest` — a clip
|
|
20429
|
-
* is a time-WINDOW over existing footage, never a separate file. A camera that
|
|
20430
|
-
* exposes NATIVE onboard clips (Reolink/Hikvision NVR) can later substitute the
|
|
20431
|
-
* wrapper provider for its device and serve its own clip catalog + URLs.
|
|
20432
|
-
*
|
|
20433
|
-
* A `Clip` is purely time-based (subtree-blind): playback resolves segments by
|
|
20434
|
-
* temporal overlap, so the API never decides `continuous` vs `events`.
|
|
20435
|
-
*/
|
|
20436
20501
|
var ClipSchema = object({
|
|
20437
20502
|
/** Opaque, provider-namespaced id. The default provider encodes the time
|
|
20438
20503
|
* window so `getClipPlayback` is self-contained (no event re-query). */
|
|
@@ -20449,8 +20514,57 @@ var ClipSchema = object({
|
|
|
20449
20514
|
startMs: number(),
|
|
20450
20515
|
endMs: number()
|
|
20451
20516
|
}),
|
|
20452
|
-
/**
|
|
20453
|
-
thumbnail
|
|
20517
|
+
/**
|
|
20518
|
+
* Lazy thumbnail URL, never inlined.
|
|
20519
|
+
*
|
|
20520
|
+
* Recording-derived clips (events-mode keep-window, and the prepared
|
|
20521
|
+
* continuous event+fragment visit) MUST use the snapshot of the **main
|
|
20522
|
+
* event of the interval** — `getEventMedia({ eventId, kind: 'snapshot' })`
|
|
20523
|
+
* of the event that owns `kind` (object > motion > audio). Do not extract
|
|
20524
|
+
* a keyframe from the recorded segments. Other providers (onboard, HKSV)
|
|
20525
|
+
* mint their own stills.
|
|
20526
|
+
*
|
|
20527
|
+
* **VOUCHED, never fabricated.** A provider emits this only for an event it
|
|
20528
|
+
* has CONFIRMED owns at least one media row (its own, or its owning track's).
|
|
20529
|
+
* Absent is meaningful — "this visit has no event still" — never "we did not
|
|
20530
|
+
* look". Stamping it from a URL template made 35% of one camera's clips point
|
|
20531
|
+
* at a 404 (device 3836, 2026-08-17: 64 of 179 clips dead, 63 of them motion).
|
|
20532
|
+
* A read that FAILS drops the claim; it never invents it.
|
|
20533
|
+
*/
|
|
20534
|
+
thumbnail: string().optional(),
|
|
20535
|
+
/**
|
|
20536
|
+
* An instant INSIDE this visit's footage, hole-safe, where a recorded still
|
|
20537
|
+
* can be decoded. Present whenever the visit came from recorded availability;
|
|
20538
|
+
* absent on a per-event padded window (there is no footage to promise).
|
|
20539
|
+
*
|
|
20540
|
+
* This is not a thumbnail and not a second byte path: it is the argument to
|
|
20541
|
+
* the recorder's existing still route. The surface — never the provider —
|
|
20542
|
+
* decides whether to use it. It is the midpoint of the visit's LONGEST
|
|
20543
|
+
* contiguous range, not of the visit: a visit spans its holes by
|
|
20544
|
+
* construction, so a naive midpoint lands in dead air.
|
|
20545
|
+
*/
|
|
20546
|
+
stillAtMs: number().optional(),
|
|
20547
|
+
/**
|
|
20548
|
+
* Analytics event ids that overlap this visit — a BOUNDED sample, newest
|
|
20549
|
+
* first within kind (object → motion → audio), capped at
|
|
20550
|
+
* {@link MAX_CLIP_EVENT_IDS}. Empty on footage-only clips.
|
|
20551
|
+
*
|
|
20552
|
+
* Bounded because it is not a payload the surface pages through: one visit on
|
|
20553
|
+
* device 615 carried 2 345 ids, and `eventIds` was 99% of a 153 KB
|
|
20554
|
+
* camera-day. Read {@link eventCount} for the true total.
|
|
20555
|
+
*/
|
|
20556
|
+
eventIds: array(string()).optional(),
|
|
20557
|
+
/** How many analytics events actually overlap this visit. Differs from
|
|
20558
|
+
* `eventIds.length` exactly when the sample was capped — so a truncated
|
|
20559
|
+
* list is never mistaken for a quiet visit. */
|
|
20560
|
+
eventCount: number().int().nonnegative().optional(),
|
|
20561
|
+
/** Intra-visit footage holes (GOP rolls, discarded segments) still shorter
|
|
20562
|
+
* than `VISIT_MERGE_GAP_MS`. Playback concatenates around them; the timeline
|
|
20563
|
+
* bar keeps showing them via `recording.getAvailability`. */
|
|
20564
|
+
holes: array(object({
|
|
20565
|
+
startMs: number(),
|
|
20566
|
+
endMs: number()
|
|
20567
|
+
})).optional()
|
|
20454
20568
|
});
|
|
20455
20569
|
var ClipPlaybackSchema = object({
|
|
20456
20570
|
/** HLS master URL through the hub data-plane (Range + token in path). */
|
|
@@ -20986,7 +21100,14 @@ var SearchResultSchema = object({
|
|
|
20986
21100
|
});
|
|
20987
21101
|
var AutoUpdateSettingsSchema = object({
|
|
20988
21102
|
channel: ChannelSchema,
|
|
20989
|
-
intervalSeconds: number()
|
|
21103
|
+
intervalSeconds: number(),
|
|
21104
|
+
/**
|
|
21105
|
+
* Cadence of the "an update exists" POLLER, in seconds. Independent of
|
|
21106
|
+
* `channel`: the poller runs while auto-apply is `off`, because being told
|
|
21107
|
+
* about a publish and installing it are different decisions. Clamped
|
|
21108
|
+
* server-side to 900 s … 604800 s; defaults to 21600 s (6 h).
|
|
21109
|
+
*/
|
|
21110
|
+
updateCheckIntervalSeconds: number()
|
|
20990
21111
|
});
|
|
20991
21112
|
var AddonAutoUpdateSchema = ChannelWithInheritSchema;
|
|
20992
21113
|
var RestartAddonResultSchema = unknown();
|
|
@@ -21127,7 +21248,9 @@ method(_void(), array(AddonListItemSchema).readonly()), method(object({
|
|
|
21127
21248
|
auth: "admin"
|
|
21128
21249
|
}), method(_void(), AutoUpdateSettingsSchema, { auth: "admin" }), method(object({
|
|
21129
21250
|
channel: ChannelSchema,
|
|
21130
|
-
intervalSeconds: number().min(300).max(86400).optional()
|
|
21251
|
+
intervalSeconds: number().min(300).max(86400).optional(),
|
|
21252
|
+
/** Availability-poll cadence; see AutoUpdateSettingsSchema. */
|
|
21253
|
+
updateCheckIntervalSeconds: number().min(900).max(604800).optional()
|
|
21131
21254
|
}), unknown(), {
|
|
21132
21255
|
kind: "mutation",
|
|
21133
21256
|
auth: "admin"
|
|
@@ -26825,7 +26948,9 @@ var ExportOptionsSchema = object({
|
|
|
26825
26948
|
includeAudio: boolean(),
|
|
26826
26949
|
maxLifeMs: number().int().positive(),
|
|
26827
26950
|
deleteAfterDownload: boolean(),
|
|
26828
|
-
title: string().max(200).optional()
|
|
26951
|
+
title: string().max(200).optional(),
|
|
26952
|
+
/** Notification-output target ids to ping when this export becomes ready. */
|
|
26953
|
+
notifyTargetIds: array(string().min(1)).max(20).optional()
|
|
26829
26954
|
}).superRefine((v, ctx) => {
|
|
26830
26955
|
if (v.speed !== void 0 && v.timelapse !== void 0) ctx.addIssue({
|
|
26831
26956
|
code: ZodIssueCode.custom,
|
|
@@ -26884,10 +27009,18 @@ var ExportBytesSchema = object({
|
|
|
26884
27009
|
});
|
|
26885
27010
|
method(object({
|
|
26886
27011
|
deviceId: number(),
|
|
26887
|
-
|
|
27012
|
+
/** @deprecated Prefer `profiles`. Kept so timelapse/notifiers keep working. */
|
|
27013
|
+
profile: string().optional(),
|
|
27014
|
+
profiles: array(string()).min(1).optional(),
|
|
26888
27015
|
fromMs: number(),
|
|
26889
27016
|
toMs: number(),
|
|
26890
27017
|
options: ExportOptionsSchema
|
|
27018
|
+
}).superRefine((v, ctx) => {
|
|
27019
|
+
if ((v.profiles !== void 0 && v.profiles.length > 0 ? v.profiles : v.profile !== void 0 ? [v.profile] : []).length < 1) ctx.addIssue({
|
|
27020
|
+
code: ZodIssueCode.custom,
|
|
27021
|
+
message: "pass profiles[] (min 1) or legacy profile",
|
|
27022
|
+
path: ["profiles"]
|
|
27023
|
+
});
|
|
26891
27024
|
}), ExportRecordSchema, {
|
|
26892
27025
|
kind: "mutation",
|
|
26893
27026
|
auth: "protected"
|
|
@@ -29829,15 +29962,6 @@ var BaseDeviceProvider = class extends BaseAddon {
|
|
|
29829
29962
|
labels: ["probe not implemented"]
|
|
29830
29963
|
};
|
|
29831
29964
|
}
|
|
29832
|
-
/**
|
|
29833
|
-
* Top-level devices restored at once in {@link onRestoreDevices}.
|
|
29834
|
-
*
|
|
29835
|
-
* Four covers the fleets this ships to without turning a boot into a burst a
|
|
29836
|
-
* camera NVR answers with a refusal. A provider whose upstream is a single
|
|
29837
|
-
* session with a serial command channel (a Baichuan hub, an NVR that
|
|
29838
|
-
* serialises ISAPI) should lower it; nothing needs to raise it.
|
|
29839
|
-
*/
|
|
29840
|
-
restoreConcurrency = 4;
|
|
29841
29965
|
async restoreDevices(savedDevices) {
|
|
29842
29966
|
await this.onRestoreDevices(savedDevices);
|
|
29843
29967
|
if (savedDevices.length > 0) this.ctx.logger.info(`Restored ${savedDevices.length} ${this.providerName} device(s)`);
|
|
@@ -29892,14 +30016,7 @@ var BaseDeviceProvider = class extends BaseAddon {
|
|
|
29892
30016
|
});
|
|
29893
30017
|
}
|
|
29894
30018
|
};
|
|
29895
|
-
|
|
29896
|
-
await Promise.all(Array.from({ length: Math.min(Math.max(1, this.restoreConcurrency), topLevel.length) }, async () => {
|
|
29897
|
-
for (;;) {
|
|
29898
|
-
const saved = topLevel[nextTopLevel++];
|
|
29899
|
-
if (saved === void 0) return;
|
|
29900
|
-
await restoreOne(saved);
|
|
29901
|
-
}
|
|
29902
|
-
}));
|
|
30019
|
+
await Promise.all(topLevel.map((saved) => restoreOne(saved)));
|
|
29903
30020
|
const childRows = savedDevices.filter((s) => s.parentDeviceId !== null);
|
|
29904
30021
|
for (const saved of childRows) {
|
|
29905
30022
|
const Class = this.deviceClasses[saved.type];
|
|
@@ -33172,6 +33289,12 @@ Object.freeze({
|
|
|
33172
33289
|
addonId: null,
|
|
33173
33290
|
access: "create"
|
|
33174
33291
|
},
|
|
33292
|
+
"pipelineAnalytics.reconcileFromDisk": {
|
|
33293
|
+
capName: "pipeline-analytics",
|
|
33294
|
+
capScope: "device",
|
|
33295
|
+
addonId: null,
|
|
33296
|
+
access: "create"
|
|
33297
|
+
},
|
|
33175
33298
|
"pipelineAnalytics.refreshStorageLocationsForMigration": {
|
|
33176
33299
|
capName: "pipeline-analytics",
|
|
33177
33300
|
capScope: "device",
|
|
@@ -33574,6 +33697,12 @@ Object.freeze({
|
|
|
33574
33697
|
addonId: null,
|
|
33575
33698
|
access: "view"
|
|
33576
33699
|
},
|
|
33700
|
+
"pipelineOrchestrator.getReconcileFromDiskStatus": {
|
|
33701
|
+
capName: "pipeline-orchestrator",
|
|
33702
|
+
capScope: "system",
|
|
33703
|
+
addonId: null,
|
|
33704
|
+
access: "view"
|
|
33705
|
+
},
|
|
33577
33706
|
"pipelineOrchestrator.listAgentSettings": {
|
|
33578
33707
|
capName: "pipeline-orchestrator",
|
|
33579
33708
|
capScope: "system",
|
|
@@ -33598,6 +33727,12 @@ Object.freeze({
|
|
|
33598
33727
|
addonId: null,
|
|
33599
33728
|
access: "create"
|
|
33600
33729
|
},
|
|
33730
|
+
"pipelineOrchestrator.reconcileFromDisk": {
|
|
33731
|
+
capName: "pipeline-orchestrator",
|
|
33732
|
+
capScope: "system",
|
|
33733
|
+
addonId: null,
|
|
33734
|
+
access: "create"
|
|
33735
|
+
},
|
|
33601
33736
|
"pipelineOrchestrator.removeAgentSettings": {
|
|
33602
33737
|
capName: "pipeline-orchestrator",
|
|
33603
33738
|
capScope: "system",
|
|
@@ -36589,6 +36724,11 @@ Object.freeze({
|
|
|
36589
36724
|
form: "single",
|
|
36590
36725
|
optional: true
|
|
36591
36726
|
}],
|
|
36727
|
+
"pipelineAnalytics.reconcileFromDisk": [{
|
|
36728
|
+
name: "deviceId",
|
|
36729
|
+
form: "single",
|
|
36730
|
+
optional: false
|
|
36731
|
+
}],
|
|
36592
36732
|
"pipelineAnalytics.restageRetrainTrack": [{
|
|
36593
36733
|
name: "deviceId",
|
|
36594
36734
|
form: "single",
|
|
@@ -37913,5 +38053,7 @@ function bestLocationMatch(externalName, existing, threshold = .8) {
|
|
|
37913
38053
|
}
|
|
37914
38054
|
return best;
|
|
37915
38055
|
}
|
|
38056
|
+
var MB = 1024 * 1024;
|
|
38057
|
+
1024 * MB, 3072 * MB;
|
|
37916
38058
|
//#endregion
|
|
37917
38059
|
export { pressureSensorCapability as $, coverCapability as A, imageCapability as B, buttonCapability as C, record as Ct, connectivityCapability as D, url as Dt, colorCapability as E, unknown as Et, fanControlCapability as F, normalizeUnit as G, lockControlCapability as H, floodCapability as I, numericSensorCapability as J, notificationOutputCapability as K, gasCapability as L, deviceExportCapability as M, enumSensorCapability as N, contactCapability as O, EventCategory as Ot, eventEmitterCapability as P, presenceCapability as Q, humidifierCapability as R, buildAddonRouteProvider as S, object as St, climateControlCapability as T, union as Tt, mediaPlayerCapability as U, lawnMowerControlCapability as V, motionCapability as W, powerMeterCapability as X, oauthIntegrationCapability as Y, prepareNotification as Z, batteryCapability as _, _enum as _t, CameraSwitchIdSchema as a, updateCapability as at, brightnessCapability as b, literal as bt, HvacModeSchema as c, vibrationCapability as ct, accessoriesCapability as d, errMsg as dt, scriptRunnerCapability as et, addonRoutesCapability as f, BaseAddon as ft, automationControlCapability as g, createEvent as gt, ambientLightSensorCapability as h, DeviceType as ht, COCO_TO_MACRO as i, temperatureSensorCapability as it, deviceAdoptionCapability as j, controlCapability as k, MediaPlayerRepeatSchema as l, waterHeaterCapability as lt, alarmPanelCapability as m, DeviceRole as mt, BaseDevice as n, switchCapability as nt, EnumSensorDateTimeFormatSchema as o, vacuumControlCapability as ot, airQualitySensorCapability as p, DeviceFeature as pt, notifierCapability as q, BaseDeviceProvider as r, tamperCapability as rt, FanDirectionSchema as s, valveCapability as st, AlarmArmModeSchema as t, smokeCapability as tt, TargetSchema as u, weatherCapability as ut, bestLocationMatch as v, array as vt, carbonMonoxideCapability as w, string as wt, brokerCapability as x, number as xt, binaryCapability as y, discriminatedUnion as yt, humiditySensorCapability as z };
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
//#region ../types/dist/event-category-
|
|
1
|
+
//#region ../types/dist/event-category-XfKNtfCc.mjs
|
|
2
2
|
var EventCategory = /* @__PURE__ */ function(EventCategory) {
|
|
3
3
|
EventCategory["SystemBoot"] = "system.boot";
|
|
4
4
|
EventCategory["SystemAddonsReady"] = "system.addons-ready";
|
|
@@ -15,9 +15,10 @@ var EventCategory = /* @__PURE__ */ function(EventCategory) {
|
|
|
15
15
|
EventCategory["SystemRestartCompleted"] = "system.restart-completed";
|
|
16
16
|
/**
|
|
17
17
|
* A newer addon or server-root package version was found by the
|
|
18
|
-
* authoritative registry check. Emitted once
|
|
19
|
-
* `(
|
|
20
|
-
*
|
|
18
|
+
* authoritative registry check. Emitted once when any observed
|
|
19
|
+
* `latestVersion` changes (or a package/node first appears behind);
|
|
20
|
+
* the payload carries the full currently-available list. Repeated
|
|
21
|
+
* polling of the same latests is silent.
|
|
21
22
|
*/
|
|
22
23
|
EventCategory["UpdateAvailable"] = "update.available";
|
|
23
24
|
/**
|
|
@@ -36,6 +37,22 @@ var EventCategory = /* @__PURE__ */ function(EventCategory) {
|
|
|
36
37
|
EventCategory["AddonInstalled"] = "addon.installed";
|
|
37
38
|
EventCategory["AddonUninstalled"] = "addon.uninstalled";
|
|
38
39
|
EventCategory["AddonCrashed"] = "addon.crashed";
|
|
40
|
+
/**
|
|
41
|
+
* A RUNNER the D6 crash circuit-breaker gave up on — terminal.
|
|
42
|
+
*
|
|
43
|
+
* `AddonCrashed` is the routine, self-healing fact ("it crashed; it is being
|
|
44
|
+
* respawned"); this is the one that never resolves itself. Emitted exactly
|
|
45
|
+
* once per trip, by `process-service.ts`, carrying the node, the runner, the
|
|
46
|
+
* addons it hosted and the crash count that tripped the breaker.
|
|
47
|
+
*
|
|
48
|
+
* It exists because a runner marked terminally `failed` used to be SILENT:
|
|
49
|
+
* on 2026-08-18 the `recorder` runner died of three unhandled ffmpeg spawn
|
|
50
|
+
* errors, the breaker stopped respawning it (correctly), `/health` kept
|
|
51
|
+
* returning 200, and fleet-wide recording was gone for 3h15 before the
|
|
52
|
+
* operator's phone told him. The Notification Center's system-event intake
|
|
53
|
+
* consumes this category and maps it to the `addon-crash-loop` kind.
|
|
54
|
+
*/
|
|
55
|
+
EventCategory["AddonRunnerFailed"] = "addon.runner-failed";
|
|
39
56
|
EventCategory["AddonError"] = "addon.error";
|
|
40
57
|
EventCategory["AddonPageReady"] = "addon.page-ready";
|
|
41
58
|
EventCategory["AddonWidgetReady"] = "addon.widget-ready";
|
|
@@ -7666,6 +7683,10 @@ var RecordingBandSchema = object({
|
|
|
7666
7683
|
preBufferSec: number().min(0).optional(),
|
|
7667
7684
|
postBufferSec: number().min(0).optional()
|
|
7668
7685
|
});
|
|
7686
|
+
({
|
|
7687
|
+
preBufferSec: 10,
|
|
7688
|
+
postBufferSec: 30
|
|
7689
|
+
}).postBufferSec * 1e3;
|
|
7669
7690
|
/**
|
|
7670
7691
|
* Per-device retention overrides. Every field is optional; an unset or `0`
|
|
7671
7692
|
* value inherits the node-wide recorder default. Only footage-lifetime limits
|
|
@@ -7713,6 +7734,12 @@ var RecordingConfigSchema = object({
|
|
|
7713
7734
|
/** DERIVED summary of `bands`, stamped by the recorder on every save.
|
|
7714
7735
|
* Authoring it has no effect — see {@link RecordingStorageModeSchema}. */
|
|
7715
7736
|
mode: RecordingStorageModeSchema.optional(),
|
|
7737
|
+
/**
|
|
7738
|
+
* Which assigned broker slots to record. Absent / empty = {@link
|
|
7739
|
+
* DEFAULT_RECORDING_PROFILES} (`high`+`low`) intersected with the
|
|
7740
|
+
* camera's currently assigned slots — never `mid` unless the operator
|
|
7741
|
+
* picks it, and never a slot the broker has not assigned.
|
|
7742
|
+
*/
|
|
7716
7743
|
profiles: array(CamProfileSchema).optional(),
|
|
7717
7744
|
segmentSeconds: number().int().positive().optional(),
|
|
7718
7745
|
/**
|
|
@@ -7793,7 +7820,11 @@ var RelocateFootageInputSchema = object({
|
|
|
7793
7820
|
profiles: array(string()).optional(),
|
|
7794
7821
|
/** Copy throttle in MB/s (default 40) — the drain is a background chore,
|
|
7795
7822
|
* never allowed to starve live writers. */
|
|
7796
|
-
throttleMbps: number().min(1).max(1e3).optional()
|
|
7823
|
+
throttleMbps: number().min(1).max(1e3).optional(),
|
|
7824
|
+
/** Move only segments whose startMs is >= this. Absent = the whole source
|
|
7825
|
+
* pile. Used when a full drain is too expensive and the operator only
|
|
7826
|
+
* wants the recent window on the new disk. */
|
|
7827
|
+
sinceMs: number().int().optional()
|
|
7797
7828
|
});
|
|
7798
7829
|
/** Internal, lease-scoped participant operation. It is intentionally separate
|
|
7799
7830
|
* from persistent recording settings: a migration never changes
|
|
@@ -14827,6 +14858,7 @@ var NcSystemEventKindSchema = _enum([
|
|
|
14827
14858
|
"node-offline",
|
|
14828
14859
|
"node-inference-unavailable",
|
|
14829
14860
|
"detection-blind",
|
|
14861
|
+
"addon-crash-loop",
|
|
14830
14862
|
"addon-update-available",
|
|
14831
14863
|
"server-update-available",
|
|
14832
14864
|
"alarm-triggered",
|
|
@@ -14834,6 +14866,9 @@ var NcSystemEventKindSchema = _enum([
|
|
|
14834
14866
|
"alarm-disarmed",
|
|
14835
14867
|
"alarm-arming",
|
|
14836
14868
|
"alarm-arm-refused",
|
|
14869
|
+
"addon-updated",
|
|
14870
|
+
"server-updated",
|
|
14871
|
+
"export-completed",
|
|
14837
14872
|
"camera-online",
|
|
14838
14873
|
"camera-offline",
|
|
14839
14874
|
"camera-disabled",
|
|
@@ -16733,13 +16768,19 @@ var RetrainStatusSchema = _enum([
|
|
|
16733
16768
|
* "never marked" from "already trained" must read `retrainStatus`.
|
|
16734
16769
|
*
|
|
16735
16770
|
* `debug` does NOT pin; it is attention, not durability.
|
|
16771
|
+
*
|
|
16772
|
+
* `favourited` IS a BOOLEAN pin (durability bit), not a retrain lifecycle.
|
|
16773
|
+
* A favourited track is skipped by retention the same way `staging` is, but
|
|
16774
|
+
* it does not enter `none|staging|trained` and has no staging budget.
|
|
16736
16775
|
*/
|
|
16737
16776
|
var TrackFlagFields = {
|
|
16738
16777
|
/** Operator marked this track as training material — i.e. `retrainStatus` is
|
|
16739
16778
|
* `'staging'`. */
|
|
16740
16779
|
markForTrain: boolean().optional(),
|
|
16741
16780
|
/** Operator marked this track for diagnostic attention. */
|
|
16742
|
-
debug: boolean().optional()
|
|
16781
|
+
debug: boolean().optional(),
|
|
16782
|
+
/** Operator favourited this track. Pins it against pruning. */
|
|
16783
|
+
favourited: boolean().optional()
|
|
16743
16784
|
};
|
|
16744
16785
|
/**
|
|
16745
16786
|
* The lifecycle field itself, on the READ surfaces only (`Track`, `KeyEvent`).
|
|
@@ -16764,6 +16805,7 @@ var TrackFlagsSchema = object({
|
|
|
16764
16805
|
trackId: string(),
|
|
16765
16806
|
markForTrain: boolean(),
|
|
16766
16807
|
debug: boolean(),
|
|
16808
|
+
favourited: boolean(),
|
|
16767
16809
|
/** The lifecycle state the boolean was derived from. Required here (unlike on
|
|
16768
16810
|
* a track row) because this shape is only ever produced by the write body,
|
|
16769
16811
|
* which always knows it — and a surface that has just written needs to render
|
|
@@ -17396,6 +17438,12 @@ var TrackCascadeCountsSchema = object({
|
|
|
17396
17438
|
/** Per-track CLIP search vectors removed (best-effort). */
|
|
17397
17439
|
embeddings: number().int()
|
|
17398
17440
|
});
|
|
17441
|
+
/** Disk-wins reconcile: media rows whose blobs are gone, then empty tracks. */
|
|
17442
|
+
var DiskReconcileCountsSchema = object({
|
|
17443
|
+
mediaDropped: number().int(),
|
|
17444
|
+
tracks: number().int(),
|
|
17445
|
+
events: number().int()
|
|
17446
|
+
});
|
|
17399
17447
|
/** Event-store footprint for one camera. */
|
|
17400
17448
|
var EventStoreDeviceFootprintSchema = object({
|
|
17401
17449
|
deviceId: number(),
|
|
@@ -17572,6 +17620,9 @@ DeviceType.Camera, method(object({ deviceId: number() }), array(TrackSchema).rea
|
|
|
17572
17620
|
}), method(object({ deviceId: number() }), TrackCascadeCountsSchema, {
|
|
17573
17621
|
kind: "mutation",
|
|
17574
17622
|
auth: "admin"
|
|
17623
|
+
}), method(object({ deviceId: number() }), DiskReconcileCountsSchema, {
|
|
17624
|
+
kind: "mutation",
|
|
17625
|
+
auth: "admin"
|
|
17575
17626
|
}), method(object({
|
|
17576
17627
|
deviceId: number(),
|
|
17577
17628
|
trackIds: array(string()).min(1)
|
|
@@ -19122,6 +19173,24 @@ var CameraStatusDegradationSchema = object({
|
|
|
19122
19173
|
*
|
|
19123
19174
|
* See spec: `docs/superpowers/specs/2026-06-24-camera-status-aggregator-cap.md`
|
|
19124
19175
|
*/
|
|
19176
|
+
var DiskReconcileJobSchema = object({
|
|
19177
|
+
state: _enum([
|
|
19178
|
+
"idle",
|
|
19179
|
+
"running",
|
|
19180
|
+
"done",
|
|
19181
|
+
"error"
|
|
19182
|
+
]),
|
|
19183
|
+
total: number().int().nonnegative(),
|
|
19184
|
+
completed: number().int().nonnegative(),
|
|
19185
|
+
currentDeviceId: number().int().nullable(),
|
|
19186
|
+
failed: array(number().int()).readonly(),
|
|
19187
|
+
mediaDropped: number().int().nonnegative(),
|
|
19188
|
+
tracks: number().int().nonnegative(),
|
|
19189
|
+
events: number().int().nonnegative(),
|
|
19190
|
+
startedAtMs: number().int().nullable(),
|
|
19191
|
+
finishedAtMs: number().int().nullable(),
|
|
19192
|
+
error: string().nullable()
|
|
19193
|
+
});
|
|
19125
19194
|
var CameraStatusSchema = object({
|
|
19126
19195
|
deviceId: number(),
|
|
19127
19196
|
assignment: CameraAssignmentStatusSchema,
|
|
@@ -19353,7 +19422,10 @@ method(StorageMigrationLeaseInputSchema, object({ paused: literal(true) }), {
|
|
|
19353
19422
|
}), CameraSwitchGroupSchema, {
|
|
19354
19423
|
kind: "mutation",
|
|
19355
19424
|
auth: "admin"
|
|
19356
|
-
}), method(object({ deviceId: number() }), CameraStatusSchema), method(object({ deviceIds: array(number()).optional() }), array(CameraStatusSchema).readonly()), method(_void(),
|
|
19425
|
+
}), method(object({ deviceId: number() }), CameraStatusSchema), method(object({ deviceIds: array(number()).optional() }), array(CameraStatusSchema).readonly()), method(_void(), DiskReconcileJobSchema, {
|
|
19426
|
+
kind: "mutation",
|
|
19427
|
+
auth: "admin"
|
|
19428
|
+
}), method(_void(), DiskReconcileJobSchema, { auth: "admin" }), method(_void(), array(PipelineTemplateSchema).readonly()), method(object({
|
|
19357
19429
|
name: string(),
|
|
19358
19430
|
description: string().optional(),
|
|
19359
19431
|
config: CameraPipelineConfigSchema
|
|
@@ -19758,7 +19830,14 @@ targets: array(object({
|
|
|
19758
19830
|
"sleeping",
|
|
19759
19831
|
"unreachable",
|
|
19760
19832
|
"waking"
|
|
19761
|
-
]).nullable()
|
|
19833
|
+
]).nullable(),
|
|
19834
|
+
/** A battery camera (whatever its current state). An AWAKE battery
|
|
19835
|
+
* camera is deliberately NOT recaptured on the poll cadence — every
|
|
19836
|
+
* capture is a camera hit that would keep it out of sleep — so its
|
|
19837
|
+
* cached frame legitimately ages past the currency ceiling while
|
|
19838
|
+
* nothing is streaming. A surface must keep painting it (a fresh
|
|
19839
|
+
* frame is captured at each wake), not blank to "unavailable". */
|
|
19840
|
+
battery: boolean()
|
|
19762
19841
|
})));
|
|
19763
19842
|
/**
|
|
19764
19843
|
* `sso-bridge` — internal hub-only cap that lets SSO-style auth
|
|
@@ -20419,20 +20498,6 @@ var VectorStatsResultSchema = object({
|
|
|
20419
20498
|
exact: boolean()
|
|
20420
20499
|
});
|
|
20421
20500
|
method(VectorDeclareIndexInputSchema, _void(), { kind: "mutation" }), method(VectorUpsertInputSchema, VectorUpsertResultSchema, { kind: "mutation" }), method(VectorQueryInputSchema, VectorQueryResultSchema), method(VectorGetInputSchema, VectorGetResultSchema), method(VectorDeleteInputSchema, VectorDeleteResultSchema, { kind: "mutation" }), method(VectorDeleteByFilterInputSchema, VectorDeleteResultSchema, { kind: "mutation" }), method(VectorStatsInputSchema, VectorStatsResultSchema);
|
|
20422
|
-
/**
|
|
20423
|
-
* `videoclips` — the unified, navigable-clip surface for a camera.
|
|
20424
|
-
*
|
|
20425
|
-
* A device-scoped WRAPPER cap (like `pipeline-analytics`): exactly one active
|
|
20426
|
-
* provider per device, substitutable. The DEFAULT provider (registered by
|
|
20427
|
-
* `addon-post-analysis`, `defaultActive: true`) composes the analytics event
|
|
20428
|
-
* log (markers + thumbnails) with the recorder's `getPlaybackManifest` — a clip
|
|
20429
|
-
* is a time-WINDOW over existing footage, never a separate file. A camera that
|
|
20430
|
-
* exposes NATIVE onboard clips (Reolink/Hikvision NVR) can later substitute the
|
|
20431
|
-
* wrapper provider for its device and serve its own clip catalog + URLs.
|
|
20432
|
-
*
|
|
20433
|
-
* A `Clip` is purely time-based (subtree-blind): playback resolves segments by
|
|
20434
|
-
* temporal overlap, so the API never decides `continuous` vs `events`.
|
|
20435
|
-
*/
|
|
20436
20501
|
var ClipSchema = object({
|
|
20437
20502
|
/** Opaque, provider-namespaced id. The default provider encodes the time
|
|
20438
20503
|
* window so `getClipPlayback` is self-contained (no event re-query). */
|
|
@@ -20449,8 +20514,57 @@ var ClipSchema = object({
|
|
|
20449
20514
|
startMs: number(),
|
|
20450
20515
|
endMs: number()
|
|
20451
20516
|
}),
|
|
20452
|
-
/**
|
|
20453
|
-
thumbnail
|
|
20517
|
+
/**
|
|
20518
|
+
* Lazy thumbnail URL, never inlined.
|
|
20519
|
+
*
|
|
20520
|
+
* Recording-derived clips (events-mode keep-window, and the prepared
|
|
20521
|
+
* continuous event+fragment visit) MUST use the snapshot of the **main
|
|
20522
|
+
* event of the interval** — `getEventMedia({ eventId, kind: 'snapshot' })`
|
|
20523
|
+
* of the event that owns `kind` (object > motion > audio). Do not extract
|
|
20524
|
+
* a keyframe from the recorded segments. Other providers (onboard, HKSV)
|
|
20525
|
+
* mint their own stills.
|
|
20526
|
+
*
|
|
20527
|
+
* **VOUCHED, never fabricated.** A provider emits this only for an event it
|
|
20528
|
+
* has CONFIRMED owns at least one media row (its own, or its owning track's).
|
|
20529
|
+
* Absent is meaningful — "this visit has no event still" — never "we did not
|
|
20530
|
+
* look". Stamping it from a URL template made 35% of one camera's clips point
|
|
20531
|
+
* at a 404 (device 3836, 2026-08-17: 64 of 179 clips dead, 63 of them motion).
|
|
20532
|
+
* A read that FAILS drops the claim; it never invents it.
|
|
20533
|
+
*/
|
|
20534
|
+
thumbnail: string().optional(),
|
|
20535
|
+
/**
|
|
20536
|
+
* An instant INSIDE this visit's footage, hole-safe, where a recorded still
|
|
20537
|
+
* can be decoded. Present whenever the visit came from recorded availability;
|
|
20538
|
+
* absent on a per-event padded window (there is no footage to promise).
|
|
20539
|
+
*
|
|
20540
|
+
* This is not a thumbnail and not a second byte path: it is the argument to
|
|
20541
|
+
* the recorder's existing still route. The surface — never the provider —
|
|
20542
|
+
* decides whether to use it. It is the midpoint of the visit's LONGEST
|
|
20543
|
+
* contiguous range, not of the visit: a visit spans its holes by
|
|
20544
|
+
* construction, so a naive midpoint lands in dead air.
|
|
20545
|
+
*/
|
|
20546
|
+
stillAtMs: number().optional(),
|
|
20547
|
+
/**
|
|
20548
|
+
* Analytics event ids that overlap this visit — a BOUNDED sample, newest
|
|
20549
|
+
* first within kind (object → motion → audio), capped at
|
|
20550
|
+
* {@link MAX_CLIP_EVENT_IDS}. Empty on footage-only clips.
|
|
20551
|
+
*
|
|
20552
|
+
* Bounded because it is not a payload the surface pages through: one visit on
|
|
20553
|
+
* device 615 carried 2 345 ids, and `eventIds` was 99% of a 153 KB
|
|
20554
|
+
* camera-day. Read {@link eventCount} for the true total.
|
|
20555
|
+
*/
|
|
20556
|
+
eventIds: array(string()).optional(),
|
|
20557
|
+
/** How many analytics events actually overlap this visit. Differs from
|
|
20558
|
+
* `eventIds.length` exactly when the sample was capped — so a truncated
|
|
20559
|
+
* list is never mistaken for a quiet visit. */
|
|
20560
|
+
eventCount: number().int().nonnegative().optional(),
|
|
20561
|
+
/** Intra-visit footage holes (GOP rolls, discarded segments) still shorter
|
|
20562
|
+
* than `VISIT_MERGE_GAP_MS`. Playback concatenates around them; the timeline
|
|
20563
|
+
* bar keeps showing them via `recording.getAvailability`. */
|
|
20564
|
+
holes: array(object({
|
|
20565
|
+
startMs: number(),
|
|
20566
|
+
endMs: number()
|
|
20567
|
+
})).optional()
|
|
20454
20568
|
});
|
|
20455
20569
|
var ClipPlaybackSchema = object({
|
|
20456
20570
|
/** HLS master URL through the hub data-plane (Range + token in path). */
|
|
@@ -20986,7 +21100,14 @@ var SearchResultSchema = object({
|
|
|
20986
21100
|
});
|
|
20987
21101
|
var AutoUpdateSettingsSchema = object({
|
|
20988
21102
|
channel: ChannelSchema,
|
|
20989
|
-
intervalSeconds: number()
|
|
21103
|
+
intervalSeconds: number(),
|
|
21104
|
+
/**
|
|
21105
|
+
* Cadence of the "an update exists" POLLER, in seconds. Independent of
|
|
21106
|
+
* `channel`: the poller runs while auto-apply is `off`, because being told
|
|
21107
|
+
* about a publish and installing it are different decisions. Clamped
|
|
21108
|
+
* server-side to 900 s … 604800 s; defaults to 21600 s (6 h).
|
|
21109
|
+
*/
|
|
21110
|
+
updateCheckIntervalSeconds: number()
|
|
20990
21111
|
});
|
|
20991
21112
|
var AddonAutoUpdateSchema = ChannelWithInheritSchema;
|
|
20992
21113
|
var RestartAddonResultSchema = unknown();
|
|
@@ -21127,7 +21248,9 @@ method(_void(), array(AddonListItemSchema).readonly()), method(object({
|
|
|
21127
21248
|
auth: "admin"
|
|
21128
21249
|
}), method(_void(), AutoUpdateSettingsSchema, { auth: "admin" }), method(object({
|
|
21129
21250
|
channel: ChannelSchema,
|
|
21130
|
-
intervalSeconds: number().min(300).max(86400).optional()
|
|
21251
|
+
intervalSeconds: number().min(300).max(86400).optional(),
|
|
21252
|
+
/** Availability-poll cadence; see AutoUpdateSettingsSchema. */
|
|
21253
|
+
updateCheckIntervalSeconds: number().min(900).max(604800).optional()
|
|
21131
21254
|
}), unknown(), {
|
|
21132
21255
|
kind: "mutation",
|
|
21133
21256
|
auth: "admin"
|
|
@@ -26825,7 +26948,9 @@ var ExportOptionsSchema = object({
|
|
|
26825
26948
|
includeAudio: boolean(),
|
|
26826
26949
|
maxLifeMs: number().int().positive(),
|
|
26827
26950
|
deleteAfterDownload: boolean(),
|
|
26828
|
-
title: string().max(200).optional()
|
|
26951
|
+
title: string().max(200).optional(),
|
|
26952
|
+
/** Notification-output target ids to ping when this export becomes ready. */
|
|
26953
|
+
notifyTargetIds: array(string().min(1)).max(20).optional()
|
|
26829
26954
|
}).superRefine((v, ctx) => {
|
|
26830
26955
|
if (v.speed !== void 0 && v.timelapse !== void 0) ctx.addIssue({
|
|
26831
26956
|
code: ZodIssueCode.custom,
|
|
@@ -26884,10 +27009,18 @@ var ExportBytesSchema = object({
|
|
|
26884
27009
|
});
|
|
26885
27010
|
method(object({
|
|
26886
27011
|
deviceId: number(),
|
|
26887
|
-
|
|
27012
|
+
/** @deprecated Prefer `profiles`. Kept so timelapse/notifiers keep working. */
|
|
27013
|
+
profile: string().optional(),
|
|
27014
|
+
profiles: array(string()).min(1).optional(),
|
|
26888
27015
|
fromMs: number(),
|
|
26889
27016
|
toMs: number(),
|
|
26890
27017
|
options: ExportOptionsSchema
|
|
27018
|
+
}).superRefine((v, ctx) => {
|
|
27019
|
+
if ((v.profiles !== void 0 && v.profiles.length > 0 ? v.profiles : v.profile !== void 0 ? [v.profile] : []).length < 1) ctx.addIssue({
|
|
27020
|
+
code: ZodIssueCode.custom,
|
|
27021
|
+
message: "pass profiles[] (min 1) or legacy profile",
|
|
27022
|
+
path: ["profiles"]
|
|
27023
|
+
});
|
|
26891
27024
|
}), ExportRecordSchema, {
|
|
26892
27025
|
kind: "mutation",
|
|
26893
27026
|
auth: "protected"
|
|
@@ -29829,15 +29962,6 @@ var BaseDeviceProvider = class extends BaseAddon {
|
|
|
29829
29962
|
labels: ["probe not implemented"]
|
|
29830
29963
|
};
|
|
29831
29964
|
}
|
|
29832
|
-
/**
|
|
29833
|
-
* Top-level devices restored at once in {@link onRestoreDevices}.
|
|
29834
|
-
*
|
|
29835
|
-
* Four covers the fleets this ships to without turning a boot into a burst a
|
|
29836
|
-
* camera NVR answers with a refusal. A provider whose upstream is a single
|
|
29837
|
-
* session with a serial command channel (a Baichuan hub, an NVR that
|
|
29838
|
-
* serialises ISAPI) should lower it; nothing needs to raise it.
|
|
29839
|
-
*/
|
|
29840
|
-
restoreConcurrency = 4;
|
|
29841
29965
|
async restoreDevices(savedDevices) {
|
|
29842
29966
|
await this.onRestoreDevices(savedDevices);
|
|
29843
29967
|
if (savedDevices.length > 0) this.ctx.logger.info(`Restored ${savedDevices.length} ${this.providerName} device(s)`);
|
|
@@ -29892,14 +30016,7 @@ var BaseDeviceProvider = class extends BaseAddon {
|
|
|
29892
30016
|
});
|
|
29893
30017
|
}
|
|
29894
30018
|
};
|
|
29895
|
-
|
|
29896
|
-
await Promise.all(Array.from({ length: Math.min(Math.max(1, this.restoreConcurrency), topLevel.length) }, async () => {
|
|
29897
|
-
for (;;) {
|
|
29898
|
-
const saved = topLevel[nextTopLevel++];
|
|
29899
|
-
if (saved === void 0) return;
|
|
29900
|
-
await restoreOne(saved);
|
|
29901
|
-
}
|
|
29902
|
-
}));
|
|
30019
|
+
await Promise.all(topLevel.map((saved) => restoreOne(saved)));
|
|
29903
30020
|
const childRows = savedDevices.filter((s) => s.parentDeviceId !== null);
|
|
29904
30021
|
for (const saved of childRows) {
|
|
29905
30022
|
const Class = this.deviceClasses[saved.type];
|
|
@@ -33172,6 +33289,12 @@ Object.freeze({
|
|
|
33172
33289
|
addonId: null,
|
|
33173
33290
|
access: "create"
|
|
33174
33291
|
},
|
|
33292
|
+
"pipelineAnalytics.reconcileFromDisk": {
|
|
33293
|
+
capName: "pipeline-analytics",
|
|
33294
|
+
capScope: "device",
|
|
33295
|
+
addonId: null,
|
|
33296
|
+
access: "create"
|
|
33297
|
+
},
|
|
33175
33298
|
"pipelineAnalytics.refreshStorageLocationsForMigration": {
|
|
33176
33299
|
capName: "pipeline-analytics",
|
|
33177
33300
|
capScope: "device",
|
|
@@ -33574,6 +33697,12 @@ Object.freeze({
|
|
|
33574
33697
|
addonId: null,
|
|
33575
33698
|
access: "view"
|
|
33576
33699
|
},
|
|
33700
|
+
"pipelineOrchestrator.getReconcileFromDiskStatus": {
|
|
33701
|
+
capName: "pipeline-orchestrator",
|
|
33702
|
+
capScope: "system",
|
|
33703
|
+
addonId: null,
|
|
33704
|
+
access: "view"
|
|
33705
|
+
},
|
|
33577
33706
|
"pipelineOrchestrator.listAgentSettings": {
|
|
33578
33707
|
capName: "pipeline-orchestrator",
|
|
33579
33708
|
capScope: "system",
|
|
@@ -33598,6 +33727,12 @@ Object.freeze({
|
|
|
33598
33727
|
addonId: null,
|
|
33599
33728
|
access: "create"
|
|
33600
33729
|
},
|
|
33730
|
+
"pipelineOrchestrator.reconcileFromDisk": {
|
|
33731
|
+
capName: "pipeline-orchestrator",
|
|
33732
|
+
capScope: "system",
|
|
33733
|
+
addonId: null,
|
|
33734
|
+
access: "create"
|
|
33735
|
+
},
|
|
33601
33736
|
"pipelineOrchestrator.removeAgentSettings": {
|
|
33602
33737
|
capName: "pipeline-orchestrator",
|
|
33603
33738
|
capScope: "system",
|
|
@@ -36589,6 +36724,11 @@ Object.freeze({
|
|
|
36589
36724
|
form: "single",
|
|
36590
36725
|
optional: true
|
|
36591
36726
|
}],
|
|
36727
|
+
"pipelineAnalytics.reconcileFromDisk": [{
|
|
36728
|
+
name: "deviceId",
|
|
36729
|
+
form: "single",
|
|
36730
|
+
optional: false
|
|
36731
|
+
}],
|
|
36592
36732
|
"pipelineAnalytics.restageRetrainTrack": [{
|
|
36593
36733
|
name: "deviceId",
|
|
36594
36734
|
form: "single",
|
|
@@ -37913,6 +38053,8 @@ function bestLocationMatch(externalName, existing, threshold = .8) {
|
|
|
37913
38053
|
}
|
|
37914
38054
|
return best;
|
|
37915
38055
|
}
|
|
38056
|
+
var MB = 1024 * 1024;
|
|
38057
|
+
1024 * MB, 3072 * MB;
|
|
37916
38058
|
//#endregion
|
|
37917
38059
|
Object.defineProperty(exports, "AlarmArmModeSchema", {
|
|
37918
38060
|
enumerable: true,
|
|
@@ -3,7 +3,7 @@ Object.defineProperties(exports, {
|
|
|
3
3
|
[Symbol.toStringTag]: { value: "Module" }
|
|
4
4
|
});
|
|
5
5
|
//#endregion
|
|
6
|
-
const require_dist = require("../dist-
|
|
6
|
+
const require_dist = require("../dist-ubUo7WrJ.js");
|
|
7
7
|
let node_crypto = require("node:crypto");
|
|
8
8
|
//#region src/ha-export/topics.ts
|
|
9
9
|
/**
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { M as deviceExportCapability, Ot as EventCategory, S as buildAddonRouteProvider, Y as oauthIntegrationCapability, a as CameraSwitchIdSchema, c as HvacModeSchema, f as addonRoutesCapability, ft as BaseAddon, i as COCO_TO_MACRO, l as MediaPlayerRepeatSchema, s as FanDirectionSchema, t as AlarmArmModeSchema, wt as string } from "../dist-
|
|
1
|
+
import { M as deviceExportCapability, Ot as EventCategory, S as buildAddonRouteProvider, Y as oauthIntegrationCapability, a as CameraSwitchIdSchema, c as HvacModeSchema, f as addonRoutesCapability, ft as BaseAddon, i as COCO_TO_MACRO, l as MediaPlayerRepeatSchema, s as FanDirectionSchema, t as AlarmArmModeSchema, wt as string } from "../dist-AzTGVuqy.mjs";
|
|
2
2
|
import { createHmac, timingSafeEqual } from "node:crypto";
|
|
3
3
|
//#region src/ha-export/topics.ts
|
|
4
4
|
/**
|