camstack 1.2.22 → 1.2.24
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.
|
@@ -6378,62 +6378,30 @@ var require_first_boot_addon_plan = __commonJS({
|
|
|
6378
6378
|
"../../server/backend/dist/first-boot-addon-plan.js"(exports) {
|
|
6379
6379
|
"use strict";
|
|
6380
6380
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6381
|
-
exports.resolveWantedVersion = resolveWantedVersion;
|
|
6382
|
-
exports.compareVersions = compareVersions;
|
|
6383
|
-
exports.bootstrapPinsFrom = bootstrapPinsFrom;
|
|
6384
6381
|
exports.planFirstBootAddons = planFirstBootAddons;
|
|
6385
6382
|
exports.formatFirstBootPlan = formatFirstBootPlan;
|
|
6386
|
-
var EXACT_VERSION = /^\d+\.\d+\.\d+(?:[-+][0-9A-Za-z-.]+)?$/;
|
|
6387
|
-
function resolveWantedVersion(raw) {
|
|
6388
|
-
if (raw !== void 0 && EXACT_VERSION.test(raw))
|
|
6389
|
-
return { spec: raw, pinned: true };
|
|
6390
|
-
return { spec: "latest", pinned: false };
|
|
6391
|
-
}
|
|
6392
|
-
function compareVersions(a, b) {
|
|
6393
|
-
if (!EXACT_VERSION.test(a) || !EXACT_VERSION.test(b))
|
|
6394
|
-
return null;
|
|
6395
|
-
const parse4 = (v) => v.split(/[-+]/)[0].split(".").map((n) => Number.parseInt(n, 10));
|
|
6396
|
-
const left = parse4(a);
|
|
6397
|
-
const right = parse4(b);
|
|
6398
|
-
for (let i = 0; i < 3; i++) {
|
|
6399
|
-
const l = left[i] ?? 0;
|
|
6400
|
-
const r = right[i] ?? 0;
|
|
6401
|
-
if (l !== r)
|
|
6402
|
-
return l > r ? 1 : -1;
|
|
6403
|
-
}
|
|
6404
|
-
return 0;
|
|
6405
|
-
}
|
|
6406
|
-
function bootstrapPinsFrom(manifest) {
|
|
6407
|
-
const out = {};
|
|
6408
|
-
for (const [name, spec] of Object.entries(manifest.dependencies ?? {})) {
|
|
6409
|
-
if (name.startsWith("@camstack/"))
|
|
6410
|
-
out[name] = spec;
|
|
6411
|
-
}
|
|
6412
|
-
return out;
|
|
6413
|
-
}
|
|
6414
6383
|
function planFirstBootAddons(input) {
|
|
6415
6384
|
const provided = new Set(input.closureProvided);
|
|
6416
|
-
const decisions = input.required.map((pkg) => decide(pkg, input.
|
|
6385
|
+
const decisions = input.required.map((pkg) => decide(pkg, input.installed, input.closureVersions, provided));
|
|
6417
6386
|
const wouldInstall = decisions.filter((d) => d.action === "install-npm").map((d) => d.pkg);
|
|
6418
6387
|
return {
|
|
6419
6388
|
decisions,
|
|
6420
6389
|
wouldInstall,
|
|
6421
|
-
|
|
6422
|
-
divergent: decisions.filter((d) => d.divergent).map((d) => d.pkg),
|
|
6390
|
+
twoVersions: decisions.filter((d) => d.twoVersions).map((d) => d.pkg),
|
|
6423
6391
|
needsRegistry: wouldInstall.length > 0
|
|
6424
6392
|
};
|
|
6425
6393
|
}
|
|
6426
|
-
function decide(pkg,
|
|
6427
|
-
const want = resolveWantedVersion(pin);
|
|
6394
|
+
function decide(pkg, installed, closureVersions, closureProvided) {
|
|
6428
6395
|
const hasEntry = Object.hasOwn(installed, pkg);
|
|
6429
6396
|
const version = installed[pkg] ?? null;
|
|
6397
|
+
const closureVersion = closureVersions[pkg] ?? null;
|
|
6430
6398
|
if (closureProvided.has(pkg)) {
|
|
6431
6399
|
return {
|
|
6432
6400
|
pkg,
|
|
6433
6401
|
action: "skip-closure-provided",
|
|
6434
|
-
want,
|
|
6435
6402
|
installedVersion: version,
|
|
6436
|
-
|
|
6403
|
+
closureVersion,
|
|
6404
|
+
twoVersions: false,
|
|
6437
6405
|
reason: "provided by the server closure \u2014 a copy here would shadow it (D15)"
|
|
6438
6406
|
};
|
|
6439
6407
|
}
|
|
@@ -6441,59 +6409,33 @@ var require_first_boot_addon_plan = __commonJS({
|
|
|
6441
6409
|
return {
|
|
6442
6410
|
pkg,
|
|
6443
6411
|
action: "install-npm",
|
|
6444
|
-
want,
|
|
6445
6412
|
installedVersion: null,
|
|
6446
|
-
|
|
6447
|
-
|
|
6413
|
+
closureVersion,
|
|
6414
|
+
twoVersions: false,
|
|
6415
|
+
reason: hasEntry ? "installed copy has an unreadable package.json \u2014 fetching latest" : "absent \u2014 fetching latest, which is the whole version contract (addons-agnostic)"
|
|
6448
6416
|
};
|
|
6449
6417
|
}
|
|
6418
|
+
const twoVersions = closureVersion !== null && closureVersion !== version;
|
|
6450
6419
|
return {
|
|
6451
6420
|
pkg,
|
|
6452
6421
|
action: "adopt-installed",
|
|
6453
|
-
want,
|
|
6454
6422
|
installedVersion: version,
|
|
6455
|
-
|
|
6456
|
-
|
|
6457
|
-
|
|
6458
|
-
function adoptionVerdict(version, want) {
|
|
6459
|
-
if (!want.pinned) {
|
|
6460
|
-
return { divergent: false, reason: `installed ${version}; the closure carries no pin to check` };
|
|
6461
|
-
}
|
|
6462
|
-
const order = compareVersions(version, want.spec);
|
|
6463
|
-
if (order === null) {
|
|
6464
|
-
return { divergent: true, reason: `installed ${version} is not comparable to pin ${want.spec}` };
|
|
6465
|
-
}
|
|
6466
|
-
if (order === 0)
|
|
6467
|
-
return { divergent: false, reason: `installed ${version} matches the pin` };
|
|
6468
|
-
const sameMajor = version.split(".")[0] === want.spec.split(".")[0];
|
|
6469
|
-
if (!sameMajor) {
|
|
6470
|
-
return {
|
|
6471
|
-
divergent: true,
|
|
6472
|
-
reason: `installed ${version} is a different major from the pinned ${want.spec} \u2014 a framework contract, not a version gap`
|
|
6473
|
-
};
|
|
6474
|
-
}
|
|
6475
|
-
if (order > 0) {
|
|
6476
|
-
return {
|
|
6477
|
-
divergent: false,
|
|
6478
|
-
reason: `installed ${version} is ahead of the pinned ${want.spec} \u2014 a deploy outranks the image (D90)`
|
|
6479
|
-
};
|
|
6480
|
-
}
|
|
6481
|
-
return {
|
|
6482
|
-
divergent: true,
|
|
6483
|
-
reason: `installed ${version} is BEHIND the pinned ${want.spec} \u2014 kept, because replacing it is an un-deploy`
|
|
6423
|
+
closureVersion,
|
|
6424
|
+
twoVersions,
|
|
6425
|
+
reason: twoVersions ? `installed ${version}; this closure carries ${closureVersion} \u2014 the installed copy is what runs (D90)` : `installed ${version} \u2014 kept`
|
|
6484
6426
|
};
|
|
6485
6427
|
}
|
|
6486
6428
|
function formatFirstBootPlan(plan, mode) {
|
|
6487
|
-
const header = `first-boot addon plan (${mode}) \u2014 ${plan.decisions.length} package(s), ${plan.wouldInstall.length} to install
|
|
6429
|
+
const header = `first-boot addon plan (${mode}) \u2014 ${plan.decisions.length} package(s), ${plan.wouldInstall.length} to install`;
|
|
6488
6430
|
const lines = [
|
|
6489
6431
|
mode === "observe" ? `${header}; nothing was installed from this plan` : header
|
|
6490
6432
|
];
|
|
6491
6433
|
for (const d of plan.decisions) {
|
|
6492
|
-
const target = d.action === "install-npm" ?
|
|
6434
|
+
const target = d.action === "install-npm" ? "@latest" : "";
|
|
6493
6435
|
lines.push(` ${d.pkg}${target} \u2014 ${d.action}: ${d.reason}`);
|
|
6494
6436
|
}
|
|
6495
|
-
if (plan.
|
|
6496
|
-
lines.push(`
|
|
6437
|
+
if (plan.twoVersions.length > 0) {
|
|
6438
|
+
lines.push(` two versions on this node (installed vs this closure's own copy): ${plan.twoVersions.join(", ")} \u2014 INFO: the installed copy is the one that runs`);
|
|
6497
6439
|
}
|
|
6498
6440
|
if (!plan.needsRegistry) {
|
|
6499
6441
|
lines.push(" no registry access needed \u2014 every required addon is already on disk");
|
|
@@ -23689,9 +23631,9 @@ var require_zod = __commonJS({
|
|
|
23689
23631
|
}
|
|
23690
23632
|
});
|
|
23691
23633
|
|
|
23692
|
-
// ../system/dist/dist-
|
|
23693
|
-
var
|
|
23694
|
-
"../system/dist/dist-
|
|
23634
|
+
// ../system/dist/dist-D4nuaPdd.js
|
|
23635
|
+
var require_dist_D4nuaPdd = __commonJS({
|
|
23636
|
+
"../system/dist/dist-D4nuaPdd.js"(exports) {
|
|
23695
23637
|
"use strict";
|
|
23696
23638
|
var zod = require_zod();
|
|
23697
23639
|
var EventCategory = /* @__PURE__ */ (function(EventCategory2) {
|
|
@@ -29149,7 +29091,14 @@ var require_dist_DiScsb8j = __commonJS({
|
|
|
29149
29091
|
low: zod.z.string().optional()
|
|
29150
29092
|
}),
|
|
29151
29093
|
lastChangedAt: zod.z.number()
|
|
29152
|
-
})
|
|
29094
|
+
}),
|
|
29095
|
+
/**
|
|
29096
|
+
* Runtime-state durability: **session** — a restored `slotStatuses: streaming` for a camera that has been dark for two hours is a lie the UI renders as truth.
|
|
29097
|
+
*
|
|
29098
|
+
* See `RuntimeStateDurability`. Enforced by
|
|
29099
|
+
* `scripts/check-runtime-state-durability.ts`.
|
|
29100
|
+
*/
|
|
29101
|
+
durability: "session"
|
|
29153
29102
|
};
|
|
29154
29103
|
function isVoidInput(schema) {
|
|
29155
29104
|
const def = schema._def;
|
|
@@ -29819,6 +29768,13 @@ var require_dist_DiScsb8j = __commonJS({
|
|
|
29819
29768
|
kind: "poll"
|
|
29820
29769
|
},
|
|
29821
29770
|
runtimeState: DeviceDiscoveryStatusSchema.extend({ lastFetchedAt: zod.z.number().int().nonnegative() }),
|
|
29771
|
+
/**
|
|
29772
|
+
* Runtime-state durability: **session** — 5.7 KB of scan output on the largest device, fully re-derivable by re-scanning.
|
|
29773
|
+
*
|
|
29774
|
+
* See `RuntimeStateDurability`. Enforced by
|
|
29775
|
+
* `scripts/check-runtime-state-durability.ts`.
|
|
29776
|
+
*/
|
|
29777
|
+
durability: "session",
|
|
29822
29778
|
methods: {
|
|
29823
29779
|
/**
|
|
29824
29780
|
* Snapshot of the current `discovered` list. Returns the
|
|
@@ -32043,7 +31999,23 @@ var require_dist_DiScsb8j = __commonJS({
|
|
|
32043
31999
|
* else — see `notification-center/action-token.ts` for what that does and
|
|
32044
32000
|
* does not buy.
|
|
32045
32001
|
*/
|
|
32046
|
-
destructive: zod.z.boolean().optional()
|
|
32002
|
+
destructive: zod.z.boolean().optional(),
|
|
32003
|
+
/**
|
|
32004
|
+
* How the tap should REACH the url.
|
|
32005
|
+
*
|
|
32006
|
+
* `navigate` (absent, and every button authored before this field) opens it:
|
|
32007
|
+
* the phone leaves the notification and shows whatever the callback returns.
|
|
32008
|
+
* That is right for a button whose answer the operator wants to read.
|
|
32009
|
+
*
|
|
32010
|
+
* `background` fires it as a POST and stays put. It exists for the buttons
|
|
32011
|
+
* whose whole point is not to interrupt — "silence this for 30 minutes" is
|
|
32012
|
+
* an answer to the notification, and being thrown into a browser tab to
|
|
32013
|
+
* confirm it costs more attention than the notification did. A backend that
|
|
32014
|
+
* cannot do a background call renders it as an ordinary link (the adapters
|
|
32015
|
+
* fall back rather than dropping the button), so this is a preference, never
|
|
32016
|
+
* a requirement.
|
|
32017
|
+
*/
|
|
32018
|
+
mode: zod.z.enum(["navigate", "background"]).optional()
|
|
32047
32019
|
});
|
|
32048
32020
|
var NotificationSchema = zod.z.object({
|
|
32049
32021
|
body: zod.z.string(),
|
|
@@ -32821,7 +32793,17 @@ var require_dist_DiScsb8j = __commonJS({
|
|
|
32821
32793
|
* full slice; renders an arm button per `availableModes` entry and
|
|
32822
32794
|
* a PIN field iff `requiresCode === true`.
|
|
32823
32795
|
*/
|
|
32824
|
-
runtimeState: AlarmPanelStatusSchema
|
|
32796
|
+
runtimeState: AlarmPanelStatusSchema,
|
|
32797
|
+
/**
|
|
32798
|
+
* Runtime-state durability: **restored** — armed state is the one thing a panel must not lose across a restart.
|
|
32799
|
+
*
|
|
32800
|
+
* See `RuntimeStateDurability`. Enforced by
|
|
32801
|
+
* `scripts/check-runtime-state-durability.ts`.
|
|
32802
|
+
*/
|
|
32803
|
+
durability: "restored",
|
|
32804
|
+
/** Clock fields: written, but excluded from the compare that decides
|
|
32805
|
+
* whether persisting is worth a SQLite commit. */
|
|
32806
|
+
volatileStateFields: ["lastChangedAt"]
|
|
32825
32807
|
};
|
|
32826
32808
|
var MaskPointSchema = zod.z.object({
|
|
32827
32809
|
x: zod.z.number(),
|
|
@@ -32919,6 +32901,7 @@ var require_dist_DiScsb8j = __commonJS({
|
|
|
32919
32901
|
nodeIds: zod.z.array(zod.z.string().min(1)).min(1).optional(),
|
|
32920
32902
|
packageNames: zod.z.array(zod.z.string().min(1)).min(1).optional()
|
|
32921
32903
|
});
|
|
32904
|
+
var NC_SNOOZE_MAX_MINUTES = 1440;
|
|
32922
32905
|
var NcScheduleWindowSchema = zod.z.object({
|
|
32923
32906
|
/** Days of week the window STARTS on (0 = Sunday … 6 = Saturday). */
|
|
32924
32907
|
days: zod.z.array(zod.z.number().int().min(0).max(6)).min(1),
|
|
@@ -33175,15 +33158,15 @@ var require_dist_DiScsb8j = __commonJS({
|
|
|
33175
33158
|
* (an `immediate` rule naming an `audio-*` class, one notification per
|
|
33176
33159
|
* classified sample) stays exactly as it was for rules that already use it.
|
|
33177
33160
|
*
|
|
33178
|
-
*
|
|
33179
|
-
* rather than an
|
|
33180
|
-
* (`camstack/src/data/notification-center.ts`, guarded by
|
|
33181
|
-
* `scripts/check-viewer-condition-mirror.ts`) and its rule editor
|
|
33161
|
+
* In {@link NC_CONDITION_CATALOG} since P2, and the ORDER it got there is the
|
|
33162
|
+
* rule rather than an accident: the viewer mirrors the descriptor enums BY
|
|
33163
|
+
* HAND (`camstack/src/data/notification-center.ts`, guarded by
|
|
33164
|
+
* `scripts/check-viewer-condition-mirror.ts`) and its rule editor strips the
|
|
33182
33165
|
* condition fields it does not know when a rule is saved from the phone.
|
|
33183
33166
|
* Publishing an editor for a condition the app cannot round-trip is how an
|
|
33184
|
-
* operator loses a rule's conditions by opening it — so the
|
|
33185
|
-
*
|
|
33186
|
-
*
|
|
33167
|
+
* operator loses a rule's conditions by opening it — so the viewer mirror
|
|
33168
|
+
* (P3, shipped) went FIRST, and the descriptor an editor renders from
|
|
33169
|
+
* follows here.
|
|
33187
33170
|
*/
|
|
33188
33171
|
audio: NcAudioConditionSchema.optional()
|
|
33189
33172
|
});
|
|
@@ -33352,6 +33335,30 @@ var require_dist_DiScsb8j = __commonJS({
|
|
|
33352
33335
|
*/
|
|
33353
33336
|
snoozeAllowGlobal: zod.z.boolean().optional(),
|
|
33354
33337
|
/**
|
|
33338
|
+
* The snooze durations THIS rule's notification offers as buttons, in
|
|
33339
|
+
* minutes.
|
|
33340
|
+
*
|
|
33341
|
+
* Three states, and all three are distinct — which is exactly why this is
|
|
33342
|
+
* `.optional()` and never `.default()`. A Zod default does not run on the
|
|
33343
|
+
* addon cap path (three production failures in one day), so a schema default
|
|
33344
|
+
* would collapse the first two:
|
|
33345
|
+
*
|
|
33346
|
+
* | value | meaning |
|
|
33347
|
+
* | --- | --- |
|
|
33348
|
+
* | absent | the operator never said ⇒ {@link NC_DEFAULT_SNOOZE_MINUTES} |
|
|
33349
|
+
* | `[]` | **no snooze buttons on this rule** — the explicit override |
|
|
33350
|
+
* | a list | these choices, de-duplicated and sorted, at most four |
|
|
33351
|
+
*
|
|
33352
|
+
* `.max(4)` because the notifier's own action budget is small (ntfy allows
|
|
33353
|
+
* three buttons in total) and a rule that spent it all on snooze choices
|
|
33354
|
+
* would push its own tap-through actions off the notification.
|
|
33355
|
+
*
|
|
33356
|
+
* An empty list is NOT an alarm exemption: a rule the alarm is about, or
|
|
33357
|
+
* that arms the panel, is exempt automatically and cannot be silenced by a
|
|
33358
|
+
* window from anywhere (D133).
|
|
33359
|
+
*/
|
|
33360
|
+
snoozeOptions: zod.z.array(zod.z.number().int().min(1).max(NC_SNOOZE_MAX_MINUTES)).max(4).optional(),
|
|
33361
|
+
/**
|
|
33355
33362
|
* Devices this rule ACTUATES — arm the alarm, open a gate, turn on a light.
|
|
33356
33363
|
*
|
|
33357
33364
|
* This is what makes the rule set the alarm's trigger set without the alarm
|
|
@@ -33441,6 +33448,7 @@ var require_dist_DiScsb8j = __commonJS({
|
|
|
33441
33448
|
"device",
|
|
33442
33449
|
"package",
|
|
33443
33450
|
"occupancy",
|
|
33451
|
+
"audio",
|
|
33444
33452
|
"system"
|
|
33445
33453
|
]),
|
|
33446
33454
|
label: zod.z.string(),
|
|
@@ -33459,6 +33467,7 @@ var require_dist_DiScsb8j = __commonJS({
|
|
|
33459
33467
|
"crossingSelect",
|
|
33460
33468
|
"polygonDraw",
|
|
33461
33469
|
"occupancy",
|
|
33470
|
+
"audio",
|
|
33462
33471
|
"deviceState",
|
|
33463
33472
|
"systemEvent"
|
|
33464
33473
|
]),
|
|
@@ -33569,7 +33578,20 @@ var require_dist_DiScsb8j = __commonJS({
|
|
|
33569
33578
|
ruleId: zod.z.string().optional(),
|
|
33570
33579
|
/** Required when `scope: 'device'`. */
|
|
33571
33580
|
deviceId: zod.z.number().int().optional(),
|
|
33572
|
-
|
|
33581
|
+
/**
|
|
33582
|
+
* Narrow the window to these subject classes — "the cat, not the person".
|
|
33583
|
+
*
|
|
33584
|
+
* ORTHOGONAL to `scope`, deliberately, and absent means EVERY class: that is
|
|
33585
|
+
* what every window authored before this field meant, so no persisted row
|
|
33586
|
+
* changes meaning and no client has to learn anything to keep working.
|
|
33587
|
+
*
|
|
33588
|
+
* It is what makes the window's real key `(deviceId, classes[])` and lets it
|
|
33589
|
+
* cross rules (D133): the operator points at a camera and a kind of thing,
|
|
33590
|
+
* not at whichever of their four rules happened to produce the notification
|
|
33591
|
+
* they are dismissing.
|
|
33592
|
+
*/
|
|
33593
|
+
classes: zod.z.array(zod.z.string().min(1)).min(1).optional(),
|
|
33594
|
+
durationMinutes: zod.z.number().int().min(1).max(NC_SNOOZE_MAX_MINUTES),
|
|
33573
33595
|
/**
|
|
33574
33596
|
* Silence this for EVERY recipient, not just the caller. Permission is
|
|
33575
33597
|
* checked server-side (the rule's `snoozeAllowGlobal`, or admin for the
|
|
@@ -33593,6 +33615,10 @@ var require_dist_DiScsb8j = __commonJS({
|
|
|
33593
33615
|
scope: NcSnoozeScopeSchema,
|
|
33594
33616
|
ruleId: zod.z.string().optional(),
|
|
33595
33617
|
deviceId: zod.z.number().int().optional(),
|
|
33618
|
+
/** Subject classes this window covers. ABSENT = every class — see
|
|
33619
|
+
* {@link NcSnoozeInputSchema.shape.classes}. Lives in the JSON blob and has
|
|
33620
|
+
* no SQLite column: nothing queries a window by class. */
|
|
33621
|
+
classes: zod.z.array(zod.z.string().min(1)).min(1).optional(),
|
|
33596
33622
|
startedAt: zod.z.number(),
|
|
33597
33623
|
/** Exclusive: at exactly this instant the snooze is over. Expiry is a
|
|
33598
33624
|
* COMPARISON, not a job — no sweeper can leave the operator silenced. */
|
|
@@ -35865,7 +35891,14 @@ var require_dist_DiScsb8j = __commonJS({
|
|
|
35865
35891
|
* handle. Slice shape is `{ zones: Zone[] }` so future extensions
|
|
35866
35892
|
* (e.g. zone groupings) can sit alongside the polygon list.
|
|
35867
35893
|
*/
|
|
35868
|
-
runtimeState: zod.z.object({ zones: zod.z.array(ZoneSchema).readonly() })
|
|
35894
|
+
runtimeState: zod.z.object({ zones: zod.z.array(ZoneSchema).readonly() }),
|
|
35895
|
+
/**
|
|
35896
|
+
* Runtime-state durability: **restored** — written only on operator mutation, so a camera that never had one has nothing to re-derive from. This is the slice `zone-mirror-hydration.ts` exists to paper over.
|
|
35897
|
+
*
|
|
35898
|
+
* See `RuntimeStateDurability`. Enforced by
|
|
35899
|
+
* `scripts/check-runtime-state-durability.ts`.
|
|
35900
|
+
*/
|
|
35901
|
+
durability: "restored"
|
|
35869
35902
|
};
|
|
35870
35903
|
var NativeCropBboxSchema = zod.z.object({
|
|
35871
35904
|
x: zod.z.number(),
|
|
@@ -39168,7 +39201,17 @@ var require_dist_DiScsb8j = __commonJS({
|
|
|
39168
39201
|
schema: AirQualitySensorStatusSchema,
|
|
39169
39202
|
kind: "push"
|
|
39170
39203
|
},
|
|
39171
|
-
runtimeState: AirQualitySensorStatusSchema
|
|
39204
|
+
runtimeState: AirQualitySensorStatusSchema,
|
|
39205
|
+
/**
|
|
39206
|
+
* Runtime-state durability: **restored** — as `numeric-sensor`.
|
|
39207
|
+
*
|
|
39208
|
+
* See `RuntimeStateDurability`. Enforced by
|
|
39209
|
+
* `scripts/check-runtime-state-durability.ts`.
|
|
39210
|
+
*/
|
|
39211
|
+
durability: "restored",
|
|
39212
|
+
/** Clock fields: written, but excluded from the compare that decides
|
|
39213
|
+
* whether persisting is worth a SQLite commit. */
|
|
39214
|
+
volatileStateFields: ["lastFetchedAt"]
|
|
39172
39215
|
};
|
|
39173
39216
|
var AmbientLightSensorStatusSchema = zod.z.object({
|
|
39174
39217
|
/** Current illuminance in lux (lx). */
|
|
@@ -39196,7 +39239,17 @@ var require_dist_DiScsb8j = __commonJS({
|
|
|
39196
39239
|
schema: AmbientLightSensorStatusSchema,
|
|
39197
39240
|
kind: "push"
|
|
39198
39241
|
},
|
|
39199
|
-
runtimeState: AmbientLightSensorStatusSchema
|
|
39242
|
+
runtimeState: AmbientLightSensorStatusSchema,
|
|
39243
|
+
/**
|
|
39244
|
+
* Runtime-state durability: **restored** — as `numeric-sensor`.
|
|
39245
|
+
*
|
|
39246
|
+
* See `RuntimeStateDurability`. Enforced by
|
|
39247
|
+
* `scripts/check-runtime-state-durability.ts`.
|
|
39248
|
+
*/
|
|
39249
|
+
durability: "restored",
|
|
39250
|
+
/** Clock fields: written, but excluded from the compare that decides
|
|
39251
|
+
* whether persisting is worth a SQLite commit. */
|
|
39252
|
+
volatileStateFields: ["lastFetchedAt"]
|
|
39200
39253
|
};
|
|
39201
39254
|
var AudioClassSummarySchema = zod.z.object({
|
|
39202
39255
|
className: zod.z.string(),
|
|
@@ -39286,7 +39339,14 @@ var require_dist_DiScsb8j = __commonJS({
|
|
|
39286
39339
|
}), AudioMetricsHistorySchema)
|
|
39287
39340
|
},
|
|
39288
39341
|
/** Reactive runtime-state mirror — live `device.state.audioMetrics.value`. */
|
|
39289
|
-
runtimeState: AudioMetricsSnapshotSchema
|
|
39342
|
+
runtimeState: AudioMetricsSnapshotSchema,
|
|
39343
|
+
/**
|
|
39344
|
+
* Runtime-state durability: **session** — 1 Hz per camera at the mirror and ~63 % of the fleet's whole runtime-state write rate. `avgDbfs` is a rolling 60 s mean that genuinely moves every second, so no equality fix reclaims it — and a two-hour-old dB reading rendered as current is worse than no reading.
|
|
39345
|
+
*
|
|
39346
|
+
* See `RuntimeStateDurability`. Enforced by
|
|
39347
|
+
* `scripts/check-runtime-state-durability.ts`.
|
|
39348
|
+
*/
|
|
39349
|
+
durability: "session"
|
|
39290
39350
|
};
|
|
39291
39351
|
var AutomationControlStatusSchema = zod.z.object({
|
|
39292
39352
|
/** Whether the automation is currently enabled. Disabled automations
|
|
@@ -39337,7 +39397,14 @@ var require_dist_DiScsb8j = __commonJS({
|
|
|
39337
39397
|
* reads `enabled` (toggle) + `isRunning` (spinner) + `lastError`
|
|
39338
39398
|
* (badge) directly.
|
|
39339
39399
|
*/
|
|
39340
|
-
runtimeState: AutomationControlStatusSchema
|
|
39400
|
+
runtimeState: AutomationControlStatusSchema,
|
|
39401
|
+
/**
|
|
39402
|
+
* Runtime-state durability: **session** — the authority for an automation being enabled is the automation store; a restored `isRunning` would be a lie. D62: one authority per switch.
|
|
39403
|
+
*
|
|
39404
|
+
* See `RuntimeStateDurability`. Enforced by
|
|
39405
|
+
* `scripts/check-runtime-state-durability.ts`.
|
|
39406
|
+
*/
|
|
39407
|
+
durability: "session"
|
|
39341
39408
|
};
|
|
39342
39409
|
var BatteryStatusSchema = zod.z.object({
|
|
39343
39410
|
/** 0..100 inclusive. Firmware-reported. */
|
|
@@ -39438,7 +39505,17 @@ var require_dist_DiScsb8j = __commonJS({
|
|
|
39438
39505
|
* via `device.runtimeState.getCapState('battery')` regardless of
|
|
39439
39506
|
* the underlying driver.
|
|
39440
39507
|
*/
|
|
39441
|
-
runtimeState: BatteryStatusSchema
|
|
39508
|
+
runtimeState: BatteryStatusSchema,
|
|
39509
|
+
/**
|
|
39510
|
+
* Runtime-state durability: **restored** — a sleeping battery camera may not report for hours; the restored percentage is the only thing the UI and the sleep gate have. Zero churn once `lastUpdated` is excluded — 526 writes, 0 value changes, in 25 minutes.
|
|
39511
|
+
*
|
|
39512
|
+
* See `RuntimeStateDurability`. Enforced by
|
|
39513
|
+
* `scripts/check-runtime-state-durability.ts`.
|
|
39514
|
+
*/
|
|
39515
|
+
durability: "restored",
|
|
39516
|
+
/** Clock fields: written, but excluded from the compare that decides
|
|
39517
|
+
* whether persisting is worth a SQLite commit. */
|
|
39518
|
+
volatileStateFields: ["lastUpdated"]
|
|
39442
39519
|
};
|
|
39443
39520
|
var BinaryStatusSchema = zod.z.object({
|
|
39444
39521
|
on: zod.z.boolean(),
|
|
@@ -39456,7 +39533,17 @@ var require_dist_DiScsb8j = __commonJS({
|
|
|
39456
39533
|
schema: BinaryStatusSchema,
|
|
39457
39534
|
kind: "push"
|
|
39458
39535
|
},
|
|
39459
|
-
runtimeState: BinaryStatusSchema
|
|
39536
|
+
runtimeState: BinaryStatusSchema,
|
|
39537
|
+
/**
|
|
39538
|
+
* Runtime-state durability: **restored** — transition-driven sensor state; the restored value gives the boot comparison.
|
|
39539
|
+
*
|
|
39540
|
+
* See `RuntimeStateDurability`. Enforced by
|
|
39541
|
+
* `scripts/check-runtime-state-durability.ts`.
|
|
39542
|
+
*/
|
|
39543
|
+
durability: "restored",
|
|
39544
|
+
/** Clock fields: written, but excluded from the compare that decides
|
|
39545
|
+
* whether persisting is worth a SQLite commit. */
|
|
39546
|
+
volatileStateFields: ["lastChangedAt"]
|
|
39460
39547
|
};
|
|
39461
39548
|
var BrightnessStatusSchema = zod.z.object({
|
|
39462
39549
|
/** Current level as 0..100 inclusive. Firmware-reported. */
|
|
@@ -39498,7 +39585,14 @@ var require_dist_DiScsb8j = __commonJS({
|
|
|
39498
39585
|
* by the kernel. Read via `device.state.brightness.value` so UI
|
|
39499
39586
|
* sliders surface the current level without polling the provider.
|
|
39500
39587
|
*/
|
|
39501
|
-
runtimeState: BrightnessStatusSchema
|
|
39588
|
+
runtimeState: BrightnessStatusSchema,
|
|
39589
|
+
/**
|
|
39590
|
+
* Runtime-state durability: **session** — live lamp state, re-published by the provider on connect.
|
|
39591
|
+
*
|
|
39592
|
+
* See `RuntimeStateDurability`. Enforced by
|
|
39593
|
+
* `scripts/check-runtime-state-durability.ts`.
|
|
39594
|
+
*/
|
|
39595
|
+
durability: "session"
|
|
39502
39596
|
};
|
|
39503
39597
|
var buttonCapability = {
|
|
39504
39598
|
name: "button",
|
|
@@ -39578,7 +39672,17 @@ var require_dist_DiScsb8j = __commonJS({
|
|
|
39578
39672
|
schema: CarbonMonoxideStatusSchema,
|
|
39579
39673
|
kind: "push"
|
|
39580
39674
|
},
|
|
39581
|
-
runtimeState: CarbonMonoxideStatusSchema
|
|
39675
|
+
runtimeState: CarbonMonoxideStatusSchema,
|
|
39676
|
+
/**
|
|
39677
|
+
* Runtime-state durability: **restored** — as `smoke`.
|
|
39678
|
+
*
|
|
39679
|
+
* See `RuntimeStateDurability`. Enforced by
|
|
39680
|
+
* `scripts/check-runtime-state-durability.ts`.
|
|
39681
|
+
*/
|
|
39682
|
+
durability: "restored",
|
|
39683
|
+
/** Clock fields: written, but excluded from the compare that decides
|
|
39684
|
+
* whether persisting is worth a SQLite commit. */
|
|
39685
|
+
volatileStateFields: ["lastChangedAt"]
|
|
39582
39686
|
};
|
|
39583
39687
|
var HvacModeSchema = zod.z.enum([
|
|
39584
39688
|
"off",
|
|
@@ -39707,7 +39811,14 @@ var require_dist_DiScsb8j = __commonJS({
|
|
|
39707
39811
|
* the full slice via `device.state.climate-control.value` and refresh
|
|
39708
39812
|
* on every push without re-querying the provider.
|
|
39709
39813
|
*/
|
|
39710
|
-
runtimeState: ClimateControlStatusSchema
|
|
39814
|
+
runtimeState: ClimateControlStatusSchema,
|
|
39815
|
+
/**
|
|
39816
|
+
* Runtime-state durability: **session** — as `brightness`; `currentTemp` moves continuously and is re-published on connect.
|
|
39817
|
+
*
|
|
39818
|
+
* See `RuntimeStateDurability`. Enforced by
|
|
39819
|
+
* `scripts/check-runtime-state-durability.ts`.
|
|
39820
|
+
*/
|
|
39821
|
+
durability: "session"
|
|
39711
39822
|
};
|
|
39712
39823
|
var RgbTripletSchema = zod.z.object({
|
|
39713
39824
|
r: zod.z.number().int().min(0).max(255),
|
|
@@ -39794,7 +39905,14 @@ var require_dist_DiScsb8j = __commonJS({
|
|
|
39794
39905
|
* kernel. Read via `device.state.color.value` so UI pickers surface
|
|
39795
39906
|
* the current chromaticity without polling the provider.
|
|
39796
39907
|
*/
|
|
39797
|
-
runtimeState: ColorStatusSchema
|
|
39908
|
+
runtimeState: ColorStatusSchema,
|
|
39909
|
+
/**
|
|
39910
|
+
* Runtime-state durability: **session** — as `brightness`.
|
|
39911
|
+
*
|
|
39912
|
+
* See `RuntimeStateDurability`. Enforced by
|
|
39913
|
+
* `scripts/check-runtime-state-durability.ts`.
|
|
39914
|
+
*/
|
|
39915
|
+
durability: "session"
|
|
39798
39916
|
};
|
|
39799
39917
|
var ConnectionTestOutcomeSchema = zod.z.discriminatedUnion("outcome", [
|
|
39800
39918
|
zod.z.object({
|
|
@@ -39848,7 +39966,17 @@ var require_dist_DiScsb8j = __commonJS({
|
|
|
39848
39966
|
schema: ConnectivityStatusSchema,
|
|
39849
39967
|
kind: "push"
|
|
39850
39968
|
},
|
|
39851
|
-
runtimeState: ConnectivityStatusSchema
|
|
39969
|
+
runtimeState: ConnectivityStatusSchema,
|
|
39970
|
+
/**
|
|
39971
|
+
* Runtime-state durability: **restored** — same shape and same argument as `device-status`, for links rather than devices.
|
|
39972
|
+
*
|
|
39973
|
+
* See `RuntimeStateDurability`. Enforced by
|
|
39974
|
+
* `scripts/check-runtime-state-durability.ts`.
|
|
39975
|
+
*/
|
|
39976
|
+
durability: "restored",
|
|
39977
|
+
/** Clock fields: written, but excluded from the compare that decides
|
|
39978
|
+
* whether persisting is worth a SQLite commit. */
|
|
39979
|
+
volatileStateFields: ["lastChangedAt"]
|
|
39852
39980
|
};
|
|
39853
39981
|
var ConsumableItemSchema = zod.z.object({
|
|
39854
39982
|
/** Stable id, e.g. 'main-brush'. */
|
|
@@ -39915,7 +40043,14 @@ var require_dist_DiScsb8j = __commonJS({
|
|
|
39915
40043
|
}
|
|
39916
40044
|
}
|
|
39917
40045
|
},
|
|
39918
|
-
runtimeState: ConsumablesStatusSchema.extend({ lastFetchedAt: zod.z.number() })
|
|
40046
|
+
runtimeState: ConsumablesStatusSchema.extend({ lastFetchedAt: zod.z.number() }),
|
|
40047
|
+
/**
|
|
40048
|
+
* Runtime-state durability: **session** — the authority is the appliance; the provider re-reads the whole item array on connect.
|
|
40049
|
+
*
|
|
40050
|
+
* See `RuntimeStateDurability`. Enforced by
|
|
40051
|
+
* `scripts/check-runtime-state-durability.ts`.
|
|
40052
|
+
*/
|
|
40053
|
+
durability: "session"
|
|
39919
40054
|
};
|
|
39920
40055
|
var ContactStatusSchema = zod.z.object({
|
|
39921
40056
|
/** True when the entry is open; false when closed. */
|
|
@@ -39934,7 +40069,17 @@ var require_dist_DiScsb8j = __commonJS({
|
|
|
39934
40069
|
schema: ContactStatusSchema,
|
|
39935
40070
|
kind: "push"
|
|
39936
40071
|
},
|
|
39937
|
-
runtimeState: ContactStatusSchema
|
|
40072
|
+
runtimeState: ContactStatusSchema,
|
|
40073
|
+
/**
|
|
40074
|
+
* Runtime-state durability: **restored** — a door left open across a restart must still read open.
|
|
40075
|
+
*
|
|
40076
|
+
* See `RuntimeStateDurability`. Enforced by
|
|
40077
|
+
* `scripts/check-runtime-state-durability.ts`.
|
|
40078
|
+
*/
|
|
40079
|
+
durability: "restored",
|
|
40080
|
+
/** Clock fields: written, but excluded from the compare that decides
|
|
40081
|
+
* whether persisting is worth a SQLite commit. */
|
|
40082
|
+
volatileStateFields: ["lastChangedAt"]
|
|
39938
40083
|
};
|
|
39939
40084
|
var ControlKindSchema = zod.z.enum([
|
|
39940
40085
|
"numeric",
|
|
@@ -40021,7 +40166,14 @@ var require_dist_DiScsb8j = __commonJS({
|
|
|
40021
40166
|
* dropdown / text field / date picker) read the slice's discriminant
|
|
40022
40167
|
* and value directly without polling the provider.
|
|
40023
40168
|
*/
|
|
40024
|
-
runtimeState: ControlStatusSchema
|
|
40169
|
+
runtimeState: ControlStatusSchema,
|
|
40170
|
+
/**
|
|
40171
|
+
* Runtime-state durability: **session** — a generic control mirrors an external entity that re-publishes on connect; the options array is re-derived with it.
|
|
40172
|
+
*
|
|
40173
|
+
* See `RuntimeStateDurability`. Enforced by
|
|
40174
|
+
* `scripts/check-runtime-state-durability.ts`.
|
|
40175
|
+
*/
|
|
40176
|
+
durability: "session"
|
|
40025
40177
|
};
|
|
40026
40178
|
var CoverStateSchema = zod.z.enum([
|
|
40027
40179
|
"open",
|
|
@@ -40083,7 +40235,17 @@ var require_dist_DiScsb8j = __commonJS({
|
|
|
40083
40235
|
* Runtime-state slice — mirrored by the kernel. UI controls watch
|
|
40084
40236
|
* the slice for live position changes during a move.
|
|
40085
40237
|
*/
|
|
40086
|
-
runtimeState: CoverStatusSchema
|
|
40238
|
+
runtimeState: CoverStatusSchema,
|
|
40239
|
+
/**
|
|
40240
|
+
* Runtime-state durability: **restored** — position survives a restart on the device; the mirror should agree at boot rather than read blank.
|
|
40241
|
+
*
|
|
40242
|
+
* See `RuntimeStateDurability`. Enforced by
|
|
40243
|
+
* `scripts/check-runtime-state-durability.ts`.
|
|
40244
|
+
*/
|
|
40245
|
+
durability: "restored",
|
|
40246
|
+
/** Clock fields: written, but excluded from the compare that decides
|
|
40247
|
+
* whether persisting is worth a SQLite commit. */
|
|
40248
|
+
volatileStateFields: ["lastChangedAt"]
|
|
40087
40249
|
};
|
|
40088
40250
|
var DayNightModeSchema = zod.z.enum([
|
|
40089
40251
|
"auto",
|
|
@@ -40144,7 +40306,17 @@ var require_dist_DiScsb8j = __commonJS({
|
|
|
40144
40306
|
schema: DayNightStatusSchema,
|
|
40145
40307
|
kind: "poll"
|
|
40146
40308
|
},
|
|
40147
|
-
runtimeState: DayNightStatusSchema
|
|
40309
|
+
runtimeState: DayNightStatusSchema,
|
|
40310
|
+
/**
|
|
40311
|
+
* Runtime-state durability: **restored** — operator-set IR-cut behaviour; mutation-driven.
|
|
40312
|
+
*
|
|
40313
|
+
* See `RuntimeStateDurability`. Enforced by
|
|
40314
|
+
* `scripts/check-runtime-state-durability.ts`.
|
|
40315
|
+
*/
|
|
40316
|
+
durability: "restored",
|
|
40317
|
+
/** Clock fields: written, but excluded from the compare that decides
|
|
40318
|
+
* whether persisting is worth a SQLite commit. */
|
|
40319
|
+
volatileStateFields: ["lastFetchedAt"]
|
|
40148
40320
|
};
|
|
40149
40321
|
var DeviceStatusSchema = zod.z.object({
|
|
40150
40322
|
/**
|
|
@@ -40177,7 +40349,17 @@ var require_dist_DiScsb8j = __commonJS({
|
|
|
40177
40349
|
schema: DeviceStatusSchema,
|
|
40178
40350
|
kind: "push"
|
|
40179
40351
|
},
|
|
40180
|
-
runtimeState: DeviceStatusSchema
|
|
40352
|
+
runtimeState: DeviceStatusSchema,
|
|
40353
|
+
/**
|
|
40354
|
+
* Runtime-state durability: **restored** — the previous observation is what makes the first reading after a restart a COMPARISON instead of a phantom transition (D130). 32 real flips across 16 devices in 25 min — the busiest slice in the cold half.
|
|
40355
|
+
*
|
|
40356
|
+
* See `RuntimeStateDurability`. Enforced by
|
|
40357
|
+
* `scripts/check-runtime-state-durability.ts`.
|
|
40358
|
+
*/
|
|
40359
|
+
durability: "restored",
|
|
40360
|
+
/** Clock fields: written, but excluded from the compare that decides
|
|
40361
|
+
* whether persisting is worth a SQLite commit. */
|
|
40362
|
+
volatileStateFields: ["lastChangedAt"]
|
|
40181
40363
|
};
|
|
40182
40364
|
var DoorbellStatusSchema = zod.z.object({
|
|
40183
40365
|
/** Ms epoch of the last press. null = never observed since this provider started. */
|
|
@@ -40217,7 +40399,14 @@ var require_dist_DiScsb8j = __commonJS({
|
|
|
40217
40399
|
* `device.state.doorbell.value`. UIs can show "last ring 5m ago"
|
|
40218
40400
|
* without subscribing.
|
|
40219
40401
|
*/
|
|
40220
|
-
runtimeState: DoorbellStatusSchema
|
|
40402
|
+
runtimeState: DoorbellStatusSchema,
|
|
40403
|
+
/**
|
|
40404
|
+
* Runtime-state durability: **restored** — a monotonic accumulator: the slice IS the record. `lastPressedAt` is content here, not a clock, so it is deliberately NOT volatile.
|
|
40405
|
+
*
|
|
40406
|
+
* See `RuntimeStateDurability`. Enforced by
|
|
40407
|
+
* `scripts/check-runtime-state-durability.ts`.
|
|
40408
|
+
*/
|
|
40409
|
+
durability: "restored"
|
|
40221
40410
|
};
|
|
40222
40411
|
var EnumSensorDateTimeFormatSchema = zod.z.enum([
|
|
40223
40412
|
"date",
|
|
@@ -40247,7 +40436,17 @@ var require_dist_DiScsb8j = __commonJS({
|
|
|
40247
40436
|
schema: EnumSensorStatusSchema,
|
|
40248
40437
|
kind: "push"
|
|
40249
40438
|
},
|
|
40250
|
-
runtimeState: EnumSensorStatusSchema
|
|
40439
|
+
runtimeState: EnumSensorStatusSchema,
|
|
40440
|
+
/**
|
|
40441
|
+
* Runtime-state durability: **restored** — as `numeric-sensor`; 80 devices.
|
|
40442
|
+
*
|
|
40443
|
+
* See `RuntimeStateDurability`. Enforced by
|
|
40444
|
+
* `scripts/check-runtime-state-durability.ts`.
|
|
40445
|
+
*/
|
|
40446
|
+
durability: "restored",
|
|
40447
|
+
/** Clock fields: written, but excluded from the compare that decides
|
|
40448
|
+
* whether persisting is worth a SQLite commit. */
|
|
40449
|
+
volatileStateFields: ["lastFetchedAt"]
|
|
40251
40450
|
};
|
|
40252
40451
|
var EventFireSchema = zod.z.object({
|
|
40253
40452
|
deviceId: zod.z.number(),
|
|
@@ -40273,7 +40472,14 @@ var require_dist_DiScsb8j = __commonJS({
|
|
|
40273
40472
|
schema: EventEmitterStatusSchema,
|
|
40274
40473
|
kind: "push"
|
|
40275
40474
|
},
|
|
40276
|
-
runtimeState: EventEmitterStatusSchema
|
|
40475
|
+
runtimeState: EventEmitterStatusSchema,
|
|
40476
|
+
/**
|
|
40477
|
+
* Runtime-state durability: **session** — `eventCountSinceStart` names its own scope.
|
|
40478
|
+
*
|
|
40479
|
+
* See `RuntimeStateDurability`. Enforced by
|
|
40480
|
+
* `scripts/check-runtime-state-durability.ts`.
|
|
40481
|
+
*/
|
|
40482
|
+
durability: "session"
|
|
40277
40483
|
};
|
|
40278
40484
|
var EventItemSchema = zod.z.object({
|
|
40279
40485
|
id: zod.z.string(),
|
|
@@ -40572,7 +40778,14 @@ var require_dist_DiScsb8j = __commonJS({
|
|
|
40572
40778
|
* Runtime-state slice — mirrored by the kernel. UI fan speed
|
|
40573
40779
|
* sliders read `percentage` for live updates.
|
|
40574
40780
|
*/
|
|
40575
|
-
runtimeState: FanControlStatusSchema
|
|
40781
|
+
runtimeState: FanControlStatusSchema,
|
|
40782
|
+
/**
|
|
40783
|
+
* Runtime-state durability: **session** — as `brightness`.
|
|
40784
|
+
*
|
|
40785
|
+
* See `RuntimeStateDurability`. Enforced by
|
|
40786
|
+
* `scripts/check-runtime-state-durability.ts`.
|
|
40787
|
+
*/
|
|
40788
|
+
durability: "session"
|
|
40576
40789
|
};
|
|
40577
40790
|
var FeatureProbeStatusSchema = zod.z.object({
|
|
40578
40791
|
/**
|
|
@@ -40625,7 +40838,14 @@ var require_dist_DiScsb8j = __commonJS({
|
|
|
40625
40838
|
schema: FeatureProbeStatusSchema,
|
|
40626
40839
|
kind: "push"
|
|
40627
40840
|
},
|
|
40628
|
-
runtimeState: FeatureProbeStatusSchema
|
|
40841
|
+
runtimeState: FeatureProbeStatusSchema,
|
|
40842
|
+
/**
|
|
40843
|
+
* Runtime-state durability: **session** — per-session by definition — `lastProbedAt` means "this worker completed a probe THIS session", which is why the mirror seed already blanks it. Persisting it only creates something to blank.
|
|
40844
|
+
*
|
|
40845
|
+
* See `RuntimeStateDurability`. Enforced by
|
|
40846
|
+
* `scripts/check-runtime-state-durability.ts`.
|
|
40847
|
+
*/
|
|
40848
|
+
durability: "session"
|
|
40629
40849
|
};
|
|
40630
40850
|
var FloodStatusSchema = zod.z.object({
|
|
40631
40851
|
/** True when leak is currently detected. */
|
|
@@ -40644,7 +40864,17 @@ var require_dist_DiScsb8j = __commonJS({
|
|
|
40644
40864
|
schema: FloodStatusSchema,
|
|
40645
40865
|
kind: "push"
|
|
40646
40866
|
},
|
|
40647
|
-
runtimeState: FloodStatusSchema
|
|
40867
|
+
runtimeState: FloodStatusSchema,
|
|
40868
|
+
/**
|
|
40869
|
+
* Runtime-state durability: **restored** — as `smoke`.
|
|
40870
|
+
*
|
|
40871
|
+
* See `RuntimeStateDurability`. Enforced by
|
|
40872
|
+
* `scripts/check-runtime-state-durability.ts`.
|
|
40873
|
+
*/
|
|
40874
|
+
durability: "restored",
|
|
40875
|
+
/** Clock fields: written, but excluded from the compare that decides
|
|
40876
|
+
* whether persisting is worth a SQLite commit. */
|
|
40877
|
+
volatileStateFields: ["lastChangedAt"]
|
|
40648
40878
|
};
|
|
40649
40879
|
var GasStatusSchema = zod.z.object({
|
|
40650
40880
|
detected: zod.z.boolean(),
|
|
@@ -40662,7 +40892,17 @@ var require_dist_DiScsb8j = __commonJS({
|
|
|
40662
40892
|
schema: GasStatusSchema,
|
|
40663
40893
|
kind: "push"
|
|
40664
40894
|
},
|
|
40665
|
-
runtimeState: GasStatusSchema
|
|
40895
|
+
runtimeState: GasStatusSchema,
|
|
40896
|
+
/**
|
|
40897
|
+
* Runtime-state durability: **restored** — as `smoke`.
|
|
40898
|
+
*
|
|
40899
|
+
* See `RuntimeStateDurability`. Enforced by
|
|
40900
|
+
* `scripts/check-runtime-state-durability.ts`.
|
|
40901
|
+
*/
|
|
40902
|
+
durability: "restored",
|
|
40903
|
+
/** Clock fields: written, but excluded from the compare that decides
|
|
40904
|
+
* whether persisting is worth a SQLite commit. */
|
|
40905
|
+
volatileStateFields: ["lastChangedAt"]
|
|
40666
40906
|
};
|
|
40667
40907
|
var HumidifierStatusSchema = zod.z.object({
|
|
40668
40908
|
/** Whether the humidifier is currently on. */
|
|
@@ -40723,7 +40963,14 @@ var require_dist_DiScsb8j = __commonJS({
|
|
|
40723
40963
|
* Runtime-state slice — mirrored by the kernel. UI controls watch the
|
|
40724
40964
|
* slice for live humidity / mode changes.
|
|
40725
40965
|
*/
|
|
40726
|
-
runtimeState: HumidifierStatusSchema
|
|
40966
|
+
runtimeState: HumidifierStatusSchema,
|
|
40967
|
+
/**
|
|
40968
|
+
* Runtime-state durability: **session** — as `climate-control`.
|
|
40969
|
+
*
|
|
40970
|
+
* See `RuntimeStateDurability`. Enforced by
|
|
40971
|
+
* `scripts/check-runtime-state-durability.ts`.
|
|
40972
|
+
*/
|
|
40973
|
+
durability: "session"
|
|
40727
40974
|
};
|
|
40728
40975
|
var HumiditySensorStatusSchema = zod.z.object({
|
|
40729
40976
|
/** Current relative humidity, 0..100. */
|
|
@@ -40751,7 +40998,17 @@ var require_dist_DiScsb8j = __commonJS({
|
|
|
40751
40998
|
schema: HumiditySensorStatusSchema,
|
|
40752
40999
|
kind: "push"
|
|
40753
41000
|
},
|
|
40754
|
-
runtimeState: HumiditySensorStatusSchema
|
|
41001
|
+
runtimeState: HumiditySensorStatusSchema,
|
|
41002
|
+
/**
|
|
41003
|
+
* Runtime-state durability: **restored** — as `numeric-sensor` (67 of 75 writes were the clock alone).
|
|
41004
|
+
*
|
|
41005
|
+
* See `RuntimeStateDurability`. Enforced by
|
|
41006
|
+
* `scripts/check-runtime-state-durability.ts`.
|
|
41007
|
+
*/
|
|
41008
|
+
durability: "restored",
|
|
41009
|
+
/** Clock fields: written, but excluded from the compare that decides
|
|
41010
|
+
* whether persisting is worth a SQLite commit. */
|
|
41011
|
+
volatileStateFields: ["lastFetchedAt"]
|
|
40755
41012
|
};
|
|
40756
41013
|
var ImageStatusSchema = zod.z.object({
|
|
40757
41014
|
/** Absolute signed URL the browser loads directly. Null when the
|
|
@@ -40775,7 +41032,14 @@ var require_dist_DiScsb8j = __commonJS({
|
|
|
40775
41032
|
* Runtime-state slice — mirrored by the kernel. The UI reads `url`
|
|
40776
41033
|
* directly and renders the still image.
|
|
40777
41034
|
*/
|
|
40778
|
-
runtimeState: ImageStatusSchema
|
|
41035
|
+
runtimeState: ImageStatusSchema,
|
|
41036
|
+
/**
|
|
41037
|
+
* Runtime-state durability: **session** — a snapshot URL is a session-scoped handle; a restored one points at nothing.
|
|
41038
|
+
*
|
|
41039
|
+
* See `RuntimeStateDurability`. Enforced by
|
|
41040
|
+
* `scripts/check-runtime-state-durability.ts`.
|
|
41041
|
+
*/
|
|
41042
|
+
durability: "session"
|
|
40779
41043
|
};
|
|
40780
41044
|
var ImageRotateSchema = zod.z.enum([
|
|
40781
41045
|
"0",
|
|
@@ -40876,7 +41140,17 @@ var require_dist_DiScsb8j = __commonJS({
|
|
|
40876
41140
|
schema: ImageSettingsStatusSchema,
|
|
40877
41141
|
kind: "poll"
|
|
40878
41142
|
},
|
|
40879
|
-
runtimeState: ImageSettingsStatusSchema
|
|
41143
|
+
runtimeState: ImageSettingsStatusSchema,
|
|
41144
|
+
/**
|
|
41145
|
+
* Runtime-state durability: **restored** — operator-set camera imaging; mutation-driven.
|
|
41146
|
+
*
|
|
41147
|
+
* See `RuntimeStateDurability`. Enforced by
|
|
41148
|
+
* `scripts/check-runtime-state-durability.ts`.
|
|
41149
|
+
*/
|
|
41150
|
+
durability: "restored",
|
|
41151
|
+
/** Clock fields: written, but excluded from the compare that decides
|
|
41152
|
+
* whether persisting is worth a SQLite commit. */
|
|
41153
|
+
volatileStateFields: ["lastFetchedAt"]
|
|
40880
41154
|
};
|
|
40881
41155
|
var IntegrationWithStateSchema = zod.z.object({
|
|
40882
41156
|
id: zod.z.string(),
|
|
@@ -41207,7 +41481,14 @@ var require_dist_DiScsb8j = __commonJS({
|
|
|
41207
41481
|
* Runtime-state slice — mirrored by the kernel. UI controls watch the
|
|
41208
41482
|
* slice for live activity + battery changes.
|
|
41209
41483
|
*/
|
|
41210
|
-
runtimeState: LawnMowerControlStatusSchema
|
|
41484
|
+
runtimeState: LawnMowerControlStatusSchema,
|
|
41485
|
+
/**
|
|
41486
|
+
* Runtime-state durability: **session** — as `vacuum-control`.
|
|
41487
|
+
*
|
|
41488
|
+
* See `RuntimeStateDurability`. Enforced by
|
|
41489
|
+
* `scripts/check-runtime-state-durability.ts`.
|
|
41490
|
+
*/
|
|
41491
|
+
durability: "session"
|
|
41211
41492
|
};
|
|
41212
41493
|
var InterfaceKindEnum = zod.z.enum([
|
|
41213
41494
|
"lan",
|
|
@@ -41456,7 +41737,17 @@ var require_dist_DiScsb8j = __commonJS({
|
|
|
41456
41737
|
* read `state` and disable themselves during `locking`/`unlocking`
|
|
41457
41738
|
* transitions.
|
|
41458
41739
|
*/
|
|
41459
|
-
runtimeState: LockControlStatusSchema
|
|
41740
|
+
runtimeState: LockControlStatusSchema,
|
|
41741
|
+
/**
|
|
41742
|
+
* Runtime-state durability: **restored** — a lock left locked must still read locked.
|
|
41743
|
+
*
|
|
41744
|
+
* See `RuntimeStateDurability`. Enforced by
|
|
41745
|
+
* `scripts/check-runtime-state-durability.ts`.
|
|
41746
|
+
*/
|
|
41747
|
+
durability: "restored",
|
|
41748
|
+
/** Clock fields: written, but excluded from the compare that decides
|
|
41749
|
+
* whether persisting is worth a SQLite commit. */
|
|
41750
|
+
volatileStateFields: ["lastChangedAt"]
|
|
41460
41751
|
};
|
|
41461
41752
|
var MediaPlayerStateSchema = zod.z.enum([
|
|
41462
41753
|
"off",
|
|
@@ -41606,7 +41897,14 @@ var require_dist_DiScsb8j = __commonJS({
|
|
|
41606
41897
|
* full slice for live now-playing, volume, and progress updates
|
|
41607
41898
|
* without polling.
|
|
41608
41899
|
*/
|
|
41609
|
-
runtimeState: MediaPlayerStatusSchema
|
|
41900
|
+
runtimeState: MediaPlayerStatusSchema,
|
|
41901
|
+
/**
|
|
41902
|
+
* Runtime-state durability: **session** — a restored transport position describes a playback that stopped when the hub did.
|
|
41903
|
+
*
|
|
41904
|
+
* See `RuntimeStateDurability`. Enforced by
|
|
41905
|
+
* `scripts/check-runtime-state-durability.ts`.
|
|
41906
|
+
*/
|
|
41907
|
+
durability: "session"
|
|
41610
41908
|
};
|
|
41611
41909
|
var MeshEndpointSchema = zod.z.object({
|
|
41612
41910
|
/** Stable identifier within the provider (e.g. `mesh-ipv4`, `magicdns`, `funnel`). */
|
|
@@ -41890,7 +42188,14 @@ var require_dist_DiScsb8j = __commonJS({
|
|
|
41890
42188
|
* `device.state.motion.value`. Reads never invoke the provider, so
|
|
41891
42189
|
* UIs and other addons can poll the cached state safely.
|
|
41892
42190
|
*/
|
|
41893
|
-
runtimeState: MotionStatusSchema
|
|
42191
|
+
runtimeState: MotionStatusSchema,
|
|
42192
|
+
/**
|
|
42193
|
+
* Runtime-state durability: **session** — self-clearing by construction (`autoClearAfterMs`); a restored `detected: true` is a frozen event, and the next frame re-publishes the real one.
|
|
42194
|
+
*
|
|
42195
|
+
* See `RuntimeStateDurability`. Enforced by
|
|
42196
|
+
* `scripts/check-runtime-state-durability.ts`.
|
|
42197
|
+
*/
|
|
42198
|
+
durability: "session"
|
|
41894
42199
|
};
|
|
41895
42200
|
var MotionTriggerStatusSchema = zod.z.object({
|
|
41896
42201
|
enabled: zod.z.boolean(),
|
|
@@ -41927,7 +42232,14 @@ var require_dist_DiScsb8j = __commonJS({
|
|
|
41927
42232
|
schema: MotionTriggerStatusSchema,
|
|
41928
42233
|
kind: "command-driven"
|
|
41929
42234
|
},
|
|
41930
|
-
runtimeState: MotionTriggerRuntimeStateSchema
|
|
42235
|
+
runtimeState: MotionTriggerRuntimeStateSchema,
|
|
42236
|
+
/**
|
|
42237
|
+
* Runtime-state durability: **session** — the authority for motion-trigger enablement is the provider's own config; the slice is a mirror of it, re-published on connect.
|
|
42238
|
+
*
|
|
42239
|
+
* See `RuntimeStateDurability`. Enforced by
|
|
42240
|
+
* `scripts/check-runtime-state-durability.ts`.
|
|
42241
|
+
*/
|
|
42242
|
+
durability: "session"
|
|
41931
42243
|
};
|
|
41932
42244
|
var MotionZoneRegionSchema = zod.z.object({
|
|
41933
42245
|
id: zod.z.number(),
|
|
@@ -41982,7 +42294,17 @@ var require_dist_DiScsb8j = __commonJS({
|
|
|
41982
42294
|
schema: MotionZoneStatusSchema,
|
|
41983
42295
|
kind: "poll"
|
|
41984
42296
|
},
|
|
41985
|
-
runtimeState: MotionZoneStatusSchema
|
|
42297
|
+
runtimeState: MotionZoneStatusSchema,
|
|
42298
|
+
/**
|
|
42299
|
+
* Runtime-state durability: **restored** — the 14 KB polygon list is the single largest slice on the fleet and has not changed since the operator drew it. Highest value per byte in the table.
|
|
42300
|
+
*
|
|
42301
|
+
* See `RuntimeStateDurability`. Enforced by
|
|
42302
|
+
* `scripts/check-runtime-state-durability.ts`.
|
|
42303
|
+
*/
|
|
42304
|
+
durability: "restored",
|
|
42305
|
+
/** Clock fields: written, but excluded from the compare that decides
|
|
42306
|
+
* whether persisting is worth a SQLite commit. */
|
|
42307
|
+
volatileStateFields: ["lastFetchedAt"]
|
|
41986
42308
|
};
|
|
41987
42309
|
var NativeObjectClassEnum = zod.z.enum([
|
|
41988
42310
|
"person",
|
|
@@ -42045,7 +42367,17 @@ var require_dist_DiScsb8j = __commonJS({
|
|
|
42045
42367
|
schema: NativeObjectDetectionStatusSchema,
|
|
42046
42368
|
kind: "push"
|
|
42047
42369
|
},
|
|
42048
|
-
runtimeState: NativeObjectDetectionRuntimeStateSchema
|
|
42370
|
+
runtimeState: NativeObjectDetectionRuntimeStateSchema,
|
|
42371
|
+
/**
|
|
42372
|
+
* Runtime-state durability: **restored** — `enabled` is an operator toggle on a camera whose refresh is a no-op and whose staleMs is Infinity. There is no hardware value to re-read — losing it loses the setting.
|
|
42373
|
+
*
|
|
42374
|
+
* See `RuntimeStateDurability`. Enforced by
|
|
42375
|
+
* `scripts/check-runtime-state-durability.ts`.
|
|
42376
|
+
*/
|
|
42377
|
+
durability: "restored",
|
|
42378
|
+
/** Clock fields: written, but excluded from the compare that decides
|
|
42379
|
+
* whether persisting is worth a SQLite commit. */
|
|
42380
|
+
volatileStateFields: ["lastFetchedAt"]
|
|
42049
42381
|
};
|
|
42050
42382
|
var StreamNetworkStatsSchema = zod.z.object({
|
|
42051
42383
|
nominalBitrateKbps: zod.z.number(),
|
|
@@ -42368,7 +42700,14 @@ var require_dist_DiScsb8j = __commonJS({
|
|
|
42368
42700
|
* form reads `supports` to gate optional fields; history pane reads
|
|
42369
42701
|
* `lastSentAt` / `lastError` / `queueDepth`.
|
|
42370
42702
|
*/
|
|
42371
|
-
runtimeState: NotifierStatusSchema
|
|
42703
|
+
runtimeState: NotifierStatusSchema,
|
|
42704
|
+
/**
|
|
42705
|
+
* Runtime-state durability: **session** — live queue depth and last-send state; a restored queue depth describes a queue that no longer exists.
|
|
42706
|
+
*
|
|
42707
|
+
* See `RuntimeStateDurability`. Enforced by
|
|
42708
|
+
* `scripts/check-runtime-state-durability.ts`.
|
|
42709
|
+
*/
|
|
42710
|
+
durability: "session"
|
|
42372
42711
|
};
|
|
42373
42712
|
var NumericSensorStatusSchema = zod.z.object({
|
|
42374
42713
|
value: zod.z.number(),
|
|
@@ -42394,7 +42733,17 @@ var require_dist_DiScsb8j = __commonJS({
|
|
|
42394
42733
|
schema: NumericSensorStatusSchema,
|
|
42395
42734
|
kind: "push"
|
|
42396
42735
|
},
|
|
42397
|
-
runtimeState: NumericSensorStatusSchema
|
|
42736
|
+
runtimeState: NumericSensorStatusSchema,
|
|
42737
|
+
/**
|
|
42738
|
+
* Runtime-state durability: **restored** — polled value, low churn once the clock is excluded (251 of 669 writes were the clock alone); restoring it removes the cold window before the first poll.
|
|
42739
|
+
*
|
|
42740
|
+
* See `RuntimeStateDurability`. Enforced by
|
|
42741
|
+
* `scripts/check-runtime-state-durability.ts`.
|
|
42742
|
+
*/
|
|
42743
|
+
durability: "restored",
|
|
42744
|
+
/** Clock fields: written, but excluded from the compare that decides
|
|
42745
|
+
* whether persisting is worth a SQLite commit. */
|
|
42746
|
+
volatileStateFields: ["lastFetchedAt"]
|
|
42398
42747
|
};
|
|
42399
42748
|
var OsdOverlayKindEnum = zod.z.enum([
|
|
42400
42749
|
"text",
|
|
@@ -42817,7 +43166,14 @@ var require_dist_DiScsb8j = __commonJS({
|
|
|
42817
43166
|
* the full slice via `device.state.petFeeder.value` and refresh on
|
|
42818
43167
|
* every poll without re-querying the provider.
|
|
42819
43168
|
*/
|
|
42820
|
-
runtimeState: PetFeederStatusSchema
|
|
43169
|
+
runtimeState: PetFeederStatusSchema,
|
|
43170
|
+
/**
|
|
43171
|
+
* Runtime-state durability: **session** — live appliance state re-published on connect.
|
|
43172
|
+
*
|
|
43173
|
+
* See `RuntimeStateDurability`. Enforced by
|
|
43174
|
+
* `scripts/check-runtime-state-durability.ts`.
|
|
43175
|
+
*/
|
|
43176
|
+
durability: "session"
|
|
42821
43177
|
};
|
|
42822
43178
|
var VehicleSchema = zod.z.object({
|
|
42823
43179
|
id: zod.z.string(),
|
|
@@ -43151,7 +43507,17 @@ var require_dist_DiScsb8j = __commonJS({
|
|
|
43151
43507
|
schema: PowerMeterStatusSchema,
|
|
43152
43508
|
kind: "push"
|
|
43153
43509
|
},
|
|
43154
|
-
runtimeState: PowerMeterStatusSchema
|
|
43510
|
+
runtimeState: PowerMeterStatusSchema,
|
|
43511
|
+
/**
|
|
43512
|
+
* Runtime-state durability: **restored** — as `numeric-sensor`; `kwhTotal` is an accumulator whose restored value is the baseline.
|
|
43513
|
+
*
|
|
43514
|
+
* See `RuntimeStateDurability`. Enforced by
|
|
43515
|
+
* `scripts/check-runtime-state-durability.ts`.
|
|
43516
|
+
*/
|
|
43517
|
+
durability: "restored",
|
|
43518
|
+
/** Clock fields: written, but excluded from the compare that decides
|
|
43519
|
+
* whether persisting is worth a SQLite commit. */
|
|
43520
|
+
volatileStateFields: ["lastFetchedAt"]
|
|
43155
43521
|
};
|
|
43156
43522
|
var GpsLocationSchema = zod.z.object({
|
|
43157
43523
|
/** Latitude in decimal degrees, -90..90. */
|
|
@@ -43192,7 +43558,17 @@ var require_dist_DiScsb8j = __commonJS({
|
|
|
43192
43558
|
* the map pin is rendered (use `DeviceFeature.PresenceGps` for the
|
|
43193
43559
|
* pre-fetch fast-path check).
|
|
43194
43560
|
*/
|
|
43195
|
-
runtimeState: PresenceStatusSchema
|
|
43561
|
+
runtimeState: PresenceStatusSchema,
|
|
43562
|
+
/**
|
|
43563
|
+
* Runtime-state durability: **restored** — occupancy-relevant: the restored state is what an occupancy rule compares the first post-restart observation against.
|
|
43564
|
+
*
|
|
43565
|
+
* See `RuntimeStateDurability`. Enforced by
|
|
43566
|
+
* `scripts/check-runtime-state-durability.ts`.
|
|
43567
|
+
*/
|
|
43568
|
+
durability: "restored",
|
|
43569
|
+
/** Clock fields: written, but excluded from the compare that decides
|
|
43570
|
+
* whether persisting is worth a SQLite commit. */
|
|
43571
|
+
volatileStateFields: ["lastChangedAt"]
|
|
43196
43572
|
};
|
|
43197
43573
|
var PressureSensorStatusSchema = zod.z.object({
|
|
43198
43574
|
/** Current pressure in hPa. */
|
|
@@ -43220,7 +43596,17 @@ var require_dist_DiScsb8j = __commonJS({
|
|
|
43220
43596
|
schema: PressureSensorStatusSchema,
|
|
43221
43597
|
kind: "push"
|
|
43222
43598
|
},
|
|
43223
|
-
runtimeState: PressureSensorStatusSchema
|
|
43599
|
+
runtimeState: PressureSensorStatusSchema,
|
|
43600
|
+
/**
|
|
43601
|
+
* Runtime-state durability: **restored** — as `numeric-sensor`.
|
|
43602
|
+
*
|
|
43603
|
+
* See `RuntimeStateDurability`. Enforced by
|
|
43604
|
+
* `scripts/check-runtime-state-durability.ts`.
|
|
43605
|
+
*/
|
|
43606
|
+
durability: "restored",
|
|
43607
|
+
/** Clock fields: written, but excluded from the compare that decides
|
|
43608
|
+
* whether persisting is worth a SQLite commit. */
|
|
43609
|
+
volatileStateFields: ["lastFetchedAt"]
|
|
43224
43610
|
};
|
|
43225
43611
|
var PrivacyMaskShapeSchema = zod.z.discriminatedUnion("kind", [MaskRectShapeSchema, MaskPolygonShapeSchema]);
|
|
43226
43612
|
var PrivacyMaskRegionSchema = zod.z.object({
|
|
@@ -43319,7 +43705,17 @@ var require_dist_DiScsb8j = __commonJS({
|
|
|
43319
43705
|
schema: PrivacyMaskStatusSchema,
|
|
43320
43706
|
kind: "poll"
|
|
43321
43707
|
},
|
|
43322
|
-
runtimeState: PrivacyMaskStatusSchema
|
|
43708
|
+
runtimeState: PrivacyMaskStatusSchema,
|
|
43709
|
+
/**
|
|
43710
|
+
* Runtime-state durability: **restored** — operator-drawn regions, zero real churn — 22 writes in 25 minutes, every one of them the clock.
|
|
43711
|
+
*
|
|
43712
|
+
* See `RuntimeStateDurability`. Enforced by
|
|
43713
|
+
* `scripts/check-runtime-state-durability.ts`.
|
|
43714
|
+
*/
|
|
43715
|
+
durability: "restored",
|
|
43716
|
+
/** Clock fields: written, but excluded from the compare that decides
|
|
43717
|
+
* whether persisting is worth a SQLite commit. */
|
|
43718
|
+
volatileStateFields: ["lastFetchedAt"]
|
|
43323
43719
|
};
|
|
43324
43720
|
var PtzPresetSchema = zod.z.object({
|
|
43325
43721
|
id: zod.z.string(),
|
|
@@ -43505,7 +43901,14 @@ var require_dist_DiScsb8j = __commonJS({
|
|
|
43505
43901
|
* fetch / cache / fallback logic out of the four cap methods —
|
|
43506
43902
|
* they become trampolines over `runtimeState`.
|
|
43507
43903
|
*/
|
|
43508
|
-
runtimeState: PtzAutotrackRuntimeStateSchema
|
|
43904
|
+
runtimeState: PtzAutotrackRuntimeStateSchema,
|
|
43905
|
+
/**
|
|
43906
|
+
* Runtime-state durability: **session** — mirrors the camera's own autotrack config, re-read on connect.
|
|
43907
|
+
*
|
|
43908
|
+
* See `RuntimeStateDurability`. Enforced by
|
|
43909
|
+
* `scripts/check-runtime-state-durability.ts`.
|
|
43910
|
+
*/
|
|
43911
|
+
durability: "session"
|
|
43509
43912
|
};
|
|
43510
43913
|
var rebootCapability = {
|
|
43511
43914
|
name: "reboot",
|
|
@@ -44173,7 +44576,14 @@ var require_dist_DiScsb8j = __commonJS({
|
|
|
44173
44576
|
schema: SceneMonitorStatusSchema,
|
|
44174
44577
|
kind: "push"
|
|
44175
44578
|
},
|
|
44176
|
-
runtimeState: SceneMonitorStatusSchema
|
|
44579
|
+
runtimeState: SceneMonitorStatusSchema,
|
|
44580
|
+
/**
|
|
44581
|
+
* Runtime-state durability: **session** — re-derived from the current scene on the next evaluation.
|
|
44582
|
+
*
|
|
44583
|
+
* See `RuntimeStateDurability`. Enforced by
|
|
44584
|
+
* `scripts/check-runtime-state-durability.ts`.
|
|
44585
|
+
*/
|
|
44586
|
+
durability: "session"
|
|
44177
44587
|
};
|
|
44178
44588
|
var ZoneRuleModeEnum = zod.z.enum(["include", "exclude"]);
|
|
44179
44589
|
var ZoneRuleSchema = zod.z.object({
|
|
@@ -44275,7 +44685,14 @@ var require_dist_DiScsb8j = __commonJS({
|
|
|
44275
44685
|
* `isRunning` to render a spinner during execution and surfaces
|
|
44276
44686
|
* `lastError` / `lastRunSuccess` in the recent-runs panel.
|
|
44277
44687
|
*/
|
|
44278
|
-
runtimeState: ScriptRunnerStatusSchema
|
|
44688
|
+
runtimeState: ScriptRunnerStatusSchema,
|
|
44689
|
+
/**
|
|
44690
|
+
* Runtime-state durability: **session** — a restored `isRunning: true` describes a process that died with the previous hub.
|
|
44691
|
+
*
|
|
44692
|
+
* See `RuntimeStateDurability`. Enforced by
|
|
44693
|
+
* `scripts/check-runtime-state-durability.ts`.
|
|
44694
|
+
*/
|
|
44695
|
+
durability: "session"
|
|
44279
44696
|
};
|
|
44280
44697
|
var SmokeStatusSchema = zod.z.object({
|
|
44281
44698
|
detected: zod.z.boolean(),
|
|
@@ -44293,7 +44710,17 @@ var require_dist_DiScsb8j = __commonJS({
|
|
|
44293
44710
|
schema: SmokeStatusSchema,
|
|
44294
44711
|
kind: "push"
|
|
44295
44712
|
},
|
|
44296
|
-
runtimeState: SmokeStatusSchema
|
|
44713
|
+
runtimeState: SmokeStatusSchema,
|
|
44714
|
+
/**
|
|
44715
|
+
* Runtime-state durability: **restored** — a safety sensor must not read "clear" merely because the hub restarted.
|
|
44716
|
+
*
|
|
44717
|
+
* See `RuntimeStateDurability`. Enforced by
|
|
44718
|
+
* `scripts/check-runtime-state-durability.ts`.
|
|
44719
|
+
*/
|
|
44720
|
+
durability: "restored",
|
|
44721
|
+
/** Clock fields: written, but excluded from the compare that decides
|
|
44722
|
+
* whether persisting is worth a SQLite commit. */
|
|
44723
|
+
volatileStateFields: ["lastChangedAt"]
|
|
44297
44724
|
};
|
|
44298
44725
|
var CamStreamDescriptorSchema = zod.z.object({
|
|
44299
44726
|
camStreamId: zod.z.string().min(1),
|
|
@@ -44444,7 +44871,17 @@ var require_dist_DiScsb8j = __commonJS({
|
|
|
44444
44871
|
schema: StreamParamsStatusSchema,
|
|
44445
44872
|
kind: "poll"
|
|
44446
44873
|
},
|
|
44447
|
-
runtimeState: StreamParamsStatusSchema
|
|
44874
|
+
runtimeState: StreamParamsStatusSchema,
|
|
44875
|
+
/**
|
|
44876
|
+
* Runtime-state durability: **restored** — operator-set encoder profile; mutation-driven.
|
|
44877
|
+
*
|
|
44878
|
+
* See `RuntimeStateDurability`. Enforced by
|
|
44879
|
+
* `scripts/check-runtime-state-durability.ts`.
|
|
44880
|
+
*/
|
|
44881
|
+
durability: "restored",
|
|
44882
|
+
/** Clock fields: written, but excluded from the compare that decides
|
|
44883
|
+
* whether persisting is worth a SQLite commit. */
|
|
44884
|
+
volatileStateFields: ["lastFetchedAt"]
|
|
44448
44885
|
};
|
|
44449
44886
|
var STREAM_PROFILE_META = [
|
|
44450
44887
|
{
|
|
@@ -44715,6 +45152,16 @@ var require_dist_DiScsb8j = __commonJS({
|
|
|
44715
45152
|
* not need to re-query the provider after a setState mutation.
|
|
44716
45153
|
*/
|
|
44717
45154
|
runtimeState: SwitchStatusSchema,
|
|
45155
|
+
/**
|
|
45156
|
+
* Runtime-state durability: **restored** — device state an operator reads as authoritative; 55 devices, transition-driven.
|
|
45157
|
+
*
|
|
45158
|
+
* See `RuntimeStateDurability`. Enforced by
|
|
45159
|
+
* `scripts/check-runtime-state-durability.ts`.
|
|
45160
|
+
*/
|
|
45161
|
+
durability: "restored",
|
|
45162
|
+
/** Clock fields: written, but excluded from the compare that decides
|
|
45163
|
+
* whether persisting is worth a SQLite commit. */
|
|
45164
|
+
volatileStateFields: ["lastChangedAt"],
|
|
44718
45165
|
settings: { bindings: [{
|
|
44719
45166
|
kind: "scalar",
|
|
44720
45167
|
statusPath: "on",
|
|
@@ -44787,7 +45234,17 @@ var require_dist_DiScsb8j = __commonJS({
|
|
|
44787
45234
|
schema: TamperStatusSchema,
|
|
44788
45235
|
kind: "push"
|
|
44789
45236
|
},
|
|
44790
|
-
runtimeState: TamperStatusSchema
|
|
45237
|
+
runtimeState: TamperStatusSchema,
|
|
45238
|
+
/**
|
|
45239
|
+
* Runtime-state durability: **restored** — as `smoke`.
|
|
45240
|
+
*
|
|
45241
|
+
* See `RuntimeStateDurability`. Enforced by
|
|
45242
|
+
* `scripts/check-runtime-state-durability.ts`.
|
|
45243
|
+
*/
|
|
45244
|
+
durability: "restored",
|
|
45245
|
+
/** Clock fields: written, but excluded from the compare that decides
|
|
45246
|
+
* whether persisting is worth a SQLite commit. */
|
|
45247
|
+
volatileStateFields: ["lastChangedAt"]
|
|
44791
45248
|
};
|
|
44792
45249
|
var TemperatureSensorStatusSchema = zod.z.object({
|
|
44793
45250
|
/** Current temperature in Celsius. */
|
|
@@ -44816,7 +45273,17 @@ var require_dist_DiScsb8j = __commonJS({
|
|
|
44816
45273
|
schema: TemperatureSensorStatusSchema,
|
|
44817
45274
|
kind: "push"
|
|
44818
45275
|
},
|
|
44819
|
-
runtimeState: TemperatureSensorStatusSchema
|
|
45276
|
+
runtimeState: TemperatureSensorStatusSchema,
|
|
45277
|
+
/**
|
|
45278
|
+
* Runtime-state durability: **restored** — as `numeric-sensor` (69 of 125 writes were the clock alone).
|
|
45279
|
+
*
|
|
45280
|
+
* See `RuntimeStateDurability`. Enforced by
|
|
45281
|
+
* `scripts/check-runtime-state-durability.ts`.
|
|
45282
|
+
*/
|
|
45283
|
+
durability: "restored",
|
|
45284
|
+
/** Clock fields: written, but excluded from the compare that decides
|
|
45285
|
+
* whether persisting is worth a SQLite commit. */
|
|
45286
|
+
volatileStateFields: ["lastFetchedAt"]
|
|
44820
45287
|
};
|
|
44821
45288
|
var ToastSchema = zod.z.object({
|
|
44822
45289
|
title: zod.z.string(),
|
|
@@ -44867,7 +45334,14 @@ var require_dist_DiScsb8j = __commonJS({
|
|
|
44867
45334
|
schema: UpdateStatusSchema,
|
|
44868
45335
|
kind: "poll"
|
|
44869
45336
|
},
|
|
44870
|
-
runtimeState: UpdateStatusSchema
|
|
45337
|
+
runtimeState: UpdateStatusSchema,
|
|
45338
|
+
/**
|
|
45339
|
+
* Runtime-state durability: **session** — a restored `inProgress: true` describes an update that is no longer running; versions are re-probed at boot.
|
|
45340
|
+
*
|
|
45341
|
+
* See `RuntimeStateDurability`. Enforced by
|
|
45342
|
+
* `scripts/check-runtime-state-durability.ts`.
|
|
45343
|
+
*/
|
|
45344
|
+
durability: "session"
|
|
44871
45345
|
};
|
|
44872
45346
|
var UserSummarySchema = zod.z.object({
|
|
44873
45347
|
id: zod.z.string(),
|
|
@@ -45201,7 +45675,14 @@ var require_dist_DiScsb8j = __commonJS({
|
|
|
45201
45675
|
* Runtime-state slice — mirrored by the kernel. UI controls watch the
|
|
45202
45676
|
* slice for live state + battery + fan-speed changes.
|
|
45203
45677
|
*/
|
|
45204
|
-
runtimeState: VacuumControlStatusSchema
|
|
45678
|
+
runtimeState: VacuumControlStatusSchema,
|
|
45679
|
+
/**
|
|
45680
|
+
* Runtime-state durability: **session** — as `media-player` — a restored `state: cleaning` is a robot that is not cleaning.
|
|
45681
|
+
*
|
|
45682
|
+
* See `RuntimeStateDurability`. Enforced by
|
|
45683
|
+
* `scripts/check-runtime-state-durability.ts`.
|
|
45684
|
+
*/
|
|
45685
|
+
durability: "session"
|
|
45205
45686
|
};
|
|
45206
45687
|
var ValveStateSchema = zod.z.enum([
|
|
45207
45688
|
"open",
|
|
@@ -45254,7 +45735,14 @@ var require_dist_DiScsb8j = __commonJS({
|
|
|
45254
45735
|
* Runtime-state slice — mirrored by the kernel. UI controls watch the
|
|
45255
45736
|
* slice for live position changes during a move.
|
|
45256
45737
|
*/
|
|
45257
|
-
runtimeState: ValveStatusSchema
|
|
45738
|
+
runtimeState: ValveStatusSchema,
|
|
45739
|
+
/**
|
|
45740
|
+
* Runtime-state durability: **session** — as `brightness`.
|
|
45741
|
+
*
|
|
45742
|
+
* See `RuntimeStateDurability`. Enforced by
|
|
45743
|
+
* `scripts/check-runtime-state-durability.ts`.
|
|
45744
|
+
*/
|
|
45745
|
+
durability: "session"
|
|
45258
45746
|
};
|
|
45259
45747
|
var VibrationStatusSchema = zod.z.object({
|
|
45260
45748
|
detected: zod.z.boolean(),
|
|
@@ -45272,7 +45760,17 @@ var require_dist_DiScsb8j = __commonJS({
|
|
|
45272
45760
|
schema: VibrationStatusSchema,
|
|
45273
45761
|
kind: "push"
|
|
45274
45762
|
},
|
|
45275
|
-
runtimeState: VibrationStatusSchema
|
|
45763
|
+
runtimeState: VibrationStatusSchema,
|
|
45764
|
+
/**
|
|
45765
|
+
* Runtime-state durability: **restored** — as `smoke`.
|
|
45766
|
+
*
|
|
45767
|
+
* See `RuntimeStateDurability`. Enforced by
|
|
45768
|
+
* `scripts/check-runtime-state-durability.ts`.
|
|
45769
|
+
*/
|
|
45770
|
+
durability: "restored",
|
|
45771
|
+
/** Clock fields: written, but excluded from the compare that decides
|
|
45772
|
+
* whether persisting is worth a SQLite commit. */
|
|
45773
|
+
volatileStateFields: ["lastChangedAt"]
|
|
45276
45774
|
};
|
|
45277
45775
|
var WaterHeaterStatusSchema = zod.z.object({
|
|
45278
45776
|
/** Current measured temperature. Null when not reported. */
|
|
@@ -45332,7 +45830,14 @@ var require_dist_DiScsb8j = __commonJS({
|
|
|
45332
45830
|
* Runtime-state slice — mirrored by the kernel. UI controls watch the
|
|
45333
45831
|
* slice for live temperature / mode / away changes.
|
|
45334
45832
|
*/
|
|
45335
|
-
runtimeState: WaterHeaterStatusSchema
|
|
45833
|
+
runtimeState: WaterHeaterStatusSchema,
|
|
45834
|
+
/**
|
|
45835
|
+
* Runtime-state durability: **session** — as `climate-control`.
|
|
45836
|
+
*
|
|
45837
|
+
* See `RuntimeStateDurability`. Enforced by
|
|
45838
|
+
* `scripts/check-runtime-state-durability.ts`.
|
|
45839
|
+
*/
|
|
45840
|
+
durability: "session"
|
|
45336
45841
|
};
|
|
45337
45842
|
var WeatherStatusSchema = zod.z.object({
|
|
45338
45843
|
/** Verbatim HA condition state (`sunny`, `cloudy`, `rainy`, …). Null
|
|
@@ -45372,7 +45877,14 @@ var require_dist_DiScsb8j = __commonJS({
|
|
|
45372
45877
|
* Runtime-state slice — mirrored by the kernel. The UI reads the
|
|
45373
45878
|
* current conditions directly from the slice on each weather push.
|
|
45374
45879
|
*/
|
|
45375
|
-
runtimeState: WeatherStatusSchema
|
|
45880
|
+
runtimeState: WeatherStatusSchema,
|
|
45881
|
+
/**
|
|
45882
|
+
* Runtime-state durability: **session** — a forecast is stale the moment the hub is down; the provider re-fetches on connect.
|
|
45883
|
+
*
|
|
45884
|
+
* See `RuntimeStateDurability`. Enforced by
|
|
45885
|
+
* `scripts/check-runtime-state-durability.ts`.
|
|
45886
|
+
*/
|
|
45887
|
+
durability: "session"
|
|
45376
45888
|
};
|
|
45377
45889
|
var PerScopeBreakdownSchema = zod.z.object({
|
|
45378
45890
|
/** Total tracked objects in this scope (frame / zone / unzoned). */
|
|
@@ -45481,7 +45993,14 @@ var require_dist_DiScsb8j = __commonJS({
|
|
|
45481
45993
|
* automatically; the explicit `getCurrentSnapshot` cap method is
|
|
45482
45994
|
* still useful for one-off polls without a subscription.
|
|
45483
45995
|
*/
|
|
45484
|
-
runtimeState: CameraOccupancySnapshotSchema
|
|
45996
|
+
runtimeState: CameraOccupancySnapshotSchema,
|
|
45997
|
+
/**
|
|
45998
|
+
* Runtime-state durability: **session** — per-frame analytics; with `audio-metrics` it is ~90 % of the offered write rate. Re-derived on the next frame.
|
|
45999
|
+
*
|
|
46000
|
+
* See `RuntimeStateDurability`. Enforced by
|
|
46001
|
+
* `scripts/check-runtime-state-durability.ts`.
|
|
46002
|
+
*/
|
|
46003
|
+
durability: "session"
|
|
45485
46004
|
};
|
|
45486
46005
|
var ZoneRuleStageEnum = zod.z.enum([
|
|
45487
46006
|
"motion",
|
|
@@ -45533,7 +46052,14 @@ var require_dist_DiScsb8j = __commonJS({
|
|
|
45533
46052
|
motion: zod.z.array(ZoneRuleSchema).readonly(),
|
|
45534
46053
|
detection: zod.z.array(ZoneRuleSchema).readonly(),
|
|
45535
46054
|
package: zod.z.array(ZoneRuleSchema).readonly()
|
|
45536
|
-
})
|
|
46055
|
+
}),
|
|
46056
|
+
/**
|
|
46057
|
+
* Runtime-state durability: **restored** — operator intent, mutation-only, same argument as `zones`.
|
|
46058
|
+
*
|
|
46059
|
+
* See `RuntimeStateDurability`. Enforced by
|
|
46060
|
+
* `scripts/check-runtime-state-durability.ts`.
|
|
46061
|
+
*/
|
|
46062
|
+
durability: "restored"
|
|
45537
46063
|
};
|
|
45538
46064
|
var RUNTIME_DEFAULTS = {
|
|
45539
46065
|
"features.streaming": true,
|
|
@@ -51676,6 +52202,264 @@ var require_dist_DiScsb8j = __commonJS({
|
|
|
51676
52202
|
"network-access": "ingress",
|
|
51677
52203
|
"smtp-provider": "email"
|
|
51678
52204
|
});
|
|
52205
|
+
var RUNTIME_STATE_POLICY = {
|
|
52206
|
+
"air-quality-sensor": {
|
|
52207
|
+
durability: "restored",
|
|
52208
|
+
volatileFields: ["lastFetchedAt"]
|
|
52209
|
+
},
|
|
52210
|
+
"alarm-panel": {
|
|
52211
|
+
durability: "restored",
|
|
52212
|
+
volatileFields: ["lastChangedAt"]
|
|
52213
|
+
},
|
|
52214
|
+
"ambient-light-sensor": {
|
|
52215
|
+
durability: "restored",
|
|
52216
|
+
volatileFields: ["lastFetchedAt"]
|
|
52217
|
+
},
|
|
52218
|
+
"audio-metrics": {
|
|
52219
|
+
durability: "session",
|
|
52220
|
+
volatileFields: []
|
|
52221
|
+
},
|
|
52222
|
+
"automation-control": {
|
|
52223
|
+
durability: "session",
|
|
52224
|
+
volatileFields: []
|
|
52225
|
+
},
|
|
52226
|
+
"battery": {
|
|
52227
|
+
durability: "restored",
|
|
52228
|
+
volatileFields: ["lastUpdated"]
|
|
52229
|
+
},
|
|
52230
|
+
"binary": {
|
|
52231
|
+
durability: "restored",
|
|
52232
|
+
volatileFields: ["lastChangedAt"]
|
|
52233
|
+
},
|
|
52234
|
+
"brightness": {
|
|
52235
|
+
durability: "session",
|
|
52236
|
+
volatileFields: []
|
|
52237
|
+
},
|
|
52238
|
+
"camera-streams": {
|
|
52239
|
+
durability: "session",
|
|
52240
|
+
volatileFields: []
|
|
52241
|
+
},
|
|
52242
|
+
"carbon-monoxide": {
|
|
52243
|
+
durability: "restored",
|
|
52244
|
+
volatileFields: ["lastChangedAt"]
|
|
52245
|
+
},
|
|
52246
|
+
"climate-control": {
|
|
52247
|
+
durability: "session",
|
|
52248
|
+
volatileFields: []
|
|
52249
|
+
},
|
|
52250
|
+
"color": {
|
|
52251
|
+
durability: "session",
|
|
52252
|
+
volatileFields: []
|
|
52253
|
+
},
|
|
52254
|
+
"connectivity": {
|
|
52255
|
+
durability: "restored",
|
|
52256
|
+
volatileFields: ["lastChangedAt"]
|
|
52257
|
+
},
|
|
52258
|
+
"consumables": {
|
|
52259
|
+
durability: "session",
|
|
52260
|
+
volatileFields: []
|
|
52261
|
+
},
|
|
52262
|
+
"contact": {
|
|
52263
|
+
durability: "restored",
|
|
52264
|
+
volatileFields: ["lastChangedAt"]
|
|
52265
|
+
},
|
|
52266
|
+
"control": {
|
|
52267
|
+
durability: "session",
|
|
52268
|
+
volatileFields: []
|
|
52269
|
+
},
|
|
52270
|
+
"cover": {
|
|
52271
|
+
durability: "restored",
|
|
52272
|
+
volatileFields: ["lastChangedAt"]
|
|
52273
|
+
},
|
|
52274
|
+
"day-night": {
|
|
52275
|
+
durability: "restored",
|
|
52276
|
+
volatileFields: ["lastFetchedAt"]
|
|
52277
|
+
},
|
|
52278
|
+
"device-discovery": {
|
|
52279
|
+
durability: "session",
|
|
52280
|
+
volatileFields: []
|
|
52281
|
+
},
|
|
52282
|
+
"device-status": {
|
|
52283
|
+
durability: "restored",
|
|
52284
|
+
volatileFields: ["lastChangedAt"]
|
|
52285
|
+
},
|
|
52286
|
+
"doorbell": {
|
|
52287
|
+
durability: "restored",
|
|
52288
|
+
volatileFields: []
|
|
52289
|
+
},
|
|
52290
|
+
"enum-sensor": {
|
|
52291
|
+
durability: "restored",
|
|
52292
|
+
volatileFields: ["lastFetchedAt"]
|
|
52293
|
+
},
|
|
52294
|
+
"event-emitter": {
|
|
52295
|
+
durability: "session",
|
|
52296
|
+
volatileFields: []
|
|
52297
|
+
},
|
|
52298
|
+
"fan-control": {
|
|
52299
|
+
durability: "session",
|
|
52300
|
+
volatileFields: []
|
|
52301
|
+
},
|
|
52302
|
+
"feature-probe": {
|
|
52303
|
+
durability: "session",
|
|
52304
|
+
volatileFields: []
|
|
52305
|
+
},
|
|
52306
|
+
"flood": {
|
|
52307
|
+
durability: "restored",
|
|
52308
|
+
volatileFields: ["lastChangedAt"]
|
|
52309
|
+
},
|
|
52310
|
+
"gas": {
|
|
52311
|
+
durability: "restored",
|
|
52312
|
+
volatileFields: ["lastChangedAt"]
|
|
52313
|
+
},
|
|
52314
|
+
"humidifier": {
|
|
52315
|
+
durability: "session",
|
|
52316
|
+
volatileFields: []
|
|
52317
|
+
},
|
|
52318
|
+
"humidity-sensor": {
|
|
52319
|
+
durability: "restored",
|
|
52320
|
+
volatileFields: ["lastFetchedAt"]
|
|
52321
|
+
},
|
|
52322
|
+
"image": {
|
|
52323
|
+
durability: "session",
|
|
52324
|
+
volatileFields: []
|
|
52325
|
+
},
|
|
52326
|
+
"image-settings": {
|
|
52327
|
+
durability: "restored",
|
|
52328
|
+
volatileFields: ["lastFetchedAt"]
|
|
52329
|
+
},
|
|
52330
|
+
"lawn-mower-control": {
|
|
52331
|
+
durability: "session",
|
|
52332
|
+
volatileFields: []
|
|
52333
|
+
},
|
|
52334
|
+
"lock-control": {
|
|
52335
|
+
durability: "restored",
|
|
52336
|
+
volatileFields: ["lastChangedAt"]
|
|
52337
|
+
},
|
|
52338
|
+
"media-player": {
|
|
52339
|
+
durability: "session",
|
|
52340
|
+
volatileFields: []
|
|
52341
|
+
},
|
|
52342
|
+
"motion": {
|
|
52343
|
+
durability: "session",
|
|
52344
|
+
volatileFields: []
|
|
52345
|
+
},
|
|
52346
|
+
"motion-trigger": {
|
|
52347
|
+
durability: "session",
|
|
52348
|
+
volatileFields: []
|
|
52349
|
+
},
|
|
52350
|
+
"motion-zones": {
|
|
52351
|
+
durability: "restored",
|
|
52352
|
+
volatileFields: ["lastFetchedAt"]
|
|
52353
|
+
},
|
|
52354
|
+
"native-object-detection": {
|
|
52355
|
+
durability: "restored",
|
|
52356
|
+
volatileFields: ["lastFetchedAt"]
|
|
52357
|
+
},
|
|
52358
|
+
"notifier": {
|
|
52359
|
+
durability: "session",
|
|
52360
|
+
volatileFields: []
|
|
52361
|
+
},
|
|
52362
|
+
"numeric-sensor": {
|
|
52363
|
+
durability: "restored",
|
|
52364
|
+
volatileFields: ["lastFetchedAt"]
|
|
52365
|
+
},
|
|
52366
|
+
"pet-feeder": {
|
|
52367
|
+
durability: "session",
|
|
52368
|
+
volatileFields: []
|
|
52369
|
+
},
|
|
52370
|
+
"power-meter": {
|
|
52371
|
+
durability: "restored",
|
|
52372
|
+
volatileFields: ["lastFetchedAt"]
|
|
52373
|
+
},
|
|
52374
|
+
"presence": {
|
|
52375
|
+
durability: "restored",
|
|
52376
|
+
volatileFields: ["lastChangedAt"]
|
|
52377
|
+
},
|
|
52378
|
+
"pressure-sensor": {
|
|
52379
|
+
durability: "restored",
|
|
52380
|
+
volatileFields: ["lastFetchedAt"]
|
|
52381
|
+
},
|
|
52382
|
+
"privacy-mask": {
|
|
52383
|
+
durability: "restored",
|
|
52384
|
+
volatileFields: ["lastFetchedAt"]
|
|
52385
|
+
},
|
|
52386
|
+
"ptz-autotrack": {
|
|
52387
|
+
durability: "session",
|
|
52388
|
+
volatileFields: []
|
|
52389
|
+
},
|
|
52390
|
+
"scene-monitor": {
|
|
52391
|
+
durability: "session",
|
|
52392
|
+
volatileFields: []
|
|
52393
|
+
},
|
|
52394
|
+
"script-runner": {
|
|
52395
|
+
durability: "session",
|
|
52396
|
+
volatileFields: []
|
|
52397
|
+
},
|
|
52398
|
+
"smoke": {
|
|
52399
|
+
durability: "restored",
|
|
52400
|
+
volatileFields: ["lastChangedAt"]
|
|
52401
|
+
},
|
|
52402
|
+
"stream-params": {
|
|
52403
|
+
durability: "restored",
|
|
52404
|
+
volatileFields: ["lastFetchedAt"]
|
|
52405
|
+
},
|
|
52406
|
+
"switch": {
|
|
52407
|
+
durability: "restored",
|
|
52408
|
+
volatileFields: ["lastChangedAt"]
|
|
52409
|
+
},
|
|
52410
|
+
"tamper": {
|
|
52411
|
+
durability: "restored",
|
|
52412
|
+
volatileFields: ["lastChangedAt"]
|
|
52413
|
+
},
|
|
52414
|
+
"temperature-sensor": {
|
|
52415
|
+
durability: "restored",
|
|
52416
|
+
volatileFields: ["lastFetchedAt"]
|
|
52417
|
+
},
|
|
52418
|
+
"update": {
|
|
52419
|
+
durability: "session",
|
|
52420
|
+
volatileFields: []
|
|
52421
|
+
},
|
|
52422
|
+
"vacuum-control": {
|
|
52423
|
+
durability: "session",
|
|
52424
|
+
volatileFields: []
|
|
52425
|
+
},
|
|
52426
|
+
"valve": {
|
|
52427
|
+
durability: "session",
|
|
52428
|
+
volatileFields: []
|
|
52429
|
+
},
|
|
52430
|
+
"vibration": {
|
|
52431
|
+
durability: "restored",
|
|
52432
|
+
volatileFields: ["lastChangedAt"]
|
|
52433
|
+
},
|
|
52434
|
+
"water-heater": {
|
|
52435
|
+
durability: "session",
|
|
52436
|
+
volatileFields: []
|
|
52437
|
+
},
|
|
52438
|
+
"weather": {
|
|
52439
|
+
durability: "session",
|
|
52440
|
+
volatileFields: []
|
|
52441
|
+
},
|
|
52442
|
+
"zone-analytics": {
|
|
52443
|
+
durability: "session",
|
|
52444
|
+
volatileFields: []
|
|
52445
|
+
},
|
|
52446
|
+
"zone-rules": {
|
|
52447
|
+
durability: "restored",
|
|
52448
|
+
volatileFields: []
|
|
52449
|
+
},
|
|
52450
|
+
"zones": {
|
|
52451
|
+
durability: "restored",
|
|
52452
|
+
volatileFields: []
|
|
52453
|
+
}
|
|
52454
|
+
};
|
|
52455
|
+
function runtimeStatePolicyFor(capName) {
|
|
52456
|
+
return RUNTIME_STATE_POLICY[capName] ?? SESSION_ONLY_POLICY;
|
|
52457
|
+
}
|
|
52458
|
+
var SESSION_ONLY_POLICY = {
|
|
52459
|
+
durability: "session",
|
|
52460
|
+
volatileFields: []
|
|
52461
|
+
};
|
|
52462
|
+
new Map(AUDIO_MACRO_LABELS.flatMap((macro2) => macro2.icon === void 0 ? [] : [[macro2.id, macro2.icon]]));
|
|
51679
52463
|
var TimelapseTemplateSchema = zod.z.object({
|
|
51680
52464
|
title: zod.z.string().max(500).optional(),
|
|
51681
52465
|
body: zod.z.string().max(2e3).optional()
|
|
@@ -51812,25 +52596,32 @@ var require_dist_DiScsb8j = __commonJS({
|
|
|
51812
52596
|
var NativeLeaseAdmissionSchema = zod.z.enum(["all", "inferred"]);
|
|
51813
52597
|
zod.z.object({
|
|
51814
52598
|
/**
|
|
51815
|
-
* How
|
|
52599
|
+
* How many delivered frames the worker HOLDS at once, waiting for each one's
|
|
52600
|
+
* detection result.
|
|
52601
|
+
*
|
|
52602
|
+
* This replaced a TTL on 2026-08-13, and the replacement is the whole point:
|
|
52603
|
+
* a time window was never related to the event the pixels were waiting for.
|
|
52604
|
+
* A held frame now lives from delivery until the runner has its `FrameResult`
|
|
52605
|
+
* — at which moment the runner cuts the subject tiles it actually wanted and
|
|
52606
|
+
* releases the frame. The bound exists only so a runner that stops answering
|
|
52607
|
+
* cannot pin RAM: above it the OLDEST held frame is dropped and counted.
|
|
51816
52608
|
*
|
|
51817
|
-
*
|
|
51818
|
-
*
|
|
51819
|
-
*
|
|
51820
|
-
*
|
|
51821
|
-
*
|
|
52609
|
+
* Sizing: the steady state is `inferenceLatency × deliveredFps`, measured at
|
|
52610
|
+
* 40-160 ms × ≤25 fps = 1-4 frames. The default leaves headroom for a hiccup
|
|
52611
|
+
* without ever approaching the old resident set (43 frames × 24.9 MB at 4K).
|
|
52612
|
+
* Raising it does not buy hit rate — it buys tolerance for a slow runner, and
|
|
52613
|
+
* `holdOverflow` on the metrics line is what says you need it.
|
|
51822
52614
|
*/
|
|
51823
|
-
|
|
52615
|
+
holdFrames: zod.z.number().int().min(1).max(64),
|
|
51824
52616
|
/**
|
|
51825
52617
|
* Hard per-decode-worker RAM ceiling for retained native frames, in MB.
|
|
51826
52618
|
*
|
|
51827
|
-
*
|
|
51828
|
-
*
|
|
51829
|
-
*
|
|
51830
|
-
*
|
|
51831
|
-
*
|
|
51832
|
-
*
|
|
51833
|
-
* rather than giving RAM back — lower this knob if RAM is what you wanted.
|
|
52619
|
+
* Since 2026-08-13 this is a SAFETY ceiling and nothing else: `holdFrames`
|
|
52620
|
+
* is what decides how much is held, and the ceiling is the number above which
|
|
52621
|
+
* something is wrong. Before that it was the effective cap — at 1024 MB with
|
|
52622
|
+
* a 2 800 ms TTL a 4K camera sat pinned at `leaseMb:1020, leaseFrames:43`
|
|
52623
|
+
* with the TTL expiring nothing, which is exactly the confusion the hold
|
|
52624
|
+
* removes. `leaseMb` / `leaseFrames` still say what is resident.
|
|
51834
52625
|
* `0` DISABLES the lease entirely and falls the worker back to the tiny
|
|
51835
52626
|
* leak-prone GPU surface ring (~85% crop miss; that is what the lease exists
|
|
51836
52627
|
* to replace).
|
|
@@ -51856,17 +52647,36 @@ var require_dist_DiScsb8j = __commonJS({
|
|
|
51856
52647
|
* there is the signal that some caller names frames outside the inference set
|
|
51857
52648
|
* and that this must go back to `all`.
|
|
51858
52649
|
*/
|
|
51859
|
-
admission: NativeLeaseAdmissionSchema
|
|
52650
|
+
admission: NativeLeaseAdmissionSchema,
|
|
52651
|
+
/**
|
|
52652
|
+
* RAM ceiling per decode worker, in MB, for the SUBJECT TILES — the
|
|
52653
|
+
* compressed native crops the worker cuts at the moment a frame's detection
|
|
52654
|
+
* result arrives, and keeps long after the frame itself is freed.
|
|
52655
|
+
*
|
|
52656
|
+
* This is the knob that replaced the old retention window, and it buys about
|
|
52657
|
+
* three orders of magnitude more of it: a tile is one subject at native
|
|
52658
|
+
* resolution, JPEG-encoded (~60-120 KB on a 4K person), against ~24.9 MB for
|
|
52659
|
+
* the frame it was cut from. A frame on which nothing was detected costs
|
|
52660
|
+
* nothing at all, which is the real change — the old lease paid per FRAME and
|
|
52661
|
+
* was interrogated per SUBJECT.
|
|
52662
|
+
*
|
|
52663
|
+
* `0` DISABLES tiles, leaving only the hold window and the ≤640 RAM
|
|
52664
|
+
* fallback — i.e. the pre-2026-08-13 miss profile. Set it there only to
|
|
52665
|
+
* reproduce that.
|
|
52666
|
+
*/
|
|
52667
|
+
tileBudgetMb: zod.z.number().int().min(0).max(1024)
|
|
51860
52668
|
});
|
|
51861
52669
|
var DEFAULT_NATIVE_LEASE_SETTINGS = {
|
|
51862
|
-
|
|
52670
|
+
holdFrames: 8,
|
|
51863
52671
|
budgetMb: 1024,
|
|
51864
52672
|
activityMs: 15e3,
|
|
52673
|
+
tileBudgetMb: 64,
|
|
51865
52674
|
admission: "inferred"
|
|
51866
52675
|
};
|
|
51867
|
-
DEFAULT_NATIVE_LEASE_SETTINGS.
|
|
52676
|
+
DEFAULT_NATIVE_LEASE_SETTINGS.holdFrames;
|
|
51868
52677
|
DEFAULT_NATIVE_LEASE_SETTINGS.budgetMb;
|
|
51869
52678
|
DEFAULT_NATIVE_LEASE_SETTINGS.activityMs;
|
|
52679
|
+
DEFAULT_NATIVE_LEASE_SETTINGS.tileBudgetMb;
|
|
51870
52680
|
DEFAULT_NATIVE_LEASE_SETTINGS.admission;
|
|
51871
52681
|
var ADDON_ID_PREFIX = "addon:";
|
|
51872
52682
|
function bareAddonId(id) {
|
|
@@ -52467,6 +53277,12 @@ var require_dist_DiScsb8j = __commonJS({
|
|
|
52467
53277
|
return resolveCapMount;
|
|
52468
53278
|
}
|
|
52469
53279
|
});
|
|
53280
|
+
Object.defineProperty(exports, "runtimeStatePolicyFor", {
|
|
53281
|
+
enumerable: true,
|
|
53282
|
+
get: function() {
|
|
53283
|
+
return runtimeStatePolicyFor;
|
|
53284
|
+
}
|
|
53285
|
+
});
|
|
52470
53286
|
Object.defineProperty(exports, "scopeKey", {
|
|
52471
53287
|
enumerable: true,
|
|
52472
53288
|
get: function() {
|
|
@@ -52563,7 +53379,7 @@ var require_alerts_addon = __commonJS({
|
|
|
52563
53379
|
[Symbol.toStringTag]: { value: "Module" }
|
|
52564
53380
|
});
|
|
52565
53381
|
require_chunk_Cek0wNdY();
|
|
52566
|
-
var require_dist10 =
|
|
53382
|
+
var require_dist10 = require_dist_D4nuaPdd();
|
|
52567
53383
|
function selectExpired(alerts, cutoffMs) {
|
|
52568
53384
|
return alerts.filter((a) => a.createdAt < cutoffMs).sort((a, b) => a.createdAt - b.createdAt).map((a) => a.id);
|
|
52569
53385
|
}
|
|
@@ -53376,7 +54192,7 @@ var require_console_logging = __commonJS({
|
|
|
53376
54192
|
[Symbol.toStringTag]: { value: "Module" }
|
|
53377
54193
|
});
|
|
53378
54194
|
require_chunk_Cek0wNdY();
|
|
53379
|
-
var require_dist10 =
|
|
54195
|
+
var require_dist10 = require_dist_D4nuaPdd();
|
|
53380
54196
|
var require_formatter = require_formatter_DqAKDlvN();
|
|
53381
54197
|
var LEVEL_RANK = {
|
|
53382
54198
|
debug: 0,
|
|
@@ -53470,7 +54286,7 @@ var require_core_blocks_addon = __commonJS({
|
|
|
53470
54286
|
"use strict";
|
|
53471
54287
|
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
53472
54288
|
var require_chunk = require_chunk_Cek0wNdY();
|
|
53473
|
-
var require_dist10 =
|
|
54289
|
+
var require_dist10 = require_dist_D4nuaPdd();
|
|
53474
54290
|
var node_crypto = __require("crypto");
|
|
53475
54291
|
var node_fs_promises = __require("fs/promises");
|
|
53476
54292
|
node_fs_promises = require_chunk.__toESM(node_fs_promises);
|
|
@@ -56168,7 +56984,7 @@ var require_device_manager_addon = __commonJS({
|
|
|
56168
56984
|
[Symbol.toStringTag]: { value: "Module" }
|
|
56169
56985
|
});
|
|
56170
56986
|
require_chunk_Cek0wNdY();
|
|
56171
|
-
var require_dist10 =
|
|
56987
|
+
var require_dist10 = require_dist_D4nuaPdd();
|
|
56172
56988
|
var node_crypto = __require("crypto");
|
|
56173
56989
|
var _camstack_types_node = require_node();
|
|
56174
56990
|
var JOB_HISTORY = 20;
|
|
@@ -59364,8 +60180,60 @@ var require_device_manager_addon = __commonJS({
|
|
|
59364
60180
|
return current;
|
|
59365
60181
|
};
|
|
59366
60182
|
};
|
|
60183
|
+
function persistableBlob(blob, policyFor) {
|
|
60184
|
+
const out = {};
|
|
60185
|
+
for (const [capName, slice] of Object.entries(blob)) {
|
|
60186
|
+
if (policyFor(capName).durability !== "restored") continue;
|
|
60187
|
+
out[capName] = { ...slice };
|
|
60188
|
+
}
|
|
60189
|
+
return out;
|
|
60190
|
+
}
|
|
60191
|
+
function sliceEffectivelyEqual(a, b, volatileFields) {
|
|
60192
|
+
const skip = new Set(volatileFields);
|
|
60193
|
+
const keys = /* @__PURE__ */ new Set();
|
|
60194
|
+
for (const k of Object.keys(a)) if (!skip.has(k)) keys.add(k);
|
|
60195
|
+
for (const k of Object.keys(b)) if (!skip.has(k)) keys.add(k);
|
|
60196
|
+
for (const k of keys) {
|
|
60197
|
+
if (!deepEqual(a[k], b[k])) return false;
|
|
60198
|
+
if (Object.hasOwn(a, k) !== Object.hasOwn(b, k)) return false;
|
|
60199
|
+
}
|
|
60200
|
+
return true;
|
|
60201
|
+
}
|
|
60202
|
+
function effectivelyEqual(before, after, policyFor) {
|
|
60203
|
+
const caps = /* @__PURE__ */ new Set([...Object.keys(before), ...Object.keys(after)]);
|
|
60204
|
+
for (const capName of caps) {
|
|
60205
|
+
const a = before[capName];
|
|
60206
|
+
const b = after[capName];
|
|
60207
|
+
if (a === void 0 || b === void 0) return false;
|
|
60208
|
+
if (!sliceEffectivelyEqual(a, b, policyFor(capName).volatileFields)) return false;
|
|
60209
|
+
}
|
|
60210
|
+
return true;
|
|
60211
|
+
}
|
|
60212
|
+
function deepEqual(a, b) {
|
|
60213
|
+
if (a === b) return true;
|
|
60214
|
+
if (typeof a === "number" && typeof b === "number") return Number.isNaN(a) && Number.isNaN(b);
|
|
60215
|
+
if (a === null || b === null || typeof a !== "object" || typeof b !== "object") return false;
|
|
60216
|
+
const aIsArray = Array.isArray(a);
|
|
60217
|
+
if (aIsArray !== Array.isArray(b)) return false;
|
|
60218
|
+
if (aIsArray) {
|
|
60219
|
+
const bArr = b;
|
|
60220
|
+
if (a.length !== bArr.length) return false;
|
|
60221
|
+
for (let i = 0; i < a.length; i += 1) if (!deepEqual(a[i], bArr[i])) return false;
|
|
60222
|
+
return true;
|
|
60223
|
+
}
|
|
60224
|
+
const aRec = a;
|
|
60225
|
+
const bRec = b;
|
|
60226
|
+
const aKeys = Object.keys(aRec);
|
|
60227
|
+
if (aKeys.length !== Object.keys(bRec).length) return false;
|
|
60228
|
+
for (const k of aKeys) {
|
|
60229
|
+
if (!Object.hasOwn(bRec, k)) return false;
|
|
60230
|
+
if (!deepEqual(aRec[k], bRec[k])) return false;
|
|
60231
|
+
}
|
|
60232
|
+
return true;
|
|
60233
|
+
}
|
|
59367
60234
|
var DeviceStateMirror = class DeviceStateMirror2 {
|
|
59368
60235
|
ctx;
|
|
60236
|
+
policyFor;
|
|
59369
60237
|
/**
|
|
59370
60238
|
* Hub-side mirror of every device's cap-keyed runtime state.
|
|
59371
60239
|
* Key: deviceId. Value: per-cap slice map. Empty by default —
|
|
@@ -59379,8 +60247,24 @@ var require_device_manager_addon = __commonJS({
|
|
|
59379
60247
|
*/
|
|
59380
60248
|
runtimeStateDebounce = /* @__PURE__ */ new Map();
|
|
59381
60249
|
static RUNTIME_STATE_DEBOUNCE_MS = 1e3;
|
|
59382
|
-
|
|
60250
|
+
/**
|
|
60251
|
+
* What is believed to be ON DISK for each device — the persistable projection
|
|
60252
|
+
* of the last blob actually written (or seeded at boot). The effective-change
|
|
60253
|
+
* gate compares against THIS, not against the previous mirror state: two
|
|
60254
|
+
* clock-only ticks in a row must not add up to a write just because each was
|
|
60255
|
+
* compared with its immediate predecessor.
|
|
60256
|
+
*/
|
|
60257
|
+
lastPersisted = /* @__PURE__ */ new Map();
|
|
60258
|
+
/**
|
|
60259
|
+
* Per-device count of writes the effective-change gate skipped since the last
|
|
60260
|
+
* real one. Reported on the next write that DOES happen, so the log says how
|
|
60261
|
+
* much churn the gate absorbed instead of saying nothing at all — a branch
|
|
60262
|
+
* that drops work silently reads as "never happened".
|
|
60263
|
+
*/
|
|
60264
|
+
skippedSinceWrite = /* @__PURE__ */ new Map();
|
|
60265
|
+
constructor(ctx, policyFor = require_dist10.runtimeStatePolicyFor) {
|
|
59383
60266
|
this.ctx = ctx;
|
|
60267
|
+
this.policyFor = policyFor;
|
|
59384
60268
|
}
|
|
59385
60269
|
/**
|
|
59386
60270
|
* Single-cap mirror update — diff against the current mirror,
|
|
@@ -59407,13 +60291,23 @@ var require_device_manager_addon = __commonJS({
|
|
|
59407
60291
|
return true;
|
|
59408
60292
|
}
|
|
59409
60293
|
/**
|
|
59410
|
-
* Debounced disk writer
|
|
59411
|
-
*
|
|
59412
|
-
*
|
|
59413
|
-
*
|
|
60294
|
+
* Debounced disk writer, behind two gates.
|
|
60295
|
+
*
|
|
60296
|
+
* GATE — DURABILITY: a change to a `durability: 'session'` cap never even
|
|
60297
|
+
* arms the timer. That is where the fleet's write rate goes: `audio-metrics`
|
|
60298
|
+
* and `zone-analytics` are ~90 % of the offered 12–19 writes/s, they change
|
|
60299
|
+
* genuinely every second, and their restored value is worthless.
|
|
60300
|
+
*
|
|
60301
|
+
* GATE — EFFECTIVE CHANGE (at flush): the persistable blob is compared with
|
|
60302
|
+
* what is believed to be on disk, ignoring the clock fields each cap declared
|
|
60303
|
+
* volatile. `battery` wrote its blob 526 times in 25 minutes without one
|
|
60304
|
+
* percentage moving; this is the gate that turns those into one write.
|
|
60305
|
+
*
|
|
60306
|
+
* The blob is read from the live mirror at flush time, so the disk picture is
|
|
59414
60307
|
* always the latest state — no risk of writing a stale snapshot.
|
|
59415
60308
|
*/
|
|
59416
|
-
scheduleRuntimeStateDiskWrite(deviceId, settings) {
|
|
60309
|
+
scheduleRuntimeStateDiskWrite(deviceId, settings, changedCap) {
|
|
60310
|
+
if (this.policyFor(changedCap).durability !== "restored") return;
|
|
59417
60311
|
let slot = this.runtimeStateDebounce.get(deviceId);
|
|
59418
60312
|
if (!slot) {
|
|
59419
60313
|
slot = {
|
|
@@ -59425,10 +60319,21 @@ var require_device_manager_addon = __commonJS({
|
|
|
59425
60319
|
if (slot.timer) return;
|
|
59426
60320
|
slot.timer = setTimeout(() => {
|
|
59427
60321
|
slot.timer = null;
|
|
59428
|
-
const blob = this.
|
|
60322
|
+
const blob = this.persistableForDevice(deviceId);
|
|
60323
|
+
if (this.isAlreadyPersisted(deviceId, blob)) return;
|
|
60324
|
+
const skipped = this.skippedSinceWrite.get(deviceId) ?? 0;
|
|
60325
|
+
this.skippedSinceWrite.delete(deviceId);
|
|
59429
60326
|
const write = (async () => {
|
|
59430
60327
|
try {
|
|
59431
60328
|
await settings.writeDeviceRuntimeState(deviceId, blob);
|
|
60329
|
+
this.lastPersisted.set(deviceId, blob);
|
|
60330
|
+
if (skipped > 0) this.ctx.logger.debug("runtime state persisted", {
|
|
60331
|
+
tags: { deviceId },
|
|
60332
|
+
meta: {
|
|
60333
|
+
caps: Object.keys(blob).length,
|
|
60334
|
+
skippedSinceLastWrite: skipped
|
|
60335
|
+
}
|
|
60336
|
+
});
|
|
59432
60337
|
} catch (err) {
|
|
59433
60338
|
this.ctx.logger.warn("writeDeviceRuntimeState failed", {
|
|
59434
60339
|
tags: { deviceId },
|
|
@@ -59442,6 +60347,22 @@ var require_device_manager_addon = __commonJS({
|
|
|
59442
60347
|
}, DeviceStateMirror2.RUNTIME_STATE_DEBOUNCE_MS);
|
|
59443
60348
|
}
|
|
59444
60349
|
/**
|
|
60350
|
+
* True when `blob` differs from what is believed to be on disk only in fields
|
|
60351
|
+
* the owning caps declared volatile. Counts the skip so the next real write
|
|
60352
|
+
* can report how much churn was absorbed.
|
|
60353
|
+
*/
|
|
60354
|
+
isAlreadyPersisted(deviceId, blob) {
|
|
60355
|
+
const onDisk = this.lastPersisted.get(deviceId);
|
|
60356
|
+
if (!onDisk) return false;
|
|
60357
|
+
if (!effectivelyEqual(onDisk, blob, this.policyFor)) return false;
|
|
60358
|
+
this.skippedSinceWrite.set(deviceId, (this.skippedSinceWrite.get(deviceId) ?? 0) + 1);
|
|
60359
|
+
return true;
|
|
60360
|
+
}
|
|
60361
|
+
/** The device's mirror, restricted to the slices that may reach disk. */
|
|
60362
|
+
persistableForDevice(deviceId) {
|
|
60363
|
+
return persistableBlob(this.snapshotForDevice(deviceId), this.policyFor);
|
|
60364
|
+
}
|
|
60365
|
+
/**
|
|
59445
60366
|
* One-shot mirror seed used by `loadRuntimeState` at boot so the
|
|
59446
60367
|
* hub knows about every persisted slice without waiting for the
|
|
59447
60368
|
* first `setCapSlice` call. No events emitted — this is
|
|
@@ -59461,6 +60382,7 @@ var require_device_manager_addon = __commonJS({
|
|
|
59461
60382
|
if (!raw || typeof raw !== "object" || Array.isArray(raw)) continue;
|
|
59462
60383
|
perCap.set(capName, { ...raw });
|
|
59463
60384
|
}
|
|
60385
|
+
this.lastPersisted.set(deviceId, persistableBlob(this.snapshotForDevice(deviceId), this.policyFor));
|
|
59464
60386
|
}
|
|
59465
60387
|
/**
|
|
59466
60388
|
* The hub mirror's `feature-probe.lastProbedAt` is a PER-SESSION liveness
|
|
@@ -59574,15 +60496,15 @@ var require_device_manager_addon = __commonJS({
|
|
|
59574
60496
|
if (slot.timer) {
|
|
59575
60497
|
clearTimeout(slot.timer);
|
|
59576
60498
|
slot.timer = null;
|
|
59577
|
-
|
|
59578
|
-
|
|
59579
|
-
|
|
59580
|
-
|
|
59581
|
-
|
|
59582
|
-
|
|
59583
|
-
}
|
|
59584
|
-
})
|
|
59585
|
-
}
|
|
60499
|
+
const blob = settings ? this.persistableForDevice(deviceId) : null;
|
|
60500
|
+
if (settings && blob !== null && !this.isAlreadyPersisted(deviceId, blob)) pending.push(settings.writeDeviceRuntimeState(deviceId, blob).then(() => {
|
|
60501
|
+
this.lastPersisted.set(deviceId, blob);
|
|
60502
|
+
}).catch((err) => {
|
|
60503
|
+
this.ctx.logger.warn("shutdown writeDeviceRuntimeState failed", {
|
|
60504
|
+
tags: { deviceId },
|
|
60505
|
+
meta: { error: err instanceof Error ? err.message : String(err) }
|
|
60506
|
+
});
|
|
60507
|
+
}));
|
|
59586
60508
|
}
|
|
59587
60509
|
if (slot.inFlight) pending.push(slot.inFlight);
|
|
59588
60510
|
}
|
|
@@ -60009,7 +60931,7 @@ var require_device_manager_addon = __commonJS({
|
|
|
60009
60931
|
setCapSlice: async (input) => {
|
|
60010
60932
|
const { deviceId, capName, slice } = input;
|
|
60011
60933
|
if (!await resolvePersistedById(deviceId)) throw new Error(`[device-manager] setCapSlice: unknown device id=${deviceId}`);
|
|
60012
|
-
if (stateMirror.applySingleCapUpdate(deviceId, capName, slice)) stateMirror.scheduleRuntimeStateDiskWrite(deviceId, settings);
|
|
60934
|
+
if (stateMirror.applySingleCapUpdate(deviceId, capName, slice)) stateMirror.scheduleRuntimeStateDiskWrite(deviceId, settings, capName);
|
|
60013
60935
|
}
|
|
60014
60936
|
}
|
|
60015
60937
|
}];
|
|
@@ -60050,7 +60972,7 @@ var require_hub_forwarder = __commonJS({
|
|
|
60050
60972
|
[Symbol.toStringTag]: { value: "Module" }
|
|
60051
60973
|
});
|
|
60052
60974
|
require_chunk_Cek0wNdY();
|
|
60053
|
-
var require_dist10 =
|
|
60975
|
+
var require_dist10 = require_dist_D4nuaPdd();
|
|
60054
60976
|
var require_formatter = require_formatter_DqAKDlvN();
|
|
60055
60977
|
var DEFAULT_OUTBOUND_BUFFER_SIZE = 500;
|
|
60056
60978
|
var HubForwarderDestination = class {
|
|
@@ -60187,7 +61109,7 @@ var require_liveness_monitor_addon = __commonJS({
|
|
|
60187
61109
|
"use strict";
|
|
60188
61110
|
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
60189
61111
|
require_chunk_Cek0wNdY();
|
|
60190
|
-
var require_dist10 =
|
|
61112
|
+
var require_dist10 = require_dist_D4nuaPdd();
|
|
60191
61113
|
var NO_DEVICES = "liveness:no-devices";
|
|
60192
61114
|
var ALL_OFFLINE = "liveness:all-devices-offline";
|
|
60193
61115
|
var NO_FOOTAGE_PREFIX = "liveness:no-footage:";
|
|
@@ -60377,7 +61299,7 @@ var require_local_auth_addon = __commonJS({
|
|
|
60377
61299
|
[Symbol.toStringTag]: { value: "Module" }
|
|
60378
61300
|
});
|
|
60379
61301
|
var require_chunk = require_chunk_Cek0wNdY();
|
|
60380
|
-
var require_dist10 =
|
|
61302
|
+
var require_dist10 = require_dist_D4nuaPdd();
|
|
60381
61303
|
var node_crypto = __require("crypto");
|
|
60382
61304
|
node_crypto = require_chunk.__toESM(node_crypto);
|
|
60383
61305
|
var crypto$1 = __require("crypto");
|
|
@@ -68061,7 +68983,7 @@ var require_loki_logging = __commonJS({
|
|
|
68061
68983
|
[Symbol.toStringTag]: { value: "Module" }
|
|
68062
68984
|
});
|
|
68063
68985
|
require_chunk_Cek0wNdY();
|
|
68064
|
-
var require_dist10 =
|
|
68986
|
+
var require_dist10 = require_dist_D4nuaPdd();
|
|
68065
68987
|
function sanitizeLabelName(raw) {
|
|
68066
68988
|
const replaced = raw.replaceAll(/[^a-zA-Z0-9_]/g, "_");
|
|
68067
68989
|
return /^[a-zA-Z_]/.test(replaced) ? replaced : `_${replaced}`;
|
|
@@ -68626,7 +69548,7 @@ var require_native_metrics_addon = __commonJS({
|
|
|
68626
69548
|
[Symbol.toStringTag]: { value: "Module" }
|
|
68627
69549
|
});
|
|
68628
69550
|
var require_chunk = require_chunk_Cek0wNdY();
|
|
68629
|
-
var require_dist10 =
|
|
69551
|
+
var require_dist10 = require_dist_D4nuaPdd();
|
|
68630
69552
|
var node_child_process = __require("child_process");
|
|
68631
69553
|
var node_util = __require("util");
|
|
68632
69554
|
var node_os = __require("os");
|
|
@@ -69568,7 +70490,7 @@ var require_filesystem_storage_addon = __commonJS({
|
|
|
69568
70490
|
[Symbol.toStringTag]: { value: "Module" }
|
|
69569
70491
|
});
|
|
69570
70492
|
var require_chunk = require_chunk_Cek0wNdY();
|
|
69571
|
-
var require_dist10 =
|
|
70493
|
+
var require_dist10 = require_dist_D4nuaPdd();
|
|
69572
70494
|
var node_crypto = __require("crypto");
|
|
69573
70495
|
var node_fs_promises = __require("fs/promises");
|
|
69574
70496
|
var node_path = __require("path");
|
|
@@ -70684,7 +71606,7 @@ var require_sqlite_settings_addon = __commonJS({
|
|
|
70684
71606
|
[Symbol.toStringTag]: { value: "Module" }
|
|
70685
71607
|
});
|
|
70686
71608
|
var require_chunk = require_chunk_Cek0wNdY();
|
|
70687
|
-
var require_dist10 =
|
|
71609
|
+
var require_dist10 = require_dist_D4nuaPdd();
|
|
70688
71610
|
var node_crypto = __require("crypto");
|
|
70689
71611
|
var node_fs = __require("fs");
|
|
70690
71612
|
var node_module = __require("module");
|
|
@@ -71356,6 +72278,42 @@ var require_sqlite_settings_addon = __commonJS({
|
|
|
71356
72278
|
const where = this.prefixWhere(`${addonId}:${deviceId}.`);
|
|
71357
72279
|
this.getDb().prepare(`DELETE FROM "addon-device-settings" WHERE ${where.sql}`).run(...where.params);
|
|
71358
72280
|
}
|
|
72281
|
+
static LEGACY_RUNTIME_STATE_ADDON_ID = "__device-state";
|
|
72282
|
+
/**
|
|
72283
|
+
* The device's whole cap-slice map. Canonical row first, legacy prefix as the
|
|
72284
|
+
* fallback. `{}` — never null — when the device has never persisted a slice,
|
|
72285
|
+
* because every caller treats the result as a cap map to iterate.
|
|
72286
|
+
*/
|
|
72287
|
+
getDeviceRuntimeState(deviceId) {
|
|
72288
|
+
this.requireDeclared("device-runtime-state");
|
|
72289
|
+
const row = this.getDb().prepare('SELECT data FROM "device-runtime-state" WHERE id = ?').get(deviceId);
|
|
72290
|
+
if (row) return parseRowData(row.data);
|
|
72291
|
+
return this.getAddonDevice(SqliteSettingsBackend2.LEGACY_RUNTIME_STATE_ADDON_ID, deviceId);
|
|
72292
|
+
}
|
|
72293
|
+
/**
|
|
72294
|
+
* Replace the device's whole cap-slice map. Replace, not merge — the caller
|
|
72295
|
+
* always hands over the full persistable blob, and merging would resurrect a
|
|
72296
|
+
* slice the durability policy has since stopped persisting.
|
|
72297
|
+
*/
|
|
72298
|
+
setDeviceRuntimeState(deviceId, blob) {
|
|
72299
|
+
this.requireDeclared("device-runtime-state");
|
|
72300
|
+
this.requireDeclared("addon-device-settings");
|
|
72301
|
+
const db = this.getDb();
|
|
72302
|
+
const upsert = db.prepare(`INSERT INTO "device-runtime-state" (id, data) VALUES (?, ?)
|
|
72303
|
+
ON CONFLICT(id) DO UPDATE SET data = excluded.data`);
|
|
72304
|
+
const legacy = this.prefixWhere(`${SqliteSettingsBackend2.LEGACY_RUNTIME_STATE_ADDON_ID}:${deviceId}.`);
|
|
72305
|
+
const retire = db.prepare(`DELETE FROM "addon-device-settings" WHERE ${legacy.sql}`);
|
|
72306
|
+
db.transaction(() => {
|
|
72307
|
+
upsert.run(deviceId, JSON.stringify(blob));
|
|
72308
|
+
retire.run(...legacy.params);
|
|
72309
|
+
})();
|
|
72310
|
+
}
|
|
72311
|
+
/** Forget the device's runtime state in BOTH stores (device removal). */
|
|
72312
|
+
clearDeviceRuntimeState(deviceId) {
|
|
72313
|
+
this.requireDeclared("device-runtime-state");
|
|
72314
|
+
this.getDb().prepare('DELETE FROM "device-runtime-state" WHERE id = ?').run(deviceId);
|
|
72315
|
+
this.clearAddonDevice(SqliteSettingsBackend2.LEGACY_RUNTIME_STATE_ADDON_ID, deviceId);
|
|
72316
|
+
}
|
|
71359
72317
|
/** Seed system-settings with runtime defaults (first boot) */
|
|
71360
72318
|
async seedDefaults() {
|
|
71361
72319
|
this.requireDeclared("system-settings");
|
|
@@ -72199,7 +73157,7 @@ var require_storage_orchestrator_addon = __commonJS({
|
|
|
72199
73157
|
[Symbol.toStringTag]: { value: "Module" }
|
|
72200
73158
|
});
|
|
72201
73159
|
var require_chunk = require_chunk_Cek0wNdY();
|
|
72202
|
-
var require_dist10 =
|
|
73160
|
+
var require_dist10 = require_dist_D4nuaPdd();
|
|
72203
73161
|
var node_crypto = __require("crypto");
|
|
72204
73162
|
var node_fs_promises = __require("fs/promises");
|
|
72205
73163
|
node_fs_promises = require_chunk.__toESM(node_fs_promises);
|
|
@@ -74040,7 +74998,7 @@ var require_system_config_addon = __commonJS({
|
|
|
74040
74998
|
[Symbol.toStringTag]: { value: "Module" }
|
|
74041
74999
|
});
|
|
74042
75000
|
require_chunk_Cek0wNdY();
|
|
74043
|
-
var require_dist10 =
|
|
75001
|
+
var require_dist10 = require_dist_D4nuaPdd();
|
|
74044
75002
|
var SECTION_TITLES = {
|
|
74045
75003
|
server: "Server",
|
|
74046
75004
|
auth: "Authentication"
|
|
@@ -92101,7 +93059,7 @@ var require_winston_logging = __commonJS({
|
|
|
92101
93059
|
[Symbol.toStringTag]: { value: "Module" }
|
|
92102
93060
|
});
|
|
92103
93061
|
var require_chunk = require_chunk_Cek0wNdY();
|
|
92104
|
-
var require_dist10 =
|
|
93062
|
+
var require_dist10 = require_dist_D4nuaPdd();
|
|
92105
93063
|
var require_formatter = require_formatter_DqAKDlvN();
|
|
92106
93064
|
var node_path = __require("path");
|
|
92107
93065
|
node_path = require_chunk.__toESM(node_path);
|
|
@@ -93252,9 +94210,9 @@ var require_event_category_DxZbWydC = __commonJS({
|
|
|
93252
94210
|
}
|
|
93253
94211
|
});
|
|
93254
94212
|
|
|
93255
|
-
// ../types/dist/sleep-
|
|
93256
|
-
var
|
|
93257
|
-
"../types/dist/sleep-
|
|
94213
|
+
// ../types/dist/sleep-Dh1EJSqF.js
|
|
94214
|
+
var require_sleep_Dh1EJSqF = __commonJS({
|
|
94215
|
+
"../types/dist/sleep-Dh1EJSqF.js"(exports) {
|
|
93258
94216
|
"use strict";
|
|
93259
94217
|
var require_event_category = require_event_category_DxZbWydC();
|
|
93260
94218
|
var zod = require_zod();
|
|
@@ -94862,6 +95820,7 @@ var require_sleep_BszXLEvP = __commonJS({
|
|
|
94862
95820
|
const value = Reflect.get(context, CAP_NODE_PIN_CONTEXT_KEY);
|
|
94863
95821
|
return typeof value === "string" ? value : void 0;
|
|
94864
95822
|
}
|
|
95823
|
+
var DEFAULT_RUNTIME_STATE_DURABILITY = "session";
|
|
94865
95824
|
function resolveCapMount(def) {
|
|
94866
95825
|
if (def.mount) return def.mount;
|
|
94867
95826
|
if (def.deviceNative === true) return { kind: "device-native" };
|
|
@@ -96247,6 +97206,12 @@ var require_sleep_BszXLEvP = __commonJS({
|
|
|
96247
97206
|
return DATAPLANE_SECRET_HEADER;
|
|
96248
97207
|
}
|
|
96249
97208
|
});
|
|
97209
|
+
Object.defineProperty(exports, "DEFAULT_RUNTIME_STATE_DURABILITY", {
|
|
97210
|
+
enumerable: true,
|
|
97211
|
+
get: function() {
|
|
97212
|
+
return DEFAULT_RUNTIME_STATE_DURABILITY;
|
|
97213
|
+
}
|
|
97214
|
+
});
|
|
96250
97215
|
Object.defineProperty(exports, "DEVICE_SCOPED_CAPS", {
|
|
96251
97216
|
enumerable: true,
|
|
96252
97217
|
get: function() {
|
|
@@ -96670,7 +97635,7 @@ var require_addon = __commonJS({
|
|
|
96670
97635
|
"use strict";
|
|
96671
97636
|
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
96672
97637
|
var require_event_category = require_event_category_DxZbWydC();
|
|
96673
|
-
var require_sleep =
|
|
97638
|
+
var require_sleep = require_sleep_Dh1EJSqF();
|
|
96674
97639
|
var require_err_msg = require_err_msg_COpsHMw2();
|
|
96675
97640
|
var COLLECTION_ARRAY_METHODS = Object.freeze({
|
|
96676
97641
|
"addon-pages-source": ["listPages"],
|
|
@@ -114114,7 +115079,7 @@ var require_dist3 = __commonJS({
|
|
|
114114
115079
|
"use strict";
|
|
114115
115080
|
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
114116
115081
|
var require_chunk = require_chunk_Cek0wNdY();
|
|
114117
|
-
var require_dist10 =
|
|
115082
|
+
var require_dist10 = require_dist_D4nuaPdd();
|
|
114118
115083
|
var require_builtins_alerts_alerts_addon = require_alerts_addon();
|
|
114119
115084
|
require_alerts();
|
|
114120
115085
|
var require_formatter = require_formatter_DqAKDlvN();
|
|
@@ -117666,23 +118631,15 @@ var require_dist3 = __commonJS({
|
|
|
117666
118631
|
* installs from the admin UI go through `install()` instead, which
|
|
117667
118632
|
* defaults to npm in production.
|
|
117668
118633
|
*
|
|
117669
|
-
*
|
|
117670
|
-
*
|
|
117671
|
-
*
|
|
118634
|
+
* There is no version argument and there is deliberately no pin: the system is
|
|
118635
|
+
* addons-agnostic and `latest` is the whole contract at first boot (operator,
|
|
118636
|
+
* 2026-08-13). A copy already under the addon root is never replaced either —
|
|
118637
|
+
* bootstrap is seed-only, and overwriting a deployed bundle would be an
|
|
118638
|
+
* un-deploy ([D90](../../../../docs/decisions/adr-0090.md)).
|
|
117672
118639
|
*
|
|
117673
|
-
*
|
|
117674
|
-
* image seed answers first today, so `latest` has never been the version a
|
|
117675
|
-
* node actually got. Once the image stops baking an addon tree under `/opt`
|
|
117676
|
-
* this call IS the answer, and it has to be the version the running closure was
|
|
117677
|
-
* published with — otherwise a node fetches latest-of-everything and its
|
|
117678
|
-
* addon set depends on the minute it first booted. Passing nothing keeps
|
|
117679
|
-
* exactly today's behaviour, and `launcher.ts` passes nothing yet.
|
|
117680
|
-
*
|
|
117681
|
-
* A pin never triggers a re-install: bootstrap stays seed-only, so a copy
|
|
117682
|
-
* already under the addon root is left alone whatever its version. Replacing
|
|
117683
|
-
* it would be an un-deploy ([D90](../../../../docs/decisions/adr-0090.md)).
|
|
118640
|
+
* @param packages — optional custom package list (default: REQUIRED_PACKAGES)
|
|
117684
118641
|
*/
|
|
117685
|
-
async ensureRequiredPackages(packages
|
|
118642
|
+
async ensureRequiredPackages(packages) {
|
|
117686
118643
|
const pkgList = packages ?? AddonInstaller2.REQUIRED_PACKAGES;
|
|
117687
118644
|
ensureDir(this.addonsDir);
|
|
117688
118645
|
const isLocal = this.installSource !== "npm" && this.workspaceDir != null;
|
|
@@ -117710,7 +118667,7 @@ var require_dist3 = __commonJS({
|
|
|
117710
118667
|
}
|
|
117711
118668
|
this.logger.info(`${packageName} \u2014 not found locally, trying npm`);
|
|
117712
118669
|
}
|
|
117713
|
-
await this.installFromNpm(packageName
|
|
118670
|
+
await this.installFromNpm(packageName);
|
|
117714
118671
|
} catch (err) {
|
|
117715
118672
|
const msg = require_dist10.errMsg(err);
|
|
117716
118673
|
if (packageName === "@camstack/system") throw new Error(`Required package ${packageName} failed to install: ${msg}`, { cause: err });
|
|
@@ -122833,6 +123790,32 @@ var require_dist3 = __commonJS({
|
|
|
122833
123790
|
if (this.settingsStore === null) return;
|
|
122834
123791
|
this.settingsStore.clearAddonDevice(addonId, deviceId);
|
|
122835
123792
|
}
|
|
123793
|
+
/**
|
|
123794
|
+
* The device's persisted runtime-state blob. `{}` before the settings store
|
|
123795
|
+
* is wired — the same answer as "this device has never persisted a slice",
|
|
123796
|
+
* which is what every caller already handles.
|
|
123797
|
+
*/
|
|
123798
|
+
getDeviceRuntimeState(deviceId) {
|
|
123799
|
+
if (this.settingsStore === null) return {};
|
|
123800
|
+
return this.settingsStore.getDeviceRuntimeState(deviceId);
|
|
123801
|
+
}
|
|
123802
|
+
/**
|
|
123803
|
+
* Replace the device's persisted runtime-state blob.
|
|
123804
|
+
*
|
|
123805
|
+
* THROWS when the store is not wired, and that is deliberate: the caller
|
|
123806
|
+
* (`DeviceStateMirror.scheduleRuntimeStateDiskWrite`) catches and logs, so a
|
|
123807
|
+
* persist that cannot happen leaves a line naming the device. A silent no-op
|
|
123808
|
+
* here is the shape that let a whole collection read zero for months.
|
|
123809
|
+
*/
|
|
123810
|
+
setDeviceRuntimeState(deviceId, blob) {
|
|
123811
|
+
if (this.settingsStore === null) throw new Error("[ConfigManager] SettingsStore not initialized -- call setSettingsStore() first");
|
|
123812
|
+
this.settingsStore.setDeviceRuntimeState(deviceId, blob);
|
|
123813
|
+
}
|
|
123814
|
+
/** Forget the device's runtime state. No-op before the store is wired. */
|
|
123815
|
+
clearDeviceRuntimeState(deviceId) {
|
|
123816
|
+
if (this.settingsStore === null) return;
|
|
123817
|
+
this.settingsStore.clearDeviceRuntimeState(deviceId);
|
|
123818
|
+
}
|
|
122836
123819
|
createSettingsView(addonId) {
|
|
122837
123820
|
const cm = this;
|
|
122838
123821
|
return {
|
|
@@ -122861,13 +123844,13 @@ var require_dist3 = __commonJS({
|
|
|
122861
123844
|
cm.clearAddonDevice(addonId, String(deviceId));
|
|
122862
123845
|
},
|
|
122863
123846
|
async readDeviceRuntimeState(deviceId) {
|
|
122864
|
-
return cm.
|
|
123847
|
+
return cm.getDeviceRuntimeState(String(deviceId));
|
|
122865
123848
|
},
|
|
122866
123849
|
async writeDeviceRuntimeState(deviceId, data) {
|
|
122867
|
-
cm.
|
|
123850
|
+
cm.setDeviceRuntimeState(String(deviceId), data);
|
|
122868
123851
|
},
|
|
122869
123852
|
async clearDeviceRuntimeState(deviceId) {
|
|
122870
|
-
cm.
|
|
123853
|
+
cm.clearDeviceRuntimeState(String(deviceId));
|
|
122871
123854
|
},
|
|
122872
123855
|
async getSection(section) {
|
|
122873
123856
|
return cm.getSection(section);
|
|
@@ -233137,6 +234120,271 @@ var require_agent_http = __commonJS({
|
|
|
233137
234120
|
}
|
|
233138
234121
|
});
|
|
233139
234122
|
|
|
234123
|
+
// ../../server/backend/dist/single-copy-cleanup.js
|
|
234124
|
+
var require_single_copy_cleanup = __commonJS({
|
|
234125
|
+
"../../server/backend/dist/single-copy-cleanup.js"(exports) {
|
|
234126
|
+
"use strict";
|
|
234127
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
234128
|
+
exports.CLOSURE_PROVIDED_PACKAGES = void 0;
|
|
234129
|
+
exports.planSingleCopyCleanup = planSingleCopyCleanup;
|
|
234130
|
+
exports.executeSingleCopyCleanup = executeSingleCopyCleanup;
|
|
234131
|
+
exports.formatCleanupPlan = formatCleanupPlan;
|
|
234132
|
+
exports.discoverRedundantCopies = discoverRedundantCopies;
|
|
234133
|
+
exports.isCleanupEnabled = isCleanupEnabled;
|
|
234134
|
+
var IMAGE_PREFIX = "/opt/";
|
|
234135
|
+
function planSingleCopyCleanup(input) {
|
|
234136
|
+
const blockedReason = nodeWideBlock(input);
|
|
234137
|
+
if (blockedReason !== null) {
|
|
234138
|
+
return {
|
|
234139
|
+
remove: [],
|
|
234140
|
+
keep: input.candidates.map((candidate) => ({ candidate, reason: blockedReason })),
|
|
234141
|
+
blocked: true,
|
|
234142
|
+
blockedReason
|
|
234143
|
+
};
|
|
234144
|
+
}
|
|
234145
|
+
const remove = [];
|
|
234146
|
+
const keep = [];
|
|
234147
|
+
for (const candidate of input.candidates) {
|
|
234148
|
+
const refusal = perCandidateRefusal(candidate, input);
|
|
234149
|
+
if (refusal === null)
|
|
234150
|
+
remove.push(candidate);
|
|
234151
|
+
else
|
|
234152
|
+
keep.push({ candidate, reason: refusal });
|
|
234153
|
+
}
|
|
234154
|
+
return { remove, keep, blocked: false, blockedReason: null };
|
|
234155
|
+
}
|
|
234156
|
+
function nodeWideBlock(input) {
|
|
234157
|
+
if (!input.bootHealthy) {
|
|
234158
|
+
return "this boot is not confirmed healthy \u2014 the redundant copies are the recovery path and stay";
|
|
234159
|
+
}
|
|
234160
|
+
if (input.activeRoot === null) {
|
|
234161
|
+
return "baked mode: there is no active closure, so the node is running FROM the fallback tree";
|
|
234162
|
+
}
|
|
234163
|
+
if (input.closureResolvedFrom === null) {
|
|
234164
|
+
return "the process resolved no @camstack/system at all \u2014 nothing here is safe to remove";
|
|
234165
|
+
}
|
|
234166
|
+
if (!isInside(input.closureResolvedFrom, input.activeRoot)) {
|
|
234167
|
+
return `@camstack/system resolved from ${input.closureResolvedFrom}, which is OUTSIDE the active closure \u2014 the copy being removed could be the one in memory`;
|
|
234168
|
+
}
|
|
234169
|
+
return null;
|
|
234170
|
+
}
|
|
234171
|
+
function perCandidateRefusal(candidate, input) {
|
|
234172
|
+
if (input.activeRoot !== null && isInside(candidate.path, input.activeRoot)) {
|
|
234173
|
+
return "inside the active closure \u2014 this is the copy that runs, not a redundant one";
|
|
234174
|
+
}
|
|
234175
|
+
if (candidate.path.startsWith(IMAGE_PREFIX)) {
|
|
234176
|
+
return "an image tree \u2014 the operator keeps it as the first-boot and fallback source";
|
|
234177
|
+
}
|
|
234178
|
+
const onNodePath = input.nodePathEntries.some((entry) => entry === candidate.path || isInside(entry, candidate.path));
|
|
234179
|
+
if (onNodePath) {
|
|
234180
|
+
return "still on NODE_PATH \u2014 a live resolution path, whatever the boot mode says";
|
|
234181
|
+
}
|
|
234182
|
+
return null;
|
|
234183
|
+
}
|
|
234184
|
+
function isInside(child, parent) {
|
|
234185
|
+
const normalise = (p2) => p2.endsWith("/") ? p2.slice(0, -1) : p2;
|
|
234186
|
+
const c = normalise(child);
|
|
234187
|
+
const p = normalise(parent);
|
|
234188
|
+
return c === p || c.startsWith(`${p}/`);
|
|
234189
|
+
}
|
|
234190
|
+
async function executeSingleCopyCleanup(plan, fs, log) {
|
|
234191
|
+
if (plan.blocked) {
|
|
234192
|
+
log(`single-copy cleanup REFUSED \u2014 ${plan.blockedReason ?? "blocked"}`);
|
|
234193
|
+
return { removed: [], failed: [], refused: true };
|
|
234194
|
+
}
|
|
234195
|
+
const removed = [];
|
|
234196
|
+
const failed = [];
|
|
234197
|
+
for (const candidate of plan.remove) {
|
|
234198
|
+
if (!fs.exists(candidate.path))
|
|
234199
|
+
continue;
|
|
234200
|
+
const label = `${candidate.pkg ?? candidate.kind} ${candidate.version ?? "<unknown version>"}`;
|
|
234201
|
+
const aside = `${candidate.path}.removing-${(/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-")}`;
|
|
234202
|
+
try {
|
|
234203
|
+
await fs.rename(candidate.path, aside);
|
|
234204
|
+
} catch (err) {
|
|
234205
|
+
failed.push(candidate.path);
|
|
234206
|
+
log(`single-copy cleanup \u2014 could NOT remove ${candidate.path} (${label}): ${errMsg(err)}`);
|
|
234207
|
+
continue;
|
|
234208
|
+
}
|
|
234209
|
+
removed.push(candidate.path);
|
|
234210
|
+
log(`single-copy cleanup \u2014 removed ${candidate.path} (${label})`);
|
|
234211
|
+
try {
|
|
234212
|
+
await fs.remove(aside);
|
|
234213
|
+
} catch (err) {
|
|
234214
|
+
log(`single-copy cleanup \u2014 ${aside} still on disk (held open?): ${errMsg(err)}`);
|
|
234215
|
+
}
|
|
234216
|
+
}
|
|
234217
|
+
return { removed, failed, refused: false };
|
|
234218
|
+
}
|
|
234219
|
+
function errMsg(err) {
|
|
234220
|
+
return err instanceof Error ? err.message : String(err);
|
|
234221
|
+
}
|
|
234222
|
+
function formatCleanupPlan(plan) {
|
|
234223
|
+
const lines = [];
|
|
234224
|
+
if (plan.blocked) {
|
|
234225
|
+
lines.push(`single-copy cleanup blocked \u2014 ${plan.blockedReason ?? "unknown reason"}; ${plan.keep.length} copy(ies) kept`);
|
|
234226
|
+
} else {
|
|
234227
|
+
lines.push(`single-copy cleanup \u2014 ${plan.remove.length} copy(ies) to remove`);
|
|
234228
|
+
}
|
|
234229
|
+
for (const c of plan.remove) {
|
|
234230
|
+
lines.push(` remove ${c.path} \u2014 ${c.pkg ?? c.kind} ${c.version ?? "<unknown version>"}`);
|
|
234231
|
+
}
|
|
234232
|
+
for (const k of plan.keep) {
|
|
234233
|
+
lines.push(` keep ${k.candidate.path} \u2014 ${k.candidate.pkg ?? k.candidate.kind} ${k.candidate.version ?? "<unknown version>"}: ${k.reason}`);
|
|
234234
|
+
}
|
|
234235
|
+
return lines;
|
|
234236
|
+
}
|
|
234237
|
+
exports.CLOSURE_PROVIDED_PACKAGES = [
|
|
234238
|
+
"@camstack/system",
|
|
234239
|
+
"@camstack/types",
|
|
234240
|
+
"@camstack/sdk",
|
|
234241
|
+
"@camstack/shm-ring",
|
|
234242
|
+
"@camstack/ui-library"
|
|
234243
|
+
];
|
|
234244
|
+
function discoverRedundantCopies(input, fs) {
|
|
234245
|
+
const found = [];
|
|
234246
|
+
const legacyFramework = `${trimSlash(input.dataDir)}/framework`;
|
|
234247
|
+
if (fs.exists(legacyFramework)) {
|
|
234248
|
+
found.push({
|
|
234249
|
+
kind: "legacy-framework-tree",
|
|
234250
|
+
path: legacyFramework,
|
|
234251
|
+
pkg: null,
|
|
234252
|
+
version: fs.readVersion(`${legacyFramework}/node_modules/@camstack/system`)
|
|
234253
|
+
});
|
|
234254
|
+
}
|
|
234255
|
+
for (const pkg of exports.CLOSURE_PROVIDED_PACKAGES) {
|
|
234256
|
+
if (!input.closureProvides(pkg))
|
|
234257
|
+
continue;
|
|
234258
|
+
const dir = `${trimSlash(input.addonRoot)}/${pkg}`;
|
|
234259
|
+
if (!fs.exists(dir))
|
|
234260
|
+
continue;
|
|
234261
|
+
found.push({
|
|
234262
|
+
kind: "addon-root-closure-copy",
|
|
234263
|
+
path: dir,
|
|
234264
|
+
pkg,
|
|
234265
|
+
version: fs.readVersion(dir)
|
|
234266
|
+
});
|
|
234267
|
+
}
|
|
234268
|
+
return found;
|
|
234269
|
+
}
|
|
234270
|
+
function trimSlash(p) {
|
|
234271
|
+
return p.endsWith("/") ? p.slice(0, -1) : p;
|
|
234272
|
+
}
|
|
234273
|
+
function isCleanupEnabled(env) {
|
|
234274
|
+
const raw = env["CAMSTACK_SINGLE_COPY_CLEANUP"]?.trim().toLowerCase();
|
|
234275
|
+
return raw !== "off" && raw !== "0" && raw !== "false";
|
|
234276
|
+
}
|
|
234277
|
+
}
|
|
234278
|
+
});
|
|
234279
|
+
|
|
234280
|
+
// ../../server/backend/dist/single-copy-cleanup-runner.js
|
|
234281
|
+
var require_single_copy_cleanup_runner = __commonJS({
|
|
234282
|
+
"../../server/backend/dist/single-copy-cleanup-runner.js"(exports) {
|
|
234283
|
+
"use strict";
|
|
234284
|
+
var __createBinding = exports && exports.__createBinding || (Object.create ? (function(o, m, k, k2) {
|
|
234285
|
+
if (k2 === void 0) k2 = k;
|
|
234286
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
234287
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
234288
|
+
desc = { enumerable: true, get: function() {
|
|
234289
|
+
return m[k];
|
|
234290
|
+
} };
|
|
234291
|
+
}
|
|
234292
|
+
Object.defineProperty(o, k2, desc);
|
|
234293
|
+
}) : (function(o, m, k, k2) {
|
|
234294
|
+
if (k2 === void 0) k2 = k;
|
|
234295
|
+
o[k2] = m[k];
|
|
234296
|
+
}));
|
|
234297
|
+
var __setModuleDefault = exports && exports.__setModuleDefault || (Object.create ? (function(o, v) {
|
|
234298
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
234299
|
+
}) : function(o, v) {
|
|
234300
|
+
o["default"] = v;
|
|
234301
|
+
});
|
|
234302
|
+
var __importStar = exports && exports.__importStar || /* @__PURE__ */ (function() {
|
|
234303
|
+
var ownKeys = function(o) {
|
|
234304
|
+
ownKeys = Object.getOwnPropertyNames || function(o2) {
|
|
234305
|
+
var ar = [];
|
|
234306
|
+
for (var k in o2) if (Object.prototype.hasOwnProperty.call(o2, k)) ar[ar.length] = k;
|
|
234307
|
+
return ar;
|
|
234308
|
+
};
|
|
234309
|
+
return ownKeys(o);
|
|
234310
|
+
};
|
|
234311
|
+
return function(mod) {
|
|
234312
|
+
if (mod && mod.__esModule) return mod;
|
|
234313
|
+
var result = {};
|
|
234314
|
+
if (mod != null) {
|
|
234315
|
+
for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
234316
|
+
}
|
|
234317
|
+
__setModuleDefault(result, mod);
|
|
234318
|
+
return result;
|
|
234319
|
+
};
|
|
234320
|
+
})();
|
|
234321
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
234322
|
+
exports.runSingleCopyCleanup = runSingleCopyCleanup;
|
|
234323
|
+
var fs = __importStar(__require("fs"));
|
|
234324
|
+
var path = __importStar(__require("path"));
|
|
234325
|
+
var single_copy_cleanup_js_1 = require_single_copy_cleanup();
|
|
234326
|
+
var EMPTY_RESULT = { removed: [], failed: [], refused: true };
|
|
234327
|
+
async function runSingleCopyCleanup(opts) {
|
|
234328
|
+
try {
|
|
234329
|
+
if (!(0, single_copy_cleanup_js_1.isCleanupEnabled)(process.env)) {
|
|
234330
|
+
opts.log("single-copy cleanup disabled by CAMSTACK_SINGLE_COPY_CLEANUP \u2014 nothing removed");
|
|
234331
|
+
return EMPTY_RESULT;
|
|
234332
|
+
}
|
|
234333
|
+
const candidates = (0, single_copy_cleanup_js_1.discoverRedundantCopies)({
|
|
234334
|
+
dataDir: opts.dataDir,
|
|
234335
|
+
addonRoot: opts.addonRoot,
|
|
234336
|
+
closureProvides: (pkg) => {
|
|
234337
|
+
try {
|
|
234338
|
+
__require.resolve(`${pkg}/package.json`);
|
|
234339
|
+
return true;
|
|
234340
|
+
} catch {
|
|
234341
|
+
return false;
|
|
234342
|
+
}
|
|
234343
|
+
}
|
|
234344
|
+
}, {
|
|
234345
|
+
exists: (p) => fs.existsSync(p),
|
|
234346
|
+
readVersion: (dir) => readVersion(dir)
|
|
234347
|
+
});
|
|
234348
|
+
const plan = (0, single_copy_cleanup_js_1.planSingleCopyCleanup)({
|
|
234349
|
+
activeRoot: process.env["CAMSTACK_SERVER_ACTIVE_ROOT"] ?? null,
|
|
234350
|
+
closureResolvedFrom: resolveSystemPath(),
|
|
234351
|
+
bootHealthy: true,
|
|
234352
|
+
nodePathEntries: (process.env["NODE_PATH"] ?? "").split(process.platform === "win32" ? ";" : ":").map((entry) => entry.trim()).filter((entry) => entry.length > 0),
|
|
234353
|
+
candidates
|
|
234354
|
+
});
|
|
234355
|
+
for (const line of (0, single_copy_cleanup_js_1.formatCleanupPlan)(plan))
|
|
234356
|
+
opts.log(line);
|
|
234357
|
+
return await (0, single_copy_cleanup_js_1.executeSingleCopyCleanup)(plan, {
|
|
234358
|
+
exists: (p) => fs.existsSync(p),
|
|
234359
|
+
rename: (from, to) => fs.renameSync(from, to),
|
|
234360
|
+
remove: async (p) => {
|
|
234361
|
+
await fs.promises.rm(p, { recursive: true, force: true });
|
|
234362
|
+
}
|
|
234363
|
+
}, opts.log);
|
|
234364
|
+
} catch (err) {
|
|
234365
|
+
opts.log(`single-copy cleanup failed: ${err instanceof Error ? err.message : String(err)} \u2014 nothing was removed`);
|
|
234366
|
+
return EMPTY_RESULT;
|
|
234367
|
+
}
|
|
234368
|
+
}
|
|
234369
|
+
function resolveSystemPath() {
|
|
234370
|
+
try {
|
|
234371
|
+
return __require.resolve("@camstack/system/package.json");
|
|
234372
|
+
} catch {
|
|
234373
|
+
return null;
|
|
234374
|
+
}
|
|
234375
|
+
}
|
|
234376
|
+
function readVersion(packageDir) {
|
|
234377
|
+
try {
|
|
234378
|
+
const raw = JSON.parse(fs.readFileSync(path.join(packageDir, "package.json"), "utf-8"));
|
|
234379
|
+
const version = typeof raw === "object" && raw !== null ? raw.version : void 0;
|
|
234380
|
+
return typeof version === "string" ? version : null;
|
|
234381
|
+
} catch {
|
|
234382
|
+
return null;
|
|
234383
|
+
}
|
|
234384
|
+
}
|
|
234385
|
+
}
|
|
234386
|
+
});
|
|
234387
|
+
|
|
233140
234388
|
// ../types/dist/enums.js
|
|
233141
234389
|
var require_enums = __commonJS({
|
|
233142
234390
|
"../types/dist/enums.js"(exports) {
|
|
@@ -233163,7 +234411,7 @@ var require_dist9 = __commonJS({
|
|
|
233163
234411
|
"use strict";
|
|
233164
234412
|
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
233165
234413
|
var require_event_category = require_event_category_DxZbWydC();
|
|
233166
|
-
var require_sleep =
|
|
234414
|
+
var require_sleep = require_sleep_Dh1EJSqF();
|
|
233167
234415
|
var require_canonical_hash = require_canonical_hash_DNV8S5ET();
|
|
233168
234416
|
var require_enums2 = require_enums();
|
|
233169
234417
|
var require_err_msg = require_err_msg_COpsHMw2();
|
|
@@ -238254,7 +239502,14 @@ ${recipe.triggers.map((t, i) => emitTrigger(t, i)).join("\n\n")}
|
|
|
238254
239502
|
low: zod.z.string().optional()
|
|
238255
239503
|
}),
|
|
238256
239504
|
lastChangedAt: zod.z.number()
|
|
238257
|
-
})
|
|
239505
|
+
}),
|
|
239506
|
+
/**
|
|
239507
|
+
* Runtime-state durability: **session** — a restored `slotStatuses: streaming` for a camera that has been dark for two hours is a lie the UI renders as truth.
|
|
239508
|
+
*
|
|
239509
|
+
* See `RuntimeStateDurability`. Enforced by
|
|
239510
|
+
* `scripts/check-runtime-state-durability.ts`.
|
|
239511
|
+
*/
|
|
239512
|
+
durability: "session"
|
|
238258
239513
|
};
|
|
238259
239514
|
function isVoidInput(schema) {
|
|
238260
239515
|
const def2 = schema._def;
|
|
@@ -239033,6 +240288,13 @@ ${recipe.triggers.map((t, i) => emitTrigger(t, i)).join("\n\n")}
|
|
|
239033
240288
|
kind: "poll"
|
|
239034
240289
|
},
|
|
239035
240290
|
runtimeState: DeviceDiscoveryStatusSchema.extend({ lastFetchedAt: zod.z.number().int().nonnegative() }),
|
|
240291
|
+
/**
|
|
240292
|
+
* Runtime-state durability: **session** — 5.7 KB of scan output on the largest device, fully re-derivable by re-scanning.
|
|
240293
|
+
*
|
|
240294
|
+
* See `RuntimeStateDurability`. Enforced by
|
|
240295
|
+
* `scripts/check-runtime-state-durability.ts`.
|
|
240296
|
+
*/
|
|
240297
|
+
durability: "session",
|
|
239036
240298
|
methods: {
|
|
239037
240299
|
/**
|
|
239038
240300
|
* Snapshot of the current `discovered` list. Returns the
|
|
@@ -241261,7 +242523,23 @@ ${recipe.triggers.map((t, i) => emitTrigger(t, i)).join("\n\n")}
|
|
|
241261
242523
|
* else — see `notification-center/action-token.ts` for what that does and
|
|
241262
242524
|
* does not buy.
|
|
241263
242525
|
*/
|
|
241264
|
-
destructive: zod.z.boolean().optional()
|
|
242526
|
+
destructive: zod.z.boolean().optional(),
|
|
242527
|
+
/**
|
|
242528
|
+
* How the tap should REACH the url.
|
|
242529
|
+
*
|
|
242530
|
+
* `navigate` (absent, and every button authored before this field) opens it:
|
|
242531
|
+
* the phone leaves the notification and shows whatever the callback returns.
|
|
242532
|
+
* That is right for a button whose answer the operator wants to read.
|
|
242533
|
+
*
|
|
242534
|
+
* `background` fires it as a POST and stays put. It exists for the buttons
|
|
242535
|
+
* whose whole point is not to interrupt — "silence this for 30 minutes" is
|
|
242536
|
+
* an answer to the notification, and being thrown into a browser tab to
|
|
242537
|
+
* confirm it costs more attention than the notification did. A backend that
|
|
242538
|
+
* cannot do a background call renders it as an ordinary link (the adapters
|
|
242539
|
+
* fall back rather than dropping the button), so this is a preference, never
|
|
242540
|
+
* a requirement.
|
|
242541
|
+
*/
|
|
242542
|
+
mode: zod.z.enum(["navigate", "background"]).optional()
|
|
241265
242543
|
});
|
|
241266
242544
|
var NotificationSchema = zod.z.object({
|
|
241267
242545
|
body: zod.z.string(),
|
|
@@ -242397,7 +243675,17 @@ ${recipe.triggers.map((t, i) => emitTrigger(t, i)).join("\n\n")}
|
|
|
242397
243675
|
* full slice; renders an arm button per `availableModes` entry and
|
|
242398
243676
|
* a PIN field iff `requiresCode === true`.
|
|
242399
243677
|
*/
|
|
242400
|
-
runtimeState: AlarmPanelStatusSchema
|
|
243678
|
+
runtimeState: AlarmPanelStatusSchema,
|
|
243679
|
+
/**
|
|
243680
|
+
* Runtime-state durability: **restored** — armed state is the one thing a panel must not lose across a restart.
|
|
243681
|
+
*
|
|
243682
|
+
* See `RuntimeStateDurability`. Enforced by
|
|
243683
|
+
* `scripts/check-runtime-state-durability.ts`.
|
|
243684
|
+
*/
|
|
243685
|
+
durability: "restored",
|
|
243686
|
+
/** Clock fields: written, but excluded from the compare that decides
|
|
243687
|
+
* whether persisting is worth a SQLite commit. */
|
|
243688
|
+
volatileStateFields: ["lastChangedAt"]
|
|
242401
243689
|
};
|
|
242402
243690
|
var MaskPointSchema = zod.z.object({
|
|
242403
243691
|
x: zod.z.number(),
|
|
@@ -242501,6 +243789,12 @@ ${recipe.triggers.map((t, i) => emitTrigger(t, i)).join("\n\n")}
|
|
|
242501
243789
|
packageNames: zod.z.array(zod.z.string().min(1)).min(1).optional()
|
|
242502
243790
|
});
|
|
242503
243791
|
var NC_MAX_PER_TRACK_IMMEDIATE = 1;
|
|
243792
|
+
var NC_SNOOZE_MAX_MINUTES = 1440;
|
|
243793
|
+
var NC_DEFAULT_SNOOZE_MINUTES = [
|
|
243794
|
+
10,
|
|
243795
|
+
30,
|
|
243796
|
+
60
|
|
243797
|
+
];
|
|
242504
243798
|
var NcScheduleWindowSchema = zod.z.object({
|
|
242505
243799
|
/** Days of week the window STARTS on (0 = Sunday … 6 = Saturday). */
|
|
242506
243800
|
days: zod.z.array(zod.z.number().int().min(0).max(6)).min(1),
|
|
@@ -242758,15 +244052,15 @@ ${recipe.triggers.map((t, i) => emitTrigger(t, i)).join("\n\n")}
|
|
|
242758
244052
|
* (an `immediate` rule naming an `audio-*` class, one notification per
|
|
242759
244053
|
* classified sample) stays exactly as it was for rules that already use it.
|
|
242760
244054
|
*
|
|
242761
|
-
*
|
|
242762
|
-
* rather than an
|
|
242763
|
-
* (`camstack/src/data/notification-center.ts`, guarded by
|
|
242764
|
-
* `scripts/check-viewer-condition-mirror.ts`) and its rule editor
|
|
244055
|
+
* In {@link NC_CONDITION_CATALOG} since P2, and the ORDER it got there is the
|
|
244056
|
+
* rule rather than an accident: the viewer mirrors the descriptor enums BY
|
|
244057
|
+
* HAND (`camstack/src/data/notification-center.ts`, guarded by
|
|
244058
|
+
* `scripts/check-viewer-condition-mirror.ts`) and its rule editor strips the
|
|
242765
244059
|
* condition fields it does not know when a rule is saved from the phone.
|
|
242766
244060
|
* Publishing an editor for a condition the app cannot round-trip is how an
|
|
242767
|
-
* operator loses a rule's conditions by opening it — so the
|
|
242768
|
-
*
|
|
242769
|
-
*
|
|
244061
|
+
* operator loses a rule's conditions by opening it — so the viewer mirror
|
|
244062
|
+
* (P3, shipped) went FIRST, and the descriptor an editor renders from
|
|
244063
|
+
* follows here.
|
|
242770
244064
|
*/
|
|
242771
244065
|
audio: NcAudioConditionSchema.optional()
|
|
242772
244066
|
});
|
|
@@ -242936,6 +244230,30 @@ ${recipe.triggers.map((t, i) => emitTrigger(t, i)).join("\n\n")}
|
|
|
242936
244230
|
*/
|
|
242937
244231
|
snoozeAllowGlobal: zod.z.boolean().optional(),
|
|
242938
244232
|
/**
|
|
244233
|
+
* The snooze durations THIS rule's notification offers as buttons, in
|
|
244234
|
+
* minutes.
|
|
244235
|
+
*
|
|
244236
|
+
* Three states, and all three are distinct — which is exactly why this is
|
|
244237
|
+
* `.optional()` and never `.default()`. A Zod default does not run on the
|
|
244238
|
+
* addon cap path (three production failures in one day), so a schema default
|
|
244239
|
+
* would collapse the first two:
|
|
244240
|
+
*
|
|
244241
|
+
* | value | meaning |
|
|
244242
|
+
* | --- | --- |
|
|
244243
|
+
* | absent | the operator never said ⇒ {@link NC_DEFAULT_SNOOZE_MINUTES} |
|
|
244244
|
+
* | `[]` | **no snooze buttons on this rule** — the explicit override |
|
|
244245
|
+
* | a list | these choices, de-duplicated and sorted, at most four |
|
|
244246
|
+
*
|
|
244247
|
+
* `.max(4)` because the notifier's own action budget is small (ntfy allows
|
|
244248
|
+
* three buttons in total) and a rule that spent it all on snooze choices
|
|
244249
|
+
* would push its own tap-through actions off the notification.
|
|
244250
|
+
*
|
|
244251
|
+
* An empty list is NOT an alarm exemption: a rule the alarm is about, or
|
|
244252
|
+
* that arms the panel, is exempt automatically and cannot be silenced by a
|
|
244253
|
+
* window from anywhere (D133).
|
|
244254
|
+
*/
|
|
244255
|
+
snoozeOptions: zod.z.array(zod.z.number().int().min(1).max(NC_SNOOZE_MAX_MINUTES)).max(4).optional(),
|
|
244256
|
+
/**
|
|
242939
244257
|
* Devices this rule ACTUATES — arm the alarm, open a gate, turn on a light.
|
|
242940
244258
|
*
|
|
242941
244259
|
* This is what makes the rule set the alarm's trigger set without the alarm
|
|
@@ -243025,6 +244343,7 @@ ${recipe.triggers.map((t, i) => emitTrigger(t, i)).join("\n\n")}
|
|
|
243025
244343
|
"device",
|
|
243026
244344
|
"package",
|
|
243027
244345
|
"occupancy",
|
|
244346
|
+
"audio",
|
|
243028
244347
|
"system"
|
|
243029
244348
|
]),
|
|
243030
244349
|
label: zod.z.string(),
|
|
@@ -243043,6 +244362,7 @@ ${recipe.triggers.map((t, i) => emitTrigger(t, i)).join("\n\n")}
|
|
|
243043
244362
|
"crossingSelect",
|
|
243044
244363
|
"polygonDraw",
|
|
243045
244364
|
"occupancy",
|
|
244365
|
+
"audio",
|
|
243046
244366
|
"deviceState",
|
|
243047
244367
|
"systemEvent"
|
|
243048
244368
|
]),
|
|
@@ -243436,6 +244756,16 @@ ${recipe.triggers.map((t, i) => emitTrigger(t, i)).join("\n\n")}
|
|
|
243436
244756
|
phase: "P1",
|
|
243437
244757
|
description: "ZoneAnalytics occupancy edge (optionally zone/class-scoped): count crosses the threshold and holds for sustainSeconds. Fail-closed on a missing snapshot."
|
|
243438
244758
|
},
|
|
244759
|
+
{
|
|
244760
|
+
id: "audio",
|
|
244761
|
+
group: "audio",
|
|
244762
|
+
label: "Sound",
|
|
244763
|
+
valueType: "audio",
|
|
244764
|
+
operator: "anyOf",
|
|
244765
|
+
appliesTo: ["immediate"],
|
|
244766
|
+
phase: "P2",
|
|
244767
|
+
description: "Fires when at least hitPercent% of the samples in a samplingSeconds window are hits \u2014 a hit clears the dBFS floor AND carries one of the chosen sounds. Both filters are optional and independent, but naming NEITHER never matches: every sample would be a hit, so the engine refuses rather than notifying on silence. dBFS is negative-going (0 = full scale, -96 = silence)."
|
|
244768
|
+
},
|
|
243439
244769
|
{
|
|
243440
244770
|
id: "customZones",
|
|
243441
244771
|
group: "zones",
|
|
@@ -243534,7 +244864,6 @@ ${recipe.triggers.map((t, i) => emitTrigger(t, i)).join("\n\n")}
|
|
|
243534
244864
|
"device",
|
|
243535
244865
|
"all"
|
|
243536
244866
|
]);
|
|
243537
|
-
var NC_SNOOZE_MAX_MINUTES = 1440;
|
|
243538
244867
|
var NcSnoozeInputSchema = zod.z.object({
|
|
243539
244868
|
scope: NcSnoozeScopeSchema,
|
|
243540
244869
|
/** Required when `scope: 'rule'` — a scoped snooze with no id matches
|
|
@@ -243542,6 +244871,19 @@ ${recipe.triggers.map((t, i) => emitTrigger(t, i)).join("\n\n")}
|
|
|
243542
244871
|
ruleId: zod.z.string().optional(),
|
|
243543
244872
|
/** Required when `scope: 'device'`. */
|
|
243544
244873
|
deviceId: zod.z.number().int().optional(),
|
|
244874
|
+
/**
|
|
244875
|
+
* Narrow the window to these subject classes — "the cat, not the person".
|
|
244876
|
+
*
|
|
244877
|
+
* ORTHOGONAL to `scope`, deliberately, and absent means EVERY class: that is
|
|
244878
|
+
* what every window authored before this field meant, so no persisted row
|
|
244879
|
+
* changes meaning and no client has to learn anything to keep working.
|
|
244880
|
+
*
|
|
244881
|
+
* It is what makes the window's real key `(deviceId, classes[])` and lets it
|
|
244882
|
+
* cross rules (D133): the operator points at a camera and a kind of thing,
|
|
244883
|
+
* not at whichever of their four rules happened to produce the notification
|
|
244884
|
+
* they are dismissing.
|
|
244885
|
+
*/
|
|
244886
|
+
classes: zod.z.array(zod.z.string().min(1)).min(1).optional(),
|
|
243545
244887
|
durationMinutes: zod.z.number().int().min(1).max(NC_SNOOZE_MAX_MINUTES),
|
|
243546
244888
|
/**
|
|
243547
244889
|
* Silence this for EVERY recipient, not just the caller. Permission is
|
|
@@ -243566,6 +244908,10 @@ ${recipe.triggers.map((t, i) => emitTrigger(t, i)).join("\n\n")}
|
|
|
243566
244908
|
scope: NcSnoozeScopeSchema,
|
|
243567
244909
|
ruleId: zod.z.string().optional(),
|
|
243568
244910
|
deviceId: zod.z.number().int().optional(),
|
|
244911
|
+
/** Subject classes this window covers. ABSENT = every class — see
|
|
244912
|
+
* {@link NcSnoozeInputSchema.shape.classes}. Lives in the JSON blob and has
|
|
244913
|
+
* no SQLite column: nothing queries a window by class. */
|
|
244914
|
+
classes: zod.z.array(zod.z.string().min(1)).min(1).optional(),
|
|
243569
244915
|
startedAt: zod.z.number(),
|
|
243570
244916
|
/** Exclusive: at exactly this instant the snooze is over. Expiry is a
|
|
243571
244917
|
* COMPARISON, not a job — no sweeper can leave the operator silenced. */
|
|
@@ -245838,7 +247184,14 @@ ${recipe.triggers.map((t, i) => emitTrigger(t, i)).join("\n\n")}
|
|
|
245838
247184
|
* handle. Slice shape is `{ zones: Zone[] }` so future extensions
|
|
245839
247185
|
* (e.g. zone groupings) can sit alongside the polygon list.
|
|
245840
247186
|
*/
|
|
245841
|
-
runtimeState: zod.z.object({ zones: zod.z.array(ZoneSchema).readonly() })
|
|
247187
|
+
runtimeState: zod.z.object({ zones: zod.z.array(ZoneSchema).readonly() }),
|
|
247188
|
+
/**
|
|
247189
|
+
* Runtime-state durability: **restored** — written only on operator mutation, so a camera that never had one has nothing to re-derive from. This is the slice `zone-mirror-hydration.ts` exists to paper over.
|
|
247190
|
+
*
|
|
247191
|
+
* See `RuntimeStateDurability`. Enforced by
|
|
247192
|
+
* `scripts/check-runtime-state-durability.ts`.
|
|
247193
|
+
*/
|
|
247194
|
+
durability: "restored"
|
|
245842
247195
|
};
|
|
245843
247196
|
var NativeCropBboxSchema = zod.z.object({
|
|
245844
247197
|
x: zod.z.number(),
|
|
@@ -249285,7 +250638,17 @@ ${recipe.triggers.map((t, i) => emitTrigger(t, i)).join("\n\n")}
|
|
|
249285
250638
|
schema: AirQualitySensorStatusSchema,
|
|
249286
250639
|
kind: "push"
|
|
249287
250640
|
},
|
|
249288
|
-
runtimeState: AirQualitySensorStatusSchema
|
|
250641
|
+
runtimeState: AirQualitySensorStatusSchema,
|
|
250642
|
+
/**
|
|
250643
|
+
* Runtime-state durability: **restored** — as `numeric-sensor`.
|
|
250644
|
+
*
|
|
250645
|
+
* See `RuntimeStateDurability`. Enforced by
|
|
250646
|
+
* `scripts/check-runtime-state-durability.ts`.
|
|
250647
|
+
*/
|
|
250648
|
+
durability: "restored",
|
|
250649
|
+
/** Clock fields: written, but excluded from the compare that decides
|
|
250650
|
+
* whether persisting is worth a SQLite commit. */
|
|
250651
|
+
volatileStateFields: ["lastFetchedAt"]
|
|
249289
250652
|
};
|
|
249290
250653
|
var AmbientLightSensorStatusSchema = zod.z.object({
|
|
249291
250654
|
/** Current illuminance in lux (lx). */
|
|
@@ -249313,7 +250676,17 @@ ${recipe.triggers.map((t, i) => emitTrigger(t, i)).join("\n\n")}
|
|
|
249313
250676
|
schema: AmbientLightSensorStatusSchema,
|
|
249314
250677
|
kind: "push"
|
|
249315
250678
|
},
|
|
249316
|
-
runtimeState: AmbientLightSensorStatusSchema
|
|
250679
|
+
runtimeState: AmbientLightSensorStatusSchema,
|
|
250680
|
+
/**
|
|
250681
|
+
* Runtime-state durability: **restored** — as `numeric-sensor`.
|
|
250682
|
+
*
|
|
250683
|
+
* See `RuntimeStateDurability`. Enforced by
|
|
250684
|
+
* `scripts/check-runtime-state-durability.ts`.
|
|
250685
|
+
*/
|
|
250686
|
+
durability: "restored",
|
|
250687
|
+
/** Clock fields: written, but excluded from the compare that decides
|
|
250688
|
+
* whether persisting is worth a SQLite commit. */
|
|
250689
|
+
volatileStateFields: ["lastFetchedAt"]
|
|
249317
250690
|
};
|
|
249318
250691
|
var AudioClassSummarySchema = zod.z.object({
|
|
249319
250692
|
className: zod.z.string(),
|
|
@@ -249403,7 +250776,14 @@ ${recipe.triggers.map((t, i) => emitTrigger(t, i)).join("\n\n")}
|
|
|
249403
250776
|
}), AudioMetricsHistorySchema)
|
|
249404
250777
|
},
|
|
249405
250778
|
/** Reactive runtime-state mirror — live `device.state.audioMetrics.value`. */
|
|
249406
|
-
runtimeState: AudioMetricsSnapshotSchema
|
|
250779
|
+
runtimeState: AudioMetricsSnapshotSchema,
|
|
250780
|
+
/**
|
|
250781
|
+
* Runtime-state durability: **session** — 1 Hz per camera at the mirror and ~63 % of the fleet's whole runtime-state write rate. `avgDbfs` is a rolling 60 s mean that genuinely moves every second, so no equality fix reclaims it — and a two-hour-old dB reading rendered as current is worse than no reading.
|
|
250782
|
+
*
|
|
250783
|
+
* See `RuntimeStateDurability`. Enforced by
|
|
250784
|
+
* `scripts/check-runtime-state-durability.ts`.
|
|
250785
|
+
*/
|
|
250786
|
+
durability: "session"
|
|
249407
250787
|
};
|
|
249408
250788
|
var AutomationControlStatusSchema = zod.z.object({
|
|
249409
250789
|
/** Whether the automation is currently enabled. Disabled automations
|
|
@@ -249454,7 +250834,14 @@ ${recipe.triggers.map((t, i) => emitTrigger(t, i)).join("\n\n")}
|
|
|
249454
250834
|
* reads `enabled` (toggle) + `isRunning` (spinner) + `lastError`
|
|
249455
250835
|
* (badge) directly.
|
|
249456
250836
|
*/
|
|
249457
|
-
runtimeState: AutomationControlStatusSchema
|
|
250837
|
+
runtimeState: AutomationControlStatusSchema,
|
|
250838
|
+
/**
|
|
250839
|
+
* Runtime-state durability: **session** — the authority for an automation being enabled is the automation store; a restored `isRunning` would be a lie. D62: one authority per switch.
|
|
250840
|
+
*
|
|
250841
|
+
* See `RuntimeStateDurability`. Enforced by
|
|
250842
|
+
* `scripts/check-runtime-state-durability.ts`.
|
|
250843
|
+
*/
|
|
250844
|
+
durability: "session"
|
|
249458
250845
|
};
|
|
249459
250846
|
var BatteryStatusSchema = zod.z.object({
|
|
249460
250847
|
/** 0..100 inclusive. Firmware-reported. */
|
|
@@ -249555,7 +250942,17 @@ ${recipe.triggers.map((t, i) => emitTrigger(t, i)).join("\n\n")}
|
|
|
249555
250942
|
* via `device.runtimeState.getCapState('battery')` regardless of
|
|
249556
250943
|
* the underlying driver.
|
|
249557
250944
|
*/
|
|
249558
|
-
runtimeState: BatteryStatusSchema
|
|
250945
|
+
runtimeState: BatteryStatusSchema,
|
|
250946
|
+
/**
|
|
250947
|
+
* Runtime-state durability: **restored** — a sleeping battery camera may not report for hours; the restored percentage is the only thing the UI and the sleep gate have. Zero churn once `lastUpdated` is excluded — 526 writes, 0 value changes, in 25 minutes.
|
|
250948
|
+
*
|
|
250949
|
+
* See `RuntimeStateDurability`. Enforced by
|
|
250950
|
+
* `scripts/check-runtime-state-durability.ts`.
|
|
250951
|
+
*/
|
|
250952
|
+
durability: "restored",
|
|
250953
|
+
/** Clock fields: written, but excluded from the compare that decides
|
|
250954
|
+
* whether persisting is worth a SQLite commit. */
|
|
250955
|
+
volatileStateFields: ["lastUpdated"]
|
|
249559
250956
|
};
|
|
249560
250957
|
var BinaryStatusSchema = zod.z.object({
|
|
249561
250958
|
on: zod.z.boolean(),
|
|
@@ -249573,7 +250970,17 @@ ${recipe.triggers.map((t, i) => emitTrigger(t, i)).join("\n\n")}
|
|
|
249573
250970
|
schema: BinaryStatusSchema,
|
|
249574
250971
|
kind: "push"
|
|
249575
250972
|
},
|
|
249576
|
-
runtimeState: BinaryStatusSchema
|
|
250973
|
+
runtimeState: BinaryStatusSchema,
|
|
250974
|
+
/**
|
|
250975
|
+
* Runtime-state durability: **restored** — transition-driven sensor state; the restored value gives the boot comparison.
|
|
250976
|
+
*
|
|
250977
|
+
* See `RuntimeStateDurability`. Enforced by
|
|
250978
|
+
* `scripts/check-runtime-state-durability.ts`.
|
|
250979
|
+
*/
|
|
250980
|
+
durability: "restored",
|
|
250981
|
+
/** Clock fields: written, but excluded from the compare that decides
|
|
250982
|
+
* whether persisting is worth a SQLite commit. */
|
|
250983
|
+
volatileStateFields: ["lastChangedAt"]
|
|
249577
250984
|
};
|
|
249578
250985
|
var BrightnessStatusSchema = zod.z.object({
|
|
249579
250986
|
/** Current level as 0..100 inclusive. Firmware-reported. */
|
|
@@ -249615,7 +251022,14 @@ ${recipe.triggers.map((t, i) => emitTrigger(t, i)).join("\n\n")}
|
|
|
249615
251022
|
* by the kernel. Read via `device.state.brightness.value` so UI
|
|
249616
251023
|
* sliders surface the current level without polling the provider.
|
|
249617
251024
|
*/
|
|
249618
|
-
runtimeState: BrightnessStatusSchema
|
|
251025
|
+
runtimeState: BrightnessStatusSchema,
|
|
251026
|
+
/**
|
|
251027
|
+
* Runtime-state durability: **session** — live lamp state, re-published by the provider on connect.
|
|
251028
|
+
*
|
|
251029
|
+
* See `RuntimeStateDurability`. Enforced by
|
|
251030
|
+
* `scripts/check-runtime-state-durability.ts`.
|
|
251031
|
+
*/
|
|
251032
|
+
durability: "session"
|
|
249619
251033
|
};
|
|
249620
251034
|
var buttonCapability = {
|
|
249621
251035
|
name: "button",
|
|
@@ -249695,7 +251109,17 @@ ${recipe.triggers.map((t, i) => emitTrigger(t, i)).join("\n\n")}
|
|
|
249695
251109
|
schema: CarbonMonoxideStatusSchema,
|
|
249696
251110
|
kind: "push"
|
|
249697
251111
|
},
|
|
249698
|
-
runtimeState: CarbonMonoxideStatusSchema
|
|
251112
|
+
runtimeState: CarbonMonoxideStatusSchema,
|
|
251113
|
+
/**
|
|
251114
|
+
* Runtime-state durability: **restored** — as `smoke`.
|
|
251115
|
+
*
|
|
251116
|
+
* See `RuntimeStateDurability`. Enforced by
|
|
251117
|
+
* `scripts/check-runtime-state-durability.ts`.
|
|
251118
|
+
*/
|
|
251119
|
+
durability: "restored",
|
|
251120
|
+
/** Clock fields: written, but excluded from the compare that decides
|
|
251121
|
+
* whether persisting is worth a SQLite commit. */
|
|
251122
|
+
volatileStateFields: ["lastChangedAt"]
|
|
249699
251123
|
};
|
|
249700
251124
|
var HvacModeSchema = zod.z.enum([
|
|
249701
251125
|
"off",
|
|
@@ -249824,7 +251248,14 @@ ${recipe.triggers.map((t, i) => emitTrigger(t, i)).join("\n\n")}
|
|
|
249824
251248
|
* the full slice via `device.state.climate-control.value` and refresh
|
|
249825
251249
|
* on every push without re-querying the provider.
|
|
249826
251250
|
*/
|
|
249827
|
-
runtimeState: ClimateControlStatusSchema
|
|
251251
|
+
runtimeState: ClimateControlStatusSchema,
|
|
251252
|
+
/**
|
|
251253
|
+
* Runtime-state durability: **session** — as `brightness`; `currentTemp` moves continuously and is re-published on connect.
|
|
251254
|
+
*
|
|
251255
|
+
* See `RuntimeStateDurability`. Enforced by
|
|
251256
|
+
* `scripts/check-runtime-state-durability.ts`.
|
|
251257
|
+
*/
|
|
251258
|
+
durability: "session"
|
|
249828
251259
|
};
|
|
249829
251260
|
var RgbTripletSchema = zod.z.object({
|
|
249830
251261
|
r: zod.z.number().int().min(0).max(255),
|
|
@@ -249911,7 +251342,14 @@ ${recipe.triggers.map((t, i) => emitTrigger(t, i)).join("\n\n")}
|
|
|
249911
251342
|
* kernel. Read via `device.state.color.value` so UI pickers surface
|
|
249912
251343
|
* the current chromaticity without polling the provider.
|
|
249913
251344
|
*/
|
|
249914
|
-
runtimeState: ColorStatusSchema
|
|
251345
|
+
runtimeState: ColorStatusSchema,
|
|
251346
|
+
/**
|
|
251347
|
+
* Runtime-state durability: **session** — as `brightness`.
|
|
251348
|
+
*
|
|
251349
|
+
* See `RuntimeStateDurability`. Enforced by
|
|
251350
|
+
* `scripts/check-runtime-state-durability.ts`.
|
|
251351
|
+
*/
|
|
251352
|
+
durability: "session"
|
|
249915
251353
|
};
|
|
249916
251354
|
var CONNECTION_TEST_TIMEOUT_MS = 2e4;
|
|
249917
251355
|
var ConnectionTestOutcomeSchema = zod.z.discriminatedUnion("outcome", [
|
|
@@ -249966,7 +251404,17 @@ ${recipe.triggers.map((t, i) => emitTrigger(t, i)).join("\n\n")}
|
|
|
249966
251404
|
schema: ConnectivityStatusSchema,
|
|
249967
251405
|
kind: "push"
|
|
249968
251406
|
},
|
|
249969
|
-
runtimeState: ConnectivityStatusSchema
|
|
251407
|
+
runtimeState: ConnectivityStatusSchema,
|
|
251408
|
+
/**
|
|
251409
|
+
* Runtime-state durability: **restored** — same shape and same argument as `device-status`, for links rather than devices.
|
|
251410
|
+
*
|
|
251411
|
+
* See `RuntimeStateDurability`. Enforced by
|
|
251412
|
+
* `scripts/check-runtime-state-durability.ts`.
|
|
251413
|
+
*/
|
|
251414
|
+
durability: "restored",
|
|
251415
|
+
/** Clock fields: written, but excluded from the compare that decides
|
|
251416
|
+
* whether persisting is worth a SQLite commit. */
|
|
251417
|
+
volatileStateFields: ["lastChangedAt"]
|
|
249970
251418
|
};
|
|
249971
251419
|
var ConsumableItemSchema = zod.z.object({
|
|
249972
251420
|
/** Stable id, e.g. 'main-brush'. */
|
|
@@ -250033,7 +251481,14 @@ ${recipe.triggers.map((t, i) => emitTrigger(t, i)).join("\n\n")}
|
|
|
250033
251481
|
}
|
|
250034
251482
|
}
|
|
250035
251483
|
},
|
|
250036
|
-
runtimeState: ConsumablesStatusSchema.extend({ lastFetchedAt: zod.z.number() })
|
|
251484
|
+
runtimeState: ConsumablesStatusSchema.extend({ lastFetchedAt: zod.z.number() }),
|
|
251485
|
+
/**
|
|
251486
|
+
* Runtime-state durability: **session** — the authority is the appliance; the provider re-reads the whole item array on connect.
|
|
251487
|
+
*
|
|
251488
|
+
* See `RuntimeStateDurability`. Enforced by
|
|
251489
|
+
* `scripts/check-runtime-state-durability.ts`.
|
|
251490
|
+
*/
|
|
251491
|
+
durability: "session"
|
|
250037
251492
|
};
|
|
250038
251493
|
var ContactStatusSchema = zod.z.object({
|
|
250039
251494
|
/** True when the entry is open; false when closed. */
|
|
@@ -250052,7 +251507,17 @@ ${recipe.triggers.map((t, i) => emitTrigger(t, i)).join("\n\n")}
|
|
|
250052
251507
|
schema: ContactStatusSchema,
|
|
250053
251508
|
kind: "push"
|
|
250054
251509
|
},
|
|
250055
|
-
runtimeState: ContactStatusSchema
|
|
251510
|
+
runtimeState: ContactStatusSchema,
|
|
251511
|
+
/**
|
|
251512
|
+
* Runtime-state durability: **restored** — a door left open across a restart must still read open.
|
|
251513
|
+
*
|
|
251514
|
+
* See `RuntimeStateDurability`. Enforced by
|
|
251515
|
+
* `scripts/check-runtime-state-durability.ts`.
|
|
251516
|
+
*/
|
|
251517
|
+
durability: "restored",
|
|
251518
|
+
/** Clock fields: written, but excluded from the compare that decides
|
|
251519
|
+
* whether persisting is worth a SQLite commit. */
|
|
251520
|
+
volatileStateFields: ["lastChangedAt"]
|
|
250056
251521
|
};
|
|
250057
251522
|
var ControlKindSchema = zod.z.enum([
|
|
250058
251523
|
"numeric",
|
|
@@ -250139,7 +251604,14 @@ ${recipe.triggers.map((t, i) => emitTrigger(t, i)).join("\n\n")}
|
|
|
250139
251604
|
* dropdown / text field / date picker) read the slice's discriminant
|
|
250140
251605
|
* and value directly without polling the provider.
|
|
250141
251606
|
*/
|
|
250142
|
-
runtimeState: ControlStatusSchema
|
|
251607
|
+
runtimeState: ControlStatusSchema,
|
|
251608
|
+
/**
|
|
251609
|
+
* Runtime-state durability: **session** — a generic control mirrors an external entity that re-publishes on connect; the options array is re-derived with it.
|
|
251610
|
+
*
|
|
251611
|
+
* See `RuntimeStateDurability`. Enforced by
|
|
251612
|
+
* `scripts/check-runtime-state-durability.ts`.
|
|
251613
|
+
*/
|
|
251614
|
+
durability: "session"
|
|
250143
251615
|
};
|
|
250144
251616
|
var CoverStateSchema = zod.z.enum([
|
|
250145
251617
|
"open",
|
|
@@ -250201,7 +251673,17 @@ ${recipe.triggers.map((t, i) => emitTrigger(t, i)).join("\n\n")}
|
|
|
250201
251673
|
* Runtime-state slice — mirrored by the kernel. UI controls watch
|
|
250202
251674
|
* the slice for live position changes during a move.
|
|
250203
251675
|
*/
|
|
250204
|
-
runtimeState: CoverStatusSchema
|
|
251676
|
+
runtimeState: CoverStatusSchema,
|
|
251677
|
+
/**
|
|
251678
|
+
* Runtime-state durability: **restored** — position survives a restart on the device; the mirror should agree at boot rather than read blank.
|
|
251679
|
+
*
|
|
251680
|
+
* See `RuntimeStateDurability`. Enforced by
|
|
251681
|
+
* `scripts/check-runtime-state-durability.ts`.
|
|
251682
|
+
*/
|
|
251683
|
+
durability: "restored",
|
|
251684
|
+
/** Clock fields: written, but excluded from the compare that decides
|
|
251685
|
+
* whether persisting is worth a SQLite commit. */
|
|
251686
|
+
volatileStateFields: ["lastChangedAt"]
|
|
250205
251687
|
};
|
|
250206
251688
|
var DayNightModeSchema = zod.z.enum([
|
|
250207
251689
|
"auto",
|
|
@@ -250262,7 +251744,17 @@ ${recipe.triggers.map((t, i) => emitTrigger(t, i)).join("\n\n")}
|
|
|
250262
251744
|
schema: DayNightStatusSchema,
|
|
250263
251745
|
kind: "poll"
|
|
250264
251746
|
},
|
|
250265
|
-
runtimeState: DayNightStatusSchema
|
|
251747
|
+
runtimeState: DayNightStatusSchema,
|
|
251748
|
+
/**
|
|
251749
|
+
* Runtime-state durability: **restored** — operator-set IR-cut behaviour; mutation-driven.
|
|
251750
|
+
*
|
|
251751
|
+
* See `RuntimeStateDurability`. Enforced by
|
|
251752
|
+
* `scripts/check-runtime-state-durability.ts`.
|
|
251753
|
+
*/
|
|
251754
|
+
durability: "restored",
|
|
251755
|
+
/** Clock fields: written, but excluded from the compare that decides
|
|
251756
|
+
* whether persisting is worth a SQLite commit. */
|
|
251757
|
+
volatileStateFields: ["lastFetchedAt"]
|
|
250266
251758
|
};
|
|
250267
251759
|
var DeviceStatusSchema = zod.z.object({
|
|
250268
251760
|
/**
|
|
@@ -250295,7 +251787,17 @@ ${recipe.triggers.map((t, i) => emitTrigger(t, i)).join("\n\n")}
|
|
|
250295
251787
|
schema: DeviceStatusSchema,
|
|
250296
251788
|
kind: "push"
|
|
250297
251789
|
},
|
|
250298
|
-
runtimeState: DeviceStatusSchema
|
|
251790
|
+
runtimeState: DeviceStatusSchema,
|
|
251791
|
+
/**
|
|
251792
|
+
* Runtime-state durability: **restored** — the previous observation is what makes the first reading after a restart a COMPARISON instead of a phantom transition (D130). 32 real flips across 16 devices in 25 min — the busiest slice in the cold half.
|
|
251793
|
+
*
|
|
251794
|
+
* See `RuntimeStateDurability`. Enforced by
|
|
251795
|
+
* `scripts/check-runtime-state-durability.ts`.
|
|
251796
|
+
*/
|
|
251797
|
+
durability: "restored",
|
|
251798
|
+
/** Clock fields: written, but excluded from the compare that decides
|
|
251799
|
+
* whether persisting is worth a SQLite commit. */
|
|
251800
|
+
volatileStateFields: ["lastChangedAt"]
|
|
250299
251801
|
};
|
|
250300
251802
|
var DoorbellStatusSchema = zod.z.object({
|
|
250301
251803
|
/** Ms epoch of the last press. null = never observed since this provider started. */
|
|
@@ -250335,7 +251837,14 @@ ${recipe.triggers.map((t, i) => emitTrigger(t, i)).join("\n\n")}
|
|
|
250335
251837
|
* `device.state.doorbell.value`. UIs can show "last ring 5m ago"
|
|
250336
251838
|
* without subscribing.
|
|
250337
251839
|
*/
|
|
250338
|
-
runtimeState: DoorbellStatusSchema
|
|
251840
|
+
runtimeState: DoorbellStatusSchema,
|
|
251841
|
+
/**
|
|
251842
|
+
* Runtime-state durability: **restored** — a monotonic accumulator: the slice IS the record. `lastPressedAt` is content here, not a clock, so it is deliberately NOT volatile.
|
|
251843
|
+
*
|
|
251844
|
+
* See `RuntimeStateDurability`. Enforced by
|
|
251845
|
+
* `scripts/check-runtime-state-durability.ts`.
|
|
251846
|
+
*/
|
|
251847
|
+
durability: "restored"
|
|
250339
251848
|
};
|
|
250340
251849
|
var EnumSensorDateTimeFormatSchema = zod.z.enum([
|
|
250341
251850
|
"date",
|
|
@@ -250365,7 +251874,17 @@ ${recipe.triggers.map((t, i) => emitTrigger(t, i)).join("\n\n")}
|
|
|
250365
251874
|
schema: EnumSensorStatusSchema,
|
|
250366
251875
|
kind: "push"
|
|
250367
251876
|
},
|
|
250368
|
-
runtimeState: EnumSensorStatusSchema
|
|
251877
|
+
runtimeState: EnumSensorStatusSchema,
|
|
251878
|
+
/**
|
|
251879
|
+
* Runtime-state durability: **restored** — as `numeric-sensor`; 80 devices.
|
|
251880
|
+
*
|
|
251881
|
+
* See `RuntimeStateDurability`. Enforced by
|
|
251882
|
+
* `scripts/check-runtime-state-durability.ts`.
|
|
251883
|
+
*/
|
|
251884
|
+
durability: "restored",
|
|
251885
|
+
/** Clock fields: written, but excluded from the compare that decides
|
|
251886
|
+
* whether persisting is worth a SQLite commit. */
|
|
251887
|
+
volatileStateFields: ["lastFetchedAt"]
|
|
250369
251888
|
};
|
|
250370
251889
|
var EventFireSchema = zod.z.object({
|
|
250371
251890
|
deviceId: zod.z.number(),
|
|
@@ -250391,7 +251910,14 @@ ${recipe.triggers.map((t, i) => emitTrigger(t, i)).join("\n\n")}
|
|
|
250391
251910
|
schema: EventEmitterStatusSchema,
|
|
250392
251911
|
kind: "push"
|
|
250393
251912
|
},
|
|
250394
|
-
runtimeState: EventEmitterStatusSchema
|
|
251913
|
+
runtimeState: EventEmitterStatusSchema,
|
|
251914
|
+
/**
|
|
251915
|
+
* Runtime-state durability: **session** — `eventCountSinceStart` names its own scope.
|
|
251916
|
+
*
|
|
251917
|
+
* See `RuntimeStateDurability`. Enforced by
|
|
251918
|
+
* `scripts/check-runtime-state-durability.ts`.
|
|
251919
|
+
*/
|
|
251920
|
+
durability: "session"
|
|
250395
251921
|
};
|
|
250396
251922
|
var EventItemSchema = zod.z.object({
|
|
250397
251923
|
id: zod.z.string(),
|
|
@@ -250690,7 +252216,14 @@ ${recipe.triggers.map((t, i) => emitTrigger(t, i)).join("\n\n")}
|
|
|
250690
252216
|
* Runtime-state slice — mirrored by the kernel. UI fan speed
|
|
250691
252217
|
* sliders read `percentage` for live updates.
|
|
250692
252218
|
*/
|
|
250693
|
-
runtimeState: FanControlStatusSchema
|
|
252219
|
+
runtimeState: FanControlStatusSchema,
|
|
252220
|
+
/**
|
|
252221
|
+
* Runtime-state durability: **session** — as `brightness`.
|
|
252222
|
+
*
|
|
252223
|
+
* See `RuntimeStateDurability`. Enforced by
|
|
252224
|
+
* `scripts/check-runtime-state-durability.ts`.
|
|
252225
|
+
*/
|
|
252226
|
+
durability: "session"
|
|
250694
252227
|
};
|
|
250695
252228
|
var FeatureProbeStatusSchema = zod.z.object({
|
|
250696
252229
|
/**
|
|
@@ -250743,7 +252276,14 @@ ${recipe.triggers.map((t, i) => emitTrigger(t, i)).join("\n\n")}
|
|
|
250743
252276
|
schema: FeatureProbeStatusSchema,
|
|
250744
252277
|
kind: "push"
|
|
250745
252278
|
},
|
|
250746
|
-
runtimeState: FeatureProbeStatusSchema
|
|
252279
|
+
runtimeState: FeatureProbeStatusSchema,
|
|
252280
|
+
/**
|
|
252281
|
+
* Runtime-state durability: **session** — per-session by definition — `lastProbedAt` means "this worker completed a probe THIS session", which is why the mirror seed already blanks it. Persisting it only creates something to blank.
|
|
252282
|
+
*
|
|
252283
|
+
* See `RuntimeStateDurability`. Enforced by
|
|
252284
|
+
* `scripts/check-runtime-state-durability.ts`.
|
|
252285
|
+
*/
|
|
252286
|
+
durability: "session"
|
|
250747
252287
|
};
|
|
250748
252288
|
var FloodStatusSchema = zod.z.object({
|
|
250749
252289
|
/** True when leak is currently detected. */
|
|
@@ -250762,7 +252302,17 @@ ${recipe.triggers.map((t, i) => emitTrigger(t, i)).join("\n\n")}
|
|
|
250762
252302
|
schema: FloodStatusSchema,
|
|
250763
252303
|
kind: "push"
|
|
250764
252304
|
},
|
|
250765
|
-
runtimeState: FloodStatusSchema
|
|
252305
|
+
runtimeState: FloodStatusSchema,
|
|
252306
|
+
/**
|
|
252307
|
+
* Runtime-state durability: **restored** — as `smoke`.
|
|
252308
|
+
*
|
|
252309
|
+
* See `RuntimeStateDurability`. Enforced by
|
|
252310
|
+
* `scripts/check-runtime-state-durability.ts`.
|
|
252311
|
+
*/
|
|
252312
|
+
durability: "restored",
|
|
252313
|
+
/** Clock fields: written, but excluded from the compare that decides
|
|
252314
|
+
* whether persisting is worth a SQLite commit. */
|
|
252315
|
+
volatileStateFields: ["lastChangedAt"]
|
|
250766
252316
|
};
|
|
250767
252317
|
var GasStatusSchema = zod.z.object({
|
|
250768
252318
|
detected: zod.z.boolean(),
|
|
@@ -250780,7 +252330,17 @@ ${recipe.triggers.map((t, i) => emitTrigger(t, i)).join("\n\n")}
|
|
|
250780
252330
|
schema: GasStatusSchema,
|
|
250781
252331
|
kind: "push"
|
|
250782
252332
|
},
|
|
250783
|
-
runtimeState: GasStatusSchema
|
|
252333
|
+
runtimeState: GasStatusSchema,
|
|
252334
|
+
/**
|
|
252335
|
+
* Runtime-state durability: **restored** — as `smoke`.
|
|
252336
|
+
*
|
|
252337
|
+
* See `RuntimeStateDurability`. Enforced by
|
|
252338
|
+
* `scripts/check-runtime-state-durability.ts`.
|
|
252339
|
+
*/
|
|
252340
|
+
durability: "restored",
|
|
252341
|
+
/** Clock fields: written, but excluded from the compare that decides
|
|
252342
|
+
* whether persisting is worth a SQLite commit. */
|
|
252343
|
+
volatileStateFields: ["lastChangedAt"]
|
|
250784
252344
|
};
|
|
250785
252345
|
var HumidifierStatusSchema = zod.z.object({
|
|
250786
252346
|
/** Whether the humidifier is currently on. */
|
|
@@ -250841,7 +252401,14 @@ ${recipe.triggers.map((t, i) => emitTrigger(t, i)).join("\n\n")}
|
|
|
250841
252401
|
* Runtime-state slice — mirrored by the kernel. UI controls watch the
|
|
250842
252402
|
* slice for live humidity / mode changes.
|
|
250843
252403
|
*/
|
|
250844
|
-
runtimeState: HumidifierStatusSchema
|
|
252404
|
+
runtimeState: HumidifierStatusSchema,
|
|
252405
|
+
/**
|
|
252406
|
+
* Runtime-state durability: **session** — as `climate-control`.
|
|
252407
|
+
*
|
|
252408
|
+
* See `RuntimeStateDurability`. Enforced by
|
|
252409
|
+
* `scripts/check-runtime-state-durability.ts`.
|
|
252410
|
+
*/
|
|
252411
|
+
durability: "session"
|
|
250845
252412
|
};
|
|
250846
252413
|
var HumiditySensorStatusSchema = zod.z.object({
|
|
250847
252414
|
/** Current relative humidity, 0..100. */
|
|
@@ -250869,7 +252436,17 @@ ${recipe.triggers.map((t, i) => emitTrigger(t, i)).join("\n\n")}
|
|
|
250869
252436
|
schema: HumiditySensorStatusSchema,
|
|
250870
252437
|
kind: "push"
|
|
250871
252438
|
},
|
|
250872
|
-
runtimeState: HumiditySensorStatusSchema
|
|
252439
|
+
runtimeState: HumiditySensorStatusSchema,
|
|
252440
|
+
/**
|
|
252441
|
+
* Runtime-state durability: **restored** — as `numeric-sensor` (67 of 75 writes were the clock alone).
|
|
252442
|
+
*
|
|
252443
|
+
* See `RuntimeStateDurability`. Enforced by
|
|
252444
|
+
* `scripts/check-runtime-state-durability.ts`.
|
|
252445
|
+
*/
|
|
252446
|
+
durability: "restored",
|
|
252447
|
+
/** Clock fields: written, but excluded from the compare that decides
|
|
252448
|
+
* whether persisting is worth a SQLite commit. */
|
|
252449
|
+
volatileStateFields: ["lastFetchedAt"]
|
|
250873
252450
|
};
|
|
250874
252451
|
var ImageStatusSchema = zod.z.object({
|
|
250875
252452
|
/** Absolute signed URL the browser loads directly. Null when the
|
|
@@ -250893,7 +252470,14 @@ ${recipe.triggers.map((t, i) => emitTrigger(t, i)).join("\n\n")}
|
|
|
250893
252470
|
* Runtime-state slice — mirrored by the kernel. The UI reads `url`
|
|
250894
252471
|
* directly and renders the still image.
|
|
250895
252472
|
*/
|
|
250896
|
-
runtimeState: ImageStatusSchema
|
|
252473
|
+
runtimeState: ImageStatusSchema,
|
|
252474
|
+
/**
|
|
252475
|
+
* Runtime-state durability: **session** — a snapshot URL is a session-scoped handle; a restored one points at nothing.
|
|
252476
|
+
*
|
|
252477
|
+
* See `RuntimeStateDurability`. Enforced by
|
|
252478
|
+
* `scripts/check-runtime-state-durability.ts`.
|
|
252479
|
+
*/
|
|
252480
|
+
durability: "session"
|
|
250897
252481
|
};
|
|
250898
252482
|
var ImageRotateSchema = zod.z.enum([
|
|
250899
252483
|
"0",
|
|
@@ -250994,7 +252578,17 @@ ${recipe.triggers.map((t, i) => emitTrigger(t, i)).join("\n\n")}
|
|
|
250994
252578
|
schema: ImageSettingsStatusSchema,
|
|
250995
252579
|
kind: "poll"
|
|
250996
252580
|
},
|
|
250997
|
-
runtimeState: ImageSettingsStatusSchema
|
|
252581
|
+
runtimeState: ImageSettingsStatusSchema,
|
|
252582
|
+
/**
|
|
252583
|
+
* Runtime-state durability: **restored** — operator-set camera imaging; mutation-driven.
|
|
252584
|
+
*
|
|
252585
|
+
* See `RuntimeStateDurability`. Enforced by
|
|
252586
|
+
* `scripts/check-runtime-state-durability.ts`.
|
|
252587
|
+
*/
|
|
252588
|
+
durability: "restored",
|
|
252589
|
+
/** Clock fields: written, but excluded from the compare that decides
|
|
252590
|
+
* whether persisting is worth a SQLite commit. */
|
|
252591
|
+
volatileStateFields: ["lastFetchedAt"]
|
|
250998
252592
|
};
|
|
250999
252593
|
var IntegrationWithStateSchema = zod.z.object({
|
|
251000
252594
|
id: zod.z.string(),
|
|
@@ -251325,7 +252919,14 @@ ${recipe.triggers.map((t, i) => emitTrigger(t, i)).join("\n\n")}
|
|
|
251325
252919
|
* Runtime-state slice — mirrored by the kernel. UI controls watch the
|
|
251326
252920
|
* slice for live activity + battery changes.
|
|
251327
252921
|
*/
|
|
251328
|
-
runtimeState: LawnMowerControlStatusSchema
|
|
252922
|
+
runtimeState: LawnMowerControlStatusSchema,
|
|
252923
|
+
/**
|
|
252924
|
+
* Runtime-state durability: **session** — as `vacuum-control`.
|
|
252925
|
+
*
|
|
252926
|
+
* See `RuntimeStateDurability`. Enforced by
|
|
252927
|
+
* `scripts/check-runtime-state-durability.ts`.
|
|
252928
|
+
*/
|
|
252929
|
+
durability: "session"
|
|
251329
252930
|
};
|
|
251330
252931
|
var InterfaceKindEnum = zod.z.enum([
|
|
251331
252932
|
"lan",
|
|
@@ -251574,7 +253175,17 @@ ${recipe.triggers.map((t, i) => emitTrigger(t, i)).join("\n\n")}
|
|
|
251574
253175
|
* read `state` and disable themselves during `locking`/`unlocking`
|
|
251575
253176
|
* transitions.
|
|
251576
253177
|
*/
|
|
251577
|
-
runtimeState: LockControlStatusSchema
|
|
253178
|
+
runtimeState: LockControlStatusSchema,
|
|
253179
|
+
/**
|
|
253180
|
+
* Runtime-state durability: **restored** — a lock left locked must still read locked.
|
|
253181
|
+
*
|
|
253182
|
+
* See `RuntimeStateDurability`. Enforced by
|
|
253183
|
+
* `scripts/check-runtime-state-durability.ts`.
|
|
253184
|
+
*/
|
|
253185
|
+
durability: "restored",
|
|
253186
|
+
/** Clock fields: written, but excluded from the compare that decides
|
|
253187
|
+
* whether persisting is worth a SQLite commit. */
|
|
253188
|
+
volatileStateFields: ["lastChangedAt"]
|
|
251578
253189
|
};
|
|
251579
253190
|
var MediaPlayerStateSchema = zod.z.enum([
|
|
251580
253191
|
"off",
|
|
@@ -251724,7 +253335,14 @@ ${recipe.triggers.map((t, i) => emitTrigger(t, i)).join("\n\n")}
|
|
|
251724
253335
|
* full slice for live now-playing, volume, and progress updates
|
|
251725
253336
|
* without polling.
|
|
251726
253337
|
*/
|
|
251727
|
-
runtimeState: MediaPlayerStatusSchema
|
|
253338
|
+
runtimeState: MediaPlayerStatusSchema,
|
|
253339
|
+
/**
|
|
253340
|
+
* Runtime-state durability: **session** — a restored transport position describes a playback that stopped when the hub did.
|
|
253341
|
+
*
|
|
253342
|
+
* See `RuntimeStateDurability`. Enforced by
|
|
253343
|
+
* `scripts/check-runtime-state-durability.ts`.
|
|
253344
|
+
*/
|
|
253345
|
+
durability: "session"
|
|
251728
253346
|
};
|
|
251729
253347
|
var MeshEndpointSchema = zod.z.object({
|
|
251730
253348
|
/** Stable identifier within the provider (e.g. `mesh-ipv4`, `magicdns`, `funnel`). */
|
|
@@ -252008,7 +253626,14 @@ ${recipe.triggers.map((t, i) => emitTrigger(t, i)).join("\n\n")}
|
|
|
252008
253626
|
* `device.state.motion.value`. Reads never invoke the provider, so
|
|
252009
253627
|
* UIs and other addons can poll the cached state safely.
|
|
252010
253628
|
*/
|
|
252011
|
-
runtimeState: MotionStatusSchema
|
|
253629
|
+
runtimeState: MotionStatusSchema,
|
|
253630
|
+
/**
|
|
253631
|
+
* Runtime-state durability: **session** — self-clearing by construction (`autoClearAfterMs`); a restored `detected: true` is a frozen event, and the next frame re-publishes the real one.
|
|
253632
|
+
*
|
|
253633
|
+
* See `RuntimeStateDurability`. Enforced by
|
|
253634
|
+
* `scripts/check-runtime-state-durability.ts`.
|
|
253635
|
+
*/
|
|
253636
|
+
durability: "session"
|
|
252012
253637
|
};
|
|
252013
253638
|
var MotionTriggerStatusSchema = zod.z.object({
|
|
252014
253639
|
enabled: zod.z.boolean(),
|
|
@@ -252045,7 +253670,14 @@ ${recipe.triggers.map((t, i) => emitTrigger(t, i)).join("\n\n")}
|
|
|
252045
253670
|
schema: MotionTriggerStatusSchema,
|
|
252046
253671
|
kind: "command-driven"
|
|
252047
253672
|
},
|
|
252048
|
-
runtimeState: MotionTriggerRuntimeStateSchema
|
|
253673
|
+
runtimeState: MotionTriggerRuntimeStateSchema,
|
|
253674
|
+
/**
|
|
253675
|
+
* Runtime-state durability: **session** — the authority for motion-trigger enablement is the provider's own config; the slice is a mirror of it, re-published on connect.
|
|
253676
|
+
*
|
|
253677
|
+
* See `RuntimeStateDurability`. Enforced by
|
|
253678
|
+
* `scripts/check-runtime-state-durability.ts`.
|
|
253679
|
+
*/
|
|
253680
|
+
durability: "session"
|
|
252049
253681
|
};
|
|
252050
253682
|
var MotionZoneRegionSchema = zod.z.object({
|
|
252051
253683
|
id: zod.z.number(),
|
|
@@ -252100,7 +253732,17 @@ ${recipe.triggers.map((t, i) => emitTrigger(t, i)).join("\n\n")}
|
|
|
252100
253732
|
schema: MotionZoneStatusSchema,
|
|
252101
253733
|
kind: "poll"
|
|
252102
253734
|
},
|
|
252103
|
-
runtimeState: MotionZoneStatusSchema
|
|
253735
|
+
runtimeState: MotionZoneStatusSchema,
|
|
253736
|
+
/**
|
|
253737
|
+
* Runtime-state durability: **restored** — the 14 KB polygon list is the single largest slice on the fleet and has not changed since the operator drew it. Highest value per byte in the table.
|
|
253738
|
+
*
|
|
253739
|
+
* See `RuntimeStateDurability`. Enforced by
|
|
253740
|
+
* `scripts/check-runtime-state-durability.ts`.
|
|
253741
|
+
*/
|
|
253742
|
+
durability: "restored",
|
|
253743
|
+
/** Clock fields: written, but excluded from the compare that decides
|
|
253744
|
+
* whether persisting is worth a SQLite commit. */
|
|
253745
|
+
volatileStateFields: ["lastFetchedAt"]
|
|
252104
253746
|
};
|
|
252105
253747
|
var NativeObjectClassEnum = zod.z.enum([
|
|
252106
253748
|
"person",
|
|
@@ -252163,7 +253805,17 @@ ${recipe.triggers.map((t, i) => emitTrigger(t, i)).join("\n\n")}
|
|
|
252163
253805
|
schema: NativeObjectDetectionStatusSchema,
|
|
252164
253806
|
kind: "push"
|
|
252165
253807
|
},
|
|
252166
|
-
runtimeState: NativeObjectDetectionRuntimeStateSchema
|
|
253808
|
+
runtimeState: NativeObjectDetectionRuntimeStateSchema,
|
|
253809
|
+
/**
|
|
253810
|
+
* Runtime-state durability: **restored** — `enabled` is an operator toggle on a camera whose refresh is a no-op and whose staleMs is Infinity. There is no hardware value to re-read — losing it loses the setting.
|
|
253811
|
+
*
|
|
253812
|
+
* See `RuntimeStateDurability`. Enforced by
|
|
253813
|
+
* `scripts/check-runtime-state-durability.ts`.
|
|
253814
|
+
*/
|
|
253815
|
+
durability: "restored",
|
|
253816
|
+
/** Clock fields: written, but excluded from the compare that decides
|
|
253817
|
+
* whether persisting is worth a SQLite commit. */
|
|
253818
|
+
volatileStateFields: ["lastFetchedAt"]
|
|
252167
253819
|
};
|
|
252168
253820
|
var StreamNetworkStatsSchema = zod.z.object({
|
|
252169
253821
|
nominalBitrateKbps: zod.z.number(),
|
|
@@ -252486,7 +254138,14 @@ ${recipe.triggers.map((t, i) => emitTrigger(t, i)).join("\n\n")}
|
|
|
252486
254138
|
* form reads `supports` to gate optional fields; history pane reads
|
|
252487
254139
|
* `lastSentAt` / `lastError` / `queueDepth`.
|
|
252488
254140
|
*/
|
|
252489
|
-
runtimeState: NotifierStatusSchema
|
|
254141
|
+
runtimeState: NotifierStatusSchema,
|
|
254142
|
+
/**
|
|
254143
|
+
* Runtime-state durability: **session** — live queue depth and last-send state; a restored queue depth describes a queue that no longer exists.
|
|
254144
|
+
*
|
|
254145
|
+
* See `RuntimeStateDurability`. Enforced by
|
|
254146
|
+
* `scripts/check-runtime-state-durability.ts`.
|
|
254147
|
+
*/
|
|
254148
|
+
durability: "session"
|
|
252490
254149
|
};
|
|
252491
254150
|
var NumericSensorStatusSchema = zod.z.object({
|
|
252492
254151
|
value: zod.z.number(),
|
|
@@ -252512,7 +254171,17 @@ ${recipe.triggers.map((t, i) => emitTrigger(t, i)).join("\n\n")}
|
|
|
252512
254171
|
schema: NumericSensorStatusSchema,
|
|
252513
254172
|
kind: "push"
|
|
252514
254173
|
},
|
|
252515
|
-
runtimeState: NumericSensorStatusSchema
|
|
254174
|
+
runtimeState: NumericSensorStatusSchema,
|
|
254175
|
+
/**
|
|
254176
|
+
* Runtime-state durability: **restored** — polled value, low churn once the clock is excluded (251 of 669 writes were the clock alone); restoring it removes the cold window before the first poll.
|
|
254177
|
+
*
|
|
254178
|
+
* See `RuntimeStateDurability`. Enforced by
|
|
254179
|
+
* `scripts/check-runtime-state-durability.ts`.
|
|
254180
|
+
*/
|
|
254181
|
+
durability: "restored",
|
|
254182
|
+
/** Clock fields: written, but excluded from the compare that decides
|
|
254183
|
+
* whether persisting is worth a SQLite commit. */
|
|
254184
|
+
volatileStateFields: ["lastFetchedAt"]
|
|
252516
254185
|
};
|
|
252517
254186
|
var OsdOverlayKindEnum = zod.z.enum([
|
|
252518
254187
|
"text",
|
|
@@ -252937,7 +254606,14 @@ ${recipe.triggers.map((t, i) => emitTrigger(t, i)).join("\n\n")}
|
|
|
252937
254606
|
* the full slice via `device.state.petFeeder.value` and refresh on
|
|
252938
254607
|
* every poll without re-querying the provider.
|
|
252939
254608
|
*/
|
|
252940
|
-
runtimeState: PetFeederStatusSchema
|
|
254609
|
+
runtimeState: PetFeederStatusSchema,
|
|
254610
|
+
/**
|
|
254611
|
+
* Runtime-state durability: **session** — live appliance state re-published on connect.
|
|
254612
|
+
*
|
|
254613
|
+
* See `RuntimeStateDurability`. Enforced by
|
|
254614
|
+
* `scripts/check-runtime-state-durability.ts`.
|
|
254615
|
+
*/
|
|
254616
|
+
durability: "session"
|
|
252941
254617
|
};
|
|
252942
254618
|
var VehicleSchema = zod.z.object({
|
|
252943
254619
|
id: zod.z.string(),
|
|
@@ -253271,7 +254947,17 @@ ${recipe.triggers.map((t, i) => emitTrigger(t, i)).join("\n\n")}
|
|
|
253271
254947
|
schema: PowerMeterStatusSchema,
|
|
253272
254948
|
kind: "push"
|
|
253273
254949
|
},
|
|
253274
|
-
runtimeState: PowerMeterStatusSchema
|
|
254950
|
+
runtimeState: PowerMeterStatusSchema,
|
|
254951
|
+
/**
|
|
254952
|
+
* Runtime-state durability: **restored** — as `numeric-sensor`; `kwhTotal` is an accumulator whose restored value is the baseline.
|
|
254953
|
+
*
|
|
254954
|
+
* See `RuntimeStateDurability`. Enforced by
|
|
254955
|
+
* `scripts/check-runtime-state-durability.ts`.
|
|
254956
|
+
*/
|
|
254957
|
+
durability: "restored",
|
|
254958
|
+
/** Clock fields: written, but excluded from the compare that decides
|
|
254959
|
+
* whether persisting is worth a SQLite commit. */
|
|
254960
|
+
volatileStateFields: ["lastFetchedAt"]
|
|
253275
254961
|
};
|
|
253276
254962
|
var GpsLocationSchema = zod.z.object({
|
|
253277
254963
|
/** Latitude in decimal degrees, -90..90. */
|
|
@@ -253312,7 +254998,17 @@ ${recipe.triggers.map((t, i) => emitTrigger(t, i)).join("\n\n")}
|
|
|
253312
254998
|
* the map pin is rendered (use `DeviceFeature.PresenceGps` for the
|
|
253313
254999
|
* pre-fetch fast-path check).
|
|
253314
255000
|
*/
|
|
253315
|
-
runtimeState: PresenceStatusSchema
|
|
255001
|
+
runtimeState: PresenceStatusSchema,
|
|
255002
|
+
/**
|
|
255003
|
+
* Runtime-state durability: **restored** — occupancy-relevant: the restored state is what an occupancy rule compares the first post-restart observation against.
|
|
255004
|
+
*
|
|
255005
|
+
* See `RuntimeStateDurability`. Enforced by
|
|
255006
|
+
* `scripts/check-runtime-state-durability.ts`.
|
|
255007
|
+
*/
|
|
255008
|
+
durability: "restored",
|
|
255009
|
+
/** Clock fields: written, but excluded from the compare that decides
|
|
255010
|
+
* whether persisting is worth a SQLite commit. */
|
|
255011
|
+
volatileStateFields: ["lastChangedAt"]
|
|
253316
255012
|
};
|
|
253317
255013
|
var PressureSensorStatusSchema = zod.z.object({
|
|
253318
255014
|
/** Current pressure in hPa. */
|
|
@@ -253340,7 +255036,17 @@ ${recipe.triggers.map((t, i) => emitTrigger(t, i)).join("\n\n")}
|
|
|
253340
255036
|
schema: PressureSensorStatusSchema,
|
|
253341
255037
|
kind: "push"
|
|
253342
255038
|
},
|
|
253343
|
-
runtimeState: PressureSensorStatusSchema
|
|
255039
|
+
runtimeState: PressureSensorStatusSchema,
|
|
255040
|
+
/**
|
|
255041
|
+
* Runtime-state durability: **restored** — as `numeric-sensor`.
|
|
255042
|
+
*
|
|
255043
|
+
* See `RuntimeStateDurability`. Enforced by
|
|
255044
|
+
* `scripts/check-runtime-state-durability.ts`.
|
|
255045
|
+
*/
|
|
255046
|
+
durability: "restored",
|
|
255047
|
+
/** Clock fields: written, but excluded from the compare that decides
|
|
255048
|
+
* whether persisting is worth a SQLite commit. */
|
|
255049
|
+
volatileStateFields: ["lastFetchedAt"]
|
|
253344
255050
|
};
|
|
253345
255051
|
var PrivacyMaskShapeSchema = zod.z.discriminatedUnion("kind", [MaskRectShapeSchema, MaskPolygonShapeSchema]);
|
|
253346
255052
|
var PrivacyMaskRegionSchema = zod.z.object({
|
|
@@ -253439,7 +255145,17 @@ ${recipe.triggers.map((t, i) => emitTrigger(t, i)).join("\n\n")}
|
|
|
253439
255145
|
schema: PrivacyMaskStatusSchema,
|
|
253440
255146
|
kind: "poll"
|
|
253441
255147
|
},
|
|
253442
|
-
runtimeState: PrivacyMaskStatusSchema
|
|
255148
|
+
runtimeState: PrivacyMaskStatusSchema,
|
|
255149
|
+
/**
|
|
255150
|
+
* Runtime-state durability: **restored** — operator-drawn regions, zero real churn — 22 writes in 25 minutes, every one of them the clock.
|
|
255151
|
+
*
|
|
255152
|
+
* See `RuntimeStateDurability`. Enforced by
|
|
255153
|
+
* `scripts/check-runtime-state-durability.ts`.
|
|
255154
|
+
*/
|
|
255155
|
+
durability: "restored",
|
|
255156
|
+
/** Clock fields: written, but excluded from the compare that decides
|
|
255157
|
+
* whether persisting is worth a SQLite commit. */
|
|
255158
|
+
volatileStateFields: ["lastFetchedAt"]
|
|
253443
255159
|
};
|
|
253444
255160
|
function summarisePrivacyAudio(profiles) {
|
|
253445
255161
|
if (profiles.length === 0) return null;
|
|
@@ -253629,7 +255345,14 @@ ${recipe.triggers.map((t, i) => emitTrigger(t, i)).join("\n\n")}
|
|
|
253629
255345
|
* fetch / cache / fallback logic out of the four cap methods —
|
|
253630
255346
|
* they become trampolines over `runtimeState`.
|
|
253631
255347
|
*/
|
|
253632
|
-
runtimeState: PtzAutotrackRuntimeStateSchema
|
|
255348
|
+
runtimeState: PtzAutotrackRuntimeStateSchema,
|
|
255349
|
+
/**
|
|
255350
|
+
* Runtime-state durability: **session** — mirrors the camera's own autotrack config, re-read on connect.
|
|
255351
|
+
*
|
|
255352
|
+
* See `RuntimeStateDurability`. Enforced by
|
|
255353
|
+
* `scripts/check-runtime-state-durability.ts`.
|
|
255354
|
+
*/
|
|
255355
|
+
durability: "session"
|
|
253633
255356
|
};
|
|
253634
255357
|
var rebootCapability = {
|
|
253635
255358
|
name: "reboot",
|
|
@@ -254299,7 +256022,14 @@ ${recipe.triggers.map((t, i) => emitTrigger(t, i)).join("\n\n")}
|
|
|
254299
256022
|
schema: SceneMonitorStatusSchema,
|
|
254300
256023
|
kind: "push"
|
|
254301
256024
|
},
|
|
254302
|
-
runtimeState: SceneMonitorStatusSchema
|
|
256025
|
+
runtimeState: SceneMonitorStatusSchema,
|
|
256026
|
+
/**
|
|
256027
|
+
* Runtime-state durability: **session** — re-derived from the current scene on the next evaluation.
|
|
256028
|
+
*
|
|
256029
|
+
* See `RuntimeStateDurability`. Enforced by
|
|
256030
|
+
* `scripts/check-runtime-state-durability.ts`.
|
|
256031
|
+
*/
|
|
256032
|
+
durability: "session"
|
|
254303
256033
|
};
|
|
254304
256034
|
var ZoneRuleModeEnum = zod.z.enum(["include", "exclude"]);
|
|
254305
256035
|
var ZoneRuleSchema = zod.z.object({
|
|
@@ -254401,7 +256131,14 @@ ${recipe.triggers.map((t, i) => emitTrigger(t, i)).join("\n\n")}
|
|
|
254401
256131
|
* `isRunning` to render a spinner during execution and surfaces
|
|
254402
256132
|
* `lastError` / `lastRunSuccess` in the recent-runs panel.
|
|
254403
256133
|
*/
|
|
254404
|
-
runtimeState: ScriptRunnerStatusSchema
|
|
256134
|
+
runtimeState: ScriptRunnerStatusSchema,
|
|
256135
|
+
/**
|
|
256136
|
+
* Runtime-state durability: **session** — a restored `isRunning: true` describes a process that died with the previous hub.
|
|
256137
|
+
*
|
|
256138
|
+
* See `RuntimeStateDurability`. Enforced by
|
|
256139
|
+
* `scripts/check-runtime-state-durability.ts`.
|
|
256140
|
+
*/
|
|
256141
|
+
durability: "session"
|
|
254405
256142
|
};
|
|
254406
256143
|
var SmokeStatusSchema = zod.z.object({
|
|
254407
256144
|
detected: zod.z.boolean(),
|
|
@@ -254419,7 +256156,17 @@ ${recipe.triggers.map((t, i) => emitTrigger(t, i)).join("\n\n")}
|
|
|
254419
256156
|
schema: SmokeStatusSchema,
|
|
254420
256157
|
kind: "push"
|
|
254421
256158
|
},
|
|
254422
|
-
runtimeState: SmokeStatusSchema
|
|
256159
|
+
runtimeState: SmokeStatusSchema,
|
|
256160
|
+
/**
|
|
256161
|
+
* Runtime-state durability: **restored** — a safety sensor must not read "clear" merely because the hub restarted.
|
|
256162
|
+
*
|
|
256163
|
+
* See `RuntimeStateDurability`. Enforced by
|
|
256164
|
+
* `scripts/check-runtime-state-durability.ts`.
|
|
256165
|
+
*/
|
|
256166
|
+
durability: "restored",
|
|
256167
|
+
/** Clock fields: written, but excluded from the compare that decides
|
|
256168
|
+
* whether persisting is worth a SQLite commit. */
|
|
256169
|
+
volatileStateFields: ["lastChangedAt"]
|
|
254423
256170
|
};
|
|
254424
256171
|
var CamStreamDescriptorSchema = zod.z.object({
|
|
254425
256172
|
camStreamId: zod.z.string().min(1),
|
|
@@ -254570,7 +256317,17 @@ ${recipe.triggers.map((t, i) => emitTrigger(t, i)).join("\n\n")}
|
|
|
254570
256317
|
schema: StreamParamsStatusSchema,
|
|
254571
256318
|
kind: "poll"
|
|
254572
256319
|
},
|
|
254573
|
-
runtimeState: StreamParamsStatusSchema
|
|
256320
|
+
runtimeState: StreamParamsStatusSchema,
|
|
256321
|
+
/**
|
|
256322
|
+
* Runtime-state durability: **restored** — operator-set encoder profile; mutation-driven.
|
|
256323
|
+
*
|
|
256324
|
+
* See `RuntimeStateDurability`. Enforced by
|
|
256325
|
+
* `scripts/check-runtime-state-durability.ts`.
|
|
256326
|
+
*/
|
|
256327
|
+
durability: "restored",
|
|
256328
|
+
/** Clock fields: written, but excluded from the compare that decides
|
|
256329
|
+
* whether persisting is worth a SQLite commit. */
|
|
256330
|
+
volatileStateFields: ["lastFetchedAt"]
|
|
254574
256331
|
};
|
|
254575
256332
|
var STREAM_PROFILE_META = [
|
|
254576
256333
|
{
|
|
@@ -254841,6 +256598,16 @@ ${recipe.triggers.map((t, i) => emitTrigger(t, i)).join("\n\n")}
|
|
|
254841
256598
|
* not need to re-query the provider after a setState mutation.
|
|
254842
256599
|
*/
|
|
254843
256600
|
runtimeState: SwitchStatusSchema,
|
|
256601
|
+
/**
|
|
256602
|
+
* Runtime-state durability: **restored** — device state an operator reads as authoritative; 55 devices, transition-driven.
|
|
256603
|
+
*
|
|
256604
|
+
* See `RuntimeStateDurability`. Enforced by
|
|
256605
|
+
* `scripts/check-runtime-state-durability.ts`.
|
|
256606
|
+
*/
|
|
256607
|
+
durability: "restored",
|
|
256608
|
+
/** Clock fields: written, but excluded from the compare that decides
|
|
256609
|
+
* whether persisting is worth a SQLite commit. */
|
|
256610
|
+
volatileStateFields: ["lastChangedAt"],
|
|
254844
256611
|
settings: { bindings: [{
|
|
254845
256612
|
kind: "scalar",
|
|
254846
256613
|
statusPath: "on",
|
|
@@ -254913,7 +256680,17 @@ ${recipe.triggers.map((t, i) => emitTrigger(t, i)).join("\n\n")}
|
|
|
254913
256680
|
schema: TamperStatusSchema,
|
|
254914
256681
|
kind: "push"
|
|
254915
256682
|
},
|
|
254916
|
-
runtimeState: TamperStatusSchema
|
|
256683
|
+
runtimeState: TamperStatusSchema,
|
|
256684
|
+
/**
|
|
256685
|
+
* Runtime-state durability: **restored** — as `smoke`.
|
|
256686
|
+
*
|
|
256687
|
+
* See `RuntimeStateDurability`. Enforced by
|
|
256688
|
+
* `scripts/check-runtime-state-durability.ts`.
|
|
256689
|
+
*/
|
|
256690
|
+
durability: "restored",
|
|
256691
|
+
/** Clock fields: written, but excluded from the compare that decides
|
|
256692
|
+
* whether persisting is worth a SQLite commit. */
|
|
256693
|
+
volatileStateFields: ["lastChangedAt"]
|
|
254917
256694
|
};
|
|
254918
256695
|
var TemperatureSensorStatusSchema = zod.z.object({
|
|
254919
256696
|
/** Current temperature in Celsius. */
|
|
@@ -254942,7 +256719,17 @@ ${recipe.triggers.map((t, i) => emitTrigger(t, i)).join("\n\n")}
|
|
|
254942
256719
|
schema: TemperatureSensorStatusSchema,
|
|
254943
256720
|
kind: "push"
|
|
254944
256721
|
},
|
|
254945
|
-
runtimeState: TemperatureSensorStatusSchema
|
|
256722
|
+
runtimeState: TemperatureSensorStatusSchema,
|
|
256723
|
+
/**
|
|
256724
|
+
* Runtime-state durability: **restored** — as `numeric-sensor` (69 of 125 writes were the clock alone).
|
|
256725
|
+
*
|
|
256726
|
+
* See `RuntimeStateDurability`. Enforced by
|
|
256727
|
+
* `scripts/check-runtime-state-durability.ts`.
|
|
256728
|
+
*/
|
|
256729
|
+
durability: "restored",
|
|
256730
|
+
/** Clock fields: written, but excluded from the compare that decides
|
|
256731
|
+
* whether persisting is worth a SQLite commit. */
|
|
256732
|
+
volatileStateFields: ["lastFetchedAt"]
|
|
254946
256733
|
};
|
|
254947
256734
|
var ToastSchema = zod.z.object({
|
|
254948
256735
|
title: zod.z.string(),
|
|
@@ -254993,7 +256780,14 @@ ${recipe.triggers.map((t, i) => emitTrigger(t, i)).join("\n\n")}
|
|
|
254993
256780
|
schema: UpdateStatusSchema,
|
|
254994
256781
|
kind: "poll"
|
|
254995
256782
|
},
|
|
254996
|
-
runtimeState: UpdateStatusSchema
|
|
256783
|
+
runtimeState: UpdateStatusSchema,
|
|
256784
|
+
/**
|
|
256785
|
+
* Runtime-state durability: **session** — a restored `inProgress: true` describes an update that is no longer running; versions are re-probed at boot.
|
|
256786
|
+
*
|
|
256787
|
+
* See `RuntimeStateDurability`. Enforced by
|
|
256788
|
+
* `scripts/check-runtime-state-durability.ts`.
|
|
256789
|
+
*/
|
|
256790
|
+
durability: "session"
|
|
254997
256791
|
};
|
|
254998
256792
|
var UserSummarySchema = zod.z.object({
|
|
254999
256793
|
id: zod.z.string(),
|
|
@@ -255327,7 +257121,14 @@ ${recipe.triggers.map((t, i) => emitTrigger(t, i)).join("\n\n")}
|
|
|
255327
257121
|
* Runtime-state slice — mirrored by the kernel. UI controls watch the
|
|
255328
257122
|
* slice for live state + battery + fan-speed changes.
|
|
255329
257123
|
*/
|
|
255330
|
-
runtimeState: VacuumControlStatusSchema
|
|
257124
|
+
runtimeState: VacuumControlStatusSchema,
|
|
257125
|
+
/**
|
|
257126
|
+
* Runtime-state durability: **session** — as `media-player` — a restored `state: cleaning` is a robot that is not cleaning.
|
|
257127
|
+
*
|
|
257128
|
+
* See `RuntimeStateDurability`. Enforced by
|
|
257129
|
+
* `scripts/check-runtime-state-durability.ts`.
|
|
257130
|
+
*/
|
|
257131
|
+
durability: "session"
|
|
255331
257132
|
};
|
|
255332
257133
|
var ValveStateSchema = zod.z.enum([
|
|
255333
257134
|
"open",
|
|
@@ -255380,7 +257181,14 @@ ${recipe.triggers.map((t, i) => emitTrigger(t, i)).join("\n\n")}
|
|
|
255380
257181
|
* Runtime-state slice — mirrored by the kernel. UI controls watch the
|
|
255381
257182
|
* slice for live position changes during a move.
|
|
255382
257183
|
*/
|
|
255383
|
-
runtimeState: ValveStatusSchema
|
|
257184
|
+
runtimeState: ValveStatusSchema,
|
|
257185
|
+
/**
|
|
257186
|
+
* Runtime-state durability: **session** — as `brightness`.
|
|
257187
|
+
*
|
|
257188
|
+
* See `RuntimeStateDurability`. Enforced by
|
|
257189
|
+
* `scripts/check-runtime-state-durability.ts`.
|
|
257190
|
+
*/
|
|
257191
|
+
durability: "session"
|
|
255384
257192
|
};
|
|
255385
257193
|
var VibrationStatusSchema = zod.z.object({
|
|
255386
257194
|
detected: zod.z.boolean(),
|
|
@@ -255398,7 +257206,17 @@ ${recipe.triggers.map((t, i) => emitTrigger(t, i)).join("\n\n")}
|
|
|
255398
257206
|
schema: VibrationStatusSchema,
|
|
255399
257207
|
kind: "push"
|
|
255400
257208
|
},
|
|
255401
|
-
runtimeState: VibrationStatusSchema
|
|
257209
|
+
runtimeState: VibrationStatusSchema,
|
|
257210
|
+
/**
|
|
257211
|
+
* Runtime-state durability: **restored** — as `smoke`.
|
|
257212
|
+
*
|
|
257213
|
+
* See `RuntimeStateDurability`. Enforced by
|
|
257214
|
+
* `scripts/check-runtime-state-durability.ts`.
|
|
257215
|
+
*/
|
|
257216
|
+
durability: "restored",
|
|
257217
|
+
/** Clock fields: written, but excluded from the compare that decides
|
|
257218
|
+
* whether persisting is worth a SQLite commit. */
|
|
257219
|
+
volatileStateFields: ["lastChangedAt"]
|
|
255402
257220
|
};
|
|
255403
257221
|
var WaterHeaterStatusSchema = zod.z.object({
|
|
255404
257222
|
/** Current measured temperature. Null when not reported. */
|
|
@@ -255458,7 +257276,14 @@ ${recipe.triggers.map((t, i) => emitTrigger(t, i)).join("\n\n")}
|
|
|
255458
257276
|
* Runtime-state slice — mirrored by the kernel. UI controls watch the
|
|
255459
257277
|
* slice for live temperature / mode / away changes.
|
|
255460
257278
|
*/
|
|
255461
|
-
runtimeState: WaterHeaterStatusSchema
|
|
257279
|
+
runtimeState: WaterHeaterStatusSchema,
|
|
257280
|
+
/**
|
|
257281
|
+
* Runtime-state durability: **session** — as `climate-control`.
|
|
257282
|
+
*
|
|
257283
|
+
* See `RuntimeStateDurability`. Enforced by
|
|
257284
|
+
* `scripts/check-runtime-state-durability.ts`.
|
|
257285
|
+
*/
|
|
257286
|
+
durability: "session"
|
|
255462
257287
|
};
|
|
255463
257288
|
var WeatherStatusSchema = zod.z.object({
|
|
255464
257289
|
/** Verbatim HA condition state (`sunny`, `cloudy`, `rainy`, …). Null
|
|
@@ -255498,7 +257323,14 @@ ${recipe.triggers.map((t, i) => emitTrigger(t, i)).join("\n\n")}
|
|
|
255498
257323
|
* Runtime-state slice — mirrored by the kernel. The UI reads the
|
|
255499
257324
|
* current conditions directly from the slice on each weather push.
|
|
255500
257325
|
*/
|
|
255501
|
-
runtimeState: WeatherStatusSchema
|
|
257326
|
+
runtimeState: WeatherStatusSchema,
|
|
257327
|
+
/**
|
|
257328
|
+
* Runtime-state durability: **session** — a forecast is stale the moment the hub is down; the provider re-fetches on connect.
|
|
257329
|
+
*
|
|
257330
|
+
* See `RuntimeStateDurability`. Enforced by
|
|
257331
|
+
* `scripts/check-runtime-state-durability.ts`.
|
|
257332
|
+
*/
|
|
257333
|
+
durability: "session"
|
|
255502
257334
|
};
|
|
255503
257335
|
var PerScopeBreakdownSchema = zod.z.object({
|
|
255504
257336
|
/** Total tracked objects in this scope (frame / zone / unzoned). */
|
|
@@ -255607,7 +257439,14 @@ ${recipe.triggers.map((t, i) => emitTrigger(t, i)).join("\n\n")}
|
|
|
255607
257439
|
* automatically; the explicit `getCurrentSnapshot` cap method is
|
|
255608
257440
|
* still useful for one-off polls without a subscription.
|
|
255609
257441
|
*/
|
|
255610
|
-
runtimeState: CameraOccupancySnapshotSchema
|
|
257442
|
+
runtimeState: CameraOccupancySnapshotSchema,
|
|
257443
|
+
/**
|
|
257444
|
+
* Runtime-state durability: **session** — per-frame analytics; with `audio-metrics` it is ~90 % of the offered write rate. Re-derived on the next frame.
|
|
257445
|
+
*
|
|
257446
|
+
* See `RuntimeStateDurability`. Enforced by
|
|
257447
|
+
* `scripts/check-runtime-state-durability.ts`.
|
|
257448
|
+
*/
|
|
257449
|
+
durability: "session"
|
|
255611
257450
|
};
|
|
255612
257451
|
var ZoneRuleStageEnum = zod.z.enum([
|
|
255613
257452
|
"motion",
|
|
@@ -255659,7 +257498,14 @@ ${recipe.triggers.map((t, i) => emitTrigger(t, i)).join("\n\n")}
|
|
|
255659
257498
|
motion: zod.z.array(ZoneRuleSchema).readonly(),
|
|
255660
257499
|
detection: zod.z.array(ZoneRuleSchema).readonly(),
|
|
255661
257500
|
package: zod.z.array(ZoneRuleSchema).readonly()
|
|
255662
|
-
})
|
|
257501
|
+
}),
|
|
257502
|
+
/**
|
|
257503
|
+
* Runtime-state durability: **restored** — operator intent, mutation-only, same argument as `zones`.
|
|
257504
|
+
*
|
|
257505
|
+
* See `RuntimeStateDurability`. Enforced by
|
|
257506
|
+
* `scripts/check-runtime-state-durability.ts`.
|
|
257507
|
+
*/
|
|
257508
|
+
durability: "restored"
|
|
255663
257509
|
};
|
|
255664
257510
|
var PIPELINE_FLOW_CAPABILITY_NAMES = [
|
|
255665
257511
|
"decoder",
|
|
@@ -264909,6 +266755,301 @@ ${recipe.triggers.map((t, i) => emitTrigger(t, i)).join("\n\n")}
|
|
|
264909
266755
|
for (const [capName, capKind] of Object.entries(CAP_PROVIDER_KIND_MAP)) if (capKind === kind) out.push(capName);
|
|
264910
266756
|
return out;
|
|
264911
266757
|
}
|
|
266758
|
+
var RUNTIME_STATE_POLICY = {
|
|
266759
|
+
"air-quality-sensor": {
|
|
266760
|
+
durability: "restored",
|
|
266761
|
+
volatileFields: ["lastFetchedAt"]
|
|
266762
|
+
},
|
|
266763
|
+
"alarm-panel": {
|
|
266764
|
+
durability: "restored",
|
|
266765
|
+
volatileFields: ["lastChangedAt"]
|
|
266766
|
+
},
|
|
266767
|
+
"ambient-light-sensor": {
|
|
266768
|
+
durability: "restored",
|
|
266769
|
+
volatileFields: ["lastFetchedAt"]
|
|
266770
|
+
},
|
|
266771
|
+
"audio-metrics": {
|
|
266772
|
+
durability: "session",
|
|
266773
|
+
volatileFields: []
|
|
266774
|
+
},
|
|
266775
|
+
"automation-control": {
|
|
266776
|
+
durability: "session",
|
|
266777
|
+
volatileFields: []
|
|
266778
|
+
},
|
|
266779
|
+
"battery": {
|
|
266780
|
+
durability: "restored",
|
|
266781
|
+
volatileFields: ["lastUpdated"]
|
|
266782
|
+
},
|
|
266783
|
+
"binary": {
|
|
266784
|
+
durability: "restored",
|
|
266785
|
+
volatileFields: ["lastChangedAt"]
|
|
266786
|
+
},
|
|
266787
|
+
"brightness": {
|
|
266788
|
+
durability: "session",
|
|
266789
|
+
volatileFields: []
|
|
266790
|
+
},
|
|
266791
|
+
"camera-streams": {
|
|
266792
|
+
durability: "session",
|
|
266793
|
+
volatileFields: []
|
|
266794
|
+
},
|
|
266795
|
+
"carbon-monoxide": {
|
|
266796
|
+
durability: "restored",
|
|
266797
|
+
volatileFields: ["lastChangedAt"]
|
|
266798
|
+
},
|
|
266799
|
+
"climate-control": {
|
|
266800
|
+
durability: "session",
|
|
266801
|
+
volatileFields: []
|
|
266802
|
+
},
|
|
266803
|
+
"color": {
|
|
266804
|
+
durability: "session",
|
|
266805
|
+
volatileFields: []
|
|
266806
|
+
},
|
|
266807
|
+
"connectivity": {
|
|
266808
|
+
durability: "restored",
|
|
266809
|
+
volatileFields: ["lastChangedAt"]
|
|
266810
|
+
},
|
|
266811
|
+
"consumables": {
|
|
266812
|
+
durability: "session",
|
|
266813
|
+
volatileFields: []
|
|
266814
|
+
},
|
|
266815
|
+
"contact": {
|
|
266816
|
+
durability: "restored",
|
|
266817
|
+
volatileFields: ["lastChangedAt"]
|
|
266818
|
+
},
|
|
266819
|
+
"control": {
|
|
266820
|
+
durability: "session",
|
|
266821
|
+
volatileFields: []
|
|
266822
|
+
},
|
|
266823
|
+
"cover": {
|
|
266824
|
+
durability: "restored",
|
|
266825
|
+
volatileFields: ["lastChangedAt"]
|
|
266826
|
+
},
|
|
266827
|
+
"day-night": {
|
|
266828
|
+
durability: "restored",
|
|
266829
|
+
volatileFields: ["lastFetchedAt"]
|
|
266830
|
+
},
|
|
266831
|
+
"device-discovery": {
|
|
266832
|
+
durability: "session",
|
|
266833
|
+
volatileFields: []
|
|
266834
|
+
},
|
|
266835
|
+
"device-status": {
|
|
266836
|
+
durability: "restored",
|
|
266837
|
+
volatileFields: ["lastChangedAt"]
|
|
266838
|
+
},
|
|
266839
|
+
"doorbell": {
|
|
266840
|
+
durability: "restored",
|
|
266841
|
+
volatileFields: []
|
|
266842
|
+
},
|
|
266843
|
+
"enum-sensor": {
|
|
266844
|
+
durability: "restored",
|
|
266845
|
+
volatileFields: ["lastFetchedAt"]
|
|
266846
|
+
},
|
|
266847
|
+
"event-emitter": {
|
|
266848
|
+
durability: "session",
|
|
266849
|
+
volatileFields: []
|
|
266850
|
+
},
|
|
266851
|
+
"fan-control": {
|
|
266852
|
+
durability: "session",
|
|
266853
|
+
volatileFields: []
|
|
266854
|
+
},
|
|
266855
|
+
"feature-probe": {
|
|
266856
|
+
durability: "session",
|
|
266857
|
+
volatileFields: []
|
|
266858
|
+
},
|
|
266859
|
+
"flood": {
|
|
266860
|
+
durability: "restored",
|
|
266861
|
+
volatileFields: ["lastChangedAt"]
|
|
266862
|
+
},
|
|
266863
|
+
"gas": {
|
|
266864
|
+
durability: "restored",
|
|
266865
|
+
volatileFields: ["lastChangedAt"]
|
|
266866
|
+
},
|
|
266867
|
+
"humidifier": {
|
|
266868
|
+
durability: "session",
|
|
266869
|
+
volatileFields: []
|
|
266870
|
+
},
|
|
266871
|
+
"humidity-sensor": {
|
|
266872
|
+
durability: "restored",
|
|
266873
|
+
volatileFields: ["lastFetchedAt"]
|
|
266874
|
+
},
|
|
266875
|
+
"image": {
|
|
266876
|
+
durability: "session",
|
|
266877
|
+
volatileFields: []
|
|
266878
|
+
},
|
|
266879
|
+
"image-settings": {
|
|
266880
|
+
durability: "restored",
|
|
266881
|
+
volatileFields: ["lastFetchedAt"]
|
|
266882
|
+
},
|
|
266883
|
+
"lawn-mower-control": {
|
|
266884
|
+
durability: "session",
|
|
266885
|
+
volatileFields: []
|
|
266886
|
+
},
|
|
266887
|
+
"lock-control": {
|
|
266888
|
+
durability: "restored",
|
|
266889
|
+
volatileFields: ["lastChangedAt"]
|
|
266890
|
+
},
|
|
266891
|
+
"media-player": {
|
|
266892
|
+
durability: "session",
|
|
266893
|
+
volatileFields: []
|
|
266894
|
+
},
|
|
266895
|
+
"motion": {
|
|
266896
|
+
durability: "session",
|
|
266897
|
+
volatileFields: []
|
|
266898
|
+
},
|
|
266899
|
+
"motion-trigger": {
|
|
266900
|
+
durability: "session",
|
|
266901
|
+
volatileFields: []
|
|
266902
|
+
},
|
|
266903
|
+
"motion-zones": {
|
|
266904
|
+
durability: "restored",
|
|
266905
|
+
volatileFields: ["lastFetchedAt"]
|
|
266906
|
+
},
|
|
266907
|
+
"native-object-detection": {
|
|
266908
|
+
durability: "restored",
|
|
266909
|
+
volatileFields: ["lastFetchedAt"]
|
|
266910
|
+
},
|
|
266911
|
+
"notifier": {
|
|
266912
|
+
durability: "session",
|
|
266913
|
+
volatileFields: []
|
|
266914
|
+
},
|
|
266915
|
+
"numeric-sensor": {
|
|
266916
|
+
durability: "restored",
|
|
266917
|
+
volatileFields: ["lastFetchedAt"]
|
|
266918
|
+
},
|
|
266919
|
+
"pet-feeder": {
|
|
266920
|
+
durability: "session",
|
|
266921
|
+
volatileFields: []
|
|
266922
|
+
},
|
|
266923
|
+
"power-meter": {
|
|
266924
|
+
durability: "restored",
|
|
266925
|
+
volatileFields: ["lastFetchedAt"]
|
|
266926
|
+
},
|
|
266927
|
+
"presence": {
|
|
266928
|
+
durability: "restored",
|
|
266929
|
+
volatileFields: ["lastChangedAt"]
|
|
266930
|
+
},
|
|
266931
|
+
"pressure-sensor": {
|
|
266932
|
+
durability: "restored",
|
|
266933
|
+
volatileFields: ["lastFetchedAt"]
|
|
266934
|
+
},
|
|
266935
|
+
"privacy-mask": {
|
|
266936
|
+
durability: "restored",
|
|
266937
|
+
volatileFields: ["lastFetchedAt"]
|
|
266938
|
+
},
|
|
266939
|
+
"ptz-autotrack": {
|
|
266940
|
+
durability: "session",
|
|
266941
|
+
volatileFields: []
|
|
266942
|
+
},
|
|
266943
|
+
"scene-monitor": {
|
|
266944
|
+
durability: "session",
|
|
266945
|
+
volatileFields: []
|
|
266946
|
+
},
|
|
266947
|
+
"script-runner": {
|
|
266948
|
+
durability: "session",
|
|
266949
|
+
volatileFields: []
|
|
266950
|
+
},
|
|
266951
|
+
"smoke": {
|
|
266952
|
+
durability: "restored",
|
|
266953
|
+
volatileFields: ["lastChangedAt"]
|
|
266954
|
+
},
|
|
266955
|
+
"stream-params": {
|
|
266956
|
+
durability: "restored",
|
|
266957
|
+
volatileFields: ["lastFetchedAt"]
|
|
266958
|
+
},
|
|
266959
|
+
"switch": {
|
|
266960
|
+
durability: "restored",
|
|
266961
|
+
volatileFields: ["lastChangedAt"]
|
|
266962
|
+
},
|
|
266963
|
+
"tamper": {
|
|
266964
|
+
durability: "restored",
|
|
266965
|
+
volatileFields: ["lastChangedAt"]
|
|
266966
|
+
},
|
|
266967
|
+
"temperature-sensor": {
|
|
266968
|
+
durability: "restored",
|
|
266969
|
+
volatileFields: ["lastFetchedAt"]
|
|
266970
|
+
},
|
|
266971
|
+
"update": {
|
|
266972
|
+
durability: "session",
|
|
266973
|
+
volatileFields: []
|
|
266974
|
+
},
|
|
266975
|
+
"vacuum-control": {
|
|
266976
|
+
durability: "session",
|
|
266977
|
+
volatileFields: []
|
|
266978
|
+
},
|
|
266979
|
+
"valve": {
|
|
266980
|
+
durability: "session",
|
|
266981
|
+
volatileFields: []
|
|
266982
|
+
},
|
|
266983
|
+
"vibration": {
|
|
266984
|
+
durability: "restored",
|
|
266985
|
+
volatileFields: ["lastChangedAt"]
|
|
266986
|
+
},
|
|
266987
|
+
"water-heater": {
|
|
266988
|
+
durability: "session",
|
|
266989
|
+
volatileFields: []
|
|
266990
|
+
},
|
|
266991
|
+
"weather": {
|
|
266992
|
+
durability: "session",
|
|
266993
|
+
volatileFields: []
|
|
266994
|
+
},
|
|
266995
|
+
"zone-analytics": {
|
|
266996
|
+
durability: "session",
|
|
266997
|
+
volatileFields: []
|
|
266998
|
+
},
|
|
266999
|
+
"zone-rules": {
|
|
267000
|
+
durability: "restored",
|
|
267001
|
+
volatileFields: []
|
|
267002
|
+
},
|
|
267003
|
+
"zones": {
|
|
267004
|
+
durability: "restored",
|
|
267005
|
+
volatileFields: []
|
|
267006
|
+
}
|
|
267007
|
+
};
|
|
267008
|
+
function runtimeStatePolicyFor(capName) {
|
|
267009
|
+
return RUNTIME_STATE_POLICY[capName] ?? SESSION_ONLY_POLICY;
|
|
267010
|
+
}
|
|
267011
|
+
var SESSION_ONLY_POLICY = {
|
|
267012
|
+
durability: "session",
|
|
267013
|
+
volatileFields: []
|
|
267014
|
+
};
|
|
267015
|
+
function isRestoredCap(capName) {
|
|
267016
|
+
return runtimeStatePolicyFor(capName).durability === "restored";
|
|
267017
|
+
}
|
|
267018
|
+
var RESTORED_CAP_NAMES = [
|
|
267019
|
+
"air-quality-sensor",
|
|
267020
|
+
"alarm-panel",
|
|
267021
|
+
"ambient-light-sensor",
|
|
267022
|
+
"battery",
|
|
267023
|
+
"binary",
|
|
267024
|
+
"carbon-monoxide",
|
|
267025
|
+
"connectivity",
|
|
267026
|
+
"contact",
|
|
267027
|
+
"cover",
|
|
267028
|
+
"day-night",
|
|
267029
|
+
"device-status",
|
|
267030
|
+
"doorbell",
|
|
267031
|
+
"enum-sensor",
|
|
267032
|
+
"flood",
|
|
267033
|
+
"gas",
|
|
267034
|
+
"humidity-sensor",
|
|
267035
|
+
"image-settings",
|
|
267036
|
+
"lock-control",
|
|
267037
|
+
"motion-zones",
|
|
267038
|
+
"native-object-detection",
|
|
267039
|
+
"numeric-sensor",
|
|
267040
|
+
"power-meter",
|
|
267041
|
+
"presence",
|
|
267042
|
+
"pressure-sensor",
|
|
267043
|
+
"privacy-mask",
|
|
267044
|
+
"smoke",
|
|
267045
|
+
"stream-params",
|
|
267046
|
+
"switch",
|
|
267047
|
+
"tamper",
|
|
267048
|
+
"temperature-sensor",
|
|
267049
|
+
"vibration",
|
|
267050
|
+
"zone-rules",
|
|
267051
|
+
"zones"
|
|
267052
|
+
];
|
|
264912
267053
|
var SCOPE_PRESETS = [
|
|
264913
267054
|
{
|
|
264914
267055
|
id: "camera-viewer",
|
|
@@ -265552,6 +267693,96 @@ ${recipe.triggers.map((t, i) => emitTrigger(t, i)).join("\n\n")}
|
|
|
265552
267693
|
}
|
|
265553
267694
|
};
|
|
265554
267695
|
}
|
|
267696
|
+
var AUDIO_KIND_PREFIX = "audio-";
|
|
267697
|
+
function normalizeAudioLabel(value) {
|
|
267698
|
+
return value.startsWith(AUDIO_KIND_PREFIX) ? value.slice(6) : value;
|
|
267699
|
+
}
|
|
267700
|
+
var NC_AUDIO_DB_MIN = -96;
|
|
267701
|
+
var NC_AUDIO_DB_MAX = 0;
|
|
267702
|
+
var NC_AUDIO_DB_STEP = 3;
|
|
267703
|
+
var NC_AUDIO_DB_OFFERED = -30;
|
|
267704
|
+
var NC_AUDIO_HIT_PERCENT_MIN = 1;
|
|
267705
|
+
var NC_AUDIO_HIT_PERCENT_MAX = 100;
|
|
267706
|
+
var NC_AUDIO_SAMPLING_MIN_SEC = 1;
|
|
267707
|
+
var NC_AUDIO_SAMPLING_MAX_SEC = 300;
|
|
267708
|
+
var NC_AUDIO_DEFAULTS = {
|
|
267709
|
+
hitPercent: 60,
|
|
267710
|
+
samplingSeconds: 10
|
|
267711
|
+
};
|
|
267712
|
+
function audioOrDefaults(value) {
|
|
267713
|
+
return value ?? NC_AUDIO_DEFAULTS;
|
|
267714
|
+
}
|
|
267715
|
+
function audioIsFailClosed(value) {
|
|
267716
|
+
if (value === void 0) return false;
|
|
267717
|
+
return value.dbThreshold === void 0 && (value.labels === void 0 || value.labels.length === 0);
|
|
267718
|
+
}
|
|
267719
|
+
function clampInt(value, min, max) {
|
|
267720
|
+
if (!Number.isFinite(value)) return min;
|
|
267721
|
+
return Math.min(max, Math.max(min, Math.round(value)));
|
|
267722
|
+
}
|
|
267723
|
+
function has(patch, key) {
|
|
267724
|
+
return Object.prototype.hasOwnProperty.call(patch, key);
|
|
267725
|
+
}
|
|
267726
|
+
function patchAudio(current, patch) {
|
|
267727
|
+
const base = audioOrDefaults(current);
|
|
267728
|
+
const labels = has(patch, "labels") ? patch.labels : base.labels;
|
|
267729
|
+
const dbThreshold = has(patch, "dbThreshold") ? patch.dbThreshold : base.dbThreshold;
|
|
267730
|
+
return {
|
|
267731
|
+
...labels !== void 0 && labels.length > 0 ? { labels: [...labels] } : {},
|
|
267732
|
+
...dbThreshold !== void 0 ? { dbThreshold: clampInt(dbThreshold, NC_AUDIO_DB_MIN, 0) } : {},
|
|
267733
|
+
hitPercent: clampInt(patch.hitPercent ?? base.hitPercent, 1, 100),
|
|
267734
|
+
samplingSeconds: clampInt(patch.samplingSeconds ?? base.samplingSeconds, 1, 300)
|
|
267735
|
+
};
|
|
267736
|
+
}
|
|
267737
|
+
var UNKNOWN_LABEL_ICON = "\u{1F508}";
|
|
267738
|
+
var ICON_BY_ID = new Map(AUDIO_MACRO_LABELS.flatMap((macro2) => macro2.icon === void 0 ? [] : [[macro2.id, macro2.icon]]));
|
|
267739
|
+
function audioLabelChoices(taxonomy, selected) {
|
|
267740
|
+
const fromHub = taxonomy?.audioKinds ?? [];
|
|
267741
|
+
const choices = fromHub.length > 0 ? fromHub.map((entry) => {
|
|
267742
|
+
const id = normalizeAudioLabel(entry.kind);
|
|
267743
|
+
return {
|
|
267744
|
+
value: id,
|
|
267745
|
+
label: entry.label,
|
|
267746
|
+
icon: ICON_BY_ID.get(id) ?? UNKNOWN_LABEL_ICON,
|
|
267747
|
+
unknown: false
|
|
267748
|
+
};
|
|
267749
|
+
}) : AUDIO_MACRO_LABELS.map((macro2) => ({
|
|
267750
|
+
value: macro2.id,
|
|
267751
|
+
label: macro2.name,
|
|
267752
|
+
icon: macro2.icon ?? UNKNOWN_LABEL_ICON,
|
|
267753
|
+
unknown: false
|
|
267754
|
+
}));
|
|
267755
|
+
const known = new Set(choices.map((choice) => choice.value));
|
|
267756
|
+
const unknownLabels = [];
|
|
267757
|
+
for (const stored of selected ?? []) {
|
|
267758
|
+
const id = normalizeAudioLabel(stored);
|
|
267759
|
+
if (known.has(id) || unknownLabels.includes(id)) continue;
|
|
267760
|
+
unknownLabels.push(id);
|
|
267761
|
+
choices.push({
|
|
267762
|
+
value: id,
|
|
267763
|
+
label: id,
|
|
267764
|
+
icon: UNKNOWN_LABEL_ICON,
|
|
267765
|
+
unknown: true
|
|
267766
|
+
});
|
|
267767
|
+
}
|
|
267768
|
+
return {
|
|
267769
|
+
choices,
|
|
267770
|
+
unknownLabels
|
|
267771
|
+
};
|
|
267772
|
+
}
|
|
267773
|
+
function isAudioLabelSelected(labels, id) {
|
|
267774
|
+
const wanted = normalizeAudioLabel(id);
|
|
267775
|
+
return (labels ?? []).some((stored) => normalizeAudioLabel(stored) === wanted);
|
|
267776
|
+
}
|
|
267777
|
+
function toggleAudioLabel(labels, id) {
|
|
267778
|
+
const wanted = normalizeAudioLabel(id);
|
|
267779
|
+
const current = labels ?? [];
|
|
267780
|
+
if (isAudioLabelSelected(current, wanted)) {
|
|
267781
|
+
const next = current.filter((stored) => normalizeAudioLabel(stored) !== wanted);
|
|
267782
|
+
return next.length > 0 ? next : void 0;
|
|
267783
|
+
}
|
|
267784
|
+
return [...current, wanted];
|
|
267785
|
+
}
|
|
265555
267786
|
var CLASS_CONDITION_IDS = /* @__PURE__ */ new Set(["classes", "classesExclude"]);
|
|
265556
267787
|
var LABEL_CONDITION_IDS = /* @__PURE__ */ new Set(["sensorKinds"]);
|
|
265557
267788
|
function toOption(entry) {
|
|
@@ -266086,32 +268317,40 @@ ${recipe.triggers.map((t, i) => emitTrigger(t, i)).join("\n\n")}
|
|
|
266086
268317
|
};
|
|
266087
268318
|
}
|
|
266088
268319
|
var NATIVE_LEASE_SECTION_ID = "native-lease";
|
|
266089
|
-
var
|
|
268320
|
+
var NATIVE_LEASE_HOLD_KEY = "nativeLeaseHoldFrames";
|
|
266090
268321
|
var NATIVE_LEASE_BUDGET_KEY = "nativeLeaseBudgetMb";
|
|
266091
268322
|
var NATIVE_LEASE_ACTIVITY_KEY = "nativeLeaseActivityMs";
|
|
266092
268323
|
var NATIVE_LEASE_ADMISSION_KEY = "nativeLeaseAdmission";
|
|
268324
|
+
var NATIVE_LEASE_TILE_BUDGET_KEY = "nativeTileBudgetMb";
|
|
266093
268325
|
var NativeLeaseAdmissionSchema = zod.z.enum(["all", "inferred"]);
|
|
266094
268326
|
var NativeLeaseSettingsSchema = zod.z.object({
|
|
266095
268327
|
/**
|
|
266096
|
-
* How
|
|
268328
|
+
* How many delivered frames the worker HOLDS at once, waiting for each one's
|
|
268329
|
+
* detection result.
|
|
266097
268330
|
*
|
|
266098
|
-
*
|
|
266099
|
-
*
|
|
266100
|
-
*
|
|
266101
|
-
*
|
|
266102
|
-
*
|
|
268331
|
+
* This replaced a TTL on 2026-08-13, and the replacement is the whole point:
|
|
268332
|
+
* a time window was never related to the event the pixels were waiting for.
|
|
268333
|
+
* A held frame now lives from delivery until the runner has its `FrameResult`
|
|
268334
|
+
* — at which moment the runner cuts the subject tiles it actually wanted and
|
|
268335
|
+
* releases the frame. The bound exists only so a runner that stops answering
|
|
268336
|
+
* cannot pin RAM: above it the OLDEST held frame is dropped and counted.
|
|
268337
|
+
*
|
|
268338
|
+
* Sizing: the steady state is `inferenceLatency × deliveredFps`, measured at
|
|
268339
|
+
* 40-160 ms × ≤25 fps = 1-4 frames. The default leaves headroom for a hiccup
|
|
268340
|
+
* without ever approaching the old resident set (43 frames × 24.9 MB at 4K).
|
|
268341
|
+
* Raising it does not buy hit rate — it buys tolerance for a slow runner, and
|
|
268342
|
+
* `holdOverflow` on the metrics line is what says you need it.
|
|
266103
268343
|
*/
|
|
266104
|
-
|
|
268344
|
+
holdFrames: zod.z.number().int().min(1).max(64),
|
|
266105
268345
|
/**
|
|
266106
268346
|
* Hard per-decode-worker RAM ceiling for retained native frames, in MB.
|
|
266107
268347
|
*
|
|
266108
|
-
*
|
|
266109
|
-
*
|
|
266110
|
-
*
|
|
266111
|
-
*
|
|
266112
|
-
*
|
|
266113
|
-
*
|
|
266114
|
-
* rather than giving RAM back — lower this knob if RAM is what you wanted.
|
|
268348
|
+
* Since 2026-08-13 this is a SAFETY ceiling and nothing else: `holdFrames`
|
|
268349
|
+
* is what decides how much is held, and the ceiling is the number above which
|
|
268350
|
+
* something is wrong. Before that it was the effective cap — at 1024 MB with
|
|
268351
|
+
* a 2 800 ms TTL a 4K camera sat pinned at `leaseMb:1020, leaseFrames:43`
|
|
268352
|
+
* with the TTL expiring nothing, which is exactly the confusion the hold
|
|
268353
|
+
* removes. `leaseMb` / `leaseFrames` still say what is resident.
|
|
266115
268354
|
* `0` DISABLES the lease entirely and falls the worker back to the tiny
|
|
266116
268355
|
* leak-prone GPU surface ring (~85% crop miss; that is what the lease exists
|
|
266117
268356
|
* to replace).
|
|
@@ -266137,19 +268376,37 @@ ${recipe.triggers.map((t, i) => emitTrigger(t, i)).join("\n\n")}
|
|
|
266137
268376
|
* there is the signal that some caller names frames outside the inference set
|
|
266138
268377
|
* and that this must go back to `all`.
|
|
266139
268378
|
*/
|
|
266140
|
-
admission: NativeLeaseAdmissionSchema
|
|
268379
|
+
admission: NativeLeaseAdmissionSchema,
|
|
268380
|
+
/**
|
|
268381
|
+
* RAM ceiling per decode worker, in MB, for the SUBJECT TILES — the
|
|
268382
|
+
* compressed native crops the worker cuts at the moment a frame's detection
|
|
268383
|
+
* result arrives, and keeps long after the frame itself is freed.
|
|
268384
|
+
*
|
|
268385
|
+
* This is the knob that replaced the old retention window, and it buys about
|
|
268386
|
+
* three orders of magnitude more of it: a tile is one subject at native
|
|
268387
|
+
* resolution, JPEG-encoded (~60-120 KB on a 4K person), against ~24.9 MB for
|
|
268388
|
+
* the frame it was cut from. A frame on which nothing was detected costs
|
|
268389
|
+
* nothing at all, which is the real change — the old lease paid per FRAME and
|
|
268390
|
+
* was interrogated per SUBJECT.
|
|
268391
|
+
*
|
|
268392
|
+
* `0` DISABLES tiles, leaving only the hold window and the ≤640 RAM
|
|
268393
|
+
* fallback — i.e. the pre-2026-08-13 miss profile. Set it there only to
|
|
268394
|
+
* reproduce that.
|
|
268395
|
+
*/
|
|
268396
|
+
tileBudgetMb: zod.z.number().int().min(0).max(1024)
|
|
266141
268397
|
});
|
|
266142
268398
|
var DEFAULT_NATIVE_LEASE_SETTINGS = {
|
|
266143
|
-
|
|
268399
|
+
holdFrames: 8,
|
|
266144
268400
|
budgetMb: 1024,
|
|
266145
268401
|
activityMs: 15e3,
|
|
268402
|
+
tileBudgetMb: 64,
|
|
266146
268403
|
admission: "inferred"
|
|
266147
268404
|
};
|
|
266148
|
-
var
|
|
266149
|
-
min:
|
|
266150
|
-
max:
|
|
266151
|
-
step:
|
|
266152
|
-
default: DEFAULT_NATIVE_LEASE_SETTINGS.
|
|
268405
|
+
var NATIVE_LEASE_HOLD_FIELD = {
|
|
268406
|
+
min: 1,
|
|
268407
|
+
max: 64,
|
|
268408
|
+
step: 1,
|
|
268409
|
+
default: DEFAULT_NATIVE_LEASE_SETTINGS.holdFrames
|
|
266153
268410
|
};
|
|
266154
268411
|
var NATIVE_LEASE_BUDGET_FIELD = {
|
|
266155
268412
|
min: 0,
|
|
@@ -266163,6 +268420,12 @@ ${recipe.triggers.map((t, i) => emitTrigger(t, i)).join("\n\n")}
|
|
|
266163
268420
|
step: 1e3,
|
|
266164
268421
|
default: DEFAULT_NATIVE_LEASE_SETTINGS.activityMs
|
|
266165
268422
|
};
|
|
268423
|
+
var NATIVE_LEASE_TILE_BUDGET_FIELD = {
|
|
268424
|
+
min: 0,
|
|
268425
|
+
max: 1024,
|
|
268426
|
+
step: 16,
|
|
268427
|
+
default: DEFAULT_NATIVE_LEASE_SETTINGS.tileBudgetMb
|
|
268428
|
+
};
|
|
266166
268429
|
var NATIVE_LEASE_ADMISSION_FIELD = {
|
|
266167
268430
|
options: [{
|
|
266168
268431
|
value: "all",
|
|
@@ -266184,25 +268447,28 @@ ${recipe.triggers.map((t, i) => emitTrigger(t, i)).join("\n\n")}
|
|
|
266184
268447
|
return parsed.data === DEFAULT_NATIVE_LEASE_SETTINGS.admission ? null : parsed.data;
|
|
266185
268448
|
}
|
|
266186
268449
|
function readNativeLeaseOverride(config) {
|
|
266187
|
-
const
|
|
268450
|
+
const holdFrames = readKnob("holdFrames", config[NATIVE_LEASE_HOLD_KEY]);
|
|
266188
268451
|
const budgetMb = readKnob("budgetMb", config[NATIVE_LEASE_BUDGET_KEY]);
|
|
266189
268452
|
const activityMs = readKnob("activityMs", config[NATIVE_LEASE_ACTIVITY_KEY]);
|
|
266190
268453
|
const admission = readAdmissionKnob(config[NATIVE_LEASE_ADMISSION_KEY]);
|
|
268454
|
+
const tileBudgetMb = readKnob("tileBudgetMb", config[NATIVE_LEASE_TILE_BUDGET_KEY]);
|
|
266191
268455
|
return {
|
|
266192
|
-
...
|
|
268456
|
+
...holdFrames === null ? {} : { holdFrames },
|
|
266193
268457
|
...budgetMb === null ? {} : { budgetMb },
|
|
266194
268458
|
...activityMs === null ? {} : { activityMs },
|
|
266195
|
-
...admission === null ? {} : { admission }
|
|
268459
|
+
...admission === null ? {} : { admission },
|
|
268460
|
+
...tileBudgetMb === null ? {} : { tileBudgetMb }
|
|
266196
268461
|
};
|
|
266197
268462
|
}
|
|
266198
268463
|
function isHydratedField(entry) {
|
|
266199
268464
|
return typeof entry === "object" && entry !== null && "key" in entry;
|
|
266200
268465
|
}
|
|
266201
268466
|
var LEASE_KEYS = [
|
|
266202
|
-
|
|
268467
|
+
NATIVE_LEASE_HOLD_KEY,
|
|
266203
268468
|
NATIVE_LEASE_BUDGET_KEY,
|
|
266204
268469
|
NATIVE_LEASE_ACTIVITY_KEY,
|
|
266205
|
-
NATIVE_LEASE_ADMISSION_KEY
|
|
268470
|
+
NATIVE_LEASE_ADMISSION_KEY,
|
|
268471
|
+
NATIVE_LEASE_TILE_BUDGET_KEY
|
|
266206
268472
|
];
|
|
266207
268473
|
function pickNativeLeaseOverride(view) {
|
|
266208
268474
|
if (view === null) return {};
|
|
@@ -267369,6 +269635,7 @@ ${recipe.triggers.map((t, i) => emitTrigger(t, i)).join("\n\n")}
|
|
|
267369
269635
|
exports.DEFAULT_FEATURES = DEFAULT_FEATURES;
|
|
267370
269636
|
exports.DEFAULT_NATIVE_LEASE_SETTINGS = DEFAULT_NATIVE_LEASE_SETTINGS;
|
|
267371
269637
|
exports.DEFAULT_RETENTION = DEFAULT_RETENTION;
|
|
269638
|
+
exports.DEFAULT_RUNTIME_STATE_DURABILITY = require_sleep.DEFAULT_RUNTIME_STATE_DURABILITY;
|
|
267372
269639
|
exports.DEFAULT_SCRUB_THUMBNAIL_PRESET = DEFAULT_SCRUB_THUMBNAIL_PRESET;
|
|
267373
269640
|
exports.DEFAULT_TIMELAPSE_PREVIEW_TEXT = DEFAULT_TIMELAPSE_PREVIEW_TEXT;
|
|
267374
269641
|
exports.DETAIL_CROP_PADDING_FIELD = DETAIL_CROP_PADDING_FIELD;
|
|
@@ -267611,11 +269878,22 @@ ${recipe.triggers.map((t, i) => emitTrigger(t, i)).join("\n\n")}
|
|
|
267611
269878
|
exports.NATIVE_LEASE_ADMISSION_KEY = NATIVE_LEASE_ADMISSION_KEY;
|
|
267612
269879
|
exports.NATIVE_LEASE_BUDGET_FIELD = NATIVE_LEASE_BUDGET_FIELD;
|
|
267613
269880
|
exports.NATIVE_LEASE_BUDGET_KEY = NATIVE_LEASE_BUDGET_KEY;
|
|
269881
|
+
exports.NATIVE_LEASE_HOLD_FIELD = NATIVE_LEASE_HOLD_FIELD;
|
|
269882
|
+
exports.NATIVE_LEASE_HOLD_KEY = NATIVE_LEASE_HOLD_KEY;
|
|
267614
269883
|
exports.NATIVE_LEASE_SECTION_ID = NATIVE_LEASE_SECTION_ID;
|
|
267615
|
-
exports.
|
|
267616
|
-
exports.
|
|
269884
|
+
exports.NATIVE_LEASE_TILE_BUDGET_FIELD = NATIVE_LEASE_TILE_BUDGET_FIELD;
|
|
269885
|
+
exports.NATIVE_LEASE_TILE_BUDGET_KEY = NATIVE_LEASE_TILE_BUDGET_KEY;
|
|
267617
269886
|
exports.NC_ALARM_SYSTEM_EVENT_KINDS = NC_ALARM_SYSTEM_EVENT_KINDS;
|
|
267618
269887
|
exports.NC_AUDIO_DBFS_FLOOR = NC_AUDIO_DBFS_FLOOR;
|
|
269888
|
+
exports.NC_AUDIO_DB_MAX = NC_AUDIO_DB_MAX;
|
|
269889
|
+
exports.NC_AUDIO_DB_MIN = NC_AUDIO_DB_MIN;
|
|
269890
|
+
exports.NC_AUDIO_DB_OFFERED = NC_AUDIO_DB_OFFERED;
|
|
269891
|
+
exports.NC_AUDIO_DB_STEP = NC_AUDIO_DB_STEP;
|
|
269892
|
+
exports.NC_AUDIO_DEFAULTS = NC_AUDIO_DEFAULTS;
|
|
269893
|
+
exports.NC_AUDIO_HIT_PERCENT_MAX = NC_AUDIO_HIT_PERCENT_MAX;
|
|
269894
|
+
exports.NC_AUDIO_HIT_PERCENT_MIN = NC_AUDIO_HIT_PERCENT_MIN;
|
|
269895
|
+
exports.NC_AUDIO_SAMPLING_MAX_SEC = NC_AUDIO_SAMPLING_MAX_SEC;
|
|
269896
|
+
exports.NC_AUDIO_SAMPLING_MIN_SEC = NC_AUDIO_SAMPLING_MIN_SEC;
|
|
267619
269897
|
exports.NC_AUTHORABLE_SYSTEM_EVENT_KINDS = NC_AUTHORABLE_SYSTEM_EVENT_KINDS;
|
|
267620
269898
|
exports.NC_BASE_CONDITION_KEYS = NC_BASE_CONDITION_KEYS;
|
|
267621
269899
|
exports.NC_CONDITION_CATALOG = NC_CONDITION_CATALOG;
|
|
@@ -267623,6 +269901,7 @@ ${recipe.triggers.map((t, i) => emitTrigger(t, i)).join("\n\n")}
|
|
|
267623
269901
|
exports.NC_CONFIRM_DEFAULT_TIMEOUT_MS = NC_CONFIRM_DEFAULT_TIMEOUT_MS;
|
|
267624
269902
|
exports.NC_CONFIRM_MAX_TIMEOUT_MS = NC_CONFIRM_MAX_TIMEOUT_MS;
|
|
267625
269903
|
exports.NC_CONFIRM_MIN_TIMEOUT_MS = NC_CONFIRM_MIN_TIMEOUT_MS;
|
|
269904
|
+
exports.NC_DEFAULT_SNOOZE_MINUTES = NC_DEFAULT_SNOOZE_MINUTES;
|
|
267626
269905
|
exports.NC_HISTORY_LIMIT_DEFAULT = NC_HISTORY_LIMIT_DEFAULT;
|
|
267627
269906
|
exports.NC_HISTORY_LIMIT_MAX = NC_HISTORY_LIMIT_MAX;
|
|
267628
269907
|
exports.NC_MAX_PER_TRACK_IMMEDIATE = NC_MAX_PER_TRACK_IMMEDIATE;
|
|
@@ -267769,7 +270048,9 @@ ${recipe.triggers.map((t, i) => emitTrigger(t, i)).join("\n\n")}
|
|
|
267769
270048
|
exports.RECOGNITION_TYPES = RECOGNITION_TYPES;
|
|
267770
270049
|
exports.RECORDING_EXPORT_MAX_READ_BYTES = RECORDING_EXPORT_MAX_READ_BYTES;
|
|
267771
270050
|
exports.RESERVED_BINDING_NAMES = RESERVED_BINDING_NAMES;
|
|
270051
|
+
exports.RESTORED_CAP_NAMES = RESTORED_CAP_NAMES;
|
|
267772
270052
|
exports.RUNTIME_DEFAULTS = RUNTIME_DEFAULTS;
|
|
270053
|
+
exports.RUNTIME_STATE_POLICY = RUNTIME_STATE_POLICY;
|
|
267773
270054
|
exports.RUNTIME_TO_FORMAT = RUNTIME_TO_FORMAT;
|
|
267774
270055
|
exports.RawStateResultSchema = require_sleep.RawStateResultSchema;
|
|
267775
270056
|
exports.ReadGopBytesResultSchema = ReadGopBytesResultSchema;
|
|
@@ -268041,7 +270322,10 @@ ${recipe.triggers.map((t, i) => emitTrigger(t, i)).join("\n\n")}
|
|
|
268041
270322
|
exports.audioAnalysisCapability = audioAnalysisCapability;
|
|
268042
270323
|
exports.audioAnalyzerCapability = audioAnalyzerCapability;
|
|
268043
270324
|
exports.audioCodecCapability = audioCodecCapability;
|
|
270325
|
+
exports.audioIsFailClosed = audioIsFailClosed;
|
|
270326
|
+
exports.audioLabelChoices = audioLabelChoices;
|
|
268044
270327
|
exports.audioMetricsCapability = audioMetricsCapability;
|
|
270328
|
+
exports.audioOrDefaults = audioOrDefaults;
|
|
268045
270329
|
exports.audioPlanFromEncodeProfile = require_canonical_hash.audioPlanFromEncodeProfile;
|
|
268046
270330
|
exports.authProviderCapability = authProviderCapability;
|
|
268047
270331
|
exports.autoAssignProfiles = autoAssignProfiles;
|
|
@@ -268179,6 +270463,7 @@ ${recipe.triggers.map((t, i) => emitTrigger(t, i)).join("\n\n")}
|
|
|
268179
270463
|
exports.invocationFromEncodeProfile = require_canonical_hash.invocationFromEncodeProfile;
|
|
268180
270464
|
exports.isAgentOnlyPlacement = isAgentOnlyPlacement;
|
|
268181
270465
|
exports.isArrayOutputSchema = isArrayOutputSchema;
|
|
270466
|
+
exports.isAudioLabelSelected = isAudioLabelSelected;
|
|
268182
270467
|
exports.isBaseConditionKey = isBaseConditionKey;
|
|
268183
270468
|
exports.isCollectionArrayMethod = isCollectionArrayMethod;
|
|
268184
270469
|
exports.isDeployableToAgent = isDeployableToAgent;
|
|
@@ -268188,6 +270473,7 @@ ${recipe.triggers.map((t, i) => emitTrigger(t, i)).join("\n\n")}
|
|
|
268188
270473
|
exports.isIsolatedBuiltin = isIsolatedBuiltin;
|
|
268189
270474
|
exports.isNode = isNode;
|
|
268190
270475
|
exports.isObjectInput = isObjectInput;
|
|
270476
|
+
exports.isRestoredCap = isRestoredCap;
|
|
268191
270477
|
exports.isSameAddonId = isSameAddonId;
|
|
268192
270478
|
exports.isScheduleActive = isScheduleActive;
|
|
268193
270479
|
exports.isSoftwareDecode = require_canonical_hash.isSoftwareDecode;
|
|
@@ -268236,6 +270522,7 @@ ${recipe.triggers.map((t, i) => emitTrigger(t, i)).join("\n\n")}
|
|
|
268236
270522
|
exports.nodePin = require_sleep.nodePin;
|
|
268237
270523
|
exports.nodesCapability = nodesCapability;
|
|
268238
270524
|
exports.normalizeAddonInitResult = require_sleep.normalizeAddonInitResult;
|
|
270525
|
+
exports.normalizeAudioLabel = normalizeAudioLabel;
|
|
268239
270526
|
exports.normalizeUnit = normalizeUnit;
|
|
268240
270527
|
exports.notificationOutputCapability = notificationOutputCapability;
|
|
268241
270528
|
exports.notificationRulesCapability = notificationRulesCapability;
|
|
@@ -268252,6 +270539,7 @@ ${recipe.triggers.map((t, i) => emitTrigger(t, i)).join("\n\n")}
|
|
|
268252
270539
|
exports.parseJsonUnknown = require_sleep.parseJsonUnknown;
|
|
268253
270540
|
exports.parseProfileBrokerId = require_sleep.parseProfileBrokerId;
|
|
268254
270541
|
exports.parseStreamParamsFormPatch = parseStreamParamsFormPatch;
|
|
270542
|
+
exports.patchAudio = patchAudio;
|
|
268255
270543
|
exports.petFeederCapability = petFeederCapability;
|
|
268256
270544
|
exports.pickAccessoryControl = pickAccessoryControl;
|
|
268257
270545
|
exports.pickDetailCropConvention = pickDetailCropConvention;
|
|
@@ -268304,6 +270592,7 @@ ${recipe.triggers.map((t, i) => emitTrigger(t, i)).join("\n\n")}
|
|
|
268304
270592
|
exports.resolveVariantModelId = resolveVariantModelId;
|
|
268305
270593
|
exports.runInferenceStep = runInferenceStep;
|
|
268306
270594
|
exports.runtimeDevices = runtimeDevices;
|
|
270595
|
+
exports.runtimeStatePolicyFor = runtimeStatePolicyFor;
|
|
268307
270596
|
exports.sceneMonitorCapability = sceneMonitorCapability;
|
|
268308
270597
|
exports.scopeKey = require_sleep.scopeKey;
|
|
268309
270598
|
exports.scopesAllowAddon = scopesAllowAddon;
|
|
@@ -268350,6 +270639,7 @@ ${recipe.triggers.map((t, i) => emitTrigger(t, i)).join("\n\n")}
|
|
|
268350
270639
|
exports.toNodeId = require_sleep.toNodeId;
|
|
268351
270640
|
exports.toStreamSourceEntry = toStreamSourceEntry;
|
|
268352
270641
|
exports.toastCapability = toastCapability;
|
|
270642
|
+
exports.toggleAudioLabel = toggleAudioLabel;
|
|
268353
270643
|
exports.tokenize = tokenize;
|
|
268354
270644
|
exports.transcodeBody = transcodeBody;
|
|
268355
270645
|
exports.tryConvertUnit = tryConvertUnit;
|
|
@@ -362585,6 +364875,7 @@ var require_main2 = __commonJS({
|
|
|
362585
364875
|
var fs = __importStar(__require("fs"));
|
|
362586
364876
|
var path = __importStar(__require("path"));
|
|
362587
364877
|
var agent_http_js_1 = require_agent_http();
|
|
364878
|
+
var single_copy_cleanup_runner_js_1 = require_single_copy_cleanup_runner();
|
|
362588
364879
|
var derive_hub_url_js_1 = require_derive_hub_url();
|
|
362589
364880
|
var system_1 = require_dist3();
|
|
362590
364881
|
var types_1 = require_dist9();
|
|
@@ -362805,6 +365096,11 @@ var require_main2 = __commonJS({
|
|
|
362805
365096
|
} catch (err) {
|
|
362806
365097
|
consoleLogger.warn(`agent root boot confirmation failed: ${err instanceof Error ? err.message : String(err)}`);
|
|
362807
365098
|
}
|
|
365099
|
+
void (0, single_copy_cleanup_runner_js_1.runSingleCopyCleanup)({
|
|
365100
|
+
dataDir: config.dataDir,
|
|
365101
|
+
addonRoot: config.addonsDir,
|
|
365102
|
+
log: (line) => consoleLogger.info(line)
|
|
365103
|
+
});
|
|
362808
365104
|
};
|
|
362809
365105
|
const loggerFactory = (addonId) => agentLogManager.createLogger().withTags({ addonId });
|
|
362810
365106
|
const agentServiceSchema = (0, agent_service_js_1.createAgentService)({
|
|
@@ -389476,7 +391772,10 @@ var require_addon_registry_service = __commonJS({
|
|
|
389476
391772
|
"setDevice",
|
|
389477
391773
|
"getAddonDevice",
|
|
389478
391774
|
"setAddonDevice",
|
|
389479
|
-
"clearAddonDevice"
|
|
391775
|
+
"clearAddonDevice",
|
|
391776
|
+
"getDeviceRuntimeState",
|
|
391777
|
+
"setDeviceRuntimeState",
|
|
391778
|
+
"clearDeviceRuntimeState"
|
|
389480
391779
|
];
|
|
389481
391780
|
for (const key of required) {
|
|
389482
391781
|
if (typeof Reflect.get(backend, key) !== "function")
|
|
@@ -396933,6 +399232,18 @@ var require_cluster_node_history_store = __commonJS({
|
|
|
396933
399232
|
descriptor: DescriptorSchema
|
|
396934
399233
|
});
|
|
396935
399234
|
var COLLECTION = "cluster-node-history";
|
|
399235
|
+
var LAST_ACTIVE_HEARTBEAT_MS = 5 * 6e4;
|
|
399236
|
+
function descriptorsEqual(a, b) {
|
|
399237
|
+
return a.id === b.id && a.name === b.name && a.hostname === b.hostname && a.platform === b.platform && a.arch === b.arch && a.cpuModel === b.cpuModel && a.cpuCores === b.cpuCores && a.memoryMB === b.memoryMB && a.isHub === b.isHub && sameStrings(a.engines, b.engines) && sameStrings(a.localIps, b.localIps) && sameStrings(a.addonIds, b.addonIds) && samePackages(a.packages, b.packages);
|
|
399238
|
+
}
|
|
399239
|
+
function sameStrings(a, b) {
|
|
399240
|
+
return a.length === b.length && a.every((v, i) => v === b[i]);
|
|
399241
|
+
}
|
|
399242
|
+
function samePackages(a, b) {
|
|
399243
|
+
if (a === void 0 || b === void 0)
|
|
399244
|
+
return a === b;
|
|
399245
|
+
return a.length === b.length && a.every((p, i) => p.name === b[i]?.name && p.version === b[i]?.version);
|
|
399246
|
+
}
|
|
396936
399247
|
var ClusterNodeHistoryStore = class _ClusterNodeHistoryStore {
|
|
396937
399248
|
resolveSettingsStore;
|
|
396938
399249
|
logger;
|
|
@@ -396974,6 +399285,19 @@ var require_cluster_node_history_store = __commonJS({
|
|
|
396974
399285
|
* Upsert a node's descriptor + addon roster while it is ONLINE, stamping
|
|
396975
399286
|
* `lastActive = Date.now()`. Called on each `listNodes()` refresh for every
|
|
396976
399287
|
* live node (R2 capture point).
|
|
399288
|
+
*
|
|
399289
|
+
* WRITES ONLY ON A CHANGE, OR ONCE PER {@link LAST_ACTIVE_HEARTBEAT_MS}.
|
|
399290
|
+
* `listNodes()` runs off the 30 s topology heartbeat, so the unconditional
|
|
399291
|
+
* upsert this used to be was the worst write:row ratio in the whole system —
|
|
399292
|
+
* measured on the live hub at ~6 upserts/minute = **8,640 a day to maintain
|
|
399293
|
+
* three rows**, i.e. 40 % of every ledger write on the hub, on the same shfs
|
|
399294
|
+
* SQLite file whose WAL checkpoint can stall hub-main for seconds (D96).
|
|
399295
|
+
*
|
|
399296
|
+
* Nothing is lost. `lastActive` exists to answer "when was this node last
|
|
399297
|
+
* seen", which only matters at OFFLINE resolution — and the disconnect edge
|
|
399298
|
+
* is written by {@link touch}, which is unbounded. The bound costs at most
|
|
399299
|
+
* five minutes of precision on a node that then disappeared without a
|
|
399300
|
+
* `$node.disconnected`, and buys 288 writes/day/node instead of 2,880.
|
|
396977
399301
|
*/
|
|
396978
399302
|
async snapshot(descriptor) {
|
|
396979
399303
|
const store = await this.ensureDeclared();
|
|
@@ -396982,13 +399306,13 @@ var require_cluster_node_history_store = __commonJS({
|
|
|
396982
399306
|
try {
|
|
396983
399307
|
const existing = await this.readRow(store, descriptor.id);
|
|
396984
399308
|
const packages = descriptor.packages ?? existing?.descriptor.packages;
|
|
399309
|
+
const next = packages === void 0 ? descriptor : { ...descriptor, packages };
|
|
399310
|
+
if (existing !== null && !this.worthWriting(existing, next))
|
|
399311
|
+
return;
|
|
396985
399312
|
await store.set({
|
|
396986
399313
|
collection: COLLECTION,
|
|
396987
399314
|
key: descriptor.id,
|
|
396988
|
-
value: {
|
|
396989
|
-
lastActive: Date.now(),
|
|
396990
|
-
descriptor: packages === void 0 ? descriptor : { ...descriptor, packages }
|
|
396991
|
-
}
|
|
399315
|
+
value: { lastActive: Date.now(), descriptor: next }
|
|
396992
399316
|
});
|
|
396993
399317
|
} catch (err) {
|
|
396994
399318
|
this.logger.warn("snapshot upsert failed (best-effort)", {
|
|
@@ -396997,6 +399321,16 @@ var require_cluster_node_history_store = __commonJS({
|
|
|
396997
399321
|
});
|
|
396998
399322
|
}
|
|
396999
399323
|
}
|
|
399324
|
+
/**
|
|
399325
|
+
* Is this snapshot worth a commit? Yes when the descriptor CHANGED, or when
|
|
399326
|
+
* the stored `lastActive` has aged past the heartbeat bound. A read that
|
|
399327
|
+
* fails never reaches here — `snapshot` writes when there is no existing row.
|
|
399328
|
+
*/
|
|
399329
|
+
worthWriting(existing, next) {
|
|
399330
|
+
if (Date.now() - existing.lastActive >= LAST_ACTIVE_HEARTBEAT_MS)
|
|
399331
|
+
return true;
|
|
399332
|
+
return !descriptorsEqual(existing.descriptor, next);
|
|
399333
|
+
}
|
|
397000
399334
|
/** Read one node's row, validated. `null` when absent or malformed. */
|
|
397001
399335
|
async readRow(store, nodeId) {
|
|
397002
399336
|
const raw = await store.get({ collection: COLLECTION, key: nodeId });
|
|
@@ -397832,6 +400166,7 @@ var require_main4 = __commonJS({
|
|
|
397832
400166
|
var fs = __importStar(__require("fs"));
|
|
397833
400167
|
var path = __importStar(__require("path"));
|
|
397834
400168
|
var node_child_process_1 = __require("child_process");
|
|
400169
|
+
var single_copy_cleanup_runner_js_1 = require_single_copy_cleanup_runner();
|
|
397835
400170
|
var logging_service_1 = require_logging_service();
|
|
397836
400171
|
var event_bus_service_1 = require_event_bus_service();
|
|
397837
400172
|
var config_service_1 = require_config_service();
|
|
@@ -398684,6 +401019,11 @@ var require_main4 = __commonJS({
|
|
|
398684
401019
|
meta: { error: err instanceof Error ? err.message : String(err) }
|
|
398685
401020
|
});
|
|
398686
401021
|
}
|
|
401022
|
+
void (0, single_copy_cleanup_runner_js_1.runSingleCopyCleanup)({
|
|
401023
|
+
dataDir: dataPath,
|
|
401024
|
+
addonRoot: process.env["CAMSTACK_ADDONS_DIR"] ?? path.join(dataPath, "addons"),
|
|
401025
|
+
log: (line) => logger.info(line)
|
|
401026
|
+
});
|
|
398687
401027
|
try {
|
|
398688
401028
|
const dmForBackfill = capabilityRegistry.getSingleton("device-manager");
|
|
398689
401029
|
const integrationRegistry = addonRegistry.getIntegrationRegistry();
|
|
@@ -398982,11 +401322,11 @@ var require_launcher = __commonJS({
|
|
|
398982
401322
|
const bootstrapRequired = readBootstrapRequiredAddons(dataDir, bootstrapSchema) ?? roleDefaultBootstrap;
|
|
398983
401323
|
console.log(`[launcher] bootstrap (${role}): ${bootstrapRequired.length} required package(s)`);
|
|
398984
401324
|
try {
|
|
398985
|
-
const
|
|
401325
|
+
const closureNodeModules = path.resolve(__dirname, "..", "node_modules");
|
|
398986
401326
|
const plan = (0, first_boot_addon_plan_js_1.planFirstBootAddons)({
|
|
398987
401327
|
required: bootstrapRequired,
|
|
398988
|
-
closurePins: ownManifest === null ? {} : (0, first_boot_addon_plan_js_1.bootstrapPinsFrom)(ownManifest),
|
|
398989
401328
|
installed: readInstalledAddonVersions(addonsDir, bootstrapRequired),
|
|
401329
|
+
closureVersions: readInstalledAddonVersions(closureNodeModules, bootstrapRequired),
|
|
398990
401330
|
// Mirrors `shouldSkipClosureProvidedSeed`: only `@camstack/system`, and
|
|
398991
401331
|
// only while it actually resolves.
|
|
398992
401332
|
closureProvided: (() => {
|