@camstack/server 1.1.63 → 1.1.65

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.
@@ -45,13 +45,14 @@ const system_2 = require("@camstack/system");
45
45
  const client_1 = require("@trpc/client");
46
46
  const system_3 = require("@camstack/system");
47
47
  const system_4 = require("@camstack/system");
48
+ const system_5 = require("@camstack/system");
48
49
  const node_crypto_1 = require("node:crypto");
49
50
  const path = __importStar(require("node:path"));
50
51
  const fs = __importStar(require("node:fs"));
51
52
  const node_url_1 = require("node:url");
52
53
  const addon_settings_provider_js_1 = require("./addon-settings-provider.js");
53
54
  const addon_call_gateway_js_1 = require("./addon-call-gateway.js");
54
- const system_5 = require("@camstack/system");
55
+ const system_6 = require("@camstack/system");
55
56
  const types_2 = require("@camstack/types");
56
57
  /**
57
58
  * Type predicate: true when an `ISettingsBackend` also satisfies the
@@ -376,7 +377,7 @@ class AddonRegistryService {
376
377
  // Register the addon-settings singleton provider — replaces the
377
378
  // former `$addonHost` Moleculer service. The provider resolves
378
379
  // addonId → local addon instance (hub) or remote Moleculer call.
379
- this.capabilityRegistry.declareCapability(system_5.addonSettingsCapability);
380
+ this.capabilityRegistry.declareCapability(system_6.addonSettingsCapability);
380
381
  // The SINGLE router for addon-level calls (routes / custom / settings).
381
382
  // It classifies in-process | hub-local-child (UDS) | remote-agent
382
383
  // (Moleculer) in ONE place — `resolveNode` reports only the BASE node
@@ -2511,6 +2512,25 @@ class AddonRegistryService {
2511
2512
  capHandleCache.set(key, handle);
2512
2513
  return handle;
2513
2514
  }
2515
+ // In-process HTTP data-plane for co-located hub builtins (e.g. the snapshot
2516
+ // wrapper's per-device image endpoint). The facility binds a `127.0.0.1`
2517
+ // listener in the hub process on first `serve()`; the sink publishes its
2518
+ // endpoints straight into the hub's `DataPlaneRegistry` (bare `addonId`, the
2519
+ // same key the `/addon/:addonId/*` reverse-proxy matches), so a builtin
2520
+ // serves media exactly like a forked addon — no per-builtin proxy plumbing.
2521
+ // `mountAddonDataPlanes` handles only FORKED addons; this covers the
2522
+ // co-located path it defers. Disposed via the addon's disposer chain.
2523
+ const dataPlaneSink = {
2524
+ set: (id, endpoints) => {
2525
+ registry.dataPlaneRegistry?.registerAddon(id, endpoints);
2526
+ },
2527
+ };
2528
+ const dataPlaneFacility = (0, system_5.createAddonDataPlaneFacility)({
2529
+ addonId,
2530
+ logger,
2531
+ sink: dataPlaneSink,
2532
+ });
2533
+ this.getOrCreateDisposerChain(addonId).add(() => dataPlaneFacility.dispose());
2514
2534
  const ctx = {
2515
2535
  id: `addon:${addonId}`,
2516
2536
  logger,
@@ -2518,6 +2538,7 @@ class AddonRegistryService {
2518
2538
  addonConfig: bootstrapConfig,
2519
2539
  dataDir,
2520
2540
  nodeDataDir,
2541
+ dataPlane: dataPlaneFacility.dataPlane,
2521
2542
  get api() {
2522
2543
  return registry.getBrokerApi();
2523
2544
  },
@@ -78,9 +78,12 @@ const AGENT_BOOTSTRAP_PACKAGES = new Set([
78
78
  * nodes — excluded, same rule as `listNodes()` / `classifyNode`.
79
79
  */
80
80
  function toNodeLiveness(nodes) {
81
- return nodes
82
- .filter((node) => !node.id.includes('/'))
83
- .map((node) => ({ id: node.id, isHub: node.id === 'hub', isOnline: node.available }));
81
+ return (nodes
82
+ // A Moleculer registry can transiently hold a malformed entry with no id
83
+ // (seen live 2026-07-16 after agent churn): guard it or every consumer of
84
+ // this projection 500s on `undefined.includes`.
85
+ .filter((node) => typeof node.id === 'string' && !node.id.includes('/'))
86
+ .map((node) => ({ id: node.id, isHub: node.id === 'hub', isOnline: node.available })));
84
87
  }
85
88
  /**
86
89
  * Project a live `AgentListItem` into the durable history descriptor. Field
@@ -269,7 +272,9 @@ class AgentRegistryService {
269
272
  async reconcileConnectedAgents() {
270
273
  const registry = this.moleculer.broker.registry;
271
274
  const nodes = registry?.getNodeList?.({ onlyAvailable: true }) ?? [];
272
- const agentIds = nodes.map((n) => n.id).filter((id) => id !== 'hub' && !id.includes('/'));
275
+ const agentIds = nodes
276
+ .map((n) => n.id)
277
+ .filter((id) => typeof id === 'string' && id !== 'hub' && !id.includes('/'));
273
278
  if (agentIds.length === 0)
274
279
  return;
275
280
  console.log(`[agent-registry] Boot reconcile: ${agentIds.length} connected agent(s)`);
@@ -468,8 +473,10 @@ class AgentRegistryService {
468
473
  const nodes = registry?.getNodeList?.({ onlyAvailable: false }) ?? [];
469
474
  for (const node of nodes) {
470
475
  const nodeId = node.id;
471
- // Skip hub (already included) and child processes (contain '/')
472
- if (nodeId === 'hub' || nodeId.includes('/'))
476
+ // Skip hub (already included), child processes (contain '/'), and
477
+ // malformed registry entries with no id (live 2026-07-16: one such
478
+ // ghost 500'd nodes.topology — the whole Cluster page — until restart).
479
+ if (typeof nodeId !== 'string' || nodeId === 'hub' || nodeId.includes('/'))
473
480
  continue;
474
481
  if (!node.available) {
475
482
  // Offline: skip the `$agent.status`/`$process.list` RPC fan-out
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@camstack/server",
3
- "version": "1.1.63",
3
+ "version": "1.1.65",
4
4
  "private": false,
5
5
  "files": [
6
6
  "dist",
@@ -23,19 +23,19 @@
23
23
  "test:watch": "vitest"
24
24
  },
25
25
  "dependencies": {
26
- "@camstack/addon-admin-ui": "1.1.52",
27
- "@camstack/addon-advanced-notifier": "1.1.24",
28
- "@camstack/addon-auth": "1.1.9",
29
- "@camstack/addon-decoder-nodeav": "1.1.12",
30
- "@camstack/addon-notifiers": "1.1.24",
31
- "@camstack/addon-pipeline": "1.1.57",
32
- "@camstack/addon-pipeline-orchestrator": "1.1.46",
33
- "@camstack/addon-post-analysis": "1.1.29",
34
- "@camstack/sdk": "1.1.24",
35
- "@camstack/shm-ring": "1.0.23",
36
- "@camstack/system": "1.1.50",
37
- "@camstack/types": "1.1.45",
38
- "@camstack/ui-library": "1.1.36",
26
+ "@camstack/addon-admin-ui": "1.1.53",
27
+ "@camstack/addon-advanced-notifier": "1.1.25",
28
+ "@camstack/addon-auth": "1.1.10",
29
+ "@camstack/addon-decoder-nodeav": "1.1.13",
30
+ "@camstack/addon-notifiers": "1.1.25",
31
+ "@camstack/addon-pipeline": "1.1.58",
32
+ "@camstack/addon-pipeline-orchestrator": "1.1.48",
33
+ "@camstack/addon-post-analysis": "1.1.30",
34
+ "@camstack/sdk": "1.1.25",
35
+ "@camstack/shm-ring": "1.0.24",
36
+ "@camstack/system": "1.1.51",
37
+ "@camstack/types": "1.1.46",
38
+ "@camstack/ui-library": "1.1.37",
39
39
  "@fastify/compress": "^9.0.0",
40
40
  "@fastify/cookie": "^11.0.2",
41
41
  "@fastify/multipart": "^10.0.0",