@camstack/addon-provider-homeassistant 1.2.147 → 1.2.148

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.
package/dist/addon.js CHANGED
@@ -1,5 +1,5 @@
1
1
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
- const require_dist = require("./dist-CslhAXSs.js");
2
+ const require_dist = require("./dist-nvulD3Mi.js");
3
3
  let node_crypto = require("node:crypto");
4
4
  let node_zlib = require("node:zlib");
5
5
  //#region src/ha-admin-link.ts
@@ -959,13 +959,15 @@ var HaBinarySensorDevice = class extends HaBaseChildDevice {
959
959
  super(ctx, persisted.role !== void 0 ? { role: persisted.role } : {});
960
960
  this.capName = capName;
961
961
  this.registerCap(capName);
962
- this.runtimeState.setCapState(this.capName, buildSlice(capName, false, 0));
962
+ const stored = this.runtimeState.getCapState(capName);
963
+ this.runtimeState.setCapState(this.capName, buildSlice(capName, false, 0, stored));
963
964
  }
964
965
  handleStatePush(state) {
965
966
  if (state.state === "unavailable" || state.state === "unknown") return;
966
967
  const active = state.state === "on";
967
968
  const lastChangedAt = Date.parse(state.last_changed) || Date.now();
968
- this.runtimeState.setCapState(this.capName, buildSlice(this.capName, active, lastChangedAt));
969
+ const prior = this.runtimeState.getCapState(this.capName);
970
+ this.runtimeState.setCapState(this.capName, buildSlice(this.capName, active, lastChangedAt, prior));
969
971
  }
970
972
  registerCap(name) {
971
973
  switch (name) {
@@ -1041,7 +1043,16 @@ var HaBinarySensorDevice = class extends HaBaseChildDevice {
1041
1043
  return this.runtimeState.getCapState(this.capName) ?? fallback;
1042
1044
  }
1043
1045
  };
1044
- function buildSlice(capName, active, lastChangedAt) {
1046
+ /**
1047
+ * The motion slice's last rise, carried across a fall. `null` only while no
1048
+ * rise was ever observed — never a time taken from an `off` state, whose HA
1049
+ * `last_changed` is the FALL, not the rise.
1050
+ */
1051
+ function priorLastDetectedAt(prior) {
1052
+ const raw = prior?.["lastDetectedAt"];
1053
+ return typeof raw === "number" && Number.isFinite(raw) && raw > 0 ? raw : null;
1054
+ }
1055
+ function buildSlice(capName, active, lastChangedAt, prior) {
1045
1056
  switch (capName) {
1046
1057
  case "contact": return {
1047
1058
  entryOpen: active,
@@ -1081,7 +1092,7 @@ function buildSlice(capName, active, lastChangedAt) {
1081
1092
  };
1082
1093
  case "motion": return {
1083
1094
  detected: active,
1084
- lastDetectedAt: active ? lastChangedAt : null,
1095
+ lastDetectedAt: active ? lastChangedAt : priorLastDetectedAt(prior),
1085
1096
  autoClearAfterMs: null
1086
1097
  };
1087
1098
  }
package/dist/addon.mjs CHANGED
@@ -1,4 +1,4 @@
1
- import { $ as parseAdminBase, A as contactCapability, At as union, B as gasCapability, C as buildAddonRouteProvider, Ct as array, D as climateControlCapability, Dt as object, E as carbonMonoxideCapability, Et as number, G as lockControlCapability, H as humiditySensorCapability, I as enumSensorCapability, J as normalizeUnit, K as mediaPlayerCapability, L as eventEmitterCapability, M as coverCapability, Mt as url, N as deviceAdminLinkCapability, Nt as EventCategory, O as colorCapability, Ot as record, P as deviceAdoptionCapability, R as fanControlCapability, S as brokerCapability, St as _enum, T as buttonCapability, Tt as literal, U as imageCapability, V as humidifierCapability, W as lawnMowerControlCapability, X as notifierCapability, Y as notificationOutputCapability, Z as numericSensorCapability, _ as automationControlCapability, _t as DeviceType, at as smokeCapability, b as binaryCapability, bt as createEvent, ct as temperatureSensorCapability, d as TargetSchema, dt as valveCapability, et as powerMeterCapability, f as accessoriesCapability, ft as vibrationCapability, g as ambientLightSensorCapability, gt as DeviceRole, h as alarmPanelCapability, ht as DeviceFeature, it as scriptRunnerCapability, j as controlCapability, jt as unknown, k as connectivityCapability, kt as string, lt as updateCapability, m as airQualitySensorCapability, mt as weatherCapability, n as BaseDevice, nt as presenceCapability, ot as switchCapability, p as addonRoutesCapability, pt as waterHeaterCapability, q as motionCapability, r as BaseDeviceProvider, rt as pressureSensorCapability, s as EnumSensorDateTimeFormatSchema, st as tamperCapability, tt as prepareNotification, ut as vacuumControlCapability, v as batteryCapability, vt as errMsg, w as buildDeviceAdminUrl, wt as discriminatedUnion, x as brightnessCapability, y as bestLocationMatch, z as floodCapability } from "./dist-DVwhiKWh.mjs";
1
+ import { $ as parseAdminBase, A as contactCapability, At as union, B as gasCapability, C as buildAddonRouteProvider, Ct as array, D as climateControlCapability, Dt as object, E as carbonMonoxideCapability, Et as number, G as lockControlCapability, H as humiditySensorCapability, I as enumSensorCapability, J as normalizeUnit, K as mediaPlayerCapability, L as eventEmitterCapability, M as coverCapability, Mt as url, N as deviceAdminLinkCapability, Nt as EventCategory, O as colorCapability, Ot as record, P as deviceAdoptionCapability, R as fanControlCapability, S as brokerCapability, St as _enum, T as buttonCapability, Tt as literal, U as imageCapability, V as humidifierCapability, W as lawnMowerControlCapability, X as notifierCapability, Y as notificationOutputCapability, Z as numericSensorCapability, _ as automationControlCapability, _t as DeviceType, at as smokeCapability, b as binaryCapability, bt as createEvent, ct as temperatureSensorCapability, d as TargetSchema, dt as valveCapability, et as powerMeterCapability, f as accessoriesCapability, ft as vibrationCapability, g as ambientLightSensorCapability, gt as DeviceRole, h as alarmPanelCapability, ht as DeviceFeature, it as scriptRunnerCapability, j as controlCapability, jt as unknown, k as connectivityCapability, kt as string, lt as updateCapability, m as airQualitySensorCapability, mt as weatherCapability, n as BaseDevice, nt as presenceCapability, ot as switchCapability, p as addonRoutesCapability, pt as waterHeaterCapability, q as motionCapability, r as BaseDeviceProvider, rt as pressureSensorCapability, s as EnumSensorDateTimeFormatSchema, st as tamperCapability, tt as prepareNotification, ut as vacuumControlCapability, v as batteryCapability, vt as errMsg, w as buildDeviceAdminUrl, wt as discriminatedUnion, x as brightnessCapability, y as bestLocationMatch, z as floodCapability } from "./dist-DmoYnWid.mjs";
2
2
  import { randomUUID } from "node:crypto";
3
3
  import { brotliCompressSync, deflateSync, gzipSync } from "node:zlib";
4
4
  //#region src/ha-admin-link.ts
@@ -958,13 +958,15 @@ var HaBinarySensorDevice = class extends HaBaseChildDevice {
958
958
  super(ctx, persisted.role !== void 0 ? { role: persisted.role } : {});
959
959
  this.capName = capName;
960
960
  this.registerCap(capName);
961
- this.runtimeState.setCapState(this.capName, buildSlice(capName, false, 0));
961
+ const stored = this.runtimeState.getCapState(capName);
962
+ this.runtimeState.setCapState(this.capName, buildSlice(capName, false, 0, stored));
962
963
  }
963
964
  handleStatePush(state) {
964
965
  if (state.state === "unavailable" || state.state === "unknown") return;
965
966
  const active = state.state === "on";
966
967
  const lastChangedAt = Date.parse(state.last_changed) || Date.now();
967
- this.runtimeState.setCapState(this.capName, buildSlice(this.capName, active, lastChangedAt));
968
+ const prior = this.runtimeState.getCapState(this.capName);
969
+ this.runtimeState.setCapState(this.capName, buildSlice(this.capName, active, lastChangedAt, prior));
968
970
  }
969
971
  registerCap(name) {
970
972
  switch (name) {
@@ -1040,7 +1042,16 @@ var HaBinarySensorDevice = class extends HaBaseChildDevice {
1040
1042
  return this.runtimeState.getCapState(this.capName) ?? fallback;
1041
1043
  }
1042
1044
  };
1043
- function buildSlice(capName, active, lastChangedAt) {
1045
+ /**
1046
+ * The motion slice's last rise, carried across a fall. `null` only while no
1047
+ * rise was ever observed — never a time taken from an `off` state, whose HA
1048
+ * `last_changed` is the FALL, not the rise.
1049
+ */
1050
+ function priorLastDetectedAt(prior) {
1051
+ const raw = prior?.["lastDetectedAt"];
1052
+ return typeof raw === "number" && Number.isFinite(raw) && raw > 0 ? raw : null;
1053
+ }
1054
+ function buildSlice(capName, active, lastChangedAt, prior) {
1044
1055
  switch (capName) {
1045
1056
  case "contact": return {
1046
1057
  entryOpen: active,
@@ -1080,7 +1091,7 @@ function buildSlice(capName, active, lastChangedAt) {
1080
1091
  };
1081
1092
  case "motion": return {
1082
1093
  detected: active,
1083
- lastDetectedAt: active ? lastChangedAt : null,
1094
+ lastDetectedAt: active ? lastChangedAt : priorLastDetectedAt(prior),
1084
1095
  autoClearAfterMs: null
1085
1096
  };
1086
1097
  }
@@ -5369,7 +5369,7 @@ var ZodIssueCode = {
5369
5369
  var ZodFirstPartyTypeKind;
5370
5370
  ZodFirstPartyTypeKind || (ZodFirstPartyTypeKind = {});
5371
5371
  //#endregion
5372
- //#region ../types/dist/sleep-DlrgY4Qb.mjs
5372
+ //#region ../types/dist/sleep-C-v96WpE.mjs
5373
5373
  /**
5374
5374
  * The audio chunk plane's byte format, and the ONE expansion from a coded
5375
5375
  * window to float samples (D455).
@@ -8277,7 +8277,6 @@ var CompositionSchema = object({
8277
8277
  });
8278
8278
  new Set([
8279
8279
  "track",
8280
- "summary",
8281
8280
  "face",
8282
8281
  "identity",
8283
8282
  "plate",
@@ -20883,6 +20882,102 @@ var oauthIntegrationCapability = {
20883
20882
  getDescriptor: method(_void(), OauthIntegrationDescriptorSchema, { auth: "admin" }) }
20884
20883
  };
20885
20884
  /**
20885
+ * What started a camera's onboard motion (D672). `camera` is the camera's own
20886
+ * firmware; `sensor` is a device the operator ATTACHED to it. Absent on the
20887
+ * wire means the camera: only the camera-sensors bridge ever says `sensor`.
20888
+ */
20889
+ var MotionTriggeredBySchema = discriminatedUnion("kind", [object({ kind: literal("camera") }), object({
20890
+ kind: literal("sensor"),
20891
+ deviceId: number().int().positive()
20892
+ })]);
20893
+ Object.freeze({ kind: "camera" });
20894
+ var CameraSensorRefSchema = object({
20895
+ addonId: string().min(1),
20896
+ stableId: string().min(1)
20897
+ });
20898
+ function cameraSensorRefKey(ref) {
20899
+ return `${ref.addonId}/${ref.stableId}`;
20900
+ }
20901
+ /** CS-1 accepts exactly one mode; CS-2 (D673) widens it to confirm / replace. */
20902
+ var CameraSensorsModeSchema = _enum(["in-addition"]);
20903
+ object({
20904
+ mode: CameraSensorsModeSchema,
20905
+ sensors: array(CameraSensorRefSchema).min(1).max(8)
20906
+ }).superRefine((value, ctx) => {
20907
+ const seen = /* @__PURE__ */ new Set();
20908
+ value.sensors.forEach((ref, index) => {
20909
+ const key = cameraSensorRefKey(ref);
20910
+ if (seen.has(key)) ctx.addIssue({
20911
+ code: "custom",
20912
+ path: ["sensors", index],
20913
+ message: `duplicate camera sensor ${key}`
20914
+ });
20915
+ seen.add(key);
20916
+ });
20917
+ });
20918
+ var RefFields = {
20919
+ addonId: string(),
20920
+ stableId: string()
20921
+ };
20922
+ var CameraSensorAttachmentSchema = discriminatedUnion("state", [
20923
+ object({
20924
+ ...RefFields,
20925
+ state: literal("ready"),
20926
+ deviceId: number(),
20927
+ name: string(),
20928
+ caps: array(string()).readonly()
20929
+ }),
20930
+ object({
20931
+ ...RefFields,
20932
+ state: literal("offline"),
20933
+ deviceId: number(),
20934
+ name: string(),
20935
+ reason: _enum(["offline", "disabled"])
20936
+ }),
20937
+ object({
20938
+ ...RefFields,
20939
+ state: literal("missing"),
20940
+ reason: string()
20941
+ }),
20942
+ object({
20943
+ ...RefFields,
20944
+ state: literal("unsupported"),
20945
+ deviceId: number(),
20946
+ name: string(),
20947
+ reason: string()
20948
+ }),
20949
+ object({
20950
+ ...RefFields,
20951
+ state: literal("unreadable"),
20952
+ reason: string()
20953
+ })
20954
+ ]);
20955
+ /**
20956
+ * Why a configured camera forwards NOTHING from its sensors, however ready they
20957
+ * are (D672): it does not list `onboard` in `motionSources` (attaching a sensor
20958
+ * does not add it), or it has no active detection config at all (the bridge
20959
+ * reads the active config). Absent = forwarded, or an older node that does not
20960
+ * say.
20961
+ */
20962
+ var CameraSensorsNotForwardedSchema = _enum(["onboard-not-listed", "no-active-detection"]);
20963
+ var CameraSensorsStatusSchema = discriminatedUnion("state", [
20964
+ object({ state: literal("not-configured") }),
20965
+ object({
20966
+ state: literal("unreadable"),
20967
+ reason: string()
20968
+ }),
20969
+ object({
20970
+ state: literal("configured"),
20971
+ mode: CameraSensorsModeSchema,
20972
+ sensors: array(CameraSensorAttachmentSchema).readonly(),
20973
+ notForwarded: CameraSensorsNotForwardedSchema.optional()
20974
+ })
20975
+ ]);
20976
+ Object.freeze({
20977
+ state: "unreadable",
20978
+ reason: "camera sensor mappings not loaded"
20979
+ });
20980
+ /**
20886
20981
  * A model choice has a SCOPE, and a scope change has a workflow.
20887
20982
  *
20888
20983
  * ## The two scopes
@@ -21631,6 +21726,12 @@ var MotionEventSchema = object({
21631
21726
  /** Populated by B5 (recording playback URL for this event). */
21632
21727
  mediaUrl: string().optional(),
21633
21728
  /**
21729
+ * The FIRST trigger of an `onboard` episode, written once at open (D672).
21730
+ * Absent = not recorded (a row written before D672, or an analyzer /
21731
+ * device-activity episode) — never read as "the camera" (D393).
21732
+ */
21733
+ triggeredBy: MotionTriggeredBySchema.optional(),
21734
+ /**
21634
21735
  * One row per motion EPISODE, not one per push (D475). `null` while the
21635
21736
  * episode is still open — a further rising edge extends it in place rather
21636
21737
  * than inserting a new row. Set once, at close, to `lastOnAt - startedAt`
@@ -21789,6 +21890,21 @@ var ObjectEventSchema = object({
21789
21890
  keyFrameMediaId: number().int().optional(),
21790
21891
  /** Populated by B5 (recording playback URL for this event). */
21791
21892
  mediaUrl: string().optional(),
21893
+ /**
21894
+ * When the change this row records HAPPENED, epoch ms, when that is earlier
21895
+ * than {@link timestamp} and the producer could date it (D684).
21896
+ *
21897
+ * Set on a package PICK-UP row only: its `timestamp` is when the departure
21898
+ * was CONCLUDED — five minutes of unseen observed time after the parcel went
21899
+ * — and a notification's footage has to be cut around the pick-up, not the
21900
+ * empty doormat after it (D682). Stored so every path that rebuilds a
21901
+ * notification subject from the row (the boot reconcile, a dry-run) anchors
21902
+ * on the same instant the live hook did.
21903
+ *
21904
+ * `timestamp` keeps its meaning. Absent on every other row and on every
21905
+ * pick-up written before D684 — UNKNOWN, never 0 and never `timestamp`.
21906
+ */
21907
+ observedAt: number().optional(),
21792
21908
  /** The parent track's key-event importance [0,1], propagated to every object
21793
21909
  * event of the track (so an event row can be sorted by importance without a
21794
21910
  * track join). Absent on legacy rows / before the track was scored. */
@@ -22124,131 +22240,6 @@ var RecentTracksQueryInput = object({
22124
22240
  /** See {@link ExcludeSourcesDoc}. */
22125
22241
  excludeSources: array(TrackSourceSchema).optional()
22126
22242
  });
22127
- /**
22128
- * A Summary (D359): the per-camera session envelope that references tracks.
22129
- * `groupShotMediaId` is the media ROW id of its group shot (`ownerKind:
22130
- * 'summary'`, served by the event-media plane at `/m/<id>`), null until the
22131
- * first frame with a member visible has been materialised (D482 — it was the
22132
- * row's composite key, which embedded the owner and could name another table's
22133
- * row once event ids became per-table rowids).
22134
- */
22135
- var SummarySchema = object({
22136
- id: string(),
22137
- deviceId: number(),
22138
- openedAt: number(),
22139
- lastActiveAt: number(),
22140
- sealedAt: number().nullable(),
22141
- memberCount: number().int().nonnegative(),
22142
- groupShotMediaId: number().int().nullable()
22143
- });
22144
- var SummariesQueryInput = object({
22145
- deviceIds: array(number()).min(1),
22146
- since: number().optional(),
22147
- until: number().optional(),
22148
- limit: number().int().min(1).max(200).default(50),
22149
- /** The same member-wise filter {@link listRecentSummaries} takes — one
22150
- * meaning of "dog" on every summary surface. */
22151
- classes: array(string().min(1).max(60)).max(40).optional()
22152
- });
22153
- var SummaryDetailSchema = object({
22154
- summary: SummarySchema,
22155
- /** Members in absorption order, oldest join first. */
22156
- members: array(object({
22157
- trackId: string(),
22158
- /**
22159
- * The track's class at the time it JOINED, or `null` when it was unresolved
22160
- * and the track no longer exists to fill it.
22161
- *
22162
- * The join, not the latest opinion: class voting can re-decide a track's
22163
- * class afterwards, and a group's composition is the history of who came
22164
- * together. A consumer counts these to badge a thumbnail — "two people and a
22165
- * dog" — rather than being handed a second, denormalised tally that would
22166
- * drift from the members it claims to describe.
22167
- */
22168
- className: string().nullable(),
22169
- /** `primary` is the one member that carries the group's identity. */
22170
- role: _enum([
22171
- "primary",
22172
- "sibling",
22173
- "child"
22174
- ]).nullable(),
22175
- joinedAt: number(),
22176
- /** Tier 1 — the sub-class (`dog`, `van`), resolved from the member's track
22177
- * at read time. Absent when nothing resolved, never an empty string. */
22178
- label: string().optional(),
22179
- /** Tier 2 — the instance: a person's name, a plate. Absent when the pipeline
22180
- * recognised nobody, and absent for a member whose track has been pruned —
22181
- * a thumbnail that names the wrong person is worse than one naming nobody. */
22182
- subLabel: string().optional()
22183
- })).readonly()
22184
- });
22185
- /**
22186
- * What a LIST of groups carries: the envelope plus what it is MADE OF.
22187
- *
22188
- * Coarse on purpose — the operator's rule is "only the rough data on the list,
22189
- * we extend when we notice we need more". Enough to draw the card ("two people
22190
- * and a dog") and no more. The MEMBERS, their names and the per-member links
22191
- * are on {@link getSummary}: shipping every member of every group so a client
22192
- * can count them turns a page of two hundred groups into a thousand records to
22193
- * draw two hundred badges.
22194
- */
22195
- var SummaryListItemSchema = object({
22196
- summary: SummarySchema,
22197
- /** Class counts, most numerous first; `className: null` is a member whose
22198
- * class never resolved, counted so the counts add up to `memberCount`. */
22199
- classes: array(object({
22200
- className: string().nullable(),
22201
- count: number().int().positive()
22202
- })).readonly()
22203
- });
22204
- var SummariesPageSchema = object({ summaries: array(SummaryListItemSchema).readonly() });
22205
- /**
22206
- * The paged feed, deliberately the SAME shape as {@link RecentTracksQueryInput}.
22207
- *
22208
- * The reel on the cameras page and the Events gallery both ride a cursor, so a
22209
- * summaries feed that could only answer "the last N for these cameras"
22210
- * (`listSummaries`) would make groups available in the timeline and nowhere
22211
- * else. Two feeds with different ordering contracts would be two ideas of what
22212
- * "newest" means, on one screen.
22213
- */
22214
- var RecentSummariesQueryInput = object({
22215
- /** Devices to merge. An empty array yields an empty page. */
22216
- deviceIds: array(number()),
22217
- /** Window lower bound on `lastActiveAt` (inclusive). */
22218
- since: number().optional(),
22219
- /** Window upper bound on `lastActiveAt` (inclusive). */
22220
- until: number().optional(),
22221
- limit: number().int().min(1).max(500).default(100),
22222
- /** Opaque continuation cursor from a previous page's `nextCursor`. */
22223
- cursor: string().optional(),
22224
- /**
22225
- * Restrict to these classes — THE SAME FIELD `listRecentTracks` takes, and
22226
- * deliberately the same name: the events filter tree emits one list of ticked
22227
- * taxonomy nodes, and a summaries feed that called it something else would
22228
- * make the operator's one filter component produce two shapes.
22229
- *
22230
- * A question about the MEMBERS: a group matches when ANY of them does. "Show
22231
- * me the arrivals with a dog" has to return the group of four people who had
22232
- * one with them; a filter on the group's own fields could only ever answer
22233
- * about its primary.
22234
- *
22235
- * Matched against all THREE tiers of a member — the class (`animal`), the
22236
- * sub-class (`dog`) and the instance (a name, a plate) — because which tier a
22237
- * ticked node lives on is the taxonomy's business, not the caller's. `dog` is
22238
- * an event kind in the tree and a tier-1 label on an `animal` track; a filter
22239
- * that read only the class would answer "animal" and never "dog".
22240
- *
22241
- * ABSENT or EMPTY means no filter — absent is not a selection of none.
22242
- */
22243
- classes: array(string().min(1).max(60)).max(40).optional()
22244
- });
22245
- var RecentSummariesPageSchema = object({
22246
- /** Ordered by (`lastActiveAt` DESC, id DESC). Same light item as
22247
- * {@link listSummaries} — one list shape, so a card renders the same
22248
- * whichever feed drew it. */
22249
- summaries: array(SummaryListItemSchema).readonly(),
22250
- nextCursor: string().nullable()
22251
- });
22252
22243
  var RecentTracksPageSchema = object({
22253
22244
  /** Merged page, ordered by (`lastSeen` DESC, `trackId` DESC). */
22254
22245
  tracks: array(TrackSchema).readonly(),
@@ -22760,7 +22751,7 @@ DeviceType.Camera, method(object({ deviceId: number() }), array(TrackSchema).rea
22760
22751
  classes: array(string()).optional(),
22761
22752
  /** See {@link ExcludeSourcesDoc}. */
22762
22753
  excludeSources: array(TrackSourceSchema).optional()
22763
- }), array(TrackSchema).readonly()), method(RecentTracksQueryInput, RecentTracksPageSchema), method(SummariesQueryInput, SummariesPageSchema), method(RecentSummariesQueryInput, RecentSummariesPageSchema), method(object({ id: string() }), SummaryDetailSchema.nullable()), method(object({ deviceId: number() }), _void(), {
22754
+ }), array(TrackSchema).readonly()), method(RecentTracksQueryInput, RecentTracksPageSchema), method(object({ deviceId: number() }), _void(), {
22764
22755
  kind: "mutation",
22765
22756
  auth: "admin"
22766
22757
  }), method(DeviceEventQueryInput, array(MotionEventSchema).readonly()), method(ObjectEventQueryInput, array(ObjectEventSchema).readonly()), method(DeviceEventQueryInput, array(AudioEventSchema).readonly()), method(object({ deviceId: number() }), array(EventKindDescriptorSchema).readonly()), method(object({ deviceIds: array(number()).min(1).max(200) }), array(EventKindsForDeviceSchema).readonly()), method(object({
@@ -23980,6 +23971,23 @@ var MotionSourceEnum = _enum([
23980
23971
  */
23981
23972
  var MotionSourcesSchema = array(MotionSourceEnum);
23982
23973
  /**
23974
+ * The operator-facing name of each MOTION source (D672: `onboard` = the
23975
+ * camera's sensors — its own motion plus any sensor attached to it). The wire
23976
+ * value stays `onboard`; only the label changed. `detectionSources: 'onboard'`
23977
+ * ("Camera onboard AI") and the notification source filter keep their labels.
23978
+ */
23979
+ var MOTION_SOURCE_LABELS = {
23980
+ analyzer: "Frame-diff Analyzer (motion addon)",
23981
+ onboard: "Camera sensors",
23982
+ "device-activity": "Device activity (the device says it is working)"
23983
+ };
23984
+ /** The order the motion-source picker offers them in (not the enum's order). */
23985
+ var MOTION_SOURCE_PICKER_ORDER = [
23986
+ "analyzer",
23987
+ "onboard",
23988
+ "device-activity"
23989
+ ];
23990
+ /**
23983
23991
  * Which root detector a camera runs — EXACTLY ONE.
23984
23992
  *
23985
23993
  * Deliberately the SAME vocabulary post-analysis already tags every detection
@@ -24326,7 +24334,14 @@ var RunnerCameraConfigSchema = object({
24326
24334
  */
24327
24335
  inferenceDevices: array(RunnerInferenceDeviceSchema).readonly().optional()
24328
24336
  });
24329
- 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;
24337
+ MOTION_SOURCE_PICKER_ORDER.map((value) => value === "onboard" ? {
24338
+ value,
24339
+ label: MOTION_SOURCE_LABELS[value],
24340
+ description: "The camera's own motion, plus any sensor attached to it"
24341
+ } : {
24342
+ value,
24343
+ label: MOTION_SOURCE_LABELS[value]
24344
+ }), 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;
24330
24345
  /**
24331
24346
  * Runtime load summary returned by `getLocalLoad`. Used by the orchestrator's
24332
24347
  * load-balancing levels (L2 capacity-based, L3 hardware-aware) to decide
@@ -24900,6 +24915,11 @@ var CameraStatusSchema = object({
24900
24915
  */
24901
24916
  switchedOff: array(CameraSwitchIdSchema).readonly(),
24902
24917
  /**
24918
+ * The camera's attached sensors (D672). Optional only for a status composed
24919
+ * by an orchestrator older than D672; this orchestrator always sets it.
24920
+ */
24921
+ cameraSensors: CameraSensorsStatusSchema.optional(),
24922
+ /**
24903
24923
  * Stages of the bounded fan-out that were CUT SHORT — a timeout or a
24904
24924
  * rejection — and whose block is therefore `null` because we could not
24905
24925
  * READ it, not because there is nothing there.
@@ -32327,7 +32347,9 @@ var MotionOnMotionChangedDataSchema = object({
32327
32347
  detected: boolean(),
32328
32348
  timestamp: number(),
32329
32349
  source: MotionSourceEnum,
32330
- regions: array(MotionRegionSchema).readonly().optional()
32350
+ regions: array(MotionRegionSchema).readonly().optional(),
32351
+ /** Who started it (D672). Absent = the camera itself. Only `onboard` carries `sensor`. */
32352
+ triggeredBy: MotionTriggeredBySchema.optional()
32331
32353
  });
32332
32354
  var motionCapability = {
32333
32355
  name: "motion",
@@ -45773,12 +45795,6 @@ Object.freeze({
45773
45795
  addonId: null,
45774
45796
  access: "view"
45775
45797
  },
45776
- "pipelineAnalytics.getSummary": {
45777
- capName: "pipeline-analytics",
45778
- capScope: "device",
45779
- addonId: null,
45780
- access: "view"
45781
- },
45782
45798
  "pipelineAnalytics.getTrack": {
45783
45799
  capName: "pipeline-analytics",
45784
45800
  capScope: "device",
@@ -45839,12 +45855,6 @@ Object.freeze({
45839
45855
  addonId: null,
45840
45856
  access: "view"
45841
45857
  },
45842
- "pipelineAnalytics.listRecentSummaries": {
45843
- capName: "pipeline-analytics",
45844
- capScope: "device",
45845
- addonId: null,
45846
- access: "view"
45847
- },
45848
45858
  "pipelineAnalytics.listRecentTracks": {
45849
45859
  capName: "pipeline-analytics",
45850
45860
  capScope: "device",
@@ -45875,12 +45885,6 @@ Object.freeze({
45875
45885
  addonId: null,
45876
45886
  access: "view"
45877
45887
  },
45878
- "pipelineAnalytics.listSummaries": {
45879
- capName: "pipeline-analytics",
45880
- capScope: "device",
45881
- addonId: null,
45882
- access: "view"
45883
- },
45884
45888
  "pipelineAnalytics.listTrackMedia": {
45885
45889
  capName: "pipeline-analytics",
45886
45890
  capScope: "device",
@@ -50050,11 +50054,6 @@ Object.freeze({
50050
50054
  form: "single",
50051
50055
  optional: true
50052
50056
  }],
50053
- "pipelineAnalytics.listRecentSummaries": [{
50054
- name: "deviceIds",
50055
- form: "array",
50056
- optional: false
50057
- }],
50058
50057
  "pipelineAnalytics.listRecentTracks": [{
50059
50058
  name: "deviceIds",
50060
50059
  form: "array",
@@ -50065,11 +50064,6 @@ Object.freeze({
50065
50064
  form: "array",
50066
50065
  optional: true
50067
50066
  }],
50068
- "pipelineAnalytics.listSummaries": [{
50069
- name: "deviceIds",
50070
- form: "array",
50071
- optional: false
50072
- }],
50073
50067
  "pipelineAnalytics.listTrackMedia": [{
50074
50068
  name: "deviceId",
50075
50069
  form: "single",
@@ -5370,7 +5370,7 @@ var ZodIssueCode = {
5370
5370
  var ZodFirstPartyTypeKind;
5371
5371
  ZodFirstPartyTypeKind || (ZodFirstPartyTypeKind = {});
5372
5372
  //#endregion
5373
- //#region ../types/dist/sleep-DlrgY4Qb.mjs
5373
+ //#region ../types/dist/sleep-C-v96WpE.mjs
5374
5374
  /**
5375
5375
  * The audio chunk plane's byte format, and the ONE expansion from a coded
5376
5376
  * window to float samples (D455).
@@ -8278,7 +8278,6 @@ var CompositionSchema = object({
8278
8278
  });
8279
8279
  new Set([
8280
8280
  "track",
8281
- "summary",
8282
8281
  "face",
8283
8282
  "identity",
8284
8283
  "plate",
@@ -20884,6 +20883,102 @@ var oauthIntegrationCapability = {
20884
20883
  getDescriptor: method(_void(), OauthIntegrationDescriptorSchema, { auth: "admin" }) }
20885
20884
  };
20886
20885
  /**
20886
+ * What started a camera's onboard motion (D672). `camera` is the camera's own
20887
+ * firmware; `sensor` is a device the operator ATTACHED to it. Absent on the
20888
+ * wire means the camera: only the camera-sensors bridge ever says `sensor`.
20889
+ */
20890
+ var MotionTriggeredBySchema = discriminatedUnion("kind", [object({ kind: literal("camera") }), object({
20891
+ kind: literal("sensor"),
20892
+ deviceId: number().int().positive()
20893
+ })]);
20894
+ Object.freeze({ kind: "camera" });
20895
+ var CameraSensorRefSchema = object({
20896
+ addonId: string().min(1),
20897
+ stableId: string().min(1)
20898
+ });
20899
+ function cameraSensorRefKey(ref) {
20900
+ return `${ref.addonId}/${ref.stableId}`;
20901
+ }
20902
+ /** CS-1 accepts exactly one mode; CS-2 (D673) widens it to confirm / replace. */
20903
+ var CameraSensorsModeSchema = _enum(["in-addition"]);
20904
+ object({
20905
+ mode: CameraSensorsModeSchema,
20906
+ sensors: array(CameraSensorRefSchema).min(1).max(8)
20907
+ }).superRefine((value, ctx) => {
20908
+ const seen = /* @__PURE__ */ new Set();
20909
+ value.sensors.forEach((ref, index) => {
20910
+ const key = cameraSensorRefKey(ref);
20911
+ if (seen.has(key)) ctx.addIssue({
20912
+ code: "custom",
20913
+ path: ["sensors", index],
20914
+ message: `duplicate camera sensor ${key}`
20915
+ });
20916
+ seen.add(key);
20917
+ });
20918
+ });
20919
+ var RefFields = {
20920
+ addonId: string(),
20921
+ stableId: string()
20922
+ };
20923
+ var CameraSensorAttachmentSchema = discriminatedUnion("state", [
20924
+ object({
20925
+ ...RefFields,
20926
+ state: literal("ready"),
20927
+ deviceId: number(),
20928
+ name: string(),
20929
+ caps: array(string()).readonly()
20930
+ }),
20931
+ object({
20932
+ ...RefFields,
20933
+ state: literal("offline"),
20934
+ deviceId: number(),
20935
+ name: string(),
20936
+ reason: _enum(["offline", "disabled"])
20937
+ }),
20938
+ object({
20939
+ ...RefFields,
20940
+ state: literal("missing"),
20941
+ reason: string()
20942
+ }),
20943
+ object({
20944
+ ...RefFields,
20945
+ state: literal("unsupported"),
20946
+ deviceId: number(),
20947
+ name: string(),
20948
+ reason: string()
20949
+ }),
20950
+ object({
20951
+ ...RefFields,
20952
+ state: literal("unreadable"),
20953
+ reason: string()
20954
+ })
20955
+ ]);
20956
+ /**
20957
+ * Why a configured camera forwards NOTHING from its sensors, however ready they
20958
+ * are (D672): it does not list `onboard` in `motionSources` (attaching a sensor
20959
+ * does not add it), or it has no active detection config at all (the bridge
20960
+ * reads the active config). Absent = forwarded, or an older node that does not
20961
+ * say.
20962
+ */
20963
+ var CameraSensorsNotForwardedSchema = _enum(["onboard-not-listed", "no-active-detection"]);
20964
+ var CameraSensorsStatusSchema = discriminatedUnion("state", [
20965
+ object({ state: literal("not-configured") }),
20966
+ object({
20967
+ state: literal("unreadable"),
20968
+ reason: string()
20969
+ }),
20970
+ object({
20971
+ state: literal("configured"),
20972
+ mode: CameraSensorsModeSchema,
20973
+ sensors: array(CameraSensorAttachmentSchema).readonly(),
20974
+ notForwarded: CameraSensorsNotForwardedSchema.optional()
20975
+ })
20976
+ ]);
20977
+ Object.freeze({
20978
+ state: "unreadable",
20979
+ reason: "camera sensor mappings not loaded"
20980
+ });
20981
+ /**
20887
20982
  * A model choice has a SCOPE, and a scope change has a workflow.
20888
20983
  *
20889
20984
  * ## The two scopes
@@ -21632,6 +21727,12 @@ var MotionEventSchema = object({
21632
21727
  /** Populated by B5 (recording playback URL for this event). */
21633
21728
  mediaUrl: string().optional(),
21634
21729
  /**
21730
+ * The FIRST trigger of an `onboard` episode, written once at open (D672).
21731
+ * Absent = not recorded (a row written before D672, or an analyzer /
21732
+ * device-activity episode) — never read as "the camera" (D393).
21733
+ */
21734
+ triggeredBy: MotionTriggeredBySchema.optional(),
21735
+ /**
21635
21736
  * One row per motion EPISODE, not one per push (D475). `null` while the
21636
21737
  * episode is still open — a further rising edge extends it in place rather
21637
21738
  * than inserting a new row. Set once, at close, to `lastOnAt - startedAt`
@@ -21790,6 +21891,21 @@ var ObjectEventSchema = object({
21790
21891
  keyFrameMediaId: number().int().optional(),
21791
21892
  /** Populated by B5 (recording playback URL for this event). */
21792
21893
  mediaUrl: string().optional(),
21894
+ /**
21895
+ * When the change this row records HAPPENED, epoch ms, when that is earlier
21896
+ * than {@link timestamp} and the producer could date it (D684).
21897
+ *
21898
+ * Set on a package PICK-UP row only: its `timestamp` is when the departure
21899
+ * was CONCLUDED — five minutes of unseen observed time after the parcel went
21900
+ * — and a notification's footage has to be cut around the pick-up, not the
21901
+ * empty doormat after it (D682). Stored so every path that rebuilds a
21902
+ * notification subject from the row (the boot reconcile, a dry-run) anchors
21903
+ * on the same instant the live hook did.
21904
+ *
21905
+ * `timestamp` keeps its meaning. Absent on every other row and on every
21906
+ * pick-up written before D684 — UNKNOWN, never 0 and never `timestamp`.
21907
+ */
21908
+ observedAt: number().optional(),
21793
21909
  /** The parent track's key-event importance [0,1], propagated to every object
21794
21910
  * event of the track (so an event row can be sorted by importance without a
21795
21911
  * track join). Absent on legacy rows / before the track was scored. */
@@ -22125,131 +22241,6 @@ var RecentTracksQueryInput = object({
22125
22241
  /** See {@link ExcludeSourcesDoc}. */
22126
22242
  excludeSources: array(TrackSourceSchema).optional()
22127
22243
  });
22128
- /**
22129
- * A Summary (D359): the per-camera session envelope that references tracks.
22130
- * `groupShotMediaId` is the media ROW id of its group shot (`ownerKind:
22131
- * 'summary'`, served by the event-media plane at `/m/<id>`), null until the
22132
- * first frame with a member visible has been materialised (D482 — it was the
22133
- * row's composite key, which embedded the owner and could name another table's
22134
- * row once event ids became per-table rowids).
22135
- */
22136
- var SummarySchema = object({
22137
- id: string(),
22138
- deviceId: number(),
22139
- openedAt: number(),
22140
- lastActiveAt: number(),
22141
- sealedAt: number().nullable(),
22142
- memberCount: number().int().nonnegative(),
22143
- groupShotMediaId: number().int().nullable()
22144
- });
22145
- var SummariesQueryInput = object({
22146
- deviceIds: array(number()).min(1),
22147
- since: number().optional(),
22148
- until: number().optional(),
22149
- limit: number().int().min(1).max(200).default(50),
22150
- /** The same member-wise filter {@link listRecentSummaries} takes — one
22151
- * meaning of "dog" on every summary surface. */
22152
- classes: array(string().min(1).max(60)).max(40).optional()
22153
- });
22154
- var SummaryDetailSchema = object({
22155
- summary: SummarySchema,
22156
- /** Members in absorption order, oldest join first. */
22157
- members: array(object({
22158
- trackId: string(),
22159
- /**
22160
- * The track's class at the time it JOINED, or `null` when it was unresolved
22161
- * and the track no longer exists to fill it.
22162
- *
22163
- * The join, not the latest opinion: class voting can re-decide a track's
22164
- * class afterwards, and a group's composition is the history of who came
22165
- * together. A consumer counts these to badge a thumbnail — "two people and a
22166
- * dog" — rather than being handed a second, denormalised tally that would
22167
- * drift from the members it claims to describe.
22168
- */
22169
- className: string().nullable(),
22170
- /** `primary` is the one member that carries the group's identity. */
22171
- role: _enum([
22172
- "primary",
22173
- "sibling",
22174
- "child"
22175
- ]).nullable(),
22176
- joinedAt: number(),
22177
- /** Tier 1 — the sub-class (`dog`, `van`), resolved from the member's track
22178
- * at read time. Absent when nothing resolved, never an empty string. */
22179
- label: string().optional(),
22180
- /** Tier 2 — the instance: a person's name, a plate. Absent when the pipeline
22181
- * recognised nobody, and absent for a member whose track has been pruned —
22182
- * a thumbnail that names the wrong person is worse than one naming nobody. */
22183
- subLabel: string().optional()
22184
- })).readonly()
22185
- });
22186
- /**
22187
- * What a LIST of groups carries: the envelope plus what it is MADE OF.
22188
- *
22189
- * Coarse on purpose — the operator's rule is "only the rough data on the list,
22190
- * we extend when we notice we need more". Enough to draw the card ("two people
22191
- * and a dog") and no more. The MEMBERS, their names and the per-member links
22192
- * are on {@link getSummary}: shipping every member of every group so a client
22193
- * can count them turns a page of two hundred groups into a thousand records to
22194
- * draw two hundred badges.
22195
- */
22196
- var SummaryListItemSchema = object({
22197
- summary: SummarySchema,
22198
- /** Class counts, most numerous first; `className: null` is a member whose
22199
- * class never resolved, counted so the counts add up to `memberCount`. */
22200
- classes: array(object({
22201
- className: string().nullable(),
22202
- count: number().int().positive()
22203
- })).readonly()
22204
- });
22205
- var SummariesPageSchema = object({ summaries: array(SummaryListItemSchema).readonly() });
22206
- /**
22207
- * The paged feed, deliberately the SAME shape as {@link RecentTracksQueryInput}.
22208
- *
22209
- * The reel on the cameras page and the Events gallery both ride a cursor, so a
22210
- * summaries feed that could only answer "the last N for these cameras"
22211
- * (`listSummaries`) would make groups available in the timeline and nowhere
22212
- * else. Two feeds with different ordering contracts would be two ideas of what
22213
- * "newest" means, on one screen.
22214
- */
22215
- var RecentSummariesQueryInput = object({
22216
- /** Devices to merge. An empty array yields an empty page. */
22217
- deviceIds: array(number()),
22218
- /** Window lower bound on `lastActiveAt` (inclusive). */
22219
- since: number().optional(),
22220
- /** Window upper bound on `lastActiveAt` (inclusive). */
22221
- until: number().optional(),
22222
- limit: number().int().min(1).max(500).default(100),
22223
- /** Opaque continuation cursor from a previous page's `nextCursor`. */
22224
- cursor: string().optional(),
22225
- /**
22226
- * Restrict to these classes — THE SAME FIELD `listRecentTracks` takes, and
22227
- * deliberately the same name: the events filter tree emits one list of ticked
22228
- * taxonomy nodes, and a summaries feed that called it something else would
22229
- * make the operator's one filter component produce two shapes.
22230
- *
22231
- * A question about the MEMBERS: a group matches when ANY of them does. "Show
22232
- * me the arrivals with a dog" has to return the group of four people who had
22233
- * one with them; a filter on the group's own fields could only ever answer
22234
- * about its primary.
22235
- *
22236
- * Matched against all THREE tiers of a member — the class (`animal`), the
22237
- * sub-class (`dog`) and the instance (a name, a plate) — because which tier a
22238
- * ticked node lives on is the taxonomy's business, not the caller's. `dog` is
22239
- * an event kind in the tree and a tier-1 label on an `animal` track; a filter
22240
- * that read only the class would answer "animal" and never "dog".
22241
- *
22242
- * ABSENT or EMPTY means no filter — absent is not a selection of none.
22243
- */
22244
- classes: array(string().min(1).max(60)).max(40).optional()
22245
- });
22246
- var RecentSummariesPageSchema = object({
22247
- /** Ordered by (`lastActiveAt` DESC, id DESC). Same light item as
22248
- * {@link listSummaries} — one list shape, so a card renders the same
22249
- * whichever feed drew it. */
22250
- summaries: array(SummaryListItemSchema).readonly(),
22251
- nextCursor: string().nullable()
22252
- });
22253
22244
  var RecentTracksPageSchema = object({
22254
22245
  /** Merged page, ordered by (`lastSeen` DESC, `trackId` DESC). */
22255
22246
  tracks: array(TrackSchema).readonly(),
@@ -22761,7 +22752,7 @@ DeviceType.Camera, method(object({ deviceId: number() }), array(TrackSchema).rea
22761
22752
  classes: array(string()).optional(),
22762
22753
  /** See {@link ExcludeSourcesDoc}. */
22763
22754
  excludeSources: array(TrackSourceSchema).optional()
22764
- }), array(TrackSchema).readonly()), method(RecentTracksQueryInput, RecentTracksPageSchema), method(SummariesQueryInput, SummariesPageSchema), method(RecentSummariesQueryInput, RecentSummariesPageSchema), method(object({ id: string() }), SummaryDetailSchema.nullable()), method(object({ deviceId: number() }), _void(), {
22755
+ }), array(TrackSchema).readonly()), method(RecentTracksQueryInput, RecentTracksPageSchema), method(object({ deviceId: number() }), _void(), {
22765
22756
  kind: "mutation",
22766
22757
  auth: "admin"
22767
22758
  }), method(DeviceEventQueryInput, array(MotionEventSchema).readonly()), method(ObjectEventQueryInput, array(ObjectEventSchema).readonly()), method(DeviceEventQueryInput, array(AudioEventSchema).readonly()), method(object({ deviceId: number() }), array(EventKindDescriptorSchema).readonly()), method(object({ deviceIds: array(number()).min(1).max(200) }), array(EventKindsForDeviceSchema).readonly()), method(object({
@@ -23981,6 +23972,23 @@ var MotionSourceEnum = _enum([
23981
23972
  */
23982
23973
  var MotionSourcesSchema = array(MotionSourceEnum);
23983
23974
  /**
23975
+ * The operator-facing name of each MOTION source (D672: `onboard` = the
23976
+ * camera's sensors — its own motion plus any sensor attached to it). The wire
23977
+ * value stays `onboard`; only the label changed. `detectionSources: 'onboard'`
23978
+ * ("Camera onboard AI") and the notification source filter keep their labels.
23979
+ */
23980
+ var MOTION_SOURCE_LABELS = {
23981
+ analyzer: "Frame-diff Analyzer (motion addon)",
23982
+ onboard: "Camera sensors",
23983
+ "device-activity": "Device activity (the device says it is working)"
23984
+ };
23985
+ /** The order the motion-source picker offers them in (not the enum's order). */
23986
+ var MOTION_SOURCE_PICKER_ORDER = [
23987
+ "analyzer",
23988
+ "onboard",
23989
+ "device-activity"
23990
+ ];
23991
+ /**
23984
23992
  * Which root detector a camera runs — EXACTLY ONE.
23985
23993
  *
23986
23994
  * Deliberately the SAME vocabulary post-analysis already tags every detection
@@ -24327,7 +24335,14 @@ var RunnerCameraConfigSchema = object({
24327
24335
  */
24328
24336
  inferenceDevices: array(RunnerInferenceDeviceSchema).readonly().optional()
24329
24337
  });
24330
- 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;
24338
+ MOTION_SOURCE_PICKER_ORDER.map((value) => value === "onboard" ? {
24339
+ value,
24340
+ label: MOTION_SOURCE_LABELS[value],
24341
+ description: "The camera's own motion, plus any sensor attached to it"
24342
+ } : {
24343
+ value,
24344
+ label: MOTION_SOURCE_LABELS[value]
24345
+ }), 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;
24331
24346
  /**
24332
24347
  * Runtime load summary returned by `getLocalLoad`. Used by the orchestrator's
24333
24348
  * load-balancing levels (L2 capacity-based, L3 hardware-aware) to decide
@@ -24901,6 +24916,11 @@ var CameraStatusSchema = object({
24901
24916
  */
24902
24917
  switchedOff: array(CameraSwitchIdSchema).readonly(),
24903
24918
  /**
24919
+ * The camera's attached sensors (D672). Optional only for a status composed
24920
+ * by an orchestrator older than D672; this orchestrator always sets it.
24921
+ */
24922
+ cameraSensors: CameraSensorsStatusSchema.optional(),
24923
+ /**
24904
24924
  * Stages of the bounded fan-out that were CUT SHORT — a timeout or a
24905
24925
  * rejection — and whose block is therefore `null` because we could not
24906
24926
  * READ it, not because there is nothing there.
@@ -32328,7 +32348,9 @@ var MotionOnMotionChangedDataSchema = object({
32328
32348
  detected: boolean(),
32329
32349
  timestamp: number(),
32330
32350
  source: MotionSourceEnum,
32331
- regions: array(MotionRegionSchema).readonly().optional()
32351
+ regions: array(MotionRegionSchema).readonly().optional(),
32352
+ /** Who started it (D672). Absent = the camera itself. Only `onboard` carries `sensor`. */
32353
+ triggeredBy: MotionTriggeredBySchema.optional()
32332
32354
  });
32333
32355
  var motionCapability = {
32334
32356
  name: "motion",
@@ -45774,12 +45796,6 @@ Object.freeze({
45774
45796
  addonId: null,
45775
45797
  access: "view"
45776
45798
  },
45777
- "pipelineAnalytics.getSummary": {
45778
- capName: "pipeline-analytics",
45779
- capScope: "device",
45780
- addonId: null,
45781
- access: "view"
45782
- },
45783
45799
  "pipelineAnalytics.getTrack": {
45784
45800
  capName: "pipeline-analytics",
45785
45801
  capScope: "device",
@@ -45840,12 +45856,6 @@ Object.freeze({
45840
45856
  addonId: null,
45841
45857
  access: "view"
45842
45858
  },
45843
- "pipelineAnalytics.listRecentSummaries": {
45844
- capName: "pipeline-analytics",
45845
- capScope: "device",
45846
- addonId: null,
45847
- access: "view"
45848
- },
45849
45859
  "pipelineAnalytics.listRecentTracks": {
45850
45860
  capName: "pipeline-analytics",
45851
45861
  capScope: "device",
@@ -45876,12 +45886,6 @@ Object.freeze({
45876
45886
  addonId: null,
45877
45887
  access: "view"
45878
45888
  },
45879
- "pipelineAnalytics.listSummaries": {
45880
- capName: "pipeline-analytics",
45881
- capScope: "device",
45882
- addonId: null,
45883
- access: "view"
45884
- },
45885
45889
  "pipelineAnalytics.listTrackMedia": {
45886
45890
  capName: "pipeline-analytics",
45887
45891
  capScope: "device",
@@ -50051,11 +50055,6 @@ Object.freeze({
50051
50055
  form: "single",
50052
50056
  optional: true
50053
50057
  }],
50054
- "pipelineAnalytics.listRecentSummaries": [{
50055
- name: "deviceIds",
50056
- form: "array",
50057
- optional: false
50058
- }],
50059
50058
  "pipelineAnalytics.listRecentTracks": [{
50060
50059
  name: "deviceIds",
50061
50060
  form: "array",
@@ -50066,11 +50065,6 @@ Object.freeze({
50066
50065
  form: "array",
50067
50066
  optional: true
50068
50067
  }],
50069
- "pipelineAnalytics.listSummaries": [{
50070
- name: "deviceIds",
50071
- form: "array",
50072
- optional: false
50073
- }],
50074
50068
  "pipelineAnalytics.listTrackMedia": [{
50075
50069
  name: "deviceId",
50076
50070
  form: "single",
@@ -3,7 +3,7 @@ Object.defineProperties(exports, {
3
3
  [Symbol.toStringTag]: { value: "Module" }
4
4
  });
5
5
  //#endregion
6
- const require_dist = require("../dist-CslhAXSs.js");
6
+ const require_dist = require("../dist-nvulD3Mi.js");
7
7
  let node_crypto = require("node:crypto");
8
8
  //#region src/ha-export/topics.ts
9
9
  /**
@@ -1,4 +1,4 @@
1
- import { C as buildAddonRouteProvider, F as deviceExportCapability, Nt as EventCategory, Q as oauthIntegrationCapability, a as COCO_TO_MACRO, c as FanDirectionSchema, i as CAMERA_SWITCH_ORDER, kt as string, l as HvacModeSchema, o as CameraSwitchIdSchema, p as addonRoutesCapability, t as AlarmArmModeSchema, u as MediaPlayerRepeatSchema, xt as nodePin, yt as BaseAddon } from "../dist-DVwhiKWh.mjs";
1
+ import { C as buildAddonRouteProvider, F as deviceExportCapability, Nt as EventCategory, Q as oauthIntegrationCapability, a as COCO_TO_MACRO, c as FanDirectionSchema, i as CAMERA_SWITCH_ORDER, kt as string, l as HvacModeSchema, o as CameraSwitchIdSchema, p as addonRoutesCapability, t as AlarmArmModeSchema, u as MediaPlayerRepeatSchema, xt as nodePin, yt as BaseAddon } from "../dist-DmoYnWid.mjs";
2
2
  import { createHmac, timingSafeEqual } from "node:crypto";
3
3
  //#region src/ha-export/topics.ts
4
4
  /**
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@camstack/addon-provider-homeassistant",
3
- "version": "1.2.147",
3
+ "version": "1.2.148",
4
4
  "description": "Home Assistant device provider addon for CamStack",
5
5
  "keywords": [
6
6
  "camstack",