@camstack/addon-provider-dreo 0.2.0 → 0.2.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.
package/dist/addon.js CHANGED
@@ -12343,7 +12343,8 @@ var PipelineStepInputSchema = lazy(() => object({
12343
12343
  modelId: string().optional(),
12344
12344
  enabled: boolean().default(true),
12345
12345
  children: array(PipelineStepInputSchema).optional(),
12346
- settings: record(string(), unknown()).optional()
12346
+ settings: record(string(), unknown()).optional(),
12347
+ jumpDeviceKey: string().optional()
12347
12348
  }));
12348
12349
  var ModelSubstitutionSchema = object({
12349
12350
  addonId: string(),
@@ -12682,10 +12683,40 @@ var NativeCropBboxSchema = object({
12682
12683
  });
12683
12684
  /** Result of a best-effort native-resolution crop (`getNativeCrop`). */
12684
12685
  var NativeCropResultSchema = object({
12685
- /** Packed rgb (24-bit) pixels of the crop. */
12686
- bytes: _instanceof(Uint8Array),
12686
+ /**
12687
+ * Packed rgb (24-bit) pixels of the crop. Present on the DEFAULT (raw) path —
12688
+ * same-node (in-process / UDS) callers get zero-copy RGB and encode locally.
12689
+ * OMITTED when the caller requested `encodeJpeg` (the cross-node compressed
12690
+ * path below), where shipping raw RGB is both an invariant violation and, for
12691
+ * a native full frame (~26 MB at 4K), larger than Moleculer's 10 MB
12692
+ * `maxPacketSize` → the packet is dropped and the call 60s-times-out. That is
12693
+ * the cross-node native-media miss: `bytes` is replaced by `jpeg`.
12694
+ */
12695
+ bytes: _instanceof(Uint8Array).optional(),
12696
+ /**
12697
+ * Base64 JPEG of the crop — the COMPRESSED cross-node payload. The OWNING node
12698
+ * (which holds the native surface) encodes it in-process, so a native 4K frame
12699
+ * ships as ~0.5–2 MB (well under `maxPacketSize`) and NO raw pixels ever cross
12700
+ * a process boundary (CLAUDE.md invariant #21). Present ONLY when the request
12701
+ * set `encodeJpeg: true`; `bytes` is then absent.
12702
+ */
12703
+ jpeg: string().optional(),
12687
12704
  width: number().int().positive(),
12688
- height: number().int().positive()
12705
+ height: number().int().positive(),
12706
+ /**
12707
+ * Which source served this crop, so a quality-sensitive consumer (the native
12708
+ * `keyFrame`) can reject a degraded fallback:
12709
+ * - `native` — cut from the decode worker's retained NATIVE surface (the
12710
+ * quality path).
12711
+ * - `ram-fullframe` — the native surface MISSED but the request was full-frame,
12712
+ * so the ≤640 RAM `RetainedFrameStore` served it (honest lower-res; legit for
12713
+ * the blank-frame guard / 640-snapshot resolve, NOT for the clean keyFrame).
12714
+ *
12715
+ * OPTIONAL: a pre-tier runner (version skew) omits it — an ABSENT `tier` MUST be
12716
+ * treated as `native` (accepted) by every consumer so mixed-version clusters
12717
+ * keep the pre-tier behaviour. An ROI miss returns `null` (no tier at all).
12718
+ */
12719
+ tier: _enum(["native", "ram-fullframe"]).optional()
12689
12720
  });
12690
12721
  /** Parent detection context passed to `runDetailSubtree` — the crop's
12691
12722
  * originating detection, in FRAME-space coordinates. Reuses
@@ -12815,6 +12846,20 @@ var RunnerFrameSourceSchema = discriminatedUnion("kind", [object({ kind: literal
12815
12846
  hubHostnameOverride: string().optional()
12816
12847
  })]).describe("Per-camera frame-source mode for the runner (P2c)");
12817
12848
  /**
12849
+ * One ENABLED inference device on the runner's node, as the step-tree
12850
+ * device-jump resolver sees it (phase 1). The orchestrator populates this
12851
+ * roster on the attach payload whenever the camera is elected onto a specific
12852
+ * `deviceKey` and the node has ≥2 enabled devices — it is the candidate set the
12853
+ * runner auto-jumps an enrichment step to when the elected device's format
12854
+ * cannot run that step's model. `weight`/`maxSessions` mirror the balancer's
12855
+ * per-device knobs so the auto choice is weighted-least-loaded.
12856
+ */
12857
+ var RunnerInferenceDeviceSchema = object({
12858
+ deviceKey: string(),
12859
+ weight: number().positive().default(1),
12860
+ maxSessions: number().int().positive().nullable().default(null)
12861
+ });
12862
+ /**
12818
12863
  * Camera assignment payload sent by `addon-pipeline-orchestrator` to a
12819
12864
  * specific runner instance via `attachCamera`. Carries everything the
12820
12865
  * runner needs to subscribe to the local broker and execute inference.
@@ -12932,7 +12977,16 @@ var RunnerCameraConfigSchema = object({
12932
12977
  * omitted ⇒ the runner's default device. The engine itself stays node-local —
12933
12978
  * this only selects WHICH device pool of that node runs the session.
12934
12979
  */
12935
- deviceKey: string().optional()
12980
+ deviceKey: string().optional(),
12981
+ /**
12982
+ * Step-tree device-jump roster (phase 1): the node's ENABLED inference
12983
+ * devices, populated by the orchestrator ONLY when `deviceKey` is set and the
12984
+ * node has ≥2 enabled devices. The runner uses it to AUTO-jump an enrichment
12985
+ * step whose model has no build for the elected device's format onto another
12986
+ * enabled device of the SAME node (weighted-least-loaded). Absent/single-entry
12987
+ * ⇒ no jump possible; the step runs on `deviceKey`.
12988
+ */
12989
+ inferenceDevices: array(RunnerInferenceDeviceSchema).readonly().optional()
12936
12990
  });
12937
12991
  motionFpsField.min, motionFpsField.max, motionFpsField.step, motionFpsField.default, detectionFpsField.min, detectionFpsField.max, detectionFpsField.step, detectionFpsField.default, motionCooldownMsField.min, motionCooldownMsField.max, motionCooldownMsField.step, motionCooldownMsField.default, occupancyRecheckSecField.min, occupancyRecheckSecField.max, occupancyRecheckSecField.step, occupancyRecheckSecField.default, occupancyRecheckFramesField.min, occupancyRecheckFramesField.max, occupancyRecheckFramesField.step, occupancyRecheckFramesField.default;
12938
12992
  /**
@@ -12988,7 +13042,18 @@ var RunnerLocalMetricsSchema = object({
12988
13042
  method(RunnerCameraConfigSchema, object({ success: literal(true) }), { kind: "mutation" }), method(object({ deviceId: number() }), object({ success: literal(true) }), { kind: "mutation" }), method(ReportMotionInputSchema, object({ success: literal(true) }), { kind: "mutation" }), method(_void(), RunnerLocalLoadSchema), method(_void(), RunnerLocalMetricsSchema), method(object({ deviceId: number() }), CameraMetricsSchema.nullable()), method(_void(), array(CameraMetricsWithDeviceIdSchema).readonly()), method(_void(), array(number()).readonly()), method(object({
12989
13043
  handle: FrameHandleSchema,
12990
13044
  bbox: NativeCropBboxSchema,
12991
- maxWidth: number().int().positive().optional()
13045
+ maxWidth: number().int().positive().optional(),
13046
+ /**
13047
+ * When `true`, the runner encodes the resolved crop to JPEG ON THE
13048
+ * OWNING NODE and returns it in `jpeg` (base64) INSTEAD of raw `bytes`.
13049
+ * Callers set this for CROSS-NODE fetches (`handle.nodeId` is a remote
13050
+ * agent) so the compressed payload fits Moleculer's `maxPacketSize` and
13051
+ * no raw pixels cross the process boundary. Same-node callers omit it
13052
+ * and keep the zero-copy raw `bytes` path. Additive + optional: a
13053
+ * pre-encode runner (version skew) ignores it and returns `bytes`, so
13054
+ * the caller falls back to encoding locally.
13055
+ */
13056
+ encodeJpeg: boolean().optional()
12992
13057
  }), NativeCropResultSchema.nullable()), method(object({
12993
13058
  deviceId: number(),
12994
13059
  frameHandle: FrameHandleSchema.optional(),
@@ -17706,7 +17771,8 @@ var LinkedDeviceSchema = object({
17706
17771
  deviceId: number(),
17707
17772
  name: string(),
17708
17773
  location: string().nullable(),
17709
- features: array(string())
17774
+ features: array(string()),
17775
+ producesTrackedEvents: boolean().optional()
17710
17776
  });
17711
17777
  var SavedDeviceRowSchema = object({
17712
17778
  /** Numeric id reserved at allocateDeviceId time. */
@@ -19336,6 +19402,7 @@ var TrackSchema = object({
19336
19402
  deviceId: number(),
19337
19403
  className: string(),
19338
19404
  label: string().optional(),
19405
+ producingDeviceName: string().optional(),
19339
19406
  /** Track provenance. Absent ⇒ `pipeline` (legacy rows). */
19340
19407
  source: TrackSourceSchema.optional(),
19341
19408
  firstSeen: number(),
@@ -19473,7 +19540,8 @@ var MediaFileKindEnum = _enum([
19473
19540
  "fullFrameBoxed",
19474
19541
  "faceCrop",
19475
19542
  "plateCrop",
19476
- "keyFrame"
19543
+ "keyFrame",
19544
+ "keyFrameSmall"
19477
19545
  ]);
19478
19546
  var MediaFileSchema = object({
19479
19547
  key: string(),
@@ -19804,7 +19872,16 @@ var PipelineTemplateSchema = object({
19804
19872
  });
19805
19873
  var DeviceStepConfigSchema = object({
19806
19874
  modelId: string().optional(),
19807
- settings: record(string(), unknown()).optional()
19875
+ settings: record(string(), unknown()).optional(),
19876
+ /**
19877
+ * Step-tree device jump (same-node, phase 1) — OPTIONAL manual override.
19878
+ * When set, this step runs on the named enabled device of the SAME node
19879
+ * (`<backend>:<device>`) instead of the camera's elected device, bypassing
19880
+ * the runtime AUTO-jump. The orchestrator rejects a `jumpDeviceKey` pointing
19881
+ * at a disabled/absent device on that node at save time. Absent ⇒ the runner
19882
+ * auto-jumps only when the effective device's format cannot run the step.
19883
+ */
19884
+ jumpDeviceKey: string().optional()
19808
19885
  });
19809
19886
  var AgentPipelineSettingsSchema = object({
19810
19887
  maxCameras: number().int().nonnegative().nullable().default(null),
package/dist/addon.mjs CHANGED
@@ -12344,7 +12344,8 @@ var PipelineStepInputSchema = lazy(() => object({
12344
12344
  modelId: string().optional(),
12345
12345
  enabled: boolean().default(true),
12346
12346
  children: array(PipelineStepInputSchema).optional(),
12347
- settings: record(string(), unknown()).optional()
12347
+ settings: record(string(), unknown()).optional(),
12348
+ jumpDeviceKey: string().optional()
12348
12349
  }));
12349
12350
  var ModelSubstitutionSchema = object({
12350
12351
  addonId: string(),
@@ -12683,10 +12684,40 @@ var NativeCropBboxSchema = object({
12683
12684
  });
12684
12685
  /** Result of a best-effort native-resolution crop (`getNativeCrop`). */
12685
12686
  var NativeCropResultSchema = object({
12686
- /** Packed rgb (24-bit) pixels of the crop. */
12687
- bytes: _instanceof(Uint8Array),
12687
+ /**
12688
+ * Packed rgb (24-bit) pixels of the crop. Present on the DEFAULT (raw) path —
12689
+ * same-node (in-process / UDS) callers get zero-copy RGB and encode locally.
12690
+ * OMITTED when the caller requested `encodeJpeg` (the cross-node compressed
12691
+ * path below), where shipping raw RGB is both an invariant violation and, for
12692
+ * a native full frame (~26 MB at 4K), larger than Moleculer's 10 MB
12693
+ * `maxPacketSize` → the packet is dropped and the call 60s-times-out. That is
12694
+ * the cross-node native-media miss: `bytes` is replaced by `jpeg`.
12695
+ */
12696
+ bytes: _instanceof(Uint8Array).optional(),
12697
+ /**
12698
+ * Base64 JPEG of the crop — the COMPRESSED cross-node payload. The OWNING node
12699
+ * (which holds the native surface) encodes it in-process, so a native 4K frame
12700
+ * ships as ~0.5–2 MB (well under `maxPacketSize`) and NO raw pixels ever cross
12701
+ * a process boundary (CLAUDE.md invariant #21). Present ONLY when the request
12702
+ * set `encodeJpeg: true`; `bytes` is then absent.
12703
+ */
12704
+ jpeg: string().optional(),
12688
12705
  width: number().int().positive(),
12689
- height: number().int().positive()
12706
+ height: number().int().positive(),
12707
+ /**
12708
+ * Which source served this crop, so a quality-sensitive consumer (the native
12709
+ * `keyFrame`) can reject a degraded fallback:
12710
+ * - `native` — cut from the decode worker's retained NATIVE surface (the
12711
+ * quality path).
12712
+ * - `ram-fullframe` — the native surface MISSED but the request was full-frame,
12713
+ * so the ≤640 RAM `RetainedFrameStore` served it (honest lower-res; legit for
12714
+ * the blank-frame guard / 640-snapshot resolve, NOT for the clean keyFrame).
12715
+ *
12716
+ * OPTIONAL: a pre-tier runner (version skew) omits it — an ABSENT `tier` MUST be
12717
+ * treated as `native` (accepted) by every consumer so mixed-version clusters
12718
+ * keep the pre-tier behaviour. An ROI miss returns `null` (no tier at all).
12719
+ */
12720
+ tier: _enum(["native", "ram-fullframe"]).optional()
12690
12721
  });
12691
12722
  /** Parent detection context passed to `runDetailSubtree` — the crop's
12692
12723
  * originating detection, in FRAME-space coordinates. Reuses
@@ -12816,6 +12847,20 @@ var RunnerFrameSourceSchema = discriminatedUnion("kind", [object({ kind: literal
12816
12847
  hubHostnameOverride: string().optional()
12817
12848
  })]).describe("Per-camera frame-source mode for the runner (P2c)");
12818
12849
  /**
12850
+ * One ENABLED inference device on the runner's node, as the step-tree
12851
+ * device-jump resolver sees it (phase 1). The orchestrator populates this
12852
+ * roster on the attach payload whenever the camera is elected onto a specific
12853
+ * `deviceKey` and the node has ≥2 enabled devices — it is the candidate set the
12854
+ * runner auto-jumps an enrichment step to when the elected device's format
12855
+ * cannot run that step's model. `weight`/`maxSessions` mirror the balancer's
12856
+ * per-device knobs so the auto choice is weighted-least-loaded.
12857
+ */
12858
+ var RunnerInferenceDeviceSchema = object({
12859
+ deviceKey: string(),
12860
+ weight: number().positive().default(1),
12861
+ maxSessions: number().int().positive().nullable().default(null)
12862
+ });
12863
+ /**
12819
12864
  * Camera assignment payload sent by `addon-pipeline-orchestrator` to a
12820
12865
  * specific runner instance via `attachCamera`. Carries everything the
12821
12866
  * runner needs to subscribe to the local broker and execute inference.
@@ -12933,7 +12978,16 @@ var RunnerCameraConfigSchema = object({
12933
12978
  * omitted ⇒ the runner's default device. The engine itself stays node-local —
12934
12979
  * this only selects WHICH device pool of that node runs the session.
12935
12980
  */
12936
- deviceKey: string().optional()
12981
+ deviceKey: string().optional(),
12982
+ /**
12983
+ * Step-tree device-jump roster (phase 1): the node's ENABLED inference
12984
+ * devices, populated by the orchestrator ONLY when `deviceKey` is set and the
12985
+ * node has ≥2 enabled devices. The runner uses it to AUTO-jump an enrichment
12986
+ * step whose model has no build for the elected device's format onto another
12987
+ * enabled device of the SAME node (weighted-least-loaded). Absent/single-entry
12988
+ * ⇒ no jump possible; the step runs on `deviceKey`.
12989
+ */
12990
+ inferenceDevices: array(RunnerInferenceDeviceSchema).readonly().optional()
12937
12991
  });
12938
12992
  motionFpsField.min, motionFpsField.max, motionFpsField.step, motionFpsField.default, detectionFpsField.min, detectionFpsField.max, detectionFpsField.step, detectionFpsField.default, motionCooldownMsField.min, motionCooldownMsField.max, motionCooldownMsField.step, motionCooldownMsField.default, occupancyRecheckSecField.min, occupancyRecheckSecField.max, occupancyRecheckSecField.step, occupancyRecheckSecField.default, occupancyRecheckFramesField.min, occupancyRecheckFramesField.max, occupancyRecheckFramesField.step, occupancyRecheckFramesField.default;
12939
12993
  /**
@@ -12989,7 +13043,18 @@ var RunnerLocalMetricsSchema = object({
12989
13043
  method(RunnerCameraConfigSchema, object({ success: literal(true) }), { kind: "mutation" }), method(object({ deviceId: number() }), object({ success: literal(true) }), { kind: "mutation" }), method(ReportMotionInputSchema, object({ success: literal(true) }), { kind: "mutation" }), method(_void(), RunnerLocalLoadSchema), method(_void(), RunnerLocalMetricsSchema), method(object({ deviceId: number() }), CameraMetricsSchema.nullable()), method(_void(), array(CameraMetricsWithDeviceIdSchema).readonly()), method(_void(), array(number()).readonly()), method(object({
12990
13044
  handle: FrameHandleSchema,
12991
13045
  bbox: NativeCropBboxSchema,
12992
- maxWidth: number().int().positive().optional()
13046
+ maxWidth: number().int().positive().optional(),
13047
+ /**
13048
+ * When `true`, the runner encodes the resolved crop to JPEG ON THE
13049
+ * OWNING NODE and returns it in `jpeg` (base64) INSTEAD of raw `bytes`.
13050
+ * Callers set this for CROSS-NODE fetches (`handle.nodeId` is a remote
13051
+ * agent) so the compressed payload fits Moleculer's `maxPacketSize` and
13052
+ * no raw pixels cross the process boundary. Same-node callers omit it
13053
+ * and keep the zero-copy raw `bytes` path. Additive + optional: a
13054
+ * pre-encode runner (version skew) ignores it and returns `bytes`, so
13055
+ * the caller falls back to encoding locally.
13056
+ */
13057
+ encodeJpeg: boolean().optional()
12993
13058
  }), NativeCropResultSchema.nullable()), method(object({
12994
13059
  deviceId: number(),
12995
13060
  frameHandle: FrameHandleSchema.optional(),
@@ -17707,7 +17772,8 @@ var LinkedDeviceSchema = object({
17707
17772
  deviceId: number(),
17708
17773
  name: string(),
17709
17774
  location: string().nullable(),
17710
- features: array(string())
17775
+ features: array(string()),
17776
+ producesTrackedEvents: boolean().optional()
17711
17777
  });
17712
17778
  var SavedDeviceRowSchema = object({
17713
17779
  /** Numeric id reserved at allocateDeviceId time. */
@@ -19337,6 +19403,7 @@ var TrackSchema = object({
19337
19403
  deviceId: number(),
19338
19404
  className: string(),
19339
19405
  label: string().optional(),
19406
+ producingDeviceName: string().optional(),
19340
19407
  /** Track provenance. Absent ⇒ `pipeline` (legacy rows). */
19341
19408
  source: TrackSourceSchema.optional(),
19342
19409
  firstSeen: number(),
@@ -19474,7 +19541,8 @@ var MediaFileKindEnum = _enum([
19474
19541
  "fullFrameBoxed",
19475
19542
  "faceCrop",
19476
19543
  "plateCrop",
19477
- "keyFrame"
19544
+ "keyFrame",
19545
+ "keyFrameSmall"
19478
19546
  ]);
19479
19547
  var MediaFileSchema = object({
19480
19548
  key: string(),
@@ -19805,7 +19873,16 @@ var PipelineTemplateSchema = object({
19805
19873
  });
19806
19874
  var DeviceStepConfigSchema = object({
19807
19875
  modelId: string().optional(),
19808
- settings: record(string(), unknown()).optional()
19876
+ settings: record(string(), unknown()).optional(),
19877
+ /**
19878
+ * Step-tree device jump (same-node, phase 1) — OPTIONAL manual override.
19879
+ * When set, this step runs on the named enabled device of the SAME node
19880
+ * (`<backend>:<device>`) instead of the camera's elected device, bypassing
19881
+ * the runtime AUTO-jump. The orchestrator rejects a `jumpDeviceKey` pointing
19882
+ * at a disabled/absent device on that node at save time. Absent ⇒ the runner
19883
+ * auto-jumps only when the effective device's format cannot run the step.
19884
+ */
19885
+ jumpDeviceKey: string().optional()
19809
19886
  });
19810
19887
  var AgentPipelineSettingsSchema = object({
19811
19888
  maxCameras: number().int().nonnegative().nullable().default(null),
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@camstack/addon-provider-dreo",
3
- "version": "0.2.0",
3
+ "version": "0.2.2",
4
4
  "description": "Dreo smart-device (fan / air-circulator / purifier / heater / humidifier) device-provider addon for CamStack — wraps the @apocaliss92/nodedreo Dreo cloud client (REST + WebSocket)",
5
5
  "keywords": [
6
6
  "camstack",