@camstack/addon-export-hap 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.
@@ -4664,7 +4664,7 @@ function _instanceof(cls, params = {}) {
4664
4664
  return inst;
4665
4665
  }
4666
4666
  //#endregion
4667
- //#region ../types/dist/sleep-B1dKJAMJ.mjs
4667
+ //#region ../types/dist/sleep-BV7rLc6Y.mjs
4668
4668
  var EventCategory = /* @__PURE__ */ function(EventCategory) {
4669
4669
  EventCategory["SystemBoot"] = "system.boot";
4670
4670
  EventCategory["SystemAddonsReady"] = "system.addons-ready";
@@ -5143,6 +5143,12 @@ var EventCategory = /* @__PURE__ */ function(EventCategory) {
5143
5143
  * Payload: `{ deviceId, childDeviceIds, hiddenChildIds }`.
5144
5144
  */
5145
5145
  EventCategory["AccessoriesChanged"] = "accessories.onAccessoriesChanged";
5146
+ /**
5147
+ * Progress update from a running model conversion job.
5148
+ * Payload: `{ kind: 'model-convert', phase, sessionId?, pct?, detail? }`.
5149
+ * Emitted by `addon-model-studio` on the converting node.
5150
+ */
5151
+ EventCategory["ModelConvertProgress"] = "model-convert.progress";
5146
5152
  return EventCategory;
5147
5153
  }({});
5148
5154
  Object.fromEntries([
@@ -6664,6 +6670,13 @@ object({
6664
6670
  unreachable: number()
6665
6671
  })
6666
6672
  });
6673
+ var LabelDefinitionSchema = object({
6674
+ id: string(),
6675
+ name: string(),
6676
+ category: string().optional(),
6677
+ description: string().optional(),
6678
+ icon: string().optional()
6679
+ });
6667
6680
  var MODEL_FORMATS = [
6668
6681
  "onnx",
6669
6682
  "coreml",
@@ -6672,6 +6685,120 @@ var MODEL_FORMATS = [
6672
6685
  "pt"
6673
6686
  ];
6674
6687
  /**
6688
+ * Multi-file format payload.
6689
+ *
6690
+ * - Directory formats (`isDirectory: true`, e.g. `.mlpackage`): files
6691
+ * relative to the directory root — the downloader fetches each from
6692
+ * `{url}/{file}` into `{modelDir}/{file}`. If omitted, it probes the
6693
+ * HuggingFace API (slower).
6694
+ * - Single-file formats (no `isDirectory`, e.g. OpenVINO IR): sibling
6695
+ * files fetched from the SAME remote directory as `url` and stored flat
6696
+ * alongside the main file — e.g. `['camstack-yolov9t.bin']` for the IR
6697
+ * weights next to `camstack-yolov9t.xml`.
6698
+ */
6699
+ var ModelFormatEntrySchema = object({
6700
+ url: string(),
6701
+ sizeMB: number(),
6702
+ /** Whether this format is a directory bundle (e.g., .mlpackage) rather than a single file */
6703
+ isDirectory: boolean().optional(),
6704
+ /** Multi-file payload (directory members or sibling files). */
6705
+ files: array(string()).readonly().optional(),
6706
+ /** Runtime(s) that can use this format. If omitted, inferred from ModelFormat key */
6707
+ runtimes: array(_enum(["node", "python"])).readonly().optional()
6708
+ });
6709
+ /**
6710
+ * Extra file that must be downloaded alongside the model (e.g., labels JSON, dict.txt).
6711
+ * The downloader fetches from `url` and saves to `{modelsDir}/{filename}`.
6712
+ */
6713
+ var ModelExtraFileSchema = object({
6714
+ url: string(),
6715
+ filename: string(),
6716
+ sizeMB: number()
6717
+ });
6718
+ /**
6719
+ * Per-format payload map. Modelled as an explicit object (one optional key
6720
+ * per `ModelFormat`) rather than `z.record(enum, …)` — zod v4's enum-keyed
6721
+ * record requires every key, but a catalog entry only ships a subset of
6722
+ * formats.
6723
+ */
6724
+ var ModelFormatsSchema = object({
6725
+ onnx: ModelFormatEntrySchema.optional(),
6726
+ coreml: ModelFormatEntrySchema.optional(),
6727
+ openvino: ModelFormatEntrySchema.optional(),
6728
+ tflite: ModelFormatEntrySchema.optional(),
6729
+ pt: ModelFormatEntrySchema.optional()
6730
+ });
6731
+ var ModelCatalogEntrySchema = object({
6732
+ id: string(),
6733
+ name: string(),
6734
+ description: string(),
6735
+ formats: ModelFormatsSchema,
6736
+ inputSize: object({
6737
+ width: number(),
6738
+ height: number()
6739
+ }),
6740
+ labels: array(LabelDefinitionSchema).readonly(),
6741
+ inputLayout: _enum(["nchw", "nhwc"]).optional(),
6742
+ inputNormalization: _enum([
6743
+ "zero-one",
6744
+ "imagenet",
6745
+ "none"
6746
+ ]).optional(),
6747
+ preprocessMode: _enum(["letterbox", "resize"]).optional(),
6748
+ /**
6749
+ * When true, the executor produces a landmark-aligned crop (similarity warp
6750
+ * onto the canonical template) before this step runs, instead of a plain
6751
+ * axis-aligned bbox crop. Required for face-recognition embedders (ArcFace):
6752
+ * their embeddings are only discriminative on an aligned input. The face
6753
+ * detector that produced the parent detail must emit 5 landmarks.
6754
+ */
6755
+ faceAlignment: boolean().optional(),
6756
+ /**
6757
+ * Auxiliary files required at runtime (labels JSON, charset dict, etc.).
6758
+ * Downloaded into the same modelsDir alongside the model file.
6759
+ */
6760
+ extraFiles: array(ModelExtraFileSchema).readonly().optional()
6761
+ });
6762
+ var ConvertTargetSchema = discriminatedUnion("format", [object({
6763
+ format: literal("openvino"),
6764
+ precisions: array(_enum(["fp16", "int8"])).min(1).readonly()
6765
+ }), object({ format: literal("coreml") })]);
6766
+ var ModelConvertMetadataSchema = object({
6767
+ id: string().regex(/^[a-zA-Z0-9._-]+$/),
6768
+ name: string(),
6769
+ labels: array(LabelDefinitionSchema).readonly(),
6770
+ inputSize: object({
6771
+ width: number(),
6772
+ height: number()
6773
+ }),
6774
+ inputLayout: _enum(["nchw", "nhwc"]).optional(),
6775
+ inputNormalization: _enum([
6776
+ "zero-one",
6777
+ "imagenet",
6778
+ "none"
6779
+ ]).optional(),
6780
+ preprocessMode: _enum(["letterbox", "resize"]).optional(),
6781
+ outputFormat: _enum([
6782
+ "yolo",
6783
+ "ssd",
6784
+ "embedding",
6785
+ "classification",
6786
+ "ocr",
6787
+ "segmentation"
6788
+ ]),
6789
+ faceAlignment: boolean().optional()
6790
+ });
6791
+ var ConvertResultSchema = object({
6792
+ entry: ModelCatalogEntrySchema,
6793
+ artifacts: array(object({
6794
+ format: _enum(MODEL_FORMATS),
6795
+ precision: _enum(["fp16", "int8"]).optional(),
6796
+ sizeMB: number(),
6797
+ validated: boolean(),
6798
+ files: array(string()).readonly()
6799
+ })).readonly()
6800
+ });
6801
+ /**
6675
6802
  * Numeric day-of-week: 0 = Sunday … 6 = Saturday (matches `Date.getDay`).
6676
6803
  * Named `RecordingWeekday` to avoid collision with the string-union
6677
6804
  * `Weekday` exported from `interfaces/timezones.ts`.
@@ -12589,6 +12716,54 @@ var EnrichedWidgetMetadataSchema = WidgetMetadataSchema.extend({
12589
12716
  bundleUrl: string()
12590
12717
  });
12591
12718
  method(_void(), array(EnrichedWidgetMetadataSchema).readonly());
12719
+ /**
12720
+ * `custom-model-registry` — collection cap exposing operator-registered
12721
+ * custom detection models. Each provider (today: `addon-model-studio`)
12722
+ * contributes a list of `CustomModelDescriptor`s; the hub auto-concatenates
12723
+ * them across providers (`concatCollection`).
12724
+ *
12725
+ * The detection-pipeline is *aware* of this cap: when at least one provider
12726
+ * exists it unions these descriptors into the per-step model picker and the
12727
+ * runtime model-resolution path, alongside the static catalog. When no
12728
+ * provider exists the consumer no-ops entirely (identical to the catalog-only
12729
+ * behaviour).
12730
+ *
12731
+ * A descriptor carries a full `ModelCatalogEntry` directly — the same shape
12732
+ * the static catalog uses — so the existing download/resolution code consumes
12733
+ * it unchanged. `stepId` is the detection step the model targets
12734
+ * (e.g. `'object-detection'`).
12735
+ */
12736
+ var CustomModelDescriptorSchema = object({
12737
+ stepId: string(),
12738
+ entry: ModelCatalogEntrySchema
12739
+ });
12740
+ method(_void(), array(CustomModelDescriptorSchema).readonly());
12741
+ method(object({
12742
+ nodeId: string(),
12743
+ modelId: string(),
12744
+ format: _enum(MODEL_FORMATS),
12745
+ entry: ModelCatalogEntrySchema
12746
+ }), object({
12747
+ ok: boolean(),
12748
+ /** sha256 of the staged tarball (empty for a hub-local no-op). */
12749
+ sha256: string(),
12750
+ bytes: number(),
12751
+ /** The target node's modelsDir the artifact landed in. */
12752
+ path: string()
12753
+ }), {
12754
+ kind: "mutation",
12755
+ auth: "admin"
12756
+ });
12757
+ method(object({
12758
+ sourceUrl: string(),
12759
+ metadata: ModelConvertMetadataSchema,
12760
+ targets: array(ConvertTargetSchema).min(1).readonly(),
12761
+ calibrationRef: string().optional(),
12762
+ sessionId: string().optional()
12763
+ }), ConvertResultSchema, {
12764
+ kind: "mutation",
12765
+ auth: "admin"
12766
+ });
12592
12767
  var AddonHttpRouteSchema = object({
12593
12768
  method: _enum([
12594
12769
  "GET",
@@ -17483,6 +17658,12 @@ Object.freeze({
17483
17658
  addonId: null,
17484
17659
  access: "create"
17485
17660
  },
17661
+ "customModelRegistry.listModels": {
17662
+ capName: "custom-model-registry",
17663
+ capScope: "system",
17664
+ addonId: null,
17665
+ access: "view"
17666
+ },
17486
17667
  "decoder.createSession": {
17487
17668
  capName: "decoder",
17488
17669
  capScope: "system",
@@ -18707,6 +18888,18 @@ Object.freeze({
18707
18888
  addonId: null,
18708
18889
  access: "view"
18709
18890
  },
18891
+ "modelConvert.convert": {
18892
+ capName: "model-convert",
18893
+ capScope: "system",
18894
+ addonId: null,
18895
+ access: "create"
18896
+ },
18897
+ "modelDistributor.distributeModel": {
18898
+ capName: "model-distributor",
18899
+ capScope: "system",
18900
+ addonId: null,
18901
+ access: "create"
18902
+ },
18710
18903
  "motion.isDetected": {
18711
18904
  capName: "motion",
18712
18905
  capScope: "device",
@@ -4639,7 +4639,7 @@ function _instanceof(cls, params = {}) {
4639
4639
  return inst;
4640
4640
  }
4641
4641
  //#endregion
4642
- //#region ../types/dist/sleep-B1dKJAMJ.mjs
4642
+ //#region ../types/dist/sleep-BV7rLc6Y.mjs
4643
4643
  var EventCategory = /* @__PURE__ */ function(EventCategory) {
4644
4644
  EventCategory["SystemBoot"] = "system.boot";
4645
4645
  EventCategory["SystemAddonsReady"] = "system.addons-ready";
@@ -5118,6 +5118,12 @@ var EventCategory = /* @__PURE__ */ function(EventCategory) {
5118
5118
  * Payload: `{ deviceId, childDeviceIds, hiddenChildIds }`.
5119
5119
  */
5120
5120
  EventCategory["AccessoriesChanged"] = "accessories.onAccessoriesChanged";
5121
+ /**
5122
+ * Progress update from a running model conversion job.
5123
+ * Payload: `{ kind: 'model-convert', phase, sessionId?, pct?, detail? }`.
5124
+ * Emitted by `addon-model-studio` on the converting node.
5125
+ */
5126
+ EventCategory["ModelConvertProgress"] = "model-convert.progress";
5121
5127
  return EventCategory;
5122
5128
  }({});
5123
5129
  Object.fromEntries([
@@ -6639,6 +6645,13 @@ object({
6639
6645
  unreachable: number()
6640
6646
  })
6641
6647
  });
6648
+ var LabelDefinitionSchema = object({
6649
+ id: string(),
6650
+ name: string(),
6651
+ category: string().optional(),
6652
+ description: string().optional(),
6653
+ icon: string().optional()
6654
+ });
6642
6655
  var MODEL_FORMATS = [
6643
6656
  "onnx",
6644
6657
  "coreml",
@@ -6647,6 +6660,120 @@ var MODEL_FORMATS = [
6647
6660
  "pt"
6648
6661
  ];
6649
6662
  /**
6663
+ * Multi-file format payload.
6664
+ *
6665
+ * - Directory formats (`isDirectory: true`, e.g. `.mlpackage`): files
6666
+ * relative to the directory root — the downloader fetches each from
6667
+ * `{url}/{file}` into `{modelDir}/{file}`. If omitted, it probes the
6668
+ * HuggingFace API (slower).
6669
+ * - Single-file formats (no `isDirectory`, e.g. OpenVINO IR): sibling
6670
+ * files fetched from the SAME remote directory as `url` and stored flat
6671
+ * alongside the main file — e.g. `['camstack-yolov9t.bin']` for the IR
6672
+ * weights next to `camstack-yolov9t.xml`.
6673
+ */
6674
+ var ModelFormatEntrySchema = object({
6675
+ url: string(),
6676
+ sizeMB: number(),
6677
+ /** Whether this format is a directory bundle (e.g., .mlpackage) rather than a single file */
6678
+ isDirectory: boolean().optional(),
6679
+ /** Multi-file payload (directory members or sibling files). */
6680
+ files: array(string()).readonly().optional(),
6681
+ /** Runtime(s) that can use this format. If omitted, inferred from ModelFormat key */
6682
+ runtimes: array(_enum(["node", "python"])).readonly().optional()
6683
+ });
6684
+ /**
6685
+ * Extra file that must be downloaded alongside the model (e.g., labels JSON, dict.txt).
6686
+ * The downloader fetches from `url` and saves to `{modelsDir}/{filename}`.
6687
+ */
6688
+ var ModelExtraFileSchema = object({
6689
+ url: string(),
6690
+ filename: string(),
6691
+ sizeMB: number()
6692
+ });
6693
+ /**
6694
+ * Per-format payload map. Modelled as an explicit object (one optional key
6695
+ * per `ModelFormat`) rather than `z.record(enum, …)` — zod v4's enum-keyed
6696
+ * record requires every key, but a catalog entry only ships a subset of
6697
+ * formats.
6698
+ */
6699
+ var ModelFormatsSchema = object({
6700
+ onnx: ModelFormatEntrySchema.optional(),
6701
+ coreml: ModelFormatEntrySchema.optional(),
6702
+ openvino: ModelFormatEntrySchema.optional(),
6703
+ tflite: ModelFormatEntrySchema.optional(),
6704
+ pt: ModelFormatEntrySchema.optional()
6705
+ });
6706
+ var ModelCatalogEntrySchema = object({
6707
+ id: string(),
6708
+ name: string(),
6709
+ description: string(),
6710
+ formats: ModelFormatsSchema,
6711
+ inputSize: object({
6712
+ width: number(),
6713
+ height: number()
6714
+ }),
6715
+ labels: array(LabelDefinitionSchema).readonly(),
6716
+ inputLayout: _enum(["nchw", "nhwc"]).optional(),
6717
+ inputNormalization: _enum([
6718
+ "zero-one",
6719
+ "imagenet",
6720
+ "none"
6721
+ ]).optional(),
6722
+ preprocessMode: _enum(["letterbox", "resize"]).optional(),
6723
+ /**
6724
+ * When true, the executor produces a landmark-aligned crop (similarity warp
6725
+ * onto the canonical template) before this step runs, instead of a plain
6726
+ * axis-aligned bbox crop. Required for face-recognition embedders (ArcFace):
6727
+ * their embeddings are only discriminative on an aligned input. The face
6728
+ * detector that produced the parent detail must emit 5 landmarks.
6729
+ */
6730
+ faceAlignment: boolean().optional(),
6731
+ /**
6732
+ * Auxiliary files required at runtime (labels JSON, charset dict, etc.).
6733
+ * Downloaded into the same modelsDir alongside the model file.
6734
+ */
6735
+ extraFiles: array(ModelExtraFileSchema).readonly().optional()
6736
+ });
6737
+ var ConvertTargetSchema = discriminatedUnion("format", [object({
6738
+ format: literal("openvino"),
6739
+ precisions: array(_enum(["fp16", "int8"])).min(1).readonly()
6740
+ }), object({ format: literal("coreml") })]);
6741
+ var ModelConvertMetadataSchema = object({
6742
+ id: string().regex(/^[a-zA-Z0-9._-]+$/),
6743
+ name: string(),
6744
+ labels: array(LabelDefinitionSchema).readonly(),
6745
+ inputSize: object({
6746
+ width: number(),
6747
+ height: number()
6748
+ }),
6749
+ inputLayout: _enum(["nchw", "nhwc"]).optional(),
6750
+ inputNormalization: _enum([
6751
+ "zero-one",
6752
+ "imagenet",
6753
+ "none"
6754
+ ]).optional(),
6755
+ preprocessMode: _enum(["letterbox", "resize"]).optional(),
6756
+ outputFormat: _enum([
6757
+ "yolo",
6758
+ "ssd",
6759
+ "embedding",
6760
+ "classification",
6761
+ "ocr",
6762
+ "segmentation"
6763
+ ]),
6764
+ faceAlignment: boolean().optional()
6765
+ });
6766
+ var ConvertResultSchema = object({
6767
+ entry: ModelCatalogEntrySchema,
6768
+ artifacts: array(object({
6769
+ format: _enum(MODEL_FORMATS),
6770
+ precision: _enum(["fp16", "int8"]).optional(),
6771
+ sizeMB: number(),
6772
+ validated: boolean(),
6773
+ files: array(string()).readonly()
6774
+ })).readonly()
6775
+ });
6776
+ /**
6650
6777
  * Numeric day-of-week: 0 = Sunday … 6 = Saturday (matches `Date.getDay`).
6651
6778
  * Named `RecordingWeekday` to avoid collision with the string-union
6652
6779
  * `Weekday` exported from `interfaces/timezones.ts`.
@@ -12564,6 +12691,54 @@ var EnrichedWidgetMetadataSchema = WidgetMetadataSchema.extend({
12564
12691
  bundleUrl: string()
12565
12692
  });
12566
12693
  method(_void(), array(EnrichedWidgetMetadataSchema).readonly());
12694
+ /**
12695
+ * `custom-model-registry` — collection cap exposing operator-registered
12696
+ * custom detection models. Each provider (today: `addon-model-studio`)
12697
+ * contributes a list of `CustomModelDescriptor`s; the hub auto-concatenates
12698
+ * them across providers (`concatCollection`).
12699
+ *
12700
+ * The detection-pipeline is *aware* of this cap: when at least one provider
12701
+ * exists it unions these descriptors into the per-step model picker and the
12702
+ * runtime model-resolution path, alongside the static catalog. When no
12703
+ * provider exists the consumer no-ops entirely (identical to the catalog-only
12704
+ * behaviour).
12705
+ *
12706
+ * A descriptor carries a full `ModelCatalogEntry` directly — the same shape
12707
+ * the static catalog uses — so the existing download/resolution code consumes
12708
+ * it unchanged. `stepId` is the detection step the model targets
12709
+ * (e.g. `'object-detection'`).
12710
+ */
12711
+ var CustomModelDescriptorSchema = object({
12712
+ stepId: string(),
12713
+ entry: ModelCatalogEntrySchema
12714
+ });
12715
+ method(_void(), array(CustomModelDescriptorSchema).readonly());
12716
+ method(object({
12717
+ nodeId: string(),
12718
+ modelId: string(),
12719
+ format: _enum(MODEL_FORMATS),
12720
+ entry: ModelCatalogEntrySchema
12721
+ }), object({
12722
+ ok: boolean(),
12723
+ /** sha256 of the staged tarball (empty for a hub-local no-op). */
12724
+ sha256: string(),
12725
+ bytes: number(),
12726
+ /** The target node's modelsDir the artifact landed in. */
12727
+ path: string()
12728
+ }), {
12729
+ kind: "mutation",
12730
+ auth: "admin"
12731
+ });
12732
+ method(object({
12733
+ sourceUrl: string(),
12734
+ metadata: ModelConvertMetadataSchema,
12735
+ targets: array(ConvertTargetSchema).min(1).readonly(),
12736
+ calibrationRef: string().optional(),
12737
+ sessionId: string().optional()
12738
+ }), ConvertResultSchema, {
12739
+ kind: "mutation",
12740
+ auth: "admin"
12741
+ });
12567
12742
  var AddonHttpRouteSchema = object({
12568
12743
  method: _enum([
12569
12744
  "GET",
@@ -17458,6 +17633,12 @@ Object.freeze({
17458
17633
  addonId: null,
17459
17634
  access: "create"
17460
17635
  },
17636
+ "customModelRegistry.listModels": {
17637
+ capName: "custom-model-registry",
17638
+ capScope: "system",
17639
+ addonId: null,
17640
+ access: "view"
17641
+ },
17461
17642
  "decoder.createSession": {
17462
17643
  capName: "decoder",
17463
17644
  capScope: "system",
@@ -18682,6 +18863,18 @@ Object.freeze({
18682
18863
  addonId: null,
18683
18864
  access: "view"
18684
18865
  },
18866
+ "modelConvert.convert": {
18867
+ capName: "model-convert",
18868
+ capScope: "system",
18869
+ addonId: null,
18870
+ access: "create"
18871
+ },
18872
+ "modelDistributor.distributeModel": {
18873
+ capName: "model-distributor",
18874
+ capScope: "system",
18875
+ addonId: null,
18876
+ access: "create"
18877
+ },
18685
18878
  "motion.isDetected": {
18686
18879
  capName: "motion",
18687
18880
  capScope: "device",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@camstack/addon-export-hap",
3
- "version": "1.1.0",
3
+ "version": "1.1.2",
4
4
  "description": "HomeKit (HAP) bridge exporter for CamStack devices. Publishes a bridged accessory per exposed device — MotionSensor in this MVP; Camera/Doorbell/Switch/Light follow.",
5
5
  "keywords": [
6
6
  "camstack",