@camstack/addon-pipeline 1.2.196 → 1.2.197

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 (38) hide show
  1. package/dist/audio-analyzer/index.js +2 -2
  2. package/dist/audio-analyzer/index.mjs +2 -2
  3. package/dist/{default-detection-model-CJdc8j83.js → default-detection-model-CM-8U0Bb.js} +1 -1
  4. package/dist/{default-detection-model-BGBAmtEp.mjs → default-detection-model-CplzzTmN.mjs} +1 -1
  5. package/dist/detection-pipeline/index.js +5 -5
  6. package/dist/detection-pipeline/index.mjs +4 -4
  7. package/dist/{dist-HG5geL9t.js → dist-CBa1j3On.js} +141 -35
  8. package/dist/{dist-mYDK58Jp.mjs → dist-Y4BsF_EC.mjs} +130 -36
  9. package/dist/{lazy-sharp-DmAwZ0s9.js → lazy-sharp-CS5WE9mI.js} +1 -1
  10. package/dist/motion-wasm/index.js +2 -2
  11. package/dist/motion-wasm/index.mjs +1 -1
  12. package/dist/{node-xRsaPwBa.mjs → node-B5ouEQYN.mjs} +1 -1
  13. package/dist/{node--my8JTOW.js → node-C-B8VuGi.js} +1 -1
  14. package/dist/pipeline-runner/index.js +363 -6
  15. package/dist/pipeline-runner/index.mjs +362 -5
  16. package/dist/{process-memory-CoCSce63.js → process-memory-CmeKr_MZ.js} +1 -1
  17. package/dist/{process-memory-BDHR3lxe.mjs → process-memory-DeO2OZ3-.mjs} +1 -1
  18. package/dist/recorder/index.js +131 -18
  19. package/dist/recorder/index.mjs +131 -18
  20. package/dist/{retire-root-keys-KE6D6Xh_.js → retire-root-keys-Csb8z2f3.js} +19 -0
  21. package/dist/{retire-root-keys-DMolfhsP.mjs → retire-root-keys-DZvlso2l.mjs} +19 -0
  22. package/dist/{segment-demux-js-CXvgKfsn.mjs → segment-demux-js-DXPgq2cf.mjs} +1 -1
  23. package/dist/{segment-demux-js-CBynn9Gh.js → segment-demux-js-DiIsywGz.js} +1 -1
  24. package/dist/session-decode/decode-worker-child.js +2 -2
  25. package/dist/session-decode/decode-worker-child.mjs +1 -1
  26. package/dist/stream-broker/_stub.js +2 -2
  27. package/dist/stream-broker/{_virtual_mf-localSharedImportMap___mfe_internal__addon_stream_broker_widgets-BMsB2MVD.mjs → _virtual_mf-localSharedImportMap___mfe_internal__addon_stream_broker_widgets-Q-6HzWJ0.mjs} +3 -3
  28. package/dist/stream-broker/{_virtual_mf___mfe_internal__addon_stream_broker_widgets__loadShare___mf_0_camstack_mf_1_types__loadShare__.js-B_NVJXAy.mjs → _virtual_mf___mfe_internal__addon_stream_broker_widgets__loadShare___mf_0_camstack_mf_1_types__loadShare__.js-Cv5McbTI.mjs} +1 -1
  29. package/dist/stream-broker/{_virtual_mf___mfe_internal__addon_stream_broker_widgets__loadShare___mf_0_camstack_mf_1_ui_mf_2_library__loadShare__.js-CBxobiZW.mjs → _virtual_mf___mfe_internal__addon_stream_broker_widgets__loadShare___mf_0_camstack_mf_1_ui_mf_2_library__loadShare__.js-Dj_qoc1e.mjs} +1 -1
  30. package/dist/stream-broker/demux-worker-child.js +1 -1
  31. package/dist/stream-broker/demux-worker-child.mjs +1 -1
  32. package/dist/stream-broker/{hostInit-CZig_taJ.mjs → hostInit-C-2Eo_nr.mjs} +3 -3
  33. package/dist/stream-broker/index.js +4 -4
  34. package/dist/stream-broker/index.mjs +4 -4
  35. package/dist/stream-broker/remoteEntry.js +1 -1
  36. package/dist/{worker-protocol-DCsi4YS1.js → worker-protocol-CXsdriRX.js} +1 -1
  37. package/dist/{worker-protocol-C0R1DDC0.mjs → worker-protocol-_7zrToTo.mjs} +1 -1
  38. package/package.json +1 -1
@@ -2,8 +2,8 @@ Object.defineProperties(exports, {
2
2
  __esModule: { value: true },
3
3
  [Symbol.toStringTag]: { value: "Module" }
4
4
  });
5
- const require_dist = require("../dist-HG5geL9t.js");
6
- const require_process_memory = require("../process-memory-CoCSce63.js");
5
+ const require_dist = require("../dist-CBa1j3On.js");
6
+ const require_process_memory = require("../process-memory-CmeKr_MZ.js");
7
7
  let node_fs = require("node:fs");
8
8
  node_fs = require_dist.__toESM(node_fs);
9
9
  let node_path = require("node:path");
@@ -1,6 +1,6 @@
1
1
  import { n as __require } from "../chunk-DnnnRqeS.mjs";
2
- import { Et as errMsg, M as audioAnalyzerCapability, Nt as BaseAddon, Rt as hydrateSchema, S as PoolMemoryWatchdog, j as audioAnalysisCapability, n as AUDIO_BACKEND_CHOICES, rt as mapAudioLabelToMacro, s as DEFAULT_AUDIO_ANALYZER_CONFIG, v as HF_BASE_URL, yt as resolvePoolMemoryPolicy } from "../dist-mYDK58Jp.mjs";
3
- import { n as pickNodePlatformArch, t as readProcessMemory } from "../process-memory-BDHR3lxe.mjs";
2
+ import { Dt as errMsg, M as audioAnalyzerCapability, Pt as BaseAddon, S as PoolMemoryWatchdog, bt as resolvePoolMemoryPolicy, j as audioAnalysisCapability, n as AUDIO_BACKEND_CHOICES, rt as mapAudioLabelToMacro, s as DEFAULT_AUDIO_ANALYZER_CONFIG, v as HF_BASE_URL, zt as hydrateSchema } from "../dist-Y4BsF_EC.mjs";
3
+ import { n as pickNodePlatformArch, t as readProcessMemory } from "../process-memory-DeO2OZ3-.mjs";
4
4
  import * as fs from "node:fs";
5
5
  import * as path$1 from "node:path";
6
6
  import { downloadFile } from "@camstack/system/addon-utils";
@@ -1,4 +1,4 @@
1
- const require_dist = require("./dist-HG5geL9t.js");
1
+ const require_dist = require("./dist-CBa1j3On.js");
2
2
  let node_crypto = require("node:crypto");
3
3
  //#region src/detection-pipeline/registry/model-catalogs.ts
4
4
  var HF_REPO = "camstack/camstack-models";
@@ -1,4 +1,4 @@
1
- import { N as audioKindId, Q as hfModelUrl, a as COCO_80_LABELS, o as COCO_TO_MACRO, r as AUDIO_MACRO_LABELS } from "./dist-mYDK58Jp.mjs";
1
+ import { N as audioKindId, Q as hfModelUrl, a as COCO_80_LABELS, o as COCO_TO_MACRO, r as AUDIO_MACRO_LABELS } from "./dist-Y4BsF_EC.mjs";
2
2
  import { randomUUID } from "node:crypto";
3
3
  //#region src/detection-pipeline/registry/model-catalogs.ts
4
4
  var HF_REPO = "camstack/camstack-models";
@@ -2,12 +2,12 @@ Object.defineProperties(exports, {
2
2
  __esModule: { value: true },
3
3
  [Symbol.toStringTag]: { value: "Module" }
4
4
  });
5
- const require_dist = require("../dist-HG5geL9t.js");
6
- const require_node = require("../node--my8JTOW.js");
7
- const require_default_detection_model = require("../default-detection-model-CJdc8j83.js");
8
- const require_lazy_sharp = require("../lazy-sharp-DmAwZ0s9.js");
5
+ const require_dist = require("../dist-CBa1j3On.js");
6
+ const require_node = require("../node-C-B8VuGi.js");
7
+ const require_default_detection_model = require("../default-detection-model-CM-8U0Bb.js");
8
+ const require_lazy_sharp = require("../lazy-sharp-CS5WE9mI.js");
9
9
  const require_event_loop_stall_monitor = require("../event-loop-stall-monitor-DaUBcb13.js");
10
- const require_process_memory = require("../process-memory-CoCSce63.js");
10
+ const require_process_memory = require("../process-memory-CmeKr_MZ.js");
11
11
  let node_os = require("node:os");
12
12
  node_os = require_dist.__toESM(node_os);
13
13
  let node_fs = require("node:fs");
@@ -1,10 +1,10 @@
1
1
  import { n as __require } from "../chunk-DnnnRqeS.mjs";
2
- import { $ as inferModelProvider, B as defaultDeviceFor$1, Et as errMsg, G as detectionPipelineCapability, Ht as nodePin, J as enumerateInferenceDevices, Jt as array, Kt as sleep, Lt as createEvent, Nt as BaseAddon, Rt as hydrateSchema, S as PoolMemoryWatchdog, Ut as parseJsonUnknown, X as evaluateZoneRules, _t as resolveClusterStepModelId, c as DEFAULT_CLUSTER_STEP_MODELS, ct as pickClusterStepModels, en as object, ft as pipelineExecutorCapability, in as EventCategory, k as YAMNET_TO_MACRO, l as DEFAULT_CLUSTER_STEP_SETTINGS, lt as pickClusterStepSettings, m as DEVICE_BACKEND_TO_FORMAT, nn as string, ot as overlayClusterStepSettings, rn as union, t as APPLE_SA_TO_MACRO, tt as loadContributionCapability, wt as supportedRuntimes$1, xt as runtimeDevices$1, yt as resolvePoolMemoryPolicy } from "../dist-mYDK58Jp.mjs";
3
- import { a as readProcessCost } from "../node-xRsaPwBa.mjs";
4
- import { a as ALL_PIPELINE_STEPS, c as getStep, d as landmarkPrecisionVerdict, l as getStepDefinition, n as resolveDefaultDetectionModel, o as ALL_STEPS, r as localFrameRegistry, s as getDefaultModelForFormat, u as resolveModelForFormat } from "../default-detection-model-BGBAmtEp.mjs";
2
+ import { $ as inferModelProvider, B as defaultDeviceFor$1, Dt as errMsg, G as detectionPipelineCapability, J as enumerateInferenceDevices, Pt as BaseAddon, Rt as createEvent, S as PoolMemoryWatchdog, St as runtimeDevices$1, Tt as supportedRuntimes$1, Ut as nodePin, Wt as parseJsonUnknown, X as evaluateZoneRules, Yt as array, an as union, bt as resolvePoolMemoryPolicy, c as DEFAULT_CLUSTER_STEP_MODELS, in as string, k as YAMNET_TO_MACRO, l as DEFAULT_CLUSTER_STEP_SETTINGS, lt as pickClusterStepModels, m as DEVICE_BACKEND_TO_FORMAT, on as EventCategory, pt as pipelineExecutorCapability, qt as sleep, st as overlayClusterStepSettings, t as APPLE_SA_TO_MACRO, tn as object, tt as loadContributionCapability, ut as pickClusterStepSettings, vt as resolveClusterStepModelId, zt as hydrateSchema } from "../dist-Y4BsF_EC.mjs";
3
+ import { a as readProcessCost } from "../node-B5ouEQYN.mjs";
4
+ import { a as ALL_PIPELINE_STEPS, c as getStep, d as landmarkPrecisionVerdict, l as getStepDefinition, n as resolveDefaultDetectionModel, o as ALL_STEPS, r as localFrameRegistry, s as getDefaultModelForFormat, u as resolveModelForFormat } from "../default-detection-model-CplzzTmN.mjs";
5
5
  import { t as getSharp } from "../lazy-sharp-DXsqwpph.mjs";
6
6
  import { n as startEventLoopStallMonitor } from "../event-loop-stall-monitor-DXLNBMkY.mjs";
7
- import { n as pickNodePlatformArch, t as readProcessMemory } from "../process-memory-BDHR3lxe.mjs";
7
+ import { n as pickNodePlatformArch, t as readProcessMemory } from "../process-memory-DeO2OZ3-.mjs";
8
8
  import * as os from "node:os";
9
9
  import * as fs from "node:fs";
10
10
  import * as path$1 from "node:path";
@@ -9110,17 +9110,29 @@ var HHMM = /^([01]\d|2[0-3]):[0-5]\d$/;
9110
9110
  /**
9111
9111
  * DERIVED per-camera storage summary — the single field cheap consumers read
9112
9112
  * (the viewer's status dot, the camera list) instead of walking `bands`:
9113
- * - `off` — no band covers the camera (or it is disabled).
9114
- * - `events` — every band records around triggers only.
9115
- * - `continuous` — at least one band records continuously.
9116
- *
9117
- * NEVER authored: the recorder stamps it from the authoritative `bands` on
9118
- * every save (`activeModeForConfig`). Writing it has no effect.
9113
+ * - `off` — no band covers the camera (or it is disabled).
9114
+ * - `events` — every band records around triggers only.
9115
+ * - `continuous` — at least one band records continuously.
9116
+ * - `on-device-decision`— the DEVICE decides: recording runs for as long as the
9117
+ * camera raises its own `recording-signal` level (a robot that cleans). There
9118
+ * is no schedule to author, because there is no hour to program — see
9119
+ * {@link RecordingConfigSchema}`.deviceDecision`.
9120
+ *
9121
+ * NEVER authored: the recorder stamps it from the authoritative intent
9122
+ * (`bands` + `deviceDecision`) on every save (`activeModeForConfig`). Writing it
9123
+ * has no effect.
9124
+ *
9125
+ * `on-device-decision` is named for WHO decides, not for how the recording is
9126
+ * requested. `on-demand` was rejected: in this repo's vocabulary a "demand" is
9127
+ * something the operator makes (the live gate is the recorder's own "demand
9128
+ * window"), and a knob whose name suggests the operator starts it while the
9129
+ * device actually does is the D62 shape — a control nobody can predict.
9119
9130
  */
9120
9131
  var RecordingStorageModeSchema = _enum([
9121
9132
  "off",
9122
9133
  "events",
9123
- "continuous"
9134
+ "continuous",
9135
+ "on-device-decision"
9124
9136
  ]);
9125
9137
  /**
9126
9138
  * Le macro classi che possono aprire una finestra di registrazione — le stesse
@@ -9170,22 +9182,7 @@ var RecordingTriggersSchema = object({
9170
9182
  * il livello: un contatto trovato già aperto al riavvio del runner non fa
9171
9183
  * registrare.
9172
9184
  */
9173
- sensorDeviceIds: array(number().int().positive()).min(1).max(16).refine(noDuplicates, { message: "sensorDeviceIds must not repeat a device" }).optional(),
9174
- /**
9175
- * La camera registra per tutta la durata del SEGNALE che lei stessa
9176
- * pubblica — la cap `recording-signal` (`active: true` mentre il device è in
9177
- * funzione: un robot che pulisce). È un LIVELLO, non un fronte: la finestra
9178
- * resta aperta finché il segnale è alto e si chiude `postBufferSec` dopo la
9179
- * caduta, così una pulizia di quaranta minuti è UNA clip.
9180
- *
9181
- * Non nomina un device: il segnale è della camera stessa, tenuto fresco dal
9182
- * suo provider (D224); il recorder lo ascolta su `DeviceStateChanged` e lo
9183
- * riconcilia leggendo la slice via RPC, con un tetto oltre il quale un
9184
- * segnale mai abbassato (un evento perso) non può tenere aperta una
9185
- * registrazione (D11). Vedi `recorder/addon/band-decision.ts`
9186
- * (`holdTrigger` / `releaseTrigger`).
9187
- */
9188
- deviceSignal: boolean().optional()
9185
+ sensorDeviceIds: array(number().int().positive()).min(1).max(16).refine(noDuplicates, { message: "sensorDeviceIds must not repeat a device" }).optional()
9189
9186
  });
9190
9187
  /**
9191
9188
  * Mode of a single recording band — the recorder per-band vocabulary.
@@ -9303,8 +9300,29 @@ var RecordingConfigSchema = object({
9303
9300
  * "off" is the absence of a covering band, never a band value.
9304
9301
  */
9305
9302
  bands: array(RecordingBandSchema).default([]),
9303
+ /**
9304
+ * THE device-decided intent: record for as long as the camera itself raises
9305
+ * `recording-signal` (`active: true` while the device is in function — a
9306
+ * robot that cleans). AUTHORED, unlike `mode`, and the only authored
9307
+ * recording intent that is not a band.
9308
+ *
9309
+ * It carries NO schedule on purpose. A band is an HOUR, and this feature has
9310
+ * no hour to program: the device decides. What it costs the operator is one
9311
+ * flag — "this camera can record on its own" — and what it buys is the same
9312
+ * hold/release the recorder already implements (D371, `holdTrigger` /
9313
+ * `releaseTrigger`): the window opens on the rise, stays open for the whole
9314
+ * job however long it is, and closes one pad after the fall.
9315
+ *
9316
+ * EXCLUSIVE with `bands` (below): two authorities deciding when the same
9317
+ * camera records is the D62 failure. `off` remains `enabled: false`, so an
9318
+ * operator switching this camera off is REPORTED off, never as broken.
9319
+ */
9320
+ deviceDecision: boolean().optional(),
9306
9321
  retention: RecordingRetentionSchema.optional()
9307
- }).strict();
9322
+ }).strict().refine((config) => config.deviceDecision !== true || config.bands.length === 0, {
9323
+ message: "deviceDecision is a whole-config mode and carries no schedule: it cannot be combined with bands",
9324
+ path: ["bands"]
9325
+ });
9308
9326
  /**
9309
9327
  * Derive the {@link RecordingStorageModeSchema} summary from the authoritative
9310
9328
  * bands: `continuous` when any band records continuously, `events` when a band
@@ -9317,7 +9335,9 @@ var RecordingConfigSchema = object({
9317
9335
  * bug this field was added to fix.
9318
9336
  */
9319
9337
  function deriveRecordingMode(config) {
9320
- if (!config.enabled || config.bands.length === 0) return "off";
9338
+ if (!config.enabled) return "off";
9339
+ if (config.deviceDecision === true) return "on-device-decision";
9340
+ if (config.bands.length === 0) return "off";
9321
9341
  if (config.bands.some((band) => band.mode === "continuous")) return "continuous";
9322
9342
  return "events";
9323
9343
  }
@@ -9345,6 +9365,85 @@ function resolveRecordingProfiles(assigned, override) {
9345
9365
  const preferred = assigned.filter((profile) => DEFAULT_RECORDING_PROFILES.includes(profile));
9346
9366
  return preferred.length > 0 ? preferred : [...assigned];
9347
9367
  }
9368
+ /** Trigger keys that survive D380 — a band carrying one of these is a real band. */
9369
+ var SURVIVING_TRIGGER_KEYS = [
9370
+ "motion",
9371
+ "audioThresholdDbfs",
9372
+ "objectClasses",
9373
+ "sensorDeviceIds"
9374
+ ];
9375
+ function isRecord$1(value) {
9376
+ return typeof value === "object" && value !== null && !Array.isArray(value);
9377
+ }
9378
+ function listensToLegacySignal(band) {
9379
+ return isRecord$1(band) && isRecord$1(band.triggers) && band.triggers.deviceSignal === true;
9380
+ }
9381
+ function hasSurvivingTrigger(band) {
9382
+ const triggers = band.triggers;
9383
+ if (!isRecord$1(triggers)) return false;
9384
+ return SURVIVING_TRIGGER_KEYS.some((key) => triggers[key] !== void 0);
9385
+ }
9386
+ function withoutLegacySignal(band) {
9387
+ const triggers = band.triggers;
9388
+ if (!isRecord$1(triggers)) return band;
9389
+ const { deviceSignal: _retired, ...rest } = triggers;
9390
+ return {
9391
+ ...band,
9392
+ triggers: rest
9393
+ };
9394
+ }
9395
+ /**
9396
+ * Turn a config stored under D371 (`bands[].triggers.deviceSignal: true`) into
9397
+ * a D380 one (`deviceDecision: true`, no bands). Pure, total and IDEMPOTENT —
9398
+ * a row with no legacy key comes back as the SAME reference, `migrated: false`.
9399
+ *
9400
+ * ## Why the schema cannot be left to do this
9401
+ *
9402
+ * `RecordingTriggersSchema` is a non-strict `z.object`, so the retired key is
9403
+ * SILENTLY STRIPPED on read. The camera whose only trigger it was would parse
9404
+ * cleanly into an `events` band that lists nothing — "enabled, and records
9405
+ * nothing, forever", the exact shape `eventsBandCanEverDemand` exists to shout
9406
+ * about, reached without a single line in the log. On the reference hub that is
9407
+ * camera 4374, the one camera an operator had configured by hand.
9408
+ *
9409
+ * `enabled` is carried through untouched: a camera the operator had switched
9410
+ * OFF comes out of a migration still off (D62).
9411
+ */
9412
+ function migrateLegacyDeviceSignalConfig(raw) {
9413
+ const unchanged = {
9414
+ value: raw,
9415
+ migrated: false,
9416
+ strippedOnly: false
9417
+ };
9418
+ if (!isRecord$1(raw) || !Array.isArray(raw.bands)) return unchanged;
9419
+ if (!raw.bands.some(listensToLegacySignal)) return unchanged;
9420
+ const kept = [];
9421
+ for (const band of raw.bands) {
9422
+ if (!listensToLegacySignal(band) || !isRecord$1(band)) {
9423
+ kept.push(band);
9424
+ continue;
9425
+ }
9426
+ if (hasSurvivingTrigger(band)) kept.push(withoutLegacySignal(band));
9427
+ }
9428
+ if (kept.length > 0) return {
9429
+ value: {
9430
+ ...raw,
9431
+ bands: kept
9432
+ },
9433
+ migrated: false,
9434
+ strippedOnly: true
9435
+ };
9436
+ const { mode: _derived, ...rest } = raw;
9437
+ return {
9438
+ value: {
9439
+ ...rest,
9440
+ bands: [],
9441
+ deviceDecision: true
9442
+ },
9443
+ migrated: true,
9444
+ strippedOnly: false
9445
+ };
9446
+ }
9348
9447
  /**
9349
9448
  * Entity-relocation job state (storage entity-routing spec, Phase 4).
9350
9449
  *
@@ -23320,11 +23419,7 @@ var CameraAudioStatusSchema = object({
23320
23419
  });
23321
23420
  /** Recording block — null when no recording cap is active for this device. */
23322
23421
  var CameraRecordingStatusSchema = object({
23323
- mode: _enum([
23324
- "off",
23325
- "continuous",
23326
- "events"
23327
- ]),
23422
+ mode: RecordingStorageModeSchema,
23328
23423
  active: boolean(),
23329
23424
  storageBytes: number()
23330
23425
  });
@@ -29899,11 +29994,10 @@ DeviceType.Camera, DeviceType.Sensor, DeviceType.Switch, method(object({ deviceI
29899
29994
  var RecordingStatusSchema = object({
29900
29995
  deviceId: number(),
29901
29996
  enabled: boolean(),
29902
- activeMode: _enum([
29903
- "off",
29904
- "continuous",
29905
- "events"
29906
- ]),
29997
+ /** THE derived storage mode, from the one definition
29998
+ * (`deriveRecordingMode`) — never a second enum. A duplicated list is how
29999
+ * `on-device-decision` could have reached the recorder and not the status. */
30000
+ activeMode: RecordingStorageModeSchema,
29907
30001
  nodeId: string(),
29908
30002
  storageBytes: number()
29909
30003
  });
@@ -42740,6 +42834,12 @@ Object.defineProperty(exports, "maskUrlCredentials", {
42740
42834
  return maskUrlCredentials;
42741
42835
  }
42742
42836
  });
42837
+ Object.defineProperty(exports, "migrateLegacyDeviceSignalConfig", {
42838
+ enumerable: true,
42839
+ get: function() {
42840
+ return migrateLegacyDeviceSignalConfig;
42841
+ }
42842
+ });
42743
42843
  Object.defineProperty(exports, "motionDetectionCapability", {
42744
42844
  enumerable: true,
42745
42845
  get: function() {
@@ -42824,6 +42924,12 @@ Object.defineProperty(exports, "pipelineRunnerCapability", {
42824
42924
  return pipelineRunnerCapability;
42825
42925
  }
42826
42926
  });
42927
+ Object.defineProperty(exports, "preprocess", {
42928
+ enumerable: true,
42929
+ get: function() {
42930
+ return preprocess;
42931
+ }
42932
+ });
42827
42933
  Object.defineProperty(exports, "record", {
42828
42934
  enumerable: true,
42829
42935
  get: function() {
@@ -9087,17 +9087,29 @@ var HHMM = /^([01]\d|2[0-3]):[0-5]\d$/;
9087
9087
  /**
9088
9088
  * DERIVED per-camera storage summary — the single field cheap consumers read
9089
9089
  * (the viewer's status dot, the camera list) instead of walking `bands`:
9090
- * - `off` — no band covers the camera (or it is disabled).
9091
- * - `events` — every band records around triggers only.
9092
- * - `continuous` — at least one band records continuously.
9093
- *
9094
- * NEVER authored: the recorder stamps it from the authoritative `bands` on
9095
- * every save (`activeModeForConfig`). Writing it has no effect.
9090
+ * - `off` — no band covers the camera (or it is disabled).
9091
+ * - `events` — every band records around triggers only.
9092
+ * - `continuous` — at least one band records continuously.
9093
+ * - `on-device-decision`— the DEVICE decides: recording runs for as long as the
9094
+ * camera raises its own `recording-signal` level (a robot that cleans). There
9095
+ * is no schedule to author, because there is no hour to program — see
9096
+ * {@link RecordingConfigSchema}`.deviceDecision`.
9097
+ *
9098
+ * NEVER authored: the recorder stamps it from the authoritative intent
9099
+ * (`bands` + `deviceDecision`) on every save (`activeModeForConfig`). Writing it
9100
+ * has no effect.
9101
+ *
9102
+ * `on-device-decision` is named for WHO decides, not for how the recording is
9103
+ * requested. `on-demand` was rejected: in this repo's vocabulary a "demand" is
9104
+ * something the operator makes (the live gate is the recorder's own "demand
9105
+ * window"), and a knob whose name suggests the operator starts it while the
9106
+ * device actually does is the D62 shape — a control nobody can predict.
9096
9107
  */
9097
9108
  var RecordingStorageModeSchema = _enum([
9098
9109
  "off",
9099
9110
  "events",
9100
- "continuous"
9111
+ "continuous",
9112
+ "on-device-decision"
9101
9113
  ]);
9102
9114
  /**
9103
9115
  * Le macro classi che possono aprire una finestra di registrazione — le stesse
@@ -9147,22 +9159,7 @@ var RecordingTriggersSchema = object({
9147
9159
  * il livello: un contatto trovato già aperto al riavvio del runner non fa
9148
9160
  * registrare.
9149
9161
  */
9150
- sensorDeviceIds: array(number().int().positive()).min(1).max(16).refine(noDuplicates, { message: "sensorDeviceIds must not repeat a device" }).optional(),
9151
- /**
9152
- * La camera registra per tutta la durata del SEGNALE che lei stessa
9153
- * pubblica — la cap `recording-signal` (`active: true` mentre il device è in
9154
- * funzione: un robot che pulisce). È un LIVELLO, non un fronte: la finestra
9155
- * resta aperta finché il segnale è alto e si chiude `postBufferSec` dopo la
9156
- * caduta, così una pulizia di quaranta minuti è UNA clip.
9157
- *
9158
- * Non nomina un device: il segnale è della camera stessa, tenuto fresco dal
9159
- * suo provider (D224); il recorder lo ascolta su `DeviceStateChanged` e lo
9160
- * riconcilia leggendo la slice via RPC, con un tetto oltre il quale un
9161
- * segnale mai abbassato (un evento perso) non può tenere aperta una
9162
- * registrazione (D11). Vedi `recorder/addon/band-decision.ts`
9163
- * (`holdTrigger` / `releaseTrigger`).
9164
- */
9165
- deviceSignal: boolean().optional()
9162
+ sensorDeviceIds: array(number().int().positive()).min(1).max(16).refine(noDuplicates, { message: "sensorDeviceIds must not repeat a device" }).optional()
9166
9163
  });
9167
9164
  /**
9168
9165
  * Mode of a single recording band — the recorder per-band vocabulary.
@@ -9280,8 +9277,29 @@ var RecordingConfigSchema = object({
9280
9277
  * "off" is the absence of a covering band, never a band value.
9281
9278
  */
9282
9279
  bands: array(RecordingBandSchema).default([]),
9280
+ /**
9281
+ * THE device-decided intent: record for as long as the camera itself raises
9282
+ * `recording-signal` (`active: true` while the device is in function — a
9283
+ * robot that cleans). AUTHORED, unlike `mode`, and the only authored
9284
+ * recording intent that is not a band.
9285
+ *
9286
+ * It carries NO schedule on purpose. A band is an HOUR, and this feature has
9287
+ * no hour to program: the device decides. What it costs the operator is one
9288
+ * flag — "this camera can record on its own" — and what it buys is the same
9289
+ * hold/release the recorder already implements (D371, `holdTrigger` /
9290
+ * `releaseTrigger`): the window opens on the rise, stays open for the whole
9291
+ * job however long it is, and closes one pad after the fall.
9292
+ *
9293
+ * EXCLUSIVE with `bands` (below): two authorities deciding when the same
9294
+ * camera records is the D62 failure. `off` remains `enabled: false`, so an
9295
+ * operator switching this camera off is REPORTED off, never as broken.
9296
+ */
9297
+ deviceDecision: boolean().optional(),
9283
9298
  retention: RecordingRetentionSchema.optional()
9284
- }).strict();
9299
+ }).strict().refine((config) => config.deviceDecision !== true || config.bands.length === 0, {
9300
+ message: "deviceDecision is a whole-config mode and carries no schedule: it cannot be combined with bands",
9301
+ path: ["bands"]
9302
+ });
9285
9303
  /**
9286
9304
  * Derive the {@link RecordingStorageModeSchema} summary from the authoritative
9287
9305
  * bands: `continuous` when any band records continuously, `events` when a band
@@ -9294,7 +9312,9 @@ var RecordingConfigSchema = object({
9294
9312
  * bug this field was added to fix.
9295
9313
  */
9296
9314
  function deriveRecordingMode(config) {
9297
- if (!config.enabled || config.bands.length === 0) return "off";
9315
+ if (!config.enabled) return "off";
9316
+ if (config.deviceDecision === true) return "on-device-decision";
9317
+ if (config.bands.length === 0) return "off";
9298
9318
  if (config.bands.some((band) => band.mode === "continuous")) return "continuous";
9299
9319
  return "events";
9300
9320
  }
@@ -9322,6 +9342,85 @@ function resolveRecordingProfiles(assigned, override) {
9322
9342
  const preferred = assigned.filter((profile) => DEFAULT_RECORDING_PROFILES.includes(profile));
9323
9343
  return preferred.length > 0 ? preferred : [...assigned];
9324
9344
  }
9345
+ /** Trigger keys that survive D380 — a band carrying one of these is a real band. */
9346
+ var SURVIVING_TRIGGER_KEYS = [
9347
+ "motion",
9348
+ "audioThresholdDbfs",
9349
+ "objectClasses",
9350
+ "sensorDeviceIds"
9351
+ ];
9352
+ function isRecord$1(value) {
9353
+ return typeof value === "object" && value !== null && !Array.isArray(value);
9354
+ }
9355
+ function listensToLegacySignal(band) {
9356
+ return isRecord$1(band) && isRecord$1(band.triggers) && band.triggers.deviceSignal === true;
9357
+ }
9358
+ function hasSurvivingTrigger(band) {
9359
+ const triggers = band.triggers;
9360
+ if (!isRecord$1(triggers)) return false;
9361
+ return SURVIVING_TRIGGER_KEYS.some((key) => triggers[key] !== void 0);
9362
+ }
9363
+ function withoutLegacySignal(band) {
9364
+ const triggers = band.triggers;
9365
+ if (!isRecord$1(triggers)) return band;
9366
+ const { deviceSignal: _retired, ...rest } = triggers;
9367
+ return {
9368
+ ...band,
9369
+ triggers: rest
9370
+ };
9371
+ }
9372
+ /**
9373
+ * Turn a config stored under D371 (`bands[].triggers.deviceSignal: true`) into
9374
+ * a D380 one (`deviceDecision: true`, no bands). Pure, total and IDEMPOTENT —
9375
+ * a row with no legacy key comes back as the SAME reference, `migrated: false`.
9376
+ *
9377
+ * ## Why the schema cannot be left to do this
9378
+ *
9379
+ * `RecordingTriggersSchema` is a non-strict `z.object`, so the retired key is
9380
+ * SILENTLY STRIPPED on read. The camera whose only trigger it was would parse
9381
+ * cleanly into an `events` band that lists nothing — "enabled, and records
9382
+ * nothing, forever", the exact shape `eventsBandCanEverDemand` exists to shout
9383
+ * about, reached without a single line in the log. On the reference hub that is
9384
+ * camera 4374, the one camera an operator had configured by hand.
9385
+ *
9386
+ * `enabled` is carried through untouched: a camera the operator had switched
9387
+ * OFF comes out of a migration still off (D62).
9388
+ */
9389
+ function migrateLegacyDeviceSignalConfig(raw) {
9390
+ const unchanged = {
9391
+ value: raw,
9392
+ migrated: false,
9393
+ strippedOnly: false
9394
+ };
9395
+ if (!isRecord$1(raw) || !Array.isArray(raw.bands)) return unchanged;
9396
+ if (!raw.bands.some(listensToLegacySignal)) return unchanged;
9397
+ const kept = [];
9398
+ for (const band of raw.bands) {
9399
+ if (!listensToLegacySignal(band) || !isRecord$1(band)) {
9400
+ kept.push(band);
9401
+ continue;
9402
+ }
9403
+ if (hasSurvivingTrigger(band)) kept.push(withoutLegacySignal(band));
9404
+ }
9405
+ if (kept.length > 0) return {
9406
+ value: {
9407
+ ...raw,
9408
+ bands: kept
9409
+ },
9410
+ migrated: false,
9411
+ strippedOnly: true
9412
+ };
9413
+ const { mode: _derived, ...rest } = raw;
9414
+ return {
9415
+ value: {
9416
+ ...rest,
9417
+ bands: [],
9418
+ deviceDecision: true
9419
+ },
9420
+ migrated: true,
9421
+ strippedOnly: false
9422
+ };
9423
+ }
9325
9424
  /**
9326
9425
  * Entity-relocation job state (storage entity-routing spec, Phase 4).
9327
9426
  *
@@ -23297,11 +23396,7 @@ var CameraAudioStatusSchema = object({
23297
23396
  });
23298
23397
  /** Recording block — null when no recording cap is active for this device. */
23299
23398
  var CameraRecordingStatusSchema = object({
23300
- mode: _enum([
23301
- "off",
23302
- "continuous",
23303
- "events"
23304
- ]),
23399
+ mode: RecordingStorageModeSchema,
23305
23400
  active: boolean(),
23306
23401
  storageBytes: number()
23307
23402
  });
@@ -29876,11 +29971,10 @@ DeviceType.Camera, DeviceType.Sensor, DeviceType.Switch, method(object({ deviceI
29876
29971
  var RecordingStatusSchema = object({
29877
29972
  deviceId: number(),
29878
29973
  enabled: boolean(),
29879
- activeMode: _enum([
29880
- "off",
29881
- "continuous",
29882
- "events"
29883
- ]),
29974
+ /** THE derived storage mode, from the one definition
29975
+ * (`deriveRecordingMode`) — never a second enum. A duplicated list is how
29976
+ * `on-device-decision` could have reached the recorder and not the status. */
29977
+ activeMode: RecordingStorageModeSchema,
29884
29978
  nodeId: string(),
29885
29979
  storageBytes: number()
29886
29980
  });
@@ -42219,4 +42313,4 @@ function enumerateInferenceDevices(hw) {
42219
42313
  return out;
42220
42314
  }
42221
42315
  //#endregion
42222
- export { inferModelProvider as $, number as $t, addonWidgetsSourceCapability as A, invocationFromEncodeProfile as At, defaultDeviceFor as B, makeProfileBrokerId as Bt, RATE_CONTROL_RELAXED as C, streamBrokerCapability as Ct, RecordingSignalStatusSchema as D, AUDIO_PRESETS as Dt, RecordingConfigSchema as E, errMsg as Et, cameraStreamsCapability as F, DeviceFeature as Ft, detectionPipelineCapability as G, selectAssignedProfileSlots as Gt, deriveBatteryPresence as H, nodePin as Ht, createHwAccelCache as I, DeviceType as It, enumerateInferenceDevices as J, array as Jt, egressTranscodeSharingKey as K, sleep as Kt, createLogChannelsProvider as L, createEvent as Lt, audioAnalyzerCapability as M, BOOT_RECOVERY_BACKOFF_MS as Mt, audioKindId as N, BaseAddon as Nt, RingBuffer as O, Fmp4BoxSplitter as Ot, batteryCapability as P, CAM_PROFILE_ORDER as Pt, hfModelUrl as Q, literal as Qt, customAction as R, hydrateSchema as Rt, PoolMemoryWatchdog as S, storageEvictableCapability as St, RECORDING_EXPORT_MAX_READ_BYTES as T, webrtcSessionCapability as Tt, deriveDetailCropRect as U, parseJsonUnknown as Ut, defineCustomActions as V, makeSourceBrokerId as Vt, deriveRecordingMode as W, parseProfileBrokerId as Wt, evaluateZoneRules as X, discriminatedUnion as Xt, evaluateSensorEdge as Y, boolean as Yt, failureContributionCapability as Z, lazy as Zt, FailureCounters as _, resolveClusterStepModelId as _t, COCO_80_LABELS as a, motionDetectionCapability as at, NativeLeaseSettingsSchema as b, resolveRecordingProfiles as bt, DEFAULT_CLUSTER_STEP_MODELS as c, pickClusterStepModels as ct, DEFAULT_EVENTS_BAND_BUFFER_SEC as d, pickNativeLeaseOverride as dt, object as en, isFirstLevelMacroClass as et, DEFAULT_FIRST_SIGHTING_FRESHNESS_MS as f, pipelineExecutorCapability as ft, ExportRecordSchema as g, recordingSignalCapability as gt, EncodeProfileSchema as h, recordingExportCapability as ht, BatteryStatusSchema as i, EventCategory as in, maskUrlCredentials as it, audioAnalysisCapability as j, isSoftwareDecode as jt, YAMNET_TO_MACRO as k, buildFfmpegArgs as kt, DEFAULT_CLUSTER_STEP_SETTINGS as l, pickClusterStepSettings as lt, DEVICE_BACKEND_TO_FORMAT as m, recordingCapability as mt, AUDIO_BACKEND_CHOICES as n, string as nn, logChannelsCapability as nt, COCO_TO_MACRO as o, overlayClusterStepSettings as ot, DEFAULT_NATIVE_LEASE_SETTINGS as p, pipelineRunnerCapability as pt, egressTransportFromRequest as q, _enum as qt, AUDIO_MACRO_LABELS as r, union as rn, mapAudioLabelToMacro as rt, DEFAULT_AUDIO_ANALYZER_CONFIG as s, parseProcStatus as st, APPLE_SA_TO_MACRO as t, record as tn, loadContributionCapability as tt, DEFAULT_DETAIL_CROP_CONVENTION as u, pickDetailCropConvention as ut, HF_BASE_URL as v, resolveEgressDecodeHwAccel as vt, RATE_CONTROL_TIGHT as w, supportedRuntimes as wt, OpsLogEntrySchema as x, runtimeDevices as xt, NativeLeaseAdmissionSchema as y, resolvePoolMemoryPolicy as yt, declareLogChannel as z, isEvent as zt };
42316
+ export { inferModelProvider as $, literal as $t, addonWidgetsSourceCapability as A, buildFfmpegArgs as At, defaultDeviceFor as B, isEvent as Bt, RATE_CONTROL_RELAXED as C, storageEvictableCapability as Ct, RecordingSignalStatusSchema as D, errMsg as Dt, RecordingConfigSchema as E, webrtcSessionCapability as Et, cameraStreamsCapability as F, CAM_PROFILE_ORDER as Ft, detectionPipelineCapability as G, parseProfileBrokerId as Gt, deriveBatteryPresence as H, makeSourceBrokerId as Ht, createHwAccelCache as I, DeviceFeature as It, enumerateInferenceDevices as J, _enum as Jt, egressTranscodeSharingKey as K, selectAssignedProfileSlots as Kt, createLogChannelsProvider as L, DeviceType as Lt, audioAnalyzerCapability as M, isSoftwareDecode as Mt, audioKindId as N, BOOT_RECOVERY_BACKOFF_MS as Nt, RingBuffer as O, AUDIO_PRESETS as Ot, batteryCapability as P, BaseAddon as Pt, hfModelUrl as Q, lazy as Qt, customAction as R, createEvent as Rt, PoolMemoryWatchdog as S, runtimeDevices as St, RECORDING_EXPORT_MAX_READ_BYTES as T, supportedRuntimes as Tt, deriveDetailCropRect as U, nodePin as Ut, defineCustomActions as V, makeProfileBrokerId as Vt, deriveRecordingMode as W, parseJsonUnknown as Wt, evaluateZoneRules as X, boolean as Xt, evaluateSensorEdge as Y, array as Yt, failureContributionCapability as Z, discriminatedUnion as Zt, FailureCounters as _, recordingSignalCapability as _t, COCO_80_LABELS as a, union as an, migrateLegacyDeviceSignalConfig as at, NativeLeaseSettingsSchema as b, resolvePoolMemoryPolicy as bt, DEFAULT_CLUSTER_STEP_MODELS as c, parseProcStatus as ct, DEFAULT_EVENTS_BAND_BUFFER_SEC as d, pickDetailCropConvention as dt, number as en, isFirstLevelMacroClass as et, DEFAULT_FIRST_SIGHTING_FRESHNESS_MS as f, pickNativeLeaseOverride as ft, ExportRecordSchema as g, recordingExportCapability as gt, EncodeProfileSchema as h, recordingCapability as ht, BatteryStatusSchema as i, string as in, maskUrlCredentials as it, audioAnalysisCapability as j, invocationFromEncodeProfile as jt, YAMNET_TO_MACRO as k, Fmp4BoxSplitter as kt, DEFAULT_CLUSTER_STEP_SETTINGS as l, pickClusterStepModels as lt, DEVICE_BACKEND_TO_FORMAT as m, pipelineRunnerCapability as mt, AUDIO_BACKEND_CHOICES as n, preprocess as nn, logChannelsCapability as nt, COCO_TO_MACRO as o, EventCategory as on, motionDetectionCapability as ot, DEFAULT_NATIVE_LEASE_SETTINGS as p, pipelineExecutorCapability as pt, egressTransportFromRequest as q, sleep as qt, AUDIO_MACRO_LABELS as r, record as rn, mapAudioLabelToMacro as rt, DEFAULT_AUDIO_ANALYZER_CONFIG as s, overlayClusterStepSettings as st, APPLE_SA_TO_MACRO as t, object as tn, loadContributionCapability as tt, DEFAULT_DETAIL_CROP_CONVENTION as u, pickClusterStepSettings as ut, HF_BASE_URL as v, resolveClusterStepModelId as vt, RATE_CONTROL_TIGHT as w, streamBrokerCapability as wt, OpsLogEntrySchema as x, resolveRecordingProfiles as xt, NativeLeaseAdmissionSchema as y, resolveEgressDecodeHwAccel as yt, declareLogChannel as z, hydrateSchema as zt };
@@ -1,4 +1,4 @@
1
- const require_dist = require("./dist-HG5geL9t.js");
1
+ const require_dist = require("./dist-CBa1j3On.js");
2
2
  let node_path = require("node:path");
3
3
  node_path = require_dist.__toESM(node_path);
4
4
  let node_url = require("node:url");
@@ -2,8 +2,8 @@ Object.defineProperties(exports, {
2
2
  __esModule: { value: true },
3
3
  [Symbol.toStringTag]: { value: "Module" }
4
4
  });
5
- const require_dist = require("../dist-HG5geL9t.js");
6
- const require_lazy_sharp = require("../lazy-sharp-DmAwZ0s9.js");
5
+ const require_dist = require("../dist-CBa1j3On.js");
6
+ const require_lazy_sharp = require("../lazy-sharp-CS5WE9mI.js");
7
7
  let node_fs = require("node:fs");
8
8
  let node_path = require("node:path");
9
9
  //#region src/motion-wasm/wasm-motion-detector.ts
@@ -1,4 +1,4 @@
1
- import { It as DeviceType, Nt as BaseAddon, Rt as hydrateSchema, X as evaluateZoneRules, at as motionDetectionCapability } from "../dist-mYDK58Jp.mjs";
1
+ import { Lt as DeviceType, Pt as BaseAddon, X as evaluateZoneRules, ot as motionDetectionCapability, zt as hydrateSchema } from "../dist-Y4BsF_EC.mjs";
2
2
  import { t as getSharp } from "../lazy-sharp-DXsqwpph.mjs";
3
3
  import { readFileSync } from "node:fs";
4
4
  import { join } from "node:path";
@@ -1,4 +1,4 @@
1
- import { Et as errMsg, Ot as Fmp4BoxSplitter, jt as isSoftwareDecode, kt as buildFfmpegArgs } from "./dist-mYDK58Jp.mjs";
1
+ import { At as buildFfmpegArgs, Dt as errMsg, Mt as isSoftwareDecode, kt as Fmp4BoxSplitter } from "./dist-Y4BsF_EC.mjs";
2
2
  import { randomUUID } from "node:crypto";
3
3
  import "node:fs";
4
4
  import "node:path";
@@ -1,4 +1,4 @@
1
- const require_dist = require("./dist-HG5geL9t.js");
1
+ const require_dist = require("./dist-CBa1j3On.js");
2
2
  let node_crypto = require("node:crypto");
3
3
  let node_fs = require("node:fs");
4
4
  node_fs = require_dist.__toESM(node_fs, 1);