@camstack/addon-provider-petkit 0.2.57 → 0.2.59

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
@@ -11629,6 +11629,89 @@ var LocationStatSchema = object({
11629
11629
  fileCount: number(),
11630
11630
  present: boolean()
11631
11631
  });
11632
+ /** Lifecycle of a backup run. Terminal states: succeeded / failed / cancelled. */
11633
+ var BackupRunStateSchema = _enum([
11634
+ "queued",
11635
+ "running",
11636
+ "succeeded",
11637
+ "failed",
11638
+ "cancelled"
11639
+ ]);
11640
+ /**
11641
+ * Where a running backup currently is. `queued` before it starts,
11642
+ * `building` while the tar.gz is being staged, `uploading` during the
11643
+ * per-destination fan-out, `done` once terminal.
11644
+ */
11645
+ var BackupRunPhaseSchema = _enum([
11646
+ "queued",
11647
+ "building",
11648
+ "uploading",
11649
+ "done"
11650
+ ]);
11651
+ /**
11652
+ * Observable state of one backup run — readable WHILE it runs via
11653
+ * `backup.listRuns`. This is what makes the execution queue and
11654
+ * `backup.cancel` usable: the 2026-09-04 incident (two concurrent
11655
+ * multi-GB builds, staging 5.1 GB → 18 GB, load 62) was only
11656
+ * diagnosable with `du` because nothing reported that runs existed or
11657
+ * how large the staged archive had grown.
11658
+ */
11659
+ var BackupRunSchema = object({
11660
+ /** Stable run id — the handle `backup.cancel` takes. */
11661
+ id: string(),
11662
+ state: BackupRunStateSchema,
11663
+ phase: BackupRunPhaseSchema,
11664
+ /**
11665
+ * Resolved destination location ids. Empty while queued (targets are
11666
+ * resolved when the run starts, against the then-current policies).
11667
+ */
11668
+ destinationIds: array(string()).readonly(),
11669
+ label: string().optional(),
11670
+ /** ms-epoch when the run was submitted (trigger call / schedule fire). */
11671
+ requestedAt: number(),
11672
+ /** ms-epoch when the run left the queue and started building. */
11673
+ startedAt: number().optional(),
11674
+ /** ms-epoch when the run reached a terminal state. */
11675
+ finishedAt: number().optional(),
11676
+ /** Compressed bytes of the staging archive written so far. */
11677
+ stagedBytes: number(),
11678
+ /** Final staged archive size, once the build phase completes. */
11679
+ archiveSizeBytes: number().optional(),
11680
+ /** Bytes pushed to the destination currently uploading. */
11681
+ uploadedBytes: number(),
11682
+ /** Destinations where the archive fully landed (uploaded + indexed). */
11683
+ completedDestinationIds: array(string()).readonly(),
11684
+ /** Destinations that failed during the fan-out. */
11685
+ failedDestinationIds: array(string()).readonly(),
11686
+ /** Failure message when `state === 'failed'`. */
11687
+ error: string().optional(),
11688
+ /**
11689
+ * 1-based place in the execution queue — 1 = runs next. Present only
11690
+ * while `state === 'queued'`. Stamped by the orchestrator from the
11691
+ * queue's OWN pending order, never derived from timestamps, so the
11692
+ * UI cannot show an order the executor will not honour.
11693
+ */
11694
+ queuePosition: number().int().min(1).optional()
11695
+ });
11696
+ /**
11697
+ * Result of `backup.trigger`. The call still resolves when the run
11698
+ * terminates (compat with schedule-driven runs and the admin UI), but
11699
+ * it now names the run and says whether it had to WAIT: a trigger that
11700
+ * arrives while another run is in flight is enqueued (or joined onto
11701
+ * an identical already-queued run), never started concurrently.
11702
+ */
11703
+ var BackupTriggerResultSchema = object({
11704
+ /** The run this trigger mapped to — poll it via `listRuns`, stop it via `cancel`. */
11705
+ runId: string(),
11706
+ /** True when the run waited behind an in-flight run instead of starting immediately. */
11707
+ queued: boolean(),
11708
+ /** True when this trigger was coalesced onto an identical already-queued run. */
11709
+ joined: boolean(),
11710
+ /** True when the run was cancelled before completing every destination. */
11711
+ cancelled: boolean(),
11712
+ /** One entry per destination the archive landed at (partial on cancel). */
11713
+ entries: array(BackupEntrySchema).readonly()
11714
+ });
11632
11715
  /**
11633
11716
  * A backup schedule — the N:M "entry" that binds one cron cadence to a
11634
11717
  * SET of destination locations. Supersedes the per-location cron on
@@ -11676,7 +11759,10 @@ method(_void(), array(BackupDestinationInfoSchema).readonly(), { auth: "admin" }
11676
11759
  * retention (manual runs).
11677
11760
  */
11678
11761
  retentionCount: number().int().min(1).max(1e3).optional()
11679
- }).optional(), array(BackupEntrySchema).readonly(), {
11762
+ }).optional(), BackupTriggerResultSchema, {
11763
+ kind: "mutation",
11764
+ auth: "admin"
11765
+ }), method(_void(), array(BackupRunSchema).readonly(), { auth: "admin" }), method(object({ runId: string() }), object({ cancelled: boolean() }), {
11680
11766
  kind: "mutation",
11681
11767
  auth: "admin"
11682
11768
  }), method(_void(), array(BackupEntrySchema).readonly(), { auth: "admin" }), method(_void(), array(LocationStatSchema).readonly(), { auth: "admin" }), method(object({
@@ -12393,6 +12479,14 @@ method(object({
12393
12479
  }), object({ success: literal(true) }), {
12394
12480
  kind: "mutation",
12395
12481
  auth: "admin"
12482
+ }), method(object({ deviceId: number().int().nonnegative() }), object({
12483
+ derivedStreamsDeleted: array(string()).readonly(),
12484
+ assignmentsPurged: boolean(),
12485
+ probeSnapshotsDropped: number().int().nonnegative(),
12486
+ rtspTokenRowsDeleted: number().int().nonnegative()
12487
+ }), {
12488
+ kind: "mutation",
12489
+ auth: "admin"
12396
12490
  }), method(object({
12397
12491
  deviceId: number(),
12398
12492
  /** Absent = the LOWEST assigned profile — a notification attachment is
@@ -20302,7 +20396,20 @@ var RecentTracksQueryInput = object({
20302
20396
  projection: TrackProjectionSchema.optional(),
20303
20397
  /** Include stationary-promoted rows (parked objects). Default false: the
20304
20398
  * feed lists passages; parking records live on the stationary registry. */
20305
- includeStationary: boolean().optional()
20399
+ includeStationary: boolean().optional(),
20400
+ /**
20401
+ * Restrict to these track classes. ABSENT or EMPTY means no filter.
20402
+ *
20403
+ * The same filter `listTracks` takes, because the timeline's class chips must
20404
+ * mean the same thing whether the scope is one camera or twelve. Until this
20405
+ * existed the scoped feed downloaded a page and narrowed it on the phone
20406
+ * while the single-camera path narrowed the read — one filter, two costs.
20407
+ *
20408
+ * A SUPERSET prefilter on `classes[]`, like its single-camera twin: rows
20409
+ * whose class list is unreadable are kept, and the client's rule stays the
20410
+ * exact one.
20411
+ */
20412
+ classes: array(string()).optional()
20306
20413
  });
20307
20414
  var RecentTracksPageSchema = object({
20308
20415
  /** Merged page, ordered by (`lastSeen` DESC, `trackId` DESC). */
@@ -24472,8 +24579,22 @@ var automationControlCapability = {
24472
24579
  * threshold.
24473
24580
  */
24474
24581
  var BatteryStatusSchema = object({
24475
- /** 0..100 inclusive. Firmware-reported. */
24476
- percentage: number().min(0).max(100),
24582
+ /**
24583
+ * 0..100 inclusive, firmware-reported. **`null` means NOT YET KNOWN** — the
24584
+ * provider has registered the capability but no reading has landed.
24585
+ *
24586
+ * It is nullable because it was not, and the only value a provider could
24587
+ * seed with was `0`. A battery camera behind an NVR therefore announced
24588
+ * itself at 0% on every start and corrected itself a moment later, which is
24589
+ * indistinguishable from a real flat battery: it fires the low-battery alert
24590
+ * every time the hub restarts. Unknown is not empty (D315), and on a battery
24591
+ * reading the difference is an alarm.
24592
+ *
24593
+ * `vacuum-control` and `lawn-mower-control` already model it this way.
24594
+ * Consumers must SKIP a null rather than coerce it — `battery-band` already
24595
+ * declines to band a non-finite reading, which is the correct shape.
24596
+ */
24597
+ percentage: number().min(0).max(100).nullable(),
24477
24598
  /**
24478
24599
  * Charging source. `'dc'` covers wall/USB adapters; `'solar'` is
24479
24600
  * Reolink-specific for the Solar Panel 2 accessory (will become
@@ -34242,6 +34363,12 @@ Object.freeze({
34242
34363
  addonId: null,
34243
34364
  access: "create"
34244
34365
  },
34366
+ "backup.cancel": {
34367
+ capName: "backup",
34368
+ capScope: "system",
34369
+ addonId: null,
34370
+ access: "create"
34371
+ },
34245
34372
  "backup.delete": {
34246
34373
  capName: "backup",
34247
34374
  capScope: "system",
@@ -34284,6 +34411,12 @@ Object.freeze({
34284
34411
  addonId: null,
34285
34412
  access: "view"
34286
34413
  },
34414
+ "backup.listRuns": {
34415
+ capName: "backup",
34416
+ capScope: "system",
34417
+ addonId: null,
34418
+ access: "view"
34419
+ },
34287
34420
  "backup.listSchedules": {
34288
34421
  capName: "backup",
34289
34422
  capScope: "system",
@@ -38850,6 +38983,12 @@ Object.freeze({
38850
38983
  addonId: null,
38851
38984
  access: "create"
38852
38985
  },
38986
+ "streamBroker.forgetDeviceHardware": {
38987
+ capName: "stream-broker",
38988
+ capScope: "system",
38989
+ addonId: null,
38990
+ access: "delete"
38991
+ },
38853
38992
  "streamBroker.getAllRtspEntries": {
38854
38993
  capName: "stream-broker",
38855
38994
  capScope: "system",
@@ -41308,6 +41447,11 @@ Object.freeze({
41308
41447
  form: "single",
41309
41448
  optional: false
41310
41449
  }],
41450
+ "streamBroker.forgetDeviceHardware": [{
41451
+ name: "deviceId",
41452
+ form: "single",
41453
+ optional: false
41454
+ }],
41311
41455
  "streamBroker.getDeviceAudioMute": [{
41312
41456
  name: "deviceId",
41313
41457
  form: "single",
package/dist/addon.mjs CHANGED
@@ -11628,6 +11628,89 @@ var LocationStatSchema = object({
11628
11628
  fileCount: number(),
11629
11629
  present: boolean()
11630
11630
  });
11631
+ /** Lifecycle of a backup run. Terminal states: succeeded / failed / cancelled. */
11632
+ var BackupRunStateSchema = _enum([
11633
+ "queued",
11634
+ "running",
11635
+ "succeeded",
11636
+ "failed",
11637
+ "cancelled"
11638
+ ]);
11639
+ /**
11640
+ * Where a running backup currently is. `queued` before it starts,
11641
+ * `building` while the tar.gz is being staged, `uploading` during the
11642
+ * per-destination fan-out, `done` once terminal.
11643
+ */
11644
+ var BackupRunPhaseSchema = _enum([
11645
+ "queued",
11646
+ "building",
11647
+ "uploading",
11648
+ "done"
11649
+ ]);
11650
+ /**
11651
+ * Observable state of one backup run — readable WHILE it runs via
11652
+ * `backup.listRuns`. This is what makes the execution queue and
11653
+ * `backup.cancel` usable: the 2026-09-04 incident (two concurrent
11654
+ * multi-GB builds, staging 5.1 GB → 18 GB, load 62) was only
11655
+ * diagnosable with `du` because nothing reported that runs existed or
11656
+ * how large the staged archive had grown.
11657
+ */
11658
+ var BackupRunSchema = object({
11659
+ /** Stable run id — the handle `backup.cancel` takes. */
11660
+ id: string(),
11661
+ state: BackupRunStateSchema,
11662
+ phase: BackupRunPhaseSchema,
11663
+ /**
11664
+ * Resolved destination location ids. Empty while queued (targets are
11665
+ * resolved when the run starts, against the then-current policies).
11666
+ */
11667
+ destinationIds: array(string()).readonly(),
11668
+ label: string().optional(),
11669
+ /** ms-epoch when the run was submitted (trigger call / schedule fire). */
11670
+ requestedAt: number(),
11671
+ /** ms-epoch when the run left the queue and started building. */
11672
+ startedAt: number().optional(),
11673
+ /** ms-epoch when the run reached a terminal state. */
11674
+ finishedAt: number().optional(),
11675
+ /** Compressed bytes of the staging archive written so far. */
11676
+ stagedBytes: number(),
11677
+ /** Final staged archive size, once the build phase completes. */
11678
+ archiveSizeBytes: number().optional(),
11679
+ /** Bytes pushed to the destination currently uploading. */
11680
+ uploadedBytes: number(),
11681
+ /** Destinations where the archive fully landed (uploaded + indexed). */
11682
+ completedDestinationIds: array(string()).readonly(),
11683
+ /** Destinations that failed during the fan-out. */
11684
+ failedDestinationIds: array(string()).readonly(),
11685
+ /** Failure message when `state === 'failed'`. */
11686
+ error: string().optional(),
11687
+ /**
11688
+ * 1-based place in the execution queue — 1 = runs next. Present only
11689
+ * while `state === 'queued'`. Stamped by the orchestrator from the
11690
+ * queue's OWN pending order, never derived from timestamps, so the
11691
+ * UI cannot show an order the executor will not honour.
11692
+ */
11693
+ queuePosition: number().int().min(1).optional()
11694
+ });
11695
+ /**
11696
+ * Result of `backup.trigger`. The call still resolves when the run
11697
+ * terminates (compat with schedule-driven runs and the admin UI), but
11698
+ * it now names the run and says whether it had to WAIT: a trigger that
11699
+ * arrives while another run is in flight is enqueued (or joined onto
11700
+ * an identical already-queued run), never started concurrently.
11701
+ */
11702
+ var BackupTriggerResultSchema = object({
11703
+ /** The run this trigger mapped to — poll it via `listRuns`, stop it via `cancel`. */
11704
+ runId: string(),
11705
+ /** True when the run waited behind an in-flight run instead of starting immediately. */
11706
+ queued: boolean(),
11707
+ /** True when this trigger was coalesced onto an identical already-queued run. */
11708
+ joined: boolean(),
11709
+ /** True when the run was cancelled before completing every destination. */
11710
+ cancelled: boolean(),
11711
+ /** One entry per destination the archive landed at (partial on cancel). */
11712
+ entries: array(BackupEntrySchema).readonly()
11713
+ });
11631
11714
  /**
11632
11715
  * A backup schedule — the N:M "entry" that binds one cron cadence to a
11633
11716
  * SET of destination locations. Supersedes the per-location cron on
@@ -11675,7 +11758,10 @@ method(_void(), array(BackupDestinationInfoSchema).readonly(), { auth: "admin" }
11675
11758
  * retention (manual runs).
11676
11759
  */
11677
11760
  retentionCount: number().int().min(1).max(1e3).optional()
11678
- }).optional(), array(BackupEntrySchema).readonly(), {
11761
+ }).optional(), BackupTriggerResultSchema, {
11762
+ kind: "mutation",
11763
+ auth: "admin"
11764
+ }), method(_void(), array(BackupRunSchema).readonly(), { auth: "admin" }), method(object({ runId: string() }), object({ cancelled: boolean() }), {
11679
11765
  kind: "mutation",
11680
11766
  auth: "admin"
11681
11767
  }), method(_void(), array(BackupEntrySchema).readonly(), { auth: "admin" }), method(_void(), array(LocationStatSchema).readonly(), { auth: "admin" }), method(object({
@@ -12392,6 +12478,14 @@ method(object({
12392
12478
  }), object({ success: literal(true) }), {
12393
12479
  kind: "mutation",
12394
12480
  auth: "admin"
12481
+ }), method(object({ deviceId: number().int().nonnegative() }), object({
12482
+ derivedStreamsDeleted: array(string()).readonly(),
12483
+ assignmentsPurged: boolean(),
12484
+ probeSnapshotsDropped: number().int().nonnegative(),
12485
+ rtspTokenRowsDeleted: number().int().nonnegative()
12486
+ }), {
12487
+ kind: "mutation",
12488
+ auth: "admin"
12395
12489
  }), method(object({
12396
12490
  deviceId: number(),
12397
12491
  /** Absent = the LOWEST assigned profile — a notification attachment is
@@ -20301,7 +20395,20 @@ var RecentTracksQueryInput = object({
20301
20395
  projection: TrackProjectionSchema.optional(),
20302
20396
  /** Include stationary-promoted rows (parked objects). Default false: the
20303
20397
  * feed lists passages; parking records live on the stationary registry. */
20304
- includeStationary: boolean().optional()
20398
+ includeStationary: boolean().optional(),
20399
+ /**
20400
+ * Restrict to these track classes. ABSENT or EMPTY means no filter.
20401
+ *
20402
+ * The same filter `listTracks` takes, because the timeline's class chips must
20403
+ * mean the same thing whether the scope is one camera or twelve. Until this
20404
+ * existed the scoped feed downloaded a page and narrowed it on the phone
20405
+ * while the single-camera path narrowed the read — one filter, two costs.
20406
+ *
20407
+ * A SUPERSET prefilter on `classes[]`, like its single-camera twin: rows
20408
+ * whose class list is unreadable are kept, and the client's rule stays the
20409
+ * exact one.
20410
+ */
20411
+ classes: array(string()).optional()
20305
20412
  });
20306
20413
  var RecentTracksPageSchema = object({
20307
20414
  /** Merged page, ordered by (`lastSeen` DESC, `trackId` DESC). */
@@ -24471,8 +24578,22 @@ var automationControlCapability = {
24471
24578
  * threshold.
24472
24579
  */
24473
24580
  var BatteryStatusSchema = object({
24474
- /** 0..100 inclusive. Firmware-reported. */
24475
- percentage: number().min(0).max(100),
24581
+ /**
24582
+ * 0..100 inclusive, firmware-reported. **`null` means NOT YET KNOWN** — the
24583
+ * provider has registered the capability but no reading has landed.
24584
+ *
24585
+ * It is nullable because it was not, and the only value a provider could
24586
+ * seed with was `0`. A battery camera behind an NVR therefore announced
24587
+ * itself at 0% on every start and corrected itself a moment later, which is
24588
+ * indistinguishable from a real flat battery: it fires the low-battery alert
24589
+ * every time the hub restarts. Unknown is not empty (D315), and on a battery
24590
+ * reading the difference is an alarm.
24591
+ *
24592
+ * `vacuum-control` and `lawn-mower-control` already model it this way.
24593
+ * Consumers must SKIP a null rather than coerce it — `battery-band` already
24594
+ * declines to band a non-finite reading, which is the correct shape.
24595
+ */
24596
+ percentage: number().min(0).max(100).nullable(),
24476
24597
  /**
24477
24598
  * Charging source. `'dc'` covers wall/USB adapters; `'solar'` is
24478
24599
  * Reolink-specific for the Solar Panel 2 accessory (will become
@@ -34241,6 +34362,12 @@ Object.freeze({
34241
34362
  addonId: null,
34242
34363
  access: "create"
34243
34364
  },
34365
+ "backup.cancel": {
34366
+ capName: "backup",
34367
+ capScope: "system",
34368
+ addonId: null,
34369
+ access: "create"
34370
+ },
34244
34371
  "backup.delete": {
34245
34372
  capName: "backup",
34246
34373
  capScope: "system",
@@ -34283,6 +34410,12 @@ Object.freeze({
34283
34410
  addonId: null,
34284
34411
  access: "view"
34285
34412
  },
34413
+ "backup.listRuns": {
34414
+ capName: "backup",
34415
+ capScope: "system",
34416
+ addonId: null,
34417
+ access: "view"
34418
+ },
34286
34419
  "backup.listSchedules": {
34287
34420
  capName: "backup",
34288
34421
  capScope: "system",
@@ -38849,6 +38982,12 @@ Object.freeze({
38849
38982
  addonId: null,
38850
38983
  access: "create"
38851
38984
  },
38985
+ "streamBroker.forgetDeviceHardware": {
38986
+ capName: "stream-broker",
38987
+ capScope: "system",
38988
+ addonId: null,
38989
+ access: "delete"
38990
+ },
38852
38991
  "streamBroker.getAllRtspEntries": {
38853
38992
  capName: "stream-broker",
38854
38993
  capScope: "system",
@@ -41307,6 +41446,11 @@ Object.freeze({
41307
41446
  form: "single",
41308
41447
  optional: false
41309
41448
  }],
41449
+ "streamBroker.forgetDeviceHardware": [{
41450
+ name: "deviceId",
41451
+ form: "single",
41452
+ optional: false
41453
+ }],
41310
41454
  "streamBroker.getDeviceAudioMute": [{
41311
41455
  name: "deviceId",
41312
41456
  form: "single",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@camstack/addon-provider-petkit",
3
- "version": "0.2.57",
3
+ "version": "0.2.59",
4
4
  "description": "PetKit smart-feeder device-provider addon for CamStack — wraps the @apocaliss92/nodepetkit PetKit cloud client",
5
5
  "keywords": [
6
6
  "camstack",