@camstack/system 1.2.16 → 1.2.18

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 (51) hide show
  1. package/dist/addon-runner.js +2 -10
  2. package/dist/addon-runner.mjs +3 -11
  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.js +37 -7
  24. package/dist/builtins/loki-logging/index.mjs +37 -7
  25. package/dist/builtins/loki-logging/loki-destination.d.ts +11 -0
  26. package/dist/builtins/loki-logging/loki-logging.addon.d.ts +8 -0
  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 +1 -1
  34. package/dist/builtins/snapshot/index.mjs +1 -1
  35. package/dist/builtins/sqlite-storage/filesystem-storage.addon.js +1 -1
  36. package/dist/builtins/sqlite-storage/filesystem-storage.addon.mjs +1 -1
  37. package/dist/builtins/sqlite-storage/sqlite-settings.addon.js +1 -1
  38. package/dist/builtins/sqlite-storage/sqlite-settings.addon.mjs +1 -1
  39. package/dist/builtins/storage-orchestrator/storage-orchestrator.addon.js +1 -1
  40. package/dist/builtins/storage-orchestrator/storage-orchestrator.addon.mjs +1 -1
  41. package/dist/builtins/system-config/system-config.addon.js +1 -1
  42. package/dist/builtins/system-config/system-config.addon.mjs +1 -1
  43. package/dist/builtins/winston-logging/index.js +1 -1
  44. package/dist/builtins/winston-logging/index.mjs +1 -1
  45. package/dist/{dist-BU-QPlE8.mjs → dist-DmQ6thmF.mjs} +31 -40
  46. package/dist/{dist-3AzhkmeY.js → dist-OQ1yU92D.js} +30 -45
  47. package/dist/index.js +2 -2
  48. package/dist/index.mjs +2 -2
  49. package/dist/{manifest-python-deps-D7-WBIg_.mjs → manifest-python-deps-B30qVAuW.mjs} +1 -2
  50. package/dist/{manifest-python-deps-DRN3x53E.js → manifest-python-deps-CnRW2Utv.js} +2 -3
  51. package/package.json +1 -1
@@ -1,6 +1,5 @@
1
1
  const require_chunk = require("./chunk-Cek0wNdY.js");
2
- const require_dist = require("./dist-3AzhkmeY.js");
3
- const require_manifest_python_deps = require("./manifest-python-deps-DRN3x53E.js");
2
+ const require_manifest_python_deps = require("./manifest-python-deps-CnRW2Utv.js");
4
3
  const require_custom_action_registry = require("./custom-action-registry-jY0NOZK8.js");
5
4
  let node_fs = require("node:fs");
6
5
  node_fs = require_chunk.__toESM(node_fs);
@@ -473,13 +472,6 @@ async function main() {
473
472
  */
474
473
  const allSingletonProviders = /* @__PURE__ */ new Map();
475
474
  /**
476
- * Cap-definition lookup for the dispatcher's collection-list-method guard.
477
- * Lets `child-cap-dispatch` reproduce the hub-side `concatCollection` skip:
478
- * a provider that doesn't implement a COLLECTION cap's array-returning method
479
- * contributes `[]` instead of throwing "method not found".
480
- */
481
- const capDefsByName = new Map(require_dist.ALL_CAPABILITY_DEFINITIONS.map((def) => [def.name, def]));
482
- /**
483
475
  * Resolve a singleton provider for the dispatcher: exact (capName, addonId)
484
476
  * match when the hint names a hosted provider, else the cap's first
485
477
  * registered provider (an unmatched `addonId` is method DATA — e.g.
@@ -536,7 +528,7 @@ async function main() {
536
528
  dispatch: createChildCapDispatch({
537
529
  getSingletonProvider: (capName, addonId) => resolveSingletonProvider(capName, addonId),
538
530
  getDeviceProvider: (capName, deviceId) => require_manifest_python_deps.getWorkerNativeCapProvider(capName, deviceId) ?? null,
539
- isCollectionListMethod: (capName, method) => require_dist.isCollectionArrayMethod(capDefsByName.get(capName), method)
531
+ isCollectionListMethod: (capName, method) => (0, _camstack_types_addon.isCollectionArrayMethodName)(capName, method)
540
532
  })
541
533
  });
542
534
  udsChildClient.onAddonCall(createChildAddonCallDispatch({
@@ -1,10 +1,9 @@
1
- import { N as isCollectionArrayMethod, t as ALL_CAPABILITY_DEFINITIONS } from "./dist-BU-QPlE8.mjs";
2
- import { Ct as resolveAddonClass, I as createUdsLoggerWithControl, L as LocalChildClient, at as setWorkerNativeCapsChangeListener, bt as installManifestNativeDeps, i as createUdsAddonContext, nt as getWorkerNativeCapProvider, rt as getWorkerNativeCapSnapshot, st as validateProviderRegistrations, t as installManifestPythonDeps } from "./manifest-python-deps-D7-WBIg_.mjs";
1
+ import { Ct as resolveAddonClass, I as createUdsLoggerWithControl, L as LocalChildClient, at as setWorkerNativeCapsChangeListener, bt as installManifestNativeDeps, i as createUdsAddonContext, nt as getWorkerNativeCapProvider, rt as getWorkerNativeCapSnapshot, st as validateProviderRegistrations, t as installManifestPythonDeps } from "./manifest-python-deps-B30qVAuW.mjs";
3
2
  import { t as CustomActionRegistry } from "./custom-action-registry-F__gp_VX.mjs";
4
3
  import { register } from "node:module";
5
4
  import * as fs from "node:fs";
6
5
  import * as path$1 from "node:path";
7
- import { ReadinessRegistry, ReadinessTimeoutError, errMsg, normalizeAddonInitResult } from "@camstack/types/addon";
6
+ import { ReadinessRegistry, ReadinessTimeoutError, errMsg, isCollectionArrayMethodName, normalizeAddonInitResult } from "@camstack/types/addon";
8
7
  import { pathToFileURL } from "node:url";
9
8
  import * as v8 from "node:v8";
10
9
  //#region src/kernel/moleculer/worker-device-restore.ts
@@ -469,13 +468,6 @@ async function main() {
469
468
  */
470
469
  const allSingletonProviders = /* @__PURE__ */ new Map();
471
470
  /**
472
- * Cap-definition lookup for the dispatcher's collection-list-method guard.
473
- * Lets `child-cap-dispatch` reproduce the hub-side `concatCollection` skip:
474
- * a provider that doesn't implement a COLLECTION cap's array-returning method
475
- * contributes `[]` instead of throwing "method not found".
476
- */
477
- const capDefsByName = new Map(ALL_CAPABILITY_DEFINITIONS.map((def) => [def.name, def]));
478
- /**
479
471
  * Resolve a singleton provider for the dispatcher: exact (capName, addonId)
480
472
  * match when the hint names a hosted provider, else the cap's first
481
473
  * registered provider (an unmatched `addonId` is method DATA — e.g.
@@ -532,7 +524,7 @@ async function main() {
532
524
  dispatch: createChildCapDispatch({
533
525
  getSingletonProvider: (capName, addonId) => resolveSingletonProvider(capName, addonId),
534
526
  getDeviceProvider: (capName, deviceId) => getWorkerNativeCapProvider(capName, deviceId) ?? null,
535
- isCollectionListMethod: (capName, method) => isCollectionArrayMethod(capDefsByName.get(capName), method)
527
+ isCollectionListMethod: (capName, method) => isCollectionArrayMethodName(capName, method)
536
528
  })
537
529
  });
538
530
  udsChildClient.onAddonCall(createChildAddonCallDispatch({
@@ -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-3AzhkmeY.js");
6
+ const require_dist = require("../../dist-OQ1yU92D.js");
7
7
  const require_settle_sources = require("../../settle-sources-Bhsy57y-.js");
8
8
  let node_fs = require("node:fs");
9
9
  node_fs = require_chunk.__toESM(node_fs);
@@ -1,4 +1,4 @@
1
- import { Mt as EventCategory, ot as errMsg, p as addonPagesCapability, st as BaseAddon } from "../../dist-BU-QPlE8.mjs";
1
+ import { at as BaseAddon, it as errMsg, jt as EventCategory, p as addonPagesCapability } from "../../dist-DmQ6thmF.mjs";
2
2
  import { t as settleSourcesWithTimeout } from "../../settle-sources-CDtNC8ub.mjs";
3
3
  import * as fs from "node:fs";
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-3AzhkmeY.js");
6
+ const require_dist = require("../../dist-OQ1yU92D.js");
7
7
  const require_settle_sources = require("../../settle-sources-Bhsy57y-.js");
8
8
  let node_fs = require("node:fs");
9
9
  node_fs = require_chunk.__toESM(node_fs);
@@ -1,4 +1,4 @@
1
- import { Mt as EventCategory, h as addonWidgetsCapability, ot as errMsg, st as BaseAddon } from "../../dist-BU-QPlE8.mjs";
1
+ import { at as BaseAddon, h as addonWidgetsCapability, it as errMsg, jt as EventCategory } from "../../dist-DmQ6thmF.mjs";
2
2
  import { t as settleSourcesWithTimeout } from "../../settle-sources-CDtNC8ub.mjs";
3
3
  import * as fs from "node:fs";
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-3AzhkmeY.js");
6
+ const require_dist = require("../../dist-OQ1yU92D.js");
7
7
  //#region src/builtins/alerts/alerts.addon.ts
8
8
  var CATEGORY_MAPPINGS = {
9
9
  "addon.crashed": {
@@ -1,4 +1,4 @@
1
- import { Mt as EventCategory, bt as createEvent, g as alertsCapability, n as AlertSchema, ot as errMsg, st as BaseAddon } from "../../dist-BU-QPlE8.mjs";
1
+ import { at as BaseAddon, g as alertsCapability, it as errMsg, jt as EventCategory, n as AlertSchema, vt as createEvent } from "../../dist-DmQ6thmF.mjs";
2
2
  //#region src/builtins/alerts/alerts.addon.ts
3
3
  var CATEGORY_MAPPINGS = {
4
4
  "addon.crashed": {
@@ -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-3AzhkmeY.js");
6
+ const require_dist = require("../../dist-OQ1yU92D.js");
7
7
  let node_fs = require("node:fs");
8
8
  let node_fs$1 = require_chunk.__toESM(node_fs, 1);
9
9
  node_fs = require_chunk.__toESM(node_fs);
@@ -1,4 +1,4 @@
1
- import { Mt as EventCategory, st as BaseAddon, y as backupCapability } from "../../dist-BU-QPlE8.mjs";
1
+ import { at as BaseAddon, jt as EventCategory, y as backupCapability } from "../../dist-DmQ6thmF.mjs";
2
2
  import * as fs from "node:fs";
3
3
  import Kt from "node:fs";
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-3AzhkmeY.js");
6
+ const require_dist = require("../../dist-OQ1yU92D.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 { st as BaseAddon, z as logDestinationCapability } from "../../dist-BU-QPlE8.mjs";
1
+ import { at as BaseAddon, z as logDestinationCapability } from "../../dist-DmQ6thmF.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 = {
@@ -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-3AzhkmeY.js");
6
+ const require_dist = require("../../dist-OQ1yU92D.js");
7
7
  let _camstack_types_node = require("@camstack/types/node");
8
8
  let zod = require("zod");
9
9
  let node_crypto = require("node:crypto");
@@ -1,4 +1,4 @@
1
- import { C as deviceStatusCapability, D as enumerateSchemaFields, E as enumerateItemArrayFields, K as parseStreamParamsFormPatch, Mt as EventCategory, O as evaluateLinkExpression, S as deviceStateCapability, Tt as isDeviceConfigCap, W as normalizeUnit, Z as setByPath, _ as applyTransform, a as CAP_NAMES_WITH_STATUS, at as validateExpressionSource, b as buildStreamParamsConfigSchema, dt as DeviceFeature, ft as DeviceRole, gt as WELL_KNOWN_TAB_MAP, j as getByPath, jt as sleep, l as STREAM_PROFILE_META, o as DeviceStatusSchema, ot as errMsg, pt as DeviceType, rt as toExpressionValue, st as BaseAddon, t as ALL_CAPABILITY_DEFINITIONS, x as deviceManagerCapability } from "../../dist-BU-QPlE8.mjs";
1
+ import { At as sleep, C as deviceStatusCapability, Ct as isDeviceConfigCap, D as enumerateSchemaFields, E as enumerateItemArrayFields, G as parseStreamParamsFormPatch, O as evaluateLinkExpression, S as deviceStateCapability, U as normalizeUnit, Y as setByPath, _ as applyTransform, a as CAP_NAMES_WITH_STATUS, at as BaseAddon, b as buildStreamParamsConfigSchema, dt as DeviceType, it as errMsg, j as getByPath, jt as EventCategory, l as STREAM_PROFILE_META, lt as DeviceFeature, mt as WELL_KNOWN_TAB_MAP, o as DeviceStatusSchema, rt as validateExpressionSource, t as ALL_CAPABILITY_DEFINITIONS, tt as toExpressionValue, ut as DeviceRole, x as deviceManagerCapability } from "../../dist-DmQ6thmF.mjs";
2
2
  import { canonicalDeviceFingerprint } from "@camstack/types/node";
3
3
  import { z } from "zod";
4
4
  import { randomUUID } from "node:crypto";
@@ -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-3AzhkmeY.js");
6
+ const require_dist = require("../../dist-OQ1yU92D.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 { Mt as EventCategory, bt as createEvent, ot as errMsg, pt as DeviceType, st as BaseAddon, w as doorbellCapability } from "../../dist-BU-QPlE8.mjs";
1
+ import { at as BaseAddon, dt as DeviceType, it as errMsg, jt as EventCategory, vt as createEvent, w as doorbellCapability } from "../../dist-DmQ6thmF.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-3AzhkmeY.js");
6
+ const require_dist = require("../../dist-OQ1yU92D.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 { st as BaseAddon, z as logDestinationCapability } from "../../dist-BU-QPlE8.mjs";
1
+ import { at as BaseAddon, z as logDestinationCapability } from "../../dist-DmQ6thmF.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;
@@ -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-3AzhkmeY.js");
6
+ const require_dist = require("../../dist-OQ1yU92D.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 { f as UserRecordSchema, it as userManagementCapability, r as ApiKeyRecordSchema, st as BaseAddon, u as ScopedTokenSchema, v as authProviderCapability } from "../../dist-BU-QPlE8.mjs";
2
+ import { at as BaseAddon, f as UserRecordSchema, nt as userManagementCapability, r as ApiKeyRecordSchema, u as ScopedTokenSchema, v as authProviderCapability } from "../../dist-DmQ6thmF.mjs";
3
3
  import * as crypto$1 from "node:crypto";
4
4
  import { randomUUID } 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-3AzhkmeY.js");
3
+ const require_dist = require("../../dist-OQ1yU92D.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 { Mt as EventCategory, R as localNetworkCapability, st as BaseAddon } from "../../dist-BU-QPlE8.mjs";
1
+ import { R as localNetworkCapability, at as BaseAddon, jt as EventCategory } from "../../dist-DmQ6thmF.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-3AzhkmeY.js");
6
+ const require_dist = require("../../dist-OQ1yU92D.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
@@ -118,10 +118,32 @@ var LokiDestination = class {
118
118
  }
119
119
  async initialize(config) {
120
120
  this.config = config ?? null;
121
- if (!this.isActive()) return;
121
+ this.startTimerIfActive();
122
+ }
123
+ /**
124
+ * Re-apply configuration to an already-initialized destination after a
125
+ * settings change, without dropping the queued tail. Stops the current flush
126
+ * timer, swaps the config in, and starts a fresh timer only when the new
127
+ * config is active. This is what makes the addon's "enable without a restart"
128
+ * contract real: `initialize()` starts a timer, so calling it twice would leak
129
+ * the first one — `reconfigure()` clears it first.
130
+ */
131
+ async reconfigure(config) {
132
+ this.stopTimer();
133
+ this.config = config;
134
+ this.startTimerIfActive();
135
+ }
136
+ stopTimer() {
137
+ if (this.timer !== void 0) {
138
+ this.clearIntervalFn(this.timer);
139
+ this.timer = void 0;
140
+ }
141
+ }
142
+ startTimerIfActive() {
143
+ if (!this.isActive() || this.config === null) return;
122
144
  this.timer = this.setIntervalFn(() => {
123
145
  this.flush();
124
- }, Math.max(250, config?.batchIntervalMs ?? 5e3));
146
+ }, Math.max(250, this.config.batchIntervalMs));
125
147
  const timer = this.timer;
126
148
  if (typeof timer === "object" && timer !== null && "unref" in timer) timer.unref();
127
149
  }
@@ -254,10 +276,7 @@ var LokiDestination = class {
254
276
  return [];
255
277
  }
256
278
  async shutdown() {
257
- if (this.timer !== void 0) {
258
- this.clearIntervalFn(this.timer);
259
- this.timer = void 0;
260
- }
279
+ this.stopTimer();
261
280
  await this.flush();
262
281
  this.config = null;
263
282
  }
@@ -296,6 +315,17 @@ var LokiLoggingAddon = class extends require_dist.BaseAddon {
296
315
  this.destination = null;
297
316
  }
298
317
  /**
318
+ * React to a settings change (enable/disable, URL, level, batching) without a
319
+ * restart — the contract this addon advertises. `BaseAddon` has already
320
+ * reloaded `this.config` by the time this runs; re-apply it to the live
321
+ * destination so toggling `enabled` on actually starts pushing (and off stops
322
+ * it). Without this the destination keeps its boot-time config forever.
323
+ */
324
+ async onConfigChanged() {
325
+ await this.destination?.reconfigure(this.destinationConfig());
326
+ this.ctx.logger.info(this.config.enabled && this.config.url.length > 0 ? `Loki logging reconfigured → ${this.config.url}` : "Loki logging now inactive (disabled or no URL)");
327
+ }
328
+ /**
299
329
  * `node` is a Loki LABEL, so it must be the node's real identity and must not
300
330
  * be operator-editable — a typo would fork the stream and split a node's history
301
331
  * in two. `kernel.localNodeId` is the Moleculer node id (`'hub'` on the hub, the
@@ -1,4 +1,4 @@
1
- import { st as BaseAddon, z as logDestinationCapability } from "../../dist-BU-QPlE8.mjs";
1
+ import { at as BaseAddon, z as logDestinationCapability } from "../../dist-DmQ6thmF.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
@@ -113,10 +113,32 @@ var LokiDestination = class {
113
113
  }
114
114
  async initialize(config) {
115
115
  this.config = config ?? null;
116
- if (!this.isActive()) return;
116
+ this.startTimerIfActive();
117
+ }
118
+ /**
119
+ * Re-apply configuration to an already-initialized destination after a
120
+ * settings change, without dropping the queued tail. Stops the current flush
121
+ * timer, swaps the config in, and starts a fresh timer only when the new
122
+ * config is active. This is what makes the addon's "enable without a restart"
123
+ * contract real: `initialize()` starts a timer, so calling it twice would leak
124
+ * the first one — `reconfigure()` clears it first.
125
+ */
126
+ async reconfigure(config) {
127
+ this.stopTimer();
128
+ this.config = config;
129
+ this.startTimerIfActive();
130
+ }
131
+ stopTimer() {
132
+ if (this.timer !== void 0) {
133
+ this.clearIntervalFn(this.timer);
134
+ this.timer = void 0;
135
+ }
136
+ }
137
+ startTimerIfActive() {
138
+ if (!this.isActive() || this.config === null) return;
117
139
  this.timer = this.setIntervalFn(() => {
118
140
  this.flush();
119
- }, Math.max(250, config?.batchIntervalMs ?? 5e3));
141
+ }, Math.max(250, this.config.batchIntervalMs));
120
142
  const timer = this.timer;
121
143
  if (typeof timer === "object" && timer !== null && "unref" in timer) timer.unref();
122
144
  }
@@ -249,10 +271,7 @@ var LokiDestination = class {
249
271
  return [];
250
272
  }
251
273
  async shutdown() {
252
- if (this.timer !== void 0) {
253
- this.clearIntervalFn(this.timer);
254
- this.timer = void 0;
255
- }
274
+ this.stopTimer();
256
275
  await this.flush();
257
276
  this.config = null;
258
277
  }
@@ -291,6 +310,17 @@ var LokiLoggingAddon = class extends BaseAddon {
291
310
  this.destination = null;
292
311
  }
293
312
  /**
313
+ * React to a settings change (enable/disable, URL, level, batching) without a
314
+ * restart — the contract this addon advertises. `BaseAddon` has already
315
+ * reloaded `this.config` by the time this runs; re-apply it to the live
316
+ * destination so toggling `enabled` on actually starts pushing (and off stops
317
+ * it). Without this the destination keeps its boot-time config forever.
318
+ */
319
+ async onConfigChanged() {
320
+ await this.destination?.reconfigure(this.destinationConfig());
321
+ this.ctx.logger.info(this.config.enabled && this.config.url.length > 0 ? `Loki logging reconfigured → ${this.config.url}` : "Loki logging now inactive (disabled or no URL)");
322
+ }
323
+ /**
294
324
  * `node` is a Loki LABEL, so it must be the node's real identity and must not
295
325
  * be operator-editable — a typo would fork the stream and split a node's history
296
326
  * in two. `kernel.localNodeId` is the Moleculer node id (`'hub'` on the hub, the
@@ -60,6 +60,17 @@ export declare class LokiDestination implements ILogDestination {
60
60
  private readonly clearIntervalFn;
61
61
  constructor(deps?: LokiDestinationDeps);
62
62
  initialize(config?: LokiConfig): Promise<void>;
63
+ /**
64
+ * Re-apply configuration to an already-initialized destination after a
65
+ * settings change, without dropping the queued tail. Stops the current flush
66
+ * timer, swaps the config in, and starts a fresh timer only when the new
67
+ * config is active. This is what makes the addon's "enable without a restart"
68
+ * contract real: `initialize()` starts a timer, so calling it twice would leak
69
+ * the first one — `reconfigure()` clears it first.
70
+ */
71
+ reconfigure(config: LokiConfig): Promise<void>;
72
+ private stopTimer;
73
+ private startTimerIfActive;
63
74
  /** Enabled AND pointed somewhere. An enabled destination with no URL is inert. */
64
75
  private isActive;
65
76
  write(entry: LogEntry): void;
@@ -18,6 +18,14 @@ export declare class LokiLoggingAddon extends BaseAddon<LokiAddonConfig> {
18
18
  constructor();
19
19
  protected onInitialize(): Promise<ProviderRegistration[]>;
20
20
  protected onShutdown(): Promise<void>;
21
+ /**
22
+ * React to a settings change (enable/disable, URL, level, batching) without a
23
+ * restart — the contract this addon advertises. `BaseAddon` has already
24
+ * reloaded `this.config` by the time this runs; re-apply it to the live
25
+ * destination so toggling `enabled` on actually starts pushing (and off stops
26
+ * it). Without this the destination keeps its boot-time config forever.
27
+ */
28
+ protected onConfigChanged(): Promise<void>;
21
29
  /**
22
30
  * `node` is a Loki LABEL, so it must be the node's real identity and must not
23
31
  * be operator-editable — a typo would fork the stream and split a node's history
@@ -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-3AzhkmeY.js");
6
+ const require_dist = require("../../dist-OQ1yU92D.js");
7
7
  let node_fs = require("node:fs");
8
8
  node_fs = require_chunk.__toESM(node_fs);
9
9
  let node_child_process = require("node:child_process");
@@ -1,4 +1,4 @@
1
- import { H as metricsProviderCapability, Mt as EventCategory, bt as createEvent, st as BaseAddon } from "../../dist-BU-QPlE8.mjs";
1
+ import { H as metricsProviderCapability, at as BaseAddon, jt as EventCategory, vt as createEvent } from "../../dist-DmQ6thmF.mjs";
2
2
  import * as fs from "node:fs";
3
3
  import { execFile, execFileSync } from "node:child_process";
4
4
  import { promisify } from "node:util";
@@ -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-3AzhkmeY.js");
6
+ const require_dist = require("../../dist-OQ1yU92D.js");
7
7
  let node_fs = require("node:fs");
8
8
  node_fs = require_chunk.__toESM(node_fs);
9
9
  let node_child_process = require("node:child_process");
@@ -1,5 +1,5 @@
1
1
  import { o as __toESM } from "../../chunk-CNf5ZN-e.mjs";
2
- import { Mt as EventCategory, St as emitReadiness, T as enumerateInferenceDevices, X as scoreRuntimes, ot as errMsg, q as platformProbeCapability, st as BaseAddon } from "../../dist-BU-QPlE8.mjs";
2
+ import { J as scoreRuntimes, K as platformProbeCapability, T as enumerateInferenceDevices, at as BaseAddon, bt as emitReadiness, it as errMsg, jt as EventCategory } from "../../dist-DmQ6thmF.mjs";
3
3
  import * as fs from "node:fs";
4
4
  import { execFile } from "node:child_process";
5
5
  import { promisify } from "node:util";
@@ -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-3AzhkmeY.js");
6
+ const require_dist = require("../../dist-OQ1yU92D.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 { Mt as EventCategory, st as BaseAddon } from "../../dist-BU-QPlE8.mjs";
1
+ import { at as BaseAddon, jt as EventCategory } from "../../dist-DmQ6thmF.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
  require("../../chunk-Cek0wNdY.js");
6
- const require_dist = require("../../dist-3AzhkmeY.js");
6
+ const require_dist = require("../../dist-OQ1yU92D.js");
7
7
  let node_child_process = require("node:child_process");
8
8
  //#region src/builtins/snapshot/snapshot-coalescing.ts
9
9
  /**
@@ -1,4 +1,4 @@
1
- import { $ as snapshotCapability, U as nodePin, dt as DeviceFeature, i as BatteryStatusSchema, nt as streamQualityLabel, ot as errMsg, pt as DeviceType, st as BaseAddon } from "../../dist-BU-QPlE8.mjs";
1
+ import { Z as snapshotCapability, at as BaseAddon, dt as DeviceType, et as streamQualityLabel, i as BatteryStatusSchema, it as errMsg, lt as DeviceFeature, wt as nodePin } from "../../dist-DmQ6thmF.mjs";
2
2
  import { execFile } from "node:child_process";
3
3
  //#region src/builtins/snapshot/snapshot-coalescing.ts
4
4
  /**
@@ -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-3AzhkmeY.js");
6
+ const require_dist = require("../../dist-OQ1yU92D.js");
7
7
  let node_fs = require("node:fs");
8
8
  node_fs = require_chunk.__toESM(node_fs);
9
9
  let node_path = require("node:path");
@@ -1,4 +1,4 @@
1
- import { A as filesystemBrowseCapability, st as BaseAddon, tt as storageProviderCapability } from "../../dist-BU-QPlE8.mjs";
1
+ import { $ as storageProviderCapability, A as filesystemBrowseCapability, at as BaseAddon } from "../../dist-DmQ6thmF.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-3AzhkmeY.js");
6
+ const require_dist = require("../../dist-OQ1yU92D.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 { Dt as parseJsonUnknown, Q as settingsStoreCapability, _t as asJsonObject, c as RUNTIME_DEFAULTS, ot as errMsg, st as BaseAddon } from "../../dist-BU-QPlE8.mjs";
1
+ import { Et as parseJsonUnknown, X as settingsStoreCapability, at as BaseAddon, c as RUNTIME_DEFAULTS, ht as asJsonObject, it as errMsg } from "../../dist-DmQ6thmF.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-3AzhkmeY.js");
6
+ const require_dist = require("../../dist-OQ1yU92D.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 { Et as parseJsonObject, d as StorageLocationTypeSchema, et as storageCapability, st as BaseAddon } from "../../dist-BU-QPlE8.mjs";
1
+ import { Q as storageCapability, Tt as parseJsonObject, at as BaseAddon, d as StorageLocationTypeSchema } from "../../dist-DmQ6thmF.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-3AzhkmeY.js");
6
+ const require_dist = require("../../dist-OQ1yU92D.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 { ot as errMsg, st as BaseAddon, wt as hydrateSchema } from "../../dist-BU-QPlE8.mjs";
1
+ import { St as hydrateSchema, at as BaseAddon, it as errMsg } from "../../dist-DmQ6thmF.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-3AzhkmeY.js");
6
+ const require_dist = require("../../dist-OQ1yU92D.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 { st as BaseAddon, z as logDestinationCapability } from "../../dist-BU-QPlE8.mjs";
1
+ import { at as BaseAddon, z as logDestinationCapability } from "../../dist-DmQ6thmF.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";
@@ -2214,6 +2214,36 @@ function emitDownForOwnedCaps(registry, owned) {
2214
2214
  */
2215
2215
  var DATAPLANE_SECRET_HEADER = "x-camstack-dataplane-secret";
2216
2216
  /**
2217
+ * Per-call node pinning for `ctx.api` capability calls.
2218
+ *
2219
+ * A capability call normally resolves to its DEFAULT provider — a `singleton`
2220
+ * cap resolves to the hub, a device-scoped cap to the device's owning node. To
2221
+ * query a SPECIFIC node's provider instead (e.g. a remote agent's own
2222
+ * in-process `platform-probe` hardware, which the hub cannot probe), pin the
2223
+ * call to that node.
2224
+ *
2225
+ * The nodeId rides OUT-OF-BAND in the tRPC call context (NOT in the validated
2226
+ * method args), so capability method signatures stay `nodeId`-free — node
2227
+ * targeting is a property of the CALL, not of the method. The transport lifts
2228
+ * it from `op.context` onto the `CapCallInput.nodeId` field (`ipcParentLink`),
2229
+ * and the hub parent's `onUnownedCall` passes it to the `CapRouteResolver`,
2230
+ * which classifies a pinned agent node as `agent-child-forward`
2231
+ * (`$agent-cap-fwd.forward` → the agent's in-process provider).
2232
+ *
2233
+ * Usage at a call site:
2234
+ *
2235
+ * await api.platformProbe.getCapabilities.query(undefined, nodePin(nodeId))
2236
+ */
2237
+ /** tRPC `op.context` key carrying a per-call node pin. */
2238
+ var CAP_NODE_PIN_CONTEXT_KEY = "__camstackNodePin";
2239
+ /**
2240
+ * Build the tRPC request options that pin a single capability call to `nodeId`.
2241
+ * Pass as the second argument to `.query(input, …)` / `.mutate(input, …)`.
2242
+ */
2243
+ function nodePin(nodeId) {
2244
+ return { context: { [CAP_NODE_PIN_CONTEXT_KEY]: nodeId } };
2245
+ }
2246
+ /**
2217
2247
  * Type-safe JSON parsing helpers.
2218
2248
  *
2219
2249
  * `JSON.parse` is typed as `any` in lib.es5.d.ts, which triggers
@@ -3731,45 +3761,6 @@ var RUNTIME_DEFAULTS = {
3731
3761
  "ffmpeg.threadCount": 0,
3732
3762
  "auth.tokenExpiry": "7d"
3733
3763
  };
3734
- /**
3735
- * Per-call node pinning for `ctx.api` capability calls.
3736
- *
3737
- * A capability call normally resolves to its DEFAULT provider — a `singleton`
3738
- * cap resolves to the hub, a device-scoped cap to the device's owning node. To
3739
- * query a SPECIFIC node's provider instead (e.g. a remote agent's own
3740
- * in-process `platform-probe` hardware, which the hub cannot probe), pin the
3741
- * call to that node.
3742
- *
3743
- * The nodeId rides OUT-OF-BAND in the tRPC call context (NOT in the validated
3744
- * method args), so capability method signatures stay `nodeId`-free — node
3745
- * targeting is a property of the CALL, not of the method. The transport lifts
3746
- * it from `op.context` onto the `CapCallInput.nodeId` field (`ipcParentLink`),
3747
- * and the hub parent's `onUnownedCall` passes it to the `CapRouteResolver`,
3748
- * which classifies a pinned agent node as `agent-child-forward`
3749
- * (`$agent-cap-fwd.forward` → the agent's in-process provider).
3750
- *
3751
- * Usage at a call site:
3752
- *
3753
- * await api.platformProbe.getCapabilities.query(undefined, nodePin(nodeId))
3754
- */
3755
- /** tRPC `op.context` key carrying a per-call node pin. */
3756
- var CAP_NODE_PIN_CONTEXT_KEY = "__camstackNodePin";
3757
- /**
3758
- * Build the tRPC request options that pin a single capability call to `nodeId`.
3759
- * Pass as the second argument to `.query(input, …)` / `.mutate(input, …)`.
3760
- */
3761
- function nodePin(nodeId) {
3762
- return { context: { [CAP_NODE_PIN_CONTEXT_KEY]: nodeId } };
3763
- }
3764
- /**
3765
- * Read a per-call node pin out of a tRPC `op.context` (transport side).
3766
- * Returns the pinned nodeId, or `undefined` when no pin is present.
3767
- */
3768
- function readNodePin(context) {
3769
- if (context === null || typeof context !== "object") return void 0;
3770
- const value = Reflect.get(context, CAP_NODE_PIN_CONTEXT_KEY);
3771
- return typeof value === "string" ? value : void 0;
3772
- }
3773
3764
  var COCO_TO_MACRO = {
3774
3765
  mapping: {
3775
3766
  person: "person",
@@ -28405,4 +28396,4 @@ function enumerateInferenceDevices(hw) {
28405
28396
  return out;
28406
28397
  }
28407
28398
  //#endregion
28408
- 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 };
28399
+ export { storageProviderCapability as $, filesystemBrowseCapability as A, sleep as At, logLevelAtMost as B, deviceStatusCapability as C, isDeviceConfigCap as Ct, enumerateSchemaFields as D, readinessKey as Dt, enumerateItemArrayFields as E, parseJsonUnknown as Et, isVoidInput as F, parseStreamParamsFormPatch as G, metricsProviderCapability as H, kebabToCamel as I, scoreRuntimes as J, platformProbeCapability as K, lifecycleJobSchema as L, isArrayOutputSchema as M, isCollectionArrayMethod as N, evaluateLinkExpression as O, resolveCapMount as Ot, isObjectInput as P, storageCapability as Q, localNetworkCapability as R, deviceStateCapability as S, hydrateSchema as St, enumerateInferenceDevices as T, parseJsonObject as Tt, normalizeUnit as U, looseSchema as V, objectInputDeclaresAddonId as W, settingsStoreCapability as X, setByPath as Y, snapshotCapability as Z, applyTransform as _, asString as _t, CAP_NAMES_WITH_STATUS as a, BaseAddon as at, buildStreamParamsConfigSchema as b, emitReadiness as bt, RUNTIME_DEFAULTS as c, DEVICE_STATUS_METHOD as ct, StorageLocationTypeSchema as d, DeviceType as dt, streamQualityLabel as et, UserRecordSchema as f, ReadinessRegistry as ft, alertsCapability as g, asNumber as gt, addonWidgetsCapability as h, asJsonObject as ht, BatteryStatusSchema as i, errMsg as it, getByPath as j, EventCategory as jt, extractNestedAddonId as k, scopeKey as kt, STREAM_PROFILE_META as l, DeviceFeature as lt, addonSettingsCapability as m, WELL_KNOWN_TAB_MAP as mt, AlertSchema as n, userManagementCapability as nt, DeviceStatusSchema as o, DATAPLANE_SECRET_HEADER as ot, addonPagesCapability as p, ReadinessTimeoutError as pt, procedureAuthKey as q, ApiKeyRecordSchema as r, validateExpressionSource as rt, METHOD_ACCESS_MAP as s, DEVICE_SETTINGS_CONTRIBUTION_METHODS as st, ALL_CAPABILITY_DEFINITIONS as t, toExpressionValue as tt, ScopedTokenSchema as u, DeviceRole as ut, authProviderCapability as v, createEvent as vt, doorbellCapability as w, nodePin as wt, deviceManagerCapability as x, expandCapMethods as xt, backupCapability as y, emitDownForOwnedCaps as yt, logDestinationCapability as z };
@@ -2214,6 +2214,36 @@ function emitDownForOwnedCaps(registry, owned) {
2214
2214
  */
2215
2215
  var DATAPLANE_SECRET_HEADER = "x-camstack-dataplane-secret";
2216
2216
  /**
2217
+ * Per-call node pinning for `ctx.api` capability calls.
2218
+ *
2219
+ * A capability call normally resolves to its DEFAULT provider — a `singleton`
2220
+ * cap resolves to the hub, a device-scoped cap to the device's owning node. To
2221
+ * query a SPECIFIC node's provider instead (e.g. a remote agent's own
2222
+ * in-process `platform-probe` hardware, which the hub cannot probe), pin the
2223
+ * call to that node.
2224
+ *
2225
+ * The nodeId rides OUT-OF-BAND in the tRPC call context (NOT in the validated
2226
+ * method args), so capability method signatures stay `nodeId`-free — node
2227
+ * targeting is a property of the CALL, not of the method. The transport lifts
2228
+ * it from `op.context` onto the `CapCallInput.nodeId` field (`ipcParentLink`),
2229
+ * and the hub parent's `onUnownedCall` passes it to the `CapRouteResolver`,
2230
+ * which classifies a pinned agent node as `agent-child-forward`
2231
+ * (`$agent-cap-fwd.forward` → the agent's in-process provider).
2232
+ *
2233
+ * Usage at a call site:
2234
+ *
2235
+ * await api.platformProbe.getCapabilities.query(undefined, nodePin(nodeId))
2236
+ */
2237
+ /** tRPC `op.context` key carrying a per-call node pin. */
2238
+ var CAP_NODE_PIN_CONTEXT_KEY = "__camstackNodePin";
2239
+ /**
2240
+ * Build the tRPC request options that pin a single capability call to `nodeId`.
2241
+ * Pass as the second argument to `.query(input, …)` / `.mutate(input, …)`.
2242
+ */
2243
+ function nodePin(nodeId) {
2244
+ return { context: { [CAP_NODE_PIN_CONTEXT_KEY]: nodeId } };
2245
+ }
2246
+ /**
2217
2247
  * Type-safe JSON parsing helpers.
2218
2248
  *
2219
2249
  * `JSON.parse` is typed as `any` in lib.es5.d.ts, which triggers
@@ -3731,45 +3761,6 @@ var RUNTIME_DEFAULTS = {
3731
3761
  "ffmpeg.threadCount": 0,
3732
3762
  "auth.tokenExpiry": "7d"
3733
3763
  };
3734
- /**
3735
- * Per-call node pinning for `ctx.api` capability calls.
3736
- *
3737
- * A capability call normally resolves to its DEFAULT provider — a `singleton`
3738
- * cap resolves to the hub, a device-scoped cap to the device's owning node. To
3739
- * query a SPECIFIC node's provider instead (e.g. a remote agent's own
3740
- * in-process `platform-probe` hardware, which the hub cannot probe), pin the
3741
- * call to that node.
3742
- *
3743
- * The nodeId rides OUT-OF-BAND in the tRPC call context (NOT in the validated
3744
- * method args), so capability method signatures stay `nodeId`-free — node
3745
- * targeting is a property of the CALL, not of the method. The transport lifts
3746
- * it from `op.context` onto the `CapCallInput.nodeId` field (`ipcParentLink`),
3747
- * and the hub parent's `onUnownedCall` passes it to the `CapRouteResolver`,
3748
- * which classifies a pinned agent node as `agent-child-forward`
3749
- * (`$agent-cap-fwd.forward` → the agent's in-process provider).
3750
- *
3751
- * Usage at a call site:
3752
- *
3753
- * await api.platformProbe.getCapabilities.query(undefined, nodePin(nodeId))
3754
- */
3755
- /** tRPC `op.context` key carrying a per-call node pin. */
3756
- var CAP_NODE_PIN_CONTEXT_KEY = "__camstackNodePin";
3757
- /**
3758
- * Build the tRPC request options that pin a single capability call to `nodeId`.
3759
- * Pass as the second argument to `.query(input, …)` / `.mutate(input, …)`.
3760
- */
3761
- function nodePin(nodeId) {
3762
- return { context: { [CAP_NODE_PIN_CONTEXT_KEY]: nodeId } };
3763
- }
3764
- /**
3765
- * Read a per-call node pin out of a tRPC `op.context` (transport side).
3766
- * Returns the pinned nodeId, or `undefined` when no pin is present.
3767
- */
3768
- function readNodePin(context) {
3769
- if (context === null || typeof context !== "object") return void 0;
3770
- const value = Reflect.get(context, CAP_NODE_PIN_CONTEXT_KEY);
3771
- return typeof value === "string" ? value : void 0;
3772
- }
3773
3764
  var COCO_TO_MACRO = {
3774
3765
  mapping: {
3775
3766
  person: "person",
@@ -28831,12 +28822,6 @@ Object.defineProperty(exports, "procedureAuthKey", {
28831
28822
  return procedureAuthKey;
28832
28823
  }
28833
28824
  });
28834
- Object.defineProperty(exports, "readNodePin", {
28835
- enumerable: true,
28836
- get: function() {
28837
- return readNodePin;
28838
- }
28839
- });
28840
28825
  Object.defineProperty(exports, "readinessKey", {
28841
28826
  enumerable: true,
28842
28827
  get: function() {
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-3AzhkmeY.js");
3
+ const require_dist = require("./dist-OQ1yU92D.js");
4
4
  const require_model_download_service = require("./model-download-service-hf0ookyy.js");
5
- const require_manifest_python_deps = require("./manifest-python-deps-DRN3x53E.js");
5
+ const require_manifest_python_deps = require("./manifest-python-deps-CnRW2Utv.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");
package/dist/index.mjs CHANGED
@@ -1,7 +1,7 @@
1
1
  import { a as __toCommonJS, i as __require, n as __esmMin, o as __toESM$1, r as __exportAll, t as __commonJSMin$1 } from "./chunk-CNf5ZN-e.mjs";
2
- 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-BU-QPlE8.mjs";
2
+ import { B as logLevelAtMost, 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, Tt as parseJsonObject, V as looseSchema, W as objectInputDeclaresAddonId, _t as asString$1, c as RUNTIME_DEFAULTS, ct as DEVICE_STATUS_METHOD, ft as ReadinessRegistry, gt as asNumber, ht as asJsonObject$1, it as errMsg$1, jt as EventCategory$1, k as extractNestedAddonId, kt as scopeKey, m as addonSettingsCapability, ot as DATAPLANE_SECRET_HEADER$1, pt as ReadinessTimeoutError, q as procedureAuthKey, s as METHOD_ACCESS_MAP, st as DEVICE_SETTINGS_CONTRIBUTION_METHODS, t as ALL_CAPABILITY_DEFINITIONS, vt as createEvent, xt as expandCapMethods, yt as emitDownForOwnedCaps } from "./dist-DmQ6thmF.mjs";
3
3
  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";
4
- 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-D7-WBIg_.mjs";
4
+ 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-B30qVAuW.mjs";
5
5
  import { n as getSinglePidStats, t as getPidStats } from "./resource-monitor-BkP504Vq.mjs";
6
6
  import { FilesystemStorageAddon, t as FilesystemStorageProvider } from "./builtins/sqlite-storage/filesystem-storage.addon.mjs";
7
7
  import { SqliteSettingsAddon, t as SqliteSettingsBackend } from "./builtins/sqlite-storage/sqlite-settings.addon.mjs";
@@ -1,4 +1,3 @@
1
- import { Y as readNodePin } from "./dist-BU-QPlE8.mjs";
2
1
  import { ensureBinary, ensureFfmpeg, ensurePython, installPythonPackages, installPythonRequirements } from "@camstack/types/node";
3
2
  import { createServer } from "node:http";
4
3
  import * as fs from "node:fs";
@@ -6,7 +5,7 @@ import * as path$1 from "node:path";
6
5
  import { isAbsolute, join } from "node:path";
7
6
  import * as crypto$1 from "node:crypto";
8
7
  import { randomBytes, randomUUID } from "node:crypto";
9
- import { DATAPLANE_SECRET_HEADER, DeviceType, DisposerChain, EventCategory, ReadinessRegistry, asJsonObject, asString, createDeviceProxy, deviceOpsCapability, emitReadiness, errMsg, expandCapMethods, scopeKey, sleep } from "@camstack/types/addon";
8
+ import { DATAPLANE_SECRET_HEADER, DeviceType, DisposerChain, EventCategory, ReadinessRegistry, asJsonObject, asString, createDeviceProxy, deviceOpsCapability, emitReadiness, errMsg, expandCapMethods, readNodePin, scopeKey, sleep } from "@camstack/types/addon";
10
9
  import { execFile } from "node:child_process";
11
10
  import { promisify } from "node:util";
12
11
  import * as os from "node:os";
@@ -1,5 +1,4 @@
1
1
  const require_chunk = require("./chunk-Cek0wNdY.js");
2
- const require_dist = require("./dist-3AzhkmeY.js");
3
2
  let _camstack_types_node = require("@camstack/types/node");
4
3
  let node_http = require("node:http");
5
4
  let node_fs = require("node:fs");
@@ -5419,7 +5418,7 @@ function localProviderLink(resolver, observerOpts) {
5419
5418
  const parsed = parsePath(op.path);
5420
5419
  if (!parsed) return next(op);
5421
5420
  if (localBase !== void 0) {
5422
- const pinnedNodeId = require_dist.readNodePin(op.context);
5421
+ const pinnedNodeId = (0, _camstack_types_addon.readNodePin)(op.context);
5423
5422
  if (pinnedNodeId !== void 0 && pinnedNodeId !== localBase) return next(op);
5424
5423
  }
5425
5424
  const provider = resolver.getByName(parsed.capName);
@@ -5788,7 +5787,7 @@ function ipcParentLink(getCallOut) {
5788
5787
  const input = op.input;
5789
5788
  const inputObj = input && typeof input === "object" && !Array.isArray(input) ? input : null;
5790
5789
  const deviceId = inputObj && typeof Reflect.get(inputObj, "deviceId") === "number" ? Reflect.get(inputObj, "deviceId") : void 0;
5791
- const pinnedNodeId = require_dist.readNodePin(op.context);
5790
+ const pinnedNodeId = (0, _camstack_types_addon.readNodePin)(op.context);
5792
5791
  const capCallInput = {
5793
5792
  capName: parsed.capName,
5794
5793
  method: parsed.method,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@camstack/system",
3
- "version": "1.2.16",
3
+ "version": "1.2.18",
4
4
  "description": "Core addon for CamStack — builtins, pipeline, process management, auth, logging, events",
5
5
  "keywords": [
6
6
  "camstack",