@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.
- package/dist/addon.js +138 -56
- package/dist/addon.mjs +138 -56
- 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:
|
|
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
|
-
}
|
|
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:
|
|
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
|
-
}
|
|
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