@camstack/core 0.1.1 → 0.1.3

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 (66) hide show
  1. package/dist/builtins/local-backup/index.d.mts +42 -0
  2. package/dist/builtins/local-backup/index.d.ts +42 -0
  3. package/dist/builtins/local-backup/index.js +188 -0
  4. package/dist/builtins/local-backup/index.js.map +1 -0
  5. package/dist/builtins/local-backup/index.mjs +11 -0
  6. package/dist/builtins/sqlite-storage/filesystem-storage.addon.d.mts +2 -0
  7. package/dist/builtins/sqlite-storage/filesystem-storage.addon.d.ts +2 -0
  8. package/dist/builtins/sqlite-storage/filesystem-storage.addon.js +210 -0
  9. package/dist/builtins/sqlite-storage/filesystem-storage.addon.js.map +1 -0
  10. package/dist/builtins/sqlite-storage/filesystem-storage.addon.mjs +10 -0
  11. package/dist/builtins/sqlite-storage/index.d.mts +4 -0
  12. package/dist/builtins/sqlite-storage/index.d.ts +4 -0
  13. package/dist/builtins/sqlite-storage/index.js +1025 -0
  14. package/dist/builtins/sqlite-storage/index.js.map +1 -0
  15. package/dist/builtins/sqlite-storage/index.mjs +31 -0
  16. package/dist/builtins/sqlite-storage/index.mjs.map +1 -0
  17. package/dist/builtins/sqlite-storage/sqlite-settings.addon.d.mts +2 -0
  18. package/dist/builtins/sqlite-storage/sqlite-settings.addon.d.ts +2 -0
  19. package/dist/builtins/sqlite-storage/sqlite-settings.addon.js +317 -0
  20. package/dist/builtins/sqlite-storage/sqlite-settings.addon.js.map +1 -0
  21. package/dist/builtins/sqlite-storage/sqlite-settings.addon.mjs +10 -0
  22. package/dist/builtins/sqlite-storage/sqlite-settings.addon.mjs.map +1 -0
  23. package/dist/builtins/winston-logging/index.d.mts +30 -0
  24. package/dist/builtins/winston-logging/index.d.ts +30 -0
  25. package/dist/builtins/winston-logging/index.js +185 -0
  26. package/dist/builtins/winston-logging/index.js.map +1 -0
  27. package/dist/builtins/winston-logging/index.mjs +11 -0
  28. package/dist/builtins/winston-logging/index.mjs.map +1 -0
  29. package/dist/chunk-LQFPAEQF.mjs +147 -0
  30. package/dist/chunk-LQFPAEQF.mjs.map +1 -0
  31. package/dist/{chunk-LZOMFHX3.mjs → chunk-QEMJH3KY.mjs} +11 -1
  32. package/dist/chunk-QEMJH3KY.mjs.map +1 -0
  33. package/dist/chunk-R3DIIBBX.mjs +532 -0
  34. package/dist/chunk-R3DIIBBX.mjs.map +1 -0
  35. package/dist/chunk-SO4LROOT.mjs +150 -0
  36. package/dist/chunk-SO4LROOT.mjs.map +1 -0
  37. package/dist/chunk-SPA4JBKN.mjs +175 -0
  38. package/dist/chunk-SPA4JBKN.mjs.map +1 -0
  39. package/dist/chunk-YXNXYYHL.mjs +282 -0
  40. package/dist/chunk-YXNXYYHL.mjs.map +1 -0
  41. package/dist/dist-N7SR63RN.mjs +3515 -0
  42. package/dist/dist-N7SR63RN.mjs.map +1 -0
  43. package/dist/filesystem-storage.addon-C42r589X.d.mts +57 -0
  44. package/dist/filesystem-storage.addon-C42r589X.d.ts +57 -0
  45. package/dist/index.d.mts +281 -849
  46. package/dist/index.d.ts +281 -849
  47. package/dist/index.js +8351 -1942
  48. package/dist/index.js.map +1 -1
  49. package/dist/index.mjs +4086 -2164
  50. package/dist/index.mjs.map +1 -1
  51. package/dist/onnxruntime_binding-6Q6HXASN.node +0 -0
  52. package/dist/onnxruntime_binding-EKZT2NRK.node +0 -0
  53. package/dist/onnxruntime_binding-P6S7V3CI.node +0 -0
  54. package/dist/onnxruntime_binding-PJNNIIUO.node +0 -0
  55. package/dist/onnxruntime_binding-UN6SPTQK.node +0 -0
  56. package/dist/sql-schema-CKz78rId.d.mts +97 -0
  57. package/dist/sql-schema-CKz78rId.d.ts +97 -0
  58. package/dist/sqlite-settings.addon-DigoKwpZ.d.mts +70 -0
  59. package/dist/sqlite-settings.addon-DigoKwpZ.d.ts +70 -0
  60. package/dist/{storage-location-manager-F4YZMHGM.mjs → storage-location-manager-UQRGHTCA.mjs} +2 -2
  61. package/dist/storage-location-manager-UQRGHTCA.mjs.map +1 -0
  62. package/dist/{wrapper-NTBY5HOA.mjs → wrapper-Y55ADNM5.mjs} +2 -2
  63. package/package.json +64 -12
  64. /package/dist/{chunk-LZOMFHX3.mjs.map → builtins/local-backup/index.mjs.map} +0 -0
  65. /package/dist/{storage-location-manager-F4YZMHGM.mjs.map → builtins/sqlite-storage/filesystem-storage.addon.mjs.map} +0 -0
  66. /package/dist/{wrapper-NTBY5HOA.mjs.map → wrapper-Y55ADNM5.mjs.map} +0 -0
package/dist/index.d.mts CHANGED
@@ -1,7 +1,71 @@
1
- import { ModelDownloadOptions, ModelDownloadResult, IPythonEnvironment, PythonProbeResult, PythonEnvReady, AddonDeclaration, ICamstackAddon, AddonContext, PipelineConfig, FrameInput, PipelineResult, AudioChunkInput, PipelineNode, IScopedLogger, CapabilityDeclaration, CapabilityConsumerRegistration, CapabilityMode, CapabilityInfo, LoggerFactory, AgentRegistrationInfo, AgentToHubMessage, HubToAgentMessage, AgentRuntimeStatus, ITaskHandler, TaskContext, IFileStorage as IFileStorage$1, IStorageProvider as IStorageProvider$1, StorageLocationName as StorageLocationName$1, IStorageLocation as IStorageLocation$1, IConfigurable, AddonManifest, CapabilityProviderMap, ConfigUISchema, ILogDestination as ILogDestination$1, LogEntry as LogEntry$1, LogFilter as LogFilter$1, IEventBus, SystemEvent, EventFilter, TokenScope, ScopedToken, INotificationOutput, Notification, Toast, IAddonRouteProvider, IAddonHttpRoute } from '@camstack/types';
2
- export { EventFilter, EventSource, IScopedLogger, SystemEvent } from '@camstack/types';
1
+ import { IScopedLogger, ModelDownloadOptions, ModelDownloadResult, IAddonModelManager, ModelCatalogEntry, ModelFormat, IPythonEnvironment, PythonProbeResult, PythonEnvReady, PipelineConfig, ValidationResult, FrameInput, PipelineResult, AudioChunkInput, PipelineNode, ElementState as ElementState$1, LoggerFactory, ProcessConfig, ManagedProcessStatus, INetworkQualityTracker, ClientNetworkStats, DeviceNetworkStats, ReplResult, AgentInfo, AgentEntry, AgentStatus, AgentTask, TaskDispatchOptions, AgentTaskResult, LogEntry, LogFilter, AgentRegistrationInfo, AgentToHubMessage, HubToAgentMessage, AgentRuntimeStatus, ITaskHandler, TaskContext, IEventBus, FeatureManifest, FeatureFlag, SystemEvent, EventFilter, IStorageProvider as IStorageProvider$1, ISettingsBackend, TokenScope, ScopedToken, TokenPayload, UserRole, UserRecord, INotificationOutput, Notification, Toast, IAddonRouteProvider, IAddonHttpRoute, PlatformCapabilities, HardwareInfo, PlatformScore, ModelRequirement, ResolvedInferenceConfig, ProviderListItem } from '@camstack/types';
2
+ export { AgentEntry, AgentInfo, AgentResources, AgentStatus, AgentTask, AgentTaskResult, BackupManifest, ClientNetworkStats, DeviceNetworkStats, EventFilter, EventSource, FeatureFlag, FeatureManifest, INetworkQualityTracker, IScopedLogger, LogEntry, LogFilter, LogLevel, ManagedProcessStatus, ProcessConfig, ProcessStats, ProviderListItem, ReplResult, StreamNetworkStats, SystemEvent, TaskDispatchOptions, TokenPayload, UserRecord, UserRole, ValidationIssue, ValidationResult } from '@camstack/types';
3
3
  import { ChildProcess } from 'node:child_process';
4
- import { z } from 'zod';
4
+ import { AddonLoader, AddonEngineManager, CapabilityRegistry } from '@camstack/kernel';
5
+ export { A as AddonTableSchema, C as CORE_TABLE_DDL, F as FileSystemStorage, S as SettingsStore, a as SqliteStorageAddon, b as SqliteStorageProvider, c as addonTableToDdl } from './sql-schema-CKz78rId.mjs';
6
+ export { WinstonDestination, WinstonLoggingAddon } from './builtins/winston-logging/index.mjs';
7
+ export { BackupConfig, LocalBackupAddon, LocalBackupService } from './builtins/local-backup/index.mjs';
8
+
9
+ interface PlatformInfo {
10
+ readonly platform: NodeJS.Platform;
11
+ readonly arch: NodeJS.Architecture;
12
+ }
13
+ declare function getPlatformInfo(): PlatformInfo;
14
+ declare function buildBinaryPath(dataDir: string, name: string, platform?: string): string;
15
+ /** Check if a binary exists in PATH */
16
+ declare function findInPath(name: string): string | null;
17
+ interface DownloadOptions {
18
+ readonly name: string;
19
+ readonly url: string;
20
+ readonly targetDir: string;
21
+ readonly targetName: string;
22
+ readonly logger: IScopedLogger;
23
+ readonly isArchive?: boolean;
24
+ readonly archiveFormat?: 'zip' | 'tar.gz' | 'tar.xz';
25
+ /** Relative path within archive to the binary (e.g., 'ffmpeg-6.1/bin/ffmpeg') */
26
+ readonly archiveInnerPath?: string;
27
+ }
28
+ /**
29
+ * Download a binary to the target directory.
30
+ * Handles archives (zip, tar.gz, tar.xz) and raw binaries.
31
+ */
32
+ declare function downloadBinary(opts: DownloadOptions): Promise<string>;
33
+ /**
34
+ * Ensure a binary is available. Checks:
35
+ * 1. Target path (already downloaded)
36
+ * 2. System PATH
37
+ * 3. Download from URL
38
+ */
39
+ declare function ensureBinary(opts: {
40
+ readonly name: string;
41
+ readonly targetDir: string;
42
+ readonly downloadUrl: string;
43
+ readonly logger: IScopedLogger;
44
+ readonly isArchive?: boolean;
45
+ readonly archiveFormat?: 'zip' | 'tar.gz' | 'tar.xz';
46
+ readonly archiveInnerPath?: string;
47
+ }): Promise<string>;
48
+
49
+ declare function getFfmpegDownloadUrl(platform: string, arch: string): string;
50
+ /**
51
+ * Ensure ffmpeg binary is available.
52
+ * Checks: deps dir → system PATH → download.
53
+ */
54
+ declare function ensureFfmpeg(dataDir: string, logger: IScopedLogger): Promise<string>;
55
+
56
+ declare const PYTHON_VERSION = "3.12.12";
57
+ declare function getPythonDownloadUrl(platform: string, arch: string): string;
58
+ /**
59
+ * Ensure a portable Python is available.
60
+ * Checks: embedded python → system PATH → download portable.
61
+ *
62
+ * Returns the path to the python3 binary.
63
+ */
64
+ declare function ensurePython(dataDir: string, logger: IScopedLogger): Promise<string | null>;
65
+ /**
66
+ * Install Python packages into the portable Python environment.
67
+ */
68
+ declare function installPythonPackages(pythonPath: string, packages: readonly string[], logger: IScopedLogger): Promise<void>;
5
69
 
6
70
  type EventCallback<T = unknown> = (data: T) => void;
7
71
  declare class EventBus {
@@ -13,8 +77,69 @@ declare class EventBus {
13
77
  listenerCount(event: string): number;
14
78
  }
15
79
 
80
+ /**
81
+ * Download a single file from a URL to a destination path.
82
+ * Uses native fetch() (Node 22+) which handles redirects natively.
83
+ * Streams to disk with optional progress callback.
84
+ * Returns the destination path. Skips download if file already exists.
85
+ */
86
+ declare function downloadFile(url: string, destPath: string, onProgress?: (downloaded: number, total: number) => void): Promise<string>;
87
+ /**
88
+ * Fetch JSON from a URL using native fetch().
89
+ */
90
+ declare function fetchJson(url: string): Promise<unknown>;
91
+ /**
92
+ * Download a model with fallback URLs and optional SHA256 verification.
93
+ * Legacy API preserved for backward compatibility -- delegates to downloadFile().
94
+ */
16
95
  declare function downloadModel(options: ModelDownloadOptions): Promise<ModelDownloadResult>;
17
96
 
97
+ /**
98
+ * Unified model download service.
99
+ *
100
+ * Handles downloading model files and extra files (labels, dicts) from a
101
+ * catalog of ModelCatalogEntry items. Supports single-file models and
102
+ * directory bundles (e.g., .mlpackage for CoreML).
103
+ *
104
+ * Addons use this via `context.models.ensure(modelId, format)`.
105
+ */
106
+ declare class ModelDownloadService implements IAddonModelManager {
107
+ private readonly modelsDir;
108
+ private readonly onProgress?;
109
+ private readonly catalog;
110
+ constructor(modelsDir: string, catalog: readonly ModelCatalogEntry[], onProgress?: ((modelId: string, downloaded: number, total: number) => void) | undefined);
111
+ /**
112
+ * Ensure a model (and its extra files) is downloaded.
113
+ * Returns the local filesystem path to the model file/directory.
114
+ */
115
+ ensure(modelId: string, format?: ModelFormat): Promise<string>;
116
+ /**
117
+ * Ensure extra files for a model are downloaded.
118
+ * Returns the local paths of all extra files.
119
+ */
120
+ ensureExtraFiles(modelId: string): Promise<readonly string[]>;
121
+ /** Absolute path to the shared models directory. */
122
+ getModelsDir(): string;
123
+ /** Check if a model file is already present on disk. */
124
+ isDownloaded(modelId: string, format?: ModelFormat): boolean;
125
+ /**
126
+ * Legacy API: download a model by ID (delegates to ensure with default format).
127
+ * Required by IAddonModelManager interface.
128
+ */
129
+ downloadModel(id: string): Promise<string>;
130
+ /** Get the catalog entry for a model by ID. */
131
+ getEntry(modelId: string): ModelCatalogEntry | undefined;
132
+ private pickDefaultFormat;
133
+ private modelFilePath;
134
+ /**
135
+ * Download a directory bundle (e.g., .mlpackage) from HuggingFace.
136
+ * ATOMIC: downloads to temp dir, renames only on complete success.
137
+ */
138
+ private downloadDirectory;
139
+ /** Recursively list all files in a HuggingFace directory via API. */
140
+ private listHfFiles;
141
+ }
142
+
18
143
  declare class PythonEnvManager implements IPythonEnvironment {
19
144
  private readonly dataDir;
20
145
  private venvPath;
@@ -27,113 +152,6 @@ declare class PythonEnvManager implements IPythonEnvironment {
27
152
  spawn(script: string, args: readonly string[]): ChildProcess;
28
153
  }
29
154
 
30
- interface AddonInstallerConfig {
31
- /** Directory where addons are installed (e.g., ~/.camstack/addons or {dataDir}/addons) */
32
- readonly addonsDir: string;
33
- /** Builtin packages to auto-install on first boot */
34
- readonly builtinPackages: readonly string[];
35
- /** npm registry URL (default: https://registry.npmjs.org) */
36
- readonly registry?: string;
37
- }
38
- interface InstalledPackage {
39
- readonly name: string;
40
- readonly version: string;
41
- readonly path: string;
42
- }
43
- declare class AddonInstaller {
44
- private readonly config;
45
- constructor(config: AddonInstallerConfig);
46
- /** Initialize addon directory — create if not exists, install builtins if needed */
47
- initialize(): Promise<void>;
48
- /** Ensure addon directory exists with a package.json */
49
- private ensureAddonDirectory;
50
- /** Install builtin packages if not already present */
51
- private installBuiltins;
52
- /**
53
- * Ensure a set of packages are installed — installs any that are missing.
54
- * This is the public entry-point used during boot to guarantee required
55
- * addon packages are present before the loader tries to resolve them.
56
- */
57
- ensureInstalled(packages: string[]): Promise<void>;
58
- /** Check if a package is installed */
59
- isInstalled(packageName: string): boolean;
60
- /** Get installed package info */
61
- getInstalledPackage(packageName: string): InstalledPackage | null;
62
- /** List all installed addon packages (those with camstack.addons in package.json) */
63
- listInstalled(): InstalledPackage[];
64
- /** Install one or more packages from npm */
65
- installPackages(packages: readonly string[]): Promise<void>;
66
- /** Uninstall a package */
67
- uninstallPackage(packageName: string): Promise<void>;
68
- /** Update a package to latest version */
69
- updatePackage(packageName: string): Promise<void>;
70
- /** Install an addon from a local .tgz file */
71
- installFromTgz(tgzPath: string): Promise<void>;
72
- /** Update all packages */
73
- updateAll(): Promise<void>;
74
- /** Get the node_modules path for require/import resolution */
75
- getNodeModulesPath(): string;
76
- }
77
- /** Default builtin packages that are auto-installed on first boot */
78
- declare const BUILTIN_PACKAGES: readonly string[];
79
-
80
- interface RegisteredAddon {
81
- readonly declaration: AddonDeclaration;
82
- readonly packageName: string;
83
- readonly addonClass: new () => ICamstackAddon;
84
- }
85
- declare class AddonLoader {
86
- private addons;
87
- /** Load all addons from an npm package */
88
- loadPackage(packageName: string): Promise<void>;
89
- /** Load addon from a direct path (for development/testing) */
90
- loadFromPath(addonId: string, modulePath: string, packageName: string, declaration?: Partial<AddonDeclaration>): Promise<void>;
91
- /** Get a registered addon by ID */
92
- getAddon(addonId: string): RegisteredAddon | undefined;
93
- /** List all registered addons */
94
- listAddons(): RegisteredAddon[];
95
- /** Check if an addon is registered */
96
- hasAddon(addonId: string): boolean;
97
- /** Create a new instance of an addon (not yet initialized) */
98
- createInstance(addonId: string): ICamstackAddon;
99
- /** Load all installed addon packages from the addon directory */
100
- loadAllInstalled(installer: AddonInstaller): Promise<void>;
101
- /** Load addon package from a specific filesystem path */
102
- loadPackageFromPath(packageName: string, packagePath: string): Promise<void>;
103
- }
104
-
105
- declare class AddonEngineManager {
106
- private readonly loader;
107
- private readonly baseContext;
108
- private engines;
109
- constructor(loader: AddonLoader, baseContext: Partial<Omit<AddonContext, 'addonConfig'>>);
110
- /**
111
- * Get or create an addon engine for the given effective config.
112
- * Cameras with the same addonId + effective config share the same engine.
113
- */
114
- getOrCreateEngine(addonId: string, globalConfig: Record<string, unknown>, cameraOverride?: Record<string, unknown>): Promise<ICamstackAddon>;
115
- /** Get all active engines */
116
- getActiveEngines(): Map<string, ICamstackAddon>;
117
- /** Shutdown a specific engine by its config key */
118
- shutdownEngine(configKey: string): Promise<void>;
119
- /** Shutdown all engines */
120
- shutdownAll(): Promise<void>;
121
- /** Compute a deterministic config key (visible for tests) */
122
- computeConfigKey(addonId: string, effectiveConfig: Record<string, unknown>): string;
123
- private hashConfig;
124
- }
125
-
126
- interface ValidationIssue {
127
- readonly step?: string;
128
- readonly addon?: string;
129
- readonly message: string;
130
- readonly severity: 'error' | 'warning';
131
- }
132
- interface ValidationResult {
133
- readonly valid: boolean;
134
- readonly errors: readonly ValidationIssue[];
135
- readonly warnings: readonly ValidationIssue[];
136
- }
137
155
  declare class PipelineValidator {
138
156
  private readonly loader;
139
157
  constructor(loader: AddonLoader);
@@ -155,169 +173,7 @@ declare class PipelineRunner {
155
173
  private executeChildren;
156
174
  }
157
175
 
158
- /**
159
- * Central registry for all capability providers and consumers.
160
- * Lives in @camstack/core. Mode-aware: singleton (one active) or collection (all active).
161
- *
162
- * Uses injected LoggingService, NEVER NestJS static Logger.
163
- */
164
- declare class CapabilityRegistry {
165
- private readonly logger;
166
- private readonly configReader;
167
- private readonly capabilities;
168
- /** Per-device singleton overrides: deviceId → (capability → addonId) */
169
- private readonly deviceOverrides;
170
- /** Per-device collection filters: deviceId → (capability → addonIds[]) */
171
- private readonly deviceCollectionFilters;
172
- constructor(logger: IScopedLogger, configReader: (capability: string) => string | undefined);
173
- /**
174
- * Declare a capability (typically called when addon manifests are loaded).
175
- * Must be called before registerProvider/registerConsumer for that capability.
176
- */
177
- declareCapability(declaration: CapabilityDeclaration): void;
178
- /**
179
- * Register a capability provider (called by addon loader when addon is enabled).
180
- * For singleton: auto-activates if user-preferred or first registered.
181
- * For collection: adds to active set and notifies consumers.
182
- */
183
- registerProvider(capability: string, addonId: string, provider: unknown): void;
184
- /**
185
- * Unregister a provider (called when addon is disabled/uninstalled).
186
- */
187
- unregisterProvider(capability: string, addonId: string): void;
188
- /**
189
- * Register a consumer that wants to be notified when providers change.
190
- * If a provider is already active, the consumer is immediately notified.
191
- * Returns a disposer function for cleanup.
192
- */
193
- registerConsumer<T = unknown>(registration: CapabilityConsumerRegistration<T>): () => void;
194
- /**
195
- * Get the active singleton provider for a capability.
196
- * Returns null if none set.
197
- */
198
- getSingleton<T = unknown>(capability: string): T | null;
199
- /**
200
- * Get all active collection providers for a capability.
201
- */
202
- getCollection<T = unknown>(capability: string): readonly T[];
203
- /**
204
- * Set which addon should be the active singleton for a capability.
205
- * Call with `immediate: true` to also swap the runtime provider now
206
- * (consumers' onSet will be awaited).
207
- */
208
- setActiveSingleton(capability: string, addonId: string, immediate?: boolean): Promise<void>;
209
- /**
210
- * Get the mode declared for a capability.
211
- */
212
- getMode(capability: string): CapabilityMode | undefined;
213
- /**
214
- * List all registered capabilities with their providers.
215
- */
216
- listCapabilities(): CapabilityInfo[];
217
- /**
218
- * Check if all dependencies for a capability are satisfied (have active providers).
219
- */
220
- areDependenciesMet(declaration: CapabilityDeclaration): boolean;
221
- /**
222
- * Get the dependency-ordered list of capability names for boot sequencing.
223
- * Returns capabilities sorted topologically by dependsOn.
224
- * Throws if a cycle is detected.
225
- */
226
- getBootOrder(): string[];
227
- /**
228
- * Set a per-device singleton override. When resolveForDevice is called for
229
- * this device + capability, the specified addon's provider is returned
230
- * instead of the global singleton.
231
- */
232
- setDeviceOverride(deviceId: string, capability: string, addonId: string): void;
233
- /**
234
- * Clear a per-device singleton override, reverting to the global singleton.
235
- */
236
- clearDeviceOverride(deviceId: string, capability: string): void;
237
- /**
238
- * Get all per-device singleton overrides for a device.
239
- * Returns a Map of capability name to addon ID.
240
- */
241
- getDeviceOverrides(deviceId: string): Map<string, string>;
242
- /**
243
- * Resolve a singleton provider for a specific device.
244
- * 1. Check device override — return that addon's provider
245
- * 2. Fallback to global singleton
246
- */
247
- resolveForDevice<T = unknown>(capability: string, deviceId: string): T | null;
248
- /**
249
- * Set a per-device collection filter. When resolveCollectionForDevice is called
250
- * for this device + capability, only providers from the specified addon IDs
251
- * are returned instead of the full collection.
252
- */
253
- setDeviceCollectionFilter(deviceId: string, capability: string, addonIds: string[]): void;
254
- /**
255
- * Clear a per-device collection filter, reverting to the full collection.
256
- */
257
- clearDeviceCollectionFilter(deviceId: string, capability: string): void;
258
- /**
259
- * Resolve collection providers for a specific device.
260
- * If a filter exists for the device + capability, only those addon's providers are returned.
261
- * If no filter exists, the full collection is returned.
262
- */
263
- resolveCollectionForDevice<T = unknown>(capability: string, deviceId: string): readonly T[];
264
- /**
265
- * Get a specific addon's provider by addon ID, regardless of whether it's the active singleton.
266
- * Useful for per-device overrides that need to look up any registered provider.
267
- */
268
- getProviderByAddonId<T = unknown>(capability: string, addonId: string): T | null;
269
- private activateSingleton;
270
- private activateSingletonAsync;
271
- }
272
-
273
- interface InfraCapability {
274
- /** Capability name */
275
- readonly name: string;
276
- /** If true, boot aborts when this capability's addon fails to initialize */
277
- readonly required: boolean;
278
- }
279
- /**
280
- * Infrastructure capabilities that must boot before all other addons.
281
- * Enabled in Phase 1 of the boot sequence. Order matters: storage before logging.
282
- */
283
- declare const INFRA_CAPABILITIES: readonly InfraCapability[];
284
- /** Check if a capability name is an infrastructure capability */
285
- declare function isInfraCapability(name: string): boolean;
286
-
287
- type ProcessState = 'stopped' | 'starting' | 'running' | 'stopping' | 'error';
288
- interface ProcessConfig {
289
- readonly id: string;
290
- readonly label: string;
291
- readonly command?: string;
292
- readonly modulePath?: string;
293
- readonly args?: string[];
294
- readonly env?: Record<string, string>;
295
- readonly autoRestart: boolean;
296
- readonly maxRestarts?: number;
297
- readonly healthCheck?: {
298
- readonly intervalMs: number;
299
- readonly timeoutMs: number;
300
- readonly failureThreshold: number;
301
- };
302
- }
303
- interface ProcessStats {
304
- readonly pid: number;
305
- readonly cpu: number;
306
- readonly memory: number;
307
- readonly uptime: number;
308
- readonly restartCount: number;
309
- }
310
- interface ManagedProcessStatus {
311
- readonly id: string;
312
- readonly label: string;
313
- readonly state: ProcessState;
314
- readonly pid?: number;
315
- readonly stats?: ProcessStats;
316
- readonly lastCrashAt?: number;
317
- readonly lastCrashError?: string;
318
- readonly restartCount: number;
319
- readonly nextRestartAt?: number;
320
- }
176
+ type ProcessState = ElementState$1;
321
177
 
322
178
  /** Event emitter for process lifecycle events */
323
179
  type ProcessEventEmitter = {
@@ -363,30 +219,6 @@ declare class ProcessManager {
363
219
  shutdownAll(): Promise<void>;
364
220
  }
365
221
 
366
- interface StreamNetworkStats {
367
- readonly nominalBitrateKbps: number;
368
- readonly observedBitrateKbps: number;
369
- readonly peakBitrateKbps: number;
370
- readonly packetLossPercent: number;
371
- readonly lastUpdated: number;
372
- }
373
- interface ClientNetworkStats {
374
- readonly rttMs: number;
375
- readonly jitterMs: number;
376
- readonly estimatedBandwidthKbps: number;
377
- readonly lastUpdated: number;
378
- }
379
- interface DeviceNetworkStats {
380
- readonly deviceId: string;
381
- readonly streams: Readonly<Record<string, StreamNetworkStats>>;
382
- readonly client?: ClientNetworkStats;
383
- }
384
- interface INetworkQualityTracker {
385
- reportStreamStats(deviceId: string, streamId: string, bitrateKbps: number, packetLoss?: number): void;
386
- reportClientStats(deviceId: string, stats: Omit<ClientNetworkStats, 'lastUpdated'>): void;
387
- getDeviceStats(deviceId: string): DeviceNetworkStats | null;
388
- getAllStats(): readonly DeviceNetworkStats[];
389
- }
390
222
  declare class NetworkQualityTracker implements INetworkQualityTracker {
391
223
  private readonly devices;
392
224
  private static readonly MAX_SAMPLES;
@@ -408,11 +240,7 @@ interface ReplSessionContext {
408
240
  /** Pre-populated variables available in the REPL session */
409
241
  readonly variables: Record<string, unknown>;
410
242
  }
411
- interface ReplResult {
412
- readonly output: string;
413
- readonly type: 'value' | 'error' | 'void';
414
- readonly duration: number;
415
- }
243
+
416
244
  interface IReplEngine {
417
245
  execute(code: string, context: ReplSessionContext): Promise<ReplResult>;
418
246
  getCompletions(partial: string, context: ReplSessionContext): Promise<string[]>;
@@ -436,62 +264,6 @@ declare class ReplEngine implements IReplEngine {
436
264
  private buildSandbox;
437
265
  }
438
266
 
439
- interface AgentInfo {
440
- readonly id: string;
441
- readonly name: string;
442
- readonly capabilities: readonly string[];
443
- readonly host: string;
444
- readonly port: number;
445
- readonly resources?: AgentResources;
446
- }
447
- interface AgentResources {
448
- readonly cpuCores?: number;
449
- readonly memoryMB?: number;
450
- readonly gpuAvailable?: boolean;
451
- readonly gpuModel?: string;
452
- }
453
- interface AgentStatus {
454
- readonly id: string;
455
- readonly name: string;
456
- readonly state: 'online' | 'offline' | 'degraded';
457
- readonly capabilities: readonly string[];
458
- readonly lastHeartbeat: number;
459
- readonly connectedSince?: number;
460
- readonly resources?: AgentResources;
461
- readonly activeTaskCount: number;
462
- readonly completedTaskCount: number;
463
- readonly failedTaskCount: number;
464
- }
465
- interface AgentTask {
466
- readonly id: string;
467
- readonly capability: string;
468
- readonly input: Record<string, unknown>;
469
- readonly timeout: number;
470
- readonly priority: 'low' | 'normal' | 'high';
471
- readonly label?: string;
472
- }
473
- interface AgentTaskResult {
474
- readonly taskId: string;
475
- readonly agentId: string;
476
- readonly status: 'success' | 'error' | 'timeout';
477
- readonly output?: Record<string, unknown>;
478
- readonly error?: string;
479
- readonly durationMs: number;
480
- }
481
- interface TaskDispatchOptions {
482
- readonly preferredAgent?: string;
483
- readonly capability: string;
484
- readonly remoteOnly?: boolean;
485
- }
486
- interface AgentEntry {
487
- readonly info: AgentInfo;
488
- state: 'online' | 'offline' | 'degraded';
489
- connectedSince: number;
490
- lastHeartbeat: number;
491
- activeTaskCount: number;
492
- completedTaskCount: number;
493
- failedTaskCount: number;
494
- }
495
267
  /** Event emitter for agent lifecycle and task events */
496
268
  type AgentEventEmitter = {
497
269
  emitAgentRegistered(agentId: string, capabilities: readonly string[]): void;
@@ -543,21 +315,6 @@ declare class TaskDispatcher {
543
315
  private sendToAgent;
544
316
  }
545
317
 
546
- type LogLevel = 'debug' | 'info' | 'warn' | 'error';
547
- interface LogEntry {
548
- timestamp: Date;
549
- level: LogLevel;
550
- scope: string[];
551
- message: string;
552
- meta?: Record<string, unknown>;
553
- }
554
- interface LogFilter {
555
- scope?: string[];
556
- level?: LogLevel;
557
- since?: Date;
558
- until?: Date;
559
- limit?: number;
560
- }
561
318
  declare class LogRingBuffer {
562
319
  private readonly capacity;
563
320
  private readonly buffer;
@@ -706,128 +463,6 @@ declare class RecordTaskHandler implements ITaskHandler {
706
463
  cancel(): Promise<void>;
707
464
  }
708
465
 
709
- declare class FileSystemStorage implements IFileStorage$1 {
710
- private readonly basePath;
711
- constructor(basePath: string);
712
- readFile(filePath: string): Promise<Buffer>;
713
- writeFile(filePath: string, data: Buffer): Promise<void>;
714
- deleteFile(filePath: string): Promise<void>;
715
- listFiles(prefix?: string): Promise<readonly string[]>;
716
- getFileUrl(_path: string): Promise<string>;
717
- exists(filePath: string): Promise<boolean>;
718
- }
719
- declare class SqliteStorageProvider implements IStorageProvider$1 {
720
- private mainDb;
721
- private sharedStructured;
722
- private readonly locations;
723
- initialize(): Promise<void>;
724
- /**
725
- * Configure all storage locations.
726
- * ONE single SQLite database (camstack.db) is used for ALL structured storage.
727
- * File-based locations use the filesystem at their configured path.
728
- */
729
- configure(config: {
730
- locations: Record<string, string>;
731
- }): Promise<void>;
732
- getLocation(name: StorageLocationName$1): IStorageLocation$1;
733
- shutdown(): Promise<void>;
734
- export(_locationName: StorageLocationName$1): Promise<Buffer>;
735
- import(_locationName: StorageLocationName$1, _data: Buffer): Promise<void>;
736
- }
737
-
738
- declare class SqliteStorageAddon implements ICamstackAddon, IConfigurable {
739
- readonly manifest: AddonManifest;
740
- private provider;
741
- initialize(context: AddonContext): Promise<void>;
742
- shutdown(): Promise<void>;
743
- getProvider(): SqliteStorageProvider;
744
- getCapabilityProvider<K extends keyof CapabilityProviderMap>(name: K): CapabilityProviderMap[K] | null;
745
- getConfigSchema(): ConfigUISchema;
746
- getConfig(): Record<string, unknown>;
747
- onConfigChange(_config: Record<string, unknown>): Promise<void>;
748
- }
749
-
750
- interface WinstonConfig {
751
- readonly level: string;
752
- readonly retentionDays: number;
753
- /** Resolved absolute path to the logs directory (replaces the old dataPath field). */
754
- readonly logsDir: string;
755
- }
756
- declare class WinstonDestination implements ILogDestination$1 {
757
- private logger;
758
- initialize(config?: WinstonConfig): Promise<void>;
759
- write(entry: LogEntry$1): void;
760
- query(_filter: LogFilter$1): Promise<readonly LogEntry$1[]>;
761
- shutdown(): Promise<void>;
762
- }
763
-
764
- declare class WinstonLoggingAddon implements ICamstackAddon, IConfigurable {
765
- readonly manifest: AddonManifest;
766
- private destination;
767
- private currentConfig;
768
- initialize(context: AddonContext): Promise<void>;
769
- shutdown(): Promise<void>;
770
- getDestination(): WinstonDestination;
771
- getCapabilityProvider<K extends keyof CapabilityProviderMap>(name: K): CapabilityProviderMap[K] | null;
772
- getConfigSchema(): ConfigUISchema;
773
- getConfig(): Record<string, unknown>;
774
- onConfigChange(config: Record<string, unknown>): Promise<void>;
775
- }
776
-
777
- interface BackupManifest {
778
- readonly id: string;
779
- readonly timestamp: number;
780
- readonly label?: string;
781
- readonly locations: readonly string[];
782
- readonly sizeMB: number;
783
- readonly path: string;
784
- }
785
- interface BackupConfig {
786
- readonly backupDir: string;
787
- readonly retentionCount: number;
788
- }
789
- declare class LocalBackupService {
790
- private readonly config;
791
- private readonly logger;
792
- private readonly eventBus;
793
- private readonly storage;
794
- private manifests;
795
- constructor(config: BackupConfig, logger: IScopedLogger, eventBus: IEventBus, storage: IStorageLocation$1);
796
- /** Create a backup of specified locations */
797
- backup(options?: {
798
- locations?: string[];
799
- label?: string;
800
- }): Promise<BackupManifest>;
801
- /** Restore from a backup */
802
- restore(backupId: string): Promise<void>;
803
- /** List all backups sorted by timestamp descending */
804
- list(): readonly BackupManifest[];
805
- /** Delete a specific backup */
806
- delete(backupId: string): Promise<void>;
807
- private pruneOldBackups;
808
- }
809
-
810
- declare class LocalBackupAddon implements ICamstackAddon, IConfigurable {
811
- readonly manifest: AddonManifest;
812
- private service;
813
- private currentConfig;
814
- initialize(context: AddonContext): Promise<void>;
815
- shutdown(): Promise<void>;
816
- getService(): LocalBackupService;
817
- getCapabilityProvider<K extends keyof CapabilityProviderMap>(name: K): CapabilityProviderMap[K] | null;
818
- getConfigSchema(): ConfigUISchema;
819
- getConfig(): Record<string, unknown>;
820
- onConfigChange(config: Record<string, unknown>): Promise<void>;
821
- }
822
-
823
- declare class AdminUIAddon implements ICamstackAddon {
824
- readonly id = "admin-ui";
825
- readonly manifest: AddonManifest;
826
- initialize(_ctx: AddonContext): Promise<void>;
827
- shutdown(): Promise<void>;
828
- getCapabilityProvider<K extends keyof CapabilityProviderMap>(name: K): CapabilityProviderMap[K] | null;
829
- }
830
-
831
466
  type ElementState = 'stopped' | 'starting' | 'running' | 'stopping' | 'error' | 'disabled';
832
467
  interface ElementStatus {
833
468
  state: ElementState;
@@ -856,18 +491,6 @@ declare class LifecycleStateMachine {
856
491
  private isValidTransition;
857
492
  }
858
493
 
859
- interface FeatureManifest {
860
- streaming: boolean;
861
- notifications: boolean;
862
- objectDetection: boolean;
863
- remoteAccess: boolean;
864
- agentCluster: boolean;
865
- smartHome: boolean;
866
- recordings: boolean;
867
- backup: boolean;
868
- repl: boolean;
869
- }
870
- type FeatureFlag = keyof FeatureManifest;
871
494
  type FeatureConfigReader = {
872
495
  readonly features: FeatureManifest;
873
496
  };
@@ -878,240 +501,6 @@ declare class FeatureManager {
878
501
  getManifest(): FeatureManifest;
879
502
  }
880
503
 
881
- /** Bootstrap config -- loaded from config.yaml ONLY at startup.
882
- * All other settings live in SQL (system_settings table). */
883
- declare const bootstrapSchema: z.ZodObject<{
884
- /** Server mode: 'hub' (full server) or 'agent' (worker node) */
885
- mode: z.ZodDefault<z.ZodEnum<["hub", "agent"]>>;
886
- server: z.ZodDefault<z.ZodObject<{
887
- port: z.ZodDefault<z.ZodNumber>;
888
- host: z.ZodDefault<z.ZodString>;
889
- dataPath: z.ZodDefault<z.ZodString>;
890
- }, "strip", z.ZodTypeAny, {
891
- port: number;
892
- host: string;
893
- dataPath: string;
894
- }, {
895
- port?: number | undefined;
896
- host?: string | undefined;
897
- dataPath?: string | undefined;
898
- }>>;
899
- auth: z.ZodDefault<z.ZodObject<{
900
- jwtSecret: z.ZodDefault<z.ZodNullable<z.ZodString>>;
901
- adminUsername: z.ZodDefault<z.ZodString>;
902
- adminPassword: z.ZodDefault<z.ZodString>;
903
- }, "strip", z.ZodTypeAny, {
904
- jwtSecret: string | null;
905
- adminUsername: string;
906
- adminPassword: string;
907
- }, {
908
- jwtSecret?: string | null | undefined;
909
- adminUsername?: string | undefined;
910
- adminPassword?: string | undefined;
911
- }>>;
912
- /** Hub connection config — only used when mode='agent' */
913
- hub: z.ZodDefault<z.ZodObject<{
914
- url: z.ZodDefault<z.ZodString>;
915
- token: z.ZodDefault<z.ZodString>;
916
- }, "strip", z.ZodTypeAny, {
917
- url: string;
918
- token: string;
919
- }, {
920
- url?: string | undefined;
921
- token?: string | undefined;
922
- }>>;
923
- /** Agent-specific config — only used when mode='agent' */
924
- agent: z.ZodDefault<z.ZodObject<{
925
- name: z.ZodDefault<z.ZodString>;
926
- /** Port for the agent status page (minimal HTML) */
927
- statusPort: z.ZodDefault<z.ZodNumber>;
928
- }, "strip", z.ZodTypeAny, {
929
- name: string;
930
- statusPort: number;
931
- }, {
932
- name?: string | undefined;
933
- statusPort?: number | undefined;
934
- }>>;
935
- }, "strip", z.ZodTypeAny, {
936
- agent: {
937
- name: string;
938
- statusPort: number;
939
- };
940
- auth: {
941
- jwtSecret: string | null;
942
- adminUsername: string;
943
- adminPassword: string;
944
- };
945
- mode: "agent" | "hub";
946
- hub: {
947
- url: string;
948
- token: string;
949
- };
950
- server: {
951
- port: number;
952
- host: string;
953
- dataPath: string;
954
- };
955
- }, {
956
- agent?: {
957
- name?: string | undefined;
958
- statusPort?: number | undefined;
959
- } | undefined;
960
- auth?: {
961
- jwtSecret?: string | null | undefined;
962
- adminUsername?: string | undefined;
963
- adminPassword?: string | undefined;
964
- } | undefined;
965
- mode?: "agent" | "hub" | undefined;
966
- hub?: {
967
- url?: string | undefined;
968
- token?: string | undefined;
969
- } | undefined;
970
- server?: {
971
- port?: number | undefined;
972
- host?: string | undefined;
973
- dataPath?: string | undefined;
974
- } | undefined;
975
- }>;
976
- type BootstrapConfig = z.infer<typeof bootstrapSchema>;
977
- /**
978
- * Runtime defaults -- used by ConfigManager.get() for backward compatibility
979
- * until Plan B wires all runtime settings to the system_settings SQL table.
980
- */
981
- declare const RUNTIME_DEFAULTS: Record<string, unknown>;
982
- type ServerMode = 'hub' | 'agent';
983
- type AppConfig = BootstrapConfig & {
984
- features: {
985
- streaming: boolean;
986
- notifications: boolean;
987
- objectDetection: boolean;
988
- remoteAccess: boolean;
989
- agentCluster: boolean;
990
- smartHome: boolean;
991
- recordings: boolean;
992
- backup: boolean;
993
- repl: boolean;
994
- };
995
- storage: {
996
- provider: string;
997
- locations: Record<string, string>;
998
- };
999
- logging: {
1000
- level: string;
1001
- retentionDays: number;
1002
- };
1003
- eventBus: {
1004
- ringBufferSize: number;
1005
- };
1006
- addons: {
1007
- enabled: string[];
1008
- };
1009
- retention: {
1010
- detectionEventsDays: number;
1011
- audioLevelsDays: number;
1012
- };
1013
- providers: Array<{
1014
- id: string;
1015
- type: string;
1016
- name: string;
1017
- url?: string;
1018
- username?: string;
1019
- password?: string;
1020
- mqtt?: {
1021
- brokerUrl: string;
1022
- username?: string;
1023
- password?: string;
1024
- topicPrefix: string;
1025
- };
1026
- }>;
1027
- };
1028
-
1029
- interface ISettingsStore {
1030
- getSystem(key: string): unknown;
1031
- setSystem(key: string, value: unknown): void;
1032
- getAllSystem(): Record<string, unknown>;
1033
- getAllAddon(addonId: string): Record<string, unknown>;
1034
- setAllAddon(addonId: string, config: Record<string, unknown>): void;
1035
- getAllProvider(providerId: string): Record<string, unknown>;
1036
- setProvider(providerId: string, key: string, value: unknown): void;
1037
- getAllDevice(deviceId: string): Record<string, unknown>;
1038
- setDevice(deviceId: string, key: string, value: unknown): void;
1039
- }
1040
- declare class ConfigManager {
1041
- private readonly configPath;
1042
- private bootstrapConfig;
1043
- private settingsStore;
1044
- constructor(configPath: string);
1045
- /** Called by main.ts after the SQLite DB is ready (Phase 2). */
1046
- setSettingsStore(store: ISettingsStore): void;
1047
- /**
1048
- * Get a config value by dot-notation path.
1049
- * Priority: bootstrap config -> SQL system_settings -> RUNTIME_DEFAULTS fallback.
1050
- */
1051
- get<T>(path: string): T;
1052
- /**
1053
- * Write a value to SQL system_settings.
1054
- * Throws if the settings store is not yet wired.
1055
- */
1056
- set(key: string, value: unknown): void;
1057
- /**
1058
- * Bulk-read all system_settings keys that belong to a logical section.
1059
- * A "section" is the first segment of a dot-notation key (e.g. 'features', 'logging').
1060
- */
1061
- getSection(section: string): Record<string, unknown>;
1062
- /**
1063
- * Bulk-write a section of runtime settings to SQL system_settings.
1064
- * Each entry in `data` is stored as `section.key`.
1065
- */
1066
- setSection(section: string, data: Record<string, unknown>): void;
1067
- /** Read all config for an addon from addon_settings. */
1068
- getAddonConfig(addonId: string): Record<string, unknown>;
1069
- /** Write (bulk-replace) config for an addon to addon_settings. */
1070
- setAddonConfig(addonId: string, config: Record<string, unknown>): void;
1071
- /** Read all config for a provider from provider_settings. */
1072
- getProviderConfig(providerId: string): Record<string, unknown>;
1073
- /** Write (upsert) a single key for a provider to provider_settings. */
1074
- setProviderConfig(providerId: string, key: string, value: unknown): void;
1075
- /** Read all config for a device from device_settings. */
1076
- getDeviceConfig(deviceId: string): Record<string, unknown>;
1077
- /** Write (upsert) a single key for a device to device_settings. */
1078
- setDeviceConfig(deviceId: string, key: string, value: unknown): void;
1079
- /** Get a value from the parsed bootstrap config */
1080
- getBootstrap<T>(path: string): T;
1081
- /** Features accessor -- reads from SQL when available, falls back to RUNTIME_DEFAULTS */
1082
- get features(): FeatureManifest;
1083
- /**
1084
- * Returns a merged view of bootstrap config + runtime defaults for backward compat.
1085
- */
1086
- get raw(): AppConfig;
1087
- /**
1088
- * Atomically update one top-level section of config.yaml and sync in-memory.
1089
- * Only bootstrap sections (server, auth) are persisted. Runtime settings should
1090
- * go to SQL (Plan B).
1091
- */
1092
- update(section: string, data: Record<string, unknown>): void;
1093
- /**
1094
- * Deep-set a value in a nested plain object using a dot-notation path.
1095
- * Returns a new object (immutable).
1096
- */
1097
- private setNested;
1098
- /**
1099
- * Apply env var overrides onto the raw YAML object.
1100
- * Only bootstrap-level env vars are applied.
1101
- */
1102
- private applyEnvOverrides;
1103
- private loadYaml;
1104
- private warnDefaultCredentials;
1105
- private getFromBootstrap;
1106
- private getFromRuntimeDefaults;
1107
- /**
1108
- * Perform a prefix-based nested lookup against SQL system_settings.
1109
- * e.g. path='features' matches keys 'features.streaming', 'features.notifications', etc.
1110
- * Returns an object keyed by the sub-key, or undefined if nothing is found.
1111
- */
1112
- private getNestedFromSystemSettings;
1113
- }
1114
-
1115
504
  declare class SystemEventBus implements IEventBus {
1116
505
  private readonly ringBuffer;
1117
506
  private readonly subscribers;
@@ -1185,8 +574,8 @@ interface IStorageProvider {
1185
574
  initialize(): Promise<void>;
1186
575
  shutdown(): Promise<void>;
1187
576
  getLocation(name: StorageLocationName): IStorageLocation;
1188
- export(locationName: StorageLocationName): Promise<Buffer>;
1189
- import(locationName: StorageLocationName, data: Buffer): Promise<void>;
577
+ export?(locationName: StorageLocationName): Promise<Buffer>;
578
+ import?(locationName: StorageLocationName, data: Buffer): Promise<void>;
1190
579
  }
1191
580
  interface QueryFilter {
1192
581
  where?: Record<string, unknown>;
@@ -1223,94 +612,38 @@ interface IStorageLocation {
1223
612
  structured?: IStructuredStorage;
1224
613
  files?: IFileStorage;
1225
614
  }
615
+ /**
616
+ * StorageManager — bridge between legacy code (getLocation/getLocationPath)
617
+ * and the new capability-based storage system.
618
+ *
619
+ * Legacy consumers call getLocation('addon', namespace) to get structured + file storage.
620
+ * This manager builds the response from:
621
+ * - SettingsBackend (for structured queries) — provided by sqlite-settings addon
622
+ * - LocationManager (for file paths) — set during Phase 2 boot
623
+ */
1226
624
  declare class StorageManager {
1227
- private provider;
625
+ private legacyProvider;
1228
626
  private locationManager;
1229
- setProvider(provider: IStorageProvider): void;
627
+ private newStorageProvider;
628
+ private settingsBackend;
629
+ /** @deprecated Set by legacy capability consumer — use setNewStorageProvider instead */
630
+ setProvider(provider: IStorageProvider | IStorageProvider$1): void;
631
+ setNewStorageProvider(provider: IStorageProvider$1): void;
632
+ setSettingsBackend(backend: ISettingsBackend): void;
1230
633
  getProvider(): IStorageProvider;
1231
- /**
1232
- * Set the StorageLocationManager (called from main.ts during Phase 2 boot,
1233
- * before NestJS lifecycle hooks run).
1234
- */
1235
634
  setLocationManager(manager: StorageLocationManager): void;
1236
- /**
1237
- * Get the StorageLocationManager (for file path resolution).
1238
- * Available after Phase 2 boot (main.ts calls setLocationManager).
1239
- */
1240
635
  getLocationManager(): StorageLocationManager;
1241
- /**
1242
- * Initialize the StorageLocationManager with a dataPath and set it on this service.
1243
- * Called during 3-phase boot from main.ts (Phase 2).
1244
- */
1245
636
  initializeLocations(dataPath: string): Promise<void>;
1246
- /**
1247
- * Return the base filesystem path for a named storage location.
1248
- * Convenience wrapper around locationManager.getBackend(name).basePath.
1249
- * Available after Phase 2 boot (main.ts calls setLocationManager).
1250
- */
1251
637
  getLocationPath(name: StorageLocationName): string;
1252
638
  /**
1253
- * Get a storage location, optionally namespaced.
1254
- * Without namespace: returns the raw location (e.g., 'config' -> config DB)
1255
- * With namespace: returns a scoped view where all collections/paths are prefixed
1256
- * e.g., getLocation('addon', 'providers/frigate-1') -> collections prefixed with 'providers/frigate-1/'
639
+ * Get a storage location with optional namespace scoping.
640
+ * Builds IStorageLocation from settingsBackend (structured) + locationManager (files).
1257
641
  */
1258
642
  getLocation(name: StorageLocationName | string, namespace?: string): IStorageLocation;
643
+ private createLegacyShim;
1259
644
  private createNamespacedLocation;
1260
645
  }
1261
646
 
1262
- /**
1263
- * Thin wrapper over better-sqlite3 that manages the four settings tables:
1264
- * system_settings, addon_settings, provider_settings, device_settings.
1265
- *
1266
- * All values are stored as JSON text and deserialized on read.
1267
- */
1268
- declare class SettingsStore {
1269
- private readonly db;
1270
- constructor(dbPath: string);
1271
- getSystem(key: string): unknown;
1272
- setSystem(key: string, value: unknown): void;
1273
- getAllSystem(): Record<string, unknown>;
1274
- getAddon(addonId: string, key: string): unknown;
1275
- setAddon(addonId: string, key: string, value: unknown): void;
1276
- getAllAddon(addonId: string): Record<string, unknown>;
1277
- /** Bulk-replace all keys for an addon (within a transaction). */
1278
- setAllAddon(addonId: string, config: Record<string, unknown>): void;
1279
- getProvider(providerId: string, key: string): unknown;
1280
- setProvider(providerId: string, key: string, value: unknown): void;
1281
- getAllProvider(providerId: string): Record<string, unknown>;
1282
- getDevice(deviceId: string, key: string): unknown;
1283
- setDevice(deviceId: string, key: string, value: unknown): void;
1284
- getAllDevice(deviceId: string): Record<string, unknown>;
1285
- /** Close the SQLite connection (call on shutdown). */
1286
- close(): void;
1287
- /** Check if system_settings is empty (used for first-boot seeding). */
1288
- isSystemSettingsEmpty(): boolean;
1289
- /** Seed system_settings with RUNTIME_DEFAULTS (only on first boot). */
1290
- seedDefaults(): void;
1291
- private initTables;
1292
- }
1293
-
1294
- /** Core table DDL statements -- executed on first boot */
1295
- declare const CORE_TABLE_DDL: readonly string[];
1296
- /** Addon table schema declaration */
1297
- interface AddonTableSchema {
1298
- readonly name: string;
1299
- readonly columns: ReadonlyArray<{
1300
- readonly name: string;
1301
- readonly type: 'TEXT' | 'INTEGER' | 'REAL' | 'JSON';
1302
- readonly primaryKey?: boolean;
1303
- readonly notNull?: boolean;
1304
- }>;
1305
- readonly indexes?: ReadonlyArray<{
1306
- readonly name: string;
1307
- readonly columns: readonly string[];
1308
- readonly unique?: boolean;
1309
- }>;
1310
- }
1311
- /** Generate CREATE TABLE DDL from addon schema */
1312
- declare function addonTableToDdl(schema: AddonTableSchema): string[];
1313
-
1314
647
  /**
1315
648
  * Manages scoped API tokens with restricted addon/route/capability access.
1316
649
  * Framework-agnostic — dependencies injected via constructor.
@@ -1348,18 +681,6 @@ declare class ScopedTokenManager {
1348
681
  updateLastUsed(tokenId: string): Promise<void>;
1349
682
  }
1350
683
 
1351
- type UserRole = 'super_admin' | 'admin' | 'viewer';
1352
- interface TokenPayload {
1353
- type?: 'api_key';
1354
- keyId?: string;
1355
- userId?: string;
1356
- username?: string;
1357
- role: UserRole;
1358
- allowedProviders: string[] | '*';
1359
- allowedDevices: Record<string, string[] | '*'>;
1360
- iat?: number;
1361
- exp?: number;
1362
- }
1363
684
  type AuthConfigReader = {
1364
685
  get<T>(path: string): T;
1365
686
  update(section: string, data: Record<string, unknown>): void;
@@ -1379,6 +700,15 @@ declare class AuthManager {
1379
700
  prefix: string;
1380
701
  };
1381
702
  validateApiKey(token: string, storedHash: string): boolean;
703
+ /**
704
+ * Create a service token for agent/worker authentication.
705
+ * Used when forking workers or when agents register.
706
+ */
707
+ createServiceToken(opts: {
708
+ readonly agentId: string;
709
+ readonly role?: string;
710
+ readonly expiresIn?: string;
711
+ }): string;
1382
712
  /**
1383
713
  * Set the scoped token manager for the auth chain.
1384
714
  */
@@ -1429,16 +759,6 @@ declare class ApiKeyManager {
1429
759
  findById(id: string): Promise<ApiKeyRecord | null>;
1430
760
  }
1431
761
 
1432
- interface UserRecord {
1433
- id: string;
1434
- username: string;
1435
- passwordHash: string;
1436
- role: UserRole;
1437
- allowedProviders: string[] | '*';
1438
- allowedDevices: Record<string, string[] | '*'>;
1439
- createdAt: number;
1440
- updatedAt: number;
1441
- }
1442
762
  interface CreateUserInput {
1443
763
  username: string;
1444
764
  password: string;
@@ -1612,6 +932,125 @@ declare class CapabilityResolver {
1612
932
  getEffectiveCapabilities(device: IResolvableDevice): string[];
1613
933
  }
1614
934
 
935
+ interface TlsCertPair {
936
+ readonly cert: Buffer;
937
+ readonly key: Buffer;
938
+ }
939
+ interface EnsureTlsResult {
940
+ readonly certPath: string;
941
+ readonly keyPath: string;
942
+ readonly generated: boolean;
943
+ }
944
+ interface CertOptions {
945
+ /** Common Name for the cert (default: 'camstack.local') */
946
+ readonly commonName?: string;
947
+ /** Validity in days (default: 825 — max for browsers) */
948
+ readonly validDays?: number;
949
+ /** Additional SANs (DNS names or IPs) */
950
+ readonly extraSans?: readonly string[];
951
+ }
952
+ /**
953
+ * Ensure a self-signed TLS certificate exists in the given directory.
954
+ * Generates one if missing. Returns paths to cert and key files.
955
+ */
956
+ declare function ensureTlsCert(dataDir: string, options?: CertOptions): Promise<EnsureTlsResult>;
957
+ /**
958
+ * Load TLS cert+key from files. Returns Buffers suitable for Node.js TLS options.
959
+ */
960
+ declare function loadTlsCert(certPath: string, keyPath: string): TlsCertPair;
961
+
962
+ /**
963
+ * Factory for creating tRPC clients for addons.
964
+ *
965
+ * Two modes:
966
+ * - Direct caller (in-process): zero overhead, uses createCallerFactory
967
+ * - WSS client (worker/agent): real WebSocket connection to the server
968
+ */
969
+ interface DirectCallerOptions {
970
+ /** The tRPC router instance (from buildAppRouter) */
971
+ readonly router: unknown;
972
+ /** Context for the caller (user identity, etc.) */
973
+ readonly context: {
974
+ readonly user: {
975
+ readonly id: string;
976
+ readonly username: string;
977
+ readonly role: string;
978
+ };
979
+ };
980
+ }
981
+ interface WssClientOptions {
982
+ /** WebSocket URL (e.g., wss://localhost:4443/trpc) */
983
+ readonly url: string;
984
+ /** Auth token for the connection */
985
+ readonly token: string;
986
+ }
987
+ declare class AddonApiFactory {
988
+ /**
989
+ * Build a WSS URL from host and port.
990
+ */
991
+ buildWssUrl(host: string, port: number): string;
992
+ /**
993
+ * Create a direct caller -- calls tRPC procedures directly in-process.
994
+ * Zero network overhead. Used for in-process addons and dev mode.
995
+ *
996
+ * @param options.router - The tRPC router from buildAppRouter()
997
+ * @param options.context - The auth context (service account)
998
+ * @returns A tRPC caller that can be used as context.api
999
+ */
1000
+ createDirectCaller(options: DirectCallerOptions): unknown;
1001
+ /**
1002
+ * Create a WSS tRPC client -- connects to the server via WebSocket.
1003
+ * Used for forked workers and remote agents.
1004
+ *
1005
+ * @param options.url - WSS URL (e.g., wss://localhost:4443/trpc)
1006
+ * @param options.token - Bearer token for authentication
1007
+ * @returns A tRPC client that can be used as context.api
1008
+ */
1009
+ createWssClient(options: WssClientOptions): Promise<{
1010
+ readonly client: unknown;
1011
+ readonly close: () => void;
1012
+ }>;
1013
+ }
1014
+
1015
+ declare class PlatformScorer {
1016
+ private cached;
1017
+ /** Probe hardware + runtimes and score all backend combos. Cached after first call. */
1018
+ probe(): Promise<PlatformCapabilities>;
1019
+ probeHardware(): Promise<HardwareInfo>;
1020
+ private probeNodeBackends;
1021
+ private probePythonBackends;
1022
+ private scoreBackends;
1023
+ }
1024
+
1025
+ declare class InferenceConfigResolver {
1026
+ private readonly scores;
1027
+ private readonly hardware;
1028
+ constructor(scores: readonly PlatformScore[], hardware: HardwareInfo);
1029
+ /**
1030
+ * Compute accuracy/backend weights based on available system RAM.
1031
+ * availableRAM_MB is now sourced from systeminformation (reliable cross-platform),
1032
+ * not os.freemem() which is broken on macOS.
1033
+ *
1034
+ * - > 16 GB available: prefer larger, more accurate models (accuracy 0.6, backend 0.4)
1035
+ * - > 8 GB available: balanced (accuracy 0.5, backend 0.5)
1036
+ * - <= 8 GB available: prefer speed (accuracy 0.4, backend 0.6)
1037
+ */
1038
+ private getWeights;
1039
+ /**
1040
+ * Given an addon's model requirements, pick the best model + runtime + backend.
1041
+ *
1042
+ * Algorithm:
1043
+ * 1. Filter models by available RAM (minRAM_MB < 25% of available RAM)
1044
+ * 2. For each remaining model, find the best platform score whose format
1045
+ * is available in the model's formats
1046
+ * 3. Pick the model with the highest combined score using RAM-adaptive weights:
1047
+ * - High RAM (>16 GB): accuracy × 0.6 + backend × 0.4 (prefer accuracy)
1048
+ * - Mid RAM (>8 GB): accuracy × 0.5 + backend × 0.5 (balanced)
1049
+ * - Low RAM (<=8 GB): accuracy × 0.4 + backend × 0.6 (prefer speed)
1050
+ */
1051
+ resolve(requirements: readonly ModelRequirement[]): ResolvedInferenceConfig;
1052
+ }
1053
+
1615
1054
  /** Minimal device registry interface for provider management */
1616
1055
  type ProviderDeviceRegistry = {
1617
1056
  registerProviderDevices(providerId: string, devices: readonly IRegistrableDevice[]): void;
@@ -1644,14 +1083,7 @@ interface IManagedProvider {
1644
1083
  getDevices(): readonly IRegistrableDevice[];
1645
1084
  subscribeLiveEvents(callback: (event: LiveEvent) => void): () => void;
1646
1085
  }
1647
- interface ProviderListItem {
1648
- id: string;
1649
- type: string;
1650
- name: string;
1651
- status: ProviderStatus;
1652
- started: boolean;
1653
- lifecycle: ElementStatus;
1654
- }
1086
+
1655
1087
  declare class ProviderManager<P extends IManagedProvider = IManagedProvider> {
1656
1088
  private readonly deviceRegistry;
1657
1089
  private readonly eventBus;
@@ -1671,4 +1103,4 @@ declare class ProviderManager<P extends IManagedProvider = IManagedProvider> {
1671
1103
  shutdownAll(): Promise<void>;
1672
1104
  }
1673
1105
 
1674
- export { AddonEngineManager, AddonInstaller, type AddonInstallerConfig, AddonLoader, AddonRouteRegistry, type AddonTableSchema, AdminUIAddon, AgentClient, type AgentClientConfig, type AgentEntry, type AgentEventEmitter, type AgentInfo, AgentRegistry, type AgentResources, type AgentStatus, type AgentTask, type AgentTaskResult, AgentTaskRunner, ApiKeyManager, type ApiKeyRecord, type ApiKeyStorageAccess, type AppConfig, type AuthConfigReader, AuthManager, BUILTIN_PACKAGES, type BackupConfig, type BackupManifest, type BinaryHandler, type BootstrapConfig, CORE_TABLE_DDL, type CapabilityBinding, CapabilityRegistry, CapabilityResolver, type ClientNetworkStats, ConfigManager, type ConnectionHandler, DecodeTaskHandler, DetectTaskHandler, type DeviceNetworkStats, DeviceRegistry, type ElementState, type ElementStatus, EventBus, type FeatureConfigReader, type FeatureFlag, FeatureManager, type FeatureManifest, FileSystemStorage, FsStorageBackend, type IAddonRegistryAccess, type IStorageProvider as ICoreStorageProvider, type IDeviceCapability, type IFileStorage, type ILogDestination, type IManagedProvider, INFRA_CAPABILITIES, type INetworkQualityTracker, type IRegisteredDevice, type IReplContextProvider, type IReplEngine, type IResolvableDevice, type ISettingsStore, type IStorageBackend, type IStorageLocation, type IStructuredStorage, type InfraCapability, type InstalledPackage, LifecycleStateMachine, LocalBackupAddon, LocalBackupService, type LogEntry, type LogFilter, type LogLevel, LogManager, LogRingBuffer, ManagedProcess, type ManagedProcessStatus, type MessageHandler, NetworkQualityTracker, NotificationService, PipelineRunner, PipelineValidator, type ProcessConfig, type ProcessEventEmitter, type ProcessLoggerFactory, ProcessManager, type ProcessState, type ProcessStats, type ProviderDeviceRegistry, type ProviderListItem, ProviderManager, PythonEnvManager, type QueryFilter, RUNTIME_DEFAULTS, RecordTaskHandler, type RegisteredAddon, ReplEngine, type ReplResult, type ReplScope, type ReplSessionContext, ScopedLogger, ScopedTokenManager, type ServerMode, SettingsStore, SqliteStorageAddon, SqliteStorageProvider, StorageLocationManager, type StorageLocationName, StorageManager, type StorageRecord, type StreamNetworkStats, SystemEventBus, type TaskDispatchOptions, TaskDispatcher, ToastService, type TokenPayload, type Unsubscribe, type UserConfigReader, UserManager, type UserRecord, type UserRole, type UserStorageAccess, type ValidationIssue, type ValidationResult, WinstonDestination, WinstonLoggingAddon, addonTableToDdl, bootstrapSchema, downloadModel, isInfraCapability };
1106
+ export { AddonApiFactory, AddonRouteRegistry, AgentClient, type AgentClientConfig, type AgentEventEmitter, AgentRegistry, AgentTaskRunner, ApiKeyManager, type ApiKeyRecord, type ApiKeyStorageAccess, type AuthConfigReader, AuthManager, type BinaryHandler, type CapabilityBinding, CapabilityResolver, type CertOptions, type ConnectionHandler, DecodeTaskHandler, DetectTaskHandler, DeviceRegistry, type DirectCallerOptions, type ElementState, type ElementStatus, type EnsureTlsResult, EventBus, type FeatureConfigReader, FeatureManager, FsStorageBackend, type IAddonRegistryAccess, type IStorageProvider as ICoreStorageProvider, type IDeviceCapability, type IFileStorage, type ILogDestination, type IManagedProvider, type IRegisteredDevice, type IReplContextProvider, type IReplEngine, type IResolvableDevice, type IStorageBackend, type IStorageLocation, type IStructuredStorage, InferenceConfigResolver, LifecycleStateMachine, LogManager, LogRingBuffer, ManagedProcess, type MessageHandler, ModelDownloadService, NetworkQualityTracker, NotificationService, PYTHON_VERSION, PipelineRunner, PipelineValidator, PlatformScorer, type ProcessEventEmitter, type ProcessLoggerFactory, ProcessManager, type ProcessState, type ProviderDeviceRegistry, ProviderManager, PythonEnvManager, type QueryFilter, RecordTaskHandler, ReplEngine, type ReplScope, type ReplSessionContext, ScopedLogger, ScopedTokenManager, StorageLocationManager, type StorageLocationName, StorageManager, type StorageRecord, SystemEventBus, TaskDispatcher, type TlsCertPair, ToastService, type Unsubscribe, type UserConfigReader, UserManager, type UserStorageAccess, type WssClientOptions, buildBinaryPath, downloadBinary, downloadFile, downloadModel, ensureBinary, ensureFfmpeg, ensurePython, ensureTlsCert, fetchJson, findInPath, getFfmpegDownloadUrl, getPlatformInfo, getPythonDownloadUrl, installPythonPackages, loadTlsCert };