@camstack/system 1.0.2

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 (262) hide show
  1. package/dist/addon/addon-api-factory.d.ts +35 -0
  2. package/dist/addon-routes/addon-route-registry.d.ts +37 -0
  3. package/dist/addon-runner.js +599 -0
  4. package/dist/addon-runner.mjs +597 -0
  5. package/dist/auth/api-key-manager.d.ts +26 -0
  6. package/dist/auth/auth-manager.d.ts +109 -0
  7. package/dist/auth/parse-record.d.ts +18 -0
  8. package/dist/auth/scope-matcher.d.ts +7 -0
  9. package/dist/auth/scoped-token-manager.d.ts +40 -0
  10. package/dist/auth/totp-manager.d.ts +51 -0
  11. package/dist/auth/user-manager.d.ts +34 -0
  12. package/dist/builtins/addon-pages-aggregator/addon-pages-aggregator.addon.d.ts +53 -0
  13. package/dist/builtins/addon-pages-aggregator/addon-pages-aggregator.addon.js +259 -0
  14. package/dist/builtins/addon-pages-aggregator/addon-pages-aggregator.addon.mjs +251 -0
  15. package/dist/builtins/addon-pages-aggregator/dedupe-pages.d.ts +6 -0
  16. package/dist/builtins/addon-pages-aggregator/index.d.ts +1 -0
  17. package/dist/builtins/addon-pages-aggregator/index.js +8 -0
  18. package/dist/builtins/addon-pages-aggregator/index.mjs +2 -0
  19. package/dist/builtins/addon-widgets-aggregator/addon-widgets-aggregator.addon.d.ts +47 -0
  20. package/dist/builtins/addon-widgets-aggregator/addon-widgets-aggregator.addon.js +228 -0
  21. package/dist/builtins/addon-widgets-aggregator/addon-widgets-aggregator.addon.mjs +220 -0
  22. package/dist/builtins/addon-widgets-aggregator/index.d.ts +1 -0
  23. package/dist/builtins/addon-widgets-aggregator/index.js +8 -0
  24. package/dist/builtins/addon-widgets-aggregator/index.mjs +2 -0
  25. package/dist/builtins/alerts/alerts.addon.d.ts +81 -0
  26. package/dist/builtins/alerts/alerts.addon.js +601 -0
  27. package/dist/builtins/alerts/alerts.addon.mjs +595 -0
  28. package/dist/builtins/alerts/index.d.ts +1 -0
  29. package/dist/builtins/alerts/index.js +4 -0
  30. package/dist/builtins/alerts/index.mjs +2 -0
  31. package/dist/builtins/backup-orchestrator/backup-orchestrator.addon.d.ts +147 -0
  32. package/dist/builtins/backup-orchestrator/backup-orchestrator.addon.js +2229 -0
  33. package/dist/builtins/backup-orchestrator/backup-orchestrator.addon.mjs +2220 -0
  34. package/dist/builtins/backup-orchestrator/cron-helpers.d.ts +23 -0
  35. package/dist/builtins/backup-orchestrator/destination-policy.d.ts +72 -0
  36. package/dist/builtins/backup-orchestrator/download-helpers.d.ts +12 -0
  37. package/dist/builtins/backup-orchestrator/index.d.ts +2 -0
  38. package/dist/builtins/backup-orchestrator/index.js +8 -0
  39. package/dist/builtins/backup-orchestrator/index.mjs +2 -0
  40. package/dist/builtins/backup-orchestrator/manifest-store.d.ts +77 -0
  41. package/dist/builtins/console-logging/console-destination.d.ts +13 -0
  42. package/dist/builtins/console-logging/console-logging.addon.d.ts +25 -0
  43. package/dist/builtins/console-logging/index.d.ts +3 -0
  44. package/dist/builtins/console-logging/index.js +104 -0
  45. package/dist/builtins/console-logging/index.mjs +95 -0
  46. package/dist/builtins/device-manager/device-config-contribution.d.ts +32 -0
  47. package/dist/builtins/device-manager/device-event-propagator.d.ts +26 -0
  48. package/dist/builtins/device-manager/device-link-overlay.d.ts +23 -0
  49. package/dist/builtins/device-manager/device-link-resolver.d.ts +15 -0
  50. package/dist/builtins/device-manager/device-manager.addon.d.ts +452 -0
  51. package/dist/builtins/device-manager/device-manager.addon.js +3299 -0
  52. package/dist/builtins/device-manager/device-manager.addon.mjs +3292 -0
  53. package/dist/builtins/device-manager/index.d.ts +2 -0
  54. package/dist/builtins/device-manager/index.js +8 -0
  55. package/dist/builtins/device-manager/index.mjs +2 -0
  56. package/dist/builtins/hub-forwarder/hub-forwarder-destination.d.ts +44 -0
  57. package/dist/builtins/hub-forwarder/hub-forwarder.addon.d.ts +15 -0
  58. package/dist/builtins/hub-forwarder/index.d.ts +3 -0
  59. package/dist/builtins/hub-forwarder/index.js +154 -0
  60. package/dist/builtins/hub-forwarder/index.mjs +145 -0
  61. package/dist/builtins/local-auth/auth-schema.d.ts +26 -0
  62. package/dist/builtins/local-auth/index.d.ts +1 -0
  63. package/dist/builtins/local-auth/index.js +4 -0
  64. package/dist/builtins/local-auth/index.mjs +2 -0
  65. package/dist/builtins/local-auth/local-auth.addon.d.ts +18 -0
  66. package/dist/builtins/local-auth/local-auth.addon.js +8094 -0
  67. package/dist/builtins/local-auth/local-auth.addon.mjs +8063 -0
  68. package/dist/builtins/local-auth/oauth-grants.d.ts +45 -0
  69. package/dist/builtins/local-auth/oauth-session-manager.d.ts +50 -0
  70. package/dist/builtins/local-network/index.d.ts +2 -0
  71. package/dist/builtins/local-network/index.js +10 -0
  72. package/dist/builtins/local-network/index.mjs +2 -0
  73. package/dist/builtins/local-network/local-network.addon.d.ts +150 -0
  74. package/dist/builtins/local-network/local-network.addon.js +489 -0
  75. package/dist/builtins/local-network/local-network.addon.mjs +477 -0
  76. package/dist/builtins/native-metrics/index.d.ts +2 -0
  77. package/dist/builtins/native-metrics/native-metrics-provider.d.ts +48 -0
  78. package/dist/builtins/native-metrics/native-metrics.addon.d.ts +73 -0
  79. package/dist/builtins/native-metrics/native-metrics.addon.js +922 -0
  80. package/dist/builtins/native-metrics/native-metrics.addon.mjs +914 -0
  81. package/dist/builtins/platform-probe/hardware-decode-accel-probe.d.ts +37 -0
  82. package/dist/builtins/platform-probe/hardware-encoder-probe.d.ts +13 -0
  83. package/dist/builtins/platform-probe/index.d.ts +22 -0
  84. package/dist/builtins/platform-probe/index.js +834 -0
  85. package/dist/builtins/platform-probe/index.mjs +822 -0
  86. package/dist/builtins/platform-probe/inference-config-resolver.d.ts +29 -0
  87. package/dist/builtins/platform-probe/intel-accelerators.d.ts +11 -0
  88. package/dist/builtins/platform-probe/platform-scorer.d.ts +30 -0
  89. package/dist/builtins/platform-probe/runtime-packages.d.ts +6 -0
  90. package/dist/builtins/remote-access-orchestrator/enabled-providers-reconcile.d.ts +96 -0
  91. package/dist/builtins/remote-access-orchestrator/index.d.ts +1 -0
  92. package/dist/builtins/remote-access-orchestrator/index.js +8 -0
  93. package/dist/builtins/remote-access-orchestrator/index.mjs +2 -0
  94. package/dist/builtins/remote-access-orchestrator/remote-access-orchestrator.addon.d.ts +40 -0
  95. package/dist/builtins/remote-access-orchestrator/remote-access-orchestrator.addon.js +214 -0
  96. package/dist/builtins/remote-access-orchestrator/remote-access-orchestrator.addon.mjs +208 -0
  97. package/dist/builtins/shared/settle-sources.d.ts +22 -0
  98. package/dist/builtins/snapshot/index.d.ts +2 -0
  99. package/dist/builtins/snapshot/index.js +494 -0
  100. package/dist/builtins/snapshot/index.mjs +488 -0
  101. package/dist/builtins/snapshot/snapshot.addon.d.ts +120 -0
  102. package/dist/builtins/sqlite-storage/config-store.d.ts +8 -0
  103. package/dist/builtins/sqlite-storage/device-store.d.ts +23 -0
  104. package/dist/builtins/sqlite-storage/filesystem-browse-provider.d.ts +25 -0
  105. package/dist/builtins/sqlite-storage/filesystem-storage-provider.d.ts +83 -0
  106. package/dist/builtins/sqlite-storage/filesystem-storage.addon.d.ts +32 -0
  107. package/dist/builtins/sqlite-storage/filesystem-storage.addon.js +396 -0
  108. package/dist/builtins/sqlite-storage/filesystem-storage.addon.mjs +388 -0
  109. package/dist/builtins/sqlite-storage/index.d.ts +8 -0
  110. package/dist/builtins/sqlite-storage/index.js +62 -0
  111. package/dist/builtins/sqlite-storage/index.mjs +49 -0
  112. package/dist/builtins/sqlite-storage/integration-registry.d.ts +27 -0
  113. package/dist/builtins/sqlite-storage/path-guard.d.ts +4 -0
  114. package/dist/builtins/sqlite-storage/sqlite-settings-backend.d.ts +102 -0
  115. package/dist/builtins/sqlite-storage/sqlite-settings.addon.d.ts +14 -0
  116. package/dist/builtins/sqlite-storage/sqlite-settings.addon.js +644 -0
  117. package/dist/builtins/sqlite-storage/sqlite-settings.addon.mjs +636 -0
  118. package/dist/builtins/storage-orchestrator/index.d.ts +6 -0
  119. package/dist/builtins/storage-orchestrator/index.js +10 -0
  120. package/dist/builtins/storage-orchestrator/index.mjs +2 -0
  121. package/dist/builtins/storage-orchestrator/location-store.d.ts +49 -0
  122. package/dist/builtins/storage-orchestrator/provider-discovery.d.ts +10 -0
  123. package/dist/builtins/storage-orchestrator/storage-orchestrator.addon.d.ts +103 -0
  124. package/dist/builtins/storage-orchestrator/storage-orchestrator.addon.js +1138 -0
  125. package/dist/builtins/storage-orchestrator/storage-orchestrator.addon.mjs +1128 -0
  126. package/dist/builtins/storage-orchestrator/storage-orchestrator.service.d.ts +236 -0
  127. package/dist/builtins/storage-orchestrator/storage-pressure-manager.d.ts +38 -0
  128. package/dist/builtins/system-backup/system-backup.service.d.ts +137 -0
  129. package/dist/builtins/system-config/index.d.ts +1 -0
  130. package/dist/builtins/system-config/index.js +8 -0
  131. package/dist/builtins/system-config/index.mjs +2 -0
  132. package/dist/builtins/system-config/system-config.addon.d.ts +10 -0
  133. package/dist/builtins/system-config/system-config.addon.js +232 -0
  134. package/dist/builtins/system-config/system-config.addon.mjs +226 -0
  135. package/dist/builtins/winston-logging/index.d.ts +3 -0
  136. package/dist/builtins/winston-logging/index.js +156 -0
  137. package/dist/builtins/winston-logging/index.mjs +144 -0
  138. package/dist/builtins/winston-logging/winston-destination.d.ts +21 -0
  139. package/dist/builtins/winston-logging/winston-logging.addon.d.ts +19 -0
  140. package/dist/chunk-CNf5ZN-e.mjs +37 -0
  141. package/dist/chunk-Cek0wNdY.js +64 -0
  142. package/dist/download/model-download-service.d.ts +41 -0
  143. package/dist/download/model-downloader.d.ts +31 -0
  144. package/dist/events/event-bus.d.ts +10 -0
  145. package/dist/events/system-event-bus.d.ts +14 -0
  146. package/dist/feature/feature-manager.d.ts +11 -0
  147. package/dist/formatter-B7qW8bPJ.mjs +162 -0
  148. package/dist/formatter-DqAKDlvN.js +167 -0
  149. package/dist/http/authenticated-file-server.d.ts +53 -0
  150. package/dist/http/data-plane-registry.d.ts +23 -0
  151. package/dist/http/file-data-plane.d.ts +10 -0
  152. package/dist/http/reverse-proxy.d.ts +15 -0
  153. package/dist/index.d.ts +82 -0
  154. package/dist/index.js +93485 -0
  155. package/dist/index.mjs +93179 -0
  156. package/dist/intel-accelerators-Gg0P5mnl.js +20 -0
  157. package/dist/intel-accelerators-hGgpZ0pX.mjs +19 -0
  158. package/dist/kernel/addon-class-resolver.d.ts +4 -0
  159. package/dist/kernel/addon-engine-manager.d.ts +22 -0
  160. package/dist/kernel/addon-health-monitor.d.ts +154 -0
  161. package/dist/kernel/addon-installer.d.ts +208 -0
  162. package/dist/kernel/addon-loader.d.ts +106 -0
  163. package/dist/kernel/addon-manifest.d.ts +77 -0
  164. package/dist/kernel/capability-handle.d.ts +46 -0
  165. package/dist/kernel/capability-registry.d.ts +412 -0
  166. package/dist/kernel/config-manager.d.ts +212 -0
  167. package/dist/kernel/config-schema.d.ts +93 -0
  168. package/dist/kernel/custom-action-registry.d.ts +23 -0
  169. package/dist/kernel/deps/addon-deps-manager.d.ts +19 -0
  170. package/dist/kernel/deps/manifest-native-deps.d.ts +25 -0
  171. package/dist/kernel/deps/manifest-python-deps.d.ts +20 -0
  172. package/dist/kernel/device-registry.d.ts +29 -0
  173. package/dist/kernel/fs-utils.d.ts +41 -0
  174. package/dist/kernel/hwaccel/hwaccel-resolver.d.ts +19 -0
  175. package/dist/kernel/hwaccel/hwaccel-service.d.ts +4 -0
  176. package/dist/kernel/index.d.ts +74 -0
  177. package/dist/kernel/infra-capabilities.d.ts +13 -0
  178. package/dist/kernel/moleculer/addon-context-factory.d.ts +91 -0
  179. package/dist/kernel/moleculer/addon-data-plane-facility.d.ts +19 -0
  180. package/dist/kernel/moleculer/addon-runner.d.ts +1 -0
  181. package/dist/kernel/moleculer/addon-service-factory.d.ts +50 -0
  182. package/dist/kernel/moleculer/broker-factory.d.ts +50 -0
  183. package/dist/kernel/moleculer/cap-usage-registry.d.ts +46 -0
  184. package/dist/kernel/moleculer/capabilities-access.d.ts +21 -0
  185. package/dist/kernel/moleculer/child-addon-call-dispatch.d.ts +46 -0
  186. package/dist/kernel/moleculer/child-cap-dispatch.d.ts +20 -0
  187. package/dist/kernel/moleculer/cluster-secret.d.ts +15 -0
  188. package/dist/kernel/moleculer/core-cap-service.d.ts +50 -0
  189. package/dist/kernel/moleculer/crash-supervisor.d.ts +50 -0
  190. package/dist/kernel/moleculer/device-cap-proxy.d.ts +79 -0
  191. package/dist/kernel/moleculer/event-bus-core.d.ts +53 -0
  192. package/dist/kernel/moleculer/event-bus.d.ts +53 -0
  193. package/dist/kernel/moleculer/hub-log-forwarder.d.ts +36 -0
  194. package/dist/kernel/moleculer/hub-service.d.ts +35 -0
  195. package/dist/kernel/moleculer/node-registry.d.ts +126 -0
  196. package/dist/kernel/moleculer/process-context.d.ts +4 -0
  197. package/dist/kernel/moleculer/process-service.d.ts +72 -0
  198. package/dist/kernel/moleculer/provider-registry.d.ts +28 -0
  199. package/dist/kernel/moleculer/readiness-context.d.ts +62 -0
  200. package/dist/kernel/moleculer/readiness-service.d.ts +7 -0
  201. package/dist/kernel/moleculer/register-node-client.d.ts +35 -0
  202. package/dist/kernel/moleculer/remote-logger.d.ts +43 -0
  203. package/dist/kernel/moleculer/resilient-cap-call.d.ts +28 -0
  204. package/dist/kernel/moleculer/stream-probe-service.d.ts +9 -0
  205. package/dist/kernel/moleculer/trpc-links.d.ts +189 -0
  206. package/dist/kernel/moleculer/typed-array-serde.d.ts +25 -0
  207. package/dist/kernel/moleculer/worker-device-restore.d.ts +10 -0
  208. package/dist/kernel/provider-kind-drift.d.ts +12 -0
  209. package/dist/kernel/restart-coordinator.d.ts +90 -0
  210. package/dist/kernel/storage-location-registry.d.ts +40 -0
  211. package/dist/kernel/transport/cap-action-name.d.ts +100 -0
  212. package/dist/kernel/transport/cap-route-resolver.d.ts +148 -0
  213. package/dist/kernel/transport/cap-route.d.ts +148 -0
  214. package/dist/kernel/transport/child-cap-protocol.d.ts +136 -0
  215. package/dist/kernel/transport/create-local-transport.d.ts +7 -0
  216. package/dist/kernel/transport/frame-codec.d.ts +7 -0
  217. package/dist/kernel/transport/index.d.ts +27 -0
  218. package/dist/kernel/transport/local-child-client.d.ts +136 -0
  219. package/dist/kernel/transport/local-child-registry.d.ts +179 -0
  220. package/dist/kernel/transport/local-endpoint-path.d.ts +6 -0
  221. package/dist/kernel/transport/local-transport.d.ts +46 -0
  222. package/dist/kernel/transport/parent-unowned-call.d.ts +75 -0
  223. package/dist/kernel/transport/socket-channel.d.ts +27 -0
  224. package/dist/kernel/transport/uds-event-bridge.d.ts +36 -0
  225. package/dist/kernel/transport/uds-event-bus.d.ts +22 -0
  226. package/dist/kernel/transport/uds-local-transport.d.ts +18 -0
  227. package/dist/kernel/transport/uds-log-ingest.d.ts +28 -0
  228. package/dist/kernel/transport/uds-logger.d.ts +44 -0
  229. package/dist/kernel/utils/ring-buffer.d.ts +15 -0
  230. package/dist/kernel/workspace-detect.d.ts +9 -0
  231. package/dist/lifecycle/lifecycle-state-machine.d.ts +28 -0
  232. package/dist/logging/formatter.d.ts +30 -0
  233. package/dist/logging/log-manager.d.ts +54 -0
  234. package/dist/logging/log-ring-buffer.d.ts +47 -0
  235. package/dist/logging/partitioned-log-buffer.d.ts +35 -0
  236. package/dist/logging/scoped-logger.d.ts +17 -0
  237. package/dist/main-DNnMW7Z2.js +9983 -0
  238. package/dist/main-rtjOwPBR.mjs +9976 -0
  239. package/dist/manifest-python-deps-D1DbAQEv.js +6724 -0
  240. package/dist/manifest-python-deps-DZsKTbs1.mjs +6315 -0
  241. package/dist/network/network-quality.d.ts +11 -0
  242. package/dist/notification/notification-service.d.ts +37 -0
  243. package/dist/notification/toast-service.d.ts +22 -0
  244. package/dist/pipeline/engine-manager-resolver.d.ts +15 -0
  245. package/dist/pipeline/pipeline-runner.d.ts +8 -0
  246. package/dist/pipeline/pipeline-validator.d.ts +13 -0
  247. package/dist/process/resource-monitor.d.ts +11 -0
  248. package/dist/python/python-env-manager.d.ts +12 -0
  249. package/dist/repl/interfaces.d.ts +31 -0
  250. package/dist/repl/repl-engine.d.ts +8 -0
  251. package/dist/resource-monitor-ClDGFyf6.mjs +57 -0
  252. package/dist/resource-monitor-IIEanuJt.js +74 -0
  253. package/dist/settle-sources-Bhsy57y-.js +38 -0
  254. package/dist/settle-sources-CDtNC8ub.mjs +33 -0
  255. package/dist/storage/fs-storage-backend.d.ts +40 -0
  256. package/dist/storage/storage-location-manager.d.ts +23 -0
  257. package/dist/storage/storage-manager.d.ts +83 -0
  258. package/dist/tar-BgAEMRBR.js +5434 -0
  259. package/dist/tar-ByMOPNM0.mjs +5429 -0
  260. package/dist/tls/cert-manager.d.ts +26 -0
  261. package/dist/tls/index.d.ts +1 -0
  262. package/package.json +343 -0
@@ -0,0 +1,29 @@
1
+ import { PlatformScore, HardwareInfo, ModelRequirement, ResolvedInferenceConfig } from '@camstack/types';
2
+ export declare class InferenceConfigResolver {
3
+ private readonly scores;
4
+ private readonly hardware;
5
+ constructor(scores: readonly PlatformScore[], hardware: HardwareInfo);
6
+ /**
7
+ * Compute accuracy/backend weights based on available system RAM.
8
+ * availableRAM_MB is now sourced from systeminformation (reliable cross-platform),
9
+ * not os.freemem() which is broken on macOS.
10
+ *
11
+ * - > 16 GB available: prefer larger, more accurate models (accuracy 0.6, backend 0.4)
12
+ * - > 8 GB available: balanced (accuracy 0.5, backend 0.5)
13
+ * - <= 8 GB available: prefer speed (accuracy 0.4, backend 0.6)
14
+ */
15
+ private getWeights;
16
+ /**
17
+ * Given an addon's model requirements, pick the best model + runtime + backend.
18
+ *
19
+ * Algorithm:
20
+ * 1. Filter models by available RAM (minRAM_MB < 25% of available RAM)
21
+ * 2. For each remaining model, find the best platform score whose format
22
+ * is available in the model's formats
23
+ * 3. Pick the model with the highest combined score using RAM-adaptive weights:
24
+ * - High RAM (>16 GB): accuracy × 0.6 + backend × 0.4 (prefer accuracy)
25
+ * - Mid RAM (>8 GB): accuracy × 0.5 + backend × 0.5 (balanced)
26
+ * - Low RAM (<=8 GB): accuracy × 0.4 + backend × 0.6 (prefer speed)
27
+ */
28
+ resolve(requirements: readonly ModelRequirement[]): ResolvedInferenceConfig;
29
+ }
@@ -0,0 +1,11 @@
1
+ import { GpuInfo, NpuInfo } from '@camstack/types';
2
+ export interface AcceleratorFs {
3
+ listRenderNodes(): readonly string[];
4
+ readVendor(renderNode: string): string;
5
+ exists(path: string): boolean;
6
+ }
7
+ export interface IntelAccelerators {
8
+ gpu: GpuInfo | null;
9
+ npu: NpuInfo | null;
10
+ }
11
+ export declare function classifyIntelAccelerators(fsx: AcceleratorFs): IntelAccelerators;
@@ -0,0 +1,30 @@
1
+ import { HardwareInfo, PlatformCapabilities, IScopedLogger } from '@camstack/types';
2
+ export declare class PlatformScorer {
3
+ private cached;
4
+ private readonly logger;
5
+ /**
6
+ * Path to the embedded portable Python (from `ctx.deps.ensurePython()`).
7
+ * The Docker hub ships NO system `python3` — inference runs on the
8
+ * downloaded portable build — so probing system `python3`/`python` would
9
+ * wrongly report "Python not found" and never surface coreml/openvino
10
+ * backends. When set, the Python module probes run against THIS binary;
11
+ * `null` falls back to a system `python3`/`python` lookup (dev / agent
12
+ * environments where Python is on PATH).
13
+ */
14
+ private readonly embeddedPythonPath;
15
+ constructor(logger?: IScopedLogger, embeddedPythonPath?: string | null);
16
+ /**
17
+ * Probe hardware + runtimes and score all backend combos.
18
+ *
19
+ * An optional `onPhase` callback is invoked at each step so consumers
20
+ * (e.g. the platform-probe addon) can emit live progress events on
21
+ * the event bus. The callback takes a phase id + a typed payload; all
22
+ * phases fire in strict order: `started` → `hardware` → `node-backends`
23
+ * → `python-backends` → `scored` → `done`. On failure, `error` fires
24
+ * once with the exception. Cached after first call.
25
+ */
26
+ probe(onPhase?: (phase: string, payload?: Record<string, unknown>) => void): Promise<PlatformCapabilities>;
27
+ probeHardware(): Promise<HardwareInfo>;
28
+ private probePythonBackends;
29
+ private scoreBackends;
30
+ }
@@ -0,0 +1,6 @@
1
+ import { HardwareInfo } from '@camstack/types';
2
+ export interface RuntimePackageSet {
3
+ requirementsFiles: string[];
4
+ backendIds: string[];
5
+ }
6
+ export declare function resolveRuntimePackages(hardware: HardwareInfo): RuntimePackageSet;
@@ -0,0 +1,96 @@
1
+ /**
2
+ * Pure reconciliation core for the remote-access orchestrator's durable
3
+ * `enabledProviders` set (D8 delivery-rule fix).
4
+ *
5
+ * Why this module exists
6
+ * ----------------------
7
+ * `enabledProviders: string[]` is the operator's "auto-start on boot"
8
+ * intent — a DURABLE setting. Historically it was written ONLY from two
9
+ * fire-and-forget bus events (`NetworkTunnelStarted` / `Stopped`). A
10
+ * dropped event (hub restart, addon crash-respawn, hub↔orchestrator
11
+ * partition) silently diverges the persisted set from reality:
12
+ * - dropped `Started` → tunnel running, not recorded → no auto-start
13
+ * - dropped `Stopped` → tunnel stopped, still recorded → boot restarts
14
+ * an operator-stopped tunnel.
15
+ *
16
+ * A durable setting must not be written by a lossy event. The fix is an
17
+ * idempotent reconcile pass that pulls authoritative state via an
18
+ * ACKNOWLEDGED RPC (`network-access` cap `getStatus`) on every provider
19
+ * (re)connect — mirroring the kernel readiness-registry hydration via
20
+ * `$readiness.getSnapshot`. The lifecycle events stay (still fine for
21
+ * live UI dashboards); only the PERSISTENCE WRITE moves to the RPC pull.
22
+ *
23
+ * Reconcile semantics — ADD-ONLY (deliberately conservative)
24
+ * ----------------------------------------------------------
25
+ * `connected: true` from an acked RPC is UNAMBIGUOUS: the tunnel is up,
26
+ * so the operator must have started it → safe to ADD to `enabledProviders`
27
+ * (recovers a dropped `NetworkTunnelStarted` event).
28
+ *
29
+ * `connected: false` is AMBIGUOUS:
30
+ * - Provider registered but not yet started (normal cold-boot state,
31
+ * BEFORE `autoStartEnabledProviders` has called `start()`).
32
+ * - Provider transiently down (network blip, restart in progress).
33
+ * - Provider intentionally stopped by the operator.
34
+ * `getStatus()` reports connectivity, NOT operator intent. Acting on
35
+ * `connected: false` would wipe `enabledProviders` on every hub restart
36
+ * (providers re-register ~15-20 s before `start()` is called), defeating
37
+ * the purpose of the durable enabled-set. Therefore the reconcile pass
38
+ * NEVER removes on `connected: false`.
39
+ *
40
+ * Removal of operator intent stays event-driven (`NetworkTunnelStopped`
41
+ * → `markEnabled(id, false)`). That event is emitted synchronously by
42
+ * the provider's own `stop()` call — it is the reliable signal that the
43
+ * operator actually stopped the tunnel. A failed/absent RPC probe also
44
+ * leaves the provider untouched.
45
+ *
46
+ * // Follow-up: covering the dropped-`Stopped` direction (a `Stopped`
47
+ * // event lost → tunnel stopped but still in enabledProviders → boot
48
+ * // wrongly restarts it) would require a provider-side persisted
49
+ * // operator-intent flag that `getStatus()` surfaces. That is a larger
50
+ * // multi-addon change (the audit's "approach 2") and is OUT OF SCOPE
51
+ * // for this backstop. The current fix covers the higher-impact direction
52
+ * // (dropped `Started` → operator's running tunnel not auto-restarted).
53
+ *
54
+ * The function is pure: the addon owns the RPC fan-out + the persist
55
+ * call, so this core is unit-testable without a CapabilityRegistry.
56
+ */
57
+ /**
58
+ * Outcome of one provider's `getStatus()` RPC probe.
59
+ *
60
+ * `ok: true` → the RPC was acknowledged; `connected` is authoritative.
61
+ * `ok: false` → the RPC threw / timed out; state is unknown and the
62
+ * provider's membership must be left as-is.
63
+ */
64
+ export type ProviderProbeResult = {
65
+ readonly addonId: string;
66
+ readonly ok: true;
67
+ readonly connected: boolean;
68
+ } | {
69
+ readonly addonId: string;
70
+ readonly ok: false;
71
+ };
72
+ export interface ReconcileResult {
73
+ /** The corrected enabled-set, sorted for stable persistence. */
74
+ readonly nextEnabled: readonly string[];
75
+ /** `true` when `nextEnabled` differs from the input — caller persists only then. */
76
+ readonly changed: boolean;
77
+ /** addonIds added because an acked RPC reported them connected. */
78
+ readonly added: readonly string[];
79
+ /**
80
+ * Always empty — reconcile is add-only. Removal of operator intent is
81
+ * event-driven (`NetworkTunnelStopped`). Kept in the type so callers
82
+ * that log `result.removed` continue to compile without changes.
83
+ */
84
+ readonly removed: readonly string[];
85
+ }
86
+ /**
87
+ * Reconcile the durable `enabledProviders` set against authoritative
88
+ * RPC probe results. Pure — no I/O. ADD-ONLY: only adds providers whose
89
+ * acked `getStatus()` reports `connected: true`. Never removes on
90
+ * `connected: false` — see module doc for the full rationale.
91
+ *
92
+ * @param currentEnabled - the persisted enabled-set before reconcile.
93
+ * @param probes - one entry per provider whose `getStatus()` RPC was
94
+ * attempted this pass. Providers absent from this list are untouched.
95
+ */
96
+ export declare function reconcileEnabledProviders(currentEnabled: readonly string[], probes: readonly ProviderProbeResult[]): ReconcileResult;
@@ -0,0 +1 @@
1
+ export { RemoteAccessOrchestratorAddon, default } from './remote-access-orchestrator.addon.js';
@@ -0,0 +1,8 @@
1
+ Object.defineProperties(exports, {
2
+ __esModule: { value: true },
3
+ [Symbol.toStringTag]: { value: "Module" }
4
+ });
5
+ require("../../chunk-Cek0wNdY.js");
6
+ const require_builtins_remote_access_orchestrator_remote_access_orchestrator_addon = require("./remote-access-orchestrator.addon.js");
7
+ exports.RemoteAccessOrchestratorAddon = require_builtins_remote_access_orchestrator_remote_access_orchestrator_addon.RemoteAccessOrchestratorAddon;
8
+ exports.default = require_builtins_remote_access_orchestrator_remote_access_orchestrator_addon.RemoteAccessOrchestratorAddon;
@@ -0,0 +1,2 @@
1
+ import { RemoteAccessOrchestratorAddon } from "./remote-access-orchestrator.addon.mjs";
2
+ export { RemoteAccessOrchestratorAddon, RemoteAccessOrchestratorAddon as default };
@@ -0,0 +1,40 @@
1
+ import { BaseAddon, ProviderRegistration } from '@camstack/types';
2
+ interface RemoteAccessOrchestratorConfig {
3
+ /**
4
+ * addonIds the operator has explicitly Started. Auto-respawned on
5
+ * boot so a tunnel set up once stays up across hub restarts.
6
+ */
7
+ readonly enabledProviders: readonly string[];
8
+ }
9
+ export declare class RemoteAccessOrchestratorAddon extends BaseAddon<RemoteAccessOrchestratorConfig> {
10
+ constructor();
11
+ protected onInitialize(): Promise<ProviderRegistration[]>;
12
+ /**
13
+ * Maintain the persisted `enabledProviders` set from a tunnel
14
+ * lifecycle event. `source.id` is `string | number`; `network-access`
15
+ * providers emit with `type: 'addon'` so it is always the addonId
16
+ * string. Non-string / non-addon sources are ignored defensively.
17
+ */
18
+ private onTunnelLifecycle;
19
+ /**
20
+ * Probe every locally-visible `network-access` provider's
21
+ * `getStatus()` over RPC and reconcile the durable `enabledProviders`
22
+ * set against the result. This is the D8 backstop for dropped
23
+ * `NetworkTunnelStarted` events: if `connected: true` is acked, the
24
+ * provider is added to `enabledProviders`. ADD-ONLY — never removes on
25
+ * `connected: false` (see enabled-providers-reconcile.ts for rationale).
26
+ *
27
+ * `getStatus()` is an acknowledged cap RPC — a transport blip surfaces
28
+ * as a rejected promise (recorded as `ok: false`, membership left
29
+ * untouched), never as a silent lossy write. Runs on every provider
30
+ * (re)connect via the `watchCapability` hooks, mirroring the kernel
31
+ * readiness-registry hydration on `$node.connected`. Safe to call
32
+ * before `autoStartEnabledProviders`: add-only semantics mean it cannot
33
+ * wipe the enabled-set even when providers are registered-not-yet-started.
34
+ */
35
+ private reconcileAndPersist;
36
+ private autoStartEnabledProviders;
37
+ private markEnabled;
38
+ private resolveImpl;
39
+ }
40
+ export default RemoteAccessOrchestratorAddon;
@@ -0,0 +1,214 @@
1
+ Object.defineProperties(exports, {
2
+ __esModule: { value: true },
3
+ [Symbol.toStringTag]: { value: "Module" }
4
+ });
5
+ require("../../chunk-Cek0wNdY.js");
6
+ let _camstack_types = require("@camstack/types");
7
+ //#region src/builtins/remote-access-orchestrator/enabled-providers-reconcile.ts
8
+ /**
9
+ * Reconcile the durable `enabledProviders` set against authoritative
10
+ * RPC probe results. Pure — no I/O. ADD-ONLY: only adds providers whose
11
+ * acked `getStatus()` reports `connected: true`. Never removes on
12
+ * `connected: false` — see module doc for the full rationale.
13
+ *
14
+ * @param currentEnabled - the persisted enabled-set before reconcile.
15
+ * @param probes - one entry per provider whose `getStatus()` RPC was
16
+ * attempted this pass. Providers absent from this list are untouched.
17
+ */
18
+ function reconcileEnabledProviders(currentEnabled, probes) {
19
+ const next = new Set(currentEnabled);
20
+ const added = [];
21
+ for (const probe of probes) {
22
+ if (!probe.ok) continue;
23
+ if (probe.connected) {
24
+ if (!next.has(probe.addonId)) {
25
+ next.add(probe.addonId);
26
+ added.push(probe.addonId);
27
+ }
28
+ }
29
+ }
30
+ return {
31
+ nextEnabled: [...next].toSorted(),
32
+ changed: added.length > 0,
33
+ added,
34
+ removed: []
35
+ };
36
+ }
37
+ //#endregion
38
+ //#region src/builtins/remote-access-orchestrator/remote-access-orchestrator.addon.ts
39
+ /**
40
+ * Remote-access orchestrator — backend-only boot-autostart service for
41
+ * the `network-access` collection (Cloudflare Tunnel, ngrok, Tailscale, …).
42
+ *
43
+ * Retired its `remote-access` facade cap (2026-05-15): the admin UI now
44
+ * talks to the `network-access` collection cap directly via generic
45
+ * per-`addonId` routing, so this addon registers NO capability.
46
+ *
47
+ * What it still owns — the load-bearing logic:
48
+ * The orchestrator owns the "operator wants this provider running"
49
+ * intent — an `enabledProviders: string[]` slice in its addon-store
50
+ * blob (BaseAddon.config). On boot we iterate the list and call
51
+ * `provider.start()` for each enabled entry, so a tunnel set up once
52
+ * stays up across hub restarts.
53
+ *
54
+ * Since start/stop no longer flow through this addon, the enabled-set
55
+ * is kept in sync from two sources:
56
+ * 1. `NetworkTunnelStarted` / `NetworkTunnelStopped` bus events —
57
+ * fast, but lossy (fire-and-forget broadcasts). They drive both
58
+ * the live UI and removal from the durable set (`Stopped` is the
59
+ * only reliable "operator stopped it" signal).
60
+ * 2. An RPC-driven ADD-ONLY RECONCILE pass (`reconcileEnabledProviders`)
61
+ * that pulls authoritative `connected` state via the `network-access`
62
+ * cap's `getStatus()` on every provider (re)connect. THIS covers
63
+ * dropped `NetworkTunnelStarted` events — if `connected: true` is
64
+ * acked, the provider is added to `enabledProviders`. It NEVER
65
+ * removes on `connected: false` because that signal is ambiguous
66
+ * (registered-not-yet-started vs transiently-down vs intentionally
67
+ * stopped). Running before `autoStartEnabledProviders` is safe:
68
+ * it can only add already-connected providers, never evict.
69
+ */
70
+ var RemoteAccessOrchestratorAddon = class extends _camstack_types.BaseAddon {
71
+ constructor() {
72
+ super({ enabledProviders: [] });
73
+ }
74
+ async onInitialize() {
75
+ this.ctx.logger.info("Remote-access orchestrator initialized (backend-only)", { meta: { enabledCount: this.config.enabledProviders.length } });
76
+ this.ctx.eventBus?.subscribe({ category: _camstack_types.EventCategory.NetworkTunnelStarted }, (event) => {
77
+ this.onTunnelLifecycle(event.source, true);
78
+ });
79
+ this.ctx.eventBus?.subscribe({ category: _camstack_types.EventCategory.NetworkTunnelStopped }, (event) => {
80
+ this.onTunnelLifecycle(event.source, false);
81
+ });
82
+ setImmediate(() => {
83
+ this.autoStartEnabledProviders();
84
+ });
85
+ this.watchCapability("network-access", { onReady: () => {
86
+ this.autoStartEnabledProviders();
87
+ } });
88
+ this.watchCapability("mesh-network", { onReady: () => {
89
+ this.autoStartEnabledProviders();
90
+ } });
91
+ return [];
92
+ }
93
+ /**
94
+ * Maintain the persisted `enabledProviders` set from a tunnel
95
+ * lifecycle event. `source.id` is `string | number`; `network-access`
96
+ * providers emit with `type: 'addon'` so it is always the addonId
97
+ * string. Non-string / non-addon sources are ignored defensively.
98
+ */
99
+ async onTunnelLifecycle(source, started) {
100
+ if (source.type !== "addon" || typeof source.id !== "string") {
101
+ this.ctx.logger.warn("tunnel lifecycle event with non-addon source — ignoring", { meta: {
102
+ sourceType: source.type,
103
+ sourceId: source.id,
104
+ started
105
+ } });
106
+ return;
107
+ }
108
+ await this.markEnabled(source.id, started);
109
+ }
110
+ /**
111
+ * Probe every locally-visible `network-access` provider's
112
+ * `getStatus()` over RPC and reconcile the durable `enabledProviders`
113
+ * set against the result. This is the D8 backstop for dropped
114
+ * `NetworkTunnelStarted` events: if `connected: true` is acked, the
115
+ * provider is added to `enabledProviders`. ADD-ONLY — never removes on
116
+ * `connected: false` (see enabled-providers-reconcile.ts for rationale).
117
+ *
118
+ * `getStatus()` is an acknowledged cap RPC — a transport blip surfaces
119
+ * as a rejected promise (recorded as `ok: false`, membership left
120
+ * untouched), never as a silent lossy write. Runs on every provider
121
+ * (re)connect via the `watchCapability` hooks, mirroring the kernel
122
+ * readiness-registry hydration on `$node.connected`. Safe to call
123
+ * before `autoStartEnabledProviders`: add-only semantics mean it cannot
124
+ * wipe the enabled-set even when providers are registered-not-yet-started.
125
+ */
126
+ async reconcileAndPersist() {
127
+ const entries = this.capabilities?.getCollectionEntries("network-access") ?? [];
128
+ if (entries.length === 0) return;
129
+ const probes = await Promise.all(entries.map(async ([addonId, impl]) => {
130
+ if (!impl.getStatus) return {
131
+ addonId,
132
+ ok: false
133
+ };
134
+ try {
135
+ return {
136
+ addonId,
137
+ ok: true,
138
+ connected: (await impl.getStatus()).connected
139
+ };
140
+ } catch (err) {
141
+ this.ctx.logger.warn("reconcile: getStatus RPC failed — leaving membership as-is", { meta: {
142
+ addonId,
143
+ error: err instanceof Error ? err.message : String(err)
144
+ } });
145
+ return {
146
+ addonId,
147
+ ok: false
148
+ };
149
+ }
150
+ }));
151
+ const result = reconcileEnabledProviders(this.config.enabledProviders, probes);
152
+ if (!result.changed) return;
153
+ this.ctx.logger.info("reconcile: corrected enabledProviders from RPC-pulled state", { meta: {
154
+ added: result.added,
155
+ removed: result.removed
156
+ } });
157
+ await this.updateGlobalSettings({ enabledProviders: result.nextEnabled });
158
+ }
159
+ async autoStartEnabledProviders() {
160
+ await this.reconcileAndPersist();
161
+ const ids = this.config.enabledProviders;
162
+ if (ids.length === 0) return;
163
+ this.ctx.logger.info("Auto-starting enabled remote-access providers", { meta: { addonIds: [...ids] } });
164
+ for (const addonId of ids) try {
165
+ const impl = this.resolveImpl(addonId);
166
+ if (!impl?.start) {
167
+ this.ctx.logger.warn("autostart: provider not ready or unsupported", { meta: {
168
+ addonId,
169
+ hasImpl: !!impl,
170
+ hasStart: !!impl?.start
171
+ } });
172
+ continue;
173
+ }
174
+ if (impl.getStatus) {
175
+ const status = await impl.getStatus().catch(() => null);
176
+ if (status?.connected) {
177
+ this.ctx.logger.info("autostart: provider already connected — skipping", { meta: {
178
+ addonId,
179
+ url: status.endpoint?.url
180
+ } });
181
+ continue;
182
+ }
183
+ }
184
+ const endpoint = await impl.start();
185
+ this.ctx.logger.info("autostart: provider started", { meta: {
186
+ addonId,
187
+ url: endpoint.url
188
+ } });
189
+ } catch (err) {
190
+ this.ctx.logger.error("autostart: provider start failed", { meta: {
191
+ addonId,
192
+ error: err instanceof Error ? err.message : String(err)
193
+ } });
194
+ }
195
+ }
196
+ async markEnabled(addonId, enabled) {
197
+ const current = new Set(this.config.enabledProviders);
198
+ const wasEnabled = current.has(addonId);
199
+ if (enabled) current.add(addonId);
200
+ else current.delete(addonId);
201
+ if (wasEnabled === enabled) return;
202
+ this.ctx.logger.info("remote-access intent updated", { meta: {
203
+ addonId,
204
+ enabled
205
+ } });
206
+ await this.updateGlobalSettings({ enabledProviders: [...current] });
207
+ }
208
+ resolveImpl(addonId) {
209
+ return (this.capabilities?.getCollectionEntries("network-access") ?? []).find(([id]) => id === addonId)?.[1] ?? null;
210
+ }
211
+ };
212
+ //#endregion
213
+ exports.RemoteAccessOrchestratorAddon = RemoteAccessOrchestratorAddon;
214
+ exports.default = RemoteAccessOrchestratorAddon;
@@ -0,0 +1,208 @@
1
+ import { BaseAddon, EventCategory } from "@camstack/types";
2
+ //#region src/builtins/remote-access-orchestrator/enabled-providers-reconcile.ts
3
+ /**
4
+ * Reconcile the durable `enabledProviders` set against authoritative
5
+ * RPC probe results. Pure — no I/O. ADD-ONLY: only adds providers whose
6
+ * acked `getStatus()` reports `connected: true`. Never removes on
7
+ * `connected: false` — see module doc for the full rationale.
8
+ *
9
+ * @param currentEnabled - the persisted enabled-set before reconcile.
10
+ * @param probes - one entry per provider whose `getStatus()` RPC was
11
+ * attempted this pass. Providers absent from this list are untouched.
12
+ */
13
+ function reconcileEnabledProviders(currentEnabled, probes) {
14
+ const next = new Set(currentEnabled);
15
+ const added = [];
16
+ for (const probe of probes) {
17
+ if (!probe.ok) continue;
18
+ if (probe.connected) {
19
+ if (!next.has(probe.addonId)) {
20
+ next.add(probe.addonId);
21
+ added.push(probe.addonId);
22
+ }
23
+ }
24
+ }
25
+ return {
26
+ nextEnabled: [...next].toSorted(),
27
+ changed: added.length > 0,
28
+ added,
29
+ removed: []
30
+ };
31
+ }
32
+ //#endregion
33
+ //#region src/builtins/remote-access-orchestrator/remote-access-orchestrator.addon.ts
34
+ /**
35
+ * Remote-access orchestrator — backend-only boot-autostart service for
36
+ * the `network-access` collection (Cloudflare Tunnel, ngrok, Tailscale, …).
37
+ *
38
+ * Retired its `remote-access` facade cap (2026-05-15): the admin UI now
39
+ * talks to the `network-access` collection cap directly via generic
40
+ * per-`addonId` routing, so this addon registers NO capability.
41
+ *
42
+ * What it still owns — the load-bearing logic:
43
+ * The orchestrator owns the "operator wants this provider running"
44
+ * intent — an `enabledProviders: string[]` slice in its addon-store
45
+ * blob (BaseAddon.config). On boot we iterate the list and call
46
+ * `provider.start()` for each enabled entry, so a tunnel set up once
47
+ * stays up across hub restarts.
48
+ *
49
+ * Since start/stop no longer flow through this addon, the enabled-set
50
+ * is kept in sync from two sources:
51
+ * 1. `NetworkTunnelStarted` / `NetworkTunnelStopped` bus events —
52
+ * fast, but lossy (fire-and-forget broadcasts). They drive both
53
+ * the live UI and removal from the durable set (`Stopped` is the
54
+ * only reliable "operator stopped it" signal).
55
+ * 2. An RPC-driven ADD-ONLY RECONCILE pass (`reconcileEnabledProviders`)
56
+ * that pulls authoritative `connected` state via the `network-access`
57
+ * cap's `getStatus()` on every provider (re)connect. THIS covers
58
+ * dropped `NetworkTunnelStarted` events — if `connected: true` is
59
+ * acked, the provider is added to `enabledProviders`. It NEVER
60
+ * removes on `connected: false` because that signal is ambiguous
61
+ * (registered-not-yet-started vs transiently-down vs intentionally
62
+ * stopped). Running before `autoStartEnabledProviders` is safe:
63
+ * it can only add already-connected providers, never evict.
64
+ */
65
+ var RemoteAccessOrchestratorAddon = class extends BaseAddon {
66
+ constructor() {
67
+ super({ enabledProviders: [] });
68
+ }
69
+ async onInitialize() {
70
+ this.ctx.logger.info("Remote-access orchestrator initialized (backend-only)", { meta: { enabledCount: this.config.enabledProviders.length } });
71
+ this.ctx.eventBus?.subscribe({ category: EventCategory.NetworkTunnelStarted }, (event) => {
72
+ this.onTunnelLifecycle(event.source, true);
73
+ });
74
+ this.ctx.eventBus?.subscribe({ category: EventCategory.NetworkTunnelStopped }, (event) => {
75
+ this.onTunnelLifecycle(event.source, false);
76
+ });
77
+ setImmediate(() => {
78
+ this.autoStartEnabledProviders();
79
+ });
80
+ this.watchCapability("network-access", { onReady: () => {
81
+ this.autoStartEnabledProviders();
82
+ } });
83
+ this.watchCapability("mesh-network", { onReady: () => {
84
+ this.autoStartEnabledProviders();
85
+ } });
86
+ return [];
87
+ }
88
+ /**
89
+ * Maintain the persisted `enabledProviders` set from a tunnel
90
+ * lifecycle event. `source.id` is `string | number`; `network-access`
91
+ * providers emit with `type: 'addon'` so it is always the addonId
92
+ * string. Non-string / non-addon sources are ignored defensively.
93
+ */
94
+ async onTunnelLifecycle(source, started) {
95
+ if (source.type !== "addon" || typeof source.id !== "string") {
96
+ this.ctx.logger.warn("tunnel lifecycle event with non-addon source — ignoring", { meta: {
97
+ sourceType: source.type,
98
+ sourceId: source.id,
99
+ started
100
+ } });
101
+ return;
102
+ }
103
+ await this.markEnabled(source.id, started);
104
+ }
105
+ /**
106
+ * Probe every locally-visible `network-access` provider's
107
+ * `getStatus()` over RPC and reconcile the durable `enabledProviders`
108
+ * set against the result. This is the D8 backstop for dropped
109
+ * `NetworkTunnelStarted` events: if `connected: true` is acked, the
110
+ * provider is added to `enabledProviders`. ADD-ONLY — never removes on
111
+ * `connected: false` (see enabled-providers-reconcile.ts for rationale).
112
+ *
113
+ * `getStatus()` is an acknowledged cap RPC — a transport blip surfaces
114
+ * as a rejected promise (recorded as `ok: false`, membership left
115
+ * untouched), never as a silent lossy write. Runs on every provider
116
+ * (re)connect via the `watchCapability` hooks, mirroring the kernel
117
+ * readiness-registry hydration on `$node.connected`. Safe to call
118
+ * before `autoStartEnabledProviders`: add-only semantics mean it cannot
119
+ * wipe the enabled-set even when providers are registered-not-yet-started.
120
+ */
121
+ async reconcileAndPersist() {
122
+ const entries = this.capabilities?.getCollectionEntries("network-access") ?? [];
123
+ if (entries.length === 0) return;
124
+ const probes = await Promise.all(entries.map(async ([addonId, impl]) => {
125
+ if (!impl.getStatus) return {
126
+ addonId,
127
+ ok: false
128
+ };
129
+ try {
130
+ return {
131
+ addonId,
132
+ ok: true,
133
+ connected: (await impl.getStatus()).connected
134
+ };
135
+ } catch (err) {
136
+ this.ctx.logger.warn("reconcile: getStatus RPC failed — leaving membership as-is", { meta: {
137
+ addonId,
138
+ error: err instanceof Error ? err.message : String(err)
139
+ } });
140
+ return {
141
+ addonId,
142
+ ok: false
143
+ };
144
+ }
145
+ }));
146
+ const result = reconcileEnabledProviders(this.config.enabledProviders, probes);
147
+ if (!result.changed) return;
148
+ this.ctx.logger.info("reconcile: corrected enabledProviders from RPC-pulled state", { meta: {
149
+ added: result.added,
150
+ removed: result.removed
151
+ } });
152
+ await this.updateGlobalSettings({ enabledProviders: result.nextEnabled });
153
+ }
154
+ async autoStartEnabledProviders() {
155
+ await this.reconcileAndPersist();
156
+ const ids = this.config.enabledProviders;
157
+ if (ids.length === 0) return;
158
+ this.ctx.logger.info("Auto-starting enabled remote-access providers", { meta: { addonIds: [...ids] } });
159
+ for (const addonId of ids) try {
160
+ const impl = this.resolveImpl(addonId);
161
+ if (!impl?.start) {
162
+ this.ctx.logger.warn("autostart: provider not ready or unsupported", { meta: {
163
+ addonId,
164
+ hasImpl: !!impl,
165
+ hasStart: !!impl?.start
166
+ } });
167
+ continue;
168
+ }
169
+ if (impl.getStatus) {
170
+ const status = await impl.getStatus().catch(() => null);
171
+ if (status?.connected) {
172
+ this.ctx.logger.info("autostart: provider already connected — skipping", { meta: {
173
+ addonId,
174
+ url: status.endpoint?.url
175
+ } });
176
+ continue;
177
+ }
178
+ }
179
+ const endpoint = await impl.start();
180
+ this.ctx.logger.info("autostart: provider started", { meta: {
181
+ addonId,
182
+ url: endpoint.url
183
+ } });
184
+ } catch (err) {
185
+ this.ctx.logger.error("autostart: provider start failed", { meta: {
186
+ addonId,
187
+ error: err instanceof Error ? err.message : String(err)
188
+ } });
189
+ }
190
+ }
191
+ async markEnabled(addonId, enabled) {
192
+ const current = new Set(this.config.enabledProviders);
193
+ const wasEnabled = current.has(addonId);
194
+ if (enabled) current.add(addonId);
195
+ else current.delete(addonId);
196
+ if (wasEnabled === enabled) return;
197
+ this.ctx.logger.info("remote-access intent updated", { meta: {
198
+ addonId,
199
+ enabled
200
+ } });
201
+ await this.updateGlobalSettings({ enabledProviders: [...current] });
202
+ }
203
+ resolveImpl(addonId) {
204
+ return (this.capabilities?.getCollectionEntries("network-access") ?? []).find(([id]) => id === addonId)?.[1] ?? null;
205
+ }
206
+ };
207
+ //#endregion
208
+ export { RemoteAccessOrchestratorAddon, RemoteAccessOrchestratorAddon as default };