@camstack/system 1.2.13 → 1.2.15

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/addon-runner.js +2 -2
  2. package/dist/addon-runner.mjs +2 -2
  3. package/dist/builtins/addon-pages-aggregator/addon-pages-aggregator.addon.js +1 -1
  4. package/dist/builtins/addon-pages-aggregator/addon-pages-aggregator.addon.mjs +1 -1
  5. package/dist/builtins/addon-widgets-aggregator/addon-widgets-aggregator.addon.js +1 -1
  6. package/dist/builtins/addon-widgets-aggregator/addon-widgets-aggregator.addon.mjs +1 -1
  7. package/dist/builtins/alerts/alerts.addon.js +1 -1
  8. package/dist/builtins/alerts/alerts.addon.mjs +1 -1
  9. package/dist/builtins/backup-orchestrator/backup-orchestrator.addon.js +1 -1
  10. package/dist/builtins/backup-orchestrator/backup-orchestrator.addon.mjs +1 -1
  11. package/dist/builtins/console-logging/index.js +1 -1
  12. package/dist/builtins/console-logging/index.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/local-auth/local-auth.addon.js +1 -1
  20. package/dist/builtins/local-auth/local-auth.addon.mjs +1 -1
  21. package/dist/builtins/local-network/local-network.addon.js +1 -1
  22. package/dist/builtins/local-network/local-network.addon.mjs +1 -1
  23. package/dist/builtins/loki-logging/index.d.ts +4 -0
  24. package/dist/builtins/loki-logging/index.js +445 -0
  25. package/dist/builtins/loki-logging/index.mjs +431 -0
  26. package/dist/builtins/loki-logging/loki-destination.d.ts +88 -0
  27. package/dist/builtins/loki-logging/loki-logging.addon.d.ts +36 -0
  28. package/dist/builtins/loki-logging/loki-payload.d.ts +46 -0
  29. package/dist/builtins/native-metrics/native-metrics.addon.js +1 -1
  30. package/dist/builtins/native-metrics/native-metrics.addon.mjs +1 -1
  31. package/dist/builtins/platform-probe/index.js +1 -1
  32. package/dist/builtins/platform-probe/index.mjs +1 -1
  33. package/dist/builtins/remote-access-orchestrator/remote-access-orchestrator.addon.js +1 -1
  34. package/dist/builtins/remote-access-orchestrator/remote-access-orchestrator.addon.mjs +1 -1
  35. package/dist/builtins/snapshot/index.js +1 -1
  36. package/dist/builtins/snapshot/index.mjs +1 -1
  37. package/dist/builtins/sqlite-storage/filesystem-storage.addon.js +1 -1
  38. package/dist/builtins/sqlite-storage/filesystem-storage.addon.mjs +1 -1
  39. package/dist/builtins/sqlite-storage/sqlite-settings.addon.js +1 -1
  40. package/dist/builtins/sqlite-storage/sqlite-settings.addon.mjs +1 -1
  41. package/dist/builtins/storage-orchestrator/storage-orchestrator.addon.js +1 -1
  42. package/dist/builtins/storage-orchestrator/storage-orchestrator.addon.mjs +1 -1
  43. package/dist/builtins/system-config/system-config.addon.js +1 -1
  44. package/dist/builtins/system-config/system-config.addon.mjs +1 -1
  45. package/dist/builtins/winston-logging/index.js +1 -1
  46. package/dist/builtins/winston-logging/index.mjs +1 -1
  47. package/dist/{dist-DpKeSZel.mjs → dist-eOaraBhT.mjs} +21 -1
  48. package/dist/{dist-BQOCTD5b.js → dist-yttC1aUI.js} +26 -0
  49. package/dist/index.d.ts +2 -0
  50. package/dist/index.js +128 -15
  51. package/dist/index.mjs +127 -16
  52. package/dist/kernel/config-schema.d.ts +38 -1
  53. package/dist/logging/log-manager.d.ts +14 -4
  54. package/dist/logging/log-ring-buffer.d.ts +15 -0
  55. package/dist/logging/partitioned-log-buffer.d.ts +49 -6
  56. package/dist/{manifest-python-deps-1I7WdPDD.js → manifest-python-deps-DSrmih6E.js} +1 -1
  57. package/dist/{manifest-python-deps-I2MGvDvo.mjs → manifest-python-deps-bn3qrsxR.mjs} +1 -1
  58. package/package.json +13 -1
@@ -1,4 +1,4 @@
1
- import { A as filesystemBrowseCapability, et as storageProviderCapability, ot as BaseAddon } from "../../dist-DpKeSZel.mjs";
1
+ import { A as filesystemBrowseCapability, st as BaseAddon, tt as storageProviderCapability } from "../../dist-eOaraBhT.mjs";
2
2
  import * as fs from "node:fs";
3
3
  import * as path$1 from "node:path";
4
4
  import { basename, dirname, join, resolve, sep } 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-BQOCTD5b.js");
6
+ const require_dist = require("../../dist-yttC1aUI.js");
7
7
  let node_crypto = require("node:crypto");
8
8
  let better_sqlite3 = require("better-sqlite3");
9
9
  better_sqlite3 = require_chunk.__toESM(better_sqlite3);
@@ -1,4 +1,4 @@
1
- import { Et as parseJsonUnknown, Z as settingsStoreCapability, at as errMsg, c as RUNTIME_DEFAULTS, gt as asJsonObject, ot as BaseAddon } from "../../dist-DpKeSZel.mjs";
1
+ import { Dt as parseJsonUnknown, Q as settingsStoreCapability, _t as asJsonObject, c as RUNTIME_DEFAULTS, ot as errMsg, st as BaseAddon } from "../../dist-eOaraBhT.mjs";
2
2
  import { randomUUID } from "node:crypto";
3
3
  import Database from "better-sqlite3";
4
4
  //#region src/builtins/sqlite-storage/sqlite-settings-backend.ts
@@ -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-BQOCTD5b.js");
6
+ const require_dist = require("../../dist-yttC1aUI.js");
7
7
  let node_path = require("node:path");
8
8
  node_path = require_chunk.__toESM(node_path);
9
9
  let node_fs_promises = require("node:fs/promises");
@@ -1,4 +1,4 @@
1
- import { $ as storageCapability, Tt as parseJsonObject, d as StorageLocationTypeSchema, ot as BaseAddon } from "../../dist-DpKeSZel.mjs";
1
+ import { Et as parseJsonObject, d as StorageLocationTypeSchema, et as storageCapability, st as BaseAddon } from "../../dist-eOaraBhT.mjs";
2
2
  import * as path$1 from "node:path";
3
3
  import * as fs from "node:fs/promises";
4
4
  import { buildStorageLocationRegistry } from "@camstack/system";
@@ -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-BQOCTD5b.js");
6
+ const require_dist = require("../../dist-yttC1aUI.js");
7
7
  //#region src/builtins/system-config/system-config.addon.ts
8
8
  /**
9
9
  * Built-in `system-config` addon — Phase 4 of the settings redesign.
@@ -1,4 +1,4 @@
1
- import { Ct as hydrateSchema, at as errMsg, ot as BaseAddon } from "../../dist-DpKeSZel.mjs";
1
+ import { ot as errMsg, st as BaseAddon, wt as hydrateSchema } from "../../dist-eOaraBhT.mjs";
2
2
  //#region src/builtins/system-config/system-config.addon.ts
3
3
  /**
4
4
  * Built-in `system-config` addon — Phase 4 of the settings redesign.
@@ -3,7 +3,7 @@ Object.defineProperties(exports, {
3
3
  [Symbol.toStringTag]: { value: "Module" }
4
4
  });
5
5
  const require_chunk = require("../../chunk-Cek0wNdY.js");
6
- const require_dist = require("../../dist-BQOCTD5b.js");
6
+ const require_dist = require("../../dist-yttC1aUI.js");
7
7
  const require_formatter = require("../../formatter-DqAKDlvN.js");
8
8
  let node_path = require("node:path");
9
9
  node_path = require_chunk.__toESM(node_path);
@@ -1,4 +1,4 @@
1
- import { ot as BaseAddon, z as logDestinationCapability } from "../../dist-DpKeSZel.mjs";
1
+ import { st as BaseAddon, z as logDestinationCapability } from "../../dist-eOaraBhT.mjs";
2
2
  import { t as formatLogLine } from "../../formatter-B7qW8bPJ.mjs";
3
3
  import * as path$1 from "node:path";
4
4
  import path from "node:path";
@@ -3407,6 +3407,26 @@ var OpsLogQueryInputSchema = z.object({
3407
3407
  limit: z.number().int().min(1).max(1e3).optional()
3408
3408
  });
3409
3409
  /**
3410
+ * Severity ordering. Declared once here because it had already been re-declared
3411
+ * three times independently (`kernel/transport/uds-logger.ts`,
3412
+ * `builtins/loki-logging/loki-destination.ts`, and the log buffer) — four copies
3413
+ * of the same four numbers is four chances for one of them to disagree.
3414
+ *
3415
+ * `uds-logger` keeps its own copy on purpose: it ranks a plain `string` coming off
3416
+ * the wire and needs a tolerant fallback for an unknown value, which this typed
3417
+ * map deliberately does not offer.
3418
+ */
3419
+ var LOG_LEVEL_RANK = {
3420
+ debug: 0,
3421
+ info: 1,
3422
+ warn: 2,
3423
+ error: 3
3424
+ };
3425
+ /** True when `level` is no more severe than `threshold` — i.e. prunable/filterable. */
3426
+ function logLevelAtMost(level, threshold) {
3427
+ return LOG_LEVEL_RANK[level] <= LOG_LEVEL_RANK[threshold];
3428
+ }
3429
+ /**
3410
3430
  * `StorageLocationType` — an addon-declared id that identifies the *kind* of
3411
3431
  * storage a location serves. Defined here (not in `capabilities/storage.cap.ts`)
3412
3432
  * so the persisted record schema and the consumer-facing cap can both consume it
@@ -28189,4 +28209,4 @@ function enumerateInferenceDevices(hw) {
28189
28209
  return out;
28190
28210
  }
28191
28211
  //#endregion
28192
- export { storageCapability as $, filesystemBrowseCapability as A, sleep as At, looseSchema as B, deviceStatusCapability as C, hydrateSchema as Ct, enumerateSchemaFields as D, readinessKey as Dt, enumerateItemArrayFields as E, parseJsonUnknown as Et, isVoidInput as F, parseStreamParamsFormPatch as G, nodePin as H, kebabToCamel as I, readNodePin as J, platformProbeCapability as K, lifecycleJobSchema as L, isArrayOutputSchema as M, isCollectionArrayMethod as N, evaluateLinkExpression as O, resolveCapMount as Ot, isObjectInput as P, snapshotCapability as Q, localNetworkCapability as R, deviceStateCapability as S, expandCapMethods as St, enumerateInferenceDevices as T, parseJsonObject as Tt, normalizeUnit as U, metricsProviderCapability as V, objectInputDeclaresAddonId as W, setByPath as X, scoreRuntimes as Y, settingsStoreCapability as Z, applyTransform as _, asNumber as _t, CAP_NAMES_WITH_STATUS as a, errMsg as at, buildStreamParamsConfigSchema as b, emitDownForOwnedCaps as bt, RUNTIME_DEFAULTS as c, DEVICE_SETTINGS_CONTRIBUTION_METHODS as ct, StorageLocationTypeSchema as d, DeviceRole as dt, storageProviderCapability as et, UserRecordSchema as f, DeviceType as ft, alertsCapability as g, asJsonObject as gt, addonWidgetsCapability as h, WELL_KNOWN_TAB_MAP as ht, BatteryStatusSchema as i, validateExpressionSource as it, getByPath as j, EventCategory as jt, extractNestedAddonId as k, scopeKey as kt, STREAM_PROFILE_META as l, DEVICE_STATUS_METHOD as lt, addonSettingsCapability as m, ReadinessTimeoutError as mt, AlertSchema as n, toExpressionValue as nt, DeviceStatusSchema as o, BaseAddon as ot, addonPagesCapability as p, ReadinessRegistry as pt, procedureAuthKey as q, ApiKeyRecordSchema as r, userManagementCapability as rt, METHOD_ACCESS_MAP as s, DATAPLANE_SECRET_HEADER as st, ALL_CAPABILITY_DEFINITIONS as t, streamQualityLabel as tt, ScopedTokenSchema as u, DeviceFeature as ut, authProviderCapability as v, asString as vt, doorbellCapability as w, isDeviceConfigCap as wt, deviceManagerCapability as x, emitReadiness as xt, backupCapability as y, createEvent as yt, logDestinationCapability as z };
28212
+ export { snapshotCapability as $, filesystemBrowseCapability as A, scopeKey as At, logLevelAtMost as B, deviceStatusCapability as C, expandCapMethods as Ct, enumerateSchemaFields as D, parseJsonUnknown as Dt, enumerateItemArrayFields as E, parseJsonObject as Et, isVoidInput as F, objectInputDeclaresAddonId as G, metricsProviderCapability as H, kebabToCamel as I, procedureAuthKey as J, parseStreamParamsFormPatch as K, lifecycleJobSchema as L, isArrayOutputSchema as M, EventCategory as Mt, isCollectionArrayMethod as N, evaluateLinkExpression as O, readinessKey as Ot, isObjectInput as P, settingsStoreCapability as Q, localNetworkCapability as R, deviceStateCapability as S, emitReadiness as St, enumerateInferenceDevices as T, isDeviceConfigCap as Tt, nodePin as U, looseSchema as V, normalizeUnit as W, scoreRuntimes as X, readNodePin as Y, setByPath as Z, applyTransform as _, asJsonObject as _t, CAP_NAMES_WITH_STATUS as a, validateExpressionSource as at, buildStreamParamsConfigSchema as b, createEvent as bt, RUNTIME_DEFAULTS as c, DATAPLANE_SECRET_HEADER as ct, StorageLocationTypeSchema as d, DeviceFeature as dt, storageCapability as et, UserRecordSchema as f, DeviceRole as ft, alertsCapability as g, WELL_KNOWN_TAB_MAP as gt, addonWidgetsCapability as h, ReadinessTimeoutError as ht, BatteryStatusSchema as i, userManagementCapability as it, getByPath as j, sleep as jt, extractNestedAddonId as k, resolveCapMount as kt, STREAM_PROFILE_META as l, DEVICE_SETTINGS_CONTRIBUTION_METHODS as lt, addonSettingsCapability as m, ReadinessRegistry as mt, AlertSchema as n, streamQualityLabel as nt, DeviceStatusSchema as o, errMsg as ot, addonPagesCapability as p, DeviceType as pt, platformProbeCapability as q, ApiKeyRecordSchema as r, toExpressionValue as rt, METHOD_ACCESS_MAP as s, BaseAddon as st, ALL_CAPABILITY_DEFINITIONS as t, storageProviderCapability as tt, ScopedTokenSchema as u, DEVICE_STATUS_METHOD as ut, authProviderCapability as v, asNumber as vt, doorbellCapability as w, hydrateSchema as wt, deviceManagerCapability as x, emitDownForOwnedCaps as xt, backupCapability as y, asString as yt, logDestinationCapability as z };
@@ -3407,6 +3407,26 @@ var OpsLogQueryInputSchema = zod.z.object({
3407
3407
  limit: zod.z.number().int().min(1).max(1e3).optional()
3408
3408
  });
3409
3409
  /**
3410
+ * Severity ordering. Declared once here because it had already been re-declared
3411
+ * three times independently (`kernel/transport/uds-logger.ts`,
3412
+ * `builtins/loki-logging/loki-destination.ts`, and the log buffer) — four copies
3413
+ * of the same four numbers is four chances for one of them to disagree.
3414
+ *
3415
+ * `uds-logger` keeps its own copy on purpose: it ranks a plain `string` coming off
3416
+ * the wire and needs a tolerant fallback for an unknown value, which this typed
3417
+ * map deliberately does not offer.
3418
+ */
3419
+ var LOG_LEVEL_RANK = {
3420
+ debug: 0,
3421
+ info: 1,
3422
+ warn: 2,
3423
+ error: 3
3424
+ };
3425
+ /** True when `level` is no more severe than `threshold` — i.e. prunable/filterable. */
3426
+ function logLevelAtMost(level, threshold) {
3427
+ return LOG_LEVEL_RANK[level] <= LOG_LEVEL_RANK[threshold];
3428
+ }
3429
+ /**
3410
3430
  * `StorageLocationType` — an addon-declared id that identifies the *kind* of
3411
3431
  * storage a location serves. Defined here (not in `capabilities/storage.cap.ts`)
3412
3432
  * so the persisted record schema and the consumer-facing cap can both consume it
@@ -28549,6 +28569,12 @@ Object.defineProperty(exports, "logDestinationCapability", {
28549
28569
  return logDestinationCapability;
28550
28570
  }
28551
28571
  });
28572
+ Object.defineProperty(exports, "logLevelAtMost", {
28573
+ enumerable: true,
28574
+ get: function() {
28575
+ return logLevelAtMost;
28576
+ }
28577
+ });
28552
28578
  Object.defineProperty(exports, "looseSchema", {
28553
28579
  enumerable: true,
28554
28580
  get: function() {
package/dist/index.d.ts CHANGED
@@ -37,6 +37,8 @@ export { WinstonLoggingAddon } from './builtins/winston-logging/index.js';
37
37
  export { WinstonDestination } from './builtins/winston-logging/index.js';
38
38
  export { ConsoleLoggingAddon } from './builtins/console-logging/index.js';
39
39
  export { ConsoleDestination } from './builtins/console-logging/index.js';
40
+ export { LokiLoggingAddon, LokiDestination } from './builtins/loki-logging/index.js';
41
+ export type { LokiConfig, LokiStatus } from './builtins/loki-logging/index.js';
40
42
  export { HubForwarderAddon } from './builtins/hub-forwarder/index.js';
41
43
  export { HubForwarderDestination } from './builtins/hub-forwarder/index.js';
42
44
  export { StorageOrchestratorAddon, StorageOrchestratorService, } from './builtins/storage-orchestrator/index.js';
package/dist/index.js CHANGED
@@ -1,8 +1,8 @@
1
1
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
2
  const require_chunk = require("./chunk-Cek0wNdY.js");
3
- const require_dist = require("./dist-BQOCTD5b.js");
3
+ const require_dist = require("./dist-yttC1aUI.js");
4
4
  const require_model_download_service = require("./model-download-service-hf0ookyy.js");
5
- const require_manifest_python_deps = require("./manifest-python-deps-1I7WdPDD.js");
5
+ const require_manifest_python_deps = require("./manifest-python-deps-DSrmih6E.js");
6
6
  const require_resource_monitor = require("./resource-monitor-DNNomR-i.js");
7
7
  const require_builtins_sqlite_storage_filesystem_storage_addon = require("./builtins/sqlite-storage/filesystem-storage.addon.js");
8
8
  const require_builtins_sqlite_storage_sqlite_settings_addon = require("./builtins/sqlite-storage/sqlite-settings.addon.js");
@@ -10,6 +10,7 @@ const require_builtins_sqlite_storage_index = require("./builtins/sqlite-storage
10
10
  const require_formatter = require("./formatter-DqAKDlvN.js");
11
11
  const require_builtins_winston_logging_index = require("./builtins/winston-logging/index.js");
12
12
  const require_builtins_console_logging_index = require("./builtins/console-logging/index.js");
13
+ const require_builtins_loki_logging_index = require("./builtins/loki-logging/index.js");
13
14
  const require_builtins_hub_forwarder_index = require("./builtins/hub-forwarder/index.js");
14
15
  const require_builtins_storage_orchestrator_storage_orchestrator_addon = require("./builtins/storage-orchestrator/storage-orchestrator.addon.js");
15
16
  require("./builtins/storage-orchestrator/index.js");
@@ -886,6 +887,43 @@ var LogRingBuffer = class {
886
887
  for (let i = survivors.length - 1; i >= 0; i--) this.push(survivors[i]);
887
888
  return removed;
888
889
  }
890
+ /** Entries currently retained. */
891
+ size() {
892
+ return this.count;
893
+ }
894
+ /**
895
+ * Drop up to `max` entries, OLDEST first, whose level is at or below
896
+ * `threshold`. Returns how many were removed.
897
+ *
898
+ * This is what lets a total-memory cap be enforced without losing the entries
899
+ * that matter: sweeping `debug` reclaims almost all of the space (debug is the
900
+ * overwhelming majority of any busy buffer) while `warn` and `error` are never
901
+ * touched. Losing the one error line that explains an incident, in order to keep
902
+ * a thousand debug lines about frame timings, would be the wrong trade.
903
+ *
904
+ * Oldest-first because recent context is what an operator is looking at.
905
+ */
906
+ pruneOldestAtOrBelow(threshold, max) {
907
+ if (this.count === 0 || max <= 0) return 0;
908
+ const victims = /* @__PURE__ */ new Set();
909
+ for (let i = this.count - 1; i >= 0 && victims.size < max; i--) {
910
+ const index = (this.head - 1 - i + this.capacity) % this.capacity;
911
+ const entry = this.buffer[index];
912
+ if (entry !== void 0 && require_dist.logLevelAtMost(entry.level, threshold)) victims.add(index);
913
+ }
914
+ if (victims.size === 0) return 0;
915
+ const survivors = [];
916
+ for (let i = this.count - 1; i >= 0; i--) {
917
+ const index = (this.head - 1 - i + this.capacity) % this.capacity;
918
+ if (!victims.has(index)) survivors.push(this.buffer[index]);
919
+ }
920
+ const removed = this.count - survivors.length;
921
+ this.buffer.fill(void 0);
922
+ this.head = 0;
923
+ this.count = 0;
924
+ for (const entry of survivors) this.push(entry);
925
+ return removed;
926
+ }
889
927
  };
890
928
  //#endregion
891
929
  //#region src/logging/partitioned-log-buffer.ts
@@ -906,21 +944,52 @@ function addonBucketKey(addonId) {
906
944
  return bare;
907
945
  }
908
946
  /**
947
+ * Once a total cap is hit, prune down to this fraction of it rather than to
948
+ * exactly the cap. Without the gap, the buffer would sit permanently at the
949
+ * threshold and every single subsequent push would trigger a sweep.
950
+ */
951
+ var PRUNE_TARGET_RATIO = .9;
952
+ /**
909
953
  * A log buffer partitioned into one fixed-capacity {@link LogRingBuffer} per
910
954
  * `addonId`. A chatty addon (e.g. detection-pipeline) only ever evicts its OWN
911
955
  * bucket, so a quiet addon's sparse lines (e.g. a HomeAssistant `image` entity)
912
956
  * survive far longer than they would in a single shared FIFO ring.
913
957
  *
914
958
  * Drop-in for {@link LogRingBuffer} from {@link LogManager}'s perspective —
915
- * exposes the same `push` / `getAll` / `query` / `clear` surface. Total memory
916
- * is bounded by `perAddonCapacity × (number of distinct addons seen)`; quiet
917
- * buckets never grow past the handful of lines they actually emit.
959
+ * exposes the same `push` / `getAll` / `query` / `clear` surface.
960
+ *
961
+ * ## Two bounds, doing different jobs
962
+ *
963
+ * **`perAddonCapacity`** is a HARD bound: each bucket is a fixed-size ring, so
964
+ * total memory can never exceed `perAddonCapacity × buckets` whatever else
965
+ * happens. This is the safety net.
966
+ *
967
+ * **`maxTotalEntries`** is a SOFT target across all buckets, and it exists because
968
+ * the hard bound scales with addon count — 70 addons × 5000 is a lot of retained
969
+ * entries on a small box. When the total is exceeded, the sweep discards only
970
+ * entries at or below `pruneLevel` (default `debug`), oldest first, from the
971
+ * largest buckets first.
972
+ *
973
+ * It is deliberately soft. Meeting a total cap by discarding `warn` and `error`
974
+ * would trade the entries that explain an incident for entries about frame
975
+ * timings; if pruning every prunable entry still leaves the total above the cap,
976
+ * the buffer stays above it and the hard per-bucket bound is what holds. A cap
977
+ * that can evict an error is not a feature.
978
+ *
979
+ * Largest-bucket-first because the noisy addon is the one creating the pressure —
980
+ * the same principle that motivated partitioning in the first place.
918
981
  */
919
982
  var PartitionedLogBuffer = class {
920
- perAddonCapacity;
921
983
  buffers = /* @__PURE__ */ new Map();
922
- constructor(perAddonCapacity = 5e3) {
923
- this.perAddonCapacity = perAddonCapacity;
984
+ perAddonCapacity;
985
+ maxTotalEntries;
986
+ pruneLevel;
987
+ /** Running total, so `push` does not walk every bucket to decide. */
988
+ totalEntries = 0;
989
+ constructor(perAddonCapacity = 5e3, options = {}) {
990
+ this.perAddonCapacity = options.perAddonCapacity ?? perAddonCapacity;
991
+ this.maxTotalEntries = options.maxTotalEntries ?? null;
992
+ this.pruneLevel = options.pruneLevel ?? "debug";
924
993
  }
925
994
  bufferFor(key) {
926
995
  let buf = this.buffers.get(key);
@@ -931,7 +1000,33 @@ var PartitionedLogBuffer = class {
931
1000
  return buf;
932
1001
  }
933
1002
  push(entry) {
934
- this.bufferFor(addonBucketKey(entry.tags?.addonId)).push(entry);
1003
+ const buf = this.bufferFor(addonBucketKey(entry.tags?.addonId));
1004
+ const before = buf.size();
1005
+ buf.push(entry);
1006
+ this.totalEntries += buf.size() - before;
1007
+ if (this.maxTotalEntries !== null && this.totalEntries > this.maxTotalEntries) this.enforceTotalCap(this.maxTotalEntries);
1008
+ }
1009
+ /**
1010
+ * Bring the total down to `PRUNE_TARGET_RATIO × cap` by discarding prunable
1011
+ * entries, largest bucket first. Stops early when nothing prunable is left —
1012
+ * see the class docblock on why that is the correct outcome rather than a
1013
+ * failure to enforce.
1014
+ */
1015
+ enforceTotalCap(cap) {
1016
+ const target = Math.max(1, Math.floor(cap * PRUNE_TARGET_RATIO));
1017
+ let deficit = this.totalEntries - target;
1018
+ if (deficit <= 0) return;
1019
+ const bySizeDesc = [...this.buffers.values()].sort((a, b) => b.size() - a.size());
1020
+ for (const buf of bySizeDesc) {
1021
+ if (deficit <= 0) break;
1022
+ const removed = buf.pruneOldestAtOrBelow(this.pruneLevel, deficit);
1023
+ this.totalEntries -= removed;
1024
+ deficit -= removed;
1025
+ }
1026
+ }
1027
+ /** Entries retained across every bucket. */
1028
+ size() {
1029
+ return this.totalEntries;
935
1030
  }
936
1031
  /** Every retained entry across all buckets, newest-first (mirrors
937
1032
  * {@link LogRingBuffer.getAll}). Used to replay history to a destination. */
@@ -957,9 +1052,14 @@ var PartitionedLogBuffer = class {
957
1052
  }
958
1053
  clear(filter = {}) {
959
1054
  const pinned = this.pinnedAddonKey(filter);
960
- if (pinned !== null) return this.buffers.get(pinned)?.clear(filter) ?? 0;
1055
+ if (pinned !== null) {
1056
+ const removed = this.buffers.get(pinned)?.clear(filter) ?? 0;
1057
+ this.totalEntries -= removed;
1058
+ return removed;
1059
+ }
961
1060
  let removed = 0;
962
1061
  for (const buf of this.buffers.values()) removed += buf.clear(filter);
1062
+ this.totalEntries -= removed;
963
1063
  return removed;
964
1064
  }
965
1065
  /** The bucket key a filter pins to via `tags.addonId`, or null when the
@@ -1037,11 +1137,22 @@ var LogManager = class {
1037
1137
  destinations = [];
1038
1138
  subscribers = /* @__PURE__ */ new Map();
1039
1139
  deviceNameLookup = null;
1040
- /** `perAddonCapacity` bounds EACH addon's bucket, not the total — a chatty
1041
- * addon evicts only its own lines, so quiet addons keep their sparse history.
1042
- * See {@link PartitionedLogBuffer}. */
1043
- constructor(perAddonCapacity = 5e3) {
1044
- this.ringBuffer = new PartitionedLogBuffer(perAddonCapacity);
1140
+ /**
1141
+ * `perAddonCapacity` bounds EACH addon's bucket, not the total a chatty addon
1142
+ * evicts only its own lines, so quiet addons keep their sparse history.
1143
+ *
1144
+ * `options.maxTotalEntries` adds a soft ceiling across all buckets, because the
1145
+ * per-bucket bound scales with addon count. When it is exceeded, only entries at
1146
+ * or below `options.pruneLevel` (default `debug`) are discarded — `warn` and
1147
+ * `error` are never evicted to satisfy it. Both default to the previous
1148
+ * behaviour: no total cap. See {@link PartitionedLogBuffer}.
1149
+ */
1150
+ constructor(perAddonCapacity = 5e3, options = {}) {
1151
+ this.ringBuffer = new PartitionedLogBuffer(perAddonCapacity, options);
1152
+ }
1153
+ /** Entries currently retained across every bucket. */
1154
+ bufferSize() {
1155
+ return this.ringBuffer.size();
1045
1156
  }
1046
1157
  /**
1047
1158
  * Register a callback that resolves `deviceId → deviceName`. Called
@@ -93782,6 +93893,8 @@ exports.LocalChildClient = require_manifest_python_deps.LocalChildClient;
93782
93893
  exports.LocalChildRegistry = require_manifest_python_deps.LocalChildRegistry;
93783
93894
  exports.LogManager = LogManager;
93784
93895
  exports.LogRingBuffer = LogRingBuffer;
93896
+ exports.LokiDestination = require_builtins_loki_logging_index.LokiDestination$1;
93897
+ exports.LokiLoggingAddon = require_builtins_loki_logging_index.LokiLoggingAddon$1;
93785
93898
  exports.METHOD_ACCESS_MAP = require_dist.METHOD_ACCESS_MAP;
93786
93899
  exports.ModelDownloadService = require_model_download_service.ModelDownloadService;
93787
93900
  exports.NATIVE_PROVIDER_SERVICE_INFIX = require_manifest_python_deps.NATIVE_PROVIDER_SERVICE_INFIX;
package/dist/index.mjs CHANGED
@@ -1,6 +1,6 @@
1
- import { B as looseSchema, Dt as readinessKey, Et as parseJsonUnknown$1, F as isVoidInput, I as kebabToCamel, L as lifecycleJobSchema, M as isArrayOutputSchema, N as isCollectionArrayMethod, Ot as resolveCapMount, P as isObjectInput, St as expandCapMethods, Tt as parseJsonObject, W as objectInputDeclaresAddonId, _t as asNumber, at as errMsg$1, bt as emitDownForOwnedCaps, c as RUNTIME_DEFAULTS, ct as DEVICE_SETTINGS_CONTRIBUTION_METHODS, gt as asJsonObject$1, jt as EventCategory$1, k as extractNestedAddonId, kt as scopeKey, lt as DEVICE_STATUS_METHOD, m as addonSettingsCapability, mt as ReadinessTimeoutError, pt as ReadinessRegistry, q as procedureAuthKey, s as METHOD_ACCESS_MAP, st as DATAPLANE_SECRET_HEADER$1, t as ALL_CAPABILITY_DEFINITIONS, vt as asString$1, yt as createEvent } from "./dist-DpKeSZel.mjs";
1
+ import { At as scopeKey, B as logLevelAtMost, Ct as expandCapMethods, Dt as parseJsonUnknown$1, Et as parseJsonObject, F as isVoidInput, G as objectInputDeclaresAddonId, I as kebabToCamel, J as procedureAuthKey, L as lifecycleJobSchema, M as isArrayOutputSchema, Mt as EventCategory$1, N as isCollectionArrayMethod, Ot as readinessKey, P as isObjectInput, V as looseSchema, _t as asJsonObject$1, bt as createEvent, c as RUNTIME_DEFAULTS, ct as DATAPLANE_SECRET_HEADER$1, ht as ReadinessTimeoutError, k as extractNestedAddonId, kt as resolveCapMount, lt as DEVICE_SETTINGS_CONTRIBUTION_METHODS, m as addonSettingsCapability, mt as ReadinessRegistry, ot as errMsg$1, s as METHOD_ACCESS_MAP, t as ALL_CAPABILITY_DEFINITIONS, ut as DEVICE_STATUS_METHOD, vt as asNumber, xt as emitDownForOwnedCaps, yt as asString$1 } from "./dist-eOaraBhT.mjs";
2
2
  import { a as downloadModel, c as getModelFilePath, d as contentTypeFor, f as createAuthenticatedFileServer, h as resolveFilePath, i as downloadFile, l as isModelDownloaded, m as parseTokenizedUrl, n as collectModelFiles, o as ensureModel, p as parseRangeHeader, r as deleteModelFromDisk, s as fetchJson, t as ModelDownloadService, u as createFileDataPlaneHandler } from "./model-download-service-Cp9f4dk6.mjs";
3
- import { $ as buildNativeCapProxy, A as createHubCapForwardService, B as AGENT_CAP_FWD_ACTION, C as brokerTransportLink, Ct as resolveAddonClass, D as localProviderLink, E as ipcParentLink, F as createUdsLogger, G as callWithServiceDiscovery, H as CapRouteResolver, I as createUdsLoggerWithControl, J as UdsLocalTransportServer, K as createLocalTransport, L as LocalChildClient, M as createUdsEventBridge, N as createUdsEventBus, O as HUB_CAP_FWD_ACTION, P as udsChildLogToWorkerEntry, Q as encodeFrame, R as LocalChildRegistry, S as brokerCallForCap, St as runNpm, T as ipcChildLink, U as CapRouteError, V as AGENT_CAP_FWD_SERVICE, W as classifyCapRoute, X as localEndpointPath, Y as SocketChannel, Z as FrameDecoder, _ as createKernelHwAccel, _t as CapabilityHandle, a as getWorkerDeviceRegistry, b as __resetCapUsageRegistryForTests, bt as installManifestNativeDeps, c as setHubConnected, ct as NATIVE_PROVIDER_SERVICE_INFIX, d as getBrokerEventBus, dt as capBareAction, et as buildUdsNativeCapProxy, f as getMoleculerEventStats, ft as capServiceName, g as AddonDepsManager, gt as DeviceRegistry, h as subscribePassthrough, ht as serializeTypedArrays, i as createUdsAddonContext, it as mountNativeCapService, j as createParentUnownedCallHandler, k as HUB_CAP_FWD_SERVICE, l as EVENT_TOPIC_PREFIX, lt as capActionName, m as setNodeEventInterest, mt as deserializeTypedArrays, n as adaptBrokerToCluster, o as getOrInitReadinessRegistry, ot as createAddonService, p as registerEventBusService, pt as parseCapAction, q as UdsLocalTransportClient, r as createAddonContext, s as getOrInitReadinessRegistryForClient, st as validateProviderRegistrations, t as installManifestPythonDeps, tt as createBrokerDeviceManagerApi, u as clusterEventTopic, ut as capActionSuffix, v as resolveHwAccel, vt as CapabilityUnavailableError, w as buildLinkChain, wt as createAddonDataPlaneFacility, x as getCapUsageRegistry, xt as resolveNpmInvocation, y as CapUsageRegistry, yt as copyBundledNativeModules, z as UDS_NO_ROUTE_PREFIX } from "./manifest-python-deps-I2MGvDvo.mjs";
3
+ import { $ as buildNativeCapProxy, A as createHubCapForwardService, B as AGENT_CAP_FWD_ACTION, C as brokerTransportLink, Ct as resolveAddonClass, D as localProviderLink, E as ipcParentLink, F as createUdsLogger, G as callWithServiceDiscovery, H as CapRouteResolver, I as createUdsLoggerWithControl, J as UdsLocalTransportServer, K as createLocalTransport, L as LocalChildClient, M as createUdsEventBridge, N as createUdsEventBus, O as HUB_CAP_FWD_ACTION, P as udsChildLogToWorkerEntry, Q as encodeFrame, R as LocalChildRegistry, S as brokerCallForCap, St as runNpm, T as ipcChildLink, U as CapRouteError, V as AGENT_CAP_FWD_SERVICE, W as classifyCapRoute, X as localEndpointPath, Y as SocketChannel, Z as FrameDecoder, _ as createKernelHwAccel, _t as CapabilityHandle, a as getWorkerDeviceRegistry, b as __resetCapUsageRegistryForTests, bt as installManifestNativeDeps, c as setHubConnected, ct as NATIVE_PROVIDER_SERVICE_INFIX, d as getBrokerEventBus, dt as capBareAction, et as buildUdsNativeCapProxy, f as getMoleculerEventStats, ft as capServiceName, g as AddonDepsManager, gt as DeviceRegistry, h as subscribePassthrough, ht as serializeTypedArrays, i as createUdsAddonContext, it as mountNativeCapService, j as createParentUnownedCallHandler, k as HUB_CAP_FWD_SERVICE, l as EVENT_TOPIC_PREFIX, lt as capActionName, m as setNodeEventInterest, mt as deserializeTypedArrays, n as adaptBrokerToCluster, o as getOrInitReadinessRegistry, ot as createAddonService, p as registerEventBusService, pt as parseCapAction, q as UdsLocalTransportClient, r as createAddonContext, s as getOrInitReadinessRegistryForClient, st as validateProviderRegistrations, t as installManifestPythonDeps, tt as createBrokerDeviceManagerApi, u as clusterEventTopic, ut as capActionSuffix, v as resolveHwAccel, vt as CapabilityUnavailableError, w as buildLinkChain, wt as createAddonDataPlaneFacility, x as getCapUsageRegistry, xt as resolveNpmInvocation, y as CapUsageRegistry, yt as copyBundledNativeModules, z as UDS_NO_ROUTE_PREFIX } from "./manifest-python-deps-bn3qrsxR.mjs";
4
4
  import { n as getSinglePidStats, t as getPidStats } from "./resource-monitor-Le3l0qS2.mjs";
5
5
  import { FilesystemStorageAddon, t as FilesystemStorageProvider } from "./builtins/sqlite-storage/filesystem-storage.addon.mjs";
6
6
  import { SqliteSettingsAddon, t as SqliteSettingsBackend } from "./builtins/sqlite-storage/sqlite-settings.addon.mjs";
@@ -8,6 +8,7 @@ import { ConfigStore, DeviceStore } from "./builtins/sqlite-storage/index.mjs";
8
8
  import { t as formatLogLine } from "./formatter-B7qW8bPJ.mjs";
9
9
  import { WinstonDestination, WinstonLoggingAddon } from "./builtins/winston-logging/index.mjs";
10
10
  import { ConsoleDestination, ConsoleLoggingAddon } from "./builtins/console-logging/index.mjs";
11
+ import { LokiDestination, LokiLoggingAddon } from "./builtins/loki-logging/index.mjs";
11
12
  import { HubForwarderAddon, HubForwarderDestination } from "./builtins/hub-forwarder/index.mjs";
12
13
  import { StorageOrchestratorAddon, n as StorageOrchestratorService } from "./builtins/storage-orchestrator/storage-orchestrator.addon.mjs";
13
14
  import "./builtins/storage-orchestrator/index.mjs";
@@ -878,6 +879,43 @@ var LogRingBuffer = class {
878
879
  for (let i = survivors.length - 1; i >= 0; i--) this.push(survivors[i]);
879
880
  return removed;
880
881
  }
882
+ /** Entries currently retained. */
883
+ size() {
884
+ return this.count;
885
+ }
886
+ /**
887
+ * Drop up to `max` entries, OLDEST first, whose level is at or below
888
+ * `threshold`. Returns how many were removed.
889
+ *
890
+ * This is what lets a total-memory cap be enforced without losing the entries
891
+ * that matter: sweeping `debug` reclaims almost all of the space (debug is the
892
+ * overwhelming majority of any busy buffer) while `warn` and `error` are never
893
+ * touched. Losing the one error line that explains an incident, in order to keep
894
+ * a thousand debug lines about frame timings, would be the wrong trade.
895
+ *
896
+ * Oldest-first because recent context is what an operator is looking at.
897
+ */
898
+ pruneOldestAtOrBelow(threshold, max) {
899
+ if (this.count === 0 || max <= 0) return 0;
900
+ const victims = /* @__PURE__ */ new Set();
901
+ for (let i = this.count - 1; i >= 0 && victims.size < max; i--) {
902
+ const index = (this.head - 1 - i + this.capacity) % this.capacity;
903
+ const entry = this.buffer[index];
904
+ if (entry !== void 0 && logLevelAtMost(entry.level, threshold)) victims.add(index);
905
+ }
906
+ if (victims.size === 0) return 0;
907
+ const survivors = [];
908
+ for (let i = this.count - 1; i >= 0; i--) {
909
+ const index = (this.head - 1 - i + this.capacity) % this.capacity;
910
+ if (!victims.has(index)) survivors.push(this.buffer[index]);
911
+ }
912
+ const removed = this.count - survivors.length;
913
+ this.buffer.fill(void 0);
914
+ this.head = 0;
915
+ this.count = 0;
916
+ for (const entry of survivors) this.push(entry);
917
+ return removed;
918
+ }
881
919
  };
882
920
  //#endregion
883
921
  //#region src/logging/partitioned-log-buffer.ts
@@ -898,21 +936,52 @@ function addonBucketKey(addonId) {
898
936
  return bare;
899
937
  }
900
938
  /**
939
+ * Once a total cap is hit, prune down to this fraction of it rather than to
940
+ * exactly the cap. Without the gap, the buffer would sit permanently at the
941
+ * threshold and every single subsequent push would trigger a sweep.
942
+ */
943
+ var PRUNE_TARGET_RATIO = .9;
944
+ /**
901
945
  * A log buffer partitioned into one fixed-capacity {@link LogRingBuffer} per
902
946
  * `addonId`. A chatty addon (e.g. detection-pipeline) only ever evicts its OWN
903
947
  * bucket, so a quiet addon's sparse lines (e.g. a HomeAssistant `image` entity)
904
948
  * survive far longer than they would in a single shared FIFO ring.
905
949
  *
906
950
  * Drop-in for {@link LogRingBuffer} from {@link LogManager}'s perspective —
907
- * exposes the same `push` / `getAll` / `query` / `clear` surface. Total memory
908
- * is bounded by `perAddonCapacity × (number of distinct addons seen)`; quiet
909
- * buckets never grow past the handful of lines they actually emit.
951
+ * exposes the same `push` / `getAll` / `query` / `clear` surface.
952
+ *
953
+ * ## Two bounds, doing different jobs
954
+ *
955
+ * **`perAddonCapacity`** is a HARD bound: each bucket is a fixed-size ring, so
956
+ * total memory can never exceed `perAddonCapacity × buckets` whatever else
957
+ * happens. This is the safety net.
958
+ *
959
+ * **`maxTotalEntries`** is a SOFT target across all buckets, and it exists because
960
+ * the hard bound scales with addon count — 70 addons × 5000 is a lot of retained
961
+ * entries on a small box. When the total is exceeded, the sweep discards only
962
+ * entries at or below `pruneLevel` (default `debug`), oldest first, from the
963
+ * largest buckets first.
964
+ *
965
+ * It is deliberately soft. Meeting a total cap by discarding `warn` and `error`
966
+ * would trade the entries that explain an incident for entries about frame
967
+ * timings; if pruning every prunable entry still leaves the total above the cap,
968
+ * the buffer stays above it and the hard per-bucket bound is what holds. A cap
969
+ * that can evict an error is not a feature.
970
+ *
971
+ * Largest-bucket-first because the noisy addon is the one creating the pressure —
972
+ * the same principle that motivated partitioning in the first place.
910
973
  */
911
974
  var PartitionedLogBuffer = class {
912
- perAddonCapacity;
913
975
  buffers = /* @__PURE__ */ new Map();
914
- constructor(perAddonCapacity = 5e3) {
915
- this.perAddonCapacity = perAddonCapacity;
976
+ perAddonCapacity;
977
+ maxTotalEntries;
978
+ pruneLevel;
979
+ /** Running total, so `push` does not walk every bucket to decide. */
980
+ totalEntries = 0;
981
+ constructor(perAddonCapacity = 5e3, options = {}) {
982
+ this.perAddonCapacity = options.perAddonCapacity ?? perAddonCapacity;
983
+ this.maxTotalEntries = options.maxTotalEntries ?? null;
984
+ this.pruneLevel = options.pruneLevel ?? "debug";
916
985
  }
917
986
  bufferFor(key) {
918
987
  let buf = this.buffers.get(key);
@@ -923,7 +992,33 @@ var PartitionedLogBuffer = class {
923
992
  return buf;
924
993
  }
925
994
  push(entry) {
926
- this.bufferFor(addonBucketKey(entry.tags?.addonId)).push(entry);
995
+ const buf = this.bufferFor(addonBucketKey(entry.tags?.addonId));
996
+ const before = buf.size();
997
+ buf.push(entry);
998
+ this.totalEntries += buf.size() - before;
999
+ if (this.maxTotalEntries !== null && this.totalEntries > this.maxTotalEntries) this.enforceTotalCap(this.maxTotalEntries);
1000
+ }
1001
+ /**
1002
+ * Bring the total down to `PRUNE_TARGET_RATIO × cap` by discarding prunable
1003
+ * entries, largest bucket first. Stops early when nothing prunable is left —
1004
+ * see the class docblock on why that is the correct outcome rather than a
1005
+ * failure to enforce.
1006
+ */
1007
+ enforceTotalCap(cap) {
1008
+ const target = Math.max(1, Math.floor(cap * PRUNE_TARGET_RATIO));
1009
+ let deficit = this.totalEntries - target;
1010
+ if (deficit <= 0) return;
1011
+ const bySizeDesc = [...this.buffers.values()].sort((a, b) => b.size() - a.size());
1012
+ for (const buf of bySizeDesc) {
1013
+ if (deficit <= 0) break;
1014
+ const removed = buf.pruneOldestAtOrBelow(this.pruneLevel, deficit);
1015
+ this.totalEntries -= removed;
1016
+ deficit -= removed;
1017
+ }
1018
+ }
1019
+ /** Entries retained across every bucket. */
1020
+ size() {
1021
+ return this.totalEntries;
927
1022
  }
928
1023
  /** Every retained entry across all buckets, newest-first (mirrors
929
1024
  * {@link LogRingBuffer.getAll}). Used to replay history to a destination. */
@@ -949,9 +1044,14 @@ var PartitionedLogBuffer = class {
949
1044
  }
950
1045
  clear(filter = {}) {
951
1046
  const pinned = this.pinnedAddonKey(filter);
952
- if (pinned !== null) return this.buffers.get(pinned)?.clear(filter) ?? 0;
1047
+ if (pinned !== null) {
1048
+ const removed = this.buffers.get(pinned)?.clear(filter) ?? 0;
1049
+ this.totalEntries -= removed;
1050
+ return removed;
1051
+ }
953
1052
  let removed = 0;
954
1053
  for (const buf of this.buffers.values()) removed += buf.clear(filter);
1054
+ this.totalEntries -= removed;
955
1055
  return removed;
956
1056
  }
957
1057
  /** The bucket key a filter pins to via `tags.addonId`, or null when the
@@ -1029,11 +1129,22 @@ var LogManager = class {
1029
1129
  destinations = [];
1030
1130
  subscribers = /* @__PURE__ */ new Map();
1031
1131
  deviceNameLookup = null;
1032
- /** `perAddonCapacity` bounds EACH addon's bucket, not the total — a chatty
1033
- * addon evicts only its own lines, so quiet addons keep their sparse history.
1034
- * See {@link PartitionedLogBuffer}. */
1035
- constructor(perAddonCapacity = 5e3) {
1036
- this.ringBuffer = new PartitionedLogBuffer(perAddonCapacity);
1132
+ /**
1133
+ * `perAddonCapacity` bounds EACH addon's bucket, not the total a chatty addon
1134
+ * evicts only its own lines, so quiet addons keep their sparse history.
1135
+ *
1136
+ * `options.maxTotalEntries` adds a soft ceiling across all buckets, because the
1137
+ * per-bucket bound scales with addon count. When it is exceeded, only entries at
1138
+ * or below `options.pruneLevel` (default `debug`) are discarded — `warn` and
1139
+ * `error` are never evicted to satisfy it. Both default to the previous
1140
+ * behaviour: no total cap. See {@link PartitionedLogBuffer}.
1141
+ */
1142
+ constructor(perAddonCapacity = 5e3, options = {}) {
1143
+ this.ringBuffer = new PartitionedLogBuffer(perAddonCapacity, options);
1144
+ }
1145
+ /** Entries currently retained across every bucket. */
1146
+ bufferSize() {
1147
+ return this.ringBuffer.size();
1037
1148
  }
1038
1149
  /**
1039
1150
  * Register a callback that resolves `deviceId → deviceName`. Called
@@ -93711,4 +93822,4 @@ var LifecycleJobEngine = class {
93711
93822
  }
93712
93823
  };
93713
93824
  //#endregion
93714
- export { AGENT_CAP_FWD_ACTION, AGENT_CAP_FWD_SERVICE, AGENT_READINESS_SERVICE_NAME, ALL_CAPABILITY_DEFINITIONS, AddonApiFactory, AddonDepsManager, AddonEngineManager, AddonHealthMonitor, AddonInstaller, AddonLoader, AddonManifest, AddonRouteRegistry, AlertCenterAddon, ApiKeyManager, AuthManager, CLUSTER_SECRET_MISMATCH_TYPE, CLUSTER_SECRET_REJECTED_EXIT_CODE, CORE_CAP_SERVICE_NAME, CapRouteError, CapRouteResolver, CapUsageRegistry, CapabilityHandle, CapabilityRegistry, CapabilityUnavailableError, ConfigManager, ConfigStore, ConsoleDestination, ConsoleLoggingAddon, CustomActionRegistry, DEFAULT_DATA_PATH, DEVICE_SETTINGS_CONTRIBUTION_METHODS, DEVICE_STATUS_METHOD, DataPlaneRegistry, DeviceManagerAddon, DeviceRegistry, DeviceStore, EVENT_TOPIC_PREFIX, EngineManagerResolver, EventBus, FeatureManager, FilesystemStorageAddon, FilesystemStorageProvider, FrameDecoder, FsStorageBackend, HEALTH_MONITOR_GRACE_PERIOD_MS, HEALTH_MONITOR_RETRY_INTERVALS_MS, HEALTH_MONITOR_TICK_MS, HUB_CAP_FWD_ACTION, HUB_CAP_FWD_SERVICE, HubForwarderAddon, HubForwarderDestination, HubLogForwarder, HubNodeRegistry, INFRA_CAPABILITIES, IntegrationRegistry, JobJournal, LifecycleJobEngine, LifecycleStateMachine, LocalAuthAddon, LocalChildClient, LocalChildRegistry, LogManager, LogRingBuffer, METHOD_ACCESS_MAP, ModelDownloadService, NATIVE_PROVIDER_SERVICE_INFIX, NATIVE_SCAN_DEPTH, NativeMetricsAddon, NativeMetricsProvider, NetworkQualityTracker, NotificationService, PYTHON_VERSION, PipelineRunner, PipelineValidator, PythonEnvManager, RESTART_MARKER_FILE, RUNTIME_DEFAULTS, ReadinessRegistry, ReadinessTimeoutError, ReplEngine, RingBuffer, ScopedLogger, ScopedTokenManager, SocketChannel, SqliteSettingsAddon, SqliteSettingsBackend, StagingArea, StorageLocationManager, StorageManager, StorageOrchestratorAddon, StorageOrchestratorService, SystemConfigAddon, SystemEventBus, TRADITIONAL_NATIVE_PACKAGES, ToastService, UDS_NO_ROUTE_PREFIX, UdsLocalTransportClient, UdsLocalTransportServer, UserManager, WinstonDestination, WinstonLoggingAddon, __resetCapUsageRegistryForTests, adaptBrokerToCluster, addonSettingsCapability, bootstrapSchema, brokerCallForCap, brokerTransportLink, buildBinaryPath, buildCapRouters, buildLinkChain, buildNativeCapProxy, buildNodeManifest, buildStorageLocationRegistry, buildUdsNativeCapProxy, builderMountedCapNames, callRegisterNodeWithRetry, callWithServiceDiscovery, capActionName, capActionSuffix, capBareAction, capServiceName, classifyCapRoute, clearPendingRestart, clusterEventTopic, clusterSecretMatches, collectModelFiles, contentTypeFor, copyDirRecursive, copyExtraFileDirs, createAddonContext, createAddonDataPlaneFacility, createAddonService, createAuthenticatedFileServer, createBroker, createBrokerDeviceManagerApi, createCoreCapService, createFileDataPlaneHandler, createHubCapForwardService, createHubService, createKernelHwAccel, createLocalTransport, createParentUnownedCallHandler, createProcessService, createReadinessService, createReadinessServiceForRegistry, createScopedProcessManager, createStreamProbeBrokerService, createUdsAddonContext, createUdsEventBridge, createUdsEventBus, createUdsLogger, createUdsLoggerWithControl, deleteModelFromDisk, deriveAgentListenPort, describeProviderKindDrift, detectWorkspacePackagesDir, downloadBinary, downloadFile, downloadModel, emitDownForOwnedCaps, encodeFrame, ensureAddonNativePrebuilds, ensureBinary, ensureDir, ensureFfmpeg, ensureLibraryBuilt, ensureModel, ensureNativePrebuilds, ensurePython, ensureTlsCert, expandCapMethods, fetchJson, findInPath, formatLogLine, getBrokerEventBus, getCapUsageRegistry, getFfmpegDownloadUrl, getModelFilePath, getMoleculerEventStats, getOrInitReadinessRegistry, getOrInitReadinessRegistryForClient, getPidStats, getPlatformInfo, getPythonDownloadUrl, getRestartMarkerPath, getSinglePidStats, getWorkerDeviceRegistry, hasDotNode, hashClusterSecret, installManifestNativeDeps, installManifestPythonDeps, installPackageFromNpm, installPythonPackages, installPythonRequirements, ipcChildLink, ipcParentLink, isAddonDeploySource, isArrayOutputSchema, isClusterSecretMismatchError, isCollectionArrayMethod, isInfraCapability, isModelDownloaded, isSourceNewer, loadTlsCert, localEndpointPath, localProviderLink, mountNativeCapService, parseCapAction, parseRangeHeader, parseTokenizedUrl, proxyToUpstream, readPendingRestart, readinessKey, registerEventBusService, resolveFilePath, resolveHwAccel, resolveNpmInvocation, runNpm, scheduleSelfRestart, scopeKey, scopesAllowDeviceCap, serializeTypedArrays, setHubConnected, setNodeEventInterest, stripCamstackDeps, subscribePassthrough, udsChildLogToWorkerEntry, validateProviderRegistrations, writePendingRestart };
93825
+ export { AGENT_CAP_FWD_ACTION, AGENT_CAP_FWD_SERVICE, AGENT_READINESS_SERVICE_NAME, ALL_CAPABILITY_DEFINITIONS, AddonApiFactory, AddonDepsManager, AddonEngineManager, AddonHealthMonitor, AddonInstaller, AddonLoader, AddonManifest, AddonRouteRegistry, AlertCenterAddon, ApiKeyManager, AuthManager, CLUSTER_SECRET_MISMATCH_TYPE, CLUSTER_SECRET_REJECTED_EXIT_CODE, CORE_CAP_SERVICE_NAME, CapRouteError, CapRouteResolver, CapUsageRegistry, CapabilityHandle, CapabilityRegistry, CapabilityUnavailableError, ConfigManager, ConfigStore, ConsoleDestination, ConsoleLoggingAddon, CustomActionRegistry, DEFAULT_DATA_PATH, DEVICE_SETTINGS_CONTRIBUTION_METHODS, DEVICE_STATUS_METHOD, DataPlaneRegistry, DeviceManagerAddon, DeviceRegistry, DeviceStore, EVENT_TOPIC_PREFIX, EngineManagerResolver, EventBus, FeatureManager, FilesystemStorageAddon, FilesystemStorageProvider, FrameDecoder, FsStorageBackend, HEALTH_MONITOR_GRACE_PERIOD_MS, HEALTH_MONITOR_RETRY_INTERVALS_MS, HEALTH_MONITOR_TICK_MS, HUB_CAP_FWD_ACTION, HUB_CAP_FWD_SERVICE, HubForwarderAddon, HubForwarderDestination, HubLogForwarder, HubNodeRegistry, INFRA_CAPABILITIES, IntegrationRegistry, JobJournal, LifecycleJobEngine, LifecycleStateMachine, LocalAuthAddon, LocalChildClient, LocalChildRegistry, LogManager, LogRingBuffer, LokiDestination, LokiLoggingAddon, METHOD_ACCESS_MAP, ModelDownloadService, NATIVE_PROVIDER_SERVICE_INFIX, NATIVE_SCAN_DEPTH, NativeMetricsAddon, NativeMetricsProvider, NetworkQualityTracker, NotificationService, PYTHON_VERSION, PipelineRunner, PipelineValidator, PythonEnvManager, RESTART_MARKER_FILE, RUNTIME_DEFAULTS, ReadinessRegistry, ReadinessTimeoutError, ReplEngine, RingBuffer, ScopedLogger, ScopedTokenManager, SocketChannel, SqliteSettingsAddon, SqliteSettingsBackend, StagingArea, StorageLocationManager, StorageManager, StorageOrchestratorAddon, StorageOrchestratorService, SystemConfigAddon, SystemEventBus, TRADITIONAL_NATIVE_PACKAGES, ToastService, UDS_NO_ROUTE_PREFIX, UdsLocalTransportClient, UdsLocalTransportServer, UserManager, WinstonDestination, WinstonLoggingAddon, __resetCapUsageRegistryForTests, adaptBrokerToCluster, addonSettingsCapability, bootstrapSchema, brokerCallForCap, brokerTransportLink, buildBinaryPath, buildCapRouters, buildLinkChain, buildNativeCapProxy, buildNodeManifest, buildStorageLocationRegistry, buildUdsNativeCapProxy, builderMountedCapNames, callRegisterNodeWithRetry, callWithServiceDiscovery, capActionName, capActionSuffix, capBareAction, capServiceName, classifyCapRoute, clearPendingRestart, clusterEventTopic, clusterSecretMatches, collectModelFiles, contentTypeFor, copyDirRecursive, copyExtraFileDirs, createAddonContext, createAddonDataPlaneFacility, createAddonService, createAuthenticatedFileServer, createBroker, createBrokerDeviceManagerApi, createCoreCapService, createFileDataPlaneHandler, createHubCapForwardService, createHubService, createKernelHwAccel, createLocalTransport, createParentUnownedCallHandler, createProcessService, createReadinessService, createReadinessServiceForRegistry, createScopedProcessManager, createStreamProbeBrokerService, createUdsAddonContext, createUdsEventBridge, createUdsEventBus, createUdsLogger, createUdsLoggerWithControl, deleteModelFromDisk, deriveAgentListenPort, describeProviderKindDrift, detectWorkspacePackagesDir, downloadBinary, downloadFile, downloadModel, emitDownForOwnedCaps, encodeFrame, ensureAddonNativePrebuilds, ensureBinary, ensureDir, ensureFfmpeg, ensureLibraryBuilt, ensureModel, ensureNativePrebuilds, ensurePython, ensureTlsCert, expandCapMethods, fetchJson, findInPath, formatLogLine, getBrokerEventBus, getCapUsageRegistry, getFfmpegDownloadUrl, getModelFilePath, getMoleculerEventStats, getOrInitReadinessRegistry, getOrInitReadinessRegistryForClient, getPidStats, getPlatformInfo, getPythonDownloadUrl, getRestartMarkerPath, getSinglePidStats, getWorkerDeviceRegistry, hasDotNode, hashClusterSecret, installManifestNativeDeps, installManifestPythonDeps, installPackageFromNpm, installPythonPackages, installPythonRequirements, ipcChildLink, ipcParentLink, isAddonDeploySource, isArrayOutputSchema, isClusterSecretMismatchError, isCollectionArrayMethod, isInfraCapability, isModelDownloaded, isSourceNewer, loadTlsCert, localEndpointPath, localProviderLink, mountNativeCapService, parseCapAction, parseRangeHeader, parseTokenizedUrl, proxyToUpstream, readPendingRestart, readinessKey, registerEventBusService, resolveFilePath, resolveHwAccel, resolveNpmInvocation, runNpm, scheduleSelfRestart, scopeKey, scopesAllowDeviceCap, serializeTypedArrays, setHubConnected, setNodeEventInterest, stripCamstackDeps, subscribePassthrough, udsChildLogToWorkerEntry, validateProviderRegistrations, writePendingRestart };