@camstack/server 1.2.675 → 1.2.676
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/CHANGELOG.md +7 -0
- package/dist/agent/agent-boot-mode.js +6 -0
- package/dist/agent/main.js +50 -30
- package/package.json +2 -2
package/CHANGELOG.md
CHANGED
|
@@ -7,6 +7,13 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
7
7
|
|
|
8
8
|
## [Unreleased]
|
|
9
9
|
|
|
10
|
+
## [1.2.676] - 2026-10-28
|
|
11
|
+
|
|
12
|
+
### Fixed
|
|
13
|
+
|
|
14
|
+
- An agent advertises itself on the network again, so the hub lists a new agent for pairing without typing its address
|
|
15
|
+
- An unpaired agent no longer crash-loops: it stays up to be paired and starts its addons once pairing completes
|
|
16
|
+
|
|
10
17
|
## [1.2.675] - 2026-10-28
|
|
11
18
|
|
|
12
19
|
### Changed
|
package/dist/agent/main.js
CHANGED
|
@@ -56,6 +56,7 @@ const agent_http_js_1 = require("./agent-http.js");
|
|
|
56
56
|
const agent_node_certificates_js_1 = require("./agent-node-certificates.js");
|
|
57
57
|
const agent_reconnect_js_1 = require("./agent-reconnect.js");
|
|
58
58
|
const serial_queue_js_1 = require("./serial-queue.js");
|
|
59
|
+
const agent_boot_mode_js_1 = require("./agent-boot-mode.js");
|
|
59
60
|
const agent_infra_capabilities_js_1 = require("./agent-infra-capabilities.js");
|
|
60
61
|
const agent_service_js_1 = require("./agent-service.js");
|
|
61
62
|
const agent_hub_addon_update_js_1 = require("./agent-hub-addon-update.js");
|
|
@@ -900,6 +901,7 @@ async function startAgent(configPath) {
|
|
|
900
901
|
leafFingerprint: (0, agent_pairing_store_js_1.pairedLeafFingerprint)(config.configPath),
|
|
901
902
|
});
|
|
902
903
|
};
|
|
904
|
+
const addonsBooted = (0, agent_boot_mode_js_1.decideAgentBootMode)({ paired: (0, agent_pairing_store_js_1.isAgentPaired)(config.configPath) }) === 'full';
|
|
903
905
|
const localPairing = (0, agent_pairing_local_js_1.createLocalPairingAnnouncer)(config.dataDir, consoleLogger);
|
|
904
906
|
const pairing = new system_1.AgentPairing({
|
|
905
907
|
nodeId: config.nodeId,
|
|
@@ -912,7 +914,16 @@ async function startAgent(configPath) {
|
|
|
912
914
|
meta: { hubUrl: installed.hubUrl, hubAddress: installed.hubAddress },
|
|
913
915
|
});
|
|
914
916
|
// The completion is answered first; the wire is replaced right after.
|
|
915
|
-
const timer = setTimeout(() =>
|
|
917
|
+
const timer = setTimeout(() => {
|
|
918
|
+
if (addonsBooted) {
|
|
919
|
+
void reconnect().then(advertise, advertise);
|
|
920
|
+
}
|
|
921
|
+
else {
|
|
922
|
+
// Booted unpaired: no addon was started (agent-boot-mode.ts). Relaunch (D5) so
|
|
923
|
+
// the core addons boot with the hub reachable.
|
|
924
|
+
(0, agent_update_service_js_1.scheduleAgentRestart)(consoleLogger, 'paired with the hub', config.dataDir);
|
|
925
|
+
}
|
|
926
|
+
}, 400);
|
|
916
927
|
timer.unref?.();
|
|
917
928
|
},
|
|
918
929
|
log: (message, meta) => consoleLogger.info(`pairing: ${message}`, meta ? { meta } : undefined),
|
|
@@ -951,6 +962,40 @@ async function startAgent(configPath) {
|
|
|
951
962
|
}).then((listener) => {
|
|
952
963
|
agentHttpListener = listener;
|
|
953
964
|
});
|
|
965
|
+
// Graceful shutdown
|
|
966
|
+
const shutdown = async () => {
|
|
967
|
+
console.log('[Agent] Shutting down...');
|
|
968
|
+
// Abort any in-flight upward hub registration retry loop.
|
|
969
|
+
registerAbortController.abort();
|
|
970
|
+
// Dispose the UDS event bridge to remove the parent-bus subscriber and
|
|
971
|
+
// clear the child-event handler, preventing subscriber leaks on shutdown.
|
|
972
|
+
udsEventBridgeDispose?.();
|
|
973
|
+
udsEventBridgeDispose = null;
|
|
974
|
+
for (const [, entry] of loadedAddons) {
|
|
975
|
+
if (entry.addon?.shutdown) {
|
|
976
|
+
try {
|
|
977
|
+
await entry.addon.shutdown();
|
|
978
|
+
}
|
|
979
|
+
catch {
|
|
980
|
+
/* */
|
|
981
|
+
}
|
|
982
|
+
}
|
|
983
|
+
}
|
|
984
|
+
// Withdraw the mDNS advertisement, then stop accepting new HTTP/HTTPS connections before
|
|
985
|
+
// the broker goes away.
|
|
986
|
+
await agentMdns.stop().catch(() => undefined);
|
|
987
|
+
await agentHttpListener?.close().catch(() => undefined);
|
|
988
|
+
await broker.stop();
|
|
989
|
+
process.exit(0);
|
|
990
|
+
};
|
|
991
|
+
process.on('SIGTERM', shutdown);
|
|
992
|
+
process.on('SIGINT', shutdown);
|
|
993
|
+
// An unpaired agent has no hub to read settings from (D857): serve pairing only and
|
|
994
|
+
// relaunch after the certificate is installed (D5). See agent-boot-mode.ts.
|
|
995
|
+
if (!addonsBooted) {
|
|
996
|
+
console.log(`[Agent] Node "${config.nodeId}" is unpaired - serving pairing only; addons boot after pairing`);
|
|
997
|
+
return;
|
|
998
|
+
}
|
|
954
999
|
// ── Phase 1: Load core infrastructure addons (in-process) ──
|
|
955
1000
|
// storage + settings + metrics + hub-forwarder (log destination)
|
|
956
1001
|
await bootCoreAddons(broker, config, capabilityRegistry, loadedAddons, loggerFactory);
|
|
@@ -1003,34 +1048,6 @@ async function startAgent(configPath) {
|
|
|
1003
1048
|
}
|
|
1004
1049
|
});
|
|
1005
1050
|
console.log(`[Agent] Node "${config.nodeId}" (name="${config.name}") ready — ${loadedAddons.size} addon(s) loaded`);
|
|
1006
|
-
// Graceful shutdown
|
|
1007
|
-
const shutdown = async () => {
|
|
1008
|
-
console.log('[Agent] Shutting down...');
|
|
1009
|
-
// Abort any in-flight upward hub registration retry loop.
|
|
1010
|
-
registerAbortController.abort();
|
|
1011
|
-
// Dispose the UDS event bridge to remove the parent-bus subscriber and
|
|
1012
|
-
// clear the child-event handler, preventing subscriber leaks on shutdown.
|
|
1013
|
-
udsEventBridgeDispose?.();
|
|
1014
|
-
udsEventBridgeDispose = null;
|
|
1015
|
-
for (const [, entry] of loadedAddons) {
|
|
1016
|
-
if (entry.addon?.shutdown) {
|
|
1017
|
-
try {
|
|
1018
|
-
await entry.addon.shutdown();
|
|
1019
|
-
}
|
|
1020
|
-
catch {
|
|
1021
|
-
/* */
|
|
1022
|
-
}
|
|
1023
|
-
}
|
|
1024
|
-
}
|
|
1025
|
-
// Withdraw the mDNS advertisement, then stop accepting new HTTP/HTTPS connections before
|
|
1026
|
-
// the broker goes away.
|
|
1027
|
-
await agentMdns.stop().catch(() => undefined);
|
|
1028
|
-
await agentHttpListener?.close().catch(() => undefined);
|
|
1029
|
-
await broker.stop();
|
|
1030
|
-
process.exit(0);
|
|
1031
|
-
};
|
|
1032
|
-
process.on('SIGTERM', shutdown);
|
|
1033
|
-
process.on('SIGINT', shutdown);
|
|
1034
1051
|
}
|
|
1035
1052
|
// ---------------------------------------------------------------------------
|
|
1036
1053
|
// Phase 1: Boot core addons (storage, settings, metrics — NO winston)
|
|
@@ -1217,7 +1234,10 @@ async function loadClusterCapableAddons(broker, config, capabilityRegistry, load
|
|
|
1217
1234
|
try {
|
|
1218
1235
|
await broker.call('$process.spawnRunner', {
|
|
1219
1236
|
runnerId: groupId,
|
|
1220
|
-
addons: addons.map((a) => ({
|
|
1237
|
+
addons: addons.map((a) => ({
|
|
1238
|
+
addonId: a.addonId,
|
|
1239
|
+
addonDir: a.addonDir,
|
|
1240
|
+
})),
|
|
1221
1241
|
});
|
|
1222
1242
|
// Shared with the reload path (`ensureGroupRunner`) so the boot and
|
|
1223
1243
|
// reload registrations can never drift — the drift was the in-process
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@camstack/server",
|
|
3
|
-
"version": "1.2.
|
|
3
|
+
"version": "1.2.676",
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
@@ -60,7 +60,7 @@
|
|
|
60
60
|
"@camstack/addon-post-analysis": "1.2.649",
|
|
61
61
|
"@camstack/develop": "0.1.38",
|
|
62
62
|
"@camstack/sdk": "1.2.154",
|
|
63
|
-
"@camstack/system": "1.2.
|
|
63
|
+
"@camstack/system": "1.2.507",
|
|
64
64
|
"@camstack/types": "1.2.436",
|
|
65
65
|
"@camstack/ui-library": "1.2.345",
|
|
66
66
|
"@fastify/compress": "^9.0.0",
|