@camstack/system 1.2.101 → 1.2.103

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.
Files changed (58) hide show
  1. package/dist/builtins/addon-pages-aggregator/addon-pages-aggregator.addon.js +1 -1
  2. package/dist/builtins/addon-pages-aggregator/addon-pages-aggregator.addon.mjs +1 -1
  3. package/dist/builtins/addon-widgets-aggregator/addon-widgets-aggregator.addon.js +1 -1
  4. package/dist/builtins/addon-widgets-aggregator/addon-widgets-aggregator.addon.mjs +1 -1
  5. package/dist/builtins/alerts/alerts.addon.js +1 -1
  6. package/dist/builtins/alerts/alerts.addon.mjs +1 -1
  7. package/dist/builtins/backup-orchestrator/backup-orchestrator.addon.js +1 -1
  8. package/dist/builtins/backup-orchestrator/backup-orchestrator.addon.mjs +1 -1
  9. package/dist/builtins/console-logging/index.js +1 -1
  10. package/dist/builtins/console-logging/index.mjs +1 -1
  11. package/dist/builtins/core-blocks/core-blocks.addon.js +1 -1
  12. package/dist/builtins/core-blocks/core-blocks.addon.mjs +1 -1
  13. package/dist/builtins/device-manager/device-manager.addon.js +1 -1
  14. package/dist/builtins/device-manager/device-manager.addon.mjs +1 -1
  15. package/dist/builtins/doorbell/virtual-doorbell.addon.js +1 -1
  16. package/dist/builtins/doorbell/virtual-doorbell.addon.mjs +1 -1
  17. package/dist/builtins/hub-forwarder/index.js +1 -1
  18. package/dist/builtins/hub-forwarder/index.mjs +1 -1
  19. package/dist/builtins/liveness-monitor/liveness-monitor.addon.js +1 -1
  20. package/dist/builtins/liveness-monitor/liveness-monitor.addon.mjs +1 -1
  21. package/dist/builtins/local-auth/local-auth.addon.js +1 -1
  22. package/dist/builtins/local-auth/local-auth.addon.mjs +1 -1
  23. package/dist/builtins/local-network/local-network.addon.js +1 -1
  24. package/dist/builtins/local-network/local-network.addon.mjs +1 -1
  25. package/dist/builtins/loki-logging/index.js +1 -1
  26. package/dist/builtins/loki-logging/index.mjs +1 -1
  27. package/dist/builtins/native-metrics/native-metrics.addon.js +1 -1
  28. package/dist/builtins/native-metrics/native-metrics.addon.mjs +1 -1
  29. package/dist/builtins/platform-probe/index.js +1 -1
  30. package/dist/builtins/platform-probe/index.mjs +1 -1
  31. package/dist/builtins/remote-access-orchestrator/remote-access-orchestrator.addon.js +1 -1
  32. package/dist/builtins/remote-access-orchestrator/remote-access-orchestrator.addon.mjs +1 -1
  33. package/dist/builtins/snapshot/index.js +182 -25
  34. package/dist/builtins/snapshot/index.mjs +182 -25
  35. package/dist/builtins/snapshot/snapshot-cache.d.ts +63 -0
  36. package/dist/builtins/snapshot/snapshot-grab-pick.d.ts +20 -0
  37. package/dist/builtins/snapshot/snapshot-resize.d.ts +33 -1
  38. package/dist/builtins/snapshot/snapshot.addon.d.ts +6 -0
  39. package/dist/builtins/sqlite-storage/filesystem-storage.addon.js +1 -1
  40. package/dist/builtins/sqlite-storage/filesystem-storage.addon.mjs +1 -1
  41. package/dist/builtins/sqlite-storage/sqlite-settings.addon.js +1 -1
  42. package/dist/builtins/sqlite-storage/sqlite-settings.addon.mjs +1 -1
  43. package/dist/builtins/storage-orchestrator/storage-orchestrator.addon.js +1 -1
  44. package/dist/builtins/storage-orchestrator/storage-orchestrator.addon.mjs +1 -1
  45. package/dist/builtins/system-config/system-config.addon.js +1 -1
  46. package/dist/builtins/system-config/system-config.addon.mjs +1 -1
  47. package/dist/builtins/winston-logging/index.js +1 -1
  48. package/dist/builtins/winston-logging/index.mjs +1 -1
  49. package/dist/{dist-RbFV8cX7.mjs → dist-DHKXob1m.mjs} +179 -29
  50. package/dist/{dist-tMrPAfpF.js → dist-qnwy_iWM.js} +179 -29
  51. package/dist/index.js +264 -62
  52. package/dist/index.mjs +264 -62
  53. package/dist/kernel/config-schema.d.ts +14 -10
  54. package/dist/kernel/heap-watch.d.ts +39 -7
  55. package/dist/kernel/moleculer/process-service.d.ts +34 -0
  56. package/dist/logging/log-manager.d.ts +7 -5
  57. package/dist/logging/partitioned-log-buffer.d.ts +95 -16
  58. package/package.json +1 -1
@@ -3,7 +3,7 @@ Object.defineProperties(exports, {
3
3
  [Symbol.toStringTag]: { value: "Module" }
4
4
  });
5
5
  const require_chunk = require("../../chunk-Cek0wNdY.js");
6
- const require_dist = require("../../dist-tMrPAfpF.js");
6
+ const require_dist = require("../../dist-qnwy_iWM.js");
7
7
  const require_settle_sources = require("../../settle-sources-Bhsy57y-.js");
8
8
  let node_crypto = require("node:crypto");
9
9
  let node_path = require("node:path");
@@ -1,4 +1,4 @@
1
- import { Gt as EventCategory, v as addonPagesCapability, vt as errMsg, yt as BaseAddon } from "../../dist-RbFV8cX7.mjs";
1
+ import { Gt as EventCategory, v as addonPagesCapability, vt as errMsg, yt as BaseAddon } from "../../dist-DHKXob1m.mjs";
2
2
  import { t as settleSourcesWithTimeout } from "../../settle-sources-CDtNC8ub.mjs";
3
3
  import { createHash, randomUUID } from "node:crypto";
4
4
  import * as path$1 from "node:path";
@@ -3,7 +3,7 @@ Object.defineProperties(exports, {
3
3
  [Symbol.toStringTag]: { value: "Module" }
4
4
  });
5
5
  const require_chunk = require("../../chunk-Cek0wNdY.js");
6
- const require_dist = require("../../dist-tMrPAfpF.js");
6
+ const require_dist = require("../../dist-qnwy_iWM.js");
7
7
  const require_settle_sources = require("../../settle-sources-Bhsy57y-.js");
8
8
  let node_crypto = require("node:crypto");
9
9
  let node_path = require("node:path");
@@ -1,4 +1,4 @@
1
- import { Gt as EventCategory, b as addonWidgetsCapability, vt as errMsg, yt as BaseAddon } from "../../dist-RbFV8cX7.mjs";
1
+ import { Gt as EventCategory, b as addonWidgetsCapability, vt as errMsg, yt as BaseAddon } from "../../dist-DHKXob1m.mjs";
2
2
  import { t as settleSourcesWithTimeout } from "../../settle-sources-CDtNC8ub.mjs";
3
3
  import { createHash, randomUUID } from "node:crypto";
4
4
  import * as path$1 from "node:path";
@@ -3,7 +3,7 @@ Object.defineProperties(exports, {
3
3
  [Symbol.toStringTag]: { value: "Module" }
4
4
  });
5
5
  require("../../chunk-Cek0wNdY.js");
6
- const require_dist = require("../../dist-tMrPAfpF.js");
6
+ const require_dist = require("../../dist-qnwy_iWM.js");
7
7
  //#region src/builtins/alerts/prune-policy.ts
8
8
  /**
9
9
  * Ids older than `cutoffMs`, oldest first.
@@ -1,4 +1,4 @@
1
- import { Gt as EventCategory, Mt as createEvent, n as AlertSchema, vt as errMsg, x as alertsCapability, yt as BaseAddon } from "../../dist-RbFV8cX7.mjs";
1
+ import { Gt as EventCategory, Mt as createEvent, n as AlertSchema, vt as errMsg, x as alertsCapability, yt as BaseAddon } from "../../dist-DHKXob1m.mjs";
2
2
  //#region src/builtins/alerts/prune-policy.ts
3
3
  /**
4
4
  * Ids older than `cutoffMs`, oldest first.
@@ -3,7 +3,7 @@ Object.defineProperties(exports, {
3
3
  [Symbol.toStringTag]: { value: "Module" }
4
4
  });
5
5
  const require_chunk = require("../../chunk-Cek0wNdY.js");
6
- const require_dist = require("../../dist-tMrPAfpF.js");
6
+ const require_dist = require("../../dist-qnwy_iWM.js");
7
7
  let node_crypto = require("node:crypto");
8
8
  let buffer = require("buffer");
9
9
  let node_fs_promises = require("node:fs/promises");
@@ -1,4 +1,4 @@
1
- import { C as backupCapability, Gt as EventCategory, yt as BaseAddon } from "../../dist-RbFV8cX7.mjs";
1
+ import { C as backupCapability, Gt as EventCategory, yt as BaseAddon } from "../../dist-DHKXob1m.mjs";
2
2
  import { randomBytes, randomUUID } from "node:crypto";
3
3
  import { Buffer as Buffer$1 } from "buffer";
4
4
  import * as fsp from "node:fs/promises";
@@ -3,7 +3,7 @@ Object.defineProperties(exports, {
3
3
  [Symbol.toStringTag]: { value: "Module" }
4
4
  });
5
5
  require("../../chunk-Cek0wNdY.js");
6
- const require_dist = require("../../dist-tMrPAfpF.js");
6
+ const require_dist = require("../../dist-qnwy_iWM.js");
7
7
  const require_formatter = require("../../formatter-DqAKDlvN.js");
8
8
  //#region src/builtins/console-logging/console-destination.ts
9
9
  var LEVEL_RANK = {
@@ -1,4 +1,4 @@
1
- import { X as logDestinationCapability, yt as BaseAddon } from "../../dist-RbFV8cX7.mjs";
1
+ import { X as logDestinationCapability, yt as BaseAddon } from "../../dist-DHKXob1m.mjs";
2
2
  import { t as formatLogLine } from "../../formatter-B7qW8bPJ.mjs";
3
3
  //#region src/builtins/console-logging/console-destination.ts
4
4
  var LEVEL_RANK = {
@@ -1,6 +1,6 @@
1
1
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
2
  const require_chunk = require("../../chunk-Cek0wNdY.js");
3
- const require_dist = require("../../dist-tMrPAfpF.js");
3
+ const require_dist = require("../../dist-qnwy_iWM.js");
4
4
  let node_crypto = require("node:crypto");
5
5
  let node_fs_promises = require("node:fs/promises");
6
6
  node_fs_promises = require_chunk.__toESM(node_fs_promises);
@@ -1,4 +1,4 @@
1
- import { D as coreBlockAddonId, O as coreBlockIdFromAddonId, c as CoreBlockSchema, k as coreBlocksCapability, l as DeclaredDevices, o as CORE_BLOCKS_ADDON_ID, s as CORE_BLOCK_ADDON_PREFIX, vt as errMsg, yt as BaseAddon } from "../../dist-RbFV8cX7.mjs";
1
+ import { D as coreBlockAddonId, O as coreBlockIdFromAddonId, c as CoreBlockSchema, k as coreBlocksCapability, l as DeclaredDevices, o as CORE_BLOCKS_ADDON_ID, s as CORE_BLOCK_ADDON_PREFIX, vt as errMsg, yt as BaseAddon } from "../../dist-DHKXob1m.mjs";
2
2
  import { randomUUID } from "node:crypto";
3
3
  import * as fs from "node:fs/promises";
4
4
  import * as path$1 from "node:path";
@@ -3,7 +3,7 @@ Object.defineProperties(exports, {
3
3
  [Symbol.toStringTag]: { value: "Module" }
4
4
  });
5
5
  require("../../chunk-Cek0wNdY.js");
6
- const require_dist = require("../../dist-tMrPAfpF.js");
6
+ const require_dist = require("../../dist-qnwy_iWM.js");
7
7
  let node_crypto = require("node:crypto");
8
8
  let _camstack_types_node = require("@camstack/types/node");
9
9
  //#region src/builtins/device-manager/adoption-job-engine.ts
@@ -1,4 +1,4 @@
1
- import { Ct as DeviceFeature, E as buildStreamParamsConfigSchema, F as deviceStatusCapability, Gt as EventCategory, Lt as isDeviceConfigCap, N as deviceManagerCapability, Ot as WELL_KNOWN_TAB_MAP, P as deviceStateCapability, R as enumerateItemArrayFields, Tt as DeviceType, Wt as sleep, a as CAP_NAMES_WITH_STATUS, at as runtimeStatePolicyFor, et as normalizeUnit, nt as parseStreamParamsFormPatch, p as STREAM_PROFILE_META, t as ALL_CAPABILITY_DEFINITIONS, u as DeviceStatusSchema, vt as errMsg, wt as DeviceRole, yt as BaseAddon, z as enumerateSchemaFields } from "../../dist-RbFV8cX7.mjs";
1
+ import { Ct as DeviceFeature, E as buildStreamParamsConfigSchema, F as deviceStatusCapability, Gt as EventCategory, Lt as isDeviceConfigCap, N as deviceManagerCapability, Ot as WELL_KNOWN_TAB_MAP, P as deviceStateCapability, R as enumerateItemArrayFields, Tt as DeviceType, Wt as sleep, a as CAP_NAMES_WITH_STATUS, at as runtimeStatePolicyFor, et as normalizeUnit, nt as parseStreamParamsFormPatch, p as STREAM_PROFILE_META, t as ALL_CAPABILITY_DEFINITIONS, u as DeviceStatusSchema, vt as errMsg, wt as DeviceRole, yt as BaseAddon, z as enumerateSchemaFields } from "../../dist-DHKXob1m.mjs";
2
2
  import { randomUUID } from "node:crypto";
3
3
  import { canonicalDeviceFingerprint } from "@camstack/types/node";
4
4
  //#region src/builtins/device-manager/adoption-job-engine.ts
@@ -3,7 +3,7 @@ Object.defineProperties(exports, {
3
3
  [Symbol.toStringTag]: { value: "Module" }
4
4
  });
5
5
  require("../../chunk-Cek0wNdY.js");
6
- const require_dist = require("../../dist-tMrPAfpF.js");
6
+ const require_dist = require("../../dist-qnwy_iWM.js");
7
7
  //#region src/builtins/doorbell/trigger-engine.ts
8
8
  /**
9
9
  * Pure trigger logic for the virtual-doorbell builtin — edge detection over
@@ -1,4 +1,4 @@
1
- import { G as isSameAddonId, Gt as EventCategory, I as doorbellCapability, Mt as createEvent, Tt as DeviceType, vt as errMsg, w as bareAddonId, yt as BaseAddon } from "../../dist-RbFV8cX7.mjs";
1
+ import { G as isSameAddonId, Gt as EventCategory, I as doorbellCapability, Mt as createEvent, Tt as DeviceType, vt as errMsg, w as bareAddonId, yt as BaseAddon } from "../../dist-DHKXob1m.mjs";
2
2
  //#region src/builtins/doorbell/trigger-engine.ts
3
3
  /**
4
4
  * Pure trigger logic for the virtual-doorbell builtin — edge detection over
@@ -3,7 +3,7 @@ Object.defineProperties(exports, {
3
3
  [Symbol.toStringTag]: { value: "Module" }
4
4
  });
5
5
  require("../../chunk-Cek0wNdY.js");
6
- const require_dist = require("../../dist-tMrPAfpF.js");
6
+ const require_dist = require("../../dist-qnwy_iWM.js");
7
7
  const require_formatter = require("../../formatter-DqAKDlvN.js");
8
8
  //#region src/builtins/hub-forwarder/hub-forwarder-destination.ts
9
9
  var DEFAULT_OUTBOUND_BUFFER_SIZE = 500;
@@ -1,4 +1,4 @@
1
- import { X as logDestinationCapability, yt as BaseAddon } from "../../dist-RbFV8cX7.mjs";
1
+ import { X as logDestinationCapability, yt as BaseAddon } from "../../dist-DHKXob1m.mjs";
2
2
  import { t as formatLogLine } from "../../formatter-B7qW8bPJ.mjs";
3
3
  //#region src/builtins/hub-forwarder/hub-forwarder-destination.ts
4
4
  var DEFAULT_OUTBOUND_BUFFER_SIZE = 500;
@@ -1,6 +1,6 @@
1
1
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
2
  require("../../chunk-Cek0wNdY.js");
3
- const require_dist = require("../../dist-tMrPAfpF.js");
3
+ const require_dist = require("../../dist-qnwy_iWM.js");
4
4
  //#region src/builtins/liveness-monitor/liveness-checks.ts
5
5
  var NO_DEVICES = "liveness:no-devices";
6
6
  var ALL_OFFLINE = "liveness:all-devices-offline";
@@ -1,4 +1,4 @@
1
- import { Gt as EventCategory, Mt as createEvent, vt as errMsg, yt as BaseAddon } from "../../dist-RbFV8cX7.mjs";
1
+ import { Gt as EventCategory, Mt as createEvent, vt as errMsg, yt as BaseAddon } from "../../dist-DHKXob1m.mjs";
2
2
  //#region src/builtins/liveness-monitor/liveness-checks.ts
3
3
  var NO_DEVICES = "liveness:no-devices";
4
4
  var ALL_OFFLINE = "liveness:all-devices-offline";
@@ -3,7 +3,7 @@ Object.defineProperties(exports, {
3
3
  [Symbol.toStringTag]: { value: "Module" }
4
4
  });
5
5
  const require_chunk = require("../../chunk-Cek0wNdY.js");
6
- const require_dist = require("../../dist-tMrPAfpF.js");
6
+ const require_dist = require("../../dist-qnwy_iWM.js");
7
7
  let node_crypto = require("node:crypto");
8
8
  node_crypto = require_chunk.__toESM(node_crypto);
9
9
  let crypto$1 = require("crypto");
@@ -1,5 +1,5 @@
1
1
  import { i as __require, o as __toESM, t as __commonJSMin } from "../../chunk-CNf5ZN-e.mjs";
2
- import { S as authProviderCapability, _ as UserRecordSchema, ht as userManagementCapability, m as ScopedTokenSchema, r as ApiKeyRecordSchema, yt as BaseAddon } from "../../dist-RbFV8cX7.mjs";
2
+ import { S as authProviderCapability, _ as UserRecordSchema, ht as userManagementCapability, m as ScopedTokenSchema, r as ApiKeyRecordSchema, yt as BaseAddon } from "../../dist-DHKXob1m.mjs";
3
3
  import * as crypto$2 from "node:crypto";
4
4
  import { createHash, randomUUID, timingSafeEqual } from "node:crypto";
5
5
  import nodeCrypto from "crypto";
@@ -1,6 +1,6 @@
1
1
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
2
  const require_chunk = require("../../chunk-Cek0wNdY.js");
3
- const require_dist = require("../../dist-tMrPAfpF.js");
3
+ const require_dist = require("../../dist-qnwy_iWM.js");
4
4
  let node_os = require("node:os");
5
5
  node_os = require_chunk.__toESM(node_os);
6
6
  //#region src/builtins/local-network/local-network.addon.ts
@@ -1,4 +1,4 @@
1
- import { Gt as EventCategory, Y as localNetworkCapability, yt as BaseAddon } from "../../dist-RbFV8cX7.mjs";
1
+ import { Gt as EventCategory, Y as localNetworkCapability, yt as BaseAddon } from "../../dist-DHKXob1m.mjs";
2
2
  import * as os from "node:os";
3
3
  //#region src/builtins/local-network/local-network.addon.ts
4
4
  /**
@@ -3,7 +3,7 @@ Object.defineProperties(exports, {
3
3
  [Symbol.toStringTag]: { value: "Module" }
4
4
  });
5
5
  require("../../chunk-Cek0wNdY.js");
6
- const require_dist = require("../../dist-tMrPAfpF.js");
6
+ const require_dist = require("../../dist-qnwy_iWM.js");
7
7
  //#region src/builtins/loki-logging/loki-payload.ts
8
8
  /**
9
9
  * Loki rejects a label name that is not a valid Prometheus label
@@ -1,4 +1,4 @@
1
- import { X as logDestinationCapability, yt as BaseAddon } from "../../dist-RbFV8cX7.mjs";
1
+ import { X as logDestinationCapability, yt as BaseAddon } from "../../dist-DHKXob1m.mjs";
2
2
  //#region src/builtins/loki-logging/loki-payload.ts
3
3
  /**
4
4
  * Loki rejects a label name that is not a valid Prometheus label
@@ -3,7 +3,7 @@ Object.defineProperties(exports, {
3
3
  [Symbol.toStringTag]: { value: "Module" }
4
4
  });
5
5
  const require_chunk = require("../../chunk-Cek0wNdY.js");
6
- const require_dist = require("../../dist-tMrPAfpF.js");
6
+ const require_dist = require("../../dist-qnwy_iWM.js");
7
7
  let node_child_process = require("node:child_process");
8
8
  let node_util = require("node:util");
9
9
  let node_os = require("node:os");
@@ -1,4 +1,4 @@
1
- import { $ as metricsProviderCapability, Gt as EventCategory, Mt as createEvent, yt as BaseAddon } from "../../dist-RbFV8cX7.mjs";
1
+ import { $ as metricsProviderCapability, Gt as EventCategory, Mt as createEvent, yt as BaseAddon } from "../../dist-DHKXob1m.mjs";
2
2
  import { execFile, execFileSync } from "node:child_process";
3
3
  import { promisify } from "node:util";
4
4
  import * as os from "node:os";
@@ -3,7 +3,7 @@ Object.defineProperties(exports, {
3
3
  [Symbol.toStringTag]: { value: "Module" }
4
4
  });
5
5
  const require_chunk = require("../../chunk-Cek0wNdY.js");
6
- const require_dist = require("../../dist-tMrPAfpF.js");
6
+ const require_dist = require("../../dist-qnwy_iWM.js");
7
7
  let node_child_process = require("node:child_process");
8
8
  let node_util = require("node:util");
9
9
  let node_os = require("node:os");
@@ -1,5 +1,5 @@
1
1
  import { o as __toESM } from "../../chunk-CNf5ZN-e.mjs";
2
- import { Gt as EventCategory, L as enumerateInferenceDevices, Pt as emitReadiness, ct as scoreRuntimes, rt as platformProbeCapability, vt as errMsg, yt as BaseAddon } from "../../dist-RbFV8cX7.mjs";
2
+ import { Gt as EventCategory, L as enumerateInferenceDevices, Pt as emitReadiness, ct as scoreRuntimes, rt as platformProbeCapability, vt as errMsg, yt as BaseAddon } from "../../dist-DHKXob1m.mjs";
3
3
  import { execFile } from "node:child_process";
4
4
  import { promisify } from "node:util";
5
5
  import * as os from "node:os";
@@ -3,7 +3,7 @@ Object.defineProperties(exports, {
3
3
  [Symbol.toStringTag]: { value: "Module" }
4
4
  });
5
5
  require("../../chunk-Cek0wNdY.js");
6
- const require_dist = require("../../dist-tMrPAfpF.js");
6
+ const require_dist = require("../../dist-qnwy_iWM.js");
7
7
  //#region src/builtins/remote-access-orchestrator/enabled-providers-reconcile.ts
8
8
  /**
9
9
  * Reconcile the durable `enabledProviders` set against authoritative
@@ -1,4 +1,4 @@
1
- import { Gt as EventCategory, yt as BaseAddon } from "../../dist-RbFV8cX7.mjs";
1
+ import { Gt as EventCategory, yt as BaseAddon } from "../../dist-DHKXob1m.mjs";
2
2
  //#region src/builtins/remote-access-orchestrator/enabled-providers-reconcile.ts
3
3
  /**
4
4
  * Reconcile the durable `enabledProviders` set against authoritative
@@ -3,7 +3,7 @@ Object.defineProperties(exports, {
3
3
  [Symbol.toStringTag]: { value: "Module" }
4
4
  });
5
5
  const require_chunk = require("../../chunk-Cek0wNdY.js");
6
- const require_dist = require("../../dist-tMrPAfpF.js");
6
+ const require_dist = require("../../dist-qnwy_iWM.js");
7
7
  let zod = require("zod");
8
8
  let node_crypto = require("node:crypto");
9
9
  let _camstack_types_node = require("@camstack/types/node");
@@ -22,25 +22,94 @@ var SnapshotCache = class {
22
22
  byKey = /* @__PURE__ */ new Map();
23
23
  /** deviceId → its live keys, so invalidation is O(streams) not O(cache). */
24
24
  keysByDevice = /* @__PURE__ */ new Map();
25
+ maxBytes;
26
+ idleTtlMs;
27
+ now;
28
+ onEvict;
29
+ totalBytes = 0;
30
+ constructor(options = {}) {
31
+ this.maxBytes = options.maxBytes ?? 67108864;
32
+ this.idleTtlMs = options.idleTtlMs ?? 36e5;
33
+ this.now = options.now ?? (() => Date.now());
34
+ this.onEvict = options.onEvict;
35
+ }
25
36
  get(deviceId, streamId) {
26
- return this.byKey.get(keyOf(deviceId, streamId));
37
+ return this.read(keyOf(deviceId, streamId));
27
38
  }
28
39
  set(deviceId, streamId, entry) {
29
40
  const key = keyOf(deviceId, streamId);
30
- this.byKey.set(key, entry);
41
+ this.forget(key);
42
+ this.byKey.set(key, {
43
+ entry,
44
+ deviceId,
45
+ bytes: entry.data.base64.length,
46
+ lastAccessAt: this.now()
47
+ });
48
+ this.totalBytes += entry.data.base64.length;
31
49
  const keys = this.keysByDevice.get(deviceId) ?? /* @__PURE__ */ new Set();
32
50
  keys.add(key);
33
51
  this.keysByDevice.set(deviceId, keys);
52
+ this.enforceBudget(key);
34
53
  }
35
54
  /** The newest entry for a device, whichever stream produced it. */
36
55
  latest(deviceId) {
37
56
  let newest;
38
- for (const key of this.keysByDevice.get(deviceId) ?? []) {
39
- const entry = this.byKey.get(key);
57
+ for (const key of [...this.keysByDevice.get(deviceId) ?? []]) {
58
+ const entry = this.read(key);
40
59
  if (entry !== void 0 && (newest === void 0 || entry.ts > newest.ts)) newest = entry;
41
60
  }
42
61
  return newest;
43
62
  }
63
+ /** Base64 bytes currently retained. The number the budget is enforced on. */
64
+ sizeBytes() {
65
+ return this.totalBytes;
66
+ }
67
+ /** Entries currently retained. */
68
+ entryCount() {
69
+ return this.byKey.size;
70
+ }
71
+ /** Read through the idle timeout: an entry nobody has touched inside
72
+ * `idleTtlMs` is dropped here rather than on a sweep, so the cost is paid by
73
+ * the caller that proves it was not wanted. */
74
+ read(key) {
75
+ const slot = this.byKey.get(key);
76
+ if (slot === void 0) return void 0;
77
+ const at = this.now();
78
+ if (at - slot.lastAccessAt > this.idleTtlMs) {
79
+ this.evict(key, "idle");
80
+ return;
81
+ }
82
+ slot.lastAccessAt = at;
83
+ return slot.entry;
84
+ }
85
+ /** Evict least-recently-ACCESSED first until the budget holds. `protectedKey`
86
+ * is the entry just written — evicting it would make `set` a no-op. */
87
+ enforceBudget(protectedKey) {
88
+ if (this.totalBytes <= this.maxBytes) return;
89
+ const coldestFirst = [...this.byKey.entries()].filter(([key]) => key !== protectedKey).toSorted((a, b) => a[1].lastAccessAt - b[1].lastAccessAt);
90
+ for (const [key] of coldestFirst) {
91
+ if (this.totalBytes <= this.maxBytes) return;
92
+ this.evict(key, "budget");
93
+ }
94
+ }
95
+ evict(key, reason) {
96
+ const slot = this.byKey.get(key);
97
+ if (slot === void 0) return;
98
+ this.forget(key);
99
+ this.onEvict?.(slot.deviceId, slot.entry.streamId, reason);
100
+ }
101
+ /** Remove a key and everything that indexes or accounts for it. */
102
+ forget(key) {
103
+ const slot = this.byKey.get(key);
104
+ if (slot === void 0) return;
105
+ this.totalBytes -= slot.bytes;
106
+ this.byKey.delete(key);
107
+ const keys = this.keysByDevice.get(slot.deviceId);
108
+ if (keys !== void 0) {
109
+ keys.delete(key);
110
+ if (keys.size === 0) this.keysByDevice.delete(slot.deviceId);
111
+ }
112
+ }
44
113
  /**
45
114
  * Drop every stream of one device.
46
115
  *
@@ -49,12 +118,13 @@ var SnapshotCache = class {
49
118
  * serving the pre-change frame from the other key.
50
119
  */
51
120
  deleteDevice(deviceId) {
52
- for (const key of this.keysByDevice.get(deviceId) ?? []) this.byKey.delete(key);
121
+ for (const key of [...this.keysByDevice.get(deviceId) ?? []]) this.forget(key);
53
122
  this.keysByDevice.delete(deviceId);
54
123
  }
55
124
  clear() {
56
125
  this.byKey.clear();
57
126
  this.keysByDevice.clear();
127
+ this.totalBytes = 0;
58
128
  }
59
129
  };
60
130
  //#endregion
@@ -759,48 +829,114 @@ function resizeJpeg(bytes, width, timeoutMs = RESIZE_TIMEOUT_MS) {
759
829
  if (timer !== void 0) clearTimeout(timer);
760
830
  });
761
831
  }
762
- /**
763
- * Resized frames, keyed by (device, stream, width, state treatment) AND
764
- * validated against the source frame's timestamp.
765
- *
766
- * The timestamp is the whole correctness argument: a variant outlives nothing.
767
- * When the underlying frame is recaptured its `capturedAt` moves, every variant
768
- * derived from the old one stops matching, and the next request re-derives.
769
- * Without that check a card would keep showing a thumbnail of a frame the
770
- * full-size view had already replaced.
771
- */
772
832
  var SnapshotVariantCache = class SnapshotVariantCache {
773
833
  byKey = /* @__PURE__ */ new Map();
774
834
  keysByDevice = /* @__PURE__ */ new Map();
835
+ maxBytes;
836
+ now;
837
+ totalBytes = 0;
838
+ constructor(options = {}) {
839
+ this.maxBytes = options.maxBytes ?? 16777216;
840
+ this.now = options.now ?? (() => Date.now());
841
+ }
775
842
  static key(deviceId, streamId, width, variantKey) {
776
843
  return `${deviceId}:${streamId ?? "auto"}:${width}:${variantKey ?? "raw"}`;
777
844
  }
778
845
  /** The variant for this exact frame, or undefined when it is missing or was
779
- * derived from an older capture. */
846
+ * derived from an older capture.
847
+ *
848
+ * A superseded variant is DELETED here, not merely reported missing. It used
849
+ * to be left in the map: unreachable by every future read (its `sourceTs` can
850
+ * never match again) and removed by nothing, so every recapture added a dead
851
+ * key. Returning `undefined` while retaining the bytes is the leak. */
780
852
  get(deviceId, streamId, width, sourceTs, variantKey) {
781
- const entry = this.byKey.get(SnapshotVariantCache.key(deviceId, streamId, width, variantKey));
782
- return entry !== void 0 && entry.sourceTs === sourceTs ? entry.bytes : void 0;
853
+ const key = SnapshotVariantCache.key(deviceId, streamId, width, variantKey);
854
+ const slot = this.byKey.get(key);
855
+ if (slot === void 0) return void 0;
856
+ if (slot.sourceTs !== sourceTs) {
857
+ this.forget(key);
858
+ return;
859
+ }
860
+ slot.lastAccessAt = this.now();
861
+ return slot.bytes;
783
862
  }
784
863
  set(deviceId, streamId, width, sourceTs, bytes, variantKey) {
785
864
  const key = SnapshotVariantCache.key(deviceId, streamId, width, variantKey);
865
+ this.forget(key);
786
866
  this.byKey.set(key, {
787
867
  bytes,
788
- sourceTs
868
+ sourceTs,
869
+ deviceId,
870
+ lastAccessAt: this.now()
789
871
  });
872
+ this.totalBytes += bytes.byteLength;
790
873
  const keys = this.keysByDevice.get(deviceId) ?? /* @__PURE__ */ new Set();
791
874
  keys.add(key);
792
875
  this.keysByDevice.set(deviceId, keys);
876
+ this.enforceBudget(key);
877
+ }
878
+ /** Variant bytes currently retained. */
879
+ sizeBytes() {
880
+ return this.totalBytes;
881
+ }
882
+ /** Variants currently retained — including any that are no longer readable.
883
+ * The number that used to only ever go up. */
884
+ entryCount() {
885
+ return this.byKey.size;
886
+ }
887
+ /** Evict least-recently-accessed first until the budget holds. */
888
+ enforceBudget(protectedKey) {
889
+ if (this.totalBytes <= this.maxBytes) return;
890
+ const coldestFirst = [...this.byKey.entries()].filter(([key]) => key !== protectedKey).toSorted((a, b) => a[1].lastAccessAt - b[1].lastAccessAt);
891
+ for (const [key] of coldestFirst) {
892
+ if (this.totalBytes <= this.maxBytes) return;
893
+ this.forget(key);
894
+ }
895
+ }
896
+ forget(key) {
897
+ const slot = this.byKey.get(key);
898
+ if (slot === void 0) return;
899
+ this.totalBytes -= slot.bytes.byteLength;
900
+ this.byKey.delete(key);
901
+ const keys = this.keysByDevice.get(slot.deviceId);
902
+ if (keys !== void 0) {
903
+ keys.delete(key);
904
+ if (keys.size === 0) this.keysByDevice.delete(slot.deviceId);
905
+ }
793
906
  }
794
907
  deleteDevice(deviceId) {
795
- for (const key of this.keysByDevice.get(deviceId) ?? []) this.byKey.delete(key);
908
+ for (const key of [...this.keysByDevice.get(deviceId) ?? []]) this.forget(key);
796
909
  this.keysByDevice.delete(deviceId);
797
910
  }
798
911
  clear() {
799
912
  this.byKey.clear();
800
913
  this.keysByDevice.clear();
914
+ this.totalBytes = 0;
801
915
  }
802
916
  };
803
917
  //#endregion
918
+ //#region src/builtins/snapshot/snapshot-grab-pick.ts
919
+ /**
920
+ * Which restream ffmpeg should grab a snapshot JPEG from.
921
+ *
922
+ * `status: 'streaming'` is not enough. A derived whose source profile is
923
+ * unassigned sits in that state with zero packets (618, 2026-08-16: `derived:Mid
924
+ * to low` had four subscribers and never a frame). Preferring it as "warm"
925
+ * parked every grab on a 15 s ffmpeg timeout, so the connecting poster never
926
+ * moved.
927
+ *
928
+ * Derived brokers are never the warm shortcut. A native that is actually
929
+ * streaming still wins; otherwise the caller walks the ranked list and will
930
+ * wake an idle source.
931
+ */
932
+ function isDerivedBrokerId(brokerId, devicePrefix) {
933
+ return (brokerId.startsWith(devicePrefix) ? brokerId.slice(devicePrefix.length) : brokerId).startsWith("derived:");
934
+ }
935
+ /** Highest-quality currently-streaming NON-derived broker, or undefined. */
936
+ function pickWarmSnapshotBroker(ranked, devicePrefix) {
937
+ return ranked.find((c) => c.status === "streaming" && !isDerivedBrokerId(c.brokerId, devicePrefix));
938
+ }
939
+ //#endregion
804
940
  //#region src/builtins/snapshot/snapshot.addon.ts
805
941
  /**
806
942
  * How long `getSnapshotLinks` waits for the capture it triggered before minting
@@ -886,7 +1022,21 @@ function effectiveMaxAgeS(prefs, isBattery) {
886
1022
  * publishes stream endpoints.
887
1023
  */
888
1024
  var SnapshotAddon = class SnapshotAddon extends require_dist.BaseAddon {
889
- cache = new SnapshotCache();
1025
+ /**
1026
+ * The frame cache. Bounded by a byte budget + an idle timeout — it used to be
1027
+ * unbounded in both. Every eviction is logged with the device tag: a frame
1028
+ * that silently left the cache is the reason a later capture had to happen,
1029
+ * and per-camera is the only way that question is ever asked.
1030
+ */
1031
+ cache = new SnapshotCache({ onEvict: (deviceId, streamId, reason) => {
1032
+ this.ctx.logger.debug("snapshot cache evicted", {
1033
+ tags: { deviceId },
1034
+ meta: {
1035
+ stream: streamId ?? "auto",
1036
+ reason
1037
+ }
1038
+ });
1039
+ } });
890
1040
  /** Card-sized derivatives of the frames above, keyed by width and validated
891
1041
  * against the source frame's timestamp. */
892
1042
  variants = new SnapshotVariantCache();
@@ -1799,12 +1949,19 @@ var SnapshotAddon = class SnapshotAddon extends require_dist.BaseAddon {
1799
1949
  entry: e,
1800
1950
  status: statusByBrokerId.get(e.brokerId) ?? "idle"
1801
1951
  }));
1802
- const warm = statuses.find((s) => s.status === "streaming");
1952
+ const warm = pickWarmSnapshotBroker(statuses.map((s) => ({
1953
+ brokerId: s.entry.brokerId,
1954
+ status: s.status
1955
+ })), prefix);
1803
1956
  if (warm) {
1804
- const grabbed = await this.runGrabWithResumeRetry(warm.entry.url, deviceId);
1805
- if (grabbed) return grabbed;
1957
+ const match = statuses.find((s) => s.entry.brokerId === warm.brokerId);
1958
+ if (match) {
1959
+ const grabbed = await this.runGrabWithResumeRetry(match.entry.url, deviceId);
1960
+ if (grabbed) return grabbed;
1961
+ }
1806
1962
  }
1807
1963
  for (const { entry } of statuses) {
1964
+ if (isDerivedBrokerId(entry.brokerId, prefix)) continue;
1808
1965
  const grabbed = await this.runGrabWithResumeRetry(entry.url, deviceId).catch(() => null);
1809
1966
  if (grabbed) return grabbed;
1810
1967
  }