@camstack/addon-admin-ui 1.2.349 → 1.2.350

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (110) hide show
  1. package/dist/assets/{AddonCollectionPage-jXCbcMZu.js → AddonCollectionPage-D9Q3skZA.js} +1 -1
  2. package/dist/assets/Addons-Bxd8giTY.js +1 -0
  3. package/dist/assets/{AdminTabs-DcYKYXzK.js → AdminTabs-DbxtEjk6.js} +1 -1
  4. package/dist/assets/AiProfiles-D4ktKl5a.js +3 -0
  5. package/dist/assets/{BrokerForm-rRXdhvBg.js → BrokerForm-b2HG3A_I.js} +1 -1
  6. package/dist/assets/Build-D9tNwFp7.js +40 -0
  7. package/dist/assets/{Calendars-BhTVLKHz.js → Calendars-DPpRjVVr.js} +1 -1
  8. package/dist/assets/{Capabilities-CvhnCl7c.js → Capabilities-0tfKqmQA.js} +1 -1
  9. package/dist/assets/Cluster-BQanBpWv.js +11 -0
  10. package/dist/assets/ClusterStepModel-Di3RCHbu.js +1 -0
  11. package/dist/assets/{CompositionEditor-gkHb7ZT2.js → CompositionEditor-8xtSUeri.js} +1 -1
  12. package/dist/assets/{CompositionEditorPage-UrJerX9A.js → CompositionEditorPage-boKGo8GQ.js} +1 -1
  13. package/dist/assets/Data-DMpZGfrn.js +1 -0
  14. package/dist/assets/DetectionIntelligence-DAgaEMGO.js +1 -0
  15. package/dist/assets/DeviceDetail-BSb1-TNN.js +2 -0
  16. package/dist/assets/{DeviceDoActionFields-Qp-mdQoy.js → DeviceDoActionFields-BfmISfgz.js} +1 -1
  17. package/dist/assets/{Devices-D0X5ZMil.js → Devices-Hx32f7xo.js} +1 -1
  18. package/dist/assets/{EmbedPlayerPage-BCohm6GU.js → EmbedPlayerPage-CocO1BTn.js} +1 -1
  19. package/dist/assets/Events-BkTP2omD.js +1 -0
  20. package/dist/assets/Identity-CWRUDt5i.js +1 -0
  21. package/dist/assets/IntegrationDetail-BKzLD-QT.js +1 -0
  22. package/dist/assets/Integrations-BeENEzwD.js +1 -0
  23. package/dist/assets/Integrations-CDvy6QgO.js +1 -0
  24. package/dist/assets/Locations-DRody3E5.js +3 -0
  25. package/dist/assets/{Logs-4q8jFD5i.js → Logs-CBhyoglF.js} +1 -1
  26. package/dist/assets/{MotionZonesSettings-M2UAaOLw.js → MotionZonesSettings-TfnZ4ZPN.js} +1 -1
  27. package/dist/assets/{MyAccess-Brzl2xif.js → MyAccess-BGXlB9No.js} +1 -1
  28. package/dist/assets/Network-DCoLk82s.js +1 -0
  29. package/dist/assets/NodeAddonsSettingsPanel-DzIjWuOo.js +1 -0
  30. package/dist/assets/Notifications-BmXW8_iS.js +1 -0
  31. package/dist/assets/Plates-DTq6QrGW.js +1 -0
  32. package/dist/assets/{PrivacyMaskSettings-8lVg2P1M.js → PrivacyMaskSettings-Ha-Zqjj7.js} +1 -1
  33. package/dist/assets/Recordings-BtqzNlHC.js +1 -0
  34. package/dist/assets/{ScanNetworkModal-B59h5xvq.js → ScanNetworkModal-Bu7C4PSL.js} +1 -1
  35. package/dist/assets/{SceneMonitorEditor-B1E8n6ou.js → SceneMonitorEditor-breuTs7j.js} +1 -1
  36. package/dist/assets/{Scenes-CR29v0gZ.js → Scenes-DkIfQKai.js} +1 -1
  37. package/dist/assets/{Settings-BvzufFl5.js → Settings-DPHIIOeT.js} +1 -1
  38. package/dist/assets/{Showroom-BnjdRdKN.js → Showroom-CvSria_z.js} +1 -1
  39. package/dist/assets/{Terminal-aUzk1uKX.js → Terminal-DvihlsfY.js} +5 -5
  40. package/dist/assets/{Viewer-M6qlWxs9.js → Viewer-DAm-N3A9.js} +1 -1
  41. package/dist/assets/{_virtual_mf-localSharedImportMap___mfe_internal__admin_ui_host-BsOXjLIp.js → _virtual_mf-localSharedImportMap___mfe_internal__admin_ui_host-B1L1rmsf.js} +1 -1
  42. package/dist/assets/{archive-D-Y4i_R_.js → archive-QWpDQvmy.js} +1 -1
  43. package/dist/assets/{authed-media-_X4FXSBp.js → authed-media-CvliDudL.js} +1 -1
  44. package/dist/assets/{boxes-DXM8dtQJ.js → boxes-ghM9MyNI.js} +1 -1
  45. package/dist/assets/circle-slash-BY9azzp9.js +1 -0
  46. package/dist/assets/client-D2T6hnwJ.js +357 -0
  47. package/dist/assets/crop-eTEKuG4V.js +1 -0
  48. package/dist/assets/debounced-invalidate-Brd-xEUl.js +1 -0
  49. package/dist/assets/{device-integration-icon-BXFJAjbm.js → device-integration-icon-BxxUQkzA.js} +1 -1
  50. package/dist/assets/device-picker-model-Er0KXZFo.js +1 -0
  51. package/dist/assets/{dist-BoA-02Ta.js → dist-BkWWqFzL.js} +1 -1
  52. package/dist/assets/dist-CWyZkxmr.js +357 -0
  53. package/dist/assets/face-bbox-BtWjVAUr.js +1 -0
  54. package/dist/assets/{hard-drive-download-DI78Qxnu.js → hard-drive-download-BNwv1QZy.js} +1 -1
  55. package/dist/assets/{hostInit-CjZNBAf2.js → hostInit-DeFZcRbl.js} +1 -1
  56. package/dist/assets/index-CFu9bpWo.css +2 -0
  57. package/dist/assets/index-CTLsm4or.js +4 -0
  58. package/dist/assets/{layers-BYuVbzVs.js → layers-Cqi6DnJp.js} +1 -1
  59. package/dist/assets/{location-owned-usage-Bj5-khSs.js → location-owned-usage-nUG-wNCP.js} +1 -1
  60. package/dist/assets/{mf-entry-bootstrap-0-ea91eb80.js → mf-entry-bootstrap-0-f3da6c45.js} +2 -2
  61. package/dist/assets/mount-Er0KXZFo.js +1 -0
  62. package/dist/assets/notification-schedule-field-OWvLlCoa.js +1 -0
  63. package/dist/assets/{player-overlays-BddRivLE.js → player-overlays-BHccEyE0.js} +1 -1
  64. package/dist/assets/remoteEntry-BFQE9dZb.js +1 -0
  65. package/dist/assets/{send-CyJGX9-U.js → send-JCuF4gJW.js} +1 -1
  66. package/dist/assets/{settings-2-BOGh_wO6.js → settings-2-x7GDFxSP.js} +1 -1
  67. package/dist/assets/src-DgWGoEDF.js +67 -0
  68. package/dist/assets/{use-scenes-feed-B4UtvXrE.js → use-scenes-feed-B7UdAzGO.js} +1 -1
  69. package/dist/assets/{use-stationary-objects-QRm4Gn4u.js → use-stationary-objects-BnA_XGaA.js} +1 -1
  70. package/dist/assets/useEventInvalidation-Er0KXZFo.js +1 -0
  71. package/dist/assets/{useNodeUrlSelection-BDv33pGy.js → useNodeUrlSelection-uZUf1p_p.js} +1 -1
  72. package/dist/assets/user-round-Ck3MDNjX.js +1 -0
  73. package/dist/assets/{virtual_mf-REMOTE_ENTRY_ID___mfe_internal__admin_ui_host__remoteEntry-_hash_-C2YrzRgM.js → virtual_mf-REMOTE_ENTRY_ID___mfe_internal__admin_ui_host__remoteEntry-_hash_-DWDVV7Rx.js} +2 -2
  74. package/dist/index.html +8 -8
  75. package/dist/server/addon.js +35 -327
  76. package/package.json +1 -1
  77. package/dist/assets/Addons-rr7aue1z.js +0 -1
  78. package/dist/assets/AiProfiles-CxBtibtD.js +0 -3
  79. package/dist/assets/Build-Tu52RNi0.js +0 -40
  80. package/dist/assets/Cluster-Bq5YAagB.js +0 -11
  81. package/dist/assets/ClusterStepModel-BXuKvfKQ.js +0 -1
  82. package/dist/assets/Data-CRMaoAvA.js +0 -1
  83. package/dist/assets/DetectionIntelligence-hpln0NzF.js +0 -1
  84. package/dist/assets/DeviceDetail-DA9kIkj-.js +0 -2
  85. package/dist/assets/Events-DJqXUhGE.js +0 -1
  86. package/dist/assets/Identity-CMHAJE1i.js +0 -1
  87. package/dist/assets/IntegrationDetail-D6CPV8I0.js +0 -1
  88. package/dist/assets/Integrations-C3v7m_pV.js +0 -1
  89. package/dist/assets/Integrations-CrSI1y99.js +0 -1
  90. package/dist/assets/Locations-BXxpBY8V.js +0 -3
  91. package/dist/assets/Network-UpHA2zPn.js +0 -1
  92. package/dist/assets/NodeAddonsSettingsPanel-D7Ope1My.js +0 -1
  93. package/dist/assets/Notifications-3jCEMiJT.js +0 -1
  94. package/dist/assets/Plates-DnKm0uO5.js +0 -1
  95. package/dist/assets/Recordings-C8Dz8QdA.js +0 -1
  96. package/dist/assets/circle-slash-Bh6ndID4.js +0 -1
  97. package/dist/assets/client-BVesZTvN.js +0 -357
  98. package/dist/assets/debounced-invalidate-On21l1Xj.js +0 -1
  99. package/dist/assets/device-picker-model-Br0xkUVQ.js +0 -1
  100. package/dist/assets/dist-CXTK9bJc.js +0 -357
  101. package/dist/assets/face-bbox-3mjLW0O1.js +0 -1
  102. package/dist/assets/index-DP2qgRL_.css +0 -2
  103. package/dist/assets/index-NHwA6Zmb.js +0 -4
  104. package/dist/assets/mount-Br0xkUVQ.js +0 -1
  105. package/dist/assets/notification-schedule-field-Bho2AfCu.js +0 -1
  106. package/dist/assets/remoteEntry-CJLM9B1W.js +0 -1
  107. package/dist/assets/square-check-big-CpCHNAfP.js +0 -1
  108. package/dist/assets/src-DnQxdAYg.js +0 -67
  109. package/dist/assets/useEventInvalidation-Br0xkUVQ.js +0 -1
  110. package/dist/assets/user-round-1jRRPQok.js +0 -1
@@ -1,6 +1,6 @@
1
1
  import path from "node:path";
2
2
  import { fileURLToPath } from "node:url";
3
- //#region ../types/dist/event-category-BGmz_oxW.mjs
3
+ //#region ../types/dist/event-category-B_0XEcLF.mjs
4
4
  var EventCategory = /* @__PURE__ */ function(EventCategory) {
5
5
  EventCategory["SystemBoot"] = "system.boot";
6
6
  EventCategory["SystemAddonsReady"] = "system.addons-ready";
@@ -501,15 +501,6 @@ var EventCategory = /* @__PURE__ */ function(EventCategory) {
501
501
  EventCategory["AgentWsDisconnected"] = "agent.ws.disconnected";
502
502
  EventCategory["AgentBackupActivated"] = "agent.backup.activated";
503
503
  EventCategory["OrchestrationSettingsUpdated"] = "orchestration.settings-updated";
504
- /**
505
- * Per-agent hwaccel preference changed (user override set, cleared, or
506
- * re-probed). Observability event — decoders pull the current pref at
507
- * `createSession`, so running sessions keep their current backend until
508
- * they rotate naturally (camera add/remove, stream restart). Future
509
- * work can wire a listener in stream-broker that force-rotates live
510
- * sessions; for now this event powers logs + admin-UI toast feedback.
511
- */
512
- EventCategory["PipelineAgentHwaccelChanged"] = "pipeline.agent-hwaccel-changed";
513
504
  EventCategory["MotionAnalysis"] = "detection.motion-analysis";
514
505
  /** All raw motion zones from CCL before minArea filter — for UI debug overlay. */
515
506
  EventCategory["MotionZonesRaw"] = "detection.motion-zones-raw";
@@ -5380,7 +5371,7 @@ var ZodIssueCode = {
5380
5371
  var ZodFirstPartyTypeKind;
5381
5372
  ZodFirstPartyTypeKind || (ZodFirstPartyTypeKind = {});
5382
5373
  //#endregion
5383
- //#region ../types/dist/sleep-DAJ9Er57.mjs
5374
+ //#region ../types/dist/sleep-BNeXenvr.mjs
5384
5375
  /**
5385
5376
  * The audio chunk plane's byte format, and the ONE expansion from a coded
5386
5377
  * window to float samples (D455).
@@ -6746,32 +6737,12 @@ object({
6746
6737
  audioCodec: string().optional(),
6747
6738
  metadata: record(string(), unknown()).readonly().optional()
6748
6739
  });
6749
- var EncodedPacketSchema = object({
6750
- type: _enum(["video", "audio"]),
6751
- data: _instanceof(Uint8Array),
6752
- pts: number(),
6753
- dts: number(),
6754
- keyframe: boolean(),
6755
- codec: string()
6756
- });
6757
- var DecodedFrameSchema = object({
6758
- data: _instanceof(Uint8Array),
6759
- width: number(),
6760
- height: number(),
6761
- format: _enum([
6762
- "jpeg",
6763
- "rgb",
6764
- "bgr",
6765
- "yuv420",
6766
- "gray"
6767
- ]),
6768
- timestamp: number()
6769
- });
6770
6740
  /**
6771
6741
  * Wire schema for `FrameHandle` — a zero-pixel, serialisable reference to a
6772
6742
  * frame in a shared-memory ring (Phase 5 / D9). Mirrors the `FrameHandle` TS
6773
- * interface in `interfaces/frame-handle.ts` field-for-field so a decoder cap
6774
- * method (`pullHandles`) can carry handles over tRPC / Moleculer.
6743
+ * interface in `interfaces/frame-handle.ts` field-for-field so a cap method
6744
+ * (the runner's native-crop and pipeline-executor inputs) can carry handles
6745
+ * over tRPC / Moleculer.
6775
6746
  *
6776
6747
  * The `satisfies` assertion below pins this schema to the interface: if a
6777
6748
  * field is added to / removed from `FrameHandle` without a matching schema
@@ -6797,50 +6768,6 @@ var FrameHandleSchema = object({
6797
6768
  slotCount: number().int().positive()
6798
6769
  });
6799
6770
  /**
6800
- * Pixel format a frame-handle subscriber can request from the broker
6801
- * (Phase 5 / D9). The packed, raster subset of `FrameFormat` — the formats a
6802
- * `frameSink: 'shm'` decoder session can write into a `FrameRing` slot.
6803
- * `jpeg` is excluded: a variable-length stream is not a fixed-stride ring
6804
- * payload, and no decoded-frame consumer requests it over the shm plane.
6805
- */
6806
- var FrameHandleFormatSchema = _enum([
6807
- "rgb",
6808
- "bgr",
6809
- "yuv420",
6810
- "gray"
6811
- ]);
6812
- /**
6813
- * Input for `stream-broker.subscribeFrames` (Phase 5 / D9). A consumer asks the
6814
- * broker for a `FrameHandle` stream of one `format`; the broker maintains one
6815
- * shared-memory ring per `(brokerId, format)` actually requested, so a `gray`
6816
- * subscriber (motion) and an `rgb` subscriber (detection) each read the format
6817
- * they asked for with no broker-side conversion.
6818
- */
6819
- var SubscribeFramesInputSchema = object({
6820
- brokerId: string(),
6821
- format: FrameHandleFormatSchema,
6822
- /**
6823
- * Optional reader-side cadence hint in frames per second. The broker does
6824
- * NOT throttle — latest-wins ring reads drop frames implicitly for a slow
6825
- * consumer. The value is echoed back in `SubscribeFramesResult.maxFps` so
6826
- * the consumer can pace its own `pullFrameHandles` polling.
6827
- */
6828
- maxFps: number().positive().optional(),
6829
- /** Short caller-identity tag (`motion`, `detection`, …) for diagnostics. */
6830
- tag: string().optional()
6831
- });
6832
- /**
6833
- * Result of `stream-broker.subscribeFrames`. The consumer then polls
6834
- * `pullFrameHandles({ subscriptionId, maxCount })` and feeds each returned
6835
- * `FrameHandle` to a `FrameRingReader`.
6836
- */
6837
- var SubscribeFramesResultSchema = object({
6838
- /** Opaque id the consumer passes to `pullFrameHandles` / `unsubscribeFrames`. */
6839
- subscriptionId: string(),
6840
- /** Reader-side cadence hint (frames/s) — echoes `SubscribeFramesInput.maxFps`. */
6841
- maxFps: number().nonnegative()
6842
- });
6843
- /**
6844
6771
  * Wire schema for a decoded audio chunk (Phase 5 / D9). Mirrors the
6845
6772
  * `DecodedAudioChunk` TS interface in `interfaces/stream-broker.ts`: PCM
6846
6773
  * sample bytes plus the track parameters a consumer needs to interpret them.
@@ -6848,8 +6775,8 @@ var SubscribeFramesResultSchema = object({
6848
6775
  * Audio chunks are tiny (a ~500ms AudioCodecSession window is a few KB of
6849
6776
  * Float32 PCM), so unlike video frames they ship their bytes INLINE over
6850
6777
  * tRPC / Moleculer — no shared-memory plane. `data` is typed `Uint8Array`
6851
- * (the wire-serialisable supertype of `Buffer`) to match `DecodedFrameSchema`
6852
- * / `EncodedPacketSchema`'s precedent; a `Buffer` is assignable to it.
6778
+ * (the wire-serialisable supertype of `Buffer`); a `Buffer` is assignable to
6779
+ * it.
6853
6780
  */
6854
6781
  var AudioChunkFormatSchema = _enum(AUDIO_CHUNK_FORMATS);
6855
6782
  var DecodedAudioChunkSchema = object({
@@ -6867,11 +6794,10 @@ var DecodedAudioChunkSchema = object({
6867
6794
  format: AudioChunkFormatSchema.optional()
6868
6795
  });
6869
6796
  /**
6870
- * Input for `stream-broker.subscribeAudioChunks` (Phase 5 / D9). The
6871
- * handle-free, ship-bytes-inline analogue of `subscribeFrames`: a consumer
6872
- * asks the broker for the decoded audio-chunk stream of one broker; the
6873
- * broker keeps a per-subscription bounded FIFO queue the consumer drains via
6874
- * `pullAudioChunks`.
6797
+ * Input for `stream-broker.subscribeAudioChunks` (Phase 5 / D9). Audio ships
6798
+ * its bytes inline: a consumer asks the broker for the decoded audio-chunk
6799
+ * stream of one broker; the broker keeps a per-subscription bounded FIFO queue
6800
+ * the consumer drains via `pullAudioChunks`.
6875
6801
  */
6876
6802
  var SubscribeAudioChunksInputSchema = object({
6877
6803
  brokerId: string(),
@@ -6902,9 +6828,7 @@ var BrokerStatsSchema = object({
6902
6828
  "stopped"
6903
6829
  ]),
6904
6830
  inputFps: number(),
6905
- decodeFps: number(),
6906
6831
  encodedSubscribers: number(),
6907
- decodedSubscribers: number(),
6908
6832
  uptimeMs: number(),
6909
6833
  bitrateKbps: number(),
6910
6834
  idrIntervalMs: number(),
@@ -6917,14 +6841,6 @@ var BrokerStatsSchema = object({
6917
6841
  preBufferMs: number(),
6918
6842
  preBufferPackets: number(),
6919
6843
  /**
6920
- * Moleculer node id of the decoder provider currently servicing this
6921
- * stream's decoded subscribers. `null` until the deferred decoder is
6922
- * created (no decoded clients yet, or codec not detected). Surfaces the
6923
- * runtime decoder placement so the UI can show "Decoder: <agent>" without
6924
- * a separate cap call per broker.
6925
- */
6926
- decoderNodeId: string().nullable(),
6927
- /**
6928
6844
  * Detected audio track parameters from the RTSP DESCRIBE / SDP. `null`
6929
6845
  * when the stream has no audio track or the broker is in cold start.
6930
6846
  * `supported = false` means the codec was detected but the local
@@ -10264,70 +10180,6 @@ var StorageLocationDeclarationSchema = object({
10264
10180
  "backup"
10265
10181
  ]).optional()
10266
10182
  });
10267
- var DecoderStatsSchema = object({
10268
- inputFps: number(),
10269
- outputFps: number(),
10270
- avgDecodeTimeMs: number(),
10271
- droppedFrames: number(),
10272
- /**
10273
- * Pull-mode adaptive-fps telemetry (optional — only pull sessions run the
10274
- * lag-driven controller; push sessions omit these). `lagMs` is the EWMA of
10275
- * the decoder's real-time drift (rising = falling behind live); `adaptiveFps`
10276
- * is the current lag-throttled emit rate (≤ `effectiveFps` ceiling).
10277
- */
10278
- lagMs: number().optional(),
10279
- effectiveFps: number().optional(),
10280
- adaptiveFps: number().optional()
10281
- });
10282
- var DecoderSessionConfigSchema = object({
10283
- codec: string(),
10284
- maxFps: number().default(0),
10285
- outputFormat: _enum([
10286
- "jpeg",
10287
- "rgb",
10288
- "bgr",
10289
- "yuv420",
10290
- "gray"
10291
- ]).default("jpeg"),
10292
- scale: number().default(1),
10293
- width: number().optional(),
10294
- height: number().optional(),
10295
- /**
10296
- * Identifier of the camera this decoder session serves. Optional
10297
- * because the cap is generic (any caller could request decode), but
10298
- * stream-broker passes it so decoder logs include `deviceId` for
10299
- * per-camera filtering when diagnosing failures (e.g. node-av
10300
- * sendPacket errors on a single hung camera).
10301
- */
10302
- deviceId: number().int().nonnegative().optional(),
10303
- /**
10304
- * Free-form tag for log scoping. Stream-broker uses
10305
- * `broker:<deviceId>/<profile>`. Decoder session logger surfaces it
10306
- * on every line so `grep tag=broker:5/high` filters one camera
10307
- * profile cleanly.
10308
- */
10309
- tag: string().optional(),
10310
- /**
10311
- * Where the session delivers decoded frames (Phase 5 / D9):
10312
- *
10313
- * - `'callback'` (default) — the legacy pixel path: decoded frames are
10314
- * buffered as `DecodedFrame`s and drained via `pullFrames`.
10315
- * - `'shm'` — the shared-memory frame plane: decoded frames are written
10316
- * into an OS shared-memory ring and drained as zero-pixel
10317
- * `FrameHandle`s via `pullHandles`. A session is one mode or the
10318
- * other — `pullFrames` returns nothing for an `'shm'` session and
10319
- * `pullHandles` returns nothing for a `'callback'` session.
10320
- */
10321
- frameSink: _enum(["callback", "shm"]).default("callback"),
10322
- /**
10323
- * Per-camera decoder DEBUG facility. When `true`, a pull-mode session emits
10324
- * a throttled (~1Hz) structured `decoder debug` line (effective/adaptive fps,
10325
- * real-time lag, dropped-frame delta, avg decode time, hwaccel). Mirrors the
10326
- * stream-broker's `streamingDebug` gate — off by default so production logs
10327
- * stay quiet and the emit path pays zero per-frame cost when disabled.
10328
- */
10329
- debug: boolean().optional()
10330
- });
10331
10183
  /**
10332
10184
  * Per-component log CHANNELS — the gate a hot path consults, and the registry
10333
10185
  * an addon declares its channels in.
@@ -12474,13 +12326,6 @@ var BrokerRtspClientSchema = object({
12474
12326
  lastRtpAt: number(),
12475
12327
  bytesSent: number()
12476
12328
  });
12477
- var BrokerDecodedClientSchema = object({
12478
- tag: string(),
12479
- subscribedAt: number(),
12480
- maxFps: number(),
12481
- framesDelivered: number(),
12482
- framesDropped: number()
12483
- });
12484
12329
  var BrokerAudioClientSchema = object({
12485
12330
  tag: string(),
12486
12331
  subscribedAt: number(),
@@ -12572,7 +12417,6 @@ var BrokerEncodedClientSchema = object({
12572
12417
  });
12573
12418
  var BrokerClientsSchema = object({
12574
12419
  rtsp: array(BrokerRtspClientSchema).readonly(),
12575
- decoded: array(BrokerDecodedClientSchema).readonly(),
12576
12420
  audio: array(BrokerAudioClientSchema).readonly(),
12577
12421
  encoded: array(BrokerEncodedClientSchema).readonly(),
12578
12422
  pipeClients: number(),
@@ -12941,11 +12785,7 @@ method(object({
12941
12785
  auth: "admin"
12942
12786
  }), method(object({ brokerId: string() }), BrokerClientsSchema), method(object({
12943
12787
  brokerId: string(),
12944
- channel: _enum([
12945
- "rtsp",
12946
- "decoded",
12947
- "audio"
12948
- ]),
12788
+ channel: _enum(["rtsp", "audio"]),
12949
12789
  handle: string()
12950
12790
  }), object({ killed: boolean() }), {
12951
12791
  kind: "mutation",
@@ -12980,10 +12820,7 @@ method(object({
12980
12820
  }), method(SubscribeAudioChunksInputSchema, SubscribeAudioChunksResultSchema, { kind: "mutation" }), method(object({
12981
12821
  subscriptionId: string(),
12982
12822
  maxCount: number().int().positive().default(8)
12983
- }), array(DecodedAudioChunkSchema).readonly()), method(object({ subscriptionId: string() }), object({ released: boolean() }), { kind: "mutation" }), method(SubscribeFramesInputSchema, SubscribeFramesResultSchema, { kind: "mutation" }), method(object({
12984
- subscriptionId: string(),
12985
- maxCount: number().int().positive().default(4)
12986
- }), array(FrameHandleSchema).readonly()), method(object({ subscriptionId: string() }), object({ released: boolean() }), { kind: "mutation" }), method(object({
12823
+ }), array(DecodedAudioChunkSchema).readonly()), method(object({ subscriptionId: string() }), object({ released: boolean() }), { kind: "mutation" }), method(object({
12987
12824
  brokerId: string(),
12988
12825
  seconds: number().min(0).max(30)
12989
12826
  }), _void(), {
@@ -14140,54 +13977,12 @@ id: union([string(), number()]) }), {
14140
13977
  kind: "mutation",
14141
13978
  auth: "admin"
14142
13979
  });
14143
- /**
14144
- * shm ring usage stats for a `frameSink: 'shm'` decoder session —
14145
- * exposed via `decoder.getShmStats` so downstream consumers can
14146
- * observe ring pressure (slot count, byte budget, hit/miss ratio).
14147
- */
14148
- var ShmRingStatsSchema = object({
14149
- sessionId: string(),
14150
- slotCount: number().int(),
14151
- slotByteLength: number().int(),
14152
- segmentBytes: number().int(),
14153
- budgetMb: number().int(),
14154
- framesWritten: number().int(),
14155
- getFrameHits: number().int(),
14156
- getFrameMisses: number().int()
14157
- });
14158
- method(object({ codec: string() }), boolean()), method(_void(), object({
13980
+ method(_void(), object({
14159
13981
  id: string(),
14160
13982
  name: string(),
14161
- isPullMode: boolean().optional(),
14162
- priority: number().optional(),
14163
13983
  hwaccel: string().optional(),
14164
13984
  probedBestHwaccel: string().optional()
14165
- })), method(DecoderSessionConfigSchema, object({
14166
- sessionId: string(),
14167
- nodeId: string()
14168
- })), method(object({ sessionId: string() }), _void()), method(object({
14169
- sessionId: string(),
14170
- packet: EncodedPacketSchema
14171
- }), _void()), method(object({
14172
- sessionId: string(),
14173
- url: string()
14174
- }), _void()), method(object({
14175
- sessionId: string(),
14176
- maxCount: number().default(1),
14177
- waitMs: number().optional()
14178
- }), array(DecodedFrameSchema)), method(object({
14179
- sessionId: string(),
14180
- maxCount: number().default(1),
14181
- waitMs: number().optional()
14182
- }), array(FrameHandleSchema)), method(object({ handle: FrameHandleSchema }), DecodedFrameSchema.nullable()), method(object({ sessionId: string() }), ShmRingStatsSchema.nullable()), method(object({
14183
- sessionId: string(),
14184
- config: DecoderSessionConfigSchema.partial()
14185
- }), _void()), method(object({ sessionId: string() }), DecoderStatsSchema), method(_void(), array(object({
14186
- sessionId: string(),
14187
- codec: string(),
14188
- outputFormat: string(),
14189
- createdAtMs: number()
14190
- })).readonly()), method(_void(), object({ backend: string() }), {
13985
+ })), method(_void(), object({ backend: string() }), {
14191
13986
  kind: "mutation",
14192
13987
  auth: "admin"
14193
13988
  });
@@ -21207,8 +21002,8 @@ Object.freeze(Object.fromEntries([{
21207
21002
  var CLUSTER_STEP_SETTING_FIELDS = [{
21208
21003
  stepId: "face-embedding",
21209
21004
  key: "minLandmarkFaceSize",
21210
- label: "Min face size for recognition (detection px)",
21211
- description: "Refuse to embed a face smaller than this IN THE DETECTION FRAME. Applies to every node — the enrolled gallery is one index, and two admission floors would fill it from two policies. 0 disables the gate.",
21005
+ label: "Min face size to embed (detection-frame px)",
21006
+ description: "Faces smaller than this in the small frame the detector sees are not embedded, so they can never be recognised. Below it the face cannot be aligned reliably and a bad embedding matches everyone. Same value on every node. 0 = no limit.",
21212
21007
  type: "slider",
21213
21008
  min: 0,
21214
21009
  max: 64,
@@ -24881,14 +24676,15 @@ var RunnerLocalLoadSchema = object({
24881
24676
  * Per-inference-device live load (multi-device C4). One entry per deviceKey
24882
24677
  * this runner currently has attached cameras on, so the orchestrator's second
24883
24678
  * `balance()` pass (over a node's devices) weights on real per-pool session
24884
- * counts. Empty on single-device / pre-multi-device runners. `queueDepthTotal`
24885
- * per device is 0 until the pool backlog gets a public accessor (follow-up).
24679
+ * counts. Empty on single-device / pre-multi-device runners. There is no
24680
+ * per-device queue depth: the inference pool's backlog has no accessor, and
24681
+ * a field that always read 0 was removed rather than shown as a measurement
24682
+ * (D762).
24886
24683
  */
24887
24684
  devices: array(object({
24888
24685
  deviceKey: string(),
24889
24686
  backend: string(),
24890
- attachedCameras: number(),
24891
- queueDepthTotal: number()
24687
+ attachedCameras: number()
24892
24688
  })).default([]),
24893
24689
  /** Hardware capability flags reported by this node. */
24894
24690
  hardware: object({
@@ -25211,7 +25007,10 @@ var PipelineAssignmentSchema = object({
25211
25007
  });
25212
25008
  /**
25213
25009
  * Per-agent load summary surfaced to the load balancer + dashboards.
25214
- * Aggregated from each runner's `getLocalLoad` cap call.
25010
+ * Aggregated from each runner's `getLocalLoad` cap call. In the
25011
+ * `getAgentLoad` report, a single-device node's default-pool sessions (no
25012
+ * `deviceKey`) are credited to its one eligible device in `load.devices` —
25013
+ * the default pool IS that device (D745); the balancer's census stays raw.
25215
25014
  */
25216
25015
  var AgentLoadSummarySchema = object({
25217
25016
  nodeId: string(),
@@ -25300,8 +25099,14 @@ var CameraBrokerStatusSchema = object({
25300
25099
  width: number(),
25301
25100
  height: number(),
25302
25101
  subscribers: number(),
25303
- inFps: number(),
25304
- outFps: number()
25102
+ /**
25103
+ * Encoded packets/s the broker receives from the camera. null when the
25104
+ * broker's stats read failed — unknown, never 0 (a 0 here reads as a stall).
25105
+ * There is no output rate: decoding runs in the session decode workers, not
25106
+ * in the broker, so the broker's own decoded-frame rate is 0 on every live
25107
+ * camera and is not served (D758).
25108
+ */
25109
+ inFps: number().nullable()
25305
25110
  })).readonly(),
25306
25111
  webrtcSessions: number(),
25307
25112
  rtspRestream: boolean()
@@ -27987,8 +27792,6 @@ var WebrtcStreamChoiceSchema = object({
27987
27792
  ]).nullable(),
27988
27793
  /** Input FPS from the camera (null for adaptive). */
27989
27794
  inputFps: number().nullable(),
27990
- /** Decoded FPS (null for adaptive). */
27991
- decodeFps: number().nullable(),
27992
27795
  /** Bitrate in kbps (null for adaptive). */
27993
27796
  bitrateKbps: number().nullable()
27994
27797
  });
@@ -38123,90 +37926,18 @@ Object.freeze({
38123
37926
  addonId: null,
38124
37927
  access: "create"
38125
37928
  },
38126
- "decoder.createSession": {
38127
- capName: "decoder",
38128
- capScope: "system",
38129
- addonId: null,
38130
- access: "view"
38131
- },
38132
- "decoder.destroySession": {
38133
- capName: "decoder",
38134
- capScope: "system",
38135
- addonId: null,
38136
- access: "delete"
38137
- },
38138
- "decoder.getFrame": {
38139
- capName: "decoder",
38140
- capScope: "system",
38141
- addonId: null,
38142
- access: "view"
38143
- },
38144
37929
  "decoder.getInfo": {
38145
37930
  capName: "decoder",
38146
37931
  capScope: "system",
38147
37932
  addonId: null,
38148
37933
  access: "view"
38149
37934
  },
38150
- "decoder.getShmStats": {
38151
- capName: "decoder",
38152
- capScope: "system",
38153
- addonId: null,
38154
- access: "view"
38155
- },
38156
- "decoder.getStats": {
38157
- capName: "decoder",
38158
- capScope: "system",
38159
- addonId: null,
38160
- access: "view"
38161
- },
38162
- "decoder.listActiveSessions": {
38163
- capName: "decoder",
38164
- capScope: "system",
38165
- addonId: null,
38166
- access: "view"
38167
- },
38168
- "decoder.openStream": {
38169
- capName: "decoder",
38170
- capScope: "system",
38171
- addonId: null,
38172
- access: "view"
38173
- },
38174
- "decoder.pullFrames": {
38175
- capName: "decoder",
38176
- capScope: "system",
38177
- addonId: null,
38178
- access: "view"
38179
- },
38180
- "decoder.pullHandles": {
38181
- capName: "decoder",
38182
- capScope: "system",
38183
- addonId: null,
38184
- access: "view"
38185
- },
38186
- "decoder.pushPacket": {
38187
- capName: "decoder",
38188
- capScope: "system",
38189
- addonId: null,
38190
- access: "view"
38191
- },
38192
37935
  "decoder.reprobeHwaccel": {
38193
37936
  capName: "decoder",
38194
37937
  capScope: "system",
38195
37938
  addonId: null,
38196
37939
  access: "create"
38197
37940
  },
38198
- "decoder.supportsCodec": {
38199
- capName: "decoder",
38200
- capScope: "system",
38201
- addonId: null,
38202
- access: "view"
38203
- },
38204
- "decoder.updateConfig": {
38205
- capName: "decoder",
38206
- capScope: "system",
38207
- addonId: null,
38208
- access: "view"
38209
- },
38210
37941
  "detectionPipeline.applyDeviceSettingsPatch": {
38211
37942
  capName: "detection-pipeline",
38212
37943
  capScope: "device",
@@ -43253,12 +42984,6 @@ Object.freeze({
43253
42984
  addonId: null,
43254
42985
  access: "view"
43255
42986
  },
43256
- "streamBroker.pullFrameHandles": {
43257
- capName: "stream-broker",
43258
- capScope: "system",
43259
- addonId: null,
43260
- access: "view"
43261
- },
43262
42987
  "streamBroker.regenerateRtspToken": {
43263
42988
  capName: "stream-broker",
43264
42989
  capScope: "system",
@@ -43325,12 +43050,6 @@ Object.freeze({
43325
43050
  addonId: null,
43326
43051
  access: "create"
43327
43052
  },
43328
- "streamBroker.subscribeFrames": {
43329
- capName: "stream-broker",
43330
- capScope: "system",
43331
- addonId: null,
43332
- access: "create"
43333
- },
43334
43053
  "streamBroker.unassignProfile": {
43335
43054
  capName: "stream-broker",
43336
43055
  capScope: "system",
@@ -43343,12 +43062,6 @@ Object.freeze({
43343
43062
  addonId: null,
43344
43063
  access: "create"
43345
43064
  },
43346
- "streamBroker.unsubscribeFrames": {
43347
- capName: "stream-broker",
43348
- capScope: "system",
43349
- addonId: null,
43350
- access: "create"
43351
- },
43352
43065
  "streamCatalog.getCatalog": {
43353
43066
  capName: "stream-catalog",
43354
43067
  capScope: "device",
@@ -45862,11 +45575,6 @@ Object.freeze({
45862
45575
  form: "single",
45863
45576
  optional: false
45864
45577
  }],
45865
- "decoder.createSession": [{
45866
- name: "deviceId",
45867
- form: "single",
45868
- optional: true
45869
- }],
45870
45578
  "detectionPipeline.applyDeviceSettingsPatch": [{
45871
45579
  name: "deviceId",
45872
45580
  form: "single",
@@ -49146,7 +48854,7 @@ var AdminUIAddon = class extends BaseAddon {
49146
48854
  capability: adminUiCapability,
49147
48855
  provider: {
49148
48856
  getStaticDir: async () => ({ staticDir: resolveAdminUiDistDir() }),
49149
- getVersion: async () => ({ version: "1.2.349" })
48857
+ getVersion: async () => ({ version: "1.2.350" })
49150
48858
  }
49151
48859
  }];
49152
48860
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@camstack/addon-admin-ui",
3
- "version": "1.2.349",
3
+ "version": "1.2.350",
4
4
  "private": false,
5
5
  "type": "module",
6
6
  "description": "Admin UI — Vite frontend build and server-side addon",
@@ -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{Z as d,gt as f,st as p,vt as m}from"./player-overlays-BddRivLE.js";import{Ar as h,Au as g,Br as _,Bu as v,Cr as y,Ct as b,Dr as x,Ed as S,Er as C,Fr as w,Hl as T,Hr as ee,I as te,Io as E,Ir as ne,K as re,Kl as D,Ku as ie,Lr as O,Lu as k,Mr as A,Nd as j,Nr as ae,Or as M,Ou as N,Qn as oe,Rd as se,Rr as P,Sr as F,St as ce,Tr as le,Ud as I,Uu as L,Vd as ue,Vr as de,br as fe,iu as R,jr as z,ju as pe,rd as B,wr as me,xu as V,zl as H}from"./src-DnQxdAYg.js";import{ni as U}from"./client-BVesZTvN.js";import"./mount-Br0xkUVQ.js";import{F as he,N as ge}from"./index-NHwA6Zmb.js";import{t as W}from"./AdminPage-CiKtOLQm.js";import{t as _e}from"./NodeAddonsSettingsPanel-D7Ope1My.js";import{r as G,t as K}from"./useNodeUrlSelection-BDv33pGy.js";var q=m(`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`}]]);n();var J=new Set([`completed`,`failed`,`partially-failed`,`cancelled`]),ve=new Set([`done`,`failed`,`skipped`]);function Y(e){return!ve.has(e.phase)&&!J.has(e.jobState)}function X(e,t){let n=new Map,r=[...e].sort((e,t)=>e.createdAtMs-t.createdAtMs);for(let e of r){let r=J.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 Z(){let{data:e}=h({activeOnly:!0},{refetchOnWindowFocus:!1,refetchInterval:e=>(e.state.data?.length??0)>0?3e3:!1}),{map:t}=T(U.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 X([...n.values()],Date.now())},[e,t])}var ye={queued:{icon:j,cls:`bg-muted text-foreground-subtle`,label:`queued`},fetching:{icon:B,cls:`bg-primary/10 text-primary`,label:`fetching`,spin:!0},staged:{icon:B,cls:`bg-primary/10 text-primary`,label:`staged`,spin:!0},validating:{icon:B,cls:`bg-primary/10 text-primary`,label:`validating`,spin:!0},applying:{icon:B,cls:`bg-primary/10 text-primary`,label:`applying`,spin:!0},restarting:{icon:B,cls:`bg-amber-500/10 text-amber-600 dark:text-amber-400`,label:`restarting`,spin:!0},applied:{icon:B,cls:`bg-primary/10 text-primary`,label:`finalizing`,spin:!0},done:{icon:I,cls:`bg-success/10 text-success`,label:`updated`},failed:{icon:q,cls:`bg-danger/10 text-danger`,label:`failed`},skipped:{icon:V,cls:`bg-muted text-foreground-subtle`,label:`skipped`}};function be({progress:e}){let t=ye[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 xe({packageName:e,currentVersion:t,installSource:n,onInstall:r,onClose:a,onSelect:s,selectedVersion:c}){let u=n===`upload`||n===`local`,{data:d,isLoading:f}=C({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(D,{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(R,{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(B,{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(I,{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(I,{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(S,{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 Se={queued:{icon:j,bg:`bg-muted text-foreground-subtle`,label:`queued`},updating:{icon:B,bg:`bg-primary/10 text-primary`,label:`updating`,spin:!0},"done-pending-restart":{icon:k,bg:`bg-amber-500/10 text-amber-700`,label:`pending restart`},done:{icon:I,bg:`bg-success/10 text-success`,label:`done`},failed:{icon:q,bg:`bg-danger/10 text-danger`,label:`failed`}};function Q({item:e}){let t=Se[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 Ce=`device-export`;function we(e){return e.capabilities.some(e=>(typeof e==`string`?e:e.name)===Ce)}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,f=e?`bg-indigo-500/20 text-indigo-700 dark:text-indigo-300`:`bg-purple-500/20 text-purple-700 dark:text-purple-300`,p=n&&r?d(`/api/addon-assets/${n}/${r}`):null,m=!!p&&!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?``:f}`,style:u,children:m?l(`img`,{src:p,alt:n,className:`h-5 w-5`,onError:()=>s(!0)}):l(e?ie:v,{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(R,{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(B,{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(S,{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`}=y({addonId:e}),r=O({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:d,isUpdating:m,jobProgress:h,bundle:g,bulkItem:_,disabledByBulk:v,isSystem:y}){let[S,C]=c(!1),[T,ee]=c(!1),[te,E]=c(!1),[ne,O]=c(null);u(()=>{O(null)},[a]);let A=ne??a,[j,M]=c(!1),[se,P]=c(!1),[F,le]=c(`logs`),I=s(),fe=ge(),R=oe(),{manifest:z}=e,B=e.installedOn??[],me=!g&&!z.protected&&z.removable!==!1,V=!!g,H=g?.displayName??z.name,U=g?.packageName??z.packageName,he=g?.version??z.packageVersion??z.version,W=g?.installSource??e.installSource,G=g?g.bundle?.description??g.addons[0]?.manifest.description:z.description,K=de({onSuccess:()=>{I.invalidateQueries({queryKey:[[`addons`]]}),I.invalidateQueries({queryKey:[[`addonPages`]]}),I.invalidateQueries({queryKey:[[`capabilities`]]})}}),J=ae({onSuccess:()=>{I.invalidateQueries({queryKey:[[`addons`]]})}}),ve=x({onSuccess:()=>{I.invalidateQueries({queryKey:[[`addons`]]}),I.invalidateQueries({queryKey:[[`addonPages`]]}),I.invalidateQueries({queryKey:[[`capabilities`]]}),I.invalidateQueries({queryKey:[[`integrations`]]})}}),Y=w({onSuccess:()=>{I.invalidateQueries({queryKey:[[`addons`]]}),I.invalidateQueries({queryKey:[[`alerts`]]})}}),X=e.health,Z=X?.phase===`failed`&&!X.inGracePeriod,ye=Z&&X?.nextRetryAt&&!X.retrying;return i(`div`,{className:`rounded-lg border bg-surface overflow-hidden ${Z?`border-red-500/50`:`border-border`}`,children:[Z&&X&&i(`div`,{className:`bg-danger/10 border-b border-danger/30 px-4 py-2.5 flex items-start gap-2.5`,children:[l(q,{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 #`,X.retryCount,`)`]}),l(`div`,{className:`text-[11px] text-foreground mt-0.5 break-words font-mono`,children:X.lastError?.message??`Unknown error`}),ye&&X.nextRetryAt&&i(`div`,{className:`text-[10px] text-foreground-subtle mt-1`,children:[`Auto-retry at `,new Date(X.nextRetryAt).toLocaleTimeString()]})]}),i(`button`,{type:`button`,disabled:Y.isPending||X.retrying,onClick:e=>{e.stopPropagation(),Y.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(k,{className:`h-3 w-3 ${Y.isPending||X.retrying?`animate-spin`:``}`}),`Retry now`]})]}),i(`div`,{className:`flex items-start gap-3 px-4 py-3`,children:[l(Te,{isBundle:V||!!z.components&&z.components.length>1,installSource:W,addonId:V?g.addons[0]?.manifest.id:z.id,iconPath:V?g.bundle?.icon??g.addons[0]?.manifest.icon:z.icon,color:V?g.addons[0]?.manifest.color:z.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:he,availableUpdate:a,...A===void 0?{}:{selectedVersion:A},isUpdating:m,installSource:W,disabled:v,...d&&A!==void 0?{onUpdate:()=>d(A)}:{},onOpenPicker:()=>E(e=>!e),children:te&&l(xe,{packageName:U,currentVersion:he,...W?{installSource:W}:{},...a!==void 0&&A!==void 0?{selectedVersion:A,onSelect:e=>{O(e),E(!1)}}:{},onInstall:e=>{E(!1),ve.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}),V&&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(ie,{className:`h-3 w-3`}),g.addons.length]}),y&&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(k,{className:`h-3 w-3`}),`System`]}),_!=null&&l(Q,{item:_}),h!=null&&l(be,{progress:h})]}),G&&l(`p`,{className:`text-[10px] text-foreground-subtle mt-1 line-clamp-1`,children:G}),!V&&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})]})]})]}),!V&&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(),J.mutate({addonId:z.id})},disabled:J.isPending||v,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(k,{className:`h-3 w-3 ${J.isPending?`animate-spin`:``}`}),`Restart`]}),i(`button`,{type:`button`,onClick:e=>{e.stopPropagation(),M(e=>!e)},className:`inline-flex items-center gap-1 rounded-md px-2 py-1 text-[10px] font-medium border transition-colors ${j?`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(pe,{className:`h-3 w-3`}),`Logs`]}),!V&&i(`button`,{type:`button`,onClick:e=>{e.stopPropagation(),P(!0)},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(N,{className:`h-3 w-3`}),`Settings`]}),l(`div`,{className:`flex-1`}),me&&i(`button`,{type:`button`,onClick:async e=>{e.stopPropagation(),await R({title:`Uninstall ${z.name}?`,message:`This will remove the addon package and all its data. This action cannot be undone.`,confirmLabel:`Uninstall`,variant:`danger`})&&K.mutate({packageName:z.packageName})},disabled:K.isPending||v,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(p,{className:`h-3 w-3`}),K.isPending?`Removing...`:`Uninstall`]})]}),n&&n.nodes.length>1&&!V&&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))})]}),j&&!V&&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:()=>le(`logs`),className:`px-2 py-0.5 transition-colors ${F===`logs`?`bg-primary/10 text-primary`:`text-foreground-subtle hover:bg-surface-hover`}`,children:`Logs`}),l(`button`,{type:`button`,onClick:()=>le(`events`),className:`px-2 py-0.5 border-l border-border transition-colors ${F===`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(),M(!1)},className:`text-foreground-subtle hover:text-foreground`,children:l(D,{className:`h-3.5 w-3.5`})})]}),F===`logs`&&l(b,{addonId:z.id,maxHeight:`max-h-64`,showFilters:!1}),F===`events`&&l(ce,{addonId:z.id,category:`addon.*`,maxHeight:`max-h-64`})]}),V&&i(o,{children:[l(`button`,{type:`button`,onClick:()=>C(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(S?ue:f,{className:`h-3.5 w-3.5 text-foreground-subtle`})}),S&&l(`div`,{className:`border-t border-border px-3 py-2 space-y-2`,children:g.addons.map(e=>l(Oe,{addon:e,agents:t,hideVersion:!0},e.manifest.id))})]}),se&&!V&&l(`div`,{className:`fixed inset-0 z-50 flex items-center justify-center bg-black/60 backdrop-blur-sm p-4`,onClick:()=>P(!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(N,{className:`h-4 w-4 text-primary`}),i(`h2`,{className:`text-sm font-semibold text-foreground`,children:[H,` Settings`]})]}),l(`button`,{onClick:()=>P(!1),className:`text-foreground-subtle hover:text-foreground transition-colors p-1 rounded`,children:l(D,{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(_e,{nodeId:null,addonIds:[z.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(z)&&i(`div`,{children:[l(`div`,{className:`text-[10px] font-medium text-foreground-subtle uppercase tracking-wide mb-2`,children:`Device export`}),l(re,{addonId:z.id,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:z.id})]}),z.components&&z.components.length>0&&i(`div`,{children:[i(`div`,{className:`text-[10px] font-medium text-foreground-subtle uppercase tracking-wide mb-2`,children:[`Components (`,z.components.length,`)`]}),l(`div`,{className:`flex flex-wrap gap-1`,children:z.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:[B.length===0&&l(`span`,{className:`text-[10px] text-foreground-subtle`,children:`Hub (local)`}),B.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(),ee(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(L,{className:`h-3 w-3`}),`Add agent`]}),T&&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&&!B.includes(e.name)).map(e=>l(`button`,{type:`button`,onClick:e=>{e.stopPropagation(),ee(!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&&!B.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:()=>P(!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(d(`/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(B,{className:`w-3.5 h-3.5 animate-spin`}):l(R,{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(),[h,v]=c(``),y=r(h),[b,C]=c(!1),w=t(null);u(()=>{if(!b)return;let e=e=>{w.current&&!w.current.contains(e.target)&&C(!1)};return document.addEventListener(`mousedown`,e),()=>document.removeEventListener(`mousedown`,e)},[b]);let{data:T}=z({nodeId:d.id}),te=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]),[re,D]=c(()=>new Set),[ie,O]=c(()=>new Map),A=e(e=>{D(t=>new Set(t).add(e))},[]),j=e(e=>{D(t=>{if(!t.has(e))return t;let n=new Set(t);return n.delete(e),n})},[]),ae=e((e,t)=>{O(n=>new Map(n).set(e,t))},[]),M=e(e=>{O(t=>{if(!t.has(e))return t;let n=new Map(t);return n.delete(e),n})},[]),N=ee({onMutate:e=>{A(e.name),M(e.name)},onSuccess:(e,t)=>{j(t.name);let n=e;if(n&&n.success===!1){ae(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)=>{j(t.name),ae(t.name,e instanceof Error?e.message:String(e))}}),F=Z(),ce=t(new Set);u(()=>{let e=new Set;for(let[t,n]of F)Y(n)&&e.add(t);let t=[...ce.current].some(t=>!e.has(t));ce.current=e,t&&(m.invalidateQueries({queryKey:[[`addons`]]}),m.invalidateQueries({queryKey:[[`addons`,`listUpdates`]]}))},[F,m]);let{data:L}=me(void 0),ue=fe({onSuccess:()=>{m.invalidateQueries({queryKey:[[`addons`,`getAutoUpdateSettings`]]})}}),de=P({onSuccess:()=>{m.invalidateQueries({queryKey:[[`addons`,`getAutoUpdateSettings`]]})}}),{data:R,isFetching:pe}=ne({query:y||void 0},{enabled:b}),V=_(),{data:H}=le(void 0),U=H?.requestedAt,[ge,W]=c(null),[_e,G]=c(!1);u(()=>{if(H?.kind===`framework-bulk-update`&&H.requestedAt!==ge){W(H.requestedAt),G(!0);let e=window.setTimeout(()=>G(!1),6e3);return()=>window.clearTimeout(e)}},[U,ge,H]),oe();let K=e(async()=>{let e=(T??[]).filter(e=>!e.isSystem);if(e.length!==0){if(!d.isHub){for(let t of e)await N.mutateAsync({name:t.name,version:t.latestVersion,nodeId:d.id});return}await V.mutateAsync({kind:`update`,targets:e.map(e=>({name:e.name,version:e.latestVersion})),nodeIds:[d.id]})}},[T,d.id,d.isHub,V,N]),q=x({onSuccess:()=>{m.invalidateQueries({queryKey:[[`addons`]]}),m.invalidateQueries({queryKey:[[`addonPages`]]}),m.invalidateQueries({queryKey:[[`capabilities`]]}),m.invalidateQueries({queryKey:[[`integrations`]]})}}),[J,ve]=c(`type`),[X,ye]=c(()=>typeof window>`u`?`grouped`:window.localStorage.getItem(`camstack.addons.viewMode`)===`flat`?`flat`:`grouped`),be=e=>{ye(e),typeof window<`u`&&window.localStorage.setItem(`camstack.addons.viewMode`,e)},[xe,Se]=he(),Q=xe.get(`capability`),Ce=a(()=>{let e=n.filter(e=>!Ne(e.manifest.packageName));return d.isHub||(e=e.filter(e=>Fe(e.placement,d.isHub))),Q&&(e=e.filter(e=>(e.manifest.capabilities??[]).some(e=>(typeof e==`string`?e:e.name)===Q))),e},[n,d.isHub,Q]),we=()=>{let e=new URLSearchParams(xe);e.delete(`capability`),Se(e,{replace:!0})},Te=X===`flat`?Ce:Le(Ce),Ee=a(()=>{let e=[...Te];switch(J){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,J]);return i(`div`,{className:`space-y-4`,children:[[...ie.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:()=>M(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:J,onChange:e=>ve(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:()=>be(e),className:`px-2.5 py-1.5 transition-colors capitalize ${X===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(k,{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:()=>ue.mutate({channel:e}),disabled:ue.isPending,className:`px-2.5 py-1.5 transition-colors capitalize ${L?.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:L?.updateCheckIntervalSeconds??21600,disabled:de.isPending||L===void 0,onChange:e=>{L!==void 0&&de.mutate({channel:L.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 K(),disabled:V.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:[V.isPending?l(B,{className:`w-3 h-3 animate-spin`}):l(S,{className:`w-3 h-3`}),V.isPending?`Updating…`:`Update All (${E})`]}),i(`button`,{type:`button`,onClick:f,disabled:p||V.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(k,{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:w,children:[l(g,{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:h,onChange:e=>{v(e.target.value),C(!0)},onFocus:()=>C(!0),placeholder:`Search addons on npm...`,disabled:V.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`}),pe&&l(B,{className:`absolute right-2.5 top-1/2 -translate-y-1/2 h-3 w-3 text-foreground-subtle animate-spin`}),b&&R&&R.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:[R.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 (`,R.length,`)`]}),R&&R.length>0&&l(`div`,{className:`max-h-72 overflow-auto divide-y divide-border`,children:R.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(I,{className:`h-3 w-3`}),e.installedVersion??`Installed`]}):i(`button`,{type:`button`,onClick:()=>q.mutate({packageName:e.name}),disabled:q.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:[q.isPending?l(B,{className:`h-3 w-3 animate-spin`}):l(S,{className:`h-3 w-3`}),`Install`]})]},e.name))})]})]}),l(Ae,{onUploadSuccess:()=>{m.invalidateQueries({queryKey:[[`addons`]]}),f()}})]}),Q&&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:Q}),l(`button`,{type:`button`,onClick:we,className:`ml-auto text-xs text-foreground-subtle hover:text-foreground underline`,children:`Clear`})]}),_e&&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(se,{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.`})]})]}),Ce.length===0&&l(`div`,{className:`text-xs text-foreground-subtle`,children:n.length===0?`No addons installed`:Q?`No installed addons declare the "${Q}" 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=te.get(t),r=$(e)?e.representative:e,i=n?e=>N.mutate({name:t,version:e,nodeId:d.id}):void 0,a=F.get(t)??null,s=a!==null&&Y(a);return l(Oe,{addon:r,clusterStatus:o?.[r.manifest.id],bundle:$(e)?e.bundle:void 0,availableUpdate:n,isUpdating:re.has(t)||s,jobProgress:a,onUpdate:i,disabledByBulk:V.isPending},$(e)?t:e.manifest.id)})})]})}function ze(){let e=s(),{data:n,isLoading:r,isError:a}=M(),{data:o}=E(void 0),{nodes:c}=H(),{selection:d,selectNode:f,requestedNodeId:p}=K(c.length>0?c:[Pe]),m=d.node??Pe,h=m.id,g=c.length>0?d.staleNodeId:null,_=F(),v=A(),y=_.isPending||v.isPending,b=async()=>{await _.mutateAsync({nodeId:h}),await v.mutateAsync(),e.invalidateQueries({queryKey:[[`addons`]]})},x=t(_);x.current=_;let S=t(p??`hub`);u(()=>{x.current.mutate({nodeId:S.current})},[]);let C=(n??[]).map(Ie).filter(e=>e!==null);return i(W,{children:[i(`div`,{className:`flex items-center justify-between gap-3 flex-wrap`,children:[l(te,{selectedNodeId:h,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:[C.length,` installed`]}),i(`button`,{type:`button`,onClick:()=>void b(),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(k,{className:`w-3 h-3 ${y?`animate-spin`:``}`}),`Check for updates`]})]})]}),l(G,{staleNodeId:g,shownNodeName:m.name}),!m.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:m.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:C,clusterStatus:o,selectedNode:m,onRefresh:()=>void b(),isRefreshing:y})]})}export{ze as AddonsPage};