@camstack/addon-provider-rademacher 0.2.22 → 0.2.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.
Files changed (3) hide show
  1. package/dist/addon.js +138 -56
  2. package/dist/addon.mjs +138 -56
  3. package/package.json +1 -1
package/dist/addon.js CHANGED
@@ -8551,7 +8551,7 @@ var RecordingBandSchema = object({
8551
8551
  postBufferSec: number().min(0).optional()
8552
8552
  });
8553
8553
  ({
8554
- preBufferSec: 10,
8554
+ preBufferSec: 15,
8555
8555
  postBufferSec: 30
8556
8556
  }).postBufferSec * 1e3;
8557
8557
  /**
@@ -14754,128 +14754,103 @@ var COCO_TO_MACRO = {
14754
14754
  var AUDIO_MACRO_LABELS = [
14755
14755
  {
14756
14756
  id: "speech",
14757
- name: "Speech",
14758
- icon: "🗣️"
14757
+ name: "Speech"
14759
14758
  },
14760
14759
  {
14761
14760
  id: "scream",
14762
- name: "Scream / Shout",
14763
- icon: "😱"
14761
+ name: "Scream / Shout"
14764
14762
  },
14765
14763
  {
14766
14764
  id: "crying",
14767
- name: "Crying / Baby",
14768
- icon: "😢"
14765
+ name: "Crying / Baby"
14769
14766
  },
14770
14767
  {
14771
14768
  id: "laughter",
14772
- name: "Laughter",
14773
- icon: "😂"
14769
+ name: "Laughter"
14774
14770
  },
14775
14771
  {
14776
14772
  id: "music",
14777
- name: "Music",
14778
- icon: "🎵"
14773
+ name: "Music"
14779
14774
  },
14780
14775
  {
14781
14776
  id: "dog",
14782
- name: "Dog",
14783
- icon: "🐕"
14777
+ name: "Dog"
14784
14778
  },
14785
14779
  {
14786
14780
  id: "cat",
14787
- name: "Cat",
14788
- icon: "🐈"
14781
+ name: "Cat"
14789
14782
  },
14790
14783
  {
14791
14784
  id: "bird",
14792
- name: "Bird",
14793
- icon: "🐦"
14785
+ name: "Bird"
14794
14786
  },
14795
14787
  {
14796
14788
  id: "animal",
14797
- name: "Animal (other)",
14798
- icon: "🐾"
14789
+ name: "Animal (other)"
14799
14790
  },
14800
14791
  {
14801
14792
  id: "alarm",
14802
- name: "Alarm / Siren",
14803
- icon: "🚨"
14793
+ name: "Alarm / Siren"
14804
14794
  },
14805
14795
  {
14806
14796
  id: "doorbell",
14807
- name: "Doorbell / Knock",
14808
- icon: "🔔"
14797
+ name: "Doorbell / Knock"
14809
14798
  },
14810
14799
  {
14811
14800
  id: "glass_breaking",
14812
- name: "Glass Breaking",
14813
- icon: "💥"
14801
+ name: "Glass Breaking"
14814
14802
  },
14815
14803
  {
14816
14804
  id: "gunshot",
14817
- name: "Gunshot / Explosion",
14818
- icon: "💣"
14805
+ name: "Gunshot / Explosion"
14819
14806
  },
14820
14807
  {
14821
14808
  id: "vehicle",
14822
- name: "Vehicle",
14823
- icon: "🚗"
14809
+ name: "Vehicle"
14824
14810
  },
14825
14811
  {
14826
14812
  id: "siren",
14827
- name: "Emergency Siren",
14828
- icon: "🚑"
14813
+ name: "Emergency Siren"
14829
14814
  },
14830
14815
  {
14831
14816
  id: "fire",
14832
- name: "Fire / Smoke",
14833
- icon: "🔥"
14817
+ name: "Fire / Smoke"
14834
14818
  },
14835
14819
  {
14836
14820
  id: "water",
14837
- name: "Water",
14838
- icon: "💧"
14821
+ name: "Water"
14839
14822
  },
14840
14823
  {
14841
14824
  id: "wind",
14842
- name: "Wind / Weather",
14843
- icon: "🌬️"
14825
+ name: "Wind / Weather"
14844
14826
  },
14845
14827
  {
14846
14828
  id: "door",
14847
- name: "Door",
14848
- icon: "🚪"
14829
+ name: "Door"
14849
14830
  },
14850
14831
  {
14851
14832
  id: "footsteps",
14852
- name: "Footsteps",
14853
- icon: "👣"
14833
+ name: "Footsteps"
14854
14834
  },
14855
14835
  {
14856
14836
  id: "crowd",
14857
- name: "Crowd / Chatter",
14858
- icon: "👥"
14837
+ name: "Crowd / Chatter"
14859
14838
  },
14860
14839
  {
14861
14840
  id: "telephone",
14862
- name: "Telephone",
14863
- icon: "📞"
14841
+ name: "Telephone"
14864
14842
  },
14865
14843
  {
14866
14844
  id: "engine",
14867
- name: "Engine / Motor",
14868
- icon: "⚙️"
14845
+ name: "Engine / Motor"
14869
14846
  },
14870
14847
  {
14871
14848
  id: "tools",
14872
- name: "Tools / Construction",
14873
- icon: "🔨"
14849
+ name: "Tools / Construction"
14874
14850
  },
14875
14851
  {
14876
14852
  id: "silence",
14877
- name: "Silence",
14878
- icon: "🤫"
14853
+ name: "Silence"
14879
14854
  }
14880
14855
  ];
14881
14856
  var YAMNET_TO_MACRO = {
@@ -17377,7 +17352,7 @@ var TrackEnvelopeSchema = object({
17377
17352
  * `snapshots[]` references — megabytes across a page of tracks. `slim`
17378
17353
  * keeps every scalar the list surfaces actually render (ids, class(es),
17379
17354
  * label / audioLabels / importance enrichment, firstSeen/lastSeen, state,
17380
- * zonesVisited, bestEventId, envelope, hasFace, hasRider) and returns `positions` /
17355
+ * zonesVisited, bestEventId, envelope, hasFace, hasEmbeddedFace, hasRider) and returns `positions` /
17381
17356
  * `snapshots` as EMPTY arrays — detail views re-fetch the full row via
17382
17357
  * `getTrack`. Mirrors the event-store `projection` convention
17383
17358
  * (`getObjectEvents` et al.).
@@ -17672,6 +17647,35 @@ var TrackSchema = object({
17672
17647
  */
17673
17648
  hasFace: boolean().optional(),
17674
17649
  /**
17650
+ * This track has a face row IN THE GALLERY: a crop **and** an embedding — a
17651
+ * face an operator could ASSIGN to an identity.
17652
+ *
17653
+ * The STRICT twin of {@link hasFace}, and the pair only earns its keep
17654
+ * because the two disagree. `hasFace` is stamped at the TOP of the face
17655
+ * branch, before every gate, and means no more than "a face detector produced
17656
+ * a face detail". This one is stamped at the single moment the gallery row
17657
+ * LANDS — after `FaceRecognizer.onTrackEnd` successfully persists it, i.e.
17658
+ * past the embedding-magnitude verdict, the `minFacePx` detection gate, the
17659
+ * candidate gate, the imageless-track drop (no crop was ever captured) and
17660
+ * the crop-store drop. Everything between the detector and that insert can
17661
+ * legitimately refuse the face, so a flag written any earlier promises the
17662
+ * operator something to assign and delivers nothing.
17663
+ *
17664
+ * **Independent of recognition.** A face collected but never auto-matched is
17665
+ * still assignable — it is in fact the face an operator most wants to reach —
17666
+ * so this is NOT gated on `recognizedIdentityId`. Recognition lands in
17667
+ * `subLabel`; this says only that the raw material exists.
17668
+ *
17669
+ * **Set once, never cleared.** A track that produced a gallery row produced
17670
+ * one; deleting the row later is the gallery's business, not this flag's.
17671
+ *
17672
+ * **Absent ≠ false**, the same rule as {@link hasFace}: every row written
17673
+ * before the column omits it, and so does every server that predates the
17674
+ * field. A consumer must test `=== true` and render nothing otherwise —
17675
+ * never infer "no assignable face".
17676
+ */
17677
+ hasEmbeddedFace: boolean().optional(),
17678
+ /**
17675
17679
  * This subject CONTAINS a folded rider — a person the rider-pairing step
17676
17680
  * ([D34](../decisions/adr-0034.md)) removed from the frame BEFORE the tracker,
17677
17681
  * so the passage is tracked once and as a VEHICLE.
@@ -19061,6 +19065,32 @@ var DetailResultSchema = object({
19061
19065
  /** FRAME-space bbox (already mapped back from crop space). */
19062
19066
  bbox: NativeCropBboxSchema.optional(),
19063
19067
  embedding: string().optional(),
19068
+ /**
19069
+ * L2 magnitude of the RAW pre-normalization embedding. Additive and optional
19070
+ * so an older runner that does not send it degrades to "unmeasurable", which
19071
+ * the consuming gate treats as accept — never as reject.
19072
+ */
19073
+ embeddingMagnitude: number().optional(),
19074
+ /**
19075
+ * Model that produced `embedding` — the SAME contract `labelModelId` has for
19076
+ * `label`, and for the same reason: the producing node is the only side that
19077
+ * knows which model actually ran, and re-deriving it downstream is exactly
19078
+ * the inference this model exists to forbid.
19079
+ *
19080
+ * Additive and optional, so a runner that predates it degrades to
19081
+ * "unmeasurable" rather than to a wrong answer — the consumer falls back to
19082
+ * its previous assumption instead of refusing.
19083
+ *
19084
+ * Its absence was not cosmetic. `FaceRecognizer` needs the probe's model id
19085
+ * to use `face-matcher`'s same-model gate (`sample.modelId !== probe.modelId`);
19086
+ * with nothing on the wire it took the id from the GALLERY, so the gate
19087
+ * compared the gallery against itself and could never fire. That turned the
19088
+ * one guard protecting the face feature space into a tautology, and it is
19089
+ * why swapping `face-embedding`'s model would NOT have stranded the enrolled
19090
+ * gallery as the catalog comment predicts — it would have scored the new
19091
+ * model's vectors against the old model's samples in one cosine space.
19092
+ */
19093
+ embeddingModelId: string().optional(),
19064
19094
  label: string().optional(),
19065
19095
  /**
19066
19096
  * The tier `label` occupies, copied VERBATIM from the producing step's
@@ -20471,6 +20501,7 @@ DeviceType.Camera, method(object({
20471
20501
  isBattery: boolean(),
20472
20502
  reason: _enum([
20473
20503
  "disabled",
20504
+ "offline",
20474
20505
  "sleeping",
20475
20506
  "unreachable",
20476
20507
  "waking"
@@ -20516,9 +20547,17 @@ targets: array(object({
20516
20547
  sleeping: boolean(),
20517
20548
  /** Current device state rendered over the cached frame. State images
20518
20549
  * remain authoritative even when their photographic background is
20519
- * old; null means the link must carry a current camera frame. */
20550
+ * old; null means the link must carry a current camera frame.
20551
+ *
20552
+ * **This is the ONLY source a surface may derive an inactive tile
20553
+ * from.** A client that reads a device's `online`/`disabled` flags and
20554
+ * draws its own verdict will disagree with the pixels it is painting
20555
+ * — the frame comes from here, and so must the sentence over it
20556
+ * (D190). Pair with `ageMs` for the age of the photograph behind the
20557
+ * state. */
20520
20558
  stateReason: _enum([
20521
20559
  "disabled",
20560
+ "offline",
20522
20561
  "sleeping",
20523
20562
  "unreachable",
20524
20563
  "waking"
@@ -38061,7 +38100,6 @@ var NC_AUDIO_DEFAULTS = {
38061
38100
  hitPercent: 60,
38062
38101
  samplingSeconds: 10
38063
38102
  };
38064
- new Map(AUDIO_MACRO_LABELS.flatMap((macro) => macro.icon === void 0 ? [] : [[macro.id, macro.icon]]));
38065
38103
  new Set(["devices", "classes"]);
38066
38104
  NC_AUDIO_DEFAULTS.hitPercent, NC_AUDIO_DEFAULTS.samplingSeconds;
38067
38105
  /**
@@ -38295,6 +38333,39 @@ TimelapseRuleInputSchema.extend({
38295
38333
  createdAt: number(),
38296
38334
  updatedAt: number()
38297
38335
  });
38336
+ Object.freeze(Object.fromEntries([{
38337
+ stepId: "face-embedding",
38338
+ label: "Face recognition model",
38339
+ defaultModelId: "arcface-r100",
38340
+ indexName: "the enrolled face gallery",
38341
+ options: [
38342
+ {
38343
+ id: "arcface-r100",
38344
+ label: "ArcFace (ResNet34)"
38345
+ },
38346
+ {
38347
+ id: "auraface-r100",
38348
+ label: "AuraFace R100"
38349
+ },
38350
+ {
38351
+ id: "inception-resnet-v1",
38352
+ label: "Inception ResNet V1"
38353
+ }
38354
+ ]
38355
+ }, {
38356
+ stepId: "clip-embedding",
38357
+ label: "Semantic search model",
38358
+ defaultModelId: "mobileclip-s1",
38359
+ indexName: "the object semantic-search index",
38360
+ options: [{
38361
+ id: "mobileclip-s1",
38362
+ label: "MobileCLIP S1"
38363
+ }, {
38364
+ id: "mobileclip-s2",
38365
+ label: "MobileCLIP S2"
38366
+ }]
38367
+ }].map((s) => [s.stepId, s.defaultModelId])));
38368
+ string().min(1);
38298
38369
  object({
38299
38370
  /**
38300
38371
  * Fraction of the box's own size added on EACH side before cutting.
@@ -38315,10 +38386,21 @@ object({
38315
38386
  */
38316
38387
  square: boolean()
38317
38388
  });
38318
- ({
38389
+ /**
38390
+ * The convention in force when nobody has configured one — byte-for-byte the
38391
+ * behaviour of the pre-unification LIVE path (`DETAIL_CROP_PADDING_RATIO`).
38392
+ */
38393
+ var DEFAULT_DETAIL_CROP_CONVENTION = {
38319
38394
  paddingRatio: .15,
38320
38395
  square: false
38321
- }).paddingRatio;
38396
+ };
38397
+ Object.freeze({
38398
+ x: 0,
38399
+ y: 0,
38400
+ w: 1,
38401
+ h: 1
38402
+ });
38403
+ DEFAULT_DETAIL_CROP_CONVENTION.paddingRatio;
38322
38404
  /**
38323
38405
  * WHICH delivered frames the decode worker retains a native copy of.
38324
38406
  *
package/dist/addon.mjs CHANGED
@@ -8550,7 +8550,7 @@ var RecordingBandSchema = object({
8550
8550
  postBufferSec: number().min(0).optional()
8551
8551
  });
8552
8552
  ({
8553
- preBufferSec: 10,
8553
+ preBufferSec: 15,
8554
8554
  postBufferSec: 30
8555
8555
  }).postBufferSec * 1e3;
8556
8556
  /**
@@ -14753,128 +14753,103 @@ var COCO_TO_MACRO = {
14753
14753
  var AUDIO_MACRO_LABELS = [
14754
14754
  {
14755
14755
  id: "speech",
14756
- name: "Speech",
14757
- icon: "🗣️"
14756
+ name: "Speech"
14758
14757
  },
14759
14758
  {
14760
14759
  id: "scream",
14761
- name: "Scream / Shout",
14762
- icon: "😱"
14760
+ name: "Scream / Shout"
14763
14761
  },
14764
14762
  {
14765
14763
  id: "crying",
14766
- name: "Crying / Baby",
14767
- icon: "😢"
14764
+ name: "Crying / Baby"
14768
14765
  },
14769
14766
  {
14770
14767
  id: "laughter",
14771
- name: "Laughter",
14772
- icon: "😂"
14768
+ name: "Laughter"
14773
14769
  },
14774
14770
  {
14775
14771
  id: "music",
14776
- name: "Music",
14777
- icon: "🎵"
14772
+ name: "Music"
14778
14773
  },
14779
14774
  {
14780
14775
  id: "dog",
14781
- name: "Dog",
14782
- icon: "🐕"
14776
+ name: "Dog"
14783
14777
  },
14784
14778
  {
14785
14779
  id: "cat",
14786
- name: "Cat",
14787
- icon: "🐈"
14780
+ name: "Cat"
14788
14781
  },
14789
14782
  {
14790
14783
  id: "bird",
14791
- name: "Bird",
14792
- icon: "🐦"
14784
+ name: "Bird"
14793
14785
  },
14794
14786
  {
14795
14787
  id: "animal",
14796
- name: "Animal (other)",
14797
- icon: "🐾"
14788
+ name: "Animal (other)"
14798
14789
  },
14799
14790
  {
14800
14791
  id: "alarm",
14801
- name: "Alarm / Siren",
14802
- icon: "🚨"
14792
+ name: "Alarm / Siren"
14803
14793
  },
14804
14794
  {
14805
14795
  id: "doorbell",
14806
- name: "Doorbell / Knock",
14807
- icon: "🔔"
14796
+ name: "Doorbell / Knock"
14808
14797
  },
14809
14798
  {
14810
14799
  id: "glass_breaking",
14811
- name: "Glass Breaking",
14812
- icon: "💥"
14800
+ name: "Glass Breaking"
14813
14801
  },
14814
14802
  {
14815
14803
  id: "gunshot",
14816
- name: "Gunshot / Explosion",
14817
- icon: "💣"
14804
+ name: "Gunshot / Explosion"
14818
14805
  },
14819
14806
  {
14820
14807
  id: "vehicle",
14821
- name: "Vehicle",
14822
- icon: "🚗"
14808
+ name: "Vehicle"
14823
14809
  },
14824
14810
  {
14825
14811
  id: "siren",
14826
- name: "Emergency Siren",
14827
- icon: "🚑"
14812
+ name: "Emergency Siren"
14828
14813
  },
14829
14814
  {
14830
14815
  id: "fire",
14831
- name: "Fire / Smoke",
14832
- icon: "🔥"
14816
+ name: "Fire / Smoke"
14833
14817
  },
14834
14818
  {
14835
14819
  id: "water",
14836
- name: "Water",
14837
- icon: "💧"
14820
+ name: "Water"
14838
14821
  },
14839
14822
  {
14840
14823
  id: "wind",
14841
- name: "Wind / Weather",
14842
- icon: "🌬️"
14824
+ name: "Wind / Weather"
14843
14825
  },
14844
14826
  {
14845
14827
  id: "door",
14846
- name: "Door",
14847
- icon: "🚪"
14828
+ name: "Door"
14848
14829
  },
14849
14830
  {
14850
14831
  id: "footsteps",
14851
- name: "Footsteps",
14852
- icon: "👣"
14832
+ name: "Footsteps"
14853
14833
  },
14854
14834
  {
14855
14835
  id: "crowd",
14856
- name: "Crowd / Chatter",
14857
- icon: "👥"
14836
+ name: "Crowd / Chatter"
14858
14837
  },
14859
14838
  {
14860
14839
  id: "telephone",
14861
- name: "Telephone",
14862
- icon: "📞"
14840
+ name: "Telephone"
14863
14841
  },
14864
14842
  {
14865
14843
  id: "engine",
14866
- name: "Engine / Motor",
14867
- icon: "⚙️"
14844
+ name: "Engine / Motor"
14868
14845
  },
14869
14846
  {
14870
14847
  id: "tools",
14871
- name: "Tools / Construction",
14872
- icon: "🔨"
14848
+ name: "Tools / Construction"
14873
14849
  },
14874
14850
  {
14875
14851
  id: "silence",
14876
- name: "Silence",
14877
- icon: "🤫"
14852
+ name: "Silence"
14878
14853
  }
14879
14854
  ];
14880
14855
  var YAMNET_TO_MACRO = {
@@ -17376,7 +17351,7 @@ var TrackEnvelopeSchema = object({
17376
17351
  * `snapshots[]` references — megabytes across a page of tracks. `slim`
17377
17352
  * keeps every scalar the list surfaces actually render (ids, class(es),
17378
17353
  * label / audioLabels / importance enrichment, firstSeen/lastSeen, state,
17379
- * zonesVisited, bestEventId, envelope, hasFace, hasRider) and returns `positions` /
17354
+ * zonesVisited, bestEventId, envelope, hasFace, hasEmbeddedFace, hasRider) and returns `positions` /
17380
17355
  * `snapshots` as EMPTY arrays — detail views re-fetch the full row via
17381
17356
  * `getTrack`. Mirrors the event-store `projection` convention
17382
17357
  * (`getObjectEvents` et al.).
@@ -17671,6 +17646,35 @@ var TrackSchema = object({
17671
17646
  */
17672
17647
  hasFace: boolean().optional(),
17673
17648
  /**
17649
+ * This track has a face row IN THE GALLERY: a crop **and** an embedding — a
17650
+ * face an operator could ASSIGN to an identity.
17651
+ *
17652
+ * The STRICT twin of {@link hasFace}, and the pair only earns its keep
17653
+ * because the two disagree. `hasFace` is stamped at the TOP of the face
17654
+ * branch, before every gate, and means no more than "a face detector produced
17655
+ * a face detail". This one is stamped at the single moment the gallery row
17656
+ * LANDS — after `FaceRecognizer.onTrackEnd` successfully persists it, i.e.
17657
+ * past the embedding-magnitude verdict, the `minFacePx` detection gate, the
17658
+ * candidate gate, the imageless-track drop (no crop was ever captured) and
17659
+ * the crop-store drop. Everything between the detector and that insert can
17660
+ * legitimately refuse the face, so a flag written any earlier promises the
17661
+ * operator something to assign and delivers nothing.
17662
+ *
17663
+ * **Independent of recognition.** A face collected but never auto-matched is
17664
+ * still assignable — it is in fact the face an operator most wants to reach —
17665
+ * so this is NOT gated on `recognizedIdentityId`. Recognition lands in
17666
+ * `subLabel`; this says only that the raw material exists.
17667
+ *
17668
+ * **Set once, never cleared.** A track that produced a gallery row produced
17669
+ * one; deleting the row later is the gallery's business, not this flag's.
17670
+ *
17671
+ * **Absent ≠ false**, the same rule as {@link hasFace}: every row written
17672
+ * before the column omits it, and so does every server that predates the
17673
+ * field. A consumer must test `=== true` and render nothing otherwise —
17674
+ * never infer "no assignable face".
17675
+ */
17676
+ hasEmbeddedFace: boolean().optional(),
17677
+ /**
17674
17678
  * This subject CONTAINS a folded rider — a person the rider-pairing step
17675
17679
  * ([D34](../decisions/adr-0034.md)) removed from the frame BEFORE the tracker,
17676
17680
  * so the passage is tracked once and as a VEHICLE.
@@ -19060,6 +19064,32 @@ var DetailResultSchema = object({
19060
19064
  /** FRAME-space bbox (already mapped back from crop space). */
19061
19065
  bbox: NativeCropBboxSchema.optional(),
19062
19066
  embedding: string().optional(),
19067
+ /**
19068
+ * L2 magnitude of the RAW pre-normalization embedding. Additive and optional
19069
+ * so an older runner that does not send it degrades to "unmeasurable", which
19070
+ * the consuming gate treats as accept — never as reject.
19071
+ */
19072
+ embeddingMagnitude: number().optional(),
19073
+ /**
19074
+ * Model that produced `embedding` — the SAME contract `labelModelId` has for
19075
+ * `label`, and for the same reason: the producing node is the only side that
19076
+ * knows which model actually ran, and re-deriving it downstream is exactly
19077
+ * the inference this model exists to forbid.
19078
+ *
19079
+ * Additive and optional, so a runner that predates it degrades to
19080
+ * "unmeasurable" rather than to a wrong answer — the consumer falls back to
19081
+ * its previous assumption instead of refusing.
19082
+ *
19083
+ * Its absence was not cosmetic. `FaceRecognizer` needs the probe's model id
19084
+ * to use `face-matcher`'s same-model gate (`sample.modelId !== probe.modelId`);
19085
+ * with nothing on the wire it took the id from the GALLERY, so the gate
19086
+ * compared the gallery against itself and could never fire. That turned the
19087
+ * one guard protecting the face feature space into a tautology, and it is
19088
+ * why swapping `face-embedding`'s model would NOT have stranded the enrolled
19089
+ * gallery as the catalog comment predicts — it would have scored the new
19090
+ * model's vectors against the old model's samples in one cosine space.
19091
+ */
19092
+ embeddingModelId: string().optional(),
19063
19093
  label: string().optional(),
19064
19094
  /**
19065
19095
  * The tier `label` occupies, copied VERBATIM from the producing step's
@@ -20470,6 +20500,7 @@ DeviceType.Camera, method(object({
20470
20500
  isBattery: boolean(),
20471
20501
  reason: _enum([
20472
20502
  "disabled",
20503
+ "offline",
20473
20504
  "sleeping",
20474
20505
  "unreachable",
20475
20506
  "waking"
@@ -20515,9 +20546,17 @@ targets: array(object({
20515
20546
  sleeping: boolean(),
20516
20547
  /** Current device state rendered over the cached frame. State images
20517
20548
  * remain authoritative even when their photographic background is
20518
- * old; null means the link must carry a current camera frame. */
20549
+ * old; null means the link must carry a current camera frame.
20550
+ *
20551
+ * **This is the ONLY source a surface may derive an inactive tile
20552
+ * from.** A client that reads a device's `online`/`disabled` flags and
20553
+ * draws its own verdict will disagree with the pixels it is painting
20554
+ * — the frame comes from here, and so must the sentence over it
20555
+ * (D190). Pair with `ageMs` for the age of the photograph behind the
20556
+ * state. */
20519
20557
  stateReason: _enum([
20520
20558
  "disabled",
20559
+ "offline",
20521
20560
  "sleeping",
20522
20561
  "unreachable",
20523
20562
  "waking"
@@ -38060,7 +38099,6 @@ var NC_AUDIO_DEFAULTS = {
38060
38099
  hitPercent: 60,
38061
38100
  samplingSeconds: 10
38062
38101
  };
38063
- new Map(AUDIO_MACRO_LABELS.flatMap((macro) => macro.icon === void 0 ? [] : [[macro.id, macro.icon]]));
38064
38102
  new Set(["devices", "classes"]);
38065
38103
  NC_AUDIO_DEFAULTS.hitPercent, NC_AUDIO_DEFAULTS.samplingSeconds;
38066
38104
  /**
@@ -38294,6 +38332,39 @@ TimelapseRuleInputSchema.extend({
38294
38332
  createdAt: number(),
38295
38333
  updatedAt: number()
38296
38334
  });
38335
+ Object.freeze(Object.fromEntries([{
38336
+ stepId: "face-embedding",
38337
+ label: "Face recognition model",
38338
+ defaultModelId: "arcface-r100",
38339
+ indexName: "the enrolled face gallery",
38340
+ options: [
38341
+ {
38342
+ id: "arcface-r100",
38343
+ label: "ArcFace (ResNet34)"
38344
+ },
38345
+ {
38346
+ id: "auraface-r100",
38347
+ label: "AuraFace R100"
38348
+ },
38349
+ {
38350
+ id: "inception-resnet-v1",
38351
+ label: "Inception ResNet V1"
38352
+ }
38353
+ ]
38354
+ }, {
38355
+ stepId: "clip-embedding",
38356
+ label: "Semantic search model",
38357
+ defaultModelId: "mobileclip-s1",
38358
+ indexName: "the object semantic-search index",
38359
+ options: [{
38360
+ id: "mobileclip-s1",
38361
+ label: "MobileCLIP S1"
38362
+ }, {
38363
+ id: "mobileclip-s2",
38364
+ label: "MobileCLIP S2"
38365
+ }]
38366
+ }].map((s) => [s.stepId, s.defaultModelId])));
38367
+ string().min(1);
38297
38368
  object({
38298
38369
  /**
38299
38370
  * Fraction of the box's own size added on EACH side before cutting.
@@ -38314,10 +38385,21 @@ object({
38314
38385
  */
38315
38386
  square: boolean()
38316
38387
  });
38317
- ({
38388
+ /**
38389
+ * The convention in force when nobody has configured one — byte-for-byte the
38390
+ * behaviour of the pre-unification LIVE path (`DETAIL_CROP_PADDING_RATIO`).
38391
+ */
38392
+ var DEFAULT_DETAIL_CROP_CONVENTION = {
38318
38393
  paddingRatio: .15,
38319
38394
  square: false
38320
- }).paddingRatio;
38395
+ };
38396
+ Object.freeze({
38397
+ x: 0,
38398
+ y: 0,
38399
+ w: 1,
38400
+ h: 1
38401
+ });
38402
+ DEFAULT_DETAIL_CROP_CONVENTION.paddingRatio;
38321
38403
  /**
38322
38404
  * WHICH delivered frames the decode worker retains a native copy of.
38323
38405
  *
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@camstack/addon-provider-rademacher",
3
- "version": "0.2.22",
3
+ "version": "0.2.23",
4
4
  "description": "Rademacher HomePilot device-provider addon for CamStack — wraps the @apocaliss92/noderademacher local-hub client (roller shutters over the cover cap)",
5
5
  "keywords": [
6
6
  "camstack",