@camstack/types 1.2.155 → 1.2.157

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/index.js CHANGED
@@ -1,6 +1,6 @@
1
1
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
2
  const require_event_category = require("./event-category-b8kBSOTT.js");
3
- const require_sleep = require("./sleep-QEBby1J6.js");
3
+ const require_sleep = require("./sleep-BGiOgxye.js");
4
4
  const require_canonical_hash = require("./canonical-hash-DNV8S5ET.js");
5
5
  const require_enums = require("./enums.js");
6
6
  const require_err_msg = require("./err-msg-COpsHMw2.js");
@@ -2041,7 +2041,22 @@ var RecordingTriggersSchema = zod.z.object({
2041
2041
  * il livello: un contatto trovato già aperto al riavvio del runner non fa
2042
2042
  * registrare.
2043
2043
  */
2044
- sensorDeviceIds: zod.z.array(zod.z.number().int().positive()).min(1).max(16).refine(noDuplicates, { message: "sensorDeviceIds must not repeat a device" }).optional()
2044
+ sensorDeviceIds: zod.z.array(zod.z.number().int().positive()).min(1).max(16).refine(noDuplicates, { message: "sensorDeviceIds must not repeat a device" }).optional(),
2045
+ /**
2046
+ * La camera registra per tutta la durata del SEGNALE che lei stessa
2047
+ * pubblica — la cap `recording-signal` (`active: true` mentre il device è in
2048
+ * funzione: un robot che pulisce). È un LIVELLO, non un fronte: la finestra
2049
+ * resta aperta finché il segnale è alto e si chiude `postBufferSec` dopo la
2050
+ * caduta, così una pulizia di quaranta minuti è UNA clip.
2051
+ *
2052
+ * Non nomina un device: il segnale è della camera stessa, tenuto fresco dal
2053
+ * suo provider (D224); il recorder lo ascolta su `DeviceStateChanged` e lo
2054
+ * riconcilia leggendo la slice via RPC, con un tetto oltre il quale un
2055
+ * segnale mai abbassato (un evento perso) non può tenere aperta una
2056
+ * registrazione (D11). Vedi `recorder/addon/band-decision.ts`
2057
+ * (`holdTrigger` / `releaseTrigger`).
2058
+ */
2059
+ deviceSignal: zod.z.boolean().optional()
2045
2060
  });
2046
2061
  /**
2047
2062
  * Mode of a single recording band — the recorder per-band vocabulary.
@@ -7644,6 +7659,8 @@ var streamBrokerCapability = {
7644
7659
  label: zod.z.string().optional(),
7645
7660
  deviceFeatures: zod.z.array(zod.z.string()).optional(),
7646
7661
  autoEligible: zod.z.boolean().optional(),
7662
+ /** The slot the publisher says this stream IS — see `CameraStreamSchema.profileHint`. */
7663
+ profileHint: require_sleep.CamProfileSchema.optional(),
7647
7664
  metadata: zod.z.record(zod.z.string(), zod.z.unknown()).optional(),
7648
7665
  /** Required when kind === 'derived' — the source camStreamId the
7649
7666
  * derived broker reads its encoded plane from.
@@ -32989,6 +33006,79 @@ var recordingExportCapability = {
32989
33006
  }
32990
33007
  };
32991
33008
  //#endregion
33009
+ //#region src/capabilities/recording-signal.cap.ts
33010
+ /**
33011
+ * A camera's own "record me NOW" LEVEL — a signal the device raises while
33012
+ * something it knows about is happening (a robot vacuum cleaning, a machine
33013
+ * running, a gate open) and lowers when it stops.
33014
+ *
33015
+ * It is a level, not an edge. The sensor triggers the recorder already listens
33016
+ * to (`SOURCE_CAP_ACTIVE_FIELD`) fire on a rising edge and record for a fixed
33017
+ * post-buffer; a cleaning lasts forty minutes, and forty minutes of "this is
33018
+ * still happening" cannot be expressed as an edge plus a post-buffer without
33019
+ * either re-triggering on a timer (polling — D224 forbids the consumer keeping
33020
+ * the fact fresh) or picking a post-buffer long enough to cover every job,
33021
+ * which records the dock for that long after every short one. So the recorder
33022
+ * reads the LEVEL: it records for as long as `active` is true, plus the band's
33023
+ * own post-buffer once it falls.
33024
+ *
33025
+ * Who owns the fact: the PROVIDER of the device, which already reads the state
33026
+ * the signal is derived from (the vacuum's lifecycle state, for Dreame). It
33027
+ * writes this slice on every change; consumers subscribe to the kernel's
33028
+ * `DeviceStateChanged` for it and read it back through
33029
+ * `deviceState.getCapSlice` to reconcile — never a second copy, never a poll
33030
+ * against the device (D224, D8/D11).
33031
+ *
33032
+ * Deliberately NOT a `binary` sensor on the camera: a binary sensor is exported
33033
+ * to Home Assistant, HomeKit and the sensor picker as a thing an operator can
33034
+ * bind, and "the camera wants to record" is not a room sensor. It is a fact
33035
+ * about the camera, on the camera.
33036
+ */
33037
+ var RecordingSignalStatusSchema = zod.z.object({
33038
+ /** True while the device asks to be recorded. */
33039
+ active: zod.z.boolean(),
33040
+ /**
33041
+ * Why, in the provider's own vocabulary (a vacuum's `cleaning` / `docked`,
33042
+ * …). Free text for the log line and the UI badge; the recorder never
33043
+ * branches on it.
33044
+ */
33045
+ reason: zod.z.string(),
33046
+ /** Ms epoch of the last `active` transition. 0 if never observed. */
33047
+ lastChangedAt: zod.z.number()
33048
+ });
33049
+ /** The runtime-state slice: the status plus the clock every slice carries. */
33050
+ var RecordingSignalRuntimeStateSchema = RecordingSignalStatusSchema.extend({ lastFetchedAt: zod.z.number() });
33051
+ var recordingSignalCapability = {
33052
+ name: "recording-signal",
33053
+ scope: "device",
33054
+ deviceNative: true,
33055
+ mode: "singleton",
33056
+ deviceTypes: [require_sleep.DeviceType.Camera],
33057
+ methods: {
33058
+ /** The current level, straight from the slice the provider keeps fresh. */
33059
+ getStatus: require_sleep.method(zod.z.object({ deviceId: zod.z.number() }), RecordingSignalStatusSchema) },
33060
+ status: {
33061
+ schema: RecordingSignalStatusSchema,
33062
+ kind: "push",
33063
+ empty: {
33064
+ active: false,
33065
+ reason: "unknown",
33066
+ lastChangedAt: 0
33067
+ }
33068
+ },
33069
+ runtimeState: RecordingSignalRuntimeStateSchema,
33070
+ /**
33071
+ * Runtime-state durability: **session** — a restored `active: true` from
33072
+ * before a restart is exactly the stale level the recorder's reconcile bound
33073
+ * exists to end, and the provider re-derives the true level on activation
33074
+ * anyway. Nothing is lost by forgetting it; a lie is avoided.
33075
+ *
33076
+ * See `RuntimeStateDurability`. Enforced by
33077
+ * `scripts/check-runtime-state-durability.ts`.
33078
+ */
33079
+ durability: "session"
33080
+ };
33081
+ //#endregion
32992
33082
  //#region src/capabilities/scene-monitor.cap.ts
32993
33083
  /**
32994
33084
  * scene-monitor — device-scoped reference-region state cap. An operator marks
@@ -33521,6 +33611,8 @@ var CamStreamDescriptorSchema = zod.z.object({
33521
33611
  deviceFeatures: zod.z.array(zod.z.string()).optional(),
33522
33612
  /** Eligible for automatic profile assignment. Absent = `true`. */
33523
33613
  autoEligible: zod.z.boolean().optional(),
33614
+ /** The slot the publisher says this stream IS — see `CameraStreamSchema.profileHint`. */
33615
+ profileHint: require_sleep.CamProfileSchema.optional(),
33524
33616
  /** Transport-specific opaque metadata (e.g. rfc4571 SDP). */
33525
33617
  metadata: zod.z.record(zod.z.string(), zod.z.unknown()).optional()
33526
33618
  });
@@ -36622,6 +36714,7 @@ var DEVICE_LOCAL_STATE_CAPS = {
36622
36714
  pressureSensor: pressureSensorCapability,
36623
36715
  privacyMask: privacyMaskCapability,
36624
36716
  ptzAutotrack: ptzAutotrackCapability,
36717
+ recordingSignal: recordingSignalCapability,
36625
36718
  sceneMonitor: sceneMonitorCapability,
36626
36719
  scriptRunner: scriptRunnerCapability,
36627
36720
  smoke: smokeCapability,
@@ -37474,6 +37567,53 @@ var BaseDeviceProvider = class extends require_sleep.BaseAddon {
37474
37567
  const ids = [...this._permanentRestoreFailures.keys()].join(", ");
37475
37568
  return `${this._permanentRestoreFailures.size} device(s) permanently failed restore (deviceIds: ${ids}) — restart the ${this.providerName} provider to retry`;
37476
37569
  }
37570
+ /**
37571
+ * A top-level persisted row with NO configuration is a leftover, not a
37572
+ * device — quarantine it instead of dialling it.
37573
+ *
37574
+ * Device 614 was deleted, resurrected as a config-less shell by a write
37575
+ * already in flight (D376), and then dialled at every single boot: eight
37576
+ * `Failed to restore device — bounded retry scheduled` lines in one day,
37577
+ * each one the same Zod refusal on `host` and `password`. The bound was
37578
+ * real, but it is a bound PER PROCESS, and the runner restarts — so nothing
37579
+ * about the row ever stopped costing attempts and log lines.
37580
+ *
37581
+ * No retry can add a configuration that is not there. The row is reported
37582
+ * once, with its `deviceId`, and set aside.
37583
+ *
37584
+ * Top-level only: an accessory child legitimately carries an empty blob (it
37585
+ * lives off its parent), and a hub-adopted child with an emptied blob is
37586
+ * repaired by `healSavedConfig` from its parent instead. Providers that
37587
+ * genuinely create configuration-free top-level devices turn this off.
37588
+ */
37589
+ quarantineConfiglessTopLevelRestores = true;
37590
+ isUnrestorableShell(saved) {
37591
+ if (!this.quarantineConfiglessTopLevelRestores) return false;
37592
+ if (saved.parentDeviceId !== null) return false;
37593
+ const config = saved.config;
37594
+ if (config === void 0) return false;
37595
+ return Object.keys(config).length === 0;
37596
+ }
37597
+ quarantineShell(saved) {
37598
+ this._permanentRestoreFailures.set(saved.id, {
37599
+ deviceId: saved.id,
37600
+ stableId: saved.stableId,
37601
+ type: saved.type,
37602
+ attempts: 0,
37603
+ lastError: "persisted row has no configuration",
37604
+ failedAt: Date.now()
37605
+ });
37606
+ this.ctx.logger.error("Persisted device row has NO configuration — quarantined: not restored, not retried. Remove it (deviceManager.removeDevice) or re-add the device.", {
37607
+ tags: {
37608
+ deviceId: saved.id,
37609
+ stableId: saved.stableId
37610
+ },
37611
+ meta: {
37612
+ type: saved.type,
37613
+ provider: this.providerName
37614
+ }
37615
+ });
37616
+ }
37477
37617
  cancelRestoreRetries() {
37478
37618
  this._restoreRetryScheduler?.cancel();
37479
37619
  this._restoreRetryScheduler = null;
@@ -37658,6 +37798,10 @@ var BaseDeviceProvider = class extends require_sleep.BaseAddon {
37658
37798
  });
37659
37799
  return;
37660
37800
  }
37801
+ if (this.isUnrestorableShell(saved)) {
37802
+ this.quarantineShell(saved);
37803
+ return;
37804
+ }
37661
37805
  try {
37662
37806
  await attemptRestore(saved);
37663
37807
  } catch (err) {
@@ -39439,6 +39583,7 @@ var CAP_NAMES_WITH_STATUS = [
39439
39583
  "ptz",
39440
39584
  "ptz-autotrack",
39441
39585
  "recording",
39586
+ "recording-signal",
39442
39587
  "scene-monitor",
39443
39588
  "script-runner",
39444
39589
  "smoke",
@@ -39574,6 +39719,7 @@ var CAPABILITY_NAMES = {
39574
39719
  reboot: "reboot",
39575
39720
  recording: "recording",
39576
39721
  recordingExport: "recording-export",
39722
+ recordingSignal: "recording-signal",
39577
39723
  sceneMonitor: "scene-monitor",
39578
39724
  scriptRunner: "script-runner",
39579
39725
  serverManagement: "server-management",
@@ -40082,6 +40228,10 @@ var CAPABILITY_ROUTER_KEYS = [
40082
40228
  key: "recordingExport",
40083
40229
  name: "recording-export"
40084
40230
  },
40231
+ {
40232
+ key: "recordingSignal",
40233
+ name: "recording-signal"
40234
+ },
40085
40235
  {
40086
40236
  key: "sceneMonitor",
40087
40237
  name: "scene-monitor"
@@ -40358,6 +40508,7 @@ var ALL_CAPABILITY_DEFINITIONS = [
40358
40508
  rebootCapability,
40359
40509
  recordingCapability,
40360
40510
  recordingExportCapability,
40511
+ recordingSignalCapability,
40361
40512
  sceneMonitorCapability,
40362
40513
  scriptRunnerCapability,
40363
40514
  serverManagementCapability,
@@ -45037,6 +45188,12 @@ var METHOD_ACCESS_MAP = Object.freeze({
45037
45188
  addonId: null,
45038
45189
  access: "view"
45039
45190
  },
45191
+ "recordingSignal.getStatus": {
45192
+ capName: "recording-signal",
45193
+ capScope: "device",
45194
+ addonId: null,
45195
+ access: "view"
45196
+ },
45040
45197
  "sceneMonitor.captureReference": {
45041
45198
  capName: "scene-monitor",
45042
45199
  capScope: "device",
@@ -46611,6 +46768,7 @@ var KNOWN_CAP_NAMES = [
46611
46768
  "reboot",
46612
46769
  "recording",
46613
46770
  "recording-export",
46771
+ "recording-signal",
46614
46772
  "scene-monitor",
46615
46773
  "script-runner",
46616
46774
  "server-management",
@@ -46686,6 +46844,7 @@ var DEVICE_CAP_NAMES = [
46686
46844
  "ptz",
46687
46845
  "ptz-autotrack",
46688
46846
  "reboot",
46847
+ "recording-signal",
46689
46848
  "scene-monitor",
46690
46849
  "script-runner",
46691
46850
  "snapshot",
@@ -48294,6 +48453,11 @@ var METHOD_DEVICE_SELECTORS = Object.freeze({
48294
48453
  form: "single",
48295
48454
  optional: true
48296
48455
  }],
48456
+ "recordingSignal.getStatus": [{
48457
+ name: "deviceId",
48458
+ form: "single",
48459
+ optional: false
48460
+ }],
48297
48461
  "sceneMonitor.captureReference": [{
48298
48462
  name: "deviceId",
48299
48463
  form: "single",
@@ -48808,7 +48972,7 @@ function getCapsByProviderKind(kind) {
48808
48972
  //#region src/generated/runtime-state-durability.ts
48809
48973
  /**
48810
48974
  * Per-cap runtime-state policy, projected from every `*.cap.ts` that declares
48811
- * `runtimeState`. 66 caps: 35 `restored`, 31 `session`.
48975
+ * `runtimeState`. 67 caps: 35 `restored`, 32 `session`.
48812
48976
  *
48813
48977
  * A cap absent from this map has no runtime-state slice at all. A cap PRESENT
48814
48978
  * with `durability: 'session'` has one and has decided not to keep it.
@@ -49010,6 +49174,10 @@ var RUNTIME_STATE_POLICY = {
49010
49174
  durability: "session",
49011
49175
  volatileFields: []
49012
49176
  },
49177
+ "recording-signal": {
49178
+ durability: "session",
49179
+ volatileFields: []
49180
+ },
49013
49181
  "scene-monitor": {
49014
49182
  durability: "session",
49015
49183
  volatileFields: []
@@ -54587,6 +54755,8 @@ exports.RecordingRebalancePlanSchema = RecordingRebalancePlanSchema;
54587
54755
  exports.RecordingRebalanceSkipReasonSchema = RecordingRebalanceSkipReasonSchema;
54588
54756
  exports.RecordingRebalanceSkipSchema = RecordingRebalanceSkipSchema;
54589
54757
  exports.RecordingRetentionSchema = RecordingRetentionSchema;
54758
+ exports.RecordingSignalRuntimeStateSchema = RecordingSignalRuntimeStateSchema;
54759
+ exports.RecordingSignalStatusSchema = RecordingSignalStatusSchema;
54590
54760
  exports.RecordingStatusSchema = RecordingStatusSchema;
54591
54761
  exports.RecordingStorageModeSchema = RecordingStorageModeSchema;
54592
54762
  exports.RecordingStorageUsageSchema = RecordingStorageUsageSchema;
@@ -55190,6 +55360,7 @@ exports.readinessKey = require_sleep.readinessKey;
55190
55360
  exports.rebootCapability = rebootCapability;
55191
55361
  exports.recordingCapability = recordingCapability;
55192
55362
  exports.recordingExportCapability = recordingExportCapability;
55363
+ exports.recordingSignalCapability = recordingSignalCapability;
55193
55364
  exports.rectsToCells = rectsToCells;
55194
55365
  exports.reducePoints = reducePoints;
55195
55366
  exports.requiresPython = requiresPython;