@camstack/addon-provider-tuya 0.2.49 → 0.2.51

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (3) hide show
  1. package/dist/addon.js +236 -73
  2. package/dist/addon.mjs +236 -73
  3. package/package.json +1 -1
package/dist/addon.js CHANGED
@@ -8916,6 +8916,13 @@ var MediaRelocateModeSchema = _enum([
8916
8916
  ]);
8917
8917
  var RelocateMediaInputSchema = object({
8918
8918
  toLocationId: string(),
8919
+ /**
8920
+ * Restrict the pass to rows currently on this location. Omitted / `'*'` =
8921
+ * every row that is not already on `toLocationId` (the historical
8922
+ * behaviour). A named source is what a from→to migration needs: without it
8923
+ * "move events off disk 2" also emptied disk 1.
8924
+ */
8925
+ fromLocationId: string().optional(),
8919
8926
  throttleMbps: number().min(1).max(1e3).optional(),
8920
8927
  /** Omitted = `move`, the pre-existing behaviour. */
8921
8928
  mode: MediaRelocateModeSchema.optional()
@@ -8983,6 +8990,19 @@ var StorageMigrationDestinationsSchema = object({
8983
8990
  galleryMedia: string().min(1).optional()
8984
8991
  }).refine((value) => Object.keys(value).length > 0, { message: "select at least one storage class" });
8985
8992
  /**
8993
+ * Optional named source per class. Omitted = the class's current default
8994
+ * (the historical behaviour). A named source that is NOT the default is a
8995
+ * drain of that disk: bytes move, the default stays, and the source is
8996
+ * disabled when the move finishes.
8997
+ */
8998
+ var StorageMigrationSourcesSchema = object({
8999
+ recordings: string().min(1).optional(),
9000
+ recordingsLow: string().min(1).optional(),
9001
+ eventMedia: string().min(1).optional(),
9002
+ backups: string().min(1).optional(),
9003
+ galleryMedia: string().min(1).optional()
9004
+ }).optional();
9005
+ /**
8986
9006
  * How a migration sequences the cutover against the byte move.
8987
9007
  *
8988
9008
  * - `blocking` — the historical order: pause, move every byte, repoint,
@@ -9004,6 +9024,8 @@ var StorageMigrationModeSchema = _enum(["blocking", "nonBlocking"]);
9004
9024
  /** Shared input for planning and starting an orchestrated storage migration. */
9005
9025
  var StorageMigrationInputSchema = object({
9006
9026
  destinations: StorageMigrationDestinationsSchema,
9027
+ /** Omitted = each class's current default. */
9028
+ sources: StorageMigrationSourcesSchema,
9007
9029
  throttleMbps: number().min(1).max(1e3).optional(),
9008
9030
  /** Omitted = `blocking`, which stays the default. */
9009
9031
  mode: StorageMigrationModeSchema.optional()
@@ -9083,6 +9105,13 @@ var StorageMigrationMoveSchema = object({
9083
9105
  storageClass: StorageMigrationClassSchema,
9084
9106
  fromLocationId: string(),
9085
9107
  toLocationId: string(),
9108
+ /**
9109
+ * True when `from` was NOT the class default at plan time. The move still
9110
+ * copies bytes, but the default is left alone and the source is disabled
9111
+ * once the copy verifies. Absent on jobs planned before this field existed
9112
+ * — those jobs always repointed, which is `false`.
9113
+ */
9114
+ freezeSource: boolean().optional(),
9086
9115
  moverJobId: string().nullable(),
9087
9116
  state: RelocateJobStateSchema.nullable(),
9088
9117
  error: string().nullable(),
@@ -9096,6 +9125,7 @@ var StorageMigrationJobSchema = object({
9096
9125
  * can tell a seconds-long cutover from a thirty-hour one. */
9097
9126
  mode: StorageMigrationModeSchema,
9098
9127
  destinations: StorageMigrationDestinationsSchema,
9128
+ sources: StorageMigrationSourcesSchema,
9099
9129
  throttleMbps: number(),
9100
9130
  moves: array(StorageMigrationMoveSchema),
9101
9131
  pauseLeaseId: string().nullable(),
@@ -9121,6 +9151,7 @@ var StorageMigrationFindingSchema = object({
9121
9151
  });
9122
9152
  var StorageMigrationPlanSchema = object({
9123
9153
  destinations: StorageMigrationDestinationsSchema,
9154
+ sources: StorageMigrationSourcesSchema,
9124
9155
  /** The mode this plan was built for. A plan is only valid for its mode: the
9125
9156
  * `eventMedia` seal gate and the single-cardinality refusal both depend on
9126
9157
  * it. */
@@ -9128,7 +9159,8 @@ var StorageMigrationPlanSchema = object({
9128
9159
  moves: array(object({
9129
9160
  storageClass: StorageMigrationClassSchema,
9130
9161
  fromLocationId: string(),
9131
- toLocationId: string()
9162
+ toLocationId: string(),
9163
+ freezeSource: boolean().optional()
9132
9164
  })),
9133
9165
  findings: array(StorageMigrationFindingSchema)
9134
9166
  });
@@ -9306,10 +9338,51 @@ var LedgerWalkReportSchema = object({
9306
9338
  var RelocatableMediaCountSchema = object({ rows: number().int().nonnegative() }).nullable();
9307
9339
  var RelocatableMediaCountInputSchema = object({
9308
9340
  toLocationId: string().min(1),
9341
+ /** Restrict the count to one source; omitted / `'*'` = every non-target row. */
9342
+ fromLocationId: string().optional(),
9309
9343
  /** Omitted = `move`. */
9310
9344
  mode: MediaRelocateModeSchema.optional()
9311
9345
  });
9312
9346
  /**
9347
+ * Operator cleanup of leftover analytics rows, optional debug media, and
9348
+ * ghost ledger entries on frozen footage locations.
9349
+ *
9350
+ * A pass is tens of minutes on a standing backlog. The hub method RETURNS
9351
+ * `{ jobId }` immediately; progress is `cleanupStatus`. Awaiting the work
9352
+ * is how `addons.custom` hit the 60 s UDS deadline while reclaim continued
9353
+ * with no operator-visible status.
9354
+ */
9355
+ var StorageCleanupPhaseSchema = _enum([
9356
+ "orphans",
9357
+ "debug-media",
9358
+ "ghost-ledger",
9359
+ "done",
9360
+ "failed",
9361
+ "cancelled"
9362
+ ]);
9363
+ var StorageCleanupInputSchema = object({
9364
+ /** Also walk motion stills / track filmstrips. Off by default. */
9365
+ includeDebugMedia: boolean().optional() });
9366
+ var StorageCleanupJobSchema = object({
9367
+ jobId: string(),
9368
+ phase: StorageCleanupPhaseSchema,
9369
+ includeDebugMedia: boolean(),
9370
+ orphansReclaimed: number().int().nonnegative(),
9371
+ orphanBytesReclaimed: number().int().nonnegative(),
9372
+ debugMediaReclaimed: number().int().nonnegative(),
9373
+ debugMediaBytesReclaimed: number().int().nonnegative(),
9374
+ ghostsForgotten: number().int().nonnegative(),
9375
+ ghostBytesForgotten: number().int().nonnegative(),
9376
+ /** Short operator-facing line: current collection, pass, or location. */
9377
+ detail: string().nullable(),
9378
+ cancelRequested: boolean(),
9379
+ startedAt: number(),
9380
+ updatedAt: number(),
9381
+ finishedAt: number().nullable(),
9382
+ error: string().nullable()
9383
+ });
9384
+ var StorageCleanupStatusInputSchema = object({ jobId: string().optional() });
9385
+ /**
9313
9386
  * `StorageLocationType` — an addon-declared id that identifies the *kind* of
9314
9387
  * storage a location serves. Defined here (not in `capabilities/storage.cap.ts`)
9315
9388
  * so the persisted record schema and the consumer-facing cap can both consume it
@@ -9337,11 +9410,10 @@ var StorageLocationTypeSchema = string().regex(/^[a-z][a-zA-Z0-9-]*$/);
9337
9410
  * The default location for a type uses `id === <type>:default` by
9338
9411
  * convention (the bare type ref like `'backups'` resolves to it).
9339
9412
  *
9340
- * `isSystem: true` marks a location as orchestrator-seeded and
9341
- * undeletable. The bootstrap-installed defaults (one per type) carry
9342
- * this flag; operator-added locations don't. Editing the config of
9343
- * a system location is allowed (path migration, provider swap) but
9344
- * deleting it is rejected at the cap level.
9413
+ * `isSystem` is a legacy persisted flag. Seed still creates the initial
9414
+ * `<type>:default` locations; the flag is no longer a lock, a badge, or a
9415
+ * prune selector. New writes leave it false. Deletion is gated on uniqueness
9416
+ * / last-enabled, not on this bit.
9345
9417
  */
9346
9418
  var StorageLocationSchema = object({
9347
9419
  id: string().regex(/^[a-z][a-zA-Z0-9-]*:[a-zA-Z0-9-]+$/),
@@ -13884,6 +13956,12 @@ method(object({
13884
13956
  }), _void(), {
13885
13957
  kind: "mutation",
13886
13958
  auth: "admin"
13959
+ }), method(object({
13960
+ from: string(),
13961
+ to: string()
13962
+ }), object({ moved: number() }), {
13963
+ kind: "mutation",
13964
+ auth: "admin"
13887
13965
  }), method(object({
13888
13966
  deviceId: number(),
13889
13967
  disabled: boolean()
@@ -16634,6 +16712,8 @@ var NcSystemEventKindSchema = _enum([
16634
16712
  "device-offline",
16635
16713
  "device-disabled",
16636
16714
  "device-enabled",
16715
+ "device-battery-low",
16716
+ "device-battery-normal",
16637
16717
  "stream-online",
16638
16718
  "stream-offline",
16639
16719
  "node-online",
@@ -19892,46 +19972,6 @@ var RecentTracksPageSchema = object({
19892
19972
  /** Cursor for the next page, or null when this page is the last. */
19893
19973
  nextCursor: string().nullable()
19894
19974
  });
19895
- var LIST_GROUPS_DEFAULT_LIMIT = 40;
19896
- var LIST_GROUPS_MAX_LIMIT = 100;
19897
- var AnalyticsGroupRecordSchema = object({
19898
- id: string(),
19899
- deviceId: number().int(),
19900
- openedAt: number().int(),
19901
- closedAt: number().int(),
19902
- timestamp: number().int(),
19903
- memberCount: number().int(),
19904
- memberTrackIds: array(string()).readonly(),
19905
- className: string(),
19906
- classes: array(string()).readonly(),
19907
- /** Relative event-media path, or null when the group has no picture yet. */
19908
- mediaUrl: string().nullable(),
19909
- singleton: boolean()
19910
- });
19911
- var AnalyticsGroupMemberSchema = object({
19912
- trackId: string(),
19913
- deviceId: number().int(),
19914
- className: string(),
19915
- firstSeen: number().int(),
19916
- lastSeen: number().int(),
19917
- mediaUrl: string().nullable()
19918
- });
19919
- var AnalyticsGroupDetailSchema = AnalyticsGroupRecordSchema.extend({ members: array(AnalyticsGroupMemberSchema).readonly() });
19920
- var ListGroupsQueryInput = object({
19921
- /** Devices to merge. An empty array yields `{ groups: [], nextCursor: null }`. */
19922
- deviceIds: array(number()),
19923
- /** Window lower bound on `closedAt` (inclusive). */
19924
- since: number().optional(),
19925
- /** Window upper bound on `openedAt` (inclusive). */
19926
- until: number().optional(),
19927
- limit: number().int().min(1).max(LIST_GROUPS_MAX_LIMIT).default(LIST_GROUPS_DEFAULT_LIMIT),
19928
- /** Opaque continuation cursor from a previous page's `nextCursor`. */
19929
- cursor: string().optional()
19930
- });
19931
- var ListGroupsPageSchema = object({
19932
- groups: array(AnalyticsGroupRecordSchema).readonly(),
19933
- nextCursor: string().nullable()
19934
- });
19935
19975
  var KEY_EVENTS_DEFAULT_LIMIT = 50;
19936
19976
  var KEY_EVENTS_MAX_LIMIT = 200;
19937
19977
  var KeyEventQueryInput = object({
@@ -20035,9 +20075,7 @@ var TrackCascadeCountsSchema = object({
20035
20075
  /** Unassigned plate reads removed (best-effort; plate leg deferred to plate-intelligence). */
20036
20076
  plates: number().int(),
20037
20077
  /** Per-track CLIP search vectors removed (best-effort). */
20038
- embeddings: number().int(),
20039
- /** Group membership + group rows removed with their last member (best-effort). */
20040
- groups: number().int()
20078
+ embeddings: number().int()
20041
20079
  });
20042
20080
  /** Disk-wins reconcile: media rows whose blobs are gone, then empty tracks. */
20043
20081
  var DiskReconcileCountsSchema = object({
@@ -20207,6 +20245,47 @@ var RebuildStatusSchema = object({
20207
20245
  /** Present when the pass ended by throwing. */
20208
20246
  error: string().nullable()
20209
20247
  });
20248
+ /**
20249
+ * Acknowledgement that a debug-media reclaim STARTED.
20250
+ *
20251
+ * The pass is paced at ~2 MB/s over a standing 100 GB — tens of minutes — so
20252
+ * it runs detached and this returns immediately. Awaiting it is how the
20253
+ * `addons.custom` door hit the 60 s UDS deadline while the walk carried on
20254
+ * with no status. Poll {@link pipelineAnalyticsCapability.methods.getMediaReclaimStatus}.
20255
+ */
20256
+ var MediaReclaimStartResultSchema = object({
20257
+ started: boolean(),
20258
+ /** True when a pass was already running; the new request is ignored. */
20259
+ alreadyRunning: boolean()
20260
+ });
20261
+ var MediaReclaimInputSchema = object({
20262
+ mode: _enum(["report", "reclaim"]).default("report"),
20263
+ scopes: array(_enum(["motion-still", "track-filmstrip"])).min(1).optional(),
20264
+ deviceIds: array(number().int()).min(1).optional(),
20265
+ restart: boolean().optional(),
20266
+ pageSize: number().int().min(50).max(5e3).optional(),
20267
+ maxRowsPerDevice: number().int().min(1).max(5e5).optional(),
20268
+ maxReclaimPerDevice: number().int().min(1).max(5e5).optional(),
20269
+ maxBytesPerRun: number().int().min(1).optional(),
20270
+ budgetMinutes: number().int().min(1).max(720).optional(),
20271
+ throttleBytesPerSec: number().int().min(64 * 1024).optional(),
20272
+ graceMinutes: number().int().min(1).max(10080).optional()
20273
+ });
20274
+ var MediaReclaimStatusSchema = object({
20275
+ running: boolean(),
20276
+ mode: _enum(["report", "reclaim"]).nullable(),
20277
+ totalExamined: number(),
20278
+ totalEligible: number(),
20279
+ totalReclaimed: number(),
20280
+ totalBytesReclaimed: number(),
20281
+ totalRefused: number(),
20282
+ /** Device+scope windows finished in this pass. */
20283
+ devicesDone: number(),
20284
+ complete: boolean().nullable(),
20285
+ startedAtMs: number().nullable(),
20286
+ finishedAtMs: number().nullable(),
20287
+ error: string().nullable()
20288
+ });
20210
20289
  var ReplayFrameInputSchema = object({
20211
20290
  timestamp: number(),
20212
20291
  frame: PipelineRunResultBridge
@@ -20245,10 +20324,7 @@ DeviceType.Camera, method(object({ deviceId: number() }), array(TrackSchema).rea
20245
20324
  * stationary registry). Default false: the timeline lists passages,
20246
20325
  * not parking records (operator decision, 2026-08-15). */
20247
20326
  includeStationary: boolean().optional()
20248
- }), array(TrackSchema).readonly()), method(RecentTracksQueryInput, RecentTracksPageSchema), method(ListGroupsQueryInput, ListGroupsPageSchema), method(object({
20249
- deviceId: number(),
20250
- groupId: string().min(1)
20251
- }), AnalyticsGroupDetailSchema.nullable()), method(object({ deviceId: number() }), _void(), {
20327
+ }), array(TrackSchema).readonly()), method(RecentTracksQueryInput, RecentTracksPageSchema), method(object({ deviceId: number() }), _void(), {
20252
20328
  kind: "mutation",
20253
20329
  auth: "admin"
20254
20330
  }), 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({
@@ -20348,6 +20424,12 @@ DeviceType.Camera, method(object({ deviceId: number() }), array(TrackSchema).rea
20348
20424
  }), method(OpsLogQueryInputSchema, array(OpsLogEntrySchema).readonly(), {
20349
20425
  kind: "query",
20350
20426
  auth: "admin"
20427
+ }), method(MediaReclaimInputSchema, MediaReclaimStartResultSchema, {
20428
+ kind: "mutation",
20429
+ auth: "admin"
20430
+ }), method(object({}), MediaReclaimStatusSchema, {
20431
+ kind: "query",
20432
+ auth: "admin"
20351
20433
  }), method(object({ deviceIds: array(number()).optional() }), TrainingExportSummarySchema, {
20352
20434
  kind: "query",
20353
20435
  auth: "admin"
@@ -22318,7 +22400,13 @@ method(StorageMigrationInputSchema, StorageMigrationPlanSchema, { auth: "admin"
22318
22400
  }), method(object({}), array(StorageMigrationMoverSchema).readonly(), { auth: "admin" }), method(object({}), array(StorageMigrationResidueSchema).readonly(), { auth: "admin" }), method(StorageMigrationDrainInputSchema, object({ jobId: string() }), {
22319
22401
  kind: "mutation",
22320
22402
  auth: "admin"
22321
- });
22403
+ }), method(StorageCleanupInputSchema, object({ jobId: string() }), {
22404
+ kind: "mutation",
22405
+ auth: "admin"
22406
+ }), method(StorageCleanupStatusInputSchema, StorageCleanupJobSchema.nullable(), { auth: "admin" }), method(object({ jobId: string() }), object({ cancelled: boolean() }), {
22407
+ kind: "mutation",
22408
+ auth: "admin"
22409
+ }), method(object({}), array(StorageMigrationJobSchema).readonly(), { auth: "admin" });
22322
22410
  var ProviderInfoSchema = discriminatedUnion("shouldSaveDiskSpace", [object({
22323
22411
  providerId: string().min(1),
22324
22412
  displayName: string().min(1),
@@ -29419,6 +29507,33 @@ var RecordingRebalanceInputSchema = object({
29419
29507
  minMoveGb: number().min(0).optional()
29420
29508
  });
29421
29509
  /**
29510
+ * Operator-facing placement of one camera onto a recordings location.
29511
+ *
29512
+ * `pinLocationId` is the operator instruction: a location id, or `null` for
29513
+ * Auto (the planner may move this camera). `locationId` is where high/mid
29514
+ * currently write — the plan, which may disagree with the pin when Auto.
29515
+ */
29516
+ var RecordingDevicePlacementSchema = object({
29517
+ deviceId: number().int(),
29518
+ profile: string(),
29519
+ locationId: string()
29520
+ });
29521
+ var RecordingDevicePinSchema = object({
29522
+ deviceId: number().int(),
29523
+ /** Recordings-class location this camera is pinned to. */
29524
+ locationId: string()
29525
+ });
29526
+ var RecordingPlacementViewSchema = object({
29527
+ assignments: array(RecordingDevicePlacementSchema),
29528
+ pins: array(RecordingDevicePinSchema),
29529
+ defaultLocations: record(string(), string())
29530
+ });
29531
+ var RecordingSetDevicePlacementInputSchema = object({
29532
+ deviceId: number().int(),
29533
+ /** `null` = Auto. Otherwise a `recordings:*` location id. */
29534
+ locationId: string().nullable()
29535
+ });
29536
+ /**
29422
29537
  * Result of locating footage at a wall-clock instant for one device/profile.
29423
29538
  * `segment` carries the covering segment's window; `gap` reports the forward
29424
29539
  * nearest covered edge (`null` past the end of footage / when none exists)
@@ -29644,6 +29759,12 @@ method(object({
29644
29759
  }), method(RecordingRebalanceInputSchema, RecordingRebalancePlanSchema, {
29645
29760
  kind: "mutation",
29646
29761
  auth: "admin"
29762
+ }), method(object({}), RecordingPlacementViewSchema, {
29763
+ kind: "query",
29764
+ auth: "admin"
29765
+ }), method(RecordingSetDevicePlacementInputSchema, object({ ok: literal(true) }), {
29766
+ kind: "mutation",
29767
+ auth: "admin"
29647
29768
  });
29648
29769
  /**
29649
29770
  * `recording-export` cap — render a footage time range into a single downloadable
@@ -34713,6 +34834,12 @@ Object.freeze({
34713
34834
  addonId: null,
34714
34835
  access: "delete"
34715
34836
  },
34837
+ "deviceManager.renameLocation": {
34838
+ capName: "device-manager",
34839
+ capScope: "system",
34840
+ addonId: null,
34841
+ access: "create"
34842
+ },
34716
34843
  "deviceManager.runDeviceAction": {
34717
34844
  capName: "device-manager",
34718
34845
  capScope: "system",
@@ -36405,19 +36532,19 @@ Object.freeze({
36405
36532
  addonId: null,
36406
36533
  access: "view"
36407
36534
  },
36408
- "pipelineAnalytics.getGroup": {
36535
+ "pipelineAnalytics.getKeyEvents": {
36409
36536
  capName: "pipeline-analytics",
36410
36537
  capScope: "device",
36411
36538
  addonId: null,
36412
36539
  access: "view"
36413
36540
  },
36414
- "pipelineAnalytics.getKeyEvents": {
36541
+ "pipelineAnalytics.getKeyEventsBatch": {
36415
36542
  capName: "pipeline-analytics",
36416
36543
  capScope: "device",
36417
36544
  addonId: null,
36418
36545
  access: "view"
36419
36546
  },
36420
- "pipelineAnalytics.getKeyEventsBatch": {
36547
+ "pipelineAnalytics.getMediaReclaimStatus": {
36421
36548
  capName: "pipeline-analytics",
36422
36549
  capScope: "device",
36423
36550
  addonId: null,
@@ -36507,12 +36634,6 @@ Object.freeze({
36507
36634
  addonId: null,
36508
36635
  access: "view"
36509
36636
  },
36510
- "pipelineAnalytics.listGroups": {
36511
- capName: "pipeline-analytics",
36512
- capScope: "device",
36513
- addonId: null,
36514
- access: "view"
36515
- },
36516
36637
  "pipelineAnalytics.listOpsLog": {
36517
36638
  capName: "pipeline-analytics",
36518
36639
  capScope: "device",
@@ -36597,6 +36718,12 @@ Object.freeze({
36597
36718
  addonId: null,
36598
36719
  access: "create"
36599
36720
  },
36721
+ "pipelineAnalytics.reclaimDebugMedia": {
36722
+ capName: "pipeline-analytics",
36723
+ capScope: "device",
36724
+ addonId: null,
36725
+ access: "create"
36726
+ },
36600
36727
  "pipelineAnalytics.reconcileFromDisk": {
36601
36728
  capName: "pipeline-analytics",
36602
36729
  capScope: "device",
@@ -37521,6 +37648,12 @@ Object.freeze({
37521
37648
  addonId: null,
37522
37649
  access: "view"
37523
37650
  },
37651
+ "recording.getPlacement": {
37652
+ capName: "recording",
37653
+ capScope: "system",
37654
+ addonId: null,
37655
+ access: "view"
37656
+ },
37524
37657
  "recording.getPlaybackManifest": {
37525
37658
  capName: "recording",
37526
37659
  capScope: "system",
@@ -37647,6 +37780,12 @@ Object.freeze({
37647
37780
  addonId: null,
37648
37781
  access: "create"
37649
37782
  },
37783
+ "recording.setDevicePlacement": {
37784
+ capName: "recording",
37785
+ capScope: "system",
37786
+ addonId: null,
37787
+ access: "create"
37788
+ },
37650
37789
  "recording.startStorageMigrationMove": {
37651
37790
  capName: "recording",
37652
37791
  capScope: "system",
@@ -38091,12 +38230,36 @@ Object.freeze({
38091
38230
  addonId: null,
38092
38231
  access: "create"
38093
38232
  },
38233
+ "storageMigration.cleanupCancel": {
38234
+ capName: "storage-migration",
38235
+ capScope: "system",
38236
+ addonId: null,
38237
+ access: "create"
38238
+ },
38239
+ "storageMigration.cleanupStart": {
38240
+ capName: "storage-migration",
38241
+ capScope: "system",
38242
+ addonId: null,
38243
+ access: "create"
38244
+ },
38245
+ "storageMigration.cleanupStatus": {
38246
+ capName: "storage-migration",
38247
+ capScope: "system",
38248
+ addonId: null,
38249
+ access: "view"
38250
+ },
38094
38251
  "storageMigration.drain": {
38095
38252
  capName: "storage-migration",
38096
38253
  capScope: "system",
38097
38254
  addonId: null,
38098
38255
  access: "create"
38099
38256
  },
38257
+ "storageMigration.history": {
38258
+ capName: "storage-migration",
38259
+ capScope: "system",
38260
+ addonId: null,
38261
+ access: "view"
38262
+ },
38100
38263
  "storageMigration.movers": {
38101
38264
  capName: "storage-migration",
38102
38265
  capScope: "system",
@@ -40093,11 +40256,6 @@ Object.freeze({
40093
40256
  form: "single",
40094
40257
  optional: true
40095
40258
  }],
40096
- "pipelineAnalytics.getGroup": [{
40097
- name: "deviceId",
40098
- form: "single",
40099
- optional: false
40100
- }],
40101
40259
  "pipelineAnalytics.getKeyEvents": [{
40102
40260
  name: "deviceId",
40103
40261
  form: "single",
@@ -40163,11 +40321,6 @@ Object.freeze({
40163
40321
  form: "single",
40164
40322
  optional: false
40165
40323
  }],
40166
- "pipelineAnalytics.listGroups": [{
40167
- name: "deviceIds",
40168
- form: "array",
40169
- optional: false
40170
- }],
40171
40324
  "pipelineAnalytics.listOpsLog": [{
40172
40325
  name: "deviceId",
40173
40326
  form: "single",
@@ -40213,6 +40366,11 @@ Object.freeze({
40213
40366
  form: "single",
40214
40367
  optional: true
40215
40368
  }],
40369
+ "pipelineAnalytics.reclaimDebugMedia": [{
40370
+ name: "deviceIds",
40371
+ form: "array",
40372
+ optional: true
40373
+ }],
40216
40374
  "pipelineAnalytics.reconcileFromDisk": [{
40217
40375
  name: "deviceId",
40218
40376
  form: "single",
@@ -40578,6 +40736,11 @@ Object.freeze({
40578
40736
  form: "single",
40579
40737
  optional: false
40580
40738
  }],
40739
+ "recording.setDevicePlacement": [{
40740
+ name: "deviceId",
40741
+ form: "single",
40742
+ optional: false
40743
+ }],
40581
40744
  "recording.startStorageMigrationMove": [{
40582
40745
  name: "deviceId",
40583
40746
  form: "single",
package/dist/addon.mjs CHANGED
@@ -8915,6 +8915,13 @@ var MediaRelocateModeSchema = _enum([
8915
8915
  ]);
8916
8916
  var RelocateMediaInputSchema = object({
8917
8917
  toLocationId: string(),
8918
+ /**
8919
+ * Restrict the pass to rows currently on this location. Omitted / `'*'` =
8920
+ * every row that is not already on `toLocationId` (the historical
8921
+ * behaviour). A named source is what a from→to migration needs: without it
8922
+ * "move events off disk 2" also emptied disk 1.
8923
+ */
8924
+ fromLocationId: string().optional(),
8918
8925
  throttleMbps: number().min(1).max(1e3).optional(),
8919
8926
  /** Omitted = `move`, the pre-existing behaviour. */
8920
8927
  mode: MediaRelocateModeSchema.optional()
@@ -8982,6 +8989,19 @@ var StorageMigrationDestinationsSchema = object({
8982
8989
  galleryMedia: string().min(1).optional()
8983
8990
  }).refine((value) => Object.keys(value).length > 0, { message: "select at least one storage class" });
8984
8991
  /**
8992
+ * Optional named source per class. Omitted = the class's current default
8993
+ * (the historical behaviour). A named source that is NOT the default is a
8994
+ * drain of that disk: bytes move, the default stays, and the source is
8995
+ * disabled when the move finishes.
8996
+ */
8997
+ var StorageMigrationSourcesSchema = object({
8998
+ recordings: string().min(1).optional(),
8999
+ recordingsLow: string().min(1).optional(),
9000
+ eventMedia: string().min(1).optional(),
9001
+ backups: string().min(1).optional(),
9002
+ galleryMedia: string().min(1).optional()
9003
+ }).optional();
9004
+ /**
8985
9005
  * How a migration sequences the cutover against the byte move.
8986
9006
  *
8987
9007
  * - `blocking` — the historical order: pause, move every byte, repoint,
@@ -9003,6 +9023,8 @@ var StorageMigrationModeSchema = _enum(["blocking", "nonBlocking"]);
9003
9023
  /** Shared input for planning and starting an orchestrated storage migration. */
9004
9024
  var StorageMigrationInputSchema = object({
9005
9025
  destinations: StorageMigrationDestinationsSchema,
9026
+ /** Omitted = each class's current default. */
9027
+ sources: StorageMigrationSourcesSchema,
9006
9028
  throttleMbps: number().min(1).max(1e3).optional(),
9007
9029
  /** Omitted = `blocking`, which stays the default. */
9008
9030
  mode: StorageMigrationModeSchema.optional()
@@ -9082,6 +9104,13 @@ var StorageMigrationMoveSchema = object({
9082
9104
  storageClass: StorageMigrationClassSchema,
9083
9105
  fromLocationId: string(),
9084
9106
  toLocationId: string(),
9107
+ /**
9108
+ * True when `from` was NOT the class default at plan time. The move still
9109
+ * copies bytes, but the default is left alone and the source is disabled
9110
+ * once the copy verifies. Absent on jobs planned before this field existed
9111
+ * — those jobs always repointed, which is `false`.
9112
+ */
9113
+ freezeSource: boolean().optional(),
9085
9114
  moverJobId: string().nullable(),
9086
9115
  state: RelocateJobStateSchema.nullable(),
9087
9116
  error: string().nullable(),
@@ -9095,6 +9124,7 @@ var StorageMigrationJobSchema = object({
9095
9124
  * can tell a seconds-long cutover from a thirty-hour one. */
9096
9125
  mode: StorageMigrationModeSchema,
9097
9126
  destinations: StorageMigrationDestinationsSchema,
9127
+ sources: StorageMigrationSourcesSchema,
9098
9128
  throttleMbps: number(),
9099
9129
  moves: array(StorageMigrationMoveSchema),
9100
9130
  pauseLeaseId: string().nullable(),
@@ -9120,6 +9150,7 @@ var StorageMigrationFindingSchema = object({
9120
9150
  });
9121
9151
  var StorageMigrationPlanSchema = object({
9122
9152
  destinations: StorageMigrationDestinationsSchema,
9153
+ sources: StorageMigrationSourcesSchema,
9123
9154
  /** The mode this plan was built for. A plan is only valid for its mode: the
9124
9155
  * `eventMedia` seal gate and the single-cardinality refusal both depend on
9125
9156
  * it. */
@@ -9127,7 +9158,8 @@ var StorageMigrationPlanSchema = object({
9127
9158
  moves: array(object({
9128
9159
  storageClass: StorageMigrationClassSchema,
9129
9160
  fromLocationId: string(),
9130
- toLocationId: string()
9161
+ toLocationId: string(),
9162
+ freezeSource: boolean().optional()
9131
9163
  })),
9132
9164
  findings: array(StorageMigrationFindingSchema)
9133
9165
  });
@@ -9305,10 +9337,51 @@ var LedgerWalkReportSchema = object({
9305
9337
  var RelocatableMediaCountSchema = object({ rows: number().int().nonnegative() }).nullable();
9306
9338
  var RelocatableMediaCountInputSchema = object({
9307
9339
  toLocationId: string().min(1),
9340
+ /** Restrict the count to one source; omitted / `'*'` = every non-target row. */
9341
+ fromLocationId: string().optional(),
9308
9342
  /** Omitted = `move`. */
9309
9343
  mode: MediaRelocateModeSchema.optional()
9310
9344
  });
9311
9345
  /**
9346
+ * Operator cleanup of leftover analytics rows, optional debug media, and
9347
+ * ghost ledger entries on frozen footage locations.
9348
+ *
9349
+ * A pass is tens of minutes on a standing backlog. The hub method RETURNS
9350
+ * `{ jobId }` immediately; progress is `cleanupStatus`. Awaiting the work
9351
+ * is how `addons.custom` hit the 60 s UDS deadline while reclaim continued
9352
+ * with no operator-visible status.
9353
+ */
9354
+ var StorageCleanupPhaseSchema = _enum([
9355
+ "orphans",
9356
+ "debug-media",
9357
+ "ghost-ledger",
9358
+ "done",
9359
+ "failed",
9360
+ "cancelled"
9361
+ ]);
9362
+ var StorageCleanupInputSchema = object({
9363
+ /** Also walk motion stills / track filmstrips. Off by default. */
9364
+ includeDebugMedia: boolean().optional() });
9365
+ var StorageCleanupJobSchema = object({
9366
+ jobId: string(),
9367
+ phase: StorageCleanupPhaseSchema,
9368
+ includeDebugMedia: boolean(),
9369
+ orphansReclaimed: number().int().nonnegative(),
9370
+ orphanBytesReclaimed: number().int().nonnegative(),
9371
+ debugMediaReclaimed: number().int().nonnegative(),
9372
+ debugMediaBytesReclaimed: number().int().nonnegative(),
9373
+ ghostsForgotten: number().int().nonnegative(),
9374
+ ghostBytesForgotten: number().int().nonnegative(),
9375
+ /** Short operator-facing line: current collection, pass, or location. */
9376
+ detail: string().nullable(),
9377
+ cancelRequested: boolean(),
9378
+ startedAt: number(),
9379
+ updatedAt: number(),
9380
+ finishedAt: number().nullable(),
9381
+ error: string().nullable()
9382
+ });
9383
+ var StorageCleanupStatusInputSchema = object({ jobId: string().optional() });
9384
+ /**
9312
9385
  * `StorageLocationType` — an addon-declared id that identifies the *kind* of
9313
9386
  * storage a location serves. Defined here (not in `capabilities/storage.cap.ts`)
9314
9387
  * so the persisted record schema and the consumer-facing cap can both consume it
@@ -9336,11 +9409,10 @@ var StorageLocationTypeSchema = string().regex(/^[a-z][a-zA-Z0-9-]*$/);
9336
9409
  * The default location for a type uses `id === <type>:default` by
9337
9410
  * convention (the bare type ref like `'backups'` resolves to it).
9338
9411
  *
9339
- * `isSystem: true` marks a location as orchestrator-seeded and
9340
- * undeletable. The bootstrap-installed defaults (one per type) carry
9341
- * this flag; operator-added locations don't. Editing the config of
9342
- * a system location is allowed (path migration, provider swap) but
9343
- * deleting it is rejected at the cap level.
9412
+ * `isSystem` is a legacy persisted flag. Seed still creates the initial
9413
+ * `<type>:default` locations; the flag is no longer a lock, a badge, or a
9414
+ * prune selector. New writes leave it false. Deletion is gated on uniqueness
9415
+ * / last-enabled, not on this bit.
9344
9416
  */
9345
9417
  var StorageLocationSchema = object({
9346
9418
  id: string().regex(/^[a-z][a-zA-Z0-9-]*:[a-zA-Z0-9-]+$/),
@@ -13883,6 +13955,12 @@ method(object({
13883
13955
  }), _void(), {
13884
13956
  kind: "mutation",
13885
13957
  auth: "admin"
13958
+ }), method(object({
13959
+ from: string(),
13960
+ to: string()
13961
+ }), object({ moved: number() }), {
13962
+ kind: "mutation",
13963
+ auth: "admin"
13886
13964
  }), method(object({
13887
13965
  deviceId: number(),
13888
13966
  disabled: boolean()
@@ -16633,6 +16711,8 @@ var NcSystemEventKindSchema = _enum([
16633
16711
  "device-offline",
16634
16712
  "device-disabled",
16635
16713
  "device-enabled",
16714
+ "device-battery-low",
16715
+ "device-battery-normal",
16636
16716
  "stream-online",
16637
16717
  "stream-offline",
16638
16718
  "node-online",
@@ -19891,46 +19971,6 @@ var RecentTracksPageSchema = object({
19891
19971
  /** Cursor for the next page, or null when this page is the last. */
19892
19972
  nextCursor: string().nullable()
19893
19973
  });
19894
- var LIST_GROUPS_DEFAULT_LIMIT = 40;
19895
- var LIST_GROUPS_MAX_LIMIT = 100;
19896
- var AnalyticsGroupRecordSchema = object({
19897
- id: string(),
19898
- deviceId: number().int(),
19899
- openedAt: number().int(),
19900
- closedAt: number().int(),
19901
- timestamp: number().int(),
19902
- memberCount: number().int(),
19903
- memberTrackIds: array(string()).readonly(),
19904
- className: string(),
19905
- classes: array(string()).readonly(),
19906
- /** Relative event-media path, or null when the group has no picture yet. */
19907
- mediaUrl: string().nullable(),
19908
- singleton: boolean()
19909
- });
19910
- var AnalyticsGroupMemberSchema = object({
19911
- trackId: string(),
19912
- deviceId: number().int(),
19913
- className: string(),
19914
- firstSeen: number().int(),
19915
- lastSeen: number().int(),
19916
- mediaUrl: string().nullable()
19917
- });
19918
- var AnalyticsGroupDetailSchema = AnalyticsGroupRecordSchema.extend({ members: array(AnalyticsGroupMemberSchema).readonly() });
19919
- var ListGroupsQueryInput = object({
19920
- /** Devices to merge. An empty array yields `{ groups: [], nextCursor: null }`. */
19921
- deviceIds: array(number()),
19922
- /** Window lower bound on `closedAt` (inclusive). */
19923
- since: number().optional(),
19924
- /** Window upper bound on `openedAt` (inclusive). */
19925
- until: number().optional(),
19926
- limit: number().int().min(1).max(LIST_GROUPS_MAX_LIMIT).default(LIST_GROUPS_DEFAULT_LIMIT),
19927
- /** Opaque continuation cursor from a previous page's `nextCursor`. */
19928
- cursor: string().optional()
19929
- });
19930
- var ListGroupsPageSchema = object({
19931
- groups: array(AnalyticsGroupRecordSchema).readonly(),
19932
- nextCursor: string().nullable()
19933
- });
19934
19974
  var KEY_EVENTS_DEFAULT_LIMIT = 50;
19935
19975
  var KEY_EVENTS_MAX_LIMIT = 200;
19936
19976
  var KeyEventQueryInput = object({
@@ -20034,9 +20074,7 @@ var TrackCascadeCountsSchema = object({
20034
20074
  /** Unassigned plate reads removed (best-effort; plate leg deferred to plate-intelligence). */
20035
20075
  plates: number().int(),
20036
20076
  /** Per-track CLIP search vectors removed (best-effort). */
20037
- embeddings: number().int(),
20038
- /** Group membership + group rows removed with their last member (best-effort). */
20039
- groups: number().int()
20077
+ embeddings: number().int()
20040
20078
  });
20041
20079
  /** Disk-wins reconcile: media rows whose blobs are gone, then empty tracks. */
20042
20080
  var DiskReconcileCountsSchema = object({
@@ -20206,6 +20244,47 @@ var RebuildStatusSchema = object({
20206
20244
  /** Present when the pass ended by throwing. */
20207
20245
  error: string().nullable()
20208
20246
  });
20247
+ /**
20248
+ * Acknowledgement that a debug-media reclaim STARTED.
20249
+ *
20250
+ * The pass is paced at ~2 MB/s over a standing 100 GB — tens of minutes — so
20251
+ * it runs detached and this returns immediately. Awaiting it is how the
20252
+ * `addons.custom` door hit the 60 s UDS deadline while the walk carried on
20253
+ * with no status. Poll {@link pipelineAnalyticsCapability.methods.getMediaReclaimStatus}.
20254
+ */
20255
+ var MediaReclaimStartResultSchema = object({
20256
+ started: boolean(),
20257
+ /** True when a pass was already running; the new request is ignored. */
20258
+ alreadyRunning: boolean()
20259
+ });
20260
+ var MediaReclaimInputSchema = object({
20261
+ mode: _enum(["report", "reclaim"]).default("report"),
20262
+ scopes: array(_enum(["motion-still", "track-filmstrip"])).min(1).optional(),
20263
+ deviceIds: array(number().int()).min(1).optional(),
20264
+ restart: boolean().optional(),
20265
+ pageSize: number().int().min(50).max(5e3).optional(),
20266
+ maxRowsPerDevice: number().int().min(1).max(5e5).optional(),
20267
+ maxReclaimPerDevice: number().int().min(1).max(5e5).optional(),
20268
+ maxBytesPerRun: number().int().min(1).optional(),
20269
+ budgetMinutes: number().int().min(1).max(720).optional(),
20270
+ throttleBytesPerSec: number().int().min(64 * 1024).optional(),
20271
+ graceMinutes: number().int().min(1).max(10080).optional()
20272
+ });
20273
+ var MediaReclaimStatusSchema = object({
20274
+ running: boolean(),
20275
+ mode: _enum(["report", "reclaim"]).nullable(),
20276
+ totalExamined: number(),
20277
+ totalEligible: number(),
20278
+ totalReclaimed: number(),
20279
+ totalBytesReclaimed: number(),
20280
+ totalRefused: number(),
20281
+ /** Device+scope windows finished in this pass. */
20282
+ devicesDone: number(),
20283
+ complete: boolean().nullable(),
20284
+ startedAtMs: number().nullable(),
20285
+ finishedAtMs: number().nullable(),
20286
+ error: string().nullable()
20287
+ });
20209
20288
  var ReplayFrameInputSchema = object({
20210
20289
  timestamp: number(),
20211
20290
  frame: PipelineRunResultBridge
@@ -20244,10 +20323,7 @@ DeviceType.Camera, method(object({ deviceId: number() }), array(TrackSchema).rea
20244
20323
  * stationary registry). Default false: the timeline lists passages,
20245
20324
  * not parking records (operator decision, 2026-08-15). */
20246
20325
  includeStationary: boolean().optional()
20247
- }), array(TrackSchema).readonly()), method(RecentTracksQueryInput, RecentTracksPageSchema), method(ListGroupsQueryInput, ListGroupsPageSchema), method(object({
20248
- deviceId: number(),
20249
- groupId: string().min(1)
20250
- }), AnalyticsGroupDetailSchema.nullable()), method(object({ deviceId: number() }), _void(), {
20326
+ }), array(TrackSchema).readonly()), method(RecentTracksQueryInput, RecentTracksPageSchema), method(object({ deviceId: number() }), _void(), {
20251
20327
  kind: "mutation",
20252
20328
  auth: "admin"
20253
20329
  }), 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({
@@ -20347,6 +20423,12 @@ DeviceType.Camera, method(object({ deviceId: number() }), array(TrackSchema).rea
20347
20423
  }), method(OpsLogQueryInputSchema, array(OpsLogEntrySchema).readonly(), {
20348
20424
  kind: "query",
20349
20425
  auth: "admin"
20426
+ }), method(MediaReclaimInputSchema, MediaReclaimStartResultSchema, {
20427
+ kind: "mutation",
20428
+ auth: "admin"
20429
+ }), method(object({}), MediaReclaimStatusSchema, {
20430
+ kind: "query",
20431
+ auth: "admin"
20350
20432
  }), method(object({ deviceIds: array(number()).optional() }), TrainingExportSummarySchema, {
20351
20433
  kind: "query",
20352
20434
  auth: "admin"
@@ -22317,7 +22399,13 @@ method(StorageMigrationInputSchema, StorageMigrationPlanSchema, { auth: "admin"
22317
22399
  }), method(object({}), array(StorageMigrationMoverSchema).readonly(), { auth: "admin" }), method(object({}), array(StorageMigrationResidueSchema).readonly(), { auth: "admin" }), method(StorageMigrationDrainInputSchema, object({ jobId: string() }), {
22318
22400
  kind: "mutation",
22319
22401
  auth: "admin"
22320
- });
22402
+ }), method(StorageCleanupInputSchema, object({ jobId: string() }), {
22403
+ kind: "mutation",
22404
+ auth: "admin"
22405
+ }), method(StorageCleanupStatusInputSchema, StorageCleanupJobSchema.nullable(), { auth: "admin" }), method(object({ jobId: string() }), object({ cancelled: boolean() }), {
22406
+ kind: "mutation",
22407
+ auth: "admin"
22408
+ }), method(object({}), array(StorageMigrationJobSchema).readonly(), { auth: "admin" });
22321
22409
  var ProviderInfoSchema = discriminatedUnion("shouldSaveDiskSpace", [object({
22322
22410
  providerId: string().min(1),
22323
22411
  displayName: string().min(1),
@@ -29418,6 +29506,33 @@ var RecordingRebalanceInputSchema = object({
29418
29506
  minMoveGb: number().min(0).optional()
29419
29507
  });
29420
29508
  /**
29509
+ * Operator-facing placement of one camera onto a recordings location.
29510
+ *
29511
+ * `pinLocationId` is the operator instruction: a location id, or `null` for
29512
+ * Auto (the planner may move this camera). `locationId` is where high/mid
29513
+ * currently write — the plan, which may disagree with the pin when Auto.
29514
+ */
29515
+ var RecordingDevicePlacementSchema = object({
29516
+ deviceId: number().int(),
29517
+ profile: string(),
29518
+ locationId: string()
29519
+ });
29520
+ var RecordingDevicePinSchema = object({
29521
+ deviceId: number().int(),
29522
+ /** Recordings-class location this camera is pinned to. */
29523
+ locationId: string()
29524
+ });
29525
+ var RecordingPlacementViewSchema = object({
29526
+ assignments: array(RecordingDevicePlacementSchema),
29527
+ pins: array(RecordingDevicePinSchema),
29528
+ defaultLocations: record(string(), string())
29529
+ });
29530
+ var RecordingSetDevicePlacementInputSchema = object({
29531
+ deviceId: number().int(),
29532
+ /** `null` = Auto. Otherwise a `recordings:*` location id. */
29533
+ locationId: string().nullable()
29534
+ });
29535
+ /**
29421
29536
  * Result of locating footage at a wall-clock instant for one device/profile.
29422
29537
  * `segment` carries the covering segment's window; `gap` reports the forward
29423
29538
  * nearest covered edge (`null` past the end of footage / when none exists)
@@ -29643,6 +29758,12 @@ method(object({
29643
29758
  }), method(RecordingRebalanceInputSchema, RecordingRebalancePlanSchema, {
29644
29759
  kind: "mutation",
29645
29760
  auth: "admin"
29761
+ }), method(object({}), RecordingPlacementViewSchema, {
29762
+ kind: "query",
29763
+ auth: "admin"
29764
+ }), method(RecordingSetDevicePlacementInputSchema, object({ ok: literal(true) }), {
29765
+ kind: "mutation",
29766
+ auth: "admin"
29646
29767
  });
29647
29768
  /**
29648
29769
  * `recording-export` cap — render a footage time range into a single downloadable
@@ -34712,6 +34833,12 @@ Object.freeze({
34712
34833
  addonId: null,
34713
34834
  access: "delete"
34714
34835
  },
34836
+ "deviceManager.renameLocation": {
34837
+ capName: "device-manager",
34838
+ capScope: "system",
34839
+ addonId: null,
34840
+ access: "create"
34841
+ },
34715
34842
  "deviceManager.runDeviceAction": {
34716
34843
  capName: "device-manager",
34717
34844
  capScope: "system",
@@ -36404,19 +36531,19 @@ Object.freeze({
36404
36531
  addonId: null,
36405
36532
  access: "view"
36406
36533
  },
36407
- "pipelineAnalytics.getGroup": {
36534
+ "pipelineAnalytics.getKeyEvents": {
36408
36535
  capName: "pipeline-analytics",
36409
36536
  capScope: "device",
36410
36537
  addonId: null,
36411
36538
  access: "view"
36412
36539
  },
36413
- "pipelineAnalytics.getKeyEvents": {
36540
+ "pipelineAnalytics.getKeyEventsBatch": {
36414
36541
  capName: "pipeline-analytics",
36415
36542
  capScope: "device",
36416
36543
  addonId: null,
36417
36544
  access: "view"
36418
36545
  },
36419
- "pipelineAnalytics.getKeyEventsBatch": {
36546
+ "pipelineAnalytics.getMediaReclaimStatus": {
36420
36547
  capName: "pipeline-analytics",
36421
36548
  capScope: "device",
36422
36549
  addonId: null,
@@ -36506,12 +36633,6 @@ Object.freeze({
36506
36633
  addonId: null,
36507
36634
  access: "view"
36508
36635
  },
36509
- "pipelineAnalytics.listGroups": {
36510
- capName: "pipeline-analytics",
36511
- capScope: "device",
36512
- addonId: null,
36513
- access: "view"
36514
- },
36515
36636
  "pipelineAnalytics.listOpsLog": {
36516
36637
  capName: "pipeline-analytics",
36517
36638
  capScope: "device",
@@ -36596,6 +36717,12 @@ Object.freeze({
36596
36717
  addonId: null,
36597
36718
  access: "create"
36598
36719
  },
36720
+ "pipelineAnalytics.reclaimDebugMedia": {
36721
+ capName: "pipeline-analytics",
36722
+ capScope: "device",
36723
+ addonId: null,
36724
+ access: "create"
36725
+ },
36599
36726
  "pipelineAnalytics.reconcileFromDisk": {
36600
36727
  capName: "pipeline-analytics",
36601
36728
  capScope: "device",
@@ -37520,6 +37647,12 @@ Object.freeze({
37520
37647
  addonId: null,
37521
37648
  access: "view"
37522
37649
  },
37650
+ "recording.getPlacement": {
37651
+ capName: "recording",
37652
+ capScope: "system",
37653
+ addonId: null,
37654
+ access: "view"
37655
+ },
37523
37656
  "recording.getPlaybackManifest": {
37524
37657
  capName: "recording",
37525
37658
  capScope: "system",
@@ -37646,6 +37779,12 @@ Object.freeze({
37646
37779
  addonId: null,
37647
37780
  access: "create"
37648
37781
  },
37782
+ "recording.setDevicePlacement": {
37783
+ capName: "recording",
37784
+ capScope: "system",
37785
+ addonId: null,
37786
+ access: "create"
37787
+ },
37649
37788
  "recording.startStorageMigrationMove": {
37650
37789
  capName: "recording",
37651
37790
  capScope: "system",
@@ -38090,12 +38229,36 @@ Object.freeze({
38090
38229
  addonId: null,
38091
38230
  access: "create"
38092
38231
  },
38232
+ "storageMigration.cleanupCancel": {
38233
+ capName: "storage-migration",
38234
+ capScope: "system",
38235
+ addonId: null,
38236
+ access: "create"
38237
+ },
38238
+ "storageMigration.cleanupStart": {
38239
+ capName: "storage-migration",
38240
+ capScope: "system",
38241
+ addonId: null,
38242
+ access: "create"
38243
+ },
38244
+ "storageMigration.cleanupStatus": {
38245
+ capName: "storage-migration",
38246
+ capScope: "system",
38247
+ addonId: null,
38248
+ access: "view"
38249
+ },
38093
38250
  "storageMigration.drain": {
38094
38251
  capName: "storage-migration",
38095
38252
  capScope: "system",
38096
38253
  addonId: null,
38097
38254
  access: "create"
38098
38255
  },
38256
+ "storageMigration.history": {
38257
+ capName: "storage-migration",
38258
+ capScope: "system",
38259
+ addonId: null,
38260
+ access: "view"
38261
+ },
38099
38262
  "storageMigration.movers": {
38100
38263
  capName: "storage-migration",
38101
38264
  capScope: "system",
@@ -40092,11 +40255,6 @@ Object.freeze({
40092
40255
  form: "single",
40093
40256
  optional: true
40094
40257
  }],
40095
- "pipelineAnalytics.getGroup": [{
40096
- name: "deviceId",
40097
- form: "single",
40098
- optional: false
40099
- }],
40100
40258
  "pipelineAnalytics.getKeyEvents": [{
40101
40259
  name: "deviceId",
40102
40260
  form: "single",
@@ -40162,11 +40320,6 @@ Object.freeze({
40162
40320
  form: "single",
40163
40321
  optional: false
40164
40322
  }],
40165
- "pipelineAnalytics.listGroups": [{
40166
- name: "deviceIds",
40167
- form: "array",
40168
- optional: false
40169
- }],
40170
40323
  "pipelineAnalytics.listOpsLog": [{
40171
40324
  name: "deviceId",
40172
40325
  form: "single",
@@ -40212,6 +40365,11 @@ Object.freeze({
40212
40365
  form: "single",
40213
40366
  optional: true
40214
40367
  }],
40368
+ "pipelineAnalytics.reclaimDebugMedia": [{
40369
+ name: "deviceIds",
40370
+ form: "array",
40371
+ optional: true
40372
+ }],
40215
40373
  "pipelineAnalytics.reconcileFromDisk": [{
40216
40374
  name: "deviceId",
40217
40375
  form: "single",
@@ -40577,6 +40735,11 @@ Object.freeze({
40577
40735
  form: "single",
40578
40736
  optional: false
40579
40737
  }],
40738
+ "recording.setDevicePlacement": [{
40739
+ name: "deviceId",
40740
+ form: "single",
40741
+ optional: false
40742
+ }],
40580
40743
  "recording.startStorageMigrationMove": [{
40581
40744
  name: "deviceId",
40582
40745
  form: "single",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@camstack/addon-provider-tuya",
3
- "version": "0.2.49",
3
+ "version": "0.2.51",
4
4
  "description": "Tuya / Smart Life device-provider addon for CamStack — account-onboarded (Tuya IoT cloud fetch of device localKeys) + LOCAL DP control via the @apocaliss92/nodetuya encrypted-LAN client, exposing switch / water-heater-family kettle entities",
5
5
  "keywords": [
6
6
  "camstack",