@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.
- package/dist/addon/addon-api-factory.d.ts +35 -0
- package/dist/addon-routes/addon-route-registry.d.ts +37 -0
- package/dist/addon-runner.js +599 -0
- package/dist/addon-runner.mjs +597 -0
- package/dist/auth/api-key-manager.d.ts +26 -0
- package/dist/auth/auth-manager.d.ts +109 -0
- package/dist/auth/parse-record.d.ts +18 -0
- package/dist/auth/scope-matcher.d.ts +7 -0
- package/dist/auth/scoped-token-manager.d.ts +40 -0
- package/dist/auth/totp-manager.d.ts +51 -0
- package/dist/auth/user-manager.d.ts +34 -0
- package/dist/builtins/addon-pages-aggregator/addon-pages-aggregator.addon.d.ts +53 -0
- package/dist/builtins/addon-pages-aggregator/addon-pages-aggregator.addon.js +259 -0
- package/dist/builtins/addon-pages-aggregator/addon-pages-aggregator.addon.mjs +251 -0
- package/dist/builtins/addon-pages-aggregator/dedupe-pages.d.ts +6 -0
- package/dist/builtins/addon-pages-aggregator/index.d.ts +1 -0
- package/dist/builtins/addon-pages-aggregator/index.js +8 -0
- package/dist/builtins/addon-pages-aggregator/index.mjs +2 -0
- package/dist/builtins/addon-widgets-aggregator/addon-widgets-aggregator.addon.d.ts +47 -0
- package/dist/builtins/addon-widgets-aggregator/addon-widgets-aggregator.addon.js +228 -0
- package/dist/builtins/addon-widgets-aggregator/addon-widgets-aggregator.addon.mjs +220 -0
- package/dist/builtins/addon-widgets-aggregator/index.d.ts +1 -0
- package/dist/builtins/addon-widgets-aggregator/index.js +8 -0
- package/dist/builtins/addon-widgets-aggregator/index.mjs +2 -0
- package/dist/builtins/alerts/alerts.addon.d.ts +81 -0
- package/dist/builtins/alerts/alerts.addon.js +601 -0
- package/dist/builtins/alerts/alerts.addon.mjs +595 -0
- package/dist/builtins/alerts/index.d.ts +1 -0
- package/dist/builtins/alerts/index.js +4 -0
- package/dist/builtins/alerts/index.mjs +2 -0
- package/dist/builtins/backup-orchestrator/backup-orchestrator.addon.d.ts +147 -0
- package/dist/builtins/backup-orchestrator/backup-orchestrator.addon.js +2229 -0
- package/dist/builtins/backup-orchestrator/backup-orchestrator.addon.mjs +2220 -0
- package/dist/builtins/backup-orchestrator/cron-helpers.d.ts +23 -0
- package/dist/builtins/backup-orchestrator/destination-policy.d.ts +72 -0
- package/dist/builtins/backup-orchestrator/download-helpers.d.ts +12 -0
- package/dist/builtins/backup-orchestrator/index.d.ts +2 -0
- package/dist/builtins/backup-orchestrator/index.js +8 -0
- package/dist/builtins/backup-orchestrator/index.mjs +2 -0
- package/dist/builtins/backup-orchestrator/manifest-store.d.ts +77 -0
- package/dist/builtins/console-logging/console-destination.d.ts +13 -0
- package/dist/builtins/console-logging/console-logging.addon.d.ts +25 -0
- package/dist/builtins/console-logging/index.d.ts +3 -0
- package/dist/builtins/console-logging/index.js +104 -0
- package/dist/builtins/console-logging/index.mjs +95 -0
- package/dist/builtins/device-manager/device-config-contribution.d.ts +32 -0
- package/dist/builtins/device-manager/device-event-propagator.d.ts +26 -0
- package/dist/builtins/device-manager/device-link-overlay.d.ts +23 -0
- package/dist/builtins/device-manager/device-link-resolver.d.ts +15 -0
- package/dist/builtins/device-manager/device-manager.addon.d.ts +452 -0
- package/dist/builtins/device-manager/device-manager.addon.js +3299 -0
- package/dist/builtins/device-manager/device-manager.addon.mjs +3292 -0
- package/dist/builtins/device-manager/index.d.ts +2 -0
- package/dist/builtins/device-manager/index.js +8 -0
- package/dist/builtins/device-manager/index.mjs +2 -0
- package/dist/builtins/hub-forwarder/hub-forwarder-destination.d.ts +44 -0
- package/dist/builtins/hub-forwarder/hub-forwarder.addon.d.ts +15 -0
- package/dist/builtins/hub-forwarder/index.d.ts +3 -0
- package/dist/builtins/hub-forwarder/index.js +154 -0
- package/dist/builtins/hub-forwarder/index.mjs +145 -0
- package/dist/builtins/local-auth/auth-schema.d.ts +26 -0
- package/dist/builtins/local-auth/index.d.ts +1 -0
- package/dist/builtins/local-auth/index.js +4 -0
- package/dist/builtins/local-auth/index.mjs +2 -0
- package/dist/builtins/local-auth/local-auth.addon.d.ts +18 -0
- package/dist/builtins/local-auth/local-auth.addon.js +8094 -0
- package/dist/builtins/local-auth/local-auth.addon.mjs +8063 -0
- package/dist/builtins/local-auth/oauth-grants.d.ts +45 -0
- package/dist/builtins/local-auth/oauth-session-manager.d.ts +50 -0
- package/dist/builtins/local-network/index.d.ts +2 -0
- package/dist/builtins/local-network/index.js +10 -0
- package/dist/builtins/local-network/index.mjs +2 -0
- package/dist/builtins/local-network/local-network.addon.d.ts +150 -0
- package/dist/builtins/local-network/local-network.addon.js +489 -0
- package/dist/builtins/local-network/local-network.addon.mjs +477 -0
- package/dist/builtins/native-metrics/index.d.ts +2 -0
- package/dist/builtins/native-metrics/native-metrics-provider.d.ts +48 -0
- package/dist/builtins/native-metrics/native-metrics.addon.d.ts +73 -0
- package/dist/builtins/native-metrics/native-metrics.addon.js +922 -0
- package/dist/builtins/native-metrics/native-metrics.addon.mjs +914 -0
- package/dist/builtins/platform-probe/hardware-decode-accel-probe.d.ts +37 -0
- package/dist/builtins/platform-probe/hardware-encoder-probe.d.ts +13 -0
- package/dist/builtins/platform-probe/index.d.ts +22 -0
- package/dist/builtins/platform-probe/index.js +834 -0
- package/dist/builtins/platform-probe/index.mjs +822 -0
- package/dist/builtins/platform-probe/inference-config-resolver.d.ts +29 -0
- package/dist/builtins/platform-probe/intel-accelerators.d.ts +11 -0
- package/dist/builtins/platform-probe/platform-scorer.d.ts +30 -0
- package/dist/builtins/platform-probe/runtime-packages.d.ts +6 -0
- package/dist/builtins/remote-access-orchestrator/enabled-providers-reconcile.d.ts +96 -0
- package/dist/builtins/remote-access-orchestrator/index.d.ts +1 -0
- package/dist/builtins/remote-access-orchestrator/index.js +8 -0
- package/dist/builtins/remote-access-orchestrator/index.mjs +2 -0
- package/dist/builtins/remote-access-orchestrator/remote-access-orchestrator.addon.d.ts +40 -0
- package/dist/builtins/remote-access-orchestrator/remote-access-orchestrator.addon.js +214 -0
- package/dist/builtins/remote-access-orchestrator/remote-access-orchestrator.addon.mjs +208 -0
- package/dist/builtins/shared/settle-sources.d.ts +22 -0
- package/dist/builtins/snapshot/index.d.ts +2 -0
- package/dist/builtins/snapshot/index.js +494 -0
- package/dist/builtins/snapshot/index.mjs +488 -0
- package/dist/builtins/snapshot/snapshot.addon.d.ts +120 -0
- package/dist/builtins/sqlite-storage/config-store.d.ts +8 -0
- package/dist/builtins/sqlite-storage/device-store.d.ts +23 -0
- package/dist/builtins/sqlite-storage/filesystem-browse-provider.d.ts +25 -0
- package/dist/builtins/sqlite-storage/filesystem-storage-provider.d.ts +83 -0
- package/dist/builtins/sqlite-storage/filesystem-storage.addon.d.ts +32 -0
- package/dist/builtins/sqlite-storage/filesystem-storage.addon.js +396 -0
- package/dist/builtins/sqlite-storage/filesystem-storage.addon.mjs +388 -0
- package/dist/builtins/sqlite-storage/index.d.ts +8 -0
- package/dist/builtins/sqlite-storage/index.js +62 -0
- package/dist/builtins/sqlite-storage/index.mjs +49 -0
- package/dist/builtins/sqlite-storage/integration-registry.d.ts +27 -0
- package/dist/builtins/sqlite-storage/path-guard.d.ts +4 -0
- package/dist/builtins/sqlite-storage/sqlite-settings-backend.d.ts +102 -0
- package/dist/builtins/sqlite-storage/sqlite-settings.addon.d.ts +14 -0
- package/dist/builtins/sqlite-storage/sqlite-settings.addon.js +644 -0
- package/dist/builtins/sqlite-storage/sqlite-settings.addon.mjs +636 -0
- package/dist/builtins/storage-orchestrator/index.d.ts +6 -0
- package/dist/builtins/storage-orchestrator/index.js +10 -0
- package/dist/builtins/storage-orchestrator/index.mjs +2 -0
- package/dist/builtins/storage-orchestrator/location-store.d.ts +49 -0
- package/dist/builtins/storage-orchestrator/provider-discovery.d.ts +10 -0
- package/dist/builtins/storage-orchestrator/storage-orchestrator.addon.d.ts +103 -0
- package/dist/builtins/storage-orchestrator/storage-orchestrator.addon.js +1138 -0
- package/dist/builtins/storage-orchestrator/storage-orchestrator.addon.mjs +1128 -0
- package/dist/builtins/storage-orchestrator/storage-orchestrator.service.d.ts +236 -0
- package/dist/builtins/storage-orchestrator/storage-pressure-manager.d.ts +38 -0
- package/dist/builtins/system-backup/system-backup.service.d.ts +137 -0
- package/dist/builtins/system-config/index.d.ts +1 -0
- package/dist/builtins/system-config/index.js +8 -0
- package/dist/builtins/system-config/index.mjs +2 -0
- package/dist/builtins/system-config/system-config.addon.d.ts +10 -0
- package/dist/builtins/system-config/system-config.addon.js +232 -0
- package/dist/builtins/system-config/system-config.addon.mjs +226 -0
- package/dist/builtins/winston-logging/index.d.ts +3 -0
- package/dist/builtins/winston-logging/index.js +156 -0
- package/dist/builtins/winston-logging/index.mjs +144 -0
- package/dist/builtins/winston-logging/winston-destination.d.ts +21 -0
- package/dist/builtins/winston-logging/winston-logging.addon.d.ts +19 -0
- package/dist/chunk-CNf5ZN-e.mjs +37 -0
- package/dist/chunk-Cek0wNdY.js +64 -0
- package/dist/download/model-download-service.d.ts +41 -0
- package/dist/download/model-downloader.d.ts +31 -0
- package/dist/events/event-bus.d.ts +10 -0
- package/dist/events/system-event-bus.d.ts +14 -0
- package/dist/feature/feature-manager.d.ts +11 -0
- package/dist/formatter-B7qW8bPJ.mjs +162 -0
- package/dist/formatter-DqAKDlvN.js +167 -0
- package/dist/http/authenticated-file-server.d.ts +53 -0
- package/dist/http/data-plane-registry.d.ts +23 -0
- package/dist/http/file-data-plane.d.ts +10 -0
- package/dist/http/reverse-proxy.d.ts +15 -0
- package/dist/index.d.ts +82 -0
- package/dist/index.js +93485 -0
- package/dist/index.mjs +93179 -0
- package/dist/intel-accelerators-Gg0P5mnl.js +20 -0
- package/dist/intel-accelerators-hGgpZ0pX.mjs +19 -0
- package/dist/kernel/addon-class-resolver.d.ts +4 -0
- package/dist/kernel/addon-engine-manager.d.ts +22 -0
- package/dist/kernel/addon-health-monitor.d.ts +154 -0
- package/dist/kernel/addon-installer.d.ts +208 -0
- package/dist/kernel/addon-loader.d.ts +106 -0
- package/dist/kernel/addon-manifest.d.ts +77 -0
- package/dist/kernel/capability-handle.d.ts +46 -0
- package/dist/kernel/capability-registry.d.ts +412 -0
- package/dist/kernel/config-manager.d.ts +212 -0
- package/dist/kernel/config-schema.d.ts +93 -0
- package/dist/kernel/custom-action-registry.d.ts +23 -0
- package/dist/kernel/deps/addon-deps-manager.d.ts +19 -0
- package/dist/kernel/deps/manifest-native-deps.d.ts +25 -0
- package/dist/kernel/deps/manifest-python-deps.d.ts +20 -0
- package/dist/kernel/device-registry.d.ts +29 -0
- package/dist/kernel/fs-utils.d.ts +41 -0
- package/dist/kernel/hwaccel/hwaccel-resolver.d.ts +19 -0
- package/dist/kernel/hwaccel/hwaccel-service.d.ts +4 -0
- package/dist/kernel/index.d.ts +74 -0
- package/dist/kernel/infra-capabilities.d.ts +13 -0
- package/dist/kernel/moleculer/addon-context-factory.d.ts +91 -0
- package/dist/kernel/moleculer/addon-data-plane-facility.d.ts +19 -0
- package/dist/kernel/moleculer/addon-runner.d.ts +1 -0
- package/dist/kernel/moleculer/addon-service-factory.d.ts +50 -0
- package/dist/kernel/moleculer/broker-factory.d.ts +50 -0
- package/dist/kernel/moleculer/cap-usage-registry.d.ts +46 -0
- package/dist/kernel/moleculer/capabilities-access.d.ts +21 -0
- package/dist/kernel/moleculer/child-addon-call-dispatch.d.ts +46 -0
- package/dist/kernel/moleculer/child-cap-dispatch.d.ts +20 -0
- package/dist/kernel/moleculer/cluster-secret.d.ts +15 -0
- package/dist/kernel/moleculer/core-cap-service.d.ts +50 -0
- package/dist/kernel/moleculer/crash-supervisor.d.ts +50 -0
- package/dist/kernel/moleculer/device-cap-proxy.d.ts +79 -0
- package/dist/kernel/moleculer/event-bus-core.d.ts +53 -0
- package/dist/kernel/moleculer/event-bus.d.ts +53 -0
- package/dist/kernel/moleculer/hub-log-forwarder.d.ts +36 -0
- package/dist/kernel/moleculer/hub-service.d.ts +35 -0
- package/dist/kernel/moleculer/node-registry.d.ts +126 -0
- package/dist/kernel/moleculer/process-context.d.ts +4 -0
- package/dist/kernel/moleculer/process-service.d.ts +72 -0
- package/dist/kernel/moleculer/provider-registry.d.ts +28 -0
- package/dist/kernel/moleculer/readiness-context.d.ts +62 -0
- package/dist/kernel/moleculer/readiness-service.d.ts +7 -0
- package/dist/kernel/moleculer/register-node-client.d.ts +35 -0
- package/dist/kernel/moleculer/remote-logger.d.ts +43 -0
- package/dist/kernel/moleculer/resilient-cap-call.d.ts +28 -0
- package/dist/kernel/moleculer/stream-probe-service.d.ts +9 -0
- package/dist/kernel/moleculer/trpc-links.d.ts +189 -0
- package/dist/kernel/moleculer/typed-array-serde.d.ts +25 -0
- package/dist/kernel/moleculer/worker-device-restore.d.ts +10 -0
- package/dist/kernel/provider-kind-drift.d.ts +12 -0
- package/dist/kernel/restart-coordinator.d.ts +90 -0
- package/dist/kernel/storage-location-registry.d.ts +40 -0
- package/dist/kernel/transport/cap-action-name.d.ts +100 -0
- package/dist/kernel/transport/cap-route-resolver.d.ts +148 -0
- package/dist/kernel/transport/cap-route.d.ts +148 -0
- package/dist/kernel/transport/child-cap-protocol.d.ts +136 -0
- package/dist/kernel/transport/create-local-transport.d.ts +7 -0
- package/dist/kernel/transport/frame-codec.d.ts +7 -0
- package/dist/kernel/transport/index.d.ts +27 -0
- package/dist/kernel/transport/local-child-client.d.ts +136 -0
- package/dist/kernel/transport/local-child-registry.d.ts +179 -0
- package/dist/kernel/transport/local-endpoint-path.d.ts +6 -0
- package/dist/kernel/transport/local-transport.d.ts +46 -0
- package/dist/kernel/transport/parent-unowned-call.d.ts +75 -0
- package/dist/kernel/transport/socket-channel.d.ts +27 -0
- package/dist/kernel/transport/uds-event-bridge.d.ts +36 -0
- package/dist/kernel/transport/uds-event-bus.d.ts +22 -0
- package/dist/kernel/transport/uds-local-transport.d.ts +18 -0
- package/dist/kernel/transport/uds-log-ingest.d.ts +28 -0
- package/dist/kernel/transport/uds-logger.d.ts +44 -0
- package/dist/kernel/utils/ring-buffer.d.ts +15 -0
- package/dist/kernel/workspace-detect.d.ts +9 -0
- package/dist/lifecycle/lifecycle-state-machine.d.ts +28 -0
- package/dist/logging/formatter.d.ts +30 -0
- package/dist/logging/log-manager.d.ts +54 -0
- package/dist/logging/log-ring-buffer.d.ts +47 -0
- package/dist/logging/partitioned-log-buffer.d.ts +35 -0
- package/dist/logging/scoped-logger.d.ts +17 -0
- package/dist/main-DNnMW7Z2.js +9983 -0
- package/dist/main-rtjOwPBR.mjs +9976 -0
- package/dist/manifest-python-deps-D1DbAQEv.js +6724 -0
- package/dist/manifest-python-deps-DZsKTbs1.mjs +6315 -0
- package/dist/network/network-quality.d.ts +11 -0
- package/dist/notification/notification-service.d.ts +37 -0
- package/dist/notification/toast-service.d.ts +22 -0
- package/dist/pipeline/engine-manager-resolver.d.ts +15 -0
- package/dist/pipeline/pipeline-runner.d.ts +8 -0
- package/dist/pipeline/pipeline-validator.d.ts +13 -0
- package/dist/process/resource-monitor.d.ts +11 -0
- package/dist/python/python-env-manager.d.ts +12 -0
- package/dist/repl/interfaces.d.ts +31 -0
- package/dist/repl/repl-engine.d.ts +8 -0
- package/dist/resource-monitor-ClDGFyf6.mjs +57 -0
- package/dist/resource-monitor-IIEanuJt.js +74 -0
- package/dist/settle-sources-Bhsy57y-.js +38 -0
- package/dist/settle-sources-CDtNC8ub.mjs +33 -0
- package/dist/storage/fs-storage-backend.d.ts +40 -0
- package/dist/storage/storage-location-manager.d.ts +23 -0
- package/dist/storage/storage-manager.d.ts +83 -0
- package/dist/tar-BgAEMRBR.js +5434 -0
- package/dist/tar-ByMOPNM0.mjs +5429 -0
- package/dist/tls/cert-manager.d.ts +26 -0
- package/dist/tls/index.d.ts +1 -0
- package/package.json +343 -0
|
@@ -0,0 +1,412 @@
|
|
|
1
|
+
import { CapabilityDefinition, CapabilityDeclaration, CapabilityMode, CapabilityInfo, CapabilityProviderMap, SingletonCapabilityMap, CollectionCapabilityMap, IScopedLogger, IEventBus } from '@camstack/types';
|
|
2
|
+
import { ConfigManager } from './config-manager.js';
|
|
3
|
+
/** Result of creating a capability router (opaque to the kernel). */
|
|
4
|
+
export type CapabilityRouter = unknown;
|
|
5
|
+
/** Factory that creates a tRPC router from a capability definition + provider getter. */
|
|
6
|
+
export type CapabilityRouterFactory = (definition: CapabilityDefinition, getProvider: () => unknown | null) => CapabilityRouter;
|
|
7
|
+
/** Reader function that resolves user's singleton preference for a capability. */
|
|
8
|
+
export type ConfigReader = (capability: string) => string | undefined;
|
|
9
|
+
/**
|
|
10
|
+
* Reader function that resolves the persisted set of disabled addonIds for a
|
|
11
|
+
* collection capability. Parallel to {@link ConfigReader} but for the
|
|
12
|
+
* collection mode — returns the addonIds an operator has disabled so the
|
|
13
|
+
* registry can restore them as disabled on a fresh boot. An empty array (or
|
|
14
|
+
* `undefined`) means "nothing persisted, all providers enabled".
|
|
15
|
+
*
|
|
16
|
+
* Wired by the server layer in `addon-registry.service.ts` to read the same
|
|
17
|
+
* `capabilities.collection.<cap>` ConfigService key the `capabilities` router
|
|
18
|
+
* writes. Keeps the registry decoupled from `ConfigService` — exactly like
|
|
19
|
+
* {@link ConfigReader} does for singletons.
|
|
20
|
+
*/
|
|
21
|
+
export type CollectionConfigReader = (capability: string) => readonly string[] | undefined;
|
|
22
|
+
export declare class CapabilityRegistry {
|
|
23
|
+
private readonly capabilities;
|
|
24
|
+
private readonly logger;
|
|
25
|
+
private readonly eventBus;
|
|
26
|
+
private routerFactory;
|
|
27
|
+
private configReader;
|
|
28
|
+
private collectionConfigReader;
|
|
29
|
+
private configManager;
|
|
30
|
+
private _ready;
|
|
31
|
+
/** Boot-time dependency graph: capability → dependsOn names (from CapabilityDeclaration) */
|
|
32
|
+
private readonly capabilityDeps;
|
|
33
|
+
/** Per-device singleton overrides: deviceId → (capability → addonId) */
|
|
34
|
+
private readonly deviceOverrides;
|
|
35
|
+
/** capName → (nodeId → bare addonId) per-node singleton overrides. */
|
|
36
|
+
private readonly singletonNodeOverrides;
|
|
37
|
+
/** Optional reader for persisted per-node overrides: (cap, nodeId) → addonId. */
|
|
38
|
+
private nodeConfigReader;
|
|
39
|
+
/** Per-device collection filters: deviceId → (capability → addonIds[]) */
|
|
40
|
+
private readonly deviceCollectionFilters;
|
|
41
|
+
/** autoActivate flags per (capability, addonId) — from addon manifests */
|
|
42
|
+
private readonly autoActivateFlags;
|
|
43
|
+
/**
|
|
44
|
+
* Per-device native providers: capName → deviceId (numeric) → { addonId, provider }.
|
|
45
|
+
*
|
|
46
|
+
* Backs `DeviceContext.registerNativeCap`. Lets device-driver addons
|
|
47
|
+
* (OnvifCamera, RtspCamera, etc.) publish capability implementations
|
|
48
|
+
* scoped to a single device; the device-proxy router resolves these by
|
|
49
|
+
* `(capName, deviceId)` to dispatch incoming calls.
|
|
50
|
+
*
|
|
51
|
+
* Distinct from the `capabilities[].providers` map (system-wide providers
|
|
52
|
+
* keyed by addonId) — native providers are device-instance-scoped and
|
|
53
|
+
* never participate in singleton/collection resolution.
|
|
54
|
+
*/
|
|
55
|
+
private readonly nativeProviders;
|
|
56
|
+
/**
|
|
57
|
+
* Wrapper provider registrations: capName → Set<addonId>. Tracked separately
|
|
58
|
+
* from `capabilities[].providers` because wrappers aren't system-wide
|
|
59
|
+
* providers — they're user-toggleable decorators addons declare via
|
|
60
|
+
* `ProviderRegistration.kind === 'wrapper'`. Consumers query this map (via
|
|
61
|
+
* `getWrappersForCap`) to render the "pick a wrapper for this device"
|
|
62
|
+
* dropdown in the device-bindings UI.
|
|
63
|
+
*/
|
|
64
|
+
private readonly wrapperProviders;
|
|
65
|
+
/**
|
|
66
|
+
* Wrapper registrations that declared `ProviderRegistration.defaultActive:
|
|
67
|
+
* true`. Keyed by `capName` and valued by `addonId` — the first wrapper
|
|
68
|
+
* flagged default-active wins per cap. Consumed by `device-manager.getBindings`
|
|
69
|
+
* to synthesise a wrapper binding when no explicit activation has been
|
|
70
|
+
* persisted for a (device, cap) pair and no native provider exists either —
|
|
71
|
+
* otherwise the default wrapper would sit dormant waiting for a manual
|
|
72
|
+
* `setWrapperActive({active: true})` that never comes.
|
|
73
|
+
*/
|
|
74
|
+
private readonly wrapperDefaults;
|
|
75
|
+
/**
|
|
76
|
+
* Pending {@link waitForProvider} waiters, keyed by
|
|
77
|
+
* `"${capabilityName}::${addonId}"`. Resolved by {@link registerProvider}
|
|
78
|
+
* as soon as the matching pair is registered — the mechanism that replaces
|
|
79
|
+
* the 100ms polling loop the device-management router used to run while
|
|
80
|
+
* waiting for forked providers to finish announcing their Moleculer service.
|
|
81
|
+
*/
|
|
82
|
+
private readonly pendingWaiters;
|
|
83
|
+
/** Period for the "still waiting" log emitted by `waitForProvider`. */
|
|
84
|
+
private static readonly WAIT_HEARTBEAT_INTERVAL_MS;
|
|
85
|
+
constructor(logger: IScopedLogger, eventBus?: IEventBus);
|
|
86
|
+
/** Set the config reader for singleton preference resolution. */
|
|
87
|
+
setConfigReader(reader: ConfigReader): void;
|
|
88
|
+
/**
|
|
89
|
+
* Set the config reader for collection-provider enable/disable persistence.
|
|
90
|
+
* Consulted by {@link registerProvider} so a provider an operator disabled
|
|
91
|
+
* in a previous session comes back disabled after a hub reboot.
|
|
92
|
+
*/
|
|
93
|
+
setCollectionConfigReader(reader: CollectionConfigReader): void;
|
|
94
|
+
/** Set the config manager for persisted device activation state. */
|
|
95
|
+
setConfigManager(manager: ConfigManager): void;
|
|
96
|
+
/** Register boot-time dependency edges (from CapabilityDeclaration.dependsOn). */
|
|
97
|
+
setDependencies(capabilityName: string, dependsOn: readonly string[]): void;
|
|
98
|
+
/** Set the router factory — called by the server layer once at boot. */
|
|
99
|
+
setRouterFactory(factory: CapabilityRouterFactory): void;
|
|
100
|
+
/** Mark boot complete. Before this, getProvider() returns null. */
|
|
101
|
+
ready(): void;
|
|
102
|
+
isReady(): boolean;
|
|
103
|
+
/**
|
|
104
|
+
* Declare a capability from its definition.
|
|
105
|
+
* Creates the auto-mounted router (if factory is set).
|
|
106
|
+
* Called during addon manifest loading, before providers are registered.
|
|
107
|
+
*/
|
|
108
|
+
declareCapability(definition: CapabilityDefinition): void;
|
|
109
|
+
/**
|
|
110
|
+
* Register manifest metadata (dependsOn + autoActivate) for a capability,
|
|
111
|
+
* and — when the capability's definition declares `kind: 'wrapper'` —
|
|
112
|
+
* register the addon as a wrapper provider.
|
|
113
|
+
*
|
|
114
|
+
* The capability MUST already be declared via `declareCapability` from
|
|
115
|
+
* its full `CapabilityDefinition`. Behavioural metadata (`mode`, `kind`,
|
|
116
|
+
* `defaultActive`) is owned exclusively by the cap definition — never
|
|
117
|
+
* the manifest (D4, base-layer rework; mirrors the Session 5 A5 `mode`
|
|
118
|
+
* consolidation). The manifest declaration carries only the cap name,
|
|
119
|
+
* `dependsOn`, `autoActivate`, and `optional`.
|
|
120
|
+
*/
|
|
121
|
+
declareFromManifest(declaration: CapabilityDeclaration, addonId?: string): void;
|
|
122
|
+
/**
|
|
123
|
+
* Register a provider for a capability.
|
|
124
|
+
* For singleton: auto-activates if user-preferred or first registered.
|
|
125
|
+
* For collection: adds to the collection.
|
|
126
|
+
*
|
|
127
|
+
* Phase 12 (settings redesign follow-up): throws if the same
|
|
128
|
+
* `(capabilityName, addonId)` pair is registered more than once.
|
|
129
|
+
* Previously the second call would silently replace the first via
|
|
130
|
+
* `state.providers.set(addonId, provider)` — that was the root cause
|
|
131
|
+
* of the "analysis-pipeline registered three times" bug observed in
|
|
132
|
+
* the kernel cleanup log (`analytics` addon called `registerProvider`
|
|
133
|
+
* twice plus the `analysis-pipeline` addon called it a third time).
|
|
134
|
+
*
|
|
135
|
+
* Double-register of the same pair is always a programmer error —
|
|
136
|
+
* two legitimately different addons implementing the same cap keep
|
|
137
|
+
* using different `addonId`s and the user picks one via `configReader`.
|
|
138
|
+
*/
|
|
139
|
+
registerProvider(capabilityName: string, addonId: string, provider: unknown): void;
|
|
140
|
+
/** Unregister a provider. For singleton: clears active. For collection: removes from list. */
|
|
141
|
+
unregisterProvider(capabilityName: string, addonId: string): void;
|
|
142
|
+
/** Enable a previously disabled collection provider. */
|
|
143
|
+
enableCollectionProvider(capability: string, addonId: string): void;
|
|
144
|
+
/** Disable a collection provider (keeps it registered but excluded from active list). */
|
|
145
|
+
disableCollectionProvider(capability: string, addonId: string): void;
|
|
146
|
+
/**
|
|
147
|
+
* Register a native capability provider scoped to a single device.
|
|
148
|
+
* Throws if the same `(capName, deviceId)` is registered twice — that is
|
|
149
|
+
* always a programmer error: device-driver addons must call
|
|
150
|
+
* `DeviceContext.registerNativeCap` exactly once per cap per device.
|
|
151
|
+
*/
|
|
152
|
+
registerNativeProvider(capName: string, deviceId: number, addonId: string, provider: unknown): void;
|
|
153
|
+
/** Remove a single native provider entry. No-op if absent. */
|
|
154
|
+
unregisterNativeProvider(capName: string, deviceId: number): void;
|
|
155
|
+
/** Remove every native provider entry for a device — called on device removal. */
|
|
156
|
+
unregisterAllNativeForDevice(deviceId: number): void;
|
|
157
|
+
/** Fallback resolver for native providers that aren't registered in-process. */
|
|
158
|
+
private nativeFallback;
|
|
159
|
+
/**
|
|
160
|
+
* Install a fallback resolver for cross-process native caps. When a device's
|
|
161
|
+
* live `IDevice` lives in a forked worker (e.g. `provider-rtsp`), the native
|
|
162
|
+
* cap it published via `DeviceContext.registerNativeCap` is reachable over
|
|
163
|
+
* the broker — but the hub's `nativeProviders` map never saw it. The fallback
|
|
164
|
+
* is called by {@link getNativeProvider} on local-miss and is expected to
|
|
165
|
+
* return a proxy object whose methods issue `broker.call` into the owning
|
|
166
|
+
* worker. Set once at hub boot time.
|
|
167
|
+
*/
|
|
168
|
+
setNativeFallback(resolver: (capName: string, deviceId: number) => unknown | null): void;
|
|
169
|
+
/** Resolve the native provider for `(capName, deviceId)` or null. */
|
|
170
|
+
getNativeProvider<T = unknown>(capName: string, deviceId: number): T | null;
|
|
171
|
+
/** Resolve the addonId that registered the native provider for `(capName, deviceId)`. */
|
|
172
|
+
getNativeAddonId(capName: string, deviceId: number): string | null;
|
|
173
|
+
/** List the capability names for which this device has a native provider registered. */
|
|
174
|
+
getNativeCapsForDevice(deviceId: number): readonly string[];
|
|
175
|
+
/**
|
|
176
|
+
* Mark `addonId` as providing a wrapper implementation for `capName`. Called
|
|
177
|
+
* by `declareFromManifest` when the capability's `CapabilityDefinition` declares
|
|
178
|
+
* `kind: 'wrapper'` (D4 — the cap definition is the single source of truth for wrapper behaviour).
|
|
179
|
+
* Idempotent — re-registration keeps a single entry.
|
|
180
|
+
*/
|
|
181
|
+
registerWrapper(capName: string, addonId: string, opts?: {
|
|
182
|
+
defaultActive?: boolean;
|
|
183
|
+
}): void;
|
|
184
|
+
/** Remove a wrapper registration. No-op if absent. */
|
|
185
|
+
unregisterWrapper(capName: string, addonId: string): void;
|
|
186
|
+
/** Remove every wrapper registration owned by `addonId`. Called on addon stop. */
|
|
187
|
+
unregisterAllWrappersForAddon(addonId: string): void;
|
|
188
|
+
/** Return the addon ids that declared a wrapper for `capName`. */
|
|
189
|
+
getWrappersForCap(capName: string): readonly string[];
|
|
190
|
+
/**
|
|
191
|
+
* Return the wrapper addon flagged `defaultActive: true` for `capName`, or
|
|
192
|
+
* null when no wrapper declared itself the default. Used by
|
|
193
|
+
* `device-manager.getBindings` to auto-bind default wrappers on devices
|
|
194
|
+
* without an explicit user activation.
|
|
195
|
+
*/
|
|
196
|
+
getDefaultWrapperForCap(capName: string): string | null;
|
|
197
|
+
/** List capability names that have at least one wrapper flagged `defaultActive: true`. */
|
|
198
|
+
getCapsWithDefaultWrapper(): readonly string[];
|
|
199
|
+
/**
|
|
200
|
+
* Get the active provider for a singleton capability.
|
|
201
|
+
*
|
|
202
|
+
* When called with a declared capability name (a key of
|
|
203
|
+
* `CapabilityProviderMap`), the return type is inferred automatically —
|
|
204
|
+
* no caller-side casts needed. Arbitrary string names fall back to
|
|
205
|
+
* `unknown`.
|
|
206
|
+
*/
|
|
207
|
+
getProvider<K extends keyof CapabilityProviderMap>(capabilityName: K): CapabilityProviderMap[K] | null;
|
|
208
|
+
getProvider(capabilityName: string): unknown | null;
|
|
209
|
+
/**
|
|
210
|
+
* Unified per-device resolver (D13). Resolves a `(cap, device)` pair to
|
|
211
|
+
* its provider transparently — native (per-device) first, then a
|
|
212
|
+
* device-bound system provider. Callers no longer branch on
|
|
213
|
+
* `kind: 'native' | 'wrapped'`; `kind` is metadata on the binding only.
|
|
214
|
+
*
|
|
215
|
+
* Resolution order:
|
|
216
|
+
* 1. Native provider registered for the exact `(capName, deviceId)` pair.
|
|
217
|
+
* 2. System provider: for singleton caps, honours per-device overrides and
|
|
218
|
+
* activation via `resolveForDevice`; for collection caps, returns the
|
|
219
|
+
* first registered provider.
|
|
220
|
+
* 3. `null` when neither exists.
|
|
221
|
+
*/
|
|
222
|
+
getProviderForDevice<T = unknown>(capName: string, deviceId: number): T | null;
|
|
223
|
+
/** Get all providers for a collection capability. */
|
|
224
|
+
getAllProviders<K extends keyof CapabilityProviderMap>(capabilityName: K): readonly CapabilityProviderMap[K][];
|
|
225
|
+
getAllProviders(capabilityName: string): readonly unknown[];
|
|
226
|
+
/** Get provider by addon ID (for per-device resolution). */
|
|
227
|
+
getProviderByAddon<K extends keyof CapabilityProviderMap>(capabilityName: K, addonId: string): CapabilityProviderMap[K] | null;
|
|
228
|
+
getProviderByAddon<T = unknown>(capabilityName: string, addonId: string): T | null;
|
|
229
|
+
/**
|
|
230
|
+
* Wait for a specific `(capabilityName, addonId)` provider to become
|
|
231
|
+
* available, up to `timeoutMs`. Resolves synchronously with the live
|
|
232
|
+
* provider if it is already registered; otherwise queues a waiter that
|
|
233
|
+
* {@link registerProvider} fulfils as soon as the matching pair shows up.
|
|
234
|
+
* Resolves to `null` on timeout instead of rejecting — the caller
|
|
235
|
+
* ({@link device-management.router}) already branches on `null` to return
|
|
236
|
+
* a user-facing "provider not available" error.
|
|
237
|
+
*
|
|
238
|
+
* Replaces the 100ms polling loop from the post-settings-redesign
|
|
239
|
+
* `waitForDeviceProvider` helper. On the happy path there is zero
|
|
240
|
+
* overhead and zero behavioural change; on the race path the wait
|
|
241
|
+
* unblocks on the next `registerProvider` call without any intermediate
|
|
242
|
+
* sleeps. See `[WAIT-EVENT]` in the 2026-04-12 handover.
|
|
243
|
+
*/
|
|
244
|
+
waitForProvider<K extends keyof CapabilityProviderMap>(capabilityName: K, addonId: string, timeoutMs: number): Promise<CapabilityProviderMap[K] | null>;
|
|
245
|
+
waitForProvider(capabilityName: string, addonId: string, timeoutMs: number): Promise<unknown | null>;
|
|
246
|
+
/**
|
|
247
|
+
* Get the active singleton provider for a capability.
|
|
248
|
+
*
|
|
249
|
+
* Declared capability names resolve to their typed provider via
|
|
250
|
+
* `SingletonCapabilityMap` — a cap declared as `collection` in its
|
|
251
|
+
* `.cap.ts` definition is rejected at the type level. Arbitrary strings
|
|
252
|
+
* (non-declared capabilities) fall back to the caller-provided `T`
|
|
253
|
+
* (default `unknown`) through the second overload for compatibility
|
|
254
|
+
* with downstream packages that extend `CapabilityProviderMap` via
|
|
255
|
+
* declaration merging.
|
|
256
|
+
*
|
|
257
|
+
* Hard-typed narrowing via `SingletonCapabilityMap` was introduced in
|
|
258
|
+
* session 5 Sprint A5 — see audit addendum finding R6.
|
|
259
|
+
*/
|
|
260
|
+
getSingleton<K extends keyof SingletonCapabilityMap>(capability: K): SingletonCapabilityMap[K] | null;
|
|
261
|
+
getSingleton<T = unknown>(capability: string): T | null;
|
|
262
|
+
/** Get the addon ID of the active singleton provider. */
|
|
263
|
+
getSingletonAddonId(capability: string): string | null;
|
|
264
|
+
/**
|
|
265
|
+
* Override the active addon for a singleton capability. Called by the
|
|
266
|
+
* pipeline-orchestrator binding system so future `getSingleton(cap)`
|
|
267
|
+
* lookups return the addon the operator explicitly selected. If
|
|
268
|
+
* `addonId` is `null` or no provider is registered under that id,
|
|
269
|
+
* falls back to the cap-declared `preferredProvider` (when registered),
|
|
270
|
+
* otherwise the first-registered provider (legacy behaviour).
|
|
271
|
+
*
|
|
272
|
+
* This helper is an internal hook for the UDS-preference race (it does
|
|
273
|
+
* NOT read `configReader` — the operator's persisted choice is applied
|
|
274
|
+
* by `registerProvider`/`unregisterProvider`). For consistency with those
|
|
275
|
+
* paths the fallback still honours `preferredProvider` ahead of
|
|
276
|
+
* insertion-order first-remaining.
|
|
277
|
+
*
|
|
278
|
+
* No-op when the capability isn't declared, isn't a singleton, or the
|
|
279
|
+
* requested addon hasn't registered a provider for it yet.
|
|
280
|
+
*/
|
|
281
|
+
setSingletonActiveAddon(capability: string, addonId: string | null): void;
|
|
282
|
+
/**
|
|
283
|
+
* Get all active collection providers for a capability.
|
|
284
|
+
*
|
|
285
|
+
* Declared capability names resolve to their typed provider via
|
|
286
|
+
* `CollectionCapabilityMap` — a cap declared as `singleton` in its
|
|
287
|
+
* `.cap.ts` definition is rejected at the type level. Arbitrary strings
|
|
288
|
+
* fall back to the caller-provided `T` (default `unknown`) for
|
|
289
|
+
* compatibility with declaration-merged extensions.
|
|
290
|
+
*/
|
|
291
|
+
getCollection<K extends keyof CollectionCapabilityMap>(capability: K): readonly CollectionCapabilityMap[K][];
|
|
292
|
+
getCollection<T = unknown>(capability: string): readonly T[];
|
|
293
|
+
/**
|
|
294
|
+
* Like {@link getCollection} but returns `[addonId, provider]` tuples so
|
|
295
|
+
* callers can attribute work back to the contributing addon.
|
|
296
|
+
*
|
|
297
|
+
* Needed by the device-settings aggregator (`device-manager.addon.ts`) —
|
|
298
|
+
* each contributed field must carry the writer's `addonId` so the
|
|
299
|
+
* `deviceManager.updateDeviceField` mutation can route the write to the
|
|
300
|
+
* correct addon-settings store without hardcoding any addon identity.
|
|
301
|
+
*/
|
|
302
|
+
getCollectionEntries<K extends keyof CollectionCapabilityMap>(capability: K): readonly (readonly [string, CollectionCapabilityMap[K]])[];
|
|
303
|
+
getCollectionEntries<T = unknown>(capability: string): readonly (readonly [string, T])[];
|
|
304
|
+
/** Get the full CapabilityDefinition for a declared capability. */
|
|
305
|
+
getDefinition(capability: string): CapabilityDefinition | undefined;
|
|
306
|
+
/** Get the mode declared for a capability. */
|
|
307
|
+
getMode(capability: string): CapabilityMode | undefined;
|
|
308
|
+
/** Get a specific addon's provider by addon ID. */
|
|
309
|
+
getProviderByAddonId<K extends keyof CapabilityProviderMap>(capability: K, addonId: string): CapabilityProviderMap[K] | null;
|
|
310
|
+
getProviderByAddonId<T = unknown>(capability: string, addonId: string): T | null;
|
|
311
|
+
/** Bare addonId from a registry key (`webrtc-native@dev-agent-0` → `webrtc-native`). */
|
|
312
|
+
private bareAddonId;
|
|
313
|
+
/** nodeId a provider key belongs to (bare → 'hub', `@node` → node). */
|
|
314
|
+
private nodeOfKey;
|
|
315
|
+
/** capName → (nodeId → bare addonId[]) availability derived from provider keys. */
|
|
316
|
+
getProvidersByNode(capability: string): Map<string, string[]>;
|
|
317
|
+
/**
|
|
318
|
+
* Resolve the BARE addon id a node should use for a singleton cap.
|
|
319
|
+
* Chain: per-node override → cluster-global default → first available.
|
|
320
|
+
* Returns null when the node hosts no provider for the cap.
|
|
321
|
+
*/
|
|
322
|
+
resolveSingletonAddonIdForNode(capability: string, nodeId: string): string | null;
|
|
323
|
+
/** Resolve the in-process provider object for a node (hub-local only). */
|
|
324
|
+
getSingletonForNode<T = unknown>(capability: string, nodeId: string): T | null;
|
|
325
|
+
/** Per-node override accessor (for listCapabilities + tests). */
|
|
326
|
+
getSingletonNodeOverrides(capability: string): Map<string, string>;
|
|
327
|
+
/** Set the reader for persisted per-node overrides (boot restore). */
|
|
328
|
+
setNodeConfigReader(reader: (capability: string, nodeId: string) => string | undefined): void;
|
|
329
|
+
/** Clear a per-node override (UI "inherit global"). */
|
|
330
|
+
clearSingletonNodeOverride(capability: string, nodeId: string): void;
|
|
331
|
+
/**
|
|
332
|
+
* Set which addon should be the active singleton for a capability.
|
|
333
|
+
* Pass an optional `nodeId` to set a per-node override instead of the cluster-global default.
|
|
334
|
+
*/
|
|
335
|
+
setActiveSingleton(capability: string, addonId: string, nodeId?: string): Promise<void>;
|
|
336
|
+
/**
|
|
337
|
+
* Check if a specific addon's capability is active system-wide.
|
|
338
|
+
*
|
|
339
|
+
* Resolution: 1. explicit system override → 2. autoActivate flag → 3. default true
|
|
340
|
+
*/
|
|
341
|
+
isActiveForSystem(capability: string, addonId: string): boolean;
|
|
342
|
+
/** Set system-wide activation for a capability/addon pair. */
|
|
343
|
+
setSystemActivation(capability: string, addonId: string, active: boolean): void;
|
|
344
|
+
/**
|
|
345
|
+
* Check if a specific addon's capability is active for a device.
|
|
346
|
+
*
|
|
347
|
+
* Resolution: 1. explicit device override → 2. system activation → 3. autoActivate → 4. default true
|
|
348
|
+
*/
|
|
349
|
+
isActiveForDevice(capability: string, addonId: string, deviceId: string): boolean;
|
|
350
|
+
/** Set device activation for a capability/addon pair. */
|
|
351
|
+
setDeviceActivation(deviceId: string, capability: string, addonId: string, active: boolean): void;
|
|
352
|
+
/**
|
|
353
|
+
* Get all addon/capability activations for a device.
|
|
354
|
+
* Returns every registered provider with its resolved active status.
|
|
355
|
+
*/
|
|
356
|
+
getDeviceActivations(deviceId: string): ReadonlyArray<{
|
|
357
|
+
capability: string;
|
|
358
|
+
addonId: string;
|
|
359
|
+
active: boolean;
|
|
360
|
+
}>;
|
|
361
|
+
/**
|
|
362
|
+
* Get all addon/capability activations at system level.
|
|
363
|
+
* Returns every registered provider with its resolved active status.
|
|
364
|
+
*/
|
|
365
|
+
getSystemActivations(): ReadonlyArray<{
|
|
366
|
+
capability: string;
|
|
367
|
+
addonId: string;
|
|
368
|
+
active: boolean;
|
|
369
|
+
}>;
|
|
370
|
+
/** Set a per-device singleton override. */
|
|
371
|
+
setDeviceOverride(deviceId: string, capability: string, addonId: string): void;
|
|
372
|
+
/** Clear a per-device singleton override. */
|
|
373
|
+
clearDeviceOverride(deviceId: string, capability: string): void;
|
|
374
|
+
/** Get all per-device singleton overrides for a device. */
|
|
375
|
+
getDeviceOverrides(deviceId: string): Map<string, string>;
|
|
376
|
+
/**
|
|
377
|
+
* Resolve a singleton provider for a specific device.
|
|
378
|
+
* Checks activation (autoActivate + explicit overrides) then per-device override.
|
|
379
|
+
*/
|
|
380
|
+
resolveForDevice<T = unknown>(capability: string, deviceId: string): T | null;
|
|
381
|
+
/** Set a per-device collection filter. */
|
|
382
|
+
setDeviceCollectionFilter(deviceId: string, capability: string, addonIds: string[]): void;
|
|
383
|
+
/** Clear a per-device collection filter. */
|
|
384
|
+
clearDeviceCollectionFilter(deviceId: string, capability: string): void;
|
|
385
|
+
/**
|
|
386
|
+
* Resolve collection providers for a specific device.
|
|
387
|
+
* Filters by activation (autoActivate + explicit overrides) and optional collection filter.
|
|
388
|
+
*/
|
|
389
|
+
resolveCollectionForDevice<T = unknown>(capability: string, deviceId: string): readonly T[];
|
|
390
|
+
/** Check if all dependencies for a capability are satisfied. */
|
|
391
|
+
areDependenciesMet(capabilityName: string): boolean;
|
|
392
|
+
/** Get topologically sorted boot order based on dependsOn. */
|
|
393
|
+
getBootOrder(): string[];
|
|
394
|
+
/** Get all auto-mounted routers. Key = capability name. */
|
|
395
|
+
getMountedRouters(): ReadonlyMap<string, CapabilityRouter>;
|
|
396
|
+
/** Get a single mounted router by capability name. */
|
|
397
|
+
getRouter(capabilityName: string): CapabilityRouter | null;
|
|
398
|
+
/** List all declared capabilities (v1-compatible shape). */
|
|
399
|
+
listCapabilities(): CapabilityInfo[];
|
|
400
|
+
/** Check if a capability is declared. */
|
|
401
|
+
has(capabilityName: string): boolean;
|
|
402
|
+
/** Check if a capability has at least one provider. */
|
|
403
|
+
isAvailable(capabilityName: string): boolean;
|
|
404
|
+
/**
|
|
405
|
+
* Return every declared device-scoped capability (`scope: 'device'`)
|
|
406
|
+
* whose `deviceTypes` list includes the given type — or caps that declare
|
|
407
|
+
* no explicit `deviceTypes` (treat as applies-to-all). Used by the
|
|
408
|
+
* bindings UI to enumerate which caps the user can wire for a device.
|
|
409
|
+
*/
|
|
410
|
+
listDeviceScopedCapsForType(deviceType: string): readonly string[];
|
|
411
|
+
private emitEvent;
|
|
412
|
+
}
|
|
@@ -0,0 +1,212 @@
|
|
|
1
|
+
import { AppConfig } from './config-schema.js';
|
|
2
|
+
import { FeatureManifest } from '@camstack/types';
|
|
3
|
+
export interface AddonSettingsView {
|
|
4
|
+
readAddonStore(): Promise<Record<string, unknown>>;
|
|
5
|
+
writeAddonStore(patch: Record<string, unknown>): Promise<void>;
|
|
6
|
+
readDeviceStore(deviceId: number): Promise<Record<string, unknown>>;
|
|
7
|
+
writeDeviceStore(deviceId: number, patch: Record<string, unknown>): Promise<void>;
|
|
8
|
+
clearDeviceStore(deviceId: number): Promise<void>;
|
|
9
|
+
getSection(section: string): Promise<Record<string, unknown>>;
|
|
10
|
+
setSection(section: string, patch: Record<string, unknown>): Promise<void>;
|
|
11
|
+
/**
|
|
12
|
+
* Per-device runtime state — separate namespace from
|
|
13
|
+
* `readDeviceStore` / `writeDeviceStore` (which is the addon's
|
|
14
|
+
* config blob: host, password, deviceCache, …). Holds mutable
|
|
15
|
+
* runtime signals discovered after boot: battery snapshot, sleep
|
|
16
|
+
* flag, last-seen timestamps. Stored under a kernel-internal
|
|
17
|
+
* `__device-state` namespace so the device's config schema
|
|
18
|
+
* never has to know about it (clean separation of operator
|
|
19
|
+
* intent from runtime telemetry).
|
|
20
|
+
*
|
|
21
|
+
* Patch semantics: shallow merge. Pass the FULL persistent slice
|
|
22
|
+
* each call (the kernel doesn't try to compute deltas) — concrete
|
|
23
|
+
* implementations of `DeviceRuntimeState` already coalesce in
|
|
24
|
+
* memory, so the kernel just persists the latest blob.
|
|
25
|
+
*/
|
|
26
|
+
readDeviceRuntimeState(deviceId: number): Promise<Record<string, unknown>>;
|
|
27
|
+
writeDeviceRuntimeState(deviceId: number, data: Record<string, unknown>): Promise<void>;
|
|
28
|
+
clearDeviceRuntimeState(deviceId: number): Promise<void>;
|
|
29
|
+
}
|
|
30
|
+
export interface ISettingsStore {
|
|
31
|
+
getSystem(key: string): unknown;
|
|
32
|
+
setSystem(key: string, value: unknown): void;
|
|
33
|
+
getAllSystem(): Record<string, unknown>;
|
|
34
|
+
/** Addon-level global settings (apply to every device unless overridden). */
|
|
35
|
+
getAllAddon(addonId: string): Record<string, unknown>;
|
|
36
|
+
setAllAddon(addonId: string, config: Record<string, unknown>): void;
|
|
37
|
+
/** Legacy per-provider settings (used by some older wiring paths). */
|
|
38
|
+
getAllProvider(providerId: string): Record<string, unknown>;
|
|
39
|
+
setProvider(providerId: string, key: string, value: unknown): void;
|
|
40
|
+
/** Legacy flat per-device settings. Kept for backward compatibility
|
|
41
|
+
* with pre-addon wiring; new code should use the addon-device API. */
|
|
42
|
+
getAllDevice(deviceId: string): Record<string, unknown>;
|
|
43
|
+
setDevice(deviceId: string, key: string, value: unknown): void;
|
|
44
|
+
/**
|
|
45
|
+
* Multi-level addon settings: per-device overrides for a specific addon.
|
|
46
|
+
*
|
|
47
|
+
* Resolution chain when the frontend asks for the effective value of a
|
|
48
|
+
* field on a given device:
|
|
49
|
+
* 1. schema default (from `ConfigUISchema.field.default`)
|
|
50
|
+
* 2. `getAllAddon(addonId)` — addon global value
|
|
51
|
+
* 3. `getAddonDevice(addonId, devId)` — per-device override (wins)
|
|
52
|
+
*
|
|
53
|
+
* Only fields declared with `scope: 'device'` in the addon's
|
|
54
|
+
* `ConfigUISchema` should ever be persisted here.
|
|
55
|
+
*/
|
|
56
|
+
getAddonDevice(addonId: string, deviceId: string): Record<string, unknown>;
|
|
57
|
+
setAddonDevice(addonId: string, deviceId: string, values: Record<string, unknown>): void;
|
|
58
|
+
clearAddonDevice(addonId: string, deviceId: string): void;
|
|
59
|
+
}
|
|
60
|
+
export declare class ConfigManager {
|
|
61
|
+
private readonly configPath;
|
|
62
|
+
private bootstrapConfig;
|
|
63
|
+
private settingsStore;
|
|
64
|
+
private runtimeState;
|
|
65
|
+
private readonly runtimeStatePath;
|
|
66
|
+
constructor(configPath: string);
|
|
67
|
+
/**
|
|
68
|
+
* Wire the settings-store backend. Called once, after the `settings-store`
|
|
69
|
+
* capability provider has registered (normally during Phase-1 infra boot).
|
|
70
|
+
* Before this call, runtime reads/writes fall back to bootstrap + defaults.
|
|
71
|
+
*/
|
|
72
|
+
setSettingsStore(store: ISettingsStore): void;
|
|
73
|
+
/**
|
|
74
|
+
* Get a config value by dot-notation path.
|
|
75
|
+
* Priority: bootstrap config (yaml) → settings-store → RUNTIME_DEFAULTS fallback.
|
|
76
|
+
*
|
|
77
|
+
* Returns `unknown` — callers must narrow via `typeof`/type guards, OR use
|
|
78
|
+
* the generic overload at their own risk. The generic overload exists only
|
|
79
|
+
* as a convenience alias for legacy call sites; it performs NO runtime
|
|
80
|
+
* check and is the one documented type-level bridge in this function.
|
|
81
|
+
*/
|
|
82
|
+
get(path: string): unknown;
|
|
83
|
+
get<T>(path: string): T | undefined;
|
|
84
|
+
private resolveConfigValue;
|
|
85
|
+
/**
|
|
86
|
+
* Write a value to the settings-store.
|
|
87
|
+
* Throws if the settings store is not yet wired.
|
|
88
|
+
*/
|
|
89
|
+
set(key: string, value: unknown): void;
|
|
90
|
+
/**
|
|
91
|
+
* Bulk-read all keys that belong to a logical section.
|
|
92
|
+
* A "section" is the first segment of a dot-notation key (e.g. 'features', 'logging').
|
|
93
|
+
*
|
|
94
|
+
* Sources are merged in priority order (lowest → highest):
|
|
95
|
+
* 1. RUNTIME_DEFAULTS — kernel constants.
|
|
96
|
+
* 2. Bootstrap config — values loaded from config.yaml at boot.
|
|
97
|
+
* 3. Settings-store — runtime writes via the `settings-store` capability.
|
|
98
|
+
*
|
|
99
|
+
* Higher layers override earlier ones. Merging (instead of short-circuiting
|
|
100
|
+
* on the first non-null source) prevents a single store-seeded key from
|
|
101
|
+
* shadowing the rest of the section that only lives in config.yaml.
|
|
102
|
+
* The kernel is agnostic about the store backend — any `ISettingsStore`
|
|
103
|
+
* implementation (sqlite, redis, in-memory, …) behaves identically here.
|
|
104
|
+
*/
|
|
105
|
+
getSection(section: string): Record<string, unknown>;
|
|
106
|
+
/**
|
|
107
|
+
* Bulk-write a logical section to the settings-store.
|
|
108
|
+
* Each entry in `data` is persisted under the key `section.<entryKey>`.
|
|
109
|
+
*/
|
|
110
|
+
setSection(section: string, data: Record<string, unknown>): void;
|
|
111
|
+
/** Read all config for an addon from addon_settings. */
|
|
112
|
+
getAddonConfig(addonId: string): Record<string, unknown>;
|
|
113
|
+
/** Write (bulk-replace) config for an addon to addon_settings. */
|
|
114
|
+
setAddonConfig(addonId: string, config: Record<string, unknown>): void;
|
|
115
|
+
/** Read all config for a provider from provider_settings. */
|
|
116
|
+
getProviderConfig(providerId: string): Record<string, unknown>;
|
|
117
|
+
/** Write (upsert) a single key for a provider to provider_settings. */
|
|
118
|
+
setProviderConfig(providerId: string, key: string, value: unknown): void;
|
|
119
|
+
/** Read all config for a device from device_settings. */
|
|
120
|
+
getDeviceConfig(deviceId: string): Record<string, unknown>;
|
|
121
|
+
/** Write (upsert) a single key for a device to device_settings. */
|
|
122
|
+
setDeviceConfig(deviceId: string, key: string, value: unknown): void;
|
|
123
|
+
/**
|
|
124
|
+
* Read per-device overrides for a specific addon. Returns a flat record
|
|
125
|
+
* of field → value. Missing keys fall back to the addon-global value via
|
|
126
|
+
* `getAddonConfig(addonId)` — that composition is the resolver service's
|
|
127
|
+
* responsibility, not ConfigManager's.
|
|
128
|
+
*/
|
|
129
|
+
getAddonDevice(addonId: string, deviceId: string): Record<string, unknown>;
|
|
130
|
+
/**
|
|
131
|
+
* Write (bulk-replace) per-device overrides for a specific addon.
|
|
132
|
+
* Throws if the settings store is not yet wired.
|
|
133
|
+
*/
|
|
134
|
+
setAddonDevice(addonId: string, deviceId: string, values: Record<string, unknown>): void;
|
|
135
|
+
/**
|
|
136
|
+
* Clear all per-device overrides for a specific addon/device pair.
|
|
137
|
+
* Resolution falls back to the addon-global value after this call.
|
|
138
|
+
* No-op if the settings store is not yet wired.
|
|
139
|
+
*/
|
|
140
|
+
clearAddonDevice(addonId: string, deviceId: string): void;
|
|
141
|
+
createSettingsView(addonId: string): AddonSettingsView;
|
|
142
|
+
/** Get all system-wide activation overrides. */
|
|
143
|
+
getSystemActivation(): Readonly<Record<string, boolean>>;
|
|
144
|
+
/** Set system-wide activation for a capability/addon pair. */
|
|
145
|
+
setSystemActivation(capability: string, addonId: string, active: boolean): void;
|
|
146
|
+
/**
|
|
147
|
+
* Get activation overrides for a device.
|
|
148
|
+
* Returns a map of `{capability}/{addonId}` → active boolean.
|
|
149
|
+
* Missing entries mean "use system activation or autoActivate default".
|
|
150
|
+
*/
|
|
151
|
+
getDeviceActivation(deviceId: string): Readonly<Record<string, boolean>>;
|
|
152
|
+
/**
|
|
153
|
+
* Get all device activation overrides.
|
|
154
|
+
* Returns deviceId → (`{capability}/{addonId}` → active).
|
|
155
|
+
*/
|
|
156
|
+
getAllDeviceActivation(): Readonly<Record<string, Record<string, boolean>>>;
|
|
157
|
+
/**
|
|
158
|
+
* Set activation for a specific capability/addon on a device.
|
|
159
|
+
* Persists immediately to runtime-state.json.
|
|
160
|
+
*
|
|
161
|
+
* @param deviceId - The device to configure
|
|
162
|
+
* @param capability - Capability name (e.g., 'motion-detection')
|
|
163
|
+
* @param addonId - Addon providing the capability (e.g., 'wasm-motion')
|
|
164
|
+
* @param active - Whether the capability is active on this device
|
|
165
|
+
*/
|
|
166
|
+
setDeviceActivation(deviceId: string, capability: string, addonId: string, active: boolean): void;
|
|
167
|
+
/**
|
|
168
|
+
* Clear all activation overrides for a device (resets to autoActivate defaults).
|
|
169
|
+
*/
|
|
170
|
+
clearDeviceActivation(deviceId: string): void;
|
|
171
|
+
/** Get a value from the parsed bootstrap config.
|
|
172
|
+
* Generic overload is a documented type-level bridge — callers are responsible
|
|
173
|
+
* for passing a T that matches the config.yaml shape. */
|
|
174
|
+
getBootstrap(path: string): unknown;
|
|
175
|
+
getBootstrap<T>(path: string): T | undefined;
|
|
176
|
+
/** Features accessor -- reads from settings-store when available, falls back to RUNTIME_DEFAULTS */
|
|
177
|
+
get features(): FeatureManifest;
|
|
178
|
+
/**
|
|
179
|
+
* Returns a merged view of bootstrap config + runtime defaults for backward compat.
|
|
180
|
+
*/
|
|
181
|
+
get raw(): AppConfig;
|
|
182
|
+
/** Sections that live in config.yaml. Everything else goes to the settings-store. */
|
|
183
|
+
private static readonly BOOTSTRAP_SECTIONS;
|
|
184
|
+
/**
|
|
185
|
+
* Atomically update one top-level section of config.yaml and sync in-memory.
|
|
186
|
+
* Only bootstrap sections (server, auth, mode) are written to YAML.
|
|
187
|
+
* Runtime settings must use setSection() which writes to the settings-store.
|
|
188
|
+
*/
|
|
189
|
+
update(section: string, data: Record<string, unknown>): void;
|
|
190
|
+
/**
|
|
191
|
+
* Deep-set a value in a nested plain object using a dot-notation path.
|
|
192
|
+
* Returns a new object (immutable).
|
|
193
|
+
*/
|
|
194
|
+
private setNested;
|
|
195
|
+
/**
|
|
196
|
+
* Apply env var overrides onto the raw YAML object.
|
|
197
|
+
* Only bootstrap-level env vars are applied.
|
|
198
|
+
*/
|
|
199
|
+
private applyEnvOverrides;
|
|
200
|
+
private loadYaml;
|
|
201
|
+
private warnDefaultCredentials;
|
|
202
|
+
private getFromBootstrap;
|
|
203
|
+
private getFromRuntimeDefaults;
|
|
204
|
+
/**
|
|
205
|
+
* Perform a prefix-based nested lookup against the settings-store.
|
|
206
|
+
* e.g. path='features' matches keys 'features.streaming', 'features.notifications', etc.
|
|
207
|
+
* Returns an object keyed by the sub-key, or undefined if nothing is found.
|
|
208
|
+
*/
|
|
209
|
+
private getNestedFromSystemSettings;
|
|
210
|
+
private loadRuntimeState;
|
|
211
|
+
private saveRuntimeState;
|
|
212
|
+
}
|