@camstack/types 1.2.300 → 1.2.303

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.
package/dist/index.js CHANGED
@@ -1,5 +1,5 @@
1
1
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
- const require_sleep = require("./sleep-G4F3X9X_.js");
2
+ const require_sleep = require("./sleep-C3gDpn7G.js");
3
3
  const require_event_category = require("./event-category-DmS_tLsU.js");
4
4
  const require_composition = require("./composition-BLWAivB2.js");
5
5
  const require_err_msg = require("./err-msg-Dx2Kor0g.js");
@@ -6008,7 +6008,16 @@ var AutomationActionSchema = zod.z.discriminatedUnion("kind", [
6008
6008
  }),
6009
6009
  zod.z.object({
6010
6010
  kind: zod.z.literal("cap"),
6011
- deviceId: zod.z.union([zod.z.number().int(), zod.z.object({ $var: zod.z.string().min(1) })]),
6011
+ /**
6012
+ * One device, several same-family devices (locks / climate family / …),
6013
+ * or `{ $var }` for the device that triggered the run. An array is
6014
+ * fan-out at codegen — each id gets the same cap.method call.
6015
+ */
6016
+ deviceId: zod.z.union([
6017
+ zod.z.number().int(),
6018
+ zod.z.array(zod.z.number().int()).min(1),
6019
+ zod.z.object({ $var: zod.z.string().min(1) })
6020
+ ]),
6012
6021
  cap: zod.z.string().min(1),
6013
6022
  method: zod.z.string().min(1),
6014
6023
  /** Values may carry `{{vars.x}}` slots, which SUBSTITUTE and do not
@@ -6171,7 +6180,14 @@ function emitTrigger(trigger, index) {
6171
6180
  function emitAction(action, index) {
6172
6181
  switch (action.kind) {
6173
6182
  case "wait": return ` case ${index}: await sleep(${j(action.seconds * 1e3)}); break`;
6174
- case "cap": return ` case ${index}: {
6183
+ case "cap":
6184
+ if (Array.isArray(action.deviceId)) return ` case ${index}: {
6185
+ for (const deviceId of ${j(action.deviceId)}) {
6186
+ await actuate(deviceId, ${j(action.cap)}, ${j(action.method)}, ${j(action.args ?? {})}, vars)
6187
+ }
6188
+ break
6189
+ }`;
6190
+ return ` case ${index}: {
6175
6191
  const deviceId = ${typeof action.deviceId === "number" ? j(action.deviceId) : `resolveTarget(vars, ${j(action.deviceId.$var)})`}
6176
6192
  await actuate(deviceId, ${j(action.cap)}, ${j(action.method)}, ${j(action.args ?? {})}, vars)
6177
6193
  break
@@ -6405,11 +6421,13 @@ export default function block(ctx: AddonContext) {
6405
6421
  ): Promise<void> {
6406
6422
  const resolved: Record<string, unknown> = {}
6407
6423
  for (const [k, v] of Object.entries(args)) resolved[k] = substitute(v, vars)
6424
+ // Forked-addon ctx.api namespaces are tRPC Proxies over a noop function
6425
+ // (typeof === 'function'), not plain objects — reject only null/undefined.
6408
6426
  const client: unknown = Reflect.get(ctx.api, capToRouterKey(cap))
6409
6427
  const proc: unknown =
6410
- typeof client === 'object' && client !== null ? Reflect.get(client, method) : undefined
6428
+ client !== null && client !== undefined ? Reflect.get(client as object, method) : undefined
6411
6429
  const mutate: unknown =
6412
- typeof proc === 'object' && proc !== null ? Reflect.get(proc, 'mutate') : undefined
6430
+ proc !== null && proc !== undefined ? Reflect.get(proc as object, 'mutate') : undefined
6413
6431
  if (typeof mutate !== 'function') {
6414
6432
  throw new Error('no such device method: ' + cap + '.' + method)
6415
6433
  }
@@ -12441,7 +12459,7 @@ var detectionPipelineCapability = {
12441
12459
  * This matters here more than anywhere else in the repo, because every provider
12442
12460
  * that knows a device's host knows its PASSWORD too: `{ host, port, username,
12443
12461
  * password }` sit in one object on Hikvision, Amcrest, Reolink and ONVIF alike,
12444
- * and `http://admin:hunter2@192.168.50.139/` is a URL a browser accepts. The
12462
+ * and `http://admin:hunter2@192.168.x.x/` is a URL a browser accepts. The
12445
12463
  * camera's own page will ask for its own login. That is correct, and pre-
12446
12464
  * filling it is the operator's business, not ours.
12447
12465
  *
@@ -17904,6 +17922,17 @@ var SendResultSchema = zod.z.object({
17904
17922
  });
17905
17923
  /** Same shape as SendResult — kept as a distinct name for the test panel. */
17906
17924
  var TestResultSchema = SendResultSchema;
17925
+ /**
17926
+ * Pre-save credential probe against a partial (unsaved) target config.
17927
+ * `resolvedUrl` never includes secrets (token stripped from path).
17928
+ */
17929
+ var ProbeTargetConfigResultSchema = zod.z.object({
17930
+ ok: zod.z.boolean(),
17931
+ resolvedUrl: zod.z.string(),
17932
+ httpStatus: zod.z.number().int().optional(),
17933
+ stateInstance: zod.z.string().optional(),
17934
+ error: zod.z.string().optional()
17935
+ });
17907
17936
  var notificationOutputCapability = {
17908
17937
  name: "notification-output",
17909
17938
  scope: "system",
@@ -17911,10 +17940,32 @@ var notificationOutputCapability = {
17911
17940
  methods: {
17912
17941
  listTargetKinds: require_sleep.method(zod.z.object({}), zod.z.array(TargetKindSchema)),
17913
17942
  listTargets: require_sleep.method(zod.z.object({}), zod.z.array(TargetSchema), { auth: "admin" }),
17943
+ /**
17944
+ * One target WITH secrets — admin edit / duplicate hydration only.
17945
+ * `listTargets` stays redacted; the editor loads this so password fields
17946
+ * are filled (masked in the input) and a save can round-trip the token
17947
+ * when a destination changes (Duplicate with a new chatId, etc.).
17948
+ */
17949
+ getTarget: require_sleep.method(zod.z.object({ targetId: zod.z.string() }), TargetSchema, { auth: "admin" }),
17914
17950
  discoverTargets: require_sleep.method(zod.z.object({
17915
17951
  kind: zod.z.string(),
17916
- config: zod.z.record(zod.z.string(), zod.z.unknown()).optional()
17952
+ config: zod.z.record(zod.z.string(), zod.z.unknown()).optional(),
17953
+ /**
17954
+ * When editing / duplicating, the blank password field never round-trips
17955
+ * the stored token. Pass the source target id so the provider can restore
17956
+ * secrets server-side before dialling (same merge as upsert).
17957
+ */
17958
+ targetId: zod.z.string().optional()
17917
17959
  }), zod.z.array(DiscoveredTargetSchema), { auth: "admin" }),
17960
+ probeTargetConfig: require_sleep.method(zod.z.object({
17961
+ kind: zod.z.string(),
17962
+ config: zod.z.record(zod.z.string(), zod.z.unknown()),
17963
+ /** See `discoverTargets.targetId` — restore stored secrets for a blank password. */
17964
+ targetId: zod.z.string().optional()
17965
+ }), ProbeTargetConfigResultSchema, {
17966
+ kind: "mutation",
17967
+ auth: "admin"
17968
+ }),
17918
17969
  send: require_sleep.method(zod.z.object({
17919
17970
  targetId: zod.z.string(),
17920
17971
  notification: NotificationSchema
@@ -17929,7 +17980,16 @@ var notificationOutputCapability = {
17929
17980
  kind: "mutation",
17930
17981
  auth: "admin"
17931
17982
  }),
17932
- upsertTarget: require_sleep.method(zod.z.object({ target: TargetSchema }), TargetSchema, {
17983
+ upsertTarget: require_sleep.method(zod.z.object({
17984
+ target: TargetSchema,
17985
+ /**
17986
+ * Duplicate flow: create a NEW target id while copying secrets from an
17987
+ * existing row. The UI never holds the stored token; blank / redacted
17988
+ * password fields are restored from this source (D634 still applies if
17989
+ * destinations diverge without a re-typed secret).
17990
+ */
17991
+ cloneSecretsFrom: zod.z.string().optional()
17992
+ }), TargetSchema, {
17933
17993
  kind: "mutation",
17934
17994
  auth: "admin"
17935
17995
  }),
@@ -21462,12 +21522,33 @@ var NC_ALARM_NONBLOCKING_MAX = 200;
21462
21522
  var NcAlarmDelaySecSchema = zod.z.number().int().min(0).max(600);
21463
21523
  var NcAlarmTriggeredSecSchema = zod.z.number().int().min(0).max(NC_ALARM_TRIGGERED_MAX_SEC);
21464
21524
  var uniqueModes = (entries) => new Set(entries.map((e) => e.mode)).size === entries.length;
21525
+ /**
21526
+ * What the panel does when a bounded triggered window ends.
21527
+ * - `rearmAfter` — return to the armed mode
21528
+ * - `disableAfter` — auto-disarm
21529
+ * - `doNothing` — stay triggered until a human disarms
21530
+ */
21531
+ var NcAlarmPostTriggeredActionSchema = zod.z.enum([
21532
+ "rearmAfter",
21533
+ "disableAfter",
21534
+ "doNothing"
21535
+ ]);
21465
21536
  /** One mode's OVERRIDES. An absent field inherits the global value (D697). */
21466
21537
  var NcAlarmModeDelaysSchema = zod.z.object({
21467
21538
  mode: AlarmArmModeSchema,
21468
21539
  exitDelaySec: NcAlarmDelaySecSchema.optional(),
21469
21540
  entryDelaySec: NcAlarmDelaySecSchema.optional(),
21470
- triggeredDurationSec: NcAlarmTriggeredSecSchema.optional()
21541
+ /**
21542
+ * Duration of `triggered` before {@link postTriggeredAction}. Kept as the
21543
+ * historical field name so older clients still read/write a number.
21544
+ */
21545
+ triggeredDurationSec: NcAlarmTriggeredSecSchema.optional(),
21546
+ postTriggeredAction: NcAlarmPostTriggeredActionSchema.optional(),
21547
+ /**
21548
+ * When this mode may be armed. Absent / null = always allowed (same as a
21549
+ * rule with no `schedule`). Evaluated with {@link isScheduleActive}.
21550
+ */
21551
+ schedule: NcScheduleSchema.optional()
21471
21552
  });
21472
21553
  var NcAlarmModeDelaysListSchema = zod.z.array(NcAlarmModeDelaysSchema).max(8).refine(uniqueModes, { message: "modeDelays: at most one entry per arm mode" });
21473
21554
  /**
@@ -21479,7 +21560,10 @@ var NcAlarmModeDelaysEditSchema = zod.z.object({
21479
21560
  mode: AlarmArmModeSchema,
21480
21561
  exitDelaySec: NcAlarmDelaySecSchema.nullable().optional(),
21481
21562
  entryDelaySec: NcAlarmDelaySecSchema.nullable().optional(),
21482
- triggeredDurationSec: NcAlarmTriggeredSecSchema.nullable().optional()
21563
+ triggeredDurationSec: NcAlarmTriggeredSecSchema.nullable().optional(),
21564
+ postTriggeredAction: NcAlarmPostTriggeredActionSchema.nullable().optional(),
21565
+ /** Set a schedule, or `null` to clear (mode always allowed again). */
21566
+ schedule: NcScheduleSchema.nullable().optional()
21483
21567
  });
21484
21568
  var NcAlarmModeDelaysEditListSchema = zod.z.array(NcAlarmModeDelaysEditSchema).max(8).refine(uniqueModes, { message: "modeDelays: at most one edit per arm mode" });
21485
21569
  /** One switch of the alarm table: put ONE device on, or take it off, ONE mode's list. */
@@ -21552,12 +21636,18 @@ var NcAlarmSettingsSchema = zod.z.object({
21552
21636
  /** Grace period between a trigger and the alarm firing. 0 = immediate. */
21553
21637
  entryDelaySec: NcAlarmDelaySecSchema,
21554
21638
  /**
21555
- * How long `triggered` lasts before the panel re-arms itself.
21556
- * **0 = until an operator disarms it** — the behaviour before this field
21557
- * existed, and therefore what an untouched install keeps doing.
21639
+ * How long `triggered` lasts before {@link postTriggeredAction} runs.
21640
+ * Ignored when the action is `doNothing`. Historical name kept so older
21641
+ * clients still round-trip a number.
21558
21642
  */
21559
21643
  triggeredDurationSec: NcAlarmTriggeredSecSchema,
21560
21644
  /**
21645
+ * What happens when the triggered window ends. Absent on a blob older than
21646
+ * this field → derived from {@link triggeredDurationSec} (`>0` ⇒ rearmAfter,
21647
+ * else doNothing).
21648
+ */
21649
+ postTriggeredAction: NcAlarmPostTriggeredActionSchema.optional(),
21650
+ /**
21561
21651
  * Deprecated by D630 — every transition is announced. Parsed, never read;
21562
21652
  * remove after one release. Optional so an older admin's patch (which still
21563
21653
  * sends it) parses rather than failing the whole save.
@@ -37008,7 +37098,7 @@ var LocalInterfaceSchema = zod.z.object({
37008
37098
  name: zod.z.string(),
37009
37099
  family: zod.z.enum(["IPv4", "IPv6"]),
37010
37100
  address: zod.z.string(),
37011
- /** CIDR shorthand (e.g. `192.168.1.10/24`). Empty when OS doesn't expose. */
37101
+ /** CIDR shorthand (e.g. `192.168.x.x/24`). Empty when OS doesn't expose. */
37012
37102
  cidr: zod.z.string(),
37013
37103
  /** OS netmask. Stable across calls so the SDK can hash on it. */
37014
37104
  netmask: zod.z.string(),
@@ -37207,7 +37297,7 @@ var localNetworkCapability = {
37207
37297
  * every client a second authority on a socket only the hub binds. A viewer
37208
37298
  * configured with a port-less public URL (`https://camstack.example.top`)
37209
37299
  * infers 443 from the scheme, asks with 443, and was handed
37210
- * `https://192.168.1.9:443` for a hub listening on 4443. That candidate
37300
+ * `https://192.168.x.x:443` for a hub listening on 4443. That candidate
37211
37301
  * cannot ever answer, and losing its race reads in the log exactly like
37212
37302
  * "the LAN was tried and it was slower" — so an operator sitting on his own
37213
37303
  * WiFi stayed on the public tunnel for weeks, with the LAN candidate born
@@ -37666,7 +37756,7 @@ var MeshPeerSchema = zod.z.object({
37666
37756
  tags: zod.z.array(zod.z.string()).readonly(),
37667
37757
  /** True when the peer advertises itself as an exit-node candidate. */
37668
37758
  exitNodeOption: zod.z.boolean(),
37669
- /** Subnet routes the peer advertises (e.g. `["192.168.1.0/24"]`). */
37759
+ /** Subnet routes the peer advertises (e.g. `["192.168.x.x/24"]`). */
37670
37760
  advertisedRoutes: zod.z.array(zod.z.string()).readonly(),
37671
37761
  /** Owner account login (e.g. `foo@example.com`). Null for tagged peers. */
37672
37762
  userLogin: zod.z.string().nullable(),
@@ -47089,7 +47179,8 @@ function roomCompositionExample(input) {
47089
47179
  return require_composition.CompositionSchema.parse({
47090
47180
  target: {
47091
47181
  kind: "new",
47092
- type: require_err_msg.DeviceType.Sensor
47182
+ type: require_err_msg.DeviceType.Sensor,
47183
+ role: require_err_msg.DeviceRole.TemperatureSensor
47093
47184
  },
47094
47185
  features: [{
47095
47186
  kind: "fields",
@@ -53511,6 +53602,12 @@ var METHOD_ACCESS_MAP = Object.freeze({
53511
53602
  addonId: null,
53512
53603
  access: "view"
53513
53604
  },
53605
+ "notificationOutput.getTarget": {
53606
+ capName: "notification-output",
53607
+ capScope: "system",
53608
+ addonId: null,
53609
+ access: "view"
53610
+ },
53514
53611
  "notificationOutput.listTargetKinds": {
53515
53612
  capName: "notification-output",
53516
53613
  capScope: "system",
@@ -53523,6 +53620,12 @@ var METHOD_ACCESS_MAP = Object.freeze({
53523
53620
  addonId: null,
53524
53621
  access: "view"
53525
53622
  },
53623
+ "notificationOutput.probeTargetConfig": {
53624
+ capName: "notification-output",
53625
+ capScope: "system",
53626
+ addonId: null,
53627
+ access: "create"
53628
+ },
53526
53629
  "notificationOutput.send": {
53527
53630
  capName: "notification-output",
53528
53631
  capScope: "system",
@@ -57645,6 +57748,62 @@ var DEVICE_DO_ACTIONS = [
57645
57748
  method: "stop",
57646
57749
  args: {}
57647
57750
  },
57751
+ {
57752
+ id: "valve.open",
57753
+ label: "Open valve",
57754
+ cap: "valve",
57755
+ method: "open",
57756
+ args: {}
57757
+ },
57758
+ {
57759
+ id: "valve.close",
57760
+ label: "Close valve",
57761
+ cap: "valve",
57762
+ method: "close",
57763
+ args: {}
57764
+ },
57765
+ {
57766
+ id: "valve.stop",
57767
+ label: "Stop valve",
57768
+ cap: "valve",
57769
+ method: "stop",
57770
+ args: {}
57771
+ },
57772
+ {
57773
+ id: "humidifier.on",
57774
+ label: "Humidifier on",
57775
+ cap: "humidifier",
57776
+ method: "setOn",
57777
+ args: { on: true }
57778
+ },
57779
+ {
57780
+ id: "humidifier.off",
57781
+ label: "Humidifier off",
57782
+ cap: "humidifier",
57783
+ method: "setOn",
57784
+ args: { on: false }
57785
+ },
57786
+ {
57787
+ id: "waterHeater.off",
57788
+ label: "Water heater off",
57789
+ cap: "water-heater",
57790
+ method: "setOperationMode",
57791
+ args: { mode: "off" }
57792
+ },
57793
+ {
57794
+ id: "waterHeater.awayOn",
57795
+ label: "Water heater away on",
57796
+ cap: "water-heater",
57797
+ method: "setAway",
57798
+ args: { on: true }
57799
+ },
57800
+ {
57801
+ id: "waterHeater.awayOff",
57802
+ label: "Water heater away off",
57803
+ cap: "water-heater",
57804
+ method: "setAway",
57805
+ args: { on: false }
57806
+ },
57648
57807
  {
57649
57808
  id: "climate.off",
57650
57809
  label: "Climate off",
@@ -57715,6 +57874,115 @@ var DEVICE_DO_ACTIONS = [
57715
57874
  method: "returnToBase",
57716
57875
  args: {}
57717
57876
  },
57877
+ {
57878
+ id: "lawnMower.start",
57879
+ label: "Start mowing",
57880
+ cap: "lawn-mower-control",
57881
+ method: "startMowing",
57882
+ args: {}
57883
+ },
57884
+ {
57885
+ id: "lawnMower.pause",
57886
+ label: "Pause mower",
57887
+ cap: "lawn-mower-control",
57888
+ method: "pause",
57889
+ args: {}
57890
+ },
57891
+ {
57892
+ id: "lawnMower.dock",
57893
+ label: "Dock mower",
57894
+ cap: "lawn-mower-control",
57895
+ method: "dock",
57896
+ args: {}
57897
+ },
57898
+ {
57899
+ id: "media.play",
57900
+ label: "Play",
57901
+ cap: "media-player",
57902
+ method: "play",
57903
+ args: {}
57904
+ },
57905
+ {
57906
+ id: "media.pause",
57907
+ label: "Pause media",
57908
+ cap: "media-player",
57909
+ method: "pause",
57910
+ args: {}
57911
+ },
57912
+ {
57913
+ id: "media.stop",
57914
+ label: "Stop media",
57915
+ cap: "media-player",
57916
+ method: "stop",
57917
+ args: {}
57918
+ },
57919
+ {
57920
+ id: "media.next",
57921
+ label: "Next track",
57922
+ cap: "media-player",
57923
+ method: "next",
57924
+ args: {}
57925
+ },
57926
+ {
57927
+ id: "media.previous",
57928
+ label: "Previous track",
57929
+ cap: "media-player",
57930
+ method: "previous",
57931
+ args: {}
57932
+ },
57933
+ {
57934
+ id: "script.run",
57935
+ label: "Run script",
57936
+ cap: "script-runner",
57937
+ method: "run",
57938
+ args: {}
57939
+ },
57940
+ {
57941
+ id: "script.stop",
57942
+ label: "Stop script",
57943
+ cap: "script-runner",
57944
+ method: "stop",
57945
+ args: {}
57946
+ },
57947
+ {
57948
+ id: "haAutomation.enable",
57949
+ label: "Enable automation",
57950
+ cap: "automation-control",
57951
+ method: "enable",
57952
+ args: {}
57953
+ },
57954
+ {
57955
+ id: "haAutomation.disable",
57956
+ label: "Disable automation",
57957
+ cap: "automation-control",
57958
+ method: "disable",
57959
+ args: {}
57960
+ },
57961
+ {
57962
+ id: "haAutomation.trigger",
57963
+ label: "Trigger automation",
57964
+ cap: "automation-control",
57965
+ method: "trigger",
57966
+ args: {}
57967
+ },
57968
+ {
57969
+ id: "petFeeder.feed",
57970
+ label: "Feed",
57971
+ cap: "pet-feeder",
57972
+ method: "feed",
57973
+ openArgs: [{
57974
+ key: "grams",
57975
+ label: "Grams",
57976
+ kind: "number"
57977
+ }]
57978
+ },
57979
+ {
57980
+ id: "petFeeder.callPet",
57981
+ label: "Call pet",
57982
+ cap: "pet-feeder",
57983
+ method: "callPet",
57984
+ args: {}
57985
+ },
57718
57986
  {
57719
57987
  id: "ptz.goHome",
57720
57988
  label: "PTZ go home",
@@ -57942,6 +58210,94 @@ function bakedArgsEqual(action, args) {
57942
58210
  return argsEqual(action.args, args);
57943
58211
  }
57944
58212
  /**
58213
+ * Catalogue caps a `DeviceType` is expected to offer in the Do picker.
58214
+ *
58215
+ * Exhaustive over {@link DeviceType}: adding a new enum member without an
58216
+ * entry fails the TypeScript build here (same pattern as
58217
+ * {@link DEVICE_TYPE_CONTROL_KIND}). An empty list is a deliberate choice
58218
+ * for read-only / non-actuatable types — never "forgotten".
58219
+ *
58220
+ * Camera accessories (ptz, privacy-mask, …) are listed on Camera even though
58221
+ * a given camera may bind only a subset; {@link actionsForBoundCaps} still
58222
+ * filters to what the device actually binds.
58223
+ */
58224
+ var DEVICE_TYPE_DO_CAPS = {
58225
+ [require_err_msg.DeviceType.Camera]: [
58226
+ "ptz",
58227
+ "ptz-autotrack",
58228
+ "privacy-mask",
58229
+ "day-night",
58230
+ "reboot",
58231
+ "motion-trigger"
58232
+ ],
58233
+ [require_err_msg.DeviceType.Hub]: [],
58234
+ [require_err_msg.DeviceType.Light]: ["switch", "brightness"],
58235
+ [require_err_msg.DeviceType.Siren]: ["switch", "motion-trigger"],
58236
+ [require_err_msg.DeviceType.Switch]: ["switch", "motion-trigger"],
58237
+ [require_err_msg.DeviceType.Sensor]: [],
58238
+ [require_err_msg.DeviceType.Thermostat]: ["climate-control"],
58239
+ [require_err_msg.DeviceType.Climate]: ["climate-control"],
58240
+ [require_err_msg.DeviceType.Button]: ["button"],
58241
+ [require_err_msg.DeviceType.EventEmitter]: [],
58242
+ [require_err_msg.DeviceType.Update]: [],
58243
+ [require_err_msg.DeviceType.Generic]: [],
58244
+ [require_err_msg.DeviceType.Notifier]: [],
58245
+ [require_err_msg.DeviceType.Script]: ["script-runner"],
58246
+ [require_err_msg.DeviceType.Automation]: ["automation-control"],
58247
+ [require_err_msg.DeviceType.Lock]: ["lock-control"],
58248
+ [require_err_msg.DeviceType.Cover]: ["cover"],
58249
+ [require_err_msg.DeviceType.Valve]: ["valve"],
58250
+ [require_err_msg.DeviceType.Humidifier]: ["humidifier"],
58251
+ [require_err_msg.DeviceType.WaterHeater]: ["water-heater"],
58252
+ [require_err_msg.DeviceType.Fan]: ["fan-control", "switch"],
58253
+ [require_err_msg.DeviceType.MediaPlayer]: ["media-player"],
58254
+ [require_err_msg.DeviceType.AlarmPanel]: ["alarm-panel"],
58255
+ [require_err_msg.DeviceType.Control]: [],
58256
+ [require_err_msg.DeviceType.Presence]: [],
58257
+ [require_err_msg.DeviceType.Weather]: [],
58258
+ [require_err_msg.DeviceType.Vacuum]: ["vacuum-control"],
58259
+ [require_err_msg.DeviceType.LawnMower]: ["lawn-mower-control"],
58260
+ [require_err_msg.DeviceType.Container]: [],
58261
+ [require_err_msg.DeviceType.Image]: [],
58262
+ [require_err_msg.DeviceType.PetFeeder]: ["pet-feeder"]
58263
+ };
58264
+ /**
58265
+ * Whether a device type belongs in a Do / automation action device picker.
58266
+ *
58267
+ * Containers stay in {@link DEVICE_TYPE_DO_CAPS} (empty, for exhaustiveness)
58268
+ * but must never appear as selectable targets — actuate the children instead.
58269
+ */
58270
+ function isDoPickerDeviceType(type) {
58271
+ return type !== require_err_msg.DeviceType.Container;
58272
+ }
58273
+ /**
58274
+ * Do-picker family id — devices that share one may be multi-selected for
58275
+ * the same action (several locks, the climate family, cover+valve, …).
58276
+ *
58277
+ * Distinct from {@link DeviceControlKind}: humidifier / water-heater keep
58278
+ * their own control widgets but author with climate siblings.
58279
+ */
58280
+ function deviceDoFamily(type) {
58281
+ switch (type) {
58282
+ case require_err_msg.DeviceType.Climate:
58283
+ case require_err_msg.DeviceType.Thermostat:
58284
+ case require_err_msg.DeviceType.Humidifier:
58285
+ case require_err_msg.DeviceType.WaterHeater: return "climate-family";
58286
+ case require_err_msg.DeviceType.Cover:
58287
+ case require_err_msg.DeviceType.Valve: return "cover-family";
58288
+ case require_err_msg.DeviceType.Switch:
58289
+ case require_err_msg.DeviceType.Siren:
58290
+ case require_err_msg.DeviceType.Light: return "switch-family";
58291
+ case require_err_msg.DeviceType.Vacuum:
58292
+ case require_err_msg.DeviceType.LawnMower: return "robot-family";
58293
+ default: return type;
58294
+ }
58295
+ }
58296
+ /** True when two device types may share one multi-target Do step. */
58297
+ function sameDoFamily(leftType, rightType) {
58298
+ return deviceDoFamily(leftType) === deviceDoFamily(rightType);
58299
+ }
58300
+ /**
57945
58301
  * Actions offered for a device that binds the given caps.
57946
58302
  *
57947
58303
  * Only catalogue entries whose cap is bound AND still actuatable in
@@ -57952,6 +58308,50 @@ function actionsForBoundCaps(boundCaps) {
57952
58308
  const set = new Set(boundCaps);
57953
58309
  return DEVICE_DO_ACTIONS.filter((action) => set.has(action.cap) && isDoActionActuatable(action));
57954
58310
  }
58311
+ /**
58312
+ * Catalogue actions for a wire `DeviceType` string — the fallback when
58313
+ * bindings have not answered yet (or answered empty for a typed actuator).
58314
+ * Unknown type strings → empty.
58315
+ */
58316
+ function actionsForDeviceType(type) {
58317
+ if (!Object.values(require_err_msg.DeviceType).includes(type)) return [];
58318
+ return actionsForBoundCaps(DEVICE_TYPE_DO_CAPS[type]);
58319
+ }
58320
+ /**
58321
+ * Union of bound-cap actions with the type's expected catalogue caps.
58322
+ *
58323
+ * Bindings win for filtering (a lock without `lock-control` bound still
58324
+ * offers nothing from bindings alone); the type map fills gaps when the
58325
+ * binding read is empty so a Lock / Valve / Climate never shows
58326
+ * "No actions for this device" solely because getBindings lagged.
58327
+ */
58328
+ function actionsForDevice(input) {
58329
+ const fromBound = input.boundCaps !== void 0 && input.boundCaps.length > 0 ? actionsForBoundCaps(input.boundCaps) : [];
58330
+ if (fromBound.length > 0) return fromBound;
58331
+ if (input.deviceType !== void 0 && input.deviceType.length > 0) return actionsForDeviceType(input.deviceType);
58332
+ return [];
58333
+ }
58334
+ /**
58335
+ * Intersection of {@link actionsForDevice} across several targets — what a
58336
+ * multi-select same-family Do step may offer.
58337
+ */
58338
+ function actionsForDevices(targets) {
58339
+ if (targets.length === 0) return [];
58340
+ let common = null;
58341
+ for (const target of targets) {
58342
+ const offered = actionsForDevice({
58343
+ boundCaps: target.boundCaps,
58344
+ deviceType: target.deviceType
58345
+ });
58346
+ if (common === null) {
58347
+ common = offered;
58348
+ continue;
58349
+ }
58350
+ const ids = new Set(offered.map((a) => a.id));
58351
+ common = common.filter((a) => ids.has(a.id));
58352
+ }
58353
+ return common ?? [];
58354
+ }
57955
58355
  /** The whole catalogue (still actuatable) — for a `{$var}` automation target. */
57956
58356
  function allDoActions() {
57957
58357
  return DEVICE_DO_ACTIONS.filter(isDoActionActuatable);
@@ -65196,7 +65596,9 @@ function createSystemProxy(api) {
65196
65596
  notificationOutput: {
65197
65597
  listTargetKinds: (input) => dispatch("notificationOutput", "listTargetKinds", "query", input),
65198
65598
  listTargets: (input) => dispatch("notificationOutput", "listTargets", "query", input),
65599
+ getTarget: (input) => dispatch("notificationOutput", "getTarget", "query", input),
65199
65600
  discoverTargets: (input) => dispatch("notificationOutput", "discoverTargets", "query", input),
65601
+ probeTargetConfig: (input) => dispatch("notificationOutput", "probeTargetConfig", "mutation", input),
65200
65602
  send: (input) => dispatch("notificationOutput", "send", "mutation", input),
65201
65603
  testTarget: (input) => dispatch("notificationOutput", "testTarget", "mutation", input),
65202
65604
  upsertTarget: (input) => dispatch("notificationOutput", "upsertTarget", "mutation", input),
@@ -67276,6 +67678,10 @@ function bindingPullsAlarmTrigger(binding, sequenceActionsOf) {
67276
67678
  if (steps === void 0) return false;
67277
67679
  return steps.some((step) => step.kind === "cap" && step.cap === ALARM_PANEL_CAP && step.method === ALARM_PANEL_TRIGGER_METHOD);
67278
67680
  }
67681
+ /** True when the rule's deviceState gate names any `armed_*` word. */
67682
+ function ruleGatedOnArmedState(rule) {
67683
+ return (rule.conditions.deviceState?.states ?? []).some((s) => s.trim().toLowerCase().startsWith(ARMED_WORD_PREFIX));
67684
+ }
67279
67685
  /**
67280
67686
  * A rule belongs to the alarm when its `deviceState` gate names ANY device's
67281
67687
  * `armed_*` word, or an on-match binding pulls the alarm panel's trigger
@@ -67283,10 +67689,19 @@ function bindingPullsAlarmTrigger(binding, sequenceActionsOf) {
67283
67689
  * escalation.
67284
67690
  */
67285
67691
  function ruleBelongsToAlarm(rule) {
67286
- if ((rule.conditions.deviceState?.states ?? []).some((s) => s.trim().toLowerCase().startsWith(ARMED_WORD_PREFIX))) return true;
67692
+ if (ruleGatedOnArmedState(rule)) return true;
67287
67693
  for (const binding of rule.actions?.onTrigger ?? []) if (bindingPullsAlarmTrigger(binding, rule.sequenceActionsOf)) return true;
67288
67694
  return false;
67289
67695
  }
67696
+ /**
67697
+ * A rule gated on `armed_*` auto-triggers the CamStack `alarm-panel` on match
67698
+ * — no `onTrigger` sequence required. Sirens are never part of this path.
67699
+ * An explicit `alarm-panel.trigger` binding without an armed gate stays
67700
+ * explicit actuation only ({@link ruleBelongsToAlarm}).
67701
+ */
67702
+ function ruleAutoTriggersAlarm(rule) {
67703
+ return ruleGatedOnArmedState(rule);
67704
+ }
67290
67705
  function isOpeningKind(kind) {
67291
67706
  const k = kind.trim().toLowerCase();
67292
67707
  return NC_ALARM_OPENING_EVENT_KINDS.some((opening) => opening === k);
@@ -67352,6 +67767,14 @@ var NC_ALARM_DELAY_FIELDS = [
67352
67767
  "entryDelaySec",
67353
67768
  "triggeredDurationSec"
67354
67769
  ];
67770
+ /**
67771
+ * Derive the post-triggered action from a stored blob that may predate the field:
67772
+ * a positive duration meant re-arm; zero/absent meant stay triggered.
67773
+ */
67774
+ function derivePostTriggeredAction(action, triggeredDurationSec) {
67775
+ if (action !== void 0) return action;
67776
+ return triggeredDurationSec > 0 ? "rearmAfter" : "doNothing";
67777
+ }
67355
67778
  /** The mode's value when it overrides the field, else the global one. */
67356
67779
  function pick(override, global) {
67357
67780
  return override === void 0 ? {
@@ -67368,14 +67791,19 @@ function resolveModeDelays(settings, mode) {
67368
67791
  const exit = pick(entry?.exitDelaySec, settings.exitDelaySec);
67369
67792
  const entryDelay = pick(entry?.entryDelaySec, settings.entryDelaySec);
67370
67793
  const triggered = pick(entry?.triggeredDurationSec, settings.triggeredDurationSec);
67794
+ const actionOverride = entry?.postTriggeredAction;
67795
+ const actionSource = actionOverride !== void 0 ? "mode" : "default";
67796
+ const postTriggeredAction = derivePostTriggeredAction(actionOverride ?? settings.postTriggeredAction, triggered.value);
67371
67797
  return {
67372
67798
  exitDelaySec: exit.value,
67373
67799
  entryDelaySec: entryDelay.value,
67374
67800
  triggeredDurationSec: triggered.value,
67801
+ postTriggeredAction,
67375
67802
  source: {
67376
67803
  exitDelaySec: exit.source,
67377
67804
  entryDelaySec: entryDelay.source,
67378
- triggeredDurationSec: triggered.source
67805
+ triggeredDurationSec: triggered.source,
67806
+ postTriggeredAction: actionSource
67379
67807
  }
67380
67808
  };
67381
67809
  }
@@ -67384,6 +67812,29 @@ function edited(current, edit) {
67384
67812
  if (edit === void 0) return current;
67385
67813
  return edit === null ? void 0 : edit;
67386
67814
  }
67815
+ function editedAction(current, edit) {
67816
+ if (edit === void 0) return current;
67817
+ return edit === null ? void 0 : edit;
67818
+ }
67819
+ function editedSchedule(current, edit) {
67820
+ if (edit === void 0) return current;
67821
+ return edit === null ? void 0 : edit;
67822
+ }
67823
+ function sameSchedule(a, b) {
67824
+ if (a === void 0 && b === void 0) return true;
67825
+ if (a === void 0 || b === void 0) return false;
67826
+ if (a.invert !== b.invert || a.timezone !== b.timezone) return false;
67827
+ if (a.windows.length !== b.windows.length) return false;
67828
+ for (let i = 0; i < a.windows.length; i++) {
67829
+ const wa = a.windows[i];
67830
+ const wb = b.windows[i];
67831
+ if (wa === void 0 || wb === void 0) return false;
67832
+ if (wa.startMinute !== wb.startMinute || wa.endMinute !== wb.endMinute) return false;
67833
+ if (wa.days.length !== wb.days.length) return false;
67834
+ for (let d = 0; d < wa.days.length; d++) if (wa.days[d] !== wb.days[d]) return false;
67835
+ }
67836
+ return true;
67837
+ }
67387
67838
  /**
67388
67839
  * Apply per-field edits to the stored overrides. Returns new arrays, never mutates the input;
67389
67840
  * an entry with no field left is dropped (the mode inherits everything again).
@@ -67397,13 +67848,17 @@ function applyModeDelaysEdits(current, edits) {
67397
67848
  const exit = edited(base.exitDelaySec, edit.exitDelaySec);
67398
67849
  const entry = edited(base.entryDelaySec, edit.entryDelaySec);
67399
67850
  const triggered = edited(base.triggeredDurationSec, edit.triggeredDurationSec);
67851
+ const action = editedAction(base.postTriggeredAction, edit.postTriggeredAction);
67852
+ const schedule = editedSchedule(base.schedule, edit.schedule);
67400
67853
  if (exit !== void 0) next.exitDelaySec = exit;
67401
67854
  if (entry !== void 0) next.entryDelaySec = entry;
67402
67855
  if (triggered !== void 0) next.triggeredDurationSec = triggered;
67856
+ if (action !== void 0) next.postTriggeredAction = action;
67857
+ if (schedule !== void 0) next.schedule = schedule;
67403
67858
  if (at >= 0) out[at] = next;
67404
67859
  else out.push(next);
67405
67860
  }
67406
- return out.filter((e) => e.exitDelaySec !== void 0 || e.entryDelaySec !== void 0 || e.triggeredDurationSec !== void 0);
67861
+ return out.filter((e) => e.exitDelaySec !== void 0 || e.entryDelaySec !== void 0 || e.triggeredDurationSec !== void 0 || e.postTriggeredAction !== void 0 || e.schedule !== void 0);
67407
67862
  }
67408
67863
  /**
67409
67864
  * Put ONE device on, or take it off, ONE mode's device-id list. A no-op answers
@@ -67531,6 +67986,7 @@ function alarmPatchLanded(patch, returned) {
67531
67986
  if (patch.exitDelaySec !== void 0 && patch.exitDelaySec !== returned.exitDelaySec) return false;
67532
67987
  if (patch.entryDelaySec !== void 0 && patch.entryDelaySec !== returned.entryDelaySec) return false;
67533
67988
  if (patch.triggeredDurationSec !== void 0 && patch.triggeredDurationSec !== returned.triggeredDurationSec) return false;
67989
+ if (patch.postTriggeredAction !== void 0 && patch.postTriggeredAction !== derivePostTriggeredAction(returned.postTriggeredAction, returned.triggeredDurationSec)) return false;
67534
67990
  if (patch.announceTargets !== void 0 && !sameSet(patch.announceTargets, returned.announceTargets)) return false;
67535
67991
  if (patch.nonBlocking !== void 0 && !sameLists(patch.nonBlocking, returned.nonBlocking ?? [])) return false;
67536
67992
  if (patch.blocking !== void 0 && !sameLists(patch.blocking, returned.blocking ?? [])) return false;
@@ -67543,6 +67999,14 @@ function alarmPatchLanded(patch, returned) {
67543
67999
  const got = fieldOf(entry, field);
67544
68000
  if (want === null ? got !== void 0 : got !== want) return false;
67545
68001
  }
68002
+ if (edit.postTriggeredAction !== void 0) {
68003
+ const got = entry?.postTriggeredAction;
68004
+ if (edit.postTriggeredAction === null ? got !== void 0 : got !== edit.postTriggeredAction) return false;
68005
+ }
68006
+ if (edit.schedule !== void 0) {
68007
+ const got = entry?.schedule;
68008
+ if (edit.schedule === null ? got !== void 0 : !sameSchedule(got, edit.schedule)) return false;
68009
+ }
67546
68010
  }
67547
68011
  if (patch.nonBlockingEdit !== void 0) {
67548
68012
  const e = patch.nonBlockingEdit;
@@ -67563,11 +68027,12 @@ function alarmPatchLanded(patch, returned) {
67563
68027
  /** Stable id of the always-present Default profile (migrated from flat settings). */
67564
68028
  var NC_ALARM_DEFAULT_PROFILE_ID = "default";
67565
68029
  var NC_ALARM_DEFAULT_PROFILE_NAME = "Default";
67566
- /** Stock delays — same numbers the panel shipped with before any editor existed. */
68030
+ /** Stock delays — re-arm 10 s after trigger (inherited by every mode). */
67567
68031
  var NC_ALARM_SYSTEM_DEFAULT_DELAYS = {
67568
68032
  exitDelaySec: 30,
67569
68033
  entryDelaySec: 20,
67570
- triggeredDurationSec: 0
68034
+ triggeredDurationSec: 10,
68035
+ postTriggeredAction: "rearmAfter"
67571
68036
  };
67572
68037
  /** Empty memberships + stock delays + no announce targets. */
67573
68038
  function ncAlarmSystemDefaultSettings() {
@@ -67589,6 +68054,7 @@ function cloneAlarmSettings(settings) {
67589
68054
  exitDelaySec: settings.exitDelaySec,
67590
68055
  entryDelaySec: settings.entryDelaySec,
67591
68056
  triggeredDurationSec: settings.triggeredDurationSec,
68057
+ ...settings.postTriggeredAction !== void 0 ? { postTriggeredAction: settings.postTriggeredAction } : {},
67592
68058
  ...settings.announceArm !== void 0 ? { announceArm: settings.announceArm } : {},
67593
68059
  announceTargets: [...settings.announceTargets],
67594
68060
  nonBlocking: settings.nonBlocking.map((l) => ({
@@ -67603,7 +68069,22 @@ function cloneAlarmSettings(settings) {
67603
68069
  mode: l.mode,
67604
68070
  deviceIds: [...l.deviceIds]
67605
68071
  })),
67606
- modeDelays: settings.modeDelays.map((e) => ({ ...e }))
68072
+ modeDelays: settings.modeDelays.map((e) => ({
68073
+ mode: e.mode,
68074
+ ...e.exitDelaySec !== void 0 ? { exitDelaySec: e.exitDelaySec } : {},
68075
+ ...e.entryDelaySec !== void 0 ? { entryDelaySec: e.entryDelaySec } : {},
68076
+ ...e.triggeredDurationSec !== void 0 ? { triggeredDurationSec: e.triggeredDurationSec } : {},
68077
+ ...e.postTriggeredAction !== void 0 ? { postTriggeredAction: e.postTriggeredAction } : {},
68078
+ ...e.schedule !== void 0 ? { schedule: {
68079
+ windows: e.schedule.windows.map((w) => ({
68080
+ days: [...w.days],
68081
+ startMinute: w.startMinute,
68082
+ endMinute: w.endMinute
68083
+ })),
68084
+ ...e.schedule.timezone !== void 0 ? { timezone: e.schedule.timezone } : {},
68085
+ ...e.schedule.invert === true ? { invert: true } : {}
68086
+ } } : {}
68087
+ }))
67607
68088
  };
67608
68089
  }
67609
68090
  /**
@@ -68930,6 +69411,34 @@ function sendTimesOfSchedule(schedule) {
68930
69411
  }
68931
69412
  return times;
68932
69413
  }
69414
+ /**
69415
+ * Punctual times for a `mode: 'times'` editor.
69416
+ *
69417
+ * Exact one-minute windows win. Otherwise each window's END is the fire time
69418
+ * (summary delivery fires when a window closes) — so a legacy 17:00→18:00 band
69419
+ * authored as a range still opens as a single "At 18:00" row instead of two
69420
+ * clocks. `null` only when inverted (cannot map to punctual rows).
69421
+ */
69422
+ function sendTimesForEditor(schedule) {
69423
+ const exact = sendTimesOfSchedule(schedule);
69424
+ if (exact !== null) return {
69425
+ times: exact,
69426
+ approximated: false
69427
+ };
69428
+ if (schedule.invert === true) return null;
69429
+ const times = [];
69430
+ for (const window of schedule.windows) {
69431
+ const days = window.endMinute === 0 ? window.days.map((day) => (day + 1) % 7) : window.days;
69432
+ times.push({
69433
+ days: days.toSorted((a, b) => a - b),
69434
+ minute: window.endMinute
69435
+ });
69436
+ }
69437
+ return {
69438
+ times,
69439
+ approximated: times.length > 0
69440
+ };
69441
+ }
68933
69442
  var SUMMARY_CONTENT_VAR = /\{\{\s*summary(?:Text|Devices|Streams|Battery|Consumables|Tanks|Detection|Nodes|Addons|Updates)\s*\}\}/;
68934
69443
  /**
68935
69444
  * Does a custom BODY carry the summary's content (`{{summaryText}}` or a
@@ -72400,6 +72909,7 @@ exports.DEVICE_SETTINGS_CONTRIBUTION_METHODS = require_sleep.DEVICE_SETTINGS_CON
72400
72909
  exports.DEVICE_STATE_READERS = DEVICE_STATE_READERS;
72401
72910
  exports.DEVICE_STATUS_METHOD = require_sleep.DEVICE_STATUS_METHOD;
72402
72911
  exports.DEVICE_TYPE_CONTROL_KIND = DEVICE_TYPE_CONTROL_KIND;
72912
+ exports.DEVICE_TYPE_DO_CAPS = DEVICE_TYPE_DO_CAPS;
72403
72913
  exports.DEVICE_TYPE_INFO = DEVICE_TYPE_INFO;
72404
72914
  exports.DISPLAY_ICON_GROUPS = DISPLAY_ICON_GROUPS;
72405
72915
  exports.DISPLAY_ICON_KEYS = DISPLAY_ICON_KEYS;
@@ -72904,6 +73414,7 @@ exports.NcAlarmModeDelaysSchema = NcAlarmModeDelaysSchema;
72904
73414
  exports.NcAlarmModeDeviceListSchema = NcAlarmModeDeviceListSchema;
72905
73415
  exports.NcAlarmNonBlockingEditSchema = NcAlarmNonBlockingEditSchema;
72906
73416
  exports.NcAlarmNonBlockingSchema = NcAlarmNonBlockingSchema;
73417
+ exports.NcAlarmPostTriggeredActionSchema = NcAlarmPostTriggeredActionSchema;
72907
73418
  exports.NcAlarmProfileIdInputSchema = NcAlarmProfileIdInputSchema;
72908
73419
  exports.NcAlarmProfileMetaSchema = NcAlarmProfileMetaSchema;
72909
73420
  exports.NcAlarmProfilesViewSchema = NcAlarmProfilesViewSchema;
@@ -73085,6 +73596,7 @@ exports.PrivacyMaskPatchSchema = PrivacyMaskPatchSchema;
73085
73596
  exports.PrivacyMaskRegionSchema = PrivacyMaskRegionSchema;
73086
73597
  exports.PrivacyMaskShapeSchema = PrivacyMaskShapeSchema;
73087
73598
  exports.PrivacyMaskStatusSchema = PrivacyMaskStatusSchema;
73599
+ exports.ProbeTargetConfigResultSchema = ProbeTargetConfigResultSchema;
73088
73600
  exports.ProfileRtspEntrySchema = require_sleep.ProfileRtspEntrySchema;
73089
73601
  exports.ProfileSlotSchema = require_sleep.ProfileSlotSchema;
73090
73602
  exports.ProfileSlotStatusSchema = require_sleep.ProfileSlotStatusSchema;
@@ -73487,6 +73999,9 @@ exports.__resetLogChannelRegistryForTests = __resetLogChannelRegistryForTests;
73487
73999
  exports.accessoriesCapability = accessoriesCapability;
73488
74000
  exports.accessoryStableId = accessoryStableId;
73489
74001
  exports.actionsForBoundCaps = actionsForBoundCaps;
74002
+ exports.actionsForDevice = actionsForDevice;
74003
+ exports.actionsForDeviceType = actionsForDeviceType;
74004
+ exports.actionsForDevices = actionsForDevices;
73490
74005
  exports.activateAlarmProfile = activateAlarmProfile;
73491
74006
  exports.addonPagesCapability = addonPagesCapability;
73492
74007
  exports.addonPagesSourceCapability = addonPagesSourceCapability;
@@ -73652,6 +74167,7 @@ exports.deleteAlarmProfile = deleteAlarmProfile;
73652
74167
  exports.deriveBatteryPresence = deriveBatteryPresence;
73653
74168
  exports.deriveCameraSwitches = deriveCameraSwitches;
73654
74169
  exports.deriveDetailCropRect = deriveDetailCropRect;
74170
+ exports.derivePostTriggeredAction = derivePostTriggeredAction;
73655
74171
  exports.deriveRecordingMode = deriveRecordingMode;
73656
74172
  exports.describeComposableCaps = describeComposableCaps;
73657
74173
  exports.describeCustomActions = require_sleep.describeCustomActions;
@@ -73669,6 +74185,7 @@ exports.deviceAdoptionCapability = deviceAdoptionCapability;
73669
74185
  exports.deviceBackendToFormat = deviceBackendToFormat;
73670
74186
  exports.deviceCustomAction = require_sleep.deviceCustomAction;
73671
74187
  exports.deviceDiscoveryCapability = deviceDiscoveryCapability;
74188
+ exports.deviceDoFamily = deviceDoFamily;
73672
74189
  exports.deviceExportCapability = deviceExportCapability;
73673
74190
  exports.deviceExtensionCapability = deviceExtensionCapability;
73674
74191
  exports.deviceManagerCapability = deviceManagerCapability;
@@ -73795,6 +74312,7 @@ exports.isDeviceConfigCap = require_sleep.isDeviceConfigCap;
73795
74312
  exports.isDeviceScopedCap = require_sleep.isDeviceScopedCap;
73796
74313
  exports.isDisplayIconKey = isDisplayIconKey;
73797
74314
  exports.isDoActionActuatable = isDoActionActuatable;
74315
+ exports.isDoPickerDeviceType = isDoPickerDeviceType;
73798
74316
  exports.isEmbeddingModelFailed = isEmbeddingModelFailed;
73799
74317
  exports.isEvent = require_sleep.isEvent;
73800
74318
  exports.isEventKindLabelKey = isEventKindLabelKey;
@@ -74012,10 +74530,12 @@ exports.resolveVariantModelId = resolveVariantModelId;
74012
74530
  exports.resolveViewableDeviceIds = resolveViewableDeviceIds;
74013
74531
  exports.roleSpec = roleSpec;
74014
74532
  exports.roomCompositionExample = roomCompositionExample;
74533
+ exports.ruleAutoTriggersAlarm = ruleAutoTriggersAlarm;
74015
74534
  exports.ruleBelongsToAlarm = ruleBelongsToAlarm;
74016
74535
  exports.ruleDeviceCompatCapNames = ruleDeviceCompatCapNames;
74017
74536
  exports.ruleDeviceCompatCapQueries = ruleDeviceCompatCapQueries;
74018
74537
  exports.ruleEditorSectionsForKind = ruleEditorSectionsForKind;
74538
+ exports.ruleGatedOnArmedState = ruleGatedOnArmedState;
74019
74539
  exports.ruleGroupingApplies = ruleGroupingApplies;
74020
74540
  exports.ruleKindOf = ruleKindOf;
74021
74541
  exports.ruleKindSpec = ruleKindSpec;
@@ -74026,6 +74546,7 @@ exports.ruleSeedForSection = ruleSeedForSection;
74026
74546
  exports.runInferenceStep = runInferenceStep;
74027
74547
  exports.runtimeDevices = runtimeDevices;
74028
74548
  exports.runtimeStatePolicyFor = runtimeStatePolicyFor;
74549
+ exports.sameDoFamily = sameDoFamily;
74029
74550
  exports.sceneMonitorCapability = sceneMonitorCapability;
74030
74551
  exports.scheduleForSendTimes = scheduleForSendTimes;
74031
74552
  exports.schemaDeclaresAnyField = schemaDeclaresAnyField;
@@ -74038,6 +74559,7 @@ exports.scriptRunnerCapability = scriptRunnerCapability;
74038
74559
  exports.searchDisplayIcons = searchDisplayIcons;
74039
74560
  exports.secureActuationFor = secureActuationFor;
74040
74561
  exports.selectAssignedProfileSlots = require_sleep.selectAssignedProfileSlots;
74562
+ exports.sendTimesForEditor = sendTimesForEditor;
74041
74563
  exports.sendTimesOfSchedule = sendTimesOfSchedule;
74042
74564
  exports.sensorRaisedOf = sensorRaisedOf;
74043
74565
  exports.sensorTransitionNeverFires = sensorTransitionNeverFires;