@camstack/addon-pipeline 1.1.45 → 1.1.47
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 +78 -231
- package/dist/detection-pipeline/index.mjs +78 -231
- package/dist/{dist-D04numuO.mjs → dist-BXax-C-g.mjs} +316 -101
- package/dist/{dist-CjxqjgEv.js → dist-CSXbgmP-.js} +316 -101
- package/dist/motion-wasm/index.js +1 -1
- package/dist/motion-wasm/index.mjs +1 -1
- package/dist/pipeline-runner/index.js +24 -8
- package/dist/pipeline-runner/index.mjs +24 -8
- package/dist/recorder/index.js +1 -1
- package/dist/recorder/index.mjs +1 -1
- package/dist/{remote-source-plane-D31IILFN.mjs → remote-source-plane-D9mX0HiW.mjs} +1 -1
- package/dist/{remote-source-plane-CLuxyDV2.js → remote-source-plane-Rbl_xds1.js} +1 -1
- package/dist/stream-broker/_stub.js +2 -2
- package/dist/stream-broker/{_virtual_mf-localSharedImportMap___mfe_internal__addon_stream_broker_widgets-BGKueo9D.mjs → _virtual_mf-localSharedImportMap___mfe_internal__addon_stream_broker_widgets-Dz7jhO6c.mjs} +3 -3
- package/dist/stream-broker/_virtual_mf___mfe_internal__addon_stream_broker_widgets__loadShare___mf_0_camstack_mf_1_types__loadShare__.js-o4tu_xuc.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-8BUVCFIR.mjs → _virtual_mf___mfe_internal__addon_stream_broker_widgets__loadShare___mf_0_camstack_mf_1_ui_mf_2_library__loadShare__.js-CK4BmiTK.mjs} +1 -1
- package/dist/stream-broker/{hostInit-DazV2RCq.mjs → hostInit-DcMnvklS.mjs} +3 -3
- package/dist/stream-broker/index.js +79 -18
- package/dist/stream-broker/index.mjs +79 -18
- package/dist/stream-broker/remoteEntry.js +1 -1
- package/embed-dist/assets/{MaskShapeCanvas-DI4BY7W2-D_F4a_3H.js → MaskShapeCanvas-DI4BY7W2-BSSjCL6j.js} +1 -1
- package/embed-dist/assets/{MotionZonesSettings-NcxxQN8r-CfTBrn4G.js → MotionZonesSettings-NcxxQN8r-BDb2ziPs.js} +1 -1
- package/embed-dist/assets/{PrivacyMaskSettings-APgPLF7p-BWYkeoRj.js → PrivacyMaskSettings-APgPLF7p-ARYovxqE.js} +1 -1
- package/embed-dist/assets/{index-_ccEdNW7.js → index-ByiLuUQZ.js} +10 -10
- package/embed-dist/assets/{index-CA4kv43T.css → index-JqUY2p33.css} +1 -1
- package/embed-dist/index.html +2 -2
- package/package.json +1 -1
- package/dist/stream-broker/_virtual_mf___mfe_internal__addon_stream_broker_widgets__loadShare___mf_0_camstack_mf_1_types__loadShare__.js-D0sKyXiy.mjs +0 -26
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { t as __require } from "../chunk-BdkLduGY.mjs";
|
|
2
|
-
import { H as createEvent, I as errMsg, L as BaseAddon, O as pipelineExecutorCapability, P as supportedRuntimes$1, S as hfModelUrl, U as hydrateSchema, V as EventCategory, X as sleep, a as COCO_TO_MACRO, b as detectionPipelineCapability, f as YAMNET_TO_MACRO, i as COCO_80_LABELS, j as runtimeDevices$1, q as parseJsonUnknown, r as AUDIO_MACRO_LABELS, t as APPLE_SA_TO_MACRO, v as defaultDeviceFor$1, x as evaluateZoneRules } from "../dist-
|
|
2
|
+
import { H as createEvent, I as errMsg, L as BaseAddon, O as pipelineExecutorCapability, P as supportedRuntimes$1, S as hfModelUrl, U as hydrateSchema, V as EventCategory, X as sleep, a as COCO_TO_MACRO, b as detectionPipelineCapability, f as YAMNET_TO_MACRO, i as COCO_80_LABELS, j as runtimeDevices$1, q as parseJsonUnknown, r as AUDIO_MACRO_LABELS, t as APPLE_SA_TO_MACRO, v as defaultDeviceFor$1, x as evaluateZoneRules } from "../dist-BXax-C-g.mjs";
|
|
3
3
|
import { t as pickNodePlatformArch } from "../node-topology-platform-BkR_k6WT.mjs";
|
|
4
4
|
import { a as isModelDownloaded, i as ensureModel, n as deleteModelFromDisk } from "../model-download-service-C-IHWnXx-BPy6aoAx.mjs";
|
|
5
5
|
import { FrameRingReaderCache } from "@camstack/shm-ring";
|
|
@@ -4544,6 +4544,12 @@ function collectUnknownAddonIssues(steps, getStepDef = getStepDefinition) {
|
|
|
4544
4544
|
* `PipelineDefaultStep[]` (the catalog-enriched shape the executor consumes),
|
|
4545
4545
|
* resolving each step's model for `format` via `resolveModelForFormat`.
|
|
4546
4546
|
*
|
|
4547
|
+
* "Auto" model selection (ABSENT `modelId`) is hardware-aware for the
|
|
4548
|
+
* object-detection step when `engine` is provided: the default is resolved
|
|
4549
|
+
* via `resolveDefaultDetectionModel(engine.backend, engine.device, format)`.
|
|
4550
|
+
* A PINNED `modelId` is kept verbatim (subject to the usual format-build
|
|
4551
|
+
* substitution); every other step keeps its flat per-format default.
|
|
4552
|
+
*
|
|
4547
4553
|
* Pure and side-effect-free — never throws. This is the seam behind the
|
|
4548
4554
|
* LIVE per-camera dispatch path (`DetectionPipelineProvider.
|
|
4549
4555
|
* inputStepsToPipelineSteps`), which runs once per decoded frame (up to
|
|
@@ -4554,7 +4560,7 @@ function collectUnknownAddonIssues(steps, getStepDef = getStepDefinition) {
|
|
|
4554
4560
|
* `diagnostics.substitutions` instead of happening silently. The caller
|
|
4555
4561
|
* (the provider) owns logging + dedup for both.
|
|
4556
4562
|
*/
|
|
4557
|
-
function resolveInputSteps(steps, format) {
|
|
4563
|
+
function resolveInputSteps(steps, format, engine) {
|
|
4558
4564
|
const resolvedSteps = [];
|
|
4559
4565
|
const unknownAddonIds = [];
|
|
4560
4566
|
const substitutions = [];
|
|
@@ -4567,14 +4573,14 @@ function resolveInputSteps(steps, format) {
|
|
|
4567
4573
|
continue;
|
|
4568
4574
|
}
|
|
4569
4575
|
const chosenModelId = s.modelId ?? null;
|
|
4570
|
-
const runningModelId = resolveModelForFormat(s.addonId, chosenModelId, format);
|
|
4576
|
+
const runningModelId = chosenModelId === null && engine !== void 0 && s.addonId === "object-detection" ? resolveDefaultDetectionModel(engine.backend, engine.device, format) : resolveModelForFormat(s.addonId, chosenModelId, format);
|
|
4571
4577
|
if (chosenModelId !== null && runningModelId !== chosenModelId) substitutions.push({
|
|
4572
4578
|
addonId: s.addonId,
|
|
4573
4579
|
chosen: chosenModelId,
|
|
4574
4580
|
running: runningModelId,
|
|
4575
4581
|
format
|
|
4576
4582
|
});
|
|
4577
|
-
const childResult = s.children ? resolveInputSteps(s.children, format) : null;
|
|
4583
|
+
const childResult = s.children ? resolveInputSteps(s.children, format, engine) : null;
|
|
4578
4584
|
if (childResult) {
|
|
4579
4585
|
unknownAddonIds.push(...childResult.diagnostics.unknownAddonIds);
|
|
4580
4586
|
substitutions.push(...childResult.diagnostics.substitutions);
|
|
@@ -4607,8 +4613,6 @@ function resolveInputSteps(steps, format) {
|
|
|
4607
4613
|
* This is the main provider that consumers (DetectionWiring, Benchmark, tRPC)
|
|
4608
4614
|
* interact with. It manages the engine factory, pipeline executor, and config persistence.
|
|
4609
4615
|
*/
|
|
4610
|
-
var KEY_STEPS = "pipelineSteps";
|
|
4611
|
-
var KEY_ENGINE = "pipelineEngine";
|
|
4612
4616
|
var KEY_TEMPLATES = "pipelineTemplates";
|
|
4613
4617
|
function pythonModuleForBackend(backend) {
|
|
4614
4618
|
switch (backend) {
|
|
@@ -4691,14 +4695,6 @@ function readStored(raw, guard) {
|
|
|
4691
4695
|
return null;
|
|
4692
4696
|
}
|
|
4693
4697
|
}
|
|
4694
|
-
function isEngineChoice(v) {
|
|
4695
|
-
if (v === null || typeof v !== "object" || Array.isArray(v)) return false;
|
|
4696
|
-
const rec = { ...v };
|
|
4697
|
-
return typeof rec["runtime"] === "string" && typeof rec["backend"] === "string" && typeof rec["format"] === "string";
|
|
4698
|
-
}
|
|
4699
|
-
function isPipelineStepArray(v) {
|
|
4700
|
-
return Array.isArray(v);
|
|
4701
|
-
}
|
|
4702
4698
|
/**
|
|
4703
4699
|
* Phase 7 (settings redesign) template migration.
|
|
4704
4700
|
*
|
|
@@ -4915,13 +4911,6 @@ var DetectionPipelineProvider = class DetectionPipelineProvider {
|
|
|
4915
4911
|
*/
|
|
4916
4912
|
frameHandleReaders = null;
|
|
4917
4913
|
/**
|
|
4918
|
-
* True once the engine + models are fully ready for inference. No
|
|
4919
|
-
* longer gates runtime dispatch (Phase 4 removed the legacy `runFrame`
|
|
4920
|
-
* which read this flag); kept as a diagnostic the admin UI / tests
|
|
4921
|
-
* surface via the future `isReady()` helper.
|
|
4922
|
-
*/
|
|
4923
|
-
ready = false;
|
|
4924
|
-
/**
|
|
4925
4914
|
* Lazy detection-engine runtime provisioner (Phase 2). Owns the
|
|
4926
4915
|
* idle → installing → verifying → ready state machine for the
|
|
4927
4916
|
* currently-selected engine and is the SOLE authority the inference
|
|
@@ -4973,7 +4962,7 @@ var DetectionPipelineProvider = class DetectionPipelineProvider {
|
|
|
4973
4962
|
writeStore;
|
|
4974
4963
|
/** Read per-device settings. */
|
|
4975
4964
|
readDeviceStore;
|
|
4976
|
-
/** Delete all per-device settings for a device (used by `
|
|
4965
|
+
/** Delete all per-device settings for a device (used by `clearDeviceOverrides`). */
|
|
4977
4966
|
clearDeviceStore;
|
|
4978
4967
|
constructor(settings, modelsDir, logger, eventBus = null, detectionConfigSchemaSource = null, executorOptions = {}) {
|
|
4979
4968
|
this.modelsDir = modelsDir;
|
|
@@ -5048,9 +5037,9 @@ var DetectionPipelineProvider = class DetectionPipelineProvider {
|
|
|
5048
5037
|
}
|
|
5049
5038
|
await this.ensureEngineFactory();
|
|
5050
5039
|
}
|
|
5051
|
-
/** True when the engine
|
|
5040
|
+
/** True when the engine provisioning machine reports inference-ready. */
|
|
5052
5041
|
isReady() {
|
|
5053
|
-
return this.ready;
|
|
5042
|
+
return this.getEngineProvisioning().state === "ready";
|
|
5054
5043
|
}
|
|
5055
5044
|
/** Store the addon context. ctx.api is a lazy getter resolved at call time. */
|
|
5056
5045
|
async setApi(addonCtx) {
|
|
@@ -5496,46 +5485,25 @@ var DetectionPipelineProvider = class DetectionPipelineProvider {
|
|
|
5496
5485
|
getActiveModelSubstitutions() {
|
|
5497
5486
|
return [...this.modelSubstitutions.values()];
|
|
5498
5487
|
}
|
|
5488
|
+
/**
|
|
5489
|
+
* PURE node-default step tree — computed on demand, never persisted.
|
|
5490
|
+
*
|
|
5491
|
+
* The object-detection default is hardware-aware (this node's resolved
|
|
5492
|
+
* backend + device via `resolveDefaultDetectionModel`); every other step
|
|
5493
|
+
* keeps its flat per-format default. The result is cached in
|
|
5494
|
+
* `currentSteps` only as a memo — the cache is dropped whenever the
|
|
5495
|
+
* engine (hence model format) changes, so a re-read always reflects the
|
|
5496
|
+
* live engine. Nothing in the live per-camera dispatch path reads this:
|
|
5497
|
+
* it exists as the benchmark fallback (empty input steps), the Gate-A
|
|
5498
|
+
* config-issue probe, and the "effective post-reset model" probe.
|
|
5499
|
+
*/
|
|
5499
5500
|
async getGlobalSteps() {
|
|
5500
5501
|
if (this.currentSteps) return this.currentSteps;
|
|
5501
|
-
const
|
|
5502
|
-
|
|
5503
|
-
|
|
5504
|
-
|
|
5505
|
-
|
|
5506
|
-
this.currentSteps = this.resolveStepModels(defaults);
|
|
5507
|
-
this.writeStore({ [KEY_STEPS]: JSON.stringify(defaults) });
|
|
5508
|
-
this.log.info("Bootstrapped default pipeline — object-detection + face + plate recognition enabled by default", { meta: { rootSteps: defaults.length } });
|
|
5509
|
-
return this.currentSteps;
|
|
5510
|
-
}
|
|
5511
|
-
try {
|
|
5512
|
-
let steps = readStored(raw, isPipelineStepArray) ?? [];
|
|
5513
|
-
if (steps.length === 0) return null;
|
|
5514
|
-
if (!steps.some((s) => s.slot === "audio-classifier")) {
|
|
5515
|
-
const format = this.currentEngine.format;
|
|
5516
|
-
const audioDef = getStepDefinition("audio-classifier");
|
|
5517
|
-
if (audioDef.models.some((m) => m.formats[format])) {
|
|
5518
|
-
const modelId = getDefaultModelForFormat("audio-classifier", format);
|
|
5519
|
-
const audioStep = {
|
|
5520
|
-
addonId: audioDef.id,
|
|
5521
|
-
addonName: audioDef.name,
|
|
5522
|
-
slot: audioDef.slot,
|
|
5523
|
-
inputClasses: audioDef.inputClasses ?? [],
|
|
5524
|
-
outputClasses: audioDef.outputClasses,
|
|
5525
|
-
enabled: true,
|
|
5526
|
-
modelId,
|
|
5527
|
-
children: []
|
|
5528
|
-
};
|
|
5529
|
-
steps = [...steps, audioStep];
|
|
5530
|
-
this.writeStore({ [KEY_STEPS]: JSON.stringify(steps) });
|
|
5531
|
-
this.log.info("Migration: added audio-classifier step to persisted pipeline config");
|
|
5532
|
-
}
|
|
5533
|
-
}
|
|
5534
|
-
this.currentSteps = this.resolveStepModels(steps);
|
|
5535
|
-
return this.currentSteps;
|
|
5536
|
-
} catch {
|
|
5537
|
-
throw new Error(`Failed to parse persisted pipeline steps: corrupt data in key "${KEY_STEPS}"`);
|
|
5538
|
-
}
|
|
5502
|
+
const detectionModelId = resolveDefaultDetectionModel(this.currentEngine.backend, this.currentEngine.device ?? null, this.currentEngine.format);
|
|
5503
|
+
const defaults = buildDefaultStepTree(this.currentEngine.format, detectionModelId);
|
|
5504
|
+
if (defaults.length === 0) return null;
|
|
5505
|
+
this.currentSteps = this.resolveStepModels(defaults);
|
|
5506
|
+
return this.currentSteps;
|
|
5539
5507
|
}
|
|
5540
5508
|
async getGlobalPipelineConfig() {
|
|
5541
5509
|
if (!this.currentSteps) return null;
|
|
@@ -5990,7 +5958,14 @@ var DetectionPipelineProvider = class DetectionPipelineProvider {
|
|
|
5990
5958
|
}
|
|
5991
5959
|
decodeMs = performance.now() - decodeT0;
|
|
5992
5960
|
const resolveFormat = input.engine?.format ?? this.currentEngine.format;
|
|
5993
|
-
const
|
|
5961
|
+
const resolveEngine = input.engine ? {
|
|
5962
|
+
backend: input.engine.backend,
|
|
5963
|
+
device: input.engine.device ?? null
|
|
5964
|
+
} : {
|
|
5965
|
+
backend: this.currentEngine.backend,
|
|
5966
|
+
device: this.currentEngine.device ?? null
|
|
5967
|
+
};
|
|
5968
|
+
const benchmarkSteps = this.inputStepsToPipelineSteps(input.steps, resolveFormat, resolveEngine);
|
|
5994
5969
|
const stepsSignature = JSON.stringify(benchmarkSteps.map((s) => ({
|
|
5995
5970
|
id: s.addonId,
|
|
5996
5971
|
settings: s.settings ?? {}
|
|
@@ -6303,8 +6278,11 @@ var DetectionPipelineProvider = class DetectionPipelineProvider {
|
|
|
6303
6278
|
* would resolve models against the node's persisted format instead of the
|
|
6304
6279
|
* format actually being benchmarked.
|
|
6305
6280
|
*/
|
|
6306
|
-
inputStepsToPipelineSteps(steps, format = this.currentEngine.format
|
|
6307
|
-
|
|
6281
|
+
inputStepsToPipelineSteps(steps, format = this.currentEngine.format, engine = {
|
|
6282
|
+
backend: this.currentEngine.backend,
|
|
6283
|
+
device: this.currentEngine.device ?? null
|
|
6284
|
+
}) {
|
|
6285
|
+
const { steps: resolvedSteps, diagnostics } = resolveInputSteps(steps, format, engine);
|
|
6308
6286
|
for (const addonId of diagnostics.unknownAddonIds) this.logLiveDispatchIssueOnce(`unknown:${addonId}`, () => this.log.warn("Live pipeline step references an unknown addon — dropping step", { meta: { addonId } }));
|
|
6309
6287
|
for (const sub of diagnostics.substitutions) this.logLiveDispatchIssueOnce(`${sub.addonId}|${sub.chosen}|${sub.running}|${sub.format}`, () => this.log.info("Live pipeline step model substituted for engine format (node-local)", { meta: {
|
|
6310
6288
|
step: sub.addonId,
|
|
@@ -6422,67 +6400,6 @@ var DetectionPipelineProvider = class DetectionPipelineProvider {
|
|
|
6422
6400
|
height: 640
|
|
6423
6401
|
};
|
|
6424
6402
|
}
|
|
6425
|
-
async detect(input) {
|
|
6426
|
-
const { addonId, frame } = input;
|
|
6427
|
-
const { executor, tree } = await this.ensureExecutor();
|
|
6428
|
-
const data = Buffer.from(frame.data);
|
|
6429
|
-
let rootInput;
|
|
6430
|
-
let jpegProvider;
|
|
6431
|
-
if (frame.format === "jpeg") {
|
|
6432
|
-
rootInput = {
|
|
6433
|
-
kind: "jpeg",
|
|
6434
|
-
data
|
|
6435
|
-
};
|
|
6436
|
-
jpegProvider = async () => data;
|
|
6437
|
-
} else if (frame.format === "rgb" || frame.format === "bgr" || frame.format === "gray") {
|
|
6438
|
-
const channels = frame.format === "gray" ? 1 : 3;
|
|
6439
|
-
const sharp = (await import("sharp")).default;
|
|
6440
|
-
const jpeg = await sharp(data, { raw: {
|
|
6441
|
-
width: frame.width,
|
|
6442
|
-
height: frame.height,
|
|
6443
|
-
channels
|
|
6444
|
-
} }).jpeg({
|
|
6445
|
-
quality: 85,
|
|
6446
|
-
mozjpeg: false
|
|
6447
|
-
}).toBuffer();
|
|
6448
|
-
rootInput = {
|
|
6449
|
-
kind: "jpeg",
|
|
6450
|
-
data: jpeg
|
|
6451
|
-
};
|
|
6452
|
-
jpegProvider = async () => jpeg;
|
|
6453
|
-
} else {
|
|
6454
|
-
const sharp = (await import("sharp")).default;
|
|
6455
|
-
const encoded = await sharp(data, { raw: {
|
|
6456
|
-
width: frame.width,
|
|
6457
|
-
height: frame.height,
|
|
6458
|
-
channels: 3
|
|
6459
|
-
} }).jpeg({
|
|
6460
|
-
quality: 80,
|
|
6461
|
-
mozjpeg: false
|
|
6462
|
-
}).toBuffer();
|
|
6463
|
-
rootInput = {
|
|
6464
|
-
kind: "jpeg",
|
|
6465
|
-
data: encoded
|
|
6466
|
-
};
|
|
6467
|
-
jpegProvider = async () => encoded;
|
|
6468
|
-
}
|
|
6469
|
-
const { result } = await executor.run(tree, rootInput, jpegProvider, frame.width, frame.height, 0);
|
|
6470
|
-
return {
|
|
6471
|
-
detections: result.detections.filter((d) => d.kind === "first-level").map((d) => ({
|
|
6472
|
-
class: d.macroClass,
|
|
6473
|
-
originalClass: d.debug?.originalClass ?? d.macroClass,
|
|
6474
|
-
score: d.score,
|
|
6475
|
-
bbox: {
|
|
6476
|
-
x: d.bbox.x,
|
|
6477
|
-
y: d.bbox.y,
|
|
6478
|
-
w: d.bbox.width,
|
|
6479
|
-
h: d.bbox.height
|
|
6480
|
-
}
|
|
6481
|
-
})),
|
|
6482
|
-
inferenceMs: result.debug?.totalInferenceMs ?? 0,
|
|
6483
|
-
modelId: addonId
|
|
6484
|
-
};
|
|
6485
|
-
}
|
|
6486
6403
|
/**
|
|
6487
6404
|
* Batched run — dispatches N raw frames against the same loaded
|
|
6488
6405
|
* single-step model in one IPC round-trip via
|
|
@@ -6525,7 +6442,14 @@ var DetectionPipelineProvider = class DetectionPipelineProvider {
|
|
|
6525
6442
|
async runPipelineBatchImpl(input) {
|
|
6526
6443
|
if (input.frames.length === 0) return { results: [] };
|
|
6527
6444
|
const resolveFormat = input.engine?.format ?? this.currentEngine.format;
|
|
6528
|
-
const
|
|
6445
|
+
const resolveEngine = input.engine ? {
|
|
6446
|
+
backend: input.engine.backend,
|
|
6447
|
+
device: input.engine.device ?? null
|
|
6448
|
+
} : {
|
|
6449
|
+
backend: this.currentEngine.backend,
|
|
6450
|
+
device: this.currentEngine.device ?? null
|
|
6451
|
+
};
|
|
6452
|
+
const benchmarkSteps = this.inputStepsToPipelineSteps(input.steps, resolveFormat, resolveEngine);
|
|
6529
6453
|
const enabledSteps = flattenEnabledVideoSteps(benchmarkSteps);
|
|
6530
6454
|
if (enabledSteps.length === 0) throw new Error("runPipelineBatch: no enabled steps");
|
|
6531
6455
|
const rootStep = enabledSteps[0];
|
|
@@ -6817,71 +6741,11 @@ var DetectionPipelineProvider = class DetectionPipelineProvider {
|
|
|
6817
6741
|
});
|
|
6818
6742
|
await this.engineFactory.initialize([]);
|
|
6819
6743
|
}
|
|
6820
|
-
async ensureExecutor() {
|
|
6821
|
-
if (this.initPromise) await this.initPromise;
|
|
6822
|
-
if (!this.engineFactory) {
|
|
6823
|
-
await this.assertEngineReady();
|
|
6824
|
-
this.initPromise = this.doInitialize();
|
|
6825
|
-
try {
|
|
6826
|
-
await this.initPromise;
|
|
6827
|
-
} finally {
|
|
6828
|
-
this.initPromise = null;
|
|
6829
|
-
}
|
|
6830
|
-
}
|
|
6831
|
-
if (!this.currentSteps) throw new Error("No pipeline steps configured");
|
|
6832
|
-
const tree = buildExecutableTree(this.currentSteps, (stepId) => this.engineFactory.getEngine(stepId));
|
|
6833
|
-
return {
|
|
6834
|
-
executor: this.executor,
|
|
6835
|
-
tree
|
|
6836
|
-
};
|
|
6837
|
-
}
|
|
6838
|
-
/** Actual initialization — download models, create engine, load pool. Called once. */
|
|
6839
|
-
async doInitialize() {
|
|
6840
|
-
const steps = await this.getGlobalSteps();
|
|
6841
|
-
if (!steps) throw new Error("No pipeline steps configured. Use setGlobalSteps() first.");
|
|
6842
|
-
this.log.info("Pipeline initializing — frames will be dropped until ready");
|
|
6843
|
-
const format = this.currentEngine.format;
|
|
6844
|
-
const downloads = [];
|
|
6845
|
-
for (const step of flattenSteps(steps)) {
|
|
6846
|
-
const modelEntry = await this.resolveModelEntry(step.addonId, step.modelId);
|
|
6847
|
-
if (!modelEntry) {
|
|
6848
|
-
this.log.warn("Model not found in step catalog — skipping download", { meta: {
|
|
6849
|
-
modelId: step.modelId,
|
|
6850
|
-
step: step.addonId
|
|
6851
|
-
} });
|
|
6852
|
-
continue;
|
|
6853
|
-
}
|
|
6854
|
-
if (!isModelDownloaded(this.modelsDir, modelEntry, format)) this.log.info("Downloading model", { meta: {
|
|
6855
|
-
modelId: step.modelId,
|
|
6856
|
-
format
|
|
6857
|
-
} });
|
|
6858
|
-
downloads.push(ensureModel(this.modelsDir, modelEntry, format).then(() => {}));
|
|
6859
|
-
}
|
|
6860
|
-
await Promise.all(downloads);
|
|
6861
|
-
await this.ensureBackendDeps(this.currentEngine);
|
|
6862
|
-
this.engineFactory = new EngineFactory({
|
|
6863
|
-
engine: this.currentEngine,
|
|
6864
|
-
modelsDir: this.modelsDir,
|
|
6865
|
-
logger: this.log.child("engine"),
|
|
6866
|
-
pythonPath: this.executorOptions.pythonPath ?? "",
|
|
6867
|
-
concurrency: this.executorOptions.concurrency,
|
|
6868
|
-
tuning: this.executorOptions.tuning,
|
|
6869
|
-
numWorkers: this.executorOptions.numWorkers
|
|
6870
|
-
});
|
|
6871
|
-
await this.engineFactory.initialize(steps);
|
|
6872
|
-
this.currentSteps = steps;
|
|
6873
|
-
const runtimeStr = `${this.currentEngine.runtime}+${this.currentEngine.backend}`;
|
|
6874
|
-
this.executor = new PipelineExecutor({
|
|
6875
|
-
engineRuntime: runtimeStr,
|
|
6876
|
-
logger: this.log
|
|
6877
|
-
});
|
|
6878
|
-
this.ready = true;
|
|
6879
|
-
this.log.info("Pipeline ready — accepting frames");
|
|
6880
|
-
}
|
|
6881
6744
|
/**
|
|
6882
6745
|
* Phase 2b — resolve the engine from the addon's new schema-backed
|
|
6883
|
-
* fields (`engineRuntime`, `engineBackend`, `engineDevice`).
|
|
6884
|
-
*
|
|
6746
|
+
* fields (`engineRuntime`, `engineBackend`, `engineDevice`). The legacy
|
|
6747
|
+
* `pipelineEngine` JSON-blob fallback was removed with the executor seed
|
|
6748
|
+
* (any store predating the per-node cascade simply re-runs auto-pick).
|
|
6885
6749
|
*
|
|
6886
6750
|
* The `'auto'` sentinel is treated as NO override (returns null) so the
|
|
6887
6751
|
* caller re-resolves LIVE via `resolveAutoEngine()` — `'auto'` is the
|
|
@@ -6924,8 +6788,7 @@ var DetectionPipelineProvider = class DetectionPipelineProvider {
|
|
|
6924
6788
|
...device ? { device } : {}
|
|
6925
6789
|
};
|
|
6926
6790
|
}
|
|
6927
|
-
|
|
6928
|
-
return readStored(raw, isEngineChoice);
|
|
6791
|
+
return null;
|
|
6929
6792
|
}
|
|
6930
6793
|
/**
|
|
6931
6794
|
* Re-run the platform probe for the inference engine and persist the
|
|
@@ -6975,48 +6838,29 @@ var DetectionPipelineProvider = class DetectionPipelineProvider {
|
|
|
6975
6838
|
return { success: true };
|
|
6976
6839
|
}
|
|
6977
6840
|
/**
|
|
6978
|
-
*
|
|
6979
|
-
*
|
|
6841
|
+
* Clear THIS node's executor-side PER-DEVICE settings stores — the
|
|
6842
|
+
* per-camera step overrides the object-detection root reads via
|
|
6843
|
+
* `applyDeviceOverridesToTree`.
|
|
6980
6844
|
*
|
|
6981
6845
|
* Node-routed (the cap's default `nodeIdMode: 'routing'`): the generated
|
|
6982
6846
|
* cap-router strips `nodeId` and dispatches to the target node, so this
|
|
6983
|
-
* method runs ON the node being
|
|
6847
|
+
* method runs ON the node being cleared and takes no argument.
|
|
6984
6848
|
*
|
|
6985
|
-
*
|
|
6986
|
-
*
|
|
6987
|
-
*
|
|
6988
|
-
*
|
|
6989
|
-
*
|
|
6990
|
-
*
|
|
6991
|
-
* 2. the LEGACY engine blob (`KEY_ENGINE`). The per-node engine cascade
|
|
6992
|
-
* (`engineBackend@<node>` / `engineDevice@<node>`) is intentionally
|
|
6993
|
-
* left intact — the operator's engine selection is preserved and the
|
|
6994
|
-
* default is regenerated against it.
|
|
6995
|
-
* 3. every device's PER-CAMERA step overrides (the per-device store the
|
|
6996
|
-
* object-detection root reads via `applyDeviceOverridesToTree`).
|
|
6849
|
+
* This is the slimmed executor leg of the orchestrator's
|
|
6850
|
+
* `resetNodePipelineDefaults` flow. The legacy `resetToDefault` — which
|
|
6851
|
+
* also reset a persisted GLOBAL step-tree seed nothing in the live
|
|
6852
|
+
* per-camera path read — was removed together with that seed
|
|
6853
|
+
* (`getGlobalSteps` is pure now, so there is nothing node-global left to
|
|
6854
|
+
* reset here).
|
|
6997
6855
|
*
|
|
6998
|
-
* Idempotent:
|
|
6999
|
-
* already-empty per-device stores harmlessly. Returns the regenerated
|
|
7000
|
-
* object-detection model id (null when the default tree has no detector
|
|
7001
|
-
* for this node's format).
|
|
6856
|
+
* Idempotent: clearing already-empty per-device stores is a no-op.
|
|
7002
6857
|
*/
|
|
7003
|
-
async
|
|
7004
|
-
await this.writeStore({
|
|
7005
|
-
[KEY_STEPS]: null,
|
|
7006
|
-
[KEY_ENGINE]: null
|
|
7007
|
-
});
|
|
7008
|
-
this.currentSteps = null;
|
|
6858
|
+
async clearDeviceOverrides() {
|
|
7009
6859
|
const clearedDevices = await this.clearAllDeviceOverrides();
|
|
7010
|
-
|
|
7011
|
-
this.log.info("pipeline reset to default", { meta: {
|
|
7012
|
-
clearedGlobalSteps: true,
|
|
7013
|
-
clearedEngineBlob: true,
|
|
7014
|
-
clearedDeviceOverrides: clearedDevices,
|
|
7015
|
-
regeneratedModelId
|
|
7016
|
-
} });
|
|
6860
|
+
this.log.info("executor per-device overrides cleared", { meta: { clearedDevices } });
|
|
7017
6861
|
return {
|
|
7018
6862
|
success: true,
|
|
7019
|
-
|
|
6863
|
+
clearedDevices
|
|
7020
6864
|
};
|
|
7021
6865
|
}
|
|
7022
6866
|
/**
|
|
@@ -7026,7 +6870,7 @@ var DetectionPipelineProvider = class DetectionPipelineProvider {
|
|
|
7026
6870
|
* enumerated via the device-manager and cleared one by one
|
|
7027
6871
|
* (`clearDeviceStore` is idempotent — a device with no overrides is a
|
|
7028
6872
|
* no-op). Never throws: a device-manager outage degrades to "cleared
|
|
7029
|
-
* nothing" so the
|
|
6873
|
+
* nothing" so the reset flow still completes.
|
|
7030
6874
|
*/
|
|
7031
6875
|
async clearAllDeviceOverrides() {
|
|
7032
6876
|
const api = this.addonCtx?.api;
|
|
@@ -7035,7 +6879,7 @@ var DetectionPipelineProvider = class DetectionPipelineProvider {
|
|
|
7035
6879
|
try {
|
|
7036
6880
|
devices = await api.deviceManager.listAll.query({});
|
|
7037
6881
|
} catch (err) {
|
|
7038
|
-
this.log.warn("
|
|
6882
|
+
this.log.warn("clearDeviceOverrides: device enumeration failed — skipping per-device clear", { meta: { error: errMsg(err) } });
|
|
7039
6883
|
return 0;
|
|
7040
6884
|
}
|
|
7041
6885
|
let cleared = 0;
|
|
@@ -7043,10 +6887,13 @@ var DetectionPipelineProvider = class DetectionPipelineProvider {
|
|
|
7043
6887
|
await this.clearDeviceStore(device.id);
|
|
7044
6888
|
cleared++;
|
|
7045
6889
|
} catch (err) {
|
|
7046
|
-
this.log.warn("
|
|
7047
|
-
deviceId: device.id,
|
|
7048
|
-
|
|
7049
|
-
|
|
6890
|
+
this.log.warn("clearDeviceOverrides: failed to clear per-device overrides for device", {
|
|
6891
|
+
tags: { deviceId: device.id },
|
|
6892
|
+
meta: {
|
|
6893
|
+
deviceId: device.id,
|
|
6894
|
+
error: errMsg(err)
|
|
6895
|
+
}
|
|
6896
|
+
});
|
|
7050
6897
|
}
|
|
7051
6898
|
return cleared;
|
|
7052
6899
|
}
|