@lovelybunch/api 1.0.71-alpha.2 → 1.0.71-alpha.4

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 (235) hide show
  1. package/dist/lib/file-validation.d.ts +65 -0
  2. package/dist/lib/file-validation.js +125 -0
  3. package/dist/middleware/auth.d.ts +1 -0
  4. package/dist/middleware/auth.js +13 -3
  5. package/dist/routes/api/v1/resources/route.js +10 -7
  6. package/package.json +5 -4
  7. package/static/assets/{AgentDetailPage-DwWIjGx1.js → AgentDetailPage-BkWRFbPj.js} +1 -1
  8. package/static/assets/{AgentEditPage-BvVPfYR3.js → AgentEditPage-DN0TouUG.js} +1 -1
  9. package/static/assets/{AgentsPage-D-Uy87Gh.js → AgentsPage-DW6eV7oU.js} +2 -2
  10. package/static/assets/{AgentsSettingsPage-CDuAvFxu.js → AgentsSettingsPage-BJKnn0R0.js} +1 -1
  11. package/static/assets/{ApiKeysSettingsPage-Jug0kB7Z.js → ApiKeysSettingsPage-ChFu9Eo6.js} +1 -1
  12. package/static/assets/{ArchitectureEditPage-BmAgJAMV.js → ArchitectureEditPage-DWrvSS5U.js} +1 -1
  13. package/static/assets/{ArchitecturePage-ZjbdnDA7.js → ArchitecturePage-BdQG779E.js} +1 -1
  14. package/static/assets/{AuthSettingsPage-_pXoewOB.js → AuthSettingsPage-BXMn4xXd.js} +1 -1
  15. package/static/assets/{CallbackPage-CaAOpz4z.js → CallbackPage-AxQqTxCV.js} +1 -1
  16. package/static/assets/{CodePage-DEbgr8C1.js → CodePage-CfKZ52Zo.js} +1 -1
  17. package/static/assets/{CollapsibleSection-msxUBh1L.js → CollapsibleSection-ZFq6LSXW.js} +1 -1
  18. package/static/assets/{DashboardPage-BXu-fikP.js → DashboardPage-Df-d3-fG.js} +1 -1
  19. package/static/assets/{GitPage-B7qFcP-K.js → GitPage-DAWR8rrg.js} +1 -1
  20. package/static/assets/{GitSettingsPage-D7GjdOnE.js → GitSettingsPage-CzGuiY9j.js} +1 -1
  21. package/static/assets/{IdentityPage-BR48gNhN.js → IdentityPage-DbsNwWtP.js} +1 -1
  22. package/static/assets/{ImplementationStepsEditor-BdHMNVVd.js → ImplementationStepsEditor-DZq7KcDP.js} +1 -1
  23. package/static/assets/{IntegrationsSettingsPage-B1OHGlDC.js → IntegrationsSettingsPage-qvvsp1_G.js} +1 -1
  24. package/static/assets/{KnowledgeDetailPage-DBOQQs3R.js → KnowledgeDetailPage-BMnj1qiH.js} +1 -1
  25. package/static/assets/{KnowledgeEditPage-DHJxLPwi.js → KnowledgeEditPage-BZa4E2M9.js} +1 -1
  26. package/static/assets/{KnowledgePage-CuuDTMa_.js → KnowledgePage-Dtq9BKZi.js} +2 -2
  27. package/static/assets/{LoginPage-IIU6NAG9.js → LoginPage-BnlCd8Cm.js} +1 -1
  28. package/static/assets/McpSettingsPage-COPMqimV.js +1 -0
  29. package/static/assets/{NewAgentPage-DolltGy5.js → NewAgentPage-Dtvey1oU.js} +1 -1
  30. package/static/assets/{NewKnowledgePage-_jbUZqBU.js → NewKnowledgePage-CbiRD2V3.js} +1 -1
  31. package/static/assets/{NewProposalPage-bFnfuuoA.js → NewProposalPage-B1tUJIZz.js} +1 -1
  32. package/static/assets/{ProjectEditPage-DTTjPnGj.js → ProjectEditPage-CwM8LXHy.js} +1 -1
  33. package/static/assets/{ProjectPage-DhwrnEq2.js → ProjectPage-BHa8M3vI.js} +1 -1
  34. package/static/assets/{PromptsSettingsPage-DLOVysbE.js → PromptsSettingsPage-CwGmsIAW.js} +1 -1
  35. package/static/assets/{ProposalDetailPage-KvjXUaaf.js → ProposalDetailPage-DC7NMuFi.js} +1 -1
  36. package/static/assets/{ProposalEditPage-BmzkHL9a.js → ProposalEditPage-CfUidv6D.js} +1 -1
  37. package/static/assets/{ProposalsPage-DwQr1ycd.js → ProposalsPage-V8ut_TsU.js} +1 -1
  38. package/static/assets/ResourcesPage-Cofgbx3H.js +66 -0
  39. package/static/assets/{RulesSettingsPage-CsGXFTFY.js → RulesSettingsPage-BJ72X2Y3.js} +1 -1
  40. package/static/assets/{SchedulePage-CY8GdQlp.js → SchedulePage-DBYxTZMb.js} +1 -1
  41. package/static/assets/{TagInput-CbH9zq5n.js → TagInput-Cqju3cXZ.js} +1 -1
  42. package/static/assets/{TerminalPage-DsjOLnyY.js → TerminalPage-Iow1ciWG.js} +1 -1
  43. package/static/assets/{TerminalSessionPage-DQ065WYU.js → TerminalSessionPage-CZdzhFhY.js} +1 -1
  44. package/static/assets/{UserPreferencesPage-55VTrzfQ.js → UserPreferencesPage-CAuJ7yO4.js} +1 -1
  45. package/static/assets/{UserSettingsPage-BZwb93B4.js → UserSettingsPage-0j7ha-RI.js} +1 -1
  46. package/static/assets/{UtilitiesPage-BmEW7eJ_.js → UtilitiesPage-OgkcmaOS.js} +1 -1
  47. package/static/assets/{alert-CNSGDe1U.js → alert-D2VTq6m-.js} +1 -1
  48. package/static/assets/{arrow-down-D1dapxzl.js → arrow-down-vmWOjyjO.js} +1 -1
  49. package/static/assets/{arrow-left-CEZFPQje.js → arrow-left-Do2jUSS9.js} +1 -1
  50. package/static/assets/{arrow-up-D-lB4Ah6.js → arrow-up-hMM1cdZm.js} +1 -1
  51. package/static/assets/{badge-DO6e5hC1.js → badge-D7ZZbMEG.js} +1 -1
  52. package/static/assets/browser-modal-CWDhylx7.js +6 -0
  53. package/static/assets/{calendar-DWaFMSXH.js → calendar-C5JtKp_F.js} +1 -1
  54. package/static/assets/{card-Cnz8b7Ou.js → card-D_zGBKua.js} +1 -1
  55. package/static/assets/{chevron-left-CNgc28Tc.js → chevron-left-JjvWea8A.js} +1 -1
  56. package/static/assets/{circle-alert-Dick-jNf.js → circle-alert-DQD0CPB3.js} +1 -1
  57. package/static/assets/{circle-check-big-B70gdce7.js → circle-check-big-KfJvKA9H.js} +1 -1
  58. package/static/assets/{circle-check-DDk43rYV.js → circle-check-xj41FKuF.js} +1 -1
  59. package/static/assets/{circle-play-TJEfmKde.js → circle-play-BlGnYWUU.js} +1 -1
  60. package/static/assets/{circle-x-BfR2YcXx.js → circle-x-Ds97aY1x.js} +1 -1
  61. package/static/assets/{clipboard-BTZru8wn.js → clipboard-D3NA8gb4.js} +1 -1
  62. package/static/assets/{clock-DQXbrDkQ.js → clock-9dU_D6sL.js} +1 -1
  63. package/static/assets/{download-CW_rWwud.js → download-CNckZYWh.js} +1 -1
  64. package/static/assets/{eye-Bv6mO2ld.js → eye-Dp6wEoME.js} +1 -1
  65. package/static/assets/{folder-git-2-Cv5NbBZZ.js → folder-git-2-B9ILjFN2.js} +1 -1
  66. package/static/assets/{index-BSBM4i_g.js → index-Bbxvuj4b.js} +3 -3
  67. package/static/assets/index-Ca98xZVe.css +2 -0
  68. package/static/assets/{label-vEgNxdb2.js → label-CZGCmBD7.js} +1 -1
  69. package/static/assets/{markdown-editor-O6tGYa1a.js → markdown-editor-BiM9h5iI.js} +1 -1
  70. package/static/assets/{pause-6aQLhmG9.js → pause-BNL49HvB.js} +1 -1
  71. package/static/assets/{play-DsDsjO2V.js → play-8b83f5X0.js} +1 -1
  72. package/static/assets/{plus-BfBtnncn.js → plus-Be79gWKj.js} +1 -1
  73. package/static/assets/{radio-group-D_RD_9vY.js → radio-group-DpxssBzw.js} +1 -1
  74. package/static/assets/{refresh-cw-DvFNtws1.js → refresh-cw-C0_Ot2Zc.js} +1 -1
  75. package/static/assets/registry-ANRa5WBi.js +1 -0
  76. package/static/assets/{search-kcgmZUqQ.js → search-CrIdR7ah.js} +1 -1
  77. package/static/assets/{switch-Bjq8cgQn.js → switch-BYPAX9oF.js} +1 -1
  78. package/static/assets/{tabs-DDbBXbPg.js → tabs-Ug7Ug5Ha.js} +1 -1
  79. package/static/assets/{tag-Czz-3rNY.js → tag-BgO5mxYK.js} +1 -1
  80. package/static/assets/{terminal-preview-B7iP2vUT.js → terminal-preview-CDrLQbSE.js} +1 -1
  81. package/static/assets/{use-terminal-CN3pheMp.js → use-terminal-CNk4WtA6.js} +1 -1
  82. package/static/assets/{zap-BMkP_c9R.js → zap-cD8GAJPg.js} +1 -1
  83. package/static/index.html +2 -2
  84. package/dist/lib/auth/auth-manager.d.ts.map +0 -1
  85. package/dist/lib/auth/auth-manager.js.map +0 -1
  86. package/dist/lib/gait-path.d.ts.map +0 -1
  87. package/dist/lib/gait-path.js.map +0 -1
  88. package/dist/lib/git-settings.d.ts.map +0 -1
  89. package/dist/lib/git-settings.js.map +0 -1
  90. package/dist/lib/git.d.ts.map +0 -1
  91. package/dist/lib/git.js.map +0 -1
  92. package/dist/lib/jobs/global-job-scheduler.d.ts.map +0 -1
  93. package/dist/lib/jobs/global-job-scheduler.js.map +0 -1
  94. package/dist/lib/jobs/job-runner.d.ts.map +0 -1
  95. package/dist/lib/jobs/job-runner.js.map +0 -1
  96. package/dist/lib/jobs/job-scheduler.d.ts.map +0 -1
  97. package/dist/lib/jobs/job-scheduler.js.map +0 -1
  98. package/dist/lib/jobs/job-store.d.ts.map +0 -1
  99. package/dist/lib/jobs/job-store.js.map +0 -1
  100. package/dist/lib/project-paths.d.ts.map +0 -1
  101. package/dist/lib/project-paths.js.map +0 -1
  102. package/dist/lib/storage/file-storage.d.ts.map +0 -1
  103. package/dist/lib/storage/file-storage.js.map +0 -1
  104. package/dist/lib/symlinks/symlink-manager.d.ts.map +0 -1
  105. package/dist/lib/symlinks/symlink-manager.js.map +0 -1
  106. package/dist/lib/symlinks/types.d.ts.map +0 -1
  107. package/dist/lib/symlinks/types.js.map +0 -1
  108. package/dist/lib/terminal/context-helper.d.ts.map +0 -1
  109. package/dist/lib/terminal/context-helper.js.map +0 -1
  110. package/dist/lib/terminal/global-manager.d.ts.map +0 -1
  111. package/dist/lib/terminal/global-manager.js.map +0 -1
  112. package/dist/lib/terminal/shell-utils.d.ts.map +0 -1
  113. package/dist/lib/terminal/shell-utils.js.map +0 -1
  114. package/dist/lib/terminal/terminal-manager.d.ts.map +0 -1
  115. package/dist/lib/terminal/terminal-manager.js.map +0 -1
  116. package/dist/lib/user-preferences.d.ts.map +0 -1
  117. package/dist/lib/user-preferences.js.map +0 -1
  118. package/dist/middleware/auth.d.ts.map +0 -1
  119. package/dist/middleware/auth.js.map +0 -1
  120. package/dist/routes/api/v1/agents/[id]/index.d.ts.map +0 -1
  121. package/dist/routes/api/v1/agents/[id]/index.js.map +0 -1
  122. package/dist/routes/api/v1/agents/[id]/route.d.ts.map +0 -1
  123. package/dist/routes/api/v1/agents/[id]/route.js.map +0 -1
  124. package/dist/routes/api/v1/agents/index.d.ts.map +0 -1
  125. package/dist/routes/api/v1/agents/index.js.map +0 -1
  126. package/dist/routes/api/v1/agents/route.d.ts.map +0 -1
  127. package/dist/routes/api/v1/agents/route.js.map +0 -1
  128. package/dist/routes/api/v1/ai/index.d.ts.map +0 -1
  129. package/dist/routes/api/v1/ai/index.js.map +0 -1
  130. package/dist/routes/api/v1/ai/route.d.ts.map +0 -1
  131. package/dist/routes/api/v1/ai/route.js.map +0 -1
  132. package/dist/routes/api/v1/api-keys/index.d.ts.map +0 -1
  133. package/dist/routes/api/v1/api-keys/index.js.map +0 -1
  134. package/dist/routes/api/v1/api-keys/route.d.ts.map +0 -1
  135. package/dist/routes/api/v1/api-keys/route.js.map +0 -1
  136. package/dist/routes/api/v1/auth/index.d.ts.map +0 -1
  137. package/dist/routes/api/v1/auth/index.js.map +0 -1
  138. package/dist/routes/api/v1/auth/route.d.ts.map +0 -1
  139. package/dist/routes/api/v1/auth/route.js.map +0 -1
  140. package/dist/routes/api/v1/auth-settings/index.d.ts.map +0 -1
  141. package/dist/routes/api/v1/auth-settings/index.js.map +0 -1
  142. package/dist/routes/api/v1/auth-settings/route.d.ts.map +0 -1
  143. package/dist/routes/api/v1/auth-settings/route.js.map +0 -1
  144. package/dist/routes/api/v1/chats/[id]/index.d.ts.map +0 -1
  145. package/dist/routes/api/v1/chats/[id]/index.js.map +0 -1
  146. package/dist/routes/api/v1/chats/[id]/route.d.ts.map +0 -1
  147. package/dist/routes/api/v1/chats/[id]/route.js.map +0 -1
  148. package/dist/routes/api/v1/chats/index.d.ts.map +0 -1
  149. package/dist/routes/api/v1/chats/index.js.map +0 -1
  150. package/dist/routes/api/v1/chats/route.d.ts.map +0 -1
  151. package/dist/routes/api/v1/chats/route.js.map +0 -1
  152. package/dist/routes/api/v1/config/index.d.ts.map +0 -1
  153. package/dist/routes/api/v1/config/index.js.map +0 -1
  154. package/dist/routes/api/v1/config/route.d.ts.map +0 -1
  155. package/dist/routes/api/v1/config/route.js.map +0 -1
  156. package/dist/routes/api/v1/context/architecture/route.d.ts.map +0 -1
  157. package/dist/routes/api/v1/context/architecture/route.js.map +0 -1
  158. package/dist/routes/api/v1/context/index.d.ts.map +0 -1
  159. package/dist/routes/api/v1/context/index.js.map +0 -1
  160. package/dist/routes/api/v1/context/knowledge/[filename]/index.d.ts.map +0 -1
  161. package/dist/routes/api/v1/context/knowledge/[filename]/index.js.map +0 -1
  162. package/dist/routes/api/v1/context/knowledge/[filename]/route.d.ts.map +0 -1
  163. package/dist/routes/api/v1/context/knowledge/[filename]/route.js.map +0 -1
  164. package/dist/routes/api/v1/context/knowledge/index.d.ts.map +0 -1
  165. package/dist/routes/api/v1/context/knowledge/index.js.map +0 -1
  166. package/dist/routes/api/v1/context/knowledge/route.d.ts.map +0 -1
  167. package/dist/routes/api/v1/context/knowledge/route.js.map +0 -1
  168. package/dist/routes/api/v1/context/project/route.d.ts.map +0 -1
  169. package/dist/routes/api/v1/context/project/route.js.map +0 -1
  170. package/dist/routes/api/v1/git/index.d.ts.map +0 -1
  171. package/dist/routes/api/v1/git/index.js.map +0 -1
  172. package/dist/routes/api/v1/jobs/[id]/route.d.ts.map +0 -1
  173. package/dist/routes/api/v1/jobs/[id]/route.js.map +0 -1
  174. package/dist/routes/api/v1/jobs/[id]/run/route.d.ts.map +0 -1
  175. package/dist/routes/api/v1/jobs/[id]/run/route.js.map +0 -1
  176. package/dist/routes/api/v1/jobs/index.d.ts.map +0 -1
  177. package/dist/routes/api/v1/jobs/index.js.map +0 -1
  178. package/dist/routes/api/v1/jobs/route.d.ts.map +0 -1
  179. package/dist/routes/api/v1/jobs/route.js.map +0 -1
  180. package/dist/routes/api/v1/jobs/status/route.d.ts.map +0 -1
  181. package/dist/routes/api/v1/jobs/status/route.js.map +0 -1
  182. package/dist/routes/api/v1/mcp/index.d.ts.map +0 -1
  183. package/dist/routes/api/v1/mcp/index.js.map +0 -1
  184. package/dist/routes/api/v1/mcp/route.d.ts.map +0 -1
  185. package/dist/routes/api/v1/mcp/route.js.map +0 -1
  186. package/dist/routes/api/v1/proposals/[id]/route.d.ts.map +0 -1
  187. package/dist/routes/api/v1/proposals/[id]/route.js.map +0 -1
  188. package/dist/routes/api/v1/proposals/index.d.ts.map +0 -1
  189. package/dist/routes/api/v1/proposals/index.js.map +0 -1
  190. package/dist/routes/api/v1/proposals/route.d.ts.map +0 -1
  191. package/dist/routes/api/v1/proposals/route.js.map +0 -1
  192. package/dist/routes/api/v1/resources/[id]/index.d.ts.map +0 -1
  193. package/dist/routes/api/v1/resources/[id]/index.js.map +0 -1
  194. package/dist/routes/api/v1/resources/[id]/route.js.map +0 -1
  195. package/dist/routes/api/v1/resources/[id]/thumbnail/index.d.ts.map +0 -1
  196. package/dist/routes/api/v1/resources/[id]/thumbnail/index.js.map +0 -1
  197. package/dist/routes/api/v1/resources/[id]/thumbnail/route.js.map +0 -1
  198. package/dist/routes/api/v1/resources/index.d.ts.map +0 -1
  199. package/dist/routes/api/v1/resources/index.js.map +0 -1
  200. package/dist/routes/api/v1/resources/route.d.ts.map +0 -1
  201. package/dist/routes/api/v1/resources/route.js.map +0 -1
  202. package/dist/routes/api/v1/symlinks/index.d.ts.map +0 -1
  203. package/dist/routes/api/v1/symlinks/index.js.map +0 -1
  204. package/dist/routes/api/v1/symlinks/route.d.ts.map +0 -1
  205. package/dist/routes/api/v1/symlinks/route.js.map +0 -1
  206. package/dist/routes/api/v1/terminal/[proposalId]/create/index.d.ts.map +0 -1
  207. package/dist/routes/api/v1/terminal/[proposalId]/create/index.js.map +0 -1
  208. package/dist/routes/api/v1/terminal/[proposalId]/create/route.d.ts.map +0 -1
  209. package/dist/routes/api/v1/terminal/[proposalId]/create/route.js.map +0 -1
  210. package/dist/routes/api/v1/terminal/[proposalId]/destroy/index.d.ts.map +0 -1
  211. package/dist/routes/api/v1/terminal/[proposalId]/destroy/index.js.map +0 -1
  212. package/dist/routes/api/v1/terminal/[proposalId]/destroy/route.d.ts.map +0 -1
  213. package/dist/routes/api/v1/terminal/[proposalId]/destroy/route.js.map +0 -1
  214. package/dist/routes/api/v1/terminal/[proposalId]/resize/index.d.ts.map +0 -1
  215. package/dist/routes/api/v1/terminal/[proposalId]/resize/index.js.map +0 -1
  216. package/dist/routes/api/v1/terminal/[proposalId]/resize/route.d.ts.map +0 -1
  217. package/dist/routes/api/v1/terminal/[proposalId]/resize/route.js.map +0 -1
  218. package/dist/routes/api/v1/terminal/sessions/index.d.ts.map +0 -1
  219. package/dist/routes/api/v1/terminal/sessions/index.js.map +0 -1
  220. package/dist/routes/api/v1/terminal/sessions/route.d.ts.map +0 -1
  221. package/dist/routes/api/v1/terminal/sessions/route.js.map +0 -1
  222. package/dist/routes/api/v1/user/index.d.ts.map +0 -1
  223. package/dist/routes/api/v1/user/index.js.map +0 -1
  224. package/dist/routes/api/v1/user/settings/index.d.ts.map +0 -1
  225. package/dist/routes/api/v1/user/settings/index.js.map +0 -1
  226. package/dist/routes/api/v1/user/settings/route.d.ts.map +0 -1
  227. package/dist/routes/api/v1/user/settings/route.js.map +0 -1
  228. package/dist/server-with-static.d.ts.map +0 -1
  229. package/dist/server-with-static.js.map +0 -1
  230. package/dist/server.d.ts.map +0 -1
  231. package/dist/server.js.map +0 -1
  232. package/static/assets/McpSettingsPage-iz5gLGWt.js +0 -1
  233. package/static/assets/ResourcesPage-B8Hm_j47.js +0 -66
  234. package/static/assets/browser-modal-BTxVvZIA.js +0 -6
  235. package/static/assets/index-CKwmN6yL.css +0 -2
@@ -0,0 +1,65 @@
1
+ /**
2
+ * File validation and sanitization utilities
3
+ * Use these functions to prevent path traversal attacks
4
+ */
5
+ /**
6
+ * Sanitize a filename to prevent path traversal attacks
7
+ * Removes path separators and parent directory references
8
+ * Only allows safe characters
9
+ *
10
+ * @param filename - The filename to sanitize
11
+ * @param allowDots - Whether to allow dots in filenames (default: true)
12
+ * @returns Sanitized filename
13
+ * @throws Error if filename contains invalid characters
14
+ */
15
+ export declare function sanitizeFilename(filename: string, allowDots?: boolean): string;
16
+ /**
17
+ * Validate that a file path doesn't escape its base directory
18
+ *
19
+ * @param basePath - The base directory path
20
+ * @param filePath - The file path to validate
21
+ * @returns The resolved safe path
22
+ * @throws Error if path tries to escape base directory
23
+ */
24
+ export declare function validateSafePath(basePath: string, filePath: string): string;
25
+ /**
26
+ * Validate file extension against allowed list
27
+ *
28
+ * @param filename - The filename to check
29
+ * @param allowedExtensions - Array of allowed extensions (with or without dots)
30
+ * @returns The validated extension
31
+ * @throws Error if extension not allowed
32
+ */
33
+ export declare function validateFileExtension(filename: string, allowedExtensions: string[]): string;
34
+ /**
35
+ * Validate file size
36
+ *
37
+ * @param size - File size in bytes
38
+ * @param maxSize - Maximum allowed size in bytes
39
+ * @throws Error if file is too large
40
+ */
41
+ export declare function validateFileSize(size: number, maxSize: number): void;
42
+ /**
43
+ * Validate MIME type
44
+ *
45
+ * @param mimeType - The MIME type to validate
46
+ * @param allowedTypes - Array of allowed MIME types
47
+ * @throws Error if MIME type not allowed
48
+ */
49
+ export declare function validateMimeType(mimeType: string, allowedTypes: string[]): void;
50
+ /**
51
+ * Comprehensive file validation for uploads
52
+ *
53
+ * @param file - File object with name, size, and type
54
+ * @param options - Validation options
55
+ */
56
+ export interface FileValidationOptions {
57
+ maxSize?: number;
58
+ allowedExtensions?: string[];
59
+ allowedMimeTypes?: string[];
60
+ }
61
+ export declare function validateUploadedFile(file: {
62
+ name: string;
63
+ size: number;
64
+ type: string;
65
+ }, options?: FileValidationOptions): void;
@@ -0,0 +1,125 @@
1
+ /**
2
+ * File validation and sanitization utilities
3
+ * Use these functions to prevent path traversal attacks
4
+ */
5
+ /**
6
+ * Sanitize a filename to prevent path traversal attacks
7
+ * Removes path separators and parent directory references
8
+ * Only allows safe characters
9
+ *
10
+ * @param filename - The filename to sanitize
11
+ * @param allowDots - Whether to allow dots in filenames (default: true)
12
+ * @returns Sanitized filename
13
+ * @throws Error if filename contains invalid characters
14
+ */
15
+ export function sanitizeFilename(filename, allowDots = true) {
16
+ if (!filename || typeof filename !== 'string') {
17
+ throw new Error('Filename must be a non-empty string');
18
+ }
19
+ // Remove any null bytes
20
+ if (filename.includes('\0')) {
21
+ throw new Error('Filename contains null bytes');
22
+ }
23
+ // Remove path separators and parent directory references
24
+ let sanitized = filename
25
+ .replace(/[\/\\]/g, '') // Remove path separators
26
+ .replace(/\.\./g, ''); // Remove parent directory references
27
+ // Remove leading/trailing dots and spaces
28
+ sanitized = sanitized.replace(/^[\s.]+|[\s.]+$/g, '');
29
+ // Check for valid characters
30
+ const pattern = allowDots
31
+ ? /^[a-zA-Z0-9._-]+$/
32
+ : /^[a-zA-Z0-9_-]+$/;
33
+ if (!pattern.test(sanitized)) {
34
+ throw new Error('Filename contains invalid characters. Only alphanumeric, dots, hyphens, and underscores are allowed');
35
+ }
36
+ // Prevent reserved names (Windows)
37
+ const reservedNames = ['CON', 'PRN', 'AUX', 'NUL', 'COM1', 'COM2', 'COM3', 'COM4',
38
+ 'COM5', 'COM6', 'COM7', 'COM8', 'COM9', 'LPT1', 'LPT2',
39
+ 'LPT3', 'LPT4', 'LPT5', 'LPT6', 'LPT7', 'LPT8', 'LPT9'];
40
+ const nameWithoutExt = sanitized.split('.')[0].toUpperCase();
41
+ if (reservedNames.includes(nameWithoutExt)) {
42
+ throw new Error('Filename uses a reserved system name');
43
+ }
44
+ // Enforce maximum length
45
+ if (sanitized.length > 255) {
46
+ throw new Error('Filename is too long (max 255 characters)');
47
+ }
48
+ if (sanitized.length === 0) {
49
+ throw new Error('Filename is empty after sanitization');
50
+ }
51
+ return sanitized;
52
+ }
53
+ /**
54
+ * Validate that a file path doesn't escape its base directory
55
+ *
56
+ * @param basePath - The base directory path
57
+ * @param filePath - The file path to validate
58
+ * @returns The resolved safe path
59
+ * @throws Error if path tries to escape base directory
60
+ */
61
+ export function validateSafePath(basePath, filePath) {
62
+ const path = require('path');
63
+ const resolvedBase = path.resolve(basePath);
64
+ const resolvedPath = path.resolve(basePath, filePath);
65
+ // Check if the resolved path starts with the base path
66
+ if (!resolvedPath.startsWith(resolvedBase + path.sep) && resolvedPath !== resolvedBase) {
67
+ throw new Error('Path traversal detected: file path escapes base directory');
68
+ }
69
+ return resolvedPath;
70
+ }
71
+ /**
72
+ * Validate file extension against allowed list
73
+ *
74
+ * @param filename - The filename to check
75
+ * @param allowedExtensions - Array of allowed extensions (with or without dots)
76
+ * @returns The validated extension
77
+ * @throws Error if extension not allowed
78
+ */
79
+ export function validateFileExtension(filename, allowedExtensions) {
80
+ const path = require('path');
81
+ const ext = path.extname(filename).toLowerCase();
82
+ const normalizedAllowed = allowedExtensions.map(e => e.startsWith('.') ? e.toLowerCase() : '.' + e.toLowerCase());
83
+ if (!normalizedAllowed.includes(ext)) {
84
+ throw new Error(`File extension "${ext}" not allowed. Allowed: ${normalizedAllowed.join(', ')}`);
85
+ }
86
+ return ext;
87
+ }
88
+ /**
89
+ * Validate file size
90
+ *
91
+ * @param size - File size in bytes
92
+ * @param maxSize - Maximum allowed size in bytes
93
+ * @throws Error if file is too large
94
+ */
95
+ export function validateFileSize(size, maxSize) {
96
+ if (size > maxSize) {
97
+ const sizeMB = (size / 1024 / 1024).toFixed(2);
98
+ const maxMB = (maxSize / 1024 / 1024).toFixed(2);
99
+ throw new Error(`File size (${sizeMB}MB) exceeds maximum allowed size (${maxMB}MB)`);
100
+ }
101
+ }
102
+ /**
103
+ * Validate MIME type
104
+ *
105
+ * @param mimeType - The MIME type to validate
106
+ * @param allowedTypes - Array of allowed MIME types
107
+ * @throws Error if MIME type not allowed
108
+ */
109
+ export function validateMimeType(mimeType, allowedTypes) {
110
+ if (!allowedTypes.includes(mimeType)) {
111
+ throw new Error(`MIME type "${mimeType}" not allowed. Allowed: ${allowedTypes.join(', ')}`);
112
+ }
113
+ }
114
+ export function validateUploadedFile(file, options = {}) {
115
+ const { maxSize = 50 * 1024 * 1024, // 50MB default
116
+ allowedExtensions = ['.jpg', '.jpeg', '.png', '.gif', '.pdf', '.txt', '.md'], allowedMimeTypes = ['image/jpeg', 'image/png', 'image/gif', 'application/pdf', 'text/plain', 'text/markdown'] } = options;
117
+ // Validate filename
118
+ sanitizeFilename(file.name);
119
+ // Validate extension
120
+ validateFileExtension(file.name, allowedExtensions);
121
+ // Validate size
122
+ validateFileSize(file.size, maxSize);
123
+ // Validate MIME type
124
+ validateMimeType(file.type, allowedMimeTypes);
125
+ }
@@ -22,6 +22,7 @@ export declare function isAdmin(c: Context): boolean;
22
22
  /**
23
23
  * Helper to require authentication (throws if not authenticated)
24
24
  * Returns null if auth is disabled
25
+ * Also accepts API key authentication
25
26
  */
26
27
  export declare function requireAuth(c: Context): AuthSession | null;
27
28
  /**
@@ -108,6 +108,7 @@ export function isAdmin(c) {
108
108
  /**
109
109
  * Helper to require authentication (throws if not authenticated)
110
110
  * Returns null if auth is disabled
111
+ * Also accepts API key authentication
111
112
  */
112
113
  export function requireAuth(c) {
113
114
  const authEnabled = c.get('authEnabled');
@@ -115,11 +116,20 @@ export function requireAuth(c) {
115
116
  if (authEnabled === false) {
116
117
  return null;
117
118
  }
119
+ // Check for session auth (cookie or Bearer token)
118
120
  const session = getSession(c);
119
- if (!session) {
120
- throw new Error('Authentication required');
121
+ if (session) {
122
+ return session;
121
123
  }
122
- return session;
124
+ // Check for API key auth
125
+ const authType = c.get('authType');
126
+ const apiKey = c.get('apiKey');
127
+ if (authType === 'apikey' && apiKey) {
128
+ // API key is valid, authentication successful
129
+ // Return null to indicate auth passed but no session available
130
+ return null;
131
+ }
132
+ throw new Error('Authentication required');
123
133
  }
124
134
  /**
125
135
  * Helper to require admin access (throws if not admin)
@@ -1,5 +1,6 @@
1
1
  import { promises as fs } from 'fs';
2
2
  import path from 'path';
3
+ import sharp from 'sharp';
3
4
  import { getLogger, ResourceKinds } from '@lovelybunch/core/logging';
4
5
  import { requireAuth } from '../../../../middleware/auth.js';
5
6
  // Generate a random ID
@@ -65,19 +66,21 @@ async function listAllResources() {
65
66
  }
66
67
  }
67
68
  async function generateThumbnail(imageBuffer, id, mimeType) {
68
- // For now, we'll create a simple placeholder thumbnail
69
- // In a production environment, you'd use a library like Sharp for proper image processing
70
69
  const thumbnailName = `${id}_thumb.jpg`;
71
70
  const thumbnailPath = path.join(THUMBNAILS_DIR, thumbnailName);
72
71
  try {
73
- // This is a placeholder - in production, use Sharp or similar
74
- // For now, we'll just copy the original image as the thumbnail
75
- await fs.writeFile(thumbnailPath, imageBuffer);
72
+ // Resize to max 300x300 (2x retina for 128px UI display), preserve aspect ratio
73
+ await sharp(imageBuffer)
74
+ .resize(300, 300, { fit: 'inside', withoutEnlargement: true })
75
+ .jpeg({ quality: 80 })
76
+ .toFile(thumbnailPath);
76
77
  return thumbnailName;
77
78
  }
78
79
  catch (error) {
79
- console.error('Failed to generate thumbnail:', error);
80
- throw error;
80
+ console.error('Failed to generate thumbnail with Sharp:', error);
81
+ // Fallback: save original as thumbnail if Sharp fails
82
+ await fs.writeFile(thumbnailPath, imageBuffer);
83
+ return thumbnailName;
81
84
  }
82
85
  }
83
86
  export async function GET(c) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lovelybunch/api",
3
- "version": "1.0.71-alpha.2",
3
+ "version": "1.0.71-alpha.4",
4
4
  "type": "module",
5
5
  "main": "dist/server-with-static.js",
6
6
  "exports": {
@@ -36,9 +36,9 @@
36
36
  "dependencies": {
37
37
  "@hono/node-server": "^1.13.7",
38
38
  "@hono/node-ws": "^1.0.6",
39
- "@lovelybunch/core": "^1.0.71-alpha.2",
40
- "@lovelybunch/mcp": "^1.0.71-alpha.2",
41
- "@lovelybunch/types": "^1.0.71-alpha.2",
39
+ "@lovelybunch/core": "^1.0.71-alpha.4",
40
+ "@lovelybunch/mcp": "^1.0.71-alpha.4",
41
+ "@lovelybunch/types": "^1.0.71-alpha.4",
42
42
  "arctic": "^1.9.2",
43
43
  "bcrypt": "^5.1.1",
44
44
  "cookie": "^0.6.0",
@@ -49,6 +49,7 @@
49
49
  "jsonwebtoken": "^9.0.2",
50
50
  "node-pty": "^1.0.0",
51
51
  "replicate": "^0.34.1",
52
+ "sharp": "^0.33.5",
52
53
  "ws": "^8.18.0"
53
54
  },
54
55
  "devDependencies": {
@@ -1 +1 @@
1
- import{E as C,u as E,r as h,j as e,B as i,L as d,J as k,T as B,i as T,A as N}from"./index-BSBM4i_g.js";import{C as l,b as o,a as m,c as f,d as z}from"./card-Cnz8b7Ou.js";import{B as v}from"./badge-DO6e5hC1.js";import{A as u}from"./arrow-left-CEZFPQje.js";const D=t=>t?Array.isArray(t)?t.filter(r=>typeof r=="string").map(r=>r.trim()).filter(Boolean):typeof t=="string"?t.split(",").map(r=>r.trim()).filter(Boolean):[]:[],c={blue:{bg:"#dbeafe",border:"#2563eb",text:"#1e40af"},green:{bg:"#dcfce7",border:"#16a34a",text:"#166534"},red:{bg:"#fee2e2",border:"#dc2626",text:"#991b1b"},emerald:{bg:"#d1fae5",border:"#10b981",text:"#047857"},purple:{bg:"#f3e8ff",border:"#9333ea",text:"#6b21a8"},orange:{bg:"#fed7aa",border:"#ea580c",text:"#9a3412"},yellow:{bg:"#fef9c3",border:"#eab308",text:"#854d0e"},teal:{bg:"#ccfbf1",border:"#14b8a6",text:"#0f766e"},indigo:{bg:"#e0e7ff",border:"#6366f1",text:"#4338ca"},pink:{bg:"#fce7f3",border:"#ec4899",text:"#9f1239"},cyan:{bg:"#cffafe",border:"#06b6d4",text:"#155e75"},slate:{bg:"#f1f5f9",border:"#475569",text:"#334155"},gray:{bg:"#f3f4f6",border:"#6b7280",text:"#374151"}};function F(){const t=C(),r=E(),[s,y]=h.useState(null),[w,j]=h.useState(!0),[p,x]=h.useState(null);h.useEffect(()=>{async function a(){try{j(!0);const g=await(await fetch(`${N}/api/v1/agents/${t.id}`)).json();g.success?y(g.document):x(g.error||"Failed to fetch agent")}catch(n){x(n instanceof Error?n.message:"Unknown error")}finally{j(!1)}}t.id&&a()},[t.id]);const A=async()=>{if(!(!s||!confirm("Are you sure you want to delete this agent?")))try{const n=await(await fetch(`${N}/api/v1/agents/${s.filename.replace(".md","")}`,{method:"DELETE"})).json();n.success?r("/agents"):x(n.error?.message||"Failed to delete agent")}catch(a){x(a instanceof Error?a.message:"Unknown error")}};if(w)return e.jsxs("div",{className:"space-y-6",children:[e.jsxs("div",{className:"flex items-center justify-between",children:[e.jsxs("div",{className:"flex-1",children:[e.jsx("div",{className:"h-8 bg-muted rounded w-64 animate-pulse"}),e.jsx("div",{className:"h-4 bg-muted rounded w-32 animate-pulse mt-2"})]}),e.jsx("div",{className:"flex items-center gap-2",children:e.jsx(i,{variant:"ghost",size:"sm",asChild:!0,className:"px-2 hover:bg-transparent",children:e.jsx(d,{to:"/agents",className:"flex items-center text-muted-foreground hover:text-foreground transition-colors",children:e.jsx(u,{className:"h-4 w-4"})})})})]}),e.jsx(l,{children:e.jsxs(o,{children:[e.jsx("div",{className:"h-6 bg-muted rounded w-48 animate-pulse"}),e.jsx("div",{className:"h-4 bg-muted rounded w-64 animate-pulse"})]})})]});if(p||!s)return e.jsxs("div",{className:"space-y-6",children:[e.jsxs("div",{className:"flex items-center justify-between",children:[e.jsxs("div",{children:[e.jsx("h1",{className:"text-2xl font-bold tracking-tight",children:"Agent Not Found"}),e.jsx("p",{className:"text-muted-foreground",children:"The requested agent could not be found"})]}),e.jsx("div",{className:"flex items-center gap-2",children:e.jsx(i,{variant:"ghost",size:"sm",asChild:!0,className:"px-2 hover:bg-transparent",children:e.jsx(d,{to:"/agents",className:"flex items-center text-muted-foreground hover:text-foreground transition-colors",children:e.jsx(u,{className:"h-4 w-4"})})})})]}),e.jsx(l,{children:e.jsx(m,{className:"pt-6",children:e.jsx("div",{className:"text-center",children:e.jsx("p",{className:"text-destructive",children:p||"Agent not found"})})})})]});const b=D(s.metadata.tools);return e.jsxs("div",{className:"space-y-6",children:[e.jsx("div",{className:"space-y-1",children:e.jsxs("div",{className:"flex items-start justify-between gap-4",children:[e.jsx("h1",{className:"text-xl sm:text-2xl font-bold tracking-tight",children:s.metadata.name}),e.jsxs("div",{className:"flex items-center gap-2 flex-shrink-0",children:[e.jsx(i,{variant:"ghost",size:"sm",asChild:!0,children:e.jsx(d,{to:"/agents",className:"flex items-center gap-1 text-muted-foreground hover:text-foreground transition-colors",children:e.jsx(u,{className:"h-4 w-4"})})}),e.jsx(i,{variant:"outline",size:"sm",asChild:!0,children:e.jsxs(d,{to:`/agents/${s.filename.replace(".md","")}/edit`,children:[e.jsx(k,{className:"h-4 w-4 sm:mr-2"}),e.jsx("span",{className:"hidden sm:inline",children:"Edit"})]})}),e.jsxs(i,{variant:"destructive",size:"sm",onClick:A,children:[e.jsx(B,{className:"h-4 w-4 sm:mr-2"}),e.jsx("span",{className:"hidden sm:inline",children:"Delete"})]})]})]})}),e.jsxs("div",{className:"grid grid-cols-1 lg:grid-cols-3 gap-6",children:[e.jsxs("div",{className:"lg:col-span-2 space-y-6",children:[e.jsxs(l,{children:[e.jsx(o,{children:e.jsx(f,{children:"Description"})}),e.jsx(m,{children:e.jsx("p",{children:s.metadata.description})})]}),s.content&&e.jsxs(l,{children:[e.jsxs(o,{children:[e.jsx(f,{children:"Instructions"}),e.jsx(z,{children:"System prompt and behavior instructions for this agent"})]}),e.jsx(m,{children:e.jsx("pre",{className:"whitespace-pre-wrap text-sm bg-muted p-4 rounded-md",children:s.content})})]})]}),e.jsxs("div",{className:"space-y-6",children:[e.jsxs(l,{children:[e.jsx(o,{children:e.jsx(f,{children:"Agent Actions"})}),e.jsx(m,{className:"space-y-2",children:e.jsx(i,{variant:"default",className:"w-full justify-start",asChild:!0,children:e.jsxs(d,{to:`/terminal/ag-${s.filename.replace(".md","")}`,children:[e.jsx(T,{className:"h-4 w-4 mr-2"}),"Prepare Agent"]})})})]}),e.jsxs(l,{children:[e.jsx(o,{children:e.jsx(f,{children:"Information"})}),e.jsxs(m,{className:"space-y-2",children:[s.metadata.color&&e.jsxs("div",{children:[e.jsx("p",{className:"text-sm font-medium mb-2",children:"Color"}),e.jsx(v,{variant:"outline",className:"capitalize border-2",style:{backgroundColor:c[s.metadata.color]?.bg||c.blue.bg,color:c[s.metadata.color]?.text||c.blue.text,borderColor:c[s.metadata.color]?.border||c.blue.border},children:s.metadata.color})]}),e.jsxs("div",{children:[e.jsx("p",{className:"text-sm font-medium",children:"Tools"}),b.length>0?e.jsx("div",{className:"flex flex-wrap gap-2 mt-1",children:b.map(a=>e.jsx(v,{variant:"secondary",children:a},a))}):e.jsx("p",{className:"text-sm text-muted-foreground",children:"No specific tools configured - inherits all tools"})]})]})]})]})]})]})}export{F as default};
1
+ import{E as C,u as E,r as h,j as e,B as i,L as d,J as k,T as B,i as T,A as N}from"./index-Bbxvuj4b.js";import{C as l,b as o,a as m,c as f,d as z}from"./card-D_zGBKua.js";import{B as v}from"./badge-D7ZZbMEG.js";import{A as u}from"./arrow-left-Do2jUSS9.js";const D=t=>t?Array.isArray(t)?t.filter(r=>typeof r=="string").map(r=>r.trim()).filter(Boolean):typeof t=="string"?t.split(",").map(r=>r.trim()).filter(Boolean):[]:[],c={blue:{bg:"#dbeafe",border:"#2563eb",text:"#1e40af"},green:{bg:"#dcfce7",border:"#16a34a",text:"#166534"},red:{bg:"#fee2e2",border:"#dc2626",text:"#991b1b"},emerald:{bg:"#d1fae5",border:"#10b981",text:"#047857"},purple:{bg:"#f3e8ff",border:"#9333ea",text:"#6b21a8"},orange:{bg:"#fed7aa",border:"#ea580c",text:"#9a3412"},yellow:{bg:"#fef9c3",border:"#eab308",text:"#854d0e"},teal:{bg:"#ccfbf1",border:"#14b8a6",text:"#0f766e"},indigo:{bg:"#e0e7ff",border:"#6366f1",text:"#4338ca"},pink:{bg:"#fce7f3",border:"#ec4899",text:"#9f1239"},cyan:{bg:"#cffafe",border:"#06b6d4",text:"#155e75"},slate:{bg:"#f1f5f9",border:"#475569",text:"#334155"},gray:{bg:"#f3f4f6",border:"#6b7280",text:"#374151"}};function F(){const t=C(),r=E(),[s,y]=h.useState(null),[w,j]=h.useState(!0),[p,x]=h.useState(null);h.useEffect(()=>{async function a(){try{j(!0);const g=await(await fetch(`${N}/api/v1/agents/${t.id}`)).json();g.success?y(g.document):x(g.error||"Failed to fetch agent")}catch(n){x(n instanceof Error?n.message:"Unknown error")}finally{j(!1)}}t.id&&a()},[t.id]);const A=async()=>{if(!(!s||!confirm("Are you sure you want to delete this agent?")))try{const n=await(await fetch(`${N}/api/v1/agents/${s.filename.replace(".md","")}`,{method:"DELETE"})).json();n.success?r("/agents"):x(n.error?.message||"Failed to delete agent")}catch(a){x(a instanceof Error?a.message:"Unknown error")}};if(w)return e.jsxs("div",{className:"space-y-6",children:[e.jsxs("div",{className:"flex items-center justify-between",children:[e.jsxs("div",{className:"flex-1",children:[e.jsx("div",{className:"h-8 bg-muted rounded w-64 animate-pulse"}),e.jsx("div",{className:"h-4 bg-muted rounded w-32 animate-pulse mt-2"})]}),e.jsx("div",{className:"flex items-center gap-2",children:e.jsx(i,{variant:"ghost",size:"sm",asChild:!0,className:"px-2 hover:bg-transparent",children:e.jsx(d,{to:"/agents",className:"flex items-center text-muted-foreground hover:text-foreground transition-colors",children:e.jsx(u,{className:"h-4 w-4"})})})})]}),e.jsx(l,{children:e.jsxs(o,{children:[e.jsx("div",{className:"h-6 bg-muted rounded w-48 animate-pulse"}),e.jsx("div",{className:"h-4 bg-muted rounded w-64 animate-pulse"})]})})]});if(p||!s)return e.jsxs("div",{className:"space-y-6",children:[e.jsxs("div",{className:"flex items-center justify-between",children:[e.jsxs("div",{children:[e.jsx("h1",{className:"text-2xl font-bold tracking-tight",children:"Agent Not Found"}),e.jsx("p",{className:"text-muted-foreground",children:"The requested agent could not be found"})]}),e.jsx("div",{className:"flex items-center gap-2",children:e.jsx(i,{variant:"ghost",size:"sm",asChild:!0,className:"px-2 hover:bg-transparent",children:e.jsx(d,{to:"/agents",className:"flex items-center text-muted-foreground hover:text-foreground transition-colors",children:e.jsx(u,{className:"h-4 w-4"})})})})]}),e.jsx(l,{children:e.jsx(m,{className:"pt-6",children:e.jsx("div",{className:"text-center",children:e.jsx("p",{className:"text-destructive",children:p||"Agent not found"})})})})]});const b=D(s.metadata.tools);return e.jsxs("div",{className:"space-y-6",children:[e.jsx("div",{className:"space-y-1",children:e.jsxs("div",{className:"flex items-start justify-between gap-4",children:[e.jsx("h1",{className:"text-xl sm:text-2xl font-bold tracking-tight",children:s.metadata.name}),e.jsxs("div",{className:"flex items-center gap-2 flex-shrink-0",children:[e.jsx(i,{variant:"ghost",size:"sm",asChild:!0,children:e.jsx(d,{to:"/agents",className:"flex items-center gap-1 text-muted-foreground hover:text-foreground transition-colors",children:e.jsx(u,{className:"h-4 w-4"})})}),e.jsx(i,{variant:"outline",size:"sm",asChild:!0,children:e.jsxs(d,{to:`/agents/${s.filename.replace(".md","")}/edit`,children:[e.jsx(k,{className:"h-4 w-4 sm:mr-2"}),e.jsx("span",{className:"hidden sm:inline",children:"Edit"})]})}),e.jsxs(i,{variant:"destructive",size:"sm",onClick:A,children:[e.jsx(B,{className:"h-4 w-4 sm:mr-2"}),e.jsx("span",{className:"hidden sm:inline",children:"Delete"})]})]})]})}),e.jsxs("div",{className:"grid grid-cols-1 lg:grid-cols-3 gap-6",children:[e.jsxs("div",{className:"lg:col-span-2 space-y-6",children:[e.jsxs(l,{children:[e.jsx(o,{children:e.jsx(f,{children:"Description"})}),e.jsx(m,{children:e.jsx("p",{children:s.metadata.description})})]}),s.content&&e.jsxs(l,{children:[e.jsxs(o,{children:[e.jsx(f,{children:"Instructions"}),e.jsx(z,{children:"System prompt and behavior instructions for this agent"})]}),e.jsx(m,{children:e.jsx("pre",{className:"whitespace-pre-wrap text-sm bg-muted p-4 rounded-md",children:s.content})})]})]}),e.jsxs("div",{className:"space-y-6",children:[e.jsxs(l,{children:[e.jsx(o,{children:e.jsx(f,{children:"Agent Actions"})}),e.jsx(m,{className:"space-y-2",children:e.jsx(i,{variant:"default",className:"w-full justify-start",asChild:!0,children:e.jsxs(d,{to:`/terminal/ag-${s.filename.replace(".md","")}`,children:[e.jsx(T,{className:"h-4 w-4 mr-2"}),"Prepare Agent"]})})})]}),e.jsxs(l,{children:[e.jsx(o,{children:e.jsx(f,{children:"Information"})}),e.jsxs(m,{className:"space-y-2",children:[s.metadata.color&&e.jsxs("div",{children:[e.jsx("p",{className:"text-sm font-medium mb-2",children:"Color"}),e.jsx(v,{variant:"outline",className:"capitalize border-2",style:{backgroundColor:c[s.metadata.color]?.bg||c.blue.bg,color:c[s.metadata.color]?.text||c.blue.text,borderColor:c[s.metadata.color]?.border||c.blue.border},children:s.metadata.color})]}),e.jsxs("div",{children:[e.jsx("p",{className:"text-sm font-medium",children:"Tools"}),b.length>0?e.jsx("div",{className:"flex flex-wrap gap-2 mt-1",children:b.map(a=>e.jsx(v,{variant:"secondary",children:a},a))}):e.jsx("p",{className:"text-sm text-muted-foreground",children:"No specific tools configured - inherits all tools"})]})]})]})]})]})]})}export{F as default};
@@ -1 +1 @@
1
- import{E as X,u as Y,H as Z,r as n,j as e,B as m,L as v,i as O,I as D,a0 as ee,ac as te,A as y}from"./index-BSBM4i_g.js";import{C as N,a as C,b as se,c as ae}from"./card-Cnz8b7Ou.js";import{L as l}from"./label-vEgNxdb2.js";import{B as re}from"./badge-DO6e5hC1.js";import{c as ne}from"./clipboard-B9ndUJKl.js";import{A as z}from"./arrow-left-CEZFPQje.js";import{C as oe,a as ie}from"./clipboard-BTZru8wn.js";function xe(){const{id:i}=X(),U=Y(),{toast:w}=Z(),[q,S]=n.useState(!0),[o,A]=n.useState(!1),[d,c]=n.useState(null),[H,R]=n.useState(""),[u,E]=n.useState(""),[g,F]=n.useState(""),[f,P]=n.useState("blue"),[x,k]=n.useState([]),[h,$]=n.useState(""),[L,p]=n.useState([]),[_,M]=n.useState(!0),[J,T]=n.useState(!1),G=["blue","green","red","emerald","purple","orange","yellow","teal","indigo","pink","cyan","slate","gray"],K={blue:{bg:"#3b82f6",border:"#1e40af",text:"#ffffff"},green:{bg:"#22c55e",border:"#15803d",text:"#ffffff"},red:{bg:"#ef4444",border:"#b91c1c",text:"#ffffff"},emerald:{bg:"#10b981",border:"#047857",text:"#ffffff"},purple:{bg:"#a855f7",border:"#7e22ce",text:"#ffffff"},orange:{bg:"#f97316",border:"#c2410c",text:"#ffffff"},yellow:{bg:"#eab308",border:"#a16207",text:"#ffffff"},teal:{bg:"#14b8a6",border:"#0f766e",text:"#ffffff"},indigo:{bg:"#6366f1",border:"#4338ca",text:"#ffffff"},pink:{bg:"#ec4899",border:"#be185d",text:"#ffffff"},cyan:{bg:"#06b6d4",border:"#0e7490",text:"#ffffff"},slate:{bg:"#64748b",border:"#475569",text:"#ffffff"},gray:{bg:"#6b7280",border:"#4b5563",text:"#ffffff"}},Q=t=>{if(!t)return[];if(Array.isArray(t)){const a=t.filter(s=>typeof s=="string").map(s=>s.trim()).filter(Boolean);return Array.from(new Set(a))}return typeof t=="string"?Array.from(new Set(t.split(",").map(a=>a.trim()).filter(Boolean))):[]};n.useEffect(()=>{async function t(){try{S(!0);const s=await(await fetch(`${y}/api/v1/agents/${i}`)).json();if(!s.success)throw new Error(s.error||"Failed to load agent");const r=s.document;R(r.filename),E(r.metadata.name||""),F(r.metadata.description||""),P(r.metadata.color||"blue"),$(r.content||""),k(Q(r.metadata.tools))}catch(a){const s=a instanceof Error?a.message:"Failed to load agent";c(s)}finally{S(!1)}}i&&t()},[i]),n.useEffect(()=>{let t=!0;return(async()=>{M(!0);try{const s=await fetch(`${y}/api/v1/mcp`);if(!s.ok)throw new Error("Failed to fetch MCP servers");const r=await s.json();if(!r?.success||!Array.isArray(r.servers)){t&&p([]);return}const B=r.mcpServers&&typeof r.mcpServers=="object"?r.mcpServers:{},b=r.servers.map(I=>{const j=B[I]??{};return{name:I,enabled:j?.enabled!==!1,description:typeof j?.description=="string"?j.description:void 0}});t&&p(b)}catch(s){console.error("Failed to load MCP servers",s),t&&p([])}finally{t&&M(!1)}})(),()=>{t=!1}},[]);const V=async()=>{const t=".nut/config.json";try{await ne(t),T(!0),w({title:"Copied!",description:`${t} copied to clipboard`}),setTimeout(()=>T(!1),2e3)}catch(a){console.error("Failed to copy config path:",a),w({title:"Error",description:"Failed to copy to clipboard",variant:"destructive"})}},W=async t=>{if(t.preventDefault(),!u.trim()||!g.trim()||!h.trim()){c("Name, description, and agent instructions are required");return}try{A(!0),c(null);const a={name:u.trim(),description:g.trim(),content:h.trim(),metadata:{color:f,tools:x.length?x:void 0}},r=await(await fetch(`${y}/api/v1/agents/${i}`,{method:"PUT",headers:{"Content-Type":"application/json"},body:JSON.stringify(a)})).json();if(!r.success)throw new Error(r.error||"Failed to update agent");const b=r.document.filename.replace(/\.md$/,"");U(`/agents/${b}`)}catch(a){const s=a instanceof Error?a.message:"Failed to update agent";c(s)}finally{A(!1)}};return q?e.jsx("div",{className:"space-y-6",children:e.jsx(N,{children:e.jsx(C,{className:"pt-6",children:"Loading agent..."})})}):d?e.jsxs("div",{className:"space-y-6",children:[e.jsxs("div",{className:"flex items-center justify-between",children:[e.jsxs("div",{children:[e.jsx("h1",{className:"text-2xl font-bold tracking-tight",children:"Edit Agent"}),e.jsx("p",{className:"text-muted-foreground",children:"Unable to load agent"})]}),e.jsx("div",{className:"flex items-center gap-2",children:e.jsx(m,{variant:"ghost",size:"sm",asChild:!0,children:e.jsx(v,{to:`/agents/${i}`,className:"flex items-center gap-1 text-muted-foreground hover:text-foreground transition-colors",children:e.jsx(z,{className:"h-4 w-4"})})})})]}),e.jsx(N,{children:e.jsx(C,{className:"pt-6",children:e.jsx("div",{className:"text-destructive",children:d})})})]}):e.jsxs("div",{className:"space-y-6",children:[e.jsxs("div",{className:"flex items-center justify-between",children:[e.jsxs("div",{children:[e.jsx("h1",{className:"text-2xl font-bold tracking-tight",children:"Edit Agent"}),e.jsxs("p",{className:"text-muted-foreground",children:["File: ",H]})]}),e.jsx("div",{className:"flex items-center gap-2",children:e.jsx(m,{variant:"ghost",size:"sm",asChild:!0,children:e.jsx(v,{to:`/agents/${i}`,className:"flex items-center gap-1 text-muted-foreground hover:text-foreground transition-colors",children:e.jsx(z,{className:"h-4 w-4"})})})})]}),e.jsxs(N,{children:[e.jsx(se,{children:e.jsxs(ae,{className:"flex items-center gap-2",children:[e.jsx(O,{className:"h-5 w-5"}),"Agent Configuration"]})}),e.jsx(C,{children:e.jsxs("form",{onSubmit:W,className:"space-y-6",children:[e.jsxs("div",{className:"grid grid-cols-1 md:grid-cols-2 gap-6",children:[e.jsxs("div",{className:"space-y-2",children:[e.jsx(l,{htmlFor:"name",children:"Name *"}),e.jsx(D,{id:"name",value:u,onChange:t=>E(t.target.value),disabled:o})]}),e.jsxs("div",{className:"space-y-2",children:[e.jsx(l,{htmlFor:"description",children:"Description *"}),e.jsx(D,{id:"description",value:g,onChange:t=>F(t.target.value),disabled:o})]})]}),e.jsxs("div",{className:"space-y-2",children:[e.jsx(l,{children:"Color"}),e.jsx("div",{className:"flex flex-wrap gap-2",children:G.map(t=>{const a=K[t];return e.jsx("button",{type:"button",onClick:()=>P(t),disabled:o,className:`w-10 h-10 rounded-md border-2 transition-all ${f===t?"ring-2 ring-offset-2 shadow-md":"hover:scale-110 hover:shadow-sm"}`,style:{backgroundColor:a.bg,borderColor:f===t?a.border:"hsl(var(--border))",...f===t&&{"--tw-ring-color":a.border}},title:t,children:e.jsx("span",{className:"sr-only",children:t})},t)})})]}),e.jsxs("div",{className:"space-y-2",children:[e.jsx(l,{htmlFor:"content",children:"Agent Instructions *"}),e.jsxs("p",{className:"text-sm text-muted-foreground",children:["System prompt or instructions for this agent's behavior."," ","Insert ",e.jsx("code",{className:"text-xs bg-muted px-1.5 py-0.5 rounded font-mono",children:".nut/config.json"})," ",e.jsx("button",{type:"button",onClick:V,className:"inline-flex items-center align-middle text-muted-foreground hover:text-foreground transition-colors",title:"Copy .nut/config.json to clipboard",children:J?e.jsx(oe,{className:"h-3.5 w-3.5 ml-0.5"}):e.jsx(ie,{className:"h-3.5 w-3.5 ml-0.5"})})," ","if you want the agent to be able to access its name, role, or email address."]}),e.jsx(ee,{id:"content",value:h,onChange:t=>$(t.target.value),rows:8,disabled:o,required:!0})]}),e.jsxs("div",{className:"space-y-2",children:[e.jsx(l,{children:"Tools (Optional)"}),e.jsx("p",{className:"text-sm text-muted-foreground",children:"Choose which MCP servers this agent should be able to use. Leave empty to inherit all available servers."}),e.jsx("div",{className:"space-y-2",children:_?e.jsx("div",{className:"text-sm text-muted-foreground",children:"Loading MCP servers…"}):L.length===0?e.jsx("div",{className:"text-sm text-muted-foreground border border-dashed rounded-md p-3",children:"No MCP servers configured yet. Configure servers in Settings → MCP."}):L.map(t=>e.jsxs("label",{className:"flex items-start gap-3 rounded-md border border-transparent bg-muted/30 px-3 py-2 hover:border-muted transition-colors",children:[e.jsx(te,{checked:x.includes(t.name),onCheckedChange:a=>{k(s=>a===!0?s.includes(t.name)?s:[...s,t.name]:s.filter(r=>r!==t.name))},disabled:o||!t.enabled}),e.jsxs("div",{className:"flex flex-col",children:[e.jsxs("span",{className:"text-sm font-medium",children:[t.name,!t.enabled&&e.jsx(re,{variant:"secondary",className:"ml-2 text-xs",children:"Disabled"})]}),e.jsx("span",{className:"text-xs text-muted-foreground",children:t.enabled?t.description||"Enabled MCP server":"Enable this server in Settings to allow agents to use it"})]})]},t.name))})]}),d&&e.jsx("div",{className:"text-sm text-destructive bg-destructive/10 p-3 rounded-md",children:d}),e.jsxs("div",{className:"flex gap-2 justify-end",children:[e.jsx(m,{type:"button",variant:"outline",asChild:!0,disabled:o,children:e.jsx(v,{to:`/agents/${i}`,children:"Cancel"})}),e.jsx(m,{type:"submit",disabled:o,children:o?"Saving...":"Save Changes"})]})]})})]})]})}export{xe as default};
1
+ import{E as X,u as Y,H as Z,r as n,j as e,B as m,L as v,i as O,I as D,a0 as ee,ac as te,A as y}from"./index-Bbxvuj4b.js";import{C as N,a as C,b as se,c as ae}from"./card-D_zGBKua.js";import{L as l}from"./label-CZGCmBD7.js";import{B as re}from"./badge-D7ZZbMEG.js";import{c as ne}from"./clipboard-B9ndUJKl.js";import{A as z}from"./arrow-left-Do2jUSS9.js";import{C as oe,a as ie}from"./clipboard-D3NA8gb4.js";function xe(){const{id:i}=X(),U=Y(),{toast:w}=Z(),[q,S]=n.useState(!0),[o,A]=n.useState(!1),[d,c]=n.useState(null),[H,R]=n.useState(""),[u,E]=n.useState(""),[g,F]=n.useState(""),[f,P]=n.useState("blue"),[x,k]=n.useState([]),[h,$]=n.useState(""),[L,p]=n.useState([]),[_,M]=n.useState(!0),[J,T]=n.useState(!1),G=["blue","green","red","emerald","purple","orange","yellow","teal","indigo","pink","cyan","slate","gray"],K={blue:{bg:"#3b82f6",border:"#1e40af",text:"#ffffff"},green:{bg:"#22c55e",border:"#15803d",text:"#ffffff"},red:{bg:"#ef4444",border:"#b91c1c",text:"#ffffff"},emerald:{bg:"#10b981",border:"#047857",text:"#ffffff"},purple:{bg:"#a855f7",border:"#7e22ce",text:"#ffffff"},orange:{bg:"#f97316",border:"#c2410c",text:"#ffffff"},yellow:{bg:"#eab308",border:"#a16207",text:"#ffffff"},teal:{bg:"#14b8a6",border:"#0f766e",text:"#ffffff"},indigo:{bg:"#6366f1",border:"#4338ca",text:"#ffffff"},pink:{bg:"#ec4899",border:"#be185d",text:"#ffffff"},cyan:{bg:"#06b6d4",border:"#0e7490",text:"#ffffff"},slate:{bg:"#64748b",border:"#475569",text:"#ffffff"},gray:{bg:"#6b7280",border:"#4b5563",text:"#ffffff"}},Q=t=>{if(!t)return[];if(Array.isArray(t)){const a=t.filter(s=>typeof s=="string").map(s=>s.trim()).filter(Boolean);return Array.from(new Set(a))}return typeof t=="string"?Array.from(new Set(t.split(",").map(a=>a.trim()).filter(Boolean))):[]};n.useEffect(()=>{async function t(){try{S(!0);const s=await(await fetch(`${y}/api/v1/agents/${i}`)).json();if(!s.success)throw new Error(s.error||"Failed to load agent");const r=s.document;R(r.filename),E(r.metadata.name||""),F(r.metadata.description||""),P(r.metadata.color||"blue"),$(r.content||""),k(Q(r.metadata.tools))}catch(a){const s=a instanceof Error?a.message:"Failed to load agent";c(s)}finally{S(!1)}}i&&t()},[i]),n.useEffect(()=>{let t=!0;return(async()=>{M(!0);try{const s=await fetch(`${y}/api/v1/mcp`);if(!s.ok)throw new Error("Failed to fetch MCP servers");const r=await s.json();if(!r?.success||!Array.isArray(r.servers)){t&&p([]);return}const B=r.mcpServers&&typeof r.mcpServers=="object"?r.mcpServers:{},b=r.servers.map(I=>{const j=B[I]??{};return{name:I,enabled:j?.enabled!==!1,description:typeof j?.description=="string"?j.description:void 0}});t&&p(b)}catch(s){console.error("Failed to load MCP servers",s),t&&p([])}finally{t&&M(!1)}})(),()=>{t=!1}},[]);const V=async()=>{const t=".nut/config.json";try{await ne(t),T(!0),w({title:"Copied!",description:`${t} copied to clipboard`}),setTimeout(()=>T(!1),2e3)}catch(a){console.error("Failed to copy config path:",a),w({title:"Error",description:"Failed to copy to clipboard",variant:"destructive"})}},W=async t=>{if(t.preventDefault(),!u.trim()||!g.trim()||!h.trim()){c("Name, description, and agent instructions are required");return}try{A(!0),c(null);const a={name:u.trim(),description:g.trim(),content:h.trim(),metadata:{color:f,tools:x.length?x:void 0}},r=await(await fetch(`${y}/api/v1/agents/${i}`,{method:"PUT",headers:{"Content-Type":"application/json"},body:JSON.stringify(a)})).json();if(!r.success)throw new Error(r.error||"Failed to update agent");const b=r.document.filename.replace(/\.md$/,"");U(`/agents/${b}`)}catch(a){const s=a instanceof Error?a.message:"Failed to update agent";c(s)}finally{A(!1)}};return q?e.jsx("div",{className:"space-y-6",children:e.jsx(N,{children:e.jsx(C,{className:"pt-6",children:"Loading agent..."})})}):d?e.jsxs("div",{className:"space-y-6",children:[e.jsxs("div",{className:"flex items-center justify-between",children:[e.jsxs("div",{children:[e.jsx("h1",{className:"text-2xl font-bold tracking-tight",children:"Edit Agent"}),e.jsx("p",{className:"text-muted-foreground",children:"Unable to load agent"})]}),e.jsx("div",{className:"flex items-center gap-2",children:e.jsx(m,{variant:"ghost",size:"sm",asChild:!0,children:e.jsx(v,{to:`/agents/${i}`,className:"flex items-center gap-1 text-muted-foreground hover:text-foreground transition-colors",children:e.jsx(z,{className:"h-4 w-4"})})})})]}),e.jsx(N,{children:e.jsx(C,{className:"pt-6",children:e.jsx("div",{className:"text-destructive",children:d})})})]}):e.jsxs("div",{className:"space-y-6",children:[e.jsxs("div",{className:"flex items-center justify-between",children:[e.jsxs("div",{children:[e.jsx("h1",{className:"text-2xl font-bold tracking-tight",children:"Edit Agent"}),e.jsxs("p",{className:"text-muted-foreground",children:["File: ",H]})]}),e.jsx("div",{className:"flex items-center gap-2",children:e.jsx(m,{variant:"ghost",size:"sm",asChild:!0,children:e.jsx(v,{to:`/agents/${i}`,className:"flex items-center gap-1 text-muted-foreground hover:text-foreground transition-colors",children:e.jsx(z,{className:"h-4 w-4"})})})})]}),e.jsxs(N,{children:[e.jsx(se,{children:e.jsxs(ae,{className:"flex items-center gap-2",children:[e.jsx(O,{className:"h-5 w-5"}),"Agent Configuration"]})}),e.jsx(C,{children:e.jsxs("form",{onSubmit:W,className:"space-y-6",children:[e.jsxs("div",{className:"grid grid-cols-1 md:grid-cols-2 gap-6",children:[e.jsxs("div",{className:"space-y-2",children:[e.jsx(l,{htmlFor:"name",children:"Name *"}),e.jsx(D,{id:"name",value:u,onChange:t=>E(t.target.value),disabled:o})]}),e.jsxs("div",{className:"space-y-2",children:[e.jsx(l,{htmlFor:"description",children:"Description *"}),e.jsx(D,{id:"description",value:g,onChange:t=>F(t.target.value),disabled:o})]})]}),e.jsxs("div",{className:"space-y-2",children:[e.jsx(l,{children:"Color"}),e.jsx("div",{className:"flex flex-wrap gap-2",children:G.map(t=>{const a=K[t];return e.jsx("button",{type:"button",onClick:()=>P(t),disabled:o,className:`w-10 h-10 rounded-md border-2 transition-all ${f===t?"ring-2 ring-offset-2 shadow-md":"hover:scale-110 hover:shadow-sm"}`,style:{backgroundColor:a.bg,borderColor:f===t?a.border:"hsl(var(--border))",...f===t&&{"--tw-ring-color":a.border}},title:t,children:e.jsx("span",{className:"sr-only",children:t})},t)})})]}),e.jsxs("div",{className:"space-y-2",children:[e.jsx(l,{htmlFor:"content",children:"Agent Instructions *"}),e.jsxs("p",{className:"text-sm text-muted-foreground",children:["System prompt or instructions for this agent's behavior."," ","Insert ",e.jsx("code",{className:"text-xs bg-muted px-1.5 py-0.5 rounded font-mono",children:".nut/config.json"})," ",e.jsx("button",{type:"button",onClick:V,className:"inline-flex items-center align-middle text-muted-foreground hover:text-foreground transition-colors",title:"Copy .nut/config.json to clipboard",children:J?e.jsx(oe,{className:"h-3.5 w-3.5 ml-0.5"}):e.jsx(ie,{className:"h-3.5 w-3.5 ml-0.5"})})," ","if you want the agent to be able to access its name, role, or email address."]}),e.jsx(ee,{id:"content",value:h,onChange:t=>$(t.target.value),rows:8,disabled:o,required:!0})]}),e.jsxs("div",{className:"space-y-2",children:[e.jsx(l,{children:"Tools (Optional)"}),e.jsx("p",{className:"text-sm text-muted-foreground",children:"Choose which MCP servers this agent should be able to use. Leave empty to inherit all available servers."}),e.jsx("div",{className:"space-y-2",children:_?e.jsx("div",{className:"text-sm text-muted-foreground",children:"Loading MCP servers…"}):L.length===0?e.jsx("div",{className:"text-sm text-muted-foreground border border-dashed rounded-md p-3",children:"No MCP servers configured yet. Configure servers in Settings → MCP."}):L.map(t=>e.jsxs("label",{className:"flex items-start gap-3 rounded-md border border-transparent bg-muted/30 px-3 py-2 hover:border-muted transition-colors",children:[e.jsx(te,{checked:x.includes(t.name),onCheckedChange:a=>{k(s=>a===!0?s.includes(t.name)?s:[...s,t.name]:s.filter(r=>r!==t.name))},disabled:o||!t.enabled}),e.jsxs("div",{className:"flex flex-col",children:[e.jsxs("span",{className:"text-sm font-medium",children:[t.name,!t.enabled&&e.jsx(re,{variant:"secondary",className:"ml-2 text-xs",children:"Disabled"})]}),e.jsx("span",{className:"text-xs text-muted-foreground",children:t.enabled?t.description||"Enabled MCP server":"Enable this server in Settings to allow agents to use it"})]})]},t.name))})]}),d&&e.jsx("div",{className:"text-sm text-destructive bg-destructive/10 p-3 rounded-md",children:d}),e.jsxs("div",{className:"flex gap-2 justify-end",children:[e.jsx(m,{type:"button",variant:"outline",asChild:!0,disabled:o,children:e.jsx(v,{to:`/agents/${i}`,children:"Cancel"})}),e.jsx(m,{type:"submit",disabled:o,children:o?"Saving...":"Save Changes"})]})]})})]})]})}export{xe as default};
@@ -1,3 +1,3 @@
1
- import{j as e,S as I,Y as L,r as x,H as O,A as S,n as M,B as b,L as v,i as E,ah as $,ai as _}from"./index-BSBM4i_g.js";import{C as N,a as w,b as D,c as H}from"./card-Cnz8b7Ou.js";import{B as y}from"./badge-DO6e5hC1.js";import{c as U}from"./clipboard-B9ndUJKl.js";import{R as Y,a as G,f as J,L as F}from"./browser-modal-BTxVvZIA.js";import{P as T}from"./plus-BfBtnncn.js";import{T as K}from"./tag-Czz-3rNY.js";import"./search-kcgmZUqQ.js";const V=["color","tools","createdAt","updatedAt","version","focusAreas","contextPreferences","tags"];function P(t){if(t){if(Array.isArray(t)){const r=t.map(n=>{if(typeof n=="string")return n.trim();if(typeof n=="number")return`${n}`}).filter(n=>typeof n=="string"&&n.length>0);return r.length>0?r:void 0}if(typeof t=="string"){const r=t.split(",").map(n=>n.trim()).filter(n=>n.length>0);return r.length>0?r:void 0}}}function q(t,r){const n=[];if(t.content&&typeof t.content=="object")for(const o of Object.values(t.content))typeof o=="string"&&o.trim().length>0&&n.push(o.trim());const i=[];return i.push(`# ${r}`),t.description?.trim()&&i.push(t.description.trim()),[...i,...n].join(`
1
+ import{j as e,S as I,Y as L,r as x,H as O,A as S,n as M,B as b,L as v,i as E,ah as $,ai as _}from"./index-Bbxvuj4b.js";import{C as N,a as w,b as D,c as H}from"./card-D_zGBKua.js";import{B as y}from"./badge-D7ZZbMEG.js";import{c as U}from"./clipboard-B9ndUJKl.js";import{R as Y,L as F}from"./browser-modal-CWDhylx7.js";import{R as G,f as J}from"./registry-ANRa5WBi.js";import{P as T}from"./plus-Be79gWKj.js";import{T as K}from"./tag-BgO5mxYK.js";import"./search-CrIdR7ah.js";const V=["color","tools","createdAt","updatedAt","version","focusAreas","contextPreferences","tags"];function P(t){if(t){if(Array.isArray(t)){const r=t.map(n=>{if(typeof n=="string")return n.trim();if(typeof n=="number")return`${n}`}).filter(n=>typeof n=="string"&&n.length>0);return r.length>0?r:void 0}if(typeof t=="string"){const r=t.split(",").map(n=>n.trim()).filter(n=>n.length>0);return r.length>0?r:void 0}}}function q(t,r){const n=[];if(t.content&&typeof t.content=="object")for(const o of Object.values(t.content))typeof o=="string"&&o.trim().length>0&&n.push(o.trim());const i=[];return i.push(`# ${r}`),t.description?.trim()&&i.push(t.description.trim()),[...i,...n].join(`
2
2
 
3
- `).trim()}function z(t,r){const n=t.name||r.name,i=r.description||t.description||"",a={registryId:t.id,registryEndpoint:t.endpoint,registrySource:Y,author:t.author};for(const o of V){const d=r[o];if(d!==void 0)if(o==="tools"||o==="focusAreas"||o==="contextPreferences"||o==="tags"){const f=P(d);f&&(a[o]=f)}else a[o]=d}!a.version&&t.version&&(a.version=t.version),a.color||(a.color="blue"),!a.tags&&t.tags&&(a.tags=P(t.tags));for(const[o,d]of Object.entries(a))d==null&&delete a[o];return{name:n,description:i,content:q(r,n),metadata:Object.keys(a).length>0?a:void 0}}function B({open:t,onOpenChange:r,onImport:n}){return e.jsx(G,{open:t,onOpenChange:r,categoryId:"agents",title:"Coconut Registry – Agents",confirmLabel:"Import Agent",getDetail:i=>J(i.endpoint),renderPreview:(i,a)=>{if(!a)return e.jsx("div",{className:"flex h-full items-center justify-center text-muted-foreground",children:"Select an agent to preview"});const o=z(i,a),d=o.metadata??{},f=typeof d.version=="string"?d.version:void 0,u=Array.isArray(i.tags)?i.tags:[],j=Array.isArray(d.tools)?d.tools.filter(l=>typeof l=="string"):[],p=Array.isArray(d.focusAreas)?d.focusAreas.filter(l=>typeof l=="string"):[];return e.jsx("div",{className:"h-full min-h-0 overflow-hidden rounded-md border",children:e.jsx(I,{className:"h-full",children:e.jsxs("div",{className:"space-y-6 p-4",children:[e.jsxs("div",{className:"space-y-3",children:[e.jsxs("div",{className:"flex flex-wrap items-start justify-between gap-2",children:[e.jsxs("div",{children:[e.jsx("h3",{className:"text-lg font-semibold",children:i.name}),e.jsx("p",{className:"text-sm text-muted-foreground",children:a.description})]}),f&&e.jsxs(y,{variant:"outline",children:["v",f]})]}),e.jsxs("div",{className:"text-xs text-muted-foreground",children:["Registry ID: ",e.jsx("span",{className:"font-mono",children:i.id})]}),u.length>0&&e.jsx("div",{className:"flex flex-wrap gap-2",children:u.map(l=>e.jsx(y,{variant:"secondary",children:l},l))}),j.length>0&&e.jsxs("div",{className:"flex flex-wrap items-center gap-2 text-sm",children:[e.jsx("span",{className:"font-medium",children:"Tools:"}),j.map(l=>e.jsx(y,{variant:"outline",children:l},l))]}),p.length>0&&e.jsxs("div",{className:"space-y-1",children:[e.jsx("div",{className:"text-sm font-medium",children:"Focus Areas"}),e.jsx("ul",{className:"list-disc pl-5 text-sm text-muted-foreground",children:p.map(l=>e.jsx("li",{children:l},l))})]})]}),e.jsx(L,{className:"[&_.prose]:max-w-none",children:o.content})]})})})},onConfirm:async(i,a)=>{const o=z(i,a);await n({summary:i,detail:a,payload:o})}})}const Q=t=>t?Array.isArray(t)?t.filter(r=>typeof r=="string").map(r=>r.trim()).filter(Boolean):typeof t=="string"?t.split(",").map(r=>r.trim()).filter(Boolean):[]:[],g={blue:{bg:"#dbeafe",border:"#2563eb",text:"#1e40af"},green:{bg:"#dcfce7",border:"#16a34a",text:"#166534"},red:{bg:"#fee2e2",border:"#dc2626",text:"#991b1b"},emerald:{bg:"#d1fae5",border:"#10b981",text:"#047857"},purple:{bg:"#f3e8ff",border:"#9333ea",text:"#6b21a8"},orange:{bg:"#fed7aa",border:"#ea580c",text:"#9a3412"},yellow:{bg:"#fef9c3",border:"#eab308",text:"#854d0e"},teal:{bg:"#ccfbf1",border:"#14b8a6",text:"#0f766e"},indigo:{bg:"#e0e7ff",border:"#6366f1",text:"#4338ca"},pink:{bg:"#fce7f3",border:"#ec4899",text:"#9f1239"},cyan:{bg:"#cffafe",border:"#06b6d4",text:"#155e75"},slate:{bg:"#f1f5f9",border:"#475569",text:"#334155"},gray:{bg:"#f3f4f6",border:"#6b7280",text:"#374151"}};function oe(){const[t,r]=x.useState([]),[n,i]=x.useState(!0),[a,o]=x.useState({}),[d,f]=x.useState(!1),[u,j]=x.useState(!1),{toast:p}=O(),l=x.useCallback(async()=>{i(!0);try{const s=await fetch(`${S}/api/v1/agents`);if(!s.ok)throw new Error("Failed to load agents");const m=await s.json();r(Array.isArray(m.documents)?m.documents:[])}catch(s){console.error("Failed to load agents:",s),r([])}finally{i(!1)}},[]);x.useEffect(()=>{l()},[l]);const A=async s=>{const m=`.nut/agents/${s}`;try{await U(m),o(c=>({...c,[s]:!0})),setTimeout(()=>{o(c=>({...c,[s]:!1}))},2e3),p({title:"Path copied!",description:`Copied ${m} to clipboard`})}catch(c){console.error("Failed to copy path:",c),p({title:"Failed to copy",description:"Unable to copy path to clipboard",variant:"destructive"})}},C=x.useCallback(async({payload:s})=>{let m=!1;j(!0);try{const c=await fetch(`${S}/api/v1/agents`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({name:s.name,description:s.description,content:s.content,metadata:s.metadata})});let h=null;try{h=await c.json()}catch(k){console.error("Failed to parse registry import response:",k)}if(!(c.ok&&h?.success)){const R=(typeof h?.error=="string"?h.error:h?.error?.message)||c.statusText||"Failed to import agent from registry";throw p({title:"Failed to import agent",description:R,variant:"destructive"}),m=!0,new Error(R)}p({title:"Agent imported",description:`${s.name} is now available in Coconut`}),await l()}catch(c){if(!m){const h=c instanceof Error&&c.message?c.message:"Failed to import agent from registry";p({title:"Failed to import agent",description:h,variant:"destructive"})}throw c}finally{j(!1)}},[l,p]);return n?e.jsx("div",{className:"space-y-6",children:e.jsx(N,{children:e.jsx(w,{className:"pt-6",children:e.jsxs("div",{className:"flex items-center justify-center",children:[e.jsx(M,{className:"h-8 w-8 animate-spin text-muted-foreground"}),e.jsx("span",{className:"ml-2 text-muted-foreground",children:"Loading agents..."})]})})})}):t.length===0?e.jsxs(e.Fragment,{children:[e.jsxs("div",{className:"space-y-6",children:[e.jsxs("div",{className:"mb-6 flex items-center justify-between gap-4",children:[e.jsxs("div",{children:[e.jsx("h2",{className:"text-2xl font-bold tracking-tight",children:"Agents"}),e.jsx("p",{className:"text-muted-foreground",children:"Manage agents for your development workflows"})]}),e.jsxs("div",{className:"flex items-center gap-2",children:[e.jsxs(b,{variant:"outline",size:"sm",onClick:()=>f(!0),disabled:u,children:[e.jsx(F,{className:"h-4 w-4 sm:mr-2"}),e.jsx("span",{className:"hidden sm:inline",children:"Registry"})]}),e.jsx(b,{size:"sm",asChild:!0,children:e.jsxs(v,{to:"/agents/new",children:[e.jsx(T,{className:"h-4 w-4 sm:mr-2"}),e.jsx("span",{className:"hidden sm:inline",children:"Create New"})]})})]})]}),e.jsx(N,{children:e.jsx(w,{className:"pt-6",children:e.jsxs("div",{className:"text-center",children:[e.jsx(E,{className:"mx-auto h-12 w-12 text-muted-foreground"}),e.jsx("h3",{className:"mt-4 text-lg font-semibold",children:"No Agents Found"}),e.jsx("p",{className:"mt-2 text-sm text-muted-foreground",children:"Specialized agents help you automate your development and business workflows."})]})})})]}),e.jsx(B,{open:d,onOpenChange:f,onImport:C})]}):e.jsxs(e.Fragment,{children:[e.jsxs("div",{className:"space-y-6",children:[e.jsxs("div",{className:"flex items-center justify-between gap-4",children:[e.jsxs("div",{children:[e.jsx("h2",{className:"text-2xl font-bold tracking-tight",children:"Agents"}),e.jsx("p",{className:"text-muted-foreground",children:"Manage agents for your development workflows"})]}),e.jsxs("div",{className:"flex items-center gap-2",children:[e.jsxs(b,{variant:"outline",size:"sm",onClick:()=>f(!0),disabled:u,children:[e.jsx(F,{className:"h-4 w-4 sm:mr-2"}),e.jsx("span",{className:"hidden sm:inline",children:"Registry"})]}),e.jsx(b,{size:"sm",asChild:!0,children:e.jsxs(v,{to:"/agents/new",children:[e.jsx(T,{className:"h-4 w-4 sm:mr-2"}),e.jsx("span",{className:"hidden sm:inline",children:"Create New"})]})})]})]}),e.jsx("div",{className:"grid gap-4",children:t.map(s=>{const m=Q(s.metadata.tools);return e.jsx(v,{to:`/agents/${s.filename.replace(".md","")}`,className:"block",children:e.jsxs(N,{className:"group hover:shadow-md hover:bg-muted/30 transition-all cursor-pointer",children:[e.jsx(D,{children:e.jsxs("div",{className:"flex items-start justify-between",children:[e.jsxs("div",{className:"space-y-1 flex-1",children:[e.jsxs("div",{className:"flex items-center gap-2",children:[e.jsx(H,{className:"text-lg",children:s.title}),e.jsx(b,{variant:"ghost",size:"sm",onClick:c=>{c.preventDefault(),A(s.filename)},className:"h-6 w-6 p-0 hover:bg-muted opacity-0 group-hover:opacity-100 transition-opacity",title:"Copy file path to clipboard",children:a[s.filename]?e.jsx($,{className:"w-3 h-3 text-green-600"}):e.jsx(_,{className:"w-3 h-3"})})]}),e.jsxs("div",{className:"text-xs text-muted-foreground font-mono bg-muted/50 px-2 py-1 rounded inline-block cursor-pointer hover:bg-muted/70 transition-colors",onClick:c=>{c.preventDefault(),A(s.filename)},title:"Click to copy file path to clipboard",children:[".nut/agents/",s.filename]}),e.jsxs("div",{className:"flex items-center gap-4 text-sm text-muted-foreground",children:[e.jsxs("div",{className:"flex items-center gap-1",children:[e.jsx(K,{className:"w-3 h-3"}),s.metadata.color||"blue"]}),m.length>0&&e.jsxs("div",{className:"flex items-center gap-1",children:[e.jsx(E,{className:"w-3 h-3"}),m.join(", ")]})]})]}),s.metadata.color&&e.jsx(y,{variant:"outline",className:"capitalize border-2",style:{backgroundColor:g[s.metadata.color]?.bg||g.blue.bg,color:g[s.metadata.color]?.text||g.blue.text,borderColor:g[s.metadata.color]?.border||g.blue.border},children:s.metadata.color})]})}),e.jsx(w,{children:e.jsx("div",{className:"space-y-4",children:e.jsx("div",{className:"prose prose-sm max-w-none dark:prose-invert",children:e.jsx("p",{className:"text-sm text-muted-foreground line-clamp-2",children:s.metadata.description})})})})]})},s.filename)})})]}),e.jsx(B,{open:d,onOpenChange:f,onImport:C})]})}export{oe as default};
3
+ `).trim()}function z(t,r){const n=t.name||r.name,i=r.description||t.description||"",a={registryId:t.id,registryEndpoint:t.endpoint,registrySource:G,author:t.author};for(const o of V){const d=r[o];if(d!==void 0)if(o==="tools"||o==="focusAreas"||o==="contextPreferences"||o==="tags"){const f=P(d);f&&(a[o]=f)}else a[o]=d}!a.version&&t.version&&(a.version=t.version),a.color||(a.color="blue"),!a.tags&&t.tags&&(a.tags=P(t.tags));for(const[o,d]of Object.entries(a))d==null&&delete a[o];return{name:n,description:i,content:q(r,n),metadata:Object.keys(a).length>0?a:void 0}}function B({open:t,onOpenChange:r,onImport:n}){return e.jsx(Y,{open:t,onOpenChange:r,categoryId:"agents",title:"Coconut Registry – Agents",confirmLabel:"Import Agent",getDetail:i=>J(i.endpoint),renderPreview:(i,a)=>{if(!a)return e.jsx("div",{className:"flex h-full items-center justify-center text-muted-foreground",children:"Select an agent to preview"});const o=z(i,a),d=o.metadata??{},f=typeof d.version=="string"?d.version:void 0,u=Array.isArray(i.tags)?i.tags:[],j=Array.isArray(d.tools)?d.tools.filter(l=>typeof l=="string"):[],p=Array.isArray(d.focusAreas)?d.focusAreas.filter(l=>typeof l=="string"):[];return e.jsx("div",{className:"h-full min-h-0 overflow-hidden rounded-md border",children:e.jsx(I,{className:"h-full",children:e.jsxs("div",{className:"space-y-6 p-4",children:[e.jsxs("div",{className:"space-y-3",children:[e.jsxs("div",{className:"flex flex-wrap items-start justify-between gap-2",children:[e.jsxs("div",{children:[e.jsx("h3",{className:"text-lg font-semibold",children:i.name}),e.jsx("p",{className:"text-sm text-muted-foreground",children:a.description})]}),f&&e.jsxs(y,{variant:"outline",children:["v",f]})]}),e.jsxs("div",{className:"text-xs text-muted-foreground",children:["Registry ID: ",e.jsx("span",{className:"font-mono",children:i.id})]}),u.length>0&&e.jsx("div",{className:"flex flex-wrap gap-2",children:u.map(l=>e.jsx(y,{variant:"secondary",children:l},l))}),j.length>0&&e.jsxs("div",{className:"flex flex-wrap items-center gap-2 text-sm",children:[e.jsx("span",{className:"font-medium",children:"Tools:"}),j.map(l=>e.jsx(y,{variant:"outline",children:l},l))]}),p.length>0&&e.jsxs("div",{className:"space-y-1",children:[e.jsx("div",{className:"text-sm font-medium",children:"Focus Areas"}),e.jsx("ul",{className:"list-disc pl-5 text-sm text-muted-foreground",children:p.map(l=>e.jsx("li",{children:l},l))})]})]}),e.jsx(L,{className:"[&_.prose]:max-w-none",children:o.content})]})})})},onConfirm:async(i,a)=>{const o=z(i,a);await n({summary:i,detail:a,payload:o})}})}const Q=t=>t?Array.isArray(t)?t.filter(r=>typeof r=="string").map(r=>r.trim()).filter(Boolean):typeof t=="string"?t.split(",").map(r=>r.trim()).filter(Boolean):[]:[],g={blue:{bg:"#dbeafe",border:"#2563eb",text:"#1e40af"},green:{bg:"#dcfce7",border:"#16a34a",text:"#166534"},red:{bg:"#fee2e2",border:"#dc2626",text:"#991b1b"},emerald:{bg:"#d1fae5",border:"#10b981",text:"#047857"},purple:{bg:"#f3e8ff",border:"#9333ea",text:"#6b21a8"},orange:{bg:"#fed7aa",border:"#ea580c",text:"#9a3412"},yellow:{bg:"#fef9c3",border:"#eab308",text:"#854d0e"},teal:{bg:"#ccfbf1",border:"#14b8a6",text:"#0f766e"},indigo:{bg:"#e0e7ff",border:"#6366f1",text:"#4338ca"},pink:{bg:"#fce7f3",border:"#ec4899",text:"#9f1239"},cyan:{bg:"#cffafe",border:"#06b6d4",text:"#155e75"},slate:{bg:"#f1f5f9",border:"#475569",text:"#334155"},gray:{bg:"#f3f4f6",border:"#6b7280",text:"#374151"}};function ie(){const[t,r]=x.useState([]),[n,i]=x.useState(!0),[a,o]=x.useState({}),[d,f]=x.useState(!1),[u,j]=x.useState(!1),{toast:p}=O(),l=x.useCallback(async()=>{i(!0);try{const s=await fetch(`${S}/api/v1/agents`);if(!s.ok)throw new Error("Failed to load agents");const m=await s.json();r(Array.isArray(m.documents)?m.documents:[])}catch(s){console.error("Failed to load agents:",s),r([])}finally{i(!1)}},[]);x.useEffect(()=>{l()},[l]);const A=async s=>{const m=`.nut/agents/${s}`;try{await U(m),o(c=>({...c,[s]:!0})),setTimeout(()=>{o(c=>({...c,[s]:!1}))},2e3),p({title:"Path copied!",description:`Copied ${m} to clipboard`})}catch(c){console.error("Failed to copy path:",c),p({title:"Failed to copy",description:"Unable to copy path to clipboard",variant:"destructive"})}},C=x.useCallback(async({payload:s})=>{let m=!1;j(!0);try{const c=await fetch(`${S}/api/v1/agents`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({name:s.name,description:s.description,content:s.content,metadata:s.metadata})});let h=null;try{h=await c.json()}catch(k){console.error("Failed to parse registry import response:",k)}if(!(c.ok&&h?.success)){const R=(typeof h?.error=="string"?h.error:h?.error?.message)||c.statusText||"Failed to import agent from registry";throw p({title:"Failed to import agent",description:R,variant:"destructive"}),m=!0,new Error(R)}p({title:"Agent imported",description:`${s.name} is now available in Coconut`}),await l()}catch(c){if(!m){const h=c instanceof Error&&c.message?c.message:"Failed to import agent from registry";p({title:"Failed to import agent",description:h,variant:"destructive"})}throw c}finally{j(!1)}},[l,p]);return n?e.jsx("div",{className:"space-y-6",children:e.jsx(N,{children:e.jsx(w,{className:"pt-6",children:e.jsxs("div",{className:"flex items-center justify-center",children:[e.jsx(M,{className:"h-8 w-8 animate-spin text-muted-foreground"}),e.jsx("span",{className:"ml-2 text-muted-foreground",children:"Loading agents..."})]})})})}):t.length===0?e.jsxs(e.Fragment,{children:[e.jsxs("div",{className:"space-y-6",children:[e.jsxs("div",{className:"mb-6 flex items-center justify-between gap-4",children:[e.jsxs("div",{children:[e.jsx("h2",{className:"text-2xl font-bold tracking-tight",children:"Agents"}),e.jsx("p",{className:"text-muted-foreground",children:"Manage agents for your development workflows"})]}),e.jsxs("div",{className:"flex items-center gap-2",children:[e.jsxs(b,{variant:"outline",size:"sm",onClick:()=>f(!0),disabled:u,children:[e.jsx(F,{className:"h-4 w-4 sm:mr-2"}),e.jsx("span",{className:"hidden sm:inline",children:"Registry"})]}),e.jsx(b,{size:"sm",asChild:!0,children:e.jsxs(v,{to:"/agents/new",children:[e.jsx(T,{className:"h-4 w-4 sm:mr-2"}),e.jsx("span",{className:"hidden sm:inline",children:"Create New"})]})})]})]}),e.jsx(N,{children:e.jsx(w,{className:"pt-6",children:e.jsxs("div",{className:"text-center",children:[e.jsx(E,{className:"mx-auto h-12 w-12 text-muted-foreground"}),e.jsx("h3",{className:"mt-4 text-lg font-semibold",children:"No Agents Found"}),e.jsx("p",{className:"mt-2 text-sm text-muted-foreground",children:"Specialized agents help you automate your development and business workflows."})]})})})]}),e.jsx(B,{open:d,onOpenChange:f,onImport:C})]}):e.jsxs(e.Fragment,{children:[e.jsxs("div",{className:"space-y-6",children:[e.jsxs("div",{className:"flex items-center justify-between gap-4",children:[e.jsxs("div",{children:[e.jsx("h2",{className:"text-2xl font-bold tracking-tight",children:"Agents"}),e.jsx("p",{className:"text-muted-foreground",children:"Manage agents for your development workflows"})]}),e.jsxs("div",{className:"flex items-center gap-2",children:[e.jsxs(b,{variant:"outline",size:"sm",onClick:()=>f(!0),disabled:u,children:[e.jsx(F,{className:"h-4 w-4 sm:mr-2"}),e.jsx("span",{className:"hidden sm:inline",children:"Registry"})]}),e.jsx(b,{size:"sm",asChild:!0,children:e.jsxs(v,{to:"/agents/new",children:[e.jsx(T,{className:"h-4 w-4 sm:mr-2"}),e.jsx("span",{className:"hidden sm:inline",children:"Create New"})]})})]})]}),e.jsx("div",{className:"grid gap-4",children:t.map(s=>{const m=Q(s.metadata.tools);return e.jsx(v,{to:`/agents/${s.filename.replace(".md","")}`,className:"block",children:e.jsxs(N,{className:"group hover:shadow-md hover:bg-muted/30 transition-all cursor-pointer",children:[e.jsx(D,{children:e.jsxs("div",{className:"flex items-start justify-between",children:[e.jsxs("div",{className:"space-y-1 flex-1",children:[e.jsxs("div",{className:"flex items-center gap-2",children:[e.jsx(H,{className:"text-lg",children:s.title}),e.jsx(b,{variant:"ghost",size:"sm",onClick:c=>{c.preventDefault(),A(s.filename)},className:"h-6 w-6 p-0 hover:bg-muted opacity-0 group-hover:opacity-100 transition-opacity",title:"Copy file path to clipboard",children:a[s.filename]?e.jsx($,{className:"w-3 h-3 text-green-600"}):e.jsx(_,{className:"w-3 h-3"})})]}),e.jsxs("div",{className:"text-xs text-muted-foreground font-mono bg-muted/50 px-2 py-1 rounded inline-block cursor-pointer hover:bg-muted/70 transition-colors",onClick:c=>{c.preventDefault(),A(s.filename)},title:"Click to copy file path to clipboard",children:[".nut/agents/",s.filename]}),e.jsxs("div",{className:"flex items-center gap-4 text-sm text-muted-foreground",children:[e.jsxs("div",{className:"flex items-center gap-1",children:[e.jsx(K,{className:"w-3 h-3"}),s.metadata.color||"blue"]}),m.length>0&&e.jsxs("div",{className:"flex items-center gap-1",children:[e.jsx(E,{className:"w-3 h-3"}),m.join(", ")]})]})]}),s.metadata.color&&e.jsx(y,{variant:"outline",className:"capitalize border-2",style:{backgroundColor:g[s.metadata.color]?.bg||g.blue.bg,color:g[s.metadata.color]?.text||g.blue.text,borderColor:g[s.metadata.color]?.border||g.blue.border},children:s.metadata.color})]})}),e.jsx(w,{children:e.jsx("div",{className:"space-y-4",children:e.jsx("div",{className:"prose prose-sm max-w-none dark:prose-invert",children:e.jsx("p",{className:"text-sm text-muted-foreground line-clamp-2",children:s.metadata.description})})})})]})},s.filename)})})]}),e.jsx(B,{open:d,onOpenChange:f,onImport:C})]})}export{ie as default};
@@ -1,4 +1,4 @@
1
- import{c as b,j as e,a1 as w,B as t,ad as C,T as A,I as r,v as l,w as c,x as d,y as o,z as i}from"./index-BSBM4i_g.js";import{C as x,b as m,c as u,d as h,a as j}from"./card-Cnz8b7Ou.js";import{L as a}from"./label-vEgNxdb2.js";import{B as n}from"./badge-DO6e5hC1.js";import{P as S}from"./plus-BfBtnncn.js";import{P as p}from"./pause-6aQLhmG9.js";import{P as R}from"./play-DsDsjO2V.js";import{Z as T}from"./zap-BMkP_c9R.js";/**
1
+ import{c as b,j as e,a1 as w,B as t,ad as C,T as A,I as r,v as l,w as c,x as d,y as o,z as i}from"./index-Bbxvuj4b.js";import{C as x,b as m,c as u,d as h,a as j}from"./card-D_zGBKua.js";import{L as a}from"./label-CZGCmBD7.js";import{B as n}from"./badge-D7ZZbMEG.js";import{P as S}from"./plus-Be79gWKj.js";import{P as p}from"./pause-BNL49HvB.js";import{P as R}from"./play-8b83f5X0.js";import{Z as T}from"./zap-cD8GAJPg.js";/**
2
2
  * @license lucide-react v0.542.0 - ISC
3
3
  *
4
4
  * This source code is licensed under the ISC license.
@@ -1,4 +1,4 @@
1
- import{c as q,m as z,r as t,aX as y,j as e,B as a,aY as R,T as _,D as j,a as g,b as v,d as f,e as A,I as F,$ as N,ai as J,t as i}from"./index-BSBM4i_g.js";import{C as W,b as G,c as Q,d as V,a as Z}from"./card-Cnz8b7Ou.js";import{L as w}from"./label-vEgNxdb2.js";import{B as ee}from"./badge-DO6e5hC1.js";import{A as I,a as C}from"./alert-CNSGDe1U.js";import{P as se}from"./plus-BfBtnncn.js";import{C as te}from"./circle-alert-Dick-jNf.js";/**
1
+ import{c as q,m as z,r as t,aX as y,j as e,B as a,aY as R,T as _,D as j,a as g,b as v,d as f,e as A,I as F,$ as N,ai as J,t as i}from"./index-Bbxvuj4b.js";import{C as W,b as G,c as Q,d as V,a as Z}from"./card-D_zGBKua.js";import{L as w}from"./label-CZGCmBD7.js";import{B as ee}from"./badge-D7ZZbMEG.js";import{A as I,a as C}from"./alert-D2VTq6m-.js";import{P as se}from"./plus-Be79gWKj.js";import{C as te}from"./circle-alert-DQD0CPB3.js";/**
2
2
  * @license lucide-react v0.542.0 - ISC
3
3
  *
4
4
  * This source code is licensed under the ISC license.
@@ -1,4 +1,4 @@
1
- import{u as D,H as M,r as l,A as b,j as e,B as S,L as I,a2 as _,I as d,a0 as B}from"./index-BSBM4i_g.js";import{C as u,a as p,b as j,c as v}from"./card-Cnz8b7Ou.js";import{L as o}from"./label-vEgNxdb2.js";import{M as P}from"./markdown-editor-O6tGYa1a.js";import{A as R}from"./arrow-left-CEZFPQje.js";import{C as $}from"./circle-check-big-B70gdce7.js";function Q(){const F=D(),{toast:h}=M(),[n,x]=l.useState({stack:{runtime:"",framework:"",language:"",database:"",deployment:"",repository:""},commands:{}}),[y,f]=l.useState(""),[E,k]=l.useState(""),[L,N]=l.useState(!0),[C,w]=l.useState(!1);l.useEffect(()=>{fetch(`${b}/api/v1/context/architecture`).then(t=>t.json()).then(t=>{if(t.success){const a=t.document,m={stack:{runtime:a.metadata.stack?.runtime||"",framework:a.metadata.stack?.framework||"",language:a.metadata.stack?.language||"",database:a.metadata.stack?.database||"",deployment:a.metadata.stack?.deployment||"",repository:a.metadata.stack?.repository||""},commands:a.metadata.commands||{}};x(m);const s=Object.entries(m.commands).map(([r,c])=>`${r}: ${c}`).join(`
1
+ import{u as D,H as M,r as l,A as b,j as e,B as S,L as I,a2 as _,I as d,a0 as B}from"./index-Bbxvuj4b.js";import{C as u,a as p,b as j,c as v}from"./card-D_zGBKua.js";import{L as o}from"./label-CZGCmBD7.js";import{M as P}from"./markdown-editor-BiM9h5iI.js";import{A as R}from"./arrow-left-Do2jUSS9.js";import{C as $}from"./circle-check-big-KfJvKA9H.js";function Q(){const F=D(),{toast:h}=M(),[n,x]=l.useState({stack:{runtime:"",framework:"",language:"",database:"",deployment:"",repository:""},commands:{}}),[y,f]=l.useState(""),[E,k]=l.useState(""),[L,N]=l.useState(!0),[C,w]=l.useState(!1);l.useEffect(()=>{fetch(`${b}/api/v1/context/architecture`).then(t=>t.json()).then(t=>{if(t.success){const a=t.document,m={stack:{runtime:a.metadata.stack?.runtime||"",framework:a.metadata.stack?.framework||"",language:a.metadata.stack?.language||"",database:a.metadata.stack?.database||"",deployment:a.metadata.stack?.deployment||"",repository:a.metadata.stack?.repository||""},commands:a.metadata.commands||{}};x(m);const s=Object.entries(m.commands).map(([r,c])=>`${r}: ${c}`).join(`
2
2
  `);k(s),f(a.content.trim())}N(!1)}).catch(t=>{console.error("Failed to load context:",t),h({title:"Error",description:"Failed to load architecture documentation",variant:"destructive"}),N(!1)})},[h]);const A=async()=>{w(!0);try{const a=await(await fetch(`${b}/api/v1/context/architecture`,{method:"PUT",headers:{"Content-Type":"application/json"},body:JSON.stringify({content:y,metadata:{stack:n.stack,commands:n.commands}})})).json();if(a.success)h({title:"Success",description:"Architecture documentation saved successfully",action:e.jsx($,{className:"h-4 w-4"})}),F("/context/architecture");else throw new Error(a.error||"Failed to save context")}catch(t){console.error("Save error:",t),h({title:"Error",description:"Failed to save architecture documentation",variant:"destructive"})}finally{w(!1)}},i=(t,a)=>{x(m=>{const s={...m},r=t.split(".");let c=s;for(let g=0;g<r.length-1;g++)c=c[r[g]];return c[r[r.length-1]]=a,s})},T=t=>{k(t);const a={};t.split(`
3
3
  `).filter(s=>s.trim()).forEach(s=>{const[r,...c]=s.split(":");r&&c.length>0&&(a[r.trim()]=c.join(":").trim())}),x(s=>({...s,commands:a}))};return L?e.jsx("div",{className:"space-y-6",children:e.jsx(u,{children:e.jsx(p,{className:"pt-6",children:e.jsx("div",{className:"text-center",children:e.jsx("p",{children:"Loading..."})})})})}):e.jsxs("div",{className:"space-y-6",children:[e.jsxs("div",{className:"flex items-start justify-between gap-4",children:[e.jsxs("div",{className:"min-w-0",children:[e.jsx("h1",{className:"text-xl sm:text-2xl font-bold tracking-tight",children:"Edit Architecture"}),e.jsx("p",{className:"text-muted-foreground text-sm hidden sm:block",children:"Edit technical architecture and supporting metadata"})]}),e.jsxs("div",{className:"flex items-center gap-2 flex-shrink-0",children:[e.jsx(S,{variant:"ghost",size:"sm",asChild:!0,children:e.jsx(I,{to:"/context/architecture",className:"text-muted-foreground hover:text-foreground transition-colors",children:e.jsx(R,{className:"w-4 h-4"})})}),e.jsxs(S,{onClick:A,disabled:C,size:"sm",children:[e.jsx(_,{className:"w-4 h-4 sm:mr-2"}),e.jsx("span",{className:"hidden sm:inline",children:C?"Saving...":"Save"})]})]})]}),e.jsxs(u,{children:[e.jsx(j,{children:e.jsx(v,{children:"Technology Stack"})}),e.jsxs(p,{className:"space-y-4",children:[e.jsxs("div",{className:"grid grid-cols-1 md:grid-cols-2 gap-4",children:[e.jsxs("div",{className:"space-y-2",children:[e.jsx(o,{htmlFor:"runtime",children:"Runtime"}),e.jsx(d,{id:"runtime",value:n.stack.runtime,onChange:t=>i("stack.runtime",t.target.value),placeholder:"node|python|go|etc"})]}),e.jsxs("div",{className:"space-y-2",children:[e.jsx(o,{htmlFor:"framework",children:"Framework"}),e.jsx(d,{id:"framework",value:n.stack.framework,onChange:t=>i("stack.framework",t.target.value),placeholder:"express|fastify|django|gin|etc"})]})]}),e.jsxs("div",{className:"grid grid-cols-1 md:grid-cols-2 gap-4",children:[e.jsxs("div",{className:"space-y-2",children:[e.jsx(o,{htmlFor:"language",children:"Language"}),e.jsx(d,{id:"language",value:n.stack.language,onChange:t=>i("stack.language",t.target.value),placeholder:"typescript|javascript|python|go|etc"})]}),e.jsxs("div",{className:"space-y-2",children:[e.jsx(o,{htmlFor:"database",children:"Database"}),e.jsx(d,{id:"database",value:n.stack.database,onChange:t=>i("stack.database",t.target.value),placeholder:"postgresql|mysql|mongodb|sqlite|etc"})]})]}),e.jsxs("div",{className:"grid grid-cols-1 md:grid-cols-2 gap-4",children:[e.jsxs("div",{className:"space-y-2",children:[e.jsx(o,{htmlFor:"deployment",children:"Deployment"}),e.jsx(d,{id:"deployment",value:n.stack.deployment,onChange:t=>i("stack.deployment",t.target.value),placeholder:"docker|kubernetes|vercel|aws|etc"})]}),e.jsxs("div",{className:"space-y-2",children:[e.jsx(o,{htmlFor:"repository",children:"Repository"}),e.jsx(d,{id:"repository",value:n.stack.repository,onChange:t=>i("stack.repository",t.target.value),placeholder:"https://github.com/yourorg/yourproject"})]})]})]})]}),e.jsxs(u,{children:[e.jsx(j,{children:e.jsx(v,{children:"Quick Commands"})}),e.jsx(p,{className:"space-y-4",children:e.jsxs("div",{className:"space-y-2",children:[e.jsx(o,{htmlFor:"commands",children:"Commands (format: command_name: command_to_run)"}),e.jsx(B,{id:"commands",value:E,onChange:t=>T(t.target.value),placeholder:`install: npm install
4
4
  dev: npm run dev
@@ -1 +1 @@
1
- import{H as g,r as n,A as v,j as e,n as y,g as k,B as l,ap as b,ao as w,L as C,J as E,al as A}from"./index-BSBM4i_g.js";import{C as a,a as c,b as o,c as m}from"./card-Cnz8b7Ou.js";import{c as D}from"./clipboard-B9ndUJKl.js";function F(){const{toast:h}=g(),[r,x]=n.useState(null),[u,p]=n.useState(!0),[j,i]=n.useState(!1);n.useEffect(()=>{fetch(`${v}/api/v1/context/architecture`).then(t=>{if(t.ok)return t.json();throw new Error("Not found")}).then(t=>{t.success?(x(t.document),i(!0)):i(!1)}).catch(()=>{i(!1)}).finally(()=>{p(!1)})},[]);const N=async()=>{const t=".nut/context/architecture.md";try{await D(t),h({title:"Copied!",description:`Path ${t} copied to clipboard`})}catch(d){console.error("Failed to copy path:",d),h({title:"Error",description:"Failed to copy path to clipboard",variant:"destructive"})}},f=()=>{const t=new CustomEvent("discuss-in-chat",{detail:{type:"context",id:"architecture-md",filename:"architecture.md",name:"architecture.md",path:".nut/context/architecture.md"}});window.dispatchEvent(t)};if(u)return e.jsx("div",{className:"space-y-6",children:e.jsx(a,{children:e.jsx(c,{className:"pt-6",children:e.jsxs("div",{className:"flex items-center justify-center",children:[e.jsx(y,{className:"h-8 w-8 animate-spin text-muted-foreground"}),e.jsx("span",{className:"ml-2 text-muted-foreground",children:"Loading architecture documentation..."})]})})})});if(!j||!r)return e.jsx("div",{className:"space-y-6",children:e.jsx(a,{children:e.jsx(c,{className:"pt-6",children:e.jsxs("div",{className:"text-center",children:[e.jsx(k,{className:"mx-auto h-12 w-12 text-muted-foreground"}),e.jsx("h3",{className:"mt-4 text-lg font-semibold",children:"No Architecture Documentation Found"}),e.jsx("p",{className:"mt-2 text-sm text-muted-foreground",children:"Architecture documentation will appear here once created."})]})})})});const s=r.metadata;return e.jsxs("div",{className:"space-y-6",children:[e.jsxs("div",{className:"flex items-center justify-between gap-4",children:[e.jsxs("div",{children:[e.jsx("h1",{className:"text-2xl font-bold tracking-tight",children:"Technical Architecture"}),e.jsx("p",{className:"text-muted-foreground",children:"System design, components, and technical patterns"})]}),e.jsxs("div",{className:"flex items-center gap-2",children:[e.jsxs(l,{variant:"outline",size:"sm",onClick:f,children:[e.jsx(b,{className:"h-4 w-4 sm:mr-2"}),e.jsx("span",{className:"hidden sm:inline",children:"Discuss"})]}),e.jsxs(l,{variant:"outline",size:"sm",onClick:N,children:[e.jsx(w,{className:"h-4 w-4 sm:mr-2"}),e.jsx("span",{className:"hidden sm:inline",children:"Copy Path"})]}),e.jsx(l,{size:"sm",asChild:!0,children:e.jsxs(C,{to:"/context/architecture/edit",children:[e.jsx(E,{className:"h-4 w-4 sm:mr-2"}),e.jsx("span",{className:"hidden sm:inline",children:"Edit"})]})})]})]}),s&&e.jsxs("div",{className:"grid grid-cols-1 md:grid-cols-2 gap-4",children:[e.jsxs(a,{children:[e.jsx(o,{className:"pb-3",children:e.jsx(m,{className:"text-lg font-semibold",children:"Technology Stack"})}),e.jsx(c,{className:"space-y-3",children:s.stack&&e.jsxs("div",{className:"space-y-1 text-sm",children:[s.stack.runtime&&e.jsxs("div",{children:["Runtime: ",s.stack.runtime]}),s.stack.framework&&e.jsxs("div",{children:["Framework: ",s.stack.framework]}),s.stack.language&&e.jsxs("div",{children:["Language: ",s.stack.language]}),s.stack.database&&e.jsxs("div",{children:["Database: ",s.stack.database]}),s.stack.deployment&&e.jsxs("div",{children:["Deployment: ",s.stack.deployment]}),s.stack.repository&&e.jsxs("div",{children:["Repository:"," ",e.jsx("a",{href:s.stack.repository,target:"_blank",rel:"noopener noreferrer",className:"text-primary hover:underline",children:s.stack.repository})]})]})})]}),e.jsxs(a,{children:[e.jsx(o,{className:"pb-3",children:e.jsx(m,{className:"text-lg font-semibold",children:"Quick Commands"})}),e.jsx(c,{className:"space-y-3",children:s.commands&&e.jsxs("div",{className:"space-y-1",children:[Object.entries(s.commands).slice(0,5).map(([t,d])=>e.jsxs("div",{className:"text-sm",children:[e.jsxs("span",{className:"font-medium capitalize",children:[t,": "]}),e.jsx("code",{className:"bg-muted px-2 py-1 rounded text-xs",children:d})]},t)),Object.entries(s.commands).length>5&&e.jsxs("div",{className:"text-xs text-muted-foreground",children:["+ ",Object.entries(s.commands).length-5," more commands"]})]})})]})]}),e.jsxs(a,{children:[e.jsx(o,{children:e.jsx(m,{className:"text-lg font-semibold",children:"Architecture Documentation"})}),e.jsx(c,{children:e.jsx("div",{className:"prose prose-sm max-w-none dark:prose-invert",children:e.jsx(A,{children:r.content||"No content available"})})})]})]})}export{F as default};
1
+ import{H as g,r as n,A as v,j as e,n as y,g as k,B as l,ap as b,ao as w,L as C,J as E,al as A}from"./index-Bbxvuj4b.js";import{C as a,a as c,b as o,c as m}from"./card-D_zGBKua.js";import{c as D}from"./clipboard-B9ndUJKl.js";function F(){const{toast:h}=g(),[r,x]=n.useState(null),[u,p]=n.useState(!0),[j,i]=n.useState(!1);n.useEffect(()=>{fetch(`${v}/api/v1/context/architecture`).then(t=>{if(t.ok)return t.json();throw new Error("Not found")}).then(t=>{t.success?(x(t.document),i(!0)):i(!1)}).catch(()=>{i(!1)}).finally(()=>{p(!1)})},[]);const N=async()=>{const t=".nut/context/architecture.md";try{await D(t),h({title:"Copied!",description:`Path ${t} copied to clipboard`})}catch(d){console.error("Failed to copy path:",d),h({title:"Error",description:"Failed to copy path to clipboard",variant:"destructive"})}},f=()=>{const t=new CustomEvent("discuss-in-chat",{detail:{type:"context",id:"architecture-md",filename:"architecture.md",name:"architecture.md",path:".nut/context/architecture.md"}});window.dispatchEvent(t)};if(u)return e.jsx("div",{className:"space-y-6",children:e.jsx(a,{children:e.jsx(c,{className:"pt-6",children:e.jsxs("div",{className:"flex items-center justify-center",children:[e.jsx(y,{className:"h-8 w-8 animate-spin text-muted-foreground"}),e.jsx("span",{className:"ml-2 text-muted-foreground",children:"Loading architecture documentation..."})]})})})});if(!j||!r)return e.jsx("div",{className:"space-y-6",children:e.jsx(a,{children:e.jsx(c,{className:"pt-6",children:e.jsxs("div",{className:"text-center",children:[e.jsx(k,{className:"mx-auto h-12 w-12 text-muted-foreground"}),e.jsx("h3",{className:"mt-4 text-lg font-semibold",children:"No Architecture Documentation Found"}),e.jsx("p",{className:"mt-2 text-sm text-muted-foreground",children:"Architecture documentation will appear here once created."})]})})})});const s=r.metadata;return e.jsxs("div",{className:"space-y-6",children:[e.jsxs("div",{className:"flex items-center justify-between gap-4",children:[e.jsxs("div",{children:[e.jsx("h1",{className:"text-2xl font-bold tracking-tight",children:"Technical Architecture"}),e.jsx("p",{className:"text-muted-foreground",children:"System design, components, and technical patterns"})]}),e.jsxs("div",{className:"flex items-center gap-2",children:[e.jsxs(l,{variant:"outline",size:"sm",onClick:f,children:[e.jsx(b,{className:"h-4 w-4 sm:mr-2"}),e.jsx("span",{className:"hidden sm:inline",children:"Discuss"})]}),e.jsxs(l,{variant:"outline",size:"sm",onClick:N,children:[e.jsx(w,{className:"h-4 w-4 sm:mr-2"}),e.jsx("span",{className:"hidden sm:inline",children:"Copy Path"})]}),e.jsx(l,{size:"sm",asChild:!0,children:e.jsxs(C,{to:"/context/architecture/edit",children:[e.jsx(E,{className:"h-4 w-4 sm:mr-2"}),e.jsx("span",{className:"hidden sm:inline",children:"Edit"})]})})]})]}),s&&e.jsxs("div",{className:"grid grid-cols-1 md:grid-cols-2 gap-4",children:[e.jsxs(a,{children:[e.jsx(o,{className:"pb-3",children:e.jsx(m,{className:"text-lg font-semibold",children:"Technology Stack"})}),e.jsx(c,{className:"space-y-3",children:s.stack&&e.jsxs("div",{className:"space-y-1 text-sm",children:[s.stack.runtime&&e.jsxs("div",{children:["Runtime: ",s.stack.runtime]}),s.stack.framework&&e.jsxs("div",{children:["Framework: ",s.stack.framework]}),s.stack.language&&e.jsxs("div",{children:["Language: ",s.stack.language]}),s.stack.database&&e.jsxs("div",{children:["Database: ",s.stack.database]}),s.stack.deployment&&e.jsxs("div",{children:["Deployment: ",s.stack.deployment]}),s.stack.repository&&e.jsxs("div",{children:["Repository:"," ",e.jsx("a",{href:s.stack.repository,target:"_blank",rel:"noopener noreferrer",className:"text-primary hover:underline",children:s.stack.repository})]})]})})]}),e.jsxs(a,{children:[e.jsx(o,{className:"pb-3",children:e.jsx(m,{className:"text-lg font-semibold",children:"Quick Commands"})}),e.jsx(c,{className:"space-y-3",children:s.commands&&e.jsxs("div",{className:"space-y-1",children:[Object.entries(s.commands).slice(0,5).map(([t,d])=>e.jsxs("div",{className:"text-sm",children:[e.jsxs("span",{className:"font-medium capitalize",children:[t,": "]}),e.jsx("code",{className:"bg-muted px-2 py-1 rounded text-xs",children:d})]},t)),Object.entries(s.commands).length>5&&e.jsxs("div",{className:"text-xs text-muted-foreground",children:["+ ",Object.entries(s.commands).length-5," more commands"]})]})})]})]}),e.jsxs(a,{children:[e.jsx(o,{children:e.jsx(m,{className:"text-lg font-semibold",children:"Architecture Documentation"})}),e.jsx(c,{children:e.jsx("div",{className:"prose prose-sm max-w-none dark:prose-invert",children:e.jsx(A,{children:r.content||"No content available"})})})]})]})}export{F as default};
@@ -1,4 +1,4 @@
1
- import{c as Y,m as le,r as n,aX as c,j as e,a1 as O,aW as ce,D as I,_ as M,B as l,a as $,b as V,d as _,e as z,I as j,v as H,w as J,x as W,y as q,z as a,$ as B,M as oe,N as de,T as he,O as ue,P as xe,Q as me,R as ge,U as je,V as pe,W as ve,t as r}from"./index-BSBM4i_g.js";import{C as p,b as v,c as w,d as f,a as y}from"./card-Cnz8b7Ou.js";import{L as o}from"./label-vEgNxdb2.js";import{S as U}from"./switch-Bjq8cgQn.js";import{B as k}from"./badge-DO6e5hC1.js";import{C as we}from"./circle-alert-Dick-jNf.js";/**
1
+ import{c as Y,m as le,r as n,aX as c,j as e,a1 as O,aW as ce,D as I,_ as M,B as l,a as $,b as V,d as _,e as z,I as j,v as H,w as J,x as W,y as q,z as a,$ as B,M as oe,N as de,T as he,O as ue,P as xe,Q as me,R as ge,U as je,V as pe,W as ve,t as r}from"./index-Bbxvuj4b.js";import{C as p,b as v,c as w,d as f,a as y}from"./card-D_zGBKua.js";import{L as o}from"./label-CZGCmBD7.js";import{S as U}from"./switch-BYPAX9oF.js";import{B as k}from"./badge-D7ZZbMEG.js";import{C as we}from"./circle-alert-DQD0CPB3.js";/**
2
2
  * @license lucide-react v0.542.0 - ISC
3
3
  *
4
4
  * This source code is licensed under the ISC license.
@@ -1 +1 @@
1
- import{r as m,j as e,n as x,A as f}from"./index-BSBM4i_g.js";import{C as w}from"./circle-check-DDk43rYV.js";import{C as b}from"./circle-x-BfR2YcXx.js";const r="coconut/github-auth-state";function j(s){try{window.opener&&window.opener.postMessage({type:"github-auth",...s},window.location.origin)}catch{}}const v=()=>{const[s,d]=m.useState("pending"),[h,p]=m.useState("Authorizing GitHub…");return m.useEffect(()=>{const a=new URLSearchParams(window.location.search),u=a.get("error"),l=a.get("token"),n=a.get("expires_at")||a.get("expiresAt"),c=a.get("state"),o=t=>{j(t),d(t.success?"success":"error"),p(t.message),setTimeout(()=>{try{window.close()}catch{}},1200)};if(u){localStorage.removeItem(r),o({success:!1,message:decodeURIComponent(u)});return}if(!l||!n||!c){localStorage.removeItem(r),o({success:!1,message:"Missing authorization parameters. Please try again."});return}const g=localStorage.getItem(r);if(!g||g!==c){localStorage.removeItem(r),o({success:!1,message:"Authorization state mismatch. Please start again."});return}(async()=>{try{const t=await fetch(`${f}/api/v1/git/providers/github/token`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({token:l,expiresAt:n,state:c})}),i=await t.json();if(!t.ok||!i.success)throw new Error(i?.error?.message||"Failed to store GitHub token");localStorage.removeItem(r),o({success:!0,message:"GitHub connected successfully!",expiresAt:i.data?.expiresAt||n})}catch(t){localStorage.removeItem(r),o({success:!1,message:t?.message||"Failed to store GitHub token. Please try again."})}})()},[]),e.jsx("div",{className:"flex h-screen items-center justify-center bg-background px-6",children:e.jsxs("div",{className:"max-w-sm rounded-lg border bg-card p-6 text-center shadow-sm",children:[e.jsxs("div",{className:"mx-auto mb-4 flex h-12 w-12 items-center justify-center rounded-full bg-muted",children:[s==="pending"&&e.jsx(x,{className:"h-6 w-6 animate-spin text-muted-foreground"}),s==="success"&&e.jsx(w,{className:"h-6 w-6 text-green-600"}),s==="error"&&e.jsx(b,{className:"h-6 w-6 text-red-600"})]}),e.jsx("h1",{className:"text-lg font-semibold",children:"GitHub Authorization"}),e.jsx("p",{className:"mt-2 text-sm text-muted-foreground",children:h}),s!=="pending"&&e.jsx("p",{className:"mt-4 text-xs text-muted-foreground",children:"You can close this window and return to Coconut."})]})})};export{v as default};
1
+ import{r as m,j as e,n as x,A as f}from"./index-Bbxvuj4b.js";import{C as w}from"./circle-check-xj41FKuF.js";import{C as b}from"./circle-x-Ds97aY1x.js";const r="coconut/github-auth-state";function j(s){try{window.opener&&window.opener.postMessage({type:"github-auth",...s},window.location.origin)}catch{}}const v=()=>{const[s,d]=m.useState("pending"),[h,p]=m.useState("Authorizing GitHub…");return m.useEffect(()=>{const a=new URLSearchParams(window.location.search),u=a.get("error"),l=a.get("token"),n=a.get("expires_at")||a.get("expiresAt"),c=a.get("state"),o=t=>{j(t),d(t.success?"success":"error"),p(t.message),setTimeout(()=>{try{window.close()}catch{}},1200)};if(u){localStorage.removeItem(r),o({success:!1,message:decodeURIComponent(u)});return}if(!l||!n||!c){localStorage.removeItem(r),o({success:!1,message:"Missing authorization parameters. Please try again."});return}const g=localStorage.getItem(r);if(!g||g!==c){localStorage.removeItem(r),o({success:!1,message:"Authorization state mismatch. Please start again."});return}(async()=>{try{const t=await fetch(`${f}/api/v1/git/providers/github/token`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({token:l,expiresAt:n,state:c})}),i=await t.json();if(!t.ok||!i.success)throw new Error(i?.error?.message||"Failed to store GitHub token");localStorage.removeItem(r),o({success:!0,message:"GitHub connected successfully!",expiresAt:i.data?.expiresAt||n})}catch(t){localStorage.removeItem(r),o({success:!1,message:t?.message||"Failed to store GitHub token. Please try again."})}})()},[]),e.jsx("div",{className:"flex h-screen items-center justify-center bg-background px-6",children:e.jsxs("div",{className:"max-w-sm rounded-lg border bg-card p-6 text-center shadow-sm",children:[e.jsxs("div",{className:"mx-auto mb-4 flex h-12 w-12 items-center justify-center rounded-full bg-muted",children:[s==="pending"&&e.jsx(x,{className:"h-6 w-6 animate-spin text-muted-foreground"}),s==="success"&&e.jsx(w,{className:"h-6 w-6 text-green-600"}),s==="error"&&e.jsx(b,{className:"h-6 w-6 text-red-600"})]}),e.jsx("h1",{className:"text-lg font-semibold",children:"GitHub Authorization"}),e.jsx("p",{className:"mt-2 text-sm text-muted-foreground",children:h}),s!=="pending"&&e.jsx("p",{className:"mt-4 text-xs text-muted-foreground",children:"You can close this window and return to Coconut."})]})})};export{v as default};