@camstack/system 1.2.22 → 1.2.24

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 (62) hide show
  1. package/dist/addon-runner.js +1 -1
  2. package/dist/addon-runner.mjs +1 -1
  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.d.ts +0 -9
  10. package/dist/builtins/backup-orchestrator/backup-orchestrator.addon.js +1 -40
  11. package/dist/builtins/backup-orchestrator/backup-orchestrator.addon.mjs +1 -40
  12. package/dist/builtins/console-logging/index.js +1 -1
  13. package/dist/builtins/console-logging/index.mjs +1 -1
  14. package/dist/builtins/device-manager/device-manager.addon.js +1 -1
  15. package/dist/builtins/device-manager/device-manager.addon.mjs +1 -1
  16. package/dist/builtins/doorbell/virtual-doorbell.addon.js +1 -1
  17. package/dist/builtins/doorbell/virtual-doorbell.addon.mjs +1 -1
  18. package/dist/builtins/hub-forwarder/index.js +1 -1
  19. package/dist/builtins/hub-forwarder/index.mjs +1 -1
  20. package/dist/builtins/local-auth/local-auth.addon.js +1 -1
  21. package/dist/builtins/local-auth/local-auth.addon.mjs +1 -1
  22. package/dist/builtins/local-network/local-network.addon.d.ts +16 -0
  23. package/dist/builtins/local-network/local-network.addon.js +30 -2
  24. package/dist/builtins/local-network/local-network.addon.mjs +30 -2
  25. package/dist/builtins/loki-logging/index.js +34 -12
  26. package/dist/builtins/loki-logging/index.mjs +34 -12
  27. package/dist/builtins/loki-logging/loki-logging.addon.d.ts +19 -0
  28. package/dist/builtins/native-metrics/native-metrics.addon.js +1 -1
  29. package/dist/builtins/native-metrics/native-metrics.addon.mjs +1 -1
  30. package/dist/builtins/platform-probe/index.js +1 -1
  31. package/dist/builtins/platform-probe/index.mjs +1 -1
  32. package/dist/builtins/remote-access-orchestrator/remote-access-orchestrator.addon.js +1 -1
  33. package/dist/builtins/remote-access-orchestrator/remote-access-orchestrator.addon.mjs +1 -1
  34. package/dist/builtins/snapshot/index.js +1 -1
  35. package/dist/builtins/snapshot/index.mjs +1 -1
  36. package/dist/builtins/sqlite-storage/filesystem-storage.addon.js +1 -1
  37. package/dist/builtins/sqlite-storage/filesystem-storage.addon.mjs +1 -1
  38. package/dist/builtins/sqlite-storage/sqlite-settings.addon.js +1 -1
  39. package/dist/builtins/sqlite-storage/sqlite-settings.addon.mjs +1 -1
  40. package/dist/builtins/storage-orchestrator/storage-orchestrator.addon.d.ts +7 -0
  41. package/dist/builtins/storage-orchestrator/storage-orchestrator.addon.js +108 -4
  42. package/dist/builtins/storage-orchestrator/storage-orchestrator.addon.mjs +108 -4
  43. package/dist/builtins/storage-orchestrator/storage-orchestrator.service.d.ts +11 -1
  44. package/dist/builtins/storage-orchestrator/storage-pressure-manager.d.ts +5 -0
  45. package/dist/builtins/system-config/system-config.addon.js +1 -1
  46. package/dist/builtins/system-config/system-config.addon.mjs +1 -1
  47. package/dist/builtins/winston-logging/index.js +1 -1
  48. package/dist/builtins/winston-logging/index.mjs +1 -1
  49. package/dist/{dist-C9_XdXl5.mjs → dist-CIek6F9X.mjs} +436 -72
  50. package/dist/{dist-j49ewCPY.js → dist-CS0pdC8l.js} +436 -72
  51. package/dist/index.js +58 -8
  52. package/dist/index.mjs +58 -8
  53. package/dist/kernel/capability-registry.d.ts +9 -0
  54. package/dist/kernel/transport/local-child-registry.d.ts +38 -0
  55. package/dist/kernel/transport/local-transport.d.ts +11 -1
  56. package/dist/kernel/transport/parent-unowned-call.d.ts +22 -0
  57. package/dist/kernel/transport/socket-channel.d.ts +28 -1
  58. package/dist/logging/log-manager.d.ts +32 -1
  59. package/dist/logging/partitioned-log-buffer.d.ts +15 -3
  60. package/dist/{manifest-python-deps-CnRW2Utv.js → manifest-python-deps-BbOZZbVt.js} +56 -12
  61. package/dist/{manifest-python-deps-B30qVAuW.mjs → manifest-python-deps-C9qhvMUi.mjs} +57 -13
  62. package/package.json +1 -1
@@ -5,7 +5,7 @@ import * as path$1 from "node:path";
5
5
  import { isAbsolute, join } from "node:path";
6
6
  import * as crypto$1 from "node:crypto";
7
7
  import { randomBytes, randomUUID } from "node:crypto";
8
- import { DATAPLANE_SECRET_HEADER, DeviceType, DisposerChain, EventCategory, ReadinessRegistry, asJsonObject, asString, createDeviceProxy, deviceOpsCapability, emitReadiness, errMsg, expandCapMethods, readNodePin, 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, withCapInputDefaults } from "@camstack/types/addon";
9
9
  import { execFile } from "node:child_process";
10
10
  import { promisify } from "node:util";
11
11
  import * as os from "node:os";
@@ -3524,8 +3524,6 @@ function localEndpointPath(nodeId) {
3524
3524
  if (process.platform === "win32") return `\\\\.\\pipe\\camstack-${safe}`;
3525
3525
  return join(tmpdir(), `camstack-${safe}.sock`);
3526
3526
  }
3527
- //#endregion
3528
- //#region src/kernel/transport/socket-channel.ts
3529
3527
  var SocketChannel = class {
3530
3528
  socket;
3531
3529
  nextId = 1;
@@ -3544,13 +3542,34 @@ var SocketChannel = class {
3544
3542
  socket.on("close", () => this.handleClose());
3545
3543
  socket.on("error", () => {});
3546
3544
  }
3547
- request(body) {
3545
+ /**
3546
+ * Send a request and wait for the peer's response.
3547
+ *
3548
+ * Bounded. Without a timer this settles on exactly two events — a matching
3549
+ * `res` frame, or the socket's `close` (which drains `pending`) — so a peer
3550
+ * that receives the request and then neither answers nor closes leaves the
3551
+ * caller pending forever. That is a wedged handler, or a half-open socket
3552
+ * after a child died without a clean teardown, and it is how camera 615 spent
3553
+ * 30+ minutes with every inference permit held by a call that was never
3554
+ * coming back.
3555
+ */
3556
+ request(body, opts) {
3548
3557
  if (this.closed) return Promise.reject(/* @__PURE__ */ new Error("channel closed"));
3549
3558
  const id = this.nextId++;
3559
+ const timeoutMs = opts?.timeoutMs ?? 6e4;
3550
3560
  return new Promise((resolve, reject) => {
3561
+ let timer = null;
3562
+ if (timeoutMs > 0) {
3563
+ timer = setTimeout(() => {
3564
+ this.pending.delete(id);
3565
+ reject(/* @__PURE__ */ new Error(`UDS request timed out after ${timeoutMs}ms`));
3566
+ }, timeoutMs);
3567
+ timer.unref?.();
3568
+ }
3551
3569
  this.pending.set(id, {
3552
3570
  resolve,
3553
- reject
3571
+ reject,
3572
+ timer
3554
3573
  });
3555
3574
  this.send({
3556
3575
  k: "req",
@@ -3614,6 +3633,7 @@ var SocketChannel = class {
3614
3633
  const p = this.pending.get(frame.id);
3615
3634
  if (!p) return;
3616
3635
  this.pending.delete(frame.id);
3636
+ if (p.timer !== null) clearTimeout(p.timer);
3617
3637
  if (frame.ok) p.resolve(frame.body);
3618
3638
  else p.reject(new Error(frame.err));
3619
3639
  return;
@@ -3624,7 +3644,10 @@ var SocketChannel = class {
3624
3644
  if (this.closeFired) return;
3625
3645
  this.closeFired = true;
3626
3646
  this.closed = true;
3627
- for (const [, p] of this.pending) p.reject(/* @__PURE__ */ new Error("channel closed"));
3647
+ for (const [, p] of this.pending) {
3648
+ if (p.timer !== null) clearTimeout(p.timer);
3649
+ p.reject(/* @__PURE__ */ new Error("channel closed"));
3650
+ }
3628
3651
  this.pending.clear();
3629
3652
  this.closeHandler();
3630
3653
  }
@@ -4301,6 +4324,10 @@ var LocalChildRegistry = class {
4301
4324
  resolveChildIdForAddon;
4302
4325
  /** This node's own Moleculer nodeId (see {@link LocalChildRegistryOptions.ownNodeId}). */
4303
4326
  ownNodeId;
4327
+ /** See {@link LocalChildRegistryOptions.isAggregatedCollectionMethod}. */
4328
+ isAggregatedCollectionMethod;
4329
+ /** See {@link LocalChildRegistryOptions.capTimeoutMs}. */
4330
+ capTimeoutMs;
4304
4331
  /** Tracks capNames already logged as UDS-routed; one INFO line per capName per process. */
4305
4332
  egressRoutedCaps = /* @__PURE__ */ new Set();
4306
4333
  /** Active event fan-out mode, read once from `CAMSTACK_UDS_EVENT_FANOUT`. */
@@ -4329,6 +4356,8 @@ var LocalChildRegistry = class {
4329
4356
  this.getActiveSingletonAddonId = opts.getActiveSingletonAddonId;
4330
4357
  this.resolveChildIdForAddon = opts.resolveChildIdForAddon;
4331
4358
  this.ownNodeId = opts.ownNodeId;
4359
+ this.isAggregatedCollectionMethod = opts.isAggregatedCollectionMethod;
4360
+ this.capTimeoutMs = opts.capTimeoutMs;
4332
4361
  } else {
4333
4362
  this.server = serverOrOptions;
4334
4363
  this.onUnownedCall = onUnownedCallArg;
@@ -4491,11 +4520,20 @@ var LocalChildRegistry = class {
4491
4520
  if (deviceId !== void 0 && entry.caps.some((cap) => cap.capName === capName && cap.deviceId === deviceId)) return true;
4492
4521
  return entry.caps.some((cap) => cap.capName === capName && cap.deviceId === void 0);
4493
4522
  }
4523
+ /**
4524
+ * Per-request options for a cap call: the cap method's declared `timeoutMs`
4525
+ * when one exists, else `undefined` so the channel applies its default.
4526
+ * Mirrors `CapRouteResolver.callTimeout` for the remote plane.
4527
+ */
4528
+ capRequestOpts(input) {
4529
+ const declared = this.capTimeoutMs?.(input.capName, input.method);
4530
+ return typeof declared === "number" ? { timeoutMs: declared } : void 0;
4531
+ }
4494
4532
  /** Forward a cap method call to a SPECIFIC child by id over UDS; rejects if that child is absent. */
4495
4533
  async callCapOnChild(childId, input) {
4496
4534
  const entry = this.children.get(childId);
4497
4535
  if (!entry) throw new Error(`no local child "${childId}" for cap "${input.capName}"`);
4498
- return entry.channel.request(this.toCapCall(input));
4536
+ return entry.channel.request(this.toCapCall(input), this.capRequestOpts(input));
4499
4537
  }
4500
4538
  /** Forward a cap method call to the owning child over UDS; rejects if none. */
4501
4539
  async callCap(input) {
@@ -4505,7 +4543,7 @@ var LocalChildRegistry = class {
4505
4543
  const where = input.deviceId === void 0 ? "" : ` for device ${input.deviceId}`;
4506
4544
  throw new Error(`no local child provides cap "${input.capName}"${where}`);
4507
4545
  }
4508
- return entry.channel.request(this.toCapCall(input));
4546
+ return entry.channel.request(this.toCapCall(input), this.capRequestOpts(input));
4509
4547
  }
4510
4548
  /**
4511
4549
  * Forward an ADDON-LEVEL call (routes / custom-action) to a SPECIFIC child
@@ -4692,7 +4730,7 @@ var LocalChildRegistry = class {
4692
4730
  };
4693
4731
  const pinnedNodeId = out.nodeId ?? extractNodeId(out.args);
4694
4732
  const pinTargetsThisNode = pinnedNodeId !== void 0 && this.ownNodeId !== void 0 && pinnedNodeId === this.ownNodeId;
4695
- if ((pinnedNodeId === void 0 || pinTargetsThisNode ? this.resolveChildId(out.capName, out.deviceId) : null) !== null) {
4733
+ if ((!(pinnedNodeId === void 0 && this.isAggregatedCollectionMethod?.(out.capName, out.method) === true) && (pinnedNodeId === void 0 || pinTargetsThisNode) ? this.resolveChildId(out.capName, out.deviceId) : null) !== null) {
4696
4734
  if (!this.egressRoutedCaps.has(out.capName)) {
4697
4735
  this.egressRoutedCaps.add(out.capName);
4698
4736
  this.logger?.info("routed child egress over UDS", { capName: out.capName });
@@ -5248,6 +5286,8 @@ function createParentUnownedCallHandler(deps) {
5248
5286
  if (nodeId === void 0) {
5249
5287
  const empty = deps.resolveEmptyCollection?.(input.capName, input.method);
5250
5288
  if (empty != null) return empty;
5289
+ const aggregate = await deps.callCollectionAggregate?.(input.capName, input.method, input.args);
5290
+ if (aggregate != null) return aggregate;
5251
5291
  }
5252
5292
  const resolver = deps.getResolver();
5253
5293
  if (resolver !== null) try {
@@ -5415,14 +5455,18 @@ function localProviderLink(resolver, observerOpts) {
5415
5455
  return ({ op, next }) => {
5416
5456
  const parsed = parsePath(op.path);
5417
5457
  if (!parsed) return next(op);
5458
+ const opWithDefaults = op.input === void 0 ? op : {
5459
+ ...op,
5460
+ input: withCapInputDefaults(parsed.capName, parsed.method, op.input)
5461
+ };
5418
5462
  if (localBase !== void 0) {
5419
5463
  const pinnedNodeId = readNodePin(op.context);
5420
- if (pinnedNodeId !== void 0 && pinnedNodeId !== localBase) return next(op);
5464
+ if (pinnedNodeId !== void 0 && pinnedNodeId !== localBase) return next(opWithDefaults);
5421
5465
  }
5422
5466
  const provider = resolver.getByName(parsed.capName);
5423
- if (!provider || typeof provider !== "object") return next(op);
5467
+ if (!provider || typeof provider !== "object") return next(opWithDefaults);
5424
5468
  const fn = Reflect.get(provider, parsed.method);
5425
- if (typeof fn !== "function") return next(op);
5469
+ if (typeof fn !== "function") return next(opWithDefaults);
5426
5470
  if (observerOpts) try {
5427
5471
  const providerAddonId = observerOpts.providerAddonIdForCap(parsed.capName);
5428
5472
  if (providerAddonId) observerOpts.observer({
@@ -5434,7 +5478,7 @@ function localProviderLink(resolver, observerOpts) {
5434
5478
  });
5435
5479
  } catch {}
5436
5480
  return observable((observer) => {
5437
- Promise.resolve(fn.call(provider, op.input)).then((data) => {
5481
+ Promise.resolve(fn.call(provider, opWithDefaults.input)).then((data) => {
5438
5482
  observer.next({ result: {
5439
5483
  type: "data",
5440
5484
  data
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@camstack/system",
3
- "version": "1.2.22",
3
+ "version": "1.2.24",
4
4
  "description": "Core addon for CamStack — builtins, pipeline, process management, auth, logging, events",
5
5
  "keywords": [
6
6
  "camstack",