camstack 1.2.90 → 1.2.92

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.
@@ -14522,7 +14522,7 @@ function date4(params) {
14522
14522
  // ../../node_modules/zod/v4/classic/external.js
14523
14523
  config(en_default());
14524
14524
 
14525
- // ../types/dist/sleep-B195W080.mjs
14525
+ // ../types/dist/sleep-CbBk_3GJ.mjs
14526
14526
  var WELL_KNOWN_TABS = [
14527
14527
  {
14528
14528
  id: "overview",
@@ -20596,7 +20596,7 @@ var ConfigEntrySchema2 = external_exports.object({
20596
20596
  value: external_exports.unknown(),
20597
20597
  description: external_exports.string().optional()
20598
20598
  });
20599
- var LinkedDevicesModeSchema = external_exports.enum(["auto", "manual"]);
20599
+ var LinkedDevicesModeSchema = external_exports.enum(["manual"]);
20600
20600
  var LinkedDeviceSchema = external_exports.object({
20601
20601
  deviceId: external_exports.number(),
20602
20602
  name: external_exports.string(),
@@ -26134,6 +26134,21 @@ var TrackFlagFields = {
26134
26134
  markForTrain: external_exports.boolean().optional(),
26135
26135
  /** Operator marked this track for diagnostic attention. */
26136
26136
  debug: external_exports.boolean().optional(),
26137
+ /**
26138
+ * What the operator wants CHECKED on this track, in their own words.
26139
+ *
26140
+ * The flag alone says "look at this" and nothing about what for; a debug set
26141
+ * reviewed hours later is a list of tracks with no question attached. Bound
26142
+ * to `debug` on the WRITE side — the body clears it when `debug` goes off,
26143
+ * and refuses it on a track whose debug is off — so a note can never outlive
26144
+ * the attention it belongs to.
26145
+ *
26146
+ * `''` is a real value ("marked, nothing to add"); the ABSENT key means
26147
+ * "leave whatever is stored alone", which is what lets a surface turn debug
26148
+ * on without a note (a cancelled prompt) and what lets it edit the note
26149
+ * without touching the flag.
26150
+ */
26151
+ debugNote: external_exports.string().max(500).optional(),
26137
26152
  /** Operator favourited this track. Pins it against pruning. */
26138
26153
  favourited: external_exports.boolean().optional()
26139
26154
  };
@@ -26143,6 +26158,12 @@ var TrackFlagsSchema = external_exports.object({
26143
26158
  trackId: external_exports.string(),
26144
26159
  markForTrain: external_exports.boolean(),
26145
26160
  debug: external_exports.boolean(),
26161
+ /** The note as it STANDS after the write — never absent here (a track with no
26162
+ * note reports `''`), for the same reason the booleans are required: a
26163
+ * surface that has just written must be able to render the note it now owns
26164
+ * without a re-fetch, and an absent key would read as "unchanged" on a
26165
+ * screen that has no previous value to keep. */
26166
+ debugNote: external_exports.string(),
26146
26167
  favourited: external_exports.boolean(),
26147
26168
  /** The lifecycle state the boolean was derived from. Required here (unlike on
26148
26169
  * a track row) because this shape is only ever produced by the write body,
@@ -27197,11 +27218,20 @@ var pipelineAnalyticsCapability = {
27197
27218
  * staging is a deliberate action of the retrain page, which is also the only
27198
27219
  * thing that produces `trained` in the first place.
27199
27220
  *
27200
- * Returns the RESOLVED state of both flags (absent → `false`) plus the
27201
- * `retrainStatus` they were derived from, so a caller can drive its toggle
27202
- * — and render a `trained` badge — without a re-fetch. Rejects an unknown
27203
- * track, a new staging mark on a device already holding its full budget, and
27204
- * any `markForTrain` write against a trained track.
27221
+ * `debugNote` is the operator's sentence about WHAT to check on this track,
27222
+ * and it is bound to `debug`: writing `debug: false` clears it in the same
27223
+ * statement, and a note sent for a track whose debug is off (and is not
27224
+ * being turned on) is DROPPED with a warning rather than stored where
27225
+ * nothing will ever read it. An omitted `debugNote` leaves the stored one
27226
+ * alone — which is what lets a surface turn debug on when the operator
27227
+ * declined to type anything, without that refusal costing them the flag.
27228
+ *
27229
+ * Returns the RESOLVED state of all three flags (absent → `false`) plus the
27230
+ * note (absent → `''`) and the `retrainStatus` they were derived from, so a
27231
+ * caller can drive its toggle — and render a `trained` badge — without a
27232
+ * re-fetch. Rejects an unknown track, a new staging mark on a device already
27233
+ * holding its full budget, and any `markForTrain` write against a trained
27234
+ * track.
27205
27235
  */
27206
27236
  setTrackFlags: method(external_exports.object({
27207
27237
  /** Log/audit scope only — the trackId is globally unique on its own. */
package/dist/cli.js CHANGED
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
3
  runDiscover
4
- } from "./chunk-BLJRLA7I.js";
4
+ } from "./chunk-KFUPFPP3.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-7KH64TCV.js");
41
+ await import("./launcher-7Z35E2WM.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-7KH64TCV.js");
86
+ await import("./launcher-7Z35E2WM.js");
87
87
  }
88
88
 
89
89
  // src/commands/setup.ts
@@ -1130,7 +1130,7 @@ function isUnknown(_value) {
1130
1130
  return true;
1131
1131
  }
1132
1132
  async function resolveServerInteractive(presetNamespace) {
1133
- const { discoverNodes, resolveHubFromDiscovered, filterHubNodes, DEFAULT_HUB_HTTPS_PORT } = await import("./discover-FHE2CTRJ.js");
1133
+ const { discoverNodes, resolveHubFromDiscovered, filterHubNodes, DEFAULT_HUB_HTTPS_PORT } = await import("./discover-5KWSHFNI.js");
1134
1134
  if (presetNamespace) {
1135
1135
  const spinner4 = clack.spinner();
1136
1136
  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-BLJRLA7I.js";
8
+ } from "./chunk-KFUPFPP3.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-DE3OH-FG.js
23637
- var require_dist_DE3OH_FG = __commonJS({
23638
- "../system/dist/dist-DE3OH-FG.js"(exports) {
23636
+ // ../system/dist/dist-DNwhsXWi.js
23637
+ var require_dist_DNwhsXWi = __commonJS({
23638
+ "../system/dist/dist-DNwhsXWi.js"(exports) {
23639
23639
  "use strict";
23640
23640
  var zod = require_zod();
23641
23641
  var EventCategory = /* @__PURE__ */ (function(EventCategory2) {
@@ -31309,7 +31309,7 @@ var require_dist_DE3OH_FG = __commonJS({
31309
31309
  value: zod.z.unknown(),
31310
31310
  description: zod.z.string().optional()
31311
31311
  });
31312
- var LinkedDevicesModeSchema = zod.z.enum(["auto", "manual"]);
31312
+ var LinkedDevicesModeSchema = zod.z.enum(["manual"]);
31313
31313
  var LinkedDeviceSchema = zod.z.object({
31314
31314
  deviceId: zod.z.number(),
31315
31315
  name: zod.z.string(),
@@ -36840,6 +36840,21 @@ var require_dist_DE3OH_FG = __commonJS({
36840
36840
  markForTrain: zod.z.boolean().optional(),
36841
36841
  /** Operator marked this track for diagnostic attention. */
36842
36842
  debug: zod.z.boolean().optional(),
36843
+ /**
36844
+ * What the operator wants CHECKED on this track, in their own words.
36845
+ *
36846
+ * The flag alone says "look at this" and nothing about what for; a debug set
36847
+ * reviewed hours later is a list of tracks with no question attached. Bound
36848
+ * to `debug` on the WRITE side — the body clears it when `debug` goes off,
36849
+ * and refuses it on a track whose debug is off — so a note can never outlive
36850
+ * the attention it belongs to.
36851
+ *
36852
+ * `''` is a real value ("marked, nothing to add"); the ABSENT key means
36853
+ * "leave whatever is stored alone", which is what lets a surface turn debug
36854
+ * on without a note (a cancelled prompt) and what lets it edit the note
36855
+ * without touching the flag.
36856
+ */
36857
+ debugNote: zod.z.string().max(500).optional(),
36843
36858
  /** Operator favourited this track. Pins it against pruning. */
36844
36859
  favourited: zod.z.boolean().optional()
36845
36860
  };
@@ -36849,6 +36864,12 @@ var require_dist_DE3OH_FG = __commonJS({
36849
36864
  trackId: zod.z.string(),
36850
36865
  markForTrain: zod.z.boolean(),
36851
36866
  debug: zod.z.boolean(),
36867
+ /** The note as it STANDS after the write — never absent here (a track with no
36868
+ * note reports `''`), for the same reason the booleans are required: a
36869
+ * surface that has just written must be able to render the note it now owns
36870
+ * without a re-fetch, and an absent key would read as "unchanged" on a
36871
+ * screen that has no previous value to keep. */
36872
+ debugNote: zod.z.string(),
36852
36873
  favourited: zod.z.boolean(),
36853
36874
  /** The lifecycle state the boolean was derived from. Required here (unlike on
36854
36875
  * a track row) because this shape is only ever produced by the write body,
@@ -37902,11 +37923,20 @@ var require_dist_DE3OH_FG = __commonJS({
37902
37923
  * staging is a deliberate action of the retrain page, which is also the only
37903
37924
  * thing that produces `trained` in the first place.
37904
37925
  *
37905
- * Returns the RESOLVED state of both flags (absent → `false`) plus the
37906
- * `retrainStatus` they were derived from, so a caller can drive its toggle
37907
- * — and render a `trained` badge — without a re-fetch. Rejects an unknown
37908
- * track, a new staging mark on a device already holding its full budget, and
37909
- * any `markForTrain` write against a trained track.
37926
+ * `debugNote` is the operator's sentence about WHAT to check on this track,
37927
+ * and it is bound to `debug`: writing `debug: false` clears it in the same
37928
+ * statement, and a note sent for a track whose debug is off (and is not
37929
+ * being turned on) is DROPPED with a warning rather than stored where
37930
+ * nothing will ever read it. An omitted `debugNote` leaves the stored one
37931
+ * alone — which is what lets a surface turn debug on when the operator
37932
+ * declined to type anything, without that refusal costing them the flag.
37933
+ *
37934
+ * Returns the RESOLVED state of all three flags (absent → `false`) plus the
37935
+ * note (absent → `''`) and the `retrainStatus` they were derived from, so a
37936
+ * caller can drive its toggle — and render a `trained` badge — without a
37937
+ * re-fetch. Rejects an unknown track, a new staging mark on a device already
37938
+ * holding its full budget, and any `markForTrain` write against a trained
37939
+ * track.
37910
37940
  */
37911
37941
  setTrackFlags: method(zod.z.object({
37912
37942
  /** Log/audit scope only — the trackId is globally unique on its own. */
@@ -60079,7 +60109,7 @@ var require_alerts_addon = __commonJS({
60079
60109
  [Symbol.toStringTag]: { value: "Module" }
60080
60110
  });
60081
60111
  require_chunk_Cek0wNdY();
60082
- var require_dist10 = require_dist_DE3OH_FG();
60112
+ var require_dist10 = require_dist_DNwhsXWi();
60083
60113
  function selectExpired(alerts, cutoffMs) {
60084
60114
  return alerts.filter((a) => a.createdAt < cutoffMs).sort((a, b) => a.createdAt - b.createdAt).map((a) => a.id);
60085
60115
  }
@@ -60898,7 +60928,7 @@ var require_console_logging = __commonJS({
60898
60928
  [Symbol.toStringTag]: { value: "Module" }
60899
60929
  });
60900
60930
  require_chunk_Cek0wNdY();
60901
- var require_dist10 = require_dist_DE3OH_FG();
60931
+ var require_dist10 = require_dist_DNwhsXWi();
60902
60932
  var require_formatter = require_formatter_DqAKDlvN();
60903
60933
  var LEVEL_RANK = {
60904
60934
  debug: 0,
@@ -60992,7 +61022,7 @@ var require_core_blocks_addon = __commonJS({
60992
61022
  "use strict";
60993
61023
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
60994
61024
  var require_chunk = require_chunk_Cek0wNdY();
60995
- var require_dist10 = require_dist_DE3OH_FG();
61025
+ var require_dist10 = require_dist_DNwhsXWi();
60996
61026
  var node_crypto = __require("crypto");
60997
61027
  var node_fs_promises = __require("fs/promises");
60998
61028
  node_fs_promises = require_chunk.__toESM(node_fs_promises);
@@ -61889,11 +61919,11 @@ var require_core_blocks = __commonJS({
61889
61919
  }
61890
61920
  });
61891
61921
 
61892
- // ../system/dist/retired-settings-keys-BgUS9Rr3.js
61893
- var require_retired_settings_keys_BgUS9Rr3 = __commonJS({
61894
- "../system/dist/retired-settings-keys-BgUS9Rr3.js"(exports) {
61922
+ // ../system/dist/retired-settings-keys-CUXClAIQ.js
61923
+ var require_retired_settings_keys_CUXClAIQ = __commonJS({
61924
+ "../system/dist/retired-settings-keys-CUXClAIQ.js"(exports) {
61895
61925
  "use strict";
61896
- var require_dist10 = require_dist_DE3OH_FG();
61926
+ var require_dist10 = require_dist_DNwhsXWi();
61897
61927
  function settingsStoreIsAuthoritativeHere(env) {
61898
61928
  const raw = (env["CAMSTACK_ROLE"] ?? "").trim().toLowerCase();
61899
61929
  return raw === "" || raw === "hub";
@@ -64107,8 +64137,8 @@ var require_device_manager_addon = __commonJS({
64107
64137
  [Symbol.toStringTag]: { value: "Module" }
64108
64138
  });
64109
64139
  require_chunk_Cek0wNdY();
64110
- var require_dist10 = require_dist_DE3OH_FG();
64111
- var require_retired_settings_keys = require_retired_settings_keys_BgUS9Rr3();
64140
+ var require_dist10 = require_dist_DNwhsXWi();
64141
+ var require_retired_settings_keys = require_retired_settings_keys_CUXClAIQ();
64112
64142
  var node_crypto = __require("crypto");
64113
64143
  var _camstack_types_node = require_node();
64114
64144
  var JOB_HISTORY = 20;
@@ -65729,7 +65759,7 @@ var require_device_manager_addon = __commonJS({
65729
65759
  var LINKED_IDS_CONFIG_KEY = "_linkedDeviceIds";
65730
65760
  var LINKED_TRACKED_IDS_CONFIG_KEY = "_linkedDeviceTrackedIds";
65731
65761
  function parseLinkedDevicesConfig(blob) {
65732
- const mode = blob["_linkedDevicesMode"] === "manual" ? "manual" : "auto";
65762
+ const mode = "manual";
65733
65763
  const rawIds = blob[LINKED_IDS_CONFIG_KEY];
65734
65764
  const manualIds = [];
65735
65765
  if (Array.isArray(rawIds)) for (const v of rawIds) {
@@ -65761,7 +65791,7 @@ var require_device_manager_addon = __commonJS({
65761
65791
  if (primary !== null) expandContainer(primary.id, byId, byParent, nextVisited, out);
65762
65792
  }
65763
65793
  function resolveLinkedDeviceIds(params) {
65764
- const { selfId, selfLocation, config, candidates } = params;
65794
+ const { selfId, config, candidates } = params;
65765
65795
  const byId = new Map(candidates.map((c) => [c.id, c]));
65766
65796
  const byParent = /* @__PURE__ */ new Map();
65767
65797
  for (const c of candidates) {
@@ -65773,99 +65803,52 @@ var require_device_manager_addon = __commonJS({
65773
65803
  const ids = /* @__PURE__ */ new Set();
65774
65804
  const expand = (id) => expandContainer(id, byId, byParent, /* @__PURE__ */ new Set(), ids);
65775
65805
  for (const c of candidates) if (c.parentDeviceId === selfId) expand(c.id);
65776
- if (config.mode === "auto") {
65777
- if (selfLocation !== null && selfLocation.length > 0) for (const c of candidates) {
65778
- if (c.type === require_dist10.DeviceType.Container) continue;
65779
- if (c.location !== selfLocation) continue;
65780
- const parent = c.parentDeviceId !== null ? byId.get(c.parentDeviceId) : void 0;
65781
- if (parent !== void 0 && parent.type === require_dist10.DeviceType.Container) {
65782
- expand(parent.id);
65783
- continue;
65784
- }
65785
- ids.add(c.id);
65786
- }
65787
- } else for (const id of config.manualIds) if (byId.has(id)) expand(id);
65806
+ for (const id of config.manualIds) if (byId.has(id)) expand(id);
65788
65807
  ids.delete(selfId);
65789
65808
  return [...ids];
65790
65809
  }
65791
- function resolveTrackedEventDeviceIds(config, linkedIds) {
65792
- const raw = config[LINKED_TRACKED_IDS_CONFIG_KEY];
65793
- if (!Array.isArray(raw)) return [];
65794
- const picked = /* @__PURE__ */ new Set();
65795
- for (const v of raw) {
65796
- const n = typeof v === "number" ? v : typeof v === "string" ? Number(v) : NaN;
65797
- if (Number.isInteger(n)) picked.add(n);
65798
- }
65799
- return linkedIds.filter((id) => picked.has(id));
65800
- }
65801
- var LINK_CANDIDATE_PROJECTION = { projection: "slim" };
65802
- function findLocationInvisibleContainers(params) {
65803
- const { selfId, selfLocation, resolvedIds, candidates } = params;
65810
+ function legacyAutoLinkIds(params) {
65811
+ const { selfId, selfLocation, candidates } = params;
65804
65812
  if (selfLocation === null || selfLocation.length === 0) return [];
65813
+ const byId = new Map(candidates.map((c) => [c.id, c]));
65805
65814
  const byParent = /* @__PURE__ */ new Map();
65806
65815
  for (const c of candidates) {
65807
65816
  if (c.parentDeviceId === null) continue;
65808
- const bucket = byParent.get(c.parentDeviceId);
65809
- if (bucket) bucket.push(c);
65817
+ const siblings = byParent.get(c.parentDeviceId);
65818
+ if (siblings) siblings.push(c);
65810
65819
  else byParent.set(c.parentDeviceId, [c]);
65811
65820
  }
65812
- const out = [];
65821
+ const ids = /* @__PURE__ */ new Set();
65822
+ const expand = (id) => expandContainer(id, byId, byParent, /* @__PURE__ */ new Set(), ids);
65813
65823
  for (const c of candidates) {
65814
- if (c.type !== require_dist10.DeviceType.Container) continue;
65815
- if (c.id === selfId) continue;
65824
+ if (c.type === require_dist10.DeviceType.Container) continue;
65816
65825
  if (c.location !== selfLocation) continue;
65817
- let anyResolved = false;
65818
- let anyNullLocation = false;
65819
- let descendantCount = 0;
65820
- const visited = /* @__PURE__ */ new Set([c.id]);
65821
- let frontier = [c.id];
65822
- while (frontier.length > 0) {
65823
- const next = [];
65824
- for (const parentId of frontier) for (const child of byParent.get(parentId) ?? []) {
65825
- if (visited.has(child.id)) continue;
65826
- visited.add(child.id);
65827
- descendantCount += 1;
65828
- if (resolvedIds.has(child.id)) anyResolved = true;
65829
- if (child.location === null) anyNullLocation = true;
65830
- next.push(child.id);
65831
- }
65832
- frontier = next;
65833
- }
65834
- if (descendantCount > 0 && !anyResolved && anyNullLocation) out.push(c.id);
65826
+ if (c.parentDeviceId === selfId) continue;
65827
+ const parent = c.parentDeviceId !== null ? byId.get(c.parentDeviceId) : void 0;
65828
+ if (parent !== void 0 && parent.type === require_dist10.DeviceType.Container) {
65829
+ expand(parent.id);
65830
+ continue;
65831
+ }
65832
+ ids.add(c.id);
65835
65833
  }
65836
- return out;
65834
+ ids.delete(selfId);
65835
+ return [...ids];
65837
65836
  }
65838
- var INVISIBLE_CONTAINER_WARN_CAP = 4096;
65839
- var warnedInvisibleContainers = /* @__PURE__ */ new Set();
65840
- function warnLocationInvisibleContainers(pctx, cameraId, byId, all, resolved) {
65841
- if (resolved.mode !== "auto") return;
65842
- const selfLocation = byId.get(cameraId)?.location ?? null;
65843
- if (selfLocation === null || selfLocation.length === 0) return;
65844
- const invisible = findLocationInvisibleContainers({
65845
- selfId: cameraId,
65846
- selfLocation,
65847
- resolvedIds: new Set(resolved.devices.map((d) => d.deviceId)),
65848
- candidates: all
65849
- });
65850
- for (const containerId of invisible) {
65851
- const key = `${cameraId}:${containerId}`;
65852
- if (warnedInvisibleContainers.has(key)) continue;
65853
- if (warnedInvisibleContainers.size >= INVISIBLE_CONTAINER_WARN_CAP) return;
65854
- warnedInvisibleContainers.add(key);
65855
- pctx.host.ctx.logger.warn("getLinkedDevices: container matches the camera location but is invisible to auto-link \u2014 its children carry no location; re-save the container location to realign", {
65856
- tags: { deviceId: containerId },
65857
- meta: {
65858
- cameraId,
65859
- location: selfLocation
65860
- }
65861
- });
65837
+ function resolveTrackedEventDeviceIds(config, linkedIds) {
65838
+ const raw = config[LINKED_TRACKED_IDS_CONFIG_KEY];
65839
+ if (!Array.isArray(raw)) return [];
65840
+ const picked = /* @__PURE__ */ new Set();
65841
+ for (const v of raw) {
65842
+ const n = typeof v === "number" ? v : typeof v === "string" ? Number(v) : NaN;
65843
+ if (Number.isInteger(n)) picked.add(n);
65862
65844
  }
65845
+ return linkedIds.filter((id) => picked.has(id));
65863
65846
  }
65847
+ var LINK_CANDIDATE_PROJECTION = { projection: "slim" };
65864
65848
  function resolveFor(deviceId, all, byId, blob) {
65865
65849
  const config = parseLinkedDevicesConfig(blob);
65866
65850
  const ids = resolveLinkedDeviceIds({
65867
65851
  selfId: deviceId,
65868
- selfLocation: byId.get(deviceId)?.location ?? null,
65869
65852
  config,
65870
65853
  candidates: all
65871
65854
  });
@@ -65890,10 +65873,7 @@ var require_device_manager_addon = __commonJS({
65890
65873
  async function getLinkedDevices(pctx, input) {
65891
65874
  const { deviceId } = input;
65892
65875
  const [all, blob] = await Promise.all([listAll(pctx, LINK_CANDIDATE_PROJECTION), pctx.settings.readDeviceStore(deviceId)]);
65893
- const byId = new Map(all.map((d) => [d.id, d]));
65894
- const resolved = resolveFor(deviceId, all, byId, blob);
65895
- warnLocationInvisibleContainers(pctx, deviceId, byId, all, resolved);
65896
- return resolved;
65876
+ return resolveFor(deviceId, all, new Map(all.map((d) => [d.id, d])), blob);
65897
65877
  }
65898
65878
  async function getLinkedDevicesBatch(pctx, input) {
65899
65879
  const deviceIds = [...new Set(input.deviceIds)];
@@ -65907,11 +65887,9 @@ var require_device_manager_addon = __commonJS({
65907
65887
  })))]);
65908
65888
  const byId = new Map(all.map((d) => [d.id, d]));
65909
65889
  return deviceIds.map((deviceId, index) => {
65910
- const resolved = resolveFor(deviceId, all, byId, blobs[index] ?? {});
65911
- warnLocationInvisibleContainers(pctx, deviceId, byId, all, resolved);
65912
65890
  return {
65913
65891
  deviceId,
65914
- ...resolved
65892
+ ...resolveFor(deviceId, all, byId, blobs[index] ?? {})
65915
65893
  };
65916
65894
  });
65917
65895
  }
@@ -65920,13 +65898,9 @@ var require_device_manager_addon = __commonJS({
65920
65898
  if (!persisted || persisted.meta.type !== require_dist10.DeviceType.Camera) return null;
65921
65899
  const [all, blob] = await Promise.all([listAll(pctx, LINK_CANDIDATE_PROJECTION), pctx.settings.readDeviceStore(deviceId)]);
65922
65900
  const config = parseLinkedDevicesConfig(blob);
65923
- const options = all.filter((d) => d.id !== deviceId && d.type !== require_dist10.DeviceType.Container).map((d) => ({
65924
- value: String(d.id),
65925
- label: d.location !== null ? `${d.name} (${d.location})` : d.name
65926
- }));
65901
+ const self2 = all.find((d) => d.id === deviceId);
65927
65902
  const linkedIds = resolveLinkedDeviceIds({
65928
65903
  selfId: deviceId,
65929
- selfLocation: all.find((d) => d.id === deviceId)?.location ?? null,
65930
65904
  config,
65931
65905
  candidates: all
65932
65906
  });
@@ -65943,49 +65917,31 @@ var require_device_manager_addon = __commonJS({
65943
65917
  return { sections: [{
65944
65918
  id: "linked-devices",
65945
65919
  title: "Linked devices",
65946
- description: "Companion devices associated with this camera. Device-tree children are always linked; auto mode also links every device sharing the camera location, manual mode links the picked list instead.",
65920
+ description: "Companion devices associated with this camera. Device-tree children are always linked; everything else is the list you pick below. Devices in the same location are suggested first, never linked on their own (D356).",
65947
65921
  order: 70,
65948
- fields: [
65949
- {
65950
- type: "select",
65951
- key: LINKED_MODE_CONFIG_KEY,
65952
- label: "Link mode",
65953
- description: "Auto: children + same-location devices. Manual: children + the list below.",
65954
- options: [{
65955
- value: "auto",
65956
- label: "Auto (location-based)"
65957
- }, {
65958
- value: "manual",
65959
- label: "Manual"
65960
- }],
65961
- value: config.mode
65962
- },
65963
- {
65964
- type: "multiselect",
65965
- key: LINKED_IDS_CONFIG_KEY,
65966
- label: "Manually linked devices",
65967
- description: "Used in manual mode (children stay linked regardless).",
65968
- showWhen: {
65969
- field: LINKED_MODE_CONFIG_KEY,
65970
- equals: "manual"
65971
- },
65972
- options,
65973
- value: config.manualIds.map(String)
65922
+ fields: [{
65923
+ type: "device-multiselect",
65924
+ key: LINKED_IDS_CONFIG_KEY,
65925
+ label: "Linked devices",
65926
+ description: "Pick the companions of this camera. Same-location devices are suggested; device-tree children stay linked regardless.",
65927
+ deviceFilter: {
65928
+ excludeDeviceId: deviceId,
65929
+ excludeTypes: [require_dist10.DeviceType.Container]
65974
65930
  },
65975
- {
65976
- type: "multiselect",
65977
- key: LINKED_TRACKED_IDS_CONFIG_KEY,
65978
- label: "Devices that produce tracked events",
65979
- description: "Linked devices whose state changes materialize a synthetic tracked event on this camera. Default: none (opt-in).",
65980
- options: trackedOptions,
65981
- value: trackedValue
65982
- }
65983
- ]
65931
+ suggestLocation: self2?.location ?? null,
65932
+ value: config.manualIds.map(String)
65933
+ }, {
65934
+ type: "multiselect",
65935
+ key: LINKED_TRACKED_IDS_CONFIG_KEY,
65936
+ label: "Devices that produce tracked events",
65937
+ description: "Linked devices whose state changes materialize a synthetic tracked event on this camera. Default: none (opt-in).",
65938
+ options: trackedOptions,
65939
+ value: trackedValue
65940
+ }]
65984
65941
  }] };
65985
65942
  }
65986
65943
  async function applyLinkedDevicesPatch(pctx, deviceId, patch) {
65987
65944
  const next = { ...await pctx.settings.readDeviceStore(deviceId) };
65988
- if ("_linkedDevicesMode" in patch) next[LINKED_MODE_CONFIG_KEY] = patch["_linkedDevicesMode"] === "manual" ? "manual" : "auto";
65989
65945
  if ("_linkedDeviceIds" in patch) next[LINKED_IDS_CONFIG_KEY] = [...parseLinkedDevicesConfig({ [LINKED_IDS_CONFIG_KEY]: patch[LINKED_IDS_CONFIG_KEY] }).manualIds];
65990
65946
  if ("_linkedDeviceTrackedIds" in patch) {
65991
65947
  const raw = patch[LINKED_TRACKED_IDS_CONFIG_KEY];
@@ -66949,7 +66905,7 @@ var require_device_manager_addon = __commonJS({
66949
66905
  });
66950
66906
  }
66951
66907
  const residual = planNullLocationFills((!repaired && bootRows !== void 0 ? bootRows : await pctx.metaStore.rows.listAll()).map((r) => r.meta));
66952
- for (const [ancestorId, fills] of groupByAncestor(residual)) logger.warn("location cascade misaligned \u2014 location-less descendants under a located ancestor never match location auto-link; re-save the ancestor location to realign", {
66908
+ for (const [ancestorId, fills] of groupByAncestor(residual)) logger.warn("location cascade misaligned \u2014 location-less descendants under a located ancestor never reach the same-location suggestions of the picker; re-save the ancestor location to realign", {
66953
66909
  tags: { deviceId: ancestorId },
66954
66910
  meta: {
66955
66911
  location: fills[0]?.location,
@@ -67846,6 +67802,64 @@ var require_device_manager_addon = __commonJS({
67846
67802
  }
67847
67803
  });
67848
67804
  }
67805
+ var LINKED_MANUAL_BACKFILL_MARKER_KEY = "_linkedDevicesManualBackfillVersion";
67806
+ function planManualBackfill(params) {
67807
+ const { selfId, selfLocation, blob, candidates } = params;
67808
+ const current = parseLinkedDevicesConfig(blob).manualIds;
67809
+ if (blob["_linkedDevicesMode"] === "manual") return {
67810
+ write: false,
67811
+ manualIds: current
67812
+ };
67813
+ const merged = [...current];
67814
+ for (const id of legacyAutoLinkIds({
67815
+ selfId,
67816
+ selfLocation,
67817
+ candidates
67818
+ })) if (!merged.includes(id)) merged.push(id);
67819
+ return {
67820
+ write: true,
67821
+ manualIds: merged
67822
+ };
67823
+ }
67824
+ async function runLinkedDevicesManualBackfillAtBoot(pctx) {
67825
+ const logger = pctx.host.ctx.logger;
67826
+ const addonStore = await pctx.settings.readAddonStore();
67827
+ const markerRaw = addonStore[LINKED_MANUAL_BACKFILL_MARKER_KEY];
67828
+ if ((typeof markerRaw === "number" ? markerRaw : 0) >= 1) return;
67829
+ const all = await listAll(pctx, LINK_CANDIDATE_PROJECTION);
67830
+ let written = 0;
67831
+ let linked = 0;
67832
+ for (const cam of all) {
67833
+ if (cam.type !== require_dist10.DeviceType.Camera) continue;
67834
+ const blob = await pctx.settings.readDeviceStore(cam.id);
67835
+ const plan = planManualBackfill({
67836
+ selfId: cam.id,
67837
+ selfLocation: cam.location ?? null,
67838
+ blob,
67839
+ candidates: all
67840
+ });
67841
+ if (!plan.write) continue;
67842
+ await pctx.settings.writeDeviceStore(cam.id, {
67843
+ ...blob,
67844
+ [LINKED_MODE_CONFIG_KEY]: "manual",
67845
+ [LINKED_IDS_CONFIG_KEY]: [...plan.manualIds]
67846
+ });
67847
+ written += 1;
67848
+ linked += plan.manualIds.length;
67849
+ logger.info("linked devices: auto links materialised into the manual list (D356)", {
67850
+ tags: { deviceId: cam.id },
67851
+ meta: { manualIds: plan.manualIds }
67852
+ });
67853
+ }
67854
+ await pctx.settings.writeAddonStore({
67855
+ ...addonStore,
67856
+ [LINKED_MANUAL_BACKFILL_MARKER_KEY]: 1
67857
+ });
67858
+ logger.info("linked devices: manual backfill complete (D356)", { meta: {
67859
+ camerasWritten: written,
67860
+ linksMaterialised: linked
67861
+ } });
67862
+ }
67849
67863
  function decodeAddonStore(raw) {
67850
67864
  const nextDeviceId = raw["nextDeviceId"];
67851
67865
  const locations = raw["locations"];
@@ -69399,6 +69413,11 @@ var require_device_manager_addon = __commonJS({
69399
69413
  } catch (err) {
69400
69414
  this.ctx.logger.warn("location backfill failed \u2014 fleet boots without it", { meta: { error: require_dist10.errMsg(err) } });
69401
69415
  }
69416
+ try {
69417
+ await runLinkedDevicesManualBackfillAtBoot(pctx);
69418
+ } catch (err) {
69419
+ this.ctx.logger.warn("linked-devices manual backfill failed \u2014 auto links are NOT materialised", { meta: { error: require_dist10.errMsg(err) } });
69420
+ }
69402
69421
  const provider = {
69403
69422
  resolveDeviceOwnerSync: (deviceId) => resolveDeviceOwnerSync(pctx, deviceId),
69404
69423
  resolveNativeCapOwnerSync: (capName, deviceId) => resolveNativeCapOwnerSync(pctx, capName, deviceId),
@@ -69634,7 +69653,7 @@ var require_hub_forwarder = __commonJS({
69634
69653
  [Symbol.toStringTag]: { value: "Module" }
69635
69654
  });
69636
69655
  require_chunk_Cek0wNdY();
69637
- var require_dist10 = require_dist_DE3OH_FG();
69656
+ var require_dist10 = require_dist_DNwhsXWi();
69638
69657
  var require_formatter = require_formatter_DqAKDlvN();
69639
69658
  var DEFAULT_OUTBOUND_BUFFER_SIZE = 500;
69640
69659
  var HubForwarderDestination = class {
@@ -69771,7 +69790,7 @@ var require_liveness_monitor_addon = __commonJS({
69771
69790
  "use strict";
69772
69791
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
69773
69792
  require_chunk_Cek0wNdY();
69774
- var require_dist10 = require_dist_DE3OH_FG();
69793
+ var require_dist10 = require_dist_DNwhsXWi();
69775
69794
  var NO_DEVICES = "liveness:no-devices";
69776
69795
  var ALL_OFFLINE = "liveness:all-devices-offline";
69777
69796
  var NO_FOOTAGE_PREFIX = "liveness:no-footage:";
@@ -69961,7 +69980,7 @@ var require_local_auth_addon = __commonJS({
69961
69980
  [Symbol.toStringTag]: { value: "Module" }
69962
69981
  });
69963
69982
  var require_chunk = require_chunk_Cek0wNdY();
69964
- var require_dist10 = require_dist_DE3OH_FG();
69983
+ var require_dist10 = require_dist_DNwhsXWi();
69965
69984
  var node_crypto = __require("crypto");
69966
69985
  node_crypto = require_chunk.__toESM(node_crypto);
69967
69986
  var crypto$1 = __require("crypto");
@@ -77774,7 +77793,7 @@ var require_loki_logging = __commonJS({
77774
77793
  [Symbol.toStringTag]: { value: "Module" }
77775
77794
  });
77776
77795
  require_chunk_Cek0wNdY();
77777
- var require_dist10 = require_dist_DE3OH_FG();
77796
+ var require_dist10 = require_dist_DNwhsXWi();
77778
77797
  function sanitizeLabelName(raw) {
77779
77798
  const replaced = raw.replaceAll(/[^a-zA-Z0-9_]/g, "_");
77780
77799
  return /^[a-zA-Z_]/.test(replaced) ? replaced : `_${replaced}`;
@@ -78339,7 +78358,7 @@ var require_native_metrics_addon = __commonJS({
78339
78358
  [Symbol.toStringTag]: { value: "Module" }
78340
78359
  });
78341
78360
  var require_chunk = require_chunk_Cek0wNdY();
78342
- var require_dist10 = require_dist_DE3OH_FG();
78361
+ var require_dist10 = require_dist_DNwhsXWi();
78343
78362
  var node_fs_promises = __require("fs/promises");
78344
78363
  var node_child_process = __require("child_process");
78345
78364
  var node_util = __require("util");
@@ -80923,7 +80942,7 @@ var require_filesystem_storage_addon = __commonJS({
80923
80942
  [Symbol.toStringTag]: { value: "Module" }
80924
80943
  });
80925
80944
  var require_chunk = require_chunk_Cek0wNdY();
80926
- var require_dist10 = require_dist_DE3OH_FG();
80945
+ var require_dist10 = require_dist_DNwhsXWi();
80927
80946
  var node_crypto = __require("crypto");
80928
80947
  var node_fs_promises = __require("fs/promises");
80929
80948
  var node_path = __require("path");
@@ -82039,8 +82058,8 @@ var require_sqlite_settings_addon = __commonJS({
82039
82058
  [Symbol.toStringTag]: { value: "Module" }
82040
82059
  });
82041
82060
  var require_chunk = require_chunk_Cek0wNdY();
82042
- var require_dist10 = require_dist_DE3OH_FG();
82043
- var require_retired_settings_keys = require_retired_settings_keys_BgUS9Rr3();
82061
+ var require_dist10 = require_dist_DNwhsXWi();
82062
+ var require_retired_settings_keys = require_retired_settings_keys_CUXClAIQ();
82044
82063
  var node_crypto = __require("crypto");
82045
82064
  var node_fs = __require("fs");
82046
82065
  var node_module = __require("module");
@@ -84530,7 +84549,7 @@ var require_storage_orchestrator_addon = __commonJS({
84530
84549
  [Symbol.toStringTag]: { value: "Module" }
84531
84550
  });
84532
84551
  var require_chunk = require_chunk_Cek0wNdY();
84533
- var require_dist10 = require_dist_DE3OH_FG();
84552
+ var require_dist10 = require_dist_DNwhsXWi();
84534
84553
  var require_hub_cap_forward = require_hub_cap_forward_DmHNjbB0();
84535
84554
  var zod = require_zod();
84536
84555
  var node_crypto = __require("crypto");
@@ -87481,7 +87500,7 @@ var require_system_config_addon = __commonJS({
87481
87500
  [Symbol.toStringTag]: { value: "Module" }
87482
87501
  });
87483
87502
  require_chunk_Cek0wNdY();
87484
- var require_dist10 = require_dist_DE3OH_FG();
87503
+ var require_dist10 = require_dist_DNwhsXWi();
87485
87504
  var SECTION_TITLES = {
87486
87505
  server: "Server",
87487
87506
  auth: "Authentication"
@@ -105542,7 +105561,7 @@ var require_winston_logging = __commonJS({
105542
105561
  [Symbol.toStringTag]: { value: "Module" }
105543
105562
  });
105544
105563
  var require_chunk = require_chunk_Cek0wNdY();
105545
- var require_dist10 = require_dist_DE3OH_FG();
105564
+ var require_dist10 = require_dist_DNwhsXWi();
105546
105565
  var require_formatter = require_formatter_DqAKDlvN();
105547
105566
  var node_path = __require("path");
105548
105567
  node_path = require_chunk.__toESM(node_path);
@@ -107485,9 +107504,9 @@ var require_event_category_BaEgqJNv = __commonJS({
107485
107504
  }
107486
107505
  });
107487
107506
 
107488
- // ../types/dist/sleep-jdpPltQH.js
107489
- var require_sleep_jdpPltQH = __commonJS({
107490
- "../types/dist/sleep-jdpPltQH.js"(exports) {
107507
+ // ../types/dist/sleep-BtIF8lWc.js
107508
+ var require_sleep_BtIF8lWc = __commonJS({
107509
+ "../types/dist/sleep-BtIF8lWc.js"(exports) {
107491
107510
  "use strict";
107492
107511
  var require_event_category = require_event_category_BaEgqJNv();
107493
107512
  var zod = require_zod();
@@ -109478,6 +109497,7 @@ var require_sleep_jdpPltQH = __commonJS({
109478
109497
  DeviceRole2["GenericNotifier"] = "generic-notifier";
109479
109498
  return DeviceRole2;
109480
109499
  })({});
109500
+ var DEVICE_CHILDREN_BATCH_MAX = 256;
109481
109501
  var StaticDirOutputSchema = zod.z.object({ staticDir: zod.z.string() });
109482
109502
  var VersionOutputSchema = zod.z.object({ version: zod.z.string() });
109483
109503
  var viewerUiCapability = {
@@ -110732,6 +110752,12 @@ var require_sleep_jdpPltQH = __commonJS({
110732
110752
  return DEFAULT_RUNTIME_STATE_DURABILITY;
110733
110753
  }
110734
110754
  });
110755
+ Object.defineProperty(exports, "DEVICE_CHILDREN_BATCH_MAX", {
110756
+ enumerable: true,
110757
+ get: function() {
110758
+ return DEVICE_CHILDREN_BATCH_MAX;
110759
+ }
110760
+ });
110735
110761
  Object.defineProperty(exports, "DEVICE_SCOPED_CAPS", {
110736
110762
  enumerable: true,
110737
110763
  get: function() {
@@ -111161,7 +111187,7 @@ var require_addon = __commonJS({
111161
111187
  "use strict";
111162
111188
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
111163
111189
  var require_event_category = require_event_category_BaEgqJNv();
111164
- var require_sleep = require_sleep_jdpPltQH();
111190
+ var require_sleep = require_sleep_BtIF8lWc();
111165
111191
  var require_err_msg = require_err_msg_COpsHMw2();
111166
111192
  var CAP_INPUT_DEFAULTS = Object.freeze({
111167
111193
  "addons": { "getLogs": { "limit": 100 } },
@@ -111479,6 +111505,7 @@ var require_addon = __commonJS({
111479
111505
  exports.CAP_INPUT_DEFAULTS = CAP_INPUT_DEFAULTS;
111480
111506
  exports.COLLECTION_ARRAY_METHODS = COLLECTION_ARRAY_METHODS;
111481
111507
  exports.DATAPLANE_SECRET_HEADER = require_sleep.DATAPLANE_SECRET_HEADER;
111508
+ exports.DEVICE_CHILDREN_BATCH_MAX = require_sleep.DEVICE_CHILDREN_BATCH_MAX;
111482
111509
  exports.DEVICE_SCOPED_CAPS = require_sleep.DEVICE_SCOPED_CAPS;
111483
111510
  exports.DeviceType = require_sleep.DeviceType;
111484
111511
  exports.DisposerChain = require_sleep.DisposerChain;
@@ -118044,12 +118071,11 @@ var require_dist2 = __commonJS({
118044
118071
  }
118045
118072
  });
118046
118073
 
118047
- // ../system/dist/manifest-system-deps-DMWd5Ygf.js
118048
- var require_manifest_system_deps_DMWd5Ygf = __commonJS({
118049
- "../system/dist/manifest-system-deps-DMWd5Ygf.js"(exports) {
118074
+ // ../system/dist/manifest-system-deps-KBuTXH-y.js
118075
+ var require_manifest_system_deps_KBuTXH_y = __commonJS({
118076
+ "../system/dist/manifest-system-deps-KBuTXH-y.js"(exports) {
118050
118077
  "use strict";
118051
118078
  var require_chunk = require_chunk_Cek0wNdY();
118052
- require_dist_DE3OH_FG();
118053
118079
  require_hub_cap_forward_DmHNjbB0();
118054
118080
  var node_crypto = __require("crypto");
118055
118081
  node_crypto = require_chunk.__toESM(node_crypto);
@@ -119547,7 +119573,7 @@ var require_manifest_system_deps_DMWd5Ygf = __commonJS({
119547
119573
  return lowered.includes("not_found") || lowered.includes("no procedure") || lowered.includes("unknown method") || lowered.includes("no such method") || lowered.includes("not available");
119548
119574
  }
119549
119575
  function createChildrenBatchLoader(opts) {
119550
- const maxBatch = Math.max(1, opts.maxBatch ?? 256);
119576
+ const maxBatch = Math.max(1, opts.maxBatch ?? _camstack_types_addon.DEVICE_CHILDREN_BATCH_MAX);
119551
119577
  let pending = [];
119552
119578
  let flushScheduled = false;
119553
119579
  let flushing = false;
@@ -130116,7 +130142,7 @@ var require_dist3 = __commonJS({
130116
130142
  "use strict";
130117
130143
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
130118
130144
  var require_chunk = require_chunk_Cek0wNdY();
130119
- var require_dist10 = require_dist_DE3OH_FG();
130145
+ var require_dist10 = require_dist_DNwhsXWi();
130120
130146
  var require_builtins_alerts_alerts_addon = require_alerts_addon();
130121
130147
  require_alerts();
130122
130148
  var require_formatter = require_formatter_DqAKDlvN();
@@ -130143,7 +130169,7 @@ var require_dist3 = __commonJS({
130143
130169
  var require_builtins_winston_logging_index = require_winston_logging();
130144
130170
  var require_file_data_plane = require_file_data_plane_DO8KbxCe();
130145
130171
  var require_tls$1 = require_tls_BxQlomxd();
130146
- var require_manifest_system_deps = require_manifest_system_deps_DMWd5Ygf();
130172
+ var require_manifest_system_deps = require_manifest_system_deps_KBuTXH_y();
130147
130173
  var require_resource_monitor = require_resource_monitor_CdnzxBLP();
130148
130174
  var require_custom_action_registry = require_custom_action_registry_jY0NOZK8();
130149
130175
  var zod = require_zod();
@@ -211233,7 +211259,7 @@ var require_dist4 = __commonJS({
211233
211259
  "use strict";
211234
211260
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
211235
211261
  var require_event_category = require_event_category_BaEgqJNv();
211236
- var require_sleep = require_sleep_jdpPltQH();
211262
+ var require_sleep = require_sleep_BtIF8lWc();
211237
211263
  var require_canonical_hash = require_canonical_hash_DNV8S5ET();
211238
211264
  var require_enums2 = require_enums();
211239
211265
  var require_err_msg = require_err_msg_COpsHMw2();
@@ -218693,7 +218719,6 @@ ${recipe.triggers.map((t, i) => emitTrigger(t, i)).join("\n\n")}
218693
218719
  })
218694
218720
  }
218695
218721
  };
218696
- var DEVICE_CHILDREN_BATCH_MAX = 256;
218697
218722
  var ChildLayoutEntrySchema = zod.z.object({
218698
218723
  childKey: zod.z.string(),
218699
218724
  section: zod.z.string(),
@@ -218774,7 +218799,7 @@ ${recipe.triggers.map((t, i) => emitTrigger(t, i)).join("\n\n")}
218774
218799
  value: zod.z.unknown(),
218775
218800
  description: zod.z.string().optional()
218776
218801
  });
218777
- var LinkedDevicesModeSchema = zod.z.enum(["auto", "manual"]);
218802
+ var LinkedDevicesModeSchema = zod.z.enum(["manual"]);
218778
218803
  var LinkedDeviceSchema = zod.z.object({
218779
218804
  deviceId: zod.z.number(),
218780
218805
  name: zod.z.string(),
@@ -225111,12 +225136,28 @@ ${recipe.triggers.map((t, i) => emitTrigger(t, i)).join("\n\n")}
225111
225136
  "staging",
225112
225137
  "trained"
225113
225138
  ]);
225139
+ var MAX_TRACK_DEBUG_NOTE_LEN = 500;
225114
225140
  var TrackFlagFields = {
225115
225141
  /** Operator marked this track as training material — i.e. `retrainStatus` is
225116
225142
  * `'staging'`. */
225117
225143
  markForTrain: zod.z.boolean().optional(),
225118
225144
  /** Operator marked this track for diagnostic attention. */
225119
225145
  debug: zod.z.boolean().optional(),
225146
+ /**
225147
+ * What the operator wants CHECKED on this track, in their own words.
225148
+ *
225149
+ * The flag alone says "look at this" and nothing about what for; a debug set
225150
+ * reviewed hours later is a list of tracks with no question attached. Bound
225151
+ * to `debug` on the WRITE side — the body clears it when `debug` goes off,
225152
+ * and refuses it on a track whose debug is off — so a note can never outlive
225153
+ * the attention it belongs to.
225154
+ *
225155
+ * `''` is a real value ("marked, nothing to add"); the ABSENT key means
225156
+ * "leave whatever is stored alone", which is what lets a surface turn debug
225157
+ * on without a note (a cancelled prompt) and what lets it edit the note
225158
+ * without touching the flag.
225159
+ */
225160
+ debugNote: zod.z.string().max(500).optional(),
225120
225161
  /** Operator favourited this track. Pins it against pruning. */
225121
225162
  favourited: zod.z.boolean().optional()
225122
225163
  };
@@ -225126,6 +225167,12 @@ ${recipe.triggers.map((t, i) => emitTrigger(t, i)).join("\n\n")}
225126
225167
  trackId: zod.z.string(),
225127
225168
  markForTrain: zod.z.boolean(),
225128
225169
  debug: zod.z.boolean(),
225170
+ /** The note as it STANDS after the write — never absent here (a track with no
225171
+ * note reports `''`), for the same reason the booleans are required: a
225172
+ * surface that has just written must be able to render the note it now owns
225173
+ * without a re-fetch, and an absent key would read as "unchanged" on a
225174
+ * screen that has no previous value to keep. */
225175
+ debugNote: zod.z.string(),
225129
225176
  favourited: zod.z.boolean(),
225130
225177
  /** The lifecycle state the boolean was derived from. Required here (unlike on
225131
225178
  * a track row) because this shape is only ever produced by the write body,
@@ -226181,11 +226228,20 @@ ${recipe.triggers.map((t, i) => emitTrigger(t, i)).join("\n\n")}
226181
226228
  * staging is a deliberate action of the retrain page, which is also the only
226182
226229
  * thing that produces `trained` in the first place.
226183
226230
  *
226184
- * Returns the RESOLVED state of both flags (absent → `false`) plus the
226185
- * `retrainStatus` they were derived from, so a caller can drive its toggle
226186
- * — and render a `trained` badge — without a re-fetch. Rejects an unknown
226187
- * track, a new staging mark on a device already holding its full budget, and
226188
- * any `markForTrain` write against a trained track.
226231
+ * `debugNote` is the operator's sentence about WHAT to check on this track,
226232
+ * and it is bound to `debug`: writing `debug: false` clears it in the same
226233
+ * statement, and a note sent for a track whose debug is off (and is not
226234
+ * being turned on) is DROPPED with a warning rather than stored where
226235
+ * nothing will ever read it. An omitted `debugNote` leaves the stored one
226236
+ * alone — which is what lets a surface turn debug on when the operator
226237
+ * declined to type anything, without that refusal costing them the flag.
226238
+ *
226239
+ * Returns the RESOLVED state of all three flags (absent → `false`) plus the
226240
+ * note (absent → `''`) and the `retrainStatus` they were derived from, so a
226241
+ * caller can drive its toggle — and render a `trained` badge — without a
226242
+ * re-fetch. Rejects an unknown track, a new staging mark on a device already
226243
+ * holding its full budget, and any `markForTrain` write against a trained
226244
+ * track.
226189
226245
  */
226190
226246
  setTrackFlags: require_sleep.method(zod.z.object({
226191
226247
  /** Log/audit scope only — the trackId is globally unique on its own. */
@@ -254719,7 +254775,7 @@ ${recipe.triggers.map((t, i) => emitTrigger(t, i)).join("\n\n")}
254719
254775
  exports.DETECTION_PIPELINE_CAP_NAME = DETECTION_PIPELINE_CAP_NAME;
254720
254776
  exports.DEVICE_BACKEND_TO_FORMAT = DEVICE_BACKEND_TO_FORMAT;
254721
254777
  exports.DEVICE_CAP_NAMES = DEVICE_CAP_NAMES;
254722
- exports.DEVICE_CHILDREN_BATCH_MAX = DEVICE_CHILDREN_BATCH_MAX;
254778
+ exports.DEVICE_CHILDREN_BATCH_MAX = require_sleep.DEVICE_CHILDREN_BATCH_MAX;
254723
254779
  exports.DEVICE_PROFILES = DEVICE_PROFILES;
254724
254780
  exports.DEVICE_RESTORE_RETRY_CONCURRENCY = DEVICE_RESTORE_RETRY_CONCURRENCY;
254725
254781
  exports.DEVICE_RESTORE_RETRY_DELAYS_MS = DEVICE_RESTORE_RETRY_DELAYS_MS;
@@ -254955,6 +255011,7 @@ ${recipe.triggers.map((t, i) => emitTrigger(t, i)).join("\n\n")}
254955
255011
  exports.MAX_KEYS = MAX_KEYS;
254956
255012
  exports.MAX_REASONS_PER_KEY = MAX_REASONS_PER_KEY;
254957
255013
  exports.MAX_SENSOR_TRIGGER_DEVICES = MAX_SENSOR_TRIGGER_DEVICES;
255014
+ exports.MAX_TRACK_DEBUG_NOTE_LEN = MAX_TRACK_DEBUG_NOTE_LEN;
254958
255015
  exports.METHOD_ACCESS_MAP = METHOD_ACCESS_MAP;
254959
255016
  exports.METHOD_DEVICE_SELECTORS = METHOD_DEVICE_SELECTORS;
254960
255017
  exports.MODEL_FORMATS = MODEL_FORMATS;
@@ -424490,9 +424547,9 @@ var require_agent_registry_service = __commonJS({
424490
424547
  }
424491
424548
  return nodes.delete(nodeId) === true;
424492
424549
  }
424493
- /** Typed view of the broker's node catalog — one documented boundary cast. */
424550
+ /** Typed view of the broker's node catalog — reached through the ONE cast. */
424494
424551
  nodeCatalogRegistry() {
424495
- return this.moleculer.broker.registry;
424552
+ return this.broker.registry;
424496
424553
  }
424497
424554
  /** Typed view of the Moleculer broker — single documented cast. */
424498
424555
  get broker() {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "camstack",
3
- "version": "1.2.90",
3
+ "version": "1.2.92",
4
4
  "description": "CLI tool for managing and running CamStack server",
5
5
  "keywords": [
6
6
  "camstack",