@camstack/addon-provider-petkit 0.2.23 → 0.2.24

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
@@ -8668,7 +8668,7 @@ var RecordingBandSchema = object({
8668
8668
  postBufferSec: number().min(0).optional()
8669
8669
  });
8670
8670
  ({
8671
- preBufferSec: 10,
8671
+ preBufferSec: 15,
8672
8672
  postBufferSec: 30
8673
8673
  }).postBufferSec * 1e3;
8674
8674
  /**
@@ -14888,128 +14888,103 @@ var COCO_TO_MACRO = {
14888
14888
  var AUDIO_MACRO_LABELS = [
14889
14889
  {
14890
14890
  id: "speech",
14891
- name: "Speech",
14892
- icon: "🗣️"
14891
+ name: "Speech"
14893
14892
  },
14894
14893
  {
14895
14894
  id: "scream",
14896
- name: "Scream / Shout",
14897
- icon: "😱"
14895
+ name: "Scream / Shout"
14898
14896
  },
14899
14897
  {
14900
14898
  id: "crying",
14901
- name: "Crying / Baby",
14902
- icon: "😢"
14899
+ name: "Crying / Baby"
14903
14900
  },
14904
14901
  {
14905
14902
  id: "laughter",
14906
- name: "Laughter",
14907
- icon: "😂"
14903
+ name: "Laughter"
14908
14904
  },
14909
14905
  {
14910
14906
  id: "music",
14911
- name: "Music",
14912
- icon: "🎵"
14907
+ name: "Music"
14913
14908
  },
14914
14909
  {
14915
14910
  id: "dog",
14916
- name: "Dog",
14917
- icon: "🐕"
14911
+ name: "Dog"
14918
14912
  },
14919
14913
  {
14920
14914
  id: "cat",
14921
- name: "Cat",
14922
- icon: "🐈"
14915
+ name: "Cat"
14923
14916
  },
14924
14917
  {
14925
14918
  id: "bird",
14926
- name: "Bird",
14927
- icon: "🐦"
14919
+ name: "Bird"
14928
14920
  },
14929
14921
  {
14930
14922
  id: "animal",
14931
- name: "Animal (other)",
14932
- icon: "🐾"
14923
+ name: "Animal (other)"
14933
14924
  },
14934
14925
  {
14935
14926
  id: "alarm",
14936
- name: "Alarm / Siren",
14937
- icon: "🚨"
14927
+ name: "Alarm / Siren"
14938
14928
  },
14939
14929
  {
14940
14930
  id: "doorbell",
14941
- name: "Doorbell / Knock",
14942
- icon: "🔔"
14931
+ name: "Doorbell / Knock"
14943
14932
  },
14944
14933
  {
14945
14934
  id: "glass_breaking",
14946
- name: "Glass Breaking",
14947
- icon: "💥"
14935
+ name: "Glass Breaking"
14948
14936
  },
14949
14937
  {
14950
14938
  id: "gunshot",
14951
- name: "Gunshot / Explosion",
14952
- icon: "💣"
14939
+ name: "Gunshot / Explosion"
14953
14940
  },
14954
14941
  {
14955
14942
  id: "vehicle",
14956
- name: "Vehicle",
14957
- icon: "🚗"
14943
+ name: "Vehicle"
14958
14944
  },
14959
14945
  {
14960
14946
  id: "siren",
14961
- name: "Emergency Siren",
14962
- icon: "🚑"
14947
+ name: "Emergency Siren"
14963
14948
  },
14964
14949
  {
14965
14950
  id: "fire",
14966
- name: "Fire / Smoke",
14967
- icon: "🔥"
14951
+ name: "Fire / Smoke"
14968
14952
  },
14969
14953
  {
14970
14954
  id: "water",
14971
- name: "Water",
14972
- icon: "💧"
14955
+ name: "Water"
14973
14956
  },
14974
14957
  {
14975
14958
  id: "wind",
14976
- name: "Wind / Weather",
14977
- icon: "🌬️"
14959
+ name: "Wind / Weather"
14978
14960
  },
14979
14961
  {
14980
14962
  id: "door",
14981
- name: "Door",
14982
- icon: "🚪"
14963
+ name: "Door"
14983
14964
  },
14984
14965
  {
14985
14966
  id: "footsteps",
14986
- name: "Footsteps",
14987
- icon: "👣"
14967
+ name: "Footsteps"
14988
14968
  },
14989
14969
  {
14990
14970
  id: "crowd",
14991
- name: "Crowd / Chatter",
14992
- icon: "👥"
14971
+ name: "Crowd / Chatter"
14993
14972
  },
14994
14973
  {
14995
14974
  id: "telephone",
14996
- name: "Telephone",
14997
- icon: "📞"
14975
+ name: "Telephone"
14998
14976
  },
14999
14977
  {
15000
14978
  id: "engine",
15001
- name: "Engine / Motor",
15002
- icon: "⚙️"
14979
+ name: "Engine / Motor"
15003
14980
  },
15004
14981
  {
15005
14982
  id: "tools",
15006
- name: "Tools / Construction",
15007
- icon: "🔨"
14983
+ name: "Tools / Construction"
15008
14984
  },
15009
14985
  {
15010
14986
  id: "silence",
15011
- name: "Silence",
15012
- icon: "🤫"
14987
+ name: "Silence"
15013
14988
  }
15014
14989
  ];
15015
14990
  var YAMNET_TO_MACRO = {
@@ -17511,7 +17486,7 @@ var TrackEnvelopeSchema = object({
17511
17486
  * `snapshots[]` references — megabytes across a page of tracks. `slim`
17512
17487
  * keeps every scalar the list surfaces actually render (ids, class(es),
17513
17488
  * label / audioLabels / importance enrichment, firstSeen/lastSeen, state,
17514
- * zonesVisited, bestEventId, envelope, hasFace, hasRider) and returns `positions` /
17489
+ * zonesVisited, bestEventId, envelope, hasFace, hasEmbeddedFace, hasRider) and returns `positions` /
17515
17490
  * `snapshots` as EMPTY arrays — detail views re-fetch the full row via
17516
17491
  * `getTrack`. Mirrors the event-store `projection` convention
17517
17492
  * (`getObjectEvents` et al.).
@@ -17806,6 +17781,35 @@ var TrackSchema = object({
17806
17781
  */
17807
17782
  hasFace: boolean().optional(),
17808
17783
  /**
17784
+ * This track has a face row IN THE GALLERY: a crop **and** an embedding — a
17785
+ * face an operator could ASSIGN to an identity.
17786
+ *
17787
+ * The STRICT twin of {@link hasFace}, and the pair only earns its keep
17788
+ * because the two disagree. `hasFace` is stamped at the TOP of the face
17789
+ * branch, before every gate, and means no more than "a face detector produced
17790
+ * a face detail". This one is stamped at the single moment the gallery row
17791
+ * LANDS — after `FaceRecognizer.onTrackEnd` successfully persists it, i.e.
17792
+ * past the embedding-magnitude verdict, the `minFacePx` detection gate, the
17793
+ * candidate gate, the imageless-track drop (no crop was ever captured) and
17794
+ * the crop-store drop. Everything between the detector and that insert can
17795
+ * legitimately refuse the face, so a flag written any earlier promises the
17796
+ * operator something to assign and delivers nothing.
17797
+ *
17798
+ * **Independent of recognition.** A face collected but never auto-matched is
17799
+ * still assignable — it is in fact the face an operator most wants to reach —
17800
+ * so this is NOT gated on `recognizedIdentityId`. Recognition lands in
17801
+ * `subLabel`; this says only that the raw material exists.
17802
+ *
17803
+ * **Set once, never cleared.** A track that produced a gallery row produced
17804
+ * one; deleting the row later is the gallery's business, not this flag's.
17805
+ *
17806
+ * **Absent ≠ false**, the same rule as {@link hasFace}: every row written
17807
+ * before the column omits it, and so does every server that predates the
17808
+ * field. A consumer must test `=== true` and render nothing otherwise —
17809
+ * never infer "no assignable face".
17810
+ */
17811
+ hasEmbeddedFace: boolean().optional(),
17812
+ /**
17809
17813
  * This subject CONTAINS a folded rider — a person the rider-pairing step
17810
17814
  * ([D34](../decisions/adr-0034.md)) removed from the frame BEFORE the tracker,
17811
17815
  * so the passage is tracked once and as a VEHICLE.
@@ -19195,6 +19199,32 @@ var DetailResultSchema = object({
19195
19199
  /** FRAME-space bbox (already mapped back from crop space). */
19196
19200
  bbox: NativeCropBboxSchema.optional(),
19197
19201
  embedding: string().optional(),
19202
+ /**
19203
+ * L2 magnitude of the RAW pre-normalization embedding. Additive and optional
19204
+ * so an older runner that does not send it degrades to "unmeasurable", which
19205
+ * the consuming gate treats as accept — never as reject.
19206
+ */
19207
+ embeddingMagnitude: number().optional(),
19208
+ /**
19209
+ * Model that produced `embedding` — the SAME contract `labelModelId` has for
19210
+ * `label`, and for the same reason: the producing node is the only side that
19211
+ * knows which model actually ran, and re-deriving it downstream is exactly
19212
+ * the inference this model exists to forbid.
19213
+ *
19214
+ * Additive and optional, so a runner that predates it degrades to
19215
+ * "unmeasurable" rather than to a wrong answer — the consumer falls back to
19216
+ * its previous assumption instead of refusing.
19217
+ *
19218
+ * Its absence was not cosmetic. `FaceRecognizer` needs the probe's model id
19219
+ * to use `face-matcher`'s same-model gate (`sample.modelId !== probe.modelId`);
19220
+ * with nothing on the wire it took the id from the GALLERY, so the gate
19221
+ * compared the gallery against itself and could never fire. That turned the
19222
+ * one guard protecting the face feature space into a tautology, and it is
19223
+ * why swapping `face-embedding`'s model would NOT have stranded the enrolled
19224
+ * gallery as the catalog comment predicts — it would have scored the new
19225
+ * model's vectors against the old model's samples in one cosine space.
19226
+ */
19227
+ embeddingModelId: string().optional(),
19198
19228
  label: string().optional(),
19199
19229
  /**
19200
19230
  * The tier `label` occupies, copied VERBATIM from the producing step's
@@ -20605,6 +20635,7 @@ DeviceType.Camera, method(object({
20605
20635
  isBattery: boolean(),
20606
20636
  reason: _enum([
20607
20637
  "disabled",
20638
+ "offline",
20608
20639
  "sleeping",
20609
20640
  "unreachable",
20610
20641
  "waking"
@@ -20650,9 +20681,17 @@ targets: array(object({
20650
20681
  sleeping: boolean(),
20651
20682
  /** Current device state rendered over the cached frame. State images
20652
20683
  * remain authoritative even when their photographic background is
20653
- * old; null means the link must carry a current camera frame. */
20684
+ * old; null means the link must carry a current camera frame.
20685
+ *
20686
+ * **This is the ONLY source a surface may derive an inactive tile
20687
+ * from.** A client that reads a device's `online`/`disabled` flags and
20688
+ * draws its own verdict will disagree with the pixels it is painting
20689
+ * — the frame comes from here, and so must the sentence over it
20690
+ * (D190). Pair with `ageMs` for the age of the photograph behind the
20691
+ * state. */
20654
20692
  stateReason: _enum([
20655
20693
  "disabled",
20694
+ "offline",
20656
20695
  "sleeping",
20657
20696
  "unreachable",
20658
20697
  "waking"
@@ -38203,7 +38242,6 @@ var NC_AUDIO_DEFAULTS = {
38203
38242
  hitPercent: 60,
38204
38243
  samplingSeconds: 10
38205
38244
  };
38206
- new Map(AUDIO_MACRO_LABELS.flatMap((macro) => macro.icon === void 0 ? [] : [[macro.id, macro.icon]]));
38207
38245
  new Set(["devices", "classes"]);
38208
38246
  NC_AUDIO_DEFAULTS.hitPercent, NC_AUDIO_DEFAULTS.samplingSeconds;
38209
38247
  /**
@@ -38437,6 +38475,39 @@ TimelapseRuleInputSchema.extend({
38437
38475
  createdAt: number(),
38438
38476
  updatedAt: number()
38439
38477
  });
38478
+ Object.freeze(Object.fromEntries([{
38479
+ stepId: "face-embedding",
38480
+ label: "Face recognition model",
38481
+ defaultModelId: "arcface-r100",
38482
+ indexName: "the enrolled face gallery",
38483
+ options: [
38484
+ {
38485
+ id: "arcface-r100",
38486
+ label: "ArcFace (ResNet34)"
38487
+ },
38488
+ {
38489
+ id: "auraface-r100",
38490
+ label: "AuraFace R100"
38491
+ },
38492
+ {
38493
+ id: "inception-resnet-v1",
38494
+ label: "Inception ResNet V1"
38495
+ }
38496
+ ]
38497
+ }, {
38498
+ stepId: "clip-embedding",
38499
+ label: "Semantic search model",
38500
+ defaultModelId: "mobileclip-s1",
38501
+ indexName: "the object semantic-search index",
38502
+ options: [{
38503
+ id: "mobileclip-s1",
38504
+ label: "MobileCLIP S1"
38505
+ }, {
38506
+ id: "mobileclip-s2",
38507
+ label: "MobileCLIP S2"
38508
+ }]
38509
+ }].map((s) => [s.stepId, s.defaultModelId])));
38510
+ string().min(1);
38440
38511
  object({
38441
38512
  /**
38442
38513
  * Fraction of the box's own size added on EACH side before cutting.
@@ -38457,10 +38528,21 @@ object({
38457
38528
  */
38458
38529
  square: boolean()
38459
38530
  });
38460
- ({
38531
+ /**
38532
+ * The convention in force when nobody has configured one — byte-for-byte the
38533
+ * behaviour of the pre-unification LIVE path (`DETAIL_CROP_PADDING_RATIO`).
38534
+ */
38535
+ var DEFAULT_DETAIL_CROP_CONVENTION = {
38461
38536
  paddingRatio: .15,
38462
38537
  square: false
38463
- }).paddingRatio;
38538
+ };
38539
+ Object.freeze({
38540
+ x: 0,
38541
+ y: 0,
38542
+ w: 1,
38543
+ h: 1
38544
+ });
38545
+ DEFAULT_DETAIL_CROP_CONVENTION.paddingRatio;
38464
38546
  /**
38465
38547
  * WHICH delivered frames the decode worker retains a native copy of.
38466
38548
  *
package/dist/addon.mjs CHANGED
@@ -8667,7 +8667,7 @@ var RecordingBandSchema = object({
8667
8667
  postBufferSec: number().min(0).optional()
8668
8668
  });
8669
8669
  ({
8670
- preBufferSec: 10,
8670
+ preBufferSec: 15,
8671
8671
  postBufferSec: 30
8672
8672
  }).postBufferSec * 1e3;
8673
8673
  /**
@@ -14887,128 +14887,103 @@ var COCO_TO_MACRO = {
14887
14887
  var AUDIO_MACRO_LABELS = [
14888
14888
  {
14889
14889
  id: "speech",
14890
- name: "Speech",
14891
- icon: "🗣️"
14890
+ name: "Speech"
14892
14891
  },
14893
14892
  {
14894
14893
  id: "scream",
14895
- name: "Scream / Shout",
14896
- icon: "😱"
14894
+ name: "Scream / Shout"
14897
14895
  },
14898
14896
  {
14899
14897
  id: "crying",
14900
- name: "Crying / Baby",
14901
- icon: "😢"
14898
+ name: "Crying / Baby"
14902
14899
  },
14903
14900
  {
14904
14901
  id: "laughter",
14905
- name: "Laughter",
14906
- icon: "😂"
14902
+ name: "Laughter"
14907
14903
  },
14908
14904
  {
14909
14905
  id: "music",
14910
- name: "Music",
14911
- icon: "🎵"
14906
+ name: "Music"
14912
14907
  },
14913
14908
  {
14914
14909
  id: "dog",
14915
- name: "Dog",
14916
- icon: "🐕"
14910
+ name: "Dog"
14917
14911
  },
14918
14912
  {
14919
14913
  id: "cat",
14920
- name: "Cat",
14921
- icon: "🐈"
14914
+ name: "Cat"
14922
14915
  },
14923
14916
  {
14924
14917
  id: "bird",
14925
- name: "Bird",
14926
- icon: "🐦"
14918
+ name: "Bird"
14927
14919
  },
14928
14920
  {
14929
14921
  id: "animal",
14930
- name: "Animal (other)",
14931
- icon: "🐾"
14922
+ name: "Animal (other)"
14932
14923
  },
14933
14924
  {
14934
14925
  id: "alarm",
14935
- name: "Alarm / Siren",
14936
- icon: "🚨"
14926
+ name: "Alarm / Siren"
14937
14927
  },
14938
14928
  {
14939
14929
  id: "doorbell",
14940
- name: "Doorbell / Knock",
14941
- icon: "🔔"
14930
+ name: "Doorbell / Knock"
14942
14931
  },
14943
14932
  {
14944
14933
  id: "glass_breaking",
14945
- name: "Glass Breaking",
14946
- icon: "💥"
14934
+ name: "Glass Breaking"
14947
14935
  },
14948
14936
  {
14949
14937
  id: "gunshot",
14950
- name: "Gunshot / Explosion",
14951
- icon: "💣"
14938
+ name: "Gunshot / Explosion"
14952
14939
  },
14953
14940
  {
14954
14941
  id: "vehicle",
14955
- name: "Vehicle",
14956
- icon: "🚗"
14942
+ name: "Vehicle"
14957
14943
  },
14958
14944
  {
14959
14945
  id: "siren",
14960
- name: "Emergency Siren",
14961
- icon: "🚑"
14946
+ name: "Emergency Siren"
14962
14947
  },
14963
14948
  {
14964
14949
  id: "fire",
14965
- name: "Fire / Smoke",
14966
- icon: "🔥"
14950
+ name: "Fire / Smoke"
14967
14951
  },
14968
14952
  {
14969
14953
  id: "water",
14970
- name: "Water",
14971
- icon: "💧"
14954
+ name: "Water"
14972
14955
  },
14973
14956
  {
14974
14957
  id: "wind",
14975
- name: "Wind / Weather",
14976
- icon: "🌬️"
14958
+ name: "Wind / Weather"
14977
14959
  },
14978
14960
  {
14979
14961
  id: "door",
14980
- name: "Door",
14981
- icon: "🚪"
14962
+ name: "Door"
14982
14963
  },
14983
14964
  {
14984
14965
  id: "footsteps",
14985
- name: "Footsteps",
14986
- icon: "👣"
14966
+ name: "Footsteps"
14987
14967
  },
14988
14968
  {
14989
14969
  id: "crowd",
14990
- name: "Crowd / Chatter",
14991
- icon: "👥"
14970
+ name: "Crowd / Chatter"
14992
14971
  },
14993
14972
  {
14994
14973
  id: "telephone",
14995
- name: "Telephone",
14996
- icon: "📞"
14974
+ name: "Telephone"
14997
14975
  },
14998
14976
  {
14999
14977
  id: "engine",
15000
- name: "Engine / Motor",
15001
- icon: "⚙️"
14978
+ name: "Engine / Motor"
15002
14979
  },
15003
14980
  {
15004
14981
  id: "tools",
15005
- name: "Tools / Construction",
15006
- icon: "🔨"
14982
+ name: "Tools / Construction"
15007
14983
  },
15008
14984
  {
15009
14985
  id: "silence",
15010
- name: "Silence",
15011
- icon: "🤫"
14986
+ name: "Silence"
15012
14987
  }
15013
14988
  ];
15014
14989
  var YAMNET_TO_MACRO = {
@@ -17510,7 +17485,7 @@ var TrackEnvelopeSchema = object({
17510
17485
  * `snapshots[]` references — megabytes across a page of tracks. `slim`
17511
17486
  * keeps every scalar the list surfaces actually render (ids, class(es),
17512
17487
  * label / audioLabels / importance enrichment, firstSeen/lastSeen, state,
17513
- * zonesVisited, bestEventId, envelope, hasFace, hasRider) and returns `positions` /
17488
+ * zonesVisited, bestEventId, envelope, hasFace, hasEmbeddedFace, hasRider) and returns `positions` /
17514
17489
  * `snapshots` as EMPTY arrays — detail views re-fetch the full row via
17515
17490
  * `getTrack`. Mirrors the event-store `projection` convention
17516
17491
  * (`getObjectEvents` et al.).
@@ -17805,6 +17780,35 @@ var TrackSchema = object({
17805
17780
  */
17806
17781
  hasFace: boolean().optional(),
17807
17782
  /**
17783
+ * This track has a face row IN THE GALLERY: a crop **and** an embedding — a
17784
+ * face an operator could ASSIGN to an identity.
17785
+ *
17786
+ * The STRICT twin of {@link hasFace}, and the pair only earns its keep
17787
+ * because the two disagree. `hasFace` is stamped at the TOP of the face
17788
+ * branch, before every gate, and means no more than "a face detector produced
17789
+ * a face detail". This one is stamped at the single moment the gallery row
17790
+ * LANDS — after `FaceRecognizer.onTrackEnd` successfully persists it, i.e.
17791
+ * past the embedding-magnitude verdict, the `minFacePx` detection gate, the
17792
+ * candidate gate, the imageless-track drop (no crop was ever captured) and
17793
+ * the crop-store drop. Everything between the detector and that insert can
17794
+ * legitimately refuse the face, so a flag written any earlier promises the
17795
+ * operator something to assign and delivers nothing.
17796
+ *
17797
+ * **Independent of recognition.** A face collected but never auto-matched is
17798
+ * still assignable — it is in fact the face an operator most wants to reach —
17799
+ * so this is NOT gated on `recognizedIdentityId`. Recognition lands in
17800
+ * `subLabel`; this says only that the raw material exists.
17801
+ *
17802
+ * **Set once, never cleared.** A track that produced a gallery row produced
17803
+ * one; deleting the row later is the gallery's business, not this flag's.
17804
+ *
17805
+ * **Absent ≠ false**, the same rule as {@link hasFace}: every row written
17806
+ * before the column omits it, and so does every server that predates the
17807
+ * field. A consumer must test `=== true` and render nothing otherwise —
17808
+ * never infer "no assignable face".
17809
+ */
17810
+ hasEmbeddedFace: boolean().optional(),
17811
+ /**
17808
17812
  * This subject CONTAINS a folded rider — a person the rider-pairing step
17809
17813
  * ([D34](../decisions/adr-0034.md)) removed from the frame BEFORE the tracker,
17810
17814
  * so the passage is tracked once and as a VEHICLE.
@@ -19194,6 +19198,32 @@ var DetailResultSchema = object({
19194
19198
  /** FRAME-space bbox (already mapped back from crop space). */
19195
19199
  bbox: NativeCropBboxSchema.optional(),
19196
19200
  embedding: string().optional(),
19201
+ /**
19202
+ * L2 magnitude of the RAW pre-normalization embedding. Additive and optional
19203
+ * so an older runner that does not send it degrades to "unmeasurable", which
19204
+ * the consuming gate treats as accept — never as reject.
19205
+ */
19206
+ embeddingMagnitude: number().optional(),
19207
+ /**
19208
+ * Model that produced `embedding` — the SAME contract `labelModelId` has for
19209
+ * `label`, and for the same reason: the producing node is the only side that
19210
+ * knows which model actually ran, and re-deriving it downstream is exactly
19211
+ * the inference this model exists to forbid.
19212
+ *
19213
+ * Additive and optional, so a runner that predates it degrades to
19214
+ * "unmeasurable" rather than to a wrong answer — the consumer falls back to
19215
+ * its previous assumption instead of refusing.
19216
+ *
19217
+ * Its absence was not cosmetic. `FaceRecognizer` needs the probe's model id
19218
+ * to use `face-matcher`'s same-model gate (`sample.modelId !== probe.modelId`);
19219
+ * with nothing on the wire it took the id from the GALLERY, so the gate
19220
+ * compared the gallery against itself and could never fire. That turned the
19221
+ * one guard protecting the face feature space into a tautology, and it is
19222
+ * why swapping `face-embedding`'s model would NOT have stranded the enrolled
19223
+ * gallery as the catalog comment predicts — it would have scored the new
19224
+ * model's vectors against the old model's samples in one cosine space.
19225
+ */
19226
+ embeddingModelId: string().optional(),
19197
19227
  label: string().optional(),
19198
19228
  /**
19199
19229
  * The tier `label` occupies, copied VERBATIM from the producing step's
@@ -20604,6 +20634,7 @@ DeviceType.Camera, method(object({
20604
20634
  isBattery: boolean(),
20605
20635
  reason: _enum([
20606
20636
  "disabled",
20637
+ "offline",
20607
20638
  "sleeping",
20608
20639
  "unreachable",
20609
20640
  "waking"
@@ -20649,9 +20680,17 @@ targets: array(object({
20649
20680
  sleeping: boolean(),
20650
20681
  /** Current device state rendered over the cached frame. State images
20651
20682
  * remain authoritative even when their photographic background is
20652
- * old; null means the link must carry a current camera frame. */
20683
+ * old; null means the link must carry a current camera frame.
20684
+ *
20685
+ * **This is the ONLY source a surface may derive an inactive tile
20686
+ * from.** A client that reads a device's `online`/`disabled` flags and
20687
+ * draws its own verdict will disagree with the pixels it is painting
20688
+ * — the frame comes from here, and so must the sentence over it
20689
+ * (D190). Pair with `ageMs` for the age of the photograph behind the
20690
+ * state. */
20653
20691
  stateReason: _enum([
20654
20692
  "disabled",
20693
+ "offline",
20655
20694
  "sleeping",
20656
20695
  "unreachable",
20657
20696
  "waking"
@@ -38202,7 +38241,6 @@ var NC_AUDIO_DEFAULTS = {
38202
38241
  hitPercent: 60,
38203
38242
  samplingSeconds: 10
38204
38243
  };
38205
- new Map(AUDIO_MACRO_LABELS.flatMap((macro) => macro.icon === void 0 ? [] : [[macro.id, macro.icon]]));
38206
38244
  new Set(["devices", "classes"]);
38207
38245
  NC_AUDIO_DEFAULTS.hitPercent, NC_AUDIO_DEFAULTS.samplingSeconds;
38208
38246
  /**
@@ -38436,6 +38474,39 @@ TimelapseRuleInputSchema.extend({
38436
38474
  createdAt: number(),
38437
38475
  updatedAt: number()
38438
38476
  });
38477
+ Object.freeze(Object.fromEntries([{
38478
+ stepId: "face-embedding",
38479
+ label: "Face recognition model",
38480
+ defaultModelId: "arcface-r100",
38481
+ indexName: "the enrolled face gallery",
38482
+ options: [
38483
+ {
38484
+ id: "arcface-r100",
38485
+ label: "ArcFace (ResNet34)"
38486
+ },
38487
+ {
38488
+ id: "auraface-r100",
38489
+ label: "AuraFace R100"
38490
+ },
38491
+ {
38492
+ id: "inception-resnet-v1",
38493
+ label: "Inception ResNet V1"
38494
+ }
38495
+ ]
38496
+ }, {
38497
+ stepId: "clip-embedding",
38498
+ label: "Semantic search model",
38499
+ defaultModelId: "mobileclip-s1",
38500
+ indexName: "the object semantic-search index",
38501
+ options: [{
38502
+ id: "mobileclip-s1",
38503
+ label: "MobileCLIP S1"
38504
+ }, {
38505
+ id: "mobileclip-s2",
38506
+ label: "MobileCLIP S2"
38507
+ }]
38508
+ }].map((s) => [s.stepId, s.defaultModelId])));
38509
+ string().min(1);
38439
38510
  object({
38440
38511
  /**
38441
38512
  * Fraction of the box's own size added on EACH side before cutting.
@@ -38456,10 +38527,21 @@ object({
38456
38527
  */
38457
38528
  square: boolean()
38458
38529
  });
38459
- ({
38530
+ /**
38531
+ * The convention in force when nobody has configured one — byte-for-byte the
38532
+ * behaviour of the pre-unification LIVE path (`DETAIL_CROP_PADDING_RATIO`).
38533
+ */
38534
+ var DEFAULT_DETAIL_CROP_CONVENTION = {
38460
38535
  paddingRatio: .15,
38461
38536
  square: false
38462
- }).paddingRatio;
38537
+ };
38538
+ Object.freeze({
38539
+ x: 0,
38540
+ y: 0,
38541
+ w: 1,
38542
+ h: 1
38543
+ });
38544
+ DEFAULT_DETAIL_CROP_CONVENTION.paddingRatio;
38463
38545
  /**
38464
38546
  * WHICH delivered frames the decode worker retains a native copy of.
38465
38547
  *
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@camstack/addon-provider-petkit",
3
- "version": "0.2.23",
3
+ "version": "0.2.24",
4
4
  "description": "PetKit smart-feeder device-provider addon for CamStack — wraps the @apocaliss92/nodepetkit PetKit cloud client",
5
5
  "keywords": [
6
6
  "camstack",