@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.
Files changed (109) hide show
  1. package/dist/addon-runner.js +64 -12
  2. package/dist/addon-runner.mjs +65 -13
  3. package/dist/{agent-https-BZIwS4xF.js → agent-https-DlpTMDqA.js} +252 -22
  4. package/dist/{agent-https-BPfHrI4c.mjs → agent-https-U0d4uvn2.mjs} +211 -23
  5. package/dist/builtins/addon-pages-aggregator/addon-pages-aggregator.addon.js +1 -1
  6. package/dist/builtins/addon-pages-aggregator/addon-pages-aggregator.addon.mjs +1 -1
  7. package/dist/builtins/addon-widgets-aggregator/addon-widgets-aggregator.addon.js +1 -1
  8. package/dist/builtins/addon-widgets-aggregator/addon-widgets-aggregator.addon.mjs +1 -1
  9. package/dist/builtins/alerts/alerts.addon.js +7 -1
  10. package/dist/builtins/alerts/alerts.addon.mjs +7 -1
  11. package/dist/builtins/autotrack/index.js +1 -1
  12. package/dist/builtins/autotrack/index.mjs +1 -1
  13. package/dist/builtins/backup-orchestrator/backup-orchestrator.addon.js +2 -2
  14. package/dist/builtins/backup-orchestrator/backup-orchestrator.addon.mjs +2 -2
  15. package/dist/builtins/calendars/calendars.addon.js +1 -1
  16. package/dist/builtins/calendars/calendars.addon.mjs +1 -1
  17. package/dist/builtins/camera-grid/index.js +9 -1
  18. package/dist/builtins/camera-grid/index.mjs +9 -1
  19. package/dist/builtins/composer/composer.addon.js +2 -2
  20. package/dist/builtins/composer/composer.addon.mjs +2 -2
  21. package/dist/builtins/console-logging/index.js +12 -5
  22. package/dist/builtins/console-logging/index.mjs +12 -5
  23. package/dist/builtins/core-blocks/core-blocks.addon.js +2 -2
  24. package/dist/builtins/core-blocks/core-blocks.addon.mjs +2 -2
  25. package/dist/builtins/device-manager/device-manager.addon.d.ts +5 -0
  26. package/dist/builtins/device-manager/device-manager.addon.js +717 -28
  27. package/dist/builtins/device-manager/device-manager.addon.mjs +717 -28
  28. package/dist/builtins/device-manager/device-meta-types.d.ts +4 -0
  29. package/dist/builtins/device-manager/device-provider-context.d.ts +9 -0
  30. package/dist/builtins/device-manager/device-removal-hooks.d.ts +103 -0
  31. package/dist/builtins/device-manager/device-row-store.d.ts +1 -0
  32. package/dist/builtins/device-manager/device-tombstone-store.d.ts +68 -0
  33. package/dist/builtins/device-manager/removal-cleanup.d.ts +50 -0
  34. package/dist/builtins/hub-forwarder/index.js +1 -1
  35. package/dist/builtins/hub-forwarder/index.mjs +1 -1
  36. package/dist/builtins/keychain/index.js +37 -4
  37. package/dist/builtins/keychain/index.mjs +37 -4
  38. package/dist/builtins/keychain/keychain-service.d.ts +14 -0
  39. package/dist/builtins/keychain/keychain-store.d.ts +1 -1
  40. package/dist/builtins/liveness-monitor/liveness-monitor.addon.js +1 -1
  41. package/dist/builtins/liveness-monitor/liveness-monitor.addon.mjs +1 -1
  42. package/dist/builtins/local-auth/local-auth.addon.js +12 -12
  43. package/dist/builtins/local-auth/local-auth.addon.mjs +12 -12
  44. package/dist/builtins/local-network/local-network.addon.js +16 -2
  45. package/dist/builtins/local-network/local-network.addon.mjs +16 -2
  46. package/dist/builtins/loki-logging/index.js +28 -5
  47. package/dist/builtins/loki-logging/index.mjs +28 -5
  48. package/dist/builtins/native-metrics/native-metrics.addon.js +11 -1
  49. package/dist/builtins/native-metrics/native-metrics.addon.mjs +11 -1
  50. package/dist/builtins/platform-probe/index.js +1 -1
  51. package/dist/builtins/platform-probe/index.mjs +1 -1
  52. package/dist/builtins/remote-access-orchestrator/remote-access-orchestrator.addon.js +1 -1
  53. package/dist/builtins/remote-access-orchestrator/remote-access-orchestrator.addon.mjs +1 -1
  54. package/dist/builtins/snapshot/index.js +11 -1
  55. package/dist/builtins/snapshot/index.mjs +11 -1
  56. package/dist/builtins/sqlite-storage/filesystem-storage.addon.js +4 -1
  57. package/dist/builtins/sqlite-storage/filesystem-storage.addon.mjs +4 -1
  58. package/dist/builtins/sqlite-storage/index.js +1 -1
  59. package/dist/builtins/sqlite-storage/index.mjs +1 -1
  60. package/dist/builtins/sqlite-storage/sqlite-settings.addon.js +3 -3
  61. package/dist/builtins/sqlite-storage/sqlite-settings.addon.mjs +3 -3
  62. package/dist/builtins/storage-orchestrator/storage-orchestrator.addon.js +1 -1
  63. package/dist/builtins/storage-orchestrator/storage-orchestrator.addon.mjs +1 -1
  64. package/dist/builtins/system-config/system-config.addon.js +22 -4
  65. package/dist/builtins/system-config/system-config.addon.mjs +22 -4
  66. package/dist/builtins/winston-logging/index.js +14 -5
  67. package/dist/builtins/winston-logging/index.mjs +14 -5
  68. package/dist/{composition-sources-BIT8IUKm.js → composition-sources-B4jC2FC7.js} +1 -1
  69. package/dist/{composition-sources-tpYR0f1x.mjs → composition-sources-BGOSCGWa.mjs} +1 -1
  70. package/dist/{constants-Bc6trhoW.mjs → constants-B92BjObl.mjs} +1 -1
  71. package/dist/{constants-CwRY32Nx.js → constants-BRsjQwi-.js} +1 -1
  72. package/dist/{device-ca-BhdBByGD.mjs → device-ca-46BUsWD1.mjs} +2 -2
  73. package/dist/{device-ca-DImD8IzR.js → device-ca-DHG9OW2m.js} +2 -2
  74. package/dist/{dist-CEAyXW3Q.js → dist-BOWdLjoK.js} +341 -13
  75. package/dist/{dist-m5JkT8UN.mjs → dist-yI6kF6r6.mjs} +306 -14
  76. package/dist/file-host-worker.js +1 -1
  77. package/dist/file-host-worker.mjs +1 -1
  78. package/dist/{hub-mdns-ciao-CBLvq2oj.js → hub-mdns-ciao-D7S5AJRU.js} +377 -69
  79. package/dist/{hub-mdns-ciao-DMlQTdPU.mjs → hub-mdns-ciao-DGwVc2uh.mjs} +344 -72
  80. package/dist/i18n/catalog-registry.d.ts +35 -0
  81. package/dist/i18n/index.d.ts +2 -0
  82. package/dist/index.d.ts +1 -0
  83. package/dist/index.js +698 -22
  84. package/dist/index.mjs +681 -24
  85. package/dist/kernel/gc-census.d.ts +18 -1
  86. package/dist/kernel/settings-view-types.d.ts +2 -0
  87. package/dist/kernel/transport/local-transport.d.ts +3 -0
  88. package/dist/kernel/transport/peer-answered-error.d.ts +5 -1
  89. package/dist/{lib-NNxHSOIE.js → lib-8oZrELLm.js} +1 -1
  90. package/dist/{lib-BeGzVQcd.mjs → lib-DK38ompL.mjs} +1 -1
  91. package/dist/{restore-archive-DNxAStrJ.mjs → restore-archive-CpdUO-uS.mjs} +1 -1
  92. package/dist/{restore-archive-C75srVbG.js → restore-archive-DiGiI6Jp.js} +1 -1
  93. package/dist/{retired-settings-keys-DNfV28R_.js → retired-settings-keys-CyQ7uvta.js} +1 -1
  94. package/dist/{retired-settings-keys-C5qP9QIf.mjs → retired-settings-keys-UsVtLOT0.mjs} +1 -1
  95. package/dist/tls/agent-https.d.ts +2 -2
  96. package/dist/tls/boot-tls.d.ts +6 -0
  97. package/dist/tls/cert-evaluation.d.ts +1 -1
  98. package/dist/tls/cert-issue.d.ts +5 -1
  99. package/dist/tls/cert-manager.d.ts +18 -0
  100. package/dist/tls/cert-name-constraints.d.ts +53 -0
  101. package/dist/tls/index.d.ts +5 -4
  102. package/dist/tls/tls-actions.d.ts +27 -7
  103. package/dist/tls/tls-status.d.ts +22 -0
  104. package/dist/tls/uploaded-cert.d.ts +36 -4
  105. package/dist/{wal-maintenance-Ch79gy9S.js → wal-maintenance-DEL_jeG0.js} +0 -0
  106. package/dist/{wal-maintenance-DvnVO5IK.mjs → wal-maintenance-xsvdT5Go.mjs} +0 -0
  107. package/dist/{x509.es-r7Ht1thA.js → x509.es-C4cOo48M.js} +36 -0
  108. package/dist/{x509.es-CDvj67p1.mjs → x509.es-DK__ETIe.mjs} +1 -1
  109. package/package.json +3 -1
@@ -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: typeof detail === "object" && detail !== null && "kind" in detail && typeof detail.kind === "number" ? detail.kind : -1,
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 line = format(label, sample, loopDelay?.read(), budgetMb, `${formatHeapSpaces(readSpaces())}${formatEventPlane(eventPlane?.read())}` + formatSocketPlane(socketPlane?.read()) + formatMeshQueue(meshQueue?.()) + formatGcCensus(gcCensus?.read(at)) + formatProcessCpu(processCpu.read(at)));
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
- constructor(message) {
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;
@@ -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: typeof detail === "object" && detail !== null && "kind" in detail && typeof detail.kind === "number" ? detail.kind : -1,
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 line = format(label, sample, loopDelay?.read(), budgetMb, `${formatHeapSpaces(readSpaces())}${formatEventPlane(eventPlane?.read())}` + formatSocketPlane(socketPlane?.read()) + formatMeshQueue(meshQueue?.()) + formatGcCensus(gcCensus?.read(at)) + formatProcessCpu(processCpu.read(at)));
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
- constructor(message) {
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;