@camstack/addon-terminal 0.1.62 → 0.1.64

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
@@ -10626,6 +10626,89 @@ var LocationStatSchema = object({
10626
10626
  fileCount: number(),
10627
10627
  present: boolean()
10628
10628
  });
10629
+ /** Lifecycle of a backup run. Terminal states: succeeded / failed / cancelled. */
10630
+ var BackupRunStateSchema = _enum([
10631
+ "queued",
10632
+ "running",
10633
+ "succeeded",
10634
+ "failed",
10635
+ "cancelled"
10636
+ ]);
10637
+ /**
10638
+ * Where a running backup currently is. `queued` before it starts,
10639
+ * `building` while the tar.gz is being staged, `uploading` during the
10640
+ * per-destination fan-out, `done` once terminal.
10641
+ */
10642
+ var BackupRunPhaseSchema = _enum([
10643
+ "queued",
10644
+ "building",
10645
+ "uploading",
10646
+ "done"
10647
+ ]);
10648
+ /**
10649
+ * Observable state of one backup run — readable WHILE it runs via
10650
+ * `backup.listRuns`. This is what makes the execution queue and
10651
+ * `backup.cancel` usable: the 2026-09-04 incident (two concurrent
10652
+ * multi-GB builds, staging 5.1 GB → 18 GB, load 62) was only
10653
+ * diagnosable with `du` because nothing reported that runs existed or
10654
+ * how large the staged archive had grown.
10655
+ */
10656
+ var BackupRunSchema = object({
10657
+ /** Stable run id — the handle `backup.cancel` takes. */
10658
+ id: string(),
10659
+ state: BackupRunStateSchema,
10660
+ phase: BackupRunPhaseSchema,
10661
+ /**
10662
+ * Resolved destination location ids. Empty while queued (targets are
10663
+ * resolved when the run starts, against the then-current policies).
10664
+ */
10665
+ destinationIds: array(string()).readonly(),
10666
+ label: string().optional(),
10667
+ /** ms-epoch when the run was submitted (trigger call / schedule fire). */
10668
+ requestedAt: number(),
10669
+ /** ms-epoch when the run left the queue and started building. */
10670
+ startedAt: number().optional(),
10671
+ /** ms-epoch when the run reached a terminal state. */
10672
+ finishedAt: number().optional(),
10673
+ /** Compressed bytes of the staging archive written so far. */
10674
+ stagedBytes: number(),
10675
+ /** Final staged archive size, once the build phase completes. */
10676
+ archiveSizeBytes: number().optional(),
10677
+ /** Bytes pushed to the destination currently uploading. */
10678
+ uploadedBytes: number(),
10679
+ /** Destinations where the archive fully landed (uploaded + indexed). */
10680
+ completedDestinationIds: array(string()).readonly(),
10681
+ /** Destinations that failed during the fan-out. */
10682
+ failedDestinationIds: array(string()).readonly(),
10683
+ /** Failure message when `state === 'failed'`. */
10684
+ error: string().optional(),
10685
+ /**
10686
+ * 1-based place in the execution queue — 1 = runs next. Present only
10687
+ * while `state === 'queued'`. Stamped by the orchestrator from the
10688
+ * queue's OWN pending order, never derived from timestamps, so the
10689
+ * UI cannot show an order the executor will not honour.
10690
+ */
10691
+ queuePosition: number().int().min(1).optional()
10692
+ });
10693
+ /**
10694
+ * Result of `backup.trigger`. The call still resolves when the run
10695
+ * terminates (compat with schedule-driven runs and the admin UI), but
10696
+ * it now names the run and says whether it had to WAIT: a trigger that
10697
+ * arrives while another run is in flight is enqueued (or joined onto
10698
+ * an identical already-queued run), never started concurrently.
10699
+ */
10700
+ var BackupTriggerResultSchema = object({
10701
+ /** The run this trigger mapped to — poll it via `listRuns`, stop it via `cancel`. */
10702
+ runId: string(),
10703
+ /** True when the run waited behind an in-flight run instead of starting immediately. */
10704
+ queued: boolean(),
10705
+ /** True when this trigger was coalesced onto an identical already-queued run. */
10706
+ joined: boolean(),
10707
+ /** True when the run was cancelled before completing every destination. */
10708
+ cancelled: boolean(),
10709
+ /** One entry per destination the archive landed at (partial on cancel). */
10710
+ entries: array(BackupEntrySchema).readonly()
10711
+ });
10629
10712
  /**
10630
10713
  * A backup schedule — the N:M "entry" that binds one cron cadence to a
10631
10714
  * SET of destination locations. Supersedes the per-location cron on
@@ -10673,7 +10756,10 @@ method(_void(), array(BackupDestinationInfoSchema).readonly(), { auth: "admin" }
10673
10756
  * retention (manual runs).
10674
10757
  */
10675
10758
  retentionCount: number().int().min(1).max(1e3).optional()
10676
- }).optional(), array(BackupEntrySchema).readonly(), {
10759
+ }).optional(), BackupTriggerResultSchema, {
10760
+ kind: "mutation",
10761
+ auth: "admin"
10762
+ }), method(_void(), array(BackupRunSchema).readonly(), { auth: "admin" }), method(object({ runId: string() }), object({ cancelled: boolean() }), {
10677
10763
  kind: "mutation",
10678
10764
  auth: "admin"
10679
10765
  }), method(_void(), array(BackupEntrySchema).readonly(), { auth: "admin" }), method(_void(), array(LocationStatSchema).readonly(), { auth: "admin" }), method(object({
@@ -11390,6 +11476,14 @@ method(object({
11390
11476
  }), object({ success: literal(true) }), {
11391
11477
  kind: "mutation",
11392
11478
  auth: "admin"
11479
+ }), method(object({ deviceId: number().int().nonnegative() }), object({
11480
+ derivedStreamsDeleted: array(string()).readonly(),
11481
+ assignmentsPurged: boolean(),
11482
+ probeSnapshotsDropped: number().int().nonnegative(),
11483
+ rtspTokenRowsDeleted: number().int().nonnegative()
11484
+ }), {
11485
+ kind: "mutation",
11486
+ auth: "admin"
11393
11487
  }), method(object({
11394
11488
  deviceId: number(),
11395
11489
  /** Absent = the LOWEST assigned profile — a notification attachment is
@@ -19227,7 +19321,20 @@ var RecentTracksQueryInput = object({
19227
19321
  projection: TrackProjectionSchema.optional(),
19228
19322
  /** Include stationary-promoted rows (parked objects). Default false: the
19229
19323
  * feed lists passages; parking records live on the stationary registry. */
19230
- includeStationary: boolean().optional()
19324
+ includeStationary: boolean().optional(),
19325
+ /**
19326
+ * Restrict to these track classes. ABSENT or EMPTY means no filter.
19327
+ *
19328
+ * The same filter `listTracks` takes, because the timeline's class chips must
19329
+ * mean the same thing whether the scope is one camera or twelve. Until this
19330
+ * existed the scoped feed downloaded a page and narrowed it on the phone
19331
+ * while the single-camera path narrowed the read — one filter, two costs.
19332
+ *
19333
+ * A SUPERSET prefilter on `classes[]`, like its single-camera twin: rows
19334
+ * whose class list is unreadable are kept, and the client's rule stays the
19335
+ * exact one.
19336
+ */
19337
+ classes: array(string()).optional()
19231
19338
  });
19232
19339
  var RecentTracksPageSchema = object({
19233
19340
  /** Merged page, ordered by (`lastSeen` DESC, `trackId` DESC). */
@@ -23545,8 +23652,22 @@ var automationControlCapability = {
23545
23652
  * threshold.
23546
23653
  */
23547
23654
  var BatteryStatusSchema = object({
23548
- /** 0..100 inclusive. Firmware-reported. */
23549
- percentage: number().min(0).max(100),
23655
+ /**
23656
+ * 0..100 inclusive, firmware-reported. **`null` means NOT YET KNOWN** — the
23657
+ * provider has registered the capability but no reading has landed.
23658
+ *
23659
+ * It is nullable because it was not, and the only value a provider could
23660
+ * seed with was `0`. A battery camera behind an NVR therefore announced
23661
+ * itself at 0% on every start and corrected itself a moment later, which is
23662
+ * indistinguishable from a real flat battery: it fires the low-battery alert
23663
+ * every time the hub restarts. Unknown is not empty (D315), and on a battery
23664
+ * reading the difference is an alarm.
23665
+ *
23666
+ * `vacuum-control` and `lawn-mower-control` already model it this way.
23667
+ * Consumers must SKIP a null rather than coerce it — `battery-band` already
23668
+ * declines to band a non-finite reading, which is the correct shape.
23669
+ */
23670
+ percentage: number().min(0).max(100).nullable(),
23550
23671
  /**
23551
23672
  * Charging source. `'dc'` covers wall/USB adapters; `'solar'` is
23552
23673
  * Reolink-specific for the Solar Panel 2 accessory (will become
@@ -33305,6 +33426,12 @@ Object.freeze({
33305
33426
  addonId: null,
33306
33427
  access: "create"
33307
33428
  },
33429
+ "backup.cancel": {
33430
+ capName: "backup",
33431
+ capScope: "system",
33432
+ addonId: null,
33433
+ access: "create"
33434
+ },
33308
33435
  "backup.delete": {
33309
33436
  capName: "backup",
33310
33437
  capScope: "system",
@@ -33347,6 +33474,12 @@ Object.freeze({
33347
33474
  addonId: null,
33348
33475
  access: "view"
33349
33476
  },
33477
+ "backup.listRuns": {
33478
+ capName: "backup",
33479
+ capScope: "system",
33480
+ addonId: null,
33481
+ access: "view"
33482
+ },
33350
33483
  "backup.listSchedules": {
33351
33484
  capName: "backup",
33352
33485
  capScope: "system",
@@ -37913,6 +38046,12 @@ Object.freeze({
37913
38046
  addonId: null,
37914
38047
  access: "create"
37915
38048
  },
38049
+ "streamBroker.forgetDeviceHardware": {
38050
+ capName: "stream-broker",
38051
+ capScope: "system",
38052
+ addonId: null,
38053
+ access: "delete"
38054
+ },
37916
38055
  "streamBroker.getAllRtspEntries": {
37917
38056
  capName: "stream-broker",
37918
38057
  capScope: "system",
@@ -40371,6 +40510,11 @@ Object.freeze({
40371
40510
  form: "single",
40372
40511
  optional: false
40373
40512
  }],
40513
+ "streamBroker.forgetDeviceHardware": [{
40514
+ name: "deviceId",
40515
+ form: "single",
40516
+ optional: false
40517
+ }],
40374
40518
  "streamBroker.getDeviceAudioMute": [{
40375
40519
  name: "deviceId",
40376
40520
  form: "single",
package/dist/addon.mjs CHANGED
@@ -10603,6 +10603,89 @@ var LocationStatSchema = object({
10603
10603
  fileCount: number(),
10604
10604
  present: boolean()
10605
10605
  });
10606
+ /** Lifecycle of a backup run. Terminal states: succeeded / failed / cancelled. */
10607
+ var BackupRunStateSchema = _enum([
10608
+ "queued",
10609
+ "running",
10610
+ "succeeded",
10611
+ "failed",
10612
+ "cancelled"
10613
+ ]);
10614
+ /**
10615
+ * Where a running backup currently is. `queued` before it starts,
10616
+ * `building` while the tar.gz is being staged, `uploading` during the
10617
+ * per-destination fan-out, `done` once terminal.
10618
+ */
10619
+ var BackupRunPhaseSchema = _enum([
10620
+ "queued",
10621
+ "building",
10622
+ "uploading",
10623
+ "done"
10624
+ ]);
10625
+ /**
10626
+ * Observable state of one backup run — readable WHILE it runs via
10627
+ * `backup.listRuns`. This is what makes the execution queue and
10628
+ * `backup.cancel` usable: the 2026-09-04 incident (two concurrent
10629
+ * multi-GB builds, staging 5.1 GB → 18 GB, load 62) was only
10630
+ * diagnosable with `du` because nothing reported that runs existed or
10631
+ * how large the staged archive had grown.
10632
+ */
10633
+ var BackupRunSchema = object({
10634
+ /** Stable run id — the handle `backup.cancel` takes. */
10635
+ id: string(),
10636
+ state: BackupRunStateSchema,
10637
+ phase: BackupRunPhaseSchema,
10638
+ /**
10639
+ * Resolved destination location ids. Empty while queued (targets are
10640
+ * resolved when the run starts, against the then-current policies).
10641
+ */
10642
+ destinationIds: array(string()).readonly(),
10643
+ label: string().optional(),
10644
+ /** ms-epoch when the run was submitted (trigger call / schedule fire). */
10645
+ requestedAt: number(),
10646
+ /** ms-epoch when the run left the queue and started building. */
10647
+ startedAt: number().optional(),
10648
+ /** ms-epoch when the run reached a terminal state. */
10649
+ finishedAt: number().optional(),
10650
+ /** Compressed bytes of the staging archive written so far. */
10651
+ stagedBytes: number(),
10652
+ /** Final staged archive size, once the build phase completes. */
10653
+ archiveSizeBytes: number().optional(),
10654
+ /** Bytes pushed to the destination currently uploading. */
10655
+ uploadedBytes: number(),
10656
+ /** Destinations where the archive fully landed (uploaded + indexed). */
10657
+ completedDestinationIds: array(string()).readonly(),
10658
+ /** Destinations that failed during the fan-out. */
10659
+ failedDestinationIds: array(string()).readonly(),
10660
+ /** Failure message when `state === 'failed'`. */
10661
+ error: string().optional(),
10662
+ /**
10663
+ * 1-based place in the execution queue — 1 = runs next. Present only
10664
+ * while `state === 'queued'`. Stamped by the orchestrator from the
10665
+ * queue's OWN pending order, never derived from timestamps, so the
10666
+ * UI cannot show an order the executor will not honour.
10667
+ */
10668
+ queuePosition: number().int().min(1).optional()
10669
+ });
10670
+ /**
10671
+ * Result of `backup.trigger`. The call still resolves when the run
10672
+ * terminates (compat with schedule-driven runs and the admin UI), but
10673
+ * it now names the run and says whether it had to WAIT: a trigger that
10674
+ * arrives while another run is in flight is enqueued (or joined onto
10675
+ * an identical already-queued run), never started concurrently.
10676
+ */
10677
+ var BackupTriggerResultSchema = object({
10678
+ /** The run this trigger mapped to — poll it via `listRuns`, stop it via `cancel`. */
10679
+ runId: string(),
10680
+ /** True when the run waited behind an in-flight run instead of starting immediately. */
10681
+ queued: boolean(),
10682
+ /** True when this trigger was coalesced onto an identical already-queued run. */
10683
+ joined: boolean(),
10684
+ /** True when the run was cancelled before completing every destination. */
10685
+ cancelled: boolean(),
10686
+ /** One entry per destination the archive landed at (partial on cancel). */
10687
+ entries: array(BackupEntrySchema).readonly()
10688
+ });
10606
10689
  /**
10607
10690
  * A backup schedule — the N:M "entry" that binds one cron cadence to a
10608
10691
  * SET of destination locations. Supersedes the per-location cron on
@@ -10650,7 +10733,10 @@ method(_void(), array(BackupDestinationInfoSchema).readonly(), { auth: "admin" }
10650
10733
  * retention (manual runs).
10651
10734
  */
10652
10735
  retentionCount: number().int().min(1).max(1e3).optional()
10653
- }).optional(), array(BackupEntrySchema).readonly(), {
10736
+ }).optional(), BackupTriggerResultSchema, {
10737
+ kind: "mutation",
10738
+ auth: "admin"
10739
+ }), method(_void(), array(BackupRunSchema).readonly(), { auth: "admin" }), method(object({ runId: string() }), object({ cancelled: boolean() }), {
10654
10740
  kind: "mutation",
10655
10741
  auth: "admin"
10656
10742
  }), method(_void(), array(BackupEntrySchema).readonly(), { auth: "admin" }), method(_void(), array(LocationStatSchema).readonly(), { auth: "admin" }), method(object({
@@ -11367,6 +11453,14 @@ method(object({
11367
11453
  }), object({ success: literal(true) }), {
11368
11454
  kind: "mutation",
11369
11455
  auth: "admin"
11456
+ }), method(object({ deviceId: number().int().nonnegative() }), object({
11457
+ derivedStreamsDeleted: array(string()).readonly(),
11458
+ assignmentsPurged: boolean(),
11459
+ probeSnapshotsDropped: number().int().nonnegative(),
11460
+ rtspTokenRowsDeleted: number().int().nonnegative()
11461
+ }), {
11462
+ kind: "mutation",
11463
+ auth: "admin"
11370
11464
  }), method(object({
11371
11465
  deviceId: number(),
11372
11466
  /** Absent = the LOWEST assigned profile — a notification attachment is
@@ -19204,7 +19298,20 @@ var RecentTracksQueryInput = object({
19204
19298
  projection: TrackProjectionSchema.optional(),
19205
19299
  /** Include stationary-promoted rows (parked objects). Default false: the
19206
19300
  * feed lists passages; parking records live on the stationary registry. */
19207
- includeStationary: boolean().optional()
19301
+ includeStationary: boolean().optional(),
19302
+ /**
19303
+ * Restrict to these track classes. ABSENT or EMPTY means no filter.
19304
+ *
19305
+ * The same filter `listTracks` takes, because the timeline's class chips must
19306
+ * mean the same thing whether the scope is one camera or twelve. Until this
19307
+ * existed the scoped feed downloaded a page and narrowed it on the phone
19308
+ * while the single-camera path narrowed the read — one filter, two costs.
19309
+ *
19310
+ * A SUPERSET prefilter on `classes[]`, like its single-camera twin: rows
19311
+ * whose class list is unreadable are kept, and the client's rule stays the
19312
+ * exact one.
19313
+ */
19314
+ classes: array(string()).optional()
19208
19315
  });
19209
19316
  var RecentTracksPageSchema = object({
19210
19317
  /** Merged page, ordered by (`lastSeen` DESC, `trackId` DESC). */
@@ -23522,8 +23629,22 @@ var automationControlCapability = {
23522
23629
  * threshold.
23523
23630
  */
23524
23631
  var BatteryStatusSchema = object({
23525
- /** 0..100 inclusive. Firmware-reported. */
23526
- percentage: number().min(0).max(100),
23632
+ /**
23633
+ * 0..100 inclusive, firmware-reported. **`null` means NOT YET KNOWN** — the
23634
+ * provider has registered the capability but no reading has landed.
23635
+ *
23636
+ * It is nullable because it was not, and the only value a provider could
23637
+ * seed with was `0`. A battery camera behind an NVR therefore announced
23638
+ * itself at 0% on every start and corrected itself a moment later, which is
23639
+ * indistinguishable from a real flat battery: it fires the low-battery alert
23640
+ * every time the hub restarts. Unknown is not empty (D315), and on a battery
23641
+ * reading the difference is an alarm.
23642
+ *
23643
+ * `vacuum-control` and `lawn-mower-control` already model it this way.
23644
+ * Consumers must SKIP a null rather than coerce it — `battery-band` already
23645
+ * declines to band a non-finite reading, which is the correct shape.
23646
+ */
23647
+ percentage: number().min(0).max(100).nullable(),
23527
23648
  /**
23528
23649
  * Charging source. `'dc'` covers wall/USB adapters; `'solar'` is
23529
23650
  * Reolink-specific for the Solar Panel 2 accessory (will become
@@ -33282,6 +33403,12 @@ Object.freeze({
33282
33403
  addonId: null,
33283
33404
  access: "create"
33284
33405
  },
33406
+ "backup.cancel": {
33407
+ capName: "backup",
33408
+ capScope: "system",
33409
+ addonId: null,
33410
+ access: "create"
33411
+ },
33285
33412
  "backup.delete": {
33286
33413
  capName: "backup",
33287
33414
  capScope: "system",
@@ -33324,6 +33451,12 @@ Object.freeze({
33324
33451
  addonId: null,
33325
33452
  access: "view"
33326
33453
  },
33454
+ "backup.listRuns": {
33455
+ capName: "backup",
33456
+ capScope: "system",
33457
+ addonId: null,
33458
+ access: "view"
33459
+ },
33327
33460
  "backup.listSchedules": {
33328
33461
  capName: "backup",
33329
33462
  capScope: "system",
@@ -37890,6 +38023,12 @@ Object.freeze({
37890
38023
  addonId: null,
37891
38024
  access: "create"
37892
38025
  },
38026
+ "streamBroker.forgetDeviceHardware": {
38027
+ capName: "stream-broker",
38028
+ capScope: "system",
38029
+ addonId: null,
38030
+ access: "delete"
38031
+ },
37893
38032
  "streamBroker.getAllRtspEntries": {
37894
38033
  capName: "stream-broker",
37895
38034
  capScope: "system",
@@ -40348,6 +40487,11 @@ Object.freeze({
40348
40487
  form: "single",
40349
40488
  optional: false
40350
40489
  }],
40490
+ "streamBroker.forgetDeviceHardware": [{
40491
+ name: "deviceId",
40492
+ form: "single",
40493
+ optional: false
40494
+ }],
40351
40495
  "streamBroker.getDeviceAudioMute": [{
40352
40496
  name: "deviceId",
40353
40497
  form: "single",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@camstack/addon-terminal",
3
- "version": "0.1.62",
3
+ "version": "0.1.64",
4
4
  "description": "Interactive terminal sessions (pty + xterm) as a CamStack addon",
5
5
  "keywords": [
6
6
  "camstack",