@camstack/sdk 0.1.23

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.cjs ADDED
@@ -0,0 +1,1169 @@
1
+ "use strict";
2
+ var __create = Object.create;
3
+ var __defProp = Object.defineProperty;
4
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
5
+ var __getOwnPropNames = Object.getOwnPropertyNames;
6
+ var __getProtoOf = Object.getPrototypeOf;
7
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
8
+ var __name = (target, value) => __defProp(target, "name", { value, configurable: true });
9
+ var __export = (target, all) => {
10
+ for (var name in all)
11
+ __defProp(target, name, { get: all[name], enumerable: true });
12
+ };
13
+ var __copyProps = (to, from, except, desc) => {
14
+ if (from && typeof from === "object" || typeof from === "function") {
15
+ for (let key of __getOwnPropNames(from))
16
+ if (!__hasOwnProp.call(to, key) && key !== except)
17
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
18
+ }
19
+ return to;
20
+ };
21
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
22
+ // If the importer is in node compatibility mode or this is not an ESM
23
+ // file that has been converted to a CommonJS file using a Babel-
24
+ // compatible transform (i.e. "__esModule" has not been set), then set
25
+ // "default" to the CommonJS "module.exports" for node compatibility.
26
+ isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
27
+ mod
28
+ ));
29
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
30
+
31
+ // src/index.ts
32
+ var index_exports = {};
33
+ __export(index_exports, {
34
+ BackendClient: () => BackendClient,
35
+ DEFAULT_ENABLED_CLASSES: () => DEFAULT_ENABLED_CLASSES,
36
+ DetectionClass: () => DetectionClass,
37
+ ELIGIBLE_HA_DOMAINS: () => ELIGIBLE_HA_DOMAINS,
38
+ ELIGIBLE_HA_DOMAINS_SET: () => ELIGIBLE_HA_DOMAINS_SET,
39
+ ELIGIBLE_SCRYPTED_DEVICE_TYPES: () => ELIGIBLE_SCRYPTED_DEVICE_TYPES,
40
+ ELIGIBLE_SCRYPTED_DEVICE_TYPES_SET: () => ELIGIBLE_SCRYPTED_DEVICE_TYPES_SET,
41
+ FEATURE_MATRIX: () => FEATURE_MATRIX,
42
+ HA_DOMAIN_TYPE_MAP: () => HA_DOMAIN_TYPE_MAP,
43
+ RAW_TO_CANONICAL: () => RAW_TO_CANONICAL,
44
+ SCRYPTED_TYPE_TO_CANONICAL: () => SCRYPTED_TYPE_TO_CANONICAL,
45
+ TIMELINE_PRESET_ALL: () => TIMELINE_PRESET_ALL,
46
+ TIMELINE_PRESET_CRITICAL: () => TIMELINE_PRESET_CRITICAL,
47
+ TIMELINE_PRESET_IMPORTANT: () => TIMELINE_PRESET_IMPORTANT,
48
+ animalClasses: () => animalClasses,
49
+ audioClasses: () => audioClasses,
50
+ audioLabelClasses: () => audioLabelClasses,
51
+ createBackendClient: () => createBackendClient,
52
+ defaultDetectionClasses: () => defaultDetectionClasses,
53
+ detectionClassesDefaultMap: () => detectionClassesDefaultMap,
54
+ doorbellClasses: () => doorbellClasses,
55
+ faceClasses: () => faceClasses,
56
+ getBackendRequiredFeatures: () => getBackendRequiredFeatures,
57
+ getCanonicalDeviceType: () => getCanonicalDeviceType,
58
+ getClassesForTimelinePreset: () => getClassesForTimelinePreset,
59
+ getNextEvalInterval: () => getNextEvalInterval,
60
+ getParentClass: () => getParentClass,
61
+ getParentDetectionClass: () => getParentDetectionClass,
62
+ getSourceFeatures: () => getSourceFeatures,
63
+ isAnimalClassname: () => isAnimalClassname,
64
+ isAudioClassname: () => isAudioClassname,
65
+ isDoorbellClassname: () => isDoorbellClassname,
66
+ isFaceClassname: () => isFaceClassname,
67
+ isFeatureAvailable: () => isFeatureAvailable,
68
+ isLabelDetection: () => isLabelDetection,
69
+ isMotionClassname: () => isMotionClassname,
70
+ isPackageClassname: () => isPackageClassname,
71
+ isPersonClassname: () => isPersonClassname,
72
+ isPlateClassname: () => isPlateClassname,
73
+ isSensorLabelClassname: () => isSensorLabelClassname,
74
+ isVehicleClassname: () => isVehicleClassname,
75
+ licensePlateClasses: () => licensePlateClasses,
76
+ motionClasses: () => motionClasses,
77
+ packageClasses: () => packageClasses,
78
+ personClasses: () => personClasses,
79
+ selectOptimalStream: () => selectOptimalStream,
80
+ sensorLabelClasses: () => sensorLabelClasses,
81
+ vehicleClasses: () => vehicleClasses
82
+ });
83
+ module.exports = __toCommonJS(index_exports);
84
+
85
+ // src/backend-client.ts
86
+ var import_client = require("@trpc/client");
87
+ var import_superjson = __toESM(require("superjson"), 1);
88
+ var BackendClient = class {
89
+ static {
90
+ __name(this, "BackendClient");
91
+ }
92
+ /** Raw tRPC client — for advanced usage / direct path access */
93
+ trpc;
94
+ serverUrl;
95
+ token;
96
+ wsClient = null;
97
+ constructor(config) {
98
+ this.serverUrl = config.serverUrl.replace(/\/+$/, "");
99
+ this.token = config.token;
100
+ const isBrowser = typeof window !== "undefined";
101
+ const useWs = config.useWebSocket ?? isBrowser;
102
+ const headers = /* @__PURE__ */ __name(() => {
103
+ const h = {};
104
+ if (this.token) {
105
+ h["Authorization"] = `Bearer ${this.token}`;
106
+ }
107
+ return h;
108
+ }, "headers");
109
+ if (useWs) {
110
+ const wsUrl = this.serverUrl.replace(/^http/, "ws") + "/trpc";
111
+ this.wsClient = (0, import_client.createWSClient)({
112
+ url: wsUrl,
113
+ connectionParams: /* @__PURE__ */ __name(() => ({
114
+ token: this.token
115
+ }), "connectionParams"),
116
+ retryDelayMs: /* @__PURE__ */ __name(() => 2e3, "retryDelayMs")
117
+ });
118
+ this.trpc = (0, import_client.createTRPCClient)({
119
+ links: [
120
+ (0, import_client.wsLink)({
121
+ client: this.wsClient,
122
+ transformer: import_superjson.default
123
+ })
124
+ ]
125
+ });
126
+ } else {
127
+ this.trpc = (0, import_client.createTRPCClient)({
128
+ links: [
129
+ (0, import_client.httpLink)({
130
+ url: `${this.serverUrl}/trpc`,
131
+ headers,
132
+ transformer: import_superjson.default
133
+ })
134
+ ]
135
+ });
136
+ }
137
+ }
138
+ /** Update the auth token (e.g. after login) */
139
+ setToken(token) {
140
+ this.token = token;
141
+ }
142
+ /** Close the WebSocket connection (if using WS transport) */
143
+ close() {
144
+ this.wsClient?.close();
145
+ }
146
+ // ─── Auth ──────────────────────────────────────────────────────────
147
+ async login(username, password) {
148
+ return this.trpc.auth.login.mutate({
149
+ username,
150
+ password
151
+ });
152
+ }
153
+ async getMe() {
154
+ return this.trpc.auth.me.query();
155
+ }
156
+ async logout() {
157
+ return this.trpc.auth.logout.mutate();
158
+ }
159
+ // ─── System ────────────────────────────────────────────────────────
160
+ async getSystemInfo() {
161
+ return this.trpc.system.info.query();
162
+ }
163
+ async getFeatureFlags() {
164
+ return this.trpc.system.featureFlags.query();
165
+ }
166
+ // ─── Providers ─────────────────────────────────────────────────────
167
+ async listProviders() {
168
+ return this.trpc.providers.list.query();
169
+ }
170
+ async getProvider(providerId) {
171
+ return this.trpc.providers.get.query({
172
+ id: providerId
173
+ });
174
+ }
175
+ async startProvider(providerId) {
176
+ return this.trpc.providers.start.mutate({
177
+ id: providerId
178
+ });
179
+ }
180
+ async stopProvider(providerId) {
181
+ return this.trpc.providers.stop.mutate({
182
+ id: providerId
183
+ });
184
+ }
185
+ async listProviderTypes() {
186
+ return this.trpc.providerConfig.getAvailableTypes.query();
187
+ }
188
+ // ─── Devices ───────────────────────────────────────────────────────
189
+ async listDevices() {
190
+ return this.trpc.devices.list.query();
191
+ }
192
+ async getDevice(deviceId) {
193
+ return this.trpc.devices.get.query({
194
+ id: deviceId
195
+ });
196
+ }
197
+ async discoverDevices(providerId) {
198
+ return this.trpc.devices.discoverDevices.query({
199
+ providerId
200
+ });
201
+ }
202
+ async adoptDevice(providerId, externalId) {
203
+ return this.trpc.devices.adoptDevice.mutate({
204
+ providerId,
205
+ externalId
206
+ });
207
+ }
208
+ async createDevice(providerId, config) {
209
+ return this.trpc.devices.createDevice.mutate({
210
+ providerId,
211
+ config
212
+ });
213
+ }
214
+ /** Returns the URL path for a static asset served by an addon. */
215
+ getAddonAssetUrl(addonId, assetPath) {
216
+ return `/api/addon-assets/${addonId}/${assetPath}`;
217
+ }
218
+ // ─── Addons ────────────────────────────────────────────────────────
219
+ async listAddons() {
220
+ return this.trpc.addons.list.query();
221
+ }
222
+ async getAddonConfigSchema(addonId) {
223
+ return this.trpc.addons.getConfigSchema.query({
224
+ addonId
225
+ });
226
+ }
227
+ async getAddonConfig(addonId) {
228
+ return this.trpc.addons.getConfig.query({
229
+ addonId
230
+ });
231
+ }
232
+ async updateAddonConfig(addonId, config) {
233
+ return this.trpc.addons.updateConfig.mutate({
234
+ addonId,
235
+ config
236
+ });
237
+ }
238
+ async getAddonLogs(addonId, options) {
239
+ return this.trpc.addons.getLogs.query({
240
+ addonId,
241
+ ...options
242
+ });
243
+ }
244
+ // ─── Known Faces ───────────────────────────────────────────────────
245
+ async listKnownFaces() {
246
+ return this.trpc.knownFaces.list.query();
247
+ }
248
+ async registerFace(label, cropBase64, group) {
249
+ return this.trpc.knownFaces.register.mutate({
250
+ label,
251
+ cropBase64,
252
+ group
253
+ });
254
+ }
255
+ // ─── Pipeline ──────────────────────────────────────────────────────
256
+ async listPipelines() {
257
+ return this.trpc.bridgePipeline.listAddons.query();
258
+ }
259
+ async getPipelineStatus(deviceId) {
260
+ return this.trpc.bridgePipeline.getPipeline.query({
261
+ deviceId
262
+ });
263
+ }
264
+ // ─── Agents ────────────────────────────────────────────────────────
265
+ async listAgents() {
266
+ return this.trpc.agents.listAgents.query();
267
+ }
268
+ async dispatchTask(agentId, task) {
269
+ return this.trpc.agents.dispatchTask.mutate({
270
+ capability: agentId,
271
+ input: task
272
+ });
273
+ }
274
+ async getProcessTree() {
275
+ return this.trpc.agent.processTree.query();
276
+ }
277
+ // ─── Bridge Pipeline ───────────────────────────────────────────────
278
+ async bridgeListAddons() {
279
+ return this.trpc.bridgePipeline.listAddons.query();
280
+ }
281
+ async bridgeGetPipeline(deviceId) {
282
+ return this.trpc.bridgePipeline.getPipeline.query({
283
+ deviceId
284
+ });
285
+ }
286
+ async bridgeSetPipeline(deviceId, config) {
287
+ return this.trpc.bridgePipeline.setPipeline.mutate({
288
+ deviceId,
289
+ config
290
+ });
291
+ }
292
+ async bridgeValidatePipeline(config) {
293
+ return this.trpc.bridgePipeline.validatePipeline.query(config);
294
+ }
295
+ async bridgeGetAddonConfig(addonId) {
296
+ return this.trpc.bridgePipeline.getAddonConfig.query({
297
+ addonId
298
+ });
299
+ }
300
+ async bridgeSetAddonConfig(addonId, config) {
301
+ return this.trpc.bridgePipeline.setAddonConfig.mutate({
302
+ addonId,
303
+ config
304
+ });
305
+ }
306
+ // ─── Bridge Addons ─────────────────────────────────────────────────
307
+ async bridgeListPackages() {
308
+ return this.trpc.bridgeAddons.listPackages.query();
309
+ }
310
+ async bridgeListAddonsPackages() {
311
+ return this.trpc.bridgeAddons.listAddons.query();
312
+ }
313
+ async bridgeInstallPackage(packageName, version) {
314
+ return this.trpc.bridgeAddons.installPackage.mutate({
315
+ packageName,
316
+ version
317
+ });
318
+ }
319
+ async bridgeUninstallPackage(packageName) {
320
+ return this.trpc.bridgeAddons.uninstallPackage.mutate({
321
+ packageName
322
+ });
323
+ }
324
+ // ─── Recording ─────────────────────────────────────────────────────
325
+ async getRecordingConfig(deviceId) {
326
+ return this.trpc.recording.getConfig.query({
327
+ deviceId
328
+ });
329
+ }
330
+ async getRecordingPolicy(deviceId) {
331
+ return this.trpc.recording.getPolicy.query({
332
+ deviceId
333
+ });
334
+ }
335
+ async getRecordingPolicyStatus(deviceId) {
336
+ return this.trpc.recording.getPolicyStatus.query({
337
+ deviceId
338
+ });
339
+ }
340
+ async getRecordingSegments(deviceId, streamId, startTime, endTime) {
341
+ return this.trpc.recording.getSegments.query({
342
+ deviceId,
343
+ streamId,
344
+ startTime,
345
+ endTime
346
+ });
347
+ }
348
+ // ─── Events ────────────────────────────────────────────────────────
349
+ async getEvents(deviceId, options) {
350
+ return this.trpc.events.query.query({
351
+ deviceId,
352
+ ...options
353
+ });
354
+ }
355
+ // ─── Logs ──────────────────────────────────────────────────────────
356
+ async getLogs(options) {
357
+ return this.trpc.logs.query.query(options ?? {});
358
+ }
359
+ // ─── REPL ──────────────────────────────────────────────────────────
360
+ async replEval(code, scope) {
361
+ return this.trpc.repl.execute.mutate({
362
+ code,
363
+ scope: scope ?? {
364
+ type: "system"
365
+ }
366
+ });
367
+ }
368
+ // ─── Users ─────────────────────────────────────────────────────────
369
+ async listUsers() {
370
+ return this.trpc.users.list.query();
371
+ }
372
+ async createUser(username, password, role) {
373
+ return this.trpc.users.create.mutate({
374
+ username,
375
+ password,
376
+ role
377
+ });
378
+ }
379
+ // ─── Session Tracker ───────────────────────────────────────────────
380
+ async getTrackingSessions(deviceId) {
381
+ return this.trpc.session.getActiveTracks.query({
382
+ deviceId
383
+ });
384
+ }
385
+ // ─── Processes ─────────────────────────────────────────────────────
386
+ async listProcesses() {
387
+ return this.trpc.processes.listProcesses.query();
388
+ }
389
+ async enableProvider(providerId) {
390
+ return this.trpc.processes.enableProvider.mutate({
391
+ id: providerId
392
+ });
393
+ }
394
+ async disableProvider(providerId) {
395
+ return this.trpc.processes.disableProvider.mutate({
396
+ id: providerId
397
+ });
398
+ }
399
+ // ─── Settings ──────────────────────────────────────────────────────
400
+ /** Fetch the UI schema for a single section, or all sections if omitted. */
401
+ async getSettingsSchema(section) {
402
+ return this.trpc.settings.getSchema.query({
403
+ section
404
+ });
405
+ }
406
+ async getSettings(section) {
407
+ return this.trpc.settings.get.query({
408
+ section
409
+ });
410
+ }
411
+ async updateSettings(section, data) {
412
+ return this.trpc.settings.update.mutate({
413
+ section,
414
+ data
415
+ });
416
+ }
417
+ };
418
+ function createBackendClient(config) {
419
+ return new BackendClient(config);
420
+ }
421
+ __name(createBackendClient, "createBackendClient");
422
+
423
+ // src/detection.ts
424
+ var DetectionClass = /* @__PURE__ */ (function(DetectionClass2) {
425
+ DetectionClass2["Motion"] = "motion";
426
+ DetectionClass2["Person"] = "person";
427
+ DetectionClass2["Vehicle"] = "vehicle";
428
+ DetectionClass2["Animal"] = "animal";
429
+ DetectionClass2["Audio"] = "audio";
430
+ DetectionClass2["Face"] = "face";
431
+ DetectionClass2["Plate"] = "plate";
432
+ DetectionClass2["Package"] = "package";
433
+ DetectionClass2["Doorbell"] = "doorbell";
434
+ DetectionClass2["Sensor"] = "sensor";
435
+ return DetectionClass2;
436
+ })({});
437
+ var animalClasses = [
438
+ "animal",
439
+ "dog_cat",
440
+ "dog",
441
+ "cat",
442
+ "horse",
443
+ "sheep",
444
+ "cow",
445
+ "elephant",
446
+ "bear",
447
+ "zebra",
448
+ "giraffe",
449
+ "mouse",
450
+ "rabbit",
451
+ "deer",
452
+ "lion",
453
+ "tiger",
454
+ "bird",
455
+ "eagle",
456
+ "owl",
457
+ "pigeon",
458
+ "fish",
459
+ "whale",
460
+ "dolphin",
461
+ "snake",
462
+ "turtle",
463
+ "lizard"
464
+ ];
465
+ var personClasses = [
466
+ "person",
467
+ "people",
468
+ "pedestrian",
469
+ "rider",
470
+ "driver",
471
+ "cyclist",
472
+ "skier",
473
+ "skateboarder",
474
+ "face",
475
+ "hand",
476
+ "head",
477
+ "body"
478
+ ];
479
+ var vehicleClasses = [
480
+ "vehicle",
481
+ "car",
482
+ "truck",
483
+ "bus",
484
+ "motorcycle",
485
+ "bicycle",
486
+ "van",
487
+ "ambulance",
488
+ "police_car",
489
+ "fire_truck",
490
+ "train",
491
+ "subway",
492
+ "tram",
493
+ "airplane",
494
+ "boat",
495
+ "ship",
496
+ "helicopter"
497
+ ];
498
+ var faceClasses = [
499
+ "face",
500
+ "eyes",
501
+ "nose",
502
+ "mouth",
503
+ "ears",
504
+ "eyebrows",
505
+ "left_eye",
506
+ "right_eye",
507
+ "pupil",
508
+ "iris",
509
+ "eyelid",
510
+ "eye_corner",
511
+ "upper_lip",
512
+ "lower_lip",
513
+ "teeth",
514
+ "chin",
515
+ "cheek",
516
+ "forehead",
517
+ "jaw",
518
+ "glasses",
519
+ "sunglasses",
520
+ "facial_hair",
521
+ "beard",
522
+ "mustache",
523
+ "facial_landmark",
524
+ "facial_keypoint"
525
+ ];
526
+ var licensePlateClasses = [
527
+ "plate",
528
+ "license_plate",
529
+ "front_plate",
530
+ "rear_plate",
531
+ "motorcycle_plate",
532
+ "temporary_plate",
533
+ "dealer_plate",
534
+ "licensePlate",
535
+ "plate_number",
536
+ "plate_character",
537
+ "plate_digit",
538
+ "plate_letter",
539
+ "plate_symbol",
540
+ "plate_region",
541
+ "plate_country_identifier",
542
+ "plate_frame",
543
+ "plate_bolt",
544
+ "plate_sticker",
545
+ "plate_validation_tag",
546
+ "damaged_plate",
547
+ "obscured_plate",
548
+ "dirty_plate"
549
+ ];
550
+ var motionClasses = [
551
+ "motion",
552
+ "movement",
553
+ "other"
554
+ ];
555
+ var packageClasses = [
556
+ "package",
557
+ "packet"
558
+ ];
559
+ var audioClasses = [
560
+ "audio"
561
+ ];
562
+ var audioLabelClasses = [
563
+ "speech",
564
+ "scream",
565
+ "babbling",
566
+ "yell",
567
+ "bellow",
568
+ "whoop",
569
+ "whispering",
570
+ "laughter",
571
+ "snicker",
572
+ "crying",
573
+ "cry",
574
+ "sigh",
575
+ "singing",
576
+ "choir",
577
+ "chant",
578
+ "mantra",
579
+ "child_singing",
580
+ "rapping",
581
+ "humming",
582
+ "groan",
583
+ "grunt",
584
+ "whistling",
585
+ "breathing",
586
+ "wheeze",
587
+ "snoring",
588
+ "gasp",
589
+ "pant",
590
+ "snort",
591
+ "cough",
592
+ "throat_clearing",
593
+ "sneeze",
594
+ "sniff",
595
+ "cheering",
596
+ "applause",
597
+ "chatter",
598
+ "crowd",
599
+ "children_playing",
600
+ "bark",
601
+ "yip",
602
+ "howl",
603
+ "bow-wow",
604
+ "growling",
605
+ "whimper_dog",
606
+ "purr",
607
+ "meow",
608
+ "hiss",
609
+ "caterwaul",
610
+ "pets",
611
+ "livestock",
612
+ "doorbell",
613
+ "ding-dong",
614
+ "door",
615
+ "slam",
616
+ "knock",
617
+ "alarm",
618
+ "telephone",
619
+ "music",
620
+ "dog",
621
+ "dogs"
622
+ ];
623
+ var doorbellClasses = [
624
+ "doorbell",
625
+ "ring"
626
+ ];
627
+ var sensorLabelClasses = [
628
+ "lock",
629
+ "binary",
630
+ "flood",
631
+ "entry",
632
+ "door",
633
+ "leak",
634
+ "door_open",
635
+ "flooded",
636
+ "entry_open"
637
+ ];
638
+ var detectionClassesDefaultMap = {
639
+ ...animalClasses.reduce((tot, curr) => ({
640
+ ...tot,
641
+ [curr]: "animal"
642
+ }), {}),
643
+ ...personClasses.reduce((tot, curr) => ({
644
+ ...tot,
645
+ [curr]: "person"
646
+ }), {}),
647
+ ...vehicleClasses.reduce((tot, curr) => ({
648
+ ...tot,
649
+ [curr]: "vehicle"
650
+ }), {}),
651
+ ...motionClasses.reduce((tot, curr) => ({
652
+ ...tot,
653
+ [curr]: "motion"
654
+ }), {}),
655
+ ...packageClasses.reduce((tot, curr) => ({
656
+ ...tot,
657
+ [curr]: "package"
658
+ }), {}),
659
+ ...faceClasses.reduce((tot, curr) => ({
660
+ ...tot,
661
+ [curr]: "face"
662
+ }), {}),
663
+ ...licensePlateClasses.reduce((tot, curr) => ({
664
+ ...tot,
665
+ [curr]: "plate"
666
+ }), {}),
667
+ ...audioClasses.reduce((tot, curr) => ({
668
+ ...tot,
669
+ [curr]: "audio"
670
+ }), {}),
671
+ ...audioLabelClasses.reduce((tot, curr) => ({
672
+ ...tot,
673
+ [curr]: "audio"
674
+ }), {}),
675
+ ...doorbellClasses.reduce((tot, curr) => ({
676
+ ...tot,
677
+ [curr]: "doorbell"
678
+ }), {}),
679
+ ...sensorLabelClasses.reduce((tot, curr) => ({
680
+ ...tot,
681
+ [curr]: "sensor"
682
+ }), {})
683
+ };
684
+ var isFaceClassname = /* @__PURE__ */ __name((c) => faceClasses.includes(c), "isFaceClassname");
685
+ var isPlateClassname = /* @__PURE__ */ __name((c) => licensePlateClasses.includes(c), "isPlateClassname");
686
+ var isAnimalClassname = /* @__PURE__ */ __name((c) => animalClasses.includes(c), "isAnimalClassname");
687
+ var isPersonClassname = /* @__PURE__ */ __name((c) => personClasses.includes(c), "isPersonClassname");
688
+ var isVehicleClassname = /* @__PURE__ */ __name((c) => vehicleClasses.includes(c), "isVehicleClassname");
689
+ var isMotionClassname = /* @__PURE__ */ __name((c) => motionClasses.includes(c), "isMotionClassname");
690
+ var isDoorbellClassname = /* @__PURE__ */ __name((c) => doorbellClasses.includes(c), "isDoorbellClassname");
691
+ var isPackageClassname = /* @__PURE__ */ __name((c) => packageClasses.includes(c), "isPackageClassname");
692
+ var isAudioClassname = /* @__PURE__ */ __name((c) => audioClasses.includes(c) || audioLabelClasses.includes(c), "isAudioClassname");
693
+ var isSensorLabelClassname = /* @__PURE__ */ __name((c) => sensorLabelClasses.includes(c), "isSensorLabelClassname");
694
+ var isLabelDetection = /* @__PURE__ */ __name((c) => isFaceClassname(c) || isPlateClassname(c), "isLabelDetection");
695
+ var getParentClass = /* @__PURE__ */ __name((className) => detectionClassesDefaultMap[className], "getParentClass");
696
+ var getParentDetectionClass = /* @__PURE__ */ __name((det) => {
697
+ const { className } = det;
698
+ const baseMap = {
699
+ ["face"]: "person",
700
+ ["plate"]: "vehicle"
701
+ };
702
+ const parentGroup = detectionClassesDefaultMap[className];
703
+ if (parentGroup && parentGroup !== className) return parentGroup;
704
+ return baseMap[className];
705
+ }, "getParentDetectionClass");
706
+ var defaultDetectionClasses = Object.values(DetectionClass);
707
+ var DEFAULT_ENABLED_CLASSES = defaultDetectionClasses.filter((c) => c !== "motion");
708
+ var TIMELINE_PRESET_CRITICAL = [
709
+ "person",
710
+ "doorbell",
711
+ "package"
712
+ ];
713
+ var TIMELINE_PRESET_IMPORTANT = [
714
+ ...TIMELINE_PRESET_CRITICAL,
715
+ "vehicle",
716
+ "animal",
717
+ "audio",
718
+ "face",
719
+ "plate"
720
+ ];
721
+ var TIMELINE_PRESET_ALL = [
722
+ ...DEFAULT_ENABLED_CLASSES
723
+ ];
724
+ function getClassesForTimelinePreset(preset, customClasses) {
725
+ switch (preset) {
726
+ case "critical":
727
+ return TIMELINE_PRESET_CRITICAL;
728
+ case "important":
729
+ return TIMELINE_PRESET_IMPORTANT;
730
+ case "all":
731
+ return TIMELINE_PRESET_ALL;
732
+ case "custom":
733
+ return customClasses?.length ? customClasses : DEFAULT_ENABLED_CLASSES;
734
+ default:
735
+ return DEFAULT_ENABLED_CLASSES;
736
+ }
737
+ }
738
+ __name(getClassesForTimelinePreset, "getClassesForTimelinePreset");
739
+
740
+ // src/devices.ts
741
+ var RAW_TO_CANONICAL = {
742
+ // Scrypted PascalCase
743
+ Light: "light",
744
+ Switch: "switch",
745
+ WindowCovering: "cover",
746
+ Lock: "lock",
747
+ SecuritySystem: "alarm",
748
+ Buttons: "button",
749
+ Select: "select",
750
+ Siren: "siren",
751
+ Sensor: "sensor",
752
+ Entry: "entry",
753
+ Program: "script",
754
+ MediaPlayer: "media_player",
755
+ Outlet: "switch",
756
+ // Home Assistant lowercase domains
757
+ light: "light",
758
+ switch: "switch",
759
+ input_boolean: "switch",
760
+ cover: "cover",
761
+ lock: "lock",
762
+ alarm_control_panel: "alarm",
763
+ input_button: "button",
764
+ button: "button",
765
+ input_select: "select",
766
+ select: "select",
767
+ siren: "siren",
768
+ sensor: "sensor",
769
+ media_player: "media_player",
770
+ script: "script"
771
+ };
772
+ var HA_DOMAIN_TYPE_MAP = {
773
+ light: "light",
774
+ switch: "switch",
775
+ input_boolean: "switch",
776
+ cover: "cover",
777
+ lock: "lock",
778
+ alarm_control_panel: "alarm",
779
+ input_button: "button",
780
+ button: "button",
781
+ input_select: "select",
782
+ select: "select",
783
+ siren: "siren",
784
+ sensor: "sensor",
785
+ binary_sensor: "sensor",
786
+ media_player: "media_player",
787
+ script: "script",
788
+ climate: "climate",
789
+ camera: "camera",
790
+ fan: "fan",
791
+ vacuum: "vacuum",
792
+ automation: "automation",
793
+ scene: "scene",
794
+ input_number: "sensor",
795
+ person: "person",
796
+ device_tracker: "tracker",
797
+ weather: "weather",
798
+ water_heater: "climate"
799
+ };
800
+ var SCRYPTED_TYPE_TO_CANONICAL = {
801
+ Light: "light",
802
+ Switch: "switch",
803
+ WindowCovering: "cover",
804
+ Lock: "lock",
805
+ SecuritySystem: "alarm",
806
+ Buttons: "button",
807
+ Select: "select",
808
+ Siren: "siren",
809
+ Sensor: "sensor",
810
+ Entry: "entry",
811
+ Program: "script",
812
+ MediaPlayer: "media_player",
813
+ Camera: "camera",
814
+ Doorbell: "doorbell",
815
+ Fan: "fan",
816
+ Outlet: "switch"
817
+ };
818
+ function getCanonicalDeviceType(rawType) {
819
+ const canonical = RAW_TO_CANONICAL[rawType];
820
+ if (canonical) return canonical;
821
+ const lower = rawType.toLowerCase();
822
+ return RAW_TO_CANONICAL[lower] ?? null;
823
+ }
824
+ __name(getCanonicalDeviceType, "getCanonicalDeviceType");
825
+ var ELIGIBLE_SCRYPTED_DEVICE_TYPES = [
826
+ "Entry",
827
+ "Light",
828
+ "Switch",
829
+ "Lock",
830
+ "SecuritySystem",
831
+ "Buttons",
832
+ "WindowCovering",
833
+ "Siren",
834
+ "Sensor",
835
+ "Select",
836
+ "Program"
837
+ ];
838
+ var ELIGIBLE_SCRYPTED_DEVICE_TYPES_SET = new Set(ELIGIBLE_SCRYPTED_DEVICE_TYPES);
839
+ var ELIGIBLE_HA_DOMAINS = [
840
+ "light",
841
+ "switch",
842
+ "input_boolean",
843
+ "cover",
844
+ "lock",
845
+ "alarm_control_panel",
846
+ "input_button",
847
+ "button",
848
+ "input_select",
849
+ "select",
850
+ "siren",
851
+ "media_player",
852
+ "script"
853
+ ];
854
+ var ELIGIBLE_HA_DOMAINS_SET = new Set(ELIGIBLE_HA_DOMAINS);
855
+
856
+ // src/features.ts
857
+ var FEATURE_MATRIX = [
858
+ {
859
+ id: "liveStream",
860
+ label: "Live Stream",
861
+ sources: {
862
+ frigate: true,
863
+ scrypted: true,
864
+ rtsp: true
865
+ },
866
+ adapterMethod: "getLiveStream"
867
+ },
868
+ {
869
+ id: "multiResolution",
870
+ label: "Multi-Resolution",
871
+ sources: {
872
+ frigate: true,
873
+ scrypted: true,
874
+ rtsp: false
875
+ },
876
+ adapterMethod: "getResolutions"
877
+ },
878
+ {
879
+ id: "motion",
880
+ label: "Motion Detection",
881
+ sources: {
882
+ frigate: false,
883
+ scrypted: true,
884
+ rtsp: false
885
+ },
886
+ adapterMethod: "getMotion"
887
+ },
888
+ {
889
+ id: "objectDetection",
890
+ label: "Object Detection",
891
+ sources: {
892
+ frigate: false,
893
+ scrypted: true,
894
+ rtsp: false
895
+ },
896
+ adapterMethod: "getObjectDetections"
897
+ },
898
+ {
899
+ id: "audioVolume",
900
+ label: "Audio Level",
901
+ sources: {
902
+ frigate: false,
903
+ scrypted: true,
904
+ rtsp: false
905
+ },
906
+ adapterMethod: "getAudioVolume"
907
+ },
908
+ {
909
+ id: "audioVolumes",
910
+ label: "Audio Volumes (dBFS)",
911
+ sources: {
912
+ frigate: false,
913
+ scrypted: true,
914
+ rtsp: false
915
+ },
916
+ adapterMethod: "getAudioVolumes"
917
+ },
918
+ {
919
+ id: "ptz",
920
+ label: "PTZ Control",
921
+ sources: {
922
+ frigate: false,
923
+ scrypted: true,
924
+ rtsp: false
925
+ },
926
+ adapterMethod: "getPTZ"
927
+ },
928
+ {
929
+ id: "intercom",
930
+ label: "Intercom (Mic)",
931
+ sources: {
932
+ frigate: false,
933
+ scrypted: true,
934
+ rtsp: false
935
+ },
936
+ adapterMethod: "getIntercomSupport"
937
+ },
938
+ {
939
+ id: "deviceStatus",
940
+ label: "Device Status",
941
+ sources: {
942
+ frigate: false,
943
+ scrypted: true,
944
+ rtsp: false
945
+ },
946
+ adapterMethod: "getStatus"
947
+ },
948
+ {
949
+ id: "timeline",
950
+ label: "Detection Timeline",
951
+ sources: {
952
+ frigate: true,
953
+ scrypted: true,
954
+ rtsp: false
955
+ },
956
+ adapterMethod: "getCameraDayData"
957
+ },
958
+ {
959
+ id: "clusteredTimeline",
960
+ label: "Clustered Timeline",
961
+ sources: {
962
+ frigate: true,
963
+ scrypted: true,
964
+ rtsp: false
965
+ },
966
+ requiresBackend: true,
967
+ adapterMethod: "getClusteredDayData"
968
+ },
969
+ {
970
+ id: "detectionClasses",
971
+ label: "Detection Classes",
972
+ sources: {
973
+ frigate: true,
974
+ scrypted: true,
975
+ rtsp: false
976
+ },
977
+ adapterMethod: "getDetectionClasses"
978
+ },
979
+ {
980
+ id: "videoClips",
981
+ label: "Video Clips",
982
+ sources: {
983
+ frigate: true,
984
+ scrypted: true,
985
+ rtsp: false
986
+ },
987
+ adapterMethod: "getVideoClips"
988
+ },
989
+ {
990
+ id: "nvrPlayback",
991
+ label: "NVR Playback",
992
+ sources: {
993
+ frigate: true,
994
+ scrypted: true,
995
+ rtsp: false
996
+ },
997
+ adapterMethod: "getNvrPlaybackSupported"
998
+ },
999
+ {
1000
+ id: "nvrScrub",
1001
+ label: "NVR Scrub/Seek",
1002
+ sources: {
1003
+ frigate: false,
1004
+ scrypted: true,
1005
+ rtsp: false
1006
+ },
1007
+ adapterMethod: "seekRecordingStream"
1008
+ },
1009
+ {
1010
+ id: "recordingThumbnail",
1011
+ label: "Recording Thumbnails",
1012
+ sources: {
1013
+ frigate: true,
1014
+ scrypted: true,
1015
+ rtsp: false
1016
+ },
1017
+ adapterMethod: "getRecordingStreamThumbnail"
1018
+ },
1019
+ {
1020
+ id: "nvrSeekToLive",
1021
+ label: "Seek to Live",
1022
+ sources: {
1023
+ frigate: false,
1024
+ scrypted: true,
1025
+ rtsp: false
1026
+ },
1027
+ adapterMethod: "seekNvrToLive"
1028
+ }
1029
+ ];
1030
+ function isFeatureAvailable(featureId, source, platform) {
1031
+ const entry = FEATURE_MATRIX.find((f) => f.id === featureId);
1032
+ if (!entry) return false;
1033
+ if (!entry.sources[source]) return false;
1034
+ if (entry.platforms && entry.platforms[platform] === false) return false;
1035
+ return true;
1036
+ }
1037
+ __name(isFeatureAvailable, "isFeatureAvailable");
1038
+ function getSourceFeatures(source) {
1039
+ return FEATURE_MATRIX.filter((f) => f.sources[source]);
1040
+ }
1041
+ __name(getSourceFeatures, "getSourceFeatures");
1042
+ function getBackendRequiredFeatures() {
1043
+ return FEATURE_MATRIX.filter((f) => f.requiresBackend);
1044
+ }
1045
+ __name(getBackendRequiredFeatures, "getBackendRequiredFeatures");
1046
+
1047
+ // src/adaptive-stream.ts
1048
+ function selectOptimalStream(streams, constraints, defaultTransport) {
1049
+ if (streams.length === 0) return null;
1050
+ const viewportPixels = constraints.viewportWidth * constraints.viewportHeight * (constraints.pixelRatio ?? 1);
1051
+ const bw = constraints.bandwidthMbps ?? 100;
1052
+ const loss = constraints.packetLoss ?? 0;
1053
+ const rtt = constraints.rttMs ?? 50;
1054
+ let targetTier = "high";
1055
+ if (constraints.maxResolution === "low" || constraints.isCellular || bw < 1 || loss > 0.05) {
1056
+ targetTier = "low";
1057
+ } else if (constraints.maxResolution === "medium" || bw < 5 || viewportPixels < 5e5 || rtt > 200) {
1058
+ targetTier = "medium";
1059
+ } else if (constraints.maxResolution === "high" || viewportPixels > 2e6) {
1060
+ targetTier = "high";
1061
+ }
1062
+ const PROFILE_TIER = {
1063
+ main: "high",
1064
+ sub: "medium",
1065
+ ext: "low"
1066
+ };
1067
+ const preferTransport = defaultTransport ?? "native";
1068
+ const scored = streams.map((s) => {
1069
+ let score = 0;
1070
+ const streamTier = PROFILE_TIER[s.profile] ?? "medium";
1071
+ if (streamTier === targetTier) score += 100;
1072
+ else if (targetTier === "high" && streamTier === "medium" || targetTier === "medium" && streamTier === "high" || targetTier === "medium" && streamTier === "low" || targetTier === "low" && streamTier === "medium") score += 50;
1073
+ if (s.transport === preferTransport) score += 30;
1074
+ else if (s.transport === "native") score += 20;
1075
+ else if (s.transport === "rtsp") score += 15;
1076
+ else if (s.transport === "rtmp") score += 10;
1077
+ if (s.metadata?.width && s.metadata?.height) {
1078
+ const streamPixels = s.metadata.width * s.metadata.height;
1079
+ const ratio = streamPixels / Math.max(viewportPixels, 1);
1080
+ if (ratio >= 0.8 && ratio <= 2) score += 25;
1081
+ else if (ratio >= 0.5 && ratio <= 3) score += 15;
1082
+ if (ratio > 4 && bw < 10) score -= 20;
1083
+ }
1084
+ if (s.metadata?.codec) {
1085
+ if (bw < 5 && s.metadata.codec.includes("265")) score += 10;
1086
+ if (bw >= 10 && s.metadata.codec.includes("264")) score += 5;
1087
+ }
1088
+ return {
1089
+ ...s,
1090
+ score,
1091
+ targetTier
1092
+ };
1093
+ });
1094
+ scored.sort((a, b) => b.score - a.score);
1095
+ const best = scored[0];
1096
+ const tierNames = {
1097
+ high: "main",
1098
+ medium: "sub",
1099
+ low: "ext"
1100
+ };
1101
+ return {
1102
+ streamName: best.streamName,
1103
+ profile: best.profile,
1104
+ transport: best.transport,
1105
+ label: best.label,
1106
+ metadata: best.metadata,
1107
+ reason: `${best.targetTier} quality \u2192 ${best.profile}/${best.transport} (score: ${best.score})`
1108
+ };
1109
+ }
1110
+ __name(selectOptimalStream, "selectOptimalStream");
1111
+ function getNextEvalInterval(constraints, wasSwitch) {
1112
+ if (wasSwitch) return 10;
1113
+ if (constraints.isCellular) return 15;
1114
+ if ((constraints.packetLoss ?? 0) > 0.02) return 15;
1115
+ return 30;
1116
+ }
1117
+ __name(getNextEvalInterval, "getNextEvalInterval");
1118
+ // Annotate the CommonJS export names for ESM import in node:
1119
+ 0 && (module.exports = {
1120
+ BackendClient,
1121
+ DEFAULT_ENABLED_CLASSES,
1122
+ DetectionClass,
1123
+ ELIGIBLE_HA_DOMAINS,
1124
+ ELIGIBLE_HA_DOMAINS_SET,
1125
+ ELIGIBLE_SCRYPTED_DEVICE_TYPES,
1126
+ ELIGIBLE_SCRYPTED_DEVICE_TYPES_SET,
1127
+ FEATURE_MATRIX,
1128
+ HA_DOMAIN_TYPE_MAP,
1129
+ RAW_TO_CANONICAL,
1130
+ SCRYPTED_TYPE_TO_CANONICAL,
1131
+ TIMELINE_PRESET_ALL,
1132
+ TIMELINE_PRESET_CRITICAL,
1133
+ TIMELINE_PRESET_IMPORTANT,
1134
+ animalClasses,
1135
+ audioClasses,
1136
+ audioLabelClasses,
1137
+ createBackendClient,
1138
+ defaultDetectionClasses,
1139
+ detectionClassesDefaultMap,
1140
+ doorbellClasses,
1141
+ faceClasses,
1142
+ getBackendRequiredFeatures,
1143
+ getCanonicalDeviceType,
1144
+ getClassesForTimelinePreset,
1145
+ getNextEvalInterval,
1146
+ getParentClass,
1147
+ getParentDetectionClass,
1148
+ getSourceFeatures,
1149
+ isAnimalClassname,
1150
+ isAudioClassname,
1151
+ isDoorbellClassname,
1152
+ isFaceClassname,
1153
+ isFeatureAvailable,
1154
+ isLabelDetection,
1155
+ isMotionClassname,
1156
+ isPackageClassname,
1157
+ isPersonClassname,
1158
+ isPlateClassname,
1159
+ isSensorLabelClassname,
1160
+ isVehicleClassname,
1161
+ licensePlateClasses,
1162
+ motionClasses,
1163
+ packageClasses,
1164
+ personClasses,
1165
+ selectOptimalStream,
1166
+ sensorLabelClasses,
1167
+ vehicleClasses
1168
+ });
1169
+ //# sourceMappingURL=index.cjs.map