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

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
@@ -19410,6 +19440,12 @@ var CameraStatusSchema = object({
19410
19440
  /** Unix timestamp (ms) when this snapshot was composed server-side. */
19411
19441
  fetchedAt: number()
19412
19442
  });
19443
+ var InferenceDeviceExclusionReasonSchema = _enum([
19444
+ "disabled",
19445
+ "unavailable",
19446
+ "cannot-host-camera-root",
19447
+ "accelerator-preferred"
19448
+ ]);
19413
19449
  var NodeInferenceDeviceSchema = object({
19414
19450
  /** Stable per-node device key, e.g. `openvino:npu`, `edgetpu:usb`, `cpu`. */
19415
19451
  key: string(),
@@ -19440,7 +19476,17 @@ var NodeInferenceDeviceSchema = object({
19440
19476
  * available per format; this is the stored selection that becomes the
19441
19477
  * default for EVERY camera landing on this accelerator.
19442
19478
  */
19443
- steps: record(string(), DeviceStepConfigSchema).optional()
19479
+ steps: record(string(), DeviceStepConfigSchema).optional(),
19480
+ /**
19481
+ * `null` when the device IS a camera-root candidate on this node; otherwise
19482
+ * the reason the dispatcher drops it. Computed by the SAME
19483
+ * `resolveInferenceDeviceEligibility` the dispatcher runs, so this view can
19484
+ * never disagree with the election β€” deriving it in the UI from
19485
+ * `enabled`/`available` would silently miss `cannot-host-camera-root` (needs
19486
+ * the node's model catalog) and `accelerator-preferred` (needs the node-wide
19487
+ * "an accelerator is serving" predicate).
19488
+ */
19489
+ exclusion: InferenceDeviceExclusionReasonSchema.nullable()
19444
19490
  });
19445
19491
  var NodeInferenceDevicesSchema = object({
19446
19492
  nodeId: string(),
@@ -19945,6 +19991,7 @@ DeviceType.Camera, method(object({
19945
19991
  isBattery: boolean(),
19946
19992
  reason: _enum([
19947
19993
  "disabled",
19994
+ "offline",
19948
19995
  "sleeping",
19949
19996
  "unreachable",
19950
19997
  "waking"
@@ -19990,9 +20037,17 @@ targets: array(object({
19990
20037
  sleeping: boolean(),
19991
20038
  /** Current device state rendered over the cached frame. State images
19992
20039
  * remain authoritative even when their photographic background is
19993
- * old; null means the link must carry a current camera frame. */
20040
+ * old; null means the link must carry a current camera frame.
20041
+ *
20042
+ * **This is the ONLY source a surface may derive an inactive tile
20043
+ * from.** A client that reads a device's `online`/`disabled` flags and
20044
+ * draws its own verdict will disagree with the pixels it is painting
20045
+ * β€” the frame comes from here, and so must the sentence over it
20046
+ * (D190). Pair with `ageMs` for the age of the photograph behind the
20047
+ * state. */
19994
20048
  stateReason: _enum([
19995
20049
  "disabled",
20050
+ "offline",
19996
20051
  "sleeping",
19997
20052
  "unreachable",
19998
20053
  "waking"
@@ -23225,7 +23280,12 @@ var ListResultSchema = object({
23225
23280
  probedAt: number()
23226
23281
  });
23227
23282
  var PreferredSchema = LocalInterfaceSchema.nullable();
23228
- var GetConnectionEndpointsResultSchema = object({ endpoints: array(object({
23283
+ /**
23284
+ * Candidate base URL for the SDK to race on connect. Order matters β€”
23285
+ * the SDK should attempt these top-to-bottom with a short per-candidate
23286
+ * timeout (e.g. 1500ms) and cache the winner for the session.
23287
+ */
23288
+ var ConnectionEndpointSchema = object({
23229
23289
  /** Operator-facing label (e.g. "LAN β€” en0", "Public tunnel"). */
23230
23290
  label: string(),
23231
23291
  /** Fully-formed base URL with scheme + host + port. */
@@ -23268,7 +23328,42 @@ var GetConnectionEndpointsResultSchema = object({ endpoints: array(object({
23268
23328
  * ordering between polls.
23269
23329
  */
23270
23330
  priority: number()
23271
- })).readonly() });
23331
+ });
23332
+ /**
23333
+ * Where the advertised local port came from. Ordered most β†’ least
23334
+ * authoritative, and the whole point of returning it: a client must be able to
23335
+ * tell a FACT about the hub's socket from an echo of its own guess.
23336
+ */
23337
+ var LocalPortSourceEnum = _enum([
23338
+ "server-config",
23339
+ "server-env",
23340
+ "caller-hint",
23341
+ "default"
23342
+ ]);
23343
+ /** The port every LAN/loopback `baseUrl` in the same result was built with. */
23344
+ var AdvertisedLocalPortSchema = object({
23345
+ port: number().int().min(1).max(65535),
23346
+ source: LocalPortSourceEnum
23347
+ });
23348
+ var GetConnectionEndpointsResultSchema = object({
23349
+ endpoints: array(ConnectionEndpointSchema).readonly(),
23350
+ /**
23351
+ * The port the hub built the LAN/loopback URLs with, and where that number
23352
+ * came from.
23353
+ *
23354
+ * Returned rather than merely applied, because "the URL is right" and "the
23355
+ * client can KNOW the URL is right" are different properties. A client that
23356
+ * only sees a corrected URL cannot distinguish a hub that fixed the port from
23357
+ * a hub that echoed the port the client sent, so it cannot decide whether to
23358
+ * race the candidate or discard it. With `source` it can: anything but
23359
+ * `caller-hint` is the hub's own socket.
23360
+ *
23361
+ * Absent on hubs predating this field β€” a client that finds it missing is
23362
+ * talking to an echoing hub and must degrade exactly as it does for
23363
+ * `caller-hint`.
23364
+ */
23365
+ localPort: AdvertisedLocalPortSchema
23366
+ });
23272
23367
  /**
23273
23368
  * The chosen outbound endpoint for notification artifacts. `baseUrl: null` =
23274
23369
  * AUTO (resolved from the candidate ranking at send time); `resolved` reports
@@ -23289,8 +23384,13 @@ var AllowedAddressesSchema = object({
23289
23384
  */
23290
23385
  addresses: array(string()).readonly() });
23291
23386
  method(_void(), ListResultSchema), method(_void(), PreferredSchema), method(object({
23292
- /** Local hub HTTP port to use in base URLs. */
23293
- port: number().int().min(1).max(65535),
23387
+ /**
23388
+ * LEGACY HINT β€” do not send from new code. Kept optional so clients
23389
+ * written against the echoing contract keep working; the hub uses it
23390
+ * only when it cannot read its own port, and says so via
23391
+ * `localPort.source === 'caller-hint'`.
23392
+ */
23393
+ port: number().int().min(1).max(65535).optional(),
23294
23394
  /** Include `http(s)://127.0.0.1:<port>` as the lowest-priority
23295
23395
  * candidate. Default `true`. */
23296
23396
  includeLoopback: boolean().optional(),
@@ -34251,7 +34351,6 @@ var NC_AUDIO_DEFAULTS = {
34251
34351
  hitPercent: 60,
34252
34352
  samplingSeconds: 10
34253
34353
  };
34254
- new Map(AUDIO_MACRO_LABELS.flatMap((macro) => macro.icon === void 0 ? [] : [[macro.id, macro.icon]]));
34255
34354
  new Set(["devices", "classes"]);
34256
34355
  NC_AUDIO_DEFAULTS.hitPercent, NC_AUDIO_DEFAULTS.samplingSeconds;
34257
34356
  /**
@@ -34485,6 +34584,39 @@ TimelapseRuleInputSchema.extend({
34485
34584
  createdAt: number(),
34486
34585
  updatedAt: number()
34487
34586
  });
34587
+ Object.freeze(Object.fromEntries([{
34588
+ stepId: "face-embedding",
34589
+ label: "Face recognition model",
34590
+ defaultModelId: "arcface-r100",
34591
+ indexName: "the enrolled face gallery",
34592
+ options: [
34593
+ {
34594
+ id: "arcface-r100",
34595
+ label: "ArcFace (ResNet34)"
34596
+ },
34597
+ {
34598
+ id: "auraface-r100",
34599
+ label: "AuraFace R100"
34600
+ },
34601
+ {
34602
+ id: "inception-resnet-v1",
34603
+ label: "Inception ResNet V1"
34604
+ }
34605
+ ]
34606
+ }, {
34607
+ stepId: "clip-embedding",
34608
+ label: "Semantic search model",
34609
+ defaultModelId: "mobileclip-s1",
34610
+ indexName: "the object semantic-search index",
34611
+ options: [{
34612
+ id: "mobileclip-s1",
34613
+ label: "MobileCLIP S1"
34614
+ }, {
34615
+ id: "mobileclip-s2",
34616
+ label: "MobileCLIP S2"
34617
+ }]
34618
+ }].map((s) => [s.stepId, s.defaultModelId])));
34619
+ string().min(1);
34488
34620
  object({
34489
34621
  /**
34490
34622
  * Fraction of the box's own size added on EACH side before cutting.
@@ -34505,10 +34637,21 @@ object({
34505
34637
  */
34506
34638
  square: boolean()
34507
34639
  });
34508
- ({
34640
+ /**
34641
+ * The convention in force when nobody has configured one β€” byte-for-byte the
34642
+ * behaviour of the pre-unification LIVE path (`DETAIL_CROP_PADDING_RATIO`).
34643
+ */
34644
+ var DEFAULT_DETAIL_CROP_CONVENTION = {
34509
34645
  paddingRatio: .15,
34510
34646
  square: false
34511
- }).paddingRatio;
34647
+ };
34648
+ Object.freeze({
34649
+ x: 0,
34650
+ y: 0,
34651
+ w: 1,
34652
+ h: 1
34653
+ });
34654
+ DEFAULT_DETAIL_CROP_CONVENTION.paddingRatio;
34512
34655
  /**
34513
34656
  * WHICH delivered frames the decode worker retains a native copy of.
34514
34657
  *
@@ -94273,7 +94416,7 @@ function isConnectionLike(value) {
94273
94416
  return isRecord$1(value) && typeof value["hasEventNotifications"] === "function";
94274
94417
  }
94275
94418
  function isIterable$1(value) {
94276
- return isRecord$1(value) && typeof value[Symbol.iterator] === "function";
94419
+ return isRecord$1(value) && typeof Reflect.get(value, Symbol.iterator) === "function";
94277
94420
  }
94278
94421
  /** `accessory._server.httpServer.connections`, or null at any missing hop. */
94279
94422
  function readConnections$1(accessory) {
@@ -94735,7 +94878,7 @@ function isRecord(value) {
94735
94878
  return typeof value === "object" && value !== null;
94736
94879
  }
94737
94880
  function isIterable(value) {
94738
- return isRecord(value) && typeof value[Symbol.iterator] === "function";
94881
+ return isRecord(value) && typeof Reflect.get(value, Symbol.iterator) === "function";
94739
94882
  }
94740
94883
  function isAccessoryInfoLike(value) {
94741
94884
  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
@@ -19398,6 +19428,12 @@ var CameraStatusSchema = object({
19398
19428
  /** Unix timestamp (ms) when this snapshot was composed server-side. */
19399
19429
  fetchedAt: number()
19400
19430
  });
19431
+ var InferenceDeviceExclusionReasonSchema = _enum([
19432
+ "disabled",
19433
+ "unavailable",
19434
+ "cannot-host-camera-root",
19435
+ "accelerator-preferred"
19436
+ ]);
19401
19437
  var NodeInferenceDeviceSchema = object({
19402
19438
  /** Stable per-node device key, e.g. `openvino:npu`, `edgetpu:usb`, `cpu`. */
19403
19439
  key: string(),
@@ -19428,7 +19464,17 @@ var NodeInferenceDeviceSchema = object({
19428
19464
  * available per format; this is the stored selection that becomes the
19429
19465
  * default for EVERY camera landing on this accelerator.
19430
19466
  */
19431
- steps: record(string(), DeviceStepConfigSchema).optional()
19467
+ steps: record(string(), DeviceStepConfigSchema).optional(),
19468
+ /**
19469
+ * `null` when the device IS a camera-root candidate on this node; otherwise
19470
+ * the reason the dispatcher drops it. Computed by the SAME
19471
+ * `resolveInferenceDeviceEligibility` the dispatcher runs, so this view can
19472
+ * never disagree with the election β€” deriving it in the UI from
19473
+ * `enabled`/`available` would silently miss `cannot-host-camera-root` (needs
19474
+ * the node's model catalog) and `accelerator-preferred` (needs the node-wide
19475
+ * "an accelerator is serving" predicate).
19476
+ */
19477
+ exclusion: InferenceDeviceExclusionReasonSchema.nullable()
19432
19478
  });
19433
19479
  var NodeInferenceDevicesSchema = object({
19434
19480
  nodeId: string(),
@@ -19933,6 +19979,7 @@ DeviceType.Camera, method(object({
19933
19979
  isBattery: boolean(),
19934
19980
  reason: _enum([
19935
19981
  "disabled",
19982
+ "offline",
19936
19983
  "sleeping",
19937
19984
  "unreachable",
19938
19985
  "waking"
@@ -19978,9 +20025,17 @@ targets: array(object({
19978
20025
  sleeping: boolean(),
19979
20026
  /** Current device state rendered over the cached frame. State images
19980
20027
  * remain authoritative even when their photographic background is
19981
- * old; null means the link must carry a current camera frame. */
20028
+ * old; null means the link must carry a current camera frame.
20029
+ *
20030
+ * **This is the ONLY source a surface may derive an inactive tile
20031
+ * from.** A client that reads a device's `online`/`disabled` flags and
20032
+ * draws its own verdict will disagree with the pixels it is painting
20033
+ * β€” the frame comes from here, and so must the sentence over it
20034
+ * (D190). Pair with `ageMs` for the age of the photograph behind the
20035
+ * state. */
19982
20036
  stateReason: _enum([
19983
20037
  "disabled",
20038
+ "offline",
19984
20039
  "sleeping",
19985
20040
  "unreachable",
19986
20041
  "waking"
@@ -23213,7 +23268,12 @@ var ListResultSchema = object({
23213
23268
  probedAt: number()
23214
23269
  });
23215
23270
  var PreferredSchema = LocalInterfaceSchema.nullable();
23216
- var GetConnectionEndpointsResultSchema = object({ endpoints: array(object({
23271
+ /**
23272
+ * Candidate base URL for the SDK to race on connect. Order matters β€”
23273
+ * the SDK should attempt these top-to-bottom with a short per-candidate
23274
+ * timeout (e.g. 1500ms) and cache the winner for the session.
23275
+ */
23276
+ var ConnectionEndpointSchema = object({
23217
23277
  /** Operator-facing label (e.g. "LAN β€” en0", "Public tunnel"). */
23218
23278
  label: string(),
23219
23279
  /** Fully-formed base URL with scheme + host + port. */
@@ -23256,7 +23316,42 @@ var GetConnectionEndpointsResultSchema = object({ endpoints: array(object({
23256
23316
  * ordering between polls.
23257
23317
  */
23258
23318
  priority: number()
23259
- })).readonly() });
23319
+ });
23320
+ /**
23321
+ * Where the advertised local port came from. Ordered most β†’ least
23322
+ * authoritative, and the whole point of returning it: a client must be able to
23323
+ * tell a FACT about the hub's socket from an echo of its own guess.
23324
+ */
23325
+ var LocalPortSourceEnum = _enum([
23326
+ "server-config",
23327
+ "server-env",
23328
+ "caller-hint",
23329
+ "default"
23330
+ ]);
23331
+ /** The port every LAN/loopback `baseUrl` in the same result was built with. */
23332
+ var AdvertisedLocalPortSchema = object({
23333
+ port: number().int().min(1).max(65535),
23334
+ source: LocalPortSourceEnum
23335
+ });
23336
+ var GetConnectionEndpointsResultSchema = object({
23337
+ endpoints: array(ConnectionEndpointSchema).readonly(),
23338
+ /**
23339
+ * The port the hub built the LAN/loopback URLs with, and where that number
23340
+ * came from.
23341
+ *
23342
+ * Returned rather than merely applied, because "the URL is right" and "the
23343
+ * client can KNOW the URL is right" are different properties. A client that
23344
+ * only sees a corrected URL cannot distinguish a hub that fixed the port from
23345
+ * a hub that echoed the port the client sent, so it cannot decide whether to
23346
+ * race the candidate or discard it. With `source` it can: anything but
23347
+ * `caller-hint` is the hub's own socket.
23348
+ *
23349
+ * Absent on hubs predating this field β€” a client that finds it missing is
23350
+ * talking to an echoing hub and must degrade exactly as it does for
23351
+ * `caller-hint`.
23352
+ */
23353
+ localPort: AdvertisedLocalPortSchema
23354
+ });
23260
23355
  /**
23261
23356
  * The chosen outbound endpoint for notification artifacts. `baseUrl: null` =
23262
23357
  * AUTO (resolved from the candidate ranking at send time); `resolved` reports
@@ -23277,8 +23372,13 @@ var AllowedAddressesSchema = object({
23277
23372
  */
23278
23373
  addresses: array(string()).readonly() });
23279
23374
  method(_void(), ListResultSchema), method(_void(), PreferredSchema), method(object({
23280
- /** Local hub HTTP port to use in base URLs. */
23281
- port: number().int().min(1).max(65535),
23375
+ /**
23376
+ * LEGACY HINT β€” do not send from new code. Kept optional so clients
23377
+ * written against the echoing contract keep working; the hub uses it
23378
+ * only when it cannot read its own port, and says so via
23379
+ * `localPort.source === 'caller-hint'`.
23380
+ */
23381
+ port: number().int().min(1).max(65535).optional(),
23282
23382
  /** Include `http(s)://127.0.0.1:<port>` as the lowest-priority
23283
23383
  * candidate. Default `true`. */
23284
23384
  includeLoopback: boolean().optional(),
@@ -34239,7 +34339,6 @@ var NC_AUDIO_DEFAULTS = {
34239
34339
  hitPercent: 60,
34240
34340
  samplingSeconds: 10
34241
34341
  };
34242
- new Map(AUDIO_MACRO_LABELS.flatMap((macro) => macro.icon === void 0 ? [] : [[macro.id, macro.icon]]));
34243
34342
  new Set(["devices", "classes"]);
34244
34343
  NC_AUDIO_DEFAULTS.hitPercent, NC_AUDIO_DEFAULTS.samplingSeconds;
34245
34344
  /**
@@ -34473,6 +34572,39 @@ TimelapseRuleInputSchema.extend({
34473
34572
  createdAt: number(),
34474
34573
  updatedAt: number()
34475
34574
  });
34575
+ Object.freeze(Object.fromEntries([{
34576
+ stepId: "face-embedding",
34577
+ label: "Face recognition model",
34578
+ defaultModelId: "arcface-r100",
34579
+ indexName: "the enrolled face gallery",
34580
+ options: [
34581
+ {
34582
+ id: "arcface-r100",
34583
+ label: "ArcFace (ResNet34)"
34584
+ },
34585
+ {
34586
+ id: "auraface-r100",
34587
+ label: "AuraFace R100"
34588
+ },
34589
+ {
34590
+ id: "inception-resnet-v1",
34591
+ label: "Inception ResNet V1"
34592
+ }
34593
+ ]
34594
+ }, {
34595
+ stepId: "clip-embedding",
34596
+ label: "Semantic search model",
34597
+ defaultModelId: "mobileclip-s1",
34598
+ indexName: "the object semantic-search index",
34599
+ options: [{
34600
+ id: "mobileclip-s1",
34601
+ label: "MobileCLIP S1"
34602
+ }, {
34603
+ id: "mobileclip-s2",
34604
+ label: "MobileCLIP S2"
34605
+ }]
34606
+ }].map((s) => [s.stepId, s.defaultModelId])));
34607
+ string().min(1);
34476
34608
  object({
34477
34609
  /**
34478
34610
  * Fraction of the box's own size added on EACH side before cutting.
@@ -34493,10 +34625,21 @@ object({
34493
34625
  */
34494
34626
  square: boolean()
34495
34627
  });
34496
- ({
34628
+ /**
34629
+ * The convention in force when nobody has configured one β€” byte-for-byte the
34630
+ * behaviour of the pre-unification LIVE path (`DETAIL_CROP_PADDING_RATIO`).
34631
+ */
34632
+ var DEFAULT_DETAIL_CROP_CONVENTION = {
34497
34633
  paddingRatio: .15,
34498
34634
  square: false
34499
- }).paddingRatio;
34635
+ };
34636
+ Object.freeze({
34637
+ x: 0,
34638
+ y: 0,
34639
+ w: 1,
34640
+ h: 1
34641
+ });
34642
+ DEFAULT_DETAIL_CROP_CONVENTION.paddingRatio;
34500
34643
  /**
34501
34644
  * WHICH delivered frames the decode worker retains a native copy of.
34502
34645
  *
@@ -94261,7 +94404,7 @@ function isConnectionLike(value) {
94261
94404
  return isRecord$1(value) && typeof value["hasEventNotifications"] === "function";
94262
94405
  }
94263
94406
  function isIterable$1(value) {
94264
- return isRecord$1(value) && typeof value[Symbol.iterator] === "function";
94407
+ return isRecord$1(value) && typeof Reflect.get(value, Symbol.iterator) === "function";
94265
94408
  }
94266
94409
  /** `accessory._server.httpServer.connections`, or null at any missing hop. */
94267
94410
  function readConnections$1(accessory) {
@@ -94723,7 +94866,7 @@ function isRecord(value) {
94723
94866
  return typeof value === "object" && value !== null;
94724
94867
  }
94725
94868
  function isIterable(value) {
94726
- return isRecord(value) && typeof value[Symbol.iterator] === "function";
94869
+ return isRecord(value) && typeof Reflect.get(value, Symbol.iterator) === "function";
94727
94870
  }
94728
94871
  function isAccessoryInfoLike(value) {
94729
94872
  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.36",
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",