@camstack/addon-admin-ui 1.0.4 → 1.0.6

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 (85) hide show
  1. package/dist/assets/{AddLocationWizard-D6tk8U-w.js → AddLocationWizard-CukR7cTF.js} +1 -1
  2. package/dist/assets/{AddonCollectionPage-CPQWZfC0.js → AddonCollectionPage-DJx4uU6r.js} +1 -1
  3. package/dist/assets/Addons-CH-apJRX.js +1 -0
  4. package/dist/assets/{AdminTabs-Ddi8-SQJ.js → AdminTabs-BpXprAan.js} +1 -1
  5. package/dist/assets/{BrokerForm-Jzl9BAMO.js → BrokerForm-BHHqkVQb.js} +1 -1
  6. package/dist/assets/{BrokerStep-vbWWE4ss.js → BrokerStep-Cok3AhHx.js} +1 -1
  7. package/dist/assets/{Capabilities-GrzalIOH.js → Capabilities-C7ZtET2s.js} +1 -1
  8. package/dist/assets/{CapabilityBadges-BN0gXK4w.js → CapabilityBadges-CMb2KZ75.js} +1 -1
  9. package/dist/assets/Cluster-Dv4qNomn.js +1 -0
  10. package/dist/assets/{Dashboard-Dl3BUDju.js → Dashboard-DJM813RT.js} +1 -1
  11. package/dist/assets/{Data-DJn-KYZI.js → Data-DGhOO-Cu.js} +1 -1
  12. package/dist/assets/{DetectionIntelligence-BhQAT1WX.js → DetectionIntelligence-hx5aK8kV.js} +1 -1
  13. package/dist/assets/DeviceDetail-Cy3oT8kc.js +2 -0
  14. package/dist/assets/{Devices-D_zVs1PC.js → Devices-CUWOXRHi.js} +1 -1
  15. package/dist/assets/{EmbedPlayerPage-BjQGYATU.js → EmbedPlayerPage-DWa8--dX.js} +1 -1
  16. package/dist/assets/{FormBuilder-BXQEmfaE.js → FormBuilder-D1P2uZCo.js} +1 -1
  17. package/dist/assets/{Identity-ZvlfZz_A.js → Identity-Be25Wd9m.js} +1 -1
  18. package/dist/assets/IntegrationDetail-BH3qKiFl.js +1 -0
  19. package/dist/assets/{Integrations-CsaOfFWR.js → Integrations-5qRDDBvi.js} +1 -1
  20. package/dist/assets/{Integrations-Bv07bA7c.js → Integrations-D2GJn2wx.js} +1 -1
  21. package/dist/assets/{Logs-DBoE5z_U.js → Logs-CJvGn4d5.js} +1 -1
  22. package/dist/assets/{MotionZonesSettings-CepMSlXn.js → MotionZonesSettings-CrSbCbyo.js} +1 -1
  23. package/dist/assets/{MyAccess-Bp5Cp_C6.js → MyAccess-C70LOUlA.js} +1 -1
  24. package/dist/assets/Network-KGBDHmKd.js +1 -0
  25. package/dist/assets/{NodeAddonsSettingsPanel-9HVgS_gw.js → NodeAddonsSettingsPanel-DZOqqqZZ.js} +1 -1
  26. package/dist/assets/Pipeline-B4MQZJjm.js +1 -0
  27. package/dist/assets/{PrivacyMaskSettings-Cl0lj_PR.js → PrivacyMaskSettings-Btjy009a.js} +1 -1
  28. package/dist/assets/{ProviderIcon-DWSMqwcl.js → ProviderIcon-BPXhRQ1d.js} +1 -1
  29. package/dist/assets/{Settings-ayyuAbCz.js → Settings-BBKIvACs.js} +1 -1
  30. package/dist/assets/{Showroom-CQ1h4YKK.js → Showroom-D6AoJdZW.js} +1 -1
  31. package/dist/assets/{_virtual_mf-localSharedImportMap___mfe_internal__admin_ui_host-CS4OeMKk.js → _virtual_mf-localSharedImportMap___mfe_internal__admin_ui_host-DYMHJcwg.js} +1 -1
  32. package/dist/assets/{bell-C9HUnDGC.js → bell-DUIEkGPA.js} +1 -1
  33. package/dist/assets/circle-check-big-BjqV4p1D.js +1 -0
  34. package/dist/assets/{copy-BtC330Ic.js → copy-DUY8-DBe.js} +1 -1
  35. package/dist/assets/dist-BwRNbXT1.js +1 -0
  36. package/dist/assets/{dist-mzJ_Pmak.js → dist-Dw4iYpIy.js} +1 -1
  37. package/dist/assets/{download-CEQQi2pw.js → download-B3pGiRsg.js} +1 -1
  38. package/dist/assets/esm-CR7fS4E6.js +7 -0
  39. package/dist/assets/{hostInit-Y3VsYAf_.js → hostInit-DJmAUuWj.js} +1 -1
  40. package/dist/assets/index-CBUhNGng.js +4 -0
  41. package/dist/assets/index-D5fms8eH.css +2 -0
  42. package/dist/assets/{key-round-C1aQCNHE.js → key-round-BtVEvNiB.js} +1 -1
  43. package/dist/assets/{mf-entry-bootstrap-0-3e98f17f.js → mf-entry-bootstrap-0-50a30526.js} +2 -2
  44. package/dist/assets/{pencil-Dw6owGVy.js → pencil-BHXuzoZT.js} +1 -1
  45. package/dist/assets/{player-overlays-DzZKARlk.js → player-overlays-B1rOp2K0.js} +1 -1
  46. package/dist/assets/plus-CljwKCLZ.js +1 -0
  47. package/dist/assets/{radio-CyBw1Cvj.js → radio-BrSbZ3Gz.js} +1 -1
  48. package/dist/assets/{refresh-cw-CPqFoliO.js → refresh-cw-9auw5j71.js} +1 -1
  49. package/dist/assets/remoteEntry-B0hADopi.js +1 -0
  50. package/dist/assets/{rotate-ccw-BJL6I3ju.js → rotate-ccw-DeNzdz-v.js} +1 -1
  51. package/dist/assets/rotate-cw-anx2g3R_.js +1 -0
  52. package/dist/assets/search-BYve1v5o.js +1 -0
  53. package/dist/assets/{server-BgZ85UtO.js → server-Bj7As5DB.js} +1 -1
  54. package/dist/assets/{sparkles-Dj3mm_rJ.js → sparkles-BMTAprd6.js} +1 -1
  55. package/dist/assets/square-CondP2yo.js +1 -0
  56. package/dist/assets/{square-check-big-CMEqldHV.js → square-check-big-CPuMXqOw.js} +1 -1
  57. package/dist/assets/src-D-eMZfpa.js +34 -0
  58. package/dist/assets/src-DUWILaCU.js +1 -0
  59. package/dist/assets/{upload-tyMJOOSL.js → upload-BQ5R4JaW.js} +1 -1
  60. package/dist/assets/useDevice-mTj6eL8W.js +1 -0
  61. package/dist/assets/{useEventInvalidation-CqPABxEF.js → useEventInvalidation-BXdyfSQv.js} +1 -1
  62. package/dist/assets/{virtual_mf-REMOTE_ENTRY_ID___mfe_internal__admin_ui_host__remoteEntry-_hash_-B1bVOGqv.js → virtual_mf-REMOTE_ENTRY_ID___mfe_internal__admin_ui_host__remoteEntry-_hash_-BkXjP_sa.js} +2 -2
  63. package/dist/assets/{wifi-Do23YMj8.js → wifi-CV73GdWg.js} +1 -1
  64. package/dist/assets/{zap-CZ68wiP1.js → zap-Cc3-KiYB.js} +1 -1
  65. package/dist/index.html +6 -6
  66. package/dist/server/addon.js +316 -31
  67. package/package.json +1 -1
  68. package/dist/assets/Addons-BIu0hjHd.js +0 -1
  69. package/dist/assets/Cluster-zuSKpmeo.js +0 -7
  70. package/dist/assets/DeviceDetail-C16YaYd6.js +0 -2
  71. package/dist/assets/IntegrationDetail-Bnpn2hQ2.js +0 -1
  72. package/dist/assets/Network-Dyg7yTc_.js +0 -1
  73. package/dist/assets/Pipeline-DzZm2XqD.js +0 -1
  74. package/dist/assets/circle-check-big-BDdzTa9p.js +0 -1
  75. package/dist/assets/dist-CGRDjIOZ.js +0 -1
  76. package/dist/assets/index-CTiiXuB_.css +0 -2
  77. package/dist/assets/index-DuroU2aU.js +0 -4
  78. package/dist/assets/plus-CbaF5MYw.js +0 -1
  79. package/dist/assets/remoteEntry-BXtCFyvA.js +0 -1
  80. package/dist/assets/rotate-cw-DZGWB7EU.js +0 -1
  81. package/dist/assets/search-cFwrysqG.js +0 -1
  82. package/dist/assets/square-D-dTwz52.js +0 -1
  83. package/dist/assets/src-CqVYgpnN.js +0 -34
  84. package/dist/assets/src-CrhOk7JL.js +0 -1
  85. package/dist/assets/useDevice-DTk9eLX5.js +0 -1
@@ -4983,6 +4983,18 @@ var EventCategory = /* @__PURE__ */ function(EventCategory) {
4983
4983
  */
4984
4984
  EventCategory["PipelineEngineMetricsSnapshot"] = "pipeline.engine-metrics-snapshot";
4985
4985
  /**
4986
+ * Per-node detection-engine runtime-provisioning transition. Emitted by
4987
+ * the detection-pipeline provider on every state change of its lazy
4988
+ * engine-provisioning machine (idle → installing → verifying → ready,
4989
+ * or → failed with a `nextRetryAt`). Payload is the
4990
+ * `EngineProvisioningState` snapshot; `event.source.nodeId` carries the
4991
+ * node. The Pipeline page subscribes to drive a live "installing
4992
+ * OpenVINO… / ready" indicator per node without polling
4993
+ * `pipelineExecutor.getEngineProvisioning`. Telemetry-grade (D8): the UI
4994
+ * also reads the cap snapshot on mount / reconnect. Phase 2.
4995
+ */
4996
+ EventCategory["PipelineEngineProvisioning"] = "pipeline.engine-provisioning";
4997
+ /**
4986
4998
  * Cluster topology snapshot. Carries the same payload returned by
4987
4999
  * `nodes.topology` (every reachable node + addons + processes).
4988
5000
  * Emitted by the hub on any agent / addon lifecycle change
@@ -5132,14 +5144,15 @@ var EventCategory = /* @__PURE__ */ function(EventCategory) {
5132
5144
  EventCategory["DeviceSleeping"] = "device.sleeping";
5133
5145
  EventCategory["RetentionCleanup"] = "retention.cleanup";
5134
5146
  /**
5135
- * Progress snapshot emitted by `BulkUpdateCoordinator` on every state
5136
- * transition (item status change, phase change, completion, cancel).
5137
- * Payload is `BulkUpdateState`. Admin UI subscribes via `useLiveEvent`
5138
- * to drive the sticky `BulkUpdateBanner` and per-row `AddonRowBadge`.
5139
- *
5140
- * Spec: docs/superpowers/specs/2026-05-21-addons-bulk-update-progress-design.md
5147
+ * Legacy bulk-update progress snapshot (payload `BulkUpdateState`). No longer
5148
+ * emitted F3 removed the coordinator that produced it; "Update all" now runs
5149
+ * as one lifecycle engine job (`AddonsJobProgress`/`AddonsJobLog`). Retained
5150
+ * (with `BulkUpdateState`) only to avoid regenerating the event maps; removed
5151
+ * in F4 once live bulk progress is re-implemented over the engine events.
5141
5152
  */
5142
5153
  EventCategory["AddonsBulkUpdateProgress"] = "addons.bulk-update-progress";
5154
+ EventCategory["AddonsJobProgress"] = "addons.job-progress";
5155
+ EventCategory["AddonsJobLog"] = "addons.job-log";
5143
5156
  /**
5144
5157
  * A container's child visibility toggled (hidden/shown). Emitted by the
5145
5158
  * `accessories` cap when a child device is hidden or revealed.
@@ -9146,6 +9159,24 @@ var DetectorOutputSchema = object({
9146
9159
  inferenceMs: number(),
9147
9160
  modelId: string()
9148
9161
  });
9162
+ var EngineProvisioningSchema = object({
9163
+ runtimeId: _enum([
9164
+ "onnx",
9165
+ "openvino",
9166
+ "coreml"
9167
+ ]).nullable(),
9168
+ device: string().nullable(),
9169
+ state: _enum([
9170
+ "idle",
9171
+ "installing",
9172
+ "verifying",
9173
+ "ready",
9174
+ "failed"
9175
+ ]),
9176
+ progress: number().optional(),
9177
+ error: string().optional(),
9178
+ nextRetryAt: number().optional()
9179
+ });
9149
9180
  var PipelineStepInputSchema = lazy(() => object({
9150
9181
  addonId: string(),
9151
9182
  modelId: string(),
@@ -9214,7 +9245,7 @@ var PipelineRunResultBridge = custom();
9214
9245
  method(_void(), array(PipelineEngineChoiceSchema)), method(_void(), PipelineEngineChoiceSchema), method(PipelineEngineChoiceSchema, array(PipelineDefaultStepSchema)), method(_void(), PipelineEngineChoiceSchema, {
9215
9246
  kind: "mutation",
9216
9247
  auth: "admin"
9217
- }), method(_void(), record(string(), object({
9248
+ }), method(object({ nodeId: string() }), EngineProvisioningSchema), method(_void(), record(string(), object({
9218
9249
  modelId: string(),
9219
9250
  settings: record(string(), unknown()).readonly()
9220
9251
  }))), method(object({ steps: record(string(), object({
@@ -12810,7 +12841,10 @@ var AgentAddonConfigSchema = object({
12810
12841
  modelId: string(),
12811
12842
  settings: record(string(), unknown()).readonly()
12812
12843
  });
12813
- var AgentPipelineSettingsSchema = object({ addonDefaults: record(string(), AgentAddonConfigSchema).readonly() });
12844
+ var AgentPipelineSettingsSchema = object({
12845
+ addonDefaults: record(string(), AgentAddonConfigSchema).readonly(),
12846
+ maxCameras: number().int().nonnegative().nullable().default(null)
12847
+ });
12814
12848
  var CameraPipelineForAgentSchema = object({
12815
12849
  steps: array(PipelineStepInputSchema).readonly(),
12816
12850
  audio: object({
@@ -12912,6 +12946,133 @@ var GlobalMetricsSchema = object({
12912
12946
  * capability providers.
12913
12947
  */
12914
12948
  var CapabilityBindingsSchema = record(string(), string());
12949
+ /** Source block — always present; derives from the stream catalog. */
12950
+ var CameraSourceStatusSchema = object({ streams: array(object({
12951
+ camStreamId: string(),
12952
+ codec: string(),
12953
+ width: number(),
12954
+ height: number(),
12955
+ fps: number(),
12956
+ kind: string()
12957
+ })).readonly() });
12958
+ /** Assignment block — always present (orchestrator-local, no remote call). */
12959
+ var CameraAssignmentStatusSchema = object({
12960
+ detectionNodeId: string().nullable(),
12961
+ decoderNodeId: string().nullable(),
12962
+ audioNodeId: string().nullable(),
12963
+ pinned: object({
12964
+ detection: boolean(),
12965
+ decoder: boolean(),
12966
+ audio: boolean()
12967
+ }),
12968
+ reasons: object({
12969
+ detection: string().optional(),
12970
+ decoder: string().optional(),
12971
+ audio: string().optional()
12972
+ })
12973
+ });
12974
+ /** Broker block — null when the broker stage is unreachable or inactive. */
12975
+ var CameraBrokerStatusSchema = object({
12976
+ profiles: array(object({
12977
+ profile: string(),
12978
+ status: string(),
12979
+ codec: string(),
12980
+ width: number(),
12981
+ height: number(),
12982
+ subscribers: number(),
12983
+ inFps: number(),
12984
+ outFps: number()
12985
+ })).readonly(),
12986
+ webrtcSessions: number(),
12987
+ rtspRestream: boolean()
12988
+ });
12989
+ /** Shared-memory ring statistics within the decoder block. */
12990
+ var CameraDecoderShmSchema = object({
12991
+ framesWritten: number(),
12992
+ getFrameHits: number(),
12993
+ getFrameMisses: number(),
12994
+ budgetMb: number()
12995
+ });
12996
+ /** Decoder block — null when the decoder stage is unreachable or inactive. */
12997
+ var CameraDecoderStatusSchema = object({
12998
+ nodeId: string(),
12999
+ formats: array(string()).readonly(),
13000
+ sessionCount: number(),
13001
+ shm: CameraDecoderShmSchema
13002
+ });
13003
+ /** Motion block — null when motion detection is not active for this device. */
13004
+ var CameraMotionStatusSchema = object({
13005
+ enabled: boolean(),
13006
+ fps: number()
13007
+ });
13008
+ /** Detection provisioning sub-block. */
13009
+ var CameraDetectionProvisioningSchema = object({
13010
+ state: _enum([
13011
+ "idle",
13012
+ "installing",
13013
+ "verifying",
13014
+ "ready",
13015
+ "failed"
13016
+ ]),
13017
+ error: string().optional()
13018
+ });
13019
+ /** Detection phase — derived from the runner's engine phase. */
13020
+ var CameraDetectionPhaseSchema = _enum([
13021
+ "idle",
13022
+ "watching",
13023
+ "active"
13024
+ ]);
13025
+ /** Detection block — null when no detection node is assigned or reachable. */
13026
+ var CameraDetectionStatusSchema = object({
13027
+ nodeId: string(),
13028
+ engine: object({
13029
+ backend: string(),
13030
+ device: string()
13031
+ }),
13032
+ phase: CameraDetectionPhaseSchema,
13033
+ configuredFps: number(),
13034
+ actualFps: number(),
13035
+ queueDepth: number(),
13036
+ avgInferenceMs: number(),
13037
+ provisioning: CameraDetectionProvisioningSchema
13038
+ });
13039
+ /** Audio block — null when no audio node is assigned or reachable. */
13040
+ var CameraAudioStatusSchema = object({
13041
+ nodeId: string(),
13042
+ enabled: boolean()
13043
+ });
13044
+ /** Recording block — null when no recording cap is active for this device. */
13045
+ var CameraRecordingStatusSchema = object({
13046
+ mode: _enum([
13047
+ "off",
13048
+ "continuous",
13049
+ "events"
13050
+ ]),
13051
+ active: boolean(),
13052
+ storageBytes: number()
13053
+ });
13054
+ /**
13055
+ * Aggregated per-camera pipeline status — server-composed, single call.
13056
+ *
13057
+ * The `assignment` and `source` blocks are always present.
13058
+ * Every other block is `null` when the stage is inactive or unreachable
13059
+ * during the bounded parallel fan-out in the orchestrator implementation.
13060
+ *
13061
+ * See spec: `docs/superpowers/specs/2026-06-24-camera-status-aggregator-cap.md`
13062
+ */
13063
+ var CameraStatusSchema = object({
13064
+ deviceId: number(),
13065
+ assignment: CameraAssignmentStatusSchema,
13066
+ source: CameraSourceStatusSchema,
13067
+ broker: CameraBrokerStatusSchema.nullable(),
13068
+ decoder: CameraDecoderStatusSchema.nullable(),
13069
+ motion: CameraMotionStatusSchema.nullable(),
13070
+ detection: CameraDetectionStatusSchema.nullable(),
13071
+ audio: CameraAudioStatusSchema.nullable(),
13072
+ recording: CameraRecordingStatusSchema.nullable(),
13073
+ /** Unix timestamp (ms) when this snapshot was composed server-side. */
13074
+ fetchedAt: number()
13075
+ });
12915
13076
  method(object({
12916
13077
  deviceId: number(),
12917
13078
  agentNodeId: string()
@@ -12979,6 +13140,12 @@ method(object({
12979
13140
  }), {
12980
13141
  kind: "mutation",
12981
13142
  auth: "admin"
13143
+ }), method(object({
13144
+ agentNodeId: string(),
13145
+ maxCameras: number().int().nonnegative().nullable()
13146
+ }), object({ success: literal(true) }), {
13147
+ kind: "mutation",
13148
+ auth: "admin"
12982
13149
  }), method(object({ deviceId: number() }), CameraPipelineSettingsSchema.nullable()), method(object({
12983
13150
  deviceId: number(),
12984
13151
  addonId: string(),
@@ -13004,7 +13171,7 @@ method(object({
13004
13171
  }), method(object({
13005
13172
  deviceId: number(),
13006
13173
  agentNodeId: string().optional()
13007
- }), CameraPipelineConfigSchema), method(_void(), array(PipelineTemplateSchema).readonly()), method(object({
13174
+ }), CameraPipelineConfigSchema), method(object({ deviceId: number() }), CameraStatusSchema), method(object({ deviceIds: array(number()).optional() }), array(CameraStatusSchema).readonly()), method(_void(), array(PipelineTemplateSchema).readonly()), method(object({
13008
13175
  name: string(),
13009
13176
  description: string().optional(),
13010
13177
  config: CameraPipelineConfigSchema
@@ -15968,6 +16135,69 @@ method(_void(), array(IntegrationWithStateSchema)), method(object({ id: string()
15968
16135
  kind: "mutation",
15969
16136
  auth: "admin"
15970
16137
  });
16138
+ var jobKindSchema = _enum([
16139
+ "install",
16140
+ "update",
16141
+ "uninstall",
16142
+ "restart"
16143
+ ]);
16144
+ var taskPhaseSchema = _enum([
16145
+ "queued",
16146
+ "fetching",
16147
+ "staged",
16148
+ "validating",
16149
+ "applying",
16150
+ "restarting",
16151
+ "applied",
16152
+ "done",
16153
+ "failed",
16154
+ "skipped"
16155
+ ]);
16156
+ var taskTargetSchema = _enum(["framework", "addon"]);
16157
+ var taskLogEntrySchema = object({
16158
+ tsMs: number(),
16159
+ nodeId: string(),
16160
+ packageName: string(),
16161
+ phase: taskPhaseSchema,
16162
+ message: string()
16163
+ });
16164
+ var lifecycleTaskSchema = object({
16165
+ taskId: string(),
16166
+ nodeId: string(),
16167
+ packageName: string(),
16168
+ fromVersion: string().nullable(),
16169
+ toVersion: string(),
16170
+ target: taskTargetSchema,
16171
+ phase: taskPhaseSchema,
16172
+ stagedPath: string().nullable(),
16173
+ attempts: number(),
16174
+ steps: array(taskLogEntrySchema),
16175
+ error: string().nullable(),
16176
+ startedAtMs: number().nullable(),
16177
+ finishedAtMs: number().nullable()
16178
+ });
16179
+ var lifecycleJobStateSchema = _enum([
16180
+ "running",
16181
+ "completed",
16182
+ "failed",
16183
+ "partially-failed",
16184
+ "cancelled"
16185
+ ]);
16186
+ var lifecycleJobScopeSchema = _enum([
16187
+ "single",
16188
+ "bulk",
16189
+ "cluster"
16190
+ ]);
16191
+ var lifecycleJobSchema = object({
16192
+ jobId: string(),
16193
+ kind: jobKindSchema,
16194
+ createdAtMs: number(),
16195
+ createdBy: string(),
16196
+ scope: lifecycleJobScopeSchema,
16197
+ tasks: array(lifecycleTaskSchema),
16198
+ state: lifecycleJobStateSchema,
16199
+ schemaVersion: literal(1)
16200
+ });
15971
16201
  /**
15972
16202
  * addons — system-scoped singleton capability for addon package
15973
16203
  * management (install, update, configure, restart) and per-addon log
@@ -16150,7 +16380,7 @@ var BulkUpdatePhaseSchema = _enum([
16150
16380
  "restarting",
16151
16381
  "finalizing"
16152
16382
  ]);
16153
- var BulkUpdateStateSchema = object({
16383
+ object({
16154
16384
  id: string(),
16155
16385
  nodeId: string(),
16156
16386
  startedAtMs: number(),
@@ -16253,20 +16483,7 @@ method(_void(), array(AddonListItemSchema).readonly()), method(object({
16253
16483
  }), UpdateFrameworkPackageResultSchema, {
16254
16484
  kind: "mutation",
16255
16485
  auth: "admin"
16256
- }), method(object({
16257
- nodeId: string(),
16258
- items: array(object({
16259
- name: string(),
16260
- version: string(),
16261
- isSystem: boolean()
16262
- })).readonly()
16263
- }), object({ id: string() }), {
16264
- kind: "mutation",
16265
- auth: "admin"
16266
- }), method(object({ id: string() }), BulkUpdateStateSchema.nullable(), { auth: "admin" }), method(object({ id: string() }), object({ cancelled: boolean() }), {
16267
- kind: "mutation",
16268
- auth: "admin"
16269
- }), method(object({ nodeId: string().optional() }), array(BulkUpdateStateSchema).readonly(), { auth: "admin" }), method(object({ name: string() }), array(PackageVersionInfoSchema).readonly()), method(object({ addonId: string() }), RestartAddonResultSchema, {
16486
+ }), method(object({ name: string() }), array(PackageVersionInfoSchema).readonly()), method(object({ addonId: string() }), RestartAddonResultSchema, {
16270
16487
  kind: "mutation",
16271
16488
  auth: "admin"
16272
16489
  }), method(object({ packageName: string() }), object({ success: literal(true) }), {
@@ -16288,6 +16505,24 @@ method(_void(), array(AddonListItemSchema).readonly()), method(object({
16288
16505
  kind: "mutation",
16289
16506
  auth: "admin"
16290
16507
  }), method(CustomActionInputSchema, unknown(), { kind: "mutation" }), method(object({
16508
+ kind: _enum([
16509
+ "install",
16510
+ "update",
16511
+ "uninstall",
16512
+ "restart"
16513
+ ]),
16514
+ targets: array(object({
16515
+ name: string().min(1),
16516
+ version: string().min(1)
16517
+ })).min(1),
16518
+ nodeIds: array(string()).optional()
16519
+ }), object({ jobId: string() }), {
16520
+ kind: "mutation",
16521
+ auth: "admin"
16522
+ }), method(object({ jobId: string() }), lifecycleJobSchema.nullable(), { auth: "admin" }), method(object({ activeOnly: boolean().optional() }), array(lifecycleJobSchema), { auth: "admin" }), method(object({ jobId: string() }), object({ cancelled: boolean() }), {
16523
+ kind: "mutation",
16524
+ auth: "admin"
16525
+ }), method(object({
16291
16526
  addonId: string(),
16292
16527
  level: LogLevelSchema$1.optional()
16293
16528
  }), LogStreamEntrySchema, { kind: "subscription" });
@@ -16328,7 +16563,7 @@ Object.freeze({
16328
16563
  addonId: null,
16329
16564
  access: "create"
16330
16565
  },
16331
- "addons.cancelBulkUpdate": {
16566
+ "addons.cancelJob": {
16332
16567
  capName: "addons",
16333
16568
  capScope: "system",
16334
16569
  addonId: null,
@@ -16358,7 +16593,7 @@ Object.freeze({
16358
16593
  addonId: null,
16359
16594
  access: "view"
16360
16595
  },
16361
- "addons.getBulkUpdateState": {
16596
+ "addons.getJob": {
16362
16597
  capName: "addons",
16363
16598
  capScope: "system",
16364
16599
  addonId: null,
@@ -16406,19 +16641,19 @@ Object.freeze({
16406
16641
  addonId: null,
16407
16642
  access: "view"
16408
16643
  },
16409
- "addons.listActiveBulkUpdates": {
16644
+ "addons.listCapabilityProviders": {
16410
16645
  capName: "addons",
16411
16646
  capScope: "system",
16412
16647
  addonId: null,
16413
16648
  access: "view"
16414
16649
  },
16415
- "addons.listCapabilityProviders": {
16650
+ "addons.listFrameworkPackages": {
16416
16651
  capName: "addons",
16417
16652
  capScope: "system",
16418
16653
  addonId: null,
16419
16654
  access: "view"
16420
16655
  },
16421
- "addons.listFrameworkPackages": {
16656
+ "addons.listJobs": {
16422
16657
  capName: "addons",
16423
16658
  capScope: "system",
16424
16659
  addonId: null,
@@ -16502,7 +16737,7 @@ Object.freeze({
16502
16737
  addonId: null,
16503
16738
  access: "create"
16504
16739
  },
16505
- "addons.startBulkUpdate": {
16740
+ "addons.startJob": {
16506
16741
  capName: "addons",
16507
16742
  capScope: "system",
16508
16743
  addonId: null,
@@ -18728,6 +18963,12 @@ Object.freeze({
18728
18963
  addonId: null,
18729
18964
  access: "view"
18730
18965
  },
18966
+ "pipelineExecutor.getEngineProvisioning": {
18967
+ capName: "pipeline-executor",
18968
+ capScope: "system",
18969
+ addonId: null,
18970
+ access: "view"
18971
+ },
18731
18972
  "pipelineExecutor.getGlobalPipelineConfig": {
18732
18973
  capName: "pipeline-executor",
18733
18974
  capScope: "system",
@@ -18932,6 +19173,18 @@ Object.freeze({
18932
19173
  addonId: null,
18933
19174
  access: "view"
18934
19175
  },
19176
+ "pipelineOrchestrator.getCameraStatus": {
19177
+ capName: "pipeline-orchestrator",
19178
+ capScope: "system",
19179
+ addonId: null,
19180
+ access: "view"
19181
+ },
19182
+ "pipelineOrchestrator.getCameraStatuses": {
19183
+ capName: "pipeline-orchestrator",
19184
+ capScope: "system",
19185
+ addonId: null,
19186
+ access: "view"
19187
+ },
18935
19188
  "pipelineOrchestrator.getCameraStepOverrides": {
18936
19189
  capName: "pipeline-orchestrator",
18937
19190
  capScope: "system",
@@ -19016,6 +19269,12 @@ Object.freeze({
19016
19269
  addonId: null,
19017
19270
  access: "create"
19018
19271
  },
19272
+ "pipelineOrchestrator.setAgentMaxCameras": {
19273
+ capName: "pipeline-orchestrator",
19274
+ capScope: "system",
19275
+ addonId: null,
19276
+ access: "create"
19277
+ },
19019
19278
  "pipelineOrchestrator.setCameraPipelineForAgent": {
19020
19279
  capName: "pipeline-orchestrator",
19021
19280
  capScope: "system",
@@ -20489,6 +20748,32 @@ Object.freeze({
20489
20748
  "network-access": "ingress",
20490
20749
  "smtp-provider": "email"
20491
20750
  });
20751
+ var frameworkSwapPackageSchema = object({
20752
+ name: string(),
20753
+ stagedPath: string(),
20754
+ backupPath: string(),
20755
+ toVersion: string(),
20756
+ fromVersion: string().nullable()
20757
+ });
20758
+ object({
20759
+ jobId: string(),
20760
+ taskId: string(),
20761
+ packages: array(frameworkSwapPackageSchema),
20762
+ requestedAtMs: number(),
20763
+ schemaVersion: literal(1)
20764
+ });
20765
+ object({
20766
+ jobId: string(),
20767
+ taskId: string(),
20768
+ backups: array(object({
20769
+ name: string(),
20770
+ backupPath: string(),
20771
+ livePath: string()
20772
+ })),
20773
+ appliedAtMs: number(),
20774
+ bootAttempts: number(),
20775
+ schemaVersion: literal(1)
20776
+ });
20492
20777
  //#endregion
20493
20778
  //#region src/server/addon.ts
20494
20779
  var __dirname = path.dirname(fileURLToPath(import.meta.url));
@@ -20508,7 +20793,7 @@ var AdminUIAddon = class extends BaseAddon {
20508
20793
  capability: adminUiCapability,
20509
20794
  provider: {
20510
20795
  getStaticDir: async () => ({ staticDir: resolveAdminUiDistDir() }),
20511
- getVersion: async () => ({ version: "0.1.0" })
20796
+ getVersion: async () => ({ version: "1.0.6" })
20512
20797
  }
20513
20798
  }];
20514
20799
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@camstack/addon-admin-ui",
3
- "version": "1.0.4",
3
+ "version": "1.0.6",
4
4
  "private": false,
5
5
  "type": "module",
6
6
  "description": "CamStack Admin UI — Vite frontend build and server-side addon",
@@ -1 +0,0 @@
1
- import{$ as e,Li as t,Pi as n,Q as r,Vi as i,Z as a,_t as o,at as s,bt as c,ct as l,dt as u,et as d,fr as f,g as p,ht as m,it as ee,lt as h,m as te,mt as ne,nt as g,ot as re,pt as _,rt as v,tt as ie,ut as y,v as b,vt as ae,yr as x,yt as S}from"./src-CqVYgpnN.js";import{F as C,G as w,L as oe,R as T,U as E,W as se,X as D,b as O,o as ce,x as k,y as A}from"./_virtual_mf___mfe_internal__admin_ui_host__loadShare___mf_0_tanstack_mf_1_react_mf_2_query__loadShare__.js-CK8iQdP1.js";import{p as j}from"./player-overlays-DzZKARlk.js";import{t as M}from"./download-CEQQi2pw.js";import{t as le}from"./plus-CbaF5MYw.js";import{t as N}from"./refresh-cw-CPqFoliO.js";import{t as P}from"./search-cFwrysqG.js";import{t as F}from"./upload-tyMJOOSL.js";import{A as ue,B as I,F as L,H as R,P as de,W as z,f as fe,h as B,i as pe,o as V,p as H,s as me,x as U}from"./index-DuroU2aU.js";import{t as W}from"./AdminPage-CN6ZMhf0.js";import{t as he}from"./NodeAddonsSettingsPanel-9HVgS_gw.js";var G=I(`chevron-up`,[[`path`,{d:`m18 15-6-6-6 6`,key:`153udz`}]]),K=I(`clock`,[[`circle`,{cx:`12`,cy:`12`,r:`10`,key:`1mglay`}],[`polyline`,{points:`12 6 12 12 16 14`,key:`68esgv`}]]),ge=I(`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`}]]),_e=I(`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`}]]);D();function ve({packageName:e,currentVersion:t,installSource:n,onInstall:r,onClose:i}){let a=n===`upload`||n===`local`,{data:o,isLoading:s}=v({name:e});return k(`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:[k(`div`,{className:`flex items-center justify-between px-3 py-2 border-b border-border`,children:[O(`span`,{className:`text-[10px] uppercase tracking-wide text-foreground-subtle font-medium`,children:`Versions`}),O(`button`,{type:`button`,onClick:i,className:`text-foreground-subtle hover:text-foreground`,children:O(pe,{className:`h-3 w-3`})})]}),a&&k(`div`,{className:`flex items-start gap-2 px-3 py-2 border-b border-border bg-cyan-500/10 text-[10px]`,children:[O(F,{className:`h-3 w-3 mt-0.5 text-cyan-500 shrink-0`}),k(`div`,{className:`text-cyan-700 dark:text-cyan-200`,children:[k(`span`,{className:`font-semibold`,children:[n===`upload`?`Uploaded copy`:`Local copy`,` in place.`]}),` `,`Re-install `,O(`span`,{className:`font-mono`,children:t}),` from npm to track upstream releases again.`]})]}),s&&k(`div`,{className:`flex items-center justify-center gap-2 py-6 text-[10px] text-foreground-subtle`,children:[O(U,{className:`h-3.5 w-3.5 animate-spin`}),`Loading versions...`]}),o&&O(`div`,{className:`max-h-64 overflow-auto divide-y divide-border`,children:o.map(e=>{let n=e.version===t,i=/-(alpha|beta|rc|dev|canary|next)/i.test(e.version);return k(`div`,{className:`flex items-center gap-2 px-3 py-2 text-[11px] ${n?`bg-primary/5`:`hover:bg-surface-hover`} transition-colors`,children:[O(`span`,{className:`font-mono flex-1 ${n?`text-primary font-semibold`:i?`text-amber-400`:`text-foreground`}`,children:e.version}),e.distTags.map(e=>O(`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&&O(`span`,{className:`text-[9px] text-red-400 line-through`,children:`deprecated`}),O(`span`,{className:`text-[9px] text-foreground-subtle shrink-0`,children:new Date(e.publishedAt).toLocaleDateString()}),n&&!a?O(L,{className:`h-3 w-3 text-primary shrink-0`}):O(`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:O(M,{className:`h-3 w-3`})})]},e.version)})}),o&&o.length===0&&O(`div`,{className:`py-4 text-center text-[10px] text-foreground-subtle`,children:`No versions found`})]})}var q={queued:{icon:K,bg:`bg-muted text-foreground-subtle`,label:`queued`},updating:{icon:U,bg:`bg-primary/10 text-primary`,label:`updating`,spin:!0},"done-pending-restart":{icon:N,bg:`bg-amber-500/10 text-amber-700`,label:`pending restart`},done:{icon:L,bg:`bg-success/10 text-success`,label:`done`},failed:{icon:ge,bg:`bg-danger/10 text-danger`,label:`failed`}};function ye({item:e}){let t=q[e.status],n=t.icon;return k(`span`,{className:`inline-flex items-center gap-1 px-1.5 py-0.5 text-[10px] rounded ${t.bg}`,title:e.error,children:[O(n,{className:`w-2.5 h-2.5 ${t.spin?`animate-spin`:``}`}),t.label]})}var be=`device-export`;function J(e){return e.capabilities.some(e=>(typeof e==`string`?e:e.name)===be)}function xe({isBundle:e,installSource:t,addonId:n,iconPath:r,color:i}){let[a,o]=w(!1),s=i?{backgroundColor:`${i.startsWith(`#`)?i:`#${i}`}26`}:void 0,c=e?`bg-indigo-500/20 text-indigo-700 dark:text-indigo-300`:`bg-purple-500/20 text-purple-700 dark:text-purple-300`,l=n&&r?`/api/addon-assets/${n}/${r}`:null,u=!!l&&!a;return k(`div`,{className:`relative flex-shrink-0`,children:[O(`div`,{className:`h-9 w-9 rounded-lg flex items-center justify-center ${s?``:c}`,style:s,children:u?O(`img`,{src:l,alt:n,className:`h-5 w-5`,onError:()=>o(!0)}):O(e?_e:B,{className:`h-4 w-4`})}),t===`local`&&O(`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`&&O(`span`,{className:`absolute -top-1 -left-1 w-4 h-4 rounded bg-[#cb3837] flex items-center justify-center -rotate-12 shadow-sm`,children:O(`svg`,{viewBox:`0 0 780 250`,className:`w-[11px] h-[11px]`,children:O(`path`,{fill:`#fff`,d:`M240 250h100V50h100v200h340V0H0v250z`})})}),t===`upload`&&O(`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:O(F,{className:`h-2.5 w-2.5 text-white`})})]})}function Se({addonId:e}){let t=ce(),{data:n=`inherit`}=d({addonId:e}),r=m({onSuccess:()=>{t.invalidateQueries({queryKey:[[`addons`,`getAddonAutoUpdate`]]})}});return O(`div`,{className:`flex rounded-lg border border-border overflow-hidden text-[10px] font-medium`,children:[`inherit`,`off`,`latest`,`beta`].map(t=>O(`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 Ce({addon:e,agents:t=[],clusterStatus:r,hideVersion:i,availableUpdate:a,onUpdate:o,isUpdating:s,bundle:c,bulkItem:l,disabledByBulk:d,isSystem:f}){let[m,h]=w(!1),[ne,g]=w(!1),[re,v]=w(!1),[ie,y]=w(!1),[x,S]=w(!1),[C,oe]=w(`logs`),T=ce(),E=j(),se=R(),D=n(),{manifest:P}=e,F=e.installedOn??[],ue=!c&&!P.protected&&P.removable!==!1,I=!!c,L=c?.displayName??P.name,z=c?.packageName??P.packageName,B=c?.version??P.packageVersion??P.version,V=c?.installSource??e.installSource,W=c?c.bundle?.description??c.addons[0]?.manifest.description:P.description;!c&&(P.components&&P.components.length>0||t.length);let K=ae({onSuccess:()=>{T.invalidateQueries({queryKey:[[`addons`]]}),T.invalidateQueries({queryKey:[[`addonPages`]]}),T.invalidateQueries({queryKey:[[`capabilities`]]})}}),q=u({onSuccess:()=>{T.invalidateQueries({queryKey:[[`addons`]]})}}),be=ee({onSuccess:()=>{T.invalidateQueries({queryKey:[[`addons`]]}),T.invalidateQueries({queryKey:[[`addonPages`]]}),T.invalidateQueries({queryKey:[[`capabilities`]]}),T.invalidateQueries({queryKey:[[`integrations`]]})}}),Y=_({onSuccess:()=>{T.invalidateQueries({queryKey:[[`addons`]]}),T.invalidateQueries({queryKey:[[`alerts`]]})}}),X=e.health,Z=X?.phase===`failed`&&!X.inGracePeriod,we=Z&&X?.nextRetryAt&&!X.retrying;return k(`div`,{className:`rounded-lg border bg-surface overflow-hidden ${Z?`border-red-500/50`:`border-border`}`,children:[Z&&X&&k(`div`,{className:`bg-danger/10 border-b border-danger/30 px-4 py-2.5 flex items-start gap-2.5`,children:[O(ge,{className:`h-4 w-4 text-danger shrink-0 mt-0.5`}),k(`div`,{className:`flex-1 min-w-0`,children:[k(`div`,{className:`text-xs font-semibold text-danger`,children:[`Failed to load (attempt #`,X.retryCount,`)`]}),O(`div`,{className:`text-[11px] text-foreground mt-0.5 break-words font-mono`,children:X.lastError?.message??`Unknown error`}),we&&X.nextRetryAt&&k(`div`,{className:`text-[10px] text-foreground-subtle mt-1`,children:[`Auto-retry at `,new Date(X.nextRetryAt).toLocaleTimeString()]})]}),k(`button`,{type:`button`,disabled:Y.isPending||X.retrying,onClick:e=>{e.stopPropagation(),Y.mutate({packageName:z})},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:[O(N,{className:`h-3 w-3 ${Y.isPending||X.retrying?`animate-spin`:``}`}),`Retry now`]})]}),k(`div`,{className:`flex items-start gap-3 px-4 py-3`,children:[O(xe,{isBundle:I||!!P.components&&P.components.length>1,installSource:V,addonId:I?c.addons[0]?.manifest.id:P.id,iconPath:I?c.bundle?.icon??c.addons[0]?.manifest.icon:P.icon,color:I?c.addons[0]?.manifest.color:P.color}),k(`div`,{className:`flex-1 min-w-0`,children:[k(`div`,{className:`flex items-center gap-2`,children:[O(`span`,{className:`text-sm font-semibold text-foreground truncate`,children:L}),k(`span`,{className:`text-[10px] text-foreground-subtle font-mono shrink-0`,children:[`(`,z,`)`]}),I&&k(`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:[O(_e,{className:`h-3 w-3`}),c.addons.length]}),f&&k(`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:[O(N,{className:`h-3 w-3`}),`System · restart on update`]}),l!=null&&O(ye,{item:l})]}),W&&O(`p`,{className:`text-[10px] text-foreground-subtle mt-0.5 line-clamp-1`,children:W}),!I&&e.process&&k(`div`,{className:`flex items-center gap-1.5 mt-1`,children:[O(`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&&k(`span`,{className:`text-[9px] font-mono text-foreground-subtle`,children:[`PID `,e.process.pid]}),O(`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})]})]}),!i&&k(`div`,{className:`relative inline-flex items-center gap-1.5 shrink-0 pt-0.5`,children:[s?k(`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`,children:[O(U,{className:`h-3 w-3 animate-spin`}),`Updating to `,a,`…`]}):a&&o?k(`button`,{type:`button`,onClick:e=>{e.stopPropagation(),o()},disabled:d,className:`inline-flex items-center gap-1 rounded-md px-2 py-1 text-[10px] font-semibold border border-primary/40 bg-primary/10 text-primary hover:bg-primary/20 transition-colors animate-pulse disabled:opacity-50 disabled:cursor-not-allowed`,title:`Update to ${a}`,children:[O(M,{className:`h-3 w-3`}),a]}):null,k(`button`,{type:`button`,onClick:e=>{e.stopPropagation(),v(e=>!e)},disabled:d,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`,V===`local`?`border-orange-500/30 bg-orange-500/10 text-orange-400 hover:bg-orange-500/20`:a?`border-amber-500/30 bg-amber-500/10 text-amber-400 hover:bg-amber-500/20`:`border-emerald-500/30 bg-emerald-500/10 text-emerald-400 hover:bg-emerald-500/20`].join(` `),title:a?`Current ${B} — newer ${a} available`:`View all versions`,children:[B,O(de,{className:`h-3 w-3 opacity-50`})]}),re&&O(ve,{packageName:z,currentVersion:B,...V?{installSource:V}:{},onInstall:e=>{v(!1),be.mutate({packageName:z,version:e})},onClose:()=>v(!1)})]})]}),!I&&k(`div`,{className:`flex items-center gap-1 px-4 py-1.5 border-t border-border/50 bg-surface-hover/20`,children:[k(`button`,{type:`button`,onClick:e=>{e.stopPropagation(),q.mutate({addonId:P.id})},disabled:q.isPending||d,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:[O(N,{className:`h-3 w-3 ${q.isPending?`animate-spin`:``}`}),`Restart`]}),k(`button`,{type:`button`,onClick:e=>{e.stopPropagation(),y(e=>!e)},className:`inline-flex items-center gap-1 rounded-md px-2 py-1 text-[10px] font-medium border transition-colors ${ie?`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:[O(H,{className:`h-3 w-3`}),`Logs`]}),!I&&k(`button`,{type:`button`,onClick:e=>{e.stopPropagation(),S(!0)},className:`inline-flex items-center gap-1 rounded-md px-2 py-1 text-[10px] font-medium border transition-colors ${x?`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:[O(fe,{className:`h-3 w-3`}),`Settings`]}),O(`div`,{className:`flex-1`}),ue&&k(`button`,{type:`button`,onClick:async e=>{e.stopPropagation(),await D({title:`Uninstall ${P.name}?`,message:`This will remove the addon package and all its data. This action cannot be undone.`,confirmLabel:`Uninstall`,variant:`danger`})&&K.mutate({packageName:P.packageName})},disabled:K.isPending||d,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:[O(me,{className:`h-3 w-3`}),K.isPending?`Removing...`:`Uninstall`]})]}),r&&r.nodes.length>1&&!I&&k(`div`,{className:`border-t border-border px-4 py-2 bg-muted/10`,children:[O(`div`,{className:`text-[10px] font-medium text-foreground-subtle mb-1.5`,children:`Cluster Deployment`}),O(`div`,{className:`space-y-1`,children:r.nodes.map(e=>k(`div`,{className:`flex items-center gap-2 text-[10px]`,children:[O(`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`}`}),O(`span`,{className:`font-medium text-foreground min-w-[60px]`,children:e.name}),O(`span`,{className:`font-mono text-foreground-subtle`,children:e.version}),!e.synced&&e.status!==`offline`&&O(`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`&&O(`span`,{className:`text-[9px] px-1 py-0.5 rounded bg-muted text-muted-foreground`,children:`offline`}),e.synced&&e.status!==`offline`&&O(`span`,{className:`text-[9px] text-success`,children:`synced`})]},e.nodeId))})]}),ie&&!I&&k(`div`,{className:`border-t border-border`,children:[k(`div`,{className:`flex items-center px-4 py-1 bg-surface-hover/20 border-b border-border/50`,children:[k(`div`,{className:`flex rounded border border-border overflow-hidden text-[9px]`,children:[O(`button`,{type:`button`,onClick:()=>oe(`logs`),className:`px-2 py-0.5 transition-colors ${C===`logs`?`bg-primary/10 text-primary`:`text-foreground-subtle hover:bg-surface-hover`}`,children:`Logs`}),O(`button`,{type:`button`,onClick:()=>oe(`events`),className:`px-2 py-0.5 border-l border-border transition-colors ${C===`events`?`bg-primary/10 text-primary`:`text-foreground-subtle hover:bg-surface-hover`}`,children:`Events`})]}),O(`div`,{className:`flex-1`}),O(`button`,{type:`button`,onClick:e=>{e.stopPropagation(),y(!1)},className:`text-foreground-subtle hover:text-foreground`,children:O(pe,{className:`h-3.5 w-3.5`})})]}),C===`logs`&&O(p,{addonId:P.id,maxHeight:`max-h-64`,showFilters:!1}),C===`events`&&O(te,{addonId:P.id,category:`addon.*`,maxHeight:`max-h-64`})]}),I&&k(A,{children:[O(`button`,{type:`button`,onClick:()=>h(e=>!e),className:`w-full flex items-center justify-center border-t border-border py-1 hover:bg-surface-hover/50 transition-colors`,children:O(m?G:de,{className:`h-3.5 w-3.5 text-foreground-subtle`})}),m&&O(`div`,{className:`border-t border-border px-3 py-2 space-y-2`,children:c.addons.map(e=>O(Ce,{addon:e,agents:t,hideVersion:!0},e.manifest.id))})]}),x&&!I&&O(`div`,{className:`fixed inset-0 z-50 flex items-center justify-center bg-black/60 backdrop-blur-sm p-4`,onClick:()=>S(!1),children:k(`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:[k(`div`,{className:`flex items-center justify-between px-5 py-3 border-b border-border flex-shrink-0`,children:[k(`div`,{className:`flex items-center gap-2`,children:[O(fe,{className:`h-4 w-4 text-primary`}),k(`h2`,{className:`text-sm font-semibold text-foreground`,children:[L,` Settings`]})]}),O(`button`,{onClick:()=>S(!1),className:`text-foreground-subtle hover:text-foreground transition-colors p-1 rounded`,children:O(pe,{className:`h-4 w-4`})})]}),k(`div`,{className:`flex-1 overflow-y-auto px-5 py-4 space-y-4`,children:[O(he,{nodeId:`hub`,addonIds:[P.id],level:`global`}),J(P)&&k(`div`,{children:[O(`div`,{className:`text-[10px] font-medium text-foreground-subtle uppercase tracking-wide mb-2`,children:`Device export`}),O(b,{addonId:P.id,trpc:E.trpcClient,onOpenDevice:e=>se(`/devices/${e}`)})]}),V===`npm`&&k(`div`,{children:[O(`div`,{className:`text-[10px] font-medium text-foreground-subtle uppercase tracking-wide mb-2`,children:`Auto-Update`}),O(Se,{addonId:P.id})]}),P.components&&P.components.length>0&&k(`div`,{children:[k(`div`,{className:`text-[10px] font-medium text-foreground-subtle uppercase tracking-wide mb-2`,children:[`Components (`,P.components.length,`)`]}),O(`div`,{className:`flex flex-wrap gap-1`,children:P.components.map(e=>O(`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&&k(`div`,{children:[O(`div`,{className:`text-[10px] font-medium text-foreground-subtle uppercase tracking-wide mb-2`,children:`Installed on`}),k(`div`,{className:`flex items-center gap-1.5 flex-wrap`,children:[F.length===0&&O(`span`,{className:`text-[10px] text-foreground-subtle`,children:`Hub (local)`}),F.map(e=>O(`span`,{className:`rounded-full bg-surface-hover border border-border px-2 py-0.5 text-[10px] text-foreground-subtle`,children:e},e)),k(`div`,{className:`relative`,children:[k(`button`,{type:`button`,onClick:e=>{e.stopPropagation(),g(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:[O(le,{className:`h-3 w-3`}),`Add agent`]}),ne&&k(`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&&!F.includes(e.name)).map(e=>O(`button`,{type:`button`,onClick:e=>{e.stopPropagation(),g(!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&&!F.includes(e.name)).length===0&&O(`div`,{className:`px-3 py-1.5 text-[10px] text-foreground-subtle`,children:`No available agents`})]})]})]})]})]}),O(`div`,{className:`flex items-center justify-end px-5 py-3 border-t border-border flex-shrink-0`,children:O(`button`,{type:`button`,onClick:()=>S(!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`})})]})})]})}D();var Y=`.tgz,.tar.gz,.zip`;function X({onUploadSuccess:e}){let[t,n]=w(!1),r=se(null),i=C(async t=>{n(!0);let r=new FormData;r.append(`file`,t);let i=localStorage.getItem(`camstack_admin_token`)??``;try{(await(await fetch(`/api/addons/upload`,{method:`POST`,headers:{Authorization:`Bearer ${i}`},body:r})).json()).success&&e()}finally{n(!1)}},[e]);return k(A,{children:[O(`input`,{ref:r,type:`file`,accept:Y,onChange:C(e=>{let t=e.target.files?.[0];t&&i(t),e.target.value=``},[i]),className:`hidden`}),k(`button`,{type:`button`,onClick:()=>r.current?.click(),disabled:t,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:[t?O(U,{className:`w-3.5 h-3.5 animate-spin`}):O(F,{className:`w-3.5 h-3.5`}),t?`Uploading...`:`Upload`]})]})}var Z={regular:`Updating addons`,system:`Updating system packages`,restarting:`Restarting hub… (~10s)`,finalizing:`Finalizing`};function we({state:e,onCancel:t}){let n=e.total===0?0:Math.round(e.completed/e.total*100),r=e.phase!==`restarting`&&!e.cancelled&&e.completedAtMs===void 0;return k(`div`,{className:`sticky top-0 z-30 bg-surface border-b border-border px-3 py-2 space-y-1.5`,children:[k(`div`,{className:`flex items-center gap-2 text-xs`,children:[O(U,{className:`w-3.5 h-3.5 animate-spin text-primary`}),O(`span`,{className:`font-medium`,children:Z[e.phase]}),O(`span`,{className:`text-foreground-subtle`,children:`·`}),k(`span`,{className:`text-foreground-subtle`,children:[e.completed,`/`,e.total]}),e.current!==null&&k(A,{children:[O(`span`,{className:`text-foreground-subtle`,children:`·`}),O(`span`,{className:`font-mono text-foreground-subtle truncate`,children:e.current})]}),k(`div`,{className:`ml-auto flex items-center gap-2`,children:[e.failed>0&&k(`span`,{className:`text-[10px] px-1.5 py-0.5 rounded bg-danger/10 text-danger`,children:[e.failed,` failed`]}),O(`button`,{type:`button`,onClick:t,disabled:!r,className:`text-[10px] px-2 py-0.5 rounded border border-border hover:bg-surface-hover disabled:opacity-40`,children:`Cancel`})]})]}),O(`div`,{className:`h-1 bg-muted rounded overflow-hidden`,children:O(`div`,{className:`h-full bg-primary transition-[width] duration-200`,style:{width:`${n}%`}})}),e.phase===`system`&&k(`div`,{className:`text-[10px] text-amber-700 flex items-center gap-1`,children:[O(V,{className:`w-3 h-3`}),`System phase: the hub will restart once at the end (~10s).`]})]})}function Te({pending:e,onCancel:t,onConfirm:n,isPending:r,error:i}){return O(`div`,{className:`fixed inset-0 z-50 flex items-center justify-center bg-black/60`,children:k(`div`,{className:`bg-surface border border-border rounded-md shadow-xl p-5 max-w-md w-full mx-4 space-y-3`,children:[k(`div`,{className:`flex items-center gap-2`,children:[O(V,{className:`w-4 h-4 text-amber-700`}),O(`h3`,{className:`text-sm font-medium text-foreground`,children:`Update system package?`})]}),k(`div`,{className:`space-y-2 text-[11px] text-foreground-subtle`,children:[k(`div`,{children:[O(`span`,{className:`font-mono text-foreground`,children:e.packageName}),O(`span`,{className:`mx-1`,children:`·`}),k(`span`,{className:`font-mono`,children:[`v`,e.fromVersion]}),O(`span`,{className:`mx-1`,children:`→`}),k(`span`,{className:`font-mono text-amber-700`,children:[`v`,e.toVersion]})]}),O(`div`,{className:`rounded border border-amber-500/30 bg-amber-500/10 p-2 text-amber-800`,children:`The hub will restart immediately after the install. Any in-flight requests will be dropped. The reconnect typically takes ~10 seconds.`}),i!==null&&O(`div`,{className:`rounded border border-danger/40 bg-danger/10 p-2 text-danger`,children:i})]}),k(`div`,{className:`flex justify-end gap-2 pt-1`,children:[O(`button`,{type:`button`,onClick:t,disabled:r,className:`px-3 py-1.5 text-[11px] rounded bg-surface hover:bg-surface-hover border border-border disabled:opacity-50`,children:`Cancel`}),k(`button`,{type:`button`,onClick:n,disabled:r,className:`inline-flex items-center gap-1.5 px-3 py-1.5 text-[11px] rounded bg-amber-500/20 text-amber-800 hover:bg-amber-500/30 border border-amber-500/40 font-medium disabled:opacity-50`,children:[r?O(U,{className:`w-3 h-3 animate-spin`}):O(M,{className:`w-3 h-3`}),`Update & restart`]})]})]})})}D();function Ee(e,t){let n=e??`hub-only`;return n===`any-node`?!0:n===`hub-only`?t:!t}function De(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 Oe(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 Q(e){return`bundle`in e}function ke({addons:e,clusterStatus:t,selectedNode:s,onRefresh:u,isRefreshing:d}){let f=ce(),[p,m]=w(``),te=oe(p),[_,v]=w(!1),y=se(null);T(()=>{if(!_)return;let e=e=>{y.current&&!y.current.contains(e.target)&&v(!1)};return document.addEventListener(`mousedown`,e),()=>document.removeEventListener(`mousedown`,e)},[_]);let{data:b}=h({nodeId:s.id}),ae=E(()=>{let e=new Map;for(let t of b??[])e.set(t.name,t.latestVersion);return e},[b]),[x,D]=w(null),[A,j]=w(null),le=c({onMutate:e=>{D(e.name),j(null)},onSuccess:(e,t)=>{D(null);let n=e;if(n&&n.success===!1){j({name:t.name,message:n.error??`Update failed (no error message returned by server)`});return}f.invalidateQueries({queryKey:[[`addons`]]}),f.invalidateQueries({queryKey:[[`addons`,`listUpdates`]]})},onError:(e,t)=>{D(null),j({name:t.name,message:e instanceof Error?e.message:String(e)})}}),{data:F}=ie(void 0),I=a({onSuccess:()=>{f.invalidateQueries({queryKey:[[`addons`,`getAutoUpdateSettings`]]})}}),{data:R,isFetching:de}=ne({query:te||void 0},{enabled:_}),{data:fe}=re({nodeId:s.id},{staleTime:1/0}),[B,pe]=w(null);i(`AddonsBulkUpdateProgress`,e=>{e.data?.nodeId===s.id&&pe(e.data)});let V=E(()=>B===null?(fe??[])[0]??null:B,[B,fe]),H=V!==null&&V.completedAtMs===void 0,me=E(()=>V===null?new Map:new Map(V.items.map(e=>[e.name,e])),[V]),W=o(),he=r(),{data:G}=g(void 0),K=G?.requestedAt,[ge,_e]=w(null),[ve,q]=w(!1);T(()=>{if(G?.kind===`framework-bulk-update`&&G.requestedAt!==ge){_e(G.requestedAt),q(!0);let e=window.setTimeout(()=>q(!1),6e3);return()=>window.clearTimeout(e)}},[K,ge,G]);let{data:ye}=l(void 0),be=E(()=>new Map((ye??[]).map(e=>[e.packageName,e])),[ye]),[J,xe]=w(null),[Se,Y]=w(null),Z=S({onSuccess:()=>{xe(null),f.invalidateQueries({queryKey:[[`addons`]]})},onError:e=>{Y(e instanceof Error?e.message:String(e))}}),De=n(),ke=C(async()=>{let e=b??[];if(e.length===0)return;let t=e.map(e=>({name:e.name,version:e.latestVersion,isSystem:e.isSystem}));t.some(e=>e.isSystem)&&!await De({title:`Update all — includes a system package`,message:`This batch updates a system package (@camstack/system). The hub will restart automatically once the system phase completes. In-flight requests are dropped; reconnect typically takes ~10 seconds.`,confirmLabel:`Update all & restart`,variant:`warning`})||await W.mutateAsync({nodeId:s.id,items:t})},[b,s.id,W,De]),Ae=ee({onSuccess:()=>{f.invalidateQueries({queryKey:[[`addons`]]}),f.invalidateQueries({queryKey:[[`addonPages`]]}),f.invalidateQueries({queryKey:[[`capabilities`]]}),f.invalidateQueries({queryKey:[[`integrations`]]})}}),[je,Me]=w(`type`),[Ne,Pe]=w(()=>typeof window>`u`?`grouped`:window.localStorage.getItem(`camstack.addons.viewMode`)===`flat`?`flat`:`grouped`),Fe=e=>{Pe(e),typeof window<`u`&&window.localStorage.setItem(`camstack.addons.viewMode`,e)},[Ie,Le]=z(),$=Ie.get(`capability`),Re=E(()=>{let t=s.isHub?e:e.filter(e=>Ee(e.placement,s.isHub));return $&&(t=t.filter(e=>(e.manifest.capabilities??[]).some(e=>(typeof e==`string`?e:e.name)===$))),t},[e,s.isHub,$]),ze=()=>{let e=new URLSearchParams(Ie);e.delete(`capability`),Le(e,{replace:!0})},Be=Ne===`flat`?Re:Oe(Re),Ve=E(()=>{let e=[...Be];switch(je){case`type`:e.sort((e,t)=>{let n=+!Q(e),r=+!Q(t);if(n!==r)return n-r;let i=Q(e)?e.bundle.displayName:e.manifest.name,a=Q(t)?t.bundle.displayName:t.manifest.name;return i.localeCompare(a)});break;case`name`:e.sort((e,t)=>{let n=Q(e)?e.bundle.displayName:e.manifest.name,r=Q(t)?t.bundle.displayName:t.manifest.name;return n.localeCompare(r)});break;case`source`:e.sort((e,t)=>{let n=Q(e)?e.bundle.installSource??``:e.installSource??``,r=Q(t)?t.bundle.installSource??``:t.installSource??``;return n.localeCompare(r)});break}return e},[Be,je]);return k(`div`,{className:`space-y-4`,children:[A&&O(`div`,{className:`rounded-md border border-danger/30 bg-danger/5 px-3 py-2 text-[11px]`,children:k(`div`,{className:`flex items-start justify-between gap-3`,children:[k(`div`,{className:`space-y-0.5`,children:[k(`div`,{className:`font-medium text-danger`,children:[`Failed to update `,A.name]}),O(`div`,{className:`text-foreground-subtle font-mono`,children:A.message})]}),O(`button`,{type:`button`,onClick:()=>j(null),className:`text-foreground-subtle hover:text-foreground text-[10px]`,children:`dismiss`})]})}),k(`div`,{className:`flex items-center gap-2 flex-wrap`,children:[k(`div`,{className:`flex items-center gap-1.5`,children:[O(`span`,{className:`text-[10px] text-foreground-subtle`,children:`Sort:`}),k(`select`,{value:je,onChange:e=>Me(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:[O(`option`,{value:`type`,children:`Bundles first`}),O(`option`,{value:`name`,children:`Name`}),O(`option`,{value:`source`,children:`Install source`})]})]}),k(`div`,{className:`flex items-center gap-1.5`,children:[O(`span`,{className:`text-[10px] text-foreground-subtle`,children:`View:`}),O(`div`,{className:`flex rounded-md border border-border overflow-hidden text-[10px] font-medium`,children:[`grouped`,`flat`].map(e=>O(`button`,{type:`button`,onClick:()=>Fe(e),className:`px-2.5 py-1.5 transition-colors capitalize ${Ne===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))})]}),s.isHub&&k(`div`,{className:`flex items-center gap-1.5`,children:[O(N,{className:`h-3 w-3 text-foreground-subtle`}),O(`span`,{className:`text-[10px] text-foreground-subtle`,children:`Auto-Update:`}),O(`div`,{className:`flex rounded-md border border-border overflow-hidden text-[10px] font-medium`,children:[`off`,`latest`,`beta`].map(e=>O(`button`,{type:`button`,onClick:()=>I.mutate({channel:e}),disabled:I.isPending,className:`px-2.5 py-1.5 transition-colors capitalize ${F?.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))})]}),(b?.length??0)>0&&k(`button`,{type:`button`,onClick:()=>void ke(),disabled:W.isPending||H,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:[O(M,{className:`w-3 h-3 ${W.isPending?`animate-bounce`:``}`}),`Update All (`,b.length,`)`]}),k(`button`,{type:`button`,onClick:u,disabled:d||H,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:[O(N,{className:`w-3 h-3 ${d?`animate-spin`:``}`}),`Refresh`]})]}),k(`div`,{className:`flex items-center gap-3`,children:[k(`div`,{className:`relative flex-1 min-w-[200px]`,ref:y,children:[O(P,{className:`absolute left-2.5 top-1/2 -translate-y-1/2 h-3.5 w-3.5 text-foreground-subtle`}),O(`input`,{type:`text`,value:p,onChange:e=>{m(e.target.value),v(!0)},onFocus:()=>v(!0),placeholder:`Search addons on npm...`,disabled:H,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`}),de&&O(U,{className:`absolute right-2.5 top-1/2 -translate-y-1/2 h-3 w-3 text-foreground-subtle animate-spin`}),_&&R&&R.length>0&&k(`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&&k(`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&&O(`div`,{className:`max-h-72 overflow-auto divide-y divide-border`,children:R.map(e=>k(`div`,{className:`flex items-center gap-3 px-3 py-2 hover:bg-surface-hover transition-colors`,children:[O(`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()}),k(`div`,{className:`flex-1 min-w-0`,children:[k(`div`,{className:`flex items-center gap-2`,children:[O(`span`,{className:`text-[11px] font-semibold truncate`,children:e.name}),k(`span`,{className:`text-[10px] text-foreground-subtle`,children:[`v`,e.version]})]}),e.description&&O(`div`,{className:`text-[10px] text-foreground-subtle truncate`,children:e.description})]}),e.installed?k(`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:[O(L,{className:`h-3 w-3`}),e.installedVersion??`Installed`]}):k(`button`,{type:`button`,onClick:()=>Ae.mutate({packageName:e.name}),disabled:Ae.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:[Ae.isPending?O(U,{className:`h-3 w-3 animate-spin`}):O(M,{className:`h-3 w-3`}),`Install`]})]},e.name))})]})]}),O(X,{onUploadSuccess:()=>{f.invalidateQueries({queryKey:[[`addons`]]}),u()}})]}),$&&k(`div`,{className:`flex items-center gap-2 px-3 py-2 rounded-lg bg-primary/10 border border-primary/30 text-sm`,children:[O(`span`,{className:`text-foreground-subtle`,children:`Filtering by capability:`}),O(`span`,{className:`font-mono text-primary font-semibold`,children:$}),O(`button`,{type:`button`,onClick:ze,className:`ml-auto text-xs text-foreground-subtle hover:text-foreground underline`,children:`Clear`})]}),V!==null&&O(we,{state:V,onCancel:()=>he.mutate({id:V.id})}),ve&&k(`div`,{className:`fixed top-4 right-4 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:[O(ue,{className:`w-4 h-4 shrink-0 mt-0.5 text-green-400`}),k(`div`,{children:[O(`div`,{className:`text-[11px] font-semibold text-foreground`,children:`Bulk update completed`}),O(`div`,{className:`text-[10px] text-foreground-subtle mt-0.5`,children:`System packages updated — hub restarted successfully.`})]})]}),Re.length===0&&O(`div`,{className:`text-xs text-foreground-subtle`,children:e.length===0?`No addons installed`:$?`No installed addons declare the "${$}" capability. Browse the npm catalog above to find a compatible addon.`:`No addons compatible with ${s.name} (placement filter active)`}),O(`div`,{className:`space-y-2`,children:Ve.map(e=>{let n=Q(e)?e.bundle.packageName:e.manifest.packageName,r=ae.get(n),i=Q(e)?e.representative:e,a=be.has(n),o=r?a?()=>xe({packageName:n,fromVersion:be.get(n)?.currentVersion??i.manifest.packageVersion??i.manifest.version,toVersion:r}):()=>le.mutate({name:n,version:r,nodeId:s.id}):void 0;return O(Ce,{addon:i,clusterStatus:t?.[i.manifest.id],bundle:Q(e)?e.bundle:void 0,availableUpdate:r,isUpdating:x===n,onUpdate:o,isSystem:a,bulkItem:me.get(n)??null,disabledByBulk:H},Q(e)?n:e.manifest.id)})}),J!==null&&O(Te,{pending:J,onCancel:()=>{xe(null),Y(null)},onConfirm:()=>{Y(null),Z.mutate({packageName:J.packageName,version:J.toVersion})},isPending:Z.isPending,error:Se})]})}function Ae(){let n=ce(),{data:r,isLoading:i,isError:a}=s(),{data:o}=f(void 0),{data:c}=x(void 0,{refetchInterval:1e4}),l=E(()=>{let e=new Map;e.set(`hub`,{id:`hub`,name:`Hub`,isHub:!0});for(let t of c??[]){let n=String(t.id??``);n&&e.set(n,{id:n,name:String(t.name??n),isHub:!!t.isHub})}return[...e.values()]},[c]),[u,d]=w(`hub`),p=l.find(e=>e.id===u)??l[0],m=e(),ee=y(),h=m.isPending||ee.isPending,te=async()=>{await m.mutateAsync({nodeId:u}),await ee.mutateAsync(),n.invalidateQueries({queryKey:[[`addons`]]})},ne=se(m);ne.current=m,T(()=>{ne.current.mutate({nodeId:`hub`})},[]);let g=(r??[]).map(De).filter(e=>e!==null);return k(W,{children:[k(`div`,{className:`flex items-center justify-between gap-3 flex-wrap`,children:[O(t,{selectedNodeId:u,onSelect:d}),k(`div`,{className:`flex items-center gap-3 flex-wrap`,children:[!i&&!a&&k(`span`,{className:`text-[10px] rounded-full bg-primary/10 text-primary px-2 py-0.5 font-medium`,children:[g.length,` installed`]}),k(`button`,{type:`button`,onClick:()=>void te(),disabled:h,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:[O(N,{className:`w-3 h-3 ${h?`animate-spin`:``}`}),`Check for updates`]})]})]}),!p.isHub&&k(`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`,` `,O(`span`,{className:`font-medium text-foreground`,children:p.name}),` — agents only run`,` `,O(`code`,{className:`font-mono`,children:`agent-only`}),` and`,` `,O(`code`,{className:`font-mono`,children:`any-node`}),` addons. Install / uninstall is hub-driven; agents auto-sync from the hub.`]}),i&&O(`div`,{className:`text-xs text-foreground-subtle animate-pulse`,children:`Loading…`}),a&&O(`div`,{className:`text-xs text-danger`,children:`Failed to load addons`}),!i&&!a&&O(ke,{addons:g,clusterStatus:o,selectedNode:p,onRefresh:()=>void te(),isRefreshing:h})]})}export{Ae as AddonsPage};