@camstack/types 1.2.188 → 1.2.189

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.js CHANGED
@@ -1,6 +1,6 @@
1
1
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
- const require_sleep = require("./sleep-DXsYD0RX.js");
3
- const require_event_category = require("./event-category-yW4s1MGD.js");
2
+ const require_sleep = require("./sleep-D7dV-FZB.js");
3
+ const require_event_category = require("./event-category-BVfsrBYA.js");
4
4
  const require_canonical_hash = require("./canonical-hash-9lydiEzx.js");
5
5
  const require_enums = require("./enums.js");
6
6
  const require_err_msg = require("./err-msg-COpsHMw2.js");
@@ -394,6 +394,84 @@ function encodeProfileFromStreamShape(stream) {
394
394
  };
395
395
  }
396
396
  //#endregion
397
+ //#region src/camera/stream-pick.ts
398
+ /**
399
+ * THE target rule: which of two sizes serves a consumer better.
400
+ *
401
+ * "Prefer at or above the target so the consumer downscales instead of
402
+ * upscaling; among those the SMALLEST, because the extra pixels are thrown
403
+ * away and the decode is not; among the rest the LARGEST, because it is the
404
+ * closest we can get." One sentence, and until now it was written twice — once
405
+ * here in lines, once in `stream-selection.ts` in pixels, for the same two
406
+ * exporters. The two agreed, which is luck, not a property.
407
+ *
408
+ * The `size` is whatever measure the caller ranks by: the cap ranks by LINES
409
+ * (a consumer's requirement is stated in p), the RTSP picker by PIXELS (it
410
+ * compares entries of possibly different aspect). The rule is the same either
411
+ * way and the measure is the caller's business.
412
+ *
413
+ * Returns a sort delta: negative when `a` should come first.
414
+ */
415
+ function compareToTarget(a, b, target) {
416
+ const aReaches = a >= target;
417
+ if (aReaches !== b >= target) return aReaches ? -1 : 1;
418
+ return aReaches ? a - b : b - a;
419
+ }
420
+ /** `h265` and `hevc` are one codec spelled two ways, and a camera publishes
421
+ * whichever its vendor felt like. */
422
+ function canonicalCodec(value) {
423
+ const v = value.toLowerCase().replace(/[.\s-]/g, "");
424
+ if (v === "hevc" || v === "hvc1" || v === "hev1") return "h265";
425
+ if (v === "avc" || v === "avc1") return "h264";
426
+ return v;
427
+ }
428
+ function codecIsAccepted(codec, accept) {
429
+ if (accept.length === 0) return true;
430
+ if (codec === void 0) return false;
431
+ const c = canonicalCodec(codec);
432
+ return accept.some((a) => canonicalCodec(a) === c);
433
+ }
434
+ function providerRank(camStreamId, preferred) {
435
+ for (let i = 0; i < preferred.length; i += 1) if (camStreamId.startsWith(preferred[i])) return i;
436
+ return preferred.length;
437
+ }
438
+ /**
439
+ * Order the candidates and return the winner, or `null` when none qualifies.
440
+ *
441
+ * The order, and every term is there for a measured reason:
442
+ *
443
+ * 1. **A stream we can take AS IS beats one we must re-encode.** A transcode
444
+ * is a decode plus an encode for as long as the session lasts, and on this
445
+ * hub a concurrent HEVC decode is what exhausted the VAAPI device.
446
+ * 2. **Provider preference**, unchanged — a native dial beats a relayed one.
447
+ * 3. **The target**, when the consumer named one: the smallest stream that
448
+ * reaches it, else the tallest that does not. Absent, the caller's
449
+ * `resolutionPreference` decides, exactly as before.
450
+ */
451
+ function rankStreams(candidates, ranking) {
452
+ const usable = candidates.filter((c) => ranking.allowTranscode || codecIsAccepted(c.codec, ranking.acceptCodecs));
453
+ if (usable.length === 0) return null;
454
+ const target = ranking.targetHeight;
455
+ const scored = usable.map((candidate) => ({
456
+ candidate,
457
+ transcodes: !codecIsAccepted(candidate.codec, ranking.acceptCodecs),
458
+ provider: providerRank(candidate.camStreamId, ranking.preferredProviders),
459
+ height: candidate.height ?? 0
460
+ }));
461
+ scored.sort((a, b) => {
462
+ if (a.transcodes !== b.transcodes) return a.transcodes ? 1 : -1;
463
+ if (a.provider !== b.provider) return a.provider - b.provider;
464
+ if (target !== void 0) return compareToTarget(a.height, b.height, target);
465
+ return ranking.resolutionPreference === "highest" ? b.height - a.height : a.height - b.height;
466
+ });
467
+ const winner = scored[0];
468
+ if (winner === void 0) return null;
469
+ return {
470
+ candidate: winner.candidate,
471
+ transcodes: winner.transcodes
472
+ };
473
+ }
474
+ //#endregion
397
475
  //#region src/ffmpeg/encode-defaults.ts
398
476
  /**
399
477
  * The shape every live egress starts from: H.264 Baseline 3.1 at 720p25.
@@ -4519,6 +4597,47 @@ function reducePoints(points, bucketMs, origin) {
4519
4597
  }
4520
4598
  //#endregion
4521
4599
  //#region src/stream-selection.ts
4600
+ /**
4601
+ * Shared stream-selection picker for export addons.
4602
+ *
4603
+ * Both `addon-export-alexa` and `addon-export-hap` resolve the
4604
+ * operator's `streamPreference` setting against the broker's RTSP
4605
+ * entries before dialling a camera. Each addon used to roll its own:
4606
+ * Alexa had `pickPreferredRtspEntry` under `handlers/`, HAP had an
4607
+ * inline `"prefer /mid, then /high, then first"` chain inside its
4608
+ * camera-streams mapper. The chains drifted (Alexa honoured
4609
+ * `streamPreference`, HAP didn't; only Alexa got the smart
4610
+ * resolution-targeted auto-pick) and the cross-addon import rule
4611
+ * blocks deduping in either direction.
4612
+ *
4613
+ * Lifting the picker into `@camstack/types` lets every exporter call
4614
+ * the same code path with the consumer's target resolution baked into
4615
+ * the call site — Alexa passes 1280×720, HomeKit passes 1920×1080,
4616
+ * the picker handles the rest.
4617
+ *
4618
+ * Selection algorithm:
4619
+ * - pref === '<profile>' → profile-keyed entries (from
4620
+ * `getProfileRtspEntries`) match on `e.profile`;
4621
+ * legacy raw entries match on the brokerId
4622
+ * suffix (`brokerId` ENDS WITH `/${pref}`, shape
4623
+ * `${deviceId}/${camStreamId}`). Addons store the
4624
+ * bare profile/camStream id in their
4625
+ * `ExportDeviceSettings.streamPreference`. Falls
4626
+ * back to 'auto' when no enabled entry matches
4627
+ * either way.
4628
+ * - pref === 'auto' → when `targetResolution` is given, pick the
4629
+ * entry whose source resolution is closest to
4630
+ * it (prefer ≥ target so the consumer
4631
+ * downscales instead of upscaling). Without a
4632
+ * target, fall back to first-enabled. If no
4633
+ * entry advertises a resolution at all
4634
+ * (broker hasn't probed yet), also fall back
4635
+ * to first-enabled so cold start still serves.
4636
+ *
4637
+ * Returns `null` when nothing is publishable — callers fold that into
4638
+ * the consumer's "no stream" error (Alexa: STREAM_TYPE_UNSUPPORTED;
4639
+ * HAP: a thrown error inside `startFfmpegForSession`).
4640
+ */
4522
4641
  function pickPreferredRtspEntry(entries, pref, deviceId, options = {}) {
4523
4642
  if (entries.length === 0) return null;
4524
4643
  const prefix = `${deviceId}/`;
@@ -4548,30 +4667,23 @@ function pickPreferredRtspEntry(entries, pref, deviceId, options = {}) {
4548
4667
  return toPicked(eligible[0]);
4549
4668
  }
4550
4669
  /**
4551
- * Pick the entry whose `resolution` is closest to `target`. Prefer
4552
- * entries ≥ target (downscale is cheap at the consumer; upscale is
4553
- * lossy). Among the rest pick the LARGEST still ≤ target so the
4554
- * consumer gets the best feasible quality. "Closeness" is the
4555
- * `width × height` pixel delta.
4670
+ * Pick the entry whose `resolution` is closest to `target`, by the ONE target
4671
+ * rule ({@link compareToTarget}): prefer at or above the target so the consumer
4672
+ * downscales instead of upscaling; among those the smallest; among the rest the
4673
+ * largest.
4674
+ *
4675
+ * This function used to implement that rule itself, in pixels, while
4676
+ * `rankStreams` implemented it again in lines — the same sentence written twice
4677
+ * for the same two exporters, agreeing by luck rather than by construction.
4678
+ * Only the MEASURE is this picker's own: it compares whole pixel counts because
4679
+ * its entries can differ in aspect, where the cap's requirement is stated in p.
4556
4680
  */
4557
4681
  function pickClosestResolution(entries, target) {
4558
4682
  const targetPixels = target.width * target.height;
4559
- let bestAbove;
4560
- let bestBelow;
4561
- for (const e of entries) {
4562
- if (e.resolution === void 0) continue;
4563
- const pixels = e.resolution.width * e.resolution.height;
4564
- if (pixels >= targetPixels) {
4565
- if (!bestAbove || pixels < bestAbove.pixels) bestAbove = {
4566
- entry: e,
4567
- pixels
4568
- };
4569
- } else if (!bestBelow || pixels > bestBelow.pixels) bestBelow = {
4570
- entry: e,
4571
- pixels
4572
- };
4573
- }
4574
- return bestAbove?.entry ?? bestBelow?.entry;
4683
+ return [...entries.flatMap((entry) => entry.resolution === void 0 ? [] : [{
4684
+ entry,
4685
+ pixels: entry.resolution.width * entry.resolution.height
4686
+ }])].sort((a, b) => compareToTarget(a.pixels, b.pixels, targetPixels))[0]?.entry;
4575
4687
  }
4576
4688
  //#endregion
4577
4689
  //#region src/types/model-variant-groups.ts
@@ -8199,6 +8311,74 @@ var cameraPipelineConfigCapability = {
8199
8311
  methods: {}
8200
8312
  };
8201
8313
  //#endregion
8314
+ //#region src/capabilities/stream-signals.cap.ts
8315
+ /**
8316
+ * The signals a device can emit to WAKE its own stream.
8317
+ *
8318
+ * A camera whose stream is built on demand sleeps until something asks for it,
8319
+ * and "something" cannot be a consumer that is merely attached — a Frigate-style
8320
+ * puller holds a session open for ever, and treating that as demand would keep
8321
+ * a battery camera awake for ever, which is the whole thing the battery is for
8322
+ * (D173). So the wake has to come from the CAMERA: an event it noticed by
8323
+ * itself, with no stream running.
8324
+ *
8325
+ * ## The vocabulary is the PROVIDER'S, not ours
8326
+ *
8327
+ * Like `consumables`, this cap declares no vocabulary of its own. A provider
8328
+ * names each signal with a `code` it chooses and a `label` an operator reads.
8329
+ * Reolink offers motion and camera-native detection; another provider may offer
8330
+ * a tamper, a doorbell press, a PIR, or something no camera in this fleet has
8331
+ * yet. A fixed enum here would mean every new signal is a framework release.
8332
+ *
8333
+ * It is deliberately NOT derived from the caps a device already binds. Whether
8334
+ * a camera CAN push firmware motion is expressed by `motionSources` containing
8335
+ * `'onboard'`, and whether it does AI on-camera by the `native-object-detection`
8336
+ * binding — but both answer "what drives the detection pipeline", which is a
8337
+ * different question from "what may wake a sleeping stream". A camera can do
8338
+ * the first and not be trusted with the second, and the operator picks per
8339
+ * camera. Two questions, two authorities.
8340
+ *
8341
+ * ## Availability is not permission
8342
+ *
8343
+ * `listSignals` says what the device CAN emit. Whether a given signal actually
8344
+ * wakes the stream is the operator's per-camera choice, held by the broker
8345
+ * alongside the cooldown — see the stream-broker cap's wake settings. A
8346
+ * provider declaring a signal is not a provider enabling it.
8347
+ */
8348
+ /** One signal a device can emit. */
8349
+ var StreamSignalSchema = zod.z.object({
8350
+ /** Stable id chosen by the provider, e.g. `'motion'`, `'person'`, `'tamper'`. */
8351
+ code: zod.z.string().min(1),
8352
+ /** What an operator reads in the picker. The provider's own wording. */
8353
+ label: zod.z.string().min(1),
8354
+ /**
8355
+ * Whether the provider recommends this signal ON when a camera is first set
8356
+ * up. A provider knows which of its signals are cheap and reliable; an
8357
+ * operator should not have to discover that by trial. Reolink recommends
8358
+ * both of its own.
8359
+ */
8360
+ recommended: zod.z.boolean()
8361
+ });
8362
+ var StreamSignalsStatusSchema = zod.z.object({
8363
+ signals: zod.z.array(StreamSignalSchema),
8364
+ lastFetchedAt: zod.z.number()
8365
+ });
8366
+ var streamSignalsCapability = {
8367
+ name: "stream-signals",
8368
+ scope: "device",
8369
+ deviceNative: true,
8370
+ mode: "singleton",
8371
+ deviceTypes: Object.values(require_sleep.DeviceType),
8372
+ runtimeState: StreamSignalsStatusSchema,
8373
+ methods: {
8374
+ /**
8375
+ * What this device can emit. Empty is a valid and common answer — most
8376
+ * cameras have nothing to offer here, and an empty list is what makes the
8377
+ * broker's picker show nothing rather than a false choice.
8378
+ */
8379
+ listSignals: require_sleep.method(zod.z.void(), zod.z.array(StreamSignalSchema).readonly()) }
8380
+ };
8381
+ //#endregion
8202
8382
  //#region src/capabilities/stream-broker.cap.ts
8203
8383
  /** Stream delivery format. (Relocated from the retired `streaming-engine` cap.) */
8204
8384
  var StreamFormatSchema = zod.z.enum([
@@ -8609,6 +8789,46 @@ var streamBrokerCapability = {
8609
8789
  mode: "singleton",
8610
8790
  exposesDeviceSettings: true,
8611
8791
  methods: {
8792
+ /**
8793
+ * A device reporting that one of ITS OWN signals just fired.
8794
+ *
8795
+ * The provider calls this; nothing polls. The broker then decides whether
8796
+ * to wake the source, and the decision has two terms that must BOTH hold:
8797
+ *
8798
+ * - the signal is ENABLED for this camera (the operator's per-camera
8799
+ * choice — a camera may declare a signal the operator does not want
8800
+ * waking anything), and
8801
+ * - a consumer is actually attached and waiting on the prestream. Waking
8802
+ * a camera nobody is watching is the one thing a battery camera must
8803
+ * never do, and a signal arriving with no consumer is exactly that.
8804
+ *
8805
+ * Reported, never inferred: a signal that fires while the stream is
8806
+ * already up refreshes the hold instead of starting a second one, which is
8807
+ * what makes continuous motion keep a camera awake without stacking
8808
+ * timers.
8809
+ *
8810
+ * `code` is the provider's own, from `streamSignals.listSignals`. An
8811
+ * unknown code is REFUSED rather than treated as a wildcard wake — a
8812
+ * provider and an operator disagreeing about a name must not become a
8813
+ * camera that wakes for everything.
8814
+ */
8815
+ reportStreamSignal: require_sleep.method(zod.z.object({
8816
+ deviceId: zod.z.number().int().nonnegative(),
8817
+ /** The provider's signal code. */
8818
+ code: zod.z.string().min(1),
8819
+ /** Ms epoch. Absent ⇒ now. */
8820
+ at: zod.z.number().optional()
8821
+ }), zod.z.object({
8822
+ /** Whether the broker acted on it, and if not, why. */
8823
+ accepted: zod.z.boolean(),
8824
+ reason: zod.z.enum([
8825
+ "woke",
8826
+ "hold-extended",
8827
+ "not-enabled",
8828
+ "no-consumer",
8829
+ "unknown-code"
8830
+ ])
8831
+ }), { kind: "mutation" }),
8612
8832
  publishCameraStream: require_sleep.method(zod.z.object({
8613
8833
  deviceId: zod.z.number().int().nonnegative(),
8614
8834
  camStreamId: zod.z.string().min(1),
@@ -9086,6 +9306,16 @@ var PickStreamRequirementsSchema = zod.z.object({
9086
9306
  acceptCodecs: zod.z.array(StreamCodecSchema).readonly().optional(),
9087
9307
  /** Minimum vertical resolution. Streams shorter than this are dropped. */
9088
9308
  minHeight: zod.z.number().int().positive().optional(),
9309
+ /**
9310
+ * Maximum vertical resolution. Streams TALLER than this are dropped.
9311
+ *
9312
+ * A consumer can have a ceiling as real as its floor: Alexa documents
9313
+ * 480p to 1080p, and a 4K stream is as unusable to an Echo as a 360p one.
9314
+ * Without this the ceiling had to be re-implemented by every caller — and
9315
+ * one caller implementing it privately is how a second scoring authority
9316
+ * gets born.
9317
+ */
9318
+ maxHeight: zod.z.number().int().positive().optional(),
9089
9319
  /** Minimum horizontal resolution. */
9090
9320
  minWidth: zod.z.number().int().positive().optional(),
9091
9321
  /**
@@ -9102,7 +9332,22 @@ var PickStreamRequirementsSchema = zod.z.object({
9102
9332
  * transcoded" guard: if the device is already serving the consumer's
9103
9333
  * codec end-to-end, there's nothing to optimise.
9104
9334
  */
9105
- requireSiblingCodec: zod.z.array(StreamCodecSchema).readonly().optional()
9335
+ requireSiblingCodec: zod.z.array(StreamCodecSchema).readonly().optional(),
9336
+ /**
9337
+ * Whether a stream the consumer CANNOT decode may still be picked, on the
9338
+ * understanding that it will be transcoded.
9339
+ *
9340
+ * Default `false` — today's behaviour, and the right one for a bypass
9341
+ * question ("is there a stream I can forward untouched?"). Set `true` to
9342
+ * ask the larger question: "what is the best stream for me, transcoding if
9343
+ * I must?" A stream that satisfies `acceptCodecs` always outranks one that
9344
+ * does not, so a passthrough is never lost to a transcode; the answer says
9345
+ * which it is in {@link PickedCamStreamSchema.transcodes}.
9346
+ *
9347
+ * This is what lets one picker serve both the bypass and the full source
9348
+ * choice, instead of a consumer scoring privately when the bypass misses.
9349
+ */
9350
+ allowTranscode: zod.z.boolean().optional()
9106
9351
  }).readonly();
9107
9352
  var PickStreamPreferencesSchema = zod.z.object({
9108
9353
  /**
@@ -9116,12 +9361,32 @@ var PickStreamPreferencesSchema = zod.z.object({
9116
9361
  * picks the tallest stream; `'lowest'` picks the shortest (used by
9117
9362
  * memory-constrained consumers / Apple Home guest sessions).
9118
9363
  */
9119
- resolutionPreference: zod.z.enum(["highest", "lowest"]).optional()
9364
+ resolutionPreference: zod.z.enum(["highest", "lowest"]).optional(),
9365
+ /**
9366
+ * The height the consumer actually wants to DELIVER.
9367
+ *
9368
+ * Not a constraint — an ordering. With it set, the SMALLEST stream at or
9369
+ * above the target wins, and only if nothing reaches it does the tallest
9370
+ * take over. Pulling 1296 lines to draw 720 on a 1280x800 Echo panel costs
9371
+ * a decode and buys nothing, and `resolutionPreference: 'highest'` cannot
9372
+ * express that: it says "as big as possible", which is a different wish.
9373
+ *
9374
+ * Ignored when absent, so every existing caller keeps its ordering.
9375
+ */
9376
+ targetHeight: zod.z.number().int().positive().optional()
9120
9377
  }).readonly();
9121
9378
  var PickedCamStreamSchema = zod.z.object({
9122
9379
  camStreamId: zod.z.string(),
9123
9380
  codec: zod.z.string().optional(),
9124
9381
  resolution: require_sleep.CamStreamResolutionSchema.optional(),
9382
+ /**
9383
+ * Whether serving this stream requires a decode + re-encode.
9384
+ *
9385
+ * `false` is a stream the consumer can take as it stands. Only ever `true`
9386
+ * when the caller asked for it with `allowTranscode`, so a caller that did
9387
+ * not ask cannot be handed a cost it never agreed to pay.
9388
+ */
9389
+ transcodes: zod.z.boolean(),
9125
9390
  /** One-line explanation of why this stream won — for logs / debug UI. */
9126
9391
  reason: zod.z.string()
9127
9392
  });
@@ -15917,6 +16182,8 @@ var NcSystemEventKindSchema = zod.z.enum([
15917
16182
  "device-enabled",
15918
16183
  "device-battery-low",
15919
16184
  "device-battery-normal",
16185
+ "device-consumable-low",
16186
+ "device-consumable-normal",
15920
16187
  "stream-online",
15921
16188
  "stream-offline",
15922
16189
  "node-online",
@@ -15935,6 +16202,7 @@ var NcSystemEventKindSchema = zod.z.enum([
15935
16202
  "addon-updated",
15936
16203
  "server-updated",
15937
16204
  "export-completed",
16205
+ "backup-completed",
15938
16206
  "camera-online",
15939
16207
  "camera-offline",
15940
16208
  "camera-disabled",
@@ -17117,10 +17385,22 @@ var NC_CONDITION_CATALOG = [
17117
17385
  value: "server-updated",
17118
17386
  label: "Server updated"
17119
17387
  },
17388
+ {
17389
+ value: "device-consumable-low",
17390
+ label: "Consumable low"
17391
+ },
17392
+ {
17393
+ value: "device-consumable-normal",
17394
+ label: "Consumable replaced"
17395
+ },
17120
17396
  {
17121
17397
  value: "export-completed",
17122
17398
  label: "Export completed"
17123
17399
  },
17400
+ {
17401
+ value: "backup-completed",
17402
+ label: "Backup completed"
17403
+ },
17124
17404
  {
17125
17405
  value: "alarm-arming",
17126
17406
  label: "Alarm arming (exit delay)"
@@ -26257,10 +26537,28 @@ var webrtcSessionCapability = {
26257
26537
  getSessionState: require_sleep.method(zod.z.object({
26258
26538
  deviceId: zod.z.number().int().nonnegative(),
26259
26539
  sessionId: zod.z.string()
26260
- }), zod.z.object({ pendingRenegotiation: zod.z.object({
26261
- target: WebrtcStreamTargetSchema,
26262
- epoch: zod.z.number()
26263
- }).nullable() }))
26540
+ }), zod.z.object({
26541
+ pendingRenegotiation: zod.z.object({
26542
+ target: WebrtcStreamTargetSchema,
26543
+ epoch: zod.z.number()
26544
+ }).nullable(),
26545
+ /**
26546
+ * Whether the session still EXISTS.
26547
+ *
26548
+ * A consumer that holds a resource for the life of a session needs to
26549
+ * be able to ask, because a session does not always end the way it
26550
+ * began. Measured on this hub 2026-09-13: an Echo that got stuck never
26551
+ * sent `SessionDisconnected`, so the Alexa exporter's
26552
+ * `releaseEgressTranscode` never ran, and a 2304x1296 HEVC to 720p
26553
+ * H.264 transcode kept running for NOBODY for more than twenty
26554
+ * minutes. The WebRTC session had logged `WebRTC session closed`
26555
+ * minutes earlier — the broker knew; the holder had no way to ask.
26556
+ *
26557
+ * `false` for a session id the provider has never heard of, which is
26558
+ * the same answer as "it ended": either way nothing is holding it up.
26559
+ */
26560
+ alive: zod.z.boolean()
26561
+ }))
26264
26562
  },
26265
26563
  /** BIG PLAN 2: declarative mount hint — read by `@camstack/system` `buildCapRouters`. */
26266
26564
  mount: { kind: "server-provided" }
@@ -38653,6 +38951,7 @@ var DEVICE_LOCAL_STATE_CAPS = {
38653
38951
  smoke: smokeCapability,
38654
38952
  streamCatalog: streamCatalogCapability,
38655
38953
  streamParams: streamParamsCapability,
38954
+ streamSignals: streamSignalsCapability,
38656
38955
  switch: switchCapability,
38657
38956
  tamper: tamperCapability,
38658
38957
  temperatureSensor: temperatureSensorCapability,
@@ -41797,6 +42096,7 @@ var CAPABILITY_NAMES = {
41797
42096
  streamBroker: "stream-broker",
41798
42097
  streamCatalog: "stream-catalog",
41799
42098
  streamParams: "stream-params",
42099
+ streamSignals: "stream-signals",
41800
42100
  switch: "switch",
41801
42101
  system: "system",
41802
42102
  tamper: "tamper",
@@ -42358,6 +42658,10 @@ var CAPABILITY_ROUTER_KEYS = [
42358
42658
  key: "streamParams",
42359
42659
  name: "stream-params"
42360
42660
  },
42661
+ {
42662
+ key: "streamSignals",
42663
+ name: "stream-signals"
42664
+ },
42361
42665
  {
42362
42666
  key: "switch",
42363
42667
  name: "switch"
@@ -42591,6 +42895,7 @@ var ALL_CAPABILITY_DEFINITIONS = [
42591
42895
  streamBrokerCapability,
42592
42896
  streamCatalogCapability,
42593
42897
  streamParamsCapability,
42898
+ streamSignalsCapability,
42594
42899
  switchCapability,
42595
42900
  systemCapability,
42596
42901
  tamperCapability,
@@ -48035,6 +48340,12 @@ var METHOD_ACCESS_MAP = Object.freeze({
48035
48340
  addonId: null,
48036
48341
  access: "create"
48037
48342
  },
48343
+ "streamBroker.reportStreamSignal": {
48344
+ capName: "stream-broker",
48345
+ capScope: "system",
48346
+ addonId: null,
48347
+ access: "create"
48348
+ },
48038
48349
  "streamBroker.restartProfile": {
48039
48350
  capName: "stream-broker",
48040
48351
  capScope: "system",
@@ -48119,6 +48430,12 @@ var METHOD_ACCESS_MAP = Object.freeze({
48119
48430
  addonId: null,
48120
48431
  access: "create"
48121
48432
  },
48433
+ "streamSignals.listSignals": {
48434
+ capName: "stream-signals",
48435
+ capScope: "device",
48436
+ addonId: null,
48437
+ access: "view"
48438
+ },
48122
48439
  "switch.setState": {
48123
48440
  capName: "switch",
48124
48441
  capScope: "device",
@@ -48923,6 +49240,7 @@ var KNOWN_CAP_NAMES = [
48923
49240
  "stream-broker",
48924
49241
  "stream-catalog",
48925
49242
  "stream-params",
49243
+ "stream-signals",
48926
49244
  "switch",
48927
49245
  "system",
48928
49246
  "terminal-session",
@@ -48990,6 +49308,7 @@ var DEVICE_CAP_NAMES = [
48990
49308
  "snapshot",
48991
49309
  "stream-catalog",
48992
49310
  "stream-params",
49311
+ "stream-signals",
48993
49312
  "switch",
48994
49313
  "update",
48995
49314
  "vacuum-control",
@@ -50760,6 +51079,11 @@ var METHOD_DEVICE_SELECTORS = Object.freeze({
50760
51079
  form: "single",
50761
51080
  optional: false
50762
51081
  }],
51082
+ "streamBroker.reportStreamSignal": [{
51083
+ name: "deviceId",
51084
+ form: "single",
51085
+ optional: false
51086
+ }],
50763
51087
  "streamBroker.restartProfile": [{
50764
51088
  name: "deviceId",
50765
51089
  form: "single",
@@ -51119,6 +51443,7 @@ var SYSTEM_SCOPE_DEVICE_METHODS = [
51119
51443
  "streamBroker.produceEventMedia",
51120
51444
  "streamBroker.publishCameraStream",
51121
51445
  "streamBroker.renderPreBufferClip",
51446
+ "streamBroker.reportStreamSignal",
51122
51447
  "streamBroker.restartProfile",
51123
51448
  "streamBroker.retractCameraStream",
51124
51449
  "streamBroker.setDeviceAudioMute",
@@ -51158,7 +51483,7 @@ function getCapsByProviderKind(kind) {
51158
51483
  //#region src/generated/runtime-state-durability.ts
51159
51484
  /**
51160
51485
  * Per-cap runtime-state policy, projected from every `*.cap.ts` that declares
51161
- * `runtimeState`. 67 caps: 35 `restored`, 32 `session`.
51486
+ * `runtimeState`. 68 caps: 35 `restored`, 33 `session`.
51162
51487
  *
51163
51488
  * A cap absent from this map has no runtime-state slice at all. A cap PRESENT
51164
51489
  * with `durability: 'session'` has one and has decided not to keep it.
@@ -51384,6 +51709,10 @@ var RUNTIME_STATE_POLICY = {
51384
51709
  durability: "restored",
51385
51710
  volatileFields: ["lastFetchedAt"]
51386
51711
  },
51712
+ "stream-signals": {
51713
+ durability: "session",
51714
+ volatileFields: []
51715
+ },
51387
51716
  "switch": {
51388
51717
  durability: "restored",
51389
51718
  volatileFields: ["lastChangedAt"]
@@ -57301,6 +57630,8 @@ exports.StreamProfileConfigSchema = StreamProfileConfigSchema;
57301
57630
  exports.StreamProfileOptionsSchema = StreamProfileOptionsSchema;
57302
57631
  exports.StreamProfilePatchSchema = StreamProfilePatchSchema;
57303
57632
  exports.StreamProfileSchema = StreamProfileSchema;
57633
+ exports.StreamSignalSchema = StreamSignalSchema;
57634
+ exports.StreamSignalsStatusSchema = StreamSignalsStatusSchema;
57304
57635
  exports.StreamSourceEntrySchema = require_sleep.StreamSourceEntrySchema;
57305
57636
  exports.StreamSourceSchema = require_sleep.StreamSourceSchema;
57306
57637
  exports.SubscribeAudioChunksInputSchema = require_sleep.SubscribeAudioChunksInputSchema;
@@ -57486,12 +57817,14 @@ exports.climateControlCapability = climateControlCapability;
57486
57817
  exports.clusterModelSettingKey = clusterModelSettingKey;
57487
57818
  exports.clusterStepSettingFieldsFor = clusterStepSettingFieldsFor;
57488
57819
  exports.clusterStepSettingKey = clusterStepSettingKey;
57820
+ exports.codecIsAccepted = codecIsAccepted;
57489
57821
  exports.collectHydratedFieldEntries = require_sleep.collectHydratedFieldEntries;
57490
57822
  exports.collectHydratedFieldValues = require_sleep.collectHydratedFieldValues;
57491
57823
  exports.collectSecretConfigKeys = collectSecretConfigKeys;
57492
57824
  exports.colorCapability = colorCapability;
57493
57825
  exports.colorForKind = colorForKind;
57494
57826
  exports.commitWatchdogRestart = commitWatchdogRestart;
57827
+ exports.compareToTarget = compareToTarget;
57495
57828
  exports.compileExpression = compileExpression;
57496
57829
  exports.compileExpressionSafe = compileExpressionSafe;
57497
57830
  exports.composeSwitchedOff = composeSwitchedOff;
@@ -57750,6 +58083,7 @@ exports.procedureAuthKey = procedureAuthKey;
57750
58083
  exports.ptzAutotrackCapability = ptzAutotrackCapability;
57751
58084
  exports.ptzCapability = ptzCapability;
57752
58085
  exports.pythonScriptForBackend = pythonScriptForBackend;
58086
+ exports.rankStreams = rankStreams;
57753
58087
  exports.readClusterStepModels = readClusterStepModels;
57754
58088
  exports.readClusterStepSettings = readClusterStepSettings;
57755
58089
  exports.readDetailCropConvention = readDetailCropConvention;
@@ -57834,6 +58168,7 @@ exports.streamCatalogCapability = streamCatalogCapability;
57834
58168
  exports.streamParamsCapability = streamParamsCapability;
57835
58169
  exports.streamPixels = streamPixels;
57836
58170
  exports.streamQualityLabel = streamQualityLabel;
58171
+ exports.streamSignalsCapability = streamSignalsCapability;
57837
58172
  exports.stripRetiredBandPreBufferSec = stripRetiredBandPreBufferSec;
57838
58173
  exports.strippedOfLegacyReadOnly = strippedOfLegacyReadOnly;
57839
58174
  exports.subKindsOf = subKindsOf;