@camstack/system 1.2.92 → 1.2.94
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/builtins/addon-pages-aggregator/addon-pages-aggregator.addon.js +1 -1
- package/dist/builtins/addon-pages-aggregator/addon-pages-aggregator.addon.mjs +1 -1
- package/dist/builtins/addon-widgets-aggregator/addon-widgets-aggregator.addon.js +1 -1
- package/dist/builtins/addon-widgets-aggregator/addon-widgets-aggregator.addon.mjs +1 -1
- package/dist/builtins/alerts/alerts.addon.js +1 -1
- package/dist/builtins/alerts/alerts.addon.mjs +1 -1
- package/dist/builtins/backup-orchestrator/backup-orchestrator.addon.js +1 -1
- package/dist/builtins/backup-orchestrator/backup-orchestrator.addon.mjs +1 -1
- package/dist/builtins/console-logging/index.js +1 -1
- package/dist/builtins/console-logging/index.mjs +1 -1
- package/dist/builtins/core-blocks/core-blocks.addon.js +1 -1
- package/dist/builtins/core-blocks/core-blocks.addon.mjs +1 -1
- package/dist/builtins/device-manager/device-manager.addon.js +1 -1
- package/dist/builtins/device-manager/device-manager.addon.mjs +1 -1
- package/dist/builtins/doorbell/virtual-doorbell.addon.js +1 -1
- package/dist/builtins/doorbell/virtual-doorbell.addon.mjs +1 -1
- package/dist/builtins/hub-forwarder/index.js +1 -1
- package/dist/builtins/hub-forwarder/index.mjs +1 -1
- package/dist/builtins/liveness-monitor/liveness-monitor.addon.js +1 -1
- package/dist/builtins/liveness-monitor/liveness-monitor.addon.mjs +1 -1
- package/dist/builtins/local-auth/local-auth.addon.js +1 -1
- package/dist/builtins/local-auth/local-auth.addon.mjs +1 -1
- package/dist/builtins/local-network/local-network.addon.js +1 -1
- package/dist/builtins/local-network/local-network.addon.mjs +1 -1
- package/dist/builtins/loki-logging/index.js +1 -1
- package/dist/builtins/loki-logging/index.mjs +1 -1
- package/dist/builtins/native-metrics/native-metrics.addon.js +1 -1
- package/dist/builtins/native-metrics/native-metrics.addon.mjs +1 -1
- package/dist/builtins/platform-probe/index.js +1 -1
- package/dist/builtins/platform-probe/index.mjs +1 -1
- package/dist/builtins/remote-access-orchestrator/remote-access-orchestrator.addon.js +1 -1
- package/dist/builtins/remote-access-orchestrator/remote-access-orchestrator.addon.mjs +1 -1
- package/dist/builtins/snapshot/index.js +207 -75
- package/dist/builtins/snapshot/index.mjs +207 -75
- package/dist/builtins/snapshot/snapshot-courtesy.d.ts +24 -2
- package/dist/builtins/snapshot/snapshot-media-handler.d.ts +7 -1
- package/dist/builtins/snapshot/snapshot-resize.d.ts +4 -4
- package/dist/builtins/snapshot/snapshot.addon.d.ts +35 -26
- package/dist/builtins/sqlite-storage/filesystem-storage.addon.js +1 -1
- package/dist/builtins/sqlite-storage/filesystem-storage.addon.mjs +1 -1
- package/dist/builtins/sqlite-storage/sqlite-settings.addon.js +1 -1
- package/dist/builtins/sqlite-storage/sqlite-settings.addon.mjs +1 -1
- package/dist/builtins/storage-orchestrator/storage-orchestrator.addon.js +1 -1
- package/dist/builtins/storage-orchestrator/storage-orchestrator.addon.mjs +1 -1
- package/dist/builtins/system-config/system-config.addon.js +1 -1
- package/dist/builtins/system-config/system-config.addon.mjs +1 -1
- package/dist/builtins/winston-logging/index.js +1 -1
- package/dist/builtins/winston-logging/index.mjs +1 -1
- package/dist/{dist-BH2tZ9ZN.js → dist-BspfS8Q7.js} +105 -2
- package/dist/{dist-DXDvrBi0.mjs → dist-COd223t-.mjs} +94 -3
- package/dist/index.js +1 -1
- package/dist/index.mjs +1 -1
- package/package.json +1 -1
|
@@ -40,9 +40,14 @@ export declare class SnapshotAddon extends BaseAddon<SnapshotAddonConfig> {
|
|
|
40
40
|
* A courtesy frame is a pure function of those three, so it is rendered once
|
|
41
41
|
* and reused for as long as the process lives — a disabled camera must not
|
|
42
42
|
* cost an ffmpeg run per poll. Unbounded on purpose: the key space is
|
|
43
|
-
* (
|
|
43
|
+
* (state reasons × this node's own cameras), not user input.
|
|
44
44
|
*/
|
|
45
45
|
private readonly courtesyFrames;
|
|
46
|
+
/** State overlays over real cached frames, grouped by device so invalidation
|
|
47
|
+
* can discard every generation in O(1). */
|
|
48
|
+
private readonly stateFrames;
|
|
49
|
+
/** Devices inside the explicit battery wake-in-progress window. */
|
|
50
|
+
private readonly wakingDevices;
|
|
46
51
|
/**
|
|
47
52
|
* De-dupes concurrent captures per `${deviceId}:${streamId}` and holds a
|
|
48
53
|
* settled SUCCESS for COALESCE_MS so a grid-mount burst (and a row of refresh
|
|
@@ -201,9 +206,7 @@ export declare class SnapshotAddon extends BaseAddon<SnapshotAddonConfig> {
|
|
|
201
206
|
* the Viewer's 15-second currency contract and the link-mint wait bound.
|
|
202
207
|
*/
|
|
203
208
|
private awaitFreshEnough;
|
|
204
|
-
/** True only for a
|
|
205
|
-
* question so the link path cannot accidentally treat "battery" as "asleep"
|
|
206
|
-
* and stop refreshing a camera that is awake and streaming. */
|
|
209
|
+
/** True only for a battery device that must not be snapshot-refreshed. */
|
|
207
210
|
private isSleepingBatteryDevice;
|
|
208
211
|
/**
|
|
209
212
|
* Resolve a device (+ optional stream, + force) to renderable JPEG bytes for
|
|
@@ -225,8 +228,8 @@ export declare class SnapshotAddon extends BaseAddon<SnapshotAddonConfig> {
|
|
|
225
228
|
*/
|
|
226
229
|
private peekFreshFrame;
|
|
227
230
|
/**
|
|
228
|
-
* The frame at a card-sized width, derived once per
|
|
229
|
-
* per capture.
|
|
231
|
+
* The frame at a card-sized width, derived once per
|
|
232
|
+
* (device, stream, width, state treatment) per capture.
|
|
230
233
|
*
|
|
231
234
|
* A failed resize falls back to the FULL frame — a visible card beats a
|
|
232
235
|
* broken one — but never silently: the card would otherwise keep costing a
|
|
@@ -355,25 +358,26 @@ export declare class SnapshotAddon extends BaseAddon<SnapshotAddonConfig> {
|
|
|
355
358
|
*/
|
|
356
359
|
private deviceStillExists;
|
|
357
360
|
/**
|
|
358
|
-
*
|
|
361
|
+
* Resolve the state that must be visible on a snapshot.
|
|
359
362
|
*
|
|
360
|
-
*
|
|
361
|
-
*
|
|
362
|
-
*
|
|
363
|
-
* in the UI, so if the operator can see "sleeping" on screen, this
|
|
364
|
-
* sees it too. (Both spec harnesses already model exactly this wiring
|
|
365
|
-
* — like the orphaned doc comment above, it outlived the gate it was
|
|
366
|
-
* built for.)
|
|
363
|
+
* Uses the same two canonical sources as wake-on-play:
|
|
364
|
+
* 1. `deviceManager.getDevice` for the registry's BatteryOperated feature;
|
|
365
|
+
* 2. `deviceState.getCapSlice('battery')` for the durable runtime mirror.
|
|
367
366
|
*
|
|
368
|
-
*
|
|
369
|
-
*
|
|
370
|
-
* battery
|
|
371
|
-
*
|
|
367
|
+
* A valid battery slice is itself positive evidence that the device is
|
|
368
|
+
* battery-operated. That closes the field failure where "Baby monitor" had a
|
|
369
|
+
* sleeping battery slice but a stale persisted feature projection, so the
|
|
370
|
+
* snapshot wrapper classified it as mains and a Viewer thumbnail logged in
|
|
371
|
+
* to the sleeping camera. The reverse is deliberately not guessed: no
|
|
372
|
+
* feature + no valid slice remains a mains/unknown camera and follows the
|
|
373
|
+
* ordinary capture path.
|
|
372
374
|
*
|
|
373
|
-
*
|
|
374
|
-
*
|
|
375
|
+
* Once battery-operated is established, a missing slice fails safe toward
|
|
376
|
+
* `sleeping` through the shared `deriveBatteryPresence` function. This avoids
|
|
377
|
+
* a background wake without inventing an `unreachable` fault.
|
|
375
378
|
*/
|
|
376
|
-
private
|
|
379
|
+
private resolveSnapshotState;
|
|
380
|
+
private isDeviceWaking;
|
|
377
381
|
/**
|
|
378
382
|
* True when at least one of the device's brokers is actively
|
|
379
383
|
* streaming (status === 'streaming'). Used by the battery-cam guard
|
|
@@ -421,13 +425,18 @@ export declare class SnapshotAddon extends BaseAddon<SnapshotAddonConfig> {
|
|
|
421
425
|
private courtesyFrame;
|
|
422
426
|
/** A courtesy frame shaped as the cap's response, or null when unrenderable. */
|
|
423
427
|
private courtesyImage;
|
|
428
|
+
/**
|
|
429
|
+
* Render a state-labelled answer. A cached real frame is the background, not
|
|
430
|
+
* the answer by itself; if it cannot be decoded, fall back to the generated
|
|
431
|
+
* courtesy background rather than leaking an unlabelled stale frame.
|
|
432
|
+
*/
|
|
433
|
+
private stateImage;
|
|
424
434
|
/**
|
|
425
435
|
* Single-trip device lookup against device-manager. Returns the
|
|
426
|
-
* fields the wrapper
|
|
427
|
-
*
|
|
428
|
-
*
|
|
429
|
-
*
|
|
430
|
-
* we're trying to be resilient to).
|
|
436
|
+
* stable registry fields the wrapper consults. Battery classification is
|
|
437
|
+
* completed by `resolveSnapshotState` from this feature flag PLUS the
|
|
438
|
+
* canonical runtime-state mirror, so a stale persisted feature projection
|
|
439
|
+
* cannot authorize a snapshot dial against a known sleeping battery camera.
|
|
431
440
|
*
|
|
432
441
|
* Logged at debug + null return on failure: every call site already
|
|
433
442
|
* has a sensible fallback path (cache hit, conservative default, …),
|
|
@@ -3,7 +3,7 @@ Object.defineProperties(exports, {
|
|
|
3
3
|
[Symbol.toStringTag]: { value: "Module" }
|
|
4
4
|
});
|
|
5
5
|
const require_chunk = require("../../chunk-Cek0wNdY.js");
|
|
6
|
-
const require_dist = require("../../dist-
|
|
6
|
+
const require_dist = require("../../dist-BspfS8Q7.js");
|
|
7
7
|
let node_crypto = require("node:crypto");
|
|
8
8
|
let node_fs_promises = require("node:fs/promises");
|
|
9
9
|
let node_path = require("node:path");
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { V as filesystemBrowseCapability, pt as storageProviderCapability, yt as BaseAddon } from "../../dist-COd223t-.mjs";
|
|
2
2
|
import { randomUUID } from "node:crypto";
|
|
3
3
|
import { mkdir, readdir, realpath, statfs } from "node:fs/promises";
|
|
4
4
|
import * as path$1 from "node:path";
|
|
@@ -3,7 +3,7 @@ Object.defineProperties(exports, {
|
|
|
3
3
|
[Symbol.toStringTag]: { value: "Module" }
|
|
4
4
|
});
|
|
5
5
|
const require_chunk = require("../../chunk-Cek0wNdY.js");
|
|
6
|
-
const require_dist = require("../../dist-
|
|
6
|
+
const require_dist = require("../../dist-BspfS8Q7.js");
|
|
7
7
|
let node_crypto = require("node:crypto");
|
|
8
8
|
let node_fs = require("node:fs");
|
|
9
9
|
let node_module = require("node:module");
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { A as
|
|
1
|
+
import { A as dataStoreProviderCapability, Bt as parseJsonUnknown, _t as vectorStoreCapability, f as RUNTIME_DEFAULTS, gt as vectorDimFromBase64, j as decodeVectorBase64, kt as asJsonObject, vt as errMsg, w as bareAddonId, yt as BaseAddon } from "../../dist-COd223t-.mjs";
|
|
2
2
|
import { createRequire } from "node:module";
|
|
3
3
|
import { randomUUID } from "node:crypto";
|
|
4
4
|
import { statSync } from "node:fs";
|
|
@@ -3,7 +3,7 @@ Object.defineProperties(exports, {
|
|
|
3
3
|
[Symbol.toStringTag]: { value: "Module" }
|
|
4
4
|
});
|
|
5
5
|
const require_chunk = require("../../chunk-Cek0wNdY.js");
|
|
6
|
-
const require_dist = require("../../dist-
|
|
6
|
+
const require_dist = require("../../dist-BspfS8Q7.js");
|
|
7
7
|
let node_crypto = require("node:crypto");
|
|
8
8
|
let node_fs_promises = require("node:fs/promises");
|
|
9
9
|
node_fs_promises = require_chunk.__toESM(node_fs_promises);
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { dt as storageCapability, ft as storageMigrationCapability, g as StorageMigrationJobSchema, h as StorageLocationTypeSchema, lt as settingsStoreCapability, yt as BaseAddon, zt as parseJsonObject } from "../../dist-COd223t-.mjs";
|
|
2
2
|
import { randomUUID } from "node:crypto";
|
|
3
3
|
import * as fs from "node:fs/promises";
|
|
4
4
|
import * as path$1 from "node:path";
|
|
@@ -3,7 +3,7 @@ Object.defineProperties(exports, {
|
|
|
3
3
|
[Symbol.toStringTag]: { value: "Module" }
|
|
4
4
|
});
|
|
5
5
|
require("../../chunk-Cek0wNdY.js");
|
|
6
|
-
const require_dist = require("../../dist-
|
|
6
|
+
const require_dist = require("../../dist-BspfS8Q7.js");
|
|
7
7
|
//#region src/builtins/system-config/system-config.addon.ts
|
|
8
8
|
/**
|
|
9
9
|
* Built-in `system-config` addon — Phase 4 of the settings redesign.
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { It as hydrateSchema, vt as errMsg, yt as BaseAddon } from "../../dist-COd223t-.mjs";
|
|
2
2
|
//#region src/builtins/system-config/system-config.addon.ts
|
|
3
3
|
/**
|
|
4
4
|
* Built-in `system-config` addon — Phase 4 of the settings redesign.
|
|
@@ -3,7 +3,7 @@ Object.defineProperties(exports, {
|
|
|
3
3
|
[Symbol.toStringTag]: { value: "Module" }
|
|
4
4
|
});
|
|
5
5
|
const require_chunk = require("../../chunk-Cek0wNdY.js");
|
|
6
|
-
const require_dist = require("../../dist-
|
|
6
|
+
const require_dist = require("../../dist-BspfS8Q7.js");
|
|
7
7
|
const require_formatter = require("../../formatter-DqAKDlvN.js");
|
|
8
8
|
let node_path = require("node:path");
|
|
9
9
|
node_path = require_chunk.__toESM(node_path);
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { X as logDestinationCapability, yt as BaseAddon } from "../../dist-COd223t-.mjs";
|
|
2
2
|
import { t as formatLogLine } from "../../formatter-B7qW8bPJ.mjs";
|
|
3
3
|
import * as path$1 from "node:path";
|
|
4
4
|
import path from "node:path";
|
|
@@ -20825,6 +20825,25 @@ var BatteryStatusSchema = zod.z.object({
|
|
|
20825
20825
|
/** Ms epoch of the last observation. Lets consumers reason about freshness. */
|
|
20826
20826
|
lastUpdated: zod.z.number(),
|
|
20827
20827
|
/**
|
|
20828
|
+
* Ms epoch of the last time the device PROVED it was reachable — a
|
|
20829
|
+
* completed firmware round-trip, an observed wake, or an inbound push
|
|
20830
|
+
* (firmware event, email). `0`/absent = never since this slice was born.
|
|
20831
|
+
*
|
|
20832
|
+
* This is the ONLY input that separates "asleep" from "gone", and it is
|
|
20833
|
+
* fed exclusively by PASSIVE signals: nothing may write it by reaching
|
|
20834
|
+
* for the radio, because a poll that confirms reachability is the same
|
|
20835
|
+
* poll that drains the battery. See {@link deriveBatteryPresence} — the
|
|
20836
|
+
* single derivation every consumer must use; no surface computes its own.
|
|
20837
|
+
*
|
|
20838
|
+
* It is deliberately NOT a clock in the
|
|
20839
|
+
* `scripts/check-runtime-state-durability.ts` sense: it is the
|
|
20840
|
+
* observation itself, and it is the only thing a 30-hour silence is
|
|
20841
|
+
* visible in. Writers quantise it (see `CONTACT_WRITE_QUANTUM_MS` in the
|
|
20842
|
+
* Reolink provider) so a value that means "recently" cannot cost a
|
|
20843
|
+
* SQLite commit per round-trip.
|
|
20844
|
+
*/
|
|
20845
|
+
lastContactAt: zod.z.number().optional(),
|
|
20846
|
+
/**
|
|
20828
20847
|
* True when the source is a BINARY low-battery indicator (HA
|
|
20829
20848
|
* `binary_sensor` device_class=battery / `LOW_BAT`) that has no real
|
|
20830
20849
|
* charge level — `percentage` is then a coarse stand-in (100 = normal,
|
|
@@ -27507,13 +27526,63 @@ var CamStreamDescriptorSchema = zod.z.object({
|
|
|
27507
27526
|
* set of stream descriptors it can offer for the device, synchronously, so the
|
|
27508
27527
|
* broker can reconcile its registry against the authoritative provider state.
|
|
27509
27528
|
*/
|
|
27529
|
+
/**
|
|
27530
|
+
* The catalog as a DURABLE fact rather than a live answer.
|
|
27531
|
+
*
|
|
27532
|
+
* A battery camera's descriptors are profile-stable — they change when the
|
|
27533
|
+
* operator rewrites an encoder profile, not minute to minute — but building
|
|
27534
|
+
* them costs a Baichuan login, which on a sleeping Argus IS a wake. So the
|
|
27535
|
+
* provider is allowed to build them exactly once per profile and must serve
|
|
27536
|
+
* every later pull from a cache.
|
|
27537
|
+
*
|
|
27538
|
+
* Holding that cache only in RAM is what turned a restart into an outage. The
|
|
27539
|
+
* runner comes back with the camera asleep, `buildStreamCatalogUncached`
|
|
27540
|
+
* correctly refuses to wake it, the pull answers `[]`, the broker has no
|
|
27541
|
+
* cam-stream entry to build a broker from, and `webrtcSession.handleOffer`
|
|
27542
|
+
* fails with a flat "No broker for stream" — for as long as the camera sleeps,
|
|
27543
|
+
* which on a battery cam is most of the day. The camera was fine. The stream
|
|
27544
|
+
* was unreachable because the process had forgotten what the camera offers.
|
|
27545
|
+
*
|
|
27546
|
+
* Declaring it here puts it in `device-runtime-state`, the kernel's canonical
|
|
27547
|
+
* declared collection, with the same `restored` durability `battery` uses for
|
|
27548
|
+
* the same reason: the last known value is the only value there is while the
|
|
27549
|
+
* device is asleep. The broker's brokers are therefore always DEFINABLE — it
|
|
27550
|
+
* is the DIAL that wakes a camera, never the catalog (D173).
|
|
27551
|
+
*/
|
|
27552
|
+
var StreamCatalogStateSchema = zod.z.object({
|
|
27553
|
+
/** The descriptors as last built from a real camera response. Never a guess:
|
|
27554
|
+
* a failed or refused build writes NOTHING, so a restored catalog is always
|
|
27555
|
+
* one the camera itself once produced. */
|
|
27556
|
+
descriptors: zod.z.array(CamStreamDescriptorSchema),
|
|
27557
|
+
/** Ms epoch of the build that produced {@link descriptors}. Lets the wake
|
|
27558
|
+
* path decide whether the camera's own awake window is worth spending on a
|
|
27559
|
+
* re-read. */
|
|
27560
|
+
lastFetchedAt: zod.z.number()
|
|
27561
|
+
});
|
|
27510
27562
|
var streamCatalogCapability = {
|
|
27511
27563
|
name: "stream-catalog",
|
|
27512
27564
|
scope: "device",
|
|
27513
27565
|
deviceNative: true,
|
|
27514
27566
|
mode: "singleton",
|
|
27515
27567
|
deviceTypes: [DeviceType.Camera],
|
|
27516
|
-
methods: { getCatalog: method(zod.z.object({ deviceId: zod.z.number().int().nonnegative() }), zod.z.array(CamStreamDescriptorSchema).readonly()) }
|
|
27568
|
+
methods: { getCatalog: method(zod.z.object({ deviceId: zod.z.number().int().nonnegative() }), zod.z.array(CamStreamDescriptorSchema).readonly()) },
|
|
27569
|
+
runtimeState: StreamCatalogStateSchema,
|
|
27570
|
+
/**
|
|
27571
|
+
* Runtime-state durability: **restored** — see the schema doc. A cold
|
|
27572
|
+
* catalog on a sleeping battery camera is not a slow first frame, it is a
|
|
27573
|
+
* camera that cannot be watched at all until it happens to wake.
|
|
27574
|
+
*
|
|
27575
|
+
* Churn is nil by construction: the slice is written only by a SUCCESSFUL
|
|
27576
|
+
* build, and a build only runs when there is no cached copy (or the copy is
|
|
27577
|
+
* a day old and the camera is awake anyway).
|
|
27578
|
+
*
|
|
27579
|
+
* See `RuntimeStateDurability`. Enforced by
|
|
27580
|
+
* `scripts/check-runtime-state-durability.ts`.
|
|
27581
|
+
*/
|
|
27582
|
+
durability: "restored",
|
|
27583
|
+
/** Clock field: written, but excluded from the compare that decides whether
|
|
27584
|
+
* persisting is worth a SQLite commit — the descriptors are the value. */
|
|
27585
|
+
volatileStateFields: ["lastFetchedAt"]
|
|
27517
27586
|
};
|
|
27518
27587
|
/** One of the camera's stream profiles. */
|
|
27519
27588
|
var StreamProfileSchema = zod.z.enum([
|
|
@@ -29510,6 +29579,24 @@ var DeclaredDevices = class {
|
|
|
29510
29579
|
DeviceType.Cover, DeviceType.Valve, DeviceType.Humidifier, DeviceType.WaterHeater, DeviceType.Camera, DeviceType.Hub, DeviceType.Switch, DeviceType.Siren, DeviceType.Light, DeviceType.Fan, DeviceType.Sensor, DeviceType.Thermostat, DeviceType.Climate, DeviceType.Button, DeviceType.EventEmitter, DeviceType.Update, DeviceType.Generic, DeviceType.Notifier, DeviceType.Script, DeviceType.Automation, DeviceType.Lock, DeviceType.MediaPlayer, DeviceType.AlarmPanel, DeviceType.Control, DeviceType.Presence, DeviceType.Weather, DeviceType.Vacuum, DeviceType.LawnMower, DeviceType.Container, DeviceType.Image, DeviceType.PetFeeder;
|
|
29511
29580
|
new Set(Object.values(DeviceType));
|
|
29512
29581
|
DeviceFeature.BatteryOperated;
|
|
29582
|
+
/**
|
|
29583
|
+
* THE derivation. One crop rectangle, one presence verdict — see D52 for why
|
|
29584
|
+
* this repo insists a derived value has exactly one implementation.
|
|
29585
|
+
*
|
|
29586
|
+
* `undefined` status ⇒ `sleeping`. A device with no slice has made no claim,
|
|
29587
|
+
* and the caller decides separately whether it is even battery-operated
|
|
29588
|
+
* (`DeviceFeature.BatteryOperated`); this function never answers that
|
|
29589
|
+
* question, only what a battery device is doing.
|
|
29590
|
+
*/
|
|
29591
|
+
function deriveBatteryPresence(input) {
|
|
29592
|
+
const status = input.status;
|
|
29593
|
+
if (!status) return "sleeping";
|
|
29594
|
+
if (status.sleeping !== true) return "awake";
|
|
29595
|
+
const lastContactAt = status.lastContactAt;
|
|
29596
|
+
if (typeof lastContactAt !== "number" || lastContactAt <= 0) return "sleeping";
|
|
29597
|
+
const budget = input.unreachableAfterMs ?? 216e5;
|
|
29598
|
+
return input.nowMs - lastContactAt > budget ? "unreachable" : "sleeping";
|
|
29599
|
+
}
|
|
29513
29600
|
/** Unwrap ZodNullable / ZodOptional / ZodDefault wrappers to reach the inner type.
|
|
29514
29601
|
* Zod v4 exposes `.unwrap()` on all three wrapper classes. */
|
|
29515
29602
|
function unwrap(schema) {
|
|
@@ -37123,7 +37210,7 @@ Object.freeze({
|
|
|
37123
37210
|
});
|
|
37124
37211
|
/**
|
|
37125
37212
|
* Per-cap runtime-state policy, projected from every `*.cap.ts` that declares
|
|
37126
|
-
* `runtimeState`.
|
|
37213
|
+
* `runtimeState`. 64 caps: 34 `restored`, 30 `session`.
|
|
37127
37214
|
*
|
|
37128
37215
|
* A cap absent from this map has no runtime-state slice at all. A cap PRESENT
|
|
37129
37216
|
* with `durability: 'session'` has one and has decided not to keep it.
|
|
@@ -37329,6 +37416,10 @@ var RUNTIME_STATE_POLICY = {
|
|
|
37329
37416
|
durability: "restored",
|
|
37330
37417
|
volatileFields: ["lastChangedAt"]
|
|
37331
37418
|
},
|
|
37419
|
+
"stream-catalog": {
|
|
37420
|
+
durability: "restored",
|
|
37421
|
+
volatileFields: ["lastFetchedAt"]
|
|
37422
|
+
},
|
|
37332
37423
|
"stream-params": {
|
|
37333
37424
|
durability: "restored",
|
|
37334
37425
|
volatileFields: ["lastFetchedAt"]
|
|
@@ -38162,6 +38253,12 @@ Object.defineProperty(exports, "bareAddonId", {
|
|
|
38162
38253
|
return bareAddonId;
|
|
38163
38254
|
}
|
|
38164
38255
|
});
|
|
38256
|
+
Object.defineProperty(exports, "batteryCapability", {
|
|
38257
|
+
enumerable: true,
|
|
38258
|
+
get: function() {
|
|
38259
|
+
return batteryCapability;
|
|
38260
|
+
}
|
|
38261
|
+
});
|
|
38165
38262
|
Object.defineProperty(exports, "buildStreamParamsConfigSchema", {
|
|
38166
38263
|
enumerable: true,
|
|
38167
38264
|
get: function() {
|
|
@@ -38204,6 +38301,12 @@ Object.defineProperty(exports, "decodeVectorBase64", {
|
|
|
38204
38301
|
return decodeVectorBase64;
|
|
38205
38302
|
}
|
|
38206
38303
|
});
|
|
38304
|
+
Object.defineProperty(exports, "deriveBatteryPresence", {
|
|
38305
|
+
enumerable: true,
|
|
38306
|
+
get: function() {
|
|
38307
|
+
return deriveBatteryPresence;
|
|
38308
|
+
}
|
|
38309
|
+
});
|
|
38207
38310
|
Object.defineProperty(exports, "deviceManagerCapability", {
|
|
38208
38311
|
enumerable: true,
|
|
38209
38312
|
get: function() {
|
|
@@ -20825,6 +20825,25 @@ var BatteryStatusSchema = z.object({
|
|
|
20825
20825
|
/** Ms epoch of the last observation. Lets consumers reason about freshness. */
|
|
20826
20826
|
lastUpdated: z.number(),
|
|
20827
20827
|
/**
|
|
20828
|
+
* Ms epoch of the last time the device PROVED it was reachable — a
|
|
20829
|
+
* completed firmware round-trip, an observed wake, or an inbound push
|
|
20830
|
+
* (firmware event, email). `0`/absent = never since this slice was born.
|
|
20831
|
+
*
|
|
20832
|
+
* This is the ONLY input that separates "asleep" from "gone", and it is
|
|
20833
|
+
* fed exclusively by PASSIVE signals: nothing may write it by reaching
|
|
20834
|
+
* for the radio, because a poll that confirms reachability is the same
|
|
20835
|
+
* poll that drains the battery. See {@link deriveBatteryPresence} — the
|
|
20836
|
+
* single derivation every consumer must use; no surface computes its own.
|
|
20837
|
+
*
|
|
20838
|
+
* It is deliberately NOT a clock in the
|
|
20839
|
+
* `scripts/check-runtime-state-durability.ts` sense: it is the
|
|
20840
|
+
* observation itself, and it is the only thing a 30-hour silence is
|
|
20841
|
+
* visible in. Writers quantise it (see `CONTACT_WRITE_QUANTUM_MS` in the
|
|
20842
|
+
* Reolink provider) so a value that means "recently" cannot cost a
|
|
20843
|
+
* SQLite commit per round-trip.
|
|
20844
|
+
*/
|
|
20845
|
+
lastContactAt: z.number().optional(),
|
|
20846
|
+
/**
|
|
20828
20847
|
* True when the source is a BINARY low-battery indicator (HA
|
|
20829
20848
|
* `binary_sensor` device_class=battery / `LOW_BAT`) that has no real
|
|
20830
20849
|
* charge level — `percentage` is then a coarse stand-in (100 = normal,
|
|
@@ -27507,13 +27526,63 @@ var CamStreamDescriptorSchema = z.object({
|
|
|
27507
27526
|
* set of stream descriptors it can offer for the device, synchronously, so the
|
|
27508
27527
|
* broker can reconcile its registry against the authoritative provider state.
|
|
27509
27528
|
*/
|
|
27529
|
+
/**
|
|
27530
|
+
* The catalog as a DURABLE fact rather than a live answer.
|
|
27531
|
+
*
|
|
27532
|
+
* A battery camera's descriptors are profile-stable — they change when the
|
|
27533
|
+
* operator rewrites an encoder profile, not minute to minute — but building
|
|
27534
|
+
* them costs a Baichuan login, which on a sleeping Argus IS a wake. So the
|
|
27535
|
+
* provider is allowed to build them exactly once per profile and must serve
|
|
27536
|
+
* every later pull from a cache.
|
|
27537
|
+
*
|
|
27538
|
+
* Holding that cache only in RAM is what turned a restart into an outage. The
|
|
27539
|
+
* runner comes back with the camera asleep, `buildStreamCatalogUncached`
|
|
27540
|
+
* correctly refuses to wake it, the pull answers `[]`, the broker has no
|
|
27541
|
+
* cam-stream entry to build a broker from, and `webrtcSession.handleOffer`
|
|
27542
|
+
* fails with a flat "No broker for stream" — for as long as the camera sleeps,
|
|
27543
|
+
* which on a battery cam is most of the day. The camera was fine. The stream
|
|
27544
|
+
* was unreachable because the process had forgotten what the camera offers.
|
|
27545
|
+
*
|
|
27546
|
+
* Declaring it here puts it in `device-runtime-state`, the kernel's canonical
|
|
27547
|
+
* declared collection, with the same `restored` durability `battery` uses for
|
|
27548
|
+
* the same reason: the last known value is the only value there is while the
|
|
27549
|
+
* device is asleep. The broker's brokers are therefore always DEFINABLE — it
|
|
27550
|
+
* is the DIAL that wakes a camera, never the catalog (D173).
|
|
27551
|
+
*/
|
|
27552
|
+
var StreamCatalogStateSchema = z.object({
|
|
27553
|
+
/** The descriptors as last built from a real camera response. Never a guess:
|
|
27554
|
+
* a failed or refused build writes NOTHING, so a restored catalog is always
|
|
27555
|
+
* one the camera itself once produced. */
|
|
27556
|
+
descriptors: z.array(CamStreamDescriptorSchema),
|
|
27557
|
+
/** Ms epoch of the build that produced {@link descriptors}. Lets the wake
|
|
27558
|
+
* path decide whether the camera's own awake window is worth spending on a
|
|
27559
|
+
* re-read. */
|
|
27560
|
+
lastFetchedAt: z.number()
|
|
27561
|
+
});
|
|
27510
27562
|
var streamCatalogCapability = {
|
|
27511
27563
|
name: "stream-catalog",
|
|
27512
27564
|
scope: "device",
|
|
27513
27565
|
deviceNative: true,
|
|
27514
27566
|
mode: "singleton",
|
|
27515
27567
|
deviceTypes: [DeviceType.Camera],
|
|
27516
|
-
methods: { getCatalog: method(z.object({ deviceId: z.number().int().nonnegative() }), z.array(CamStreamDescriptorSchema).readonly()) }
|
|
27568
|
+
methods: { getCatalog: method(z.object({ deviceId: z.number().int().nonnegative() }), z.array(CamStreamDescriptorSchema).readonly()) },
|
|
27569
|
+
runtimeState: StreamCatalogStateSchema,
|
|
27570
|
+
/**
|
|
27571
|
+
* Runtime-state durability: **restored** — see the schema doc. A cold
|
|
27572
|
+
* catalog on a sleeping battery camera is not a slow first frame, it is a
|
|
27573
|
+
* camera that cannot be watched at all until it happens to wake.
|
|
27574
|
+
*
|
|
27575
|
+
* Churn is nil by construction: the slice is written only by a SUCCESSFUL
|
|
27576
|
+
* build, and a build only runs when there is no cached copy (or the copy is
|
|
27577
|
+
* a day old and the camera is awake anyway).
|
|
27578
|
+
*
|
|
27579
|
+
* See `RuntimeStateDurability`. Enforced by
|
|
27580
|
+
* `scripts/check-runtime-state-durability.ts`.
|
|
27581
|
+
*/
|
|
27582
|
+
durability: "restored",
|
|
27583
|
+
/** Clock field: written, but excluded from the compare that decides whether
|
|
27584
|
+
* persisting is worth a SQLite commit — the descriptors are the value. */
|
|
27585
|
+
volatileStateFields: ["lastFetchedAt"]
|
|
27517
27586
|
};
|
|
27518
27587
|
/** One of the camera's stream profiles. */
|
|
27519
27588
|
var StreamProfileSchema = z.enum([
|
|
@@ -29510,6 +29579,24 @@ var DeclaredDevices = class {
|
|
|
29510
29579
|
DeviceType.Cover, DeviceType.Valve, DeviceType.Humidifier, DeviceType.WaterHeater, DeviceType.Camera, DeviceType.Hub, DeviceType.Switch, DeviceType.Siren, DeviceType.Light, DeviceType.Fan, DeviceType.Sensor, DeviceType.Thermostat, DeviceType.Climate, DeviceType.Button, DeviceType.EventEmitter, DeviceType.Update, DeviceType.Generic, DeviceType.Notifier, DeviceType.Script, DeviceType.Automation, DeviceType.Lock, DeviceType.MediaPlayer, DeviceType.AlarmPanel, DeviceType.Control, DeviceType.Presence, DeviceType.Weather, DeviceType.Vacuum, DeviceType.LawnMower, DeviceType.Container, DeviceType.Image, DeviceType.PetFeeder;
|
|
29511
29580
|
new Set(Object.values(DeviceType));
|
|
29512
29581
|
DeviceFeature.BatteryOperated;
|
|
29582
|
+
/**
|
|
29583
|
+
* THE derivation. One crop rectangle, one presence verdict — see D52 for why
|
|
29584
|
+
* this repo insists a derived value has exactly one implementation.
|
|
29585
|
+
*
|
|
29586
|
+
* `undefined` status ⇒ `sleeping`. A device with no slice has made no claim,
|
|
29587
|
+
* and the caller decides separately whether it is even battery-operated
|
|
29588
|
+
* (`DeviceFeature.BatteryOperated`); this function never answers that
|
|
29589
|
+
* question, only what a battery device is doing.
|
|
29590
|
+
*/
|
|
29591
|
+
function deriveBatteryPresence(input) {
|
|
29592
|
+
const status = input.status;
|
|
29593
|
+
if (!status) return "sleeping";
|
|
29594
|
+
if (status.sleeping !== true) return "awake";
|
|
29595
|
+
const lastContactAt = status.lastContactAt;
|
|
29596
|
+
if (typeof lastContactAt !== "number" || lastContactAt <= 0) return "sleeping";
|
|
29597
|
+
const budget = input.unreachableAfterMs ?? 216e5;
|
|
29598
|
+
return input.nowMs - lastContactAt > budget ? "unreachable" : "sleeping";
|
|
29599
|
+
}
|
|
29513
29600
|
/** Unwrap ZodNullable / ZodOptional / ZodDefault wrappers to reach the inner type.
|
|
29514
29601
|
* Zod v4 exposes `.unwrap()` on all three wrapper classes. */
|
|
29515
29602
|
function unwrap(schema) {
|
|
@@ -37123,7 +37210,7 @@ Object.freeze({
|
|
|
37123
37210
|
});
|
|
37124
37211
|
/**
|
|
37125
37212
|
* Per-cap runtime-state policy, projected from every `*.cap.ts` that declares
|
|
37126
|
-
* `runtimeState`.
|
|
37213
|
+
* `runtimeState`. 64 caps: 34 `restored`, 30 `session`.
|
|
37127
37214
|
*
|
|
37128
37215
|
* A cap absent from this map has no runtime-state slice at all. A cap PRESENT
|
|
37129
37216
|
* with `durability: 'session'` has one and has decided not to keep it.
|
|
@@ -37329,6 +37416,10 @@ var RUNTIME_STATE_POLICY = {
|
|
|
37329
37416
|
durability: "restored",
|
|
37330
37417
|
volatileFields: ["lastChangedAt"]
|
|
37331
37418
|
},
|
|
37419
|
+
"stream-catalog": {
|
|
37420
|
+
durability: "restored",
|
|
37421
|
+
volatileFields: ["lastFetchedAt"]
|
|
37422
|
+
},
|
|
37332
37423
|
"stream-params": {
|
|
37333
37424
|
durability: "restored",
|
|
37334
37425
|
volatileFields: ["lastFetchedAt"]
|
|
@@ -37934,4 +38025,4 @@ function enumerateInferenceDevices(hw) {
|
|
|
37934
38025
|
return out;
|
|
37935
38026
|
}
|
|
37936
38027
|
//#endregion
|
|
37937
|
-
export {
|
|
38028
|
+
export { metricsProviderCapability as $, dataStoreProviderCapability as A, asNumber as At, extractNestedAddonId as B, parseJsonUnknown as Bt, backupCapability as C, DeviceFeature as Ct, coreBlockAddonId as D, ReadinessTimeoutError as Dt, buildStreamParamsConfigSchema as E, ReadinessRegistry as Et, deviceStatusCapability as F, expandCapMethods as Ft, isSameAddonId as G, EventCategory as Gt, isArrayOutputSchema as H, resolveCapMount as Ht, doorbellCapability as I, hydrateSchema as It, lifecycleJobSchema as J, isVoidInput as K, enumerateInferenceDevices as L, isDeviceConfigCap as Lt, deriveBatteryPresence as M, createEvent as Mt, deviceManagerCapability as N, emitDownForOwnedCaps as Nt, coreBlockIdFromAddonId as O, WELL_KNOWN_TAB_MAP as Ot, deviceStateCapability as P, emitReadiness as Pt, looseSchema as Q, enumerateItemArrayFields as R, nodePin as Rt, authProviderCapability as S, DEVICE_STATUS_METHOD as St, batteryCapability as T, DeviceType as Tt, isCollectionArrayMethod as U, scopeKey as Ut, filesystemBrowseCapability as V, readinessKey as Vt, isObjectInput as W, sleep as Wt, logDestinationCapability as X, localNetworkCapability as Y, logLevelAtMost as Z, UserRecordSchema as _, vectorStoreCapability as _t, CAP_NAMES_WITH_STATUS as a, runtimeStatePolicyFor as at, addonWidgetsCapability as b, DATAPLANE_SECRET_HEADER as bt, CoreBlockSchema as c, scoreRuntimes as ct, METHOD_ACCESS_MAP as d, storageCapability as dt, normalizeUnit as et, RUNTIME_DEFAULTS as f, storageMigrationCapability as ft, StorageMigrationJobSchema as g, vectorDimFromBase64 as gt, StorageLocationTypeSchema as h, userManagementCapability as ht, BatteryStatusSchema as i, procedureAuthKey as it, decodeVectorBase64 as j, asString as jt, coreBlocksCapability as k, asJsonObject as kt, DeclaredDevices as l, settingsStoreCapability as lt, ScopedTokenSchema as m, streamQualityLabel as mt, AlertSchema as n, parseStreamParamsFormPatch as nt, CORE_BLOCKS_ADDON_ID as o, scopesAllowAddon as ot, STREAM_PROFILE_META as p, storageProviderCapability as pt, kebabToCamel as q, ApiKeyRecordSchema as r, platformProbeCapability as rt, CORE_BLOCK_ADDON_PREFIX as s, scopesAllowDeviceCap as st, ALL_CAPABILITY_DEFINITIONS as t, objectInputDeclaresAddonId as tt, DeviceStatusSchema as u, snapshotCapability as ut, addonPagesCapability as v, errMsg as vt, bareAddonId as w, DeviceRole as wt, alertsCapability as x, DEVICE_SETTINGS_CONTRIBUTION_METHODS as xt, addonSettingsCapability as y, BaseAddon as yt, enumerateSchemaFields as z, parseJsonObject as zt };
|
package/dist/index.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
2
2
|
const require_chunk = require("./chunk-Cek0wNdY.js");
|
|
3
|
-
const require_dist = require("./dist-
|
|
3
|
+
const require_dist = require("./dist-BspfS8Q7.js");
|
|
4
4
|
const require_builtins_alerts_alerts_addon = require("./builtins/alerts/alerts.addon.js");
|
|
5
5
|
require("./builtins/alerts/index.js");
|
|
6
6
|
const require_formatter = require("./formatter-DqAKDlvN.js");
|
package/dist/index.mjs
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { a as __toCommonJS, i as __require, n as __esmMin, o as __toESM$1, r as __exportAll, t as __commonJSMin$1 } from "./chunk-CNf5ZN-e.mjs";
|
|
2
|
-
import {
|
|
2
|
+
import { At as asNumber, B as extractNestedAddonId, Bt as parseJsonUnknown$1, Dt as ReadinessTimeoutError, Et as ReadinessRegistry, Ft as expandCapMethods, Gt as EventCategory$1, H as isArrayOutputSchema, Ht as resolveCapMount, J as lifecycleJobSchema, K as isVoidInput, Mt as createEvent, Nt as emitDownForOwnedCaps, Q as looseSchema, St as DEVICE_STATUS_METHOD, U as isCollectionArrayMethod, Ut as scopeKey, Vt as readinessKey, W as isObjectInput, Z as logLevelAtMost, bt as DATAPLANE_SECRET_HEADER$1, d as METHOD_ACCESS_MAP, f as RUNTIME_DEFAULTS, it as procedureAuthKey, jt as asString$1, kt as asJsonObject$1, ot as scopesAllowAddon, q as kebabToCamel, st as scopesAllowDeviceCap, t as ALL_CAPABILITY_DEFINITIONS, tt as objectInputDeclaresAddonId, vt as errMsg$1, xt as DEVICE_SETTINGS_CONTRIBUTION_METHODS, y as addonSettingsCapability, zt as parseJsonObject } from "./dist-COd223t-.mjs";
|
|
3
3
|
import { AlertCenterAddon } from "./builtins/alerts/alerts.addon.mjs";
|
|
4
4
|
import "./builtins/alerts/index.mjs";
|
|
5
5
|
import { t as formatLogLine } from "./formatter-B7qW8bPJ.mjs";
|