@camstack/addon-pipeline 1.2.43 → 1.2.45
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 +1 -1
- package/dist/audio-analyzer/index.mjs +1 -1
- package/dist/detection-pipeline/index.js +158 -81
- package/dist/detection-pipeline/index.mjs +158 -81
- package/dist/{dist-B-VVBzrL.mjs → dist-BDkEhx4Z.mjs} +1315 -127
- package/dist/{dist-UHbKZiSa.js → dist-QyZ7QSRP.js} +1386 -126
- package/dist/{event-loop-stall-monitor-C7_L6vHO.js → event-loop-stall-monitor-COEKVBQK.js} +53 -8
- package/dist/{event-loop-stall-monitor-DfKdC7G4.mjs → event-loop-stall-monitor-IAuNEdmG.mjs} +53 -8
- package/dist/motion-wasm/index.js +1 -1
- package/dist/motion-wasm/index.mjs +1 -1
- package/dist/pipeline-runner/index.js +342 -69
- package/dist/pipeline-runner/index.mjs +342 -69
- package/dist/recorder/index.js +189 -6
- package/dist/recorder/index.mjs +189 -6
- package/dist/session-decode/decode-worker-child.js +197 -24
- package/dist/session-decode/decode-worker-child.mjs +197 -24
- package/dist/stream-broker/_stub.js +2 -2
- package/dist/stream-broker/{_virtual_mf-localSharedImportMap___mfe_internal__addon_stream_broker_widgets-D7iQbuKY.mjs → _virtual_mf-localSharedImportMap___mfe_internal__addon_stream_broker_widgets-C68YfSUH.mjs} +2 -2
- package/dist/stream-broker/_virtual_mf___mfe_internal__addon_stream_broker_widgets__loadShare___mf_0_camstack_mf_1_types__loadShare__.js-CT2bGWqM.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-54IklEep.mjs → _virtual_mf___mfe_internal__addon_stream_broker_widgets__loadShare___mf_0_camstack_mf_1_ui_mf_2_library__loadShare__.js-B3GxBnXM.mjs} +1 -1
- package/dist/stream-broker/{hostInit-CKYS9yZO.mjs → hostInit-BMCrULpc.mjs} +2 -2
- package/dist/stream-broker/index.js +4602 -1442
- package/dist/stream-broker/index.mjs +4601 -1442
- package/dist/stream-broker/remoteEntry.js +1 -1
- package/dist/worker-protocol-DFH_z2-q.mjs +244 -0
- package/dist/worker-protocol-le27Mw_8.js +279 -0
- package/embed-dist/assets/{MaskShapeCanvas-DI4BY7W2-DxZ75vB8.js → MaskShapeCanvas-DI4BY7W2-C7bsz4cP.js} +1 -1
- package/embed-dist/assets/{MotionZonesSettings-NcxxQN8r-BBY2Ztz5.js → MotionZonesSettings-NcxxQN8r-BmhLinUd.js} +1 -1
- package/embed-dist/assets/{PrivacyMaskSettings-APgPLF7p-BC-3QmHa.js → PrivacyMaskSettings-APgPLF7p-BJjyGWFy.js} +1 -1
- package/embed-dist/assets/index-DC63og2c.css +2 -0
- package/embed-dist/assets/{index-on1wyOnd.js → index-a4CMt-Uc.js} +12 -12
- package/embed-dist/index.html +2 -2
- package/package.json +1 -1
- package/python/postprocessors/__init__.py +2 -0
- package/python/postprocessors/rfdetr.py +161 -0
- package/python/postprocessors/test_rfdetr.py +193 -0
- package/dist/stream-broker/_virtual_mf___mfe_internal__addon_stream_broker_widgets__loadShare___mf_0_camstack_mf_1_types__loadShare__.js-CCC9fqHH.mjs +0 -26
- package/dist/worker-protocol-D7RzZIla.mjs +0 -77
- package/dist/worker-protocol-DextwlTX.js +0 -94
- package/embed-dist/assets/index-CGdwTcwE.css +0 -2
|
@@ -3,7 +3,7 @@ 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-
|
|
6
|
+
const require_dist = require("../dist-QyZ7QSRP.js");
|
|
7
7
|
const require_node_topology_platform = require("../node-topology-platform-CFZ7F4xW.js");
|
|
8
8
|
const require_model_download_service_D8B_4ktF = require("../model-download-service-D8B-4ktF-7-YxE9Wx.js");
|
|
9
9
|
let node_fs = require("node:fs");
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { n as __require } from "../chunk-DnnnRqeS.mjs";
|
|
2
|
-
import {
|
|
2
|
+
import { $ as errMsg, C as audioAnalysisCapability, R as mapAudioLabelToMacro, at as BaseAddon, n as AUDIO_BACKEND_CHOICES, o as DEFAULT_AUDIO_ANALYZER_CONFIG, p as HF_BASE_URL, ut as hydrateSchema, w as audioAnalyzerCapability } from "../dist-BDkEhx4Z.mjs";
|
|
3
3
|
import { t as pickNodePlatformArch } from "../node-topology-platform-BkR_k6WT.mjs";
|
|
4
4
|
import { i as downloadFile } from "../model-download-service-D8B-4ktF-BB7oZL3y.mjs";
|
|
5
5
|
import * as fs from "node:fs";
|
|
@@ -3,8 +3,8 @@ 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_event_loop_stall_monitor = require("../event-loop-stall-monitor-
|
|
6
|
+
const require_dist = require("../dist-QyZ7QSRP.js");
|
|
7
|
+
const require_event_loop_stall_monitor = require("../event-loop-stall-monitor-COEKVBQK.js");
|
|
8
8
|
const require_lazy_sharp = require("../lazy-sharp-CcYuXtsa.js");
|
|
9
9
|
const require_node_topology_platform = require("../node-topology-platform-CFZ7F4xW.js");
|
|
10
10
|
const require_model_download_service_D8B_4ktF = require("../model-download-service-D8B-4ktF-7-YxE9Wx.js");
|
|
@@ -254,7 +254,7 @@ function normalizeEngineNodeId(rawNodeId) {
|
|
|
254
254
|
//#endregion
|
|
255
255
|
//#region src/detection-pipeline/default-detection-model.ts
|
|
256
256
|
/** The object-detection step id — the only slot this resolver applies to. */
|
|
257
|
-
var OBJECT_DETECTION_STEP_ID
|
|
257
|
+
var OBJECT_DETECTION_STEP_ID = "object-detection";
|
|
258
258
|
/**
|
|
259
259
|
* Balanced default object-detection model per accelerator class. `'cpu'` maps to
|
|
260
260
|
* `null` → the caller substitutes the step's own `defaultModelId` (`yolo26n`).
|
|
@@ -316,7 +316,7 @@ function classifyAccelerator(backend, device) {
|
|
|
316
316
|
function resolveDefaultDetectionModel(backend, device, format, getStepDef = require_event_loop_stall_monitor.getStepDefinition) {
|
|
317
317
|
let def;
|
|
318
318
|
try {
|
|
319
|
-
def = getStepDef(OBJECT_DETECTION_STEP_ID
|
|
319
|
+
def = getStepDef(OBJECT_DETECTION_STEP_ID);
|
|
320
320
|
} catch {
|
|
321
321
|
return "yolo26n";
|
|
322
322
|
}
|
|
@@ -442,7 +442,7 @@ var PoolHandle = class {
|
|
|
442
442
|
}
|
|
443
443
|
async infer(input) {
|
|
444
444
|
const start = performance.now();
|
|
445
|
-
return poolResultToEngineOutput(input.kind === "raw" ? await this.pool.inferRaw(this.modelIndex, input.data, input.width, input.height, input.format) : await this.pool.infer(this.modelIndex, input.data), performance.now() - start);
|
|
445
|
+
return poolResultToEngineOutput(input.kind === "raw" ? await this.pool.inferRaw(this.modelIndex, input.data, input.width, input.height, input.format, input.deviceId) : await this.pool.infer(this.modelIndex, input.data, input.deviceId), performance.now() - start);
|
|
446
446
|
}
|
|
447
447
|
/**
|
|
448
448
|
* Inference on a frame previously cached in the Python pool via
|
|
@@ -646,12 +646,12 @@ var PoolWorker = class {
|
|
|
646
646
|
});
|
|
647
647
|
});
|
|
648
648
|
}
|
|
649
|
-
async infer(modelByte, jpeg) {
|
|
649
|
+
async infer(modelByte, jpeg, deviceId) {
|
|
650
650
|
this.ensureReady();
|
|
651
651
|
const payload = Buffer.concat([Buffer.from([modelByte]), jpeg]);
|
|
652
|
-
return this.dispatch(MSG_INFER_JPEG, payload);
|
|
652
|
+
return this.dispatch(MSG_INFER_JPEG, payload, deviceId);
|
|
653
653
|
}
|
|
654
|
-
async inferRaw(modelByte, raw, width, height, format) {
|
|
654
|
+
async inferRaw(modelByte, raw, width, height, format, deviceId) {
|
|
655
655
|
this.ensureReady();
|
|
656
656
|
const fmtCode = RAW_FMT_CODE[format];
|
|
657
657
|
const rawHeader = Buffer.allocUnsafe(10);
|
|
@@ -659,7 +659,7 @@ var PoolWorker = class {
|
|
|
659
659
|
rawHeader.writeUInt32LE(width, 1);
|
|
660
660
|
rawHeader.writeUInt32LE(height, 5);
|
|
661
661
|
rawHeader[9] = fmtCode;
|
|
662
|
-
return this.dispatchMulti(MSG_INFER_RAW, rawHeader.length + raw.length, [rawHeader, raw]);
|
|
662
|
+
return this.dispatchMulti(MSG_INFER_RAW, rawHeader.length + raw.length, [rawHeader, raw], deviceId);
|
|
663
663
|
}
|
|
664
664
|
async inferBatch(modelByte, items, frameId = 0) {
|
|
665
665
|
this.ensureReady();
|
|
@@ -697,12 +697,12 @@ var PoolWorker = class {
|
|
|
697
697
|
const result = await this.dispatchMulti(MSG_CACHE_FRAME, payloadLen, [header, raw]);
|
|
698
698
|
if (result["error"]) throw new Error(String(result["error"]));
|
|
699
699
|
}
|
|
700
|
-
async inferCached(modelByte, frameId) {
|
|
700
|
+
async inferCached(modelByte, frameId, deviceId) {
|
|
701
701
|
this.ensureReady();
|
|
702
702
|
const payload = Buffer.allocUnsafe(5);
|
|
703
703
|
payload[0] = modelByte;
|
|
704
704
|
payload.writeUInt32LE(frameId, 1);
|
|
705
|
-
return this.dispatch(MSG_INFER_CACHED, payload);
|
|
705
|
+
return this.dispatch(MSG_INFER_CACHED, payload, deviceId);
|
|
706
706
|
}
|
|
707
707
|
async sendCommand(cmd) {
|
|
708
708
|
this.ensureReady();
|
|
@@ -726,7 +726,7 @@ var PoolWorker = class {
|
|
|
726
726
|
* raise — but logging none is how a camera went dark for 52 minutes looking
|
|
727
727
|
* like a quiet afternoon.
|
|
728
728
|
*/
|
|
729
|
-
shedIfSaturated(msgType) {
|
|
729
|
+
shedIfSaturated(msgType, deviceId) {
|
|
730
730
|
if (!SHEDDABLE_MSG_TYPES.has(msgType)) return null;
|
|
731
731
|
if (this.pending.size < POOL_MAX_IN_FLIGHT) {
|
|
732
732
|
this.shedding = false;
|
|
@@ -734,15 +734,18 @@ var PoolWorker = class {
|
|
|
734
734
|
}
|
|
735
735
|
if (!this.shedding) {
|
|
736
736
|
this.shedding = true;
|
|
737
|
-
this.log.warn("worker saturated — shedding inference until it catches up", {
|
|
738
|
-
|
|
739
|
-
|
|
740
|
-
|
|
741
|
-
|
|
742
|
-
|
|
743
|
-
|
|
744
|
-
|
|
745
|
-
|
|
737
|
+
this.log.warn("worker saturated — shedding inference until it catches up", {
|
|
738
|
+
...deviceId !== void 0 ? { tags: { deviceId } } : {},
|
|
739
|
+
meta: {
|
|
740
|
+
worker: this.opts.workerLabel,
|
|
741
|
+
pid: this.getPid(),
|
|
742
|
+
runtime: this.opts.poolRuntime,
|
|
743
|
+
device: this.opts.device ?? "default",
|
|
744
|
+
inFlight: this.pending.size,
|
|
745
|
+
cap: POOL_MAX_IN_FLIGHT,
|
|
746
|
+
deadlineMs: POOL_LIVE_INFER_TIMEOUT_MS
|
|
747
|
+
}
|
|
748
|
+
});
|
|
746
749
|
}
|
|
747
750
|
this.shedCount++;
|
|
748
751
|
return {
|
|
@@ -755,12 +758,12 @@ var PoolWorker = class {
|
|
|
755
758
|
deadlineFor(msgType) {
|
|
756
759
|
return SHEDDABLE_MSG_TYPES.has(msgType) ? POOL_LIVE_INFER_TIMEOUT_MS : POOL_INFER_TIMEOUT_MS;
|
|
757
760
|
}
|
|
758
|
-
dispatch(msgType, payload) {
|
|
759
|
-
const shed = this.shedIfSaturated(msgType);
|
|
761
|
+
dispatch(msgType, payload, deviceId) {
|
|
762
|
+
const shed = this.shedIfSaturated(msgType, deviceId);
|
|
760
763
|
if (shed) return Promise.resolve(shed);
|
|
761
764
|
const reqId = this.allocRequestId();
|
|
762
765
|
return new Promise((resolve, reject) => {
|
|
763
|
-
const timer = this.armRequestTimeout(reqId, reject, this.deadlineFor(msgType));
|
|
766
|
+
const timer = this.armRequestTimeout(reqId, reject, this.deadlineFor(msgType), deviceId);
|
|
764
767
|
this.pending.set(reqId, {
|
|
765
768
|
resolve,
|
|
766
769
|
reject,
|
|
@@ -780,30 +783,33 @@ var PoolWorker = class {
|
|
|
780
783
|
* `POOL_INFER_TIMEOUT_MS`. `unref` so it never keeps the event loop alive.
|
|
781
784
|
* The normal response + `rejectAll` paths clear it via `PendingRequest.timer`.
|
|
782
785
|
*/
|
|
783
|
-
armRequestTimeout(reqId, reject, timeoutMs) {
|
|
786
|
+
armRequestTimeout(reqId, reject, timeoutMs, deviceId) {
|
|
784
787
|
const timer = setTimeout(() => {
|
|
785
788
|
if (this.pending.delete(reqId)) {
|
|
786
|
-
this.log.error("inference request timed out", {
|
|
787
|
-
|
|
788
|
-
|
|
789
|
-
|
|
790
|
-
|
|
791
|
-
|
|
792
|
-
|
|
793
|
-
|
|
794
|
-
|
|
789
|
+
this.log.error("inference request timed out", {
|
|
790
|
+
...deviceId !== void 0 ? { tags: { deviceId } } : {},
|
|
791
|
+
meta: {
|
|
792
|
+
worker: this.opts.workerLabel,
|
|
793
|
+
pid: this.getPid(),
|
|
794
|
+
runtime: this.opts.poolRuntime,
|
|
795
|
+
device: this.opts.device ?? "default",
|
|
796
|
+
inFlight: this.pending.size,
|
|
797
|
+
reqId,
|
|
798
|
+
timeoutMs
|
|
799
|
+
}
|
|
800
|
+
});
|
|
795
801
|
reject(/* @__PURE__ */ new Error(`PoolWorker[${this.opts.workerLabel}]: inference request ${reqId} timed out after ${timeoutMs}ms (worker alive, no reply)`));
|
|
796
802
|
}
|
|
797
803
|
}, timeoutMs);
|
|
798
804
|
timer.unref?.();
|
|
799
805
|
return timer;
|
|
800
806
|
}
|
|
801
|
-
dispatchMulti(msgType, payloadLen, parts) {
|
|
802
|
-
const shed = this.shedIfSaturated(msgType);
|
|
807
|
+
dispatchMulti(msgType, payloadLen, parts, deviceId) {
|
|
808
|
+
const shed = this.shedIfSaturated(msgType, deviceId);
|
|
803
809
|
if (shed) return Promise.resolve(shed);
|
|
804
810
|
const reqId = this.allocRequestId();
|
|
805
811
|
return new Promise((resolve, reject) => {
|
|
806
|
-
const timer = this.armRequestTimeout(reqId, reject, this.deadlineFor(msgType));
|
|
812
|
+
const timer = this.armRequestTimeout(reqId, reject, this.deadlineFor(msgType), deviceId);
|
|
807
813
|
this.pending.set(reqId, {
|
|
808
814
|
resolve,
|
|
809
815
|
reject,
|
|
@@ -999,21 +1005,21 @@ var SharedInferencePool = class {
|
|
|
999
1005
|
workers: this.numWorkers
|
|
1000
1006
|
};
|
|
1001
1007
|
}
|
|
1002
|
-
async infer(modelIndex, jpeg) {
|
|
1008
|
+
async infer(modelIndex, jpeg, deviceId) {
|
|
1003
1009
|
const w = this.pickWorker();
|
|
1004
|
-
return this.trackDroppedResponse(await w.infer(this.encodeModelByte(modelIndex), jpeg), modelIndex);
|
|
1010
|
+
return this.trackDroppedResponse(await w.infer(this.encodeModelByte(modelIndex), jpeg, deviceId), modelIndex);
|
|
1005
1011
|
}
|
|
1006
|
-
async inferRaw(modelIndex, raw, width, height, format) {
|
|
1012
|
+
async inferRaw(modelIndex, raw, width, height, format, deviceId) {
|
|
1007
1013
|
const w = this.pickWorker();
|
|
1008
|
-
return this.trackDroppedResponse(await w.inferRaw(this.encodeModelByte(modelIndex), raw, width, height, format), modelIndex);
|
|
1014
|
+
return this.trackDroppedResponse(await w.inferRaw(this.encodeModelByte(modelIndex), raw, width, height, format, deviceId), modelIndex);
|
|
1009
1015
|
}
|
|
1010
1016
|
async inferBatch(modelIndex, items, frameId = 0) {
|
|
1011
1017
|
if (items.length > 255) throw new Error(`SharedInferencePool.inferBatch: max 255 items per call, got ${items.length}`);
|
|
1012
1018
|
return this.pickWorker().inferBatch(this.encodeModelByte(modelIndex), items, frameId);
|
|
1013
1019
|
}
|
|
1014
|
-
async inferCached(modelIndex, frameId) {
|
|
1020
|
+
async inferCached(modelIndex, frameId, deviceId) {
|
|
1015
1021
|
const w = this.pickWorker();
|
|
1016
|
-
return this.trackDroppedResponse(await w.inferCached(this.encodeModelByte(modelIndex), frameId), modelIndex);
|
|
1022
|
+
return this.trackDroppedResponse(await w.inferCached(this.encodeModelByte(modelIndex), frameId, deviceId), modelIndex);
|
|
1017
1023
|
}
|
|
1018
1024
|
/**
|
|
1019
1025
|
* Total `"dropped": true` responses seen from the Python pool — frames
|
|
@@ -1639,12 +1645,24 @@ var RUNTIME_TO_FORMAT = {
|
|
|
1639
1645
|
onnxruntime: "onnx",
|
|
1640
1646
|
edgetpu: "tflite"
|
|
1641
1647
|
};
|
|
1642
|
-
/** The step whose detections are re-filtered downstream by the executor's
|
|
1643
|
-
* per-macro `minConfidence*` sliders (`macroFilterVerdict`). Its pool-side
|
|
1644
|
-
* floor must stay BELOW those sliders or it silently pre-empts them. */
|
|
1645
|
-
var OBJECT_DETECTION_STEP_ID = "object-detection";
|
|
1646
1648
|
/**
|
|
1647
|
-
*
|
|
1649
|
+
* Steps whose detections are re-filtered downstream by the executor's per-macro
|
|
1650
|
+
* `minConfidence*` sliders (`macroFilterVerdict` runs on EVERY root, keyed by
|
|
1651
|
+
* the detection's macro class). Their pool-side floor must stay BELOW those
|
|
1652
|
+
* sliders or it silently pre-empts them.
|
|
1653
|
+
*
|
|
1654
|
+
* `package-detection` joined on 2026-08-07, when it gained a
|
|
1655
|
+
* `minConfidencePackage` slider: while it kept `defaultConfidence` (0.5) as its
|
|
1656
|
+
* pool floor, every sub-0.5 position of that brand-new slider was dead on
|
|
1657
|
+
* arrival — the same foot-gun this constant was introduced to remove for
|
|
1658
|
+
* object-detection. A step with NO operator-facing threshold keeps its own
|
|
1659
|
+
* `def.defaultConfidence`; adding one without adding the id here ships a
|
|
1660
|
+
* control that lies below its default.
|
|
1661
|
+
*/
|
|
1662
|
+
var PER_MACRO_REFILTERED_STEP_IDS = new Set(["object-detection", "package-detection"]);
|
|
1663
|
+
/**
|
|
1664
|
+
* Pool-side confidence FLOOR for a step the executor re-filters (#4 foot-gun
|
|
1665
|
+
* fix).
|
|
1648
1666
|
*
|
|
1649
1667
|
* The pool used to receive `def.defaultConfidence` (0.5) as its floor and drop
|
|
1650
1668
|
* every box < 0.5 BEFORE the executor's per-macro `minConfidence*` sliders run —
|
|
@@ -1652,17 +1670,17 @@ var OBJECT_DETECTION_STEP_ID = "object-detection";
|
|
|
1652
1670
|
* constant so the operator-visible per-macro sliders are the authoritative
|
|
1653
1671
|
* filter across their full 0–1 range. The per-macro slider DEFAULTS stay at 0.5
|
|
1654
1672
|
* (see `step-definitions.ts` getConfigSchema), so default UI behaviour is
|
|
1655
|
-
* unchanged; only sub-0.5 sliders start having an effect.
|
|
1656
|
-
|
|
1657
|
-
var OBJECT_DETECTION_POOL_CONFIDENCE_FLOOR = .05;
|
|
1673
|
+
* unchanged; only sub-0.5 sliders start having an effect. */
|
|
1674
|
+
var PER_MACRO_POOL_CONFIDENCE_FLOOR = .05;
|
|
1658
1675
|
/**
|
|
1659
|
-
* Resolve the pool-side confidence FLOOR for a step (#4).
|
|
1660
|
-
*
|
|
1661
|
-
* per-macro `minConfidence*`
|
|
1662
|
-
*
|
|
1676
|
+
* Resolve the pool-side confidence FLOOR for a step (#4). A step in
|
|
1677
|
+
* {@link PER_MACRO_REFILTERED_STEP_IDS} gets the small
|
|
1678
|
+
* {@link PER_MACRO_POOL_CONFIDENCE_FLOOR} so its per-macro `minConfidence*`
|
|
1679
|
+
* slider (applied downstream by the executor) is the authoritative filter;
|
|
1680
|
+
* every other step keeps its own `defaultConfidence`.
|
|
1663
1681
|
*/
|
|
1664
1682
|
function resolvePoolConfidenceFloor(stepId, defaultConfidence) {
|
|
1665
|
-
return stepId
|
|
1683
|
+
return PER_MACRO_REFILTERED_STEP_IDS.has(stepId) ? PER_MACRO_POOL_CONFIDENCE_FLOOR : defaultConfidence;
|
|
1666
1684
|
}
|
|
1667
1685
|
/**
|
|
1668
1686
|
* Load a model's runtime label list from its `-labels.json` extraFile, if any.
|
|
@@ -2196,6 +2214,7 @@ var VALID_KINDS = new Set([
|
|
|
2196
2214
|
var KNOWN_POSTPROCESSORS = new Set([
|
|
2197
2215
|
"yolo",
|
|
2198
2216
|
"ssd",
|
|
2217
|
+
"rfdetr",
|
|
2199
2218
|
"yolo-seg",
|
|
2200
2219
|
"scrfd",
|
|
2201
2220
|
"arcface",
|
|
@@ -3490,6 +3509,21 @@ function isEnrichmentOutput(output) {
|
|
|
3490
3509
|
return output.kind === "classifications" || output.kind === "embedding" || output.kind === "text";
|
|
3491
3510
|
}
|
|
3492
3511
|
/**
|
|
3512
|
+
* Stamp the camera onto an inference input so a failure inside the SHARED pool
|
|
3513
|
+
* can name it (`InferenceInput.deviceId` — diagnostic only, it selects
|
|
3514
|
+
* nothing). Immutable, and a no-op for a caller with no real camera: the
|
|
3515
|
+
* benchmark and the reference runs pass `deviceId: 0`, and a fabricated `0` in
|
|
3516
|
+
* a log tag is worse than no tag.
|
|
3517
|
+
*/
|
|
3518
|
+
function withInferenceDeviceId(input, deviceId) {
|
|
3519
|
+
if (!Number.isFinite(deviceId) || deviceId <= 0) return input;
|
|
3520
|
+
if (input.deviceId === deviceId) return input;
|
|
3521
|
+
return {
|
|
3522
|
+
...input,
|
|
3523
|
+
deviceId
|
|
3524
|
+
};
|
|
3525
|
+
}
|
|
3526
|
+
/**
|
|
3493
3527
|
* Re-project a `crop-zone` root's detections from crop-relative coordinates
|
|
3494
3528
|
* back to full-frame image space by the crop's origin — the root analogue of
|
|
3495
3529
|
* the crop-roi child re-projection (`transformBboxToImageSpace`). Landmarks (if
|
|
@@ -3593,7 +3627,7 @@ var PipelineExecutor = class {
|
|
|
3593
3627
|
if (debug) console.log(`[executor] rootStep=${rootStep.stepId} settings=${JSON.stringify(rootStep.settings ?? {})}`);
|
|
3594
3628
|
const cropPrep = rootStep.definition.extractMode === "crop-zone" && cropZoneBbox !== void 0 ? await this.prepareCropZoneInput(cropZoneBbox, fullFrameJpegProvider, imageWidth, imageHeight, deviceId) : null;
|
|
3595
3629
|
const rootStart = Date.now();
|
|
3596
|
-
const rawRootOutput = await this.executeStep(rootStep, cropPrep?.input ?? rootInput, cropPrep?.width ?? imageWidth, cropPrep?.height ?? imageHeight, "full-frame", void 0, void 0, traceBuilder, stepTimings, poolAgg, rootShed);
|
|
3630
|
+
const rawRootOutput = await this.executeStep(rootStep, cropPrep?.input ?? withInferenceDeviceId(rootInput, deviceId), cropPrep?.width ?? imageWidth, cropPrep?.height ?? imageHeight, "full-frame", void 0, void 0, traceBuilder, stepTimings, poolAgg, rootShed);
|
|
3597
3631
|
const rootMs = Date.now() - rootStart;
|
|
3598
3632
|
if (rawRootOutput === null) continue;
|
|
3599
3633
|
const rootOutput = cropPrep && rawRootOutput.kind === "detections" ? reprojectCropZoneDetections(rawRootOutput, cropPrep.origin) : rawRootOutput;
|
|
@@ -3784,10 +3818,10 @@ var PipelineExecutor = class {
|
|
|
3784
3818
|
const ox = Math.max(0, Math.round(cropZoneBbox[0]));
|
|
3785
3819
|
const oy = Math.max(0, Math.round(cropZoneBbox[1]));
|
|
3786
3820
|
return {
|
|
3787
|
-
input: {
|
|
3821
|
+
input: withInferenceDeviceId({
|
|
3788
3822
|
kind: "jpeg",
|
|
3789
3823
|
data: crop.jpeg
|
|
3790
|
-
},
|
|
3824
|
+
}, deviceId),
|
|
3791
3825
|
width: crop.width,
|
|
3792
3826
|
height: crop.height,
|
|
3793
3827
|
origin: [
|
|
@@ -4013,10 +4047,10 @@ var PipelineExecutor = class {
|
|
|
4013
4047
|
}
|
|
4014
4048
|
} catch {}
|
|
4015
4049
|
}
|
|
4016
|
-
const childOutput = await this.executeStep(child, {
|
|
4050
|
+
const childOutput = await this.executeStep(child, withInferenceDeviceId({
|
|
4017
4051
|
kind: "jpeg",
|
|
4018
4052
|
data: cropJpegBuf
|
|
4019
|
-
}, cropW, cropH, "crop-roi", parentDetection.bbox, parentDetection.macroClass, traceBuilder, stepTimings, poolAgg);
|
|
4053
|
+
}, deviceId), cropW, cropH, "crop-roi", parentDetection.bbox, parentDetection.macroClass, traceBuilder, stepTimings, poolAgg);
|
|
4020
4054
|
const childMs = Date.now() - childStart;
|
|
4021
4055
|
if (childOutput === null) continue;
|
|
4022
4056
|
const detailsBefore = ctx.details.length;
|
|
@@ -4659,8 +4693,6 @@ var DetectionPipelineProvider = class DetectionPipelineProvider {
|
|
|
4659
4693
|
*/
|
|
4660
4694
|
deviceProxies = /* @__PURE__ */ new Map();
|
|
4661
4695
|
proxyUnsubs = /* @__PURE__ */ new Map();
|
|
4662
|
-
/** Initialization lock — ensures only one init runs at a time; concurrent callers await the same promise */
|
|
4663
|
-
initPromise = null;
|
|
4664
4696
|
/**
|
|
4665
4697
|
* Last logged "step configured" signature — used to dedupe the
|
|
4666
4698
|
* per-step debug trail so it only fires on actual config CHANGE
|
|
@@ -6701,20 +6733,66 @@ var DetectionPipelineProvider = class DetectionPipelineProvider {
|
|
|
6701
6733
|
* If global steps exist, initializes with them. Otherwise, creates an empty pool.
|
|
6702
6734
|
*/
|
|
6703
6735
|
async ensureEngineFactory() {
|
|
6704
|
-
if (this.initPromise) await this.initPromise;
|
|
6705
6736
|
if (this.engineFactory) return;
|
|
6706
|
-
|
|
6707
|
-
|
|
6708
|
-
|
|
6709
|
-
|
|
6710
|
-
|
|
6711
|
-
|
|
6712
|
-
|
|
6713
|
-
|
|
6714
|
-
|
|
6715
|
-
|
|
6737
|
+
const inflight = this.engineFactoryInflight;
|
|
6738
|
+
if (inflight) {
|
|
6739
|
+
await inflight;
|
|
6740
|
+
return;
|
|
6741
|
+
}
|
|
6742
|
+
const creation = (async () => {
|
|
6743
|
+
await this.assertEngineReady();
|
|
6744
|
+
await this.ensureBackendDeps(this.currentEngine);
|
|
6745
|
+
const factory = new EngineFactory({
|
|
6746
|
+
engine: this.currentEngine,
|
|
6747
|
+
modelsDir: this.modelsDir,
|
|
6748
|
+
logger: this.log.child("engine"),
|
|
6749
|
+
pythonPath: this.executorOptions.pythonPath ?? "",
|
|
6750
|
+
provisioning: this.executorOptions.provisioning
|
|
6751
|
+
});
|
|
6752
|
+
try {
|
|
6753
|
+
await factory.initialize([]);
|
|
6754
|
+
} catch (err) {
|
|
6755
|
+
await factory.dispose().catch(() => void 0);
|
|
6756
|
+
this.log.error("Node-default pool failed to initialize", { meta: {
|
|
6757
|
+
deviceKey: deviceKeyOf(this.currentEngine),
|
|
6758
|
+
backend: this.currentEngine.backend,
|
|
6759
|
+
device: this.currentEngine.device ?? null,
|
|
6760
|
+
error: require_dist.errMsg(err)
|
|
6761
|
+
} });
|
|
6762
|
+
throw err;
|
|
6763
|
+
}
|
|
6764
|
+
this.engineFactory = factory;
|
|
6765
|
+
return factory;
|
|
6766
|
+
})();
|
|
6767
|
+
this.engineFactoryInflight = creation;
|
|
6768
|
+
try {
|
|
6769
|
+
await creation;
|
|
6770
|
+
} finally {
|
|
6771
|
+
this.engineFactoryInflight = null;
|
|
6772
|
+
}
|
|
6716
6773
|
}
|
|
6717
6774
|
/**
|
|
6775
|
+
* In-flight node-default pool creation. Single-flights
|
|
6776
|
+
* {@link ensureEngineFactory} exactly as `deviceFactoryInflight` does for the
|
|
6777
|
+
* per-device pools.
|
|
6778
|
+
*
|
|
6779
|
+
* Its absence was the chronic `PoolWorker[w0]: not initialized` storm
|
|
6780
|
+
* (1263 lines / 24 h, 2026-08-07): `this.engineFactory` was assigned BEFORE
|
|
6781
|
+
* `initialize()` was awaited, so every caller arriving during the 1-3.5 s
|
|
6782
|
+
* Python spawn took the early-exit and dispatched into a worker whose ready
|
|
6783
|
+
* handshake had not landed. The frames were logged as ERRORs and lost.
|
|
6784
|
+
*
|
|
6785
|
+
* The same bug was found and fixed twice before in this file — once for the
|
|
6786
|
+
* benchmark override cache (whose comment describes it verbatim) and once for
|
|
6787
|
+
* `resolveDeviceFactory` — which is why no `not initialized` line ever
|
|
6788
|
+
* carried a NON-default deviceKey. This is the third and last copy.
|
|
6789
|
+
*
|
|
6790
|
+
* It replaces a `private initPromise` field that was read here and assigned
|
|
6791
|
+
* NOWHERE: a dead lock that read, for as long as it existed, as if this path
|
|
6792
|
+
* were already guarded.
|
|
6793
|
+
*/
|
|
6794
|
+
engineFactoryInflight = null;
|
|
6795
|
+
/**
|
|
6718
6796
|
* Get (or lazily build) the inference-pool factory for an explicit device
|
|
6719
6797
|
* (`<backend>:<device>`, e.g. `openvino:npu`, `edgetpu:usb`) — Phase 2
|
|
6720
6798
|
* multi-device. Each device runs its OWN pool concurrently. Never mutates
|
|
@@ -7724,13 +7802,12 @@ var DetectionPipelineAddon = class extends require_dist.BaseAddon {
|
|
|
7724
7802
|
}
|
|
7725
7803
|
}
|
|
7726
7804
|
/**
|
|
7727
|
-
* Bare node id
|
|
7728
|
-
*
|
|
7729
|
-
*
|
|
7730
|
-
*
|
|
7731
|
-
*
|
|
7732
|
-
*
|
|
7733
|
-
* provider never read — silently losing the per-node selection.
|
|
7805
|
+
* Bare node id for this instance. MUST match the provider's
|
|
7806
|
+
* `localProbeNodeId()` (kernel.localNodeId, default 'hub') so the per-node
|
|
7807
|
+
* settings projection here and the provider's own node targeting agree. The
|
|
7808
|
+
* old `?? this.ctx.id` fallback resolved to the ADDON id
|
|
7809
|
+
* ('detection-pipeline') when kernel.localNodeId was absent, so UI saves
|
|
7810
|
+
* landed on a key the provider never read.
|
|
7734
7811
|
*/
|
|
7735
7812
|
localNodeId() {
|
|
7736
7813
|
return normalizeEngineNodeId(this.ctxIfReady?.kernel?.localNodeId ?? "hub");
|