@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,20 @@
1
+ require("./chunk-Cek0wNdY.js");
2
+ //#region src/builtins/platform-probe/intel-accelerators.ts
3
+ var INTEL_VENDOR = "0x8086";
4
+ function classifyIntelAccelerators(fsx) {
5
+ let gpu = null;
6
+ for (const node of fsx.listRenderNodes()) if (fsx.readVendor(node).trim() === INTEL_VENDOR) {
7
+ gpu = {
8
+ type: "intel",
9
+ name: `Intel iGPU (${node.split("/").pop()})`
10
+ };
11
+ break;
12
+ }
13
+ const npu = fsx.exists("/dev/accel/accel0") ? { type: "intel-npu" } : null;
14
+ return {
15
+ gpu,
16
+ npu
17
+ };
18
+ }
19
+ //#endregion
20
+ exports.classifyIntelAccelerators = classifyIntelAccelerators;
@@ -0,0 +1,19 @@
1
+ //#region src/builtins/platform-probe/intel-accelerators.ts
2
+ var INTEL_VENDOR = "0x8086";
3
+ function classifyIntelAccelerators(fsx) {
4
+ let gpu = null;
5
+ for (const node of fsx.listRenderNodes()) if (fsx.readVendor(node).trim() === INTEL_VENDOR) {
6
+ gpu = {
7
+ type: "intel",
8
+ name: `Intel iGPU (${node.split("/").pop()})`
9
+ };
10
+ break;
11
+ }
12
+ const npu = fsx.exists("/dev/accel/accel0") ? { type: "intel-npu" } : null;
13
+ return {
14
+ gpu,
15
+ npu
16
+ };
17
+ }
18
+ //#endregion
19
+ export { classifyIntelAccelerators };
@@ -0,0 +1,4 @@
1
+ import { ICamstackAddon } from '@camstack/types';
2
+ type AddonConstructor = new () => ICamstackAddon;
3
+ export declare function resolveAddonClass(mod: Record<string, unknown>): AddonConstructor | undefined;
4
+ export {};
@@ -0,0 +1,22 @@
1
+ import { ICamstackAddon, AddonContext, IEngineManager, IEngineInstance } from '@camstack/types';
2
+ import { AddonLoader } from './addon-loader.js';
3
+ export declare class AddonEngineManager implements IEngineManager {
4
+ private readonly loader;
5
+ private readonly baseContext;
6
+ private engines;
7
+ constructor(loader: AddonLoader, baseContext: Partial<Omit<AddonContext, 'addonConfig'>>);
8
+ /**
9
+ * Get or create an addon engine for the given effective config.
10
+ * Cameras with the same addonId + effective config share the same engine.
11
+ */
12
+ getOrCreateEngine(addonId: string, globalConfig: Record<string, unknown>, cameraOverride?: Record<string, unknown>): Promise<IEngineInstance>;
13
+ /** Get all active engines */
14
+ getActiveEngines(): Map<string, ICamstackAddon>;
15
+ /** Shutdown a specific engine by its config key */
16
+ shutdownEngine(configKey: string): Promise<void>;
17
+ /** Shutdown all engines */
18
+ shutdownAll(): Promise<void>;
19
+ /** Compute a deterministic config key (visible for tests) */
20
+ computeConfigKey(addonId: string, effectiveConfig: Record<string, unknown>): string;
21
+ private hashConfig;
22
+ }
@@ -0,0 +1,154 @@
1
+ import { IEventBus, IScopedLogger } from '@camstack/types';
2
+ /**
3
+ * Kernel-level addon health monitor.
4
+ *
5
+ * Tracks load + initialize + crash failures across the addon population
6
+ * and drives an aggressive auto-retry loop independent of any single
7
+ * addon's logic. Mirrors the spec the operator approved:
8
+ *
9
+ * - Boot grace: 5 minutes from `start()`. Failures during this window
10
+ * are silently retried (slow-starting addons must have a chance to
11
+ * come up before alarming).
12
+ * - Retry cadence: 60s after first failure, 120s after second, then
13
+ * 300s for every subsequent attempt — never gives up.
14
+ * - Tick interval: 30s. Faster than the shortest retry interval (60s)
15
+ * so a scheduled retry never waits more than ~30s past its target.
16
+ * - Post-grace alerting: emits `AddonLoadFailed` exactly once per
17
+ * failure-streak; AlertCenter consumes the event to create a
18
+ * persistent operator-visible alert. Recovery emits
19
+ * `AddonLoadRecovered` so the alert can dismiss itself.
20
+ * - In-memory state only. Server restart resets the grace window
21
+ * (operator's call — they want a clean slate after a manual restart).
22
+ *
23
+ * The monitor never restarts addons itself: it knows nothing about
24
+ * tarball install / dist paths / dependency injection. It calls a
25
+ * caller-injected `retryFn(packageName)` which is the AddonRegistry's
26
+ * existing reload path — the monitor is just the scheduler + alert
27
+ * gate. This keeps the kernel package addon-agnostic.
28
+ *
29
+ * Group-runner / fork crashes: `process-service.ts` already respawns
30
+ * crashed children with exponential backoff. The monitor doesn't
31
+ * duplicate that loop — it only marks the addon `failed` when the
32
+ * crash supervisor reports it (via `recordFailure`) and clears it on
33
+ * `READY:<nodeId>` recovery (via `recordSuccess`). The kernel's
34
+ * spawn handler wires both edges.
35
+ */
36
+ export declare const HEALTH_MONITOR_TICK_MS = 30000;
37
+ export declare const HEALTH_MONITOR_GRACE_PERIOD_MS: number;
38
+ /** Retry intervals after each failure (capped — never stops). */
39
+ export declare const HEALTH_MONITOR_RETRY_INTERVALS_MS: readonly number[];
40
+ export type AddonHealthPhase = 'pending' | 'healthy' | 'failed';
41
+ export interface AddonHealthState {
42
+ readonly packageName: string;
43
+ readonly addonId?: string;
44
+ phase: AddonHealthPhase;
45
+ retryCount: number;
46
+ firstFailureAt: number | null;
47
+ lastAttemptAt: number | null;
48
+ lastError: {
49
+ readonly message: string;
50
+ readonly stack?: string;
51
+ } | null;
52
+ nextRetryAt: number | null;
53
+ /** True once `AddonLoadFailed` has been emitted for the current streak. */
54
+ alertEmitted: boolean;
55
+ /** True if a retry attempt is currently in flight. */
56
+ retrying: boolean;
57
+ }
58
+ export interface AddonHealthSnapshot {
59
+ readonly packageName: string;
60
+ readonly addonId?: string;
61
+ readonly phase: AddonHealthPhase;
62
+ readonly retryCount: number;
63
+ readonly firstFailureAt: number | null;
64
+ readonly lastAttemptAt: number | null;
65
+ readonly lastError: {
66
+ readonly message: string;
67
+ readonly stack?: string;
68
+ } | null;
69
+ readonly nextRetryAt: number | null;
70
+ readonly alertEmitted: boolean;
71
+ readonly retrying: boolean;
72
+ /** Whether the boot grace window is still open (suppresses alerts). */
73
+ readonly inGracePeriod: boolean;
74
+ }
75
+ export interface AddonHealthMonitorOptions {
76
+ readonly eventBus: IEventBus;
77
+ readonly logger: IScopedLogger;
78
+ /**
79
+ * Called by the monitor's tick loop when a failed package is due
80
+ * for a retry attempt. Should perform the actual reload (tarball
81
+ * extract + addon-loader re-import + initialize). Returns true on
82
+ * success; throws on failure (the monitor records the new error).
83
+ */
84
+ readonly retryFn: (packageName: string) => Promise<void>;
85
+ /** Override for tests. Defaults to `HEALTH_MONITOR_TICK_MS`. */
86
+ readonly tickIntervalMs?: number;
87
+ /** Override for tests. Defaults to `HEALTH_MONITOR_GRACE_PERIOD_MS`. */
88
+ readonly gracePeriodMs?: number;
89
+ /** Override for tests. Defaults to `HEALTH_MONITOR_RETRY_INTERVALS_MS`. */
90
+ readonly retryIntervalsMs?: readonly number[];
91
+ /** Override clock for deterministic tests. */
92
+ readonly now?: () => number;
93
+ }
94
+ export declare class AddonHealthMonitor {
95
+ private readonly state;
96
+ private readonly bootAt;
97
+ private readonly tickIntervalMs;
98
+ private readonly gracePeriodMs;
99
+ private readonly retryIntervalsMs;
100
+ private readonly eventBus;
101
+ private readonly logger;
102
+ private readonly retryFn;
103
+ private readonly now;
104
+ private timer;
105
+ private graceEmittedFor;
106
+ constructor(opts: AddonHealthMonitorOptions);
107
+ /** True while we're still inside the post-boot grace window. */
108
+ inGracePeriod(): boolean;
109
+ /**
110
+ * Record a successful load/init/recovery for a package. Clears any
111
+ * existing failure state and emits `AddonLoadRecovered` if the
112
+ * package was previously in `failed` state with an alert emitted.
113
+ */
114
+ recordSuccess(packageName: string, addonId?: string): void;
115
+ /**
116
+ * Record a load/init/crash failure. Schedules the next retry per
117
+ * `retryIntervalsMs` and (post-grace) emits `AddonLoadFailed` if
118
+ * this is the first alert for the current streak.
119
+ */
120
+ recordFailure(packageName: string, err: unknown, addonId?: string): void;
121
+ /**
122
+ * Force an immediate retry attempt for a package, resetting the
123
+ * counter back to 0 (next failure goes to the 60s interval again).
124
+ * Used by the user-facing `addons.retryLoad` tRPC procedure and by
125
+ * the explicit reinstall path.
126
+ */
127
+ retryNow(packageName: string): Promise<void>;
128
+ /** Snapshot of all tracked packages (read-only, for tRPC list / UI). */
129
+ getHealthSnapshot(): readonly AddonHealthSnapshot[];
130
+ /** Get health for a single package (or null if unknown). */
131
+ getHealth(packageName: string): AddonHealthSnapshot | null;
132
+ /**
133
+ * Drop tracking for a package (used on uninstall — we don't want
134
+ * the monitor to keep retrying a package the user explicitly removed).
135
+ */
136
+ forget(packageName: string): void;
137
+ /** Begin the retry tick loop. Idempotent. */
138
+ start(): void;
139
+ /** Stop the retry loop (cleanup on shutdown). */
140
+ stop(): void;
141
+ /**
142
+ * Public for tests. Production callers go through `start()`.
143
+ *
144
+ * Each tick:
145
+ * 1. If grace JUST ended on this tick, emit `AddonLoadFailed` for
146
+ * every package still in `failed` state that hasn't alerted yet.
147
+ * 2. For every `failed` package whose `nextRetryAt` <= now, run
148
+ * `retryFn`. On success, recordSuccess; on failure, recordFailure
149
+ * (which recomputes the next interval).
150
+ */
151
+ tick(): Promise<void>;
152
+ private attemptRetry;
153
+ private emit;
154
+ }
@@ -0,0 +1,208 @@
1
+ import { InstalledPackage, IScopedLogger } from '@camstack/types';
2
+ import { AddonManifest } from './addon-manifest.js';
3
+ /**
4
+ * Addon install source mode:
5
+ * - 'npm' — download from npm registry (production + dev default).
6
+ * - 'local' — copy dist/ from local workspace `packages/` (used by
7
+ * `installFromWorkspace` + the Electron-packaged bundled
8
+ * addons path).
9
+ * - 'symlink' — point `data/addons/<pkg>` directly at the workspace
10
+ * source dir. Dev-only: workspace edits → next addon
11
+ * load picks them up after a `npm run build` of the
12
+ * package, without re-copying. Costs ~80ms per addon at
13
+ * cold boot instead of the ~200ms-per-package copy.
14
+ * Windows fallback: drops back to `'local'` if symlink
15
+ * creation fails (needs admin / developer-mode on Win10).
16
+ *
17
+ * The previous symlink mode (auto-on when workspace was detected) was
18
+ * removed in `eb96df3c` once addons moved to self-contained bundles —
19
+ * the legacy `symlinkAddonsToNodeModules` / `symlinkPeerDepsIntoAddonsDir`
20
+ * helpers it relied on are GONE. This is the narrower successor: no
21
+ * symlinks into the hub's `node_modules`, no peer-dep planting — just
22
+ * `addonsDir/<pkg>` → `packages/<pkg>`.
23
+ */
24
+ export type InstallSource = 'npm' | 'local' | 'symlink';
25
+ export interface AddonInstallerConfig {
26
+ /** Directory where addons are stored (e.g., {dataDir}/addons) */
27
+ readonly addonsDir: string;
28
+ /** npm registry URL */
29
+ readonly registry?: string;
30
+ /** Workspace packages directory (e.g., /path/to/camstack-server/packages) */
31
+ readonly workspacePackagesDir?: string;
32
+ /** Install source mode. Default: auto-detect */
33
+ readonly installSource?: InstallSource;
34
+ }
35
+ export type { InstalledPackage };
36
+ export declare class AddonInstaller {
37
+ readonly addonsDir: string;
38
+ private readonly registry;
39
+ readonly workspaceDir: string | undefined;
40
+ readonly installSource: InstallSource;
41
+ private readonly logger;
42
+ /**
43
+ * Central manifest of installed addons. Tracks version + source +
44
+ * timestamps + last-backup pointer per package, written atomically
45
+ * after every install/uninstall. Replaces the legacy per-addon
46
+ * `.install-source` markers (which we still write for backward
47
+ * compatibility with code that reads them directly — see fs-utils
48
+ * `getAddonInstallSource`).
49
+ */
50
+ readonly manifest: AddonManifest;
51
+ constructor(config: AddonInstallerConfig, logger?: IScopedLogger);
52
+ /**
53
+ * Derive the bootstrap addon list from a meta-package's runtime dependencies.
54
+ * Single source of truth: the meta-package's `package.json` declares which
55
+ * `@camstack/addon-*` packages the deployment needs. Replaces previously
56
+ * hardcoded lists — see design spec
57
+ * docs/superpowers/specs/2026-05-20-docker-install-from-npm-design.md.
58
+ */
59
+ private static deriveBootstrapList;
60
+ /**
61
+ * Bootstrap packages installed on first boot — derived from the
62
+ * `@camstack/server` meta-package's runtime dependencies. Adding a
63
+ * bootstrap addon = adding it to `server/backend/package.json`.
64
+ * See design spec
65
+ * docs/superpowers/specs/2026-05-20-docker-install-from-npm-design.md.
66
+ *
67
+ * Camera provider drivers are NOT preinstalled with the hub — users
68
+ * pick providers from the admin UI ("Install addon"). Saves ~80MB per
69
+ * hub install and avoids shipping driver code unused on most hubs.
70
+ */
71
+ static readonly REQUIRED_PACKAGES: readonly string[];
72
+ /**
73
+ * Agent-only bootstrap packages — derived from the `@camstack/agent`
74
+ * meta-package's runtime dependencies. Adding an agent bootstrap addon
75
+ * = adding it to `packages/agent/package.json`.
76
+ */
77
+ static readonly AGENT_PACKAGES: readonly string[];
78
+ /**
79
+ * Ensure all required packages are installed in the addons directory.
80
+ *
81
+ * Bootstrap-only — prefers the workspace/bundle copy when available
82
+ * (offline-first, faster, container-self-contained). On-demand
83
+ * installs from the admin UI go through `install()` instead, which
84
+ * defaults to npm in production.
85
+ *
86
+ * @param packages — optional custom package list (default: REQUIRED_PACKAGES)
87
+ */
88
+ ensureRequiredPackages(packages?: readonly string[]): Promise<void>;
89
+ /**
90
+ * Install a single addon — on-demand installer used by AddonPackageService
91
+ * (admin UI "Install addon" / "Reinstall" buttons).
92
+ *
93
+ * Always npm. The legacy "auto-use workspace symlink in dev" branch
94
+ * was removed; local development pushes via `camstack deploy` (CLI
95
+ * tarball upload). Operators wanting to install from workspace use
96
+ * `installFromWorkspace` (explicit `'local'` codepath) instead.
97
+ */
98
+ install(packageName: string, version?: string): Promise<{
99
+ name: string;
100
+ version: string;
101
+ }>;
102
+ /**
103
+ * Install addon from a local workspace package. Two strategies
104
+ * depending on `installSource`:
105
+ * - `'symlink'` (dev): create a directory symlink
106
+ * `addonsDir/<pkg>` → `<workspace>/packages/<pkg>`. Edits to
107
+ * the workspace are visible at the next addon load after a
108
+ * `npm run build` of that package — no copy step. Falls back
109
+ * to `'local'` if symlink creation fails (Windows w/o
110
+ * developer-mode).
111
+ * - `'local'` (default): copy `package.json` (stripped) + `dist/`
112
+ * into `addonsDir/<pkg>/`. The Electron bundled-addons path
113
+ * uses this so the runtime owns its on-disk copy.
114
+ */
115
+ private installLocal;
116
+ /**
117
+ * Symlink `addonsDir/<pkg>` at the workspace source dir. Dev-only.
118
+ * After this, the AddonLoader resolves `<addonsDir>/<pkg>/dist/...`
119
+ * through the symlink straight to `packages/<pkg>/dist/...` — a fresh
120
+ * `npm run build` of the package is immediately picked up by the
121
+ * next addon load.
122
+ *
123
+ * Auto-runs `ensureBuilt` so a workspace freshly cloned (with no
124
+ * dist/ yet) still boots — same auto-build hook installCopy uses.
125
+ *
126
+ * Does NOT plant peer-dep symlinks into `<targetDir>/node_modules/`
127
+ * the way the pre-`eb96df3c` symlink mode did. Self-contained
128
+ * addons bundle their own copy of types/zod/sdk — no shared
129
+ * workspace symlinks needed.
130
+ */
131
+ private installSymlink;
132
+ private installCopy;
133
+ /**
134
+ * Install addon from npm (download tgz, then extract). Tries the
135
+ * registry HTTPS API first (works inside packaged Electron — no need
136
+ * for `npm` on PATH); falls back to `npm pack` for parity with the
137
+ * legacy path when the registry call fails (private registries with
138
+ * unusual auth, offline mode, etc).
139
+ */
140
+ installFromNpm(packageName: string, version?: string): Promise<{
141
+ name: string;
142
+ version: string;
143
+ }>;
144
+ /**
145
+ * Resolve `{packageName, version?}` against the configured registry
146
+ * over HTTPS and download the tarball into `tmpDir`. Returns the path
147
+ * to the downloaded `.tgz`.
148
+ *
149
+ * Versioning rules (mirrors `npm pack` semantics):
150
+ * - `version === undefined` → uses `dist-tags.latest`
151
+ * - exact semver string → looked up in `versions[version]`
152
+ * - dist-tag name (e.g. `next`, `beta`) → resolved via `dist-tags`
153
+ *
154
+ * Range specs (`^1.0.0`, `~1.2`, `>=2`) are NOT supported here — the
155
+ * caller should resolve those upstream. `npm pack` handles them, so
156
+ * the legacy fallback path remains the right answer for those.
157
+ */
158
+ private downloadNpmTarball;
159
+ /** Install addon from a tgz file (uploaded or downloaded) */
160
+ installFromTgz(tgzPath: string): Promise<{
161
+ name: string;
162
+ version: string;
163
+ }>;
164
+ /**
165
+ * Apply an update to an installed addon, backing up the current
166
+ * version first so the caller can roll back atomically on failure.
167
+ *
168
+ * Steps:
169
+ * 1. Rename current install dir → {addonsDir}/.backups/{name}/{ts}/
170
+ * 2. Run a fresh install (npm or local depending on installSource)
171
+ * 3. Record `lastBackupDir` in the manifest entry
172
+ *
173
+ * The post-install caller (kernel.restartAddon + health-check) is
174
+ * responsible for verifying the new version actually works and for
175
+ * triggering `rollbackAddon()` if the health check fails.
176
+ *
177
+ * Throws if there is no installed version to update — caller should
178
+ * prefer plain `install()` for first-time installs.
179
+ */
180
+ applyUpdate(packageName: string, version?: string): Promise<{
181
+ name: string;
182
+ version: string;
183
+ backupDir: string;
184
+ }>;
185
+ /**
186
+ * Roll back an addon to its most recent backup. Used after an update
187
+ * passes installation but fails its post-restart health check.
188
+ *
189
+ * Returns the version that was restored, or `null` if there was no
190
+ * backup to roll back to.
191
+ */
192
+ rollbackAddon(packageName: string): Promise<string | null>;
193
+ /**
194
+ * Drop the recorded backup for an addon (e.g. after a successful
195
+ * post-update health check confirms the new version is healthy).
196
+ * Frees disk space without affecting the running install.
197
+ */
198
+ clearBackup(packageName: string): void;
199
+ uninstall(packageName: string): Promise<void>;
200
+ listInstalled(): InstalledPackage[];
201
+ isInstalled(packageName: string): boolean;
202
+ getInstalledPackage(packageName: string): InstalledPackage | null;
203
+ private findLocalPackage;
204
+ /** Ensure a package is built (dist/ exists and page bundles present) */
205
+ private ensureBuilt;
206
+ /** Check if page bundles declared in package.json are missing from dist/ */
207
+ private isDistIncomplete;
208
+ }
@@ -0,0 +1,106 @@
1
+ import { AddonDeclaration, ICamstackAddon, IScopedLogger, StorageLocationDeclaration } from '@camstack/types';
2
+ export interface RegisteredAddon {
3
+ readonly declaration: AddonDeclaration;
4
+ readonly packageName: string;
5
+ readonly packageVersion: string;
6
+ /** Human-readable package name from camstack.displayName in package.json */
7
+ readonly packageDisplayName?: string;
8
+ /**
9
+ * Optional bundle metadata when the npm package ships multiple addon
10
+ * entries. Mirrors `AddonPackageManifest.bundle`. Drives the
11
+ * collapsible bundle card in the Addons admin UI.
12
+ */
13
+ readonly bundle?: {
14
+ displayName: string;
15
+ description?: string;
16
+ icon?: string;
17
+ };
18
+ readonly addonClass: new () => ICamstackAddon;
19
+ /**
20
+ * Full raw module namespace. Consumers can read additional named exports
21
+ * (e.g. `customActions`) without instantiating the addon — lets the hub
22
+ * register a forkable addon's custom-action catalog with real zod
23
+ * schemas before the child process is up.
24
+ */
25
+ readonly module: Readonly<Record<string, unknown>>;
26
+ }
27
+ /**
28
+ * Per-package failure record. Surfaced via `listLoadFailures()` so the
29
+ * AddonRegistry can hand the failures to the kernel's
30
+ * `AddonHealthMonitor` after `loadFromDirectory()` completes — the
31
+ * health monitor then schedules the retry loop and emits operator-
32
+ * visible alerts post-grace.
33
+ *
34
+ * Two failure shapes are tracked:
35
+ * - **package-level**: package.json couldn't be read/parsed, or the
36
+ * manifest was malformed. `addonId` undefined.
37
+ * - **declaration-level**: per-addon load failure inside
38
+ * `loadDeclaration` (entry import threw, addon class resolution
39
+ * failed, etc). `addonId` set to `declaration.id`.
40
+ */
41
+ export interface AddonLoadFailure {
42
+ readonly packageName: string;
43
+ readonly addonDir: string;
44
+ readonly addonId?: string;
45
+ readonly error: Error;
46
+ readonly timestamp: number;
47
+ }
48
+ /**
49
+ * Pure extraction of per-addon storage-location declarations from a set of
50
+ * registered addons. Each registered addon carries its manifest declaration
51
+ * (`RegisteredAddon.declaration`), whose optional `storageLocations` array is
52
+ * the `camstack.addons[].storageLocations` entry authored in package.json.
53
+ *
54
+ * Returns ONE inner array per addon that declared at least one location;
55
+ * addons declaring nothing are omitted entirely (no empty arrays). The result
56
+ * is the `perAddon` input shape consumed by
57
+ * {@link buildStorageLocationRegistry}.
58
+ */
59
+ export declare function extractStorageLocationDeclarations(addons: Iterable<RegisteredAddon>): StorageLocationDeclaration[][];
60
+ export declare class AddonLoader {
61
+ private addons;
62
+ private readonly loadFailures;
63
+ private readonly logger;
64
+ constructor(logger?: IScopedLogger);
65
+ /**
66
+ * Failures encountered during the most recent `loadFromDirectory` /
67
+ * `loadFromAddonDir` pass. Cleared (per-package) on a successful
68
+ * subsequent reload so retries don't see stale entries. Cumulative
69
+ * across multiple loads otherwise.
70
+ */
71
+ listLoadFailures(): readonly AddonLoadFailure[];
72
+ /** Forget any tracked failures for a given package — uninstall path. */
73
+ clearLoadFailures(packageName: string): void;
74
+ /** Scan addons directory and load all addon packages.
75
+ * Supports scoped layout: addons/@scope/package-name/ */
76
+ loadFromDirectory(addonsDir: string): Promise<void>;
77
+ private tryLoadAddon;
78
+ /** Load addon from a specific directory (package.json + dist/) */
79
+ loadFromAddonDir(addonDir: string): Promise<void>;
80
+ private loadDeclaration;
81
+ /** Load addon from a direct path (for development/testing) */
82
+ loadFromPath(addonId: string, modulePath: string, packageName: string, declaration?: Partial<AddonDeclaration>, packageVersion?: string): Promise<void>;
83
+ /** Get a registered addon by ID */
84
+ getAddon(addonId: string): RegisteredAddon | undefined;
85
+ /** List all registered addons */
86
+ listAddons(): RegisteredAddon[];
87
+ /**
88
+ * Per-addon storage-location declarations across every registered addon.
89
+ *
90
+ * Each registered addon's `declaration.storageLocations` (the
91
+ * `camstack.addons[].storageLocations` array from package.json) is surfaced
92
+ * as one inner array; addons declaring nothing are omitted. The result is
93
+ * fed directly to `buildStorageLocationRegistry(perAddon)` so the
94
+ * storage-orchestrator can aggregate declarations and seed `<id>:default`
95
+ * instances.
96
+ */
97
+ listStorageLocationDeclarations(): StorageLocationDeclaration[][];
98
+ /** Check if an addon is registered */
99
+ hasAddon(addonId: string): boolean;
100
+ /**
101
+ * Create a new instance of an addon (not yet initialized).
102
+ * Injects the manifest from package.json (AddonDeclaration) so the
103
+ * addon class doesn't need to declare it.
104
+ */
105
+ createInstance(addonId: string): ICamstackAddon;
106
+ }
@@ -0,0 +1,77 @@
1
+ export type AddonInstallSource = 'npm' | 'local' | 'upload' | 'bundled' | 'seed';
2
+ export interface AddonManifestEntry {
3
+ /** Full pkg name, e.g. `@camstack/addon-pipeline`. */
4
+ name: string;
5
+ /** Semver currently installed. */
6
+ version: string;
7
+ /** Where this version came from. */
8
+ source: AddonInstallSource;
9
+ /** ISO 8601 of first install. */
10
+ installedAt: string;
11
+ /** ISO 8601 of last update (== installedAt for first install). */
12
+ updatedAt: string;
13
+ /**
14
+ * Path (absolute) of the most recent pre-update backup, if any.
15
+ * Used by `applyUpdate` rollback when an upgrade fails its post-restart
16
+ * health check. Cleared once the new version is confirmed healthy.
17
+ */
18
+ lastBackupDir?: string;
19
+ /**
20
+ * Free-form, addon-specific metadata. Currently unused but reserved so
21
+ * future fields (e.g. integrity hash, peer-dep checks) don't require a
22
+ * manifest schema bump.
23
+ */
24
+ meta?: Record<string, unknown>;
25
+ }
26
+ export interface AddonManifestFile {
27
+ /**
28
+ * Schema version. Increment whenever the on-disk shape changes
29
+ * incompatibly so older readers can refuse to load.
30
+ */
31
+ version: 1;
32
+ /** Per-package state, keyed by full pkg name. */
33
+ addons: Record<string, AddonManifestEntry>;
34
+ /** ISO 8601 of last manifest write. */
35
+ updatedAt: string;
36
+ }
37
+ export declare class AddonManifest {
38
+ private readonly manifestPath;
39
+ private cache;
40
+ constructor(addonsDir: string);
41
+ /**
42
+ * Read the manifest from disk. Returns an empty manifest if the file is
43
+ * missing or corrupted (logs a warning to stderr in the corrupted case).
44
+ * Cached per instance — call `invalidate()` to force a re-read.
45
+ */
46
+ read(): AddonManifestFile;
47
+ /**
48
+ * Atomic write — writes to a tmpfile in the same directory, then renames.
49
+ * Rename is atomic on the same filesystem, so readers can never observe
50
+ * a half-written file.
51
+ */
52
+ write(manifest: AddonManifestFile): void;
53
+ /** Lookup a single addon's manifest entry, or `null` if not tracked. */
54
+ get(name: string): AddonManifestEntry | null;
55
+ /** List every tracked entry. */
56
+ list(): AddonManifestEntry[];
57
+ /**
58
+ * Insert or replace an addon entry. `installedAt` is preserved if the
59
+ * entry already exists; only `updatedAt` advances on subsequent writes.
60
+ */
61
+ upsert(name: string, fields: Omit<AddonManifestEntry, 'name' | 'installedAt' | 'updatedAt'>): void;
62
+ /** Remove an addon from tracking (e.g. uninstall). */
63
+ remove(name: string): void;
64
+ /**
65
+ * Drop the in-memory cache so the next `read()` re-loads from disk.
66
+ * Useful when an external process may have written the manifest.
67
+ */
68
+ invalidate(): void;
69
+ /**
70
+ * Migration helper: if the manifest is empty but the addons directory
71
+ * has packages with `.install-source` markers (the legacy per-addon
72
+ * tracking), seed the manifest from those markers. Runs once at boot.
73
+ * Returns the number of entries migrated.
74
+ */
75
+ migrateFromInstallSourceMarkers(addonsDir: string): number;
76
+ private empty;
77
+ }
@@ -0,0 +1,46 @@
1
+ import { ReadinessRegistry, ReadinessScope, ICapabilityHandle } from '@camstack/types';
2
+ export declare class CapabilityUnavailableError extends Error {
3
+ readonly capName: string;
4
+ readonly scope: ReadinessScope;
5
+ readonly timeoutMs: number;
6
+ constructor(capName: string, scope: ReadinessScope, timeoutMs: number);
7
+ }
8
+ /**
9
+ * A stable reference to a capability that tracks its readiness state and
10
+ * gates calls on that state.
11
+ *
12
+ * Obtained via `ctx.useCapability()` (non-blocking) or `ctx.acquireCapability()`
13
+ * (blocks until the cap is ready). The handle is cached per `(capName, scope)` in
14
+ * AddonContextImpl so repeated calls return the same instance.
15
+ *
16
+ * The generic `T` is a phantom type documenting the expected provider interface;
17
+ * the handle itself does not expose a typed proxy surface in v1.
18
+ */
19
+ export declare class CapabilityHandle<T = unknown> implements ICapabilityHandle<T> {
20
+ readonly capName: string;
21
+ readonly scope: ReadinessScope;
22
+ private readonly registry;
23
+ readonly defaultTimeoutMs: number;
24
+ private state;
25
+ private readonly unsubscribeReadiness;
26
+ constructor(capName: string, scope: ReadinessScope, registry: ReadinessRegistry, defaultTimeoutMs: number);
27
+ get isReady(): boolean;
28
+ /**
29
+ * Block until the capability is ready, or throw `CapabilityUnavailableError`
30
+ * if it does not become ready within `timeoutMs`.
31
+ */
32
+ awaitReady(timeoutMs?: number): Promise<void>;
33
+ /**
34
+ * Execute `fn` with readiness gating: if the cap is not ready, blocks
35
+ * until it becomes ready (or throws CapabilityUnavailableError on timeout),
36
+ * then calls `fn`.
37
+ *
38
+ * Preferred over calling awaitReady() + fn() separately because it
39
+ * re-gates after a down→ready transition that happens between the
40
+ * await and the call.
41
+ */
42
+ call<R>(fn: () => Promise<R>, timeoutMs?: number): Promise<R>;
43
+ /** Unsubscribe from ReadinessRegistry. Called by AddonContextImpl on shutdown. */
44
+ dispose(): void;
45
+ readonly _provider: T;
46
+ }