@camstack/addon-provider-homeassistant 1.2.633 → 1.2.635

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.
@@ -1,4 +1,4 @@
1
- //#region ../types/dist/event-category-CT-hz5Rb.mjs
1
+ //#region ../types/dist/event-category-DmZDPDf_.mjs
2
2
  var EventCategory = /* @__PURE__ */ function(EventCategory) {
3
3
  EventCategory["SystemBoot"] = "system.boot";
4
4
  EventCategory["SystemAddonsReady"] = "system.addons-ready";
@@ -625,7 +625,7 @@ var EventCategory = /* @__PURE__ */ function(EventCategory) {
625
625
  * (a track was promoted to a stationary-registry entry) or departs (the
626
626
  * object moved / was removed). Telemetry (D8): lossy, drives a UI refresh of
627
627
  * the dedicated "Stationary" section — never the live event feed. Payload:
628
- * `{ deviceId, entryId, className, phase:'appeared'|'departed', timestamp }`.
628
+ * `{ deviceId, entryId, className, phase:'appeared'|'departed', timestamp, observedAt, zones }`.
629
629
  */
630
630
  EventCategory["PipelineAnalyticsStationaryChanged"] = "pipeline-analytics.stationary-changed";
631
631
  /**
@@ -763,6 +763,11 @@ var EventCategory = /* @__PURE__ */ function(EventCategory) {
763
763
  */
764
764
  EventCategory["AccessoriesChanged"] = "accessories.onAccessoriesChanged";
765
765
  /**
766
+ * An action run started or ended. Emitted by the `actions` surface.
767
+ * Payload: `ActionRunChanged` (`{ actionId, runId, isRunning, outcome?, lastRunAt, lastError }`).
768
+ */
769
+ EventCategory["ActionsRunChanged"] = "actions.onRunChanged";
770
+ /**
766
771
  * Progress update from a running model conversion job.
767
772
  * Payload: `{ kind: 'model-convert', phase, sessionId?, pct?, detail? }`.
768
773
  * Emitted by `addon-model-studio` on the converting node.
@@ -5574,7 +5579,7 @@ var ZodIssueCode = {
5574
5579
  var ZodFirstPartyTypeKind;
5575
5580
  ZodFirstPartyTypeKind || (ZodFirstPartyTypeKind = {});
5576
5581
  //#endregion
5577
- //#region ../types/dist/sleep--jXS9hWo.mjs
5582
+ //#region ../types/dist/sleep-BAvUCi_2.mjs
5578
5583
  /**
5579
5584
  * The audio chunk plane's byte format, and the ONE expansion from a coded
5580
5585
  * window to float samples (D455).
@@ -8944,6 +8949,8 @@ Object.freeze({ "doorbell": "lastPressedAt" });
8944
8949
  /** Every capability name, so addon code can check a name without the schema graph. */
8945
8950
  var CAP_NAMES = Object.freeze([
8946
8951
  "accessories",
8952
+ "action-source",
8953
+ "actions",
8947
8954
  "addon-pages",
8948
8955
  "addon-pages-source",
8949
8956
  "addon-routes",
@@ -9027,6 +9034,7 @@ var CAP_NAMES = Object.freeze([
9027
9034
  "image-settings",
9028
9035
  "integrations",
9029
9036
  "intercom",
9037
+ "ir-transmitter",
9030
9038
  "keychain",
9031
9039
  "keychain-admin",
9032
9040
  "lawn-mower-control",
@@ -9132,11 +9140,11 @@ var CAP_NAMES = Object.freeze([
9132
9140
  Object.freeze({
9133
9141
  "air-quality-sensor": [
9134
9142
  {
9135
- "path": "co2Ppm",
9143
+ "path": "co2",
9136
9144
  "valueType": "number"
9137
9145
  },
9138
9146
  {
9139
- "path": "vocPpb",
9147
+ "path": "voc",
9140
9148
  "valueType": "number"
9141
9149
  },
9142
9150
  {
@@ -9186,7 +9194,7 @@ Object.freeze({
9186
9194
  }
9187
9195
  ],
9188
9196
  "ambient-light-sensor": [{
9189
- "path": "lux",
9197
+ "path": "illuminance",
9190
9198
  "valueType": "number"
9191
9199
  }],
9192
9200
  "audio-metrics": [
@@ -9247,7 +9255,7 @@ Object.freeze({
9247
9255
  ],
9248
9256
  "battery": [
9249
9257
  {
9250
- "path": "percentage",
9258
+ "path": "level",
9251
9259
  "valueType": "number"
9252
9260
  },
9253
9261
  {
@@ -9269,7 +9277,7 @@ Object.freeze({
9269
9277
  "valueType": "number"
9270
9278
  },
9271
9279
  {
9272
- "path": "volts",
9280
+ "path": "voltage",
9273
9281
  "valueType": "number"
9274
9282
  },
9275
9283
  {
@@ -9290,7 +9298,7 @@ Object.freeze({
9290
9298
  "valueType": "boolean"
9291
9299
  }],
9292
9300
  "brightness": [{
9293
- "path": "percentage",
9301
+ "path": "level",
9294
9302
  "valueType": "number"
9295
9303
  }],
9296
9304
  "broker": [{
@@ -9491,7 +9499,7 @@ Object.freeze({
9491
9499
  "valueType": "number"
9492
9500
  },
9493
9501
  {
9494
- "path": "mireds",
9502
+ "path": "colorTemperature",
9495
9503
  "valueType": "number"
9496
9504
  }
9497
9505
  ],
@@ -9670,15 +9678,15 @@ Object.freeze({
9670
9678
  "valueType": "string"
9671
9679
  },
9672
9680
  {
9673
- "path": "remainingSeconds",
9681
+ "path": "remaining",
9674
9682
  "valueType": "number"
9675
9683
  },
9676
9684
  {
9677
- "path": "delayedStartSeconds",
9685
+ "path": "delayedStart",
9678
9686
  "valueType": "number"
9679
9687
  },
9680
9688
  {
9681
- "path": "progressPercent",
9689
+ "path": "progress",
9682
9690
  "valueType": "number"
9683
9691
  },
9684
9692
  {
@@ -9792,7 +9800,7 @@ Object.freeze({
9792
9800
  ],
9793
9801
  "fan-control": [
9794
9802
  {
9795
- "path": "percentage",
9803
+ "path": "speed",
9796
9804
  "valueType": "number"
9797
9805
  },
9798
9806
  {
@@ -9892,7 +9900,7 @@ Object.freeze({
9892
9900
  }
9893
9901
  ],
9894
9902
  "humidity-sensor": [{
9895
- "path": "percent",
9903
+ "path": "humidity",
9896
9904
  "valueType": "number"
9897
9905
  }],
9898
9906
  "image": [{
@@ -10002,7 +10010,7 @@ Object.freeze({
10002
10010
  "valueType": "number"
10003
10011
  },
10004
10012
  {
10005
- "path": "progressPercent",
10013
+ "path": "progress",
10006
10014
  "valueType": "number"
10007
10015
  },
10008
10016
  {
@@ -10081,11 +10089,11 @@ Object.freeze({
10081
10089
  "valueType": "string"
10082
10090
  },
10083
10091
  {
10084
- "path": "positionMs",
10092
+ "path": "position",
10085
10093
  "valueType": "number"
10086
10094
  },
10087
10095
  {
10088
- "path": "durationMs",
10096
+ "path": "duration",
10089
10097
  "valueType": "number"
10090
10098
  },
10091
10099
  {
@@ -10187,11 +10195,11 @@ Object.freeze({
10187
10195
  ]
10188
10196
  },
10189
10197
  {
10190
- "path": "signalPercent",
10198
+ "path": "signal",
10191
10199
  "valueType": "number"
10192
10200
  },
10193
10201
  {
10194
- "path": "rssiDbm",
10202
+ "path": "rssi",
10195
10203
  "valueType": "number"
10196
10204
  },
10197
10205
  {
@@ -10246,6 +10254,18 @@ Object.freeze({
10246
10254
  "path": "foodLevel",
10247
10255
  "valueType": "number"
10248
10256
  },
10257
+ {
10258
+ "path": "bowlFood",
10259
+ "valueType": "number"
10260
+ },
10261
+ {
10262
+ "path": "eating",
10263
+ "valueType": "boolean"
10264
+ },
10265
+ {
10266
+ "path": "supportsMarkRefilled",
10267
+ "valueType": "boolean"
10268
+ },
10249
10269
  {
10250
10270
  "path": "food1",
10251
10271
  "valueType": "number"
@@ -10262,6 +10282,11 @@ Object.freeze({
10262
10282
  "path": "batteryPower",
10263
10283
  "valueType": "number"
10264
10284
  },
10285
+ {
10286
+ "path": "powerSource",
10287
+ "valueType": "enum",
10288
+ "enumValues": ["mains", "battery"]
10289
+ },
10265
10290
  {
10266
10291
  "path": "desiccantLeftDays",
10267
10292
  "valueType": "number"
@@ -10310,23 +10335,23 @@ Object.freeze({
10310
10335
  ],
10311
10336
  "power-meter": [
10312
10337
  {
10313
- "path": "watts",
10338
+ "path": "power",
10314
10339
  "valueType": "number"
10315
10340
  },
10316
10341
  {
10317
- "path": "kwhTotal",
10342
+ "path": "energy",
10318
10343
  "valueType": "number"
10319
10344
  },
10320
10345
  {
10321
- "path": "volts",
10346
+ "path": "voltage",
10322
10347
  "valueType": "number"
10323
10348
  },
10324
10349
  {
10325
- "path": "amps",
10350
+ "path": "current",
10326
10351
  "valueType": "number"
10327
10352
  },
10328
10353
  {
10329
- "path": "va",
10354
+ "path": "apparentPower",
10330
10355
  "valueType": "number"
10331
10356
  },
10332
10357
  {
@@ -10354,14 +10379,10 @@ Object.freeze({
10354
10379
  {
10355
10380
  "path": "gps.accuracyMeters",
10356
10381
  "valueType": "number"
10357
- },
10358
- {
10359
- "path": "batteryPercent",
10360
- "valueType": "number"
10361
10382
  }
10362
10383
  ],
10363
10384
  "pressure-sensor": [{
10364
- "path": "hpa",
10385
+ "path": "pressure",
10365
10386
  "valueType": "number"
10366
10387
  }],
10367
10388
  "privacy-mask": [{
@@ -10675,7 +10696,7 @@ Object.freeze({
10675
10696
  "valueType": "boolean"
10676
10697
  }],
10677
10698
  "temperature-sensor": [{
10678
- "path": "celsius",
10699
+ "path": "temperature",
10679
10700
  "valueType": "number"
10680
10701
  }],
10681
10702
  "update": [
@@ -10723,7 +10744,7 @@ Object.freeze({
10723
10744
  "valueType": "string"
10724
10745
  },
10725
10746
  {
10726
- "path": "progressPercent",
10747
+ "path": "progress",
10727
10748
  "valueType": "number"
10728
10749
  },
10729
10750
  {
@@ -10849,7 +10870,7 @@ object({
10849
10870
  params: record(string(), union([string(), number()])).optional()
10850
10871
  });
10851
10872
  //#endregion
10852
- //#region ../types/dist/err-msg-DIorGYeC.mjs
10873
+ //#region ../types/dist/err-msg-BCdlR2Li.mjs
10853
10874
  var DeviceType = /* @__PURE__ */ function(DeviceType) {
10854
10875
  DeviceType["Camera"] = "camera";
10855
10876
  DeviceType["Hub"] = "hub";
@@ -11195,6 +11216,9 @@ var DeviceRole = /* @__PURE__ */ function(DeviceRole) {
11195
11216
  /** Fallback when the notifier service name doesn't match a known
11196
11217
  * pattern. */
11197
11218
  DeviceRole["GenericNotifier"] = "generic-notifier";
11219
+ /** Emits a pulse train (infrared or RF) on request — the `ir-transmitter`
11220
+ * cap. A `DeviceType.Generic` device. */
11221
+ DeviceRole["IrTransmitter"] = "ir-transmitter";
11198
11222
  return DeviceRole;
11199
11223
  }({});
11200
11224
  /**
@@ -11208,7 +11232,7 @@ function errMsg(err) {
11208
11232
  return String(err);
11209
11233
  }
11210
11234
  //#endregion
11211
- //#region ../types/dist/composition-Bb8iwHEJ.mjs
11235
+ //#region ../types/dist/composition-DpFv_J6D.mjs
11212
11236
  /**
11213
11237
  * The ffmpeg build every CamStack node downloads, per platform and arch.
11214
11238
  *
@@ -15872,6 +15896,14 @@ var AutomationConditionLeafSchema = object({
15872
15896
  array(union([string(), number()]))
15873
15897
  ])
15874
15898
  });
15899
+ var AutomationConditionStationaryPresentSchema = object({
15900
+ kind: literal("stationary-present"),
15901
+ deviceId: number().int().nonnegative(),
15902
+ /** Class names; a macro class matches every raw class that maps to it. */
15903
+ classes: array(string().min(1)).min(1).optional(),
15904
+ /** The parked object must be in at least one of these zones. */
15905
+ zones: array(string().min(1)).min(1).optional()
15906
+ });
15875
15907
  /**
15876
15908
  * The expression leaf, declared as a plain object rather than an intersection
15877
15909
  * with {@link ExpressionSourceSchema}: a discriminated union has to be able to
@@ -15905,7 +15937,8 @@ var AutomationConditionSchema = lazy(() => discriminatedUnion("kind", [
15905
15937
  child: AutomationConditionSchema
15906
15938
  }),
15907
15939
  AutomationConditionLeafSchema,
15908
- AutomationConditionExpressionSchema
15940
+ AutomationConditionExpressionSchema,
15941
+ AutomationConditionStationaryPresentSchema
15909
15942
  ]));
15910
15943
  /**
15911
15944
  * What starts a run.
@@ -15946,7 +15979,34 @@ var AutomationTriggerSchema = discriminatedUnion("kind", [
15946
15979
  kind: literal("schedule"),
15947
15980
  cron: string().min(1).max(120)
15948
15981
  }),
15949
- object({ kind: literal("manual") })
15982
+ object({ kind: literal("manual") }),
15983
+ object({
15984
+ kind: literal("detection"),
15985
+ /** Class names. A macro class (`animal`, `vehicle`, `person`, `package`)
15986
+ * matches every raw class that maps to it; any other name matches
15987
+ * exactly. */
15988
+ classes: array(string().min(1)).min(1),
15989
+ deviceIds: array(number().int().nonnegative()).min(1),
15990
+ /** The track must have visited at least one of these zones. */
15991
+ zones: array(string().min(1)).min(1).optional(),
15992
+ /** Best-so-far confidence the track must reach. */
15993
+ minScore: number().min(0).max(1).optional()
15994
+ }),
15995
+ object({
15996
+ kind: literal("stationary"),
15997
+ deviceIds: array(number().int().nonnegative()).min(1),
15998
+ /** Class names; a macro class matches like the detection trigger. */
15999
+ classes: array(string().min(1)).min(1).optional(),
16000
+ /** The parked object must be in at least one of these zones. */
16001
+ zones: array(string().min(1)).min(1).optional(),
16002
+ /** `appeared`: it became parked. `departed`: the registry retired it.
16003
+ * The vocabulary of `PipelineAnalyticsStationaryChanged`. */
16004
+ phase: _enum(["appeared", "departed"])
16005
+ }),
16006
+ object({
16007
+ kind: literal("interval"),
16008
+ minutes: number().int().min(1).max(1440)
16009
+ })
15950
16010
  ]);
15951
16011
  /**
15952
16012
  * One action step.
@@ -15966,28 +16026,47 @@ var AutomationTriggerSchema = discriminatedUnion("kind", [
15966
16026
  * is called. The runner still receives a number and is untouched; the
15967
16027
  * resolution is the recipe's job, not the runner's.
15968
16028
  */
16029
+ var AutomationWaitStepSchema = object({
16030
+ kind: literal("wait"),
16031
+ seconds: number().min(0).max(300)
16032
+ });
16033
+ var AutomationCapStepSchema = object({
16034
+ kind: literal("cap"),
16035
+ /**
16036
+ * One device, several same-family devices (locks / climate family / …),
16037
+ * or `{ $var }` for the device that triggered the run. An array is
16038
+ * fan-out at codegen — each id gets the same cap.method call.
16039
+ */
16040
+ deviceId: union([
16041
+ number().int(),
16042
+ array(number().int()).min(1),
16043
+ object({ $var: string().min(1) })
16044
+ ]),
16045
+ cap: string().min(1),
16046
+ method: string().min(1),
16047
+ /** Values may carry `{{vars.x}}` slots, or be exactly `{ $var: 'name' }`, which
16048
+ * SUBSTITUTE and do not evaluate (§3.2.3). Anything beyond substitution is
16049
+ * the expression leaf. */
16050
+ args: record(string(), unknown()).optional()
16051
+ });
16052
+ /**
16053
+ * The steps an internal Action may contain: cap and wait, and nothing that can
16054
+ * call back into an Action — so an Action can never reach itself (no cycles).
16055
+ */
16056
+ var ActionStepSchema = discriminatedUnion("kind", [AutomationWaitStepSchema, AutomationCapStepSchema]);
15969
16057
  var AutomationActionSchema = discriminatedUnion("kind", [
16058
+ AutomationWaitStepSchema,
16059
+ AutomationCapStepSchema,
15970
16060
  object({
15971
- kind: literal("wait"),
15972
- seconds: number().min(0).max(300)
15973
- }),
15974
- object({
15975
- kind: literal("cap"),
15976
- /**
15977
- * One device, several same-family devices (locks / climate family / …),
15978
- * or `{ $var }` for the device that triggered the run. An array is
15979
- * fan-out at codegen — each id gets the same cap.method call.
15980
- */
15981
- deviceId: union([
15982
- number().int(),
15983
- array(number().int()).min(1),
15984
- object({ $var: string().min(1) })
15985
- ]),
15986
- cap: string().min(1),
15987
- method: string().min(1),
15988
- /** Values may carry `{{vars.x}}` slots, which SUBSTITUTE and do not
15989
- * evaluate (§3.2.3). Anything beyond substitution is the expression leaf. */
15990
- args: record(string(), unknown()).optional()
16061
+ kind: literal("action"),
16062
+ /** An entry of the `actions` surface (`internal:<uuid>` or `<addonId>:<localId>`). */
16063
+ actionId: string().min(1),
16064
+ /** Values for the action's declared variables; the others take their default. */
16065
+ variables: record(string(), union([
16066
+ string(),
16067
+ number(),
16068
+ boolean()
16069
+ ])).optional()
15991
16070
  }),
15992
16071
  object({
15993
16072
  kind: literal("code"),
@@ -15996,10 +16075,357 @@ var AutomationActionSchema = discriminatedUnion("kind", [
15996
16075
  code: string().min(1).max(2e4)
15997
16076
  })
15998
16077
  ]);
16078
+ /**
16079
+ * How a trigger that arrives while the automation is busy (or cooling down) is
16080
+ * handled. One of the automation's execution modes, never a property of its
16081
+ * actions. Absent means `single`.
16082
+ *
16083
+ * - `single` — drop the trigger while a run is in progress (traced + logged).
16084
+ * - `restart` — abort the run in progress (at its next step boundary), start fresh.
16085
+ * - `queued` — queue up to `max` triggers, drop the rest (traced).
16086
+ * - `parallel` — up to `max` runs at once, drop the rest (traced).
16087
+ * - `cooldown` — `single`, and no new run until `minutes` after the last run
16088
+ * STARTED; persisted across a restart. A manual trigger bypasses only this
16089
+ * wait, never the single/queued limits.
16090
+ */
16091
+ var AutomationRunModeSchema = discriminatedUnion("mode", [
16092
+ object({ mode: literal("single") }),
16093
+ object({ mode: literal("restart") }),
16094
+ object({
16095
+ mode: literal("queued"),
16096
+ max: number().int().min(1).max(10)
16097
+ }),
16098
+ object({
16099
+ mode: literal("parallel"),
16100
+ max: number().int().min(1).max(10)
16101
+ }),
16102
+ object({
16103
+ mode: literal("cooldown"),
16104
+ minutes: number().int().min(1).max(1440)
16105
+ })
16106
+ ]);
15999
16107
  var AutomationRecipeSchema = object({
16000
16108
  triggers: array(AutomationTriggerSchema),
16001
16109
  conditions: AutomationConditionSchema.optional(),
16002
- actions: array(AutomationActionSchema)
16110
+ actions: array(AutomationActionSchema),
16111
+ runMode: AutomationRunModeSchema.optional(),
16112
+ /** How many run traces the automation keeps (default {@link DEFAULT_TRACE_KEEP}). */
16113
+ keepTraces: number().int().min(1).max(100).optional()
16114
+ });
16115
+ new Set([
16116
+ {
16117
+ id: "person",
16118
+ name: "Person"
16119
+ },
16120
+ {
16121
+ id: "vehicle",
16122
+ name: "Vehicle"
16123
+ },
16124
+ {
16125
+ id: "animal",
16126
+ name: "Animal"
16127
+ },
16128
+ {
16129
+ id: "package",
16130
+ name: "Package"
16131
+ }
16132
+ ].map((l) => l.id));
16133
+ var COCO_TO_MACRO = {
16134
+ mapping: {
16135
+ person: "person",
16136
+ bicycle: "vehicle",
16137
+ car: "vehicle",
16138
+ motorcycle: "vehicle",
16139
+ airplane: "vehicle",
16140
+ bus: "vehicle",
16141
+ train: "vehicle",
16142
+ truck: "vehicle",
16143
+ boat: "vehicle",
16144
+ bird: "animal",
16145
+ cat: "animal",
16146
+ dog: "animal",
16147
+ horse: "animal",
16148
+ sheep: "animal",
16149
+ cow: "animal",
16150
+ elephant: "animal",
16151
+ bear: "animal",
16152
+ zebra: "animal",
16153
+ giraffe: "animal",
16154
+ suitcase: "package",
16155
+ backpack: "package",
16156
+ handbag: "package"
16157
+ },
16158
+ preserveOriginal: false
16159
+ };
16160
+ new Set(Object.values(COCO_TO_MACRO.mapping));
16161
+ /**
16162
+ * Run traces — what an automation (or, later, an Action run) DID, node by node,
16163
+ * so the editor can paint every block green or red with its reason.
16164
+ *
16165
+ * A trace is data, not a log: it covers the WHOLE tree — the trigger stage,
16166
+ * every condition node (containers and leaves, including the ones a
16167
+ * short-circuit never reached), the run-mode verdict and every action step —
16168
+ * each addressed by a stable path (`conditions.0.1`, `actions.2`, or `steps.N`
16169
+ * for an Action run). Skipped
16170
+ * evaluations are traced too, and identical consecutive skips collapse into a
16171
+ * repeat count so a trigger that fails every 5 minutes cannot flush real runs.
16172
+ *
16173
+ * {@link AutomationStepTraceSchema} is deliberately free of automation
16174
+ * vocabulary so an Action run records the same step shape.
16175
+ */
16176
+ /** A value a trace may show: JSON primitives and short lists, nothing deeper. */
16177
+ var TraceValueSchema = union([
16178
+ string(),
16179
+ number(),
16180
+ boolean(),
16181
+ _null(),
16182
+ array(union([string(), number()]))
16183
+ ]);
16184
+ var AutomationRunOutcomeSchema = _enum([
16185
+ "ran",
16186
+ "skipped-trigger",
16187
+ "skipped-conditions",
16188
+ "skipped-cooldown",
16189
+ "skipped-overlap",
16190
+ "failed",
16191
+ "aborted"
16192
+ ]);
16193
+ /** `not-evaluated` = a short-circuit never reached the node. */
16194
+ var TraceNodeOutcomeSchema = _enum([
16195
+ "pass",
16196
+ "fail",
16197
+ "not-evaluated"
16198
+ ]);
16199
+ var AutomationTriggerTraceSchema = object({
16200
+ kind: string().min(1),
16201
+ outcome: _enum(["pass", "fail"]),
16202
+ /** Why an event was rejected ("class person not in [dog]") or what fired. */
16203
+ reason: string(),
16204
+ /** deviceId, className, trackId, score … — only what the trigger exposes. */
16205
+ vars: record(string(), TraceValueSchema)
16206
+ });
16207
+ var AutomationConditionTraceNodeSchema = object({
16208
+ /** `conditions` for the root, `conditions.<i>` for its i-th child, … */
16209
+ path: string().min(1),
16210
+ kind: _enum([
16211
+ "all",
16212
+ "any",
16213
+ "not",
16214
+ "condition",
16215
+ "expression",
16216
+ "stationary-present"
16217
+ ]),
16218
+ outcome: TraceNodeOutcomeSchema,
16219
+ reason: string(),
16220
+ deviceId: number().int().optional(),
16221
+ cap: string().optional(),
16222
+ fieldPath: string().optional(),
16223
+ operator: string().optional(),
16224
+ expected: TraceValueSchema.optional(),
16225
+ /** What the mirror held; `null` when it held nothing (unknown). */
16226
+ observed: TraceValueSchema.optional()
16227
+ });
16228
+ var AutomationRunVerdictSchema = object({
16229
+ mode: AutomationRunModeSchema,
16230
+ decision: _enum([
16231
+ "run",
16232
+ "queued",
16233
+ "restart",
16234
+ "drop",
16235
+ "cooldown",
16236
+ "bypass"
16237
+ ]),
16238
+ reason: string()
16239
+ });
16240
+ /** One executed (or not-run) step — shared by automations and Action runs. */
16241
+ var AutomationStepTraceSchema = object({
16242
+ /** `actions.<i>` */
16243
+ path: string().min(1),
16244
+ kind: string().min(1),
16245
+ cap: string().optional(),
16246
+ method: string().optional(),
16247
+ deviceId: number().int().optional(),
16248
+ startedAt: number().optional(),
16249
+ endedAt: number().optional(),
16250
+ outcome: _enum([
16251
+ "ok",
16252
+ "error",
16253
+ "not-run"
16254
+ ]),
16255
+ message: string().optional()
16256
+ });
16257
+ var AutomationRunTraceSchema = object({
16258
+ runId: string().min(1),
16259
+ startedAt: number(),
16260
+ endedAt: number(),
16261
+ trigger: AutomationTriggerTraceSchema,
16262
+ conditions: array(AutomationConditionTraceNodeSchema),
16263
+ verdict: AutomationRunVerdictSchema.optional(),
16264
+ steps: array(AutomationStepTraceSchema),
16265
+ outcome: AutomationRunOutcomeSchema,
16266
+ /** How many identical consecutive skips this trace stands for (>= 1). */
16267
+ repeat: number().int().min(1),
16268
+ /** When the latest of those repeats happened. */
16269
+ lastAt: number()
16270
+ });
16271
+ /**
16272
+ * What the hub's `runs` ledger holds for one owner (`automation:<blockId>` or
16273
+ * `action:<actionId>`): the cooldown stamp and the trace ring.
16274
+ */
16275
+ var AutomationStateDocSchema = object({
16276
+ version: literal(1),
16277
+ lastRunStartedAt: number().nullable(),
16278
+ traces: array(AutomationRunTraceSchema)
16279
+ });
16280
+ /**
16281
+ * Actions — named, runnable things an operator (or an automation) can start,
16282
+ * declared as LIST ENTRIES, never as devices.
16283
+ *
16284
+ * An entry is either **internal** (a short list of cap/wait steps kept in the
16285
+ * hub's `actions` record kind) or declared by an addon through the
16286
+ * `action-source` collection (a Home Assistant script, a scene …). The one
16287
+ * surface the UI and automations talk to is the `actions` cap; it keeps no
16288
+ * catalog of its own (D3) — every `list` asks the providers live.
16289
+ *
16290
+ * This file is the data half: the entry schema, the variables an entry may
16291
+ * declare, and the pure resolution of the values a run was given. It holds no
16292
+ * runtime.
16293
+ */
16294
+ /** What a variable's value is. `select` takes one of `options`. */
16295
+ var ActionVariableTypeSchema = _enum([
16296
+ "string",
16297
+ "number",
16298
+ "boolean",
16299
+ "select"
16300
+ ]);
16301
+ var ACTION_VARIABLE_NAME_RE = /^[A-Za-z_][A-Za-z0-9_]*$/;
16302
+ var ActionVariableValueSchema = union([
16303
+ string(),
16304
+ number(),
16305
+ boolean()
16306
+ ]);
16307
+ /**
16308
+ * One declared variable. Steps reference it as `{ $var: 'name' }` (the whole
16309
+ * value) or `{{vars.name}}` (inside a string) in their args.
16310
+ */
16311
+ var ActionVariableSchema = object({
16312
+ name: string().regex(ACTION_VARIABLE_NAME_RE),
16313
+ label: string().min(1).max(120).optional(),
16314
+ type: ActionVariableTypeSchema,
16315
+ required: boolean().optional(),
16316
+ default: ActionVariableValueSchema.optional(),
16317
+ /** The allowed values of a `select`. */
16318
+ options: array(string().min(1)).min(1).optional()
16319
+ }).superRefine((v, ctx) => {
16320
+ if (v.type === "select" && v.options === void 0) ctx.addIssue({
16321
+ code: "custom",
16322
+ message: "a select variable needs options",
16323
+ path: ["options"]
16324
+ });
16325
+ if (v.default !== void 0 && variableValueError(v, v.default) !== null) ctx.addIssue({
16326
+ code: "custom",
16327
+ message: variableValueError(v, v.default) ?? "invalid default",
16328
+ path: ["default"]
16329
+ });
16330
+ });
16331
+ /** Why `value` is not a legal value for the variable, or null when it is. */
16332
+ function variableValueError(variable, value) {
16333
+ switch (variable.type) {
16334
+ case "string": return typeof value === "string" ? null : `variable "${variable.name}" must be a string`;
16335
+ case "number": return typeof value === "number" && Number.isFinite(value) ? null : `variable "${variable.name}" must be a number`;
16336
+ case "boolean": return typeof value === "boolean" ? null : `variable "${variable.name}" must be true or false`;
16337
+ case "select": return typeof value === "string" && (variable.options ?? []).includes(value) ? null : `variable "${variable.name}" must be one of ${(variable.options ?? []).join(", ")}`;
16338
+ }
16339
+ }
16340
+ var ActionSourceKindSchema = _enum(["internal", "addon"]);
16341
+ function isInternalActionId(actionId) {
16342
+ return actionId.startsWith("internal:") && actionId.length > 9;
16343
+ }
16344
+ /** The addon behind a `<addonId>:<localId>` id, or null for anything else (internal included). */
16345
+ function addonIdOfActionId(actionId) {
16346
+ if (isInternalActionId(actionId)) return null;
16347
+ const at = actionId.indexOf(":");
16348
+ return at > 0 && at < actionId.length - 1 ? actionId.slice(0, at) : null;
16349
+ }
16350
+ var ActionStatusSchema = object({
16351
+ isRunning: boolean(),
16352
+ /** Ms epoch the latest run STARTED; null when it never ran. */
16353
+ lastRunAt: number().nullable(),
16354
+ /** The latest run's failure; null on success or when it never ran. */
16355
+ lastError: string().nullable()
16356
+ });
16357
+ var ActionEntrySchema = object({
16358
+ /** `internal:<uuid>` or `<addonId>:<localId>`. */
16359
+ id: string().min(3),
16360
+ name: string().min(1).max(120),
16361
+ /** The addon that declared it; `core-blocks` for an internal one. */
16362
+ addonId: string().min(1),
16363
+ source: ActionSourceKindSchema,
16364
+ /** An addon-declared entry is edited where it was declared. */
16365
+ readOnly: boolean(),
16366
+ /** Internal only: cap and wait steps. No action-in-action, so no cycles. */
16367
+ steps: array(ActionStepSchema).min(1).max(50).optional(),
16368
+ variables: array(ActionVariableSchema).max(20).optional(),
16369
+ status: ActionStatusSchema
16370
+ }).superRefine((entry, ctx) => {
16371
+ if (entry.source === "internal") {
16372
+ if (!isInternalActionId(entry.id)) ctx.addIssue({
16373
+ code: "custom",
16374
+ message: "an internal action id is internal:<uuid>",
16375
+ path: ["id"]
16376
+ });
16377
+ return;
16378
+ }
16379
+ if (entry.steps !== void 0) ctx.addIssue({
16380
+ code: "custom",
16381
+ message: "only an internal action carries steps",
16382
+ path: ["steps"]
16383
+ });
16384
+ if (!entry.readOnly) ctx.addIssue({
16385
+ code: "custom",
16386
+ message: "an addon action is read-only here",
16387
+ path: ["readOnly"]
16388
+ });
16389
+ if (addonIdOfActionId(entry.id) === null) ctx.addIssue({
16390
+ code: "custom",
16391
+ message: "an addon action id is <addonId>:<localId>",
16392
+ path: ["id"]
16393
+ });
16394
+ });
16395
+ /** What an operator writes for an internal action. */
16396
+ var ActionInputSchema = object({
16397
+ name: string().min(1).max(120),
16398
+ steps: array(ActionStepSchema).min(1).max(50),
16399
+ variables: array(ActionVariableSchema).max(20).optional()
16400
+ });
16401
+ /** Who started a run. Absent = the operator pressed it. */
16402
+ var ActionRunOriginSchema = object({
16403
+ /** The automation block whose step started it. */
16404
+ blockId: string().min(1).optional() });
16405
+ /** `started` = the caller did not ask to wait. */
16406
+ var ActionRunOutcomeSchema = union([AutomationRunOutcomeSchema, literal("started")]);
16407
+ var ActionRunResultSchema = object({
16408
+ runId: string().min(1),
16409
+ outcome: ActionRunOutcomeSchema,
16410
+ /** Why it did not run, or what failed. */
16411
+ message: string().optional()
16412
+ });
16413
+ _enum([
16414
+ "not-found",
16415
+ "read-only",
16416
+ "invalid-variables",
16417
+ "invalid-steps",
16418
+ "not-linked",
16419
+ "busy"
16420
+ ]);
16421
+ object({
16422
+ actionId: string(),
16423
+ runId: string(),
16424
+ isRunning: boolean(),
16425
+ /** Set when the run ended. */
16426
+ outcome: AutomationRunOutcomeSchema.optional(),
16427
+ lastRunAt: number().nullable(),
16428
+ lastError: string().nullable()
16003
16429
  });
16004
16430
  /**
16005
16431
  * `addon-pages` — system-scoped singleton aggregator cap. Public-facing
@@ -18754,7 +19180,7 @@ var CompositionEventPlanSchema = object({
18754
19180
  stateField: string(),
18755
19181
  fieldKey: string()
18756
19182
  });
18757
- /** One refusal, named (D391). `path` points into the composition, e.g. `features[0].fields.celsius`. */
19183
+ /** One refusal, named (D391). `path` points into the composition, e.g. `features[0].fields.temperature`. */
18758
19184
  var CompositionProblemSchema = object({
18759
19185
  code: _enum([
18760
19186
  "reserved-variant",
@@ -19036,12 +19462,13 @@ var CHANGED = {
19036
19462
  expr: "now"
19037
19463
  };
19038
19464
  function numeric(input) {
19465
+ const { alsoFrom, ...base } = input;
19039
19466
  return {
19040
- ...input,
19467
+ ...base,
19041
19468
  family: "numeric",
19042
19469
  deviceType: DeviceType.Sensor,
19043
19470
  memberDeviceType: DeviceType.Sensor,
19044
- memberDeviceTypes: [DeviceType.Sensor],
19471
+ memberDeviceTypes: [DeviceType.Sensor, ...alsoFrom?.deviceTypes ?? []],
19045
19472
  activeWhen: void 0,
19046
19473
  commandCaps: [],
19047
19474
  baseUnit: baseUnitOf(input.quantity),
@@ -19049,9 +19476,10 @@ function numeric(input) {
19049
19476
  accept: [{
19050
19477
  cap: input.outputCap,
19051
19478
  fieldPath: input.outputField
19052
- }]
19479
+ }, ...alsoFrom === void 0 ? [] : [alsoFrom.accept]]
19053
19480
  };
19054
19481
  }
19482
+ var CLIMATE_DEVICES = [DeviceType.Thermostat, DeviceType.Climate];
19055
19483
  function binary(input) {
19056
19484
  return {
19057
19485
  ...input,
@@ -19073,29 +19501,43 @@ var GROUP_TEMPLATES = [
19073
19501
  summary: "Mean, median, min, max or sum of temperatures. Offline and unknown members are left out, never read as 0 °C.",
19074
19502
  role: DeviceRole.TemperatureSensor,
19075
19503
  outputCap: "temperature-sensor",
19076
- outputField: "celsius",
19504
+ outputField: "temperature",
19077
19505
  quantity: "temperature",
19078
19506
  defaultAggregate: "mean",
19079
19507
  empty: "null",
19080
- companions: [NOW$2]
19508
+ companions: [NOW$2],
19509
+ alsoFrom: {
19510
+ deviceTypes: CLIMATE_DEVICES,
19511
+ accept: {
19512
+ cap: "climate-control",
19513
+ fieldPath: "currentTemp"
19514
+ }
19515
+ }
19081
19516
  }),
19082
19517
  numeric({
19083
19518
  id: "humidity",
19084
19519
  summary: "Humidity in percent. Offline and unknown members are left out, never read as 0 %.",
19085
19520
  role: DeviceRole.HumiditySensor,
19086
19521
  outputCap: "humidity-sensor",
19087
- outputField: "percent",
19522
+ outputField: "humidity",
19088
19523
  quantity: "humidity",
19089
19524
  defaultAggregate: "mean",
19090
19525
  empty: "null",
19091
- companions: [NOW$2]
19526
+ companions: [NOW$2],
19527
+ alsoFrom: {
19528
+ deviceTypes: CLIMATE_DEVICES,
19529
+ accept: {
19530
+ cap: "climate-control",
19531
+ fieldPath: "currentHumidity"
19532
+ }
19533
+ }
19092
19534
  }),
19093
19535
  numeric({
19094
19536
  id: "pressure",
19095
19537
  summary: "Pressure in hectopascals. Offline and unknown members are left out, never read as 0 hPa.",
19096
19538
  role: DeviceRole.PressureSensor,
19097
19539
  outputCap: "pressure-sensor",
19098
- outputField: "hpa",
19540
+ outputField: "pressure",
19099
19541
  quantity: "pressure",
19100
19542
  defaultAggregate: "mean",
19101
19543
  empty: "null",
@@ -19106,7 +19548,7 @@ var GROUP_TEMPLATES = [
19106
19548
  summary: "Illuminance in lux. Offline and unknown members are left out, never read as 0 lx.",
19107
19549
  role: DeviceRole.AmbientLightSensor,
19108
19550
  outputCap: "ambient-light-sensor",
19109
- outputField: "lux",
19551
+ outputField: "illuminance",
19110
19552
  quantity: "illuminance",
19111
19553
  defaultAggregate: "mean",
19112
19554
  empty: "null",
@@ -19117,7 +19559,7 @@ var GROUP_TEMPLATES = [
19117
19559
  summary: "Power in watts, summed by default. Nobody reporting omits the key rather than writing 0 W.",
19118
19560
  role: DeviceRole.PowerSensor,
19119
19561
  outputCap: "power-meter",
19120
- outputField: "watts",
19562
+ outputField: "power",
19121
19563
  quantity: "power",
19122
19564
  defaultAggregate: "sum",
19123
19565
  empty: "omit",
@@ -19128,7 +19570,7 @@ var GROUP_TEMPLATES = [
19128
19570
  summary: "Energy in kilowatt-hours, summed by default. Nobody reporting omits the key rather than writing 0 kWh.",
19129
19571
  role: DeviceRole.EnergySensor,
19130
19572
  outputCap: "power-meter",
19131
- outputField: "kwhTotal",
19573
+ outputField: "energy",
19132
19574
  quantity: "energy",
19133
19575
  defaultAggregate: "sum",
19134
19576
  empty: "omit",
@@ -19139,7 +19581,7 @@ var GROUP_TEMPLATES = [
19139
19581
  summary: "Battery charge in percent. Offline and unknown members are left out, never read as 0 %.",
19140
19582
  role: DeviceRole.BatterySensor,
19141
19583
  outputCap: "battery",
19142
- outputField: "percentage",
19584
+ outputField: "level",
19143
19585
  quantity: "percentage",
19144
19586
  defaultAggregate: "mean",
19145
19587
  empty: "null",
@@ -19717,7 +20159,18 @@ method(object({}), object({ blocks: array(CoreBlockSchema) }), { auth: "admin" }
19717
20159
  kind: "mutation",
19718
20160
  auth: "admin",
19719
20161
  access: "view"
19720
- });
20162
+ }), method(object({
20163
+ blockId: string().min(1),
20164
+ trace: AutomationRunTraceSchema.optional(),
20165
+ runStartedAt: number().optional(),
20166
+ keepTraces: number().int().min(1).max(100).optional()
20167
+ }), _void(), {
20168
+ kind: "mutation",
20169
+ auth: "admin"
20170
+ }), method(object({ blockId: string().min(1) }), AutomationStateDocSchema, { auth: "admin" }), method(object({ blockId: string().min(1) }), object({
20171
+ traces: array(AutomationRunTraceSchema),
20172
+ lastError: string().nullable()
20173
+ }), { auth: "admin" });
19721
20174
  /**
19722
20175
  * `custom-model-registry` — collection cap exposing operator-registered
19723
20176
  * custom detection models. Each provider (today: `addon-model-studio`)
@@ -43750,6 +44203,17 @@ var LlmProfileSchema = object({
43750
44203
  * field in its editor only when its descriptor lists it in `profileFields`. */
43751
44204
  topK: number().int().positive().optional(),
43752
44205
  maxTokens: number().int().positive().optional(),
44206
+ /** How hard the model "thinks" before it answers. Omitted = the model's own
44207
+ * default. `off` matters for structured output: a thinking model can spend
44208
+ * the whole completion on reasoning and return an empty `content`. Carried
44209
+ * only by the wires that have it — a kind offers the field in its editor
44210
+ * only when its descriptor lists it in `profileFields`. */
44211
+ reasoningEffort: _enum([
44212
+ "off",
44213
+ "low",
44214
+ "medium",
44215
+ "high"
44216
+ ]).optional(),
43753
44217
  /** Prompt context window. Advisory for cloud kinds (they enforce their own). */
43754
44218
  contextLength: number().int().positive().optional(),
43755
44219
  /** Default system prompt. A caller's `system` REPLACES it (never appends —
@@ -43788,6 +44252,7 @@ var LlmProfileFieldSchema = _enum([
43788
44252
  "topP",
43789
44253
  "topK",
43790
44254
  "maxTokens",
44255
+ "reasoningEffort",
43791
44256
  "contextLength",
43792
44257
  "systemPrompt",
43793
44258
  "timeoutMs",
@@ -45038,6 +45503,43 @@ var NotificationActionSchema = object({
45038
45503
  */
45039
45504
  mode: _enum(["navigate", "background"]).optional()
45040
45505
  });
45506
+ /** A delivery parameter value: what a notifier declared it takes. */
45507
+ var DeliveryParamValueSchema = union([
45508
+ string(),
45509
+ number(),
45510
+ boolean()
45511
+ ]);
45512
+ /**
45513
+ * One extra delivery parameter a notifier KIND declares (D938). A rule that
45514
+ * addresses a target of that kind may set it; a kind that declares nothing is
45515
+ * never handed one. The admin UI derives its control from this descriptor —
45516
+ * no editor knows a service by name.
45517
+ *
45518
+ * Optional fields are `.optional()`, never `.default()` (a Zod default does not
45519
+ * run on the addon cap path).
45520
+ */
45521
+ var DeliveryParamSchema = object({
45522
+ key: string().min(1),
45523
+ label: string(),
45524
+ /** i18n key of the label, resolved by the declaring addon's namespace. */
45525
+ labelKey: string().optional(),
45526
+ type: _enum([
45527
+ "enum",
45528
+ "number",
45529
+ "boolean",
45530
+ "string"
45531
+ ]),
45532
+ /** `enum` only: the closed set of accepted values. */
45533
+ options: array(object({
45534
+ value: string(),
45535
+ label: string()
45536
+ })).optional(),
45537
+ /** `number` only. */
45538
+ min: number().optional(),
45539
+ max: number().optional(),
45540
+ /** What the notifier does when the rule sets nothing; shown as the placeholder. */
45541
+ default: DeliveryParamValueSchema.optional()
45542
+ });
45041
45543
  /**
45042
45544
  * The canonical notification. `body` is the only hard field (Apprise model).
45043
45545
  * `priority` is a 5-level ORDINAL (1=lowest … 3=normal(default) … 5=urgent),
@@ -45060,7 +45562,13 @@ var NotificationSchema = object({
45060
45562
  tag: string().optional(),
45061
45563
  deviceId: number().optional(),
45062
45564
  eventId: string().optional(),
45063
- metadata: record(string(), unknown()).optional()
45565
+ metadata: record(string(), unknown()).optional(),
45566
+ /**
45567
+ * Values for the parameters the target's kind DECLARES in
45568
+ * {@link TargetKindSchema} `deliveryParams`. Already validated against the
45569
+ * declaration by the sender; a notifier reads only the keys it declared.
45570
+ */
45571
+ delivery: record(string(), DeliveryParamValueSchema).optional()
45064
45572
  });
45065
45573
  /** One declared native severity/priority level for a kind. */
45066
45574
  var TargetKindLevelSchema = object({
@@ -45166,6 +45674,11 @@ var TargetKindSchema = object({
45166
45674
  */
45167
45675
  destinationKeys: array(string()).optional(),
45168
45676
  supportsDiscovery: boolean(),
45677
+ /**
45678
+ * Extra delivery parameters a rule may set for a target of this kind (D938).
45679
+ * Absent = none; the rule editor then offers nothing.
45680
+ */
45681
+ deliveryParams: array(DeliveryParamSchema).optional(),
45169
45682
  caps: TargetKindCapsSchema
45170
45683
  });
45171
45684
  /**
@@ -45287,51 +45800,6 @@ var notificationOutputCapability = {
45287
45800
  })
45288
45801
  }
45289
45802
  };
45290
- new Set([
45291
- {
45292
- id: "person",
45293
- name: "Person"
45294
- },
45295
- {
45296
- id: "vehicle",
45297
- name: "Vehicle"
45298
- },
45299
- {
45300
- id: "animal",
45301
- name: "Animal"
45302
- },
45303
- {
45304
- id: "package",
45305
- name: "Package"
45306
- }
45307
- ].map((l) => l.id));
45308
- var COCO_TO_MACRO = {
45309
- mapping: {
45310
- person: "person",
45311
- bicycle: "vehicle",
45312
- car: "vehicle",
45313
- motorcycle: "vehicle",
45314
- airplane: "vehicle",
45315
- bus: "vehicle",
45316
- train: "vehicle",
45317
- truck: "vehicle",
45318
- boat: "vehicle",
45319
- bird: "animal",
45320
- cat: "animal",
45321
- dog: "animal",
45322
- horse: "animal",
45323
- sheep: "animal",
45324
- cow: "animal",
45325
- elephant: "animal",
45326
- bear: "animal",
45327
- zebra: "animal",
45328
- giraffe: "animal",
45329
- suitcase: "package",
45330
- backpack: "package",
45331
- handbag: "package"
45332
- },
45333
- preserveOriginal: false
45334
- };
45335
45803
  var AUDIO_MACRO_LABELS = [
45336
45804
  {
45337
45805
  id: "speech",
@@ -57612,7 +58080,9 @@ var ManifestShapeSchema = object({
57612
58080
  icon: string().optional()
57613
58081
  }).optional(),
57614
58082
  protected: boolean().optional(),
57615
- removable: boolean().optional()
58083
+ removable: boolean().optional(),
58084
+ /** Declared Integrations-page block (mirror of `AddonDeclaration.integrationSection`). */
58085
+ integrationSection: _enum(["system", "providers"]).optional()
57616
58086
  });
57617
58087
  var AddonProcessSchema = object({
57618
58088
  pid: number().optional(),
@@ -57986,9 +58456,9 @@ method(object({ nodeId: string().optional() }).optional(), array(AddonListItemSc
57986
58456
  */
57987
58457
  var AirQualitySensorStatusSchema = object({
57988
58458
  /** Carbon dioxide concentration in ppm. */
57989
- co2Ppm: number().min(0).optional().meta(readingMeta("concentration-volume")),
58459
+ co2: number().min(0).optional().meta(readingMeta("concentration-volume")),
57990
58460
  /** Total volatile organic compounds in ppb. */
57991
- vocPpb: number().min(0).optional().meta(readingMeta("concentration-ppb")),
58461
+ voc: number().min(0).optional().meta(readingMeta("concentration-ppb")),
57992
58462
  /** Particulate matter ≤ 2.5 μm in µg/m³. */
57993
58463
  pm25: number().min(0).optional().meta(readingMeta("concentration-mass")),
57994
58464
  /** Particulate matter ≤ 10 μm in µg/m³. */
@@ -58021,12 +58491,12 @@ var airQualitySensorCapability = {
58021
58491
  * History (D850): recorded series.
58022
58492
  */
58023
58493
  history: { fields: {
58024
- co2Ppm: {
58494
+ co2: {
58025
58495
  kind: "gauge",
58026
58496
  unit: "ppm",
58027
58497
  deadband: 5
58028
58498
  },
58029
- vocPpb: {
58499
+ voc: {
58030
58500
  kind: "gauge",
58031
58501
  unit: "ppb",
58032
58502
  deadband: 5
@@ -58057,7 +58527,7 @@ var airQualitySensorCapability = {
58057
58527
  */
58058
58528
  var AmbientLightSensorStatusSchema = object({
58059
58529
  /** Current illuminance in lux (lx). `null` when the sample was refused (D393). */
58060
- lux: number().min(0).nullable().meta(readingMeta("illuminance", {
58530
+ illuminance: number().min(0).nullable().meta(readingMeta("illuminance", {
58061
58531
  precision: 0,
58062
58532
  label: "Illuminance"
58063
58533
  })),
@@ -58086,7 +58556,7 @@ var ambientLightSensorCapability = {
58086
58556
  /**
58087
58557
  * History (D850): recorded series. Wide range, so a RELATIVE deadband (10 %).
58088
58558
  */
58089
- history: { fields: { lux: {
58559
+ history: { fields: { illuminance: {
58090
58560
  kind: "gauge",
58091
58561
  unit: "lx",
58092
58562
  deadbandPct: 10,
@@ -58225,6 +58695,84 @@ var audioMetricsCapability = {
58225
58695
  */
58226
58696
  history: "none"
58227
58697
  };
58698
+ method(object({}), array(ActionEntrySchema), { auth: "admin" }), method(object({
58699
+ actionId: string().min(1),
58700
+ variables: record(string(), ActionVariableValueSchema).optional()
58701
+ }), _void(), {
58702
+ kind: "mutation",
58703
+ auth: "admin"
58704
+ }), method(object({ actionId: string().min(1) }), _void(), {
58705
+ kind: "mutation",
58706
+ auth: "admin"
58707
+ });
58708
+ /**
58709
+ * actions — the ONE surface for runnable actions, for the UI and for
58710
+ * automations. Provided by the core-blocks builtin on the hub.
58711
+ *
58712
+ * An action is a LIST ENTRY, not a device (D883): either internal (cap and wait
58713
+ * steps, kept in the hub's `actions` record kind) or declared by an addon over
58714
+ * `action-source`. `list` asks every `action-source` provider LIVE and overlays
58715
+ * the run status from the hub's `runs` ledger; there is no catalog here to
58716
+ * drift (D3).
58717
+ *
58718
+ * **Permissions follow the camera, as linked devices do.** An action is linked
58719
+ * to cameras by the operator (`setLinks`, D356: nothing links itself). A
58720
+ * non-admin may `get` / `run` an action only through a camera they may see that
58721
+ * links it: they name the camera (`deviceId`, a top-level field so the scope
58722
+ * gate sees it) and the provider refuses an action that camera does not link.
58723
+ * An admin, and an in-process caller (an automation block), may run any action.
58724
+ * Every refusal is typed (`[not-linked] …`) and logged.
58725
+ *
58726
+ * A second `run` of an action that is already running is REFUSED — traced and
58727
+ * logged — never queued.
58728
+ */
58729
+ var ActionIdInput = object({ actionId: string().min(1) });
58730
+ var ActionLinksSchema = object({
58731
+ deviceId: number().int().nonnegative(),
58732
+ actionIds: array(string().min(1)).max(100)
58733
+ });
58734
+ method(object({}), array(ActionEntrySchema), { auth: "admin" }), method(object({
58735
+ actionId: string().min(1),
58736
+ deviceId: number().int().nonnegative().optional()
58737
+ }), object({ action: ActionEntrySchema.nullable() }), {
58738
+ role: "viewer",
58739
+ auth: "protected",
58740
+ kind: "query",
58741
+ caller: "required"
58742
+ }), method(object({
58743
+ actionId: string().min(1),
58744
+ variables: record(string(), ActionVariableValueSchema).optional(),
58745
+ wait: boolean().optional(),
58746
+ origin: ActionRunOriginSchema.optional(),
58747
+ deviceId: number().int().nonnegative().optional()
58748
+ }), ActionRunResultSchema, {
58749
+ role: "viewer",
58750
+ auth: "protected",
58751
+ kind: "mutation",
58752
+ caller: "required"
58753
+ }), method(ActionIdInput, _void(), {
58754
+ kind: "mutation",
58755
+ auth: "admin"
58756
+ }), method(ActionIdInput, object({ traces: array(AutomationRunTraceSchema) }), { auth: "admin" }), method(object({ action: ActionInputSchema }), object({ action: ActionEntrySchema }), {
58757
+ kind: "mutation",
58758
+ auth: "admin"
58759
+ }), method(object({
58760
+ actionId: string().min(1),
58761
+ action: ActionInputSchema.partial()
58762
+ }), object({ action: ActionEntrySchema }), {
58763
+ kind: "mutation",
58764
+ auth: "admin"
58765
+ }), method(ActionIdInput, _void(), {
58766
+ kind: "mutation",
58767
+ auth: "admin"
58768
+ }), method(object({ deviceId: number().int().nonnegative() }), array(ActionEntrySchema), {
58769
+ role: "viewer",
58770
+ auth: "protected",
58771
+ kind: "query"
58772
+ }), method(object({ deviceId: number().int().nonnegative() }), ActionLinksSchema, { auth: "admin" }), method(ActionLinksSchema, ActionLinksSchema, {
58773
+ kind: "mutation",
58774
+ auth: "admin"
58775
+ });
58228
58776
  /**
58229
58777
  * Automation-control cap. Models HA `automation.*` entities on
58230
58778
  * `DeviceType.Automation`. An automation is a trigger+condition+
@@ -58321,7 +58869,7 @@ var BatteryStatusSchema = object({
58321
58869
  * Consumers must SKIP a null rather than coerce it — `battery-band` already
58322
58870
  * declines to band a non-finite reading, which is the correct shape.
58323
58871
  */
58324
- percentage: number().min(0).max(100).nullable().meta(readingMeta("percentage", { label: "Charge" })),
58872
+ level: number().min(0).max(100).nullable().meta(readingMeta("percentage", { label: "Charge" })),
58325
58873
  /**
58326
58874
  * Charging source. `'dc'` covers wall/USB adapters; `'solar'` is
58327
58875
  * Reolink-specific for the Solar Panel 2 accessory (will become
@@ -58331,7 +58879,7 @@ var BatteryStatusSchema = object({
58331
58879
  * `'unknown'` is the absence of an answer: the provider has not read the
58332
58880
  * power fields yet, or the firmware reported neither. Before it existed,
58333
58881
  * two unreadable fields produced `'none'`, and a camera nobody had reached
58334
- * was drawn "on battery alone" — the same D315 defect `percentage` closed
58882
+ * was drawn "on battery alone" — the same D315 defect `level` closed
58335
58883
  * by going nullable. Consumers SKIP it (no charger state published, no
58336
58884
  * glyph, no HomeKit ChargingState) rather than coerce it either way.
58337
58885
  */
@@ -58355,7 +58903,7 @@ var BatteryStatusSchema = object({
58355
58903
  * that only report charge. A second reading on this cap, not a second
58356
58904
  * `numeric-sensor` on the same device.
58357
58905
  */
58358
- volts: number().nullable().optional().meta(readingMeta("voltage", { label: "Voltage" })),
58906
+ voltage: number().nullable().optional().meta(readingMeta("voltage", { label: "Voltage" })),
58359
58907
  /**
58360
58908
  * Ms epoch of the last time the device PROVED it was reachable — a
58361
58909
  * completed firmware round-trip, an observed wake, or an inbound push
@@ -58389,7 +58937,7 @@ var BatteryStatusSchema = object({
58389
58937
  /**
58390
58938
  * True when the source is a BINARY low-battery indicator (HA
58391
58939
  * `binary_sensor` device_class=battery / `LOW_BAT`) that has no real
58392
- * charge level — `percentage` is then a coarse stand-in (100 = normal,
58940
+ * charge level — `level` is then a coarse stand-in (100 = normal,
58393
58941
  * sub-threshold = low). UI MUST render "Normal"/"Low" instead of a
58394
58942
  * misleading exact percentage. Absent/false → genuine 0–100 % reading.
58395
58943
  */
@@ -58409,15 +58957,15 @@ var BATTERY_DEVICE_TYPES = [
58409
58957
  var batteryCustomize = {
58410
58958
  version: 1,
58411
58959
  targets: [{
58412
- id: "percentage",
58960
+ id: "level",
58413
58961
  cardinality: "scalar",
58414
58962
  vocabulary: {
58415
58963
  cap: "battery",
58416
- stateField: "percentage"
58964
+ stateField: "level"
58417
58965
  },
58418
58966
  deviceTypes: BATTERY_DEVICE_TYPES,
58419
58967
  apply: "add",
58420
- path: "percentage",
58968
+ path: "level",
58421
58969
  sources: [{
58422
58970
  kind: "field",
58423
58971
  valueKinds: ["number", "string"],
@@ -58511,7 +59059,7 @@ onStatusChanged: { data: object({
58511
59059
  schema: BatteryStatusSchema,
58512
59060
  kind: "push",
58513
59061
  empty: {
58514
- percentage: null,
59062
+ level: null,
58515
59063
  charging: "unknown",
58516
59064
  sleeping: false,
58517
59065
  lastUpdated: 0
@@ -58538,11 +59086,11 @@ onStatusChanged: { data: object({
58538
59086
  * History (D850): recorded series. The generic capture replaces the `battery` series of `pipeline-analytics:stats-5m`.
58539
59087
  */
58540
59088
  history: { fields: {
58541
- percentage: {
59089
+ level: {
58542
59090
  kind: "gauge",
58543
59091
  unit: "%"
58544
59092
  },
58545
- volts: {
59093
+ voltage: {
58546
59094
  kind: "gauge",
58547
59095
  unit: "V"
58548
59096
  }
@@ -58602,14 +59150,14 @@ var binaryCapability = {
58602
59150
  * controls to this single-method surface.
58603
59151
  *
58604
59152
  * The cap is intentionally minimal: a single `setBrightness({deviceId,
58605
- * percentage})` mutation plus the auto-injected `getStatus`. Drivers
59153
+ * level})` mutation plus the auto-injected `getStatus`. Drivers
58606
59154
  * that expose richer controls (color temperature, scenes, schedules)
58607
59155
  * should surface those via the device's `getSettingsUISchema()`
58608
59156
  * instead of bloating this cap.
58609
59157
  */
58610
59158
  var BrightnessStatusSchema = object({
58611
59159
  /** Current level as 0..100 inclusive. Firmware-reported. */
58612
- percentage: number().min(0).max(100).meta(readingMeta("percentage")),
59160
+ level: number().min(0).max(100).meta(readingMeta("percentage")),
58613
59161
  /** Ms epoch of the last operator-driven change. Useful for UI freshness. */
58614
59162
  lastChangedAt: number()
58615
59163
  });
@@ -58621,7 +59169,7 @@ var brightnessCapability = {
58621
59169
  deviceTypes: [DeviceType.Light],
58622
59170
  methods: { setBrightness: method(object({
58623
59171
  deviceId: number().int().nonnegative(),
58624
- percentage: number().min(0).max(100)
59172
+ level: number().min(0).max(100)
58625
59173
  }), _void(), {
58626
59174
  kind: "mutation",
58627
59175
  auth: "protected"
@@ -58634,7 +59182,7 @@ var brightnessCapability = {
58634
59182
  */
58635
59183
  onBrightnessChanged: { data: object({
58636
59184
  deviceId: number(),
58637
- percentage: number().min(0).max(100),
59185
+ level: number().min(0).max(100),
58638
59186
  lastChangedAt: number()
58639
59187
  }) } },
58640
59188
  status: {
@@ -58657,7 +59205,7 @@ onBrightnessChanged: { data: object({
58657
59205
  /**
58658
59206
  * History (D850): recorded series. Actuator tier: level keeps every change.
58659
59207
  */
58660
- history: { fields: { percentage: {
59208
+ history: { fields: { level: {
58661
59209
  kind: "gauge",
58662
59210
  unit: "%",
58663
59211
  minIntervalMs: 0
@@ -58685,6 +59233,56 @@ var buttonCapability = {
58685
59233
  }) }
58686
59234
  };
58687
59235
  /**
59236
+ * A pulse train in signed microseconds: mark (+) first, then space (-), strictly
59237
+ * alternating, no zeros, 2..1024 entries.
59238
+ */
59239
+ var IrTimingsSchema = array(number().int()).min(2).max(1024).superRefine((timings, ctx) => {
59240
+ timings.forEach((value, index) => {
59241
+ const expectMark = index % 2 === 0;
59242
+ if (value === 0 || value > 0 !== expectMark) ctx.addIssue({
59243
+ code: "custom",
59244
+ message: `timing ${index} must be a non-zero ${expectMark ? "mark (positive)" : "space (negative)"}`,
59245
+ path: [index]
59246
+ });
59247
+ });
59248
+ });
59249
+ /** Per-command transmit options. Every key is optional; a transmitter applies what it can. */
59250
+ var TransmitSettingsSchema = object({
59251
+ carrierHz: number().int().positive().optional(),
59252
+ dutyCyclePercent: number().int().min(1).max(100).optional(),
59253
+ repeat: number().int().min(0).max(20).optional(),
59254
+ repeatDelayMs: number().int().min(0).optional()
59255
+ });
59256
+ /** The setting keys a transmitter may declare as settable (`getInfo.settable`). */
59257
+ var TransmitSettingKeySchema = _enum([
59258
+ "carrierHz",
59259
+ "dutyCyclePercent",
59260
+ "repeat",
59261
+ "repeatDelayMs"
59262
+ ]);
59263
+ var IrMediumSchema = _enum(["ir", "rf"]);
59264
+ var IrSendResultSchema = object({
59265
+ ok: literal(true),
59266
+ /** Settings the transmitter could not apply; the train was still sent. */
59267
+ ignoredSettings: array(string())
59268
+ });
59269
+ var IrTransmitterInfoSchema = object({
59270
+ media: array(IrMediumSchema),
59271
+ settable: array(TransmitSettingKeySchema),
59272
+ maxTimings: number().int().positive()
59273
+ });
59274
+ DeviceType.Generic, method(object({
59275
+ deviceId: number().int().nonnegative(),
59276
+ timings: IrTimingsSchema,
59277
+ settings: TransmitSettingsSchema.optional()
59278
+ }), IrSendResultSchema, {
59279
+ kind: "mutation",
59280
+ auth: "protected"
59281
+ }), method(object({ deviceId: number().int().nonnegative() }), IrTransmitterInfoSchema, {
59282
+ kind: "query",
59283
+ auth: "protected"
59284
+ });
59285
+ /**
58688
59286
  * `calendar-source` — collection cap exposing per-provider calendars and
58689
59287
  * their events. Every addon that contributes calendars (Home Assistant,
58690
59288
  * a future Google Calendar addon, …) registers a provider here. The hub
@@ -59281,11 +59879,11 @@ var ColorInputSchema = discriminatedUnion("mode", [
59281
59879
  }),
59282
59880
  object({
59283
59881
  mode: literal("mired"),
59284
- mireds: number().int().min(50).max(1e3)
59882
+ colorTemperature: number().int().min(50).max(1e3)
59285
59883
  })
59286
59884
  ]);
59287
59885
  var ColorStatusSchema = object({
59288
- /** Active color mode — which of `rgb` / `hsv` / `mireds` reflects
59886
+ /** Active color mode — which of `rgb` / `hsv` / `colorTemperature` reflects
59289
59887
  * the bulb's current state. */
59290
59888
  mode: _enum([
59291
59889
  "rgb",
@@ -59297,7 +59895,7 @@ var ColorStatusSchema = object({
59297
59895
  /** Populated when `mode === 'hsv'`. */
59298
59896
  hsv: HsvTripletSchema.optional(),
59299
59897
  /** Populated when `mode === 'mired'`. */
59300
- mireds: number().int().optional().meta(readingMeta("colour-temperature")),
59898
+ colorTemperature: number().int().optional().meta(readingMeta("colour-temperature")),
59301
59899
  /** Ms epoch of the last operator-driven change. */
59302
59900
  lastChangedAt: number()
59303
59901
  });
@@ -59329,7 +59927,7 @@ onColorChanged: { data: object({
59329
59927
  ]),
59330
59928
  rgb: RgbTripletSchema.optional(),
59331
59929
  hsv: HsvTripletSchema.optional(),
59332
- mireds: number().int().optional(),
59930
+ colorTemperature: number().int().optional(),
59333
59931
  lastChangedAt: number()
59334
59932
  }) } },
59335
59933
  status: {
@@ -60220,11 +60818,11 @@ var DishwasherStatusSchema = object({
60220
60818
  /** Feature keys of the programs the appliance currently offers — drives the UI selector. */
60221
60819
  availablePrograms: array(string()),
60222
60820
  /** Seconds remaining on the active cycle, or null when not running / not known. */
60223
- remainingSeconds: number().int().nonnegative().nullable().meta(readingMeta("duration")),
60821
+ remaining: number().int().nonnegative().nullable().meta(readingMeta("duration")),
60224
60822
  /** Seconds the delayed start is set to (time until the cycle starts), or null. */
60225
- delayedStartSeconds: number().int().nonnegative().nullable().meta(readingMeta("duration")),
60823
+ delayedStart: number().int().nonnegative().nullable().meta(readingMeta("duration")),
60226
60824
  /** Cycle completion 0..100, or null when not applicable. */
60227
- progressPercent: number().min(0).max(100).nullable().meta(readingMeta("percentage")),
60825
+ progress: number().min(0).max(100).nullable().meta(readingMeta("percentage")),
60228
60826
  /** True when the door is reported open; null when the door state is not known. */
60229
60827
  doorOpen: boolean().nullable(),
60230
60828
  /** True when the door is latched (locked) during a cycle; null when not reported. */
@@ -60443,14 +61041,14 @@ var dishwasherCapability = {
60443
61041
  runtimeState: DishwasherStatusSchema,
60444
61042
  durability: "session",
60445
61043
  history: { fields: {
60446
- progressPercent: {
61044
+ progress: {
60447
61045
  kind: "gauge",
60448
61046
  unit: "%",
60449
61047
  deadband: 2
60450
61048
  },
60451
61049
  state: { kind: "enum" },
60452
61050
  operationState: { kind: "enum" },
60453
- remainingSeconds: {
61051
+ remaining: {
60454
61052
  kind: "gauge",
60455
61053
  unit: "s",
60456
61054
  minIntervalMs: 6e4
@@ -61051,7 +61649,7 @@ var FanDirectionSchema = _enum(["forward", "reverse"]);
61051
61649
  var FanControlStatusSchema = object({
61052
61650
  /** Active speed as 0..100 inclusive. Null when the device has no
61053
61651
  * speed surface (single-speed fan). */
61054
- percentage: number().min(0).max(100).nullable().meta(readingMeta("percentage")),
61652
+ speed: number().min(0).max(100).nullable().meta(readingMeta("percentage")),
61055
61653
  /** Speed granularity the device accepts (HA `percentage_step`, e.g. 25 for
61056
61654
  * a 4-speed fan). Absent when unknown — the UI then falls back to step 1. */
61057
61655
  percentageStep: number().positive().optional().meta(readingMeta("percentage")),
@@ -61078,7 +61676,7 @@ var fanControlCapability = {
61078
61676
  methods: {
61079
61677
  setPercentage: method(object({
61080
61678
  deviceId: number().int().nonnegative(),
61081
- percentage: number().min(0).max(100)
61679
+ speed: number().min(0).max(100)
61082
61680
  }), _void(), {
61083
61681
  kind: "mutation",
61084
61682
  auth: "protected"
@@ -61111,7 +61709,7 @@ var fanControlCapability = {
61111
61709
  },
61112
61710
  /**
61113
61711
  * Runtime-state slice — mirrored by the kernel. UI fan speed
61114
- * sliders read `percentage` for live updates.
61712
+ * sliders read `speed` for live updates.
61115
61713
  */
61116
61714
  runtimeState: FanControlStatusSchema,
61117
61715
  /**
@@ -61125,7 +61723,7 @@ var fanControlCapability = {
61125
61723
  * History (D850): recorded series. Actuator tier: speed keeps every change.
61126
61724
  */
61127
61725
  history: { fields: {
61128
- percentage: {
61726
+ speed: {
61129
61727
  kind: "gauge",
61130
61728
  unit: "%",
61131
61729
  minIntervalMs: 0
@@ -61570,7 +62168,7 @@ var humidifierCapability = {
61570
62168
  */
61571
62169
  var HumiditySensorStatusSchema = object({
61572
62170
  /** Current relative humidity, 0..100. `null` when the sample was refused (D393). */
61573
- percent: number().min(0).max(100).nullable().meta(readingMeta("humidity", {
62171
+ humidity: number().min(0).max(100).nullable().meta(readingMeta("humidity", {
61574
62172
  precision: 0,
61575
62173
  label: "Humidity"
61576
62174
  })),
@@ -61599,7 +62197,7 @@ var humiditySensorCapability = {
61599
62197
  /**
61600
62198
  * History (D850): recorded series.
61601
62199
  */
61602
- history: { fields: { percent: {
62200
+ history: { fields: { humidity: {
61603
62201
  kind: "gauge",
61604
62202
  unit: "%",
61605
62203
  deadband: .5
@@ -62239,7 +62837,7 @@ var LawnMowerControlStatusSchema = object({
62239
62837
  batteryLevel: number().min(0).max(100).nullable().meta(readingMeta("percentage")),
62240
62838
  /** 0..100 mowing-completion percentage of the current task, or null when no
62241
62839
  * task is active / progress is unavailable. */
62242
- progressPercent: number().min(0).max(100).nullable().meta(readingMeta("percentage")),
62840
+ progress: number().min(0).max(100).nullable().meta(readingMeta("percentage")),
62243
62841
  /** Current device/event code (dynamic — mostly status, sometimes an error),
62244
62842
  * or null when unknown. */
62245
62843
  currentCode: number().nullable().meta(readingMeta("none")),
@@ -62739,7 +63337,7 @@ var lockControlCapability = {
62739
63337
  volatileStateFields: ["lastChangedAt"]
62740
63338
  };
62741
63339
  /**
62742
- * A monotonic total between resets (D944). Energy uses `power-meter.kwhTotal`
63340
+ * A monotonic total between resets (D944). Energy uses `power-meter.energy`
62743
63341
  * so dashboards keep one series; every other instantaneous reading lands here.
62744
63342
  * `value` is the time integral in the source quantity's accumulated base
62745
63343
  * (base-unit seconds, or kWh on the power meter). `null` is a gap, never zero.
@@ -62833,10 +63431,10 @@ var MediaPlayerStatusSchema = object({
62833
63431
  currentMedia: MediaInfoSchema.nullable(),
62834
63432
  /** Current playback position in ms. Null when not seekable or
62835
63433
  * nothing is playing. Pair with `DeviceFeature.MediaPlayerSeek`. */
62836
- positionMs: number().int().nonnegative().nullable().meta(readingMeta("duration-ms")),
63434
+ position: number().int().nonnegative().nullable().meta(readingMeta("duration-ms")),
62837
63435
  /** Total duration of the current media in ms. Null when unknown
62838
63436
  * (live stream) or nothing is playing. */
62839
- durationMs: number().int().nonnegative().nullable().meta(readingMeta("duration-ms")),
63437
+ duration: number().int().nonnegative().nullable().meta(readingMeta("duration-ms")),
62840
63438
  /** Shuffle toggle. Null when no shuffle surface.
62841
63439
  * Pair with `DeviceFeature.MediaPlayerShuffle`. */
62842
63440
  shuffle: boolean().nullable(),
@@ -62875,7 +63473,7 @@ var mediaPlayerCapability = {
62875
63473
  }),
62876
63474
  seek: method(object({
62877
63475
  deviceId: number().int().nonnegative(),
62878
- positionMs: number().int().nonnegative()
63476
+ position: number().int().nonnegative()
62879
63477
  }), _void(), {
62880
63478
  kind: "mutation",
62881
63479
  auth: "protected"
@@ -62947,7 +63545,7 @@ var mediaPlayerCapability = {
62947
63545
  /**
62948
63546
  * History (D850): volume (a level an operator or an automation sets; the
62949
63547
  * default 10 s floor folds a slider drag into its end value) and mute.
62950
- * `positionMs` is not recorded: it moves continuously while playing.
63548
+ * `position` is not recorded: it moves continuously while playing.
62951
63549
  */
62952
63550
  history: { fields: {
62953
63551
  volumeLevel: {
@@ -63909,9 +64507,9 @@ var NetworkLinkStatusSchema = object({
63909
64507
  * one whose reading has not landed must not be drawn at 0 %. Consumers
63910
64508
  * SKIP a null rather than coerce it.
63911
64509
  */
63912
- signalPercent: number().min(0).max(100).nullable().meta(readingMeta("percentage")),
64510
+ signal: number().min(0).max(100).nullable().meta(readingMeta("percentage")),
63913
64511
  /** Raw received signal strength in dBm, when the firmware reports one. */
63914
- rssiDbm: number().optional().meta(readingMeta("signal-level")),
64512
+ rssi: number().optional().meta(readingMeta("signal-level")),
63915
64513
  /** Network name of a wireless link, when the firmware reports it. */
63916
64514
  ssid: string().optional(),
63917
64515
  /** Ms epoch of the last observation. Lets consumers reason about freshness. */
@@ -63947,7 +64545,7 @@ onStatusChanged: { data: object({
63947
64545
  kind: "push",
63948
64546
  empty: {
63949
64547
  type: "unknown",
63950
- signalPercent: null,
64548
+ signal: null,
63951
64549
  lastUpdated: 0
63952
64550
  }
63953
64551
  },
@@ -63970,13 +64568,13 @@ onStatusChanged: { data: object({
63970
64568
  * History (D850): recorded series.
63971
64569
  */
63972
64570
  history: { fields: {
63973
- signalPercent: {
64571
+ signal: {
63974
64572
  kind: "gauge",
63975
64573
  unit: "%",
63976
64574
  deadband: 3,
63977
64575
  minIntervalMs: 6e4
63978
64576
  },
63979
- rssiDbm: {
64577
+ rssi: {
63980
64578
  kind: "gauge",
63981
64579
  unit: "dBm",
63982
64580
  deadband: 2,
@@ -64721,10 +65319,20 @@ var PetFeederDeviceStatusSchema = _enum([
64721
65319
  ]);
64722
65320
  var gramsPortion = number().int().min(4).max(200);
64723
65321
  var PetFeederStatusSchema = object({
64724
- /** Food currently in the bowl (grams). Null when the device has not
64725
- * reported a reading yet. On dual-hopper models this is the combined
64726
- * bowl reading; per-hopper levels live in `food1`/`food2`. */
65322
+ /** Food in the TANK (hopper), as the feeder's own sensor reports it
65323
+ * (`state.food`). A coarse level code, not grams — `0` is empty. The
65324
+ * amount in the bowl is `bowlFood`. On dual-hopper models this is the
65325
+ * combined reading; per-hopper levels live in `food1`/`food2`. Null when
65326
+ * the device has not reported yet. */
64727
65327
  foodLevel: number().nullable().meta(readingMeta("none")),
65328
+ /** Food in the BOWL as the feeder reports it (`state.bowl`), in the
65329
+ * feeder's own units. Null when the model reports none. */
65330
+ bowlFood: number().nullable().meta(readingMeta("none")),
65331
+ /** True while the pet is eating (`state.eating`). */
65332
+ eating: boolean(),
65333
+ /** Whether `markFoodReplenished` does anything on this model. When false
65334
+ * the client must not offer it. */
65335
+ supportsMarkRefilled: boolean(),
64728
65336
  /** Hopper-1 food level (grams) on dual-hopper feeders; null on
64729
65337
  * single-hopper models. */
64730
65338
  food1: number().nullable().meta(readingMeta("none")),
@@ -64732,12 +65340,17 @@ var PetFeederStatusSchema = object({
64732
65340
  * single-hopper models. */
64733
65341
  food2: number().nullable().meta(readingMeta("none")),
64734
65342
  /** Derived low-food flag — mirrors the HA `food_level` binary_sensor
64735
- * (`device_class: problem`, on = low). True when the bowl is empty /
64736
- * below the feeder's low threshold. */
65343
+ * (`device_class: problem`, on = low). True when the tank reports empty,
65344
+ * or, on a dual-hopper model, when EITHER hopper is empty. */
64737
65345
  lowFood: boolean(),
64738
- /** Battery charge 0..100 (%). Null on mains-powered models or when the
64739
- * device has no battery reading. */
65346
+ /** Battery charge 0..100 (%). On a feeder running on `mains` this is the
65347
+ * BACKUP battery's charge, not the power source. Null when the device has
65348
+ * no battery reading. */
64740
65349
  batteryPower: number().min(0).max(100).nullable().meta(readingMeta("percentage")),
65350
+ /** What the feeder is powered from right now: `mains` (plugged in, the
65351
+ * battery is only a backup) or `battery`. Null when the device does not
65352
+ * report it. */
65353
+ powerSource: _enum(["mains", "battery"]).nullable(),
64741
65354
  /**
64742
65355
  * Desiccant life remaining, stored in seconds (duration base, D944).
64743
65356
  * Providers convert from the days the feeder reports. Null when the
@@ -64801,7 +65414,9 @@ var petFeederCapability = {
64801
65414
  kind: "mutation",
64802
65415
  auth: "protected"
64803
65416
  }),
64804
- /** Mark a hopper as refilled (D4H/D4S/D4SH). */
65417
+ /** Tell the PetKit cloud a hopper was refilled so it stops its low-food
65418
+ * reminders (D4H/D4S/D4SH only — see `supportsMarkRefilled`). It does not
65419
+ * change any sensor reading. */
64805
65420
  markFoodReplenished: method(object({ deviceId: number().int().nonnegative() }), _void(), {
64806
65421
  kind: "mutation",
64807
65422
  auth: "protected"
@@ -64874,6 +65489,7 @@ var petFeederCapability = {
64874
65489
  */
64875
65490
  history: { fields: {
64876
65491
  foodLevel: { kind: "gauge" },
65492
+ bowlFood: { kind: "gauge" },
64877
65493
  food1: { kind: "gauge" },
64878
65494
  food2: { kind: "gauge" },
64879
65495
  batteryPower: {
@@ -65283,16 +65899,16 @@ method(_void(), PlatformCapabilitiesSchema), method(_void(), HardwareInfoSchema)
65283
65899
  * in real-world devices.
65284
65900
  */
65285
65901
  var PowerMeterStatusSchema = object({
65286
- /** Instantaneous power draw in watts. */
65287
- watts: number().optional().meta(readingMeta("power", { label: "Power" })),
65902
+ /** Instantaneous power draw (watts). */
65903
+ power: number().optional().meta(readingMeta("power", { label: "Power" })),
65288
65904
  /** Cumulative energy in kilowatt-hours since the meter was reset. */
65289
- kwhTotal: number().optional().meta(readingMeta("energy", { label: "Energy" })),
65290
- /** Voltage in volts. */
65291
- volts: number().optional().meta(readingMeta("voltage", { label: "Voltage" })),
65905
+ energy: number().optional().meta(readingMeta("energy", { label: "Energy" })),
65906
+ /** Voltage (volts). */
65907
+ voltage: number().optional().meta(readingMeta("voltage", { label: "Voltage" })),
65292
65908
  /** Current in amperes. */
65293
- amps: number().optional().meta(readingMeta("current", { label: "Current" })),
65909
+ current: number().optional().meta(readingMeta("current", { label: "Current" })),
65294
65910
  /** Apparent power in volt-amperes. */
65295
- va: number().optional().meta(readingMeta("apparent-power")),
65911
+ apparentPower: number().optional().meta(readingMeta("apparent-power")),
65296
65912
  /** Power factor (0..1) if reported. */
65297
65913
  powerFactor: number().min(0).max(1).optional().meta(readingMeta("ratio")),
65298
65914
  /** Ms epoch when the slice was last updated. */
@@ -65350,14 +65966,14 @@ function powerTarget(id, unit) {
65350
65966
  advancedExpression: true
65351
65967
  };
65352
65968
  }
65353
- /** "Power and energy" extension: watts, energy, voltage and current from other devices (D951). */
65969
+ /** "Power and energy" extension: power, energy, voltage and current from other devices (D951). */
65354
65970
  var powerMeterCustomize = {
65355
65971
  version: 1,
65356
65972
  targets: [
65357
- powerTarget("watts", "W"),
65358
- powerTarget("kwhTotal", "kWh"),
65359
- powerTarget("volts", "V"),
65360
- powerTarget("amps", "A")
65973
+ powerTarget("power", "W"),
65974
+ powerTarget("energy", "kWh"),
65975
+ powerTarget("voltage", "V"),
65976
+ powerTarget("current", "A")
65361
65977
  ]
65362
65978
  };
65363
65979
  var powerMeterCapability = {
@@ -65373,41 +65989,41 @@ var powerMeterCapability = {
65373
65989
  },
65374
65990
  runtimeState: PowerMeterStatusSchema,
65375
65991
  /**
65376
- * Runtime-state durability: **restored** — as `numeric-sensor`; `kwhTotal` is an accumulator whose restored value is the baseline.
65992
+ * Runtime-state durability: **restored** — as `numeric-sensor`; `energy` is an accumulator whose restored value is the baseline.
65377
65993
  *
65378
65994
  * See `RuntimeStateDurability`. Enforced by
65379
65995
  * `scripts/check-runtime-state-durability.ts`.
65380
65996
  */
65381
65997
  durability: "restored",
65382
65998
  /**
65383
- * History (D850): recorded series. Gauges are floored at 30 s; `kwhTotal` is the one monotonic meter (counter).
65999
+ * History (D850): recorded series. Gauges are floored at 30 s; `energy` is the one monotonic meter (counter).
65384
66000
  */
65385
66001
  history: { fields: {
65386
- watts: {
66002
+ power: {
65387
66003
  kind: "gauge",
65388
66004
  unit: "W",
65389
66005
  deadband: 1,
65390
66006
  minIntervalMs: 3e4
65391
66007
  },
65392
- kwhTotal: {
66008
+ energy: {
65393
66009
  kind: "counter",
65394
66010
  unit: "kWh",
65395
66011
  deadband: .01,
65396
66012
  minIntervalMs: 6e4
65397
66013
  },
65398
- volts: {
66014
+ voltage: {
65399
66015
  kind: "gauge",
65400
66016
  unit: "V",
65401
66017
  deadband: 1,
65402
66018
  minIntervalMs: 3e4
65403
66019
  },
65404
- amps: {
66020
+ current: {
65405
66021
  kind: "gauge",
65406
66022
  unit: "A",
65407
66023
  deadband: .05,
65408
66024
  minIntervalMs: 3e4
65409
66025
  },
65410
- va: {
66026
+ apparentPower: {
65411
66027
  kind: "gauge",
65412
66028
  unit: "VA",
65413
66029
  deadband: 1,
@@ -65457,9 +66073,6 @@ var PresenceStatusSchema = object({
65457
66073
  location: string().nullable(),
65458
66074
  /** GPS coordinates when available. Null otherwise. */
65459
66075
  gps: GpsLocationSchema.nullable(),
65460
- /** Optional battery level of the tracking device (0..100). Null
65461
- * when not reported. */
65462
- batteryPercent: number().min(0).max(100).nullable().meta(readingMeta("percentage")),
65463
66076
  /** Ms epoch when the slice was last updated. */
65464
66077
  lastChangedAt: number()
65465
66078
  });
@@ -65488,14 +66101,7 @@ var presenceCapability = {
65488
66101
  * `scripts/check-runtime-state-durability.ts`.
65489
66102
  */
65490
66103
  durability: "restored",
65491
- /**
65492
- * History (D850): recorded series.
65493
- */
65494
- history: { fields: { batteryPercent: {
65495
- kind: "gauge",
65496
- unit: "%",
65497
- deadband: 1
65498
- } } },
66104
+ history: "none",
65499
66105
  /** Clock fields: written, but excluded from the compare that decides
65500
66106
  * whether persisting is worth a SQLite commit. */
65501
66107
  volatileStateFields: ["lastChangedAt"]
@@ -65510,7 +66116,7 @@ var presenceCapability = {
65510
66116
  */
65511
66117
  var PressureSensorStatusSchema = object({
65512
66118
  /** Current pressure in hPa. `null` when the sample was refused (D393). */
65513
- hpa: number().nullable().meta(readingMeta("pressure", { precision: 0 })),
66119
+ pressure: number().nullable().meta(readingMeta("pressure", { precision: 0 })),
65514
66120
  /** Ms epoch when the slice was last updated. */
65515
66121
  lastFetchedAt: number()
65516
66122
  });
@@ -65536,7 +66142,7 @@ var pressureSensorCapability = {
65536
66142
  /**
65537
66143
  * History (D850): recorded series.
65538
66144
  */
65539
- history: { fields: { hpa: {
66145
+ history: { fields: { pressure: {
65540
66146
  kind: "gauge",
65541
66147
  unit: "hPa",
65542
66148
  deadband: .1
@@ -69243,7 +69849,7 @@ var tamperCapability = {
69243
69849
  */
69244
69850
  var TemperatureSensorStatusSchema = object({
69245
69851
  /** Current temperature in Celsius. `null` when the sample was refused (D393). */
69246
- celsius: number().nullable().meta(readingMeta("temperature", {
69852
+ temperature: number().nullable().meta(readingMeta("temperature", {
69247
69853
  precision: 1,
69248
69854
  label: "Temperature"
69249
69855
  })),
@@ -69272,7 +69878,7 @@ var temperatureSensorCapability = {
69272
69878
  /**
69273
69879
  * History (D850): recorded series.
69274
69880
  */
69275
- history: { fields: { celsius: {
69881
+ history: { fields: { temperature: {
69276
69882
  kind: "gauge",
69277
69883
  unit: "°C",
69278
69884
  deadband: .1
@@ -69569,7 +70175,7 @@ var VacuumControlStatusSchema = object({
69569
70175
  /** Speed tokens the hardware accepts — drives the UI selector. */
69570
70176
  availableFanSpeeds: array(string()),
69571
70177
  /** 0..100 cleaning-completion percentage of the current task, or null. */
69572
- progressPercent: number().min(0).max(100).nullable().meta(readingMeta("percentage")),
70178
+ progress: number().min(0).max(100).nullable().meta(readingMeta("percentage")),
69573
70179
  /** Current error code (0 / null = no error). */
69574
70180
  errorCode: number().nullable().meta(readingMeta("none")),
69575
70181
  /** Human label for {@link errorCode}, or null when none / undecodable. */
@@ -71658,7 +72264,7 @@ var BaseDevice = class {
71658
72264
  * `device-local-state.ts`. Drivers access via:
71659
72265
  *
71660
72266
  * `this.state.battery.sleeping = true` // patches the battery slice
71661
- * `const pct = this.state.battery.percentage` // reads the battery slice
72267
+ * `const pct = this.state.battery.level` // reads the battery slice
71662
72268
  * `this.state.deviceStatus.online = true` // mirrors `markOnline(true)`
71663
72269
  *
71664
72270
  * Adding a new cap with `runtimeState:` automatically extends this
@@ -71698,7 +72304,7 @@ var BaseDevice = class {
71698
72304
  * shape; drivers don't redeclare it, they just write through.
71699
72305
  *
71700
72306
  * Read: `this.runtimeState.getCapState('battery')` →
71701
- * `{percentage, charging, sleeping, lastUpdated}` for any
72307
+ * `{level, charging, sleeping, lastUpdated}` for any
71702
72308
  * provider that registers `batteryCapability`.
71703
72309
  * Write: `this.runtimeState.setCapState('battery', { … })`.
71704
72310
  *
@@ -72872,6 +73478,104 @@ Object.freeze({
72872
73478
  access: "create",
72873
73479
  role: "admin"
72874
73480
  },
73481
+ "actions.create": {
73482
+ capName: "actions",
73483
+ capScope: "system",
73484
+ addonId: null,
73485
+ access: "create",
73486
+ role: "admin"
73487
+ },
73488
+ "actions.delete": {
73489
+ capName: "actions",
73490
+ capScope: "system",
73491
+ addonId: null,
73492
+ access: "delete",
73493
+ role: "admin"
73494
+ },
73495
+ "actions.get": {
73496
+ capName: "actions",
73497
+ capScope: "system",
73498
+ addonId: null,
73499
+ access: "view",
73500
+ role: "viewer"
73501
+ },
73502
+ "actions.getLinks": {
73503
+ capName: "actions",
73504
+ capScope: "system",
73505
+ addonId: null,
73506
+ access: "view",
73507
+ role: "admin"
73508
+ },
73509
+ "actions.getTraces": {
73510
+ capName: "actions",
73511
+ capScope: "system",
73512
+ addonId: null,
73513
+ access: "view",
73514
+ role: "admin"
73515
+ },
73516
+ "actions.list": {
73517
+ capName: "actions",
73518
+ capScope: "system",
73519
+ addonId: null,
73520
+ access: "view",
73521
+ role: "admin"
73522
+ },
73523
+ "actions.listForCamera": {
73524
+ capName: "actions",
73525
+ capScope: "system",
73526
+ addonId: null,
73527
+ access: "view",
73528
+ role: "viewer"
73529
+ },
73530
+ "actions.run": {
73531
+ capName: "actions",
73532
+ capScope: "system",
73533
+ addonId: null,
73534
+ access: "create",
73535
+ role: "viewer"
73536
+ },
73537
+ "actions.setLinks": {
73538
+ capName: "actions",
73539
+ capScope: "system",
73540
+ addonId: null,
73541
+ access: "create",
73542
+ role: "admin"
73543
+ },
73544
+ "actions.stop": {
73545
+ capName: "actions",
73546
+ capScope: "system",
73547
+ addonId: null,
73548
+ access: "create",
73549
+ role: "admin"
73550
+ },
73551
+ "actions.update": {
73552
+ capName: "actions",
73553
+ capScope: "system",
73554
+ addonId: null,
73555
+ access: "create",
73556
+ role: "admin"
73557
+ },
73558
+ "actionSource.listActions": {
73559
+ capName: "action-source",
73560
+ capScope: "system",
73561
+ addonId: null,
73562
+ access: "view",
73563
+ role: "admin"
73564
+ },
73565
+ "actionSource.runAction": {
73566
+ capName: "action-source",
73567
+ capScope: "system",
73568
+ addonId: null,
73569
+ access: "create",
73570
+ role: "admin"
73571
+ },
73572
+ "actionSource.stopAction": {
73573
+ capName: "action-source",
73574
+ capScope: "system",
73575
+ addonId: null,
73576
+ access: "create",
73577
+ role: "admin"
73578
+ },
72875
73579
  "addonPages.listPages": {
72876
73580
  capName: "addon-pages",
72877
73581
  capScope: "system",
@@ -74153,6 +74857,13 @@ Object.freeze({
74153
74857
  access: "view",
74154
74858
  role: "admin"
74155
74859
  },
74860
+ "coreBlocks.getAutomationRunState": {
74861
+ capName: "core-blocks",
74862
+ capScope: "system",
74863
+ addonId: null,
74864
+ access: "view",
74865
+ role: "admin"
74866
+ },
74156
74867
  "coreBlocks.getBlockSettings": {
74157
74868
  capName: "core-blocks",
74158
74869
  capScope: "system",
@@ -74174,6 +74885,13 @@ Object.freeze({
74174
74885
  access: "view",
74175
74886
  role: "admin"
74176
74887
  },
74888
+ "coreBlocks.getTraces": {
74889
+ capName: "core-blocks",
74890
+ capScope: "system",
74891
+ addonId: null,
74892
+ access: "view",
74893
+ role: "admin"
74894
+ },
74177
74895
  "coreBlocks.getTypeDefs": {
74178
74896
  capName: "core-blocks",
74179
74897
  capScope: "system",
@@ -74209,6 +74927,13 @@ Object.freeze({
74209
74927
  access: "create",
74210
74928
  role: "admin"
74211
74929
  },
74930
+ "coreBlocks.reportAutomationRun": {
74931
+ capName: "core-blocks",
74932
+ capScope: "system",
74933
+ addonId: null,
74934
+ access: "create",
74935
+ role: "admin"
74936
+ },
74212
74937
  "coreBlocks.restart": {
74213
74938
  capName: "core-blocks",
74214
74939
  capScope: "system",
@@ -76288,6 +77013,20 @@ Object.freeze({
76288
77013
  access: "create",
76289
77014
  role: "viewer"
76290
77015
  },
77016
+ "irTransmitter.getInfo": {
77017
+ capName: "ir-transmitter",
77018
+ capScope: "device",
77019
+ addonId: null,
77020
+ access: "view",
77021
+ role: "viewer"
77022
+ },
77023
+ "irTransmitter.send": {
77024
+ capName: "ir-transmitter",
77025
+ capScope: "device",
77026
+ addonId: null,
77027
+ access: "create",
77028
+ role: "viewer"
77029
+ },
76291
77030
  "keychain.delete": {
76292
77031
  capName: "keychain",
76293
77032
  capScope: "system",
@@ -82782,7 +83521,7 @@ var ACTUATOR_CAP_VOCABULARY = {
82782
83521
  label: t("Full brightness", "Luminosità massima"),
82783
83522
  phrase: t("Set {device} to full brightness", "Porta {device} alla massima luminosità"),
82784
83523
  icon: "sun",
82785
- args: { percentage: 100 }
83524
+ args: { level: 100 }
82786
83525
  },
82787
83526
  {
82788
83527
  id: "brightness.half",
@@ -82790,7 +83529,7 @@ var ACTUATOR_CAP_VOCABULARY = {
82790
83529
  label: t("Half brightness", "Luminosità a metà"),
82791
83530
  phrase: t("Dim {device} to half", "Abbassa {device} a metà luminosità"),
82792
83531
  icon: "sun-dim",
82793
- args: { percentage: 50 }
83532
+ args: { level: 50 }
82794
83533
  },
82795
83534
  {
82796
83535
  id: "brightness.off",
@@ -82798,16 +83537,16 @@ var ACTUATOR_CAP_VOCABULARY = {
82798
83537
  label: t("Brightness off", "Luminosità a zero"),
82799
83538
  phrase: t("Dim {device} to zero", "Abbassa {device} a zero"),
82800
83539
  icon: "lightbulb-off",
82801
- args: { percentage: 0 }
83540
+ args: { level: 0 }
82802
83541
  },
82803
83542
  {
82804
83543
  id: "brightness.set",
82805
83544
  method: "setBrightness",
82806
83545
  label: t("Set brightness", "Imposta la luminosità"),
82807
- phrase: t("Set the brightness of {device} to {percentage}", "Imposta la luminosità di {device} a {percentage}"),
83546
+ phrase: t("Set the brightness of {device} to {level}", "Imposta la luminosità di {device} a {level}"),
82808
83547
  icon: "sun-medium",
82809
83548
  openArgs: [{
82810
- key: "percentage",
83549
+ key: "level",
82811
83550
  label: PERCENT,
82812
83551
  offer: {
82813
83552
  kind: "number",
@@ -82821,13 +83560,13 @@ var ACTUATOR_CAP_VOCABULARY = {
82821
83560
  ],
82822
83561
  state: [{
82823
83562
  kind: "numeric",
82824
- field: "percentage",
83563
+ field: "level",
82825
83564
  quantity: t("the brightness", "la luminosità"),
82826
83565
  label: t("Brightness", "Luminosità"),
82827
83566
  unit: "%",
82828
83567
  icon: "sun"
82829
83568
  }],
82830
- events: { onBrightnessChanged: { notOperatorFacing: "the `percentage` state trigger reads the same change" } }
83569
+ events: { onBrightnessChanged: { notOperatorFacing: "the `level` state trigger reads the same change" } }
82831
83570
  },
82832
83571
  color: {
82833
83572
  scope: "device",
@@ -82841,7 +83580,7 @@ var ACTUATOR_CAP_VOCABULARY = {
82841
83580
  icon: "sun",
82842
83581
  args: { color: {
82843
83582
  mode: "mired",
82844
- mireds: 370
83583
+ colorTemperature: 370
82845
83584
  } }
82846
83585
  },
82847
83586
  {
@@ -82852,7 +83591,7 @@ var ACTUATOR_CAP_VOCABULARY = {
82852
83591
  icon: "snowflake",
82853
83592
  args: { color: {
82854
83593
  mode: "mired",
82855
- mireds: 200
83594
+ colorTemperature: 200
82856
83595
  } }
82857
83596
  },
82858
83597
  {
@@ -83466,7 +84205,7 @@ var ACTUATOR_CAP_VOCABULARY = {
83466
84205
  label: t("Fan off", "Ventilatore spento"),
83467
84206
  phrase: t("Stop {device}", "Ferma {device}"),
83468
84207
  icon: "power-off",
83469
- args: { percentage: 0 }
84208
+ args: { speed: 0 }
83470
84209
  },
83471
84210
  {
83472
84211
  id: "fan.full",
@@ -83474,16 +84213,16 @@ var ACTUATOR_CAP_VOCABULARY = {
83474
84213
  label: t("Fan full", "Ventilatore al massimo"),
83475
84214
  phrase: t("Run {device} at full speed", "Porta {device} alla massima velocità"),
83476
84215
  icon: "fan",
83477
- args: { percentage: 100 }
84216
+ args: { speed: 100 }
83478
84217
  },
83479
84218
  {
83480
84219
  id: "fan.speed",
83481
84220
  method: "setPercentage",
83482
84221
  label: t("Set speed", "Imposta la velocità"),
83483
- phrase: t("Set the speed of {device} to {percentage}", "Imposta la velocità di {device} al {percentage}"),
84222
+ phrase: t("Set the speed of {device} to {speed}", "Imposta la velocità di {device} al {speed}"),
83484
84223
  icon: "fan",
83485
84224
  openArgs: [{
83486
- key: "percentage",
84225
+ key: "speed",
83487
84226
  label: t("Speed", "Velocità"),
83488
84227
  offer: {
83489
84228
  kind: "number",
@@ -83545,7 +84284,7 @@ var ACTUATOR_CAP_VOCABULARY = {
83545
84284
  ],
83546
84285
  state: [{
83547
84286
  kind: "numeric",
83548
- field: "percentage",
84287
+ field: "speed",
83549
84288
  quantity: t("the speed", "la velocità"),
83550
84289
  label: t("Speed", "Velocità"),
83551
84290
  unit: "%",
@@ -83911,6 +84650,11 @@ var ACTUATOR_CAP_VOCABULARY = {
83911
84650
  icon: "circle-dot"
83912
84651
  }]
83913
84652
  },
84653
+ "ir-transmitter": {
84654
+ scope: "device",
84655
+ noun: t("IR / RF transmitter", "Trasmettitore IR / RF"),
84656
+ notOperatorFacing: { send: "a raw pulse train is not something an operator composes in an automation; the remote that owns the command table sends it" }
84657
+ },
83914
84658
  control: {
83915
84659
  scope: "device",
83916
84660
  noun: t("Control", "Controllo"),
@@ -84343,7 +85087,7 @@ var APPLIANCE_CAP_VOCABULARY = {
84343
85087
  },
84344
85088
  {
84345
85089
  kind: "numeric",
84346
- field: "progressPercent",
85090
+ field: "progress",
84347
85091
  quantity: t("the cycle progress", "l’avanzamento del lavaggio"),
84348
85092
  label: t("Progress", "Avanzamento"),
84349
85093
  unit: "%",
@@ -84701,10 +85445,10 @@ var APPLIANCE_CAP_VOCABULARY = {
84701
85445
  id: "media.seek",
84702
85446
  method: "seek",
84703
85447
  label: t("Seek", "Vai al punto"),
84704
- phrase: t("Move {device} to {positionMs}", "Porta {device} al punto {positionMs}"),
85448
+ phrase: t("Move {device} to {position}", "Porta {device} al punto {position}"),
84705
85449
  icon: "fast-forward",
84706
85450
  openArgs: [{
84707
- key: "positionMs",
85451
+ key: "position",
84708
85452
  label: t("Position", "Posizione"),
84709
85453
  offer: {
84710
85454
  kind: "number",
@@ -85753,7 +86497,7 @@ var SENSOR_CAP_VOCABULARY = {
85753
86497
  state: [
85754
86498
  {
85755
86499
  kind: "numeric",
85756
- field: "co2Ppm",
86500
+ field: "co2",
85757
86501
  quantity: t("the CO₂", "la CO₂"),
85758
86502
  label: t("CO₂", "CO₂"),
85759
86503
  unit: "ppm",
@@ -85761,7 +86505,7 @@ var SENSOR_CAP_VOCABULARY = {
85761
86505
  },
85762
86506
  {
85763
86507
  kind: "numeric",
85764
- field: "vocPpb",
86508
+ field: "voc",
85765
86509
  quantity: t("the VOC level", "il livello di COV"),
85766
86510
  label: t("VOC", "COV"),
85767
86511
  unit: "ppb",
@@ -85797,7 +86541,7 @@ var SENSOR_CAP_VOCABULARY = {
85797
86541
  noun: t("Light level", "Luminosità ambiente"),
85798
86542
  state: [{
85799
86543
  kind: "numeric",
85800
- field: "lux",
86544
+ field: "illuminance",
85801
86545
  quantity: t("the light level", "la luminosità"),
85802
86546
  label: t("Illuminance", "Illuminamento"),
85803
86547
  unit: "lx",
@@ -86000,7 +86744,7 @@ var SENSOR_CAP_VOCABULARY = {
86000
86744
  noun: t("Humidity", "Umidità"),
86001
86745
  state: [{
86002
86746
  kind: "numeric",
86003
- field: "percent",
86747
+ field: "humidity",
86004
86748
  quantity: t("the humidity", "l’umidità"),
86005
86749
  label: t("Humidity", "Umidità"),
86006
86750
  unit: "%",
@@ -86048,7 +86792,7 @@ var SENSOR_CAP_VOCABULARY = {
86048
86792
  state: [
86049
86793
  {
86050
86794
  kind: "numeric",
86051
- field: "watts",
86795
+ field: "power",
86052
86796
  quantity: t("the power draw", "il consumo"),
86053
86797
  label: t("Power", "Potenza"),
86054
86798
  unit: "W",
@@ -86056,7 +86800,7 @@ var SENSOR_CAP_VOCABULARY = {
86056
86800
  },
86057
86801
  {
86058
86802
  kind: "numeric",
86059
- field: "kwhTotal",
86803
+ field: "energy",
86060
86804
  quantity: t("the energy used", "l’energia consumata"),
86061
86805
  label: t("Energy", "Energia"),
86062
86806
  unit: "kWh",
@@ -86064,7 +86808,7 @@ var SENSOR_CAP_VOCABULARY = {
86064
86808
  },
86065
86809
  {
86066
86810
  kind: "numeric",
86067
- field: "volts",
86811
+ field: "voltage",
86068
86812
  quantity: t("the voltage", "la tensione"),
86069
86813
  label: t("Voltage", "Tensione"),
86070
86814
  unit: "V",
@@ -86072,7 +86816,7 @@ var SENSOR_CAP_VOCABULARY = {
86072
86816
  },
86073
86817
  {
86074
86818
  kind: "numeric",
86075
- field: "amps",
86819
+ field: "current",
86076
86820
  quantity: t("the current", "la corrente"),
86077
86821
  label: t("Current", "Corrente"),
86078
86822
  unit: "A",
@@ -86089,13 +86833,6 @@ var SENSOR_CAP_VOCABULARY = {
86089
86833
  label: t("Where", "Posizione"),
86090
86834
  phrase: t("When {device} is at {value}", "Quando {device} è in {value}"),
86091
86835
  icon: "map-pin"
86092
- }, {
86093
- kind: "numeric",
86094
- field: "batteryPercent",
86095
- quantity: t("the phone battery", "la batteria del telefono"),
86096
- label: t("Battery", "Batteria"),
86097
- unit: "%",
86098
- icon: "battery"
86099
86836
  }]
86100
86837
  },
86101
86838
  "pressure-sensor": {
@@ -86103,7 +86840,7 @@ var SENSOR_CAP_VOCABULARY = {
86103
86840
  noun: t("Pressure", "Pressione"),
86104
86841
  state: [{
86105
86842
  kind: "numeric",
86106
- field: "hpa",
86843
+ field: "pressure",
86107
86844
  quantity: t("the pressure", "la pressione"),
86108
86845
  label: t("Pressure", "Pressione"),
86109
86846
  unit: "hPa",
@@ -86139,7 +86876,7 @@ var SENSOR_CAP_VOCABULARY = {
86139
86876
  noun: t("Temperature", "Temperatura"),
86140
86877
  state: [{
86141
86878
  kind: "numeric",
86142
- field: "celsius",
86879
+ field: "temperature",
86143
86880
  quantity: t("the temperature", "la temperatura"),
86144
86881
  label: t("Temperature", "Temperatura"),
86145
86882
  unit: "°C",
@@ -86210,7 +86947,7 @@ var SENSOR_CAP_VOCABULARY = {
86210
86947
  state: [
86211
86948
  {
86212
86949
  kind: "numeric",
86213
- field: "percentage",
86950
+ field: "level",
86214
86951
  quantity: t("the battery level", "il livello della batteria"),
86215
86952
  label: t("Battery", "Batteria"),
86216
86953
  unit: "%",
@@ -86252,7 +86989,7 @@ var SENSOR_CAP_VOCABULARY = {
86252
86989
  icon: "battery-charging"
86253
86990
  }
86254
86991
  ],
86255
- events: { onStatusChanged: { notOperatorFacing: "the percentage / sleeping / charging state triggers each read one field of this change" } },
86992
+ events: { onStatusChanged: { notOperatorFacing: "the level / sleeping / charging state triggers each read one field of this change" } },
86256
86993
  extraEvents: [{
86257
86994
  category: EventCategory.DeviceAwake,
86258
86995
  label: t("Woke up", "Risvegliato"),
@@ -86270,7 +87007,7 @@ var SENSOR_CAP_VOCABULARY = {
86270
87007
  noun: t("Network link", "Collegamento di rete"),
86271
87008
  state: [{
86272
87009
  kind: "numeric",
86273
- field: "signalPercent",
87010
+ field: "signal",
86274
87011
  quantity: t("the signal strength", "l’intensità del segnale"),
86275
87012
  label: t("Signal", "Segnale"),
86276
87013
  unit: "%",
@@ -86363,6 +87100,8 @@ var ML = "model and training machinery — no device action";
86363
87100
  var INTERNAL = "internal plumbing between addons — never operator-facing";
86364
87101
  /** Every system-scoped cap, with why it is not a device's vocabulary. */
86365
87102
  var SYSTEM_CAP_VOCABULARY = {
87103
+ "action-source": system(INTERNAL),
87104
+ actions: system("declared actions — run from the Actions page and from the cameras that link them"),
86366
87105
  "addon-pages": system(UI_PLUMBING),
86367
87106
  "addon-pages-source": system(UI_PLUMBING),
86368
87107
  "addon-routes": system(UI_PLUMBING),
@@ -86570,6 +87309,31 @@ Object.freeze({
86570
87309
  form: "single",
86571
87310
  optional: false
86572
87311
  }],
87312
+ "actions.get": [{
87313
+ name: "deviceId",
87314
+ form: "single",
87315
+ optional: true
87316
+ }],
87317
+ "actions.getLinks": [{
87318
+ name: "deviceId",
87319
+ form: "single",
87320
+ optional: false
87321
+ }],
87322
+ "actions.listForCamera": [{
87323
+ name: "deviceId",
87324
+ form: "single",
87325
+ optional: false
87326
+ }],
87327
+ "actions.run": [{
87328
+ name: "deviceId",
87329
+ form: "single",
87330
+ optional: true
87331
+ }],
87332
+ "actions.setLinks": [{
87333
+ name: "deviceId",
87334
+ form: "single",
87335
+ optional: false
87336
+ }],
86573
87337
  "addonSettings.getDeviceSettings": [{
86574
87338
  name: "deviceId",
86575
87339
  form: "single",
@@ -87621,6 +88385,16 @@ Object.freeze({
87621
88385
  form: "single",
87622
88386
  optional: false
87623
88387
  }],
88388
+ "irTransmitter.getInfo": [{
88389
+ name: "deviceId",
88390
+ form: "single",
88391
+ optional: false
88392
+ }],
88393
+ "irTransmitter.send": [{
88394
+ name: "deviceId",
88395
+ form: "single",
88396
+ optional: false
88397
+ }],
87624
88398
  "keychain.deleteDeviceScope": [{
87625
88399
  name: "deviceId",
87626
88400
  form: "single",
@@ -91000,7 +91774,24 @@ function bestLocationMatch(externalName, existing, threshold = .8) {
91000
91774
  }
91001
91775
  return best;
91002
91776
  }
91777
+ String.raw`(?<=^|["'(\s>,\[{])`;
91003
91778
  var MB = 1024 * 1024;
91004
91779
  1024 * MB, 3072 * MB;
91780
+ discriminatedUnion("kind", [object({
91781
+ kind: literal("raw"),
91782
+ timings: array(number().int()),
91783
+ settings: TransmitSettingsSchema.optional()
91784
+ }), object({
91785
+ kind: literal("pronto"),
91786
+ code: string()
91787
+ })]);
91788
+ object({
91789
+ manufacturer: string().optional(),
91790
+ supportedModels: array(string()).optional(),
91791
+ supportedController: string().optional(),
91792
+ commandsEncoding: string(),
91793
+ delay: number().nonnegative().optional(),
91794
+ commands: record(string(), unknown())
91795
+ });
91005
91796
  //#endregion
91006
91797
  export { lawnMowerControlCapability as $, union as $t, buttonCapability as A, weatherCapability as At, coverCapability as B, defineRecordKinds as Bt, batteryCapability as C, tryConvertDelta as Ct, brokerCapability as D, valveCapability as Dt, brightnessCapability as E, vacuumControlCapability as Et, connectivityCapability as F, BaseAddon as Ft, eventEmitterCapability as G, array as Gt, deviceAdoptionCapability as H, isReadingQuantity as Ht, consumableFormOf as I, RecordSecretUnavailableError as It, gasCapability as J, literal as Jt, fanControlCapability as K, boolean as Kt, consumableKindOf as L, baseUnitOf as Lt, carbonMonoxideCapability as M, DeviceRole as Mt, climateControlCapability as N, DeviceType as Nt, buildAddonRouteProvider as O, vibrationCapability as Ot, colorCapability as P, errMsg as Pt, ingestReading as Q, string as Qt, contactCapability as R, createEvent as Rt, automationControlCapability as S, temperatureSensorCapability as St, binaryCapability as T, updateCapability as Tt, deviceExportCapability as U, nodePin as Ut, deviceAdminLinkCapability as V, entryBody as Vt, enumSensorCapability as W, _enum as Wt, humiditySensorCapability as X, object as Xt, humidifierCapability as Y, number as Yt, imageCapability as Z, record as Zt, accessoriesCapability as _, runningStateCapability as _t, COCO_TO_MACRO as a, notifierCapability as at, alarmPanelCapability as b, switchCapability as bt, ConsumableItemSchema as c, parseAdminBase as ct, FanDirectionSchema as d, presenceCapability as dt, unknown as en, lockControlCapability as et, HvacModeSchema as f, pressureSensorCapability as ft, TargetSchema as g, runningFromVacuumState as gt, RUNNING_STATE_COLD as h, runningFromMediaPlayer as ht, CAMERA_SWITCH_ORDER as i, notificationOutputCapability as it, calendarSourceCapability as j, DeviceFeature as jt, buildDeviceAdminUrl as k, waterHeaterCapability as kt, ConsumableStatusSchema as l, powerMeterCapability as lt, PLUG_APPLIANCE_TYPES as m, runningFromLawnMower as mt, BaseDevice as n, EventCategory as nn, motionCapability as nt, CameraSwitchIdSchema as o, numericSensorCapability as ot, MediaPlayerRepeatSchema as p, quantityFromUnit as pt, floodCapability as q, discriminatedUnion as qt, BaseDeviceProvider as r, normalizeUnit as rt, ConsumableFormSchema as s, oauthIntegrationCapability as st, AlarmArmModeSchema as t, url as tn, mediaPlayerCapability as tt, EnumSensorDateTimeFormatSchema as u, prepareNotification as ut, addonRoutesCapability as v, scriptRunnerCapability as vt, bestLocationMatch as w, tryConvertUnit as wt, ambientLightSensorCapability as x, tamperCapability as xt, airQualitySensorCapability as y, smokeCapability as yt, controlCapability as z, defineEntryKind as zt };