@camstack/addon-training 0.1.103 → 0.1.105

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.
Files changed (23) hide show
  1. package/CHANGELOG.md +12 -0
  2. package/dist/{MotionZonesSettings-HAJ6awj4.mjs → MotionZonesSettings-CTiGmTwm.mjs} +2 -2
  3. package/dist/{PrivacyMaskSettings-BF0NUmVm.mjs → PrivacyMaskSettings-evTcHeEU.mjs} +2 -2
  4. package/dist/{SceneMonitorEditor-CeEWTp0p.mjs → SceneMonitorEditor-C03Xg6cM.mjs} +2 -2
  5. package/dist/_stub.js +6578 -6515
  6. package/dist/{_virtual_mf-localSharedImportMap___mfe_internal__addon_training_page-T_zCH7zZ.mjs → _virtual_mf-localSharedImportMap___mfe_internal__addon_training_page-1sr2B1A2.mjs} +3 -3
  7. package/dist/_virtual_mf___mfe_internal__addon_training_page__loadShare___mf_0_camstack_mf_1_types__loadShare__.js-rMgUaeoj.mjs +26 -0
  8. package/dist/addon-training.css +1 -1
  9. package/dist/{dist-Cq0HT75H.js → dist-BhNuTgrA.js} +490 -11
  10. package/dist/{dist-BfxOw6-O.mjs → dist-CCRzGEk1.mjs} +490 -11
  11. package/dist/{hostInit-DRiiL3Ka.mjs → hostInit-Cxx4Eh3M.mjs} +2 -2
  12. package/dist/index.js +1 -1
  13. package/dist/orchestrator/training.addon.js +1 -1
  14. package/dist/orchestrator/training.addon.mjs +1 -1
  15. package/dist/{player-overlays-NVql0bBe.mjs → player-overlays-0haBt2oQ.mjs} +1 -1
  16. package/dist/providers/modal/training-modal.addon.js +1 -1
  17. package/dist/providers/modal/training-modal.addon.mjs +1 -1
  18. package/dist/remoteEntry.js +1 -1
  19. package/dist/{responsive-Cw10UV1G.mjs → responsive-BnXGZLBS.mjs} +1 -1
  20. package/dist/{scene-monitor-copy-BiaQA_PZ.mjs → scene-monitor-copy-Bh54RJt8.mjs} +1 -1
  21. package/dist/{virtual_mf-REMOTE_ENTRY_ID___mfe_internal__addon_training_page__remoteEntry_js-Bg8j40fX.mjs → virtual_mf-REMOTE_ENTRY_ID___mfe_internal__addon_training_page__remoteEntry_js-X8CJUTYR.mjs} +399 -390
  22. package/package.json +1 -1
  23. package/dist/_virtual_mf___mfe_internal__addon_training_page__loadShare___mf_0_camstack_mf_1_types__loadShare__.js-CLeWJI6-.mjs +0 -26
@@ -5613,7 +5613,7 @@ var ZodIssueCode = {
5613
5613
  var ZodFirstPartyTypeKind;
5614
5614
  ZodFirstPartyTypeKind || (ZodFirstPartyTypeKind = {});
5615
5615
  //#endregion
5616
- //#region ../types/dist/sleep-BAvUCi_2.mjs
5616
+ //#region ../types/dist/sleep-C_u6cEAJ.mjs
5617
5617
  /**
5618
5618
  * The audio chunk plane's byte format, and the ONE expansion from a coded
5619
5619
  * window to float samples (D455).
@@ -9024,6 +9024,7 @@ var CAP_NAMES = Object.freeze([
9024
9024
  "network-link",
9025
9025
  "network-quality",
9026
9026
  "node-certificates",
9027
+ "node-removal-hook",
9027
9028
  "nodes",
9028
9029
  "notification-output",
9029
9030
  "notification-rules",
@@ -9054,6 +9055,7 @@ var CAP_NAMES = Object.freeze([
9054
9055
  "recording-onboard",
9055
9056
  "recording-signal",
9056
9057
  "records",
9058
+ "remote",
9057
9059
  "running-state",
9058
9060
  "scene-monitor",
9059
9061
  "script-runner",
@@ -9077,6 +9079,7 @@ var CAP_NAMES = Object.freeze([
9077
9079
  "system",
9078
9080
  "tamper",
9079
9081
  "temperature-sensor",
9082
+ "template",
9080
9083
  "terminal-session",
9081
9084
  "toast",
9082
9085
  "training",
@@ -10017,6 +10020,11 @@ Object.freeze({
10017
10020
  "standby"
10018
10021
  ]
10019
10022
  },
10023
+ {
10024
+ "path": "stateSource",
10025
+ "valueType": "enum",
10026
+ "enumValues": ["reported", "assumed"]
10027
+ },
10020
10028
  {
10021
10029
  "path": "volumeLevel",
10022
10030
  "valueType": "number"
@@ -10292,6 +10300,18 @@ Object.freeze({
10292
10300
  {
10293
10301
  "path": "volume",
10294
10302
  "valueType": "number"
10303
+ },
10304
+ {
10305
+ "path": "lastFeedGrams",
10306
+ "valueType": "number"
10307
+ },
10308
+ {
10309
+ "path": "lastFeedHopper1",
10310
+ "valueType": "number"
10311
+ },
10312
+ {
10313
+ "path": "lastFeedHopper2",
10314
+ "valueType": "number"
10295
10315
  }
10296
10316
  ],
10297
10317
  "power-meter": [
@@ -11183,7 +11203,7 @@ var DeviceRole = /* @__PURE__ */ function(DeviceRole) {
11183
11203
  return DeviceRole;
11184
11204
  }({});
11185
11205
  //#endregion
11186
- //#region ../types/dist/composition-DpFv_J6D.mjs
11206
+ //#region ../types/dist/composition-bIBW5_13.mjs
11187
11207
  /**
11188
11208
  * The ffmpeg build every CamStack node downloads, per platform and arch.
11189
11209
  *
@@ -42781,6 +42801,14 @@ method(object({
42781
42801
  kind: "mutation",
42782
42802
  auth: "admin"
42783
42803
  });
42804
+ method(object({
42805
+ nodeId: string().min(1),
42806
+ /** Epoch ms the node was forgotten (the tombstone's `removedAt`). */
42807
+ removedAt: number()
42808
+ }), object({ counts: record(string(), number().int().nonnegative()) }), {
42809
+ kind: "mutation",
42810
+ auth: "admin"
42811
+ });
42784
42812
  /**
42785
42813
  * `device-removal-hook` — the reliable way an addon learns a device was DELETED,
42786
42814
  * so it can delete what it keeps for that device (D865).
@@ -57793,6 +57821,318 @@ DeviceType.Light, method(object({
57793
57821
  level: number().min(0).max(100),
57794
57822
  lastChangedAt: number()
57795
57823
  });
57824
+ /**
57825
+ * The role vocabulary of a remote (D963): what a button MEANS, independent of
57826
+ * how it is wired. A layout template places buttons by role; a device binds a
57827
+ * role to an action; an exporter asks for a role by name. Roles are shared so
57828
+ * one layout fits every appliance and one voice command fits every binding.
57829
+ *
57830
+ * A role outside this list is `custom:<key>` — the operator's own button (a
57831
+ * SmartIR source, a channel preset). The key is a lowercase slug.
57832
+ */
57833
+ var REMOTE_KNOWN_ROLES = [
57834
+ "power",
57835
+ "power_on",
57836
+ "power_off",
57837
+ "volume_up",
57838
+ "volume_down",
57839
+ "mute",
57840
+ "channel_up",
57841
+ "channel_down",
57842
+ "up",
57843
+ "down",
57844
+ "left",
57845
+ "right",
57846
+ "ok",
57847
+ "back",
57848
+ "home",
57849
+ "menu",
57850
+ "info",
57851
+ "guide",
57852
+ "exit",
57853
+ "input",
57854
+ "play",
57855
+ "pause",
57856
+ "play_pause",
57857
+ "stop",
57858
+ "next",
57859
+ "previous",
57860
+ "fast_forward",
57861
+ "rewind",
57862
+ "digit_0",
57863
+ "digit_1",
57864
+ "digit_2",
57865
+ "digit_3",
57866
+ "digit_4",
57867
+ "digit_5",
57868
+ "digit_6",
57869
+ "digit_7",
57870
+ "digit_8",
57871
+ "digit_9"
57872
+ ];
57873
+ var CUSTOM_KEY_RE = /^[a-z0-9][a-z0-9_]{0,47}$/;
57874
+ var KNOWN_ROLES = new Set(REMOTE_KNOWN_ROLES);
57875
+ function isRemoteKnownRole(value) {
57876
+ return KNOWN_ROLES.has(value);
57877
+ }
57878
+ function isRemoteCustomKey(key) {
57879
+ return CUSTOM_KEY_RE.test(key);
57880
+ }
57881
+ /** The key of a `custom:<key>` role, or null for any other string. */
57882
+ function customKeyOfRole(role) {
57883
+ if (!role.startsWith("custom:")) return null;
57884
+ const key = role.slice(7);
57885
+ return isRemoteCustomKey(key) ? key : null;
57886
+ }
57887
+ function isRemoteRole(value) {
57888
+ return isRemoteKnownRole(value) || customKeyOfRole(value) !== null;
57889
+ }
57890
+ var RemoteRoleSchema = string().refine(isRemoteRole, { message: "a role is one of the known roles or custom:<key> (lowercase letters, digits, _)" });
57891
+ var RemoteBindingSchema = object({ action: AutomationCapStepSchema.extend({ deviceId: number().int().nonnegative() }) });
57892
+ var RemoteCustomButtonSchema = object({
57893
+ /** The slug after `custom:` in the role. */
57894
+ key: string().refine(isRemoteCustomKey, { message: "a lowercase slug" }),
57895
+ /** What the operator calls it, and what a voice command may name. */
57896
+ name: string().min(1).max(60)
57897
+ });
57898
+ var RemotePowerModeSchema = _enum(["toggle", "discrete"]);
57899
+ var RemoteConfigSchema = object({
57900
+ layoutTemplateId: string().min(1).nullable(),
57901
+ /**
57902
+ * The transmitter device new bindings and an import send through. A binding
57903
+ * names its own device, so one command may override it.
57904
+ */
57905
+ defaultTransmitterId: number().int().nonnegative().nullable().default(null),
57906
+ /** Keyed by role. A role with no entry falls back to the native cap. */
57907
+ bindings: record(string(), RemoteBindingSchema),
57908
+ customButtons: array(RemoteCustomButtonSchema).max(100),
57909
+ power: object({ mode: RemotePowerModeSchema })
57910
+ }).superRefine((config, ctx) => {
57911
+ const roles = Object.keys(config.bindings);
57912
+ if (roles.length > 200) ctx.addIssue({
57913
+ code: "custom",
57914
+ message: "too many bindings",
57915
+ path: ["bindings"]
57916
+ });
57917
+ for (const role of roles) if (!isRemoteRole(role)) ctx.addIssue({
57918
+ code: "custom",
57919
+ message: `"${role}" is not a role`,
57920
+ path: ["bindings", role]
57921
+ });
57922
+ const keys = /* @__PURE__ */ new Set();
57923
+ config.customButtons.forEach((button, index) => {
57924
+ if (keys.has(button.key)) ctx.addIssue({
57925
+ code: "custom",
57926
+ message: `custom button "${button.key}" is listed twice`,
57927
+ path: [
57928
+ "customButtons",
57929
+ index,
57930
+ "key"
57931
+ ]
57932
+ });
57933
+ keys.add(button.key);
57934
+ });
57935
+ for (const role of roles) {
57936
+ const key = customKeyOfRole(role);
57937
+ if (key !== null && !keys.has(key)) ctx.addIssue({
57938
+ code: "custom",
57939
+ message: `${role} is bound but has no entry in customButtons`,
57940
+ path: ["bindings", role]
57941
+ });
57942
+ }
57943
+ });
57944
+ object({
57945
+ power: object({
57946
+ state: _enum(["on", "off"]),
57947
+ at: number()
57948
+ }).nullable(),
57949
+ muted: object({
57950
+ value: boolean(),
57951
+ at: number()
57952
+ }).nullable()
57953
+ });
57954
+ var RemoteLayoutButtonSchema = object({
57955
+ id: string().min(1).max(40),
57956
+ /** 0-based grid position. */
57957
+ row: number().int().min(0).max(24),
57958
+ col: number().int().min(0).max(24),
57959
+ rowSpan: number().int().min(1).max(24),
57960
+ colSpan: number().int().min(1).max(24),
57961
+ icon: string().min(1).max(60).optional(),
57962
+ label: string().min(1).max(40).optional(),
57963
+ role: RemoteRoleSchema
57964
+ });
57965
+ object({
57966
+ columns: number().int().min(1).max(24),
57967
+ rows: number().int().min(1).max(24),
57968
+ buttons: array(RemoteLayoutButtonSchema).max(200)
57969
+ }).superRefine((grid, ctx) => {
57970
+ const ids = /* @__PURE__ */ new Set();
57971
+ const taken = /* @__PURE__ */ new Map();
57972
+ grid.buttons.forEach((button, index) => {
57973
+ if (ids.has(button.id)) ctx.addIssue({
57974
+ code: "custom",
57975
+ message: `button id "${button.id}" is used twice`,
57976
+ path: [
57977
+ "buttons",
57978
+ index,
57979
+ "id"
57980
+ ]
57981
+ });
57982
+ ids.add(button.id);
57983
+ if (button.row + button.rowSpan > grid.rows || button.col + button.colSpan > grid.columns) {
57984
+ ctx.addIssue({
57985
+ code: "custom",
57986
+ message: `button "${button.id}" leaves the grid`,
57987
+ path: ["buttons", index]
57988
+ });
57989
+ return;
57990
+ }
57991
+ for (let r = button.row; r < button.row + button.rowSpan; r += 1) for (let c = button.col; c < button.col + button.colSpan; c += 1) {
57992
+ const cell = `${r}:${c}`;
57993
+ const other = taken.get(cell);
57994
+ if (other !== void 0) {
57995
+ ctx.addIssue({
57996
+ code: "custom",
57997
+ message: `buttons "${other}" and "${button.id}" overlap`,
57998
+ path: ["buttons", index]
57999
+ });
58000
+ return;
58001
+ }
58002
+ taken.set(cell, button.id);
58003
+ }
58004
+ });
58005
+ });
58006
+ var RemoteBoundCommandSchema = object({
58007
+ role: RemoteRoleSchema,
58008
+ /** The operator's name for a custom button; absent for a known role. */
58009
+ label: string().optional(),
58010
+ custom: boolean()
58011
+ });
58012
+ var RemoteCommandListSchema = object({
58013
+ layoutTemplateId: string().nullable(),
58014
+ power: object({ mode: RemotePowerModeSchema }),
58015
+ /** Only the roles that are BOUND — the ones a press can reach. */
58016
+ commands: array(RemoteBoundCommandSchema)
58017
+ });
58018
+ var RemoteRefusalReasonSchema = _enum([
58019
+ "no-remote",
58020
+ "unbound-role",
58021
+ "action-failed"
58022
+ ]);
58023
+ var RemoteSendResultSchema = discriminatedUnion("status", [
58024
+ object({
58025
+ status: literal("sent"),
58026
+ /** How many times the action ran. */
58027
+ sends: number().int().min(1)
58028
+ }),
58029
+ object({
58030
+ status: literal("skipped"),
58031
+ reason: literal("already-in-state")
58032
+ }),
58033
+ object({
58034
+ status: literal("refused"),
58035
+ reason: RemoteRefusalReasonSchema,
58036
+ detail: string().optional()
58037
+ })
58038
+ ]);
58039
+ var RemoteMediaCommandSchema = _enum([
58040
+ "play",
58041
+ "pause",
58042
+ "stop",
58043
+ "next",
58044
+ "previous",
58045
+ "setMute",
58046
+ "selectSource"
58047
+ ]);
58048
+ /** A send result, or `not-routed`: the role is not bound, so the native cap answers. */
58049
+ var RemoteMediaCommandResultSchema = discriminatedUnion("status", [...RemoteSendResultSchema.options, object({ status: literal("not-routed") })]);
58050
+ var RemoteSetConfigResultSchema = discriminatedUnion("status", [object({ status: literal("saved") }), object({
58051
+ status: literal("refused"),
58052
+ reason: _enum(["unknown-template", "not-a-media-player"]),
58053
+ detail: string()
58054
+ })]);
58055
+ var deviceInput = object({ deviceId: number().int().nonnegative() });
58056
+ DeviceType.MediaPlayer;
58057
+ method(deviceInput, RemoteConfigSchema, { auth: "admin" }), method(deviceInput.extend({ config: RemoteConfigSchema }), RemoteSetConfigResultSchema, {
58058
+ kind: "mutation",
58059
+ auth: "admin"
58060
+ }), method(deviceInput, RemoteCommandListSchema, { auth: "protected" }), method(deviceInput.extend({
58061
+ role: RemoteRoleSchema,
58062
+ /** Sends in a row (volume steps). */
58063
+ repeat: number().int().min(1).max(50).default(1)
58064
+ }), RemoteSendResultSchema, {
58065
+ kind: "mutation",
58066
+ auth: "protected"
58067
+ }), method(deviceInput.extend({
58068
+ command: RemoteMediaCommandSchema,
58069
+ muted: boolean().optional(),
58070
+ source: string().optional(),
58071
+ repeat: number().int().min(1).max(50).default(1)
58072
+ }), RemoteMediaCommandResultSchema, {
58073
+ kind: "mutation",
58074
+ auth: "protected"
58075
+ });
58076
+ var TemplateKindSchema = _enum(["remote"]);
58077
+ /**
58078
+ * template — the generic store of reusable, named operator data (D963). A
58079
+ * record is `{ id, kind, name, payload }`; the kinds (today only `remote`, the
58080
+ * button grid of a remote) and the schema each payload must satisfy are
58081
+ * declared by the system in `template-kinds.ts`. Nothing here is specific to a
58082
+ * kind: the engine validates a payload against its kind's schema and, on a
58083
+ * delete, asks the kind's owner whether anything still points at the record.
58084
+ *
58085
+ * Every refusal is a typed result — a UI says "unknown kind" or names the
58086
+ * devices that still use a template, without parsing text.
58087
+ */
58088
+ var TemplateRecordSchema = object({
58089
+ id: string().min(1),
58090
+ kind: TemplateKindSchema,
58091
+ name: string().min(1).max(120),
58092
+ /** Shaped by the kind; `checkTemplatePayload(kind, payload)` reads it. */
58093
+ payload: unknown(),
58094
+ createdAt: number(),
58095
+ updatedAt: number()
58096
+ });
58097
+ var TemplateWriteResultSchema = discriminatedUnion("status", [object({
58098
+ status: literal("saved"),
58099
+ template: TemplateRecordSchema
58100
+ }), object({
58101
+ status: literal("refused"),
58102
+ reason: _enum(["invalid-payload", "not-found"]),
58103
+ detail: string()
58104
+ })]);
58105
+ /** A device still pointing at a template. */
58106
+ var TemplateUserSchema = object({
58107
+ deviceId: number().int().nonnegative(),
58108
+ name: string()
58109
+ });
58110
+ var TemplateDeleteResultSchema = discriminatedUnion("status", [
58111
+ object({ status: literal("deleted") }),
58112
+ object({ status: literal("not-found") }),
58113
+ object({
58114
+ status: literal("in-use"),
58115
+ devices: array(TemplateUserSchema).min(1)
58116
+ })
58117
+ ]);
58118
+ method(object({ kind: TemplateKindSchema.optional() }), array(TemplateRecordSchema), { auth: "protected" }), method(object({ id: string().min(1) }), TemplateRecordSchema.nullable(), { auth: "protected" }), method(object({
58119
+ kind: TemplateKindSchema,
58120
+ name: string().min(1).max(120),
58121
+ payload: unknown()
58122
+ }), TemplateWriteResultSchema, {
58123
+ kind: "mutation",
58124
+ auth: "admin"
58125
+ }), method(object({
58126
+ id: string().min(1),
58127
+ name: string().min(1).max(120).optional(),
58128
+ payload: unknown().optional()
58129
+ }), TemplateWriteResultSchema, {
58130
+ kind: "mutation",
58131
+ auth: "admin"
58132
+ }), method(object({ id: string().min(1) }), TemplateDeleteResultSchema, {
58133
+ kind: "mutation",
58134
+ auth: "admin"
58135
+ });
57796
58136
  DeviceType.Button, method(object({ deviceId: number().int().nonnegative() }), _void(), {
57797
58137
  kind: "mutation",
57798
58138
  auth: "protected"
@@ -60542,9 +60882,35 @@ var MediaInfoSchema = object({
60542
60882
  /** Optional cover-art / thumbnail URL. */
60543
60883
  imageUrl: string().optional()
60544
60884
  });
60885
+ /**
60886
+ * Where `state`, `volumeLevel`, `isMuted` and `source` come from. `reported`:
60887
+ * the device said so. `assumed`: the driver has no feedback (infrared) and
60888
+ * tracks what it last SENT; it moves only after a send was accepted, and a
60889
+ * human at the real remote makes it wrong. A UI shows an assumed value as a
60890
+ * guess, never as a reading.
60891
+ */
60892
+ var MediaPlayerStateSourceSchema = _enum(["reported", "assumed"]);
60893
+ /** The fields of a media-player status a driver can only guess. */
60894
+ var MediaPlayerAssumedFieldSchema = _enum([
60895
+ "state",
60896
+ "volumeLevel",
60897
+ "isMuted",
60898
+ "source"
60899
+ ]);
60545
60900
  object({
60546
60901
  /** Playback lifecycle state. */
60547
60902
  state: MediaPlayerStateSchema,
60903
+ /**
60904
+ * Whether the state fields are readings or the driver's own bookkeeping.
60905
+ * A slice written before this field existed parses as `reported`.
60906
+ */
60907
+ stateSource: MediaPlayerStateSourceSchema.default("reported"),
60908
+ /**
60909
+ * Which fields are the driver's own guess. `stateSource` is `assumed` when
60910
+ * this is not empty; a field not listed here is a reading even then (power
60911
+ * from a running-state source, mute guessed from the last send).
60912
+ */
60913
+ assumedFields: array(MediaPlayerAssumedFieldSchema).default([]),
60548
60914
  /** Volume as 0..100 inclusive. Null when the device has no volume
60549
60915
  * surface. Pair with `DeviceFeature.MediaPlayerVolume`. */
60550
60916
  volumeLevel: number().min(0).max(100).nullable().meta(readingMeta("percentage")),
@@ -61985,6 +62351,14 @@ object({
61985
62351
  feedSound: boolean(),
61986
62352
  /** Speaker / prompt volume level (device-scaled integer). */
61987
62353
  volume: number().meta(readingMeta("none")),
62354
+ /** Portion (grams) of the last manual feed sent from a single-hopper
62355
+ * stepper — the default the next manual feed starts from. Persisted per
62356
+ * device by the provider; null until a manual feed has been sent. */
62357
+ lastFeedGrams: gramsPortion.nullable(),
62358
+ /** Hopper-1 portion of the last manual feed (dual-hopper); null until sent. */
62359
+ lastFeedHopper1: gramsPortion.nullable(),
62360
+ /** Hopper-2 portion of the last manual feed (dual-hopper); null until sent. */
62361
+ lastFeedHopper2: gramsPortion.nullable(),
61988
62362
  /** Ms epoch when the slice was last refreshed from the cloud. */
61989
62363
  lastFetchedAt: number()
61990
62364
  });
@@ -66728,9 +67102,17 @@ var trainingCapability = {
66728
67102
  })
66729
67103
  }
66730
67104
  };
67105
+ discriminatedUnion("kind", [object({
67106
+ kind: literal("raw"),
67107
+ timings: array(number().int()),
67108
+ settings: TransmitSettingsSchema.optional()
67109
+ }), object({
67110
+ kind: literal("pronto"),
67111
+ code: string()
67112
+ })]);
66731
67113
  DeviceFeature.FanSpeed, DeviceFeature.FanPreset, DeviceFeature.FanDirection, DeviceFeature.FanOscillating, DeviceFeature.CoverPositionable, DeviceFeature.CoverTilt, DeviceFeature.ValvePositionable, DeviceFeature.MediaPlayerVolume, DeviceFeature.ClimateFanMode;
66732
67114
  SOURCE_CAPS.filter((cap) => cap !== "switch" && cap !== "motion");
66733
- 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;
67115
+ 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;
66734
67116
  String.raw`rose\(active(\d+), changed(\d+), (\d+(?:\.\d+)?)\)`;
66735
67117
  DeviceRole.BinarySensor, DeviceRole.MotionSensor;
66736
67118
  new Set(CAP_NAMES);
@@ -71581,6 +71963,13 @@ Object.freeze({
71581
71963
  access: "create",
71582
71964
  role: "admin"
71583
71965
  },
71966
+ "nodeRemovalHook.onNodeRemoved": {
71967
+ capName: "node-removal-hook",
71968
+ capScope: "system",
71969
+ addonId: null,
71970
+ access: "create",
71971
+ role: "admin"
71972
+ },
71584
71973
  "nodes.clusterAddonStatus": {
71585
71974
  capName: "nodes",
71586
71975
  capScope: "system",
@@ -74472,6 +74861,41 @@ Object.freeze({
74472
74861
  access: "create",
74473
74862
  role: "admin"
74474
74863
  },
74864
+ "remote.getConfig": {
74865
+ capName: "remote",
74866
+ capScope: "system",
74867
+ addonId: null,
74868
+ access: "view",
74869
+ role: "admin"
74870
+ },
74871
+ "remote.listCommands": {
74872
+ capName: "remote",
74873
+ capScope: "system",
74874
+ addonId: null,
74875
+ access: "view",
74876
+ role: "admin"
74877
+ },
74878
+ "remote.sendCommand": {
74879
+ capName: "remote",
74880
+ capScope: "system",
74881
+ addonId: null,
74882
+ access: "create",
74883
+ role: "admin"
74884
+ },
74885
+ "remote.sendMediaCommand": {
74886
+ capName: "remote",
74887
+ capScope: "system",
74888
+ addonId: null,
74889
+ access: "create",
74890
+ role: "admin"
74891
+ },
74892
+ "remote.setConfig": {
74893
+ capName: "remote",
74894
+ capScope: "system",
74895
+ addonId: null,
74896
+ access: "create",
74897
+ role: "admin"
74898
+ },
74475
74899
  "runningState.getStatus": {
74476
74900
  capName: "running-state",
74477
74901
  capScope: "device",
@@ -75662,6 +76086,41 @@ Object.freeze({
75662
76086
  access: "view",
75663
76087
  role: "viewer"
75664
76088
  },
76089
+ "template.create": {
76090
+ capName: "template",
76091
+ capScope: "system",
76092
+ addonId: null,
76093
+ access: "create",
76094
+ role: "admin"
76095
+ },
76096
+ "template.delete": {
76097
+ capName: "template",
76098
+ capScope: "system",
76099
+ addonId: null,
76100
+ access: "delete",
76101
+ role: "admin"
76102
+ },
76103
+ "template.get": {
76104
+ capName: "template",
76105
+ capScope: "system",
76106
+ addonId: null,
76107
+ access: "view",
76108
+ role: "admin"
76109
+ },
76110
+ "template.list": {
76111
+ capName: "template",
76112
+ capScope: "system",
76113
+ addonId: null,
76114
+ access: "view",
76115
+ role: "admin"
76116
+ },
76117
+ "template.update": {
76118
+ capName: "template",
76119
+ capScope: "system",
76120
+ addonId: null,
76121
+ access: "create",
76122
+ role: "admin"
76123
+ },
75665
76124
  "terminalSession.adoptLegacyMonitor": {
75666
76125
  capName: "terminal-session",
75667
76126
  capScope: "system",
@@ -80454,6 +80913,7 @@ var SYSTEM_CAP_VOCABULARY = {
80454
80913
  "device-manager": system("the device registry itself — rename, move and remove are administration"),
80455
80914
  "device-provider": system(INTERNAL),
80456
80915
  "device-removal-hook": system(INTERNAL),
80916
+ "node-removal-hook": system(INTERNAL),
80457
80917
  "device-state": system("the runtime-state mirror every trigger already reads through"),
80458
80918
  "display-palette": system("the cluster display palette — one colour table for every client, not a device action"),
80459
80919
  "embedding-encoder": system(ML),
@@ -80493,6 +80953,7 @@ var SYSTEM_CAP_VOCABULARY = {
80493
80953
  "recording-archive": system(STORAGE),
80494
80954
  "recording-export": system("recording exports — requested from the timeline, not an automation step"),
80495
80955
  records: system(INTERNAL),
80956
+ remote: system("the per-device remote setup — authored in the Customize remote editor, sent through the remote UI"),
80496
80957
  "server-management": system(CLUSTER),
80497
80958
  "settings-store": system(INTERNAL),
80498
80959
  "smtp-provider": system(INTERNAL),
@@ -80505,6 +80966,7 @@ var SYSTEM_CAP_VOCABULARY = {
80505
80966
  "storage-provider": system(STORAGE),
80506
80967
  "stream-broker": system(PIPELINE),
80507
80968
  system: system(CLUSTER),
80969
+ template: system("operator-authored templates — edited in their own editor, never actuated"),
80508
80970
  "terminal-session": system(CLUSTER),
80509
80971
  toast: system(UI_PLUMBING),
80510
80972
  training: system(ML),
@@ -82931,6 +83393,31 @@ Object.freeze({
82931
83393
  form: "single",
82932
83394
  optional: true
82933
83395
  }],
83396
+ "remote.getConfig": [{
83397
+ name: "deviceId",
83398
+ form: "single",
83399
+ optional: false
83400
+ }],
83401
+ "remote.listCommands": [{
83402
+ name: "deviceId",
83403
+ form: "single",
83404
+ optional: false
83405
+ }],
83406
+ "remote.sendCommand": [{
83407
+ name: "deviceId",
83408
+ form: "single",
83409
+ optional: false
83410
+ }],
83411
+ "remote.sendMediaCommand": [{
83412
+ name: "deviceId",
83413
+ form: "single",
83414
+ optional: false
83415
+ }],
83416
+ "remote.setConfig": [{
83417
+ name: "deviceId",
83418
+ form: "single",
83419
+ optional: false
83420
+ }],
82934
83421
  "runningState.getStatus": [{
82935
83422
  name: "deviceId",
82936
83423
  form: "single",
@@ -84739,14 +85226,6 @@ DEFAULT_NATIVE_LEASE_SETTINGS.admission;
84739
85226
  String.raw`(?<=^|["'(\s>,\[{])`;
84740
85227
  var MB = 1024 * 1024;
84741
85228
  1024 * MB, 3072 * MB;
84742
- discriminatedUnion("kind", [object({
84743
- kind: literal("raw"),
84744
- timings: array(number().int()),
84745
- settings: TransmitSettingsSchema.optional()
84746
- }), object({
84747
- kind: literal("pronto"),
84748
- code: string()
84749
- })]);
84750
85229
  object({
84751
85230
  manufacturer: string().optional(),
84752
85231
  supportedModels: array(string()).optional(),