@camstack/addon-export-alexa 1.2.1 → 1.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.
@@ -11235,7 +11235,8 @@ var PipelineStepInputSchema = lazy(() => object({
11235
11235
  modelId: string().optional(),
11236
11236
  enabled: boolean().default(true),
11237
11237
  children: array(PipelineStepInputSchema).optional(),
11238
- settings: record(string(), unknown()).optional()
11238
+ settings: record(string(), unknown()).optional(),
11239
+ jumpDeviceKey: string().optional()
11239
11240
  }));
11240
11241
  var ModelSubstitutionSchema = object({
11241
11242
  addonId: string(),
@@ -11541,8 +11542,24 @@ var NativeCropBboxSchema = object({
11541
11542
  });
11542
11543
  /** Result of a best-effort native-resolution crop (`getNativeCrop`). */
11543
11544
  var NativeCropResultSchema = object({
11544
- /** Packed rgb (24-bit) pixels of the crop. */
11545
- bytes: _instanceof(Uint8Array),
11545
+ /**
11546
+ * Packed rgb (24-bit) pixels of the crop. Present on the DEFAULT (raw) path —
11547
+ * same-node (in-process / UDS) callers get zero-copy RGB and encode locally.
11548
+ * OMITTED when the caller requested `encodeJpeg` (the cross-node compressed
11549
+ * path below), where shipping raw RGB is both an invariant violation and, for
11550
+ * a native full frame (~26 MB at 4K), larger than Moleculer's 10 MB
11551
+ * `maxPacketSize` → the packet is dropped and the call 60s-times-out. That is
11552
+ * the cross-node native-media miss: `bytes` is replaced by `jpeg`.
11553
+ */
11554
+ bytes: _instanceof(Uint8Array).optional(),
11555
+ /**
11556
+ * Base64 JPEG of the crop — the COMPRESSED cross-node payload. The OWNING node
11557
+ * (which holds the native surface) encodes it in-process, so a native 4K frame
11558
+ * ships as ~0.5–2 MB (well under `maxPacketSize`) and NO raw pixels ever cross
11559
+ * a process boundary (CLAUDE.md invariant #21). Present ONLY when the request
11560
+ * set `encodeJpeg: true`; `bytes` is then absent.
11561
+ */
11562
+ jpeg: string().optional(),
11546
11563
  width: number().int().positive(),
11547
11564
  height: number().int().positive(),
11548
11565
  /**
@@ -11688,6 +11705,20 @@ var RunnerFrameSourceSchema = discriminatedUnion("kind", [object({ kind: literal
11688
11705
  hubHostnameOverride: string().optional()
11689
11706
  })]).describe("Per-camera frame-source mode for the runner (P2c)");
11690
11707
  /**
11708
+ * One ENABLED inference device on the runner's node, as the step-tree
11709
+ * device-jump resolver sees it (phase 1). The orchestrator populates this
11710
+ * roster on the attach payload whenever the camera is elected onto a specific
11711
+ * `deviceKey` and the node has ≥2 enabled devices — it is the candidate set the
11712
+ * runner auto-jumps an enrichment step to when the elected device's format
11713
+ * cannot run that step's model. `weight`/`maxSessions` mirror the balancer's
11714
+ * per-device knobs so the auto choice is weighted-least-loaded.
11715
+ */
11716
+ var RunnerInferenceDeviceSchema = object({
11717
+ deviceKey: string(),
11718
+ weight: number().positive().default(1),
11719
+ maxSessions: number().int().positive().nullable().default(null)
11720
+ });
11721
+ /**
11691
11722
  * Camera assignment payload sent by `addon-pipeline-orchestrator` to a
11692
11723
  * specific runner instance via `attachCamera`. Carries everything the
11693
11724
  * runner needs to subscribe to the local broker and execute inference.
@@ -11805,7 +11836,16 @@ var RunnerCameraConfigSchema = object({
11805
11836
  * omitted ⇒ the runner's default device. The engine itself stays node-local —
11806
11837
  * this only selects WHICH device pool of that node runs the session.
11807
11838
  */
11808
- deviceKey: string().optional()
11839
+ deviceKey: string().optional(),
11840
+ /**
11841
+ * Step-tree device-jump roster (phase 1): the node's ENABLED inference
11842
+ * devices, populated by the orchestrator ONLY when `deviceKey` is set and the
11843
+ * node has ≥2 enabled devices. The runner uses it to AUTO-jump an enrichment
11844
+ * step whose model has no build for the elected device's format onto another
11845
+ * enabled device of the SAME node (weighted-least-loaded). Absent/single-entry
11846
+ * ⇒ no jump possible; the step runs on `deviceKey`.
11847
+ */
11848
+ inferenceDevices: array(RunnerInferenceDeviceSchema).readonly().optional()
11809
11849
  });
11810
11850
  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;
11811
11851
  /**
@@ -11861,7 +11901,18 @@ var RunnerLocalMetricsSchema = object({
11861
11901
  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({
11862
11902
  handle: FrameHandleSchema,
11863
11903
  bbox: NativeCropBboxSchema,
11864
- maxWidth: number().int().positive().optional()
11904
+ maxWidth: number().int().positive().optional(),
11905
+ /**
11906
+ * When `true`, the runner encodes the resolved crop to JPEG ON THE
11907
+ * OWNING NODE and returns it in `jpeg` (base64) INSTEAD of raw `bytes`.
11908
+ * Callers set this for CROSS-NODE fetches (`handle.nodeId` is a remote
11909
+ * agent) so the compressed payload fits Moleculer's `maxPacketSize` and
11910
+ * no raw pixels cross the process boundary. Same-node callers omit it
11911
+ * and keep the zero-copy raw `bytes` path. Additive + optional: a
11912
+ * pre-encode runner (version skew) ignores it and returns `bytes`, so
11913
+ * the caller falls back to encoding locally.
11914
+ */
11915
+ encodeJpeg: boolean().optional()
11865
11916
  }), NativeCropResultSchema.nullable()), method(object({
11866
11917
  deviceId: number(),
11867
11918
  frameHandle: FrameHandleSchema.optional(),
@@ -17061,7 +17112,16 @@ var PipelineTemplateSchema = object({
17061
17112
  });
17062
17113
  var DeviceStepConfigSchema = object({
17063
17114
  modelId: string().optional(),
17064
- settings: record(string(), unknown()).optional()
17115
+ settings: record(string(), unknown()).optional(),
17116
+ /**
17117
+ * Step-tree device jump (same-node, phase 1) — OPTIONAL manual override.
17118
+ * When set, this step runs on the named enabled device of the SAME node
17119
+ * (`<backend>:<device>`) instead of the camera's elected device, bypassing
17120
+ * the runtime AUTO-jump. The orchestrator rejects a `jumpDeviceKey` pointing
17121
+ * at a disabled/absent device on that node at save time. Absent ⇒ the runner
17122
+ * auto-jumps only when the effective device's format cannot run the step.
17123
+ */
17124
+ jumpDeviceKey: string().optional()
17065
17125
  });
17066
17126
  var AgentPipelineSettingsSchema = object({
17067
17127
  maxCameras: number().int().nonnegative().nullable().default(null),
@@ -11209,7 +11209,8 @@ var PipelineStepInputSchema = lazy(() => object({
11209
11209
  modelId: string().optional(),
11210
11210
  enabled: boolean().default(true),
11211
11211
  children: array(PipelineStepInputSchema).optional(),
11212
- settings: record(string(), unknown()).optional()
11212
+ settings: record(string(), unknown()).optional(),
11213
+ jumpDeviceKey: string().optional()
11213
11214
  }));
11214
11215
  var ModelSubstitutionSchema = object({
11215
11216
  addonId: string(),
@@ -11515,8 +11516,24 @@ var NativeCropBboxSchema = object({
11515
11516
  });
11516
11517
  /** Result of a best-effort native-resolution crop (`getNativeCrop`). */
11517
11518
  var NativeCropResultSchema = object({
11518
- /** Packed rgb (24-bit) pixels of the crop. */
11519
- bytes: _instanceof(Uint8Array),
11519
+ /**
11520
+ * Packed rgb (24-bit) pixels of the crop. Present on the DEFAULT (raw) path —
11521
+ * same-node (in-process / UDS) callers get zero-copy RGB and encode locally.
11522
+ * OMITTED when the caller requested `encodeJpeg` (the cross-node compressed
11523
+ * path below), where shipping raw RGB is both an invariant violation and, for
11524
+ * a native full frame (~26 MB at 4K), larger than Moleculer's 10 MB
11525
+ * `maxPacketSize` → the packet is dropped and the call 60s-times-out. That is
11526
+ * the cross-node native-media miss: `bytes` is replaced by `jpeg`.
11527
+ */
11528
+ bytes: _instanceof(Uint8Array).optional(),
11529
+ /**
11530
+ * Base64 JPEG of the crop — the COMPRESSED cross-node payload. The OWNING node
11531
+ * (which holds the native surface) encodes it in-process, so a native 4K frame
11532
+ * ships as ~0.5–2 MB (well under `maxPacketSize`) and NO raw pixels ever cross
11533
+ * a process boundary (CLAUDE.md invariant #21). Present ONLY when the request
11534
+ * set `encodeJpeg: true`; `bytes` is then absent.
11535
+ */
11536
+ jpeg: string().optional(),
11520
11537
  width: number().int().positive(),
11521
11538
  height: number().int().positive(),
11522
11539
  /**
@@ -11662,6 +11679,20 @@ var RunnerFrameSourceSchema = discriminatedUnion("kind", [object({ kind: literal
11662
11679
  hubHostnameOverride: string().optional()
11663
11680
  })]).describe("Per-camera frame-source mode for the runner (P2c)");
11664
11681
  /**
11682
+ * One ENABLED inference device on the runner's node, as the step-tree
11683
+ * device-jump resolver sees it (phase 1). The orchestrator populates this
11684
+ * roster on the attach payload whenever the camera is elected onto a specific
11685
+ * `deviceKey` and the node has ≥2 enabled devices — it is the candidate set the
11686
+ * runner auto-jumps an enrichment step to when the elected device's format
11687
+ * cannot run that step's model. `weight`/`maxSessions` mirror the balancer's
11688
+ * per-device knobs so the auto choice is weighted-least-loaded.
11689
+ */
11690
+ var RunnerInferenceDeviceSchema = object({
11691
+ deviceKey: string(),
11692
+ weight: number().positive().default(1),
11693
+ maxSessions: number().int().positive().nullable().default(null)
11694
+ });
11695
+ /**
11665
11696
  * Camera assignment payload sent by `addon-pipeline-orchestrator` to a
11666
11697
  * specific runner instance via `attachCamera`. Carries everything the
11667
11698
  * runner needs to subscribe to the local broker and execute inference.
@@ -11779,7 +11810,16 @@ var RunnerCameraConfigSchema = object({
11779
11810
  * omitted ⇒ the runner's default device. The engine itself stays node-local —
11780
11811
  * this only selects WHICH device pool of that node runs the session.
11781
11812
  */
11782
- deviceKey: string().optional()
11813
+ deviceKey: string().optional(),
11814
+ /**
11815
+ * Step-tree device-jump roster (phase 1): the node's ENABLED inference
11816
+ * devices, populated by the orchestrator ONLY when `deviceKey` is set and the
11817
+ * node has ≥2 enabled devices. The runner uses it to AUTO-jump an enrichment
11818
+ * step whose model has no build for the elected device's format onto another
11819
+ * enabled device of the SAME node (weighted-least-loaded). Absent/single-entry
11820
+ * ⇒ no jump possible; the step runs on `deviceKey`.
11821
+ */
11822
+ inferenceDevices: array(RunnerInferenceDeviceSchema).readonly().optional()
11783
11823
  });
11784
11824
  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;
11785
11825
  /**
@@ -11835,7 +11875,18 @@ var RunnerLocalMetricsSchema = object({
11835
11875
  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({
11836
11876
  handle: FrameHandleSchema,
11837
11877
  bbox: NativeCropBboxSchema,
11838
- maxWidth: number().int().positive().optional()
11878
+ maxWidth: number().int().positive().optional(),
11879
+ /**
11880
+ * When `true`, the runner encodes the resolved crop to JPEG ON THE
11881
+ * OWNING NODE and returns it in `jpeg` (base64) INSTEAD of raw `bytes`.
11882
+ * Callers set this for CROSS-NODE fetches (`handle.nodeId` is a remote
11883
+ * agent) so the compressed payload fits Moleculer's `maxPacketSize` and
11884
+ * no raw pixels cross the process boundary. Same-node callers omit it
11885
+ * and keep the zero-copy raw `bytes` path. Additive + optional: a
11886
+ * pre-encode runner (version skew) ignores it and returns `bytes`, so
11887
+ * the caller falls back to encoding locally.
11888
+ */
11889
+ encodeJpeg: boolean().optional()
11839
11890
  }), NativeCropResultSchema.nullable()), method(object({
11840
11891
  deviceId: number(),
11841
11892
  frameHandle: FrameHandleSchema.optional(),
@@ -17035,7 +17086,16 @@ var PipelineTemplateSchema = object({
17035
17086
  });
17036
17087
  var DeviceStepConfigSchema = object({
17037
17088
  modelId: string().optional(),
17038
- settings: record(string(), unknown()).optional()
17089
+ settings: record(string(), unknown()).optional(),
17090
+ /**
17091
+ * Step-tree device jump (same-node, phase 1) — OPTIONAL manual override.
17092
+ * When set, this step runs on the named enabled device of the SAME node
17093
+ * (`<backend>:<device>`) instead of the camera's elected device, bypassing
17094
+ * the runtime AUTO-jump. The orchestrator rejects a `jumpDeviceKey` pointing
17095
+ * at a disabled/absent device on that node at save time. Absent ⇒ the runner
17096
+ * auto-jumps only when the effective device's format cannot run the step.
17097
+ */
17098
+ jumpDeviceKey: string().optional()
17039
17099
  });
17040
17100
  var AgentPipelineSettingsSchema = object({
17041
17101
  maxCameras: number().int().nonnegative().nullable().default(null),
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@camstack/addon-export-alexa",
3
- "version": "1.2.1",
3
+ "version": "1.2.2",
4
4
  "description": "Alexa Smart Home Skill export — hub-side OAuth provider + directive handler. The companion AWS Lambda forwards Alexa directives to this addon's /addon/export-alexa/directive endpoint.",
5
5
  "keywords": [
6
6
  "camstack",