@camstack/system 1.2.316 → 1.2.318

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 (87) hide show
  1. package/dist/addon-runner.js +1 -1
  2. package/dist/addon-runner.mjs +1 -1
  3. package/dist/auth/auth-manager.d.ts +11 -0
  4. package/dist/builtins/addon-pages-aggregator/addon-pages-aggregator.addon.js +1 -1
  5. package/dist/builtins/addon-pages-aggregator/addon-pages-aggregator.addon.mjs +1 -1
  6. package/dist/builtins/addon-widgets-aggregator/addon-widgets-aggregator.addon.js +1 -1
  7. package/dist/builtins/addon-widgets-aggregator/addon-widgets-aggregator.addon.mjs +1 -1
  8. package/dist/builtins/alerts/alerts.addon.js +1 -1
  9. package/dist/builtins/alerts/alerts.addon.mjs +1 -1
  10. package/dist/builtins/autotrack/index.js +1 -1
  11. package/dist/builtins/autotrack/index.mjs +1 -1
  12. package/dist/builtins/backup-orchestrator/backup-orchestrator.addon.js +1 -1
  13. package/dist/builtins/backup-orchestrator/backup-orchestrator.addon.mjs +1 -1
  14. package/dist/builtins/camera-grid/index.js +1 -1
  15. package/dist/builtins/camera-grid/index.mjs +1 -1
  16. package/dist/builtins/composer/composer.addon.js +347 -181
  17. package/dist/builtins/composer/composer.addon.mjs +347 -181
  18. package/dist/builtins/composer/composition-evaluation.d.ts +37 -0
  19. package/dist/builtins/composer/composition-runtime.d.ts +11 -52
  20. package/dist/builtins/composer/composition-target.d.ts +50 -0
  21. package/dist/builtins/composer/existing-target.d.ts +19 -1
  22. package/dist/builtins/composer/own-field-reads.d.ts +19 -0
  23. package/dist/builtins/console-logging/index.js +1 -1
  24. package/dist/builtins/console-logging/index.mjs +1 -1
  25. package/dist/builtins/core-blocks/core-blocks.addon.js +2 -2
  26. package/dist/builtins/core-blocks/core-blocks.addon.mjs +2 -2
  27. package/dist/builtins/device-manager/device-manager.addon.js +265 -29
  28. package/dist/builtins/device-manager/device-manager.addon.mjs +265 -29
  29. package/dist/builtins/device-manager/device-provider-context.d.ts +6 -0
  30. package/dist/builtins/device-manager/device-source-activation.d.ts +26 -1
  31. package/dist/builtins/device-manager/device-state-mirror.d.ts +41 -9
  32. package/dist/builtins/device-manager/mirror-row-writer.d.ts +59 -1
  33. package/dist/builtins/doorbell/binding-mirror.d.ts +45 -81
  34. package/dist/builtins/doorbell/doorbell-extension-slot.d.ts +4 -3
  35. package/dist/builtins/doorbell/virtual-doorbell.addon.d.ts +53 -11
  36. package/dist/builtins/doorbell/virtual-doorbell.addon.js +207 -82
  37. package/dist/builtins/doorbell/virtual-doorbell.addon.mjs +207 -82
  38. package/dist/builtins/hub-forwarder/index.js +1 -1
  39. package/dist/builtins/hub-forwarder/index.mjs +1 -1
  40. package/dist/builtins/liveness-monitor/liveness-monitor.addon.js +1 -1
  41. package/dist/builtins/liveness-monitor/liveness-monitor.addon.mjs +1 -1
  42. package/dist/builtins/local-auth/local-auth.addon.js +47 -3
  43. package/dist/builtins/local-auth/local-auth.addon.mjs +46 -4
  44. package/dist/builtins/local-network/local-network.addon.js +1 -1
  45. package/dist/builtins/local-network/local-network.addon.mjs +1 -1
  46. package/dist/builtins/loki-logging/index.js +1 -1
  47. package/dist/builtins/loki-logging/index.mjs +1 -1
  48. package/dist/builtins/native-metrics/native-metrics.addon.js +1 -1
  49. package/dist/builtins/native-metrics/native-metrics.addon.mjs +1 -1
  50. package/dist/builtins/platform-probe/index.js +1 -1
  51. package/dist/builtins/platform-probe/index.mjs +1 -1
  52. package/dist/builtins/remote-access-orchestrator/remote-access-orchestrator.addon.js +1 -1
  53. package/dist/builtins/remote-access-orchestrator/remote-access-orchestrator.addon.mjs +1 -1
  54. package/dist/builtins/snapshot/index.js +1 -1
  55. package/dist/builtins/snapshot/index.mjs +1 -1
  56. package/dist/builtins/sqlite-storage/filesystem-storage.addon.js +1 -1
  57. package/dist/builtins/sqlite-storage/filesystem-storage.addon.mjs +1 -1
  58. package/dist/builtins/sqlite-storage/sqlite-settings.addon.js +0 -0
  59. package/dist/builtins/sqlite-storage/sqlite-settings.addon.mjs +0 -0
  60. package/dist/builtins/storage-orchestrator/storage-orchestrator.addon.js +1 -1
  61. package/dist/builtins/storage-orchestrator/storage-orchestrator.addon.mjs +1 -1
  62. package/dist/builtins/system-config/system-config.addon.js +4 -4
  63. package/dist/builtins/system-config/system-config.addon.mjs +4 -4
  64. package/dist/builtins/winston-logging/index.js +1 -1
  65. package/dist/builtins/winston-logging/index.mjs +1 -1
  66. package/dist/{child-cap-dispatch-AAltfBUH.mjs → child-cap-dispatch-C2VINHu1.mjs} +70 -18
  67. package/dist/{child-cap-dispatch-DzcUd_ct.js → child-cap-dispatch-C8uts1P4.js} +70 -18
  68. package/dist/{composition-sources-BwE1POnF.js → composition-sources-BjRPhWtU.js} +1 -1
  69. package/dist/{composition-sources-fUyF4z39.mjs → composition-sources-Cg2MP-qf.mjs} +1 -1
  70. package/dist/{dist-BPvku43i.mjs → dist-CQ9vXSUh.mjs} +220 -8
  71. package/dist/{dist-RAl10EfG.js → dist-Dcy0gVHu.js} +220 -8
  72. package/dist/index.js +739 -350
  73. package/dist/index.mjs +737 -352
  74. package/dist/kernel/bootstrap-config.d.ts +8 -0
  75. package/dist/kernel/capability-registry.d.ts +30 -0
  76. package/dist/kernel/config-manager.d.ts +75 -129
  77. package/dist/kernel/index.d.ts +5 -2
  78. package/dist/kernel/moleculer/runtime-state-load.d.ts +19 -0
  79. package/dist/kernel/settings-door-view.d.ts +24 -1
  80. package/dist/kernel/settings-read-error.d.ts +37 -0
  81. package/dist/kernel/settings-view-types.d.ts +105 -0
  82. package/dist/kernel/store-settings-view.d.ts +17 -0
  83. package/dist/kernel/system-settings-mirror.d.ts +34 -0
  84. package/dist/kernel/system-settings-policy.d.ts +47 -0
  85. package/dist/{retired-settings-keys-DqVWSrVw.mjs → retired-settings-keys-DNIbyfTR.mjs} +1 -1
  86. package/dist/{retired-settings-keys-D3rGTGq5.js → retired-settings-keys-pzlrLUbA.js} +1 -1
  87. package/package.json +1 -1
@@ -701,7 +701,7 @@ var EventCategory = /* @__PURE__ */ function(EventCategory) {
701
701
  return EventCategory;
702
702
  }({});
703
703
  //#endregion
704
- //#region ../types/dist/sleep-E6eD4yQS.mjs
704
+ //#region ../types/dist/sleep-DlrgY4Qb.mjs
705
705
  /**
706
706
  * The audio chunk plane's byte format, and the ONE expansion from a coded
707
707
  * window to float samples (D455).
@@ -3512,7 +3512,7 @@ function errMsg(err) {
3512
3512
  return String(err);
3513
3513
  }
3514
3514
  //#endregion
3515
- //#region ../types/dist/composition-D5BQywfe.mjs
3515
+ //#region ../types/dist/composition-BK-GTFYb.mjs
3516
3516
  var AUDIO_ENCODER_BY_CODEC = {
3517
3517
  opus: "libopus",
3518
3518
  aac: "aac",
@@ -4153,14 +4153,37 @@ function evaluateRose(level, changedAt, debounceMs, call, field, env) {
4153
4153
  field.acceptedEdgeAt = verdict.timestamp;
4154
4154
  return verdict.timestamp;
4155
4155
  }
4156
+ /**
4157
+ * `count(x)`: how many times `x` strictly advanced (D670). It starts on the
4158
+ * first ANSWERED read of `x`:
4159
+ * - an answered `null` ("never happened") primes it with no high-water, so the
4160
+ * next finite value is a real advance and counts 1;
4161
+ * - an answered finite value primes it with that value as the high-water and
4162
+ * no increment — it is history, not an event;
4163
+ * - anything else (a read that did not answer reaches here as neither) does
4164
+ * NOT prime it (D393: unknown is not null).
4165
+ * An unavailable binding never reaches this function at all: the field is
4166
+ * judged unavailable before the expression runs.
4167
+ *
4168
+ * Edge case, accepted: an input that answers `null` and LATER reports a
4169
+ * historical value (a sensor's `lastChangedAt` that was null until its first
4170
+ * report) counts that value once. For the doorbell it cannot happen — its
4171
+ * input is its own `lastPressedAt`, which only advances on a `rose` edge that
4172
+ * also emits the press — but an external input can overcount by one.
4173
+ */
4156
4174
  function evaluateCount(input, call, currentOutput) {
4157
4175
  const currentCount = typeof currentOutput === "number" && Number.isFinite(currentOutput) && currentOutput >= 0 ? currentOutput : 0;
4176
+ if (input === null) {
4177
+ call.primed = true;
4178
+ return currentCount;
4179
+ }
4158
4180
  if (typeof input !== "number" || !Number.isFinite(input)) return currentCount;
4159
- if (call.highWater === null) {
4181
+ if (!call.primed) {
4182
+ call.primed = true;
4160
4183
  call.highWater = input;
4161
4184
  return currentCount;
4162
4185
  }
4163
- if (input <= call.highWater) return currentCount;
4186
+ if (call.highWater !== null && input <= call.highWater) return currentCount;
4164
4187
  call.highWater = input;
4165
4188
  return currentCount + 1;
4166
4189
  }
@@ -4876,7 +4899,8 @@ function evaluateStatefulExpressionCall(invocation, memory, env) {
4876
4899
  case "count": {
4877
4900
  const call = existing?.kind === "count" ? existing : {
4878
4901
  kind: "count",
4879
- highWater: null
4902
+ highWater: null,
4903
+ primed: false
4880
4904
  };
4881
4905
  memory.calls.set(invocation.path, call);
4882
4906
  return evaluateCount(invocation.args[0], call, env.currentOutput);
@@ -14038,6 +14062,34 @@ var DeviceBindingsForDeviceSchema = z.object({
14038
14062
  nativeAddonId: z.string()
14039
14063
  }))
14040
14064
  });
14065
+ /**
14066
+ * The STORED wrapper activation for one `(device, capability)` pair — the row
14067
+ * `setWrapperActive` writes, read back three-way (D675):
14068
+ *
14069
+ * - `value` — the store answered and holds an activation: the bound wrapper's
14070
+ * addon id, or `null`, the operator's explicit "off" marker (D62);
14071
+ * - `missing` — the store answered, its activation map exists, and it holds
14072
+ * nothing for this pair: the operator never activated or deactivated a
14073
+ * wrapper here;
14074
+ * - `failed` — the store could not be read, holds no activation map at all
14075
+ * (an empty or unready snapshot, D44), or holds something that is not an
14076
+ * activation. It carries NO information: a consumer must never read it as
14077
+ * `missing` (D315, D393).
14078
+ *
14079
+ * This is the persisted INPUT, not the derived `getBindings` view — no registry
14080
+ * resolution, no `defaultActive` auto-binding, no cluster native-cap folding.
14081
+ */
14082
+ var WrapperActivationReadSchema = z.discriminatedUnion("kind", [
14083
+ z.object({
14084
+ kind: z.literal("value"),
14085
+ wrapperAddonId: z.string().nullable()
14086
+ }),
14087
+ z.object({ kind: z.literal("missing") }),
14088
+ z.object({
14089
+ kind: z.literal("failed"),
14090
+ error: z.string()
14091
+ })
14092
+ ]);
14041
14093
  var SavedDeviceRowSchema = z.object({
14042
14094
  /** Numeric id reserved at allocateDeviceId time. */
14043
14095
  id: z.number(),
@@ -14836,6 +14888,21 @@ var deviceManagerCapability = {
14836
14888
  auth: "admin"
14837
14889
  }),
14838
14890
  /**
14891
+ * The STORED wrapper activation for one `(device, capName)` pair, three-way
14892
+ * (`value` / `missing` / `failed`, see {@link WrapperActivationReadSchema}).
14893
+ *
14894
+ * The narrow read of the durable authority behind `getBindings`: a
14895
+ * consumer that must know what the operator PERSISTED (virtual-doorbell,
14896
+ * before it drops a press) asks this instead of pulling device-manager's
14897
+ * whole addon store through `addonSettingsRaw.getGlobal` — which answered
14898
+ * `{}` on every isolated-engine hub and so never worked (D675). It reads
14899
+ * ONE row (the activation map, ~1.6 KB), never the ~625 KB store.
14900
+ */
14901
+ getWrapperActivation: method(z.object({
14902
+ deviceId: z.number(),
14903
+ capName: z.string().min(1)
14904
+ }), WrapperActivationReadSchema),
14905
+ /**
14839
14906
  * Return the addon ids that declared a wrapper provider for `capName`.
14840
14907
  * Backs the device-bindings UI's wrapper-picker dropdown. Entries are
14841
14908
  * sourced from `CapabilityRegistry.wrapperProviders`, populated when
@@ -20836,6 +20903,102 @@ var oauthIntegrationCapability = {
20836
20903
  getDescriptor: method(z.void(), OauthIntegrationDescriptorSchema, { auth: "admin" }) }
20837
20904
  };
20838
20905
  /**
20906
+ * What started a camera's onboard motion (D672). `camera` is the camera's own
20907
+ * firmware; `sensor` is a device the operator ATTACHED to it. Absent on the
20908
+ * wire means the camera: only the camera-sensors bridge ever says `sensor`.
20909
+ */
20910
+ var MotionTriggeredBySchema = z.discriminatedUnion("kind", [z.object({ kind: z.literal("camera") }), z.object({
20911
+ kind: z.literal("sensor"),
20912
+ deviceId: z.number().int().positive()
20913
+ })]);
20914
+ Object.freeze({ kind: "camera" });
20915
+ var CameraSensorRefSchema = z.object({
20916
+ addonId: z.string().min(1),
20917
+ stableId: z.string().min(1)
20918
+ });
20919
+ function cameraSensorRefKey(ref) {
20920
+ return `${ref.addonId}/${ref.stableId}`;
20921
+ }
20922
+ /** CS-1 accepts exactly one mode; CS-2 (D673) widens it to confirm / replace. */
20923
+ var CameraSensorsModeSchema = z.enum(["in-addition"]);
20924
+ z.object({
20925
+ mode: CameraSensorsModeSchema,
20926
+ sensors: z.array(CameraSensorRefSchema).min(1).max(8)
20927
+ }).superRefine((value, ctx) => {
20928
+ const seen = /* @__PURE__ */ new Set();
20929
+ value.sensors.forEach((ref, index) => {
20930
+ const key = cameraSensorRefKey(ref);
20931
+ if (seen.has(key)) ctx.addIssue({
20932
+ code: "custom",
20933
+ path: ["sensors", index],
20934
+ message: `duplicate camera sensor ${key}`
20935
+ });
20936
+ seen.add(key);
20937
+ });
20938
+ });
20939
+ var RefFields = {
20940
+ addonId: z.string(),
20941
+ stableId: z.string()
20942
+ };
20943
+ var CameraSensorAttachmentSchema = z.discriminatedUnion("state", [
20944
+ z.object({
20945
+ ...RefFields,
20946
+ state: z.literal("ready"),
20947
+ deviceId: z.number(),
20948
+ name: z.string(),
20949
+ caps: z.array(z.string()).readonly()
20950
+ }),
20951
+ z.object({
20952
+ ...RefFields,
20953
+ state: z.literal("offline"),
20954
+ deviceId: z.number(),
20955
+ name: z.string(),
20956
+ reason: z.enum(["offline", "disabled"])
20957
+ }),
20958
+ z.object({
20959
+ ...RefFields,
20960
+ state: z.literal("missing"),
20961
+ reason: z.string()
20962
+ }),
20963
+ z.object({
20964
+ ...RefFields,
20965
+ state: z.literal("unsupported"),
20966
+ deviceId: z.number(),
20967
+ name: z.string(),
20968
+ reason: z.string()
20969
+ }),
20970
+ z.object({
20971
+ ...RefFields,
20972
+ state: z.literal("unreadable"),
20973
+ reason: z.string()
20974
+ })
20975
+ ]);
20976
+ /**
20977
+ * Why a configured camera forwards NOTHING from its sensors, however ready they
20978
+ * are (D672): it does not list `onboard` in `motionSources` (attaching a sensor
20979
+ * does not add it), or it has no active detection config at all (the bridge
20980
+ * reads the active config). Absent = forwarded, or an older node that does not
20981
+ * say.
20982
+ */
20983
+ var CameraSensorsNotForwardedSchema = z.enum(["onboard-not-listed", "no-active-detection"]);
20984
+ var CameraSensorsStatusSchema = z.discriminatedUnion("state", [
20985
+ z.object({ state: z.literal("not-configured") }),
20986
+ z.object({
20987
+ state: z.literal("unreadable"),
20988
+ reason: z.string()
20989
+ }),
20990
+ z.object({
20991
+ state: z.literal("configured"),
20992
+ mode: CameraSensorsModeSchema,
20993
+ sensors: z.array(CameraSensorAttachmentSchema).readonly(),
20994
+ notForwarded: CameraSensorsNotForwardedSchema.optional()
20995
+ })
20996
+ ]);
20997
+ Object.freeze({
20998
+ state: "unreadable",
20999
+ reason: "camera sensor mappings not loaded"
21000
+ });
21001
+ /**
20839
21002
  * A model choice has a SCOPE, and a scope change has a workflow.
20840
21003
  *
20841
21004
  * ## The two scopes
@@ -21584,6 +21747,12 @@ var MotionEventSchema = z.object({
21584
21747
  /** Populated by B5 (recording playback URL for this event). */
21585
21748
  mediaUrl: z.string().optional(),
21586
21749
  /**
21750
+ * The FIRST trigger of an `onboard` episode, written once at open (D672).
21751
+ * Absent = not recorded (a row written before D672, or an analyzer /
21752
+ * device-activity episode) — never read as "the camera" (D393).
21753
+ */
21754
+ triggeredBy: MotionTriggeredBySchema.optional(),
21755
+ /**
21587
21756
  * One row per motion EPISODE, not one per push (D475). `null` while the
21588
21757
  * episode is still open — a further rising edge extends it in place rather
21589
21758
  * than inserting a new row. Set once, at close, to `lastOnAt - startedAt`
@@ -24793,6 +24962,23 @@ var MotionSourceEnum = z.enum([
24793
24962
  */
24794
24963
  var MotionSourcesSchema = z.array(MotionSourceEnum);
24795
24964
  /**
24965
+ * The operator-facing name of each MOTION source (D672: `onboard` = the
24966
+ * camera's sensors — its own motion plus any sensor attached to it). The wire
24967
+ * value stays `onboard`; only the label changed. `detectionSources: 'onboard'`
24968
+ * ("Camera onboard AI") and the notification source filter keep their labels.
24969
+ */
24970
+ var MOTION_SOURCE_LABELS = {
24971
+ analyzer: "Frame-diff Analyzer (motion addon)",
24972
+ onboard: "Camera sensors",
24973
+ "device-activity": "Device activity (the device says it is working)"
24974
+ };
24975
+ /** The order the motion-source picker offers them in (not the enum's order). */
24976
+ var MOTION_SOURCE_PICKER_ORDER = [
24977
+ "analyzer",
24978
+ "onboard",
24979
+ "device-activity"
24980
+ ];
24981
+ /**
24796
24982
  * Which root detector a camera runs — EXACTLY ONE.
24797
24983
  *
24798
24984
  * Deliberately the SAME vocabulary post-analysis already tags every detection
@@ -25139,7 +25325,14 @@ var RunnerCameraConfigSchema = z.object({
25139
25325
  */
25140
25326
  inferenceDevices: z.array(RunnerInferenceDeviceSchema).readonly().optional()
25141
25327
  });
25142
- motionFpsField.min, motionFpsField.max, motionFpsField.step, motionFpsField.default, detectionFpsField.min, detectionFpsField.max, detectionFpsField.step, detectionFpsField.default, motionCooldownMsField.min, motionCooldownMsField.max, motionCooldownMsField.step, motionCooldownMsField.default, maxSessionHoldMsField.min, maxSessionHoldMsField.max, maxSessionHoldMsField.step, maxSessionHoldMsField.default, audioMotionWindowMsField.min, audioMotionWindowMsField.max, audioMotionWindowMsField.step, audioMotionWindowMsField.default, preRollInferenceFramesField.min, preRollInferenceFramesField.max, preRollInferenceFramesField.step, preRollInferenceFramesField.default, occupancyRecheckSecField.min, occupancyRecheckSecField.max, occupancyRecheckSecField.step, occupancyRecheckSecField.default, occupancyRecheckFramesField.min, occupancyRecheckFramesField.max, occupancyRecheckFramesField.step, occupancyRecheckFramesField.default;
25328
+ MOTION_SOURCE_PICKER_ORDER.map((value) => value === "onboard" ? {
25329
+ value,
25330
+ label: MOTION_SOURCE_LABELS[value],
25331
+ description: "The camera's own motion, plus any sensor attached to it"
25332
+ } : {
25333
+ value,
25334
+ label: MOTION_SOURCE_LABELS[value]
25335
+ }), motionFpsField.min, motionFpsField.max, motionFpsField.step, motionFpsField.default, detectionFpsField.min, detectionFpsField.max, detectionFpsField.step, detectionFpsField.default, motionCooldownMsField.min, motionCooldownMsField.max, motionCooldownMsField.step, motionCooldownMsField.default, maxSessionHoldMsField.min, maxSessionHoldMsField.max, maxSessionHoldMsField.step, maxSessionHoldMsField.default, audioMotionWindowMsField.min, audioMotionWindowMsField.max, audioMotionWindowMsField.step, audioMotionWindowMsField.default, preRollInferenceFramesField.min, preRollInferenceFramesField.max, preRollInferenceFramesField.step, preRollInferenceFramesField.default, occupancyRecheckSecField.min, occupancyRecheckSecField.max, occupancyRecheckSecField.step, occupancyRecheckSecField.default, occupancyRecheckFramesField.min, occupancyRecheckFramesField.max, occupancyRecheckFramesField.step, occupancyRecheckFramesField.default;
25143
25336
  /**
25144
25337
  * Runtime load summary returned by `getLocalLoad`. Used by the orchestrator's
25145
25338
  * load-balancing levels (L2 capacity-based, L3 hardware-aware) to decide
@@ -25935,6 +26128,11 @@ var CameraStatusSchema = z.object({
25935
26128
  */
25936
26129
  switchedOff: z.array(CameraSwitchIdSchema).readonly(),
25937
26130
  /**
26131
+ * The camera's attached sensors (D672). Optional only for a status composed
26132
+ * by an orchestrator older than D672; this orchestrator always sets it.
26133
+ */
26134
+ cameraSensors: CameraSensorsStatusSchema.optional(),
26135
+ /**
25938
26136
  * Stages of the bounded fan-out that were CUT SHORT — a timeout or a
25939
26137
  * rejection — and whose block is therefore `null` because we could not
25940
26138
  * READ it, not because there is nothing there.
@@ -35181,7 +35379,9 @@ var MotionOnMotionChangedDataSchema = z.object({
35181
35379
  detected: z.boolean(),
35182
35380
  timestamp: z.number(),
35183
35381
  source: MotionSourceEnum,
35184
- regions: z.array(MotionRegionSchema).readonly().optional()
35382
+ regions: z.array(MotionRegionSchema).readonly().optional(),
35383
+ /** Who started it (D672). Absent = the camera itself. Only `onboard` carries `sensor`. */
35384
+ triggeredBy: MotionTriggeredBySchema.optional()
35185
35385
  });
35186
35386
  var motionCapability = {
35187
35387
  name: "motion",
@@ -43527,7 +43727,8 @@ function expressionOutcome(source, read, now, stateful) {
43527
43727
  state: "stale",
43528
43728
  value: evaluateCount(null, {
43529
43729
  kind: "count",
43530
- highWater: null
43730
+ highWater: null,
43731
+ primed: false
43531
43732
  }, stateful.currentOutput),
43532
43733
  reason: `${unavailable.reason}; holding the last accumulator value`,
43533
43734
  deadline: null
@@ -48579,6 +48780,12 @@ var METHOD_ACCESS_MAP = Object.freeze({
48579
48780
  addonId: null,
48580
48781
  access: "view"
48581
48782
  },
48783
+ "deviceManager.getWrapperActivation": {
48784
+ capName: "device-manager",
48785
+ capScope: "system",
48786
+ addonId: null,
48787
+ access: "view"
48788
+ },
48582
48789
  "deviceManager.listAll": {
48583
48790
  capName: "device-manager",
48584
48791
  capScope: "system",
@@ -54388,6 +54595,11 @@ Object.freeze({
54388
54595
  form: "single",
54389
54596
  optional: false
54390
54597
  }],
54598
+ "deviceManager.getWrapperActivation": [{
54599
+ name: "deviceId",
54600
+ form: "single",
54601
+ optional: false
54602
+ }],
54391
54603
  "deviceManager.listAll": [{
54392
54604
  name: "deviceIds",
54393
54605
  form: "array",
@@ -701,7 +701,7 @@ var EventCategory = /* @__PURE__ */ function(EventCategory) {
701
701
  return EventCategory;
702
702
  }({});
703
703
  //#endregion
704
- //#region ../types/dist/sleep-E6eD4yQS.mjs
704
+ //#region ../types/dist/sleep-DlrgY4Qb.mjs
705
705
  /**
706
706
  * The audio chunk plane's byte format, and the ONE expansion from a coded
707
707
  * window to float samples (D455).
@@ -3512,7 +3512,7 @@ function errMsg(err) {
3512
3512
  return String(err);
3513
3513
  }
3514
3514
  //#endregion
3515
- //#region ../types/dist/composition-D5BQywfe.mjs
3515
+ //#region ../types/dist/composition-BK-GTFYb.mjs
3516
3516
  var AUDIO_ENCODER_BY_CODEC = {
3517
3517
  opus: "libopus",
3518
3518
  aac: "aac",
@@ -4153,14 +4153,37 @@ function evaluateRose(level, changedAt, debounceMs, call, field, env) {
4153
4153
  field.acceptedEdgeAt = verdict.timestamp;
4154
4154
  return verdict.timestamp;
4155
4155
  }
4156
+ /**
4157
+ * `count(x)`: how many times `x` strictly advanced (D670). It starts on the
4158
+ * first ANSWERED read of `x`:
4159
+ * - an answered `null` ("never happened") primes it with no high-water, so the
4160
+ * next finite value is a real advance and counts 1;
4161
+ * - an answered finite value primes it with that value as the high-water and
4162
+ * no increment — it is history, not an event;
4163
+ * - anything else (a read that did not answer reaches here as neither) does
4164
+ * NOT prime it (D393: unknown is not null).
4165
+ * An unavailable binding never reaches this function at all: the field is
4166
+ * judged unavailable before the expression runs.
4167
+ *
4168
+ * Edge case, accepted: an input that answers `null` and LATER reports a
4169
+ * historical value (a sensor's `lastChangedAt` that was null until its first
4170
+ * report) counts that value once. For the doorbell it cannot happen — its
4171
+ * input is its own `lastPressedAt`, which only advances on a `rose` edge that
4172
+ * also emits the press — but an external input can overcount by one.
4173
+ */
4156
4174
  function evaluateCount(input, call, currentOutput) {
4157
4175
  const currentCount = typeof currentOutput === "number" && Number.isFinite(currentOutput) && currentOutput >= 0 ? currentOutput : 0;
4176
+ if (input === null) {
4177
+ call.primed = true;
4178
+ return currentCount;
4179
+ }
4158
4180
  if (typeof input !== "number" || !Number.isFinite(input)) return currentCount;
4159
- if (call.highWater === null) {
4181
+ if (!call.primed) {
4182
+ call.primed = true;
4160
4183
  call.highWater = input;
4161
4184
  return currentCount;
4162
4185
  }
4163
- if (input <= call.highWater) return currentCount;
4186
+ if (call.highWater !== null && input <= call.highWater) return currentCount;
4164
4187
  call.highWater = input;
4165
4188
  return currentCount + 1;
4166
4189
  }
@@ -4876,7 +4899,8 @@ function evaluateStatefulExpressionCall(invocation, memory, env) {
4876
4899
  case "count": {
4877
4900
  const call = existing?.kind === "count" ? existing : {
4878
4901
  kind: "count",
4879
- highWater: null
4902
+ highWater: null,
4903
+ primed: false
4880
4904
  };
4881
4905
  memory.calls.set(invocation.path, call);
4882
4906
  return evaluateCount(invocation.args[0], call, env.currentOutput);
@@ -14038,6 +14062,34 @@ var DeviceBindingsForDeviceSchema = zod.z.object({
14038
14062
  nativeAddonId: zod.z.string()
14039
14063
  }))
14040
14064
  });
14065
+ /**
14066
+ * The STORED wrapper activation for one `(device, capability)` pair — the row
14067
+ * `setWrapperActive` writes, read back three-way (D675):
14068
+ *
14069
+ * - `value` — the store answered and holds an activation: the bound wrapper's
14070
+ * addon id, or `null`, the operator's explicit "off" marker (D62);
14071
+ * - `missing` — the store answered, its activation map exists, and it holds
14072
+ * nothing for this pair: the operator never activated or deactivated a
14073
+ * wrapper here;
14074
+ * - `failed` — the store could not be read, holds no activation map at all
14075
+ * (an empty or unready snapshot, D44), or holds something that is not an
14076
+ * activation. It carries NO information: a consumer must never read it as
14077
+ * `missing` (D315, D393).
14078
+ *
14079
+ * This is the persisted INPUT, not the derived `getBindings` view — no registry
14080
+ * resolution, no `defaultActive` auto-binding, no cluster native-cap folding.
14081
+ */
14082
+ var WrapperActivationReadSchema = zod.z.discriminatedUnion("kind", [
14083
+ zod.z.object({
14084
+ kind: zod.z.literal("value"),
14085
+ wrapperAddonId: zod.z.string().nullable()
14086
+ }),
14087
+ zod.z.object({ kind: zod.z.literal("missing") }),
14088
+ zod.z.object({
14089
+ kind: zod.z.literal("failed"),
14090
+ error: zod.z.string()
14091
+ })
14092
+ ]);
14041
14093
  var SavedDeviceRowSchema = zod.z.object({
14042
14094
  /** Numeric id reserved at allocateDeviceId time. */
14043
14095
  id: zod.z.number(),
@@ -14836,6 +14888,21 @@ var deviceManagerCapability = {
14836
14888
  auth: "admin"
14837
14889
  }),
14838
14890
  /**
14891
+ * The STORED wrapper activation for one `(device, capName)` pair, three-way
14892
+ * (`value` / `missing` / `failed`, see {@link WrapperActivationReadSchema}).
14893
+ *
14894
+ * The narrow read of the durable authority behind `getBindings`: a
14895
+ * consumer that must know what the operator PERSISTED (virtual-doorbell,
14896
+ * before it drops a press) asks this instead of pulling device-manager's
14897
+ * whole addon store through `addonSettingsRaw.getGlobal` — which answered
14898
+ * `{}` on every isolated-engine hub and so never worked (D675). It reads
14899
+ * ONE row (the activation map, ~1.6 KB), never the ~625 KB store.
14900
+ */
14901
+ getWrapperActivation: method(zod.z.object({
14902
+ deviceId: zod.z.number(),
14903
+ capName: zod.z.string().min(1)
14904
+ }), WrapperActivationReadSchema),
14905
+ /**
14839
14906
  * Return the addon ids that declared a wrapper provider for `capName`.
14840
14907
  * Backs the device-bindings UI's wrapper-picker dropdown. Entries are
14841
14908
  * sourced from `CapabilityRegistry.wrapperProviders`, populated when
@@ -20836,6 +20903,102 @@ var oauthIntegrationCapability = {
20836
20903
  getDescriptor: method(zod.z.void(), OauthIntegrationDescriptorSchema, { auth: "admin" }) }
20837
20904
  };
20838
20905
  /**
20906
+ * What started a camera's onboard motion (D672). `camera` is the camera's own
20907
+ * firmware; `sensor` is a device the operator ATTACHED to it. Absent on the
20908
+ * wire means the camera: only the camera-sensors bridge ever says `sensor`.
20909
+ */
20910
+ var MotionTriggeredBySchema = zod.z.discriminatedUnion("kind", [zod.z.object({ kind: zod.z.literal("camera") }), zod.z.object({
20911
+ kind: zod.z.literal("sensor"),
20912
+ deviceId: zod.z.number().int().positive()
20913
+ })]);
20914
+ Object.freeze({ kind: "camera" });
20915
+ var CameraSensorRefSchema = zod.z.object({
20916
+ addonId: zod.z.string().min(1),
20917
+ stableId: zod.z.string().min(1)
20918
+ });
20919
+ function cameraSensorRefKey(ref) {
20920
+ return `${ref.addonId}/${ref.stableId}`;
20921
+ }
20922
+ /** CS-1 accepts exactly one mode; CS-2 (D673) widens it to confirm / replace. */
20923
+ var CameraSensorsModeSchema = zod.z.enum(["in-addition"]);
20924
+ zod.z.object({
20925
+ mode: CameraSensorsModeSchema,
20926
+ sensors: zod.z.array(CameraSensorRefSchema).min(1).max(8)
20927
+ }).superRefine((value, ctx) => {
20928
+ const seen = /* @__PURE__ */ new Set();
20929
+ value.sensors.forEach((ref, index) => {
20930
+ const key = cameraSensorRefKey(ref);
20931
+ if (seen.has(key)) ctx.addIssue({
20932
+ code: "custom",
20933
+ path: ["sensors", index],
20934
+ message: `duplicate camera sensor ${key}`
20935
+ });
20936
+ seen.add(key);
20937
+ });
20938
+ });
20939
+ var RefFields = {
20940
+ addonId: zod.z.string(),
20941
+ stableId: zod.z.string()
20942
+ };
20943
+ var CameraSensorAttachmentSchema = zod.z.discriminatedUnion("state", [
20944
+ zod.z.object({
20945
+ ...RefFields,
20946
+ state: zod.z.literal("ready"),
20947
+ deviceId: zod.z.number(),
20948
+ name: zod.z.string(),
20949
+ caps: zod.z.array(zod.z.string()).readonly()
20950
+ }),
20951
+ zod.z.object({
20952
+ ...RefFields,
20953
+ state: zod.z.literal("offline"),
20954
+ deviceId: zod.z.number(),
20955
+ name: zod.z.string(),
20956
+ reason: zod.z.enum(["offline", "disabled"])
20957
+ }),
20958
+ zod.z.object({
20959
+ ...RefFields,
20960
+ state: zod.z.literal("missing"),
20961
+ reason: zod.z.string()
20962
+ }),
20963
+ zod.z.object({
20964
+ ...RefFields,
20965
+ state: zod.z.literal("unsupported"),
20966
+ deviceId: zod.z.number(),
20967
+ name: zod.z.string(),
20968
+ reason: zod.z.string()
20969
+ }),
20970
+ zod.z.object({
20971
+ ...RefFields,
20972
+ state: zod.z.literal("unreadable"),
20973
+ reason: zod.z.string()
20974
+ })
20975
+ ]);
20976
+ /**
20977
+ * Why a configured camera forwards NOTHING from its sensors, however ready they
20978
+ * are (D672): it does not list `onboard` in `motionSources` (attaching a sensor
20979
+ * does not add it), or it has no active detection config at all (the bridge
20980
+ * reads the active config). Absent = forwarded, or an older node that does not
20981
+ * say.
20982
+ */
20983
+ var CameraSensorsNotForwardedSchema = zod.z.enum(["onboard-not-listed", "no-active-detection"]);
20984
+ var CameraSensorsStatusSchema = zod.z.discriminatedUnion("state", [
20985
+ zod.z.object({ state: zod.z.literal("not-configured") }),
20986
+ zod.z.object({
20987
+ state: zod.z.literal("unreadable"),
20988
+ reason: zod.z.string()
20989
+ }),
20990
+ zod.z.object({
20991
+ state: zod.z.literal("configured"),
20992
+ mode: CameraSensorsModeSchema,
20993
+ sensors: zod.z.array(CameraSensorAttachmentSchema).readonly(),
20994
+ notForwarded: CameraSensorsNotForwardedSchema.optional()
20995
+ })
20996
+ ]);
20997
+ Object.freeze({
20998
+ state: "unreadable",
20999
+ reason: "camera sensor mappings not loaded"
21000
+ });
21001
+ /**
20839
21002
  * A model choice has a SCOPE, and a scope change has a workflow.
20840
21003
  *
20841
21004
  * ## The two scopes
@@ -21584,6 +21747,12 @@ var MotionEventSchema = zod.z.object({
21584
21747
  /** Populated by B5 (recording playback URL for this event). */
21585
21748
  mediaUrl: zod.z.string().optional(),
21586
21749
  /**
21750
+ * The FIRST trigger of an `onboard` episode, written once at open (D672).
21751
+ * Absent = not recorded (a row written before D672, or an analyzer /
21752
+ * device-activity episode) — never read as "the camera" (D393).
21753
+ */
21754
+ triggeredBy: MotionTriggeredBySchema.optional(),
21755
+ /**
21587
21756
  * One row per motion EPISODE, not one per push (D475). `null` while the
21588
21757
  * episode is still open — a further rising edge extends it in place rather
21589
21758
  * than inserting a new row. Set once, at close, to `lastOnAt - startedAt`
@@ -24793,6 +24962,23 @@ var MotionSourceEnum = zod.z.enum([
24793
24962
  */
24794
24963
  var MotionSourcesSchema = zod.z.array(MotionSourceEnum);
24795
24964
  /**
24965
+ * The operator-facing name of each MOTION source (D672: `onboard` = the
24966
+ * camera's sensors — its own motion plus any sensor attached to it). The wire
24967
+ * value stays `onboard`; only the label changed. `detectionSources: 'onboard'`
24968
+ * ("Camera onboard AI") and the notification source filter keep their labels.
24969
+ */
24970
+ var MOTION_SOURCE_LABELS = {
24971
+ analyzer: "Frame-diff Analyzer (motion addon)",
24972
+ onboard: "Camera sensors",
24973
+ "device-activity": "Device activity (the device says it is working)"
24974
+ };
24975
+ /** The order the motion-source picker offers them in (not the enum's order). */
24976
+ var MOTION_SOURCE_PICKER_ORDER = [
24977
+ "analyzer",
24978
+ "onboard",
24979
+ "device-activity"
24980
+ ];
24981
+ /**
24796
24982
  * Which root detector a camera runs — EXACTLY ONE.
24797
24983
  *
24798
24984
  * Deliberately the SAME vocabulary post-analysis already tags every detection
@@ -25139,7 +25325,14 @@ var RunnerCameraConfigSchema = zod.z.object({
25139
25325
  */
25140
25326
  inferenceDevices: zod.z.array(RunnerInferenceDeviceSchema).readonly().optional()
25141
25327
  });
25142
- motionFpsField.min, motionFpsField.max, motionFpsField.step, motionFpsField.default, detectionFpsField.min, detectionFpsField.max, detectionFpsField.step, detectionFpsField.default, motionCooldownMsField.min, motionCooldownMsField.max, motionCooldownMsField.step, motionCooldownMsField.default, maxSessionHoldMsField.min, maxSessionHoldMsField.max, maxSessionHoldMsField.step, maxSessionHoldMsField.default, audioMotionWindowMsField.min, audioMotionWindowMsField.max, audioMotionWindowMsField.step, audioMotionWindowMsField.default, preRollInferenceFramesField.min, preRollInferenceFramesField.max, preRollInferenceFramesField.step, preRollInferenceFramesField.default, occupancyRecheckSecField.min, occupancyRecheckSecField.max, occupancyRecheckSecField.step, occupancyRecheckSecField.default, occupancyRecheckFramesField.min, occupancyRecheckFramesField.max, occupancyRecheckFramesField.step, occupancyRecheckFramesField.default;
25328
+ MOTION_SOURCE_PICKER_ORDER.map((value) => value === "onboard" ? {
25329
+ value,
25330
+ label: MOTION_SOURCE_LABELS[value],
25331
+ description: "The camera's own motion, plus any sensor attached to it"
25332
+ } : {
25333
+ value,
25334
+ label: MOTION_SOURCE_LABELS[value]
25335
+ }), motionFpsField.min, motionFpsField.max, motionFpsField.step, motionFpsField.default, detectionFpsField.min, detectionFpsField.max, detectionFpsField.step, detectionFpsField.default, motionCooldownMsField.min, motionCooldownMsField.max, motionCooldownMsField.step, motionCooldownMsField.default, maxSessionHoldMsField.min, maxSessionHoldMsField.max, maxSessionHoldMsField.step, maxSessionHoldMsField.default, audioMotionWindowMsField.min, audioMotionWindowMsField.max, audioMotionWindowMsField.step, audioMotionWindowMsField.default, preRollInferenceFramesField.min, preRollInferenceFramesField.max, preRollInferenceFramesField.step, preRollInferenceFramesField.default, occupancyRecheckSecField.min, occupancyRecheckSecField.max, occupancyRecheckSecField.step, occupancyRecheckSecField.default, occupancyRecheckFramesField.min, occupancyRecheckFramesField.max, occupancyRecheckFramesField.step, occupancyRecheckFramesField.default;
25143
25336
  /**
25144
25337
  * Runtime load summary returned by `getLocalLoad`. Used by the orchestrator's
25145
25338
  * load-balancing levels (L2 capacity-based, L3 hardware-aware) to decide
@@ -25935,6 +26128,11 @@ var CameraStatusSchema = zod.z.object({
25935
26128
  */
25936
26129
  switchedOff: zod.z.array(CameraSwitchIdSchema).readonly(),
25937
26130
  /**
26131
+ * The camera's attached sensors (D672). Optional only for a status composed
26132
+ * by an orchestrator older than D672; this orchestrator always sets it.
26133
+ */
26134
+ cameraSensors: CameraSensorsStatusSchema.optional(),
26135
+ /**
25938
26136
  * Stages of the bounded fan-out that were CUT SHORT — a timeout or a
25939
26137
  * rejection — and whose block is therefore `null` because we could not
25940
26138
  * READ it, not because there is nothing there.
@@ -35181,7 +35379,9 @@ var MotionOnMotionChangedDataSchema = zod.z.object({
35181
35379
  detected: zod.z.boolean(),
35182
35380
  timestamp: zod.z.number(),
35183
35381
  source: MotionSourceEnum,
35184
- regions: zod.z.array(MotionRegionSchema).readonly().optional()
35382
+ regions: zod.z.array(MotionRegionSchema).readonly().optional(),
35383
+ /** Who started it (D672). Absent = the camera itself. Only `onboard` carries `sensor`. */
35384
+ triggeredBy: MotionTriggeredBySchema.optional()
35185
35385
  });
35186
35386
  var motionCapability = {
35187
35387
  name: "motion",
@@ -43527,7 +43727,8 @@ function expressionOutcome(source, read, now, stateful) {
43527
43727
  state: "stale",
43528
43728
  value: evaluateCount(null, {
43529
43729
  kind: "count",
43530
- highWater: null
43730
+ highWater: null,
43731
+ primed: false
43531
43732
  }, stateful.currentOutput),
43532
43733
  reason: `${unavailable.reason}; holding the last accumulator value`,
43533
43734
  deadline: null
@@ -48579,6 +48780,12 @@ var METHOD_ACCESS_MAP = Object.freeze({
48579
48780
  addonId: null,
48580
48781
  access: "view"
48581
48782
  },
48783
+ "deviceManager.getWrapperActivation": {
48784
+ capName: "device-manager",
48785
+ capScope: "system",
48786
+ addonId: null,
48787
+ access: "view"
48788
+ },
48582
48789
  "deviceManager.listAll": {
48583
48790
  capName: "device-manager",
48584
48791
  capScope: "system",
@@ -54388,6 +54595,11 @@ Object.freeze({
54388
54595
  form: "single",
54389
54596
  optional: false
54390
54597
  }],
54598
+ "deviceManager.getWrapperActivation": [{
54599
+ name: "deviceId",
54600
+ form: "single",
54601
+ optional: false
54602
+ }],
54391
54603
  "deviceManager.listAll": [{
54392
54604
  name: "deviceIds",
54393
54605
  form: "array",