@camstack/addon-pipeline 1.2.294 → 1.2.295

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.
Files changed (39) hide show
  1. package/THIRD_PARTY_MODELS.md +233 -0
  2. package/dist/audio-analyzer/index.js +2 -2
  3. package/dist/audio-analyzer/index.mjs +2 -2
  4. package/dist/{default-detection-model-0dPKRKUD.mjs → default-detection-model-CAUBVbgK.mjs} +107 -54
  5. package/dist/{default-detection-model-D24AJOTn.js → default-detection-model-wNEISVA9.js} +107 -54
  6. package/dist/detection-pipeline/index.js +284 -457
  7. package/dist/detection-pipeline/index.mjs +284 -457
  8. package/dist/{dist-CJR259Xf.js → dist-BsVcf5wO.js} +1310 -832
  9. package/dist/{dist-RXbmRAwP.mjs → dist-CuxSNLKW.mjs} +1305 -833
  10. package/dist/motion-wasm/index.js +1 -1
  11. package/dist/motion-wasm/index.mjs +1 -1
  12. package/dist/{node-atmRSHPk.mjs → node-Cqb1QiXk.mjs} +1 -1
  13. package/dist/{node-DWg9zbY1.js → node-UFk6I2f6.js} +1 -1
  14. package/dist/pipeline-runner/index.js +189 -70
  15. package/dist/pipeline-runner/index.mjs +189 -70
  16. package/dist/{process-memory-BJUXvTjd.js → process-memory-CJV29sPf.js} +1 -1
  17. package/dist/{process-memory-BgFOHFnx.mjs → process-memory-D0Nvs9rr.mjs} +1 -1
  18. package/dist/recorder/index.js +12 -2
  19. package/dist/recorder/index.mjs +12 -2
  20. package/dist/{segment-demux-js-C_fPJub3.js → segment-demux-js-DGwmf5hu.js} +1 -1
  21. package/dist/{segment-demux-js-G7wFpHzn.mjs → segment-demux-js-DIDWw1iE.mjs} +1 -1
  22. package/dist/stream-broker/_stub.js +2 -2
  23. package/dist/stream-broker/{_virtual_mf-localSharedImportMap___mfe_internal__addon_stream_broker_widgets-6IyM-BIn.mjs → _virtual_mf-localSharedImportMap___mfe_internal__addon_stream_broker_widgets-B7nBFqva.mjs} +2 -2
  24. package/dist/stream-broker/_virtual_mf___mfe_internal__addon_stream_broker_widgets__loadShare___mf_0_camstack_mf_1_types__loadShare__.js-CCIyBvRa.mjs +26 -0
  25. package/dist/stream-broker/{_virtual_mf___mfe_internal__addon_stream_broker_widgets__loadShare___mf_0_camstack_mf_1_ui_mf_2_library__loadShare__.js-DoyA71_q.mjs → _virtual_mf___mfe_internal__addon_stream_broker_widgets__loadShare___mf_0_camstack_mf_1_ui_mf_2_library__loadShare__.js-DeD_UFdb.mjs} +1 -1
  26. package/dist/stream-broker/demux-worker-child.js +1 -1
  27. package/dist/stream-broker/demux-worker-child.mjs +1 -1
  28. package/dist/stream-broker/{hostInit-BBYHWS3M.mjs → hostInit-BKlb3qac.mjs} +2 -2
  29. package/dist/stream-broker/index.js +3 -3
  30. package/dist/stream-broker/index.mjs +3 -3
  31. package/dist/stream-broker/remoteEntry.js +1 -1
  32. package/package.json +3 -2
  33. package/python/postprocessors/__init__.py +2 -0
  34. package/python/postprocessors/ssd.py +73 -17
  35. package/python/postprocessors/test_ssd.py +205 -0
  36. package/python/postprocessors/test_yunet.py +292 -0
  37. package/python/postprocessors/testdata/ssdlite_mobiledet_outputs.json +1 -0
  38. package/python/postprocessors/yunet.py +275 -0
  39. package/dist/stream-broker/_virtual_mf___mfe_internal__addon_stream_broker_widgets__loadShare___mf_0_camstack_mf_1_types__loadShare__.js-6IHzlLJ_.mjs +0 -26
@@ -2,7 +2,7 @@ Object.defineProperties(exports, {
2
2
  __esModule: { value: true },
3
3
  [Symbol.toStringTag]: { value: "Module" }
4
4
  });
5
- const require_dist = require("../dist-CJR259Xf.js");
5
+ const require_dist = require("../dist-BsVcf5wO.js");
6
6
  const require_lazy_sharp = require("../lazy-sharp-BuwKlQLR.js");
7
7
  let node_fs = require("node:fs");
8
8
  let node_path = require("node:path");
@@ -1,4 +1,4 @@
1
- import { Tt as motionDetectionCapability, ct as evaluateZoneRules, gn as hydrateSchema, on as BaseAddon, un as DeviceType } from "../dist-RXbmRAwP.mjs";
1
+ import { Et as motionDetectionCapability, _n as hydrateSchema, dn as DeviceType, lt as evaluateZoneRules, sn as BaseAddon } from "../dist-CuxSNLKW.mjs";
2
2
  import { t as getSharp } from "../lazy-sharp-DXsqwpph.mjs";
3
3
  import { readFileSync } from "node:fs";
4
4
  import { join } from "node:path";
@@ -1,4 +1,4 @@
1
- import { $t as errMsg, in as isSoftwareDecode, nn as buildFfmpegArgs, tn as Fmp4BoxSplitter } from "./dist-RXbmRAwP.mjs";
1
+ import { an as isSoftwareDecode, en as errMsg, nn as Fmp4BoxSplitter, rn as buildFfmpegArgs } from "./dist-CuxSNLKW.mjs";
2
2
  import { randomUUID } from "node:crypto";
3
3
  import { realpathSync } from "node:fs";
4
4
  import path from "node:path";
@@ -1,5 +1,5 @@
1
1
  const require_chunk = require("./chunk-emK7D4bc.js");
2
- const require_dist = require("./dist-CJR259Xf.js");
2
+ const require_dist = require("./dist-BsVcf5wO.js");
3
3
  let node_crypto = require("node:crypto");
4
4
  let node_fs = require("node:fs");
5
5
  node_fs = require_chunk.__toESM(node_fs, 1);
@@ -3,9 +3,9 @@ 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-CJR259Xf.js");
7
- const require_node = require("../node-DWg9zbY1.js");
8
- const require_default_detection_model = require("../default-detection-model-D24AJOTn.js");
6
+ const require_dist = require("../dist-BsVcf5wO.js");
7
+ const require_node = require("../node-UFk6I2f6.js");
8
+ const require_default_detection_model = require("../default-detection-model-wNEISVA9.js");
9
9
  const require_worker_protocol = require("../worker-protocol-B2MfQLlu.js");
10
10
  const require_hub_hostname = require("../hub-hostname-DAJXlOgV.js");
11
11
  const require_lazy_sharp = require("../lazy-sharp-BuwKlQLR.js");
@@ -2235,28 +2235,17 @@ function onboardRootDetections(slot, frame, gate) {
2235
2235
  //#endregion
2236
2236
  //#region src/pipeline-runner/bench-step-schema.ts
2237
2237
  /**
2238
- * Shared bench-facing schemas: the minimal recursive step tree and the
2239
- * engine choice. Extracted from `bench-actions.ts` so the capacity-ramp
2240
- * schemas (`capacity/capacity-schemas.ts`) can reuse them without a
2241
- * bench-actions ↔ capacity-schemas import cycle.
2242
- *
2243
- * Local mirror of pipeline-executor's shapes ON PURPOSE (not a cap-package
2244
- * coupling): the shape is fixed by the runtime contract
2245
- * (runtime + backend + format + optional device / addonId + modelId +
2246
- * enabled + children).
2247
- */
2248
- var BenchEngineChoiceSchema = require_dist.object({
2249
- runtime: require_dist._enum(["node", "python"]),
2250
- backend: require_dist.string(),
2251
- format: require_dist._enum([
2252
- "onnx",
2253
- "coreml",
2254
- "openvino",
2255
- "tflite",
2256
- "pt"
2257
- ]),
2258
- device: require_dist.string().optional()
2259
- });
2238
+ * Shared bench-facing schemas: the minimal recursive step tree. Extracted from
2239
+ * `bench-actions.ts` so the capacity-ramp schemas (`capacity/capacity-schemas.ts`)
2240
+ * can reuse it without a bench-actions ↔ capacity-schemas import cycle.
2241
+ *
2242
+ * Local mirror of pipeline-executor's step shape ON PURPOSE (not a cap-package
2243
+ * coupling): addonId + modelId + enabled + children.
2244
+ *
2245
+ * There is no engine choice here any more (D646). A bench names the pool it
2246
+ * measures by `deviceKey`; the engine override it used to carry was honoured by
2247
+ * swapping the executor's shared engine state under live cameras.
2248
+ */
2260
2249
  var BenchStepSchema = require_dist.lazy(() => require_dist.object({
2261
2250
  addonId: require_dist.string(),
2262
2251
  modelId: require_dist.string(),
@@ -2292,7 +2281,6 @@ var RunCapacityRampInputSchema = require_dist.object({
2292
2281
  sessionId: require_dist.string(),
2293
2282
  nodeId: require_dist.string().optional(),
2294
2283
  deviceKey: require_dist.string().optional(),
2295
- engine: BenchEngineChoiceSchema.optional(),
2296
2284
  slo: CapacitySloSchema.optional(),
2297
2285
  allowActiveCameras: require_dist.boolean().optional(),
2298
2286
  drainTimeoutSec: require_dist.number().min(1).max(300).optional()
@@ -2481,16 +2469,15 @@ var CacheBenchFrameResultSchema = require_dist.object({
2481
2469
  });
2482
2470
  var ReleaseBenchFrameInputSchema = require_dist.object({ frameId: require_dist.string() });
2483
2471
  var ReleaseBenchFrameResultSchema = require_dist.object({ released: require_dist.boolean() });
2484
- var RunSyntheticBenchInputSchema = require_dist.object({
2472
+ var StartSyntheticBenchInputSchema = require_dist.object({
2485
2473
  frameId: require_dist.string(),
2486
2474
  steps: require_dist.array(BenchStepSchema).min(1),
2487
2475
  parallel: require_dist.number().int().min(1).max(32),
2488
2476
  iterations: require_dist.number().int().min(1).max(1e4),
2489
2477
  warmup: require_dist.number().int().min(0).max(100).optional(),
2490
- sessionId: require_dist.string().optional(),
2478
+ sessionId: require_dist.string().min(1),
2491
2479
  simulatePipeline: require_dist.boolean().optional(),
2492
2480
  nodeId: require_dist.string().optional(),
2493
- engine: BenchEngineChoiceSchema.optional(),
2494
2481
  deviceKey: require_dist.string().optional(),
2495
2482
  plane: require_dist._enum(["full", "frame"]).optional()
2496
2483
  });
@@ -2500,7 +2487,16 @@ var TimingSplitSchema = require_dist.object({
2500
2487
  p95: require_dist.number(),
2501
2488
  p99: require_dist.number()
2502
2489
  });
2503
- var RunSyntheticBenchResultSchema = require_dist.object({
2490
+ var BenchPoolSchema = require_dist.object({
2491
+ nodeId: require_dist.string(),
2492
+ deviceKey: require_dist.string().nullable(),
2493
+ runtime: require_dist.string().nullable(),
2494
+ numWorkers: require_dist.number().nullable(),
2495
+ concurrency: require_dist.number().nullable(),
2496
+ batchMode: require_dist.string().nullable(),
2497
+ maxBatchSize: require_dist.number().nullable()
2498
+ });
2499
+ var SyntheticBenchResultSchema = require_dist.object({
2504
2500
  runs: require_dist.number(),
2505
2501
  wallSec: require_dist.number(),
2506
2502
  fps: require_dist.number(),
@@ -2512,23 +2508,52 @@ var RunSyntheticBenchResultSchema = require_dist.object({
2512
2508
  predictMs: require_dist.number(),
2513
2509
  batchSizeMean: require_dist.number(),
2514
2510
  batchSizeMax: require_dist.number(),
2515
- engine: require_dist.object({
2516
- runtime: require_dist.string(),
2517
- backend: require_dist.string(),
2518
- device: require_dist.string().optional()
2519
- }).optional(),
2520
- tuning: require_dist.object({
2521
- batchMode: require_dist.string(),
2522
- windowMs: require_dist.number(),
2523
- maxBatchSize: require_dist.number(),
2524
- concurrency: require_dist.number()
2525
- }).optional(),
2526
- path: require_dist.string().optional()
2511
+ pool: BenchPoolSchema,
2512
+ path: require_dist.string()
2513
+ });
2514
+ /** `startSyntheticBench` answers at once; the run continues in the background. */
2515
+ var StartSyntheticBenchAcceptedSchema = require_dist.object({
2516
+ accepted: require_dist.literal(true),
2517
+ sessionId: require_dist.string()
2527
2518
  });
2519
+ var SyntheticBenchKeySchema = require_dist.object({ sessionId: require_dist.string() });
2520
+ var SyntheticBenchStatusSchema = require_dist.object({
2521
+ sessionId: require_dist.string(),
2522
+ state: require_dist._enum([
2523
+ "running",
2524
+ "done",
2525
+ "failed",
2526
+ "aborted"
2527
+ ]),
2528
+ startedAtMs: require_dist.number(),
2529
+ finishedAtMs: require_dist.number().nullable(),
2530
+ progress: require_dist.object({
2531
+ runs: require_dist.number(),
2532
+ totalRuns: require_dist.number()
2533
+ }).nullable(),
2534
+ result: SyntheticBenchResultSchema.nullable(),
2535
+ error: require_dist.string().nullable()
2536
+ }).nullable();
2528
2537
  var pipelineRunnerBenchActions = require_dist.defineCustomActions({
2529
2538
  cacheBenchFrame: require_dist.customAction(CacheBenchFrameInputSchema, CacheBenchFrameResultSchema, { kind: "mutation" }),
2530
2539
  releaseBenchFrame: require_dist.customAction(ReleaseBenchFrameInputSchema, ReleaseBenchFrameResultSchema, { kind: "mutation" }),
2531
- runSyntheticBench: require_dist.customAction(RunSyntheticBenchInputSchema, RunSyntheticBenchResultSchema, { kind: "mutation" }),
2540
+ /**
2541
+ * START a synthetic bench and return at once (D646). Up to 32 parallel ×
2542
+ * 10 000 iterations does not fit the UDS addon-call plane's 60 s request
2543
+ * timeout, and a synchronous call was abandoned by its caller while it kept
2544
+ * loading the node. Poll `getSyntheticBenchStatus {sessionId}`; stop early
2545
+ * with `abortSyntheticBench {sessionId}`. One bench per runner at a time —
2546
+ * the measurement owns the pool.
2547
+ */
2548
+ startSyntheticBench: require_dist.customAction(StartSyntheticBenchInputSchema, StartSyntheticBenchAcceptedSchema, {
2549
+ kind: "mutation",
2550
+ auth: "admin"
2551
+ }),
2552
+ getSyntheticBenchStatus: require_dist.customAction(SyntheticBenchKeySchema, SyntheticBenchStatusSchema),
2553
+ abortSyntheticBench: require_dist.customAction(SyntheticBenchKeySchema, require_dist.object({ aborted: require_dist.boolean() }), {
2554
+ kind: "mutation",
2555
+ auth: "admin"
2556
+ }),
2532
2557
  /**
2533
2558
  * OPEN-loop capacity ramp (spec `2026-08-02-capacity-test-design.md` §4):
2534
2559
  * paced N×`fpsPerCamera` single-frame `runPipeline` calls with raw RGB —
@@ -2593,12 +2618,24 @@ function buildBenchRunPipelineInput(req) {
2593
2618
  return {
2594
2619
  steps: [...req.steps],
2595
2620
  frame: req.frame,
2596
- ...req.engine ? { engine: req.engine } : {},
2597
2621
  ...req.deviceKey ? { deviceKey: req.deviceKey } : {},
2598
2622
  ...req.plane ? { plane: req.plane } : {}
2599
2623
  };
2600
2624
  }
2601
2625
  /**
2626
+ * The tuning query for the pool a bench MEASURED (D646). It asked the node
2627
+ * default of whatever node answered first, so an NPU run was recorded beside
2628
+ * the onnx pool's `concurrency: 4`. Absent `deviceKey`, never
2629
+ * present-and-undefined, for the same `.loose()` reason as
2630
+ * {@link buildBenchRunPipelineInput}.
2631
+ */
2632
+ function buildBenchTuningQuery(target) {
2633
+ return {
2634
+ nodeId: target.nodeId,
2635
+ input: target.deviceKey ? { deviceKey: target.deviceKey } : {}
2636
+ };
2637
+ }
2638
+ /**
2602
2639
  * How long a box stays "seen".
2603
2640
  *
2604
2641
  * Sized on the gate's own clock, not on a guess: `maxDeferralMs` defaults to
@@ -7575,6 +7612,26 @@ var PipelineRunnerAddon = class PipelineRunnerAddon extends require_dist.BaseAdd
7575
7612
  benchFrameCache = /* @__PURE__ */ new Map();
7576
7613
  benchFrameSweeper = null;
7577
7614
  /**
7615
+ * Synthetic benches, start-then-poll (D646). One at a time on this runner —
7616
+ * the measurement owns the pool — and the last few finished ones kept for a
7617
+ * late poll. In RAM: a bench belongs to this process.
7618
+ */
7619
+ syntheticBenches = new require_dist.BackgroundRunRegistry({
7620
+ maxConcurrent: 1,
7621
+ keepFinished: 5,
7622
+ onSettled: (status) => {
7623
+ const line = { meta: {
7624
+ sessionId: status.runId,
7625
+ state: status.state,
7626
+ error: status.error,
7627
+ runs: status.result?.runs ?? null,
7628
+ fps: status.result?.fps ?? null
7629
+ } };
7630
+ if (status.state === "failed") this.ctx.logger.warn("synthetic bench failed", line);
7631
+ else this.ctx.logger.info("synthetic bench finished", line);
7632
+ }
7633
+ });
7634
+ /**
7578
7635
  * In-flight + recent capacity-ramp runs, keyed by sessionId. The ramp is
7579
7636
  * fire-and-poll (a full run outlives the UDS addon-call 60s timeout), so
7580
7637
  * completed results are kept here for `getCapacityRampStatus` to collect;
@@ -7775,7 +7832,9 @@ var PipelineRunnerAddon = class PipelineRunnerAddon extends require_dist.BaseAdd
7775
7832
  actionHandlers: {
7776
7833
  cacheBenchFrame: async (input) => this.cacheBenchFrame(input),
7777
7834
  releaseBenchFrame: async (input) => this.releaseBenchFrame(input),
7778
- runSyntheticBench: async (input) => this.runSyntheticBench(input),
7835
+ startSyntheticBench: async (input) => this.startSyntheticBench(input),
7836
+ getSyntheticBenchStatus: async (input) => this.getSyntheticBenchStatus(input.sessionId),
7837
+ abortSyntheticBench: async (input) => ({ aborted: this.syntheticBenches.abort(input.sessionId) }),
7779
7838
  runCapacityRamp: async (input) => this.runCapacityRampAction(input),
7780
7839
  getCapacityRampStatus: async (input) => this.getCapacityRampStatusAction(input),
7781
7840
  listCapacityRamps: async () => this.listCapacityRampsAction(),
@@ -7797,6 +7856,7 @@ var PipelineRunnerAddon = class PipelineRunnerAddon extends require_dist.BaseAdd
7797
7856
  this.benchFrameSweeper = null;
7798
7857
  }
7799
7858
  this.benchFrameCache.clear();
7859
+ this.syntheticBenches.abortAll();
7800
7860
  for (const entry of this.capacityRuns.values()) entry.abortFlag.aborted = true;
7801
7861
  this.capacityRuns.clear();
7802
7862
  if (this.unsubMotionEvents) {
@@ -7876,7 +7936,34 @@ var PipelineRunnerAddon = class PipelineRunnerAddon extends require_dist.BaseAdd
7876
7936
  const now = Date.now();
7877
7937
  for (const [id, entry] of this.benchFrameCache) if (entry.expiresAt < now) this.benchFrameCache.delete(id);
7878
7938
  }
7879
- async runSyntheticBench(input) {
7939
+ /**
7940
+ * Validate the cheap preconditions synchronously (so a bad frame id is a
7941
+ * refusal the caller sees at once), then run the bench in the background
7942
+ * and answer with the receipt (D646).
7943
+ */
7944
+ startSyntheticBench(input) {
7945
+ if (!this.ctx.api) throw new Error("startSyntheticBench: ctx.api unavailable");
7946
+ if (!this.benchFrameCache.has(input.frameId)) throw new Error(`startSyntheticBench: frameId ${input.frameId} not cached (call cacheBenchFrame first)`);
7947
+ this.syntheticBenches.start(input.sessionId, (run) => this.runSyntheticBench(input, run));
7948
+ return {
7949
+ accepted: true,
7950
+ sessionId: input.sessionId
7951
+ };
7952
+ }
7953
+ getSyntheticBenchStatus(sessionId) {
7954
+ const status = this.syntheticBenches.status(sessionId);
7955
+ if (status === null) return null;
7956
+ return {
7957
+ sessionId: status.runId,
7958
+ state: status.state,
7959
+ startedAtMs: status.startedAtMs,
7960
+ finishedAtMs: status.finishedAtMs,
7961
+ progress: status.progress,
7962
+ result: status.result,
7963
+ error: status.error
7964
+ };
7965
+ }
7966
+ async runSyntheticBench(input, run) {
7880
7967
  const ctx = this.ctx;
7881
7968
  const api = ctx.api;
7882
7969
  if (!api) throw new Error("runSyntheticBench: ctx.api unavailable");
@@ -7926,8 +8013,7 @@ var PipelineRunnerAddon = class PipelineRunnerAddon extends require_dist.BaseAdd
7926
8013
  }, pin)).frameId;
7927
8014
  await api.pipelineExecutor.runPipeline.mutate({ ...buildBenchRunPipelineInput({
7928
8015
  steps: stepsToRun,
7929
- frame: sharedFrame,
7930
- ...input.engine ? { engine: input.engine } : {}
8016
+ frame: sharedFrame
7931
8017
  }) }, pin);
7932
8018
  const warmupCount = input.warmup ?? 1;
7933
8019
  for (let w = 0; w < warmupCount; w++) await api.pipelineExecutor.inferCached.mutate({
@@ -7941,11 +8027,12 @@ var PipelineRunnerAddon = class PipelineRunnerAddon extends require_dist.BaseAdd
7941
8027
  const batchSizes = [];
7942
8028
  const detCounts = [];
7943
8029
  let _n = 0;
7944
- const sessionId = input.sessionId ?? `synth-${Date.now().toString(36)}`;
8030
+ const sessionId = input.sessionId;
7945
8031
  const totalRuns = input.parallel * input.iterations;
7946
8032
  const wallStart = performance.now();
7947
8033
  const worker = async () => {
7948
8034
  for (let i = 0; i < input.iterations; i++) {
8035
+ if (run.signal.aborted) break;
7949
8036
  const t0 = performance.now();
7950
8037
  const result = await api.pipelineExecutor.inferCached.mutate({
7951
8038
  stepId: rootStep.addonId,
@@ -7965,6 +8052,10 @@ var PipelineRunnerAddon = class PipelineRunnerAddon extends require_dist.BaseAdd
7965
8052
  batchSizes.push(bs);
7966
8053
  detCounts.push(dets);
7967
8054
  const n = ++_n;
8055
+ run.report({
8056
+ runs: n,
8057
+ totalRuns
8058
+ });
7968
8059
  if (n <= 20) ctx.logger.info("bench call trace (cached)", { meta: {
7969
8060
  n,
7970
8061
  wallMs: Math.round(wallMs),
@@ -8017,7 +8108,7 @@ var PipelineRunnerAddon = class PipelineRunnerAddon extends require_dist.BaseAdd
8017
8108
  await Promise.all(Array.from({ length: input.parallel }, () => worker()));
8018
8109
  const wallSec = (performance.now() - wallStart) / 1e3;
8019
8110
  await api.pipelineExecutor.uncacheFrame.mutate({ frameId: poolFrameId }, pin).catch(() => {});
8020
- return this.buildBenchResult(wallTimings, inferTimings, preprocessTimings, predictTimings, batchSizes, detCounts, wallSec, "cached");
8111
+ return this.buildBenchResult(wallTimings, inferTimings, preprocessTimings, predictTimings, batchSizes, detCounts, wallSec, "cached", { nodeId: benchNode });
8021
8112
  }
8022
8113
  ctx.logger.info("synthetic bench: using full runPipeline path", { meta: {
8023
8114
  steps: enabledSteps.length,
@@ -8031,7 +8122,6 @@ var PipelineRunnerAddon = class PipelineRunnerAddon extends require_dist.BaseAdd
8031
8122
  const result = await api.pipelineExecutor.runPipeline.mutate({ ...buildBenchRunPipelineInput({
8032
8123
  steps: stepsToRun,
8033
8124
  frame: sharedFrame,
8034
- ...input.engine ? { engine: input.engine } : {},
8035
8125
  ...input.deviceKey ? { deviceKey: input.deviceKey } : {},
8036
8126
  ...input.plane ? { plane: input.plane } : {}
8037
8127
  }) }, pin);
@@ -8059,11 +8149,12 @@ var PipelineRunnerAddon = class PipelineRunnerAddon extends require_dist.BaseAdd
8059
8149
  const predictTimings = [];
8060
8150
  const batchSizes = [];
8061
8151
  const detCounts = [];
8062
- const sessionId = input.sessionId ?? `synth-${Date.now().toString(36)}`;
8152
+ const sessionId = input.sessionId;
8063
8153
  const totalRuns = input.parallel * input.iterations;
8064
8154
  const wallStart = performance.now();
8065
8155
  const worker = async () => {
8066
8156
  for (let i = 0; i < input.iterations; i++) {
8157
+ if (run.signal.aborted) break;
8067
8158
  const { wallMs, result } = await callOnce();
8068
8159
  wallTimings.push(wallMs);
8069
8160
  serverWallTimings.push(result.debug?.wallMs ?? 0);
@@ -8073,6 +8164,10 @@ var PipelineRunnerAddon = class PipelineRunnerAddon extends require_dist.BaseAdd
8073
8164
  batchSizes.push(result.debug?.batchSize ?? 1);
8074
8165
  detCounts.push(result.detections?.length ?? 0);
8075
8166
  const n = wallTimings.length;
8167
+ run.report({
8168
+ runs: n,
8169
+ totalRuns
8170
+ });
8076
8171
  if (n % Math.max(1, input.parallel) === 0 && ctx.eventBus) {
8077
8172
  const elapsed = (performance.now() - wallStart) / 1e3;
8078
8173
  const fps = elapsed > 0 ? n / elapsed : 0;
@@ -8113,9 +8208,12 @@ var PipelineRunnerAddon = class PipelineRunnerAddon extends require_dist.BaseAdd
8113
8208
  };
8114
8209
  await Promise.all(Array.from({ length: input.parallel }, () => worker()));
8115
8210
  const wallSec = (performance.now() - wallStart) / 1e3;
8116
- return this.buildBenchResult(wallTimings, inferTimings, preprocessTimings, predictTimings, batchSizes, detCounts, wallSec, "pipeline");
8211
+ return this.buildBenchResult(wallTimings, inferTimings, preprocessTimings, predictTimings, batchSizes, detCounts, wallSec, "pipeline", {
8212
+ nodeId: benchNode,
8213
+ ...input.deviceKey ? { deviceKey: input.deviceKey } : {}
8214
+ });
8117
8215
  }
8118
- async buildBenchResult(wallTimings, inferTimings, preprocessTimings, predictTimings, batchSizes, detCounts, wallSec, path) {
8216
+ async buildBenchResult(wallTimings, inferTimings, preprocessTimings, predictTimings, batchSizes, detCounts, wallSec, path, target) {
8119
8217
  const meanOfArr = (xs) => xs.length > 0 ? xs.reduce((s, v) => s + v, 0) / xs.length : 0;
8120
8218
  this.ctx.logger.info("synthetic bench summary", { meta: {
8121
8219
  runs: wallTimings.length,
@@ -8151,24 +8249,47 @@ var PipelineRunnerAddon = class PipelineRunnerAddon extends require_dist.BaseAdd
8151
8249
  batchSizeMean: Math.round(meanOf(batchSizes) * 100) / 100,
8152
8250
  batchSizeMax: batchSizes.length > 0 ? Math.max(...batchSizes) : 0,
8153
8251
  path,
8154
- ...await this.getEngineAndTuning()
8252
+ pool: await this.readBenchPool(target)
8155
8253
  };
8156
8254
  }
8157
- async getEngineAndTuning() {
8255
+ /**
8256
+ * The pool a bench measured, and its provisioning — asked of the node it
8257
+ * was pinned to, for the device pool it named (D646). It used to ask the
8258
+ * node DEFAULT of whichever node answered, so an NPU bench was recorded
8259
+ * beside the onnx pool's tuning. A failed read is `null` fields and a line,
8260
+ * never a default (D393).
8261
+ */
8262
+ async readBenchPool(target) {
8263
+ const unknown = {
8264
+ nodeId: target.nodeId,
8265
+ deviceKey: target.deviceKey ?? null,
8266
+ runtime: null,
8267
+ numWorkers: null,
8268
+ concurrency: null,
8269
+ batchMode: null,
8270
+ maxBatchSize: null
8271
+ };
8272
+ const api = this.ctx.api;
8273
+ if (!api) return unknown;
8274
+ const query = buildBenchTuningQuery(target);
8158
8275
  try {
8159
- const api = this.ctx.api;
8160
- if (!api) return {};
8161
- const [eng, tuning] = await Promise.all([api.pipelineExecutor.getSelectedEngine.query(), api.pipelineExecutor.getEffectiveTuning.query()]);
8276
+ const tuning = await api.pipelineExecutor.getEffectiveTuning.query({ ...query.input }, require_dist.nodePin(query.nodeId));
8162
8277
  return {
8163
- engine: eng ? {
8164
- runtime: eng.runtime,
8165
- backend: eng.backend,
8166
- device: eng.device
8167
- } : void 0,
8168
- tuning: tuning ?? void 0
8278
+ nodeId: target.nodeId,
8279
+ deviceKey: tuning.deviceKey,
8280
+ runtime: tuning.runtime,
8281
+ numWorkers: tuning.numWorkers,
8282
+ concurrency: tuning.concurrency,
8283
+ batchMode: tuning.batchMode,
8284
+ maxBatchSize: tuning.maxBatchSize
8169
8285
  };
8170
- } catch {
8171
- return {};
8286
+ } catch (err) {
8287
+ this.ctx.logger.warn("synthetic bench: pool tuning read failed — reported as unknown", { meta: {
8288
+ nodeId: target.nodeId,
8289
+ deviceKey: target.deviceKey ?? null,
8290
+ error: require_dist.errMsg(err)
8291
+ } });
8292
+ return unknown;
8172
8293
  }
8173
8294
  }
8174
8295
  /**
@@ -8291,7 +8412,6 @@ var PipelineRunnerAddon = class PipelineRunnerAddon extends require_dist.BaseAdd
8291
8412
  settleSec,
8292
8413
  measureSec,
8293
8414
  deviceKey: input.deviceKey ?? null,
8294
- engine: input.engine ?? null,
8295
8415
  contaminatedByActiveCameras,
8296
8416
  steps: stepsToRun.map((s) => `${s.addonId}/${s.modelId}${s.enabled ? "" : "[off]"}`)
8297
8417
  } });
@@ -8308,8 +8428,7 @@ var PipelineRunnerAddon = class PipelineRunnerAddon extends require_dist.BaseAdd
8308
8428
  },
8309
8429
  plane: "frame",
8310
8430
  sessionId,
8311
- ...input.deviceKey ? { deviceKey: input.deviceKey } : {},
8312
- ...input.engine ? { engine: input.engine } : {}
8431
+ ...input.deviceKey ? { deviceKey: input.deviceKey } : {}
8313
8432
  }, pin);
8314
8433
  if (result.debug?.engine !== void 0) engineLabel = result.debug.engine;
8315
8434
  if (result.shed === true) return {