@polderlabs/bizar 10.3.0 → 10.4.0

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 (181) hide show
  1. package/bizar-dash/dist/assets/{ActivityFeed-xXiUCZLB.js → ActivityFeed-DtRtg-JN.js} +1 -1
  2. package/bizar-dash/dist/assets/{ActivityFeed-xXiUCZLB.js.map → ActivityFeed-DtRtg-JN.js.map} +1 -1
  3. package/bizar-dash/dist/assets/{ActivityView-nOYhCp3h.js → ActivityView-CoTXDyU_.js} +1 -1
  4. package/bizar-dash/dist/assets/{ActivityView-nOYhCp3h.js.map → ActivityView-CoTXDyU_.js.map} +1 -1
  5. package/bizar-dash/dist/assets/{AdminView-Coi4V3sq.js → AdminView-DNc5Ll7L.js} +1 -1
  6. package/bizar-dash/dist/assets/{AdminView-Coi4V3sq.js.map → AdminView-DNc5Ll7L.js.map} +1 -1
  7. package/bizar-dash/dist/assets/{AgentActivity-nEri4lbx.js → AgentActivity-CrX7LmQ6.js} +1 -1
  8. package/bizar-dash/dist/assets/{AgentActivity-nEri4lbx.js.map → AgentActivity-CrX7LmQ6.js.map} +1 -1
  9. package/bizar-dash/dist/assets/{AgentsView-ByiIJ0ej.js → AgentsView-Du-G_skK.js} +1 -1
  10. package/bizar-dash/dist/assets/{AgentsView-ByiIJ0ej.js.map → AgentsView-Du-G_skK.js.map} +1 -1
  11. package/bizar-dash/dist/assets/{Alert-Dg_Vwxh5.js → Alert-B6DjfRFI.js} +1 -1
  12. package/bizar-dash/dist/assets/{Alert-Dg_Vwxh5.js.map → Alert-B6DjfRFI.js.map} +1 -1
  13. package/bizar-dash/dist/assets/{ArtifactsView-CGclRNnz.js → ArtifactsView-znhN8GTR.js} +1 -1
  14. package/bizar-dash/dist/assets/{ArtifactsView-CGclRNnz.js.map → ArtifactsView-znhN8GTR.js.map} +1 -1
  15. package/bizar-dash/dist/assets/{AuthView-utVm6M3D.js → AuthView-Rk8eKUPr.js} +1 -1
  16. package/bizar-dash/dist/assets/{AuthView-utVm6M3D.js.map → AuthView-Rk8eKUPr.js.map} +1 -1
  17. package/bizar-dash/dist/assets/{Avatar-CXDZdKy4.js → Avatar-B41upSD1.js} +1 -1
  18. package/bizar-dash/dist/assets/{Avatar-CXDZdKy4.js.map → Avatar-B41upSD1.js.map} +1 -1
  19. package/bizar-dash/dist/assets/{BackgroundJobsView-j603pz6o.js → BackgroundJobsView-BLWuN9qz.js} +1 -1
  20. package/bizar-dash/dist/assets/{BackgroundJobsView-j603pz6o.js.map → BackgroundJobsView-BLWuN9qz.js.map} +1 -1
  21. package/bizar-dash/dist/assets/{BackupView-DgvnntTE.js → BackupView-CqbtcnuQ.js} +1 -1
  22. package/bizar-dash/dist/assets/{BackupView-DgvnntTE.js.map → BackupView-CqbtcnuQ.js.map} +1 -1
  23. package/bizar-dash/dist/assets/{Card-D9019JOD.js → Card-rF59wHiO.js} +1 -1
  24. package/bizar-dash/dist/assets/{Card-D9019JOD.js.map → Card-rF59wHiO.js.map} +1 -1
  25. package/bizar-dash/dist/assets/{ChatView-C0cTgj5d.js → ChatView-CUriVEgU.js} +1 -1
  26. package/bizar-dash/dist/assets/{ChatView-C0cTgj5d.js.map → ChatView-CUriVEgU.js.map} +1 -1
  27. package/bizar-dash/dist/assets/{Chip-DQtalZ4y.js → Chip-Dc2KmeWl.js} +1 -1
  28. package/bizar-dash/dist/assets/{Chip-DQtalZ4y.js.map → Chip-Dc2KmeWl.js.map} +1 -1
  29. package/bizar-dash/dist/assets/{ClaudeSessionsView-H3Bqjo6b.js → ClaudeSessionsView-CiaHQdDZ.js} +1 -1
  30. package/bizar-dash/dist/assets/{ClaudeSessionsView-H3Bqjo6b.js.map → ClaudeSessionsView-CiaHQdDZ.js.map} +1 -1
  31. package/bizar-dash/dist/assets/{ClipboardView-BAguaKbx.js → ClipboardView-DdP6aVso.js} +1 -1
  32. package/bizar-dash/dist/assets/{ClipboardView-BAguaKbx.js.map → ClipboardView-DdP6aVso.js.map} +1 -1
  33. package/bizar-dash/dist/assets/{ConfigView-DWHJgoe8.js → ConfigView-B2ysnTZU.js} +1 -1
  34. package/bizar-dash/dist/assets/{ConfigView-DWHJgoe8.js.map → ConfigView-B2ysnTZU.js.map} +1 -1
  35. package/bizar-dash/dist/assets/{DiagnosticsView-oCT624hk.js → DiagnosticsView-88OZ5k0f.js} +1 -1
  36. package/bizar-dash/dist/assets/{DiagnosticsView-oCT624hk.js.map → DiagnosticsView-88OZ5k0f.js.map} +1 -1
  37. package/bizar-dash/dist/assets/{DialogsView-CqHNals_.js → DialogsView-BcqDDCZQ.js} +1 -1
  38. package/bizar-dash/dist/assets/{DialogsView-CqHNals_.js.map → DialogsView-BcqDDCZQ.js.map} +1 -1
  39. package/bizar-dash/dist/assets/{DoctorView-6kfQq_Mx.js → DoctorView-BQwqvMAh.js} +1 -1
  40. package/bizar-dash/dist/assets/{DoctorView-6kfQq_Mx.js.map → DoctorView-BQwqvMAh.js.map} +1 -1
  41. package/bizar-dash/dist/assets/{EmptyState-DLmtBX_6.js → EmptyState-D65J5FQN.js} +1 -1
  42. package/bizar-dash/dist/assets/{EmptyState-DLmtBX_6.js.map → EmptyState-D65J5FQN.js.map} +1 -1
  43. package/bizar-dash/dist/assets/{EnvVarsView-DySOXlP1.js → EnvVarsView-DX-3oGH-.js} +1 -1
  44. package/bizar-dash/dist/assets/{EnvVarsView-DySOXlP1.js.map → EnvVarsView-DX-3oGH-.js.map} +1 -1
  45. package/bizar-dash/dist/assets/{ErrorState-Bump8diE.js → ErrorState-DULZnttJ.js} +1 -1
  46. package/bizar-dash/dist/assets/{ErrorState-Bump8diE.js.map → ErrorState-DULZnttJ.js.map} +1 -1
  47. package/bizar-dash/dist/assets/{EvalView-FnZ5d93z.js → EvalView-CpdFu_ID.js} +1 -1
  48. package/bizar-dash/dist/assets/{EvalView-FnZ5d93z.js.map → EvalView-CpdFu_ID.js.map} +1 -1
  49. package/bizar-dash/dist/assets/{GoalsView-C4m1WnVv.js → GoalsView-Br8oPPfb.js} +1 -1
  50. package/bizar-dash/dist/assets/{GoalsView-C4m1WnVv.js.map → GoalsView-Br8oPPfb.js.map} +1 -1
  51. package/bizar-dash/dist/assets/{Grid-dEnoGGws.js → Grid-BSXhsCPC.js} +1 -1
  52. package/bizar-dash/dist/assets/{Grid-dEnoGGws.js.map → Grid-BSXhsCPC.js.map} +1 -1
  53. package/bizar-dash/dist/assets/{HistoryView-xdRybjZ2.js → HistoryView-D0J3aoZF.js} +1 -1
  54. package/bizar-dash/dist/assets/{HistoryView-xdRybjZ2.js.map → HistoryView-D0J3aoZF.js.map} +1 -1
  55. package/bizar-dash/dist/assets/{Input-BSa3lh_-.js → Input-CZmRw5QX.js} +1 -1
  56. package/bizar-dash/dist/assets/{Input-BSa3lh_-.js.map → Input-CZmRw5QX.js.map} +1 -1
  57. package/bizar-dash/dist/assets/{LibrariesView-1zR04Eci.js → LibrariesView-B1YX9wzp.js} +1 -1
  58. package/bizar-dash/dist/assets/{LibrariesView-1zR04Eci.js.map → LibrariesView-B1YX9wzp.js.map} +1 -1
  59. package/bizar-dash/dist/assets/{LightRAGView-PubmA9oL.js → LightRAGView-CykR0t9y.js} +1 -1
  60. package/bizar-dash/dist/assets/{LightRAGView-PubmA9oL.js.map → LightRAGView-CykR0t9y.js.map} +1 -1
  61. package/bizar-dash/dist/assets/{ListHeader-Ak9WJd39.js → ListHeader-Dpun-r36.js} +1 -1
  62. package/bizar-dash/dist/assets/{ListHeader-Ak9WJd39.js.map → ListHeader-Dpun-r36.js.map} +1 -1
  63. package/bizar-dash/dist/assets/{MemoryView-DBGpuETw.js → MemoryView-BbER5ZKt.js} +1 -1
  64. package/bizar-dash/dist/assets/{MemoryView-DBGpuETw.js.map → MemoryView-BbER5ZKt.js.map} +1 -1
  65. package/bizar-dash/dist/assets/{MiscView-DufqBHkX.js → MiscView-DLNEGdML.js} +1 -1
  66. package/bizar-dash/dist/assets/{MiscView-DufqBHkX.js.map → MiscView-DLNEGdML.js.map} +1 -1
  67. package/bizar-dash/dist/assets/{ModsView-DcX6eVU2.js → ModsView-P7gDeNHM.js} +1 -1
  68. package/bizar-dash/dist/assets/{ModsView-DcX6eVU2.js.map → ModsView-P7gDeNHM.js.map} +1 -1
  69. package/bizar-dash/dist/assets/{NotificationsView-B8IhHRQC.js → NotificationsView-DAm2O0yf.js} +1 -1
  70. package/bizar-dash/dist/assets/{NotificationsView-B8IhHRQC.js.map → NotificationsView-DAm2O0yf.js.map} +1 -1
  71. package/bizar-dash/dist/assets/{ObsidianView-DEuk65zS.js → ObsidianView-Ci80gnwS.js} +1 -1
  72. package/bizar-dash/dist/assets/{ObsidianView-DEuk65zS.js.map → ObsidianView-Ci80gnwS.js.map} +1 -1
  73. package/bizar-dash/dist/assets/{OverviewView-CTI2spTd.js → OverviewView-rriw1GjA.js} +1 -1
  74. package/bizar-dash/dist/assets/{OverviewView-CTI2spTd.js.map → OverviewView-rriw1GjA.js.map} +1 -1
  75. package/bizar-dash/dist/assets/{ProgressBar-D3lkz42E.js → ProgressBar-BahmeJhP.js} +1 -1
  76. package/bizar-dash/dist/assets/{ProgressBar-D3lkz42E.js.map → ProgressBar-BahmeJhP.js.map} +1 -1
  77. package/bizar-dash/dist/assets/{ProjectsView-Du0LzE7A.js → ProjectsView-ChzM12bs.js} +1 -1
  78. package/bizar-dash/dist/assets/{ProjectsView-Du0LzE7A.js.map → ProjectsView-ChzM12bs.js.map} +1 -1
  79. package/bizar-dash/dist/assets/{ProvidersView-5bCgXwBo.js → ProvidersView-BftGn8Cr.js} +1 -1
  80. package/bizar-dash/dist/assets/{ProvidersView-5bCgXwBo.js.map → ProvidersView-BftGn8Cr.js.map} +1 -1
  81. package/bizar-dash/dist/assets/{SchedulesView-DFHdIz5P.js → SchedulesView-CtNxtzN6.js} +1 -1
  82. package/bizar-dash/dist/assets/{SchedulesView-DFHdIz5P.js.map → SchedulesView-CtNxtzN6.js.map} +1 -1
  83. package/bizar-dash/dist/assets/{Select-C8EJj4NM.js → Select-0VcfTDeL.js} +1 -1
  84. package/bizar-dash/dist/assets/{Select-C8EJj4NM.js.map → Select-0VcfTDeL.js.map} +1 -1
  85. package/bizar-dash/dist/assets/{SettingsRow-BdOOmYMD.js → SettingsRow-BLic3DQl.js} +1 -1
  86. package/bizar-dash/dist/assets/{SettingsRow-BdOOmYMD.js.map → SettingsRow-BLic3DQl.js.map} +1 -1
  87. package/bizar-dash/dist/assets/{SettingsView-CqwQ6Knv.js → SettingsView-BjS3i4nr.js} +1 -1
  88. package/bizar-dash/dist/assets/{SettingsView-CqwQ6Knv.js.map → SettingsView-BjS3i4nr.js.map} +1 -1
  89. package/bizar-dash/dist/assets/{Sheet-Cztsvgse.js → Sheet-BOProMs2.js} +1 -1
  90. package/bizar-dash/dist/assets/{Sheet-Cztsvgse.js.map → Sheet-BOProMs2.js.map} +1 -1
  91. package/bizar-dash/dist/assets/{Slider-BexNfF6K.js → Slider-B0eLEEUt.js} +1 -1
  92. package/bizar-dash/dist/assets/{Slider-BexNfF6K.js.map → Slider-B0eLEEUt.js.map} +1 -1
  93. package/bizar-dash/dist/assets/{Sparkline-CLZBtvsN.js → Sparkline-SSrdgyW0.js} +1 -1
  94. package/bizar-dash/dist/assets/{Sparkline-CLZBtvsN.js.map → Sparkline-SSrdgyW0.js.map} +1 -1
  95. package/bizar-dash/dist/assets/{Switch-B1tiRwNK.js → Switch-B3EQzb_q.js} +1 -1
  96. package/bizar-dash/dist/assets/{Switch-B1tiRwNK.js.map → Switch-B3EQzb_q.js.map} +1 -1
  97. package/bizar-dash/dist/assets/{TasksView-CT0fPlos.js → TasksView-SWjF_ZUQ.js} +1 -1
  98. package/bizar-dash/dist/assets/{TasksView-CT0fPlos.js.map → TasksView-SWjF_ZUQ.js.map} +1 -1
  99. package/bizar-dash/dist/assets/{Textarea-D_TPpVMy.js → Textarea-QuofpMlq.js} +1 -1
  100. package/bizar-dash/dist/assets/{Textarea-D_TPpVMy.js.map → Textarea-QuofpMlq.js.map} +1 -1
  101. package/bizar-dash/dist/assets/{UpdateView-tD2q2OhW.js → UpdateView-CEHW2nd6.js} +1 -1
  102. package/bizar-dash/dist/assets/{UpdateView-tD2q2OhW.js.map → UpdateView-CEHW2nd6.js.map} +1 -1
  103. package/bizar-dash/dist/assets/{UsageView-B4BuAFKA.js → UsageView-BqOw6FBg.js} +1 -1
  104. package/bizar-dash/dist/assets/{UsageView-B4BuAFKA.js.map → UsageView-BqOw6FBg.js.map} +1 -1
  105. package/bizar-dash/dist/assets/{ViewHeader-V_SzbUpw.js → ViewHeader-B6P-C4GD.js} +1 -1
  106. package/bizar-dash/dist/assets/{ViewHeader-V_SzbUpw.js.map → ViewHeader-B6P-C4GD.js.map} +1 -1
  107. package/bizar-dash/dist/assets/{VoiceView-D3vb5OM2.js → VoiceView-CwrPwWgi.js} +1 -1
  108. package/bizar-dash/dist/assets/{VoiceView-D3vb5OM2.js.map → VoiceView-CwrPwWgi.js.map} +1 -1
  109. package/bizar-dash/dist/assets/{brain-BmfWcitQ.js → brain-CwZt9Kta.js} +1 -1
  110. package/bizar-dash/dist/assets/{brain-BmfWcitQ.js.map → brain-CwZt9Kta.js.map} +1 -1
  111. package/bizar-dash/dist/assets/{calendar-VntJUzFB.js → calendar-C5oK0_nM.js} +1 -1
  112. package/bizar-dash/dist/assets/{calendar-VntJUzFB.js.map → calendar-C5oK0_nM.js.map} +1 -1
  113. package/bizar-dash/dist/assets/{circle-KrQQySeK.js → circle-D1Lc_P2a.js} +1 -1
  114. package/bizar-dash/dist/assets/{circle-KrQQySeK.js.map → circle-D1Lc_P2a.js.map} +1 -1
  115. package/bizar-dash/dist/assets/{circle-alert-CQ9MLygI.js → circle-alert-HdHe7m8K.js} +1 -1
  116. package/bizar-dash/dist/assets/{circle-alert-CQ9MLygI.js.map → circle-alert-HdHe7m8K.js.map} +1 -1
  117. package/bizar-dash/dist/assets/{circle-check-COtVgsWw.js → circle-check-Cs-xoV7R.js} +1 -1
  118. package/bizar-dash/dist/assets/{circle-check-COtVgsWw.js.map → circle-check-Cs-xoV7R.js.map} +1 -1
  119. package/bizar-dash/dist/assets/{clock-C0GlM4qp.js → clock-DEIuPV60.js} +1 -1
  120. package/bizar-dash/dist/assets/{clock-C0GlM4qp.js.map → clock-DEIuPV60.js.map} +1 -1
  121. package/bizar-dash/dist/assets/{download-CW4DmtRe.js → download-Clkq90Ct.js} +1 -1
  122. package/bizar-dash/dist/assets/{download-CW4DmtRe.js.map → download-Clkq90Ct.js.map} +1 -1
  123. package/bizar-dash/dist/assets/{external-link-CAOnh_DH.js → external-link-D5tq2o_I.js} +1 -1
  124. package/bizar-dash/dist/assets/{external-link-CAOnh_DH.js.map → external-link-D5tq2o_I.js.map} +1 -1
  125. package/bizar-dash/dist/assets/{file-text-CS1jB_oV.js → file-text-CQ12t7Oc.js} +1 -1
  126. package/bizar-dash/dist/assets/{file-text-CS1jB_oV.js.map → file-text-CQ12t7Oc.js.map} +1 -1
  127. package/bizar-dash/dist/assets/{filter-DyQbml3L.js → filter-BcbE37wP.js} +1 -1
  128. package/bizar-dash/dist/assets/{filter-DyQbml3L.js.map → filter-BcbE37wP.js.map} +1 -1
  129. package/bizar-dash/dist/assets/{git-pull-request-Co6gYfba.js → git-pull-request-D1qNDRia.js} +1 -1
  130. package/bizar-dash/dist/assets/{git-pull-request-Co6gYfba.js.map → git-pull-request-D1qNDRia.js.map} +1 -1
  131. package/bizar-dash/dist/assets/{main-CyAIirBB.js → main-Cxeu4LhG.js} +2 -2
  132. package/bizar-dash/dist/assets/{main-CyAIirBB.js.map → main-Cxeu4LhG.js.map} +1 -1
  133. package/bizar-dash/dist/assets/{network-CDn43Gsj.js → network-DJdvVaHx.js} +1 -1
  134. package/bizar-dash/dist/assets/{network-CDn43Gsj.js.map → network-DJdvVaHx.js.map} +1 -1
  135. package/bizar-dash/dist/assets/{pause-CKYjSTGX.js → pause-DUn9L5PB.js} +1 -1
  136. package/bizar-dash/dist/assets/{pause-CKYjSTGX.js.map → pause-DUn9L5PB.js.map} +1 -1
  137. package/bizar-dash/dist/assets/{pencil-BUJ2DpWs.js → pencil-DVrBlYV3.js} +1 -1
  138. package/bizar-dash/dist/assets/{pencil-BUJ2DpWs.js.map → pencil-DVrBlYV3.js.map} +1 -1
  139. package/bizar-dash/dist/assets/{play-CGxZWqtW.js → play-CZjsr3XM.js} +1 -1
  140. package/bizar-dash/dist/assets/{play-CGxZWqtW.js.map → play-CZjsr3XM.js.map} +1 -1
  141. package/bizar-dash/dist/assets/{plug-CQYGgGSy.js → plug-BKuyIe5W.js} +1 -1
  142. package/bizar-dash/dist/assets/{plug-CQYGgGSy.js.map → plug-BKuyIe5W.js.map} +1 -1
  143. package/bizar-dash/dist/assets/{plus-fFxt-8z5.js → plus-77h62zZm.js} +1 -1
  144. package/bizar-dash/dist/assets/{plus-fFxt-8z5.js.map → plus-77h62zZm.js.map} +1 -1
  145. package/bizar-dash/dist/assets/{power-Cjgy2KsI.js → power-DLmx-gCP.js} +1 -1
  146. package/bizar-dash/dist/assets/{power-Cjgy2KsI.js.map → power-DLmx-gCP.js.map} +1 -1
  147. package/bizar-dash/dist/assets/{power-off-B81hLRah.js → power-off-BFKzHXic.js} +1 -1
  148. package/bizar-dash/dist/assets/{power-off-B81hLRah.js.map → power-off-BFKzHXic.js.map} +1 -1
  149. package/bizar-dash/dist/assets/{refresh-ccw-BCXx86xp.js → refresh-ccw-DenGBOcq.js} +1 -1
  150. package/bizar-dash/dist/assets/{refresh-ccw-BCXx86xp.js.map → refresh-ccw-DenGBOcq.js.map} +1 -1
  151. package/bizar-dash/dist/assets/{refresh-cw-COTg1nZo.js → refresh-cw-ENBVR8hW.js} +1 -1
  152. package/bizar-dash/dist/assets/{refresh-cw-COTg1nZo.js.map → refresh-cw-ENBVR8hW.js.map} +1 -1
  153. package/bizar-dash/dist/assets/{rotate-ccw-BZrEVc0Z.js → rotate-ccw-MxryaY7q.js} +1 -1
  154. package/bizar-dash/dist/assets/{rotate-ccw-BZrEVc0Z.js.map → rotate-ccw-MxryaY7q.js.map} +1 -1
  155. package/bizar-dash/dist/assets/{rotate-cw-CsTtaLV2.js → rotate-cw-CDOlRtUR.js} +1 -1
  156. package/bizar-dash/dist/assets/{rotate-cw-CsTtaLV2.js.map → rotate-cw-CDOlRtUR.js.map} +1 -1
  157. package/bizar-dash/dist/assets/{save-DtMTge1F.js → save-Db1b-1Uq.js} +1 -1
  158. package/bizar-dash/dist/assets/{save-DtMTge1F.js.map → save-Db1b-1Uq.js.map} +1 -1
  159. package/bizar-dash/dist/assets/{send-DyBhyk8t.js → send-yz6HFZM5.js} +1 -1
  160. package/bizar-dash/dist/assets/{send-DyBhyk8t.js.map → send-yz6HFZM5.js.map} +1 -1
  161. package/bizar-dash/dist/assets/{shield-alert-BPGJlRF8.js → shield-alert-DY6RAaC8.js} +1 -1
  162. package/bizar-dash/dist/assets/{shield-alert-BPGJlRF8.js.map → shield-alert-DY6RAaC8.js.map} +1 -1
  163. package/bizar-dash/dist/assets/{trash-2-2NsyTU8c.js → trash-2-Cv7U38jw.js} +1 -1
  164. package/bizar-dash/dist/assets/{trash-2-2NsyTU8c.js.map → trash-2-Cv7U38jw.js.map} +1 -1
  165. package/bizar-dash/dist/assets/{trending-up-BXwP23VK.js → trending-up-CRPNagyX.js} +1 -1
  166. package/bizar-dash/dist/assets/{trending-up-BXwP23VK.js.map → trending-up-CRPNagyX.js.map} +1 -1
  167. package/bizar-dash/dist/assets/{triangle-alert-DFmQ_RXN.js → triangle-alert-tUTXbcEP.js} +1 -1
  168. package/bizar-dash/dist/assets/{triangle-alert-DFmQ_RXN.js.map → triangle-alert-tUTXbcEP.js.map} +1 -1
  169. package/bizar-dash/dist/assets/{upload-Cj-HYRYV.js → upload-Cq7uTsrT.js} +1 -1
  170. package/bizar-dash/dist/assets/{upload-Cj-HYRYV.js.map → upload-Cq7uTsrT.js.map} +1 -1
  171. package/bizar-dash/dist/assets/{zap-BaOiybcl.js → zap-5lAQBAPX.js} +1 -1
  172. package/bizar-dash/dist/assets/{zap-BaOiybcl.js.map → zap-5lAQBAPX.js.map} +1 -1
  173. package/bizar-dash/dist/index.html +1 -1
  174. package/bizar-dash/src/server/api.mjs +5 -1
  175. package/bizar-dash/src/web/v8/shell/Sidebar.tsx +3 -3
  176. package/cli/doctor.mjs +1 -1
  177. package/package.json +1 -1
  178. package/packages/sdk/dist/mcp/server.js +41 -409
  179. package/packages/sdk/dist/router/q-learning-router.d.ts +3 -5
  180. package/packages/sdk/dist/router/q-learning-router.js +9 -5
  181. package/packages/sdk/package.json +1 -1
@@ -1 +1 @@
1
- {"version":3,"file":"ClaudeSessionsView-H3Bqjo6b.js","sources":["../../src/web/v8/views/ClaudeSessions/ClaudeSessionDetail.tsx","../../src/web/v8/views/ClaudeSessions/ClaudeSessionsView.tsx"],"sourcesContent":["/**\n * v8/views/ClaudeSessions/ClaudeSessionDetail.tsx — Sprint S39, v9.3.0.\n *\n * Right-pane content for the ClaudeSessionSheet. Pulls messages\n * from /api/claude-sessions/:id/messages, lets the user send a\n * follow-up via /api/claude-sessions/:id/send. No streaming in\n * this initial cut — the server's SSE endpoint\n * (/api/claude-sessions/:id/stream) is read by the SDK in\n * production, but for the dashboard we treat send as fire-and-\n * refresh so the user sees the new turn after the resume exits.\n */\n\nimport { useCallback, useState } from 'react';\nimport { Send, RefreshCcw } from 'lucide-react';\nimport { Stack } from '../../ui/primitives/Stack.js';\nimport { Inline } from '../../ui/primitives/Inline.js';\nimport { Card, CardBody } from '../../ui/data/Card.js';\nimport { Button } from '../../ui/controls/Button.js';\nimport { Input } from '../../ui/controls/Input.js';\nimport { Skeleton } from '../../ui/feedback/Skeleton.js';\nimport { useFetch } from '../../data/useFetch.js';\nimport { fetchJson, FetchError } from '../../data/fetcher.js';\nimport type { ChatMessage } from '../../data/types.js';\nimport { MessageBubble } from '../../ui/chat/MessageBubble.js';\n\ninterface MessagesPayload {\n messages: ChatMessage[];\n}\n\nexport function ClaudeSessionDetail({ sessionId }: { sessionId: string }): JSX.Element {\n const url = `/api/claude-sessions/${sessionId}/messages`;\n const payload = useFetch<MessagesPayload>(url);\n const [draft, setDraft] = useState<string>('');\n const [agent, setAgent] = useState<string>('general');\n const [busy, setBusy] = useState<boolean>(false);\n const [error, setError] = useState<string | null>(null);\n\n const refresh = useCallback(() => { void payload.refetch(); }, [payload]);\n const messages = payload.data?.messages ?? [];\n\n const send = async (): Promise<void> => {\n const text = draft.trim();\n if (!text || !agent.trim() || busy) return;\n setBusy(true);\n setError(null);\n try {\n await fetchJson(`/api/claude-sessions/${sessionId}/send`, {\n method: 'POST',\n body: { message: text, agent: agent.trim() },\n });\n setDraft('');\n // The resume spawn is asynchronous; give it a moment then refresh.\n window.setTimeout(() => { refresh(); }, 750);\n } catch (err) {\n setError(err instanceof FetchError ? err.message : (err as Error).message);\n } finally {\n setBusy(false);\n }\n };\n\n return (\n <Stack gap={3} style={{ padding: 'var(--space-4)' }} data-testid={`claude-session-detail-${sessionId}`}>\n <Inline align=\"center\" justify=\"between\" gap={2}>\n <strong style={{ fontFamily: 'var(--font-mono)', fontSize: 'var(--fs-12)' }}>{sessionId}</strong>\n <Button variant=\"ghost\" onClick={() => void refresh()} data-testid={`claude-session-detail-refresh-${sessionId}`}>\n <RefreshCcw size={14} aria-hidden /> Refresh\n </Button>\n </Inline>\n\n <Card variant=\"default\">\n <CardBody>\n {payload.loading && messages.length === 0 ? (\n <Skeleton style={{ height: 120 }} />\n ) : messages.length === 0 ? (\n <span style={{ color: 'var(--fg-muted)', fontSize: 'var(--fs-12)' }}>\n No messages yet — start with a follow-up.\n </span>\n ) : (\n <Stack gap={1}>\n {messages.map((m) => (\n <MessageBubble key={m.id || `${m.ts}-${m.role}`} message={m} />\n ))}\n </Stack>\n )}\n </CardBody>\n </Card>\n\n {error !== null && (\n <span role=\"alert\" data-testid={`claude-session-detail-error-${sessionId}`} style={{ color: 'var(--danger)', fontSize: 'var(--fs-12)' }}>\n {error}\n </span>\n )}\n\n <label style={{ display: 'flex', flexDirection: 'column', gap: 'var(--space-1)' }}>\n <span style={{ fontSize: 'var(--fs-12)', color: 'var(--fg-muted)' }}>Agent</span>\n <Input\n value={agent}\n data-testid={`claude-session-detail-agent-${sessionId}`}\n onChange={(e) => setAgent((e.target as HTMLInputElement).value)}\n />\n </label>\n <label style={{ display: 'flex', flexDirection: 'column', gap: 'var(--space-1)' }}>\n <span style={{ fontSize: 'var(--fs-12)', color: 'var(--fg-muted)' }}>Follow-up</span>\n <textarea\n value={draft}\n rows={4}\n data-testid={`claude-session-detail-draft-${sessionId}`}\n onChange={(e) => setDraft((e.target as HTMLTextAreaElement).value)}\n style={{\n background: 'var(--surface-0)',\n border: '1px solid var(--border)',\n borderRadius: 'var(--radius-md)',\n padding: 'var(--space-2)',\n color: 'var(--fg)',\n fontFamily: 'var(--font-sans)',\n fontSize: 'var(--fs-13)',\n resize: 'vertical',\n }}\n />\n </label>\n <Inline justify=\"end\" gap={2}>\n <Button\n variant=\"primary\"\n onClick={() => void send()}\n disabled={busy || draft.trim() === '' || agent.trim() === ''}\n data-testid={`claude-session-detail-send-${sessionId}`}\n >\n <Send size={14} aria-hidden /> {busy ? 'Sending…' : 'Send'}\n </Button>\n </Inline>\n </Stack>\n );\n}","/**\n * v8/views/ClaudeSessions/ClaudeSessionsView.tsx — Sprint S39, v9.3.0.\n *\n * Claude Code session explorer. Lists sessions on disk (via\n * /api/claude-sessions), lets the user create a new one via Sheet\n * (POST /api/claude-sessions/new), inline-rename (PATCH\n * /api/claude-sessions/:id), inline-confirm delete (DELETE\n * /api/claude-sessions/:id), and opens a right Drawer with the\n * session detail (ClaudeSessionDetail).\n */\n\nimport { useCallback, useState } from 'react';\nimport { Plus, Trash2, Pencil, RefreshCcw, MessageSquareText } from 'lucide-react';\nimport { Stack } from '../../ui/primitives/Stack.js';\nimport { Inline } from '../../ui/primitives/Inline.js';\nimport { ViewHeader } from '../../ui/data/ViewHeader.js';\nimport { Card, CardBody } from '../../ui/data/Card.js';\nimport { Button } from '../../ui/controls/Button.js';\nimport { Input } from '../../ui/controls/Input.js';\nimport { Sheet, SheetClose, SheetContent } from '../../ui/feedback/Sheet.js';\nimport { Skeleton } from '../../ui/feedback/Skeleton.js';\nimport { EmptyState } from '../../ui/feedback/EmptyState.js';\nimport { useFetch } from '../../data/useFetch.js';\nimport { fetchJson, FetchError } from '../../data/fetcher.js';\nimport type { ClaudeSession } from '../../data/types.js';\nimport { ClaudeSessionDetail } from './ClaudeSessionDetail.js';\n\ninterface SessionsPayload {\n sessions: ClaudeSession[];\n}\n\nexport function ClaudeSessionsView(): JSX.Element {\n const payload = useFetch<SessionsPayload>('/api/claude-sessions');\n const [creating, setCreating] = useState<boolean>(false);\n const [detailId, setDetailId] = useState<string | null>(null);\n\n const sessions = payload.data?.sessions ?? [];\n\n const refresh = useCallback(() => { void payload.refetch(); }, [payload]);\n\n return (\n <Stack gap={4} data-testid=\"claude-sessions-view\">\n <ViewHeader\n title=\"Claude sessions\"\n description=\"Claude Code session explorer. Each row is a session directory under ~/.claude/sessions/.\"\n actions={\n <Inline align=\"center\" gap={2}>\n <Button variant=\"ghost\" onClick={() => void refresh()} data-testid=\"claude-sessions-refresh\">\n <RefreshCcw size={14} aria-hidden /> Refresh\n </Button>\n <Button variant=\"primary\" onClick={() => setCreating(true)} data-testid=\"claude-sessions-new\">\n <Plus size={14} aria-hidden /> New session\n </Button>\n </Inline>\n }\n />\n\n <Card variant=\"default\">\n <CardBody>\n {payload.loading && sessions.length === 0 ? (\n <Stack gap={2}>\n <Skeleton style={{ height: 36 }} />\n <Skeleton style={{ height: 36 }} />\n </Stack>\n ) : sessions.length === 0 ? (\n <EmptyState\n icon={<MessageSquareText size={28} aria-hidden />}\n title=\"No Claude sessions\"\n description=\"Create one to start a multi-turn conversation with Claude Code.\"\n />\n ) : (\n <Stack gap={2}>\n {sessions.map((s) => (\n <SessionRow key={s.id} session={s} onRefresh={refresh} onOpen={setDetailId} />\n ))}\n </Stack>\n )}\n </CardBody>\n </Card>\n\n <Sheet open={creating} onOpenChange={setCreating}>\n <SheetContent side=\"right\" title=\"New Claude session\" description=\"Spawn a Claude Code session via the runner.\">\n <NewSessionForm\n onCreated={(id) => {\n setCreating(false);\n refresh();\n setDetailId(id);\n }}\n onCancel={() => setCreating(false)}\n />\n </SheetContent>\n </Sheet>\n\n <Sheet open={detailId !== null} onOpenChange={(open) => { if (!open) setDetailId(null); }}>\n <SheetContent side=\"right\" title=\"Session detail\" description={detailId ?? ''}>\n {detailId !== null && <ClaudeSessionDetail sessionId={detailId} />}\n </SheetContent>\n </Sheet>\n </Stack>\n );\n}\n\nfunction SessionRow({\n session,\n onRefresh,\n onOpen,\n}: {\n session: ClaudeSession;\n onRefresh: () => void;\n onOpen: (id: string) => void;\n}): JSX.Element {\n const [renaming, setRenaming] = useState<boolean>(false);\n const [title, setTitle] = useState<string>(session.title ?? '');\n const [confirmDelete, setConfirmDelete] = useState<boolean>(false);\n const [error, setError] = useState<string | null>(null);\n\n const rename = async (): Promise<void> => {\n if (!title.trim()) return;\n setError(null);\n try {\n await fetchJson(`/api/claude-sessions/${session.id}`, {\n method: 'PATCH',\n body: { title: title.trim() },\n });\n setRenaming(false);\n onRefresh();\n } catch (err) {\n setError(err instanceof FetchError ? err.message : (err as Error).message);\n }\n };\n\n const resume = async (id: string): Promise<void> => {\n setError(null);\n try {\n await fetchJson(`/api/claude-sessions/${id}/resume`, { method: 'POST', body: {} });\n } catch (err) {\n setError(err instanceof FetchError ? err.message : (err as Error).message);\n }\n };\n\n const remove = async (): Promise<void> => {\n setError(null);\n try {\n await fetchJson(`/api/claude-sessions/${session.id}`, { method: 'DELETE' });\n setConfirmDelete(false);\n onRefresh();\n } catch (err) {\n setError(err instanceof FetchError ? err.message : (err as Error).message);\n }\n };\n\n return (\n <div\n data-testid={`claude-session-row-${session.id}`}\n style={{\n padding: 'var(--space-3)',\n borderRadius: 'var(--radius-md)',\n border: '1px solid var(--border)',\n background: 'var(--surface-0)',\n }}\n >\n <Inline align=\"center\" justify=\"between\" gap={3}>\n <Stack gap={1} style={{ minWidth: 0, flex: 1 }}>\n {renaming ? (\n <Inline gap={1}>\n <Input\n value={title}\n data-testid={`claude-session-rename-input-${session.id}`}\n onChange={(e) => setTitle((e.target as HTMLInputElement).value)}\n />\n <Button variant=\"primary\" onClick={() => void rename()} data-testid={`claude-session-rename-submit-${session.id}`}>Save</Button>\n <Button variant=\"ghost\" onClick={() => { setRenaming(false); setTitle(session.title ?? ''); }}>Cancel</Button>\n </Inline>\n ) : (\n <Inline align=\"center\" gap={2}>\n <strong style={{ fontSize: 'var(--fs-13)' }}>{session.title || session.id}</strong>\n {session.agent && (\n <span style={{ fontSize: 'var(--fs-12)', color: 'var(--fg-muted)', fontFamily: 'var(--font-mono)' }}>\n @{session.agent}\n </span>\n )}\n </Inline>\n )}\n <span style={{ fontFamily: 'var(--font-mono)', fontSize: 'var(--fs-12)', color: 'var(--fg-muted)' }}>\n {session.id}\n </span>\n {error !== null && (\n <span role=\"alert\" style={{ color: 'var(--danger)', fontSize: 'var(--fs-12)' }}>{error}</span>\n )}\n </Stack>\n <Inline gap={1}>\n <Button variant=\"primary\" onClick={() => void resume(session.id)} data-testid={`claude-session-resume-${session.id}`} aria-label={`Resume ${session.id}`}>\n Resume\n </Button>\n <Button variant=\"ghost\" onClick={() => onOpen(session.id)} data-testid={`claude-session-open-${session.id}`}>\n Open\n </Button>\n <Button\n variant=\"ghost\"\n onClick={() => { setRenaming(true); setTitle(session.title ?? ''); }}\n data-testid={`claude-session-rename-${session.id}`}\n aria-label={`Rename session ${session.id}`}\n >\n <Pencil size={14} aria-hidden />\n </Button>\n <Button\n variant=\"ghost\"\n onClick={() => setConfirmDelete((cur) => !cur)}\n data-testid={`claude-session-delete-${session.id}`}\n aria-label={`Delete session ${session.id}`}\n >\n <Trash2 size={14} aria-hidden />\n </Button>\n </Inline>\n </Inline>\n {confirmDelete && (\n <Inline gap={1} style={{ marginTop: 'var(--space-2)' }}>\n <Button variant=\"danger\" onClick={() => void remove()} data-testid={`claude-session-confirm-delete-${session.id}`}>\n Confirm delete\n </Button>\n <Button variant=\"ghost\" onClick={() => setConfirmDelete(false)} data-testid={`claude-session-cancel-delete-${session.id}`}>\n Cancel\n </Button>\n </Inline>\n )}\n </div>\n );\n}\n\nfunction NewSessionForm({\n onCreated,\n onCancel,\n}: {\n onCreated: (id: string) => void;\n onCancel: () => void;\n}): JSX.Element {\n const [title, setTitle] = useState<string>('');\n const [agent, setAgent] = useState<string>('general');\n const [prompt, setPrompt] = useState<string>('');\n const [directory, setDirectory] = useState<string>('');\n const [busy, setBusy] = useState<boolean>(false);\n const [error, setError] = useState<string | null>(null);\n\n const submit = async (): Promise<void> => {\n if (!agent.trim() || !prompt.trim() || busy) return;\n setBusy(true);\n setError(null);\n try {\n const res = await fetchJson<{ id: string }>('/api/claude-sessions/new', {\n method: 'POST',\n body: {\n title: title.trim() || null,\n agent: agent.trim(),\n prompt: prompt.trim(),\n directory: directory.trim() || undefined,\n },\n });\n onCreated(res.id);\n } catch (err) {\n setError(err instanceof FetchError ? err.message : (err as Error).message);\n } finally {\n setBusy(false);\n }\n };\n\n return (\n <Stack gap={3} style={{ padding: 'var(--space-4)' }}>\n <label style={{ display: 'flex', flexDirection: 'column', gap: 'var(--space-1)' }}>\n <span style={{ fontSize: 'var(--fs-12)', color: 'var(--fg-muted)' }}>Title (optional)</span>\n <Input\n value={title}\n data-testid=\"claude-sessions-new-title\"\n onChange={(e) => setTitle((e.target as HTMLInputElement).value)}\n />\n </label>\n <label style={{ display: 'flex', flexDirection: 'column', gap: 'var(--space-1)' }}>\n <span style={{ fontSize: 'var(--fs-12)', color: 'var(--fg-muted)' }}>Agent</span>\n <Input\n value={agent}\n data-testid=\"claude-sessions-new-agent\"\n onChange={(e) => setAgent((e.target as HTMLInputElement).value)}\n />\n </label>\n <label style={{ display: 'flex', flexDirection: 'column', gap: 'var(--space-1)' }}>\n <span style={{ fontSize: 'var(--fs-12)', color: 'var(--fg-muted)' }}>Seed prompt</span>\n <textarea\n value={prompt}\n rows={4}\n data-testid=\"claude-sessions-new-prompt\"\n onChange={(e) => setPrompt((e.target as HTMLTextAreaElement).value)}\n style={{\n background: 'var(--surface-0)',\n border: '1px solid var(--border)',\n borderRadius: 'var(--radius-md)',\n padding: 'var(--space-2)',\n color: 'var(--fg)',\n fontFamily: 'var(--font-sans)',\n fontSize: 'var(--fs-13)',\n resize: 'vertical',\n }}\n />\n </label>\n <label style={{ display: 'flex', flexDirection: 'column', gap: 'var(--space-1)' }}>\n <span style={{ fontSize: 'var(--fs-12)', color: 'var(--fg-muted)' }}>Working directory (optional)</span>\n <Input\n value={directory}\n data-testid=\"claude-sessions-new-directory\"\n onChange={(e) => setDirectory((e.target as HTMLInputElement).value)}\n />\n </label>\n {error !== null && (\n <span role=\"alert\" data-testid=\"claude-sessions-new-error\" style={{ color: 'var(--danger)', fontSize: 'var(--fs-12)' }}>\n {error}\n </span>\n )}\n <Inline justify=\"end\" gap={2}>\n <SheetClose asChild>\n <Button variant=\"ghost\" onClick={onCancel} data-testid=\"claude-sessions-new-cancel\">Cancel</Button>\n </SheetClose>\n <Button\n variant=\"primary\"\n onClick={() => void submit()}\n disabled={busy || !agent.trim() || !prompt.trim()}\n data-testid=\"claude-sessions-new-submit\"\n >\n Create\n </Button>\n </Inline>\n </Stack>\n );\n}"],"names":["ClaudeSessionDetail","sessionId","url","payload","useFetch","draft","setDraft","useState","agent","setAgent","busy","setBusy","error","setError","refresh","useCallback","messages","_a","send","text","fetchJson","err","FetchError","jsxs","Stack","Inline","jsx","Button","RefreshCcw","Card","CardBody","Skeleton","m","MessageBubble","Input","e","Send","ClaudeSessionsView","creating","setCreating","detailId","setDetailId","sessions","ViewHeader","Plus","EmptyState","MessageSquareText","s","SessionRow","Sheet","SheetContent","NewSessionForm","id","open","session","onRefresh","onOpen","renaming","setRenaming","title","setTitle","confirmDelete","setConfirmDelete","rename","resume","remove","Pencil","cur","Trash2","onCreated","onCancel","prompt","setPrompt","directory","setDirectory","submit","res","SheetClose"],"mappings":"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"}
1
+ {"version":3,"file":"ClaudeSessionsView-CiaHQdDZ.js","sources":["../../src/web/v8/views/ClaudeSessions/ClaudeSessionDetail.tsx","../../src/web/v8/views/ClaudeSessions/ClaudeSessionsView.tsx"],"sourcesContent":["/**\n * v8/views/ClaudeSessions/ClaudeSessionDetail.tsx — Sprint S39, v9.3.0.\n *\n * Right-pane content for the ClaudeSessionSheet. Pulls messages\n * from /api/claude-sessions/:id/messages, lets the user send a\n * follow-up via /api/claude-sessions/:id/send. No streaming in\n * this initial cut — the server's SSE endpoint\n * (/api/claude-sessions/:id/stream) is read by the SDK in\n * production, but for the dashboard we treat send as fire-and-\n * refresh so the user sees the new turn after the resume exits.\n */\n\nimport { useCallback, useState } from 'react';\nimport { Send, RefreshCcw } from 'lucide-react';\nimport { Stack } from '../../ui/primitives/Stack.js';\nimport { Inline } from '../../ui/primitives/Inline.js';\nimport { Card, CardBody } from '../../ui/data/Card.js';\nimport { Button } from '../../ui/controls/Button.js';\nimport { Input } from '../../ui/controls/Input.js';\nimport { Skeleton } from '../../ui/feedback/Skeleton.js';\nimport { useFetch } from '../../data/useFetch.js';\nimport { fetchJson, FetchError } from '../../data/fetcher.js';\nimport type { ChatMessage } from '../../data/types.js';\nimport { MessageBubble } from '../../ui/chat/MessageBubble.js';\n\ninterface MessagesPayload {\n messages: ChatMessage[];\n}\n\nexport function ClaudeSessionDetail({ sessionId }: { sessionId: string }): JSX.Element {\n const url = `/api/claude-sessions/${sessionId}/messages`;\n const payload = useFetch<MessagesPayload>(url);\n const [draft, setDraft] = useState<string>('');\n const [agent, setAgent] = useState<string>('general');\n const [busy, setBusy] = useState<boolean>(false);\n const [error, setError] = useState<string | null>(null);\n\n const refresh = useCallback(() => { void payload.refetch(); }, [payload]);\n const messages = payload.data?.messages ?? [];\n\n const send = async (): Promise<void> => {\n const text = draft.trim();\n if (!text || !agent.trim() || busy) return;\n setBusy(true);\n setError(null);\n try {\n await fetchJson(`/api/claude-sessions/${sessionId}/send`, {\n method: 'POST',\n body: { message: text, agent: agent.trim() },\n });\n setDraft('');\n // The resume spawn is asynchronous; give it a moment then refresh.\n window.setTimeout(() => { refresh(); }, 750);\n } catch (err) {\n setError(err instanceof FetchError ? err.message : (err as Error).message);\n } finally {\n setBusy(false);\n }\n };\n\n return (\n <Stack gap={3} style={{ padding: 'var(--space-4)' }} data-testid={`claude-session-detail-${sessionId}`}>\n <Inline align=\"center\" justify=\"between\" gap={2}>\n <strong style={{ fontFamily: 'var(--font-mono)', fontSize: 'var(--fs-12)' }}>{sessionId}</strong>\n <Button variant=\"ghost\" onClick={() => void refresh()} data-testid={`claude-session-detail-refresh-${sessionId}`}>\n <RefreshCcw size={14} aria-hidden /> Refresh\n </Button>\n </Inline>\n\n <Card variant=\"default\">\n <CardBody>\n {payload.loading && messages.length === 0 ? (\n <Skeleton style={{ height: 120 }} />\n ) : messages.length === 0 ? (\n <span style={{ color: 'var(--fg-muted)', fontSize: 'var(--fs-12)' }}>\n No messages yet — start with a follow-up.\n </span>\n ) : (\n <Stack gap={1}>\n {messages.map((m) => (\n <MessageBubble key={m.id || `${m.ts}-${m.role}`} message={m} />\n ))}\n </Stack>\n )}\n </CardBody>\n </Card>\n\n {error !== null && (\n <span role=\"alert\" data-testid={`claude-session-detail-error-${sessionId}`} style={{ color: 'var(--danger)', fontSize: 'var(--fs-12)' }}>\n {error}\n </span>\n )}\n\n <label style={{ display: 'flex', flexDirection: 'column', gap: 'var(--space-1)' }}>\n <span style={{ fontSize: 'var(--fs-12)', color: 'var(--fg-muted)' }}>Agent</span>\n <Input\n value={agent}\n data-testid={`claude-session-detail-agent-${sessionId}`}\n onChange={(e) => setAgent((e.target as HTMLInputElement).value)}\n />\n </label>\n <label style={{ display: 'flex', flexDirection: 'column', gap: 'var(--space-1)' }}>\n <span style={{ fontSize: 'var(--fs-12)', color: 'var(--fg-muted)' }}>Follow-up</span>\n <textarea\n value={draft}\n rows={4}\n data-testid={`claude-session-detail-draft-${sessionId}`}\n onChange={(e) => setDraft((e.target as HTMLTextAreaElement).value)}\n style={{\n background: 'var(--surface-0)',\n border: '1px solid var(--border)',\n borderRadius: 'var(--radius-md)',\n padding: 'var(--space-2)',\n color: 'var(--fg)',\n fontFamily: 'var(--font-sans)',\n fontSize: 'var(--fs-13)',\n resize: 'vertical',\n }}\n />\n </label>\n <Inline justify=\"end\" gap={2}>\n <Button\n variant=\"primary\"\n onClick={() => void send()}\n disabled={busy || draft.trim() === '' || agent.trim() === ''}\n data-testid={`claude-session-detail-send-${sessionId}`}\n >\n <Send size={14} aria-hidden /> {busy ? 'Sending…' : 'Send'}\n </Button>\n </Inline>\n </Stack>\n );\n}","/**\n * v8/views/ClaudeSessions/ClaudeSessionsView.tsx — Sprint S39, v9.3.0.\n *\n * Claude Code session explorer. Lists sessions on disk (via\n * /api/claude-sessions), lets the user create a new one via Sheet\n * (POST /api/claude-sessions/new), inline-rename (PATCH\n * /api/claude-sessions/:id), inline-confirm delete (DELETE\n * /api/claude-sessions/:id), and opens a right Drawer with the\n * session detail (ClaudeSessionDetail).\n */\n\nimport { useCallback, useState } from 'react';\nimport { Plus, Trash2, Pencil, RefreshCcw, MessageSquareText } from 'lucide-react';\nimport { Stack } from '../../ui/primitives/Stack.js';\nimport { Inline } from '../../ui/primitives/Inline.js';\nimport { ViewHeader } from '../../ui/data/ViewHeader.js';\nimport { Card, CardBody } from '../../ui/data/Card.js';\nimport { Button } from '../../ui/controls/Button.js';\nimport { Input } from '../../ui/controls/Input.js';\nimport { Sheet, SheetClose, SheetContent } from '../../ui/feedback/Sheet.js';\nimport { Skeleton } from '../../ui/feedback/Skeleton.js';\nimport { EmptyState } from '../../ui/feedback/EmptyState.js';\nimport { useFetch } from '../../data/useFetch.js';\nimport { fetchJson, FetchError } from '../../data/fetcher.js';\nimport type { ClaudeSession } from '../../data/types.js';\nimport { ClaudeSessionDetail } from './ClaudeSessionDetail.js';\n\ninterface SessionsPayload {\n sessions: ClaudeSession[];\n}\n\nexport function ClaudeSessionsView(): JSX.Element {\n const payload = useFetch<SessionsPayload>('/api/claude-sessions');\n const [creating, setCreating] = useState<boolean>(false);\n const [detailId, setDetailId] = useState<string | null>(null);\n\n const sessions = payload.data?.sessions ?? [];\n\n const refresh = useCallback(() => { void payload.refetch(); }, [payload]);\n\n return (\n <Stack gap={4} data-testid=\"claude-sessions-view\">\n <ViewHeader\n title=\"Claude sessions\"\n description=\"Claude Code session explorer. Each row is a session directory under ~/.claude/sessions/.\"\n actions={\n <Inline align=\"center\" gap={2}>\n <Button variant=\"ghost\" onClick={() => void refresh()} data-testid=\"claude-sessions-refresh\">\n <RefreshCcw size={14} aria-hidden /> Refresh\n </Button>\n <Button variant=\"primary\" onClick={() => setCreating(true)} data-testid=\"claude-sessions-new\">\n <Plus size={14} aria-hidden /> New session\n </Button>\n </Inline>\n }\n />\n\n <Card variant=\"default\">\n <CardBody>\n {payload.loading && sessions.length === 0 ? (\n <Stack gap={2}>\n <Skeleton style={{ height: 36 }} />\n <Skeleton style={{ height: 36 }} />\n </Stack>\n ) : sessions.length === 0 ? (\n <EmptyState\n icon={<MessageSquareText size={28} aria-hidden />}\n title=\"No Claude sessions\"\n description=\"Create one to start a multi-turn conversation with Claude Code.\"\n />\n ) : (\n <Stack gap={2}>\n {sessions.map((s) => (\n <SessionRow key={s.id} session={s} onRefresh={refresh} onOpen={setDetailId} />\n ))}\n </Stack>\n )}\n </CardBody>\n </Card>\n\n <Sheet open={creating} onOpenChange={setCreating}>\n <SheetContent side=\"right\" title=\"New Claude session\" description=\"Spawn a Claude Code session via the runner.\">\n <NewSessionForm\n onCreated={(id) => {\n setCreating(false);\n refresh();\n setDetailId(id);\n }}\n onCancel={() => setCreating(false)}\n />\n </SheetContent>\n </Sheet>\n\n <Sheet open={detailId !== null} onOpenChange={(open) => { if (!open) setDetailId(null); }}>\n <SheetContent side=\"right\" title=\"Session detail\" description={detailId ?? ''}>\n {detailId !== null && <ClaudeSessionDetail sessionId={detailId} />}\n </SheetContent>\n </Sheet>\n </Stack>\n );\n}\n\nfunction SessionRow({\n session,\n onRefresh,\n onOpen,\n}: {\n session: ClaudeSession;\n onRefresh: () => void;\n onOpen: (id: string) => void;\n}): JSX.Element {\n const [renaming, setRenaming] = useState<boolean>(false);\n const [title, setTitle] = useState<string>(session.title ?? '');\n const [confirmDelete, setConfirmDelete] = useState<boolean>(false);\n const [error, setError] = useState<string | null>(null);\n\n const rename = async (): Promise<void> => {\n if (!title.trim()) return;\n setError(null);\n try {\n await fetchJson(`/api/claude-sessions/${session.id}`, {\n method: 'PATCH',\n body: { title: title.trim() },\n });\n setRenaming(false);\n onRefresh();\n } catch (err) {\n setError(err instanceof FetchError ? err.message : (err as Error).message);\n }\n };\n\n const resume = async (id: string): Promise<void> => {\n setError(null);\n try {\n await fetchJson(`/api/claude-sessions/${id}/resume`, { method: 'POST', body: {} });\n } catch (err) {\n setError(err instanceof FetchError ? err.message : (err as Error).message);\n }\n };\n\n const remove = async (): Promise<void> => {\n setError(null);\n try {\n await fetchJson(`/api/claude-sessions/${session.id}`, { method: 'DELETE' });\n setConfirmDelete(false);\n onRefresh();\n } catch (err) {\n setError(err instanceof FetchError ? err.message : (err as Error).message);\n }\n };\n\n return (\n <div\n data-testid={`claude-session-row-${session.id}`}\n style={{\n padding: 'var(--space-3)',\n borderRadius: 'var(--radius-md)',\n border: '1px solid var(--border)',\n background: 'var(--surface-0)',\n }}\n >\n <Inline align=\"center\" justify=\"between\" gap={3}>\n <Stack gap={1} style={{ minWidth: 0, flex: 1 }}>\n {renaming ? (\n <Inline gap={1}>\n <Input\n value={title}\n data-testid={`claude-session-rename-input-${session.id}`}\n onChange={(e) => setTitle((e.target as HTMLInputElement).value)}\n />\n <Button variant=\"primary\" onClick={() => void rename()} data-testid={`claude-session-rename-submit-${session.id}`}>Save</Button>\n <Button variant=\"ghost\" onClick={() => { setRenaming(false); setTitle(session.title ?? ''); }}>Cancel</Button>\n </Inline>\n ) : (\n <Inline align=\"center\" gap={2}>\n <strong style={{ fontSize: 'var(--fs-13)' }}>{session.title || session.id}</strong>\n {session.agent && (\n <span style={{ fontSize: 'var(--fs-12)', color: 'var(--fg-muted)', fontFamily: 'var(--font-mono)' }}>\n @{session.agent}\n </span>\n )}\n </Inline>\n )}\n <span style={{ fontFamily: 'var(--font-mono)', fontSize: 'var(--fs-12)', color: 'var(--fg-muted)' }}>\n {session.id}\n </span>\n {error !== null && (\n <span role=\"alert\" style={{ color: 'var(--danger)', fontSize: 'var(--fs-12)' }}>{error}</span>\n )}\n </Stack>\n <Inline gap={1}>\n <Button variant=\"primary\" onClick={() => void resume(session.id)} data-testid={`claude-session-resume-${session.id}`} aria-label={`Resume ${session.id}`}>\n Resume\n </Button>\n <Button variant=\"ghost\" onClick={() => onOpen(session.id)} data-testid={`claude-session-open-${session.id}`}>\n Open\n </Button>\n <Button\n variant=\"ghost\"\n onClick={() => { setRenaming(true); setTitle(session.title ?? ''); }}\n data-testid={`claude-session-rename-${session.id}`}\n aria-label={`Rename session ${session.id}`}\n >\n <Pencil size={14} aria-hidden />\n </Button>\n <Button\n variant=\"ghost\"\n onClick={() => setConfirmDelete((cur) => !cur)}\n data-testid={`claude-session-delete-${session.id}`}\n aria-label={`Delete session ${session.id}`}\n >\n <Trash2 size={14} aria-hidden />\n </Button>\n </Inline>\n </Inline>\n {confirmDelete && (\n <Inline gap={1} style={{ marginTop: 'var(--space-2)' }}>\n <Button variant=\"danger\" onClick={() => void remove()} data-testid={`claude-session-confirm-delete-${session.id}`}>\n Confirm delete\n </Button>\n <Button variant=\"ghost\" onClick={() => setConfirmDelete(false)} data-testid={`claude-session-cancel-delete-${session.id}`}>\n Cancel\n </Button>\n </Inline>\n )}\n </div>\n );\n}\n\nfunction NewSessionForm({\n onCreated,\n onCancel,\n}: {\n onCreated: (id: string) => void;\n onCancel: () => void;\n}): JSX.Element {\n const [title, setTitle] = useState<string>('');\n const [agent, setAgent] = useState<string>('general');\n const [prompt, setPrompt] = useState<string>('');\n const [directory, setDirectory] = useState<string>('');\n const [busy, setBusy] = useState<boolean>(false);\n const [error, setError] = useState<string | null>(null);\n\n const submit = async (): Promise<void> => {\n if (!agent.trim() || !prompt.trim() || busy) return;\n setBusy(true);\n setError(null);\n try {\n const res = await fetchJson<{ id: string }>('/api/claude-sessions/new', {\n method: 'POST',\n body: {\n title: title.trim() || null,\n agent: agent.trim(),\n prompt: prompt.trim(),\n directory: directory.trim() || undefined,\n },\n });\n onCreated(res.id);\n } catch (err) {\n setError(err instanceof FetchError ? err.message : (err as Error).message);\n } finally {\n setBusy(false);\n }\n };\n\n return (\n <Stack gap={3} style={{ padding: 'var(--space-4)' }}>\n <label style={{ display: 'flex', flexDirection: 'column', gap: 'var(--space-1)' }}>\n <span style={{ fontSize: 'var(--fs-12)', color: 'var(--fg-muted)' }}>Title (optional)</span>\n <Input\n value={title}\n data-testid=\"claude-sessions-new-title\"\n onChange={(e) => setTitle((e.target as HTMLInputElement).value)}\n />\n </label>\n <label style={{ display: 'flex', flexDirection: 'column', gap: 'var(--space-1)' }}>\n <span style={{ fontSize: 'var(--fs-12)', color: 'var(--fg-muted)' }}>Agent</span>\n <Input\n value={agent}\n data-testid=\"claude-sessions-new-agent\"\n onChange={(e) => setAgent((e.target as HTMLInputElement).value)}\n />\n </label>\n <label style={{ display: 'flex', flexDirection: 'column', gap: 'var(--space-1)' }}>\n <span style={{ fontSize: 'var(--fs-12)', color: 'var(--fg-muted)' }}>Seed prompt</span>\n <textarea\n value={prompt}\n rows={4}\n data-testid=\"claude-sessions-new-prompt\"\n onChange={(e) => setPrompt((e.target as HTMLTextAreaElement).value)}\n style={{\n background: 'var(--surface-0)',\n border: '1px solid var(--border)',\n borderRadius: 'var(--radius-md)',\n padding: 'var(--space-2)',\n color: 'var(--fg)',\n fontFamily: 'var(--font-sans)',\n fontSize: 'var(--fs-13)',\n resize: 'vertical',\n }}\n />\n </label>\n <label style={{ display: 'flex', flexDirection: 'column', gap: 'var(--space-1)' }}>\n <span style={{ fontSize: 'var(--fs-12)', color: 'var(--fg-muted)' }}>Working directory (optional)</span>\n <Input\n value={directory}\n data-testid=\"claude-sessions-new-directory\"\n onChange={(e) => setDirectory((e.target as HTMLInputElement).value)}\n />\n </label>\n {error !== null && (\n <span role=\"alert\" data-testid=\"claude-sessions-new-error\" style={{ color: 'var(--danger)', fontSize: 'var(--fs-12)' }}>\n {error}\n </span>\n )}\n <Inline justify=\"end\" gap={2}>\n <SheetClose asChild>\n <Button variant=\"ghost\" onClick={onCancel} data-testid=\"claude-sessions-new-cancel\">Cancel</Button>\n </SheetClose>\n <Button\n variant=\"primary\"\n onClick={() => void submit()}\n disabled={busy || !agent.trim() || !prompt.trim()}\n data-testid=\"claude-sessions-new-submit\"\n >\n Create\n </Button>\n </Inline>\n </Stack>\n );\n}"],"names":["ClaudeSessionDetail","sessionId","url","payload","useFetch","draft","setDraft","useState","agent","setAgent","busy","setBusy","error","setError","refresh","useCallback","messages","_a","send","text","fetchJson","err","FetchError","jsxs","Stack","Inline","jsx","Button","RefreshCcw","Card","CardBody","Skeleton","m","MessageBubble","Input","e","Send","ClaudeSessionsView","creating","setCreating","detailId","setDetailId","sessions","ViewHeader","Plus","EmptyState","MessageSquareText","s","SessionRow","Sheet","SheetContent","NewSessionForm","id","open","session","onRefresh","onOpen","renaming","setRenaming","title","setTitle","confirmDelete","setConfirmDelete","rename","resume","remove","Pencil","cur","Trash2","onCreated","onCancel","prompt","setPrompt","directory","setDirectory","submit","res","SheetClose"],"mappings":"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"}
@@ -1 +1 @@
1
- import{r as s,j as e}from"./cmdk-DVxytz9i.js";import{u as k,S as h,I as f,d as n,h as y,_ as w,i as S,F as z}from"./main-CyAIirBB.js";import{V as E}from"./ViewHeader-V_SzbUpw.js";import{C as T,b as D}from"./Card-D9019JOD.js";import{I as b}from"./Input-BSa3lh_-.js";import{T as C}from"./Textarea-D_TPpVMy.js";import{S as R,a as $}from"./Sheet-Cztsvgse.js";import{E as L}from"./EmptyState-DLmtBX_6.js";import{R as F}from"./refresh-ccw-BCXx86xp.js";import{P as I}from"./plus-fFxt-8z5.js";import{E as P}from"./external-link-CAOnh_DH.js";import{T as U}from"./trash-2-2NsyTU8c.js";function Q(){const l=k("/api/clipboard/list"),[v,r]=s.useState(!1),[x,o]=s.useState(null),[u,d]=s.useState(null),p=s.useMemo(()=>{var t;return((t=l.data)==null?void 0:t.clips)??[]},[l.data]),c=s.useCallback(()=>{l.refetch()},[l]),g=async t=>{d(null);try{await S(`/api/clipboard/${t}`,{method:"DELETE"}),o(null),c()}catch(i){d((i instanceof z,i.message))}};return e.jsxs(h,{gap:4,"data-testid":"clipboard-view",children:[e.jsx(E,{title:"Clipboard",description:"Saved clips. Each becomes a markdown note under clips/.",actions:e.jsxs(f,{align:"center",gap:2,children:[u!==null&&e.jsx("span",{role:"alert","data-testid":"clipboard-error",style:{color:"var(--danger)",fontSize:"var(--fs-12)"},children:u}),e.jsxs(n,{variant:"ghost",onClick:()=>void c(),"data-testid":"clipboard-refresh",children:[e.jsx(F,{size:14,"aria-hidden":!0})," Refresh"]}),e.jsxs(n,{variant:"primary",onClick:()=>r(!0),"data-testid":"clipboard-add",children:[e.jsx(I,{size:14,"aria-hidden":!0})," Save clip"]})]})}),e.jsx(T,{variant:"default",children:e.jsx(D,{children:l.loading&&p.length===0?e.jsxs(h,{gap:1,children:[e.jsx(y,{style:{height:60}}),e.jsx(y,{style:{height:60}})]}):p.length===0?e.jsx(L,{icon:e.jsx(w,{size:28,"aria-hidden":!0}),title:"No saved clips",description:"Save one with a URL + content."}):e.jsx(h,{gap:1,children:p.map(t=>{const i=x===t.id;return e.jsxs("div",{"data-testid":`clipboard-row-${t.id}`,style:{padding:"var(--space-2)",border:"1px solid var(--border)",borderRadius:"var(--radius-sm)"},children:[e.jsxs(f,{align:"center",justify:"between",gap:2,children:[e.jsxs(h,{gap:0,style:{minWidth:0,flex:1},children:[e.jsxs(f,{align:"center",gap:2,children:[e.jsx("strong",{style:{fontSize:"var(--fs-13)"},children:t.title||t.id}),t.url&&e.jsxs("a",{href:t.url,target:"_blank",rel:"noreferrer",style:{fontSize:"var(--fs-11)",color:"var(--accent)"},children:[e.jsx(P,{size:10,"aria-hidden":!0,style:{verticalAlign:"middle"}})," ",t.url]}),t.savedAt&&e.jsx("span",{style:{fontSize:"var(--fs-11)",color:"var(--fg-subtle)"},children:t.savedAt})]}),(t.selection||t.content)&&e.jsx("span",{style:{fontSize:"var(--fs-12)",color:"var(--fg-muted)"},children:(t.selection||t.content||"").length>200?`${(t.selection||t.content||"").slice(0,200)}…`:t.selection||t.content})]}),e.jsx(n,{variant:"ghost",onClick:()=>o(m=>m===t.id?null:t.id),"data-testid":`clipboard-delete-${t.id}`,"aria-label":`Delete ${t.id}`,children:e.jsx(U,{size:14,"aria-hidden":!0})})]}),i&&e.jsxs(f,{gap:1,style:{marginTop:"var(--space-1)"},children:[e.jsx(n,{variant:"danger",onClick:()=>void g(t.id),"data-testid":`clipboard-confirm-delete-${t.id}`,children:"Confirm delete"}),e.jsx(n,{variant:"ghost",onClick:()=>o(null),children:"Cancel"})]})]},t.id)})})})}),e.jsx(R,{open:v,onOpenChange:r,children:e.jsx($,{side:"right",title:"Save clip",description:"URL or content required.",children:e.jsx(A,{onSubmit:async t=>{await S("/api/clipboard/save",{method:"POST",body:t}),r(!1),c()},onCancel:()=>r(!1)})})})]})}function A({onSubmit:l,onCancel:v}){const[r,x]=s.useState(""),[o,u]=s.useState(""),[d,p]=s.useState(""),[c,g]=s.useState(""),[t,i]=s.useState(!1),[m,j]=s.useState(null);return e.jsxs(h,{gap:3,style:{padding:"var(--space-4)"},children:[e.jsxs("label",{style:{display:"flex",flexDirection:"column",gap:"var(--space-1)"},children:[e.jsx("span",{style:{fontSize:"var(--fs-12)",color:"var(--fg-muted)"},children:"URL (optional)"}),e.jsx(b,{value:r,onChange:a=>x(a.target.value),"data-testid":"clipboard-form-url"})]}),e.jsxs("label",{style:{display:"flex",flexDirection:"column",gap:"var(--space-1)"},children:[e.jsx("span",{style:{fontSize:"var(--fs-12)",color:"var(--fg-muted)"},children:"Title (optional)"}),e.jsx(b,{value:o,onChange:a=>u(a.target.value),"data-testid":"clipboard-form-title"})]}),e.jsxs("label",{style:{display:"flex",flexDirection:"column",gap:"var(--space-1)"},children:[e.jsx("span",{style:{fontSize:"var(--fs-12)",color:"var(--fg-muted)"},children:"Content"}),e.jsx(C,{value:d,rows:6,onChange:a=>p(a.target.value),"data-testid":"clipboard-form-content"})]}),e.jsxs("label",{style:{display:"flex",flexDirection:"column",gap:"var(--space-1)"},children:[e.jsx("span",{style:{fontSize:"var(--fs-12)",color:"var(--fg-muted)"},children:"Selection (optional)"}),e.jsx(C,{value:c,rows:3,onChange:a=>g(a.target.value),"data-testid":"clipboard-form-selection"})]}),m!==null&&e.jsx("span",{role:"alert",style:{color:"var(--danger)",fontSize:"var(--fs-12)"},children:m}),e.jsxs(f,{justify:"end",gap:2,children:[e.jsx(n,{variant:"ghost",onClick:v,children:"Cancel"}),e.jsx(n,{variant:"primary",disabled:t||!r.trim()&&!d.trim(),"data-testid":"clipboard-form-submit",onClick:async()=>{i(!0),j(null);try{await l({url:r.trim()||void 0,title:o.trim()||void 0,content:d.trim()||void 0,selection:c.trim()||void 0})}catch(a){j((a instanceof z,a.message)),i(!1)}},children:t?"Saving…":"Save"})]})]})}export{Q as ClipboardView};
1
+ import{r as s,j as e}from"./cmdk-DVxytz9i.js";import{u as k,S as h,I as f,d as n,h as y,_ as w,i as S,F as z}from"./main-Cxeu4LhG.js";import{V as E}from"./ViewHeader-B6P-C4GD.js";import{C as T,b as D}from"./Card-rF59wHiO.js";import{I as b}from"./Input-CZmRw5QX.js";import{T as C}from"./Textarea-QuofpMlq.js";import{S as R,a as $}from"./Sheet-BOProMs2.js";import{E as L}from"./EmptyState-D65J5FQN.js";import{R as F}from"./refresh-ccw-DenGBOcq.js";import{P as I}from"./plus-77h62zZm.js";import{E as P}from"./external-link-D5tq2o_I.js";import{T as U}from"./trash-2-Cv7U38jw.js";function Q(){const l=k("/api/clipboard/list"),[v,r]=s.useState(!1),[x,o]=s.useState(null),[u,d]=s.useState(null),p=s.useMemo(()=>{var t;return((t=l.data)==null?void 0:t.clips)??[]},[l.data]),c=s.useCallback(()=>{l.refetch()},[l]),g=async t=>{d(null);try{await S(`/api/clipboard/${t}`,{method:"DELETE"}),o(null),c()}catch(i){d((i instanceof z,i.message))}};return e.jsxs(h,{gap:4,"data-testid":"clipboard-view",children:[e.jsx(E,{title:"Clipboard",description:"Saved clips. Each becomes a markdown note under clips/.",actions:e.jsxs(f,{align:"center",gap:2,children:[u!==null&&e.jsx("span",{role:"alert","data-testid":"clipboard-error",style:{color:"var(--danger)",fontSize:"var(--fs-12)"},children:u}),e.jsxs(n,{variant:"ghost",onClick:()=>void c(),"data-testid":"clipboard-refresh",children:[e.jsx(F,{size:14,"aria-hidden":!0})," Refresh"]}),e.jsxs(n,{variant:"primary",onClick:()=>r(!0),"data-testid":"clipboard-add",children:[e.jsx(I,{size:14,"aria-hidden":!0})," Save clip"]})]})}),e.jsx(T,{variant:"default",children:e.jsx(D,{children:l.loading&&p.length===0?e.jsxs(h,{gap:1,children:[e.jsx(y,{style:{height:60}}),e.jsx(y,{style:{height:60}})]}):p.length===0?e.jsx(L,{icon:e.jsx(w,{size:28,"aria-hidden":!0}),title:"No saved clips",description:"Save one with a URL + content."}):e.jsx(h,{gap:1,children:p.map(t=>{const i=x===t.id;return e.jsxs("div",{"data-testid":`clipboard-row-${t.id}`,style:{padding:"var(--space-2)",border:"1px solid var(--border)",borderRadius:"var(--radius-sm)"},children:[e.jsxs(f,{align:"center",justify:"between",gap:2,children:[e.jsxs(h,{gap:0,style:{minWidth:0,flex:1},children:[e.jsxs(f,{align:"center",gap:2,children:[e.jsx("strong",{style:{fontSize:"var(--fs-13)"},children:t.title||t.id}),t.url&&e.jsxs("a",{href:t.url,target:"_blank",rel:"noreferrer",style:{fontSize:"var(--fs-11)",color:"var(--accent)"},children:[e.jsx(P,{size:10,"aria-hidden":!0,style:{verticalAlign:"middle"}})," ",t.url]}),t.savedAt&&e.jsx("span",{style:{fontSize:"var(--fs-11)",color:"var(--fg-subtle)"},children:t.savedAt})]}),(t.selection||t.content)&&e.jsx("span",{style:{fontSize:"var(--fs-12)",color:"var(--fg-muted)"},children:(t.selection||t.content||"").length>200?`${(t.selection||t.content||"").slice(0,200)}…`:t.selection||t.content})]}),e.jsx(n,{variant:"ghost",onClick:()=>o(m=>m===t.id?null:t.id),"data-testid":`clipboard-delete-${t.id}`,"aria-label":`Delete ${t.id}`,children:e.jsx(U,{size:14,"aria-hidden":!0})})]}),i&&e.jsxs(f,{gap:1,style:{marginTop:"var(--space-1)"},children:[e.jsx(n,{variant:"danger",onClick:()=>void g(t.id),"data-testid":`clipboard-confirm-delete-${t.id}`,children:"Confirm delete"}),e.jsx(n,{variant:"ghost",onClick:()=>o(null),children:"Cancel"})]})]},t.id)})})})}),e.jsx(R,{open:v,onOpenChange:r,children:e.jsx($,{side:"right",title:"Save clip",description:"URL or content required.",children:e.jsx(A,{onSubmit:async t=>{await S("/api/clipboard/save",{method:"POST",body:t}),r(!1),c()},onCancel:()=>r(!1)})})})]})}function A({onSubmit:l,onCancel:v}){const[r,x]=s.useState(""),[o,u]=s.useState(""),[d,p]=s.useState(""),[c,g]=s.useState(""),[t,i]=s.useState(!1),[m,j]=s.useState(null);return e.jsxs(h,{gap:3,style:{padding:"var(--space-4)"},children:[e.jsxs("label",{style:{display:"flex",flexDirection:"column",gap:"var(--space-1)"},children:[e.jsx("span",{style:{fontSize:"var(--fs-12)",color:"var(--fg-muted)"},children:"URL (optional)"}),e.jsx(b,{value:r,onChange:a=>x(a.target.value),"data-testid":"clipboard-form-url"})]}),e.jsxs("label",{style:{display:"flex",flexDirection:"column",gap:"var(--space-1)"},children:[e.jsx("span",{style:{fontSize:"var(--fs-12)",color:"var(--fg-muted)"},children:"Title (optional)"}),e.jsx(b,{value:o,onChange:a=>u(a.target.value),"data-testid":"clipboard-form-title"})]}),e.jsxs("label",{style:{display:"flex",flexDirection:"column",gap:"var(--space-1)"},children:[e.jsx("span",{style:{fontSize:"var(--fs-12)",color:"var(--fg-muted)"},children:"Content"}),e.jsx(C,{value:d,rows:6,onChange:a=>p(a.target.value),"data-testid":"clipboard-form-content"})]}),e.jsxs("label",{style:{display:"flex",flexDirection:"column",gap:"var(--space-1)"},children:[e.jsx("span",{style:{fontSize:"var(--fs-12)",color:"var(--fg-muted)"},children:"Selection (optional)"}),e.jsx(C,{value:c,rows:3,onChange:a=>g(a.target.value),"data-testid":"clipboard-form-selection"})]}),m!==null&&e.jsx("span",{role:"alert",style:{color:"var(--danger)",fontSize:"var(--fs-12)"},children:m}),e.jsxs(f,{justify:"end",gap:2,children:[e.jsx(n,{variant:"ghost",onClick:v,children:"Cancel"}),e.jsx(n,{variant:"primary",disabled:t||!r.trim()&&!d.trim(),"data-testid":"clipboard-form-submit",onClick:async()=>{i(!0),j(null);try{await l({url:r.trim()||void 0,title:o.trim()||void 0,content:d.trim()||void 0,selection:c.trim()||void 0})}catch(a){j((a instanceof z,a.message)),i(!1)}},children:t?"Saving…":"Save"})]})]})}export{Q as ClipboardView};
@@ -1 +1 @@
1
- {"version":3,"file":"ClipboardView-BAguaKbx.js","sources":["../../src/web/v8/views/Clipboard/ClipboardView.tsx"],"sourcesContent":["/**\n * v8/views/Clipboard/ClipboardView.tsx — Sprint S43, v9.3.0.\n *\n * Saved clip list (GET /api/clipboard/list), Save Sheet\n * (POST /api/clipboard/save with {url, title, content, selection}),\n * inline-confirm Delete (DELETE /api/clipboard/:id). Each row links\n * to the source URL when present.\n */\n\nimport { useCallback, useMemo, useState } from 'react';\nimport { ClipboardPaste, Plus, Trash2, ExternalLink, RefreshCcw } from 'lucide-react';\nimport { Stack } from '../../ui/primitives/Stack.js';\nimport { Inline } from '../../ui/primitives/Inline.js';\nimport { ViewHeader } from '../../ui/data/ViewHeader.js';\nimport { Card, CardBody } from '../../ui/data/Card.js';\nimport { Button } from '../../ui/controls/Button.js';\nimport { Input } from '../../ui/controls/Input.js';\nimport { Textarea } from '../../ui/controls/Textarea.js';\nimport { Sheet, SheetContent } from '../../ui/feedback/Sheet.js';\nimport { Skeleton } from '../../ui/feedback/Skeleton.js';\nimport { EmptyState } from '../../ui/feedback/EmptyState.js';\nimport { useFetch } from '../../data/useFetch.js';\nimport { fetchJson, FetchError } from '../../data/fetcher.js';\n\ninterface Clip {\n id: string;\n url?: string;\n title?: string;\n content?: string;\n selection?: string;\n savedAt?: string;\n}\n\nexport function ClipboardView(): JSX.Element {\n const payload = useFetch<{ clips: Clip[] }>('/api/clipboard/list');\n const [saving, setSaving] = useState<boolean>(false);\n const [confirmDelete, setConfirmDelete] = useState<string | null>(null);\n const [error, setError] = useState<string | null>(null);\n\n const clips = useMemo<Clip[]>(() => payload.data?.clips ?? [], [payload.data]);\n const refresh = useCallback(() => { void payload.refetch(); }, [payload]);\n\n const drop = async (id: string): Promise<void> => {\n setError(null);\n try {\n await fetchJson(`/api/clipboard/${id}`, { method: 'DELETE' });\n setConfirmDelete(null);\n refresh();\n } catch (err) {\n setError(err instanceof FetchError ? err.message : (err as Error).message);\n }\n };\n\n return (\n <Stack gap={4} data-testid=\"clipboard-view\">\n <ViewHeader\n title=\"Clipboard\"\n description=\"Saved clips. Each becomes a markdown note under clips/.\"\n actions={\n <Inline align=\"center\" gap={2}>\n {error !== null && (\n <span role=\"alert\" data-testid=\"clipboard-error\" style={{ color: 'var(--danger)', fontSize: 'var(--fs-12)' }}>\n {error}\n </span>\n )}\n <Button variant=\"ghost\" onClick={() => void refresh()} data-testid=\"clipboard-refresh\">\n <RefreshCcw size={14} aria-hidden /> Refresh\n </Button>\n <Button variant=\"primary\" onClick={() => setSaving(true)} data-testid=\"clipboard-add\">\n <Plus size={14} aria-hidden /> Save clip\n </Button>\n </Inline>\n }\n />\n\n <Card variant=\"default\">\n <CardBody>\n {payload.loading && clips.length === 0 ? (\n <Stack gap={1}>\n <Skeleton style={{ height: 60 }} />\n <Skeleton style={{ height: 60 }} />\n </Stack>\n ) : clips.length === 0 ? (\n <EmptyState icon={<ClipboardPaste size={28} aria-hidden />} title=\"No saved clips\" description=\"Save one with a URL + content.\" />\n ) : (\n <Stack gap={1}>\n {clips.map((c) => {\n const isConfirming = confirmDelete === c.id;\n return (\n <div\n key={c.id}\n data-testid={`clipboard-row-${c.id}`}\n style={{ padding: 'var(--space-2)', border: '1px solid var(--border)', borderRadius: 'var(--radius-sm)' }}\n >\n <Inline align=\"center\" justify=\"between\" gap={2}>\n <Stack gap={0} style={{ minWidth: 0, flex: 1 }}>\n <Inline align=\"center\" gap={2}>\n <strong style={{ fontSize: 'var(--fs-13)' }}>{c.title || c.id}</strong>\n {c.url && (\n <a href={c.url} target=\"_blank\" rel=\"noreferrer\" style={{ fontSize: 'var(--fs-11)', color: 'var(--accent)' }}>\n <ExternalLink size={10} aria-hidden style={{ verticalAlign: 'middle' }} /> {c.url}\n </a>\n )}\n {c.savedAt && <span style={{ fontSize: 'var(--fs-11)', color: 'var(--fg-subtle)' }}>{c.savedAt}</span>}\n </Inline>\n {(c.selection || c.content) && (\n <span style={{ fontSize: 'var(--fs-12)', color: 'var(--fg-muted)' }}>\n {(c.selection || c.content || '').length > 200\n ? `${(c.selection || c.content || '').slice(0, 200)}…`\n : (c.selection || c.content)}\n </span>\n )}\n </Stack>\n <Button variant=\"ghost\" onClick={() => setConfirmDelete((cur) => (cur === c.id ? null : c.id))} data-testid={`clipboard-delete-${c.id}`} aria-label={`Delete ${c.id}`}>\n <Trash2 size={14} aria-hidden />\n </Button>\n </Inline>\n {isConfirming && (\n <Inline gap={1} style={{ marginTop: 'var(--space-1)' }}>\n <Button variant=\"danger\" onClick={() => void drop(c.id)} data-testid={`clipboard-confirm-delete-${c.id}`}>\n Confirm delete\n </Button>\n <Button variant=\"ghost\" onClick={() => setConfirmDelete(null)}>Cancel</Button>\n </Inline>\n )}\n </div>\n );\n })}\n </Stack>\n )}\n </CardBody>\n </Card>\n\n <Sheet open={saving} onOpenChange={setSaving}>\n <SheetContent side=\"right\" title=\"Save clip\" description=\"URL or content required.\">\n <SaveForm\n onSubmit={async (body) => {\n await fetchJson('/api/clipboard/save', { method: 'POST', body });\n setSaving(false);\n refresh();\n }}\n onCancel={() => setSaving(false)}\n />\n </SheetContent>\n </Sheet>\n </Stack>\n );\n}\n\nfunction SaveForm({\n onSubmit,\n onCancel,\n}: {\n onSubmit: (body: { url?: string; title?: string; content?: string; selection?: string }) => Promise<void>;\n onCancel: () => void;\n}): JSX.Element {\n const [url, setUrl] = useState<string>('');\n const [title, setTitle] = useState<string>('');\n const [content, setContent] = useState<string>('');\n const [selection, setSelection] = useState<string>('');\n const [busy, setBusy] = useState<boolean>(false);\n const [error, setError] = useState<string | null>(null);\n\n return (\n <Stack gap={3} style={{ padding: 'var(--space-4)' }}>\n <label style={{ display: 'flex', flexDirection: 'column', gap: 'var(--space-1)' }}>\n <span style={{ fontSize: 'var(--fs-12)', color: 'var(--fg-muted)' }}>URL (optional)</span>\n <Input value={url} onChange={(e) => setUrl((e.target as HTMLInputElement).value)} data-testid=\"clipboard-form-url\" />\n </label>\n <label style={{ display: 'flex', flexDirection: 'column', gap: 'var(--space-1)' }}>\n <span style={{ fontSize: 'var(--fs-12)', color: 'var(--fg-muted)' }}>Title (optional)</span>\n <Input value={title} onChange={(e) => setTitle((e.target as HTMLInputElement).value)} data-testid=\"clipboard-form-title\" />\n </label>\n <label style={{ display: 'flex', flexDirection: 'column', gap: 'var(--space-1)' }}>\n <span style={{ fontSize: 'var(--fs-12)', color: 'var(--fg-muted)' }}>Content</span>\n <Textarea value={content} rows={6} onChange={(e) => setContent((e.target as HTMLTextAreaElement).value)} data-testid=\"clipboard-form-content\" />\n </label>\n <label style={{ display: 'flex', flexDirection: 'column', gap: 'var(--space-1)' }}>\n <span style={{ fontSize: 'var(--fs-12)', color: 'var(--fg-muted)' }}>Selection (optional)</span>\n <Textarea value={selection} rows={3} onChange={(e) => setSelection((e.target as HTMLTextAreaElement).value)} data-testid=\"clipboard-form-selection\" />\n </label>\n {error !== null && <span role=\"alert\" style={{ color: 'var(--danger)', fontSize: 'var(--fs-12)' }}>{error}</span>}\n <Inline justify=\"end\" gap={2}>\n <Button variant=\"ghost\" onClick={onCancel}>Cancel</Button>\n <Button\n variant=\"primary\"\n disabled={busy || (!url.trim() && !content.trim())}\n data-testid=\"clipboard-form-submit\"\n onClick={async () => {\n setBusy(true);\n setError(null);\n try {\n await onSubmit({\n url: url.trim() || undefined,\n title: title.trim() || undefined,\n content: content.trim() || undefined,\n selection: selection.trim() || undefined,\n });\n } catch (err) {\n setError(err instanceof FetchError ? err.message : (err as Error).message);\n setBusy(false);\n }\n }}\n >\n {busy ? 'Saving…' : 'Save'}\n </Button>\n </Inline>\n </Stack>\n );\n}"],"names":["ClipboardView","payload","useFetch","saving","setSaving","useState","confirmDelete","setConfirmDelete","error","setError","clips","useMemo","_a","refresh","useCallback","drop","id","fetchJson","err","FetchError","jsxs","Stack","jsx","ViewHeader","Inline","Button","RefreshCcw","Plus","Card","CardBody","Skeleton","EmptyState","ClipboardPaste","c","isConfirming","ExternalLink","cur","Trash2","Sheet","SheetContent","SaveForm","body","onSubmit","onCancel","url","setUrl","title","setTitle","content","setContent","selection","setSelection","busy","setBusy","Input","e","Textarea"],"mappings":"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"}
1
+ {"version":3,"file":"ClipboardView-DdP6aVso.js","sources":["../../src/web/v8/views/Clipboard/ClipboardView.tsx"],"sourcesContent":["/**\n * v8/views/Clipboard/ClipboardView.tsx — Sprint S43, v9.3.0.\n *\n * Saved clip list (GET /api/clipboard/list), Save Sheet\n * (POST /api/clipboard/save with {url, title, content, selection}),\n * inline-confirm Delete (DELETE /api/clipboard/:id). Each row links\n * to the source URL when present.\n */\n\nimport { useCallback, useMemo, useState } from 'react';\nimport { ClipboardPaste, Plus, Trash2, ExternalLink, RefreshCcw } from 'lucide-react';\nimport { Stack } from '../../ui/primitives/Stack.js';\nimport { Inline } from '../../ui/primitives/Inline.js';\nimport { ViewHeader } from '../../ui/data/ViewHeader.js';\nimport { Card, CardBody } from '../../ui/data/Card.js';\nimport { Button } from '../../ui/controls/Button.js';\nimport { Input } from '../../ui/controls/Input.js';\nimport { Textarea } from '../../ui/controls/Textarea.js';\nimport { Sheet, SheetContent } from '../../ui/feedback/Sheet.js';\nimport { Skeleton } from '../../ui/feedback/Skeleton.js';\nimport { EmptyState } from '../../ui/feedback/EmptyState.js';\nimport { useFetch } from '../../data/useFetch.js';\nimport { fetchJson, FetchError } from '../../data/fetcher.js';\n\ninterface Clip {\n id: string;\n url?: string;\n title?: string;\n content?: string;\n selection?: string;\n savedAt?: string;\n}\n\nexport function ClipboardView(): JSX.Element {\n const payload = useFetch<{ clips: Clip[] }>('/api/clipboard/list');\n const [saving, setSaving] = useState<boolean>(false);\n const [confirmDelete, setConfirmDelete] = useState<string | null>(null);\n const [error, setError] = useState<string | null>(null);\n\n const clips = useMemo<Clip[]>(() => payload.data?.clips ?? [], [payload.data]);\n const refresh = useCallback(() => { void payload.refetch(); }, [payload]);\n\n const drop = async (id: string): Promise<void> => {\n setError(null);\n try {\n await fetchJson(`/api/clipboard/${id}`, { method: 'DELETE' });\n setConfirmDelete(null);\n refresh();\n } catch (err) {\n setError(err instanceof FetchError ? err.message : (err as Error).message);\n }\n };\n\n return (\n <Stack gap={4} data-testid=\"clipboard-view\">\n <ViewHeader\n title=\"Clipboard\"\n description=\"Saved clips. Each becomes a markdown note under clips/.\"\n actions={\n <Inline align=\"center\" gap={2}>\n {error !== null && (\n <span role=\"alert\" data-testid=\"clipboard-error\" style={{ color: 'var(--danger)', fontSize: 'var(--fs-12)' }}>\n {error}\n </span>\n )}\n <Button variant=\"ghost\" onClick={() => void refresh()} data-testid=\"clipboard-refresh\">\n <RefreshCcw size={14} aria-hidden /> Refresh\n </Button>\n <Button variant=\"primary\" onClick={() => setSaving(true)} data-testid=\"clipboard-add\">\n <Plus size={14} aria-hidden /> Save clip\n </Button>\n </Inline>\n }\n />\n\n <Card variant=\"default\">\n <CardBody>\n {payload.loading && clips.length === 0 ? (\n <Stack gap={1}>\n <Skeleton style={{ height: 60 }} />\n <Skeleton style={{ height: 60 }} />\n </Stack>\n ) : clips.length === 0 ? (\n <EmptyState icon={<ClipboardPaste size={28} aria-hidden />} title=\"No saved clips\" description=\"Save one with a URL + content.\" />\n ) : (\n <Stack gap={1}>\n {clips.map((c) => {\n const isConfirming = confirmDelete === c.id;\n return (\n <div\n key={c.id}\n data-testid={`clipboard-row-${c.id}`}\n style={{ padding: 'var(--space-2)', border: '1px solid var(--border)', borderRadius: 'var(--radius-sm)' }}\n >\n <Inline align=\"center\" justify=\"between\" gap={2}>\n <Stack gap={0} style={{ minWidth: 0, flex: 1 }}>\n <Inline align=\"center\" gap={2}>\n <strong style={{ fontSize: 'var(--fs-13)' }}>{c.title || c.id}</strong>\n {c.url && (\n <a href={c.url} target=\"_blank\" rel=\"noreferrer\" style={{ fontSize: 'var(--fs-11)', color: 'var(--accent)' }}>\n <ExternalLink size={10} aria-hidden style={{ verticalAlign: 'middle' }} /> {c.url}\n </a>\n )}\n {c.savedAt && <span style={{ fontSize: 'var(--fs-11)', color: 'var(--fg-subtle)' }}>{c.savedAt}</span>}\n </Inline>\n {(c.selection || c.content) && (\n <span style={{ fontSize: 'var(--fs-12)', color: 'var(--fg-muted)' }}>\n {(c.selection || c.content || '').length > 200\n ? `${(c.selection || c.content || '').slice(0, 200)}…`\n : (c.selection || c.content)}\n </span>\n )}\n </Stack>\n <Button variant=\"ghost\" onClick={() => setConfirmDelete((cur) => (cur === c.id ? null : c.id))} data-testid={`clipboard-delete-${c.id}`} aria-label={`Delete ${c.id}`}>\n <Trash2 size={14} aria-hidden />\n </Button>\n </Inline>\n {isConfirming && (\n <Inline gap={1} style={{ marginTop: 'var(--space-1)' }}>\n <Button variant=\"danger\" onClick={() => void drop(c.id)} data-testid={`clipboard-confirm-delete-${c.id}`}>\n Confirm delete\n </Button>\n <Button variant=\"ghost\" onClick={() => setConfirmDelete(null)}>Cancel</Button>\n </Inline>\n )}\n </div>\n );\n })}\n </Stack>\n )}\n </CardBody>\n </Card>\n\n <Sheet open={saving} onOpenChange={setSaving}>\n <SheetContent side=\"right\" title=\"Save clip\" description=\"URL or content required.\">\n <SaveForm\n onSubmit={async (body) => {\n await fetchJson('/api/clipboard/save', { method: 'POST', body });\n setSaving(false);\n refresh();\n }}\n onCancel={() => setSaving(false)}\n />\n </SheetContent>\n </Sheet>\n </Stack>\n );\n}\n\nfunction SaveForm({\n onSubmit,\n onCancel,\n}: {\n onSubmit: (body: { url?: string; title?: string; content?: string; selection?: string }) => Promise<void>;\n onCancel: () => void;\n}): JSX.Element {\n const [url, setUrl] = useState<string>('');\n const [title, setTitle] = useState<string>('');\n const [content, setContent] = useState<string>('');\n const [selection, setSelection] = useState<string>('');\n const [busy, setBusy] = useState<boolean>(false);\n const [error, setError] = useState<string | null>(null);\n\n return (\n <Stack gap={3} style={{ padding: 'var(--space-4)' }}>\n <label style={{ display: 'flex', flexDirection: 'column', gap: 'var(--space-1)' }}>\n <span style={{ fontSize: 'var(--fs-12)', color: 'var(--fg-muted)' }}>URL (optional)</span>\n <Input value={url} onChange={(e) => setUrl((e.target as HTMLInputElement).value)} data-testid=\"clipboard-form-url\" />\n </label>\n <label style={{ display: 'flex', flexDirection: 'column', gap: 'var(--space-1)' }}>\n <span style={{ fontSize: 'var(--fs-12)', color: 'var(--fg-muted)' }}>Title (optional)</span>\n <Input value={title} onChange={(e) => setTitle((e.target as HTMLInputElement).value)} data-testid=\"clipboard-form-title\" />\n </label>\n <label style={{ display: 'flex', flexDirection: 'column', gap: 'var(--space-1)' }}>\n <span style={{ fontSize: 'var(--fs-12)', color: 'var(--fg-muted)' }}>Content</span>\n <Textarea value={content} rows={6} onChange={(e) => setContent((e.target as HTMLTextAreaElement).value)} data-testid=\"clipboard-form-content\" />\n </label>\n <label style={{ display: 'flex', flexDirection: 'column', gap: 'var(--space-1)' }}>\n <span style={{ fontSize: 'var(--fs-12)', color: 'var(--fg-muted)' }}>Selection (optional)</span>\n <Textarea value={selection} rows={3} onChange={(e) => setSelection((e.target as HTMLTextAreaElement).value)} data-testid=\"clipboard-form-selection\" />\n </label>\n {error !== null && <span role=\"alert\" style={{ color: 'var(--danger)', fontSize: 'var(--fs-12)' }}>{error}</span>}\n <Inline justify=\"end\" gap={2}>\n <Button variant=\"ghost\" onClick={onCancel}>Cancel</Button>\n <Button\n variant=\"primary\"\n disabled={busy || (!url.trim() && !content.trim())}\n data-testid=\"clipboard-form-submit\"\n onClick={async () => {\n setBusy(true);\n setError(null);\n try {\n await onSubmit({\n url: url.trim() || undefined,\n title: title.trim() || undefined,\n content: content.trim() || undefined,\n selection: selection.trim() || undefined,\n });\n } catch (err) {\n setError(err instanceof FetchError ? err.message : (err as Error).message);\n setBusy(false);\n }\n }}\n >\n {busy ? 'Saving…' : 'Save'}\n </Button>\n </Inline>\n </Stack>\n );\n}"],"names":["ClipboardView","payload","useFetch","saving","setSaving","useState","confirmDelete","setConfirmDelete","error","setError","clips","useMemo","_a","refresh","useCallback","drop","id","fetchJson","err","FetchError","jsxs","Stack","jsx","ViewHeader","Inline","Button","RefreshCcw","Plus","Card","CardBody","Skeleton","EmptyState","ClipboardPaste","c","isConfirming","ExternalLink","cur","Trash2","Sheet","SheetContent","SaveForm","body","onSubmit","onCancel","url","setUrl","title","setTitle","content","setContent","selection","setSelection","busy","setBusy","Input","e","Textarea"],"mappings":"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"}
@@ -1 +1 @@
1
- import{r as t,j as e}from"./cmdk-DVxytz9i.js";import{S as v,I as o,k as I,j as w,Q as L,u as y,d as c,h as S,i as z,F as k}from"./main-CyAIirBB.js";import{V as D}from"./ViewHeader-V_SzbUpw.js";import{C as b,b as C}from"./Card-D9019JOD.js";import{I as P}from"./Input-BSa3lh_-.js";import{E}from"./EmptyState-DLmtBX_6.js";import{P as R}from"./plug-CQYGgGSy.js";import{R as M}from"./refresh-ccw-BCXx86xp.js";import{S as $}from"./save-DtMTge1F.js";import{P as T}from"./plus-fFxt-8z5.js";import{P as A}from"./pencil-BUJ2DpWs.js";import{T as B}from"./trash-2-2NsyTU8c.js";const F=[{id:"runtime",label:"Runtime config",icon:I},{id:"providers",label:"Providers",icon:w},{id:"mcps",label:"MCPs",icon:R},{id:"system-llm",label:"System LLM",icon:L}];function se(){const[s,n]=t.useState("runtime");return e.jsxs(v,{gap:4,"data-testid":"config-view",children:[e.jsx(D,{title:"Config",description:"Runtime config + providers + MCPs + system LLM."}),e.jsx(o,{gap:1,role:"tablist",children:F.map(r=>e.jsxs("button",{type:"button",role:"tab","aria-selected":s===r.id,onClick:()=>n(r.id),"data-testid":`config-tab-${r.id}`,style:{padding:"var(--space-2) var(--space-3)",borderRadius:"var(--radius-md)",border:"1px solid var(--border)",background:s===r.id?"color-mix(in oklch, var(--accent) 14%, transparent)":"var(--surface-0)",color:s===r.id?"var(--accent)":"var(--fg-muted)",fontSize:"var(--fs-12)",cursor:"pointer"},children:[e.jsx(r.icon,{size:14,"aria-hidden":!0,style:{verticalAlign:"middle",marginRight:6}}),r.label]},r.id))}),s==="runtime"&&e.jsx(N,{}),s==="providers"&&e.jsx(V,{}),s==="mcps"&&e.jsx(U,{}),s==="system-llm"&&e.jsx(H,{})]})}function N(){var h;const s=y("/api/config"),[n,r]=t.useState(""),[i,m]=t.useState(!1),[x,l]=t.useState(!1),[f,u]=t.useState(null);t.useEffect(()=>{var a;((a=s.data)==null?void 0:a.raw)!==void 0&&r(s.data.raw)},[(h=s.data)==null?void 0:h.raw]);const j=t.useCallback(()=>{s.refetch()},[s]),g=async()=>{m(!0),u(null),l(!1);try{await z("/api/config",{method:"PUT",body:n}),l(!0),j()}catch(a){u((a instanceof k,a.message))}finally{m(!1)}};return e.jsx(b,{variant:"default",children:e.jsx(C,{children:e.jsxs(v,{gap:2,children:[e.jsxs(o,{align:"center",justify:"between",gap:2,children:[e.jsx("strong",{style:{fontSize:"var(--fs-13)"},children:"Runtime config"}),e.jsxs(o,{gap:1,children:[e.jsxs(c,{variant:"ghost",onClick:j,"data-testid":"config-runtime-reload",children:[e.jsx(M,{size:14,"aria-hidden":!0})," Reload"]}),e.jsxs(c,{variant:"primary",onClick:()=>void g(),disabled:i,"data-testid":"config-runtime-save",children:[e.jsx($,{size:14,"aria-hidden":!0})," ",i?"Saving…":"Save"]})]})]}),s.loading&&s.data===null?e.jsx(S,{style:{height:240}}):e.jsx("textarea",{value:n,rows:16,"data-testid":"config-runtime-raw",onChange:a=>r(a.target.value),style:{background:"var(--surface-0)",border:"1px solid var(--border)",borderRadius:"var(--radius-md)",padding:"var(--space-2)",color:"var(--fg)",fontFamily:"var(--font-mono)",fontSize:"var(--fs-12)",resize:"vertical"}}),x&&e.jsx("span",{"data-testid":"config-runtime-saved",style:{color:"var(--success)",fontSize:"var(--fs-12)"},children:"Saved"}),f!==null&&e.jsx("span",{role:"alert","data-testid":"config-runtime-error",style:{color:"var(--danger)",fontSize:"var(--fs-12)"},children:f})]})})})}function V(){const s=y("/api/config/providers"),[n,r]=t.useState(!1),[i,m]=t.useState(null),[x,l]=t.useState(null),[f,u]=t.useState(null),j=t.useCallback(()=>{s.refetch()},[s]),g=t.useMemo(()=>{var a;return((a=s.data)==null?void 0:a.providers)??[]},[s.data]),h=async a=>{u(null);try{await z(`/api/config/providers/${a}`,{method:"DELETE"}),l(null),j()}catch(p){u((p instanceof k,p.message))}};return e.jsx(b,{variant:"default",children:e.jsx(C,{children:e.jsxs(v,{gap:2,children:[e.jsxs(o,{align:"center",justify:"between",gap:2,children:[e.jsx("strong",{style:{fontSize:"var(--fs-13)"},children:"Providers"}),e.jsxs(o,{gap:1,children:[f!==null&&e.jsx("span",{role:"alert",style:{color:"var(--danger)",fontSize:"var(--fs-12)"},children:f}),e.jsxs(c,{variant:"primary",onClick:()=>r(!0),"data-testid":"config-providers-add",children:[e.jsx(T,{size:14,"aria-hidden":!0})," Add"]})]})]}),s.loading&&g.length===0?e.jsx(S,{style:{height:100}}):g.length===0?e.jsx(E,{icon:e.jsx(w,{size:28,"aria-hidden":!0}),title:"No providers",description:"Add one or use Auto-add with key."}):e.jsx(v,{gap:1,children:g.map(a=>{const p=x===a.id;return e.jsxs("div",{"data-testid":`config-provider-row-${a.id}`,style:{padding:"var(--space-2)",border:"1px solid var(--border)",borderRadius:"var(--radius-sm)"},children:[e.jsxs(o,{align:"center",justify:"between",gap:2,children:[e.jsxs(o,{align:"center",gap:2,children:[e.jsx("strong",{children:a.name||a.id}),a.groupId&&e.jsxs("span",{style:{fontSize:"var(--fs-12)",color:"var(--fg-muted)"},children:["group=",a.groupId]})]}),e.jsxs(o,{gap:1,children:[e.jsx(c,{variant:"ghost",onClick:()=>m(a.id),"data-testid":`config-provider-edit-${a.id}`,"aria-label":`Edit ${a.id}`,children:e.jsx(A,{size:14,"aria-hidden":!0})}),e.jsx(c,{variant:"ghost",onClick:()=>l(d=>d===a.id?null:a.id),"data-testid":`config-provider-delete-${a.id}`,"aria-label":`Delete ${a.id}`,children:e.jsx(B,{size:14,"aria-hidden":!0})})]})]}),p&&e.jsxs(o,{gap:1,style:{marginTop:"var(--space-1)"},children:[e.jsx(c,{variant:"danger",onClick:()=>void h(a.id),"data-testid":`config-provider-confirm-delete-${a.id}`,children:"Confirm delete"}),e.jsx(c,{variant:"ghost",onClick:()=>l(null),children:"Cancel"})]})]},a.id)})})]})})})}function U(){const s=y("/api/config/mcps"),n=t.useMemo(()=>{var i;return((i=s.data)==null?void 0:i.mcps)??[]},[s.data]),r=t.useCallback(()=>{s.refetch()},[s]);return e.jsx(b,{variant:"default",children:e.jsx(C,{children:e.jsxs(v,{gap:2,children:[e.jsx(o,{align:"center",justify:"between",gap:2,children:e.jsx("strong",{style:{fontSize:"var(--fs-13)"},children:"MCP servers"})}),s.loading&&n.length===0?e.jsx(S,{style:{height:60}}):n.length===0?e.jsx(E,{icon:e.jsx(R,{size:28,"aria-hidden":!0}),title:"No MCPs",description:"Add one via /api/config/mcps."}):e.jsx(v,{gap:1,children:n.map(i=>e.jsxs("div",{"data-testid":`config-mcp-row-${i.id}`,style:{padding:"var(--space-2)",border:"1px solid var(--border)",borderRadius:"var(--radius-sm)",display:"flex",justifyContent:"space-between"},children:[e.jsx("strong",{children:i.name||i.id}),i.command&&e.jsx("code",{style:{fontSize:"var(--fs-12)",color:"var(--fg-muted)"},children:i.command})]},i.id))}),e.jsxs(c,{variant:"ghost",onClick:r,"data-testid":"config-mcps-refresh",children:[e.jsx(M,{size:14,"aria-hidden":!0})," Refresh"]})]})})})}function H(){const s=y("/api/llm/system-llm"),[n,r]=t.useState(!1),[i,m]=t.useState(""),[x,l]=t.useState(""),[f,u]=t.useState(!1),[j,g]=t.useState(!1),[h,a]=t.useState(null);t.useEffect(()=>{s.data&&(r(s.data.enabled),m(s.data.provider??""),l(s.data.model??""))},[s.data]);const p=async()=>{u(!0),a(null),g(!1);try{await z("/api/llm/system-llm",{method:"PUT",body:{enabled:n,provider:i,model:x}}),g(!0),s.refetch()}catch(d){a((d instanceof k,d.message))}finally{u(!1)}};return e.jsx(b,{variant:"default",children:e.jsx(C,{children:e.jsxs(v,{gap:2,children:[e.jsx("strong",{style:{fontSize:"var(--fs-13)"},children:"System LLM"}),s.loading&&s.data===null?e.jsx(S,{style:{height:100}}):e.jsxs(v,{gap:2,children:[e.jsxs("label",{style:{display:"flex",alignItems:"center",gap:"var(--space-2)"},children:[e.jsx("input",{type:"checkbox",checked:n,"data-testid":"config-system-llm-enabled",onChange:d=>r(d.target.checked)}),e.jsx("span",{style:{fontSize:"var(--fs-13)"},children:"Enabled"})]}),e.jsxs("label",{style:{display:"flex",flexDirection:"column",gap:"var(--space-1)"},children:[e.jsx("span",{style:{fontSize:"var(--fs-12)",color:"var(--fg-muted)"},children:"Provider"}),e.jsx(P,{value:i,"data-testid":"config-system-llm-provider",onChange:d=>m(d.target.value)})]}),e.jsxs("label",{style:{display:"flex",flexDirection:"column",gap:"var(--space-1)"},children:[e.jsx("span",{style:{fontSize:"var(--fs-12)",color:"var(--fg-muted)"},children:"Model"}),e.jsx(P,{value:x,"data-testid":"config-system-llm-model",onChange:d=>l(d.target.value)})]}),e.jsx(o,{justify:"end",gap:2,children:e.jsxs(c,{variant:"primary",onClick:()=>void p(),disabled:f,"data-testid":"config-system-llm-save",children:[e.jsx($,{size:14,"aria-hidden":!0})," ",f?"Saving…":"Save"]})}),j&&e.jsx("span",{"data-testid":"config-system-llm-saved",style:{color:"var(--success)",fontSize:"var(--fs-12)"},children:"Saved"}),h!==null&&e.jsx("span",{role:"alert","data-testid":"config-system-llm-error",style:{color:"var(--danger)",fontSize:"var(--fs-12)"},children:h})]})]})})})}export{se as ConfigView};
1
+ import{r as t,j as e}from"./cmdk-DVxytz9i.js";import{S as v,I as o,k as I,j as w,Q as L,u as y,d as c,h as S,i as z,F as k}from"./main-Cxeu4LhG.js";import{V as D}from"./ViewHeader-B6P-C4GD.js";import{C as b,b as C}from"./Card-rF59wHiO.js";import{I as P}from"./Input-CZmRw5QX.js";import{E}from"./EmptyState-D65J5FQN.js";import{P as R}from"./plug-BKuyIe5W.js";import{R as M}from"./refresh-ccw-DenGBOcq.js";import{S as $}from"./save-Db1b-1Uq.js";import{P as T}from"./plus-77h62zZm.js";import{P as A}from"./pencil-DVrBlYV3.js";import{T as B}from"./trash-2-Cv7U38jw.js";const F=[{id:"runtime",label:"Runtime config",icon:I},{id:"providers",label:"Providers",icon:w},{id:"mcps",label:"MCPs",icon:R},{id:"system-llm",label:"System LLM",icon:L}];function se(){const[s,n]=t.useState("runtime");return e.jsxs(v,{gap:4,"data-testid":"config-view",children:[e.jsx(D,{title:"Config",description:"Runtime config + providers + MCPs + system LLM."}),e.jsx(o,{gap:1,role:"tablist",children:F.map(r=>e.jsxs("button",{type:"button",role:"tab","aria-selected":s===r.id,onClick:()=>n(r.id),"data-testid":`config-tab-${r.id}`,style:{padding:"var(--space-2) var(--space-3)",borderRadius:"var(--radius-md)",border:"1px solid var(--border)",background:s===r.id?"color-mix(in oklch, var(--accent) 14%, transparent)":"var(--surface-0)",color:s===r.id?"var(--accent)":"var(--fg-muted)",fontSize:"var(--fs-12)",cursor:"pointer"},children:[e.jsx(r.icon,{size:14,"aria-hidden":!0,style:{verticalAlign:"middle",marginRight:6}}),r.label]},r.id))}),s==="runtime"&&e.jsx(N,{}),s==="providers"&&e.jsx(V,{}),s==="mcps"&&e.jsx(U,{}),s==="system-llm"&&e.jsx(H,{})]})}function N(){var h;const s=y("/api/config"),[n,r]=t.useState(""),[i,m]=t.useState(!1),[x,l]=t.useState(!1),[f,u]=t.useState(null);t.useEffect(()=>{var a;((a=s.data)==null?void 0:a.raw)!==void 0&&r(s.data.raw)},[(h=s.data)==null?void 0:h.raw]);const j=t.useCallback(()=>{s.refetch()},[s]),g=async()=>{m(!0),u(null),l(!1);try{await z("/api/config",{method:"PUT",body:n}),l(!0),j()}catch(a){u((a instanceof k,a.message))}finally{m(!1)}};return e.jsx(b,{variant:"default",children:e.jsx(C,{children:e.jsxs(v,{gap:2,children:[e.jsxs(o,{align:"center",justify:"between",gap:2,children:[e.jsx("strong",{style:{fontSize:"var(--fs-13)"},children:"Runtime config"}),e.jsxs(o,{gap:1,children:[e.jsxs(c,{variant:"ghost",onClick:j,"data-testid":"config-runtime-reload",children:[e.jsx(M,{size:14,"aria-hidden":!0})," Reload"]}),e.jsxs(c,{variant:"primary",onClick:()=>void g(),disabled:i,"data-testid":"config-runtime-save",children:[e.jsx($,{size:14,"aria-hidden":!0})," ",i?"Saving…":"Save"]})]})]}),s.loading&&s.data===null?e.jsx(S,{style:{height:240}}):e.jsx("textarea",{value:n,rows:16,"data-testid":"config-runtime-raw",onChange:a=>r(a.target.value),style:{background:"var(--surface-0)",border:"1px solid var(--border)",borderRadius:"var(--radius-md)",padding:"var(--space-2)",color:"var(--fg)",fontFamily:"var(--font-mono)",fontSize:"var(--fs-12)",resize:"vertical"}}),x&&e.jsx("span",{"data-testid":"config-runtime-saved",style:{color:"var(--success)",fontSize:"var(--fs-12)"},children:"Saved"}),f!==null&&e.jsx("span",{role:"alert","data-testid":"config-runtime-error",style:{color:"var(--danger)",fontSize:"var(--fs-12)"},children:f})]})})})}function V(){const s=y("/api/config/providers"),[n,r]=t.useState(!1),[i,m]=t.useState(null),[x,l]=t.useState(null),[f,u]=t.useState(null),j=t.useCallback(()=>{s.refetch()},[s]),g=t.useMemo(()=>{var a;return((a=s.data)==null?void 0:a.providers)??[]},[s.data]),h=async a=>{u(null);try{await z(`/api/config/providers/${a}`,{method:"DELETE"}),l(null),j()}catch(p){u((p instanceof k,p.message))}};return e.jsx(b,{variant:"default",children:e.jsx(C,{children:e.jsxs(v,{gap:2,children:[e.jsxs(o,{align:"center",justify:"between",gap:2,children:[e.jsx("strong",{style:{fontSize:"var(--fs-13)"},children:"Providers"}),e.jsxs(o,{gap:1,children:[f!==null&&e.jsx("span",{role:"alert",style:{color:"var(--danger)",fontSize:"var(--fs-12)"},children:f}),e.jsxs(c,{variant:"primary",onClick:()=>r(!0),"data-testid":"config-providers-add",children:[e.jsx(T,{size:14,"aria-hidden":!0})," Add"]})]})]}),s.loading&&g.length===0?e.jsx(S,{style:{height:100}}):g.length===0?e.jsx(E,{icon:e.jsx(w,{size:28,"aria-hidden":!0}),title:"No providers",description:"Add one or use Auto-add with key."}):e.jsx(v,{gap:1,children:g.map(a=>{const p=x===a.id;return e.jsxs("div",{"data-testid":`config-provider-row-${a.id}`,style:{padding:"var(--space-2)",border:"1px solid var(--border)",borderRadius:"var(--radius-sm)"},children:[e.jsxs(o,{align:"center",justify:"between",gap:2,children:[e.jsxs(o,{align:"center",gap:2,children:[e.jsx("strong",{children:a.name||a.id}),a.groupId&&e.jsxs("span",{style:{fontSize:"var(--fs-12)",color:"var(--fg-muted)"},children:["group=",a.groupId]})]}),e.jsxs(o,{gap:1,children:[e.jsx(c,{variant:"ghost",onClick:()=>m(a.id),"data-testid":`config-provider-edit-${a.id}`,"aria-label":`Edit ${a.id}`,children:e.jsx(A,{size:14,"aria-hidden":!0})}),e.jsx(c,{variant:"ghost",onClick:()=>l(d=>d===a.id?null:a.id),"data-testid":`config-provider-delete-${a.id}`,"aria-label":`Delete ${a.id}`,children:e.jsx(B,{size:14,"aria-hidden":!0})})]})]}),p&&e.jsxs(o,{gap:1,style:{marginTop:"var(--space-1)"},children:[e.jsx(c,{variant:"danger",onClick:()=>void h(a.id),"data-testid":`config-provider-confirm-delete-${a.id}`,children:"Confirm delete"}),e.jsx(c,{variant:"ghost",onClick:()=>l(null),children:"Cancel"})]})]},a.id)})})]})})})}function U(){const s=y("/api/config/mcps"),n=t.useMemo(()=>{var i;return((i=s.data)==null?void 0:i.mcps)??[]},[s.data]),r=t.useCallback(()=>{s.refetch()},[s]);return e.jsx(b,{variant:"default",children:e.jsx(C,{children:e.jsxs(v,{gap:2,children:[e.jsx(o,{align:"center",justify:"between",gap:2,children:e.jsx("strong",{style:{fontSize:"var(--fs-13)"},children:"MCP servers"})}),s.loading&&n.length===0?e.jsx(S,{style:{height:60}}):n.length===0?e.jsx(E,{icon:e.jsx(R,{size:28,"aria-hidden":!0}),title:"No MCPs",description:"Add one via /api/config/mcps."}):e.jsx(v,{gap:1,children:n.map(i=>e.jsxs("div",{"data-testid":`config-mcp-row-${i.id}`,style:{padding:"var(--space-2)",border:"1px solid var(--border)",borderRadius:"var(--radius-sm)",display:"flex",justifyContent:"space-between"},children:[e.jsx("strong",{children:i.name||i.id}),i.command&&e.jsx("code",{style:{fontSize:"var(--fs-12)",color:"var(--fg-muted)"},children:i.command})]},i.id))}),e.jsxs(c,{variant:"ghost",onClick:r,"data-testid":"config-mcps-refresh",children:[e.jsx(M,{size:14,"aria-hidden":!0})," Refresh"]})]})})})}function H(){const s=y("/api/llm/system-llm"),[n,r]=t.useState(!1),[i,m]=t.useState(""),[x,l]=t.useState(""),[f,u]=t.useState(!1),[j,g]=t.useState(!1),[h,a]=t.useState(null);t.useEffect(()=>{s.data&&(r(s.data.enabled),m(s.data.provider??""),l(s.data.model??""))},[s.data]);const p=async()=>{u(!0),a(null),g(!1);try{await z("/api/llm/system-llm",{method:"PUT",body:{enabled:n,provider:i,model:x}}),g(!0),s.refetch()}catch(d){a((d instanceof k,d.message))}finally{u(!1)}};return e.jsx(b,{variant:"default",children:e.jsx(C,{children:e.jsxs(v,{gap:2,children:[e.jsx("strong",{style:{fontSize:"var(--fs-13)"},children:"System LLM"}),s.loading&&s.data===null?e.jsx(S,{style:{height:100}}):e.jsxs(v,{gap:2,children:[e.jsxs("label",{style:{display:"flex",alignItems:"center",gap:"var(--space-2)"},children:[e.jsx("input",{type:"checkbox",checked:n,"data-testid":"config-system-llm-enabled",onChange:d=>r(d.target.checked)}),e.jsx("span",{style:{fontSize:"var(--fs-13)"},children:"Enabled"})]}),e.jsxs("label",{style:{display:"flex",flexDirection:"column",gap:"var(--space-1)"},children:[e.jsx("span",{style:{fontSize:"var(--fs-12)",color:"var(--fg-muted)"},children:"Provider"}),e.jsx(P,{value:i,"data-testid":"config-system-llm-provider",onChange:d=>m(d.target.value)})]}),e.jsxs("label",{style:{display:"flex",flexDirection:"column",gap:"var(--space-1)"},children:[e.jsx("span",{style:{fontSize:"var(--fs-12)",color:"var(--fg-muted)"},children:"Model"}),e.jsx(P,{value:x,"data-testid":"config-system-llm-model",onChange:d=>l(d.target.value)})]}),e.jsx(o,{justify:"end",gap:2,children:e.jsxs(c,{variant:"primary",onClick:()=>void p(),disabled:f,"data-testid":"config-system-llm-save",children:[e.jsx($,{size:14,"aria-hidden":!0})," ",f?"Saving…":"Save"]})}),j&&e.jsx("span",{"data-testid":"config-system-llm-saved",style:{color:"var(--success)",fontSize:"var(--fs-12)"},children:"Saved"}),h!==null&&e.jsx("span",{role:"alert","data-testid":"config-system-llm-error",style:{color:"var(--danger)",fontSize:"var(--fs-12)"},children:h})]})]})})})}export{se as ConfigView};
@@ -1 +1 @@
1
- {"version":3,"file":"ConfigView-DWHJgoe8.js","sources":["../../src/web/v8/views/Config/ConfigView.tsx"],"sourcesContent":["/**\n * v8/views/Config/ConfigView.tsx — Sprint S41, v9.3.0.\n *\n * Three sub-sections:\n * - Runtime config: read-only viewer + Reload + Save (PUT\n * /api/config with the edited raw JSON).\n * - Providers: full CRUD via /api/config/providers + the\n * \"add with key\" auto endpoint.\n * - MCPs: full CRUD via /api/config/mcps.\n * - System LLM: read/write the cline.json#systemLlm block via\n * /api/llm/system-llm.\n *\n * Inline confirm for delete. Sheet form for Add / Edit.\n */\n\nimport { useCallback, useEffect, useMemo, useState } from 'react';\nimport { Plus, Pencil, Trash2, RefreshCcw, Save, ServerCog, Cpu, Plug, Settings as SettingsIcon } from 'lucide-react';\nimport type { LucideIcon } from 'lucide-react';\nimport { Stack } from '../../ui/primitives/Stack.js';\nimport { Inline } from '../../ui/primitives/Inline.js';\nimport { ViewHeader } from '../../ui/data/ViewHeader.js';\nimport { Card, CardBody } from '../../ui/data/Card.js';\nimport { Button } from '../../ui/controls/Button.js';\nimport { Input } from '../../ui/controls/Input.js';\nimport { Sheet, SheetClose, SheetContent } from '../../ui/feedback/Sheet.js';\nimport { Skeleton } from '../../ui/feedback/Skeleton.js';\nimport { EmptyState } from '../../ui/feedback/EmptyState.js';\nimport { useFetch } from '../../data/useFetch.js';\nimport { fetchJson, FetchError } from '../../data/fetcher.js';\n\ninterface Provider {\n id: string;\n name?: string;\n groupId?: string;\n}\n\ninterface Mcp {\n id: string;\n name?: string;\n command?: string;\n}\n\ninterface SystemLlm {\n enabled: boolean;\n provider: string | null;\n model: string | null;\n}\n\ninterface RuntimeConfig {\n path: string;\n data: unknown;\n raw: string;\n exists: boolean;\n}\n\ntype SectionId = 'runtime' | 'providers' | 'mcps' | 'system-llm';\n\nconst SECTIONS: Array<{ id: SectionId; label: string; icon: LucideIcon }> = [\n { id: 'runtime', label: 'Runtime config', icon: SettingsIcon },\n { id: 'providers', label: 'Providers', icon: Cpu },\n { id: 'mcps', label: 'MCPs', icon: Plug },\n { id: 'system-llm', label: 'System LLM', icon: ServerCog },\n];\n\nexport function ConfigView(): JSX.Element {\n const [section, setSection] = useState<SectionId>('runtime');\n return (\n <Stack gap={4} data-testid=\"config-view\">\n <ViewHeader\n title=\"Config\"\n description=\"Runtime config + providers + MCPs + system LLM.\"\n />\n <Inline gap={1} role=\"tablist\">\n {SECTIONS.map((s) => (\n <button\n key={s.id}\n type=\"button\"\n role=\"tab\"\n aria-selected={section === s.id}\n onClick={() => setSection(s.id)}\n data-testid={`config-tab-${s.id}`}\n style={{\n padding: 'var(--space-2) var(--space-3)',\n borderRadius: 'var(--radius-md)',\n border: '1px solid var(--border)',\n background: section === s.id ? 'color-mix(in oklch, var(--accent) 14%, transparent)' : 'var(--surface-0)',\n color: section === s.id ? 'var(--accent)' : 'var(--fg-muted)',\n fontSize: 'var(--fs-12)',\n cursor: 'pointer',\n }}\n >\n <s.icon size={14} aria-hidden style={{ verticalAlign: 'middle', marginRight: 6 }} />\n {s.label}\n </button>\n ))}\n </Inline>\n {section === 'runtime' && <RuntimeConfigPanel />}\n {section === 'providers' && <ProvidersPanel />}\n {section === 'mcps' && <McpsPanel />}\n {section === 'system-llm' && <SystemLlmPanel />}\n </Stack>\n );\n}\n\nfunction RuntimeConfigPanel(): JSX.Element {\n const payload = useFetch<RuntimeConfig>('/api/config');\n const [draft, setDraft] = useState<string>('');\n const [busy, setBusy] = useState<boolean>(false);\n const [saved, setSaved] = useState<boolean>(false);\n const [error, setError] = useState<string | null>(null);\n\n useEffect(() => {\n if (payload.data?.raw !== undefined) setDraft(payload.data.raw);\n }, [payload.data?.raw]);\n\n const reload = useCallback(() => { void payload.refetch(); }, [payload]);\n\n const save = async (): Promise<void> => {\n setBusy(true);\n setError(null);\n setSaved(false);\n try {\n await fetchJson('/api/config', { method: 'PUT', body: draft });\n setSaved(true);\n reload();\n } catch (err) {\n setError(err instanceof FetchError ? err.message : (err as Error).message);\n } finally {\n setBusy(false);\n }\n };\n\n return (\n <Card variant=\"default\">\n <CardBody>\n <Stack gap={2}>\n <Inline align=\"center\" justify=\"between\" gap={2}>\n <strong style={{ fontSize: 'var(--fs-13)' }}>Runtime config</strong>\n <Inline gap={1}>\n <Button variant=\"ghost\" onClick={reload} data-testid=\"config-runtime-reload\">\n <RefreshCcw size={14} aria-hidden /> Reload\n </Button>\n <Button variant=\"primary\" onClick={() => void save()} disabled={busy} data-testid=\"config-runtime-save\">\n <Save size={14} aria-hidden /> {busy ? 'Saving…' : 'Save'}\n </Button>\n </Inline>\n </Inline>\n {payload.loading && payload.data === null ? (\n <Skeleton style={{ height: 240 }} />\n ) : (\n <textarea\n value={draft}\n rows={16}\n data-testid=\"config-runtime-raw\"\n onChange={(e) => setDraft((e.target as HTMLTextAreaElement).value)}\n style={{\n background: 'var(--surface-0)',\n border: '1px solid var(--border)',\n borderRadius: 'var(--radius-md)',\n padding: 'var(--space-2)',\n color: 'var(--fg)',\n fontFamily: 'var(--font-mono)',\n fontSize: 'var(--fs-12)',\n resize: 'vertical',\n }}\n />\n )}\n {saved && <span data-testid=\"config-runtime-saved\" style={{ color: 'var(--success)', fontSize: 'var(--fs-12)' }}>Saved</span>}\n {error !== null && (\n <span role=\"alert\" data-testid=\"config-runtime-error\" style={{ color: 'var(--danger)', fontSize: 'var(--fs-12)' }}>{error}</span>\n )}\n </Stack>\n </CardBody>\n </Card>\n );\n}\n\nfunction ProvidersPanel(): JSX.Element {\n const payload = useFetch<{ providers: Provider[] }>('/api/config/providers');\n const [adding, setAdding] = useState<boolean>(false);\n const [editing, setEditing] = useState<string | null>(null);\n const [confirmDelete, setConfirmDelete] = useState<string | null>(null);\n const [error, setError] = useState<string | null>(null);\n const refresh = useCallback(() => { void payload.refetch(); }, [payload]);\n const providers = useMemo(() => payload.data?.providers ?? [], [payload.data]);\n\n const drop = async (id: string): Promise<void> => {\n setError(null);\n try {\n await fetchJson(`/api/config/providers/${id}`, { method: 'DELETE' });\n setConfirmDelete(null);\n refresh();\n } catch (err) {\n setError(err instanceof FetchError ? err.message : (err as Error).message);\n }\n };\n\n return (\n <Card variant=\"default\">\n <CardBody>\n <Stack gap={2}>\n <Inline align=\"center\" justify=\"between\" gap={2}>\n <strong style={{ fontSize: 'var(--fs-13)' }}>Providers</strong>\n <Inline gap={1}>\n {error !== null && (\n <span role=\"alert\" style={{ color: 'var(--danger)', fontSize: 'var(--fs-12)' }}>{error}</span>\n )}\n <Button variant=\"primary\" onClick={() => setAdding(true)} data-testid=\"config-providers-add\">\n <Plus size={14} aria-hidden /> Add\n </Button>\n </Inline>\n </Inline>\n {payload.loading && providers.length === 0 ? (\n <Skeleton style={{ height: 100 }} />\n ) : providers.length === 0 ? (\n <EmptyState icon={<Cpu size={28} aria-hidden />} title=\"No providers\" description=\"Add one or use Auto-add with key.\" />\n ) : (\n <Stack gap={1}>\n {providers.map((p) => {\n const isConfirming = confirmDelete === p.id;\n return (\n <div key={p.id} data-testid={`config-provider-row-${p.id}`} style={{ padding: 'var(--space-2)', border: '1px solid var(--border)', borderRadius: 'var(--radius-sm)' }}>\n <Inline align=\"center\" justify=\"between\" gap={2}>\n <Inline align=\"center\" gap={2}>\n <strong>{p.name || p.id}</strong>\n {p.groupId && <span style={{ fontSize: 'var(--fs-12)', color: 'var(--fg-muted)' }}>group={p.groupId}</span>}\n </Inline>\n <Inline gap={1}>\n <Button variant=\"ghost\" onClick={() => setEditing(p.id)} data-testid={`config-provider-edit-${p.id}`} aria-label={`Edit ${p.id}`}>\n <Pencil size={14} aria-hidden />\n </Button>\n <Button variant=\"ghost\" onClick={() => setConfirmDelete((cur) => (cur === p.id ? null : p.id))} data-testid={`config-provider-delete-${p.id}`} aria-label={`Delete ${p.id}`}>\n <Trash2 size={14} aria-hidden />\n </Button>\n </Inline>\n </Inline>\n {isConfirming && (\n <Inline gap={1} style={{ marginTop: 'var(--space-1)' }}>\n <Button variant=\"danger\" onClick={() => void drop(p.id)} data-testid={`config-provider-confirm-delete-${p.id}`}>Confirm delete</Button>\n <Button variant=\"ghost\" onClick={() => setConfirmDelete(null)}>Cancel</Button>\n </Inline>\n )}\n </div>\n );\n })}\n </Stack>\n )}\n </Stack>\n </CardBody>\n </Card>\n );\n}\n\nfunction McpsPanel(): JSX.Element {\n const payload = useFetch<{ mcps: Mcp[] }>('/api/config/mcps');\n const mcps = useMemo(() => payload.data?.mcps ?? [], [payload.data]);\n const refresh = useCallback(() => { void payload.refetch(); }, [payload]);\n return (\n <Card variant=\"default\">\n <CardBody>\n <Stack gap={2}>\n <Inline align=\"center\" justify=\"between\" gap={2}>\n <strong style={{ fontSize: 'var(--fs-13)' }}>MCP servers</strong>\n </Inline>\n {payload.loading && mcps.length === 0 ? (\n <Skeleton style={{ height: 60 }} />\n ) : mcps.length === 0 ? (\n <EmptyState icon={<Plug size={28} aria-hidden />} title=\"No MCPs\" description=\"Add one via /api/config/mcps.\" />\n ) : (\n <Stack gap={1}>\n {mcps.map((m) => (\n <div key={m.id} data-testid={`config-mcp-row-${m.id}`} style={{ padding: 'var(--space-2)', border: '1px solid var(--border)', borderRadius: 'var(--radius-sm)', display: 'flex', justifyContent: 'space-between' }}>\n <strong>{m.name || m.id}</strong>\n {m.command && <code style={{ fontSize: 'var(--fs-12)', color: 'var(--fg-muted)' }}>{m.command}</code>}\n </div>\n ))}\n </Stack>\n )}\n <Button variant=\"ghost\" onClick={refresh} data-testid=\"config-mcps-refresh\">\n <RefreshCcw size={14} aria-hidden /> Refresh\n </Button>\n </Stack>\n </CardBody>\n </Card>\n );\n}\n\nfunction SystemLlmPanel(): JSX.Element {\n const payload = useFetch<SystemLlm>('/api/llm/system-llm');\n const [enabled, setEnabled] = useState<boolean>(false);\n const [provider, setProvider] = useState<string>('');\n const [model, setModel] = useState<string>('');\n const [busy, setBusy] = useState<boolean>(false);\n const [saved, setSaved] = useState<boolean>(false);\n const [error, setError] = useState<string | null>(null);\n\n useEffect(() => {\n if (payload.data) {\n setEnabled(payload.data.enabled);\n setProvider(payload.data.provider ?? '');\n setModel(payload.data.model ?? '');\n }\n }, [payload.data]);\n\n const save = async (): Promise<void> => {\n setBusy(true);\n setError(null);\n setSaved(false);\n try {\n await fetchJson('/api/llm/system-llm', {\n method: 'PUT',\n body: { enabled, provider, model },\n });\n setSaved(true);\n void payload.refetch();\n } catch (err) {\n setError(err instanceof FetchError ? err.message : (err as Error).message);\n } finally {\n setBusy(false);\n }\n };\n\n return (\n <Card variant=\"default\">\n <CardBody>\n <Stack gap={2}>\n <strong style={{ fontSize: 'var(--fs-13)' }}>System LLM</strong>\n {payload.loading && payload.data === null ? (\n <Skeleton style={{ height: 100 }} />\n ) : (\n <Stack gap={2}>\n <label style={{ display: 'flex', alignItems: 'center', gap: 'var(--space-2)' }}>\n <input\n type=\"checkbox\"\n checked={enabled}\n data-testid=\"config-system-llm-enabled\"\n onChange={(e) => setEnabled((e.target as HTMLInputElement).checked)}\n />\n <span style={{ fontSize: 'var(--fs-13)' }}>Enabled</span>\n </label>\n <label style={{ display: 'flex', flexDirection: 'column', gap: 'var(--space-1)' }}>\n <span style={{ fontSize: 'var(--fs-12)', color: 'var(--fg-muted)' }}>Provider</span>\n <Input value={provider} data-testid=\"config-system-llm-provider\" onChange={(e) => setProvider((e.target as HTMLInputElement).value)} />\n </label>\n <label style={{ display: 'flex', flexDirection: 'column', gap: 'var(--space-1)' }}>\n <span style={{ fontSize: 'var(--fs-12)', color: 'var(--fg-muted)' }}>Model</span>\n <Input value={model} data-testid=\"config-system-llm-model\" onChange={(e) => setModel((e.target as HTMLInputElement).value)} />\n </label>\n <Inline justify=\"end\" gap={2}>\n <Button variant=\"primary\" onClick={() => void save()} disabled={busy} data-testid=\"config-system-llm-save\">\n <Save size={14} aria-hidden /> {busy ? 'Saving…' : 'Save'}\n </Button>\n </Inline>\n {saved && <span data-testid=\"config-system-llm-saved\" style={{ color: 'var(--success)', fontSize: 'var(--fs-12)' }}>Saved</span>}\n {error !== null && (\n <span role=\"alert\" data-testid=\"config-system-llm-error\" style={{ color: 'var(--danger)', fontSize: 'var(--fs-12)' }}>{error}</span>\n )}\n </Stack>\n )}\n </Stack>\n </CardBody>\n </Card>\n );\n}"],"names":["SECTIONS","SettingsIcon","Cpu","Plug","ServerCog","ConfigView","section","setSection","useState","jsxs","Stack","jsx","ViewHeader","Inline","s","RuntimeConfigPanel","ProvidersPanel","McpsPanel","SystemLlmPanel","payload","useFetch","draft","setDraft","busy","setBusy","saved","setSaved","error","setError","useEffect","_a","reload","useCallback","save","fetchJson","err","FetchError","Card","CardBody","Button","RefreshCcw","Save","Skeleton","e","adding","setAdding","editing","setEditing","confirmDelete","setConfirmDelete","refresh","providers","useMemo","drop","id","Plus","EmptyState","p","isConfirming","Pencil","cur","Trash2","mcps","m","enabled","setEnabled","provider","setProvider","model","setModel","Input"],"mappings":"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"}
1
+ {"version":3,"file":"ConfigView-B2ysnTZU.js","sources":["../../src/web/v8/views/Config/ConfigView.tsx"],"sourcesContent":["/**\n * v8/views/Config/ConfigView.tsx — Sprint S41, v9.3.0.\n *\n * Three sub-sections:\n * - Runtime config: read-only viewer + Reload + Save (PUT\n * /api/config with the edited raw JSON).\n * - Providers: full CRUD via /api/config/providers + the\n * \"add with key\" auto endpoint.\n * - MCPs: full CRUD via /api/config/mcps.\n * - System LLM: read/write the cline.json#systemLlm block via\n * /api/llm/system-llm.\n *\n * Inline confirm for delete. Sheet form for Add / Edit.\n */\n\nimport { useCallback, useEffect, useMemo, useState } from 'react';\nimport { Plus, Pencil, Trash2, RefreshCcw, Save, ServerCog, Cpu, Plug, Settings as SettingsIcon } from 'lucide-react';\nimport type { LucideIcon } from 'lucide-react';\nimport { Stack } from '../../ui/primitives/Stack.js';\nimport { Inline } from '../../ui/primitives/Inline.js';\nimport { ViewHeader } from '../../ui/data/ViewHeader.js';\nimport { Card, CardBody } from '../../ui/data/Card.js';\nimport { Button } from '../../ui/controls/Button.js';\nimport { Input } from '../../ui/controls/Input.js';\nimport { Sheet, SheetClose, SheetContent } from '../../ui/feedback/Sheet.js';\nimport { Skeleton } from '../../ui/feedback/Skeleton.js';\nimport { EmptyState } from '../../ui/feedback/EmptyState.js';\nimport { useFetch } from '../../data/useFetch.js';\nimport { fetchJson, FetchError } from '../../data/fetcher.js';\n\ninterface Provider {\n id: string;\n name?: string;\n groupId?: string;\n}\n\ninterface Mcp {\n id: string;\n name?: string;\n command?: string;\n}\n\ninterface SystemLlm {\n enabled: boolean;\n provider: string | null;\n model: string | null;\n}\n\ninterface RuntimeConfig {\n path: string;\n data: unknown;\n raw: string;\n exists: boolean;\n}\n\ntype SectionId = 'runtime' | 'providers' | 'mcps' | 'system-llm';\n\nconst SECTIONS: Array<{ id: SectionId; label: string; icon: LucideIcon }> = [\n { id: 'runtime', label: 'Runtime config', icon: SettingsIcon },\n { id: 'providers', label: 'Providers', icon: Cpu },\n { id: 'mcps', label: 'MCPs', icon: Plug },\n { id: 'system-llm', label: 'System LLM', icon: ServerCog },\n];\n\nexport function ConfigView(): JSX.Element {\n const [section, setSection] = useState<SectionId>('runtime');\n return (\n <Stack gap={4} data-testid=\"config-view\">\n <ViewHeader\n title=\"Config\"\n description=\"Runtime config + providers + MCPs + system LLM.\"\n />\n <Inline gap={1} role=\"tablist\">\n {SECTIONS.map((s) => (\n <button\n key={s.id}\n type=\"button\"\n role=\"tab\"\n aria-selected={section === s.id}\n onClick={() => setSection(s.id)}\n data-testid={`config-tab-${s.id}`}\n style={{\n padding: 'var(--space-2) var(--space-3)',\n borderRadius: 'var(--radius-md)',\n border: '1px solid var(--border)',\n background: section === s.id ? 'color-mix(in oklch, var(--accent) 14%, transparent)' : 'var(--surface-0)',\n color: section === s.id ? 'var(--accent)' : 'var(--fg-muted)',\n fontSize: 'var(--fs-12)',\n cursor: 'pointer',\n }}\n >\n <s.icon size={14} aria-hidden style={{ verticalAlign: 'middle', marginRight: 6 }} />\n {s.label}\n </button>\n ))}\n </Inline>\n {section === 'runtime' && <RuntimeConfigPanel />}\n {section === 'providers' && <ProvidersPanel />}\n {section === 'mcps' && <McpsPanel />}\n {section === 'system-llm' && <SystemLlmPanel />}\n </Stack>\n );\n}\n\nfunction RuntimeConfigPanel(): JSX.Element {\n const payload = useFetch<RuntimeConfig>('/api/config');\n const [draft, setDraft] = useState<string>('');\n const [busy, setBusy] = useState<boolean>(false);\n const [saved, setSaved] = useState<boolean>(false);\n const [error, setError] = useState<string | null>(null);\n\n useEffect(() => {\n if (payload.data?.raw !== undefined) setDraft(payload.data.raw);\n }, [payload.data?.raw]);\n\n const reload = useCallback(() => { void payload.refetch(); }, [payload]);\n\n const save = async (): Promise<void> => {\n setBusy(true);\n setError(null);\n setSaved(false);\n try {\n await fetchJson('/api/config', { method: 'PUT', body: draft });\n setSaved(true);\n reload();\n } catch (err) {\n setError(err instanceof FetchError ? err.message : (err as Error).message);\n } finally {\n setBusy(false);\n }\n };\n\n return (\n <Card variant=\"default\">\n <CardBody>\n <Stack gap={2}>\n <Inline align=\"center\" justify=\"between\" gap={2}>\n <strong style={{ fontSize: 'var(--fs-13)' }}>Runtime config</strong>\n <Inline gap={1}>\n <Button variant=\"ghost\" onClick={reload} data-testid=\"config-runtime-reload\">\n <RefreshCcw size={14} aria-hidden /> Reload\n </Button>\n <Button variant=\"primary\" onClick={() => void save()} disabled={busy} data-testid=\"config-runtime-save\">\n <Save size={14} aria-hidden /> {busy ? 'Saving…' : 'Save'}\n </Button>\n </Inline>\n </Inline>\n {payload.loading && payload.data === null ? (\n <Skeleton style={{ height: 240 }} />\n ) : (\n <textarea\n value={draft}\n rows={16}\n data-testid=\"config-runtime-raw\"\n onChange={(e) => setDraft((e.target as HTMLTextAreaElement).value)}\n style={{\n background: 'var(--surface-0)',\n border: '1px solid var(--border)',\n borderRadius: 'var(--radius-md)',\n padding: 'var(--space-2)',\n color: 'var(--fg)',\n fontFamily: 'var(--font-mono)',\n fontSize: 'var(--fs-12)',\n resize: 'vertical',\n }}\n />\n )}\n {saved && <span data-testid=\"config-runtime-saved\" style={{ color: 'var(--success)', fontSize: 'var(--fs-12)' }}>Saved</span>}\n {error !== null && (\n <span role=\"alert\" data-testid=\"config-runtime-error\" style={{ color: 'var(--danger)', fontSize: 'var(--fs-12)' }}>{error}</span>\n )}\n </Stack>\n </CardBody>\n </Card>\n );\n}\n\nfunction ProvidersPanel(): JSX.Element {\n const payload = useFetch<{ providers: Provider[] }>('/api/config/providers');\n const [adding, setAdding] = useState<boolean>(false);\n const [editing, setEditing] = useState<string | null>(null);\n const [confirmDelete, setConfirmDelete] = useState<string | null>(null);\n const [error, setError] = useState<string | null>(null);\n const refresh = useCallback(() => { void payload.refetch(); }, [payload]);\n const providers = useMemo(() => payload.data?.providers ?? [], [payload.data]);\n\n const drop = async (id: string): Promise<void> => {\n setError(null);\n try {\n await fetchJson(`/api/config/providers/${id}`, { method: 'DELETE' });\n setConfirmDelete(null);\n refresh();\n } catch (err) {\n setError(err instanceof FetchError ? err.message : (err as Error).message);\n }\n };\n\n return (\n <Card variant=\"default\">\n <CardBody>\n <Stack gap={2}>\n <Inline align=\"center\" justify=\"between\" gap={2}>\n <strong style={{ fontSize: 'var(--fs-13)' }}>Providers</strong>\n <Inline gap={1}>\n {error !== null && (\n <span role=\"alert\" style={{ color: 'var(--danger)', fontSize: 'var(--fs-12)' }}>{error}</span>\n )}\n <Button variant=\"primary\" onClick={() => setAdding(true)} data-testid=\"config-providers-add\">\n <Plus size={14} aria-hidden /> Add\n </Button>\n </Inline>\n </Inline>\n {payload.loading && providers.length === 0 ? (\n <Skeleton style={{ height: 100 }} />\n ) : providers.length === 0 ? (\n <EmptyState icon={<Cpu size={28} aria-hidden />} title=\"No providers\" description=\"Add one or use Auto-add with key.\" />\n ) : (\n <Stack gap={1}>\n {providers.map((p) => {\n const isConfirming = confirmDelete === p.id;\n return (\n <div key={p.id} data-testid={`config-provider-row-${p.id}`} style={{ padding: 'var(--space-2)', border: '1px solid var(--border)', borderRadius: 'var(--radius-sm)' }}>\n <Inline align=\"center\" justify=\"between\" gap={2}>\n <Inline align=\"center\" gap={2}>\n <strong>{p.name || p.id}</strong>\n {p.groupId && <span style={{ fontSize: 'var(--fs-12)', color: 'var(--fg-muted)' }}>group={p.groupId}</span>}\n </Inline>\n <Inline gap={1}>\n <Button variant=\"ghost\" onClick={() => setEditing(p.id)} data-testid={`config-provider-edit-${p.id}`} aria-label={`Edit ${p.id}`}>\n <Pencil size={14} aria-hidden />\n </Button>\n <Button variant=\"ghost\" onClick={() => setConfirmDelete((cur) => (cur === p.id ? null : p.id))} data-testid={`config-provider-delete-${p.id}`} aria-label={`Delete ${p.id}`}>\n <Trash2 size={14} aria-hidden />\n </Button>\n </Inline>\n </Inline>\n {isConfirming && (\n <Inline gap={1} style={{ marginTop: 'var(--space-1)' }}>\n <Button variant=\"danger\" onClick={() => void drop(p.id)} data-testid={`config-provider-confirm-delete-${p.id}`}>Confirm delete</Button>\n <Button variant=\"ghost\" onClick={() => setConfirmDelete(null)}>Cancel</Button>\n </Inline>\n )}\n </div>\n );\n })}\n </Stack>\n )}\n </Stack>\n </CardBody>\n </Card>\n );\n}\n\nfunction McpsPanel(): JSX.Element {\n const payload = useFetch<{ mcps: Mcp[] }>('/api/config/mcps');\n const mcps = useMemo(() => payload.data?.mcps ?? [], [payload.data]);\n const refresh = useCallback(() => { void payload.refetch(); }, [payload]);\n return (\n <Card variant=\"default\">\n <CardBody>\n <Stack gap={2}>\n <Inline align=\"center\" justify=\"between\" gap={2}>\n <strong style={{ fontSize: 'var(--fs-13)' }}>MCP servers</strong>\n </Inline>\n {payload.loading && mcps.length === 0 ? (\n <Skeleton style={{ height: 60 }} />\n ) : mcps.length === 0 ? (\n <EmptyState icon={<Plug size={28} aria-hidden />} title=\"No MCPs\" description=\"Add one via /api/config/mcps.\" />\n ) : (\n <Stack gap={1}>\n {mcps.map((m) => (\n <div key={m.id} data-testid={`config-mcp-row-${m.id}`} style={{ padding: 'var(--space-2)', border: '1px solid var(--border)', borderRadius: 'var(--radius-sm)', display: 'flex', justifyContent: 'space-between' }}>\n <strong>{m.name || m.id}</strong>\n {m.command && <code style={{ fontSize: 'var(--fs-12)', color: 'var(--fg-muted)' }}>{m.command}</code>}\n </div>\n ))}\n </Stack>\n )}\n <Button variant=\"ghost\" onClick={refresh} data-testid=\"config-mcps-refresh\">\n <RefreshCcw size={14} aria-hidden /> Refresh\n </Button>\n </Stack>\n </CardBody>\n </Card>\n );\n}\n\nfunction SystemLlmPanel(): JSX.Element {\n const payload = useFetch<SystemLlm>('/api/llm/system-llm');\n const [enabled, setEnabled] = useState<boolean>(false);\n const [provider, setProvider] = useState<string>('');\n const [model, setModel] = useState<string>('');\n const [busy, setBusy] = useState<boolean>(false);\n const [saved, setSaved] = useState<boolean>(false);\n const [error, setError] = useState<string | null>(null);\n\n useEffect(() => {\n if (payload.data) {\n setEnabled(payload.data.enabled);\n setProvider(payload.data.provider ?? '');\n setModel(payload.data.model ?? '');\n }\n }, [payload.data]);\n\n const save = async (): Promise<void> => {\n setBusy(true);\n setError(null);\n setSaved(false);\n try {\n await fetchJson('/api/llm/system-llm', {\n method: 'PUT',\n body: { enabled, provider, model },\n });\n setSaved(true);\n void payload.refetch();\n } catch (err) {\n setError(err instanceof FetchError ? err.message : (err as Error).message);\n } finally {\n setBusy(false);\n }\n };\n\n return (\n <Card variant=\"default\">\n <CardBody>\n <Stack gap={2}>\n <strong style={{ fontSize: 'var(--fs-13)' }}>System LLM</strong>\n {payload.loading && payload.data === null ? (\n <Skeleton style={{ height: 100 }} />\n ) : (\n <Stack gap={2}>\n <label style={{ display: 'flex', alignItems: 'center', gap: 'var(--space-2)' }}>\n <input\n type=\"checkbox\"\n checked={enabled}\n data-testid=\"config-system-llm-enabled\"\n onChange={(e) => setEnabled((e.target as HTMLInputElement).checked)}\n />\n <span style={{ fontSize: 'var(--fs-13)' }}>Enabled</span>\n </label>\n <label style={{ display: 'flex', flexDirection: 'column', gap: 'var(--space-1)' }}>\n <span style={{ fontSize: 'var(--fs-12)', color: 'var(--fg-muted)' }}>Provider</span>\n <Input value={provider} data-testid=\"config-system-llm-provider\" onChange={(e) => setProvider((e.target as HTMLInputElement).value)} />\n </label>\n <label style={{ display: 'flex', flexDirection: 'column', gap: 'var(--space-1)' }}>\n <span style={{ fontSize: 'var(--fs-12)', color: 'var(--fg-muted)' }}>Model</span>\n <Input value={model} data-testid=\"config-system-llm-model\" onChange={(e) => setModel((e.target as HTMLInputElement).value)} />\n </label>\n <Inline justify=\"end\" gap={2}>\n <Button variant=\"primary\" onClick={() => void save()} disabled={busy} data-testid=\"config-system-llm-save\">\n <Save size={14} aria-hidden /> {busy ? 'Saving…' : 'Save'}\n </Button>\n </Inline>\n {saved && <span data-testid=\"config-system-llm-saved\" style={{ color: 'var(--success)', fontSize: 'var(--fs-12)' }}>Saved</span>}\n {error !== null && (\n <span role=\"alert\" data-testid=\"config-system-llm-error\" style={{ color: 'var(--danger)', fontSize: 'var(--fs-12)' }}>{error}</span>\n )}\n </Stack>\n )}\n </Stack>\n </CardBody>\n </Card>\n );\n}"],"names":["SECTIONS","SettingsIcon","Cpu","Plug","ServerCog","ConfigView","section","setSection","useState","jsxs","Stack","jsx","ViewHeader","Inline","s","RuntimeConfigPanel","ProvidersPanel","McpsPanel","SystemLlmPanel","payload","useFetch","draft","setDraft","busy","setBusy","saved","setSaved","error","setError","useEffect","_a","reload","useCallback","save","fetchJson","err","FetchError","Card","CardBody","Button","RefreshCcw","Save","Skeleton","e","adding","setAdding","editing","setEditing","confirmDelete","setConfirmDelete","refresh","providers","useMemo","drop","id","Plus","EmptyState","p","isConfirming","Pencil","cur","Trash2","mcps","m","enabled","setEnabled","provider","setProvider","model","setModel","Input"],"mappings":"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"}
@@ -1,2 +1,2 @@
1
- import{r as w,j as e}from"./cmdk-DVxytz9i.js";import{u as y,S as n,d as S,I as c,A as k,B as z,h as F}from"./main-CyAIirBB.js";import{G as C}from"./Grid-dEnoGGws.js";import{V as b}from"./ViewHeader-V_SzbUpw.js";import{C as i,b as o}from"./Card-D9019JOD.js";import{R as B}from"./refresh-cw-COTg1nZo.js";import{F as R}from"./file-text-CS1jB_oV.js";function $(t){if(!t||t<=0)return"—";const s=Math.floor(t/86400),a=Math.floor(t%86400/3600),l=Math.floor(t%3600/60);return s>0?`${s}d ${a}h`:a>0?`${a}h ${l}m`:`${l}m`}function H(){var g,m,x,u,j,p,v;const t=y("/api/diagnostics"),s=y("/api/diagnostics/logs?tail=200");w.useEffect(()=>{const r=setInterval(()=>{s.refetch()},1e4);return()=>clearInterval(r)},[s]);const a=(g=t.data)==null?void 0:g.health,l=(m=t.data)==null?void 0:m.uptime,h=((x=t.data)==null?void 0:x.checks)??[],d=((u=s.data)==null?void 0:u.lines)??[],f=((j=s.data)==null?void 0:j.file)??null;return e.jsxs(n,{gap:5,"data-testid":"diagnostics-view",children:[e.jsx(b,{title:"Diagnostics",description:"Live system snapshot + active log tail. Auto-refresh every 10s.",actions:e.jsxs(S,{variant:"ghost",onClick:()=>{t.refetch(),s.refetch()},"data-testid":"diagnostics-refresh",children:[e.jsx(B,{size:14,"aria-hidden":!0})," Refresh"]})}),e.jsxs(C,{cols:3,children:[e.jsx(i,{variant:"default",children:e.jsx(o,{children:e.jsxs(n,{gap:1,children:[e.jsx("span",{style:{fontSize:"var(--fs-12)",color:"var(--fg-muted)"},children:"Status"}),e.jsxs(c,{align:"center",gap:2,children:[e.jsx(k,{size:14,"aria-hidden":!0}),e.jsx("strong",{style:{fontFamily:"var(--font-mono)"},children:t.loading?"…":(a==null?void 0:a.status)??"unknown"})]})]})})}),e.jsx(i,{variant:"default",children:e.jsx(o,{children:e.jsxs(n,{gap:1,children:[e.jsx("span",{style:{fontSize:"var(--fs-12)",color:"var(--fg-muted)"},children:"Uptime"}),e.jsx("strong",{style:{fontFamily:"var(--font-mono)"},children:$(l)})]})})}),e.jsx(i,{variant:"default",children:e.jsx(o,{children:e.jsxs(n,{gap:1,children:[e.jsx("span",{style:{fontSize:"var(--fs-12)",color:"var(--fg-muted)"},children:"Version"}),e.jsx("strong",{style:{fontFamily:"var(--font-mono)"},children:((p=t.data)==null?void 0:p.version)??"—"})]})})})]}),h.length>0&&e.jsx(i,{variant:"default",children:e.jsx(o,{children:e.jsxs(n,{gap:2,children:[e.jsxs("strong",{children:["Checks (",h.length,")"]}),e.jsx(c,{gap:1,wrap:!0,children:h.map(r=>e.jsx(z,{tone:r.status==="ok"?"success":r.status==="warn"?"warning":"danger",children:r.name},r.name))})]})})}),e.jsx(i,{variant:"default",children:e.jsx(o,{children:e.jsxs(n,{gap:2,children:[e.jsxs(c,{align:"center",justify:"between",children:[e.jsxs(c,{align:"center",gap:2,children:[e.jsx(R,{size:14,"aria-hidden":!0}),e.jsx("strong",{children:"Log tail"}),f&&e.jsx("code",{style:{fontSize:"var(--fs-12)",color:"var(--fg-muted)",fontFamily:"var(--font-mono)"},children:f})]}),e.jsxs("span",{style:{fontSize:"var(--fs-12)",color:"var(--fg-muted)"},children:[d.length," / ",((v=s.data)==null?void 0:v.total)??0," lines"]})]}),s.loading&&d.length===0?e.jsx(F,{style:{height:240}}):d.length===0?e.jsx("span",{style:{color:"var(--fg-muted)",fontSize:"var(--fs-12)"},children:"No log lines yet."}):e.jsx("pre",{"data-testid":"diagnostics-log-tail",style:{maxHeight:320,overflowY:"auto",padding:"var(--space-3)",background:"var(--surface-1)",borderRadius:"var(--radius-sm)",fontSize:"var(--fs-12)",fontFamily:"var(--font-mono)",margin:0,whiteSpace:"pre-wrap",wordBreak:"break-all"},children:d.join(`
1
+ import{r as w,j as e}from"./cmdk-DVxytz9i.js";import{u as y,S as n,d as S,I as c,A as k,B as z,h as F}from"./main-Cxeu4LhG.js";import{G as C}from"./Grid-BSXhsCPC.js";import{V as b}from"./ViewHeader-B6P-C4GD.js";import{C as i,b as o}from"./Card-rF59wHiO.js";import{R as B}from"./refresh-cw-ENBVR8hW.js";import{F as R}from"./file-text-CQ12t7Oc.js";function $(t){if(!t||t<=0)return"—";const s=Math.floor(t/86400),a=Math.floor(t%86400/3600),l=Math.floor(t%3600/60);return s>0?`${s}d ${a}h`:a>0?`${a}h ${l}m`:`${l}m`}function H(){var g,m,x,u,j,p,v;const t=y("/api/diagnostics"),s=y("/api/diagnostics/logs?tail=200");w.useEffect(()=>{const r=setInterval(()=>{s.refetch()},1e4);return()=>clearInterval(r)},[s]);const a=(g=t.data)==null?void 0:g.health,l=(m=t.data)==null?void 0:m.uptime,h=((x=t.data)==null?void 0:x.checks)??[],d=((u=s.data)==null?void 0:u.lines)??[],f=((j=s.data)==null?void 0:j.file)??null;return e.jsxs(n,{gap:5,"data-testid":"diagnostics-view",children:[e.jsx(b,{title:"Diagnostics",description:"Live system snapshot + active log tail. Auto-refresh every 10s.",actions:e.jsxs(S,{variant:"ghost",onClick:()=>{t.refetch(),s.refetch()},"data-testid":"diagnostics-refresh",children:[e.jsx(B,{size:14,"aria-hidden":!0})," Refresh"]})}),e.jsxs(C,{cols:3,children:[e.jsx(i,{variant:"default",children:e.jsx(o,{children:e.jsxs(n,{gap:1,children:[e.jsx("span",{style:{fontSize:"var(--fs-12)",color:"var(--fg-muted)"},children:"Status"}),e.jsxs(c,{align:"center",gap:2,children:[e.jsx(k,{size:14,"aria-hidden":!0}),e.jsx("strong",{style:{fontFamily:"var(--font-mono)"},children:t.loading?"…":(a==null?void 0:a.status)??"unknown"})]})]})})}),e.jsx(i,{variant:"default",children:e.jsx(o,{children:e.jsxs(n,{gap:1,children:[e.jsx("span",{style:{fontSize:"var(--fs-12)",color:"var(--fg-muted)"},children:"Uptime"}),e.jsx("strong",{style:{fontFamily:"var(--font-mono)"},children:$(l)})]})})}),e.jsx(i,{variant:"default",children:e.jsx(o,{children:e.jsxs(n,{gap:1,children:[e.jsx("span",{style:{fontSize:"var(--fs-12)",color:"var(--fg-muted)"},children:"Version"}),e.jsx("strong",{style:{fontFamily:"var(--font-mono)"},children:((p=t.data)==null?void 0:p.version)??"—"})]})})})]}),h.length>0&&e.jsx(i,{variant:"default",children:e.jsx(o,{children:e.jsxs(n,{gap:2,children:[e.jsxs("strong",{children:["Checks (",h.length,")"]}),e.jsx(c,{gap:1,wrap:!0,children:h.map(r=>e.jsx(z,{tone:r.status==="ok"?"success":r.status==="warn"?"warning":"danger",children:r.name},r.name))})]})})}),e.jsx(i,{variant:"default",children:e.jsx(o,{children:e.jsxs(n,{gap:2,children:[e.jsxs(c,{align:"center",justify:"between",children:[e.jsxs(c,{align:"center",gap:2,children:[e.jsx(R,{size:14,"aria-hidden":!0}),e.jsx("strong",{children:"Log tail"}),f&&e.jsx("code",{style:{fontSize:"var(--fs-12)",color:"var(--fg-muted)",fontFamily:"var(--font-mono)"},children:f})]}),e.jsxs("span",{style:{fontSize:"var(--fs-12)",color:"var(--fg-muted)"},children:[d.length," / ",((v=s.data)==null?void 0:v.total)??0," lines"]})]}),s.loading&&d.length===0?e.jsx(F,{style:{height:240}}):d.length===0?e.jsx("span",{style:{color:"var(--fg-muted)",fontSize:"var(--fs-12)"},children:"No log lines yet."}):e.jsx("pre",{"data-testid":"diagnostics-log-tail",style:{maxHeight:320,overflowY:"auto",padding:"var(--space-3)",background:"var(--surface-1)",borderRadius:"var(--radius-sm)",fontSize:"var(--fs-12)",fontFamily:"var(--font-mono)",margin:0,whiteSpace:"pre-wrap",wordBreak:"break-all"},children:d.join(`
2
2
  `)})]})})})]})}export{H as DiagnosticsView};
@@ -1 +1 @@
1
- {"version":3,"file":"DiagnosticsView-oCT624hk.js","sources":["../../src/web/v8/views/Diagnostics/DiagnosticsView.tsx"],"sourcesContent":["import { useEffect, useState } from 'react';\nimport { Activity, RefreshCw, FileText } from 'lucide-react';\nimport { Stack } from '../../ui/primitives/Stack.js';\nimport { Inline } from '../../ui/primitives/Inline.js';\nimport { Grid } from '../../ui/primitives/Grid.js';\nimport { ViewHeader } from '../../ui/data/ViewHeader.js';\nimport { Card, CardBody } from '../../ui/data/Card.js';\nimport { Badge } from '../../ui/data/Badge.js';\nimport { Button } from '../../ui/controls/Button.js';\nimport { Skeleton } from '../../ui/feedback/Skeleton.js';\nimport { useFetch } from '../../data/useFetch.js';\n\n/**\n * DiagnosticsView — Sprint S35. System snapshot + active log tail.\n */\n\ninterface DiagnosticsHealth {\n status: string;\n checks?: Array<{ name: string; status: string; message?: string }>;\n}\n\ninterface DiagnosticsSnapshot {\n health?: DiagnosticsHealth;\n uptime?: number;\n version?: string;\n memory?: { used?: number; total?: number };\n checks?: Array<{ name: string; status: string; message?: string }>;\n}\n\ninterface LogsResponse {\n lines: string[];\n file: string | null;\n total: number;\n}\n\nfunction fmtUptime(secs: number | undefined): string {\n if (!secs || secs <= 0) return '—';\n const days = Math.floor(secs / 86400);\n const hours = Math.floor((secs % 86400) / 3600);\n const mins = Math.floor((secs % 3600) / 60);\n if (days > 0) return `${days}d ${hours}h`;\n if (hours > 0) return `${hours}h ${mins}m`;\n return `${mins}m`;\n}\n\nexport function DiagnosticsView(): JSX.Element {\n const snap = useFetch<DiagnosticsSnapshot>('/api/diagnostics');\n const logs = useFetch<LogsResponse>('/api/diagnostics/logs?tail=200');\n\n // Auto-refresh logs every 10s while page is open.\n useEffect(() => {\n const id = setInterval(() => { void logs.refetch(); }, 10_000);\n return () => clearInterval(id);\n }, [logs]);\n\n const health = snap.data?.health;\n const uptime = snap.data?.uptime;\n const checks = snap.data?.checks ?? [];\n const lines = logs.data?.lines ?? [];\n const logFile = logs.data?.file ?? null;\n\n return (\n <Stack gap={5} data-testid=\"diagnostics-view\">\n <ViewHeader\n title=\"Diagnostics\"\n description=\"Live system snapshot + active log tail. Auto-refresh every 10s.\"\n actions={\n <Button variant=\"ghost\" onClick={() => { void snap.refetch(); void logs.refetch(); }} data-testid=\"diagnostics-refresh\">\n <RefreshCw size={14} aria-hidden /> Refresh\n </Button>\n }\n />\n\n <Grid cols={3}>\n <Card variant=\"default\">\n <CardBody>\n <Stack gap={1}>\n <span style={{ fontSize: 'var(--fs-12)', color: 'var(--fg-muted)' }}>Status</span>\n <Inline align=\"center\" gap={2}>\n <Activity size={14} aria-hidden />\n <strong style={{ fontFamily: 'var(--font-mono)' }}>{snap.loading ? '…' : health?.status ?? 'unknown'}</strong>\n </Inline>\n </Stack>\n </CardBody>\n </Card>\n <Card variant=\"default\">\n <CardBody>\n <Stack gap={1}>\n <span style={{ fontSize: 'var(--fs-12)', color: 'var(--fg-muted)' }}>Uptime</span>\n <strong style={{ fontFamily: 'var(--font-mono)' }}>{fmtUptime(uptime)}</strong>\n </Stack>\n </CardBody>\n </Card>\n <Card variant=\"default\">\n <CardBody>\n <Stack gap={1}>\n <span style={{ fontSize: 'var(--fs-12)', color: 'var(--fg-muted)' }}>Version</span>\n <strong style={{ fontFamily: 'var(--font-mono)' }}>{snap.data?.version ?? '—'}</strong>\n </Stack>\n </CardBody>\n </Card>\n </Grid>\n\n {checks.length > 0 && (\n <Card variant=\"default\">\n <CardBody>\n <Stack gap={2}>\n <strong>Checks ({checks.length})</strong>\n <Inline gap={1} wrap={true}>\n {checks.map((c) => (\n <Badge key={c.name} tone={c.status === 'ok' ? 'success' : c.status === 'warn' ? 'warning' : 'danger'}>\n {c.name}\n </Badge>\n ))}\n </Inline>\n </Stack>\n </CardBody>\n </Card>\n )}\n\n <Card variant=\"default\">\n <CardBody>\n <Stack gap={2}>\n <Inline align=\"center\" justify=\"between\">\n <Inline align=\"center\" gap={2}>\n <FileText size={14} aria-hidden />\n <strong>Log tail</strong>\n {logFile && <code style={{ fontSize: 'var(--fs-12)', color: 'var(--fg-muted)', fontFamily: 'var(--font-mono)' }}>{logFile}</code>}\n </Inline>\n <span style={{ fontSize: 'var(--fs-12)', color: 'var(--fg-muted)' }}>{lines.length} / {logs.data?.total ?? 0} lines</span>\n </Inline>\n {logs.loading && lines.length === 0 ? (\n <Skeleton style={{ height: 240 }} />\n ) : lines.length === 0 ? (\n <span style={{ color: 'var(--fg-muted)', fontSize: 'var(--fs-12)' }}>No log lines yet.</span>\n ) : (\n <pre\n data-testid=\"diagnostics-log-tail\"\n style={{\n maxHeight: 320,\n overflowY: 'auto',\n padding: 'var(--space-3)',\n background: 'var(--surface-1)',\n borderRadius: 'var(--radius-sm)',\n fontSize: 'var(--fs-12)',\n fontFamily: 'var(--font-mono)',\n margin: 0,\n whiteSpace: 'pre-wrap',\n wordBreak: 'break-all',\n }}\n >\n {lines.join('\\n')}\n </pre>\n )}\n </Stack>\n </CardBody>\n </Card>\n </Stack>\n );\n}"],"names":["fmtUptime","secs","days","hours","mins","DiagnosticsView","snap","useFetch","logs","useEffect","id","health","_a","uptime","_b","checks","_c","lines","_d","logFile","_e","jsxs","Stack","jsx","ViewHeader","Button","RefreshCw","Grid","Card","CardBody","Inline","Activity","_f","c","Badge","FileText","_g","Skeleton"],"mappings":"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"}
1
+ {"version":3,"file":"DiagnosticsView-88OZ5k0f.js","sources":["../../src/web/v8/views/Diagnostics/DiagnosticsView.tsx"],"sourcesContent":["import { useEffect, useState } from 'react';\nimport { Activity, RefreshCw, FileText } from 'lucide-react';\nimport { Stack } from '../../ui/primitives/Stack.js';\nimport { Inline } from '../../ui/primitives/Inline.js';\nimport { Grid } from '../../ui/primitives/Grid.js';\nimport { ViewHeader } from '../../ui/data/ViewHeader.js';\nimport { Card, CardBody } from '../../ui/data/Card.js';\nimport { Badge } from '../../ui/data/Badge.js';\nimport { Button } from '../../ui/controls/Button.js';\nimport { Skeleton } from '../../ui/feedback/Skeleton.js';\nimport { useFetch } from '../../data/useFetch.js';\n\n/**\n * DiagnosticsView — Sprint S35. System snapshot + active log tail.\n */\n\ninterface DiagnosticsHealth {\n status: string;\n checks?: Array<{ name: string; status: string; message?: string }>;\n}\n\ninterface DiagnosticsSnapshot {\n health?: DiagnosticsHealth;\n uptime?: number;\n version?: string;\n memory?: { used?: number; total?: number };\n checks?: Array<{ name: string; status: string; message?: string }>;\n}\n\ninterface LogsResponse {\n lines: string[];\n file: string | null;\n total: number;\n}\n\nfunction fmtUptime(secs: number | undefined): string {\n if (!secs || secs <= 0) return '—';\n const days = Math.floor(secs / 86400);\n const hours = Math.floor((secs % 86400) / 3600);\n const mins = Math.floor((secs % 3600) / 60);\n if (days > 0) return `${days}d ${hours}h`;\n if (hours > 0) return `${hours}h ${mins}m`;\n return `${mins}m`;\n}\n\nexport function DiagnosticsView(): JSX.Element {\n const snap = useFetch<DiagnosticsSnapshot>('/api/diagnostics');\n const logs = useFetch<LogsResponse>('/api/diagnostics/logs?tail=200');\n\n // Auto-refresh logs every 10s while page is open.\n useEffect(() => {\n const id = setInterval(() => { void logs.refetch(); }, 10_000);\n return () => clearInterval(id);\n }, [logs]);\n\n const health = snap.data?.health;\n const uptime = snap.data?.uptime;\n const checks = snap.data?.checks ?? [];\n const lines = logs.data?.lines ?? [];\n const logFile = logs.data?.file ?? null;\n\n return (\n <Stack gap={5} data-testid=\"diagnostics-view\">\n <ViewHeader\n title=\"Diagnostics\"\n description=\"Live system snapshot + active log tail. Auto-refresh every 10s.\"\n actions={\n <Button variant=\"ghost\" onClick={() => { void snap.refetch(); void logs.refetch(); }} data-testid=\"diagnostics-refresh\">\n <RefreshCw size={14} aria-hidden /> Refresh\n </Button>\n }\n />\n\n <Grid cols={3}>\n <Card variant=\"default\">\n <CardBody>\n <Stack gap={1}>\n <span style={{ fontSize: 'var(--fs-12)', color: 'var(--fg-muted)' }}>Status</span>\n <Inline align=\"center\" gap={2}>\n <Activity size={14} aria-hidden />\n <strong style={{ fontFamily: 'var(--font-mono)' }}>{snap.loading ? '…' : health?.status ?? 'unknown'}</strong>\n </Inline>\n </Stack>\n </CardBody>\n </Card>\n <Card variant=\"default\">\n <CardBody>\n <Stack gap={1}>\n <span style={{ fontSize: 'var(--fs-12)', color: 'var(--fg-muted)' }}>Uptime</span>\n <strong style={{ fontFamily: 'var(--font-mono)' }}>{fmtUptime(uptime)}</strong>\n </Stack>\n </CardBody>\n </Card>\n <Card variant=\"default\">\n <CardBody>\n <Stack gap={1}>\n <span style={{ fontSize: 'var(--fs-12)', color: 'var(--fg-muted)' }}>Version</span>\n <strong style={{ fontFamily: 'var(--font-mono)' }}>{snap.data?.version ?? '—'}</strong>\n </Stack>\n </CardBody>\n </Card>\n </Grid>\n\n {checks.length > 0 && (\n <Card variant=\"default\">\n <CardBody>\n <Stack gap={2}>\n <strong>Checks ({checks.length})</strong>\n <Inline gap={1} wrap={true}>\n {checks.map((c) => (\n <Badge key={c.name} tone={c.status === 'ok' ? 'success' : c.status === 'warn' ? 'warning' : 'danger'}>\n {c.name}\n </Badge>\n ))}\n </Inline>\n </Stack>\n </CardBody>\n </Card>\n )}\n\n <Card variant=\"default\">\n <CardBody>\n <Stack gap={2}>\n <Inline align=\"center\" justify=\"between\">\n <Inline align=\"center\" gap={2}>\n <FileText size={14} aria-hidden />\n <strong>Log tail</strong>\n {logFile && <code style={{ fontSize: 'var(--fs-12)', color: 'var(--fg-muted)', fontFamily: 'var(--font-mono)' }}>{logFile}</code>}\n </Inline>\n <span style={{ fontSize: 'var(--fs-12)', color: 'var(--fg-muted)' }}>{lines.length} / {logs.data?.total ?? 0} lines</span>\n </Inline>\n {logs.loading && lines.length === 0 ? (\n <Skeleton style={{ height: 240 }} />\n ) : lines.length === 0 ? (\n <span style={{ color: 'var(--fg-muted)', fontSize: 'var(--fs-12)' }}>No log lines yet.</span>\n ) : (\n <pre\n data-testid=\"diagnostics-log-tail\"\n style={{\n maxHeight: 320,\n overflowY: 'auto',\n padding: 'var(--space-3)',\n background: 'var(--surface-1)',\n borderRadius: 'var(--radius-sm)',\n fontSize: 'var(--fs-12)',\n fontFamily: 'var(--font-mono)',\n margin: 0,\n whiteSpace: 'pre-wrap',\n wordBreak: 'break-all',\n }}\n >\n {lines.join('\\n')}\n </pre>\n )}\n </Stack>\n </CardBody>\n </Card>\n </Stack>\n );\n}"],"names":["fmtUptime","secs","days","hours","mins","DiagnosticsView","snap","useFetch","logs","useEffect","id","health","_a","uptime","_b","checks","_c","lines","_d","logFile","_e","jsxs","Stack","jsx","ViewHeader","Button","RefreshCw","Grid","Card","CardBody","Inline","Activity","_f","c","Badge","FileText","_g","Skeleton"],"mappings":"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"}
@@ -1,4 +1,4 @@
1
- import{r as c,j as e}from"./cmdk-DVxytz9i.js";import{c as k,u as b,a as C,S as h,I as l,d as r,h as m,M as S,l as $,X as w,i as f,F as x}from"./main-CyAIirBB.js";import{V as z}from"./ViewHeader-V_SzbUpw.js";import{L as E}from"./ListHeader-Ak9WJd39.js";import{C as D,b as R}from"./Card-D9019JOD.js";import{E as F}from"./EmptyState-DLmtBX_6.js";import{E as T}from"./ErrorState-Bump8diE.js";import{R as q}from"./refresh-ccw-BCXx86xp.js";import{T as j}from"./trash-2-2NsyTU8c.js";import"./Alert-Dg_Vwxh5.js";import"./circle-alert-CQ9MLygI.js";import"./triangle-alert-DFmQ_RXN.js";import"./circle-check-COtVgsWw.js";/**
1
+ import{r as c,j as e}from"./cmdk-DVxytz9i.js";import{c as k,u as b,a as C,S as h,I as l,d as r,h as m,M as S,l as $,X as w,i as f,F as x}from"./main-Cxeu4LhG.js";import{V as z}from"./ViewHeader-B6P-C4GD.js";import{L as E}from"./ListHeader-Dpun-r36.js";import{C as D,b as R}from"./Card-rF59wHiO.js";import{E as F}from"./EmptyState-D65J5FQN.js";import{E as T}from"./ErrorState-DULZnttJ.js";import{R as q}from"./refresh-ccw-DenGBOcq.js";import{T as j}from"./trash-2-Cv7U38jw.js";import"./Alert-B6DjfRFI.js";import"./circle-alert-HdHe7m8K.js";import"./triangle-alert-tUTXbcEP.js";import"./circle-check-Cs-xoV7R.js";/**
2
2
  * @license lucide-react v0.460.0 - ISC
3
3
  *
4
4
  * This source code is licensed under the ISC license.