@camstack/addon-pipeline 1.1.56 → 1.1.57

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/dist/audio-analyzer/index.js +2 -2
  2. package/dist/audio-analyzer/index.mjs +2 -2
  3. package/dist/detection-pipeline/index.js +71 -74
  4. package/dist/detection-pipeline/index.mjs +70 -73
  5. package/dist/{dist-ClE6_i0p.js → dist-CK8Ur-OS.js} +104 -6
  6. package/dist/{dist-CrjLGrkj.mjs → dist-CL531uVA.mjs} +104 -6
  7. package/dist/motion-wasm/index.js +9 -41
  8. package/dist/motion-wasm/index.mjs +9 -41
  9. package/dist/pipeline-runner/index.js +222 -656
  10. package/dist/pipeline-runner/index.mjs +211 -647
  11. package/dist/recorder/index.js +2 -2
  12. package/dist/recorder/index.mjs +2 -2
  13. package/dist/remote-restream-BeHi78PZ.mjs +25 -0
  14. package/dist/remote-restream-CO36Sr30.js +36 -0
  15. package/dist/{step-definitions-dCghpdRo.mjs → step-definitions-1d3_vQ6S.mjs} +44 -2
  16. package/dist/{step-definitions-C9kUXgC7.js → step-definitions-DHAxruAQ.js} +44 -2
  17. package/dist/stream-broker/_stub.js +282 -222
  18. package/dist/stream-broker/{_virtual_mf-localSharedImportMap___mfe_internal__addon_stream_broker_widgets-D4xH4Tm-.mjs → _virtual_mf-localSharedImportMap___mfe_internal__addon_stream_broker_widgets-Cm_B-hQT.mjs} +1 -1
  19. package/dist/stream-broker/{_virtual_mf___mfe_internal__addon_stream_broker_widgets__loadShare___mf_0_camstack_mf_1_types__loadShare__.js-D2z_vRMH.mjs → _virtual_mf___mfe_internal__addon_stream_broker_widgets__loadShare___mf_0_camstack_mf_1_types__loadShare__.js-Ba7Eyd47.mjs} +1 -1
  20. package/dist/stream-broker/{hostInit-Di9WUNlQ.mjs → hostInit-DEaqJpGA.mjs} +1 -1
  21. package/dist/stream-broker/index.js +877 -37
  22. package/dist/stream-broker/index.mjs +874 -34
  23. package/dist/stream-broker/remoteEntry.js +1 -1
  24. package/embed-dist/assets/{MaskShapeCanvas-DI4BY7W2-Ca93F1js.js → MaskShapeCanvas-DI4BY7W2-CZUzu3MF.js} +1 -1
  25. package/embed-dist/assets/{MotionZonesSettings-NcxxQN8r-CDqgb-WA.js → MotionZonesSettings-NcxxQN8r-CmZbzLQi.js} +1 -1
  26. package/embed-dist/assets/{PrivacyMaskSettings-APgPLF7p-BlxPhY_w.js → PrivacyMaskSettings-APgPLF7p-BOKDrH0N.js} +1 -1
  27. package/embed-dist/assets/{index-B23riUw8.js → index-DOsK8CZb.js} +10 -10
  28. package/embed-dist/index.html +1 -1
  29. package/package.json +7 -5
  30. package/python/inference_pool.py +172 -28
  31. package/python/postprocessors/__init__.py +2 -0
  32. package/python/postprocessors/ssd.py +128 -0
  33. package/python/requirements-edgetpu.txt +23 -0
  34. package/python/test_inference_pool_layout.py +16 -1
  35. package/python/test_inference_pool_preprocess.py +65 -0
  36. package/dist/remote-source-plane-B28iGi7h.mjs +0 -1001
  37. package/dist/remote-source-plane-BAqEHSgm.js +0 -1030
  38. package/dist/{model-download-service-C-IHWnXx-BPy6aoAx.mjs → model-download-service-C-IHWnXx-3Mmeob3l.mjs} +1 -1
  39. package/dist/{model-download-service-C-IHWnXx-BLXzxpRB.js → model-download-service-C-IHWnXx-D326YNnt.js} +1 -1
@@ -4635,7 +4635,7 @@ function _instanceof(cls, params = {}) {
4635
4635
  return inst;
4636
4636
  }
4637
4637
  //#endregion
4638
- //#region ../types/dist/sleep-DkhOVOjW.mjs
4638
+ //#region ../types/dist/sleep-_sv7WKkq.mjs
4639
4639
  var EventCategory = /* @__PURE__ */ function(EventCategory) {
4640
4640
  EventCategory["SystemBoot"] = "system.boot";
4641
4641
  EventCategory["SystemAddonsReady"] = "system.addons-ready";
@@ -5066,6 +5066,14 @@ var EventCategory = /* @__PURE__ */ function(EventCategory) {
5066
5066
  EventCategory["PipelineAnalyticsDetectionEvent"] = "pipeline-analytics.detection-event";
5067
5067
  EventCategory["PipelineAnalyticsFrameTracked"] = "pipeline-analytics.frame-tracked";
5068
5068
  /**
5069
+ * Fired by `addon-post-analysis` when a parked (stationary) object appears
5070
+ * (a track was promoted to a stationary-registry entry) or departs (the
5071
+ * object moved / was removed). Telemetry (D8): lossy, drives a UI refresh of
5072
+ * the dedicated "Stationary" section — never the live event feed. Payload:
5073
+ * `{ deviceId, entryId, className, phase:'appeared'|'departed', timestamp }`.
5074
+ */
5075
+ EventCategory["PipelineAnalyticsStationaryChanged"] = "pipeline-analytics.stationary-changed";
5076
+ /**
5069
5077
  * Fired by `addon-post-analysis` whenever a gallery face row changes:
5070
5078
  * `kind:'buffered'` a new detected face was persisted, `'assigned'` /
5071
5079
  * `'unassigned'` its identity link changed, `'deleted'` the row was
@@ -7137,6 +7145,15 @@ var ModelCatalogEntrySchema = object({
7137
7145
  width: number(),
7138
7146
  height: number()
7139
7147
  }),
7148
+ /**
7149
+ * Channel count of the model input tensor. Omit ⇒ 3 (RGB), the default for
7150
+ * every detector / classifier / embedder. Set to 1 for a grayscale CTC text
7151
+ * recognizer (EasyOCR VGG plate-OCR: input `[N,1,H,W]`) so the preprocess
7152
+ * feeds a single-channel, EasyOCR-normalized tensor instead of the default
7153
+ * 3-channel RGB one. Threaded through `PoolModelConfig.inputChannels` to the
7154
+ * Python inference pool.
7155
+ */
7156
+ inputChannels: number().int().positive().optional(),
7140
7157
  labels: array(LabelDefinitionSchema).readonly(),
7141
7158
  inputLayout: _enum(["nchw", "nhwc"]).optional(),
7142
7159
  inputNormalization: _enum([
@@ -7146,6 +7163,16 @@ var ModelCatalogEntrySchema = object({
7146
7163
  ]).optional(),
7147
7164
  preprocessMode: _enum(["letterbox", "resize"]).optional(),
7148
7165
  /**
7166
+ * Per-MODEL postprocessor override. Absent ⇒ the step's own
7167
+ * `StepDefinition.postprocessor` applies (the normal case — every model in a
7168
+ * step shares its decode). Set it when a step hosts models with DIFFERENT raw
7169
+ * output layouts under one slot: e.g. object-detection is `'yolo'` by default,
7170
+ * but a Coral SSD MobileNet build emits the `TFLite_Detection_PostProcess`
7171
+ * 4-tensor layout and needs `'ssd'`. Threaded into `PoolModelConfig.postprocessor`
7172
+ * by the engine factory (`modelEntry.postprocessor ?? def.postprocessor`).
7173
+ */
7174
+ postprocessor: custom().optional(),
7175
+ /**
7149
7176
  * When true, the executor produces a landmark-aligned crop (similarity warp
7150
7177
  * onto the canonical template) before this step runs, instead of a plain
7151
7178
  * axis-aligned bbox crop. Required for face-recognition embedders (ArcFace):
@@ -11485,7 +11512,8 @@ var EngineProvisioningSchema = object({
11485
11512
  runtimeId: _enum([
11486
11513
  "onnx",
11487
11514
  "openvino",
11488
- "coreml"
11515
+ "coreml",
11516
+ "edgetpu"
11489
11517
  ]).nullable(),
11490
11518
  device: string().nullable(),
11491
11519
  state: _enum([
@@ -13476,6 +13504,36 @@ var ZoneScopeBreakdownSchema = PerScopeBreakdownSchema.extend({
13476
13504
  * with the per-track detail panel and live overlay. */
13477
13505
  trackIds: array(string()).readonly()
13478
13506
  });
13507
+ /**
13508
+ * A parked ("stationary") object surfaced alongside occupancy — an object that
13509
+ * settled and stopped moving. It is NO LONGER a tracked object (the tracker was
13510
+ * told to forget it so it stops re-spawning tracks/events), but it IS still
13511
+ * physically present, so it keeps counting toward `frame` occupancy and is
13512
+ * listed here so the UI can show it in a dedicated "Stationary" section instead
13513
+ * of flooding the live event feed.
13514
+ */
13515
+ var StationaryObjectSchema = object({
13516
+ id: string(),
13517
+ className: string(),
13518
+ bbox: object({
13519
+ x: number(),
13520
+ y: number(),
13521
+ w: number(),
13522
+ h: number()
13523
+ }),
13524
+ frameWidth: number().int().nonnegative(),
13525
+ frameHeight: number().int().nonnegative(),
13526
+ /** When the source track was first seen. */
13527
+ firstSeenAt: number().int(),
13528
+ /** When the object was recognised as parked (promotion time). */
13529
+ becameStationaryAt: number().int(),
13530
+ /** Last frame a detection confirmed the object is still there. */
13531
+ lastConfirmedAt: number().int(),
13532
+ /** Enrichment label carried from the source track (identity / plate). */
13533
+ label: string().optional(),
13534
+ /** Native-resolution key-frame media key for the parked object's best image. */
13535
+ keyFrameMediaKey: string().optional()
13536
+ });
13479
13537
  var CameraOccupancySnapshotSchema = object({
13480
13538
  /** Frame timestamp of the inference result that produced this snapshot. */
13481
13539
  ts: number().int(),
@@ -13484,10 +13542,15 @@ var CameraOccupancySnapshotSchema = object({
13484
13542
  frameHeight: number().int().nonnegative(),
13485
13543
  /** Per-zone breakdown — one entry per defined zone (user + onboard). */
13486
13544
  zones: array(ZoneScopeBreakdownSchema).readonly(),
13487
- /** Frame-wide aggregate (everywhere, regardless of zone membership). */
13545
+ /** Frame-wide aggregate (everywhere, regardless of zone membership).
13546
+ * INCLUDES currently-confirmed stationary objects (they are still present). */
13488
13547
  frame: PerScopeBreakdownSchema,
13489
13548
  /** Detections that landed outside every zone. Empty when no zones defined. */
13490
- unzoned: PerScopeBreakdownSchema
13549
+ unzoned: PerScopeBreakdownSchema,
13550
+ /** Parked objects on this camera (additive — absent on legacy snapshots).
13551
+ * Surfaced separately so the UI shows them in a dedicated section rather
13552
+ * than as repeated tracks/events. */
13553
+ stationaryObjects: array(StationaryObjectSchema).readonly().optional()
13491
13554
  });
13492
13555
  /**
13493
13556
  * Time-series resolution. The history methods return one bucket per
@@ -17008,6 +17071,22 @@ var TrackSnapshotSchema = object({
17008
17071
  /** MediaStore key; resolve via `getTrackMedia({ trackId })`. */
17009
17072
  mediaKey: string()
17010
17073
  });
17074
+ /**
17075
+ * One audio-classification label heard on the track's camera while the
17076
+ * track was alive, aggregated per label. An "episode" is one persisted
17077
+ * audio event (the confident-classification path: score ≥ the device's
17078
+ * `classificationMinScore`, class-change-or-heartbeat coalesced) — NOT
17079
+ * one 32 ms inference chunk, so counts stay human-scaled.
17080
+ */
17081
+ var TrackAudioLabelSchema = object({
17082
+ label: string(),
17083
+ /** Highest classification score observed across the label's episodes. */
17084
+ peakScore: number(),
17085
+ /** Number of coalesced audio-event episodes carrying this label. */
17086
+ count: number(),
17087
+ firstAt: number(),
17088
+ lastAt: number()
17089
+ });
17011
17090
  var TrackSchema = object({
17012
17091
  trackId: string(),
17013
17092
  deviceId: number(),
@@ -17039,7 +17118,11 @@ var TrackSchema = object({
17039
17118
  bestEventId: string().optional(),
17040
17119
  /** Tag of the importance sub-signal that dominated the score
17041
17120
  * (identity|dwell|proximity|class|confidence|travel|zone). */
17042
- importanceReason: string().optional()
17121
+ importanceReason: string().optional(),
17122
+ /** Audio-classification labels heard on the camera during the track's
17123
+ * life (score ≥ device `classificationMinScore`), aggregated per label.
17124
+ * Absent on legacy rows / tracks with no confident audio. */
17125
+ audioLabels: array(TrackAudioLabelSchema).readonly().optional()
17043
17126
  });
17044
17127
  var BaseEventFields = {
17045
17128
  id: string(),
@@ -20355,6 +20438,10 @@ var GpuInfoSchema = object({
20355
20438
  memoryMB: number().optional()
20356
20439
  });
20357
20440
  var NpuInfoSchema = object({ type: _enum(["apple-ane", "intel-npu"]) });
20441
+ var CoralInfoSchema = object({
20442
+ type: literal("coral-edgetpu"),
20443
+ bus: string().optional()
20444
+ });
20358
20445
  var HardwareInfoSchema = object({
20359
20446
  platform: HardwarePlatformSchema,
20360
20447
  arch: HardwareArchSchema,
@@ -20363,7 +20450,8 @@ var HardwareInfoSchema = object({
20363
20450
  totalRAM_MB: number(),
20364
20451
  availableRAM_MB: number(),
20365
20452
  gpu: GpuInfoSchema.nullable(),
20366
- npu: NpuInfoSchema.nullable()
20453
+ npu: NpuInfoSchema.nullable(),
20454
+ coral: CoralInfoSchema.nullable().optional()
20367
20455
  });
20368
20456
  var PlatformScoreSchema = object({
20369
20457
  runtime: _enum(["node", "python"]),
@@ -25800,6 +25888,10 @@ var CPU = {
25800
25888
  value: "cpu",
25801
25889
  label: "CPU"
25802
25890
  };
25891
+ var USB = {
25892
+ value: "usb",
25893
+ label: "Coral USB"
25894
+ };
25803
25895
  var RUNTIMES = [
25804
25896
  {
25805
25897
  id: "onnx",
@@ -25858,6 +25950,12 @@ var RUNTIMES = [
25858
25950
  return out;
25859
25951
  },
25860
25952
  defaultDevice: "all"
25953
+ },
25954
+ {
25955
+ id: "edgetpu",
25956
+ supports: (hw) => hw?.coral != null,
25957
+ devices: () => [USB],
25958
+ defaultDevice: "usb"
25861
25959
  }
25862
25960
  ];
25863
25961
  function def(id) {
@@ -4635,7 +4635,7 @@ function _instanceof(cls, params = {}) {
4635
4635
  return inst;
4636
4636
  }
4637
4637
  //#endregion
4638
- //#region ../types/dist/sleep-DkhOVOjW.mjs
4638
+ //#region ../types/dist/sleep-_sv7WKkq.mjs
4639
4639
  var EventCategory = /* @__PURE__ */ function(EventCategory) {
4640
4640
  EventCategory["SystemBoot"] = "system.boot";
4641
4641
  EventCategory["SystemAddonsReady"] = "system.addons-ready";
@@ -5066,6 +5066,14 @@ var EventCategory = /* @__PURE__ */ function(EventCategory) {
5066
5066
  EventCategory["PipelineAnalyticsDetectionEvent"] = "pipeline-analytics.detection-event";
5067
5067
  EventCategory["PipelineAnalyticsFrameTracked"] = "pipeline-analytics.frame-tracked";
5068
5068
  /**
5069
+ * Fired by `addon-post-analysis` when a parked (stationary) object appears
5070
+ * (a track was promoted to a stationary-registry entry) or departs (the
5071
+ * object moved / was removed). Telemetry (D8): lossy, drives a UI refresh of
5072
+ * the dedicated "Stationary" section — never the live event feed. Payload:
5073
+ * `{ deviceId, entryId, className, phase:'appeared'|'departed', timestamp }`.
5074
+ */
5075
+ EventCategory["PipelineAnalyticsStationaryChanged"] = "pipeline-analytics.stationary-changed";
5076
+ /**
5069
5077
  * Fired by `addon-post-analysis` whenever a gallery face row changes:
5070
5078
  * `kind:'buffered'` a new detected face was persisted, `'assigned'` /
5071
5079
  * `'unassigned'` its identity link changed, `'deleted'` the row was
@@ -7137,6 +7145,15 @@ var ModelCatalogEntrySchema = object({
7137
7145
  width: number(),
7138
7146
  height: number()
7139
7147
  }),
7148
+ /**
7149
+ * Channel count of the model input tensor. Omit ⇒ 3 (RGB), the default for
7150
+ * every detector / classifier / embedder. Set to 1 for a grayscale CTC text
7151
+ * recognizer (EasyOCR VGG plate-OCR: input `[N,1,H,W]`) so the preprocess
7152
+ * feeds a single-channel, EasyOCR-normalized tensor instead of the default
7153
+ * 3-channel RGB one. Threaded through `PoolModelConfig.inputChannels` to the
7154
+ * Python inference pool.
7155
+ */
7156
+ inputChannels: number().int().positive().optional(),
7140
7157
  labels: array(LabelDefinitionSchema).readonly(),
7141
7158
  inputLayout: _enum(["nchw", "nhwc"]).optional(),
7142
7159
  inputNormalization: _enum([
@@ -7146,6 +7163,16 @@ var ModelCatalogEntrySchema = object({
7146
7163
  ]).optional(),
7147
7164
  preprocessMode: _enum(["letterbox", "resize"]).optional(),
7148
7165
  /**
7166
+ * Per-MODEL postprocessor override. Absent ⇒ the step's own
7167
+ * `StepDefinition.postprocessor` applies (the normal case — every model in a
7168
+ * step shares its decode). Set it when a step hosts models with DIFFERENT raw
7169
+ * output layouts under one slot: e.g. object-detection is `'yolo'` by default,
7170
+ * but a Coral SSD MobileNet build emits the `TFLite_Detection_PostProcess`
7171
+ * 4-tensor layout and needs `'ssd'`. Threaded into `PoolModelConfig.postprocessor`
7172
+ * by the engine factory (`modelEntry.postprocessor ?? def.postprocessor`).
7173
+ */
7174
+ postprocessor: custom().optional(),
7175
+ /**
7149
7176
  * When true, the executor produces a landmark-aligned crop (similarity warp
7150
7177
  * onto the canonical template) before this step runs, instead of a plain
7151
7178
  * axis-aligned bbox crop. Required for face-recognition embedders (ArcFace):
@@ -11485,7 +11512,8 @@ var EngineProvisioningSchema = object({
11485
11512
  runtimeId: _enum([
11486
11513
  "onnx",
11487
11514
  "openvino",
11488
- "coreml"
11515
+ "coreml",
11516
+ "edgetpu"
11489
11517
  ]).nullable(),
11490
11518
  device: string().nullable(),
11491
11519
  state: _enum([
@@ -13476,6 +13504,36 @@ var ZoneScopeBreakdownSchema = PerScopeBreakdownSchema.extend({
13476
13504
  * with the per-track detail panel and live overlay. */
13477
13505
  trackIds: array(string()).readonly()
13478
13506
  });
13507
+ /**
13508
+ * A parked ("stationary") object surfaced alongside occupancy — an object that
13509
+ * settled and stopped moving. It is NO LONGER a tracked object (the tracker was
13510
+ * told to forget it so it stops re-spawning tracks/events), but it IS still
13511
+ * physically present, so it keeps counting toward `frame` occupancy and is
13512
+ * listed here so the UI can show it in a dedicated "Stationary" section instead
13513
+ * of flooding the live event feed.
13514
+ */
13515
+ var StationaryObjectSchema = object({
13516
+ id: string(),
13517
+ className: string(),
13518
+ bbox: object({
13519
+ x: number(),
13520
+ y: number(),
13521
+ w: number(),
13522
+ h: number()
13523
+ }),
13524
+ frameWidth: number().int().nonnegative(),
13525
+ frameHeight: number().int().nonnegative(),
13526
+ /** When the source track was first seen. */
13527
+ firstSeenAt: number().int(),
13528
+ /** When the object was recognised as parked (promotion time). */
13529
+ becameStationaryAt: number().int(),
13530
+ /** Last frame a detection confirmed the object is still there. */
13531
+ lastConfirmedAt: number().int(),
13532
+ /** Enrichment label carried from the source track (identity / plate). */
13533
+ label: string().optional(),
13534
+ /** Native-resolution key-frame media key for the parked object's best image. */
13535
+ keyFrameMediaKey: string().optional()
13536
+ });
13479
13537
  var CameraOccupancySnapshotSchema = object({
13480
13538
  /** Frame timestamp of the inference result that produced this snapshot. */
13481
13539
  ts: number().int(),
@@ -13484,10 +13542,15 @@ var CameraOccupancySnapshotSchema = object({
13484
13542
  frameHeight: number().int().nonnegative(),
13485
13543
  /** Per-zone breakdown — one entry per defined zone (user + onboard). */
13486
13544
  zones: array(ZoneScopeBreakdownSchema).readonly(),
13487
- /** Frame-wide aggregate (everywhere, regardless of zone membership). */
13545
+ /** Frame-wide aggregate (everywhere, regardless of zone membership).
13546
+ * INCLUDES currently-confirmed stationary objects (they are still present). */
13488
13547
  frame: PerScopeBreakdownSchema,
13489
13548
  /** Detections that landed outside every zone. Empty when no zones defined. */
13490
- unzoned: PerScopeBreakdownSchema
13549
+ unzoned: PerScopeBreakdownSchema,
13550
+ /** Parked objects on this camera (additive — absent on legacy snapshots).
13551
+ * Surfaced separately so the UI shows them in a dedicated section rather
13552
+ * than as repeated tracks/events. */
13553
+ stationaryObjects: array(StationaryObjectSchema).readonly().optional()
13491
13554
  });
13492
13555
  /**
13493
13556
  * Time-series resolution. The history methods return one bucket per
@@ -17008,6 +17071,22 @@ var TrackSnapshotSchema = object({
17008
17071
  /** MediaStore key; resolve via `getTrackMedia({ trackId })`. */
17009
17072
  mediaKey: string()
17010
17073
  });
17074
+ /**
17075
+ * One audio-classification label heard on the track's camera while the
17076
+ * track was alive, aggregated per label. An "episode" is one persisted
17077
+ * audio event (the confident-classification path: score ≥ the device's
17078
+ * `classificationMinScore`, class-change-or-heartbeat coalesced) — NOT
17079
+ * one 32 ms inference chunk, so counts stay human-scaled.
17080
+ */
17081
+ var TrackAudioLabelSchema = object({
17082
+ label: string(),
17083
+ /** Highest classification score observed across the label's episodes. */
17084
+ peakScore: number(),
17085
+ /** Number of coalesced audio-event episodes carrying this label. */
17086
+ count: number(),
17087
+ firstAt: number(),
17088
+ lastAt: number()
17089
+ });
17011
17090
  var TrackSchema = object({
17012
17091
  trackId: string(),
17013
17092
  deviceId: number(),
@@ -17039,7 +17118,11 @@ var TrackSchema = object({
17039
17118
  bestEventId: string().optional(),
17040
17119
  /** Tag of the importance sub-signal that dominated the score
17041
17120
  * (identity|dwell|proximity|class|confidence|travel|zone). */
17042
- importanceReason: string().optional()
17121
+ importanceReason: string().optional(),
17122
+ /** Audio-classification labels heard on the camera during the track's
17123
+ * life (score ≥ device `classificationMinScore`), aggregated per label.
17124
+ * Absent on legacy rows / tracks with no confident audio. */
17125
+ audioLabels: array(TrackAudioLabelSchema).readonly().optional()
17043
17126
  });
17044
17127
  var BaseEventFields = {
17045
17128
  id: string(),
@@ -20355,6 +20438,10 @@ var GpuInfoSchema = object({
20355
20438
  memoryMB: number().optional()
20356
20439
  });
20357
20440
  var NpuInfoSchema = object({ type: _enum(["apple-ane", "intel-npu"]) });
20441
+ var CoralInfoSchema = object({
20442
+ type: literal("coral-edgetpu"),
20443
+ bus: string().optional()
20444
+ });
20358
20445
  var HardwareInfoSchema = object({
20359
20446
  platform: HardwarePlatformSchema,
20360
20447
  arch: HardwareArchSchema,
@@ -20363,7 +20450,8 @@ var HardwareInfoSchema = object({
20363
20450
  totalRAM_MB: number(),
20364
20451
  availableRAM_MB: number(),
20365
20452
  gpu: GpuInfoSchema.nullable(),
20366
- npu: NpuInfoSchema.nullable()
20453
+ npu: NpuInfoSchema.nullable(),
20454
+ coral: CoralInfoSchema.nullable().optional()
20367
20455
  });
20368
20456
  var PlatformScoreSchema = object({
20369
20457
  runtime: _enum(["node", "python"]),
@@ -25800,6 +25888,10 @@ var CPU = {
25800
25888
  value: "cpu",
25801
25889
  label: "CPU"
25802
25890
  };
25891
+ var USB = {
25892
+ value: "usb",
25893
+ label: "Coral USB"
25894
+ };
25803
25895
  var RUNTIMES = [
25804
25896
  {
25805
25897
  id: "onnx",
@@ -25858,6 +25950,12 @@ var RUNTIMES = [
25858
25950
  return out;
25859
25951
  },
25860
25952
  defaultDevice: "all"
25953
+ },
25954
+ {
25955
+ id: "edgetpu",
25956
+ supports: (hw) => hw?.coral != null,
25957
+ devices: () => [USB],
25958
+ defaultDevice: "usb"
25861
25959
  }
25862
25960
  ];
25863
25961
  function def(id) {
@@ -2,8 +2,7 @@ Object.defineProperties(exports, {
2
2
  __esModule: { value: true },
3
3
  [Symbol.toStringTag]: { value: "Module" }
4
4
  });
5
- const require_dist = require("../dist-ClE6_i0p.js");
6
- let _camstack_shm_ring = require("@camstack/shm-ring");
5
+ const require_dist = require("../dist-CK8Ur-OS.js");
7
6
  let node_fs = require("node:fs");
8
7
  let node_path = require("node:path");
9
8
  //#region src/motion-wasm/wasm-motion-detector.ts
@@ -136,13 +135,6 @@ var DEFAULT_CONFIG = {
136
135
  };
137
136
  var MotionWasmAddon = class MotionWasmAddon extends require_dist.BaseAddon {
138
137
  detector = null;
139
- /**
140
- * CB5 shm passthrough — process-local, long-lived reader cache for
141
- * `analyze({ frameHandle })`. Opens each named shm segment once and reuses
142
- * the mapping; lazily created on first LOCAL handle, unmapped in
143
- * {@link onShutdown}. Never opened/closed per-call.
144
- */
145
- frameHandleReaders = null;
146
138
  cameras = /* @__PURE__ */ new Map();
147
139
  deviceConfigCache = /* @__PURE__ */ new Map();
148
140
  static DEVICE_CONFIG_TTL_MS = 6e4;
@@ -196,38 +188,16 @@ var MotionWasmAddon = class MotionWasmAddon extends require_dist.BaseAddon {
196
188
  * Per-device state keyed by the numeric deviceId (stringified internally
197
189
  * so the pipeline-step sentinel shares the same Map).
198
190
  *
199
- * CB5: pixels arrive either inline (`frame`) or as a zero-pixel shm
200
- * `FrameHandle`. A LOCAL handle is read back zero-copy here; a foreign /
201
- * recycled / unmappable handle yields a null read and an empty result (the
202
- * runner ships `frame` as the fallback, queue-depth gated).
191
+ * Pixels arrive inline (`frame`). The `frameHandle` input is DORMANT since
192
+ * the shm-ring removal (2026-07-16): the runner always ships inline gray
193
+ * pixels now. A handle can only arrive under version skew (an old runner
194
+ * against a new provider); with no shm passthrough there is no way to
195
+ * resolve its pixels, so it degrades to an empty result. The field stays
196
+ * defined so no cap-surface change is needed.
203
197
  */
204
198
  async analyze({ deviceId, frame, frameHandle }) {
205
- const resolved = frame ?? (frameHandle ? this.resolveFrameHandle(frameHandle) : null);
206
- if (!resolved) return this.emptyMotionResult(frameHandle);
207
- return this.analyzeInternal(String(deviceId), resolved);
208
- }
209
- /** This node's cluster id (suffix-stripped), for local-vs-foreign gating. */
210
- ownNodeId() {
211
- const raw = this.ctx.kernel?.localNodeId ?? "hub";
212
- return raw.includes("/") ? raw.split("/")[0] : raw;
213
- }
214
- /**
215
- * CB5 — resolve a shm `FrameHandle` to gray pixels zero-copy. Returns null
216
- * for a FOREIGN handle (segment on another node — the runner only sends
217
- * local handles), a recycled ring slot, or an unmappable segment.
218
- */
219
- resolveFrameHandle(handle) {
220
- if (handle.nodeId !== this.ownNodeId()) return null;
221
- if (!this.frameHandleReaders) this.frameHandleReaders = new _camstack_shm_ring.FrameRingReaderCache(this.ctx.logger);
222
- const decoded = this.frameHandleReaders.read(handle);
223
- if (!decoded) return null;
224
- return {
225
- data: decoded.data,
226
- width: decoded.width,
227
- height: decoded.height,
228
- format: decoded.format,
229
- timestamp: decoded.timestamp
230
- };
199
+ if (!frame) return this.emptyMotionResult(frameHandle);
200
+ return this.analyzeInternal(String(deviceId), frame);
231
201
  }
232
202
  /** Zeroed motion result for a missed `frameHandle` read (dropped frame). */
233
203
  emptyMotionResult(handle) {
@@ -401,8 +371,6 @@ var MotionWasmAddon = class MotionWasmAddon extends require_dist.BaseAddon {
401
371
  this.deviceConfigCache.clear();
402
372
  for (const id of this.proxies.keys()) this.releaseProxy(id);
403
373
  this.detector = null;
404
- this.frameHandleReaders?.close();
405
- this.frameHandleReaders = null;
406
374
  }
407
375
  deviceSettingsSchema() {
408
376
  return this.schema({ sections: [{
@@ -1,5 +1,4 @@
1
- import { B as DeviceType, E as motionDetectionCapability, L as BaseAddon, U as hydrateSchema, x as evaluateZoneRules } from "../dist-CrjLGrkj.mjs";
2
- import { FrameRingReaderCache } from "@camstack/shm-ring";
1
+ import { B as DeviceType, E as motionDetectionCapability, L as BaseAddon, U as hydrateSchema, x as evaluateZoneRules } from "../dist-CL531uVA.mjs";
3
2
  import { readFileSync } from "node:fs";
4
3
  import { join } from "node:path";
5
4
  //#region src/motion-wasm/wasm-motion-detector.ts
@@ -132,13 +131,6 @@ var DEFAULT_CONFIG = {
132
131
  };
133
132
  var MotionWasmAddon = class MotionWasmAddon extends BaseAddon {
134
133
  detector = null;
135
- /**
136
- * CB5 shm passthrough — process-local, long-lived reader cache for
137
- * `analyze({ frameHandle })`. Opens each named shm segment once and reuses
138
- * the mapping; lazily created on first LOCAL handle, unmapped in
139
- * {@link onShutdown}. Never opened/closed per-call.
140
- */
141
- frameHandleReaders = null;
142
134
  cameras = /* @__PURE__ */ new Map();
143
135
  deviceConfigCache = /* @__PURE__ */ new Map();
144
136
  static DEVICE_CONFIG_TTL_MS = 6e4;
@@ -192,38 +184,16 @@ var MotionWasmAddon = class MotionWasmAddon extends BaseAddon {
192
184
  * Per-device state keyed by the numeric deviceId (stringified internally
193
185
  * so the pipeline-step sentinel shares the same Map).
194
186
  *
195
- * CB5: pixels arrive either inline (`frame`) or as a zero-pixel shm
196
- * `FrameHandle`. A LOCAL handle is read back zero-copy here; a foreign /
197
- * recycled / unmappable handle yields a null read and an empty result (the
198
- * runner ships `frame` as the fallback, queue-depth gated).
187
+ * Pixels arrive inline (`frame`). The `frameHandle` input is DORMANT since
188
+ * the shm-ring removal (2026-07-16): the runner always ships inline gray
189
+ * pixels now. A handle can only arrive under version skew (an old runner
190
+ * against a new provider); with no shm passthrough there is no way to
191
+ * resolve its pixels, so it degrades to an empty result. The field stays
192
+ * defined so no cap-surface change is needed.
199
193
  */
200
194
  async analyze({ deviceId, frame, frameHandle }) {
201
- const resolved = frame ?? (frameHandle ? this.resolveFrameHandle(frameHandle) : null);
202
- if (!resolved) return this.emptyMotionResult(frameHandle);
203
- return this.analyzeInternal(String(deviceId), resolved);
204
- }
205
- /** This node's cluster id (suffix-stripped), for local-vs-foreign gating. */
206
- ownNodeId() {
207
- const raw = this.ctx.kernel?.localNodeId ?? "hub";
208
- return raw.includes("/") ? raw.split("/")[0] : raw;
209
- }
210
- /**
211
- * CB5 — resolve a shm `FrameHandle` to gray pixels zero-copy. Returns null
212
- * for a FOREIGN handle (segment on another node — the runner only sends
213
- * local handles), a recycled ring slot, or an unmappable segment.
214
- */
215
- resolveFrameHandle(handle) {
216
- if (handle.nodeId !== this.ownNodeId()) return null;
217
- if (!this.frameHandleReaders) this.frameHandleReaders = new FrameRingReaderCache(this.ctx.logger);
218
- const decoded = this.frameHandleReaders.read(handle);
219
- if (!decoded) return null;
220
- return {
221
- data: decoded.data,
222
- width: decoded.width,
223
- height: decoded.height,
224
- format: decoded.format,
225
- timestamp: decoded.timestamp
226
- };
195
+ if (!frame) return this.emptyMotionResult(frameHandle);
196
+ return this.analyzeInternal(String(deviceId), frame);
227
197
  }
228
198
  /** Zeroed motion result for a missed `frameHandle` read (dropped frame). */
229
199
  emptyMotionResult(handle) {
@@ -397,8 +367,6 @@ var MotionWasmAddon = class MotionWasmAddon extends BaseAddon {
397
367
  this.deviceConfigCache.clear();
398
368
  for (const id of this.proxies.keys()) this.releaseProxy(id);
399
369
  this.detector = null;
400
- this.frameHandleReaders?.close();
401
- this.frameHandleReaders = null;
402
370
  }
403
371
  deviceSettingsSchema() {
404
372
  return this.schema({ sections: [{