@camstack/addon-provider-rademacher 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
@@ -13306,7 +13306,8 @@ var PipelineStepInputSchema = lazy(() => object({
13306
13306
  modelId: string().optional(),
13307
13307
  enabled: boolean().default(true),
13308
13308
  children: array(PipelineStepInputSchema).optional(),
13309
- settings: record(string(), unknown()).optional()
13309
+ settings: record(string(), unknown()).optional(),
13310
+ jumpDeviceKey: string().optional()
13310
13311
  }));
13311
13312
  var ModelSubstitutionSchema = object({
13312
13313
  addonId: string(),
@@ -13645,10 +13646,40 @@ var NativeCropBboxSchema = object({
13645
13646
  });
13646
13647
  /** Result of a best-effort native-resolution crop (`getNativeCrop`). */
13647
13648
  var NativeCropResultSchema = object({
13648
- /** Packed rgb (24-bit) pixels of the crop. */
13649
- bytes: _instanceof(Uint8Array),
13649
+ /**
13650
+ * Packed rgb (24-bit) pixels of the crop. Present on the DEFAULT (raw) path —
13651
+ * same-node (in-process / UDS) callers get zero-copy RGB and encode locally.
13652
+ * OMITTED when the caller requested `encodeJpeg` (the cross-node compressed
13653
+ * path below), where shipping raw RGB is both an invariant violation and, for
13654
+ * a native full frame (~26 MB at 4K), larger than Moleculer's 10 MB
13655
+ * `maxPacketSize` → the packet is dropped and the call 60s-times-out. That is
13656
+ * the cross-node native-media miss: `bytes` is replaced by `jpeg`.
13657
+ */
13658
+ bytes: _instanceof(Uint8Array).optional(),
13659
+ /**
13660
+ * Base64 JPEG of the crop — the COMPRESSED cross-node payload. The OWNING node
13661
+ * (which holds the native surface) encodes it in-process, so a native 4K frame
13662
+ * ships as ~0.5–2 MB (well under `maxPacketSize`) and NO raw pixels ever cross
13663
+ * a process boundary (CLAUDE.md invariant #21). Present ONLY when the request
13664
+ * set `encodeJpeg: true`; `bytes` is then absent.
13665
+ */
13666
+ jpeg: string().optional(),
13650
13667
  width: number().int().positive(),
13651
- height: number().int().positive()
13668
+ height: number().int().positive(),
13669
+ /**
13670
+ * Which source served this crop, so a quality-sensitive consumer (the native
13671
+ * `keyFrame`) can reject a degraded fallback:
13672
+ * - `native` — cut from the decode worker's retained NATIVE surface (the
13673
+ * quality path).
13674
+ * - `ram-fullframe` — the native surface MISSED but the request was full-frame,
13675
+ * so the ≤640 RAM `RetainedFrameStore` served it (honest lower-res; legit for
13676
+ * the blank-frame guard / 640-snapshot resolve, NOT for the clean keyFrame).
13677
+ *
13678
+ * OPTIONAL: a pre-tier runner (version skew) omits it — an ABSENT `tier` MUST be
13679
+ * treated as `native` (accepted) by every consumer so mixed-version clusters
13680
+ * keep the pre-tier behaviour. An ROI miss returns `null` (no tier at all).
13681
+ */
13682
+ tier: _enum(["native", "ram-fullframe"]).optional()
13652
13683
  });
13653
13684
  /** Parent detection context passed to `runDetailSubtree` — the crop's
13654
13685
  * originating detection, in FRAME-space coordinates. Reuses
@@ -13778,6 +13809,20 @@ var RunnerFrameSourceSchema = discriminatedUnion("kind", [object({ kind: literal
13778
13809
  hubHostnameOverride: string().optional()
13779
13810
  })]).describe("Per-camera frame-source mode for the runner (P2c)");
13780
13811
  /**
13812
+ * One ENABLED inference device on the runner's node, as the step-tree
13813
+ * device-jump resolver sees it (phase 1). The orchestrator populates this
13814
+ * roster on the attach payload whenever the camera is elected onto a specific
13815
+ * `deviceKey` and the node has ≥2 enabled devices — it is the candidate set the
13816
+ * runner auto-jumps an enrichment step to when the elected device's format
13817
+ * cannot run that step's model. `weight`/`maxSessions` mirror the balancer's
13818
+ * per-device knobs so the auto choice is weighted-least-loaded.
13819
+ */
13820
+ var RunnerInferenceDeviceSchema = object({
13821
+ deviceKey: string(),
13822
+ weight: number().positive().default(1),
13823
+ maxSessions: number().int().positive().nullable().default(null)
13824
+ });
13825
+ /**
13781
13826
  * Camera assignment payload sent by `addon-pipeline-orchestrator` to a
13782
13827
  * specific runner instance via `attachCamera`. Carries everything the
13783
13828
  * runner needs to subscribe to the local broker and execute inference.
@@ -13895,7 +13940,16 @@ var RunnerCameraConfigSchema = object({
13895
13940
  * omitted ⇒ the runner's default device. The engine itself stays node-local —
13896
13941
  * this only selects WHICH device pool of that node runs the session.
13897
13942
  */
13898
- deviceKey: string().optional()
13943
+ deviceKey: string().optional(),
13944
+ /**
13945
+ * Step-tree device-jump roster (phase 1): the node's ENABLED inference
13946
+ * devices, populated by the orchestrator ONLY when `deviceKey` is set and the
13947
+ * node has ≥2 enabled devices. The runner uses it to AUTO-jump an enrichment
13948
+ * step whose model has no build for the elected device's format onto another
13949
+ * enabled device of the SAME node (weighted-least-loaded). Absent/single-entry
13950
+ * ⇒ no jump possible; the step runs on `deviceKey`.
13951
+ */
13952
+ inferenceDevices: array(RunnerInferenceDeviceSchema).readonly().optional()
13899
13953
  });
13900
13954
  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;
13901
13955
  /**
@@ -13951,7 +14005,18 @@ var RunnerLocalMetricsSchema = object({
13951
14005
  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({
13952
14006
  handle: FrameHandleSchema,
13953
14007
  bbox: NativeCropBboxSchema,
13954
- maxWidth: number().int().positive().optional()
14008
+ maxWidth: number().int().positive().optional(),
14009
+ /**
14010
+ * When `true`, the runner encodes the resolved crop to JPEG ON THE
14011
+ * OWNING NODE and returns it in `jpeg` (base64) INSTEAD of raw `bytes`.
14012
+ * Callers set this for CROSS-NODE fetches (`handle.nodeId` is a remote
14013
+ * agent) so the compressed payload fits Moleculer's `maxPacketSize` and
14014
+ * no raw pixels cross the process boundary. Same-node callers omit it
14015
+ * and keep the zero-copy raw `bytes` path. Additive + optional: a
14016
+ * pre-encode runner (version skew) ignores it and returns `bytes`, so
14017
+ * the caller falls back to encoding locally.
14018
+ */
14019
+ encodeJpeg: boolean().optional()
13955
14020
  }), NativeCropResultSchema.nullable()), method(object({
13956
14021
  deviceId: number(),
13957
14022
  frameHandle: FrameHandleSchema.optional(),
@@ -18652,7 +18717,8 @@ var LinkedDeviceSchema = object({
18652
18717
  deviceId: number(),
18653
18718
  name: string(),
18654
18719
  location: string().nullable(),
18655
- features: array(string())
18720
+ features: array(string()),
18721
+ producesTrackedEvents: boolean().optional()
18656
18722
  });
18657
18723
  var SavedDeviceRowSchema = object({
18658
18724
  /** Numeric id reserved at allocateDeviceId time. */
@@ -20282,6 +20348,7 @@ var TrackSchema = object({
20282
20348
  deviceId: number(),
20283
20349
  className: string(),
20284
20350
  label: string().optional(),
20351
+ producingDeviceName: string().optional(),
20285
20352
  /** Track provenance. Absent ⇒ `pipeline` (legacy rows). */
20286
20353
  source: TrackSourceSchema.optional(),
20287
20354
  firstSeen: number(),
@@ -20419,7 +20486,8 @@ var MediaFileKindEnum = _enum([
20419
20486
  "fullFrameBoxed",
20420
20487
  "faceCrop",
20421
20488
  "plateCrop",
20422
- "keyFrame"
20489
+ "keyFrame",
20490
+ "keyFrameSmall"
20423
20491
  ]);
20424
20492
  var MediaFileSchema = object({
20425
20493
  key: string(),
@@ -20750,7 +20818,16 @@ var PipelineTemplateSchema = object({
20750
20818
  });
20751
20819
  var DeviceStepConfigSchema = object({
20752
20820
  modelId: string().optional(),
20753
- settings: record(string(), unknown()).optional()
20821
+ settings: record(string(), unknown()).optional(),
20822
+ /**
20823
+ * Step-tree device jump (same-node, phase 1) — OPTIONAL manual override.
20824
+ * When set, this step runs on the named enabled device of the SAME node
20825
+ * (`<backend>:<device>`) instead of the camera's elected device, bypassing
20826
+ * the runtime AUTO-jump. The orchestrator rejects a `jumpDeviceKey` pointing
20827
+ * at a disabled/absent device on that node at save time. Absent ⇒ the runner
20828
+ * auto-jumps only when the effective device's format cannot run the step.
20829
+ */
20830
+ jumpDeviceKey: string().optional()
20754
20831
  });
20755
20832
  var AgentPipelineSettingsSchema = object({
20756
20833
  maxCameras: number().int().nonnegative().nullable().default(null),
package/dist/addon.mjs CHANGED
@@ -13305,7 +13305,8 @@ var PipelineStepInputSchema = lazy(() => object({
13305
13305
  modelId: string().optional(),
13306
13306
  enabled: boolean().default(true),
13307
13307
  children: array(PipelineStepInputSchema).optional(),
13308
- settings: record(string(), unknown()).optional()
13308
+ settings: record(string(), unknown()).optional(),
13309
+ jumpDeviceKey: string().optional()
13309
13310
  }));
13310
13311
  var ModelSubstitutionSchema = object({
13311
13312
  addonId: string(),
@@ -13644,10 +13645,40 @@ var NativeCropBboxSchema = object({
13644
13645
  });
13645
13646
  /** Result of a best-effort native-resolution crop (`getNativeCrop`). */
13646
13647
  var NativeCropResultSchema = object({
13647
- /** Packed rgb (24-bit) pixels of the crop. */
13648
- bytes: _instanceof(Uint8Array),
13648
+ /**
13649
+ * Packed rgb (24-bit) pixels of the crop. Present on the DEFAULT (raw) path —
13650
+ * same-node (in-process / UDS) callers get zero-copy RGB and encode locally.
13651
+ * OMITTED when the caller requested `encodeJpeg` (the cross-node compressed
13652
+ * path below), where shipping raw RGB is both an invariant violation and, for
13653
+ * a native full frame (~26 MB at 4K), larger than Moleculer's 10 MB
13654
+ * `maxPacketSize` → the packet is dropped and the call 60s-times-out. That is
13655
+ * the cross-node native-media miss: `bytes` is replaced by `jpeg`.
13656
+ */
13657
+ bytes: _instanceof(Uint8Array).optional(),
13658
+ /**
13659
+ * Base64 JPEG of the crop — the COMPRESSED cross-node payload. The OWNING node
13660
+ * (which holds the native surface) encodes it in-process, so a native 4K frame
13661
+ * ships as ~0.5–2 MB (well under `maxPacketSize`) and NO raw pixels ever cross
13662
+ * a process boundary (CLAUDE.md invariant #21). Present ONLY when the request
13663
+ * set `encodeJpeg: true`; `bytes` is then absent.
13664
+ */
13665
+ jpeg: string().optional(),
13649
13666
  width: number().int().positive(),
13650
- height: number().int().positive()
13667
+ height: number().int().positive(),
13668
+ /**
13669
+ * Which source served this crop, so a quality-sensitive consumer (the native
13670
+ * `keyFrame`) can reject a degraded fallback:
13671
+ * - `native` — cut from the decode worker's retained NATIVE surface (the
13672
+ * quality path).
13673
+ * - `ram-fullframe` — the native surface MISSED but the request was full-frame,
13674
+ * so the ≤640 RAM `RetainedFrameStore` served it (honest lower-res; legit for
13675
+ * the blank-frame guard / 640-snapshot resolve, NOT for the clean keyFrame).
13676
+ *
13677
+ * OPTIONAL: a pre-tier runner (version skew) omits it — an ABSENT `tier` MUST be
13678
+ * treated as `native` (accepted) by every consumer so mixed-version clusters
13679
+ * keep the pre-tier behaviour. An ROI miss returns `null` (no tier at all).
13680
+ */
13681
+ tier: _enum(["native", "ram-fullframe"]).optional()
13651
13682
  });
13652
13683
  /** Parent detection context passed to `runDetailSubtree` — the crop's
13653
13684
  * originating detection, in FRAME-space coordinates. Reuses
@@ -13777,6 +13808,20 @@ var RunnerFrameSourceSchema = discriminatedUnion("kind", [object({ kind: literal
13777
13808
  hubHostnameOverride: string().optional()
13778
13809
  })]).describe("Per-camera frame-source mode for the runner (P2c)");
13779
13810
  /**
13811
+ * One ENABLED inference device on the runner's node, as the step-tree
13812
+ * device-jump resolver sees it (phase 1). The orchestrator populates this
13813
+ * roster on the attach payload whenever the camera is elected onto a specific
13814
+ * `deviceKey` and the node has ≥2 enabled devices — it is the candidate set the
13815
+ * runner auto-jumps an enrichment step to when the elected device's format
13816
+ * cannot run that step's model. `weight`/`maxSessions` mirror the balancer's
13817
+ * per-device knobs so the auto choice is weighted-least-loaded.
13818
+ */
13819
+ var RunnerInferenceDeviceSchema = object({
13820
+ deviceKey: string(),
13821
+ weight: number().positive().default(1),
13822
+ maxSessions: number().int().positive().nullable().default(null)
13823
+ });
13824
+ /**
13780
13825
  * Camera assignment payload sent by `addon-pipeline-orchestrator` to a
13781
13826
  * specific runner instance via `attachCamera`. Carries everything the
13782
13827
  * runner needs to subscribe to the local broker and execute inference.
@@ -13894,7 +13939,16 @@ var RunnerCameraConfigSchema = object({
13894
13939
  * omitted ⇒ the runner's default device. The engine itself stays node-local —
13895
13940
  * this only selects WHICH device pool of that node runs the session.
13896
13941
  */
13897
- deviceKey: string().optional()
13942
+ deviceKey: string().optional(),
13943
+ /**
13944
+ * Step-tree device-jump roster (phase 1): the node's ENABLED inference
13945
+ * devices, populated by the orchestrator ONLY when `deviceKey` is set and the
13946
+ * node has ≥2 enabled devices. The runner uses it to AUTO-jump an enrichment
13947
+ * step whose model has no build for the elected device's format onto another
13948
+ * enabled device of the SAME node (weighted-least-loaded). Absent/single-entry
13949
+ * ⇒ no jump possible; the step runs on `deviceKey`.
13950
+ */
13951
+ inferenceDevices: array(RunnerInferenceDeviceSchema).readonly().optional()
13898
13952
  });
13899
13953
  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;
13900
13954
  /**
@@ -13950,7 +14004,18 @@ var RunnerLocalMetricsSchema = object({
13950
14004
  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({
13951
14005
  handle: FrameHandleSchema,
13952
14006
  bbox: NativeCropBboxSchema,
13953
- maxWidth: number().int().positive().optional()
14007
+ maxWidth: number().int().positive().optional(),
14008
+ /**
14009
+ * When `true`, the runner encodes the resolved crop to JPEG ON THE
14010
+ * OWNING NODE and returns it in `jpeg` (base64) INSTEAD of raw `bytes`.
14011
+ * Callers set this for CROSS-NODE fetches (`handle.nodeId` is a remote
14012
+ * agent) so the compressed payload fits Moleculer's `maxPacketSize` and
14013
+ * no raw pixels cross the process boundary. Same-node callers omit it
14014
+ * and keep the zero-copy raw `bytes` path. Additive + optional: a
14015
+ * pre-encode runner (version skew) ignores it and returns `bytes`, so
14016
+ * the caller falls back to encoding locally.
14017
+ */
14018
+ encodeJpeg: boolean().optional()
13954
14019
  }), NativeCropResultSchema.nullable()), method(object({
13955
14020
  deviceId: number(),
13956
14021
  frameHandle: FrameHandleSchema.optional(),
@@ -18651,7 +18716,8 @@ var LinkedDeviceSchema = object({
18651
18716
  deviceId: number(),
18652
18717
  name: string(),
18653
18718
  location: string().nullable(),
18654
- features: array(string())
18719
+ features: array(string()),
18720
+ producesTrackedEvents: boolean().optional()
18655
18721
  });
18656
18722
  var SavedDeviceRowSchema = object({
18657
18723
  /** Numeric id reserved at allocateDeviceId time. */
@@ -20281,6 +20347,7 @@ var TrackSchema = object({
20281
20347
  deviceId: number(),
20282
20348
  className: string(),
20283
20349
  label: string().optional(),
20350
+ producingDeviceName: string().optional(),
20284
20351
  /** Track provenance. Absent ⇒ `pipeline` (legacy rows). */
20285
20352
  source: TrackSourceSchema.optional(),
20286
20353
  firstSeen: number(),
@@ -20418,7 +20485,8 @@ var MediaFileKindEnum = _enum([
20418
20485
  "fullFrameBoxed",
20419
20486
  "faceCrop",
20420
20487
  "plateCrop",
20421
- "keyFrame"
20488
+ "keyFrame",
20489
+ "keyFrameSmall"
20422
20490
  ]);
20423
20491
  var MediaFileSchema = object({
20424
20492
  key: string(),
@@ -20749,7 +20817,16 @@ var PipelineTemplateSchema = object({
20749
20817
  });
20750
20818
  var DeviceStepConfigSchema = object({
20751
20819
  modelId: string().optional(),
20752
- settings: record(string(), unknown()).optional()
20820
+ settings: record(string(), unknown()).optional(),
20821
+ /**
20822
+ * Step-tree device jump (same-node, phase 1) — OPTIONAL manual override.
20823
+ * When set, this step runs on the named enabled device of the SAME node
20824
+ * (`<backend>:<device>`) instead of the camera's elected device, bypassing
20825
+ * the runtime AUTO-jump. The orchestrator rejects a `jumpDeviceKey` pointing
20826
+ * at a disabled/absent device on that node at save time. Absent ⇒ the runner
20827
+ * auto-jumps only when the effective device's format cannot run the step.
20828
+ */
20829
+ jumpDeviceKey: string().optional()
20753
20830
  });
20754
20831
  var AgentPipelineSettingsSchema = object({
20755
20832
  maxCameras: number().int().nonnegative().nullable().default(null),
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@camstack/addon-provider-rademacher",
3
- "version": "0.2.0",
3
+ "version": "0.2.2",
4
4
  "description": "Rademacher HomePilot device-provider addon for CamStack — wraps the @apocaliss92/noderademacher local-hub client (roller shutters over the cover cap)",
5
5
  "keywords": [
6
6
  "camstack",