@camstack/addon-pipeline 1.2.621 → 1.2.622
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-CKCK-QcT.js} +7 -7
- package/dist/{custom-model-catalog-0_SnSXzN.mjs → custom-model-catalog-wpMi2U7e.mjs} +7 -7
- package/dist/detection-pipeline/index.js +55 -414
- package/dist/detection-pipeline/index.mjs +79 -438
- package/dist/{dist-DHqkQhTQ.mjs → dist-BF60SjmI.mjs} +76 -226
- package/dist/{dist-ClkumZgv.js → dist-DUFGDd_2.js} +75 -231
- package/dist/{model-catalogs-BagalaYp.js → model-catalogs-CjTm_0O-.js} +1 -1
- package/dist/{model-catalogs-Z1GZAhSb.mjs → model-catalogs-CqFDhb0B.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-DkphOOM2.mjs} +1 -1
- package/dist/{node-0O_61WVW.js → node-DzGVn7bD.js} +1 -1
- package/dist/pipeline-runner/index.js +18 -4
- package/dist/pipeline-runner/index.mjs +18 -4
- package/dist/{process-memory-DdIOhjYB.js → process-memory-8kKexHYR.js} +1 -1
- package/dist/{process-memory-Dj3UgL1e.mjs → process-memory-CBzfdSvC.mjs} +1 -1
- package/dist/recorder/index.js +2 -2
- package/dist/recorder/index.mjs +2 -2
- package/dist/{segment-demux-js-Bv0t0-tQ.mjs → segment-demux-js-DQNoNSJt.mjs} +1 -1
- package/dist/{segment-demux-js-BePzacki.js → segment-demux-js-DRLQb1pc.js} +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-BmANAxAe.mjs} +2 -2
- package/dist/stream-broker/_virtual_mf___mfe_internal__addon_stream_broker_widgets__loadShare___mf_0_camstack_mf_1_types__loadShare__.js-H6RKsaiZ.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-CNoWeZHH.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-B3hXAfr1.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/coreml_load_probe.py +105 -15
- package/python/openvino_compile_probe.py +72 -18
- package/python/test_coreml_load_probe.py +83 -0
- package/python/test_openvino_compile_probe.py +114 -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
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import { n as __require } from "../chunk-DnnnRqeS.mjs";
|
|
2
|
-
import { $
|
|
3
|
-
import { c as readProcessCost } from "../node-
|
|
4
|
-
import { C as resolveModelDefaultConfidence, S as landmarkPrecisionVerdict, _ as ALL_STEPS, b as getStepDefinition, f as localFrameRegistry, g as ALL_PIPELINE_STEPS, l as resolveDefaultDetectionModel, n as mergeCustomModels, o as deviceKeyOf, r as buildSubtreeCanRun, s as resolveDeviceEngine, t as CustomModelCatalog, u as macroGateVerdict, v as getDefaultModelForFormat, x as resolveModelForFormat, y as getStep } from "../custom-model-catalog-
|
|
2
|
+
import { $n as nodePin, Ct as enumerateInferenceDevices, F as PoolMemoryWatchdog, Fn as BaseAddon, It as linkedLabelStepId, Kn as hfModelUrl, Nn as errMsg, O as LABEL_SUPPLY_MACRO, Qt as pipelineExecutorCapability, Rt as loadContributionCapability, Vn as createEvent, X as applyModelBoundSettings, Yt as pickClusterStepSettings, _t as detectionPipelineCapability, an as resolveClusterStepModelId, ar as array, bt as edgetpuDelegateDevice, ct as containingParentIndex, d as CLUSTER_MODEL_SCOPED_STEPS, dr as object, ft as defaultDeviceFor$1, g as DEFAULT_CLUSTER_STEP_SETTINGS, gn as stepModelRunsOnFormat, gr as EventCategory, hr as union, mn as runtimeDevices$1, mr as string, n as APPLE_SA_TO_MACRO, nr as sleep, pn as rootSuppliesOf, q as YAMNET_TO_MACRO, qn as hydrateSchema, qt as overlayClusterStepSettings, st as collectModelBoundKeys, un as resolvePoolMemoryPolicy, wt as evaluateZoneRules, xn as supportedRuntimes$1 } from "../dist-BF60SjmI.mjs";
|
|
3
|
+
import { c as readProcessCost } from "../node-DkphOOM2.mjs";
|
|
4
|
+
import { C as resolveModelDefaultConfidence, S as landmarkPrecisionVerdict, _ as ALL_STEPS, b as getStepDefinition, f as localFrameRegistry, g as ALL_PIPELINE_STEPS, l as resolveDefaultDetectionModel, n as mergeCustomModels, o as deviceKeyOf, r as buildSubtreeCanRun, s as resolveDeviceEngine, t as CustomModelCatalog, u as macroGateVerdict, v as getDefaultModelForFormat, x as resolveModelForFormat, y as getStep } from "../custom-model-catalog-wpMi2U7e.mjs";
|
|
5
5
|
import { t as getSharp } from "../lazy-sharp-DXsqwpph.mjs";
|
|
6
|
-
import { n as pickNodePlatformArch, t as readProcessMemory } from "../process-memory-
|
|
6
|
+
import { n as pickNodePlatformArch, t as readProcessMemory } from "../process-memory-CBzfdSvC.mjs";
|
|
7
7
|
import * as os$1 from "node:os";
|
|
8
8
|
import * as fs from "node:fs";
|
|
9
9
|
import * as path$1 from "node:path";
|
|
@@ -350,84 +350,6 @@ function normalizeEngineNodeId(rawNodeId) {
|
|
|
350
350
|
return raw.includes("/") ? raw.split("/")[0] ?? "hub" : raw;
|
|
351
351
|
}
|
|
352
352
|
//#endregion
|
|
353
|
-
//#region src/detection-pipeline/model-bound-device-overrides.ts
|
|
354
|
-
/**
|
|
355
|
-
* Auto tune (D745), the executor leg: list — and optionally remove — the
|
|
356
|
-
* MODEL-BOUND thresholds stored in this addon's per-camera settings (the
|
|
357
|
-
* object-detection root's `bindsToModel` keys and their binding keys, D738).
|
|
358
|
-
* Every other key of a camera's store is kept.
|
|
359
|
-
*
|
|
360
|
-
* The device store only MERGES on write, so a removal is clear + write of the
|
|
361
|
-
* kept keys — the idiom `migrate-hardware-state.ts` uses. Both run in this
|
|
362
|
-
* process, serialized per camera; a write that fails after the clear restores
|
|
363
|
-
* the original row, and the camera is reported `refused` rather than clean. A
|
|
364
|
-
* store that cannot be read is `refused` too: a failed read is never "nothing
|
|
365
|
-
* to clear" (D393).
|
|
366
|
-
*/
|
|
367
|
-
function errMsg(err) {
|
|
368
|
-
return err instanceof Error ? err.message : String(err);
|
|
369
|
-
}
|
|
370
|
-
/** The stored keys among `boundKeys` (values and bindings), sorted. */
|
|
371
|
-
function presentBoundKeys(row, boundKeys) {
|
|
372
|
-
return boundKeys.flatMap((k) => [k, modelBindingKey(k)]).filter((k) => k in row).toSorted();
|
|
373
|
-
}
|
|
374
|
-
async function clearModelBoundDeviceOverrides(deps, input) {
|
|
375
|
-
const ids = input.deviceIds ?? await deps.listDeviceIds();
|
|
376
|
-
const entries = [];
|
|
377
|
-
const refused = [];
|
|
378
|
-
for (const deviceId of [...ids].toSorted((a, b) => a - b)) {
|
|
379
|
-
let row;
|
|
380
|
-
try {
|
|
381
|
-
row = await deps.readDeviceStore(deviceId);
|
|
382
|
-
} catch (err) {
|
|
383
|
-
refused.push({
|
|
384
|
-
deviceId,
|
|
385
|
-
reason: `read failed: ${errMsg(err)}`
|
|
386
|
-
});
|
|
387
|
-
continue;
|
|
388
|
-
}
|
|
389
|
-
const keys = presentBoundKeys(row, deps.boundKeys);
|
|
390
|
-
if (keys.length === 0) continue;
|
|
391
|
-
if (input.dryRun) {
|
|
392
|
-
entries.push({
|
|
393
|
-
deviceId,
|
|
394
|
-
keys
|
|
395
|
-
});
|
|
396
|
-
continue;
|
|
397
|
-
}
|
|
398
|
-
const kept = { ...row };
|
|
399
|
-
for (const k of keys) delete kept[k];
|
|
400
|
-
try {
|
|
401
|
-
await deps.clearDeviceStore(deviceId);
|
|
402
|
-
} catch (err) {
|
|
403
|
-
refused.push({
|
|
404
|
-
deviceId,
|
|
405
|
-
reason: `clear failed: ${errMsg(err)}`
|
|
406
|
-
});
|
|
407
|
-
continue;
|
|
408
|
-
}
|
|
409
|
-
try {
|
|
410
|
-
if (Object.keys(kept).length > 0) await deps.writeDeviceStore(deviceId, kept);
|
|
411
|
-
entries.push({
|
|
412
|
-
deviceId,
|
|
413
|
-
keys
|
|
414
|
-
});
|
|
415
|
-
} catch (err) {
|
|
416
|
-
await deps.writeDeviceStore(deviceId, row).catch(() => void 0);
|
|
417
|
-
refused.push({
|
|
418
|
-
deviceId,
|
|
419
|
-
reason: `write failed, row restored: ${errMsg(err)}`
|
|
420
|
-
});
|
|
421
|
-
} finally {
|
|
422
|
-
deps.invalidate(deviceId);
|
|
423
|
-
}
|
|
424
|
-
}
|
|
425
|
-
return {
|
|
426
|
-
entries,
|
|
427
|
-
refused
|
|
428
|
-
};
|
|
429
|
-
}
|
|
430
|
-
//#endregion
|
|
431
353
|
//#region src/detection-pipeline/model-format-facts.ts
|
|
432
354
|
/**
|
|
433
355
|
* Two per-format facts `getSchema` reports beside `downloaded`, for Model
|
|
@@ -762,122 +684,6 @@ var ClusterUnknownRefusalLog = class {
|
|
|
762
684
|
}
|
|
763
685
|
};
|
|
764
686
|
//#endregion
|
|
765
|
-
//#region src/detection-pipeline/device-override-mirror.ts
|
|
766
|
-
/**
|
|
767
|
-
* The per-device detection overrides, kept fresh OFF the frame path.
|
|
768
|
-
*
|
|
769
|
-
* ## The read this replaces
|
|
770
|
-
*
|
|
771
|
-
* `runPipeline` resolved a device's overrides by calling
|
|
772
|
-
* `settings.readDeviceStore(deviceId)` on **every inference frame**. Measured
|
|
773
|
-
* on the live hub 2026-08-25: `get detection-pipeline:addon-devices`, 1 143
|
|
774
|
-
* calls a minute at 0.44 rows per call — the disk asked, nineteen times a
|
|
775
|
-
* second, whether an operator has ever changed a threshold.
|
|
776
|
-
*
|
|
777
|
-
* ## Why this is not "a cache in the consumer" (D224)
|
|
778
|
-
*
|
|
779
|
-
* D224 forbids a SECOND authority over a fact that belongs to somebody else:
|
|
780
|
-
* the failure it records is a consumer caching a value whose write path does
|
|
781
|
-
* not run through that consumer, so an operator's own change is the one read
|
|
782
|
-
* the cache gets wrong.
|
|
783
|
-
*
|
|
784
|
-
* This addon OWNS the row. `<addonId>:addon-devices` is detection-pipeline's
|
|
785
|
-
* own store, and the only writers are this addon's `updateDeviceSettings` and
|
|
786
|
-
* its `clearDeviceOverrides` — both of which call {@link invalidate}. A write
|
|
787
|
-
* is therefore its own invalidation, exactly as D224 requires, and the window
|
|
788
|
-
* below governs only the case nobody writes through this process.
|
|
789
|
-
*
|
|
790
|
-
* ## The window, declared
|
|
791
|
-
*
|
|
792
|
-
* {@link DEVICE_OVERRIDE_STALE_MS} is what an operator's change costs on a node
|
|
793
|
-
* that did NOT serve the write — this addon runs per node, and a settings write
|
|
794
|
-
* lands on one of them. Thirty seconds is the trade: it removes 99.9% of the
|
|
795
|
-
* reads (one per device per window instead of one per frame) and it is short
|
|
796
|
-
* enough that "I moved the threshold and nothing happened" is not a support
|
|
797
|
-
* question. Ten minutes — {@link OPERATOR_WRITTEN_STALE_MS}, the constant for a
|
|
798
|
-
* cap whose value only an operator changes — is right for a POLLED reader that
|
|
799
|
-
* costs a camera round trip; this read costs one local SQLite `get`, and the
|
|
800
|
-
* cheap read buys a short window.
|
|
801
|
-
*
|
|
802
|
-
* A stale entry is SERVED and revalidated behind the caller, never awaited: a
|
|
803
|
-
* frame that waits for the settings store is a frame the pipeline dropped, and
|
|
804
|
-
* the reader is by definition about to ask again.
|
|
805
|
-
*/
|
|
806
|
-
/**
|
|
807
|
-
* How long a mirrored entry is served before a refresh is started behind the
|
|
808
|
-
* next reader. See the module doc for why it is 30 s and not ten minutes.
|
|
809
|
-
*/
|
|
810
|
-
var DEVICE_OVERRIDE_STALE_MS = 3e4;
|
|
811
|
-
/**
|
|
812
|
-
* How long a FAILED refresh is not retried.
|
|
813
|
-
*
|
|
814
|
-
* A refresh that throws leaves `fetchedAt` where it was, so without a cooldown
|
|
815
|
-
* every subsequent frame would start another one — a broken settings store
|
|
816
|
-
* would be hammered at frame rate by the very mechanism built to stop that.
|
|
817
|
-
*/
|
|
818
|
-
var DEVICE_OVERRIDE_MISS_COOLDOWN_MS = 5e3;
|
|
819
|
-
var DeviceOverrideMirror = class {
|
|
820
|
-
deps;
|
|
821
|
-
staleMs;
|
|
822
|
-
missCooldownMs;
|
|
823
|
-
entries = /* @__PURE__ */ new Map();
|
|
824
|
-
/** In-flight reads, so a burst of frames on a cold device costs ONE read and
|
|
825
|
-
* not one per frame — the exact failure this class exists to remove. */
|
|
826
|
-
inFlight = /* @__PURE__ */ new Map();
|
|
827
|
-
now;
|
|
828
|
-
constructor(deps, staleMs = DEVICE_OVERRIDE_STALE_MS, missCooldownMs = DEVICE_OVERRIDE_MISS_COOLDOWN_MS) {
|
|
829
|
-
this.deps = deps;
|
|
830
|
-
this.staleMs = staleMs;
|
|
831
|
-
this.missCooldownMs = missCooldownMs;
|
|
832
|
-
this.now = deps.now ?? (() => Date.now());
|
|
833
|
-
}
|
|
834
|
-
/**
|
|
835
|
-
* The device's overrides.
|
|
836
|
-
*
|
|
837
|
-
* COLD awaits — the first frame on a camera has to get the real answer, and a
|
|
838
|
-
* default is exactly what "the operator lowered this threshold" looks like.
|
|
839
|
-
* WARM returns immediately, stale or not, and starts the refresh behind the
|
|
840
|
-
* caller.
|
|
841
|
-
*/
|
|
842
|
-
async resolve(deviceId) {
|
|
843
|
-
const entry = this.entries.get(deviceId);
|
|
844
|
-
if (entry === void 0) return this.load(deviceId);
|
|
845
|
-
if (this.now() - entry.fetchedAt >= this.staleMs) this.load(deviceId);
|
|
846
|
-
return entry.value;
|
|
847
|
-
}
|
|
848
|
-
/** Drop a device's entry. Called by every writer in this process, so an
|
|
849
|
-
* operator's own change is never served from the mirror. */
|
|
850
|
-
invalidate(deviceId) {
|
|
851
|
-
this.entries.delete(deviceId);
|
|
852
|
-
}
|
|
853
|
-
invalidateAll() {
|
|
854
|
-
this.entries.clear();
|
|
855
|
-
}
|
|
856
|
-
async load(deviceId) {
|
|
857
|
-
const pending = this.inFlight.get(deviceId);
|
|
858
|
-
if (pending !== void 0) return pending;
|
|
859
|
-
const run = this.deps.read(deviceId).then((value) => {
|
|
860
|
-
this.entries.set(deviceId, {
|
|
861
|
-
value,
|
|
862
|
-
fetchedAt: this.now()
|
|
863
|
-
});
|
|
864
|
-
return value;
|
|
865
|
-
}).catch((err) => {
|
|
866
|
-
this.deps.onRefreshFailed?.(deviceId, err);
|
|
867
|
-
const existing = this.entries.get(deviceId);
|
|
868
|
-
if (existing !== void 0) {
|
|
869
|
-
existing.fetchedAt = this.now() - this.staleMs + this.missCooldownMs;
|
|
870
|
-
return existing.value;
|
|
871
|
-
}
|
|
872
|
-
return {};
|
|
873
|
-
}).finally(() => {
|
|
874
|
-
this.inFlight.delete(deviceId);
|
|
875
|
-
});
|
|
876
|
-
this.inFlight.set(deviceId, run);
|
|
877
|
-
return run;
|
|
878
|
-
}
|
|
879
|
-
};
|
|
880
|
-
//#endregion
|
|
881
687
|
//#region src/detection-pipeline/engine/pool-worker-health.ts
|
|
882
688
|
/**
|
|
883
689
|
* The one table of load bounds (D653, fix round 1).
|
|
@@ -4222,6 +4028,29 @@ function benchmarkKeyOf(deviceKey) {
|
|
|
4222
4028
|
function isBenchmarkRun(input) {
|
|
4223
4029
|
return input.frame === void 0 && input.frameRef === void 0 && input.deviceId === void 0 && input.replay !== true;
|
|
4224
4030
|
}
|
|
4031
|
+
/**
|
|
4032
|
+
* Backends whose device opens in ONE process at a time. libedgetpu holds an
|
|
4033
|
+
* Edge TPU exclusively for the process that opened it, so a second pool on a
|
|
4034
|
+
* Coral the cameras' pool already holds cannot open it at all — every
|
|
4035
|
+
* benchmark and auto-benchmark (D913) of an in-use Coral failed that way on
|
|
4036
|
+
* the dev hub (1.2.619). Every other backend this node builds (OpenVINO,
|
|
4037
|
+
* CoreML, CUDA, ONNX, CPU) shares its device between processes.
|
|
4038
|
+
*/
|
|
4039
|
+
var EXCLUSIVE_BACKENDS = new Set(["edgetpu"]);
|
|
4040
|
+
/** True when the device behind `deviceKey` (`<backend>:<device>`) cannot be opened by a second pool. */
|
|
4041
|
+
function isExclusiveDevice(deviceKey) {
|
|
4042
|
+
const colon = deviceKey.indexOf(":");
|
|
4043
|
+
const backend = colon >= 0 ? deviceKey.slice(0, colon) : deviceKey;
|
|
4044
|
+
return EXCLUSIVE_BACKENDS.has(backend);
|
|
4045
|
+
}
|
|
4046
|
+
/**
|
|
4047
|
+
* A benchmark on an EXCLUSIVE device is the one benchmark that goes to the
|
|
4048
|
+
* live pool: the separate pool could not open the device, so the choice is
|
|
4049
|
+
* between measuring through the cameras' pool and not measuring at all.
|
|
4050
|
+
*/
|
|
4051
|
+
function benchmarkPlacementOf(benchmark, deviceKey) {
|
|
4052
|
+
return benchmark && !isExclusiveDevice(deviceKey) ? "benchmark-pool" : "live-pool";
|
|
4053
|
+
}
|
|
4225
4054
|
var BenchmarkPools = class {
|
|
4226
4055
|
options;
|
|
4227
4056
|
pools = /* @__PURE__ */ new Map();
|
|
@@ -4802,14 +4631,15 @@ var PRIMARY_ROOT_STEP = "object-detection";
|
|
|
4802
4631
|
/**
|
|
4803
4632
|
* The same rule over an EXECUTABLE tree's roots (D658): their model ids are the
|
|
4804
4633
|
* pool variants that will run — after resolution, per-step loads and drops —
|
|
4805
|
-
* so this is what a live `runPipeline` stamps
|
|
4806
|
-
* video roots already.
|
|
4807
|
-
*/
|
|
4808
|
-
function
|
|
4809
|
-
|
|
4810
|
-
|
|
4811
|
-
|
|
4812
|
-
|
|
4634
|
+
* so this is what a live `runPipeline` stamps, with the root's step id beside
|
|
4635
|
+
* the model (D925). The tree holds only enabled video roots already.
|
|
4636
|
+
*/
|
|
4637
|
+
function resolveTreeRoot(roots) {
|
|
4638
|
+
const root = roots.find((s) => s.stepId === PRIMARY_ROOT_STEP) ?? roots[0];
|
|
4639
|
+
return root === void 0 ? void 0 : {
|
|
4640
|
+
stepId: root.stepId,
|
|
4641
|
+
modelId: root.modelId
|
|
4642
|
+
};
|
|
4813
4643
|
}
|
|
4814
4644
|
//#endregion
|
|
4815
4645
|
//#region src/detection-pipeline/engine-provisioner.ts
|
|
@@ -7189,7 +7019,7 @@ var PipelineExecutor = class {
|
|
|
7189
7019
|
rootStepId: rootStep.stepId,
|
|
7190
7020
|
parentClass: mutable.macroClass,
|
|
7191
7021
|
parentScore: mutable.score,
|
|
7192
|
-
error: errMsg
|
|
7022
|
+
error: errMsg(err)
|
|
7193
7023
|
}
|
|
7194
7024
|
});
|
|
7195
7025
|
}
|
|
@@ -7320,7 +7150,7 @@ var PipelineExecutor = class {
|
|
|
7320
7150
|
rootStepId: rootStep.stepId,
|
|
7321
7151
|
parentClass: mutable.macroClass,
|
|
7322
7152
|
parentScore: mutable.score,
|
|
7323
|
-
error: errMsg
|
|
7153
|
+
error: errMsg(err)
|
|
7324
7154
|
}
|
|
7325
7155
|
});
|
|
7326
7156
|
}
|
|
@@ -7419,7 +7249,7 @@ var PipelineExecutor = class {
|
|
|
7419
7249
|
]
|
|
7420
7250
|
};
|
|
7421
7251
|
} catch (err) {
|
|
7422
|
-
this.throttledWarn(`crop-zone-prep:${deviceId}`, 3e4, "crop-zone frame preparation failed — running package-detection full-frame", { error: errMsg
|
|
7252
|
+
this.throttledWarn(`crop-zone-prep:${deviceId}`, 3e4, "crop-zone frame preparation failed — running package-detection full-frame", { error: errMsg(err) }, deviceId);
|
|
7423
7253
|
return null;
|
|
7424
7254
|
}
|
|
7425
7255
|
}
|
|
@@ -7431,7 +7261,7 @@ var PipelineExecutor = class {
|
|
|
7431
7261
|
try {
|
|
7432
7262
|
engineOutput = await step.engine.infer(input);
|
|
7433
7263
|
} catch (err) {
|
|
7434
|
-
const errorMsg = errMsg
|
|
7264
|
+
const errorMsg = errMsg(err);
|
|
7435
7265
|
const errorOutput = {
|
|
7436
7266
|
kind: "detections",
|
|
7437
7267
|
detections: []
|
|
@@ -7718,7 +7548,7 @@ var PipelineExecutor = class {
|
|
|
7718
7548
|
this.throttledWarn(`child-fail:${child.stepId}:${deviceId}`, 15e3, "pipeline child step failed", {
|
|
7719
7549
|
step: child.stepId,
|
|
7720
7550
|
model: child.modelId,
|
|
7721
|
-
error: errMsg
|
|
7551
|
+
error: errMsg(err)
|
|
7722
7552
|
}, deviceId);
|
|
7723
7553
|
}
|
|
7724
7554
|
}
|
|
@@ -7865,16 +7695,6 @@ function collectSchemaDefaults(schema) {
|
|
|
7865
7695
|
walkFieldsForDefaults(schema, out);
|
|
7866
7696
|
return out;
|
|
7867
7697
|
}
|
|
7868
|
-
/**
|
|
7869
|
-
* The operator settings of `stepId` as the model that RUNS sees them (D738):
|
|
7870
|
-
* a model-bound value made for another model is dropped and binding keys are
|
|
7871
|
-
* stripped. For a settings layer merged AFTER the tree is built (the
|
|
7872
|
-
* executor's per-device store, `applyDeviceOverridesToTree`), so it obeys the
|
|
7873
|
-
* same binding as the layers `buildNode` merges.
|
|
7874
|
-
*/
|
|
7875
|
-
function resolveOperatorSettingsForModel(stepId, settings, runningModelId) {
|
|
7876
|
-
return applyModelBoundSettings(settings, collectModelBoundKeys(getStep(stepId).getConfigSchema()), runningModelId) ?? {};
|
|
7877
|
-
}
|
|
7878
7698
|
function walkFieldsForDefaults(fields, out) {
|
|
7879
7699
|
for (const field of fields) {
|
|
7880
7700
|
if ("type" in field && field.type === "group" && "fields" in field) {
|
|
@@ -8563,7 +8383,7 @@ var DetectionPipelineProvider = class DetectionPipelineProvider {
|
|
|
8563
8383
|
* node-default tree against `this.currentEngine.format`. Recomputed
|
|
8564
8384
|
* EAGERLY by {@link recomputeConfigIssues} whenever the engine actually
|
|
8565
8385
|
* changes (see `onEngineSelectionChanged`), rather than relying on a
|
|
8566
|
-
* `
|
|
8386
|
+
* `nodeDefaultSteps()` call that may never happen on a camera-only node.
|
|
8567
8387
|
* Merged into {@link getEngineProvisioning}'s snapshot; never consulted by
|
|
8568
8388
|
* `assertEngineReady` — this gate SURFACES, it does not block inference.
|
|
8569
8389
|
*/
|
|
@@ -8665,20 +8485,6 @@ var DetectionPipelineProvider = class DetectionPipelineProvider {
|
|
|
8665
8485
|
readStore;
|
|
8666
8486
|
/** Write a patch to the addon settings store. */
|
|
8667
8487
|
writeStore;
|
|
8668
|
-
/** Read per-device settings. */
|
|
8669
|
-
readDeviceStore;
|
|
8670
|
-
/** Delete all per-device settings for a device (used by `clearDeviceOverrides`). */
|
|
8671
|
-
clearDeviceStore;
|
|
8672
|
-
/** Merge a patch into one device's settings (Auto tune' keep-the-rest rewrite, D745). */
|
|
8673
|
-
writeDeviceStore;
|
|
8674
|
-
/**
|
|
8675
|
-
* The per-device overrides the FRAME path reads, kept fresh off that path.
|
|
8676
|
-
*
|
|
8677
|
-
* Public so the addon class can drop a device on its own
|
|
8678
|
-
* `updateDeviceSettings` — the write and the mirror have to be the same
|
|
8679
|
-
* process's, or the mirror becomes the second authority D224 forbids.
|
|
8680
|
-
*/
|
|
8681
|
-
deviceOverrides;
|
|
8682
8488
|
constructor(settings, modelsDir, logger, eventBus = null, detectionConfigSchemaSource = null, executorOptions = {}) {
|
|
8683
8489
|
this.modelsDir = modelsDir;
|
|
8684
8490
|
this.eventBus = eventBus;
|
|
@@ -8687,18 +8493,6 @@ var DetectionPipelineProvider = class DetectionPipelineProvider {
|
|
|
8687
8493
|
this.log = logger;
|
|
8688
8494
|
this.readStore = () => settings.readAddonStore();
|
|
8689
8495
|
this.writeStore = (patch) => settings.writeAddonStore(patch);
|
|
8690
|
-
this.readDeviceStore = settings.readDeviceStore ?? (async () => ({}));
|
|
8691
|
-
const clearDeviceStore = settings.clearDeviceStore;
|
|
8692
|
-
this.clearDeviceStore = clearDeviceStore ? (deviceId) => clearDeviceStore.call(settings, deviceId) : async () => void 0;
|
|
8693
|
-
const writeDeviceStore = settings.writeDeviceStore;
|
|
8694
|
-
this.writeDeviceStore = writeDeviceStore ? (deviceId, patch) => writeDeviceStore.call(settings, deviceId, patch) : async () => void 0;
|
|
8695
|
-
this.deviceOverrides = new DeviceOverrideMirror({
|
|
8696
|
-
read: (deviceId) => this.readDeviceStore(deviceId),
|
|
8697
|
-
onRefreshFailed: (deviceId, err) => this.log.warn("per-device detection overrides refresh failed — serving the last value", {
|
|
8698
|
-
tags: { deviceId },
|
|
8699
|
-
meta: { error: errMsg$1(err) }
|
|
8700
|
-
})
|
|
8701
|
-
});
|
|
8702
8496
|
this.currentEngine = ONNX_FLOOR;
|
|
8703
8497
|
this.log.info("Engine pick pending (placeholder until probe / persisted selection)", { meta: {
|
|
8704
8498
|
runtime: this.currentEngine.runtime,
|
|
@@ -8722,7 +8516,7 @@ var DetectionPipelineProvider = class DetectionPipelineProvider {
|
|
|
8722
8516
|
stale: report.stale
|
|
8723
8517
|
} });
|
|
8724
8518
|
}, (err) => {
|
|
8725
|
-
this.log.warn("Model revision check failed — copies are proven on their next download", { meta: { error: errMsg
|
|
8519
|
+
this.log.warn("Model revision check failed — copies are proven on their next download", { meta: { error: errMsg(err) } });
|
|
8726
8520
|
});
|
|
8727
8521
|
}
|
|
8728
8522
|
/**
|
|
@@ -8832,14 +8626,14 @@ var DetectionPipelineProvider = class DetectionPipelineProvider {
|
|
|
8832
8626
|
else this.log.warn("platform-probe readiness gate timed out — conservative engine pick (floor is not persisted)", { meta: {
|
|
8833
8627
|
nodeId,
|
|
8834
8628
|
timeoutMs: PROBE_READY_TIMEOUT_MS,
|
|
8835
|
-
error: errMsg
|
|
8629
|
+
error: errMsg(err)
|
|
8836
8630
|
} });
|
|
8837
8631
|
}
|
|
8838
8632
|
await this.resolveAutoEngine();
|
|
8839
8633
|
this.needsAutoPick = false;
|
|
8840
8634
|
this.startProvisioningForCurrentEngine();
|
|
8841
8635
|
await this.recomputeConfigIssues().catch((err) => {
|
|
8842
|
-
this.log.warn("config-issue recompute failed after node-default derive", { meta: { error: errMsg
|
|
8636
|
+
this.log.warn("config-issue recompute failed after node-default derive", { meta: { error: errMsg(err) } });
|
|
8843
8637
|
});
|
|
8844
8638
|
}
|
|
8845
8639
|
/**
|
|
@@ -9001,7 +8795,7 @@ var DetectionPipelineProvider = class DetectionPipelineProvider {
|
|
|
9001
8795
|
* the node-default step tree for `this.currentEngine.format` and compute
|
|
9002
8796
|
* human-readable config issues from the result:
|
|
9003
8797
|
* - model substitutions (`getActiveModelSubstitutions()`, populated as a
|
|
9004
|
-
* side effect of the `
|
|
8798
|
+
* side effect of the `nodeDefaultSteps()` re-resolve below) — a step's
|
|
9005
8799
|
* chosen model lacks a build for this format, so the format default
|
|
9006
8800
|
* runs instead (degraded but loadable).
|
|
9007
8801
|
* - zero-build steps (`collectZeroBuildIssues`) — a step whose FULL
|
|
@@ -9016,7 +8810,7 @@ var DetectionPipelineProvider = class DetectionPipelineProvider {
|
|
|
9016
8810
|
async recomputeConfigIssues() {
|
|
9017
8811
|
this.configIssues = [];
|
|
9018
8812
|
try {
|
|
9019
|
-
const steps = await this.
|
|
8813
|
+
const steps = await this.nodeDefaultSteps();
|
|
9020
8814
|
if (!steps) return;
|
|
9021
8815
|
const format = this.currentEngine.format;
|
|
9022
8816
|
const substitutionIssues = this.getActiveModelSubstitutions().map((s) => `${s.addonId}: chose ${s.chosen}, running ${s.running} (${s.format})`);
|
|
@@ -9024,7 +8818,7 @@ var DetectionPipelineProvider = class DetectionPipelineProvider {
|
|
|
9024
8818
|
this.configIssues = [...substitutionIssues, ...zeroBuildIssues];
|
|
9025
8819
|
} catch (err) {
|
|
9026
8820
|
this.configIssues = [];
|
|
9027
|
-
this.log.warn("engine-change config gate failed — no config issues surfaced", { meta: { error: errMsg
|
|
8821
|
+
this.log.warn("engine-change config gate failed — no config issues surfaced", { meta: { error: errMsg(err) } });
|
|
9028
8822
|
}
|
|
9029
8823
|
}
|
|
9030
8824
|
/**
|
|
@@ -9064,7 +8858,7 @@ var DetectionPipelineProvider = class DetectionPipelineProvider {
|
|
|
9064
8858
|
* `format` for the download fan-out.
|
|
9065
8859
|
*/
|
|
9066
8860
|
async ensureModelsForCurrentSteps(format) {
|
|
9067
|
-
const steps = await this.
|
|
8861
|
+
const steps = await this.nodeDefaultSteps();
|
|
9068
8862
|
if (!steps || steps.length === 0) return;
|
|
9069
8863
|
for (const step of flattenSteps(steps)) {
|
|
9070
8864
|
if (!step.enabled) continue;
|
|
@@ -9237,10 +9031,6 @@ var DetectionPipelineProvider = class DetectionPipelineProvider {
|
|
|
9237
9031
|
defaultDevice: e.engine.device
|
|
9238
9032
|
};
|
|
9239
9033
|
}
|
|
9240
|
-
async getDefaultSteps(engine) {
|
|
9241
|
-
const detectionModelId = resolveDefaultDetectionModel(engine.backend, engine.device ?? null, engine.format);
|
|
9242
|
-
return buildDefaultStepTree(engine.format, detectionModelId);
|
|
9243
|
-
}
|
|
9244
9034
|
/**
|
|
9245
9035
|
* Resolve every step's model for this node's engine format via the shared
|
|
9246
9036
|
* `resolveModelForFormat`, and surface any substitution. `step.engine?.format`
|
|
@@ -9283,18 +9073,19 @@ var DetectionPipelineProvider = class DetectionPipelineProvider {
|
|
|
9283
9073
|
return [...this.modelSubstitutions.values()];
|
|
9284
9074
|
}
|
|
9285
9075
|
/**
|
|
9286
|
-
* PURE node-default step tree — computed on demand, never persisted
|
|
9076
|
+
* PURE node-default step tree — computed on demand, never persisted, and
|
|
9077
|
+
* PRIVATE (D927): it is not the model any camera ran, so no caller outside
|
|
9078
|
+
* this provider may read it. It serves Gate A's config-issue probe and the
|
|
9079
|
+
* engine provisioning's model download.
|
|
9287
9080
|
*
|
|
9288
9081
|
* The object-detection default is hardware-aware (this node's resolved
|
|
9289
9082
|
* backend + device via `resolveDefaultDetectionModel`); every other step
|
|
9290
9083
|
* keeps its flat per-format default. The result is cached in
|
|
9291
9084
|
* `currentSteps` only as a memo — the cache is dropped whenever the
|
|
9292
9085
|
* engine (hence model format) changes, so a re-read always reflects the
|
|
9293
|
-
* live engine.
|
|
9294
|
-
* it exists as the benchmark fallback (empty input steps), the Gate-A
|
|
9295
|
-
* config-issue probe, and the "effective post-reset model" probe.
|
|
9086
|
+
* live engine.
|
|
9296
9087
|
*/
|
|
9297
|
-
async
|
|
9088
|
+
async nodeDefaultSteps() {
|
|
9298
9089
|
if (this.currentSteps) return this.currentSteps;
|
|
9299
9090
|
const detectionModelId = resolveDefaultDetectionModel(this.currentEngine.backend, this.currentEngine.device ?? null, this.currentEngine.format);
|
|
9300
9091
|
const defaults = buildDefaultStepTree(this.currentEngine.format, detectionModelId);
|
|
@@ -9302,10 +9093,6 @@ var DetectionPipelineProvider = class DetectionPipelineProvider {
|
|
|
9302
9093
|
this.currentSteps = this.resolveStepModels(defaults);
|
|
9303
9094
|
return this.currentSteps;
|
|
9304
9095
|
}
|
|
9305
|
-
async getGlobalPipelineConfig() {
|
|
9306
|
-
if (!this.currentSteps) return null;
|
|
9307
|
-
return stepsToPipelineConfig(this.currentSteps, this.currentEngine);
|
|
9308
|
-
}
|
|
9309
9096
|
/**
|
|
9310
9097
|
* Task G5 (Gate B) — pre-init config-correctness gate. PURE COMPUTE
|
|
9311
9098
|
* against `this.currentEngine.format`: resolves `steps` the same way the
|
|
@@ -9349,7 +9136,7 @@ var DetectionPipelineProvider = class DetectionPipelineProvider {
|
|
|
9349
9136
|
issues: [{
|
|
9350
9137
|
addonId: "*",
|
|
9351
9138
|
kind: "unknown-device",
|
|
9352
|
-
detail: errMsg
|
|
9139
|
+
detail: errMsg(err)
|
|
9353
9140
|
}],
|
|
9354
9141
|
substitutions: [],
|
|
9355
9142
|
format
|
|
@@ -9376,7 +9163,7 @@ var DetectionPipelineProvider = class DetectionPipelineProvider {
|
|
|
9376
9163
|
format
|
|
9377
9164
|
};
|
|
9378
9165
|
} catch (err) {
|
|
9379
|
-
this.log.warn("validatePipeline failed — reporting a clean result", { meta: { error: errMsg
|
|
9166
|
+
this.log.warn("validatePipeline failed — reporting a clean result", { meta: { error: errMsg(err) } });
|
|
9380
9167
|
return {
|
|
9381
9168
|
ok: true,
|
|
9382
9169
|
issues: [],
|
|
@@ -9568,7 +9355,7 @@ var DetectionPipelineProvider = class DetectionPipelineProvider {
|
|
|
9568
9355
|
durationMs
|
|
9569
9356
|
};
|
|
9570
9357
|
} catch (err) {
|
|
9571
|
-
const msg = errMsg
|
|
9358
|
+
const msg = errMsg(err);
|
|
9572
9359
|
this.log.error("Model download failed", { meta: {
|
|
9573
9360
|
error: msg,
|
|
9574
9361
|
modelId,
|
|
@@ -9888,7 +9675,9 @@ var DetectionPipelineProvider = class DetectionPipelineProvider {
|
|
|
9888
9675
|
this.executor = executor;
|
|
9889
9676
|
const dispatchEngine = dispatchDeviceKey ? resolveDeviceEngine(dispatchDeviceKey) : runEngine;
|
|
9890
9677
|
const benchmark = isBenchmarkRun(input);
|
|
9891
|
-
const
|
|
9678
|
+
const placement = benchmarkPlacementOf(benchmark, deviceKeyOf(dispatchEngine));
|
|
9679
|
+
if (benchmark && placement === "live-pool") this.log.info("Benchmark on an exclusive device — served by the live pool", { meta: { deviceKey: deviceKeyOf(dispatchEngine) } });
|
|
9680
|
+
const dispatchFactory = placement === "benchmark-pool" ? await this.benchmarkPools.acquire(deviceKeyOf(dispatchEngine), dispatchEngine) : dispatchDeviceKey ? await this.resolveDeviceFactory(dispatchDeviceKey) : this.engineFactory;
|
|
9892
9681
|
const needed = enabledSteps.filter((s) => dispatchFactory.needsPoolUpdate(s));
|
|
9893
9682
|
let runSteps = benchmarkSteps;
|
|
9894
9683
|
const loadPolicy = dispatchLoadPolicyOf(input);
|
|
@@ -9926,24 +9715,24 @@ var DetectionPipelineProvider = class DetectionPipelineProvider {
|
|
|
9926
9715
|
...input.deviceId !== void 0 ? { deviceId: input.deviceId } : {},
|
|
9927
9716
|
deviceKey: dispatchDeviceKeyLabel,
|
|
9928
9717
|
outcome: "step-dropped"
|
|
9929
|
-
}, dispatchDeviceKeyLabel, [model], model, "not-warm", errMsg
|
|
9718
|
+
}, dispatchDeviceKeyLabel, [model], model, "not-warm", errMsg(failure.error));
|
|
9930
9719
|
}
|
|
9931
9720
|
}
|
|
9932
|
-
const
|
|
9721
|
+
const treeRoot = resolveTreeRoot(tree.roots);
|
|
9933
9722
|
const rootDeviceKey = deviceKeyOf(dispatchEngine);
|
|
9934
|
-
const stampRoot = (r) =>
|
|
9723
|
+
const stampRoot = (r) => treeRoot === void 0 ? {
|
|
9935
9724
|
...r,
|
|
9936
9725
|
rootDeviceKey
|
|
9937
9726
|
} : {
|
|
9938
9727
|
...r,
|
|
9939
|
-
rootModelId,
|
|
9728
|
+
rootModelId: treeRoot.modelId,
|
|
9729
|
+
rootStepId: treeRoot.stepId,
|
|
9940
9730
|
rootDeviceKey
|
|
9941
9731
|
};
|
|
9942
9732
|
if (input.replay !== true) this.clusterModelSwitchLog.note(input.deviceId ?? 0, tree);
|
|
9943
9733
|
setupMs = performance.now() - wallT0 - decodeMs;
|
|
9944
9734
|
const effectiveDeviceId = input.deviceId ?? 0;
|
|
9945
|
-
const
|
|
9946
|
-
const effectiveTree = Object.keys(deviceOverrides).length > 0 ? applyDeviceOverridesToTree(tree, "object-detection", deviceOverrides) : tree;
|
|
9735
|
+
const effectiveTree = tree;
|
|
9947
9736
|
const nativeCropProvider = this.buildNativeCropProviderFromRef(input.nativeCropRef) ?? this.buildNativeFaceCropProvider(input.frameHandle);
|
|
9948
9737
|
let cropZoneBbox;
|
|
9949
9738
|
if (appliesCameraGates && effectiveDeviceId > 0 && effectiveTree.roots.some((r) => r.definition.extractMode === "crop-zone")) {
|
|
@@ -10339,7 +10128,7 @@ var DetectionPipelineProvider = class DetectionPipelineProvider {
|
|
|
10339
10128
|
...tags,
|
|
10340
10129
|
meta: {
|
|
10341
10130
|
deviceKey,
|
|
10342
|
-
error: errMsg
|
|
10131
|
+
error: errMsg(err)
|
|
10343
10132
|
}
|
|
10344
10133
|
});
|
|
10345
10134
|
});
|
|
@@ -10376,7 +10165,7 @@ var DetectionPipelineProvider = class DetectionPipelineProvider {
|
|
|
10376
10165
|
throw err;
|
|
10377
10166
|
}
|
|
10378
10167
|
const failed = failedModelOf(err) ?? models[0] ?? "";
|
|
10379
|
-
this.reportDispatchLoadLoss(context, deviceKey, models, failed, `failed:${flight.generation ?? "unknown"}`, errMsg
|
|
10168
|
+
this.reportDispatchLoadLoss(context, deviceKey, models, failed, `failed:${flight.generation ?? "unknown"}`, errMsg(err));
|
|
10380
10169
|
throw err;
|
|
10381
10170
|
}
|
|
10382
10171
|
}
|
|
@@ -10473,13 +10262,13 @@ var DetectionPipelineProvider = class DetectionPipelineProvider {
|
|
|
10473
10262
|
const poolModel = err instanceof StepVariantLoadError ? err.poolModel : null;
|
|
10474
10263
|
let generation = 0;
|
|
10475
10264
|
for (const model of failedModels) {
|
|
10476
|
-
const outcome = this.loadGovernor.recordFailure(pool, deviceKey, model, errMsg
|
|
10265
|
+
const outcome = this.loadGovernor.recordFailure(pool, deviceKey, model, errMsg(err), compileTimeout, Date.now(), poolModel, err instanceof StepVariantLoadError ? err.reason : null);
|
|
10477
10266
|
generation = outcome.generation;
|
|
10478
10267
|
if (outcome.refusedNow) this.log.error("model REFUSED on this device — its compile timed out repeatedly", { meta: {
|
|
10479
10268
|
deviceKey,
|
|
10480
10269
|
model,
|
|
10481
10270
|
compileTimeouts: outcome.compileTimeouts,
|
|
10482
|
-
error: errMsg
|
|
10271
|
+
error: errMsg(err),
|
|
10483
10272
|
device: "keeps serving every other model",
|
|
10484
10273
|
rearm: "pipelineExecutor.rearmInferenceDevice"
|
|
10485
10274
|
} });
|
|
@@ -10540,7 +10329,7 @@ var DetectionPipelineProvider = class DetectionPipelineProvider {
|
|
|
10540
10329
|
this.log.info("Model downloaded successfully", { meta: { modelId: entry.id } });
|
|
10541
10330
|
return;
|
|
10542
10331
|
} catch (err) {
|
|
10543
|
-
const msg = errMsg
|
|
10332
|
+
const msg = errMsg(err);
|
|
10544
10333
|
if (attempt < maxRetries) {
|
|
10545
10334
|
const delayMs = 2e3 * Math.pow(2, attempt - 1);
|
|
10546
10335
|
this.log.warn("Model download failed — retrying", { meta: {
|
|
@@ -10616,7 +10405,7 @@ var DetectionPipelineProvider = class DetectionPipelineProvider {
|
|
|
10616
10405
|
try {
|
|
10617
10406
|
return await this.runPipelineBatchImpl(input);
|
|
10618
10407
|
} catch (err) {
|
|
10619
|
-
const msg = errMsg
|
|
10408
|
+
const msg = errMsg(err);
|
|
10620
10409
|
const stack = err instanceof Error ? err.stack : void 0;
|
|
10621
10410
|
this.log.error("runPipelineBatch failed", { meta: {
|
|
10622
10411
|
phase: "batch",
|
|
@@ -10901,9 +10690,9 @@ var DetectionPipelineProvider = class DetectionPipelineProvider {
|
|
|
10901
10690
|
deviceKey: defaultDeviceKey,
|
|
10902
10691
|
backend: this.currentEngine.backend,
|
|
10903
10692
|
device: this.currentEngine.device ?? null,
|
|
10904
|
-
error: errMsg
|
|
10693
|
+
error: errMsg(err)
|
|
10905
10694
|
} });
|
|
10906
|
-
this.noteDeviceDeath(defaultDeviceKey, errMsg
|
|
10695
|
+
this.noteDeviceDeath(defaultDeviceKey, errMsg(err));
|
|
10907
10696
|
throw err;
|
|
10908
10697
|
}
|
|
10909
10698
|
this.engineFactory = factory;
|
|
@@ -11165,7 +10954,7 @@ var DetectionPipelineProvider = class DetectionPipelineProvider {
|
|
|
11165
10954
|
await factory.dispose().catch(() => void 0);
|
|
11166
10955
|
this.log.error("Benchmark pool failed to initialize", { meta: {
|
|
11167
10956
|
deviceKey,
|
|
11168
|
-
error: errMsg
|
|
10957
|
+
error: errMsg(err)
|
|
11169
10958
|
} });
|
|
11170
10959
|
throw err;
|
|
11171
10960
|
}
|
|
@@ -11212,7 +11001,7 @@ var DetectionPipelineProvider = class DetectionPipelineProvider {
|
|
|
11212
11001
|
error: err instanceof Error ? err.message : String(err)
|
|
11213
11002
|
} });
|
|
11214
11003
|
await factory.dispose().catch(() => void 0);
|
|
11215
|
-
this.noteDeviceDeath(deviceKey, errMsg
|
|
11004
|
+
this.noteDeviceDeath(deviceKey, errMsg(err));
|
|
11216
11005
|
throw err;
|
|
11217
11006
|
}
|
|
11218
11007
|
this.factoriesByDevice.set(deviceKey, factory);
|
|
@@ -11278,102 +11067,6 @@ var DetectionPipelineProvider = class DetectionPipelineProvider {
|
|
|
11278
11067
|
this.log.info("videoPipelineSteps updated", { meta: { addons: Object.keys(sanitized).length } });
|
|
11279
11068
|
return { success: true };
|
|
11280
11069
|
}
|
|
11281
|
-
/**
|
|
11282
|
-
* Clear THIS node's executor-side PER-DEVICE settings stores — the
|
|
11283
|
-
* per-camera step overrides the object-detection root reads via
|
|
11284
|
-
* `applyDeviceOverridesToTree`.
|
|
11285
|
-
*
|
|
11286
|
-
* Node-routed (the cap's default `nodeIdMode: 'routing'`): the generated
|
|
11287
|
-
* cap-router strips `nodeId` and dispatches to the target node, so this
|
|
11288
|
-
* method runs ON the node being cleared and takes no argument.
|
|
11289
|
-
*
|
|
11290
|
-
* This is the slimmed executor leg of the orchestrator's
|
|
11291
|
-
* `resetNodePipelineDefaults` flow. The legacy `resetToDefault` — which
|
|
11292
|
-
* also reset a persisted GLOBAL step-tree seed nothing in the live
|
|
11293
|
-
* per-camera path read — was removed together with that seed
|
|
11294
|
-
* (`getGlobalSteps` is pure now, so there is nothing node-global left to
|
|
11295
|
-
* reset here).
|
|
11296
|
-
*
|
|
11297
|
-
* Idempotent: clearing already-empty per-device stores is a no-op.
|
|
11298
|
-
*/
|
|
11299
|
-
async clearDeviceOverrides() {
|
|
11300
|
-
const clearedDevices = await this.clearAllDeviceOverrides();
|
|
11301
|
-
this.log.info("executor per-device overrides cleared", { meta: { clearedDevices } });
|
|
11302
|
-
return {
|
|
11303
|
-
success: true,
|
|
11304
|
-
clearedDevices
|
|
11305
|
-
};
|
|
11306
|
-
}
|
|
11307
|
-
/**
|
|
11308
|
-
* Auto tune (D745): list — or, unless `dryRun`, remove — the model-bound
|
|
11309
|
-
* thresholds of the per-camera detector store. See
|
|
11310
|
-
* `model-bound-device-overrides.ts`.
|
|
11311
|
-
*/
|
|
11312
|
-
async clearModelBoundDeviceOverrides(input) {
|
|
11313
|
-
const result = await clearModelBoundDeviceOverrides({
|
|
11314
|
-
listDeviceIds: async () => {
|
|
11315
|
-
const api = this.addonCtx?.api;
|
|
11316
|
-
if (!api) throw new Error("clearModelBoundDeviceOverrides: ctx.api unavailable");
|
|
11317
|
-
return (await api.deviceManager.listAll.query({ projection: "slim" })).map((d) => d.id);
|
|
11318
|
-
},
|
|
11319
|
-
readDeviceStore: (deviceId) => this.readDeviceStore(deviceId),
|
|
11320
|
-
clearDeviceStore: (deviceId) => this.clearDeviceStore(deviceId),
|
|
11321
|
-
writeDeviceStore: (deviceId, patch) => this.writeDeviceStore(deviceId, patch),
|
|
11322
|
-
invalidate: (deviceId) => this.deviceOverrides.invalidate(deviceId),
|
|
11323
|
-
boundKeys: collectModelBoundKeys(getStep("object-detection").getConfigSchema())
|
|
11324
|
-
}, input);
|
|
11325
|
-
if (!input.dryRun) for (const entry of result.entries) this.log.info("auto tune: per-camera detector thresholds cleared", {
|
|
11326
|
-
tags: { deviceId: entry.deviceId },
|
|
11327
|
-
meta: {
|
|
11328
|
-
deviceId: entry.deviceId,
|
|
11329
|
-
keys: entry.keys
|
|
11330
|
-
}
|
|
11331
|
-
});
|
|
11332
|
-
for (const r of result.refused) this.log.warn("auto tune: per-camera detector thresholds not cleared", {
|
|
11333
|
-
tags: { deviceId: r.deviceId },
|
|
11334
|
-
meta: {
|
|
11335
|
-
deviceId: r.deviceId,
|
|
11336
|
-
reason: r.reason,
|
|
11337
|
-
dryRun: input.dryRun
|
|
11338
|
-
}
|
|
11339
|
-
});
|
|
11340
|
-
return result;
|
|
11341
|
-
}
|
|
11342
|
-
/**
|
|
11343
|
-
* Clear the per-device pipeline-step overrides for every known device.
|
|
11344
|
-
* Returns the count of devices whose store was cleared. There is no
|
|
11345
|
-
* bulk-list primitive over the per-device store, so devices are
|
|
11346
|
-
* enumerated via the device-manager and cleared one by one
|
|
11347
|
-
* (`clearDeviceStore` is idempotent — a device with no overrides is a
|
|
11348
|
-
* no-op). Never throws: a device-manager outage degrades to "cleared
|
|
11349
|
-
* nothing" so the reset flow still completes.
|
|
11350
|
-
*/
|
|
11351
|
-
async clearAllDeviceOverrides() {
|
|
11352
|
-
const api = this.addonCtx?.api;
|
|
11353
|
-
if (!api) return 0;
|
|
11354
|
-
let devices = [];
|
|
11355
|
-
try {
|
|
11356
|
-
devices = await api.deviceManager.listAll.query({ projection: "slim" });
|
|
11357
|
-
} catch (err) {
|
|
11358
|
-
this.log.warn("clearDeviceOverrides: device enumeration failed — skipping per-device clear", { meta: { error: errMsg$1(err) } });
|
|
11359
|
-
return 0;
|
|
11360
|
-
}
|
|
11361
|
-
let cleared = 0;
|
|
11362
|
-
for (const device of devices) try {
|
|
11363
|
-
await this.clearDeviceStore(device.id);
|
|
11364
|
-
this.deviceOverrides.invalidate(device.id);
|
|
11365
|
-
cleared++;
|
|
11366
|
-
} catch (err) {
|
|
11367
|
-
this.log.warn("clearDeviceOverrides: failed to clear per-device overrides for device", {
|
|
11368
|
-
tags: { deviceId: device.id },
|
|
11369
|
-
meta: {
|
|
11370
|
-
deviceId: device.id,
|
|
11371
|
-
error: errMsg$1(err)
|
|
11372
|
-
}
|
|
11373
|
-
});
|
|
11374
|
-
}
|
|
11375
|
-
return cleared;
|
|
11376
|
-
}
|
|
11377
11070
|
async listLoadedEngines() {
|
|
11378
11071
|
const out = [];
|
|
11379
11072
|
if (this.engineFactory) {
|
|
@@ -11560,7 +11253,7 @@ var DetectionPipelineProvider = class DetectionPipelineProvider {
|
|
|
11560
11253
|
frame
|
|
11561
11254
|
};
|
|
11562
11255
|
} catch (err) {
|
|
11563
|
-
const msg = errMsg
|
|
11256
|
+
const msg = errMsg(err);
|
|
11564
11257
|
this.log.error("failed", { meta: {
|
|
11565
11258
|
phase: "audio-test",
|
|
11566
11259
|
error: msg
|
|
@@ -11620,7 +11313,6 @@ function buildSchemaSlots(formats, modelsDir, customByStep) {
|
|
|
11620
11313
|
defaultModelId: step.defaultModelId,
|
|
11621
11314
|
...step.defaultModelIdByFormat ? { defaultModelIdByFormat: { ...step.defaultModelIdByFormat } } : {},
|
|
11622
11315
|
...step.enabledByDefault !== void 0 ? { enabledByDefault: step.enabledByDefault } : {},
|
|
11623
|
-
...step.backfillIntoExistingOverrides !== void 0 ? { backfillIntoExistingOverrides: step.backfillIntoExistingOverrides } : {},
|
|
11624
11316
|
defaultConfidence: step.defaultConfidence,
|
|
11625
11317
|
...step.group ? { group: step.group } : {},
|
|
11626
11318
|
...configSchemaWithRoots.length > 0 ? { configSchema: configSchemaWithRoots } : {}
|
|
@@ -11668,7 +11360,7 @@ function resolveChildSlots(slot) {
|
|
|
11668
11360
|
}
|
|
11669
11361
|
/**
|
|
11670
11362
|
* V2 default: the node-default step tree (never persisted — see
|
|
11671
|
-
* `
|
|
11363
|
+
* `nodeDefaultSteps`). The core detection + recognition steps are enabled; every
|
|
11672
11364
|
* optional step is present with its catalog `enabledByDefault` (the animal and
|
|
11673
11365
|
* vehicle classifiers on — their answer comes from the root model when it
|
|
11674
11366
|
* declares them, D736 — the bird classifier and segmentation off).
|
|
@@ -11710,27 +11402,6 @@ function buildDefaultStepTree(format, objectDetectionModelId) {
|
|
|
11710
11402
|
if (audioStep) steps.push(audioStep);
|
|
11711
11403
|
return steps;
|
|
11712
11404
|
}
|
|
11713
|
-
function stepsToPipelineConfig(steps, engine) {
|
|
11714
|
-
const toNode = (step) => ({
|
|
11715
|
-
step: step.addonId,
|
|
11716
|
-
addon: step.addonId,
|
|
11717
|
-
configOverride: {
|
|
11718
|
-
modelId: step.modelId,
|
|
11719
|
-
...step.settings
|
|
11720
|
-
},
|
|
11721
|
-
children: step.children.map(toNode)
|
|
11722
|
-
});
|
|
11723
|
-
const videoSteps = steps.filter((s) => s.slot !== "audio-classifier");
|
|
11724
|
-
const audioStep = steps.find((s) => s.slot === "audio-classifier" && s.enabled);
|
|
11725
|
-
return {
|
|
11726
|
-
engine,
|
|
11727
|
-
video: videoSteps.map(toNode),
|
|
11728
|
-
...audioStep ? {
|
|
11729
|
-
audio: toNode(audioStep),
|
|
11730
|
-
audioEngine: engine
|
|
11731
|
-
} : {}
|
|
11732
|
-
};
|
|
11733
|
-
}
|
|
11734
11405
|
/** Flatten a step tree into a flat list (DFS) — delegates to shared utility. */
|
|
11735
11406
|
function flattenSteps(steps) {
|
|
11736
11407
|
return flattenEnabledVideoSteps(steps);
|
|
@@ -11791,22 +11462,6 @@ function availableFormatsForStep(addonId) {
|
|
|
11791
11462
|
return [];
|
|
11792
11463
|
}
|
|
11793
11464
|
}
|
|
11794
|
-
/**
|
|
11795
|
-
* Return a shallow-cloned executable tree with `rootStepId`'s `settings`
|
|
11796
|
-
* merged with `overrides` (per-device values win). Non-matching root steps
|
|
11797
|
-
* pass through unchanged. Used by `runFrame` to apply per-device detection
|
|
11798
|
-
* settings without rebuilding the tree per frame. A model-bound value (D738)
|
|
11799
|
-
* applies only while the model it was made for is the one the root RUNS.
|
|
11800
|
-
*/
|
|
11801
|
-
function applyDeviceOverridesToTree(tree, rootStepId, overrides) {
|
|
11802
|
-
return { roots: tree.roots.map((root) => root.stepId === rootStepId ? {
|
|
11803
|
-
...root,
|
|
11804
|
-
settings: {
|
|
11805
|
-
...root.settings,
|
|
11806
|
-
...resolveOperatorSettingsForModel(rootStepId, overrides, root.modelId)
|
|
11807
|
-
}
|
|
11808
|
-
} : root) };
|
|
11809
|
-
}
|
|
11810
11465
|
//#endregion
|
|
11811
11466
|
//#region src/detection-pipeline/python-readiness.ts
|
|
11812
11467
|
/**
|
|
@@ -11921,20 +11576,6 @@ function isProfileSliderKey(key) {
|
|
|
11921
11576
|
}
|
|
11922
11577
|
var DetectionPipelineAddon = class extends BaseAddon {
|
|
11923
11578
|
provider = null;
|
|
11924
|
-
/**
|
|
11925
|
-
* An operator's own write drops the mirror the frame path reads.
|
|
11926
|
-
*
|
|
11927
|
-
* This override is the half of `device-override-mirror.ts` that keeps it from
|
|
11928
|
-
* being the second authority D224 forbids: `BaseAddon.updateDeviceSettings`
|
|
11929
|
-
* writes THIS addon's `<addonId>:addon-devices` row, so the write and the
|
|
11930
|
-
* mirror are in one process and the write invalidates. Without it the
|
|
11931
|
-
* operator's own change would be the one read the mirror got wrong, which is
|
|
11932
|
-
* the exact failure D224 records.
|
|
11933
|
-
*/
|
|
11934
|
-
async updateDeviceSettings(deviceId, patch) {
|
|
11935
|
-
await super.updateDeviceSettings(deviceId, patch);
|
|
11936
|
-
this.provider?.deviceOverrides.invalidate(deviceId);
|
|
11937
|
-
}
|
|
11938
11579
|
/** Last non-null probed hardware PER NODE — reused when the probe transiently
|
|
11939
11580
|
* returns null so offered backends / device lists don't collapse. Keyed by
|
|
11940
11581
|
* node because the hub addon probes other nodes when serving their config.
|