@camstack/addon-provider-homeassistant 1.2.62 → 1.2.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
@@ -1,5 +1,5 @@
1
1
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
- const require_dist = require("./dist-u1L6UZmY.js");
2
+ const require_dist = require("./dist-Cm6-aUVi.js");
3
3
  let node_crypto = require("node:crypto");
4
4
  let node_zlib = require("node:zlib");
5
5
  //#region src/ha-device-source.ts
package/dist/addon.mjs CHANGED
@@ -1,4 +1,4 @@
1
- import { $ as presenceCapability, A as controlCapability, At as EventCategory, B as humiditySensorCapability, C as buildAddonRouteProvider, Ct as number, D as colorCapability, Dt as union, E as climateControlCapability, Et as string, F as eventEmitterCapability, G as motionCapability, H as lawnMowerControlCapability, I as fanControlCapability, J as notifierCapability, K as normalizeUnit, L as floodCapability, M as deviceAdoptionCapability, O as connectivityCapability, Ot as unknown, P as enumSensorCapability, Q as prepareNotification, R as gasCapability, S as brokerCapability, St as literal, T as carbonMonoxideCapability, Tt as record, U as lockControlCapability, V as imageCapability, W as mediaPlayerCapability, Y as numericSensorCapability, Z as powerMeterCapability, _ as automationControlCapability, _t as createEvent, at as temperatureSensorCapability, b as binaryCapability, bt as array, ct as valveCapability, d as TargetSchema, dt as weatherCapability, et as pressureSensorCapability, f as accessoriesCapability, ft as errMsg, g as ambientLightSensorCapability, gt as DeviceType, h as alarmPanelCapability, ht as DeviceRole, it as tamperCapability, j as coverCapability, k as contactCapability, kt as url, lt as vibrationCapability, m as airQualitySensorCapability, mt as DeviceFeature, n as BaseDevice, nt as smokeCapability, ot as updateCapability, p as addonRoutesCapability, q as notificationOutputCapability, r as BaseDeviceProvider, rt as switchCapability, s as EnumSensorDateTimeFormatSchema, st as vacuumControlCapability, tt as scriptRunnerCapability, ut as waterHeaterCapability, v as batteryCapability, w as buttonCapability, wt as object, x as brightnessCapability, xt as discriminatedUnion, y as bestLocationMatch, yt as _enum, z as humidifierCapability } from "./dist-DV4Xqi_x.mjs";
1
+ import { $ as presenceCapability, A as controlCapability, At as EventCategory, B as humiditySensorCapability, C as buildAddonRouteProvider, Ct as number, D as colorCapability, Dt as union, E as climateControlCapability, Et as string, F as eventEmitterCapability, G as motionCapability, H as lawnMowerControlCapability, I as fanControlCapability, J as notifierCapability, K as normalizeUnit, L as floodCapability, M as deviceAdoptionCapability, O as connectivityCapability, Ot as unknown, P as enumSensorCapability, Q as prepareNotification, R as gasCapability, S as brokerCapability, St as literal, T as carbonMonoxideCapability, Tt as record, U as lockControlCapability, V as imageCapability, W as mediaPlayerCapability, Y as numericSensorCapability, Z as powerMeterCapability, _ as automationControlCapability, _t as createEvent, at as temperatureSensorCapability, b as binaryCapability, bt as array, ct as valveCapability, d as TargetSchema, dt as weatherCapability, et as pressureSensorCapability, f as accessoriesCapability, ft as errMsg, g as ambientLightSensorCapability, gt as DeviceType, h as alarmPanelCapability, ht as DeviceRole, it as tamperCapability, j as coverCapability, k as contactCapability, kt as url, lt as vibrationCapability, m as airQualitySensorCapability, mt as DeviceFeature, n as BaseDevice, nt as smokeCapability, ot as updateCapability, p as addonRoutesCapability, q as notificationOutputCapability, r as BaseDeviceProvider, rt as switchCapability, s as EnumSensorDateTimeFormatSchema, st as vacuumControlCapability, tt as scriptRunnerCapability, ut as waterHeaterCapability, v as batteryCapability, w as buttonCapability, wt as object, x as brightnessCapability, xt as discriminatedUnion, y as bestLocationMatch, yt as _enum, z as humidifierCapability } from "./dist-Cu_caOlV.mjs";
2
2
  import { randomUUID } from "node:crypto";
3
3
  import { brotliCompressSync, deflateSync, gzipSync } from "node:zlib";
4
4
  //#region src/ha-device-source.ts
@@ -8299,6 +8299,13 @@ var MediaRelocateModeSchema = _enum([
8299
8299
  ]);
8300
8300
  var RelocateMediaInputSchema = object({
8301
8301
  toLocationId: string(),
8302
+ /**
8303
+ * Restrict the pass to rows currently on this location. Omitted / `'*'` =
8304
+ * every row that is not already on `toLocationId` (the historical
8305
+ * behaviour). A named source is what a from→to migration needs: without it
8306
+ * "move events off disk 2" also emptied disk 1.
8307
+ */
8308
+ fromLocationId: string().optional(),
8302
8309
  throttleMbps: number().min(1).max(1e3).optional(),
8303
8310
  /** Omitted = `move`, the pre-existing behaviour. */
8304
8311
  mode: MediaRelocateModeSchema.optional()
@@ -8366,6 +8373,19 @@ var StorageMigrationDestinationsSchema = object({
8366
8373
  galleryMedia: string().min(1).optional()
8367
8374
  }).refine((value) => Object.keys(value).length > 0, { message: "select at least one storage class" });
8368
8375
  /**
8376
+ * Optional named source per class. Omitted = the class's current default
8377
+ * (the historical behaviour). A named source that is NOT the default is a
8378
+ * drain of that disk: bytes move, the default stays, and the source is
8379
+ * disabled when the move finishes.
8380
+ */
8381
+ var StorageMigrationSourcesSchema = object({
8382
+ recordings: string().min(1).optional(),
8383
+ recordingsLow: string().min(1).optional(),
8384
+ eventMedia: string().min(1).optional(),
8385
+ backups: string().min(1).optional(),
8386
+ galleryMedia: string().min(1).optional()
8387
+ }).optional();
8388
+ /**
8369
8389
  * How a migration sequences the cutover against the byte move.
8370
8390
  *
8371
8391
  * - `blocking` — the historical order: pause, move every byte, repoint,
@@ -8387,6 +8407,8 @@ var StorageMigrationModeSchema = _enum(["blocking", "nonBlocking"]);
8387
8407
  /** Shared input for planning and starting an orchestrated storage migration. */
8388
8408
  var StorageMigrationInputSchema = object({
8389
8409
  destinations: StorageMigrationDestinationsSchema,
8410
+ /** Omitted = each class's current default. */
8411
+ sources: StorageMigrationSourcesSchema,
8390
8412
  throttleMbps: number().min(1).max(1e3).optional(),
8391
8413
  /** Omitted = `blocking`, which stays the default. */
8392
8414
  mode: StorageMigrationModeSchema.optional()
@@ -8466,6 +8488,13 @@ var StorageMigrationMoveSchema = object({
8466
8488
  storageClass: StorageMigrationClassSchema,
8467
8489
  fromLocationId: string(),
8468
8490
  toLocationId: string(),
8491
+ /**
8492
+ * True when `from` was NOT the class default at plan time. The move still
8493
+ * copies bytes, but the default is left alone and the source is disabled
8494
+ * once the copy verifies. Absent on jobs planned before this field existed
8495
+ * — those jobs always repointed, which is `false`.
8496
+ */
8497
+ freezeSource: boolean().optional(),
8469
8498
  moverJobId: string().nullable(),
8470
8499
  state: RelocateJobStateSchema.nullable(),
8471
8500
  error: string().nullable(),
@@ -8479,6 +8508,7 @@ var StorageMigrationJobSchema = object({
8479
8508
  * can tell a seconds-long cutover from a thirty-hour one. */
8480
8509
  mode: StorageMigrationModeSchema,
8481
8510
  destinations: StorageMigrationDestinationsSchema,
8511
+ sources: StorageMigrationSourcesSchema,
8482
8512
  throttleMbps: number(),
8483
8513
  moves: array(StorageMigrationMoveSchema),
8484
8514
  pauseLeaseId: string().nullable(),
@@ -8504,6 +8534,7 @@ var StorageMigrationFindingSchema = object({
8504
8534
  });
8505
8535
  var StorageMigrationPlanSchema = object({
8506
8536
  destinations: StorageMigrationDestinationsSchema,
8537
+ sources: StorageMigrationSourcesSchema,
8507
8538
  /** The mode this plan was built for. A plan is only valid for its mode: the
8508
8539
  * `eventMedia` seal gate and the single-cardinality refusal both depend on
8509
8540
  * it. */
@@ -8511,7 +8542,8 @@ var StorageMigrationPlanSchema = object({
8511
8542
  moves: array(object({
8512
8543
  storageClass: StorageMigrationClassSchema,
8513
8544
  fromLocationId: string(),
8514
- toLocationId: string()
8545
+ toLocationId: string(),
8546
+ freezeSource: boolean().optional()
8515
8547
  })),
8516
8548
  findings: array(StorageMigrationFindingSchema)
8517
8549
  });
@@ -8689,10 +8721,51 @@ var LedgerWalkReportSchema = object({
8689
8721
  var RelocatableMediaCountSchema = object({ rows: number().int().nonnegative() }).nullable();
8690
8722
  var RelocatableMediaCountInputSchema = object({
8691
8723
  toLocationId: string().min(1),
8724
+ /** Restrict the count to one source; omitted / `'*'` = every non-target row. */
8725
+ fromLocationId: string().optional(),
8692
8726
  /** Omitted = `move`. */
8693
8727
  mode: MediaRelocateModeSchema.optional()
8694
8728
  });
8695
8729
  /**
8730
+ * Operator cleanup of leftover analytics rows, optional debug media, and
8731
+ * ghost ledger entries on frozen footage locations.
8732
+ *
8733
+ * A pass is tens of minutes on a standing backlog. The hub method RETURNS
8734
+ * `{ jobId }` immediately; progress is `cleanupStatus`. Awaiting the work
8735
+ * is how `addons.custom` hit the 60 s UDS deadline while reclaim continued
8736
+ * with no operator-visible status.
8737
+ */
8738
+ var StorageCleanupPhaseSchema = _enum([
8739
+ "orphans",
8740
+ "debug-media",
8741
+ "ghost-ledger",
8742
+ "done",
8743
+ "failed",
8744
+ "cancelled"
8745
+ ]);
8746
+ var StorageCleanupInputSchema = object({
8747
+ /** Also walk motion stills / track filmstrips. Off by default. */
8748
+ includeDebugMedia: boolean().optional() });
8749
+ var StorageCleanupJobSchema = object({
8750
+ jobId: string(),
8751
+ phase: StorageCleanupPhaseSchema,
8752
+ includeDebugMedia: boolean(),
8753
+ orphansReclaimed: number().int().nonnegative(),
8754
+ orphanBytesReclaimed: number().int().nonnegative(),
8755
+ debugMediaReclaimed: number().int().nonnegative(),
8756
+ debugMediaBytesReclaimed: number().int().nonnegative(),
8757
+ ghostsForgotten: number().int().nonnegative(),
8758
+ ghostBytesForgotten: number().int().nonnegative(),
8759
+ /** Short operator-facing line: current collection, pass, or location. */
8760
+ detail: string().nullable(),
8761
+ cancelRequested: boolean(),
8762
+ startedAt: number(),
8763
+ updatedAt: number(),
8764
+ finishedAt: number().nullable(),
8765
+ error: string().nullable()
8766
+ });
8767
+ var StorageCleanupStatusInputSchema = object({ jobId: string().optional() });
8768
+ /**
8696
8769
  * `StorageLocationType` — an addon-declared id that identifies the *kind* of
8697
8770
  * storage a location serves. Defined here (not in `capabilities/storage.cap.ts`)
8698
8771
  * so the persisted record schema and the consumer-facing cap can both consume it
@@ -8720,11 +8793,10 @@ var StorageLocationTypeSchema = string().regex(/^[a-z][a-zA-Z0-9-]*$/);
8720
8793
  * The default location for a type uses `id === <type>:default` by
8721
8794
  * convention (the bare type ref like `'backups'` resolves to it).
8722
8795
  *
8723
- * `isSystem: true` marks a location as orchestrator-seeded and
8724
- * undeletable. The bootstrap-installed defaults (one per type) carry
8725
- * this flag; operator-added locations don't. Editing the config of
8726
- * a system location is allowed (path migration, provider swap) but
8727
- * deleting it is rejected at the cap level.
8796
+ * `isSystem` is a legacy persisted flag. Seed still creates the initial
8797
+ * `<type>:default` locations; the flag is no longer a lock, a badge, or a
8798
+ * prune selector. New writes leave it false. Deletion is gated on uniqueness
8799
+ * / last-enabled, not on this bit.
8728
8800
  */
8729
8801
  var StorageLocationSchema = object({
8730
8802
  id: string().regex(/^[a-z][a-zA-Z0-9-]*:[a-zA-Z0-9-]+$/),
@@ -13405,6 +13477,12 @@ method(object({
13405
13477
  }), _void(), {
13406
13478
  kind: "mutation",
13407
13479
  auth: "admin"
13480
+ }), method(object({
13481
+ from: string(),
13482
+ to: string()
13483
+ }), object({ moved: number() }), {
13484
+ kind: "mutation",
13485
+ auth: "admin"
13408
13486
  }), method(object({
13409
13487
  deviceId: number(),
13410
13488
  disabled: boolean()
@@ -16169,6 +16247,8 @@ var NcSystemEventKindSchema = _enum([
16169
16247
  "device-offline",
16170
16248
  "device-disabled",
16171
16249
  "device-enabled",
16250
+ "device-battery-low",
16251
+ "device-battery-normal",
16172
16252
  "stream-online",
16173
16253
  "stream-offline",
16174
16254
  "node-online",
@@ -19443,46 +19523,6 @@ var RecentTracksPageSchema = object({
19443
19523
  /** Cursor for the next page, or null when this page is the last. */
19444
19524
  nextCursor: string().nullable()
19445
19525
  });
19446
- var LIST_GROUPS_DEFAULT_LIMIT = 40;
19447
- var LIST_GROUPS_MAX_LIMIT = 100;
19448
- var AnalyticsGroupRecordSchema = object({
19449
- id: string(),
19450
- deviceId: number().int(),
19451
- openedAt: number().int(),
19452
- closedAt: number().int(),
19453
- timestamp: number().int(),
19454
- memberCount: number().int(),
19455
- memberTrackIds: array(string()).readonly(),
19456
- className: string(),
19457
- classes: array(string()).readonly(),
19458
- /** Relative event-media path, or null when the group has no picture yet. */
19459
- mediaUrl: string().nullable(),
19460
- singleton: boolean()
19461
- });
19462
- var AnalyticsGroupMemberSchema = object({
19463
- trackId: string(),
19464
- deviceId: number().int(),
19465
- className: string(),
19466
- firstSeen: number().int(),
19467
- lastSeen: number().int(),
19468
- mediaUrl: string().nullable()
19469
- });
19470
- var AnalyticsGroupDetailSchema = AnalyticsGroupRecordSchema.extend({ members: array(AnalyticsGroupMemberSchema).readonly() });
19471
- var ListGroupsQueryInput = object({
19472
- /** Devices to merge. An empty array yields `{ groups: [], nextCursor: null }`. */
19473
- deviceIds: array(number()),
19474
- /** Window lower bound on `closedAt` (inclusive). */
19475
- since: number().optional(),
19476
- /** Window upper bound on `openedAt` (inclusive). */
19477
- until: number().optional(),
19478
- limit: number().int().min(1).max(LIST_GROUPS_MAX_LIMIT).default(LIST_GROUPS_DEFAULT_LIMIT),
19479
- /** Opaque continuation cursor from a previous page's `nextCursor`. */
19480
- cursor: string().optional()
19481
- });
19482
- var ListGroupsPageSchema = object({
19483
- groups: array(AnalyticsGroupRecordSchema).readonly(),
19484
- nextCursor: string().nullable()
19485
- });
19486
19526
  var KEY_EVENTS_DEFAULT_LIMIT = 50;
19487
19527
  var KEY_EVENTS_MAX_LIMIT = 200;
19488
19528
  var KeyEventQueryInput = object({
@@ -19586,9 +19626,7 @@ var TrackCascadeCountsSchema = object({
19586
19626
  /** Unassigned plate reads removed (best-effort; plate leg deferred to plate-intelligence). */
19587
19627
  plates: number().int(),
19588
19628
  /** Per-track CLIP search vectors removed (best-effort). */
19589
- embeddings: number().int(),
19590
- /** Group membership + group rows removed with their last member (best-effort). */
19591
- groups: number().int()
19629
+ embeddings: number().int()
19592
19630
  });
19593
19631
  /** Disk-wins reconcile: media rows whose blobs are gone, then empty tracks. */
19594
19632
  var DiskReconcileCountsSchema = object({
@@ -19758,6 +19796,47 @@ var RebuildStatusSchema = object({
19758
19796
  /** Present when the pass ended by throwing. */
19759
19797
  error: string().nullable()
19760
19798
  });
19799
+ /**
19800
+ * Acknowledgement that a debug-media reclaim STARTED.
19801
+ *
19802
+ * The pass is paced at ~2 MB/s over a standing 100 GB — tens of minutes — so
19803
+ * it runs detached and this returns immediately. Awaiting it is how the
19804
+ * `addons.custom` door hit the 60 s UDS deadline while the walk carried on
19805
+ * with no status. Poll {@link pipelineAnalyticsCapability.methods.getMediaReclaimStatus}.
19806
+ */
19807
+ var MediaReclaimStartResultSchema = object({
19808
+ started: boolean(),
19809
+ /** True when a pass was already running; the new request is ignored. */
19810
+ alreadyRunning: boolean()
19811
+ });
19812
+ var MediaReclaimInputSchema = object({
19813
+ mode: _enum(["report", "reclaim"]).default("report"),
19814
+ scopes: array(_enum(["motion-still", "track-filmstrip"])).min(1).optional(),
19815
+ deviceIds: array(number().int()).min(1).optional(),
19816
+ restart: boolean().optional(),
19817
+ pageSize: number().int().min(50).max(5e3).optional(),
19818
+ maxRowsPerDevice: number().int().min(1).max(5e5).optional(),
19819
+ maxReclaimPerDevice: number().int().min(1).max(5e5).optional(),
19820
+ maxBytesPerRun: number().int().min(1).optional(),
19821
+ budgetMinutes: number().int().min(1).max(720).optional(),
19822
+ throttleBytesPerSec: number().int().min(64 * 1024).optional(),
19823
+ graceMinutes: number().int().min(1).max(10080).optional()
19824
+ });
19825
+ var MediaReclaimStatusSchema = object({
19826
+ running: boolean(),
19827
+ mode: _enum(["report", "reclaim"]).nullable(),
19828
+ totalExamined: number(),
19829
+ totalEligible: number(),
19830
+ totalReclaimed: number(),
19831
+ totalBytesReclaimed: number(),
19832
+ totalRefused: number(),
19833
+ /** Device+scope windows finished in this pass. */
19834
+ devicesDone: number(),
19835
+ complete: boolean().nullable(),
19836
+ startedAtMs: number().nullable(),
19837
+ finishedAtMs: number().nullable(),
19838
+ error: string().nullable()
19839
+ });
19761
19840
  var ReplayFrameInputSchema = object({
19762
19841
  timestamp: number(),
19763
19842
  frame: PipelineRunResultBridge
@@ -19796,10 +19875,7 @@ DeviceType.Camera, method(object({ deviceId: number() }), array(TrackSchema).rea
19796
19875
  * stationary registry). Default false: the timeline lists passages,
19797
19876
  * not parking records (operator decision, 2026-08-15). */
19798
19877
  includeStationary: boolean().optional()
19799
- }), array(TrackSchema).readonly()), method(RecentTracksQueryInput, RecentTracksPageSchema), method(ListGroupsQueryInput, ListGroupsPageSchema), method(object({
19800
- deviceId: number(),
19801
- groupId: string().min(1)
19802
- }), AnalyticsGroupDetailSchema.nullable()), method(object({ deviceId: number() }), _void(), {
19878
+ }), array(TrackSchema).readonly()), method(RecentTracksQueryInput, RecentTracksPageSchema), method(object({ deviceId: number() }), _void(), {
19803
19879
  kind: "mutation",
19804
19880
  auth: "admin"
19805
19881
  }), method(DeviceEventQueryInput, array(MotionEventSchema).readonly()), method(ObjectEventQueryInput, array(ObjectEventSchema).readonly()), method(DeviceEventQueryInput, array(AudioEventSchema).readonly()), method(object({ deviceId: number() }), array(EventKindDescriptorSchema).readonly()), method(object({ deviceIds: array(number()).min(1).max(200) }), array(EventKindsForDeviceSchema).readonly()), method(object({
@@ -19899,6 +19975,12 @@ DeviceType.Camera, method(object({ deviceId: number() }), array(TrackSchema).rea
19899
19975
  }), method(OpsLogQueryInputSchema, array(OpsLogEntrySchema).readonly(), {
19900
19976
  kind: "query",
19901
19977
  auth: "admin"
19978
+ }), method(MediaReclaimInputSchema, MediaReclaimStartResultSchema, {
19979
+ kind: "mutation",
19980
+ auth: "admin"
19981
+ }), method(object({}), MediaReclaimStatusSchema, {
19982
+ kind: "query",
19983
+ auth: "admin"
19902
19984
  }), method(object({ deviceIds: array(number()).optional() }), TrainingExportSummarySchema, {
19903
19985
  kind: "query",
19904
19986
  auth: "admin"
@@ -21869,7 +21951,13 @@ method(StorageMigrationInputSchema, StorageMigrationPlanSchema, { auth: "admin"
21869
21951
  }), method(object({}), array(StorageMigrationMoverSchema).readonly(), { auth: "admin" }), method(object({}), array(StorageMigrationResidueSchema).readonly(), { auth: "admin" }), method(StorageMigrationDrainInputSchema, object({ jobId: string() }), {
21870
21952
  kind: "mutation",
21871
21953
  auth: "admin"
21872
- });
21954
+ }), method(StorageCleanupInputSchema, object({ jobId: string() }), {
21955
+ kind: "mutation",
21956
+ auth: "admin"
21957
+ }), method(StorageCleanupStatusInputSchema, StorageCleanupJobSchema.nullable(), { auth: "admin" }), method(object({ jobId: string() }), object({ cancelled: boolean() }), {
21958
+ kind: "mutation",
21959
+ auth: "admin"
21960
+ }), method(object({}), array(StorageMigrationJobSchema).readonly(), { auth: "admin" });
21873
21961
  var ProviderInfoSchema = discriminatedUnion("shouldSaveDiskSpace", [object({
21874
21962
  providerId: string().min(1),
21875
21963
  displayName: string().min(1),
@@ -29051,6 +29139,33 @@ var RecordingRebalanceInputSchema = object({
29051
29139
  minMoveGb: number().min(0).optional()
29052
29140
  });
29053
29141
  /**
29142
+ * Operator-facing placement of one camera onto a recordings location.
29143
+ *
29144
+ * `pinLocationId` is the operator instruction: a location id, or `null` for
29145
+ * Auto (the planner may move this camera). `locationId` is where high/mid
29146
+ * currently write — the plan, which may disagree with the pin when Auto.
29147
+ */
29148
+ var RecordingDevicePlacementSchema = object({
29149
+ deviceId: number().int(),
29150
+ profile: string(),
29151
+ locationId: string()
29152
+ });
29153
+ var RecordingDevicePinSchema = object({
29154
+ deviceId: number().int(),
29155
+ /** Recordings-class location this camera is pinned to. */
29156
+ locationId: string()
29157
+ });
29158
+ var RecordingPlacementViewSchema = object({
29159
+ assignments: array(RecordingDevicePlacementSchema),
29160
+ pins: array(RecordingDevicePinSchema),
29161
+ defaultLocations: record(string(), string())
29162
+ });
29163
+ var RecordingSetDevicePlacementInputSchema = object({
29164
+ deviceId: number().int(),
29165
+ /** `null` = Auto. Otherwise a `recordings:*` location id. */
29166
+ locationId: string().nullable()
29167
+ });
29168
+ /**
29054
29169
  * Result of locating footage at a wall-clock instant for one device/profile.
29055
29170
  * `segment` carries the covering segment's window; `gap` reports the forward
29056
29171
  * nearest covered edge (`null` past the end of footage / when none exists)
@@ -29276,6 +29391,12 @@ method(object({
29276
29391
  }), method(RecordingRebalanceInputSchema, RecordingRebalancePlanSchema, {
29277
29392
  kind: "mutation",
29278
29393
  auth: "admin"
29394
+ }), method(object({}), RecordingPlacementViewSchema, {
29395
+ kind: "query",
29396
+ auth: "admin"
29397
+ }), method(RecordingSetDevicePlacementInputSchema, object({ ok: literal(true) }), {
29398
+ kind: "mutation",
29399
+ auth: "admin"
29279
29400
  });
29280
29401
  /**
29281
29402
  * `recording-export` cap — render a footage time range into a single downloadable
@@ -34345,6 +34466,12 @@ Object.freeze({
34345
34466
  addonId: null,
34346
34467
  access: "delete"
34347
34468
  },
34469
+ "deviceManager.renameLocation": {
34470
+ capName: "device-manager",
34471
+ capScope: "system",
34472
+ addonId: null,
34473
+ access: "create"
34474
+ },
34348
34475
  "deviceManager.runDeviceAction": {
34349
34476
  capName: "device-manager",
34350
34477
  capScope: "system",
@@ -36037,19 +36164,19 @@ Object.freeze({
36037
36164
  addonId: null,
36038
36165
  access: "view"
36039
36166
  },
36040
- "pipelineAnalytics.getGroup": {
36167
+ "pipelineAnalytics.getKeyEvents": {
36041
36168
  capName: "pipeline-analytics",
36042
36169
  capScope: "device",
36043
36170
  addonId: null,
36044
36171
  access: "view"
36045
36172
  },
36046
- "pipelineAnalytics.getKeyEvents": {
36173
+ "pipelineAnalytics.getKeyEventsBatch": {
36047
36174
  capName: "pipeline-analytics",
36048
36175
  capScope: "device",
36049
36176
  addonId: null,
36050
36177
  access: "view"
36051
36178
  },
36052
- "pipelineAnalytics.getKeyEventsBatch": {
36179
+ "pipelineAnalytics.getMediaReclaimStatus": {
36053
36180
  capName: "pipeline-analytics",
36054
36181
  capScope: "device",
36055
36182
  addonId: null,
@@ -36139,12 +36266,6 @@ Object.freeze({
36139
36266
  addonId: null,
36140
36267
  access: "view"
36141
36268
  },
36142
- "pipelineAnalytics.listGroups": {
36143
- capName: "pipeline-analytics",
36144
- capScope: "device",
36145
- addonId: null,
36146
- access: "view"
36147
- },
36148
36269
  "pipelineAnalytics.listOpsLog": {
36149
36270
  capName: "pipeline-analytics",
36150
36271
  capScope: "device",
@@ -36229,6 +36350,12 @@ Object.freeze({
36229
36350
  addonId: null,
36230
36351
  access: "create"
36231
36352
  },
36353
+ "pipelineAnalytics.reclaimDebugMedia": {
36354
+ capName: "pipeline-analytics",
36355
+ capScope: "device",
36356
+ addonId: null,
36357
+ access: "create"
36358
+ },
36232
36359
  "pipelineAnalytics.reconcileFromDisk": {
36233
36360
  capName: "pipeline-analytics",
36234
36361
  capScope: "device",
@@ -37153,6 +37280,12 @@ Object.freeze({
37153
37280
  addonId: null,
37154
37281
  access: "view"
37155
37282
  },
37283
+ "recording.getPlacement": {
37284
+ capName: "recording",
37285
+ capScope: "system",
37286
+ addonId: null,
37287
+ access: "view"
37288
+ },
37156
37289
  "recording.getPlaybackManifest": {
37157
37290
  capName: "recording",
37158
37291
  capScope: "system",
@@ -37279,6 +37412,12 @@ Object.freeze({
37279
37412
  addonId: null,
37280
37413
  access: "create"
37281
37414
  },
37415
+ "recording.setDevicePlacement": {
37416
+ capName: "recording",
37417
+ capScope: "system",
37418
+ addonId: null,
37419
+ access: "create"
37420
+ },
37282
37421
  "recording.startStorageMigrationMove": {
37283
37422
  capName: "recording",
37284
37423
  capScope: "system",
@@ -37723,12 +37862,36 @@ Object.freeze({
37723
37862
  addonId: null,
37724
37863
  access: "create"
37725
37864
  },
37865
+ "storageMigration.cleanupCancel": {
37866
+ capName: "storage-migration",
37867
+ capScope: "system",
37868
+ addonId: null,
37869
+ access: "create"
37870
+ },
37871
+ "storageMigration.cleanupStart": {
37872
+ capName: "storage-migration",
37873
+ capScope: "system",
37874
+ addonId: null,
37875
+ access: "create"
37876
+ },
37877
+ "storageMigration.cleanupStatus": {
37878
+ capName: "storage-migration",
37879
+ capScope: "system",
37880
+ addonId: null,
37881
+ access: "view"
37882
+ },
37726
37883
  "storageMigration.drain": {
37727
37884
  capName: "storage-migration",
37728
37885
  capScope: "system",
37729
37886
  addonId: null,
37730
37887
  access: "create"
37731
37888
  },
37889
+ "storageMigration.history": {
37890
+ capName: "storage-migration",
37891
+ capScope: "system",
37892
+ addonId: null,
37893
+ access: "view"
37894
+ },
37732
37895
  "storageMigration.movers": {
37733
37896
  capName: "storage-migration",
37734
37897
  capScope: "system",
@@ -39725,11 +39888,6 @@ Object.freeze({
39725
39888
  form: "single",
39726
39889
  optional: true
39727
39890
  }],
39728
- "pipelineAnalytics.getGroup": [{
39729
- name: "deviceId",
39730
- form: "single",
39731
- optional: false
39732
- }],
39733
39891
  "pipelineAnalytics.getKeyEvents": [{
39734
39892
  name: "deviceId",
39735
39893
  form: "single",
@@ -39795,11 +39953,6 @@ Object.freeze({
39795
39953
  form: "single",
39796
39954
  optional: false
39797
39955
  }],
39798
- "pipelineAnalytics.listGroups": [{
39799
- name: "deviceIds",
39800
- form: "array",
39801
- optional: false
39802
- }],
39803
39956
  "pipelineAnalytics.listOpsLog": [{
39804
39957
  name: "deviceId",
39805
39958
  form: "single",
@@ -39845,6 +39998,11 @@ Object.freeze({
39845
39998
  form: "single",
39846
39999
  optional: true
39847
40000
  }],
40001
+ "pipelineAnalytics.reclaimDebugMedia": [{
40002
+ name: "deviceIds",
40003
+ form: "array",
40004
+ optional: true
40005
+ }],
39848
40006
  "pipelineAnalytics.reconcileFromDisk": [{
39849
40007
  name: "deviceId",
39850
40008
  form: "single",
@@ -40210,6 +40368,11 @@ Object.freeze({
40210
40368
  form: "single",
40211
40369
  optional: false
40212
40370
  }],
40371
+ "recording.setDevicePlacement": [{
40372
+ name: "deviceId",
40373
+ form: "single",
40374
+ optional: false
40375
+ }],
40213
40376
  "recording.startStorageMigrationMove": [{
40214
40377
  name: "deviceId",
40215
40378
  form: "single",
@@ -8299,6 +8299,13 @@ var MediaRelocateModeSchema = _enum([
8299
8299
  ]);
8300
8300
  var RelocateMediaInputSchema = object({
8301
8301
  toLocationId: string(),
8302
+ /**
8303
+ * Restrict the pass to rows currently on this location. Omitted / `'*'` =
8304
+ * every row that is not already on `toLocationId` (the historical
8305
+ * behaviour). A named source is what a from→to migration needs: without it
8306
+ * "move events off disk 2" also emptied disk 1.
8307
+ */
8308
+ fromLocationId: string().optional(),
8302
8309
  throttleMbps: number().min(1).max(1e3).optional(),
8303
8310
  /** Omitted = `move`, the pre-existing behaviour. */
8304
8311
  mode: MediaRelocateModeSchema.optional()
@@ -8366,6 +8373,19 @@ var StorageMigrationDestinationsSchema = object({
8366
8373
  galleryMedia: string().min(1).optional()
8367
8374
  }).refine((value) => Object.keys(value).length > 0, { message: "select at least one storage class" });
8368
8375
  /**
8376
+ * Optional named source per class. Omitted = the class's current default
8377
+ * (the historical behaviour). A named source that is NOT the default is a
8378
+ * drain of that disk: bytes move, the default stays, and the source is
8379
+ * disabled when the move finishes.
8380
+ */
8381
+ var StorageMigrationSourcesSchema = object({
8382
+ recordings: string().min(1).optional(),
8383
+ recordingsLow: string().min(1).optional(),
8384
+ eventMedia: string().min(1).optional(),
8385
+ backups: string().min(1).optional(),
8386
+ galleryMedia: string().min(1).optional()
8387
+ }).optional();
8388
+ /**
8369
8389
  * How a migration sequences the cutover against the byte move.
8370
8390
  *
8371
8391
  * - `blocking` — the historical order: pause, move every byte, repoint,
@@ -8387,6 +8407,8 @@ var StorageMigrationModeSchema = _enum(["blocking", "nonBlocking"]);
8387
8407
  /** Shared input for planning and starting an orchestrated storage migration. */
8388
8408
  var StorageMigrationInputSchema = object({
8389
8409
  destinations: StorageMigrationDestinationsSchema,
8410
+ /** Omitted = each class's current default. */
8411
+ sources: StorageMigrationSourcesSchema,
8390
8412
  throttleMbps: number().min(1).max(1e3).optional(),
8391
8413
  /** Omitted = `blocking`, which stays the default. */
8392
8414
  mode: StorageMigrationModeSchema.optional()
@@ -8466,6 +8488,13 @@ var StorageMigrationMoveSchema = object({
8466
8488
  storageClass: StorageMigrationClassSchema,
8467
8489
  fromLocationId: string(),
8468
8490
  toLocationId: string(),
8491
+ /**
8492
+ * True when `from` was NOT the class default at plan time. The move still
8493
+ * copies bytes, but the default is left alone and the source is disabled
8494
+ * once the copy verifies. Absent on jobs planned before this field existed
8495
+ * — those jobs always repointed, which is `false`.
8496
+ */
8497
+ freezeSource: boolean().optional(),
8469
8498
  moverJobId: string().nullable(),
8470
8499
  state: RelocateJobStateSchema.nullable(),
8471
8500
  error: string().nullable(),
@@ -8479,6 +8508,7 @@ var StorageMigrationJobSchema = object({
8479
8508
  * can tell a seconds-long cutover from a thirty-hour one. */
8480
8509
  mode: StorageMigrationModeSchema,
8481
8510
  destinations: StorageMigrationDestinationsSchema,
8511
+ sources: StorageMigrationSourcesSchema,
8482
8512
  throttleMbps: number(),
8483
8513
  moves: array(StorageMigrationMoveSchema),
8484
8514
  pauseLeaseId: string().nullable(),
@@ -8504,6 +8534,7 @@ var StorageMigrationFindingSchema = object({
8504
8534
  });
8505
8535
  var StorageMigrationPlanSchema = object({
8506
8536
  destinations: StorageMigrationDestinationsSchema,
8537
+ sources: StorageMigrationSourcesSchema,
8507
8538
  /** The mode this plan was built for. A plan is only valid for its mode: the
8508
8539
  * `eventMedia` seal gate and the single-cardinality refusal both depend on
8509
8540
  * it. */
@@ -8511,7 +8542,8 @@ var StorageMigrationPlanSchema = object({
8511
8542
  moves: array(object({
8512
8543
  storageClass: StorageMigrationClassSchema,
8513
8544
  fromLocationId: string(),
8514
- toLocationId: string()
8545
+ toLocationId: string(),
8546
+ freezeSource: boolean().optional()
8515
8547
  })),
8516
8548
  findings: array(StorageMigrationFindingSchema)
8517
8549
  });
@@ -8689,10 +8721,51 @@ var LedgerWalkReportSchema = object({
8689
8721
  var RelocatableMediaCountSchema = object({ rows: number().int().nonnegative() }).nullable();
8690
8722
  var RelocatableMediaCountInputSchema = object({
8691
8723
  toLocationId: string().min(1),
8724
+ /** Restrict the count to one source; omitted / `'*'` = every non-target row. */
8725
+ fromLocationId: string().optional(),
8692
8726
  /** Omitted = `move`. */
8693
8727
  mode: MediaRelocateModeSchema.optional()
8694
8728
  });
8695
8729
  /**
8730
+ * Operator cleanup of leftover analytics rows, optional debug media, and
8731
+ * ghost ledger entries on frozen footage locations.
8732
+ *
8733
+ * A pass is tens of minutes on a standing backlog. The hub method RETURNS
8734
+ * `{ jobId }` immediately; progress is `cleanupStatus`. Awaiting the work
8735
+ * is how `addons.custom` hit the 60 s UDS deadline while reclaim continued
8736
+ * with no operator-visible status.
8737
+ */
8738
+ var StorageCleanupPhaseSchema = _enum([
8739
+ "orphans",
8740
+ "debug-media",
8741
+ "ghost-ledger",
8742
+ "done",
8743
+ "failed",
8744
+ "cancelled"
8745
+ ]);
8746
+ var StorageCleanupInputSchema = object({
8747
+ /** Also walk motion stills / track filmstrips. Off by default. */
8748
+ includeDebugMedia: boolean().optional() });
8749
+ var StorageCleanupJobSchema = object({
8750
+ jobId: string(),
8751
+ phase: StorageCleanupPhaseSchema,
8752
+ includeDebugMedia: boolean(),
8753
+ orphansReclaimed: number().int().nonnegative(),
8754
+ orphanBytesReclaimed: number().int().nonnegative(),
8755
+ debugMediaReclaimed: number().int().nonnegative(),
8756
+ debugMediaBytesReclaimed: number().int().nonnegative(),
8757
+ ghostsForgotten: number().int().nonnegative(),
8758
+ ghostBytesForgotten: number().int().nonnegative(),
8759
+ /** Short operator-facing line: current collection, pass, or location. */
8760
+ detail: string().nullable(),
8761
+ cancelRequested: boolean(),
8762
+ startedAt: number(),
8763
+ updatedAt: number(),
8764
+ finishedAt: number().nullable(),
8765
+ error: string().nullable()
8766
+ });
8767
+ var StorageCleanupStatusInputSchema = object({ jobId: string().optional() });
8768
+ /**
8696
8769
  * `StorageLocationType` — an addon-declared id that identifies the *kind* of
8697
8770
  * storage a location serves. Defined here (not in `capabilities/storage.cap.ts`)
8698
8771
  * so the persisted record schema and the consumer-facing cap can both consume it
@@ -8720,11 +8793,10 @@ var StorageLocationTypeSchema = string().regex(/^[a-z][a-zA-Z0-9-]*$/);
8720
8793
  * The default location for a type uses `id === <type>:default` by
8721
8794
  * convention (the bare type ref like `'backups'` resolves to it).
8722
8795
  *
8723
- * `isSystem: true` marks a location as orchestrator-seeded and
8724
- * undeletable. The bootstrap-installed defaults (one per type) carry
8725
- * this flag; operator-added locations don't. Editing the config of
8726
- * a system location is allowed (path migration, provider swap) but
8727
- * deleting it is rejected at the cap level.
8796
+ * `isSystem` is a legacy persisted flag. Seed still creates the initial
8797
+ * `<type>:default` locations; the flag is no longer a lock, a badge, or a
8798
+ * prune selector. New writes leave it false. Deletion is gated on uniqueness
8799
+ * / last-enabled, not on this bit.
8728
8800
  */
8729
8801
  var StorageLocationSchema = object({
8730
8802
  id: string().regex(/^[a-z][a-zA-Z0-9-]*:[a-zA-Z0-9-]+$/),
@@ -13405,6 +13477,12 @@ method(object({
13405
13477
  }), _void(), {
13406
13478
  kind: "mutation",
13407
13479
  auth: "admin"
13480
+ }), method(object({
13481
+ from: string(),
13482
+ to: string()
13483
+ }), object({ moved: number() }), {
13484
+ kind: "mutation",
13485
+ auth: "admin"
13408
13486
  }), method(object({
13409
13487
  deviceId: number(),
13410
13488
  disabled: boolean()
@@ -16169,6 +16247,8 @@ var NcSystemEventKindSchema = _enum([
16169
16247
  "device-offline",
16170
16248
  "device-disabled",
16171
16249
  "device-enabled",
16250
+ "device-battery-low",
16251
+ "device-battery-normal",
16172
16252
  "stream-online",
16173
16253
  "stream-offline",
16174
16254
  "node-online",
@@ -19443,46 +19523,6 @@ var RecentTracksPageSchema = object({
19443
19523
  /** Cursor for the next page, or null when this page is the last. */
19444
19524
  nextCursor: string().nullable()
19445
19525
  });
19446
- var LIST_GROUPS_DEFAULT_LIMIT = 40;
19447
- var LIST_GROUPS_MAX_LIMIT = 100;
19448
- var AnalyticsGroupRecordSchema = object({
19449
- id: string(),
19450
- deviceId: number().int(),
19451
- openedAt: number().int(),
19452
- closedAt: number().int(),
19453
- timestamp: number().int(),
19454
- memberCount: number().int(),
19455
- memberTrackIds: array(string()).readonly(),
19456
- className: string(),
19457
- classes: array(string()).readonly(),
19458
- /** Relative event-media path, or null when the group has no picture yet. */
19459
- mediaUrl: string().nullable(),
19460
- singleton: boolean()
19461
- });
19462
- var AnalyticsGroupMemberSchema = object({
19463
- trackId: string(),
19464
- deviceId: number().int(),
19465
- className: string(),
19466
- firstSeen: number().int(),
19467
- lastSeen: number().int(),
19468
- mediaUrl: string().nullable()
19469
- });
19470
- var AnalyticsGroupDetailSchema = AnalyticsGroupRecordSchema.extend({ members: array(AnalyticsGroupMemberSchema).readonly() });
19471
- var ListGroupsQueryInput = object({
19472
- /** Devices to merge. An empty array yields `{ groups: [], nextCursor: null }`. */
19473
- deviceIds: array(number()),
19474
- /** Window lower bound on `closedAt` (inclusive). */
19475
- since: number().optional(),
19476
- /** Window upper bound on `openedAt` (inclusive). */
19477
- until: number().optional(),
19478
- limit: number().int().min(1).max(LIST_GROUPS_MAX_LIMIT).default(LIST_GROUPS_DEFAULT_LIMIT),
19479
- /** Opaque continuation cursor from a previous page's `nextCursor`. */
19480
- cursor: string().optional()
19481
- });
19482
- var ListGroupsPageSchema = object({
19483
- groups: array(AnalyticsGroupRecordSchema).readonly(),
19484
- nextCursor: string().nullable()
19485
- });
19486
19526
  var KEY_EVENTS_DEFAULT_LIMIT = 50;
19487
19527
  var KEY_EVENTS_MAX_LIMIT = 200;
19488
19528
  var KeyEventQueryInput = object({
@@ -19586,9 +19626,7 @@ var TrackCascadeCountsSchema = object({
19586
19626
  /** Unassigned plate reads removed (best-effort; plate leg deferred to plate-intelligence). */
19587
19627
  plates: number().int(),
19588
19628
  /** Per-track CLIP search vectors removed (best-effort). */
19589
- embeddings: number().int(),
19590
- /** Group membership + group rows removed with their last member (best-effort). */
19591
- groups: number().int()
19629
+ embeddings: number().int()
19592
19630
  });
19593
19631
  /** Disk-wins reconcile: media rows whose blobs are gone, then empty tracks. */
19594
19632
  var DiskReconcileCountsSchema = object({
@@ -19758,6 +19796,47 @@ var RebuildStatusSchema = object({
19758
19796
  /** Present when the pass ended by throwing. */
19759
19797
  error: string().nullable()
19760
19798
  });
19799
+ /**
19800
+ * Acknowledgement that a debug-media reclaim STARTED.
19801
+ *
19802
+ * The pass is paced at ~2 MB/s over a standing 100 GB — tens of minutes — so
19803
+ * it runs detached and this returns immediately. Awaiting it is how the
19804
+ * `addons.custom` door hit the 60 s UDS deadline while the walk carried on
19805
+ * with no status. Poll {@link pipelineAnalyticsCapability.methods.getMediaReclaimStatus}.
19806
+ */
19807
+ var MediaReclaimStartResultSchema = object({
19808
+ started: boolean(),
19809
+ /** True when a pass was already running; the new request is ignored. */
19810
+ alreadyRunning: boolean()
19811
+ });
19812
+ var MediaReclaimInputSchema = object({
19813
+ mode: _enum(["report", "reclaim"]).default("report"),
19814
+ scopes: array(_enum(["motion-still", "track-filmstrip"])).min(1).optional(),
19815
+ deviceIds: array(number().int()).min(1).optional(),
19816
+ restart: boolean().optional(),
19817
+ pageSize: number().int().min(50).max(5e3).optional(),
19818
+ maxRowsPerDevice: number().int().min(1).max(5e5).optional(),
19819
+ maxReclaimPerDevice: number().int().min(1).max(5e5).optional(),
19820
+ maxBytesPerRun: number().int().min(1).optional(),
19821
+ budgetMinutes: number().int().min(1).max(720).optional(),
19822
+ throttleBytesPerSec: number().int().min(64 * 1024).optional(),
19823
+ graceMinutes: number().int().min(1).max(10080).optional()
19824
+ });
19825
+ var MediaReclaimStatusSchema = object({
19826
+ running: boolean(),
19827
+ mode: _enum(["report", "reclaim"]).nullable(),
19828
+ totalExamined: number(),
19829
+ totalEligible: number(),
19830
+ totalReclaimed: number(),
19831
+ totalBytesReclaimed: number(),
19832
+ totalRefused: number(),
19833
+ /** Device+scope windows finished in this pass. */
19834
+ devicesDone: number(),
19835
+ complete: boolean().nullable(),
19836
+ startedAtMs: number().nullable(),
19837
+ finishedAtMs: number().nullable(),
19838
+ error: string().nullable()
19839
+ });
19761
19840
  var ReplayFrameInputSchema = object({
19762
19841
  timestamp: number(),
19763
19842
  frame: PipelineRunResultBridge
@@ -19796,10 +19875,7 @@ DeviceType.Camera, method(object({ deviceId: number() }), array(TrackSchema).rea
19796
19875
  * stationary registry). Default false: the timeline lists passages,
19797
19876
  * not parking records (operator decision, 2026-08-15). */
19798
19877
  includeStationary: boolean().optional()
19799
- }), array(TrackSchema).readonly()), method(RecentTracksQueryInput, RecentTracksPageSchema), method(ListGroupsQueryInput, ListGroupsPageSchema), method(object({
19800
- deviceId: number(),
19801
- groupId: string().min(1)
19802
- }), AnalyticsGroupDetailSchema.nullable()), method(object({ deviceId: number() }), _void(), {
19878
+ }), array(TrackSchema).readonly()), method(RecentTracksQueryInput, RecentTracksPageSchema), method(object({ deviceId: number() }), _void(), {
19803
19879
  kind: "mutation",
19804
19880
  auth: "admin"
19805
19881
  }), method(DeviceEventQueryInput, array(MotionEventSchema).readonly()), method(ObjectEventQueryInput, array(ObjectEventSchema).readonly()), method(DeviceEventQueryInput, array(AudioEventSchema).readonly()), method(object({ deviceId: number() }), array(EventKindDescriptorSchema).readonly()), method(object({ deviceIds: array(number()).min(1).max(200) }), array(EventKindsForDeviceSchema).readonly()), method(object({
@@ -19899,6 +19975,12 @@ DeviceType.Camera, method(object({ deviceId: number() }), array(TrackSchema).rea
19899
19975
  }), method(OpsLogQueryInputSchema, array(OpsLogEntrySchema).readonly(), {
19900
19976
  kind: "query",
19901
19977
  auth: "admin"
19978
+ }), method(MediaReclaimInputSchema, MediaReclaimStartResultSchema, {
19979
+ kind: "mutation",
19980
+ auth: "admin"
19981
+ }), method(object({}), MediaReclaimStatusSchema, {
19982
+ kind: "query",
19983
+ auth: "admin"
19902
19984
  }), method(object({ deviceIds: array(number()).optional() }), TrainingExportSummarySchema, {
19903
19985
  kind: "query",
19904
19986
  auth: "admin"
@@ -21869,7 +21951,13 @@ method(StorageMigrationInputSchema, StorageMigrationPlanSchema, { auth: "admin"
21869
21951
  }), method(object({}), array(StorageMigrationMoverSchema).readonly(), { auth: "admin" }), method(object({}), array(StorageMigrationResidueSchema).readonly(), { auth: "admin" }), method(StorageMigrationDrainInputSchema, object({ jobId: string() }), {
21870
21952
  kind: "mutation",
21871
21953
  auth: "admin"
21872
- });
21954
+ }), method(StorageCleanupInputSchema, object({ jobId: string() }), {
21955
+ kind: "mutation",
21956
+ auth: "admin"
21957
+ }), method(StorageCleanupStatusInputSchema, StorageCleanupJobSchema.nullable(), { auth: "admin" }), method(object({ jobId: string() }), object({ cancelled: boolean() }), {
21958
+ kind: "mutation",
21959
+ auth: "admin"
21960
+ }), method(object({}), array(StorageMigrationJobSchema).readonly(), { auth: "admin" });
21873
21961
  var ProviderInfoSchema = discriminatedUnion("shouldSaveDiskSpace", [object({
21874
21962
  providerId: string().min(1),
21875
21963
  displayName: string().min(1),
@@ -29051,6 +29139,33 @@ var RecordingRebalanceInputSchema = object({
29051
29139
  minMoveGb: number().min(0).optional()
29052
29140
  });
29053
29141
  /**
29142
+ * Operator-facing placement of one camera onto a recordings location.
29143
+ *
29144
+ * `pinLocationId` is the operator instruction: a location id, or `null` for
29145
+ * Auto (the planner may move this camera). `locationId` is where high/mid
29146
+ * currently write — the plan, which may disagree with the pin when Auto.
29147
+ */
29148
+ var RecordingDevicePlacementSchema = object({
29149
+ deviceId: number().int(),
29150
+ profile: string(),
29151
+ locationId: string()
29152
+ });
29153
+ var RecordingDevicePinSchema = object({
29154
+ deviceId: number().int(),
29155
+ /** Recordings-class location this camera is pinned to. */
29156
+ locationId: string()
29157
+ });
29158
+ var RecordingPlacementViewSchema = object({
29159
+ assignments: array(RecordingDevicePlacementSchema),
29160
+ pins: array(RecordingDevicePinSchema),
29161
+ defaultLocations: record(string(), string())
29162
+ });
29163
+ var RecordingSetDevicePlacementInputSchema = object({
29164
+ deviceId: number().int(),
29165
+ /** `null` = Auto. Otherwise a `recordings:*` location id. */
29166
+ locationId: string().nullable()
29167
+ });
29168
+ /**
29054
29169
  * Result of locating footage at a wall-clock instant for one device/profile.
29055
29170
  * `segment` carries the covering segment's window; `gap` reports the forward
29056
29171
  * nearest covered edge (`null` past the end of footage / when none exists)
@@ -29276,6 +29391,12 @@ method(object({
29276
29391
  }), method(RecordingRebalanceInputSchema, RecordingRebalancePlanSchema, {
29277
29392
  kind: "mutation",
29278
29393
  auth: "admin"
29394
+ }), method(object({}), RecordingPlacementViewSchema, {
29395
+ kind: "query",
29396
+ auth: "admin"
29397
+ }), method(RecordingSetDevicePlacementInputSchema, object({ ok: literal(true) }), {
29398
+ kind: "mutation",
29399
+ auth: "admin"
29279
29400
  });
29280
29401
  /**
29281
29402
  * `recording-export` cap — render a footage time range into a single downloadable
@@ -34345,6 +34466,12 @@ Object.freeze({
34345
34466
  addonId: null,
34346
34467
  access: "delete"
34347
34468
  },
34469
+ "deviceManager.renameLocation": {
34470
+ capName: "device-manager",
34471
+ capScope: "system",
34472
+ addonId: null,
34473
+ access: "create"
34474
+ },
34348
34475
  "deviceManager.runDeviceAction": {
34349
34476
  capName: "device-manager",
34350
34477
  capScope: "system",
@@ -36037,19 +36164,19 @@ Object.freeze({
36037
36164
  addonId: null,
36038
36165
  access: "view"
36039
36166
  },
36040
- "pipelineAnalytics.getGroup": {
36167
+ "pipelineAnalytics.getKeyEvents": {
36041
36168
  capName: "pipeline-analytics",
36042
36169
  capScope: "device",
36043
36170
  addonId: null,
36044
36171
  access: "view"
36045
36172
  },
36046
- "pipelineAnalytics.getKeyEvents": {
36173
+ "pipelineAnalytics.getKeyEventsBatch": {
36047
36174
  capName: "pipeline-analytics",
36048
36175
  capScope: "device",
36049
36176
  addonId: null,
36050
36177
  access: "view"
36051
36178
  },
36052
- "pipelineAnalytics.getKeyEventsBatch": {
36179
+ "pipelineAnalytics.getMediaReclaimStatus": {
36053
36180
  capName: "pipeline-analytics",
36054
36181
  capScope: "device",
36055
36182
  addonId: null,
@@ -36139,12 +36266,6 @@ Object.freeze({
36139
36266
  addonId: null,
36140
36267
  access: "view"
36141
36268
  },
36142
- "pipelineAnalytics.listGroups": {
36143
- capName: "pipeline-analytics",
36144
- capScope: "device",
36145
- addonId: null,
36146
- access: "view"
36147
- },
36148
36269
  "pipelineAnalytics.listOpsLog": {
36149
36270
  capName: "pipeline-analytics",
36150
36271
  capScope: "device",
@@ -36229,6 +36350,12 @@ Object.freeze({
36229
36350
  addonId: null,
36230
36351
  access: "create"
36231
36352
  },
36353
+ "pipelineAnalytics.reclaimDebugMedia": {
36354
+ capName: "pipeline-analytics",
36355
+ capScope: "device",
36356
+ addonId: null,
36357
+ access: "create"
36358
+ },
36232
36359
  "pipelineAnalytics.reconcileFromDisk": {
36233
36360
  capName: "pipeline-analytics",
36234
36361
  capScope: "device",
@@ -37153,6 +37280,12 @@ Object.freeze({
37153
37280
  addonId: null,
37154
37281
  access: "view"
37155
37282
  },
37283
+ "recording.getPlacement": {
37284
+ capName: "recording",
37285
+ capScope: "system",
37286
+ addonId: null,
37287
+ access: "view"
37288
+ },
37156
37289
  "recording.getPlaybackManifest": {
37157
37290
  capName: "recording",
37158
37291
  capScope: "system",
@@ -37279,6 +37412,12 @@ Object.freeze({
37279
37412
  addonId: null,
37280
37413
  access: "create"
37281
37414
  },
37415
+ "recording.setDevicePlacement": {
37416
+ capName: "recording",
37417
+ capScope: "system",
37418
+ addonId: null,
37419
+ access: "create"
37420
+ },
37282
37421
  "recording.startStorageMigrationMove": {
37283
37422
  capName: "recording",
37284
37423
  capScope: "system",
@@ -37723,12 +37862,36 @@ Object.freeze({
37723
37862
  addonId: null,
37724
37863
  access: "create"
37725
37864
  },
37865
+ "storageMigration.cleanupCancel": {
37866
+ capName: "storage-migration",
37867
+ capScope: "system",
37868
+ addonId: null,
37869
+ access: "create"
37870
+ },
37871
+ "storageMigration.cleanupStart": {
37872
+ capName: "storage-migration",
37873
+ capScope: "system",
37874
+ addonId: null,
37875
+ access: "create"
37876
+ },
37877
+ "storageMigration.cleanupStatus": {
37878
+ capName: "storage-migration",
37879
+ capScope: "system",
37880
+ addonId: null,
37881
+ access: "view"
37882
+ },
37726
37883
  "storageMigration.drain": {
37727
37884
  capName: "storage-migration",
37728
37885
  capScope: "system",
37729
37886
  addonId: null,
37730
37887
  access: "create"
37731
37888
  },
37889
+ "storageMigration.history": {
37890
+ capName: "storage-migration",
37891
+ capScope: "system",
37892
+ addonId: null,
37893
+ access: "view"
37894
+ },
37732
37895
  "storageMigration.movers": {
37733
37896
  capName: "storage-migration",
37734
37897
  capScope: "system",
@@ -39725,11 +39888,6 @@ Object.freeze({
39725
39888
  form: "single",
39726
39889
  optional: true
39727
39890
  }],
39728
- "pipelineAnalytics.getGroup": [{
39729
- name: "deviceId",
39730
- form: "single",
39731
- optional: false
39732
- }],
39733
39891
  "pipelineAnalytics.getKeyEvents": [{
39734
39892
  name: "deviceId",
39735
39893
  form: "single",
@@ -39795,11 +39953,6 @@ Object.freeze({
39795
39953
  form: "single",
39796
39954
  optional: false
39797
39955
  }],
39798
- "pipelineAnalytics.listGroups": [{
39799
- name: "deviceIds",
39800
- form: "array",
39801
- optional: false
39802
- }],
39803
39956
  "pipelineAnalytics.listOpsLog": [{
39804
39957
  name: "deviceId",
39805
39958
  form: "single",
@@ -39845,6 +39998,11 @@ Object.freeze({
39845
39998
  form: "single",
39846
39999
  optional: true
39847
40000
  }],
40001
+ "pipelineAnalytics.reclaimDebugMedia": [{
40002
+ name: "deviceIds",
40003
+ form: "array",
40004
+ optional: true
40005
+ }],
39848
40006
  "pipelineAnalytics.reconcileFromDisk": [{
39849
40007
  name: "deviceId",
39850
40008
  form: "single",
@@ -40210,6 +40368,11 @@ Object.freeze({
40210
40368
  form: "single",
40211
40369
  optional: false
40212
40370
  }],
40371
+ "recording.setDevicePlacement": [{
40372
+ name: "deviceId",
40373
+ form: "single",
40374
+ optional: false
40375
+ }],
40213
40376
  "recording.startStorageMigrationMove": [{
40214
40377
  name: "deviceId",
40215
40378
  form: "single",
@@ -3,7 +3,7 @@ Object.defineProperties(exports, {
3
3
  [Symbol.toStringTag]: { value: "Module" }
4
4
  });
5
5
  //#endregion
6
- const require_dist = require("../dist-u1L6UZmY.js");
6
+ const require_dist = require("../dist-Cm6-aUVi.js");
7
7
  let node_crypto = require("node:crypto");
8
8
  //#region src/ha-export/topics.ts
9
9
  /**
@@ -1,4 +1,4 @@
1
- import { At as EventCategory, C as buildAddonRouteProvider, Et as string, N as deviceExportCapability, X as oauthIntegrationCapability, a as COCO_TO_MACRO, c as FanDirectionSchema, i as CAMERA_SWITCH_ORDER, l as HvacModeSchema, o as CameraSwitchIdSchema, p as addonRoutesCapability, pt as BaseAddon, t as AlarmArmModeSchema, u as MediaPlayerRepeatSchema, vt as nodePin } from "../dist-DV4Xqi_x.mjs";
1
+ import { At as EventCategory, C as buildAddonRouteProvider, Et as string, N as deviceExportCapability, X as oauthIntegrationCapability, a as COCO_TO_MACRO, c as FanDirectionSchema, i as CAMERA_SWITCH_ORDER, l as HvacModeSchema, o as CameraSwitchIdSchema, p as addonRoutesCapability, pt as BaseAddon, t as AlarmArmModeSchema, u as MediaPlayerRepeatSchema, vt as nodePin } from "../dist-Cu_caOlV.mjs";
2
2
  import { createHmac, timingSafeEqual } from "node:crypto";
3
3
  //#region src/ha-export/topics.ts
4
4
  /**
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@camstack/addon-provider-homeassistant",
3
- "version": "1.2.62",
3
+ "version": "1.2.64",
4
4
  "description": "Home Assistant device provider addon for CamStack",
5
5
  "keywords": [
6
6
  "camstack",