@camstack/addon-pipeline 1.1.0 → 1.1.2

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 (34) hide show
  1. package/dist/audio-analyzer/index.js +104 -29
  2. package/dist/audio-analyzer/index.mjs +100 -25
  3. package/dist/audio-codec-nodeav/index.js +1 -1
  4. package/dist/audio-codec-nodeav/index.mjs +1 -1
  5. package/dist/decoder-nodeav/index.js +1 -1
  6. package/dist/decoder-nodeav/index.mjs +1 -1
  7. package/dist/detection-pipeline/index.js +355 -116
  8. package/dist/detection-pipeline/index.mjs +343 -104
  9. package/dist/{dist-BA6DR_jV.mjs → dist-BWc-HYQz.mjs} +194 -1
  10. package/dist/{dist-BLcTVvol.js → dist-DnD2tm7T.js} +194 -1
  11. package/dist/{model-download-service-RxAOiYvX-CMAvhgO7.mjs → model-download-service-C-IHWnXx-3Mmeob3l.mjs} +1 -1
  12. package/dist/{model-download-service-RxAOiYvX-C8rTRJy_.js → model-download-service-C-IHWnXx-BnQ_awK4.js} +1 -1
  13. package/dist/motion-wasm/index.js +1 -1
  14. package/dist/motion-wasm/index.mjs +1 -1
  15. package/dist/pipeline-runner/index.js +14 -10
  16. package/dist/pipeline-runner/index.mjs +14 -10
  17. package/dist/recorder/index.js +4 -4
  18. package/dist/recorder/index.mjs +2 -2
  19. package/dist/stream-broker/_stub.js +1 -1
  20. package/dist/stream-broker/{_virtual_mf-localSharedImportMap___mfe_internal__addon_stream_broker_widgets-DrohyZ5L.mjs → _virtual_mf-localSharedImportMap___mfe_internal__addon_stream_broker_widgets-DLgk22-S.mjs} +3 -3
  21. package/dist/stream-broker/_virtual_mf___mfe_internal__addon_stream_broker_widgets__loadShare___mf_0_camstack_mf_1_types__loadShare__.js-FRD2eBuz.mjs +26 -0
  22. package/dist/stream-broker/{hostInit-zLZbYJcg.mjs → hostInit-pRSjUAJj.mjs} +3 -3
  23. package/dist/stream-broker/index.js +8 -8
  24. package/dist/stream-broker/index.mjs +2 -2
  25. package/dist/stream-broker/remoteEntry.js +1 -1
  26. package/embed-dist/assets/{MaskShapeCanvas-DI4BY7W2-DJ7ztnFv.js → MaskShapeCanvas-DI4BY7W2-5UPreLSr.js} +1 -1
  27. package/embed-dist/assets/{MotionZonesSettings-NcxxQN8r-CQzEnQoq.js → MotionZonesSettings-NcxxQN8r-Bxqs-CpZ.js} +1 -1
  28. package/embed-dist/assets/{PrivacyMaskSettings-APgPLF7p-Cl0eOy_U.js → PrivacyMaskSettings-APgPLF7p-BDMPeMJd.js} +1 -1
  29. package/embed-dist/assets/{index-CSuLwWK-.js → index-BgGwqHYl.js} +9 -9
  30. package/embed-dist/index.html +1 -1
  31. package/package.json +1 -1
  32. package/python/postprocessors/saliency.py +47 -1
  33. package/python/postprocessors/test_saliency.py +23 -0
  34. package/dist/stream-broker/_virtual_mf___mfe_internal__addon_stream_broker_widgets__loadShare___mf_0_camstack_mf_1_types__loadShare__.js-COa17XL2.mjs +0 -26
@@ -4627,7 +4627,7 @@ function _instanceof(cls, params = {}) {
4627
4627
  return inst;
4628
4628
  }
4629
4629
  //#endregion
4630
- //#region ../types/dist/sleep-B1dKJAMJ.mjs
4630
+ //#region ../types/dist/sleep-BV7rLc6Y.mjs
4631
4631
  var EventCategory = /* @__PURE__ */ function(EventCategory) {
4632
4632
  EventCategory["SystemBoot"] = "system.boot";
4633
4633
  EventCategory["SystemAddonsReady"] = "system.addons-ready";
@@ -5106,6 +5106,12 @@ var EventCategory = /* @__PURE__ */ function(EventCategory) {
5106
5106
  * Payload: `{ deviceId, childDeviceIds, hiddenChildIds }`.
5107
5107
  */
5108
5108
  EventCategory["AccessoriesChanged"] = "accessories.onAccessoriesChanged";
5109
+ /**
5110
+ * Progress update from a running model conversion job.
5111
+ * Payload: `{ kind: 'model-convert', phase, sessionId?, pct?, detail? }`.
5112
+ * Emitted by `addon-model-studio` on the converting node.
5113
+ */
5114
+ EventCategory["ModelConvertProgress"] = "model-convert.progress";
5109
5115
  return EventCategory;
5110
5116
  }({});
5111
5117
  Object.fromEntries([
@@ -6756,6 +6762,13 @@ object({
6756
6762
  unreachable: number()
6757
6763
  })
6758
6764
  });
6765
+ var LabelDefinitionSchema = object({
6766
+ id: string(),
6767
+ name: string(),
6768
+ category: string().optional(),
6769
+ description: string().optional(),
6770
+ icon: string().optional()
6771
+ });
6759
6772
  var MODEL_FORMATS = [
6760
6773
  "onnx",
6761
6774
  "coreml",
@@ -6764,6 +6777,120 @@ var MODEL_FORMATS = [
6764
6777
  "pt"
6765
6778
  ];
6766
6779
  /**
6780
+ * Multi-file format payload.
6781
+ *
6782
+ * - Directory formats (`isDirectory: true`, e.g. `.mlpackage`): files
6783
+ * relative to the directory root — the downloader fetches each from
6784
+ * `{url}/{file}` into `{modelDir}/{file}`. If omitted, it probes the
6785
+ * HuggingFace API (slower).
6786
+ * - Single-file formats (no `isDirectory`, e.g. OpenVINO IR): sibling
6787
+ * files fetched from the SAME remote directory as `url` and stored flat
6788
+ * alongside the main file — e.g. `['camstack-yolov9t.bin']` for the IR
6789
+ * weights next to `camstack-yolov9t.xml`.
6790
+ */
6791
+ var ModelFormatEntrySchema = object({
6792
+ url: string(),
6793
+ sizeMB: number(),
6794
+ /** Whether this format is a directory bundle (e.g., .mlpackage) rather than a single file */
6795
+ isDirectory: boolean().optional(),
6796
+ /** Multi-file payload (directory members or sibling files). */
6797
+ files: array(string()).readonly().optional(),
6798
+ /** Runtime(s) that can use this format. If omitted, inferred from ModelFormat key */
6799
+ runtimes: array(_enum(["node", "python"])).readonly().optional()
6800
+ });
6801
+ /**
6802
+ * Extra file that must be downloaded alongside the model (e.g., labels JSON, dict.txt).
6803
+ * The downloader fetches from `url` and saves to `{modelsDir}/{filename}`.
6804
+ */
6805
+ var ModelExtraFileSchema = object({
6806
+ url: string(),
6807
+ filename: string(),
6808
+ sizeMB: number()
6809
+ });
6810
+ /**
6811
+ * Per-format payload map. Modelled as an explicit object (one optional key
6812
+ * per `ModelFormat`) rather than `z.record(enum, …)` — zod v4's enum-keyed
6813
+ * record requires every key, but a catalog entry only ships a subset of
6814
+ * formats.
6815
+ */
6816
+ var ModelFormatsSchema = object({
6817
+ onnx: ModelFormatEntrySchema.optional(),
6818
+ coreml: ModelFormatEntrySchema.optional(),
6819
+ openvino: ModelFormatEntrySchema.optional(),
6820
+ tflite: ModelFormatEntrySchema.optional(),
6821
+ pt: ModelFormatEntrySchema.optional()
6822
+ });
6823
+ var ModelCatalogEntrySchema = object({
6824
+ id: string(),
6825
+ name: string(),
6826
+ description: string(),
6827
+ formats: ModelFormatsSchema,
6828
+ inputSize: object({
6829
+ width: number(),
6830
+ height: number()
6831
+ }),
6832
+ labels: array(LabelDefinitionSchema).readonly(),
6833
+ inputLayout: _enum(["nchw", "nhwc"]).optional(),
6834
+ inputNormalization: _enum([
6835
+ "zero-one",
6836
+ "imagenet",
6837
+ "none"
6838
+ ]).optional(),
6839
+ preprocessMode: _enum(["letterbox", "resize"]).optional(),
6840
+ /**
6841
+ * When true, the executor produces a landmark-aligned crop (similarity warp
6842
+ * onto the canonical template) before this step runs, instead of a plain
6843
+ * axis-aligned bbox crop. Required for face-recognition embedders (ArcFace):
6844
+ * their embeddings are only discriminative on an aligned input. The face
6845
+ * detector that produced the parent detail must emit 5 landmarks.
6846
+ */
6847
+ faceAlignment: boolean().optional(),
6848
+ /**
6849
+ * Auxiliary files required at runtime (labels JSON, charset dict, etc.).
6850
+ * Downloaded into the same modelsDir alongside the model file.
6851
+ */
6852
+ extraFiles: array(ModelExtraFileSchema).readonly().optional()
6853
+ });
6854
+ var ConvertTargetSchema = discriminatedUnion("format", [object({
6855
+ format: literal("openvino"),
6856
+ precisions: array(_enum(["fp16", "int8"])).min(1).readonly()
6857
+ }), object({ format: literal("coreml") })]);
6858
+ var ModelConvertMetadataSchema = object({
6859
+ id: string().regex(/^[a-zA-Z0-9._-]+$/),
6860
+ name: string(),
6861
+ labels: array(LabelDefinitionSchema).readonly(),
6862
+ inputSize: object({
6863
+ width: number(),
6864
+ height: number()
6865
+ }),
6866
+ inputLayout: _enum(["nchw", "nhwc"]).optional(),
6867
+ inputNormalization: _enum([
6868
+ "zero-one",
6869
+ "imagenet",
6870
+ "none"
6871
+ ]).optional(),
6872
+ preprocessMode: _enum(["letterbox", "resize"]).optional(),
6873
+ outputFormat: _enum([
6874
+ "yolo",
6875
+ "ssd",
6876
+ "embedding",
6877
+ "classification",
6878
+ "ocr",
6879
+ "segmentation"
6880
+ ]),
6881
+ faceAlignment: boolean().optional()
6882
+ });
6883
+ var ConvertResultSchema = object({
6884
+ entry: ModelCatalogEntrySchema,
6885
+ artifacts: array(object({
6886
+ format: _enum(MODEL_FORMATS),
6887
+ precision: _enum(["fp16", "int8"]).optional(),
6888
+ sizeMB: number(),
6889
+ validated: boolean(),
6890
+ files: array(string()).readonly()
6891
+ })).readonly()
6892
+ });
6893
+ /**
6767
6894
  * Numeric day-of-week: 0 = Sunday … 6 = Saturday (matches `Date.getDay`).
6768
6895
  * Named `RecordingWeekday` to avoid collision with the string-union
6769
6896
  * `Weekday` exported from `interfaces/timezones.ts`.
@@ -13667,6 +13794,54 @@ var EnrichedWidgetMetadataSchema = WidgetMetadataSchema.extend({
13667
13794
  bundleUrl: string()
13668
13795
  });
13669
13796
  method(_void(), array(EnrichedWidgetMetadataSchema).readonly());
13797
+ /**
13798
+ * `custom-model-registry` — collection cap exposing operator-registered
13799
+ * custom detection models. Each provider (today: `addon-model-studio`)
13800
+ * contributes a list of `CustomModelDescriptor`s; the hub auto-concatenates
13801
+ * them across providers (`concatCollection`).
13802
+ *
13803
+ * The detection-pipeline is *aware* of this cap: when at least one provider
13804
+ * exists it unions these descriptors into the per-step model picker and the
13805
+ * runtime model-resolution path, alongside the static catalog. When no
13806
+ * provider exists the consumer no-ops entirely (identical to the catalog-only
13807
+ * behaviour).
13808
+ *
13809
+ * A descriptor carries a full `ModelCatalogEntry` directly — the same shape
13810
+ * the static catalog uses — so the existing download/resolution code consumes
13811
+ * it unchanged. `stepId` is the detection step the model targets
13812
+ * (e.g. `'object-detection'`).
13813
+ */
13814
+ var CustomModelDescriptorSchema = object({
13815
+ stepId: string(),
13816
+ entry: ModelCatalogEntrySchema
13817
+ });
13818
+ method(_void(), array(CustomModelDescriptorSchema).readonly());
13819
+ method(object({
13820
+ nodeId: string(),
13821
+ modelId: string(),
13822
+ format: _enum(MODEL_FORMATS),
13823
+ entry: ModelCatalogEntrySchema
13824
+ }), object({
13825
+ ok: boolean(),
13826
+ /** sha256 of the staged tarball (empty for a hub-local no-op). */
13827
+ sha256: string(),
13828
+ bytes: number(),
13829
+ /** The target node's modelsDir the artifact landed in. */
13830
+ path: string()
13831
+ }), {
13832
+ kind: "mutation",
13833
+ auth: "admin"
13834
+ });
13835
+ method(object({
13836
+ sourceUrl: string(),
13837
+ metadata: ModelConvertMetadataSchema,
13838
+ targets: array(ConvertTargetSchema).min(1).readonly(),
13839
+ calibrationRef: string().optional(),
13840
+ sessionId: string().optional()
13841
+ }), ConvertResultSchema, {
13842
+ kind: "mutation",
13843
+ auth: "admin"
13844
+ });
13670
13845
  var AddonHttpRouteSchema = object({
13671
13846
  method: _enum([
13672
13847
  "GET",
@@ -18916,6 +19091,12 @@ Object.freeze({
18916
19091
  addonId: null,
18917
19092
  access: "create"
18918
19093
  },
19094
+ "customModelRegistry.listModels": {
19095
+ capName: "custom-model-registry",
19096
+ capScope: "system",
19097
+ addonId: null,
19098
+ access: "view"
19099
+ },
18919
19100
  "decoder.createSession": {
18920
19101
  capName: "decoder",
18921
19102
  capScope: "system",
@@ -20140,6 +20321,18 @@ Object.freeze({
20140
20321
  addonId: null,
20141
20322
  access: "view"
20142
20323
  },
20324
+ "modelConvert.convert": {
20325
+ capName: "model-convert",
20326
+ capScope: "system",
20327
+ addonId: null,
20328
+ access: "create"
20329
+ },
20330
+ "modelDistributor.distributeModel": {
20331
+ capName: "model-distributor",
20332
+ capScope: "system",
20333
+ addonId: null,
20334
+ access: "create"
20335
+ },
20143
20336
  "motion.isDetected": {
20144
20337
  capName: "motion",
20145
20338
  capScope: "device",
@@ -4627,7 +4627,7 @@ function _instanceof(cls, params = {}) {
4627
4627
  return inst;
4628
4628
  }
4629
4629
  //#endregion
4630
- //#region ../types/dist/sleep-B1dKJAMJ.mjs
4630
+ //#region ../types/dist/sleep-BV7rLc6Y.mjs
4631
4631
  var EventCategory = /* @__PURE__ */ function(EventCategory) {
4632
4632
  EventCategory["SystemBoot"] = "system.boot";
4633
4633
  EventCategory["SystemAddonsReady"] = "system.addons-ready";
@@ -5106,6 +5106,12 @@ var EventCategory = /* @__PURE__ */ function(EventCategory) {
5106
5106
  * Payload: `{ deviceId, childDeviceIds, hiddenChildIds }`.
5107
5107
  */
5108
5108
  EventCategory["AccessoriesChanged"] = "accessories.onAccessoriesChanged";
5109
+ /**
5110
+ * Progress update from a running model conversion job.
5111
+ * Payload: `{ kind: 'model-convert', phase, sessionId?, pct?, detail? }`.
5112
+ * Emitted by `addon-model-studio` on the converting node.
5113
+ */
5114
+ EventCategory["ModelConvertProgress"] = "model-convert.progress";
5109
5115
  return EventCategory;
5110
5116
  }({});
5111
5117
  Object.fromEntries([
@@ -6756,6 +6762,13 @@ object({
6756
6762
  unreachable: number()
6757
6763
  })
6758
6764
  });
6765
+ var LabelDefinitionSchema = object({
6766
+ id: string(),
6767
+ name: string(),
6768
+ category: string().optional(),
6769
+ description: string().optional(),
6770
+ icon: string().optional()
6771
+ });
6759
6772
  var MODEL_FORMATS = [
6760
6773
  "onnx",
6761
6774
  "coreml",
@@ -6764,6 +6777,120 @@ var MODEL_FORMATS = [
6764
6777
  "pt"
6765
6778
  ];
6766
6779
  /**
6780
+ * Multi-file format payload.
6781
+ *
6782
+ * - Directory formats (`isDirectory: true`, e.g. `.mlpackage`): files
6783
+ * relative to the directory root — the downloader fetches each from
6784
+ * `{url}/{file}` into `{modelDir}/{file}`. If omitted, it probes the
6785
+ * HuggingFace API (slower).
6786
+ * - Single-file formats (no `isDirectory`, e.g. OpenVINO IR): sibling
6787
+ * files fetched from the SAME remote directory as `url` and stored flat
6788
+ * alongside the main file — e.g. `['camstack-yolov9t.bin']` for the IR
6789
+ * weights next to `camstack-yolov9t.xml`.
6790
+ */
6791
+ var ModelFormatEntrySchema = object({
6792
+ url: string(),
6793
+ sizeMB: number(),
6794
+ /** Whether this format is a directory bundle (e.g., .mlpackage) rather than a single file */
6795
+ isDirectory: boolean().optional(),
6796
+ /** Multi-file payload (directory members or sibling files). */
6797
+ files: array(string()).readonly().optional(),
6798
+ /** Runtime(s) that can use this format. If omitted, inferred from ModelFormat key */
6799
+ runtimes: array(_enum(["node", "python"])).readonly().optional()
6800
+ });
6801
+ /**
6802
+ * Extra file that must be downloaded alongside the model (e.g., labels JSON, dict.txt).
6803
+ * The downloader fetches from `url` and saves to `{modelsDir}/{filename}`.
6804
+ */
6805
+ var ModelExtraFileSchema = object({
6806
+ url: string(),
6807
+ filename: string(),
6808
+ sizeMB: number()
6809
+ });
6810
+ /**
6811
+ * Per-format payload map. Modelled as an explicit object (one optional key
6812
+ * per `ModelFormat`) rather than `z.record(enum, …)` — zod v4's enum-keyed
6813
+ * record requires every key, but a catalog entry only ships a subset of
6814
+ * formats.
6815
+ */
6816
+ var ModelFormatsSchema = object({
6817
+ onnx: ModelFormatEntrySchema.optional(),
6818
+ coreml: ModelFormatEntrySchema.optional(),
6819
+ openvino: ModelFormatEntrySchema.optional(),
6820
+ tflite: ModelFormatEntrySchema.optional(),
6821
+ pt: ModelFormatEntrySchema.optional()
6822
+ });
6823
+ var ModelCatalogEntrySchema = object({
6824
+ id: string(),
6825
+ name: string(),
6826
+ description: string(),
6827
+ formats: ModelFormatsSchema,
6828
+ inputSize: object({
6829
+ width: number(),
6830
+ height: number()
6831
+ }),
6832
+ labels: array(LabelDefinitionSchema).readonly(),
6833
+ inputLayout: _enum(["nchw", "nhwc"]).optional(),
6834
+ inputNormalization: _enum([
6835
+ "zero-one",
6836
+ "imagenet",
6837
+ "none"
6838
+ ]).optional(),
6839
+ preprocessMode: _enum(["letterbox", "resize"]).optional(),
6840
+ /**
6841
+ * When true, the executor produces a landmark-aligned crop (similarity warp
6842
+ * onto the canonical template) before this step runs, instead of a plain
6843
+ * axis-aligned bbox crop. Required for face-recognition embedders (ArcFace):
6844
+ * their embeddings are only discriminative on an aligned input. The face
6845
+ * detector that produced the parent detail must emit 5 landmarks.
6846
+ */
6847
+ faceAlignment: boolean().optional(),
6848
+ /**
6849
+ * Auxiliary files required at runtime (labels JSON, charset dict, etc.).
6850
+ * Downloaded into the same modelsDir alongside the model file.
6851
+ */
6852
+ extraFiles: array(ModelExtraFileSchema).readonly().optional()
6853
+ });
6854
+ var ConvertTargetSchema = discriminatedUnion("format", [object({
6855
+ format: literal("openvino"),
6856
+ precisions: array(_enum(["fp16", "int8"])).min(1).readonly()
6857
+ }), object({ format: literal("coreml") })]);
6858
+ var ModelConvertMetadataSchema = object({
6859
+ id: string().regex(/^[a-zA-Z0-9._-]+$/),
6860
+ name: string(),
6861
+ labels: array(LabelDefinitionSchema).readonly(),
6862
+ inputSize: object({
6863
+ width: number(),
6864
+ height: number()
6865
+ }),
6866
+ inputLayout: _enum(["nchw", "nhwc"]).optional(),
6867
+ inputNormalization: _enum([
6868
+ "zero-one",
6869
+ "imagenet",
6870
+ "none"
6871
+ ]).optional(),
6872
+ preprocessMode: _enum(["letterbox", "resize"]).optional(),
6873
+ outputFormat: _enum([
6874
+ "yolo",
6875
+ "ssd",
6876
+ "embedding",
6877
+ "classification",
6878
+ "ocr",
6879
+ "segmentation"
6880
+ ]),
6881
+ faceAlignment: boolean().optional()
6882
+ });
6883
+ var ConvertResultSchema = object({
6884
+ entry: ModelCatalogEntrySchema,
6885
+ artifacts: array(object({
6886
+ format: _enum(MODEL_FORMATS),
6887
+ precision: _enum(["fp16", "int8"]).optional(),
6888
+ sizeMB: number(),
6889
+ validated: boolean(),
6890
+ files: array(string()).readonly()
6891
+ })).readonly()
6892
+ });
6893
+ /**
6767
6894
  * Numeric day-of-week: 0 = Sunday … 6 = Saturday (matches `Date.getDay`).
6768
6895
  * Named `RecordingWeekday` to avoid collision with the string-union
6769
6896
  * `Weekday` exported from `interfaces/timezones.ts`.
@@ -13667,6 +13794,54 @@ var EnrichedWidgetMetadataSchema = WidgetMetadataSchema.extend({
13667
13794
  bundleUrl: string()
13668
13795
  });
13669
13796
  method(_void(), array(EnrichedWidgetMetadataSchema).readonly());
13797
+ /**
13798
+ * `custom-model-registry` — collection cap exposing operator-registered
13799
+ * custom detection models. Each provider (today: `addon-model-studio`)
13800
+ * contributes a list of `CustomModelDescriptor`s; the hub auto-concatenates
13801
+ * them across providers (`concatCollection`).
13802
+ *
13803
+ * The detection-pipeline is *aware* of this cap: when at least one provider
13804
+ * exists it unions these descriptors into the per-step model picker and the
13805
+ * runtime model-resolution path, alongside the static catalog. When no
13806
+ * provider exists the consumer no-ops entirely (identical to the catalog-only
13807
+ * behaviour).
13808
+ *
13809
+ * A descriptor carries a full `ModelCatalogEntry` directly — the same shape
13810
+ * the static catalog uses — so the existing download/resolution code consumes
13811
+ * it unchanged. `stepId` is the detection step the model targets
13812
+ * (e.g. `'object-detection'`).
13813
+ */
13814
+ var CustomModelDescriptorSchema = object({
13815
+ stepId: string(),
13816
+ entry: ModelCatalogEntrySchema
13817
+ });
13818
+ method(_void(), array(CustomModelDescriptorSchema).readonly());
13819
+ method(object({
13820
+ nodeId: string(),
13821
+ modelId: string(),
13822
+ format: _enum(MODEL_FORMATS),
13823
+ entry: ModelCatalogEntrySchema
13824
+ }), object({
13825
+ ok: boolean(),
13826
+ /** sha256 of the staged tarball (empty for a hub-local no-op). */
13827
+ sha256: string(),
13828
+ bytes: number(),
13829
+ /** The target node's modelsDir the artifact landed in. */
13830
+ path: string()
13831
+ }), {
13832
+ kind: "mutation",
13833
+ auth: "admin"
13834
+ });
13835
+ method(object({
13836
+ sourceUrl: string(),
13837
+ metadata: ModelConvertMetadataSchema,
13838
+ targets: array(ConvertTargetSchema).min(1).readonly(),
13839
+ calibrationRef: string().optional(),
13840
+ sessionId: string().optional()
13841
+ }), ConvertResultSchema, {
13842
+ kind: "mutation",
13843
+ auth: "admin"
13844
+ });
13670
13845
  var AddonHttpRouteSchema = object({
13671
13846
  method: _enum([
13672
13847
  "GET",
@@ -18916,6 +19091,12 @@ Object.freeze({
18916
19091
  addonId: null,
18917
19092
  access: "create"
18918
19093
  },
19094
+ "customModelRegistry.listModels": {
19095
+ capName: "custom-model-registry",
19096
+ capScope: "system",
19097
+ addonId: null,
19098
+ access: "view"
19099
+ },
18919
19100
  "decoder.createSession": {
18920
19101
  capName: "decoder",
18921
19102
  capScope: "system",
@@ -20140,6 +20321,18 @@ Object.freeze({
20140
20321
  addonId: null,
20141
20322
  access: "view"
20142
20323
  },
20324
+ "modelConvert.convert": {
20325
+ capName: "model-convert",
20326
+ capScope: "system",
20327
+ addonId: null,
20328
+ access: "create"
20329
+ },
20330
+ "modelDistributor.distributeModel": {
20331
+ capName: "model-distributor",
20332
+ capScope: "system",
20333
+ addonId: null,
20334
+ access: "create"
20335
+ },
20143
20336
  "motion.isDetected": {
20144
20337
  capName: "motion",
20145
20338
  capScope: "device",
@@ -3,7 +3,7 @@ import { createReadStream, promises } from "node:fs";
3
3
  import * as path$1 from "node:path";
4
4
  import path from "node:path";
5
5
  import "node:crypto";
6
- //#region ../system/dist/model-download-service-RxAOiYvX.mjs
6
+ //#region ../system/dist/model-download-service-C-IHWnXx.mjs
7
7
  /**
8
8
  * Map a rel path to one candidate absolute path PER root, keeping only roots the
9
9
  * path stays within (traversal guard). The handler serves the first candidate
@@ -25,7 +25,7 @@ node_fs = __toESM(node_fs, 1);
25
25
  let node_path = require("node:path");
26
26
  node_path = __toESM(node_path, 1);
27
27
  require("node:crypto");
28
- //#region ../system/dist/model-download-service-RxAOiYvX.mjs
28
+ //#region ../system/dist/model-download-service-C-IHWnXx.mjs
29
29
  /**
30
30
  * Map a rel path to one candidate absolute path PER root, keeping only roots the
31
31
  * path stays within (traversal guard). The handler serves the first candidate
@@ -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-BLcTVvol.js");
5
+ const require_dist = require("../dist-DnD2tm7T.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 { B as BaseAddon, J as hydrateSchema, U as DeviceType, k as motionDetectionCapability, w as evaluateZoneRules } from "../dist-BA6DR_jV.mjs";
1
+ import { B as BaseAddon, J as hydrateSchema, U as DeviceType, k as motionDetectionCapability, w as evaluateZoneRules } from "../dist-BWc-HYQz.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
@@ -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-BLcTVvol.js");
5
+ const require_dist = require("../dist-DnD2tm7T.js");
6
6
  let _camstack_shm_ring = require("@camstack/shm-ring");
7
7
  //#region src/pipeline-runner/frame-queue.ts
8
8
  /**
@@ -903,6 +903,7 @@ var RunSyntheticBenchInputSchema = require_dist.object({
903
903
  warmup: require_dist.number().int().min(0).max(100).optional(),
904
904
  sessionId: require_dist.string().optional(),
905
905
  simulatePipeline: require_dist.boolean().optional(),
906
+ nodeId: require_dist.string().optional(),
906
907
  engine: BenchEngineChoiceSchema.optional()
907
908
  });
908
909
  var TimingSplitSchema = require_dist.object({
@@ -1171,10 +1172,13 @@ var PipelineRunnerAddon = class extends require_dist.BaseAddon {
1171
1172
  const ctx = this.ctx;
1172
1173
  const api = ctx.api;
1173
1174
  if (!api) throw new Error("runSyntheticBench: ctx.api unavailable");
1175
+ const benchNode = input.nodeId ?? this.nodeId;
1176
+ const pin = require_dist.nodePin(benchNode);
1174
1177
  ctx.logger.info("runSyntheticBench input", { meta: {
1175
1178
  frameId: input.frameId,
1176
1179
  parallel: input.parallel,
1177
- iterations: input.iterations
1180
+ iterations: input.iterations,
1181
+ node: benchNode
1178
1182
  } });
1179
1183
  const cached = this.benchFrameCache.get(input.frameId);
1180
1184
  if (!cached) throw new Error(`runSyntheticBench: frameId ${input.frameId} not cached (call cacheBenchFrame first)`);
@@ -1205,17 +1209,17 @@ var PipelineRunnerAddon = class extends require_dist.BaseAddon {
1205
1209
  width: cached.width,
1206
1210
  height: cached.height,
1207
1211
  format: cached.format
1208
- })).frameId;
1212
+ }, pin)).frameId;
1209
1213
  await api.pipelineExecutor.runPipeline.mutate({
1210
1214
  steps: stepsToRun,
1211
1215
  frame: sharedFrame,
1212
1216
  ...input.engine ? { engine: input.engine } : {}
1213
- });
1217
+ }, pin);
1214
1218
  const warmupCount = input.warmup ?? 1;
1215
1219
  for (let w = 0; w < warmupCount; w++) await api.pipelineExecutor.inferCached.mutate({
1216
1220
  stepId: rootStep.addonId,
1217
1221
  frameId: poolFrameId
1218
- });
1222
+ }, pin);
1219
1223
  const wallTimings = [];
1220
1224
  const inferTimings = [];
1221
1225
  const preprocessTimings = [];
@@ -1232,7 +1236,7 @@ var PipelineRunnerAddon = class extends require_dist.BaseAddon {
1232
1236
  const result = await api.pipelineExecutor.inferCached.mutate({
1233
1237
  stepId: rootStep.addonId,
1234
1238
  frameId: poolFrameId
1235
- });
1239
+ }, pin);
1236
1240
  const wallMs = performance.now() - t0;
1237
1241
  const r = result;
1238
1242
  const inferMs = typeof r["inferenceMs"] === "number" ? r["inferenceMs"] : wallMs;
@@ -1274,7 +1278,7 @@ var PipelineRunnerAddon = class extends require_dist.BaseAddon {
1274
1278
  },
1275
1279
  category: require_dist.EventCategory.PipelineProgress,
1276
1280
  data: {
1277
- nodeId: "hub",
1281
+ nodeId: benchNode,
1278
1282
  sessionId,
1279
1283
  step: "synthetic-bench",
1280
1284
  message: msg,
@@ -1298,7 +1302,7 @@ var PipelineRunnerAddon = class extends require_dist.BaseAddon {
1298
1302
  };
1299
1303
  await Promise.all(Array.from({ length: input.parallel }, () => worker()));
1300
1304
  const wallSec = (performance.now() - wallStart) / 1e3;
1301
- await api.pipelineExecutor.uncacheFrame.mutate({ frameId: poolFrameId }).catch(() => {});
1305
+ await api.pipelineExecutor.uncacheFrame.mutate({ frameId: poolFrameId }, pin).catch(() => {});
1302
1306
  return this.buildBenchResult(wallTimings, inferTimings, preprocessTimings, predictTimings, batchSizes, detCounts, wallSec, "cached");
1303
1307
  }
1304
1308
  ctx.logger.info("synthetic bench: using full runPipeline path", { meta: {
@@ -1312,7 +1316,7 @@ var PipelineRunnerAddon = class extends require_dist.BaseAddon {
1312
1316
  steps: stepsToRun,
1313
1317
  frame: sharedFrame,
1314
1318
  ...input.engine ? { engine: input.engine } : {}
1315
- });
1319
+ }, pin);
1316
1320
  const wallMs = performance.now() - t0;
1317
1321
  const n = ++_callCount;
1318
1322
  if (n <= 20) ctx.logger.info("bench call trace", { meta: {
@@ -1368,7 +1372,7 @@ var PipelineRunnerAddon = class extends require_dist.BaseAddon {
1368
1372
  },
1369
1373
  category: require_dist.EventCategory.PipelineProgress,
1370
1374
  data: {
1371
- nodeId: "hub",
1375
+ nodeId: benchNode,
1372
1376
  sessionId,
1373
1377
  step: "synthetic-bench",
1374
1378
  message: `runs ${n}/${totalRuns} \u00b7 ${fps.toFixed(1)} fps \u00b7 call ${meanMs.toFixed(1)}ms \u00b7 batch ${bsMean.toFixed(1)}`,