@camstack/addon-pipeline 1.2.621 → 1.2.623
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/audio-analyzer/index.js +3 -3
- package/dist/audio-analyzer/index.mjs +3 -3
- package/dist/{custom-model-catalog-Il8UY4D4.js → custom-model-catalog-BTBdgN2p.js} +29 -16
- package/dist/{custom-model-catalog-0_SnSXzN.mjs → custom-model-catalog-D5zTw1LU.mjs} +29 -10
- package/dist/detection-pipeline/index.js +67 -416
- package/dist/detection-pipeline/index.mjs +91 -440
- package/dist/{dist-ClkumZgv.js → dist-BVo3wa7s.js} +711 -302
- package/dist/{dist-DHqkQhTQ.mjs → dist-opSx6v5i.mjs} +651 -296
- package/dist/{model-catalogs-BagalaYp.js → model-catalogs-CQytR2AN.js} +1 -1
- package/dist/{model-catalogs-Z1GZAhSb.mjs → model-catalogs-rIvLUVlw.mjs} +1 -1
- package/dist/motion-wasm/index.js +1 -1
- package/dist/motion-wasm/index.mjs +1 -1
- package/dist/{node-CkJLxlWI.mjs → node-CGIYuJMN.mjs} +1 -1
- package/dist/{node-0O_61WVW.js → node-DqLsuN_A.js} +1 -1
- package/dist/pipeline-runner/index.js +115 -460
- package/dist/pipeline-runner/index.mjs +108 -453
- package/dist/{process-memory-Dj3UgL1e.mjs → process-memory-Bd-TuWfM.mjs} +1 -1
- package/dist/{process-memory-DdIOhjYB.js → process-memory-DyxG-0mG.js} +1 -1
- package/dist/recorder/index.js +2 -2
- package/dist/recorder/index.mjs +2 -2
- package/dist/{segment-demux-js-BePzacki.js → segment-demux-js-B4bfTQpK.js} +1 -1
- package/dist/{segment-demux-js-Bv0t0-tQ.mjs → segment-demux-js-CdVRzwSd.mjs} +1 -1
- package/dist/session-decode/decode-worker-main.js +12 -21
- package/dist/session-decode/decode-worker-main.mjs +12 -21
- package/dist/stream-broker/_stub.js +2 -2
- package/dist/stream-broker/{_virtual_mf-localSharedImportMap___mfe_internal__addon_stream_broker_widgets-dNk74ahz.mjs → _virtual_mf-localSharedImportMap___mfe_internal__addon_stream_broker_widgets-DF3FGCR8.mjs} +2 -2
- package/dist/stream-broker/_virtual_mf___mfe_internal__addon_stream_broker_widgets__loadShare___mf_0_camstack_mf_1_types__loadShare__.js-oUZNn2Kr.mjs +26 -0
- package/dist/stream-broker/_virtual_mf___mfe_internal__addon_stream_broker_widgets__loadShare___mf_0_camstack_mf_1_ui_mf_2_library__loadShare__.js-Bb-ETNGC.mjs +26 -0
- package/dist/stream-broker/demux-worker-child.js +1 -1
- package/dist/stream-broker/demux-worker-child.mjs +1 -1
- package/dist/stream-broker/{hostInit-CH5g78CJ.mjs → hostInit-BiyFzSqq.mjs} +2 -2
- package/dist/stream-broker/index.js +3 -3
- package/dist/stream-broker/index.mjs +3 -3
- package/dist/stream-broker/remoteEntry.js +1 -1
- package/dist/{worker-protocol-D_NzPcnh.mjs → worker-protocol-DngGEAT2.js} +102 -2
- package/dist/{worker-protocol-C-G8qmye.js → worker-protocol-_avq7y8O.mjs} +67 -25
- package/package.json +1 -1
- package/python/accelerator_facts.py +275 -0
- package/python/coreml_load_probe.py +105 -15
- package/python/inference_pool.py +19 -2
- package/python/openvino_compile_probe.py +72 -18
- package/python/postprocessors/ssd.py +12 -4
- package/python/postprocessors/test_ssd.py +64 -0
- package/python/test_accelerator_facts.py +105 -0
- package/python/test_coreml_load_probe.py +83 -0
- package/python/test_openvino_compile_probe.py +114 -0
- package/python/webgpu_isolated.py +19 -0
- package/dist/stream-broker/_virtual_mf___mfe_internal__addon_stream_broker_widgets__loadShare___mf_0_camstack_mf_1_types__loadShare__.js-2KkGoQ55.mjs +0 -26
- package/dist/stream-broker/_virtual_mf___mfe_internal__addon_stream_broker_widgets__loadShare___mf_0_camstack_mf_1_ui_mf_2_library__loadShare__.js-Dx-WrMx0.mjs +0 -26
|
@@ -3,11 +3,11 @@ Object.defineProperties(exports, {
|
|
|
3
3
|
[Symbol.toStringTag]: { value: "Module" }
|
|
4
4
|
});
|
|
5
5
|
const require_chunk = require("../chunk-emK7D4bc.js");
|
|
6
|
-
const require_dist = require("../dist-
|
|
7
|
-
const require_node = require("../node-
|
|
8
|
-
const require_custom_model_catalog = require("../custom-model-catalog-
|
|
6
|
+
const require_dist = require("../dist-BVo3wa7s.js");
|
|
7
|
+
const require_node = require("../node-DqLsuN_A.js");
|
|
8
|
+
const require_custom_model_catalog = require("../custom-model-catalog-BTBdgN2p.js");
|
|
9
9
|
const require_lazy_sharp = require("../lazy-sharp-BuwKlQLR.js");
|
|
10
|
-
const require_process_memory = require("../process-memory-
|
|
10
|
+
const require_process_memory = require("../process-memory-DyxG-0mG.js");
|
|
11
11
|
let node_os = require("node:os");
|
|
12
12
|
node_os = require_chunk.__toESM(node_os);
|
|
13
13
|
let node_fs = require("node:fs");
|
|
@@ -357,84 +357,6 @@ function normalizeEngineNodeId(rawNodeId) {
|
|
|
357
357
|
return raw.includes("/") ? raw.split("/")[0] ?? "hub" : raw;
|
|
358
358
|
}
|
|
359
359
|
//#endregion
|
|
360
|
-
//#region src/detection-pipeline/model-bound-device-overrides.ts
|
|
361
|
-
/**
|
|
362
|
-
* Auto tune (D745), the executor leg: list — and optionally remove — the
|
|
363
|
-
* MODEL-BOUND thresholds stored in this addon's per-camera settings (the
|
|
364
|
-
* object-detection root's `bindsToModel` keys and their binding keys, D738).
|
|
365
|
-
* Every other key of a camera's store is kept.
|
|
366
|
-
*
|
|
367
|
-
* The device store only MERGES on write, so a removal is clear + write of the
|
|
368
|
-
* kept keys — the idiom `migrate-hardware-state.ts` uses. Both run in this
|
|
369
|
-
* process, serialized per camera; a write that fails after the clear restores
|
|
370
|
-
* the original row, and the camera is reported `refused` rather than clean. A
|
|
371
|
-
* store that cannot be read is `refused` too: a failed read is never "nothing
|
|
372
|
-
* to clear" (D393).
|
|
373
|
-
*/
|
|
374
|
-
function errMsg(err) {
|
|
375
|
-
return err instanceof Error ? err.message : String(err);
|
|
376
|
-
}
|
|
377
|
-
/** The stored keys among `boundKeys` (values and bindings), sorted. */
|
|
378
|
-
function presentBoundKeys(row, boundKeys) {
|
|
379
|
-
return boundKeys.flatMap((k) => [k, require_dist.modelBindingKey(k)]).filter((k) => k in row).toSorted();
|
|
380
|
-
}
|
|
381
|
-
async function clearModelBoundDeviceOverrides(deps, input) {
|
|
382
|
-
const ids = input.deviceIds ?? await deps.listDeviceIds();
|
|
383
|
-
const entries = [];
|
|
384
|
-
const refused = [];
|
|
385
|
-
for (const deviceId of [...ids].toSorted((a, b) => a - b)) {
|
|
386
|
-
let row;
|
|
387
|
-
try {
|
|
388
|
-
row = await deps.readDeviceStore(deviceId);
|
|
389
|
-
} catch (err) {
|
|
390
|
-
refused.push({
|
|
391
|
-
deviceId,
|
|
392
|
-
reason: `read failed: ${errMsg(err)}`
|
|
393
|
-
});
|
|
394
|
-
continue;
|
|
395
|
-
}
|
|
396
|
-
const keys = presentBoundKeys(row, deps.boundKeys);
|
|
397
|
-
if (keys.length === 0) continue;
|
|
398
|
-
if (input.dryRun) {
|
|
399
|
-
entries.push({
|
|
400
|
-
deviceId,
|
|
401
|
-
keys
|
|
402
|
-
});
|
|
403
|
-
continue;
|
|
404
|
-
}
|
|
405
|
-
const kept = { ...row };
|
|
406
|
-
for (const k of keys) delete kept[k];
|
|
407
|
-
try {
|
|
408
|
-
await deps.clearDeviceStore(deviceId);
|
|
409
|
-
} catch (err) {
|
|
410
|
-
refused.push({
|
|
411
|
-
deviceId,
|
|
412
|
-
reason: `clear failed: ${errMsg(err)}`
|
|
413
|
-
});
|
|
414
|
-
continue;
|
|
415
|
-
}
|
|
416
|
-
try {
|
|
417
|
-
if (Object.keys(kept).length > 0) await deps.writeDeviceStore(deviceId, kept);
|
|
418
|
-
entries.push({
|
|
419
|
-
deviceId,
|
|
420
|
-
keys
|
|
421
|
-
});
|
|
422
|
-
} catch (err) {
|
|
423
|
-
await deps.writeDeviceStore(deviceId, row).catch(() => void 0);
|
|
424
|
-
refused.push({
|
|
425
|
-
deviceId,
|
|
426
|
-
reason: `write failed, row restored: ${errMsg(err)}`
|
|
427
|
-
});
|
|
428
|
-
} finally {
|
|
429
|
-
deps.invalidate(deviceId);
|
|
430
|
-
}
|
|
431
|
-
}
|
|
432
|
-
return {
|
|
433
|
-
entries,
|
|
434
|
-
refused
|
|
435
|
-
};
|
|
436
|
-
}
|
|
437
|
-
//#endregion
|
|
438
360
|
//#region src/detection-pipeline/model-format-facts.ts
|
|
439
361
|
/**
|
|
440
362
|
* Two per-format facts `getSchema` reports beside `downloaded`, for Model
|
|
@@ -769,122 +691,6 @@ var ClusterUnknownRefusalLog = class {
|
|
|
769
691
|
}
|
|
770
692
|
};
|
|
771
693
|
//#endregion
|
|
772
|
-
//#region src/detection-pipeline/device-override-mirror.ts
|
|
773
|
-
/**
|
|
774
|
-
* The per-device detection overrides, kept fresh OFF the frame path.
|
|
775
|
-
*
|
|
776
|
-
* ## The read this replaces
|
|
777
|
-
*
|
|
778
|
-
* `runPipeline` resolved a device's overrides by calling
|
|
779
|
-
* `settings.readDeviceStore(deviceId)` on **every inference frame**. Measured
|
|
780
|
-
* on the live hub 2026-08-25: `get detection-pipeline:addon-devices`, 1 143
|
|
781
|
-
* calls a minute at 0.44 rows per call — the disk asked, nineteen times a
|
|
782
|
-
* second, whether an operator has ever changed a threshold.
|
|
783
|
-
*
|
|
784
|
-
* ## Why this is not "a cache in the consumer" (D224)
|
|
785
|
-
*
|
|
786
|
-
* D224 forbids a SECOND authority over a fact that belongs to somebody else:
|
|
787
|
-
* the failure it records is a consumer caching a value whose write path does
|
|
788
|
-
* not run through that consumer, so an operator's own change is the one read
|
|
789
|
-
* the cache gets wrong.
|
|
790
|
-
*
|
|
791
|
-
* This addon OWNS the row. `<addonId>:addon-devices` is detection-pipeline's
|
|
792
|
-
* own store, and the only writers are this addon's `updateDeviceSettings` and
|
|
793
|
-
* its `clearDeviceOverrides` — both of which call {@link invalidate}. A write
|
|
794
|
-
* is therefore its own invalidation, exactly as D224 requires, and the window
|
|
795
|
-
* below governs only the case nobody writes through this process.
|
|
796
|
-
*
|
|
797
|
-
* ## The window, declared
|
|
798
|
-
*
|
|
799
|
-
* {@link DEVICE_OVERRIDE_STALE_MS} is what an operator's change costs on a node
|
|
800
|
-
* that did NOT serve the write — this addon runs per node, and a settings write
|
|
801
|
-
* lands on one of them. Thirty seconds is the trade: it removes 99.9% of the
|
|
802
|
-
* reads (one per device per window instead of one per frame) and it is short
|
|
803
|
-
* enough that "I moved the threshold and nothing happened" is not a support
|
|
804
|
-
* question. Ten minutes — {@link OPERATOR_WRITTEN_STALE_MS}, the constant for a
|
|
805
|
-
* cap whose value only an operator changes — is right for a POLLED reader that
|
|
806
|
-
* costs a camera round trip; this read costs one local SQLite `get`, and the
|
|
807
|
-
* cheap read buys a short window.
|
|
808
|
-
*
|
|
809
|
-
* A stale entry is SERVED and revalidated behind the caller, never awaited: a
|
|
810
|
-
* frame that waits for the settings store is a frame the pipeline dropped, and
|
|
811
|
-
* the reader is by definition about to ask again.
|
|
812
|
-
*/
|
|
813
|
-
/**
|
|
814
|
-
* How long a mirrored entry is served before a refresh is started behind the
|
|
815
|
-
* next reader. See the module doc for why it is 30 s and not ten minutes.
|
|
816
|
-
*/
|
|
817
|
-
var DEVICE_OVERRIDE_STALE_MS = 3e4;
|
|
818
|
-
/**
|
|
819
|
-
* How long a FAILED refresh is not retried.
|
|
820
|
-
*
|
|
821
|
-
* A refresh that throws leaves `fetchedAt` where it was, so without a cooldown
|
|
822
|
-
* every subsequent frame would start another one — a broken settings store
|
|
823
|
-
* would be hammered at frame rate by the very mechanism built to stop that.
|
|
824
|
-
*/
|
|
825
|
-
var DEVICE_OVERRIDE_MISS_COOLDOWN_MS = 5e3;
|
|
826
|
-
var DeviceOverrideMirror = class {
|
|
827
|
-
deps;
|
|
828
|
-
staleMs;
|
|
829
|
-
missCooldownMs;
|
|
830
|
-
entries = /* @__PURE__ */ new Map();
|
|
831
|
-
/** In-flight reads, so a burst of frames on a cold device costs ONE read and
|
|
832
|
-
* not one per frame — the exact failure this class exists to remove. */
|
|
833
|
-
inFlight = /* @__PURE__ */ new Map();
|
|
834
|
-
now;
|
|
835
|
-
constructor(deps, staleMs = DEVICE_OVERRIDE_STALE_MS, missCooldownMs = DEVICE_OVERRIDE_MISS_COOLDOWN_MS) {
|
|
836
|
-
this.deps = deps;
|
|
837
|
-
this.staleMs = staleMs;
|
|
838
|
-
this.missCooldownMs = missCooldownMs;
|
|
839
|
-
this.now = deps.now ?? (() => Date.now());
|
|
840
|
-
}
|
|
841
|
-
/**
|
|
842
|
-
* The device's overrides.
|
|
843
|
-
*
|
|
844
|
-
* COLD awaits — the first frame on a camera has to get the real answer, and a
|
|
845
|
-
* default is exactly what "the operator lowered this threshold" looks like.
|
|
846
|
-
* WARM returns immediately, stale or not, and starts the refresh behind the
|
|
847
|
-
* caller.
|
|
848
|
-
*/
|
|
849
|
-
async resolve(deviceId) {
|
|
850
|
-
const entry = this.entries.get(deviceId);
|
|
851
|
-
if (entry === void 0) return this.load(deviceId);
|
|
852
|
-
if (this.now() - entry.fetchedAt >= this.staleMs) this.load(deviceId);
|
|
853
|
-
return entry.value;
|
|
854
|
-
}
|
|
855
|
-
/** Drop a device's entry. Called by every writer in this process, so an
|
|
856
|
-
* operator's own change is never served from the mirror. */
|
|
857
|
-
invalidate(deviceId) {
|
|
858
|
-
this.entries.delete(deviceId);
|
|
859
|
-
}
|
|
860
|
-
invalidateAll() {
|
|
861
|
-
this.entries.clear();
|
|
862
|
-
}
|
|
863
|
-
async load(deviceId) {
|
|
864
|
-
const pending = this.inFlight.get(deviceId);
|
|
865
|
-
if (pending !== void 0) return pending;
|
|
866
|
-
const run = this.deps.read(deviceId).then((value) => {
|
|
867
|
-
this.entries.set(deviceId, {
|
|
868
|
-
value,
|
|
869
|
-
fetchedAt: this.now()
|
|
870
|
-
});
|
|
871
|
-
return value;
|
|
872
|
-
}).catch((err) => {
|
|
873
|
-
this.deps.onRefreshFailed?.(deviceId, err);
|
|
874
|
-
const existing = this.entries.get(deviceId);
|
|
875
|
-
if (existing !== void 0) {
|
|
876
|
-
existing.fetchedAt = this.now() - this.staleMs + this.missCooldownMs;
|
|
877
|
-
return existing.value;
|
|
878
|
-
}
|
|
879
|
-
return {};
|
|
880
|
-
}).finally(() => {
|
|
881
|
-
this.inFlight.delete(deviceId);
|
|
882
|
-
});
|
|
883
|
-
this.inFlight.set(deviceId, run);
|
|
884
|
-
return run;
|
|
885
|
-
}
|
|
886
|
-
};
|
|
887
|
-
//#endregion
|
|
888
694
|
//#region src/detection-pipeline/engine/pool-worker-health.ts
|
|
889
695
|
/**
|
|
890
696
|
* The one table of load bounds (D653, fix round 1).
|
|
@@ -3269,6 +3075,14 @@ var PipelineModelManager = class {
|
|
|
3269
3075
|
}
|
|
3270
3076
|
};
|
|
3271
3077
|
//#endregion
|
|
3078
|
+
//#region src/detection-pipeline/engine/labels-for-decoder.ts
|
|
3079
|
+
/** Labels forwarded to the Python pool — SSD stock Coral keeps COCO-90 in Python. */
|
|
3080
|
+
function labelsForDecoder(postprocessor, modelLabels, stepLabels) {
|
|
3081
|
+
if (modelLabels !== void 0 && modelLabels.length > 0) return modelLabels;
|
|
3082
|
+
if (postprocessor === "ssd") return;
|
|
3083
|
+
return stepLabels;
|
|
3084
|
+
}
|
|
3085
|
+
//#endregion
|
|
3272
3086
|
//#region src/detection-pipeline/engine/coral-cocompiled-set.ts
|
|
3273
3087
|
var ROOT_DETECTOR_STEP_ID = "object-detection";
|
|
3274
3088
|
/** The models a dispatch places on the pool that runs it: every enabled video step. */
|
|
@@ -3953,7 +3767,9 @@ function buildPoolModelConfigForStep(inputs) {
|
|
|
3953
3767
|
const inputSize = Math.max(inputWidth, inputHeight);
|
|
3954
3768
|
const inputChannels = modelEntry.inputChannels ?? 3;
|
|
3955
3769
|
const entryLabels = modelEntry.labels.length > 0 ? modelEntry.labels.map((l) => l.id) : void 0;
|
|
3956
|
-
const
|
|
3770
|
+
const modelLabels = readModelLabels(modelsDir, modelEntry) ?? entryLabels;
|
|
3771
|
+
const effectivePostprocessor = resolveEffectivePostprocessorForEntry(def, modelEntry);
|
|
3772
|
+
const labels = labelsForDecoder(effectivePostprocessor, modelLabels, def.labels);
|
|
3957
3773
|
return {
|
|
3958
3774
|
path: modelPath,
|
|
3959
3775
|
inputSize,
|
|
@@ -3964,7 +3780,7 @@ function buildPoolModelConfigForStep(inputs) {
|
|
|
3964
3780
|
inputNormalization: modelEntry.inputNormalization,
|
|
3965
3781
|
outputProbabilities: modelEntry.outputProbabilities,
|
|
3966
3782
|
...modelEntry.gpuInferencePrecision !== void 0 ? { gpuInferencePrecision: modelEntry.gpuInferencePrecision } : {},
|
|
3967
|
-
postprocessor:
|
|
3783
|
+
postprocessor: effectivePostprocessor,
|
|
3968
3784
|
confidence: resolvePoolConfidenceFloor(stepId, require_custom_model_catalog.resolveModelDefaultConfidence(def, modelEntry)),
|
|
3969
3785
|
nmsIouThreshold: resolvePoolDecodeSettings({
|
|
3970
3786
|
def,
|
|
@@ -4229,6 +4045,29 @@ function benchmarkKeyOf(deviceKey) {
|
|
|
4229
4045
|
function isBenchmarkRun(input) {
|
|
4230
4046
|
return input.frame === void 0 && input.frameRef === void 0 && input.deviceId === void 0 && input.replay !== true;
|
|
4231
4047
|
}
|
|
4048
|
+
/**
|
|
4049
|
+
* Backends whose device opens in ONE process at a time. libedgetpu holds an
|
|
4050
|
+
* Edge TPU exclusively for the process that opened it, so a second pool on a
|
|
4051
|
+
* Coral the cameras' pool already holds cannot open it at all — every
|
|
4052
|
+
* benchmark and auto-benchmark (D913) of an in-use Coral failed that way on
|
|
4053
|
+
* the dev hub (1.2.619). Every other backend this node builds (OpenVINO,
|
|
4054
|
+
* CoreML, CUDA, ONNX, CPU) shares its device between processes.
|
|
4055
|
+
*/
|
|
4056
|
+
var EXCLUSIVE_BACKENDS = new Set(["edgetpu"]);
|
|
4057
|
+
/** True when the device behind `deviceKey` (`<backend>:<device>`) cannot be opened by a second pool. */
|
|
4058
|
+
function isExclusiveDevice(deviceKey) {
|
|
4059
|
+
const colon = deviceKey.indexOf(":");
|
|
4060
|
+
const backend = colon >= 0 ? deviceKey.slice(0, colon) : deviceKey;
|
|
4061
|
+
return EXCLUSIVE_BACKENDS.has(backend);
|
|
4062
|
+
}
|
|
4063
|
+
/**
|
|
4064
|
+
* A benchmark on an EXCLUSIVE device is the one benchmark that goes to the
|
|
4065
|
+
* live pool: the separate pool could not open the device, so the choice is
|
|
4066
|
+
* between measuring through the cameras' pool and not measuring at all.
|
|
4067
|
+
*/
|
|
4068
|
+
function benchmarkPlacementOf(benchmark, deviceKey) {
|
|
4069
|
+
return benchmark && !isExclusiveDevice(deviceKey) ? "benchmark-pool" : "live-pool";
|
|
4070
|
+
}
|
|
4232
4071
|
var BenchmarkPools = class {
|
|
4233
4072
|
options;
|
|
4234
4073
|
pools = /* @__PURE__ */ new Map();
|
|
@@ -4809,14 +4648,15 @@ var PRIMARY_ROOT_STEP = "object-detection";
|
|
|
4809
4648
|
/**
|
|
4810
4649
|
* The same rule over an EXECUTABLE tree's roots (D658): their model ids are the
|
|
4811
4650
|
* pool variants that will run — after resolution, per-step loads and drops —
|
|
4812
|
-
* so this is what a live `runPipeline` stamps
|
|
4813
|
-
* video roots already.
|
|
4814
|
-
*/
|
|
4815
|
-
function
|
|
4816
|
-
|
|
4817
|
-
|
|
4818
|
-
|
|
4819
|
-
|
|
4651
|
+
* so this is what a live `runPipeline` stamps, with the root's step id beside
|
|
4652
|
+
* the model (D925). The tree holds only enabled video roots already.
|
|
4653
|
+
*/
|
|
4654
|
+
function resolveTreeRoot(roots) {
|
|
4655
|
+
const root = roots.find((s) => s.stepId === PRIMARY_ROOT_STEP) ?? roots[0];
|
|
4656
|
+
return root === void 0 ? void 0 : {
|
|
4657
|
+
stepId: root.stepId,
|
|
4658
|
+
modelId: root.modelId
|
|
4659
|
+
};
|
|
4820
4660
|
}
|
|
4821
4661
|
//#endregion
|
|
4822
4662
|
//#region src/detection-pipeline/engine-provisioner.ts
|
|
@@ -7872,16 +7712,6 @@ function collectSchemaDefaults(schema) {
|
|
|
7872
7712
|
walkFieldsForDefaults(schema, out);
|
|
7873
7713
|
return out;
|
|
7874
7714
|
}
|
|
7875
|
-
/**
|
|
7876
|
-
* The operator settings of `stepId` as the model that RUNS sees them (D738):
|
|
7877
|
-
* a model-bound value made for another model is dropped and binding keys are
|
|
7878
|
-
* stripped. For a settings layer merged AFTER the tree is built (the
|
|
7879
|
-
* executor's per-device store, `applyDeviceOverridesToTree`), so it obeys the
|
|
7880
|
-
* same binding as the layers `buildNode` merges.
|
|
7881
|
-
*/
|
|
7882
|
-
function resolveOperatorSettingsForModel(stepId, settings, runningModelId) {
|
|
7883
|
-
return require_dist.applyModelBoundSettings(settings, require_dist.collectModelBoundKeys(require_custom_model_catalog.getStep(stepId).getConfigSchema()), runningModelId) ?? {};
|
|
7884
|
-
}
|
|
7885
7715
|
function walkFieldsForDefaults(fields, out) {
|
|
7886
7716
|
for (const field of fields) {
|
|
7887
7717
|
if ("type" in field && field.type === "group" && "fields" in field) {
|
|
@@ -8570,7 +8400,7 @@ var DetectionPipelineProvider = class DetectionPipelineProvider {
|
|
|
8570
8400
|
* node-default tree against `this.currentEngine.format`. Recomputed
|
|
8571
8401
|
* EAGERLY by {@link recomputeConfigIssues} whenever the engine actually
|
|
8572
8402
|
* changes (see `onEngineSelectionChanged`), rather than relying on a
|
|
8573
|
-
* `
|
|
8403
|
+
* `nodeDefaultSteps()` call that may never happen on a camera-only node.
|
|
8574
8404
|
* Merged into {@link getEngineProvisioning}'s snapshot; never consulted by
|
|
8575
8405
|
* `assertEngineReady` — this gate SURFACES, it does not block inference.
|
|
8576
8406
|
*/
|
|
@@ -8672,20 +8502,6 @@ var DetectionPipelineProvider = class DetectionPipelineProvider {
|
|
|
8672
8502
|
readStore;
|
|
8673
8503
|
/** Write a patch to the addon settings store. */
|
|
8674
8504
|
writeStore;
|
|
8675
|
-
/** Read per-device settings. */
|
|
8676
|
-
readDeviceStore;
|
|
8677
|
-
/** Delete all per-device settings for a device (used by `clearDeviceOverrides`). */
|
|
8678
|
-
clearDeviceStore;
|
|
8679
|
-
/** Merge a patch into one device's settings (Auto tune' keep-the-rest rewrite, D745). */
|
|
8680
|
-
writeDeviceStore;
|
|
8681
|
-
/**
|
|
8682
|
-
* The per-device overrides the FRAME path reads, kept fresh off that path.
|
|
8683
|
-
*
|
|
8684
|
-
* Public so the addon class can drop a device on its own
|
|
8685
|
-
* `updateDeviceSettings` — the write and the mirror have to be the same
|
|
8686
|
-
* process's, or the mirror becomes the second authority D224 forbids.
|
|
8687
|
-
*/
|
|
8688
|
-
deviceOverrides;
|
|
8689
8505
|
constructor(settings, modelsDir, logger, eventBus = null, detectionConfigSchemaSource = null, executorOptions = {}) {
|
|
8690
8506
|
this.modelsDir = modelsDir;
|
|
8691
8507
|
this.eventBus = eventBus;
|
|
@@ -8694,18 +8510,6 @@ var DetectionPipelineProvider = class DetectionPipelineProvider {
|
|
|
8694
8510
|
this.log = logger;
|
|
8695
8511
|
this.readStore = () => settings.readAddonStore();
|
|
8696
8512
|
this.writeStore = (patch) => settings.writeAddonStore(patch);
|
|
8697
|
-
this.readDeviceStore = settings.readDeviceStore ?? (async () => ({}));
|
|
8698
|
-
const clearDeviceStore = settings.clearDeviceStore;
|
|
8699
|
-
this.clearDeviceStore = clearDeviceStore ? (deviceId) => clearDeviceStore.call(settings, deviceId) : async () => void 0;
|
|
8700
|
-
const writeDeviceStore = settings.writeDeviceStore;
|
|
8701
|
-
this.writeDeviceStore = writeDeviceStore ? (deviceId, patch) => writeDeviceStore.call(settings, deviceId, patch) : async () => void 0;
|
|
8702
|
-
this.deviceOverrides = new DeviceOverrideMirror({
|
|
8703
|
-
read: (deviceId) => this.readDeviceStore(deviceId),
|
|
8704
|
-
onRefreshFailed: (deviceId, err) => this.log.warn("per-device detection overrides refresh failed — serving the last value", {
|
|
8705
|
-
tags: { deviceId },
|
|
8706
|
-
meta: { error: require_dist.errMsg(err) }
|
|
8707
|
-
})
|
|
8708
|
-
});
|
|
8709
8513
|
this.currentEngine = ONNX_FLOOR;
|
|
8710
8514
|
this.log.info("Engine pick pending (placeholder until probe / persisted selection)", { meta: {
|
|
8711
8515
|
runtime: this.currentEngine.runtime,
|
|
@@ -9008,7 +8812,7 @@ var DetectionPipelineProvider = class DetectionPipelineProvider {
|
|
|
9008
8812
|
* the node-default step tree for `this.currentEngine.format` and compute
|
|
9009
8813
|
* human-readable config issues from the result:
|
|
9010
8814
|
* - model substitutions (`getActiveModelSubstitutions()`, populated as a
|
|
9011
|
-
* side effect of the `
|
|
8815
|
+
* side effect of the `nodeDefaultSteps()` re-resolve below) — a step's
|
|
9012
8816
|
* chosen model lacks a build for this format, so the format default
|
|
9013
8817
|
* runs instead (degraded but loadable).
|
|
9014
8818
|
* - zero-build steps (`collectZeroBuildIssues`) — a step whose FULL
|
|
@@ -9023,7 +8827,7 @@ var DetectionPipelineProvider = class DetectionPipelineProvider {
|
|
|
9023
8827
|
async recomputeConfigIssues() {
|
|
9024
8828
|
this.configIssues = [];
|
|
9025
8829
|
try {
|
|
9026
|
-
const steps = await this.
|
|
8830
|
+
const steps = await this.nodeDefaultSteps();
|
|
9027
8831
|
if (!steps) return;
|
|
9028
8832
|
const format = this.currentEngine.format;
|
|
9029
8833
|
const substitutionIssues = this.getActiveModelSubstitutions().map((s) => `${s.addonId}: chose ${s.chosen}, running ${s.running} (${s.format})`);
|
|
@@ -9071,7 +8875,7 @@ var DetectionPipelineProvider = class DetectionPipelineProvider {
|
|
|
9071
8875
|
* `format` for the download fan-out.
|
|
9072
8876
|
*/
|
|
9073
8877
|
async ensureModelsForCurrentSteps(format) {
|
|
9074
|
-
const steps = await this.
|
|
8878
|
+
const steps = await this.nodeDefaultSteps();
|
|
9075
8879
|
if (!steps || steps.length === 0) return;
|
|
9076
8880
|
for (const step of flattenSteps(steps)) {
|
|
9077
8881
|
if (!step.enabled) continue;
|
|
@@ -9244,10 +9048,6 @@ var DetectionPipelineProvider = class DetectionPipelineProvider {
|
|
|
9244
9048
|
defaultDevice: e.engine.device
|
|
9245
9049
|
};
|
|
9246
9050
|
}
|
|
9247
|
-
async getDefaultSteps(engine) {
|
|
9248
|
-
const detectionModelId = require_custom_model_catalog.resolveDefaultDetectionModel(engine.backend, engine.device ?? null, engine.format);
|
|
9249
|
-
return buildDefaultStepTree(engine.format, detectionModelId);
|
|
9250
|
-
}
|
|
9251
9051
|
/**
|
|
9252
9052
|
* Resolve every step's model for this node's engine format via the shared
|
|
9253
9053
|
* `resolveModelForFormat`, and surface any substitution. `step.engine?.format`
|
|
@@ -9290,18 +9090,19 @@ var DetectionPipelineProvider = class DetectionPipelineProvider {
|
|
|
9290
9090
|
return [...this.modelSubstitutions.values()];
|
|
9291
9091
|
}
|
|
9292
9092
|
/**
|
|
9293
|
-
* PURE node-default step tree — computed on demand, never persisted
|
|
9093
|
+
* PURE node-default step tree — computed on demand, never persisted, and
|
|
9094
|
+
* PRIVATE (D927): it is not the model any camera ran, so no caller outside
|
|
9095
|
+
* this provider may read it. It serves Gate A's config-issue probe and the
|
|
9096
|
+
* engine provisioning's model download.
|
|
9294
9097
|
*
|
|
9295
9098
|
* The object-detection default is hardware-aware (this node's resolved
|
|
9296
9099
|
* backend + device via `resolveDefaultDetectionModel`); every other step
|
|
9297
9100
|
* keeps its flat per-format default. The result is cached in
|
|
9298
9101
|
* `currentSteps` only as a memo — the cache is dropped whenever the
|
|
9299
9102
|
* engine (hence model format) changes, so a re-read always reflects the
|
|
9300
|
-
* live engine.
|
|
9301
|
-
* it exists as the benchmark fallback (empty input steps), the Gate-A
|
|
9302
|
-
* config-issue probe, and the "effective post-reset model" probe.
|
|
9103
|
+
* live engine.
|
|
9303
9104
|
*/
|
|
9304
|
-
async
|
|
9105
|
+
async nodeDefaultSteps() {
|
|
9305
9106
|
if (this.currentSteps) return this.currentSteps;
|
|
9306
9107
|
const detectionModelId = require_custom_model_catalog.resolveDefaultDetectionModel(this.currentEngine.backend, this.currentEngine.device ?? null, this.currentEngine.format);
|
|
9307
9108
|
const defaults = buildDefaultStepTree(this.currentEngine.format, detectionModelId);
|
|
@@ -9309,10 +9110,6 @@ var DetectionPipelineProvider = class DetectionPipelineProvider {
|
|
|
9309
9110
|
this.currentSteps = this.resolveStepModels(defaults);
|
|
9310
9111
|
return this.currentSteps;
|
|
9311
9112
|
}
|
|
9312
|
-
async getGlobalPipelineConfig() {
|
|
9313
|
-
if (!this.currentSteps) return null;
|
|
9314
|
-
return stepsToPipelineConfig(this.currentSteps, this.currentEngine);
|
|
9315
|
-
}
|
|
9316
9113
|
/**
|
|
9317
9114
|
* Task G5 (Gate B) — pre-init config-correctness gate. PURE COMPUTE
|
|
9318
9115
|
* against `this.currentEngine.format`: resolves `steps` the same way the
|
|
@@ -9895,7 +9692,9 @@ var DetectionPipelineProvider = class DetectionPipelineProvider {
|
|
|
9895
9692
|
this.executor = executor;
|
|
9896
9693
|
const dispatchEngine = dispatchDeviceKey ? require_custom_model_catalog.resolveDeviceEngine(dispatchDeviceKey) : runEngine;
|
|
9897
9694
|
const benchmark = isBenchmarkRun(input);
|
|
9898
|
-
const
|
|
9695
|
+
const placement = benchmarkPlacementOf(benchmark, require_custom_model_catalog.deviceKeyOf(dispatchEngine));
|
|
9696
|
+
if (benchmark && placement === "live-pool") this.log.info("Benchmark on an exclusive device — served by the live pool", { meta: { deviceKey: require_custom_model_catalog.deviceKeyOf(dispatchEngine) } });
|
|
9697
|
+
const dispatchFactory = placement === "benchmark-pool" ? await this.benchmarkPools.acquire(require_custom_model_catalog.deviceKeyOf(dispatchEngine), dispatchEngine) : dispatchDeviceKey ? await this.resolveDeviceFactory(dispatchDeviceKey) : this.engineFactory;
|
|
9899
9698
|
const needed = enabledSteps.filter((s) => dispatchFactory.needsPoolUpdate(s));
|
|
9900
9699
|
let runSteps = benchmarkSteps;
|
|
9901
9700
|
const loadPolicy = dispatchLoadPolicyOf(input);
|
|
@@ -9936,21 +9735,21 @@ var DetectionPipelineProvider = class DetectionPipelineProvider {
|
|
|
9936
9735
|
}, dispatchDeviceKeyLabel, [model], model, "not-warm", require_dist.errMsg(failure.error));
|
|
9937
9736
|
}
|
|
9938
9737
|
}
|
|
9939
|
-
const
|
|
9738
|
+
const treeRoot = resolveTreeRoot(tree.roots);
|
|
9940
9739
|
const rootDeviceKey = require_custom_model_catalog.deviceKeyOf(dispatchEngine);
|
|
9941
|
-
const stampRoot = (r) =>
|
|
9740
|
+
const stampRoot = (r) => treeRoot === void 0 ? {
|
|
9942
9741
|
...r,
|
|
9943
9742
|
rootDeviceKey
|
|
9944
9743
|
} : {
|
|
9945
9744
|
...r,
|
|
9946
|
-
rootModelId,
|
|
9745
|
+
rootModelId: treeRoot.modelId,
|
|
9746
|
+
rootStepId: treeRoot.stepId,
|
|
9947
9747
|
rootDeviceKey
|
|
9948
9748
|
};
|
|
9949
9749
|
if (input.replay !== true) this.clusterModelSwitchLog.note(input.deviceId ?? 0, tree);
|
|
9950
9750
|
setupMs = performance.now() - wallT0 - decodeMs;
|
|
9951
9751
|
const effectiveDeviceId = input.deviceId ?? 0;
|
|
9952
|
-
const
|
|
9953
|
-
const effectiveTree = Object.keys(deviceOverrides).length > 0 ? applyDeviceOverridesToTree(tree, "object-detection", deviceOverrides) : tree;
|
|
9752
|
+
const effectiveTree = tree;
|
|
9954
9753
|
const nativeCropProvider = this.buildNativeCropProviderFromRef(input.nativeCropRef) ?? this.buildNativeFaceCropProvider(input.frameHandle);
|
|
9955
9754
|
let cropZoneBbox;
|
|
9956
9755
|
if (appliesCameraGates && effectiveDeviceId > 0 && effectiveTree.roots.some((r) => r.definition.extractMode === "crop-zone")) {
|
|
@@ -11285,102 +11084,6 @@ var DetectionPipelineProvider = class DetectionPipelineProvider {
|
|
|
11285
11084
|
this.log.info("videoPipelineSteps updated", { meta: { addons: Object.keys(sanitized).length } });
|
|
11286
11085
|
return { success: true };
|
|
11287
11086
|
}
|
|
11288
|
-
/**
|
|
11289
|
-
* Clear THIS node's executor-side PER-DEVICE settings stores — the
|
|
11290
|
-
* per-camera step overrides the object-detection root reads via
|
|
11291
|
-
* `applyDeviceOverridesToTree`.
|
|
11292
|
-
*
|
|
11293
|
-
* Node-routed (the cap's default `nodeIdMode: 'routing'`): the generated
|
|
11294
|
-
* cap-router strips `nodeId` and dispatches to the target node, so this
|
|
11295
|
-
* method runs ON the node being cleared and takes no argument.
|
|
11296
|
-
*
|
|
11297
|
-
* This is the slimmed executor leg of the orchestrator's
|
|
11298
|
-
* `resetNodePipelineDefaults` flow. The legacy `resetToDefault` — which
|
|
11299
|
-
* also reset a persisted GLOBAL step-tree seed nothing in the live
|
|
11300
|
-
* per-camera path read — was removed together with that seed
|
|
11301
|
-
* (`getGlobalSteps` is pure now, so there is nothing node-global left to
|
|
11302
|
-
* reset here).
|
|
11303
|
-
*
|
|
11304
|
-
* Idempotent: clearing already-empty per-device stores is a no-op.
|
|
11305
|
-
*/
|
|
11306
|
-
async clearDeviceOverrides() {
|
|
11307
|
-
const clearedDevices = await this.clearAllDeviceOverrides();
|
|
11308
|
-
this.log.info("executor per-device overrides cleared", { meta: { clearedDevices } });
|
|
11309
|
-
return {
|
|
11310
|
-
success: true,
|
|
11311
|
-
clearedDevices
|
|
11312
|
-
};
|
|
11313
|
-
}
|
|
11314
|
-
/**
|
|
11315
|
-
* Auto tune (D745): list — or, unless `dryRun`, remove — the model-bound
|
|
11316
|
-
* thresholds of the per-camera detector store. See
|
|
11317
|
-
* `model-bound-device-overrides.ts`.
|
|
11318
|
-
*/
|
|
11319
|
-
async clearModelBoundDeviceOverrides(input) {
|
|
11320
|
-
const result = await clearModelBoundDeviceOverrides({
|
|
11321
|
-
listDeviceIds: async () => {
|
|
11322
|
-
const api = this.addonCtx?.api;
|
|
11323
|
-
if (!api) throw new Error("clearModelBoundDeviceOverrides: ctx.api unavailable");
|
|
11324
|
-
return (await api.deviceManager.listAll.query({ projection: "slim" })).map((d) => d.id);
|
|
11325
|
-
},
|
|
11326
|
-
readDeviceStore: (deviceId) => this.readDeviceStore(deviceId),
|
|
11327
|
-
clearDeviceStore: (deviceId) => this.clearDeviceStore(deviceId),
|
|
11328
|
-
writeDeviceStore: (deviceId, patch) => this.writeDeviceStore(deviceId, patch),
|
|
11329
|
-
invalidate: (deviceId) => this.deviceOverrides.invalidate(deviceId),
|
|
11330
|
-
boundKeys: require_dist.collectModelBoundKeys(require_custom_model_catalog.getStep("object-detection").getConfigSchema())
|
|
11331
|
-
}, input);
|
|
11332
|
-
if (!input.dryRun) for (const entry of result.entries) this.log.info("auto tune: per-camera detector thresholds cleared", {
|
|
11333
|
-
tags: { deviceId: entry.deviceId },
|
|
11334
|
-
meta: {
|
|
11335
|
-
deviceId: entry.deviceId,
|
|
11336
|
-
keys: entry.keys
|
|
11337
|
-
}
|
|
11338
|
-
});
|
|
11339
|
-
for (const r of result.refused) this.log.warn("auto tune: per-camera detector thresholds not cleared", {
|
|
11340
|
-
tags: { deviceId: r.deviceId },
|
|
11341
|
-
meta: {
|
|
11342
|
-
deviceId: r.deviceId,
|
|
11343
|
-
reason: r.reason,
|
|
11344
|
-
dryRun: input.dryRun
|
|
11345
|
-
}
|
|
11346
|
-
});
|
|
11347
|
-
return result;
|
|
11348
|
-
}
|
|
11349
|
-
/**
|
|
11350
|
-
* Clear the per-device pipeline-step overrides for every known device.
|
|
11351
|
-
* Returns the count of devices whose store was cleared. There is no
|
|
11352
|
-
* bulk-list primitive over the per-device store, so devices are
|
|
11353
|
-
* enumerated via the device-manager and cleared one by one
|
|
11354
|
-
* (`clearDeviceStore` is idempotent — a device with no overrides is a
|
|
11355
|
-
* no-op). Never throws: a device-manager outage degrades to "cleared
|
|
11356
|
-
* nothing" so the reset flow still completes.
|
|
11357
|
-
*/
|
|
11358
|
-
async clearAllDeviceOverrides() {
|
|
11359
|
-
const api = this.addonCtx?.api;
|
|
11360
|
-
if (!api) return 0;
|
|
11361
|
-
let devices = [];
|
|
11362
|
-
try {
|
|
11363
|
-
devices = await api.deviceManager.listAll.query({ projection: "slim" });
|
|
11364
|
-
} catch (err) {
|
|
11365
|
-
this.log.warn("clearDeviceOverrides: device enumeration failed — skipping per-device clear", { meta: { error: require_dist.errMsg(err) } });
|
|
11366
|
-
return 0;
|
|
11367
|
-
}
|
|
11368
|
-
let cleared = 0;
|
|
11369
|
-
for (const device of devices) try {
|
|
11370
|
-
await this.clearDeviceStore(device.id);
|
|
11371
|
-
this.deviceOverrides.invalidate(device.id);
|
|
11372
|
-
cleared++;
|
|
11373
|
-
} catch (err) {
|
|
11374
|
-
this.log.warn("clearDeviceOverrides: failed to clear per-device overrides for device", {
|
|
11375
|
-
tags: { deviceId: device.id },
|
|
11376
|
-
meta: {
|
|
11377
|
-
deviceId: device.id,
|
|
11378
|
-
error: require_dist.errMsg(err)
|
|
11379
|
-
}
|
|
11380
|
-
});
|
|
11381
|
-
}
|
|
11382
|
-
return cleared;
|
|
11383
|
-
}
|
|
11384
11087
|
async listLoadedEngines() {
|
|
11385
11088
|
const out = [];
|
|
11386
11089
|
if (this.engineFactory) {
|
|
@@ -11627,7 +11330,6 @@ function buildSchemaSlots(formats, modelsDir, customByStep) {
|
|
|
11627
11330
|
defaultModelId: step.defaultModelId,
|
|
11628
11331
|
...step.defaultModelIdByFormat ? { defaultModelIdByFormat: { ...step.defaultModelIdByFormat } } : {},
|
|
11629
11332
|
...step.enabledByDefault !== void 0 ? { enabledByDefault: step.enabledByDefault } : {},
|
|
11630
|
-
...step.backfillIntoExistingOverrides !== void 0 ? { backfillIntoExistingOverrides: step.backfillIntoExistingOverrides } : {},
|
|
11631
11333
|
defaultConfidence: step.defaultConfidence,
|
|
11632
11334
|
...step.group ? { group: step.group } : {},
|
|
11633
11335
|
...configSchemaWithRoots.length > 0 ? { configSchema: configSchemaWithRoots } : {}
|
|
@@ -11675,7 +11377,7 @@ function resolveChildSlots(slot) {
|
|
|
11675
11377
|
}
|
|
11676
11378
|
/**
|
|
11677
11379
|
* V2 default: the node-default step tree (never persisted — see
|
|
11678
|
-
* `
|
|
11380
|
+
* `nodeDefaultSteps`). The core detection + recognition steps are enabled; every
|
|
11679
11381
|
* optional step is present with its catalog `enabledByDefault` (the animal and
|
|
11680
11382
|
* vehicle classifiers on — their answer comes from the root model when it
|
|
11681
11383
|
* declares them, D736 — the bird classifier and segmentation off).
|
|
@@ -11717,27 +11419,6 @@ function buildDefaultStepTree(format, objectDetectionModelId) {
|
|
|
11717
11419
|
if (audioStep) steps.push(audioStep);
|
|
11718
11420
|
return steps;
|
|
11719
11421
|
}
|
|
11720
|
-
function stepsToPipelineConfig(steps, engine) {
|
|
11721
|
-
const toNode = (step) => ({
|
|
11722
|
-
step: step.addonId,
|
|
11723
|
-
addon: step.addonId,
|
|
11724
|
-
configOverride: {
|
|
11725
|
-
modelId: step.modelId,
|
|
11726
|
-
...step.settings
|
|
11727
|
-
},
|
|
11728
|
-
children: step.children.map(toNode)
|
|
11729
|
-
});
|
|
11730
|
-
const videoSteps = steps.filter((s) => s.slot !== "audio-classifier");
|
|
11731
|
-
const audioStep = steps.find((s) => s.slot === "audio-classifier" && s.enabled);
|
|
11732
|
-
return {
|
|
11733
|
-
engine,
|
|
11734
|
-
video: videoSteps.map(toNode),
|
|
11735
|
-
...audioStep ? {
|
|
11736
|
-
audio: toNode(audioStep),
|
|
11737
|
-
audioEngine: engine
|
|
11738
|
-
} : {}
|
|
11739
|
-
};
|
|
11740
|
-
}
|
|
11741
11422
|
/** Flatten a step tree into a flat list (DFS) — delegates to shared utility. */
|
|
11742
11423
|
function flattenSteps(steps) {
|
|
11743
11424
|
return flattenEnabledVideoSteps(steps);
|
|
@@ -11798,22 +11479,6 @@ function availableFormatsForStep(addonId) {
|
|
|
11798
11479
|
return [];
|
|
11799
11480
|
}
|
|
11800
11481
|
}
|
|
11801
|
-
/**
|
|
11802
|
-
* Return a shallow-cloned executable tree with `rootStepId`'s `settings`
|
|
11803
|
-
* merged with `overrides` (per-device values win). Non-matching root steps
|
|
11804
|
-
* pass through unchanged. Used by `runFrame` to apply per-device detection
|
|
11805
|
-
* settings without rebuilding the tree per frame. A model-bound value (D738)
|
|
11806
|
-
* applies only while the model it was made for is the one the root RUNS.
|
|
11807
|
-
*/
|
|
11808
|
-
function applyDeviceOverridesToTree(tree, rootStepId, overrides) {
|
|
11809
|
-
return { roots: tree.roots.map((root) => root.stepId === rootStepId ? {
|
|
11810
|
-
...root,
|
|
11811
|
-
settings: {
|
|
11812
|
-
...root.settings,
|
|
11813
|
-
...resolveOperatorSettingsForModel(rootStepId, overrides, root.modelId)
|
|
11814
|
-
}
|
|
11815
|
-
} : root) };
|
|
11816
|
-
}
|
|
11817
11482
|
//#endregion
|
|
11818
11483
|
//#region src/detection-pipeline/python-readiness.ts
|
|
11819
11484
|
/**
|
|
@@ -11928,20 +11593,6 @@ function isProfileSliderKey(key) {
|
|
|
11928
11593
|
}
|
|
11929
11594
|
var DetectionPipelineAddon = class extends require_dist.BaseAddon {
|
|
11930
11595
|
provider = null;
|
|
11931
|
-
/**
|
|
11932
|
-
* An operator's own write drops the mirror the frame path reads.
|
|
11933
|
-
*
|
|
11934
|
-
* This override is the half of `device-override-mirror.ts` that keeps it from
|
|
11935
|
-
* being the second authority D224 forbids: `BaseAddon.updateDeviceSettings`
|
|
11936
|
-
* writes THIS addon's `<addonId>:addon-devices` row, so the write and the
|
|
11937
|
-
* mirror are in one process and the write invalidates. Without it the
|
|
11938
|
-
* operator's own change would be the one read the mirror got wrong, which is
|
|
11939
|
-
* the exact failure D224 records.
|
|
11940
|
-
*/
|
|
11941
|
-
async updateDeviceSettings(deviceId, patch) {
|
|
11942
|
-
await super.updateDeviceSettings(deviceId, patch);
|
|
11943
|
-
this.provider?.deviceOverrides.invalidate(deviceId);
|
|
11944
|
-
}
|
|
11945
11596
|
/** Last non-null probed hardware PER NODE — reused when the probe transiently
|
|
11946
11597
|
* returns null so offered backends / device lists don't collapse. Keyed by
|
|
11947
11598
|
* node because the hub addon probes other nodes when serving their config.
|