@camstack/system 1.2.28 → 1.2.29
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.
- package/dist/addon-runner.js +3 -3
- package/dist/addon-runner.mjs +2 -2
- package/dist/builtins/addon-pages-aggregator/addon-pages-aggregator.addon.js +1 -1
- package/dist/builtins/addon-pages-aggregator/addon-pages-aggregator.addon.mjs +1 -1
- package/dist/builtins/addon-widgets-aggregator/addon-widgets-aggregator.addon.js +1 -1
- package/dist/builtins/addon-widgets-aggregator/addon-widgets-aggregator.addon.mjs +1 -1
- package/dist/builtins/alerts/alerts.addon.d.ts +0 -7
- package/dist/builtins/alerts/alerts.addon.js +47 -25
- package/dist/builtins/alerts/alerts.addon.mjs +47 -25
- package/dist/builtins/alerts/prune-policy.d.ts +44 -0
- package/dist/builtins/backup-orchestrator/backup-orchestrator.addon.js +1 -1
- package/dist/builtins/backup-orchestrator/backup-orchestrator.addon.mjs +1 -1
- package/dist/builtins/console-logging/index.js +1 -1
- package/dist/builtins/console-logging/index.mjs +1 -1
- package/dist/builtins/device-manager/device-manager.addon.js +1 -1
- package/dist/builtins/device-manager/device-manager.addon.mjs +1 -1
- package/dist/builtins/doorbell/virtual-doorbell.addon.js +1 -1
- package/dist/builtins/doorbell/virtual-doorbell.addon.mjs +1 -1
- package/dist/builtins/hub-forwarder/index.js +1 -1
- package/dist/builtins/hub-forwarder/index.mjs +1 -1
- package/dist/builtins/local-auth/local-auth.addon.js +1 -1
- package/dist/builtins/local-auth/local-auth.addon.mjs +1 -1
- package/dist/builtins/local-network/local-network.addon.js +1 -1
- package/dist/builtins/local-network/local-network.addon.mjs +1 -1
- package/dist/builtins/loki-logging/index.js +1 -1
- package/dist/builtins/loki-logging/index.mjs +1 -1
- package/dist/builtins/native-metrics/native-metrics.addon.js +1 -1
- package/dist/builtins/native-metrics/native-metrics.addon.mjs +1 -1
- package/dist/builtins/platform-probe/index.js +1 -1
- package/dist/builtins/platform-probe/index.mjs +1 -1
- package/dist/builtins/remote-access-orchestrator/remote-access-orchestrator.addon.js +1 -1
- package/dist/builtins/remote-access-orchestrator/remote-access-orchestrator.addon.mjs +1 -1
- package/dist/builtins/snapshot/index.js +1 -1
- package/dist/builtins/snapshot/index.mjs +1 -1
- package/dist/builtins/sqlite-storage/filesystem-storage.addon.js +1 -1
- package/dist/builtins/sqlite-storage/filesystem-storage.addon.mjs +1 -1
- package/dist/builtins/sqlite-storage/sqlite-settings-backend.d.ts +7 -1
- package/dist/builtins/sqlite-storage/sqlite-settings.addon.d.ts +8 -2
- package/dist/builtins/sqlite-storage/sqlite-settings.addon.js +22 -4
- package/dist/builtins/sqlite-storage/sqlite-settings.addon.mjs +22 -4
- package/dist/builtins/storage-orchestrator/data-store-dispatch.d.ts +12 -0
- package/dist/builtins/storage-orchestrator/storage-orchestrator.addon.d.ts +18 -7
- package/dist/builtins/storage-orchestrator/storage-orchestrator.addon.js +78 -11
- package/dist/builtins/storage-orchestrator/storage-orchestrator.addon.mjs +78 -11
- package/dist/builtins/system-config/system-config.addon.js +1 -1
- package/dist/builtins/system-config/system-config.addon.mjs +1 -1
- package/dist/builtins/winston-logging/index.js +1 -1
- package/dist/builtins/winston-logging/index.mjs +1 -1
- package/dist/{dist-BXmFvn3h.mjs → dist-B7hOpr5i.mjs} +411 -166
- package/dist/{dist-BxtIzexq.js → dist-CPmFYLqq.js} +416 -165
- package/dist/index.d.ts +2 -0
- package/dist/index.js +106 -2
- package/dist/index.mjs +102 -3
- package/dist/kernel/heap-watch.d.ts +36 -0
- package/dist/kernel/transport/uds-event-bus.d.ts +4 -1
- package/dist/{manifest-python-deps-KZ00cbfP.js → manifest-python-deps-BqE5j0-O.js} +25 -4
- package/dist/{manifest-python-deps-BNOApgK0.mjs → manifest-python-deps-Ck4-9K9m.mjs} +25 -4
- package/package.json +7 -3
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-
|
|
3
|
+
const require_dist = require("./dist-CPmFYLqq.js");
|
|
4
4
|
const require_model_download_service = require("./model-download-service-hf0ookyy.js");
|
|
5
|
-
const require_manifest_python_deps = require("./manifest-python-deps-
|
|
5
|
+
const require_manifest_python_deps = require("./manifest-python-deps-BqE5j0-O.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");
|
|
@@ -24,6 +24,8 @@ require("./builtins/local-auth/index.js");
|
|
|
24
24
|
const require_builtins_device_manager_device_manager_addon = require("./builtins/device-manager/device-manager.addon.js");
|
|
25
25
|
require("./builtins/device-manager/index.js");
|
|
26
26
|
const require_custom_action_registry = require("./custom-action-registry-jY0NOZK8.js");
|
|
27
|
+
let node_v8 = require("node:v8");
|
|
28
|
+
node_v8 = require_chunk.__toESM(node_v8);
|
|
27
29
|
let _camstack_types_node = require("@camstack/types/node");
|
|
28
30
|
let zod = require("zod");
|
|
29
31
|
let node_http = require("node:http");
|
|
@@ -52,6 +54,100 @@ fs = require_chunk.__toESM(fs, 1);
|
|
|
52
54
|
let path = require("path");
|
|
53
55
|
path = require_chunk.__toESM(path, 1);
|
|
54
56
|
let module$1 = require("module");
|
|
57
|
+
//#region src/kernel/heap-watch.ts
|
|
58
|
+
/**
|
|
59
|
+
* heap-watch — hub-main's own memory, on the record.
|
|
60
|
+
*
|
|
61
|
+
* ## Why this exists
|
|
62
|
+
*
|
|
63
|
+
* hub-main is launched with `--max-old-space-size=1536` (docker-entrypoint) and
|
|
64
|
+
* has logged NOTHING about its own heap. When it died on 2026-08-01/02 the only
|
|
65
|
+
* trace was V8's own stderr line:
|
|
66
|
+
*
|
|
67
|
+
* FATAL ERROR: Reached heap limit Allocation failed - JavaScript heap out of memory
|
|
68
|
+
*
|
|
69
|
+
* which carries no process name, no heap number and no history — the whole
|
|
70
|
+
* server restarts and the evidence is gone. Four of those in ~15h, and the one
|
|
71
|
+
* at 06:57:57 landed nine seconds after a viewer opened a WebRTC session, which
|
|
72
|
+
* is why the app sat in a permanent "loading": the hub was dying as it
|
|
73
|
+
* connected.
|
|
74
|
+
*
|
|
75
|
+
* `[mem]` reports already exist for forked addon runners (SIGUSR2 in
|
|
76
|
+
* `addon-runner.ts`) — hub-main, the one process that actually OOMs, was the
|
|
77
|
+
* one process with no telemetry at all.
|
|
78
|
+
*
|
|
79
|
+
* ## What it gives
|
|
80
|
+
*
|
|
81
|
+
* A heartbeat carrying the numbers that separate the two possible stories, and
|
|
82
|
+
* a WARN as the heap approaches the ceiling — the line that will exist BEFORE
|
|
83
|
+
* the next fatal instead of after it:
|
|
84
|
+
*
|
|
85
|
+
* - `heapUsedMb` climbing steadily between restarts → a leak;
|
|
86
|
+
* - `heapUsedMb` flat with a sharp jump under load → a burst allocation, and
|
|
87
|
+
* the timestamp says what was being served.
|
|
88
|
+
*
|
|
89
|
+
* `external`/`arrayBuffers` ride along because they are NOT bounded by
|
|
90
|
+
* `--max-old-space-size` and are most of the gap between a 1.5GB cap and the
|
|
91
|
+
* ~2.05GB RSS observed live: a diagnosis that only looks at the JS heap
|
|
92
|
+
* misreads that process by 500MB.
|
|
93
|
+
*/
|
|
94
|
+
/** Heartbeat period. Slow enough to be free, fast enough that the sample before
|
|
95
|
+
* a fatal is recent. */
|
|
96
|
+
var HEAP_WATCH_INTERVAL_MS = 6e4;
|
|
97
|
+
/** Warn above this share of the heap ceiling. Chosen so the warning precedes
|
|
98
|
+
* the fatal by more than one interval under realistic growth. */
|
|
99
|
+
var HEAP_WATCH_WARN_RATIO = .8;
|
|
100
|
+
var MB = (bytes) => Math.round(bytes / 1048576);
|
|
101
|
+
/**
|
|
102
|
+
* Build a sample from raw readings. Pure so the thresholds are testable without
|
|
103
|
+
* allocating a gigabyte to reach them.
|
|
104
|
+
*/
|
|
105
|
+
function buildHeapSample(mem, heapLimitBytes, warnRatio = HEAP_WATCH_WARN_RATIO) {
|
|
106
|
+
const usedRatio = heapLimitBytes > 0 ? mem.heapUsed / heapLimitBytes : 0;
|
|
107
|
+
return {
|
|
108
|
+
rssMb: MB(mem.rss),
|
|
109
|
+
heapUsedMb: MB(mem.heapUsed),
|
|
110
|
+
heapTotalMb: MB(mem.heapTotal),
|
|
111
|
+
heapLimitMb: MB(heapLimitBytes),
|
|
112
|
+
externalMb: MB(mem.external),
|
|
113
|
+
arrayBuffersMb: MB(mem.arrayBuffers),
|
|
114
|
+
usedRatio: Math.round(usedRatio * 100) / 100,
|
|
115
|
+
nearLimit: usedRatio >= warnRatio
|
|
116
|
+
};
|
|
117
|
+
}
|
|
118
|
+
var consoleSink = {
|
|
119
|
+
info: (line) => console.log(line),
|
|
120
|
+
warn: (line) => console.warn(line)
|
|
121
|
+
};
|
|
122
|
+
function format$1(label, s) {
|
|
123
|
+
return `[mem] ${label} rss=${s.rssMb}MB heapUsed=${s.heapUsedMb}MB heapTotal=${s.heapTotalMb}MB heapLimit=${s.heapLimitMb}MB used=${Math.round(s.usedRatio * 100)}% external=${s.externalMb}MB arrayBuffers=${s.arrayBuffersMb}MB`;
|
|
124
|
+
}
|
|
125
|
+
/**
|
|
126
|
+
* Start the heartbeat. Returns a stop function.
|
|
127
|
+
*
|
|
128
|
+
* `unref`ed so it can never hold the process open, and every read is wrapped:
|
|
129
|
+
* a diagnostic that can crash the process it watches is worse than none.
|
|
130
|
+
*/
|
|
131
|
+
function startHeapWatch(label = "hub-main", sink = consoleSink, intervalMs = HEAP_WATCH_INTERVAL_MS) {
|
|
132
|
+
const tick = () => {
|
|
133
|
+
try {
|
|
134
|
+
const sample = buildHeapSample(process.memoryUsage(), node_v8.getHeapStatistics().heap_size_limit);
|
|
135
|
+
const line = format$1(label, sample);
|
|
136
|
+
if (sample.nearLimit) sink.warn(`${line} — APPROACHING HEAP LIMIT`);
|
|
137
|
+
else sink.info(line);
|
|
138
|
+
} catch {}
|
|
139
|
+
};
|
|
140
|
+
const timer = setInterval(tick, intervalMs);
|
|
141
|
+
timer.unref?.();
|
|
142
|
+
tick();
|
|
143
|
+
let stopped = false;
|
|
144
|
+
return () => {
|
|
145
|
+
if (stopped) return;
|
|
146
|
+
stopped = true;
|
|
147
|
+
clearInterval(timer);
|
|
148
|
+
};
|
|
149
|
+
}
|
|
150
|
+
//#endregion
|
|
55
151
|
//#region src/events/event-bus.ts
|
|
56
152
|
var EventBus = class {
|
|
57
153
|
listeners = /* @__PURE__ */ new Map();
|
|
@@ -5948,6 +6044,10 @@ var INFRA_CAPABILITIES = [
|
|
|
5948
6044
|
name: "storage-provider",
|
|
5949
6045
|
required: true
|
|
5950
6046
|
},
|
|
6047
|
+
{
|
|
6048
|
+
name: "data-store-provider",
|
|
6049
|
+
required: true
|
|
6050
|
+
},
|
|
5951
6051
|
{
|
|
5952
6052
|
name: "storage",
|
|
5953
6053
|
required: true
|
|
@@ -94119,6 +94219,8 @@ exports.FsStorageBackend = FsStorageBackend;
|
|
|
94119
94219
|
exports.HEALTH_MONITOR_GRACE_PERIOD_MS = HEALTH_MONITOR_GRACE_PERIOD_MS;
|
|
94120
94220
|
exports.HEALTH_MONITOR_RETRY_INTERVALS_MS = HEALTH_MONITOR_RETRY_INTERVALS_MS;
|
|
94121
94221
|
exports.HEALTH_MONITOR_TICK_MS = HEALTH_MONITOR_TICK_MS;
|
|
94222
|
+
exports.HEAP_WATCH_INTERVAL_MS = HEAP_WATCH_INTERVAL_MS;
|
|
94223
|
+
exports.HEAP_WATCH_WARN_RATIO = HEAP_WATCH_WARN_RATIO;
|
|
94122
94224
|
exports.HUB_CAP_FWD_ACTION = require_manifest_python_deps.HUB_CAP_FWD_ACTION;
|
|
94123
94225
|
exports.HUB_CAP_FWD_SERVICE = require_manifest_python_deps.HUB_CAP_FWD_SERVICE;
|
|
94124
94226
|
exports.HubForwarderAddon = require_builtins_hub_forwarder_index.HubForwarderAddon$1;
|
|
@@ -94193,6 +94295,7 @@ Object.defineProperty(exports, "buildBinaryPath", {
|
|
|
94193
94295
|
}
|
|
94194
94296
|
});
|
|
94195
94297
|
exports.buildCapRouters = buildCapRouters;
|
|
94298
|
+
exports.buildHeapSample = buildHeapSample;
|
|
94196
94299
|
exports.buildLinkChain = require_manifest_python_deps.buildLinkChain;
|
|
94197
94300
|
exports.buildNativeCapProxy = require_manifest_python_deps.buildNativeCapProxy;
|
|
94198
94301
|
exports.buildNodeManifest = buildNodeManifest;
|
|
@@ -94358,6 +94461,7 @@ exports.scopesAllowDeviceCap = scopesAllowDeviceCap;
|
|
|
94358
94461
|
exports.serializeTypedArrays = require_manifest_python_deps.serializeTypedArrays;
|
|
94359
94462
|
exports.setHubConnected = require_manifest_python_deps.setHubConnected;
|
|
94360
94463
|
exports.setNodeEventInterest = require_manifest_python_deps.setNodeEventInterest;
|
|
94464
|
+
exports.startHeapWatch = startHeapWatch;
|
|
94361
94465
|
exports.stripCamstackDeps = stripCamstackDeps;
|
|
94362
94466
|
exports.subscribePassthrough = require_manifest_python_deps.subscribePassthrough;
|
|
94363
94467
|
exports.udsChildLogToWorkerEntry = require_manifest_python_deps.udsChildLogToWorkerEntry;
|
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 {
|
|
2
|
+
import { A as extractNestedAddonId, At as scopeKey, Dt as parseJsonUnknown$1, Et as parseJsonObject, F as isObjectInput, G as objectInputDeclaresAddonId, H as looseSchema, I as isVoidInput, J as procedureAuthKey, L as kebabToCamel, Mt as EventCategory$1, N as isArrayOutputSchema, Ot as readinessKey, P as isCollectionArrayMethod, R as lifecycleJobSchema, St as expandCapMethods, V as logLevelAtMost, _t as asNumber, at as errMsg$1, bt as emitDownForOwnedCaps, c as RUNTIME_DEFAULTS, ct as DEVICE_SETTINGS_CONTRIBUTION_METHODS, gt as asJsonObject$1, kt as resolveCapMount, lt as DEVICE_STATUS_METHOD, m as addonSettingsCapability, mt as ReadinessTimeoutError, pt as ReadinessRegistry, 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-B7hOpr5i.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-
|
|
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-Ck4-9K9m.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";
|
|
@@ -23,6 +23,7 @@ import "./builtins/local-auth/index.mjs";
|
|
|
23
23
|
import { DeviceManagerAddon } from "./builtins/device-manager/device-manager.addon.mjs";
|
|
24
24
|
import "./builtins/device-manager/index.mjs";
|
|
25
25
|
import { t as CustomActionRegistry } from "./custom-action-registry-F__gp_VX.mjs";
|
|
26
|
+
import * as v8 from "node:v8";
|
|
26
27
|
import { PYTHON_VERSION, buildBinaryPath, downloadBinary, ensureBinary, ensureFfmpeg, ensurePython, findInPath, getFfmpegDownloadUrl, getPlatformInfo, getPythonDownloadUrl, installPythonPackages, installPythonRequirements } from "@camstack/types/node";
|
|
27
28
|
import { z } from "zod";
|
|
28
29
|
import { request } from "node:http";
|
|
@@ -45,6 +46,100 @@ import { StringDecoder } from "node:string_decoder";
|
|
|
45
46
|
import { lstatSync, readdir as readdir$1, readdirSync, readlinkSync, realpathSync } from "fs";
|
|
46
47
|
import "path";
|
|
47
48
|
import { createRequire } from "module";
|
|
49
|
+
//#region src/kernel/heap-watch.ts
|
|
50
|
+
/**
|
|
51
|
+
* heap-watch — hub-main's own memory, on the record.
|
|
52
|
+
*
|
|
53
|
+
* ## Why this exists
|
|
54
|
+
*
|
|
55
|
+
* hub-main is launched with `--max-old-space-size=1536` (docker-entrypoint) and
|
|
56
|
+
* has logged NOTHING about its own heap. When it died on 2026-08-01/02 the only
|
|
57
|
+
* trace was V8's own stderr line:
|
|
58
|
+
*
|
|
59
|
+
* FATAL ERROR: Reached heap limit Allocation failed - JavaScript heap out of memory
|
|
60
|
+
*
|
|
61
|
+
* which carries no process name, no heap number and no history — the whole
|
|
62
|
+
* server restarts and the evidence is gone. Four of those in ~15h, and the one
|
|
63
|
+
* at 06:57:57 landed nine seconds after a viewer opened a WebRTC session, which
|
|
64
|
+
* is why the app sat in a permanent "loading": the hub was dying as it
|
|
65
|
+
* connected.
|
|
66
|
+
*
|
|
67
|
+
* `[mem]` reports already exist for forked addon runners (SIGUSR2 in
|
|
68
|
+
* `addon-runner.ts`) — hub-main, the one process that actually OOMs, was the
|
|
69
|
+
* one process with no telemetry at all.
|
|
70
|
+
*
|
|
71
|
+
* ## What it gives
|
|
72
|
+
*
|
|
73
|
+
* A heartbeat carrying the numbers that separate the two possible stories, and
|
|
74
|
+
* a WARN as the heap approaches the ceiling — the line that will exist BEFORE
|
|
75
|
+
* the next fatal instead of after it:
|
|
76
|
+
*
|
|
77
|
+
* - `heapUsedMb` climbing steadily between restarts → a leak;
|
|
78
|
+
* - `heapUsedMb` flat with a sharp jump under load → a burst allocation, and
|
|
79
|
+
* the timestamp says what was being served.
|
|
80
|
+
*
|
|
81
|
+
* `external`/`arrayBuffers` ride along because they are NOT bounded by
|
|
82
|
+
* `--max-old-space-size` and are most of the gap between a 1.5GB cap and the
|
|
83
|
+
* ~2.05GB RSS observed live: a diagnosis that only looks at the JS heap
|
|
84
|
+
* misreads that process by 500MB.
|
|
85
|
+
*/
|
|
86
|
+
/** Heartbeat period. Slow enough to be free, fast enough that the sample before
|
|
87
|
+
* a fatal is recent. */
|
|
88
|
+
var HEAP_WATCH_INTERVAL_MS = 6e4;
|
|
89
|
+
/** Warn above this share of the heap ceiling. Chosen so the warning precedes
|
|
90
|
+
* the fatal by more than one interval under realistic growth. */
|
|
91
|
+
var HEAP_WATCH_WARN_RATIO = .8;
|
|
92
|
+
var MB = (bytes) => Math.round(bytes / 1048576);
|
|
93
|
+
/**
|
|
94
|
+
* Build a sample from raw readings. Pure so the thresholds are testable without
|
|
95
|
+
* allocating a gigabyte to reach them.
|
|
96
|
+
*/
|
|
97
|
+
function buildHeapSample(mem, heapLimitBytes, warnRatio = HEAP_WATCH_WARN_RATIO) {
|
|
98
|
+
const usedRatio = heapLimitBytes > 0 ? mem.heapUsed / heapLimitBytes : 0;
|
|
99
|
+
return {
|
|
100
|
+
rssMb: MB(mem.rss),
|
|
101
|
+
heapUsedMb: MB(mem.heapUsed),
|
|
102
|
+
heapTotalMb: MB(mem.heapTotal),
|
|
103
|
+
heapLimitMb: MB(heapLimitBytes),
|
|
104
|
+
externalMb: MB(mem.external),
|
|
105
|
+
arrayBuffersMb: MB(mem.arrayBuffers),
|
|
106
|
+
usedRatio: Math.round(usedRatio * 100) / 100,
|
|
107
|
+
nearLimit: usedRatio >= warnRatio
|
|
108
|
+
};
|
|
109
|
+
}
|
|
110
|
+
var consoleSink = {
|
|
111
|
+
info: (line) => console.log(line),
|
|
112
|
+
warn: (line) => console.warn(line)
|
|
113
|
+
};
|
|
114
|
+
function format$1(label, s) {
|
|
115
|
+
return `[mem] ${label} rss=${s.rssMb}MB heapUsed=${s.heapUsedMb}MB heapTotal=${s.heapTotalMb}MB heapLimit=${s.heapLimitMb}MB used=${Math.round(s.usedRatio * 100)}% external=${s.externalMb}MB arrayBuffers=${s.arrayBuffersMb}MB`;
|
|
116
|
+
}
|
|
117
|
+
/**
|
|
118
|
+
* Start the heartbeat. Returns a stop function.
|
|
119
|
+
*
|
|
120
|
+
* `unref`ed so it can never hold the process open, and every read is wrapped:
|
|
121
|
+
* a diagnostic that can crash the process it watches is worse than none.
|
|
122
|
+
*/
|
|
123
|
+
function startHeapWatch(label = "hub-main", sink = consoleSink, intervalMs = HEAP_WATCH_INTERVAL_MS) {
|
|
124
|
+
const tick = () => {
|
|
125
|
+
try {
|
|
126
|
+
const sample = buildHeapSample(process.memoryUsage(), v8.getHeapStatistics().heap_size_limit);
|
|
127
|
+
const line = format$1(label, sample);
|
|
128
|
+
if (sample.nearLimit) sink.warn(`${line} — APPROACHING HEAP LIMIT`);
|
|
129
|
+
else sink.info(line);
|
|
130
|
+
} catch {}
|
|
131
|
+
};
|
|
132
|
+
const timer = setInterval(tick, intervalMs);
|
|
133
|
+
timer.unref?.();
|
|
134
|
+
tick();
|
|
135
|
+
let stopped = false;
|
|
136
|
+
return () => {
|
|
137
|
+
if (stopped) return;
|
|
138
|
+
stopped = true;
|
|
139
|
+
clearInterval(timer);
|
|
140
|
+
};
|
|
141
|
+
}
|
|
142
|
+
//#endregion
|
|
48
143
|
//#region src/events/event-bus.ts
|
|
49
144
|
var EventBus = class {
|
|
50
145
|
listeners = /* @__PURE__ */ new Map();
|
|
@@ -5941,6 +6036,10 @@ var INFRA_CAPABILITIES = [
|
|
|
5941
6036
|
name: "storage-provider",
|
|
5942
6037
|
required: true
|
|
5943
6038
|
},
|
|
6039
|
+
{
|
|
6040
|
+
name: "data-store-provider",
|
|
6041
|
+
required: true
|
|
6042
|
+
},
|
|
5944
6043
|
{
|
|
5945
6044
|
name: "storage",
|
|
5946
6045
|
required: true
|
|
@@ -94065,4 +94164,4 @@ var LifecycleJobEngine = class {
|
|
|
94065
94164
|
}
|
|
94066
94165
|
};
|
|
94067
94166
|
//#endregion
|
|
94068
|
-
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 };
|
|
94167
|
+
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, HEAP_WATCH_INTERVAL_MS, HEAP_WATCH_WARN_RATIO, 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, buildHeapSample, 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, startHeapWatch, stripCamstackDeps, subscribePassthrough, udsChildLogToWorkerEntry, validateProviderRegistrations, writePendingRestart };
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
/** Heartbeat period. Slow enough to be free, fast enough that the sample before
|
|
2
|
+
* a fatal is recent. */
|
|
3
|
+
export declare const HEAP_WATCH_INTERVAL_MS = 60000;
|
|
4
|
+
/** Warn above this share of the heap ceiling. Chosen so the warning precedes
|
|
5
|
+
* the fatal by more than one interval under realistic growth. */
|
|
6
|
+
export declare const HEAP_WATCH_WARN_RATIO = 0.8;
|
|
7
|
+
export interface HeapSample {
|
|
8
|
+
readonly rssMb: number;
|
|
9
|
+
readonly heapUsedMb: number;
|
|
10
|
+
readonly heapTotalMb: number;
|
|
11
|
+
readonly heapLimitMb: number;
|
|
12
|
+
readonly externalMb: number;
|
|
13
|
+
readonly arrayBuffersMb: number;
|
|
14
|
+
/** heapUsed / heapLimit, 0-1. */
|
|
15
|
+
readonly usedRatio: number;
|
|
16
|
+
/** True once the heap is close enough to the ceiling to be worth shouting. */
|
|
17
|
+
readonly nearLimit: boolean;
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* Build a sample from raw readings. Pure so the thresholds are testable without
|
|
21
|
+
* allocating a gigabyte to reach them.
|
|
22
|
+
*/
|
|
23
|
+
export declare function buildHeapSample(mem: NodeJS.MemoryUsage, heapLimitBytes: number, warnRatio?: number): HeapSample;
|
|
24
|
+
/** Minimal sink so this module stays usable before any logger exists — the
|
|
25
|
+
* starter runs before the kernel's logging is wired. */
|
|
26
|
+
export interface HeapWatchSink {
|
|
27
|
+
readonly info: (line: string) => void;
|
|
28
|
+
readonly warn: (line: string) => void;
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* Start the heartbeat. Returns a stop function.
|
|
32
|
+
*
|
|
33
|
+
* `unref`ed so it can never hold the process open, and every read is wrapped:
|
|
34
|
+
* a diagnostic that can crash the process it watches is worse than none.
|
|
35
|
+
*/
|
|
36
|
+
export declare function startHeapWatch(label?: string, sink?: HeapWatchSink, intervalMs?: number): () => void;
|
|
@@ -5,7 +5,9 @@ import { IEventBus, SystemEvent } from '@camstack/types';
|
|
|
5
5
|
*
|
|
6
6
|
* - `emitEvent` — fire-and-forget: send a system event to the parent.
|
|
7
7
|
* - `onEvent` — register the single handler for parent→child events.
|
|
8
|
-
* (Only one handler is registered; calling again replaces the previous one.
|
|
8
|
+
* (Only one handler is registered; calling again replaces the previous one.
|
|
9
|
+
* Because the slot is single, this module registers it exactly ONCE per
|
|
10
|
+
* channel — the shared-state factory below — never once per addon bus.)
|
|
9
11
|
* - `updateEventPatterns` — declare this owner's live category-pattern set to
|
|
10
12
|
* the parent so it can subscription-filter the event fan-out. Called after
|
|
11
13
|
* every subscribe/unsubscribe with the CURRENT key set (full-set replace).
|
|
@@ -19,6 +21,7 @@ export interface UdsEventChannel {
|
|
|
19
21
|
}
|
|
20
22
|
/**
|
|
21
23
|
* Create a UDS-backed `IEventBus` for use inside a forked child process.
|
|
24
|
+
* Returns a per-addon facade over the channel's ONE shared state (module doc).
|
|
22
25
|
*
|
|
23
26
|
* @param client - The UDS channel toward the parent (hub or agent).
|
|
24
27
|
* @param addonId - This child's stable addon id — stamped as `sourceAddonId`
|
|
@@ -5164,7 +5164,31 @@ function udsChildLogToWorkerEntry(childId, entry) {
|
|
|
5164
5164
|
//#endregion
|
|
5165
5165
|
//#region src/kernel/transport/uds-event-bus.ts
|
|
5166
5166
|
/**
|
|
5167
|
+
* ONE `SharedBusState` per `UdsEventChannel` (see the module doc's
|
|
5168
|
+
* group-runner contract). Keyed weakly so a channel torn down with its
|
|
5169
|
+
* process does not pin its state.
|
|
5170
|
+
*/
|
|
5171
|
+
var sharedStateByChannel = /* @__PURE__ */ new WeakMap();
|
|
5172
|
+
/**
|
|
5173
|
+
* Resolve (or lazily create) the channel's shared bus state, registering the
|
|
5174
|
+
* single-slot `client.onEvent` handler exactly once — on first creation. The
|
|
5175
|
+
* handler delivers into the SHARED state, so every co-located addon's
|
|
5176
|
+
* subscribers see parent→child events regardless of bus construction order.
|
|
5177
|
+
* It does NOT call `client.emitEvent` (no echo back to the parent).
|
|
5178
|
+
*/
|
|
5179
|
+
function sharedStateFor(client) {
|
|
5180
|
+
const existing = sharedStateByChannel.get(client);
|
|
5181
|
+
if (existing !== void 0) return existing;
|
|
5182
|
+
const created = createSharedBusState();
|
|
5183
|
+
sharedStateByChannel.set(client, created);
|
|
5184
|
+
client.onEvent((event) => {
|
|
5185
|
+
deliverShared(created, event);
|
|
5186
|
+
});
|
|
5187
|
+
return created;
|
|
5188
|
+
}
|
|
5189
|
+
/**
|
|
5167
5190
|
* Create a UDS-backed `IEventBus` for use inside a forked child process.
|
|
5191
|
+
* Returns a per-addon facade over the channel's ONE shared state (module doc).
|
|
5168
5192
|
*
|
|
5169
5193
|
* @param client - The UDS channel toward the parent (hub or agent).
|
|
5170
5194
|
* @param addonId - This child's stable addon id — stamped as `sourceAddonId`
|
|
@@ -5172,10 +5196,7 @@ function udsChildLogToWorkerEntry(childId, entry) {
|
|
|
5172
5196
|
* events to their source addon.
|
|
5173
5197
|
*/
|
|
5174
5198
|
function createUdsEventBus(client, addonId) {
|
|
5175
|
-
const state =
|
|
5176
|
-
client.onEvent((event) => {
|
|
5177
|
-
deliverShared(state, event);
|
|
5178
|
-
});
|
|
5199
|
+
const state = sharedStateFor(client);
|
|
5179
5200
|
const reportPatterns = () => {
|
|
5180
5201
|
client.updateEventPatterns(addonId, [...state.handlers.keys()]);
|
|
5181
5202
|
};
|
|
@@ -5162,7 +5162,31 @@ function udsChildLogToWorkerEntry(childId, entry) {
|
|
|
5162
5162
|
//#endregion
|
|
5163
5163
|
//#region src/kernel/transport/uds-event-bus.ts
|
|
5164
5164
|
/**
|
|
5165
|
+
* ONE `SharedBusState` per `UdsEventChannel` (see the module doc's
|
|
5166
|
+
* group-runner contract). Keyed weakly so a channel torn down with its
|
|
5167
|
+
* process does not pin its state.
|
|
5168
|
+
*/
|
|
5169
|
+
var sharedStateByChannel = /* @__PURE__ */ new WeakMap();
|
|
5170
|
+
/**
|
|
5171
|
+
* Resolve (or lazily create) the channel's shared bus state, registering the
|
|
5172
|
+
* single-slot `client.onEvent` handler exactly once — on first creation. The
|
|
5173
|
+
* handler delivers into the SHARED state, so every co-located addon's
|
|
5174
|
+
* subscribers see parent→child events regardless of bus construction order.
|
|
5175
|
+
* It does NOT call `client.emitEvent` (no echo back to the parent).
|
|
5176
|
+
*/
|
|
5177
|
+
function sharedStateFor(client) {
|
|
5178
|
+
const existing = sharedStateByChannel.get(client);
|
|
5179
|
+
if (existing !== void 0) return existing;
|
|
5180
|
+
const created = createSharedBusState();
|
|
5181
|
+
sharedStateByChannel.set(client, created);
|
|
5182
|
+
client.onEvent((event) => {
|
|
5183
|
+
deliverShared(created, event);
|
|
5184
|
+
});
|
|
5185
|
+
return created;
|
|
5186
|
+
}
|
|
5187
|
+
/**
|
|
5165
5188
|
* Create a UDS-backed `IEventBus` for use inside a forked child process.
|
|
5189
|
+
* Returns a per-addon facade over the channel's ONE shared state (module doc).
|
|
5166
5190
|
*
|
|
5167
5191
|
* @param client - The UDS channel toward the parent (hub or agent).
|
|
5168
5192
|
* @param addonId - This child's stable addon id — stamped as `sourceAddonId`
|
|
@@ -5170,10 +5194,7 @@ function udsChildLogToWorkerEntry(childId, entry) {
|
|
|
5170
5194
|
* events to their source addon.
|
|
5171
5195
|
*/
|
|
5172
5196
|
function createUdsEventBus(client, addonId) {
|
|
5173
|
-
const state =
|
|
5174
|
-
client.onEvent((event) => {
|
|
5175
|
-
deliverShared(state, event);
|
|
5176
|
-
});
|
|
5197
|
+
const state = sharedStateFor(client);
|
|
5177
5198
|
const reportPatterns = () => {
|
|
5178
5199
|
client.updateEventPatterns(addonId, [...state.handlers.keys()]);
|
|
5179
5200
|
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@camstack/system",
|
|
3
|
-
"version": "1.2.
|
|
3
|
+
"version": "1.2.29",
|
|
4
4
|
"description": "Core addon for CamStack — builtins, pipeline, process management, auth, logging, events",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"camstack",
|
|
@@ -53,9 +53,10 @@
|
|
|
53
53
|
"category": "system",
|
|
54
54
|
"name": "SQLite Settings",
|
|
55
55
|
"entry": "./dist/builtins/sqlite-storage/sqlite-settings.addon.js",
|
|
56
|
+
"description": "The relational ENGINE behind the data door (SQLite WAL). Registers `data-store-provider`, an internal collection cap; the public `settings-store` door is owned by `storage-orchestrator`, which dispatches here. Callers never reach this addon directly — that is what makes the engine replaceable.",
|
|
56
57
|
"capabilities": [
|
|
57
58
|
{
|
|
58
|
-
"name": "
|
|
59
|
+
"name": "data-store-provider"
|
|
59
60
|
}
|
|
60
61
|
]
|
|
61
62
|
},
|
|
@@ -134,12 +135,15 @@
|
|
|
134
135
|
"id": "storage-orchestrator",
|
|
135
136
|
"category": "system",
|
|
136
137
|
"name": "Storage Orchestrator",
|
|
137
|
-
"description": "
|
|
138
|
+
"description": "The single data door. Owns the consumer-facing `storage` cap for bytes — the `locationId → StorageLocation` map, `StorageLocationRef` resolution, dispatch to the matching `storage-provider` registrant (`filesystem-storage` today; SFTP / S3 / WebDAV plug in alongside) — AND the `settings-store` cap for rows, dispatching to the `data-store-provider` engine (`sqlite-settings` today; a vector engine plugs in alongside). Nothing reaches an engine except through this addon.",
|
|
138
139
|
"entry": "./dist/builtins/storage-orchestrator/index.js",
|
|
139
140
|
"protected": true,
|
|
140
141
|
"capabilities": [
|
|
141
142
|
{
|
|
142
143
|
"name": "storage"
|
|
144
|
+
},
|
|
145
|
+
{
|
|
146
|
+
"name": "settings-store"
|
|
143
147
|
}
|
|
144
148
|
]
|
|
145
149
|
},
|