camstack 1.2.129 → 1.2.131

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.
@@ -28362,6 +28362,12 @@ var occupancyRecheckFramesField = {
28362
28362
  default: 4,
28363
28363
  step: 1
28364
28364
  };
28365
+ var preRollInferenceFramesField = {
28366
+ min: 0,
28367
+ max: 30,
28368
+ default: 12,
28369
+ step: 1
28370
+ };
28365
28371
  var MotionSourceEnum = external_exports.enum([
28366
28372
  "onboard",
28367
28373
  "analyzer",
@@ -28523,6 +28529,31 @@ var RunnerCameraConfigSchema = external_exports.object({
28523
28529
  * to every occupancy rule until something moved in front of it. The churn is
28524
28530
  * now paid on the interval instead — see `occupancyRecheckSecField`.
28525
28531
  */
28532
+ /**
28533
+ * Infer the session's PRE-ROLL — the retained history the restreamer replays
28534
+ * at session open — instead of decoding it and throwing it away.
28535
+ *
28536
+ * DEFAULT `true`, and the default is the argument. This is not a new
28537
+ * capability being offered cautiously: the pre-roll is ALREADY requested,
28538
+ * already served, already decoded and already paid for on every on-motion
28539
+ * detection session that asks for history. What shipped was a last-moment
28540
+ * discard — `FrameSlot`'s throttle compares wall clocks, and ~4 s of media
28541
+ * arriving inside a few hundred ms of wall clock looks to it like one frame's
28542
+ * worth. Device 617, 2026-09-08: a re-run of the SAME model over the stored
28543
+ * recording scored the subject `vehicle 0.5669` — above the 0.50 floor —
28544
+ * 1.68 s BEFORE the live track was born, on a frame that was in the pre-roll,
28545
+ * was decoded, and was freed.
28546
+ *
28547
+ * Shipping that as opt-in would ship the bug: an operator cannot discover a
28548
+ * setting whose absence looks exactly like a camera that noticed the cyclist
28549
+ * late. What makes ON safe is not a switch but the BOUND —
28550
+ * `preRollInferenceFrames`, a wall-clock ceiling, and a lane that never takes
28551
+ * the last inference permit — so the switch exists for the camera where the
28552
+ * history is worthless (a doorbell whose subject is always already at the
28553
+ * door), not as a hedge against the feature.
28554
+ */
28555
+ preRollInferenceEnabled: external_exports.boolean().default(true),
28556
+ preRollInferenceFrames: external_exports.number().min(preRollInferenceFramesField.min).max(preRollInferenceFramesField.max).default(preRollInferenceFramesField.default),
28526
28557
  occupancyRecheckEnabled: external_exports.boolean().default(true),
28527
28558
  occupancyRecheckSec: external_exports.number().min(occupancyRecheckSecField.min).max(occupancyRecheckSecField.max).default(occupancyRecheckSecField.default),
28528
28559
  occupancyRecheckFrames: external_exports.number().min(occupancyRecheckFramesField.min).max(occupancyRecheckFramesField.max).default(occupancyRecheckFramesField.default),
@@ -28662,6 +28693,29 @@ var RunnerCameraDeviceUIFields = [
28662
28693
  includes: "onboard"
28663
28694
  }
28664
28695
  },
28696
+ {
28697
+ key: "preRollInferenceEnabled",
28698
+ type: "boolean",
28699
+ style: "checkbox",
28700
+ label: "Detect in the pre-roll",
28701
+ description: "Run detection over the few seconds of footage the camera had already buffered when motion fired, so a subject that was in view before the trigger is found at the moment it appeared rather than seconds later. The burst is bounded and never delays live detection.",
28702
+ default: true
28703
+ },
28704
+ {
28705
+ key: "preRollInferenceFrames",
28706
+ type: "slider",
28707
+ label: "Pre-roll frames",
28708
+ description: "How many frames of buffered history may be detected on, per session. Higher samples the history more densely; 0 disables the pass.",
28709
+ min: preRollInferenceFramesField.min,
28710
+ max: preRollInferenceFramesField.max,
28711
+ step: preRollInferenceFramesField.step,
28712
+ default: preRollInferenceFramesField.default,
28713
+ showValue: true,
28714
+ showWhen: {
28715
+ field: "preRollInferenceEnabled",
28716
+ equals: true
28717
+ }
28718
+ },
28665
28719
  {
28666
28720
  key: "occupancyRecheckEnabled",
28667
28721
  type: "boolean",
package/dist/cli.js CHANGED
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
3
  runDiscover
4
- } from "./chunk-WZY4EJWR.js";
4
+ } from "./chunk-FK6R4ZJQ.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-JP2K4C4Y.js");
41
+ await import("./launcher-XH2NRTWF.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-JP2K4C4Y.js");
86
+ await import("./launcher-XH2NRTWF.js");
87
87
  }
88
88
 
89
89
  // src/commands/setup.ts
@@ -1130,7 +1130,7 @@ function isUnknown(_value) {
1130
1130
  return true;
1131
1131
  }
1132
1132
  async function resolveServerInteractive(presetNamespace) {
1133
- const { discoverNodes, resolveHubFromDiscovered, filterHubNodes, DEFAULT_HUB_HTTPS_PORT } = await import("./discover-VXR5SN5P.js");
1133
+ const { discoverNodes, resolveHubFromDiscovered, filterHubNodes, DEFAULT_HUB_HTTPS_PORT } = await import("./discover-Q75B3UUE.js");
1134
1134
  if (presetNamespace) {
1135
1135
  const spinner4 = clack.spinner();
1136
1136
  spinner4.start(`Discovering hub on LAN (namespace "${presetNamespace}")`);
@@ -5,7 +5,7 @@ import {
5
5
  filterHubNodes,
6
6
  resolveHubFromDiscovered,
7
7
  runDiscover
8
- } from "./chunk-WZY4EJWR.js";
8
+ } from "./chunk-FK6R4ZJQ.js";
9
9
  import "./chunk-LMMQX4CK.js";
10
10
  export {
11
11
  DEFAULT_HUB_HTTPS_PORT,
@@ -23633,9 +23633,9 @@ var require_zod = __commonJS({
23633
23633
  }
23634
23634
  });
23635
23635
 
23636
- // ../system/dist/dist-WLsoGpyn.js
23637
- var require_dist_WLsoGpyn = __commonJS({
23638
- "../system/dist/dist-WLsoGpyn.js"(exports) {
23636
+ // ../system/dist/dist-9GQQ9F3s.js
23637
+ var require_dist_9GQQ9F3s = __commonJS({
23638
+ "../system/dist/dist-9GQQ9F3s.js"(exports) {
23639
23639
  "use strict";
23640
23640
  var zod = require_zod();
23641
23641
  var EventCategory = /* @__PURE__ */ (function(EventCategory2) {
@@ -39131,6 +39131,12 @@ var require_dist_WLsoGpyn = __commonJS({
39131
39131
  default: 4,
39132
39132
  step: 1
39133
39133
  };
39134
+ var preRollInferenceFramesField = {
39135
+ min: 0,
39136
+ max: 30,
39137
+ default: 12,
39138
+ step: 1
39139
+ };
39134
39140
  var MotionSourceEnum = zod.z.enum([
39135
39141
  "onboard",
39136
39142
  "analyzer",
@@ -39292,6 +39298,31 @@ var require_dist_WLsoGpyn = __commonJS({
39292
39298
  * to every occupancy rule until something moved in front of it. The churn is
39293
39299
  * now paid on the interval instead — see `occupancyRecheckSecField`.
39294
39300
  */
39301
+ /**
39302
+ * Infer the session's PRE-ROLL — the retained history the restreamer replays
39303
+ * at session open — instead of decoding it and throwing it away.
39304
+ *
39305
+ * DEFAULT `true`, and the default is the argument. This is not a new
39306
+ * capability being offered cautiously: the pre-roll is ALREADY requested,
39307
+ * already served, already decoded and already paid for on every on-motion
39308
+ * detection session that asks for history. What shipped was a last-moment
39309
+ * discard — `FrameSlot`'s throttle compares wall clocks, and ~4 s of media
39310
+ * arriving inside a few hundred ms of wall clock looks to it like one frame's
39311
+ * worth. Device 617, 2026-09-08: a re-run of the SAME model over the stored
39312
+ * recording scored the subject `vehicle 0.5669` — above the 0.50 floor —
39313
+ * 1.68 s BEFORE the live track was born, on a frame that was in the pre-roll,
39314
+ * was decoded, and was freed.
39315
+ *
39316
+ * Shipping that as opt-in would ship the bug: an operator cannot discover a
39317
+ * setting whose absence looks exactly like a camera that noticed the cyclist
39318
+ * late. What makes ON safe is not a switch but the BOUND —
39319
+ * `preRollInferenceFrames`, a wall-clock ceiling, and a lane that never takes
39320
+ * the last inference permit — so the switch exists for the camera where the
39321
+ * history is worthless (a doorbell whose subject is always already at the
39322
+ * door), not as a hedge against the feature.
39323
+ */
39324
+ preRollInferenceEnabled: zod.z.boolean().default(true),
39325
+ preRollInferenceFrames: zod.z.number().min(preRollInferenceFramesField.min).max(preRollInferenceFramesField.max).default(preRollInferenceFramesField.default),
39295
39326
  occupancyRecheckEnabled: zod.z.boolean().default(true),
39296
39327
  occupancyRecheckSec: zod.z.number().min(occupancyRecheckSecField.min).max(occupancyRecheckSecField.max).default(occupancyRecheckSecField.default),
39297
39328
  occupancyRecheckFrames: zod.z.number().min(occupancyRecheckFramesField.min).max(occupancyRecheckFramesField.max).default(occupancyRecheckFramesField.default),
@@ -39320,7 +39351,7 @@ var require_dist_WLsoGpyn = __commonJS({
39320
39351
  */
39321
39352
  inferenceDevices: zod.z.array(RunnerInferenceDeviceSchema).readonly().optional()
39322
39353
  });
39323
- motionFpsField.min, motionFpsField.max, motionFpsField.step, motionFpsField.default, detectionFpsField.min, detectionFpsField.max, detectionFpsField.step, detectionFpsField.default, motionCooldownMsField.min, motionCooldownMsField.max, motionCooldownMsField.step, motionCooldownMsField.default, maxSessionHoldMsField.min, maxSessionHoldMsField.max, maxSessionHoldMsField.step, maxSessionHoldMsField.default, audioMotionWindowMsField.min, audioMotionWindowMsField.max, audioMotionWindowMsField.step, audioMotionWindowMsField.default, occupancyRecheckSecField.min, occupancyRecheckSecField.max, occupancyRecheckSecField.step, occupancyRecheckSecField.default, occupancyRecheckFramesField.min, occupancyRecheckFramesField.max, occupancyRecheckFramesField.step, occupancyRecheckFramesField.default;
39354
+ motionFpsField.min, motionFpsField.max, motionFpsField.step, motionFpsField.default, detectionFpsField.min, detectionFpsField.max, detectionFpsField.step, detectionFpsField.default, motionCooldownMsField.min, motionCooldownMsField.max, motionCooldownMsField.step, motionCooldownMsField.default, maxSessionHoldMsField.min, maxSessionHoldMsField.max, maxSessionHoldMsField.step, maxSessionHoldMsField.default, audioMotionWindowMsField.min, audioMotionWindowMsField.max, audioMotionWindowMsField.step, audioMotionWindowMsField.default, preRollInferenceFramesField.min, preRollInferenceFramesField.max, preRollInferenceFramesField.step, preRollInferenceFramesField.default, occupancyRecheckSecField.min, occupancyRecheckSecField.max, occupancyRecheckSecField.step, occupancyRecheckSecField.default, occupancyRecheckFramesField.min, occupancyRecheckFramesField.max, occupancyRecheckFramesField.step, occupancyRecheckFramesField.default;
39324
39355
  var RunnerLocalLoadSchema = zod.z.object({
39325
39356
  /** Moleculer node id of this runner instance. */
39326
39357
  nodeId: zod.z.string(),
@@ -61277,7 +61308,7 @@ var require_alerts_addon = __commonJS({
61277
61308
  [Symbol.toStringTag]: { value: "Module" }
61278
61309
  });
61279
61310
  require_chunk_Cek0wNdY();
61280
- var require_dist10 = require_dist_WLsoGpyn();
61311
+ var require_dist10 = require_dist_9GQQ9F3s();
61281
61312
  function selectExpired(alerts, cutoffMs) {
61282
61313
  return alerts.filter((a) => a.createdAt < cutoffMs).sort((a, b) => a.createdAt - b.createdAt).map((a) => a.id);
61283
61314
  }
@@ -62096,7 +62127,7 @@ var require_console_logging = __commonJS({
62096
62127
  [Symbol.toStringTag]: { value: "Module" }
62097
62128
  });
62098
62129
  require_chunk_Cek0wNdY();
62099
- var require_dist10 = require_dist_WLsoGpyn();
62130
+ var require_dist10 = require_dist_9GQQ9F3s();
62100
62131
  var require_formatter = require_formatter_DqAKDlvN();
62101
62132
  var LEVEL_RANK = {
62102
62133
  debug: 0,
@@ -62190,7 +62221,7 @@ var require_core_blocks_addon = __commonJS({
62190
62221
  "use strict";
62191
62222
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
62192
62223
  var require_chunk = require_chunk_Cek0wNdY();
62193
- var require_dist10 = require_dist_WLsoGpyn();
62224
+ var require_dist10 = require_dist_9GQQ9F3s();
62194
62225
  var node_crypto = __require("crypto");
62195
62226
  var node_fs_promises = __require("fs/promises");
62196
62227
  node_fs_promises = require_chunk.__toESM(node_fs_promises);
@@ -63087,11 +63118,11 @@ var require_core_blocks = __commonJS({
63087
63118
  }
63088
63119
  });
63089
63120
 
63090
- // ../system/dist/retired-settings-keys-WShMmPM4.js
63091
- var require_retired_settings_keys_WShMmPM4 = __commonJS({
63092
- "../system/dist/retired-settings-keys-WShMmPM4.js"(exports) {
63121
+ // ../system/dist/retired-settings-keys-DfdSH46H.js
63122
+ var require_retired_settings_keys_DfdSH46H = __commonJS({
63123
+ "../system/dist/retired-settings-keys-DfdSH46H.js"(exports) {
63093
63124
  "use strict";
63094
- var require_dist10 = require_dist_WLsoGpyn();
63125
+ var require_dist10 = require_dist_9GQQ9F3s();
63095
63126
  function settingsStoreIsAuthoritativeHere(env) {
63096
63127
  const raw = (env["CAMSTACK_ROLE"] ?? "").trim().toLowerCase();
63097
63128
  return raw === "" || raw === "hub";
@@ -65326,8 +65357,8 @@ var require_device_manager_addon = __commonJS({
65326
65357
  [Symbol.toStringTag]: { value: "Module" }
65327
65358
  });
65328
65359
  require_chunk_Cek0wNdY();
65329
- var require_dist10 = require_dist_WLsoGpyn();
65330
- var require_retired_settings_keys = require_retired_settings_keys_WShMmPM4();
65360
+ var require_dist10 = require_dist_9GQQ9F3s();
65361
+ var require_retired_settings_keys = require_retired_settings_keys_DfdSH46H();
65331
65362
  var node_crypto = __require("crypto");
65332
65363
  var _camstack_types_node = require_node();
65333
65364
  var JOB_HISTORY = 20;
@@ -70952,7 +70983,7 @@ var require_hub_forwarder = __commonJS({
70952
70983
  [Symbol.toStringTag]: { value: "Module" }
70953
70984
  });
70954
70985
  require_chunk_Cek0wNdY();
70955
- var require_dist10 = require_dist_WLsoGpyn();
70986
+ var require_dist10 = require_dist_9GQQ9F3s();
70956
70987
  var require_formatter = require_formatter_DqAKDlvN();
70957
70988
  var DEFAULT_OUTBOUND_BUFFER_SIZE = 500;
70958
70989
  var HubForwarderDestination = class {
@@ -71089,7 +71120,7 @@ var require_liveness_monitor_addon = __commonJS({
71089
71120
  "use strict";
71090
71121
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
71091
71122
  require_chunk_Cek0wNdY();
71092
- var require_dist10 = require_dist_WLsoGpyn();
71123
+ var require_dist10 = require_dist_9GQQ9F3s();
71093
71124
  var NO_DEVICES = "liveness:no-devices";
71094
71125
  var ALL_OFFLINE = "liveness:all-devices-offline";
71095
71126
  var NO_FOOTAGE_PREFIX = "liveness:no-footage:";
@@ -71285,7 +71316,7 @@ var require_local_auth_addon = __commonJS({
71285
71316
  [Symbol.toStringTag]: { value: "Module" }
71286
71317
  });
71287
71318
  var require_chunk = require_chunk_Cek0wNdY();
71288
- var require_dist10 = require_dist_WLsoGpyn();
71319
+ var require_dist10 = require_dist_9GQQ9F3s();
71289
71320
  var node_crypto = __require("crypto");
71290
71321
  node_crypto = require_chunk.__toESM(node_crypto);
71291
71322
  var crypto$1 = __require("crypto");
@@ -79098,7 +79129,7 @@ var require_loki_logging = __commonJS({
79098
79129
  [Symbol.toStringTag]: { value: "Module" }
79099
79130
  });
79100
79131
  require_chunk_Cek0wNdY();
79101
- var require_dist10 = require_dist_WLsoGpyn();
79132
+ var require_dist10 = require_dist_9GQQ9F3s();
79102
79133
  function sanitizeLabelName(raw) {
79103
79134
  const replaced = raw.replaceAll(/[^a-zA-Z0-9_]/g, "_");
79104
79135
  return /^[a-zA-Z_]/.test(replaced) ? replaced : `_${replaced}`;
@@ -79663,7 +79694,7 @@ var require_native_metrics_addon = __commonJS({
79663
79694
  [Symbol.toStringTag]: { value: "Module" }
79664
79695
  });
79665
79696
  var require_chunk = require_chunk_Cek0wNdY();
79666
- var require_dist10 = require_dist_WLsoGpyn();
79697
+ var require_dist10 = require_dist_9GQQ9F3s();
79667
79698
  var node_fs_promises = __require("fs/promises");
79668
79699
  var node_child_process = __require("child_process");
79669
79700
  var node_util = __require("util");
@@ -82247,7 +82278,7 @@ var require_filesystem_storage_addon = __commonJS({
82247
82278
  [Symbol.toStringTag]: { value: "Module" }
82248
82279
  });
82249
82280
  var require_chunk = require_chunk_Cek0wNdY();
82250
- var require_dist10 = require_dist_WLsoGpyn();
82281
+ var require_dist10 = require_dist_9GQQ9F3s();
82251
82282
  var node_crypto = __require("crypto");
82252
82283
  var node_fs_promises = __require("fs/promises");
82253
82284
  var node_path = __require("path");
@@ -83363,8 +83394,8 @@ var require_sqlite_settings_addon = __commonJS({
83363
83394
  [Symbol.toStringTag]: { value: "Module" }
83364
83395
  });
83365
83396
  var require_chunk = require_chunk_Cek0wNdY();
83366
- var require_dist10 = require_dist_WLsoGpyn();
83367
- var require_retired_settings_keys = require_retired_settings_keys_WShMmPM4();
83397
+ var require_dist10 = require_dist_9GQQ9F3s();
83398
+ var require_retired_settings_keys = require_retired_settings_keys_DfdSH46H();
83368
83399
  var node_crypto = __require("crypto");
83369
83400
  var node_fs = __require("fs");
83370
83401
  var node_module = __require("module");
@@ -85868,7 +85899,7 @@ var require_storage_orchestrator_addon = __commonJS({
85868
85899
  [Symbol.toStringTag]: { value: "Module" }
85869
85900
  });
85870
85901
  var require_chunk = require_chunk_Cek0wNdY();
85871
- var require_dist10 = require_dist_WLsoGpyn();
85902
+ var require_dist10 = require_dist_9GQQ9F3s();
85872
85903
  var require_hub_cap_forward = require_hub_cap_forward_DmHNjbB0();
85873
85904
  var zod = require_zod();
85874
85905
  var node_crypto = __require("crypto");
@@ -89518,7 +89549,7 @@ var require_system_config_addon = __commonJS({
89518
89549
  [Symbol.toStringTag]: { value: "Module" }
89519
89550
  });
89520
89551
  require_chunk_Cek0wNdY();
89521
- var require_dist10 = require_dist_WLsoGpyn();
89552
+ var require_dist10 = require_dist_9GQQ9F3s();
89522
89553
  var SECTION_TITLES = {
89523
89554
  server: "Server",
89524
89555
  auth: "Authentication"
@@ -107579,7 +107610,7 @@ var require_winston_logging = __commonJS({
107579
107610
  [Symbol.toStringTag]: { value: "Module" }
107580
107611
  });
107581
107612
  var require_chunk = require_chunk_Cek0wNdY();
107582
- var require_dist10 = require_dist_WLsoGpyn();
107613
+ var require_dist10 = require_dist_9GQQ9F3s();
107583
107614
  var require_formatter = require_formatter_DqAKDlvN();
107584
107615
  var node_path = __require("path");
107585
107616
  node_path = require_chunk.__toESM(node_path);
@@ -107716,9 +107747,9 @@ var require_winston_logging = __commonJS({
107716
107747
  }
107717
107748
  });
107718
107749
 
107719
- // ../system/dist/file-data-plane-DO8KbxCe.js
107720
- var require_file_data_plane_DO8KbxCe = __commonJS({
107721
- "../system/dist/file-data-plane-DO8KbxCe.js"(exports) {
107750
+ // ../system/dist/event-loop-stall-monitor-DM9OAzy8.js
107751
+ var require_event_loop_stall_monitor_DM9OAzy8 = __commonJS({
107752
+ "../system/dist/event-loop-stall-monitor-DM9OAzy8.js"(exports) {
107722
107753
  "use strict";
107723
107754
  var require_chunk = require_chunk_Cek0wNdY();
107724
107755
  var node_crypto = __require("crypto");
@@ -107729,6 +107760,7 @@ var require_file_data_plane_DO8KbxCe = __commonJS({
107729
107760
  node_fs = require_chunk.__toESM(node_fs);
107730
107761
  var node_http = __require("http");
107731
107762
  var node_zlib = __require("zlib");
107763
+ var node_perf_hooks = __require("perf_hooks");
107732
107764
  function isNonEmptyFile(filePath) {
107733
107765
  return node_fs.existsSync(filePath) && node_fs.statSync(filePath).size > 0;
107734
107766
  }
@@ -108516,12 +108548,98 @@ var require_file_data_plane_DO8KbxCe = __commonJS({
108516
108548
  (0, node_fs.createReadStream)(absPath).pipe(res);
108517
108549
  };
108518
108550
  }
108551
+ var STALL_TICK_MS = 1e3;
108552
+ var STALL_REPORT_MS = 2e3;
108553
+ function attributeStall(stallMs, gcMs, gcCount, longestGcMs) {
108554
+ const share = stallMs > 0 ? gcMs / stallMs : 0;
108555
+ return {
108556
+ stallMs,
108557
+ gcMs,
108558
+ gcCount,
108559
+ longestGcMs,
108560
+ cause: share >= 0.7 ? "gc" : share <= 0.2 ? "synchronous-block" : "mixed"
108561
+ };
108562
+ }
108563
+ function startEventLoopStallMonitor(logger, reportThresholdMs = STALL_REPORT_MS) {
108564
+ let gc = {
108565
+ totalMs: 0,
108566
+ count: 0,
108567
+ longestMs: 0
108568
+ };
108569
+ let observer = null;
108570
+ try {
108571
+ observer = new node_perf_hooks.PerformanceObserver((list) => {
108572
+ for (const entry of list.getEntries()) {
108573
+ gc.totalMs += entry.duration;
108574
+ gc.count += 1;
108575
+ if (entry.duration > gc.longestMs) gc.longestMs = entry.duration;
108576
+ }
108577
+ });
108578
+ observer.observe({ entryTypes: ["gc"] });
108579
+ } catch {
108580
+ observer = null;
108581
+ }
108582
+ let expected = Date.now() + STALL_TICK_MS;
108583
+ const timer = setInterval(() => {
108584
+ const now = Date.now();
108585
+ const lateBy = now - expected;
108586
+ const window2 = gc;
108587
+ gc = {
108588
+ totalMs: 0,
108589
+ count: 0,
108590
+ longestMs: 0
108591
+ };
108592
+ expected = now + STALL_TICK_MS;
108593
+ if (lateBy < reportThresholdMs) return;
108594
+ const verdict = attributeStall(lateBy, Math.round(window2.totalMs), window2.count, Math.round(window2.longestMs));
108595
+ const mem = process.memoryUsage();
108596
+ logger.warn("event loop stalled", { meta: {
108597
+ stallMs: verdict.stallMs,
108598
+ cause: verdict.cause,
108599
+ gcMs: verdict.gcMs,
108600
+ gcCount: verdict.gcCount,
108601
+ longestGcMs: verdict.longestGcMs,
108602
+ gcObserved: observer !== null,
108603
+ heapUsedMb: Math.round(mem.heapUsed / 1e6),
108604
+ heapTotalMb: Math.round(mem.heapTotal / 1e6),
108605
+ rssMb: Math.round(mem.rss / 1e6),
108606
+ externalMb: Math.round(mem.external / 1e6),
108607
+ arrayBuffersMb: Math.round(mem.arrayBuffers / 1e6)
108608
+ } });
108609
+ }, STALL_TICK_MS);
108610
+ timer.unref?.();
108611
+ let stopped = false;
108612
+ return () => {
108613
+ if (stopped) return;
108614
+ stopped = true;
108615
+ clearInterval(timer);
108616
+ observer?.disconnect();
108617
+ };
108618
+ }
108519
108619
  Object.defineProperty(exports, "ModelDownloadService", {
108520
108620
  enumerable: true,
108521
108621
  get: function() {
108522
108622
  return ModelDownloadService;
108523
108623
  }
108524
108624
  });
108625
+ Object.defineProperty(exports, "STALL_REPORT_MS", {
108626
+ enumerable: true,
108627
+ get: function() {
108628
+ return STALL_REPORT_MS;
108629
+ }
108630
+ });
108631
+ Object.defineProperty(exports, "STALL_TICK_MS", {
108632
+ enumerable: true,
108633
+ get: function() {
108634
+ return STALL_TICK_MS;
108635
+ }
108636
+ });
108637
+ Object.defineProperty(exports, "attributeStall", {
108638
+ enumerable: true,
108639
+ get: function() {
108640
+ return attributeStall;
108641
+ }
108642
+ });
108525
108643
  Object.defineProperty(exports, "collectModelFiles", {
108526
108644
  enumerable: true,
108527
108645
  get: function() {
@@ -108606,6 +108724,12 @@ var require_file_data_plane_DO8KbxCe = __commonJS({
108606
108724
  return resolveFilePath;
108607
108725
  }
108608
108726
  });
108727
+ Object.defineProperty(exports, "startEventLoopStallMonitor", {
108728
+ enumerable: true,
108729
+ get: function() {
108730
+ return startEventLoopStallMonitor;
108731
+ }
108732
+ });
108609
108733
  }
108610
108734
  });
108611
108735
 
@@ -113393,6 +113517,8 @@ var require_addon = __commonJS({
113393
113517
  "pipelineEnabled": true,
113394
113518
  "zones": [],
113395
113519
  "onboardMotionDrivesAnalyzer": true,
113520
+ "preRollInferenceEnabled": true,
113521
+ "preRollInferenceFrames": 12,
113396
113522
  "occupancyRecheckEnabled": true,
113397
113523
  "occupancyRecheckSec": 300,
113398
113524
  "occupancyRecheckFrames": 4,
@@ -132191,7 +132317,7 @@ var require_dist3 = __commonJS({
132191
132317
  "use strict";
132192
132318
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
132193
132319
  var require_chunk = require_chunk_Cek0wNdY();
132194
- var require_dist10 = require_dist_WLsoGpyn();
132320
+ var require_dist10 = require_dist_9GQQ9F3s();
132195
132321
  var require_builtins_alerts_alerts_addon = require_alerts_addon();
132196
132322
  require_alerts();
132197
132323
  var require_formatter = require_formatter_DqAKDlvN();
@@ -132216,7 +132342,7 @@ var require_dist3 = __commonJS({
132216
132342
  var require_builtins_system_config_system_config_addon = require_system_config_addon();
132217
132343
  require_system_config();
132218
132344
  var require_builtins_winston_logging_index = require_winston_logging();
132219
- var require_file_data_plane = require_file_data_plane_DO8KbxCe();
132345
+ var require_event_loop_stall_monitor = require_event_loop_stall_monitor_DM9OAzy8();
132220
132346
  var require_tls$1 = require_tls_BxQlomxd();
132221
132347
  var require_manifest_system_deps = require_manifest_system_deps_DvY1bY_n();
132222
132348
  var require_resource_monitor = require_resource_monitor_CdnzxBLP();
@@ -212986,7 +213112,7 @@ globstar while`, t, d, e, f, m), this.matchOne(t.slice(d), e.slice(f), s)) retur
212986
213112
  exports.LokiLoggingAddon = require_builtins_loki_logging_index.LokiLoggingAddon$1;
212987
213113
  exports.MAX_LEAF_VALIDITY_DAYS = require_tls$1.MAX_LEAF_VALIDITY_DAYS;
212988
213114
  exports.METHOD_ACCESS_MAP = require_dist10.METHOD_ACCESS_MAP;
212989
- exports.ModelDownloadService = require_file_data_plane.ModelDownloadService;
213115
+ exports.ModelDownloadService = require_event_loop_stall_monitor.ModelDownloadService;
212990
213116
  exports.NATIVE_PROVIDER_SERVICE_INFIX = require_manifest_system_deps.NATIVE_PROVIDER_SERVICE_INFIX;
212991
213117
  exports.NATIVE_SCAN_DEPTH = NATIVE_SCAN_DEPTH;
212992
213118
  exports.NativeMetricsAddon = require_builtins_native_metrics_native_metrics_addon.default;
@@ -213016,6 +213142,8 @@ globstar while`, t, d, e, f, m), this.matchOne(t.slice(d), e.slice(f), s)) retur
213016
213142
  exports.RingBuffer = RingBuffer;
213017
213143
  exports.SERVER_AUTH_OID = require_tls$1.SERVER_AUTH_OID;
213018
213144
  exports.SOCKET_PLANE_TOP_N = require_manifest_system_deps.SOCKET_PLANE_TOP_N;
213145
+ exports.STALL_REPORT_MS = require_event_loop_stall_monitor.STALL_REPORT_MS;
213146
+ exports.STALL_TICK_MS = require_event_loop_stall_monitor.STALL_TICK_MS;
213019
213147
  exports.ScopedLogger = ScopedLogger;
213020
213148
  exports.ScopedTokenManager = require_builtins_local_auth_local_auth_addon.ScopedTokenManager;
213021
213149
  exports.SocketChannel = require_manifest_system_deps.SocketChannel;
@@ -213043,6 +213171,7 @@ globstar while`, t, d, e, f, m), this.matchOne(t.slice(d), e.slice(f), s)) retur
213043
213171
  exports.addonSettingsCapability = require_dist10.addonSettingsCapability;
213044
213172
  exports.allFamiliesListenHost = require_tls$1.allFamiliesListenHost;
213045
213173
  exports.applyLanHttp = require_tls$1.applyLanHttp;
213174
+ exports.attributeStall = require_event_loop_stall_monitor.attributeStall;
213046
213175
  exports.bindPendingLanHttp = require_tls$1.bindPendingLanHttp;
213047
213176
  exports.bootstrapSchema = bootstrapSchema;
213048
213177
  exports.brokerCallForCap = require_manifest_system_deps.brokerCallForCap;
@@ -213075,14 +213204,14 @@ globstar while`, t, d, e, f, m), this.matchOne(t.slice(d), e.slice(f), s)) retur
213075
213204
  exports.clusterEventTopic = require_manifest_system_deps.clusterEventTopic;
213076
213205
  exports.clusterSecretMatches = clusterSecretMatches;
213077
213206
  exports.collectCertIdentity = require_tls$1.collectCertIdentity;
213078
- exports.collectModelFiles = require_file_data_plane.collectModelFiles;
213079
- exports.contentTypeFor = require_file_data_plane.contentTypeFor;
213207
+ exports.collectModelFiles = require_event_loop_stall_monitor.collectModelFiles;
213208
+ exports.contentTypeFor = require_event_loop_stall_monitor.contentTypeFor;
213080
213209
  exports.copyDirRecursive = copyDirRecursive;
213081
213210
  exports.copyExtraFileDirs = copyExtraFileDirs;
213082
213211
  exports.createAddonContext = require_manifest_system_deps.createAddonContext;
213083
213212
  exports.createAddonDataPlaneFacility = require_manifest_system_deps.createAddonDataPlaneFacility;
213084
213213
  exports.createAddonService = require_manifest_system_deps.createAddonService;
213085
- exports.createAuthenticatedFileServer = require_file_data_plane.createAuthenticatedFileServer;
213214
+ exports.createAuthenticatedFileServer = require_event_loop_stall_monitor.createAuthenticatedFileServer;
213086
213215
  exports.createBroker = createBroker2;
213087
213216
  exports.createBrokerDeviceManagerApi = require_manifest_system_deps.createBrokerDeviceManagerApi;
213088
213217
  exports.createCoreCapService = createCoreCapService;
@@ -213090,7 +213219,7 @@ globstar while`, t, d, e, f, m), this.matchOne(t.slice(d), e.slice(f), s)) retur
213090
213219
  exports.createDoorSettingsView = createDoorSettingsView;
213091
213220
  exports.createEventPlaneMeter = require_manifest_system_deps.createEventPlaneMeter;
213092
213221
  exports.createEventPlaneReader = require_manifest_system_deps.createEventPlaneReader;
213093
- exports.createFileDataPlaneHandler = require_file_data_plane.createFileDataPlaneHandler;
213222
+ exports.createFileDataPlaneHandler = require_event_loop_stall_monitor.createFileDataPlaneHandler;
213094
213223
  exports.createHubCapForwardService = require_hub_cap_forward.createHubCapForwardService;
213095
213224
  exports.createHubService = createHubService;
213096
213225
  exports.createKernelHwAccel = require_manifest_system_deps.createKernelHwAccel;
@@ -213111,7 +213240,7 @@ globstar while`, t, d, e, f, m), this.matchOne(t.slice(d), e.slice(f), s)) retur
213111
213240
  exports.createUdsLogger = require_manifest_system_deps.createUdsLogger;
213112
213241
  exports.createUdsLoggerWithControl = require_manifest_system_deps.createUdsLoggerWithControl;
213113
213242
  exports.createV8Reclaimer = require_manifest_system_deps.createV8Reclaimer;
213114
- exports.deleteModelFromDisk = require_file_data_plane.deleteModelFromDisk;
213243
+ exports.deleteModelFromDisk = require_event_loop_stall_monitor.deleteModelFromDisk;
213115
213244
  exports.deriveAgentListenPort = deriveAgentListenPort;
213116
213245
  exports.describeProviderKindDrift = describeProviderKindDrift;
213117
213246
  exports.describeRss = require_manifest_system_deps.describeRss;
@@ -213124,8 +213253,8 @@ globstar while`, t, d, e, f, m), this.matchOne(t.slice(d), e.slice(f), s)) retur
213124
213253
  return _camstack_types_node.downloadBinary;
213125
213254
  }
213126
213255
  });
213127
- exports.downloadFile = require_file_data_plane.downloadFile;
213128
- exports.downloadModel = require_file_data_plane.downloadModel;
213256
+ exports.downloadFile = require_event_loop_stall_monitor.downloadFile;
213257
+ exports.downloadModel = require_event_loop_stall_monitor.downloadModel;
213129
213258
  exports.emitDownForOwnedCaps = require_dist10.emitDownForOwnedCaps;
213130
213259
  exports.emitHeapDiagnosticReport = require_manifest_system_deps.emitHeapDiagnosticReport;
213131
213260
  exports.encodeFrame = require_manifest_system_deps.encodeFrame;
@@ -213144,7 +213273,7 @@ globstar while`, t, d, e, f, m), this.matchOne(t.slice(d), e.slice(f), s)) retur
213144
213273
  }
213145
213274
  });
213146
213275
  exports.ensureLibraryBuilt = ensureLibraryBuilt;
213147
- exports.ensureModel = require_file_data_plane.ensureModel;
213276
+ exports.ensureModel = require_event_loop_stall_monitor.ensureModel;
213148
213277
  exports.ensureNativePrebuilds = ensureNativePrebuilds;
213149
213278
  Object.defineProperty(exports, "ensurePython", {
213150
213279
  enumerable: true,
@@ -213155,7 +213284,7 @@ globstar while`, t, d, e, f, m), this.matchOne(t.slice(d), e.slice(f), s)) retur
213155
213284
  exports.ensureTlsCert = require_tls$1.ensureTlsCert;
213156
213285
  exports.evaluateExistingCert = require_tls$1.evaluateExistingCert;
213157
213286
  exports.expandCapMethods = require_dist10.expandCapMethods;
213158
- exports.fetchJson = require_file_data_plane.fetchJson;
213287
+ exports.fetchJson = require_event_loop_stall_monitor.fetchJson;
213159
213288
  Object.defineProperty(exports, "findInPath", {
213160
213289
  enumerable: true,
213161
213290
  get: function() {
@@ -213175,7 +213304,7 @@ globstar while`, t, d, e, f, m), this.matchOne(t.slice(d), e.slice(f), s)) retur
213175
213304
  }
213176
213305
  });
213177
213306
  exports.getLoggingGate = getLoggingGate;
213178
- exports.getModelFilePath = require_file_data_plane.getModelFilePath;
213307
+ exports.getModelFilePath = require_event_loop_stall_monitor.getModelFilePath;
213179
213308
  exports.getMoleculerEventStats = require_manifest_system_deps.getMoleculerEventStats;
213180
213309
  exports.getOrInitReadinessRegistry = require_manifest_system_deps.getOrInitReadinessRegistry;
213181
213310
  exports.getOrInitReadinessRegistryForClient = require_manifest_system_deps.getOrInitReadinessRegistryForClient;
@@ -213221,7 +213350,7 @@ globstar while`, t, d, e, f, m), this.matchOne(t.slice(d), e.slice(f), s)) retur
213221
213350
  exports.isClusterSecretMismatchError = isClusterSecretMismatchError;
213222
213351
  exports.isCollectionArrayMethod = require_dist10.isCollectionArrayMethod;
213223
213352
  exports.isInfraCapability = isInfraCapability;
213224
- exports.isModelDownloaded = require_file_data_plane.isModelDownloaded;
213353
+ exports.isModelDownloaded = require_event_loop_stall_monitor.isModelDownloaded;
213225
213354
  exports.isSourceNewer = isSourceNewer;
213226
213355
  exports.isolatedBuiltinPhase = isolatedBuiltinPhase;
213227
213356
  exports.loadTlsCert = require_tls$1.loadTlsCert;
@@ -213230,9 +213359,9 @@ globstar while`, t, d, e, f, m), this.matchOne(t.slice(d), e.slice(f), s)) retur
213230
213359
  exports.mountNativeCapService = require_manifest_system_deps.mountNativeCapService;
213231
213360
  exports.nextRssBudgetState = require_manifest_system_deps.nextRssBudgetState;
213232
213361
  exports.parseCapAction = require_manifest_system_deps.parseCapAction;
213233
- exports.parseRangeHeader = require_file_data_plane.parseRangeHeader;
213362
+ exports.parseRangeHeader = require_event_loop_stall_monitor.parseRangeHeader;
213234
213363
  exports.parseRssBudgetMb = require_manifest_system_deps.parseRssBudgetMb;
213235
- exports.parseTokenizedUrl = require_file_data_plane.parseTokenizedUrl;
213364
+ exports.parseTokenizedUrl = require_event_loop_stall_monitor.parseTokenizedUrl;
213236
213365
  exports.partitionIsolatedBuiltinIds = partitionIsolatedBuiltinIds;
213237
213366
  exports.proxyToUpstream = proxyToUpstream;
213238
213367
  exports.quarantineAddonResidue = quarantineAddonResidue;
@@ -213249,7 +213378,7 @@ globstar while`, t, d, e, f, m), this.matchOne(t.slice(d), e.slice(f), s)) retur
213249
213378
  exports.registerEventBusService = require_manifest_system_deps.registerEventBusService;
213250
213379
  exports.registerLanHttpHandler = require_tls$1.registerLanHttpHandler;
213251
213380
  exports.reissueTlsLeaf = require_tls$1.reissueTlsLeaf;
213252
- exports.resolveFilePath = require_file_data_plane.resolveFilePath;
213381
+ exports.resolveFilePath = require_event_loop_stall_monitor.resolveFilePath;
213253
213382
  exports.resolveHwAccel = require_manifest_system_deps.resolveHwAccel;
213254
213383
  exports.resolveNpmInvocation = require_manifest_system_deps.resolveNpmInvocation;
213255
213384
  exports.runHubAddonBoot = runHubAddonBoot;
@@ -213267,6 +213396,7 @@ globstar while`, t, d, e, f, m), this.matchOne(t.slice(d), e.slice(f), s)) retur
213267
213396
  exports.shouldReclaim = require_manifest_system_deps.shouldReclaim;
213268
213397
  exports.socketDirectionBytes = require_manifest_system_deps.socketDirectionBytes;
213269
213398
  exports.socketDirectionMessages = require_manifest_system_deps.socketDirectionMessages;
213399
+ exports.startEventLoopStallMonitor = require_event_loop_stall_monitor.startEventLoopStallMonitor;
213270
213400
  exports.startHeapWatch = require_manifest_system_deps.startHeapWatch;
213271
213401
  exports.startRunnerHeapWatch = require_manifest_system_deps.startRunnerHeapWatch;
213272
213402
  exports.strandedMb = require_manifest_system_deps.strandedMb;
@@ -229552,6 +229682,12 @@ ${recipe.triggers.map((t, i) => emitTrigger(t, i)).join("\n\n")}
229552
229682
  default: 4,
229553
229683
  step: 1
229554
229684
  };
229685
+ var preRollInferenceFramesField = {
229686
+ min: 0,
229687
+ max: 30,
229688
+ default: 12,
229689
+ step: 1
229690
+ };
229555
229691
  var MotionSourceEnum = zod.z.enum([
229556
229692
  "onboard",
229557
229693
  "analyzer",
@@ -229713,6 +229849,31 @@ ${recipe.triggers.map((t, i) => emitTrigger(t, i)).join("\n\n")}
229713
229849
  * to every occupancy rule until something moved in front of it. The churn is
229714
229850
  * now paid on the interval instead — see `occupancyRecheckSecField`.
229715
229851
  */
229852
+ /**
229853
+ * Infer the session's PRE-ROLL — the retained history the restreamer replays
229854
+ * at session open — instead of decoding it and throwing it away.
229855
+ *
229856
+ * DEFAULT `true`, and the default is the argument. This is not a new
229857
+ * capability being offered cautiously: the pre-roll is ALREADY requested,
229858
+ * already served, already decoded and already paid for on every on-motion
229859
+ * detection session that asks for history. What shipped was a last-moment
229860
+ * discard — `FrameSlot`'s throttle compares wall clocks, and ~4 s of media
229861
+ * arriving inside a few hundred ms of wall clock looks to it like one frame's
229862
+ * worth. Device 617, 2026-09-08: a re-run of the SAME model over the stored
229863
+ * recording scored the subject `vehicle 0.5669` — above the 0.50 floor —
229864
+ * 1.68 s BEFORE the live track was born, on a frame that was in the pre-roll,
229865
+ * was decoded, and was freed.
229866
+ *
229867
+ * Shipping that as opt-in would ship the bug: an operator cannot discover a
229868
+ * setting whose absence looks exactly like a camera that noticed the cyclist
229869
+ * late. What makes ON safe is not a switch but the BOUND —
229870
+ * `preRollInferenceFrames`, a wall-clock ceiling, and a lane that never takes
229871
+ * the last inference permit — so the switch exists for the camera where the
229872
+ * history is worthless (a doorbell whose subject is always already at the
229873
+ * door), not as a hedge against the feature.
229874
+ */
229875
+ preRollInferenceEnabled: zod.z.boolean().default(true),
229876
+ preRollInferenceFrames: zod.z.number().min(preRollInferenceFramesField.min).max(preRollInferenceFramesField.max).default(preRollInferenceFramesField.default),
229716
229877
  occupancyRecheckEnabled: zod.z.boolean().default(true),
229717
229878
  occupancyRecheckSec: zod.z.number().min(occupancyRecheckSecField.min).max(occupancyRecheckSecField.max).default(occupancyRecheckSecField.default),
229718
229879
  occupancyRecheckFrames: zod.z.number().min(occupancyRecheckFramesField.min).max(occupancyRecheckFramesField.max).default(occupancyRecheckFramesField.default),
@@ -229852,6 +230013,29 @@ ${recipe.triggers.map((t, i) => emitTrigger(t, i)).join("\n\n")}
229852
230013
  includes: "onboard"
229853
230014
  }
229854
230015
  },
230016
+ {
230017
+ key: "preRollInferenceEnabled",
230018
+ type: "boolean",
230019
+ style: "checkbox",
230020
+ label: "Detect in the pre-roll",
230021
+ description: "Run detection over the few seconds of footage the camera had already buffered when motion fired, so a subject that was in view before the trigger is found at the moment it appeared rather than seconds later. The burst is bounded and never delays live detection.",
230022
+ default: true
230023
+ },
230024
+ {
230025
+ key: "preRollInferenceFrames",
230026
+ type: "slider",
230027
+ label: "Pre-roll frames",
230028
+ description: "How many frames of buffered history may be detected on, per session. Higher samples the history more densely; 0 disables the pass.",
230029
+ min: preRollInferenceFramesField.min,
230030
+ max: preRollInferenceFramesField.max,
230031
+ step: preRollInferenceFramesField.step,
230032
+ default: preRollInferenceFramesField.default,
230033
+ showValue: true,
230034
+ showWhen: {
230035
+ field: "preRollInferenceEnabled",
230036
+ equals: true
230037
+ }
230038
+ },
229855
230039
  {
229856
230040
  key: "occupancyRecheckEnabled",
229857
230041
  type: "boolean",
@@ -432047,6 +432231,8 @@ var require_main4 = __commonJS({
432047
432231
  heapWatchLogger.warn(line);
432048
432232
  }
432049
432233
  });
432234
+ const stallLogger = loggingService.createLogger("event-loop");
432235
+ (0, system_1.startEventLoopStallMonitor)(stallLogger);
432050
432236
  const addonRouteRegistry = new system_1.AddonRouteRegistry();
432051
432237
  const dataPlaneRegistry = new system_1.DataPlaneRegistry();
432052
432238
  const { NotificationServiceWrapper } = await Promise.resolve().then(() => __importStar(require_notification_wrapper_service()));
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "camstack",
3
- "version": "1.2.129",
3
+ "version": "1.2.131",
4
4
  "description": "CLI tool for managing and running CamStack server",
5
5
  "keywords": [
6
6
  "camstack",