@camstack/addon-export-hap 1.2.34 β†’ 1.2.35

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.
@@ -8232,7 +8232,7 @@ var RecordingBandSchema = object({
8232
8232
  postBufferSec: number().min(0).optional()
8233
8233
  });
8234
8234
  ({
8235
- preBufferSec: 10,
8235
+ preBufferSec: 15,
8236
8236
  postBufferSec: 30
8237
8237
  }).postBufferSec * 1e3;
8238
8238
  /**
@@ -14306,128 +14306,103 @@ var COCO_TO_MACRO = {
14306
14306
  var AUDIO_MACRO_LABELS = [
14307
14307
  {
14308
14308
  id: "speech",
14309
- name: "Speech",
14310
- icon: "πŸ—£οΈ"
14309
+ name: "Speech"
14311
14310
  },
14312
14311
  {
14313
14312
  id: "scream",
14314
- name: "Scream / Shout",
14315
- icon: "😱"
14313
+ name: "Scream / Shout"
14316
14314
  },
14317
14315
  {
14318
14316
  id: "crying",
14319
- name: "Crying / Baby",
14320
- icon: "😒"
14317
+ name: "Crying / Baby"
14321
14318
  },
14322
14319
  {
14323
14320
  id: "laughter",
14324
- name: "Laughter",
14325
- icon: "πŸ˜‚"
14321
+ name: "Laughter"
14326
14322
  },
14327
14323
  {
14328
14324
  id: "music",
14329
- name: "Music",
14330
- icon: "🎡"
14325
+ name: "Music"
14331
14326
  },
14332
14327
  {
14333
14328
  id: "dog",
14334
- name: "Dog",
14335
- icon: "πŸ•"
14329
+ name: "Dog"
14336
14330
  },
14337
14331
  {
14338
14332
  id: "cat",
14339
- name: "Cat",
14340
- icon: "🐈"
14333
+ name: "Cat"
14341
14334
  },
14342
14335
  {
14343
14336
  id: "bird",
14344
- name: "Bird",
14345
- icon: "🐦"
14337
+ name: "Bird"
14346
14338
  },
14347
14339
  {
14348
14340
  id: "animal",
14349
- name: "Animal (other)",
14350
- icon: "🐾"
14341
+ name: "Animal (other)"
14351
14342
  },
14352
14343
  {
14353
14344
  id: "alarm",
14354
- name: "Alarm / Siren",
14355
- icon: "🚨"
14345
+ name: "Alarm / Siren"
14356
14346
  },
14357
14347
  {
14358
14348
  id: "doorbell",
14359
- name: "Doorbell / Knock",
14360
- icon: "πŸ””"
14349
+ name: "Doorbell / Knock"
14361
14350
  },
14362
14351
  {
14363
14352
  id: "glass_breaking",
14364
- name: "Glass Breaking",
14365
- icon: "πŸ’₯"
14353
+ name: "Glass Breaking"
14366
14354
  },
14367
14355
  {
14368
14356
  id: "gunshot",
14369
- name: "Gunshot / Explosion",
14370
- icon: "πŸ’£"
14357
+ name: "Gunshot / Explosion"
14371
14358
  },
14372
14359
  {
14373
14360
  id: "vehicle",
14374
- name: "Vehicle",
14375
- icon: "πŸš—"
14361
+ name: "Vehicle"
14376
14362
  },
14377
14363
  {
14378
14364
  id: "siren",
14379
- name: "Emergency Siren",
14380
- icon: "πŸš‘"
14365
+ name: "Emergency Siren"
14381
14366
  },
14382
14367
  {
14383
14368
  id: "fire",
14384
- name: "Fire / Smoke",
14385
- icon: "πŸ”₯"
14369
+ name: "Fire / Smoke"
14386
14370
  },
14387
14371
  {
14388
14372
  id: "water",
14389
- name: "Water",
14390
- icon: "πŸ’§"
14373
+ name: "Water"
14391
14374
  },
14392
14375
  {
14393
14376
  id: "wind",
14394
- name: "Wind / Weather",
14395
- icon: "🌬️"
14377
+ name: "Wind / Weather"
14396
14378
  },
14397
14379
  {
14398
14380
  id: "door",
14399
- name: "Door",
14400
- icon: "πŸšͺ"
14381
+ name: "Door"
14401
14382
  },
14402
14383
  {
14403
14384
  id: "footsteps",
14404
- name: "Footsteps",
14405
- icon: "πŸ‘£"
14385
+ name: "Footsteps"
14406
14386
  },
14407
14387
  {
14408
14388
  id: "crowd",
14409
- name: "Crowd / Chatter",
14410
- icon: "πŸ‘₯"
14389
+ name: "Crowd / Chatter"
14411
14390
  },
14412
14391
  {
14413
14392
  id: "telephone",
14414
- name: "Telephone",
14415
- icon: "πŸ“ž"
14393
+ name: "Telephone"
14416
14394
  },
14417
14395
  {
14418
14396
  id: "engine",
14419
- name: "Engine / Motor",
14420
- icon: "βš™οΈ"
14397
+ name: "Engine / Motor"
14421
14398
  },
14422
14399
  {
14423
14400
  id: "tools",
14424
- name: "Tools / Construction",
14425
- icon: "πŸ”¨"
14401
+ name: "Tools / Construction"
14426
14402
  },
14427
14403
  {
14428
14404
  id: "silence",
14429
- name: "Silence",
14430
- icon: "🀫"
14405
+ name: "Silence"
14431
14406
  }
14432
14407
  ];
14433
14408
  var YAMNET_TO_MACRO = {
@@ -16891,7 +16866,7 @@ var TrackEnvelopeSchema = object({
16891
16866
  * `snapshots[]` references β€” megabytes across a page of tracks. `slim`
16892
16867
  * keeps every scalar the list surfaces actually render (ids, class(es),
16893
16868
  * label / audioLabels / importance enrichment, firstSeen/lastSeen, state,
16894
- * zonesVisited, bestEventId, envelope, hasFace, hasRider) and returns `positions` /
16869
+ * zonesVisited, bestEventId, envelope, hasFace, hasEmbeddedFace, hasRider) and returns `positions` /
16895
16870
  * `snapshots` as EMPTY arrays β€” detail views re-fetch the full row via
16896
16871
  * `getTrack`. Mirrors the event-store `projection` convention
16897
16872
  * (`getObjectEvents` et al.).
@@ -17186,6 +17161,35 @@ var TrackSchema = object({
17186
17161
  */
17187
17162
  hasFace: boolean().optional(),
17188
17163
  /**
17164
+ * This track has a face row IN THE GALLERY: a crop **and** an embedding β€” a
17165
+ * face an operator could ASSIGN to an identity.
17166
+ *
17167
+ * The STRICT twin of {@link hasFace}, and the pair only earns its keep
17168
+ * because the two disagree. `hasFace` is stamped at the TOP of the face
17169
+ * branch, before every gate, and means no more than "a face detector produced
17170
+ * a face detail". This one is stamped at the single moment the gallery row
17171
+ * LANDS β€” after `FaceRecognizer.onTrackEnd` successfully persists it, i.e.
17172
+ * past the embedding-magnitude verdict, the `minFacePx` detection gate, the
17173
+ * candidate gate, the imageless-track drop (no crop was ever captured) and
17174
+ * the crop-store drop. Everything between the detector and that insert can
17175
+ * legitimately refuse the face, so a flag written any earlier promises the
17176
+ * operator something to assign and delivers nothing.
17177
+ *
17178
+ * **Independent of recognition.** A face collected but never auto-matched is
17179
+ * still assignable β€” it is in fact the face an operator most wants to reach β€”
17180
+ * so this is NOT gated on `recognizedIdentityId`. Recognition lands in
17181
+ * `subLabel`; this says only that the raw material exists.
17182
+ *
17183
+ * **Set once, never cleared.** A track that produced a gallery row produced
17184
+ * one; deleting the row later is the gallery's business, not this flag's.
17185
+ *
17186
+ * **Absent β‰  false**, the same rule as {@link hasFace}: every row written
17187
+ * before the column omits it, and so does every server that predates the
17188
+ * field. A consumer must test `=== true` and render nothing otherwise β€”
17189
+ * never infer "no assignable face".
17190
+ */
17191
+ hasEmbeddedFace: boolean().optional(),
17192
+ /**
17189
17193
  * This subject CONTAINS a folded rider β€” a person the rider-pairing step
17190
17194
  * ([D34](../decisions/adr-0034.md)) removed from the frame BEFORE the tracker,
17191
17195
  * so the passage is tracked once and as a VEHICLE.
@@ -18535,6 +18539,32 @@ var DetailResultSchema = object({
18535
18539
  /** FRAME-space bbox (already mapped back from crop space). */
18536
18540
  bbox: NativeCropBboxSchema.optional(),
18537
18541
  embedding: string().optional(),
18542
+ /**
18543
+ * L2 magnitude of the RAW pre-normalization embedding. Additive and optional
18544
+ * so an older runner that does not send it degrades to "unmeasurable", which
18545
+ * the consuming gate treats as accept β€” never as reject.
18546
+ */
18547
+ embeddingMagnitude: number().optional(),
18548
+ /**
18549
+ * Model that produced `embedding` β€” the SAME contract `labelModelId` has for
18550
+ * `label`, and for the same reason: the producing node is the only side that
18551
+ * knows which model actually ran, and re-deriving it downstream is exactly
18552
+ * the inference this model exists to forbid.
18553
+ *
18554
+ * Additive and optional, so a runner that predates it degrades to
18555
+ * "unmeasurable" rather than to a wrong answer β€” the consumer falls back to
18556
+ * its previous assumption instead of refusing.
18557
+ *
18558
+ * Its absence was not cosmetic. `FaceRecognizer` needs the probe's model id
18559
+ * to use `face-matcher`'s same-model gate (`sample.modelId !== probe.modelId`);
18560
+ * with nothing on the wire it took the id from the GALLERY, so the gate
18561
+ * compared the gallery against itself and could never fire. That turned the
18562
+ * one guard protecting the face feature space into a tautology, and it is
18563
+ * why swapping `face-embedding`'s model would NOT have stranded the enrolled
18564
+ * gallery as the catalog comment predicts β€” it would have scored the new
18565
+ * model's vectors against the old model's samples in one cosine space.
18566
+ */
18567
+ embeddingModelId: string().optional(),
18538
18568
  label: string().optional(),
18539
18569
  /**
18540
18570
  * The tier `label` occupies, copied VERBATIM from the producing step's
@@ -19945,6 +19975,7 @@ DeviceType.Camera, method(object({
19945
19975
  isBattery: boolean(),
19946
19976
  reason: _enum([
19947
19977
  "disabled",
19978
+ "offline",
19948
19979
  "sleeping",
19949
19980
  "unreachable",
19950
19981
  "waking"
@@ -19990,9 +20021,17 @@ targets: array(object({
19990
20021
  sleeping: boolean(),
19991
20022
  /** Current device state rendered over the cached frame. State images
19992
20023
  * remain authoritative even when their photographic background is
19993
- * old; null means the link must carry a current camera frame. */
20024
+ * old; null means the link must carry a current camera frame.
20025
+ *
20026
+ * **This is the ONLY source a surface may derive an inactive tile
20027
+ * from.** A client that reads a device's `online`/`disabled` flags and
20028
+ * draws its own verdict will disagree with the pixels it is painting
20029
+ * β€” the frame comes from here, and so must the sentence over it
20030
+ * (D190). Pair with `ageMs` for the age of the photograph behind the
20031
+ * state. */
19994
20032
  stateReason: _enum([
19995
20033
  "disabled",
20034
+ "offline",
19996
20035
  "sleeping",
19997
20036
  "unreachable",
19998
20037
  "waking"
@@ -34251,7 +34290,6 @@ var NC_AUDIO_DEFAULTS = {
34251
34290
  hitPercent: 60,
34252
34291
  samplingSeconds: 10
34253
34292
  };
34254
- new Map(AUDIO_MACRO_LABELS.flatMap((macro) => macro.icon === void 0 ? [] : [[macro.id, macro.icon]]));
34255
34293
  new Set(["devices", "classes"]);
34256
34294
  NC_AUDIO_DEFAULTS.hitPercent, NC_AUDIO_DEFAULTS.samplingSeconds;
34257
34295
  /**
@@ -34485,6 +34523,39 @@ TimelapseRuleInputSchema.extend({
34485
34523
  createdAt: number(),
34486
34524
  updatedAt: number()
34487
34525
  });
34526
+ Object.freeze(Object.fromEntries([{
34527
+ stepId: "face-embedding",
34528
+ label: "Face recognition model",
34529
+ defaultModelId: "arcface-r100",
34530
+ indexName: "the enrolled face gallery",
34531
+ options: [
34532
+ {
34533
+ id: "arcface-r100",
34534
+ label: "ArcFace (ResNet34)"
34535
+ },
34536
+ {
34537
+ id: "auraface-r100",
34538
+ label: "AuraFace R100"
34539
+ },
34540
+ {
34541
+ id: "inception-resnet-v1",
34542
+ label: "Inception ResNet V1"
34543
+ }
34544
+ ]
34545
+ }, {
34546
+ stepId: "clip-embedding",
34547
+ label: "Semantic search model",
34548
+ defaultModelId: "mobileclip-s1",
34549
+ indexName: "the object semantic-search index",
34550
+ options: [{
34551
+ id: "mobileclip-s1",
34552
+ label: "MobileCLIP S1"
34553
+ }, {
34554
+ id: "mobileclip-s2",
34555
+ label: "MobileCLIP S2"
34556
+ }]
34557
+ }].map((s) => [s.stepId, s.defaultModelId])));
34558
+ string().min(1);
34488
34559
  object({
34489
34560
  /**
34490
34561
  * Fraction of the box's own size added on EACH side before cutting.
@@ -34505,10 +34576,21 @@ object({
34505
34576
  */
34506
34577
  square: boolean()
34507
34578
  });
34508
- ({
34579
+ /**
34580
+ * The convention in force when nobody has configured one β€” byte-for-byte the
34581
+ * behaviour of the pre-unification LIVE path (`DETAIL_CROP_PADDING_RATIO`).
34582
+ */
34583
+ var DEFAULT_DETAIL_CROP_CONVENTION = {
34509
34584
  paddingRatio: .15,
34510
34585
  square: false
34511
- }).paddingRatio;
34586
+ };
34587
+ Object.freeze({
34588
+ x: 0,
34589
+ y: 0,
34590
+ w: 1,
34591
+ h: 1
34592
+ });
34593
+ DEFAULT_DETAIL_CROP_CONVENTION.paddingRatio;
34512
34594
  /**
34513
34595
  * WHICH delivered frames the decode worker retains a native copy of.
34514
34596
  *
@@ -94273,7 +94355,7 @@ function isConnectionLike(value) {
94273
94355
  return isRecord$1(value) && typeof value["hasEventNotifications"] === "function";
94274
94356
  }
94275
94357
  function isIterable$1(value) {
94276
- return isRecord$1(value) && typeof value[Symbol.iterator] === "function";
94358
+ return isRecord$1(value) && typeof Reflect.get(value, Symbol.iterator) === "function";
94277
94359
  }
94278
94360
  /** `accessory._server.httpServer.connections`, or null at any missing hop. */
94279
94361
  function readConnections$1(accessory) {
@@ -94735,7 +94817,7 @@ function isRecord(value) {
94735
94817
  return typeof value === "object" && value !== null;
94736
94818
  }
94737
94819
  function isIterable(value) {
94738
- return isRecord(value) && typeof value[Symbol.iterator] === "function";
94820
+ return isRecord(value) && typeof Reflect.get(value, Symbol.iterator) === "function";
94739
94821
  }
94740
94822
  function isAccessoryInfoLike(value) {
94741
94823
  return isRecord(value) && isRecord(value["pairedClients"]) && typeof value["hasAdminPermissions"] === "function";
@@ -8220,7 +8220,7 @@ var RecordingBandSchema = object({
8220
8220
  postBufferSec: number().min(0).optional()
8221
8221
  });
8222
8222
  ({
8223
- preBufferSec: 10,
8223
+ preBufferSec: 15,
8224
8224
  postBufferSec: 30
8225
8225
  }).postBufferSec * 1e3;
8226
8226
  /**
@@ -14294,128 +14294,103 @@ var COCO_TO_MACRO = {
14294
14294
  var AUDIO_MACRO_LABELS = [
14295
14295
  {
14296
14296
  id: "speech",
14297
- name: "Speech",
14298
- icon: "πŸ—£οΈ"
14297
+ name: "Speech"
14299
14298
  },
14300
14299
  {
14301
14300
  id: "scream",
14302
- name: "Scream / Shout",
14303
- icon: "😱"
14301
+ name: "Scream / Shout"
14304
14302
  },
14305
14303
  {
14306
14304
  id: "crying",
14307
- name: "Crying / Baby",
14308
- icon: "😒"
14305
+ name: "Crying / Baby"
14309
14306
  },
14310
14307
  {
14311
14308
  id: "laughter",
14312
- name: "Laughter",
14313
- icon: "πŸ˜‚"
14309
+ name: "Laughter"
14314
14310
  },
14315
14311
  {
14316
14312
  id: "music",
14317
- name: "Music",
14318
- icon: "🎡"
14313
+ name: "Music"
14319
14314
  },
14320
14315
  {
14321
14316
  id: "dog",
14322
- name: "Dog",
14323
- icon: "πŸ•"
14317
+ name: "Dog"
14324
14318
  },
14325
14319
  {
14326
14320
  id: "cat",
14327
- name: "Cat",
14328
- icon: "🐈"
14321
+ name: "Cat"
14329
14322
  },
14330
14323
  {
14331
14324
  id: "bird",
14332
- name: "Bird",
14333
- icon: "🐦"
14325
+ name: "Bird"
14334
14326
  },
14335
14327
  {
14336
14328
  id: "animal",
14337
- name: "Animal (other)",
14338
- icon: "🐾"
14329
+ name: "Animal (other)"
14339
14330
  },
14340
14331
  {
14341
14332
  id: "alarm",
14342
- name: "Alarm / Siren",
14343
- icon: "🚨"
14333
+ name: "Alarm / Siren"
14344
14334
  },
14345
14335
  {
14346
14336
  id: "doorbell",
14347
- name: "Doorbell / Knock",
14348
- icon: "πŸ””"
14337
+ name: "Doorbell / Knock"
14349
14338
  },
14350
14339
  {
14351
14340
  id: "glass_breaking",
14352
- name: "Glass Breaking",
14353
- icon: "πŸ’₯"
14341
+ name: "Glass Breaking"
14354
14342
  },
14355
14343
  {
14356
14344
  id: "gunshot",
14357
- name: "Gunshot / Explosion",
14358
- icon: "πŸ’£"
14345
+ name: "Gunshot / Explosion"
14359
14346
  },
14360
14347
  {
14361
14348
  id: "vehicle",
14362
- name: "Vehicle",
14363
- icon: "πŸš—"
14349
+ name: "Vehicle"
14364
14350
  },
14365
14351
  {
14366
14352
  id: "siren",
14367
- name: "Emergency Siren",
14368
- icon: "πŸš‘"
14353
+ name: "Emergency Siren"
14369
14354
  },
14370
14355
  {
14371
14356
  id: "fire",
14372
- name: "Fire / Smoke",
14373
- icon: "πŸ”₯"
14357
+ name: "Fire / Smoke"
14374
14358
  },
14375
14359
  {
14376
14360
  id: "water",
14377
- name: "Water",
14378
- icon: "πŸ’§"
14361
+ name: "Water"
14379
14362
  },
14380
14363
  {
14381
14364
  id: "wind",
14382
- name: "Wind / Weather",
14383
- icon: "🌬️"
14365
+ name: "Wind / Weather"
14384
14366
  },
14385
14367
  {
14386
14368
  id: "door",
14387
- name: "Door",
14388
- icon: "πŸšͺ"
14369
+ name: "Door"
14389
14370
  },
14390
14371
  {
14391
14372
  id: "footsteps",
14392
- name: "Footsteps",
14393
- icon: "πŸ‘£"
14373
+ name: "Footsteps"
14394
14374
  },
14395
14375
  {
14396
14376
  id: "crowd",
14397
- name: "Crowd / Chatter",
14398
- icon: "πŸ‘₯"
14377
+ name: "Crowd / Chatter"
14399
14378
  },
14400
14379
  {
14401
14380
  id: "telephone",
14402
- name: "Telephone",
14403
- icon: "πŸ“ž"
14381
+ name: "Telephone"
14404
14382
  },
14405
14383
  {
14406
14384
  id: "engine",
14407
- name: "Engine / Motor",
14408
- icon: "βš™οΈ"
14385
+ name: "Engine / Motor"
14409
14386
  },
14410
14387
  {
14411
14388
  id: "tools",
14412
- name: "Tools / Construction",
14413
- icon: "πŸ”¨"
14389
+ name: "Tools / Construction"
14414
14390
  },
14415
14391
  {
14416
14392
  id: "silence",
14417
- name: "Silence",
14418
- icon: "🀫"
14393
+ name: "Silence"
14419
14394
  }
14420
14395
  ];
14421
14396
  var YAMNET_TO_MACRO = {
@@ -16879,7 +16854,7 @@ var TrackEnvelopeSchema = object({
16879
16854
  * `snapshots[]` references β€” megabytes across a page of tracks. `slim`
16880
16855
  * keeps every scalar the list surfaces actually render (ids, class(es),
16881
16856
  * label / audioLabels / importance enrichment, firstSeen/lastSeen, state,
16882
- * zonesVisited, bestEventId, envelope, hasFace, hasRider) and returns `positions` /
16857
+ * zonesVisited, bestEventId, envelope, hasFace, hasEmbeddedFace, hasRider) and returns `positions` /
16883
16858
  * `snapshots` as EMPTY arrays β€” detail views re-fetch the full row via
16884
16859
  * `getTrack`. Mirrors the event-store `projection` convention
16885
16860
  * (`getObjectEvents` et al.).
@@ -17174,6 +17149,35 @@ var TrackSchema = object({
17174
17149
  */
17175
17150
  hasFace: boolean().optional(),
17176
17151
  /**
17152
+ * This track has a face row IN THE GALLERY: a crop **and** an embedding β€” a
17153
+ * face an operator could ASSIGN to an identity.
17154
+ *
17155
+ * The STRICT twin of {@link hasFace}, and the pair only earns its keep
17156
+ * because the two disagree. `hasFace` is stamped at the TOP of the face
17157
+ * branch, before every gate, and means no more than "a face detector produced
17158
+ * a face detail". This one is stamped at the single moment the gallery row
17159
+ * LANDS β€” after `FaceRecognizer.onTrackEnd` successfully persists it, i.e.
17160
+ * past the embedding-magnitude verdict, the `minFacePx` detection gate, the
17161
+ * candidate gate, the imageless-track drop (no crop was ever captured) and
17162
+ * the crop-store drop. Everything between the detector and that insert can
17163
+ * legitimately refuse the face, so a flag written any earlier promises the
17164
+ * operator something to assign and delivers nothing.
17165
+ *
17166
+ * **Independent of recognition.** A face collected but never auto-matched is
17167
+ * still assignable β€” it is in fact the face an operator most wants to reach β€”
17168
+ * so this is NOT gated on `recognizedIdentityId`. Recognition lands in
17169
+ * `subLabel`; this says only that the raw material exists.
17170
+ *
17171
+ * **Set once, never cleared.** A track that produced a gallery row produced
17172
+ * one; deleting the row later is the gallery's business, not this flag's.
17173
+ *
17174
+ * **Absent β‰  false**, the same rule as {@link hasFace}: every row written
17175
+ * before the column omits it, and so does every server that predates the
17176
+ * field. A consumer must test `=== true` and render nothing otherwise β€”
17177
+ * never infer "no assignable face".
17178
+ */
17179
+ hasEmbeddedFace: boolean().optional(),
17180
+ /**
17177
17181
  * This subject CONTAINS a folded rider β€” a person the rider-pairing step
17178
17182
  * ([D34](../decisions/adr-0034.md)) removed from the frame BEFORE the tracker,
17179
17183
  * so the passage is tracked once and as a VEHICLE.
@@ -18523,6 +18527,32 @@ var DetailResultSchema = object({
18523
18527
  /** FRAME-space bbox (already mapped back from crop space). */
18524
18528
  bbox: NativeCropBboxSchema.optional(),
18525
18529
  embedding: string().optional(),
18530
+ /**
18531
+ * L2 magnitude of the RAW pre-normalization embedding. Additive and optional
18532
+ * so an older runner that does not send it degrades to "unmeasurable", which
18533
+ * the consuming gate treats as accept β€” never as reject.
18534
+ */
18535
+ embeddingMagnitude: number().optional(),
18536
+ /**
18537
+ * Model that produced `embedding` β€” the SAME contract `labelModelId` has for
18538
+ * `label`, and for the same reason: the producing node is the only side that
18539
+ * knows which model actually ran, and re-deriving it downstream is exactly
18540
+ * the inference this model exists to forbid.
18541
+ *
18542
+ * Additive and optional, so a runner that predates it degrades to
18543
+ * "unmeasurable" rather than to a wrong answer β€” the consumer falls back to
18544
+ * its previous assumption instead of refusing.
18545
+ *
18546
+ * Its absence was not cosmetic. `FaceRecognizer` needs the probe's model id
18547
+ * to use `face-matcher`'s same-model gate (`sample.modelId !== probe.modelId`);
18548
+ * with nothing on the wire it took the id from the GALLERY, so the gate
18549
+ * compared the gallery against itself and could never fire. That turned the
18550
+ * one guard protecting the face feature space into a tautology, and it is
18551
+ * why swapping `face-embedding`'s model would NOT have stranded the enrolled
18552
+ * gallery as the catalog comment predicts β€” it would have scored the new
18553
+ * model's vectors against the old model's samples in one cosine space.
18554
+ */
18555
+ embeddingModelId: string().optional(),
18526
18556
  label: string().optional(),
18527
18557
  /**
18528
18558
  * The tier `label` occupies, copied VERBATIM from the producing step's
@@ -19933,6 +19963,7 @@ DeviceType.Camera, method(object({
19933
19963
  isBattery: boolean(),
19934
19964
  reason: _enum([
19935
19965
  "disabled",
19966
+ "offline",
19936
19967
  "sleeping",
19937
19968
  "unreachable",
19938
19969
  "waking"
@@ -19978,9 +20009,17 @@ targets: array(object({
19978
20009
  sleeping: boolean(),
19979
20010
  /** Current device state rendered over the cached frame. State images
19980
20011
  * remain authoritative even when their photographic background is
19981
- * old; null means the link must carry a current camera frame. */
20012
+ * old; null means the link must carry a current camera frame.
20013
+ *
20014
+ * **This is the ONLY source a surface may derive an inactive tile
20015
+ * from.** A client that reads a device's `online`/`disabled` flags and
20016
+ * draws its own verdict will disagree with the pixels it is painting
20017
+ * β€” the frame comes from here, and so must the sentence over it
20018
+ * (D190). Pair with `ageMs` for the age of the photograph behind the
20019
+ * state. */
19982
20020
  stateReason: _enum([
19983
20021
  "disabled",
20022
+ "offline",
19984
20023
  "sleeping",
19985
20024
  "unreachable",
19986
20025
  "waking"
@@ -34239,7 +34278,6 @@ var NC_AUDIO_DEFAULTS = {
34239
34278
  hitPercent: 60,
34240
34279
  samplingSeconds: 10
34241
34280
  };
34242
- new Map(AUDIO_MACRO_LABELS.flatMap((macro) => macro.icon === void 0 ? [] : [[macro.id, macro.icon]]));
34243
34281
  new Set(["devices", "classes"]);
34244
34282
  NC_AUDIO_DEFAULTS.hitPercent, NC_AUDIO_DEFAULTS.samplingSeconds;
34245
34283
  /**
@@ -34473,6 +34511,39 @@ TimelapseRuleInputSchema.extend({
34473
34511
  createdAt: number(),
34474
34512
  updatedAt: number()
34475
34513
  });
34514
+ Object.freeze(Object.fromEntries([{
34515
+ stepId: "face-embedding",
34516
+ label: "Face recognition model",
34517
+ defaultModelId: "arcface-r100",
34518
+ indexName: "the enrolled face gallery",
34519
+ options: [
34520
+ {
34521
+ id: "arcface-r100",
34522
+ label: "ArcFace (ResNet34)"
34523
+ },
34524
+ {
34525
+ id: "auraface-r100",
34526
+ label: "AuraFace R100"
34527
+ },
34528
+ {
34529
+ id: "inception-resnet-v1",
34530
+ label: "Inception ResNet V1"
34531
+ }
34532
+ ]
34533
+ }, {
34534
+ stepId: "clip-embedding",
34535
+ label: "Semantic search model",
34536
+ defaultModelId: "mobileclip-s1",
34537
+ indexName: "the object semantic-search index",
34538
+ options: [{
34539
+ id: "mobileclip-s1",
34540
+ label: "MobileCLIP S1"
34541
+ }, {
34542
+ id: "mobileclip-s2",
34543
+ label: "MobileCLIP S2"
34544
+ }]
34545
+ }].map((s) => [s.stepId, s.defaultModelId])));
34546
+ string().min(1);
34476
34547
  object({
34477
34548
  /**
34478
34549
  * Fraction of the box's own size added on EACH side before cutting.
@@ -34493,10 +34564,21 @@ object({
34493
34564
  */
34494
34565
  square: boolean()
34495
34566
  });
34496
- ({
34567
+ /**
34568
+ * The convention in force when nobody has configured one β€” byte-for-byte the
34569
+ * behaviour of the pre-unification LIVE path (`DETAIL_CROP_PADDING_RATIO`).
34570
+ */
34571
+ var DEFAULT_DETAIL_CROP_CONVENTION = {
34497
34572
  paddingRatio: .15,
34498
34573
  square: false
34499
- }).paddingRatio;
34574
+ };
34575
+ Object.freeze({
34576
+ x: 0,
34577
+ y: 0,
34578
+ w: 1,
34579
+ h: 1
34580
+ });
34581
+ DEFAULT_DETAIL_CROP_CONVENTION.paddingRatio;
34500
34582
  /**
34501
34583
  * WHICH delivered frames the decode worker retains a native copy of.
34502
34584
  *
@@ -94261,7 +94343,7 @@ function isConnectionLike(value) {
94261
94343
  return isRecord$1(value) && typeof value["hasEventNotifications"] === "function";
94262
94344
  }
94263
94345
  function isIterable$1(value) {
94264
- return isRecord$1(value) && typeof value[Symbol.iterator] === "function";
94346
+ return isRecord$1(value) && typeof Reflect.get(value, Symbol.iterator) === "function";
94265
94347
  }
94266
94348
  /** `accessory._server.httpServer.connections`, or null at any missing hop. */
94267
94349
  function readConnections$1(accessory) {
@@ -94723,7 +94805,7 @@ function isRecord(value) {
94723
94805
  return typeof value === "object" && value !== null;
94724
94806
  }
94725
94807
  function isIterable(value) {
94726
- return isRecord(value) && typeof value[Symbol.iterator] === "function";
94808
+ return isRecord(value) && typeof Reflect.get(value, Symbol.iterator) === "function";
94727
94809
  }
94728
94810
  function isAccessoryInfoLike(value) {
94729
94811
  return isRecord(value) && isRecord(value["pairedClients"]) && typeof value["hasAdminPermissions"] === "function";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@camstack/addon-export-hap",
3
- "version": "1.2.34",
3
+ "version": "1.2.35",
4
4
  "description": "HomeKit (HAP) exporter for CamStack devices. Publishes each exposed device as its own HomeKit accessory: cameras and doorbells with SRTP streaming, HomeKit Secure Video, motion, two-way audio, PTZ and battery; switches, lights, locks and sensors through a capabilityβ†’service table.",
5
5
  "keywords": [
6
6
  "camstack",