@camstack/server 1.2.592 → 1.2.594
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-root-inventory.js +11 -50
- package/dist/agent/addon-scan.js +6 -44
- package/dist/agent/agent-addon-runtime.js +3 -8
- package/dist/agent/agent-addon-updates.js +12 -52
- package/dist/agent/agent-cap-dispatch-service.js +3 -5
- package/dist/agent/agent-config.js +7 -42
- package/dist/agent/agent-deploy-swap.js +5 -41
- package/dist/agent/agent-group-runner.js +8 -47
- package/dist/agent/agent-http-auth.js +10 -22
- package/dist/agent/agent-http.js +69 -115
- package/dist/agent/agent-hub-addon-update.js +10 -16
- package/dist/agent/agent-hub-registration.js +4 -7
- package/dist/agent/agent-infra-capabilities.js +5 -9
- package/dist/agent/agent-json-file.js +5 -42
- package/dist/agent/agent-mesh-gate.js +5 -8
- package/dist/agent/agent-node-certificates.js +25 -28
- package/dist/agent/agent-pairing-local.js +10 -47
- package/dist/agent/agent-pairing-routes.js +16 -20
- package/dist/agent/agent-pairing-store.js +18 -58
- package/dist/agent/agent-reconnect.js +1 -4
- package/dist/agent/agent-service.js +42 -78
- package/dist/agent/agent-sniffing-listener.js +11 -48
- package/dist/agent/agent-undeploy.js +5 -41
- package/dist/agent/agent-update-routes.js +14 -19
- package/dist/agent/agent-update-service.js +38 -80
- package/dist/agent/apply-model-distribution.js +1 -4
- package/dist/agent/apply-stage-dev-uploads.js +6 -9
- package/dist/agent/derive-hub-url.js +3 -8
- package/dist/agent/fetch-bundle-from-hub.js +6 -9
- package/dist/agent/hubs-found.js +6 -43
- package/dist/agent/infra-boot-guard.js +1 -4
- package/dist/agent/infra-boot-plan.js +2 -6
- package/dist/agent/main.js +158 -186
- package/dist/agent/register-agent-cap-dispatch.js +3 -6
- package/dist/agent/serial-queue.js +2 -7
- package/dist/agent-status-page.js +1 -4
- package/dist/api/addon-upload.js +22 -61
- package/dist/api/agent-addon-delivery.js +6 -11
- package/dist/api/auth-whoami.js +1 -4
- package/dist/api/backup-download-pump.js +5 -9
- package/dist/api/backup-download.js +7 -10
- package/dist/api/core/addon-settings.router.js +16 -19
- package/dist/api/core/agent-pairing.router.js +76 -79
- package/dist/api/core/agents.router.js +21 -24
- package/dist/api/core/auth-admin-tokens.procedures.js +48 -52
- package/dist/api/core/auth-device-cert.procedures.js +62 -67
- package/dist/api/core/auth-limits.js +16 -25
- package/dist/api/core/auth-reauth.procedures.js +32 -37
- package/dist/api/core/auth-revoke-credentials.procedures.js +22 -26
- package/dist/api/core/auth-sessions.procedures.js +52 -56
- package/dist/api/core/auth.router.js +300 -304
- package/dist/api/core/cap-providers.js +74 -121
- package/dist/api/core/capabilities.router.js +34 -37
- package/dist/api/core/capability-preference-writes.js +10 -17
- package/dist/api/core/certificates.router.js +106 -109
- package/dist/api/core/cluster-nodes.router.js +15 -18
- package/dist/api/core/collection-preference.js +2 -6
- package/dist/api/core/event-bus-proxy.router.js +34 -37
- package/dist/api/core/failure-contributions.js +4 -8
- package/dist/api/core/hwaccel.router.js +17 -20
- package/dist/api/core/integration-secrets.js +8 -12
- package/dist/api/core/lifecycle-job-runner.js +13 -49
- package/dist/api/core/live-events.router.js +29 -32
- package/dist/api/core/load-contributions.js +4 -8
- package/dist/api/core/logging-settings.js +30 -43
- package/dist/api/core/logs.router.js +40 -43
- package/dist/api/core/notifications.router.js +15 -18
- package/dist/api/core/public-event-filter.js +4 -8
- package/dist/api/core/repl.router.js +18 -21
- package/dist/api/core/request-census-settings.js +11 -16
- package/dist/api/core/server-management.provider.js +1 -4
- package/dist/api/core/server-name.js +9 -17
- package/dist/api/core/site-location.js +16 -24
- package/dist/api/core/stream-probe.router.js +21 -24
- package/dist/api/core/system-events.router.js +23 -26
- package/dist/api/cors/cors-policy.js +20 -29
- package/dist/api/cors/register-cors-policy.js +9 -14
- package/dist/api/deploy-stage-registry.js +6 -10
- package/dist/api/dev-uploads-bundle.js +12 -50
- package/dist/api/health/adaptive-probe.routes.js +9 -13
- package/dist/api/health/health.routes.js +8 -13
- package/dist/api/hub-cluster-url.js +3 -9
- package/dist/api/model-distributor.js +12 -50
- package/dist/api/oauth2/consent-page.js +10 -13
- package/dist/api/oauth2/oauth2-routes.js +17 -25
- package/dist/api/oauth2/private-host.js +1 -4
- package/dist/api/server-upload-propagate.js +15 -51
- package/dist/api/server-upload.js +13 -50
- package/dist/api/sse-no-compression.js +1 -4
- package/dist/api/static/frame-policy.js +4 -9
- package/dist/api/static/precompressed-asset.js +15 -57
- package/dist/api/static/spa-mount.js +8 -47
- package/dist/api/static/spa-static.js +5 -12
- package/dist/api/tarball-manifest.js +7 -44
- package/dist/api/trpc/cap-mount-helpers.js +7 -12
- package/dist/api/trpc/cap-route-error-formatter.js +10 -13
- package/dist/api/trpc/cap-router-runtime.js +40 -51
- package/dist/api/trpc/client-ip.js +9 -20
- package/dist/api/trpc/core-cap-bridge.js +32 -42
- package/dist/api/trpc/device-collection-dispatch.js +23 -27
- package/dist/api/trpc/device-config-secret-redaction.js +24 -40
- package/dist/api/trpc/generated-cap-mounts.js +219 -221
- package/dist/api/trpc/generated-cap-routers.js +4878 -4726
- package/dist/api/trpc/http-request-census-hook.js +8 -11
- package/dist/api/trpc/http-request-census.js +34 -41
- package/dist/api/trpc/http-request-census.singleton.js +4 -8
- package/dist/api/trpc/localized-schema-paths.js +1 -4
- package/dist/api/trpc/principal-visibility.js +14 -22
- package/dist/api/trpc/remote-addon-update-grant.js +1 -4
- package/dist/api/trpc/scope-access.js +10 -15
- package/dist/api/trpc/server-provided-caps.js +3 -7
- package/dist/api/trpc/share-view-access.js +6 -14
- package/dist/api/trpc/trpc-error-device-tags.js +3 -6
- package/dist/api/trpc/trpc-error-principal.js +2 -6
- package/dist/api/trpc/trpc.context.js +20 -25
- package/dist/api/trpc/trpc.middleware.js +38 -46
- package/dist/api/trpc/trpc.router.js +58 -99
- package/dist/api/trpc/user-error.js +5 -8
- package/dist/api/trpc/ws-request-census.js +17 -24
- package/dist/api/trpc/ws-slow-consumer-guard.js +11 -16
- package/dist/api/upload-auth.js +5 -9
- package/dist/auth/addon-route-jwt-gate.js +4 -7
- package/dist/auth/addon-route-share-gate.js +7 -12
- package/dist/auth/app-confirm-page.js +17 -22
- package/dist/auth/app-confirm-routes.js +26 -31
- package/dist/auth/app-confirmations.js +7 -44
- package/dist/auth/app-page-shell.js +17 -30
- package/dist/auth/app-page-strings.js +11 -17
- package/dist/auth/app-passkey-page.js +16 -21
- package/dist/auth/app-passkey-routes.js +37 -41
- package/dist/auth/app-refused-route.js +13 -18
- package/dist/auth/auth-network-policy.js +11 -15
- package/dist/auth/auth-provider-gate.js +4 -9
- package/dist/auth/auth-rate-limit.js +3 -7
- package/dist/auth/client-address.js +6 -9
- package/dist/auth/device-enroll-proofs.js +6 -43
- package/dist/auth/external-link-intents.js +3 -7
- package/dist/auth/hub-sessions.js +6 -12
- package/dist/auth/native-link-completions.js +7 -11
- package/dist/auth/native-return.js +9 -13
- package/dist/auth/passkey-provider.js +26 -32
- package/dist/auth/second-factors.js +6 -10
- package/dist/auth/session-connections.js +6 -12
- package/dist/auth/session-cookie.js +12 -23
- package/dist/auth/session-lifetimes.js +8 -12
- package/dist/auth/session-mint.js +4 -11
- package/dist/auth/sso-finish-app.js +13 -16
- package/dist/auth/sso-finish-deps.js +21 -27
- package/dist/auth/sso-finish.js +28 -38
- package/dist/auth/sso-routes.js +22 -25
- package/dist/auth/used-bridge-ids.js +1 -5
- package/dist/boot/boot-config.js +16 -55
- package/dist/boot/init-sequence.js +1 -4
- package/dist/boot/integration-id-backfill.js +3 -8
- package/dist/boot/platform-keychain-key.js +5 -42
- package/dist/boot/post-boot.service.js +14 -18
- package/dist/boot/reconcile-lifecycle-jobs.js +3 -6
- package/dist/boot/retired-public-url-env.js +4 -8
- package/dist/bootstrap-packages.js +1 -4
- package/dist/closure-node-modules.js +2 -38
- package/dist/closure-patches/patch-reach.json +6 -2
- package/dist/core/addon/addon-call-gateway.js +1 -5
- package/dist/core/addon/addon-package.service.js +83 -123
- package/dist/core/addon/addon-process-view.js +2 -6
- package/dist/core/addon/addon-realign-plan.js +1 -4
- package/dist/core/addon/addon-registry.service.js +254 -197
- package/dist/core/addon/addon-row-manifest.js +1 -4
- package/dist/core/addon/addon-search.service.js +3 -7
- package/dist/core/addon/addon-settings-provider.js +1 -3
- package/dist/core/addon/addon-uninstall.js +4 -11
- package/dist/core/addon/addon.tokens.js +2 -5
- package/dist/core/addon/device-meta-mirror.js +8 -13
- package/dist/core/addon/forked-custom-actions.js +6 -11
- package/dist/core/addon/integration-visibility.js +3 -6
- package/dist/core/addon/materialize-route-path.js +1 -4
- package/dist/core/addon/package-dir-utils.js +8 -45
- package/dist/core/addon/prune-misplaced-addons.js +5 -43
- package/dist/core/addon/runner-convergence.js +1 -4
- package/dist/core/addon/runner-serialization.js +1 -4
- package/dist/core/addon/runner-spawn-fanout.js +3 -8
- package/dist/core/addon/settings-door-wiring.js +5 -8
- package/dist/core/addon/single-flight-refresh.js +1 -4
- package/dist/core/addon-bridge/addon-bridge.service.js +7 -44
- package/dist/core/addon-pages/addon-pages.service.js +3 -40
- package/dist/core/addon-widgets/addon-widgets.service.js +4 -42
- package/dist/core/agent/agent-addon-backfill.js +9 -17
- package/dist/core/agent/agent-delivery-ledger.js +3 -7
- package/dist/core/agent/agent-liveness-event.js +2 -6
- package/dist/core/agent/agent-pairing-http.js +41 -45
- package/dist/core/agent/agent-registry.service.js +53 -92
- package/dist/core/agent/cluster-node-history-mirror.js +3 -7
- package/dist/core/agent/cluster-node-history-store.js +113 -58
- package/dist/core/agent/hub-agent-pairing.js +1 -5
- package/dist/core/agent/node-certificates-client.js +3 -6
- package/dist/core/agent/node-directory.js +1 -4
- package/dist/core/app-links/well-known-app-links.js +2 -6
- package/dist/core/auth/auth.service.js +3 -8
- package/dist/core/auth/handoff-code.service.js +11 -49
- package/dist/core/auth/record-kinds.js +35 -0
- package/dist/core/auth/share-token.service.js +174 -122
- package/dist/core/capability/capability.service.js +1 -5
- package/dist/core/config/config.schema.js +1 -6
- package/dist/core/config/config.service.js +2 -6
- package/dist/core/events/event-bus.service.js +3 -7
- package/dist/core/feature/feature.service.js +2 -6
- package/dist/core/lifecycle/lifecycle-runner.singleton.js +5 -10
- package/dist/core/lifecycle/lifecycle-state-machine.js +1 -5
- package/dist/core/logging/log-ring-buffer.js +1 -5
- package/dist/core/logging/logging.service.js +5 -9
- package/dist/core/logging/scoped-logger.js +1 -5
- package/dist/core/moleculer/agent-readiness-pull.js +1 -4
- package/dist/core/moleculer/agent-registration-request.js +3 -7
- package/dist/core/moleculer/cap-call-fn.js +39 -5
- package/dist/core/moleculer/cap-route-authority.js +3 -8
- package/dist/core/moleculer/hub-mesh-guard.js +5 -9
- package/dist/core/moleculer/moleculer.service.js +108 -119
- package/dist/core/network/network-quality.service.js +2 -6
- package/dist/core/notification/notification-wrapper.service.js +3 -7
- package/dist/core/notification/toast-wrapper.service.js +3 -7
- package/dist/core/provider/provider.tokens.js +1 -4
- package/dist/core/repl/repl-engine.service.js +4 -8
- package/dist/core/runner-health/runner-boot-check.js +7 -15
- package/dist/core/runner-health/update-preflight.js +9 -14
- package/dist/core/server-update/server-update.service.js +12 -49
- package/dist/core/server-update/system-apply-closure-patches.js +6 -42
- package/dist/core/server-update/system-ensure-prebuilds.js +3 -6
- package/dist/core/server-update/system-exec-npm.js +2 -5
- package/dist/core/storage/fs-storage-backend.js +1 -5
- package/dist/core/storage/storage-location-manager.js +1 -5
- package/dist/core/storage/storage.service.js +2 -6
- package/dist/core/streaming/ffmpeg-stream-info.js +3 -8
- package/dist/core/streaming/stream-probe.service.js +12 -16
- package/dist/core/streaming/ttl-cache.js +1 -5
- package/dist/core/topology/topology-emitter.service.js +19 -23
- package/dist/core/update-availability-emitter.js +3 -7
- package/dist/core/update-availability-store.js +8 -45
- package/dist/core/updates/agent-installed-packages.js +5 -9
- package/dist/core/updates/restart-marker.js +3 -8
- package/dist/core/updates/update-check-scheduler.js +13 -18
- package/dist/core/updates/wrapper-update-checker.js +3 -7
- package/dist/first-boot-addon-plan.js +2 -6
- package/dist/framework-nodepath.js +2 -38
- package/dist/i18n/request-lang.js +7 -11
- package/dist/launcher.js +30 -65
- package/dist/lifecycle-journal-path.js +2 -38
- package/dist/main.js +287 -324
- package/dist/manual-boot.js +120 -157
- package/dist/node-role.js +1 -4
- package/dist/package-inventory.js +7 -48
- package/dist/pending-restore.js +7 -43
- package/dist/single-copy-cleanup-runner.js +9 -45
- package/dist/single-copy-cleanup.js +7 -15
- package/dist/sqlite-restore.js +9 -48
- package/dist/starter.js +4 -39
- package/dist/ui-serving/lazy-ui-serving.js +3 -39
- package/package.json +13 -13
|
@@ -1,50 +1,12 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
if (k2 === undefined) k2 = k;
|
|
11
|
-
o[k2] = m[k];
|
|
12
|
-
}));
|
|
13
|
-
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
-
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
-
}) : function(o, v) {
|
|
16
|
-
o["default"] = v;
|
|
17
|
-
});
|
|
18
|
-
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
-
var ownKeys = function(o) {
|
|
20
|
-
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
-
var ar = [];
|
|
22
|
-
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
-
return ar;
|
|
24
|
-
};
|
|
25
|
-
return ownKeys(o);
|
|
26
|
-
};
|
|
27
|
-
return function (mod) {
|
|
28
|
-
if (mod && mod.__esModule) return mod;
|
|
29
|
-
var result = {};
|
|
30
|
-
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
-
__setModuleDefault(result, mod);
|
|
32
|
-
return result;
|
|
33
|
-
};
|
|
34
|
-
})();
|
|
35
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
-
exports.AgentRegistryService = exports.AGENT_BACKFILL_RPC_TIMEOUT_MS = void 0;
|
|
37
|
-
exports.toNodeLiveness = toNodeLiveness;
|
|
38
|
-
exports.toDescriptor = toDescriptor;
|
|
39
|
-
const node_crypto_1 = require("node:crypto");
|
|
40
|
-
const os = __importStar(require("node:os"));
|
|
41
|
-
const system_1 = require("@camstack/system");
|
|
42
|
-
const types_1 = require("@camstack/types");
|
|
43
|
-
const agent_addon_backfill_1 = require("./agent-addon-backfill");
|
|
44
|
-
const agent_delivery_ledger_1 = require("./agent-delivery-ledger");
|
|
45
|
-
const agent_liveness_event_1 = require("./agent-liveness-event");
|
|
46
|
-
const cluster_node_history_mirror_1 = require("./cluster-node-history-mirror");
|
|
47
|
-
const node_directory_1 = require("./node-directory");
|
|
1
|
+
import { randomUUID } from 'node:crypto';
|
|
2
|
+
import * as os from 'node:os';
|
|
3
|
+
import { callWithServiceDiscovery, getProcessAgentHttpsNames, localSupportedPythonRuntimes, } from '@camstack/system';
|
|
4
|
+
import { EventCategory, resolveAddonPlacement } from '@camstack/types';
|
|
5
|
+
import { BackfillAttemptTracker, computeBackfillPlan, confirmBackfillPlan, executeBackfill, MAX_BACKFILL_ATTEMPTS, triggerMayDeliver, } from './agent-addon-backfill';
|
|
6
|
+
import { AgentDeliveryLedger } from './agent-delivery-ledger';
|
|
7
|
+
import { agentOfflineData, nodeDisplayName } from './agent-liveness-event';
|
|
8
|
+
import { ClusterNodeHistoryMirror } from './cluster-node-history-mirror';
|
|
9
|
+
import { toNodeDirectory } from './node-directory';
|
|
48
10
|
/** Turn a forget outcome into the sentence the operator reads. */
|
|
49
11
|
function describeForgetOutcome(nodeId, history, registryRemoved, stillListed) {
|
|
50
12
|
const parts = [];
|
|
@@ -72,7 +34,7 @@ const AGENT_RECONCILE_RPC_TIMEOUT_MS = 8_000;
|
|
|
72
34
|
* and a timeout here aborts the call even though the deploy already landed.
|
|
73
35
|
* Matches the `addons.updatePackage` agent path.
|
|
74
36
|
*/
|
|
75
|
-
|
|
37
|
+
export const AGENT_BACKFILL_RPC_TIMEOUT_MS = 300_000;
|
|
76
38
|
/**
|
|
77
39
|
* Package name of the system/infrastructure builtins. Addons shipped in
|
|
78
40
|
* `@camstack/system` (filesystem-storage, storage-orchestrator,
|
|
@@ -127,7 +89,7 @@ function rosterFromAddons(addons) {
|
|
|
127
89
|
* Child runner ids (`hub/foo`, `agent/bar`) are processes, not cluster
|
|
128
90
|
* nodes — excluded, same rule as `listNodes()` / `classifyNode`.
|
|
129
91
|
*/
|
|
130
|
-
function toNodeLiveness(nodes) {
|
|
92
|
+
export function toNodeLiveness(nodes) {
|
|
131
93
|
return (nodes
|
|
132
94
|
// A Moleculer registry can transiently hold a malformed entry with no id
|
|
133
95
|
// (seen live 2026-07-16 after agent churn): guard it or every consumer of
|
|
@@ -141,7 +103,7 @@ function toNodeLiveness(nodes) {
|
|
|
141
103
|
* cpuModel `undefined`→`null`, addonIds from the reported `agentAddons`) so an
|
|
142
104
|
* offline row rendered from history is indistinguishable from the live shape.
|
|
143
105
|
*/
|
|
144
|
-
function toDescriptor(entry) {
|
|
106
|
+
export function toDescriptor(entry) {
|
|
145
107
|
return {
|
|
146
108
|
id: entry.info.id,
|
|
147
109
|
name: entry.info.name,
|
|
@@ -175,7 +137,7 @@ function toSubProcess(p) {
|
|
|
175
137
|
groupId: p.groupId ?? null,
|
|
176
138
|
};
|
|
177
139
|
}
|
|
178
|
-
class AgentRegistryService {
|
|
140
|
+
export class AgentRegistryService {
|
|
179
141
|
eventBus;
|
|
180
142
|
moleculer;
|
|
181
143
|
capabilityService;
|
|
@@ -221,14 +183,14 @@ class AgentRegistryService {
|
|
|
221
183
|
* Bounded per-`(node, package)` delivery breaker — see
|
|
222
184
|
* `agent-addon-backfill.ts`. Process-scoped, holds no intent.
|
|
223
185
|
*/
|
|
224
|
-
backfillTracker = new
|
|
186
|
+
backfillTracker = new BackfillAttemptTracker();
|
|
225
187
|
/**
|
|
226
188
|
* "Is the hub writing addons to this node right now?" — the gate that stops
|
|
227
189
|
* the back-fill reacting to a roster gap the hub itself opened. Public so the
|
|
228
190
|
* delivery path (`deliverAddonToAgent`) can mark its own window; see
|
|
229
191
|
* `agent-delivery-ledger.ts` for why a delivery makes the roster lie.
|
|
230
192
|
*/
|
|
231
|
-
deliveryLedger = new
|
|
193
|
+
deliveryLedger = new AgentDeliveryLedger();
|
|
232
194
|
/**
|
|
233
195
|
* Nodes with a reconcile in flight. The pass is triggered from two places
|
|
234
196
|
* (the `registerNode` ack and the hub-boot sweep) and a reconnect can fire
|
|
@@ -248,7 +210,7 @@ class AgentRegistryService {
|
|
|
248
210
|
/** Wire the durable offline-node history store (A1). */
|
|
249
211
|
setClusterNodeHistoryStore(store) {
|
|
250
212
|
this.historyStore = store;
|
|
251
|
-
this.historyMirror = new
|
|
213
|
+
this.historyMirror = new ClusterNodeHistoryMirror(() => store.tryGetAll());
|
|
252
214
|
}
|
|
253
215
|
/** Wire the scoped logger (boot order — see the field). */
|
|
254
216
|
setLogger(logger) {
|
|
@@ -296,10 +258,10 @@ class AgentRegistryService {
|
|
|
296
258
|
await this.historyStore?.prunePackages(nodeId, [packageName]);
|
|
297
259
|
for (const addonId of addonIds) {
|
|
298
260
|
this.eventBus.emit({
|
|
299
|
-
id:
|
|
261
|
+
id: randomUUID(),
|
|
300
262
|
timestamp: new Date(),
|
|
301
263
|
source: { type: 'core', id: 'agent-registry' },
|
|
302
|
-
category:
|
|
264
|
+
category: EventCategory.AddonUninstalled,
|
|
303
265
|
data: { addonId, agentId: nodeId, packageName, reason: 'operator uninstall' },
|
|
304
266
|
});
|
|
305
267
|
}
|
|
@@ -380,7 +342,7 @@ class AgentRegistryService {
|
|
|
380
342
|
this.backfillTracker.forget(nodeId);
|
|
381
343
|
this.deliveryLedger.forget(nodeId);
|
|
382
344
|
// The names the hub certified to this node are free again (a forgotten node cannot hold them).
|
|
383
|
-
await
|
|
345
|
+
await getProcessAgentHttpsNames()
|
|
384
346
|
?.release(nodeId)
|
|
385
347
|
.catch((err) => this.logger?.warn("forget cluster node: could not release the node's certified names", {
|
|
386
348
|
tags: { nodeId },
|
|
@@ -399,10 +361,10 @@ class AgentRegistryService {
|
|
|
399
361
|
// `AgentUnregistered` and re-emits immediately.
|
|
400
362
|
if (historyRemoved || registryRemoved) {
|
|
401
363
|
this.eventBus.emit({
|
|
402
|
-
id:
|
|
364
|
+
id: randomUUID(),
|
|
403
365
|
timestamp: new Date(),
|
|
404
366
|
source: { type: 'core', id: 'agent-registry' },
|
|
405
|
-
category:
|
|
367
|
+
category: EventCategory.AgentUnregistered,
|
|
406
368
|
data: { agentId: nodeId },
|
|
407
369
|
});
|
|
408
370
|
}
|
|
@@ -477,19 +439,19 @@ class AgentRegistryService {
|
|
|
477
439
|
console.log(`[agent-registry] Agent connected: ${node.id}`);
|
|
478
440
|
const nodeName = this.knownNodeName(node.id);
|
|
479
441
|
this.eventBus.emit({
|
|
480
|
-
id:
|
|
442
|
+
id: randomUUID(),
|
|
481
443
|
timestamp: new Date(),
|
|
482
444
|
source: { type: 'core', id: 'agent-registry' },
|
|
483
|
-
category:
|
|
445
|
+
category: EventCategory.AgentOnline,
|
|
484
446
|
data: { agentId: node.id, ...(nodeName !== undefined ? { nodeName } : {}) },
|
|
485
447
|
});
|
|
486
448
|
}
|
|
487
449
|
else {
|
|
488
450
|
this.eventBus.emit({
|
|
489
|
-
id:
|
|
451
|
+
id: randomUUID(),
|
|
490
452
|
timestamp: new Date(),
|
|
491
453
|
source: { type: 'core', id: 'agent-registry' },
|
|
492
|
-
category:
|
|
454
|
+
category: EventCategory.WorkerOnline,
|
|
493
455
|
data: { workerId: node.id },
|
|
494
456
|
});
|
|
495
457
|
}
|
|
@@ -505,19 +467,19 @@ class AgentRegistryService {
|
|
|
505
467
|
// node was never snapshotted while online.
|
|
506
468
|
void this.historyStore?.touch(node.id);
|
|
507
469
|
this.eventBus.emit({
|
|
508
|
-
id:
|
|
470
|
+
id: randomUUID(),
|
|
509
471
|
timestamp: new Date(),
|
|
510
472
|
source: { type: 'core', id: 'agent-registry' },
|
|
511
|
-
category:
|
|
512
|
-
data:
|
|
473
|
+
category: EventCategory.AgentOffline,
|
|
474
|
+
data: agentOfflineData(node.id, unexpected, this.knownNodeName(node.id)),
|
|
513
475
|
});
|
|
514
476
|
}
|
|
515
477
|
else {
|
|
516
478
|
this.eventBus.emit({
|
|
517
|
-
id:
|
|
479
|
+
id: randomUUID(),
|
|
518
480
|
timestamp: new Date(),
|
|
519
481
|
source: { type: 'core', id: 'agent-registry' },
|
|
520
|
-
category:
|
|
482
|
+
category: EventCategory.WorkerOffline,
|
|
521
483
|
data: { workerId: node.id },
|
|
522
484
|
});
|
|
523
485
|
}
|
|
@@ -526,7 +488,7 @@ class AgentRegistryService {
|
|
|
526
488
|
// connected when the listener registers. Classifies each as
|
|
527
489
|
// agent or worker — same logic as the live handlers above.
|
|
528
490
|
try {
|
|
529
|
-
const registry = this.
|
|
491
|
+
const registry = this.nodeCatalogRegistry();
|
|
530
492
|
const existing = registry?.getNodeList?.({ onlyAvailable: true }) ?? [];
|
|
531
493
|
for (const { id } of existing) {
|
|
532
494
|
const kind = classifyNode(id);
|
|
@@ -534,19 +496,19 @@ class AgentRegistryService {
|
|
|
534
496
|
continue;
|
|
535
497
|
if (kind === 'agent') {
|
|
536
498
|
this.eventBus.emit({
|
|
537
|
-
id:
|
|
499
|
+
id: randomUUID(),
|
|
538
500
|
timestamp: new Date(),
|
|
539
501
|
source: { type: 'core', id: 'agent-registry' },
|
|
540
|
-
category:
|
|
502
|
+
category: EventCategory.AgentOnline,
|
|
541
503
|
data: { agentId: id },
|
|
542
504
|
});
|
|
543
505
|
}
|
|
544
506
|
else {
|
|
545
507
|
this.eventBus.emit({
|
|
546
|
-
id:
|
|
508
|
+
id: randomUUID(),
|
|
547
509
|
timestamp: new Date(),
|
|
548
510
|
source: { type: 'core', id: 'agent-registry' },
|
|
549
|
-
category:
|
|
511
|
+
category: EventCategory.WorkerOnline,
|
|
550
512
|
data: { workerId: id },
|
|
551
513
|
});
|
|
552
514
|
}
|
|
@@ -558,7 +520,7 @@ class AgentRegistryService {
|
|
|
558
520
|
}
|
|
559
521
|
/** The durable history's display name for a node, when it knows a real one. */
|
|
560
522
|
knownNodeName(nodeId) {
|
|
561
|
-
return
|
|
523
|
+
return nodeDisplayName(nodeId, this.historyMirror?.peek() ?? null);
|
|
562
524
|
}
|
|
563
525
|
// ---- Placement reconciliation ----
|
|
564
526
|
/**
|
|
@@ -571,7 +533,7 @@ class AgentRegistryService {
|
|
|
571
533
|
* must not abort the pass or hub boot.
|
|
572
534
|
*/
|
|
573
535
|
async reconcileConnectedAgents() {
|
|
574
|
-
const registry = this.
|
|
536
|
+
const registry = this.nodeCatalogRegistry();
|
|
575
537
|
const nodes = registry?.getNodeList?.({ onlyAvailable: true }) ?? [];
|
|
576
538
|
const agentIds = nodes
|
|
577
539
|
.map((n) => n.id)
|
|
@@ -655,7 +617,7 @@ class AgentRegistryService {
|
|
|
655
617
|
// waitForServices primitive) and retries once, instead of giving up and
|
|
656
618
|
// leaving the agent unreconciled until the next connect. (No timers/backoff
|
|
657
619
|
// — that's banned for node readiness; this is the sanctioned primitive.)
|
|
658
|
-
const statusRaw = await
|
|
620
|
+
const statusRaw = await callWithServiceDiscovery(broker, '$agent', '$agent.status', {}, {
|
|
659
621
|
nodeID: agentId,
|
|
660
622
|
timeout: AGENT_RECONCILE_RPC_TIMEOUT_MS,
|
|
661
623
|
});
|
|
@@ -680,7 +642,7 @@ class AgentRegistryService {
|
|
|
680
642
|
if (typeof declId !== 'string')
|
|
681
643
|
continue;
|
|
682
644
|
const decl = row.declaration ?? row.manifest;
|
|
683
|
-
hubPlacements.set(declId,
|
|
645
|
+
hubPlacements.set(declId, resolveAddonPlacement(decl));
|
|
684
646
|
const packageName = row.manifest.packageName;
|
|
685
647
|
if (typeof packageName === 'string' && packageName.length > 0) {
|
|
686
648
|
hubPackages.add(packageName);
|
|
@@ -743,10 +705,10 @@ class AgentRegistryService {
|
|
|
743
705
|
undeployedPackages.add(packageName);
|
|
744
706
|
}
|
|
745
707
|
this.eventBus.emit({
|
|
746
|
-
id:
|
|
708
|
+
id: randomUUID(),
|
|
747
709
|
timestamp: new Date(),
|
|
748
710
|
source: { type: 'core', id: 'agent-registry' },
|
|
749
|
-
category:
|
|
711
|
+
category: EventCategory.AddonUninstalled,
|
|
750
712
|
data: { addonId: addon.id, agentId, reason },
|
|
751
713
|
});
|
|
752
714
|
}
|
|
@@ -788,7 +750,7 @@ class AgentRegistryService {
|
|
|
788
750
|
if (!seam)
|
|
789
751
|
return;
|
|
790
752
|
const recorded = await store.getPackages(agentId);
|
|
791
|
-
const planned =
|
|
753
|
+
const planned = computeBackfillPlan({
|
|
792
754
|
recorded,
|
|
793
755
|
live,
|
|
794
756
|
bootstrap: AGENT_BOOTSTRAP_PACKAGES,
|
|
@@ -808,7 +770,7 @@ class AgentRegistryService {
|
|
|
808
770
|
}
|
|
809
771
|
// GATE 1 — the trigger allowlist. A pass that must not install says so and
|
|
810
772
|
// stops; silence here would read as "nothing was missing".
|
|
811
|
-
if (!
|
|
773
|
+
if (!triggerMayDeliver(trigger)) {
|
|
812
774
|
console.log(`[agent-registry] Back-fill ${agentId}: SKIPPED — trigger "${trigger}" may not deliver ` +
|
|
813
775
|
`(${planned.targets.length} package(s) would have been installed)`);
|
|
814
776
|
return;
|
|
@@ -838,7 +800,7 @@ class AgentRegistryService {
|
|
|
838
800
|
const closeWindow = this.deliveryLedger.begin(agentId, plan.targets.map((t) => t.name).join(', ') || 'back-fill');
|
|
839
801
|
let outcome;
|
|
840
802
|
try {
|
|
841
|
-
outcome = await
|
|
803
|
+
outcome = await executeBackfill(seam, agentId, plan, this.backfillTracker);
|
|
842
804
|
}
|
|
843
805
|
finally {
|
|
844
806
|
closeWindow();
|
|
@@ -849,10 +811,10 @@ class AgentRegistryService {
|
|
|
849
811
|
.join(', ')} — trigger=${trigger}, node reported ${plan.liveCount} package(s) and its ` +
|
|
850
812
|
`declared roster has ${recorded.length}`);
|
|
851
813
|
this.eventBus.emit({
|
|
852
|
-
id:
|
|
814
|
+
id: randomUUID(),
|
|
853
815
|
timestamp: new Date(),
|
|
854
816
|
source: { type: 'core', id: 'agent-registry' },
|
|
855
|
-
category:
|
|
817
|
+
category: EventCategory.AddonInstalled,
|
|
856
818
|
data: {
|
|
857
819
|
agentId,
|
|
858
820
|
packages: outcome.delivered.map((d) => `${d.name}@${d.version}`),
|
|
@@ -864,7 +826,7 @@ class AgentRegistryService {
|
|
|
864
826
|
for (const failure of outcome.failed) {
|
|
865
827
|
console.error(`[agent-registry] Back-fill ${agentId}: FAILED to deliver ${failure.name}@${failure.version} — ${failure.error}` +
|
|
866
828
|
(failure.retired
|
|
867
|
-
? ` (retired after ${
|
|
829
|
+
? ` (retired after ${MAX_BACKFILL_ATTEMPTS} attempts; this node is running WITHOUT that package)`
|
|
868
830
|
: ''));
|
|
869
831
|
}
|
|
870
832
|
for (const name of outcome.skipped) {
|
|
@@ -899,7 +861,7 @@ class AgentRegistryService {
|
|
|
899
861
|
console.warn(`[agent-registry] Back-fill ${agentId}: SKIPPED — the confirmation read carried no addon list`);
|
|
900
862
|
return null;
|
|
901
863
|
}
|
|
902
|
-
const { plan: confirmed, contradicted } =
|
|
864
|
+
const { plan: confirmed, contradicted } = confirmBackfillPlan(plan, rosterFromAddons(secondAddons));
|
|
903
865
|
if (contradicted.length > 0) {
|
|
904
866
|
console.warn(`[agent-registry] Back-fill ${agentId}: two roster reads DISAGREE — ` +
|
|
905
867
|
`${contradicted.map((t) => t.name).join(', ')} reported absent then present. ` +
|
|
@@ -965,10 +927,10 @@ class AgentRegistryService {
|
|
|
965
927
|
*/
|
|
966
928
|
async listNodeDirectory() {
|
|
967
929
|
const history = this.historyMirror ? await this.historyMirror.current() : null;
|
|
968
|
-
return
|
|
930
|
+
return toNodeDirectory(this.listNodeLiveness(), history);
|
|
969
931
|
}
|
|
970
932
|
async listNodes() {
|
|
971
|
-
const registry = this.
|
|
933
|
+
const registry = this.nodeCatalogRegistry();
|
|
972
934
|
// `onlyAvailable: false` intentionally includes nodes Moleculer still
|
|
973
935
|
// remembers as disconnected (`available: false`) — the same registry
|
|
974
936
|
// read `listNodeLiveness()` uses for `/health`. This surfaces recently
|
|
@@ -1164,7 +1126,7 @@ class AgentRegistryService {
|
|
|
1164
1126
|
cpuCores: cpus.length,
|
|
1165
1127
|
memoryMB: Math.round(os.totalmem() / 1024 / 1024),
|
|
1166
1128
|
cpuModel: cpus[0]?.model,
|
|
1167
|
-
pythonRuntimes:
|
|
1129
|
+
pythonRuntimes: localSupportedPythonRuntimes(),
|
|
1168
1130
|
},
|
|
1169
1131
|
status: {
|
|
1170
1132
|
activeCameras: 0,
|
|
@@ -1205,12 +1167,11 @@ class AgentRegistryService {
|
|
|
1205
1167
|
const promoted = { ...backup, priority: 'primary' };
|
|
1206
1168
|
this.assignments.set(primaryKey, promoted);
|
|
1207
1169
|
this.eventBus.emit({
|
|
1208
|
-
id:
|
|
1170
|
+
id: randomUUID(),
|
|
1209
1171
|
timestamp: new Date(),
|
|
1210
1172
|
source: { type: 'core', id: 'agent-registry' },
|
|
1211
|
-
category:
|
|
1173
|
+
category: EventCategory.AgentBackupActivated,
|
|
1212
1174
|
data: { cameraId, role, agentId: promoted.agentId },
|
|
1213
1175
|
});
|
|
1214
1176
|
}
|
|
1215
1177
|
}
|
|
1216
|
-
exports.AgentRegistryService = AgentRegistryService;
|
|
@@ -1,9 +1,6 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.ClusterNodeHistoryMirror = exports.HISTORY_MIRROR_MAX_AGE_MS = void 0;
|
|
4
1
|
/** Two topology heartbeats: a mirror older than this was not being fed. */
|
|
5
|
-
|
|
6
|
-
class ClusterNodeHistoryMirror {
|
|
2
|
+
export const HISTORY_MIRROR_MAX_AGE_MS = 60_000;
|
|
3
|
+
export class ClusterNodeHistoryMirror {
|
|
7
4
|
read;
|
|
8
5
|
now;
|
|
9
6
|
maxAgeMs;
|
|
@@ -11,7 +8,7 @@ class ClusterNodeHistoryMirror {
|
|
|
11
8
|
inFlight = null;
|
|
12
9
|
/** Bumped by `invalidate()`: a read started before it must not land. */
|
|
13
10
|
generation = 0;
|
|
14
|
-
constructor(read, now = Date.now, maxAgeMs =
|
|
11
|
+
constructor(read, now = Date.now, maxAgeMs = HISTORY_MIRROR_MAX_AGE_MS) {
|
|
15
12
|
this.read = read;
|
|
16
13
|
this.now = now;
|
|
17
14
|
this.maxAgeMs = maxAgeMs;
|
|
@@ -57,4 +54,3 @@ class ClusterNodeHistoryMirror {
|
|
|
57
54
|
this.inFlight = null;
|
|
58
55
|
}
|
|
59
56
|
}
|
|
60
|
-
exports.ClusterNodeHistoryMirror = ClusterNodeHistoryMirror;
|