camstack 1.2.150 → 1.2.152

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.
@@ -28984,6 +28984,7 @@ var MotionSourceEnum = external_exports.enum([
28984
28984
  "device-activity"
28985
28985
  ]);
28986
28986
  var MotionSourcesSchema = external_exports.array(MotionSourceEnum);
28987
+ var DetectionSourcesSchema = external_exports.array(DetectionSourceSchema);
28987
28988
  var ReportMotionInputSchema = external_exports.object({
28988
28989
  deviceId: external_exports.number(),
28989
28990
  detected: external_exports.boolean(),
@@ -29091,6 +29092,35 @@ var RunnerCameraConfigSchema = external_exports.object({
29091
29092
  * events; the orchestrator forwards to `reportMotion`.
29092
29093
  */
29093
29094
  motionSources: MotionSourcesSchema.default(["analyzer"]),
29095
+ /**
29096
+ * WHICH root detector runs for this camera. The detection counterpart of
29097
+ * {@link motionSources}, same shape and same discipline: a per-camera list
29098
+ * of sources the system understands, vendor-agnostic, owned here.
29099
+ *
29100
+ * - `pipeline` — this runner's own root step on decoded pixels (`steps`).
29101
+ * - `onboard` — the CAMERA's own detector, admitted only when it is named
29102
+ * here. Its boxes reach post-analysis on the same
29103
+ * `PipelineInferenceResult` payload as the pipeline's, so an onboard-born
29104
+ * track gets the same tracker, the same overlay and the same detail
29105
+ * subtree (face / plate / embedding).
29106
+ *
29107
+ * `['onboard']` alone is the REPLACEMENT: this runner's root step does not
29108
+ * run, and that is where a camera with a usable onboard detector buys back
29109
+ * its share of the accelerator. It saves the root inference, not the decode
29110
+ * — the detail subtree still needs pixels to cut crops from.
29111
+ *
29112
+ * A camera whose onboard detections carry no geometry cannot serve as a root
29113
+ * step at all (there is nothing to track), and the cap that knows this says
29114
+ * so on `native-object-detection.getOptions().geometry`. On Reolink that is
29115
+ * every battery camera: the boxes ride a sub-stream a battery camera never
29116
+ * attaches, so such a camera stays on `['pipeline']` and its onboard AI is
29117
+ * worth exactly what it already is — a wake signal with a class.
29118
+ *
29119
+ * Defaults to `['pipeline']`, which is byte-for-byte today's behaviour: a
29120
+ * vendor never turns a detector on for the operator, and neither does a
29121
+ * default.
29122
+ */
29123
+ detectionSources: DetectionSourcesSchema.default(["pipeline"]),
29094
29124
  pipelineEnabled: external_exports.boolean().default(true),
29095
29125
  /** Ordered tree of video steps. Absent → runner skips video detection. */
29096
29126
  steps: external_exports.array(PipelineStepInputSchema).readonly().optional(),
@@ -29213,6 +29243,19 @@ var RunnerCameraDeviceUIFields = [
29213
29243
  }
29214
29244
  ]
29215
29245
  },
29246
+ {
29247
+ key: "detectionSources",
29248
+ type: "multiselect",
29249
+ label: "Detection Sources",
29250
+ default: ["pipeline"],
29251
+ options: [{
29252
+ value: "pipeline",
29253
+ label: "This node (ML root step on decoded frames)"
29254
+ }, {
29255
+ value: "onboard",
29256
+ label: "Camera onboard AI (replaces the root step when picked alone)"
29257
+ }]
29258
+ },
29216
29259
  {
29217
29260
  key: "motionFps",
29218
29261
  type: "slider",
@@ -36570,17 +36613,19 @@ var NativeObjectDetectionStatusSchema = external_exports.object({
36570
36613
  /**
36571
36614
  * Whether forwarding of onboard AI detections is enabled for this device.
36572
36615
  *
36573
- * The COLD-START default is the provider's, and it is not one value for
36574
- * every camera: a mains camera carries the boxed side-channel and its
36575
- * detections are usable subjects, so it defaults ON; a battery camera never
36576
- * attaches that channel, so the same toggle would buy it nothing but a write
36577
- * — it defaults OFF and an operator who wants it turns it on knowing what it
36578
- * costs. {@link NativeObjectDetectionOptionsSchema.geometry} is how the UI
36579
- * says which of the two a camera is.
36616
+ * Cold-start OFF on every camera. A vendor does not decide which detector a
36617
+ * camera runs — that is the operator's choice, and it is made where every
36618
+ * other detection choice is made. `geometry` on
36619
+ * {@link NativeObjectDetectionOptionsSchema} is how the form says what the
36620
+ * choice would buy this particular camera.
36580
36621
  */
36581
36622
  enabled: external_exports.boolean()
36582
36623
  });
36583
- var NativeObjectGeometryEnum = external_exports.enum(["boxed", "flag-only"]);
36624
+ var NativeObjectGeometryEnum = external_exports.enum([
36625
+ "boxed",
36626
+ "while-streaming",
36627
+ "flag-only"
36628
+ ]);
36584
36629
  var NativeObjectDetectionOptionsSchema = external_exports.object({
36585
36630
  /** Classes this firmware can detect — the same list the status reports. */
36586
36631
  supportedClasses: external_exports.array(NativeObjectClassEnum).readonly(),
@@ -36598,11 +36643,6 @@ var nativeObjectDetectionCapability = {
36598
36643
  deviceNative: true,
36599
36644
  mode: "singleton",
36600
36645
  deviceTypes: [DeviceType.Camera],
36601
- deviceConfig: { ui: {
36602
- kind: "derived-form",
36603
- builderId: "native-object-detection",
36604
- tab: "motion"
36605
- } },
36606
36646
  methods: {
36607
36647
  getOptions: method(external_exports.object({ deviceId: external_exports.number() }), NativeObjectDetectionOptionsSchema),
36608
36648
  setSettings: method(external_exports.object({
package/dist/cli.js CHANGED
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
3
  runDiscover
4
- } from "./chunk-KU5WDW2X.js";
4
+ } from "./chunk-G3ME646K.js";
5
5
  import "./chunk-LMMQX4CK.js";
6
6
 
7
7
  // src/cli.ts
@@ -38,7 +38,7 @@ async function runServe(args) {
38
38
  ...typeof values.data === "string" ? { data: values.data } : {}
39
39
  };
40
40
  Object.assign(process.env, buildServeEnv(opts));
41
- await import("./launcher-WSNFPR5V.js");
41
+ await import("./launcher-SQWBPN4O.js");
42
42
  }
43
43
 
44
44
  // src/commands/agent.ts
@@ -83,7 +83,7 @@ async function runAgent(args) {
83
83
  ...typeof values.port === "string" ? { port: values.port } : {}
84
84
  };
85
85
  Object.assign(process.env, buildAgentEnv(opts));
86
- await import("./launcher-WSNFPR5V.js");
86
+ await import("./launcher-SQWBPN4O.js");
87
87
  }
88
88
 
89
89
  // src/commands/setup.ts
@@ -1140,7 +1140,7 @@ function isUnknown(_value) {
1140
1140
  return true;
1141
1141
  }
1142
1142
  async function resolveServerInteractive(presetNamespace) {
1143
- const { discoverNodes, resolveHubFromDiscovered, filterHubNodes, DEFAULT_HUB_HTTPS_PORT } = await import("./discover-4NUJXKXL.js");
1143
+ const { discoverNodes, resolveHubFromDiscovered, filterHubNodes, DEFAULT_HUB_HTTPS_PORT } = await import("./discover-DFMZ7HZD.js");
1144
1144
  if (presetNamespace) {
1145
1145
  const spinner4 = clack.spinner();
1146
1146
  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-KU5WDW2X.js";
8
+ } from "./chunk-G3ME646K.js";
9
9
  import "./chunk-LMMQX4CK.js";
10
10
  export {
11
11
  DEFAULT_HUB_HTTPS_PORT,
@@ -23633,9 +23633,9 @@ var require_zod = __commonJS({
23633
23633
  }
23634
23634
  });
23635
23635
 
23636
- // ../system/dist/dist-D3lJV9M7.js
23637
- var require_dist_D3lJV9M7 = __commonJS({
23638
- "../system/dist/dist-D3lJV9M7.js"(exports) {
23636
+ // ../system/dist/dist-DaSCLJVH.js
23637
+ var require_dist_DaSCLJVH = __commonJS({
23638
+ "../system/dist/dist-DaSCLJVH.js"(exports) {
23639
23639
  "use strict";
23640
23640
  var zod = require_zod();
23641
23641
  var EventCategory = /* @__PURE__ */ (function(EventCategory2) {
@@ -39745,6 +39745,7 @@ var require_dist_D3lJV9M7 = __commonJS({
39745
39745
  "device-activity"
39746
39746
  ]);
39747
39747
  var MotionSourcesSchema = zod.z.array(MotionSourceEnum);
39748
+ var DetectionSourcesSchema = zod.z.array(DetectionSourceSchema);
39748
39749
  var ReportMotionInputSchema = zod.z.object({
39749
39750
  deviceId: zod.z.number(),
39750
39751
  detected: zod.z.boolean(),
@@ -39852,6 +39853,35 @@ var require_dist_D3lJV9M7 = __commonJS({
39852
39853
  * events; the orchestrator forwards to `reportMotion`.
39853
39854
  */
39854
39855
  motionSources: MotionSourcesSchema.default(["analyzer"]),
39856
+ /**
39857
+ * WHICH root detector runs for this camera. The detection counterpart of
39858
+ * {@link motionSources}, same shape and same discipline: a per-camera list
39859
+ * of sources the system understands, vendor-agnostic, owned here.
39860
+ *
39861
+ * - `pipeline` — this runner's own root step on decoded pixels (`steps`).
39862
+ * - `onboard` — the CAMERA's own detector, admitted only when it is named
39863
+ * here. Its boxes reach post-analysis on the same
39864
+ * `PipelineInferenceResult` payload as the pipeline's, so an onboard-born
39865
+ * track gets the same tracker, the same overlay and the same detail
39866
+ * subtree (face / plate / embedding).
39867
+ *
39868
+ * `['onboard']` alone is the REPLACEMENT: this runner's root step does not
39869
+ * run, and that is where a camera with a usable onboard detector buys back
39870
+ * its share of the accelerator. It saves the root inference, not the decode
39871
+ * — the detail subtree still needs pixels to cut crops from.
39872
+ *
39873
+ * A camera whose onboard detections carry no geometry cannot serve as a root
39874
+ * step at all (there is nothing to track), and the cap that knows this says
39875
+ * so on `native-object-detection.getOptions().geometry`. On Reolink that is
39876
+ * every battery camera: the boxes ride a sub-stream a battery camera never
39877
+ * attaches, so such a camera stays on `['pipeline']` and its onboard AI is
39878
+ * worth exactly what it already is — a wake signal with a class.
39879
+ *
39880
+ * Defaults to `['pipeline']`, which is byte-for-byte today's behaviour: a
39881
+ * vendor never turns a detector on for the operator, and neither does a
39882
+ * default.
39883
+ */
39884
+ detectionSources: DetectionSourcesSchema.default(["pipeline"]),
39855
39885
  pipelineEnabled: zod.z.boolean().default(true),
39856
39886
  /** Ordered tree of video steps. Absent → runner skips video detection. */
39857
39887
  steps: zod.z.array(PipelineStepInputSchema).readonly().optional(),
@@ -47156,17 +47186,19 @@ var require_dist_D3lJV9M7 = __commonJS({
47156
47186
  /**
47157
47187
  * Whether forwarding of onboard AI detections is enabled for this device.
47158
47188
  *
47159
- * The COLD-START default is the provider's, and it is not one value for
47160
- * every camera: a mains camera carries the boxed side-channel and its
47161
- * detections are usable subjects, so it defaults ON; a battery camera never
47162
- * attaches that channel, so the same toggle would buy it nothing but a write
47163
- * — it defaults OFF and an operator who wants it turns it on knowing what it
47164
- * costs. {@link NativeObjectDetectionOptionsSchema.geometry} is how the UI
47165
- * says which of the two a camera is.
47189
+ * Cold-start OFF on every camera. A vendor does not decide which detector a
47190
+ * camera runs — that is the operator's choice, and it is made where every
47191
+ * other detection choice is made. `geometry` on
47192
+ * {@link NativeObjectDetectionOptionsSchema} is how the form says what the
47193
+ * choice would buy this particular camera.
47166
47194
  */
47167
47195
  enabled: zod.z.boolean()
47168
47196
  });
47169
- var NativeObjectGeometryEnum = zod.z.enum(["boxed", "flag-only"]);
47197
+ var NativeObjectGeometryEnum = zod.z.enum([
47198
+ "boxed",
47199
+ "while-streaming",
47200
+ "flag-only"
47201
+ ]);
47170
47202
  var NativeObjectDetectionOptionsSchema = zod.z.object({
47171
47203
  /** Classes this firmware can detect — the same list the status reports. */
47172
47204
  supportedClasses: zod.z.array(NativeObjectClassEnum).readonly(),
@@ -47184,11 +47216,6 @@ var require_dist_D3lJV9M7 = __commonJS({
47184
47216
  deviceNative: true,
47185
47217
  mode: "singleton",
47186
47218
  deviceTypes: [DeviceType.Camera],
47187
- deviceConfig: { ui: {
47188
- kind: "derived-form",
47189
- builderId: "native-object-detection",
47190
- tab: "motion"
47191
- } },
47192
47219
  methods: {
47193
47220
  getOptions: method(zod.z.object({ deviceId: zod.z.number() }), NativeObjectDetectionOptionsSchema),
47194
47221
  setSettings: method(zod.z.object({
@@ -62352,7 +62379,7 @@ var require_alerts_addon = __commonJS({
62352
62379
  [Symbol.toStringTag]: { value: "Module" }
62353
62380
  });
62354
62381
  require_chunk_Cek0wNdY();
62355
- var require_dist10 = require_dist_D3lJV9M7();
62382
+ var require_dist10 = require_dist_DaSCLJVH();
62356
62383
  function selectExpired(alerts, cutoffMs) {
62357
62384
  return alerts.filter((a) => a.createdAt < cutoffMs).sort((a, b) => a.createdAt - b.createdAt).map((a) => a.id);
62358
62385
  }
@@ -63171,7 +63198,7 @@ var require_console_logging = __commonJS({
63171
63198
  [Symbol.toStringTag]: { value: "Module" }
63172
63199
  });
63173
63200
  require_chunk_Cek0wNdY();
63174
- var require_dist10 = require_dist_D3lJV9M7();
63201
+ var require_dist10 = require_dist_DaSCLJVH();
63175
63202
  var require_formatter = require_formatter_DqAKDlvN();
63176
63203
  var LEVEL_RANK = {
63177
63204
  debug: 0,
@@ -63265,7 +63292,7 @@ var require_core_blocks_addon = __commonJS({
63265
63292
  "use strict";
63266
63293
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
63267
63294
  var require_chunk = require_chunk_Cek0wNdY();
63268
- var require_dist10 = require_dist_D3lJV9M7();
63295
+ var require_dist10 = require_dist_DaSCLJVH();
63269
63296
  var node_crypto = __require("crypto");
63270
63297
  var node_fs_promises = __require("fs/promises");
63271
63298
  node_fs_promises = require_chunk.__toESM(node_fs_promises);
@@ -64162,11 +64189,11 @@ var require_core_blocks = __commonJS({
64162
64189
  }
64163
64190
  });
64164
64191
 
64165
- // ../system/dist/retired-settings-keys-YPsd2Exa.js
64166
- var require_retired_settings_keys_YPsd2Exa = __commonJS({
64167
- "../system/dist/retired-settings-keys-YPsd2Exa.js"(exports) {
64192
+ // ../system/dist/retired-settings-keys-CZISf623.js
64193
+ var require_retired_settings_keys_CZISf623 = __commonJS({
64194
+ "../system/dist/retired-settings-keys-CZISf623.js"(exports) {
64168
64195
  "use strict";
64169
- var require_dist10 = require_dist_D3lJV9M7();
64196
+ var require_dist10 = require_dist_DaSCLJVH();
64170
64197
  function settingsStoreIsAuthoritativeHere(env) {
64171
64198
  const raw = (env["CAMSTACK_ROLE"] ?? "").trim().toLowerCase();
64172
64199
  return raw === "" || raw === "hub";
@@ -66403,8 +66430,8 @@ var require_device_manager_addon = __commonJS({
66403
66430
  [Symbol.toStringTag]: { value: "Module" }
66404
66431
  });
66405
66432
  require_chunk_Cek0wNdY();
66406
- var require_dist10 = require_dist_D3lJV9M7();
66407
- var require_retired_settings_keys = require_retired_settings_keys_YPsd2Exa();
66433
+ var require_dist10 = require_dist_DaSCLJVH();
66434
+ var require_retired_settings_keys = require_retired_settings_keys_CZISf623();
66408
66435
  var node_crypto = __require("crypto");
66409
66436
  var _camstack_types_node = require_node();
66410
66437
  var JOB_HISTORY = 20;
@@ -67296,39 +67323,9 @@ var require_device_manager_addon = __commonJS({
67296
67323
  if ("imageSettings_backlightMode" in patch && isBacklightMode(patch.imageSettings_backlightMode)) out.backlightMode = patch.imageSettings_backlightMode;
67297
67324
  return out;
67298
67325
  }
67299
- var GEOMETRY_HELP = {
67300
- boxed: "This camera ships a bounding box with each detection, so the pipeline tracks it as a subject: it gets a track, a best shot and the notification rules that address onboard detections.",
67301
- "flag-only": "This camera ships the class with no bounding box \u2014 on Reolink that is every battery camera, because the boxes ride a sub-stream a battery camera never attaches. Turning this on makes the detections reach the tracker as motion and no further; it will not produce tracked subjects."
67302
- };
67303
- function buildNativeObjectDetectionConfigSchema(options, status) {
67304
- if (options.supportedClasses.length === 0) return null;
67305
- const fields = [{
67306
- type: "boolean",
67307
- key: "nativeObjectDetection_enabled",
67308
- label: "Forward onboard AI detections",
67309
- default: status?.enabled ?? false
67310
- }];
67311
- return { sections: [{
67312
- id: "native-object-detection",
67313
- tab: "motion",
67314
- title: "Onboard AI detections",
67315
- description: `${GEOMETRY_HELP[options.geometry]} Detected by this firmware: ${options.supportedClasses.join(", ")}.`,
67316
- columns: 1,
67317
- fields
67318
- }] };
67319
- }
67320
- function parseNativeObjectDetectionFormPatch(patch) {
67321
- const out = {};
67322
- if ("nativeObjectDetection_enabled" in patch) {
67323
- const value = patch.nativeObjectDetection_enabled;
67324
- if (typeof value === "boolean") out.enabled = value;
67325
- }
67326
- return out;
67327
- }
67328
67326
  var STREAM_PARAMS_BUILDER_ID = "stream-params";
67329
67327
  var DAY_NIGHT_BUILDER_ID = "day-night";
67330
67328
  var IMAGE_SETTINGS_BUILDER_ID = "image-settings";
67331
- var NATIVE_OBJECT_DETECTION_BUILDER_ID = "native-object-detection";
67332
67329
  var STREAM_PARAMS_REDUCER = {
67333
67330
  kind: "profile",
67334
67331
  buildSchema: (options, status) => require_dist10.buildStreamParamsConfigSchema(options, status ?? null),
@@ -67349,16 +67346,10 @@ var require_device_manager_addon = __commonJS({
67349
67346
  buildSchema: (options, status) => buildImageSettingsConfigSchema(options, status ?? null),
67350
67347
  parsePatch: (patch) => parseImageSettingsFormPatch(patch)
67351
67348
  };
67352
- var NATIVE_OBJECT_DETECTION_REDUCER = {
67353
- kind: "settings",
67354
- buildSchema: (options, status) => buildNativeObjectDetectionConfigSchema(options, status ?? null),
67355
- parsePatch: (patch) => parseNativeObjectDetectionFormPatch(patch)
67356
- };
67357
67349
  var BUILDER_REDUCERS = {
67358
67350
  [STREAM_PARAMS_BUILDER_ID]: STREAM_PARAMS_REDUCER,
67359
67351
  [DAY_NIGHT_BUILDER_ID]: DAY_NIGHT_REDUCER,
67360
- [IMAGE_SETTINGS_BUILDER_ID]: IMAGE_SETTINGS_REDUCER,
67361
- [NATIVE_OBJECT_DETECTION_BUILDER_ID]: NATIVE_OBJECT_DETECTION_REDUCER
67352
+ [IMAGE_SETTINGS_BUILDER_ID]: IMAGE_SETTINGS_REDUCER
67362
67353
  };
67363
67354
  function resolveReducer(builderId) {
67364
67355
  const reducer = BUILDER_REDUCERS[builderId];
@@ -72065,7 +72056,7 @@ var require_hub_forwarder = __commonJS({
72065
72056
  [Symbol.toStringTag]: { value: "Module" }
72066
72057
  });
72067
72058
  require_chunk_Cek0wNdY();
72068
- var require_dist10 = require_dist_D3lJV9M7();
72059
+ var require_dist10 = require_dist_DaSCLJVH();
72069
72060
  var require_formatter = require_formatter_DqAKDlvN();
72070
72061
  var DEFAULT_OUTBOUND_BUFFER_SIZE = 500;
72071
72062
  var HubForwarderDestination = class {
@@ -72202,7 +72193,7 @@ var require_liveness_monitor_addon = __commonJS({
72202
72193
  "use strict";
72203
72194
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
72204
72195
  require_chunk_Cek0wNdY();
72205
- var require_dist10 = require_dist_D3lJV9M7();
72196
+ var require_dist10 = require_dist_DaSCLJVH();
72206
72197
  var NO_DEVICES = "liveness:no-devices";
72207
72198
  var ALL_OFFLINE = "liveness:all-devices-offline";
72208
72199
  var NO_FOOTAGE_PREFIX = "liveness:no-footage:";
@@ -72398,7 +72389,7 @@ var require_local_auth_addon = __commonJS({
72398
72389
  [Symbol.toStringTag]: { value: "Module" }
72399
72390
  });
72400
72391
  var require_chunk = require_chunk_Cek0wNdY();
72401
- var require_dist10 = require_dist_D3lJV9M7();
72392
+ var require_dist10 = require_dist_DaSCLJVH();
72402
72393
  var node_crypto = __require("crypto");
72403
72394
  node_crypto = require_chunk.__toESM(node_crypto);
72404
72395
  var crypto$1 = __require("crypto");
@@ -80211,7 +80202,7 @@ var require_loki_logging = __commonJS({
80211
80202
  [Symbol.toStringTag]: { value: "Module" }
80212
80203
  });
80213
80204
  require_chunk_Cek0wNdY();
80214
- var require_dist10 = require_dist_D3lJV9M7();
80205
+ var require_dist10 = require_dist_DaSCLJVH();
80215
80206
  function sanitizeLabelName(raw) {
80216
80207
  const replaced = raw.replaceAll(/[^a-zA-Z0-9_]/g, "_");
80217
80208
  return /^[a-zA-Z_]/.test(replaced) ? replaced : `_${replaced}`;
@@ -80798,7 +80789,7 @@ var require_native_metrics_addon = __commonJS({
80798
80789
  [Symbol.toStringTag]: { value: "Module" }
80799
80790
  });
80800
80791
  var require_chunk = require_chunk_Cek0wNdY();
80801
- var require_dist10 = require_dist_D3lJV9M7();
80792
+ var require_dist10 = require_dist_DaSCLJVH();
80802
80793
  var node_fs_promises = __require("fs/promises");
80803
80794
  var node_fs = __require("fs");
80804
80795
  node_fs = require_chunk.__toESM(node_fs);
@@ -83551,7 +83542,7 @@ var require_filesystem_storage_addon = __commonJS({
83551
83542
  [Symbol.toStringTag]: { value: "Module" }
83552
83543
  });
83553
83544
  var require_chunk = require_chunk_Cek0wNdY();
83554
- var require_dist10 = require_dist_D3lJV9M7();
83545
+ var require_dist10 = require_dist_DaSCLJVH();
83555
83546
  var node_crypto = __require("crypto");
83556
83547
  var node_fs_promises = __require("fs/promises");
83557
83548
  var node_path = __require("path");
@@ -84778,8 +84769,8 @@ var require_sqlite_settings_addon = __commonJS({
84778
84769
  [Symbol.toStringTag]: { value: "Module" }
84779
84770
  });
84780
84771
  var require_chunk = require_chunk_Cek0wNdY();
84781
- var require_dist10 = require_dist_D3lJV9M7();
84782
- var require_retired_settings_keys = require_retired_settings_keys_YPsd2Exa();
84772
+ var require_dist10 = require_dist_DaSCLJVH();
84773
+ var require_retired_settings_keys = require_retired_settings_keys_CZISf623();
84783
84774
  var require_wal_checkpoint_policy = require_wal_checkpoint_policy_CCJZngds();
84784
84775
  var node_crypto = __require("crypto");
84785
84776
  var node_path = __require("path");
@@ -87566,7 +87557,7 @@ var require_storage_orchestrator_addon = __commonJS({
87566
87557
  [Symbol.toStringTag]: { value: "Module" }
87567
87558
  });
87568
87559
  var require_chunk = require_chunk_Cek0wNdY();
87569
- var require_dist10 = require_dist_D3lJV9M7();
87560
+ var require_dist10 = require_dist_DaSCLJVH();
87570
87561
  var require_hub_cap_forward = require_hub_cap_forward_DmHNjbB0();
87571
87562
  var zod = require_zod();
87572
87563
  var node_crypto = __require("crypto");
@@ -91293,7 +91284,7 @@ var require_system_config_addon = __commonJS({
91293
91284
  [Symbol.toStringTag]: { value: "Module" }
91294
91285
  });
91295
91286
  require_chunk_Cek0wNdY();
91296
- var require_dist10 = require_dist_D3lJV9M7();
91287
+ var require_dist10 = require_dist_DaSCLJVH();
91297
91288
  var SECTION_TITLES = {
91298
91289
  server: "Server",
91299
91290
  auth: "Authentication"
@@ -109354,7 +109345,7 @@ var require_winston_logging = __commonJS({
109354
109345
  [Symbol.toStringTag]: { value: "Module" }
109355
109346
  });
109356
109347
  var require_chunk = require_chunk_Cek0wNdY();
109357
- var require_dist10 = require_dist_D3lJV9M7();
109348
+ var require_dist10 = require_dist_DaSCLJVH();
109358
109349
  var require_formatter = require_formatter_DqAKDlvN();
109359
109350
  var node_path = __require("path");
109360
109351
  node_path = require_chunk.__toESM(node_path);
@@ -115371,6 +115362,7 @@ var require_addon = __commonJS({
115371
115362
  "motionFps": 4,
115372
115363
  "detectionFps": 10,
115373
115364
  "motionSources": ["analyzer"],
115365
+ "detectionSources": ["pipeline"],
115374
115366
  "pipelineEnabled": true,
115375
115367
  "zones": [],
115376
115368
  "onboardMotionDrivesAnalyzer": true,
@@ -131643,11 +131635,11 @@ var require_manifest_system_deps_CrSP0Kkp = __commonJS({
131643
131635
  }
131644
131636
  });
131645
131637
 
131646
- // ../system/dist/custom-action-registry-CWFK5UDj.js
131647
- var require_custom_action_registry_CWFK5UDj = __commonJS({
131648
- "../system/dist/custom-action-registry-CWFK5UDj.js"(exports) {
131638
+ // ../system/dist/custom-action-registry-DG-QIWxd.js
131639
+ var require_custom_action_registry_DG_QIWxd = __commonJS({
131640
+ "../system/dist/custom-action-registry-DG-QIWxd.js"(exports) {
131649
131641
  "use strict";
131650
- var require_dist10 = require_dist_D3lJV9M7();
131642
+ var require_dist10 = require_dist_DaSCLJVH();
131651
131643
  var CustomActionRegistry = class {
131652
131644
  byAddon = /* @__PURE__ */ new Map();
131653
131645
  registerAddon(addonId, catalog, handler) {
@@ -135461,7 +135453,7 @@ var require_dist3 = __commonJS({
135461
135453
  "use strict";
135462
135454
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
135463
135455
  var require_chunk = require_chunk_Cek0wNdY();
135464
- var require_dist10 = require_dist_D3lJV9M7();
135456
+ var require_dist10 = require_dist_DaSCLJVH();
135465
135457
  var require_builtins_alerts_alerts_addon = require_alerts_addon();
135466
135458
  require_alerts();
135467
135459
  var require_formatter = require_formatter_DqAKDlvN();
@@ -135490,7 +135482,7 @@ var require_dist3 = __commonJS({
135490
135482
  var require_tls$1 = require_tls_BFs4PzoW();
135491
135483
  var require_manifest_system_deps = require_manifest_system_deps_CrSP0Kkp();
135492
135484
  var require_resource_monitor = require_resource_monitor_LVE1BoLs();
135493
- var require_custom_action_registry = require_custom_action_registry_CWFK5UDj();
135485
+ var require_custom_action_registry = require_custom_action_registry_DG_QIWxd();
135494
135486
  var zod = require_zod();
135495
135487
  var node_crypto = __require("crypto");
135496
135488
  var _camstack_types_node = require_node();
@@ -233509,6 +233501,7 @@ ${recipe.triggers.map((t, i) => emitTrigger(t, i)).join("\n\n")}
233509
233501
  "device-activity"
233510
233502
  ]);
233511
233503
  var MotionSourcesSchema = zod.z.array(MotionSourceEnum);
233504
+ var DetectionSourcesSchema = zod.z.array(DetectionSourceSchema);
233512
233505
  var ReportMotionInputSchema = zod.z.object({
233513
233506
  deviceId: zod.z.number(),
233514
233507
  detected: zod.z.boolean(),
@@ -233616,6 +233609,35 @@ ${recipe.triggers.map((t, i) => emitTrigger(t, i)).join("\n\n")}
233616
233609
  * events; the orchestrator forwards to `reportMotion`.
233617
233610
  */
233618
233611
  motionSources: MotionSourcesSchema.default(["analyzer"]),
233612
+ /**
233613
+ * WHICH root detector runs for this camera. The detection counterpart of
233614
+ * {@link motionSources}, same shape and same discipline: a per-camera list
233615
+ * of sources the system understands, vendor-agnostic, owned here.
233616
+ *
233617
+ * - `pipeline` — this runner's own root step on decoded pixels (`steps`).
233618
+ * - `onboard` — the CAMERA's own detector, admitted only when it is named
233619
+ * here. Its boxes reach post-analysis on the same
233620
+ * `PipelineInferenceResult` payload as the pipeline's, so an onboard-born
233621
+ * track gets the same tracker, the same overlay and the same detail
233622
+ * subtree (face / plate / embedding).
233623
+ *
233624
+ * `['onboard']` alone is the REPLACEMENT: this runner's root step does not
233625
+ * run, and that is where a camera with a usable onboard detector buys back
233626
+ * its share of the accelerator. It saves the root inference, not the decode
233627
+ * — the detail subtree still needs pixels to cut crops from.
233628
+ *
233629
+ * A camera whose onboard detections carry no geometry cannot serve as a root
233630
+ * step at all (there is nothing to track), and the cap that knows this says
233631
+ * so on `native-object-detection.getOptions().geometry`. On Reolink that is
233632
+ * every battery camera: the boxes ride a sub-stream a battery camera never
233633
+ * attaches, so such a camera stays on `['pipeline']` and its onboard AI is
233634
+ * worth exactly what it already is — a wake signal with a class.
233635
+ *
233636
+ * Defaults to `['pipeline']`, which is byte-for-byte today's behaviour: a
233637
+ * vendor never turns a detector on for the operator, and neither does a
233638
+ * default.
233639
+ */
233640
+ detectionSources: DetectionSourcesSchema.default(["pipeline"]),
233619
233641
  pipelineEnabled: zod.z.boolean().default(true),
233620
233642
  /** Ordered tree of video steps. Absent → runner skips video detection. */
233621
233643
  steps: zod.z.array(PipelineStepInputSchema).readonly().optional(),
@@ -233738,6 +233760,19 @@ ${recipe.triggers.map((t, i) => emitTrigger(t, i)).join("\n\n")}
233738
233760
  }
233739
233761
  ]
233740
233762
  },
233763
+ {
233764
+ key: "detectionSources",
233765
+ type: "multiselect",
233766
+ label: "Detection Sources",
233767
+ default: ["pipeline"],
233768
+ options: [{
233769
+ value: "pipeline",
233770
+ label: "This node (ML root step on decoded frames)"
233771
+ }, {
233772
+ value: "onboard",
233773
+ label: "Camera onboard AI (replaces the root step when picked alone)"
233774
+ }]
233775
+ },
233741
233776
  {
233742
233777
  key: "motionFps",
233743
233778
  type: "slider",
@@ -241118,17 +241153,19 @@ ${recipe.triggers.map((t, i) => emitTrigger(t, i)).join("\n\n")}
241118
241153
  /**
241119
241154
  * Whether forwarding of onboard AI detections is enabled for this device.
241120
241155
  *
241121
- * The COLD-START default is the provider's, and it is not one value for
241122
- * every camera: a mains camera carries the boxed side-channel and its
241123
- * detections are usable subjects, so it defaults ON; a battery camera never
241124
- * attaches that channel, so the same toggle would buy it nothing but a write
241125
- * — it defaults OFF and an operator who wants it turns it on knowing what it
241126
- * costs. {@link NativeObjectDetectionOptionsSchema.geometry} is how the UI
241127
- * says which of the two a camera is.
241156
+ * Cold-start OFF on every camera. A vendor does not decide which detector a
241157
+ * camera runs — that is the operator's choice, and it is made where every
241158
+ * other detection choice is made. `geometry` on
241159
+ * {@link NativeObjectDetectionOptionsSchema} is how the form says what the
241160
+ * choice would buy this particular camera.
241128
241161
  */
241129
241162
  enabled: zod.z.boolean()
241130
241163
  });
241131
- var NativeObjectGeometryEnum = zod.z.enum(["boxed", "flag-only"]);
241164
+ var NativeObjectGeometryEnum = zod.z.enum([
241165
+ "boxed",
241166
+ "while-streaming",
241167
+ "flag-only"
241168
+ ]);
241132
241169
  var NativeObjectDetectionOptionsSchema = zod.z.object({
241133
241170
  /** Classes this firmware can detect — the same list the status reports. */
241134
241171
  supportedClasses: zod.z.array(NativeObjectClassEnum).readonly(),
@@ -241146,11 +241183,6 @@ ${recipe.triggers.map((t, i) => emitTrigger(t, i)).join("\n\n")}
241146
241183
  deviceNative: true,
241147
241184
  mode: "singleton",
241148
241185
  deviceTypes: [require_sleep.DeviceType.Camera],
241149
- deviceConfig: { ui: {
241150
- kind: "derived-form",
241151
- builderId: "native-object-detection",
241152
- tab: "motion"
241153
- } },
241154
241186
  methods: {
241155
241187
  getOptions: require_sleep.method(zod.z.object({ deviceId: zod.z.number() }), NativeObjectDetectionOptionsSchema),
241156
241188
  setSettings: require_sleep.method(zod.z.object({
@@ -262722,6 +262754,7 @@ ${recipe.triggers.map((t, i) => emitTrigger(t, i)).join("\n\n")}
262722
262754
  exports.DetailCropConventionSchema = DetailCropConventionSchema;
262723
262755
  exports.DetectionCatalogClassMapSchema = DetectionCatalogClassMapSchema;
262724
262756
  exports.DetectionSourceSchema = DetectionSourceSchema;
262757
+ exports.DetectionSourcesSchema = DetectionSourcesSchema;
262725
262758
  exports.DeviceCodeSeveritySchema = DeviceCodeSeveritySchema;
262726
262759
  exports.DeviceConfig = DeviceConfig;
262727
262760
  exports.DeviceDiscoveryStatusSchema = DeviceDiscoveryStatusSchema;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "camstack",
3
- "version": "1.2.150",
3
+ "version": "1.2.152",
4
4
  "description": "CLI tool for managing and running CamStack server",
5
5
  "keywords": [
6
6
  "camstack",