camstack 1.2.142 → 1.2.144
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.
|
@@ -15389,6 +15389,25 @@ import { createHash } from "crypto";
|
|
|
15389
15389
|
var DEFAULT_MAX_UNIT_BYTES = 16 * 1024 * 1024;
|
|
15390
15390
|
|
|
15391
15391
|
// ../types/dist/index.mjs
|
|
15392
|
+
var MEDIA_OWNER_TYPES = [
|
|
15393
|
+
"track",
|
|
15394
|
+
"summary",
|
|
15395
|
+
"face",
|
|
15396
|
+
"identity",
|
|
15397
|
+
"plate",
|
|
15398
|
+
"vehicle",
|
|
15399
|
+
"scene",
|
|
15400
|
+
"motion",
|
|
15401
|
+
"object",
|
|
15402
|
+
"audio"
|
|
15403
|
+
];
|
|
15404
|
+
var OWNER_TYPES = new Set(MEDIA_OWNER_TYPES);
|
|
15405
|
+
var EVENT_OWNER_TYPES = [
|
|
15406
|
+
"motion",
|
|
15407
|
+
"object",
|
|
15408
|
+
"audio"
|
|
15409
|
+
];
|
|
15410
|
+
var EVENT_OWNER_TYPE_SET = new Set(EVENT_OWNER_TYPES);
|
|
15392
15411
|
var VideoEncodeSchema = external_exports.object({
|
|
15393
15412
|
codec: external_exports.enum([
|
|
15394
15413
|
"h264",
|
|
@@ -19991,8 +20010,18 @@ var settingsStoreCapability = {
|
|
|
19991
20010
|
insert: method(external_exports.object({
|
|
19992
20011
|
namespace: external_exports.string().optional(),
|
|
19993
20012
|
collection: external_exports.string(),
|
|
19994
|
-
record:
|
|
19995
|
-
|
|
20013
|
+
record: external_exports.object({
|
|
20014
|
+
id: external_exports.string().optional(),
|
|
20015
|
+
data: external_exports.record(external_exports.string(), external_exports.unknown())
|
|
20016
|
+
})
|
|
20017
|
+
}), external_exports.object({
|
|
20018
|
+
/**
|
|
20019
|
+
* The id the row ACTUALLY got (D473): the one supplied, the UUID minted
|
|
20020
|
+
* for an absent one, or the ROWID SQLite assigned on an `INTEGER`
|
|
20021
|
+
* primary key — which is the only place an auto key is knowable.
|
|
20022
|
+
*/
|
|
20023
|
+
id: external_exports.union([external_exports.string(), external_exports.number()])
|
|
20024
|
+
}), { kind: "mutation" }),
|
|
19996
20025
|
/**
|
|
19997
20026
|
* Insert MANY records in ONE transaction, returning how many landed.
|
|
19998
20027
|
*
|
|
@@ -20205,8 +20234,18 @@ var dataStoreProviderCapability = {
|
|
|
20205
20234
|
insert: method(external_exports.object({
|
|
20206
20235
|
namespace: external_exports.string().optional(),
|
|
20207
20236
|
collection: external_exports.string(),
|
|
20208
|
-
record:
|
|
20209
|
-
|
|
20237
|
+
record: external_exports.object({
|
|
20238
|
+
id: external_exports.string().optional(),
|
|
20239
|
+
data: external_exports.record(external_exports.string(), external_exports.unknown())
|
|
20240
|
+
})
|
|
20241
|
+
}), external_exports.object({
|
|
20242
|
+
/**
|
|
20243
|
+
* The id the row ACTUALLY got (D473): the one supplied, the UUID minted
|
|
20244
|
+
* for an absent one, or the ROWID SQLite assigned on an `INTEGER`
|
|
20245
|
+
* primary key — which is the only place an auto key is knowable.
|
|
20246
|
+
*/
|
|
20247
|
+
id: external_exports.union([external_exports.string(), external_exports.number()])
|
|
20248
|
+
}), {
|
|
20210
20249
|
kind: "mutation",
|
|
20211
20250
|
auth: "admin"
|
|
20212
20251
|
}),
|
|
@@ -26794,7 +26833,20 @@ var TrackSchema = external_exports.object({
|
|
|
26794
26833
|
...TrackRetrainFields
|
|
26795
26834
|
});
|
|
26796
26835
|
var BaseEventFields = {
|
|
26797
|
-
|
|
26836
|
+
/**
|
|
26837
|
+
* A SQLite ROWID, assigned by the database (D474).
|
|
26838
|
+
*
|
|
26839
|
+
* Was a 36-character UUID and cost 263 MB of a 1 117 MB database — paid
|
|
26840
|
+
* TWICE per row, in the row and in the primary-key index, across 2.1 million
|
|
26841
|
+
* motion, audio and object events. An `INTEGER PRIMARY KEY` in SQLite **is**
|
|
26842
|
+
* the rowid: the table itself is that B-tree, so the index stops existing
|
|
26843
|
+
* rather than getting smaller. No shorter string does that.
|
|
26844
|
+
*
|
|
26845
|
+
* Defined once here for all three event kinds, which is why they move
|
|
26846
|
+
* together: a per-table migration would have forked this and
|
|
26847
|
+
* `COMMON_BASE_COLUMNS` and reunited them two stages later.
|
|
26848
|
+
*/
|
|
26849
|
+
id: external_exports.number().int(),
|
|
26798
26850
|
deviceId: external_exports.number(),
|
|
26799
26851
|
timestamp: external_exports.number()
|
|
26800
26852
|
};
|
|
@@ -26813,7 +26865,34 @@ var MotionEventSchema = external_exports.object({
|
|
|
26813
26865
|
/** Omitted in slim projection. */
|
|
26814
26866
|
frameHeight: external_exports.number().optional(),
|
|
26815
26867
|
/** Populated by B5 (recording playback URL for this event). */
|
|
26816
|
-
mediaUrl: external_exports.string().optional()
|
|
26868
|
+
mediaUrl: external_exports.string().optional(),
|
|
26869
|
+
/**
|
|
26870
|
+
* One row per motion EPISODE, not one per push (D475). `null` while the
|
|
26871
|
+
* episode is still open — a further rising edge extends it in place rather
|
|
26872
|
+
* than inserting a new row. Set once, at close, to `lastOnAt - startedAt`
|
|
26873
|
+
* (the span from the first rising edge to the LAST one, deliberately NOT
|
|
26874
|
+
* `closedAt - startedAt` — the close delay is a quiet CONFIRMATION, not
|
|
26875
|
+
* movement, and folding it in would report `MOTION_CLOSE_AFTER_MS` of
|
|
26876
|
+
* motion for an instantaneous trigger).
|
|
26877
|
+
*
|
|
26878
|
+
* **Absent** (not merely `null`) on a row written before D475 — that means
|
|
26879
|
+
* "closed the old way, before this column existed", never "still open".
|
|
26880
|
+
* Nothing in this codebase may read an absent `durationMs` as an open
|
|
26881
|
+
* episode; only `null` means open.
|
|
26882
|
+
*/
|
|
26883
|
+
durationMs: external_exports.number().nullable().optional(),
|
|
26884
|
+
/**
|
|
26885
|
+
* Ms offsets from `timestamp` (the episode's own first rising edge, so the
|
|
26886
|
+
* first entry is always `0`) of every genuine off→on transition the
|
|
26887
|
+
* episode saw — "ogni evento on si deve salvare" (D475). NOT one entry per
|
|
26888
|
+
* push: a firmware source that keepalives at ~1 Hz for the whole burst
|
|
26889
|
+
* (Reolink, Hikvision) produces exactly one edge; a source that reports an
|
|
26890
|
+
* explicit `false` mid-episode and then resumes before the quiet window
|
|
26891
|
+
* elapses produces another. Stored compactly — see `motion-edge-codec.ts`
|
|
26892
|
+
* — and decoded back to this shape on read. Absent/empty on a legacy row,
|
|
26893
|
+
* which must never be read as "no episode happened here".
|
|
26894
|
+
*/
|
|
26895
|
+
edges: external_exports.array(external_exports.number()).readonly().optional()
|
|
26817
26896
|
});
|
|
26818
26897
|
var DetectionSourceSchema = external_exports.enum(["pipeline", "onboard"]);
|
|
26819
26898
|
var ZoneCrossingDirectionSchema = external_exports.enum(["enter", "exit"]);
|
|
@@ -26844,6 +26923,23 @@ var ObjectEventSchema = external_exports.object({
|
|
|
26844
26923
|
* includes it (it is light). Absent on rows written before this field.
|
|
26845
26924
|
*/
|
|
26846
26925
|
frameId: external_exports.string().optional(),
|
|
26926
|
+
/**
|
|
26927
|
+
* A PRODUCER-chosen key that makes a synthetic event's emission idempotent
|
|
26928
|
+
* (D474).
|
|
26929
|
+
*
|
|
26930
|
+
* Only the package detector writes it, and it exists because the event id
|
|
26931
|
+
* stopped being choosable: the delivery and pick-up rows used to BE their
|
|
26932
|
+
* dedupe key (`pa-pkg-<entryId>-delivered`), which is how "never emit a
|
|
26933
|
+
* second delivery for this entry" survived a restart. An `INTEGER` rowid is
|
|
26934
|
+
* assigned by SQLite, so that key had to move off the primary key rather
|
|
26935
|
+
* than be dropped — a detector that cannot recognise its own row re-delivers
|
|
26936
|
+
* every parcel on every boot.
|
|
26937
|
+
*
|
|
26938
|
+
* Absent on every other object event, and on every row written before this
|
|
26939
|
+
* field. Never a substitute for `id`: it is unique per (producer, occasion),
|
|
26940
|
+
* not per row, and nothing addresses a row by it.
|
|
26941
|
+
*/
|
|
26942
|
+
idempotencyKey: external_exports.string().optional(),
|
|
26847
26943
|
/** Omitted in slim projection. */
|
|
26848
26944
|
trackId: external_exports.string().optional(),
|
|
26849
26945
|
className: external_exports.string(),
|
|
@@ -35859,9 +35955,54 @@ var MotionStatusSchema = external_exports.object({
|
|
|
35859
35955
|
/** Ms epoch of the last detected-true observation. Null if never detected. */
|
|
35860
35956
|
lastDetectedAt: external_exports.number().nullable(),
|
|
35861
35957
|
/**
|
|
35862
|
-
*
|
|
35863
|
-
*
|
|
35864
|
-
*
|
|
35958
|
+
* `MOTION_CLOSE_AFTER_MS` while `detected: true` on a `Camera` device,
|
|
35959
|
+
* `null` while false and on every `Sensor` device (D475) — see that
|
|
35960
|
+
* constant's doc for the one-authority rule.
|
|
35961
|
+
*
|
|
35962
|
+
* ## Reading this field still arms nothing
|
|
35963
|
+
*
|
|
35964
|
+
* It reads like an instruction to the consumer ("revert after N ms if
|
|
35965
|
+
* no fresh push arrives") and it is not one: nothing in this repo reads
|
|
35966
|
+
* the LIVE cap value to drive a timer. `pipeline-analytics`'s motion-episode
|
|
35967
|
+
* close DOES now use the same number — `MOTION_CLOSE_AFTER_MS` — but as an
|
|
35968
|
+
* imported constant, not as a read of `device.state.motion.value`, so this
|
|
35969
|
+
* field stays what it always was: DESCRIPTIVE output, mirroring an answer
|
|
35970
|
+
* computed elsewhere. Building a self-clear timer out of a READ of this
|
|
35971
|
+
* field would add a second falling-edge authority beside whichever one
|
|
35972
|
+
* already owns the device, and two that can disagree are worse than one.
|
|
35973
|
+
* Consumers that need a falling edge SHAPED differently — held open across
|
|
35974
|
+
* a flapping source — debounce on their own side and say so, as
|
|
35975
|
+
* `addon-export-alexa/src/motion-clear-hold.ts` and
|
|
35976
|
+
* `addon-export-hap`'s `RESET_DEBOUNCE_MS` both do.
|
|
35977
|
+
*
|
|
35978
|
+
* ## Who writes it
|
|
35979
|
+
*
|
|
35980
|
+
* - **Cameras** — the runner's phase machine, `active → watching` on
|
|
35981
|
+
* `cooldown_expired`, which then writes this slice with
|
|
35982
|
+
* `detected: false` (`handlePhaseChanged` in
|
|
35983
|
+
* `pipeline-runner/index.ts`). It produces the FALLING edge, which
|
|
35984
|
+
* matters most for the sources that only ever push a rising one:
|
|
35985
|
+
* Reolink emits `MotionOnMotionChanged { detected: true }` and never
|
|
35986
|
+
* a false.
|
|
35987
|
+
* - **Sensors** (Home Assistant binary sensors, Homematic) — the
|
|
35988
|
+
* provider pushes the false itself, from the upstream system's own
|
|
35989
|
+
* state change. No phase machine is involved.
|
|
35990
|
+
*
|
|
35991
|
+
* ### The phase machine is CANONICAL, not sole — and that is a defect
|
|
35992
|
+
*
|
|
35993
|
+
* An earlier revision of this docblock (mine, 2026-09-12) claimed the
|
|
35994
|
+
* phase machine is the sole writer for a camera. It is not.
|
|
35995
|
+
* `hikvision-camera.ts:3464` and `amcrest-camera.ts:445` both call
|
|
35996
|
+
* `setCapSlice(motionCapability, …)` on their own rising edge, and
|
|
35997
|
+
* Hikvision's comment says why: it read THIS docblock, agreed the
|
|
35998
|
+
* runner is canonical, and wrote anyway to avoid per-tick churn. So
|
|
35999
|
+
* two authorities can disagree about one slice, which this repo
|
|
36000
|
+
* forbids, and the doc said otherwise — which is worse than saying
|
|
36001
|
+
* nothing, because it reads as verification.
|
|
36002
|
+
*
|
|
36003
|
+
* This predates D475 and is not fixed there: the fix touches every
|
|
36004
|
+
* camera provider. Recorded in D475's Consequences. Do not restore the
|
|
36005
|
+
* "sole writer" wording without also removing the other writers.
|
|
35865
36006
|
*/
|
|
35866
36007
|
autoClearAfterMs: external_exports.number().nullable()
|
|
35867
36008
|
});
|
|
@@ -35927,7 +36068,11 @@ var motionCapability = {
|
|
|
35927
36068
|
*/
|
|
35928
36069
|
runtimeState: MotionStatusSchema,
|
|
35929
36070
|
/**
|
|
35930
|
-
* Runtime-state durability: **session** —
|
|
36071
|
+
* Runtime-state durability: **session** — every writer of this slice
|
|
36072
|
+
* writes only on an EDGE, so a restored `detected: true` would stay
|
|
36073
|
+
* frozen until the next one instead of being corrected. The next edge
|
|
36074
|
+
* re-publishes the real state. (On who the writers are, and why there
|
|
36075
|
+
* is more than one, see `autoClearAfterMs` above.)
|
|
35931
36076
|
*
|
|
35932
36077
|
* See `RuntimeStateDurability`. Enforced by
|
|
35933
36078
|
* `scripts/check-runtime-state-durability.ts`.
|
package/dist/cli.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import {
|
|
3
3
|
runDiscover
|
|
4
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-E3UKNBI7.js";
|
|
5
5
|
import "./chunk-LMMQX4CK.js";
|
|
6
6
|
|
|
7
7
|
// src/cli.ts
|
|
@@ -38,7 +38,7 @@ async function runServe(args) {
|
|
|
38
38
|
...typeof values.data === "string" ? { data: values.data } : {}
|
|
39
39
|
};
|
|
40
40
|
Object.assign(process.env, buildServeEnv(opts));
|
|
41
|
-
await import("./launcher-
|
|
41
|
+
await import("./launcher-25V2QKN6.js");
|
|
42
42
|
}
|
|
43
43
|
|
|
44
44
|
// src/commands/agent.ts
|
|
@@ -83,7 +83,7 @@ async function runAgent(args) {
|
|
|
83
83
|
...typeof values.port === "string" ? { port: values.port } : {}
|
|
84
84
|
};
|
|
85
85
|
Object.assign(process.env, buildAgentEnv(opts));
|
|
86
|
-
await import("./launcher-
|
|
86
|
+
await import("./launcher-25V2QKN6.js");
|
|
87
87
|
}
|
|
88
88
|
|
|
89
89
|
// src/commands/setup.ts
|
|
@@ -1140,7 +1140,7 @@ function isUnknown(_value) {
|
|
|
1140
1140
|
return true;
|
|
1141
1141
|
}
|
|
1142
1142
|
async function resolveServerInteractive(presetNamespace) {
|
|
1143
|
-
const { discoverNodes, resolveHubFromDiscovered, filterHubNodes, DEFAULT_HUB_HTTPS_PORT } = await import("./discover-
|
|
1143
|
+
const { discoverNodes, resolveHubFromDiscovered, filterHubNodes, DEFAULT_HUB_HTTPS_PORT } = await import("./discover-YH7C75RI.js");
|
|
1144
1144
|
if (presetNamespace) {
|
|
1145
1145
|
const spinner4 = clack.spinner();
|
|
1146
1146
|
spinner4.start(`Discovering hub on LAN (namespace "${presetNamespace}")`);
|
|
@@ -23633,9 +23633,9 @@ var require_zod = __commonJS({
|
|
|
23633
23633
|
}
|
|
23634
23634
|
});
|
|
23635
23635
|
|
|
23636
|
-
// ../system/dist/dist-
|
|
23637
|
-
var
|
|
23638
|
-
"../system/dist/dist-
|
|
23636
|
+
// ../system/dist/dist-DdRxWA7g.js
|
|
23637
|
+
var require_dist_DdRxWA7g = __commonJS({
|
|
23638
|
+
"../system/dist/dist-DdRxWA7g.js"(exports) {
|
|
23639
23639
|
"use strict";
|
|
23640
23640
|
var zod = require_zod();
|
|
23641
23641
|
var EventCategory = /* @__PURE__ */ (function(EventCategory2) {
|
|
@@ -30743,8 +30743,18 @@ var require_dist_0sWJNwme = __commonJS({
|
|
|
30743
30743
|
insert: method(zod.z.object({
|
|
30744
30744
|
namespace: zod.z.string().optional(),
|
|
30745
30745
|
collection: zod.z.string(),
|
|
30746
|
-
record:
|
|
30747
|
-
|
|
30746
|
+
record: zod.z.object({
|
|
30747
|
+
id: zod.z.string().optional(),
|
|
30748
|
+
data: zod.z.record(zod.z.string(), zod.z.unknown())
|
|
30749
|
+
})
|
|
30750
|
+
}), zod.z.object({
|
|
30751
|
+
/**
|
|
30752
|
+
* The id the row ACTUALLY got (D473): the one supplied, the UUID minted
|
|
30753
|
+
* for an absent one, or the ROWID SQLite assigned on an `INTEGER`
|
|
30754
|
+
* primary key — which is the only place an auto key is knowable.
|
|
30755
|
+
*/
|
|
30756
|
+
id: zod.z.union([zod.z.string(), zod.z.number()])
|
|
30757
|
+
}), { kind: "mutation" }),
|
|
30748
30758
|
/**
|
|
30749
30759
|
* Insert MANY records in ONE transaction, returning how many landed.
|
|
30750
30760
|
*
|
|
@@ -30957,8 +30967,18 @@ var require_dist_0sWJNwme = __commonJS({
|
|
|
30957
30967
|
insert: method(zod.z.object({
|
|
30958
30968
|
namespace: zod.z.string().optional(),
|
|
30959
30969
|
collection: zod.z.string(),
|
|
30960
|
-
record:
|
|
30961
|
-
|
|
30970
|
+
record: zod.z.object({
|
|
30971
|
+
id: zod.z.string().optional(),
|
|
30972
|
+
data: zod.z.record(zod.z.string(), zod.z.unknown())
|
|
30973
|
+
})
|
|
30974
|
+
}), zod.z.object({
|
|
30975
|
+
/**
|
|
30976
|
+
* The id the row ACTUALLY got (D473): the one supplied, the UUID minted
|
|
30977
|
+
* for an absent one, or the ROWID SQLite assigned on an `INTEGER`
|
|
30978
|
+
* primary key — which is the only place an auto key is knowable.
|
|
30979
|
+
*/
|
|
30980
|
+
id: zod.z.union([zod.z.string(), zod.z.number()])
|
|
30981
|
+
}), {
|
|
30962
30982
|
kind: "mutation",
|
|
30963
30983
|
auth: "admin"
|
|
30964
30984
|
}),
|
|
@@ -37573,7 +37593,20 @@ var require_dist_0sWJNwme = __commonJS({
|
|
|
37573
37593
|
...TrackRetrainFields
|
|
37574
37594
|
});
|
|
37575
37595
|
var BaseEventFields = {
|
|
37576
|
-
|
|
37596
|
+
/**
|
|
37597
|
+
* A SQLite ROWID, assigned by the database (D474).
|
|
37598
|
+
*
|
|
37599
|
+
* Was a 36-character UUID and cost 263 MB of a 1 117 MB database — paid
|
|
37600
|
+
* TWICE per row, in the row and in the primary-key index, across 2.1 million
|
|
37601
|
+
* motion, audio and object events. An `INTEGER PRIMARY KEY` in SQLite **is**
|
|
37602
|
+
* the rowid: the table itself is that B-tree, so the index stops existing
|
|
37603
|
+
* rather than getting smaller. No shorter string does that.
|
|
37604
|
+
*
|
|
37605
|
+
* Defined once here for all three event kinds, which is why they move
|
|
37606
|
+
* together: a per-table migration would have forked this and
|
|
37607
|
+
* `COMMON_BASE_COLUMNS` and reunited them two stages later.
|
|
37608
|
+
*/
|
|
37609
|
+
id: zod.z.number().int(),
|
|
37577
37610
|
deviceId: zod.z.number(),
|
|
37578
37611
|
timestamp: zod.z.number()
|
|
37579
37612
|
};
|
|
@@ -37592,7 +37625,34 @@ var require_dist_0sWJNwme = __commonJS({
|
|
|
37592
37625
|
/** Omitted in slim projection. */
|
|
37593
37626
|
frameHeight: zod.z.number().optional(),
|
|
37594
37627
|
/** Populated by B5 (recording playback URL for this event). */
|
|
37595
|
-
mediaUrl: zod.z.string().optional()
|
|
37628
|
+
mediaUrl: zod.z.string().optional(),
|
|
37629
|
+
/**
|
|
37630
|
+
* One row per motion EPISODE, not one per push (D475). `null` while the
|
|
37631
|
+
* episode is still open — a further rising edge extends it in place rather
|
|
37632
|
+
* than inserting a new row. Set once, at close, to `lastOnAt - startedAt`
|
|
37633
|
+
* (the span from the first rising edge to the LAST one, deliberately NOT
|
|
37634
|
+
* `closedAt - startedAt` — the close delay is a quiet CONFIRMATION, not
|
|
37635
|
+
* movement, and folding it in would report `MOTION_CLOSE_AFTER_MS` of
|
|
37636
|
+
* motion for an instantaneous trigger).
|
|
37637
|
+
*
|
|
37638
|
+
* **Absent** (not merely `null`) on a row written before D475 — that means
|
|
37639
|
+
* "closed the old way, before this column existed", never "still open".
|
|
37640
|
+
* Nothing in this codebase may read an absent `durationMs` as an open
|
|
37641
|
+
* episode; only `null` means open.
|
|
37642
|
+
*/
|
|
37643
|
+
durationMs: zod.z.number().nullable().optional(),
|
|
37644
|
+
/**
|
|
37645
|
+
* Ms offsets from `timestamp` (the episode's own first rising edge, so the
|
|
37646
|
+
* first entry is always `0`) of every genuine off→on transition the
|
|
37647
|
+
* episode saw — "ogni evento on si deve salvare" (D475). NOT one entry per
|
|
37648
|
+
* push: a firmware source that keepalives at ~1 Hz for the whole burst
|
|
37649
|
+
* (Reolink, Hikvision) produces exactly one edge; a source that reports an
|
|
37650
|
+
* explicit `false` mid-episode and then resumes before the quiet window
|
|
37651
|
+
* elapses produces another. Stored compactly — see `motion-edge-codec.ts`
|
|
37652
|
+
* — and decoded back to this shape on read. Absent/empty on a legacy row,
|
|
37653
|
+
* which must never be read as "no episode happened here".
|
|
37654
|
+
*/
|
|
37655
|
+
edges: zod.z.array(zod.z.number()).readonly().optional()
|
|
37596
37656
|
});
|
|
37597
37657
|
var DetectionSourceSchema = zod.z.enum(["pipeline", "onboard"]);
|
|
37598
37658
|
var ZoneCrossingDirectionSchema = zod.z.enum(["enter", "exit"]);
|
|
@@ -37623,6 +37683,23 @@ var require_dist_0sWJNwme = __commonJS({
|
|
|
37623
37683
|
* includes it (it is light). Absent on rows written before this field.
|
|
37624
37684
|
*/
|
|
37625
37685
|
frameId: zod.z.string().optional(),
|
|
37686
|
+
/**
|
|
37687
|
+
* A PRODUCER-chosen key that makes a synthetic event's emission idempotent
|
|
37688
|
+
* (D474).
|
|
37689
|
+
*
|
|
37690
|
+
* Only the package detector writes it, and it exists because the event id
|
|
37691
|
+
* stopped being choosable: the delivery and pick-up rows used to BE their
|
|
37692
|
+
* dedupe key (`pa-pkg-<entryId>-delivered`), which is how "never emit a
|
|
37693
|
+
* second delivery for this entry" survived a restart. An `INTEGER` rowid is
|
|
37694
|
+
* assigned by SQLite, so that key had to move off the primary key rather
|
|
37695
|
+
* than be dropped — a detector that cannot recognise its own row re-delivers
|
|
37696
|
+
* every parcel on every boot.
|
|
37697
|
+
*
|
|
37698
|
+
* Absent on every other object event, and on every row written before this
|
|
37699
|
+
* field. Never a substitute for `id`: it is unique per (producer, occasion),
|
|
37700
|
+
* not per row, and nothing addresses a row by it.
|
|
37701
|
+
*/
|
|
37702
|
+
idempotencyKey: zod.z.string().optional(),
|
|
37626
37703
|
/** Omitted in slim projection. */
|
|
37627
37704
|
trackId: zod.z.string().optional(),
|
|
37628
37705
|
className: zod.z.string(),
|
|
@@ -46462,9 +46539,54 @@ var require_dist_0sWJNwme = __commonJS({
|
|
|
46462
46539
|
/** Ms epoch of the last detected-true observation. Null if never detected. */
|
|
46463
46540
|
lastDetectedAt: zod.z.number().nullable(),
|
|
46464
46541
|
/**
|
|
46465
|
-
*
|
|
46466
|
-
*
|
|
46467
|
-
*
|
|
46542
|
+
* `MOTION_CLOSE_AFTER_MS` while `detected: true` on a `Camera` device,
|
|
46543
|
+
* `null` while false and on every `Sensor` device (D475) — see that
|
|
46544
|
+
* constant's doc for the one-authority rule.
|
|
46545
|
+
*
|
|
46546
|
+
* ## Reading this field still arms nothing
|
|
46547
|
+
*
|
|
46548
|
+
* It reads like an instruction to the consumer ("revert after N ms if
|
|
46549
|
+
* no fresh push arrives") and it is not one: nothing in this repo reads
|
|
46550
|
+
* the LIVE cap value to drive a timer. `pipeline-analytics`'s motion-episode
|
|
46551
|
+
* close DOES now use the same number — `MOTION_CLOSE_AFTER_MS` — but as an
|
|
46552
|
+
* imported constant, not as a read of `device.state.motion.value`, so this
|
|
46553
|
+
* field stays what it always was: DESCRIPTIVE output, mirroring an answer
|
|
46554
|
+
* computed elsewhere. Building a self-clear timer out of a READ of this
|
|
46555
|
+
* field would add a second falling-edge authority beside whichever one
|
|
46556
|
+
* already owns the device, and two that can disagree are worse than one.
|
|
46557
|
+
* Consumers that need a falling edge SHAPED differently — held open across
|
|
46558
|
+
* a flapping source — debounce on their own side and say so, as
|
|
46559
|
+
* `addon-export-alexa/src/motion-clear-hold.ts` and
|
|
46560
|
+
* `addon-export-hap`'s `RESET_DEBOUNCE_MS` both do.
|
|
46561
|
+
*
|
|
46562
|
+
* ## Who writes it
|
|
46563
|
+
*
|
|
46564
|
+
* - **Cameras** — the runner's phase machine, `active → watching` on
|
|
46565
|
+
* `cooldown_expired`, which then writes this slice with
|
|
46566
|
+
* `detected: false` (`handlePhaseChanged` in
|
|
46567
|
+
* `pipeline-runner/index.ts`). It produces the FALLING edge, which
|
|
46568
|
+
* matters most for the sources that only ever push a rising one:
|
|
46569
|
+
* Reolink emits `MotionOnMotionChanged { detected: true }` and never
|
|
46570
|
+
* a false.
|
|
46571
|
+
* - **Sensors** (Home Assistant binary sensors, Homematic) — the
|
|
46572
|
+
* provider pushes the false itself, from the upstream system's own
|
|
46573
|
+
* state change. No phase machine is involved.
|
|
46574
|
+
*
|
|
46575
|
+
* ### The phase machine is CANONICAL, not sole — and that is a defect
|
|
46576
|
+
*
|
|
46577
|
+
* An earlier revision of this docblock (mine, 2026-09-12) claimed the
|
|
46578
|
+
* phase machine is the sole writer for a camera. It is not.
|
|
46579
|
+
* `hikvision-camera.ts:3464` and `amcrest-camera.ts:445` both call
|
|
46580
|
+
* `setCapSlice(motionCapability, …)` on their own rising edge, and
|
|
46581
|
+
* Hikvision's comment says why: it read THIS docblock, agreed the
|
|
46582
|
+
* runner is canonical, and wrote anyway to avoid per-tick churn. So
|
|
46583
|
+
* two authorities can disagree about one slice, which this repo
|
|
46584
|
+
* forbids, and the doc said otherwise — which is worse than saying
|
|
46585
|
+
* nothing, because it reads as verification.
|
|
46586
|
+
*
|
|
46587
|
+
* This predates D475 and is not fixed there: the fix touches every
|
|
46588
|
+
* camera provider. Recorded in D475's Consequences. Do not restore the
|
|
46589
|
+
* "sole writer" wording without also removing the other writers.
|
|
46468
46590
|
*/
|
|
46469
46591
|
autoClearAfterMs: zod.z.number().nullable()
|
|
46470
46592
|
});
|
|
@@ -46530,7 +46652,11 @@ var require_dist_0sWJNwme = __commonJS({
|
|
|
46530
46652
|
*/
|
|
46531
46653
|
runtimeState: MotionStatusSchema,
|
|
46532
46654
|
/**
|
|
46533
|
-
* Runtime-state durability: **session** —
|
|
46655
|
+
* Runtime-state durability: **session** — every writer of this slice
|
|
46656
|
+
* writes only on an EDGE, so a restored `detected: true` would stay
|
|
46657
|
+
* frozen until the next one instead of being corrected. The next edge
|
|
46658
|
+
* re-publishes the real state. (On who the writers are, and why there
|
|
46659
|
+
* is more than one, see `autoClearAfterMs` above.)
|
|
46534
46660
|
*
|
|
46535
46661
|
* See `RuntimeStateDurability`. Enforced by
|
|
46536
46662
|
* `scripts/check-runtime-state-durability.ts`.
|
|
@@ -61739,7 +61865,7 @@ var require_alerts_addon = __commonJS({
|
|
|
61739
61865
|
[Symbol.toStringTag]: { value: "Module" }
|
|
61740
61866
|
});
|
|
61741
61867
|
require_chunk_Cek0wNdY();
|
|
61742
|
-
var require_dist10 =
|
|
61868
|
+
var require_dist10 = require_dist_DdRxWA7g();
|
|
61743
61869
|
function selectExpired(alerts, cutoffMs) {
|
|
61744
61870
|
return alerts.filter((a) => a.createdAt < cutoffMs).sort((a, b) => a.createdAt - b.createdAt).map((a) => a.id);
|
|
61745
61871
|
}
|
|
@@ -62558,7 +62684,7 @@ var require_console_logging = __commonJS({
|
|
|
62558
62684
|
[Symbol.toStringTag]: { value: "Module" }
|
|
62559
62685
|
});
|
|
62560
62686
|
require_chunk_Cek0wNdY();
|
|
62561
|
-
var require_dist10 =
|
|
62687
|
+
var require_dist10 = require_dist_DdRxWA7g();
|
|
62562
62688
|
var require_formatter = require_formatter_DqAKDlvN();
|
|
62563
62689
|
var LEVEL_RANK = {
|
|
62564
62690
|
debug: 0,
|
|
@@ -62652,7 +62778,7 @@ var require_core_blocks_addon = __commonJS({
|
|
|
62652
62778
|
"use strict";
|
|
62653
62779
|
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
62654
62780
|
var require_chunk = require_chunk_Cek0wNdY();
|
|
62655
|
-
var require_dist10 =
|
|
62781
|
+
var require_dist10 = require_dist_DdRxWA7g();
|
|
62656
62782
|
var node_crypto = __require("crypto");
|
|
62657
62783
|
var node_fs_promises = __require("fs/promises");
|
|
62658
62784
|
node_fs_promises = require_chunk.__toESM(node_fs_promises);
|
|
@@ -63549,11 +63675,11 @@ var require_core_blocks = __commonJS({
|
|
|
63549
63675
|
}
|
|
63550
63676
|
});
|
|
63551
63677
|
|
|
63552
|
-
// ../system/dist/retired-settings-keys-
|
|
63553
|
-
var
|
|
63554
|
-
"../system/dist/retired-settings-keys-
|
|
63678
|
+
// ../system/dist/retired-settings-keys-C-jOWHI0.js
|
|
63679
|
+
var require_retired_settings_keys_C_jOWHI0 = __commonJS({
|
|
63680
|
+
"../system/dist/retired-settings-keys-C-jOWHI0.js"(exports) {
|
|
63555
63681
|
"use strict";
|
|
63556
|
-
var require_dist10 =
|
|
63682
|
+
var require_dist10 = require_dist_DdRxWA7g();
|
|
63557
63683
|
function settingsStoreIsAuthoritativeHere(env) {
|
|
63558
63684
|
const raw = (env["CAMSTACK_ROLE"] ?? "").trim().toLowerCase();
|
|
63559
63685
|
return raw === "" || raw === "hub";
|
|
@@ -65788,8 +65914,8 @@ var require_device_manager_addon = __commonJS({
|
|
|
65788
65914
|
[Symbol.toStringTag]: { value: "Module" }
|
|
65789
65915
|
});
|
|
65790
65916
|
require_chunk_Cek0wNdY();
|
|
65791
|
-
var require_dist10 =
|
|
65792
|
-
var require_retired_settings_keys =
|
|
65917
|
+
var require_dist10 = require_dist_DdRxWA7g();
|
|
65918
|
+
var require_retired_settings_keys = require_retired_settings_keys_C_jOWHI0();
|
|
65793
65919
|
var node_crypto = __require("crypto");
|
|
65794
65920
|
var _camstack_types_node = require_node();
|
|
65795
65921
|
var JOB_HISTORY = 20;
|
|
@@ -71414,7 +71540,7 @@ var require_hub_forwarder = __commonJS({
|
|
|
71414
71540
|
[Symbol.toStringTag]: { value: "Module" }
|
|
71415
71541
|
});
|
|
71416
71542
|
require_chunk_Cek0wNdY();
|
|
71417
|
-
var require_dist10 =
|
|
71543
|
+
var require_dist10 = require_dist_DdRxWA7g();
|
|
71418
71544
|
var require_formatter = require_formatter_DqAKDlvN();
|
|
71419
71545
|
var DEFAULT_OUTBOUND_BUFFER_SIZE = 500;
|
|
71420
71546
|
var HubForwarderDestination = class {
|
|
@@ -71551,7 +71677,7 @@ var require_liveness_monitor_addon = __commonJS({
|
|
|
71551
71677
|
"use strict";
|
|
71552
71678
|
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
71553
71679
|
require_chunk_Cek0wNdY();
|
|
71554
|
-
var require_dist10 =
|
|
71680
|
+
var require_dist10 = require_dist_DdRxWA7g();
|
|
71555
71681
|
var NO_DEVICES = "liveness:no-devices";
|
|
71556
71682
|
var ALL_OFFLINE = "liveness:all-devices-offline";
|
|
71557
71683
|
var NO_FOOTAGE_PREFIX = "liveness:no-footage:";
|
|
@@ -71747,7 +71873,7 @@ var require_local_auth_addon = __commonJS({
|
|
|
71747
71873
|
[Symbol.toStringTag]: { value: "Module" }
|
|
71748
71874
|
});
|
|
71749
71875
|
var require_chunk = require_chunk_Cek0wNdY();
|
|
71750
|
-
var require_dist10 =
|
|
71876
|
+
var require_dist10 = require_dist_DdRxWA7g();
|
|
71751
71877
|
var node_crypto = __require("crypto");
|
|
71752
71878
|
node_crypto = require_chunk.__toESM(node_crypto);
|
|
71753
71879
|
var crypto$1 = __require("crypto");
|
|
@@ -79560,7 +79686,7 @@ var require_loki_logging = __commonJS({
|
|
|
79560
79686
|
[Symbol.toStringTag]: { value: "Module" }
|
|
79561
79687
|
});
|
|
79562
79688
|
require_chunk_Cek0wNdY();
|
|
79563
|
-
var require_dist10 =
|
|
79689
|
+
var require_dist10 = require_dist_DdRxWA7g();
|
|
79564
79690
|
function sanitizeLabelName(raw) {
|
|
79565
79691
|
const replaced = raw.replaceAll(/[^a-zA-Z0-9_]/g, "_");
|
|
79566
79692
|
return /^[a-zA-Z_]/.test(replaced) ? replaced : `_${replaced}`;
|
|
@@ -80147,7 +80273,7 @@ var require_native_metrics_addon = __commonJS({
|
|
|
80147
80273
|
[Symbol.toStringTag]: { value: "Module" }
|
|
80148
80274
|
});
|
|
80149
80275
|
var require_chunk = require_chunk_Cek0wNdY();
|
|
80150
|
-
var require_dist10 =
|
|
80276
|
+
var require_dist10 = require_dist_DdRxWA7g();
|
|
80151
80277
|
var node_fs_promises = __require("fs/promises");
|
|
80152
80278
|
var node_fs = __require("fs");
|
|
80153
80279
|
node_fs = require_chunk.__toESM(node_fs);
|
|
@@ -82900,7 +83026,7 @@ var require_filesystem_storage_addon = __commonJS({
|
|
|
82900
83026
|
[Symbol.toStringTag]: { value: "Module" }
|
|
82901
83027
|
});
|
|
82902
83028
|
var require_chunk = require_chunk_Cek0wNdY();
|
|
82903
|
-
var require_dist10 =
|
|
83029
|
+
var require_dist10 = require_dist_DdRxWA7g();
|
|
82904
83030
|
var node_crypto = __require("crypto");
|
|
82905
83031
|
var node_fs_promises = __require("fs/promises");
|
|
82906
83032
|
var node_path = __require("path");
|
|
@@ -84127,8 +84253,8 @@ var require_sqlite_settings_addon = __commonJS({
|
|
|
84127
84253
|
[Symbol.toStringTag]: { value: "Module" }
|
|
84128
84254
|
});
|
|
84129
84255
|
var require_chunk = require_chunk_Cek0wNdY();
|
|
84130
|
-
var require_dist10 =
|
|
84131
|
-
var require_retired_settings_keys =
|
|
84256
|
+
var require_dist10 = require_dist_DdRxWA7g();
|
|
84257
|
+
var require_retired_settings_keys = require_retired_settings_keys_C_jOWHI0();
|
|
84132
84258
|
var require_wal_checkpoint_policy = require_wal_checkpoint_policy_CCJZngds();
|
|
84133
84259
|
var node_crypto = __require("crypto");
|
|
84134
84260
|
var node_path = __require("path");
|
|
@@ -84948,11 +85074,12 @@ var require_sqlite_settings_addon = __commonJS({
|
|
|
84948
85074
|
async insert({ namespace, collection, record }) {
|
|
84949
85075
|
const scoped = this.scopedName(namespace, collection);
|
|
84950
85076
|
const decl = this.requireDeclared(scoped);
|
|
84951
|
-
const
|
|
84952
|
-
const row = { [decl.primaryKey]:
|
|
85077
|
+
const suppliedOrMinted = decl.autoPrimaryKey ? null : record.id || (0, node_crypto.randomUUID)();
|
|
85078
|
+
const row = decl.autoPrimaryKey ? {} : { [decl.primaryKey]: suppliedOrMinted };
|
|
84953
85079
|
if (decl.columns.size === 1 && decl.columns.has("data")) row["data"] = JSON.stringify(record.data);
|
|
84954
85080
|
else for (const [k, v] of Object.entries(record.data)) if (decl.columns.has(k)) row[k] = this.serializeColumnValue(v);
|
|
84955
|
-
await this.tableInsert(scoped, row);
|
|
85081
|
+
const rowid = await this.tableInsert(scoped, row);
|
|
85082
|
+
return { id: suppliedOrMinted ?? Number(rowid) };
|
|
84956
85083
|
}
|
|
84957
85084
|
/**
|
|
84958
85085
|
* Insert a batch in ONE transaction, on ONE prepared statement.
|
|
@@ -85829,6 +85956,8 @@ var require_sqlite_settings_addon = __commonJS({
|
|
|
85829
85956
|
this.declaredCollections.delete(table);
|
|
85830
85957
|
return { rows };
|
|
85831
85958
|
}
|
|
85959
|
+
/** Returns SQLite's `lastInsertRowid` — the only place an auto-assigned key
|
|
85960
|
+
* is knowable (D473). */
|
|
85832
85961
|
async tableInsert(table, row) {
|
|
85833
85962
|
const keys = Object.keys(row);
|
|
85834
85963
|
const cols = keys.map((k) => `"${k}"`).join(", ");
|
|
@@ -85837,7 +85966,7 @@ var require_sqlite_settings_addon = __commonJS({
|
|
|
85837
85966
|
const v = row[k];
|
|
85838
85967
|
return typeof v === "object" && v !== null ? JSON.stringify(v) : v;
|
|
85839
85968
|
});
|
|
85840
|
-
this.getDb().prepare(`INSERT INTO "${table}" (${cols}) VALUES (${placeholders})`).run(...values);
|
|
85969
|
+
return this.getDb().prepare(`INSERT INTO "${table}" (${cols}) VALUES (${placeholders})`).run(...values).lastInsertRowid;
|
|
85841
85970
|
}
|
|
85842
85971
|
async tableUpdate(table, filter, updates) {
|
|
85843
85972
|
const setClauses = [];
|
|
@@ -86864,7 +86993,7 @@ var require_storage_orchestrator_addon = __commonJS({
|
|
|
86864
86993
|
[Symbol.toStringTag]: { value: "Module" }
|
|
86865
86994
|
});
|
|
86866
86995
|
var require_chunk = require_chunk_Cek0wNdY();
|
|
86867
|
-
var require_dist10 =
|
|
86996
|
+
var require_dist10 = require_dist_DdRxWA7g();
|
|
86868
86997
|
var require_hub_cap_forward = require_hub_cap_forward_DmHNjbB0();
|
|
86869
86998
|
var zod = require_zod();
|
|
86870
86999
|
var node_crypto = __require("crypto");
|
|
@@ -90514,7 +90643,7 @@ var require_system_config_addon = __commonJS({
|
|
|
90514
90643
|
[Symbol.toStringTag]: { value: "Module" }
|
|
90515
90644
|
});
|
|
90516
90645
|
require_chunk_Cek0wNdY();
|
|
90517
|
-
var require_dist10 =
|
|
90646
|
+
var require_dist10 = require_dist_DdRxWA7g();
|
|
90518
90647
|
var SECTION_TITLES = {
|
|
90519
90648
|
server: "Server",
|
|
90520
90649
|
auth: "Authentication"
|
|
@@ -108575,7 +108704,7 @@ var require_winston_logging = __commonJS({
|
|
|
108575
108704
|
[Symbol.toStringTag]: { value: "Module" }
|
|
108576
108705
|
});
|
|
108577
108706
|
var require_chunk = require_chunk_Cek0wNdY();
|
|
108578
|
-
var require_dist10 =
|
|
108707
|
+
var require_dist10 = require_dist_DdRxWA7g();
|
|
108579
108708
|
var require_formatter = require_formatter_DqAKDlvN();
|
|
108580
108709
|
var node_path = __require("path");
|
|
108581
108710
|
node_path = require_chunk.__toESM(node_path);
|
|
@@ -121311,9 +121440,9 @@ var require_dist2 = __commonJS({
|
|
|
121311
121440
|
}
|
|
121312
121441
|
});
|
|
121313
121442
|
|
|
121314
|
-
// ../system/dist/manifest-system-deps-
|
|
121315
|
-
var
|
|
121316
|
-
"../system/dist/manifest-system-deps-
|
|
121443
|
+
// ../system/dist/manifest-system-deps-8x1jgPz_.js
|
|
121444
|
+
var require_manifest_system_deps_8x1jgPz = __commonJS({
|
|
121445
|
+
"../system/dist/manifest-system-deps-8x1jgPz_.js"(exports) {
|
|
121317
121446
|
"use strict";
|
|
121318
121447
|
var require_chunk = require_chunk_Cek0wNdY();
|
|
121319
121448
|
require_hub_cap_forward_DmHNjbB0();
|
|
@@ -121812,7 +121941,7 @@ var require_manifest_system_deps_YYKKCKSF = __commonJS({
|
|
|
121812
121941
|
}
|
|
121813
121942
|
function formatMeshQueue(peers) {
|
|
121814
121943
|
if (peers === void 0) return "";
|
|
121815
|
-
const total = peers.reduce((
|
|
121944
|
+
const total = peers.reduce((sum2, p) => sum2 + p.queuedBytes, 0);
|
|
121816
121945
|
const top = peers.filter((p) => p.queuedBytes > 0).toSorted((a, b) => b.queuedBytes - a.queuedBytes || a.nodeId.localeCompare(b.nodeId)).slice(0, 3).map((p) => `${p.nodeId}:${kb(p.queuedBytes)}`).join(",");
|
|
121817
121946
|
return ` meshQueued=${kb(total)}kB` + (top.length === 0 ? "" : ` meshQueuedTop=${top}`);
|
|
121818
121947
|
}
|
|
@@ -122165,6 +122294,98 @@ var require_manifest_system_deps_YYKKCKSF = __commonJS({
|
|
|
122165
122294
|
const perMin = (n) => window2.windowMs <= 0 ? "?" : (n / (window2.windowMs / 6e4)).toFixed(1);
|
|
122166
122295
|
return ` gc=maj${window2.majors}/min${window2.minors}/inc${window2.incrementals}@${Math.round(window2.windowMs / 1e3)}s gcMajPerMin=${perMin(window2.majors)} gcPauseMs=${Math.round(window2.pauseMs)}`;
|
|
122167
122296
|
}
|
|
122297
|
+
function createProcessCpuCensus(options) {
|
|
122298
|
+
let windowStart = options.startedAt;
|
|
122299
|
+
let cpuAtStart = options.cpuUsageUs();
|
|
122300
|
+
let tasksAtStart = options.readTasks();
|
|
122301
|
+
return { read: (at) => {
|
|
122302
|
+
const windowMs = at - windowStart;
|
|
122303
|
+
if (windowMs < 1e3) return null;
|
|
122304
|
+
const cpuNow = options.cpuUsageUs();
|
|
122305
|
+
const tasksNow = options.readTasks();
|
|
122306
|
+
const cpuUs = cpuNow - cpuAtStart;
|
|
122307
|
+
const percentOfCore = cpuUs <= 0 ? 0 : round1(cpuUs / 1e3 / windowMs * 100);
|
|
122308
|
+
const reading = {
|
|
122309
|
+
percentOfCore,
|
|
122310
|
+
windowMs,
|
|
122311
|
+
v8Workers: shareOfWorkers(tasksAtStart, tasksNow, percentOfCore)
|
|
122312
|
+
};
|
|
122313
|
+
windowStart = at;
|
|
122314
|
+
cpuAtStart = cpuNow;
|
|
122315
|
+
tasksAtStart = tasksNow;
|
|
122316
|
+
return reading;
|
|
122317
|
+
} };
|
|
122318
|
+
}
|
|
122319
|
+
function shareOfWorkers(before, after, percentOfCore) {
|
|
122320
|
+
if (before === null || after === null) return null;
|
|
122321
|
+
const b = sum(before);
|
|
122322
|
+
const a = sum(after);
|
|
122323
|
+
const workerTicks = a.worker - b.worker;
|
|
122324
|
+
const totalTicks = a.total - b.total;
|
|
122325
|
+
if (workerTicks < 0 || totalTicks <= 0 || workerTicks > totalTicks) return null;
|
|
122326
|
+
return {
|
|
122327
|
+
percentOfCore: round1(percentOfCore * (workerTicks / totalTicks)),
|
|
122328
|
+
threads: a.workerThreads
|
|
122329
|
+
};
|
|
122330
|
+
}
|
|
122331
|
+
var V8_WORKER_COMM = "V8Worker";
|
|
122332
|
+
function sum(tasks) {
|
|
122333
|
+
let worker2 = 0;
|
|
122334
|
+
let total = 0;
|
|
122335
|
+
let workerThreads = 0;
|
|
122336
|
+
for (const t of tasks) {
|
|
122337
|
+
total += t.ticks;
|
|
122338
|
+
if (t.comm === V8_WORKER_COMM) {
|
|
122339
|
+
worker2 += t.ticks;
|
|
122340
|
+
workerThreads += 1;
|
|
122341
|
+
}
|
|
122342
|
+
}
|
|
122343
|
+
return {
|
|
122344
|
+
worker: worker2,
|
|
122345
|
+
total,
|
|
122346
|
+
workerThreads
|
|
122347
|
+
};
|
|
122348
|
+
}
|
|
122349
|
+
function round1(n) {
|
|
122350
|
+
return Math.round(n * 10) / 10;
|
|
122351
|
+
}
|
|
122352
|
+
function readSelfTaskTicks() {
|
|
122353
|
+
try {
|
|
122354
|
+
const tids = (0, node_fs.readdirSync)("/proc/self/task");
|
|
122355
|
+
const out = [];
|
|
122356
|
+
for (const tid of tids) {
|
|
122357
|
+
const parsed = parseTaskStat(tid);
|
|
122358
|
+
if (parsed !== null) out.push(parsed);
|
|
122359
|
+
}
|
|
122360
|
+
return out.length === 0 ? null : out;
|
|
122361
|
+
} catch {
|
|
122362
|
+
return null;
|
|
122363
|
+
}
|
|
122364
|
+
}
|
|
122365
|
+
function parseTaskStat(tid) {
|
|
122366
|
+
try {
|
|
122367
|
+
const raw = (0, node_fs.readFileSync)(`/proc/self/task/${tid}/stat`, "utf8");
|
|
122368
|
+
const close = raw.lastIndexOf(") ");
|
|
122369
|
+
const open = raw.indexOf(" (");
|
|
122370
|
+
if (close < 0 || open < 0 || close <= open) return null;
|
|
122371
|
+
const comm = raw.slice(open + 2, close);
|
|
122372
|
+
const fields = raw.slice(close + 2).split(" ");
|
|
122373
|
+
const utime = Number(fields[11]);
|
|
122374
|
+
const stime = Number(fields[12]);
|
|
122375
|
+
if (!Number.isFinite(utime) || !Number.isFinite(stime)) return null;
|
|
122376
|
+
return {
|
|
122377
|
+
comm,
|
|
122378
|
+
ticks: utime + stime
|
|
122379
|
+
};
|
|
122380
|
+
} catch {
|
|
122381
|
+
return null;
|
|
122382
|
+
}
|
|
122383
|
+
}
|
|
122384
|
+
function formatProcessCpu(reading) {
|
|
122385
|
+
if (reading === null || reading === void 0) return "";
|
|
122386
|
+
const workers = reading.v8Workers;
|
|
122387
|
+
return ` procCpu=${reading.percentOfCore.toFixed(1)}%` + (workers === null ? "" : ` v8WorkerCpu=${workers.percentOfCore.toFixed(1)}%/${workers.threads}thr`);
|
|
122388
|
+
}
|
|
122168
122389
|
var HUB_MAIN_HEAP_WATCH_LABEL = "hub-main";
|
|
122169
122390
|
var HEAP_WATCH_INTERVAL_MS = 6e4;
|
|
122170
122391
|
var HEAP_WATCH_WARN_RATIO = 0.8;
|
|
@@ -122335,6 +122556,15 @@ var require_manifest_system_deps_YYKKCKSF = __commonJS({
|
|
|
122335
122556
|
const now = reclaimOptions?.now ?? (() => Date.now());
|
|
122336
122557
|
const gcObserver = probes?.gcObserver ?? nodeGcObserver();
|
|
122337
122558
|
const gcCensus = createGcCensus(gcObserver.install, gcObserver.kinds, now());
|
|
122559
|
+
const cpuProbe = probes?.processCpu;
|
|
122560
|
+
const processCpu = createProcessCpuCensus({
|
|
122561
|
+
cpuUsageUs: cpuProbe?.cpuUsageUs ?? (() => {
|
|
122562
|
+
const u = process.cpuUsage();
|
|
122563
|
+
return u.user + u.system;
|
|
122564
|
+
}),
|
|
122565
|
+
readTasks: cpuProbe?.readTasks ?? readSelfTaskTicks,
|
|
122566
|
+
startedAt: now()
|
|
122567
|
+
});
|
|
122338
122568
|
const triggerMb = reclaimOptions?.triggerMb ?? 1024;
|
|
122339
122569
|
const minIntervalMs = reclaimOptions?.minIntervalMs ?? 12e4;
|
|
122340
122570
|
const steadyStateIntervalMs = reclaimOptions?.steadyStateIntervalMs ?? 6e5;
|
|
@@ -122410,7 +122640,7 @@ var require_manifest_system_deps_YYKKCKSF = __commonJS({
|
|
|
122410
122640
|
const due = at - lastLoggedAt >= intervalMs;
|
|
122411
122641
|
if (mode === "escalated" || due) {
|
|
122412
122642
|
lastLoggedAt = at;
|
|
122413
|
-
const line = format2(label, sample, loopDelay?.read(), budgetMb, `${formatHeapSpaces(readSpaces())}${formatEventPlane(eventPlane?.read())}` + formatSocketPlane(socketPlane?.read()) + formatMeshQueue(meshQueue?.()) + formatGcCensus(gcCensus?.read(at)));
|
|
122643
|
+
const line = format2(label, sample, loopDelay?.read(), budgetMb, `${formatHeapSpaces(readSpaces())}${formatEventPlane(eventPlane?.read())}` + formatSocketPlane(socketPlane?.read()) + formatMeshQueue(meshQueue?.()) + formatGcCensus(gcCensus?.read(at)) + formatProcessCpu(processCpu.read(at)));
|
|
122414
122644
|
if (sample.nearLimit) sink.warn(`${line} \u2014 APPROACHING HEAP LIMIT`);
|
|
122415
122645
|
else if (mode === "escalated") sink.warn(`${line} \u2014 heap elevated, sampling every ${probeIntervalMs}ms`);
|
|
122416
122646
|
else sink.info(line);
|
|
@@ -130734,11 +130964,11 @@ var require_manifest_system_deps_YYKKCKSF = __commonJS({
|
|
|
130734
130964
|
}
|
|
130735
130965
|
});
|
|
130736
130966
|
|
|
130737
|
-
// ../system/dist/custom-action-registry-
|
|
130738
|
-
var
|
|
130739
|
-
"../system/dist/custom-action-registry-
|
|
130967
|
+
// ../system/dist/custom-action-registry-BTB-LgGN.js
|
|
130968
|
+
var require_custom_action_registry_BTB_LgGN = __commonJS({
|
|
130969
|
+
"../system/dist/custom-action-registry-BTB-LgGN.js"(exports) {
|
|
130740
130970
|
"use strict";
|
|
130741
|
-
var require_dist10 =
|
|
130971
|
+
var require_dist10 = require_dist_DdRxWA7g();
|
|
130742
130972
|
var CustomActionRegistry = class {
|
|
130743
130973
|
byAddon = /* @__PURE__ */ new Map();
|
|
130744
130974
|
registerAddon(addonId, catalog, handler) {
|
|
@@ -134552,7 +134782,7 @@ var require_dist3 = __commonJS({
|
|
|
134552
134782
|
"use strict";
|
|
134553
134783
|
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
134554
134784
|
var require_chunk = require_chunk_Cek0wNdY();
|
|
134555
|
-
var require_dist10 =
|
|
134785
|
+
var require_dist10 = require_dist_DdRxWA7g();
|
|
134556
134786
|
var require_builtins_alerts_alerts_addon = require_alerts_addon();
|
|
134557
134787
|
require_alerts();
|
|
134558
134788
|
var require_formatter = require_formatter_DqAKDlvN();
|
|
@@ -134579,9 +134809,9 @@ var require_dist3 = __commonJS({
|
|
|
134579
134809
|
var require_builtins_winston_logging_index = require_winston_logging();
|
|
134580
134810
|
var require_event_loop_stall_monitor = require_event_loop_stall_monitor_CAsHdMwP();
|
|
134581
134811
|
var require_tls$1 = require_tls_BFs4PzoW();
|
|
134582
|
-
var require_manifest_system_deps =
|
|
134812
|
+
var require_manifest_system_deps = require_manifest_system_deps_8x1jgPz();
|
|
134583
134813
|
var require_resource_monitor = require_resource_monitor_LVE1BoLs();
|
|
134584
|
-
var require_custom_action_registry =
|
|
134814
|
+
var require_custom_action_registry = require_custom_action_registry_BTB_LgGN();
|
|
134585
134815
|
var zod = require_zod();
|
|
134586
134816
|
var node_crypto = __require("crypto");
|
|
134587
134817
|
var _camstack_types_node = require_node();
|
|
@@ -215695,6 +215925,56 @@ var require_dist4 = __commonJS({
|
|
|
215695
215925
|
var require_enums2 = require_enums();
|
|
215696
215926
|
var require_err_msg = require_err_msg_COpsHMw2();
|
|
215697
215927
|
var zod = require_zod();
|
|
215928
|
+
var MEDIA_OWNER_TYPES = [
|
|
215929
|
+
"track",
|
|
215930
|
+
"summary",
|
|
215931
|
+
"face",
|
|
215932
|
+
"identity",
|
|
215933
|
+
"plate",
|
|
215934
|
+
"vehicle",
|
|
215935
|
+
"scene",
|
|
215936
|
+
"motion",
|
|
215937
|
+
"object",
|
|
215938
|
+
"audio"
|
|
215939
|
+
];
|
|
215940
|
+
var OWNER_TYPES = new Set(MEDIA_OWNER_TYPES);
|
|
215941
|
+
var DIGITS = /^\d+$/;
|
|
215942
|
+
function isOwnerType(value) {
|
|
215943
|
+
return OWNER_TYPES.has(value);
|
|
215944
|
+
}
|
|
215945
|
+
function parseMediaOwnerKey(key) {
|
|
215946
|
+
const parts = key.split(":");
|
|
215947
|
+
if (parts.length !== 3 && parts.length !== 4) return null;
|
|
215948
|
+
const [ownerType, ownerId, fileKind, timestamp] = parts;
|
|
215949
|
+
if (ownerType === void 0 || !isOwnerType(ownerType)) return null;
|
|
215950
|
+
if (ownerId === void 0 || ownerId.length === 0) return null;
|
|
215951
|
+
if (fileKind === void 0 || fileKind.length === 0) return null;
|
|
215952
|
+
if (timestamp === void 0) return {
|
|
215953
|
+
ownerType,
|
|
215954
|
+
ownerId,
|
|
215955
|
+
fileKind
|
|
215956
|
+
};
|
|
215957
|
+
if (!DIGITS.test(timestamp)) return null;
|
|
215958
|
+
return {
|
|
215959
|
+
ownerType,
|
|
215960
|
+
ownerId,
|
|
215961
|
+
fileKind,
|
|
215962
|
+
timestampMs: Number(timestamp)
|
|
215963
|
+
};
|
|
215964
|
+
}
|
|
215965
|
+
function formatMediaOwnerKey(key) {
|
|
215966
|
+
const head = `${key.ownerType}:${key.ownerId}:${key.fileKind}`;
|
|
215967
|
+
return key.timestampMs === void 0 ? head : `${head}:${key.timestampMs}`;
|
|
215968
|
+
}
|
|
215969
|
+
var EVENT_OWNER_TYPES = [
|
|
215970
|
+
"motion",
|
|
215971
|
+
"object",
|
|
215972
|
+
"audio"
|
|
215973
|
+
];
|
|
215974
|
+
var EVENT_OWNER_TYPE_SET = new Set(EVENT_OWNER_TYPES);
|
|
215975
|
+
function isEventOwnerType(ownerType) {
|
|
215976
|
+
return EVENT_OWNER_TYPE_SET.has(ownerType);
|
|
215977
|
+
}
|
|
215698
215978
|
function buildAddonRouteProvider(id, routes) {
|
|
215699
215979
|
return {
|
|
215700
215980
|
id,
|
|
@@ -222599,8 +222879,18 @@ ${recipe.triggers.map((t, i) => emitTrigger(t, i)).join("\n\n")}
|
|
|
222599
222879
|
insert: require_sleep.method(zod.z.object({
|
|
222600
222880
|
namespace: zod.z.string().optional(),
|
|
222601
222881
|
collection: zod.z.string(),
|
|
222602
|
-
record:
|
|
222603
|
-
|
|
222882
|
+
record: zod.z.object({
|
|
222883
|
+
id: zod.z.string().optional(),
|
|
222884
|
+
data: zod.z.record(zod.z.string(), zod.z.unknown())
|
|
222885
|
+
})
|
|
222886
|
+
}), zod.z.object({
|
|
222887
|
+
/**
|
|
222888
|
+
* The id the row ACTUALLY got (D473): the one supplied, the UUID minted
|
|
222889
|
+
* for an absent one, or the ROWID SQLite assigned on an `INTEGER`
|
|
222890
|
+
* primary key — which is the only place an auto key is knowable.
|
|
222891
|
+
*/
|
|
222892
|
+
id: zod.z.union([zod.z.string(), zod.z.number()])
|
|
222893
|
+
}), { kind: "mutation" }),
|
|
222604
222894
|
/**
|
|
222605
222895
|
* Insert MANY records in ONE transaction, returning how many landed.
|
|
222606
222896
|
*
|
|
@@ -222813,8 +223103,18 @@ ${recipe.triggers.map((t, i) => emitTrigger(t, i)).join("\n\n")}
|
|
|
222813
223103
|
insert: require_sleep.method(zod.z.object({
|
|
222814
223104
|
namespace: zod.z.string().optional(),
|
|
222815
223105
|
collection: zod.z.string(),
|
|
222816
|
-
record:
|
|
222817
|
-
|
|
223106
|
+
record: zod.z.object({
|
|
223107
|
+
id: zod.z.string().optional(),
|
|
223108
|
+
data: zod.z.record(zod.z.string(), zod.z.unknown())
|
|
223109
|
+
})
|
|
223110
|
+
}), zod.z.object({
|
|
223111
|
+
/**
|
|
223112
|
+
* The id the row ACTUALLY got (D473): the one supplied, the UUID minted
|
|
223113
|
+
* for an absent one, or the ROWID SQLite assigned on an `INTEGER`
|
|
223114
|
+
* primary key — which is the only place an auto key is knowable.
|
|
223115
|
+
*/
|
|
223116
|
+
id: zod.z.union([zod.z.string(), zod.z.number()])
|
|
223117
|
+
}), {
|
|
222818
223118
|
kind: "mutation",
|
|
222819
223119
|
auth: "admin"
|
|
222820
223120
|
}),
|
|
@@ -230330,7 +230630,20 @@ ${recipe.triggers.map((t, i) => emitTrigger(t, i)).join("\n\n")}
|
|
|
230330
230630
|
...TrackRetrainFields
|
|
230331
230631
|
});
|
|
230332
230632
|
var BaseEventFields = {
|
|
230333
|
-
|
|
230633
|
+
/**
|
|
230634
|
+
* A SQLite ROWID, assigned by the database (D474).
|
|
230635
|
+
*
|
|
230636
|
+
* Was a 36-character UUID and cost 263 MB of a 1 117 MB database — paid
|
|
230637
|
+
* TWICE per row, in the row and in the primary-key index, across 2.1 million
|
|
230638
|
+
* motion, audio and object events. An `INTEGER PRIMARY KEY` in SQLite **is**
|
|
230639
|
+
* the rowid: the table itself is that B-tree, so the index stops existing
|
|
230640
|
+
* rather than getting smaller. No shorter string does that.
|
|
230641
|
+
*
|
|
230642
|
+
* Defined once here for all three event kinds, which is why they move
|
|
230643
|
+
* together: a per-table migration would have forked this and
|
|
230644
|
+
* `COMMON_BASE_COLUMNS` and reunited them two stages later.
|
|
230645
|
+
*/
|
|
230646
|
+
id: zod.z.number().int(),
|
|
230334
230647
|
deviceId: zod.z.number(),
|
|
230335
230648
|
timestamp: zod.z.number()
|
|
230336
230649
|
};
|
|
@@ -230349,7 +230662,34 @@ ${recipe.triggers.map((t, i) => emitTrigger(t, i)).join("\n\n")}
|
|
|
230349
230662
|
/** Omitted in slim projection. */
|
|
230350
230663
|
frameHeight: zod.z.number().optional(),
|
|
230351
230664
|
/** Populated by B5 (recording playback URL for this event). */
|
|
230352
|
-
mediaUrl: zod.z.string().optional()
|
|
230665
|
+
mediaUrl: zod.z.string().optional(),
|
|
230666
|
+
/**
|
|
230667
|
+
* One row per motion EPISODE, not one per push (D475). `null` while the
|
|
230668
|
+
* episode is still open — a further rising edge extends it in place rather
|
|
230669
|
+
* than inserting a new row. Set once, at close, to `lastOnAt - startedAt`
|
|
230670
|
+
* (the span from the first rising edge to the LAST one, deliberately NOT
|
|
230671
|
+
* `closedAt - startedAt` — the close delay is a quiet CONFIRMATION, not
|
|
230672
|
+
* movement, and folding it in would report `MOTION_CLOSE_AFTER_MS` of
|
|
230673
|
+
* motion for an instantaneous trigger).
|
|
230674
|
+
*
|
|
230675
|
+
* **Absent** (not merely `null`) on a row written before D475 — that means
|
|
230676
|
+
* "closed the old way, before this column existed", never "still open".
|
|
230677
|
+
* Nothing in this codebase may read an absent `durationMs` as an open
|
|
230678
|
+
* episode; only `null` means open.
|
|
230679
|
+
*/
|
|
230680
|
+
durationMs: zod.z.number().nullable().optional(),
|
|
230681
|
+
/**
|
|
230682
|
+
* Ms offsets from `timestamp` (the episode's own first rising edge, so the
|
|
230683
|
+
* first entry is always `0`) of every genuine off→on transition the
|
|
230684
|
+
* episode saw — "ogni evento on si deve salvare" (D475). NOT one entry per
|
|
230685
|
+
* push: a firmware source that keepalives at ~1 Hz for the whole burst
|
|
230686
|
+
* (Reolink, Hikvision) produces exactly one edge; a source that reports an
|
|
230687
|
+
* explicit `false` mid-episode and then resumes before the quiet window
|
|
230688
|
+
* elapses produces another. Stored compactly — see `motion-edge-codec.ts`
|
|
230689
|
+
* — and decoded back to this shape on read. Absent/empty on a legacy row,
|
|
230690
|
+
* which must never be read as "no episode happened here".
|
|
230691
|
+
*/
|
|
230692
|
+
edges: zod.z.array(zod.z.number()).readonly().optional()
|
|
230353
230693
|
});
|
|
230354
230694
|
var DetectionSourceSchema = zod.z.enum(["pipeline", "onboard"]);
|
|
230355
230695
|
var ZoneCrossingDirectionSchema = zod.z.enum(["enter", "exit"]);
|
|
@@ -230380,6 +230720,23 @@ ${recipe.triggers.map((t, i) => emitTrigger(t, i)).join("\n\n")}
|
|
|
230380
230720
|
* includes it (it is light). Absent on rows written before this field.
|
|
230381
230721
|
*/
|
|
230382
230722
|
frameId: zod.z.string().optional(),
|
|
230723
|
+
/**
|
|
230724
|
+
* A PRODUCER-chosen key that makes a synthetic event's emission idempotent
|
|
230725
|
+
* (D474).
|
|
230726
|
+
*
|
|
230727
|
+
* Only the package detector writes it, and it exists because the event id
|
|
230728
|
+
* stopped being choosable: the delivery and pick-up rows used to BE their
|
|
230729
|
+
* dedupe key (`pa-pkg-<entryId>-delivered`), which is how "never emit a
|
|
230730
|
+
* second delivery for this entry" survived a restart. An `INTEGER` rowid is
|
|
230731
|
+
* assigned by SQLite, so that key had to move off the primary key rather
|
|
230732
|
+
* than be dropped — a detector that cannot recognise its own row re-delivers
|
|
230733
|
+
* every parcel on every boot.
|
|
230734
|
+
*
|
|
230735
|
+
* Absent on every other object event, and on every row written before this
|
|
230736
|
+
* field. Never a substitute for `id`: it is unique per (producer, occasion),
|
|
230737
|
+
* not per row, and nothing addresses a row by it.
|
|
230738
|
+
*/
|
|
230739
|
+
idempotencyKey: zod.z.string().optional(),
|
|
230383
230740
|
/** Omitted in slim projection. */
|
|
230384
230741
|
trackId: zod.z.string().optional(),
|
|
230385
230742
|
className: zod.z.string(),
|
|
@@ -239415,14 +239772,60 @@ ${recipe.triggers.map((t, i) => emitTrigger(t, i)).join("\n\n")}
|
|
|
239415
239772
|
}), { kind: "mutation" })
|
|
239416
239773
|
}
|
|
239417
239774
|
};
|
|
239775
|
+
var MOTION_CLOSE_AFTER_MS = 15e3;
|
|
239418
239776
|
var MotionStatusSchema = zod.z.object({
|
|
239419
239777
|
detected: zod.z.boolean(),
|
|
239420
239778
|
/** Ms epoch of the last detected-true observation. Null if never detected. */
|
|
239421
239779
|
lastDetectedAt: zod.z.number().nullable(),
|
|
239422
239780
|
/**
|
|
239423
|
-
*
|
|
239424
|
-
*
|
|
239425
|
-
*
|
|
239781
|
+
* `MOTION_CLOSE_AFTER_MS` while `detected: true` on a `Camera` device,
|
|
239782
|
+
* `null` while false and on every `Sensor` device (D475) — see that
|
|
239783
|
+
* constant's doc for the one-authority rule.
|
|
239784
|
+
*
|
|
239785
|
+
* ## Reading this field still arms nothing
|
|
239786
|
+
*
|
|
239787
|
+
* It reads like an instruction to the consumer ("revert after N ms if
|
|
239788
|
+
* no fresh push arrives") and it is not one: nothing in this repo reads
|
|
239789
|
+
* the LIVE cap value to drive a timer. `pipeline-analytics`'s motion-episode
|
|
239790
|
+
* close DOES now use the same number — `MOTION_CLOSE_AFTER_MS` — but as an
|
|
239791
|
+
* imported constant, not as a read of `device.state.motion.value`, so this
|
|
239792
|
+
* field stays what it always was: DESCRIPTIVE output, mirroring an answer
|
|
239793
|
+
* computed elsewhere. Building a self-clear timer out of a READ of this
|
|
239794
|
+
* field would add a second falling-edge authority beside whichever one
|
|
239795
|
+
* already owns the device, and two that can disagree are worse than one.
|
|
239796
|
+
* Consumers that need a falling edge SHAPED differently — held open across
|
|
239797
|
+
* a flapping source — debounce on their own side and say so, as
|
|
239798
|
+
* `addon-export-alexa/src/motion-clear-hold.ts` and
|
|
239799
|
+
* `addon-export-hap`'s `RESET_DEBOUNCE_MS` both do.
|
|
239800
|
+
*
|
|
239801
|
+
* ## Who writes it
|
|
239802
|
+
*
|
|
239803
|
+
* - **Cameras** — the runner's phase machine, `active → watching` on
|
|
239804
|
+
* `cooldown_expired`, which then writes this slice with
|
|
239805
|
+
* `detected: false` (`handlePhaseChanged` in
|
|
239806
|
+
* `pipeline-runner/index.ts`). It produces the FALLING edge, which
|
|
239807
|
+
* matters most for the sources that only ever push a rising one:
|
|
239808
|
+
* Reolink emits `MotionOnMotionChanged { detected: true }` and never
|
|
239809
|
+
* a false.
|
|
239810
|
+
* - **Sensors** (Home Assistant binary sensors, Homematic) — the
|
|
239811
|
+
* provider pushes the false itself, from the upstream system's own
|
|
239812
|
+
* state change. No phase machine is involved.
|
|
239813
|
+
*
|
|
239814
|
+
* ### The phase machine is CANONICAL, not sole — and that is a defect
|
|
239815
|
+
*
|
|
239816
|
+
* An earlier revision of this docblock (mine, 2026-09-12) claimed the
|
|
239817
|
+
* phase machine is the sole writer for a camera. It is not.
|
|
239818
|
+
* `hikvision-camera.ts:3464` and `amcrest-camera.ts:445` both call
|
|
239819
|
+
* `setCapSlice(motionCapability, …)` on their own rising edge, and
|
|
239820
|
+
* Hikvision's comment says why: it read THIS docblock, agreed the
|
|
239821
|
+
* runner is canonical, and wrote anyway to avoid per-tick churn. So
|
|
239822
|
+
* two authorities can disagree about one slice, which this repo
|
|
239823
|
+
* forbids, and the doc said otherwise — which is worse than saying
|
|
239824
|
+
* nothing, because it reads as verification.
|
|
239825
|
+
*
|
|
239826
|
+
* This predates D475 and is not fixed there: the fix touches every
|
|
239827
|
+
* camera provider. Recorded in D475's Consequences. Do not restore the
|
|
239828
|
+
* "sole writer" wording without also removing the other writers.
|
|
239426
239829
|
*/
|
|
239427
239830
|
autoClearAfterMs: zod.z.number().nullable()
|
|
239428
239831
|
});
|
|
@@ -239488,7 +239891,11 @@ ${recipe.triggers.map((t, i) => emitTrigger(t, i)).join("\n\n")}
|
|
|
239488
239891
|
*/
|
|
239489
239892
|
runtimeState: MotionStatusSchema,
|
|
239490
239893
|
/**
|
|
239491
|
-
* Runtime-state durability: **session** —
|
|
239894
|
+
* Runtime-state durability: **session** — every writer of this slice
|
|
239895
|
+
* writes only on an EDGE, so a restored `detected: true` would stay
|
|
239896
|
+
* frozen until the next one instead of being corrected. The next edge
|
|
239897
|
+
* re-publishes the real state. (On who the writers are, and why there
|
|
239898
|
+
* is more than one, see `autoClearAfterMs` above.)
|
|
239492
239899
|
*
|
|
239493
239900
|
* See `RuntimeStateDurability`. Enforced by
|
|
239494
239901
|
* `scripts/check-runtime-state-durability.ts`.
|
|
@@ -261124,6 +261531,7 @@ ${recipe.triggers.map((t, i) => emitTrigger(t, i)).join("\n\n")}
|
|
|
261124
261531
|
exports.EVENTFUL_CAP_NAMES = EVENTFUL_CAP_NAMES;
|
|
261125
261532
|
exports.EVENT_DENSITY_BATCH_MAX = EVENT_DENSITY_BATCH_MAX;
|
|
261126
261533
|
exports.EVENT_KIND_BY_CAP = EVENT_KIND_BY_CAP;
|
|
261534
|
+
exports.EVENT_OWNER_TYPES = EVENT_OWNER_TYPES;
|
|
261127
261535
|
exports.EVENT_PAD_MS = EVENT_PAD_MS;
|
|
261128
261536
|
exports.EVENT_TAXONOMY = EVENT_TAXONOMY;
|
|
261129
261537
|
exports.EXPORT_DENSE_MAX_RANGES = EXPORT_DENSE_MAX_RANGES;
|
|
@@ -261314,10 +261722,12 @@ ${recipe.triggers.map((t, i) => emitTrigger(t, i)).join("\n\n")}
|
|
|
261314
261722
|
exports.MAX_REASONS_PER_KEY = MAX_REASONS_PER_KEY;
|
|
261315
261723
|
exports.MAX_SENSOR_TRIGGER_DEVICES = MAX_SENSOR_TRIGGER_DEVICES;
|
|
261316
261724
|
exports.MAX_TRACK_DEBUG_NOTE_LEN = MAX_TRACK_DEBUG_NOTE_LEN;
|
|
261725
|
+
exports.MEDIA_OWNER_TYPES = MEDIA_OWNER_TYPES;
|
|
261317
261726
|
exports.METHOD_ACCESS_MAP = METHOD_ACCESS_MAP;
|
|
261318
261727
|
exports.METHOD_DEVICE_SELECTORS = METHOD_DEVICE_SELECTORS;
|
|
261319
261728
|
exports.MODEL_FORMATS = MODEL_FORMATS;
|
|
261320
261729
|
exports.MODEL_PROVIDER_IDS = MODEL_PROVIDER_IDS;
|
|
261730
|
+
exports.MOTION_CLOSE_AFTER_MS = MOTION_CLOSE_AFTER_MS;
|
|
261321
261731
|
exports.MOTION_TRIGGER_FEATURE = MOTION_TRIGGER_FEATURE;
|
|
261322
261732
|
exports.ManagedModelCatalogEntrySchema = ManagedModelCatalogEntrySchema;
|
|
261323
261733
|
exports.ManagedModelExtraFileSchema = ManagedModelExtraFileSchema;
|
|
@@ -262089,6 +262499,7 @@ ${recipe.triggers.map((t, i) => emitTrigger(t, i)).join("\n\n")}
|
|
|
262089
262499
|
exports.foldSnapshotByFunction = foldSnapshotByFunction;
|
|
262090
262500
|
exports.formatForBackend = formatForBackend;
|
|
262091
262501
|
exports.formatForRuntime = formatForRuntime;
|
|
262502
|
+
exports.formatMediaOwnerKey = formatMediaOwnerKey;
|
|
262092
262503
|
exports.gasCapability = gasCapability;
|
|
262093
262504
|
exports.gbToBytes = gbToBytes;
|
|
262094
262505
|
exports.generateAutomationBlock = generateAutomationBlock;
|
|
@@ -262124,6 +262535,7 @@ ${recipe.triggers.map((t, i) => emitTrigger(t, i)).join("\n\n")}
|
|
|
262124
262535
|
exports.isDeviceConfigCap = require_sleep.isDeviceConfigCap;
|
|
262125
262536
|
exports.isDeviceScopedCap = require_sleep.isDeviceScopedCap;
|
|
262126
262537
|
exports.isEvent = require_sleep.isEvent;
|
|
262538
|
+
exports.isEventOwnerType = isEventOwnerType;
|
|
262127
262539
|
exports.isFirstLevelMacroClass = isFirstLevelMacroClass;
|
|
262128
262540
|
exports.isIsolatedBuiltin = isIsolatedBuiltin;
|
|
262129
262541
|
exports.isLocationEnabled = isLocationEnabled;
|
|
@@ -262211,6 +262623,7 @@ ${recipe.triggers.map((t, i) => emitTrigger(t, i)).join("\n\n")}
|
|
|
262211
262623
|
exports.parseJsonArray = require_sleep.parseJsonArray;
|
|
262212
262624
|
exports.parseJsonObject = require_sleep.parseJsonObject;
|
|
262213
262625
|
exports.parseJsonUnknown = require_sleep.parseJsonUnknown;
|
|
262626
|
+
exports.parseMediaOwnerKey = parseMediaOwnerKey;
|
|
262214
262627
|
exports.parseProcStatus = parseProcStatus;
|
|
262215
262628
|
exports.parseProfileBrokerId = require_sleep.parseProfileBrokerId;
|
|
262216
262629
|
exports.parseRuleSection = parseRuleSection;
|
|
@@ -262981,6 +263394,7 @@ var require_server_root = __commonJS({
|
|
|
262981
263394
|
devUploadsDir: /* @__PURE__ */ __name(() => devUploadsDir, "devUploadsDir"),
|
|
262982
263395
|
emptyServerRootState: /* @__PURE__ */ __name(() => emptyServerRootState, "emptyServerRootState"),
|
|
262983
263396
|
findMissingNativePrebuilds: /* @__PURE__ */ __name(() => findMissingNativePrebuilds, "findMissingNativePrebuilds"),
|
|
263397
|
+
findUnappliedClosurePatches: /* @__PURE__ */ __name(() => findUnappliedClosurePatches, "findUnappliedClosurePatches"),
|
|
262984
263398
|
isDevChannelVersion: /* @__PURE__ */ __name(() => isDevChannelVersion, "isDevChannelVersion"),
|
|
262985
263399
|
isHostExternal: /* @__PURE__ */ __name(() => isHostExternal, "isHostExternal"),
|
|
262986
263400
|
isServerRootState: /* @__PURE__ */ __name(() => isServerRootState, "isServerRootState"),
|
|
@@ -263385,6 +263799,58 @@ var require_server_root = __commonJS({
|
|
|
263385
263799
|
return missing;
|
|
263386
263800
|
}
|
|
263387
263801
|
__name(findMissingNativePrebuilds, "findMissingNativePrebuilds");
|
|
263802
|
+
var CLOSURE_PATCH_PAYLOAD = [
|
|
263803
|
+
"node_modules",
|
|
263804
|
+
"@camstack",
|
|
263805
|
+
"server",
|
|
263806
|
+
"dist",
|
|
263807
|
+
"closure-patches"
|
|
263808
|
+
];
|
|
263809
|
+
var CLOSURE_PATCH_MANIFEST = "patch-reach.json";
|
|
263810
|
+
function fileContains(file, marker) {
|
|
263811
|
+
try {
|
|
263812
|
+
return fs3.readFileSync(file, "utf-8").includes(marker);
|
|
263813
|
+
} catch {
|
|
263814
|
+
return false;
|
|
263815
|
+
}
|
|
263816
|
+
}
|
|
263817
|
+
__name(fileContains, "fileContains");
|
|
263818
|
+
function findUnappliedClosurePatches(closureDir) {
|
|
263819
|
+
const payloadDir = path3.join(closureDir, ...CLOSURE_PATCH_PAYLOAD);
|
|
263820
|
+
let manifest;
|
|
263821
|
+
try {
|
|
263822
|
+
const raw = JSON.parse(fs3.readFileSync(path3.join(payloadDir, CLOSURE_PATCH_MANIFEST), "utf-8"));
|
|
263823
|
+
if (typeof raw !== "object" || raw === null) return [];
|
|
263824
|
+
manifest = raw;
|
|
263825
|
+
} catch {
|
|
263826
|
+
return [];
|
|
263827
|
+
}
|
|
263828
|
+
if (!Array.isArray(manifest.patches)) return [];
|
|
263829
|
+
const nm = path3.join(closureDir, "node_modules");
|
|
263830
|
+
const missing = [];
|
|
263831
|
+
for (const raw of manifest.patches) {
|
|
263832
|
+
if (raw.reach !== "closure-postinstall") continue;
|
|
263833
|
+
const pkg = raw.package;
|
|
263834
|
+
const markers = raw.markers;
|
|
263835
|
+
if (typeof pkg !== "string" || typeof markers !== "object" || markers === null) continue;
|
|
263836
|
+
const pkgDir = path3.join(nm, pkg);
|
|
263837
|
+
if (!fs3.existsSync(pkgDir)) {
|
|
263838
|
+
continue;
|
|
263839
|
+
}
|
|
263840
|
+
for (const [rel, list] of Object.entries(markers)) {
|
|
263841
|
+
if (!Array.isArray(list)) continue;
|
|
263842
|
+
const target = path3.join(pkgDir, ...rel.split("/"));
|
|
263843
|
+
for (const marker of list) {
|
|
263844
|
+
if (typeof marker !== "string") continue;
|
|
263845
|
+
if (!fileContains(target, marker)) {
|
|
263846
|
+
missing.push(`${pkg}/${rel}: ${marker}`);
|
|
263847
|
+
}
|
|
263848
|
+
}
|
|
263849
|
+
}
|
|
263850
|
+
}
|
|
263851
|
+
return missing;
|
|
263852
|
+
}
|
|
263853
|
+
__name(findUnappliedClosurePatches, "findUnappliedClosurePatches");
|
|
263388
263854
|
function rmrf(target) {
|
|
263389
263855
|
try {
|
|
263390
263856
|
fs3.rmSync(target, {
|
|
@@ -264321,6 +264787,10 @@ var require_server_root = __commonJS({
|
|
|
264321
264787
|
if (missingNatives.length > 0) {
|
|
264322
264788
|
throw new Error(`staged closure missing native prebuilds: ${missingNatives.join(", ")} \u2014 refusing to arm a swap that would break the forked runners`);
|
|
264323
264789
|
}
|
|
264790
|
+
const unpatched = findUnappliedClosurePatches(stagingDir);
|
|
264791
|
+
if (unpatched.length > 0) {
|
|
264792
|
+
throw new Error(`staged closure did not apply its shipped patches: ${unpatched.join(", ")} \u2014 refusing to arm a swap into an unpatched closure`);
|
|
264793
|
+
}
|
|
264324
264794
|
return stagingDir;
|
|
264325
264795
|
} catch (err) {
|
|
264326
264796
|
await fs6.promises.rm(stagingDir, {
|