@camstack/system 1.2.485 → 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 (83) hide show
  1. package/dist/{agent-https-_EXvi6F8.mjs → agent-https-C4PLR74Z.mjs} +1 -1
  2. package/dist/{agent-https-DBP7P-ee.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 +59 -13
  18. package/dist/builtins/composer/composer.addon.mjs +59 -13
  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.js +2 -2
  26. package/dist/builtins/device-history/device-history.addon.mjs +2 -2
  27. package/dist/builtins/device-manager/device-manager.addon.js +1 -1
  28. package/dist/builtins/device-manager/device-manager.addon.mjs +1 -1
  29. package/dist/builtins/hub-forwarder/index.js +1 -1
  30. package/dist/builtins/hub-forwarder/index.mjs +1 -1
  31. package/dist/builtins/keychain/index.js +3 -3
  32. package/dist/builtins/keychain/index.mjs +3 -3
  33. package/dist/builtins/liveness-monitor/liveness-monitor.addon.js +1 -1
  34. package/dist/builtins/liveness-monitor/liveness-monitor.addon.mjs +1 -1
  35. package/dist/builtins/local-auth/local-auth.addon.js +2 -2
  36. package/dist/builtins/local-auth/local-auth.addon.mjs +2 -2
  37. package/dist/builtins/local-network/local-network.addon.js +2 -2
  38. package/dist/builtins/local-network/local-network.addon.mjs +2 -2
  39. package/dist/builtins/loki-logging/index.js +1 -1
  40. package/dist/builtins/loki-logging/index.mjs +1 -1
  41. package/dist/builtins/native-metrics/native-metrics.addon.js +1 -1
  42. package/dist/builtins/native-metrics/native-metrics.addon.mjs +1 -1
  43. package/dist/builtins/platform-probe/index.js +1 -1
  44. package/dist/builtins/platform-probe/index.mjs +1 -1
  45. package/dist/builtins/record-entries/index.js +1 -1
  46. package/dist/builtins/record-entries/index.mjs +1 -1
  47. package/dist/builtins/remote-access-orchestrator/remote-access-orchestrator.addon.js +1 -1
  48. package/dist/builtins/remote-access-orchestrator/remote-access-orchestrator.addon.mjs +1 -1
  49. package/dist/builtins/snapshot/index.js +1 -1
  50. package/dist/builtins/snapshot/index.mjs +1 -1
  51. package/dist/builtins/sqlite-storage/filesystem-storage.addon.js +1 -1
  52. package/dist/builtins/sqlite-storage/filesystem-storage.addon.mjs +1 -1
  53. package/dist/builtins/sqlite-storage/index.js +1 -1
  54. package/dist/builtins/sqlite-storage/index.mjs +1 -1
  55. package/dist/builtins/sqlite-storage/sqlite-settings.addon.js +2 -2
  56. package/dist/builtins/sqlite-storage/sqlite-settings.addon.mjs +2 -2
  57. package/dist/builtins/storage-orchestrator/storage-orchestrator.addon.js +1 -1
  58. package/dist/builtins/storage-orchestrator/storage-orchestrator.addon.mjs +1 -1
  59. package/dist/builtins/system-config/system-config.addon.js +3 -3
  60. package/dist/builtins/system-config/system-config.addon.mjs +3 -3
  61. package/dist/builtins/winston-logging/index.js +1 -1
  62. package/dist/builtins/winston-logging/index.mjs +1 -1
  63. package/dist/{composition-sources-BSQneZV9.js → composition-sources-CN8K2Q91.js} +4 -2
  64. package/dist/{composition-sources-BnZpIA8u.mjs → composition-sources-IxiUkrz1.mjs} +4 -2
  65. package/dist/{constants-CQfTeCnB.js → constants-1S7BBGMb.js} +1 -1
  66. package/dist/{constants-7D7xjw0h.mjs → constants-DLyGFHZ2.mjs} +1 -1
  67. package/dist/{device-ca-Bzd6UO_c.mjs → device-ca-Cbf7_R9t.mjs} +1 -1
  68. package/dist/{device-ca-D_4dI5gv.js → device-ca-DoOFG0nm.js} +1 -1
  69. package/dist/{dist-xCNJAQMh.js → dist-D-d_UWL4.js} +760 -19
  70. package/dist/{dist-Df6c0RX_.mjs → dist-HBue971z.mjs} +760 -19
  71. package/dist/file-host-worker.js +1 -1
  72. package/dist/file-host-worker.mjs +1 -1
  73. package/dist/{hub-mdns-ciao-D7GMnEz0.mjs → hub-mdns-ciao-CuEWb6gB.mjs} +2 -2
  74. package/dist/{hub-mdns-ciao-DRfmLR_Z.js → hub-mdns-ciao-dcacrwqd.js} +2 -2
  75. package/dist/index.js +7 -7
  76. package/dist/index.mjs +7 -7
  77. package/dist/{restore-archive-Co70oRya.mjs → restore-archive-BGBRadFJ.mjs} +1 -1
  78. package/dist/{restore-archive-DA7N6ZZA.js → restore-archive-DHdXrKwG.js} +1 -1
  79. package/dist/{retention-DfCW-dZS.mjs → retention-8uqDWll8.mjs} +1 -1
  80. package/dist/{retention-DNDOPW7Z.js → retention-ChgrkTfz.js} +1 -1
  81. package/dist/{wal-maintenance-CA0L6WZ9.js → wal-maintenance-BOT7wWvH.js} +0 -0
  82. package/dist/{wal-maintenance-71-j48Ci.mjs → wal-maintenance-DubGwqz2.mjs} +0 -0
  83. package/package.json +1 -1
@@ -1,4 +1,4 @@
1
- import { Ji as defineRecordKinds } from "./dist-Df6c0RX_.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-xCNJAQMh.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-xCNJAQMh.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, ja as EventCategory, ni as BaseAddon, ti as errMsg } from "../../dist-Df6c0RX_.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-xCNJAQMh.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 { ja as EventCategory, ni as BaseAddon, ti as errMsg, yt as addonWidgetsCapability } from "../../dist-Df6c0RX_.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-xCNJAQMh.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, ja as EventCategory, ni as BaseAddon, ti as errMsg, xt as alertEpisodePayload, yn as isAlertEpisodeOpen } from "../../dist-Df6c0RX_.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-xCNJAQMh.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, ja as EventCategory, ni as BaseAddon, ra as isEvent, rr as ptzAutotrackCapability, ti as errMsg } from "../../dist-Df6c0RX_.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-xCNJAQMh.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-DA7N6ZZA.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 { Ea as toNodeId, Or as storageOccupancyCapability, Tt as backupCapability, Vn as mayWriteToLocation, fa as nodePin, ja as EventCategory, ni as BaseAddon } from "../../dist-Df6c0RX_.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-Co70oRya.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-xCNJAQMh.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-Df6c0RX_.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-xCNJAQMh.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, ei as DeviceType, ja as EventCategory, ni as BaseAddon, qt as declarationOwnerNodeId, ta as hydrateSchema, ti as errMsg } from "../../dist-Df6c0RX_.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-xCNJAQMh.js");
7
- const require_composition_sources = require("../../composition-sources-BSQneZV9.js");
8
- const require_retention = require("../../retention-DNDOPW7Z.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) {
@@ -1295,7 +1313,9 @@ function writable(record) {
1295
1313
  switch (record.plan.unavailable) {
1296
1314
  case "null": return null;
1297
1315
  case "unknown": return "unknown";
1298
- default: return;
1316
+ case "omit":
1317
+ case "offline":
1318
+ case "release": return;
1299
1319
  }
1300
1320
  }
1301
1321
  function errorText(error) {
@@ -2018,7 +2038,16 @@ var CompositionRuntime = class {
2018
2038
  this.seeded = new Set([...this.seeded, cap]);
2019
2039
  this.markWritten(cap, entries);
2020
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
+ }
2021
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
+ }
2022
2051
  const entries = this.entriesFor(cap, this.recordsOf(cap).filter((r) => touched.has(fieldKey(r.plan)) && (!r.hasWritten || writable(r) !== r.written)));
2023
2052
  if (entries.length === 0) return;
2024
2053
  if (this.write(cap, "patch", entries)) this.markWritten(cap, entries);
@@ -3746,8 +3775,21 @@ var NodeDeadlineTimer = class {
3746
3775
  function unanswered(def) {
3747
3776
  return Object.entries(def.methods).filter(([name, m]) => m.systemOnly !== true && def.composedMethods?.[name] === void 0).map(([name]) => name);
3748
3777
  }
3749
- 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) {
3750
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
+ }
3751
3793
  return async () => {
3752
3794
  throw new Error(answer.reason);
3753
3795
  };
@@ -3865,7 +3907,11 @@ var GraftHost = class {
3865
3907
  return ctx;
3866
3908
  }
3867
3909
  providerFor(deviceId, def) {
3868
- 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)]);
3869
3915
  const withStatus = def.status === void 0 && def.runtimeState === void 0 ? [] : [["getStatus", async () => this.readMerged(deviceId, def.name)]];
3870
3916
  return Object.fromEntries([...answers, ...withStatus]);
3871
3917
  }
@@ -3942,7 +3988,7 @@ function entriesOf(request) {
3942
3988
  }))];
3943
3989
  }
3944
3990
  function valueAtPath(slice, path) {
3945
- 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);
3946
3992
  }
3947
3993
  function onlineOf(slice) {
3948
3994
  const online = slice["online"];
@@ -4609,12 +4655,12 @@ var DECLARED_INTEGRATION_NAME_UNUSED = "Blocks";
4609
4655
  var PULSE_HISTORY_MAX_POINTS = 5e3;
4610
4656
  /** The owner-only shadow payload is not in the typed catalog: narrowed at the boundary, like `device.state-changed`. */
4611
4657
  function parseNativeShadowChanged(data) {
4612
- if (!isRecord$2(data)) return null;
4658
+ if (!isRecord$3(data)) return null;
4613
4659
  const deviceId = data["deviceId"];
4614
4660
  const capName = data["capName"];
4615
4661
  const native = data["native"];
4616
4662
  if (typeof deviceId !== "number" || typeof capName !== "string") return null;
4617
- if (!isRecord$2(native)) return null;
4663
+ if (!isRecord$3(native)) return null;
4618
4664
  return {
4619
4665
  deviceId,
4620
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, ja as EventCategory, ni as BaseAddon, qr as compositionSliceKey, r as ALL_CAPABILITY_DEFINITIONS, ti as errMsg } from "../../dist-Df6c0RX_.mjs";
2
- import { n as normalizedNativeOwner } from "../../composition-sources-BnZpIA8u.mjs";
3
- import { i as DAY_MS, m as capSeriesKey, t as DEFAULT_RETENTION } from "../../retention-DfCW-dZS.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) {
@@ -1290,7 +1308,9 @@ function writable(record) {
1290
1308
  switch (record.plan.unavailable) {
1291
1309
  case "null": return null;
1292
1310
  case "unknown": return "unknown";
1293
- default: return;
1311
+ case "omit":
1312
+ case "offline":
1313
+ case "release": return;
1294
1314
  }
1295
1315
  }
1296
1316
  function errorText(error) {
@@ -2013,7 +2033,16 @@ var CompositionRuntime = class {
2013
2033
  this.seeded = new Set([...this.seeded, cap]);
2014
2034
  this.markWritten(cap, entries);
2015
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
+ }
2016
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
+ }
2017
2046
  const entries = this.entriesFor(cap, this.recordsOf(cap).filter((r) => touched.has(fieldKey(r.plan)) && (!r.hasWritten || writable(r) !== r.written)));
2018
2047
  if (entries.length === 0) return;
2019
2048
  if (this.write(cap, "patch", entries)) this.markWritten(cap, entries);
@@ -3741,8 +3770,21 @@ var NodeDeadlineTimer = class {
3741
3770
  function unanswered(def) {
3742
3771
  return Object.entries(def.methods).filter(([name, m]) => m.systemOnly !== true && def.composedMethods?.[name] === void 0).map(([name]) => name);
3743
3772
  }
3744
- 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) {
3745
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
+ }
3746
3788
  return async () => {
3747
3789
  throw new Error(answer.reason);
3748
3790
  };
@@ -3860,7 +3902,11 @@ var GraftHost = class {
3860
3902
  return ctx;
3861
3903
  }
3862
3904
  providerFor(deviceId, def) {
3863
- 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)]);
3864
3910
  const withStatus = def.status === void 0 && def.runtimeState === void 0 ? [] : [["getStatus", async () => this.readMerged(deviceId, def.name)]];
3865
3911
  return Object.fromEntries([...answers, ...withStatus]);
3866
3912
  }
@@ -3937,7 +3983,7 @@ function entriesOf(request) {
3937
3983
  }))];
3938
3984
  }
3939
3985
  function valueAtPath(slice, path) {
3940
- 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);
3941
3987
  }
3942
3988
  function onlineOf(slice) {
3943
3989
  const online = slice["online"];
@@ -4604,12 +4650,12 @@ var DECLARED_INTEGRATION_NAME_UNUSED = "Blocks";
4604
4650
  var PULSE_HISTORY_MAX_POINTS = 5e3;
4605
4651
  /** The owner-only shadow payload is not in the typed catalog: narrowed at the boundary, like `device.state-changed`. */
4606
4652
  function parseNativeShadowChanged(data) {
4607
- if (!isRecord$2(data)) return null;
4653
+ if (!isRecord$3(data)) return null;
4608
4654
  const deviceId = data["deviceId"];
4609
4655
  const capName = data["capName"];
4610
4656
  const native = data["native"];
4611
4657
  if (typeof deviceId !== "number" || typeof capName !== "string") return null;
4612
- if (!isRecord$2(native)) return null;
4658
+ if (!isRecord$3(native)) return null;
4613
4659
  return {
4614
4660
  deviceId,
4615
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-xCNJAQMh.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-Df6c0RX_.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 {
@@ -1,8 +1,8 @@
1
1
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
2
  const require_chunk = require("../../chunk-Cek0wNdY.js");
3
- const require_dist = require("../../dist-xCNJAQMh.js");
3
+ const require_dist = require("../../dist-D-d_UWL4.js");
4
4
  const require_read_all_rows$1 = require("../../read-all-rows-CVoO1ONM.js");
5
- const require_composition_sources = require("../../composition-sources-BSQneZV9.js");
5
+ const require_composition_sources = require("../../composition-sources-CN8K2Q91.js");
6
6
  const require_prefix_range = require("../../prefix-range-D_KueXbQ.js");
7
7
  const require_prefix_walk = require("../../prefix-walk-Dv6MLZlM.js");
8
8
  let zod = require("zod");
@@ -1933,6 +1933,16 @@ function refuseIfChanged(deps, blockId, expectedUpdatedAt) {
1933
1933
  function existingTarget(composition) {
1934
1934
  return composition.target.kind === "existing" ? composition.target.device : null;
1935
1935
  }
1936
+ function helperMemberDeviceIds(composition, sources) {
1937
+ const helper = composition.helper;
1938
+ if (helper === void 0) return [];
1939
+ const ids = [];
1940
+ for (const member of helper.members) {
1941
+ const found = sources.get(require_dist.compositionSourceKey(member.source));
1942
+ if (found?.kind === "found") ids.push(found.deviceId);
1943
+ }
1944
+ return ids;
1945
+ }
1936
1946
  async function validateAgainstStore(deps, composition, blockId) {
1937
1947
  if (!deps.store.isLoaded()) throw new Error(`${NOT_LOADED_REASON} — a composition cannot be judged against the stored ones until it has; retry shortly`);
1938
1948
  const self = blockId === null ? null : require_dist.composedDeviceRef(blockId);
@@ -1942,29 +1952,37 @@ async function validateAgainstStore(deps, composition, blockId) {
1942
1952
  const blocks = deps.store.list();
1943
1953
  const read = await deps.describe(refs, [...target === null ? [] : [target], ...storedCustomizationTargets(blocks)]);
1944
1954
  const stored = storedPeers(blocks, read.targets, deps.lookupCap, blockId);
1945
- return require_dist.validateComposition(composition, {
1946
- lookupCap: deps.lookupCap,
1947
- sources: read.sources,
1948
- self,
1949
- blockId,
1950
- target: target === null ? null : read.targets.get(require_dist.compositionSourceKey(target)) ?? {
1951
- kind: "unreadable",
1952
- error: "it was not read"
1953
- },
1954
- peers: stored.peers,
1955
- unreadTargets: stored.unread
1956
- });
1955
+ return {
1956
+ validation: require_dist.validateComposition(composition, {
1957
+ lookupCap: deps.lookupCap,
1958
+ sources: read.sources,
1959
+ self,
1960
+ blockId,
1961
+ target: target === null ? null : read.targets.get(require_dist.compositionSourceKey(target)) ?? {
1962
+ kind: "unreadable",
1963
+ error: "it was not read"
1964
+ },
1965
+ peers: stored.peers,
1966
+ unreadTargets: stored.unread
1967
+ }),
1968
+ memberDeviceIds: helperMemberDeviceIds(composition, read.sources)
1969
+ };
1957
1970
  }
1958
1971
  function describeProblems(validation) {
1959
1972
  return validation.problems.map((p) => `${p.path} [${p.code}]: ${p.message}`);
1960
1973
  }
1961
- function refuse(deps, subject, validation) {
1974
+ function refuse(deps, subject, validation, memberDeviceIds) {
1962
1975
  const problems = describeProblems(validation);
1963
- deps.logger.warn("composition save refused", { meta: {
1976
+ const meta = {
1964
1977
  name: subject.name,
1965
1978
  blockId: subject.blockId,
1966
1979
  problems
1967
- } });
1980
+ };
1981
+ if (memberDeviceIds.length === 0) deps.logger.warn("composition save refused", { meta });
1982
+ else for (const deviceId of memberDeviceIds) deps.logger.warn("composition save refused", {
1983
+ tags: { deviceId },
1984
+ meta
1985
+ });
1968
1986
  throw new Error(`core-blocks: the composition "${subject.name}" was refused — ${problems.join("; ")}`);
1969
1987
  }
1970
1988
  async function readStates(deps, blockIds) {
@@ -2109,11 +2127,11 @@ function buildCompositionApi(deps) {
2109
2127
  return {
2110
2128
  createComposition: ({ block, caller }) => serialized(async () => {
2111
2129
  const name = await nameOnCreate(deps, block);
2112
- const validation = await validateAgainstStore(deps, block.composition, null);
2113
- if (!validation.ok && require_dist.problemsBlockSave(validation.problems)) refuse(deps, {
2130
+ const judged = await validateAgainstStore(deps, block.composition, null);
2131
+ if (!judged.validation.ok && require_dist.problemsBlockSave(judged.validation.problems)) refuse(deps, {
2114
2132
  name,
2115
2133
  blockId: null
2116
- }, validation);
2134
+ }, judged.validation, judged.memberDeviceIds);
2117
2135
  const created = await deps.store.createComposition({
2118
2136
  ...block,
2119
2137
  name
@@ -2130,11 +2148,11 @@ function buildCompositionApi(deps) {
2130
2148
  refuseIfChanged(deps, blockId, expectedUpdatedAt);
2131
2149
  await refuseRetarget(deps, blockId, block);
2132
2150
  if (block.composition !== void 0) {
2133
- const validation = await validateAgainstStore(deps, block.composition, blockId);
2134
- if (!validation.ok && require_dist.problemsBlockSave(validation.problems)) refuse(deps, {
2151
+ const judged = await validateAgainstStore(deps, block.composition, blockId);
2152
+ if (!judged.validation.ok && require_dist.problemsBlockSave(judged.validation.problems)) refuse(deps, {
2135
2153
  name: block.name ?? blockId,
2136
2154
  blockId
2137
- }, validation);
2155
+ }, judged.validation, judged.memberDeviceIds);
2138
2156
  }
2139
2157
  const updated = await deps.store.updateComposition(blockId, block);
2140
2158
  deps.logger.info("composition updated", { meta: {
@@ -2212,7 +2230,7 @@ function buildCompositionApi(deps) {
2212
2230
  }
2213
2231
  };
2214
2232
  },
2215
- validateComposition: async ({ composition, blockId }) => validateAgainstStore(deps, composition, blockId ?? null),
2233
+ validateComposition: async ({ composition, blockId }) => (await validateAgainstStore(deps, composition, blockId ?? null)).validation,
2216
2234
  listComposableCaps: async ({ deviceType }) => ({ caps: [...require_dist.describeComposableCaps(deps.capabilityDefinitions, deviceType)] })
2217
2235
  };
2218
2236
  }
@@ -2637,10 +2655,17 @@ var CoreBlocksAddon = class extends require_dist.BaseAddon {
2637
2655
  return buildCompositionApi({
2638
2656
  store: this.requireStore(),
2639
2657
  describe: (sources, targets) => require_composition_sources.describeCompositionSources({
2640
- listByAddon: async (addonId) => requireApi().deviceManager.listAll.query({
2641
- addonId,
2642
- projection: "slim"
2643
- }),
2658
+ listByAddon: async (addonId) => {
2659
+ return (await requireApi().deviceManager.listAll.query({
2660
+ addonId,
2661
+ projection: "slim"
2662
+ })).map((row) => ({
2663
+ id: row.id,
2664
+ stableId: row.stableId,
2665
+ type: row.type,
2666
+ ...row.sourceInfo?.quantity === void 0 ? {} : { quantity: row.sourceInfo.quantity }
2667
+ }));
2668
+ },
2644
2669
  bindings: async (deviceId) => (await requireApi().deviceManager.getBindings.query({ deviceId })).entries
2645
2670
  }, sources, targets),
2646
2671
  lookupCap: require_dist.buildCapabilityLookup(require_dist.ALL_CAPABILITY_DEFINITIONS),