@camstack/addon-pipeline 1.1.69 → 1.1.71

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 (35) hide show
  1. package/dist/audio-analyzer/index.js +1 -1
  2. package/dist/audio-analyzer/index.mjs +1 -1
  3. package/dist/detection-pipeline/index.js +215 -485
  4. package/dist/detection-pipeline/index.mjs +216 -485
  5. package/dist/{dist-BT4Ug2Bf.mjs → dist-DyALtmD7.mjs} +240 -45
  6. package/dist/{dist-DUcDVlg7.js → dist-DzTjxf39.js} +251 -44
  7. package/dist/motion-wasm/index.js +1 -1
  8. package/dist/motion-wasm/index.mjs +1 -1
  9. package/dist/pipeline-runner/index.js +24 -2
  10. package/dist/pipeline-runner/index.mjs +24 -2
  11. package/dist/recorder/index.js +1 -1
  12. package/dist/recorder/index.mjs +1 -1
  13. package/dist/session-decode/decode-worker-child.js +177 -12
  14. package/dist/session-decode/decode-worker-child.mjs +177 -12
  15. package/dist/{step-definitions-4tt-nRM4.js → step-definitions-Djy8aZLt.js} +6 -2
  16. package/dist/{step-definitions-DO0hIDMx.mjs → step-definitions-rmBALHX4.mjs} +6 -2
  17. package/dist/stream-broker/_stub.js +2 -2
  18. package/dist/stream-broker/{_virtual_mf-localSharedImportMap___mfe_internal__addon_stream_broker_widgets-CP4DpABx.mjs → _virtual_mf-localSharedImportMap___mfe_internal__addon_stream_broker_widgets-CMP316sx.mjs} +2 -2
  19. package/dist/stream-broker/_virtual_mf___mfe_internal__addon_stream_broker_widgets__loadShare___mf_0_camstack_mf_1_types__loadShare__.js-BflyNuZv.mjs +26 -0
  20. package/dist/stream-broker/_virtual_mf___mfe_internal__addon_stream_broker_widgets__loadShare___mf_0_camstack_mf_1_ui_mf_2_library__loadShare__.js-5Zc9wj-A.mjs +26 -0
  21. package/dist/stream-broker/{hostInit-Do2ymS0O.mjs → hostInit-DLJNx0Ly.mjs} +2 -2
  22. package/dist/stream-broker/index.js +1 -1
  23. package/dist/stream-broker/index.mjs +1 -1
  24. package/dist/stream-broker/remoteEntry.js +1 -1
  25. package/embed-dist/assets/{MaskShapeCanvas-DI4BY7W2-DlI3udxg.js → MaskShapeCanvas-DI4BY7W2-sOOxiGvP.js} +1 -1
  26. package/embed-dist/assets/{MotionZonesSettings-NcxxQN8r-Du8J0kED.js → MotionZonesSettings-NcxxQN8r-DdTQuT23.js} +1 -1
  27. package/embed-dist/assets/{PrivacyMaskSettings-APgPLF7p-DSST47WI.js → PrivacyMaskSettings-APgPLF7p-BrR0L3ql.js} +1 -1
  28. package/embed-dist/assets/index-D4MGuECB.css +2 -0
  29. package/embed-dist/assets/{index-B2ux2xJ7.js → index-Dk21l1_3.js} +14 -14
  30. package/embed-dist/index.html +2 -2
  31. package/package.json +1 -1
  32. package/python/inference_pool.py +30 -5
  33. package/dist/stream-broker/_virtual_mf___mfe_internal__addon_stream_broker_widgets__loadShare___mf_0_camstack_mf_1_types__loadShare__.js-D68Lj69v.mjs +0 -26
  34. package/dist/stream-broker/_virtual_mf___mfe_internal__addon_stream_broker_widgets__loadShare___mf_0_camstack_mf_1_ui_mf_2_library__loadShare__.js-DlALQ_wp.mjs +0 -26
  35. package/embed-dist/assets/index-D2pF9Z3W.css +0 -2
@@ -7924,6 +7924,24 @@ function nodePin(nodeId) {
7924
7924
  function hfModelUrl(repo, path) {
7925
7925
  return `https://huggingface.co/${repo}/resolve/main/${path}`;
7926
7926
  }
7927
+ /**
7928
+ * DEVICE-POOL backend → model format — the SSOT for the multi-device inference
7929
+ * DESCRIPTOR path (Python per-device pools), distinct from {@link BACKEND_TO_FORMAT}
7930
+ * above which is the legacy NODE runtime map (where `coreml → onnx` because
7931
+ * onnxruntime-node's CoreML EP loads `.onnx`). Here a device pool runs the
7932
+ * backend NATIVELY, so `coreml → coreml` and `edgetpu → tflite`. Consumed by
7933
+ * `resolveDeviceEngine` (addon-pipeline) and the orchestrator's
7934
+ * `parseDeviceKey`/`getNodeInferenceDevices` — the previously-duplicated
7935
+ * `BACKEND_FORMAT` maps (R3/node-F2). `cpu`/`cuda` floor to onnx.
7936
+ */
7937
+ var DEVICE_BACKEND_TO_FORMAT = {
7938
+ openvino: "openvino",
7939
+ edgetpu: "tflite",
7940
+ coreml: "coreml",
7941
+ onnx: "onnx",
7942
+ cpu: "onnx",
7943
+ cuda: "onnx"
7944
+ };
7927
7945
  var COCO_80_LABELS = [
7928
7946
  {
7929
7947
  id: "person",
@@ -11941,20 +11959,6 @@ var pipelineExecutorCapability = {
11941
11959
  getSelectedEngine: method(_void(), PipelineEngineChoiceSchema),
11942
11960
  getDefaultSteps: method(PipelineEngineChoiceSchema, array(PipelineDefaultStepSchema)),
11943
11961
  /**
11944
- * Re-run the platform probe for the inference engine and write the
11945
- * detected runtime / backend / device back into the addon's own
11946
- * global settings store. Returns the engine that was picked so the
11947
- * UI can confirm without a second round-trip. Triggers the standard
11948
- * `requiresRestart` auto-restart flow because all three fields are
11949
- * marked restart-required. Replaces the legacy per-agent
11950
- * `pipeline-orchestrator.reprobeAgentHwAccel` surface for the
11951
- * engine dimension — each addon now owns its own probe.
11952
- */
11953
- reprobeEngine: method(_void(), PipelineEngineChoiceSchema, {
11954
- kind: "mutation",
11955
- auth: "admin"
11956
- }),
11957
- /**
11958
11962
  * Per-node detection-engine provisioning snapshot. Returns the live
11959
11963
  * state of the lazy runtime-provisioning machine on `nodeId`
11960
11964
  * (idle / installing / verifying / ready / failed). The UI pairs this
@@ -12585,6 +12589,19 @@ var RunnerLocalLoadSchema = object({
12585
12589
  avgInferenceTimeMs: number(),
12586
12590
  /** Total queue depth across motion + detection queues. */
12587
12591
  queueDepthTotal: number(),
12592
+ /**
12593
+ * Per-inference-device live load (multi-device C4). One entry per deviceKey
12594
+ * this runner currently has attached cameras on, so the orchestrator's second
12595
+ * `balance()` pass (over a node's devices) weights on real per-pool session
12596
+ * counts. Empty on single-device / pre-multi-device runners. `queueDepthTotal`
12597
+ * per device is 0 until the pool backlog gets a public accessor (follow-up).
12598
+ */
12599
+ devices: array(object({
12600
+ deviceKey: string(),
12601
+ backend: string(),
12602
+ attachedCameras: number(),
12603
+ queueDepthTotal: number()
12604
+ })).default([]),
12588
12605
  /** Hardware capability flags reported by this node. */
12589
12606
  hardware: object({
12590
12607
  hasGpu: boolean(),
@@ -18016,13 +18033,11 @@ var PipelineTemplateSchema = object({
18016
18033
  createdAt: string(),
18017
18034
  updatedAt: string()
18018
18035
  });
18019
- var AgentAddonConfigSchema = object({
18020
- enabled: boolean(),
18036
+ var DeviceStepConfigSchema = object({
18021
18037
  modelId: string().optional(),
18022
- settings: record(string(), unknown()).readonly()
18038
+ settings: record(string(), unknown()).optional()
18023
18039
  });
18024
18040
  var AgentPipelineSettingsSchema = object({
18025
- addonDefaults: record(string(), AgentAddonConfigSchema).readonly(),
18026
18041
  maxCameras: number().int().nonnegative().nullable().default(null),
18027
18042
  /** Per-node detection weight (relative share for the quota balancer). */
18028
18043
  detectWeight: number().positive().optional(),
@@ -18049,13 +18064,18 @@ var AgentPipelineSettingsSchema = object({
18049
18064
  reachableHost: string().optional(),
18050
18065
  /**
18051
18066
  * Multi-device inference opt-in (Phase 4). Per-node map deviceKey → {enabled,
18052
- * weight}. Absent / all-disabled ⇒ the node's single default accelerator
18053
- * (safe default); two+ enabled ⇒ the dispatcher balances detection sessions
18054
- * across them so they run CONCURRENTLY.
18067
+ * weight, steps}. Absent / all-disabled ⇒ the node's single default
18068
+ * accelerator (safe default); two+ enabled ⇒ the dispatcher balances
18069
+ * detection sessions across them so they run CONCURRENTLY. `steps` is the
18070
+ * per-(node,device) BASE provisioning (`stepId → {modelId?, settings?}`) —
18071
+ * the default model/settings for every camera landing on that accelerator;
18072
+ * a stepId absent ⇒ the step uses that device's format default.
18055
18073
  */
18056
18074
  inferenceDevices: record(string(), object({
18057
18075
  enabled: boolean(),
18058
- weight: number().positive().optional()
18076
+ weight: number().positive().optional(),
18077
+ maxSessions: number().int().positive().optional(),
18078
+ steps: record(string(), DeviceStepConfigSchema).optional()
18059
18079
  })).optional()
18060
18080
  });
18061
18081
  var CameraPipelineForAgentSchema = object({
@@ -18066,14 +18086,13 @@ var CameraPipelineForAgentSchema = object({
18066
18086
  }).nullable()
18067
18087
  });
18068
18088
  var CameraStepOverridePatchSchema = object({
18069
- enabled: boolean().optional(),
18070
18089
  modelId: string().optional(),
18071
18090
  settings: record(string(), unknown()).readonly().optional()
18072
18091
  });
18073
18092
  var CameraPipelineSettingsSchema = object({
18074
18093
  pinnedAgentNodeId: string().optional(),
18075
18094
  stepToggles: record(string(), boolean()).optional(),
18076
- stepOverridesByAgent: record(string(), record(string(), CameraStepOverridePatchSchema)).optional(),
18095
+ stepOverridesByDevice: record(string(), record(string(), record(string(), CameraStepOverridePatchSchema))).optional(),
18077
18096
  pipelineByAgent: record(string(), CameraPipelineForAgentSchema).optional()
18078
18097
  });
18079
18098
  /**
@@ -18287,6 +18306,44 @@ var CameraStatusSchema = object({
18287
18306
  /** Unix timestamp (ms) when this snapshot was composed server-side. */
18288
18307
  fetchedAt: number()
18289
18308
  });
18309
+ var NodeInferenceDeviceSchema = object({
18310
+ /** Stable per-node device key, e.g. `openvino:npu`, `edgetpu:usb`, `cpu`. */
18311
+ key: string(),
18312
+ backend: string(),
18313
+ device: string(),
18314
+ format: _enum(MODEL_FORMATS),
18315
+ /** Whether the node's live probe reports the device as usable right now. */
18316
+ available: boolean(),
18317
+ /**
18318
+ * Whether this device participates in dispatch. AUTO default (spec C2):
18319
+ * accelerators are opt-OUT (a discovered NPU/iGPU/Coral/ANE with no stored
18320
+ * entry is `true`); CPU is opt-IN (`false` by default — the fallback pool,
18321
+ * not a balanced target). An explicit stored value always wins; a stored-only
18322
+ * (unavailable) key keeps its stored value.
18323
+ */
18324
+ enabled: boolean(),
18325
+ /** Relative balancer weight for the enabled device (default 1). */
18326
+ weight: number(),
18327
+ /** Per-device concurrent-session cap; null = unlimited (multi-device C4). */
18328
+ maxSessions: number().nullable(),
18329
+ /** Object-detection model the executor defaults to for this deviceKey. */
18330
+ defaultModelId: string(),
18331
+ /**
18332
+ * Per-(node,device) BASE provisioning (C7.2/C7.4) — the RAW stored
18333
+ * `stepId → {modelId?, settings?}` map from `inferenceDevices[key].steps`.
18334
+ * Absent/empty ⇒ no base (every step uses its device format default). The
18335
+ * UI cross-references `pipelineExecutor.getSchema` for the models actually
18336
+ * available per format; this is the stored selection that becomes the
18337
+ * default for EVERY camera landing on this accelerator.
18338
+ */
18339
+ steps: record(string(), DeviceStepConfigSchema).optional()
18340
+ });
18341
+ var NodeInferenceDevicesSchema = object({
18342
+ nodeId: string(),
18343
+ /** False when the node's platform-probe was unreachable (no live device set). */
18344
+ reachable: boolean(),
18345
+ devices: array(NodeInferenceDeviceSchema).readonly()
18346
+ });
18290
18347
  method(object({
18291
18348
  deviceId: number(),
18292
18349
  agentNodeId: string()
@@ -18296,7 +18353,13 @@ method(object({
18296
18353
  }), method(object({ deviceId: number() }), object({ success: literal(true) }), {
18297
18354
  kind: "mutation",
18298
18355
  auth: "admin"
18299
- }), method(_void(), object({ migrated: number() }), {
18356
+ }), method(object({
18357
+ deviceId: number(),
18358
+ deviceKey: string()
18359
+ }), object({ success: literal(true) }), {
18360
+ kind: "mutation",
18361
+ auth: "admin"
18362
+ }), method(object({ deviceId: number() }), object({ deviceKey: string().nullable() })), method(_void(), object({ migrated: number() }), {
18300
18363
  kind: "mutation",
18301
18364
  auth: "admin"
18302
18365
  }), method(_void(), array(PipelineAssignmentSchema).readonly()), method(object({ deviceId: number() }), PipelineAssignmentSchema.nullable()), method(_void(), array(AgentLoadSummarySchema).readonly()), method(_void(), GlobalMetricsSchema), method(object({ deviceId: number() }), CameraMetricsSchema.nullable()), method(object({ nodeId: string() }), CapabilityBindingsSchema), method(object({
@@ -18330,13 +18393,7 @@ method(object({
18330
18393
  }))), method(object({ agentNodeId: string() }), AgentPipelineSettingsSchema.nullable()), method(_void(), array(object({
18331
18394
  nodeId: string(),
18332
18395
  settings: AgentPipelineSettingsSchema
18333
- })).readonly()), method(object({
18334
- agentNodeId: string(),
18335
- defaults: record(string(), AgentAddonConfigSchema)
18336
- }), object({ success: literal(true) }), {
18337
- kind: "mutation",
18338
- auth: "admin"
18339
- }), method(object({ agentNodeId: string() }), object({
18396
+ })).readonly()), method(object({ agentNodeId: string() }), object({
18340
18397
  success: boolean(),
18341
18398
  removed: boolean()
18342
18399
  }), {
@@ -18368,7 +18425,18 @@ method(object({
18368
18425
  }), object({ success: literal(true) }), {
18369
18426
  kind: "mutation",
18370
18427
  auth: "admin"
18371
- }), method(object({ agentNodeId: string() }), object({
18428
+ }), method(object({
18429
+ agentNodeId: string(),
18430
+ inferenceDevices: record(string(), object({
18431
+ enabled: boolean(),
18432
+ weight: number().positive().optional(),
18433
+ maxSessions: number().int().positive().optional(),
18434
+ steps: record(string(), DeviceStepConfigSchema).optional()
18435
+ }))
18436
+ }), object({ success: literal(true) }), {
18437
+ kind: "mutation",
18438
+ auth: "admin"
18439
+ }), method(object({ nodeId: string() }), NodeInferenceDevicesSchema), method(object({ agentNodeId: string() }), object({
18372
18440
  success: literal(true),
18373
18441
  /** Hardware-aware default detection model now in effect on the node (null when unresolvable). */
18374
18442
  effectiveModelId: string().nullable(),
@@ -18384,9 +18452,10 @@ method(object({
18384
18452
  }), object({ success: literal(true) }), {
18385
18453
  kind: "mutation",
18386
18454
  auth: "admin"
18387
- }), method(object({ deviceId: number() }), record(string(), record(string(), CameraStepOverridePatchSchema)).nullable()), method(object({
18455
+ }), method(object({ deviceId: number() }), record(string(), record(string(), record(string(), CameraStepOverridePatchSchema))).nullable()), method(object({
18388
18456
  deviceId: number(),
18389
18457
  agentNodeId: string(),
18458
+ deviceKey: string(),
18390
18459
  addonId: string(),
18391
18460
  patch: CameraStepOverridePatchSchema.nullable()
18392
18461
  }), object({ success: literal(true) }), {
@@ -18538,7 +18607,8 @@ method(_void(), ServerPackageStatusSchema, { auth: "admin" }), method(_void(), S
18538
18607
  /** Explicit target version; omitted = latest from the registry. */
18539
18608
  version: string().optional() }), ServerUpdateActionResultSchema, {
18540
18609
  kind: "mutation",
18541
- auth: "admin"
18610
+ auth: "admin",
18611
+ timeoutMs: 16 * 6e4
18542
18612
  }), method(_void(), ServerUpdateActionResultSchema, {
18543
18613
  kind: "mutation",
18544
18614
  auth: "admin"
@@ -24795,12 +24865,6 @@ Object.freeze({
24795
24865
  addonId: null,
24796
24866
  access: "view"
24797
24867
  },
24798
- "pipelineExecutor.reprobeEngine": {
24799
- capName: "pipeline-executor",
24800
- capScope: "system",
24801
- addonId: null,
24802
- access: "create"
24803
- },
24804
24868
  "pipelineExecutor.runAudioTest": {
24805
24869
  capName: "pipeline-executor",
24806
24870
  capScope: "system",
@@ -24951,6 +25015,12 @@ Object.freeze({
24951
25015
  addonId: null,
24952
25016
  access: "view"
24953
25017
  },
25018
+ "pipelineOrchestrator.getNodeInferenceDevices": {
25019
+ capName: "pipeline-orchestrator",
25020
+ capScope: "system",
25021
+ addonId: null,
25022
+ access: "view"
25023
+ },
24954
25024
  "pipelineOrchestrator.getPipelineAssignment": {
24955
25025
  capName: "pipeline-orchestrator",
24956
25026
  capScope: "system",
@@ -24963,6 +25033,12 @@ Object.freeze({
24963
25033
  addonId: null,
24964
25034
  access: "view"
24965
25035
  },
25036
+ "pipelineOrchestrator.getPipelineDevicePin": {
25037
+ capName: "pipeline-orchestrator",
25038
+ capScope: "system",
25039
+ addonId: null,
25040
+ access: "view"
25041
+ },
24966
25042
  "pipelineOrchestrator.listAgentSettings": {
24967
25043
  capName: "pipeline-orchestrator",
24968
25044
  capScope: "system",
@@ -25005,19 +25081,19 @@ Object.freeze({
25005
25081
  addonId: null,
25006
25082
  access: "create"
25007
25083
  },
25008
- "pipelineOrchestrator.setAgentAddonDefaults": {
25084
+ "pipelineOrchestrator.setAgentCapabilities": {
25009
25085
  capName: "pipeline-orchestrator",
25010
25086
  capScope: "system",
25011
25087
  addonId: null,
25012
25088
  access: "create"
25013
25089
  },
25014
- "pipelineOrchestrator.setAgentCapabilities": {
25090
+ "pipelineOrchestrator.setAgentDetectWeight": {
25015
25091
  capName: "pipeline-orchestrator",
25016
25092
  capScope: "system",
25017
25093
  addonId: null,
25018
25094
  access: "create"
25019
25095
  },
25020
- "pipelineOrchestrator.setAgentDetectWeight": {
25096
+ "pipelineOrchestrator.setAgentInferenceDevices": {
25021
25097
  capName: "pipeline-orchestrator",
25022
25098
  capScope: "system",
25023
25099
  addonId: null,
@@ -25059,6 +25135,12 @@ Object.freeze({
25059
25135
  addonId: null,
25060
25136
  access: "create"
25061
25137
  },
25138
+ "pipelineOrchestrator.setPipelineDevicePin": {
25139
+ capName: "pipeline-orchestrator",
25140
+ capScope: "system",
25141
+ addonId: null,
25142
+ access: "create"
25143
+ },
25062
25144
  "pipelineOrchestrator.unassignAudio": {
25063
25145
  capName: "pipeline-orchestrator",
25064
25146
  capScope: "system",
@@ -26813,6 +26895,119 @@ function runtimeDevices(id, hw) {
26813
26895
  function defaultDeviceFor(id) {
26814
26896
  return def(id).defaultDevice;
26815
26897
  }
26898
+ /**
26899
+ * Scores all applicable inference backends for the given hardware.
26900
+ *
26901
+ * Rules (hardware-driven only — no Python import probes):
26902
+ * - coreml: score 95, darwin+arm64
26903
+ * - cuda: score 85, nvidia gpu
26904
+ * - openvino: score 90 if intel-npu present, else 80 if intel gpu
26905
+ * - edgetpu: score 70, coral usb present
26906
+ * - cpu: score 50 (universal floor, always included)
26907
+ *
26908
+ * All hardware-matched entries are `available: true`.
26909
+ * Scores are sorted descending; `best` is the first available entry
26910
+ * (or last entry as fallback).
26911
+ */
26912
+ function scoreRuntimes(hw) {
26913
+ const scores = [];
26914
+ if (hw.platform === "darwin" && hw.arch === "arm64") scores.push({
26915
+ runtime: "python",
26916
+ backend: "coreml",
26917
+ format: "coreml",
26918
+ score: 95,
26919
+ reason: "Apple Neural Engine (Python CoreML)",
26920
+ available: true
26921
+ });
26922
+ if (hw.gpu?.type === "nvidia") scores.push({
26923
+ runtime: "python",
26924
+ backend: "cuda",
26925
+ format: "onnx",
26926
+ score: 85,
26927
+ reason: "NVIDIA CUDA (Python ONNX Runtime)",
26928
+ available: true
26929
+ });
26930
+ if (hw.gpu?.type === "intel") {
26931
+ const score = hw.npu?.type === "intel-npu" ? 90 : 80;
26932
+ scores.push({
26933
+ runtime: "python",
26934
+ backend: "openvino",
26935
+ format: "openvino",
26936
+ score,
26937
+ reason: "Intel OpenVINO",
26938
+ available: true
26939
+ });
26940
+ }
26941
+ if (hw.coral != null) scores.push({
26942
+ runtime: "python",
26943
+ backend: "edgetpu",
26944
+ format: "tflite",
26945
+ score: 70,
26946
+ reason: "Coral Edge TPU (Python LiteRT)",
26947
+ available: true
26948
+ });
26949
+ scores.push({
26950
+ runtime: "python",
26951
+ backend: "cpu",
26952
+ format: "onnx",
26953
+ score: 50,
26954
+ reason: "CPU (Python ONNX Runtime)",
26955
+ available: true
26956
+ });
26957
+ const sorted = scores.toSorted((a, b) => b.score - a.score);
26958
+ return {
26959
+ scores: sorted,
26960
+ best: sorted.find((s) => s.available) ?? sorted[sorted.length - 1]
26961
+ };
26962
+ }
26963
+ var DEVICE_FOR_BACKEND = {
26964
+ cuda: "gpu",
26965
+ edgetpu: "usb",
26966
+ coreml: "all",
26967
+ cpu: "cpu"
26968
+ };
26969
+ function device(backend, dev, format, score) {
26970
+ return {
26971
+ key: backend === "cpu" ? "cpu" : `${backend}:${dev}`,
26972
+ backend,
26973
+ device: dev,
26974
+ format,
26975
+ runtime: "python",
26976
+ score,
26977
+ available: true
26978
+ };
26979
+ }
26980
+ /**
26981
+ * Enumerate every usable inference device on a node — one descriptor PER PHYSICAL
26982
+ * ACCELERATOR, so the orchestrator can run and balance across all of them
26983
+ * CONCURRENTLY (each device is its own pool). Critically, OpenVINO is expanded
26984
+ * into its distinct devices (NPU / iGPU / CPU) rather than a single AUTO entry:
26985
+ * the Intel NPU ("AI Boost") and the iGPU are separate accelerators and run in
26986
+ * parallel — collapsing them to AUTO would leave one idle. NPU is scored above
26987
+ * the iGPU (faster for int8 detection AND frees the GPU).
26988
+ */
26989
+ function enumerateInferenceDevices(hw) {
26990
+ const { scores } = scoreRuntimes(hw);
26991
+ const out = [];
26992
+ for (const s of scores) {
26993
+ if (s.backend === "openvino") {
26994
+ if (hw.npu?.type === "intel-npu") out.push(device("openvino", "npu", s.format, s.score + 2));
26995
+ if (hw.gpu?.type === "intel") out.push(device("openvino", "gpu", s.format, s.score));
26996
+ continue;
26997
+ }
26998
+ if (s.backend === "edgetpu") {
26999
+ const coralCount = Math.max(1, hw.coral?.count ?? 1);
27000
+ for (let i = 0; i < coralCount; i++) {
27001
+ const dev = i === 0 ? "usb" : `usb:${i}`;
27002
+ out.push(device("edgetpu", dev, s.format, s.score));
27003
+ }
27004
+ continue;
27005
+ }
27006
+ const dev = DEVICE_FOR_BACKEND[s.backend] ?? s.backend;
27007
+ out.push(device(s.backend, dev, s.format, s.score));
27008
+ }
27009
+ return out;
27010
+ }
26816
27011
  //#endregion
26817
27012
  Object.defineProperty(exports, "APPLE_SA_TO_MACRO", {
26818
27013
  enumerable: true,
@@ -26862,6 +27057,12 @@ Object.defineProperty(exports, "DEFAULT_AUDIO_ANALYZER_CONFIG", {
26862
27057
  return DEFAULT_AUDIO_ANALYZER_CONFIG;
26863
27058
  }
26864
27059
  });
27060
+ Object.defineProperty(exports, "DEVICE_BACKEND_TO_FORMAT", {
27061
+ enumerable: true,
27062
+ get: function() {
27063
+ return DEVICE_BACKEND_TO_FORMAT;
27064
+ }
27065
+ });
26865
27066
  Object.defineProperty(exports, "DeviceFeature", {
26866
27067
  enumerable: true,
26867
27068
  get: function() {
@@ -27006,6 +27207,12 @@ Object.defineProperty(exports, "discriminatedUnion", {
27006
27207
  return discriminatedUnion;
27007
27208
  }
27008
27209
  });
27210
+ Object.defineProperty(exports, "enumerateInferenceDevices", {
27211
+ enumerable: true,
27212
+ get: function() {
27213
+ return enumerateInferenceDevices;
27214
+ }
27215
+ });
27009
27216
  Object.defineProperty(exports, "errMsg", {
27010
27217
  enumerable: true,
27011
27218
  get: function() {
@@ -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-DUcDVlg7.js");
5
+ const require_dist = require("../dist-DzTjxf39.js");
6
6
  let node_fs = require("node:fs");
7
7
  let node_path = require("node:path");
8
8
  //#region src/motion-wasm/wasm-motion-detector.ts
@@ -1,4 +1,4 @@
1
- import { C as evaluateZoneRules, K as hydrateSchema, O as motionDetectionCapability, V as BaseAddon, W as DeviceType } from "../dist-BT4Ug2Bf.mjs";
1
+ import { A as motionDetectionCapability, J as hydrateSchema, K as DeviceType, T as evaluateZoneRules, U as BaseAddon } from "../dist-DyALtmD7.mjs";
2
2
  import { readFileSync } from "node:fs";
3
3
  import { join } from "node:path";
4
4
  //#region src/motion-wasm/wasm-motion-detector.ts
@@ -3,11 +3,11 @@ Object.defineProperties(exports, {
3
3
  [Symbol.toStringTag]: { value: "Module" }
4
4
  });
5
5
  const require_chunk = require("../chunk-D6vf50IK.js");
6
- const require_dist = require("../dist-DUcDVlg7.js");
6
+ const require_dist = require("../dist-DzTjxf39.js");
7
7
  const require_remote_restream = require("../remote-restream-CO36Sr30.js");
8
8
  const require_sheet_geometry = require("../sheet-geometry-BR-ip0CP.js");
9
9
  const require_worker_protocol = require("../worker-protocol-PP4jKHHJ.js");
10
- const require_step_definitions = require("../step-definitions-4tt-nRM4.js");
10
+ const require_step_definitions = require("../step-definitions-Djy8aZLt.js");
11
11
  let node_child_process = require("node:child_process");
12
12
  let node_url = require("node:url");
13
13
  let sharp = require("sharp");
@@ -1132,6 +1132,26 @@ var PipelineRunner = class {
1132
1132
  }
1133
1133
  };
1134
1134
  //#endregion
1135
+ //#region src/pipeline-runner/device-load.ts
1136
+ /** The backend prefix of a `<backend>:<device>` key (bare `cpu` → `cpu`). */
1137
+ function backendOf(deviceKey) {
1138
+ const colon = deviceKey.indexOf(":");
1139
+ return colon >= 0 ? deviceKey.slice(0, colon) : deviceKey;
1140
+ }
1141
+ function summarizeDeviceLoad(attachedDeviceKeys) {
1142
+ const counts = /* @__PURE__ */ new Map();
1143
+ for (const key of attachedDeviceKeys) {
1144
+ if (!key) continue;
1145
+ counts.set(key, (counts.get(key) ?? 0) + 1);
1146
+ }
1147
+ return Array.from(counts.entries()).map(([deviceKey, attachedCameras]) => ({
1148
+ deviceKey,
1149
+ backend: backendOf(deviceKey),
1150
+ attachedCameras,
1151
+ queueDepthTotal: 0
1152
+ })).toSorted((a, b) => a.deviceKey.localeCompare(b.deviceKey));
1153
+ }
1154
+ //#endregion
1135
1155
  //#region src/session-decode/fork-decode-worker.ts
1136
1156
  /**
1137
1157
  * Real `fork` implementation for the session-decode coordinator — Epic C P1,
@@ -3459,6 +3479,7 @@ var PipelineRunnerAddon = class extends require_dist.BaseAddon {
3459
3479
  if (cm.phase === "active") activeCameras++;
3460
3480
  totalActualFps += cm.actualFps;
3461
3481
  }
3482
+ const devices = summarizeDeviceLoad(Array.from(this.attached.values(), (cam) => cam.config.deviceKey));
3462
3483
  return {
3463
3484
  nodeId: this.nodeId,
3464
3485
  attachedCameras: this.attached.size,
@@ -3466,6 +3487,7 @@ var PipelineRunnerAddon = class extends require_dist.BaseAddon {
3466
3487
  avgInferenceFps: totalActualFps,
3467
3488
  avgInferenceTimeMs: metrics.avgInferenceTimeMs,
3468
3489
  queueDepthTotal: metrics.queueDepth,
3490
+ devices,
3469
3491
  hardware: {
3470
3492
  hasGpu: false,
3471
3493
  inferenceBackend: void 0
@@ -1,8 +1,8 @@
1
- import { B as errMsg, G as createEvent, V as BaseAddon, dt as EventCategory, et as _enum, it as lazy, j as pipelineRunnerCapability, k as nodePin, lt as string, nt as boolean, ot as number, st as object, tt as array, x as defineCustomActions, y as customAction } from "../dist-BT4Ug2Bf.mjs";
1
+ import { H as errMsg, N as pipelineRunnerCapability, S as defineCustomActions, U as BaseAddon, b as customAction, ct as number, dt as string, it as boolean, j as nodePin, lt as object, nt as _enum, ot as lazy, pt as EventCategory, q as createEvent, rt as array } from "../dist-DyALtmD7.mjs";
2
2
  import { n as profileForStreamId, t as isRemoteRestream } from "../remote-restream-BeHi78PZ.mjs";
3
3
  import { r as resolveHubHostname } from "../sheet-geometry-DcpuGTCm.mjs";
4
4
  import { t as isWorkerReply } from "../worker-protocol-CyVJTZEO.mjs";
5
- import { a as getStepDefinition } from "../step-definitions-DO0hIDMx.mjs";
5
+ import { a as getStepDefinition } from "../step-definitions-rmBALHX4.mjs";
6
6
  import { fork } from "node:child_process";
7
7
  import { fileURLToPath } from "node:url";
8
8
  import sharp from "sharp";
@@ -1126,6 +1126,26 @@ var PipelineRunner = class {
1126
1126
  }
1127
1127
  };
1128
1128
  //#endregion
1129
+ //#region src/pipeline-runner/device-load.ts
1130
+ /** The backend prefix of a `<backend>:<device>` key (bare `cpu` → `cpu`). */
1131
+ function backendOf(deviceKey) {
1132
+ const colon = deviceKey.indexOf(":");
1133
+ return colon >= 0 ? deviceKey.slice(0, colon) : deviceKey;
1134
+ }
1135
+ function summarizeDeviceLoad(attachedDeviceKeys) {
1136
+ const counts = /* @__PURE__ */ new Map();
1137
+ for (const key of attachedDeviceKeys) {
1138
+ if (!key) continue;
1139
+ counts.set(key, (counts.get(key) ?? 0) + 1);
1140
+ }
1141
+ return Array.from(counts.entries()).map(([deviceKey, attachedCameras]) => ({
1142
+ deviceKey,
1143
+ backend: backendOf(deviceKey),
1144
+ attachedCameras,
1145
+ queueDepthTotal: 0
1146
+ })).toSorted((a, b) => a.deviceKey.localeCompare(b.deviceKey));
1147
+ }
1148
+ //#endregion
1129
1149
  //#region src/session-decode/fork-decode-worker.ts
1130
1150
  /**
1131
1151
  * Real `fork` implementation for the session-decode coordinator — Epic C P1,
@@ -3453,6 +3473,7 @@ var PipelineRunnerAddon = class extends BaseAddon {
3453
3473
  if (cm.phase === "active") activeCameras++;
3454
3474
  totalActualFps += cm.actualFps;
3455
3475
  }
3476
+ const devices = summarizeDeviceLoad(Array.from(this.attached.values(), (cam) => cam.config.deviceKey));
3456
3477
  return {
3457
3478
  nodeId: this.nodeId,
3458
3479
  attachedCameras: this.attached.size,
@@ -3460,6 +3481,7 @@ var PipelineRunnerAddon = class extends BaseAddon {
3460
3481
  avgInferenceFps: totalActualFps,
3461
3482
  avgInferenceTimeMs: metrics.avgInferenceTimeMs,
3462
3483
  queueDepthTotal: metrics.queueDepth,
3484
+ devices,
3463
3485
  hardware: {
3464
3486
  hasGpu: false,
3465
3487
  inferenceBackend: void 0
@@ -1,5 +1,5 @@
1
1
  const require_chunk = require("../chunk-D6vf50IK.js");
2
- const require_dist = require("../dist-DUcDVlg7.js");
2
+ const require_dist = require("../dist-DzTjxf39.js");
3
3
  const require_sheet_geometry = require("../sheet-geometry-BR-ip0CP.js");
4
4
  const require_model_download_service_Cp9f4dk6 = require("../model-download-service-Cp9f4dk6-Dv-oFwjN.js");
5
5
  let node_child_process = require("node:child_process");
@@ -1,4 +1,4 @@
1
- import { B as errMsg, D as migrateConfigToBands, I as storageEvictableCapability, K as hydrateSchema, M as recordingCapability, N as recordingExportCapability, P as resolveScrubThumbnailGeometry, Q as selectAssignedProfileSlots, V as BaseAddon, W as DeviceType, ct as record, d as OpsLogEntrySchema, dt as EventCategory, f as RecordingConfigSchema, k as nodePin, l as ExportRecordSchema, lt as string, q as isEvent, s as EVENT_PAD_MS, tt as array } from "../dist-BT4Ug2Bf.mjs";
1
+ import { F as recordingExportCapability, H as errMsg, I as resolveScrubThumbnailGeometry, J as hydrateSchema, K as DeviceType, P as recordingCapability, R as storageEvictableCapability, U as BaseAddon, Y as isEvent, c as EVENT_PAD_MS, dt as string, et as selectAssignedProfileSlots, f as OpsLogEntrySchema, j as nodePin, k as migrateConfigToBands, p as RecordingConfigSchema, pt as EventCategory, rt as array, u as ExportRecordSchema, ut as record } from "../dist-DyALtmD7.mjs";
2
2
  import { n as computeSheetGeometry, r as resolveHubHostname, t as allTilePlacements } from "../sheet-geometry-DcpuGTCm.mjs";
3
3
  import { n as createFileDataPlaneHandler, s as parseRangeHeader, t as contentTypeFor } from "../model-download-service-Cp9f4dk6-CwUb5v3Y.mjs";
4
4
  import { spawn } from "node:child_process";