@camstack/addon-pipeline 1.2.170 → 1.2.172

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/detection-pipeline/index.js +5 -5
  4. package/dist/detection-pipeline/index.mjs +4 -4
  5. package/dist/{dist-CIfo4mG5.mjs → dist-A-CKFNg9.mjs} +172 -4
  6. package/dist/{dist-D1GcKxTl.js → dist-CpmqDTel.js} +172 -4
  7. package/dist/{lazy-sharp-AjtuNBru.js → lazy-sharp-c_IKosOs.js} +1 -1
  8. package/dist/{local-frame-registry-Bd2qxPtO.js → local-frame-registry-CHzo5v0z.js} +1 -1
  9. package/dist/{local-frame-registry-C6p0o5JF.mjs → local-frame-registry-DuEPtfBk.mjs} +1 -1
  10. package/dist/motion-wasm/index.js +2 -2
  11. package/dist/motion-wasm/index.mjs +1 -1
  12. package/dist/{node-COkvb2aY.mjs → node-CNhb6GOd.mjs} +1 -1
  13. package/dist/{node-DnaSxKtp.js → node-DudW4uSe.js} +1 -1
  14. package/dist/pipeline-runner/index.js +63 -6
  15. package/dist/pipeline-runner/index.mjs +62 -5
  16. package/dist/{process-memory-B8yE5D8z.js → process-memory-CcWK6O93.js} +1 -1
  17. package/dist/{process-memory--nGY2kIF.mjs → process-memory-DVPPoQS1.mjs} +1 -1
  18. package/dist/recorder/index.js +97 -13
  19. package/dist/recorder/index.mjs +97 -13
  20. package/dist/{segment-demux-js-CZDoMfuY.mjs → segment-demux-js-B0MPr5g4.mjs} +1 -1
  21. package/dist/{segment-demux-js-CMUyyqQC.js → segment-demux-js-ChcjdSdF.js} +1 -1
  22. package/dist/session-decode/decode-worker-child.js +2 -2
  23. package/dist/session-decode/decode-worker-child.mjs +1 -1
  24. package/dist/stream-broker/_stub.js +2 -2
  25. package/dist/stream-broker/{_virtual_mf-localSharedImportMap___mfe_internal__addon_stream_broker_widgets-Chc5GeFl.mjs → _virtual_mf-localSharedImportMap___mfe_internal__addon_stream_broker_widgets-DDhnhOI4.mjs} +3 -3
  26. package/dist/stream-broker/_virtual_mf___mfe_internal__addon_stream_broker_widgets__loadShare___mf_0_camstack_mf_1_types__loadShare__.js-BVpZlsT7.mjs +26 -0
  27. package/dist/stream-broker/_virtual_mf___mfe_internal__addon_stream_broker_widgets__loadShare___mf_0_camstack_mf_1_ui_mf_2_library__loadShare__.js-CwP-r0hs.mjs +26 -0
  28. package/dist/stream-broker/demux-worker-child.js +1 -1
  29. package/dist/stream-broker/demux-worker-child.mjs +1 -1
  30. package/dist/stream-broker/{hostInit-weZPzKXa.mjs → hostInit-CrI9kLNo.mjs} +3 -3
  31. package/dist/stream-broker/index.js +87 -4
  32. package/dist/stream-broker/index.mjs +87 -4
  33. package/dist/stream-broker/remoteEntry.js +1 -1
  34. package/dist/{worker-protocol-DJLjyeMR.mjs → worker-protocol-BuUyu8aI.mjs} +1 -1
  35. package/dist/{worker-protocol-BzedLkGB.js → worker-protocol-IC_mPIhk.js} +1 -1
  36. package/package.json +8 -1
  37. package/dist/stream-broker/_virtual_mf___mfe_internal__addon_stream_broker_widgets__loadShare___mf_0_camstack_mf_1_types__loadShare__.js-BjYSKqCM.mjs +0 -26
  38. package/dist/stream-broker/_virtual_mf___mfe_internal__addon_stream_broker_widgets__loadShare___mf_0_camstack_mf_1_ui_mf_2_library__loadShare__.js-E0nHxt6U.mjs +0 -26
@@ -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-D1GcKxTl.js");
6
- const require_process_memory = require("../process-memory-B8yE5D8z.js");
5
+ const require_dist = require("../dist-CpmqDTel.js");
6
+ const require_process_memory = require("../process-memory-CcWK6O93.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 { A as audioAnalysisCapability, It as hydrateSchema, S as PoolMemoryWatchdog, _t as resolvePoolMemoryPolicy, j as audioAnalyzerCapability, jt as BaseAddon, n as AUDIO_BACKEND_CHOICES, nt as mapAudioLabelToMacro, s as DEFAULT_AUDIO_ANALYZER_CONFIG, v as HF_BASE_URL, wt as errMsg } from "../dist-CIfo4mG5.mjs";
3
- import { n as pickNodePlatformArch, t as readProcessMemory } from "../process-memory--nGY2kIF.mjs";
2
+ import { A as audioAnalysisCapability, It as hydrateSchema, S as PoolMemoryWatchdog, _t as resolvePoolMemoryPolicy, j as audioAnalyzerCapability, jt as BaseAddon, n as AUDIO_BACKEND_CHOICES, nt as mapAudioLabelToMacro, s as DEFAULT_AUDIO_ANALYZER_CONFIG, v as HF_BASE_URL, wt as errMsg } from "../dist-A-CKFNg9.mjs";
3
+ import { n as pickNodePlatformArch, t as readProcessMemory } from "../process-memory-DVPPoQS1.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";
@@ -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-D1GcKxTl.js");
6
- const require_node = require("../node-DnaSxKtp.js");
7
- const require_local_frame_registry = require("../local-frame-registry-Bd2qxPtO.js");
8
- const require_lazy_sharp = require("../lazy-sharp-AjtuNBru.js");
5
+ const require_dist = require("../dist-CpmqDTel.js");
6
+ const require_node = require("../node-DudW4uSe.js");
7
+ const require_local_frame_registry = require("../local-frame-registry-CHzo5v0z.js");
8
+ const require_lazy_sharp = require("../lazy-sharp-c_IKosOs.js");
9
9
  const require_event_loop_stall_monitor = require("../event-loop-stall-monitor-DaUBcb13.js");
10
- const require_process_memory = require("../process-memory-B8yE5D8z.js");
10
+ const require_process_memory = require("../process-memory-CcWK6O93.js");
11
11
  let node_fs = require("node:fs");
12
12
  node_fs = require_dist.__toESM(node_fs);
13
13
  let node_path = require("node:path");
@@ -1,10 +1,10 @@
1
1
  import { n as __require } from "../chunk-DnnnRqeS.mjs";
2
- import { Bt as nodePin, Ft as createEvent, It as hydrateSchema, Kt as array, O as YAMNET_TO_MACRO, Q as inferModelProvider, Qt as object, S as PoolMemoryWatchdog, St as supportedRuntimes$1, Vt as parseJsonUnknown, W as detectionPipelineCapability, Wt as sleep, Y as evaluateZoneRules, _t as resolvePoolMemoryPolicy, at as overlayClusterStepSettings, c as DEFAULT_CLUSTER_STEP_MODELS, ct as pickClusterStepSettings, dt as pipelineExecutorCapability, en as string, et as loadContributionCapability, ht as resolveClusterStepModelId, jt as BaseAddon, l as DEFAULT_CLUSTER_STEP_SETTINGS, m as DEVICE_BACKEND_TO_FORMAT, nn as EventCategory, q as enumerateInferenceDevices, st as pickClusterStepModels, t as APPLE_SA_TO_MACRO, tn as union, wt as errMsg, yt as runtimeDevices$1, z as defaultDeviceFor$1 } from "../dist-CIfo4mG5.mjs";
3
- import { a as readProcessCost } from "../node-COkvb2aY.mjs";
4
- import { a as getDefaultModelForFormat, c as getStepDefinition, i as ALL_STEPS, l as resolveModelForFormat, o as getDefaultModelForFormatFromDef, r as ALL_PIPELINE_STEPS, s as getStep, t as localFrameRegistry, u as landmarkPrecisionVerdict } from "../local-frame-registry-C6p0o5JF.mjs";
2
+ import { Bt as nodePin, Ft as createEvent, It as hydrateSchema, Kt as array, O as YAMNET_TO_MACRO, Q as inferModelProvider, Qt as object, S as PoolMemoryWatchdog, St as supportedRuntimes$1, Vt as parseJsonUnknown, W as detectionPipelineCapability, Wt as sleep, Y as evaluateZoneRules, _t as resolvePoolMemoryPolicy, at as overlayClusterStepSettings, c as DEFAULT_CLUSTER_STEP_MODELS, ct as pickClusterStepSettings, dt as pipelineExecutorCapability, en as string, et as loadContributionCapability, ht as resolveClusterStepModelId, jt as BaseAddon, l as DEFAULT_CLUSTER_STEP_SETTINGS, m as DEVICE_BACKEND_TO_FORMAT, nn as EventCategory, q as enumerateInferenceDevices, st as pickClusterStepModels, t as APPLE_SA_TO_MACRO, tn as union, wt as errMsg, yt as runtimeDevices$1, z as defaultDeviceFor$1 } from "../dist-A-CKFNg9.mjs";
3
+ import { a as readProcessCost } from "../node-CNhb6GOd.mjs";
4
+ import { a as getDefaultModelForFormat, c as getStepDefinition, i as ALL_STEPS, l as resolveModelForFormat, o as getDefaultModelForFormatFromDef, r as ALL_PIPELINE_STEPS, s as getStep, t as localFrameRegistry, u as landmarkPrecisionVerdict } from "../local-frame-registry-DuEPtfBk.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--nGY2kIF.mjs";
7
+ import { n as pickNodePlatformArch, t as readProcessMemory } from "../process-memory-DVPPoQS1.mjs";
8
8
  import * as fs from "node:fs";
9
9
  import * as path$1 from "node:path";
10
10
  import { spawn } from "node:child_process";
@@ -12061,6 +12061,89 @@ var LocationStatSchema = object({
12061
12061
  fileCount: number(),
12062
12062
  present: boolean()
12063
12063
  });
12064
+ /** Lifecycle of a backup run. Terminal states: succeeded / failed / cancelled. */
12065
+ var BackupRunStateSchema = _enum([
12066
+ "queued",
12067
+ "running",
12068
+ "succeeded",
12069
+ "failed",
12070
+ "cancelled"
12071
+ ]);
12072
+ /**
12073
+ * Where a running backup currently is. `queued` before it starts,
12074
+ * `building` while the tar.gz is being staged, `uploading` during the
12075
+ * per-destination fan-out, `done` once terminal.
12076
+ */
12077
+ var BackupRunPhaseSchema = _enum([
12078
+ "queued",
12079
+ "building",
12080
+ "uploading",
12081
+ "done"
12082
+ ]);
12083
+ /**
12084
+ * Observable state of one backup run — readable WHILE it runs via
12085
+ * `backup.listRuns`. This is what makes the execution queue and
12086
+ * `backup.cancel` usable: the 2026-09-04 incident (two concurrent
12087
+ * multi-GB builds, staging 5.1 GB → 18 GB, load 62) was only
12088
+ * diagnosable with `du` because nothing reported that runs existed or
12089
+ * how large the staged archive had grown.
12090
+ */
12091
+ var BackupRunSchema = object({
12092
+ /** Stable run id — the handle `backup.cancel` takes. */
12093
+ id: string(),
12094
+ state: BackupRunStateSchema,
12095
+ phase: BackupRunPhaseSchema,
12096
+ /**
12097
+ * Resolved destination location ids. Empty while queued (targets are
12098
+ * resolved when the run starts, against the then-current policies).
12099
+ */
12100
+ destinationIds: array(string()).readonly(),
12101
+ label: string().optional(),
12102
+ /** ms-epoch when the run was submitted (trigger call / schedule fire). */
12103
+ requestedAt: number(),
12104
+ /** ms-epoch when the run left the queue and started building. */
12105
+ startedAt: number().optional(),
12106
+ /** ms-epoch when the run reached a terminal state. */
12107
+ finishedAt: number().optional(),
12108
+ /** Compressed bytes of the staging archive written so far. */
12109
+ stagedBytes: number(),
12110
+ /** Final staged archive size, once the build phase completes. */
12111
+ archiveSizeBytes: number().optional(),
12112
+ /** Bytes pushed to the destination currently uploading. */
12113
+ uploadedBytes: number(),
12114
+ /** Destinations where the archive fully landed (uploaded + indexed). */
12115
+ completedDestinationIds: array(string()).readonly(),
12116
+ /** Destinations that failed during the fan-out. */
12117
+ failedDestinationIds: array(string()).readonly(),
12118
+ /** Failure message when `state === 'failed'`. */
12119
+ error: string().optional(),
12120
+ /**
12121
+ * 1-based place in the execution queue — 1 = runs next. Present only
12122
+ * while `state === 'queued'`. Stamped by the orchestrator from the
12123
+ * queue's OWN pending order, never derived from timestamps, so the
12124
+ * UI cannot show an order the executor will not honour.
12125
+ */
12126
+ queuePosition: number().int().min(1).optional()
12127
+ });
12128
+ /**
12129
+ * Result of `backup.trigger`. The call still resolves when the run
12130
+ * terminates (compat with schedule-driven runs and the admin UI), but
12131
+ * it now names the run and says whether it had to WAIT: a trigger that
12132
+ * arrives while another run is in flight is enqueued (or joined onto
12133
+ * an identical already-queued run), never started concurrently.
12134
+ */
12135
+ var BackupTriggerResultSchema = object({
12136
+ /** The run this trigger mapped to — poll it via `listRuns`, stop it via `cancel`. */
12137
+ runId: string(),
12138
+ /** True when the run waited behind an in-flight run instead of starting immediately. */
12139
+ queued: boolean(),
12140
+ /** True when this trigger was coalesced onto an identical already-queued run. */
12141
+ joined: boolean(),
12142
+ /** True when the run was cancelled before completing every destination. */
12143
+ cancelled: boolean(),
12144
+ /** One entry per destination the archive landed at (partial on cancel). */
12145
+ entries: array(BackupEntrySchema).readonly()
12146
+ });
12064
12147
  /**
12065
12148
  * A backup schedule — the N:M "entry" that binds one cron cadence to a
12066
12149
  * SET of destination locations. Supersedes the per-location cron on
@@ -12108,7 +12191,10 @@ method(_void(), array(BackupDestinationInfoSchema).readonly(), { auth: "admin" }
12108
12191
  * retention (manual runs).
12109
12192
  */
12110
12193
  retentionCount: number().int().min(1).max(1e3).optional()
12111
- }).optional(), array(BackupEntrySchema).readonly(), {
12194
+ }).optional(), BackupTriggerResultSchema, {
12195
+ kind: "mutation",
12196
+ auth: "admin"
12197
+ }), method(_void(), array(BackupRunSchema).readonly(), { auth: "admin" }), method(object({ runId: string() }), object({ cancelled: boolean() }), {
12112
12198
  kind: "mutation",
12113
12199
  auth: "admin"
12114
12200
  }), method(_void(), array(BackupEntrySchema).readonly(), { auth: "admin" }), method(_void(), array(LocationStatSchema).readonly(), { auth: "admin" }), method(object({
@@ -12836,6 +12922,38 @@ var streamBrokerCapability = {
12836
12922
  auth: "admin"
12837
12923
  }),
12838
12924
  /**
12925
+ * The HARDWARE behind a device number was replaced
12926
+ * (`deviceManager.migrateDevice`). Forget every piece of broker state that
12927
+ * described the old box, so the next catalog pull derives everything from
12928
+ * the camera that is actually there:
12929
+ *
12930
+ * - every `derived:*` stream definition — a derived is authored against a
12931
+ * specific profile layout, and against the wrong hardware its feeder
12932
+ * respawns forever (observed at attempt 2732 on the live hub,
12933
+ * 2026-09-01);
12934
+ * - the profile-slot assignment entry, PURGED (not unassigned — unassign
12935
+ * marks the slot manual, which would pin the stale choice instead of
12936
+ * letting `computeInitialAssignment` re-derive it);
12937
+ * - the probe snapshots (`<deviceId>/…` — probed codec/resolution of the
12938
+ * old hardware);
12939
+ * - the persisted RTSP token rows for the device's brokers (keyed
12940
+ * `<deviceId>/<camStreamId>`; the stream ids change with the hardware,
12941
+ * so the rows are dead URLs).
12942
+ *
12943
+ * An RPC, deliberately — an event is telemetry and may be dropped (D8),
12944
+ * and a dropped forget leaves a feeder respawning against a stream that
12945
+ * does not exist.
12946
+ */
12947
+ forgetDeviceHardware: method(object({ deviceId: number().int().nonnegative() }), object({
12948
+ derivedStreamsDeleted: array(string()).readonly(),
12949
+ assignmentsPurged: boolean(),
12950
+ probeSnapshotsDropped: number().int().nonnegative(),
12951
+ rtspTokenRowsDeleted: number().int().nonnegative()
12952
+ }), {
12953
+ kind: "mutation",
12954
+ auth: "admin"
12955
+ }),
12956
+ /**
12839
12957
  * Render a short GIF or MP4 from the broker's PRE-BUFFER around an instant.
12840
12958
  *
12841
12959
  * The pre-buffer is the only source that already holds the seconds BEFORE
@@ -21315,7 +21433,20 @@ var RecentTracksQueryInput = object({
21315
21433
  projection: TrackProjectionSchema.optional(),
21316
21434
  /** Include stationary-promoted rows (parked objects). Default false: the
21317
21435
  * feed lists passages; parking records live on the stationary registry. */
21318
- includeStationary: boolean().optional()
21436
+ includeStationary: boolean().optional(),
21437
+ /**
21438
+ * Restrict to these track classes. ABSENT or EMPTY means no filter.
21439
+ *
21440
+ * The same filter `listTracks` takes, because the timeline's class chips must
21441
+ * mean the same thing whether the scope is one camera or twelve. Until this
21442
+ * existed the scoped feed downloaded a page and narrowed it on the phone
21443
+ * while the single-camera path narrowed the read — one filter, two costs.
21444
+ *
21445
+ * A SUPERSET prefilter on `classes[]`, like its single-camera twin: rows
21446
+ * whose class list is unreadable are kept, and the client's rule stays the
21447
+ * exact one.
21448
+ */
21449
+ classes: array(string()).optional()
21319
21450
  });
21320
21451
  var RecentTracksPageSchema = object({
21321
21452
  /** Merged page, ordered by (`lastSeen` DESC, `trackId` DESC). */
@@ -25597,8 +25728,22 @@ DeviceType.Automation, method(object({ deviceId: number().int().nonnegative() })
25597
25728
  * threshold.
25598
25729
  */
25599
25730
  var BatteryStatusSchema = object({
25600
- /** 0..100 inclusive. Firmware-reported. */
25601
- percentage: number().min(0).max(100),
25731
+ /**
25732
+ * 0..100 inclusive, firmware-reported. **`null` means NOT YET KNOWN** — the
25733
+ * provider has registered the capability but no reading has landed.
25734
+ *
25735
+ * It is nullable because it was not, and the only value a provider could
25736
+ * seed with was `0`. A battery camera behind an NVR therefore announced
25737
+ * itself at 0% on every start and corrected itself a moment later, which is
25738
+ * indistinguishable from a real flat battery: it fires the low-battery alert
25739
+ * every time the hub restarts. Unknown is not empty (D315), and on a battery
25740
+ * reading the difference is an alarm.
25741
+ *
25742
+ * `vacuum-control` and `lawn-mower-control` already model it this way.
25743
+ * Consumers must SKIP a null rather than coerce it — `battery-band` already
25744
+ * declines to band a non-finite reading, which is the correct shape.
25745
+ */
25746
+ percentage: number().min(0).max(100).nullable(),
25602
25747
  /**
25603
25748
  * Charging source. `'dc'` covers wall/USB adapters; `'solar'` is
25604
25749
  * Reolink-specific for the Solar Panel 2 accessory (will become
@@ -32528,6 +32673,12 @@ Object.freeze({
32528
32673
  addonId: null,
32529
32674
  access: "create"
32530
32675
  },
32676
+ "backup.cancel": {
32677
+ capName: "backup",
32678
+ capScope: "system",
32679
+ addonId: null,
32680
+ access: "create"
32681
+ },
32531
32682
  "backup.delete": {
32532
32683
  capName: "backup",
32533
32684
  capScope: "system",
@@ -32570,6 +32721,12 @@ Object.freeze({
32570
32721
  addonId: null,
32571
32722
  access: "view"
32572
32723
  },
32724
+ "backup.listRuns": {
32725
+ capName: "backup",
32726
+ capScope: "system",
32727
+ addonId: null,
32728
+ access: "view"
32729
+ },
32573
32730
  "backup.listSchedules": {
32574
32731
  capName: "backup",
32575
32732
  capScope: "system",
@@ -37136,6 +37293,12 @@ Object.freeze({
37136
37293
  addonId: null,
37137
37294
  access: "create"
37138
37295
  },
37296
+ "streamBroker.forgetDeviceHardware": {
37297
+ capName: "stream-broker",
37298
+ capScope: "system",
37299
+ addonId: null,
37300
+ access: "delete"
37301
+ },
37139
37302
  "streamBroker.getAllRtspEntries": {
37140
37303
  capName: "stream-broker",
37141
37304
  capScope: "system",
@@ -39594,6 +39757,11 @@ Object.freeze({
39594
39757
  form: "single",
39595
39758
  optional: false
39596
39759
  }],
39760
+ "streamBroker.forgetDeviceHardware": [{
39761
+ name: "deviceId",
39762
+ form: "single",
39763
+ optional: false
39764
+ }],
39597
39765
  "streamBroker.getDeviceAudioMute": [{
39598
39766
  name: "deviceId",
39599
39767
  form: "single",
@@ -12084,6 +12084,89 @@ var LocationStatSchema = object({
12084
12084
  fileCount: number(),
12085
12085
  present: boolean()
12086
12086
  });
12087
+ /** Lifecycle of a backup run. Terminal states: succeeded / failed / cancelled. */
12088
+ var BackupRunStateSchema = _enum([
12089
+ "queued",
12090
+ "running",
12091
+ "succeeded",
12092
+ "failed",
12093
+ "cancelled"
12094
+ ]);
12095
+ /**
12096
+ * Where a running backup currently is. `queued` before it starts,
12097
+ * `building` while the tar.gz is being staged, `uploading` during the
12098
+ * per-destination fan-out, `done` once terminal.
12099
+ */
12100
+ var BackupRunPhaseSchema = _enum([
12101
+ "queued",
12102
+ "building",
12103
+ "uploading",
12104
+ "done"
12105
+ ]);
12106
+ /**
12107
+ * Observable state of one backup run — readable WHILE it runs via
12108
+ * `backup.listRuns`. This is what makes the execution queue and
12109
+ * `backup.cancel` usable: the 2026-09-04 incident (two concurrent
12110
+ * multi-GB builds, staging 5.1 GB → 18 GB, load 62) was only
12111
+ * diagnosable with `du` because nothing reported that runs existed or
12112
+ * how large the staged archive had grown.
12113
+ */
12114
+ var BackupRunSchema = object({
12115
+ /** Stable run id — the handle `backup.cancel` takes. */
12116
+ id: string(),
12117
+ state: BackupRunStateSchema,
12118
+ phase: BackupRunPhaseSchema,
12119
+ /**
12120
+ * Resolved destination location ids. Empty while queued (targets are
12121
+ * resolved when the run starts, against the then-current policies).
12122
+ */
12123
+ destinationIds: array(string()).readonly(),
12124
+ label: string().optional(),
12125
+ /** ms-epoch when the run was submitted (trigger call / schedule fire). */
12126
+ requestedAt: number(),
12127
+ /** ms-epoch when the run left the queue and started building. */
12128
+ startedAt: number().optional(),
12129
+ /** ms-epoch when the run reached a terminal state. */
12130
+ finishedAt: number().optional(),
12131
+ /** Compressed bytes of the staging archive written so far. */
12132
+ stagedBytes: number(),
12133
+ /** Final staged archive size, once the build phase completes. */
12134
+ archiveSizeBytes: number().optional(),
12135
+ /** Bytes pushed to the destination currently uploading. */
12136
+ uploadedBytes: number(),
12137
+ /** Destinations where the archive fully landed (uploaded + indexed). */
12138
+ completedDestinationIds: array(string()).readonly(),
12139
+ /** Destinations that failed during the fan-out. */
12140
+ failedDestinationIds: array(string()).readonly(),
12141
+ /** Failure message when `state === 'failed'`. */
12142
+ error: string().optional(),
12143
+ /**
12144
+ * 1-based place in the execution queue — 1 = runs next. Present only
12145
+ * while `state === 'queued'`. Stamped by the orchestrator from the
12146
+ * queue's OWN pending order, never derived from timestamps, so the
12147
+ * UI cannot show an order the executor will not honour.
12148
+ */
12149
+ queuePosition: number().int().min(1).optional()
12150
+ });
12151
+ /**
12152
+ * Result of `backup.trigger`. The call still resolves when the run
12153
+ * terminates (compat with schedule-driven runs and the admin UI), but
12154
+ * it now names the run and says whether it had to WAIT: a trigger that
12155
+ * arrives while another run is in flight is enqueued (or joined onto
12156
+ * an identical already-queued run), never started concurrently.
12157
+ */
12158
+ var BackupTriggerResultSchema = object({
12159
+ /** The run this trigger mapped to — poll it via `listRuns`, stop it via `cancel`. */
12160
+ runId: string(),
12161
+ /** True when the run waited behind an in-flight run instead of starting immediately. */
12162
+ queued: boolean(),
12163
+ /** True when this trigger was coalesced onto an identical already-queued run. */
12164
+ joined: boolean(),
12165
+ /** True when the run was cancelled before completing every destination. */
12166
+ cancelled: boolean(),
12167
+ /** One entry per destination the archive landed at (partial on cancel). */
12168
+ entries: array(BackupEntrySchema).readonly()
12169
+ });
12087
12170
  /**
12088
12171
  * A backup schedule — the N:M "entry" that binds one cron cadence to a
12089
12172
  * SET of destination locations. Supersedes the per-location cron on
@@ -12131,7 +12214,10 @@ method(_void(), array(BackupDestinationInfoSchema).readonly(), { auth: "admin" }
12131
12214
  * retention (manual runs).
12132
12215
  */
12133
12216
  retentionCount: number().int().min(1).max(1e3).optional()
12134
- }).optional(), array(BackupEntrySchema).readonly(), {
12217
+ }).optional(), BackupTriggerResultSchema, {
12218
+ kind: "mutation",
12219
+ auth: "admin"
12220
+ }), method(_void(), array(BackupRunSchema).readonly(), { auth: "admin" }), method(object({ runId: string() }), object({ cancelled: boolean() }), {
12135
12221
  kind: "mutation",
12136
12222
  auth: "admin"
12137
12223
  }), method(_void(), array(BackupEntrySchema).readonly(), { auth: "admin" }), method(_void(), array(LocationStatSchema).readonly(), { auth: "admin" }), method(object({
@@ -12859,6 +12945,38 @@ var streamBrokerCapability = {
12859
12945
  auth: "admin"
12860
12946
  }),
12861
12947
  /**
12948
+ * The HARDWARE behind a device number was replaced
12949
+ * (`deviceManager.migrateDevice`). Forget every piece of broker state that
12950
+ * described the old box, so the next catalog pull derives everything from
12951
+ * the camera that is actually there:
12952
+ *
12953
+ * - every `derived:*` stream definition — a derived is authored against a
12954
+ * specific profile layout, and against the wrong hardware its feeder
12955
+ * respawns forever (observed at attempt 2732 on the live hub,
12956
+ * 2026-09-01);
12957
+ * - the profile-slot assignment entry, PURGED (not unassigned — unassign
12958
+ * marks the slot manual, which would pin the stale choice instead of
12959
+ * letting `computeInitialAssignment` re-derive it);
12960
+ * - the probe snapshots (`<deviceId>/…` — probed codec/resolution of the
12961
+ * old hardware);
12962
+ * - the persisted RTSP token rows for the device's brokers (keyed
12963
+ * `<deviceId>/<camStreamId>`; the stream ids change with the hardware,
12964
+ * so the rows are dead URLs).
12965
+ *
12966
+ * An RPC, deliberately — an event is telemetry and may be dropped (D8),
12967
+ * and a dropped forget leaves a feeder respawning against a stream that
12968
+ * does not exist.
12969
+ */
12970
+ forgetDeviceHardware: method(object({ deviceId: number().int().nonnegative() }), object({
12971
+ derivedStreamsDeleted: array(string()).readonly(),
12972
+ assignmentsPurged: boolean(),
12973
+ probeSnapshotsDropped: number().int().nonnegative(),
12974
+ rtspTokenRowsDeleted: number().int().nonnegative()
12975
+ }), {
12976
+ kind: "mutation",
12977
+ auth: "admin"
12978
+ }),
12979
+ /**
12862
12980
  * Render a short GIF or MP4 from the broker's PRE-BUFFER around an instant.
12863
12981
  *
12864
12982
  * The pre-buffer is the only source that already holds the seconds BEFORE
@@ -21338,7 +21456,20 @@ var RecentTracksQueryInput = object({
21338
21456
  projection: TrackProjectionSchema.optional(),
21339
21457
  /** Include stationary-promoted rows (parked objects). Default false: the
21340
21458
  * feed lists passages; parking records live on the stationary registry. */
21341
- includeStationary: boolean().optional()
21459
+ includeStationary: boolean().optional(),
21460
+ /**
21461
+ * Restrict to these track classes. ABSENT or EMPTY means no filter.
21462
+ *
21463
+ * The same filter `listTracks` takes, because the timeline's class chips must
21464
+ * mean the same thing whether the scope is one camera or twelve. Until this
21465
+ * existed the scoped feed downloaded a page and narrowed it on the phone
21466
+ * while the single-camera path narrowed the read — one filter, two costs.
21467
+ *
21468
+ * A SUPERSET prefilter on `classes[]`, like its single-camera twin: rows
21469
+ * whose class list is unreadable are kept, and the client's rule stays the
21470
+ * exact one.
21471
+ */
21472
+ classes: array(string()).optional()
21342
21473
  });
21343
21474
  var RecentTracksPageSchema = object({
21344
21475
  /** Merged page, ordered by (`lastSeen` DESC, `trackId` DESC). */
@@ -25620,8 +25751,22 @@ DeviceType.Automation, method(object({ deviceId: number().int().nonnegative() })
25620
25751
  * threshold.
25621
25752
  */
25622
25753
  var BatteryStatusSchema = object({
25623
- /** 0..100 inclusive. Firmware-reported. */
25624
- percentage: number().min(0).max(100),
25754
+ /**
25755
+ * 0..100 inclusive, firmware-reported. **`null` means NOT YET KNOWN** — the
25756
+ * provider has registered the capability but no reading has landed.
25757
+ *
25758
+ * It is nullable because it was not, and the only value a provider could
25759
+ * seed with was `0`. A battery camera behind an NVR therefore announced
25760
+ * itself at 0% on every start and corrected itself a moment later, which is
25761
+ * indistinguishable from a real flat battery: it fires the low-battery alert
25762
+ * every time the hub restarts. Unknown is not empty (D315), and on a battery
25763
+ * reading the difference is an alarm.
25764
+ *
25765
+ * `vacuum-control` and `lawn-mower-control` already model it this way.
25766
+ * Consumers must SKIP a null rather than coerce it — `battery-band` already
25767
+ * declines to band a non-finite reading, which is the correct shape.
25768
+ */
25769
+ percentage: number().min(0).max(100).nullable(),
25625
25770
  /**
25626
25771
  * Charging source. `'dc'` covers wall/USB adapters; `'solar'` is
25627
25772
  * Reolink-specific for the Solar Panel 2 accessory (will become
@@ -32551,6 +32696,12 @@ Object.freeze({
32551
32696
  addonId: null,
32552
32697
  access: "create"
32553
32698
  },
32699
+ "backup.cancel": {
32700
+ capName: "backup",
32701
+ capScope: "system",
32702
+ addonId: null,
32703
+ access: "create"
32704
+ },
32554
32705
  "backup.delete": {
32555
32706
  capName: "backup",
32556
32707
  capScope: "system",
@@ -32593,6 +32744,12 @@ Object.freeze({
32593
32744
  addonId: null,
32594
32745
  access: "view"
32595
32746
  },
32747
+ "backup.listRuns": {
32748
+ capName: "backup",
32749
+ capScope: "system",
32750
+ addonId: null,
32751
+ access: "view"
32752
+ },
32596
32753
  "backup.listSchedules": {
32597
32754
  capName: "backup",
32598
32755
  capScope: "system",
@@ -37159,6 +37316,12 @@ Object.freeze({
37159
37316
  addonId: null,
37160
37317
  access: "create"
37161
37318
  },
37319
+ "streamBroker.forgetDeviceHardware": {
37320
+ capName: "stream-broker",
37321
+ capScope: "system",
37322
+ addonId: null,
37323
+ access: "delete"
37324
+ },
37162
37325
  "streamBroker.getAllRtspEntries": {
37163
37326
  capName: "stream-broker",
37164
37327
  capScope: "system",
@@ -39617,6 +39780,11 @@ Object.freeze({
39617
39780
  form: "single",
39618
39781
  optional: false
39619
39782
  }],
39783
+ "streamBroker.forgetDeviceHardware": [{
39784
+ name: "deviceId",
39785
+ form: "single",
39786
+ optional: false
39787
+ }],
39620
39788
  "streamBroker.getDeviceAudioMute": [{
39621
39789
  name: "deviceId",
39622
39790
  form: "single",
@@ -1,4 +1,4 @@
1
- const require_dist = require("./dist-D1GcKxTl.js");
1
+ const require_dist = require("./dist-CpmqDTel.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");
@@ -1,4 +1,4 @@
1
- const require_dist = require("./dist-D1GcKxTl.js");
1
+ const require_dist = require("./dist-CpmqDTel.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 { M as audioKindId, Z as hfModelUrl, a as COCO_80_LABELS, o as COCO_TO_MACRO, r as AUDIO_MACRO_LABELS } from "./dist-CIfo4mG5.mjs";
1
+ import { M as audioKindId, Z as hfModelUrl, a as COCO_80_LABELS, o as COCO_TO_MACRO, r as AUDIO_MACRO_LABELS } from "./dist-A-CKFNg9.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,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-D1GcKxTl.js");
6
- const require_lazy_sharp = require("../lazy-sharp-AjtuNBru.js");
5
+ const require_dist = require("../dist-CpmqDTel.js");
6
+ const require_lazy_sharp = require("../lazy-sharp-c_IKosOs.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 hydrateSchema, Pt as DeviceType, Y as evaluateZoneRules, it as motionDetectionCapability, jt as BaseAddon } from "../dist-CIfo4mG5.mjs";
1
+ import { It as hydrateSchema, Pt as DeviceType, Y as evaluateZoneRules, it as motionDetectionCapability, jt as BaseAddon } from "../dist-A-CKFNg9.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 { Dt as buildFfmpegArgs, Et as Fmp4BoxSplitter, kt as isSoftwareDecode, wt as errMsg } from "./dist-CIfo4mG5.mjs";
1
+ import { Dt as buildFfmpegArgs, Et as Fmp4BoxSplitter, kt as isSoftwareDecode, wt as errMsg } from "./dist-A-CKFNg9.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-D1GcKxTl.js");
1
+ const require_dist = require("./dist-CpmqDTel.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);