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