@camstack/addon-pipeline 1.2.103 → 1.2.105
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-utils-CLc6yHCN.js → addon-utils-UzUMfVj1.js} +1 -1
- package/dist/audio-analyzer/index.js +3 -3
- package/dist/audio-analyzer/index.mjs +2 -2
- package/dist/detection-pipeline/index.js +1188 -127
- package/dist/detection-pipeline/index.mjs +1186 -125
- package/dist/{dist-Ccmt3fGJ.mjs → dist-BSWr9Qg8.mjs} +296 -11
- package/dist/{dist-C11WuNUP.js → dist-DVMPCqaj.js} +313 -10
- package/dist/{event-loop-stall-monitor-Cq_NeC4o.js → event-loop-stall-monitor-BazdZ0g0.js} +82 -88
- package/dist/{event-loop-stall-monitor-OJrOMeuu.mjs → event-loop-stall-monitor-BeQHivuY.mjs} +82 -88
- package/dist/{lazy-sharp-RxUs6on_.js → lazy-sharp-Du1-XaNP.js} +1 -1
- package/dist/motion-wasm/index.js +2 -2
- package/dist/motion-wasm/index.mjs +1 -1
- package/dist/pipeline-runner/index.js +8 -6
- package/dist/pipeline-runner/index.mjs +6 -4
- package/dist/{process-memory-DOjQ3MgC.js → process-memory-CiNyC-wv.js} +1 -1
- package/dist/{process-memory-D0zDmXLI.mjs → process-memory-DFL51gCx.mjs} +1 -1
- package/dist/recorder/index.js +660 -130
- package/dist/recorder/index.mjs +659 -129
- package/dist/remote-restream-BeHi78PZ.mjs +25 -0
- package/dist/remote-restream-CO36Sr30.js +36 -0
- package/dist/restream-intent-B4BXZra7.mjs +72 -0
- package/dist/{remote-restream-BYbAsgUf.js → restream-intent-Cv9x3jmu.js} +30 -30
- package/dist/session-decode/decode-worker-child.js +2 -2
- package/dist/session-decode/decode-worker-child.mjs +1 -1
- package/dist/stream-broker/_stub.js +1 -1
- package/dist/stream-broker/{_virtual_mf-localSharedImportMap___mfe_internal__addon_stream_broker_widgets-BdgcF1lL.mjs → _virtual_mf-localSharedImportMap___mfe_internal__addon_stream_broker_widgets-pkzutnza.mjs} +3 -3
- package/dist/stream-broker/_virtual_mf___mfe_internal__addon_stream_broker_widgets__loadShare___mf_0_camstack_mf_1_types__loadShare__.js-DvZWLWk1.mjs +26 -0
- package/dist/stream-broker/{hostInit-Da9wVA2r.mjs → hostInit-B1i1rtBB.mjs} +3 -3
- package/dist/stream-broker/index.js +598 -82
- package/dist/stream-broker/index.mjs +597 -81
- package/dist/stream-broker/remoteEntry.js +1 -1
- package/dist/{worker-protocol-DDpliBIW.mjs → worker-protocol-Clcy8PvY.mjs} +1 -1
- package/dist/{worker-protocol-BePduZVV.js → worker-protocol-pUUt-yhh.js} +1 -1
- package/package.json +1 -1
- package/python/inference_pool.py +238 -2
- package/python/postprocessors/__init__.py +4 -0
- package/python/postprocessors/ctc.py +52 -0
- package/python/postprocessors/plate_slots.py +180 -0
- package/python/postprocessors/test_ctc.py +39 -0
- package/python/postprocessors/test_plate_slots.py +217 -0
- package/python/postprocessors/test_yolonas.py +83 -0
- package/python/postprocessors/yolonas.py +67 -0
- package/python/test_inference_pool_backpressure.py +6 -2
- package/python/test_inference_pool_coreml_cache.py +12 -4
- package/python/test_inference_pool_device_selection.py +12 -4
- package/python/test_inference_pool_layout.py +16 -5
- package/python/test_inference_pool_memstats.py +6 -2
- package/python/test_inference_pool_ov_ppp.py +12 -9
- package/python/test_inference_pool_preprocess.py +57 -0
- package/python/test_inference_pool_reconfigure.py +122 -0
- package/python/test_inference_pool_static_batch.py +426 -0
- package/dist/remote-restream-Ci7RXNGb.mjs +0 -66
- package/dist/stream-broker/_virtual_mf___mfe_internal__addon_stream_broker_widgets__loadShare___mf_0_camstack_mf_1_types__loadShare__.js-DY31bUCj.mjs +0 -26
|
@@ -8545,12 +8545,25 @@ var RecordingBandSchema = object({
|
|
|
8545
8545
|
* segment is ever finalized and the camera records nothing anyway. At the 10 s
|
|
8546
8546
|
* default segment length, 30 s leaves room for two full segments. `preBufferSec`
|
|
8547
8547
|
* is retroactive only — it costs nothing at record time, it merely keeps
|
|
8548
|
-
* already-written segments
|
|
8548
|
+
* already-written segments.
|
|
8549
8549
|
*
|
|
8550
|
-
*
|
|
8550
|
+
* ## Why `preBufferSec` is 15 and not one segment length
|
|
8551
|
+
*
|
|
8552
|
+
* It has to cover the broker's RECORDING pre-roll, which is media handed to the
|
|
8553
|
+
* writer from BEFORE the trigger (D192/D193). If this bound were narrower, the
|
|
8554
|
+
* keep gate would delete the very seconds the ring just supplied — two
|
|
8555
|
+
* authorities disagreeing about the same footage, which is the failure D191 was
|
|
8556
|
+
* written against. It is therefore set to `RECORDING_PRE_ROLL_MAX_MS` (15 s),
|
|
8557
|
+
* the widest window the broker can be configured to serve, so an operator
|
|
8558
|
+
* raising the cluster pre-roll can never walk past the gate silently. The
|
|
8559
|
+
* addon-side guard is
|
|
8560
|
+
* `packages/addon-pipeline/src/recorder/addon/__tests__/band-decision.spec.ts`.
|
|
8561
|
+
*
|
|
8562
|
+
* An EXPLICIT `0` is left alone: that is an operator statement, not an omission,
|
|
8563
|
+
* and it is excluded from that invariant by name.
|
|
8551
8564
|
*/
|
|
8552
8565
|
var DEFAULT_EVENTS_BAND_BUFFER_SEC = {
|
|
8553
|
-
preBufferSec:
|
|
8566
|
+
preBufferSec: 15,
|
|
8554
8567
|
postBufferSec: 30
|
|
8555
8568
|
};
|
|
8556
8569
|
DEFAULT_EVENTS_BAND_BUFFER_SEC.postBufferSec * 1e3;
|
|
@@ -17883,7 +17896,7 @@ var TrackEnvelopeSchema = object({
|
|
|
17883
17896
|
* `snapshots[]` references — megabytes across a page of tracks. `slim`
|
|
17884
17897
|
* keeps every scalar the list surfaces actually render (ids, class(es),
|
|
17885
17898
|
* label / audioLabels / importance enrichment, firstSeen/lastSeen, state,
|
|
17886
|
-
* zonesVisited, bestEventId, envelope, hasFace, hasRider) and returns `positions` /
|
|
17899
|
+
* zonesVisited, bestEventId, envelope, hasFace, hasEmbeddedFace, hasRider) and returns `positions` /
|
|
17887
17900
|
* `snapshots` as EMPTY arrays — detail views re-fetch the full row via
|
|
17888
17901
|
* `getTrack`. Mirrors the event-store `projection` convention
|
|
17889
17902
|
* (`getObjectEvents` et al.).
|
|
@@ -18178,6 +18191,35 @@ var TrackSchema = object({
|
|
|
18178
18191
|
*/
|
|
18179
18192
|
hasFace: boolean().optional(),
|
|
18180
18193
|
/**
|
|
18194
|
+
* This track has a face row IN THE GALLERY: a crop **and** an embedding — a
|
|
18195
|
+
* face an operator could ASSIGN to an identity.
|
|
18196
|
+
*
|
|
18197
|
+
* The STRICT twin of {@link hasFace}, and the pair only earns its keep
|
|
18198
|
+
* because the two disagree. `hasFace` is stamped at the TOP of the face
|
|
18199
|
+
* branch, before every gate, and means no more than "a face detector produced
|
|
18200
|
+
* a face detail". This one is stamped at the single moment the gallery row
|
|
18201
|
+
* LANDS — after `FaceRecognizer.onTrackEnd` successfully persists it, i.e.
|
|
18202
|
+
* past the embedding-magnitude verdict, the `minFacePx` detection gate, the
|
|
18203
|
+
* candidate gate, the imageless-track drop (no crop was ever captured) and
|
|
18204
|
+
* the crop-store drop. Everything between the detector and that insert can
|
|
18205
|
+
* legitimately refuse the face, so a flag written any earlier promises the
|
|
18206
|
+
* operator something to assign and delivers nothing.
|
|
18207
|
+
*
|
|
18208
|
+
* **Independent of recognition.** A face collected but never auto-matched is
|
|
18209
|
+
* still assignable — it is in fact the face an operator most wants to reach —
|
|
18210
|
+
* so this is NOT gated on `recognizedIdentityId`. Recognition lands in
|
|
18211
|
+
* `subLabel`; this says only that the raw material exists.
|
|
18212
|
+
*
|
|
18213
|
+
* **Set once, never cleared.** A track that produced a gallery row produced
|
|
18214
|
+
* one; deleting the row later is the gallery's business, not this flag's.
|
|
18215
|
+
*
|
|
18216
|
+
* **Absent ≠ false**, the same rule as {@link hasFace}: every row written
|
|
18217
|
+
* before the column omits it, and so does every server that predates the
|
|
18218
|
+
* field. A consumer must test `=== true` and render nothing otherwise —
|
|
18219
|
+
* never infer "no assignable face".
|
|
18220
|
+
*/
|
|
18221
|
+
hasEmbeddedFace: boolean().optional(),
|
|
18222
|
+
/**
|
|
18181
18223
|
* This subject CONTAINS a folded rider — a person the rider-pairing step
|
|
18182
18224
|
* ([D34](../decisions/adr-0034.md)) removed from the frame BEFORE the tracker,
|
|
18183
18225
|
* so the passage is tracked once and as a VEHICLE.
|
|
@@ -19685,6 +19727,26 @@ var DetailResultSchema = object({
|
|
|
19685
19727
|
* the consuming gate treats as accept — never as reject.
|
|
19686
19728
|
*/
|
|
19687
19729
|
embeddingMagnitude: number().optional(),
|
|
19730
|
+
/**
|
|
19731
|
+
* Model that produced `embedding` — the SAME contract `labelModelId` has for
|
|
19732
|
+
* `label`, and for the same reason: the producing node is the only side that
|
|
19733
|
+
* knows which model actually ran, and re-deriving it downstream is exactly
|
|
19734
|
+
* the inference this model exists to forbid.
|
|
19735
|
+
*
|
|
19736
|
+
* Additive and optional, so a runner that predates it degrades to
|
|
19737
|
+
* "unmeasurable" rather than to a wrong answer — the consumer falls back to
|
|
19738
|
+
* its previous assumption instead of refusing.
|
|
19739
|
+
*
|
|
19740
|
+
* Its absence was not cosmetic. `FaceRecognizer` needs the probe's model id
|
|
19741
|
+
* to use `face-matcher`'s same-model gate (`sample.modelId !== probe.modelId`);
|
|
19742
|
+
* with nothing on the wire it took the id from the GALLERY, so the gate
|
|
19743
|
+
* compared the gallery against itself and could never fire. That turned the
|
|
19744
|
+
* one guard protecting the face feature space into a tautology, and it is
|
|
19745
|
+
* why swapping `face-embedding`'s model would NOT have stranded the enrolled
|
|
19746
|
+
* gallery as the catalog comment predicts — it would have scored the new
|
|
19747
|
+
* model's vectors against the old model's samples in one cosine space.
|
|
19748
|
+
*/
|
|
19749
|
+
embeddingModelId: string().optional(),
|
|
19688
19750
|
label: string().optional(),
|
|
19689
19751
|
/**
|
|
19690
19752
|
* The tier `label` occupies, copied VERBATIM from the producing step's
|
|
@@ -20702,6 +20764,12 @@ var CameraStatusSchema = object({
|
|
|
20702
20764
|
/** Unix timestamp (ms) when this snapshot was composed server-side. */
|
|
20703
20765
|
fetchedAt: number()
|
|
20704
20766
|
});
|
|
20767
|
+
var InferenceDeviceExclusionReasonSchema = _enum([
|
|
20768
|
+
"disabled",
|
|
20769
|
+
"unavailable",
|
|
20770
|
+
"cannot-host-camera-root",
|
|
20771
|
+
"accelerator-preferred"
|
|
20772
|
+
]);
|
|
20705
20773
|
var NodeInferenceDeviceSchema = object({
|
|
20706
20774
|
/** Stable per-node device key, e.g. `openvino:npu`, `edgetpu:usb`, `cpu`. */
|
|
20707
20775
|
key: string(),
|
|
@@ -20732,7 +20800,17 @@ var NodeInferenceDeviceSchema = object({
|
|
|
20732
20800
|
* available per format; this is the stored selection that becomes the
|
|
20733
20801
|
* default for EVERY camera landing on this accelerator.
|
|
20734
20802
|
*/
|
|
20735
|
-
steps: record(string(), DeviceStepConfigSchema).optional()
|
|
20803
|
+
steps: record(string(), DeviceStepConfigSchema).optional(),
|
|
20804
|
+
/**
|
|
20805
|
+
* `null` when the device IS a camera-root candidate on this node; otherwise
|
|
20806
|
+
* the reason the dispatcher drops it. Computed by the SAME
|
|
20807
|
+
* `resolveInferenceDeviceEligibility` the dispatcher runs, so this view can
|
|
20808
|
+
* never disagree with the election — deriving it in the UI from
|
|
20809
|
+
* `enabled`/`available` would silently miss `cannot-host-camera-root` (needs
|
|
20810
|
+
* the node's model catalog) and `accelerator-preferred` (needs the node-wide
|
|
20811
|
+
* "an accelerator is serving" predicate).
|
|
20812
|
+
*/
|
|
20813
|
+
exclusion: InferenceDeviceExclusionReasonSchema.nullable()
|
|
20736
20814
|
});
|
|
20737
20815
|
var NodeInferenceDevicesSchema = object({
|
|
20738
20816
|
nodeId: string(),
|
|
@@ -21237,6 +21315,7 @@ DeviceType.Camera, method(object({
|
|
|
21237
21315
|
isBattery: boolean(),
|
|
21238
21316
|
reason: _enum([
|
|
21239
21317
|
"disabled",
|
|
21318
|
+
"offline",
|
|
21240
21319
|
"sleeping",
|
|
21241
21320
|
"unreachable",
|
|
21242
21321
|
"waking"
|
|
@@ -21282,9 +21361,17 @@ targets: array(object({
|
|
|
21282
21361
|
sleeping: boolean(),
|
|
21283
21362
|
/** Current device state rendered over the cached frame. State images
|
|
21284
21363
|
* remain authoritative even when their photographic background is
|
|
21285
|
-
* old; null means the link must carry a current camera frame.
|
|
21364
|
+
* old; null means the link must carry a current camera frame.
|
|
21365
|
+
*
|
|
21366
|
+
* **This is the ONLY source a surface may derive an inactive tile
|
|
21367
|
+
* from.** A client that reads a device's `online`/`disabled` flags and
|
|
21368
|
+
* draws its own verdict will disagree with the pixels it is painting
|
|
21369
|
+
* — the frame comes from here, and so must the sentence over it
|
|
21370
|
+
* (D190). Pair with `ageMs` for the age of the photograph behind the
|
|
21371
|
+
* state. */
|
|
21286
21372
|
stateReason: _enum([
|
|
21287
21373
|
"disabled",
|
|
21374
|
+
"offline",
|
|
21288
21375
|
"sleeping",
|
|
21289
21376
|
"unreachable",
|
|
21290
21377
|
"waking"
|
|
@@ -24643,7 +24730,12 @@ var ListResultSchema = object({
|
|
|
24643
24730
|
probedAt: number()
|
|
24644
24731
|
});
|
|
24645
24732
|
var PreferredSchema = LocalInterfaceSchema.nullable();
|
|
24646
|
-
|
|
24733
|
+
/**
|
|
24734
|
+
* Candidate base URL for the SDK to race on connect. Order matters —
|
|
24735
|
+
* the SDK should attempt these top-to-bottom with a short per-candidate
|
|
24736
|
+
* timeout (e.g. 1500ms) and cache the winner for the session.
|
|
24737
|
+
*/
|
|
24738
|
+
var ConnectionEndpointSchema = object({
|
|
24647
24739
|
/** Operator-facing label (e.g. "LAN — en0", "Public tunnel"). */
|
|
24648
24740
|
label: string(),
|
|
24649
24741
|
/** Fully-formed base URL with scheme + host + port. */
|
|
@@ -24686,7 +24778,42 @@ var GetConnectionEndpointsResultSchema = object({ endpoints: array(object({
|
|
|
24686
24778
|
* ordering between polls.
|
|
24687
24779
|
*/
|
|
24688
24780
|
priority: number()
|
|
24689
|
-
})
|
|
24781
|
+
});
|
|
24782
|
+
/**
|
|
24783
|
+
* Where the advertised local port came from. Ordered most → least
|
|
24784
|
+
* authoritative, and the whole point of returning it: a client must be able to
|
|
24785
|
+
* tell a FACT about the hub's socket from an echo of its own guess.
|
|
24786
|
+
*/
|
|
24787
|
+
var LocalPortSourceEnum = _enum([
|
|
24788
|
+
"server-config",
|
|
24789
|
+
"server-env",
|
|
24790
|
+
"caller-hint",
|
|
24791
|
+
"default"
|
|
24792
|
+
]);
|
|
24793
|
+
/** The port every LAN/loopback `baseUrl` in the same result was built with. */
|
|
24794
|
+
var AdvertisedLocalPortSchema = object({
|
|
24795
|
+
port: number().int().min(1).max(65535),
|
|
24796
|
+
source: LocalPortSourceEnum
|
|
24797
|
+
});
|
|
24798
|
+
var GetConnectionEndpointsResultSchema = object({
|
|
24799
|
+
endpoints: array(ConnectionEndpointSchema).readonly(),
|
|
24800
|
+
/**
|
|
24801
|
+
* The port the hub built the LAN/loopback URLs with, and where that number
|
|
24802
|
+
* came from.
|
|
24803
|
+
*
|
|
24804
|
+
* Returned rather than merely applied, because "the URL is right" and "the
|
|
24805
|
+
* client can KNOW the URL is right" are different properties. A client that
|
|
24806
|
+
* only sees a corrected URL cannot distinguish a hub that fixed the port from
|
|
24807
|
+
* a hub that echoed the port the client sent, so it cannot decide whether to
|
|
24808
|
+
* race the candidate or discard it. With `source` it can: anything but
|
|
24809
|
+
* `caller-hint` is the hub's own socket.
|
|
24810
|
+
*
|
|
24811
|
+
* Absent on hubs predating this field — a client that finds it missing is
|
|
24812
|
+
* talking to an echoing hub and must degrade exactly as it does for
|
|
24813
|
+
* `caller-hint`.
|
|
24814
|
+
*/
|
|
24815
|
+
localPort: AdvertisedLocalPortSchema
|
|
24816
|
+
});
|
|
24690
24817
|
/**
|
|
24691
24818
|
* The chosen outbound endpoint for notification artifacts. `baseUrl: null` =
|
|
24692
24819
|
* AUTO (resolved from the candidate ranking at send time); `resolved` reports
|
|
@@ -24707,8 +24834,13 @@ var AllowedAddressesSchema = object({
|
|
|
24707
24834
|
*/
|
|
24708
24835
|
addresses: array(string()).readonly() });
|
|
24709
24836
|
method(_void(), ListResultSchema), method(_void(), PreferredSchema), method(object({
|
|
24710
|
-
/**
|
|
24711
|
-
|
|
24837
|
+
/**
|
|
24838
|
+
* LEGACY HINT — do not send from new code. Kept optional so clients
|
|
24839
|
+
* written against the echoing contract keep working; the hub uses it
|
|
24840
|
+
* only when it cannot read its own port, and says so via
|
|
24841
|
+
* `localPort.source === 'caller-hint'`.
|
|
24842
|
+
*/
|
|
24843
|
+
port: number().int().min(1).max(65535).optional(),
|
|
24712
24844
|
/** Include `http(s)://127.0.0.1:<port>` as the lowest-priority
|
|
24713
24845
|
* candidate. Default `true`. */
|
|
24714
24846
|
includeLoopback: boolean().optional(),
|
|
@@ -36087,6 +36219,153 @@ TimelapseRuleInputSchema.extend({
|
|
|
36087
36219
|
createdAt: number(),
|
|
36088
36220
|
updatedAt: number()
|
|
36089
36221
|
});
|
|
36222
|
+
/**
|
|
36223
|
+
* A model choice has a SCOPE, and a scope change has a workflow.
|
|
36224
|
+
*
|
|
36225
|
+
* ## The two scopes
|
|
36226
|
+
*
|
|
36227
|
+
* Almost every pipeline step's model is a **node** question: which build runs
|
|
36228
|
+
* fastest on THIS accelerator. Two nodes may legitimately answer differently —
|
|
36229
|
+
* a Coral runs the tflite SSD, a Mac runs the coreml YOLO — because the answers
|
|
36230
|
+
* are compared against nothing. They produce boxes, and a box is a box.
|
|
36231
|
+
*
|
|
36232
|
+
* Two steps are not like that. `face-embedding` and `clip-embedding` produce
|
|
36233
|
+
* **vectors that land in ONE shared index** (`identity_samples`,
|
|
36234
|
+
* `vec_object_clip`) and are ranked against each other by cosine similarity.
|
|
36235
|
+
* Cosine similarity between two encoders is not a weak signal, it is a
|
|
36236
|
+
* meaningless number — and nothing inside a vector can tell you it happened.
|
|
36237
|
+
* So for those two steps the model is a **cluster** question with exactly one
|
|
36238
|
+
* answer, stored in exactly one row.
|
|
36239
|
+
*
|
|
36240
|
+
* That is the same argument [D52](../../../../docs/decisions/adr-0052.md) makes
|
|
36241
|
+
* for the crop convention (`detail-crop.ts`), one level up: the crop decides
|
|
36242
|
+
* WHAT pixels the encoder sees, this decides WHICH encoder sees them. Both are
|
|
36243
|
+
* cluster-wide for the same reason and neither may become per-node.
|
|
36244
|
+
*
|
|
36245
|
+
* ## Why the registry lives here and not in the step catalog
|
|
36246
|
+
*
|
|
36247
|
+
* The scope itself is declared on the step, in
|
|
36248
|
+
* `detection-pipeline/registry/step-definitions.ts` (`StepDefinition.modelScope`)
|
|
36249
|
+
* — that is where a new step declares what kind of choice its model is. But the
|
|
36250
|
+
* catalog lives inside `addon-pipeline`, and three packages that must NOT
|
|
36251
|
+
* import an addon need to know the set: the orchestrator (which renders and
|
|
36252
|
+
* stores the row), post-analysis (which pins the row for a re-embed pass) and
|
|
36253
|
+
* admin-ui (which mirrors it). So the set is mirrored here, and
|
|
36254
|
+
* `scripts/check-cluster-model-scope.ts` fails the build when the two disagree.
|
|
36255
|
+
* A hand-copied key that stops matching is exactly how a setting silently stops
|
|
36256
|
+
* arriving while both sides still look correct.
|
|
36257
|
+
*
|
|
36258
|
+
* ## The defaults ARE today's behaviour
|
|
36259
|
+
*
|
|
36260
|
+
* {@link DEFAULT_CLUSTER_STEP_MODELS} reproduces the catalog `defaultModelId`
|
|
36261
|
+
* of both steps. Declaring the scope therefore changes nothing on the day it
|
|
36262
|
+
* ships: the cluster row starts out saying what every node was already doing.
|
|
36263
|
+
* Changing it is legitimate — that is what the knob is for — but it invalidates
|
|
36264
|
+
* the stored vectors of that surface, and must be followed by a re-embed pass
|
|
36265
|
+
* (`face-reembed-pass.ts`, `embedding-rebuild.ts`).
|
|
36266
|
+
*/
|
|
36267
|
+
/**
|
|
36268
|
+
* The cluster-scoped steps. Mirrored from the catalog's `modelScope: 'cluster'`
|
|
36269
|
+
* declarations and guarded by `scripts/check-cluster-model-scope.ts`.
|
|
36270
|
+
*/
|
|
36271
|
+
var CLUSTER_MODEL_SCOPED_STEPS = [{
|
|
36272
|
+
stepId: "face-embedding",
|
|
36273
|
+
label: "Face recognition model",
|
|
36274
|
+
defaultModelId: "arcface-r100",
|
|
36275
|
+
indexName: "the enrolled face gallery",
|
|
36276
|
+
options: [
|
|
36277
|
+
{
|
|
36278
|
+
id: "arcface-r100",
|
|
36279
|
+
label: "ArcFace (ResNet34)"
|
|
36280
|
+
},
|
|
36281
|
+
{
|
|
36282
|
+
id: "auraface-r100",
|
|
36283
|
+
label: "AuraFace R100"
|
|
36284
|
+
},
|
|
36285
|
+
{
|
|
36286
|
+
id: "inception-resnet-v1",
|
|
36287
|
+
label: "Inception ResNet V1"
|
|
36288
|
+
}
|
|
36289
|
+
]
|
|
36290
|
+
}, {
|
|
36291
|
+
stepId: "clip-embedding",
|
|
36292
|
+
label: "Semantic search model",
|
|
36293
|
+
defaultModelId: "mobileclip-s1",
|
|
36294
|
+
indexName: "the object semantic-search index",
|
|
36295
|
+
options: [{
|
|
36296
|
+
id: "mobileclip-s1",
|
|
36297
|
+
label: "MobileCLIP S1"
|
|
36298
|
+
}, {
|
|
36299
|
+
id: "mobileclip-s2",
|
|
36300
|
+
label: "MobileCLIP S2"
|
|
36301
|
+
}]
|
|
36302
|
+
}];
|
|
36303
|
+
/**
|
|
36304
|
+
* The settings key holding one step's cluster model choice.
|
|
36305
|
+
*
|
|
36306
|
+
* Step-qualified so the keys stay unique across the addon's whole schema, which
|
|
36307
|
+
* is what lets {@link pickClusterStepModels} walk every section instead of
|
|
36308
|
+
* trusting the section id.
|
|
36309
|
+
*/
|
|
36310
|
+
function clusterModelSettingKey(stepId) {
|
|
36311
|
+
return `clusterModel:${stepId}`;
|
|
36312
|
+
}
|
|
36313
|
+
/** The cluster row when nobody has configured one — today's catalog defaults. */
|
|
36314
|
+
var DEFAULT_CLUSTER_STEP_MODELS = Object.freeze(Object.fromEntries(CLUSTER_MODEL_SCOPED_STEPS.map((s) => [s.stepId, s.defaultModelId])));
|
|
36315
|
+
/** A stored choice is a non-empty model id, or it is not a choice. */
|
|
36316
|
+
var ChosenModelIdSchema = string().min(1);
|
|
36317
|
+
/**
|
|
36318
|
+
* Narrow a FLAT settings record to the cluster row.
|
|
36319
|
+
*
|
|
36320
|
+
* Per-FIELD fallback, deliberately (same rule as `readDetailCropConvention`): a
|
|
36321
|
+
* junk face model must not also discard a valid clip model. An absent, empty or
|
|
36322
|
+
* non-string value resolves to the step's catalog default — the historical
|
|
36323
|
+
* behaviour — never to a blank id, because a blank id downstream becomes
|
|
36324
|
+
* "substitute the format default", which is precisely the substitution this
|
|
36325
|
+
* scope exists to forbid.
|
|
36326
|
+
*/
|
|
36327
|
+
function readClusterStepModels(config) {
|
|
36328
|
+
const out = {};
|
|
36329
|
+
for (const step of CLUSTER_MODEL_SCOPED_STEPS) {
|
|
36330
|
+
const parsed = ChosenModelIdSchema.safeParse(config[clusterModelSettingKey(step.stepId)]);
|
|
36331
|
+
out[step.stepId] = parsed.success ? parsed.data : step.defaultModelId;
|
|
36332
|
+
}
|
|
36333
|
+
return out;
|
|
36334
|
+
}
|
|
36335
|
+
function isHydratedField$2(entry) {
|
|
36336
|
+
return typeof entry === "object" && entry !== null && "key" in entry;
|
|
36337
|
+
}
|
|
36338
|
+
/**
|
|
36339
|
+
* Extract the cluster row from an `addon-settings.getGlobalSettings` payload.
|
|
36340
|
+
*
|
|
36341
|
+
* Walks EVERY section rather than looking inside {@link CLUSTER_MODEL_SECTION_ID}
|
|
36342
|
+
* alone: the keys are unique across the addon's schema, and a section rename
|
|
36343
|
+
* must not silently revert the whole cluster to the defaults. A `null` payload
|
|
36344
|
+
* (addon mid-boot) is the defaults.
|
|
36345
|
+
*/
|
|
36346
|
+
function pickClusterStepModels(view) {
|
|
36347
|
+
if (view === null) return DEFAULT_CLUSTER_STEP_MODELS;
|
|
36348
|
+
const flat = {};
|
|
36349
|
+
const wanted = new Set(CLUSTER_MODEL_SCOPED_STEPS.map((s) => clusterModelSettingKey(s.stepId)));
|
|
36350
|
+
for (const section of view.sections) for (const entry of section.fields) {
|
|
36351
|
+
if (!isHydratedField$2(entry) || typeof entry.key !== "string") continue;
|
|
36352
|
+
if (wanted.has(entry.key)) flat[entry.key] = entry.value;
|
|
36353
|
+
}
|
|
36354
|
+
return readClusterStepModels(flat);
|
|
36355
|
+
}
|
|
36356
|
+
/**
|
|
36357
|
+
* The cluster model for `stepId`, or `null` when the step is node-scoped.
|
|
36358
|
+
*
|
|
36359
|
+
* `null` is the signal to LEAVE THE CALLER'S RESOLUTION ALONE — it is not "no
|
|
36360
|
+
* model". Returning a default here for a node-scoped step would quietly
|
|
36361
|
+
* override every per-(node,device) selection in the fleet.
|
|
36362
|
+
*/
|
|
36363
|
+
function resolveClusterStepModelId(stepId, models) {
|
|
36364
|
+
const step = CLUSTER_MODEL_SCOPED_STEPS.find((s) => s.stepId === stepId);
|
|
36365
|
+
if (step === void 0) return null;
|
|
36366
|
+
const chosen = models[stepId];
|
|
36367
|
+
return chosen !== void 0 && chosen !== "" ? chosen : step.defaultModelId;
|
|
36368
|
+
}
|
|
36090
36369
|
var DETAIL_CROP_PADDING_KEY = "detailCropPaddingRatio";
|
|
36091
36370
|
var DETAIL_CROP_SQUARE_KEY = "detailCropSquare";
|
|
36092
36371
|
/**
|
|
@@ -36158,6 +36437,12 @@ function pickDetailCropConvention(view) {
|
|
|
36158
36437
|
}
|
|
36159
36438
|
return readDetailCropConvention(flat);
|
|
36160
36439
|
}
|
|
36440
|
+
Object.freeze({
|
|
36441
|
+
x: 0,
|
|
36442
|
+
y: 0,
|
|
36443
|
+
w: 1,
|
|
36444
|
+
h: 1
|
|
36445
|
+
});
|
|
36161
36446
|
DEFAULT_DETAIL_CROP_CONVENTION.paddingRatio;
|
|
36162
36447
|
/**
|
|
36163
36448
|
* Derive the crop rectangle for one parent detection.
|
|
@@ -37140,4 +37425,4 @@ function enumerateInferenceDevices(hw) {
|
|
|
37140
37425
|
return out;
|
|
37141
37426
|
}
|
|
37142
37427
|
//#endregion
|
|
37143
|
-
export {
|
|
37428
|
+
export { pipelineExecutorCapability as $, audioKindId as A, selectAssignedProfileSlots as At, detectionPipelineCapability as B, record as Bt, RECORDING_EXPORT_MAX_READ_BYTES as C, hydrateSchema as Ct, addonWidgetsSourceCapability as D, nodePin as Dt, YAMNET_TO_MACRO as E, makeSourceBrokerId as Et, defaultDeviceFor as F, discriminatedUnion as Ft, hfModelUrl as G, egressTransportFromRequest as H, union as Ht, defineCustomActions as I, lazy as It, motionDetectionCapability as J, mapAudioLabelToMacro as K, deriveBatteryPresence as L, literal as Lt, cameraStreamsCapability as M, _enum as Mt, createHwAccelCache as N, array as Nt, audioAnalysisCapability as O, parseJsonUnknown as Ot, customAction as P, boolean as Pt, pickNativeLeaseOverride as Q, deriveDetailCropRect as R, number as Rt, RATE_CONTROL_TIGHT as S, createEvent as St, RingBuffer as T, makeProfileBrokerId as Tt, enumerateInferenceDevices as U, EventCategory as Ut, egressTranscodeSharingKey as V, string as Vt, evaluateZoneRules as W, pickClusterStepModels as X, parseProcStatus as Y, pickDetailCropConvention as Z, NativeLeaseAdmissionSchema as _, isSoftwareDecode as _t, COCO_80_LABELS as a, resolvePoolMemoryPolicy as at, PoolMemoryWatchdog as b, DeviceFeature as bt, DEFAULT_CLUSTER_STEP_MODELS as c, storageEvictableCapability as ct, DEFAULT_NATIVE_LEASE_SETTINGS as d, webrtcSessionCapability as dt, pipelineRunnerCapability as et, DEVICE_BACKEND_TO_FORMAT as f, errMsg as ft, HF_BASE_URL as g, invocationFromEncodeProfile as gt, ExportRecordSchema as h, buildFfmpegArgs as ht, BatteryStatusSchema as i, resolveEgressDecodeHwAccel as it, batteryCapability as j, sleep as jt, audioAnalyzerCapability as k, parseProfileBrokerId as kt, DEFAULT_DETAIL_CROP_CONVENTION as l, streamBrokerCapability as lt, EncodeProfileSchema as m, Fmp4BoxSplitter as mt, AUDIO_BACKEND_CHOICES as n, recordingExportCapability as nt, COCO_TO_MACRO as o, resolveRecordingProfiles as ot, EVENT_PAD_MS as p, AUDIO_PRESETS as pt, maskUrlCredentials as q, AUDIO_MACRO_LABELS as r, resolveClusterStepModelId as rt, DEFAULT_AUDIO_ANALYZER_CONFIG as s, runtimeDevices as st, APPLE_SA_TO_MACRO as t, recordingCapability as tt, DEFAULT_EVENTS_BAND_BUFFER_SEC as u, supportedRuntimes as ut, NativeLeaseSettingsSchema as v, BaseAddon as vt, RecordingConfigSchema as w, isEvent as wt, RATE_CONTROL_RELAXED as x, DeviceType as xt, OpsLogEntrySchema as y, CAM_PROFILE_ORDER as yt, deriveRecordingMode as z, object as zt };
|