camstack 1.2.0 → 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.
@@ -19628,7 +19628,8 @@ var PipelineStepInputSchema = external_exports.lazy(() => external_exports.objec
19628
19628
  modelId: external_exports.string().optional(),
19629
19629
  enabled: external_exports.boolean().default(true),
19630
19630
  children: external_exports.array(PipelineStepInputSchema).optional(),
19631
- settings: external_exports.record(external_exports.string(), external_exports.unknown()).optional()
19631
+ settings: external_exports.record(external_exports.string(), external_exports.unknown()).optional(),
19632
+ jumpDeviceKey: external_exports.string().optional()
19632
19633
  }));
19633
19634
  var ModelSubstitutionSchema = external_exports.object({
19634
19635
  addonId: external_exports.string(),
@@ -20050,10 +20051,40 @@ var NativeCropBboxSchema = external_exports.object({
20050
20051
  h: external_exports.number()
20051
20052
  });
20052
20053
  var NativeCropResultSchema = external_exports.object({
20053
- /** Packed rgb (24-bit) pixels of the crop. */
20054
- bytes: external_exports.instanceof(Uint8Array),
20054
+ /**
20055
+ * Packed rgb (24-bit) pixels of the crop. Present on the DEFAULT (raw) path —
20056
+ * same-node (in-process / UDS) callers get zero-copy RGB and encode locally.
20057
+ * OMITTED when the caller requested `encodeJpeg` (the cross-node compressed
20058
+ * path below), where shipping raw RGB is both an invariant violation and, for
20059
+ * a native full frame (~26 MB at 4K), larger than Moleculer's 10 MB
20060
+ * `maxPacketSize` → the packet is dropped and the call 60s-times-out. That is
20061
+ * the cross-node native-media miss: `bytes` is replaced by `jpeg`.
20062
+ */
20063
+ bytes: external_exports.instanceof(Uint8Array).optional(),
20064
+ /**
20065
+ * Base64 JPEG of the crop — the COMPRESSED cross-node payload. The OWNING node
20066
+ * (which holds the native surface) encodes it in-process, so a native 4K frame
20067
+ * ships as ~0.5–2 MB (well under `maxPacketSize`) and NO raw pixels ever cross
20068
+ * a process boundary (CLAUDE.md invariant #21). Present ONLY when the request
20069
+ * set `encodeJpeg: true`; `bytes` is then absent.
20070
+ */
20071
+ jpeg: external_exports.string().optional(),
20055
20072
  width: external_exports.number().int().positive(),
20056
- height: external_exports.number().int().positive()
20073
+ height: external_exports.number().int().positive(),
20074
+ /**
20075
+ * Which source served this crop, so a quality-sensitive consumer (the native
20076
+ * `keyFrame`) can reject a degraded fallback:
20077
+ * - `native` — cut from the decode worker's retained NATIVE surface (the
20078
+ * quality path).
20079
+ * - `ram-fullframe` — the native surface MISSED but the request was full-frame,
20080
+ * so the ≤640 RAM `RetainedFrameStore` served it (honest lower-res; legit for
20081
+ * the blank-frame guard / 640-snapshot resolve, NOT for the clean keyFrame).
20082
+ *
20083
+ * OPTIONAL: a pre-tier runner (version skew) omits it — an ABSENT `tier` MUST be
20084
+ * treated as `native` (accepted) by every consumer so mixed-version clusters
20085
+ * keep the pre-tier behaviour. An ROI miss returns `null` (no tier at all).
20086
+ */
20087
+ tier: external_exports.enum(["native", "ram-fullframe"]).optional()
20057
20088
  });
20058
20089
  var DetailParentSchema = external_exports.object({
20059
20090
  bbox: NativeCropBboxSchema,
@@ -20121,6 +20152,11 @@ var RunnerFrameSourceSchema = external_exports.discriminatedUnion("kind", [exter
20121
20152
  /** Operator override for the owner host the runner dials. */
20122
20153
  hubHostnameOverride: external_exports.string().optional()
20123
20154
  })]).describe("Per-camera frame-source mode for the runner (P2c)");
20155
+ var RunnerInferenceDeviceSchema = external_exports.object({
20156
+ deviceKey: external_exports.string(),
20157
+ weight: external_exports.number().positive().default(1),
20158
+ maxSessions: external_exports.number().int().positive().nullable().default(null)
20159
+ });
20124
20160
  var RunnerCameraConfigSchema = external_exports.object({
20125
20161
  deviceId: external_exports.number(),
20126
20162
  /**
@@ -20228,7 +20264,16 @@ var RunnerCameraConfigSchema = external_exports.object({
20228
20264
  * omitted ⇒ the runner's default device. The engine itself stays node-local —
20229
20265
  * this only selects WHICH device pool of that node runs the session.
20230
20266
  */
20231
- deviceKey: external_exports.string().optional()
20267
+ deviceKey: external_exports.string().optional(),
20268
+ /**
20269
+ * Step-tree device-jump roster (phase 1): the node's ENABLED inference
20270
+ * devices, populated by the orchestrator ONLY when `deviceKey` is set and the
20271
+ * node has ≥2 enabled devices. The runner uses it to AUTO-jump an enrichment
20272
+ * step whose model has no build for the elected device's format onto another
20273
+ * enabled device of the SAME node (weighted-least-loaded). Absent/single-entry
20274
+ * ⇒ no jump possible; the step runs on `deviceKey`.
20275
+ */
20276
+ inferenceDevices: external_exports.array(RunnerInferenceDeviceSchema).readonly().optional()
20232
20277
  });
20233
20278
  var RunnerCameraDeviceUIFields = [
20234
20279
  {
@@ -20420,15 +20465,31 @@ var pipelineRunnerCapability = {
20420
20465
  * `FrameHandle` that rode an inference-result event and a normalized `bbox`,
20421
20466
  * the runner asks the decode worker still holding that frame's NATIVE
20422
20467
  * surface to GPU/CPU-crop ONLY the ROI at native res and download just the
20423
- * crop. Returns `null` on a miss (handle not registered, or the worker's
20424
- * tiny native-retention ring already evicted the frame) — the caller falls
20425
- * back to a detection-frame crop. Routed to the frame's owning node by
20426
- * `handle.nodeId`; NEVER ships a full native frame.
20468
+ * crop. Routed to the frame's owning node by `handle.nodeId`; NEVER ships a
20469
+ * full native frame.
20470
+ *
20471
+ * Miss behaviour differs by request shape (see `NativeCropResultSchema.tier`):
20472
+ * - an ROI (subject-crop) miss returns `null` — the caller reports the miss
20473
+ * and retries; it is NEVER handed a ≤640 crop masquerading as native.
20474
+ * - a FULL-FRAME miss falls back to the ≤640 RAM `RetainedFrameStore`, tagged
20475
+ * `tier: 'ram-fullframe'` (honest lower-res for the blank-frame guard /
20476
+ * 640-snapshot resolve). A native hit is tagged `tier: 'native'`.
20427
20477
  */
20428
20478
  getNativeCrop: method(external_exports.object({
20429
20479
  handle: FrameHandleSchema,
20430
20480
  bbox: NativeCropBboxSchema,
20431
- maxWidth: external_exports.number().int().positive().optional()
20481
+ maxWidth: external_exports.number().int().positive().optional(),
20482
+ /**
20483
+ * When `true`, the runner encodes the resolved crop to JPEG ON THE
20484
+ * OWNING NODE and returns it in `jpeg` (base64) INSTEAD of raw `bytes`.
20485
+ * Callers set this for CROSS-NODE fetches (`handle.nodeId` is a remote
20486
+ * agent) so the compressed payload fits Moleculer's `maxPacketSize` and
20487
+ * no raw pixels cross the process boundary. Same-node callers omit it
20488
+ * and keep the zero-copy raw `bytes` path. Additive + optional: a
20489
+ * pre-encode runner (version skew) ignores it and returns `bytes`, so
20490
+ * the caller falls back to encoding locally.
20491
+ */
20492
+ encodeJpeg: external_exports.boolean().optional()
20432
20493
  }), NativeCropResultSchema.nullable()),
20433
20494
  /**
20434
20495
  * Two-plane design: run the DETAIL subtree (crop children —
@@ -24146,7 +24207,8 @@ var LinkedDeviceSchema = external_exports.object({
24146
24207
  deviceId: external_exports.number(),
24147
24208
  name: external_exports.string(),
24148
24209
  location: external_exports.string().nullable(),
24149
- features: external_exports.array(external_exports.string())
24210
+ features: external_exports.array(external_exports.string()),
24211
+ producesTrackedEvents: external_exports.boolean().optional()
24150
24212
  });
24151
24213
  var SavedDeviceRowSchema = external_exports.object({
24152
24214
  /** Numeric id reserved at allocateDeviceId time. */
@@ -26063,6 +26125,7 @@ var TrackSchema = external_exports.object({
26063
26125
  deviceId: external_exports.number(),
26064
26126
  className: external_exports.string(),
26065
26127
  label: external_exports.string().optional(),
26128
+ producingDeviceName: external_exports.string().optional(),
26066
26129
  /** Track provenance. Absent ⇒ `pipeline` (legacy rows). */
26067
26130
  source: TrackSourceSchema.optional(),
26068
26131
  firstSeen: external_exports.number(),
@@ -26192,7 +26255,8 @@ var MediaFileKindEnum = external_exports.enum([
26192
26255
  "fullFrameBoxed",
26193
26256
  "faceCrop",
26194
26257
  "plateCrop",
26195
- "keyFrame"
26258
+ "keyFrame",
26259
+ "keyFrameSmall"
26196
26260
  ]);
26197
26261
  var MediaFileSchema = external_exports.object({
26198
26262
  key: external_exports.string(),
@@ -26653,7 +26717,16 @@ var PipelineTemplateSchema = external_exports.object({
26653
26717
  });
26654
26718
  var DeviceStepConfigSchema = external_exports.object({
26655
26719
  modelId: external_exports.string().optional(),
26656
- settings: external_exports.record(external_exports.string(), external_exports.unknown()).optional()
26720
+ settings: external_exports.record(external_exports.string(), external_exports.unknown()).optional(),
26721
+ /**
26722
+ * Step-tree device jump (same-node, phase 1) — OPTIONAL manual override.
26723
+ * When set, this step runs on the named enabled device of the SAME node
26724
+ * (`<backend>:<device>`) instead of the camera's elected device, bypassing
26725
+ * the runtime AUTO-jump. The orchestrator rejects a `jumpDeviceKey` pointing
26726
+ * at a disabled/absent device on that node at save time. Absent ⇒ the runner
26727
+ * auto-jumps only when the effective device's format cannot run the step.
26728
+ */
26729
+ jumpDeviceKey: external_exports.string().optional()
26657
26730
  });
26658
26731
  var AgentPipelineSettingsSchema = external_exports.object({
26659
26732
  maxCameras: external_exports.number().int().nonnegative().nullable().default(null),
package/dist/cli.js CHANGED
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
3
  runDiscover
4
- } from "./chunk-LQUCPQ55.js";
4
+ } from "./chunk-QCUR7GXB.js";
5
5
  import "./chunk-K3NQKI34.js";
6
6
 
7
7
  // src/cli.ts
@@ -1079,7 +1079,7 @@ function isUnknown(_value) {
1079
1079
  return true;
1080
1080
  }
1081
1081
  async function resolveServerInteractive(presetNamespace) {
1082
- const { discoverNodes, resolveHubFromDiscovered, filterHubNodes, DEFAULT_HUB_HTTPS_PORT } = await import("./discover-GAE4KR5T.js");
1082
+ const { discoverNodes, resolveHubFromDiscovered, filterHubNodes, DEFAULT_HUB_HTTPS_PORT } = await import("./discover-4OS76PKO.js");
1083
1083
  if (presetNamespace) {
1084
1084
  const spinner4 = clack.spinner();
1085
1085
  spinner4.start(`Discovering hub on LAN (namespace "${presetNamespace}")`);
@@ -5,7 +5,7 @@ import {
5
5
  filterHubNodes,
6
6
  resolveHubFromDiscovered,
7
7
  runDiscover
8
- } from "./chunk-LQUCPQ55.js";
8
+ } from "./chunk-QCUR7GXB.js";
9
9
  import "./chunk-K3NQKI34.js";
10
10
  export {
11
11
  DEFAULT_HUB_HTTPS_PORT,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "camstack",
3
- "version": "1.2.0",
3
+ "version": "1.2.2",
4
4
  "description": "CLI tool for managing and running CamStack server",
5
5
  "keywords": [
6
6
  "camstack",