@camstack/addon-admin-ui 1.2.122 → 1.2.128
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/assets/AddLocationWizard-B_AdfXau.js +1 -0
- package/dist/assets/{AddonCollectionPage-BDrM-bi7.js → AddonCollectionPage-7_ZV4vRY.js} +1 -1
- package/dist/assets/Addons-XVPdUykV.js +1 -0
- package/dist/assets/{AdminTabs-B-DTEeo0.js → AdminTabs-D8BTKYuR.js} +1 -1
- package/dist/assets/AiProfiles-BkdAAMW4.js +3 -0
- package/dist/assets/{BrokerForm-DkTbh7e9.js → BrokerForm-B_OAC_1i.js} +1 -1
- package/dist/assets/{Build-BP4fixrD.js → Build-BMOCLNvU.js} +3 -3
- package/dist/assets/{Capabilities-v3ciWeJW.js → Capabilities-AobscDZw.js} +1 -1
- package/dist/assets/CapabilityBadges-D0rIjqQG.js +1 -0
- package/dist/assets/Cluster-CDyS8G_H.js +11 -0
- package/dist/assets/Data-1Vu6qKIL.js +1 -0
- package/dist/assets/DetectionIntelligence-CpLIYNjK.js +1 -0
- package/dist/assets/{DeviceAggregateSection-Db0LhcGe.js → DeviceAggregateSection-D8CMIFDC.js} +1 -1
- package/dist/assets/DeviceDetail-C7PAkrDU.js +2 -0
- package/dist/assets/{Devices-hW8DXlvS.js → Devices-Dvs5rS8v.js} +1 -1
- package/dist/assets/{EmbedPlayerPage-Dyhw73FF.js → EmbedPlayerPage-D7z5YtA6.js} +1 -1
- package/dist/assets/Events-Db-3LlE5.js +1 -0
- package/dist/assets/FormBuilder-B_c8sWx_.js +1 -0
- package/dist/assets/Identity-DjxH85iq.js +1 -0
- package/dist/assets/IntegrationDetail-bTYH6lED.js +1 -0
- package/dist/assets/{Integrations-CeMKkD7M.js → Integrations-BCWQ_DtJ.js} +1 -1
- package/dist/assets/Integrations-XfmO-1pH.js +1 -0
- package/dist/assets/Locations-Lk2UKqdY.js +1 -0
- package/dist/assets/{Logs-Bz5wv5Qq.js → Logs-Dv3hDv5y.js} +1 -1
- package/dist/assets/{MotionZonesSettings--3TXO6vq.js → MotionZonesSettings-N9HQGRa7.js} +1 -1
- package/dist/assets/MyAccess-DPba9KGj.js +2 -0
- package/dist/assets/Network-v6WaPUyz.js +1 -0
- package/dist/assets/NodeAddonsSettingsPanel-Dg6XqJHG.js +1 -0
- package/dist/assets/{NodeInferenceDevices-CgtlXT45.js → NodeInferenceDevices-DXV-jla5.js} +1 -1
- package/dist/assets/Notifications-BVojel12.js +1 -0
- package/dist/assets/Pipeline-Dmpsmosq.js +1 -0
- package/dist/assets/Plates-C7dmcASO.js +1 -0
- package/dist/assets/{PrivacyMaskSettings-8V46Jdgm.js → PrivacyMaskSettings-CG9q_Pck.js} +1 -1
- package/dist/assets/{ProviderIcon-CKFlb9NC.js → ProviderIcon-CIaUpaX5.js} +1 -1
- package/dist/assets/Recordings-B5jDvGa-.js +1 -0
- package/dist/assets/{ScanNetworkModal-B7LGMcDr.js → ScanNetworkModal-hRzZAB8R.js} +1 -1
- package/dist/assets/{SceneMonitorEditor-DZd4dDVQ.js → SceneMonitorEditor-SEB-zTQ7.js} +1 -1
- package/dist/assets/{Scenes-D6D5QAMW.js → Scenes-Y44onRFz.js} +1 -1
- package/dist/assets/Settings-CD8UtVyp.js +1 -0
- package/dist/assets/{Showroom-DDzYd3AF.js → Showroom-CVs4Og7T.js} +1 -1
- package/dist/assets/StorageLocationsPanel-5ZLCupIV.js +1 -0
- package/dist/assets/{Terminal-D3n_uL2U.js → Terminal-BRki_hjt.js} +3 -3
- package/dist/assets/{_virtual_mf-localSharedImportMap___mfe_internal__admin_ui_host-YbPw2VQX.js → _virtual_mf-localSharedImportMap___mfe_internal__admin_ui_host-geNDybfU.js} +1 -1
- package/dist/assets/bell-off-BiDWk58P.js +1 -0
- package/dist/assets/bell-ring-Dy0jL0Xx.js +1 -0
- package/dist/assets/{boxes-BAFsgFOP.js → boxes-CQ-CqusQ.js} +1 -1
- package/dist/assets/circle-check-big-Ba7-2FmC.js +1 -0
- package/dist/assets/circle-dot-C6iJnWKI.js +1 -0
- package/dist/assets/{circle-x-BmzsLDtE.js → circle-x-HjVr4za2.js} +1 -1
- package/dist/assets/clock-n6vVuAob.js +1 -0
- package/dist/assets/{copy-CD-KIahX.js → copy-ejXj3qrK.js} +1 -1
- package/dist/assets/{debounced-invalidate-CyVKCjeP.js → debounced-invalidate-B5E6Ixcz.js} +1 -1
- package/dist/assets/dist-7EjqJbju.js +349 -0
- package/dist/assets/{dist-BU1WIKGl.js → dist-Bn4X4eRb.js} +1 -1
- package/dist/assets/{download-F5TwZ1QT.js → download-tpveiw3F.js} +1 -1
- package/dist/assets/{face-bbox-COl_xNUu.js → face-bbox-CBNXMWBK.js} +1 -1
- package/dist/assets/flame-C3GhvXox.js +1 -0
- package/dist/assets/hard-drive-BKAwKbJ6.js +1 -0
- package/dist/assets/{hostInit-BymnDQUp.js → hostInit-Dmv2WFL3.js} +1 -1
- package/dist/assets/index-Cch0DQuM.js +4 -0
- package/dist/assets/index-DpyC2pdq.css +2 -0
- package/dist/assets/{key-round-J-NFrhgM.js → key-round-CDMBgOvT.js} +1 -1
- package/dist/assets/{layers-C_lSBqn_.js → layers-vQ18uXEf.js} +1 -1
- package/dist/assets/{mf-entry-bootstrap-0-d5c55f05.js → mf-entry-bootstrap-0-524d60aa.js} +2 -2
- package/dist/assets/{pencil-DPWl5tLj.js → pencil-CcMQxamh.js} +1 -1
- package/dist/assets/play-DLMQ6Vbg.js +1 -0
- package/dist/assets/{player-overlays-CxHvyzBL.js → player-overlays-Dp8sC0O9.js} +1 -1
- package/dist/assets/plus-BgLQb6Wt.js +1 -0
- package/dist/assets/power-k7lYmVTU.js +1 -0
- package/dist/assets/{radio-BhphTUWO.js → radio-BQzOLx-i.js} +1 -1
- package/dist/assets/{refresh-cw-CuaHjcq3.js → refresh-cw-Y4QItX4o.js} +1 -1
- package/dist/assets/remoteEntry-BD_rj9II.js +1 -0
- package/dist/assets/rotate-ccw-CXRHsxOB.js +1 -0
- package/dist/assets/rotate-cw-Czrkx2xL.js +1 -0
- package/dist/assets/rule-device-filter-BucaBSBx.js +1 -0
- package/dist/assets/{send-DX8bQrru.js → send-C0z2ucNo.js} +1 -1
- package/dist/assets/{server-DD1xVy9e.js → server-v9OuAyra.js} +1 -1
- package/dist/assets/{shield-Cu3-d7ee.js → shield-C-98dFJL.js} +1 -1
- package/dist/assets/shield-alert-DPfckHEV.js +1 -0
- package/dist/assets/square-BYFMnk1w.js +1 -0
- package/dist/assets/{square-check-big-BozZrI7m.js → square-check-big-BU1ojXbi.js} +1 -1
- package/dist/assets/src-BGScj5qL.js +67 -0
- package/dist/assets/src-CRel5e6M.js +349 -0
- package/dist/assets/{undo-2-D33lbdQW.js → undo-2-CZ0eaA5I.js} +1 -1
- package/dist/assets/{use-scenes-feed-DqeDE69y.js → use-scenes-feed-BslHGf2y.js} +1 -1
- package/dist/assets/useEventInvalidation-CNtbe7Vf.js +1 -0
- package/dist/assets/{useNodeUrlSelection-Dumcs9MP.js → useNodeUrlSelection-C_HRBbD_.js} +1 -1
- package/dist/assets/user-round-CE_Qj9Tt.js +1 -0
- package/dist/assets/{video-C5L4OAcP.js → video-Cd8wmX94.js} +1 -1
- package/dist/assets/{virtual_mf-REMOTE_ENTRY_ID___mfe_internal__admin_ui_host__remoteEntry-_hash_-Bf6u6B3K.js → virtual_mf-REMOTE_ENTRY_ID___mfe_internal__admin_ui_host__remoteEntry-_hash_-DyHPvfpF.js} +2 -2
- package/dist/assets/{wifi-BSOzXDhI.js → wifi-7d3lUFsA.js} +1 -1
- package/dist/assets/{zap-D9dFxZiG.js → zap-BM8jYFt-.js} +1 -1
- package/dist/index.html +6 -6
- package/dist/server/addon.js +174 -77
- package/package.json +1 -1
- package/dist/assets/AddLocationWizard-DN0aFv_r.js +0 -1
- package/dist/assets/Addons-BHJcpdJ-.js +0 -1
- package/dist/assets/AiProfiles-Bih3GsbW.js +0 -3
- package/dist/assets/CapabilityBadges-CLTWAVNu.js +0 -1
- package/dist/assets/Cluster-rJJOcazu.js +0 -11
- package/dist/assets/Data-BZzuA9x6.js +0 -1
- package/dist/assets/DetectionIntelligence-D4C2W-48.js +0 -1
- package/dist/assets/DeviceDetail-UtKZwbux.js +0 -2
- package/dist/assets/Events-dVdiz1V-.js +0 -1
- package/dist/assets/FormBuilder-BP2OntiX.js +0 -1
- package/dist/assets/Identity-WGacdktR.js +0 -1
- package/dist/assets/IntegrationDetail-BP5Xam5L.js +0 -1
- package/dist/assets/Integrations-Dh9ZRz4E.js +0 -1
- package/dist/assets/MyAccess-DJbTo1Af.js +0 -2
- package/dist/assets/Network-cjqbvhNs.js +0 -1
- package/dist/assets/NodeAddonsSettingsPanel-BipJ2NAz.js +0 -1
- package/dist/assets/Notifications-Czo2o5b5.js +0 -1
- package/dist/assets/Pipeline-Bbmikduo.js +0 -1
- package/dist/assets/Plates-h_Z_xuvh.js +0 -1
- package/dist/assets/Recordings-CyeFU3i9.js +0 -1
- package/dist/assets/Settings-DT7nLsPy.js +0 -1
- package/dist/assets/bell-ring-C_bZ8IoR.js +0 -1
- package/dist/assets/circle-check-big-DuuIo-l7.js +0 -1
- package/dist/assets/clock-xyxm0Vrl.js +0 -1
- package/dist/assets/dist-D8HjVQmi.js +0 -349
- package/dist/assets/index-BGPx1Wue.css +0 -2
- package/dist/assets/index-BRCxCK68.js +0 -4
- package/dist/assets/play-BJyEu2-A.js +0 -1
- package/dist/assets/plus-y8WmfmHp.js +0 -1
- package/dist/assets/power-Ck186zUF.js +0 -1
- package/dist/assets/remoteEntry-ClB9u5zx.js +0 -1
- package/dist/assets/rotate-ccw-BJsfKt0-.js +0 -1
- package/dist/assets/rotate-cw-CiA7cZdt.js +0 -1
- package/dist/assets/square-CuFP0Uhg.js +0 -1
- package/dist/assets/src-BVvs1Rok.js +0 -349
- package/dist/assets/src-CoTJVD7e.js +0 -67
- package/dist/assets/useEventInvalidation-DsypM9SU.js +0 -1
package/dist/server/addon.js
CHANGED
|
@@ -8099,6 +8099,13 @@ var MediaRelocateModeSchema = _enum([
|
|
|
8099
8099
|
]);
|
|
8100
8100
|
var RelocateMediaInputSchema = object({
|
|
8101
8101
|
toLocationId: string(),
|
|
8102
|
+
/**
|
|
8103
|
+
* Restrict the pass to rows currently on this location. Omitted / `'*'` =
|
|
8104
|
+
* every row that is not already on `toLocationId` (the historical
|
|
8105
|
+
* behaviour). A named source is what a from→to migration needs: without it
|
|
8106
|
+
* "move events off disk 2" also emptied disk 1.
|
|
8107
|
+
*/
|
|
8108
|
+
fromLocationId: string().optional(),
|
|
8102
8109
|
throttleMbps: number().min(1).max(1e3).optional(),
|
|
8103
8110
|
/** Omitted = `move`, the pre-existing behaviour. */
|
|
8104
8111
|
mode: MediaRelocateModeSchema.optional()
|
|
@@ -8166,6 +8173,19 @@ var StorageMigrationDestinationsSchema = object({
|
|
|
8166
8173
|
galleryMedia: string().min(1).optional()
|
|
8167
8174
|
}).refine((value) => Object.keys(value).length > 0, { message: "select at least one storage class" });
|
|
8168
8175
|
/**
|
|
8176
|
+
* Optional named source per class. Omitted = the class's current default
|
|
8177
|
+
* (the historical behaviour). A named source that is NOT the default is a
|
|
8178
|
+
* drain of that disk: bytes move, the default stays, and the source is
|
|
8179
|
+
* disabled when the move finishes.
|
|
8180
|
+
*/
|
|
8181
|
+
var StorageMigrationSourcesSchema = object({
|
|
8182
|
+
recordings: string().min(1).optional(),
|
|
8183
|
+
recordingsLow: string().min(1).optional(),
|
|
8184
|
+
eventMedia: string().min(1).optional(),
|
|
8185
|
+
backups: string().min(1).optional(),
|
|
8186
|
+
galleryMedia: string().min(1).optional()
|
|
8187
|
+
}).optional();
|
|
8188
|
+
/**
|
|
8169
8189
|
* How a migration sequences the cutover against the byte move.
|
|
8170
8190
|
*
|
|
8171
8191
|
* - `blocking` — the historical order: pause, move every byte, repoint,
|
|
@@ -8187,6 +8207,8 @@ var StorageMigrationModeSchema = _enum(["blocking", "nonBlocking"]);
|
|
|
8187
8207
|
/** Shared input for planning and starting an orchestrated storage migration. */
|
|
8188
8208
|
var StorageMigrationInputSchema = object({
|
|
8189
8209
|
destinations: StorageMigrationDestinationsSchema,
|
|
8210
|
+
/** Omitted = each class's current default. */
|
|
8211
|
+
sources: StorageMigrationSourcesSchema,
|
|
8190
8212
|
throttleMbps: number().min(1).max(1e3).optional(),
|
|
8191
8213
|
/** Omitted = `blocking`, which stays the default. */
|
|
8192
8214
|
mode: StorageMigrationModeSchema.optional()
|
|
@@ -8266,6 +8288,13 @@ var StorageMigrationMoveSchema = object({
|
|
|
8266
8288
|
storageClass: StorageMigrationClassSchema,
|
|
8267
8289
|
fromLocationId: string(),
|
|
8268
8290
|
toLocationId: string(),
|
|
8291
|
+
/**
|
|
8292
|
+
* True when `from` was NOT the class default at plan time. The move still
|
|
8293
|
+
* copies bytes, but the default is left alone and the source is disabled
|
|
8294
|
+
* once the copy verifies. Absent on jobs planned before this field existed
|
|
8295
|
+
* — those jobs always repointed, which is `false`.
|
|
8296
|
+
*/
|
|
8297
|
+
freezeSource: boolean().optional(),
|
|
8269
8298
|
moverJobId: string().nullable(),
|
|
8270
8299
|
state: RelocateJobStateSchema.nullable(),
|
|
8271
8300
|
error: string().nullable(),
|
|
@@ -8279,6 +8308,7 @@ var StorageMigrationJobSchema = object({
|
|
|
8279
8308
|
* can tell a seconds-long cutover from a thirty-hour one. */
|
|
8280
8309
|
mode: StorageMigrationModeSchema,
|
|
8281
8310
|
destinations: StorageMigrationDestinationsSchema,
|
|
8311
|
+
sources: StorageMigrationSourcesSchema,
|
|
8282
8312
|
throttleMbps: number(),
|
|
8283
8313
|
moves: array(StorageMigrationMoveSchema),
|
|
8284
8314
|
pauseLeaseId: string().nullable(),
|
|
@@ -8304,6 +8334,7 @@ var StorageMigrationFindingSchema = object({
|
|
|
8304
8334
|
});
|
|
8305
8335
|
var StorageMigrationPlanSchema = object({
|
|
8306
8336
|
destinations: StorageMigrationDestinationsSchema,
|
|
8337
|
+
sources: StorageMigrationSourcesSchema,
|
|
8307
8338
|
/** The mode this plan was built for. A plan is only valid for its mode: the
|
|
8308
8339
|
* `eventMedia` seal gate and the single-cardinality refusal both depend on
|
|
8309
8340
|
* it. */
|
|
@@ -8311,7 +8342,8 @@ var StorageMigrationPlanSchema = object({
|
|
|
8311
8342
|
moves: array(object({
|
|
8312
8343
|
storageClass: StorageMigrationClassSchema,
|
|
8313
8344
|
fromLocationId: string(),
|
|
8314
|
-
toLocationId: string()
|
|
8345
|
+
toLocationId: string(),
|
|
8346
|
+
freezeSource: boolean().optional()
|
|
8315
8347
|
})),
|
|
8316
8348
|
findings: array(StorageMigrationFindingSchema)
|
|
8317
8349
|
});
|
|
@@ -8489,10 +8521,51 @@ var LedgerWalkReportSchema = object({
|
|
|
8489
8521
|
var RelocatableMediaCountSchema = object({ rows: number().int().nonnegative() }).nullable();
|
|
8490
8522
|
var RelocatableMediaCountInputSchema = object({
|
|
8491
8523
|
toLocationId: string().min(1),
|
|
8524
|
+
/** Restrict the count to one source; omitted / `'*'` = every non-target row. */
|
|
8525
|
+
fromLocationId: string().optional(),
|
|
8492
8526
|
/** Omitted = `move`. */
|
|
8493
8527
|
mode: MediaRelocateModeSchema.optional()
|
|
8494
8528
|
});
|
|
8495
8529
|
/**
|
|
8530
|
+
* Operator cleanup of leftover analytics rows, optional debug media, and
|
|
8531
|
+
* ghost ledger entries on frozen footage locations.
|
|
8532
|
+
*
|
|
8533
|
+
* A pass is tens of minutes on a standing backlog. The hub method RETURNS
|
|
8534
|
+
* `{ jobId }` immediately; progress is `cleanupStatus`. Awaiting the work
|
|
8535
|
+
* is how `addons.custom` hit the 60 s UDS deadline while reclaim continued
|
|
8536
|
+
* with no operator-visible status.
|
|
8537
|
+
*/
|
|
8538
|
+
var StorageCleanupPhaseSchema = _enum([
|
|
8539
|
+
"orphans",
|
|
8540
|
+
"debug-media",
|
|
8541
|
+
"ghost-ledger",
|
|
8542
|
+
"done",
|
|
8543
|
+
"failed",
|
|
8544
|
+
"cancelled"
|
|
8545
|
+
]);
|
|
8546
|
+
var StorageCleanupInputSchema = object({
|
|
8547
|
+
/** Also walk motion stills / track filmstrips. Off by default. */
|
|
8548
|
+
includeDebugMedia: boolean().optional() });
|
|
8549
|
+
var StorageCleanupJobSchema = object({
|
|
8550
|
+
jobId: string(),
|
|
8551
|
+
phase: StorageCleanupPhaseSchema,
|
|
8552
|
+
includeDebugMedia: boolean(),
|
|
8553
|
+
orphansReclaimed: number().int().nonnegative(),
|
|
8554
|
+
orphanBytesReclaimed: number().int().nonnegative(),
|
|
8555
|
+
debugMediaReclaimed: number().int().nonnegative(),
|
|
8556
|
+
debugMediaBytesReclaimed: number().int().nonnegative(),
|
|
8557
|
+
ghostsForgotten: number().int().nonnegative(),
|
|
8558
|
+
ghostBytesForgotten: number().int().nonnegative(),
|
|
8559
|
+
/** Short operator-facing line: current collection, pass, or location. */
|
|
8560
|
+
detail: string().nullable(),
|
|
8561
|
+
cancelRequested: boolean(),
|
|
8562
|
+
startedAt: number(),
|
|
8563
|
+
updatedAt: number(),
|
|
8564
|
+
finishedAt: number().nullable(),
|
|
8565
|
+
error: string().nullable()
|
|
8566
|
+
});
|
|
8567
|
+
var StorageCleanupStatusInputSchema = object({ jobId: string().optional() });
|
|
8568
|
+
/**
|
|
8496
8569
|
* `StorageLocationType` — an addon-declared id that identifies the *kind* of
|
|
8497
8570
|
* storage a location serves. Defined here (not in `capabilities/storage.cap.ts`)
|
|
8498
8571
|
* so the persisted record schema and the consumer-facing cap can both consume it
|
|
@@ -8520,11 +8593,10 @@ var StorageLocationTypeSchema = string().regex(/^[a-z][a-zA-Z0-9-]*$/);
|
|
|
8520
8593
|
* The default location for a type uses `id === <type>:default` by
|
|
8521
8594
|
* convention (the bare type ref like `'backups'` resolves to it).
|
|
8522
8595
|
*
|
|
8523
|
-
* `isSystem
|
|
8524
|
-
*
|
|
8525
|
-
*
|
|
8526
|
-
*
|
|
8527
|
-
* deleting it is rejected at the cap level.
|
|
8596
|
+
* `isSystem` is a legacy persisted flag. Seed still creates the initial
|
|
8597
|
+
* `<type>:default` locations; the flag is no longer a lock, a badge, or a
|
|
8598
|
+
* prune selector. New writes leave it false. Deletion is gated on uniqueness
|
|
8599
|
+
* / last-enabled, not on this bit.
|
|
8528
8600
|
*/
|
|
8529
8601
|
var StorageLocationSchema = object({
|
|
8530
8602
|
id: string().regex(/^[a-z][a-zA-Z0-9-]*:[a-zA-Z0-9-]+$/),
|
|
@@ -12786,6 +12858,12 @@ method(object({
|
|
|
12786
12858
|
}), _void(), {
|
|
12787
12859
|
kind: "mutation",
|
|
12788
12860
|
auth: "admin"
|
|
12861
|
+
}), method(object({
|
|
12862
|
+
from: string(),
|
|
12863
|
+
to: string()
|
|
12864
|
+
}), object({ moved: number() }), {
|
|
12865
|
+
kind: "mutation",
|
|
12866
|
+
auth: "admin"
|
|
12789
12867
|
}), method(object({
|
|
12790
12868
|
deviceId: number(),
|
|
12791
12869
|
disabled: boolean()
|
|
@@ -18716,46 +18794,6 @@ var RecentTracksPageSchema = object({
|
|
|
18716
18794
|
/** Cursor for the next page, or null when this page is the last. */
|
|
18717
18795
|
nextCursor: string().nullable()
|
|
18718
18796
|
});
|
|
18719
|
-
var LIST_GROUPS_DEFAULT_LIMIT = 40;
|
|
18720
|
-
var LIST_GROUPS_MAX_LIMIT = 100;
|
|
18721
|
-
var AnalyticsGroupRecordSchema = object({
|
|
18722
|
-
id: string(),
|
|
18723
|
-
deviceId: number().int(),
|
|
18724
|
-
openedAt: number().int(),
|
|
18725
|
-
closedAt: number().int(),
|
|
18726
|
-
timestamp: number().int(),
|
|
18727
|
-
memberCount: number().int(),
|
|
18728
|
-
memberTrackIds: array(string()).readonly(),
|
|
18729
|
-
className: string(),
|
|
18730
|
-
classes: array(string()).readonly(),
|
|
18731
|
-
/** Relative event-media path, or null when the group has no picture yet. */
|
|
18732
|
-
mediaUrl: string().nullable(),
|
|
18733
|
-
singleton: boolean()
|
|
18734
|
-
});
|
|
18735
|
-
var AnalyticsGroupMemberSchema = object({
|
|
18736
|
-
trackId: string(),
|
|
18737
|
-
deviceId: number().int(),
|
|
18738
|
-
className: string(),
|
|
18739
|
-
firstSeen: number().int(),
|
|
18740
|
-
lastSeen: number().int(),
|
|
18741
|
-
mediaUrl: string().nullable()
|
|
18742
|
-
});
|
|
18743
|
-
var AnalyticsGroupDetailSchema = AnalyticsGroupRecordSchema.extend({ members: array(AnalyticsGroupMemberSchema).readonly() });
|
|
18744
|
-
var ListGroupsQueryInput = object({
|
|
18745
|
-
/** Devices to merge. An empty array yields `{ groups: [], nextCursor: null }`. */
|
|
18746
|
-
deviceIds: array(number()),
|
|
18747
|
-
/** Window lower bound on `closedAt` (inclusive). */
|
|
18748
|
-
since: number().optional(),
|
|
18749
|
-
/** Window upper bound on `openedAt` (inclusive). */
|
|
18750
|
-
until: number().optional(),
|
|
18751
|
-
limit: number().int().min(1).max(LIST_GROUPS_MAX_LIMIT).default(LIST_GROUPS_DEFAULT_LIMIT),
|
|
18752
|
-
/** Opaque continuation cursor from a previous page's `nextCursor`. */
|
|
18753
|
-
cursor: string().optional()
|
|
18754
|
-
});
|
|
18755
|
-
var ListGroupsPageSchema = object({
|
|
18756
|
-
groups: array(AnalyticsGroupRecordSchema).readonly(),
|
|
18757
|
-
nextCursor: string().nullable()
|
|
18758
|
-
});
|
|
18759
18797
|
var KEY_EVENTS_DEFAULT_LIMIT = 50;
|
|
18760
18798
|
var KEY_EVENTS_MAX_LIMIT = 200;
|
|
18761
18799
|
var KeyEventQueryInput = object({
|
|
@@ -18859,9 +18897,7 @@ var TrackCascadeCountsSchema = object({
|
|
|
18859
18897
|
/** Unassigned plate reads removed (best-effort; plate leg deferred to plate-intelligence). */
|
|
18860
18898
|
plates: number().int(),
|
|
18861
18899
|
/** Per-track CLIP search vectors removed (best-effort). */
|
|
18862
|
-
embeddings: number().int()
|
|
18863
|
-
/** Group membership + group rows removed with their last member (best-effort). */
|
|
18864
|
-
groups: number().int()
|
|
18900
|
+
embeddings: number().int()
|
|
18865
18901
|
});
|
|
18866
18902
|
/** Disk-wins reconcile: media rows whose blobs are gone, then empty tracks. */
|
|
18867
18903
|
var DiskReconcileCountsSchema = object({
|
|
@@ -19110,10 +19146,7 @@ DeviceType.Camera, method(object({ deviceId: number() }), array(TrackSchema).rea
|
|
|
19110
19146
|
* stationary registry). Default false: the timeline lists passages,
|
|
19111
19147
|
* not parking records (operator decision, 2026-08-15). */
|
|
19112
19148
|
includeStationary: boolean().optional()
|
|
19113
|
-
}), array(TrackSchema).readonly()), method(RecentTracksQueryInput, RecentTracksPageSchema), method(
|
|
19114
|
-
deviceId: number(),
|
|
19115
|
-
groupId: string().min(1)
|
|
19116
|
-
}), AnalyticsGroupDetailSchema.nullable()), method(object({ deviceId: number() }), _void(), {
|
|
19149
|
+
}), array(TrackSchema).readonly()), method(RecentTracksQueryInput, RecentTracksPageSchema), method(object({ deviceId: number() }), _void(), {
|
|
19117
19150
|
kind: "mutation",
|
|
19118
19151
|
auth: "admin"
|
|
19119
19152
|
}), 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({
|
|
@@ -21189,7 +21222,13 @@ method(StorageMigrationInputSchema, StorageMigrationPlanSchema, { auth: "admin"
|
|
|
21189
21222
|
}), method(object({}), array(StorageMigrationMoverSchema).readonly(), { auth: "admin" }), method(object({}), array(StorageMigrationResidueSchema).readonly(), { auth: "admin" }), method(StorageMigrationDrainInputSchema, object({ jobId: string() }), {
|
|
21190
21223
|
kind: "mutation",
|
|
21191
21224
|
auth: "admin"
|
|
21192
|
-
})
|
|
21225
|
+
}), method(StorageCleanupInputSchema, object({ jobId: string() }), {
|
|
21226
|
+
kind: "mutation",
|
|
21227
|
+
auth: "admin"
|
|
21228
|
+
}), method(StorageCleanupStatusInputSchema, StorageCleanupJobSchema.nullable(), { auth: "admin" }), method(object({ jobId: string() }), object({ cancelled: boolean() }), {
|
|
21229
|
+
kind: "mutation",
|
|
21230
|
+
auth: "admin"
|
|
21231
|
+
}), method(object({}), array(StorageMigrationJobSchema).readonly(), { auth: "admin" });
|
|
21193
21232
|
var ProviderInfoSchema = discriminatedUnion("shouldSaveDiskSpace", [object({
|
|
21194
21233
|
providerId: string().min(1),
|
|
21195
21234
|
displayName: string().min(1),
|
|
@@ -26567,6 +26606,33 @@ var RecordingRebalanceInputSchema = object({
|
|
|
26567
26606
|
minMoveGb: number().min(0).optional()
|
|
26568
26607
|
});
|
|
26569
26608
|
/**
|
|
26609
|
+
* Operator-facing placement of one camera onto a recordings location.
|
|
26610
|
+
*
|
|
26611
|
+
* `pinLocationId` is the operator instruction: a location id, or `null` for
|
|
26612
|
+
* Auto (the planner may move this camera). `locationId` is where high/mid
|
|
26613
|
+
* currently write — the plan, which may disagree with the pin when Auto.
|
|
26614
|
+
*/
|
|
26615
|
+
var RecordingDevicePlacementSchema = object({
|
|
26616
|
+
deviceId: number().int(),
|
|
26617
|
+
profile: string(),
|
|
26618
|
+
locationId: string()
|
|
26619
|
+
});
|
|
26620
|
+
var RecordingDevicePinSchema = object({
|
|
26621
|
+
deviceId: number().int(),
|
|
26622
|
+
/** Recordings-class location this camera is pinned to. */
|
|
26623
|
+
locationId: string()
|
|
26624
|
+
});
|
|
26625
|
+
var RecordingPlacementViewSchema = object({
|
|
26626
|
+
assignments: array(RecordingDevicePlacementSchema),
|
|
26627
|
+
pins: array(RecordingDevicePinSchema),
|
|
26628
|
+
defaultLocations: record(string(), string())
|
|
26629
|
+
});
|
|
26630
|
+
var RecordingSetDevicePlacementInputSchema = object({
|
|
26631
|
+
deviceId: number().int(),
|
|
26632
|
+
/** `null` = Auto. Otherwise a `recordings:*` location id. */
|
|
26633
|
+
locationId: string().nullable()
|
|
26634
|
+
});
|
|
26635
|
+
/**
|
|
26570
26636
|
* Result of locating footage at a wall-clock instant for one device/profile.
|
|
26571
26637
|
* `segment` carries the covering segment's window; `gap` reports the forward
|
|
26572
26638
|
* nearest covered edge (`null` past the end of footage / when none exists)
|
|
@@ -26792,6 +26858,12 @@ method(object({
|
|
|
26792
26858
|
}), method(RecordingRebalanceInputSchema, RecordingRebalancePlanSchema, {
|
|
26793
26859
|
kind: "mutation",
|
|
26794
26860
|
auth: "admin"
|
|
26861
|
+
}), method(object({}), RecordingPlacementViewSchema, {
|
|
26862
|
+
kind: "query",
|
|
26863
|
+
auth: "admin"
|
|
26864
|
+
}), method(RecordingSetDevicePlacementInputSchema, object({ ok: literal(true) }), {
|
|
26865
|
+
kind: "mutation",
|
|
26866
|
+
auth: "admin"
|
|
26795
26867
|
});
|
|
26796
26868
|
/**
|
|
26797
26869
|
* `recording-export` cap — render a footage time range into a single downloadable
|
|
@@ -30162,6 +30234,12 @@ Object.freeze({
|
|
|
30162
30234
|
addonId: null,
|
|
30163
30235
|
access: "delete"
|
|
30164
30236
|
},
|
|
30237
|
+
"deviceManager.renameLocation": {
|
|
30238
|
+
capName: "device-manager",
|
|
30239
|
+
capScope: "system",
|
|
30240
|
+
addonId: null,
|
|
30241
|
+
access: "create"
|
|
30242
|
+
},
|
|
30165
30243
|
"deviceManager.runDeviceAction": {
|
|
30166
30244
|
capName: "device-manager",
|
|
30167
30245
|
capScope: "system",
|
|
@@ -31854,12 +31932,6 @@ Object.freeze({
|
|
|
31854
31932
|
addonId: null,
|
|
31855
31933
|
access: "view"
|
|
31856
31934
|
},
|
|
31857
|
-
"pipelineAnalytics.getGroup": {
|
|
31858
|
-
capName: "pipeline-analytics",
|
|
31859
|
-
capScope: "device",
|
|
31860
|
-
addonId: null,
|
|
31861
|
-
access: "view"
|
|
31862
|
-
},
|
|
31863
31935
|
"pipelineAnalytics.getKeyEvents": {
|
|
31864
31936
|
capName: "pipeline-analytics",
|
|
31865
31937
|
capScope: "device",
|
|
@@ -31962,12 +32034,6 @@ Object.freeze({
|
|
|
31962
32034
|
addonId: null,
|
|
31963
32035
|
access: "view"
|
|
31964
32036
|
},
|
|
31965
|
-
"pipelineAnalytics.listGroups": {
|
|
31966
|
-
capName: "pipeline-analytics",
|
|
31967
|
-
capScope: "device",
|
|
31968
|
-
addonId: null,
|
|
31969
|
-
access: "view"
|
|
31970
|
-
},
|
|
31971
32037
|
"pipelineAnalytics.listOpsLog": {
|
|
31972
32038
|
capName: "pipeline-analytics",
|
|
31973
32039
|
capScope: "device",
|
|
@@ -32982,6 +33048,12 @@ Object.freeze({
|
|
|
32982
33048
|
addonId: null,
|
|
32983
33049
|
access: "view"
|
|
32984
33050
|
},
|
|
33051
|
+
"recording.getPlacement": {
|
|
33052
|
+
capName: "recording",
|
|
33053
|
+
capScope: "system",
|
|
33054
|
+
addonId: null,
|
|
33055
|
+
access: "view"
|
|
33056
|
+
},
|
|
32985
33057
|
"recording.getPlaybackManifest": {
|
|
32986
33058
|
capName: "recording",
|
|
32987
33059
|
capScope: "system",
|
|
@@ -33108,6 +33180,12 @@ Object.freeze({
|
|
|
33108
33180
|
addonId: null,
|
|
33109
33181
|
access: "create"
|
|
33110
33182
|
},
|
|
33183
|
+
"recording.setDevicePlacement": {
|
|
33184
|
+
capName: "recording",
|
|
33185
|
+
capScope: "system",
|
|
33186
|
+
addonId: null,
|
|
33187
|
+
access: "create"
|
|
33188
|
+
},
|
|
33111
33189
|
"recording.startStorageMigrationMove": {
|
|
33112
33190
|
capName: "recording",
|
|
33113
33191
|
capScope: "system",
|
|
@@ -33552,12 +33630,36 @@ Object.freeze({
|
|
|
33552
33630
|
addonId: null,
|
|
33553
33631
|
access: "create"
|
|
33554
33632
|
},
|
|
33633
|
+
"storageMigration.cleanupCancel": {
|
|
33634
|
+
capName: "storage-migration",
|
|
33635
|
+
capScope: "system",
|
|
33636
|
+
addonId: null,
|
|
33637
|
+
access: "create"
|
|
33638
|
+
},
|
|
33639
|
+
"storageMigration.cleanupStart": {
|
|
33640
|
+
capName: "storage-migration",
|
|
33641
|
+
capScope: "system",
|
|
33642
|
+
addonId: null,
|
|
33643
|
+
access: "create"
|
|
33644
|
+
},
|
|
33645
|
+
"storageMigration.cleanupStatus": {
|
|
33646
|
+
capName: "storage-migration",
|
|
33647
|
+
capScope: "system",
|
|
33648
|
+
addonId: null,
|
|
33649
|
+
access: "view"
|
|
33650
|
+
},
|
|
33555
33651
|
"storageMigration.drain": {
|
|
33556
33652
|
capName: "storage-migration",
|
|
33557
33653
|
capScope: "system",
|
|
33558
33654
|
addonId: null,
|
|
33559
33655
|
access: "create"
|
|
33560
33656
|
},
|
|
33657
|
+
"storageMigration.history": {
|
|
33658
|
+
capName: "storage-migration",
|
|
33659
|
+
capScope: "system",
|
|
33660
|
+
addonId: null,
|
|
33661
|
+
access: "view"
|
|
33662
|
+
},
|
|
33561
33663
|
"storageMigration.movers": {
|
|
33562
33664
|
capName: "storage-migration",
|
|
33563
33665
|
capScope: "system",
|
|
@@ -35554,11 +35656,6 @@ Object.freeze({
|
|
|
35554
35656
|
form: "single",
|
|
35555
35657
|
optional: true
|
|
35556
35658
|
}],
|
|
35557
|
-
"pipelineAnalytics.getGroup": [{
|
|
35558
|
-
name: "deviceId",
|
|
35559
|
-
form: "single",
|
|
35560
|
-
optional: false
|
|
35561
|
-
}],
|
|
35562
35659
|
"pipelineAnalytics.getKeyEvents": [{
|
|
35563
35660
|
name: "deviceId",
|
|
35564
35661
|
form: "single",
|
|
@@ -35624,11 +35721,6 @@ Object.freeze({
|
|
|
35624
35721
|
form: "single",
|
|
35625
35722
|
optional: false
|
|
35626
35723
|
}],
|
|
35627
|
-
"pipelineAnalytics.listGroups": [{
|
|
35628
|
-
name: "deviceIds",
|
|
35629
|
-
form: "array",
|
|
35630
|
-
optional: false
|
|
35631
|
-
}],
|
|
35632
35724
|
"pipelineAnalytics.listOpsLog": [{
|
|
35633
35725
|
name: "deviceId",
|
|
35634
35726
|
form: "single",
|
|
@@ -36044,6 +36136,11 @@ Object.freeze({
|
|
|
36044
36136
|
form: "single",
|
|
36045
36137
|
optional: false
|
|
36046
36138
|
}],
|
|
36139
|
+
"recording.setDevicePlacement": [{
|
|
36140
|
+
name: "deviceId",
|
|
36141
|
+
form: "single",
|
|
36142
|
+
optional: false
|
|
36143
|
+
}],
|
|
36047
36144
|
"recording.startStorageMigrationMove": [{
|
|
36048
36145
|
name: "deviceId",
|
|
36049
36146
|
form: "single",
|
|
@@ -36906,7 +37003,7 @@ var AdminUIAddon = class extends BaseAddon {
|
|
|
36906
37003
|
capability: adminUiCapability,
|
|
36907
37004
|
provider: {
|
|
36908
37005
|
getStaticDir: async () => ({ staticDir: resolveAdminUiDistDir() }),
|
|
36909
|
-
getVersion: async () => ({ version: "1.2.
|
|
37006
|
+
getVersion: async () => ({ version: "1.2.128" })
|
|
36910
37007
|
}
|
|
36911
37008
|
}];
|
|
36912
37009
|
}
|
package/package.json
CHANGED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
import{I as e,Q as t,S as n,W as r,a as i,o as a,q as o,x as s,z as c}from"./_virtual_mf___mfe_internal__admin_ui_host__loadShare___mf_0_tanstack_mf_1_react_mf_2_query__loadShare__.js-DhP-Lgiq.js";import{Q as l}from"./player-overlays-CxHvyzBL.js";import{Ko as u,es as d,g as f}from"./src-CoTJVD7e.js";import{t as p}from"./FormBuilder-BP2OntiX.js";import{t as m}from"./pencil-DPWl5tLj.js";import{t as h}from"./plus-y8WmfmHp.js";import{t as g}from"./power-Ck186zUF.js";import{C as _,I as v,K as y,o as b,r as x}from"./index-BRCxCK68.js";var S=y(`hard-drive`,[[`line`,{x1:`22`,x2:`2`,y1:`12`,y2:`12`,key:`1y58io`}],[`path`,{d:`M5.45 5.11 2 12v6a2 2 0 0 0 2 2h16a2 2 0 0 0 2-2v-6l-3.45-6.89A2 2 0 0 0 16.76 4H7.24a2 2 0 0 0-1.79 1.11z`,key:`oot6mr`}],[`line`,{x1:`6`,x2:`6.01`,y1:`16`,y2:`16`,key:`sgf278`}],[`line`,{x1:`10`,x2:`10.01`,y1:`16`,y2:`16`,key:`1l4acy`}]]);t();function C(e){return e.enabled!==!1}function w(e,t){let n={id:e.id,type:e.type,displayName:t.displayName??e.displayName,providerId:e.providerId,config:e.config,isDefault:t.isDefault??e.isDefault,isSystem:e.isSystem},r=e.nodeId===void 0?n:{...n,nodeId:e.nodeId},i=t.enabled??e.enabled;return i===void 0?r:{...r,enabled:i}}function T(e){return`${(e/1024**3).toFixed(e>=100*1024**3?0:1)} GB`}function E({location:e}){let t=e.capacity;return t==null?null:n(`span`,{className:`text-[10px] text-foreground-subtle tabular-nums`,children:[T(t.availableBytes),` free of `,T(t.totalBytes)]})}function D(e){let t=e.basePath;if(typeof t==`string`&&t.length>0)return t;let n=Object.keys(e);return n.length===0?``:n.join(`, `)}function O({location:e,cardinality:t,onEdit:r,onDelete:i,onToggleEnabled:a}){let o=D(e.config),c=C(e);return n(`div`,{className:`flex flex-wrap items-center gap-x-3 gap-y-2 px-3 py-2 border-t border-border first:border-t-0 hover:bg-primary/5`,children:[n(`div`,{className:`flex flex-wrap items-center gap-2 min-w-0 flex-1 basis-64`,children:[s(`span`,{className:`text-[10px] uppercase tracking-wide text-foreground-subtle bg-background border border-border rounded px-1.5 py-0.5 font-mono`,children:e.providerId}),!c&&s(`span`,{className:`text-[10px] uppercase tracking-wide text-warning bg-warning/10 border border-warning/30 rounded px-1.5 py-0.5`,title:`Disabled — nothing new is written here. Existing data stays readable and is still pruned by age.`,children:`disabled`}),e.isSystem&&s(`span`,{className:`text-[10px] uppercase tracking-wide text-foreground-subtle bg-background border border-border rounded px-1.5 py-0.5`,title:`System-managed location — cannot be deleted; edit config to relocate`,children:`system`}),e.config.readOnly===!0&&s(`span`,{className:`text-[10px] uppercase tracking-wide text-warning bg-warning/10 border border-warning/30 rounded px-1.5 py-0.5`,title:`Drain mode — reads and age retention continue; nothing new is written here and disk-pressure eviction skips it`,children:`read-only`}),n(`div`,{className:`min-w-0`,children:[s(`div`,{className:`text-xs font-medium text-foreground truncate`,children:e.displayName}),n(`div`,{className:`flex flex-wrap items-center gap-x-2`,children:[o&&s(`span`,{className:`text-[10px] text-foreground-subtle truncate font-mono`,children:o}),s(E,{location:e})]})]})]}),n(`div`,{className:`flex flex-wrap items-center gap-1 shrink-0`,children:[n(`button`,{type:`button`,role:`switch`,"aria-label":`Writes enabled`,"aria-checked":c,onClick:()=>a(e,!c),title:c?`Enabled — balancing consumers may write new data here. Click to stop new writes.`:`Disabled — no new data is written here. Existing data stays readable. Click to enable.`,className:`inline-flex items-center gap-1 rounded px-2 py-1 text-[10px] font-medium border disabled:cursor-not-allowed ${c?`border-success/30 text-success hover:bg-success/10`:`border-warning/40 text-warning hover:bg-warning/10`}`,children:[s(g,{className:`h-3 w-3`}),c?`Enabled`:`Disabled`]}),n(`button`,{onClick:()=>r(e),className:`inline-flex items-center gap-1 rounded px-2 py-1 text-[10px] font-medium text-foreground-subtle border border-border hover:text-foreground hover:bg-primary/10`,children:[s(m,{className:`h-3 w-3`}),`Edit`]}),!e.isSystem&&t!==`single`&&s(`button`,{onClick:()=>i(e),className:`inline-flex items-center gap-1 rounded px-2 py-1 text-[10px] font-medium text-danger hover:bg-danger/10`,title:`Delete location`,children:s(b,{className:`h-3 w-3`})})]})]})}function k({type:e,displayName:t,description:i,cardinality:a,locations:o,onAdd:c,onEdit:l,onDelete:u,onToggleEnabled:d}){let f=r(()=>{let e=[...o];return e.sort((e,t)=>{let n=e.enabled!==!1;return n===(t.enabled!==!1)?e.displayName.localeCompare(t.displayName):n?-1:1}),e},[o]);return n(`div`,{className:`rounded-lg border border-border bg-surface`,children:[n(`div`,{className:`flex items-start justify-between border-b border-border px-3 py-2`,children:[n(`div`,{className:`space-y-0.5`,children:[n(`div`,{className:`flex items-center gap-2`,children:[s(`span`,{className:`text-sm font-semibold text-foreground capitalize`,children:t}),s(`span`,{className:`text-[10px] uppercase tracking-wide text-foreground-subtle bg-background border border-border rounded px-1.5 py-0.5 font-mono`,children:e})]}),i&&s(`p`,{className:`text-[11px] text-foreground-subtle`,children:i}),a===`single`&&s(`p`,{className:`text-[10px] text-foreground-subtle italic`,children:`Single — one location per type. Edit the existing entry; it can't be split.`})]}),a===`multi`&&n(`button`,{onClick:()=>c(e),className:`inline-flex items-center gap-1 rounded bg-primary px-2 py-1 text-[11px] font-medium text-primary-foreground hover:bg-primary/90`,children:[s(h,{className:`h-3 w-3`}),`Add`]})]}),f.length===0?s(`div`,{className:`px-3 py-4 text-center text-[11px] text-foreground-subtle italic`,children:a===`multi`?`No location registered. Click "Add" to register one.`:`No location registered yet — should be auto-seeded at next boot.`}):s(`div`,{children:f.map(e=>s(O,{location:e,cardinality:a,onEdit:l,onDelete:u,onToggleEnabled:d},e.id))})]})}var A=new Set([`proc`,`sys`,`dev`,`run`,`boot`,`lost+found`,`snap`,`bin`,`sbin`,`lib`,`lib32`,`lib64`,`libx32`,`usr`,`etc`,`var`,`opt`,`tmp`,`srv`,`root`,`System`,`Library`,`Applications`,`cores`,`private`]),j=[`recordings`,`data`,`mnt`,`media`,`Volumes`];function M(e){let t=j.findIndex(t=>t===`recordings`?e.startsWith(t):e===t);return t===-1?j.length:t}function N(e){return e.filter(e=>!e.name.startsWith(`.`)&&!A.has(e.name)).toSorted((e,t)=>{let n=M(e.name)-M(t.name);return n===0?e.name.localeCompare(t.name):n}).map(e=>e.path)}t();function P({nodeId:t,value:r,onChange:i}){let a=l().trpcClient,[u,d]=o([]),[f,p]=o(r),[m,h]=o(null),[g,_]=o(null),[v,y]=o(``),b=e(async(e,n)=>{_(null);try{let r=await a.filesystemBrowse.browse.query({nodeId:t,path:e});h(r),p(r.path),n&&i(r.path)}catch(e){_(e instanceof Error?e.message:`browse failed`)}},[a,t,i]);c(()=>{p(r),(async()=>{let e=await a.filesystemBrowse.browse.query({nodeId:t,path:`/`}).then(e=>e).catch(()=>null);if(e){d(N(e.entries)),await b(r.startsWith(`/`)?r:`/`,!1);return}try{let e=await a.filesystemBrowse.listAllowedRoots.query({nodeId:t});d(e),await b(r&&e.some(e=>r.startsWith(e))?r:e[0]??``,!1)}catch(e){d([]),h(null),_(e instanceof Error&&/not available on node/i.test(e.message)?`This node can't be browsed remotely. Enter the path manually.`:e instanceof Error?e.message:`browse unavailable`)}})()},[t]);let x=async()=>{if(!(!v.trim()||!m)){_(null);try{let e=`${m.path.replace(/\/+$/,``)}/${v.trim()}`;await a.filesystemBrowse.createDir.mutate({nodeId:t,path:e}),y(``),await b(m.path,!0)}catch(e){_(e instanceof Error?e.message:`create failed`)}}},S=e=>`${(e/1e9).toFixed(1)} GB`;return n(`div`,{className:`space-y-2 rounded border border-border p-2`,children:[s(`div`,{className:`flex flex-wrap gap-1`,children:u.map(e=>s(`button`,{onClick:()=>void b(e,!0),className:`rounded border border-border px-2 py-0.5 text-[10px] font-mono hover:border-primary/40`,children:e},e))}),s(`input`,{value:f,onChange:e=>{p(e.target.value),i(e.target.value)},placeholder:`/absolute/path`,className:`w-full rounded border border-border bg-background px-2 py-1 text-[11px] font-mono`}),m&&n(`div`,{className:`text-[10px] text-foreground-subtle`,children:[S(m.freeBytes),` free / `,S(m.totalBytes)]}),s(`div`,{className:`max-h-40 space-y-0.5 overflow-y-auto`,children:m?.entries.map(e=>n(`button`,{onClick:()=>void b(e.path,!0),className:`block w-full truncate rounded px-2 py-1 text-left text-xs hover:bg-primary/5`,children:[`📁 `,e.name]},e.path))}),n(`div`,{className:`flex gap-1`,children:[s(`input`,{value:v,onChange:e=>y(e.target.value),placeholder:`new folder`,className:`flex-1 rounded border border-border bg-background px-2 py-1 text-xs`}),s(`button`,{onClick:()=>void x(),className:`rounded border border-border px-2 py-1 text-xs hover:border-primary/40`,children:`Create`})]}),g&&s(`div`,{className:`text-[10px] text-red-400`,children:g})]})}t();function F({location:e,onClose:t,onSaved:c}){let m=a(),h=l().trpcClient,[g,v]=o({...e.config}),[y,b]=o(e.displayName),[S,C]=o(null),[w,T]=o(!1),E=u(),D=r(()=>{let t=E.data;return Array.isArray(t)?t.find(t=>t.providerId===e.providerId)??null:null},[E.data,e.providerId]),O=d({onSuccess:()=>{m.invalidateQueries({queryKey:[[`storage`,`listLocations`]]}),c()}}),k=D?.shouldSaveDiskSpace===!0,A=D?.nodeLocal===!0,[j,M]=o(typeof e.nodeId==`string`?e.nodeId:`hub`),N=typeof g.basePath==`string`?g.basePath:``,F=e=>v(t=>({...t,basePath:e})),I=g.readOnly===!0,L=i({queryKey:[`storage`,`listLocations`,`ro-guard`],queryFn:()=>h.storage.listLocations.query({})}),R=(L.data??[]).filter(t=>t.type===e.type&&t.id!==e.id&&t.config.readOnly!==!0).length,z=!I&&L.data!==void 0&&R===0,B=e=>v(t=>{let n={...t};return delete n.readOnly,e?{...n,readOnly:!0}:n}),V=typeof g.maxUsedGb==`number`?g.maxUsedGb:``,H=e=>{let t=e.trim(),n=t===``?void 0:Number(t);v(e=>{let t={...e};return n===void 0||!Number.isFinite(n)||n<=0?delete t.maxUsedGb:t.maxUsedGb=n,t})},U=typeof g.minFreePercent==`number`?g.minFreePercent:``,W=e=>{let t=e.trim(),n=t===``?void 0:Number(t);v(e=>{let t={...e};return n===void 0||!Number.isFinite(n)?delete t.minFreePercent:t.minFreePercent=Math.min(100,Math.max(0,n)),t})},G=async()=>{T(!0),C(null);try{C(await(e=>h.storage.testConfig.query(e))({providerId:e.providerId,locationId:e.id,config:g}))}catch(e){C({ok:!1,error:e instanceof Error?e.message:String(e)})}finally{T(!1)}};return s(`div`,{className:`fixed inset-0 z-50 flex items-center justify-center bg-background/80 backdrop-blur-sm`,onClick:t,children:n(`div`,{className:`w-full max-w-md rounded-xl border border-border bg-surface shadow-2xl`,onClick:e=>e.stopPropagation(),children:[n(`div`,{className:`flex items-start justify-between border-b border-border px-4 py-3`,children:[n(`div`,{className:`space-y-0.5`,children:[n(`h2`,{className:`text-sm font-semibold text-foreground`,children:[`Edit `,e.displayName]}),n(`p`,{className:`text-xs text-foreground-subtle`,children:[s(`span`,{className:`font-mono`,children:e.id}),` ·`,` `,D?.displayName??e.providerId]})]}),s(`button`,{onClick:t,className:`text-foreground-subtle hover:text-foreground`,children:s(x,{className:`h-4 w-4`})})]}),n(`div`,{className:`p-4 space-y-3 max-h-[60vh] overflow-y-auto`,children:[n(`div`,{className:`space-y-1`,children:[s(`label`,{className:`text-[10px] uppercase tracking-wide text-foreground-subtle`,children:`Display name`}),s(`input`,{type:`text`,value:y,onChange:e=>b(e.target.value),className:`w-full rounded border border-border bg-background px-2 py-1.5 text-xs text-foreground focus:outline-none focus:ring-1 focus:ring-primary`})]}),D&&s(p,{schema:D.configSchema,values:g,onChange:v}),n(`div`,{className:`space-y-1`,children:[n(`label`,{className:`flex items-center gap-2 text-xs ${z?`text-foreground-subtle cursor-not-allowed`:`text-foreground cursor-pointer`}`,children:[s(`input`,{type:`checkbox`,checked:I,disabled:z,onChange:e=>B(e.target.checked),className:`accent-primary`}),`Read-only (drain mode)`]}),s(`p`,{className:`text-[10px] text-foreground-subtle`,children:z?`Blocked: this is the last writable location of its type — new footage would have nowhere to go.`:`Reads and age-based retention continue; nothing new is written here and disk-pressure eviction skips it. Use it to slowly decommission a disk.`})]}),A&&n(`div`,{className:`space-y-2`,children:[s(`label`,{className:`text-[10px] uppercase tracking-wide text-foreground-subtle`,children:`Node`}),s(f,{selectedNodeId:j,onSelect:M,alwaysShow:!0}),s(`label`,{className:`text-[10px] uppercase tracking-wide text-foreground-subtle`,children:`Path`}),s(P,{nodeId:j,value:N,onChange:F})]}),k&&n(`div`,{className:`space-y-1`,children:[s(`label`,{className:`text-[10px] uppercase tracking-wide text-foreground-subtle`,children:`Min free disk %`}),s(`input`,{type:`number`,min:0,max:100,value:U,placeholder:D?.minFreePercent==null?``:String(D.minFreePercent),onChange:e=>W(e.target.value),className:`w-full rounded border border-border bg-background px-2 py-1.5 text-xs text-foreground focus:outline-none focus:ring-1 focus:ring-primary`}),n(`p`,{className:`text-[10px] text-foreground-subtle`,children:[`When free space on this volume drops below this %, the oldest data stored here is evicted to reclaim space.`,D?.minFreePercent==null?` Empty = use the default.`:` Empty = use the default (${D.minFreePercent}%).`]}),s(`label`,{className:`text-[10px] uppercase tracking-wide text-foreground-subtle`,children:`Max used (GB)`}),s(`input`,{type:`number`,min:1,value:V,placeholder:`unlimited`,onChange:e=>H(e.target.value),className:`w-full rounded border border-border bg-background px-2 py-1.5 text-xs text-foreground focus:outline-none focus:ring-1 focus:ring-primary`}),s(`p`,{className:`text-[10px] text-foreground-subtle`,children:`Hard cap on the TOTAL bytes evictable data (recordings) may occupy on this location, independent of disk free space — oldest footage is evicted past it. Empty = unlimited.`})]}),!D&&!E.isLoading&&n(`div`,{className:`rounded border border-amber-500/30 bg-amber-500/10 px-3 py-2 text-[11px] text-amber-700 dark:text-amber-300`,children:[`Provider `,s(`code`,{className:`font-mono`,children:e.providerId}),` is no longer registered. Field schema unavailable; raw config is preserved on save.`]}),S&&s(`div`,{className:`rounded border px-3 py-2 text-[11px] ${S.ok?`border-success/30 bg-success/5 text-success`:`border-danger/30 bg-danger/5 text-danger`}`,children:S.ok?`Connection OK.`:`Test failed: ${S.error??`unknown error`}`}),O.isError&&s(`div`,{className:`rounded border border-danger/30 bg-danger/5 text-danger px-3 py-2 text-[11px]`,children:O.error instanceof Error?O.error.message:String(O.error)})]}),n(`div`,{className:`flex items-center justify-between gap-2 border-t border-border px-4 py-3`,children:[s(`button`,{onClick:t,className:`rounded px-3 py-1.5 text-xs text-foreground-subtle border border-border hover:text-foreground`,children:`Cancel`}),n(`div`,{className:`flex items-center gap-2`,children:[s(`button`,{onClick:()=>{G()},disabled:w||!D,className:`rounded border border-border px-3 py-1.5 text-xs text-foreground hover:bg-primary/10 disabled:opacity-50`,children:w?`Testing…`:`Test connection`}),n(`button`,{onClick:()=>{O.mutate({id:e.id,type:e.type,providerId:e.providerId,isDefault:e.isDefault,displayName:y.trim(),config:g,nodeId:A?j:void 0})},disabled:O.isPending||y.trim().length===0,className:`inline-flex items-center gap-1.5 rounded bg-primary px-3 py-1.5 text-xs font-medium text-primary-foreground hover:bg-primary/90 disabled:opacity-50`,children:[O.isPending?s(_,{className:`h-3.5 w-3.5 animate-spin`}):null,O.isPending?`Saving…`:`Save`]})]})]})]})})}function I(e){let t=e.trim().toLowerCase();return t.length===0?``:t.replace(/[^a-z0-9]+/g,`-`).replace(/^-+|-+$/g,``)}function L(e,t){let n=I(t);return`${e}:${n.length>0?n:`default`}`}t();function R({initialType:e,onClose:t,onCreated:i}){let c=a(),m=l().trpcClient,[h,g]=o(`picker`),[y,b]=o(e),[S,C]=o(null),[w,T]=o({}),[E,D]=o(``),[O,k]=o(null),[A,j]=o(!1),[M,N]=o(`hub`),[F,I]=o(null),[R,z]=o(!1),B=e=>T(t=>({...t,basePath:e})),V=typeof w.basePath==`string`?w.basePath:``,H=u(),U=r(()=>{let e=H.data;return Array.isArray(e)?e:[]},[H.data]),W=H.isLoading,G=d({onSuccess:()=>{c.invalidateQueries({queryKey:[[`storage`,`listLocations`]]}),i()}}),K=r(()=>O!==null&&O.length>0?O:L(y,E),[y,E,O]),q=async()=>{if(S){z(!0),I(null);try{I(await(e=>m.storage.testConfig.query(e))({providerId:S.providerId,config:w}))}catch(e){I({ok:!1,error:e instanceof Error?e.message:String(e)})}finally{z(!1)}}};return s(`div`,{className:`fixed inset-0 z-50 flex items-center justify-center bg-background/80 backdrop-blur-sm`,onClick:t,children:n(`div`,{className:`w-full max-w-md rounded-xl border border-border bg-surface shadow-2xl`,onClick:e=>e.stopPropagation(),children:[n(`div`,{className:`flex items-start justify-between border-b border-border px-4 py-3`,children:[n(`div`,{className:`space-y-0.5`,children:[s(`h2`,{className:`text-sm font-semibold text-foreground`,children:{picker:`Add Location — Pick provider`,config:`Add Location — ${S?.displayName??``}`,naming:`Add Location — Name`}[h]}),n(`p`,{className:`text-xs text-foreground-subtle`,children:[`Type: `,s(`span`,{className:`font-mono`,children:y})]})]}),s(`button`,{onClick:t,className:`text-foreground-subtle hover:text-foreground`,children:s(x,{className:`h-4 w-4`})})]}),h===`picker`&&n(`div`,{className:`p-4 space-y-2`,children:[W&&s(`div`,{className:`text-xs text-foreground-subtle animate-pulse`,children:`Loading providers…`}),!W&&U.length===0&&n(`div`,{className:`rounded border border-border bg-background px-3 py-4 text-center text-xs text-foreground-subtle`,children:[`No storage-provider supports type "`,y,`". Install a compatible addon (e.g.`,` `,s(`code`,{className:`font-mono`,children:`remote-storage`}),`) to enable it.`]}),U.map(e=>n(`button`,{onClick:()=>{C(e),g(`config`)},className:`flex w-full items-center gap-3 rounded-lg border border-border bg-background p-3 text-left hover:border-primary/40 hover:bg-primary/5 transition-colors`,children:[n(`div`,{className:`flex-1 min-w-0`,children:[s(`p`,{className:`text-xs font-semibold text-foreground`,children:e.displayName}),s(`p`,{className:`text-[10px] text-foreground-subtle font-mono mt-0.5 truncate`,children:e.providerId})]}),s(v,{className:`h-4 w-4 text-foreground-subtle flex-shrink-0`})]},e.providerId))]}),h===`config`&&S&&n(`div`,{className:`p-4 space-y-3 max-h-[60vh] overflow-y-auto`,children:[s(p,{schema:S.configSchema,values:w,onChange:T}),S.nodeLocal&&n(`div`,{className:`space-y-2`,children:[s(`label`,{className:`text-[10px] uppercase tracking-wide text-foreground-subtle`,children:`Node`}),s(f,{selectedNodeId:M,onSelect:N,alwaysShow:!0}),s(`label`,{className:`text-[10px] uppercase tracking-wide text-foreground-subtle`,children:`Path`}),s(P,{nodeId:M,value:V,onChange:B})]}),F&&s(`div`,{className:`rounded border px-3 py-2 text-[11px] ${F.ok?`border-success/30 bg-success/5 text-success`:`border-danger/30 bg-danger/5 text-danger`}`,children:F.ok?`Connection OK.`:`Test failed: ${F.error??`unknown error`}`}),n(`div`,{className:`flex items-center justify-between pt-1`,children:[s(`button`,{onClick:()=>g(`picker`),className:`rounded px-3 py-1.5 text-xs text-foreground-subtle border border-border hover:text-foreground`,children:`Back`}),n(`div`,{className:`flex items-center gap-2`,children:[s(`button`,{onClick:()=>{q()},disabled:R,className:`rounded border border-border px-3 py-1.5 text-xs text-foreground hover:bg-primary/10 disabled:opacity-50`,children:R?`Testing…`:`Test connection`}),s(`button`,{onClick:()=>g(`naming`),className:`rounded bg-primary px-3 py-1.5 text-xs font-medium text-primary-foreground hover:bg-primary/90`,children:`Next`})]})]})]}),h===`naming`&&S&&n(`div`,{className:`p-4 space-y-3`,children:[n(`div`,{className:`space-y-1`,children:[s(`label`,{className:`text-[10px] uppercase tracking-wide text-foreground-subtle`,children:`Display name`}),s(`input`,{type:`text`,value:E,onChange:e=>D(e.target.value),placeholder:`${y} on ${S.displayName}`,className:`w-full rounded border border-border bg-background px-2 py-1.5 text-xs text-foreground focus:outline-none focus:ring-1 focus:ring-primary`})]}),n(`div`,{className:`space-y-1`,children:[n(`label`,{className:`text-[10px] uppercase tracking-wide text-foreground-subtle`,children:[`Id`,` `,s(`span`,{className:`lowercase tracking-normal text-foreground-subtle`,children:`— auto-derived; override if needed`})]}),s(`input`,{type:`text`,value:K,onChange:e=>k(e.target.value),placeholder:L(y,E),className:`w-full rounded border border-border bg-background px-2 py-1.5 text-xs text-foreground font-mono focus:outline-none focus:ring-1 focus:ring-primary`}),n(`p`,{className:`text-[10px] text-foreground-subtle`,children:[`Format: `,s(`code`,{className:`font-mono`,children:`<type>:<slug>`}),`. Lowercase letters, digits, and hyphens only.`]})]}),n(`label`,{className:`flex items-start gap-2 rounded border border-border bg-background px-3 py-2 cursor-pointer hover:bg-primary/5`,children:[s(`input`,{type:`checkbox`,checked:A,onChange:e=>j(e.target.checked),className:`accent-primary mt-0.5`}),n(`div`,{className:`space-y-0.5`,children:[s(`div`,{className:`text-xs font-medium text-foreground`,children:`Enable immediately`}),s(`div`,{className:`text-[10px] text-foreground-subtle`,children:`A disabled location receives no writes until enabled — reads and age-based retention still work, nothing new lands here. Leave this off to register the disk now and start using it later.`})]})]}),G.isError&&s(`div`,{className:`rounded border border-danger/30 bg-danger/5 text-danger px-3 py-2 text-[11px]`,children:G.error instanceof Error?G.error.message:String(G.error)}),n(`div`,{className:`flex items-center justify-between pt-1`,children:[s(`button`,{onClick:()=>g(`config`),className:`rounded px-3 py-1.5 text-xs text-foreground-subtle border border-border hover:text-foreground`,children:`Back`}),n(`div`,{className:`flex items-center gap-2`,children:[s(`button`,{onClick:()=>{b(e),C(null),T({}),D(``),k(null),j(!1),I(null),g(`picker`)},className:`rounded px-3 py-1.5 text-xs text-foreground-subtle border border-border hover:text-foreground`,children:`Reset`}),n(`button`,{onClick:()=>{S&&G.mutate({id:K,type:y,displayName:E.trim(),providerId:S.providerId,config:w,isDefault:!1,enabled:A,nodeId:S.nodeLocal?M:void 0})},disabled:G.isPending||E.trim().length===0,className:`inline-flex items-center gap-1.5 rounded bg-primary px-3 py-1.5 text-xs font-medium text-primary-foreground hover:bg-primary/90 disabled:opacity-50`,children:[G.isPending?s(_,{className:`h-3.5 w-3.5 animate-spin`}):null,G.isPending?`Saving…`:`Save`]})]})]})]})]})})}export{S as a,w as i,F as n,k as r,R as t};
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
import{I as e,K as t,Q as n,R as r,S as i,W as a,b as o,o as s,q as c,x as l,z as u}from"./_virtual_mf___mfe_internal__admin_ui_host__loadShare___mf_0_tanstack_mf_1_react_mf_2_query__loadShare__.js-DhP-Lgiq.js";import{Q as d}from"./player-overlays-CxHvyzBL.js";import{C as f,Cn as p,Dn as m,En as h,Hn as g,In as ee,J as _,Ln as v,Mn as y,Nn as b,On as x,Pn as S,Rn as C,Tn as w,Un as te,Vn as ne,Vs as T,Ws as re,ea as E,g as ie,jn as D,kn as O,q as ae,un as oe,wn as se,xn as ce,zn as le}from"./src-CoTJVD7e.js";import{Bt as k}from"./src-BVvs1Rok.js";import{t as A}from"./clock-xyxm0Vrl.js";import{t as j}from"./download-F5TwZ1QT.js";import{t as ue}from"./plus-y8WmfmHp.js";import{t as M}from"./refresh-cw-CuaHjcq3.js";import{C as N,J as de,K as P,P as fe,R as F,X as pe,_ as I,f as me,m as he,o as L,p as R,r as ge,z}from"./index-BRCxCK68.js";import{t as B}from"./AdminPage-CCD07UMs.js";import{t as V}from"./NodeAddonsSettingsPanel-BipJ2NAz.js";import{r as H,t as U}from"./useNodeUrlSelection-Dumcs9MP.js";var _e=P(`chevron-up`,[[`path`,{d:`m18 15-6-6-6 6`,key:`153udz`}]]),ve=P(`octagon-alert`,[[`path`,{d:`M12 16h.01`,key:`1drbdi`}],[`path`,{d:`M12 8v4`,key:`1got3b`}],[`path`,{d:`M15.312 2a2 2 0 0 1 1.414.586l4.688 4.688A2 2 0 0 1 22 8.688v6.624a2 2 0 0 1-.586 1.414l-4.688 4.688a2 2 0 0 1-1.414.586H8.688a2 2 0 0 1-1.414-.586l-4.688-4.688A2 2 0 0 1 2 15.312V8.688a2 2 0 0 1 .586-1.414l4.688-4.688A2 2 0 0 1 8.688 2z`,key:`1fd625`}]]),ye=P(`package`,[[`path`,{d:`M11 21.73a2 2 0 0 0 2 0l7-4A2 2 0 0 0 21 16V8a2 2 0 0 0-1-1.73l-7-4a2 2 0 0 0-2 0l-7 4A2 2 0 0 0 3 8v8a2 2 0 0 0 1 1.73z`,key:`1a0edw`}],[`path`,{d:`M12 22V12`,key:`d0xqtd`}],[`polyline`,{points:`3.29 7 12 12 20.71 7`,key:`ousv84`}],[`path`,{d:`m7.5 4.27 9 5.15`,key:`1c824w`}]]),be=P(`skip-forward`,[[`polygon`,{points:`5 4 15 12 5 20 5 4`,key:`16p6eg`}],[`line`,{x1:`19`,x2:`19`,y1:`5`,y2:`19`,key:`futhcm`}]]),W=P(`upload`,[[`path`,{d:`M12 3v12`,key:`1x0j5s`}],[`path`,{d:`m17 8-5-5-5 5`,key:`7q97r8`}],[`path`,{d:`M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4`,key:`ih7n3h`}]]);n();var G=new Set([`completed`,`failed`,`partially-failed`,`cancelled`]),K=new Set([`done`,`failed`,`skipped`]);function q(e){return!K.has(e.phase)&&!G.has(e.jobState)}function xe(e,t){let n=new Map,r=[...e].sort((e,t)=>e.createdAtMs-t.createdAtMs);for(let e of r){let r=G.has(e.state);for(let i of e.tasks)r&&i.finishedAtMs!==null&&t-i.finishedAtMs>6e4||n.set(i.packageName,{jobId:e.jobId,packageName:i.packageName,phase:i.phase,fromVersion:i.fromVersion,toVersion:i.toVersion,error:i.error,jobState:e.state,finishedAtMs:i.finishedAtMs})}return n}function J(){let{data:e}=D({activeOnly:!0},{refetchOnWindowFocus:!1,refetchInterval:e=>(e.state.data?.length??0)>0?3e3:!1}),{map:t}=re(k.AddonsJobProgress,e=>e.job.jobId);return a(()=>{let n=new Map;for(let t of e??[])n.set(t.jobId,t);for(let[e,r]of t)n.set(e,r.job);return xe([...n.values()],Date.now())},[e,t])}var Y={queued:{icon:A,cls:`bg-muted text-foreground-subtle`,label:`queued`},fetching:{icon:N,cls:`bg-primary/10 text-primary`,label:`fetching`,spin:!0},staged:{icon:N,cls:`bg-primary/10 text-primary`,label:`staged`,spin:!0},validating:{icon:N,cls:`bg-primary/10 text-primary`,label:`validating`,spin:!0},applying:{icon:N,cls:`bg-primary/10 text-primary`,label:`applying`,spin:!0},restarting:{icon:N,cls:`bg-amber-500/10 text-amber-600 dark:text-amber-400`,label:`restarting`,spin:!0},applied:{icon:N,cls:`bg-primary/10 text-primary`,label:`finalizing`,spin:!0},done:{icon:z,cls:`bg-success/10 text-success`,label:`updated`},failed:{icon:ve,cls:`bg-danger/10 text-danger`,label:`failed`},skipped:{icon:be,cls:`bg-muted text-foreground-subtle`,label:`skipped`}};function Se({progress:e}){let t=Y[e.phase],n=t.icon,r=e.error??`${e.packageName}: ${e.fromVersion??`?`} → ${e.toVersion}`;return i(`span`,{"data-testid":`addon-job-progress`,className:`inline-flex items-center gap-1 px-1.5 py-0.5 text-[10px] rounded shrink-0 ${t.cls}`,title:r,children:[l(n,{className:`w-2.5 h-2.5 ${t.spin?`animate-spin`:``}`}),t.label,i(`span`,{className:`font-mono`,children:[`→ `,e.toVersion]})]})}function Ce({packageName:e,currentVersion:t,installSource:n,onInstall:r,onClose:a,onSelect:s,selectedVersion:c}){let u=n===`upload`||n===`local`,{data:d,isLoading:f}=m({name:e});return i(`div`,{className:`fixed z-50 w-72 rounded-lg border border-border bg-surface shadow-xl overflow-hidden`,style:{top:`auto`,bottom:`auto`},ref:e=>{if(!e)return;let t=e.parentElement?.getBoundingClientRect();if(!t)return;let n=window.innerHeight-t.bottom,r=t.top;n<280&&r>n?(e.style.bottom=`${window.innerHeight-t.top+4}px`,e.style.top=`auto`):(e.style.top=`${t.bottom+4}px`,e.style.bottom=`auto`),e.style.right=`${window.innerWidth-t.right}px`},onClick:e=>e.stopPropagation(),children:[i(`div`,{className:`flex items-center justify-between px-3 py-2 border-b border-border`,children:[l(`span`,{className:`text-[10px] uppercase tracking-wide text-foreground-subtle font-medium`,children:`Versions`}),l(`button`,{type:`button`,onClick:a,className:`text-foreground-subtle hover:text-foreground`,children:l(ge,{className:`h-3 w-3`})})]}),u&&i(`div`,{className:`flex items-start gap-2 px-3 py-2 border-b border-border bg-cyan-500/10 text-[10px]`,children:[l(W,{className:`h-3 w-3 mt-0.5 text-cyan-500 shrink-0`}),i(`div`,{className:`text-cyan-700 dark:text-cyan-200`,children:[i(`span`,{className:`font-semibold`,children:[n===`upload`?`Uploaded copy`:`Local copy`,` in place.`]}),` `,`Re-install `,l(`span`,{className:`font-mono`,children:t}),` from npm to track upstream releases again.`]})]}),f&&i(`div`,{className:`flex items-center justify-center gap-2 py-6 text-[10px] text-foreground-subtle`,children:[l(N,{className:`h-3.5 w-3.5 animate-spin`}),`Loading versions...`]}),d&&l(`div`,{className:`max-h-64 overflow-auto divide-y divide-border`,children:d.map(e=>{let n=e.version===t,a=s!==void 0&&e.version===c,d=/-(alpha|beta|rc|dev|canary|next)/i.test(e.version),f=i(o,{children:[l(`span`,{className:`font-mono flex-1 text-left ${n?`text-primary font-semibold`:d?`text-amber-400`:`text-foreground`}`,children:e.version}),n&&l(`span`,{className:`text-[9px] rounded-full px-1.5 py-0.5 font-medium bg-primary/10 text-primary`,children:`current`}),e.distTags.map(e=>l(`span`,{className:`text-[9px] rounded-full px-1.5 py-0.5 font-medium ${e===`latest`?`bg-emerald-500/15 text-emerald-400`:e===`beta`?`bg-amber-500/15 text-amber-400`:`bg-gray-500/15 text-gray-400`}`,children:e},e)),e.deprecated&&l(`span`,{className:`text-[9px] text-red-400 line-through`,children:`deprecated`}),l(`span`,{className:`text-[9px] text-foreground-subtle shrink-0`,children:new Date(e.publishedAt).toLocaleDateString()})]});return s?i(`button`,{type:`button`,"aria-label":`Select ${e.version}`,onClick:()=>s(e.version),className:`w-full flex items-center gap-2 px-3 py-2 text-[11px] ${a?`bg-primary/5`:`hover:bg-surface-hover`} transition-colors`,children:[f,a?l(z,{className:`h-3 w-3 text-primary shrink-0`}):l(`span`,{className:`w-3 shrink-0`})]},e.version):i(`div`,{className:`flex items-center gap-2 px-3 py-2 text-[11px] ${n?`bg-primary/5`:`hover:bg-surface-hover`} transition-colors`,children:[f,n&&!u?l(z,{className:`h-3 w-3 text-primary shrink-0`}):l(`button`,{type:`button`,onClick:()=>r(e.version),className:`shrink-0 rounded p-0.5 hover:bg-primary/20 text-foreground-subtle hover:text-primary transition-colors`,title:n?`Re-install ${e.version} from npm`:`Install ${e.version}`,children:l(j,{className:`h-3 w-3`})})]},e.version)})}),d&&d.length===0&&l(`div`,{className:`py-4 text-center text-[10px] text-foreground-subtle`,children:`No versions found`})]})}var X={queued:{icon:A,bg:`bg-muted text-foreground-subtle`,label:`queued`},updating:{icon:N,bg:`bg-primary/10 text-primary`,label:`updating`,spin:!0},"done-pending-restart":{icon:M,bg:`bg-amber-500/10 text-amber-700`,label:`pending restart`},done:{icon:z,bg:`bg-success/10 text-success`,label:`done`},failed:{icon:ve,bg:`bg-danger/10 text-danger`,label:`failed`}};function Z({item:e}){let t=X[e.status],n=t.icon;return i(`span`,{className:`inline-flex items-center gap-1 px-1.5 py-0.5 text-[10px] rounded ${t.bg}`,title:e.error,children:[l(n,{className:`w-2.5 h-2.5 ${t.spin?`animate-spin`:``}`}),t.label]})}n();var Q=`device-export`;function we(e){return e.capabilities.some(e=>(typeof e==`string`?e:e.name)===Q)}function Te({isBundle:e,installSource:t,addonId:n,iconPath:r,color:a}){let[o,s]=c(!1),u=a?{backgroundColor:`${a.startsWith(`#`)?a:`#${a}`}26`}:void 0,d=e?`bg-indigo-500/20 text-indigo-700 dark:text-indigo-300`:`bg-purple-500/20 text-purple-700 dark:text-purple-300`,f=n&&r?`/api/addon-assets/${n}/${r}`:null,p=!!f&&!o;return i(`div`,{className:`relative flex-shrink-0`,children:[l(`div`,{className:`h-9 w-9 rounded-lg flex items-center justify-center ${u?``:d}`,style:u,children:p?l(`img`,{src:f,alt:n,className:`h-5 w-5`,onError:()=>s(!0)}):l(e?ye:I,{className:`h-4 w-4`})}),t===`local`&&l(`span`,{className:`absolute -top-1.5 -left-1.5 text-[7px] font-bold leading-none bg-orange-500 text-white px-1 py-0.5 rounded -rotate-12 shadow-sm`,children:`DEV`}),t===`npm`&&l(`span`,{className:`absolute -top-1 -left-1 w-4 h-4 rounded bg-[#cb3837] flex items-center justify-center -rotate-12 shadow-sm`,children:l(`svg`,{viewBox:`0 0 780 250`,className:`w-[11px] h-[11px]`,children:l(`path`,{fill:`#fff`,d:`M240 250h100V50h100v200h340V0H0v250z`})})}),t===`upload`&&l(`span`,{className:`absolute -top-1.5 -left-1.5 flex items-center justify-center h-4 w-4 rounded bg-cyan-500 -rotate-12 shadow-sm`,children:l(W,{className:`h-2.5 w-2.5 text-white`})})]})}function Ee({version:e,availableUpdate:t,selectedVersion:n,isUpdating:r,installSource:a,disabled:o,onUpdate:s,onOpenPicker:c,children:u}){if(r)return i(`span`,{className:`inline-flex items-center gap-1 rounded-md px-2 py-1 text-[10px] font-medium border border-blue-500/30 bg-blue-500/10 text-blue-400 shrink-0`,children:[l(N,{className:`h-3 w-3 animate-spin`}),`Updating…`]});if(t){let r=n??t;return i(`div`,{className:`relative inline-flex items-center gap-1 shrink-0`,children:[s&&i(`button`,{type:`button`,onClick:e=>{e.stopPropagation(),s()},disabled:o,className:`inline-flex items-center gap-1 rounded-md px-2 py-1 text-[10px] font-semibold border border-blue-500/30 bg-blue-500/10 text-blue-400 hover:bg-blue-500/20 disabled:opacity-50 disabled:cursor-not-allowed transition-colors`,title:`Update to ${r}`,children:[l(j,{className:`h-3 w-3`}),`Update`]}),i(`button`,{type:`button`,onClick:e=>{e.stopPropagation(),c()},disabled:o,"aria-label":`Select version to install`,title:`Installed ${e} — update available. Selected ${r}; tap to choose another version.`,className:`inline-flex items-center gap-1 rounded-md px-2 py-1 text-[10px] font-bold font-mono border border-amber-500/40 bg-amber-500/15 text-amber-500 hover:bg-amber-500/25 animate-pulse disabled:opacity-50 disabled:cursor-not-allowed transition-colors`,children:[l(`span`,{className:`font-normal opacity-70`,children:e}),l(`span`,{className:`font-normal opacity-70`,children:`→`}),r,l(F,{className:`h-3 w-3`})]}),u]})}return i(`div`,{className:`relative inline-flex items-center gap-1 shrink-0`,children:[i(`button`,{type:`button`,onClick:e=>{e.stopPropagation(),c()},disabled:o,className:[`inline-flex items-center gap-1 rounded-md px-2 py-1 text-[10px] font-bold font-mono border transition-colors disabled:opacity-50 disabled:cursor-not-allowed`,a===`local`?`border-orange-500/30 bg-orange-500/10 text-orange-400 hover:bg-orange-500/20`:`border-emerald-500/30 bg-emerald-500/10 text-emerald-400 hover:bg-emerald-500/20`].join(` `),title:`Version ${e} — tap to view all versions`,children:[e,l(F,{className:`h-3 w-3 opacity-50`})]}),u]})}function De({addonId:e}){let t=s(),{data:n=`inherit`}=se({addonId:e}),r=C({onSuccess:()=>{t.invalidateQueries({queryKey:[[`addons`,`getAddonAutoUpdate`]]})}});return l(`div`,{className:`flex rounded-lg border border-border overflow-hidden text-[10px] font-medium`,children:[`inherit`,`off`,`latest`,`beta`].map(t=>l(`button`,{type:`button`,onClick:n=>{n.stopPropagation(),r.mutate({addonId:e,channel:t})},disabled:r.isPending,className:`px-2.5 py-1 transition-colors capitalize ${n===t?t===`inherit`?`bg-gray-700/50 text-gray-700 dark:text-gray-300`:t===`off`?`bg-gray-700 text-gray-700 dark:text-gray-300`:t===`latest`?`bg-blue-500/20 text-blue-400`:`bg-amber-500/20 text-amber-400`:`bg-transparent text-foreground-subtle hover:bg-surface-hover`} ${t===`inherit`?``:`border-l border-border`}`,children:t},t))})}function Oe({addon:e,agents:t=[],clusterStatus:n,hideVersion:r,availableUpdate:a,onUpdate:p,isUpdating:m,jobProgress:h,bundle:v,bulkItem:y,disabledByBulk:b,isSystem:C}){let[w,te]=c(!1),[ne,T]=c(!1),[re,E]=c(!1),[ie,D]=c(null);u(()=>{D(null)},[a]);let O=ie??a,[se,ce]=c(!1),[le,k]=c(!1),[A,j]=c(`logs`),N=s(),P=d(),fe=de(),pe=oe(),{manifest:I}=e,R=e.installedOn??[],z=!v&&!I.protected&&I.removable!==!1,B=!!v,H=v?.displayName??I.name,U=v?.packageName??I.packageName,be=v?.version??I.packageVersion??I.version,W=v?.installSource??e.installSource,G=v?v.bundle?.description??v.addons[0]?.manifest.description:I.description,K=g({onSuccess:()=>{N.invalidateQueries({queryKey:[[`addons`]]}),N.invalidateQueries({queryKey:[[`addonPages`]]}),N.invalidateQueries({queryKey:[[`capabilities`]]})}}),q=S({onSuccess:()=>{N.invalidateQueries({queryKey:[[`addons`]]})}}),xe=x({onSuccess:()=>{N.invalidateQueries({queryKey:[[`addons`]]}),N.invalidateQueries({queryKey:[[`addonPages`]]}),N.invalidateQueries({queryKey:[[`capabilities`]]}),N.invalidateQueries({queryKey:[[`integrations`]]})}}),J=ee({onSuccess:()=>{N.invalidateQueries({queryKey:[[`addons`]]}),N.invalidateQueries({queryKey:[[`alerts`]]})}}),Y=e.health,X=Y?.phase===`failed`&&!Y.inGracePeriod,Q=X&&Y?.nextRetryAt&&!Y.retrying;return i(`div`,{className:`rounded-lg border bg-surface overflow-hidden ${X?`border-red-500/50`:`border-border`}`,children:[X&&Y&&i(`div`,{className:`bg-danger/10 border-b border-danger/30 px-4 py-2.5 flex items-start gap-2.5`,children:[l(ve,{className:`h-4 w-4 text-danger shrink-0 mt-0.5`}),i(`div`,{className:`flex-1 min-w-0`,children:[i(`div`,{className:`text-xs font-semibold text-danger`,children:[`Failed to load (attempt #`,Y.retryCount,`)`]}),l(`div`,{className:`text-[11px] text-foreground mt-0.5 break-words font-mono`,children:Y.lastError?.message??`Unknown error`}),Q&&Y.nextRetryAt&&i(`div`,{className:`text-[10px] text-foreground-subtle mt-1`,children:[`Auto-retry at `,new Date(Y.nextRetryAt).toLocaleTimeString()]})]}),i(`button`,{type:`button`,disabled:J.isPending||Y.retrying,onClick:e=>{e.stopPropagation(),J.mutate({packageName:U})},className:`inline-flex items-center gap-1.5 rounded-md px-2.5 py-1 text-[11px] font-semibold border border-red-400/40 bg-red-400/10 text-red-700 dark:text-red-300 hover:bg-red-400/20 disabled:opacity-50 disabled:cursor-not-allowed transition-colors shrink-0`,title:`Reset retry counter and force immediate reload`,children:[l(M,{className:`h-3 w-3 ${J.isPending||Y.retrying?`animate-spin`:``}`}),`Retry now`]})]}),i(`div`,{className:`flex items-start gap-3 px-4 py-3`,children:[l(Te,{isBundle:B||!!I.components&&I.components.length>1,installSource:W,addonId:B?v.addons[0]?.manifest.id:I.id,iconPath:B?v.bundle?.icon??v.addons[0]?.manifest.icon:I.icon,color:B?v.addons[0]?.manifest.color:I.color}),i(`div`,{className:`flex-1 min-w-0`,children:[i(`div`,{className:`flex items-start justify-between gap-2`,children:[l(`span`,{className:`text-sm font-semibold text-foreground truncate min-w-0`,children:H}),!r&&l(Ee,{version:be,availableUpdate:a,...O===void 0?{}:{selectedVersion:O},isUpdating:m,installSource:W,disabled:b,...p&&O!==void 0?{onUpdate:()=>p(O)}:{},onOpenPicker:()=>E(e=>!e),children:re&&l(Ce,{packageName:U,currentVersion:be,...W?{installSource:W}:{},...a!==void 0&&O!==void 0?{selectedVersion:O,onSelect:e=>{D(e),E(!1)}}:{},onInstall:e=>{E(!1),xe.mutate({packageName:U,version:e})},onClose:()=>E(!1)})})]}),i(`div`,{className:`flex flex-wrap items-center gap-x-1.5 gap-y-1 mt-0.5`,children:[U!==H&&l(`span`,{className:`text-[10px] text-foreground-subtle font-mono truncate max-w-full`,children:U}),B&&i(`span`,{className:`text-[10px] rounded-full bg-primary/10 text-primary px-2 py-0.5 font-medium shrink-0 inline-flex items-center gap-1`,children:[l(ye,{className:`h-3 w-3`}),v.addons.length]}),C&&i(`span`,{className:`text-[10px] rounded-full bg-amber-500/15 text-amber-700 dark:text-amber-300 px-2 py-0.5 font-medium shrink-0 inline-flex items-center gap-1`,title:`System package — updating restarts the hub`,children:[l(M,{className:`h-3 w-3`}),`System`]}),y!=null&&l(Z,{item:y}),h!=null&&l(Se,{progress:h})]}),G&&l(`p`,{className:`text-[10px] text-foreground-subtle mt-1 line-clamp-1`,children:G}),!B&&e.process&&i(`div`,{className:`flex flex-wrap items-center gap-1.5 mt-1`,children:[l(`span`,{className:`text-[9px] rounded-full px-1.5 py-0.5 font-medium ${e.process.mode===`forked`?`bg-blue-500/15 text-blue-400`:`bg-gray-500/15 text-gray-400`}`,children:e.process.mode===`forked`?`forked`:`in-process`}),e.process.pid!=null&&i(`span`,{className:`text-[9px] font-mono text-foreground-subtle`,children:[`PID `,e.process.pid]}),l(`span`,{className:`text-[9px] rounded-full px-1.5 py-0.5 font-medium ${e.process.state===`running`?`bg-emerald-500/15 text-emerald-400`:e.process.state===`crashed`||e.process.state===`failed`?`bg-red-500/15 text-red-400`:`bg-gray-500/15 text-gray-400`}`,children:e.process.state})]})]})]}),!B&&i(`div`,{className:`flex items-center gap-1 px-4 py-1.5 border-t border-border/50 bg-surface-hover/20`,children:[i(`button`,{type:`button`,onClick:e=>{e.stopPropagation(),q.mutate({addonId:I.id})},disabled:q.isPending||b,className:`inline-flex items-center gap-1 rounded-md px-2 py-1 text-[10px] font-medium border border-border text-foreground-subtle hover:text-blue-400 hover:border-blue-500/30 hover:bg-blue-500/10 disabled:opacity-50 transition-colors`,children:[l(M,{className:`h-3 w-3 ${q.isPending?`animate-spin`:``}`}),`Restart`]}),i(`button`,{type:`button`,onClick:e=>{e.stopPropagation(),ce(e=>!e)},className:`inline-flex items-center gap-1 rounded-md px-2 py-1 text-[10px] font-medium border transition-colors ${se?`border-primary/30 bg-primary/10 text-primary`:`border-border text-foreground-subtle hover:text-foreground hover:border-primary/30 hover:bg-primary/10`}`,children:[l(he,{className:`h-3 w-3`}),`Logs`]}),!B&&i(`button`,{type:`button`,onClick:e=>{e.stopPropagation(),k(!0)},className:`inline-flex items-center gap-1 rounded-md px-2 py-1 text-[10px] font-medium border transition-colors ${le?`border-primary/30 bg-primary/10 text-primary`:`border-border text-foreground-subtle hover:text-foreground hover:border-primary/30 hover:bg-primary/10`}`,children:[l(me,{className:`h-3 w-3`}),`Settings`]}),l(`div`,{className:`flex-1`}),z&&i(`button`,{type:`button`,onClick:async e=>{e.stopPropagation(),await pe({title:`Uninstall ${I.name}?`,message:`This will remove the addon package and all its data. This action cannot be undone.`,confirmLabel:`Uninstall`,variant:`danger`})&&K.mutate({packageName:I.packageName})},disabled:K.isPending||b,className:`inline-flex items-center gap-1 rounded-md px-2 py-1 text-[10px] font-medium border border-border text-foreground-subtle hover:text-red-400 hover:border-red-500/30 hover:bg-red-500/10 disabled:opacity-50 transition-colors`,children:[l(L,{className:`h-3 w-3`}),K.isPending?`Removing...`:`Uninstall`]})]}),n&&n.nodes.length>1&&!B&&i(`div`,{className:`border-t border-border px-4 py-2 bg-muted/10`,children:[l(`div`,{className:`text-[10px] font-medium text-foreground-subtle mb-1.5`,children:`Cluster Deployment`}),l(`div`,{className:`space-y-1`,children:n.nodes.map(e=>i(`div`,{className:`flex items-center gap-2 text-[10px]`,children:[l(`div`,{className:`h-1.5 w-1.5 rounded-full shrink-0 ${e.status===`offline`?`bg-muted-foreground/30`:e.synced?`bg-success`:`bg-amber-500`}`}),l(`span`,{className:`font-medium text-foreground min-w-[60px]`,children:e.name}),l(`span`,{className:`font-mono text-foreground-subtle`,children:e.version}),!e.synced&&e.status!==`offline`&&l(`span`,{className:`text-[9px] px-1 py-0.5 rounded bg-amber-500/10 text-amber-400 border border-amber-500/20`,children:`outdated`}),e.status===`offline`&&l(`span`,{className:`text-[9px] px-1 py-0.5 rounded bg-muted text-muted-foreground`,children:`offline`}),e.synced&&e.status!==`offline`&&l(`span`,{className:`text-[9px] text-success`,children:`synced`})]},e.nodeId))})]}),se&&!B&&i(`div`,{className:`border-t border-border`,children:[i(`div`,{className:`flex items-center px-4 py-1 bg-surface-hover/20 border-b border-border/50`,children:[i(`div`,{className:`flex rounded border border-border overflow-hidden text-[9px]`,children:[l(`button`,{type:`button`,onClick:()=>j(`logs`),className:`px-2 py-0.5 transition-colors ${A===`logs`?`bg-primary/10 text-primary`:`text-foreground-subtle hover:bg-surface-hover`}`,children:`Logs`}),l(`button`,{type:`button`,onClick:()=>j(`events`),className:`px-2 py-0.5 border-l border-border transition-colors ${A===`events`?`bg-primary/10 text-primary`:`text-foreground-subtle hover:bg-surface-hover`}`,children:`Events`})]}),l(`div`,{className:`flex-1`}),l(`button`,{type:`button`,onClick:e=>{e.stopPropagation(),ce(!1)},className:`text-foreground-subtle hover:text-foreground`,children:l(ge,{className:`h-3.5 w-3.5`})})]}),A===`logs`&&l(_,{addonId:I.id,maxHeight:`max-h-64`,showFilters:!1}),A===`events`&&l(ae,{addonId:I.id,category:`addon.*`,maxHeight:`max-h-64`})]}),B&&i(o,{children:[l(`button`,{type:`button`,onClick:()=>te(e=>!e),className:`w-full flex items-center justify-center border-t border-border py-1 hover:bg-surface-hover/50 transition-colors`,children:l(w?_e:F,{className:`h-3.5 w-3.5 text-foreground-subtle`})}),w&&l(`div`,{className:`border-t border-border px-3 py-2 space-y-2`,children:v.addons.map(e=>l(Oe,{addon:e,agents:t,hideVersion:!0},e.manifest.id))})]}),le&&!B&&l(`div`,{className:`fixed inset-0 z-50 flex items-center justify-center bg-black/60 backdrop-blur-sm p-4`,onClick:()=>k(!1),children:i(`div`,{className:`w-full max-w-lg max-h-[80vh] rounded-xl border border-border bg-surface shadow-2xl flex flex-col overflow-hidden`,onClick:e=>e.stopPropagation(),children:[i(`div`,{className:`flex items-center justify-between px-5 py-3 border-b border-border flex-shrink-0`,children:[i(`div`,{className:`flex items-center gap-2`,children:[l(me,{className:`h-4 w-4 text-primary`}),i(`h2`,{className:`text-sm font-semibold text-foreground`,children:[H,` Settings`]})]}),l(`button`,{onClick:()=>k(!1),className:`text-foreground-subtle hover:text-foreground transition-colors p-1 rounded`,children:l(ge,{className:`h-4 w-4`})})]}),i(`div`,{className:`flex-1 overflow-y-auto px-5 py-4 space-y-4`,children:[l(`div`,{className:`text-[10px] text-foreground-subtle mb-2`,children:`Cluster-wide settings — one value for every node. Per-node settings live under Cluster → the node → Settings.`}),l(V,{nodeId:null,addonIds:[I.id],level:`global`,fieldScope:`cluster`,emptyMessage:`This addon exposes no cluster-wide settings. Anything it can configure is per-node — open it from Cluster → the node → Settings.`}),we(I)&&i(`div`,{children:[l(`div`,{className:`text-[10px] font-medium text-foreground-subtle uppercase tracking-wide mb-2`,children:`Device export`}),l(f,{addonId:I.id,trpc:P.trpcClient,onOpenDevice:e=>fe(`/devices/${e}`)})]}),W===`npm`&&i(`div`,{children:[l(`div`,{className:`text-[10px] font-medium text-foreground-subtle uppercase tracking-wide mb-2`,children:`Auto-Update`}),l(De,{addonId:I.id})]}),I.components&&I.components.length>0&&i(`div`,{children:[i(`div`,{className:`text-[10px] font-medium text-foreground-subtle uppercase tracking-wide mb-2`,children:[`Components (`,I.components.length,`)`]}),l(`div`,{className:`flex flex-wrap gap-1`,children:I.components.map(e=>l(`span`,{className:`text-[10px] rounded bg-background border border-border px-1.5 py-0.5 text-foreground-subtle font-mono`,children:e},e))})]}),t.length>=2&&i(`div`,{children:[l(`div`,{className:`text-[10px] font-medium text-foreground-subtle uppercase tracking-wide mb-2`,children:`Installed on`}),i(`div`,{className:`flex items-center gap-1.5 flex-wrap`,children:[R.length===0&&l(`span`,{className:`text-[10px] text-foreground-subtle`,children:`Hub (local)`}),R.map(e=>l(`span`,{className:`rounded-full bg-surface-hover border border-border px-2 py-0.5 text-[10px] text-foreground-subtle`,children:e},e)),i(`div`,{className:`relative`,children:[i(`button`,{type:`button`,onClick:e=>{e.stopPropagation(),T(e=>!e)},className:`inline-flex items-center gap-1 rounded-full border border-dashed border-border px-2 py-0.5 text-[10px] text-foreground-subtle hover:text-foreground hover:border-primary transition-colors`,title:`Install on more agents`,children:[l(ue,{className:`h-3 w-3`}),`Add agent`]}),ne&&i(`div`,{className:`absolute left-0 top-full mt-1 z-10 min-w-[160px] rounded-md border border-border bg-surface shadow-lg overflow-hidden`,children:[t.filter(e=>!e.isHub&&!R.includes(e.name)).map(e=>l(`button`,{type:`button`,onClick:e=>{e.stopPropagation(),T(!1)},className:`w-full text-left px-3 py-1.5 text-[10px] text-foreground hover:bg-surface-hover transition-colors`,children:e.name},e.id)),t.filter(e=>!e.isHub&&!R.includes(e.name)).length===0&&l(`div`,{className:`px-3 py-1.5 text-[10px] text-foreground-subtle`,children:`No available agents`})]})]})]})]})]}),l(`div`,{className:`flex items-center justify-end px-5 py-3 border-t border-border flex-shrink-0`,children:l(`button`,{type:`button`,onClick:()=>k(!1),className:`rounded-lg border border-border px-3 py-1.5 text-xs font-medium text-foreground-subtle hover:text-foreground hover:bg-surface-hover transition-colors`,children:`Close`})})]})})]})}n();var ke=`.tgz,.tar.gz,.zip`;function Ae({onUploadSuccess:n}){let[r,a]=c(!1),s=t(null),u=e(async e=>{a(!0);let t=new FormData;t.append(`file`,e);let r=localStorage.getItem(`camstack_admin_token`)??``;try{(await(await fetch(`/api/addons/upload`,{method:`POST`,headers:{Authorization:`Bearer ${r}`},body:t})).json()).success&&n()}finally{a(!1)}},[n]);return i(o,{children:[l(`input`,{ref:s,type:`file`,accept:ke,onChange:e(e=>{let t=e.target.files?.[0];t&&u(t),e.target.value=``},[u]),className:`hidden`}),i(`button`,{type:`button`,onClick:()=>s.current?.click(),disabled:r,className:`flex items-center gap-1.5 px-3 py-1.5 text-xs rounded-md bg-surface hover:bg-surface-hover border border-border disabled:opacity-50 transition-colors`,children:[r?l(N,{className:`w-3.5 h-3.5 animate-spin`}):l(W,{className:`w-3.5 h-3.5`}),r?`Uploading...`:`Upload`]})]})}n();var je=[{seconds:900,label:`15m`},{seconds:3600,label:`1h`},{seconds:21600,label:`6h`},{seconds:43200,label:`12h`},{seconds:86400,label:`24h`}],Me=new Set([`@camstack/system`,`@camstack/types`,`@camstack/sdk`,`@camstack/shm-ring`,`@camstack/ui-library`]);function Ne(e){return e!==void 0&&Me.has(e)}var Pe={id:`hub`,name:`Hub`,isHub:!0,isOnline:!0};function Fe(e,t){let n=e??`hub-only`;return n===`any-node`?!0:n===`hub-only`?t:!t}function Ie(e){let t=e;if(!t?.manifest)return null;let n={...t.manifest,name:t.manifest.name??t.manifest.id,version:t.manifest.version??`0.0.0`,capabilities:t.manifest.capabilities??[]},r=t.process,i=r?{pid:r.pid,mode:r.mode===`forked`?`forked`:`in-process`,state:r.state??`unknown`}:void 0,a=t.health,o=t.declaration?.execution,s=t.manifest.execution,c=o?.placement??s?.placement;return{manifest:n,enabled:!0,source:t.source,installSource:t.installSource,installedOn:[],...i?{process:i}:{},hasBackup:t.hasBackup,...a?{health:a}:{},...c?{placement:c}:{}}}function Le(e){let t=new Map,n=[];for(let r of e){let e=r.manifest.packageName;if(!e){n.push(r);continue}let i=t.get(e);if(i)i.addons.push(r);else{let n=r.manifest.bundle,i={packageName:e,displayName:n?.displayName??r.manifest.packageDisplayName??r.manifest.name,version:r.manifest.packageVersion,addons:[r],...r.installSource===void 0?{}:{installSource:r.installSource},...n===void 0?{}:{bundle:n}};t.set(e,i)}}let r=[];for(let e of t.values())e.bundle!==void 0||e.addons.length>=2?r.push({bundle:e,representative:e.addons[0]}):r.push(e.addons[0]);return r.push(...n),r}function $(e){return`bundle`in e}function Re({addons:n,clusterStatus:o,selectedNode:d,onRefresh:f,isRefreshing:p}){let m=s(),[g,ee]=c(``),_=r(g),[b,S]=c(!1),C=t(null);u(()=>{if(!b)return;let e=e=>{C.current&&!C.current.contains(e.target)&&S(!1)};return document.addEventListener(`mousedown`,e),()=>document.removeEventListener(`mousedown`,e)},[b]);let{data:T}=y({nodeId:d.id}),re=a(()=>{let e=new Map;for(let t of T??[])e.set(t.name,t.latestVersion);return e},[T]),E=a(()=>(T??[]).filter(e=>!e.isSystem).length,[T]),[ie,D]=c(()=>new Set),[O,ae]=c(()=>new Map),se=e(e=>{D(t=>new Set(t).add(e))},[]),k=e(e=>{D(t=>{if(!t.has(e))return t;let n=new Set(t);return n.delete(e),n})},[]),A=e((e,t)=>{ae(n=>new Map(n).set(e,t))},[]),ue=e(e=>{ae(t=>{if(!t.has(e))return t;let n=new Map(t);return n.delete(e),n})},[]),de=te({onMutate:e=>{se(e.name),ue(e.name)},onSuccess:(e,t)=>{k(t.name);let n=e;if(n&&n.success===!1){A(t.name,n.error??`Update failed (no error message returned by server)`);return}m.invalidateQueries({queryKey:[[`addons`]]}),m.invalidateQueries({queryKey:[[`addons`,`listUpdates`]]})},onError:(e,t)=>{k(t.name),A(t.name,e instanceof Error?e.message:String(e))}}),P=J(),F=t(new Set);u(()=>{let e=new Set;for(let[t,n]of P)q(n)&&e.add(t);let t=[...F.current].some(t=>!e.has(t));F.current=e,t&&(m.invalidateQueries({queryKey:[[`addons`]]}),m.invalidateQueries({queryKey:[[`addons`,`listUpdates`]]}))},[P,m]);let{data:I}=w(void 0),me=ce({onSuccess:()=>{m.invalidateQueries({queryKey:[[`addons`,`getAutoUpdateSettings`]]})}}),he=le({onSuccess:()=>{m.invalidateQueries({queryKey:[[`addons`,`getAutoUpdateSettings`]]})}}),{data:L,isFetching:ge}=v({query:_||void 0},{enabled:b}),B=ne(),{data:V}=h(void 0),H=V?.requestedAt,[U,_e]=c(null),[ve,ye]=c(!1);u(()=>{if(V?.kind===`framework-bulk-update`&&V.requestedAt!==U){_e(V.requestedAt),ye(!0);let e=window.setTimeout(()=>ye(!1),6e3);return()=>window.clearTimeout(e)}},[H,U,V]),oe();let be=e(async()=>{let e=(T??[]).filter(e=>!e.isSystem);if(e.length!==0){if(!d.isHub){for(let t of e)await de.mutateAsync({name:t.name,version:t.latestVersion,nodeId:d.id});return}await B.mutateAsync({kind:`update`,targets:e.map(e=>({name:e.name,version:e.latestVersion})),nodeIds:[d.id]})}},[T,d.id,d.isHub,B,de]),W=x({onSuccess:()=>{m.invalidateQueries({queryKey:[[`addons`]]}),m.invalidateQueries({queryKey:[[`addonPages`]]}),m.invalidateQueries({queryKey:[[`capabilities`]]}),m.invalidateQueries({queryKey:[[`integrations`]]})}}),[G,K]=c(`type`),[xe,Y]=c(()=>typeof window>`u`?`grouped`:window.localStorage.getItem(`camstack.addons.viewMode`)===`flat`?`flat`:`grouped`),Se=e=>{Y(e),typeof window<`u`&&window.localStorage.setItem(`camstack.addons.viewMode`,e)},[Ce,X]=pe(),Z=Ce.get(`capability`),Q=a(()=>{let e=n.filter(e=>!Ne(e.manifest.packageName));return d.isHub||(e=e.filter(e=>Fe(e.placement,d.isHub))),Z&&(e=e.filter(e=>(e.manifest.capabilities??[]).some(e=>(typeof e==`string`?e:e.name)===Z))),e},[n,d.isHub,Z]),we=()=>{let e=new URLSearchParams(Ce);e.delete(`capability`),X(e,{replace:!0})},Te=xe===`flat`?Q:Le(Q),Ee=a(()=>{let e=[...Te];switch(G){case`type`:e.sort((e,t)=>{let n=+!$(e),r=+!$(t);if(n!==r)return n-r;let i=$(e)?e.bundle.displayName:e.manifest.name,a=$(t)?t.bundle.displayName:t.manifest.name;return i.localeCompare(a)});break;case`name`:e.sort((e,t)=>{let n=$(e)?e.bundle.displayName:e.manifest.name,r=$(t)?t.bundle.displayName:t.manifest.name;return n.localeCompare(r)});break;case`source`:e.sort((e,t)=>{let n=$(e)?e.bundle.installSource??``:e.installSource??``,r=$(t)?t.bundle.installSource??``:t.installSource??``;return n.localeCompare(r)});break}return e},[Te,G]);return i(`div`,{className:`space-y-4`,children:[[...O.entries()].map(([e,t])=>l(`div`,{className:`rounded-md border border-danger/30 bg-danger/5 px-3 py-2 text-[11px]`,children:i(`div`,{className:`flex items-start justify-between gap-3`,children:[i(`div`,{className:`space-y-0.5`,children:[i(`div`,{className:`font-medium text-danger`,children:[`Failed to update `,e]}),l(`div`,{className:`text-foreground-subtle font-mono`,children:t})]}),l(`button`,{type:`button`,onClick:()=>ue(e),className:`text-foreground-subtle hover:text-foreground text-[10px]`,children:`dismiss`})]})},e)),i(`div`,{className:`flex items-center gap-2 flex-wrap`,children:[i(`div`,{className:`flex items-center gap-1.5`,children:[l(`span`,{className:`text-[10px] text-foreground-subtle`,children:`Sort:`}),i(`select`,{value:G,onChange:e=>K(e.target.value),className:`rounded-md border border-border bg-surface px-2 py-1.5 text-[11px] text-foreground focus:outline-none focus:border-primary/50`,children:[l(`option`,{value:`type`,children:`Bundles first`}),l(`option`,{value:`name`,children:`Name`}),l(`option`,{value:`source`,children:`Install source`})]})]}),i(`div`,{className:`flex items-center gap-1.5`,children:[l(`span`,{className:`text-[10px] text-foreground-subtle`,children:`View:`}),l(`div`,{className:`flex rounded-md border border-border overflow-hidden text-[10px] font-medium`,children:[`grouped`,`flat`].map(e=>l(`button`,{type:`button`,onClick:()=>Se(e),className:`px-2.5 py-1.5 transition-colors capitalize ${xe===e?`bg-primary/10 text-primary`:`bg-transparent text-foreground-subtle hover:bg-surface-hover`}`,title:e===`grouped`?`Group multi-addon packages into a bundle card`:`Show every addon as its own card`,children:e},e))})]}),d.isHub&&i(`div`,{className:`flex items-center gap-1.5`,children:[l(M,{className:`h-3 w-3 text-foreground-subtle`}),l(`span`,{className:`text-[10px] text-foreground-subtle`,children:`Auto-Update:`}),l(`div`,{className:`flex rounded-md border border-border overflow-hidden text-[10px] font-medium`,children:[`off`,`latest`,`beta`].map(e=>l(`button`,{type:`button`,onClick:()=>me.mutate({channel:e}),disabled:me.isPending,className:`px-2.5 py-1.5 transition-colors capitalize ${I?.channel===e?e===`off`?`bg-gray-700 text-gray-200`:e===`latest`?`bg-blue-500/20 text-blue-400`:`bg-amber-500/20 text-amber-400`:`bg-transparent text-foreground-subtle hover:bg-surface-hover`} ${e===`off`?``:`border-l border-border`}`,children:e},e))})]}),d.isHub&&i(`div`,{className:`flex items-center gap-1.5`,children:[l(`span`,{className:`text-[10px] text-foreground-subtle`,children:`Check every:`}),l(`select`,{className:`rounded-md border border-border bg-transparent px-1.5 py-1 text-[10px] font-medium text-foreground-subtle`,value:I?.updateCheckIntervalSeconds??21600,disabled:he.isPending||I===void 0,onChange:e=>{I!==void 0&&he.mutate({channel:I.channel,updateCheckIntervalSeconds:Number(e.target.value)})},children:je.map(e=>l(`option`,{value:e.seconds,children:e.label},e.seconds))})]}),E>0&&i(`button`,{type:`button`,onClick:()=>void be(),disabled:B.isPending,className:`flex items-center gap-1.5 px-2.5 py-1.5 text-[11px] rounded-md bg-blue-500/10 text-blue-400 hover:bg-blue-500/20 border border-blue-500/30 disabled:opacity-50 transition-colors font-medium`,children:[B.isPending?l(N,{className:`w-3 h-3 animate-spin`}):l(j,{className:`w-3 h-3`}),B.isPending?`Updating…`:`Update All (${E})`]}),i(`button`,{type:`button`,onClick:f,disabled:p||B.isPending,className:`flex items-center gap-1.5 px-2.5 py-1.5 text-[11px] rounded-md bg-surface hover:bg-surface-hover border border-border disabled:opacity-50 transition-colors`,children:[l(M,{className:`w-3 h-3 ${p?`animate-spin`:``}`}),`Refresh`]})]}),i(`div`,{className:`flex flex-col gap-2 sm:flex-row sm:items-center sm:gap-3`,children:[i(`div`,{className:`relative flex-1 min-w-0 sm:min-w-[200px]`,ref:C,children:[l(R,{className:`absolute left-2.5 top-1/2 -translate-y-1/2 h-3.5 w-3.5 text-foreground-subtle`}),l(`input`,{type:`text`,value:g,onChange:e=>{ee(e.target.value),S(!0)},onFocus:()=>S(!0),placeholder:`Search addons on npm...`,disabled:B.isPending,className:`w-full rounded-lg border border-border bg-background pl-9 pr-3 py-2 text-xs text-foreground placeholder:text-foreground-subtle focus:outline-none focus:ring-1 focus:ring-primary disabled:opacity-50 disabled:cursor-not-allowed`}),ge&&l(N,{className:`absolute right-2.5 top-1/2 -translate-y-1/2 h-3 w-3 text-foreground-subtle animate-spin`}),b&&L&&L.length>0&&i(`div`,{className:`absolute left-0 right-0 top-full mt-1 z-40 rounded-lg border border-border bg-surface shadow-xl overflow-hidden`,children:[L.length>0&&i(`div`,{className:`px-3 py-1.5 text-[10px] uppercase tracking-wide text-foreground-subtle border-b border-border`,children:[`npm results (`,L.length,`)`]}),L&&L.length>0&&l(`div`,{className:`max-h-72 overflow-auto divide-y divide-border`,children:L.map(e=>i(`div`,{className:`flex items-center gap-3 px-3 py-2 hover:bg-surface-hover transition-colors`,children:[l(`div`,{className:`w-6 h-6 rounded-md bg-primary/10 flex items-center justify-center text-primary text-[9px] font-bold shrink-0`,children:e.name.replace(`@camstack/addon-`,``).charAt(0).toUpperCase()}),i(`div`,{className:`flex-1 min-w-0`,children:[i(`div`,{className:`flex items-baseline gap-2 min-w-0`,children:[l(`span`,{className:`text-[11px] font-semibold break-words`,children:e.name.replace(/^@camstack\/(addon-)?/,``)}),i(`span`,{className:`text-[10px] text-foreground-subtle shrink-0`,children:[`v`,e.version]})]}),l(`div`,{className:`font-mono text-[9px] text-foreground-subtle/80 truncate`,children:e.name}),e.description&&l(`div`,{className:`text-[10px] text-foreground-subtle truncate`,children:e.description})]}),e.installed?i(`span`,{className:`inline-flex items-center gap-1 px-2 py-1 text-[10px] font-medium rounded-md border border-emerald-500/30 bg-emerald-500/10 text-emerald-400 shrink-0`,children:[l(z,{className:`h-3 w-3`}),e.installedVersion??`Installed`]}):i(`button`,{type:`button`,onClick:()=>W.mutate({packageName:e.name}),disabled:W.isPending,className:`inline-flex items-center gap-1 px-2 py-1 text-[10px] font-medium rounded-md bg-primary text-primary-foreground hover:bg-primary/90 disabled:opacity-50 transition-colors shrink-0`,children:[W.isPending?l(N,{className:`h-3 w-3 animate-spin`}):l(j,{className:`h-3 w-3`}),`Install`]})]},e.name))})]})]}),l(Ae,{onUploadSuccess:()=>{m.invalidateQueries({queryKey:[[`addons`]]}),f()}})]}),Z&&i(`div`,{className:`flex items-center gap-2 px-3 py-2 rounded-lg bg-primary/10 border border-primary/30 text-sm`,children:[l(`span`,{className:`text-foreground-subtle`,children:`Filtering by capability:`}),l(`span`,{className:`font-mono text-primary font-semibold`,children:Z}),l(`button`,{type:`button`,onClick:we,className:`ml-auto text-xs text-foreground-subtle hover:text-foreground underline`,children:`Clear`})]}),ve&&i(`div`,{className:`fixed top-[calc(env(safe-area-inset-top)+1rem)] right-[calc(env(safe-area-inset-right)+1rem)] z-50 flex items-start gap-2 px-3 py-2.5 rounded-md border border-green-500/30 bg-green-500/10 shadow-lg backdrop-blur-sm max-w-sm pointer-events-auto`,children:[l(fe,{className:`w-4 h-4 shrink-0 mt-0.5 text-green-400`}),i(`div`,{children:[l(`div`,{className:`text-[11px] font-semibold text-foreground`,children:`Bulk update completed`}),l(`div`,{className:`text-[10px] text-foreground-subtle mt-0.5`,children:`System packages updated — hub restarted successfully.`})]})]}),Q.length===0&&l(`div`,{className:`text-xs text-foreground-subtle`,children:n.length===0?`No addons installed`:Z?`No installed addons declare the "${Z}" capability. Browse the npm catalog above to find a compatible addon.`:`No addons compatible with ${d.name} (placement filter active)`}),l(`div`,{className:`space-y-2`,children:Ee.map(e=>{let t=$(e)?e.bundle.packageName:e.manifest.packageName,n=re.get(t),r=$(e)?e.representative:e,i=n?e=>de.mutate({name:t,version:e,nodeId:d.id}):void 0,a=P.get(t)??null,s=a!==null&&q(a);return l(Oe,{addon:r,clusterStatus:o?.[r.manifest.id],bundle:$(e)?e.bundle:void 0,availableUpdate:n,isUpdating:ie.has(t)||s,jobProgress:a,onUpdate:i,disabledByBulk:B.isPending},$(e)?t:e.manifest.id)})})]})}function ze(){let e=s(),{data:n,isLoading:r,isError:a}=O(),{data:o}=E(void 0),{nodes:c}=T(),{selection:d,selectNode:f,requestedNodeId:m}=U(c.length>0?c:[Pe]),h=d.node??Pe,g=h.id,ee=c.length>0?d.staleNodeId:null,_=p(),v=b(),y=_.isPending||v.isPending,x=async()=>{await _.mutateAsync({nodeId:g}),await v.mutateAsync(),e.invalidateQueries({queryKey:[[`addons`]]})},S=t(_);S.current=_;let C=t(m??`hub`);u(()=>{S.current.mutate({nodeId:C.current})},[]);let w=(n??[]).map(Ie).filter(e=>e!==null);return i(B,{children:[i(`div`,{className:`flex items-center justify-between gap-3 flex-wrap`,children:[l(ie,{selectedNodeId:g,onSelect:f}),i(`div`,{className:`flex items-center gap-3 flex-wrap`,children:[!r&&!a&&i(`span`,{className:`text-[10px] rounded-full bg-primary/10 text-primary px-2 py-0.5 font-medium`,children:[w.length,` installed`]}),i(`button`,{type:`button`,onClick:()=>void x(),disabled:y,className:`inline-flex items-center gap-1.5 px-2.5 py-1.5 text-[11px] rounded-md bg-surface hover:bg-surface-hover border border-border disabled:opacity-50 transition-colors`,title:`Re-fetch addons + check npm for new versions`,children:[l(M,{className:`w-3 h-3 ${y?`animate-spin`:``}`}),`Check for updates`]})]})]}),l(H,{staleNodeId:ee,shownNodeName:h.name}),!h.isHub&&i(`div`,{className:`rounded-md border border-warning/30 bg-warning/5 px-3 py-2 text-[11px] text-foreground-subtle`,children:[`Showing only addons compatible with`,` `,l(`span`,{className:`font-medium text-foreground`,children:h.name}),` — agents only run`,` `,l(`code`,{className:`font-mono`,children:`agent-only`}),` and`,` `,l(`code`,{className:`font-mono`,children:`any-node`}),` addons. Install / uninstall is hub-driven; agents auto-sync from the hub.`]}),r&&l(`div`,{className:`text-xs text-foreground-subtle animate-pulse`,children:`Loading…`}),a&&l(`div`,{className:`text-xs text-danger`,children:`Failed to load addons`}),!r&&!a&&l(Re,{addons:w,clusterStatus:o,selectedNode:h,onRefresh:()=>void x(),isRefreshing:y})]})}export{ze as AddonsPage};
|