@camstack/types 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 (200) hide show
  1. package/dist/__tests__/addon-capability-provider.test.d.ts +2 -0
  2. package/dist/__tests__/addon-capability-provider.test.d.ts.map +1 -0
  3. package/dist/__tests__/addon-declaration.test.d.ts +2 -0
  4. package/dist/__tests__/addon-declaration.test.d.ts.map +1 -0
  5. package/dist/__tests__/capability.test.d.ts +2 -0
  6. package/dist/__tests__/capability.test.d.ts.map +1 -0
  7. package/dist/catalogs/coco-classmap.d.ts +5 -0
  8. package/dist/catalogs/coco-classmap.d.ts.map +1 -0
  9. package/dist/catalogs/index.d.ts +2 -0
  10. package/dist/catalogs/index.d.ts.map +1 -0
  11. package/dist/constants.d.ts +3 -0
  12. package/dist/constants.d.ts.map +1 -0
  13. package/dist/generated/addon-api.d.ts +4870 -0
  14. package/dist/generated/addon-api.d.ts.map +1 -0
  15. package/dist/index.d.ts +82 -3053
  16. package/dist/index.d.ts.map +1 -0
  17. package/dist/index.js +377 -8
  18. package/dist/index.js.map +1 -1
  19. package/dist/index.mjs +369 -7
  20. package/dist/index.mjs.map +1 -1
  21. package/dist/interfaces/addon-i18n.d.ts +41 -0
  22. package/dist/interfaces/addon-i18n.d.ts.map +1 -0
  23. package/dist/interfaces/addon-routes.d.ts +50 -0
  24. package/dist/interfaces/addon-routes.d.ts.map +1 -0
  25. package/dist/interfaces/addon.d.ts +294 -0
  26. package/dist/interfaces/addon.d.ts.map +1 -0
  27. package/dist/interfaces/advanced-notifier.d.ts +59 -0
  28. package/dist/interfaces/advanced-notifier.d.ts.map +1 -0
  29. package/dist/interfaces/agent-protocol.d.ts +189 -0
  30. package/dist/interfaces/agent-protocol.d.ts.map +1 -0
  31. package/dist/interfaces/agent.d.ts +87 -0
  32. package/dist/interfaces/agent.d.ts.map +1 -0
  33. package/dist/interfaces/analysis-persistence.d.ts +278 -0
  34. package/dist/interfaces/analysis-persistence.d.ts.map +1 -0
  35. package/dist/interfaces/analysis.d.ts +27 -0
  36. package/dist/interfaces/analysis.d.ts.map +1 -0
  37. package/dist/interfaces/api-shared.d.ts +168 -0
  38. package/dist/interfaces/api-shared.d.ts.map +1 -0
  39. package/dist/interfaces/auth-provider.d.ts +39 -0
  40. package/dist/interfaces/auth-provider.d.ts.map +1 -0
  41. package/dist/interfaces/auth.d.ts +47 -0
  42. package/dist/interfaces/auth.d.ts.map +1 -0
  43. package/dist/interfaces/camera-pipeline.d.ts +121 -0
  44. package/dist/interfaces/camera-pipeline.d.ts.map +1 -0
  45. package/dist/interfaces/capability.d.ts +84 -0
  46. package/dist/interfaces/capability.d.ts.map +1 -0
  47. package/dist/interfaces/classifier.d.ts +8 -0
  48. package/dist/interfaces/classifier.d.ts.map +1 -0
  49. package/dist/interfaces/config-ui.d.ts +152 -0
  50. package/dist/interfaces/config-ui.d.ts.map +1 -0
  51. package/dist/interfaces/context.d.ts +44 -0
  52. package/dist/interfaces/context.d.ts.map +1 -0
  53. package/dist/interfaces/cropper.d.ts +8 -0
  54. package/dist/interfaces/cropper.d.ts.map +1 -0
  55. package/dist/interfaces/decoder.d.ts +27 -0
  56. package/dist/interfaces/decoder.d.ts.map +1 -0
  57. package/dist/interfaces/detection-addon.d.ts +15 -0
  58. package/dist/interfaces/detection-addon.d.ts.map +1 -0
  59. package/dist/interfaces/detector.d.ts +8 -0
  60. package/dist/interfaces/detector.d.ts.map +1 -0
  61. package/dist/interfaces/device-capabilities/accessory.d.ts +14 -0
  62. package/dist/interfaces/device-capabilities/accessory.d.ts.map +1 -0
  63. package/dist/interfaces/device-capabilities/audio-detector.d.ts +12 -0
  64. package/dist/interfaces/device-capabilities/audio-detector.d.ts.map +1 -0
  65. package/dist/interfaces/device-capabilities/camera.d.ts +22 -0
  66. package/dist/interfaces/device-capabilities/camera.d.ts.map +1 -0
  67. package/dist/interfaces/device-capabilities/doorbell.d.ts +10 -0
  68. package/dist/interfaces/device-capabilities/doorbell.d.ts.map +1 -0
  69. package/dist/interfaces/device-capabilities/events.d.ts +47 -0
  70. package/dist/interfaces/device-capabilities/events.d.ts.map +1 -0
  71. package/dist/interfaces/device-capabilities/index.d.ts +15 -0
  72. package/dist/interfaces/device-capabilities/index.d.ts.map +1 -0
  73. package/dist/interfaces/device-capabilities/motion-sensor.d.ts +7 -0
  74. package/dist/interfaces/device-capabilities/motion-sensor.d.ts.map +1 -0
  75. package/dist/interfaces/device-capabilities/native-detection.d.ts +14 -0
  76. package/dist/interfaces/device-capabilities/native-detection.d.ts.map +1 -0
  77. package/dist/interfaces/device-capabilities/object-detector.d.ts +59 -0
  78. package/dist/interfaces/device-capabilities/object-detector.d.ts.map +1 -0
  79. package/dist/interfaces/device-capabilities/pan-tilt-zoom.d.ts +29 -0
  80. package/dist/interfaces/device-capabilities/pan-tilt-zoom.d.ts.map +1 -0
  81. package/dist/interfaces/device-capabilities/recording.d.ts +18 -0
  82. package/dist/interfaces/device-capabilities/recording.d.ts.map +1 -0
  83. package/dist/interfaces/device-capabilities/siren.d.ts +8 -0
  84. package/dist/interfaces/device-capabilities/siren.d.ts.map +1 -0
  85. package/dist/interfaces/device-capabilities/status-light.d.ts +7 -0
  86. package/dist/interfaces/device-capabilities/status-light.d.ts.map +1 -0
  87. package/dist/interfaces/device-capabilities/switch.d.ts +8 -0
  88. package/dist/interfaces/device-capabilities/switch.d.ts.map +1 -0
  89. package/dist/interfaces/device-capabilities/two-way-audio.d.ts +8 -0
  90. package/dist/interfaces/device-capabilities/two-way-audio.d.ts.map +1 -0
  91. package/dist/interfaces/device-capability.d.ts +14 -0
  92. package/dist/interfaces/device-capability.d.ts.map +1 -0
  93. package/dist/interfaces/device-provider.d.ts +43 -0
  94. package/dist/interfaces/device-provider.d.ts.map +1 -0
  95. package/dist/interfaces/device.d.ts +40 -0
  96. package/dist/interfaces/device.d.ts.map +1 -0
  97. package/dist/interfaces/event-bus.d.ts +22 -0
  98. package/dist/interfaces/event-bus.d.ts.map +1 -0
  99. package/dist/interfaces/feature-flags.d.ts +14 -0
  100. package/dist/interfaces/feature-flags.d.ts.map +1 -0
  101. package/dist/interfaces/ffmpeg.d.ts +10 -0
  102. package/dist/interfaces/ffmpeg.d.ts.map +1 -0
  103. package/dist/interfaces/inference-capabilities.d.ts +101 -0
  104. package/dist/interfaces/inference-capabilities.d.ts.map +1 -0
  105. package/dist/interfaces/inference-engine.d.ts +17 -0
  106. package/dist/interfaces/inference-engine.d.ts.map +1 -0
  107. package/dist/interfaces/lifecycle.d.ts +19 -0
  108. package/dist/interfaces/lifecycle.d.ts.map +1 -0
  109. package/dist/interfaces/logging.d.ts +33 -0
  110. package/dist/interfaces/logging.d.ts.map +1 -0
  111. package/dist/interfaces/model-catalog.d.ts +25 -0
  112. package/dist/interfaces/model-catalog.d.ts.map +1 -0
  113. package/dist/interfaces/network-quality.d.ts +25 -0
  114. package/dist/interfaces/network-quality.d.ts.map +1 -0
  115. package/dist/interfaces/network.d.ts +43 -0
  116. package/dist/interfaces/network.d.ts.map +1 -0
  117. package/dist/interfaces/notification.d.ts +53 -0
  118. package/dist/interfaces/notification.d.ts.map +1 -0
  119. package/dist/interfaces/pipeline-runner.d.ts +23 -0
  120. package/dist/interfaces/pipeline-runner.d.ts.map +1 -0
  121. package/dist/interfaces/pipeline-slot.d.ts +10 -0
  122. package/dist/interfaces/pipeline-slot.d.ts.map +1 -0
  123. package/dist/interfaces/platform.d.ts +55 -0
  124. package/dist/interfaces/platform.d.ts.map +1 -0
  125. package/dist/interfaces/process.d.ts +41 -0
  126. package/dist/interfaces/process.d.ts.map +1 -0
  127. package/dist/interfaces/python-env.d.ts +20 -0
  128. package/dist/interfaces/python-env.d.ts.map +1 -0
  129. package/dist/interfaces/refiner.d.ts +8 -0
  130. package/dist/interfaces/refiner.d.ts.map +1 -0
  131. package/dist/interfaces/repl.d.ts +26 -0
  132. package/dist/interfaces/repl.d.ts.map +1 -0
  133. package/dist/interfaces/repositories.d.ts +20 -0
  134. package/dist/interfaces/repositories.d.ts.map +1 -0
  135. package/dist/interfaces/restreamer.d.ts +24 -0
  136. package/dist/interfaces/restreamer.d.ts.map +1 -0
  137. package/dist/interfaces/router.d.ts +30 -0
  138. package/dist/interfaces/router.d.ts.map +1 -0
  139. package/dist/interfaces/scene-intelligence.d.ts +21 -0
  140. package/dist/interfaces/scene-intelligence.d.ts.map +1 -0
  141. package/dist/interfaces/scoped-token.d.ts +22 -0
  142. package/dist/interfaces/scoped-token.d.ts.map +1 -0
  143. package/dist/interfaces/server-analysis.d.ts +146 -0
  144. package/dist/interfaces/server-analysis.d.ts.map +1 -0
  145. package/dist/interfaces/server-network.d.ts +78 -0
  146. package/dist/interfaces/server-network.d.ts.map +1 -0
  147. package/dist/interfaces/storage-backend.d.ts +27 -0
  148. package/dist/interfaces/storage-backend.d.ts.map +1 -0
  149. package/dist/interfaces/storage.d.ts +174 -0
  150. package/dist/interfaces/storage.d.ts.map +1 -0
  151. package/dist/interfaces/stream-broker.d.ts +92 -0
  152. package/dist/interfaces/stream-broker.d.ts.map +1 -0
  153. package/dist/interfaces/streaming.d.ts +29 -0
  154. package/dist/interfaces/streaming.d.ts.map +1 -0
  155. package/dist/interfaces/task-handler.d.ts +46 -0
  156. package/dist/interfaces/task-handler.d.ts.map +1 -0
  157. package/dist/interfaces/webrtc-provider.d.ts +11 -0
  158. package/dist/interfaces/webrtc-provider.d.ts.map +1 -0
  159. package/dist/interfaces/worker-protocol.d.ts +110 -0
  160. package/dist/interfaces/worker-protocol.d.ts.map +1 -0
  161. package/dist/schemas/system-settings-schemas.d.ts +27 -0
  162. package/dist/schemas/system-settings-schemas.d.ts.map +1 -0
  163. package/dist/types/analytics.d.ts +75 -0
  164. package/dist/types/analytics.d.ts.map +1 -0
  165. package/dist/types/benchmark.d.ts +112 -0
  166. package/dist/types/benchmark.d.ts.map +1 -0
  167. package/dist/types/camera-detection.d.ts +34 -0
  168. package/dist/types/camera-detection.d.ts.map +1 -0
  169. package/dist/types/config.d.ts +37 -0
  170. package/dist/types/config.d.ts.map +1 -0
  171. package/dist/types/detection.d.ts +93 -0
  172. package/dist/types/detection.d.ts.map +1 -0
  173. package/dist/types/device-type.d.ts +10 -0
  174. package/dist/types/device-type.d.ts.map +1 -0
  175. package/dist/types/entities.d.ts +35 -0
  176. package/dist/types/entities.d.ts.map +1 -0
  177. package/dist/types/events.d.ts +35 -0
  178. package/dist/types/events.d.ts.map +1 -0
  179. package/dist/types/io.d.ts +25 -0
  180. package/dist/types/io.d.ts.map +1 -0
  181. package/dist/types/labels.d.ts +12 -0
  182. package/dist/types/labels.d.ts.map +1 -0
  183. package/dist/types/live-state.d.ts +47 -0
  184. package/dist/types/live-state.d.ts.map +1 -0
  185. package/dist/types/models.d.ts +79 -0
  186. package/dist/types/models.d.ts.map +1 -0
  187. package/dist/types/pipeline-schema.d.ts +78 -0
  188. package/dist/types/pipeline-schema.d.ts.map +1 -0
  189. package/dist/types/pipeline.d.ts +42 -0
  190. package/dist/types/pipeline.d.ts.map +1 -0
  191. package/dist/types/tracked.d.ts +21 -0
  192. package/dist/types/tracked.d.ts.map +1 -0
  193. package/dist/types/zones.d.ts +48 -0
  194. package/dist/types/zones.d.ts.map +1 -0
  195. package/dist/utils/cosine-similarity.d.ts +3 -0
  196. package/dist/utils/cosine-similarity.d.ts.map +1 -0
  197. package/dist/utils/hf-url.d.ts +2 -0
  198. package/dist/utils/hf-url.d.ts.map +1 -0
  199. package/package.json +16 -5
  200. package/dist/index.d.mts +0 -3053
package/dist/index.d.ts CHANGED
@@ -1,3053 +1,82 @@
1
- import { ChildProcess } from 'node:child_process';
2
-
3
- interface BoundingBox {
4
- readonly x: number;
5
- readonly y: number;
6
- readonly w: number;
7
- readonly h: number;
8
- }
9
- interface Landmark {
10
- readonly x: number;
11
- readonly y: number;
12
- readonly label?: string;
13
- }
14
- interface FrameInput {
15
- readonly data: Buffer;
16
- readonly format: 'jpeg' | 'rgb' | 'yuv420';
17
- readonly width: number;
18
- readonly height: number;
19
- readonly timestamp: number;
20
- }
21
- interface AudioChunkInput {
22
- readonly data: Float32Array;
23
- readonly sampleRate: number;
24
- readonly channels: number;
25
- readonly timestamp: number;
26
- }
27
-
28
- interface LabelDefinition {
29
- readonly id: string;
30
- readonly name: string;
31
- readonly category?: string;
32
- readonly description?: string;
33
- readonly icon?: string;
34
- }
35
- interface ClassMapDefinition {
36
- readonly mapping: Readonly<Record<string, string>>;
37
- readonly preserveOriginal: boolean;
38
- }
39
-
40
- interface SpatialDetection {
41
- readonly class: string;
42
- readonly originalClass: string;
43
- readonly score: number;
44
- readonly bbox: BoundingBox;
45
- readonly landmarks?: readonly Landmark[];
46
- readonly mask?: Uint8Array;
47
- readonly maskWidth?: number;
48
- readonly maskHeight?: number;
49
- }
50
- interface CropInput {
51
- readonly frame: FrameInput;
52
- readonly roi: BoundingBox;
53
- readonly parentDetection: SpatialDetection;
54
- }
55
- interface Classification {
56
- readonly class: string;
57
- readonly score: number;
58
- readonly text?: string;
59
- readonly embedding?: Float32Array;
60
- readonly metadata?: Readonly<Record<string, unknown>>;
61
- }
62
- interface DetectorOutput {
63
- readonly detections: readonly SpatialDetection[];
64
- readonly inferenceMs: number;
65
- readonly modelId: string;
66
- }
67
- interface CropperOutput {
68
- readonly crops: readonly SpatialDetection[];
69
- readonly inferenceMs: number;
70
- readonly modelId: string;
71
- }
72
- interface ClassifierOutput {
73
- readonly classifications: readonly Classification[];
74
- readonly inferenceMs: number;
75
- readonly modelId: string;
76
- }
77
-
78
- type ObjectState = 'entering' | 'moving' | 'stationary' | 'leaving' | 'loitering';
79
- interface TrackedDetection extends SpatialDetection {
80
- readonly trackId: string;
81
- readonly trackAge: number;
82
- readonly velocity?: {
83
- readonly dx: number;
84
- readonly dy: number;
85
- };
86
- readonly path: readonly BoundingBox[];
87
- }
88
- interface TrackedObjectState {
89
- readonly trackId: string;
90
- readonly state: ObjectState;
91
- readonly stationarySince?: number;
92
- readonly enteredAt: number;
93
- readonly totalDistancePx: number;
94
- readonly dwellTimeMs: number;
95
- }
96
-
97
- type DetectionEventType = 'object.detected' | 'object.classified' | 'object.entering' | 'object.leaving' | 'object.stationary' | 'object.loitering' | 'zone.enter' | 'zone.exit' | 'tripwire.cross' | 'audio.detected';
98
- interface ZoneEvent {
99
- readonly type: 'zone-enter' | 'zone-exit' | 'zone-loiter' | 'tripwire-cross';
100
- readonly zoneId: string;
101
- readonly zoneName: string;
102
- readonly trackId: string;
103
- readonly detection: TrackedDetection;
104
- readonly direction?: 'in' | 'out' | 'left' | 'right';
105
- readonly timestamp: number;
106
- }
107
- interface EventSnapshot {
108
- readonly thumbnailPath: string;
109
- readonly annotatedFramePath: string;
110
- readonly debugThumbnails?: Readonly<Record<string, string>>;
111
- readonly clipPath?: string;
112
- readonly clipDurationSec?: number;
113
- }
114
- interface DetectionEvent {
115
- readonly id: string;
116
- readonly type: DetectionEventType;
117
- readonly timestamp: number;
118
- readonly deviceId: string;
119
- readonly detection: TrackedDetection;
120
- readonly classifications: readonly Classification[];
121
- readonly objectState: TrackedObjectState;
122
- readonly zoneEvents: readonly ZoneEvent[];
123
- readonly snapshot?: EventSnapshot;
124
- readonly trackPath: readonly BoundingBox[];
125
- }
126
-
127
- type DetectionRuntime = 'onnx' | 'coreml' | 'pytorch' | 'openvino' | 'tflite';
128
- type DetectionDevice = 'cpu' | 'gpu-cuda' | 'gpu-mps' | 'npu' | 'coral-edgetpu' | 'tensorrt';
129
- type ProbeCapability = 'fp32' | 'fp16' | 'int8' | 'batch-inference';
130
- interface ProbeResult {
131
- readonly available: boolean;
132
- readonly runtime: DetectionRuntime;
133
- readonly device: DetectionDevice;
134
- readonly capabilities: readonly ProbeCapability[];
135
- readonly estimatedMemoryMB?: number;
136
- }
137
- interface CameraAnalysisConfig {
138
- readonly tracker: {
139
- readonly maxAge: number;
140
- readonly minHits: number;
141
- readonly iouThreshold: number;
142
- };
143
- readonly stateAnalyzer: {
144
- readonly stationaryThresholdSec: number;
145
- readonly loiteringThresholdSec: number;
146
- readonly velocityThreshold: number;
147
- };
148
- readonly snapshots: {
149
- readonly enabled: boolean;
150
- readonly saveThumbnail: boolean;
151
- readonly saveAnnotatedFrame: boolean;
152
- readonly saveDebugThumbnails: boolean;
153
- readonly clipPreSec: number;
154
- readonly clipPostSec: number;
155
- };
156
- readonly events: {
157
- readonly minTrackAge: number;
158
- readonly cooldownSec: number;
159
- readonly enabledTypes: readonly DetectionEventType[];
160
- };
161
- }
162
-
163
- interface ZoneDefinition {
164
- readonly id: string;
165
- readonly name: string;
166
- readonly cameraId: string;
167
- readonly type: 'polygon' | 'tripwire';
168
- readonly points: ReadonlyArray<{
169
- readonly x: number;
170
- readonly y: number;
171
- }>;
172
- readonly direction?: 'in' | 'out' | 'both';
173
- readonly alertOnClasses?: readonly string[];
174
- readonly color?: string;
175
- }
176
- interface KnownFace {
177
- readonly id: string;
178
- readonly name: string;
179
- readonly label?: string;
180
- readonly embeddings: readonly Float32Array[];
181
- readonly thumbnailPath?: string;
182
- readonly createdAt: number;
183
- }
184
- interface KnownPlate {
185
- readonly id: string;
186
- readonly plateText: string;
187
- readonly label?: string;
188
- readonly vehicleDescription?: string;
189
- readonly createdAt: number;
190
- }
191
- interface KnownAudioEvent {
192
- readonly id: string;
193
- readonly className: string;
194
- readonly label: string;
195
- readonly notifyAlways: boolean;
196
- }
197
-
198
- type ModelFormat$1 = 'onnx' | 'coreml' | 'openvino' | 'tflite' | 'pt';
199
- type ModelOutputFormat = 'yolo' | 'ssd' | 'embedding' | 'classification' | 'ocr';
200
- interface ModelFormatEntry {
201
- readonly url: string;
202
- readonly sizeMB: number;
203
- }
204
- interface ModelCatalogEntry {
205
- readonly id: string;
206
- readonly name: string;
207
- readonly description: string;
208
- readonly formats: Partial<Readonly<Record<ModelFormat$1, ModelFormatEntry>>>;
209
- readonly inputSize: {
210
- readonly width: number;
211
- readonly height: number;
212
- };
213
- readonly labels: readonly LabelDefinition[];
214
- readonly inputLayout?: 'nchw' | 'nhwc';
215
- readonly inputNormalization?: 'zero-one' | 'imagenet' | 'none';
216
- }
217
- interface DetectionModel {
218
- readonly id: string;
219
- readonly name: string;
220
- readonly labels: readonly string[];
221
- readonly inputSize: {
222
- readonly width: number;
223
- readonly height: number;
224
- };
225
- }
226
- interface ModelDownloadOptions {
227
- readonly url: string;
228
- readonly fallbackUrls?: readonly string[];
229
- readonly destDir: string;
230
- readonly filename?: string;
231
- readonly expectedSha256?: string;
232
- readonly onProgress?: (downloaded: number, total: number) => void;
233
- }
234
- interface ModelDownloadResult {
235
- readonly filePath: string;
236
- readonly downloadedBytes: number;
237
- readonly fromCache: boolean;
238
- }
239
- interface CustomModelMetadata {
240
- readonly name: string;
241
- readonly inputSize: {
242
- readonly width: number;
243
- readonly height: number;
244
- };
245
- readonly labels: readonly LabelDefinition[];
246
- readonly classMap?: ClassMapDefinition;
247
- readonly inputLayout?: 'nchw' | 'nhwc';
248
- readonly inputNormalization?: 'zero-one' | 'imagenet' | 'none';
249
- readonly outputFormat: ModelOutputFormat;
250
- }
251
-
252
- type PipelineSlot = 'detector' | 'cropper' | 'classifier';
253
- interface PipelineNode {
254
- readonly step: string;
255
- readonly addon: string;
256
- readonly configOverride?: Readonly<Record<string, unknown>>;
257
- readonly children?: readonly PipelineNode[];
258
- }
259
- interface PipelineConfig {
260
- readonly video: readonly PipelineNode[];
261
- readonly audio?: PipelineNode;
262
- }
263
- interface PipelineStatus {
264
- readonly addon: string;
265
- readonly slot: PipelineSlot;
266
- readonly state: 'initializing' | 'ready' | 'running' | 'error';
267
- readonly error?: string;
268
- readonly lastRunMs?: number;
269
- }
270
- interface StepError {
271
- readonly code: string;
272
- readonly message: string;
273
- readonly childrenSkipped: boolean;
274
- }
275
- interface StepResult {
276
- readonly addon: string;
277
- readonly slot: PipelineSlot;
278
- readonly output: DetectorOutput | CropperOutput | ClassifierOutput;
279
- readonly parentResultId?: string;
280
- readonly resultId: string;
281
- readonly inferenceMs: number;
282
- readonly preprocessMs: number;
283
- readonly totalMs: number;
284
- readonly error?: StepError;
285
- }
286
- interface PipelineResult {
287
- readonly results: readonly StepResult[];
288
- readonly totalMs: number;
289
- readonly timings: Readonly<Record<string, number>>;
290
- readonly frameTimestamp: number;
291
- }
292
-
293
- interface TrackedObjectSummary {
294
- readonly trackId: string;
295
- readonly class: string;
296
- readonly originalClass: string;
297
- readonly state: ObjectState;
298
- readonly bbox: BoundingBox;
299
- readonly velocity: {
300
- readonly dx: number;
301
- readonly dy: number;
302
- };
303
- readonly dwellTimeMs: number;
304
- readonly inZones: readonly string[];
305
- readonly identity?: string;
306
- readonly plateText?: string;
307
- readonly subClass?: string;
308
- }
309
- interface ZoneLiveState {
310
- readonly zoneId: string;
311
- readonly zoneName: string;
312
- readonly occupied: boolean;
313
- readonly objectCount: number;
314
- readonly objectsByClass: Readonly<Record<string, number>>;
315
- readonly trackIds: readonly string[];
316
- readonly avgDwellTimeMs: number;
317
- readonly totalEntrancesToday: number;
318
- readonly totalExitsToday: number;
319
- readonly loiteringTracks: readonly string[];
320
- }
321
- interface CameraLiveState {
322
- readonly deviceId: string;
323
- readonly lastFrameTimestamp: number;
324
- readonly activeObjects: number;
325
- readonly movingObjects: number;
326
- readonly stationaryObjects: number;
327
- readonly objectCounts: Readonly<Record<string, number>>;
328
- readonly tracks: readonly TrackedObjectSummary[];
329
- readonly zones: readonly ZoneLiveState[];
330
- readonly lastEvent?: DetectionEvent;
331
- readonly pipelineStatus: readonly PipelineStatus[];
332
- readonly avgPipelineMs: number;
333
- readonly currentFps: number;
334
- }
335
-
336
- interface TrackFilter {
337
- readonly class?: readonly string[];
338
- readonly state?: readonly ObjectState[];
339
- readonly inZone?: string;
340
- readonly minDwellMs?: number;
341
- }
342
- interface TimeRangeOptions {
343
- readonly from: number;
344
- readonly to: number;
345
- readonly resolution: 'minute' | '5min' | 'hour';
346
- }
347
- interface ZoneHistoryPoint {
348
- readonly timestamp: number;
349
- readonly objectCount: number;
350
- readonly objectsByClass: Readonly<Record<string, number>>;
351
- readonly entrances: number;
352
- readonly exits: number;
353
- }
354
- interface HeatmapOptions {
355
- readonly from: number;
356
- readonly to: number;
357
- readonly class?: string;
358
- readonly resolution: number;
359
- }
360
- interface HeatmapData {
361
- readonly width: number;
362
- readonly height: number;
363
- readonly gridSize: number;
364
- readonly cells: Float32Array;
365
- readonly maxCount: number;
366
- }
367
- interface TrackDetail {
368
- readonly trackId: string;
369
- readonly class: string;
370
- readonly originalClass: string;
371
- readonly state: ObjectState;
372
- readonly firstSeen: number;
373
- readonly lastSeen: number;
374
- readonly totalDwellMs: number;
375
- readonly path: ReadonlyArray<{
376
- readonly timestamp: number;
377
- readonly bbox: BoundingBox;
378
- readonly velocity: {
379
- readonly dx: number;
380
- readonly dy: number;
381
- };
382
- }>;
383
- readonly identity?: {
384
- readonly name: string;
385
- readonly confidence: number;
386
- readonly matchedAt: number;
387
- };
388
- readonly plateText?: {
389
- readonly text: string;
390
- readonly confidence: number;
391
- readonly readAt: number;
392
- };
393
- readonly subClass?: {
394
- readonly class: string;
395
- readonly confidence: number;
396
- };
397
- readonly zoneTransitions: ReadonlyArray<{
398
- readonly zoneId: string;
399
- readonly zoneName: string;
400
- readonly entered: number;
401
- readonly exited?: number;
402
- readonly dwellMs: number;
403
- }>;
404
- readonly bestSnapshot?: EventSnapshot;
405
- readonly events: readonly DetectionEvent[];
406
- }
407
-
408
- type BenchmarkMode = 'single-addon' | 'full-pipeline' | 'compare-runtimes' | 'compare-models';
409
- type BenchmarkSource = {
410
- readonly type: 'reference';
411
- readonly images: 'all' | readonly string[];
412
- } | {
413
- readonly type: 'camera';
414
- readonly deviceId: string;
415
- readonly durationSec: number;
416
- };
417
- type BenchmarkExecution = {
418
- readonly type: 'local';
419
- } | {
420
- readonly type: 'agent';
421
- readonly agentId: string;
422
- } | {
423
- readonly type: 'multi-agent';
424
- readonly agentIds: readonly string[];
425
- } | {
426
- readonly type: 'all-agents';
427
- };
428
- interface BenchmarkTarget {
429
- readonly label: string;
430
- readonly addonId: string;
431
- readonly config: Readonly<Record<string, unknown>>;
432
- }
433
- interface BenchmarkConfig {
434
- readonly mode: BenchmarkMode;
435
- readonly source: BenchmarkSource;
436
- readonly execution: BenchmarkExecution;
437
- readonly iterations?: number;
438
- readonly warmup?: number;
439
- readonly targets: readonly BenchmarkTarget[];
440
- }
441
- interface LatencyStats {
442
- readonly mean: number;
443
- readonly median: number;
444
- readonly p95: number;
445
- readonly p99: number;
446
- readonly min: number;
447
- readonly max: number;
448
- }
449
- interface ResourceStats {
450
- readonly peakMemoryMB: number;
451
- readonly avgCpuPercent: number;
452
- readonly avgGpuPercent?: number;
453
- }
454
- interface AccuracyStats {
455
- readonly mAP50?: number;
456
- readonly precision?: number;
457
- readonly recall?: number;
458
- }
459
- interface SystemInfo {
460
- readonly os: string;
461
- readonly arch: string;
462
- readonly cpuModel: string;
463
- readonly cpuCores: number;
464
- readonly totalMemoryMB: number;
465
- readonly gpuModel?: string;
466
- readonly pythonVersion?: string;
467
- readonly nodeVersion: string;
468
- }
469
- interface BenchmarkTargetResult {
470
- readonly label: string;
471
- readonly addonId: string;
472
- readonly config: Readonly<Record<string, unknown>>;
473
- readonly latency: LatencyStats;
474
- readonly fps: number;
475
- readonly accuracy?: AccuracyStats;
476
- readonly resources: ResourceStats;
477
- readonly stepBreakdown?: Readonly<Record<string, {
478
- readonly meanMs: number;
479
- readonly percentOfTotal: number;
480
- }>>;
481
- }
482
- type AgentBenchmarkStatus = 'completed' | 'partial' | 'failed' | 'disconnected';
483
- interface MultiBenchmarkReport {
484
- readonly timestamp: string;
485
- readonly source: BenchmarkSource;
486
- readonly agents: ReadonlyArray<{
487
- readonly agentId: string;
488
- readonly status: AgentBenchmarkStatus;
489
- readonly systemInfo: SystemInfo;
490
- readonly results: readonly BenchmarkTargetResult[];
491
- readonly error?: string;
492
- readonly completedIterations?: number;
493
- }>;
494
- readonly leaderboard: ReadonlyArray<{
495
- readonly rank: number;
496
- readonly agentId: string;
497
- readonly label: string;
498
- readonly meanMs: number;
499
- readonly fps: number;
500
- readonly peakMemoryMB: number;
501
- readonly accuracy?: AccuracyStats;
502
- }>;
503
- }
504
- interface GroundTruthAnnotation {
505
- readonly class: string;
506
- readonly originalClass?: string;
507
- readonly bbox: BoundingBox;
508
- readonly children?: readonly GroundTruthAnnotation[];
509
- readonly identity?: string;
510
- readonly plateText?: string;
511
- readonly species?: string;
512
- readonly vehicleType?: string;
513
- }
514
- interface GroundTruth {
515
- readonly image: string;
516
- readonly annotations: readonly GroundTruthAnnotation[];
517
- }
518
-
519
- /**
520
- * Configuration UI Schema -- declarative form definition for any element.
521
- *
522
- * Used by addons, providers, and devices to declare their settings UI.
523
- * The admin UI renders these schemas as responsive forms.
524
- */
525
- interface ConfigUISchema {
526
- sections: ConfigSection[];
527
- }
528
- interface ConfigSection {
529
- id: string;
530
- title: string;
531
- description?: string;
532
- style?: 'card' | 'accordion';
533
- defaultCollapsed?: boolean;
534
- columns?: 1 | 2 | 3 | 4;
535
- fields: ConfigField[];
536
- }
537
- type ConfigField = ConfigTextField | ConfigNumberField | ConfigBooleanField | ConfigSelectField | ConfigMultiSelectField | ConfigColorField | ConfigPasswordField | ConfigTextAreaField | ConfigSliderField | ConfigTagsField | ConfigGroupField | ConfigSeparatorField | ConfigInfoField | ConfigModelSelectorField;
538
- interface ConfigFieldBase {
539
- key: string;
540
- label: string;
541
- description?: string;
542
- required?: boolean;
543
- disabled?: boolean;
544
- placeholder?: string;
545
- span?: 1 | 2 | 3 | 4;
546
- showWhen?: ConfigCondition;
547
- }
548
- interface ConfigCondition {
549
- field: string;
550
- equals?: unknown;
551
- notEquals?: unknown;
552
- in?: unknown[];
553
- notIn?: unknown[];
554
- }
555
- interface ConfigTextField extends ConfigFieldBase {
556
- type: 'text';
557
- maxLength?: number;
558
- pattern?: string;
559
- inputType?: 'text' | 'url' | 'email';
560
- }
561
- interface ConfigNumberField extends ConfigFieldBase {
562
- type: 'number';
563
- min?: number;
564
- max?: number;
565
- step?: number;
566
- unit?: string;
567
- }
568
- interface ConfigBooleanField extends ConfigFieldBase {
569
- type: 'boolean';
570
- style?: 'switch' | 'checkbox';
571
- }
572
- interface ConfigSelectField extends ConfigFieldBase {
573
- type: 'select';
574
- options: ConfigOption[];
575
- dependsOn?: Record<string, unknown>;
576
- }
577
- interface ConfigMultiSelectField extends ConfigFieldBase {
578
- type: 'multiselect';
579
- options: ConfigOption[];
580
- maxItems?: number;
581
- }
582
- interface ConfigColorField extends ConfigFieldBase {
583
- type: 'color';
584
- presets?: string[];
585
- }
586
- interface ConfigPasswordField extends ConfigFieldBase {
587
- type: 'password';
588
- showToggle?: boolean;
589
- }
590
- interface ConfigTextAreaField extends ConfigFieldBase {
591
- type: 'textarea';
592
- rows?: number;
593
- maxLength?: number;
594
- }
595
- interface ConfigSliderField extends ConfigFieldBase {
596
- type: 'slider';
597
- min: number;
598
- max: number;
599
- step?: number;
600
- showValue?: boolean;
601
- unit?: string;
602
- default?: number;
603
- }
604
- interface ConfigTagsField extends ConfigFieldBase {
605
- type: 'tags';
606
- suggestions?: string[];
607
- maxTags?: number;
608
- }
609
- interface ConfigGroupField extends ConfigFieldBase {
610
- type: 'group';
611
- fields: ConfigField[];
612
- style?: 'card' | 'inline' | 'accordion';
613
- defaultCollapsed?: boolean;
614
- }
615
- /** Visual separator between fields */
616
- interface ConfigSeparatorField {
617
- type: 'separator';
618
- key: string;
619
- }
620
- /** Read-only informational text */
621
- interface ConfigInfoField {
622
- type: 'info';
623
- key: string;
624
- label: string;
625
- content: string;
626
- variant?: 'info' | 'warning' | 'success' | 'danger';
627
- }
628
- interface ConfigOption {
629
- value: string;
630
- label: string;
631
- description?: string;
632
- icon?: string;
633
- }
634
- interface ConfigModelSelectorField extends ConfigFieldBase {
635
- type: 'model-selector';
636
- /** Filter models by type */
637
- modelType?: string;
638
- /** Allow user to enter a custom local path or URL (default: true) */
639
- allowCustomPath?: boolean;
640
- /** Allow file upload via UI (default: true) */
641
- allowUpload?: boolean;
642
- /** Accepted file extensions for upload (default: ['.onnx']) */
643
- acceptExtensions?: string[];
644
- /** URL to model conversion documentation/guide */
645
- conversionGuideUrl?: string;
646
- /** Brief text explaining what models are compatible */
647
- compatibilityNote?: string;
648
- /** Legacy: inline catalog entries */
649
- catalog?: readonly ModelCatalogEntry[];
650
- allowCustom?: boolean;
651
- acceptFormats?: readonly ModelFormat$1[];
652
- allowConversion?: boolean;
653
- requiredMetadata?: readonly (keyof CustomModelMetadata)[];
654
- outputFormatHint?: ModelOutputFormat;
655
- }
656
- interface IConfigurable {
657
- getConfigSchema(): ConfigUISchema;
658
- getConfig(): Record<string, unknown>;
659
- onConfigChange(config: Record<string, unknown>): Promise<void>;
660
- }
661
-
662
- interface RouteRequest {
663
- readonly params: Readonly<Record<string, string>>;
664
- readonly query: Readonly<Record<string, string | string[]>>;
665
- readonly headers: Readonly<Record<string, string | undefined>>;
666
- readonly body?: unknown;
667
- }
668
- interface RouteResponse {
669
- status(code: number): RouteResponse;
670
- json(data: unknown): void;
671
- send(data: string | Buffer): void;
672
- sendFile(path: string): void;
673
- header(name: string, value: string): RouteResponse;
674
- }
675
- type RouteHandler = (req: RouteRequest, res: RouteResponse) => void | Promise<void>;
676
- type HttpMethod = 'GET' | 'POST' | 'PUT' | 'DELETE' | 'PATCH';
677
- interface IAddonRouter {
678
- /** Public route — no auth required */
679
- public(method: HttpMethod, path: string, handler: RouteHandler): void;
680
- /** Protected route — requires valid JWT or API key */
681
- protected(method: HttpMethod, path: string, handler: RouteHandler): void;
682
- /** Admin route — requires admin role */
683
- admin(method: HttpMethod, path: string, handler: RouteHandler): void;
684
- /** Serve static directory */
685
- static(urlPath: string, directory: string, options?: {
686
- auth?: boolean;
687
- }): void;
688
- /** Get the base URL prefix for this addon's routes */
689
- getBaseUrl(): string;
690
- }
691
-
692
- interface NetworkAddress {
693
- readonly host: string;
694
- readonly port: number;
695
- readonly protocol: 'http' | 'https';
696
- }
697
- interface PublicAddress {
698
- readonly url: string;
699
- readonly provider: string;
700
- }
701
- interface INetworkProvider {
702
- getLocalAddress(): NetworkAddress;
703
- getPublicAddress(): PublicAddress | null;
704
- registerRemoteAccess(provider: IRemoteAccessProvider): void;
705
- unregisterRemoteAccess(providerId: string): void;
706
- onPublicAddressChange(callback: (address: PublicAddress | null) => void): () => void;
707
- }
708
- type RemoteAccessStatus = 'connected' | 'connecting' | 'disconnected' | 'error';
709
- interface IRemoteAccessProvider {
710
- readonly id: string;
711
- readonly name: string;
712
- getPublicUrl(): string | null;
713
- getStatus(): RemoteAccessStatus;
714
- start(): Promise<void>;
715
- stop(): Promise<void>;
716
- onStatusChange?(callback: (status: RemoteAccessStatus) => void): () => void;
717
- }
718
- interface ITurnProvider {
719
- readonly id: string;
720
- readonly name: string;
721
- getCredentials(): Promise<TurnCredentials>;
722
- getServers(): TurnServer[];
723
- }
724
- interface TurnCredentials {
725
- readonly username: string;
726
- readonly credential: string;
727
- readonly ttl: number;
728
- }
729
- interface TurnServer {
730
- readonly urls: string;
731
- readonly username?: string;
732
- readonly credential?: string;
733
- }
734
-
735
- type LogLevel = 'debug' | 'info' | 'warn' | 'error';
736
- interface LogEntry {
737
- timestamp: Date;
738
- level: LogLevel;
739
- scope: string[];
740
- message: string;
741
- meta?: Record<string, unknown>;
742
- }
743
- interface LogFilter {
744
- scope?: string[];
745
- level?: LogLevel;
746
- since?: Date;
747
- until?: Date;
748
- limit?: number;
749
- }
750
- interface ILogDestination {
751
- initialize(): Promise<void>;
752
- shutdown(): Promise<void>;
753
- write(entry: LogEntry): void;
754
- query?(filter: LogFilter): Promise<readonly LogEntry[]>;
755
- }
756
- interface IScopedLogger {
757
- debug(message: string, meta?: Record<string, unknown>): void;
758
- info(message: string, meta?: Record<string, unknown>): void;
759
- warn(message: string, meta?: Record<string, unknown>): void;
760
- error(message: string, meta?: Record<string, unknown>): void;
761
- child(scope: string): IScopedLogger;
762
- }
763
- /** Factory that creates scoped loggers */
764
- type LoggerFactory = {
765
- createLogger(scope: string): IScopedLogger;
766
- };
767
-
768
- interface EventSource {
769
- type: string;
770
- id: string;
771
- }
772
- interface SystemEvent {
773
- id: string;
774
- timestamp: Date;
775
- source: EventSource;
776
- category: string;
777
- data: Record<string, unknown>;
778
- }
779
- interface EventFilter {
780
- source?: EventSource;
781
- category?: string;
782
- since?: Date;
783
- }
784
- interface IEventBus {
785
- emit(event: SystemEvent): void;
786
- subscribe(filter: EventFilter, handler: (event: SystemEvent) => void): () => void;
787
- getRecent(filter?: EventFilter, limit?: number): readonly SystemEvent[];
788
- }
789
-
790
- type StorageLocationName = 'data' | 'media' | 'recordings' | 'models' | 'cache' | 'logs' | 'config' | 'events' | 'addon';
791
- interface StorageConfig {
792
- locations: Record<StorageLocationName, string>;
793
- }
794
- interface QueryFilter {
795
- where?: Record<string, unknown>;
796
- whereIn?: Record<string, unknown[]>;
797
- whereBetween?: Record<string, [unknown, unknown]>;
798
- orderBy?: {
799
- field: string;
800
- direction: 'asc' | 'desc';
801
- };
802
- limit?: number;
803
- offset?: number;
804
- }
805
- interface StorageRecord {
806
- collection: string;
807
- id: string;
808
- data: Record<string, unknown>;
809
- }
810
- interface IStructuredStorage {
811
- query(collection: string, filter?: QueryFilter): Promise<readonly StorageRecord[]>;
812
- insert(record: StorageRecord): Promise<StorageRecord>;
813
- update(collection: string, id: string, data: Record<string, unknown>): Promise<StorageRecord>;
814
- delete(collection: string, id: string): Promise<void>;
815
- count(collection: string, filter?: QueryFilter): Promise<number>;
816
- }
817
- interface IFileStorage {
818
- readFile(path: string): Promise<Buffer>;
819
- writeFile(path: string, data: Buffer): Promise<void>;
820
- deleteFile(path: string): Promise<void>;
821
- listFiles(prefix?: string): Promise<readonly string[]>;
822
- getFileUrl(path: string): Promise<string>;
823
- exists(path: string): Promise<boolean>;
824
- }
825
- interface IStorageLocation {
826
- structured?: IStructuredStorage;
827
- files?: IFileStorage;
828
- }
829
- interface IStorageProvider {
830
- initialize(): Promise<void>;
831
- shutdown(): Promise<void>;
832
- getLocation(name: StorageLocationName): IStorageLocation;
833
- export(locationName: StorageLocationName): Promise<Buffer>;
834
- import(locationName: StorageLocationName, data: Buffer): Promise<void>;
835
- }
836
-
837
- interface ICameraAnalyticsProvider {
838
- getLiveState(deviceId: string): CameraLiveState | null;
839
- getTracks(deviceId: string, filter?: TrackFilter): TrackedObjectSummary[];
840
- getZoneState(deviceId: string, zoneId: string): ZoneLiveState | null;
841
- getZoneHistory(deviceId: string, zoneId: string, options: TimeRangeOptions): Promise<ZoneHistoryPoint[]>;
842
- getHeatmap(deviceId: string, options: HeatmapOptions): Promise<HeatmapData>;
843
- getTrackDetail(deviceId: string, trackId: string): TrackDetail | null;
844
- getCameraStatus(deviceId: string): PipelineStatus[];
845
- }
846
- interface IAnalysisAddon extends ICamstackAddon, ICameraAnalyticsProvider {
847
- processFrame(deviceId: string, frame: FrameInput): Promise<DetectionEvent[]>;
848
- setCameraPipeline(deviceId: string, config: PipelineConfig): void;
849
- setCameraZones(deviceId: string, zones: ZoneDefinition[]): void;
850
- setKnownFaces(faces: KnownFace[]): void;
851
- setKnownPlates(plates: KnownPlate[]): void;
852
- onLiveStateChange(deviceId: string, callback: (state: CameraLiveState) => void): () => void;
853
- }
854
-
855
- /**
856
- * Result returned by an auth provider after successful authentication.
857
- */
858
- interface AuthResult {
859
- readonly externalId: string;
860
- readonly username: string;
861
- readonly email?: string;
862
- readonly displayName?: string;
863
- readonly avatarUrl?: string;
864
- readonly groups?: string[];
865
- readonly rawProfile?: unknown;
866
- }
867
- /**
868
- * Pluggable authentication provider.
869
- * Each addon can register one or more auth providers (collection capability).
870
- */
871
- interface IAuthProvider {
872
- readonly id: string;
873
- readonly name: string;
874
- readonly icon: string;
875
- /** Type of auth flow */
876
- readonly flowType: 'credentials' | 'redirect' | 'token';
877
- /**
878
- * For 'credentials' flow: validate username/password, return user info.
879
- */
880
- validateCredentials?(username: string, password: string): Promise<AuthResult | null>;
881
- /**
882
- * For 'redirect' flow (OIDC, OAuth2):
883
- * getLoginUrl() returns the URL to redirect the user to.
884
- * handleCallback() processes the callback and returns user info.
885
- */
886
- getLoginUrl?(state: string): string;
887
- handleCallback?(params: Record<string, string>): Promise<AuthResult>;
888
- /**
889
- * For 'token' flow: validate an external token (e.g., from mobile app).
890
- */
891
- validateToken?(token: string): Promise<AuthResult | null>;
892
- }
893
-
894
- /**
895
- * A notification to be sent through configured output channels.
896
- */
897
- interface Notification {
898
- readonly title: string;
899
- readonly message: string;
900
- readonly severity: 'info' | 'warning' | 'critical';
901
- readonly category: string;
902
- readonly data?: Record<string, unknown>;
903
- readonly imageUrl?: string;
904
- readonly deviceId?: string;
905
- readonly timestamp: number;
906
- }
907
- /**
908
- * A toast notification for the admin UI.
909
- */
910
- interface Toast {
911
- readonly title: string;
912
- readonly message: string;
913
- readonly severity: 'info' | 'warning' | 'critical';
914
- readonly duration?: number;
915
- readonly action?: {
916
- readonly label: string;
917
- readonly url: string;
918
- };
919
- }
920
- /**
921
- * Service interface for broadcasting toast notifications to connected clients.
922
- */
923
- interface IToastService {
924
- broadcast(toast: Toast): void;
925
- sendToUser(userId: string, toast: Toast): void;
926
- }
927
- /**
928
- * Pluggable notification output channel.
929
- * Each addon implements a notification channel (Telegram, webhook, email, etc.).
930
- */
931
- interface INotificationOutput {
932
- readonly id: string;
933
- readonly name: string;
934
- readonly icon: string;
935
- /** Send a notification */
936
- send(notification: Notification): Promise<void>;
937
- /** Test the notification channel */
938
- sendTest?(): Promise<{
939
- success: boolean;
940
- error?: string;
941
- }>;
942
- /** Config schema for the admin UI */
943
- getConfigSchema?(): ConfigUISchema;
944
- }
945
-
946
- /**
947
- * Scope restriction for a scoped token.
948
- */
949
- interface TokenScope {
950
- readonly type: 'addon' | 'route-prefix' | 'capability';
951
- readonly target: string;
952
- }
953
- /**
954
- * A per-user API token with restricted scopes.
955
- */
956
- interface ScopedToken {
957
- readonly id: string;
958
- readonly userId: string;
959
- readonly name: string;
960
- readonly tokenHash: string;
961
- readonly tokenPrefix: string;
962
- readonly scopes: TokenScope[];
963
- readonly expiresAt?: number;
964
- readonly lastUsedAt?: number;
965
- readonly createdAt: number;
966
- }
967
-
968
- type RouteAccess = 'public' | 'authenticated' | 'admin';
969
- /**
970
- * Request object passed to addon route handlers.
971
- */
972
- interface AddonHttpRequest {
973
- readonly params: Record<string, string>;
974
- readonly query: Record<string, string>;
975
- readonly body: unknown;
976
- readonly headers: Record<string, string>;
977
- /** Populated for 'authenticated' and 'admin' routes */
978
- readonly user?: {
979
- readonly id: string;
980
- readonly username: string;
981
- readonly role: string;
982
- };
983
- /** Populated when request uses a scoped token */
984
- readonly scopedToken?: {
985
- readonly id: string;
986
- readonly userId: string;
987
- readonly scopes: TokenScope[];
988
- };
989
- }
990
- /**
991
- * Reply object for addon route handlers.
992
- */
993
- interface AddonHttpReply {
994
- status(code: number): AddonHttpReply;
995
- send(data: unknown): void;
996
- redirect(url: string): void;
997
- header(name: string, value: string): AddonHttpReply;
998
- }
999
- /**
1000
- * A single HTTP route registered by an addon.
1001
- */
1002
- interface IAddonHttpRoute {
1003
- readonly method: 'GET' | 'POST' | 'PUT' | 'DELETE';
1004
- readonly path: string;
1005
- readonly access: RouteAccess;
1006
- readonly description?: string;
1007
- readonly handler: (request: AddonHttpRequest, reply: AddonHttpReply) => Promise<void>;
1008
- }
1009
- /**
1010
- * Provider interface for addons that expose HTTP endpoints.
1011
- */
1012
- interface IAddonRouteProvider {
1013
- readonly id: string;
1014
- getRoutes(): IAddonHttpRoute[];
1015
- }
1016
-
1017
- /**
1018
- * Camera Analysis Pipeline -- unified stream processing.
1019
- */
1020
- interface IStreamSourceAdapter {
1021
- protocol: string;
1022
- connect(config: Record<string, unknown>): Promise<NormalizedSource>;
1023
- disconnect(): Promise<void>;
1024
- getStatus(): SourceAdapterStatus;
1025
- }
1026
- interface NormalizedSource {
1027
- type: 'url' | 'pipe';
1028
- url?: string;
1029
- pipe?: NodeJS.ReadableStream;
1030
- capabilities: SourceCapabilities;
1031
- }
1032
- interface SourceCapabilities {
1033
- hasVideo: boolean;
1034
- hasAudio: boolean;
1035
- videoCodec?: 'h264' | 'h265' | 'mjpeg' | 'vp8' | 'vp9' | 'av1';
1036
- audioCodec?: 'aac' | 'opus' | 'pcm' | 'g711';
1037
- width?: number;
1038
- height?: number;
1039
- fps?: number;
1040
- sampleRate?: number;
1041
- audioChannels?: number;
1042
- }
1043
- interface SourceAdapterStatus {
1044
- connected: boolean;
1045
- protocol: string;
1046
- error?: string;
1047
- bytesReceived?: number;
1048
- connectedSince?: number;
1049
- }
1050
- interface VideoFrame {
1051
- data: Buffer;
1052
- format: 'jpeg' | 'raw-yuv420' | 'raw-rgb' | 'h264-nal';
1053
- width: number;
1054
- height: number;
1055
- pts: number;
1056
- timestamp: number;
1057
- keyframe?: boolean;
1058
- }
1059
- interface AudioChunk {
1060
- data: Buffer;
1061
- format: 'pcm-s16le' | 'pcm-f32le' | 'aac' | 'opus';
1062
- sampleRate: number;
1063
- channels: number;
1064
- pts: number;
1065
- timestamp: number;
1066
- dBFS?: number;
1067
- }
1068
- interface ICameraPipeline {
1069
- readonly deviceId: string;
1070
- readonly active: boolean;
1071
- start(): Promise<void>;
1072
- stop(): Promise<void>;
1073
- onVideoFrame(callback: VideoFrameCallback, options?: FrameSubscriptionOptions): () => void;
1074
- getLatestFrame(): VideoFrame | null;
1075
- onAudioChunk(callback: AudioChunkCallback): () => void;
1076
- getAudioLevel(): number;
1077
- getOutputStream(format: PipelineOutputFormat): PipelineOutputStream | null;
1078
- getAvailableOutputs(): PipelineOutputFormat[];
1079
- getStatus(): PipelineStatusInfo;
1080
- }
1081
- type VideoFrameCallback = (frame: VideoFrame) => void;
1082
- type AudioChunkCallback = (chunk: AudioChunk) => void;
1083
- interface FrameSubscriptionOptions {
1084
- maxFps?: number;
1085
- format?: 'jpeg' | 'raw-yuv420' | 'raw-rgb';
1086
- maxWidth?: number;
1087
- maxHeight?: number;
1088
- keyframeOnly?: boolean;
1089
- }
1090
- type PipelineOutputFormat = 'webrtc' | 'hls' | 'mjpeg' | 'rtsp' | 'raw-h264';
1091
- interface PipelineOutputStream {
1092
- format: PipelineOutputFormat;
1093
- url?: string;
1094
- createOffer?(): Promise<string>;
1095
- handleAnswer?(sdp: string): Promise<void>;
1096
- pipe?: NodeJS.ReadableStream;
1097
- consumerCount: number;
1098
- }
1099
- interface PipelineStatusInfo {
1100
- active: boolean;
1101
- source: {
1102
- protocol: string;
1103
- connected: boolean;
1104
- capabilities: SourceCapabilities;
1105
- } | null;
1106
- decode: {
1107
- fps: number;
1108
- droppedFrames: number;
1109
- totalFrames: number;
1110
- };
1111
- videoConsumers: number;
1112
- audioConsumers: number;
1113
- outputs: Array<{
1114
- format: PipelineOutputFormat;
1115
- consumers: number;
1116
- active: boolean;
1117
- }>;
1118
- uptime: number;
1119
- }
1120
- interface IPipelineManager {
1121
- getPipeline(deviceId: string): ICameraPipeline | null;
1122
- createPipeline(deviceId: string, source: NormalizedSource): ICameraPipeline;
1123
- destroyPipeline(deviceId: string): Promise<void>;
1124
- listPipelines(): Array<{
1125
- deviceId: string;
1126
- status: PipelineStatusInfo;
1127
- }>;
1128
- }
1129
- interface IPipelineConsumer {
1130
- id: string;
1131
- name: string;
1132
- videoRequirements?: FrameSubscriptionOptions;
1133
- needsAudio: boolean;
1134
- attachToPipeline(pipeline: ICameraPipeline, deviceId: string): void;
1135
- detachFromPipeline(deviceId: string): void;
1136
- }
1137
-
1138
- interface IDeviceCapability {
1139
- kind: DeviceCapabilityName;
1140
- }
1141
- type DeviceCapabilityName = 'camera' | 'panTiltZoom' | 'motionSensor' | 'objectDetector' | 'audioDetector' | 'twoWayAudio' | 'doorbell' | 'events' | 'recording' | 'accessory' | 'statusLight' | 'siren' | 'switch';
1142
- interface CapabilityBinding {
1143
- source: 'native' | 'addon' | 'disabled';
1144
- addonId?: string;
1145
- config?: Record<string, unknown>;
1146
- }
1147
- interface DeviceCapabilityBinding {
1148
- deviceId: string;
1149
- bindings: Partial<Record<DeviceCapabilityName, CapabilityBinding>>;
1150
- }
1151
-
1152
- /** A single detection result from a frame */
1153
- interface Detection {
1154
- className: string;
1155
- score: number;
1156
- boundingBox?: [number, number, number, number];
1157
- id?: string;
1158
- label?: string;
1159
- labelScore?: number;
1160
- zones?: string[];
1161
- previousZones?: string[];
1162
- }
1163
- /** Payload emitted by onDetections -- a full frame of detections */
1164
- interface DetectionFrame {
1165
- detections: Detection[];
1166
- frameWidth: number;
1167
- frameHeight: number;
1168
- timestamp: number;
1169
- }
1170
- /** An actively tracked object in the scene */
1171
- interface ActiveDetection extends Detection {
1172
- state: 'moving' | 'stationary';
1173
- durationMs: number;
1174
- velocity?: {
1175
- dx: number;
1176
- dy: number;
1177
- };
1178
- }
1179
- /** A closed polygon zone on the camera scene */
1180
- interface DetectionZone {
1181
- id: string;
1182
- name: string;
1183
- polygon: Array<[number, number]>;
1184
- mode: 'observe' | 'restrict';
1185
- }
1186
- /** A line on the scene for crossing rules */
1187
- interface DetectionLine {
1188
- id: string;
1189
- name: string;
1190
- points: [[number, number], [number, number]];
1191
- direction: 'left-to-right' | 'right-to-left' | 'both';
1192
- }
1193
- interface IObjectDetector extends IDeviceCapability {
1194
- kind: 'objectDetector';
1195
- getLabels(): string[];
1196
- onDetections(callback: (frame: DetectionFrame) => void): () => void;
1197
- getZones(): Promise<DetectionZone[]>;
1198
- addZone(zone: DetectionZone): Promise<void>;
1199
- removeZone(zoneId: string): Promise<void>;
1200
- updateZone(zoneId: string, zone: Partial<Omit<DetectionZone, 'id'>>): Promise<void>;
1201
- getLines(): Promise<DetectionLine[]>;
1202
- addLine(line: DetectionLine): Promise<void>;
1203
- removeLine(lineId: string): Promise<void>;
1204
- getActiveDetections(): ActiveDetection[];
1205
- getZoneDetections(zoneId: string): ActiveDetection[];
1206
- getStationaryDetections(): ActiveDetection[];
1207
- getMovingDetections(): ActiveDetection[];
1208
- }
1209
-
1210
- /**
1211
- * Detection Analysis Pipeline -- processes raw detections through
1212
- * configurable stages to produce tracked, enriched, actionable events.
1213
- */
1214
-
1215
- declare const DETECTION_TYPES: readonly ["person", "vehicle", "animal", "package"];
1216
- type DetectionType = typeof DETECTION_TYPES[number];
1217
- declare const SUB_DETECTION_TYPES: readonly ["face", "plate"];
1218
- type SubDetectionType = typeof SUB_DETECTION_TYPES[number];
1219
- declare const RECOGNITION_TYPES: readonly ["face", "plate", "clip", "custom"];
1220
- type RecognitionType = typeof RECOGNITION_TYPES[number];
1221
- interface AnalysisContext {
1222
- readonly deviceId: string;
1223
- readonly frame: VideoFrame;
1224
- readonly timestamp: number;
1225
- readonly rawDetections: readonly Detection[];
1226
- readonly trackedDetections: readonly ServerTrackedDetection[];
1227
- readonly events: readonly AnalysisEvent[];
1228
- readonly metadata: Readonly<Record<string, unknown>>;
1229
- }
1230
- interface ServerTrackedDetection {
1231
- readonly trackId: string;
1232
- readonly detection: Detection;
1233
- readonly crop?: Buffer;
1234
- readonly tracking: TrackingInfo;
1235
- readonly subDetections: readonly SubDetection[];
1236
- readonly recognitions: readonly RecognitionResult[];
1237
- readonly zones: readonly string[];
1238
- readonly previousZones: readonly string[];
1239
- }
1240
- interface TrackingInfo {
1241
- readonly age: number;
1242
- readonly state: 'moving' | 'stationary' | 'new' | 'lost';
1243
- readonly stationaryDuration: number;
1244
- readonly velocity: {
1245
- readonly dx: number;
1246
- readonly dy: number;
1247
- };
1248
- readonly positionHistory: ReadonlyArray<{
1249
- readonly x: number;
1250
- readonly y: number;
1251
- readonly t: number;
1252
- }>;
1253
- }
1254
- interface SubDetection {
1255
- readonly detectionType: SubDetectionType;
1256
- readonly boundingBox: readonly [number, number, number, number];
1257
- readonly score: number;
1258
- readonly crop?: Buffer;
1259
- }
1260
- interface RecognitionResult {
1261
- readonly recognitionType: RecognitionType;
1262
- readonly label: string;
1263
- readonly score: number;
1264
- readonly embedding?: readonly number[];
1265
- readonly metadata?: Readonly<Record<string, unknown>>;
1266
- }
1267
- interface AnalysisEvent {
1268
- readonly category: string;
1269
- readonly severity: 'info' | 'warning' | 'alert';
1270
- readonly detection: ServerTrackedDetection;
1271
- readonly description: string;
1272
- readonly data: Readonly<Record<string, unknown>>;
1273
- }
1274
- interface IAnalysisStage {
1275
- readonly id: string;
1276
- readonly name: string;
1277
- readonly priority: number;
1278
- enabled: boolean;
1279
- process(ctx: AnalysisContext): Promise<AnalysisContext>;
1280
- }
1281
- interface ISubDetector {
1282
- readonly detectionType: SubDetectionType;
1283
- readonly targetClasses: readonly string[];
1284
- detect(crop: Buffer, cropWidth: number, cropHeight: number): Promise<SubDetection[]>;
1285
- }
1286
- interface IFaceDetector extends ISubDetector {
1287
- readonly detectionType: 'face';
1288
- }
1289
- interface IPlateDetector extends ISubDetector {
1290
- readonly detectionType: 'plate';
1291
- }
1292
- interface IRecognizer {
1293
- readonly recognitionType: RecognitionType;
1294
- recognize(crop: Buffer, width: number, height: number): Promise<RecognitionResult | null>;
1295
- }
1296
- interface IFaceRecognizer extends IRecognizer {
1297
- getEmbedding(crop: Buffer): Promise<Float32Array>;
1298
- registerKnown(label: string, embedding: Float32Array): void;
1299
- }
1300
- interface IPlateRecognizer extends IRecognizer {
1301
- readonly recognitionType: 'plate';
1302
- }
1303
- interface IAudioClassifier {
1304
- readonly ready: boolean;
1305
- initialize(): Promise<void>;
1306
- classify(audioSamples: Float32Array, sampleRate: number, topN?: number): Promise<readonly AudioClassification[]>;
1307
- release(): Promise<void>;
1308
- }
1309
- interface AudioClassification {
1310
- readonly classIndex: number;
1311
- readonly className: string;
1312
- readonly score: number;
1313
- readonly isSurveillanceRelevant: boolean;
1314
- }
1315
- interface IClassFilterStage extends IAnalysisStage {
1316
- readonly id: 'class-filter';
1317
- setConfig(deviceId: string, config: Record<string, unknown>): void;
1318
- getConfig(deviceId: string): Record<string, unknown>;
1319
- }
1320
- interface ITrackerStage extends IAnalysisStage {
1321
- readonly id: 'tracker';
1322
- setConfig(deviceId: string, config: Record<string, unknown>): void;
1323
- getConfig(deviceId: string): Record<string, unknown>;
1324
- resetDevice(deviceId: string): void;
1325
- }
1326
- interface ISubDetectionStage extends IAnalysisStage {
1327
- readonly id: 'sub-detection';
1328
- registerDetector(detector: ISubDetector): void;
1329
- }
1330
- interface IRecognitionStage extends IAnalysisStage {
1331
- readonly id: 'recognition';
1332
- registerRecognizer(recognizer: IRecognizer): void;
1333
- }
1334
- interface IZoneAnalysisStage extends IAnalysisStage {
1335
- readonly id: 'zone-analysis';
1336
- setConfig(deviceId: string, config: Record<string, unknown>): void;
1337
- }
1338
- interface IEventGenerationStage extends IAnalysisStage {
1339
- readonly id: 'event-generation';
1340
- setConfig(deviceId: string, config: Record<string, unknown>): void;
1341
- }
1342
- interface IObjectSnapshotStage extends IAnalysisStage {
1343
- readonly id: 'object-snapshot';
1344
- setConfig(deviceId: string, config: Record<string, unknown>): void;
1345
- }
1346
- interface IAnalysisPipeline {
1347
- addStage(stage: IAnalysisStage): void;
1348
- removeStage(stageId: string): void;
1349
- getStages(): readonly IAnalysisStage[];
1350
- analyze(deviceId: string, frame: VideoFrame, rawDetections: Detection[]): Promise<AnalysisContext>;
1351
- }
1352
- declare function createAnalysisContext(deviceId: string, frame: VideoFrame, rawDetections: Detection[]): AnalysisContext;
1353
- declare function enrichContext(ctx: AnalysisContext, updates: Partial<Pick<AnalysisContext, 'trackedDetections' | 'events' | 'metadata'>>): AnalysisContext;
1354
-
1355
- interface ObjectSnapshotResult {
1356
- readonly trackId: string;
1357
- readonly thumbnail?: Buffer;
1358
- readonly fullCrop?: Buffer;
1359
- }
1360
- interface AnnotatedSnapshotResult {
1361
- readonly thumbnail: Buffer;
1362
- readonly full: Buffer;
1363
- }
1364
- interface PersistableEvent {
1365
- readonly id: string;
1366
- readonly timestamp: number;
1367
- readonly deviceId: string;
1368
- readonly category: string;
1369
- readonly className: string;
1370
- readonly score: number;
1371
- readonly trackId: string;
1372
- readonly severity: string;
1373
- readonly description: string;
1374
- readonly data: Record<string, unknown>;
1375
- readonly mediaFiles: readonly string[];
1376
- }
1377
- interface EventBufferStatus {
1378
- readonly eventCount: number;
1379
- readonly mediaCount: number;
1380
- readonly mediaSizeMB: number;
1381
- }
1382
- type TrackMediaType = 'crop-thumb' | 'crop-full' | 'debug-annotated-thumb' | 'debug-annotated-full' | 'original' | 'original-thumb' | 'inline-crop' | 'unknown';
1383
- interface TrackMediaFile {
1384
- readonly path: string;
1385
- readonly type: TrackMediaType;
1386
- readonly data: Buffer;
1387
- readonly source: 'buffer' | 'storage';
1388
- }
1389
- interface TrackCaptureConfig {
1390
- readonly enabled: boolean;
1391
- readonly snapshotIntervalMs: number;
1392
- readonly maxTrailLength: number;
1393
- readonly saveThumbnails: boolean;
1394
- readonly thumbnailSize: {
1395
- readonly width: number;
1396
- readonly height: number;
1397
- };
1398
- }
1399
- interface TrackPosition {
1400
- readonly x: number;
1401
- readonly y: number;
1402
- readonly timestamp: number;
1403
- readonly bbox: readonly [number, number, number, number];
1404
- }
1405
- interface TrackSnapshot {
1406
- readonly timestamp: number;
1407
- readonly position: TrackPosition;
1408
- readonly thumbnailPath: string;
1409
- }
1410
- interface TrackTrail {
1411
- readonly trackId: string;
1412
- readonly deviceId: string;
1413
- readonly className: string;
1414
- readonly label?: string;
1415
- readonly firstSeen: number;
1416
- readonly lastSeen: number;
1417
- readonly positions: readonly TrackPosition[];
1418
- readonly snapshots: readonly TrackSnapshot[];
1419
- readonly totalDistance: number;
1420
- readonly zonesVisited: readonly string[];
1421
- readonly active: boolean;
1422
- }
1423
- interface RetentionConfig {
1424
- readonly cleanupIntervalMs: number;
1425
- readonly detectionEventsDays: number;
1426
- readonly audioLevelsDays: number;
1427
- /** @deprecated — snapshots are tied to events, use detectionEventsDays */
1428
- readonly snapshotsDays: number;
1429
- readonly deviceOverrides?: Readonly<Record<string, Partial<Pick<RetentionConfig, 'detectionEventsDays' | 'audioLevelsDays' | 'snapshotsDays'>>>>;
1430
- }
1431
- declare const DEFAULT_RETENTION: RetentionConfig;
1432
- interface RetentionReport {
1433
- readonly deletedEvents: number;
1434
- readonly deletedAudioRecords: number;
1435
- readonly deletedSnapshots: number;
1436
- }
1437
- interface SessionTrack {
1438
- readonly trackId: string;
1439
- readonly deviceId: string;
1440
- readonly className: string;
1441
- readonly label?: string;
1442
- readonly firstSeen: number;
1443
- readonly lastSeen: number;
1444
- readonly totalFrames: number;
1445
- readonly lastDetection: ServerTrackedDetection;
1446
- readonly state: string;
1447
- readonly positions: ReadonlyArray<{
1448
- readonly x: number;
1449
- readonly y: number;
1450
- readonly t: number;
1451
- }>;
1452
- readonly embedding?: Float32Array;
1453
- readonly globalId?: string;
1454
- readonly bestCrop?: Buffer;
1455
- }
1456
- interface GlobalIdentity {
1457
- readonly globalId: string;
1458
- readonly embedding: Float32Array;
1459
- readonly label?: string;
1460
- readonly firstSeen: number;
1461
- readonly lastSeen: number;
1462
- readonly deviceIds: ReadonlyArray<string>;
1463
- }
1464
- interface ClipRecognizer {
1465
- getEmbedding(imageBuffer: Buffer): Promise<Float32Array>;
1466
- }
1467
- interface KnownFaceEntry {
1468
- readonly id: string;
1469
- readonly label: string;
1470
- readonly group?: string;
1471
- readonly embedding: readonly number[];
1472
- readonly cropBase64: string;
1473
- readonly createdAt: number;
1474
- readonly updatedAt: number;
1475
- readonly source?: string;
1476
- readonly metadata?: Readonly<Record<string, unknown>>;
1477
- }
1478
- /**
1479
- * Interface for the recording addon — the server uses this instead of
1480
- * importing PipelineAddon directly from addon-pipeline.
1481
- */
1482
- interface IRecordingAddon {
1483
- getCoordinator(): IRecordingCoordinator;
1484
- getRecordingDb(): IRecordingDb;
1485
- }
1486
- /**
1487
- * Minimal coordinator interface for the server's recording router.
1488
- */
1489
- interface IRecordingCoordinator {
1490
- enableRecording(deviceId: string, options: {
1491
- policy: unknown;
1492
- ffmpegOverrides?: unknown;
1493
- }): Promise<void>;
1494
- disableRecording(deviceId: string): Promise<void>;
1495
- isRecording(deviceId: string): boolean;
1496
- readonly playlistGenerator: {
1497
- generate(deviceId: string, streamId: string, startTime: number, endTime: number, options?: {
1498
- live?: boolean;
1499
- }): unknown;
1500
- };
1501
- readonly storageEstimator: {
1502
- estimateForDevice(deviceId: string, motionInput?: {
1503
- avgEventsPerDay: number;
1504
- avgDurationSec: number;
1505
- }): {
1506
- totalEstimatedGb: number;
1507
- [key: string]: unknown;
1508
- };
1509
- };
1510
- }
1511
- /**
1512
- * Minimal recording database interface for the server's recording router.
1513
- */
1514
- interface IRecordingDb {
1515
- upsertStorageConfig(config: {
1516
- deviceId: string;
1517
- dataCategory: string;
1518
- storageName: string;
1519
- subDirectory: string;
1520
- retentionDays: number | null;
1521
- retentionGb: number | null;
1522
- }): void;
1523
- getPolicy(deviceId: string): unknown;
1524
- getEnabledPolicies(): Array<{
1525
- deviceId: string;
1526
- [key: string]: unknown;
1527
- }>;
1528
- querySegments(deviceId: string, streamId: string, startTime: number, endTime: number): unknown;
1529
- getAvailability(deviceId: string, startTime: number, endTime: number): unknown;
1530
- getStorageUsage(deviceId: string, streamId: string): unknown;
1531
- upsertPolicy(policy: unknown): void;
1532
- findNearestThumbnail(deviceId: string, timestamp: number, category: string): unknown;
1533
- getMotionStats(deviceId: string, startTime: number, endTime: number): {
1534
- avgEventsPerDay: number;
1535
- avgDurationSec: number;
1536
- dutyCyclePercent: number;
1537
- totalEvents: number;
1538
- };
1539
- resolveStorageConfig(deviceId: string, dataCategory: string): unknown;
1540
- }
1541
- interface IEventPersistence {
1542
- start(): void;
1543
- stop(): void;
1544
- saveDetectionCrops(eventId: string, crops: readonly ObjectSnapshotResult[]): void;
1545
- saveAnnotatedFrame(eventId: string, result: AnnotatedSnapshotResult): void;
1546
- saveOriginalFrame(eventId: string, frame: VideoFrame): Promise<void>;
1547
- getEventMedia(eventId: string): Promise<unknown>;
1548
- getTrackMedia(trackId: string): Promise<unknown>;
1549
- getDeviceMedia(deviceId: string, since?: number, until?: number): Promise<unknown>;
1550
- getBufferStatus(): unknown;
1551
- flush(): Promise<void>;
1552
- }
1553
- interface ITrackTrail {
1554
- setConfig(deviceId: string, config: Partial<TrackCaptureConfig>): void;
1555
- getConfig(deviceId: string): unknown;
1556
- recordFrame(ctx: unknown): Promise<void>;
1557
- getActiveTrail(trackId: string): unknown;
1558
- getActiveTrails(deviceId: string): unknown;
1559
- getPersistedTrail(trackId: string): Promise<unknown>;
1560
- getTrail(trackId: string): Promise<unknown>;
1561
- listTrails(deviceId: string, options?: {
1562
- since?: number;
1563
- until?: number;
1564
- limit?: number;
1565
- className?: string;
1566
- }): Promise<unknown>;
1567
- }
1568
- interface IRetention {
1569
- start(): void;
1570
- stop(): void;
1571
- runCleanup(): Promise<unknown>;
1572
- setConfig(update: Partial<RetentionConfig>): void;
1573
- getConfig(): unknown;
1574
- forceCleanup(): Promise<unknown>;
1575
- }
1576
- interface ISessionTracker {
1577
- updateFromAnalysis(deviceId: string, ctx: unknown): void;
1578
- getActiveTracks(deviceId: string): unknown;
1579
- getAllActiveTracks(): unknown;
1580
- getTrack(deviceId: string, trackId: string): unknown;
1581
- getTrackCounts(): unknown;
1582
- clearDevice(deviceId: string): void;
1583
- clearAll(): void;
1584
- getGlobalPool(): unknown;
1585
- }
1586
- interface IKnownFaces {
1587
- register(entry: KnownFaceEntry): Promise<void>;
1588
- listAll(): Promise<unknown>;
1589
- delete(id: string): Promise<void>;
1590
- update(id: string, updates: Partial<Pick<KnownFaceEntry, 'label' | 'group'>>): Promise<void>;
1591
- recalculateEmbedding(id: string, clipRecognizer: ClipRecognizer): Promise<void>;
1592
- findMatch(embedding: Float32Array, threshold: number): Promise<unknown>;
1593
- batchRegister(entries: ReadonlyArray<{
1594
- readonly label: string;
1595
- readonly cropBase64: string;
1596
- readonly group?: string;
1597
- }>, clipRecognizer: ClipRecognizer): Promise<unknown>;
1598
- }
1599
- /**
1600
- * Composite interface exposed via CapabilityRegistry as the
1601
- * 'analysis-data-persistence' singleton. Each sub-service is wired
1602
- * individually to the corresponding NestJS wrapper service.
1603
- */
1604
- interface IAnalysisDataPersistence {
1605
- readonly eventPersistence: IEventPersistence;
1606
- readonly knownFaces: IKnownFaces;
1607
- readonly sessionTracker: ISessionTracker;
1608
- readonly retention: IRetention;
1609
- readonly trackTrail: ITrackTrail;
1610
- }
1611
- interface TestConnectionResult {
1612
- readonly success: boolean;
1613
- readonly version?: string;
1614
- readonly cameraCount?: number;
1615
- readonly error?: string;
1616
- }
1617
- /**
1618
- * Generic interface for testing provider connections.
1619
- * Each provider addon can expose a connection tester.
1620
- */
1621
- interface IProviderConnectionTester {
1622
- testConnection(): Promise<TestConnectionResult>;
1623
- }
1624
-
1625
- /**
1626
- * Whether a capability allows one active provider (singleton) or many (collection).
1627
- */
1628
- type CapabilityMode = 'singleton' | 'collection';
1629
- /**
1630
- * Declared in addon package.json manifests under camstack.addons[].capabilities.
1631
- */
1632
- interface CapabilityDeclaration {
1633
- /** Capability name (e.g. 'storage', 'decoder', 'analysis-pipeline') */
1634
- readonly name: string;
1635
- /** singleton: one active at a time. collection: all active in parallel. */
1636
- readonly mode: CapabilityMode;
1637
- /** Optional dependencies — addon won't initialize until these capabilities are available */
1638
- readonly dependsOn?: readonly string[];
1639
- }
1640
- /**
1641
- * Registration object for a service that consumes a capability.
1642
- * The registry calls the appropriate callback when providers are added/removed/replaced.
1643
- */
1644
- interface CapabilityConsumerRegistration<T = unknown> {
1645
- /** Which capability this consumer needs */
1646
- readonly capability: string;
1647
- /** Called when a singleton provider is set or replaced. Async for teardown of previous. */
1648
- onSet?(provider: T): void | Promise<void>;
1649
- /** Called when a collection provider is added */
1650
- onAdded?(provider: T): void | Promise<void>;
1651
- /** Called when a collection provider is removed (addon disabled) */
1652
- onRemoved?(provider: T): void | Promise<void>;
1653
- }
1654
- /**
1655
- * Introspection data for a registered capability.
1656
- */
1657
- interface CapabilityInfo {
1658
- readonly name: string;
1659
- readonly mode: CapabilityMode;
1660
- /** All addon IDs that provide this capability */
1661
- readonly providers: readonly string[];
1662
- /** For singleton: the active addon ID (null if none) */
1663
- readonly activeProvider: string | null;
1664
- }
1665
- /**
1666
- * Maps capability names to their provider interfaces.
1667
- * Extensible via TypeScript declaration merging:
1668
- *
1669
- * ```typescript
1670
- * declare module '@camstack/types' {
1671
- * interface CapabilityProviderMap {
1672
- * 'my-custom-capability': IMyProvider
1673
- * }
1674
- * }
1675
- * ```
1676
- */
1677
- interface CapabilityProviderMap {
1678
- 'storage': IStorageProvider;
1679
- 'log-destination': ILogDestination;
1680
- 'analysis-pipeline': IAnalysisAddon;
1681
- 'restreamer': unknown;
1682
- 'webrtc': unknown;
1683
- 'stream-broker': unknown;
1684
- 'addon-pages': IAddonPageProvider;
1685
- 'admin-ui': IAdminUI;
1686
- 'auth-provider': IAuthProvider;
1687
- 'notification-output': INotificationOutput;
1688
- 'addon-routes': IAddonRouteProvider;
1689
- 'recording-engine': unknown;
1690
- 'analysis-data-persistence': IAnalysisDataPersistence;
1691
- 'device-provider': unknown;
1692
- 'network-access': unknown;
1693
- 'streaming-engine': unknown;
1694
- [key: string]: unknown;
1695
- }
1696
-
1697
- /**
1698
- * CamstackContext -- injected into every provider, device, and addon.
1699
- *
1700
- * Each element receives a context scoped to its identity:
1701
- * - logger is pre-scoped: (Frigate)[FrontDoor] for a device, (Frigate) for a provider
1702
- * - storage is namespaced: all reads/writes are relative to this element's ID
1703
- * - eventBus is shared (system-wide) but the source is pre-filled
1704
- * - config provides read/write access to this element's persisted configuration
1705
- *
1706
- * The `id` is an immutable progressive identifier assigned at creation time.
1707
- * It never changes even if the element is renamed.
1708
- */
1709
- interface CamstackContext {
1710
- /** Immutable progressive ID of this element (e.g., 'provider:frigate-1', 'device:frigate-1/front-door') */
1711
- readonly id: string;
1712
- /** Pre-scoped logger -- logs automatically include this element's scope chain */
1713
- readonly logger: IScopedLogger;
1714
- /** Event bus -- shared system-wide, use for emitting and subscribing to events */
1715
- readonly eventBus: IEventBus;
1716
- /** Storage scoped to this element -- all paths are relative to this element's namespace */
1717
- readonly storage: IStorageLocation;
1718
- /** Persisted configuration for this element -- read/write/subscribe to changes */
1719
- readonly config: IElementConfig;
1720
- }
1721
- /**
1722
- * Scoped configuration store for an element.
1723
- * Values are persisted in the element's storage namespace.
1724
- */
1725
- interface IElementConfig {
1726
- /** Get the full config object */
1727
- getAll(): Record<string, unknown>;
1728
- /** Get a single value by dot-path (e.g., 'mqtt.brokerUrl') */
1729
- get<T = unknown>(key: string): T | undefined;
1730
- /** Set a single value */
1731
- set(key: string, value: unknown): Promise<void>;
1732
- /** Set the entire config object (merge or replace) */
1733
- setAll(config: Record<string, unknown>): Promise<void>;
1734
- /** Subscribe to config changes -- callback receives the new full config */
1735
- onChange(callback: (config: Record<string, unknown>) => void): () => void;
1736
- }
1737
-
1738
- /**
1739
- * Progress update sent from a task handler back to the hub.
1740
- */
1741
- interface TaskProgress {
1742
- readonly percent?: number;
1743
- readonly message?: string;
1744
- readonly data?: unknown;
1745
- }
1746
- /**
1747
- * Context provided to a task handler when executing a task.
1748
- */
1749
- interface TaskContext {
1750
- /** ID of the agent executing this task */
1751
- readonly taskId: string;
1752
- /** ID of the agent executing this task */
1753
- readonly agentId: string;
1754
- /** Pre-scoped logger for the task */
1755
- readonly logger: IScopedLogger;
1756
- /** Send progress updates back to hub */
1757
- reportProgress(progress: TaskProgress): void;
1758
- /** Check if the task has been cancelled */
1759
- isCancelled(): boolean;
1760
- }
1761
- /**
1762
- * Security level for a task handler. Dangerous tasks (e.g., terminal.exec)
1763
- * require explicit admin approval per agent.
1764
- */
1765
- type TaskHandlerSecurity = 'safe' | 'dangerous';
1766
- /**
1767
- * Pluggable task handler interface. Any addon can register task handlers
1768
- * that the hub can dispatch to agents.
1769
- */
1770
- interface ITaskHandler {
1771
- /** Unique task type identifier (e.g., 'pipeline.decode', 'system.info') */
1772
- readonly taskType: string;
1773
- /** Human-readable description */
1774
- readonly description: string;
1775
- /** Security level — dangerous tasks need explicit admin approval */
1776
- readonly security?: TaskHandlerSecurity;
1777
- /** Execute the task and return a result */
1778
- handle(payload: unknown, context: TaskContext): Promise<unknown>;
1779
- /** Optional cleanup when a running task is cancelled */
1780
- cancel?(): Promise<void>;
1781
- }
1782
-
1783
- /** Storage interface for addon file operations */
1784
- interface IAddonFileStorage {
1785
- readFile(path: string): Promise<Buffer>;
1786
- writeFile(path: string, data: Buffer): Promise<void>;
1787
- deleteFile(path: string): Promise<void>;
1788
- listFiles(prefix?: string): Promise<readonly string[]>;
1789
- exists(path: string): Promise<boolean>;
1790
- }
1791
- /** Storage interface for addon structured data (DB) */
1792
- interface IAddonStructuredStorage {
1793
- query(collection: string, filter?: Record<string, unknown>): Promise<readonly unknown[]>;
1794
- insert(collection: string, data: Record<string, unknown>): Promise<void>;
1795
- update(collection: string, id: string, data: Record<string, unknown>): Promise<void>;
1796
- delete(collection: string, id: string): Promise<void>;
1797
- }
1798
- /** Named file storage locations available to addons */
1799
- type AddonFileLocationName = 'data' | 'media' | 'recordings' | 'models' | 'cache' | 'logs';
1800
- /** Named structured storage locations available to addons */
1801
- type AddonStructuredLocationName = 'data' | 'events' | 'config';
1802
- /** Combined storage location name (union of file and structured) */
1803
- type AddonStorageLocationName = AddonFileLocationName | AddonStructuredLocationName;
1804
- /** Storage access for addons -- replaces raw AddonLocationPaths */
1805
- interface AddonStorageLocations {
1806
- /** Get file storage for a named location */
1807
- getFiles(location: AddonFileLocationName): IAddonFileStorage;
1808
- /** Get structured storage (DB) for a named location */
1809
- getStructured(location: AddonStructuredLocationName): IAddonStructuredStorage;
1810
- }
1811
- type AddonCapability = 'storage' | 'backup' | 'log-destination' | 'device-exporter' | 'network-access' | 'turn-provider' | 'webrtc-provider' | 'remote-access' | 'recording-engine' | 'notification-output' | 'streaming-engine' | 'pipeline-consumer' | 'detection-engine' | 'object-detector' | 'motion-analyzer' | 'sub-detector' | 'face-detector' | 'plate-detector' | 'recognizer' | 'face-recognizer' | 'plate-recognizer' | 'audio-classifier' | 'device-provider' | 'stream-broker' | 'analysis-data-persistence' | 'analysis-pipeline';
1812
- interface RequiredStep {
1813
- readonly slot: PipelineSlot;
1814
- readonly outputClasses: readonly string[];
1815
- readonly description: string;
1816
- }
1817
- interface AddonManifest {
1818
- readonly id: string;
1819
- readonly name: string;
1820
- readonly version: string;
1821
- readonly description?: string;
1822
- readonly packageName?: string;
1823
- readonly capabilities?: readonly (AddonCapability | {
1824
- name: string;
1825
- mode: string;
1826
- })[];
1827
- readonly requiredFeatures?: readonly string[];
1828
- readonly slot?: PipelineSlot;
1829
- readonly inputClasses?: readonly string[];
1830
- readonly outputClasses?: readonly string[];
1831
- readonly requiredSteps?: readonly RequiredStep[];
1832
- readonly supportsCustomModels?: boolean;
1833
- readonly mayRequirePython?: boolean;
1834
- readonly defaultConfig?: Readonly<Record<string, unknown>>;
1835
- }
1836
- interface AddonLocationPaths {
1837
- readonly data: string;
1838
- readonly media: string;
1839
- readonly recordings: string;
1840
- readonly models: string;
1841
- readonly logs: string;
1842
- readonly cache: string;
1843
- }
1844
- /**
1845
- * Minimal model-management API exposed to addons via AddonContext.
1846
- */
1847
- interface IAddonModelManager {
1848
- /** Download (if necessary) and return the local filesystem path for a model. */
1849
- downloadModel(id: string): Promise<string>;
1850
- /** Absolute path to the shared models directory. */
1851
- getModelsDir(): string;
1852
- /** Whether a model file is already present on disk. */
1853
- isDownloaded(id: string): boolean;
1854
- }
1855
- /**
1856
- * AddonContext -- injected into every addon at initialize().
1857
- *
1858
- * The context includes both the CamstackContext fields (id, logger, eventBus, storage, config)
1859
- * and addon-specific extras (addonConfig, models, locationPaths, router, network).
1860
- */
1861
- interface AddonContext {
1862
- /** Immutable progressive ID */
1863
- readonly id: string;
1864
- /** Pre-scoped logger */
1865
- readonly logger: IScopedLogger;
1866
- /** System event bus */
1867
- readonly eventBus: IEventBus;
1868
- /** Scoped storage location */
1869
- readonly storage: IStorageLocation;
1870
- /** Persisted config store */
1871
- readonly config: IElementConfig;
1872
- /** Bootstrap configuration from server settings (read-only, from config.yaml) */
1873
- readonly addonConfig: Readonly<Record<string, unknown>>;
1874
- /** Model management -- download default models or retrieve cached paths. */
1875
- models?: IAddonModelManager;
1876
- /** Resolved filesystem paths for all named storage locations. */
1877
- readonly locationPaths: AddonLocationPaths;
1878
- /** HTTP router for registering addon routes */
1879
- readonly router?: IAddonRouter;
1880
- /** Network access provider */
1881
- readonly network?: INetworkProvider;
1882
- /** Storage provider */
1883
- readonly storageProvider?: IStorageProvider;
1884
- /**
1885
- * Register a task handler that can be dispatched by the hub.
1886
- * Only effective in agent mode — in hub mode, handlers are stored but not dispatched.
1887
- */
1888
- registerTaskHandler?(handler: ITaskHandler): void;
1889
- }
1890
- interface ICamstackAddon {
1891
- readonly id?: string;
1892
- readonly manifest: AddonManifest;
1893
- initialize(context: AddonContext): Promise<void>;
1894
- shutdown(): Promise<void>;
1895
- getConfigSchema?(): ConfigUISchema;
1896
- /**
1897
- * Return the provider instance for a declared capability.
1898
- * Called by CapabilityRegistry after initialize() succeeds.
1899
- * Returns null if this addon does not provide the requested capability.
1900
- */
1901
- getCapabilityProvider?<K extends keyof CapabilityProviderMap>(name: K): CapabilityProviderMap[K] | null;
1902
- }
1903
- /** Declaration of a UI page provided by an addon */
1904
- interface AddonPageDeclaration {
1905
- /** Unique page ID (scoped to addon) */
1906
- readonly id: string;
1907
- /** Display label for sidebar */
1908
- readonly label: string;
1909
- /** Lucide icon name for sidebar */
1910
- readonly icon: string;
1911
- /** Route path (e.g., '/benchmark') */
1912
- readonly path: string;
1913
- /** Relative path to JS bundle within addon package */
1914
- readonly bundle: string;
1915
- /** Web component custom element tag name */
1916
- readonly element: string;
1917
- }
1918
- /** Provider interface for addons that expose UI pages */
1919
- interface IAddonPageProvider {
1920
- readonly id: string;
1921
- getPages(): readonly AddonPageDeclaration[];
1922
- }
1923
- /** Provider interface for the admin UI shell (singleton capability) */
1924
- interface IAdminUI {
1925
- getStaticDir(): string;
1926
- getVersion(): string;
1927
- }
1928
- interface AddonDeclaration {
1929
- readonly id: string;
1930
- readonly entry: string;
1931
- readonly slot: PipelineSlot;
1932
- /** Capabilities this addon provides. Declared in package.json camstack.addons[].capabilities */
1933
- readonly capabilities?: readonly CapabilityDeclaration[];
1934
- /** UI pages provided by this addon */
1935
- readonly pages?: readonly AddonPageDeclaration[];
1936
- }
1937
- interface AddonPackageManifest {
1938
- readonly addons: readonly AddonDeclaration[];
1939
- }
1940
-
1941
- interface IPipelineSlotProvider {
1942
- readonly slot: PipelineSlot;
1943
- readonly inputClasses: readonly string[] | null;
1944
- readonly outputClasses: readonly string[];
1945
- readonly requiredSteps?: readonly RequiredStep[];
1946
- readonly slotPriority: number;
1947
- }
1948
-
1949
- interface IDetectorProvider extends IPipelineSlotProvider {
1950
- readonly slot: 'detector';
1951
- detect(frame: FrameInput): Promise<DetectorOutput>;
1952
- }
1953
-
1954
- interface ICropperProvider extends IPipelineSlotProvider {
1955
- readonly slot: 'cropper';
1956
- crop(input: CropInput): Promise<CropperOutput>;
1957
- }
1958
-
1959
- interface IClassifierProvider extends IPipelineSlotProvider {
1960
- readonly slot: 'classifier';
1961
- classify(input: CropInput): Promise<ClassifierOutput>;
1962
- }
1963
-
1964
- interface IDetectionAddon extends ICamstackAddon, IPipelineSlotProvider {
1965
- getConfigSchema(): ConfigUISchema;
1966
- getClassMap(): ClassMapDefinition;
1967
- getModelCatalog(): ModelCatalogEntry[];
1968
- getAvailableModels(): DetectionModel[];
1969
- getActiveLabels(): readonly LabelDefinition[];
1970
- probe(): Promise<ProbeResult>;
1971
- }
1972
-
1973
- interface IInferenceEngine {
1974
- readonly runtime: DetectionRuntime;
1975
- readonly device: DetectionDevice;
1976
- run(input: Float32Array, inputShape: readonly number[]): Promise<Float32Array>;
1977
- /** Run inference and return all named output tensors. Used by multi-output models (e.g. YOLO-seg). */
1978
- runMultiOutput(input: Float32Array, inputShape: readonly number[]): Promise<Record<string, Float32Array>>;
1979
- dispose(): Promise<void>;
1980
- }
1981
- interface ResolveEngineOptions {
1982
- readonly runtime: DetectionRuntime | 'auto';
1983
- readonly backend: string;
1984
- readonly modelEntry: ModelCatalogEntry;
1985
- readonly modelsDir: string;
1986
- }
1987
-
1988
- interface IZoneRepository {
1989
- getByCamera(cameraId: string): Promise<ZoneDefinition[]>;
1990
- save(zone: ZoneDefinition): Promise<void>;
1991
- delete(zoneId: string): Promise<void>;
1992
- }
1993
- interface IKnownFaceRepository {
1994
- getAll(): Promise<KnownFace[]>;
1995
- findByEmbedding(embedding: Float32Array, threshold: number): Promise<KnownFace | null>;
1996
- save(face: KnownFace): Promise<void>;
1997
- addEmbedding(faceId: string, embedding: Float32Array): Promise<void>;
1998
- delete(faceId: string): Promise<void>;
1999
- }
2000
- interface IKnownPlateRepository {
2001
- getAll(): Promise<KnownPlate[]>;
2002
- findByText(text: string): Promise<KnownPlate | null>;
2003
- save(plate: KnownPlate): Promise<void>;
2004
- delete(plateId: string): Promise<void>;
2005
- }
2006
-
2007
- interface PythonProbeResult {
2008
- readonly available: boolean;
2009
- readonly version?: string;
2010
- readonly path?: string;
2011
- readonly installedPackages?: readonly string[];
2012
- }
2013
- interface PythonEnvReady {
2014
- readonly pythonPath: string;
2015
- readonly venvPath: string;
2016
- spawn(script: string, args: readonly string[]): ChildProcess;
2017
- }
2018
- interface IPythonEnvironment {
2019
- probe(): Promise<PythonProbeResult>;
2020
- ensure(options: {
2021
- readonly packages: readonly string[];
2022
- }): Promise<PythonEnvReady>;
2023
- spawn(script: string, args: readonly string[]): ChildProcess;
2024
- }
2025
-
2026
- /**
2027
- * Abstract storage backend -- resolves subpaths to absolute filesystem paths.
2028
- */
2029
- interface IStorageBackend {
2030
- /** Backend type identifier */
2031
- readonly type: string;
2032
- /** Base path of this backend */
2033
- readonly basePath: string;
2034
- /** Resolve a subpath to an absolute path */
2035
- resolve(subpath: string): string;
2036
- /** Also support location-based resolution */
2037
- resolve(location: StorageLocationName, ...segments: string[]): string;
2038
- /** Check if the backend path exists and is writable */
2039
- isAvailable(location?: StorageLocationName): boolean;
2040
- /** Ensure base directory exists (mkdir -p equivalent) */
2041
- initialize(): Promise<void>;
2042
- /** Get the absolute path for a named storage location */
2043
- getLocationPath?(location: StorageLocationName): string;
2044
- }
2045
- /** @deprecated Use IStorageProvider from storage.ts instead */
2046
- interface IStorageProviderLegacy {
2047
- getLocation(name: string): string;
2048
- setLocationPath?(name: StorageLocationName, absolutePath: string): void;
2049
- }
2050
- /** Configuration for a storage location */
2051
- interface StorageLocationConfig {
2052
- readonly name: string;
2053
- readonly basePath: string;
2054
- readonly backendType?: string;
2055
- }
2056
- /** Default storage location paths, relative to dataPath */
2057
- declare const DEFAULT_LOCATION_SUBPATHS: Record<string, string>;
2058
-
2059
- interface IPipelineRunner {
2060
- run(frame: FrameInput, config?: PipelineConfig): Promise<PipelineResult>;
2061
- runSingle(addonId: string, input: FrameInput | CropInput, config?: Record<string, unknown>): Promise<StepResult>;
2062
- getStatus(): PipelineStatus[];
2063
- }
2064
- interface ValidationIssue {
2065
- readonly step?: string;
2066
- readonly addon?: string;
2067
- readonly message: string;
2068
- readonly severity: 'error' | 'warning';
2069
- }
2070
- interface ValidationResult {
2071
- readonly valid: boolean;
2072
- readonly errors: readonly ValidationIssue[];
2073
- readonly warnings: readonly ValidationIssue[];
2074
- }
2075
- interface IPipelineValidator {
2076
- validate(config: PipelineConfig): ValidationResult;
2077
- }
2078
-
2079
- type DeviceType = 'camera' | 'doorbell' | 'sensor' | 'switch' | 'thermostat' | 'light' | 'generic';
2080
- interface DeviceState {
2081
- online: boolean;
2082
- lastSeen?: number;
2083
- error?: string;
2084
- }
2085
- interface DeviceMetadata {
2086
- manufacturer?: string;
2087
- model?: string;
2088
- firmware?: string;
2089
- hardwareId?: string;
2090
- ip?: string;
2091
- }
2092
- interface DeviceEvent {
2093
- deviceId: string;
2094
- type: string;
2095
- timestamp: number;
2096
- data: Record<string, unknown>;
2097
- }
2098
- interface IDevice {
2099
- /** Immutable progressive ID */
2100
- readonly id: string;
2101
- readonly name: string;
2102
- readonly providerId: string;
2103
- readonly type: DeviceType;
2104
- readonly capabilities: DeviceCapabilityName[];
2105
- /** The device's context -- logger, storage, eventBus scoped to this device */
2106
- readonly ctx: CamstackContext;
2107
- getCapability<T extends IDeviceCapability>(cap: DeviceCapabilityName): T | null;
2108
- hasCapability(cap: DeviceCapabilityName): boolean;
2109
- getState(): DeviceState;
2110
- getMetadata(): DeviceMetadata;
2111
- subscribeEvents?(callback: (event: DeviceEvent) => void): () => void;
2112
- /** Optional: declare configurable settings UI for this device */
2113
- getConfigSchema?(): ConfigUISchema;
2114
- }
2115
-
2116
- interface ProviderStatus {
2117
- connected: boolean;
2118
- error?: string;
2119
- deviceCount: number;
2120
- }
2121
- interface DiscoveredDevice {
2122
- externalId: string;
2123
- name: string;
2124
- type: DeviceType;
2125
- capabilities: DeviceCapabilityName[];
2126
- metadata: DeviceMetadata;
2127
- }
2128
- interface LiveEvent {
2129
- type: string;
2130
- camera: string;
2131
- timestamp: number;
2132
- data: Record<string, unknown>;
2133
- }
2134
- interface IDeviceProvider {
2135
- /** Immutable progressive ID */
2136
- readonly id: string;
2137
- readonly type: string;
2138
- readonly name: string;
2139
- readonly discoveryMode: 'auto' | 'manual' | 'both';
2140
- /** The provider's context -- logger, storage, eventBus scoped to this provider */
2141
- readonly ctx: CamstackContext;
2142
- start(): Promise<void>;
2143
- stop(): Promise<void>;
2144
- getStatus(): ProviderStatus;
2145
- discoverDevices(): Promise<DiscoveredDevice[]>;
2146
- getDeviceConfigSchema?(): unknown;
2147
- createDevice?(config: Record<string, unknown>): Promise<IDevice>;
2148
- adoptDevice?(externalId: string, config?: Record<string, unknown>): Promise<IDevice>;
2149
- getDevices(): IDevice[];
2150
- subscribeLiveEvents(callback: (event: LiveEvent) => void): () => void;
2151
- /** Optional: declare configurable settings UI for this provider */
2152
- getConfigSchema?(): ConfigUISchema;
2153
- }
2154
-
2155
- interface StreamOption {
2156
- id: string;
2157
- label: string;
2158
- protocol: 'rtsp' | 'http' | 'webrtc';
2159
- quality: 'main' | 'mid' | 'sub' | 'mobile';
2160
- url?: string;
2161
- }
2162
- type ConnectionMode = 'always-on' | 'on-demand';
2163
- interface ICamera extends IDeviceCapability {
2164
- kind: 'camera';
2165
- getSnapshot(options?: {
2166
- width?: number;
2167
- height?: number;
2168
- }): Promise<Buffer>;
2169
- getStreamOptions(): Promise<StreamOption[]>;
2170
- getStreamUrl(option: StreamOption): Promise<string>;
2171
- onStreamRequested?(streamId: string): Promise<void>;
2172
- getConnectionMode(): ConnectionMode;
2173
- setConnectionMode(mode: ConnectionMode): Promise<void>;
2174
- }
2175
-
2176
- interface PtzPreset {
2177
- id: string;
2178
- name: string;
2179
- }
2180
- interface IPanTiltZoom extends IDeviceCapability {
2181
- kind: 'panTiltZoom';
2182
- move(command: {
2183
- pan?: number;
2184
- tilt?: number;
2185
- zoom?: number;
2186
- speed?: number;
2187
- }): Promise<void>;
2188
- continuousMove(command: {
2189
- pan?: number;
2190
- tilt?: number;
2191
- zoom?: number;
2192
- }): Promise<void>;
2193
- stop(): Promise<void>;
2194
- getPresets(): Promise<PtzPreset[]>;
2195
- goToPreset(presetId: string): Promise<void>;
2196
- goHome(): Promise<void>;
2197
- getPosition(): Promise<{
2198
- pan: number;
2199
- tilt: number;
2200
- zoom: number;
2201
- }>;
2202
- }
2203
-
2204
- interface IMotionSensor extends IDeviceCapability {
2205
- kind: 'motionSensor';
2206
- isMotionDetected(): boolean;
2207
- subscribe(callback: (active: boolean) => void): () => void;
2208
- }
2209
-
2210
- interface AudioEvent {
2211
- timestamp: number;
2212
- metric: string;
2213
- value?: number;
2214
- }
2215
- interface IAudioDetector extends IDeviceCapability {
2216
- kind: 'audioDetector';
2217
- getAudioLevel(): number;
2218
- subscribe(callback: (event: AudioEvent) => void): () => void;
2219
- }
2220
-
2221
- interface ITwoWayAudio extends IDeviceCapability {
2222
- kind: 'twoWayAudio';
2223
- startMicrophone(stream: unknown): Promise<void>;
2224
- stopMicrophone(): Promise<void>;
2225
- isMicrophoneActive(): boolean;
2226
- }
2227
-
2228
- interface DoorbellEvent {
2229
- timestamp: number;
2230
- deviceId: string;
2231
- }
2232
- interface IDoorbell extends IDeviceCapability {
2233
- kind: 'doorbell';
2234
- onRing(callback: (event: DoorbellEvent) => void): () => void;
2235
- }
2236
-
2237
- /** A stored event from a device */
2238
- interface DeviceStoredEvent {
2239
- id: string;
2240
- type: string;
2241
- timestamp: number;
2242
- endTimestamp?: number;
2243
- label?: string;
2244
- score?: number;
2245
- hasClip?: boolean;
2246
- hasSnapshot?: boolean;
2247
- thumbnailUrl?: string;
2248
- data?: Record<string, unknown>;
2249
- }
2250
- /** Query filter for events */
2251
- interface EventQuery {
2252
- since?: number;
2253
- until?: number;
2254
- types?: string[];
2255
- detectionClasses?: string[];
2256
- clusterSpan?: number;
2257
- onlyKeyEvents?: boolean;
2258
- includeClip?: boolean;
2259
- limit?: number;
2260
- offset?: number;
2261
- }
2262
- /** Query result */
2263
- interface EventQueryResult {
2264
- events: DeviceStoredEvent[];
2265
- total: number;
2266
- }
2267
- /** A cluster of nearby events */
2268
- interface EventCluster {
2269
- representative: DeviceStoredEvent;
2270
- events: DeviceStoredEvent[];
2271
- startMs: number;
2272
- endMs: number;
2273
- classes: string[];
2274
- }
2275
- interface IEvents extends IDeviceCapability {
2276
- kind: 'events';
2277
- getEvents(query: EventQuery): Promise<EventQueryResult>;
2278
- getEventThumbnail(eventId: string): Promise<Buffer | null>;
2279
- getEventSnapshot(eventId: string): Promise<Buffer | null>;
2280
- getEventClipUrl(eventId: string): Promise<string | null>;
2281
- }
2282
-
2283
- interface TimeRange {
2284
- since: number;
2285
- until: number;
2286
- }
2287
- interface RecordingSegment {
2288
- id: string;
2289
- startTime: number;
2290
- endTime: number;
2291
- duration: number;
2292
- }
2293
- interface IRecording extends IDeviceCapability {
2294
- kind: 'recording';
2295
- getSegments(range: TimeRange): Promise<RecordingSegment[]>;
2296
- getPlaybackUrl(startTime: number, endTime: number): Promise<string>;
2297
- getThumbnailAt(timestampMs: number): Promise<Buffer | null>;
2298
- }
2299
-
2300
- interface AccessoryInfo {
2301
- id: string;
2302
- name: string;
2303
- type: string;
2304
- state?: Record<string, unknown>;
2305
- }
2306
- interface IAccessory extends IDeviceCapability {
2307
- kind: 'accessory';
2308
- getAccessories(): Promise<AccessoryInfo[]>;
2309
- executeCommand(accessoryId: string, command: string, params?: Record<string, unknown>): Promise<void>;
2310
- getAccessoryState(accessoryId: string): Promise<Record<string, unknown>>;
2311
- }
2312
-
2313
- interface IStatusLight extends IDeviceCapability {
2314
- kind: 'statusLight';
2315
- isOn(): boolean;
2316
- setOn(on: boolean): Promise<void>;
2317
- }
2318
-
2319
- interface ISiren extends IDeviceCapability {
2320
- kind: 'siren';
2321
- isActive(): boolean;
2322
- activate(durationMs?: number): Promise<void>;
2323
- deactivate(): Promise<void>;
2324
- }
2325
-
2326
- interface ISwitch extends IDeviceCapability {
2327
- kind: 'switch';
2328
- isOn(): boolean;
2329
- setOn(on: boolean): Promise<void>;
2330
- toggle(): Promise<void>;
2331
- }
2332
-
2333
- type StreamFormat = 'webrtc' | 'hls' | 'mjpeg' | 'rtsp';
2334
- interface StreamingSource {
2335
- readonly url: string;
2336
- readonly protocol: 'rtsp' | 'http' | 'rtmp';
2337
- readonly deviceId: string;
2338
- readonly providerId: string;
2339
- readonly label?: string;
2340
- }
2341
- interface StreamInfo {
2342
- readonly streamId: string;
2343
- readonly source: StreamingSource;
2344
- readonly formats: StreamFormat[];
2345
- }
2346
- interface StreamStatus {
2347
- readonly active: boolean;
2348
- readonly viewers: number;
2349
- readonly startedAt?: number;
2350
- }
2351
- interface IStreamingEngine {
2352
- initialize(config: Record<string, unknown>): Promise<void>;
2353
- shutdown(): Promise<void>;
2354
- registerStream(streamId: string, source: StreamingSource): Promise<void>;
2355
- unregisterStream(streamId: string): Promise<void>;
2356
- getStreamUrl(streamId: string, format: StreamFormat): string | null;
2357
- proxyWhepOffer(streamId: string, sdpOffer: string): Promise<string>;
2358
- listStreams(): StreamInfo[];
2359
- getStreamStatus(streamId: string): StreamStatus | null;
2360
- }
2361
-
2362
- type UserRole = 'super_admin' | 'admin' | 'viewer';
2363
- interface UserPermissions {
2364
- role: UserRole;
2365
- allowedProviders: string[] | '*';
2366
- allowedDevices: Record<string, string[] | '*'>;
2367
- }
2368
- interface UserRecord {
2369
- id: string;
2370
- username: string;
2371
- passwordHash: string;
2372
- role: UserRole;
2373
- allowedProviders: string[] | '*';
2374
- allowedDevices: Record<string, string[] | '*'>;
2375
- createdAt: number;
2376
- updatedAt: number;
2377
- }
2378
- interface ApiKeyRecord {
2379
- id: string;
2380
- label: string;
2381
- role: UserRole;
2382
- allowedProviders: string[] | '*';
2383
- allowedDevices: Record<string, string[] | '*'>;
2384
- tokenHash: string;
2385
- tokenPrefix: string;
2386
- createdAt: number;
2387
- lastUsedAt?: number;
2388
- }
2389
- interface TokenPayload {
2390
- type?: 'api_key';
2391
- keyId?: string;
2392
- userId?: string;
2393
- username?: string;
2394
- role: UserRole;
2395
- allowedProviders: string[] | '*';
2396
- allowedDevices: Record<string, string[] | '*'>;
2397
- iat?: number;
2398
- exp?: number;
2399
- }
2400
- interface AuthenticatedUser {
2401
- id: string;
2402
- username: string;
2403
- role: UserRole;
2404
- permissions: UserPermissions;
2405
- isApiKey: boolean;
2406
- }
2407
-
2408
- type ElementState = 'stopped' | 'starting' | 'running' | 'stopping' | 'error' | 'disabled';
2409
- interface ElementStatus {
2410
- state: ElementState;
2411
- error?: string;
2412
- startedAt?: number;
2413
- stoppedAt?: number;
2414
- restartCount: number;
2415
- uptime: number;
2416
- }
2417
- interface ILifecycleManaged {
2418
- readonly id: string;
2419
- getStatus(): ElementStatus;
2420
- start(): Promise<void>;
2421
- stop(): Promise<void>;
2422
- restart(): Promise<void>;
2423
- enable(): Promise<void>;
2424
- disable(): Promise<void>;
2425
- }
2426
-
2427
- /**
2428
- * Server-side network access interfaces.
2429
- * These cover tunnel/VPN/endpoint management, NOT the addon-facing INetworkProvider.
2430
- */
2431
- interface INetworkEndpoint {
2432
- id: string;
2433
- type: 'lan' | 'mdns' | 'domain' | 'tunnel' | 'vpn' | 'custom';
2434
- provider: string;
2435
- url: string;
2436
- internal: boolean;
2437
- capabilities: EndpointCapabilities;
2438
- priority: number;
2439
- status: 'online' | 'offline' | 'unknown';
2440
- metadata?: Record<string, unknown>;
2441
- }
2442
- interface EndpointCapabilities {
2443
- supportsWebRTC: boolean;
2444
- supportsWebSocket: boolean;
2445
- supportsSSE: boolean;
2446
- maxBandwidthMbps?: number;
2447
- }
2448
- interface INetworkAccessProvider {
2449
- id: string;
2450
- type: string;
2451
- start(): Promise<INetworkEndpoint>;
2452
- stop(): Promise<void>;
2453
- getEndpoint(): INetworkEndpoint | null;
2454
- getStatus(): NetworkAccessStatus;
2455
- }
2456
- interface NetworkAccessStatus {
2457
- connected: boolean;
2458
- publicUrl?: string;
2459
- error?: string;
2460
- connectedSince?: number;
2461
- }
2462
- interface IExposedResource {
2463
- id: string;
2464
- providerId: string;
2465
- deviceId?: string;
2466
- type: ExposedResourceType;
2467
- path: string;
2468
- auth: ResourceAuthMode;
2469
- description: string;
2470
- contentType?: string;
2471
- enabled: boolean;
2472
- }
2473
- type ExposedResourceType = 'snapshot' | 'stream' | 'webhook' | 'api' | 'media' | 'custom';
2474
- type ResourceAuthMode = {
2475
- mode: 'public';
2476
- } | {
2477
- mode: 'token';
2478
- token: string;
2479
- } | {
2480
- mode: 'api-key';
2481
- } | {
2482
- mode: 'jwt';
2483
- } | {
2484
- mode: 'ip-whitelist';
2485
- ips: string[];
2486
- };
2487
- interface IResourceExposer {
2488
- getExposedResources(): IExposedResource[];
2489
- handleResourceRequest(resourceId: string, request: ExposedResourceRequest): Promise<ExposedResourceResponse>;
2490
- }
2491
- interface ExposedResourceRequest {
2492
- method: 'GET' | 'POST' | 'PUT' | 'DELETE';
2493
- path: string;
2494
- headers: Record<string, string>;
2495
- query: Record<string, string>;
2496
- body?: Buffer | string;
2497
- remoteIp: string;
2498
- }
2499
- interface ExposedResourceResponse {
2500
- status: number;
2501
- headers?: Record<string, string>;
2502
- body?: Buffer | string | NodeJS.ReadableStream;
2503
- }
2504
-
2505
- interface ProcessStats {
2506
- pid: number;
2507
- cpu: number;
2508
- memory: number;
2509
- uptime: number;
2510
- restartCount: number;
2511
- }
2512
- interface ProcessConfig {
2513
- id: string;
2514
- label: string;
2515
- command?: string;
2516
- modulePath?: string;
2517
- args?: string[];
2518
- env?: Record<string, string>;
2519
- autoRestart: boolean;
2520
- maxRestarts?: number;
2521
- healthCheck?: {
2522
- intervalMs: number;
2523
- timeoutMs: number;
2524
- failureThreshold: number;
2525
- };
2526
- }
2527
- interface ManagedProcessStatus {
2528
- id: string;
2529
- label: string;
2530
- state: ElementState;
2531
- pid?: number;
2532
- stats?: ProcessStats;
2533
- lastCrashAt?: number;
2534
- lastCrashError?: string;
2535
- restartCount: number;
2536
- nextRestartAt?: number;
2537
- }
2538
- /** Minimal interface for ProcessManagerService used by addons */
2539
- interface IProcessManager {
2540
- register(config: ProcessConfig): unknown;
2541
- start(id: string): Promise<void>;
2542
- stop(id: string): Promise<void>;
2543
- }
2544
-
2545
- interface FeatureManifest {
2546
- streaming: boolean;
2547
- notifications: boolean;
2548
- objectDetection: boolean;
2549
- remoteAccess: boolean;
2550
- agentCluster: boolean;
2551
- smartHome: boolean;
2552
- recordings: boolean;
2553
- backup: boolean;
2554
- repl: boolean;
2555
- }
2556
- type FeatureFlag = keyof FeatureManifest;
2557
- declare const DEFAULT_FEATURES: FeatureManifest;
2558
-
2559
- interface AgentInfo {
2560
- readonly id: string;
2561
- readonly name: string;
2562
- readonly capabilities: readonly string[];
2563
- readonly host: string;
2564
- readonly port: number;
2565
- readonly resources?: AgentResources;
2566
- }
2567
- interface AgentResources {
2568
- readonly cpuCores?: number;
2569
- readonly memoryMB?: number;
2570
- readonly gpuAvailable?: boolean;
2571
- readonly gpuModel?: string;
2572
- }
2573
- interface AgentStatus {
2574
- readonly id: string;
2575
- readonly name: string;
2576
- readonly state: 'online' | 'offline' | 'degraded';
2577
- readonly capabilities: readonly string[];
2578
- readonly lastHeartbeat: number;
2579
- readonly connectedSince?: number;
2580
- readonly resources?: AgentResources;
2581
- readonly activeTaskCount: number;
2582
- readonly completedTaskCount: number;
2583
- readonly failedTaskCount: number;
2584
- }
2585
- interface AgentTask {
2586
- readonly id: string;
2587
- readonly capability: string;
2588
- readonly input: Record<string, unknown>;
2589
- readonly timeout: number;
2590
- readonly priority: 'low' | 'normal' | 'high';
2591
- readonly label?: string;
2592
- }
2593
- interface AgentTaskResult {
2594
- readonly taskId: string;
2595
- readonly agentId: string;
2596
- readonly status: 'success' | 'error' | 'timeout';
2597
- readonly output?: Record<string, unknown>;
2598
- readonly error?: string;
2599
- readonly durationMs: number;
2600
- }
2601
- interface TaskDispatchOptions {
2602
- readonly preferredAgent?: string;
2603
- readonly capability: string;
2604
- readonly remoteOnly?: boolean;
2605
- }
2606
- interface AgentEntry {
2607
- readonly info: AgentInfo;
2608
- state: 'online' | 'offline' | 'degraded';
2609
- connectedSince: number;
2610
- lastHeartbeat: number;
2611
- activeTaskCount: number;
2612
- completedTaskCount: number;
2613
- failedTaskCount: number;
2614
- }
2615
-
2616
- type AgentCapability = 'decoder' | 'transcoder' | 'detector' | 'recorder';
2617
- type RolePriority = 'primary' | 'backup' | 'overflow';
2618
- interface CameraRoleAssignment {
2619
- cameraId: string;
2620
- role: AgentCapability;
2621
- agentId: string;
2622
- priority: RolePriority;
2623
- rtspUrl?: string;
2624
- detectionConfig?: {
2625
- modelId: string;
2626
- runtime: string;
2627
- confidence: number;
2628
- fps: number;
2629
- classes?: string[];
2630
- };
2631
- }
2632
- type HubToAgentMessage = {
2633
- type: 'assign';
2634
- assignment: CameraRoleAssignment;
2635
- } | {
2636
- type: 'unassign';
2637
- cameraId: string;
2638
- role: AgentCapability;
2639
- } | {
2640
- type: 'recording.start';
2641
- cameraId: string;
2642
- rtspUrl: string;
2643
- } | {
2644
- type: 'recording.stop';
2645
- cameraId: string;
2646
- } | {
2647
- type: 'benchmark.run';
2648
- config: RemoteBenchmarkConfig;
2649
- } | {
2650
- type: 'config.update';
2651
- addonId: string;
2652
- config: Record<string, unknown>;
2653
- } | {
2654
- type: 'task.execute';
2655
- taskId: string;
2656
- taskType: string;
2657
- payload: unknown;
2658
- } | {
2659
- type: 'task.cancel';
2660
- taskId: string;
2661
- } | {
2662
- type: 'addon.install';
2663
- package: string;
2664
- version?: string;
2665
- } | {
2666
- type: 'addon.uninstall';
2667
- package: string;
2668
- } | {
2669
- type: 'addon.update';
2670
- package: string;
2671
- version?: string;
2672
- } | {
2673
- type: 'addon.restart';
2674
- } | {
2675
- type: 'ping';
2676
- };
2677
- type AgentToHubMessage = {
2678
- type: 'register';
2679
- info: AgentRegistrationInfo;
2680
- } | {
2681
- type: 'heartbeat';
2682
- status: AgentRuntimeStatus;
2683
- } | {
2684
- type: 'detection.result';
2685
- cameraId: string;
2686
- detections: DetectionResult[];
2687
- timestamp: number;
2688
- inferenceMs: number;
2689
- } | {
2690
- type: 'recording.segment';
2691
- cameraId: string;
2692
- segment: RecordingSegmentInfo;
2693
- } | {
2694
- type: 'recording.status';
2695
- cameraId: string;
2696
- recording: boolean;
2697
- } | {
2698
- type: 'benchmark.progress';
2699
- event: BenchmarkStreamEvent;
2700
- } | {
2701
- type: 'benchmark.result';
2702
- report: BenchmarkReport;
2703
- } | {
2704
- type: 'task.result';
2705
- taskId: string;
2706
- success: boolean;
2707
- result?: unknown;
2708
- error?: string;
2709
- } | {
2710
- type: 'task.progress';
2711
- taskId: string;
2712
- progress: TaskProgress;
2713
- } | {
2714
- type: 'addon.install-result';
2715
- package: string;
2716
- success: boolean;
2717
- version?: string;
2718
- error?: string;
2719
- } | {
2720
- type: 'addon.uninstall-result';
2721
- package: string;
2722
- success: boolean;
2723
- error?: string;
2724
- } | {
2725
- type: 'addon.update-result';
2726
- package: string;
2727
- success: boolean;
2728
- version?: string;
2729
- error?: string;
2730
- } | {
2731
- type: 'log';
2732
- level: string;
2733
- scope: string;
2734
- message: string;
2735
- } | {
2736
- type: 'pong';
2737
- };
2738
- declare const BINARY_FRAME_HEADER_SIZE = 29;
2739
- declare const BINARY_FRAME_TYPE = 1;
2740
- interface AgentRegistrationInfo {
2741
- id: string;
2742
- name: string;
2743
- capabilities: AgentCapability[];
2744
- host: string;
2745
- port: number;
2746
- platform: string;
2747
- arch: string;
2748
- cpuCores: number;
2749
- memoryMB: number;
2750
- gpuModel?: string;
2751
- pythonRuntimes: string[];
2752
- httpPort: number;
2753
- /** Task types this agent can handle (e.g., 'pipeline.decode', 'system.info') */
2754
- taskTypes?: string[];
2755
- /** Installed addons on this agent */
2756
- installedAddons?: string[];
2757
- }
2758
- interface AgentRuntimeStatus {
2759
- activeCameras: number;
2760
- cpuPercent: number;
2761
- memoryPercent: number;
2762
- fps: Record<string, number>;
2763
- errors: string[];
2764
- }
2765
- interface DetectionResult {
2766
- className: string;
2767
- score: number;
2768
- bbox: [number, number, number, number];
2769
- }
2770
- interface RecordingSegmentInfo {
2771
- id: string;
2772
- startTime: number;
2773
- endTime: number;
2774
- duration: number;
2775
- sizeBytes: number;
2776
- path: string;
2777
- format: 'mp4' | 'ts';
2778
- }
2779
- interface RemoteBenchmarkConfig {
2780
- runtime: string;
2781
- modelId?: string;
2782
- durationMs: number;
2783
- warmupMs: number;
2784
- inputWidth: number;
2785
- inputHeight: number;
2786
- }
2787
- interface BenchmarkStreamEvent {
2788
- phase: 'warmup' | 'running';
2789
- iteration: number;
2790
- inferenceMs: number;
2791
- }
2792
- interface BenchmarkReport {
2793
- runtime: string;
2794
- modelId?: string;
2795
- iterations: number;
2796
- meanMs: number;
2797
- p50Ms: number;
2798
- p95Ms: number;
2799
- p99Ms: number;
2800
- minMs: number;
2801
- maxMs: number;
2802
- }
2803
-
2804
- type Unsubscribe = () => void;
2805
- interface StreamSource {
2806
- readonly type: string;
2807
- readonly url: string;
2808
- readonly videoCodec?: string;
2809
- readonly audioCodec?: string;
2810
- readonly metadata?: Readonly<Record<string, unknown>>;
2811
- }
2812
- interface StreamSourceOption {
2813
- readonly id: string;
2814
- readonly label: string;
2815
- readonly source: StreamSource;
2816
- readonly resolution?: {
2817
- readonly width: number;
2818
- readonly height: number;
2819
- };
2820
- readonly primary?: boolean;
2821
- }
2822
- interface EncodedPacket {
2823
- readonly type: 'video' | 'audio';
2824
- readonly data: Buffer;
2825
- readonly pts: number;
2826
- readonly dts: number;
2827
- readonly keyframe: boolean;
2828
- readonly codec: string;
2829
- }
2830
- interface DecodedFrame {
2831
- readonly data: Buffer;
2832
- readonly width: number;
2833
- readonly height: number;
2834
- readonly format: 'jpeg' | 'rgb' | 'yuv420';
2835
- readonly timestamp: number;
2836
- }
2837
- interface DecodedAudioChunk {
2838
- readonly data: Buffer;
2839
- readonly sampleRate: number;
2840
- readonly channels: number;
2841
- readonly timestamp: number;
2842
- }
2843
- interface DecodeOptions {
2844
- readonly maxFps?: number;
2845
- readonly format?: 'jpeg' | 'rgb' | 'yuv420';
2846
- readonly scale?: number;
2847
- }
2848
- type BrokerStatus = 'idle' | 'connecting' | 'streaming' | 'error' | 'stopped';
2849
- interface BrokerStats {
2850
- readonly status: BrokerStatus;
2851
- readonly inputFps: number;
2852
- readonly decodeFps: number;
2853
- readonly encodedSubscribers: number;
2854
- readonly decodedSubscribers: number;
2855
- readonly uptimeMs: number;
2856
- }
2857
- interface IStreamBroker {
2858
- readonly deviceId: string;
2859
- readonly status: BrokerStatus;
2860
- start(source: StreamSource): Promise<void>;
2861
- stop(): Promise<void>;
2862
- onEncodedData(callback: (packet: EncodedPacket) => void): Unsubscribe;
2863
- onDecodedFrame(callback: (frame: DecodedFrame) => void, options?: DecodeOptions): Unsubscribe;
2864
- onDecodedAudioChunk(callback: (chunk: DecodedAudioChunk) => void): Unsubscribe;
2865
- getStats(): BrokerStats;
2866
- getLocalStreamUrl(): string;
2867
- }
2868
- /**
2869
- * Manager for stream brokers — the server interacts with this interface,
2870
- * while the concrete implementation lives in the addon-pipeline package.
2871
- */
2872
- interface IStreamBrokerManager {
2873
- createBroker(brokerId: string, source: StreamSource): Promise<IStreamBroker>;
2874
- getBroker(brokerId: string): IStreamBroker | undefined;
2875
- destroyBroker(brokerId: string): Promise<void>;
2876
- destroyBrokersForDevice(deviceId: string): Promise<void>;
2877
- listBrokers(): readonly IStreamBroker[];
2878
- destroyAll(): Promise<void>;
2879
- setRestreamers(restreamers: readonly unknown[]): void;
2880
- getRestreamers(): readonly unknown[];
2881
- }
2882
- type CameraPriority = 'always-on' | 'default';
2883
- type CameraPhase = 'watching' | 'active';
2884
- interface CameraDetectionConfig {
2885
- readonly enabled: boolean;
2886
- readonly priority: CameraPriority;
2887
- readonly pipeline: PipelineConfig;
2888
- readonly motionStreamId: string;
2889
- readonly detectionStreamId: string;
2890
- readonly motionFps: number;
2891
- readonly detectionFps: number;
2892
- readonly motionCooldownMs: number;
2893
- readonly audioStreamId?: string;
2894
- }
2895
-
2896
- interface RegisteredStream {
2897
- readonly streamId: string;
2898
- readonly label: string;
2899
- readonly codec: string;
2900
- readonly type: 'video' | 'audio';
2901
- readonly sourceUrl?: string;
2902
- }
2903
- interface RestreamerExposedResource {
2904
- readonly type: string;
2905
- readonly format: string;
2906
- readonly value: string;
2907
- readonly metadata?: Readonly<Record<string, unknown>>;
2908
- }
2909
- interface IRestreamer {
2910
- readonly id: string;
2911
- readonly name: string;
2912
- registerDevice(deviceId: string, streams: readonly RegisteredStream[]): Promise<void>;
2913
- pushPacket(streamId: string, packet: EncodedPacket): void;
2914
- unregisterDevice(deviceId: string): Promise<void>;
2915
- getExposedResources(deviceId: string): readonly RestreamerExposedResource[];
2916
- proxyWhepOffer?(streamId: string, sdpOffer: string): Promise<string>;
2917
- }
2918
-
2919
- interface DecoderSessionConfig {
2920
- readonly codec: string;
2921
- readonly maxFps: number;
2922
- readonly outputFormat: 'jpeg' | 'rgb' | 'yuv420';
2923
- readonly scale: number;
2924
- }
2925
- interface DecoderStats {
2926
- readonly inputFps: number;
2927
- readonly outputFps: number;
2928
- readonly avgDecodeTimeMs: number;
2929
- readonly droppedFrames: number;
2930
- }
2931
- interface IDecoderSession {
2932
- pushPacket(packet: EncodedPacket): void;
2933
- onFrame(callback: (frame: DecodedFrame) => void): Unsubscribe;
2934
- updateConfig(config: Partial<DecoderSessionConfig>): void;
2935
- destroy(): Promise<void>;
2936
- getStats(): DecoderStats;
2937
- }
2938
- interface IDecoderProvider {
2939
- readonly id: string;
2940
- readonly name: string;
2941
- supportsCodec(codec: string): boolean;
2942
- createSession(config: DecoderSessionConfig): IDecoderSession;
2943
- }
2944
-
2945
- interface FfmpegConfig {
2946
- readonly path: string;
2947
- readonly hwaccel?: 'vaapi' | 'qsv' | 'videotoolbox' | 'cuda' | 'v4l2m2m' | 'none';
2948
- readonly inputArgs?: readonly string[];
2949
- readonly outputArgs?: readonly string[];
2950
- readonly videoCodec?: string;
2951
- readonly audioCodec?: string;
2952
- readonly threads?: number;
2953
- }
2954
-
2955
- type ModelType = 'detection' | 'face-detection' | 'face-recognition' | 'plate-detection' | 'ocr' | 'embedding' | 'audio-classification' | 'custom';
2956
- type ModelFormat = 'onnx' | 'tflite' | 'coreml' | 'openvino';
2957
- interface ServerModelCatalogEntry {
2958
- readonly id: string;
2959
- readonly name: string;
2960
- readonly description: string;
2961
- readonly type: ModelType;
2962
- readonly format: ModelFormat;
2963
- readonly available: boolean;
2964
- readonly downloadUrl?: string;
2965
- readonly fallbackDownloadUrls?: readonly string[];
2966
- readonly sizeMB?: number;
2967
- readonly exportHint?: string;
2968
- readonly inputSize: {
2969
- readonly width: number;
2970
- readonly height: number;
2971
- readonly channels?: number;
2972
- };
2973
- readonly labels?: readonly string[];
2974
- }
2975
- interface IModelCatalogProvider {
2976
- readonly pluginId: string;
2977
- getModelCatalog(): ServerModelCatalogEntry[];
2978
- }
2979
-
2980
- interface StreamNetworkStats {
2981
- readonly nominalBitrateKbps: number;
2982
- readonly observedBitrateKbps: number;
2983
- readonly peakBitrateKbps: number;
2984
- readonly packetLossPercent: number;
2985
- readonly lastUpdated: number;
2986
- }
2987
- interface ClientNetworkStats {
2988
- readonly rttMs: number;
2989
- readonly jitterMs: number;
2990
- readonly estimatedBandwidthKbps: number;
2991
- readonly lastUpdated: number;
2992
- }
2993
- interface DeviceNetworkStats {
2994
- readonly deviceId: string;
2995
- readonly streams: Readonly<Record<string, StreamNetworkStats>>;
2996
- readonly client?: ClientNetworkStats;
2997
- }
2998
- interface INetworkQualityTracker {
2999
- reportStreamStats(deviceId: string, streamId: string, bitrateKbps: number, packetLoss?: number): void;
3000
- reportClientStats(deviceId: string, stats: Omit<ClientNetworkStats, 'lastUpdated'>): void;
3001
- getDeviceStats(deviceId: string): DeviceNetworkStats | null;
3002
- getAllStats(): readonly DeviceNetworkStats[];
3003
- }
3004
-
3005
- interface IWebRtcProvider {
3006
- readonly id: string;
3007
- readonly name: string;
3008
- handleOffer(streamId: string, sdpOffer: string): Promise<string>;
3009
- supportsStream(streamId: string): boolean;
3010
- registerStream(streamId: string, codec: string): Promise<void>;
3011
- pushPacket(streamId: string, packet: EncodedPacket): void;
3012
- unregisterStream(streamId: string): Promise<void>;
3013
- }
3014
-
3015
- interface ReplContext {
3016
- scope: ReplScope;
3017
- variables: Record<string, unknown>;
3018
- }
3019
- type ReplScope = {
3020
- type: 'system';
3021
- } | {
3022
- type: 'provider';
3023
- providerId: string;
3024
- } | {
3025
- type: 'device';
3026
- deviceId: string;
3027
- } | {
3028
- type: 'addon';
3029
- addonId: string;
3030
- };
3031
- interface ReplResult {
3032
- output: string;
3033
- type: 'value' | 'error' | 'void';
3034
- duration: number;
3035
- }
3036
- interface IReplEngine {
3037
- execute(code: string, context: ReplContext): Promise<ReplResult>;
3038
- getCompletions(partial: string, context: ReplContext): Promise<string[]>;
3039
- }
3040
-
3041
- declare const HF_REPO = "camstack/camstack-models";
3042
- declare const HF_BASE_URL = "https://huggingface.co/camstack/camstack-models/resolve/main";
3043
-
3044
- declare function hfModelUrl(repo: string, path: string): string;
3045
-
3046
- /** Cosine similarity between two embedding vectors */
3047
- declare function cosineSimilarity(a: Float32Array, b: Float32Array): number;
3048
-
3049
- declare const COCO_80_LABELS: readonly LabelDefinition[];
3050
- declare const MACRO_LABELS: readonly LabelDefinition[];
3051
- declare const COCO_TO_MACRO: ClassMapDefinition;
3052
-
3053
- export { type AccessoryInfo, type AccuracyStats, type ActiveDetection, type AddonCapability, type AddonContext, type AddonDeclaration, type AddonFileLocationName, type AddonHttpReply, type AddonHttpRequest, type AddonLocationPaths, type AddonManifest, type AddonPackageManifest, type AddonPageDeclaration, type AddonStorageLocationName, type AddonStorageLocations, type AddonStructuredLocationName, type AgentBenchmarkStatus, type AgentCapability, type AgentEntry, type AgentInfo, type AgentRegistrationInfo, type AgentResources, type AgentRuntimeStatus, type AgentStatus, type AgentTask, type AgentTaskResult, type AgentToHubMessage, type AnalysisContext, type AnalysisEvent, type AnnotatedSnapshotResult, type ApiKeyRecord, type AudioChunk, type AudioChunkCallback, type AudioChunkInput, type AudioClassification, type AudioEvent, type AuthResult, type AuthenticatedUser, BINARY_FRAME_HEADER_SIZE, BINARY_FRAME_TYPE, type BenchmarkConfig, type BenchmarkExecution, type BenchmarkMode, type BenchmarkReport, type BenchmarkSource, type BenchmarkStreamEvent, type BenchmarkTarget, type BenchmarkTargetResult, type BoundingBox, type BrokerStats, type BrokerStatus, COCO_80_LABELS, COCO_TO_MACRO, type CameraAnalysisConfig, type CameraDetectionConfig, type CameraLiveState, type CameraPhase, type CameraPriority, type CameraRoleAssignment, type CamstackContext, type CapabilityBinding, type CapabilityConsumerRegistration, type CapabilityDeclaration, type CapabilityInfo, type CapabilityMode, type CapabilityProviderMap, type ClassMapDefinition, type Classification, type ClassifierOutput, type ClientNetworkStats, type ClipRecognizer, type ConfigBooleanField, type ConfigColorField, type ConfigCondition, type ConfigField, type ConfigFieldBase, type ConfigGroupField, type ConfigInfoField, type ConfigModelSelectorField, type ConfigMultiSelectField, type ConfigNumberField, type ConfigOption, type ConfigPasswordField, type ConfigSection, type ConfigSelectField, type ConfigSeparatorField, type ConfigSliderField, type ConfigTagsField, type ConfigTextAreaField, type ConfigTextField, type ConfigUISchema, type ConnectionMode, type CropInput, type CropperOutput, type CustomModelMetadata, DEFAULT_FEATURES, DEFAULT_LOCATION_SUBPATHS, DEFAULT_RETENTION, DETECTION_TYPES, type DecodeOptions, type DecodedAudioChunk, type DecodedFrame, type DecoderSessionConfig, type DecoderStats, type Detection, type DetectionDevice, type DetectionEvent, type DetectionEventType, type DetectionFrame, type DetectionLine, type DetectionModel, type DetectionResult, type DetectionRuntime, type DetectionType, type DetectionZone, type DetectorOutput, type DeviceCapabilityBinding, type DeviceCapabilityName, type DeviceEvent, type DeviceMetadata, type DeviceNetworkStats, type DeviceState, type DeviceStoredEvent, type DeviceType, type DiscoveredDevice, type DoorbellEvent, type ElementState, type ElementStatus, type EncodedPacket, type EndpointCapabilities, type EventBufferStatus, type EventCluster, type EventFilter, type EventQuery, type EventQueryResult, type EventSnapshot, type EventSource, type ExposedResourceRequest, type ExposedResourceResponse, type ExposedResourceType, type FeatureFlag, type FeatureManifest, type FfmpegConfig, type FrameInput, type FrameSubscriptionOptions, type GlobalIdentity, type GroundTruth, type GroundTruthAnnotation, HF_BASE_URL, HF_REPO, type HeatmapData, type HeatmapOptions, type HttpMethod, type HubToAgentMessage, type IAccessory, type IAddonFileStorage, type IAddonHttpRoute, type IAddonModelManager, type IAddonPageProvider, type IAddonRouteProvider, type IAddonRouter, type IAddonStructuredStorage, type IAdminUI, type IAnalysisAddon, type IAnalysisDataPersistence, type IAnalysisPipeline, type IAnalysisStage, type IAudioClassifier, type IAudioDetector, type IAuthProvider, type ICamera, type ICameraAnalyticsProvider, type ICameraPipeline, type ICamstackAddon, type IClassFilterStage, type IClassifierProvider, type IConfigurable, type ICropperProvider, type IDecoderProvider, type IDecoderSession, type IDetectionAddon, type IDetectorProvider, type IDevice, type IDeviceCapability, type IDeviceProvider, type IDoorbell, type IElementConfig, type IEventBus, type IEventGenerationStage, type IEventPersistence, type IEvents, type IExposedResource, type IFaceDetector, type IFaceRecognizer, type IFileStorage, type IInferenceEngine, type IKnownFaceRepository, type IKnownFaces, type IKnownPlateRepository, type ILifecycleManaged, type ILogDestination, type IModelCatalogProvider, type IMotionSensor, type INetworkAccessProvider, type INetworkEndpoint, type INetworkProvider, type INetworkQualityTracker, type INotificationOutput, type IObjectDetector, type IObjectSnapshotStage, type IPanTiltZoom, type IPipelineConsumer, type IPipelineManager, type IPipelineRunner, type IPipelineSlotProvider, type IPipelineValidator, type IPlateDetector, type IPlateRecognizer, type IProcessManager, type IProviderConnectionTester, type IPythonEnvironment, type IRecognitionStage, type IRecognizer, type IRecording, type IRecordingAddon, type IRecordingCoordinator, type IRecordingDb, type IRemoteAccessProvider, type IReplEngine, type IResourceExposer, type IRestreamer, type IRetention, type IScopedLogger, type ISessionTracker, type ISiren, type IStatusLight, type IStorageBackend, type IStorageLocation, type IStorageProvider, type IStorageProviderLegacy, type IStreamBroker, type IStreamBrokerManager, type IStreamSourceAdapter, type IStreamingEngine, type IStructuredStorage, type ISubDetectionStage, type ISubDetector, type ISwitch, type ITaskHandler, type IToastService, type ITrackTrail, type ITrackerStage, type ITurnProvider, type ITwoWayAudio, type IWebRtcProvider, type IZoneAnalysisStage, type IZoneRepository, type KnownAudioEvent, type KnownFace, type KnownFaceEntry, type KnownPlate, type LabelDefinition, type Landmark, type LatencyStats, type LiveEvent, type LogEntry, type LogFilter, type LogLevel, type LoggerFactory, MACRO_LABELS, type ManagedProcessStatus, type ModelCatalogEntry, type ModelDownloadOptions, type ModelDownloadResult, type ModelFormat$1 as ModelFormat, type ModelFormatEntry, type ModelOutputFormat, type MultiBenchmarkReport, type NetworkAccessStatus, type NetworkAddress, type NormalizedSource, type Notification, type ObjectSnapshotResult, type ObjectState, type PersistableEvent, type PipelineConfig, type PipelineNode, type PipelineOutputFormat, type PipelineOutputStream, type PipelineResult, type PipelineSlot, type PipelineStatus, type PipelineStatusInfo, type ProbeCapability, type ProbeResult, type ProcessConfig, type ProcessStats, type ProviderStatus, type PtzPreset, type PublicAddress, type PythonEnvReady, type PythonProbeResult, type QueryFilter, RECOGNITION_TYPES, type RecognitionResult, type RecognitionType, type RecordingSegment, type RecordingSegmentInfo, type RegisteredStream, type RemoteAccessStatus, type RemoteBenchmarkConfig, type ReplContext, type ReplResult, type ReplScope, type RequiredStep, type ResolveEngineOptions, type ResourceAuthMode, type ResourceStats, type RestreamerExposedResource, type RetentionConfig, type RetentionReport, type RolePriority, type RouteAccess, type RouteHandler, type RouteRequest, type RouteResponse, SUB_DETECTION_TYPES, type ScopedToken, type ServerModelCatalogEntry, type ModelType as ServerModelType, type ServerTrackedDetection, type SessionTrack, type SourceAdapterStatus, type SourceCapabilities, type SpatialDetection, type StepError, type StepResult, type StorageConfig, type StorageLocationConfig, type StorageLocationName, type StorageRecord, type StreamFormat, type StreamInfo, type StreamNetworkStats, type StreamOption, type StreamSource, type StreamSourceOption, type StreamStatus, type StreamingSource, type SubDetection, type SubDetectionType, type SystemEvent, type SystemInfo, type TaskContext, type TaskDispatchOptions, type TaskHandlerSecurity, type TaskProgress, type TestConnectionResult, type TimeRange, type TimeRangeOptions, type Toast, type TokenPayload, type TokenScope, type TrackCaptureConfig, type TrackDetail, type TrackFilter, type TrackMediaFile, type TrackMediaType, type TrackPosition, type TrackSnapshot, type TrackTrail, type TrackedDetection, type TrackedObjectState, type TrackedObjectSummary, type TrackingInfo, type TurnCredentials, type TurnServer, type Unsubscribe, type UserPermissions, type UserRecord, type UserRole, type ValidationIssue, type ValidationResult, type VideoFrame, type VideoFrameCallback, type ZoneDefinition, type ZoneEvent, type ZoneHistoryPoint, type ZoneLiveState, cosineSimilarity, createAnalysisContext, enrichContext, hfModelUrl };
1
+ export * from './types/io.js';
2
+ export * from './types/labels.js';
3
+ export * from './types/detection.js';
4
+ export * from './types/tracked.js';
5
+ export * from './types/events.js';
6
+ export * from './types/config.js';
7
+ export * from './types/entities.js';
8
+ export * from './types/zones.js';
9
+ export * from './types/models.js';
10
+ export * from './types/pipeline.js';
11
+ export * from './types/live-state.js';
12
+ export * from './types/analytics.js';
13
+ export type * from './types/benchmark.js';
14
+ export type { PipelineAddonSchema, PipelineModelOption, PipelineSlotSchema, PipelineSchema, PipelineDefaultStep, PipelineTemplateStep, PipelineTemplate, TemplateValidationResult, } from './types/pipeline-schema.js';
15
+ export type * from './interfaces/addon.js';
16
+ export type * from './interfaces/capability.js';
17
+ export type * from './interfaces/config-ui.js';
18
+ export type * from './interfaces/pipeline-slot.js';
19
+ export type * from './interfaces/detector.js';
20
+ export type * from './interfaces/cropper.js';
21
+ export type * from './interfaces/classifier.js';
22
+ export type * from './interfaces/refiner.js';
23
+ export type * from './interfaces/detection-addon.js';
24
+ export type * from './interfaces/inference-engine.js';
25
+ export type * from './interfaces/inference-capabilities.js';
26
+ export type * from './interfaces/repositories.js';
27
+ export type * from './interfaces/analysis.js';
28
+ export type * from './interfaces/scene-intelligence.js';
29
+ export type * from './interfaces/advanced-notifier.js';
30
+ export type * from './interfaces/python-env.js';
31
+ export type * from './interfaces/network.js';
32
+ export type * from './interfaces/router.js';
33
+ export * from './interfaces/storage-backend.js';
34
+ export type * from './interfaces/logging.js';
35
+ export type * from './interfaces/event-bus.js';
36
+ export type * from './interfaces/pipeline-runner.js';
37
+ export type * from './interfaces/auth-provider.js';
38
+ export type * from './interfaces/notification.js';
39
+ export type * from './interfaces/addon-routes.js';
40
+ export type * from './interfaces/addon-i18n.js';
41
+ export { resolveTranslation } from './interfaces/addon-i18n.js';
42
+ export type * from './interfaces/scoped-token.js';
43
+ export type * from './interfaces/task-handler.js';
44
+ export type * from './interfaces/worker-protocol.js';
45
+ export type * from './interfaces/storage.js';
46
+ export type * from './interfaces/context.js';
47
+ export type * from './interfaces/device-capability.js';
48
+ export type * from './interfaces/device.js';
49
+ export type * from './interfaces/device-provider.js';
50
+ export type * from './interfaces/device-capabilities/index.js';
51
+ export type * from './interfaces/streaming.js';
52
+ export type * from './interfaces/auth.js';
53
+ export type * from './interfaces/lifecycle.js';
54
+ export type * from './interfaces/server-network.js';
55
+ export type * from './interfaces/process.js';
56
+ export * from './interfaces/feature-flags.js';
57
+ export type * from './interfaces/agent.js';
58
+ export type * from './interfaces/agent-protocol.js';
59
+ export * from './interfaces/agent-protocol.js';
60
+ export type * from './interfaces/camera-pipeline.js';
61
+ export type * from './interfaces/server-analysis.js';
62
+ export * from './interfaces/server-analysis.js';
63
+ export type * from './interfaces/stream-broker.js';
64
+ export * from './interfaces/analysis-persistence.js';
65
+ export type * from './interfaces/restreamer.js';
66
+ export type * from './interfaces/decoder.js';
67
+ export type * from './interfaces/ffmpeg.js';
68
+ export type { ModelType as ServerModelType, ServerModelCatalogEntry, IModelCatalogProvider, } from './interfaces/model-catalog.js';
69
+ export type * from './interfaces/network-quality.js';
70
+ export type * from './interfaces/webrtc-provider.js';
71
+ export type * from './interfaces/repl.js';
72
+ export type * from './interfaces/platform.js';
73
+ export type * from './interfaces/api-shared.js';
74
+ export * from './schemas/system-settings-schemas.js';
75
+ export * from './constants.js';
76
+ export { hfModelUrl } from './utils/hf-url.js';
77
+ export { cosineSimilarity } from './utils/cosine-similarity.js';
78
+ export { COCO_80_LABELS, COCO_TO_MACRO, MACRO_LABELS, } from './catalogs/coco-classmap.js';
79
+ export type { CameraMotionConfig, CameraNativeDetectionConfig, CameraDetectionCapabilities, } from './types/camera-detection.js';
80
+ export { DeviceType, type DeviceTypeInfo, DEVICE_TYPE_INFO } from './types/device-type.js';
81
+ export type { AppRouter } from './generated/addon-api.js';
82
+ //# sourceMappingURL=index.d.ts.map