@camstack/system 1.2.437 → 1.2.439
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 +64 -12
- package/dist/addon-runner.mjs +65 -13
- package/dist/{agent-https-BZIwS4xF.js → agent-https-DlpTMDqA.js} +252 -22
- package/dist/{agent-https-BPfHrI4c.mjs → agent-https-U0d4uvn2.mjs} +211 -23
- 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.js +7 -1
- package/dist/builtins/alerts/alerts.addon.mjs +7 -1
- package/dist/builtins/autotrack/index.js +1 -1
- package/dist/builtins/autotrack/index.mjs +1 -1
- package/dist/builtins/backup-orchestrator/backup-orchestrator.addon.js +2 -2
- package/dist/builtins/backup-orchestrator/backup-orchestrator.addon.mjs +2 -2
- package/dist/builtins/calendars/calendars.addon.js +1 -1
- package/dist/builtins/calendars/calendars.addon.mjs +1 -1
- package/dist/builtins/camera-grid/index.js +9 -1
- package/dist/builtins/camera-grid/index.mjs +9 -1
- package/dist/builtins/composer/composer.addon.js +2 -2
- package/dist/builtins/composer/composer.addon.mjs +2 -2
- package/dist/builtins/console-logging/index.js +12 -5
- package/dist/builtins/console-logging/index.mjs +12 -5
- package/dist/builtins/core-blocks/core-blocks.addon.js +2 -2
- package/dist/builtins/core-blocks/core-blocks.addon.mjs +2 -2
- package/dist/builtins/device-manager/device-manager.addon.d.ts +5 -0
- package/dist/builtins/device-manager/device-manager.addon.js +717 -28
- package/dist/builtins/device-manager/device-manager.addon.mjs +717 -28
- package/dist/builtins/device-manager/device-meta-types.d.ts +4 -0
- package/dist/builtins/device-manager/device-provider-context.d.ts +9 -0
- package/dist/builtins/device-manager/device-removal-hooks.d.ts +103 -0
- package/dist/builtins/device-manager/device-row-store.d.ts +1 -0
- package/dist/builtins/device-manager/device-tombstone-store.d.ts +68 -0
- package/dist/builtins/device-manager/removal-cleanup.d.ts +50 -0
- package/dist/builtins/hub-forwarder/index.js +1 -1
- package/dist/builtins/hub-forwarder/index.mjs +1 -1
- package/dist/builtins/keychain/index.js +37 -4
- package/dist/builtins/keychain/index.mjs +37 -4
- package/dist/builtins/keychain/keychain-service.d.ts +14 -0
- package/dist/builtins/keychain/keychain-store.d.ts +1 -1
- package/dist/builtins/liveness-monitor/liveness-monitor.addon.js +1 -1
- package/dist/builtins/liveness-monitor/liveness-monitor.addon.mjs +1 -1
- package/dist/builtins/local-auth/local-auth.addon.js +12 -12
- package/dist/builtins/local-auth/local-auth.addon.mjs +12 -12
- package/dist/builtins/local-network/local-network.addon.js +16 -2
- package/dist/builtins/local-network/local-network.addon.mjs +16 -2
- package/dist/builtins/loki-logging/index.js +28 -5
- package/dist/builtins/loki-logging/index.mjs +28 -5
- package/dist/builtins/native-metrics/native-metrics.addon.js +11 -1
- package/dist/builtins/native-metrics/native-metrics.addon.mjs +11 -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 +11 -1
- package/dist/builtins/snapshot/index.mjs +11 -1
- package/dist/builtins/sqlite-storage/filesystem-storage.addon.js +4 -1
- package/dist/builtins/sqlite-storage/filesystem-storage.addon.mjs +4 -1
- package/dist/builtins/sqlite-storage/index.js +1 -1
- package/dist/builtins/sqlite-storage/index.mjs +1 -1
- package/dist/builtins/sqlite-storage/sqlite-settings.addon.js +3 -3
- package/dist/builtins/sqlite-storage/sqlite-settings.addon.mjs +3 -3
- package/dist/builtins/storage-orchestrator/storage-orchestrator.addon.js +1 -1
- package/dist/builtins/storage-orchestrator/storage-orchestrator.addon.mjs +1 -1
- package/dist/builtins/system-config/system-config.addon.js +22 -4
- package/dist/builtins/system-config/system-config.addon.mjs +22 -4
- package/dist/builtins/winston-logging/index.js +14 -5
- package/dist/builtins/winston-logging/index.mjs +14 -5
- package/dist/{composition-sources-BIT8IUKm.js → composition-sources-B4jC2FC7.js} +1 -1
- package/dist/{composition-sources-tpYR0f1x.mjs → composition-sources-BGOSCGWa.mjs} +1 -1
- package/dist/{constants-Bc6trhoW.mjs → constants-B92BjObl.mjs} +1 -1
- package/dist/{constants-CwRY32Nx.js → constants-BRsjQwi-.js} +1 -1
- package/dist/{device-ca-BhdBByGD.mjs → device-ca-46BUsWD1.mjs} +2 -2
- package/dist/{device-ca-DImD8IzR.js → device-ca-DHG9OW2m.js} +2 -2
- package/dist/{dist-CEAyXW3Q.js → dist-BOWdLjoK.js} +341 -13
- package/dist/{dist-m5JkT8UN.mjs → dist-yI6kF6r6.mjs} +306 -14
- package/dist/file-host-worker.js +1 -1
- package/dist/file-host-worker.mjs +1 -1
- package/dist/{hub-mdns-ciao-CBLvq2oj.js → hub-mdns-ciao-D7S5AJRU.js} +377 -69
- package/dist/{hub-mdns-ciao-DMlQTdPU.mjs → hub-mdns-ciao-DGwVc2uh.mjs} +344 -72
- package/dist/i18n/catalog-registry.d.ts +35 -0
- package/dist/i18n/index.d.ts +2 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.js +698 -22
- package/dist/index.mjs +681 -24
- package/dist/kernel/gc-census.d.ts +18 -1
- package/dist/kernel/settings-view-types.d.ts +2 -0
- package/dist/kernel/transport/local-transport.d.ts +3 -0
- package/dist/kernel/transport/peer-answered-error.d.ts +5 -1
- package/dist/{lib-NNxHSOIE.js → lib-8oZrELLm.js} +1 -1
- package/dist/{lib-BeGzVQcd.mjs → lib-DK38ompL.mjs} +1 -1
- package/dist/{restore-archive-DNxAStrJ.mjs → restore-archive-CpdUO-uS.mjs} +1 -1
- package/dist/{restore-archive-C75srVbG.js → restore-archive-DiGiI6Jp.js} +1 -1
- package/dist/{retired-settings-keys-DNfV28R_.js → retired-settings-keys-CyQ7uvta.js} +1 -1
- package/dist/{retired-settings-keys-C5qP9QIf.mjs → retired-settings-keys-UsVtLOT0.mjs} +1 -1
- package/dist/tls/agent-https.d.ts +2 -2
- package/dist/tls/boot-tls.d.ts +6 -0
- package/dist/tls/cert-evaluation.d.ts +1 -1
- package/dist/tls/cert-issue.d.ts +5 -1
- package/dist/tls/cert-manager.d.ts +18 -0
- package/dist/tls/cert-name-constraints.d.ts +53 -0
- package/dist/tls/index.d.ts +5 -4
- package/dist/tls/tls-actions.d.ts +27 -7
- package/dist/tls/tls-status.d.ts +22 -0
- package/dist/tls/uploaded-cert.d.ts +36 -4
- package/dist/{wal-maintenance-Ch79gy9S.js → wal-maintenance-DEL_jeG0.js} +0 -0
- package/dist/{wal-maintenance-DvnVO5IK.mjs → wal-maintenance-xsvdT5Go.mjs} +0 -0
- package/dist/{x509.es-r7Ht1thA.js → x509.es-C4cOo48M.js} +36 -0
- package/dist/{x509.es-CDvj67p1.mjs → x509.es-DK__ETIe.mjs} +1 -1
- package/package.json +3 -1
package/dist/addon-runner.js
CHANGED
|
@@ -1578,7 +1578,8 @@ function formatOutboundQueueVerdict(label, verdict) {
|
|
|
1578
1578
|
}
|
|
1579
1579
|
//#endregion
|
|
1580
1580
|
//#region src/kernel/gc-census.ts
|
|
1581
|
-
function countsOf(entries, kinds) {
|
|
1581
|
+
function countsOf(entries, kinds, flagBits) {
|
|
1582
|
+
const flags = {};
|
|
1582
1583
|
let majors = 0;
|
|
1583
1584
|
let minors = 0;
|
|
1584
1585
|
let incrementals = 0;
|
|
@@ -1588,13 +1589,17 @@ function countsOf(entries, kinds) {
|
|
|
1588
1589
|
else if (e.kind === kinds.minor) minors++;
|
|
1589
1590
|
else if (e.kind === kinds.incremental) incrementals++;
|
|
1590
1591
|
pauseMs += e.durationMs;
|
|
1592
|
+
if (e.flags !== void 0) {
|
|
1593
|
+
for (const f of flagBits) if ((e.flags & f.bit) !== 0) flags[f.name] = (flags[f.name] ?? 0) + 1;
|
|
1594
|
+
}
|
|
1591
1595
|
}
|
|
1592
1596
|
return {
|
|
1593
1597
|
majors,
|
|
1594
1598
|
minors,
|
|
1595
1599
|
incrementals,
|
|
1596
1600
|
pauseMs,
|
|
1597
|
-
windowMs: 0
|
|
1601
|
+
windowMs: 0,
|
|
1602
|
+
...Object.keys(flags).length > 0 ? { flags } : {}
|
|
1598
1603
|
};
|
|
1599
1604
|
}
|
|
1600
1605
|
/**
|
|
@@ -1606,7 +1611,7 @@ function countsOf(entries, kinds) {
|
|
|
1606
1611
|
* observed and a process that is not collecting look identical on the line, and
|
|
1607
1612
|
* they are the two answers furthest apart.
|
|
1608
1613
|
*/
|
|
1609
|
-
function createGcCensus(install, kinds, startedAt) {
|
|
1614
|
+
function createGcCensus(install, kinds, startedAt, flagBits = []) {
|
|
1610
1615
|
let pending = [];
|
|
1611
1616
|
const stopObserving = install((entry) => {
|
|
1612
1617
|
pending.push(entry);
|
|
@@ -1621,7 +1626,7 @@ function createGcCensus(install, kinds, startedAt) {
|
|
|
1621
1626
|
pending = [];
|
|
1622
1627
|
windowStart = at;
|
|
1623
1628
|
return {
|
|
1624
|
-
...countsOf(taken, kinds),
|
|
1629
|
+
...countsOf(taken, kinds, flagBits),
|
|
1625
1630
|
windowMs
|
|
1626
1631
|
};
|
|
1627
1632
|
},
|
|
@@ -1646,14 +1651,18 @@ function nodeGcObserver() {
|
|
|
1646
1651
|
minor: 1,
|
|
1647
1652
|
incremental: 8
|
|
1648
1653
|
}),
|
|
1654
|
+
flagBits: readFlagBits(),
|
|
1649
1655
|
install: (observe) => {
|
|
1650
1656
|
try {
|
|
1651
1657
|
const observer = new (process.getBuiltinModule("node:perf_hooks")).PerformanceObserver((list) => {
|
|
1652
1658
|
for (const entry of list.getEntries()) {
|
|
1653
1659
|
const detail = "detail" in entry ? entry.detail : void 0;
|
|
1660
|
+
const kind = typeof detail === "object" && detail !== null && "kind" in detail && typeof detail.kind === "number" ? detail.kind : -1;
|
|
1661
|
+
const flags = typeof detail === "object" && detail !== null && "flags" in detail && typeof detail.flags === "number" ? detail.flags : void 0;
|
|
1654
1662
|
observe({
|
|
1655
|
-
kind
|
|
1656
|
-
durationMs: entry.duration
|
|
1663
|
+
kind,
|
|
1664
|
+
durationMs: entry.duration,
|
|
1665
|
+
...flags !== void 0 ? { flags } : {}
|
|
1657
1666
|
});
|
|
1658
1667
|
}
|
|
1659
1668
|
});
|
|
@@ -1667,6 +1676,25 @@ function nodeGcObserver() {
|
|
|
1667
1676
|
}
|
|
1668
1677
|
};
|
|
1669
1678
|
}
|
|
1679
|
+
var GC_FLAG_PREFIX = "NODE_PERFORMANCE_GC_FLAGS_";
|
|
1680
|
+
/**
|
|
1681
|
+
* The flag bits, read from `perf_hooks.constants` by their prefix so a flag V8
|
|
1682
|
+
* adds tomorrow gets a name without anyone editing a table. `NO` (0) can never
|
|
1683
|
+
* match a bit and is dropped.
|
|
1684
|
+
*/
|
|
1685
|
+
function readFlagBits() {
|
|
1686
|
+
try {
|
|
1687
|
+
const perf = process.getBuiltinModule("node:perf_hooks");
|
|
1688
|
+
const bits = [];
|
|
1689
|
+
for (const [key, value] of Object.entries(perf.constants)) if (key.startsWith(GC_FLAG_PREFIX) && typeof value === "number" && value > 0) bits.push({
|
|
1690
|
+
name: key.slice(26),
|
|
1691
|
+
bit: value
|
|
1692
|
+
});
|
|
1693
|
+
return bits;
|
|
1694
|
+
} catch {
|
|
1695
|
+
return [];
|
|
1696
|
+
}
|
|
1697
|
+
}
|
|
1670
1698
|
function readKinds(fallback) {
|
|
1671
1699
|
try {
|
|
1672
1700
|
const c = process.getBuiltinModule("node:perf_hooks").constants;
|
|
@@ -1693,7 +1721,14 @@ function readKinds(fallback) {
|
|
|
1693
1721
|
function formatGcCensus(window) {
|
|
1694
1722
|
if (window === null || window === void 0) return "";
|
|
1695
1723
|
const perMin = (n) => window.windowMs <= 0 ? "?" : (n / (window.windowMs / 6e4)).toFixed(1);
|
|
1696
|
-
return ` gc=maj${window.majors}/min${window.minors}/inc${window.incrementals}@${Math.round(window.windowMs / 1e3)}s gcMajPerMin=${perMin(window.majors)} gcPauseMs=${Math.round(window.pauseMs)}
|
|
1724
|
+
return ` gc=maj${window.majors}/min${window.minors}/inc${window.incrementals}@${Math.round(window.windowMs / 1e3)}s gcMajPerMin=${perMin(window.majors)} gcPauseMs=${Math.round(window.pauseMs)}` + formatGcFlags(window.flags);
|
|
1725
|
+
}
|
|
1726
|
+
/** ` gcFlags=ALL_EXTERNAL_MEMORY:12,FORCED:1` — most frequent first; empty when none. */
|
|
1727
|
+
function formatGcFlags(flags) {
|
|
1728
|
+
if (flags === void 0) return "";
|
|
1729
|
+
const entries = Object.entries(flags).toSorted((a, b) => b[1] - a[1] || a[0].localeCompare(b[0]));
|
|
1730
|
+
if (entries.length === 0) return "";
|
|
1731
|
+
return ` gcFlags=${entries.map(([name, n]) => `${name}:${n}`).join(",")}`;
|
|
1697
1732
|
}
|
|
1698
1733
|
/**
|
|
1699
1734
|
* The census. Always exists — `process.cpuUsage()` is available on every
|
|
@@ -2440,7 +2475,7 @@ function startHeapWatch(label = HUB_MAIN_HEAP_WATCH_LABEL, sink = consoleSink, i
|
|
|
2440
2475
|
const readMemory = reclaimOptions?.readMemory ?? (() => process.memoryUsage());
|
|
2441
2476
|
const now = reclaimOptions?.now ?? (() => Date.now());
|
|
2442
2477
|
const gcObserver = probes?.gcObserver ?? nodeGcObserver();
|
|
2443
|
-
const gcCensus = createGcCensus(gcObserver.install, gcObserver.kinds, now());
|
|
2478
|
+
const gcCensus = createGcCensus(gcObserver.install, gcObserver.kinds, now(), gcObserver.flagBits);
|
|
2444
2479
|
const cpuProbe = probes?.processCpu;
|
|
2445
2480
|
const processCpu = createProcessCpuCensus({
|
|
2446
2481
|
cpuUsageUs: cpuProbe?.cpuUsageUs ?? (() => {
|
|
@@ -2494,6 +2529,7 @@ function startHeapWatch(label = HUB_MAIN_HEAP_WATCH_LABEL, sink = consoleSink, i
|
|
|
2494
2529
|
};
|
|
2495
2530
|
let mode = "steady";
|
|
2496
2531
|
let lastLoggedAt = Number.NEGATIVE_INFINITY;
|
|
2532
|
+
let firstLinePending = true;
|
|
2497
2533
|
const budgetMb = rssBudget?.budgetMb !== void 0 && rssBudget.budgetMb > 0 ? rssBudget.budgetMb : void 0;
|
|
2498
2534
|
const budgetSource = rssBudget?.source ?? "unspecified";
|
|
2499
2535
|
const releaseRatio = rssBudget?.releaseRatio ?? .9;
|
|
@@ -2552,7 +2588,9 @@ function startHeapWatch(label = HUB_MAIN_HEAP_WATCH_LABEL, sink = consoleSink, i
|
|
|
2552
2588
|
const due = at - lastLoggedAt >= intervalMs;
|
|
2553
2589
|
if (mode === "escalated" || due) {
|
|
2554
2590
|
lastLoggedAt = at;
|
|
2555
|
-
const
|
|
2591
|
+
const firstLine = firstLinePending;
|
|
2592
|
+
firstLinePending = false;
|
|
2593
|
+
const line = format(label, sample, loopDelay?.read(), budgetMb, `${formatHeapSpaces(readSpaces(), firstLine ? 0 : void 0)}${formatEventPlane(eventPlane?.read())}` + formatSocketPlane(socketPlane?.read()) + formatMeshQueue(meshQueue?.()) + formatGcCensus(gcCensus?.read(at)) + formatProcessCpu(processCpu.read(at)));
|
|
2556
2594
|
if (sample.nearLimit) sink.warn(`${line} — APPROACHING HEAP LIMIT`);
|
|
2557
2595
|
else if (mode === "escalated") sink.warn(`${line} — heap elevated, sampling every ${probeIntervalMs}ms`);
|
|
2558
2596
|
else sink.info(line);
|
|
@@ -2775,9 +2813,14 @@ function capBareAction(capName, method) {
|
|
|
2775
2813
|
* node had answered (2026-09-25, device 3836).
|
|
2776
2814
|
*/
|
|
2777
2815
|
var PeerAnsweredError = class extends Error {
|
|
2778
|
-
|
|
2816
|
+
/** The far end's stable error code (D863), carried so the hub can translate it. */
|
|
2817
|
+
i18nCode;
|
|
2818
|
+
i18nParams;
|
|
2819
|
+
constructor(message, i18n) {
|
|
2779
2820
|
super(message);
|
|
2780
2821
|
this.name = "PeerAnsweredError";
|
|
2822
|
+
this.i18nCode = i18n?.code;
|
|
2823
|
+
this.i18nParams = i18n?.params;
|
|
2781
2824
|
}
|
|
2782
2825
|
};
|
|
2783
2826
|
/**
|
|
@@ -4306,6 +4349,13 @@ var PayloadReply = class {
|
|
|
4306
4349
|
this.payload = payload;
|
|
4307
4350
|
}
|
|
4308
4351
|
};
|
|
4352
|
+
//#endregion
|
|
4353
|
+
//#region src/kernel/transport/socket-channel.ts
|
|
4354
|
+
/** A peer's `i18n` is untrusted wire data: a malformed one is dropped, the message still travels. */
|
|
4355
|
+
function parseWireI18n(raw) {
|
|
4356
|
+
const parsed = _camstack_types_addon.ErrorI18nPayloadSchema.safeParse(raw);
|
|
4357
|
+
return parsed.success ? parsed.data : void 0;
|
|
4358
|
+
}
|
|
4309
4359
|
var SocketChannel = class {
|
|
4310
4360
|
socket;
|
|
4311
4361
|
nextId = 1;
|
|
@@ -4517,11 +4567,13 @@ var SocketChannel = class {
|
|
|
4517
4567
|
body: result
|
|
4518
4568
|
});
|
|
4519
4569
|
} catch (err) {
|
|
4570
|
+
const i18n = (0, _camstack_types_addon.readErrorI18n)(err);
|
|
4520
4571
|
resBytes = this.send({
|
|
4521
4572
|
k: "res",
|
|
4522
4573
|
id: frame.id,
|
|
4523
4574
|
ok: false,
|
|
4524
|
-
err: err instanceof Error ? err.message : String(err)
|
|
4575
|
+
err: err instanceof Error ? err.message : String(err),
|
|
4576
|
+
...i18n !== null ? { i18n } : {}
|
|
4525
4577
|
});
|
|
4526
4578
|
}
|
|
4527
4579
|
if (label !== void 0) this.recordAction(label, wireBytes, resBytes);
|
|
@@ -4533,7 +4585,7 @@ var SocketChannel = class {
|
|
|
4533
4585
|
this.pending.delete(frame.id);
|
|
4534
4586
|
if (p.timer !== null) clearTimeout(p.timer);
|
|
4535
4587
|
if (p.action !== null) this.recordAction(p.action.label, p.action.reqBytes, wireBytes);
|
|
4536
|
-
if (!frame.ok) p.reject(new PeerAnsweredError(frame.err));
|
|
4588
|
+
if (!frame.ok) p.reject(new PeerAnsweredError(frame.err, parseWireI18n(frame.i18n)));
|
|
4537
4589
|
else if (frame.pl !== void 0) p.resolve(new PayloadReply(frame.body, frame.pl));
|
|
4538
4590
|
else p.resolve(frame.body);
|
|
4539
4591
|
return;
|
package/dist/addon-runner.mjs
CHANGED
|
@@ -3,7 +3,7 @@ import * as fs from "node:fs";
|
|
|
3
3
|
import { createReadStream, createWriteStream, existsSync, readFileSync, readdirSync } from "node:fs";
|
|
4
4
|
import * as path from "node:path";
|
|
5
5
|
import { dirname, isAbsolute, join } from "node:path";
|
|
6
|
-
import { BOOT_RECOVERY_BACKOFF_MS, DATAPLANE_SECRET_HEADER, DEVICE_CHILDREN_BATCH_MAX, DeviceType, DisposerChain, EventCategory, PEER_BYTES_CHUNK_BYTES, PEER_BYTES_MAX_OUTSTANDING, PEER_BYTES_STALL_MS, PEER_BYTES_TICKET_TTL_MS, ReadinessRegistry, ReadinessTimeoutError, asJsonObject, asString, collectZodSecretPaths, createDeviceProxy, createEventBusSliceSource, createSecretsAccess, describeCustomActions, deviceOpsCapability, emitReadiness, errMsg, expandCapMethods, isCollectionArrayMethodName, isProviderOptionalMethodName, maskUrlCredentials, normalizeAddonInitResult, readNodePin, resolveSecretViewsIn, scopeKey, scrubKnownSecrets, withCapInputDefaults } from "@camstack/types/addon";
|
|
6
|
+
import { BOOT_RECOVERY_BACKOFF_MS, DATAPLANE_SECRET_HEADER, DEVICE_CHILDREN_BATCH_MAX, DeviceType, DisposerChain, ErrorI18nPayloadSchema, EventCategory, PEER_BYTES_CHUNK_BYTES, PEER_BYTES_MAX_OUTSTANDING, PEER_BYTES_STALL_MS, PEER_BYTES_TICKET_TTL_MS, ReadinessRegistry, ReadinessTimeoutError, asJsonObject, asString, collectZodSecretPaths, createDeviceProxy, createEventBusSliceSource, createSecretsAccess, describeCustomActions, deviceOpsCapability, emitReadiness, errMsg, expandCapMethods, isCollectionArrayMethodName, isProviderOptionalMethodName, maskUrlCredentials, normalizeAddonInitResult, readErrorI18n, readNodePin, resolveSecretViewsIn, scopeKey, scrubKnownSecrets, withCapInputDefaults } from "@camstack/types/addon";
|
|
7
7
|
import { execFile } from "node:child_process";
|
|
8
8
|
import { promisify } from "node:util";
|
|
9
9
|
import * as os from "node:os";
|
|
@@ -1554,7 +1554,8 @@ function formatOutboundQueueVerdict(label, verdict) {
|
|
|
1554
1554
|
}
|
|
1555
1555
|
//#endregion
|
|
1556
1556
|
//#region src/kernel/gc-census.ts
|
|
1557
|
-
function countsOf(entries, kinds) {
|
|
1557
|
+
function countsOf(entries, kinds, flagBits) {
|
|
1558
|
+
const flags = {};
|
|
1558
1559
|
let majors = 0;
|
|
1559
1560
|
let minors = 0;
|
|
1560
1561
|
let incrementals = 0;
|
|
@@ -1564,13 +1565,17 @@ function countsOf(entries, kinds) {
|
|
|
1564
1565
|
else if (e.kind === kinds.minor) minors++;
|
|
1565
1566
|
else if (e.kind === kinds.incremental) incrementals++;
|
|
1566
1567
|
pauseMs += e.durationMs;
|
|
1568
|
+
if (e.flags !== void 0) {
|
|
1569
|
+
for (const f of flagBits) if ((e.flags & f.bit) !== 0) flags[f.name] = (flags[f.name] ?? 0) + 1;
|
|
1570
|
+
}
|
|
1567
1571
|
}
|
|
1568
1572
|
return {
|
|
1569
1573
|
majors,
|
|
1570
1574
|
minors,
|
|
1571
1575
|
incrementals,
|
|
1572
1576
|
pauseMs,
|
|
1573
|
-
windowMs: 0
|
|
1577
|
+
windowMs: 0,
|
|
1578
|
+
...Object.keys(flags).length > 0 ? { flags } : {}
|
|
1574
1579
|
};
|
|
1575
1580
|
}
|
|
1576
1581
|
/**
|
|
@@ -1582,7 +1587,7 @@ function countsOf(entries, kinds) {
|
|
|
1582
1587
|
* observed and a process that is not collecting look identical on the line, and
|
|
1583
1588
|
* they are the two answers furthest apart.
|
|
1584
1589
|
*/
|
|
1585
|
-
function createGcCensus(install, kinds, startedAt) {
|
|
1590
|
+
function createGcCensus(install, kinds, startedAt, flagBits = []) {
|
|
1586
1591
|
let pending = [];
|
|
1587
1592
|
const stopObserving = install((entry) => {
|
|
1588
1593
|
pending.push(entry);
|
|
@@ -1597,7 +1602,7 @@ function createGcCensus(install, kinds, startedAt) {
|
|
|
1597
1602
|
pending = [];
|
|
1598
1603
|
windowStart = at;
|
|
1599
1604
|
return {
|
|
1600
|
-
...countsOf(taken, kinds),
|
|
1605
|
+
...countsOf(taken, kinds, flagBits),
|
|
1601
1606
|
windowMs
|
|
1602
1607
|
};
|
|
1603
1608
|
},
|
|
@@ -1622,14 +1627,18 @@ function nodeGcObserver() {
|
|
|
1622
1627
|
minor: 1,
|
|
1623
1628
|
incremental: 8
|
|
1624
1629
|
}),
|
|
1630
|
+
flagBits: readFlagBits(),
|
|
1625
1631
|
install: (observe) => {
|
|
1626
1632
|
try {
|
|
1627
1633
|
const observer = new (process.getBuiltinModule("node:perf_hooks")).PerformanceObserver((list) => {
|
|
1628
1634
|
for (const entry of list.getEntries()) {
|
|
1629
1635
|
const detail = "detail" in entry ? entry.detail : void 0;
|
|
1636
|
+
const kind = typeof detail === "object" && detail !== null && "kind" in detail && typeof detail.kind === "number" ? detail.kind : -1;
|
|
1637
|
+
const flags = typeof detail === "object" && detail !== null && "flags" in detail && typeof detail.flags === "number" ? detail.flags : void 0;
|
|
1630
1638
|
observe({
|
|
1631
|
-
kind
|
|
1632
|
-
durationMs: entry.duration
|
|
1639
|
+
kind,
|
|
1640
|
+
durationMs: entry.duration,
|
|
1641
|
+
...flags !== void 0 ? { flags } : {}
|
|
1633
1642
|
});
|
|
1634
1643
|
}
|
|
1635
1644
|
});
|
|
@@ -1643,6 +1652,25 @@ function nodeGcObserver() {
|
|
|
1643
1652
|
}
|
|
1644
1653
|
};
|
|
1645
1654
|
}
|
|
1655
|
+
var GC_FLAG_PREFIX = "NODE_PERFORMANCE_GC_FLAGS_";
|
|
1656
|
+
/**
|
|
1657
|
+
* The flag bits, read from `perf_hooks.constants` by their prefix so a flag V8
|
|
1658
|
+
* adds tomorrow gets a name without anyone editing a table. `NO` (0) can never
|
|
1659
|
+
* match a bit and is dropped.
|
|
1660
|
+
*/
|
|
1661
|
+
function readFlagBits() {
|
|
1662
|
+
try {
|
|
1663
|
+
const perf = process.getBuiltinModule("node:perf_hooks");
|
|
1664
|
+
const bits = [];
|
|
1665
|
+
for (const [key, value] of Object.entries(perf.constants)) if (key.startsWith(GC_FLAG_PREFIX) && typeof value === "number" && value > 0) bits.push({
|
|
1666
|
+
name: key.slice(26),
|
|
1667
|
+
bit: value
|
|
1668
|
+
});
|
|
1669
|
+
return bits;
|
|
1670
|
+
} catch {
|
|
1671
|
+
return [];
|
|
1672
|
+
}
|
|
1673
|
+
}
|
|
1646
1674
|
function readKinds(fallback) {
|
|
1647
1675
|
try {
|
|
1648
1676
|
const c = process.getBuiltinModule("node:perf_hooks").constants;
|
|
@@ -1669,7 +1697,14 @@ function readKinds(fallback) {
|
|
|
1669
1697
|
function formatGcCensus(window) {
|
|
1670
1698
|
if (window === null || window === void 0) return "";
|
|
1671
1699
|
const perMin = (n) => window.windowMs <= 0 ? "?" : (n / (window.windowMs / 6e4)).toFixed(1);
|
|
1672
|
-
return ` gc=maj${window.majors}/min${window.minors}/inc${window.incrementals}@${Math.round(window.windowMs / 1e3)}s gcMajPerMin=${perMin(window.majors)} gcPauseMs=${Math.round(window.pauseMs)}
|
|
1700
|
+
return ` gc=maj${window.majors}/min${window.minors}/inc${window.incrementals}@${Math.round(window.windowMs / 1e3)}s gcMajPerMin=${perMin(window.majors)} gcPauseMs=${Math.round(window.pauseMs)}` + formatGcFlags(window.flags);
|
|
1701
|
+
}
|
|
1702
|
+
/** ` gcFlags=ALL_EXTERNAL_MEMORY:12,FORCED:1` — most frequent first; empty when none. */
|
|
1703
|
+
function formatGcFlags(flags) {
|
|
1704
|
+
if (flags === void 0) return "";
|
|
1705
|
+
const entries = Object.entries(flags).toSorted((a, b) => b[1] - a[1] || a[0].localeCompare(b[0]));
|
|
1706
|
+
if (entries.length === 0) return "";
|
|
1707
|
+
return ` gcFlags=${entries.map(([name, n]) => `${name}:${n}`).join(",")}`;
|
|
1673
1708
|
}
|
|
1674
1709
|
/**
|
|
1675
1710
|
* The census. Always exists — `process.cpuUsage()` is available on every
|
|
@@ -2416,7 +2451,7 @@ function startHeapWatch(label = HUB_MAIN_HEAP_WATCH_LABEL, sink = consoleSink, i
|
|
|
2416
2451
|
const readMemory = reclaimOptions?.readMemory ?? (() => process.memoryUsage());
|
|
2417
2452
|
const now = reclaimOptions?.now ?? (() => Date.now());
|
|
2418
2453
|
const gcObserver = probes?.gcObserver ?? nodeGcObserver();
|
|
2419
|
-
const gcCensus = createGcCensus(gcObserver.install, gcObserver.kinds, now());
|
|
2454
|
+
const gcCensus = createGcCensus(gcObserver.install, gcObserver.kinds, now(), gcObserver.flagBits);
|
|
2420
2455
|
const cpuProbe = probes?.processCpu;
|
|
2421
2456
|
const processCpu = createProcessCpuCensus({
|
|
2422
2457
|
cpuUsageUs: cpuProbe?.cpuUsageUs ?? (() => {
|
|
@@ -2470,6 +2505,7 @@ function startHeapWatch(label = HUB_MAIN_HEAP_WATCH_LABEL, sink = consoleSink, i
|
|
|
2470
2505
|
};
|
|
2471
2506
|
let mode = "steady";
|
|
2472
2507
|
let lastLoggedAt = Number.NEGATIVE_INFINITY;
|
|
2508
|
+
let firstLinePending = true;
|
|
2473
2509
|
const budgetMb = rssBudget?.budgetMb !== void 0 && rssBudget.budgetMb > 0 ? rssBudget.budgetMb : void 0;
|
|
2474
2510
|
const budgetSource = rssBudget?.source ?? "unspecified";
|
|
2475
2511
|
const releaseRatio = rssBudget?.releaseRatio ?? .9;
|
|
@@ -2528,7 +2564,9 @@ function startHeapWatch(label = HUB_MAIN_HEAP_WATCH_LABEL, sink = consoleSink, i
|
|
|
2528
2564
|
const due = at - lastLoggedAt >= intervalMs;
|
|
2529
2565
|
if (mode === "escalated" || due) {
|
|
2530
2566
|
lastLoggedAt = at;
|
|
2531
|
-
const
|
|
2567
|
+
const firstLine = firstLinePending;
|
|
2568
|
+
firstLinePending = false;
|
|
2569
|
+
const line = format(label, sample, loopDelay?.read(), budgetMb, `${formatHeapSpaces(readSpaces(), firstLine ? 0 : void 0)}${formatEventPlane(eventPlane?.read())}` + formatSocketPlane(socketPlane?.read()) + formatMeshQueue(meshQueue?.()) + formatGcCensus(gcCensus?.read(at)) + formatProcessCpu(processCpu.read(at)));
|
|
2532
2570
|
if (sample.nearLimit) sink.warn(`${line} — APPROACHING HEAP LIMIT`);
|
|
2533
2571
|
else if (mode === "escalated") sink.warn(`${line} — heap elevated, sampling every ${probeIntervalMs}ms`);
|
|
2534
2572
|
else sink.info(line);
|
|
@@ -2751,9 +2789,14 @@ function capBareAction(capName, method) {
|
|
|
2751
2789
|
* node had answered (2026-09-25, device 3836).
|
|
2752
2790
|
*/
|
|
2753
2791
|
var PeerAnsweredError = class extends Error {
|
|
2754
|
-
|
|
2792
|
+
/** The far end's stable error code (D863), carried so the hub can translate it. */
|
|
2793
|
+
i18nCode;
|
|
2794
|
+
i18nParams;
|
|
2795
|
+
constructor(message, i18n) {
|
|
2755
2796
|
super(message);
|
|
2756
2797
|
this.name = "PeerAnsweredError";
|
|
2798
|
+
this.i18nCode = i18n?.code;
|
|
2799
|
+
this.i18nParams = i18n?.params;
|
|
2757
2800
|
}
|
|
2758
2801
|
};
|
|
2759
2802
|
/**
|
|
@@ -4282,6 +4325,13 @@ var PayloadReply = class {
|
|
|
4282
4325
|
this.payload = payload;
|
|
4283
4326
|
}
|
|
4284
4327
|
};
|
|
4328
|
+
//#endregion
|
|
4329
|
+
//#region src/kernel/transport/socket-channel.ts
|
|
4330
|
+
/** A peer's `i18n` is untrusted wire data: a malformed one is dropped, the message still travels. */
|
|
4331
|
+
function parseWireI18n(raw) {
|
|
4332
|
+
const parsed = ErrorI18nPayloadSchema.safeParse(raw);
|
|
4333
|
+
return parsed.success ? parsed.data : void 0;
|
|
4334
|
+
}
|
|
4285
4335
|
var SocketChannel = class {
|
|
4286
4336
|
socket;
|
|
4287
4337
|
nextId = 1;
|
|
@@ -4493,11 +4543,13 @@ var SocketChannel = class {
|
|
|
4493
4543
|
body: result
|
|
4494
4544
|
});
|
|
4495
4545
|
} catch (err) {
|
|
4546
|
+
const i18n = readErrorI18n(err);
|
|
4496
4547
|
resBytes = this.send({
|
|
4497
4548
|
k: "res",
|
|
4498
4549
|
id: frame.id,
|
|
4499
4550
|
ok: false,
|
|
4500
|
-
err: err instanceof Error ? err.message : String(err)
|
|
4551
|
+
err: err instanceof Error ? err.message : String(err),
|
|
4552
|
+
...i18n !== null ? { i18n } : {}
|
|
4501
4553
|
});
|
|
4502
4554
|
}
|
|
4503
4555
|
if (label !== void 0) this.recordAction(label, wireBytes, resBytes);
|
|
@@ -4509,7 +4561,7 @@ var SocketChannel = class {
|
|
|
4509
4561
|
this.pending.delete(frame.id);
|
|
4510
4562
|
if (p.timer !== null) clearTimeout(p.timer);
|
|
4511
4563
|
if (p.action !== null) this.recordAction(p.action.label, p.action.reqBytes, wireBytes);
|
|
4512
|
-
if (!frame.ok) p.reject(new PeerAnsweredError(frame.err));
|
|
4564
|
+
if (!frame.ok) p.reject(new PeerAnsweredError(frame.err, parseWireI18n(frame.i18n)));
|
|
4513
4565
|
else if (frame.pl !== void 0) p.resolve(new PayloadReply(frame.body, frame.pl));
|
|
4514
4566
|
else p.resolve(frame.body);
|
|
4515
4567
|
return;
|