@camstack/addon-provider-homeassistant 1.2.633 → 1.2.634

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-Crlmu_tO.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",
@@ -9133,11 +9140,11 @@ var CAP_NAMES = Object.freeze([
9133
9140
  Object.freeze({
9134
9141
  "air-quality-sensor": [
9135
9142
  {
9136
- "path": "co2Ppm",
9143
+ "path": "co2",
9137
9144
  "valueType": "number"
9138
9145
  },
9139
9146
  {
9140
- "path": "vocPpb",
9147
+ "path": "voc",
9141
9148
  "valueType": "number"
9142
9149
  },
9143
9150
  {
@@ -9187,7 +9194,7 @@ Object.freeze({
9187
9194
  }
9188
9195
  ],
9189
9196
  "ambient-light-sensor": [{
9190
- "path": "lux",
9197
+ "path": "illuminance",
9191
9198
  "valueType": "number"
9192
9199
  }],
9193
9200
  "audio-metrics": [
@@ -9248,7 +9255,7 @@ Object.freeze({
9248
9255
  ],
9249
9256
  "battery": [
9250
9257
  {
9251
- "path": "percentage",
9258
+ "path": "level",
9252
9259
  "valueType": "number"
9253
9260
  },
9254
9261
  {
@@ -9270,7 +9277,7 @@ Object.freeze({
9270
9277
  "valueType": "number"
9271
9278
  },
9272
9279
  {
9273
- "path": "volts",
9280
+ "path": "voltage",
9274
9281
  "valueType": "number"
9275
9282
  },
9276
9283
  {
@@ -9291,7 +9298,7 @@ Object.freeze({
9291
9298
  "valueType": "boolean"
9292
9299
  }],
9293
9300
  "brightness": [{
9294
- "path": "percentage",
9301
+ "path": "level",
9295
9302
  "valueType": "number"
9296
9303
  }],
9297
9304
  "broker": [{
@@ -9492,7 +9499,7 @@ Object.freeze({
9492
9499
  "valueType": "number"
9493
9500
  },
9494
9501
  {
9495
- "path": "mireds",
9502
+ "path": "colorTemperature",
9496
9503
  "valueType": "number"
9497
9504
  }
9498
9505
  ],
@@ -9671,15 +9678,15 @@ Object.freeze({
9671
9678
  "valueType": "string"
9672
9679
  },
9673
9680
  {
9674
- "path": "remainingSeconds",
9681
+ "path": "remaining",
9675
9682
  "valueType": "number"
9676
9683
  },
9677
9684
  {
9678
- "path": "delayedStartSeconds",
9685
+ "path": "delayedStart",
9679
9686
  "valueType": "number"
9680
9687
  },
9681
9688
  {
9682
- "path": "progressPercent",
9689
+ "path": "progress",
9683
9690
  "valueType": "number"
9684
9691
  },
9685
9692
  {
@@ -9793,7 +9800,7 @@ Object.freeze({
9793
9800
  ],
9794
9801
  "fan-control": [
9795
9802
  {
9796
- "path": "percentage",
9803
+ "path": "speed",
9797
9804
  "valueType": "number"
9798
9805
  },
9799
9806
  {
@@ -9893,7 +9900,7 @@ Object.freeze({
9893
9900
  }
9894
9901
  ],
9895
9902
  "humidity-sensor": [{
9896
- "path": "percent",
9903
+ "path": "humidity",
9897
9904
  "valueType": "number"
9898
9905
  }],
9899
9906
  "image": [{
@@ -10003,7 +10010,7 @@ Object.freeze({
10003
10010
  "valueType": "number"
10004
10011
  },
10005
10012
  {
10006
- "path": "progressPercent",
10013
+ "path": "progress",
10007
10014
  "valueType": "number"
10008
10015
  },
10009
10016
  {
@@ -10082,11 +10089,11 @@ Object.freeze({
10082
10089
  "valueType": "string"
10083
10090
  },
10084
10091
  {
10085
- "path": "positionMs",
10092
+ "path": "position",
10086
10093
  "valueType": "number"
10087
10094
  },
10088
10095
  {
10089
- "path": "durationMs",
10096
+ "path": "duration",
10090
10097
  "valueType": "number"
10091
10098
  },
10092
10099
  {
@@ -10188,11 +10195,11 @@ Object.freeze({
10188
10195
  ]
10189
10196
  },
10190
10197
  {
10191
- "path": "signalPercent",
10198
+ "path": "signal",
10192
10199
  "valueType": "number"
10193
10200
  },
10194
10201
  {
10195
- "path": "rssiDbm",
10202
+ "path": "rssi",
10196
10203
  "valueType": "number"
10197
10204
  },
10198
10205
  {
@@ -10247,6 +10254,18 @@ Object.freeze({
10247
10254
  "path": "foodLevel",
10248
10255
  "valueType": "number"
10249
10256
  },
10257
+ {
10258
+ "path": "bowlFood",
10259
+ "valueType": "number"
10260
+ },
10261
+ {
10262
+ "path": "eating",
10263
+ "valueType": "boolean"
10264
+ },
10265
+ {
10266
+ "path": "supportsMarkRefilled",
10267
+ "valueType": "boolean"
10268
+ },
10250
10269
  {
10251
10270
  "path": "food1",
10252
10271
  "valueType": "number"
@@ -10311,23 +10330,23 @@ Object.freeze({
10311
10330
  ],
10312
10331
  "power-meter": [
10313
10332
  {
10314
- "path": "watts",
10333
+ "path": "power",
10315
10334
  "valueType": "number"
10316
10335
  },
10317
10336
  {
10318
- "path": "kwhTotal",
10337
+ "path": "energy",
10319
10338
  "valueType": "number"
10320
10339
  },
10321
10340
  {
10322
- "path": "volts",
10341
+ "path": "voltage",
10323
10342
  "valueType": "number"
10324
10343
  },
10325
10344
  {
10326
- "path": "amps",
10345
+ "path": "current",
10327
10346
  "valueType": "number"
10328
10347
  },
10329
10348
  {
10330
- "path": "va",
10349
+ "path": "apparentPower",
10331
10350
  "valueType": "number"
10332
10351
  },
10333
10352
  {
@@ -10355,14 +10374,10 @@ Object.freeze({
10355
10374
  {
10356
10375
  "path": "gps.accuracyMeters",
10357
10376
  "valueType": "number"
10358
- },
10359
- {
10360
- "path": "batteryPercent",
10361
- "valueType": "number"
10362
10377
  }
10363
10378
  ],
10364
10379
  "pressure-sensor": [{
10365
- "path": "hpa",
10380
+ "path": "pressure",
10366
10381
  "valueType": "number"
10367
10382
  }],
10368
10383
  "privacy-mask": [{
@@ -10676,7 +10691,7 @@ Object.freeze({
10676
10691
  "valueType": "boolean"
10677
10692
  }],
10678
10693
  "temperature-sensor": [{
10679
- "path": "celsius",
10694
+ "path": "temperature",
10680
10695
  "valueType": "number"
10681
10696
  }],
10682
10697
  "update": [
@@ -10724,7 +10739,7 @@ Object.freeze({
10724
10739
  "valueType": "string"
10725
10740
  },
10726
10741
  {
10727
- "path": "progressPercent",
10742
+ "path": "progress",
10728
10743
  "valueType": "number"
10729
10744
  },
10730
10745
  {
@@ -11209,7 +11224,7 @@ function errMsg(err) {
11209
11224
  return String(err);
11210
11225
  }
11211
11226
  //#endregion
11212
- //#region ../types/dist/composition-Bb8iwHEJ.mjs
11227
+ //#region ../types/dist/composition-CZImLpOI.mjs
11213
11228
  /**
11214
11229
  * The ffmpeg build every CamStack node downloads, per platform and arch.
11215
11230
  *
@@ -15873,6 +15888,14 @@ var AutomationConditionLeafSchema = object({
15873
15888
  array(union([string(), number()]))
15874
15889
  ])
15875
15890
  });
15891
+ var AutomationConditionStationaryPresentSchema = object({
15892
+ kind: literal("stationary-present"),
15893
+ deviceId: number().int().nonnegative(),
15894
+ /** Class names; a macro class matches every raw class that maps to it. */
15895
+ classes: array(string().min(1)).min(1).optional(),
15896
+ /** The parked object must be in at least one of these zones. */
15897
+ zones: array(string().min(1)).min(1).optional()
15898
+ });
15876
15899
  /**
15877
15900
  * The expression leaf, declared as a plain object rather than an intersection
15878
15901
  * with {@link ExpressionSourceSchema}: a discriminated union has to be able to
@@ -15906,7 +15929,8 @@ var AutomationConditionSchema = lazy(() => discriminatedUnion("kind", [
15906
15929
  child: AutomationConditionSchema
15907
15930
  }),
15908
15931
  AutomationConditionLeafSchema,
15909
- AutomationConditionExpressionSchema
15932
+ AutomationConditionExpressionSchema,
15933
+ AutomationConditionStationaryPresentSchema
15910
15934
  ]));
15911
15935
  /**
15912
15936
  * What starts a run.
@@ -15947,7 +15971,34 @@ var AutomationTriggerSchema = discriminatedUnion("kind", [
15947
15971
  kind: literal("schedule"),
15948
15972
  cron: string().min(1).max(120)
15949
15973
  }),
15950
- object({ kind: literal("manual") })
15974
+ object({ kind: literal("manual") }),
15975
+ object({
15976
+ kind: literal("detection"),
15977
+ /** Class names. A macro class (`animal`, `vehicle`, `person`, `package`)
15978
+ * matches every raw class that maps to it; any other name matches
15979
+ * exactly. */
15980
+ classes: array(string().min(1)).min(1),
15981
+ deviceIds: array(number().int().nonnegative()).min(1),
15982
+ /** The track must have visited at least one of these zones. */
15983
+ zones: array(string().min(1)).min(1).optional(),
15984
+ /** Best-so-far confidence the track must reach. */
15985
+ minScore: number().min(0).max(1).optional()
15986
+ }),
15987
+ object({
15988
+ kind: literal("stationary"),
15989
+ deviceIds: array(number().int().nonnegative()).min(1),
15990
+ /** Class names; a macro class matches like the detection trigger. */
15991
+ classes: array(string().min(1)).min(1).optional(),
15992
+ /** The parked object must be in at least one of these zones. */
15993
+ zones: array(string().min(1)).min(1).optional(),
15994
+ /** `appeared`: it became parked. `departed`: the registry retired it.
15995
+ * The vocabulary of `PipelineAnalyticsStationaryChanged`. */
15996
+ phase: _enum(["appeared", "departed"])
15997
+ }),
15998
+ object({
15999
+ kind: literal("interval"),
16000
+ minutes: number().int().min(1).max(1440)
16001
+ })
15951
16002
  ]);
15952
16003
  /**
15953
16004
  * One action step.
@@ -15967,28 +16018,47 @@ var AutomationTriggerSchema = discriminatedUnion("kind", [
15967
16018
  * is called. The runner still receives a number and is untouched; the
15968
16019
  * resolution is the recipe's job, not the runner's.
15969
16020
  */
16021
+ var AutomationWaitStepSchema = object({
16022
+ kind: literal("wait"),
16023
+ seconds: number().min(0).max(300)
16024
+ });
16025
+ var AutomationCapStepSchema = object({
16026
+ kind: literal("cap"),
16027
+ /**
16028
+ * One device, several same-family devices (locks / climate family / …),
16029
+ * or `{ $var }` for the device that triggered the run. An array is
16030
+ * fan-out at codegen — each id gets the same cap.method call.
16031
+ */
16032
+ deviceId: union([
16033
+ number().int(),
16034
+ array(number().int()).min(1),
16035
+ object({ $var: string().min(1) })
16036
+ ]),
16037
+ cap: string().min(1),
16038
+ method: string().min(1),
16039
+ /** Values may carry `{{vars.x}}` slots, or be exactly `{ $var: 'name' }`, which
16040
+ * SUBSTITUTE and do not evaluate (§3.2.3). Anything beyond substitution is
16041
+ * the expression leaf. */
16042
+ args: record(string(), unknown()).optional()
16043
+ });
16044
+ /**
16045
+ * The steps an internal Action may contain: cap and wait, and nothing that can
16046
+ * call back into an Action — so an Action can never reach itself (no cycles).
16047
+ */
16048
+ var ActionStepSchema = discriminatedUnion("kind", [AutomationWaitStepSchema, AutomationCapStepSchema]);
15970
16049
  var AutomationActionSchema = discriminatedUnion("kind", [
16050
+ AutomationWaitStepSchema,
16051
+ AutomationCapStepSchema,
15971
16052
  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()
16053
+ kind: literal("action"),
16054
+ /** An entry of the `actions` surface (`internal:<uuid>` or `<addonId>:<localId>`). */
16055
+ actionId: string().min(1),
16056
+ /** Values for the action's declared variables; the others take their default. */
16057
+ variables: record(string(), union([
16058
+ string(),
16059
+ number(),
16060
+ boolean()
16061
+ ])).optional()
15992
16062
  }),
15993
16063
  object({
15994
16064
  kind: literal("code"),
@@ -15997,10 +16067,357 @@ var AutomationActionSchema = discriminatedUnion("kind", [
15997
16067
  code: string().min(1).max(2e4)
15998
16068
  })
15999
16069
  ]);
16070
+ /**
16071
+ * How a trigger that arrives while the automation is busy (or cooling down) is
16072
+ * handled. One of the automation's execution modes, never a property of its
16073
+ * actions. Absent means `single`.
16074
+ *
16075
+ * - `single` — drop the trigger while a run is in progress (traced + logged).
16076
+ * - `restart` — abort the run in progress (at its next step boundary), start fresh.
16077
+ * - `queued` — queue up to `max` triggers, drop the rest (traced).
16078
+ * - `parallel` — up to `max` runs at once, drop the rest (traced).
16079
+ * - `cooldown` — `single`, and no new run until `minutes` after the last run
16080
+ * STARTED; persisted across a restart. A manual trigger bypasses only this
16081
+ * wait, never the single/queued limits.
16082
+ */
16083
+ var AutomationRunModeSchema = discriminatedUnion("mode", [
16084
+ object({ mode: literal("single") }),
16085
+ object({ mode: literal("restart") }),
16086
+ object({
16087
+ mode: literal("queued"),
16088
+ max: number().int().min(1).max(10)
16089
+ }),
16090
+ object({
16091
+ mode: literal("parallel"),
16092
+ max: number().int().min(1).max(10)
16093
+ }),
16094
+ object({
16095
+ mode: literal("cooldown"),
16096
+ minutes: number().int().min(1).max(1440)
16097
+ })
16098
+ ]);
16000
16099
  var AutomationRecipeSchema = object({
16001
16100
  triggers: array(AutomationTriggerSchema),
16002
16101
  conditions: AutomationConditionSchema.optional(),
16003
- actions: array(AutomationActionSchema)
16102
+ actions: array(AutomationActionSchema),
16103
+ runMode: AutomationRunModeSchema.optional(),
16104
+ /** How many run traces the automation keeps (default {@link DEFAULT_TRACE_KEEP}). */
16105
+ keepTraces: number().int().min(1).max(100).optional()
16106
+ });
16107
+ new Set([
16108
+ {
16109
+ id: "person",
16110
+ name: "Person"
16111
+ },
16112
+ {
16113
+ id: "vehicle",
16114
+ name: "Vehicle"
16115
+ },
16116
+ {
16117
+ id: "animal",
16118
+ name: "Animal"
16119
+ },
16120
+ {
16121
+ id: "package",
16122
+ name: "Package"
16123
+ }
16124
+ ].map((l) => l.id));
16125
+ var COCO_TO_MACRO = {
16126
+ mapping: {
16127
+ person: "person",
16128
+ bicycle: "vehicle",
16129
+ car: "vehicle",
16130
+ motorcycle: "vehicle",
16131
+ airplane: "vehicle",
16132
+ bus: "vehicle",
16133
+ train: "vehicle",
16134
+ truck: "vehicle",
16135
+ boat: "vehicle",
16136
+ bird: "animal",
16137
+ cat: "animal",
16138
+ dog: "animal",
16139
+ horse: "animal",
16140
+ sheep: "animal",
16141
+ cow: "animal",
16142
+ elephant: "animal",
16143
+ bear: "animal",
16144
+ zebra: "animal",
16145
+ giraffe: "animal",
16146
+ suitcase: "package",
16147
+ backpack: "package",
16148
+ handbag: "package"
16149
+ },
16150
+ preserveOriginal: false
16151
+ };
16152
+ new Set(Object.values(COCO_TO_MACRO.mapping));
16153
+ /**
16154
+ * Run traces — what an automation (or, later, an Action run) DID, node by node,
16155
+ * so the editor can paint every block green or red with its reason.
16156
+ *
16157
+ * A trace is data, not a log: it covers the WHOLE tree — the trigger stage,
16158
+ * every condition node (containers and leaves, including the ones a
16159
+ * short-circuit never reached), the run-mode verdict and every action step —
16160
+ * each addressed by a stable path (`conditions.0.1`, `actions.2`, or `steps.N`
16161
+ * for an Action run). Skipped
16162
+ * evaluations are traced too, and identical consecutive skips collapse into a
16163
+ * repeat count so a trigger that fails every 5 minutes cannot flush real runs.
16164
+ *
16165
+ * {@link AutomationStepTraceSchema} is deliberately free of automation
16166
+ * vocabulary so an Action run records the same step shape.
16167
+ */
16168
+ /** A value a trace may show: JSON primitives and short lists, nothing deeper. */
16169
+ var TraceValueSchema = union([
16170
+ string(),
16171
+ number(),
16172
+ boolean(),
16173
+ _null(),
16174
+ array(union([string(), number()]))
16175
+ ]);
16176
+ var AutomationRunOutcomeSchema = _enum([
16177
+ "ran",
16178
+ "skipped-trigger",
16179
+ "skipped-conditions",
16180
+ "skipped-cooldown",
16181
+ "skipped-overlap",
16182
+ "failed",
16183
+ "aborted"
16184
+ ]);
16185
+ /** `not-evaluated` = a short-circuit never reached the node. */
16186
+ var TraceNodeOutcomeSchema = _enum([
16187
+ "pass",
16188
+ "fail",
16189
+ "not-evaluated"
16190
+ ]);
16191
+ var AutomationTriggerTraceSchema = object({
16192
+ kind: string().min(1),
16193
+ outcome: _enum(["pass", "fail"]),
16194
+ /** Why an event was rejected ("class person not in [dog]") or what fired. */
16195
+ reason: string(),
16196
+ /** deviceId, className, trackId, score … — only what the trigger exposes. */
16197
+ vars: record(string(), TraceValueSchema)
16198
+ });
16199
+ var AutomationConditionTraceNodeSchema = object({
16200
+ /** `conditions` for the root, `conditions.<i>` for its i-th child, … */
16201
+ path: string().min(1),
16202
+ kind: _enum([
16203
+ "all",
16204
+ "any",
16205
+ "not",
16206
+ "condition",
16207
+ "expression",
16208
+ "stationary-present"
16209
+ ]),
16210
+ outcome: TraceNodeOutcomeSchema,
16211
+ reason: string(),
16212
+ deviceId: number().int().optional(),
16213
+ cap: string().optional(),
16214
+ fieldPath: string().optional(),
16215
+ operator: string().optional(),
16216
+ expected: TraceValueSchema.optional(),
16217
+ /** What the mirror held; `null` when it held nothing (unknown). */
16218
+ observed: TraceValueSchema.optional()
16219
+ });
16220
+ var AutomationRunVerdictSchema = object({
16221
+ mode: AutomationRunModeSchema,
16222
+ decision: _enum([
16223
+ "run",
16224
+ "queued",
16225
+ "restart",
16226
+ "drop",
16227
+ "cooldown",
16228
+ "bypass"
16229
+ ]),
16230
+ reason: string()
16231
+ });
16232
+ /** One executed (or not-run) step — shared by automations and Action runs. */
16233
+ var AutomationStepTraceSchema = object({
16234
+ /** `actions.<i>` */
16235
+ path: string().min(1),
16236
+ kind: string().min(1),
16237
+ cap: string().optional(),
16238
+ method: string().optional(),
16239
+ deviceId: number().int().optional(),
16240
+ startedAt: number().optional(),
16241
+ endedAt: number().optional(),
16242
+ outcome: _enum([
16243
+ "ok",
16244
+ "error",
16245
+ "not-run"
16246
+ ]),
16247
+ message: string().optional()
16248
+ });
16249
+ var AutomationRunTraceSchema = object({
16250
+ runId: string().min(1),
16251
+ startedAt: number(),
16252
+ endedAt: number(),
16253
+ trigger: AutomationTriggerTraceSchema,
16254
+ conditions: array(AutomationConditionTraceNodeSchema),
16255
+ verdict: AutomationRunVerdictSchema.optional(),
16256
+ steps: array(AutomationStepTraceSchema),
16257
+ outcome: AutomationRunOutcomeSchema,
16258
+ /** How many identical consecutive skips this trace stands for (>= 1). */
16259
+ repeat: number().int().min(1),
16260
+ /** When the latest of those repeats happened. */
16261
+ lastAt: number()
16262
+ });
16263
+ /**
16264
+ * What the hub's `runs` ledger holds for one owner (`automation:<blockId>` or
16265
+ * `action:<actionId>`): the cooldown stamp and the trace ring.
16266
+ */
16267
+ var AutomationStateDocSchema = object({
16268
+ version: literal(1),
16269
+ lastRunStartedAt: number().nullable(),
16270
+ traces: array(AutomationRunTraceSchema)
16271
+ });
16272
+ /**
16273
+ * Actions — named, runnable things an operator (or an automation) can start,
16274
+ * declared as LIST ENTRIES, never as devices.
16275
+ *
16276
+ * An entry is either **internal** (a short list of cap/wait steps kept in the
16277
+ * hub's `actions` record kind) or declared by an addon through the
16278
+ * `action-source` collection (a Home Assistant script, a scene …). The one
16279
+ * surface the UI and automations talk to is the `actions` cap; it keeps no
16280
+ * catalog of its own (D3) — every `list` asks the providers live.
16281
+ *
16282
+ * This file is the data half: the entry schema, the variables an entry may
16283
+ * declare, and the pure resolution of the values a run was given. It holds no
16284
+ * runtime.
16285
+ */
16286
+ /** What a variable's value is. `select` takes one of `options`. */
16287
+ var ActionVariableTypeSchema = _enum([
16288
+ "string",
16289
+ "number",
16290
+ "boolean",
16291
+ "select"
16292
+ ]);
16293
+ var ACTION_VARIABLE_NAME_RE = /^[A-Za-z_][A-Za-z0-9_]*$/;
16294
+ var ActionVariableValueSchema = union([
16295
+ string(),
16296
+ number(),
16297
+ boolean()
16298
+ ]);
16299
+ /**
16300
+ * One declared variable. Steps reference it as `{ $var: 'name' }` (the whole
16301
+ * value) or `{{vars.name}}` (inside a string) in their args.
16302
+ */
16303
+ var ActionVariableSchema = object({
16304
+ name: string().regex(ACTION_VARIABLE_NAME_RE),
16305
+ label: string().min(1).max(120).optional(),
16306
+ type: ActionVariableTypeSchema,
16307
+ required: boolean().optional(),
16308
+ default: ActionVariableValueSchema.optional(),
16309
+ /** The allowed values of a `select`. */
16310
+ options: array(string().min(1)).min(1).optional()
16311
+ }).superRefine((v, ctx) => {
16312
+ if (v.type === "select" && v.options === void 0) ctx.addIssue({
16313
+ code: "custom",
16314
+ message: "a select variable needs options",
16315
+ path: ["options"]
16316
+ });
16317
+ if (v.default !== void 0 && variableValueError(v, v.default) !== null) ctx.addIssue({
16318
+ code: "custom",
16319
+ message: variableValueError(v, v.default) ?? "invalid default",
16320
+ path: ["default"]
16321
+ });
16322
+ });
16323
+ /** Why `value` is not a legal value for the variable, or null when it is. */
16324
+ function variableValueError(variable, value) {
16325
+ switch (variable.type) {
16326
+ case "string": return typeof value === "string" ? null : `variable "${variable.name}" must be a string`;
16327
+ case "number": return typeof value === "number" && Number.isFinite(value) ? null : `variable "${variable.name}" must be a number`;
16328
+ case "boolean": return typeof value === "boolean" ? null : `variable "${variable.name}" must be true or false`;
16329
+ case "select": return typeof value === "string" && (variable.options ?? []).includes(value) ? null : `variable "${variable.name}" must be one of ${(variable.options ?? []).join(", ")}`;
16330
+ }
16331
+ }
16332
+ var ActionSourceKindSchema = _enum(["internal", "addon"]);
16333
+ function isInternalActionId(actionId) {
16334
+ return actionId.startsWith("internal:") && actionId.length > 9;
16335
+ }
16336
+ /** The addon behind a `<addonId>:<localId>` id, or null for anything else (internal included). */
16337
+ function addonIdOfActionId(actionId) {
16338
+ if (isInternalActionId(actionId)) return null;
16339
+ const at = actionId.indexOf(":");
16340
+ return at > 0 && at < actionId.length - 1 ? actionId.slice(0, at) : null;
16341
+ }
16342
+ var ActionStatusSchema = object({
16343
+ isRunning: boolean(),
16344
+ /** Ms epoch the latest run STARTED; null when it never ran. */
16345
+ lastRunAt: number().nullable(),
16346
+ /** The latest run's failure; null on success or when it never ran. */
16347
+ lastError: string().nullable()
16348
+ });
16349
+ var ActionEntrySchema = object({
16350
+ /** `internal:<uuid>` or `<addonId>:<localId>`. */
16351
+ id: string().min(3),
16352
+ name: string().min(1).max(120),
16353
+ /** The addon that declared it; `core-blocks` for an internal one. */
16354
+ addonId: string().min(1),
16355
+ source: ActionSourceKindSchema,
16356
+ /** An addon-declared entry is edited where it was declared. */
16357
+ readOnly: boolean(),
16358
+ /** Internal only: cap and wait steps. No action-in-action, so no cycles. */
16359
+ steps: array(ActionStepSchema).min(1).max(50).optional(),
16360
+ variables: array(ActionVariableSchema).max(20).optional(),
16361
+ status: ActionStatusSchema
16362
+ }).superRefine((entry, ctx) => {
16363
+ if (entry.source === "internal") {
16364
+ if (!isInternalActionId(entry.id)) ctx.addIssue({
16365
+ code: "custom",
16366
+ message: "an internal action id is internal:<uuid>",
16367
+ path: ["id"]
16368
+ });
16369
+ return;
16370
+ }
16371
+ if (entry.steps !== void 0) ctx.addIssue({
16372
+ code: "custom",
16373
+ message: "only an internal action carries steps",
16374
+ path: ["steps"]
16375
+ });
16376
+ if (!entry.readOnly) ctx.addIssue({
16377
+ code: "custom",
16378
+ message: "an addon action is read-only here",
16379
+ path: ["readOnly"]
16380
+ });
16381
+ if (addonIdOfActionId(entry.id) === null) ctx.addIssue({
16382
+ code: "custom",
16383
+ message: "an addon action id is <addonId>:<localId>",
16384
+ path: ["id"]
16385
+ });
16386
+ });
16387
+ /** What an operator writes for an internal action. */
16388
+ var ActionInputSchema = object({
16389
+ name: string().min(1).max(120),
16390
+ steps: array(ActionStepSchema).min(1).max(50),
16391
+ variables: array(ActionVariableSchema).max(20).optional()
16392
+ });
16393
+ /** Who started a run. Absent = the operator pressed it. */
16394
+ var ActionRunOriginSchema = object({
16395
+ /** The automation block whose step started it. */
16396
+ blockId: string().min(1).optional() });
16397
+ /** `started` = the caller did not ask to wait. */
16398
+ var ActionRunOutcomeSchema = union([AutomationRunOutcomeSchema, literal("started")]);
16399
+ var ActionRunResultSchema = object({
16400
+ runId: string().min(1),
16401
+ outcome: ActionRunOutcomeSchema,
16402
+ /** Why it did not run, or what failed. */
16403
+ message: string().optional()
16404
+ });
16405
+ _enum([
16406
+ "not-found",
16407
+ "read-only",
16408
+ "invalid-variables",
16409
+ "invalid-steps",
16410
+ "not-linked",
16411
+ "busy"
16412
+ ]);
16413
+ object({
16414
+ actionId: string(),
16415
+ runId: string(),
16416
+ isRunning: boolean(),
16417
+ /** Set when the run ended. */
16418
+ outcome: AutomationRunOutcomeSchema.optional(),
16419
+ lastRunAt: number().nullable(),
16420
+ lastError: string().nullable()
16004
16421
  });
16005
16422
  /**
16006
16423
  * `addon-pages` — system-scoped singleton aggregator cap. Public-facing
@@ -18755,7 +19172,7 @@ var CompositionEventPlanSchema = object({
18755
19172
  stateField: string(),
18756
19173
  fieldKey: string()
18757
19174
  });
18758
- /** One refusal, named (D391). `path` points into the composition, e.g. `features[0].fields.celsius`. */
19175
+ /** One refusal, named (D391). `path` points into the composition, e.g. `features[0].fields.temperature`. */
18759
19176
  var CompositionProblemSchema = object({
18760
19177
  code: _enum([
18761
19178
  "reserved-variant",
@@ -19074,7 +19491,7 @@ var GROUP_TEMPLATES = [
19074
19491
  summary: "Mean, median, min, max or sum of temperatures. Offline and unknown members are left out, never read as 0 °C.",
19075
19492
  role: DeviceRole.TemperatureSensor,
19076
19493
  outputCap: "temperature-sensor",
19077
- outputField: "celsius",
19494
+ outputField: "temperature",
19078
19495
  quantity: "temperature",
19079
19496
  defaultAggregate: "mean",
19080
19497
  empty: "null",
@@ -19085,7 +19502,7 @@ var GROUP_TEMPLATES = [
19085
19502
  summary: "Humidity in percent. Offline and unknown members are left out, never read as 0 %.",
19086
19503
  role: DeviceRole.HumiditySensor,
19087
19504
  outputCap: "humidity-sensor",
19088
- outputField: "percent",
19505
+ outputField: "humidity",
19089
19506
  quantity: "humidity",
19090
19507
  defaultAggregate: "mean",
19091
19508
  empty: "null",
@@ -19096,7 +19513,7 @@ var GROUP_TEMPLATES = [
19096
19513
  summary: "Pressure in hectopascals. Offline and unknown members are left out, never read as 0 hPa.",
19097
19514
  role: DeviceRole.PressureSensor,
19098
19515
  outputCap: "pressure-sensor",
19099
- outputField: "hpa",
19516
+ outputField: "pressure",
19100
19517
  quantity: "pressure",
19101
19518
  defaultAggregate: "mean",
19102
19519
  empty: "null",
@@ -19107,7 +19524,7 @@ var GROUP_TEMPLATES = [
19107
19524
  summary: "Illuminance in lux. Offline and unknown members are left out, never read as 0 lx.",
19108
19525
  role: DeviceRole.AmbientLightSensor,
19109
19526
  outputCap: "ambient-light-sensor",
19110
- outputField: "lux",
19527
+ outputField: "illuminance",
19111
19528
  quantity: "illuminance",
19112
19529
  defaultAggregate: "mean",
19113
19530
  empty: "null",
@@ -19118,7 +19535,7 @@ var GROUP_TEMPLATES = [
19118
19535
  summary: "Power in watts, summed by default. Nobody reporting omits the key rather than writing 0 W.",
19119
19536
  role: DeviceRole.PowerSensor,
19120
19537
  outputCap: "power-meter",
19121
- outputField: "watts",
19538
+ outputField: "power",
19122
19539
  quantity: "power",
19123
19540
  defaultAggregate: "sum",
19124
19541
  empty: "omit",
@@ -19129,7 +19546,7 @@ var GROUP_TEMPLATES = [
19129
19546
  summary: "Energy in kilowatt-hours, summed by default. Nobody reporting omits the key rather than writing 0 kWh.",
19130
19547
  role: DeviceRole.EnergySensor,
19131
19548
  outputCap: "power-meter",
19132
- outputField: "kwhTotal",
19549
+ outputField: "energy",
19133
19550
  quantity: "energy",
19134
19551
  defaultAggregate: "sum",
19135
19552
  empty: "omit",
@@ -19140,7 +19557,7 @@ var GROUP_TEMPLATES = [
19140
19557
  summary: "Battery charge in percent. Offline and unknown members are left out, never read as 0 %.",
19141
19558
  role: DeviceRole.BatterySensor,
19142
19559
  outputCap: "battery",
19143
- outputField: "percentage",
19560
+ outputField: "level",
19144
19561
  quantity: "percentage",
19145
19562
  defaultAggregate: "mean",
19146
19563
  empty: "null",
@@ -19718,7 +20135,18 @@ method(object({}), object({ blocks: array(CoreBlockSchema) }), { auth: "admin" }
19718
20135
  kind: "mutation",
19719
20136
  auth: "admin",
19720
20137
  access: "view"
19721
- });
20138
+ }), method(object({
20139
+ blockId: string().min(1),
20140
+ trace: AutomationRunTraceSchema.optional(),
20141
+ runStartedAt: number().optional(),
20142
+ keepTraces: number().int().min(1).max(100).optional()
20143
+ }), _void(), {
20144
+ kind: "mutation",
20145
+ auth: "admin"
20146
+ }), method(object({ blockId: string().min(1) }), AutomationStateDocSchema, { auth: "admin" }), method(object({ blockId: string().min(1) }), object({
20147
+ traces: array(AutomationRunTraceSchema),
20148
+ lastError: string().nullable()
20149
+ }), { auth: "admin" });
19722
20150
  /**
19723
20151
  * `custom-model-registry` — collection cap exposing operator-registered
19724
20152
  * custom detection models. Each provider (today: `addon-model-studio`)
@@ -45288,51 +45716,6 @@ var notificationOutputCapability = {
45288
45716
  })
45289
45717
  }
45290
45718
  };
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
45719
  var AUDIO_MACRO_LABELS = [
45337
45720
  {
45338
45721
  id: "speech",
@@ -57987,9 +58370,9 @@ method(object({ nodeId: string().optional() }).optional(), array(AddonListItemSc
57987
58370
  */
57988
58371
  var AirQualitySensorStatusSchema = object({
57989
58372
  /** Carbon dioxide concentration in ppm. */
57990
- co2Ppm: number().min(0).optional().meta(readingMeta("concentration-volume")),
58373
+ co2: number().min(0).optional().meta(readingMeta("concentration-volume")),
57991
58374
  /** Total volatile organic compounds in ppb. */
57992
- vocPpb: number().min(0).optional().meta(readingMeta("concentration-ppb")),
58375
+ voc: number().min(0).optional().meta(readingMeta("concentration-ppb")),
57993
58376
  /** Particulate matter ≤ 2.5 μm in µg/m³. */
57994
58377
  pm25: number().min(0).optional().meta(readingMeta("concentration-mass")),
57995
58378
  /** Particulate matter ≤ 10 μm in µg/m³. */
@@ -58022,12 +58405,12 @@ var airQualitySensorCapability = {
58022
58405
  * History (D850): recorded series.
58023
58406
  */
58024
58407
  history: { fields: {
58025
- co2Ppm: {
58408
+ co2: {
58026
58409
  kind: "gauge",
58027
58410
  unit: "ppm",
58028
58411
  deadband: 5
58029
58412
  },
58030
- vocPpb: {
58413
+ voc: {
58031
58414
  kind: "gauge",
58032
58415
  unit: "ppb",
58033
58416
  deadband: 5
@@ -58058,7 +58441,7 @@ var airQualitySensorCapability = {
58058
58441
  */
58059
58442
  var AmbientLightSensorStatusSchema = object({
58060
58443
  /** Current illuminance in lux (lx). `null` when the sample was refused (D393). */
58061
- lux: number().min(0).nullable().meta(readingMeta("illuminance", {
58444
+ illuminance: number().min(0).nullable().meta(readingMeta("illuminance", {
58062
58445
  precision: 0,
58063
58446
  label: "Illuminance"
58064
58447
  })),
@@ -58087,7 +58470,7 @@ var ambientLightSensorCapability = {
58087
58470
  /**
58088
58471
  * History (D850): recorded series. Wide range, so a RELATIVE deadband (10 %).
58089
58472
  */
58090
- history: { fields: { lux: {
58473
+ history: { fields: { illuminance: {
58091
58474
  kind: "gauge",
58092
58475
  unit: "lx",
58093
58476
  deadbandPct: 10,
@@ -58226,6 +58609,84 @@ var audioMetricsCapability = {
58226
58609
  */
58227
58610
  history: "none"
58228
58611
  };
58612
+ method(object({}), array(ActionEntrySchema), { auth: "admin" }), method(object({
58613
+ actionId: string().min(1),
58614
+ variables: record(string(), ActionVariableValueSchema).optional()
58615
+ }), _void(), {
58616
+ kind: "mutation",
58617
+ auth: "admin"
58618
+ }), method(object({ actionId: string().min(1) }), _void(), {
58619
+ kind: "mutation",
58620
+ auth: "admin"
58621
+ });
58622
+ /**
58623
+ * actions — the ONE surface for runnable actions, for the UI and for
58624
+ * automations. Provided by the core-blocks builtin on the hub.
58625
+ *
58626
+ * An action is a LIST ENTRY, not a device (D883): either internal (cap and wait
58627
+ * steps, kept in the hub's `actions` record kind) or declared by an addon over
58628
+ * `action-source`. `list` asks every `action-source` provider LIVE and overlays
58629
+ * the run status from the hub's `runs` ledger; there is no catalog here to
58630
+ * drift (D3).
58631
+ *
58632
+ * **Permissions follow the camera, as linked devices do.** An action is linked
58633
+ * to cameras by the operator (`setLinks`, D356: nothing links itself). A
58634
+ * non-admin may `get` / `run` an action only through a camera they may see that
58635
+ * links it: they name the camera (`deviceId`, a top-level field so the scope
58636
+ * gate sees it) and the provider refuses an action that camera does not link.
58637
+ * An admin, and an in-process caller (an automation block), may run any action.
58638
+ * Every refusal is typed (`[not-linked] …`) and logged.
58639
+ *
58640
+ * A second `run` of an action that is already running is REFUSED — traced and
58641
+ * logged — never queued.
58642
+ */
58643
+ var ActionIdInput = object({ actionId: string().min(1) });
58644
+ var ActionLinksSchema = object({
58645
+ deviceId: number().int().nonnegative(),
58646
+ actionIds: array(string().min(1)).max(100)
58647
+ });
58648
+ method(object({}), array(ActionEntrySchema), { auth: "admin" }), method(object({
58649
+ actionId: string().min(1),
58650
+ deviceId: number().int().nonnegative().optional()
58651
+ }), object({ action: ActionEntrySchema.nullable() }), {
58652
+ role: "viewer",
58653
+ auth: "protected",
58654
+ kind: "query",
58655
+ caller: "required"
58656
+ }), method(object({
58657
+ actionId: string().min(1),
58658
+ variables: record(string(), ActionVariableValueSchema).optional(),
58659
+ wait: boolean().optional(),
58660
+ origin: ActionRunOriginSchema.optional(),
58661
+ deviceId: number().int().nonnegative().optional()
58662
+ }), ActionRunResultSchema, {
58663
+ role: "viewer",
58664
+ auth: "protected",
58665
+ kind: "mutation",
58666
+ caller: "required"
58667
+ }), method(ActionIdInput, _void(), {
58668
+ kind: "mutation",
58669
+ auth: "admin"
58670
+ }), method(ActionIdInput, object({ traces: array(AutomationRunTraceSchema) }), { auth: "admin" }), method(object({ action: ActionInputSchema }), object({ action: ActionEntrySchema }), {
58671
+ kind: "mutation",
58672
+ auth: "admin"
58673
+ }), method(object({
58674
+ actionId: string().min(1),
58675
+ action: ActionInputSchema.partial()
58676
+ }), object({ action: ActionEntrySchema }), {
58677
+ kind: "mutation",
58678
+ auth: "admin"
58679
+ }), method(ActionIdInput, _void(), {
58680
+ kind: "mutation",
58681
+ auth: "admin"
58682
+ }), method(object({ deviceId: number().int().nonnegative() }), array(ActionEntrySchema), {
58683
+ role: "viewer",
58684
+ auth: "protected",
58685
+ kind: "query"
58686
+ }), method(object({ deviceId: number().int().nonnegative() }), ActionLinksSchema, { auth: "admin" }), method(ActionLinksSchema, ActionLinksSchema, {
58687
+ kind: "mutation",
58688
+ auth: "admin"
58689
+ });
58229
58690
  /**
58230
58691
  * Automation-control cap. Models HA `automation.*` entities on
58231
58692
  * `DeviceType.Automation`. An automation is a trigger+condition+
@@ -58322,7 +58783,7 @@ var BatteryStatusSchema = object({
58322
58783
  * Consumers must SKIP a null rather than coerce it — `battery-band` already
58323
58784
  * declines to band a non-finite reading, which is the correct shape.
58324
58785
  */
58325
- percentage: number().min(0).max(100).nullable().meta(readingMeta("percentage", { label: "Charge" })),
58786
+ level: number().min(0).max(100).nullable().meta(readingMeta("percentage", { label: "Charge" })),
58326
58787
  /**
58327
58788
  * Charging source. `'dc'` covers wall/USB adapters; `'solar'` is
58328
58789
  * Reolink-specific for the Solar Panel 2 accessory (will become
@@ -58332,7 +58793,7 @@ var BatteryStatusSchema = object({
58332
58793
  * `'unknown'` is the absence of an answer: the provider has not read the
58333
58794
  * power fields yet, or the firmware reported neither. Before it existed,
58334
58795
  * two unreadable fields produced `'none'`, and a camera nobody had reached
58335
- * was drawn "on battery alone" — the same D315 defect `percentage` closed
58796
+ * was drawn "on battery alone" — the same D315 defect `level` closed
58336
58797
  * by going nullable. Consumers SKIP it (no charger state published, no
58337
58798
  * glyph, no HomeKit ChargingState) rather than coerce it either way.
58338
58799
  */
@@ -58356,7 +58817,7 @@ var BatteryStatusSchema = object({
58356
58817
  * that only report charge. A second reading on this cap, not a second
58357
58818
  * `numeric-sensor` on the same device.
58358
58819
  */
58359
- volts: number().nullable().optional().meta(readingMeta("voltage", { label: "Voltage" })),
58820
+ voltage: number().nullable().optional().meta(readingMeta("voltage", { label: "Voltage" })),
58360
58821
  /**
58361
58822
  * Ms epoch of the last time the device PROVED it was reachable — a
58362
58823
  * completed firmware round-trip, an observed wake, or an inbound push
@@ -58390,7 +58851,7 @@ var BatteryStatusSchema = object({
58390
58851
  /**
58391
58852
  * True when the source is a BINARY low-battery indicator (HA
58392
58853
  * `binary_sensor` device_class=battery / `LOW_BAT`) that has no real
58393
- * charge level — `percentage` is then a coarse stand-in (100 = normal,
58854
+ * charge level — `level` is then a coarse stand-in (100 = normal,
58394
58855
  * sub-threshold = low). UI MUST render "Normal"/"Low" instead of a
58395
58856
  * misleading exact percentage. Absent/false → genuine 0–100 % reading.
58396
58857
  */
@@ -58410,15 +58871,15 @@ var BATTERY_DEVICE_TYPES = [
58410
58871
  var batteryCustomize = {
58411
58872
  version: 1,
58412
58873
  targets: [{
58413
- id: "percentage",
58874
+ id: "level",
58414
58875
  cardinality: "scalar",
58415
58876
  vocabulary: {
58416
58877
  cap: "battery",
58417
- stateField: "percentage"
58878
+ stateField: "level"
58418
58879
  },
58419
58880
  deviceTypes: BATTERY_DEVICE_TYPES,
58420
58881
  apply: "add",
58421
- path: "percentage",
58882
+ path: "level",
58422
58883
  sources: [{
58423
58884
  kind: "field",
58424
58885
  valueKinds: ["number", "string"],
@@ -58512,7 +58973,7 @@ onStatusChanged: { data: object({
58512
58973
  schema: BatteryStatusSchema,
58513
58974
  kind: "push",
58514
58975
  empty: {
58515
- percentage: null,
58976
+ level: null,
58516
58977
  charging: "unknown",
58517
58978
  sleeping: false,
58518
58979
  lastUpdated: 0
@@ -58539,11 +59000,11 @@ onStatusChanged: { data: object({
58539
59000
  * History (D850): recorded series. The generic capture replaces the `battery` series of `pipeline-analytics:stats-5m`.
58540
59001
  */
58541
59002
  history: { fields: {
58542
- percentage: {
59003
+ level: {
58543
59004
  kind: "gauge",
58544
59005
  unit: "%"
58545
59006
  },
58546
- volts: {
59007
+ voltage: {
58547
59008
  kind: "gauge",
58548
59009
  unit: "V"
58549
59010
  }
@@ -58603,14 +59064,14 @@ var binaryCapability = {
58603
59064
  * controls to this single-method surface.
58604
59065
  *
58605
59066
  * The cap is intentionally minimal: a single `setBrightness({deviceId,
58606
- * percentage})` mutation plus the auto-injected `getStatus`. Drivers
59067
+ * level})` mutation plus the auto-injected `getStatus`. Drivers
58607
59068
  * that expose richer controls (color temperature, scenes, schedules)
58608
59069
  * should surface those via the device's `getSettingsUISchema()`
58609
59070
  * instead of bloating this cap.
58610
59071
  */
58611
59072
  var BrightnessStatusSchema = object({
58612
59073
  /** Current level as 0..100 inclusive. Firmware-reported. */
58613
- percentage: number().min(0).max(100).meta(readingMeta("percentage")),
59074
+ level: number().min(0).max(100).meta(readingMeta("percentage")),
58614
59075
  /** Ms epoch of the last operator-driven change. Useful for UI freshness. */
58615
59076
  lastChangedAt: number()
58616
59077
  });
@@ -58622,7 +59083,7 @@ var brightnessCapability = {
58622
59083
  deviceTypes: [DeviceType.Light],
58623
59084
  methods: { setBrightness: method(object({
58624
59085
  deviceId: number().int().nonnegative(),
58625
- percentage: number().min(0).max(100)
59086
+ level: number().min(0).max(100)
58626
59087
  }), _void(), {
58627
59088
  kind: "mutation",
58628
59089
  auth: "protected"
@@ -58635,7 +59096,7 @@ var brightnessCapability = {
58635
59096
  */
58636
59097
  onBrightnessChanged: { data: object({
58637
59098
  deviceId: number(),
58638
- percentage: number().min(0).max(100),
59099
+ level: number().min(0).max(100),
58639
59100
  lastChangedAt: number()
58640
59101
  }) } },
58641
59102
  status: {
@@ -58658,7 +59119,7 @@ onBrightnessChanged: { data: object({
58658
59119
  /**
58659
59120
  * History (D850): recorded series. Actuator tier: level keeps every change.
58660
59121
  */
58661
- history: { fields: { percentage: {
59122
+ history: { fields: { level: {
58662
59123
  kind: "gauge",
58663
59124
  unit: "%",
58664
59125
  minIntervalMs: 0
@@ -59282,11 +59743,11 @@ var ColorInputSchema = discriminatedUnion("mode", [
59282
59743
  }),
59283
59744
  object({
59284
59745
  mode: literal("mired"),
59285
- mireds: number().int().min(50).max(1e3)
59746
+ colorTemperature: number().int().min(50).max(1e3)
59286
59747
  })
59287
59748
  ]);
59288
59749
  var ColorStatusSchema = object({
59289
- /** Active color mode — which of `rgb` / `hsv` / `mireds` reflects
59750
+ /** Active color mode — which of `rgb` / `hsv` / `colorTemperature` reflects
59290
59751
  * the bulb's current state. */
59291
59752
  mode: _enum([
59292
59753
  "rgb",
@@ -59298,7 +59759,7 @@ var ColorStatusSchema = object({
59298
59759
  /** Populated when `mode === 'hsv'`. */
59299
59760
  hsv: HsvTripletSchema.optional(),
59300
59761
  /** Populated when `mode === 'mired'`. */
59301
- mireds: number().int().optional().meta(readingMeta("colour-temperature")),
59762
+ colorTemperature: number().int().optional().meta(readingMeta("colour-temperature")),
59302
59763
  /** Ms epoch of the last operator-driven change. */
59303
59764
  lastChangedAt: number()
59304
59765
  });
@@ -59330,7 +59791,7 @@ onColorChanged: { data: object({
59330
59791
  ]),
59331
59792
  rgb: RgbTripletSchema.optional(),
59332
59793
  hsv: HsvTripletSchema.optional(),
59333
- mireds: number().int().optional(),
59794
+ colorTemperature: number().int().optional(),
59334
59795
  lastChangedAt: number()
59335
59796
  }) } },
59336
59797
  status: {
@@ -60221,11 +60682,11 @@ var DishwasherStatusSchema = object({
60221
60682
  /** Feature keys of the programs the appliance currently offers — drives the UI selector. */
60222
60683
  availablePrograms: array(string()),
60223
60684
  /** Seconds remaining on the active cycle, or null when not running / not known. */
60224
- remainingSeconds: number().int().nonnegative().nullable().meta(readingMeta("duration")),
60685
+ remaining: number().int().nonnegative().nullable().meta(readingMeta("duration")),
60225
60686
  /** Seconds the delayed start is set to (time until the cycle starts), or null. */
60226
- delayedStartSeconds: number().int().nonnegative().nullable().meta(readingMeta("duration")),
60687
+ delayedStart: number().int().nonnegative().nullable().meta(readingMeta("duration")),
60227
60688
  /** Cycle completion 0..100, or null when not applicable. */
60228
- progressPercent: number().min(0).max(100).nullable().meta(readingMeta("percentage")),
60689
+ progress: number().min(0).max(100).nullable().meta(readingMeta("percentage")),
60229
60690
  /** True when the door is reported open; null when the door state is not known. */
60230
60691
  doorOpen: boolean().nullable(),
60231
60692
  /** True when the door is latched (locked) during a cycle; null when not reported. */
@@ -60444,14 +60905,14 @@ var dishwasherCapability = {
60444
60905
  runtimeState: DishwasherStatusSchema,
60445
60906
  durability: "session",
60446
60907
  history: { fields: {
60447
- progressPercent: {
60908
+ progress: {
60448
60909
  kind: "gauge",
60449
60910
  unit: "%",
60450
60911
  deadband: 2
60451
60912
  },
60452
60913
  state: { kind: "enum" },
60453
60914
  operationState: { kind: "enum" },
60454
- remainingSeconds: {
60915
+ remaining: {
60455
60916
  kind: "gauge",
60456
60917
  unit: "s",
60457
60918
  minIntervalMs: 6e4
@@ -61052,7 +61513,7 @@ var FanDirectionSchema = _enum(["forward", "reverse"]);
61052
61513
  var FanControlStatusSchema = object({
61053
61514
  /** Active speed as 0..100 inclusive. Null when the device has no
61054
61515
  * speed surface (single-speed fan). */
61055
- percentage: number().min(0).max(100).nullable().meta(readingMeta("percentage")),
61516
+ speed: number().min(0).max(100).nullable().meta(readingMeta("percentage")),
61056
61517
  /** Speed granularity the device accepts (HA `percentage_step`, e.g. 25 for
61057
61518
  * a 4-speed fan). Absent when unknown — the UI then falls back to step 1. */
61058
61519
  percentageStep: number().positive().optional().meta(readingMeta("percentage")),
@@ -61079,7 +61540,7 @@ var fanControlCapability = {
61079
61540
  methods: {
61080
61541
  setPercentage: method(object({
61081
61542
  deviceId: number().int().nonnegative(),
61082
- percentage: number().min(0).max(100)
61543
+ speed: number().min(0).max(100)
61083
61544
  }), _void(), {
61084
61545
  kind: "mutation",
61085
61546
  auth: "protected"
@@ -61112,7 +61573,7 @@ var fanControlCapability = {
61112
61573
  },
61113
61574
  /**
61114
61575
  * Runtime-state slice — mirrored by the kernel. UI fan speed
61115
- * sliders read `percentage` for live updates.
61576
+ * sliders read `speed` for live updates.
61116
61577
  */
61117
61578
  runtimeState: FanControlStatusSchema,
61118
61579
  /**
@@ -61126,7 +61587,7 @@ var fanControlCapability = {
61126
61587
  * History (D850): recorded series. Actuator tier: speed keeps every change.
61127
61588
  */
61128
61589
  history: { fields: {
61129
- percentage: {
61590
+ speed: {
61130
61591
  kind: "gauge",
61131
61592
  unit: "%",
61132
61593
  minIntervalMs: 0
@@ -61571,7 +62032,7 @@ var humidifierCapability = {
61571
62032
  */
61572
62033
  var HumiditySensorStatusSchema = object({
61573
62034
  /** Current relative humidity, 0..100. `null` when the sample was refused (D393). */
61574
- percent: number().min(0).max(100).nullable().meta(readingMeta("humidity", {
62035
+ humidity: number().min(0).max(100).nullable().meta(readingMeta("humidity", {
61575
62036
  precision: 0,
61576
62037
  label: "Humidity"
61577
62038
  })),
@@ -61600,7 +62061,7 @@ var humiditySensorCapability = {
61600
62061
  /**
61601
62062
  * History (D850): recorded series.
61602
62063
  */
61603
- history: { fields: { percent: {
62064
+ history: { fields: { humidity: {
61604
62065
  kind: "gauge",
61605
62066
  unit: "%",
61606
62067
  deadband: .5
@@ -62240,7 +62701,7 @@ var LawnMowerControlStatusSchema = object({
62240
62701
  batteryLevel: number().min(0).max(100).nullable().meta(readingMeta("percentage")),
62241
62702
  /** 0..100 mowing-completion percentage of the current task, or null when no
62242
62703
  * task is active / progress is unavailable. */
62243
- progressPercent: number().min(0).max(100).nullable().meta(readingMeta("percentage")),
62704
+ progress: number().min(0).max(100).nullable().meta(readingMeta("percentage")),
62244
62705
  /** Current device/event code (dynamic — mostly status, sometimes an error),
62245
62706
  * or null when unknown. */
62246
62707
  currentCode: number().nullable().meta(readingMeta("none")),
@@ -62740,7 +63201,7 @@ var lockControlCapability = {
62740
63201
  volatileStateFields: ["lastChangedAt"]
62741
63202
  };
62742
63203
  /**
62743
- * A monotonic total between resets (D944). Energy uses `power-meter.kwhTotal`
63204
+ * A monotonic total between resets (D944). Energy uses `power-meter.energy`
62744
63205
  * so dashboards keep one series; every other instantaneous reading lands here.
62745
63206
  * `value` is the time integral in the source quantity's accumulated base
62746
63207
  * (base-unit seconds, or kWh on the power meter). `null` is a gap, never zero.
@@ -62834,10 +63295,10 @@ var MediaPlayerStatusSchema = object({
62834
63295
  currentMedia: MediaInfoSchema.nullable(),
62835
63296
  /** Current playback position in ms. Null when not seekable or
62836
63297
  * nothing is playing. Pair with `DeviceFeature.MediaPlayerSeek`. */
62837
- positionMs: number().int().nonnegative().nullable().meta(readingMeta("duration-ms")),
63298
+ position: number().int().nonnegative().nullable().meta(readingMeta("duration-ms")),
62838
63299
  /** Total duration of the current media in ms. Null when unknown
62839
63300
  * (live stream) or nothing is playing. */
62840
- durationMs: number().int().nonnegative().nullable().meta(readingMeta("duration-ms")),
63301
+ duration: number().int().nonnegative().nullable().meta(readingMeta("duration-ms")),
62841
63302
  /** Shuffle toggle. Null when no shuffle surface.
62842
63303
  * Pair with `DeviceFeature.MediaPlayerShuffle`. */
62843
63304
  shuffle: boolean().nullable(),
@@ -62876,7 +63337,7 @@ var mediaPlayerCapability = {
62876
63337
  }),
62877
63338
  seek: method(object({
62878
63339
  deviceId: number().int().nonnegative(),
62879
- positionMs: number().int().nonnegative()
63340
+ position: number().int().nonnegative()
62880
63341
  }), _void(), {
62881
63342
  kind: "mutation",
62882
63343
  auth: "protected"
@@ -62948,7 +63409,7 @@ var mediaPlayerCapability = {
62948
63409
  /**
62949
63410
  * History (D850): volume (a level an operator or an automation sets; the
62950
63411
  * default 10 s floor folds a slider drag into its end value) and mute.
62951
- * `positionMs` is not recorded: it moves continuously while playing.
63412
+ * `position` is not recorded: it moves continuously while playing.
62952
63413
  */
62953
63414
  history: { fields: {
62954
63415
  volumeLevel: {
@@ -63910,9 +64371,9 @@ var NetworkLinkStatusSchema = object({
63910
64371
  * one whose reading has not landed must not be drawn at 0 %. Consumers
63911
64372
  * SKIP a null rather than coerce it.
63912
64373
  */
63913
- signalPercent: number().min(0).max(100).nullable().meta(readingMeta("percentage")),
64374
+ signal: number().min(0).max(100).nullable().meta(readingMeta("percentage")),
63914
64375
  /** Raw received signal strength in dBm, when the firmware reports one. */
63915
- rssiDbm: number().optional().meta(readingMeta("signal-level")),
64376
+ rssi: number().optional().meta(readingMeta("signal-level")),
63916
64377
  /** Network name of a wireless link, when the firmware reports it. */
63917
64378
  ssid: string().optional(),
63918
64379
  /** Ms epoch of the last observation. Lets consumers reason about freshness. */
@@ -63948,7 +64409,7 @@ onStatusChanged: { data: object({
63948
64409
  kind: "push",
63949
64410
  empty: {
63950
64411
  type: "unknown",
63951
- signalPercent: null,
64412
+ signal: null,
63952
64413
  lastUpdated: 0
63953
64414
  }
63954
64415
  },
@@ -63971,13 +64432,13 @@ onStatusChanged: { data: object({
63971
64432
  * History (D850): recorded series.
63972
64433
  */
63973
64434
  history: { fields: {
63974
- signalPercent: {
64435
+ signal: {
63975
64436
  kind: "gauge",
63976
64437
  unit: "%",
63977
64438
  deadband: 3,
63978
64439
  minIntervalMs: 6e4
63979
64440
  },
63980
- rssiDbm: {
64441
+ rssi: {
63981
64442
  kind: "gauge",
63982
64443
  unit: "dBm",
63983
64444
  deadband: 2,
@@ -64722,10 +65183,20 @@ var PetFeederDeviceStatusSchema = _enum([
64722
65183
  ]);
64723
65184
  var gramsPortion = number().int().min(4).max(200);
64724
65185
  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`. */
65186
+ /** Food in the TANK (hopper), as the feeder's own sensor reports it
65187
+ * (`state.food`). A coarse level code, not grams — `0` is empty. The
65188
+ * amount in the bowl is `bowlFood`. On dual-hopper models this is the
65189
+ * combined reading; per-hopper levels live in `food1`/`food2`. Null when
65190
+ * the device has not reported yet. */
64728
65191
  foodLevel: number().nullable().meta(readingMeta("none")),
65192
+ /** Food in the BOWL as the feeder reports it (`state.bowl`), in the
65193
+ * feeder's own units. Null when the model reports none. */
65194
+ bowlFood: number().nullable().meta(readingMeta("none")),
65195
+ /** True while the pet is eating (`state.eating`). */
65196
+ eating: boolean(),
65197
+ /** Whether `markFoodReplenished` does anything on this model. When false
65198
+ * the client must not offer it. */
65199
+ supportsMarkRefilled: boolean(),
64729
65200
  /** Hopper-1 food level (grams) on dual-hopper feeders; null on
64730
65201
  * single-hopper models. */
64731
65202
  food1: number().nullable().meta(readingMeta("none")),
@@ -64733,8 +65204,8 @@ var PetFeederStatusSchema = object({
64733
65204
  * single-hopper models. */
64734
65205
  food2: number().nullable().meta(readingMeta("none")),
64735
65206
  /** 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. */
65207
+ * (`device_class: problem`, on = low). True when the tank reports empty,
65208
+ * or, on a dual-hopper model, when EITHER hopper is empty. */
64738
65209
  lowFood: boolean(),
64739
65210
  /** Battery charge 0..100 (%). Null on mains-powered models or when the
64740
65211
  * device has no battery reading. */
@@ -64802,7 +65273,9 @@ var petFeederCapability = {
64802
65273
  kind: "mutation",
64803
65274
  auth: "protected"
64804
65275
  }),
64805
- /** Mark a hopper as refilled (D4H/D4S/D4SH). */
65276
+ /** Tell the PetKit cloud a hopper was refilled so it stops its low-food
65277
+ * reminders (D4H/D4S/D4SH only — see `supportsMarkRefilled`). It does not
65278
+ * change any sensor reading. */
64806
65279
  markFoodReplenished: method(object({ deviceId: number().int().nonnegative() }), _void(), {
64807
65280
  kind: "mutation",
64808
65281
  auth: "protected"
@@ -64875,6 +65348,7 @@ var petFeederCapability = {
64875
65348
  */
64876
65349
  history: { fields: {
64877
65350
  foodLevel: { kind: "gauge" },
65351
+ bowlFood: { kind: "gauge" },
64878
65352
  food1: { kind: "gauge" },
64879
65353
  food2: { kind: "gauge" },
64880
65354
  batteryPower: {
@@ -65284,16 +65758,16 @@ method(_void(), PlatformCapabilitiesSchema), method(_void(), HardwareInfoSchema)
65284
65758
  * in real-world devices.
65285
65759
  */
65286
65760
  var PowerMeterStatusSchema = object({
65287
- /** Instantaneous power draw in watts. */
65288
- watts: number().optional().meta(readingMeta("power", { label: "Power" })),
65761
+ /** Instantaneous power draw (watts). */
65762
+ power: number().optional().meta(readingMeta("power", { label: "Power" })),
65289
65763
  /** 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" })),
65764
+ energy: number().optional().meta(readingMeta("energy", { label: "Energy" })),
65765
+ /** Voltage (volts). */
65766
+ voltage: number().optional().meta(readingMeta("voltage", { label: "Voltage" })),
65293
65767
  /** Current in amperes. */
65294
- amps: number().optional().meta(readingMeta("current", { label: "Current" })),
65768
+ current: number().optional().meta(readingMeta("current", { label: "Current" })),
65295
65769
  /** Apparent power in volt-amperes. */
65296
- va: number().optional().meta(readingMeta("apparent-power")),
65770
+ apparentPower: number().optional().meta(readingMeta("apparent-power")),
65297
65771
  /** Power factor (0..1) if reported. */
65298
65772
  powerFactor: number().min(0).max(1).optional().meta(readingMeta("ratio")),
65299
65773
  /** Ms epoch when the slice was last updated. */
@@ -65351,14 +65825,14 @@ function powerTarget(id, unit) {
65351
65825
  advancedExpression: true
65352
65826
  };
65353
65827
  }
65354
- /** "Power and energy" extension: watts, energy, voltage and current from other devices (D951). */
65828
+ /** "Power and energy" extension: power, energy, voltage and current from other devices (D951). */
65355
65829
  var powerMeterCustomize = {
65356
65830
  version: 1,
65357
65831
  targets: [
65358
- powerTarget("watts", "W"),
65359
- powerTarget("kwhTotal", "kWh"),
65360
- powerTarget("volts", "V"),
65361
- powerTarget("amps", "A")
65832
+ powerTarget("power", "W"),
65833
+ powerTarget("energy", "kWh"),
65834
+ powerTarget("voltage", "V"),
65835
+ powerTarget("current", "A")
65362
65836
  ]
65363
65837
  };
65364
65838
  var powerMeterCapability = {
@@ -65374,41 +65848,41 @@ var powerMeterCapability = {
65374
65848
  },
65375
65849
  runtimeState: PowerMeterStatusSchema,
65376
65850
  /**
65377
- * Runtime-state durability: **restored** — as `numeric-sensor`; `kwhTotal` is an accumulator whose restored value is the baseline.
65851
+ * Runtime-state durability: **restored** — as `numeric-sensor`; `energy` is an accumulator whose restored value is the baseline.
65378
65852
  *
65379
65853
  * See `RuntimeStateDurability`. Enforced by
65380
65854
  * `scripts/check-runtime-state-durability.ts`.
65381
65855
  */
65382
65856
  durability: "restored",
65383
65857
  /**
65384
- * History (D850): recorded series. Gauges are floored at 30 s; `kwhTotal` is the one monotonic meter (counter).
65858
+ * History (D850): recorded series. Gauges are floored at 30 s; `energy` is the one monotonic meter (counter).
65385
65859
  */
65386
65860
  history: { fields: {
65387
- watts: {
65861
+ power: {
65388
65862
  kind: "gauge",
65389
65863
  unit: "W",
65390
65864
  deadband: 1,
65391
65865
  minIntervalMs: 3e4
65392
65866
  },
65393
- kwhTotal: {
65867
+ energy: {
65394
65868
  kind: "counter",
65395
65869
  unit: "kWh",
65396
65870
  deadband: .01,
65397
65871
  minIntervalMs: 6e4
65398
65872
  },
65399
- volts: {
65873
+ voltage: {
65400
65874
  kind: "gauge",
65401
65875
  unit: "V",
65402
65876
  deadband: 1,
65403
65877
  minIntervalMs: 3e4
65404
65878
  },
65405
- amps: {
65879
+ current: {
65406
65880
  kind: "gauge",
65407
65881
  unit: "A",
65408
65882
  deadband: .05,
65409
65883
  minIntervalMs: 3e4
65410
65884
  },
65411
- va: {
65885
+ apparentPower: {
65412
65886
  kind: "gauge",
65413
65887
  unit: "VA",
65414
65888
  deadband: 1,
@@ -65458,9 +65932,6 @@ var PresenceStatusSchema = object({
65458
65932
  location: string().nullable(),
65459
65933
  /** GPS coordinates when available. Null otherwise. */
65460
65934
  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
65935
  /** Ms epoch when the slice was last updated. */
65465
65936
  lastChangedAt: number()
65466
65937
  });
@@ -65489,14 +65960,7 @@ var presenceCapability = {
65489
65960
  * `scripts/check-runtime-state-durability.ts`.
65490
65961
  */
65491
65962
  durability: "restored",
65492
- /**
65493
- * History (D850): recorded series.
65494
- */
65495
- history: { fields: { batteryPercent: {
65496
- kind: "gauge",
65497
- unit: "%",
65498
- deadband: 1
65499
- } } },
65963
+ history: "none",
65500
65964
  /** Clock fields: written, but excluded from the compare that decides
65501
65965
  * whether persisting is worth a SQLite commit. */
65502
65966
  volatileStateFields: ["lastChangedAt"]
@@ -65511,7 +65975,7 @@ var presenceCapability = {
65511
65975
  */
65512
65976
  var PressureSensorStatusSchema = object({
65513
65977
  /** Current pressure in hPa. `null` when the sample was refused (D393). */
65514
- hpa: number().nullable().meta(readingMeta("pressure", { precision: 0 })),
65978
+ pressure: number().nullable().meta(readingMeta("pressure", { precision: 0 })),
65515
65979
  /** Ms epoch when the slice was last updated. */
65516
65980
  lastFetchedAt: number()
65517
65981
  });
@@ -65537,7 +66001,7 @@ var pressureSensorCapability = {
65537
66001
  /**
65538
66002
  * History (D850): recorded series.
65539
66003
  */
65540
- history: { fields: { hpa: {
66004
+ history: { fields: { pressure: {
65541
66005
  kind: "gauge",
65542
66006
  unit: "hPa",
65543
66007
  deadband: .1
@@ -69244,7 +69708,7 @@ var tamperCapability = {
69244
69708
  */
69245
69709
  var TemperatureSensorStatusSchema = object({
69246
69710
  /** Current temperature in Celsius. `null` when the sample was refused (D393). */
69247
- celsius: number().nullable().meta(readingMeta("temperature", {
69711
+ temperature: number().nullable().meta(readingMeta("temperature", {
69248
69712
  precision: 1,
69249
69713
  label: "Temperature"
69250
69714
  })),
@@ -69273,7 +69737,7 @@ var temperatureSensorCapability = {
69273
69737
  /**
69274
69738
  * History (D850): recorded series.
69275
69739
  */
69276
- history: { fields: { celsius: {
69740
+ history: { fields: { temperature: {
69277
69741
  kind: "gauge",
69278
69742
  unit: "°C",
69279
69743
  deadband: .1
@@ -69570,7 +70034,7 @@ var VacuumControlStatusSchema = object({
69570
70034
  /** Speed tokens the hardware accepts — drives the UI selector. */
69571
70035
  availableFanSpeeds: array(string()),
69572
70036
  /** 0..100 cleaning-completion percentage of the current task, or null. */
69573
- progressPercent: number().min(0).max(100).nullable().meta(readingMeta("percentage")),
70037
+ progress: number().min(0).max(100).nullable().meta(readingMeta("percentage")),
69574
70038
  /** Current error code (0 / null = no error). */
69575
70039
  errorCode: number().nullable().meta(readingMeta("none")),
69576
70040
  /** Human label for {@link errorCode}, or null when none / undecodable. */
@@ -71659,7 +72123,7 @@ var BaseDevice = class {
71659
72123
  * `device-local-state.ts`. Drivers access via:
71660
72124
  *
71661
72125
  * `this.state.battery.sleeping = true` // patches the battery slice
71662
- * `const pct = this.state.battery.percentage` // reads the battery slice
72126
+ * `const pct = this.state.battery.level` // reads the battery slice
71663
72127
  * `this.state.deviceStatus.online = true` // mirrors `markOnline(true)`
71664
72128
  *
71665
72129
  * Adding a new cap with `runtimeState:` automatically extends this
@@ -71699,7 +72163,7 @@ var BaseDevice = class {
71699
72163
  * shape; drivers don't redeclare it, they just write through.
71700
72164
  *
71701
72165
  * Read: `this.runtimeState.getCapState('battery')` →
71702
- * `{percentage, charging, sleeping, lastUpdated}` for any
72166
+ * `{level, charging, sleeping, lastUpdated}` for any
71703
72167
  * provider that registers `batteryCapability`.
71704
72168
  * Write: `this.runtimeState.setCapState('battery', { … })`.
71705
72169
  *
@@ -72873,6 +73337,104 @@ Object.freeze({
72873
73337
  access: "create",
72874
73338
  role: "admin"
72875
73339
  },
73340
+ "actions.create": {
73341
+ capName: "actions",
73342
+ capScope: "system",
73343
+ addonId: null,
73344
+ access: "create",
73345
+ role: "admin"
73346
+ },
73347
+ "actions.delete": {
73348
+ capName: "actions",
73349
+ capScope: "system",
73350
+ addonId: null,
73351
+ access: "delete",
73352
+ role: "admin"
73353
+ },
73354
+ "actions.get": {
73355
+ capName: "actions",
73356
+ capScope: "system",
73357
+ addonId: null,
73358
+ access: "view",
73359
+ role: "viewer"
73360
+ },
73361
+ "actions.getLinks": {
73362
+ capName: "actions",
73363
+ capScope: "system",
73364
+ addonId: null,
73365
+ access: "view",
73366
+ role: "admin"
73367
+ },
73368
+ "actions.getTraces": {
73369
+ capName: "actions",
73370
+ capScope: "system",
73371
+ addonId: null,
73372
+ access: "view",
73373
+ role: "admin"
73374
+ },
73375
+ "actions.list": {
73376
+ capName: "actions",
73377
+ capScope: "system",
73378
+ addonId: null,
73379
+ access: "view",
73380
+ role: "admin"
73381
+ },
73382
+ "actions.listForCamera": {
73383
+ capName: "actions",
73384
+ capScope: "system",
73385
+ addonId: null,
73386
+ access: "view",
73387
+ role: "viewer"
73388
+ },
73389
+ "actions.run": {
73390
+ capName: "actions",
73391
+ capScope: "system",
73392
+ addonId: null,
73393
+ access: "create",
73394
+ role: "viewer"
73395
+ },
73396
+ "actions.setLinks": {
73397
+ capName: "actions",
73398
+ capScope: "system",
73399
+ addonId: null,
73400
+ access: "create",
73401
+ role: "admin"
73402
+ },
73403
+ "actions.stop": {
73404
+ capName: "actions",
73405
+ capScope: "system",
73406
+ addonId: null,
73407
+ access: "create",
73408
+ role: "admin"
73409
+ },
73410
+ "actions.update": {
73411
+ capName: "actions",
73412
+ capScope: "system",
73413
+ addonId: null,
73414
+ access: "create",
73415
+ role: "admin"
73416
+ },
73417
+ "actionSource.listActions": {
73418
+ capName: "action-source",
73419
+ capScope: "system",
73420
+ addonId: null,
73421
+ access: "view",
73422
+ role: "admin"
73423
+ },
73424
+ "actionSource.runAction": {
73425
+ capName: "action-source",
73426
+ capScope: "system",
73427
+ addonId: null,
73428
+ access: "create",
73429
+ role: "admin"
73430
+ },
73431
+ "actionSource.stopAction": {
73432
+ capName: "action-source",
73433
+ capScope: "system",
73434
+ addonId: null,
73435
+ access: "create",
73436
+ role: "admin"
73437
+ },
72876
73438
  "addonPages.listPages": {
72877
73439
  capName: "addon-pages",
72878
73440
  capScope: "system",
@@ -74154,6 +74716,13 @@ Object.freeze({
74154
74716
  access: "view",
74155
74717
  role: "admin"
74156
74718
  },
74719
+ "coreBlocks.getAutomationRunState": {
74720
+ capName: "core-blocks",
74721
+ capScope: "system",
74722
+ addonId: null,
74723
+ access: "view",
74724
+ role: "admin"
74725
+ },
74157
74726
  "coreBlocks.getBlockSettings": {
74158
74727
  capName: "core-blocks",
74159
74728
  capScope: "system",
@@ -74175,6 +74744,13 @@ Object.freeze({
74175
74744
  access: "view",
74176
74745
  role: "admin"
74177
74746
  },
74747
+ "coreBlocks.getTraces": {
74748
+ capName: "core-blocks",
74749
+ capScope: "system",
74750
+ addonId: null,
74751
+ access: "view",
74752
+ role: "admin"
74753
+ },
74178
74754
  "coreBlocks.getTypeDefs": {
74179
74755
  capName: "core-blocks",
74180
74756
  capScope: "system",
@@ -74210,6 +74786,13 @@ Object.freeze({
74210
74786
  access: "create",
74211
74787
  role: "admin"
74212
74788
  },
74789
+ "coreBlocks.reportAutomationRun": {
74790
+ capName: "core-blocks",
74791
+ capScope: "system",
74792
+ addonId: null,
74793
+ access: "create",
74794
+ role: "admin"
74795
+ },
74213
74796
  "coreBlocks.restart": {
74214
74797
  capName: "core-blocks",
74215
74798
  capScope: "system",
@@ -82783,7 +83366,7 @@ var ACTUATOR_CAP_VOCABULARY = {
82783
83366
  label: t("Full brightness", "Luminosità massima"),
82784
83367
  phrase: t("Set {device} to full brightness", "Porta {device} alla massima luminosità"),
82785
83368
  icon: "sun",
82786
- args: { percentage: 100 }
83369
+ args: { level: 100 }
82787
83370
  },
82788
83371
  {
82789
83372
  id: "brightness.half",
@@ -82791,7 +83374,7 @@ var ACTUATOR_CAP_VOCABULARY = {
82791
83374
  label: t("Half brightness", "Luminosità a metà"),
82792
83375
  phrase: t("Dim {device} to half", "Abbassa {device} a metà luminosità"),
82793
83376
  icon: "sun-dim",
82794
- args: { percentage: 50 }
83377
+ args: { level: 50 }
82795
83378
  },
82796
83379
  {
82797
83380
  id: "brightness.off",
@@ -82799,16 +83382,16 @@ var ACTUATOR_CAP_VOCABULARY = {
82799
83382
  label: t("Brightness off", "Luminosità a zero"),
82800
83383
  phrase: t("Dim {device} to zero", "Abbassa {device} a zero"),
82801
83384
  icon: "lightbulb-off",
82802
- args: { percentage: 0 }
83385
+ args: { level: 0 }
82803
83386
  },
82804
83387
  {
82805
83388
  id: "brightness.set",
82806
83389
  method: "setBrightness",
82807
83390
  label: t("Set brightness", "Imposta la luminosità"),
82808
- phrase: t("Set the brightness of {device} to {percentage}", "Imposta la luminosità di {device} a {percentage}"),
83391
+ phrase: t("Set the brightness of {device} to {level}", "Imposta la luminosità di {device} a {level}"),
82809
83392
  icon: "sun-medium",
82810
83393
  openArgs: [{
82811
- key: "percentage",
83394
+ key: "level",
82812
83395
  label: PERCENT,
82813
83396
  offer: {
82814
83397
  kind: "number",
@@ -82822,13 +83405,13 @@ var ACTUATOR_CAP_VOCABULARY = {
82822
83405
  ],
82823
83406
  state: [{
82824
83407
  kind: "numeric",
82825
- field: "percentage",
83408
+ field: "level",
82826
83409
  quantity: t("the brightness", "la luminosità"),
82827
83410
  label: t("Brightness", "Luminosità"),
82828
83411
  unit: "%",
82829
83412
  icon: "sun"
82830
83413
  }],
82831
- events: { onBrightnessChanged: { notOperatorFacing: "the `percentage` state trigger reads the same change" } }
83414
+ events: { onBrightnessChanged: { notOperatorFacing: "the `level` state trigger reads the same change" } }
82832
83415
  },
82833
83416
  color: {
82834
83417
  scope: "device",
@@ -82842,7 +83425,7 @@ var ACTUATOR_CAP_VOCABULARY = {
82842
83425
  icon: "sun",
82843
83426
  args: { color: {
82844
83427
  mode: "mired",
82845
- mireds: 370
83428
+ colorTemperature: 370
82846
83429
  } }
82847
83430
  },
82848
83431
  {
@@ -82853,7 +83436,7 @@ var ACTUATOR_CAP_VOCABULARY = {
82853
83436
  icon: "snowflake",
82854
83437
  args: { color: {
82855
83438
  mode: "mired",
82856
- mireds: 200
83439
+ colorTemperature: 200
82857
83440
  } }
82858
83441
  },
82859
83442
  {
@@ -83467,7 +84050,7 @@ var ACTUATOR_CAP_VOCABULARY = {
83467
84050
  label: t("Fan off", "Ventilatore spento"),
83468
84051
  phrase: t("Stop {device}", "Ferma {device}"),
83469
84052
  icon: "power-off",
83470
- args: { percentage: 0 }
84053
+ args: { speed: 0 }
83471
84054
  },
83472
84055
  {
83473
84056
  id: "fan.full",
@@ -83475,16 +84058,16 @@ var ACTUATOR_CAP_VOCABULARY = {
83475
84058
  label: t("Fan full", "Ventilatore al massimo"),
83476
84059
  phrase: t("Run {device} at full speed", "Porta {device} alla massima velocità"),
83477
84060
  icon: "fan",
83478
- args: { percentage: 100 }
84061
+ args: { speed: 100 }
83479
84062
  },
83480
84063
  {
83481
84064
  id: "fan.speed",
83482
84065
  method: "setPercentage",
83483
84066
  label: t("Set speed", "Imposta la velocità"),
83484
- phrase: t("Set the speed of {device} to {percentage}", "Imposta la velocità di {device} al {percentage}"),
84067
+ phrase: t("Set the speed of {device} to {speed}", "Imposta la velocità di {device} al {speed}"),
83485
84068
  icon: "fan",
83486
84069
  openArgs: [{
83487
- key: "percentage",
84070
+ key: "speed",
83488
84071
  label: t("Speed", "Velocità"),
83489
84072
  offer: {
83490
84073
  kind: "number",
@@ -83546,7 +84129,7 @@ var ACTUATOR_CAP_VOCABULARY = {
83546
84129
  ],
83547
84130
  state: [{
83548
84131
  kind: "numeric",
83549
- field: "percentage",
84132
+ field: "speed",
83550
84133
  quantity: t("the speed", "la velocità"),
83551
84134
  label: t("Speed", "Velocità"),
83552
84135
  unit: "%",
@@ -84344,7 +84927,7 @@ var APPLIANCE_CAP_VOCABULARY = {
84344
84927
  },
84345
84928
  {
84346
84929
  kind: "numeric",
84347
- field: "progressPercent",
84930
+ field: "progress",
84348
84931
  quantity: t("the cycle progress", "l’avanzamento del lavaggio"),
84349
84932
  label: t("Progress", "Avanzamento"),
84350
84933
  unit: "%",
@@ -84702,10 +85285,10 @@ var APPLIANCE_CAP_VOCABULARY = {
84702
85285
  id: "media.seek",
84703
85286
  method: "seek",
84704
85287
  label: t("Seek", "Vai al punto"),
84705
- phrase: t("Move {device} to {positionMs}", "Porta {device} al punto {positionMs}"),
85288
+ phrase: t("Move {device} to {position}", "Porta {device} al punto {position}"),
84706
85289
  icon: "fast-forward",
84707
85290
  openArgs: [{
84708
- key: "positionMs",
85291
+ key: "position",
84709
85292
  label: t("Position", "Posizione"),
84710
85293
  offer: {
84711
85294
  kind: "number",
@@ -85754,7 +86337,7 @@ var SENSOR_CAP_VOCABULARY = {
85754
86337
  state: [
85755
86338
  {
85756
86339
  kind: "numeric",
85757
- field: "co2Ppm",
86340
+ field: "co2",
85758
86341
  quantity: t("the CO₂", "la CO₂"),
85759
86342
  label: t("CO₂", "CO₂"),
85760
86343
  unit: "ppm",
@@ -85762,7 +86345,7 @@ var SENSOR_CAP_VOCABULARY = {
85762
86345
  },
85763
86346
  {
85764
86347
  kind: "numeric",
85765
- field: "vocPpb",
86348
+ field: "voc",
85766
86349
  quantity: t("the VOC level", "il livello di COV"),
85767
86350
  label: t("VOC", "COV"),
85768
86351
  unit: "ppb",
@@ -85798,7 +86381,7 @@ var SENSOR_CAP_VOCABULARY = {
85798
86381
  noun: t("Light level", "Luminosità ambiente"),
85799
86382
  state: [{
85800
86383
  kind: "numeric",
85801
- field: "lux",
86384
+ field: "illuminance",
85802
86385
  quantity: t("the light level", "la luminosità"),
85803
86386
  label: t("Illuminance", "Illuminamento"),
85804
86387
  unit: "lx",
@@ -86001,7 +86584,7 @@ var SENSOR_CAP_VOCABULARY = {
86001
86584
  noun: t("Humidity", "Umidità"),
86002
86585
  state: [{
86003
86586
  kind: "numeric",
86004
- field: "percent",
86587
+ field: "humidity",
86005
86588
  quantity: t("the humidity", "l’umidità"),
86006
86589
  label: t("Humidity", "Umidità"),
86007
86590
  unit: "%",
@@ -86049,7 +86632,7 @@ var SENSOR_CAP_VOCABULARY = {
86049
86632
  state: [
86050
86633
  {
86051
86634
  kind: "numeric",
86052
- field: "watts",
86635
+ field: "power",
86053
86636
  quantity: t("the power draw", "il consumo"),
86054
86637
  label: t("Power", "Potenza"),
86055
86638
  unit: "W",
@@ -86057,7 +86640,7 @@ var SENSOR_CAP_VOCABULARY = {
86057
86640
  },
86058
86641
  {
86059
86642
  kind: "numeric",
86060
- field: "kwhTotal",
86643
+ field: "energy",
86061
86644
  quantity: t("the energy used", "l’energia consumata"),
86062
86645
  label: t("Energy", "Energia"),
86063
86646
  unit: "kWh",
@@ -86065,7 +86648,7 @@ var SENSOR_CAP_VOCABULARY = {
86065
86648
  },
86066
86649
  {
86067
86650
  kind: "numeric",
86068
- field: "volts",
86651
+ field: "voltage",
86069
86652
  quantity: t("the voltage", "la tensione"),
86070
86653
  label: t("Voltage", "Tensione"),
86071
86654
  unit: "V",
@@ -86073,7 +86656,7 @@ var SENSOR_CAP_VOCABULARY = {
86073
86656
  },
86074
86657
  {
86075
86658
  kind: "numeric",
86076
- field: "amps",
86659
+ field: "current",
86077
86660
  quantity: t("the current", "la corrente"),
86078
86661
  label: t("Current", "Corrente"),
86079
86662
  unit: "A",
@@ -86090,13 +86673,6 @@ var SENSOR_CAP_VOCABULARY = {
86090
86673
  label: t("Where", "Posizione"),
86091
86674
  phrase: t("When {device} is at {value}", "Quando {device} è in {value}"),
86092
86675
  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
86676
  }]
86101
86677
  },
86102
86678
  "pressure-sensor": {
@@ -86104,7 +86680,7 @@ var SENSOR_CAP_VOCABULARY = {
86104
86680
  noun: t("Pressure", "Pressione"),
86105
86681
  state: [{
86106
86682
  kind: "numeric",
86107
- field: "hpa",
86683
+ field: "pressure",
86108
86684
  quantity: t("the pressure", "la pressione"),
86109
86685
  label: t("Pressure", "Pressione"),
86110
86686
  unit: "hPa",
@@ -86140,7 +86716,7 @@ var SENSOR_CAP_VOCABULARY = {
86140
86716
  noun: t("Temperature", "Temperatura"),
86141
86717
  state: [{
86142
86718
  kind: "numeric",
86143
- field: "celsius",
86719
+ field: "temperature",
86144
86720
  quantity: t("the temperature", "la temperatura"),
86145
86721
  label: t("Temperature", "Temperatura"),
86146
86722
  unit: "°C",
@@ -86211,7 +86787,7 @@ var SENSOR_CAP_VOCABULARY = {
86211
86787
  state: [
86212
86788
  {
86213
86789
  kind: "numeric",
86214
- field: "percentage",
86790
+ field: "level",
86215
86791
  quantity: t("the battery level", "il livello della batteria"),
86216
86792
  label: t("Battery", "Batteria"),
86217
86793
  unit: "%",
@@ -86253,7 +86829,7 @@ var SENSOR_CAP_VOCABULARY = {
86253
86829
  icon: "battery-charging"
86254
86830
  }
86255
86831
  ],
86256
- events: { onStatusChanged: { notOperatorFacing: "the percentage / sleeping / charging state triggers each read one field of this change" } },
86832
+ events: { onStatusChanged: { notOperatorFacing: "the level / sleeping / charging state triggers each read one field of this change" } },
86257
86833
  extraEvents: [{
86258
86834
  category: EventCategory.DeviceAwake,
86259
86835
  label: t("Woke up", "Risvegliato"),
@@ -86271,7 +86847,7 @@ var SENSOR_CAP_VOCABULARY = {
86271
86847
  noun: t("Network link", "Collegamento di rete"),
86272
86848
  state: [{
86273
86849
  kind: "numeric",
86274
- field: "signalPercent",
86850
+ field: "signal",
86275
86851
  quantity: t("the signal strength", "l’intensità del segnale"),
86276
86852
  label: t("Signal", "Segnale"),
86277
86853
  unit: "%",
@@ -86364,6 +86940,8 @@ var ML = "model and training machinery — no device action";
86364
86940
  var INTERNAL = "internal plumbing between addons — never operator-facing";
86365
86941
  /** Every system-scoped cap, with why it is not a device's vocabulary. */
86366
86942
  var SYSTEM_CAP_VOCABULARY = {
86943
+ "action-source": system(INTERNAL),
86944
+ actions: system("declared actions — run from the Actions page and from the cameras that link them"),
86367
86945
  "addon-pages": system(UI_PLUMBING),
86368
86946
  "addon-pages-source": system(UI_PLUMBING),
86369
86947
  "addon-routes": system(UI_PLUMBING),
@@ -86571,6 +87149,31 @@ Object.freeze({
86571
87149
  form: "single",
86572
87150
  optional: false
86573
87151
  }],
87152
+ "actions.get": [{
87153
+ name: "deviceId",
87154
+ form: "single",
87155
+ optional: true
87156
+ }],
87157
+ "actions.getLinks": [{
87158
+ name: "deviceId",
87159
+ form: "single",
87160
+ optional: false
87161
+ }],
87162
+ "actions.listForCamera": [{
87163
+ name: "deviceId",
87164
+ form: "single",
87165
+ optional: false
87166
+ }],
87167
+ "actions.run": [{
87168
+ name: "deviceId",
87169
+ form: "single",
87170
+ optional: true
87171
+ }],
87172
+ "actions.setLinks": [{
87173
+ name: "deviceId",
87174
+ form: "single",
87175
+ optional: false
87176
+ }],
86574
87177
  "addonSettings.getDeviceSettings": [{
86575
87178
  name: "deviceId",
86576
87179
  form: "single",
@@ -91001,6 +91604,7 @@ function bestLocationMatch(externalName, existing, threshold = .8) {
91001
91604
  }
91002
91605
  return best;
91003
91606
  }
91607
+ String.raw`(?<=^|["'(\s>,\[{])`;
91004
91608
  var MB = 1024 * 1024;
91005
91609
  1024 * MB, 3072 * MB;
91006
91610
  //#endregion