@camstack/addon-export-ha-mqtt 1.1.0 → 1.1.1

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.
@@ -4679,7 +4679,7 @@ function number(params) {
4679
4679
  return /* @__PURE__ */ _coercedNumber(ZodNumber, params);
4680
4680
  }
4681
4681
  //#endregion
4682
- //#region ../types/dist/sleep-B1dKJAMJ.mjs
4682
+ //#region ../types/dist/sleep-BV7rLc6Y.mjs
4683
4683
  var EventCategory = /* @__PURE__ */ function(EventCategory) {
4684
4684
  EventCategory["SystemBoot"] = "system.boot";
4685
4685
  EventCategory["SystemAddonsReady"] = "system.addons-ready";
@@ -5158,6 +5158,12 @@ var EventCategory = /* @__PURE__ */ function(EventCategory) {
5158
5158
  * Payload: `{ deviceId, childDeviceIds, hiddenChildIds }`.
5159
5159
  */
5160
5160
  EventCategory["AccessoriesChanged"] = "accessories.onAccessoriesChanged";
5161
+ /**
5162
+ * Progress update from a running model conversion job.
5163
+ * Payload: `{ kind: 'model-convert', phase, sessionId?, pct?, detail? }`.
5164
+ * Emitted by `addon-model-studio` on the converting node.
5165
+ */
5166
+ EventCategory["ModelConvertProgress"] = "model-convert.progress";
5161
5167
  return EventCategory;
5162
5168
  }({});
5163
5169
  Object.fromEntries([
@@ -6679,6 +6685,13 @@ object({
6679
6685
  unreachable: number$1()
6680
6686
  })
6681
6687
  });
6688
+ var LabelDefinitionSchema = object({
6689
+ id: string(),
6690
+ name: string(),
6691
+ category: string().optional(),
6692
+ description: string().optional(),
6693
+ icon: string().optional()
6694
+ });
6682
6695
  var MODEL_FORMATS = [
6683
6696
  "onnx",
6684
6697
  "coreml",
@@ -6687,6 +6700,120 @@ var MODEL_FORMATS = [
6687
6700
  "pt"
6688
6701
  ];
6689
6702
  /**
6703
+ * Multi-file format payload.
6704
+ *
6705
+ * - Directory formats (`isDirectory: true`, e.g. `.mlpackage`): files
6706
+ * relative to the directory root — the downloader fetches each from
6707
+ * `{url}/{file}` into `{modelDir}/{file}`. If omitted, it probes the
6708
+ * HuggingFace API (slower).
6709
+ * - Single-file formats (no `isDirectory`, e.g. OpenVINO IR): sibling
6710
+ * files fetched from the SAME remote directory as `url` and stored flat
6711
+ * alongside the main file — e.g. `['camstack-yolov9t.bin']` for the IR
6712
+ * weights next to `camstack-yolov9t.xml`.
6713
+ */
6714
+ var ModelFormatEntrySchema = object({
6715
+ url: string(),
6716
+ sizeMB: number$1(),
6717
+ /** Whether this format is a directory bundle (e.g., .mlpackage) rather than a single file */
6718
+ isDirectory: boolean().optional(),
6719
+ /** Multi-file payload (directory members or sibling files). */
6720
+ files: array(string()).readonly().optional(),
6721
+ /** Runtime(s) that can use this format. If omitted, inferred from ModelFormat key */
6722
+ runtimes: array(_enum(["node", "python"])).readonly().optional()
6723
+ });
6724
+ /**
6725
+ * Extra file that must be downloaded alongside the model (e.g., labels JSON, dict.txt).
6726
+ * The downloader fetches from `url` and saves to `{modelsDir}/{filename}`.
6727
+ */
6728
+ var ModelExtraFileSchema = object({
6729
+ url: string(),
6730
+ filename: string(),
6731
+ sizeMB: number$1()
6732
+ });
6733
+ /**
6734
+ * Per-format payload map. Modelled as an explicit object (one optional key
6735
+ * per `ModelFormat`) rather than `z.record(enum, …)` — zod v4's enum-keyed
6736
+ * record requires every key, but a catalog entry only ships a subset of
6737
+ * formats.
6738
+ */
6739
+ var ModelFormatsSchema = object({
6740
+ onnx: ModelFormatEntrySchema.optional(),
6741
+ coreml: ModelFormatEntrySchema.optional(),
6742
+ openvino: ModelFormatEntrySchema.optional(),
6743
+ tflite: ModelFormatEntrySchema.optional(),
6744
+ pt: ModelFormatEntrySchema.optional()
6745
+ });
6746
+ var ModelCatalogEntrySchema = object({
6747
+ id: string(),
6748
+ name: string(),
6749
+ description: string(),
6750
+ formats: ModelFormatsSchema,
6751
+ inputSize: object({
6752
+ width: number$1(),
6753
+ height: number$1()
6754
+ }),
6755
+ labels: array(LabelDefinitionSchema).readonly(),
6756
+ inputLayout: _enum(["nchw", "nhwc"]).optional(),
6757
+ inputNormalization: _enum([
6758
+ "zero-one",
6759
+ "imagenet",
6760
+ "none"
6761
+ ]).optional(),
6762
+ preprocessMode: _enum(["letterbox", "resize"]).optional(),
6763
+ /**
6764
+ * When true, the executor produces a landmark-aligned crop (similarity warp
6765
+ * onto the canonical template) before this step runs, instead of a plain
6766
+ * axis-aligned bbox crop. Required for face-recognition embedders (ArcFace):
6767
+ * their embeddings are only discriminative on an aligned input. The face
6768
+ * detector that produced the parent detail must emit 5 landmarks.
6769
+ */
6770
+ faceAlignment: boolean().optional(),
6771
+ /**
6772
+ * Auxiliary files required at runtime (labels JSON, charset dict, etc.).
6773
+ * Downloaded into the same modelsDir alongside the model file.
6774
+ */
6775
+ extraFiles: array(ModelExtraFileSchema).readonly().optional()
6776
+ });
6777
+ var ConvertTargetSchema = discriminatedUnion("format", [object({
6778
+ format: literal("openvino"),
6779
+ precisions: array(_enum(["fp16", "int8"])).min(1).readonly()
6780
+ }), object({ format: literal("coreml") })]);
6781
+ var ModelConvertMetadataSchema = object({
6782
+ id: string().regex(/^[a-zA-Z0-9._-]+$/),
6783
+ name: string(),
6784
+ labels: array(LabelDefinitionSchema).readonly(),
6785
+ inputSize: object({
6786
+ width: number$1(),
6787
+ height: number$1()
6788
+ }),
6789
+ inputLayout: _enum(["nchw", "nhwc"]).optional(),
6790
+ inputNormalization: _enum([
6791
+ "zero-one",
6792
+ "imagenet",
6793
+ "none"
6794
+ ]).optional(),
6795
+ preprocessMode: _enum(["letterbox", "resize"]).optional(),
6796
+ outputFormat: _enum([
6797
+ "yolo",
6798
+ "ssd",
6799
+ "embedding",
6800
+ "classification",
6801
+ "ocr",
6802
+ "segmentation"
6803
+ ]),
6804
+ faceAlignment: boolean().optional()
6805
+ });
6806
+ var ConvertResultSchema = object({
6807
+ entry: ModelCatalogEntrySchema,
6808
+ artifacts: array(object({
6809
+ format: _enum(MODEL_FORMATS),
6810
+ precision: _enum(["fp16", "int8"]).optional(),
6811
+ sizeMB: number$1(),
6812
+ validated: boolean(),
6813
+ files: array(string()).readonly()
6814
+ })).readonly()
6815
+ });
6816
+ /**
6690
6817
  * Numeric day-of-week: 0 = Sunday … 6 = Saturday (matches `Date.getDay`).
6691
6818
  * Named `RecordingWeekday` to avoid collision with the string-union
6692
6819
  * `Weekday` exported from `interfaces/timezones.ts`.
@@ -12550,6 +12677,54 @@ var EnrichedWidgetMetadataSchema = WidgetMetadataSchema.extend({
12550
12677
  bundleUrl: string()
12551
12678
  });
12552
12679
  method(_void(), array(EnrichedWidgetMetadataSchema).readonly());
12680
+ /**
12681
+ * `custom-model-registry` — collection cap exposing operator-registered
12682
+ * custom detection models. Each provider (today: `addon-model-studio`)
12683
+ * contributes a list of `CustomModelDescriptor`s; the hub auto-concatenates
12684
+ * them across providers (`concatCollection`).
12685
+ *
12686
+ * The detection-pipeline is *aware* of this cap: when at least one provider
12687
+ * exists it unions these descriptors into the per-step model picker and the
12688
+ * runtime model-resolution path, alongside the static catalog. When no
12689
+ * provider exists the consumer no-ops entirely (identical to the catalog-only
12690
+ * behaviour).
12691
+ *
12692
+ * A descriptor carries a full `ModelCatalogEntry` directly — the same shape
12693
+ * the static catalog uses — so the existing download/resolution code consumes
12694
+ * it unchanged. `stepId` is the detection step the model targets
12695
+ * (e.g. `'object-detection'`).
12696
+ */
12697
+ var CustomModelDescriptorSchema = object({
12698
+ stepId: string(),
12699
+ entry: ModelCatalogEntrySchema
12700
+ });
12701
+ method(_void(), array(CustomModelDescriptorSchema).readonly());
12702
+ method(object({
12703
+ nodeId: string(),
12704
+ modelId: string(),
12705
+ format: _enum(MODEL_FORMATS),
12706
+ entry: ModelCatalogEntrySchema
12707
+ }), object({
12708
+ ok: boolean(),
12709
+ /** sha256 of the staged tarball (empty for a hub-local no-op). */
12710
+ sha256: string(),
12711
+ bytes: number$1(),
12712
+ /** The target node's modelsDir the artifact landed in. */
12713
+ path: string()
12714
+ }), {
12715
+ kind: "mutation",
12716
+ auth: "admin"
12717
+ });
12718
+ method(object({
12719
+ sourceUrl: string(),
12720
+ metadata: ModelConvertMetadataSchema,
12721
+ targets: array(ConvertTargetSchema).min(1).readonly(),
12722
+ calibrationRef: string().optional(),
12723
+ sessionId: string().optional()
12724
+ }), ConvertResultSchema, {
12725
+ kind: "mutation",
12726
+ auth: "admin"
12727
+ });
12553
12728
  var AddonHttpRouteSchema = object({
12554
12729
  method: _enum([
12555
12730
  "GET",
@@ -17444,6 +17619,12 @@ Object.freeze({
17444
17619
  addonId: null,
17445
17620
  access: "create"
17446
17621
  },
17622
+ "customModelRegistry.listModels": {
17623
+ capName: "custom-model-registry",
17624
+ capScope: "system",
17625
+ addonId: null,
17626
+ access: "view"
17627
+ },
17447
17628
  "decoder.createSession": {
17448
17629
  capName: "decoder",
17449
17630
  capScope: "system",
@@ -18668,6 +18849,18 @@ Object.freeze({
18668
18849
  addonId: null,
18669
18850
  access: "view"
18670
18851
  },
18852
+ "modelConvert.convert": {
18853
+ capName: "model-convert",
18854
+ capScope: "system",
18855
+ addonId: null,
18856
+ access: "create"
18857
+ },
18858
+ "modelDistributor.distributeModel": {
18859
+ capName: "model-distributor",
18860
+ capScope: "system",
18861
+ addonId: null,
18862
+ access: "create"
18863
+ },
18671
18864
  "motion.isDetected": {
18672
18865
  capName: "motion",
18673
18866
  capScope: "device",
@@ -4677,7 +4677,7 @@ function number(params) {
4677
4677
  return /* @__PURE__ */ _coercedNumber(ZodNumber, params);
4678
4678
  }
4679
4679
  //#endregion
4680
- //#region ../types/dist/sleep-B1dKJAMJ.mjs
4680
+ //#region ../types/dist/sleep-BV7rLc6Y.mjs
4681
4681
  var EventCategory = /* @__PURE__ */ function(EventCategory) {
4682
4682
  EventCategory["SystemBoot"] = "system.boot";
4683
4683
  EventCategory["SystemAddonsReady"] = "system.addons-ready";
@@ -5156,6 +5156,12 @@ var EventCategory = /* @__PURE__ */ function(EventCategory) {
5156
5156
  * Payload: `{ deviceId, childDeviceIds, hiddenChildIds }`.
5157
5157
  */
5158
5158
  EventCategory["AccessoriesChanged"] = "accessories.onAccessoriesChanged";
5159
+ /**
5160
+ * Progress update from a running model conversion job.
5161
+ * Payload: `{ kind: 'model-convert', phase, sessionId?, pct?, detail? }`.
5162
+ * Emitted by `addon-model-studio` on the converting node.
5163
+ */
5164
+ EventCategory["ModelConvertProgress"] = "model-convert.progress";
5159
5165
  return EventCategory;
5160
5166
  }({});
5161
5167
  Object.fromEntries([
@@ -6677,6 +6683,13 @@ object({
6677
6683
  unreachable: number$1()
6678
6684
  })
6679
6685
  });
6686
+ var LabelDefinitionSchema = object({
6687
+ id: string(),
6688
+ name: string(),
6689
+ category: string().optional(),
6690
+ description: string().optional(),
6691
+ icon: string().optional()
6692
+ });
6680
6693
  var MODEL_FORMATS = [
6681
6694
  "onnx",
6682
6695
  "coreml",
@@ -6685,6 +6698,120 @@ var MODEL_FORMATS = [
6685
6698
  "pt"
6686
6699
  ];
6687
6700
  /**
6701
+ * Multi-file format payload.
6702
+ *
6703
+ * - Directory formats (`isDirectory: true`, e.g. `.mlpackage`): files
6704
+ * relative to the directory root — the downloader fetches each from
6705
+ * `{url}/{file}` into `{modelDir}/{file}`. If omitted, it probes the
6706
+ * HuggingFace API (slower).
6707
+ * - Single-file formats (no `isDirectory`, e.g. OpenVINO IR): sibling
6708
+ * files fetched from the SAME remote directory as `url` and stored flat
6709
+ * alongside the main file — e.g. `['camstack-yolov9t.bin']` for the IR
6710
+ * weights next to `camstack-yolov9t.xml`.
6711
+ */
6712
+ var ModelFormatEntrySchema = object({
6713
+ url: string(),
6714
+ sizeMB: number$1(),
6715
+ /** Whether this format is a directory bundle (e.g., .mlpackage) rather than a single file */
6716
+ isDirectory: boolean().optional(),
6717
+ /** Multi-file payload (directory members or sibling files). */
6718
+ files: array(string()).readonly().optional(),
6719
+ /** Runtime(s) that can use this format. If omitted, inferred from ModelFormat key */
6720
+ runtimes: array(_enum(["node", "python"])).readonly().optional()
6721
+ });
6722
+ /**
6723
+ * Extra file that must be downloaded alongside the model (e.g., labels JSON, dict.txt).
6724
+ * The downloader fetches from `url` and saves to `{modelsDir}/{filename}`.
6725
+ */
6726
+ var ModelExtraFileSchema = object({
6727
+ url: string(),
6728
+ filename: string(),
6729
+ sizeMB: number$1()
6730
+ });
6731
+ /**
6732
+ * Per-format payload map. Modelled as an explicit object (one optional key
6733
+ * per `ModelFormat`) rather than `z.record(enum, …)` — zod v4's enum-keyed
6734
+ * record requires every key, but a catalog entry only ships a subset of
6735
+ * formats.
6736
+ */
6737
+ var ModelFormatsSchema = object({
6738
+ onnx: ModelFormatEntrySchema.optional(),
6739
+ coreml: ModelFormatEntrySchema.optional(),
6740
+ openvino: ModelFormatEntrySchema.optional(),
6741
+ tflite: ModelFormatEntrySchema.optional(),
6742
+ pt: ModelFormatEntrySchema.optional()
6743
+ });
6744
+ var ModelCatalogEntrySchema = object({
6745
+ id: string(),
6746
+ name: string(),
6747
+ description: string(),
6748
+ formats: ModelFormatsSchema,
6749
+ inputSize: object({
6750
+ width: number$1(),
6751
+ height: number$1()
6752
+ }),
6753
+ labels: array(LabelDefinitionSchema).readonly(),
6754
+ inputLayout: _enum(["nchw", "nhwc"]).optional(),
6755
+ inputNormalization: _enum([
6756
+ "zero-one",
6757
+ "imagenet",
6758
+ "none"
6759
+ ]).optional(),
6760
+ preprocessMode: _enum(["letterbox", "resize"]).optional(),
6761
+ /**
6762
+ * When true, the executor produces a landmark-aligned crop (similarity warp
6763
+ * onto the canonical template) before this step runs, instead of a plain
6764
+ * axis-aligned bbox crop. Required for face-recognition embedders (ArcFace):
6765
+ * their embeddings are only discriminative on an aligned input. The face
6766
+ * detector that produced the parent detail must emit 5 landmarks.
6767
+ */
6768
+ faceAlignment: boolean().optional(),
6769
+ /**
6770
+ * Auxiliary files required at runtime (labels JSON, charset dict, etc.).
6771
+ * Downloaded into the same modelsDir alongside the model file.
6772
+ */
6773
+ extraFiles: array(ModelExtraFileSchema).readonly().optional()
6774
+ });
6775
+ var ConvertTargetSchema = discriminatedUnion("format", [object({
6776
+ format: literal("openvino"),
6777
+ precisions: array(_enum(["fp16", "int8"])).min(1).readonly()
6778
+ }), object({ format: literal("coreml") })]);
6779
+ var ModelConvertMetadataSchema = object({
6780
+ id: string().regex(/^[a-zA-Z0-9._-]+$/),
6781
+ name: string(),
6782
+ labels: array(LabelDefinitionSchema).readonly(),
6783
+ inputSize: object({
6784
+ width: number$1(),
6785
+ height: number$1()
6786
+ }),
6787
+ inputLayout: _enum(["nchw", "nhwc"]).optional(),
6788
+ inputNormalization: _enum([
6789
+ "zero-one",
6790
+ "imagenet",
6791
+ "none"
6792
+ ]).optional(),
6793
+ preprocessMode: _enum(["letterbox", "resize"]).optional(),
6794
+ outputFormat: _enum([
6795
+ "yolo",
6796
+ "ssd",
6797
+ "embedding",
6798
+ "classification",
6799
+ "ocr",
6800
+ "segmentation"
6801
+ ]),
6802
+ faceAlignment: boolean().optional()
6803
+ });
6804
+ var ConvertResultSchema = object({
6805
+ entry: ModelCatalogEntrySchema,
6806
+ artifacts: array(object({
6807
+ format: _enum(MODEL_FORMATS),
6808
+ precision: _enum(["fp16", "int8"]).optional(),
6809
+ sizeMB: number$1(),
6810
+ validated: boolean(),
6811
+ files: array(string()).readonly()
6812
+ })).readonly()
6813
+ });
6814
+ /**
6688
6815
  * Numeric day-of-week: 0 = Sunday … 6 = Saturday (matches `Date.getDay`).
6689
6816
  * Named `RecordingWeekday` to avoid collision with the string-union
6690
6817
  * `Weekday` exported from `interfaces/timezones.ts`.
@@ -12548,6 +12675,54 @@ var EnrichedWidgetMetadataSchema = WidgetMetadataSchema.extend({
12548
12675
  bundleUrl: string()
12549
12676
  });
12550
12677
  method(_void(), array(EnrichedWidgetMetadataSchema).readonly());
12678
+ /**
12679
+ * `custom-model-registry` — collection cap exposing operator-registered
12680
+ * custom detection models. Each provider (today: `addon-model-studio`)
12681
+ * contributes a list of `CustomModelDescriptor`s; the hub auto-concatenates
12682
+ * them across providers (`concatCollection`).
12683
+ *
12684
+ * The detection-pipeline is *aware* of this cap: when at least one provider
12685
+ * exists it unions these descriptors into the per-step model picker and the
12686
+ * runtime model-resolution path, alongside the static catalog. When no
12687
+ * provider exists the consumer no-ops entirely (identical to the catalog-only
12688
+ * behaviour).
12689
+ *
12690
+ * A descriptor carries a full `ModelCatalogEntry` directly — the same shape
12691
+ * the static catalog uses — so the existing download/resolution code consumes
12692
+ * it unchanged. `stepId` is the detection step the model targets
12693
+ * (e.g. `'object-detection'`).
12694
+ */
12695
+ var CustomModelDescriptorSchema = object({
12696
+ stepId: string(),
12697
+ entry: ModelCatalogEntrySchema
12698
+ });
12699
+ method(_void(), array(CustomModelDescriptorSchema).readonly());
12700
+ method(object({
12701
+ nodeId: string(),
12702
+ modelId: string(),
12703
+ format: _enum(MODEL_FORMATS),
12704
+ entry: ModelCatalogEntrySchema
12705
+ }), object({
12706
+ ok: boolean(),
12707
+ /** sha256 of the staged tarball (empty for a hub-local no-op). */
12708
+ sha256: string(),
12709
+ bytes: number$1(),
12710
+ /** The target node's modelsDir the artifact landed in. */
12711
+ path: string()
12712
+ }), {
12713
+ kind: "mutation",
12714
+ auth: "admin"
12715
+ });
12716
+ method(object({
12717
+ sourceUrl: string(),
12718
+ metadata: ModelConvertMetadataSchema,
12719
+ targets: array(ConvertTargetSchema).min(1).readonly(),
12720
+ calibrationRef: string().optional(),
12721
+ sessionId: string().optional()
12722
+ }), ConvertResultSchema, {
12723
+ kind: "mutation",
12724
+ auth: "admin"
12725
+ });
12551
12726
  var AddonHttpRouteSchema = object({
12552
12727
  method: _enum([
12553
12728
  "GET",
@@ -17442,6 +17617,12 @@ Object.freeze({
17442
17617
  addonId: null,
17443
17618
  access: "create"
17444
17619
  },
17620
+ "customModelRegistry.listModels": {
17621
+ capName: "custom-model-registry",
17622
+ capScope: "system",
17623
+ addonId: null,
17624
+ access: "view"
17625
+ },
17445
17626
  "decoder.createSession": {
17446
17627
  capName: "decoder",
17447
17628
  capScope: "system",
@@ -18666,6 +18847,18 @@ Object.freeze({
18666
18847
  addonId: null,
18667
18848
  access: "view"
18668
18849
  },
18850
+ "modelConvert.convert": {
18851
+ capName: "model-convert",
18852
+ capScope: "system",
18853
+ addonId: null,
18854
+ access: "create"
18855
+ },
18856
+ "modelDistributor.distributeModel": {
18857
+ capName: "model-distributor",
18858
+ capScope: "system",
18859
+ addonId: null,
18860
+ access: "create"
18861
+ },
18669
18862
  "motion.isDetected": {
18670
18863
  capName: "motion",
18671
18864
  capScope: "device",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@camstack/addon-export-ha-mqtt",
3
- "version": "1.1.0",
3
+ "version": "1.1.1",
4
4
  "description": "HomeAssistant MQTT discovery exporter for CamStack devices. Publishes discovery topics so HA auto-creates entities for exposed cameras/switches/intercoms/sensors.",
5
5
  "keywords": [
6
6
  "camstack",