@camstack/types 1.2.405 → 1.2.406

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (41) hide show
  1. package/dist/addon.js +21 -2
  2. package/dist/addon.mjs +21 -2
  3. package/dist/capabilities/index.d.ts +4 -2
  4. package/dist/capabilities/notification-rules.cap.d.ts +3 -78
  5. package/dist/capabilities/osd-manager.cap.d.ts +0 -18
  6. package/dist/capabilities/running-state.cap.d.ts +76 -0
  7. package/dist/client.js +10 -62
  8. package/dist/client.mjs +10 -62
  9. package/dist/{composition-eoYYVfOp.js → composition-RmnnN39T.js} +86 -2
  10. package/dist/{composition-CB6PMT9p.mjs → composition-xz-ud5EQ.mjs} +86 -2
  11. package/dist/device/cap-vocabulary/entries/appliances.d.ts +1 -1
  12. package/dist/enums/event-category.d.ts +4 -0
  13. package/dist/enums.js +1 -1
  14. package/dist/enums.mjs +1 -1
  15. package/dist/{event-category-fDPduoeC.mjs → event-category-Ceif8n-v.mjs} +4 -0
  16. package/dist/{event-category-CXrwjC3e.js → event-category-DG6Vir8Z.js} +4 -0
  17. package/dist/expression/builtins.d.ts +7 -18
  18. package/dist/expression/expression-source.d.ts +14 -2
  19. package/dist/generated/addon-api.d.ts +14 -0
  20. package/dist/generated/addon-cap-facts.d.ts +1 -1
  21. package/dist/generated/cap-status-types.d.ts +3 -1
  22. package/dist/generated/capability-router-map.d.ts +5 -2
  23. package/dist/generated/device-local-state.d.ts +3 -0
  24. package/dist/generated/device-proxy.d.ts +3 -0
  25. package/dist/generated/device-scoped-caps.d.ts +1 -1
  26. package/dist/generated/history-catalog.d.ts +1 -1
  27. package/dist/generated/method-access-map.d.ts +1 -1
  28. package/dist/generated/method-device-selectors.d.ts +1 -1
  29. package/dist/generated/runtime-state-durability.d.ts +1 -1
  30. package/dist/index.d.ts +3 -0
  31. package/dist/index.js +345 -88
  32. package/dist/index.mjs +331 -88
  33. package/dist/interfaces/config-ui.d.ts +69 -2
  34. package/dist/node.js +1 -1
  35. package/dist/node.mjs +1 -1
  36. package/dist/running-state/assignment.d.ts +34 -0
  37. package/dist/running-state/defaults.d.ts +3 -0
  38. package/dist/running-state/from-operation.d.ts +14 -0
  39. package/dist/{sleep-CHIEEJkY.mjs → sleep-CYfIZzGv.mjs} +7 -3
  40. package/dist/{sleep-BKS4OPMo.js → sleep-UP964hNP.js} +7 -3
  41. package/package.json +1 -1
package/dist/client.js CHANGED
@@ -22259,9 +22259,6 @@ var NcSystemEventKindSchema = zod.z.enum([
22259
22259
  "device-battery-normal",
22260
22260
  "device-consumable-low",
22261
22261
  "device-consumable-normal",
22262
- "device-tank-low",
22263
- "device-tank-full",
22264
- "device-tank-normal",
22265
22262
  "stream-online",
22266
22263
  "stream-offline",
22267
22264
  "node-online",
@@ -22308,13 +22305,14 @@ var NcSystemEventKindSchema = zod.z.enum([
22308
22305
  "camera-enabled"
22309
22306
  ]);
22310
22307
  /** The legacy tail of {@link NcSystemEventKindSchema} — see its docblock. */
22311
- var NC_LEGACY_SYSTEM_EVENT_KINDS = new Set([
22308
+ var NC_LEGACY_SYSTEM_EVENT_KINDS = [
22312
22309
  "camera-online",
22313
22310
  "camera-offline",
22314
22311
  "camera-disabled",
22315
22312
  "camera-enabled"
22316
- ]);
22317
- NcSystemEventKindSchema.options.filter((kind) => !NC_LEGACY_SYSTEM_EVENT_KINDS.has(kind));
22313
+ ];
22314
+ var NC_LEGACY_SYSTEM_EVENT_KIND_SET = new Set(NC_LEGACY_SYSTEM_EVENT_KINDS);
22315
+ NcSystemEventKindSchema.options.filter((kind) => !NC_LEGACY_SYSTEM_EVENT_KIND_SET.has(kind));
22318
22316
  /**
22319
22317
  * The panel's transitions, as ONE list.
22320
22318
  *
@@ -23491,18 +23489,11 @@ var NcRuleSchema = NcRuleInputSchema.extend({
23491
23489
  */
23492
23490
  disabledTargetIds: zod.z.array(zod.z.string()).default([])
23493
23491
  });
23494
- /**
23495
- * The state-summary SECTIONS (D647 / D698 / D708): the D637 kind groups that
23496
- * report a still-true state. `addons` is the crash-looped addons only and
23497
- * `addon-updates` the addons that are behind (D708 split them). `backups-exports` and `alarm` are not sections — a completed
23498
- * job is not an open state, and the alarm stays instant.
23499
- */
23500
23492
  var NcStateSummarySectionIdSchema = zod.z.enum([
23501
23493
  "device-state",
23502
23494
  "streams",
23503
23495
  "battery",
23504
23496
  "consumables",
23505
- "tanks",
23506
23497
  "detection-blind",
23507
23498
  "nodes",
23508
23499
  "addons",
@@ -26520,6 +26511,7 @@ function createDeviceProxy(api, binding, opts) {
26520
26511
  getStatus: (input) => dispatch("recording-onboard", "recordingOnboard", "getStatus", "query", input)
26521
26512
  };
26522
26513
  const recordingSignalInterface = { getStatus: (input) => dispatch("recording-signal", "recordingSignal", "getStatus", "query", input) };
26514
+ const runningStateInterface = { getStatus: (input) => dispatch("running-state", "runningState", "getStatus", "query", input) };
26523
26515
  const sceneMonitorInterface = {
26524
26516
  listScenes: (input) => dispatch("scene-monitor", "sceneMonitor", "listScenes", "query", input),
26525
26517
  listScenesBatch: (input) => dispatch("scene-monitor", "sceneMonitor", "listScenesBatch", "query", input),
@@ -26846,6 +26838,7 @@ function createDeviceProxy(api, binding, opts) {
26846
26838
  ptzAutotrack: createSliceHandle(stateSource, binding.deviceId, "ptz-autotrack"),
26847
26839
  recordingOnboard: createSliceHandle(stateSource, binding.deviceId, "recording-onboard"),
26848
26840
  recordingSignal: createSliceHandle(stateSource, binding.deviceId, "recording-signal"),
26841
+ runningState: createSliceHandle(stateSource, binding.deviceId, "running-state"),
26849
26842
  sceneMonitor: createSliceHandle(stateSource, binding.deviceId, "scene-monitor"),
26850
26843
  scriptRunner: createSliceHandle(stateSource, binding.deviceId, "script-runner"),
26851
26844
  smoke: createSliceHandle(stateSource, binding.deviceId, "smoke"),
@@ -26934,6 +26927,7 @@ function createDeviceProxy(api, binding, opts) {
26934
26927
  ...bound("recording") ? { recording: recordingInterface } : {},
26935
26928
  ...bound("recording-onboard") ? { recordingOnboard: recordingOnboardInterface } : {},
26936
26929
  ...bound("recording-signal") ? { recordingSignal: recordingSignalInterface } : {},
26930
+ ...bound("running-state") ? { runningState: runningStateInterface } : {},
26937
26931
  ...bound("scene-monitor") ? { sceneMonitor: sceneMonitorInterface } : {},
26938
26932
  ...bound("script-runner") ? { scriptRunner: scriptRunnerInterface } : {},
26939
26933
  ...bound("smoke") ? { smoke: smokeInterface } : {},
@@ -28736,6 +28730,7 @@ new Set(["devices", "classes"]);
28736
28730
  * narrows, and still fails CLOSED on a subject that cannot produce the identity
28737
28731
  * it tests (a device the mirror cannot name is not evidence of a camera).
28738
28732
  */
28733
+ var LEGACY_KINDS_WITHOUT_FILTERS = new Set(NC_LEGACY_SYSTEM_EVENT_KINDS);
28739
28734
  /**
28740
28735
  * Every filter, for the callers that must cover all of them (guards, tests).
28741
28736
  *
@@ -28759,6 +28754,7 @@ var NC_SYSTEM_EVENT_FILTER_KEYS = [
28759
28754
  * ignores it and an editor hides its input. It never means "excluded".
28760
28755
  */
28761
28756
  function systemEventFilterApplies(kind, filter) {
28757
+ if (LEGACY_KINDS_WITHOUT_FILTERS.has(kind)) return false;
28762
28758
  switch (filter) {
28763
28759
  case "deviceIds": return kind.startsWith("device-") || kind.startsWith("stream-") || kind === "detection-blind" || kind.startsWith("motion-") || kind.startsWith("recording-") || kind === "alarm-triggered";
28764
28760
  case "deviceTypes": return kind.startsWith("device-") || kind === "detection-blind" || kind.startsWith("motion-");
@@ -28813,9 +28809,6 @@ var NC_SYSTEM_EVENT_FAMILY = {
28813
28809
  "device-battery-normal": "device-events",
28814
28810
  "device-consumable-low": "device-events",
28815
28811
  "device-consumable-normal": "device-events",
28816
- "device-tank-low": "device-events",
28817
- "device-tank-full": "device-events",
28818
- "device-tank-normal": "device-events",
28819
28812
  "stream-online": "device-events",
28820
28813
  "stream-offline": "device-events",
28821
28814
  "detection-blind": "device-events",
@@ -28910,16 +28903,6 @@ var NC_SYSTEM_EVENT_KIND_GROUP_SPECS = [
28910
28903
  label: "Consumables",
28911
28904
  kinds: ["device-consumable-low", "device-consumable-normal"]
28912
28905
  },
28913
- {
28914
- id: "tanks",
28915
- family: "device-events",
28916
- label: "Tanks",
28917
- kinds: [
28918
- "device-tank-low",
28919
- "device-tank-full",
28920
- "device-tank-normal"
28921
- ]
28922
- },
28923
28906
  {
28924
28907
  id: "detection-blind",
28925
28908
  family: "device-events",
@@ -29893,11 +29876,6 @@ var RULE_BODY_ONLY = ["body"];
29893
29876
  var RULE_TEXT = ["title", "body"];
29894
29877
  var BATTERY = ["device-battery-low", "device-battery-normal"];
29895
29878
  var CONSUMABLE = ["device-consumable-low", "device-consumable-normal"];
29896
- var TANK = [
29897
- "device-tank-low",
29898
- "device-tank-full",
29899
- "device-tank-normal"
29900
- ];
29901
29879
  var ALERT_EPISODE = [
29902
29880
  "alert-critical",
29903
29881
  "alert-error",
@@ -29929,7 +29907,6 @@ var DEVICE_EVENTS = [
29929
29907
  "device-enabled",
29930
29908
  ...BATTERY,
29931
29909
  ...CONSUMABLE,
29932
- ...TANK,
29933
29910
  "stream-online",
29934
29911
  "stream-offline",
29935
29912
  "detection-blind",
@@ -29975,12 +29952,6 @@ var STATE_SUMMARY_SECTION_VARS = [
29975
29952
  example: "Robot — filter 10 %",
29976
29953
  kinds: CONSUMABLE
29977
29954
  },
29978
- {
29979
- name: "summaryTanks",
29980
- label: "Summary: tanks",
29981
- example: "Robot — clean water low",
29982
- kinds: TANK
29983
- },
29984
29955
  {
29985
29956
  name: "summaryDetection",
29986
29957
  label: "Summary: cameras detecting nothing",
@@ -30389,18 +30360,7 @@ var NC_TEMPLATE_VARS = [
30389
30360
  families: ["rule"],
30390
30361
  fields: [...RULE_TEXT],
30391
30362
  kinds: ["system"],
30392
- systemEventKinds: [...CONSUMABLE, ...TANK]
30393
- },
30394
- {
30395
- name: "tank",
30396
- label: "Tank",
30397
- description: "Which tank, as a stable token: cleanWater, dirtyWater, detergent, dustBin, or the device key of any other supply (salt, rinse aid).",
30398
- example: "clean water",
30399
- group: "system",
30400
- families: ["rule"],
30401
- fields: [...RULE_TEXT],
30402
- kinds: ["system"],
30403
- systemEventKinds: [...TANK]
30363
+ systemEventKinds: [...CONSUMABLE]
30404
30364
  },
30405
30365
  {
30406
30366
  name: "profile",
@@ -31051,9 +31011,6 @@ var NC_TEMPLATE_VARS = [
31051
31011
  * delete it from here then, and the served catalog names it again.
31052
31012
  */
31053
31013
  var NC_TEMPLATE_HELD_BACK_SYSTEM_EVENT_KINDS = [
31054
- "device-tank-low",
31055
- "device-tank-full",
31056
- "device-tank-normal",
31057
31014
  "node-restarting",
31058
31015
  "node-updating",
31059
31016
  "alert-critical",
@@ -31166,15 +31123,6 @@ var NC_SYSTEM_EVENT_CLASS_SPECS = [
31166
31123
  snapshotLabel: "Consumables low now",
31167
31124
  snapshotSection: "consumables"
31168
31125
  },
31169
- {
31170
- id: "tanks",
31171
- family: "device-events",
31172
- label: "Tanks (low or full / back to normal)",
31173
- bad: ["device-tank-low", "device-tank-full"],
31174
- recovery: ["device-tank-normal"],
31175
- snapshotLabel: "Tanks low or full now",
31176
- snapshotSection: "tanks"
31177
- },
31178
31126
  {
31179
31127
  id: "motion-noise",
31180
31128
  family: "device-events",
package/dist/client.mjs CHANGED
@@ -22258,9 +22258,6 @@ var NcSystemEventKindSchema = z.enum([
22258
22258
  "device-battery-normal",
22259
22259
  "device-consumable-low",
22260
22260
  "device-consumable-normal",
22261
- "device-tank-low",
22262
- "device-tank-full",
22263
- "device-tank-normal",
22264
22261
  "stream-online",
22265
22262
  "stream-offline",
22266
22263
  "node-online",
@@ -22307,13 +22304,14 @@ var NcSystemEventKindSchema = z.enum([
22307
22304
  "camera-enabled"
22308
22305
  ]);
22309
22306
  /** The legacy tail of {@link NcSystemEventKindSchema} — see its docblock. */
22310
- var NC_LEGACY_SYSTEM_EVENT_KINDS = new Set([
22307
+ var NC_LEGACY_SYSTEM_EVENT_KINDS = [
22311
22308
  "camera-online",
22312
22309
  "camera-offline",
22313
22310
  "camera-disabled",
22314
22311
  "camera-enabled"
22315
- ]);
22316
- NcSystemEventKindSchema.options.filter((kind) => !NC_LEGACY_SYSTEM_EVENT_KINDS.has(kind));
22312
+ ];
22313
+ var NC_LEGACY_SYSTEM_EVENT_KIND_SET = new Set(NC_LEGACY_SYSTEM_EVENT_KINDS);
22314
+ NcSystemEventKindSchema.options.filter((kind) => !NC_LEGACY_SYSTEM_EVENT_KIND_SET.has(kind));
22317
22315
  /**
22318
22316
  * The panel's transitions, as ONE list.
22319
22317
  *
@@ -23490,18 +23488,11 @@ var NcRuleSchema = NcRuleInputSchema.extend({
23490
23488
  */
23491
23489
  disabledTargetIds: z.array(z.string()).default([])
23492
23490
  });
23493
- /**
23494
- * The state-summary SECTIONS (D647 / D698 / D708): the D637 kind groups that
23495
- * report a still-true state. `addons` is the crash-looped addons only and
23496
- * `addon-updates` the addons that are behind (D708 split them). `backups-exports` and `alarm` are not sections — a completed
23497
- * job is not an open state, and the alarm stays instant.
23498
- */
23499
23491
  var NcStateSummarySectionIdSchema = z.enum([
23500
23492
  "device-state",
23501
23493
  "streams",
23502
23494
  "battery",
23503
23495
  "consumables",
23504
- "tanks",
23505
23496
  "detection-blind",
23506
23497
  "nodes",
23507
23498
  "addons",
@@ -26519,6 +26510,7 @@ function createDeviceProxy(api, binding, opts) {
26519
26510
  getStatus: (input) => dispatch("recording-onboard", "recordingOnboard", "getStatus", "query", input)
26520
26511
  };
26521
26512
  const recordingSignalInterface = { getStatus: (input) => dispatch("recording-signal", "recordingSignal", "getStatus", "query", input) };
26513
+ const runningStateInterface = { getStatus: (input) => dispatch("running-state", "runningState", "getStatus", "query", input) };
26522
26514
  const sceneMonitorInterface = {
26523
26515
  listScenes: (input) => dispatch("scene-monitor", "sceneMonitor", "listScenes", "query", input),
26524
26516
  listScenesBatch: (input) => dispatch("scene-monitor", "sceneMonitor", "listScenesBatch", "query", input),
@@ -26845,6 +26837,7 @@ function createDeviceProxy(api, binding, opts) {
26845
26837
  ptzAutotrack: createSliceHandle(stateSource, binding.deviceId, "ptz-autotrack"),
26846
26838
  recordingOnboard: createSliceHandle(stateSource, binding.deviceId, "recording-onboard"),
26847
26839
  recordingSignal: createSliceHandle(stateSource, binding.deviceId, "recording-signal"),
26840
+ runningState: createSliceHandle(stateSource, binding.deviceId, "running-state"),
26848
26841
  sceneMonitor: createSliceHandle(stateSource, binding.deviceId, "scene-monitor"),
26849
26842
  scriptRunner: createSliceHandle(stateSource, binding.deviceId, "script-runner"),
26850
26843
  smoke: createSliceHandle(stateSource, binding.deviceId, "smoke"),
@@ -26933,6 +26926,7 @@ function createDeviceProxy(api, binding, opts) {
26933
26926
  ...bound("recording") ? { recording: recordingInterface } : {},
26934
26927
  ...bound("recording-onboard") ? { recordingOnboard: recordingOnboardInterface } : {},
26935
26928
  ...bound("recording-signal") ? { recordingSignal: recordingSignalInterface } : {},
26929
+ ...bound("running-state") ? { runningState: runningStateInterface } : {},
26936
26930
  ...bound("scene-monitor") ? { sceneMonitor: sceneMonitorInterface } : {},
26937
26931
  ...bound("script-runner") ? { scriptRunner: scriptRunnerInterface } : {},
26938
26932
  ...bound("smoke") ? { smoke: smokeInterface } : {},
@@ -28735,6 +28729,7 @@ new Set(["devices", "classes"]);
28735
28729
  * narrows, and still fails CLOSED on a subject that cannot produce the identity
28736
28730
  * it tests (a device the mirror cannot name is not evidence of a camera).
28737
28731
  */
28732
+ var LEGACY_KINDS_WITHOUT_FILTERS = new Set(NC_LEGACY_SYSTEM_EVENT_KINDS);
28738
28733
  /**
28739
28734
  * Every filter, for the callers that must cover all of them (guards, tests).
28740
28735
  *
@@ -28758,6 +28753,7 @@ var NC_SYSTEM_EVENT_FILTER_KEYS = [
28758
28753
  * ignores it and an editor hides its input. It never means "excluded".
28759
28754
  */
28760
28755
  function systemEventFilterApplies(kind, filter) {
28756
+ if (LEGACY_KINDS_WITHOUT_FILTERS.has(kind)) return false;
28761
28757
  switch (filter) {
28762
28758
  case "deviceIds": return kind.startsWith("device-") || kind.startsWith("stream-") || kind === "detection-blind" || kind.startsWith("motion-") || kind.startsWith("recording-") || kind === "alarm-triggered";
28763
28759
  case "deviceTypes": return kind.startsWith("device-") || kind === "detection-blind" || kind.startsWith("motion-");
@@ -28812,9 +28808,6 @@ var NC_SYSTEM_EVENT_FAMILY = {
28812
28808
  "device-battery-normal": "device-events",
28813
28809
  "device-consumable-low": "device-events",
28814
28810
  "device-consumable-normal": "device-events",
28815
- "device-tank-low": "device-events",
28816
- "device-tank-full": "device-events",
28817
- "device-tank-normal": "device-events",
28818
28811
  "stream-online": "device-events",
28819
28812
  "stream-offline": "device-events",
28820
28813
  "detection-blind": "device-events",
@@ -28909,16 +28902,6 @@ var NC_SYSTEM_EVENT_KIND_GROUP_SPECS = [
28909
28902
  label: "Consumables",
28910
28903
  kinds: ["device-consumable-low", "device-consumable-normal"]
28911
28904
  },
28912
- {
28913
- id: "tanks",
28914
- family: "device-events",
28915
- label: "Tanks",
28916
- kinds: [
28917
- "device-tank-low",
28918
- "device-tank-full",
28919
- "device-tank-normal"
28920
- ]
28921
- },
28922
28905
  {
28923
28906
  id: "detection-blind",
28924
28907
  family: "device-events",
@@ -29892,11 +29875,6 @@ var RULE_BODY_ONLY = ["body"];
29892
29875
  var RULE_TEXT = ["title", "body"];
29893
29876
  var BATTERY = ["device-battery-low", "device-battery-normal"];
29894
29877
  var CONSUMABLE = ["device-consumable-low", "device-consumable-normal"];
29895
- var TANK = [
29896
- "device-tank-low",
29897
- "device-tank-full",
29898
- "device-tank-normal"
29899
- ];
29900
29878
  var ALERT_EPISODE = [
29901
29879
  "alert-critical",
29902
29880
  "alert-error",
@@ -29928,7 +29906,6 @@ var DEVICE_EVENTS = [
29928
29906
  "device-enabled",
29929
29907
  ...BATTERY,
29930
29908
  ...CONSUMABLE,
29931
- ...TANK,
29932
29909
  "stream-online",
29933
29910
  "stream-offline",
29934
29911
  "detection-blind",
@@ -29974,12 +29951,6 @@ var STATE_SUMMARY_SECTION_VARS = [
29974
29951
  example: "Robot — filter 10 %",
29975
29952
  kinds: CONSUMABLE
29976
29953
  },
29977
- {
29978
- name: "summaryTanks",
29979
- label: "Summary: tanks",
29980
- example: "Robot — clean water low",
29981
- kinds: TANK
29982
- },
29983
29954
  {
29984
29955
  name: "summaryDetection",
29985
29956
  label: "Summary: cameras detecting nothing",
@@ -30388,18 +30359,7 @@ var NC_TEMPLATE_VARS = [
30388
30359
  families: ["rule"],
30389
30360
  fields: [...RULE_TEXT],
30390
30361
  kinds: ["system"],
30391
- systemEventKinds: [...CONSUMABLE, ...TANK]
30392
- },
30393
- {
30394
- name: "tank",
30395
- label: "Tank",
30396
- description: "Which tank, as a stable token: cleanWater, dirtyWater, detergent, dustBin, or the device key of any other supply (salt, rinse aid).",
30397
- example: "clean water",
30398
- group: "system",
30399
- families: ["rule"],
30400
- fields: [...RULE_TEXT],
30401
- kinds: ["system"],
30402
- systemEventKinds: [...TANK]
30362
+ systemEventKinds: [...CONSUMABLE]
30403
30363
  },
30404
30364
  {
30405
30365
  name: "profile",
@@ -31050,9 +31010,6 @@ var NC_TEMPLATE_VARS = [
31050
31010
  * delete it from here then, and the served catalog names it again.
31051
31011
  */
31052
31012
  var NC_TEMPLATE_HELD_BACK_SYSTEM_EVENT_KINDS = [
31053
- "device-tank-low",
31054
- "device-tank-full",
31055
- "device-tank-normal",
31056
31013
  "node-restarting",
31057
31014
  "node-updating",
31058
31015
  "alert-critical",
@@ -31165,15 +31122,6 @@ var NC_SYSTEM_EVENT_CLASS_SPECS = [
31165
31122
  snapshotLabel: "Consumables low now",
31166
31123
  snapshotSection: "consumables"
31167
31124
  },
31168
- {
31169
- id: "tanks",
31170
- family: "device-events",
31171
- label: "Tanks (low or full / back to normal)",
31172
- bad: ["device-tank-low", "device-tank-full"],
31173
- recovery: ["device-tank-normal"],
31174
- snapshotLabel: "Tanks low or full now",
31175
- snapshotSection: "tanks"
31176
- },
31177
31125
  {
31178
31126
  id: "motion-noise",
31179
31127
  family: "device-events",
@@ -1138,7 +1138,7 @@ var ExpressionEvalError = class extends Error {
1138
1138
  //#endregion
1139
1139
  //#region src/expression/builtins.ts
1140
1140
  function isStatefulBuiltin(name) {
1141
- return name === "rose" || name === "count";
1141
+ return name === "rose" || name === "count" || name === "dwell" || name === "latchedAt";
1142
1142
  }
1143
1143
  function asFiniteNumber(value, name, index) {
1144
1144
  if (typeof value !== "number" || !Number.isFinite(value)) throw new ExpressionEvalError(`${name}: argument ${index + 1} must be a finite number`);
@@ -1229,6 +1229,57 @@ function disarmRoseMemory(memory) {
1229
1229
  * input is its own `lastPressedAt`, which only advances on a `rose` edge that
1230
1230
  * also emits the press — but an external input can overcount by one.
1231
1231
  */
1232
+ function asNonNegativeMs(value, name, index) {
1233
+ const ms = asFiniteNumber(value, name, index);
1234
+ if (ms < 0) throw new ExpressionEvalError(`${name}: delay must be a non-negative finite number`);
1235
+ return ms;
1236
+ }
1237
+ /**
1238
+ * `dwell(active, onForMs, offForMs)`: unknown until a delay elapses, then holds
1239
+ * the latched boolean through gaps shorter than the opposing delay (D933).
1240
+ */
1241
+ function evaluateDwell(activeRaw, onForMsRaw, offForMsRaw, call, nowMs, hooks) {
1242
+ const active = asBoolean(activeRaw, "dwell", 0);
1243
+ const onForMs = asNonNegativeMs(onForMsRaw, "dwell", 1);
1244
+ const offForMs = asNonNegativeMs(offForMsRaw, "dwell", 2);
1245
+ if (call.latched === null) {
1246
+ if (call.seenSince === null) call.seenSince = nowMs;
1247
+ const delay = active ? onForMs : offForMs;
1248
+ if (nowMs - call.seenSince >= delay) {
1249
+ call.latched = active;
1250
+ return call.latched;
1251
+ }
1252
+ hooks?.noteDeadline?.(call.seenSince + delay);
1253
+ return null;
1254
+ }
1255
+ if (active === call.latched) {
1256
+ call.pendingSince = null;
1257
+ return call.latched;
1258
+ }
1259
+ if (call.pendingSince === null) call.pendingSince = nowMs;
1260
+ const delay = active ? onForMs : offForMs;
1261
+ if (nowMs - call.pendingSince >= delay) {
1262
+ call.latched = active;
1263
+ call.pendingSince = null;
1264
+ return call.latched;
1265
+ }
1266
+ hooks?.noteDeadline?.(call.pendingSince + delay);
1267
+ return call.latched;
1268
+ }
1269
+ /** `latchedAt(value)`: epoch ms when `value` last changed; null clears the stamp. */
1270
+ function evaluateLatchedAt(value, call, nowMs) {
1271
+ if (value === null) {
1272
+ call.last = null;
1273
+ call.at = null;
1274
+ return null;
1275
+ }
1276
+ if (typeof value !== "boolean" && typeof value !== "number" && typeof value !== "string") return call.at;
1277
+ if (call.last !== value) {
1278
+ call.last = value;
1279
+ call.at = nowMs;
1280
+ }
1281
+ return call.at;
1282
+ }
1232
1283
  function evaluateCount(input, call, currentOutput) {
1233
1284
  const currentCount = typeof currentOutput === "number" && Number.isFinite(currentOutput) && currentOutput >= 0 ? currentOutput : 0;
1234
1285
  if (input === null) {
@@ -1398,6 +1449,20 @@ var table = {
1398
1449
  apply: () => {
1399
1450
  throw new ExpressionEvalError("count: stateful evaluation context is required");
1400
1451
  }
1452
+ },
1453
+ dwell: {
1454
+ minArgs: 3,
1455
+ maxArgs: 3,
1456
+ apply: () => {
1457
+ throw new ExpressionEvalError("dwell: stateful evaluation context is required");
1458
+ }
1459
+ },
1460
+ latchedAt: {
1461
+ minArgs: 1,
1462
+ maxArgs: 1,
1463
+ apply: () => {
1464
+ throw new ExpressionEvalError("latchedAt: stateful evaluation context is required");
1465
+ }
1401
1466
  }
1402
1467
  };
1403
1468
  /** Frozen, null-prototype builtin table. */
@@ -1975,7 +2040,7 @@ function cloneStatefulExpressionMemory(memory) {
1975
2040
  disarmRoseNext: memory.disarmRoseNext
1976
2041
  };
1977
2042
  }
1978
- function evaluateStatefulExpressionCall(invocation, memory, env) {
2043
+ function evaluateStatefulExpressionCall(invocation, memory, env, hooks) {
1979
2044
  const existing = memory.calls.get(invocation.path);
1980
2045
  switch (invocation.name) {
1981
2046
  case "rose": {
@@ -1997,6 +2062,25 @@ function evaluateStatefulExpressionCall(invocation, memory, env) {
1997
2062
  memory.calls.set(invocation.path, call);
1998
2063
  return evaluateCount(invocation.args[0], call, env.currentOutput);
1999
2064
  }
2065
+ case "dwell": {
2066
+ const call = existing?.kind === "dwell" ? existing : {
2067
+ kind: "dwell",
2068
+ pendingSince: null,
2069
+ latched: null,
2070
+ seenSince: null
2071
+ };
2072
+ memory.calls.set(invocation.path, call);
2073
+ return evaluateDwell(invocation.args[0], invocation.args[1], invocation.args[2], call, env.nowMs, hooks);
2074
+ }
2075
+ case "latchedAt": {
2076
+ const call = existing?.kind === "latchedAt" ? existing : {
2077
+ kind: "latchedAt",
2078
+ last: void 0,
2079
+ at: null
2080
+ };
2081
+ memory.calls.set(invocation.path, call);
2082
+ return evaluateLatchedAt(invocation.args[0], call, env.nowMs);
2083
+ }
2000
2084
  }
2001
2085
  }
2002
2086
  /** The `now` epoch-ms binding is auto-injected into every evaluation and is a
@@ -1138,7 +1138,7 @@ var ExpressionEvalError = class extends Error {
1138
1138
  //#endregion
1139
1139
  //#region src/expression/builtins.ts
1140
1140
  function isStatefulBuiltin(name) {
1141
- return name === "rose" || name === "count";
1141
+ return name === "rose" || name === "count" || name === "dwell" || name === "latchedAt";
1142
1142
  }
1143
1143
  function asFiniteNumber(value, name, index) {
1144
1144
  if (typeof value !== "number" || !Number.isFinite(value)) throw new ExpressionEvalError(`${name}: argument ${index + 1} must be a finite number`);
@@ -1229,6 +1229,57 @@ function disarmRoseMemory(memory) {
1229
1229
  * input is its own `lastPressedAt`, which only advances on a `rose` edge that
1230
1230
  * also emits the press — but an external input can overcount by one.
1231
1231
  */
1232
+ function asNonNegativeMs(value, name, index) {
1233
+ const ms = asFiniteNumber(value, name, index);
1234
+ if (ms < 0) throw new ExpressionEvalError(`${name}: delay must be a non-negative finite number`);
1235
+ return ms;
1236
+ }
1237
+ /**
1238
+ * `dwell(active, onForMs, offForMs)`: unknown until a delay elapses, then holds
1239
+ * the latched boolean through gaps shorter than the opposing delay (D933).
1240
+ */
1241
+ function evaluateDwell(activeRaw, onForMsRaw, offForMsRaw, call, nowMs, hooks) {
1242
+ const active = asBoolean(activeRaw, "dwell", 0);
1243
+ const onForMs = asNonNegativeMs(onForMsRaw, "dwell", 1);
1244
+ const offForMs = asNonNegativeMs(offForMsRaw, "dwell", 2);
1245
+ if (call.latched === null) {
1246
+ if (call.seenSince === null) call.seenSince = nowMs;
1247
+ const delay = active ? onForMs : offForMs;
1248
+ if (nowMs - call.seenSince >= delay) {
1249
+ call.latched = active;
1250
+ return call.latched;
1251
+ }
1252
+ hooks?.noteDeadline?.(call.seenSince + delay);
1253
+ return null;
1254
+ }
1255
+ if (active === call.latched) {
1256
+ call.pendingSince = null;
1257
+ return call.latched;
1258
+ }
1259
+ if (call.pendingSince === null) call.pendingSince = nowMs;
1260
+ const delay = active ? onForMs : offForMs;
1261
+ if (nowMs - call.pendingSince >= delay) {
1262
+ call.latched = active;
1263
+ call.pendingSince = null;
1264
+ return call.latched;
1265
+ }
1266
+ hooks?.noteDeadline?.(call.pendingSince + delay);
1267
+ return call.latched;
1268
+ }
1269
+ /** `latchedAt(value)`: epoch ms when `value` last changed; null clears the stamp. */
1270
+ function evaluateLatchedAt(value, call, nowMs) {
1271
+ if (value === null) {
1272
+ call.last = null;
1273
+ call.at = null;
1274
+ return null;
1275
+ }
1276
+ if (typeof value !== "boolean" && typeof value !== "number" && typeof value !== "string") return call.at;
1277
+ if (call.last !== value) {
1278
+ call.last = value;
1279
+ call.at = nowMs;
1280
+ }
1281
+ return call.at;
1282
+ }
1232
1283
  function evaluateCount(input, call, currentOutput) {
1233
1284
  const currentCount = typeof currentOutput === "number" && Number.isFinite(currentOutput) && currentOutput >= 0 ? currentOutput : 0;
1234
1285
  if (input === null) {
@@ -1398,6 +1449,20 @@ var table = {
1398
1449
  apply: () => {
1399
1450
  throw new ExpressionEvalError("count: stateful evaluation context is required");
1400
1451
  }
1452
+ },
1453
+ dwell: {
1454
+ minArgs: 3,
1455
+ maxArgs: 3,
1456
+ apply: () => {
1457
+ throw new ExpressionEvalError("dwell: stateful evaluation context is required");
1458
+ }
1459
+ },
1460
+ latchedAt: {
1461
+ minArgs: 1,
1462
+ maxArgs: 1,
1463
+ apply: () => {
1464
+ throw new ExpressionEvalError("latchedAt: stateful evaluation context is required");
1465
+ }
1401
1466
  }
1402
1467
  };
1403
1468
  /** Frozen, null-prototype builtin table. */
@@ -1975,7 +2040,7 @@ function cloneStatefulExpressionMemory(memory) {
1975
2040
  disarmRoseNext: memory.disarmRoseNext
1976
2041
  };
1977
2042
  }
1978
- function evaluateStatefulExpressionCall(invocation, memory, env) {
2043
+ function evaluateStatefulExpressionCall(invocation, memory, env, hooks) {
1979
2044
  const existing = memory.calls.get(invocation.path);
1980
2045
  switch (invocation.name) {
1981
2046
  case "rose": {
@@ -1997,6 +2062,25 @@ function evaluateStatefulExpressionCall(invocation, memory, env) {
1997
2062
  memory.calls.set(invocation.path, call);
1998
2063
  return evaluateCount(invocation.args[0], call, env.currentOutput);
1999
2064
  }
2065
+ case "dwell": {
2066
+ const call = existing?.kind === "dwell" ? existing : {
2067
+ kind: "dwell",
2068
+ pendingSince: null,
2069
+ latched: null,
2070
+ seenSince: null
2071
+ };
2072
+ memory.calls.set(invocation.path, call);
2073
+ return evaluateDwell(invocation.args[0], invocation.args[1], invocation.args[2], call, env.nowMs, hooks);
2074
+ }
2075
+ case "latchedAt": {
2076
+ const call = existing?.kind === "latchedAt" ? existing : {
2077
+ kind: "latchedAt",
2078
+ last: void 0,
2079
+ at: null
2080
+ };
2081
+ memory.calls.set(invocation.path, call);
2082
+ return evaluateLatchedAt(invocation.args[0], call, env.nowMs);
2083
+ }
2000
2084
  }
2001
2085
  }
2002
2086
  /** The `now` epoch-ms binding is auto-injected into every evaluation and is a
@@ -1,5 +1,5 @@
1
1
  import type { CapVocabularySlice } from '../types.js';
2
- type ApplianceCap = 'vacuum-control' | 'lawn-mower-control' | 'dishwasher' | 'pet-feeder' | 'media-player' | 'consumables' | 'navigation' | 'script-runner' | 'automation-control' | 'notifier' | 'update';
2
+ type ApplianceCap = 'vacuum-control' | 'lawn-mower-control' | 'dishwasher' | 'pet-feeder' | 'media-player' | 'consumables' | 'running-state' | 'navigation' | 'script-runner' | 'automation-control' | 'notifier' | 'update';
3
3
  /** The appliance family of the vocabulary. */
4
4
  export declare const APPLIANCE_CAP_VOCABULARY: CapVocabularySlice<ApplianceCap>;
5
5
  export {};
@@ -469,6 +469,10 @@ export declare enum EventCategory {
469
469
  * on the device detail page.
470
470
  */
471
471
  DoorbellOnPressed = "doorbell.onPressed",
472
+ /** Mirrors `runningStateCapability.events.onStarted`. */
473
+ RunningStarted = "running.started",
474
+ /** Mirrors `runningStateCapability.events.onFinished`. */
475
+ RunningFinished = "running.finished",
472
476
  /**
473
477
  * Cap event fired by every device that registers the `event-emitter`
474
478
  * capability. Mirrors `eventEmitterCapability.events.onEvent`. Carries
package/dist/enums.js CHANGED
@@ -1,5 +1,5 @@
1
1
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
- const require_event_category = require("./event-category-CXrwjC3e.js");
2
+ const require_event_category = require("./event-category-DG6Vir8Z.js");
3
3
  //#region src/enums/event-source-type.ts
4
4
  var EventSourceType = /* @__PURE__ */ function(EventSourceType) {
5
5
  EventSourceType["Addon"] = "addon";
package/dist/enums.mjs CHANGED
@@ -1,4 +1,4 @@
1
- import { t as EventCategory } from "./event-category-fDPduoeC.mjs";
1
+ import { t as EventCategory } from "./event-category-Ceif8n-v.mjs";
2
2
  //#region src/enums/event-source-type.ts
3
3
  var EventSourceType = /* @__PURE__ */ function(EventSourceType) {
4
4
  EventSourceType["Addon"] = "addon";
@@ -470,6 +470,10 @@ var EventCategory = /* @__PURE__ */ function(EventCategory) {
470
470
  * on the device detail page.
471
471
  */
472
472
  EventCategory["DoorbellOnPressed"] = "doorbell.onPressed";
473
+ /** Mirrors `runningStateCapability.events.onStarted`. */
474
+ EventCategory["RunningStarted"] = "running.started";
475
+ /** Mirrors `runningStateCapability.events.onFinished`. */
476
+ EventCategory["RunningFinished"] = "running.finished";
473
477
  /**
474
478
  * Cap event fired by every device that registers the `event-emitter`
475
479
  * capability. Mirrors `eventEmitterCapability.events.onEvent`. Carries
@@ -470,6 +470,10 @@ var EventCategory = /* @__PURE__ */ function(EventCategory) {
470
470
  * on the device detail page.
471
471
  */
472
472
  EventCategory["DoorbellOnPressed"] = "doorbell.onPressed";
473
+ /** Mirrors `runningStateCapability.events.onStarted`. */
474
+ EventCategory["RunningStarted"] = "running.started";
475
+ /** Mirrors `runningStateCapability.events.onFinished`. */
476
+ EventCategory["RunningFinished"] = "running.finished";
473
477
  /**
474
478
  * Cap event fired by every device that registers the `event-emitter`
475
479
  * capability. Mirrors `eventEmitterCapability.events.onEvent`. Carries