@camstack/system 1.2.484 → 1.2.486

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 (89) hide show
  1. package/dist/{agent-https-DttPIFry.mjs → agent-https-C4PLR74Z.mjs} +1 -1
  2. package/dist/{agent-https-CW8aLMDL.js → agent-https-DP-Ds2hU.js} +1 -1
  3. package/dist/builtins/addon-pages-aggregator/addon-pages-aggregator.addon.js +1 -1
  4. package/dist/builtins/addon-pages-aggregator/addon-pages-aggregator.addon.mjs +1 -1
  5. package/dist/builtins/addon-widgets-aggregator/addon-widgets-aggregator.addon.js +1 -1
  6. package/dist/builtins/addon-widgets-aggregator/addon-widgets-aggregator.addon.mjs +1 -1
  7. package/dist/builtins/alerts/alerts.addon.js +1 -1
  8. package/dist/builtins/alerts/alerts.addon.mjs +1 -1
  9. package/dist/builtins/autotrack/index.js +1 -1
  10. package/dist/builtins/autotrack/index.mjs +1 -1
  11. package/dist/builtins/backup-orchestrator/backup-orchestrator.addon.js +2 -2
  12. package/dist/builtins/backup-orchestrator/backup-orchestrator.addon.mjs +2 -2
  13. package/dist/builtins/calendars/calendars.addon.js +1 -1
  14. package/dist/builtins/calendars/calendars.addon.mjs +1 -1
  15. package/dist/builtins/camera-grid/index.js +1 -1
  16. package/dist/builtins/camera-grid/index.mjs +1 -1
  17. package/dist/builtins/composer/composer.addon.js +69 -15
  18. package/dist/builtins/composer/composer.addon.mjs +69 -15
  19. package/dist/builtins/composer/composition-runtime.d.ts +2 -0
  20. package/dist/builtins/console-logging/index.js +1 -1
  21. package/dist/builtins/console-logging/index.mjs +1 -1
  22. package/dist/builtins/core-blocks/composition-sources.d.ts +3 -1
  23. package/dist/builtins/core-blocks/core-blocks.addon.js +53 -28
  24. package/dist/builtins/core-blocks/core-blocks.addon.mjs +53 -28
  25. package/dist/builtins/device-history/device-history.addon.d.ts +2 -0
  26. package/dist/builtins/device-history/device-history.addon.js +248 -4
  27. package/dist/builtins/device-history/device-history.addon.mjs +248 -4
  28. package/dist/builtins/device-history/query/history-query.d.ts +5 -1
  29. package/dist/builtins/device-history/runtime/history-runtime.d.ts +18 -1
  30. package/dist/builtins/device-history/store/history-schema.d.ts +2 -0
  31. package/dist/builtins/device-history/store/history-store.d.ts +11 -0
  32. package/dist/builtins/device-history/store/series-scale.d.ts +37 -0
  33. package/dist/builtins/device-manager/device-manager.addon.js +3 -2
  34. package/dist/builtins/device-manager/device-manager.addon.mjs +3 -2
  35. package/dist/builtins/hub-forwarder/index.js +1 -1
  36. package/dist/builtins/hub-forwarder/index.mjs +1 -1
  37. package/dist/builtins/keychain/index.js +3 -3
  38. package/dist/builtins/keychain/index.mjs +3 -3
  39. package/dist/builtins/liveness-monitor/liveness-monitor.addon.js +1 -1
  40. package/dist/builtins/liveness-monitor/liveness-monitor.addon.mjs +1 -1
  41. package/dist/builtins/local-auth/local-auth.addon.js +2 -2
  42. package/dist/builtins/local-auth/local-auth.addon.mjs +2 -2
  43. package/dist/builtins/local-network/local-network.addon.js +2 -2
  44. package/dist/builtins/local-network/local-network.addon.mjs +2 -2
  45. package/dist/builtins/loki-logging/index.js +1 -1
  46. package/dist/builtins/loki-logging/index.mjs +1 -1
  47. package/dist/builtins/native-metrics/native-metrics.addon.js +1 -1
  48. package/dist/builtins/native-metrics/native-metrics.addon.mjs +1 -1
  49. package/dist/builtins/platform-probe/index.js +1 -1
  50. package/dist/builtins/platform-probe/index.mjs +1 -1
  51. package/dist/builtins/record-entries/index.js +1 -1
  52. package/dist/builtins/record-entries/index.mjs +1 -1
  53. package/dist/builtins/remote-access-orchestrator/remote-access-orchestrator.addon.js +1 -1
  54. package/dist/builtins/remote-access-orchestrator/remote-access-orchestrator.addon.mjs +1 -1
  55. package/dist/builtins/snapshot/index.js +1 -1
  56. package/dist/builtins/snapshot/index.mjs +1 -1
  57. package/dist/builtins/sqlite-storage/filesystem-storage.addon.js +1 -1
  58. package/dist/builtins/sqlite-storage/filesystem-storage.addon.mjs +1 -1
  59. package/dist/builtins/sqlite-storage/index.js +1 -1
  60. package/dist/builtins/sqlite-storage/index.mjs +1 -1
  61. package/dist/builtins/sqlite-storage/sqlite-settings.addon.js +2 -2
  62. package/dist/builtins/sqlite-storage/sqlite-settings.addon.mjs +2 -2
  63. package/dist/builtins/storage-orchestrator/storage-orchestrator.addon.js +1 -1
  64. package/dist/builtins/storage-orchestrator/storage-orchestrator.addon.mjs +1 -1
  65. package/dist/builtins/system-config/system-config.addon.js +3 -3
  66. package/dist/builtins/system-config/system-config.addon.mjs +3 -3
  67. package/dist/builtins/winston-logging/index.js +1 -1
  68. package/dist/builtins/winston-logging/index.mjs +1 -1
  69. package/dist/{composition-sources-DqRPHdtw.js → composition-sources-CN8K2Q91.js} +4 -2
  70. package/dist/{composition-sources-DEsDonpg.mjs → composition-sources-IxiUkrz1.mjs} +4 -2
  71. package/dist/{constants-71vf77HY.js → constants-1S7BBGMb.js} +1 -1
  72. package/dist/{constants-B3FDrBIq.mjs → constants-DLyGFHZ2.mjs} +1 -1
  73. package/dist/{device-ca-bhz04X_N.mjs → device-ca-Cbf7_R9t.mjs} +1 -1
  74. package/dist/{device-ca-BDPYXhkH.js → device-ca-DoOFG0nm.js} +1 -1
  75. package/dist/{dist-k--OhKkO.js → dist-D-d_UWL4.js} +1375 -537
  76. package/dist/{dist-BT_THdzJ.mjs → dist-HBue971z.mjs} +1364 -538
  77. package/dist/file-host-worker.js +1 -1
  78. package/dist/file-host-worker.mjs +1 -1
  79. package/dist/{hub-mdns-ciao-DDgdvcQw.mjs → hub-mdns-ciao-CuEWb6gB.mjs} +2 -2
  80. package/dist/{hub-mdns-ciao-CGXfhvTk.js → hub-mdns-ciao-dcacrwqd.js} +2 -2
  81. package/dist/index.js +7 -7
  82. package/dist/index.mjs +7 -7
  83. package/dist/{restore-archive-z0XT2g29.mjs → restore-archive-BGBRadFJ.mjs} +1 -1
  84. package/dist/{restore-archive-B-GiglWt.js → restore-archive-DHdXrKwG.js} +1 -1
  85. package/dist/{retention-DFkmhjeH.mjs → retention-8uqDWll8.mjs} +1 -1
  86. package/dist/{retention-DR0_xRTy.js → retention-ChgrkTfz.js} +1 -1
  87. package/dist/{wal-maintenance-C4cma95b.js → wal-maintenance-BOT7wWvH.js} +0 -0
  88. package/dist/{wal-maintenance-CVDrL_BD.mjs → wal-maintenance-DubGwqz2.mjs} +0 -0
  89. package/package.json +1 -1
@@ -1,4 +1,4 @@
1
- import { Ji as defineRecordKinds } from "./dist-BT_THdzJ.mjs";
1
+ import { Ji as defineRecordKinds } from "./dist-HBue971z.mjs";
2
2
  import { C as backdatedNotBefore, S as withUtcTimeEncoding, _ as NameConstraints, a as KeyUsageFlags, c as Pkcs10CertificateRequest, d as SubjectKeyIdentifierExtension, f as X509Certificate$1, g as GeneralSubtrees, h as GeneralSubtree, i as Extension, l as Pkcs10CertificateRequestGenerator, m as cryptoProvider, n as BasicConstraintsExtension, o as KeyUsagesExtension, p as X509CertificateGenerator, r as ExtendedKeyUsageExtension, s as PemConverter, t as AuthorityKeyIdentifierExtension, u as SubjectAlternativeNameExtension, v as GeneralName, x as AsnConvert } from "./x509.es-BRiJgOvu.mjs";
3
3
  import { z } from "zod";
4
4
  import { X509Certificate, createHash, createPrivateKey, randomBytes, webcrypto } from "node:crypto";
@@ -1,5 +1,5 @@
1
1
  const require_chunk = require("./chunk-Cek0wNdY.js");
2
- const require_dist = require("./dist-k--OhKkO.js");
2
+ const require_dist = require("./dist-D-d_UWL4.js");
3
3
  const require_x509_es = require("./x509.es-WtnRNyYS.js");
4
4
  let zod = require("zod");
5
5
  let node_crypto = require("node:crypto");
@@ -3,7 +3,7 @@ Object.defineProperties(exports, {
3
3
  [Symbol.toStringTag]: { value: "Module" }
4
4
  });
5
5
  const require_chunk = require("../../chunk-Cek0wNdY.js");
6
- const require_dist = require("../../dist-k--OhKkO.js");
6
+ const require_dist = require("../../dist-D-d_UWL4.js");
7
7
  const require_settle_sources = require("../../settle-sources-Bhsy57y-.js");
8
8
  let node_crypto = require("node:crypto");
9
9
  let node_path = require("node:path");
@@ -1,4 +1,4 @@
1
- import { _t as addonPagesCapability, ka as EventCategory, ni as BaseAddon, ti as errMsg } from "../../dist-BT_THdzJ.mjs";
1
+ import { _t as addonPagesCapability, ja as EventCategory, ni as BaseAddon, ti as errMsg } from "../../dist-HBue971z.mjs";
2
2
  import { t as settleSourcesWithTimeout } from "../../settle-sources-CDtNC8ub.mjs";
3
3
  import { createHash, randomUUID } from "node:crypto";
4
4
  import * as path$1 from "node:path";
@@ -3,7 +3,7 @@ Object.defineProperties(exports, {
3
3
  [Symbol.toStringTag]: { value: "Module" }
4
4
  });
5
5
  const require_chunk = require("../../chunk-Cek0wNdY.js");
6
- const require_dist = require("../../dist-k--OhKkO.js");
6
+ const require_dist = require("../../dist-D-d_UWL4.js");
7
7
  const require_settle_sources = require("../../settle-sources-Bhsy57y-.js");
8
8
  let node_crypto = require("node:crypto");
9
9
  let node_path = require("node:path");
@@ -1,4 +1,4 @@
1
- import { ka as EventCategory, ni as BaseAddon, ti as errMsg, yt as addonWidgetsCapability } from "../../dist-BT_THdzJ.mjs";
1
+ import { ja as EventCategory, ni as BaseAddon, ti as errMsg, yt as addonWidgetsCapability } from "../../dist-HBue971z.mjs";
2
2
  import { t as settleSourcesWithTimeout } from "../../settle-sources-CDtNC8ub.mjs";
3
3
  import { createHash, randomUUID } from "node:crypto";
4
4
  import * as path$1 from "node:path";
@@ -3,7 +3,7 @@ Object.defineProperties(exports, {
3
3
  [Symbol.toStringTag]: { value: "Module" }
4
4
  });
5
5
  require("../../chunk-Cek0wNdY.js");
6
- const require_dist = require("../../dist-k--OhKkO.js");
6
+ const require_dist = require("../../dist-D-d_UWL4.js");
7
7
  const require_read_all_rows$1 = require("../../read-all-rows-CVoO1ONM.js");
8
8
  //#region src/builtins/alerts/alert-episode-policy.ts
9
9
  /**
@@ -1,4 +1,4 @@
1
- import { Gi as createEvent, Ji as defineRecordKinds, St as alertsCapability, bn as isAlertEpisodeSeverity, bt as alertEpisodeId, i as AlertSchema, ka as EventCategory, ni as BaseAddon, ti as errMsg, xt as alertEpisodePayload, yn as isAlertEpisodeOpen } from "../../dist-BT_THdzJ.mjs";
1
+ import { Gi as createEvent, Ji as defineRecordKinds, St as alertsCapability, bn as isAlertEpisodeSeverity, bt as alertEpisodeId, i as AlertSchema, ja as EventCategory, ni as BaseAddon, ti as errMsg, xt as alertEpisodePayload, yn as isAlertEpisodeOpen } from "../../dist-HBue971z.mjs";
2
2
  import { t as require_read_all_rows } from "../../read-all-rows-TaPqdWNF.mjs";
3
3
  //#region src/builtins/alerts/alert-episode-policy.ts
4
4
  /**
@@ -3,7 +3,7 @@ Object.defineProperties(exports, {
3
3
  [Symbol.toStringTag]: { value: "Module" }
4
4
  });
5
5
  require("../../chunk-Cek0wNdY.js");
6
- const require_dist = require("../../dist-k--OhKkO.js");
6
+ const require_dist = require("../../dist-D-d_UWL4.js");
7
7
  //#region src/builtins/autotrack/autotrack-config.ts
8
8
  var DEFAULT_AUTOTRACK_LOOP_CONFIG = {
9
9
  deadZoneFraction: .5,
@@ -1,4 +1,4 @@
1
- import { Et as bareAddonId, I as FIRST_LEVEL_MACRO_CLASSES, ka as EventCategory, na as isEvent, ni as BaseAddon, rr as ptzAutotrackCapability, ti as errMsg } from "../../dist-BT_THdzJ.mjs";
1
+ import { Et as bareAddonId, I as FIRST_LEVEL_MACRO_CLASSES, ja as EventCategory, ni as BaseAddon, ra as isEvent, rr as ptzAutotrackCapability, ti as errMsg } from "../../dist-HBue971z.mjs";
2
2
  //#region src/builtins/autotrack/autotrack-config.ts
3
3
  var DEFAULT_AUTOTRACK_LOOP_CONFIG = {
4
4
  deadZoneFraction: .5,
@@ -3,9 +3,9 @@ Object.defineProperties(exports, {
3
3
  [Symbol.toStringTag]: { value: "Module" }
4
4
  });
5
5
  const require_chunk = require("../../chunk-Cek0wNdY.js");
6
- const require_dist = require("../../dist-k--OhKkO.js");
6
+ const require_dist = require("../../dist-D-d_UWL4.js");
7
7
  const require_read_all_rows$1 = require("../../read-all-rows-CVoO1ONM.js");
8
- const require_restore_archive = require("../../restore-archive-B-GiglWt.js");
8
+ const require_restore_archive = require("../../restore-archive-DHdXrKwG.js");
9
9
  let node_crypto = require("node:crypto");
10
10
  let node_fs_promises = require("node:fs/promises");
11
11
  node_fs_promises = require_chunk.__toESM(node_fs_promises);
@@ -1,6 +1,6 @@
1
- import { Or as storageOccupancyCapability, Tt as backupCapability, Vn as mayWriteToLocation, ka as EventCategory, ni as BaseAddon, ua as nodePin, wa as toNodeId } from "../../dist-BT_THdzJ.mjs";
1
+ import { Ea as toNodeId, Or as storageOccupancyCapability, Tt as backupCapability, Vn as mayWriteToLocation, fa as nodePin, ja as EventCategory, ni as BaseAddon } from "../../dist-HBue971z.mjs";
2
2
  import { t as require_read_all_rows } from "../../read-all-rows-TaPqdWNF.mjs";
3
- import { _ as backupRecordStoresOf, a as BackupSnapshotRefusedError, d as ENCRYPTED_BACKUP_SUFFIX, f as generateBackupKeyPair, g as backupOrchestratorRecordKinds, i as BackupCancelledError, l as BackupKeyFormatError, m as parseBackupSecretKey, n as precheckRestoreKey, o as DEFAULT_BACKUP_DATABASES, p as parseBackupPublicKey, r as prepareRestoreArchive, s as SystemBackupService } from "../../restore-archive-z0XT2g29.mjs";
3
+ import { _ as backupRecordStoresOf, a as BackupSnapshotRefusedError, d as ENCRYPTED_BACKUP_SUFFIX, f as generateBackupKeyPair, g as backupOrchestratorRecordKinds, i as BackupCancelledError, l as BackupKeyFormatError, m as parseBackupSecretKey, n as precheckRestoreKey, o as DEFAULT_BACKUP_DATABASES, p as parseBackupPublicKey, r as prepareRestoreArchive, s as SystemBackupService } from "../../restore-archive-BGBRadFJ.mjs";
4
4
  import { randomUUID } from "node:crypto";
5
5
  import * as fsp from "node:fs/promises";
6
6
  import * as path$1 from "node:path";
@@ -3,7 +3,7 @@ Object.defineProperties(exports, {
3
3
  [Symbol.toStringTag]: { value: "Module" }
4
4
  });
5
5
  require("../../chunk-Cek0wNdY.js");
6
- const require_dist = require("../../dist-k--OhKkO.js");
6
+ const require_dist = require("../../dist-D-d_UWL4.js");
7
7
  const require_settle_sources = require("../../settle-sources-Bhsy57y-.js");
8
8
  let zod = require("zod");
9
9
  //#region src/builtins/calendars/calendar-color.ts
@@ -1,4 +1,4 @@
1
- import { Ji as defineRecordKinds, Mt as calendarsCapability, g as CalendarPreferencesSchema, ni as BaseAddon } from "../../dist-BT_THdzJ.mjs";
1
+ import { Ji as defineRecordKinds, Mt as calendarsCapability, g as CalendarPreferencesSchema, ni as BaseAddon } from "../../dist-HBue971z.mjs";
2
2
  import { t as settleSourcesWithTimeout } from "../../settle-sources-CDtNC8ub.mjs";
3
3
  import { z } from "zod";
4
4
  //#region src/builtins/calendars/calendar-color.ts
@@ -3,7 +3,7 @@ Object.defineProperties(exports, {
3
3
  [Symbol.toStringTag]: { value: "Module" }
4
4
  });
5
5
  require("../../chunk-Cek0wNdY.js");
6
- const require_dist = require("../../dist-k--OhKkO.js");
6
+ const require_dist = require("../../dist-D-d_UWL4.js");
7
7
  let zod = require("zod");
8
8
  let _camstack_types_node = require("@camstack/types/node");
9
9
  let node_path = require("node:path");
@@ -1,4 +1,4 @@
1
- import { Ar as streamCatalogCapability, Cr as snapshotCapability, Gi as createEvent, Gn as motionCapability, Hn as memoizePinnedFfmpeg, N as DeclaredDevices, Nt as cameraGridLayoutCapability, Qr as DeviceFeature, T as DERIVED_CAMERA_SILENCED_CAP_NAMES, Vr as buildFfmpegArgs, X as MOTION_CLOSE_AFTER_MS, a as BaseDevice, ea as hydrateSchema, ei as DeviceType, ka as EventCategory, ni as BaseAddon, qt as declarationOwnerNodeId, ti as errMsg } from "../../dist-BT_THdzJ.mjs";
1
+ import { Ar as streamCatalogCapability, Cr as snapshotCapability, Gi as createEvent, Gn as motionCapability, Hn as memoizePinnedFfmpeg, N as DeclaredDevices, Nt as cameraGridLayoutCapability, Qr as DeviceFeature, T as DERIVED_CAMERA_SILENCED_CAP_NAMES, Vr as buildFfmpegArgs, X as MOTION_CLOSE_AFTER_MS, a as BaseDevice, ei as DeviceType, ja as EventCategory, ni as BaseAddon, qt as declarationOwnerNodeId, ta as hydrateSchema, ti as errMsg } from "../../dist-HBue971z.mjs";
2
2
  import { z } from "zod";
3
3
  import { FfmpegProcess } from "@camstack/types/node";
4
4
  import { join } from "node:path";
@@ -3,22 +3,22 @@ Object.defineProperties(exports, {
3
3
  [Symbol.toStringTag]: { value: "Module" }
4
4
  });
5
5
  require("../../chunk-Cek0wNdY.js");
6
- const require_dist = require("../../dist-k--OhKkO.js");
7
- const require_composition_sources = require("../../composition-sources-DqRPHdtw.js");
8
- const require_retention = require("../../retention-DR0_xRTy.js");
6
+ const require_dist = require("../../dist-D-d_UWL4.js");
7
+ const require_composition_sources = require("../../composition-sources-CN8K2Q91.js");
8
+ const require_retention = require("../../retention-ChgrkTfz.js");
9
9
  let zod = require("zod");
10
10
  //#region src/builtins/shared/device-state-changed.ts
11
11
  /** Structural narrowing helper for untrusted bus payloads. */
12
- function isRecord$2(value) {
12
+ function isRecord$3(value) {
13
13
  return typeof value === "object" && value !== null && !Array.isArray(value);
14
14
  }
15
15
  function parseDeviceStateChanged(data) {
16
- if (!isRecord$2(data)) return null;
16
+ if (!isRecord$3(data)) return null;
17
17
  const deviceId = data["deviceId"];
18
18
  const capName = data["capName"];
19
19
  const slice = data["slice"];
20
20
  if (typeof deviceId !== "number" || typeof capName !== "string") return null;
21
- if (!isRecord$2(slice)) return null;
21
+ if (!isRecord$3(slice)) return null;
22
22
  return {
23
23
  deviceId,
24
24
  capName,
@@ -50,11 +50,29 @@ function parseDeviceStateChanged(data) {
50
50
  * declaration is the authority for what this device is.
51
51
  */
52
52
  var COMPOSED_DEVICE_CONFIG_SCHEMA = zod.z.object({});
53
+ function isRecord$2(value) {
54
+ return typeof value === "object" && value !== null && !Array.isArray(value);
55
+ }
56
+ /** Unknown is a throw, never `false` (D393). */
57
+ function sliceBoolean(slice, field) {
58
+ if (isRecord$2(slice)) {
59
+ const value = slice[field];
60
+ if (typeof value === "boolean") return value;
61
+ }
62
+ throw new Error(`composed ${field} is unknown — not a stand-in value`);
63
+ }
53
64
  var ComposedDevice = class extends require_dist.BaseDevice {
54
65
  features = [];
55
66
  constructor(ctx, type, caps) {
56
67
  super(ctx, COMPOSED_DEVICE_CONFIG_SCHEMA, { type });
57
- for (const cap of caps) ctx.registerNativeCap(cap, {});
68
+ for (const cap of caps) {
69
+ if (cap.name === require_dist.motionCapability.name) {
70
+ const read = () => this.runtimeState.getCapState(require_dist.motionCapability.name);
71
+ ctx.registerNativeCap(require_dist.motionCapability, { isDetected: async () => sliceBoolean(read(), "detected") });
72
+ continue;
73
+ }
74
+ ctx.registerNativeCap(cap, {});
75
+ }
58
76
  this.markOnline(false);
59
77
  }
60
78
  seed(capName, slice) {
@@ -569,7 +587,7 @@ function withEntry(map, key, value) {
569
587
  return new Map([...map, [key, value]]);
570
588
  }
571
589
  function nativeTakenReason(addonId, when) {
572
- return `a native provider (${addonId}) ${when} — the cap is not grafted and its claim is kept; edit or restart the block to replace the native instead`;
590
+ return `a native provider (${addonId}) ${when} — the cap is not grafted and its claim is kept`;
573
591
  }
574
592
  var ComposerGrafts = class {
575
593
  ports;
@@ -610,9 +628,10 @@ var ComposerGrafts = class {
610
628
  if (ports === void 0) return;
611
629
  const { deviceId } = input;
612
630
  const added = input.enabled && input.settled ? addedCapsOf(input.features) : [];
631
+ const nativeNow = new Set([...input.nativeCaps.entries()].filter(([, owner]) => owner !== require_dist.COMPOSER_ADDON_ID).map(([cap]) => cap));
613
632
  const replaced = new Set(input.features.filter((f) => f.mode === "replace").map((f) => f.cap));
614
633
  for (const cap of ports.grafted(deviceId)) {
615
- if (!replaced.has(cap)) continue;
634
+ if (!nativeNow.has(cap) && !replaced.has(cap)) continue;
616
635
  this.logger.info("a native provider serves a grafted cap — the graft is removed; the claim stays", {
617
636
  tags: { deviceId },
618
637
  meta: { cap }
@@ -1161,6 +1180,13 @@ function logPlanTransition(logger, previous, p, liveTags) {
1161
1180
  }
1162
1181
  });
1163
1182
  else if (p.problems.length === 0) logger.info("composition plans again", extras);
1183
+ else if (target.kind === "existing" && target.deviceId !== null && p.problems.some((line) => line.includes("native-capability-replace"))) logger.warn(`stored customization ${p.block.id} replaces a native capability — refused`, {
1184
+ tags: { deviceId: target.deviceId },
1185
+ meta: {
1186
+ ...extras.meta,
1187
+ problems: p.problems
1188
+ }
1189
+ });
1164
1190
  else logger.warn(p.declaration === null ? "composition does not plan — no device is declared for it" : "composition no longer plans — its device is kept offline with no capabilities", extras);
1165
1191
  }
1166
1192
  //#endregion
@@ -1287,7 +1313,9 @@ function writable(record) {
1287
1313
  switch (record.plan.unavailable) {
1288
1314
  case "null": return null;
1289
1315
  case "unknown": return "unknown";
1290
- default: return;
1316
+ case "omit":
1317
+ case "offline":
1318
+ case "release": return;
1291
1319
  }
1292
1320
  }
1293
1321
  function errorText(error) {
@@ -2010,7 +2038,16 @@ var CompositionRuntime = class {
2010
2038
  this.seeded = new Set([...this.seeded, cap]);
2011
2039
  this.markWritten(cap, entries);
2012
2040
  }
2041
+ /** An omitted optional reading must leave the slice, not keep the previous number (D944). */
2042
+ clearsOmitted(cap) {
2043
+ return this.recordsOf(cap).some((record) => record.plan.unavailable === "omit" && record.outcome?.state === "unavailable");
2044
+ }
2013
2045
  patchCap(cap, touched) {
2046
+ if (this.clearsOmitted(cap)) {
2047
+ const entries = this.entriesFor(cap, this.recordsOf(cap));
2048
+ if (this.write(cap, "seed", entries)) this.markWritten(cap, entries);
2049
+ return;
2050
+ }
2014
2051
  const entries = this.entriesFor(cap, this.recordsOf(cap).filter((r) => touched.has(fieldKey(r.plan)) && (!r.hasWritten || writable(r) !== r.written)));
2015
2052
  if (entries.length === 0) return;
2016
2053
  if (this.write(cap, "patch", entries)) this.markWritten(cap, entries);
@@ -3738,8 +3775,21 @@ var NodeDeadlineTimer = class {
3738
3775
  function unanswered(def) {
3739
3776
  return Object.entries(def.methods).filter(([name, m]) => m.systemOnly !== true && def.composedMethods?.[name] === void 0).map(([name]) => name);
3740
3777
  }
3741
- function composedMethod(answer) {
3778
+ function isSliceRecord(value) {
3779
+ return typeof value === "object" && value !== null && !Array.isArray(value);
3780
+ }
3781
+ /** A slice field that is present. Unknown throws — it is not false or 0 (D393). */
3782
+ function sliceField(slice, field) {
3783
+ const value = slice?.[field];
3784
+ if (typeof value === "boolean" || typeof value === "number" || typeof value === "string") return value;
3785
+ throw new Error(`composed ${field} is unknown — not a stand-in value`);
3786
+ }
3787
+ function composedMethod(answer, readSlice) {
3742
3788
  if (answer.kind === "answer") return async () => answer.value;
3789
+ if (answer.kind === "slice") {
3790
+ const field = answer.field;
3791
+ return async () => sliceField(await readSlice(), field);
3792
+ }
3743
3793
  return async () => {
3744
3794
  throw new Error(answer.reason);
3745
3795
  };
@@ -3857,7 +3907,11 @@ var GraftHost = class {
3857
3907
  return ctx;
3858
3908
  }
3859
3909
  providerFor(deviceId, def) {
3860
- const answers = Object.entries(def.composedMethods ?? {}).map(([name, answer]) => [name, composedMethod(answer)]);
3910
+ const readSlice = async () => {
3911
+ const slice = await this.readMerged(deviceId, def.name);
3912
+ return isSliceRecord(slice) ? slice : null;
3913
+ };
3914
+ const answers = Object.entries(def.composedMethods ?? {}).map(([name, answer]) => [name, composedMethod(answer, readSlice)]);
3861
3915
  const withStatus = def.status === void 0 && def.runtimeState === void 0 ? [] : [["getStatus", async () => this.readMerged(deviceId, def.name)]];
3862
3916
  return Object.fromEntries([...answers, ...withStatus]);
3863
3917
  }
@@ -3934,7 +3988,7 @@ function entriesOf(request) {
3934
3988
  }))];
3935
3989
  }
3936
3990
  function valueAtPath(slice, path) {
3937
- return path.split(".").reduce((node, segment) => isRecord$2(node) ? node[segment] : void 0, slice);
3991
+ return path.split(".").reduce((node, segment) => isRecord$3(node) ? node[segment] : void 0, slice);
3938
3992
  }
3939
3993
  function onlineOf(slice) {
3940
3994
  const online = slice["online"];
@@ -4601,12 +4655,12 @@ var DECLARED_INTEGRATION_NAME_UNUSED = "Blocks";
4601
4655
  var PULSE_HISTORY_MAX_POINTS = 5e3;
4602
4656
  /** The owner-only shadow payload is not in the typed catalog: narrowed at the boundary, like `device.state-changed`. */
4603
4657
  function parseNativeShadowChanged(data) {
4604
- if (!isRecord$2(data)) return null;
4658
+ if (!isRecord$3(data)) return null;
4605
4659
  const deviceId = data["deviceId"];
4606
4660
  const capName = data["capName"];
4607
4661
  const native = data["native"];
4608
4662
  if (typeof deviceId !== "number" || typeof capName !== "string") return null;
4609
- if (!isRecord$2(native)) return null;
4663
+ if (!isRecord$3(native)) return null;
4610
4664
  return {
4611
4665
  deviceId,
4612
4666
  capName,
@@ -1,19 +1,19 @@
1
- import { $n as planComposition, Br as COMPOSER_ADDON_ID, Gi as createEvent, Gr as compositionFeatureEnabled, Hr as cloneStatefulExpressionMemory, It as composerCapability, Jr as compositionSourceKey, Kr as compositionItemFieldPath, Lt as compositionFieldKey, N as DeclaredDevices, Ot as buildCapabilityLookup, Ur as composedDeviceRef, Wr as composedDeviceStableId, Xr as disarmRoseMemory, Yr as createStatefulExpressionMemory, Zr as toExpressionValue, a as BaseDevice, cn as evaluateCompositionField, d as COMPOSED_ITEM_FIXED_FIELDS, dn as expressionContainsBuiltinCall, ei as DeviceType, ka as EventCategory, ni as BaseAddon, qr as compositionSliceKey, r as ALL_CAPABILITY_DEFINITIONS, ti as errMsg } from "../../dist-BT_THdzJ.mjs";
2
- import { n as normalizedNativeOwner } from "../../composition-sources-DEsDonpg.mjs";
3
- import { i as DAY_MS, m as capSeriesKey, t as DEFAULT_RETENTION } from "../../retention-DFkmhjeH.mjs";
1
+ import { $n as planComposition, Br as COMPOSER_ADDON_ID, Gi as createEvent, Gn as motionCapability, Gr as compositionFeatureEnabled, Hr as cloneStatefulExpressionMemory, It as composerCapability, Jr as compositionSourceKey, Kr as compositionItemFieldPath, Lt as compositionFieldKey, N as DeclaredDevices, Ot as buildCapabilityLookup, Ur as composedDeviceRef, Wr as composedDeviceStableId, Xr as disarmRoseMemory, Yr as createStatefulExpressionMemory, Zr as toExpressionValue, a as BaseDevice, cn as evaluateCompositionField, d as COMPOSED_ITEM_FIXED_FIELDS, dn as expressionContainsBuiltinCall, ei as DeviceType, ja as EventCategory, ni as BaseAddon, qr as compositionSliceKey, r as ALL_CAPABILITY_DEFINITIONS, ti as errMsg } from "../../dist-HBue971z.mjs";
2
+ import { n as normalizedNativeOwner } from "../../composition-sources-IxiUkrz1.mjs";
3
+ import { i as DAY_MS, m as capSeriesKey, t as DEFAULT_RETENTION } from "../../retention-8uqDWll8.mjs";
4
4
  import { z } from "zod";
5
5
  //#region src/builtins/shared/device-state-changed.ts
6
6
  /** Structural narrowing helper for untrusted bus payloads. */
7
- function isRecord$2(value) {
7
+ function isRecord$3(value) {
8
8
  return typeof value === "object" && value !== null && !Array.isArray(value);
9
9
  }
10
10
  function parseDeviceStateChanged(data) {
11
- if (!isRecord$2(data)) return null;
11
+ if (!isRecord$3(data)) return null;
12
12
  const deviceId = data["deviceId"];
13
13
  const capName = data["capName"];
14
14
  const slice = data["slice"];
15
15
  if (typeof deviceId !== "number" || typeof capName !== "string") return null;
16
- if (!isRecord$2(slice)) return null;
16
+ if (!isRecord$3(slice)) return null;
17
17
  return {
18
18
  deviceId,
19
19
  capName,
@@ -45,11 +45,29 @@ function parseDeviceStateChanged(data) {
45
45
  * declaration is the authority for what this device is.
46
46
  */
47
47
  var COMPOSED_DEVICE_CONFIG_SCHEMA = z.object({});
48
+ function isRecord$2(value) {
49
+ return typeof value === "object" && value !== null && !Array.isArray(value);
50
+ }
51
+ /** Unknown is a throw, never `false` (D393). */
52
+ function sliceBoolean(slice, field) {
53
+ if (isRecord$2(slice)) {
54
+ const value = slice[field];
55
+ if (typeof value === "boolean") return value;
56
+ }
57
+ throw new Error(`composed ${field} is unknown — not a stand-in value`);
58
+ }
48
59
  var ComposedDevice = class extends BaseDevice {
49
60
  features = [];
50
61
  constructor(ctx, type, caps) {
51
62
  super(ctx, COMPOSED_DEVICE_CONFIG_SCHEMA, { type });
52
- for (const cap of caps) ctx.registerNativeCap(cap, {});
63
+ for (const cap of caps) {
64
+ if (cap.name === motionCapability.name) {
65
+ const read = () => this.runtimeState.getCapState(motionCapability.name);
66
+ ctx.registerNativeCap(motionCapability, { isDetected: async () => sliceBoolean(read(), "detected") });
67
+ continue;
68
+ }
69
+ ctx.registerNativeCap(cap, {});
70
+ }
53
71
  this.markOnline(false);
54
72
  }
55
73
  seed(capName, slice) {
@@ -564,7 +582,7 @@ function withEntry(map, key, value) {
564
582
  return new Map([...map, [key, value]]);
565
583
  }
566
584
  function nativeTakenReason(addonId, when) {
567
- return `a native provider (${addonId}) ${when} — the cap is not grafted and its claim is kept; edit or restart the block to replace the native instead`;
585
+ return `a native provider (${addonId}) ${when} — the cap is not grafted and its claim is kept`;
568
586
  }
569
587
  var ComposerGrafts = class {
570
588
  ports;
@@ -605,9 +623,10 @@ var ComposerGrafts = class {
605
623
  if (ports === void 0) return;
606
624
  const { deviceId } = input;
607
625
  const added = input.enabled && input.settled ? addedCapsOf(input.features) : [];
626
+ const nativeNow = new Set([...input.nativeCaps.entries()].filter(([, owner]) => owner !== COMPOSER_ADDON_ID).map(([cap]) => cap));
608
627
  const replaced = new Set(input.features.filter((f) => f.mode === "replace").map((f) => f.cap));
609
628
  for (const cap of ports.grafted(deviceId)) {
610
- if (!replaced.has(cap)) continue;
629
+ if (!nativeNow.has(cap) && !replaced.has(cap)) continue;
611
630
  this.logger.info("a native provider serves a grafted cap — the graft is removed; the claim stays", {
612
631
  tags: { deviceId },
613
632
  meta: { cap }
@@ -1156,6 +1175,13 @@ function logPlanTransition(logger, previous, p, liveTags) {
1156
1175
  }
1157
1176
  });
1158
1177
  else if (p.problems.length === 0) logger.info("composition plans again", extras);
1178
+ else if (target.kind === "existing" && target.deviceId !== null && p.problems.some((line) => line.includes("native-capability-replace"))) logger.warn(`stored customization ${p.block.id} replaces a native capability — refused`, {
1179
+ tags: { deviceId: target.deviceId },
1180
+ meta: {
1181
+ ...extras.meta,
1182
+ problems: p.problems
1183
+ }
1184
+ });
1159
1185
  else logger.warn(p.declaration === null ? "composition does not plan — no device is declared for it" : "composition no longer plans — its device is kept offline with no capabilities", extras);
1160
1186
  }
1161
1187
  //#endregion
@@ -1282,7 +1308,9 @@ function writable(record) {
1282
1308
  switch (record.plan.unavailable) {
1283
1309
  case "null": return null;
1284
1310
  case "unknown": return "unknown";
1285
- default: return;
1311
+ case "omit":
1312
+ case "offline":
1313
+ case "release": return;
1286
1314
  }
1287
1315
  }
1288
1316
  function errorText(error) {
@@ -2005,7 +2033,16 @@ var CompositionRuntime = class {
2005
2033
  this.seeded = new Set([...this.seeded, cap]);
2006
2034
  this.markWritten(cap, entries);
2007
2035
  }
2036
+ /** An omitted optional reading must leave the slice, not keep the previous number (D944). */
2037
+ clearsOmitted(cap) {
2038
+ return this.recordsOf(cap).some((record) => record.plan.unavailable === "omit" && record.outcome?.state === "unavailable");
2039
+ }
2008
2040
  patchCap(cap, touched) {
2041
+ if (this.clearsOmitted(cap)) {
2042
+ const entries = this.entriesFor(cap, this.recordsOf(cap));
2043
+ if (this.write(cap, "seed", entries)) this.markWritten(cap, entries);
2044
+ return;
2045
+ }
2009
2046
  const entries = this.entriesFor(cap, this.recordsOf(cap).filter((r) => touched.has(fieldKey(r.plan)) && (!r.hasWritten || writable(r) !== r.written)));
2010
2047
  if (entries.length === 0) return;
2011
2048
  if (this.write(cap, "patch", entries)) this.markWritten(cap, entries);
@@ -3733,8 +3770,21 @@ var NodeDeadlineTimer = class {
3733
3770
  function unanswered(def) {
3734
3771
  return Object.entries(def.methods).filter(([name, m]) => m.systemOnly !== true && def.composedMethods?.[name] === void 0).map(([name]) => name);
3735
3772
  }
3736
- function composedMethod(answer) {
3773
+ function isSliceRecord(value) {
3774
+ return typeof value === "object" && value !== null && !Array.isArray(value);
3775
+ }
3776
+ /** A slice field that is present. Unknown throws — it is not false or 0 (D393). */
3777
+ function sliceField(slice, field) {
3778
+ const value = slice?.[field];
3779
+ if (typeof value === "boolean" || typeof value === "number" || typeof value === "string") return value;
3780
+ throw new Error(`composed ${field} is unknown — not a stand-in value`);
3781
+ }
3782
+ function composedMethod(answer, readSlice) {
3737
3783
  if (answer.kind === "answer") return async () => answer.value;
3784
+ if (answer.kind === "slice") {
3785
+ const field = answer.field;
3786
+ return async () => sliceField(await readSlice(), field);
3787
+ }
3738
3788
  return async () => {
3739
3789
  throw new Error(answer.reason);
3740
3790
  };
@@ -3852,7 +3902,11 @@ var GraftHost = class {
3852
3902
  return ctx;
3853
3903
  }
3854
3904
  providerFor(deviceId, def) {
3855
- const answers = Object.entries(def.composedMethods ?? {}).map(([name, answer]) => [name, composedMethod(answer)]);
3905
+ const readSlice = async () => {
3906
+ const slice = await this.readMerged(deviceId, def.name);
3907
+ return isSliceRecord(slice) ? slice : null;
3908
+ };
3909
+ const answers = Object.entries(def.composedMethods ?? {}).map(([name, answer]) => [name, composedMethod(answer, readSlice)]);
3856
3910
  const withStatus = def.status === void 0 && def.runtimeState === void 0 ? [] : [["getStatus", async () => this.readMerged(deviceId, def.name)]];
3857
3911
  return Object.fromEntries([...answers, ...withStatus]);
3858
3912
  }
@@ -3929,7 +3983,7 @@ function entriesOf(request) {
3929
3983
  }))];
3930
3984
  }
3931
3985
  function valueAtPath(slice, path) {
3932
- return path.split(".").reduce((node, segment) => isRecord$2(node) ? node[segment] : void 0, slice);
3986
+ return path.split(".").reduce((node, segment) => isRecord$3(node) ? node[segment] : void 0, slice);
3933
3987
  }
3934
3988
  function onlineOf(slice) {
3935
3989
  const online = slice["online"];
@@ -4596,12 +4650,12 @@ var DECLARED_INTEGRATION_NAME_UNUSED = "Blocks";
4596
4650
  var PULSE_HISTORY_MAX_POINTS = 5e3;
4597
4651
  /** The owner-only shadow payload is not in the typed catalog: narrowed at the boundary, like `device.state-changed`. */
4598
4652
  function parseNativeShadowChanged(data) {
4599
- if (!isRecord$2(data)) return null;
4653
+ if (!isRecord$3(data)) return null;
4600
4654
  const deviceId = data["deviceId"];
4601
4655
  const capName = data["capName"];
4602
4656
  const native = data["native"];
4603
4657
  if (typeof deviceId !== "number" || typeof capName !== "string") return null;
4604
- if (!isRecord$2(native)) return null;
4658
+ if (!isRecord$3(native)) return null;
4605
4659
  return {
4606
4660
  deviceId,
4607
4661
  capName,
@@ -156,6 +156,8 @@ export declare class CompositionRuntime {
156
156
  /** One info line per field per direction, never one per pass. */
157
157
  private logReleaseTransitions;
158
158
  private seedCap;
159
+ /** An omitted optional reading must leave the slice, not keep the previous number (D944). */
160
+ private clearsOmitted;
159
161
  private patchCap;
160
162
  /**
161
163
  * After a failed write nothing is known about what landed, and after a
@@ -3,7 +3,7 @@ Object.defineProperties(exports, {
3
3
  [Symbol.toStringTag]: { value: "Module" }
4
4
  });
5
5
  require("../../chunk-Cek0wNdY.js");
6
- const require_dist = require("../../dist-k--OhKkO.js");
6
+ const require_dist = require("../../dist-D-d_UWL4.js");
7
7
  const require_formatter = require("../../formatter-xbxeV4GD.js");
8
8
  //#region src/builtins/console-logging/console-destination.ts
9
9
  var LEVEL_RANK = {
@@ -1,4 +1,4 @@
1
- import { Ln as logDestinationCapability, ni as BaseAddon } from "../../dist-BT_THdzJ.mjs";
1
+ import { Ln as logDestinationCapability, ni as BaseAddon } from "../../dist-HBue971z.mjs";
2
2
  import { t as formatLogLine } from "../../formatter-DkYZ4LXp.mjs";
3
3
  //#region src/builtins/console-logging/console-destination.ts
4
4
  var LEVEL_RANK = {
@@ -13,11 +13,13 @@
13
13
  * Devices are keyed by `{addonId, stableId}` — never a numeric device id,
14
14
  * which is this node's allocation and not the composition's identity.
15
15
  */
16
- import { type CompositionSourceDescription, type CompositionSourceRef, type CompositionTargetDescription, type DeviceType } from "@camstack/types";
16
+ import { type CompositionSourceDescription, type CompositionSourceRef, type CompositionTargetDescription, type DeviceType, type ReadingQuantity } from "@camstack/types";
17
17
  export interface SourceRowView {
18
18
  readonly id: number;
19
19
  readonly stableId: string;
20
20
  readonly type: DeviceType;
21
+ /** The device's stored quantity, when it declares one (D944 §4). */
22
+ readonly quantity?: ReadingQuantity;
21
23
  }
22
24
  /** One `getBindings` entry: the cap, and the addon serving it natively. */
23
25
  export interface BoundCapView {