@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
@@ -1,6 +1,6 @@
1
- import { $t as errMsg, An as literal, At as pickDetailCropConvention, C as FailureCounters, D as NativeLeaseAdmissionSchema, Dn as boolean, E as MOTION_CLOSE_AFTER_MS, En as array, Fn as string, Ln as EventCategory, Mn as object, Nt as pipelineRunnerCapability, O as NativeLeaseSettingsSchema, Tn as _enum, _ as DEFAULT_NATIVE_LEASE_SETTINGS, _t as loadContributionCapability, bn as nodePin, fn as createEvent, ft as failureContributionCapability, jn as number, jt as pickNativeLeaseOverride, kn as lazy, m as DEFAULT_DETAIL_CROP_CONVENTION, mn as defineCustomActions, on as BaseAddon, pn as customAction, tt as deriveDetailCropRect, v as DEVICE_BACKEND_TO_FORMAT } from "../dist-RXbmRAwP.mjs";
2
- import { i as NO_COST_CLAIM, t as ChildCostRegistry } from "../node-atmRSHPk.mjs";
3
- import { a as localFrameRegistry, d as getStepDefinition, i as rootObjectGate, o as resolveFrameViewGeometry, p as RETIRED_MODEL_IDS, r as macroGateVerdict } from "../default-detection-model-0dPKRKUD.mjs";
1
+ import { An as lazy, D as MOTION_CLOSE_AFTER_MS, Dn as array, En as _enum, In as string, Mn as number, Mt as pickNativeLeaseOverride, Nn as object, O as NativeLeaseAdmissionSchema, On as boolean, Pt as pipelineRunnerCapability, Rn as EventCategory, en as errMsg, h as DEFAULT_DETAIL_CROP_CONVENTION, hn as defineCustomActions, i as BackgroundRunRegistry, jn as literal, jt as pickDetailCropConvention, k as NativeLeaseSettingsSchema, mn as customAction, nt as deriveDetailCropRect, pn as createEvent, pt as failureContributionCapability, sn as BaseAddon, v as DEFAULT_NATIVE_LEASE_SETTINGS, vt as loadContributionCapability, w as FailureCounters, xn as nodePin, y as DEVICE_BACKEND_TO_FORMAT } from "../dist-CuxSNLKW.mjs";
2
+ import { i as NO_COST_CLAIM, t as ChildCostRegistry } from "../node-Cqb1QiXk.mjs";
3
+ import { a as localFrameRegistry, d as getStepDefinition, i as rootObjectGate, o as resolveFrameViewGeometry, p as RETIRED_MODEL_IDS, r as macroGateVerdict } from "../default-detection-model-CAUBVbgK.mjs";
4
4
  import { t as isWorkerReply } from "../worker-protocol-C_W-P_g-.mjs";
5
5
  import { t as resolveHubHostname } from "../hub-hostname-cCknRYKj.mjs";
6
6
  import { t as getSharp } from "../lazy-sharp-DXsqwpph.mjs";
@@ -2228,28 +2228,17 @@ function onboardRootDetections(slot, frame, gate) {
2228
2228
  //#endregion
2229
2229
  //#region src/pipeline-runner/bench-step-schema.ts
2230
2230
  /**
2231
- * Shared bench-facing schemas: the minimal recursive step tree and the
2232
- * engine choice. Extracted from `bench-actions.ts` so the capacity-ramp
2233
- * schemas (`capacity/capacity-schemas.ts`) can reuse them without a
2234
- * bench-actions ↔ capacity-schemas import cycle.
2235
- *
2236
- * Local mirror of pipeline-executor's shapes ON PURPOSE (not a cap-package
2237
- * coupling): the shape is fixed by the runtime contract
2238
- * (runtime + backend + format + optional device / addonId + modelId +
2239
- * enabled + children).
2240
- */
2241
- var BenchEngineChoiceSchema = object({
2242
- runtime: _enum(["node", "python"]),
2243
- backend: string(),
2244
- format: _enum([
2245
- "onnx",
2246
- "coreml",
2247
- "openvino",
2248
- "tflite",
2249
- "pt"
2250
- ]),
2251
- device: string().optional()
2252
- });
2231
+ * Shared bench-facing schemas: the minimal recursive step tree. Extracted from
2232
+ * `bench-actions.ts` so the capacity-ramp schemas (`capacity/capacity-schemas.ts`)
2233
+ * can reuse it without a bench-actions ↔ capacity-schemas import cycle.
2234
+ *
2235
+ * Local mirror of pipeline-executor's step shape ON PURPOSE (not a cap-package
2236
+ * coupling): addonId + modelId + enabled + children.
2237
+ *
2238
+ * There is no engine choice here any more (D646). A bench names the pool it
2239
+ * measures by `deviceKey`; the engine override it used to carry was honoured by
2240
+ * swapping the executor's shared engine state under live cameras.
2241
+ */
2253
2242
  var BenchStepSchema = lazy(() => object({
2254
2243
  addonId: string(),
2255
2244
  modelId: string(),
@@ -2285,7 +2274,6 @@ var RunCapacityRampInputSchema = object({
2285
2274
  sessionId: string(),
2286
2275
  nodeId: string().optional(),
2287
2276
  deviceKey: string().optional(),
2288
- engine: BenchEngineChoiceSchema.optional(),
2289
2277
  slo: CapacitySloSchema.optional(),
2290
2278
  allowActiveCameras: boolean().optional(),
2291
2279
  drainTimeoutSec: number().min(1).max(300).optional()
@@ -2473,16 +2461,15 @@ var CacheBenchFrameResultSchema = object({
2473
2461
  });
2474
2462
  var ReleaseBenchFrameInputSchema = object({ frameId: string() });
2475
2463
  var ReleaseBenchFrameResultSchema = object({ released: boolean() });
2476
- var RunSyntheticBenchInputSchema = object({
2464
+ var StartSyntheticBenchInputSchema = object({
2477
2465
  frameId: string(),
2478
2466
  steps: array(BenchStepSchema).min(1),
2479
2467
  parallel: number().int().min(1).max(32),
2480
2468
  iterations: number().int().min(1).max(1e4),
2481
2469
  warmup: number().int().min(0).max(100).optional(),
2482
- sessionId: string().optional(),
2470
+ sessionId: string().min(1),
2483
2471
  simulatePipeline: boolean().optional(),
2484
2472
  nodeId: string().optional(),
2485
- engine: BenchEngineChoiceSchema.optional(),
2486
2473
  deviceKey: string().optional(),
2487
2474
  plane: _enum(["full", "frame"]).optional()
2488
2475
  });
@@ -2492,7 +2479,16 @@ var TimingSplitSchema = object({
2492
2479
  p95: number(),
2493
2480
  p99: number()
2494
2481
  });
2495
- var RunSyntheticBenchResultSchema = object({
2482
+ var BenchPoolSchema = object({
2483
+ nodeId: string(),
2484
+ deviceKey: string().nullable(),
2485
+ runtime: string().nullable(),
2486
+ numWorkers: number().nullable(),
2487
+ concurrency: number().nullable(),
2488
+ batchMode: string().nullable(),
2489
+ maxBatchSize: number().nullable()
2490
+ });
2491
+ var SyntheticBenchResultSchema = object({
2496
2492
  runs: number(),
2497
2493
  wallSec: number(),
2498
2494
  fps: number(),
@@ -2504,23 +2500,52 @@ var RunSyntheticBenchResultSchema = object({
2504
2500
  predictMs: number(),
2505
2501
  batchSizeMean: number(),
2506
2502
  batchSizeMax: number(),
2507
- engine: object({
2508
- runtime: string(),
2509
- backend: string(),
2510
- device: string().optional()
2511
- }).optional(),
2512
- tuning: object({
2513
- batchMode: string(),
2514
- windowMs: number(),
2515
- maxBatchSize: number(),
2516
- concurrency: number()
2517
- }).optional(),
2518
- path: string().optional()
2503
+ pool: BenchPoolSchema,
2504
+ path: string()
2505
+ });
2506
+ /** `startSyntheticBench` answers at once; the run continues in the background. */
2507
+ var StartSyntheticBenchAcceptedSchema = object({
2508
+ accepted: literal(true),
2509
+ sessionId: string()
2519
2510
  });
2511
+ var SyntheticBenchKeySchema = object({ sessionId: string() });
2512
+ var SyntheticBenchStatusSchema = object({
2513
+ sessionId: string(),
2514
+ state: _enum([
2515
+ "running",
2516
+ "done",
2517
+ "failed",
2518
+ "aborted"
2519
+ ]),
2520
+ startedAtMs: number(),
2521
+ finishedAtMs: number().nullable(),
2522
+ progress: object({
2523
+ runs: number(),
2524
+ totalRuns: number()
2525
+ }).nullable(),
2526
+ result: SyntheticBenchResultSchema.nullable(),
2527
+ error: string().nullable()
2528
+ }).nullable();
2520
2529
  var pipelineRunnerBenchActions = defineCustomActions({
2521
2530
  cacheBenchFrame: customAction(CacheBenchFrameInputSchema, CacheBenchFrameResultSchema, { kind: "mutation" }),
2522
2531
  releaseBenchFrame: customAction(ReleaseBenchFrameInputSchema, ReleaseBenchFrameResultSchema, { kind: "mutation" }),
2523
- runSyntheticBench: customAction(RunSyntheticBenchInputSchema, RunSyntheticBenchResultSchema, { kind: "mutation" }),
2532
+ /**
2533
+ * START a synthetic bench and return at once (D646). Up to 32 parallel ×
2534
+ * 10 000 iterations does not fit the UDS addon-call plane's 60 s request
2535
+ * timeout, and a synchronous call was abandoned by its caller while it kept
2536
+ * loading the node. Poll `getSyntheticBenchStatus {sessionId}`; stop early
2537
+ * with `abortSyntheticBench {sessionId}`. One bench per runner at a time —
2538
+ * the measurement owns the pool.
2539
+ */
2540
+ startSyntheticBench: customAction(StartSyntheticBenchInputSchema, StartSyntheticBenchAcceptedSchema, {
2541
+ kind: "mutation",
2542
+ auth: "admin"
2543
+ }),
2544
+ getSyntheticBenchStatus: customAction(SyntheticBenchKeySchema, SyntheticBenchStatusSchema),
2545
+ abortSyntheticBench: customAction(SyntheticBenchKeySchema, object({ aborted: boolean() }), {
2546
+ kind: "mutation",
2547
+ auth: "admin"
2548
+ }),
2524
2549
  /**
2525
2550
  * OPEN-loop capacity ramp (spec `2026-08-02-capacity-test-design.md` §4):
2526
2551
  * paced N×`fpsPerCamera` single-frame `runPipeline` calls with raw RGB —
@@ -2585,12 +2610,24 @@ function buildBenchRunPipelineInput(req) {
2585
2610
  return {
2586
2611
  steps: [...req.steps],
2587
2612
  frame: req.frame,
2588
- ...req.engine ? { engine: req.engine } : {},
2589
2613
  ...req.deviceKey ? { deviceKey: req.deviceKey } : {},
2590
2614
  ...req.plane ? { plane: req.plane } : {}
2591
2615
  };
2592
2616
  }
2593
2617
  /**
2618
+ * The tuning query for the pool a bench MEASURED (D646). It asked the node
2619
+ * default of whatever node answered first, so an NPU run was recorded beside
2620
+ * the onnx pool's `concurrency: 4`. Absent `deviceKey`, never
2621
+ * present-and-undefined, for the same `.loose()` reason as
2622
+ * {@link buildBenchRunPipelineInput}.
2623
+ */
2624
+ function buildBenchTuningQuery(target) {
2625
+ return {
2626
+ nodeId: target.nodeId,
2627
+ input: target.deviceKey ? { deviceKey: target.deviceKey } : {}
2628
+ };
2629
+ }
2630
+ /**
2594
2631
  * How long a box stays "seen".
2595
2632
  *
2596
2633
  * Sized on the gate's own clock, not on a guess: `maxDeferralMs` defaults to
@@ -7567,6 +7604,26 @@ var PipelineRunnerAddon = class PipelineRunnerAddon extends BaseAddon {
7567
7604
  benchFrameCache = /* @__PURE__ */ new Map();
7568
7605
  benchFrameSweeper = null;
7569
7606
  /**
7607
+ * Synthetic benches, start-then-poll (D646). One at a time on this runner —
7608
+ * the measurement owns the pool — and the last few finished ones kept for a
7609
+ * late poll. In RAM: a bench belongs to this process.
7610
+ */
7611
+ syntheticBenches = new BackgroundRunRegistry({
7612
+ maxConcurrent: 1,
7613
+ keepFinished: 5,
7614
+ onSettled: (status) => {
7615
+ const line = { meta: {
7616
+ sessionId: status.runId,
7617
+ state: status.state,
7618
+ error: status.error,
7619
+ runs: status.result?.runs ?? null,
7620
+ fps: status.result?.fps ?? null
7621
+ } };
7622
+ if (status.state === "failed") this.ctx.logger.warn("synthetic bench failed", line);
7623
+ else this.ctx.logger.info("synthetic bench finished", line);
7624
+ }
7625
+ });
7626
+ /**
7570
7627
  * In-flight + recent capacity-ramp runs, keyed by sessionId. The ramp is
7571
7628
  * fire-and-poll (a full run outlives the UDS addon-call 60s timeout), so
7572
7629
  * completed results are kept here for `getCapacityRampStatus` to collect;
@@ -7767,7 +7824,9 @@ var PipelineRunnerAddon = class PipelineRunnerAddon extends BaseAddon {
7767
7824
  actionHandlers: {
7768
7825
  cacheBenchFrame: async (input) => this.cacheBenchFrame(input),
7769
7826
  releaseBenchFrame: async (input) => this.releaseBenchFrame(input),
7770
- runSyntheticBench: async (input) => this.runSyntheticBench(input),
7827
+ startSyntheticBench: async (input) => this.startSyntheticBench(input),
7828
+ getSyntheticBenchStatus: async (input) => this.getSyntheticBenchStatus(input.sessionId),
7829
+ abortSyntheticBench: async (input) => ({ aborted: this.syntheticBenches.abort(input.sessionId) }),
7771
7830
  runCapacityRamp: async (input) => this.runCapacityRampAction(input),
7772
7831
  getCapacityRampStatus: async (input) => this.getCapacityRampStatusAction(input),
7773
7832
  listCapacityRamps: async () => this.listCapacityRampsAction(),
@@ -7789,6 +7848,7 @@ var PipelineRunnerAddon = class PipelineRunnerAddon extends BaseAddon {
7789
7848
  this.benchFrameSweeper = null;
7790
7849
  }
7791
7850
  this.benchFrameCache.clear();
7851
+ this.syntheticBenches.abortAll();
7792
7852
  for (const entry of this.capacityRuns.values()) entry.abortFlag.aborted = true;
7793
7853
  this.capacityRuns.clear();
7794
7854
  if (this.unsubMotionEvents) {
@@ -7868,7 +7928,34 @@ var PipelineRunnerAddon = class PipelineRunnerAddon extends BaseAddon {
7868
7928
  const now = Date.now();
7869
7929
  for (const [id, entry] of this.benchFrameCache) if (entry.expiresAt < now) this.benchFrameCache.delete(id);
7870
7930
  }
7871
- async runSyntheticBench(input) {
7931
+ /**
7932
+ * Validate the cheap preconditions synchronously (so a bad frame id is a
7933
+ * refusal the caller sees at once), then run the bench in the background
7934
+ * and answer with the receipt (D646).
7935
+ */
7936
+ startSyntheticBench(input) {
7937
+ if (!this.ctx.api) throw new Error("startSyntheticBench: ctx.api unavailable");
7938
+ if (!this.benchFrameCache.has(input.frameId)) throw new Error(`startSyntheticBench: frameId ${input.frameId} not cached (call cacheBenchFrame first)`);
7939
+ this.syntheticBenches.start(input.sessionId, (run) => this.runSyntheticBench(input, run));
7940
+ return {
7941
+ accepted: true,
7942
+ sessionId: input.sessionId
7943
+ };
7944
+ }
7945
+ getSyntheticBenchStatus(sessionId) {
7946
+ const status = this.syntheticBenches.status(sessionId);
7947
+ if (status === null) return null;
7948
+ return {
7949
+ sessionId: status.runId,
7950
+ state: status.state,
7951
+ startedAtMs: status.startedAtMs,
7952
+ finishedAtMs: status.finishedAtMs,
7953
+ progress: status.progress,
7954
+ result: status.result,
7955
+ error: status.error
7956
+ };
7957
+ }
7958
+ async runSyntheticBench(input, run) {
7872
7959
  const ctx = this.ctx;
7873
7960
  const api = ctx.api;
7874
7961
  if (!api) throw new Error("runSyntheticBench: ctx.api unavailable");
@@ -7918,8 +8005,7 @@ var PipelineRunnerAddon = class PipelineRunnerAddon extends BaseAddon {
7918
8005
  }, pin)).frameId;
7919
8006
  await api.pipelineExecutor.runPipeline.mutate({ ...buildBenchRunPipelineInput({
7920
8007
  steps: stepsToRun,
7921
- frame: sharedFrame,
7922
- ...input.engine ? { engine: input.engine } : {}
8008
+ frame: sharedFrame
7923
8009
  }) }, pin);
7924
8010
  const warmupCount = input.warmup ?? 1;
7925
8011
  for (let w = 0; w < warmupCount; w++) await api.pipelineExecutor.inferCached.mutate({
@@ -7933,11 +8019,12 @@ var PipelineRunnerAddon = class PipelineRunnerAddon extends BaseAddon {
7933
8019
  const batchSizes = [];
7934
8020
  const detCounts = [];
7935
8021
  let _n = 0;
7936
- const sessionId = input.sessionId ?? `synth-${Date.now().toString(36)}`;
8022
+ const sessionId = input.sessionId;
7937
8023
  const totalRuns = input.parallel * input.iterations;
7938
8024
  const wallStart = performance.now();
7939
8025
  const worker = async () => {
7940
8026
  for (let i = 0; i < input.iterations; i++) {
8027
+ if (run.signal.aborted) break;
7941
8028
  const t0 = performance.now();
7942
8029
  const result = await api.pipelineExecutor.inferCached.mutate({
7943
8030
  stepId: rootStep.addonId,
@@ -7957,6 +8044,10 @@ var PipelineRunnerAddon = class PipelineRunnerAddon extends BaseAddon {
7957
8044
  batchSizes.push(bs);
7958
8045
  detCounts.push(dets);
7959
8046
  const n = ++_n;
8047
+ run.report({
8048
+ runs: n,
8049
+ totalRuns
8050
+ });
7960
8051
  if (n <= 20) ctx.logger.info("bench call trace (cached)", { meta: {
7961
8052
  n,
7962
8053
  wallMs: Math.round(wallMs),
@@ -8009,7 +8100,7 @@ var PipelineRunnerAddon = class PipelineRunnerAddon extends BaseAddon {
8009
8100
  await Promise.all(Array.from({ length: input.parallel }, () => worker()));
8010
8101
  const wallSec = (performance.now() - wallStart) / 1e3;
8011
8102
  await api.pipelineExecutor.uncacheFrame.mutate({ frameId: poolFrameId }, pin).catch(() => {});
8012
- return this.buildBenchResult(wallTimings, inferTimings, preprocessTimings, predictTimings, batchSizes, detCounts, wallSec, "cached");
8103
+ return this.buildBenchResult(wallTimings, inferTimings, preprocessTimings, predictTimings, batchSizes, detCounts, wallSec, "cached", { nodeId: benchNode });
8013
8104
  }
8014
8105
  ctx.logger.info("synthetic bench: using full runPipeline path", { meta: {
8015
8106
  steps: enabledSteps.length,
@@ -8023,7 +8114,6 @@ var PipelineRunnerAddon = class PipelineRunnerAddon extends BaseAddon {
8023
8114
  const result = await api.pipelineExecutor.runPipeline.mutate({ ...buildBenchRunPipelineInput({
8024
8115
  steps: stepsToRun,
8025
8116
  frame: sharedFrame,
8026
- ...input.engine ? { engine: input.engine } : {},
8027
8117
  ...input.deviceKey ? { deviceKey: input.deviceKey } : {},
8028
8118
  ...input.plane ? { plane: input.plane } : {}
8029
8119
  }) }, pin);
@@ -8051,11 +8141,12 @@ var PipelineRunnerAddon = class PipelineRunnerAddon extends BaseAddon {
8051
8141
  const predictTimings = [];
8052
8142
  const batchSizes = [];
8053
8143
  const detCounts = [];
8054
- const sessionId = input.sessionId ?? `synth-${Date.now().toString(36)}`;
8144
+ const sessionId = input.sessionId;
8055
8145
  const totalRuns = input.parallel * input.iterations;
8056
8146
  const wallStart = performance.now();
8057
8147
  const worker = async () => {
8058
8148
  for (let i = 0; i < input.iterations; i++) {
8149
+ if (run.signal.aborted) break;
8059
8150
  const { wallMs, result } = await callOnce();
8060
8151
  wallTimings.push(wallMs);
8061
8152
  serverWallTimings.push(result.debug?.wallMs ?? 0);
@@ -8065,6 +8156,10 @@ var PipelineRunnerAddon = class PipelineRunnerAddon extends BaseAddon {
8065
8156
  batchSizes.push(result.debug?.batchSize ?? 1);
8066
8157
  detCounts.push(result.detections?.length ?? 0);
8067
8158
  const n = wallTimings.length;
8159
+ run.report({
8160
+ runs: n,
8161
+ totalRuns
8162
+ });
8068
8163
  if (n % Math.max(1, input.parallel) === 0 && ctx.eventBus) {
8069
8164
  const elapsed = (performance.now() - wallStart) / 1e3;
8070
8165
  const fps = elapsed > 0 ? n / elapsed : 0;
@@ -8105,9 +8200,12 @@ var PipelineRunnerAddon = class PipelineRunnerAddon extends BaseAddon {
8105
8200
  };
8106
8201
  await Promise.all(Array.from({ length: input.parallel }, () => worker()));
8107
8202
  const wallSec = (performance.now() - wallStart) / 1e3;
8108
- return this.buildBenchResult(wallTimings, inferTimings, preprocessTimings, predictTimings, batchSizes, detCounts, wallSec, "pipeline");
8203
+ return this.buildBenchResult(wallTimings, inferTimings, preprocessTimings, predictTimings, batchSizes, detCounts, wallSec, "pipeline", {
8204
+ nodeId: benchNode,
8205
+ ...input.deviceKey ? { deviceKey: input.deviceKey } : {}
8206
+ });
8109
8207
  }
8110
- async buildBenchResult(wallTimings, inferTimings, preprocessTimings, predictTimings, batchSizes, detCounts, wallSec, path) {
8208
+ async buildBenchResult(wallTimings, inferTimings, preprocessTimings, predictTimings, batchSizes, detCounts, wallSec, path, target) {
8111
8209
  const meanOfArr = (xs) => xs.length > 0 ? xs.reduce((s, v) => s + v, 0) / xs.length : 0;
8112
8210
  this.ctx.logger.info("synthetic bench summary", { meta: {
8113
8211
  runs: wallTimings.length,
@@ -8143,24 +8241,47 @@ var PipelineRunnerAddon = class PipelineRunnerAddon extends BaseAddon {
8143
8241
  batchSizeMean: Math.round(meanOf(batchSizes) * 100) / 100,
8144
8242
  batchSizeMax: batchSizes.length > 0 ? Math.max(...batchSizes) : 0,
8145
8243
  path,
8146
- ...await this.getEngineAndTuning()
8244
+ pool: await this.readBenchPool(target)
8147
8245
  };
8148
8246
  }
8149
- async getEngineAndTuning() {
8247
+ /**
8248
+ * The pool a bench measured, and its provisioning — asked of the node it
8249
+ * was pinned to, for the device pool it named (D646). It used to ask the
8250
+ * node DEFAULT of whichever node answered, so an NPU bench was recorded
8251
+ * beside the onnx pool's tuning. A failed read is `null` fields and a line,
8252
+ * never a default (D393).
8253
+ */
8254
+ async readBenchPool(target) {
8255
+ const unknown = {
8256
+ nodeId: target.nodeId,
8257
+ deviceKey: target.deviceKey ?? null,
8258
+ runtime: null,
8259
+ numWorkers: null,
8260
+ concurrency: null,
8261
+ batchMode: null,
8262
+ maxBatchSize: null
8263
+ };
8264
+ const api = this.ctx.api;
8265
+ if (!api) return unknown;
8266
+ const query = buildBenchTuningQuery(target);
8150
8267
  try {
8151
- const api = this.ctx.api;
8152
- if (!api) return {};
8153
- const [eng, tuning] = await Promise.all([api.pipelineExecutor.getSelectedEngine.query(), api.pipelineExecutor.getEffectiveTuning.query()]);
8268
+ const tuning = await api.pipelineExecutor.getEffectiveTuning.query({ ...query.input }, nodePin(query.nodeId));
8154
8269
  return {
8155
- engine: eng ? {
8156
- runtime: eng.runtime,
8157
- backend: eng.backend,
8158
- device: eng.device
8159
- } : void 0,
8160
- tuning: tuning ?? void 0
8270
+ nodeId: target.nodeId,
8271
+ deviceKey: tuning.deviceKey,
8272
+ runtime: tuning.runtime,
8273
+ numWorkers: tuning.numWorkers,
8274
+ concurrency: tuning.concurrency,
8275
+ batchMode: tuning.batchMode,
8276
+ maxBatchSize: tuning.maxBatchSize
8161
8277
  };
8162
- } catch {
8163
- return {};
8278
+ } catch (err) {
8279
+ this.ctx.logger.warn("synthetic bench: pool tuning read failed — reported as unknown", { meta: {
8280
+ nodeId: target.nodeId,
8281
+ deviceKey: target.deviceKey ?? null,
8282
+ error: errMsg(err)
8283
+ } });
8284
+ return unknown;
8164
8285
  }
8165
8286
  }
8166
8287
  /**
@@ -8283,7 +8404,6 @@ var PipelineRunnerAddon = class PipelineRunnerAddon extends BaseAddon {
8283
8404
  settleSec,
8284
8405
  measureSec,
8285
8406
  deviceKey: input.deviceKey ?? null,
8286
- engine: input.engine ?? null,
8287
8407
  contaminatedByActiveCameras,
8288
8408
  steps: stepsToRun.map((s) => `${s.addonId}/${s.modelId}${s.enabled ? "" : "[off]"}`)
8289
8409
  } });
@@ -8300,8 +8420,7 @@ var PipelineRunnerAddon = class PipelineRunnerAddon extends BaseAddon {
8300
8420
  },
8301
8421
  plane: "frame",
8302
8422
  sessionId,
8303
- ...input.deviceKey ? { deviceKey: input.deviceKey } : {},
8304
- ...input.engine ? { engine: input.engine } : {}
8423
+ ...input.deviceKey ? { deviceKey: input.deviceKey } : {}
8305
8424
  }, pin);
8306
8425
  if (result.debug?.engine !== void 0) engineLabel = result.debug.engine;
8307
8426
  if (result.shed === true) return {
@@ -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_fs = require("node:fs");
4
4
  node_fs = require_chunk.__toESM(node_fs);
5
5
  let node_child_process = require("node:child_process");
@@ -1,4 +1,4 @@
1
- import { Dt as parseProcStatus } from "./dist-RXbmRAwP.mjs";
1
+ import { Ot as parseProcStatus } from "./dist-CuxSNLKW.mjs";
2
2
  import * as fs from "node:fs";
3
3
  import { execFile } from "node:child_process";
4
4
  //#region src/shared/node-topology-platform.ts
@@ -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-CJR259Xf.js");
7
- const require_node = require("../node-DWg9zbY1.js");
6
+ const require_dist = require("../dist-BsVcf5wO.js");
7
+ const require_node = require("../node-UFk6I2f6.js");
8
8
  const require_hub_hostname = require("../hub-hostname-DAJXlOgV.js");
9
9
  const require_restream_intent = require("../restream-intent-7uDNqMKs.js");
10
10
  const require_retire_root_keys = require("../retire-root-keys-Csb8z2f3.js");
@@ -5576,6 +5576,16 @@ Object.freeze({
5576
5576
  "priority": 3
5577
5577
  } } },
5578
5578
  "getHistory": { "filter": { "limit": 100 } },
5579
+ "previewStateSummary": { "rule": { "__nested__": {
5580
+ "enabled": true,
5581
+ "conditions": {},
5582
+ "media": { "attach": "best" },
5583
+ "throttle": {
5584
+ "cooldownSec": 60,
5585
+ "scope": "rule-device"
5586
+ },
5587
+ "priority": 3
5588
+ } } },
5579
5589
  "testRule": {
5580
5590
  "rule": { "__nested__": {
5581
5591
  "enabled": true,
@@ -1,5 +1,5 @@
1
- import { $t as errMsg, B as VISIT_MERGE_GAP_MS, Bt as resolveCreateExportSubject, Cn as selectAssignedProfileSlots, Ct as migrateLegacyDeviceSignalConfig, Dn as boolean, En as array, F as RECORDING_SOURCE_CAMSTACK_ADDON, Fn as string, Ft as recordingArchiveCapability, Ht as resolveLocationMode, I as RecordingConfigSchema, It as recordingCapability, J as clipExportFailure, K as batteryCapability, Kt as storageEvictableCapability, L as RecordingSignalStatusSchema, Ln as EventCategory, Lt as recordingExportCapability, Mn as object, N as RECORDING_EXPORT_MAX_READ_BYTES, Nn as preprocess, P as RECORDING_SOURCE_CAMSTACK, Pn as record, Rt as recordingSignalCapability, S as ExportRecordSchema, St as mayWriteToLocation, Tn as _enum, Wt as resolveRecordingProfiles, Y as clipExportFailureOf, Yt as stripRetiredBandPreBufferSec, Zt as videoclipsCapability, _t as loadContributionCapability, a as CLIP_BROKER_PACED_RATES, b as EVENT_PAD_MS, bn as nodePin, dt as exportSubjectOf, et as deriveBatteryPresence, gn as hydrateSchema, gt as isFirstLevelMacroClass, h as DEFAULT_EVENTS_BAND_BUFFER_SEC, i as BatteryStatusSchema, jn as number, k as OpsLogEntrySchema, ln as DeviceFeature, lt as evictionPolicyForMode, mn as defineCustomActions, nt as deriveRecordingMode, on as BaseAddon, pn as customAction, pt as gbToBytes, qt as storageOccupancyCapability, st as evaluateSensorEdge, un as DeviceType, ut as evictionPolicyOfLocation, wn as sleep$1, wt as modeMayWrite, xt as mayReadLocation, y as EVENT_OWNER_TYPES, z as VIDEOCLIPS_MAX_OFFER_BYTES } from "../dist-RXbmRAwP.mjs";
2
- import { a as physicalRootOf, i as NO_COST_CLAIM, t as ChildCostRegistry } from "../node-atmRSHPk.mjs";
1
+ import { A as OpsLogEntrySchema, B as VIDEOCLIPS_MAX_OFFER_BYTES, C as ExportRecordSchema, Ct as mayWriteToLocation, Dn as array, En as _enum, F as RECORDING_SOURCE_CAMSTACK, Fn as record, Gt as resolveRecordingProfiles, I as RECORDING_SOURCE_CAMSTACK_ADDON, In as string, It as recordingArchiveCapability, Jt as storageOccupancyCapability, L as RecordingConfigSchema, Lt as recordingCapability, Mn as number, Nn as object, On as boolean, P as RECORDING_EXPORT_MAX_READ_BYTES, Pn as preprocess, Qt as videoclipsCapability, R as RecordingSignalStatusSchema, Rn as EventCategory, Rt as recordingExportCapability, St as mayReadLocation, Tn as sleep$1, Tt as modeMayWrite, Ut as resolveLocationMode, V as VISIT_MERGE_GAP_MS, Vt as resolveCreateExportSubject, X as clipExportFailureOf, Xt as stripRetiredBandPreBufferSec, Y as clipExportFailure, _n as hydrateSchema, _t as isFirstLevelMacroClass, a as BatteryStatusSchema, b as EVENT_OWNER_TYPES, ct as evaluateSensorEdge, dn as DeviceType, dt as evictionPolicyOfLocation, en as errMsg, ft as exportSubjectOf, g as DEFAULT_EVENTS_BAND_BUFFER_SEC, hn as defineCustomActions, mn as customAction, mt as gbToBytes, o as CLIP_BROKER_PACED_RATES, q as batteryCapability, qt as storageEvictableCapability, rt as deriveRecordingMode, sn as BaseAddon, tt as deriveBatteryPresence, un as DeviceFeature, ut as evictionPolicyForMode, vt as loadContributionCapability, wn as selectAssignedProfileSlots, wt as migrateLegacyDeviceSignalConfig, x as EVENT_PAD_MS, xn as nodePin, zt as recordingSignalCapability } from "../dist-CuxSNLKW.mjs";
2
+ import { a as physicalRootOf, i as NO_COST_CLAIM, t as ChildCostRegistry } from "../node-Cqb1QiXk.mjs";
3
3
  import { t as resolveHubHostname } from "../hub-hostname-cCknRYKj.mjs";
4
4
  import { d as PREBUFFER_MAX_MS, l as withRecordingIntent, r as RECORDING_PRE_ROLL_REQUEST_MS } from "../restream-intent-DyGmLAU9.mjs";
5
5
  import { n as RowMapStore, t as retireRootKeys } from "../retire-root-keys-DZvlso2l.mjs";
@@ -5569,6 +5569,16 @@ Object.freeze({
5569
5569
  "priority": 3
5570
5570
  } } },
5571
5571
  "getHistory": { "filter": { "limit": 100 } },
5572
+ "previewStateSummary": { "rule": { "__nested__": {
5573
+ "enabled": true,
5574
+ "conditions": {},
5575
+ "media": { "attach": "best" },
5576
+ "throttle": {
5577
+ "cooldownSec": 60,
5578
+ "scope": "rule-device"
5579
+ },
5580
+ "priority": 3
5581
+ } } },
5572
5582
  "testRule": {
5573
5583
  "rule": { "__nested__": {
5574
5584
  "enabled": true,
@@ -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_child_process = require("node:child_process");
4
4
  //#region src/stream-broker/recorded/avcc-annexb.ts
5
5
  /**
@@ -1,5 +1,5 @@
1
1
  import { r as __toESM, t as __commonJSMin } from "./chunk-DnnnRqeS.mjs";
2
- import { $t as errMsg } from "./dist-RXbmRAwP.mjs";
2
+ import { en as errMsg } from "./dist-CuxSNLKW.mjs";
3
3
  import { spawn } from "node:child_process";
4
4
  //#region src/stream-broker/recorded/avcc-annexb.ts
5
5
  /**
@@ -1,7 +1,7 @@
1
- import { a as e, c as t, d as n, f as r, i, l as a, n as o, o as s, p as c, r as l, s as u, t as d, u as f } from "./_virtual_mf___mfe_internal__addon_stream_broker_widgets__loadShare___mf_0_camstack_mf_1_ui_mf_2_library__loadShare__.js-DoyA71_q.mjs";
1
+ import { a as e, c as t, d as n, f as r, i, l as a, n as o, o as s, p as c, r as l, s as u, t as d, u as f } from "./_virtual_mf___mfe_internal__addon_stream_broker_widgets__loadShare___mf_0_camstack_mf_1_ui_mf_2_library__loadShare__.js-DeD_UFdb.mjs";
2
2
  import { a as p, i as m, n as h, o as g, r as _, t as v } from "./_virtual_mf___mfe_internal__addon_stream_broker_widgets__loadShare__react__loadShare__.js-C9j-2lBe.mjs";
3
3
  import { n as y, r as b, t as x } from "./_virtual_mf___mfe_internal__addon_stream_broker_widgets__loadShare__react_mf_1_jsx_mf_2_runtime__loadShare__.js-XO0-Pyu6.mjs";
4
- import { t as S } from "./_virtual_mf___mfe_internal__addon_stream_broker_widgets__loadShare___mf_0_camstack_mf_1_types__loadShare__.js-6IHzlLJ_.mjs";
4
+ import { t as S } from "./_virtual_mf___mfe_internal__addon_stream_broker_widgets__loadShare___mf_0_camstack_mf_1_types__loadShare__.js-CCIyBvRa.mjs";
5
5
  import { n as C, t as w } from "./_virtual_mf___mfe_internal__addon_stream_broker_widgets__loadShare___mf_0_tanstack_mf_1_react_mf_2_query__loadShare__.js-BO7TIbJV.mjs";
6
6
  //#region ../../node_modules/lucide-react/dist/esm/shared/src/utils/mergeClasses.js
7
7
  var T = (...e) => e.filter((e, t, n) => !!e && e.trim() !== "" && n.indexOf(e) === t).join(" ").trim(), E = (e) => e.replace(/([a-z0-9])([A-Z])/g, "$1-$2").toLowerCase(), D = (e) => e.replace(/^([A-Z])|[\s-_]+(\w)/g, (e, t, n) => n ? n.toUpperCase() : t.toLowerCase()), O = (e) => {
@@ -18,7 +18,7 @@ var e = {
18
18
  },
19
19
  "@camstack/types": {
20
20
  name: "@camstack/types",
21
- version: "1.2.259",
21
+ version: "1.2.260",
22
22
  scope: ["default"],
23
23
  loaded: !1,
24
24
  from: "addon_stream_broker_widgets",
@@ -33,7 +33,7 @@ var e = {
33
33
  },
34
34
  "@camstack/ui-library": {
35
35
  name: "@camstack/ui-library",
36
- version: "1.2.205",
36
+ version: "1.2.206",
37
37
  scope: ["default"],
38
38
  loaded: !1,
39
39
  from: "addon_stream_broker_widgets",