camstack 1.2.158 → 1.2.159

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.
@@ -21031,6 +21031,19 @@ var LocationIconAssignmentSchema = external_exports.object({
21031
21031
  locationKey: external_exports.string(),
21032
21032
  icon: LocationIconIdSchema
21033
21033
  });
21034
+ var LocationDescriptionAssignmentSchema = external_exports.object({
21035
+ locationKey: external_exports.string(),
21036
+ description: external_exports.string()
21037
+ });
21038
+ var SiteZoneSchema = external_exports.object({
21039
+ zoneKey: external_exports.string(),
21040
+ label: external_exports.string(),
21041
+ icon: LocationIconIdSchema.nullable(),
21042
+ /** Folded location keys, sorted. A location listed here need not be
21043
+ * REGISTERED — devices carry labels nobody registered, and those rooms are
21044
+ * the ones that most want grouping. */
21045
+ locationKeys: external_exports.array(external_exports.string())
21046
+ });
21034
21047
  var ProviderStatusSchema = external_exports.object({
21035
21048
  connected: external_exports.boolean(),
21036
21049
  deviceCount: external_exports.number(),
@@ -21752,6 +21765,94 @@ var deviceManagerCapability = {
21752
21765
  kind: "mutation",
21753
21766
  auth: "admin"
21754
21767
  }),
21768
+ /** Every location that carries a DESCRIPTION — what the place LOOKS like,
21769
+ * in plain words, given to the vision model alongside the pictures so it
21770
+ * knows what it is looking at. A driveway of cobbles between a brick wall
21771
+ * and three parking spaces reads very differently from a back garden.
21772
+ *
21773
+ * Same additive shape and same join key as `listLocationIcons`, and that
21774
+ * is the point of it being here at all: this lived in the post-analysis
21775
+ * addon's own settings, keyed by a hand-typed label matched exactly and
21776
+ * case-sensitively, while the icon hung off the location itself. A rename
21777
+ * carried the icon and silently orphaned the description. One location,
21778
+ * one authority, one key.
21779
+ *
21780
+ * Absent means nobody wrote one — the digest then tells the model only the
21781
+ * location NAME, exactly as it did before descriptions existed. */
21782
+ listLocationDescriptions: method(external_exports.void(), external_exports.array(LocationDescriptionAssignmentSchema)),
21783
+ /** Set (or clear) a location's description. `description: null`, or a
21784
+ * blank string, removes it — an empty description and no description are
21785
+ * the same thing to every reader, and storing the first would send an
21786
+ * empty line to the model.
21787
+ *
21788
+ * Like `setLocationIcon`, the label need NOT be registered, and an
21789
+ * empty / whitespace-only LABEL throws. */
21790
+ setLocationDescription: method(external_exports.object({
21791
+ location: external_exports.string(),
21792
+ description: external_exports.string().max(400).nullable()
21793
+ }), external_exports.void(), {
21794
+ kind: "mutation",
21795
+ auth: "admin"
21796
+ }),
21797
+ /** Every SITE ZONE — a named part of the property that groups locations
21798
+ * ("Zona notte" holds the bedrooms). One call answers the whole picture:
21799
+ * key, the label as typed, the icon, and the locations inside.
21800
+ *
21801
+ * Together, because a surface that asked for membership separately could
21802
+ * draw a zone whose rooms it has not fetched — and the strip that renders
21803
+ * these puts zones BEFORE locations, so a half-known zone is the first
21804
+ * thing an operator sees.
21805
+ *
21806
+ * Nothing here touches a device: a camera's zone is derived from its
21807
+ * location, never stored on the row. Grouping rooms must not rewrite the
21808
+ * fleet. */
21809
+ listSiteZones: method(external_exports.void(), external_exports.array(SiteZoneSchema)),
21810
+ /** Create a zone, or set the icon of one that exists. `icon: null` clears
21811
+ * the icon and KEEPS the zone — a zone with no icon is a normal zone, and
21812
+ * conflating "no icon" with "no zone" would delete membership on a
21813
+ * mis-click.
21814
+ *
21815
+ * Idempotent, and the label is stored as typed: the key is folded, so
21816
+ * re-running this with different casing re-labels rather than duplicating. */
21817
+ setSiteZone: method(external_exports.object({
21818
+ name: external_exports.string(),
21819
+ icon: LocationIconIdSchema.nullable().optional()
21820
+ }), external_exports.void(), {
21821
+ kind: "mutation",
21822
+ auth: "admin"
21823
+ }),
21824
+ /** Delete a zone. Its LOCATIONS survive — they simply stop belonging to
21825
+ * anything. Deleting a grouping must never delete what was grouped. */
21826
+ removeSiteZone: method(external_exports.object({ name: external_exports.string() }), external_exports.void(), {
21827
+ kind: "mutation",
21828
+ auth: "admin"
21829
+ }),
21830
+ /** Rename a zone, carrying its icon AND its membership.
21831
+ *
21832
+ * It exists so that renaming is not delete-then-recreate, which would drop
21833
+ * both — the exact orphaning that lost a location's description when the
21834
+ * two hung off different keys. Renaming onto an existing zone MERGES into
21835
+ * it and the target keeps its own icon. */
21836
+ renameSiteZone: method(external_exports.object({
21837
+ from: external_exports.string(),
21838
+ to: external_exports.string()
21839
+ }), external_exports.void(), {
21840
+ kind: "mutation",
21841
+ auth: "admin"
21842
+ }),
21843
+ /** Put a location in a zone, or take it out with `zone: null`.
21844
+ *
21845
+ * At most one zone per location, by construction: this writes one key, so
21846
+ * there is no state in which a room is in two places at once. The zone
21847
+ * need not exist yet — it is created empty-labelled from this call, the
21848
+ * same way `setLocationIcon` does not require a registered location. */
21849
+ setLocationZone: method(external_exports.object({
21850
+ location: external_exports.string(),
21851
+ zone: external_exports.string().nullable()
21852
+ }), external_exports.void(), {
21853
+ kind: "mutation",
21854
+ auth: "admin"
21855
+ }),
21755
21856
  /** Soft-disable / re-enable the device. Drivers consult
21756
21857
  * `BaseDevice.disabled` to gate lifecycle hooks. */
21757
21858
  setDisabled: method(external_exports.object({
@@ -43020,6 +43121,12 @@ var METHOD_ACCESS_MAP = Object.freeze({
43020
43121
  addonId: null,
43021
43122
  access: "view"
43022
43123
  },
43124
+ "deviceManager.listLocationDescriptions": {
43125
+ capName: "device-manager",
43126
+ capScope: "system",
43127
+ addonId: null,
43128
+ access: "view"
43129
+ },
43023
43130
  "deviceManager.listLocationIcons": {
43024
43131
  capName: "device-manager",
43025
43132
  capScope: "system",
@@ -43038,6 +43145,12 @@ var METHOD_ACCESS_MAP = Object.freeze({
43038
43145
  addonId: null,
43039
43146
  access: "view"
43040
43147
  },
43148
+ "deviceManager.listSiteZones": {
43149
+ capName: "device-manager",
43150
+ capScope: "system",
43151
+ addonId: null,
43152
+ access: "view"
43153
+ },
43041
43154
  "deviceManager.listWrappersForCap": {
43042
43155
  capName: "device-manager",
43043
43156
  capScope: "system",
@@ -43122,12 +43235,24 @@ var METHOD_ACCESS_MAP = Object.freeze({
43122
43235
  addonId: null,
43123
43236
  access: "delete"
43124
43237
  },
43238
+ "deviceManager.removeSiteZone": {
43239
+ capName: "device-manager",
43240
+ capScope: "system",
43241
+ addonId: null,
43242
+ access: "delete"
43243
+ },
43125
43244
  "deviceManager.renameLocation": {
43126
43245
  capName: "device-manager",
43127
43246
  capScope: "system",
43128
43247
  addonId: null,
43129
43248
  access: "create"
43130
43249
  },
43250
+ "deviceManager.renameSiteZone": {
43251
+ capName: "device-manager",
43252
+ capScope: "system",
43253
+ addonId: null,
43254
+ access: "create"
43255
+ },
43131
43256
  "deviceManager.runDeviceAction": {
43132
43257
  capName: "device-manager",
43133
43258
  capScope: "system",
@@ -43170,12 +43295,24 @@ var METHOD_ACCESS_MAP = Object.freeze({
43170
43295
  addonId: null,
43171
43296
  access: "create"
43172
43297
  },
43298
+ "deviceManager.setLocationDescription": {
43299
+ capName: "device-manager",
43300
+ capScope: "system",
43301
+ addonId: null,
43302
+ access: "create"
43303
+ },
43173
43304
  "deviceManager.setLocationIcon": {
43174
43305
  capName: "device-manager",
43175
43306
  capScope: "system",
43176
43307
  addonId: null,
43177
43308
  access: "create"
43178
43309
  },
43310
+ "deviceManager.setLocationZone": {
43311
+ capName: "device-manager",
43312
+ capScope: "system",
43313
+ addonId: null,
43314
+ access: "create"
43315
+ },
43179
43316
  "deviceManager.setMetadata": {
43180
43317
  capName: "device-manager",
43181
43318
  capScope: "system",
@@ -43206,6 +43343,12 @@ var METHOD_ACCESS_MAP = Object.freeze({
43206
43343
  addonId: null,
43207
43344
  access: "create"
43208
43345
  },
43346
+ "deviceManager.setSiteZone": {
43347
+ capName: "device-manager",
43348
+ capScope: "system",
43349
+ addonId: null,
43350
+ access: "create"
43351
+ },
43209
43352
  "deviceManager.setStreamProfileMap": {
43210
43353
  capName: "device-manager",
43211
43354
  capScope: "system",
package/dist/cli.js CHANGED
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
3
  runDiscover
4
- } from "./chunk-GDVPY652.js";
4
+ } from "./chunk-VJIT6AOW.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-MMBEAJYM.js");
41
+ await import("./launcher-HOXPTYJH.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-MMBEAJYM.js");
86
+ await import("./launcher-HOXPTYJH.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-HGPO3SNF.js");
1143
+ const { discoverNodes, resolveHubFromDiscovered, filterHubNodes, DEFAULT_HUB_HTTPS_PORT } = await import("./discover-N63N6OOD.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-GDVPY652.js";
8
+ } from "./chunk-VJIT6AOW.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-D6kqBW1G.js
23637
- var require_dist_D6kqBW1G = __commonJS({
23638
- "../system/dist/dist-D6kqBW1G.js"(exports) {
23636
+ // ../system/dist/dist-Cz6h6Nc3.js
23637
+ var require_dist_Cz6h6Nc3 = __commonJS({
23638
+ "../system/dist/dist-Cz6h6Nc3.js"(exports) {
23639
23639
  "use strict";
23640
23640
  var zod = require_zod();
23641
23641
  var EventCategory = /* @__PURE__ */ (function(EventCategory2) {
@@ -31792,6 +31792,22 @@ var require_dist_D6kqBW1G = __commonJS({
31792
31792
  function locationIconKey(label) {
31793
31793
  return label.trim().toLowerCase();
31794
31794
  }
31795
+ var LocationDescriptionAssignmentSchema = zod.z.object({
31796
+ locationKey: zod.z.string(),
31797
+ description: zod.z.string()
31798
+ });
31799
+ var SiteZoneSchema = zod.z.object({
31800
+ zoneKey: zod.z.string(),
31801
+ label: zod.z.string(),
31802
+ icon: LocationIconIdSchema.nullable(),
31803
+ /** Folded location keys, sorted. A location listed here need not be
31804
+ * REGISTERED — devices carry labels nobody registered, and those rooms are
31805
+ * the ones that most want grouping. */
31806
+ locationKeys: zod.z.array(zod.z.string())
31807
+ });
31808
+ function siteZoneKey(label) {
31809
+ return label.trim().toLowerCase();
31810
+ }
31795
31811
  var ProviderStatusSchema = zod.z.object({
31796
31812
  connected: zod.z.boolean(),
31797
31813
  deviceCount: zod.z.number(),
@@ -32513,6 +32529,94 @@ var require_dist_D6kqBW1G = __commonJS({
32513
32529
  kind: "mutation",
32514
32530
  auth: "admin"
32515
32531
  }),
32532
+ /** Every location that carries a DESCRIPTION — what the place LOOKS like,
32533
+ * in plain words, given to the vision model alongside the pictures so it
32534
+ * knows what it is looking at. A driveway of cobbles between a brick wall
32535
+ * and three parking spaces reads very differently from a back garden.
32536
+ *
32537
+ * Same additive shape and same join key as `listLocationIcons`, and that
32538
+ * is the point of it being here at all: this lived in the post-analysis
32539
+ * addon's own settings, keyed by a hand-typed label matched exactly and
32540
+ * case-sensitively, while the icon hung off the location itself. A rename
32541
+ * carried the icon and silently orphaned the description. One location,
32542
+ * one authority, one key.
32543
+ *
32544
+ * Absent means nobody wrote one — the digest then tells the model only the
32545
+ * location NAME, exactly as it did before descriptions existed. */
32546
+ listLocationDescriptions: method(zod.z.void(), zod.z.array(LocationDescriptionAssignmentSchema)),
32547
+ /** Set (or clear) a location's description. `description: null`, or a
32548
+ * blank string, removes it — an empty description and no description are
32549
+ * the same thing to every reader, and storing the first would send an
32550
+ * empty line to the model.
32551
+ *
32552
+ * Like `setLocationIcon`, the label need NOT be registered, and an
32553
+ * empty / whitespace-only LABEL throws. */
32554
+ setLocationDescription: method(zod.z.object({
32555
+ location: zod.z.string(),
32556
+ description: zod.z.string().max(400).nullable()
32557
+ }), zod.z.void(), {
32558
+ kind: "mutation",
32559
+ auth: "admin"
32560
+ }),
32561
+ /** Every SITE ZONE — a named part of the property that groups locations
32562
+ * ("Zona notte" holds the bedrooms). One call answers the whole picture:
32563
+ * key, the label as typed, the icon, and the locations inside.
32564
+ *
32565
+ * Together, because a surface that asked for membership separately could
32566
+ * draw a zone whose rooms it has not fetched — and the strip that renders
32567
+ * these puts zones BEFORE locations, so a half-known zone is the first
32568
+ * thing an operator sees.
32569
+ *
32570
+ * Nothing here touches a device: a camera's zone is derived from its
32571
+ * location, never stored on the row. Grouping rooms must not rewrite the
32572
+ * fleet. */
32573
+ listSiteZones: method(zod.z.void(), zod.z.array(SiteZoneSchema)),
32574
+ /** Create a zone, or set the icon of one that exists. `icon: null` clears
32575
+ * the icon and KEEPS the zone — a zone with no icon is a normal zone, and
32576
+ * conflating "no icon" with "no zone" would delete membership on a
32577
+ * mis-click.
32578
+ *
32579
+ * Idempotent, and the label is stored as typed: the key is folded, so
32580
+ * re-running this with different casing re-labels rather than duplicating. */
32581
+ setSiteZone: method(zod.z.object({
32582
+ name: zod.z.string(),
32583
+ icon: LocationIconIdSchema.nullable().optional()
32584
+ }), zod.z.void(), {
32585
+ kind: "mutation",
32586
+ auth: "admin"
32587
+ }),
32588
+ /** Delete a zone. Its LOCATIONS survive — they simply stop belonging to
32589
+ * anything. Deleting a grouping must never delete what was grouped. */
32590
+ removeSiteZone: method(zod.z.object({ name: zod.z.string() }), zod.z.void(), {
32591
+ kind: "mutation",
32592
+ auth: "admin"
32593
+ }),
32594
+ /** Rename a zone, carrying its icon AND its membership.
32595
+ *
32596
+ * It exists so that renaming is not delete-then-recreate, which would drop
32597
+ * both — the exact orphaning that lost a location's description when the
32598
+ * two hung off different keys. Renaming onto an existing zone MERGES into
32599
+ * it and the target keeps its own icon. */
32600
+ renameSiteZone: method(zod.z.object({
32601
+ from: zod.z.string(),
32602
+ to: zod.z.string()
32603
+ }), zod.z.void(), {
32604
+ kind: "mutation",
32605
+ auth: "admin"
32606
+ }),
32607
+ /** Put a location in a zone, or take it out with `zone: null`.
32608
+ *
32609
+ * At most one zone per location, by construction: this writes one key, so
32610
+ * there is no state in which a room is in two places at once. The zone
32611
+ * need not exist yet — it is created empty-labelled from this call, the
32612
+ * same way `setLocationIcon` does not require a registered location. */
32613
+ setLocationZone: method(zod.z.object({
32614
+ location: zod.z.string(),
32615
+ zone: zod.z.string().nullable()
32616
+ }), zod.z.void(), {
32617
+ kind: "mutation",
32618
+ auth: "admin"
32619
+ }),
32516
32620
  /** Soft-disable / re-enable the device. Drivers consult
32517
32621
  * `BaseDevice.disabled` to gate lifecycle hooks. */
32518
32622
  setDisabled: method(zod.z.object({
@@ -54413,6 +54517,12 @@ var require_dist_D6kqBW1G = __commonJS({
54413
54517
  addonId: null,
54414
54518
  access: "view"
54415
54519
  },
54520
+ "deviceManager.listLocationDescriptions": {
54521
+ capName: "device-manager",
54522
+ capScope: "system",
54523
+ addonId: null,
54524
+ access: "view"
54525
+ },
54416
54526
  "deviceManager.listLocationIcons": {
54417
54527
  capName: "device-manager",
54418
54528
  capScope: "system",
@@ -54431,6 +54541,12 @@ var require_dist_D6kqBW1G = __commonJS({
54431
54541
  addonId: null,
54432
54542
  access: "view"
54433
54543
  },
54544
+ "deviceManager.listSiteZones": {
54545
+ capName: "device-manager",
54546
+ capScope: "system",
54547
+ addonId: null,
54548
+ access: "view"
54549
+ },
54434
54550
  "deviceManager.listWrappersForCap": {
54435
54551
  capName: "device-manager",
54436
54552
  capScope: "system",
@@ -54515,12 +54631,24 @@ var require_dist_D6kqBW1G = __commonJS({
54515
54631
  addonId: null,
54516
54632
  access: "delete"
54517
54633
  },
54634
+ "deviceManager.removeSiteZone": {
54635
+ capName: "device-manager",
54636
+ capScope: "system",
54637
+ addonId: null,
54638
+ access: "delete"
54639
+ },
54518
54640
  "deviceManager.renameLocation": {
54519
54641
  capName: "device-manager",
54520
54642
  capScope: "system",
54521
54643
  addonId: null,
54522
54644
  access: "create"
54523
54645
  },
54646
+ "deviceManager.renameSiteZone": {
54647
+ capName: "device-manager",
54648
+ capScope: "system",
54649
+ addonId: null,
54650
+ access: "create"
54651
+ },
54524
54652
  "deviceManager.runDeviceAction": {
54525
54653
  capName: "device-manager",
54526
54654
  capScope: "system",
@@ -54563,12 +54691,24 @@ var require_dist_D6kqBW1G = __commonJS({
54563
54691
  addonId: null,
54564
54692
  access: "create"
54565
54693
  },
54694
+ "deviceManager.setLocationDescription": {
54695
+ capName: "device-manager",
54696
+ capScope: "system",
54697
+ addonId: null,
54698
+ access: "create"
54699
+ },
54566
54700
  "deviceManager.setLocationIcon": {
54567
54701
  capName: "device-manager",
54568
54702
  capScope: "system",
54569
54703
  addonId: null,
54570
54704
  access: "create"
54571
54705
  },
54706
+ "deviceManager.setLocationZone": {
54707
+ capName: "device-manager",
54708
+ capScope: "system",
54709
+ addonId: null,
54710
+ access: "create"
54711
+ },
54572
54712
  "deviceManager.setMetadata": {
54573
54713
  capName: "device-manager",
54574
54714
  capScope: "system",
@@ -54599,6 +54739,12 @@ var require_dist_D6kqBW1G = __commonJS({
54599
54739
  addonId: null,
54600
54740
  access: "create"
54601
54741
  },
54742
+ "deviceManager.setSiteZone": {
54743
+ capName: "device-manager",
54744
+ capScope: "system",
54745
+ addonId: null,
54746
+ access: "create"
54747
+ },
54602
54748
  "deviceManager.setStreamProfileMap": {
54603
54749
  capName: "device-manager",
54604
54750
  capScope: "system",
@@ -62575,6 +62721,12 @@ var require_dist_D6kqBW1G = __commonJS({
62575
62721
  return settingsStoreCapability;
62576
62722
  }
62577
62723
  });
62724
+ Object.defineProperty(exports, "siteZoneKey", {
62725
+ enumerable: true,
62726
+ get: function() {
62727
+ return siteZoneKey;
62728
+ }
62729
+ });
62578
62730
  Object.defineProperty(exports, "sleep", {
62579
62731
  enumerable: true,
62580
62732
  get: function() {
@@ -62653,7 +62805,7 @@ var require_alerts_addon = __commonJS({
62653
62805
  [Symbol.toStringTag]: { value: "Module" }
62654
62806
  });
62655
62807
  require_chunk_Cek0wNdY();
62656
- var require_dist10 = require_dist_D6kqBW1G();
62808
+ var require_dist10 = require_dist_Cz6h6Nc3();
62657
62809
  function selectExpired(alerts, cutoffMs) {
62658
62810
  return alerts.filter((a) => a.createdAt < cutoffMs).sort((a, b) => a.createdAt - b.createdAt).map((a) => a.id);
62659
62811
  }
@@ -63472,7 +63624,7 @@ var require_console_logging = __commonJS({
63472
63624
  [Symbol.toStringTag]: { value: "Module" }
63473
63625
  });
63474
63626
  require_chunk_Cek0wNdY();
63475
- var require_dist10 = require_dist_D6kqBW1G();
63627
+ var require_dist10 = require_dist_Cz6h6Nc3();
63476
63628
  var require_formatter = require_formatter_DqAKDlvN();
63477
63629
  var LEVEL_RANK = {
63478
63630
  debug: 0,
@@ -63566,7 +63718,7 @@ var require_core_blocks_addon = __commonJS({
63566
63718
  "use strict";
63567
63719
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
63568
63720
  var require_chunk = require_chunk_Cek0wNdY();
63569
- var require_dist10 = require_dist_D6kqBW1G();
63721
+ var require_dist10 = require_dist_Cz6h6Nc3();
63570
63722
  var node_crypto = __require("crypto");
63571
63723
  var node_fs_promises = __require("fs/promises");
63572
63724
  node_fs_promises = require_chunk.__toESM(node_fs_promises);
@@ -64463,11 +64615,11 @@ var require_core_blocks = __commonJS({
64463
64615
  }
64464
64616
  });
64465
64617
 
64466
- // ../system/dist/retired-settings-keys-BPIyHR4_.js
64467
- var require_retired_settings_keys_BPIyHR4 = __commonJS({
64468
- "../system/dist/retired-settings-keys-BPIyHR4_.js"(exports) {
64618
+ // ../system/dist/retired-settings-keys-DBrIdOQp.js
64619
+ var require_retired_settings_keys_DBrIdOQp = __commonJS({
64620
+ "../system/dist/retired-settings-keys-DBrIdOQp.js"(exports) {
64469
64621
  "use strict";
64470
- var require_dist10 = require_dist_D6kqBW1G();
64622
+ var require_dist10 = require_dist_Cz6h6Nc3();
64471
64623
  function settingsStoreIsAuthoritativeHere(env) {
64472
64624
  const raw = (env["CAMSTACK_ROLE"] ?? "").trim().toLowerCase();
64473
64625
  return raw === "" || raw === "hub";
@@ -66704,8 +66856,8 @@ var require_device_manager_addon = __commonJS({
66704
66856
  [Symbol.toStringTag]: { value: "Module" }
66705
66857
  });
66706
66858
  require_chunk_Cek0wNdY();
66707
- var require_dist10 = require_dist_D6kqBW1G();
66708
- var require_retired_settings_keys = require_retired_settings_keys_BPIyHR4();
66859
+ var require_dist10 = require_dist_Cz6h6Nc3();
66860
+ var require_retired_settings_keys = require_retired_settings_keys_DBrIdOQp();
66709
66861
  var node_crypto = __require("crypto");
66710
66862
  var _camstack_types_node = require_node();
66711
66863
  var JOB_HISTORY = 20;
@@ -70457,6 +70609,164 @@ var require_device_manager_addon = __commonJS({
70457
70609
  } });
70458
70610
  });
70459
70611
  }
70612
+ async function listLocationDescriptions(pctx) {
70613
+ const descriptions = (await pctx.metaStore.readStore()).locationDescriptions ?? {};
70614
+ return Object.entries(descriptions).map(([locationKey, description]) => ({
70615
+ locationKey,
70616
+ description
70617
+ })).toSorted((a, b) => a.locationKey.localeCompare(b.locationKey));
70618
+ }
70619
+ async function setLocationDescription(pctx, input) {
70620
+ const trimmed = input.location.trim();
70621
+ if (trimmed.length === 0) throw new Error("[device-manager] setLocationDescription: location must be non-empty");
70622
+ const key = require_dist10.locationIconKey(trimmed);
70623
+ const text = input.description === null ? "" : input.description.trim();
70624
+ await pctx.bindingsDeps.withAddonStoreWriteLock(async () => {
70625
+ const descriptions = (await pctx.metaStore.readStore()).locationDescriptions ?? {};
70626
+ if (text.length === 0) {
70627
+ if (!(key in descriptions)) return;
70628
+ const { [key]: _cleared, ...kept } = descriptions;
70629
+ await pctx.settings.writeAddonStore({ locationDescriptions: kept });
70630
+ return;
70631
+ }
70632
+ if (descriptions[key] === text) return;
70633
+ await pctx.settings.writeAddonStore({ locationDescriptions: {
70634
+ ...descriptions,
70635
+ [key]: text
70636
+ } });
70637
+ });
70638
+ }
70639
+ async function listSiteZones(pctx) {
70640
+ const store = await pctx.metaStore.readStore();
70641
+ const zones = store.siteZones ?? {};
70642
+ const membership = store.locationZones ?? {};
70643
+ const rooms = /* @__PURE__ */ new Map();
70644
+ for (const [locationKey, zoneKey] of Object.entries(membership)) {
70645
+ const list = rooms.get(zoneKey);
70646
+ if (list === void 0) rooms.set(zoneKey, [locationKey]);
70647
+ else list.push(locationKey);
70648
+ }
70649
+ return Object.entries(zones).map(([zoneKey, record]) => ({
70650
+ zoneKey,
70651
+ label: record.label,
70652
+ icon: record.icon ?? null,
70653
+ locationKeys: (rooms.get(zoneKey) ?? []).toSorted((a, b) => a.localeCompare(b))
70654
+ })).toSorted((a, b) => a.zoneKey.localeCompare(b.zoneKey));
70655
+ }
70656
+ async function setSiteZone(pctx, input) {
70657
+ const label = input.name.trim();
70658
+ if (label.length === 0) throw new Error("[device-manager] setSiteZone: name must be non-empty");
70659
+ const key = require_dist10.siteZoneKey(label);
70660
+ await pctx.bindingsDeps.withAddonStoreWriteLock(async () => {
70661
+ const zones = (await pctx.metaStore.readStore()).siteZones ?? {};
70662
+ const existing = zones[key];
70663
+ const icon = input.icon === void 0 ? existing?.icon : input.icon === null ? void 0 : input.icon;
70664
+ const next = icon === void 0 ? { label } : {
70665
+ label,
70666
+ icon
70667
+ };
70668
+ if (existing?.label === next.label && existing.icon === next.icon) return;
70669
+ await pctx.settings.writeAddonStore({ siteZones: {
70670
+ ...zones,
70671
+ [key]: next
70672
+ } });
70673
+ });
70674
+ }
70675
+ async function removeSiteZone(pctx, input) {
70676
+ const key = require_dist10.siteZoneKey(input.name);
70677
+ await pctx.bindingsDeps.withAddonStoreWriteLock(async () => {
70678
+ const store = await pctx.metaStore.readStore();
70679
+ const zones = store.siteZones ?? {};
70680
+ const membership = store.locationZones ?? {};
70681
+ const hadZone = key in zones;
70682
+ const orphaned = Object.entries(membership).filter(([, zoneKey]) => zoneKey === key);
70683
+ if (!hadZone && orphaned.length === 0) return;
70684
+ const { [key]: _dropped, ...keptZones } = zones;
70685
+ const keptMembership = Object.fromEntries(Object.entries(membership).filter(([, zoneKey]) => zoneKey !== key));
70686
+ await pctx.settings.writeAddonStore({
70687
+ ...hadZone ? { siteZones: keptZones } : {},
70688
+ ...orphaned.length > 0 ? { locationZones: keptMembership } : {}
70689
+ });
70690
+ });
70691
+ }
70692
+ async function renameSiteZone(pctx, input) {
70693
+ const toLabel = input.to.trim();
70694
+ if (toLabel.length === 0) throw new Error("[device-manager] renameSiteZone: target name must be non-empty");
70695
+ const fromKey = require_dist10.siteZoneKey(input.from);
70696
+ const toKey = require_dist10.siteZoneKey(toLabel);
70697
+ await pctx.bindingsDeps.withAddonStoreWriteLock(async () => {
70698
+ const store = await pctx.metaStore.readStore();
70699
+ const zones = store.siteZones ?? {};
70700
+ const moved = zones[fromKey];
70701
+ if (moved === void 0) return;
70702
+ const { [fromKey]: _dropped, ...rest } = zones;
70703
+ const target = rest[toKey];
70704
+ const nextZones = {
70705
+ ...rest,
70706
+ [toKey]: target ?? (moved.icon === void 0 ? { label: toLabel } : {
70707
+ label: toLabel,
70708
+ icon: moved.icon
70709
+ })
70710
+ };
70711
+ const membership = store.locationZones ?? {};
70712
+ const nextMembership = Object.fromEntries(Object.entries(membership).map(([locationKey, zoneKey]) => [locationKey, zoneKey === fromKey ? toKey : zoneKey]));
70713
+ await pctx.settings.writeAddonStore({
70714
+ siteZones: nextZones,
70715
+ locationZones: nextMembership
70716
+ });
70717
+ });
70718
+ }
70719
+ async function setLocationZone(pctx, input) {
70720
+ const location = input.location.trim();
70721
+ if (location.length === 0) throw new Error("[device-manager] setLocationZone: location must be non-empty");
70722
+ const locationKey = require_dist10.locationIconKey(location);
70723
+ const label = input.zone === null ? null : input.zone.trim();
70724
+ if (label !== null && label.length === 0) throw new Error("[device-manager] setLocationZone: zone must be non-empty or null");
70725
+ await pctx.bindingsDeps.withAddonStoreWriteLock(async () => {
70726
+ const store = await pctx.metaStore.readStore();
70727
+ const membership = store.locationZones ?? {};
70728
+ if (label === null) {
70729
+ if (!(locationKey in membership)) return;
70730
+ const { [locationKey]: _cleared, ...kept } = membership;
70731
+ await pctx.settings.writeAddonStore({ locationZones: kept });
70732
+ return;
70733
+ }
70734
+ const zoneKey = require_dist10.siteZoneKey(label);
70735
+ const zones = store.siteZones ?? {};
70736
+ const needsZone = !(zoneKey in zones);
70737
+ if (membership[locationKey] === zoneKey && !needsZone) return;
70738
+ await pctx.settings.writeAddonStore({
70739
+ ...needsZone ? { siteZones: {
70740
+ ...zones,
70741
+ [zoneKey]: { label }
70742
+ } } : {},
70743
+ locationZones: {
70744
+ ...membership,
70745
+ [locationKey]: zoneKey
70746
+ }
70747
+ });
70748
+ });
70749
+ }
70750
+ function renameLocationZone(membership, fromKey, toKey) {
70751
+ const moved = membership[fromKey];
70752
+ if (moved === void 0) return null;
70753
+ if (fromKey === toKey) return null;
70754
+ const { [fromKey]: _dropped, ...rest } = membership;
70755
+ return toKey in rest ? rest : {
70756
+ ...rest,
70757
+ [toKey]: moved
70758
+ };
70759
+ }
70760
+ function renameLocationDescription(descriptions, fromKey, toKey) {
70761
+ const moved = descriptions[fromKey];
70762
+ if (moved === void 0) return null;
70763
+ if (fromKey === toKey) return null;
70764
+ const { [fromKey]: _dropped, ...rest } = descriptions;
70765
+ return toKey in rest ? rest : {
70766
+ ...rest,
70767
+ [toKey]: moved
70768
+ };
70769
+ }
70460
70770
  function renameLocationIcon(icons, fromKey, toKey) {
70461
70771
  const moved = icons[fromKey];
70462
70772
  if (moved === void 0) return null;
@@ -70479,14 +70789,18 @@ var require_device_manager_addon = __commonJS({
70479
70789
  const current = store.locations ?? [];
70480
70790
  const registered = current.some((l) => l.trim().toLowerCase() === fromKey);
70481
70791
  const movedIcons = renameLocationIcon(store.locationIcons ?? {}, fromKey, toKey);
70482
- if (!registered && movedIcons === null) return;
70792
+ const movedDescriptions = renameLocationDescription(store.locationDescriptions ?? {}, fromKey, toKey);
70793
+ const movedZones = renameLocationZone(store.locationZones ?? {}, fromKey, toKey);
70794
+ if (!registered && movedIcons === null && movedDescriptions === null && movedZones === null) return;
70483
70795
  const kept = current.filter((l) => {
70484
70796
  const key = l.trim().toLowerCase();
70485
70797
  return key !== fromKey && key !== toKey;
70486
70798
  });
70487
70799
  await pctx.settings.writeAddonStore({
70488
70800
  ...registered ? { locations: [...kept, to] } : {},
70489
- ...movedIcons !== null ? { locationIcons: movedIcons } : {}
70801
+ ...movedIcons !== null ? { locationIcons: movedIcons } : {},
70802
+ ...movedDescriptions !== null ? { locationDescriptions: movedDescriptions } : {},
70803
+ ...movedZones !== null ? { locationZones: movedZones } : {}
70490
70804
  });
70491
70805
  });
70492
70806
  const moved = await pctx.metaStore.withMetaWriteLock(async () => {
@@ -70532,11 +70846,19 @@ var require_device_manager_addon = __commonJS({
70532
70846
  const droppedLabel = remaining.length !== current.length;
70533
70847
  const icons = store.locationIcons ?? {};
70534
70848
  const droppedIcon = key in icons;
70535
- if (!droppedLabel && !droppedIcon) return;
70849
+ const descriptions = store.locationDescriptions ?? {};
70850
+ const droppedDescription = key in descriptions;
70851
+ const membership = store.locationZones ?? {};
70852
+ const droppedZone = key in membership;
70853
+ if (!droppedLabel && !droppedIcon && !droppedDescription && !droppedZone) return;
70536
70854
  const { [key]: _removedIcon, ...keptIcons } = icons;
70855
+ const { [key]: _removedDescription, ...keptDescriptions } = descriptions;
70856
+ const { [key]: _removedZone, ...keptMembership } = membership;
70537
70857
  await pctx.settings.writeAddonStore({
70538
70858
  ...droppedLabel ? { locations: remaining } : {},
70539
- ...droppedIcon ? { locationIcons: keptIcons } : {}
70859
+ ...droppedIcon ? { locationIcons: keptIcons } : {},
70860
+ ...droppedDescription ? { locationDescriptions: keptDescriptions } : {},
70861
+ ...droppedZone ? { locationZones: keptMembership } : {}
70540
70862
  });
70541
70863
  });
70542
70864
  if (input.cascade !== true) return;
@@ -70629,11 +70951,17 @@ var require_device_manager_addon = __commonJS({
70629
70951
  const locations = raw["locations"];
70630
70952
  const roleDisplayDefaults = raw["roleDisplayDefaults"];
70631
70953
  const locationIcons = decodeLocationIcons(raw["locationIcons"]);
70954
+ const locationDescriptions = decodeLocationDescriptions(raw["locationDescriptions"]);
70955
+ const siteZones = decodeSiteZones(raw["siteZones"]);
70956
+ const locationZones = decodeStringMap(raw["locationZones"]);
70632
70957
  return {
70633
70958
  ...typeof nextDeviceId === "number" && Number.isFinite(nextDeviceId) ? { nextDeviceId } : {},
70634
70959
  ...Array.isArray(locations) ? { locations: locations.filter((l) => typeof l === "string") } : {},
70635
70960
  ...isRoleDisplayDefaults(roleDisplayDefaults) ? { roleDisplayDefaults } : {},
70636
- ...locationIcons !== null ? { locationIcons } : {}
70961
+ ...locationIcons !== null ? { locationIcons } : {},
70962
+ ...locationDescriptions !== null ? { locationDescriptions } : {},
70963
+ ...siteZones !== null ? { siteZones } : {},
70964
+ ...locationZones !== null ? { locationZones } : {}
70637
70965
  };
70638
70966
  }
70639
70967
  function decodeLocationIcons(raw) {
@@ -70646,6 +70974,42 @@ var require_device_manager_addon = __commonJS({
70646
70974
  }
70647
70975
  return out;
70648
70976
  }
70977
+ function decodeLocationDescriptions(raw) {
70978
+ if (raw === null || typeof raw !== "object" || Array.isArray(raw)) return null;
70979
+ const out = {};
70980
+ for (const [key, value] of Object.entries(raw)) {
70981
+ if (typeof value !== "string") continue;
70982
+ const text = value.trim();
70983
+ if (text.length === 0) continue;
70984
+ out[key] = text.slice(0, 400);
70985
+ }
70986
+ return out;
70987
+ }
70988
+ function decodeSiteZones(raw) {
70989
+ if (raw === null || typeof raw !== "object" || Array.isArray(raw)) return null;
70990
+ const out = {};
70991
+ for (const [key, value] of Object.entries(raw)) {
70992
+ if (value === null || typeof value !== "object" || Array.isArray(value)) continue;
70993
+ const rec = value;
70994
+ const label = typeof rec["label"] === "string" ? rec["label"].trim() : "";
70995
+ if (label.length === 0) continue;
70996
+ const icon = require_dist10.LocationIconIdSchema.safeParse(rec["icon"]);
70997
+ out[key] = icon.success ? {
70998
+ label,
70999
+ icon: icon.data
71000
+ } : { label };
71001
+ }
71002
+ return out;
71003
+ }
71004
+ function decodeStringMap(raw) {
71005
+ if (raw === null || typeof raw !== "object" || Array.isArray(raw)) return null;
71006
+ const out = {};
71007
+ for (const [key, value] of Object.entries(raw)) {
71008
+ if (typeof value !== "string" || value.trim().length === 0) continue;
71009
+ out[key] = value;
71010
+ }
71011
+ return out;
71012
+ }
70649
71013
  function isRoleDisplayDefaults(value) {
70650
71014
  return value !== null && typeof value === "object" && !Array.isArray(value);
70651
71015
  }
@@ -72288,6 +72652,13 @@ var require_device_manager_addon = __commonJS({
72288
72652
  renameLocation: (input) => renameLocation(pctx, input),
72289
72653
  listLocationIcons: () => listLocationIcons(pctx),
72290
72654
  setLocationIcon: (input) => setLocationIcon(pctx, input),
72655
+ listLocationDescriptions: () => listLocationDescriptions(pctx),
72656
+ setLocationDescription: (input) => setLocationDescription(pctx, input),
72657
+ listSiteZones: () => listSiteZones(pctx),
72658
+ setSiteZone: (input) => setSiteZone(pctx, input),
72659
+ removeSiteZone: (input) => removeSiteZone(pctx, input),
72660
+ renameSiteZone: (input) => renameSiteZone(pctx, input),
72661
+ setLocationZone: (input) => setLocationZone(pctx, input),
72291
72662
  listPersistedByAddon: (input) => listPersistedByAddon(pctx, input),
72292
72663
  listAll: (input) => listAll(pctx, input),
72293
72664
  getDevice: (input) => getDevice(pctx, input),
@@ -72494,7 +72865,7 @@ var require_hub_forwarder = __commonJS({
72494
72865
  [Symbol.toStringTag]: { value: "Module" }
72495
72866
  });
72496
72867
  require_chunk_Cek0wNdY();
72497
- var require_dist10 = require_dist_D6kqBW1G();
72868
+ var require_dist10 = require_dist_Cz6h6Nc3();
72498
72869
  var require_formatter = require_formatter_DqAKDlvN();
72499
72870
  var DEFAULT_OUTBOUND_BUFFER_SIZE = 500;
72500
72871
  var HubForwarderDestination = class {
@@ -72631,7 +73002,7 @@ var require_liveness_monitor_addon = __commonJS({
72631
73002
  "use strict";
72632
73003
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
72633
73004
  require_chunk_Cek0wNdY();
72634
- var require_dist10 = require_dist_D6kqBW1G();
73005
+ var require_dist10 = require_dist_Cz6h6Nc3();
72635
73006
  var NO_DEVICES = "liveness:no-devices";
72636
73007
  var ALL_OFFLINE = "liveness:all-devices-offline";
72637
73008
  var NO_FOOTAGE_PREFIX = "liveness:no-footage:";
@@ -72827,7 +73198,7 @@ var require_local_auth_addon = __commonJS({
72827
73198
  [Symbol.toStringTag]: { value: "Module" }
72828
73199
  });
72829
73200
  var require_chunk = require_chunk_Cek0wNdY();
72830
- var require_dist10 = require_dist_D6kqBW1G();
73201
+ var require_dist10 = require_dist_Cz6h6Nc3();
72831
73202
  var node_crypto = __require("crypto");
72832
73203
  node_crypto = require_chunk.__toESM(node_crypto);
72833
73204
  var crypto$1 = __require("crypto");
@@ -80640,7 +81011,7 @@ var require_loki_logging = __commonJS({
80640
81011
  [Symbol.toStringTag]: { value: "Module" }
80641
81012
  });
80642
81013
  require_chunk_Cek0wNdY();
80643
- var require_dist10 = require_dist_D6kqBW1G();
81014
+ var require_dist10 = require_dist_Cz6h6Nc3();
80644
81015
  function sanitizeLabelName(raw) {
80645
81016
  const replaced = raw.replaceAll(/[^a-zA-Z0-9_]/g, "_");
80646
81017
  return /^[a-zA-Z_]/.test(replaced) ? replaced : `_${replaced}`;
@@ -81227,7 +81598,7 @@ var require_native_metrics_addon = __commonJS({
81227
81598
  [Symbol.toStringTag]: { value: "Module" }
81228
81599
  });
81229
81600
  var require_chunk = require_chunk_Cek0wNdY();
81230
- var require_dist10 = require_dist_D6kqBW1G();
81601
+ var require_dist10 = require_dist_Cz6h6Nc3();
81231
81602
  var node_fs_promises = __require("fs/promises");
81232
81603
  var node_fs = __require("fs");
81233
81604
  node_fs = require_chunk.__toESM(node_fs);
@@ -83980,7 +84351,7 @@ var require_filesystem_storage_addon = __commonJS({
83980
84351
  [Symbol.toStringTag]: { value: "Module" }
83981
84352
  });
83982
84353
  var require_chunk = require_chunk_Cek0wNdY();
83983
- var require_dist10 = require_dist_D6kqBW1G();
84354
+ var require_dist10 = require_dist_Cz6h6Nc3();
83984
84355
  var node_crypto = __require("crypto");
83985
84356
  var node_fs_promises = __require("fs/promises");
83986
84357
  var node_path = __require("path");
@@ -85207,8 +85578,8 @@ var require_sqlite_settings_addon = __commonJS({
85207
85578
  [Symbol.toStringTag]: { value: "Module" }
85208
85579
  });
85209
85580
  var require_chunk = require_chunk_Cek0wNdY();
85210
- var require_dist10 = require_dist_D6kqBW1G();
85211
- var require_retired_settings_keys = require_retired_settings_keys_BPIyHR4();
85581
+ var require_dist10 = require_dist_Cz6h6Nc3();
85582
+ var require_retired_settings_keys = require_retired_settings_keys_DBrIdOQp();
85212
85583
  var require_wal_checkpoint_policy = require_wal_checkpoint_policy_CCJZngds();
85213
85584
  var node_crypto = __require("crypto");
85214
85585
  var node_path = __require("path");
@@ -87995,7 +88366,7 @@ var require_storage_orchestrator_addon = __commonJS({
87995
88366
  [Symbol.toStringTag]: { value: "Module" }
87996
88367
  });
87997
88368
  var require_chunk = require_chunk_Cek0wNdY();
87998
- var require_dist10 = require_dist_D6kqBW1G();
88369
+ var require_dist10 = require_dist_Cz6h6Nc3();
87999
88370
  var require_hub_cap_forward = require_hub_cap_forward_DmHNjbB0();
88000
88371
  var zod = require_zod();
88001
88372
  var node_crypto = __require("crypto");
@@ -91722,7 +92093,7 @@ var require_system_config_addon = __commonJS({
91722
92093
  [Symbol.toStringTag]: { value: "Module" }
91723
92094
  });
91724
92095
  require_chunk_Cek0wNdY();
91725
- var require_dist10 = require_dist_D6kqBW1G();
92096
+ var require_dist10 = require_dist_Cz6h6Nc3();
91726
92097
  var SECTION_TITLES = {
91727
92098
  server: "Server",
91728
92099
  auth: "Authentication"
@@ -109783,7 +110154,7 @@ var require_winston_logging = __commonJS({
109783
110154
  [Symbol.toStringTag]: { value: "Module" }
109784
110155
  });
109785
110156
  var require_chunk = require_chunk_Cek0wNdY();
109786
- var require_dist10 = require_dist_D6kqBW1G();
110157
+ var require_dist10 = require_dist_Cz6h6Nc3();
109787
110158
  var require_formatter = require_formatter_DqAKDlvN();
109788
110159
  var node_path = __require("path");
109789
110160
  node_path = require_chunk.__toESM(node_path);
@@ -136050,7 +136421,7 @@ var require_dist3 = __commonJS({
136050
136421
  "use strict";
136051
136422
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
136052
136423
  var require_chunk = require_chunk_Cek0wNdY();
136053
- var require_dist10 = require_dist_D6kqBW1G();
136424
+ var require_dist10 = require_dist_Cz6h6Nc3();
136054
136425
  var require_builtins_alerts_alerts_addon = require_alerts_addon();
136055
136426
  require_alerts();
136056
136427
  var require_formatter = require_formatter_DqAKDlvN();
@@ -225336,6 +225707,23 @@ ${recipe.triggers.map((t, i) => emitTrigger(t, i)).join("\n\n")}
225336
225707
  const parsed = LocationIconIdSchema.safeParse(value);
225337
225708
  return parsed.success ? parsed.data : LOCATION_ICON_FALLBACK;
225338
225709
  }
225710
+ var LOCATION_DESCRIPTION_MAX = 400;
225711
+ var LocationDescriptionAssignmentSchema = zod.z.object({
225712
+ locationKey: zod.z.string(),
225713
+ description: zod.z.string()
225714
+ });
225715
+ var SiteZoneSchema = zod.z.object({
225716
+ zoneKey: zod.z.string(),
225717
+ label: zod.z.string(),
225718
+ icon: LocationIconIdSchema.nullable(),
225719
+ /** Folded location keys, sorted. A location listed here need not be
225720
+ * REGISTERED — devices carry labels nobody registered, and those rooms are
225721
+ * the ones that most want grouping. */
225722
+ locationKeys: zod.z.array(zod.z.string())
225723
+ });
225724
+ function siteZoneKey(label) {
225725
+ return label.trim().toLowerCase();
225726
+ }
225339
225727
  var ProviderStatusSchema = zod.z.object({
225340
225728
  connected: zod.z.boolean(),
225341
225729
  deviceCount: zod.z.number(),
@@ -226057,6 +226445,94 @@ ${recipe.triggers.map((t, i) => emitTrigger(t, i)).join("\n\n")}
226057
226445
  kind: "mutation",
226058
226446
  auth: "admin"
226059
226447
  }),
226448
+ /** Every location that carries a DESCRIPTION — what the place LOOKS like,
226449
+ * in plain words, given to the vision model alongside the pictures so it
226450
+ * knows what it is looking at. A driveway of cobbles between a brick wall
226451
+ * and three parking spaces reads very differently from a back garden.
226452
+ *
226453
+ * Same additive shape and same join key as `listLocationIcons`, and that
226454
+ * is the point of it being here at all: this lived in the post-analysis
226455
+ * addon's own settings, keyed by a hand-typed label matched exactly and
226456
+ * case-sensitively, while the icon hung off the location itself. A rename
226457
+ * carried the icon and silently orphaned the description. One location,
226458
+ * one authority, one key.
226459
+ *
226460
+ * Absent means nobody wrote one — the digest then tells the model only the
226461
+ * location NAME, exactly as it did before descriptions existed. */
226462
+ listLocationDescriptions: require_sleep.method(zod.z.void(), zod.z.array(LocationDescriptionAssignmentSchema)),
226463
+ /** Set (or clear) a location's description. `description: null`, or a
226464
+ * blank string, removes it — an empty description and no description are
226465
+ * the same thing to every reader, and storing the first would send an
226466
+ * empty line to the model.
226467
+ *
226468
+ * Like `setLocationIcon`, the label need NOT be registered, and an
226469
+ * empty / whitespace-only LABEL throws. */
226470
+ setLocationDescription: require_sleep.method(zod.z.object({
226471
+ location: zod.z.string(),
226472
+ description: zod.z.string().max(400).nullable()
226473
+ }), zod.z.void(), {
226474
+ kind: "mutation",
226475
+ auth: "admin"
226476
+ }),
226477
+ /** Every SITE ZONE — a named part of the property that groups locations
226478
+ * ("Zona notte" holds the bedrooms). One call answers the whole picture:
226479
+ * key, the label as typed, the icon, and the locations inside.
226480
+ *
226481
+ * Together, because a surface that asked for membership separately could
226482
+ * draw a zone whose rooms it has not fetched — and the strip that renders
226483
+ * these puts zones BEFORE locations, so a half-known zone is the first
226484
+ * thing an operator sees.
226485
+ *
226486
+ * Nothing here touches a device: a camera's zone is derived from its
226487
+ * location, never stored on the row. Grouping rooms must not rewrite the
226488
+ * fleet. */
226489
+ listSiteZones: require_sleep.method(zod.z.void(), zod.z.array(SiteZoneSchema)),
226490
+ /** Create a zone, or set the icon of one that exists. `icon: null` clears
226491
+ * the icon and KEEPS the zone — a zone with no icon is a normal zone, and
226492
+ * conflating "no icon" with "no zone" would delete membership on a
226493
+ * mis-click.
226494
+ *
226495
+ * Idempotent, and the label is stored as typed: the key is folded, so
226496
+ * re-running this with different casing re-labels rather than duplicating. */
226497
+ setSiteZone: require_sleep.method(zod.z.object({
226498
+ name: zod.z.string(),
226499
+ icon: LocationIconIdSchema.nullable().optional()
226500
+ }), zod.z.void(), {
226501
+ kind: "mutation",
226502
+ auth: "admin"
226503
+ }),
226504
+ /** Delete a zone. Its LOCATIONS survive — they simply stop belonging to
226505
+ * anything. Deleting a grouping must never delete what was grouped. */
226506
+ removeSiteZone: require_sleep.method(zod.z.object({ name: zod.z.string() }), zod.z.void(), {
226507
+ kind: "mutation",
226508
+ auth: "admin"
226509
+ }),
226510
+ /** Rename a zone, carrying its icon AND its membership.
226511
+ *
226512
+ * It exists so that renaming is not delete-then-recreate, which would drop
226513
+ * both — the exact orphaning that lost a location's description when the
226514
+ * two hung off different keys. Renaming onto an existing zone MERGES into
226515
+ * it and the target keeps its own icon. */
226516
+ renameSiteZone: require_sleep.method(zod.z.object({
226517
+ from: zod.z.string(),
226518
+ to: zod.z.string()
226519
+ }), zod.z.void(), {
226520
+ kind: "mutation",
226521
+ auth: "admin"
226522
+ }),
226523
+ /** Put a location in a zone, or take it out with `zone: null`.
226524
+ *
226525
+ * At most one zone per location, by construction: this writes one key, so
226526
+ * there is no state in which a room is in two places at once. The zone
226527
+ * need not exist yet — it is created empty-labelled from this call, the
226528
+ * same way `setLocationIcon` does not require a registered location. */
226529
+ setLocationZone: require_sleep.method(zod.z.object({
226530
+ location: zod.z.string(),
226531
+ zone: zod.z.string().nullable()
226532
+ }), zod.z.void(), {
226533
+ kind: "mutation",
226534
+ auth: "admin"
226535
+ }),
226060
226536
  /** Soft-disable / re-enable the device. Drivers consult
226061
226537
  * `BaseDevice.disabled` to gate lifecycle hooks. */
226062
226538
  setDisabled: require_sleep.method(zod.z.object({
@@ -252534,6 +253010,12 @@ ${recipe.triggers.map((t, i) => emitTrigger(t, i)).join("\n\n")}
252534
253010
  addonId: null,
252535
253011
  access: "view"
252536
253012
  },
253013
+ "deviceManager.listLocationDescriptions": {
253014
+ capName: "device-manager",
253015
+ capScope: "system",
253016
+ addonId: null,
253017
+ access: "view"
253018
+ },
252537
253019
  "deviceManager.listLocationIcons": {
252538
253020
  capName: "device-manager",
252539
253021
  capScope: "system",
@@ -252552,6 +253034,12 @@ ${recipe.triggers.map((t, i) => emitTrigger(t, i)).join("\n\n")}
252552
253034
  addonId: null,
252553
253035
  access: "view"
252554
253036
  },
253037
+ "deviceManager.listSiteZones": {
253038
+ capName: "device-manager",
253039
+ capScope: "system",
253040
+ addonId: null,
253041
+ access: "view"
253042
+ },
252555
253043
  "deviceManager.listWrappersForCap": {
252556
253044
  capName: "device-manager",
252557
253045
  capScope: "system",
@@ -252636,12 +253124,24 @@ ${recipe.triggers.map((t, i) => emitTrigger(t, i)).join("\n\n")}
252636
253124
  addonId: null,
252637
253125
  access: "delete"
252638
253126
  },
253127
+ "deviceManager.removeSiteZone": {
253128
+ capName: "device-manager",
253129
+ capScope: "system",
253130
+ addonId: null,
253131
+ access: "delete"
253132
+ },
252639
253133
  "deviceManager.renameLocation": {
252640
253134
  capName: "device-manager",
252641
253135
  capScope: "system",
252642
253136
  addonId: null,
252643
253137
  access: "create"
252644
253138
  },
253139
+ "deviceManager.renameSiteZone": {
253140
+ capName: "device-manager",
253141
+ capScope: "system",
253142
+ addonId: null,
253143
+ access: "create"
253144
+ },
252645
253145
  "deviceManager.runDeviceAction": {
252646
253146
  capName: "device-manager",
252647
253147
  capScope: "system",
@@ -252684,12 +253184,24 @@ ${recipe.triggers.map((t, i) => emitTrigger(t, i)).join("\n\n")}
252684
253184
  addonId: null,
252685
253185
  access: "create"
252686
253186
  },
253187
+ "deviceManager.setLocationDescription": {
253188
+ capName: "device-manager",
253189
+ capScope: "system",
253190
+ addonId: null,
253191
+ access: "create"
253192
+ },
252687
253193
  "deviceManager.setLocationIcon": {
252688
253194
  capName: "device-manager",
252689
253195
  capScope: "system",
252690
253196
  addonId: null,
252691
253197
  access: "create"
252692
253198
  },
253199
+ "deviceManager.setLocationZone": {
253200
+ capName: "device-manager",
253201
+ capScope: "system",
253202
+ addonId: null,
253203
+ access: "create"
253204
+ },
252693
253205
  "deviceManager.setMetadata": {
252694
253206
  capName: "device-manager",
252695
253207
  capScope: "system",
@@ -252720,6 +253232,12 @@ ${recipe.triggers.map((t, i) => emitTrigger(t, i)).join("\n\n")}
252720
253232
  addonId: null,
252721
253233
  access: "create"
252722
253234
  },
253235
+ "deviceManager.setSiteZone": {
253236
+ capName: "device-manager",
253237
+ capScope: "system",
253238
+ addonId: null,
253239
+ access: "create"
253240
+ },
252723
253241
  "deviceManager.setStreamProfileMap": {
252724
253242
  capName: "device-manager",
252725
253243
  capScope: "system",
@@ -260258,6 +260776,13 @@ ${recipe.triggers.map((t, i) => emitTrigger(t, i)).join("\n\n")}
260258
260776
  renameLocation: (input) => dispatch("deviceManager", "renameLocation", "mutation", input),
260259
260777
  listLocationIcons: (input) => dispatch("deviceManager", "listLocationIcons", "query", input),
260260
260778
  setLocationIcon: (input) => dispatch("deviceManager", "setLocationIcon", "mutation", input),
260779
+ listLocationDescriptions: (input) => dispatch("deviceManager", "listLocationDescriptions", "query", input),
260780
+ setLocationDescription: (input) => dispatch("deviceManager", "setLocationDescription", "mutation", input),
260781
+ listSiteZones: (input) => dispatch("deviceManager", "listSiteZones", "query", input),
260782
+ setSiteZone: (input) => dispatch("deviceManager", "setSiteZone", "mutation", input),
260783
+ removeSiteZone: (input) => dispatch("deviceManager", "removeSiteZone", "mutation", input),
260784
+ renameSiteZone: (input) => dispatch("deviceManager", "renameSiteZone", "mutation", input),
260785
+ setLocationZone: (input) => dispatch("deviceManager", "setLocationZone", "mutation", input),
260261
260786
  listPersistedByAddon: (input) => dispatch("deviceManager", "listPersistedByAddon", "query", input),
260262
260787
  listAll: (input) => dispatch("deviceManager", "listAll", "query", input),
260263
260788
  getChildren: (input) => dispatch("deviceManager", "getChildren", "query", input),
@@ -263805,6 +264330,7 @@ ${recipe.triggers.map((t, i) => emitTrigger(t, i)).join("\n\n")}
263805
264330
  exports.LEGACY_READ_ONLY_CONFIG_KEY = LEGACY_READ_ONLY_CONFIG_KEY;
263806
264331
  exports.LOAD_CONTRIBUTION_ATTRIBUTIONS = LOAD_CONTRIBUTION_ATTRIBUTIONS;
263807
264332
  exports.LOAD_CONTRIBUTION_ROLES = LOAD_CONTRIBUTION_ROLES;
264333
+ exports.LOCATION_DESCRIPTION_MAX = LOCATION_DESCRIPTION_MAX;
263808
264334
  exports.LOCATION_ICON_FALLBACK = LOCATION_ICON_FALLBACK;
263809
264335
  exports.LOCATION_ICON_IDS = LOCATION_ICON_IDS;
263810
264336
  exports.LOG_CHANNEL_TICK_MS = LOG_CHANNEL_TICK_MS;
@@ -263847,6 +264373,7 @@ ${recipe.triggers.map((t, i) => emitTrigger(t, i)).join("\n\n")}
263847
264373
  exports.LlmUsageSchema = LlmUsageSchema;
263848
264374
  exports.LoadContributionSchema = LoadContributionSchema;
263849
264375
  exports.LocateSegmentResultSchema = LocateSegmentResultSchema;
264376
+ exports.LocationDescriptionAssignmentSchema = LocationDescriptionAssignmentSchema;
263850
264377
  exports.LocationIconAssignmentSchema = LocationIconAssignmentSchema;
263851
264378
  exports.LocationIconIdSchema = LocationIconIdSchema;
263852
264379
  exports.LocationStatSchema = LocationStatSchema;
@@ -264324,6 +264851,7 @@ ${recipe.triggers.map((t, i) => emitTrigger(t, i)).join("\n\n")}
264324
264851
  exports.SiteLocationSchema = SiteLocationSchema;
264325
264852
  exports.SiteLocationSourceSchema = SiteLocationSourceSchema;
264326
264853
  exports.SiteLocationStatusSchema = SiteLocationStatusSchema;
264854
+ exports.SiteZoneSchema = SiteZoneSchema;
264327
264855
  exports.SmokeStatusSchema = SmokeStatusSchema;
264328
264856
  exports.SmtpStatusSchema = SmtpStatusSchema;
264329
264857
  exports.SnapshotImageSchema = SnapshotImageSchema;
@@ -264908,6 +265436,7 @@ ${recipe.triggers.map((t, i) => emitTrigger(t, i)).join("\n\n")}
264908
265436
  exports.settingsStoreCapability = settingsStoreCapability;
264909
265437
  exports.signalPercentFromBars = signalPercentFromBars;
264910
265438
  exports.signalPercentFromRssi = signalPercentFromRssi;
265439
+ exports.siteZoneKey = siteZoneKey;
264911
265440
  exports.sleep = require_sleep.sleep;
264912
265441
  exports.sleepCancellable = require_sleep.sleepCancellable;
264913
265442
  exports.sliceActiveValue = sliceActiveValue;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "camstack",
3
- "version": "1.2.158",
3
+ "version": "1.2.159",
4
4
  "description": "CLI tool for managing and running CamStack server",
5
5
  "keywords": [
6
6
  "camstack",