@camstack/addon-agent-ui 1.2.289 → 1.2.291

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/CHANGELOG.md CHANGED
@@ -7,6 +7,18 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
7
7
 
8
8
  ## [Unreleased]
9
9
 
10
+ ## [1.2.291] - 2026-10-29
11
+
12
+ ### Changed
13
+
14
+ - Rebuilt against updated dependencies.
15
+
16
+ ## [1.2.290] - 2026-10-29
17
+
18
+ ### Changed
19
+
20
+ - Rebuilt against updated dependencies.
21
+
10
22
  ## [1.2.289] - 2026-10-28
11
23
 
12
24
  ### Changed
package/dist/addon.js CHANGED
@@ -5448,7 +5448,7 @@ var ZodIssueCode = {
5448
5448
  var ZodFirstPartyTypeKind;
5449
5449
  ZodFirstPartyTypeKind || (ZodFirstPartyTypeKind = {});
5450
5450
  //#endregion
5451
- //#region ../types/dist/sleep-BAvUCi_2.mjs
5451
+ //#region ../types/dist/sleep-C_u6cEAJ.mjs
5452
5452
  /**
5453
5453
  * The audio chunk plane's byte format, and the ONE expansion from a coded
5454
5454
  * window to float samples (D455).
@@ -8629,6 +8629,7 @@ var CAP_NAMES = Object.freeze([
8629
8629
  "network-link",
8630
8630
  "network-quality",
8631
8631
  "node-certificates",
8632
+ "node-removal-hook",
8632
8633
  "nodes",
8633
8634
  "notification-output",
8634
8635
  "notification-rules",
@@ -8659,6 +8660,7 @@ var CAP_NAMES = Object.freeze([
8659
8660
  "recording-onboard",
8660
8661
  "recording-signal",
8661
8662
  "records",
8663
+ "remote",
8662
8664
  "running-state",
8663
8665
  "scene-monitor",
8664
8666
  "script-runner",
@@ -8682,6 +8684,7 @@ var CAP_NAMES = Object.freeze([
8682
8684
  "system",
8683
8685
  "tamper",
8684
8686
  "temperature-sensor",
8687
+ "template",
8685
8688
  "terminal-session",
8686
8689
  "toast",
8687
8690
  "training",
@@ -9622,6 +9625,11 @@ Object.freeze({
9622
9625
  "standby"
9623
9626
  ]
9624
9627
  },
9628
+ {
9629
+ "path": "stateSource",
9630
+ "valueType": "enum",
9631
+ "enumValues": ["reported", "assumed"]
9632
+ },
9625
9633
  {
9626
9634
  "path": "volumeLevel",
9627
9635
  "valueType": "number"
@@ -9897,6 +9905,18 @@ Object.freeze({
9897
9905
  {
9898
9906
  "path": "volume",
9899
9907
  "valueType": "number"
9908
+ },
9909
+ {
9910
+ "path": "lastFeedGrams",
9911
+ "valueType": "number"
9912
+ },
9913
+ {
9914
+ "path": "lastFeedHopper1",
9915
+ "valueType": "number"
9916
+ },
9917
+ {
9918
+ "path": "lastFeedHopper2",
9919
+ "valueType": "number"
9900
9920
  }
9901
9921
  ],
9902
9922
  "power-meter": [
@@ -10788,7 +10808,7 @@ var DeviceRole = /* @__PURE__ */ function(DeviceRole) {
10788
10808
  return DeviceRole;
10789
10809
  }({});
10790
10810
  //#endregion
10791
- //#region ../types/dist/composition-DpFv_J6D.mjs
10811
+ //#region ../types/dist/composition-bIBW5_13.mjs
10792
10812
  /**
10793
10813
  * The ffmpeg build every CamStack node downloads, per platform and arch.
10794
10814
  *
@@ -42351,6 +42371,14 @@ method(object({
42351
42371
  kind: "mutation",
42352
42372
  auth: "admin"
42353
42373
  });
42374
+ method(object({
42375
+ nodeId: string().min(1),
42376
+ /** Epoch ms the node was forgotten (the tombstone's `removedAt`). */
42377
+ removedAt: number()
42378
+ }), object({ counts: record(string(), number().int().nonnegative()) }), {
42379
+ kind: "mutation",
42380
+ auth: "admin"
42381
+ });
42354
42382
  /**
42355
42383
  * `device-removal-hook` — the reliable way an addon learns a device was DELETED,
42356
42384
  * so it can delete what it keeps for that device (D865).
@@ -57363,6 +57391,318 @@ DeviceType.Light, method(object({
57363
57391
  level: number().min(0).max(100),
57364
57392
  lastChangedAt: number()
57365
57393
  });
57394
+ /**
57395
+ * The role vocabulary of a remote (D963): what a button MEANS, independent of
57396
+ * how it is wired. A layout template places buttons by role; a device binds a
57397
+ * role to an action; an exporter asks for a role by name. Roles are shared so
57398
+ * one layout fits every appliance and one voice command fits every binding.
57399
+ *
57400
+ * A role outside this list is `custom:<key>` — the operator's own button (a
57401
+ * SmartIR source, a channel preset). The key is a lowercase slug.
57402
+ */
57403
+ var REMOTE_KNOWN_ROLES = [
57404
+ "power",
57405
+ "power_on",
57406
+ "power_off",
57407
+ "volume_up",
57408
+ "volume_down",
57409
+ "mute",
57410
+ "channel_up",
57411
+ "channel_down",
57412
+ "up",
57413
+ "down",
57414
+ "left",
57415
+ "right",
57416
+ "ok",
57417
+ "back",
57418
+ "home",
57419
+ "menu",
57420
+ "info",
57421
+ "guide",
57422
+ "exit",
57423
+ "input",
57424
+ "play",
57425
+ "pause",
57426
+ "play_pause",
57427
+ "stop",
57428
+ "next",
57429
+ "previous",
57430
+ "fast_forward",
57431
+ "rewind",
57432
+ "digit_0",
57433
+ "digit_1",
57434
+ "digit_2",
57435
+ "digit_3",
57436
+ "digit_4",
57437
+ "digit_5",
57438
+ "digit_6",
57439
+ "digit_7",
57440
+ "digit_8",
57441
+ "digit_9"
57442
+ ];
57443
+ var CUSTOM_KEY_RE = /^[a-z0-9][a-z0-9_]{0,47}$/;
57444
+ var KNOWN_ROLES = new Set(REMOTE_KNOWN_ROLES);
57445
+ function isRemoteKnownRole(value) {
57446
+ return KNOWN_ROLES.has(value);
57447
+ }
57448
+ function isRemoteCustomKey(key) {
57449
+ return CUSTOM_KEY_RE.test(key);
57450
+ }
57451
+ /** The key of a `custom:<key>` role, or null for any other string. */
57452
+ function customKeyOfRole(role) {
57453
+ if (!role.startsWith("custom:")) return null;
57454
+ const key = role.slice(7);
57455
+ return isRemoteCustomKey(key) ? key : null;
57456
+ }
57457
+ function isRemoteRole(value) {
57458
+ return isRemoteKnownRole(value) || customKeyOfRole(value) !== null;
57459
+ }
57460
+ var RemoteRoleSchema = string().refine(isRemoteRole, { message: "a role is one of the known roles or custom:<key> (lowercase letters, digits, _)" });
57461
+ var RemoteBindingSchema = object({ action: AutomationCapStepSchema.extend({ deviceId: number().int().nonnegative() }) });
57462
+ var RemoteCustomButtonSchema = object({
57463
+ /** The slug after `custom:` in the role. */
57464
+ key: string().refine(isRemoteCustomKey, { message: "a lowercase slug" }),
57465
+ /** What the operator calls it, and what a voice command may name. */
57466
+ name: string().min(1).max(60)
57467
+ });
57468
+ var RemotePowerModeSchema = _enum(["toggle", "discrete"]);
57469
+ var RemoteConfigSchema = object({
57470
+ layoutTemplateId: string().min(1).nullable(),
57471
+ /**
57472
+ * The transmitter device new bindings and an import send through. A binding
57473
+ * names its own device, so one command may override it.
57474
+ */
57475
+ defaultTransmitterId: number().int().nonnegative().nullable().default(null),
57476
+ /** Keyed by role. A role with no entry falls back to the native cap. */
57477
+ bindings: record(string(), RemoteBindingSchema),
57478
+ customButtons: array(RemoteCustomButtonSchema).max(100),
57479
+ power: object({ mode: RemotePowerModeSchema })
57480
+ }).superRefine((config, ctx) => {
57481
+ const roles = Object.keys(config.bindings);
57482
+ if (roles.length > 200) ctx.addIssue({
57483
+ code: "custom",
57484
+ message: "too many bindings",
57485
+ path: ["bindings"]
57486
+ });
57487
+ for (const role of roles) if (!isRemoteRole(role)) ctx.addIssue({
57488
+ code: "custom",
57489
+ message: `"${role}" is not a role`,
57490
+ path: ["bindings", role]
57491
+ });
57492
+ const keys = /* @__PURE__ */ new Set();
57493
+ config.customButtons.forEach((button, index) => {
57494
+ if (keys.has(button.key)) ctx.addIssue({
57495
+ code: "custom",
57496
+ message: `custom button "${button.key}" is listed twice`,
57497
+ path: [
57498
+ "customButtons",
57499
+ index,
57500
+ "key"
57501
+ ]
57502
+ });
57503
+ keys.add(button.key);
57504
+ });
57505
+ for (const role of roles) {
57506
+ const key = customKeyOfRole(role);
57507
+ if (key !== null && !keys.has(key)) ctx.addIssue({
57508
+ code: "custom",
57509
+ message: `${role} is bound but has no entry in customButtons`,
57510
+ path: ["bindings", role]
57511
+ });
57512
+ }
57513
+ });
57514
+ object({
57515
+ power: object({
57516
+ state: _enum(["on", "off"]),
57517
+ at: number()
57518
+ }).nullable(),
57519
+ muted: object({
57520
+ value: boolean(),
57521
+ at: number()
57522
+ }).nullable()
57523
+ });
57524
+ var RemoteLayoutButtonSchema = object({
57525
+ id: string().min(1).max(40),
57526
+ /** 0-based grid position. */
57527
+ row: number().int().min(0).max(24),
57528
+ col: number().int().min(0).max(24),
57529
+ rowSpan: number().int().min(1).max(24),
57530
+ colSpan: number().int().min(1).max(24),
57531
+ icon: string().min(1).max(60).optional(),
57532
+ label: string().min(1).max(40).optional(),
57533
+ role: RemoteRoleSchema
57534
+ });
57535
+ object({
57536
+ columns: number().int().min(1).max(24),
57537
+ rows: number().int().min(1).max(24),
57538
+ buttons: array(RemoteLayoutButtonSchema).max(200)
57539
+ }).superRefine((grid, ctx) => {
57540
+ const ids = /* @__PURE__ */ new Set();
57541
+ const taken = /* @__PURE__ */ new Map();
57542
+ grid.buttons.forEach((button, index) => {
57543
+ if (ids.has(button.id)) ctx.addIssue({
57544
+ code: "custom",
57545
+ message: `button id "${button.id}" is used twice`,
57546
+ path: [
57547
+ "buttons",
57548
+ index,
57549
+ "id"
57550
+ ]
57551
+ });
57552
+ ids.add(button.id);
57553
+ if (button.row + button.rowSpan > grid.rows || button.col + button.colSpan > grid.columns) {
57554
+ ctx.addIssue({
57555
+ code: "custom",
57556
+ message: `button "${button.id}" leaves the grid`,
57557
+ path: ["buttons", index]
57558
+ });
57559
+ return;
57560
+ }
57561
+ for (let r = button.row; r < button.row + button.rowSpan; r += 1) for (let c = button.col; c < button.col + button.colSpan; c += 1) {
57562
+ const cell = `${r}:${c}`;
57563
+ const other = taken.get(cell);
57564
+ if (other !== void 0) {
57565
+ ctx.addIssue({
57566
+ code: "custom",
57567
+ message: `buttons "${other}" and "${button.id}" overlap`,
57568
+ path: ["buttons", index]
57569
+ });
57570
+ return;
57571
+ }
57572
+ taken.set(cell, button.id);
57573
+ }
57574
+ });
57575
+ });
57576
+ var RemoteBoundCommandSchema = object({
57577
+ role: RemoteRoleSchema,
57578
+ /** The operator's name for a custom button; absent for a known role. */
57579
+ label: string().optional(),
57580
+ custom: boolean()
57581
+ });
57582
+ var RemoteCommandListSchema = object({
57583
+ layoutTemplateId: string().nullable(),
57584
+ power: object({ mode: RemotePowerModeSchema }),
57585
+ /** Only the roles that are BOUND — the ones a press can reach. */
57586
+ commands: array(RemoteBoundCommandSchema)
57587
+ });
57588
+ var RemoteRefusalReasonSchema = _enum([
57589
+ "no-remote",
57590
+ "unbound-role",
57591
+ "action-failed"
57592
+ ]);
57593
+ var RemoteSendResultSchema = discriminatedUnion("status", [
57594
+ object({
57595
+ status: literal("sent"),
57596
+ /** How many times the action ran. */
57597
+ sends: number().int().min(1)
57598
+ }),
57599
+ object({
57600
+ status: literal("skipped"),
57601
+ reason: literal("already-in-state")
57602
+ }),
57603
+ object({
57604
+ status: literal("refused"),
57605
+ reason: RemoteRefusalReasonSchema,
57606
+ detail: string().optional()
57607
+ })
57608
+ ]);
57609
+ var RemoteMediaCommandSchema = _enum([
57610
+ "play",
57611
+ "pause",
57612
+ "stop",
57613
+ "next",
57614
+ "previous",
57615
+ "setMute",
57616
+ "selectSource"
57617
+ ]);
57618
+ /** A send result, or `not-routed`: the role is not bound, so the native cap answers. */
57619
+ var RemoteMediaCommandResultSchema = discriminatedUnion("status", [...RemoteSendResultSchema.options, object({ status: literal("not-routed") })]);
57620
+ var RemoteSetConfigResultSchema = discriminatedUnion("status", [object({ status: literal("saved") }), object({
57621
+ status: literal("refused"),
57622
+ reason: _enum(["unknown-template", "not-a-media-player"]),
57623
+ detail: string()
57624
+ })]);
57625
+ var deviceInput = object({ deviceId: number().int().nonnegative() });
57626
+ DeviceType.MediaPlayer;
57627
+ method(deviceInput, RemoteConfigSchema, { auth: "admin" }), method(deviceInput.extend({ config: RemoteConfigSchema }), RemoteSetConfigResultSchema, {
57628
+ kind: "mutation",
57629
+ auth: "admin"
57630
+ }), method(deviceInput, RemoteCommandListSchema, { auth: "protected" }), method(deviceInput.extend({
57631
+ role: RemoteRoleSchema,
57632
+ /** Sends in a row (volume steps). */
57633
+ repeat: number().int().min(1).max(50).default(1)
57634
+ }), RemoteSendResultSchema, {
57635
+ kind: "mutation",
57636
+ auth: "protected"
57637
+ }), method(deviceInput.extend({
57638
+ command: RemoteMediaCommandSchema,
57639
+ muted: boolean().optional(),
57640
+ source: string().optional(),
57641
+ repeat: number().int().min(1).max(50).default(1)
57642
+ }), RemoteMediaCommandResultSchema, {
57643
+ kind: "mutation",
57644
+ auth: "protected"
57645
+ });
57646
+ var TemplateKindSchema = _enum(["remote"]);
57647
+ /**
57648
+ * template — the generic store of reusable, named operator data (D963). A
57649
+ * record is `{ id, kind, name, payload }`; the kinds (today only `remote`, the
57650
+ * button grid of a remote) and the schema each payload must satisfy are
57651
+ * declared by the system in `template-kinds.ts`. Nothing here is specific to a
57652
+ * kind: the engine validates a payload against its kind's schema and, on a
57653
+ * delete, asks the kind's owner whether anything still points at the record.
57654
+ *
57655
+ * Every refusal is a typed result — a UI says "unknown kind" or names the
57656
+ * devices that still use a template, without parsing text.
57657
+ */
57658
+ var TemplateRecordSchema = object({
57659
+ id: string().min(1),
57660
+ kind: TemplateKindSchema,
57661
+ name: string().min(1).max(120),
57662
+ /** Shaped by the kind; `checkTemplatePayload(kind, payload)` reads it. */
57663
+ payload: unknown(),
57664
+ createdAt: number(),
57665
+ updatedAt: number()
57666
+ });
57667
+ var TemplateWriteResultSchema = discriminatedUnion("status", [object({
57668
+ status: literal("saved"),
57669
+ template: TemplateRecordSchema
57670
+ }), object({
57671
+ status: literal("refused"),
57672
+ reason: _enum(["invalid-payload", "not-found"]),
57673
+ detail: string()
57674
+ })]);
57675
+ /** A device still pointing at a template. */
57676
+ var TemplateUserSchema = object({
57677
+ deviceId: number().int().nonnegative(),
57678
+ name: string()
57679
+ });
57680
+ var TemplateDeleteResultSchema = discriminatedUnion("status", [
57681
+ object({ status: literal("deleted") }),
57682
+ object({ status: literal("not-found") }),
57683
+ object({
57684
+ status: literal("in-use"),
57685
+ devices: array(TemplateUserSchema).min(1)
57686
+ })
57687
+ ]);
57688
+ method(object({ kind: TemplateKindSchema.optional() }), array(TemplateRecordSchema), { auth: "protected" }), method(object({ id: string().min(1) }), TemplateRecordSchema.nullable(), { auth: "protected" }), method(object({
57689
+ kind: TemplateKindSchema,
57690
+ name: string().min(1).max(120),
57691
+ payload: unknown()
57692
+ }), TemplateWriteResultSchema, {
57693
+ kind: "mutation",
57694
+ auth: "admin"
57695
+ }), method(object({
57696
+ id: string().min(1),
57697
+ name: string().min(1).max(120).optional(),
57698
+ payload: unknown().optional()
57699
+ }), TemplateWriteResultSchema, {
57700
+ kind: "mutation",
57701
+ auth: "admin"
57702
+ }), method(object({ id: string().min(1) }), TemplateDeleteResultSchema, {
57703
+ kind: "mutation",
57704
+ auth: "admin"
57705
+ });
57366
57706
  DeviceType.Button, method(object({ deviceId: number().int().nonnegative() }), _void(), {
57367
57707
  kind: "mutation",
57368
57708
  auth: "protected"
@@ -60112,9 +60452,35 @@ var MediaInfoSchema = object({
60112
60452
  /** Optional cover-art / thumbnail URL. */
60113
60453
  imageUrl: string().optional()
60114
60454
  });
60455
+ /**
60456
+ * Where `state`, `volumeLevel`, `isMuted` and `source` come from. `reported`:
60457
+ * the device said so. `assumed`: the driver has no feedback (infrared) and
60458
+ * tracks what it last SENT; it moves only after a send was accepted, and a
60459
+ * human at the real remote makes it wrong. A UI shows an assumed value as a
60460
+ * guess, never as a reading.
60461
+ */
60462
+ var MediaPlayerStateSourceSchema = _enum(["reported", "assumed"]);
60463
+ /** The fields of a media-player status a driver can only guess. */
60464
+ var MediaPlayerAssumedFieldSchema = _enum([
60465
+ "state",
60466
+ "volumeLevel",
60467
+ "isMuted",
60468
+ "source"
60469
+ ]);
60115
60470
  object({
60116
60471
  /** Playback lifecycle state. */
60117
60472
  state: MediaPlayerStateSchema,
60473
+ /**
60474
+ * Whether the state fields are readings or the driver's own bookkeeping.
60475
+ * A slice written before this field existed parses as `reported`.
60476
+ */
60477
+ stateSource: MediaPlayerStateSourceSchema.default("reported"),
60478
+ /**
60479
+ * Which fields are the driver's own guess. `stateSource` is `assumed` when
60480
+ * this is not empty; a field not listed here is a reading even then (power
60481
+ * from a running-state source, mute guessed from the last send).
60482
+ */
60483
+ assumedFields: array(MediaPlayerAssumedFieldSchema).default([]),
60118
60484
  /** Volume as 0..100 inclusive. Null when the device has no volume
60119
60485
  * surface. Pair with `DeviceFeature.MediaPlayerVolume`. */
60120
60486
  volumeLevel: number().min(0).max(100).nullable().meta(readingMeta("percentage")),
@@ -61555,6 +61921,14 @@ object({
61555
61921
  feedSound: boolean(),
61556
61922
  /** Speaker / prompt volume level (device-scaled integer). */
61557
61923
  volume: number().meta(readingMeta("none")),
61924
+ /** Portion (grams) of the last manual feed sent from a single-hopper
61925
+ * stepper — the default the next manual feed starts from. Persisted per
61926
+ * device by the provider; null until a manual feed has been sent. */
61927
+ lastFeedGrams: gramsPortion.nullable(),
61928
+ /** Hopper-1 portion of the last manual feed (dual-hopper); null until sent. */
61929
+ lastFeedHopper1: gramsPortion.nullable(),
61930
+ /** Hopper-2 portion of the last manual feed (dual-hopper); null until sent. */
61931
+ lastFeedHopper2: gramsPortion.nullable(),
61558
61932
  /** Ms epoch when the slice was last refreshed from the cloud. */
61559
61933
  lastFetchedAt: number()
61560
61934
  });
@@ -66196,9 +66570,17 @@ method(object({}), array(TrainingBaseModelSchema).readonly(), { auth: "admin" })
66196
66570
  kind: "mutation",
66197
66571
  auth: "admin"
66198
66572
  });
66573
+ discriminatedUnion("kind", [object({
66574
+ kind: literal("raw"),
66575
+ timings: array(number().int()),
66576
+ settings: TransmitSettingsSchema.optional()
66577
+ }), object({
66578
+ kind: literal("pronto"),
66579
+ code: string()
66580
+ })]);
66199
66581
  DeviceFeature.FanSpeed, DeviceFeature.FanPreset, DeviceFeature.FanDirection, DeviceFeature.FanOscillating, DeviceFeature.CoverPositionable, DeviceFeature.CoverTilt, DeviceFeature.ValvePositionable, DeviceFeature.MediaPlayerVolume, DeviceFeature.ClimateFanMode;
66200
66582
  SOURCE_CAPS.filter((cap) => cap !== "switch" && cap !== "motion");
66201
- DeviceType.Camera, DeviceType.Sensor, DeviceType.Button, DeviceType.Switch, DeviceType.PetFeeder, DeviceType.Container, DeviceType.Thermostat, DeviceType.EventEmitter, DeviceType.Camera, DeviceType.Hub, DeviceType.Light, DeviceType.Siren, DeviceType.Switch, DeviceType.Sensor, DeviceType.Thermostat, DeviceType.Climate, DeviceType.Button, DeviceType.EventEmitter, DeviceType.Update, DeviceType.Generic, DeviceType.Notifier, DeviceType.Script, DeviceType.Automation, DeviceType.Lock, DeviceType.Cover, DeviceType.Valve, DeviceType.Humidifier, DeviceType.WaterHeater, DeviceType.Fan, DeviceType.MediaPlayer, DeviceType.AlarmPanel, DeviceType.Control, DeviceType.Presence, DeviceType.Weather, DeviceType.Vacuum, DeviceType.LawnMower, DeviceType.Container, DeviceType.Image, DeviceType.PetFeeder, DeviceType.Dishwasher, DeviceType.Washer, DeviceType.Dryer, DeviceType.Camera, DeviceType.Camera, DeviceType.Switch, DeviceType.Light, DeviceType.Fan, DeviceType.Climate, DeviceType.Thermostat, DeviceType.Humidifier, DeviceType.WaterHeater, DeviceType.MediaPlayer, DeviceType.Washer, DeviceType.Dryer, DeviceType.Dishwasher, DeviceType.Vacuum, DeviceType.LawnMower, DeviceType.PetFeeder, DeviceType.Switch, DeviceType.Light, DeviceType.Fan, DeviceType.Climate, DeviceType.Thermostat, DeviceType.Humidifier, DeviceType.WaterHeater, DeviceType.MediaPlayer, DeviceType.Washer, DeviceType.Dryer, DeviceType.Dishwasher, DeviceType.Vacuum, DeviceType.LawnMower, DeviceType.PetFeeder, DeviceType.Switch, DeviceType.Light, DeviceType.Fan, DeviceType.Climate, DeviceType.Thermostat, DeviceType.Humidifier, DeviceType.WaterHeater, DeviceType.MediaPlayer, DeviceType.Washer, DeviceType.Dryer, DeviceType.Dishwasher, DeviceType.Vacuum, DeviceType.LawnMower, DeviceType.PetFeeder, DeviceType.Switch, DeviceType.Light, DeviceType.Fan, DeviceType.Climate, DeviceType.Thermostat, DeviceType.Humidifier, DeviceType.WaterHeater, DeviceType.MediaPlayer, DeviceType.Washer, DeviceType.Dryer, DeviceType.Dishwasher, DeviceType.Vacuum, DeviceType.LawnMower, DeviceType.PetFeeder, DeviceType.Washer, DeviceType.Dryer, DeviceType.Dishwasher, DeviceType.Vacuum, DeviceType.LawnMower, DeviceType.MediaPlayer, DeviceType.WaterHeater, DeviceType.Humidifier, DeviceType.Fan, DeviceType.Climate, DeviceType.Thermostat, DeviceType.PetFeeder;
66583
+ DeviceType.Camera, DeviceType.Sensor, DeviceType.Button, DeviceType.Switch, DeviceType.PetFeeder, DeviceType.Container, DeviceType.Thermostat, DeviceType.EventEmitter, DeviceType.Camera, DeviceType.Hub, DeviceType.Light, DeviceType.Siren, DeviceType.Switch, DeviceType.Sensor, DeviceType.Thermostat, DeviceType.Climate, DeviceType.Button, DeviceType.EventEmitter, DeviceType.Update, DeviceType.Generic, DeviceType.Notifier, DeviceType.Script, DeviceType.Automation, DeviceType.Lock, DeviceType.Cover, DeviceType.Valve, DeviceType.Humidifier, DeviceType.WaterHeater, DeviceType.Fan, DeviceType.MediaPlayer, DeviceType.AlarmPanel, DeviceType.Control, DeviceType.Presence, DeviceType.Weather, DeviceType.Vacuum, DeviceType.LawnMower, DeviceType.Container, DeviceType.Image, DeviceType.PetFeeder, DeviceType.Dishwasher, DeviceType.Washer, DeviceType.Dryer, DeviceType.Camera, DeviceType.Camera, DeviceType.Switch, DeviceType.Light, DeviceType.Fan, DeviceType.Climate, DeviceType.Thermostat, DeviceType.Humidifier, DeviceType.WaterHeater, DeviceType.MediaPlayer, DeviceType.Washer, DeviceType.Dryer, DeviceType.Dishwasher, DeviceType.Vacuum, DeviceType.LawnMower, DeviceType.PetFeeder, DeviceType.Switch, DeviceType.Light, DeviceType.Fan, DeviceType.Climate, DeviceType.Thermostat, DeviceType.Humidifier, DeviceType.WaterHeater, DeviceType.MediaPlayer, DeviceType.Washer, DeviceType.Dryer, DeviceType.Dishwasher, DeviceType.Vacuum, DeviceType.LawnMower, DeviceType.PetFeeder, DeviceType.Switch, DeviceType.Light, DeviceType.Fan, DeviceType.Climate, DeviceType.Thermostat, DeviceType.Humidifier, DeviceType.WaterHeater, DeviceType.MediaPlayer, DeviceType.Washer, DeviceType.Dryer, DeviceType.Dishwasher, DeviceType.Vacuum, DeviceType.LawnMower, DeviceType.PetFeeder, DeviceType.Switch, DeviceType.Light, DeviceType.Fan, DeviceType.Climate, DeviceType.Thermostat, DeviceType.Humidifier, DeviceType.WaterHeater, DeviceType.MediaPlayer, DeviceType.Washer, DeviceType.Dryer, DeviceType.Dishwasher, DeviceType.Vacuum, DeviceType.LawnMower, DeviceType.PetFeeder, DeviceType.MediaPlayer, DeviceType.Washer, DeviceType.Dryer, DeviceType.Dishwasher, DeviceType.Vacuum, DeviceType.LawnMower, DeviceType.MediaPlayer, DeviceType.WaterHeater, DeviceType.Humidifier, DeviceType.Fan, DeviceType.Climate, DeviceType.Thermostat, DeviceType.PetFeeder;
66202
66584
  String.raw`rose\(active(\d+), changed(\d+), (\d+(?:\.\d+)?)\)`;
66203
66585
  DeviceRole.BinarySensor, DeviceRole.MotionSensor;
66204
66586
  new Set(CAP_NAMES);
@@ -71049,6 +71431,13 @@ Object.freeze({
71049
71431
  access: "create",
71050
71432
  role: "admin"
71051
71433
  },
71434
+ "nodeRemovalHook.onNodeRemoved": {
71435
+ capName: "node-removal-hook",
71436
+ capScope: "system",
71437
+ addonId: null,
71438
+ access: "create",
71439
+ role: "admin"
71440
+ },
71052
71441
  "nodes.clusterAddonStatus": {
71053
71442
  capName: "nodes",
71054
71443
  capScope: "system",
@@ -73940,6 +74329,41 @@ Object.freeze({
73940
74329
  access: "create",
73941
74330
  role: "admin"
73942
74331
  },
74332
+ "remote.getConfig": {
74333
+ capName: "remote",
74334
+ capScope: "system",
74335
+ addonId: null,
74336
+ access: "view",
74337
+ role: "admin"
74338
+ },
74339
+ "remote.listCommands": {
74340
+ capName: "remote",
74341
+ capScope: "system",
74342
+ addonId: null,
74343
+ access: "view",
74344
+ role: "admin"
74345
+ },
74346
+ "remote.sendCommand": {
74347
+ capName: "remote",
74348
+ capScope: "system",
74349
+ addonId: null,
74350
+ access: "create",
74351
+ role: "admin"
74352
+ },
74353
+ "remote.sendMediaCommand": {
74354
+ capName: "remote",
74355
+ capScope: "system",
74356
+ addonId: null,
74357
+ access: "create",
74358
+ role: "admin"
74359
+ },
74360
+ "remote.setConfig": {
74361
+ capName: "remote",
74362
+ capScope: "system",
74363
+ addonId: null,
74364
+ access: "create",
74365
+ role: "admin"
74366
+ },
73943
74367
  "runningState.getStatus": {
73944
74368
  capName: "running-state",
73945
74369
  capScope: "device",
@@ -75130,6 +75554,41 @@ Object.freeze({
75130
75554
  access: "view",
75131
75555
  role: "viewer"
75132
75556
  },
75557
+ "template.create": {
75558
+ capName: "template",
75559
+ capScope: "system",
75560
+ addonId: null,
75561
+ access: "create",
75562
+ role: "admin"
75563
+ },
75564
+ "template.delete": {
75565
+ capName: "template",
75566
+ capScope: "system",
75567
+ addonId: null,
75568
+ access: "delete",
75569
+ role: "admin"
75570
+ },
75571
+ "template.get": {
75572
+ capName: "template",
75573
+ capScope: "system",
75574
+ addonId: null,
75575
+ access: "view",
75576
+ role: "admin"
75577
+ },
75578
+ "template.list": {
75579
+ capName: "template",
75580
+ capScope: "system",
75581
+ addonId: null,
75582
+ access: "view",
75583
+ role: "admin"
75584
+ },
75585
+ "template.update": {
75586
+ capName: "template",
75587
+ capScope: "system",
75588
+ addonId: null,
75589
+ access: "create",
75590
+ role: "admin"
75591
+ },
75133
75592
  "terminalSession.adoptLegacyMonitor": {
75134
75593
  capName: "terminal-session",
75135
75594
  capScope: "system",
@@ -79922,6 +80381,7 @@ var SYSTEM_CAP_VOCABULARY = {
79922
80381
  "device-manager": system("the device registry itself — rename, move and remove are administration"),
79923
80382
  "device-provider": system(INTERNAL),
79924
80383
  "device-removal-hook": system(INTERNAL),
80384
+ "node-removal-hook": system(INTERNAL),
79925
80385
  "device-state": system("the runtime-state mirror every trigger already reads through"),
79926
80386
  "display-palette": system("the cluster display palette — one colour table for every client, not a device action"),
79927
80387
  "embedding-encoder": system(ML),
@@ -79961,6 +80421,7 @@ var SYSTEM_CAP_VOCABULARY = {
79961
80421
  "recording-archive": system(STORAGE),
79962
80422
  "recording-export": system("recording exports — requested from the timeline, not an automation step"),
79963
80423
  records: system(INTERNAL),
80424
+ remote: system("the per-device remote setup — authored in the Customize remote editor, sent through the remote UI"),
79964
80425
  "server-management": system(CLUSTER),
79965
80426
  "settings-store": system(INTERNAL),
79966
80427
  "smtp-provider": system(INTERNAL),
@@ -79973,6 +80434,7 @@ var SYSTEM_CAP_VOCABULARY = {
79973
80434
  "storage-provider": system(STORAGE),
79974
80435
  "stream-broker": system(PIPELINE),
79975
80436
  system: system(CLUSTER),
80437
+ template: system("operator-authored templates — edited in their own editor, never actuated"),
79976
80438
  "terminal-session": system(CLUSTER),
79977
80439
  toast: system(UI_PLUMBING),
79978
80440
  training: system(ML),
@@ -82399,6 +82861,31 @@ Object.freeze({
82399
82861
  form: "single",
82400
82862
  optional: true
82401
82863
  }],
82864
+ "remote.getConfig": [{
82865
+ name: "deviceId",
82866
+ form: "single",
82867
+ optional: false
82868
+ }],
82869
+ "remote.listCommands": [{
82870
+ name: "deviceId",
82871
+ form: "single",
82872
+ optional: false
82873
+ }],
82874
+ "remote.sendCommand": [{
82875
+ name: "deviceId",
82876
+ form: "single",
82877
+ optional: false
82878
+ }],
82879
+ "remote.sendMediaCommand": [{
82880
+ name: "deviceId",
82881
+ form: "single",
82882
+ optional: false
82883
+ }],
82884
+ "remote.setConfig": [{
82885
+ name: "deviceId",
82886
+ form: "single",
82887
+ optional: false
82888
+ }],
82402
82889
  "runningState.getStatus": [{
82403
82890
  name: "deviceId",
82404
82891
  form: "single",
@@ -84207,14 +84694,6 @@ DEFAULT_NATIVE_LEASE_SETTINGS.admission;
84207
84694
  String.raw`(?<=^|["'(\s>,\[{])`;
84208
84695
  var MB = 1024 * 1024;
84209
84696
  1024 * MB, 3072 * MB;
84210
- discriminatedUnion("kind", [object({
84211
- kind: literal("raw"),
84212
- timings: array(number().int()),
84213
- settings: TransmitSettingsSchema.optional()
84214
- }), object({
84215
- kind: literal("pronto"),
84216
- code: string()
84217
- })]);
84218
84697
  object({
84219
84698
  manufacturer: string().optional(),
84220
84699
  supportedModels: array(string()).optional(),
@@ -84244,7 +84723,7 @@ var AgentUIAddon = class extends BaseAddon {
84244
84723
  capability: adminUiCapability,
84245
84724
  provider: {
84246
84725
  getStaticDir: async () => ({ staticDir: path.resolve(__dirname) }),
84247
- getVersion: async () => ({ version: "1.2.289" })
84726
+ getVersion: async () => ({ version: "1.2.291" })
84248
84727
  }
84249
84728
  }];
84250
84729
  }